Просмотр исходного кода

Merge branch 'next' of https://gitee.com/zuohuaijun/Admin.NET into next

zuohuaijun 3 лет назад
Родитель
Сommit
0caa82eeb7

+ 0 - 4
Admin.NET/Admin.NET.Application/Configuration/JWT.json

@@ -9,11 +9,7 @@
         "ValidateAudience": true, // 是否验证签收方,bool 类型,默认true
         "ValidAudience": "Admin.NET", // 签收方,string 类型
         "ValidateLifetime": true, // 是否验证过期时间,bool 类型,默认true,建议true
-        "ExpiredTime": 10080, // 过期时间,long 类型,单位分钟,默认20分钟
         "ClockSkew": 5, // 过期时间容错值,long 类型,单位秒,默认5秒
         "Algorithm": "HS256" // 加密算法,string 类型,默认 HS256
-    },
-    "RefreshToken": {
-        "ExpiredTime": 20160 // 过期时间单位分钟(一般 refresh_token 的有效时间 > 2 * access_token 的有效时间)
     }
 }

+ 5 - 0
Admin.NET/Admin.NET.Core/Const/CommonConst.cs

@@ -41,6 +41,11 @@ public class CommonConst
     /// </summary>
     public const string SysTokenExpire = "sys_token_expire";
 
+    /// <summary>
+    /// RefreshToken过期时间
+    /// </summary>
+    public const string SysRefreshTokenExpire = "sys_refresh_token_expire";
+
     /// <summary>
     /// 单用户登录
     /// </summary>

+ 37 - 29
Admin.NET/Admin.NET.Core/Logging/DatabaseLoggingWriter.cs

@@ -9,12 +9,14 @@ public class DatabaseLoggingWriter : IDatabaseLoggingWriter
 {
     private readonly SqlSugarRepository<SysLogVis> _sysLogVisRep; // 访问日志
     private readonly SqlSugarRepository<SysLogOp> _sysLogOpRep;   // 操作日志
+    private readonly SysConfigService _sysConfigService; // 参数配置服务
 
     public DatabaseLoggingWriter(SqlSugarRepository<SysLogVis> sysLogVisRep,
-        SqlSugarRepository<SysLogOp> sysLogOpRep)
+        SqlSugarRepository<SysLogOp> sysLogOpRep, SysConfigService sysConfigService)
     {
         _sysLogVisRep = sysLogVisRep;
         _sysLogOpRep = sysLogOpRep;
+        _sysConfigService = sysConfigService;
     }
 
     public async void Write(LogMessage logMsg, bool flush)
