😎同步代码

This commit is contained in:
zuohuaijun 2025-09-14 16:18:23 +08:00
parent de7d688e9a
commit 012867a4ee
6 changed files with 126 additions and 150 deletions

View File

@ -103,7 +103,7 @@ public abstract class EntityBaseData : EntityBase, IOrgIdFilter
[Newtonsoft.Json.JsonIgnore] [Newtonsoft.Json.JsonIgnore]
[System.Text.Json.Serialization.JsonIgnore] [System.Text.Json.Serialization.JsonIgnore]
[Navigate(NavigateType.OneToOne, nameof(CreateOrgId))] [Navigate(NavigateType.OneToOne, nameof(CreateOrgId))]
public virtual SysOrg SysOrg { get; set; } public virtual SysOrg CreateOrg { get; set; }
/// <summary> /// <summary>
/// 创建者机构名称 /// 创建者机构名称
@ -129,7 +129,7 @@ public abstract class EntityTenant : EntityBase, ITenantIdFilter
[Newtonsoft.Json.JsonIgnore] [Newtonsoft.Json.JsonIgnore]
[System.Text.Json.Serialization.JsonIgnore] [System.Text.Json.Serialization.JsonIgnore]
[Navigate(NavigateType.OneToOne, nameof(TenantId))] [Navigate(NavigateType.OneToOne, nameof(TenantId))]
public SysTenant SysTenant { get; set; } public SysTenant Tenant { get; set; }
} }
/// <summary> /// <summary>
@ -149,7 +149,7 @@ public abstract class EntityTenantId : EntityBaseId, ITenantIdFilter
[Newtonsoft.Json.JsonIgnore] [Newtonsoft.Json.JsonIgnore]
[System.Text.Json.Serialization.JsonIgnore] [System.Text.Json.Serialization.JsonIgnore]
[Navigate(NavigateType.OneToOne, nameof(TenantId))] [Navigate(NavigateType.OneToOne, nameof(TenantId))]
public SysTenant SysTenant { get; set; } public SysTenant Tenant { get; set; }
} }
/// <summary> /// <summary>
@ -169,5 +169,5 @@ public abstract class EntityTenantBaseData : EntityBaseData, ITenantIdFilter
[Newtonsoft.Json.JsonIgnore] [Newtonsoft.Json.JsonIgnore]
[System.Text.Json.Serialization.JsonIgnore] [System.Text.Json.Serialization.JsonIgnore]
[Navigate(NavigateType.OneToOne, nameof(TenantId))] [Navigate(NavigateType.OneToOne, nameof(TenantId))]
public SysTenant SysTenant { get; set; } public SysTenant Tenant { get; set; }
} }

View File

