mirror of
				https://github.com/nsnail/NetAdmin.git
				synced 2025-10-31 03:19:26 +08:00 
			
		
		
		
	feat: ✨ 框架代码同步 (#148)
[skip ci] Co-authored-by: tk <fiyne1a@dingtalk.com>
This commit is contained in:
		| @@ -24,7 +24,7 @@ | ||||
|     "Component": "sys/user", | ||||
|     "Icon": "el-icon-user", | ||||
|     "Id": 373837957840901, | ||||
|     "Name": "sys-user", | ||||
|     "Name": "sys/user", | ||||
|     "ParentId": 373837917724677, | ||||
|     "Path": "/sys/user", | ||||
|     "Sort": 100, | ||||
| @@ -35,7 +35,7 @@ | ||||
|     "Component": "sys/role", | ||||
|     "Icon": "sc-icon-role", | ||||
|     "Id": 373838018527237, | ||||
|     "Name": "sys-role", | ||||
|     "Name": "sys/role", | ||||
|     "ParentId": 373837917724677, | ||||
|     "Path": "/sys/role", | ||||
|     "Sort": 99, | ||||
| @@ -46,7 +46,7 @@ | ||||
|     "Component": "sys/dept", | ||||
|     "Icon": "sc-icon-dept", | ||||
|     "Id": 373838045605893, | ||||
|     "Name": "sys-dept", | ||||
|     "Name": "sys/dept", | ||||
|     "ParentId": 373837917724677, | ||||
|     "Path": "/sys/dept", | ||||
|     "Sort": 98, | ||||
| @@ -57,7 +57,7 @@ | ||||
|     "Component": "sys/menu", | ||||
|     "Icon": "el-icon-fold", | ||||
|     "Id": 373838070898693, | ||||
|     "Name": "sys-menu", | ||||
|     "Name": "sys/menu", | ||||
|     "ParentId": 373837917724677, | ||||
|     "Path": "/sys/menu", | ||||
|     "Sort": 97, | ||||
| @@ -78,7 +78,7 @@ | ||||
|     "Component": "sys/config", | ||||
|     "Icon": "el-icon-set-up", | ||||
|     "Id": 380415005847557, | ||||
|     "Name": "sys-config", | ||||
|     "Name": "sys/config", | ||||
|     "ParentId": 485278637670422, | ||||
|     "Path": "/sys/config", | ||||
|     "Sort": 100, | ||||
| @@ -89,7 +89,7 @@ | ||||
|     "Component": "sys/job", | ||||
|     "Icon": "sc-icon-ScheduledJob", | ||||
|     "Id": 510067557638158, | ||||
|     "Name": "sys-job", | ||||
|     "Name": "sys/job", | ||||
|     "ParentId": 485278637670422, | ||||
|     "Path": "/sys/job", | ||||
|     "Sort": 99, | ||||
| @@ -100,7 +100,7 @@ | ||||
|     "Component": "sys/dic", | ||||
|     "Icon": "sc-icon-dic", | ||||
|     "Id": 375315654221829, | ||||
|     "Name": "sys-dic", | ||||
|     "Name": "sys/dic", | ||||
|     "ParentId": 485278637670422, | ||||
|     "Path": "/sys/dic", | ||||
|     "Sort": 98, | ||||
| @@ -111,7 +111,7 @@ | ||||
|     "Component": "sys/msg", | ||||
|     "Icon": "el-icon-message", | ||||
|     "Id": 482779610341392, | ||||
|     "Name": "sys-msg", | ||||
|     "Name": "sys/msg", | ||||
|     "ParentId": 485278637670422, | ||||
|     "Path": "/sys/msg", | ||||
|     "Sort": 97, | ||||
| @@ -122,7 +122,7 @@ | ||||
|     "Component": "sys/api", | ||||
|     "Icon": "sc-icon-api", | ||||
|     "Id": 397880678895621, | ||||
|     "Name": "sys-api", | ||||
|     "Name": "sys/api", | ||||
|     "ParentId": 485278637670422, | ||||
|     "Path": "/sys/api", | ||||
|     "Sort": 96, | ||||
| @@ -133,7 +133,7 @@ | ||||
|     "Component": "sys/cache", | ||||
|     "Icon": "sc-icon-memory", | ||||
|     "Id": 374911555702789, | ||||
|     "Name": "sys-cache", | ||||
|     "Name": "sys/cache", | ||||
|     "ParentId": 485278637670422, | ||||
|     "Path": "/sys/cache", | ||||
|     "Sort": 95, | ||||
| @@ -154,7 +154,7 @@ | ||||
|     "Component": "sys/log/operation", | ||||
|     "Icon": "el-icon-pointer", | ||||
|     "Id": 485285246504976, | ||||
|     "Name": "sys-log-operation", | ||||
|     "Name": "sys/log/operation", | ||||
|     "ParentId": 374792687640581, | ||||
|     "Path": "/sys/log/operation", | ||||
|     "Sort": 100, | ||||
| @@ -165,7 +165,7 @@ | ||||
|     "Component": "sys/log/login", | ||||
|     "Icon": "sc-icon-OpenDoor", | ||||
|     "Id": 485285246504970, | ||||
|     "Name": "sys-log-login", | ||||
|     "Name": "sys/log/login", | ||||
|     "ParentId": 374792687640581, | ||||
|     "Path": "/sys/log/login", | ||||
|     "Sort": 99, | ||||
| @@ -186,7 +186,7 @@ | ||||
|     "Component": "dev/code", | ||||
|     "Icon": "sc-icon-code2", | ||||
|     "Id": 373838147022853, | ||||
|     "Name": "dev-code", | ||||
|     "Name": "dev/code", | ||||
|     "ParentId": 373838105399301, | ||||
|     "Path": "/dev/code", | ||||
|     "Sort": 100, | ||||
| @@ -197,10 +197,20 @@ | ||||
|     "Id": 482777529417739, | ||||
|     "ParentId": 373838105399301, | ||||
|     "Icon": "el-icon-eleme-filled", | ||||
|     "Name": "dev-element", | ||||
|     "Path": "https://element-plus.gitee.io/zh-CN/component/button.html", | ||||
|     "Name": "dev/element", | ||||
|     "Path": "http://element-plus.org/zh-CN/component/overview.html", | ||||
|     "Sort": 99, | ||||
|     "Title": "Element", | ||||
|     "Type": 3, | ||||
|   }, | ||||
|   { | ||||
|     "Id": 560217289232398, | ||||
|     "ParentId": 373838105399301, | ||||
|     "Icon": "sc-icon-FreeSql", | ||||
|     "Name": "dev/freesql", | ||||
|     "Path": "https://freesql.net/guide", | ||||
|     "Sort": 99, | ||||
|     "Title": "FreeSql", | ||||
|     "Type": 3, | ||||
|   } | ||||
| ] | ||||
| @@ -34,5 +34,13 @@ | ||||
|   { | ||||
|     "ApiId": "api/sys/site.msg/set.site.msg.status", | ||||
|     "RoleId": 371729946431493, | ||||
|   }, | ||||
|   { | ||||
|     "ApiId": "api/sys/user/get.session.user.app.config", | ||||
|     "RoleId": 371729946431493, | ||||
|   }, | ||||
|   { | ||||
|     "ApiId": "api/sys/user/set.session.user.app.config", | ||||
|     "RoleId": 371729946431493, | ||||
|   } | ||||
| ] | ||||
| @@ -6,5 +6,13 @@ | ||||
|     "Password": "A8E87D23-49BC-25A1-1C7C-59186BEF5D15", | ||||
|     "Token": "A9AFD92E-A33D-4152-9A6C-A9C141D24887", | ||||
|     "UserName": "root" | ||||
|   }, | ||||
|   { | ||||
|     "DeptId": 372119301627909, | ||||
|     "Enabled": true, | ||||
|     "Id": 560217289236492, | ||||
|     "Password": "A8E87D23-49BC-25A1-1C7C-59186BEF5D15", | ||||
|     "Token": "4208EA97-B32F-4E39-A290-4C0D27B61EBF", | ||||
|     "UserName": "user" | ||||
|   } | ||||
| ] | ||||
| @@ -1,5 +1,8 @@ | ||||
| [ | ||||
|   { | ||||
|     "Id": 370942943322181 | ||||
|   }, | ||||
|   { | ||||
|     "Id": 560217289236492 | ||||
|   } | ||||
| ] | ||||
| @@ -2,5 +2,9 @@ | ||||
|   { | ||||
|     "RoleId": 370943613149253, | ||||
|     "UserId": 370942943322181 | ||||
|   }, | ||||
|   { | ||||
|     "RoleId": 371729946431493, | ||||
|     "UserId": 560217289236492 | ||||
|   } | ||||
| ] | ||||
| @@ -954,6 +954,13 @@ public class AllTests(WebApplicationFactory<Startup> factory, ITestOutputHelper | ||||
|         return default; | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     [Fact] | ||||
|     public Task<GetSessionUserAppConfigRsp> GetSessionUserAppConfigAsync() | ||||
|     { | ||||
|         return default; | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     [Fact] | ||||
|     public async Task<string> GetVersionAsync() | ||||
| @@ -1342,7 +1349,7 @@ public class AllTests(WebApplicationFactory<Startup> factory, ITestOutputHelper | ||||
|     /// <inheritdoc /> | ||||
|     [InlineData(default)] | ||||
|     [Theory] | ||||
|     public Task<uint> ResetPasswordAsync(ResetPasswordReq req) | ||||
|     public Task<int> ResetPasswordAsync(ResetPasswordReq req) | ||||
|     { | ||||
|         return default; | ||||
|     } | ||||
| @@ -1363,6 +1370,14 @@ public class AllTests(WebApplicationFactory<Startup> factory, ITestOutputHelper | ||||
|         return default; | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     [InlineData(default)] | ||||
|     [Theory] | ||||
|     public Task<int> SetDisplayDashboardAsync(SetDisplayDashboardReq req) | ||||
|     { | ||||
|         return default; | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     [InlineData(default)] | ||||
|     [Theory] | ||||
| @@ -1374,7 +1389,7 @@ public class AllTests(WebApplicationFactory<Startup> factory, ITestOutputHelper | ||||
|     /// <inheritdoc /> | ||||
|     [InlineData(default)] | ||||
|     [Theory] | ||||
|     public Task SetEnabledAsync(SetDeptEnabledReq req) | ||||
|     public Task<int> SetEnabledAsync(SetDeptEnabledReq req) | ||||
|     { | ||||
|         return default; | ||||
|     } | ||||
| @@ -1382,7 +1397,7 @@ public class AllTests(WebApplicationFactory<Startup> factory, ITestOutputHelper | ||||
|     /// <inheritdoc /> | ||||
|     [InlineData(default)] | ||||
|     [Theory] | ||||
|     public Task SetEnabledAsync(SetRoleEnabledReq req) | ||||
|     public Task<int> SetEnabledAsync(SetConfigEnabledReq req) | ||||
|     { | ||||
|         return default; | ||||
|     } | ||||
| @@ -1390,7 +1405,7 @@ public class AllTests(WebApplicationFactory<Startup> factory, ITestOutputHelper | ||||
|     /// <inheritdoc /> | ||||
|     [InlineData(default)] | ||||
|     [Theory] | ||||
|     public Task SetEnabledAsync(SetJobEnabledReq req) | ||||
|     public Task<int> SetEnabledAsync(SetRoleEnabledReq req) | ||||
|     { | ||||
|         return default; | ||||
|     } | ||||
| @@ -1398,7 +1413,23 @@ public class AllTests(WebApplicationFactory<Startup> factory, ITestOutputHelper | ||||
|     /// <inheritdoc /> | ||||
|     [InlineData(default)] | ||||
|     [Theory] | ||||
|     public Task SetEnabledAsync(SetUserEnabledReq req) | ||||
|     public Task<int> SetEnabledAsync(SetJobEnabledReq req) | ||||
|     { | ||||
|         return default; | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     [InlineData(default)] | ||||
|     [Theory] | ||||
|     public Task<int> SetEnabledAsync(SetUserEnabledReq req) | ||||
|     { | ||||
|         return default; | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     [InlineData(default)] | ||||
|     [Theory] | ||||
|     public Task<int> SetIgnorePermissionControlAsync(SetIgnorePermissionControlReq req) | ||||
|     { | ||||
|         return default; | ||||
|     } | ||||
| @@ -1414,7 +1445,15 @@ public class AllTests(WebApplicationFactory<Startup> factory, ITestOutputHelper | ||||
|     /// <inheritdoc /> | ||||
|     [InlineData(default)] | ||||
|     [Theory] | ||||
|     public Task<uint> SetPasswordAsync(SetPasswordReq req) | ||||
|     public Task<int> SetPasswordAsync(SetPasswordReq req) | ||||
|     { | ||||
|         return default; | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     [InlineData(default)] | ||||
|     [Theory] | ||||
|     public Task<int> SetSessionUserAppConfigAsync(SetSessionUserAppConfigReq req) | ||||
|     { | ||||
|         return default; | ||||
|     } | ||||
|   | ||||
| @@ -9,6 +9,7 @@ namespace NetAdmin.Domain.DbMaps.Sys; | ||||
| [Index($"{Chars.FLG_DB_INDEX_PREFIX}{nameof(JobId)}_{nameof(TimeId)}", $"{nameof(JobId)},{nameof(TimeId)}", true)] | ||||
| [Index(Chars.FLG_DB_INDEX_PREFIX             + nameof(CreatedTime),    nameof(CreatedTime),                 false)] | ||||
| [Index(Chars.FLG_DB_INDEX_PREFIX             + nameof(JobId),          nameof(JobId),                       false)] | ||||
| [Index(Chars.FLG_DB_INDEX_PREFIX             + nameof(HttpStatusCode), nameof(HttpStatusCode),              false)] | ||||
| [Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Sys_JobRecord))] | ||||
| public record Sys_JobRecord : LiteImmutableEntity | ||||
| { | ||||
|   | ||||
| @@ -115,7 +115,7 @@ public record Sys_User : VersionEntity, IFieldSummary, IFieldEnabled, IRegister | ||||
|                           ? Array.Empty<Sys_Role>() | ||||
|                           : s.RoleIds.Select(x => new Sys_Role { Id = x })); | ||||
|  | ||||
|         _ = config.ForType<EditSingleUserReq, Sys_User>() | ||||
|         _ = config.ForType<EditUserReq, Sys_User>() | ||||
|                   .Map( // | ||||
|                       d => d.Password, s => s.PasswordText.NullOrEmpty() ? Guid.Empty : s.PasswordText.Pwd().Guid()) | ||||
|                   .Map( // | ||||
|   | ||||
| @@ -9,6 +9,17 @@ namespace NetAdmin.Domain.DbMaps.Sys; | ||||
| [Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Sys_UserProfile))] | ||||
| public record Sys_UserProfile : VersionEntity, IRegister | ||||
| { | ||||
|     /// <summary> | ||||
|     ///     应用配置 | ||||
|     /// </summary> | ||||
|     #if DBTYPE_SQLSERVER | ||||
|     [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_MAX)] | ||||
|     #else | ||||
|     [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)] | ||||
|     #endif | ||||
|     [JsonIgnore] | ||||
|     public virtual string AppConfig { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     出生日期 | ||||
|     /// </summary> | ||||
|   | ||||
| @@ -8,5 +8,5 @@ public sealed record GetAllEntriesReq : DataAbstraction | ||||
|     /// <summary> | ||||
|     ///     数据库索引号 | ||||
|     /// </summary> | ||||
|     public uint DbIndex { get; init; } | ||||
|     public int DbIndex { get; init; } | ||||
| } | ||||
| @@ -1,22 +1,22 @@ | ||||
| using NetAdmin.Domain.DbMaps.Dependency; | ||||
| using NetAdmin.Domain.DbMaps.Dependency.Fields; | ||||
| using NetAdmin.Domain.DbMaps.Sys; | ||||
| using NetAdmin.Domain.Dto.Sys.UserProfile; | ||||
| 
 | ||||
| namespace NetAdmin.Domain.Dto.Sys.User; | ||||
| namespace NetAdmin.Domain.Dto.Sys.Config; | ||||
| 
 | ||||
| /// <summary> | ||||
| ///     请求:编辑用户单体 | ||||
| ///     请求:启用/禁用配置 | ||||
| /// </summary> | ||||
| public sealed record EditSingleUserReq : CreateEditUserReq | ||||
| public sealed record SetConfigEnabledReq : Sys_Config | ||||
| { | ||||
|     /// <inheritdoc cref="IFieldEnabled.Enabled" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.Never)] | ||||
|     public override bool Enabled { get; init; } | ||||
| 
 | ||||
|     /// <inheritdoc cref="EntityBase{T}.Id" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.Never)] | ||||
|     public override long Id { get; init; } | ||||
| 
 | ||||
|     /// <inheritdoc cref="Sys_User.Profile" /> | ||||
|     public new EditUserProfileReq Profile { get; init; } | ||||
| 
 | ||||
|     /// <inheritdoc cref="IFieldVersion.Version" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.Never)] | ||||
|     public override long Version { get; init; } | ||||
| @@ -5,4 +5,11 @@ namespace NetAdmin.Domain.Dto.Sys.Job; | ||||
| /// <summary> | ||||
| ///     请求:完成计划作业 | ||||
| /// </summary> | ||||
| public sealed record FinishJobReq : Sys_Job; | ||||
| public sealed record FinishJobReq : Sys_Job, IRegister | ||||
| { | ||||
|     /// <inheritdoc /> | ||||
|     public void Register(TypeAdapterConfig config) | ||||
|     { | ||||
|         _ = config.ForType<QueryJobRsp, FinishJobReq>().Map(d => d.LastStatusCode, s => ((Sys_Job)s).LastStatusCode); | ||||
|     } | ||||
| } | ||||
| @@ -12,6 +12,17 @@ namespace NetAdmin.Domain.Dto.Sys.Job; | ||||
| /// </summary> | ||||
| public sealed record QueryJobRsp : Sys_Job | ||||
| { | ||||
|     /// <inheritdoc cref="Sys_Job.LastStatusCode" /> | ||||
|     public new string LastStatusCode => | ||||
|         #pragma warning disable IDE0072 | ||||
|         base.LastStatusCode switch { | ||||
|             #pragma warning restore IDE0072 | ||||
|             null => null | ||||
|           , _ => (int)base.LastStatusCode.Value == Numbers.HTTP_STATUS_BIZ_FAIL | ||||
|                 ? nameof(ErrorCodes.Unhandled).ToLowerCamelCase() | ||||
|                 : base.LastStatusCode.Value.ToString().ToLowerCamelCase() | ||||
|         }; | ||||
|  | ||||
|     /// <inheritdoc cref="IFieldCreatedTime.CreatedTime" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.Never)] | ||||
|     public override DateTime CreatedTime { get; init; } | ||||
| @@ -52,10 +63,6 @@ public sealed record QueryJobRsp : Sys_Job | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] | ||||
|     public override DateTime? LastExecTime { get; init; } | ||||
|  | ||||
|     /// <inheritdoc cref="Sys_Job.LastStatusCode" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] | ||||
|     public override HttpStatusCode? LastStatusCode { get; init; } | ||||
|  | ||||
|     /// <inheritdoc cref="IFieldModifiedTime.ModifiedTime" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] | ||||
|     public override DateTime? ModifiedTime { get; init; } | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| using NetAdmin.Domain.DbMaps.Dependency; | ||||
| using NetAdmin.Domain.DbMaps.Dependency.Fields; | ||||
| using NetAdmin.Domain.DbMaps.Sys; | ||||
| using NetAdmin.Domain.Dto.Sys.Job; | ||||
| using HttpMethods = NetAdmin.Domain.Enums.HttpMethods; | ||||
|  | ||||
| namespace NetAdmin.Domain.Dto.Sys.JobRecord; | ||||
| @@ -11,8 +12,10 @@ namespace NetAdmin.Domain.Dto.Sys.JobRecord; | ||||
| public sealed record QueryJobRecordRsp : Sys_JobRecord | ||||
| { | ||||
|     /// <inheritdoc cref="Sys_JobRecord.HttpStatusCode" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.Never)] | ||||
|     public new HttpStatusCode HttpStatusCode => (HttpStatusCode)base.HttpStatusCode; | ||||
|     public new string HttpStatusCode => | ||||
|         base.HttpStatusCode == Numbers.HTTP_STATUS_BIZ_FAIL | ||||
|             ? nameof(ErrorCodes.Unhandled).ToLowerCamelCase() | ||||
|             : ((HttpStatusCode)base.HttpStatusCode).ToString().ToLowerCamelCase(); | ||||
|  | ||||
|     /// <inheritdoc cref="IFieldCreatedTime.CreatedTime" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.Never)] | ||||
| @@ -30,6 +33,11 @@ public sealed record QueryJobRecordRsp : Sys_JobRecord | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.Never)] | ||||
|     public override long Id { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     作业信息 | ||||
|     /// </summary> | ||||
|     public new QueryJobRsp Job { get; init; } | ||||
|  | ||||
|     /// <inheritdoc cref="Sys_JobRecord.JobId" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.Never)] | ||||
|     public override long JobId { get; init; } | ||||
|   | ||||
| @@ -0,0 +1,23 @@ | ||||
| using NetAdmin.Domain.DbMaps.Dependency; | ||||
| using NetAdmin.Domain.DbMaps.Dependency.Fields; | ||||
| using NetAdmin.Domain.DbMaps.Sys; | ||||
|  | ||||
| namespace NetAdmin.Domain.Dto.Sys.Role; | ||||
|  | ||||
| /// <summary> | ||||
| ///     请求:设置是否显示仪表板 | ||||
| /// </summary> | ||||
| public sealed record SetDisplayDashboardReq : Sys_Role | ||||
| { | ||||
|     /// <inheritdoc cref="Sys_Role.DisplayDashboard" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.Never)] | ||||
|     public override bool DisplayDashboard { get; init; } | ||||
|  | ||||
|     /// <inheritdoc cref="EntityBase{T}.Id" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.Never)] | ||||
|     public override long Id { get; init; } | ||||
|  | ||||
|     /// <inheritdoc cref="IFieldVersion.Version" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.Never)] | ||||
|     public override long Version { get; init; } | ||||
| } | ||||
| @@ -0,0 +1,23 @@ | ||||
| using NetAdmin.Domain.DbMaps.Dependency; | ||||
| using NetAdmin.Domain.DbMaps.Dependency.Fields; | ||||
| using NetAdmin.Domain.DbMaps.Sys; | ||||
|  | ||||
| namespace NetAdmin.Domain.Dto.Sys.Role; | ||||
|  | ||||
| /// <summary> | ||||
| ///     请求:设置是否忽略权限控制 | ||||
| /// </summary> | ||||
| public sealed record SetIgnorePermissionControlReq : Sys_Role | ||||
| { | ||||
|     /// <inheritdoc cref="EntityBase{T}.Id" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.Never)] | ||||
|     public override long Id { get; init; } | ||||
|  | ||||
|     /// <inheritdoc cref="Sys_Role.IgnorePermissionControl" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.Never)] | ||||
|     public override bool IgnorePermissionControl { get; init; } | ||||
|  | ||||
|     /// <inheritdoc cref="IFieldVersion.Version" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.Never)] | ||||
|     public override long Version { get; init; } | ||||
| } | ||||
| @@ -0,0 +1,23 @@ | ||||
| using NetAdmin.Domain.DbMaps.Dependency; | ||||
| using NetAdmin.Domain.DbMaps.Dependency.Fields; | ||||
| using NetAdmin.Domain.DbMaps.Sys; | ||||
|  | ||||
| namespace NetAdmin.Domain.Dto.Sys.UserProfile; | ||||
|  | ||||
| /// <summary> | ||||
| ///     响应:获取当前用户应用配置 | ||||
| /// </summary> | ||||
| public sealed record GetSessionUserAppConfigRsp : Sys_UserProfile | ||||
| { | ||||
|     /// <inheritdoc cref="Sys_UserProfile.AppConfig" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] | ||||
|     public override string AppConfig { get; init; } | ||||
|  | ||||
|     /// <inheritdoc cref="EntityBase{T}.Id" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.Never)] | ||||
|     public override long Id { get; init; } | ||||
|  | ||||
|     /// <inheritdoc cref="IFieldVersion.Version" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.Never)] | ||||
|     public override long Version { get; init; } | ||||
| } | ||||
| @@ -0,0 +1,13 @@ | ||||
| using NetAdmin.Domain.DbMaps.Sys; | ||||
|  | ||||
| namespace NetAdmin.Domain.Dto.Sys.UserProfile; | ||||
|  | ||||
| /// <summary> | ||||
| ///     请求:设置当前用户应用配置 | ||||
| /// </summary> | ||||
| public record SetSessionUserAppConfigReq : Sys_UserProfile | ||||
| { | ||||
|     /// <inheritdoc cref="Sys_UserProfile.AppConfig" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] | ||||
|     public override string AppConfig { get; init; } | ||||
| } | ||||
| @@ -21,7 +21,8 @@ public static class UnitOfWorkManagerExtensions | ||||
|             unitOfWork.Commit(); | ||||
|             logger?.Info($"{Ln.事务已提交}: {hashCode}"); | ||||
|         } | ||||
|         catch { | ||||
|         catch (Exception ex) { | ||||
|             logger?.Warn(ex); | ||||
|             unitOfWork.Rollback(); | ||||
|             logger?.Warn($"{Ln.事务已回滚}: {hashCode}"); | ||||
|             throw; | ||||
|   | ||||
| @@ -21,4 +21,9 @@ public interface IConfigModule : ICrudModule<CreateConfigReq, QueryConfigRsp // | ||||
|     ///     获取最新有效配置 | ||||
|     /// </summary> | ||||
|     Task<QueryConfigRsp> GetLatestConfigAsync(); | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     设置配置启用状态 | ||||
|     /// </summary> | ||||
|     Task<int> SetEnabledAsync(SetConfigEnabledReq req); | ||||
| } | ||||
| @@ -20,5 +20,5 @@ public interface IDeptModule : ICrudModule<CreateDeptReq, QueryDeptRsp // 创建 | ||||
|     /// <summary> | ||||
|     ///     启用/禁用部门 | ||||
|     /// </summary> | ||||
|     Task SetEnabledAsync(SetDeptEnabledReq req); | ||||
|     Task<int> SetEnabledAsync(SetDeptEnabledReq req); | ||||
| } | ||||
| @@ -52,5 +52,5 @@ public interface IJobModule : ICrudModule<CreateJobReq, QueryJobRsp // 创建类 | ||||
|     /// <summary> | ||||
|     ///     设置计划作业启用状态 | ||||
|     /// </summary> | ||||
|     Task SetEnabledAsync(SetJobEnabledReq req); | ||||
|     Task<int> SetEnabledAsync(SetJobEnabledReq req); | ||||
| } | ||||
| @@ -17,8 +17,18 @@ public interface IRoleModule : ICrudModule<CreateRoleReq, QueryRoleRsp // 创建 | ||||
|     /// </summary> | ||||
|     Task<QueryRoleRsp> EditAsync(EditRoleReq req); | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     设置是否显示仪表板 | ||||
|     /// </summary> | ||||
|     Task<int> SetDisplayDashboardAsync(SetDisplayDashboardReq req); | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     启用/禁用角色 | ||||
|     /// </summary> | ||||
|     Task SetEnabledAsync(SetRoleEnabledReq req); | ||||
|     Task<int> SetEnabledAsync(SetRoleEnabledReq req); | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     设置是否忽略权限控制 | ||||
|     /// </summary> | ||||
|     Task<int> SetIgnorePermissionControlAsync(SetIgnorePermissionControlReq req); | ||||
| } | ||||
| @@ -8,9 +8,9 @@ namespace NetAdmin.SysComponent.Application.Modules.Sys; | ||||
| /// <summary> | ||||
| ///     用户模块 | ||||
| /// </summary> | ||||
| public interface IUserModule : ICrudModule<CreateUserReq, QueryUserRsp // 创建类型 | ||||
|   , QueryUserReq, QueryUserRsp                                         // 查询类型 | ||||
|   , DelReq                                                             // 删除类型 | ||||
| public partial interface IUserModule : ICrudModule<CreateUserReq, QueryUserRsp // 创建类型 | ||||
|   , QueryUserReq, QueryUserRsp                                                 // 查询类型 | ||||
|   , DelReq                                                                     // 删除类型 | ||||
| > | ||||
| { | ||||
|     /// <summary> | ||||
| @@ -51,7 +51,7 @@ public interface IUserModule : ICrudModule<CreateUserReq, QueryUserRsp // 创建 | ||||
|     /// <summary> | ||||
|     ///     重设密码 | ||||
|     /// </summary> | ||||
|     Task<uint> ResetPasswordAsync(ResetPasswordReq req); | ||||
|     Task<int> ResetPasswordAsync(ResetPasswordReq req); | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     设置用户头像 | ||||
| @@ -66,7 +66,7 @@ public interface IUserModule : ICrudModule<CreateUserReq, QueryUserRsp // 创建 | ||||
|     /// <summary> | ||||
|     ///     启用/禁用用户 | ||||
|     /// </summary> | ||||
|     Task SetEnabledAsync(SetUserEnabledReq req); | ||||
|     Task<int> SetEnabledAsync(SetUserEnabledReq req); | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     设置手机号码 | ||||
| @@ -76,7 +76,7 @@ public interface IUserModule : ICrudModule<CreateUserReq, QueryUserRsp // 创建 | ||||
|     /// <summary> | ||||
|     ///     设置密码 | ||||
|     /// </summary> | ||||
|     Task<uint> SetPasswordAsync(SetPasswordReq req); | ||||
|     Task<int> SetPasswordAsync(SetPasswordReq req); | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     当前用户信息 | ||||
|   | ||||
| @@ -0,0 +1,17 @@ | ||||
| using NetAdmin.Domain.Dto.Sys.UserProfile; | ||||
|  | ||||
| // ReSharper disable once CheckNamespace | ||||
| namespace NetAdmin.SysComponent.Application.Modules.Sys; | ||||
|  | ||||
| public partial interface IUserModule | ||||
| { | ||||
|     /// <summary> | ||||
|     ///     获取当前用户应用配置 | ||||
|     /// </summary> | ||||
|     Task<GetSessionUserAppConfigRsp> GetSessionUserAppConfigAsync(); | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     设置当前用户应用配置 | ||||
|     /// </summary> | ||||
|     Task<int> SetSessionUserAppConfigAsync(SetSessionUserAppConfigReq req); | ||||
| } | ||||
| @@ -122,6 +122,13 @@ public sealed class ConfigService(BasicRepository<Sys_Config, long> rpo) // | ||||
|         return ret.Adapt<IEnumerable<QueryConfigRsp>>(); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public Task<int> SetEnabledAsync(SetConfigEnabledReq req) | ||||
|     { | ||||
|         req.ThrowIfInvalid(); | ||||
|         return UpdateAsync(req, [nameof(req.Enabled)]); | ||||
|     } | ||||
|  | ||||
|     private ISelect<Sys_Config> QueryInternal(QueryReq<QueryConfigReq> req) | ||||
|     { | ||||
|         var ret = Rpo.Select.Include(a => a.UserRegisterDept) | ||||
|   | ||||
| @@ -24,16 +24,14 @@ public sealed class ConstantService : ServiceBase<IConstantService>, IConstantSe | ||||
|                      .ToDictionary(x => x.Name, x => // | ||||
|                                        x.GetEnumValues().Cast<Enum>().ToDictionary(y => y.ToString(), GetDicValue)); | ||||
|  | ||||
|         ret.Add(                         // | ||||
|             $"{nameof(HttpStatusCode)}s" // | ||||
|           , Enum.GetNames<HttpStatusCode>() | ||||
|                 .ToDictionary( | ||||
|                     x => x | ||||
|                   , x => new[] { | ||||
|                                    Convert.ToInt64(Enum.Parse<HttpStatusCode>(x), CultureInfo.InvariantCulture) | ||||
|                                           .ToString(CultureInfo.InvariantCulture) | ||||
|                                  , x | ||||
|                                })); | ||||
|         var httpStatusCodes = Enum.GetNames<HttpStatusCode>().ToDictionary(x => x, GetHttpStatusCodeDicValue); | ||||
|         httpStatusCodes.Add( // | ||||
|             nameof(ErrorCodes.Unhandled) | ||||
|           , [ | ||||
|                 Numbers.HTTP_STATUS_BIZ_FAIL.ToInvString(), nameof(ErrorCodes.Unhandled) | ||||
|               , nameof(Indicates.Danger).ToLowerInvariant() | ||||
|             ]); | ||||
|         ret.Add($"{nameof(HttpStatusCode)}s", httpStatusCodes); | ||||
|         return ret; | ||||
|  | ||||
|         static string[] GetDicValue(Enum y) | ||||
| @@ -45,6 +43,19 @@ public sealed class ConstantService : ServiceBase<IConstantService>, IConstantSe | ||||
|             var indicate = y.GetAttributeOfType<IndicatorAttribute>()?.Indicate.ToLowerInvariant(); | ||||
|             return indicate.NullOrEmpty() ? ret : [..ret, indicate]; | ||||
|         } | ||||
|  | ||||
|         static string[] GetHttpStatusCodeDicValue(string name) | ||||
|         { | ||||
|             var codeInt = Convert.ToInt64(Enum.Parse<HttpStatusCode>(name), CultureInfo.InvariantCulture); | ||||
|             return [ | ||||
|                 codeInt.ToString(CultureInfo.InvariantCulture), name | ||||
|               , (codeInt switch { | ||||
|                      >= 200 and < 300 => nameof(Indicates.Success) | ||||
|                    , < 400            => nameof(Indicates.Warning) | ||||
|                    , _                => nameof(Indicates.Danger) | ||||
|                  }).ToLowerInvariant() | ||||
|             ]; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|   | ||||
| @@ -13,4 +13,14 @@ public interface IUserProfileService : IService, IUserProfileModule | ||||
|     ///     编辑用户档案 | ||||
|     /// </summary> | ||||
|     Task<int> EditAsync(EditUserProfileReq req); | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     获取当前用户配置 | ||||
|     /// </summary> | ||||
|     Task<GetSessionUserAppConfigRsp> GetSessionUserAppConfigAsync(); | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     设置当前用户配置 | ||||
|     /// </summary> | ||||
|     Task<int> SetSessionUserAppConfigAsync(SetSessionUserAppConfigReq req); | ||||
| } | ||||
| @@ -120,7 +120,7 @@ public sealed class DeptService(BasicRepository<Sys_Dept, long> rpo) // | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public Task SetEnabledAsync(SetDeptEnabledReq req) | ||||
|     public Task<int> SetEnabledAsync(SetDeptEnabledReq req) | ||||
|     { | ||||
|         req.ThrowIfInvalid(); | ||||
|         return UpdateAsync(req, [nameof(req.Enabled)]); | ||||
|   | ||||
| @@ -165,7 +165,8 @@ public sealed class JobRecordService(BasicRepository<Sys_JobRecord, long> rpo) / | ||||
|  | ||||
|     private ISelect<Sys_JobRecord> QueryInternal(QueryReq<QueryJobRecordReq> req) | ||||
|     { | ||||
|         var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter) | ||||
|         var ret = Rpo.Select.Include(a => a.Job) | ||||
|                      .WhereDynamicFilter(req.DynamicFilter) | ||||
|                      .WhereDynamic(req.Filter) | ||||
|                      .WhereIf( // | ||||
|                          req.Keywords?.Length > 0 | ||||
|   | ||||
| @@ -295,7 +295,7 @@ public sealed class JobService(BasicRepository<Sys_Job, long> rpo, IJobRecordSer | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public Task SetEnabledAsync(SetJobEnabledReq req) | ||||
|     public Task<int> SetEnabledAsync(SetJobEnabledReq req) | ||||
|     { | ||||
|         req.ThrowIfInvalid(); | ||||
|         return UpdateAsync(req, [nameof(Sys_Job.Enabled)]); | ||||
|   | ||||
| @@ -124,12 +124,26 @@ public sealed class RoleService(BasicRepository<Sys_Role, long> rpo) // | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public Task SetEnabledAsync(SetRoleEnabledReq req) | ||||
|     public Task<int> SetDisplayDashboardAsync(SetDisplayDashboardReq req) | ||||
|     { | ||||
|         req.ThrowIfInvalid(); | ||||
|         return UpdateAsync(req, [nameof(req.DisplayDashboard)]); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public Task<int> SetEnabledAsync(SetRoleEnabledReq req) | ||||
|     { | ||||
|         req.ThrowIfInvalid(); | ||||
|         return UpdateAsync(req, [nameof(req.Enabled)]); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public Task<int> SetIgnorePermissionControlAsync(SetIgnorePermissionControlReq req) | ||||
|     { | ||||
|         req.ThrowIfInvalid(); | ||||
|         return UpdateAsync(req, [nameof(req.IgnorePermissionControl)]); | ||||
|     } | ||||
|  | ||||
|     private ISelect<Sys_Role> QueryInternal(QueryReq<QueryRoleReq> req) | ||||
|     { | ||||
|         var ret = Rpo.Select.IncludeMany(a => a.Depts.Select(b => new Sys_Dept { Id = b.Id })) | ||||
|   | ||||
| @@ -56,7 +56,7 @@ public sealed class UserProfileService(BasicRepository<Sys_UserProfile, long> rp | ||||
|     /// <inheritdoc /> | ||||
|     public Task<int> EditAsync(EditUserProfileReq req) | ||||
|     { | ||||
|         return UpdateAsync(req, null); | ||||
|         return UpdateAsync(req.Adapt<Sys_UserProfile>(), null); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
| @@ -80,6 +80,13 @@ public sealed class UserProfileService(BasicRepository<Sys_UserProfile, long> rp | ||||
|         return ret.Adapt<QueryUserProfileRsp>(); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public async Task<GetSessionUserAppConfigRsp> GetSessionUserAppConfigAsync() | ||||
|     { | ||||
|         var ret = await Rpo.Select.Where(a => a.Id == UserToken.Id).ToOneAsync().ConfigureAwait(false); | ||||
|         return ret.Adapt<GetSessionUserAppConfigRsp>(); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public async Task<PagedQueryRsp<QueryUserProfileRsp>> PagedQueryAsync(PagedQueryReq<QueryUserProfileReq> req) | ||||
|     { | ||||
| @@ -147,6 +154,13 @@ public sealed class UserProfileService(BasicRepository<Sys_UserProfile, long> rp | ||||
|                                                                          }); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public Task<int> SetSessionUserAppConfigAsync(SetSessionUserAppConfigReq req) | ||||
|     { | ||||
|         req.ThrowIfInvalid(); | ||||
|         return UpdateAsync(req, [nameof(req.AppConfig)], null, a => a.Id == UserToken.Id, null, true); | ||||
|     } | ||||
|  | ||||
|     private ISelect<Sys_UserProfile, Sys_DicContent, Sys_DicContent, Sys_DicContent, Sys_DicContent> QueryInternal( | ||||
|         QueryReq<QueryUserProfileReq> req) | ||||
|     { | ||||
|   | ||||
| @@ -163,6 +163,12 @@ public sealed class UserService( | ||||
|         return ret.Adapt<QueryUserRsp>(); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public Task<GetSessionUserAppConfigRsp> GetSessionUserAppConfigAsync() | ||||
|     { | ||||
|         return userProfileService.GetSessionUserAppConfigAsync(); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     /// <exception cref="NetAdminInvalidOperationException">用户名或密码错误</exception> | ||||
|     public async Task<LoginRsp> LoginByPwdAsync(LoginByPwdReq req) | ||||
| @@ -259,7 +265,7 @@ public sealed class UserService( | ||||
|     /// <inheritdoc /> | ||||
|     /// <exception cref="NetAdminInvalidOperationException">验证码不正确</exception> | ||||
|     /// <exception cref="NetAdminInvalidOperationException">用户不存在</exception> | ||||
|     public async Task<uint> ResetPasswordAsync(ResetPasswordReq req) | ||||
|     public async Task<int> ResetPasswordAsync(ResetPasswordReq req) | ||||
|     { | ||||
|         req.ThrowIfInvalid(); | ||||
|         if (await verifyCodeService.VerifyAsync(req.VerifySmsCodeReq).ConfigureAwait(false)) { | ||||
| @@ -269,7 +275,7 @@ public sealed class UserService( | ||||
|                                                                                    Password = req.PasswordText.Pwd() | ||||
|                                                                                        .Guid() | ||||
|                                                                                }; | ||||
|             return (uint)await UpdateAsync(dto, [nameof(Sys_User.Password)]).ConfigureAwait(false); | ||||
|             return await UpdateAsync(dto, [nameof(Sys_User.Password)]).ConfigureAwait(false); | ||||
|         } | ||||
|  | ||||
|         throw new NetAdminInvalidOperationException(Ln.验证码不正确); | ||||
| @@ -335,7 +341,7 @@ public sealed class UserService( | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public Task SetEnabledAsync(SetUserEnabledReq req) | ||||
|     public Task<int> SetEnabledAsync(SetUserEnabledReq req) | ||||
|     { | ||||
|         req.ThrowIfInvalid(); | ||||
|         return UpdateAsync(req, [nameof(req.Enabled)]); | ||||
| @@ -386,18 +392,23 @@ public sealed class UserService( | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public async Task<uint> SetPasswordAsync(SetPasswordReq req) | ||||
|     public async Task<int> SetPasswordAsync(SetPasswordReq req) | ||||
|     { | ||||
|         req.ThrowIfInvalid(); | ||||
|         var version = await Rpo.Where(a => a.Id == UserToken.Id && a.Password == req.OldPassword.Pwd().Guid()) | ||||
|                                .ToOneAsync(a => new long?(a.Version)) | ||||
|                                .ConfigureAwait(false) ?? throw new NetAdminInvalidOperationException($"{Ln.旧密码不正确}"); | ||||
|  | ||||
|         var ret = await UpdateAsync( | ||||
|         return await UpdateAsync( | ||||
|                 new Sys_User { Id = UserToken.Id, Password = req.NewPassword.Pwd().Guid(), Version = version } | ||||
|               , [nameof(Sys_User.Password)]) | ||||
|             .ConfigureAwait(false); | ||||
|         return (uint)ret; | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public Task<int> SetSessionUserAppConfigAsync(SetSessionUserAppConfigReq req) | ||||
|     { | ||||
|         return userProfileService.SetSessionUserAppConfigAsync(req); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
| @@ -495,9 +506,9 @@ public sealed class UserService( | ||||
|                          req.Filter?.RoleId > 0, a => a.Roles.Any(b => b.Id == req.Filter.RoleId)) | ||||
|                      .WhereIf( // | ||||
|                          req.Keywords?.Length > 0 | ||||
|                        , a => a.Id == req.Keywords.Int64Try(0) || a.UserName.Contains(req.Keywords) || | ||||
|                               a.Mobile.Contains(req.Keywords)  || a.Email.Contains(req.Keywords)    || | ||||
|                               a.Summary.Contains(req.Keywords)); | ||||
|                        , a => a.Id     == req.Keywords.Int64Try(0) || a.UserName == req.Keywords || | ||||
|                               a.Mobile == req.Keywords             || | ||||
|                               a.Email  == req.Keywords             || a.Summary.Contains(req.Keywords)); | ||||
|         switch (req.Order) { | ||||
|             case Orders.None: | ||||
|                 return ret; | ||||
|   | ||||
| @@ -69,4 +69,10 @@ public sealed class ConfigCache(IDistributedCache cache, IConfigService service) | ||||
|     { | ||||
|         return Service.QueryAsync(req); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public Task<int> SetEnabledAsync(SetConfigEnabledReq req) | ||||
|     { | ||||
|         return Service.SetEnabledAsync(req); | ||||
|     } | ||||
| } | ||||
| @@ -65,7 +65,7 @@ public sealed class DeptCache(IDistributedCache cache, IDeptService service) // | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public Task SetEnabledAsync(SetDeptEnabledReq req) | ||||
|     public Task<int> SetEnabledAsync(SetDeptEnabledReq req) | ||||
|     { | ||||
|         return Service.SetEnabledAsync(req); | ||||
|     } | ||||
|   | ||||
| @@ -123,7 +123,7 @@ public sealed class JobCache(IDistributedCache cache, IJobService service) | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public Task SetEnabledAsync(SetJobEnabledReq req) | ||||
|     public Task<int> SetEnabledAsync(SetJobEnabledReq req) | ||||
|     { | ||||
|         return Service.SetEnabledAsync(req); | ||||
|     } | ||||
|   | ||||
| @@ -65,8 +65,20 @@ public sealed class RoleCache(IDistributedCache cache, IRoleService service) // | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public Task SetEnabledAsync(SetRoleEnabledReq req) | ||||
|     public Task<int> SetDisplayDashboardAsync(SetDisplayDashboardReq req) | ||||
|     { | ||||
|         return Service.SetDisplayDashboardAsync(req); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public Task<int> SetEnabledAsync(SetRoleEnabledReq req) | ||||
|     { | ||||
|         return Service.SetEnabledAsync(req); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public Task<int> SetIgnorePermissionControlAsync(SetIgnorePermissionControlReq req) | ||||
|     { | ||||
|         return Service.SetIgnorePermissionControlAsync(req); | ||||
|     } | ||||
| } | ||||
| @@ -65,6 +65,12 @@ public sealed class UserCache(IDistributedCache cache, IUserService service, IVe | ||||
|         return Service.GetAsync(req); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public Task<GetSessionUserAppConfigRsp> GetSessionUserAppConfigAsync() | ||||
|     { | ||||
|         return Service.GetSessionUserAppConfigAsync(); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public Task<LoginRsp> LoginByPwdAsync(LoginByPwdReq req) | ||||
|     { | ||||
| @@ -157,7 +163,7 @@ public sealed class UserCache(IDistributedCache cache, IUserService service, IVe | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public Task<uint> ResetPasswordAsync(ResetPasswordReq req) | ||||
|     public Task<int> ResetPasswordAsync(ResetPasswordReq req) | ||||
|     { | ||||
|         return Service.ResetPasswordAsync(req); | ||||
|     } | ||||
| @@ -177,7 +183,7 @@ public sealed class UserCache(IDistributedCache cache, IUserService service, IVe | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public Task SetEnabledAsync(SetUserEnabledReq req) | ||||
|     public Task<int> SetEnabledAsync(SetUserEnabledReq req) | ||||
|     { | ||||
|         return Service.SetEnabledAsync(req); | ||||
|     } | ||||
| @@ -189,11 +195,17 @@ public sealed class UserCache(IDistributedCache cache, IUserService service, IVe | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public Task<uint> SetPasswordAsync(SetPasswordReq req) | ||||
|     public Task<int> SetPasswordAsync(SetPasswordReq req) | ||||
|     { | ||||
|         return Service.SetPasswordAsync(req); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public Task<int> SetSessionUserAppConfigAsync(SetSessionUserAppConfigReq req) | ||||
|     { | ||||
|         return Service.SetSessionUserAppConfigAsync(req); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public Task<UserInfoRsp> UserInfoAsync() | ||||
|     { | ||||
|   | ||||
| @@ -99,4 +99,12 @@ public sealed class ConfigController(IConfigCache cache) : ControllerBase<IConfi | ||||
|     { | ||||
|         return Cache.QueryAsync(req); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     设置配置启用状态 | ||||
|     /// </summary> | ||||
|     public Task<int> SetEnabledAsync(SetConfigEnabledReq req) | ||||
|     { | ||||
|         return Cache.SetEnabledAsync(req); | ||||
|     } | ||||
| } | ||||
| @@ -95,7 +95,7 @@ public sealed class DeptController(IDeptCache cache) : ControllerBase<IDeptCache | ||||
|     /// <summary> | ||||
|     ///     启用/禁用部门 | ||||
|     /// </summary> | ||||
|     public Task SetEnabledAsync(SetDeptEnabledReq req) | ||||
|     public Task<int> SetEnabledAsync(SetDeptEnabledReq req) | ||||
|     { | ||||
|         return Cache.SetEnabledAsync(req); | ||||
|     } | ||||
|   | ||||
| @@ -144,7 +144,7 @@ public sealed class JobController(IJobCache cache) : ControllerBase<IJobCache, I | ||||
|     /// <summary> | ||||
|     ///     启用/禁用作业 | ||||
|     /// </summary> | ||||
|     public Task SetEnabledAsync(SetJobEnabledReq req) | ||||
|     public Task<int> SetEnabledAsync(SetJobEnabledReq req) | ||||
|     { | ||||
|         return Cache.SetEnabledAsync(req); | ||||
|     } | ||||
|   | ||||
| @@ -91,11 +91,27 @@ public sealed class RoleController(IRoleCache cache) : ControllerBase<IRoleCache | ||||
|         return Cache.QueryAsync(req); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     设置是否显示仪表板 | ||||
|     /// </summary> | ||||
|     public Task<int> SetDisplayDashboardAsync(SetDisplayDashboardReq req) | ||||
|     { | ||||
|         return Cache.SetDisplayDashboardAsync(req); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     启用/禁用角色 | ||||
|     /// </summary> | ||||
|     public Task SetEnabledAsync(SetRoleEnabledReq req) | ||||
|     public Task<int> SetEnabledAsync(SetRoleEnabledReq req) | ||||
|     { | ||||
|         return Cache.SetEnabledAsync(req); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     设置是否忽略权限控制 | ||||
|     /// </summary> | ||||
|     public Task<int> SetIgnorePermissionControlAsync(SetIgnorePermissionControlReq req) | ||||
|     { | ||||
|         return Cache.SetIgnorePermissionControlAsync(req); | ||||
|     } | ||||
| } | ||||
| @@ -96,6 +96,14 @@ public sealed class UserController(IUserCache cache, IConfigCache configCache) | ||||
|         return Cache.GetAsync(req); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     获取当前用户应用配置 | ||||
|     /// </summary> | ||||
|     public Task<GetSessionUserAppConfigRsp> GetSessionUserAppConfigAsync() | ||||
|     { | ||||
|         return Cache.GetSessionUserAppConfigAsync(); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     密码登录 | ||||
|     /// </summary> | ||||
| @@ -168,7 +176,7 @@ public sealed class UserController(IUserCache cache, IConfigCache configCache) | ||||
|     /// </summary> | ||||
|     [AllowAnonymous] | ||||
|     [Transaction] | ||||
|     public Task<uint> ResetPasswordAsync(ResetPasswordReq req) | ||||
|     public Task<int> ResetPasswordAsync(ResetPasswordReq req) | ||||
|     { | ||||
|         return Cache.ResetPasswordAsync(req); | ||||
|     } | ||||
| @@ -195,7 +203,7 @@ public sealed class UserController(IUserCache cache, IConfigCache configCache) | ||||
|     ///     启用/禁用用户 | ||||
|     /// </summary> | ||||
|     [Transaction] | ||||
|     public Task SetEnabledAsync(SetUserEnabledReq req) | ||||
|     public Task<int> SetEnabledAsync(SetUserEnabledReq req) | ||||
|     { | ||||
|         return Cache.SetEnabledAsync(req); | ||||
|     } | ||||
| @@ -213,11 +221,19 @@ public sealed class UserController(IUserCache cache, IConfigCache configCache) | ||||
|     ///     设置密码 | ||||
|     /// </summary> | ||||
|     [Transaction] | ||||
|     public Task<uint> SetPasswordAsync(SetPasswordReq req) | ||||
|     public Task<int> SetPasswordAsync(SetPasswordReq req) | ||||
|     { | ||||
|         return Cache.SetPasswordAsync(req); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     设置当前用户应用配置 | ||||
|     /// </summary> | ||||
|     public Task<int> SetSessionUserAppConfigAsync(SetSessionUserAppConfigReq req) | ||||
|     { | ||||
|         return Cache.SetSessionUserAppConfigAsync(req); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     当前用户信息 | ||||
|     /// </summary> | ||||
|   | ||||
| @@ -68,7 +68,7 @@ | ||||
|             } | ||||
|  | ||||
|             .app-loading__title { | ||||
|                 font-family: 'Arial', 'Microsoft YaHei', 'monospace'; | ||||
|                 font-family: 'Microsoft YaHei', sans-serif; | ||||
|                 font-size: 24px; | ||||
|                 color: #333; | ||||
|                 margin-top: 30px; | ||||
| @@ -125,7 +125,7 @@ | ||||
|  | ||||
|         <script type="text/javascript"> | ||||
|             // 黑夜模式 | ||||
|             if (window.localStorage.getItem('APP_DARK')) { | ||||
|             if (window.localStorage.getItem('APP_SET_DARK')) { | ||||
|                 document.documentElement.classList.add('dark') | ||||
|             } | ||||
|  | ||||
|   | ||||
| @@ -43,8 +43,17 @@ export default { | ||||
|         }, | ||||
|     }, | ||||
|     async created() { | ||||
|         await this.$TOOL.data.downloadConfig() | ||||
|  | ||||
|         //设置深色模式 | ||||
|         if (this.$TOOL.data.get('APP_SET_DARK') || this.$CONFIG.APP_SET_DARK) { | ||||
|             document.documentElement.classList.add('dark') | ||||
|         } else { | ||||
|             document.documentElement.classList.remove('dark') | ||||
|         } | ||||
|  | ||||
|         //设置主题颜色 | ||||
|         const app_color = this.$TOOL.data.get('APP_COLOR') ?? this.$CONFIG.COLOR | ||||
|         const app_color = this.$TOOL.data.get('APP_SET_COLOR') || this.$CONFIG.APP_SET_COLOR | ||||
|         if (app_color) { | ||||
|             document.documentElement.style.setProperty('--el-color-primary', app_color) | ||||
|             for (let i = 1; i <= 9; i++) { | ||||
| @@ -56,28 +65,31 @@ export default { | ||||
|         } | ||||
|  | ||||
|         //设置布局 | ||||
|         const layout = this.$TOOL.data.get('LAYOUT') ?? this.$CONFIG.LAYOUT | ||||
|         const layout = this.$TOOL.data.get('APP_SET_LAYOUT') || this.$CONFIG.APP_SET_LAYOUT | ||||
|         if (layout) { | ||||
|             this.$store.commit('SET_layout', layout) | ||||
|         } | ||||
|  | ||||
|         //菜单是否折叠 | ||||
|         const menuIsCollapse = this.$TOOL.data.get('MENU_IS_COLLAPSE') ?? this.$CONFIG.MENU_IS_COLLAPSE | ||||
|         const menuIsCollapse = this.$TOOL.data.get('APP_SET_MENU_IS_COLLAPSE') || this.$CONFIG.APP_SET_MENU_IS_COLLAPSE | ||||
|         if (menuIsCollapse !== this.$store.state.global.menuIsCollapse) { | ||||
|             this.$store.commit('TOGGLE_menuIsCollapse') | ||||
|         } | ||||
|  | ||||
|         //是否开启多标签 | ||||
|         const layoutTags = this.$TOOL.data.get('LAYOUT_TAGS') ?? this.$CONFIG.LAYOUT_TAGS | ||||
|         const layoutTags = this.$TOOL.data.get('APP_SET_MULTI_TAGS') || this.$CONFIG.APP_SET_MULTI_TAGS | ||||
|         if (layoutTags !== this.$store.state.global.layoutTags) { | ||||
|             this.$store.commit('TOGGLE_layoutTags') | ||||
|         } | ||||
|  | ||||
|         //是否开启手风琴菜单 | ||||
|         const menuUniqueOpened = this.$TOOL.data.get('MENU_UNIQUE_OPENED') ?? this.$CONFIG.MENU_UNIQUE_OPENED | ||||
|         if (menuUniqueOpened !== this.$CONFIG.MENU_UNIQUE_OPENED) { | ||||
|             this.$CONFIG.MENU_UNIQUE_OPENED = menuUniqueOpened | ||||
|         const menuUniqueOpened = this.$TOOL.data.get('APP_SET_MENU_UNIQUE_OPENED') || this.$CONFIG.APP_SET_MENU_UNIQUE_OPENED | ||||
|         if (menuUniqueOpened !== this.$CONFIG.APP_SET_MENU_UNIQUE_OPENED) { | ||||
|             this.$CONFIG.APP_SET_MENU_UNIQUE_OPENED = menuUniqueOpened | ||||
|         } | ||||
|  | ||||
|         // 设置语言 | ||||
|         this.$i18n.locale = this.$TOOL.data.get('APP_SET_LANG') || this.$CONFIG.APP_SET_LANG | ||||
|     }, | ||||
| } | ||||
| </script> | ||||
|   | ||||
| @@ -103,4 +103,15 @@ export default { | ||||
|             return await http.post(this.url, data, config) | ||||
|         }, | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * 设置配置启用状态 | ||||
|      */ | ||||
|     setEnabled: { | ||||
|         url: `${config.API_URL}/api/sys/config/set.enabled`, | ||||
|         name: `设置配置启用状态`, | ||||
|         post: async function (data = {}, config = {}) { | ||||
|             return await http.post(this.url, data, config) | ||||
|         }, | ||||
|     }, | ||||
| } | ||||
| @@ -93,6 +93,17 @@ export default { | ||||
|         }, | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * 设置是否显示仪表板 | ||||
|      */ | ||||
|     setDisplayDashboard: { | ||||
|         url: `${config.API_URL}/api/sys/role/set.display.dashboard`, | ||||
|         name: `设置是否显示仪表板`, | ||||
|         post: async function (data = {}, config = {}) { | ||||
|             return await http.post(this.url, data, config) | ||||
|         }, | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * 启用/禁用角色 | ||||
|      */ | ||||
| @@ -103,4 +114,15 @@ export default { | ||||
|             return await http.post(this.url, data, config) | ||||
|         }, | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * 设置是否忽略权限控制 | ||||
|      */ | ||||
|     setIgnorePermissionControl: { | ||||
|         url: `${config.API_URL}/api/sys/role/set.ignore.permission.control`, | ||||
|         name: `设置是否忽略权限控制`, | ||||
|         post: async function (data = {}, config = {}) { | ||||
|             return await http.post(this.url, data, config) | ||||
|         }, | ||||
|     }, | ||||
| } | ||||
| @@ -82,6 +82,17 @@ export default { | ||||
|         }, | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * 获取当前用户应用配置 | ||||
|      */ | ||||
|     getSessionUserAppConfig: { | ||||
|         url: `${config.API_URL}/api/sys/user/get.session.user.app.config`, | ||||
|         name: `获取当前用户应用配置`, | ||||
|         post: async function (data = {}, config = {}) { | ||||
|             return await http.post(this.url, data, config) | ||||
|         }, | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * 密码登录 | ||||
|      */ | ||||
| @@ -214,6 +225,17 @@ export default { | ||||
|         }, | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * 设置当前用户应用配置 | ||||
|      */ | ||||
|     setSessionUserAppConfig: { | ||||
|         url: `${config.API_URL}/api/sys/user/set.session.user.app.config`, | ||||
|         name: `设置当前用户应用配置`, | ||||
|         post: async function (data = {}, config = {}) { | ||||
|             return await http.post(this.url, data, config) | ||||
|         }, | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * 当前用户信息 | ||||
|      */ | ||||
|   | ||||
| @@ -1,25 +0,0 @@ | ||||
| <template> | ||||
|     <el-button @click="add" icon="el-icon-plus" type="primary"></el-button> | ||||
| </template> | ||||
| <style scoped></style> | ||||
| <script> | ||||
| export default { | ||||
|     emits: [], | ||||
|     props: { vue: { type: Object }, data: { type: Object } }, | ||||
|     data() { | ||||
|         return {} | ||||
|     }, | ||||
|     mounted() {}, | ||||
|     created() {}, | ||||
|     components: {}, | ||||
|     computed: {}, | ||||
|     methods: { | ||||
|         //添加 | ||||
|         async add() { | ||||
|             this.vue.dialog.save = true | ||||
|             await this.vue.$nextTick() | ||||
|             this.vue.$refs.saveDialog.open('add', this.data) | ||||
|         }, | ||||
|     }, | ||||
| } | ||||
| </script> | ||||
| @@ -1,9 +1,9 @@ | ||||
| <template> | ||||
|     <el-table-column :label="label" :prop="prop" sortable="custom"> | ||||
|         <template #default="scope"> | ||||
|         <template #default="{ row }"> | ||||
|             <div class="avatar"> | ||||
|                 <el-avatar :src="getAvatar(scope, prop)" size="small"></el-avatar> | ||||
|                 <span>{{ tool.getNestedProperty(scope.row, prop) }}</span> | ||||
|                 <el-avatar :src="getAvatar(row, prop)" size="small"></el-avatar> | ||||
|                 <span>{{ tool.getNestedProperty(row, prop) }}</span> | ||||
|             </div> | ||||
|         </template> | ||||
|     </el-table-column> | ||||
| @@ -36,8 +36,8 @@ export default { | ||||
|     }, | ||||
|     methods: { | ||||
|         //获取头像 | ||||
|         getAvatar(scope, prop) { | ||||
|             return scope.row.avatar ? scope.row.avatar : this.$CONFIG.DEFAULT_AVATAR(tool.getNestedProperty(scope.row, prop)) | ||||
|         getAvatar(row, prop) { | ||||
|             return row.avatar ? row.avatar : this.$CONFIG.DEFAULT_AVATAR(tool.getNestedProperty(row, prop)) | ||||
|         }, | ||||
|     }, | ||||
| } | ||||
|   | ||||
| @@ -1,33 +1,33 @@ | ||||
| <template> | ||||
|     <el-table-column v-bind="$attrs"> | ||||
|         <template #default="scope"> | ||||
|             <el-text @click="click(scope.row)" style="cursor: pointer" tag="ins"> | ||||
|                 {{ tool.getNestedProperty(scope.row, $attrs.prop) }} | ||||
|             </el-text> | ||||
|         <template #default="{ row }"> | ||||
|             <p>{{ row.id }}</p> | ||||
|             <p v-if="showTime" class="time">{{ row.createdTime }}</p> | ||||
|             <slot :data="row"></slot> | ||||
|         </template> | ||||
|     </el-table-column> | ||||
| </template> | ||||
| <script> | ||||
| import tool from '@/utils/tool' | ||||
| export default { | ||||
|     emits: ['click'], | ||||
|     props: {}, | ||||
|     emits: [], | ||||
|     props: { | ||||
|         showTime: { | ||||
|             type: Boolean, | ||||
|             default: true, | ||||
|         }, | ||||
|     }, | ||||
|     data() { | ||||
|         return {} | ||||
|     }, | ||||
|     mounted() {}, | ||||
|     created() {}, | ||||
|     components: {}, | ||||
|     computed: { | ||||
|         tool() { | ||||
|             return tool | ||||
|         }, | ||||
|     }, | ||||
|     methods: { | ||||
|         async click(row) { | ||||
|             this.$emit('click', row) | ||||
|         }, | ||||
|     }, | ||||
|     computed: {}, | ||||
|     methods: {}, | ||||
| } | ||||
| </script> | ||||
| <style scoped></style> | ||||
| <style scoped> | ||||
| .time { | ||||
|     color: var(--el-text-color-secondary); | ||||
| } | ||||
| </style> | ||||
| @@ -2,6 +2,7 @@ | ||||
|     <el-table-column v-bind:="$attrs"> | ||||
|         <template #default="{ row }"> | ||||
|             <na-indicator :data="row" :options="options" :prop="$attrs.prop" /> | ||||
|             <slot :data="row" name="info"></slot> | ||||
|         </template> | ||||
|     </el-table-column> | ||||
| </template> | ||||
|   | ||||
| @@ -1,31 +1,23 @@ | ||||
| <template> | ||||
|     <el-table-column align="right"> | ||||
|         <template #default="scope"> | ||||
|         <template #default="{ row }"> | ||||
|             <el-button-group> | ||||
|                 <template v-for="(item, i) in buttons?.filter((x) => !x.condition || x.condition(scope))" :key="i"> | ||||
|                 <template v-for="(item, i) in buttons?.filter((x) => !x.condition || x.condition(row))" :key="i"> | ||||
|                     <el-popconfirm | ||||
|                         v-if="item.confirm" | ||||
|                         :title="this.$t(`确定 {title}?`, { title: item.title })" | ||||
|                         @confirm="item.click(scope.row, vue)" | ||||
|                         @confirm="item.click(row, vue)" | ||||
|                         width="20rem"> | ||||
|                         <template #reference> | ||||
|                             <el-button :icon="item.icon" :title="item.title" :type="item.type" @click.native.stop size="small"></el-button> | ||||
|                         </template> | ||||
|                     </el-popconfirm> | ||||
|                     <el-button v-else :icon="item.icon" :title="item.title" @click="item.click(scope.row, vue)" size="small" | ||||
|                         >{{ item.title }} | ||||
|                     </el-button> | ||||
|                     <el-button v-else :icon="item.icon" :title="item.title" @click="item.click(row, vue)" size="small">{{ item.title }} </el-button> | ||||
|                 </template> | ||||
|             </el-button-group> | ||||
|         </template> | ||||
|     </el-table-column> | ||||
| </template> | ||||
| <style scoped> | ||||
| .avatar { | ||||
|     display: flex; | ||||
|     gap: 0.5rem; | ||||
| } | ||||
| </style> | ||||
| <script> | ||||
| import naColOperation from '@/config/naColOperation' | ||||
|  | ||||
| @@ -48,4 +40,5 @@ export default { | ||||
|     computed: {}, | ||||
|     methods: {}, | ||||
| } | ||||
| </script> | ||||
| </script> | ||||
| <style scoped></style> | ||||
| @@ -1,15 +1,16 @@ | ||||
| <template> | ||||
|     <el-table-column :label="label" :prop="`${prop}.${field}`"> | ||||
|         <template #default="scope"> | ||||
|             <template v-for="(item, i) in Array.isArray(scope.row[prop]) ? scope.row[prop] : [scope.row[prop]]" :key="i"> | ||||
|                 <el-tag v-if="item" @click="$emit('click', item)"> | ||||
|                     {{ item ? item[field] : '' }} | ||||
|                 </el-tag> | ||||
|             </template> | ||||
|         <template #default="{ row }"> | ||||
|             <div class="flex"> | ||||
|                 <template v-for="(item, i) in Array.isArray(row[prop]) ? row[prop] : [row[prop]]" :key="i"> | ||||
|                     <el-tag v-if="item" @click="$emit('click', item)"> | ||||
|                         {{ item ? item[field] : '' }} | ||||
|                     </el-tag> | ||||
|                 </template> | ||||
|             </div> | ||||
|         </template> | ||||
|     </el-table-column> | ||||
| </template> | ||||
| <style scoped></style> | ||||
| <script> | ||||
| export default { | ||||
|     emits: ['click'], | ||||
| @@ -27,4 +28,9 @@ export default { | ||||
|     computed: {}, | ||||
|     methods: {}, | ||||
| } | ||||
| </script> | ||||
| </script> | ||||
| <style scoped> | ||||
| .el-tag { | ||||
|     cursor: pointer; | ||||
| } | ||||
| </style> | ||||
| @@ -1,7 +1,7 @@ | ||||
| <template> | ||||
|     <el-table-column :label="label" :prop="prop"> | ||||
|         <template #default="scope"> | ||||
|             {{ tool.dateFormat(scope.row[prop]) }} | ||||
|         <template #default="{ row }"> | ||||
|             {{ tool.dateFormat(row[prop]) }} | ||||
|         </template> | ||||
|     </el-table-column> | ||||
| </template> | ||||
|   | ||||
| @@ -1,24 +1,50 @@ | ||||
| <template> | ||||
|     <el-table-column v-bind="$attrs"> | ||||
|         <template #default="scope"> | ||||
|             <div @click="click(tool.getNestedProperty(scope.row, $attrs.prop))" class="avatar"> | ||||
|                 <el-avatar | ||||
|                     v-if="tool.getNestedProperty(scope.row, $attrs.nestProp)" | ||||
|                     :src="getAvatar(scope, $attrs.nestProp)" | ||||
|                     size="small"></el-avatar> | ||||
|         <template #default="{ row }"> | ||||
|             <div @click="click($TOOL.getNestedProperty(row, $attrs.prop))" class="avatar"> | ||||
|                 <el-avatar v-if="$TOOL.getNestedProperty(row, $attrs.nestProp)" :src="getAvatar(row, $attrs.nestProp)" size="small"></el-avatar> | ||||
|                 <div> | ||||
|                     <p>{{ tool.getNestedProperty(scope.row, $attrs.nestProp) }}</p> | ||||
|                     <p v-if="$attrs.nestProp2">{{ tool.getNestedProperty(scope.row, $attrs.nestProp2) }}</p> | ||||
|                     <p>{{ $TOOL.getNestedProperty(row, $attrs.nestProp) }}</p> | ||||
|                     <p v-if="$attrs.nestProp2">{{ $TOOL.getNestedProperty(row, $attrs.nestProp2) }}</p> | ||||
|                 </div> | ||||
|             </div> | ||||
|             <save-dialog v-if="dialog.save" @closed="dialog.save = false" ref="saveDialog"></save-dialog> | ||||
|         </template> | ||||
|     </el-table-column> | ||||
| </template> | ||||
| <script> | ||||
| import saveDialog from '@/views/sys/user/save.vue' | ||||
|  | ||||
| export default { | ||||
|     components: { saveDialog }, | ||||
|     computed: {}, | ||||
|     created() {}, | ||||
|     data() { | ||||
|         return { | ||||
|             dialog: { save: false }, | ||||
|         } | ||||
|     }, | ||||
|     emits: ['click'], | ||||
|     methods: { | ||||
|         async click(id) { | ||||
|             this.dialog.save = true | ||||
|             await this.$nextTick() | ||||
|             await this.$refs.saveDialog.open({ mode: 'view', row: { id: id } }) | ||||
|         }, | ||||
|         //获取头像 | ||||
|         getAvatar(row, prop) { | ||||
|             return row.avatar ? row.avatar : this.$CONFIG.DEFAULT_AVATAR(this.$TOOL.getNestedProperty(row, prop)) | ||||
|         }, | ||||
|     }, | ||||
|     mounted() {}, | ||||
|     props: {}, | ||||
|     watch: {}, | ||||
| } | ||||
| </script> | ||||
| <style lang="scss" scoped> | ||||
| .avatar { | ||||
|     div:last-child { | ||||
|         line-height: 1rem; | ||||
|         line-height: 1.2rem; | ||||
|         p:last-child { | ||||
|             color: var(--el-color-info-light-3); | ||||
|         } | ||||
| @@ -29,37 +55,4 @@ | ||||
|     display: flex; | ||||
|     gap: 0.5rem; | ||||
| } | ||||
| </style> | ||||
| <script> | ||||
| import saveDialog from '@/views/sys/user/save.vue' | ||||
| import tool from '@/utils/tool' | ||||
|  | ||||
| export default { | ||||
|     emits: ['click'], | ||||
|     props: {}, | ||||
|     data() { | ||||
|         return { | ||||
|             dialog: { save: false }, | ||||
|         } | ||||
|     }, | ||||
|     mounted() {}, | ||||
|     created() {}, | ||||
|     components: { saveDialog }, | ||||
|     computed: { | ||||
|         tool() { | ||||
|             return tool | ||||
|         }, | ||||
|     }, | ||||
|     methods: { | ||||
|         async click(id) { | ||||
|             this.dialog.save = true | ||||
|             await this.$nextTick() | ||||
|             await this.$refs.saveDialog.open('view', { id: id }) | ||||
|         }, | ||||
|         //获取头像 | ||||
|         getAvatar(scope, prop) { | ||||
|             return scope.row.avatar ? scope.row.avatar : this.$CONFIG.DEFAULT_AVATAR(tool.getNestedProperty(scope.row, prop)) | ||||
|         }, | ||||
|     }, | ||||
| } | ||||
| </script> | ||||
| </style> | ||||
| @@ -36,7 +36,8 @@ export default { | ||||
|     }, | ||||
|     mounted() {}, | ||||
|     async created() { | ||||
|         this.options = (await this.$API.sys_dept.query.post()).data | ||||
|         const res = await this.$API.sys_dept.query.post() | ||||
|         this.options = res.data | ||||
|     }, | ||||
|     components: {}, | ||||
|     computed: {}, | ||||
|   | ||||
| @@ -41,7 +41,8 @@ export default { | ||||
|     }, | ||||
|     mounted() {}, | ||||
|     async created() { | ||||
|         this.options = (await this.$API.sys_dic.queryCatalog.post()).data | ||||
|         const res = await this.$API.sys_dic.queryCatalog.post() | ||||
|         this.options = res.data | ||||
|     }, | ||||
|     components: {}, | ||||
|     computed: {}, | ||||
|   | ||||
| @@ -82,13 +82,16 @@ export default { | ||||
|         async captchaSuccess(obj) { | ||||
|             this.sendDisabled = true | ||||
|             try { | ||||
|                 await this.$API.sys_verifycode.sendVerifyCode.post({ | ||||
|                 const res = await this.$API.sys_verifycode.sendVerifyCode.post({ | ||||
|                     destDevice: this.form[Array.isArray(this.phoneField) ? this.phoneField[1] : this.phoneField], | ||||
|                     type: 'login', | ||||
|                     deviceType: 'mobile', | ||||
|                     verifyCaptchaReq: obj, | ||||
|                 }) | ||||
|                 this.$message.success(this.$t('发送成功')) | ||||
|                 if (res.data?.code) { | ||||
|                     this.$message.success(res.data.code.toString()) | ||||
|                 } | ||||
|                 this.waitSecs = 60 | ||||
|                 const t = setInterval(() => { | ||||
|                     this.waitSecs -= 1 | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| <template> | ||||
|     <template v-for="(item, i) in options" :key="i"> | ||||
|         <div v-if="tool.getNestedProperty(data, this.prop) === item.value"> | ||||
|         <div v-if="this.$TOOL.getNestedProperty(data, this.prop)?.toLowerCase() === item.value?.toLowerCase()"> | ||||
|             <sc-status-indicator | ||||
|                 :pulse="item.pulse" | ||||
|                 :style="item.type ? '' : `background: #${Math.abs(this.$TOOL.crypto.hashCode(item.value)).toString(16).substring(0, 6)}`" | ||||
| @@ -9,11 +9,8 @@ | ||||
|             <slot :data="data" :text="item.text"></slot> | ||||
|         </div> | ||||
|     </template> | ||||
|     <slot :data="data" name="info"></slot> | ||||
| </template> | ||||
| <script> | ||||
| import tool from '@/utils/tool' | ||||
|  | ||||
| export default { | ||||
|     emits: [], | ||||
|     props: { | ||||
| @@ -27,11 +24,7 @@ export default { | ||||
|     mounted() {}, | ||||
|     created() {}, | ||||
|     components: {}, | ||||
|     computed: { | ||||
|         tool() { | ||||
|             return tool | ||||
|         }, | ||||
|     }, | ||||
|     computed: {}, | ||||
|     methods: {}, | ||||
| } | ||||
| </script> | ||||
| @@ -66,7 +66,7 @@ | ||||
|                         <el-button @click="reset" icon="el-icon-refresh-left">{{ $t('重置') }}</el-button> | ||||
|                     </template> | ||||
|                     <v-ace-editor | ||||
|                         :theme="this.$TOOL.data.get('APP_DARK') ? 'github_dark' : 'github'" | ||||
|                         :theme="this.$TOOL.data.get('APP_SET_DARK') || this.$CONFIG.APP_SET_DARK ? 'github_dark' : 'github'" | ||||
|                         :value="vkbeautify().json(vue.query, 2)" | ||||
|                         lang="json" | ||||
|                         style="height: 20rem; width: 100%" /> | ||||
| @@ -323,6 +323,7 @@ export default { | ||||
|             casLoaded: false, | ||||
|             keepKeywords: null, | ||||
|             keepCreatedTime: null, | ||||
|             keepHttpStatusCode: null, | ||||
|             form: { | ||||
|                 root: {}, | ||||
|                 filter: {}, | ||||
| @@ -404,6 +405,9 @@ export default { | ||||
|             if (this.keepCreatedTime) { | ||||
|                 this.form.dy.createdTime = this.keepCreatedTime | ||||
|             } | ||||
|             if (this.keepHttpStatusCode) { | ||||
|                 this.form.dy.httpStatusCode = this.keepHttpStatusCode | ||||
|             } | ||||
|             this.$emit('reset') | ||||
|             this.search() | ||||
|         }, | ||||
|   | ||||
| @@ -25,7 +25,7 @@ export default { | ||||
|             const contents = [] | ||||
|             const msg = h('p', { style: 'width:230px;display:flex;justify-content:space-between' }, [ | ||||
|                 h('span', {}, this.$t('即将开始更新……')), | ||||
|                 h('a', { style: 'color:#409eff', href: 'javascript:window.location.reload()' }, this.$t('立即更新')), | ||||
|                 h('a', { style: 'color:#21A675', href: 'javascript:window.location.reload()' }, this.$t('立即更新')), | ||||
|             ]) | ||||
|             const task = h('p', { style: 'font-weight:bold' }, version) | ||||
|             const progress = h( | ||||
| @@ -37,7 +37,7 @@ export default { | ||||
|                     style: { | ||||
|                         width: '230px', | ||||
|                         height: '6px', | ||||
|                         'background-color': '#409eff', | ||||
|                         'background-color': '#21A675', | ||||
|                         'margin-top': '6px', | ||||
|                         'border-radius': '6px', | ||||
|                     }, | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| const T = { | ||||
|     color: ['#409EFF', '#36CE9E', '#f56e6a', '#626c91', '#edb00d', '#909399'], | ||||
|     color: ['#21A675', '#36CE9E', '#f56e6a', '#626c91', '#edb00d', '#909399'], | ||||
|     grid: { | ||||
|         left: '3%', | ||||
|         right: '3%', | ||||
|   | ||||
| @@ -8,15 +8,13 @@ | ||||
|             </el-tag> | ||||
|         </el-table-column> | ||||
|         <el-table-column :label="$t('列名')" prop="label"> | ||||
|             <template #default="scope"> | ||||
|                 <el-tag :effect="scope.row.hide ? 'light' : 'dark'" :type="scope.row.hide ? 'info' : ''" disable-transitions round | ||||
|                     >{{ scope.row.label }} | ||||
|                 </el-tag> | ||||
|             <template #default="{ row }"> | ||||
|                 <el-tag :effect="row.hide ? 'light' : 'dark'" :type="row.hide ? 'info' : ''" disable-transitions round>{{ row.label }} </el-tag> | ||||
|             </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column :label="$t('显示')" prop="hide" width="60"> | ||||
|             <template #default="scope"> | ||||
|                 <el-switch v-model="scope.row.hide" :active-value="false" :inactive-value="true" size="small" /> | ||||
|             <template #default="{ row }"> | ||||
|                 <el-switch v-model="row.hide" :active-value="false" :inactive-value="true" size="small" /> | ||||
|             </template> | ||||
|         </el-table-column> | ||||
|     </el-table> | ||||
|   | ||||
| @@ -440,7 +440,7 @@ export default { | ||||
| } | ||||
|  | ||||
| .sc-file-select__item__file .item-file.item-file-doc { | ||||
|     color: #409eff; | ||||
|     color: #21a675; | ||||
| } | ||||
|  | ||||
| .sc-file-select__item__upload { | ||||
|   | ||||
| @@ -125,7 +125,7 @@ export default { | ||||
|  | ||||
| .sc-filter-my-list li:hover { | ||||
|     background: #ecf5ff; | ||||
|     color: #409eff; | ||||
|     color: #21a675; | ||||
| } | ||||
|  | ||||
| .sc-filter-my-list li label { | ||||
|   | ||||
| @@ -53,7 +53,7 @@ export default { | ||||
| .sc-page-header__icon span { | ||||
|     width: 2.5rem; | ||||
|     height: 2.5rem; | ||||
|     background: #409eff; | ||||
|     background: #21a675; | ||||
|     border-radius: 40%; | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|   | ||||
| @@ -76,6 +76,7 @@ export default { | ||||
| } | ||||
|  | ||||
| .sc-statistic-content-value { | ||||
|     font-family: 'Lucida Console', 'Microsoft YaHei', monospace; | ||||
|     font-weight: bold; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -43,11 +43,11 @@ export default { | ||||
|     files: { | ||||
|         doc: { | ||||
|             icon: 'sc-icon-file-word-2-fill', | ||||
|             color: '#409eff', | ||||
|             color: '#21A675', | ||||
|         }, | ||||
|         docx: { | ||||
|             icon: 'sc-icon-file-word-2-fill', | ||||
|             color: '#409eff', | ||||
|             color: '#21A675', | ||||
|         }, | ||||
|         xls: { | ||||
|             icon: 'sc-icon-file-excel-2-fill', | ||||
|   | ||||
| @@ -10,57 +10,51 @@ const DEFAULT_CONFIG = { | ||||
|     //首页地址 | ||||
|     DASHBOARD_URL: '/home', | ||||
|  | ||||
|     //版本号 | ||||
|     APP_VER: '1.0.0', | ||||
|  | ||||
|     //内核版本号 | ||||
|     CORE_VER: '1.6.9', | ||||
|  | ||||
|     //接口地址 | ||||
|     API_URL: '', | ||||
|  | ||||
|     //请求超时 | ||||
|     TIMEOUT: 10000, | ||||
|  | ||||
|     //TokenName | ||||
|     TOKEN_NAME: 'Authorization', | ||||
|  | ||||
|     //Token前缀,注意最后有个空格,如不需要需设置空字符串 | ||||
|     TOKEN_PREFIX: 'Bearer ', | ||||
|  | ||||
|     //追加其他头 | ||||
|     HEADERS: {}, | ||||
|  | ||||
|     //请求是否开启缓存 | ||||
|     REQUEST_CACHE: false, | ||||
|  | ||||
|     //布局 默认:default | 通栏:header | 经典:menu | 功能坞:dock | ||||
|     //dock将关闭标签和面包屑栏 | ||||
|     LAYOUT: 'menu', | ||||
|  | ||||
|     //菜单是否折叠 | ||||
|     MENU_IS_COLLAPSE: false, | ||||
|  | ||||
|     //菜单是否启用手风琴效果 | ||||
|     MENU_UNIQUE_OPENED: false, | ||||
|  | ||||
|     //是否开启多标签 | ||||
|     LAYOUT_TAGS: true, | ||||
|  | ||||
|     //语言 | ||||
|     LANG: 'zh-cn', | ||||
|  | ||||
|     //主题颜色 | ||||
|     COLOR: '#21A675', | ||||
|  | ||||
|     //是否加密localStorage, 为空不加密,可填写AES(模式ECB,移位Pkcs7)加密 | ||||
|     LS_ENCRYPTION: '', | ||||
|  | ||||
|     //localStorageAES加密秘钥,位数建议填写8的倍数 | ||||
|     LS_ENCRYPTION_key: '2XNN4K8LC0ELVWN4', | ||||
|  | ||||
|     //控制台首页默认布局 | ||||
|     DEFAULT_GRID: { | ||||
|     //布局 默认:default | 通栏:header | 经典:menu | 功能坞:dock | ||||
|     //dock将关闭标签和面包屑栏 | ||||
|     APP_SET_LAYOUT: 'menu', | ||||
|  | ||||
|     //菜单是否折叠 | ||||
|     APP_SET_MENU_IS_COLLAPSE: false, | ||||
|  | ||||
|     //菜单是否启用手风琴效果 | ||||
|     APP_SET_MENU_UNIQUE_OPENED: false, | ||||
|  | ||||
|     //是否开启多标签 | ||||
|     APP_SET_MULTI_TAGS: true, | ||||
|  | ||||
|     //语言 | ||||
|     APP_SET_LANG: 'zh-cn', | ||||
|  | ||||
|     //自动退出 | ||||
|     APP_SET_AUTO_EXIT: 0, | ||||
|  | ||||
|     //深色模式 | ||||
|     APP_SET_DARK: false, | ||||
|  | ||||
|     //主题颜色 | ||||
|     APP_SET_COLOR: '#21A675', | ||||
|  | ||||
|     //控制台首页布局 | ||||
|     APP_SET_HOME_GRID: { | ||||
|         //默认分栏数量和宽度 例如 [24] [18,6] [8,8,8] [6,12,6] | ||||
|         layout: [8, 8, 8, 12, 12, 12, 12], | ||||
|         //小组件分布,com取值:views/home/components 文件名 | ||||
|   | ||||
| @@ -3,21 +3,13 @@ export default { | ||||
|         { | ||||
|             icon: 'el-icon-view', | ||||
|             click: async (row, vue) => { | ||||
|                 vue.loading = true | ||||
|                 vue.dialog.save = true | ||||
|                 await vue.$nextTick() | ||||
|                 await vue.$refs.saveDialog.open('view', row) | ||||
|                 vue.loading = false | ||||
|                 vue.dialog.save = { row, mode: 'view' } | ||||
|             }, | ||||
|         }, | ||||
|         { | ||||
|             icon: 'el-icon-edit', | ||||
|             click: async (row, vue) => { | ||||
|                 vue.loading = true | ||||
|                 vue.dialog.save = true | ||||
|                 await vue.$nextTick() | ||||
|                 await vue.$refs.saveDialog.open('edit', row) | ||||
|                 vue.loading = false | ||||
|                 vue.dialog.save = { row, mode: 'edit' } | ||||
|             }, | ||||
|         }, | ||||
|     ], | ||||
|   | ||||
| @@ -46,7 +46,6 @@ import scWaterMark from '@/components/scWaterMark' | ||||
|  | ||||
| // net-admin组件 | ||||
| import naArea from '@/components/naArea/index.vue' | ||||
| import naButtonAdd from '@/components/naButtonAdd/index.vue' | ||||
| import naButtonBulkDel from '@/components/naButtonBulkDel/index.vue' | ||||
| import naColAvatar from '@/components/naColAvatar' | ||||
| import naColId from '@/components/naColId/index.vue' | ||||
| @@ -87,7 +86,6 @@ export default { | ||||
|  | ||||
|         // net-admin组件 | ||||
|         app.component('naArea', naArea) | ||||
|         app.component('naButtonAdd', naButtonAdd) | ||||
|         app.component('naButtonBulkDel', naButtonBulkDel) | ||||
|         app.component('naColAvatar', naColAvatar) | ||||
|         app.component('naColId', naColId) | ||||
|   | ||||
| @@ -17,7 +17,7 @@ | ||||
|                     <el-menu | ||||
|                         :default-active="$route.meta.active || $route.fullPath" | ||||
|                         @select="select" | ||||
|                         active-text-color="#409EFF" | ||||
|                         active-text-color="#21A675" | ||||
|                         background-color="#424c50" | ||||
|                         router | ||||
|                         text-color="#fff"> | ||||
|   | ||||
| @@ -45,27 +45,25 @@ | ||||
|             <el-button @click="refresh" circle icon="el-icon-refresh"></el-button> | ||||
|         </el-footer> | ||||
|     </el-container> | ||||
|     <save-dialog v-if="dialog.save" @closed="dialog.save = false" ref="saveDialog"></save-dialog> | ||||
|  | ||||
|     <save-dialog v-if="dialog.save" @closed="dialog.save = null" @mounted="$refs.saveDialog.open(dialog.save)" ref="saveDialog"></save-dialog> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import saveDialog from '@/views/sys/job/save.vue' | ||||
| import { defineAsyncComponent } from 'vue' | ||||
| const saveDialog = defineAsyncComponent(() => import('@/views/sys/job/all/save.vue')) | ||||
| export default { | ||||
|     components: { | ||||
|         saveDialog, | ||||
|     }, | ||||
|     data() { | ||||
|         return { | ||||
|             dialog: { | ||||
|                 save: false, | ||||
|             }, | ||||
|             dialog: {}, | ||||
|             loading: false, | ||||
|             jobs: [], | ||||
|         } | ||||
|     }, | ||||
|     mounted() { | ||||
|         this.getData() | ||||
|     }, | ||||
|     inject: ['reload'], | ||||
|     methods: { | ||||
|         async getData() { | ||||
|             this.loading = true | ||||
| @@ -77,11 +75,14 @@ export default { | ||||
|             this.getData() | ||||
|         }, | ||||
|         async view(job) { | ||||
|             this.dialog.save = true | ||||
|             await this.$nextTick() | ||||
|             await this.$refs.saveDialog.open('view', { id: job.id }) | ||||
|             this.dialog.save = { mode: 'view', row: { id: job.id }, tabId: 'record' } | ||||
|         }, | ||||
|     }, | ||||
|     mounted() { | ||||
|         this.getData() | ||||
|     }, | ||||
|     props: [], | ||||
|     watch: {}, | ||||
| } | ||||
| </script> | ||||
|  | ||||
|   | ||||
| @@ -78,37 +78,31 @@ | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import search from './search.vue' | ||||
| import tasks from './tasks.vue' | ||||
| import message from '@/views/profile/message/components/list.vue' | ||||
| import { defineAsyncComponent } from 'vue' | ||||
| import avatar from '../../utils/avatar' | ||||
|  | ||||
| const search = defineAsyncComponent(() => import('./search.vue')) | ||||
| const tasks = defineAsyncComponent(() => import('./tasks.vue')) | ||||
| const message = defineAsyncComponent(() => import('@/views/profile/message/components/list.vue')) | ||||
| export default { | ||||
|     computed: { | ||||
|         avatar() { | ||||
|             return avatar | ||||
|         }, | ||||
|     }, | ||||
|     components: { | ||||
|         search, | ||||
|         tasks, | ||||
|         message, | ||||
|     }, | ||||
|     watch: { | ||||
|         'config.dark'(val) { | ||||
|             if (val) { | ||||
|                 document.documentElement.classList.add('dark') | ||||
|                 this.$TOOL.data.set('APP_DARK', val) | ||||
|             } else { | ||||
|                 document.documentElement.classList.remove('dark') | ||||
|                 this.$TOOL.data.remove('APP_DARK') | ||||
|             } | ||||
|     computed: { | ||||
|         avatar() { | ||||
|             return avatar | ||||
|         }, | ||||
|     }, | ||||
|     async created() { | ||||
|         this.user = this.$GLOBAL.user | ||||
|         const res = await this.$API.sys_sitemsg.unreadCount.post() | ||||
|         this.unreadCnt = res.data | ||||
|     }, | ||||
|     data() { | ||||
|         return { | ||||
|             config: { | ||||
|                 dark: this.$TOOL.data.get('APP_DARK') || false, | ||||
|                 dark: this.$TOOL.data.get('APP_SET_DARK') || this.$CONFIG.APP_SET_DARK, | ||||
|             }, | ||||
|             user: {}, | ||||
|             userName: '', | ||||
| @@ -119,12 +113,21 @@ export default { | ||||
|             unreadCnt: 0, | ||||
|         } | ||||
|     }, | ||||
|     async created() { | ||||
|         this.user = this.$GLOBAL.user | ||||
|         const res = await this.$API.sys_sitemsg.unreadCount.post() | ||||
|         this.unreadCnt = res.data | ||||
|     }, | ||||
|     methods: { | ||||
|         clearData(fullClear) { | ||||
|             const loading = this.$loading() | ||||
|             this.$TOOL.cookie.clear() | ||||
|             if (fullClear) { | ||||
|                 this.$TOOL.data.clear() | ||||
|             } else { | ||||
|                 this.$TOOL.data.clearAppSet() | ||||
|             } | ||||
|             this.$router.replace({ path: '/guest/login' }) | ||||
|             setTimeout(() => { | ||||
|                 loading.close() | ||||
|                 location.reload() | ||||
|             }, 1000) | ||||
|         }, | ||||
|         configDark() { | ||||
|             this.config.dark = !this.config.dark | ||||
|         }, | ||||
| @@ -133,7 +136,7 @@ export default { | ||||
|             this.msg = false | ||||
|         }, | ||||
|         //个人信息 | ||||
|         handleUser(command) { | ||||
|         async handleUser(command) { | ||||
|             if (command === 'uc') { | ||||
|                 this.$router.push({ path: '/profile/account' }) | ||||
|             } | ||||
| @@ -141,36 +144,22 @@ export default { | ||||
|                 this.$router.push({ path: '/cmd' }) | ||||
|             } | ||||
|             if (command === 'clearCache') { | ||||
|                 this.$confirm(this.$t('清除缓存会将系统初始化,包括登录状态、主题、语言设置等,是否继续?'), this.$t('提示'), { | ||||
|                     type: 'info', | ||||
|                 }) | ||||
|                     .then(() => { | ||||
|                         const loading = this.$loading() | ||||
|                         this.$TOOL.data.clear() | ||||
|                         this.$TOOL.cookie.clear() | ||||
|                         this.$router.replace({ path: '/guest/login' }) | ||||
|                         setTimeout(() => { | ||||
|                             loading.close() | ||||
|                             location.reload() | ||||
|                         }, 1000) | ||||
|                     }) | ||||
|                     .catch(() => { | ||||
|                         //取消 | ||||
|                 try { | ||||
|                     await this.$confirm(this.$t('清除缓存会将系统初始化,包括登录状态、主题、语言设置等,是否继续?'), this.$t('提示'), { | ||||
|                         type: 'info', | ||||
|                     }) | ||||
|                     this.clearData(true) | ||||
|                 } catch {} | ||||
|             } | ||||
|             if (command === 'outLogin') { | ||||
|                 this.$confirm(this.$t('确认是否退出当前用户?'), this.$t('提示'), { | ||||
|                     type: 'warning', | ||||
|                     confirmButtonText: this.$t('退出'), | ||||
|                     confirmButtonClass: 'el-button--danger', | ||||
|                 }) | ||||
|                     .then(() => { | ||||
|                         this.$TOOL.cookie.clear() | ||||
|                         this.$router.replace({ path: '/guest/login' }) | ||||
|                     }) | ||||
|                     .catch(() => { | ||||
|                         //取消退出 | ||||
|                 try { | ||||
|                     await this.$confirm(this.$t('确认是否退出当前用户?'), this.$t('提示'), { | ||||
|                         type: 'warning', | ||||
|                         confirmButtonText: this.$t('退出'), | ||||
|                         confirmButtonClass: 'el-button--danger', | ||||
|                     }) | ||||
|                     this.clearData(false) | ||||
|                 } catch {} | ||||
|             } | ||||
|         }, | ||||
|         //全屏 | ||||
| @@ -190,6 +179,18 @@ export default { | ||||
|             this.tasksVisible = true | ||||
|         }, | ||||
|     }, | ||||
|     props: [], | ||||
|     watch: { | ||||
|         'config.dark'(val) { | ||||
|             if (val) { | ||||
|                 document.documentElement.classList.add('dark') | ||||
|                 this.$TOOL.data.set('APP_SET_DARK', val) | ||||
|             } else { | ||||
|                 document.documentElement.classList.remove('dark') | ||||
|                 this.$TOOL.data.remove('APP_SET_DARK') | ||||
|             } | ||||
|         }, | ||||
|     }, | ||||
| } | ||||
| </script> | ||||
|  | ||||
|   | ||||
| @@ -29,7 +29,7 @@ | ||||
|                 </div> | ||||
|                 <div class="adminui-side-scroll"> | ||||
|                     <el-scrollbar> | ||||
|                         <el-menu :collapse="menuIsCollapse" :default-active="active" :unique-opened="$CONFIG.MENU_UNIQUE_OPENED" router> | ||||
|                         <el-menu :collapse="menuIsCollapse" :default-active="active" :unique-opened="$CONFIG.APP_SET_MENU_UNIQUE_OPENED" router> | ||||
|                             <NavMenu :navMenus="nextMenu"></NavMenu> | ||||
|                         </el-menu> | ||||
|                     </el-scrollbar> | ||||
| @@ -74,7 +74,7 @@ | ||||
|             <div v-if="!ismobile" :class="menuIsCollapse ? 'aminui-side isCollapse' : 'aminui-side'"> | ||||
|                 <div class="adminui-side-scroll"> | ||||
|                     <el-scrollbar> | ||||
|                         <el-menu :collapse="menuIsCollapse" :default-active="active" :unique-opened="$CONFIG.MENU_UNIQUE_OPENED" router> | ||||
|                         <el-menu :collapse="menuIsCollapse" :default-active="active" :unique-opened="$CONFIG.APP_SET_MENU_UNIQUE_OPENED" router> | ||||
|                             <NavMenu :navMenus="menu"></NavMenu> | ||||
|                         </el-menu> | ||||
|                     </el-scrollbar> | ||||
| @@ -172,7 +172,7 @@ | ||||
|                 </div> | ||||
|                 <div class="adminui-side-scroll"> | ||||
|                     <el-scrollbar> | ||||
|                         <el-menu :collapse="menuIsCollapse" :default-active="active" :unique-opened="$CONFIG.MENU_UNIQUE_OPENED" router> | ||||
|                         <el-menu :collapse="menuIsCollapse" :default-active="active" :unique-opened="$CONFIG.APP_SET_MENU_UNIQUE_OPENED" router> | ||||
|                             <NavMenu :navMenus="nextMenu"></NavMenu> | ||||
|                         </el-menu> | ||||
|                     </el-scrollbar> | ||||
|   | ||||
| @@ -2,7 +2,7 @@ export default { | ||||
|     render() {}, | ||||
|     data() { | ||||
|         return { | ||||
|             logoutCount: this.$TOOL.data.get('AUTO_EXIT'), | ||||
|             logoutCount: this.$TOOL.data.get('APP_SET_AUTO_EXIT') || this.$CONFIG.APP_SET_AUTO_EXIT, | ||||
|         } | ||||
|     }, | ||||
|     mounted() { | ||||
|   | ||||
| @@ -19,7 +19,7 @@ const messages = { | ||||
| } | ||||
|  | ||||
| const i18n = createI18n({ | ||||
|     locale: tool.data.get('APP_LANG') || sysConfig.LANG, | ||||
|     locale: tool.data.get('APP_SET_LANG') || sysConfig.APP_SET_LANG, | ||||
|     fallbackLocale: 'zh-cn', | ||||
|     globalInjection: true, | ||||
|     messages, | ||||
|   | ||||
| @@ -74,7 +74,7 @@ export default { | ||||
|     启用状态: 'Enabled status', | ||||
|     响应状态码: 'Response status code', | ||||
|     响应码: 'Response code', | ||||
|     唯一编码: 'Unique code', | ||||
|     唯一编码: 'Unique ID', | ||||
|     图标名称: 'Icon name', | ||||
|     图标选择器: 'Icon selector', | ||||
|     地区: 'Region', | ||||
| @@ -448,4 +448,28 @@ export default { | ||||
|     返回首页: 'Return to homepage', | ||||
|     重新登录: 'Re-login', | ||||
|     返回上一页: 'Return to previous page', | ||||
|     批量操作: 'Batch operation', | ||||
|     启用用户: 'Enable user', | ||||
|     禁用用户: 'Disable user', | ||||
|     '确定要 {operator} 选中的 {count} 项吗?': 'Are you sure you want to {operator} the selected {count} items?', | ||||
|     '操作成功 {count}/{total} 项': '{count}/{total} items operation successful', | ||||
|     启用角色: 'Enable role', | ||||
|     禁用角色: 'Disable role', | ||||
|     启用部门: 'Enable department', | ||||
|     禁用部门: 'Disable department', | ||||
|     启用配置: 'Enable configuration', | ||||
|     禁用配置: 'Disable configuration', | ||||
|     启用作业: 'Enable job', | ||||
|     禁用作业: 'Disable job', | ||||
|     重置为默认值: 'Reset to default value', | ||||
|     '确定将当前主题设置恢复默认值吗?': 'Are you sure you want to reset the current theme settings to default?', | ||||
|     '确定将当前设置恢复默认值吗?': 'Are you sure you want to reset the current settings to default?', | ||||
|     作业信息: 'Job information', | ||||
|     查看作业记录: 'View job records', | ||||
|     异常作业: 'Abnormal jobs', | ||||
|     所有作业: 'All jobs', | ||||
|     用户列表: 'User list', | ||||
|     是: 'Yes', | ||||
|     否: 'No', | ||||
|     手机: 'Mobile', | ||||
| } | ||||
| @@ -447,4 +447,27 @@ export default { | ||||
|     返回首页: '返回首页', | ||||
|     重新登录: '重新登录', | ||||
|     返回上一页: '返回上一页', | ||||
|     批量操作: '批量操作', | ||||
|     启用用户: '启用用户', | ||||
|     禁用用户: '禁用用户', | ||||
|     '确定要 {operator} 选中的 {count} 项吗?': '确定要 {operator} 选中的 {count} 项吗?', | ||||
|     '操作成功 {count}/{total} 项': '操作成功 {count}/{total} 项', | ||||
|     启用角色: '启用角色', | ||||
|     禁用角色: '禁用角色', | ||||
|     启用部门: '启用部门', | ||||
|     禁用部门: '禁用部门', | ||||
|     启用配置: '启用配置', | ||||
|     禁用配置: '禁用配置', | ||||
|     启用作业: '启用作业', | ||||
|     禁用作业: '禁用作业', | ||||
|     '确定将当前主题设置恢复默认值吗?': '确定将当前主题设置恢复默认值吗?', | ||||
|     '确定将当前设置恢复默认值吗?': '确定将当前设置恢复默认值吗?', | ||||
|     作业信息: '作业信息', | ||||
|     查看作业记录: '查看作业记录', | ||||
|     异常作业: '异常作业', | ||||
|     所有作业: '所有作业', | ||||
|     用户列表: '用户列表', | ||||
|     是: '是', | ||||
|     否: '否', | ||||
|     手机: '手机', | ||||
| } | ||||
| @@ -5,11 +5,11 @@ export default { | ||||
|         //移动端布局 | ||||
|         ismobile: false, | ||||
|         //布局 | ||||
|         layout: config.LAYOUT, | ||||
|         layout: config.APP_SET_LAYOUT, | ||||
|         //菜单是否折叠 toggle | ||||
|         menuIsCollapse: config.MENU_IS_COLLAPSE, | ||||
|         menuIsCollapse: config.APP_SET_MENU_IS_COLLAPSE, | ||||
|         //多标签栏 | ||||
|         layoutTags: config.LAYOUT_TAGS, | ||||
|         layoutTags: config.APP_SET_MULTI_TAGS, | ||||
|         //主题 | ||||
|         theme: config.THEME, | ||||
|     }, | ||||
|   | ||||
| @@ -6,7 +6,7 @@ html { | ||||
|     height: 100%; | ||||
|     background-color: #f6f8f9; | ||||
|     font-size: var(--el-font-size-base); | ||||
|     font-family: 'Arial', 'Microsoft YaHei', 'monospace'; | ||||
|     font-family: 'Microsoft YaHei', sans-serif; | ||||
| } | ||||
|  | ||||
| a { | ||||
| @@ -92,7 +92,7 @@ textarea { | ||||
|     bottom: 10rem; | ||||
|     right: 0; | ||||
|     z-index: 100; | ||||
|     background: #409eff; | ||||
|     background: #21a675; | ||||
|     display: flex; | ||||
|     flex-direction: column; | ||||
|     align-items: center; | ||||
| @@ -235,7 +235,7 @@ textarea { | ||||
| } | ||||
|  | ||||
| .aminui-side-split li.active { | ||||
|     background: #409eff; | ||||
|     background: #21a675; | ||||
| } | ||||
|  | ||||
| .adminui-side-split-scroll::-webkit-scrollbar-thumb { | ||||
| @@ -410,7 +410,7 @@ textarea { | ||||
| } | ||||
|  | ||||
| .adminui-tags li.active { | ||||
|     background: #409eff; | ||||
|     background: #21a675; | ||||
| } | ||||
|  | ||||
| .adminui-tags li.active a { | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* 覆盖element-plus样式 */ | ||||
|  | ||||
| :root { | ||||
|     --el-color-primary: #409eff; | ||||
|     --el-color-primary: #21a675; | ||||
|     --el-color-primary-light-1: #53a7ff; | ||||
|     --el-color-primary-light-2: #66b1ff; | ||||
|     --el-color-primary-light-3: #79bbff; | ||||
| @@ -44,6 +44,7 @@ | ||||
|  | ||||
| .el-date-editor { | ||||
|     --el-date-editor-daterange-width: 20rem; | ||||
|     --el-date-editor-datetimerange-width: 30rem; | ||||
| } | ||||
|  | ||||
| .el-menu { | ||||
| @@ -167,7 +168,7 @@ | ||||
|  | ||||
| .el-table { | ||||
|     td { | ||||
|         font-family: 'Lucida Console', 'Microsoft YaHei', 'monospace'; | ||||
|         font-family: 'Lucida Console', 'Microsoft YaHei', monospace; | ||||
|     } | ||||
|  | ||||
|     .el-link:after { | ||||
|   | ||||
| @@ -26,7 +26,6 @@ export default { | ||||
|         text.setAttribute('text-anchor', 'middle') | ||||
|         text.setAttribute('font-size', '16') | ||||
|         text.setAttribute('font-weight', '900') | ||||
|         text.setAttribute('font-family', 'monospace') | ||||
|  | ||||
|         // IE/Edge don't support alignment-baseline | ||||
|         // @see https://msdn.microsoft.com/en-us/library/gg558060(v=vs.85).aspx | ||||
|   | ||||
| @@ -12,7 +12,35 @@ const tool = {} | ||||
|  | ||||
| /* localStorage */ | ||||
| tool.data = { | ||||
|     set(key, data, datetime = 0) { | ||||
|     configJson: null, | ||||
|     async uploadConfig() { | ||||
|         try { | ||||
|             const json = JSON.stringify(Object.entries(localStorage).filter((x) => x[0].indexOf('APP_SET_') === 0)) | ||||
|             if (this.configJson !== json) { | ||||
|                 this.configJson = json | ||||
|                 const userApi = await import('@/api/sys/user') | ||||
|                 await userApi.default.setSessionUserAppConfig.post({ | ||||
|                     appConfig: this.configJson, | ||||
|                 }) | ||||
|             } | ||||
|         } catch {} | ||||
|     }, | ||||
|     clearAppSet() { | ||||
|         Object.entries(localStorage) | ||||
|             .filter((x) => x[0].indexOf('APP_SET_') === 0) | ||||
|             .map((x) => localStorage.removeItem(x[0])) | ||||
|     }, | ||||
|     async downloadConfig() { | ||||
|         try { | ||||
|             const userApi = await import('@/api/sys/user') | ||||
|             const res = await userApi.default.getSessionUserAppConfig.post({}) | ||||
|             this.clearAppSet() | ||||
|             for (const item of JSON.parse(res.data.appConfig)) { | ||||
|                 localStorage.setItem(item[0], item[1]) | ||||
|             } | ||||
|         } catch {} | ||||
|     }, | ||||
|     async set(key, data, datetime = 0) { | ||||
|         //加密 | ||||
|         if (sysConfig.LS_ENCRYPTION === 'AES') { | ||||
|             data = tool.crypto.AES.encrypt(JSON.stringify(data), sysConfig.LS_ENCRYPTION_key) | ||||
| @@ -21,7 +49,9 @@ tool.data = { | ||||
|             content: data, | ||||
|             datetime: parseInt(datetime) === 0 ? 0 : new Date().getTime() + parseInt(datetime) * 1000, | ||||
|         } | ||||
|         return localStorage.setItem(key, JSON.stringify(cacheValue)) | ||||
|         const ret = localStorage.setItem(key, JSON.stringify(cacheValue)) | ||||
|         await this.uploadConfig() | ||||
|         return ret | ||||
|     }, | ||||
|     get(key) { | ||||
|         try { | ||||
| @@ -43,11 +73,15 @@ tool.data = { | ||||
|             return null | ||||
|         } | ||||
|     }, | ||||
|     remove(key) { | ||||
|         return localStorage.removeItem(key) | ||||
|     async remove(key) { | ||||
|         const ret = localStorage.removeItem(key) | ||||
|         await this.uploadConfig() | ||||
|         return ret | ||||
|     }, | ||||
|     clear() { | ||||
|         return localStorage.clear() | ||||
|     async clear() { | ||||
|         const ret = localStorage.clear() | ||||
|         await this.uploadConfig() | ||||
|         return ret | ||||
|     }, | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -49,7 +49,7 @@ export default { | ||||
|         }, | ||||
|     }, | ||||
|     mounted() { | ||||
|         this.autoLogin = this.$TOOL.data.get('AUTO_LOGIN') | ||||
|         this.autoLogin = this.$TOOL.data.get('AUTO_LOGIN') || false | ||||
|     }, | ||||
|     methods: { | ||||
|         async login() { | ||||
|   | ||||
| @@ -69,8 +69,8 @@ export default { | ||||
|     data() { | ||||
|         return { | ||||
|             config: { | ||||
|                 lang: this.$TOOL.data.get('APP_LANG') || this.$CONFIG.LANG, | ||||
|                 dark: this.$TOOL.data.get('APP_DARK') || false, | ||||
|                 lang: this.$TOOL.data.get('APP_SET_LANG') || this.$CONFIG.APP_SET_LANG, | ||||
|                 dark: this.$TOOL.data.get('APP_SET_DARK') || this.$CONFIG.APP_SET_DARK, | ||||
|             }, | ||||
|             lang: [ | ||||
|                 { | ||||
| @@ -88,15 +88,15 @@ export default { | ||||
|         'config.dark'(val) { | ||||
|             if (val) { | ||||
|                 document.documentElement.classList.add('dark') | ||||
|                 this.$TOOL.data.set('APP_DARK', val) | ||||
|                 this.$TOOL.data.set('APP_SET_DARK', val) | ||||
|             } else { | ||||
|                 document.documentElement.classList.remove('dark') | ||||
|                 this.$TOOL.data.remove('APP_DARK') | ||||
|                 this.$TOOL.data.remove('APP_SET_DARK') | ||||
|             } | ||||
|         }, | ||||
|         'config.lang'(val) { | ||||
|             this.$i18n.locale = val | ||||
|             this.$TOOL.data.set('APP_LANG', val) | ||||
|             this.$TOOL.data.set('APP_SET_LANG', val) | ||||
|         }, | ||||
|     }, | ||||
|     created: function () { | ||||
| @@ -105,7 +105,7 @@ export default { | ||||
|         this.$TOOL.data.remove('MENU') | ||||
|         this.$TOOL.data.remove('PERMISSIONS') | ||||
|         this.$TOOL.data.remove('DASHBOARD_GRID') | ||||
|         this.$TOOL.data.remove('grid') | ||||
|         this.$TOOL.data.remove('APP_SET_HOME_GRID') | ||||
|         this.$store.commit('clearViewTags') | ||||
|         this.$store.commit('clearKeepLive') | ||||
|         this.$store.commit('clearIframeList') | ||||
|   | ||||
| @@ -1,7 +1,8 @@ | ||||
| <template> | ||||
|     <el-main> | ||||
|         <widgets v-if="dashboard" @on-mounted="onMounted"></widgets> | ||||
|         <work v-else @on-mounted="onMounted"></work> | ||||
|     <div v-if="loading" v-loading="true" style="height: 100%"></div> | ||||
|     <el-main v-else> | ||||
|         <widgets v-if="dashboard"></widgets> | ||||
|         <work v-else></work> | ||||
|     </el-main> | ||||
| </template> | ||||
|  | ||||
| @@ -18,20 +19,19 @@ export default { | ||||
|     }, | ||||
|     data() { | ||||
|         return { | ||||
|             pageLoading: true, | ||||
|             loading: true, | ||||
|             dashboard: false, | ||||
|         } | ||||
|     }, | ||||
|     created() { | ||||
|     async created() { | ||||
|         //下载配置 | ||||
|         await this.$TOOL.data.downloadConfig() | ||||
|         this.dashboard = this.$GLOBAL.user.roles.findIndex((x) => x.displayDashboard) >= 0 | ||||
|         this.loading = false | ||||
|     }, | ||||
|     mounted() {}, | ||||
|     methods: { | ||||
|         onMounted() { | ||||
|             this.pageLoading = false | ||||
|         }, | ||||
|     }, | ||||
|     methods: {}, | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style></style> | ||||
| <style scoped></style> | ||||
| @@ -1,7 +1,7 @@ | ||||
| <template> | ||||
|     <el-card v-loading="loading" class="main" shadow="never"> | ||||
|         <div class="wrap"> | ||||
|             <img alt="" src="@/assets/img/logo.png" /> | ||||
|             <img alt="" src="@/assets/img/logo.png" width="200" /> | ||||
|             <h2>{{ packageJson.name }}</h2> | ||||
|             <p>{{ ver }}</p> | ||||
|             <el-link href="https://github.com/nsnail/NetAdmin" target="_blank">{{ $t('喜欢就点个 Star⭐️ 吧!') }}</el-link> | ||||
|   | ||||
| @@ -146,7 +146,7 @@ export default { | ||||
|             customizing: false, | ||||
|             allComps: allComps, | ||||
|             selectLayout: [], | ||||
|             defaultGrid: this.$CONFIG.DEFAULT_GRID, | ||||
|             defaultGrid: this.$CONFIG.APP_SET_HOME_GRID, | ||||
|             grid: [], | ||||
|         } | ||||
|     }, | ||||
| @@ -225,14 +225,14 @@ export default { | ||||
|         save() { | ||||
|             this.customizing = false | ||||
|             this.$refs.widgets.style.removeProperty('transform') | ||||
|             this.$TOOL.data.set('grid', this.grid) | ||||
|             this.$TOOL.data.set('APP_SET_HOME_GRID', this.grid) | ||||
|         }, | ||||
|         //恢复默认 | ||||
|         backDefault() { | ||||
|             this.customizing = false | ||||
|             this.$refs.widgets.style.removeProperty('transform') | ||||
|             this.grid = JSON.parse(JSON.stringify(this.defaultGrid)) | ||||
|             this.$TOOL.data.remove('grid') | ||||
|             this.$TOOL.data.remove('APP_SET_HOME_GRID') | ||||
|         }, | ||||
|         //关闭 | ||||
|         close() { | ||||
| @@ -241,7 +241,7 @@ export default { | ||||
|             this.loadGrid() | ||||
|         }, | ||||
|         loadGrid() { | ||||
|             this.grid = this.$TOOL.data.get('grid') || JSON.parse(JSON.stringify(this.defaultGrid)) | ||||
|             this.grid = this.$TOOL.data.get('APP_SET_HOME_GRID') || JSON.parse(JSON.stringify(this.defaultGrid)) | ||||
|         }, | ||||
|     }, | ||||
| } | ||||
| @@ -259,6 +259,7 @@ export default { | ||||
|     flex: 1; | ||||
|     overflow: auto; | ||||
|     overflow-x: hidden; | ||||
|     font-family: 'Lucida Console', 'Microsoft YaHei', monospace; | ||||
| } | ||||
|  | ||||
| .widgets-aside { | ||||
|   | ||||
| @@ -84,7 +84,7 @@ export default { | ||||
|         }, | ||||
|         getMods() { | ||||
|             //这里可用改为读取远程数据 | ||||
|             this.myModsName = this.$TOOL.data.get('MY_MODS') || [] | ||||
|             this.myModsName = this.$TOOL.data.get('APP_SET_MY_MODS') || [] | ||||
|             this.filterMenu(this.$GLOBAL.menu) | ||||
|             this.myMods = this.mods.filter((item) => { | ||||
|                 return this.myModsName.includes(item.name) | ||||
| @@ -110,7 +110,7 @@ export default { | ||||
|         }, | ||||
|         saveMods() { | ||||
|             this.$TOOL.data.set( | ||||
|                 'MY_MODS', | ||||
|                 'APP_SET_MY_MODS', | ||||
|                 this.myMods.map((v) => v.name), | ||||
|             ) | ||||
|             this.$message.success(this.$t('设置常用成功')) | ||||
| @@ -178,8 +178,8 @@ export default { | ||||
|  | ||||
| .modItem-add:hover, | ||||
| .modItem-add:hover i { | ||||
|     border-color: #409eff; | ||||
|     color: #409eff !important; | ||||
|     border-color: #21a675; | ||||
|     color: #21a675 !important; | ||||
| } | ||||
|  | ||||
| .setMods { | ||||
|   | ||||
| @@ -34,18 +34,42 @@ | ||||
|         </el-form> | ||||
|     </el-card> | ||||
|  | ||||
|     <set-mobile-dialog v-if="dialog.setMobile" @closed="dialog.setMobile = false" @success="setSuccess" ref="setMobileDialog"></set-mobile-dialog> | ||||
|     <set-password-dialog v-if="dialog.setPassword" @closed="dialog.setPassword = false" ref="setPasswordDialog"></set-password-dialog> | ||||
|     <set-email-dialog v-if="dialog.setEmail" @closed="dialog.setEmail = false" @success="setSuccess" ref="setEmailDialog"></set-email-dialog> | ||||
|     <set-mobile-dialog | ||||
|         v-if="dialog.setMobile" | ||||
|         @closed="dialog.setMobile = null" | ||||
|         @mounted="$refs.setMobileDialog.open(dialog.setMobile)" | ||||
|         @success="setSuccess" | ||||
|         ref="setMobileDialog"></set-mobile-dialog> | ||||
|     <set-password-dialog | ||||
|         v-if="dialog.setPassword" | ||||
|         @closed="dialog.setPassword = null" | ||||
|         @mounted="$refs.setPasswordDialog.open(dialog.setPassword)" | ||||
|         ref="setPasswordDialog"></set-password-dialog> | ||||
|     <set-email-dialog | ||||
|         v-if="dialog.setEmail" | ||||
|         @closed="dialog.setEmail = null" | ||||
|         @mounted="$refs.setEmailDialog.open(dialog.setEmail)" | ||||
|         @success="setSuccess" | ||||
|         ref="setEmailDialog"></set-email-dialog> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import setMobileDialog from '@/views/profile/account/set-mobile.vue' | ||||
| import setPasswordDialog from '@/views/profile/account/set-password.vue' | ||||
| import setEmailDialog from '@/views/profile/account/set-email.vue' | ||||
| import { defineAsyncComponent } from 'vue' | ||||
| const setMobileDialog = defineAsyncComponent(() => import('@/views/profile/account/set-mobile.vue')) | ||||
| const setPasswordDialog = defineAsyncComponent(() => import('@/views/profile/account/set-password.vue')) | ||||
| const setEmailDialog = defineAsyncComponent(() => import('@/views/profile/account/set-email.vue')) | ||||
|  | ||||
| export default { | ||||
|     components: { setMobileDialog, setPasswordDialog, setEmailDialog }, | ||||
|     created() { | ||||
|         this.form = this.$GLOBAL.user | ||||
|     }, | ||||
|     data() { | ||||
|         return { | ||||
|             dialog: {}, | ||||
|             form: {}, | ||||
|         } | ||||
|     }, | ||||
|     methods: { | ||||
|         updateUser(res) { | ||||
|             try { | ||||
| @@ -59,34 +83,17 @@ export default { | ||||
|             this.form = this.$GLOBAL.user = data | ||||
|         }, | ||||
|         async setPasswordClick() { | ||||
|             this.dialog.setPassword = true | ||||
|             await this.$nextTick() | ||||
|             this.$refs.setPasswordDialog.open() | ||||
|             this.dialog.setPassword = {} | ||||
|         }, | ||||
|         async setEmailClick() { | ||||
|             this.dialog.setEmail = true | ||||
|             await this.$nextTick() | ||||
|             this.$refs.setEmailDialog.open() | ||||
|             this.dialog.setEmail = {} | ||||
|         }, | ||||
|         async setMobileClick() { | ||||
|             this.dialog.setMobile = true | ||||
|             await this.$nextTick() | ||||
|             this.$refs.setMobileDialog.open(this.form.mobile ? 'edit' : 'add') | ||||
|             this.dialog.setMobile = { mode: this.form.mobile ? 'edit' : 'add' } | ||||
|         }, | ||||
|     }, | ||||
|  | ||||
|     created() { | ||||
|         this.form = this.$GLOBAL.user | ||||
|     }, | ||||
|     data() { | ||||
|         return { | ||||
|             dialog: { | ||||
|                 setPassword: false, | ||||
|                 setMobile: false, | ||||
|             }, | ||||
|             form: {}, | ||||
|         } | ||||
|     }, | ||||
|     props: [], | ||||
|     watch: {}, | ||||
| } | ||||
| </script> | ||||
|  | ||||
|   | ||||
| @@ -29,7 +29,7 @@ | ||||
|  | ||||
|         <template #footer> | ||||
|             <el-button @click="visible = false">{{ $t('取消') }}</el-button> | ||||
|             <el-button :loading="loading" @click="submit" type="primary">{{ $t('保存') }}</el-button> | ||||
|             <el-button :disabled="loading" :loading="loading" @click="submit" type="primary">{{ $t('保存') }}</el-button> | ||||
|         </template> | ||||
|     </el-dialog> | ||||
| </template> | ||||
| @@ -40,17 +40,42 @@ import phoneConfig from '@/config/naFormPhone' | ||||
| import emailConfig from '@/config/naFormEmail' | ||||
|  | ||||
| export default { | ||||
|     created() {}, | ||||
|     components: { | ||||
|         naFormPhone, | ||||
|     }, | ||||
|     created() {}, | ||||
|  | ||||
|     data() { | ||||
|         return { | ||||
|             //表单数据 | ||||
|             form: { | ||||
|                 verifySmsCodeReq: {}, | ||||
|             }, | ||||
|             loading: false, | ||||
|             //验证规则 | ||||
|             rules: { | ||||
|                 verifySmsCodeReq: { | ||||
|                     destDevice: phoneConfig.mobile(this), | ||||
|                     code: phoneConfig.code(this), | ||||
|                 }, | ||||
|  | ||||
|                 destDevice: [emailConfig.email(this)], | ||||
|                 code: emailConfig.code(), | ||||
|             }, | ||||
|             visible: false, | ||||
|         } | ||||
|     }, | ||||
|     emits: ['success', 'closed', 'mounted'], | ||||
|     methods: { | ||||
|         //显示 | ||||
|         open() { | ||||
|             this.visible = true | ||||
|             return this | ||||
|         }, | ||||
|         //表单提交方法 | ||||
|         async submit() { | ||||
|             if (!(await this.$refs.form.validate().catch(() => {}))) { | ||||
|             const valid = await this.$refs.form.validate().catch(() => {}) | ||||
|             if (!valid) { | ||||
|                 return false | ||||
|             } | ||||
|  | ||||
| @@ -64,23 +89,8 @@ export default { | ||||
|             this.loading = false | ||||
|         }, | ||||
|     }, | ||||
|     data() { | ||||
|         return { | ||||
|             visible: false, | ||||
|             loading: false, | ||||
|             form: { | ||||
|                 verifySmsCodeReq: {}, | ||||
|             }, | ||||
|             rules: { | ||||
|                 verifySmsCodeReq: { | ||||
|                     destDevice: phoneConfig.mobile(this), | ||||
|                     code: phoneConfig.code(this), | ||||
|                 }, | ||||
|  | ||||
|                 destDevice: [emailConfig.email(this)], | ||||
|                 code: emailConfig.code(), | ||||
|             }, | ||||
|         } | ||||
|     mounted() { | ||||
|         this.$emit('mounted') | ||||
|     }, | ||||
| } | ||||
| </script> | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| <template> | ||||
|     <el-dialog v-model="visible" :title="`${titleMap[mode]}:${form?.id ?? '...'}`" :width="800" @closed="$emit('closed')" destroy-on-close> | ||||
|     <el-dialog v-model="visible" :title="`${titleMap[mode]}`" :width="800" @closed="$emit('closed')" destroy-on-close> | ||||
|         <el-form :model="form" :rules="rules" label-position="top" ref="form"> | ||||
|             <el-row class="items-center justify-content-center"> | ||||
|                 <el-col v-if="mode === 'edit'" :lg="10"> | ||||
| @@ -34,7 +34,7 @@ | ||||
|  | ||||
|         <template #footer> | ||||
|             <el-button @click="visible = false">{{ $t('取消') }}</el-button> | ||||
|             <el-button :loading="loading" @click="submit" type="primary">{{ $t('保存') }}</el-button> | ||||
|             <el-button :disabled="loading" :loading="loading" @click="submit" type="primary">{{ $t('保存') }}</el-button> | ||||
|         </template> | ||||
|     </el-dialog> | ||||
| </template> | ||||
| @@ -44,18 +44,50 @@ import naFormPhone from '@/components/naFormPhone/index.vue' | ||||
| import phoneConfig from '@/config/naFormPhone' | ||||
|  | ||||
| export default { | ||||
|     created() {}, | ||||
|     components: { | ||||
|         naFormPhone, | ||||
|     }, | ||||
|     created() {}, | ||||
|  | ||||
|     data() { | ||||
|         return { | ||||
|             //表单数据 | ||||
|             form: { | ||||
|                 newverifySmsCodeReq: {}, | ||||
|                 originverifySmsCodeReq: {}, | ||||
|             }, | ||||
|             loading: false, | ||||
|             mode: 'add', | ||||
|             //验证规则 | ||||
|             rules: { | ||||
|                 originverifySmsCodeReq: { | ||||
|                     destDevice: phoneConfig.mobile(this), | ||||
|                     code: phoneConfig.code(this), | ||||
|                 }, | ||||
|                 newverifySmsCodeReq: { | ||||
|                     destDevice: [phoneConfig.mobile(this), phoneConfig.mobileNoUsed(this, () => this.$GLOBAL.user.id)], | ||||
|                     code: phoneConfig.code(this), | ||||
|                 }, | ||||
|             }, | ||||
|             titleMap: { | ||||
|                 add: this.$t('绑定手机'), | ||||
|                 edit: this.$t('更换手机'), | ||||
|             }, | ||||
|             visible: false, | ||||
|         } | ||||
|     }, | ||||
|     emits: ['success', 'closed', 'mounted'], | ||||
|     methods: { | ||||
|         open(mode = 'add') { | ||||
|             this.mode = mode | ||||
|         //显示 | ||||
|         open(data) { | ||||
|             this.mode = data.mode | ||||
|             this.visible = true | ||||
|             return this | ||||
|         }, | ||||
|         //表单提交方法 | ||||
|         async submit() { | ||||
|             if (!(await this.$refs.form.validate().catch(() => {}))) { | ||||
|             const valid = await this.$refs.form.validate().catch(() => {}) | ||||
|             if (!valid) { | ||||
|                 return false | ||||
|             } | ||||
|  | ||||
| @@ -69,30 +101,8 @@ export default { | ||||
|             this.loading = false | ||||
|         }, | ||||
|     }, | ||||
|     data() { | ||||
|         return { | ||||
|             mode: 'add', | ||||
|             titleMap: { | ||||
|                 add: this.$t('绑定手机'), | ||||
|                 edit: this.$t('更换手机'), | ||||
|             }, | ||||
|             visible: false, | ||||
|             loading: false, | ||||
|             form: { | ||||
|                 newverifySmsCodeReq: {}, | ||||
|                 originverifySmsCodeReq: {}, | ||||
|             }, | ||||
|             rules: { | ||||
|                 originverifySmsCodeReq: { | ||||
|                     destDevice: phoneConfig.mobile(this), | ||||
|                     code: phoneConfig.code(this), | ||||
|                 }, | ||||
|                 newverifySmsCodeReq: { | ||||
|                     destDevice: [phoneConfig.mobile(this), phoneConfig.mobileNoUsed(this, () => this.$GLOBAL.user.id)], | ||||
|                     code: phoneConfig.code(this), | ||||
|                 }, | ||||
|             }, | ||||
|         } | ||||
|     mounted() { | ||||
|         this.$emit('mounted') | ||||
|     }, | ||||
| } | ||||
| </script> | ||||
|   | ||||
| @@ -32,9 +32,10 @@ | ||||
|                     type="password"></el-input> | ||||
|             </el-form-item> | ||||
|         </el-form> | ||||
|  | ||||
|         <template #footer> | ||||
|             <el-button @click="visible = false">{{ $t('取消') }}</el-button> | ||||
|             <el-button :loading="loading" @click="submit" type="primary">{{ $t('保存') }}</el-button> | ||||
|             <el-button :disabled="loading" :loading="loading" @click="submit" type="primary">{{ $t('保存') }}</el-button> | ||||
|         </template> | ||||
|     </el-dialog> | ||||
| </template> | ||||
| @@ -44,43 +45,51 @@ import scPasswordStrength from '@/components/scPasswordStrength/index.vue' | ||||
| import naFormPassword from '@/config/naFormPassword' | ||||
|  | ||||
| export default { | ||||
|     created() {}, | ||||
|     components: { | ||||
|         scPasswordStrength, | ||||
|     }, | ||||
|     created() {}, | ||||
|  | ||||
|     data() { | ||||
|         return { | ||||
|             form: {}, | ||||
|             loading: false, | ||||
|             //验证规则 | ||||
|             rules: { | ||||
|                 oldPassword: naFormPassword.passwordText(this), | ||||
|                 newPassword: naFormPassword.passwordText(this), | ||||
|                 confirmNewPassword: naFormPassword.passwordText2(() => this.form.newPassword), | ||||
|             }, | ||||
|             visible: false, | ||||
|         } | ||||
|     }, | ||||
|     emits: ['success', 'closed', 'mounted'], | ||||
|     methods: { | ||||
|         //显示 | ||||
|         open() { | ||||
|             this.visible = true | ||||
|             return this | ||||
|         }, | ||||
|         //表单提交方法 | ||||
|         async submit() { | ||||
|             if (!(await this.$refs.form.validate().catch(() => {}))) { | ||||
|             const valid = await this.$refs.form.validate().catch(() => {}) | ||||
|             if (!valid) { | ||||
|                 return false | ||||
|             } | ||||
|  | ||||
|             this.loading = true | ||||
|             try { | ||||
|                 const res = await this.$API.sys_user.setPassword.post(this.form) | ||||
|                 this.$emit('success', res.data, this.mode) | ||||
|                 this.$emit('success', res.data) | ||||
|                 this.visible = false | ||||
|                 this.$message.success(this.$t('操作成功')) | ||||
|             } catch { | ||||
|                 // | ||||
|             } | ||||
|             } catch {} | ||||
|             this.loading = false | ||||
|         }, | ||||
|     }, | ||||
|     data() { | ||||
|         return { | ||||
|             visible: false, | ||||
|             loading: false, | ||||
|             form: {}, | ||||
|             rules: { | ||||
|                 oldPassword: naFormPassword.passwordText(this), | ||||
|                 newPassword: naFormPassword.passwordText(this), | ||||
|                 confirmNewPassword: naFormPassword.passwordText2(() => this.form.newPassword), | ||||
|             }, | ||||
|         } | ||||
|     mounted() { | ||||
|         this.$emit('mounted') | ||||
|     }, | ||||
| } | ||||
| </script> | ||||
| </script> | ||||
| <style scoped></style> | ||||
| @@ -1,6 +1,6 @@ | ||||
| <template> | ||||
|     <el-card :header="$t('主题样式')" shadow="never"> | ||||
|         <el-form class="mt-4" label-width="15rem"> | ||||
|         <el-form class="mt-4" label-width="10rem"> | ||||
|             <el-form-item :label="$t('黑夜模式')"> | ||||
|                 <el-switch v-model="config.dark" active-icon="el-icon-moon" inactive-icon="el-icon-sunny" inline-prompt /> | ||||
|             </el-form-item> | ||||
| @@ -24,10 +24,17 @@ | ||||
|             <el-form-item :label="$t('标签栏')"> | ||||
|                 <el-switch v-model="config.layoutTags"></el-switch> | ||||
|             </el-form-item> | ||||
|             <el-form-item> | ||||
|                 <el-popconfirm :title="$t('确定将当前主题设置恢复默认值吗?')" @confirm="themeReset" width="20rem"> | ||||
|                     <template #reference> | ||||
|                         <el-button>{{ $t('重置为默认值') }}</el-button> | ||||
|                     </template> | ||||
|                 </el-popconfirm> | ||||
|             </el-form-item> | ||||
|         </el-form> | ||||
|     </el-card> | ||||
|     <el-card :header="$t('个人设置')" class="mt-4" shadow="never"> | ||||
|         <el-form class="mt-4" label-width="15rem"> | ||||
|         <el-form class="mt-4" label-width="10rem"> | ||||
|             <el-form-item :label="$t('界面语言')"> | ||||
|                 <el-select v-model="config.lang"> | ||||
|                     <el-option :label="$t('简体中文')" value="zh-cn" /> | ||||
| @@ -52,6 +59,13 @@ | ||||
|                     <el-option :label="$t('60分钟')" :value="60" /> | ||||
|                 </el-select> | ||||
|             </el-form-item> | ||||
|             <el-form-item> | ||||
|                 <el-popconfirm :title="$t('确定将当前设置恢复默认值吗?')" @confirm="personalReset" width="20rem"> | ||||
|                     <template #reference> | ||||
|                         <el-button>{{ $t('重置为默认值') }}</el-button> | ||||
|                     </template> | ||||
|                 </el-popconfirm> | ||||
|             </el-form-item> | ||||
|         </el-form> | ||||
|     </el-card> | ||||
| </template> | ||||
| @@ -62,16 +76,16 @@ import colorTool from '@/utils/color' | ||||
| export default { | ||||
|     data() { | ||||
|         return { | ||||
|             colorList: ['#409EFF', '#009688', '#536dfe', '#ff5c93', '#c62f2f', '#fd726d'], | ||||
|             colorList: ['#21A675', '#009688', '#536dfe', '#ff5c93', '#c62f2f', '#fd726d'], | ||||
|             config: { | ||||
|                 layout: this.$TOOL.data.get('LAYOUT') ?? this.$CONFIG.LAYOUT, | ||||
|                 menuIsCollapse: this.$TOOL.data.get('MENU_IS_COLLAPSE') ?? this.$CONFIG.MENU_IS_COLLAPSE, | ||||
|                 menuUniqueOpened: this.$TOOL.data.get('MENU_UNIQUE_OPENED') ?? this.$CONFIG.MENU_UNIQUE_OPENED, | ||||
|                 layoutTags: this.$TOOL.data.get('LAYOUT_TAGS') ?? this.$CONFIG.LAYOUT_TAGS, | ||||
|                 lang: this.$TOOL.data.get('APP_LANG') ?? this.$CONFIG.LANG, | ||||
|                 dark: this.$TOOL.data.get('APP_DARK') ?? false, | ||||
|                 colorPrimary: this.$TOOL.data.get('APP_COLOR') ?? this.$CONFIG.COLOR ?? '#409EFF', | ||||
|                 autoExit: this.$TOOL.data.get('AUTO_EXIT') ?? 0, | ||||
|                 layout: this.$TOOL.data.get('APP_SET_LAYOUT') || this.$CONFIG.APP_SET_LAYOUT, | ||||
|                 menuIsCollapse: this.$TOOL.data.get('APP_SET_MENU_IS_COLLAPSE') || this.$CONFIG.APP_SET_MENU_IS_COLLAPSE, | ||||
|                 menuUniqueOpened: this.$TOOL.data.get('APP_SET_MENU_UNIQUE_OPENED') || this.$CONFIG.APP_SET_MENU_UNIQUE_OPENED, | ||||
|                 layoutTags: this.$TOOL.data.get('APP_SET_MULTI_TAGS') || this.$CONFIG.APP_SET_MULTI_TAGS, | ||||
|                 lang: this.$TOOL.data.get('APP_SET_LANG') || this.$CONFIG.APP_SET_LANG, | ||||
|                 dark: this.$TOOL.data.get('APP_SET_DARK') || this.$CONFIG.APP_SET_DARK, | ||||
|                 colorPrimary: this.$TOOL.data.get('APP_SET_COLOR') || this.$CONFIG.APP_SET_COLOR || '#17ABE3', | ||||
|                 autoExit: this.$TOOL.data.get('APP_SET_AUTO_EXIT') || this.$CONFIG.APP_SET_AUTO_EXIT, | ||||
|             }, | ||||
|         } | ||||
|     }, | ||||
| @@ -79,51 +93,51 @@ export default { | ||||
|         'config.dark'(val) { | ||||
|             if (val) { | ||||
|                 document.documentElement.classList.add('dark') | ||||
|                 this.$TOOL.data.set('APP_DARK', val) | ||||
|                 this.$TOOL.data.set('APP_SET_DARK', val) | ||||
|             } else { | ||||
|                 document.documentElement.classList.remove('dark') | ||||
|                 this.$TOOL.data.remove('APP_DARK') | ||||
|                 this.$TOOL.data.remove('APP_SET_DARK') | ||||
|             } | ||||
|         }, | ||||
|         'config.layout'(val) { | ||||
|             if (val) { | ||||
|                 this.$TOOL.data.set('LAYOUT', val) | ||||
|                 this.$TOOL.data.set('APP_SET_LAYOUT', val) | ||||
|                 this.$store.commit('SET_layout', val) | ||||
|             } else { | ||||
|                 this.$TOOL.data.remove('LAYOUT') | ||||
|                 this.$TOOL.data.remove('APP_SET_LAYOUT') | ||||
|             } | ||||
|         }, | ||||
|         'config.menuIsCollapse'(val) { | ||||
|             if (typeof val === 'boolean') { | ||||
|                 this.$TOOL.data.set('MENU_IS_COLLAPSE', val) | ||||
|                 this.$TOOL.data.set('APP_SET_MENU_IS_COLLAPSE', val) | ||||
|                 this.$store.commit('TOGGLE_menuIsCollapse') | ||||
|             } else { | ||||
|                 this.$TOOL.data.remove('MENU_IS_COLLAPSE') | ||||
|                 this.$TOOL.data.remove('APP_SET_MENU_IS_COLLAPSE') | ||||
|             } | ||||
|         }, | ||||
|         'config.layoutTags'(val) { | ||||
|             if (typeof val === 'boolean') { | ||||
|                 this.$TOOL.data.set('LAYOUT_TAGS', val) | ||||
|                 this.$TOOL.data.set('APP_SET_MULTI_TAGS', val) | ||||
|                 this.$store.commit('TOGGLE_layoutTags') | ||||
|             } else { | ||||
|                 this.$TOOL.data.remove('LAYOUT_TAGS') | ||||
|                 this.$TOOL.data.remove('APP_SET_MULTI_TAGS') | ||||
|             } | ||||
|         }, | ||||
|         'config.menuUniqueOpened'(val) { | ||||
|             if (typeof val === 'boolean') { | ||||
|                 this.$TOOL.data.set('MENU_UNIQUE_OPENED', val) | ||||
|                 this.$TOOL.data.set('APP_SET_MENU_UNIQUE_OPENED', val) | ||||
|             } else { | ||||
|                 this.$TOOL.data.remove('MENU_UNIQUE_OPENED') | ||||
|                 this.$TOOL.data.remove('APP_SET_MENU_UNIQUE_OPENED') | ||||
|             } | ||||
|         }, | ||||
|         'config.lang'(val) { | ||||
|             this.$i18n.locale = val | ||||
|             this.$TOOL.data.set('APP_LANG', val) | ||||
|             this.$TOOL.data.set('APP_SET_LANG', val) | ||||
|         }, | ||||
|         'config.colorPrimary'(val) { | ||||
|             if (!val) { | ||||
|                 val = '#409EFF' | ||||
|                 this.config.colorPrimary = '#409EFF' | ||||
|                 val = '#21A675' | ||||
|                 this.config.colorPrimary = '#21A675' | ||||
|             } | ||||
|             document.documentElement.style.setProperty('--el-color-primary', val) | ||||
|             for (let i = 1; i <= 9; i++) { | ||||
| @@ -132,16 +146,38 @@ export default { | ||||
|             for (let i = 1; i <= 9; i++) { | ||||
|                 document.documentElement.style.setProperty(`--el-color-primary-dark-${i}`, colorTool.darken(val, i / 10)) | ||||
|             } | ||||
|             this.$TOOL.data.set('APP_COLOR', val) | ||||
|             this.$TOOL.data.set('APP_SET_COLOR', val) | ||||
|         }, | ||||
|         'config.autoExit'(val) { | ||||
|             if (val === 0) { | ||||
|                 this.$TOOL.data.remove('AUTO_EXIT') | ||||
|                 this.$TOOL.data.remove('APP_SET_AUTO_EXIT') | ||||
|             } else { | ||||
|                 this.$TOOL.data.set('AUTO_EXIT', val) | ||||
|                 this.$TOOL.data.set('APP_SET_AUTO_EXIT', val) | ||||
|             } | ||||
|         }, | ||||
|     }, | ||||
|     methods: { | ||||
|         async themeReset() { | ||||
|             this.$loading() | ||||
|             this.$message.success(this.$t('操作成功')) | ||||
|             localStorage.removeItem('APP_SET_LAYOUT') | ||||
|             localStorage.removeItem('APP_SET_MENU_IS_COLLAPSE') | ||||
|             localStorage.removeItem('APP_SET_MENU_UNIQUE_OPENED') | ||||
|             localStorage.removeItem('APP_SET_MULTI_TAGS') | ||||
|             localStorage.removeItem('APP_SET_DARK') | ||||
|             localStorage.removeItem('APP_SET_COLOR') | ||||
|             await this.$TOOL.data.uploadConfig() | ||||
|             window.location.reload() | ||||
|         }, | ||||
|         async personalReset() { | ||||
|             this.$loading() | ||||
|             this.$message.success(this.$t('操作成功')) | ||||
|             localStorage.removeItem('APP_SET_AUTO_EXIT') | ||||
|             localStorage.removeItem('APP_SET_LANG') | ||||
|             await this.$TOOL.data.uploadConfig() | ||||
|             window.location.reload() | ||||
|         }, | ||||
|     }, | ||||
| } | ||||
| </script> | ||||
|  | ||||
|   | ||||
							
								
								
									
										31
									
								
								src/frontend/admin/src/views/sys/cache/index.vue
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										31
									
								
								src/frontend/admin/src/views/sys/cache/index.vue
									
									
									
									
										vendored
									
									
								
							| @@ -66,25 +66,22 @@ | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import scStatistic from '@/components/scStatistic' | ||||
| import naInfo from '@/components/naInfo/index.vue' | ||||
| import tool from '@/utils/tool' | ||||
|  | ||||
| export default { | ||||
|     components: { | ||||
|         scStatistic, | ||||
|         naInfo, | ||||
|     }, | ||||
|     data() { | ||||
|         return { | ||||
|             dialog: { | ||||
|                 info: false, | ||||
|             }, | ||||
|             query: { | ||||
|                 filter: { | ||||
|                     dbIndex: 1, | ||||
|                 }, | ||||
|             }, | ||||
|             dialog: { | ||||
|                 info: false, | ||||
|             }, | ||||
|             statistics: { | ||||
|                 keyspaceHits: 0, | ||||
|                 keyspaceMisses: 0, | ||||
| @@ -95,21 +92,11 @@ export default { | ||||
|             }, | ||||
|         } | ||||
|     }, | ||||
|     mounted() { | ||||
|         this.cacheStatistics() | ||||
|     }, | ||||
|     watch: { | ||||
|         'query.filter.dbIndex': { | ||||
|             handler() { | ||||
|                 this.$refs.table.upData() | ||||
|             }, | ||||
|         }, | ||||
|     }, | ||||
|     methods: { | ||||
|         async rowClick(row) { | ||||
|             this.dialog.info = true | ||||
|             await this.$nextTick() | ||||
|             this.$refs.info.open(tool.sortProperties(row), `缓存详情`) | ||||
|             this.$refs.info.open(this.$TOOL.sortProperties(row), this.$t('缓存详情')) | ||||
|         }, | ||||
|         async cacheStatistics() { | ||||
|             try { | ||||
| @@ -122,6 +109,16 @@ export default { | ||||
|             } | ||||
|         }, | ||||
|     }, | ||||
|     mounted() { | ||||
|         this.cacheStatistics() | ||||
|     }, | ||||
|     watch: { | ||||
|         'query.filter.dbIndex': { | ||||
|             handler() { | ||||
|                 this.$refs.table.upData() | ||||
|             }, | ||||
|         }, | ||||
|     }, | ||||
| } | ||||
| </script> | ||||
|  | ||||
|   | ||||
| @@ -13,8 +13,8 @@ | ||||
|                         ], | ||||
|                     }, | ||||
|                 ]" | ||||
|                 :label-width="10" | ||||
|                 @on-change="filterChange" | ||||
|                 label-width="10" | ||||
|                 ref="selectFilter"></sc-select-filter> | ||||
|         </el-header> | ||||
|         <el-header> | ||||
| @@ -27,13 +27,26 @@ | ||||
|                     ref="search" /> | ||||
|             </div> | ||||
|             <div class="right-panel"> | ||||
|                 <na-button-add :vue="this" /> | ||||
|                 <el-button @click="this.dialog.save = { mode: 'add' }" icon="el-icon-plus" type="primary"></el-button> | ||||
|                 <na-button-bulk-del :api="$API.sys_config.bulkDelete" :vue="this" /> | ||||
|                 <el-dropdown v-show="this.selection.length > 0"> | ||||
|                     <el-button type="primary"> | ||||
|                         {{ $t('批量操作') }} | ||||
|                         <el-icon> | ||||
|                             <el-icon-arrow-down /> | ||||
|                         </el-icon> | ||||
|                     </el-button> | ||||
|                     <template #dropdown> | ||||
|                         <el-dropdown-menu> | ||||
|                             <el-dropdown-item @click="setEnabled(true)">{{ $t('启用配置') }}</el-dropdown-item> | ||||
|                             <el-dropdown-item @click="setEnabled(false)">{{ $t('禁用配置') }}</el-dropdown-item> | ||||
|                         </el-dropdown-menu> | ||||
|                     </template> | ||||
|                 </el-dropdown> | ||||
|             </div> | ||||
|         </el-header> | ||||
|         <el-main class="nopadding"> | ||||
|             <sc-table | ||||
|                 v-loading="loading" | ||||
|                 :apiObj="$API.sys_config.pagedQuery" | ||||
|                 :context-menus="['id', 'userRegisterConfirm', 'enabled', 'createdTime']" | ||||
|                 :params="query" | ||||
| @@ -47,22 +60,21 @@ | ||||
|                 row-key="id" | ||||
|                 stripe> | ||||
|                 <el-table-column type="selection" /> | ||||
|                 <el-table-column :label="$t('配置编号')" align="center" prop="id" width="170" /> | ||||
|                 <na-col-id :label="$t('配置编号')" prop="id" width="170" /> | ||||
|                 <el-table-column :label="$t('用户注册')" align="center"> | ||||
|                     <el-table-column :label="$t('默认部门')" align="center" prop="userRegisterDept.name" width="150" /> | ||||
|                     <el-table-column :label="$t('默认角色')" align="center" prop="userRegisterRole.name" width="150" /> | ||||
|                     <el-table-column :label="$t('人工审核')" align="center" prop="userRegisterConfirm" width="120"> | ||||
|                         <template #default="scope"> | ||||
|                             <el-switch v-model="scope.row.userRegisterConfirm" @change="changeSwitch($event, scope.row)"></el-switch> | ||||
|                         <template #default="{ row }"> | ||||
|                             <el-switch v-model="row.userRegisterConfirm" @change="changeSwitch($event, row)"></el-switch> | ||||
|                         </template> | ||||
|                     </el-table-column> | ||||
|                 </el-table-column> | ||||
|                 <el-table-column :label="$t('启用')" align="center" prop="enabled" width="100"> | ||||
|                     <template #default="scope"> | ||||
|                         <el-switch v-model="scope.row.enabled" @change="changeSwitch($event, scope.row)"></el-switch> | ||||
|                     <template #default="{ row }"> | ||||
|                         <el-switch v-model="row.enabled" @change="changeSwitch($event, row)"></el-switch> | ||||
|                     </template> | ||||
|                 </el-table-column> | ||||
|                 <el-table-column :label="$t('创建时间')" align="center" prop="createdTime" width="170" /> | ||||
|                 <na-col-operation | ||||
|                     :buttons=" | ||||
|                         naColOperation.buttons.concat({ | ||||
| @@ -73,25 +85,25 @@ | ||||
|                             type: 'danger', | ||||
|                         }) | ||||
|                     " | ||||
|                     :vue="this" | ||||
|                     width="170" /> | ||||
|                     :vue="this" /> | ||||
|             </sc-table> | ||||
|         </el-main> | ||||
|     </el-container> | ||||
|  | ||||
|     <save-dialog | ||||
|         v-if="dialog.save" | ||||
|         @closed="dialog.save = false" | ||||
|         @success="(data, mode) => table.handleUpdate($refs.table, data, mode)" | ||||
|         @closed="dialog.save = null" | ||||
|         @mounted="$refs.saveDialog.open(dialog.save)" | ||||
|         @success="(data, mode) => $refs.table.upData()" | ||||
|         ref="saveDialog"></save-dialog> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import saveDialog from './save' | ||||
| import naColOperation from '@/config/naColOperation' | ||||
| import { defineAsyncComponent } from 'vue' | ||||
| import table from '@/config/table' | ||||
| import tool from '@/utils/tool' | ||||
| import naColOperation from '@/config/naColOperation' | ||||
|  | ||||
| const saveDialog = defineAsyncComponent(() => import('./save.vue')) | ||||
| export default { | ||||
|     components: { | ||||
|         saveDialog, | ||||
| @@ -104,13 +116,14 @@ export default { | ||||
|             return table | ||||
|         }, | ||||
|     }, | ||||
|     created() {}, | ||||
|     created() { | ||||
|         if (this.keywords) { | ||||
|             this.query.keywords = this.keywords | ||||
|         } | ||||
|     }, | ||||
|     data() { | ||||
|         return { | ||||
|             dialog: { | ||||
|                 info: false, | ||||
|                 save: false, | ||||
|             }, | ||||
|             dialog: {}, | ||||
|             loading: false, | ||||
|             query: { | ||||
|                 dynamicFilter: { | ||||
| @@ -123,6 +136,33 @@ export default { | ||||
|     }, | ||||
|     inject: ['reload'], | ||||
|     methods: { | ||||
|         async setEnabled(enabled) { | ||||
|             let loading | ||||
|             try { | ||||
|                 await this.$confirm( | ||||
|                     this.$t('确定要 {operator} 选中的 {count} 项吗?', { | ||||
|                         operator: enabled ? this.$t('启用') : this.$t('禁用'), | ||||
|                         count: this.selection.length, | ||||
|                     }), | ||||
|                     this.$t('提示'), | ||||
|                     { | ||||
|                         type: 'warning', | ||||
|                     }, | ||||
|                 ) | ||||
|                 loading = this.$loading() | ||||
|                 const res = await Promise.all(this.selection.map((x) => this.$API.sys_config.setEnabled.post(Object.assign(x, { enabled: enabled })))) | ||||
|                 this.$message.success( | ||||
|                     this.$t('操作成功 {count}/{total} 项', { | ||||
|                         count: res.map((x) => x.data ?? 0).reduce((a, b) => a + b, 0), | ||||
|                         total: this.selection.length, | ||||
|                     }), | ||||
|                 ) | ||||
|             } catch { | ||||
|                 // | ||||
|             } | ||||
|             this.$refs.table.refresh() | ||||
|             loading?.close() | ||||
|         }, | ||||
|         async changeSwitch(event, row) { | ||||
|             try { | ||||
|                 await this.$API.sys_config.edit.post(row) | ||||
| @@ -135,10 +175,9 @@ export default { | ||||
|         filterChange(data) { | ||||
|             Object.entries(data).forEach(([key, value]) => { | ||||
|                 this.$refs.search.form.dy[key] = value === 'true' ? true : value === 'false' ? false : value | ||||
|                 this.$refs.search.search() | ||||
|             }) | ||||
|             this.$refs.search.search() | ||||
|         }, | ||||
|  | ||||
|         async rowDel(row) { | ||||
|             try { | ||||
|                 const res = await this.$API.sys_config.delete.post({ id: row.id }) | ||||
| @@ -168,7 +207,14 @@ export default { | ||||
|             this.$refs.table.upData() | ||||
|         }, | ||||
|     }, | ||||
|     mounted() {}, | ||||
|     mounted() { | ||||
|         if (this.keywords) { | ||||
|             this.$refs.search.form.root.keywords = this.keywords | ||||
|             this.$refs.search.keepKeywords = this.keywords | ||||
|         } | ||||
|     }, | ||||
|     props: ['keywords'], | ||||
|     watch: {}, | ||||
| } | ||||
| </script> | ||||
|  | ||||
|   | ||||
| @@ -35,7 +35,7 @@ | ||||
|                 <el-tab-pane v-if="mode === 'view'" :label="$t('原始数据')"> | ||||
|                     <json-viewer | ||||
|                         :expand-depth="5" | ||||
|                         :theme="this.$TOOL.data.get('APP_DARK') ? 'dark' : 'light'" | ||||
|                         :theme="this.$TOOL.data.get('APP_SET_DARK') || this.$CONFIG.APP_SET_DARK ? 'dark' : 'light'" | ||||
|                         :value="form" | ||||
|                         copyable | ||||
|                         expanded | ||||
| @@ -45,7 +45,7 @@ | ||||
|         </div> | ||||
|         <template #footer> | ||||
|             <el-button @click="visible = false">{{ $t('取消') }}</el-button> | ||||
|             <el-button v-if="mode !== 'view'" :loading="loading" @click="submit" type="primary">{{ $t('保存') }}</el-button> | ||||
|             <el-button v-if="mode !== 'view'" :disabled="loading" :loading="loading" @click="submit" type="primary">{{ $t('保存') }}</el-button> | ||||
|         </template> | ||||
|     </sc-dialog> | ||||
| </template> | ||||
| @@ -53,37 +53,37 @@ | ||||
| <script> | ||||
| export default { | ||||
|     components: {}, | ||||
|     emits: ['success', 'closed'], | ||||
|     data() { | ||||
|         return { | ||||
|             //表单数据 | ||||
|             form: { | ||||
|                 enabled: true, | ||||
|             }, | ||||
|             loading: false, | ||||
|             mode: 'add', | ||||
|             //验证规则 | ||||
|             rules: { | ||||
|                 userRegisterDeptId: [{ required: true, message: '请选择默认部门' }], | ||||
|                 userRegisterRoleId: [{ required: true, message: '请选择默认角色' }], | ||||
|             }, | ||||
|             titleMap: { | ||||
|                 add: this.$t('新增配置'), | ||||
|                 edit: this.$t('编辑配置'), | ||||
|                 view: this.$t('查看配置'), | ||||
|             }, | ||||
|             visible: false, | ||||
|             loading: false, | ||||
|             //表单数据 | ||||
|             form: { | ||||
|                 enabled: true, | ||||
|             }, | ||||
|             //验证规则 | ||||
|             rules: { | ||||
|                 userRegisterDeptId: [{ required: true, message: '请选择默认部门' }], | ||||
|                 userRegisterRoleId: [{ required: true, message: '请选择默认角色' }], | ||||
|             }, | ||||
|         } | ||||
|     }, | ||||
|     mounted() {}, | ||||
|     emits: ['success', 'closed', 'mounted'], | ||||
|     methods: { | ||||
|         //显示 | ||||
|         async open(mode = 'add', data) { | ||||
|         async open(data) { | ||||
|             this.visible = true | ||||
|             this.loading = true | ||||
|             this.mode = mode | ||||
|             if (data) { | ||||
|                 Object.assign(this.form, (await this.$API.sys_config.get.post({ id: data.id })).data) | ||||
|             this.mode = data.mode | ||||
|             if (data.row?.id) { | ||||
|                 const res = await this.$API.sys_config.get.post({ id: data.row.id }) | ||||
|                 Object.assign(this.form, res.data) | ||||
|             } | ||||
|             this.loading = false | ||||
|             return this | ||||
| @@ -95,20 +95,21 @@ export default { | ||||
|             if (!valid) { | ||||
|                 return false | ||||
|             } | ||||
|  | ||||
|             this.loading = true | ||||
|  | ||||
|             const method = this.mode === 'add' ? this.$API.sys_config.create : this.$API.sys_config.edit | ||||
|             try { | ||||
|                 const method = this.mode === 'add' ? this.$API.sys_config.create : this.$API.sys_config.edit | ||||
|                 const res = await method.post(this.form) | ||||
|                 this.$emit('success', res.data, this.mode) | ||||
|                 this.visible = false | ||||
|                 this.$message.success(this.$t('操作成功')) | ||||
|             } catch { | ||||
|                 /// | ||||
|             } | ||||
|             } catch {} | ||||
|             this.loading = false | ||||
|         }, | ||||
|     }, | ||||
|     mounted() { | ||||
|         this.$emit('mounted') | ||||
|     }, | ||||
| } | ||||
| </script> | ||||
|  | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user
	 GitHub
						GitHub