@@ -47,7 +49,7 @@ public class DatabaseLoggingWriter : IDatabaseLoggingWriter
 
         if (loggingMonitor.actionName == "userInfo" || loggingMonitor.actionName == "logout")
         {
-            _sysLogVisRep.Insert(new SysLogVis
+            await _sysLogVisRep.InsertAsync(new SysLogVis
             {
                 ControllerName = loggingMonitor.controllerName,
                 ActionName = loggingMonitor.actionTypeName,
@@ -69,34 +71,40 @@ public class DatabaseLoggingWriter : IDatabaseLoggingWriter
         }
         else
         {
-            _sysLogOpRep.Insert(new SysLogOp
+            // 如果启用操作日志
+            var sysOpLogEnabled = await _sysConfigService.GetConfigValue<bool>(CommonConst.SysOpLog);
+            if (sysOpLogEnabled)
             {
-                ControllerName = loggingMonitor.controllerName,
-                ActionName = loggingMonitor.actionTypeName,
-                DisplayTitle = loggingMonitor.displayTitle,
-                Status = loggingMonitor.returnInformation?.httpStatusCode,
-                RemoteIp = remoteIPv4,
-                Location = ipLocation,
-                Longitude = longitude,
-                Latitude = latitude,
-                Browser = loggingMonitor.userAgent,
-                Os = loggingMonitor.osDescription + " " + loggingMonitor.osArchitecture,
-                Elapsed = loggingMonitor.timeOperationElapsedMilliseconds,
-                LogDateTime = logMsg.LogDateTime,
-                Account = account,
-                RealName = realName,
-                HttpMethod = loggingMonitor.httpMethod,
-                RequestUrl = loggingMonitor.requestUrl,
-                RequestParam = (loggingMonitor.parameters == null || loggingMonitor.parameters.Count == 0) ? null : JSON.Serialize(loggingMonitor.parameters[0].value),
-                ReturnResult = loggingMonitor.returnInformation == null ? null : JSON.Serialize(loggingMonitor.returnInformation),
-                EventId = logMsg.EventId.Id,
-                ThreadId = logMsg.ThreadId,
-                TraceId = logMsg.TraceId,
-                Exception = loggingMonitor.exception == null ? null : JSON.Serialize(loggingMonitor.exception),
-                Message = logMsg.Message,
-                CreateUserId = string.IsNullOrWhiteSpace(userId) ? 0 : long.Parse(userId),
-                TenantId = string.IsNullOrWhiteSpace(tenantId) ? 0 : long.Parse(tenantId)
-            });
+                await _sysLogOpRep.InsertAsync(new SysLogOp
+                {
+                    ControllerName = loggingMonitor.controllerName,
+                    ActionName = loggingMonitor.actionTypeName,
+                    DisplayTitle = loggingMonitor.displayTitle,
+                    Status = loggingMonitor.returnInformation?.httpStatusCode,
+                    RemoteIp = remoteIPv4,
+                    Location = ipLocation,
+                    Longitude = longitude,
+                    Latitude = latitude,
+                    Browser = loggingMonitor.userAgent,
+                    Os = loggingMonitor.osDescription + " " + loggingMonitor.osArchitecture,
+                    Elapsed = loggingMonitor.timeOperationElapsedMilliseconds,
+                    LogDateTime = logMsg.LogDateTime,
+                    Account = account,
+                    RealName = realName,
+                    HttpMethod = loggingMonitor.httpMethod,
+                    RequestUrl = loggingMonitor.requestUrl,
+                    RequestParam = (loggingMonitor.parameters == null || loggingMonitor.parameters.Count == 0) ? null : JSON.Serialize(loggingMonitor.parameters[0].value),
+                    ReturnResult = loggingMonitor.returnInformation == null ? null : JSON.Serialize(loggingMonitor.returnInformation),
+                    EventId = logMsg.EventId.Id,
+                    ThreadId = logMsg.ThreadId,
+                    TraceId = logMsg.TraceId,
+                    Exception = loggingMonitor.exception == null ? null : JSON.Serialize(loggingMonitor.exception),
+                    Message = logMsg.Message,
+                    CreateUserId = string.IsNullOrWhiteSpace(userId) ? 0 : long.Parse(userId),
+                    TenantId = string.IsNullOrWhiteSpace(tenantId) ? 0 : long.Parse(tenantId)
+                });
+            }
+
         }
 
         // 若有异常时则发送邮件

+ 14 - 4
Admin.NET/Admin.NET.Core/Logging/ElasticSearchLoggingWriter.cs

@@ -8,16 +8,26 @@ namespace Admin.NET.Core;
 public class ElasticSearchLoggingWriter : IDatabaseLoggingWriter
 {
     private readonly ElasticClient _esClient;
+    private readonly SysConfigService _sysConfigService; // 参数配置服务
 
-    public ElasticSearchLoggingWriter(ElasticClient esClient)
+    public ElasticSearchLoggingWriter(ElasticClient esClient, SysConfigService sysConfigService)
     {
         _esClient = esClient;
+        _sysConfigService = sysConfigService;
     }
 
-    public void Write(LogMessage logMsg, bool flush)
+    public async void Write(LogMessage logMsg, bool flush)
     {
+        // 如果启用操作日志
+        var sysOpLogEnabled = await _sysConfigService.GetConfigValue<bool>(CommonConst.SysOpLog);
+        if (!sysOpLogEnabled) return;
+
         var jsonStr = logMsg.Context.Get("loggingMonitor").ToString();
-        // var loggingMonitor = JSON.Deserialize<dynamic>(jsonStr);
-        _esClient.IndexDocument(jsonStr);
+        var loggingMonitor = JSON.Deserialize<dynamic>(jsonStr);
+
+        // 登录登出日志,不记录
+        if (loggingMonitor.actionName == "userInfo" || loggingMonitor.actionName == "logout") return;
+
+        await _esClient.IndexDocumentAsync(jsonStr);
     }
 }

+ 0 - 12
Admin.NET/Admin.NET.Core/Option/RefreshTokenOptions.cs

@@ -1,12 +0,0 @@
-namespace Admin.NET.Core;
-
-/// <summary>
-/// 刷新Token配置选项
-/// </summary>
-public sealed class RefreshTokenOptions : IConfigurableOptions
-{
-    /// <summary>
-    /// 令牌过期时间(分钟) 默认2天
-    /// </summary>
-    public int ExpiredTime { get; set; }
-}

+ 1 - 0
Admin.NET/Admin.NET.Core/SeedData/SysConfigSeedData.cs

@@ -22,6 +22,7 @@ public class SysConfigSeedData : ISqlSugarEntitySeedData<SysConfig>
             new SysConfig{ Id=1300000000106, Name="登录二次验证", Code="sys_second_ver", Value="True", SysFlag=YesNoEnum.Y, Remark="登录二次验证", OrderNo=6, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
             new SysConfig{ Id=1300000000107, Name="开启图形验证码", Code="sys_captcha", Value="False", SysFlag=YesNoEnum.Y, Remark="开启图形验证码", OrderNo=7, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
             new SysConfig{ Id=1300000000108, Name="开启水印", Code="sys_watermark", Value="True", SysFlag=YesNoEnum.Y, Remark="开启水印", OrderNo=8, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
+            new SysConfig{ Id=1300000000109, Name="RefreshToken过期时间", Code="sys_refresh_token_expire", Value="20160", SysFlag=YesNoEnum.Y, Remark="RefreshToken过期时间,单位分钟(一般 refresh_token 的有效时间 > 2 * access_token 的有效时间)", OrderNo=3, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
         };
     }
 }

+ 21 - 8
Admin.NET/Admin.NET.Core/Service/Auth/SysAuthService.cs

@@ -12,7 +12,6 @@ public class SysAuthService : IDynamicApiController, ITransient
 {
     private readonly UserManager _userManager;
     private readonly SqlSugarRepository<SysUser> _sysUserRep;
-    private readonly RefreshTokenOptions _refreshTokenOptions;
     private readonly IHttpContextAccessor _httpContextAccessor;
     private readonly SysMenuService _sysMenuService;
     private readonly SysOnlineUserService _sysOnlineUserService;
@@ -22,7 +21,6 @@ public class SysAuthService : IDynamicApiController, ITransient
 
     public SysAuthService(UserManager userManager,
         SqlSugarRepository<SysUser> sysUserRep,
-        IOptions<RefreshTokenOptions> refreshTokenOptions,
         IHttpContextAccessor httpContextAccessor,
         SysMenuService sysMenuService,
         SysOnlineUserService sysOnlineUserService,
@@ -33,7 +31,6 @@ public class SysAuthService : IDynamicApiController, ITransient
         _userManager = userManager;
         _sysUserRep = sysUserRep;
         _httpContextAccessor = httpContextAccessor;
-        _refreshTokenOptions = refreshTokenOptions.Value;
         _sysMenuService = sysMenuService;
         _sysOnlineUserService = sysOnlineUserService;
         _sysConfigService = sysConfigService;
@@ -90,6 +87,9 @@ public class SysAuthService : IDynamicApiController, ITransient
         // 单用户登录
         await _sysOnlineUserService.SignleLogin(user.Id);
 
+        var tokenExpire = await _sysConfigService.GetTokenExpire();
+        var refreshTokenExpire = await _sysConfigService.GetRefreshTokenExpire();
+
         // 生成Token令牌
         var accessToken = JWTEncryption.Encrypt(new Dictionary<string, object>
         {
@@ -100,10 +100,10 @@ public class SysAuthService : IDynamicApiController, ITransient
             { ClaimConst.AccountType, user.AccountType },
             { ClaimConst.OrgId, user.OrgId },
             { ClaimConst.OrgName, user.SysOrg?.Name },
-        });
+        }, tokenExpire);
 
         // 生成刷新Token令牌
-        var refreshToken = JWTEncryption.GenerateRefreshToken(accessToken, _refreshTokenOptions.ExpiredTime);
+        var refreshToken = JWTEncryption.GenerateRefreshToken(accessToken, refreshTokenExpire);
 
         // 设置响应报文头
         _httpContextAccessor.HttpContext.SetTokensOfResponseHeaders(accessToken, refreshToken);
@@ -127,7 +127,7 @@ public class SysAuthService : IDynamicApiController, ITransient
     {
         var user = await _sysUserRep.GetFirstAsync(u => u.Id == _userManager.UserId);
         if (user == null)
-            throw Oops.Oh(ErrorCodeEnum.D1011);
+            throw Oops.Oh(ErrorCodeEnum.D1011).StatusCode(401);
 
         // 获取机构
         var org = await _sysUserRep.ChangeRepository<SqlSugarRepository<SysOrg>>().GetFirstAsync(u => u.Id == user.OrgId);
@@ -158,7 +158,8 @@ public class SysAuthService : IDynamicApiController, ITransient
     [DisplayName("获取刷新Token")]
     public string GetRefreshToken(string accessToken)
     {
-        return JWTEncryption.GenerateRefreshToken(accessToken, _refreshTokenOptions.ExpiredTime);
+        var refreshTokenExpire = _sysConfigService.GetRefreshTokenExpire().GetAwaiter().GetResult();
+        return JWTEncryption.GenerateRefreshToken(accessToken, refreshTokenExpire);
     }
 
     /// <summary>
@@ -184,8 +185,20 @@ public class SysAuthService : IDynamicApiController, ITransient
     {
         var secondVerEnabled = await _sysConfigService.GetConfigValue<bool>(CommonConst.SysSecondVer);
         var captchaEnabled = await _sysConfigService.GetConfigValue<bool>(CommonConst.SysCaptcha);
+        return new { SecondVerEnabled = secondVerEnabled, CaptchaEnabled = captchaEnabled };
+    }
+
+    /// <summary>
+    /// 获取用户配置
+    /// </summary>
+    /// <returns></returns>
+    [SuppressMonitor]
+    [DisplayName("获取用户配置")]
+    public async Task<dynamic> GetUserConfig()
+    {
+        //返回用户和通用配置
         var watermarkEnabled = await _sysConfigService.GetConfigValue<bool>(CommonConst.SysWatermark);
-        return new { SecondVerEnabled = secondVerEnabled, CaptchaEnabled = captchaEnabled, WatermarkEnabled = watermarkEnabled };
+        return new { WatermarkEnabled = watermarkEnabled };
     }
 
     /// <summary>

+ 3 - 3
Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenService.cs

@@ -225,7 +225,7 @@ public class SysCodeGenService : IDynamicApiController, ITransient
         // 先删除该表已生成的菜单列表
         var templatePathList = GetTemplatePathList();
         List<string> targetPathList;
-        var zipPath = App.WebHostEnvironment.WebRootPath + $@"\CodeGen\{input.TableName}";
+        var zipPath = Path.Combine(App.WebHostEnvironment.WebRootPath, "CodeGen", input.TableName);
         if (input.GenerateType.StartsWith('1'))
         {
             targetPathList = GetZipPathList(input);
@@ -446,7 +446,7 @@ public class SysCodeGenService : IDynamicApiController, ITransient
     /// <returns></returns>
     private static List<string> GetTemplatePathList(SysCodeGen input)
     {
-        var templatePath = App.WebHostEnvironment.WebRootPath + @"\Template\";
+        var templatePath = Path.Combine(App.WebHostEnvironment.WebRootPath, "Template");
         if (input.GenerateType.Substring(1, 1).Contains('1'))
             return new List<string>()
         {
@@ -530,7 +530,7 @@ public class SysCodeGenService : IDynamicApiController, ITransient
     /// <returns></returns>
     private List<string> GetZipPathList(SysCodeGen input)
     {
-        var zipPath = App.WebHostEnvironment.WebRootPath + $@"\CodeGen\{input.TableName}";
+        var zipPath = Path.Combine(App.WebHostEnvironment.WebRootPath, "CodeGen", input.TableName);
 
         var backendPath = Path.Combine(zipPath, _codeGenOptions.BackendApplicationNamespace, "Service", input.TableName);
         var servicePath = Path.Combine(backendPath, input.TableName + "Service.cs");

+ 32 - 0
Admin.NET/Admin.NET.Core/Service/Config/SysConfigService.cs

@@ -133,4 +133,36 @@ public class SysConfigService : IDynamicApiController, ITransient
     {
         return await _sysConfigRep.AsQueryable().GroupBy(u => u.GroupCode).Select(u => u.GroupCode).ToListAsync();
     }
+
+    /// <summary>
+    /// 获取 Token 过期时间
+    /// </summary>
+    /// <returns></returns>
+    [ApiDescriptionSettings(false)]
+    public async Task<int> GetTokenExpire()
+    {
+        var tokenExpireStr = await GetConfigValue<string>(CommonConst.SysTokenExpire);
+
+        int.TryParse(tokenExpireStr, out var tokenExpire);
+        // 参数不存在或转换失败,设置默认值
+        tokenExpire = tokenExpire == 0 ? 20 : tokenExpire;
+
+        return tokenExpire;
+    }
+
+    /// <summary>
+    /// 获取 RefreshToken 过期时间
+    /// </summary>
+    /// <returns></returns>
+    [ApiDescriptionSettings(false)]
+    public async Task<int> GetRefreshTokenExpire()
+    {
+        var refreshTokenExpireStr = await GetConfigValue<string>(CommonConst.SysRefreshTokenExpire);
+
+        int.TryParse(refreshTokenExpireStr, out var refreshTokenExpire);
+        // 参数不存在或转换失败,设置默认值
+        refreshTokenExpire = refreshTokenExpire == 0 ? 40 : refreshTokenExpire;
+
+        return refreshTokenExpire;
+    }
 }

+ 1 - 1
Admin.NET/Admin.NET.Core/Service/DataBase/SysDatabaseService.cs

@@ -239,7 +239,7 @@ public class SysDatabaseService : IDynamicApiController, ITransient
     /// <returns></returns>
     private static string GetEntityTemplatePath()
     {
-        var templatePath = App.WebHostEnvironment.WebRootPath + @"\Template\";
+        var templatePath = Path.Combine(App.WebHostEnvironment.WebRootPath, "Template");
         return Path.Combine(templatePath, "Entity.cs.vm");
     }
 

+ 1 - 1
Admin.NET/Admin.NET.Core/Util/AdminResultProvider.cs

@@ -91,7 +91,7 @@ public class AdminResultProvider : IUnifyResultProvider
         return new AdminResult<object>
         {
             Code = statusCode,
-            Message = errors is string str ? str : JSON.Serialize(errors),
+            Message = errors is null or string ? (errors + "") : JSON.Serialize(errors),
             Result = data,
             Type = succeeded ? "success" : "error",
             Extras = UnifyContext.Take(),

+ 8 - 3
Admin.NET/Admin.NET.Web.Core/Handlers/JwtHandler.cs

@@ -6,6 +6,7 @@ using Furion.DataEncryption;
 using Microsoft.AspNetCore.Authorization;
 using Microsoft.AspNetCore.Http;
 using System.Threading.Tasks;
+using Microsoft.Extensions.DependencyInjection;
 
 namespace Admin.NET.Web.Core
 {
@@ -18,9 +19,13 @@ namespace Admin.NET.Web.Core
         /// <returns></returns>
         public override async Task HandleAsync(AuthorizationHandlerContext context)
         {
-            if (JWTEncryption.AutoRefreshToken(context, context.GetCurrentHttpContext(),
-                App.GetOptions<JWTSettingsOptions>().ExpiredTime,
-                App.GetOptions<RefreshTokenOptions>().ExpiredTime))
+            // 读取参数
+            var serviceProvider = context.GetCurrentHttpContext().RequestServices;
+            var sysConfigService = serviceProvider.GetService<SysConfigService>();
+            var tokenExpire = await sysConfigService.GetTokenExpire();
+            var refreshTokenExpire = await sysConfigService.GetRefreshTokenExpire();
+
+            if (JWTEncryption.AutoRefreshToken(context, context.GetCurrentHttpContext(), tokenExpire, refreshTokenExpire))
             {
                 await AuthorizeHandleAsync(context);
             }

+ 0 - 1
Admin.NET/Admin.NET.Web.Core/ProjectOptions.cs

@@ -15,7 +15,6 @@ public static class ProjectOptions
     public static IServiceCollection AddProjectOptions(this IServiceCollection services)
     {
         services.AddConfigurableOptions<DbConnectionOptions>();
-        services.AddConfigurableOptions<RefreshTokenOptions>();
         services.AddConfigurableOptions<SnowIdOptions>();
         services.AddConfigurableOptions<CacheOptions>();
         services.AddConfigurableOptions<OSSProviderOptions>();

+ 68 - 0
Web/src/api-services/apis/sys-auth-api.ts

@@ -308,6 +308,42 @@ export const SysAuthApiAxiosParamCreator = function (configuration?: Configurati
                 options: localVarRequestOptions,
             };
         },
+        /**
+         * 
+         * @summary 获取用户配置
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        apiSysAuthUserConfigGet: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/api/sysAuth/userConfig`;
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, 'https://example.com');
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
+            }
+            const localVarRequestOptions :AxiosRequestConfig = { method: 'GET', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+            // authentication Bearer required
+
+            const query = new URLSearchParams(localVarUrlObj.search);
+            for (const key in localVarQueryParameter) {
+                query.set(key, localVarQueryParameter[key]);
+            }
+            for (const key in options.params) {
+                query.set(key, options.params[key]);
+            }
+            localVarUrlObj.search = (new URLSearchParams(query)).toString();
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+
+            return {
+                url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
+                options: localVarRequestOptions,
+            };
+        },
         /**
          * 
          * @summary 获取登录账号
@@ -448,6 +484,19 @@ export const SysAuthApiFp = function(configuration?: Configuration) {
                 return axios.request(axiosRequestArgs);
             };
         },
+        /**
+         * 
+         * @summary 获取用户配置
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async apiSysAuthUserConfigGet(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultObject>>> {
+            const localVarAxiosArgs = await SysAuthApiAxiosParamCreator(configuration).apiSysAuthUserConfigGet(options);
+            return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
+                const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
+                return axios.request(axiosRequestArgs);
+            };
+        },
         /**
          * 
          * @summary 获取登录账号
@@ -537,6 +586,15 @@ export const SysAuthApiFactory = function (configuration?: Configuration, basePa
         async apiSysAuthRefreshTokenAccessTokenGet(accessToken: string, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultString>> {
             return SysAuthApiFp(configuration).apiSysAuthRefreshTokenAccessTokenGet(accessToken, options).then((request) => request(axios, basePath));
         },
+        /**
+         * 
+         * @summary 获取用户配置
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async apiSysAuthUserConfigGet(options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultObject>> {
+            return SysAuthApiFp(configuration).apiSysAuthUserConfigGet(options).then((request) => request(axios, basePath));
+        },
         /**
          * 
          * @summary 获取登录账号
@@ -630,6 +688,16 @@ export class SysAuthApi extends BaseAPI {
     public async apiSysAuthRefreshTokenAccessTokenGet(accessToken: string, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultString>> {
         return SysAuthApiFp(this.configuration).apiSysAuthRefreshTokenAccessTokenGet(accessToken, options).then((request) => request(this.axios, this.basePath));
     }
+    /**
+     * 
+     * @summary 获取用户配置
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof SysAuthApi
+     */
+    public async apiSysAuthUserConfigGet(options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultObject>> {
+        return SysAuthApiFp(this.configuration).apiSysAuthUserConfigGet(options).then((request) => request(this.axios, this.basePath));
+    }
     /**
      * 
      * @summary 获取登录账号

+ 1 - 1
Web/src/api-services/models/add-menu-input.ts

@@ -69,7 +69,7 @@ export interface AddMenuInput {
      */
     type?: MenuTypeEnum;
     /**
-     * 名称
+     * 路由名称
      * @type {string}
      * @memberof AddMenuInput
      */

+ 6 - 0
Web/src/api-services/models/file-output.ts

@@ -59,4 +59,10 @@ export interface FileOutput {
      * @memberof FileOutput
      */
     filePath?: string | null;
+    /**
+     * 文件名称
+     * @type {string}
+     * @memberof FileOutput
+     */
+    fileName?: string | null;
 }

+ 12 - 0
Web/src/api-services/models/send-subscribe-message-input.ts

@@ -36,4 +36,16 @@ export interface SendSubscribeMessageInput {
      * @memberof SendSubscribeMessageInput
      */
     data: { [key: string]: DataItem; };
+    /**
+     * 跳转小程序类型
+     * @type {string}
+     * @memberof SendSubscribeMessageInput
+     */
+    miniprogramState?: string | null;
+    /**
+     * 语言类型
+     * @type {string}
+     * @memberof SendSubscribeMessageInput
+     */
+    language?: string | null;
 }

+ 2 - 2
Web/src/api-services/models/sys-menu.ts

@@ -69,7 +69,7 @@ export interface SysMenu {
      */
     type?: MenuTypeEnum;
     /**
-     * 名称
+     * 路由名称
      * @type {string}
      * @memberof SysMenu
      */
@@ -99,7 +99,7 @@ export interface SysMenu {
      */
     permission?: string | null;
     /**
-     * 标题
+     * 菜单名称
      * @type {string}
      * @memberof SysMenu
      */

+ 1 - 1
Web/src/api-services/models/update-menu-input.ts

@@ -69,7 +69,7 @@ export interface UpdateMenuInput {
      */
     type?: MenuTypeEnum;
     /**
-     * 名称
+     * 路由名称
      * @type {string}
      * @memberof UpdateMenuInput
      */

+ 21 - 3
Web/src/stores/userInfo.ts

@@ -1,5 +1,7 @@
 import { defineStore } from 'pinia';
-import { Session } from '/@/utils/storage';
+import { Local, Session } from '/@/utils/storage';
+import Watermark from '/@/utils/watermark';
+import { useThemeConfig } from '/@/stores/themeConfig';
 
 import { getAPI } from '/@/utils/axios-utils';
 import { SysAuthApi, SysConstApi } from '/@/api-services/api';
@@ -32,11 +34,11 @@ export const useUserInfo = defineStore('userInfo', {
 			}
 		},
 		// 获取当前用户信息
-		async getApiUserInfo() {
+		getApiUserInfo() {
 			return new Promise((resolve) => {
 				getAPI(SysAuthApi)
 					.apiSysAuthUserInfoGet()
-					.then((res: any) => {
+					.then(async (res: any) => {
 						if (res.data.result == null) return;
 						var d = res.data.result;
 						const userInfos = {
@@ -52,6 +54,22 @@ export const useUserInfo = defineStore('userInfo', {
 							authBtnList: d.buttons,
 							time: new Date().getTime(),
 						};
+
+						// 读取用户配置
+						const configRes: any = await getAPI(SysAuthApi).apiSysAuthUserConfigGet();
+						if (configRes.data.result == null) return;
+
+						const configData = configRes.data.result;
+						const storesThemeConfig = useThemeConfig();
+
+						// storesThemeConfig.themeConfig.watermarkText = d.account;
+						storesThemeConfig.themeConfig.isWatermark = configData.watermarkEnabled;
+						if (storesThemeConfig.themeConfig.isWatermark) Watermark.set(storesThemeConfig.themeConfig.watermarkText);
+						else Watermark.del();
+
+						Local.remove('themeConfig');
+						Local.set('themeConfig', storesThemeConfig.themeConfig);
+
 						resolve(userInfos);
 					});
 			});

+ 7 - 1
Web/src/utils/request.ts

@@ -120,7 +120,13 @@ service.interceptors.response.use(
 		} else if (serve.code === undefined) {
 			return Promise.resolve(res);
 		} else if (serve.code !== 200) {
-			var message = JSON.stringify(serve.message);
+			var message;
+			// 判断 serve.message 是否为对象
+			if (serve.message && typeof serve.message == 'object') {
+				message = JSON.stringify(serve.message);
+			} else {
+				message = serve.message;
+			}
 			ElMessage.error(message);
 			throw new Error(message);
 		}

+ 1 - 27
Web/src/views/login/component/account.vue

@@ -68,14 +68,10 @@ import { useRoute, useRouter } from 'vue-router';
 import { ElMessage } from 'element-plus';
 import { useI18n } from 'vue-i18n';
 import { initBackEndControlRoutes } from '/@/router/backEnd';
-import { Local, Session } from '/@/utils/storage';
+import { Session } from '/@/utils/storage';
 import { formatAxis } from '/@/utils/formatTime';
 import { NextLoading } from '/@/utils/loading';
 
-import { storeToRefs } from 'pinia';
-import { useThemeConfig } from '/@/stores/themeConfig';
-import Watermark from '/@/utils/watermark';
-
 import { clearTokens, feature, getAPI } from '/@/utils/axios-utils';
 import { SysAuthApi } from '/@/api-services/api';
 
@@ -83,8 +79,6 @@ import { SysAuthApi } from '/@/api-services/api';
 import verifyImg from '/@/assets/logo-mini.svg';
 const DragVerifyImgRotate = defineAsyncComponent(() => import('/@/components/dragVerify/dragVerifyImgRotate.vue'));
 
-const storesThemeConfig = useThemeConfig();
-const { themeConfig } = storeToRefs(storesThemeConfig);
 const { t } = useI18n();
 const route = useRoute();
 const router = useRouter();
@@ -112,7 +106,6 @@ const state = reactive({
 	rotateVerifyImg: verifyImg,
 	secondVerEnabled: true,
 	captchaEnabled: true,
-	watermarkEnabled: true,
 	isPassRotate: false,
 });
 onMounted(async () => {
@@ -120,26 +113,9 @@ onMounted(async () => {
 	var res1 = await getAPI(SysAuthApi).apiSysAuthLoginConfigGet();
 	state.secondVerEnabled = res1.data.result.secondVerEnabled ?? true;
 	state.captchaEnabled = res1.data.result.captchaEnabled ?? true;
-	state.watermarkEnabled = res1.data.result.watermarkEnabled ?? true;
 
 	getCaptcha();
 });
-// 获取布局配置信息
-const getThemeConfig = computed(() => {
-	return themeConfig.value;
-});
-// 存储布局配置
-const setLocalThemeConfig = () => {
-	// 是否显示水印
-	if (!state.watermarkEnabled) return;
-
-	// getThemeConfig.value.watermarkText = state.ruleForm.account;
-	getThemeConfig.value.isWatermark = true;
-	Watermark.set(getThemeConfig.value.watermarkText);
-
-	Local.remove('themeConfig');
-	Local.set('themeConfig', getThemeConfig.value);
-};
 // 获取验证码
 const getCaptcha = async () => {
 	state.ruleForm.code = '';
@@ -191,8 +167,6 @@ const signInSuccess = (isNoPower: boolean | undefined) => {
 		} else {
 			router.push('/');
 		}
-		// // 设置水印
-		// setLocalThemeConfig();
 
 		// 登录成功提示
 		const signInText = t('message.signInText');