@ -1,113 +1,118 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 // Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
// //
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 // 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
// //
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! // 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Core.Service; namespace Admin.NET.Core.Service;
/// <summary> /// <summary>
/// 文件分页查询 /// 文件分页查询
/// </summary> /// </summary>
public class PageFileInput : BasePageInput public class PageFileInput : BasePageInput
{ {
/// <summary> /// <summary>
/// 文件名称 /// 文件名称
/// </summary> /// </summary>
public string FileName { get; set; } public string FileName { get; set; }
/// <summary> /// <summary>
/// 文件后缀 /// 文件后缀
/// </summary> /// </summary>
/// <example></example> /// <example></example>
public string? Suffix { get; set; } public string? Suffix { get; set; }
/// <summary> /// <summary>
/// 开始时间 /// 开始时间
/// </summary> /// </summary>
public DateTime? StartTime { get; set; } public DateTime? StartTime { get; set; }
/// <summary> /// <summary>
/// 结束时间 /// 结束时间
/// </summary> /// </summary>
public DateTime? EndTime { get; set; } public DateTime? EndTime { get; set; }
} }
/// <summary> /// <summary>
/// 上传文件 /// 上传文件
/// </summary> /// </summary>
public class UploadFileInput public class UploadFileInput
{ {
/// <summary> /// <summary>
/// 文件 /// 文件
/// </summary> /// </summary>
[Required] [Required]
public IFormFile File { get; set; } public IFormFile File { get; set; }
/// <summary> /// <summary>
/// 文件类别 /// 文件类别
/// </summary> /// </summary>
/// <example></example> /// <example></example>
public string FileType { get; set; } public string FileType { get; set; }
/// <summary> /// <summary>
/// 文件别名 /// 文件别名
/// </summary> /// </summary>
/// <example></example> /// <example></example>
public string FileAlias { get; set; } public string FileAlias { get; set; }
/// <summary> /// <summary>
/// 是否公开 /// 是否公开
/// </summary> /// </summary>
public bool IsPublic { get; set; } = false; public bool IsPublic { get; set; } = false;
/// <summary> /// <summary>
/// 允许格式:.jpeg.jpg.png.bmp.gif.tif /// 允许格式:.jpeg.jpg.png.bmp.gif.tif
/// </summary> /// </summary>
/// <example></example> /// <example></example>
public string AllowSuffix { get; set; } public string AllowSuffix { get; set; }
/// <summary> /// <summary>
/// 业务数据Id /// 业务数据Id
/// </summary> /// </summary>
public long DataId { get; set; } public long DataId { get; set; }
} }
/// <summary> /// <summary>
/// 上传文件Base64 /// 上传文件Base64
/// </summary> /// </summary>
public class UploadFileFromBase64Input public class UploadFileFromBase64Input
{ {
/// <summary> /// <summary>
/// 文件名 /// 文件名
/// </summary> /// </summary>
public string FileName { get; set; } public string FileName { get; set; }
/// <summary> /// <summary>
/// 文件内容 /// 文件内容
/// </summary> /// </summary>
public string FileDataBase64 { get; set; } public string FileDataBase64 { get; set; }
/// <summary> /// <summary>
/// 文件类型( "image/jpeg",) /// 文件类型( "image/jpeg",)
/// </summary> /// </summary>
/// <example></example> /// <example></example>
public string ContentType { get; set; } public string ContentType { get; set; }
/// <summary> /// <summary>
/// 文件类别 /// 文件类别
/// </summary> /// </summary>
/// <example></example> /// <example></example>
public string FileType { get; set; } public string FileType { get; set; }
/// <summary> /// <summary>
/// 文件别名 /// 文件别名
/// </summary> /// </summary>
/// <example></example> /// <example></example>
public string FileAlias { get; set; } public string FileAlias { get; set; }
/// <summary> /// <summary>
/// 是否公开 /// 是否公开
/// </summary> /// </summary>
public bool IsPublic { get; set; } = false; public bool IsPublic { get; set; } = false;
/// <summary>
/// 业务Id
/// </summary>
public long? DataId { get; set; }
} }

View File

@ -561,6 +561,6 @@ public static class CommonHelper
public static bool IsMobile(string userAgent) public static bool IsMobile(string userAgent)
{ {
var mobilePatterns = new[] { "android.*mobile", "iphone", "ipod", "windows phone", "blackberry", "nokia", "mobile", "opera mini", "opera mobi", "palm", "webos", "bb\\d+", "meego" }; var mobilePatterns = new[] { "android.*mobile", "iphone", "ipod", "windows phone", "blackberry", "nokia", "mobile", "opera mini", "opera mobi", "palm", "webos", "bb\\d+", "meego" };
return mobilePatterns.Any(pattern => Regex.IsMatch(userAgent, pattern, RegexOptions.IgnoreCase)); return mobilePatterns.Any(pattern => Regex.IsMatch(userAgent ?? "", pattern, RegexOptions.IgnoreCase));
} }
} }

View File

@ -382,6 +382,7 @@ public class Startup : AppStartup
var contentTypeProvider = FS.GetFileExtensionContentTypeProvider(); var contentTypeProvider = FS.GetFileExtensionContentTypeProvider();
// contentTypeProvider.Mappings[".文件后缀"] = "MIME 类型"; // contentTypeProvider.Mappings[".文件后缀"] = "MIME 类型";
var cpMappings = App.GetConfig<Dictionary<string, string>>("StaticContentTypeMappings"); var cpMappings = App.GetConfig<Dictionary<string, string>>("StaticContentTypeMappings");
var uploadOption = App.GetConfig<UploadOptions>("Upload");
if (cpMappings != null) if (cpMappings != null)
{ {
if (cpMappings.TryGetValue(".*", out string value)) if (cpMappings.TryGetValue(".*", out string value))
@ -401,6 +402,7 @@ public class Startup : AppStartup
contentTypeProvider.Mappings[key] = cpMappings[key]; contentTypeProvider.Mappings[key] = cpMappings[key];
app.UseStaticFiles(new StaticFileOptions app.UseStaticFiles(new StaticFileOptions
{ {
FileProvider = uploadOption.Path.StartsWith('/') ? new PhysicalFileProvider("/") : null,
ContentTypeProvider = contentTypeProvider ContentTypeProvider = contentTypeProvider
}); });
} }
@ -409,6 +411,7 @@ public class Startup : AppStartup
{ {
app.UseStaticFiles(new StaticFileOptions app.UseStaticFiles(new StaticFileOptions
{ {
FileProvider = uploadOption.Path.StartsWith('/') ? new PhysicalFileProvider("/") : null,
ContentTypeProvider = contentTypeProvider ContentTypeProvider = contentTypeProvider
}); });
} }

View File

@ -65,7 +65,6 @@
<el-button icon="ele-Coin" size="small" text type="danger" @click="createTenantData(row)" :v-auth="'sysTenant/createDb'" v-if="row.tenantType === 0"> 创建租户数据 </el-button> <el-button icon="ele-Coin" size="small" text type="danger" @click="createTenantData(row)" :v-auth="'sysTenant/createDb'" v-if="row.tenantType === 0"> 创建租户数据 </el-button>
<el-button icon="ele-Coin" size="small" text type="danger" @click="createTenantDb(row)" :v-auth="'sysTenant/createDb'" v-else> 创建租户库表 </el-button> <el-button icon="ele-Coin" size="small" text type="danger" @click="createTenantDb(row)" :v-auth="'sysTenant/createDb'" v-else> 创建租户库表 </el-button>
<el-button icon="ele-Menu" size="small" text type="primary" @click="openGrantMenu(row)" v-auth="'sysTenant/grantMenu'"> 授权菜单 </el-button> <el-button icon="ele-Menu" size="small" text type="primary" @click="openGrantMenu(row)" v-auth="'sysTenant/grantMenu'"> 授权菜单 </el-button>
<el-button icon="ele-Position" text type="success" v-auth="'sysTenant/goLoginUser'" @click="goUserLogin(row)">{{ $t('message.list.goTenantUserLogin') }}</el-button>
<el-button icon="ele-Link" size="small" text type="primary" @click="openGrantApi(row)"> 接口黑名单 </el-button> <el-button icon="ele-Link" size="small" text type="primary" @click="openGrantApi(row)"> 接口黑名单 </el-button>
</template> </template>
</vxe-grid> </vxe-grid>
@ -94,7 +93,6 @@ import ModifyRecord from '/@/components/table/modifyRecord.vue';
import { getAPI } from '/@/utils/axios-utils'; import { getAPI } from '/@/utils/axios-utils';
import { SysTenantApi } from '/@/api-services/system/api'; import { SysTenantApi } from '/@/api-services/system/api';
import { PageTenantInput, TenantOutput } from '/@/api-services/system/models'; import { PageTenantInput, TenantOutput } from '/@/api-services/system/models';
import { reLoadLoginAccessToken } from '/@/utils/request';
const xGrid = ref<VxeGridInstance>(); const xGrid = ref<VxeGridInstance>();
const editTenantRef = ref<InstanceType<typeof EditTenant>>(); const editTenantRef = ref<InstanceType<typeof EditTenant>>();
@ -312,17 +310,4 @@ const syncTenantDb = () => {
}) })
.catch(() => {}); .catch(() => {});
}; };
//
const goUserLogin = (row: any) => {
ElMessageBox.confirm(`确定要进入【${row.realName}】用户端?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() =>
getAPI(SysTenantApi)
.apiSysTenantGoLoginUserPost({ id: row.id })
.then((res) => reLoadLoginAccessToken(res.data.result))
);
};
</script> </script>

View File

@ -88,9 +88,6 @@
<el-tooltip :content="$t('message.list.copy')" placement="top"> <el-tooltip :content="$t('message.list.copy')" placement="top">
<el-button icon="ele-CopyDocument" text type="primary" v-auth="'sysUser/add'" @click="openCopyMenu(row)"> </el-button> <el-button icon="ele-CopyDocument" text type="primary" v-auth="'sysUser/add'" @click="openCopyMenu(row)"> </el-button>
</el-tooltip> </el-tooltip>
<el-tooltip :content="$t('message.list.goUserLogin')" placement="top">
<el-button icon="ele-Position" text type="success" v-auth="'sysTenant/goLoginUser'" @click="goUserLogin(row)"> </el-button>
</el-tooltip>
<el-button icon="ele-RefreshLeft" text type="danger" v-auth="'sysUser/resetPwd'" @click="resetQueryPwd(row)">{{ $t('message.list.resetPassword') }}</el-button> <el-button icon="ele-RefreshLeft" text type="danger" v-auth="'sysUser/resetPwd'" @click="resetQueryPwd(row)">{{ $t('message.list.resetPassword') }}</el-button>
<el-button icon="ele-Unlock" text type="primary" v-auth="'sysUser/unlockLogin'" @click="handleUnlock(row)">{{ $t('message.list.unlockAccount') }}</el-button> <el-button icon="ele-Unlock" text type="primary" v-auth="'sysUser/unlockLogin'" @click="handleUnlock(row)">{{ $t('message.list.unlockAccount') }}</el-button>
@ -122,9 +119,8 @@ import EditUser from '/@/views/system/user/component/editUser.vue';
import ModifyRecord from '/@/components/table/modifyRecord.vue'; import ModifyRecord from '/@/components/table/modifyRecord.vue';
import { getAPI } from '/@/utils/axios-utils'; import { getAPI } from '/@/utils/axios-utils';
import { SysUserApi, SysOrgApi, SysTenantApi } from '/@/api-services/system/api'; import { SysUserApi, SysOrgApi } from '/@/api-services/system/api';
import { SysOrg, PageTenantInput, UserOutput, UpdateUserInput } from '/@/api-services/system/models'; import { SysOrg, PageTenantInput, UserOutput, UpdateUserInput } from '/@/api-services/system/models';
import { reLoadLoginAccessToken } from '/@/utils/request';
const { t } = useI18n(); const { t } = useI18n();
const xGrid = ref<VxeGridInstance>(); const xGrid = ref<VxeGridInstance>();
@ -338,17 +334,4 @@ const handleNodeChange = async (node: any) => {
state.queryParams.phone = undefined; state.queryParams.phone = undefined;
await handleQuery(); await handleQuery();
}; };
//
const goUserLogin = (row: any) => {
ElMessageBox.confirm(`确定要进入【${row.realName}】用户端?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() =>
getAPI(SysTenantApi)
.apiSysTenantGoLoginUserPost({ id: row.id })
.then((res) => reLoadLoginAccessToken(res.data.result))
);
};
</script> </script>