Pārlūkot izejas kodu

Merge branch 'next_upstream' into local_dev

# Conflicts:
#	Admin.NET/Admin.NET.Application/AppConfig.json
#	Admin.NET/Admin.NET.Core/Const/SqlSugarConst.cs
ALANE\Sevy.Jiang 3 gadi atpakaļ
vecāks
revīzija
71f95a7d5a
100 mainītis faili ar 2602 papildinājumiem un 2035 dzēšanām
  1. 3 1
      .gitignore
  2. 0 1
      Admin.NET/Admin.NET.Application/AppConfig.json
  3. 1 1
      Admin.NET/Admin.NET.Application/Const/ApplicationConst.cs
  4. 0 2
      Admin.NET/Admin.NET.Application/Service/TestService.cs
  5. 7 7
      Admin.NET/Admin.NET.Core/Admin.NET.Core.csproj
  6. 139 310
      Admin.NET/Admin.NET.Core/Admin.NET.Core.xml
  7. 6 1
      Admin.NET/Admin.NET.Core/Const/CacheConst.cs
  8. 21 11
      Admin.NET/Admin.NET.Core/Const/CommonConst.cs
  9. 6 1
      Admin.NET/Admin.NET.Core/Const/SqlSugarConst.cs
  10. 4 4
      Admin.NET/Admin.NET.Core/Entity/EntityBase.cs
  11. 2 2
      Admin.NET/Admin.NET.Core/Entity/SysConfig.cs
  12. 5 5
      Admin.NET/Admin.NET.Core/Entity/SysNotice.cs
  13. 11 4
      Admin.NET/Admin.NET.Core/Entity/SysNoticeUser.cs
  14. 7 0
      Admin.NET/Admin.NET.Core/Entity/SysTenant.cs
  15. 1 1
      Admin.NET/Admin.NET.Core/Entity/SysUser.cs
  16. 1 1
      Admin.NET/Admin.NET.Core/Enum/ErrorCodeEnum.cs
  17. 1 1
      Admin.NET/Admin.NET.Core/Hub/Dto/OnlineUserHubOutput.cs
  18. 9 9
      Admin.NET/Admin.NET.Core/Hub/IOnlineUserHub.cs
  19. 6 8
      Admin.NET/Admin.NET.Core/Hub/OnlineUserHub.cs
  20. 3 0
      Admin.NET/Admin.NET.Core/Job/OnlineUserJob.cs
  21. 4 4
      Admin.NET/Admin.NET.Core/SeedData/SysConfigSeedData.cs
  22. 0 2
      Admin.NET/Admin.NET.Core/SeedData/SysDictTypeSeedData.cs
  23. 67 57
      Admin.NET/Admin.NET.Core/SeedData/SysMenuSeedData.cs
  24. 1 3
      Admin.NET/Admin.NET.Core/SeedData/SysOrgSeedData.cs
  25. 0 16
      Admin.NET/Admin.NET.Core/SeedData/SysPosSeedData.cs
  26. 11 60
      Admin.NET/Admin.NET.Core/SeedData/SysRoleMenuSeedData.cs
  27. 0 6
      Admin.NET/Admin.NET.Core/SeedData/SysRoleSeedData.cs
  28. 1 2
      Admin.NET/Admin.NET.Core/SeedData/SysTenantSeedData.cs
  29. 0 2
      Admin.NET/Admin.NET.Core/SeedData/SysUserRoleSeedData.cs
  30. 0 2
      Admin.NET/Admin.NET.Core/SeedData/SysUserSeedData.cs
  31. 5 0
      Admin.NET/Admin.NET.Core/Service/Auth/Dto/LoginInput.cs
  32. 41 10
      Admin.NET/Admin.NET.Core/Service/Auth/SysAuthService.cs
  33. 5 108
      Admin.NET/Admin.NET.Core/Service/Cache/SysCacheService.cs
  34. 24 7
      Admin.NET/Admin.NET.Core/Service/File/SysFileService.cs
  35. 6 4
      Admin.NET/Admin.NET.Core/Service/Menu/SysMenuService.cs
  36. 0 57
      Admin.NET/Admin.NET.Core/Service/Notice/Dto/NoticeBase.cs
  37. 0 40
      Admin.NET/Admin.NET.Core/Service/Notice/Dto/NoticeDetailOutput.cs
  38. 7 71
      Admin.NET/Admin.NET.Core/Service/Notice/Dto/NoticeInput.cs
  39. 0 22
      Admin.NET/Admin.NET.Core/Service/Notice/Dto/NoticeReceiveOutput.cs
  40. 0 18
      Admin.NET/Admin.NET.Core/Service/Notice/ISysNoticeService.cs
  41. 0 12
      Admin.NET/Admin.NET.Core/Service/Notice/ISysNoticeUserService.cs
  42. 69 159
      Admin.NET/Admin.NET.Core/Service/Notice/SysNoticeService.cs
  43. 0 77
      Admin.NET/Admin.NET.Core/Service/Notice/SysNoticeUserService.cs
  44. 3 3
      Admin.NET/Admin.NET.Core/Service/OnlineUser/SysOnlineUserService.cs
  45. 5 5
      Admin.NET/Admin.NET.Core/Service/Org/SysOrgService.cs
  46. 0 1
      Admin.NET/Admin.NET.Core/Service/Region/Dto/RegionInput.cs
  47. 3 3
      Admin.NET/Admin.NET.Core/Service/Role/SysRoleService.cs
  48. 87 14
      Admin.NET/Admin.NET.Core/Service/Tenant/SysTenantService.cs
  49. 10 3
      Admin.NET/Admin.NET.Core/Service/User/SysUserService.cs
  50. 18 26
      Admin.NET/Admin.NET.Core/Service/User/UserManager.cs
  51. 23 2
      Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarRepository.cs
  52. 200 113
      Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarSetup.cs
  53. 1 1
      Admin.NET/Admin.NET.Web.Core/Admin.NET.Web.Core.csproj
  54. 2 1
      Admin.NET/Admin.NET.Web.Core/Startup.cs
  55. 175 37
      Web/src/api-services/apis/sys-auth-api.ts
  56. 32 32
      Web/src/api-services/apis/sys-cache-api.ts
  57. 222 354
      Web/src/api-services/apis/sys-notice-api.ts
  58. 76 0
      Web/src/api-services/apis/sys-tenant-api.ts
  59. 57 21
      Web/src/api-services/models/add-notice-input.ts
  60. 6 0
      Web/src/api-services/models/add-tenant-input.ts
  61. 12 12
      Web/src/api-services/models/admin-result-list-sys-notice.ts
  62. 57 0
      Web/src/api-services/models/admin-result-list-sys-tenant.ts
  63. 57 0
      Web/src/api-services/models/admin-result-sql-sugar-paged-list-sys-notice-user.ts
  64. 57 0
      Web/src/api-services/models/admin-result-sql-sugar-paged-list-sys-notice.ts
  65. 1 1
      Web/src/api-services/models/delete-notice-input.ts
  66. 9 4
      Web/src/api-services/models/index.ts
  67. 6 0
      Web/src/api-services/models/login-input.ts
  68. 4 11
      Web/src/api-services/models/notice-input.ts
  69. 63 0
      Web/src/api-services/models/sql-sugar-paged-list-sys-notice-user.ts
  70. 63 0
      Web/src/api-services/models/sql-sugar-paged-list-sys-notice.ts
  71. 22 15
      Web/src/api-services/models/sys-notice-user.ts
  72. 59 34
      Web/src/api-services/models/sys-notice.ts
  73. 6 0
      Web/src/api-services/models/sys-tenant.ts
  74. 53 23
      Web/src/api-services/models/update-notice-input.ts
  75. 6 0
      Web/src/api-services/models/update-tenant-input.ts
  76. 22 7
      Web/src/layout/navBars/breadcrumb/user.vue
  77. 89 85
      Web/src/layout/navBars/breadcrumb/userNews.vue
  78. 2 0
      Web/src/main.ts
  79. 1 1
      Web/src/stores/themeConfig.ts
  80. 8 6
      Web/src/theme/element.scss
  81. 12 0
      Web/src/utils/commonFunction.ts
  82. 166 0
      Web/src/views/home/notice/index.vue
  83. 40 13
      Web/src/views/login/component/account.vue
  84. 6 7
      Web/src/views/login/index.vue
  85. 2 2
      Web/src/views/system/cache/index.vue
  86. 1 1
      Web/src/views/system/config/component/editConfig.vue
  87. 1 1
      Web/src/views/system/config/index.vue
  88. 2 2
      Web/src/views/system/file/index.vue
  89. 2 2
      Web/src/views/system/log/oplog/index.vue
  90. 1 1
      Web/src/views/system/menu/component/editMenu.vue
  91. 1 1
      Web/src/views/system/menu/index.vue
  92. 96 0
      Web/src/views/system/notice/component/editNotice.vue
  93. 186 0
      Web/src/views/system/notice/index.vue
  94. 23 61
      Web/src/views/system/onlineUser/index.vue
  95. 44 0
      Web/src/views/system/onlineUser/signalR.ts
  96. 1 1
      Web/src/views/system/org/index.vue
  97. 1 1
      Web/src/views/system/pos/index.vue
  98. 1 1
      Web/src/views/system/role/component/editRole.vue
  99. 1 1
      Web/src/views/system/server/index.vue
  100. 24 16
      Web/src/views/system/tenant/component/editTenant.vue

+ 3 - 1
.gitignore

@@ -26,4 +26,6 @@ bin-release/
 # folders
 dist/
 .vs/
-node_modules/
+node_modules/
+/Admin.NET/Admin.NET.Web.Entry/wwwroot/Avatar
+/Admin.NET/Admin.NET.Web.Entry/wwwroot/Signature

+ 0 - 1
Admin.NET/Admin.NET.Application/AppConfig.json

@@ -51,5 +51,4 @@
     "AlipayUrl": "", // 支付宝支付回调
     "AlipayRefundUrl": "" // 支付宝退款回调
   }
-
 }

+ 1 - 1
Admin.NET/Admin.NET.Application/Const/ApplicationConst.cs

@@ -13,5 +13,5 @@ public class ApplicationConst
     /// <summary>
     /// 数据库标识
     /// </summary>
-    public const string ConfigId = "Test";
+    public const string ConfigId = "test";
 }

+ 0 - 2
Admin.NET/Admin.NET.Application/Service/TestService.cs

@@ -1,6 +1,4 @@
 using Admin.NET.Application.Const;
-using AngleSharp;
-using AngleSharp.Html.Dom;
 using Furion.DatabaseAccessor;
 using Furion.FriendlyException;
 using Furion.Localization;

+ 7 - 7
Admin.NET/Admin.NET.Core/Admin.NET.Core.csproj

@@ -25,24 +25,24 @@
   <ItemGroup>
     <PackageReference Include="AngleSharp" Version="0.17.1" />
     <PackageReference Include="AspNetCoreRateLimit" Version="4.0.2" />
-    <PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.7.2" />
-    <PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.7.2" />
-    <PackageReference Include="Furion.Pure" Version="4.7.2" />
+    <PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.7.3" />
+    <PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.7.3" />
+    <PackageReference Include="Furion.Pure" Version="4.7.3" />
     <PackageReference Include="Lazy.Captcha.Core" Version="1.1.6" />
     <PackageReference Include="Magicodes.IE.Excel" Version="2.6.9" />
     <PackageReference Include="Magicodes.IE.Pdf" Version="2.6.9" />
     <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.10" />
     <PackageReference Include="NEST" Version="7.17.5" />
     <PackageReference Include="NETCore.MailKit" Version="2.1.0" />
-    <PackageReference Include="NewLife.Redis" Version="5.0.2022.901" />
+    <PackageReference Include="NewLife.Redis" Version="5.0.2022.1101" />
     <PackageReference Include="OnceMi.AspNetCore.OSS" Version="1.1.9" />
-    <PackageReference Include="SKIT.FlurlHttpClient.Wechat.Api" Version="2.19.0" />
+    <PackageReference Include="SKIT.FlurlHttpClient.Wechat.Api" Version="2.20.0" />
     <PackageReference Include="SKIT.FlurlHttpClient.Wechat.TenpayV3" Version="2.13.1" />
-    <PackageReference Include="SqlSugarCore" Version="5.1.3.29" />
+    <PackageReference Include="SqlSugarCore" Version="5.1.3.30" />
     <PackageReference Include="System.Linq.Dynamic.Core" Version="1.2.21" />
     <PackageReference Include="UAParser" Version="3.1.47" />
     <PackageReference Include="Yitter.IdGenerator" Version="1.0.14" />
-    <PackageReference Include="Masuit.Tools.Core" Version="2.5.6.3" />
+    <PackageReference Include="Masuit.Tools.Core" Version="2.5.7.1" />
   </ItemGroup>
 
   <ItemGroup>

+ 139 - 310
Admin.NET/Admin.NET.Core/Admin.NET.Core.xml

@@ -64,7 +64,7 @@
         </member>
         <member name="F:Admin.NET.Core.CacheConst.KeyPermission">
             <summary>
-            权限缓存
+            权限缓存(按钮集合)
             </summary>
         </member>
         <member name="F:Admin.NET.Core.CacheConst.KeyOrgIdList">
@@ -107,6 +107,11 @@
             swagger登录缓存
             </summary>
         </member>
+        <member name="F:Admin.NET.Core.CacheConst.KeyTenant">
+            <summary>
+            租户缓存
+            </summary>
+        </member>
         <member name="T:Admin.NET.Core.ClaimConst">
             <summary>
             Claim相关常量
@@ -167,19 +172,14 @@
             通用常量
             </summary>
         </member>
-        <member name="F:Admin.NET.Core.CommonConst.SysPassword">
-            <summary>
-            默认密码
-            </summary>
-        </member>
-        <member name="F:Admin.NET.Core.CommonConst.SysAdminRoleCode">
+        <member name="F:Admin.NET.Core.CommonConst.SysDemoEnv">
             <summary>
-            系统管理员角色编码
+            演示环境开关
             </summary>
         </member>
-        <member name="F:Admin.NET.Core.CommonConst.SysDemoEnv">
+        <member name="F:Admin.NET.Core.CommonConst.SysPassword">
             <summary>
-            演示环境开关
+            默认密码
             </summary>
         </member>
         <member name="F:Admin.NET.Core.CommonConst.SysCaptcha">
@@ -192,9 +192,24 @@
             开启操作日志
             </summary>
         </member>
+        <member name="F:Admin.NET.Core.CommonConst.SysTokenExpire">
+            <summary>
+            Token过期时间
+            </summary>
+        </member>
         <member name="F:Admin.NET.Core.CommonConst.SysSingleLogin">
             <summary>
-            开启当用户登录
+            单用户登录
+            </summary>
+        </member>
+        <member name="F:Admin.NET.Core.CommonConst.SysTenantDb">
+            <summary>
+            开启多库租户
+            </summary>
+        </member>
+        <member name="F:Admin.NET.Core.CommonConst.SysAdminRole">
+            <summary>
+            系统管理员角色编码
             </summary>
         </member>
         <member name="F:Admin.NET.Core.CommonConst.SysSensitiveDetection">
@@ -242,6 +257,11 @@
             默认表主键
             </summary>
         </member>
+        <member name="F:Admin.NET.Core.SqlSugarConst.TenantId">
+            <summary>
+            默认租户Id
+            </summary>
+        </member>
         <member name="T:Admin.NET.Core.EntityBaseId">
             <summary>
             框架实体基类Id
@@ -509,7 +529,7 @@
         </member>
         <member name="P:Admin.NET.Core.SysConfig.SysFlag">
             <summary>
-            是否是系统参数(Y-是,N-否)
+            是否是内置参数(Y-是,N-否)
             </summary>
         </member>
         <member name="P:Admin.NET.Core.SysConfig.GroupCode">
@@ -979,7 +999,7 @@
         </member>
         <member name="P:Admin.NET.Core.SysNotice.Type">
             <summary>
-            类型(字典 1通知 2公告)
+            类型(1通知 2公告)
             </summary>
         </member>
         <member name="P:Admin.NET.Core.SysNotice.PublicUserId">
@@ -1014,7 +1034,7 @@
         </member>
         <member name="P:Admin.NET.Core.SysNotice.Status">
             <summary>
-            状态(字典 0草稿 1发布 2撤回 3删除)
+            状态(0草稿 1发布 2撤回 3删除)
             </summary>
         </member>
         <member name="T:Admin.NET.Core.SysNoticeUser">
@@ -1027,6 +1047,11 @@
             通知公告Id
             </summary>
         </member>
+        <member name="P:Admin.NET.Core.SysNoticeUser.SysNotice">
+            <summary>
+            通知公告
+            </summary>
+        </member>
         <member name="P:Admin.NET.Core.SysNoticeUser.UserId">
             <summary>
             用户Id
@@ -1039,7 +1064,7 @@
         </member>
         <member name="P:Admin.NET.Core.SysNoticeUser.ReadStatus">
             <summary>
-            状态(字典 0未读 1已读)
+            状态(0未读 1已读)
             </summary>
         </member>
         <member name="T:Admin.NET.Core.SysOnlineUser">
@@ -1352,6 +1377,11 @@
             数据库连接
             </summary>
         </member>
+        <member name="P:Admin.NET.Core.SysTenant.ConfigId">
+            <summary>
+            数据库标识
+            </summary>
+        </member>
         <member name="P:Admin.NET.Core.SysTenant.Order">
             <summary>
             排序
@@ -3297,32 +3327,32 @@
             结果筛选器
             </summary>
         </member>
-        <member name="M:Admin.NET.Core.IOnlineUserHub.ForceOffline(System.Object)">
+        <member name="M:Admin.NET.Core.IOnlineUserHub.OnlineUserList(Admin.NET.Core.OnlineUserList)">
             <summary>
-            强制下线
+            在线用户列表
             </summary>
             <param name="context"></param>
             <returns></returns>
         </member>
-        <member name="M:Admin.NET.Core.IOnlineUserHub.ReceiveMessage(System.Object)">
+        <member name="M:Admin.NET.Core.IOnlineUserHub.ForceOffline(System.Object)">
             <summary>
-            接收消息
+            强制下线
             </summary>
             <param name="context"></param>
             <returns></returns>
         </member>
-        <member name="M:Admin.NET.Core.IOnlineUserHub.OnlineUserChange(Admin.NET.Core.OnlineUserHubOutput)">
+        <member name="M:Admin.NET.Core.IOnlineUserHub.PublicNotice(Admin.NET.Core.SysNotice)">
             <summary>
-            在线用户变动
+            发布站内消息
             </summary>
             <param name="context"></param>
             <returns></returns>
         </member>
-        <member name="M:Admin.NET.Core.IOnlineUserHub.AppendNotice(Admin.NET.Core.SysNotice)">
+        <member name="M:Admin.NET.Core.IOnlineUserHub.ReceiveMessage(System.Object)">
             <summary>
-            组合消息
+            接收消息
             </summary>
-            <param name="notice"></param>
+            <param name="context"></param>
             <returns></returns>
         </member>
         <member name="T:Admin.NET.Core.OnlineUserHub">
@@ -3800,6 +3830,11 @@
             验证码
             </summary>
         </member>
+        <member name="P:Admin.NET.Core.Service.LoginInput.TenantId">
+            <summary>
+            租户Id
+            </summary>
+        </member>
         <member name="T:Admin.NET.Core.Service.LoginOutput">
             <summary>
             用户登录结果
@@ -3901,12 +3936,24 @@
             退出系统
             </summary>
         </member>
+        <member name="M:Admin.NET.Core.Service.SysAuthService.GetCaptchaFlag">
+            <summary>
+            是否启用验证码
+            </summary>
+            <returns></returns>
+        </member>
         <member name="M:Admin.NET.Core.Service.SysAuthService.GetCaptcha">
             <summary>
             生成图片验证码
             </summary>
             <returns></returns>
         </member>
+        <member name="M:Admin.NET.Core.Service.SysAuthService.GetTenantDbList">
+            <summary>
+            是否启用多库租户
+            </summary>
+            <returns></returns>
+        </member>
         <member name="M:Admin.NET.Core.Service.SysAuthService.SwaggerCheckUrl">
             <summary>
             Swagger登录检查
@@ -3977,56 +4024,11 @@
             <param name="prefixKey">键名前缀</param>
             <returns></returns>
         </member>
-        <member name="M:Admin.NET.Core.Service.SysCacheService.GetOrgIdList(System.Int64)">
+        <member name="M:Admin.NET.Core.Service.SysCacheService.GetCacheValue(System.String)">
             <summary>
-            获取机构Id集合
+            获取缓存值
             </summary>
-            <param name="userId"></param>
-            <returns></returns>
-        </member>
-        <member name="M:Admin.NET.Core.Service.SysCacheService.SetOrgIdList(System.Int64,System.Collections.Generic.List{System.Int64})">
-            <summary>
-            缓存机构Id集合
-            </summary>
-            <param name="userId"></param>
-            <param name="orgIdList"></param>
-            <returns></returns>
-        </member>
-        <member name="M:Admin.NET.Core.Service.SysCacheService.GetPermission(System.Int64)">
-            <summary>
-            获取权限集合(按钮)
-            </summary>
-            <param name="userId"></param>
-            <returns></returns>
-        </member>
-        <member name="M:Admin.NET.Core.Service.SysCacheService.SetPermission(System.Int64,System.Collections.Generic.List{System.String})">
-            <summary>
-            缓存权限集合(按钮)
-            </summary>
-            <param name="userId"></param>
-            <param name="permissions"></param>
-            <returns></returns>
-        </member>
-        <member name="M:Admin.NET.Core.Service.SysCacheService.GetMaxDataScopeType(System.Int64)">
-            <summary>
-            获取最大角色数据范围
-            </summary>
-            <param name="userId"></param>
-            <returns></returns>
-        </member>
-        <member name="M:Admin.NET.Core.Service.SysCacheService.SetMaxDataScopeType(System.Int64,System.Int32)">
-            <summary>
-            缓存最大角色数据范围
-            </summary>
-            <param name="userId"></param>
-            <param name="dataScopeType"></param>
-            <returns></returns>
-        </member>
-        <member name="M:Admin.NET.Core.Service.SysCacheService.CacheDetail(System.String)">
-            <summary>
-            获取缓存
-            </summary>
-            <param name="cacheKey"></param>
+            <param name="key"></param>
             <returns></returns>
         </member>
         <member name="P:Admin.NET.Core.Service.CustomViewEngine.ConfigId">
@@ -5448,184 +5450,14 @@
             <param name="message"></param>
             <returns></returns>
         </member>
-        <member name="T:Admin.NET.Core.Service.NoticeBase">
-            <summary>
-            通知公告参数
-            </summary>
-        </member>
-        <member name="P:Admin.NET.Core.Service.NoticeBase.Title">
+        <member name="P:Admin.NET.Core.Service.PageNoticeInput.Title">
             <summary>
             标题
             </summary>
         </member>
-        <member name="P:Admin.NET.Core.Service.NoticeBase.Content">
-            <summary>
-            内容
-            </summary>
-        </member>
-        <member name="P:Admin.NET.Core.Service.NoticeBase.Type">
-            <summary>
-            类型(字典 1通知 2公告)
-            </summary>
-        </member>
-        <member name="P:Admin.NET.Core.Service.NoticeBase.PublicUserId">
-            <summary>
-            发布人Id
-            </summary>
-        </member>
-        <member name="P:Admin.NET.Core.Service.NoticeBase.PublicUserName">
-            <summary>
-            发布人姓名
-            </summary>
-        </member>
-        <member name="P:Admin.NET.Core.Service.NoticeBase.PublicOrgId">
-            <summary>
-            发布机构Id
-            </summary>
-        </member>
-        <member name="P:Admin.NET.Core.Service.NoticeBase.PublicOrgName">
-            <summary>
-            发布机构名称
-            </summary>
-        </member>
-        <member name="P:Admin.NET.Core.Service.NoticeBase.PublicTime">
-            <summary>
-            发布时间
-            </summary>
-        </member>
-        <member name="P:Admin.NET.Core.Service.NoticeBase.CancelTime">
+        <member name="P:Admin.NET.Core.Service.PageNoticeInput.Type">
             <summary>
-            撤回时间
-            </summary>
-        </member>
-        <member name="P:Admin.NET.Core.Service.NoticeBase.Status">
-            <summary>
-            状态(字典 0草稿 1发布 2撤回 3删除)
-            </summary>
-        </member>
-        <member name="T:Admin.NET.Core.Service.NoticeDetailOutput">
-            <summary>
-            系统通知公告详情参数
-            </summary>
-        </member>
-        <member name="P:Admin.NET.Core.Service.NoticeDetailOutput.NoticeUserIdList">
-            <summary>
-            通知到的用户Id集合
-            </summary>
-        </member>
-        <member name="P:Admin.NET.Core.Service.NoticeDetailOutput.NoticeUserReadInfoList">
-            <summary>
-            通知到的用户阅读信息集合
-            </summary>
-        </member>
-        <member name="P:Admin.NET.Core.Service.NoticeUserRead.UserId">
-            <summary>
-            用户Id
-            </summary>
-        </member>
-        <member name="P:Admin.NET.Core.Service.NoticeUserRead.UserName">
-            <summary>
-            用户名称
-            </summary>
-        </member>
-        <member name="P:Admin.NET.Core.Service.NoticeUserRead.ReadStatus">
-            <summary>
-            状态(字典 0未读 1已读)
-            </summary>
-        </member>
-        <member name="P:Admin.NET.Core.Service.NoticeUserRead.ReadTime">
-            <summary>
-            阅读时间
-            </summary>
-        </member>
-        <member name="T:Admin.NET.Core.Service.NoticeInput">
-            <summary>
-            通知公告参数
-            </summary>
-        </member>
-        <member name="P:Admin.NET.Core.Service.NoticeInput.Title">
-            <summary>
-            标题
-            </summary>
-        </member>
-        <member name="P:Admin.NET.Core.Service.NoticeInput.Content">
-            <summary>
-            内容
-            </summary>
-        </member>
-        <member name="P:Admin.NET.Core.Service.NoticeInput.Type">
-            <summary>
-            类型(字典 1通知 2公告)
-            </summary>
-        </member>
-        <member name="P:Admin.NET.Core.Service.NoticeInput.Status">
-            <summary>
-            状态(字典 0草稿 1发布 2撤回 3删除)
-            </summary>
-        </member>
-        <member name="P:Admin.NET.Core.Service.NoticeInput.NoticeUserIdList">
-            <summary>
-            通知到的人
-            </summary>
-        </member>
-        <member name="P:Admin.NET.Core.Service.AddNoticeInput.Title">
-            <summary>
-            标题
-            </summary>
-        </member>
-        <member name="P:Admin.NET.Core.Service.AddNoticeInput.Content">
-            <summary>
-            内容
-            </summary>
-        </member>
-        <member name="P:Admin.NET.Core.Service.AddNoticeInput.Type">
-            <summary>
-            类型(字典 1通知 2公告)
-            </summary>
-        </member>
-        <member name="P:Admin.NET.Core.Service.AddNoticeInput.Status">
-            <summary>
-            状态(字典 0草稿 1发布 2撤回 3删除)
-            </summary>
-        </member>
-        <member name="P:Admin.NET.Core.Service.AddNoticeInput.NoticeUserIdList">
-            <summary>
-            通知到的人
-            </summary>
-        </member>
-        <member name="P:Admin.NET.Core.Service.DeleteNoticeInput.Id">
-            <summary>
-            Id
-            </summary>
-        </member>
-        <member name="P:Admin.NET.Core.Service.UpdateNoticeInput.Id">
-            <summary>
-            Id
-            </summary>
-        </member>
-        <member name="P:Admin.NET.Core.Service.ChangeStatusNoticeInput.Status">
-            <summary>
-            状态(字典 0草稿 1发布 2撤回 3删除)
-            </summary>
-        </member>
-        <member name="T:Admin.NET.Core.Service.NoticeReceiveOutput">
-            <summary>
-            通知公告接收参数
-            </summary>
-        </member>
-        <member name="P:Admin.NET.Core.Service.NoticeReceiveOutput.Id">
-            <summary>
-            Id
-            </summary>
-        </member>
-        <member name="P:Admin.NET.Core.Service.NoticeReceiveOutput.ReadStatus">
-            <summary>
-            阅读状态(字典 0未读 1已读)
-            </summary>
-        </member>
-        <member name="P:Admin.NET.Core.Service.NoticeReceiveOutput.ReadTime">
-            <summary>
-            阅读时间
+            类型(1通知 2公告)
             </summary>
         </member>
         <member name="T:Admin.NET.Core.Service.SysNoticeService">
@@ -5633,9 +5465,9 @@
             系统通知公告服务
             </summary>
         </member>
-        <member name="M:Admin.NET.Core.Service.SysNoticeService.QueryNoticePageList(Admin.NET.Core.Service.NoticeInput)">
+        <member name="M:Admin.NET.Core.Service.SysNoticeService.GetPageNotice(Admin.NET.Core.Service.PageNoticeInput)">
             <summary>
-            分页查询通知公告
+            获取通知公告分页列表
             </summary>
             <param name="input"></param>
             <returns></returns>
@@ -5647,13 +5479,6 @@
             <param name="input"></param>
             <returns></returns>
         </member>
-        <member name="M:Admin.NET.Core.Service.SysNoticeService.DeleteNotice(Admin.NET.Core.Service.DeleteNoticeInput)">
-            <summary>
-            删除通知公告
-            </summary>
-            <param name="input"></param>
-            <returns></returns>
-        </member>
         <member name="M:Admin.NET.Core.Service.SysNoticeService.UpdateNotice(Admin.NET.Core.Service.UpdateNoticeInput)">
             <summary>
             更新通知公告
@@ -5661,78 +5486,45 @@
             <param name="input"></param>
             <returns></returns>
         </member>
-        <member name="M:Admin.NET.Core.Service.SysNoticeService.GetNotice(Admin.NET.Core.Service.QueryNoticeInput)">
+        <member name="M:Admin.NET.Core.Service.SysNoticeService.DeleteNotice(Admin.NET.Core.Service.DeleteNoticeInput)">
             <summary>
-            获取通知公告详情
+            删除通知公告
             </summary>
             <param name="input"></param>
             <returns></returns>
         </member>
-        <member name="M:Admin.NET.Core.Service.SysNoticeService.ChangeStatus(Admin.NET.Core.Service.ChangeStatusNoticeInput)">
+        <member name="M:Admin.NET.Core.Service.SysNoticeService.PublicNotice(Admin.NET.Core.Service.NoticeInput)">
             <summary>
-            修改通知公告状态
+            发布通知公告
             </summary>
             <param name="input"></param>
             <returns></returns>
         </member>
-        <member name="M:Admin.NET.Core.Service.SysNoticeService.ReceivedNoticePageList(Admin.NET.Core.Service.NoticeInput)">
+        <member name="M:Admin.NET.Core.Service.SysNoticeService.SetNoticeRead(Admin.NET.Core.Service.NoticeInput)">
             <summary>
-            获取接收的通知公告
+            设置通知公告已读状态
             </summary>
             <param name="input"></param>
             <returns></returns>
         </member>
-        <member name="M:Admin.NET.Core.Service.SysNoticeService.UnReadNoticeList(Admin.NET.Core.Service.NoticeInput)">
+        <member name="M:Admin.NET.Core.Service.SysNoticeService.GetPageReceivedNotice(Admin.NET.Core.Service.PageNoticeInput)">
             <summary>
-            未处理消息
+            获取接收的通知公告(当前用户)
             </summary>
             <param name="input"></param>
             <returns></returns>
         </member>
-        <member name="M:Admin.NET.Core.Service.SysNoticeService.UpdatePublicInfo(Admin.NET.Core.SysNotice)">
-            <summary>
-            更新发布信息
-            </summary>
-            <param name="notice"></param>
-        </member>
-        <member name="T:Admin.NET.Core.Service.SysNoticeUserService">
-            <summary>
-            系统通知公告用户
-            </summary>
-        </member>
-        <member name="M:Admin.NET.Core.Service.SysNoticeUserService.Add(System.Int64,System.Collections.Generic.List{System.Int64},Admin.NET.Core.NoticeUserStatusEnum)">
-            <summary>
-            增加
-            </summary>
-            <param name="noticeId"></param>
-            <param name="noticeUserIdList"></param>
-            <param name="noticeUserStatus"></param>
-            <returns></returns>
-        </member>
-        <member name="M:Admin.NET.Core.Service.SysNoticeUserService.Update(System.Int64,System.Collections.Generic.List{System.Int64},Admin.NET.Core.NoticeUserStatusEnum)">
+        <member name="M:Admin.NET.Core.Service.SysNoticeService.GetUnReadNoticeList">
             <summary>
-            更新
+            获取未读的通知公告(当前用户)
             </summary>
-            <param name="noticeId"></param>
-            <param name="noticeUserIdList"></param>
-            <param name="noticeUserStatus"></param>
             <returns></returns>
         </member>
-        <member name="M:Admin.NET.Core.Service.SysNoticeUserService.GetNoticeUserListByNoticeId(System.Int64)">
+        <member name="M:Admin.NET.Core.Service.SysNoticeService.InitNoticeInfo(Admin.NET.Core.SysNotice)">
             <summary>
-            获取通知公告用户列表
+            初始化通知公告信息
             </summary>
-            <param name="noticeId"></param>
-            <returns></returns>
-        </member>
-        <member name="M:Admin.NET.Core.Service.SysNoticeUserService.Read(System.Int64,System.Int64,Admin.NET.Core.NoticeUserStatusEnum)">
-            <summary>
-            设置通知公告读取状态
-            </summary>
-            <param name="noticeId"></param>
-            <param name="userId"></param>
-            <param name="status"></param>
-            <returns></returns>
+            <param name="notice"></param>
         </member>
         <member name="P:Admin.NET.Core.Service.PageOnlineUserInput.UserName">
             <summary>
@@ -5762,9 +5554,9 @@
             <param name="user"></param>
             <returns></returns>
         </member>
-        <member name="M:Admin.NET.Core.Service.SysOnlineUserService.AppendNotice(Admin.NET.Core.SysNotice,System.Collections.Generic.List{System.Int64})">
+        <member name="M:Admin.NET.Core.Service.SysOnlineUserService.PublicNotice(Admin.NET.Core.SysNotice,System.Collections.Generic.List{System.Int64})">
             <summary>
-            发消息
+            发布站内消息
             </summary>
             <param name="notice"></param>
             <param name="userIds"></param>
@@ -6285,6 +6077,12 @@
             <param name="input"></param>
             <returns></returns>
         </member>
+        <member name="M:Admin.NET.Core.Service.SysTenantService.GetTenantDbList">
+            <summary>
+            获取库隔离的租户列表
+            </summary>
+            <returns></returns>
+        </member>
         <member name="M:Admin.NET.Core.Service.SysTenantService.AddTenant(Admin.NET.Core.Service.AddTenantInput)">
             <summary>
             增加租户
@@ -6294,7 +6092,7 @@
         </member>
         <member name="M:Admin.NET.Core.Service.SysTenantService.InitNewTenant(Admin.NET.Core.SysTenant)">
             <summary>
-            新增租户初始化
+            新增租户初始化(Id隔离)
             </summary>
             <param name="newTenant"></param>
         </member>
@@ -6340,6 +6138,13 @@
             <param name="input"></param>
             <returns></returns>
         </member>
+        <member name="M:Admin.NET.Core.Service.SysTenantService.GetTenant(System.Int64)">
+            <summary>
+            获取租户
+            </summary>
+            <param name="tenantId"></param>
+            <returns></returns>
+        </member>
         <member name="M:Admin.NET.Core.Service.SysTenantService.GetTenantAdminUser(System.Int64)">
             <summary>
             获取租户管理员用户
@@ -6347,6 +6152,19 @@
             <param name="tenantId"></param>
             <returns></returns>
         </member>
+        <member name="M:Admin.NET.Core.Service.SysTenantService.UpdateTenantCache">
+            <summary>
+            缓存所有租户
+            </summary>
+            <returns></returns>
+        </member>
+        <member name="M:Admin.NET.Core.Service.SysTenantService.CreateTenantDb(Admin.NET.Core.Service.TenantInput)">
+            <summary>
+            创建租户数据库(根据默认库结构)
+            </summary>
+            <param name="input"></param>
+            <returns></returns>
+        </member>
         <member name="P:Admin.NET.Core.Service.PageTimerInput.TimerName">
             <summary>
             任务名称
@@ -6926,13 +6744,6 @@
             当前登录用户
             </summary>
         </member>
-        <member name="M:Admin.NET.Core.UserManager.CheckUserAsync(System.Int64)">
-            <summary>
-            获取用户信息
-            </summary>
-            <param name="userId"></param>
-            <returns></returns>
-        </member>
         <member name="T:Admin.NET.Core.IEntityFilter">
             <summary>
             自定义实体过滤器接口
@@ -7032,11 +6843,29 @@
             </summary>
             <param name="services"></param>
         </member>
+        <member name="M:Admin.NET.Core.SqlSugarSetup.SetDbConfig(Admin.NET.Core.DbConnectionConfig)">
+            <summary>
+            配置连接属性
+            </summary>
+            <param name="config"></param>
+        </member>
+        <member name="M:Admin.NET.Core.SqlSugarSetup.SetDbAop(SqlSugar.SqlSugarScopeProvider,Admin.NET.Core.DbConnectionConfig)">
+            <summary>
+            配置Aop
+            </summary>
+            <param name="db"></param>
+            <param name="config"></param>
+        </member>
         <member name="M:Admin.NET.Core.SqlSugarSetup.InitDataBase(SqlSugar.SqlSugarScope,Admin.NET.Core.DbConnectionOptions)">
             <summary>
             初始化数据库结构
             </summary>
         </member>
+        <member name="M:Admin.NET.Core.SqlSugarSetup.CreateDataBase(SqlSugar.ISqlSugarClient,Admin.NET.Core.DbConnectionConfig,System.Int64)">
+            <summary>
+            初始化数据库结构
+            </summary>
+        </member>
         <member name="M:Admin.NET.Core.SqlSugarSetup.SetDeletedEntityFilter(SqlSugar.SqlSugarScopeProvider)">
             <summary>
             配置实体假删除过滤器

+ 6 - 1
Admin.NET/Admin.NET.Core/Const/CacheConst.cs

@@ -16,7 +16,7 @@ public class CacheConst
     public const string KeyMenu = "menu:";
 
     /// <summary>
-    /// 权限缓存
+    /// 权限缓存(按钮集合)
     /// </summary>
     public const string KeyPermission = "permission:";
 
@@ -59,4 +59,9 @@ public class CacheConst
     /// swagger登录缓存
     /// </summary>
     public const string SwaggerLogin = "swaggerLogin:";
+
+    /// <summary>
+    /// 租户缓存
+    /// </summary>
+    public const string KeyTenant = "tenant:";
 }

+ 21 - 11
Admin.NET/Admin.NET.Core/Const/CommonConst.cs

@@ -6,19 +6,14 @@
 public class CommonConst
 {
     /// <summary>
-    /// 默认密码
-    /// </summary>
-    public const string SysPassword = "123456";
-
-    /// <summary>
-    /// 系统管理员角色编码
+    /// 演示环境开关
     /// </summary>
-    public const string SysAdminRoleCode = "sys_admin";
+    public const string SysDemoEnv = "sys_demo";
 
     /// <summary>
-    /// 演示环境开关
+    /// 默认密码
     /// </summary>
-    public const string SysDemoEnv = "sys_demo_env";
+    public const string SysPassword = "sys_password";
 
     /// <summary>
     /// 验证码开关
@@ -28,13 +23,28 @@ public class CommonConst
     /// <summary>
     /// 开启操作日志
     /// </summary>
-    public const string SysOpLog = "sys_op_log";
+    public const string SysOpLog = "sys_oplog";
+
+    /// <summary>
+    /// Token过期时间
+    /// </summary>
+    public const string SysTokenExpire = "sys_token_expire";
 
     /// <summary>
-    /// 开启当用户登录
+    /// 用户登录
     /// </summary>
     public const string SysSingleLogin = "sys_single_login";
 
+    /// <summary>
+    /// 开启多库租户
+    /// </summary>
+    public const string SysTenantDb = "sys_tenant_db";
+
+    /// <summary>
+    /// 系统管理员角色编码
+    /// </summary>
+    public const string SysAdminRole = "sys_admin";
+
     /// <summary>
     /// 开启全局脱敏处理(默认不开启)
     /// </summary>

+ 6 - 1
Admin.NET/Admin.NET.Core/Const/SqlSugarConst.cs

@@ -8,10 +8,15 @@ public class SqlSugarConst
     /// <summary>
     /// 默认数据库标识
     /// </summary>
-    public const string ConfigId = "eolane";
+    public const string ConfigId = "default";
 
     /// <summary>
     /// 默认表主键
     /// </summary>
     public const string PrimaryKey = "Id";
+
+    /// <summary>
+    /// 默认租户Id
+    /// </summary>
+    public const string TenantId = "TenantId";
 }

+ 4 - 4
Admin.NET/Admin.NET.Core/Entity/EntityBase.cs

@@ -20,25 +20,25 @@ public abstract class EntityBase : EntityBaseId
     /// <summary>
     /// 创建时间
     /// </summary>
-    [SugarColumn(ColumnDescription = "创建时间")]
+    [SugarColumn(ColumnDescription = "创建时间", IsOnlyIgnoreUpdate = true)]
     public virtual DateTime? CreateTime { get; set; }
 
     /// <summary>
     /// 更新时间
     /// </summary>
-    [SugarColumn(ColumnDescription = "更新时间")]
+    [SugarColumn(ColumnDescription = "更新时间", IsOnlyIgnoreInsert = true)]
     public virtual DateTime? UpdateTime { get; set; }
 
     /// <summary>
     /// 创建者Id
     /// </summary>
-    [SugarColumn(ColumnDescription = "创建者Id")]
+    [SugarColumn(ColumnDescription = "创建者Id", IsOnlyIgnoreUpdate = true)]
     public virtual long? CreateUserId { get; set; }
 
     /// <summary>
     /// 修改者Id
     /// </summary>
-    [SugarColumn(ColumnDescription = "修改者Id")]
+    [SugarColumn(ColumnDescription = "修改者Id", IsOnlyIgnoreInsert = true)]
     public virtual long? UpdateUserId { get; set; }
 
     /// <summary>

+ 2 - 2
Admin.NET/Admin.NET.Core/Entity/SysConfig.cs

@@ -28,9 +28,9 @@ public class SysConfig : EntityBase
     public string Value { get; set; }
 
     /// <summary>
-    /// 是否是系统参数(Y-是,N-否)
+    /// 是否是内置参数(Y-是,N-否)
     /// </summary>
-    [SugarColumn(ColumnDescription = "是否是系统参数")]
+    [SugarColumn(ColumnDescription = "是否是内置参数")]
     public YesNoEnum SysFlag { get; set; }
 
     /// <summary>

+ 5 - 5
Admin.NET/Admin.NET.Core/Entity/SysNotice.cs

@@ -3,7 +3,7 @@
 /// <summary>
 /// 系统通知公告表
 /// </summary>
-[SugarTable("sys_notice", "通知公告表")]
+[SugarTable("sys_notice", "系统通知公告表")]
 public class SysNotice : EntityBase
 {
     /// <summary>
@@ -21,9 +21,9 @@ public class SysNotice : EntityBase
     public virtual string Content { get; set; }
 
     /// <summary>
-    /// 类型(字典 1通知 2公告)
+    /// 类型(1通知 2公告)
     /// </summary>
-    [SugarColumn(ColumnDescription = "类型(字典 1通知 2公告)")]
+    [SugarColumn(ColumnDescription = "类型(1通知 2公告)")]
     public NoticeTypeEnum Type { get; set; }
 
     /// <summary>
@@ -65,8 +65,8 @@ public class SysNotice : EntityBase
     public DateTime CancelTime { get; set; }
 
     /// <summary>
-    /// 状态(字典 0草稿 1发布 2撤回 3删除)
+    /// 状态(0草稿 1发布 2撤回 3删除)
     /// </summary>
-    [SugarColumn(ColumnDescription = "状态(字典 0草稿 1发布 2撤回 3删除)")]
+    [SugarColumn(ColumnDescription = "状态(0草稿 1发布 2撤回 3删除)")]
     public NoticeStatusEnum Status { get; set; }
 }

+ 11 - 4
Admin.NET/Admin.NET.Core/Entity/SysNoticeUser.cs

@@ -3,7 +3,7 @@
 /// <summary>
 /// 系统通知公告用户表
 /// </summary>
-[SugarTable("sys_notice_user", "通知公告用户表")]
+[SugarTable("sys_notice_user", "系统通知公告用户表")]
 public class SysNoticeUser
 {
     /// <summary>
@@ -12,6 +12,13 @@ public class SysNoticeUser
     [SugarColumn(ColumnDescription = "通知公告Id")]
     public long NoticeId { get; set; }
 
+    /// <summary>
+    /// 通知公告
+    /// </summary>
+    [SugarColumn(IsIgnore = true)]
+    [Navigate(NavigateType.OneToOne, nameof(NoticeId))]
+    public SysNotice SysNotice { get; set; }
+
     /// <summary>
     /// 用户Id
     /// </summary>
@@ -25,8 +32,8 @@ public class SysNoticeUser
     public DateTime ReadTime { get; set; }
 
     /// <summary>
-    /// 状态(字典 0未读 1已读)
+    /// 状态(0未读 1已读)
     /// </summary>
-    [SugarColumn(ColumnDescription = "状态(字典 0未读 1已读)")]
-    public NoticeUserStatusEnum ReadStatus { get; set; }
+    [SugarColumn(ColumnDescription = "状态(0未读 1已读)")]
+    public NoticeUserStatusEnum ReadStatus { get; set; } = NoticeUserStatusEnum.UNREAD;
 }

+ 7 - 0
Admin.NET/Admin.NET.Core/Entity/SysTenant.cs

@@ -60,6 +60,13 @@ public class SysTenant : EntityBase
     [MaxLength(256)]
     public string Connection { get; set; }
 
+    /// <summary>
+    /// 数据库标识
+    /// </summary>
+    [SugarColumn(ColumnDescription = "数据库标识", Length = 64)]
+    [MaxLength(64)]
+    public string ConfigId { get; set; }
+
     /// <summary>
     /// 排序
     /// </summary>

+ 1 - 1
Admin.NET/Admin.NET.Core/Entity/SysUser.cs

@@ -20,7 +20,7 @@ public class SysUser : EntityTenant
     [MaxLength(64)]
     [System.Text.Json.Serialization.JsonIgnore]
     [JsonIgnore]
-    public virtual string Password { get; set; }  = CommonConst.SysPassword;
+    public virtual string Password { get; set; }
 
     /// <summary>
     /// 真实姓名

+ 1 - 1
Admin.NET/Admin.NET.Core/Enum/ErrorCodeEnum.cs

@@ -81,7 +81,7 @@ public enum ErrorCodeEnum
     /// <summary>
     /// 非法数据
     /// </summary>
-    [ErrorCodeItemMetadata("非法数据")]
+    [ErrorCodeItemMetadata("非法操作,未登录")]
     D1011,
 
     /// <summary>

+ 1 - 1
Admin.NET/Admin.NET.Core/Hub/Dto/OnlineUserHubOutput.cs

@@ -1,6 +1,6 @@
 namespace Admin.NET.Core;
 
-public class OnlineUserHubOutput
+public class OnlineUserList
 {
     public string RealName { get; set; }
 

+ 9 - 9
Admin.NET/Admin.NET.Core/Hub/IOnlineUserHub.cs

@@ -3,30 +3,30 @@
 public interface IOnlineUserHub
 {
     /// <summary>
-    /// 强制下线
+    /// 在线用户列表
     /// </summary>
     /// <param name="context"></param>
     /// <returns></returns>
-    Task ForceOffline(object context);
+    Task OnlineUserList(OnlineUserList context);
 
     /// <summary>
-    /// 接收消息
+    /// 强制下线
     /// </summary>
     /// <param name="context"></param>
     /// <returns></returns>
-    Task ReceiveMessage(object context);
+    Task ForceOffline(object context);
 
     /// <summary>
-    /// 在线用户变动
+    /// 发布站内消息
     /// </summary>
     /// <param name="context"></param>
     /// <returns></returns>
-    Task OnlineUserChange(OnlineUserHubOutput context);
+    Task PublicNotice(SysNotice context);
 
     /// <summary>
-    /// 组合消息
+    /// 接收消息
     /// </summary>
-    /// <param name="notice"></param>
+    /// <param name="context"></param>
     /// <returns></returns>
-    Task AppendNotice(SysNotice notice);
+    Task ReceiveMessage(object context);
 }

+ 6 - 8
Admin.NET/Admin.NET.Core/Hub/OnlineUserHub.cs

@@ -9,20 +9,17 @@ namespace Admin.NET.Core;
 [MapHub("/hubs/onlineUser")]
 public class OnlineUserHub : Hub<IOnlineUserHub>
 {
+    private const string GROUP_ONLINE = "GROUP_ONLINE_"; // 租户分组前缀
+
     private readonly SqlSugarRepository<SysOnlineUser> _sysOnlineUerRep;
-    private readonly SysCacheService _sysCache;
     private readonly SysMessageService _sysMessageService;
     private readonly IHubContext<OnlineUserHub, IOnlineUserHub> _onlineUserHubContext;
 
-    private const string GROUP_ONLINE = "GROUP_ONLINE_"; // 租户分组前缀
-
     public OnlineUserHub(SqlSugarRepository<SysOnlineUser> sysOnlineUerRep,
-        SysCacheService sysCache,
         SysMessageService sysMessageService,
         IHubContext<OnlineUserHub, IOnlineUserHub> onlineUserHubContext)
     {
         _sysOnlineUerRep = sysOnlineUerRep;
-        _sysCache = sysCache;
         _sysMessageService = sysMessageService;
         _onlineUserHubContext = onlineUserHubContext;
     }
@@ -51,11 +48,12 @@ public class OnlineUserHub : Hub<IOnlineUserHub>
         await _sysOnlineUerRep.InsertAsync(user);
 
         // 以租户Id分组方便区分
-        await _onlineUserHubContext.Groups.AddToGroupAsync(Context.ConnectionId, $"{GROUP_ONLINE}{user.TenantId}");
+        var groupName = $"{GROUP_ONLINE}{user.TenantId}";
+        await _onlineUserHubContext.Groups.AddToGroupAsync(Context.ConnectionId, groupName);
 
         var userList = await _sysOnlineUerRep.AsQueryable().Filter("", true)
             .Where(u => u.TenantId == user.TenantId).Take(10).ToListAsync();
-        await _onlineUserHubContext.Clients.Groups($"{GROUP_ONLINE}{user.TenantId}").OnlineUserChange(new OnlineUserHubOutput
+        await _onlineUserHubContext.Clients.Groups(groupName).OnlineUserList(new OnlineUserList
         {
             RealName = user.RealName,
             Online = true,
@@ -80,7 +78,7 @@ public class OnlineUserHub : Hub<IOnlineUserHub>
         // 通知当前组用户变动
         var userList = await _sysOnlineUerRep.AsQueryable().Filter("", true)
             .Where(u => u.TenantId == user.TenantId).Take(10).ToListAsync();
-        await _onlineUserHubContext.Clients.Groups($"{GROUP_ONLINE}{user.TenantId}").OnlineUserChange(new OnlineUserHubOutput
+        await _onlineUserHubContext.Clients.Groups($"{GROUP_ONLINE}{user.TenantId}").OnlineUserList(new OnlineUserList
         {
             RealName = user.RealName,
             Online = false,

+ 3 - 0
Admin.NET/Admin.NET.Core/Job/OnlineUserJob.cs

@@ -19,6 +19,9 @@ public class OnlineUserJob : ISpareTimeWorker
 
             Console.ForegroundColor = ConsoleColor.Red;
             Console.WriteLine("【" + DateTime.Now + "】服务重启清空在线用户");
+
+            // 缓存多租户
+            await services.GetService<SysTenantService>().UpdateTenantCache();
         });
     }
 }

+ 4 - 4
Admin.NET/Admin.NET.Core/SeedData/SysConfigSeedData.cs

@@ -13,13 +13,13 @@ public class SysConfigSeedData : ISqlSugarEntitySeedData<SysConfig>
     {
         return new[]
         {
-            new SysConfig{ Id=252885263003800, Name="演示环境", Code="sys_demo_env", Value="False", SysFlag=YesNoEnum.Y, Remark="演示环境", Order=1, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
+            new SysConfig{ Id=252885263003800, Name="演示环境", Code="sys_demo", Value="False", SysFlag=YesNoEnum.Y, Remark="演示环境", Order=1, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
             new SysConfig{ Id=252885263003801, Name="默认密码", Code="sys_password", Value="123456", SysFlag=YesNoEnum.Y, Remark="默认密码", Order=2, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
             new SysConfig{ Id=252885263003802, Name="Token过期时间", Code="sys_token_expire", Value="10080", SysFlag=YesNoEnum.Y, Remark="Token过期时间", Order=3, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
-            new SysConfig{ Id=252885263003803, Name="操作日志", Code="sys_op_log", Value="True", SysFlag=YesNoEnum.Y, Remark="开启操作日志", Order=4, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
-            new SysConfig{ Id=252885263003804, Name="单用户登录", Code="sys_single_login", Value="True", SysFlag=YesNoEnum.Y, Remark="开启单用户登录", Order=5, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
+            new SysConfig{ Id=252885263003803, Name="操作日志", Code="sys_oplog", Value="True", SysFlag=YesNoEnum.Y, Remark="开启操作日志", Order=4, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
+            new SysConfig{ Id=252885263003804, Name="单点登录", Code="sys_single_login", Value="True", SysFlag=YesNoEnum.Y, Remark="开启单点登录", Order=5, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
             new SysConfig{ Id=252885263003805, Name="验证码", Code="sys_captcha", Value="True", SysFlag=YesNoEnum.Y, Remark="开启验证码", Order=6, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
-            new SysConfig{ Id=252885263003806, Name="管理员角色编码", Code="sys_admin_role", Value="True", SysFlag=YesNoEnum.Y, Remark="管理员角色编码", Order=7, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
+            new SysConfig{ Id=252885263003806, Name="多库租户", Code="sys_tenant_db", Value="True", SysFlag=YesNoEnum.Y, Remark="开启多库租户", Order=7, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
         };
     }
 }

+ 0 - 2
Admin.NET/Admin.NET.Core/SeedData/SysDictTypeSeedData.cs

@@ -17,8 +17,6 @@ public class SysDictTypeSeedData : ISqlSugarEntitySeedData<SysDictType>
             new SysDictType{ Id=269037954100002, Name="代码生成查询类型", Code="code_gen_query_type", Order=100, Remark="代码生成查询类型", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
             new SysDictType{ Id=269037954100003, Name="代码生成.NET类型", Code="code_gen_net_type", Order=100, Remark="代码生成.NET类型", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
             new SysDictType{ Id=269037954100004, Name="代码生成方式", Code="code_gen_create_type", Order=100, Remark="代码生成方式", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
-
-            new SysDictType{ Id=269037954200001, Name="机构级别", Code="org_level", Order=100, Remark="机构级别", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
         };
     }
 }

+ 67 - 57
Admin.NET/Admin.NET.Core/SeedData/SysMenuSeedData.cs

@@ -15,15 +15,16 @@ public class SysMenuSeedData : ISqlSugarEntitySeedData<SysMenu>
         {
             new SysMenu{ Id=252885263002100, Pid=0, Title="数据面板", Path="/dashboard", Name="dashboard", Component="Layout", Redirect="/dashboard/home", Icon="ele-HomeFilled", Type=MenuTypeEnum.Dir, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=10 },
             new SysMenu{ Id=252885263002110, Pid=252885263002100, Title="工作台", Path="/dashboard/home", Name="home", Component="/home/index", IsAffix=true, Icon="ele-HomeFilled", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002111, Pid=252885263002100, Title="站内信", Path="/dashboard/notice", Name="notice", Component="/home/notice/index", Icon="ele-Bell", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=101 },
 
             new SysMenu{ Id=252885263002200, Pid=0, Title="系统管理", Path="/system", Name="system", Component="Layout", Redirect="/system/user", Icon="ele-Setting", Type=MenuTypeEnum.Dir, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
 
             new SysMenu{ Id=252885263002210, Pid=252885263002200, Title="账号管理", Path="/system/user", Name="sysUser", Component="/system/user/index", Icon="ele-User", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002211, Pid=252885263002210, Title="账号查询", Permission="sysUser:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002212, Pid=252885263002210, Title="账号编辑", Permission="sysUser:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002213, Pid=252885263002210, Title="账号增加", Permission="sysUser:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002214, Pid=252885263002210, Title="账号删除", Permission="sysUser:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002215, Pid=252885263002210, Title="查看详情", Permission="sysUser:detail", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002211, Pid=252885263002210, Title="查询", Permission="sysUser:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002212, Pid=252885263002210, Title="编辑", Permission="sysUser:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002213, Pid=252885263002210, Title="增加", Permission="sysUser:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002214, Pid=252885263002210, Title="删除", Permission="sysUser:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002215, Pid=252885263002210, Title="详情", Permission="sysUser:detail", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
             new SysMenu{ Id=252885263002216, Pid=252885263002210, Title="授权角色", Permission="sysUser:grantRole", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
             new SysMenu{ Id=252885263002217, Pid=252885263002210, Title="重置密码", Permission="sysUser:resetPwd", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
             new SysMenu{ Id=252885263002218, Pid=252885263002210, Title="设置状态", Permission="sysUser:setStatus", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
@@ -31,98 +32,107 @@ public class SysMenuSeedData : ISqlSugarEntitySeedData<SysMenu>
             new SysMenu{ Id=252885263012220, Pid=252885263002210, Title="强制下线", Permission="sysUser:forceOffline", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
 
             new SysMenu{ Id=252885263002220, Pid=252885263002200, Title="角色管理", Path="/system/role", Name="sysRole", Component="/system/role/index", Icon="ele-UserFilled", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=110 },
-            new SysMenu{ Id=252885263002221, Pid=252885263002220, Title="角色查询", Permission="sysRole:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002222, Pid=252885263002220, Title="角色编辑", Permission="sysRole:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002223, Pid=252885263002220, Title="角色增加", Permission="sysRole:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002224, Pid=252885263002220, Title="角色删除", Permission="sysRole:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002221, Pid=252885263002220, Title="查询", Permission="sysRole:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002222, Pid=252885263002220, Title="编辑", Permission="sysRole:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002223, Pid=252885263002220, Title="增加", Permission="sysRole:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002224, Pid=252885263002220, Title="删除", Permission="sysRole:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
             new SysMenu{ Id=252885263002225, Pid=252885263002220, Title="授权菜单", Permission="sysRole:grantMenu", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
             new SysMenu{ Id=252885263002226, Pid=252885263002220, Title="授权数据", Permission="sysRole:grantData", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
             new SysMenu{ Id=252885263002227, Pid=252885263002220, Title="设置状态", Permission="sysRole:setStatus", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
 
             new SysMenu{ Id=252885263002230, Pid=252885263002200, Title="菜单管理", Path="/system/menu", Name="sysMenu", Component="/system/menu/index", Icon="ele-Menu", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=120 },
-            new SysMenu{ Id=252885263002231, Pid=252885263002230, Title="菜单查询", Permission="sysMenu:list", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002232, Pid=252885263002230, Title="菜单编辑", Permission="sysMenu:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002233, Pid=252885263002230, Title="菜单增加", Permission="sysMenu:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002234, Pid=252885263002230, Title="菜单删除", Permission="sysMenu:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002231, Pid=252885263002230, Title="查询", Permission="sysMenu:list", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002232, Pid=252885263002230, Title="编辑", Permission="sysMenu:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002233, Pid=252885263002230, Title="增加", Permission="sysMenu:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002234, Pid=252885263002230, Title="删除", Permission="sysMenu:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
 
             new SysMenu{ Id=252885263002240, Pid=252885263002200, Title="机构管理", Path="/system/org", Name="sysOrg", Component="/system/org/index", Icon="ele-OfficeBuilding", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=130 },
-            new SysMenu{ Id=252885263002241, Pid=252885263002240, Title="机构查询", Permission="sysOrg:list", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002242, Pid=252885263002240, Title="机构编辑", Permission="sysOrg:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002243, Pid=252885263002240, Title="机构增加", Permission="sysOrg:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002244, Pid=252885263002240, Title="机构删除", Permission="sysOrg:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002241, Pid=252885263002240, Title="查询", Permission="sysOrg:list", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002242, Pid=252885263002240, Title="编辑", Permission="sysOrg:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002243, Pid=252885263002240, Title="增加", Permission="sysOrg:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002244, Pid=252885263002240, Title="删除", Permission="sysOrg:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
 
             new SysMenu{ Id=252885263002250, Pid=252885263002200, Title="职位管理", Path="/system/pos", Name="sysPos", Component="/system/pos/index",Icon="ele-Mug", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=140 },
-            new SysMenu{ Id=252885263002251, Pid=252885263002250, Title="职位查询", Permission="sysPos:list", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002252, Pid=252885263002250, Title="职位编辑", Permission="sysPos:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002253, Pid=252885263002250, Title="职位增加", Permission="sysPos:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002254, Pid=252885263002250, Title="职位删除", Permission="sysPos:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002251, Pid=252885263002250, Title="查询", Permission="sysPos:list", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002252, Pid=252885263002250, Title="编辑", Permission="sysPos:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002253, Pid=252885263002250, Title="增加", Permission="sysPos:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002254, Pid=252885263002250, Title="删除", Permission="sysPos:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
 
             new SysMenu{ Id=252885263002260, Pid=252885263002200, Title="个人中心", Path="/system/userCenter", Name="sysUserCenter", Component="/system/user/component/userCenter",Icon="ele-Medal", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=150 },
             new SysMenu{ Id=252885263002261, Pid=252885263002260, Title="修改密码", Permission="sysUser:changePwd", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
             new SysMenu{ Id=252885263002262, Pid=252885263002260, Title="更新信息", Permission="sysUser:updateBase", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
             new SysMenu{ Id=252885263002263, Pid=252885263002260, Title="电子签名", Permission="sysUser:signature", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
 
+            new SysMenu{ Id=252885263002270, Pid=252885263002200, Title="通知公告", Path="/system/notice", Name="sysNotice", Component="/system/notice/index",Icon="ele-Bell", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=160 },
+            new SysMenu{ Id=252885263002271, Pid=252885263002270, Title="查询", Permission="sysNotice:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002272, Pid=252885263002270, Title="编辑", Permission="sysNotice:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002273, Pid=252885263002270, Title="增加", Permission="sysNotice:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002274, Pid=252885263002270, Title="删除", Permission="sysNotice:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002275, Pid=252885263002270, Title="发布", Permission="sysNotice:public", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002276, Pid=252885263002270, Title="撤回", Permission="sysNotice:cancel", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+
             new SysMenu{ Id=252885263002300, Pid=0, Title="平台管理", Path="/platform", Name="platform", Component="Layout", Redirect="/platform/tenant", Icon="ele-Menu", Type=MenuTypeEnum.Dir, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=200 },
 
             new SysMenu{ Id=252885263002310, Pid=252885263002300, Title="租户管理", Path="/platform/tenant", Name="sysTenant", Component="/system/tenant/index", Icon="ele-School", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002311, Pid=252885263002310, Title="租户查询", Permission="sysTenant:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002312, Pid=252885263002310, Title="租户编辑", Permission="sysTenant:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002313, Pid=252885263002310, Title="租户增加", Permission="sysTenant:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002314, Pid=252885263002310, Title="租户删除", Permission="sysTenant:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002311, Pid=252885263002310, Title="查询", Permission="sysTenant:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002312, Pid=252885263002310, Title="编辑", Permission="sysTenant:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002313, Pid=252885263002310, Title="增加", Permission="sysTenant:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002314, Pid=252885263002310, Title="删除", Permission="sysTenant:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
             new SysMenu{ Id=252885263002315, Pid=252885263002310, Title="授权菜单", Permission="sysTenant:grantMenu", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
             new SysMenu{ Id=252885263002316, Pid=252885263002310, Title="重置密码", Permission="sysTenant:resetPwd", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002317, Pid=252885263002310, Title="生成库", Permission="sysTenant:createDb", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
 
             new SysMenu{ Id=252885263002320, Pid=252885263002300, Title="参数配置", Path="/platform/config", Name="sysConfig", Component="/system/config/index", Icon="ele-DocumentCopy", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=110 },
-            new SysMenu{ Id=252885263002321, Pid=252885263002320, Title="配置查询", Permission="sysConfig:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002322, Pid=252885263002320, Title="配置编辑", Permission="sysConfig:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002323, Pid=252885263002320, Title="配置增加", Permission="sysConfig:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002324, Pid=252885263002320, Title="配置删除", Permission="sysConfig:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002321, Pid=252885263002320, Title="查询", Permission="sysConfig:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002322, Pid=252885263002320, Title="编辑", Permission="sysConfig:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002323, Pid=252885263002320, Title="增加", Permission="sysConfig:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002324, Pid=252885263002320, Title="删除", Permission="sysConfig:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
 
             new SysMenu{ Id=252885263002330, Pid=252885263002300, Title="字典管理", Path="/platform/dict", Name="sysDict", Component="/system/dict/index", Icon="ele-Collection", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=120 },
-            new SysMenu{ Id=252885263002331, Pid=252885263002330, Title="字典查询", Permission="sysDictType:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002332, Pid=252885263002330, Title="字典编辑", Permission="sysDictType:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002333, Pid=252885263002330, Title="字典增加", Permission="sysDictType:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002334, Pid=252885263002330, Title="字典删除", Permission="sysDictType:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002331, Pid=252885263002330, Title="查询", Permission="sysDictType:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002332, Pid=252885263002330, Title="编辑", Permission="sysDictType:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002333, Pid=252885263002330, Title="增加", Permission="sysDictType:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002334, Pid=252885263002330, Title="删除", Permission="sysDictType:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
 
             new SysMenu{ Id=252885263002340, Pid=252885263002300, Title="任务调度", Path="/platform/timer", Name="sysTimer", Component="/system/timer/index", Icon="ele-AlarmClock", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=130 },
-            new SysMenu{ Id=252885263002341, Pid=252885263002340, Title="任务查询", Permission="sysTimer:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002342, Pid=252885263002340, Title="任务编辑", Permission="sysTimer:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002343, Pid=252885263002340, Title="任务增加", Permission="sysTimer:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002344, Pid=252885263002340, Title="任务删除", Permission="sysTimer:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002345, Pid=252885263002340, Title="设置状态", Permission="sysTimer:setStatus", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002341, Pid=252885263002340, Title="查询", Permission="sysTimer:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002342, Pid=252885263002340, Title="编辑", Permission="sysTimer:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002343, Pid=252885263002340, Title="增加", Permission="sysTimer:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002344, Pid=252885263002340, Title="删除", Permission="sysTimer:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002345, Pid=252885263002340, Title="状态", Permission="sysTimer:setStatus", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
 
             new SysMenu{ Id=252885263002360, Pid=252885263002300, Title="系统监控", Path="/platform/server", Name="sysServer", Component="/system/server/index", Icon="ele-Monitor", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=140 },
 
             new SysMenu{ Id=252885263002370, Pid=252885263002300, Title="缓存管理", Path="/platform/cache", Name="sysCache", Component="/system/cache/index", Icon="ele-Loading", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=150 },
-            new SysMenu{ Id=252885263002371, Pid=252885263002370, Title="缓存查询", Permission="sysCache:keyList", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002372, Pid=252885263002370, Title="缓存删除", Permission="sysCache:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002371, Pid=252885263002370, Title="查询", Permission="sysCache:keyList", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002372, Pid=252885263002370, Title="删除", Permission="sysCache:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
 
             new SysMenu{ Id=252885263002380, Pid=252885263002300, Title="行政区域", Path="/platform/region", Name="sysRegion", Component="/system/region/index", Icon="ele-LocationInformation", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=160 },
-            new SysMenu{ Id=252885263002381, Pid=252885263002380, Title="区域查询", Permission="sysRegion:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002382, Pid=252885263002380, Title="区域编辑", Permission="sysRegion:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002383, Pid=252885263002380, Title="区域增加", Permission="sysRegion:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002384, Pid=252885263002380, Title="区域删除", Permission="sysRegion:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002385, Pid=252885263002380, Title="更新同步", Permission="sysRegion:sync", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002381, Pid=252885263002380, Title="查询", Permission="sysRegion:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002382, Pid=252885263002380, Title="编辑", Permission="sysRegion:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002383, Pid=252885263002380, Title="增加", Permission="sysRegion:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002384, Pid=252885263002380, Title="删除", Permission="sysRegion:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002385, Pid=252885263002380, Title="同步", Permission="sysRegion:sync", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
 
             new SysMenu{ Id=252885263002390, Pid=252885263002300, Title="文件管理", Path="/platform/file", Name="sysFile", Component="/system/file/index", Icon="ele-Document", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=170 },
-            new SysMenu{ Id=252885263002391, Pid=252885263002390, Title="文件查询", Permission="sysFile:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002392, Pid=252885263002390, Title="文件上传", Permission="sysFile:upload", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002393, Pid=252885263002390, Title="文件下载", Permission="sysFile:download", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002394, Pid=252885263002390, Title="文件删除", Permission="sysFile:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002391, Pid=252885263002390, Title="查询", Permission="sysFile:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002392, Pid=252885263002390, Title="上传", Permission="sysFile:upload", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002393, Pid=252885263002390, Title="下载", Permission="sysFile:download", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002394, Pid=252885263002390, Title="删除", Permission="sysFile:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
 
             new SysMenu{ Id=252885263002500, Pid=0, Title="日志管理", Path="/log", Name="log", Component="Layout", Redirect="/log/vislog", Icon="ele-DocumentCopy", Type=MenuTypeEnum.Dir, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=300 },
             new SysMenu{ Id=252885263002510, Pid=252885263002500, Title="访问日志", Path="/log/vislog", Name="sysVislog", Component="/system/log/vislog/index", Icon="ele-Document", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002511, Pid=252885263002510, Title="日志查询", Permission="sysVislog:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002512, Pid=252885263002510, Title="日志清空", Permission="sysVislog:clear", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002511, Pid=252885263002510, Title="查询", Permission="sysVislog:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002512, Pid=252885263002510, Title="清空", Permission="sysVislog:clear", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
             new SysMenu{ Id=252885263002520, Pid=252885263002500, Title="操作日志", Path="/log/oplog", Name="sysOplog", Component="/system/log/oplog/index", Icon="ele-Document", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=110 },
-            new SysMenu{ Id=252885263002521, Pid=252885263002520, Title="日志查询", Permission="sysOplog:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002522, Pid=252885263002520, Title="日志清空", Permission="sysOplog:clear", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002521, Pid=252885263002520, Title="查询", Permission="sysOplog:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002522, Pid=252885263002520, Title="清空", Permission="sysOplog:clear", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
             new SysMenu{ Id=252885263002530, Pid=252885263002500, Title="异常日志", Path="/log/exlog", Name="sysExlog", Component="/system/log/exlog/index", Icon="ele-Document", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=120 },
-            new SysMenu{ Id=252885263002531, Pid=252885263002530, Title="日志查询", Permission="sysExlog:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002532, Pid=252885263002530, Title="日志清空", Permission="sysExlog:clear", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002531, Pid=252885263002530, Title="查询", Permission="sysExlog:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002532, Pid=252885263002530, Title="清空", Permission="sysExlog:clear", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
             new SysMenu{ Id=252885263002540, Pid=252885263002500, Title="差异日志", Path="/log/difflog", Name="sysDifflog", Component="/system/log/difflog/index", Icon="ele-Document", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=130 },
-            new SysMenu{ Id=252885263002541, Pid=252885263002540, Title="日志查询", Permission="sysDifflog:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263002542, Pid=252885263002540, Title="日志清空", Permission="sysDifflog:clear", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002541, Pid=252885263002540, Title="查询", Permission="sysDifflog:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
+            new SysMenu{ Id=252885263002542, Pid=252885263002540, Title="清空", Permission="sysDifflog:clear", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
 
             new SysMenu{ Id=252885263002600, Pid=0, Title="开发工具", Path="/develop", Name="develop", Component="Layout", Redirect="/develop/api", Icon="ele-Cpu", Type=MenuTypeEnum.Dir, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=400 },
             new SysMenu{ Id=252885263002610, Pid=252885263002600, Title="系统接口", Path="/develop/api", Name="sysApi", Component="layout/routerView/iframe", IsIframe=true, OutLink="https://localhost:44326/api/", Icon="ele-Help", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },

+ 1 - 3
Admin.NET/Admin.NET.Core/SeedData/SysOrgSeedData.cs

@@ -13,7 +13,7 @@ public class SysOrgSeedData : ISqlSugarEntitySeedData<SysOrg>
     {
         return new[]
         {
-            new SysOrg{ Id=252885263003720, Pid=0, Name="大名科技有限公司", Code="1001", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="大名科技", TenantId=142307070918780 },
+            new SysOrg{ Id=252885263003720, Pid=0, Name="大名科技", Code="1001", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="大名科技", TenantId=142307070918780 },
             new SysOrg{ Id=252885263003721, Pid=252885263003720, Name="市场部", Code="100101", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="市场部", TenantId=142307070918780 },
             new SysOrg{ Id=252885263003722, Pid=252885263003720, Name="研发部", Code="100102", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="研发部", TenantId=142307070918780 },
             new SysOrg{ Id=252885263003723, Pid=252885263003720, Name="财务部", Code="100103", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="财务部", TenantId=142307070918780 },
@@ -29,8 +29,6 @@ public class SysOrgSeedData : ISqlSugarEntitySeedData<SysOrg>
             new SysOrg{ Id=252885263003741, Pid=252885263003740, Name="市场部", Code="100301", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="市场部", TenantId=142307070918780 },
             new SysOrg{ Id=252885263003742, Pid=252885263003740, Name="研发部", Code="100302", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="市场部", TenantId=142307070918780 },
             new SysOrg{ Id=252885263003743, Pid=252885263003740, Name="财务部", Code="100303", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="市场部", TenantId=142307070918780 },
-
-            new SysOrg{ Id=252885263004720, Pid=0, Name="租户1公司", Code="2001", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="租户1公司" , TenantId=142307070918781 },
         };
     }
 }

+ 0 - 16
Admin.NET/Admin.NET.Core/SeedData/SysPosSeedData.cs

@@ -28,22 +28,6 @@ public class SysPosSeedData : ISqlSugarEntitySeedData<SysPos>
             new SysPos{ Id=252885263003732, Name="副科长", Code="fkz", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="副科长", TenantId=142307070918780 },
             new SysPos{ Id=252885263003733, Name="职员", Code="zy", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="职员", TenantId=142307070918780 },
             new SysPos{ Id=252885263003734, Name="其他", Code="qt", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="其他", TenantId=142307070918780 },
-
-            new SysPos{ Id=252885263004720, Name="党委书记", Code="dwsj", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="党委书记", TenantId=142307070918781 },
-            new SysPos{ Id=252885263004721, Name="董事长", Code="dsz", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="董事长", TenantId=142307070918781 },
-            new SysPos{ Id=252885263004722, Name="副董事长", Code="fdsz", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="副董事长", TenantId=142307070918781 },
-            new SysPos{ Id=252885263004723, Name="总经理", Code="zjl", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="总经理", TenantId=142307070918781 },
-            new SysPos{ Id=252885263004724, Name="副总经理", Code="fzjl", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="副总经理", Status=StatusEnum.Disable, TenantId=142307070918781 },
-            new SysPos{ Id=252885263004725, Name="部门经理", Code="bmjl", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="部门经理", TenantId=142307070918781 },
-            new SysPos{ Id=252885263004726, Name="部门副经理", Code="bmfjl", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="部门副经理", TenantId=142307070918781 },
-            new SysPos{ Id=252885263004727, Name="主任", Code="zr", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="主任", TenantId=142307070918781 },
-            new SysPos{ Id=252885263004728, Name="副主任", Code="fzr", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="副主任", TenantId=142307070918781 },
-            new SysPos{ Id=252885263004729, Name="局长", Code="jz", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="局长", TenantId=142307070918781 },
-            new SysPos{ Id=252885263004730, Name="副局长", Code="fjz", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="副局长", TenantId=142307070918781 },
-            new SysPos{ Id=252885263004731, Name="科长", Code="kz", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="科长", TenantId=142307070918781 },
-            new SysPos{ Id=252885263004732, Name="副科长", Code="fkz", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="副科长", TenantId=142307070918781 },
-            new SysPos{ Id=252885263004733, Name="职员", Code="zy", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="职员", TenantId=142307070918781 },
-            new SysPos{ Id=252885263004734, Name="其他", Code="qt", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="其他", TenantId=142307070918781 },
         };
     }
 }

+ 11 - 60
Admin.NET/Admin.NET.Core/SeedData/SysRoleMenuSeedData.cs

@@ -16,7 +16,7 @@ public class SysRoleMenuSeedData : ISqlSugarEntitySeedData<SysRoleMenu>
             // 数据面板【admin/252885263003721】
             new SysRoleMenu{ Id=252885263003000, RoleId=252885263003721, MenuId=252885263002100 },
             new SysRoleMenu{ Id=252885263003001, RoleId=252885263003721, MenuId=252885263002110 },
-            //new SysRoleMenu{ Id=252885263003002, RoleId=252885263003721, MenuId=252885263002111 },
+            new SysRoleMenu{ Id=252885263003002, RoleId=252885263003721, MenuId=252885263002111 },
 
             // 系统管理
             new SysRoleMenu{ Id=252885263003100, RoleId=252885263003721, MenuId=252885263002200 },
@@ -64,6 +64,14 @@ public class SysRoleMenuSeedData : ISqlSugarEntitySeedData<SysRoleMenu>
             new SysRoleMenu{ Id=252885263003152, RoleId=252885263003721, MenuId=252885263002261 },
             new SysRoleMenu{ Id=252885263003153, RoleId=252885263003721, MenuId=252885263002262 },
             new SysRoleMenu{ Id=252885263003154, RoleId=252885263003721, MenuId=252885263002263 },
+            // 通知公告
+            new SysRoleMenu{ Id=252885263003161, RoleId=252885263003721, MenuId=252885263002270 },
+            new SysRoleMenu{ Id=252885263003162, RoleId=252885263003721, MenuId=252885263002271 },
+            new SysRoleMenu{ Id=252885263003163, RoleId=252885263003721, MenuId=252885263002272 },
+            new SysRoleMenu{ Id=252885263003164, RoleId=252885263003721, MenuId=252885263002273 },
+            new SysRoleMenu{ Id=252885263003165, RoleId=252885263003721, MenuId=252885263002274 },
+            new SysRoleMenu{ Id=252885263003166, RoleId=252885263003721, MenuId=252885263002275 },
+            new SysRoleMenu{ Id=252885263003167, RoleId=252885263003721, MenuId=252885263002276 },
 
             // 平台管理
             new SysRoleMenu{ Id=252885263003200, RoleId=252885263003721, MenuId=252885263002300 },
@@ -79,11 +87,6 @@ public class SysRoleMenuSeedData : ISqlSugarEntitySeedData<SysRoleMenu>
             new SysRoleMenu{ Id=252885263003213, RoleId=252885263003721, MenuId=252885263002332 },
             new SysRoleMenu{ Id=252885263003214, RoleId=252885263003721, MenuId=252885263002333 },
             new SysRoleMenu{ Id=252885263003215, RoleId=252885263003721, MenuId=252885263002334 },
-            //// 在线用户
-            //new SysRoleMenu{ Id=252885263003221, RoleId=252885263003721, MenuId=252885263002350 },
-            //new SysRoleMenu{ Id=252885263003222, RoleId=252885263003721, MenuId=252885263002351 },
-            //new SysRoleMenu{ Id=252885263003223, RoleId=252885263003721, MenuId=252885263002352 },
-            //new SysRoleMenu{ Id=252885263003224, RoleId=252885263003721, MenuId=252885263002353 },
             // 系统监控
             new SysRoleMenu{ Id=252885263003231, RoleId=252885263003721, MenuId=252885263002360 },
             // 缓存管理
@@ -123,7 +126,7 @@ public class SysRoleMenuSeedData : ISqlSugarEntitySeedData<SysRoleMenu>
             // 数据面板【user1/252885263003722】
             new SysRoleMenu{ Id=252885263004000, RoleId=252885263003722, MenuId=252885263002100 },
             new SysRoleMenu{ Id=252885263004001, RoleId=252885263003722, MenuId=252885263002110 },
-            //new SysRoleMenu{ Id=252885263004002, RoleId=252885263003722, MenuId=252885263002111 },
+            new SysRoleMenu{ Id=252885263004002, RoleId=252885263003722, MenuId=252885263002111 },
             // 系统管理
             new SysRoleMenu{ Id=252885263004100, RoleId=252885263003722, MenuId=252885263002200 },
             // 个人中心
@@ -135,7 +138,7 @@ public class SysRoleMenuSeedData : ISqlSugarEntitySeedData<SysRoleMenu>
             // 数据面板【user3/252885263003724】
             new SysRoleMenu{ Id=252885263005000, RoleId=252885263003724, MenuId=252885263002100 },
             new SysRoleMenu{ Id=252885263005001, RoleId=252885263003724, MenuId=252885263002110 },
-            //new SysRoleMenu{ Id=252885263005002, RoleId=252885263003724, MenuId=252885263002111 },
+            new SysRoleMenu{ Id=252885263005002, RoleId=252885263003724, MenuId=252885263002111 },
             // 系统管理
             new SysRoleMenu{ Id=252885263005100, RoleId=252885263003724, MenuId=252885263002200 },
             // 个人中心
@@ -143,58 +146,6 @@ public class SysRoleMenuSeedData : ISqlSugarEntitySeedData<SysRoleMenu>
             new SysRoleMenu{ Id=252885263005152, RoleId=252885263003724, MenuId=252885263002261 },
             new SysRoleMenu{ Id=252885263005153, RoleId=252885263003724, MenuId=252885263002262 },
             new SysRoleMenu{ Id=252885263005154, RoleId=252885263003724, MenuId=252885263002263 },
-
-            // 其他租户
-            // 数据面板【admin1/252885263004721】
-            new SysRoleMenu{ Id=252885263101000, RoleId=252885263004721, MenuId=252885263002100 },
-            new SysRoleMenu{ Id=252885263101001, RoleId=252885263004721, MenuId=252885263002110 },
-            //new SysRoleMenu{ Id=252885263101002, RoleId=252885263004721, MenuId=252885263002111 },
-            // 系统管理
-            new SysRoleMenu{ Id=252885263101100, RoleId=252885263004721, MenuId=252885263002200 },
-            // 账号管理
-            new SysRoleMenu{ Id=252885263101101, RoleId=252885263004721, MenuId=252885263002210 },
-            new SysRoleMenu{ Id=252885263101102, RoleId=252885263004721, MenuId=252885263002211 },
-            new SysRoleMenu{ Id=252885263101103, RoleId=252885263004721, MenuId=252885263002212 },
-            new SysRoleMenu{ Id=252885263101104, RoleId=252885263004721, MenuId=252885263002213 },
-            new SysRoleMenu{ Id=252885263101105, RoleId=252885263004721, MenuId=252885263002214 },
-            new SysRoleMenu{ Id=252885263101106, RoleId=252885263004721, MenuId=252885263002215 },
-            new SysRoleMenu{ Id=252885263101107, RoleId=252885263004721, MenuId=252885263002216 },
-            new SysRoleMenu{ Id=252885263101108, RoleId=252885263004721, MenuId=252885263002217 },
-            new SysRoleMenu{ Id=252885263101109, RoleId=252885263004721, MenuId=252885263002218 },
-            new SysRoleMenu{ Id=252885263103110, RoleId=252885263004721, MenuId=252885263002219 },
-            new SysRoleMenu{ Id=252885263113111, RoleId=252885263003721, MenuId=252885263012220 },
-            // 角色管理
-            new SysRoleMenu{ Id=252885263103111, RoleId=252885263004721, MenuId=252885263002220 },
-            new SysRoleMenu{ Id=252885263103112, RoleId=252885263004721, MenuId=252885263002221 },
-            new SysRoleMenu{ Id=252885263103113, RoleId=252885263004721, MenuId=252885263002222 },
-            new SysRoleMenu{ Id=252885263103114, RoleId=252885263004721, MenuId=252885263002223 },
-            new SysRoleMenu{ Id=252885263103115, RoleId=252885263004721, MenuId=252885263002224 },
-            new SysRoleMenu{ Id=252885263103116, RoleId=252885263004721, MenuId=252885263002225 },
-            new SysRoleMenu{ Id=252885263103117, RoleId=252885263004721, MenuId=252885263002226 },
-            new SysRoleMenu{ Id=252885263103118, RoleId=252885263004721, MenuId=252885263002227 },
-            // 菜单管理
-            new SysRoleMenu{ Id=252885263103121, RoleId=252885263004721, MenuId=252885263002230 },
-            new SysRoleMenu{ Id=252885263103122, RoleId=252885263004721, MenuId=252885263002231 },
-            new SysRoleMenu{ Id=252885263103123, RoleId=252885263004721, MenuId=252885263002232 },
-            new SysRoleMenu{ Id=252885263103124, RoleId=252885263004721, MenuId=252885263002233 },
-            new SysRoleMenu{ Id=252885263103125, RoleId=252885263004721, MenuId=252885263002234 },
-            // 机构管理
-            new SysRoleMenu{ Id=252885263103131, RoleId=252885263004721, MenuId=252885263002240 },
-            new SysRoleMenu{ Id=252885263103132, RoleId=252885263004721, MenuId=252885263002241 },
-            new SysRoleMenu{ Id=252885263103133, RoleId=252885263004721, MenuId=252885263002242 },
-            new SysRoleMenu{ Id=252885263103134, RoleId=252885263004721, MenuId=252885263002243 },
-            new SysRoleMenu{ Id=252885263103135, RoleId=252885263004721, MenuId=252885263002244 },
-            // 职位管理
-            new SysRoleMenu{ Id=252885263103141, RoleId=252885263004721, MenuId=252885263002250 },
-            new SysRoleMenu{ Id=252885263103142, RoleId=252885263004721, MenuId=252885263002251 },
-            new SysRoleMenu{ Id=252885263103143, RoleId=252885263004721, MenuId=252885263002252 },
-            new SysRoleMenu{ Id=252885263103144, RoleId=252885263004721, MenuId=252885263002253 },
-            new SysRoleMenu{ Id=252885263103145, RoleId=252885263004721, MenuId=252885263002254 },
-            // 个人中心
-            new SysRoleMenu{ Id=252885263103151, RoleId=252885263004721, MenuId=252885263002260 },
-            new SysRoleMenu{ Id=252885263103152, RoleId=252885263004721, MenuId=252885263002261 },
-            new SysRoleMenu{ Id=252885263103153, RoleId=252885263004721, MenuId=252885263002262 },
-            new SysRoleMenu{ Id=252885263103154, RoleId=252885263004721, MenuId=252885263002263 },
         };
     }
 }

+ 0 - 6
Admin.NET/Admin.NET.Core/SeedData/SysRoleSeedData.cs

@@ -18,12 +18,6 @@ public class SysRoleSeedData : ISqlSugarEntitySeedData<SysRole>
             new SysRole{ Id=252885263003723, Name="本部门数据", DataScope=DataScopeEnum.Dept, Code="sys_dept", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="本部门数据", TenantId=142307070918780 },
             new SysRole{ Id=252885263003724, Name="仅本人数据", DataScope=DataScopeEnum.Self, Code="sys_self", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="仅本人数据", TenantId=142307070918780 },
             new SysRole{ Id=252885263003725, Name="自定义数据", DataScope=DataScopeEnum.Define, Code="sys_define", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="自定义数据", TenantId=142307070918780 },
-
-            new SysRole{ Id=252885263004721, Name="系统管理员", DataScope=DataScopeEnum.All, Code="sys_admin", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="系统管理员", TenantId=142307070918781 },
-            new SysRole{ Id=252885263004722, Name="本部门及以下数据", DataScope=DataScopeEnum.DeptChild, Code="sys_deptChild", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="本部门及以下数据", TenantId=142307070918781 },
-            new SysRole{ Id=252885263004723, Name="本部门数据", DataScope=DataScopeEnum.Dept, Code="sys_dept", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="本部门数据", TenantId=142307070918781 },
-            new SysRole{ Id=252885263004724, Name="仅本人数据", DataScope=DataScopeEnum.Self, Code="sys_self", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="仅本人数据", TenantId=142307070918781 },
-            new SysRole{ Id=252885263004725, Name="自定义数据", DataScope=DataScopeEnum.Define, Code="sys_define", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="自定义数据", TenantId=142307070918781 },
         };
     }
 }

+ 1 - 2
Admin.NET/Admin.NET.Core/SeedData/SysTenantSeedData.cs

@@ -13,8 +13,7 @@ public class SysTenantSeedData : ISqlSugarEntitySeedData<SysTenant>
     {
         return new[]
         {
-            new SysTenant{ Id=142307070918780, Name="系统默认", AdminName="Administrator", Host="www.dilon.vip", Email="zuohuaijun@163.com", Phone="18020030720", TenantType=TenantTypeEnum.Db, DbType=SqlSugar.DbType.Sqlite, Connection="DataSource=./Admin.NET.db", Remark="系统默认", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
-            new SysTenant{ Id=142307070918781, Name="测试租户", AdminName="TestAdmin", Host="www.dilon.top", Email="515096995@qq.com", Phone="18020030720", TenantType=TenantTypeEnum.Db, DbType=SqlSugar.DbType.Sqlite, Connection="DataSource=./Test.db", Remark="测试租户", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
+            new SysTenant{ Id=142307070918780, Name="系统默认", AdminName="Administrator", Host="www.dilon.vip", Email="zuohuaijun@163.com", Phone="18020030720", TenantType=TenantTypeEnum.Db, DbType=SqlSugar.DbType.Sqlite, Connection="DataSource=./Admin.NET.db", ConfigId=SqlSugarConst.ConfigId, Remark="系统默认", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
         };
     }
 }

+ 0 - 2
Admin.NET/Admin.NET.Core/SeedData/SysUserRoleSeedData.cs

@@ -18,8 +18,6 @@ public class SysUserRoleSeedData : ISqlSugarEntitySeedData<SysUserRole>
             new SysUserRole{ Id=252885263003003, UserId=252885263003723, RoleId=252885263003723 },
             new SysUserRole{ Id=252885263003004, UserId=252885263003724, RoleId=252885263003724 },
             new SysUserRole{ Id=252885263003005, UserId=252885263003725, RoleId=252885263003725 },
-
-            new SysUserRole{ Id=252885263004001, UserId=252885263004721, RoleId=252885263004721 }
         };
     }
 }

+ 0 - 2
Admin.NET/Admin.NET.Core/SeedData/SysUserSeedData.cs

@@ -19,8 +19,6 @@ public class SysUserSeedData : ISqlSugarEntitySeedData<SysUser>
             new SysUser{ Id=252885263003723, Account="user2", Password="e10adc3949ba59abbe56e057f20f883e", NickName="部门职员", RealName="部门职员", Phone="18020030720", Birthday=DateTime.Parse("1986-06-28"), Sex=GenderEnum.Female, AccountType=AccountTypeEnum.User, Remark="部门职员", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrgId=252885263003722, PosId=252885263003729, TenantId=142307070918780 },
             new SysUser{ Id=252885263003724, Account="user3", Password="e10adc3949ba59abbe56e057f20f883e", NickName="普通用户", RealName="普通用户", Phone="18020030720", Birthday=DateTime.Parse("1986-06-28"), Sex=GenderEnum.Female, AccountType=AccountTypeEnum.User, Remark="普通用户", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrgId=252885263003723, PosId=252885263003729, TenantId=142307070918780 },
             new SysUser{ Id=252885263003725, Account="user4", Password="e10adc3949ba59abbe56e057f20f883e", NickName="其他", RealName="其他", Phone="18020030720", Birthday=DateTime.Parse("1986-06-28"), Sex=GenderEnum.Female, AccountType=AccountTypeEnum.None, Remark="普通用户", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrgId=252885263003724, PosId=252885263003729, TenantId=142307070918780 },
-
-            new SysUser{ Id=252885263004721, Account="admin1", Password="e10adc3949ba59abbe56e057f20f883e", NickName="系统管理员", RealName="系统管理员", Phone="18020030720", Birthday=DateTime.Parse("1986-06-28"), Sex=GenderEnum.Male, AccountType=AccountTypeEnum.Admin, Remark="系统管理员", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrgId=252885263004720, PosId=252885263004721, TenantId=142307070918781 }
         };
     }
 }

+ 5 - 0
Admin.NET/Admin.NET.Core/Service/Auth/Dto/LoginInput.cs

@@ -28,4 +28,9 @@ public class LoginInput
     /// 验证码
     /// </summary>
     public string Code { get; set; }
+
+    /// <summary>
+    /// 租户Id
+    /// </summary>
+    public long TenantId { get; set; }
 }

+ 41 - 10
Admin.NET/Admin.NET.Core/Service/Auth/SysAuthService.cs

@@ -15,9 +15,10 @@ public class SysAuthService : IDynamicApiController, ITransient
     private readonly RefreshTokenOptions _refreshTokenOptions;
     private readonly IHttpContextAccessor _httpContextAccessor;
     private readonly IEventPublisher _eventPublisher;
-    private readonly SysUserService _sysUserService;
     private readonly SysMenuService _sysMenuService;
+    private readonly SysTenantService _sysTenantService;
     private readonly SysOnlineUserService _sysOnlineUserService;
+    private readonly SysConfigService _sysConfigService;
     private readonly IMemoryCache _cache;
     private readonly ICaptcha _captcha;
 
@@ -26,9 +27,10 @@ public class SysAuthService : IDynamicApiController, ITransient
         IOptions<RefreshTokenOptions> refreshTokenOptions,
         IHttpContextAccessor httpContextAccessor,
         IEventPublisher eventPublisher,
-        SysUserService sysUserService,
         SysMenuService sysMenuService,
+        SysTenantService sysTenantService,
         SysOnlineUserService sysOnlineUserService,
+        SysConfigService sysConfigService,
         IMemoryCache cache,
         ICaptcha captcha)
     {
@@ -37,9 +39,10 @@ public class SysAuthService : IDynamicApiController, ITransient
         _httpContextAccessor = httpContextAccessor;
         _refreshTokenOptions = refreshTokenOptions.Value;
         _eventPublisher = eventPublisher;
-        _sysUserService = sysUserService;
         _sysMenuService = sysMenuService;
+        _sysTenantService = sysTenantService;
         _sysOnlineUserService = sysOnlineUserService;
+        _sysConfigService = sysConfigService;
         _cache = cache;
         _captcha = captcha;
     }
@@ -55,8 +58,12 @@ public class SysAuthService : IDynamicApiController, ITransient
     [SuppressMonitor]
     public async Task<LoginOutput> Login([Required] LoginInput input)
     {
+        // 记录当前租户
+        _userManager.TenantId = input.TenantId;
+
         // 判断验证码
-        if (!_captcha.Validate(input.CodeId.ToString(), input.Code))
+        var captchaEnabled = await GetCaptchaFlag();
+        if (captchaEnabled && !_captcha.Validate(input.CodeId.ToString(), input.Code))
             throw Oops.Oh(ErrorCodeEnum.D0009);
 
         var encryptPasswod = MD5Encryption.Encrypt(input.Password);
@@ -106,7 +113,7 @@ public class SysAuthService : IDynamicApiController, ITransient
     [HttpGet("/userInfo")]
     public async Task<LoginUserOutput> GetUserInfo()
     {
-        var user = _userManager.User;
+        var user = await _sysUserRep.GetFirstAsync(u => u.Id == _userManager.UserId);
         if (user == null)
             throw Oops.Oh(ErrorCodeEnum.D1011);
 
@@ -153,7 +160,7 @@ public class SysAuthService : IDynamicApiController, ITransient
     /// </summary>
     /// <param name="accessToken"></param>
     /// <returns></returns>
-    [HttpPost("/getRefreshToken")]
+    [HttpPost("/refreshToken")]
     public string RefreshToken([Required] string accessToken)
     {
         return JWTEncryption.GenerateRefreshToken(accessToken, _refreshTokenOptions.ExpiredTime);
@@ -165,8 +172,7 @@ public class SysAuthService : IDynamicApiController, ITransient
     [HttpPost("/logout")]
     public async void Logout()
     {
-        var user = _userManager.User;
-        if (user == null)
+        if (string.IsNullOrWhiteSpace(_userManager.Account))
             throw Oops.Oh(ErrorCodeEnum.D1011);
 
         // 设置响应报文头
@@ -179,11 +185,23 @@ public class SysAuthService : IDynamicApiController, ITransient
             Message = "退出",
             VisType = LoginTypeEnum.Logout,
             Ip = _httpContextAccessor.HttpContext.GetRemoteIpAddressToIPv4(),
-            Account = user.Account,
-            RealName = user.RealName
+            Account = _userManager.Account,
+            RealName = _userManager.RealName
         });
     }
 
+    /// <summary>
+    /// 是否启用验证码
+    /// </summary>
+    /// <returns></returns>
+    [HttpGet("/captchaFlag")]
+    [AllowAnonymous]
+    [SuppressMonitor]
+    public async Task<bool> GetCaptchaFlag()
+    {
+        return await _sysConfigService.GetConfigValue<bool>(CommonConst.SysCaptcha);
+    }
+
     /// <summary>
     /// 生成图片验证码
     /// </summary>
@@ -198,6 +216,19 @@ public class SysAuthService : IDynamicApiController, ITransient
         return new { Id = codeId, Img = captcha.Base64 };
     }
 
+    /// <summary>
+    /// 是否启用多库租户
+    /// </summary>
+    /// <returns></returns>
+    [HttpGet("/tenantDbList")]
+    [AllowAnonymous]
+    [SuppressMonitor]
+    public async Task<List<SysTenant>> GetTenantDbList()
+    {
+        var tenantDbEnabled = await _sysConfigService.GetConfigValue<bool>(CommonConst.SysTenantDb);
+        return tenantDbEnabled ? await _sysTenantService.GetTenantDbList() : new List<SysTenant>();
+    }
+
     /// <summary>
     /// Swagger登录检查
     /// </summary>

+ 5 - 108
Admin.NET/Admin.NET.Core/Service/Cache/SysCacheService.cs

@@ -98,116 +98,13 @@ public class SysCacheService : IDynamicApiController, ISingleton
     }
 
     /// <summary>
-    /// 获取机构Id集合
+    /// 获取缓存值
     /// </summary>
-    /// <param name="userId"></param>
-    /// <returns></returns>
-    [NonAction]
-    public List<long> GetOrgIdList(long userId)
-    {
-        var key = CacheConst.KeyOrgIdList + userId;
-        return _cache.Get<List<long>>(key);
-    }
-
-    /// <summary>
-    /// 缓存机构Id集合
-    /// </summary>
-    /// <param name="userId"></param>
-    /// <param name="orgIdList"></param>
-    /// <returns></returns>
-    [NonAction]
-    public bool SetOrgIdList(long userId, List<long> orgIdList)
-    {
-        var key = CacheConst.KeyOrgIdList + userId;
-        return _cache.Set(key, orgIdList);
-    }
-
-    /// <summary>
-    /// 获取权限集合(按钮)
-    /// </summary>
-    /// <param name="userId"></param>
-    /// <returns></returns>
-    [NonAction]
-    public List<string> GetPermission(long userId)
-    {
-        var key = CacheConst.KeyPermission + userId;
-        return _cache.Get<List<string>>(key);
-    }
-
-    /// <summary>
-    /// 缓存权限集合(按钮)
-    /// </summary>
-    /// <param name="userId"></param>
-    /// <param name="permissions"></param>
-    /// <returns></returns>
-    [NonAction]
-    public bool SetPermission(long userId, List<string> permissions)
-    {
-        var key = CacheConst.KeyPermission + userId;
-        return _cache.Set(key, permissions);
-    }
-
-    /// <summary>
-    /// 获取最大角色数据范围
-    /// </summary>
-    /// <param name="userId"></param>
-    /// <returns></returns>
-    [NonAction]
-    public int? GetMaxDataScopeType(long userId)
-    {
-        var key = CacheConst.KeyMaxDataScopeType + userId;
-        return _cache.Get<int>(key);
-    }
-
-    /// <summary>
-    /// 缓存最大角色数据范围
-    /// </summary>
-    /// <param name="userId"></param>
-    /// <param name="dataScopeType"></param>
-    /// <returns></returns>
-    [NonAction]
-    public bool SetMaxDataScopeType(long userId, int dataScopeType)
-    {
-        var key = CacheConst.KeyMaxDataScopeType + userId;
-        return _cache.Set(key, dataScopeType);
-    }
-
-    /// <summary>
-    /// 获取缓存
-    /// </summary>
-    /// <param name="cacheKey"></param>
+    /// <param name="key"></param>
     /// <returns></returns>
-    [HttpGet("/sysCache/detail")]
-    public dynamic CacheDetail(string cacheKey)
+    [HttpGet("/sysCache/value")]
+    public dynamic GetCacheValue(string key)
     {
-        return _cache.Get<dynamic>(cacheKey);
+        return _cache.Get<dynamic>(key);
     }
-
-    ///// <summary>
-    ///// 获取菜单缓存
-    ///// </summary>
-    ///// <param name="userId"></param>
-    ///// <param name="appCode"></param>
-    ///// <returns></returns>
-    //[NonAction]
-    //public async Task<List<AntDesignTreeNode>> GetMenu(long userId, string appCode)
-    //{
-    //    var cacheKey = CacheConst.KeyMenu + $"{userId}-{appCode}";
-    //    var res = await _cache.GetStringAsync(cacheKey);
-    //    return string.IsNullOrWhiteSpace(res) ? null : JSON.Deserialize<List<AntDesignTreeNode>>(res);
-    //}
-
-    ///// <summary>
-    ///// 缓存菜单
-    ///// </summary>
-    ///// <param name="userId"></param>
-    ///// <param name="appCode"></param>
-    ///// <param name="menus"></param>
-    ///// <returns></returns>
-    //[NonAction]
-    //public async Task SetMenu(long userId, string appCode, List<AntDesignTreeNode> menus)
-    //{
-    //    var cacheKey = CommonConst.CACHE_KEY_MENU + $"{userId}-{appCode}";
-    //    await _cache.SetStringAsync(cacheKey, JSON.Serialize(menus));
-    //}
 }

+ 24 - 7
Admin.NET/Admin.NET.Core/Service/File/SysFileService.cs

@@ -9,18 +9,21 @@ namespace Admin.NET.Core.Service;
 [ApiDescriptionSettings(Order = 194)]
 public class SysFileService : IDynamicApiController, ITransient
 {
+    private readonly UserManager _userManager;
     private readonly SqlSugarRepository<SysFile> _sysFileRep;
     private readonly OSSProviderOptions _OSSProviderOptions;
     private readonly UploadOptions _uploadOptions;
     private readonly ICommonService _commonService;
     private readonly IOSSService _OSSService;
 
-    public SysFileService(SqlSugarRepository<SysFile> sysFileRep,
+    public SysFileService(UserManager userManager,
+        SqlSugarRepository<SysFile> sysFileRep,
         IOptions<OSSProviderOptions> oSSProviderOptions,
         IOptions<UploadOptions> uploadOptions,
         ICommonService commonService,
         IOSSServiceFactory ossServiceFactory)
     {
+        _userManager = userManager;
         _sysFileRep = sysFileRep;
         _OSSProviderOptions = oSSProviderOptions.Value;
         _uploadOptions = uploadOptions.Value;
@@ -257,10 +260,17 @@ public class SysFileService : IDynamicApiController, ITransient
     [HttpPost("/sysFile/uploadAvatar")]
     public async Task<FileOutput> UploadAvatar([Required] IFormFile file)
     {
+        var sysUserRep = _sysFileRep.ChangeRepository<SqlSugarRepository<SysUser>>();
+        var user = sysUserRep.GetFirst(u => u.Id == _userManager.UserId);
+        // 删除当前用户已有头像
+        if (!string.IsNullOrWhiteSpace(user.Avatar) && user.Avatar.EndsWith(".png"))
+        {
+            var fileId = Path.GetFileNameWithoutExtension(user.Avatar);
+            await DeleteFile(new DeleteFileInput { Id = long.Parse(fileId) });
+        }
+
         var res = await UploadFile(file, "Avatar");
-        var userId = App.GetService<UserManager>().UserId;
-        await _sysFileRep.ChangeRepository<SqlSugarRepository<SysUser>>()
-            .UpdateAsync(u => new SysUser() { Avatar = res.Url }, u => u.Id == userId);
+        await sysUserRep.UpdateAsync(u => new SysUser() { Avatar = res.Url }, u => u.Id == user.Id);
         return res;
     }
 
@@ -272,10 +282,17 @@ public class SysFileService : IDynamicApiController, ITransient
     [HttpPost("/sysFile/uploadSignature")]
     public async Task<FileOutput> UploadSignature([Required] IFormFile file)
     {
+        var sysUserRep = _sysFileRep.ChangeRepository<SqlSugarRepository<SysUser>>();
+        var user = sysUserRep.GetFirst(u => u.Id == _userManager.UserId);
+        // 删除当前用户已有电子签名
+        if (!string.IsNullOrWhiteSpace(user.Signature) && user.Signature.EndsWith(".png"))
+        {
+            var fileId = Path.GetFileNameWithoutExtension(user.Signature);
+            await DeleteFile(new DeleteFileInput { Id = long.Parse(fileId) });
+        }
+
         var res = await UploadFile(file, "Signature");
-        var userId = App.GetService<UserManager>().UserId;
-        await _sysFileRep.ChangeRepository<SqlSugarRepository<SysUser>>()
-            .UpdateAsync(u => new SysUser() { Signature = res.Url }, u => u.Id == userId);
+        await sysUserRep.UpdateAsync(u => new SysUser() { Signature = res.Url }, u => u.Id == user.Id);
         return res;
     }
 }

+ 6 - 4
Admin.NET/Admin.NET.Core/Service/Menu/SysMenuService.cs

@@ -1,3 +1,5 @@
+using static SKIT.FlurlHttpClient.Wechat.Api.Models.CgibinUserInfoBatchGetResponse.Types;
+
 namespace Admin.NET.Core.Service;
 
 /// <summary>
@@ -168,7 +170,7 @@ public class SysMenuService : IDynamicApiController, ITransient
     public async Task<List<string>> GetPermCodeList()
     {
         var userId = _userManager.UserId;
-        var permissions = _sysCacheService.GetPermission(userId); // 取缓存
+        var permissions = _sysCacheService.Get<List<string>>(CacheConst.KeyPermission + userId); // 取缓存
         if (permissions == null || permissions.Count == 0)
         {
             var menuIdList = _userManager.SuperAdmin ? new List<long>() : await GetMenuIdList();
@@ -176,7 +178,7 @@ public class SysMenuService : IDynamicApiController, ITransient
                 .Where(u => u.Type == MenuTypeEnum.Btn)
                 .WhereIF(menuIdList.Count > 0, u => menuIdList.Contains(u.Id))
                 .Select(u => u.Permission).ToListAsync();
-            _sysCacheService.SetPermission(userId, permissions); // 缓存结果
+            _sysCacheService.Set(CacheConst.KeyPermission + userId, permissions); // 缓存结果
         }
         return permissions;
     }
@@ -188,13 +190,13 @@ public class SysMenuService : IDynamicApiController, ITransient
     [NonAction]
     public async Task<List<string>> GetAllPermCodeList()
     {
-        var permissions = _sysCacheService.GetPermission(0); // 先从缓存里面读取
+        var permissions = _sysCacheService.Get<List<string>>(CacheConst.KeyPermission + 0); // 先从缓存里面读取
         if (permissions == null || permissions.Count == 0)
         {
             permissions = await _sysMenuRep.AsQueryable()
                 .Where(u => u.Type == MenuTypeEnum.Btn)
                 .Select(u => u.Permission).ToListAsync();
-            _sysCacheService.SetPermission(0, permissions); // 缓存结果
+            _sysCacheService.Set(CacheConst.KeyPermission + 0, permissions); // 缓存结果
         }
         return permissions;
     }

+ 0 - 57
Admin.NET/Admin.NET.Core/Service/Notice/Dto/NoticeBase.cs

@@ -1,57 +0,0 @@
-namespace Admin.NET.Core.Service;
-
-/// <summary>
-/// 通知公告参数
-/// </summary>
-public class NoticeBase
-{
-    /// <summary>
-    /// 标题
-    /// </summary>
-    public string Title { get; set; }
-
-    /// <summary>
-    /// 内容
-    /// </summary>
-    public string Content { get; set; }
-
-    /// <summary>
-    /// 类型(字典 1通知 2公告)
-    /// </summary>
-    public int Type { get; set; }
-
-    /// <summary>
-    /// 发布人Id
-    /// </summary>
-    public long PublicUserId { get; set; }
-
-    /// <summary>
-    /// 发布人姓名
-    /// </summary>
-    public string PublicUserName { get; set; }
-
-    /// <summary>
-    /// 发布机构Id
-    /// </summary>
-    public long PublicOrgId { get; set; }
-
-    /// <summary>
-    /// 发布机构名称
-    /// </summary>
-    public string PublicOrgName { get; set; }
-
-    /// <summary>
-    /// 发布时间
-    /// </summary>
-    public DateTime PublicTime { get; set; }
-
-    /// <summary>
-    /// 撤回时间
-    /// </summary>
-    public DateTime CancelTime { get; set; }
-
-    /// <summary>
-    /// 状态(字典 0草稿 1发布 2撤回 3删除)
-    /// </summary>
-    public int Status { get; set; }
-}

+ 0 - 40
Admin.NET/Admin.NET.Core/Service/Notice/Dto/NoticeDetailOutput.cs

@@ -1,40 +0,0 @@
-namespace Admin.NET.Core.Service;
-
-/// <summary>
-/// 系统通知公告详情参数
-/// </summary>
-public class NoticeDetailOutput : NoticeBase
-{
-    /// <summary>
-    /// 通知到的用户Id集合
-    /// </summary>
-    public List<string> NoticeUserIdList { get; set; }
-
-    /// <summary>
-    /// 通知到的用户阅读信息集合
-    /// </summary>
-    public List<NoticeUserRead> NoticeUserReadInfoList { get; set; }
-}
-
-public class NoticeUserRead
-{
-    /// <summary>
-    /// 用户Id
-    /// </summary>
-    public long UserId { get; set; }
-
-    /// <summary>
-    /// 用户名称
-    /// </summary>
-    public string UserName { get; set; }
-
-    /// <summary>
-    /// 状态(字典 0未读 1已读)
-    /// </summary>
-    public NoticeUserStatusEnum ReadStatus { get; set; }
-
-    /// <summary>
-    /// 阅读时间
-    /// </summary>
-    public DateTime ReadTime { get; set; }
-}

+ 7 - 71
Admin.NET/Admin.NET.Core/Service/Notice/Dto/NoticeInput.cs

@@ -1,9 +1,6 @@
 namespace Admin.NET.Core.Service;
 
-/// <summary>
-/// 通知公告参数
-/// </summary>
-public class NoticeInput : BasePageInput
+public class PageNoticeInput : BasePageInput
 {
     /// <summary>
     /// 标题
@@ -11,86 +8,25 @@ public class NoticeInput : BasePageInput
     public virtual string Title { get; set; }
 
     /// <summary>
-    /// 内容
-    /// </summary>
-    public virtual string Content { get; set; }
-
-    /// <summary>
-    /// 类型(字典 1通知 2公告)
+    /// 类型(1通知 2公告)
     /// </summary>
     public virtual NoticeTypeEnum Type { get; set; }
-
-    /// <summary>
-    /// 状态(字典 0草稿 1发布 2撤回 3删除)
-    /// </summary>
-    public virtual NoticeStatusEnum Status { get; set; }
-
-    /// <summary>
-    /// 通知到的人
-    /// </summary>
-    public virtual List<long> NoticeUserIdList { get; set; }
 }
 
-public class AddNoticeInput : NoticeInput
+[NotTable]
+public class AddNoticeInput : SysNotice
 {
-    /// <summary>
-    /// 标题
-    /// </summary>
-    [Required(ErrorMessage = "标题不能为空")]
-    public override string Title { get; set; }
-
-    /// <summary>
-    /// 内容
-    /// </summary>
-    [Required(ErrorMessage = "内容不能为空")]
-    public override string Content { get; set; }
-
-    /// <summary>
-    /// 类型(字典 1通知 2公告)
-    /// </summary>
-    [Required(ErrorMessage = "类型不能为空")]
-    public override NoticeTypeEnum Type { get; set; }
-
-    /// <summary>
-    /// 状态(字典 0草稿 1发布 2撤回 3删除)
-    /// </summary>
-    [Required(ErrorMessage = "状态不能为空")]
-    public override NoticeStatusEnum Status { get; set; }
-
-    /// <summary>
-    /// 通知到的人
-    /// </summary>
-    [Required(ErrorMessage = "通知到的人不能为空")]
-    public override List<long> NoticeUserIdList { get; set; }
-}
-
-public class DeleteNoticeInput
-{
-    /// <summary>
-    /// Id
-    /// </summary>
-    [Required(ErrorMessage = "通知公告Id不能为空")]
-    public long Id { get; set; }
 }
 
+[NotTable]
 public class UpdateNoticeInput : AddNoticeInput
 {
-    /// <summary>
-    /// Id
-    /// </summary>
-    [Required(ErrorMessage = "通知公告Id不能为空")]
-    public long Id { get; set; }
 }
 
-public class QueryNoticeInput : DeleteNoticeInput
+public class DeleteNoticeInput : BaseIdInput
 {
 }
 
-public class ChangeStatusNoticeInput : DeleteNoticeInput
+public class NoticeInput : BaseIdInput
 {
-    /// <summary>
-    /// 状态(字典 0草稿 1发布 2撤回 3删除)
-    /// </summary>
-    [Required(ErrorMessage = "状态不能为空")]
-    public NoticeStatusEnum Status { get; set; }
 }

+ 0 - 22
Admin.NET/Admin.NET.Core/Service/Notice/Dto/NoticeReceiveOutput.cs

@@ -1,22 +0,0 @@
-namespace Admin.NET.Core.Service;
-
-/// <summary>
-/// 通知公告接收参数
-/// </summary>
-public class NoticeReceiveOutput : NoticeBase
-{
-    /// <summary>
-    /// Id
-    /// </summary>
-    public long Id { get; set; }
-
-    /// <summary>
-    /// 阅读状态(字典 0未读 1已读)
-    /// </summary>
-    public int ReadStatus { get; set; }
-
-    /// <summary>
-    /// 阅读时间
-    /// </summary>
-    public DateTime ReadTime { get; set; }
-}

+ 0 - 18
Admin.NET/Admin.NET.Core/Service/Notice/ISysNoticeService.cs

@@ -1,18 +0,0 @@
-namespace Admin.NET.Core.Service;
-
-public interface ISysNoticeService
-{
-    Task AddNotice(AddNoticeInput input);
-
-    Task ChangeStatus(ChangeStatusNoticeInput input);
-
-    Task DeleteNotice(DeleteNoticeInput input);
-
-    Task<NoticeDetailOutput> GetNotice([FromQuery] QueryNoticeInput input);
-
-    Task<dynamic> QueryNoticePageList([FromQuery] NoticeInput input);
-
-    Task<dynamic> ReceivedNoticePageList([FromQuery] NoticeInput input);
-
-    Task UpdateNotice(UpdateNoticeInput input);
-}

+ 0 - 12
Admin.NET/Admin.NET.Core/Service/Notice/ISysNoticeUserService.cs

@@ -1,12 +0,0 @@
-namespace Admin.NET.Core.Service;
-
-public interface ISysNoticeUserService
-{
-    Task Add(long noticeId, List<long> noticeUserIdList, NoticeUserStatusEnum noticeUserStatus);
-
-    Task<List<SysNoticeUser>> GetNoticeUserListByNoticeId(long noticeId);
-
-    Task Read(long noticeId, long userId, NoticeUserStatusEnum status);
-
-    Task Update(long noticeId, List<long> noticeUserIdList, NoticeUserStatusEnum noticeUserStatus);
-}

+ 69 - 159
Admin.NET/Admin.NET.Core/Service/Notice/SysNoticeService.cs

@@ -1,46 +1,43 @@
-namespace Admin.NET.Core.Service;
+namespace Admin.NET.Core.Service;
 
 /// <summary>
 /// 系统通知公告服务
 /// </summary>
 [ApiDescriptionSettings(Order = 100)]
-public class SysNoticeService : ISysNoticeService, IDynamicApiController, ITransient
+public class SysNoticeService : IDynamicApiController, ITransient
 {
     private readonly UserManager _userManager;
-
     private readonly SqlSugarRepository<SysUser> _sysUserRep;
     private readonly SqlSugarRepository<SysNotice> _sysNoticeRep;
-
+    private readonly SqlSugarRepository<SysNoticeUser> _sysNoticeUserRep;
     private readonly SysOnlineUserService _sysOnlineUserService;
-    private readonly ISysNoticeUserService _sysNoticeUserService;
 
     public SysNoticeService(
         UserManager userManager,
         SqlSugarRepository<SysUser> sysUserRep,
         SqlSugarRepository<SysNotice> sysNoticeRep,
-        SysOnlineUserService sysOnlineUserService,
-        ISysNoticeUserService sysNoticeUserService)
+        SqlSugarRepository<SysNoticeUser> sysNoticeUserRep,
+        SysOnlineUserService sysOnlineUserService)
     {
         _userManager = userManager;
         _sysUserRep = sysUserRep;
         _sysNoticeRep = sysNoticeRep;
+        _sysNoticeUserRep = sysNoticeUserRep;
         _sysOnlineUserService = sysOnlineUserService;
-        _sysNoticeUserService = sysNoticeUserService;
     }
 
     /// <summary>
-    /// 分页查询通知公告
+    /// 获取通知公告分页列表
     /// </summary>
     /// <param name="input"></param>
     /// <returns></returns>
     [HttpGet("/sysNotice/page")]
-    public async Task<dynamic> QueryNoticePageList([FromQuery] NoticeInput input)
+    public async Task<SqlSugarPagedList<SysNotice>> GetPageNotice([FromQuery] PageNoticeInput input)
     {
         return await _sysNoticeRep.Context.Queryable<SysNotice>()
             .WhereIF(!string.IsNullOrWhiteSpace(input.Title), u => u.Title.Contains(input.Title.Trim()))
-            .WhereIF(!string.IsNullOrWhiteSpace(input.Content), u => u.Content.Contains(input.Content.Trim()))
             .WhereIF(input.Type > 0, u => u.Type == input.Type)
-            .Where(u => u.Status != NoticeStatusEnum.DELETED)
+            .OrderBy(u => u.CreateTime, OrderByType.Desc)
             .ToPagedListAsync(input.Page, input.PageSize);
     }
 
@@ -52,207 +49,120 @@ public class SysNoticeService : ISysNoticeService, IDynamicApiController, ITrans
     [HttpPost("/sysNotice/add")]
     public async Task AddNotice(AddNoticeInput input)
     {
-        if (input.Status != NoticeStatusEnum.DRAFT && input.Status != NoticeStatusEnum.PUBLIC)
-            throw Oops.Oh(ErrorCodeEnum.D7000);
-
         var notice = input.Adapt<SysNotice>();
-        await UpdatePublicInfo(notice);
-        // 如果是发布,则设置发布时间
-        if (input.Status == NoticeStatusEnum.PUBLIC)
-            notice.PublicTime = DateTime.Now;
-        var newItem = await _sysNoticeRep.AsInsertable(notice).ExecuteReturnEntityAsync();
-
-        // 通知到的人
-        var noticeUserIdList = input.NoticeUserIdList;
-        var noticeUserStatus = NoticeUserStatusEnum.UNREAD;
-        await _sysNoticeUserService.Add(newItem.Id, noticeUserIdList, noticeUserStatus);
-        if (newItem.Status == NoticeStatusEnum.PUBLIC)
-        {
-            await _sysOnlineUserService.AppendNotice(newItem, noticeUserIdList);
-        }
+        InitNoticeInfo(notice);
+        await _sysNoticeRep.InsertAsync(notice);
     }
 
     /// <summary>
-    /// 删除通知公告
+    /// 更新通知公告
     /// </summary>
     /// <param name="input"></param>
     /// <returns></returns>
-    [HttpPost("/sysNotice/delete")]
-    public async Task DeleteNotice(DeleteNoticeInput input)
+    [HttpPost("/sysNotice/update")]
+    [UnitOfWork]
+    public async Task UpdateNotice(UpdateNoticeInput input)
     {
-        var notice = await _sysNoticeRep.GetFirstAsync(u => u.Id == input.Id);
-        if (notice.Status != NoticeStatusEnum.DRAFT && notice.Status != NoticeStatusEnum.CANCEL) // 只能删除草稿和撤回的
-            throw Oops.Oh(ErrorCodeEnum.D7001);
-
-        await _sysNoticeRep.DeleteAsync(notice);
+        var notice = input.Adapt<SysNotice>();
+        InitNoticeInfo(notice);
+        await _sysNoticeRep.UpdateAsync(notice);
     }
 
     /// <summary>
-    /// 更新通知公告
+    /// 删除通知公告
     /// </summary>
     /// <param name="input"></param>
     /// <returns></returns>
-    [HttpPost("/sysNotice/edit")]
-    public async Task UpdateNotice(UpdateNoticeInput input)
+    [HttpPost("/sysNotice/delete")]
+    [UnitOfWork]
+    public async Task DeleteNotice(DeleteNoticeInput input)
     {
-        if (input.Status != NoticeStatusEnum.DRAFT && input.Status != NoticeStatusEnum.PUBLIC)
-            throw Oops.Oh(ErrorCodeEnum.D7000);
-
-        //  非草稿状态
-        if (input.Status != NoticeStatusEnum.DRAFT)
-            throw Oops.Oh(ErrorCodeEnum.D7002);
+        await _sysNoticeRep.DeleteAsync(u => u.Id == input.Id);
 
-        var notice = input.Adapt<SysNotice>();
-        if (input.Status == NoticeStatusEnum.PUBLIC)
-        {
-            notice.PublicTime = DateTime.Now;
-            await UpdatePublicInfo(notice);
-        }
-        await _sysNoticeRep.UpdateAsync(notice);
-
-        // 通知到的人
-        var noticeUserIdList = input.NoticeUserIdList;
-        var noticeUserStatus = NoticeUserStatusEnum.UNREAD;
-        await _sysNoticeUserService.Update(input.Id, noticeUserIdList, noticeUserStatus);
-        if (notice.Status == NoticeStatusEnum.PUBLIC)
-        {
-            await _sysOnlineUserService.AppendNotice(notice, noticeUserIdList);
-        }
+        await _sysNoticeUserRep.DeleteAsync(u => u.NoticeId == input.Id);
     }
 
     /// <summary>
-    /// 获取通知公告详情
+    /// 发布通知公告
     /// </summary>
     /// <param name="input"></param>
     /// <returns></returns>
-    [HttpGet("/sysNotice/detail")]
-    public async Task<NoticeDetailOutput> GetNotice([FromQuery] QueryNoticeInput input)
+    [HttpPost("/sysNotice/public")]
+    public async Task PublicNotice(NoticeInput input)
     {
+        // 更新发布状态和时间
+        await _sysNoticeRep.UpdateAsync(u => new SysNotice() { Status = NoticeStatusEnum.PUBLIC, PublicTime = DateTime.Now }, u => u.Id == input.Id);
+
         var notice = await _sysNoticeRep.GetFirstAsync(u => u.Id == input.Id);
 
-        // 获取通知到的用户
-        var noticeUserList = await _sysNoticeUserService.GetNoticeUserListByNoticeId(input.Id);
-        var noticeUserIdList = new List<string>();
-        var noticeUserReadInfoList = new List<NoticeUserRead>();
-        if (noticeUserList != null)
+        // 通知到的人(所有账号)
+        var userIdList = await _sysUserRep.AsQueryable().Select(u => u.Id).ToListAsync();
+
+        await _sysNoticeUserRep.DeleteAsync(u => u.NoticeId == notice.Id);
+        var noticeUserList = userIdList.Select(u => new SysNoticeUser
         {
-            noticeUserList.ForEach(u =>
-            {
-                noticeUserIdList.Add(u.UserId.ToString());
-                var noticeUserRead = new NoticeUserRead
-                {
-                    UserId = u.UserId,
-                    UserName = _userManager.Account,
-                    ReadStatus = u.ReadStatus,
-                    ReadTime = u.ReadTime
-                };
-                noticeUserReadInfoList.Add(noticeUserRead);
-            });
-        }
-        var noticeResult = notice.Adapt<NoticeDetailOutput>();
-        noticeResult.NoticeUserIdList = noticeUserIdList;
-        noticeResult.NoticeUserReadInfoList = noticeUserReadInfoList;
-        // 如果该条通知公告为已发布,则将当前用户的该条通知公告设置为已读
-        if (notice.Status == NoticeStatusEnum.PUBLIC)
-            await _sysNoticeUserService.Read(notice.Id, _userManager.UserId, NoticeUserStatusEnum.READ);
-        return noticeResult;
+            NoticeId = notice.Id,
+            UserId = u,
+        }).ToList();
+        await _sysNoticeUserRep.InsertRangeAsync(noticeUserList);
+
+        // 广播所有在线账号
+        await _sysOnlineUserService.PublicNotice(notice, userIdList);
     }
 
     /// <summary>
-    /// 修改通知公告状态
+    /// 设置通知公告已读状态
     /// </summary>
     /// <param name="input"></param>
     /// <returns></returns>
-    [HttpPost("/sysNotice/changeStatus")]
-    public async Task ChangeStatus(ChangeStatusNoticeInput input)
+    [HttpPost("/sysNotice/setRead")]
+    public async Task SetNoticeRead(NoticeInput input)
     {
-        // 状态应为撤回或删除或发布
-        if (input.Status != NoticeStatusEnum.CANCEL && input.Status != NoticeStatusEnum.DELETED && input.Status != NoticeStatusEnum.PUBLIC)
-            throw Oops.Oh(ErrorCodeEnum.D7000);
-
-        var notice = await _sysNoticeRep.GetFirstAsync(u => u.Id == input.Id);
-        notice.Status = input.Status;
-
-        if (input.Status == NoticeStatusEnum.CANCEL)
-        {
-            notice.CancelTime = DateTime.Now;
-        }
-        else if (input.Status == NoticeStatusEnum.PUBLIC)
+        await _sysNoticeUserRep.UpdateAsync(u => new SysNoticeUser
         {
-            notice.PublicTime = DateTime.Now;
-        }
-        await _sysNoticeRep.UpdateAsync(notice);
-        if (notice.Status == NoticeStatusEnum.PUBLIC)
-        {
-            // 获取通知到的用户
-            var noticeUserList = await _sysNoticeUserService.GetNoticeUserListByNoticeId(input.Id);
-            await _sysOnlineUserService.AppendNotice(notice, noticeUserList.Select(m => m.UserId).ToList());
-        }
+            ReadStatus = NoticeUserStatusEnum.READ,
+            ReadTime = DateTime.Now
+        }, u => u.NoticeId == input.Id && u.UserId == _userManager.UserId);
     }
 
     /// <summary>
-    /// 获取接收的通知公告
+    /// 获取接收的通知公告(当前用户)
     /// </summary>
     /// <param name="input"></param>
     /// <returns></returns>
-    [HttpGet("/sysNotice/received")]
-    public async Task<dynamic> ReceivedNoticePageList([FromQuery] NoticeInput input)
+    [HttpGet("/sysNotice/pageReceived")]
+    public async Task<SqlSugarPagedList<SysNoticeUser>> GetPageReceivedNotice([FromQuery] PageNoticeInput input)
     {
-        return await _sysNoticeRep.Context.Queryable<SysNotice, SysNoticeUser>((n, u) => new JoinQueryInfos(JoinType.Inner, n.Id == u.NoticeId))
-          .Where((n, u) => u.UserId == _userManager.UserId)
-          .WhereIF(!string.IsNullOrWhiteSpace(input.Title), u => u.Title.Contains(input.Title.Trim()))
-          .WhereIF(!string.IsNullOrWhiteSpace(input.Content), u => u.Title.Contains(input.Content.Trim()))
-          .WhereIF(input.Type > 0, (n, u) => n.Type == input.Type)
-          .Select<NoticeReceiveOutput>()
-          .ToPagedListAsync(input.Page, input.PageSize);
+        return await _sysNoticeRep.AsSugarClient().Queryable<SysNoticeUser>().Includes(u => u.SysNotice)
+            .Where(u => u.UserId == _userManager.UserId)
+            .WhereIF(!string.IsNullOrWhiteSpace(input.Title), u => u.SysNotice.Title.Contains(input.Title.Trim()))
+            .WhereIF(input.Type > 0, u => u.SysNotice.Type == input.Type)
+            .OrderBy(u => u.SysNotice.CreateTime, OrderByType.Desc)
+            .ToPagedListAsync(input.Page, input.PageSize);
     }
 
     /// <summary>
-    /// 未处理消息
+    /// 获取未读的通知公告(当前用户)
     /// </summary>
-    /// <param name="input"></param>
     /// <returns></returns>
-    [HttpGet("/sysNotice/unread")]
-    public async Task<dynamic> UnReadNoticeList([FromQuery] NoticeInput input)
+    [HttpGet("/sysNotice/unReadList")]
+    public async Task<List<SysNotice>> GetUnReadNoticeList()
     {
-        var dic = typeof(NoticeTypeEnum).EnumToList();
-        var notices = await _sysNoticeRep.Context.Queryable<SysNotice, SysNoticeUser>((n, u) => new JoinQueryInfos(JoinType.Inner, n.Id == u.NoticeId))
-            .Where((n, u) => u.UserId == _userManager.UserId && u.ReadStatus == NoticeUserStatusEnum.UNREAD)
-            .PartitionBy(n => n.Type).OrderBy(n => n.CreateTime, OrderByType.Desc)
-            .Take(input.PageSize).Select<NoticeReceiveOutput>().ToListAsync();
-        var count = await _sysNoticeRep.Context.Queryable<SysNotice, SysNoticeUser>((n, u) => new JoinQueryInfos(JoinType.Inner, n.Id == u.NoticeId))
-            .Where((n, u) => u.UserId == _userManager.UserId && u.ReadStatus == NoticeUserStatusEnum.UNREAD).CountAsync();
-
-        var noticeClays = new List<dynamic>();
-        int index = 0;
-        foreach (var item in dic)
-        {
-            noticeClays.Add(new
-            {
-                Index = index++,
-                Key = item.Describe,
-                Value = item.Value,
-                NoticeData = notices.Where(m => m.Type == item.Value).ToList()
-            });
-        }
-        return new
-        {
-            Rows = noticeClays,
-            TotalRows = count
-        };
+        var noticeUserList = await _sysNoticeRep.AsSugarClient().Queryable<SysNoticeUser>().Includes(u => u.SysNotice)
+            .Where(u => u.UserId == _userManager.UserId && u.ReadStatus == NoticeUserStatusEnum.UNREAD)
+            .OrderBy(u => u.SysNotice.CreateTime, OrderByType.Desc).ToListAsync();
+        return noticeUserList.Select(t => t.SysNotice).ToList();
     }
 
     /// <summary>
-    /// 更新发布信息
+    /// 初始化通知公告信息
     /// </summary>
     /// <param name="notice"></param>
     [NonAction]
-    private async Task UpdatePublicInfo(SysNotice notice)
+    private void InitNoticeInfo(SysNotice notice)
     {
-        var user = await _sysUserRep.GetFirstAsync(u => u.Id == _userManager.UserId);
         notice.PublicUserId = _userManager.UserId;
-        notice.PublicUserName = _userManager.Account;
-        notice.PublicOrgId = user.OrgId;
-        // notice.PublicOrgName = user.OrgName;
+        notice.PublicUserName = _userManager.RealName;
+        notice.PublicOrgId = _userManager.OrgId;
     }
 }

+ 0 - 77
Admin.NET/Admin.NET.Core/Service/Notice/SysNoticeUserService.cs

@@ -1,77 +0,0 @@
-namespace Admin.NET.Core.Service;
-
-/// <summary>
-/// 系统通知公告用户
-/// </summary>
-[ApiDescriptionSettings(Order = 100)]
-public class SysNoticeUserService : ISysNoticeUserService, ITransient
-{
-    private readonly SqlSugarRepository<SysNoticeUser> _sysNoticeUserRep;  // 通知公告用户表仓储
-
-    public SysNoticeUserService(SqlSugarRepository<SysNoticeUser> sysNoticeUserRep)
-    {
-        _sysNoticeUserRep = sysNoticeUserRep;
-    }
-
-    /// <summary>
-    /// 增加
-    /// </summary>
-    /// <param name="noticeId"></param>
-    /// <param name="noticeUserIdList"></param>
-    /// <param name="noticeUserStatus"></param>
-    /// <returns></returns>
-    public async Task Add(long noticeId, List<long> noticeUserIdList, NoticeUserStatusEnum noticeUserStatus)
-    {
-        var list = new List<SysNoticeUser>();
-        noticeUserIdList.ForEach(u =>
-        {
-            list.Add(new SysNoticeUser
-            {
-                NoticeId = noticeId,
-                UserId = u,
-                ReadStatus = noticeUserStatus
-            });
-        });
-        await _sysNoticeUserRep.InsertRangeAsync(list);
-    }
-
-    /// <summary>
-    /// 更新
-    /// </summary>
-    /// <param name="noticeId"></param>
-    /// <param name="noticeUserIdList"></param>
-    /// <param name="noticeUserStatus"></param>
-    /// <returns></returns>
-    public async Task Update(long noticeId, List<long> noticeUserIdList, NoticeUserStatusEnum noticeUserStatus)
-    {
-        await _sysNoticeUserRep.DeleteAsync(u => u.NoticeId == noticeId);
-
-        await Add(noticeId, noticeUserIdList, noticeUserStatus);
-    }
-
-    /// <summary>
-    /// 获取通知公告用户列表
-    /// </summary>
-    /// <param name="noticeId"></param>
-    /// <returns></returns>
-    public async Task<List<SysNoticeUser>> GetNoticeUserListByNoticeId(long noticeId)
-    {
-        return await _sysNoticeUserRep.GetListAsync(u => u.NoticeId == noticeId);
-    }
-
-    /// <summary>
-    /// 设置通知公告读取状态
-    /// </summary>
-    /// <param name="noticeId"></param>
-    /// <param name="userId"></param>
-    /// <param name="status"></param>
-    /// <returns></returns>
-    public async Task Read(long noticeId, long userId, NoticeUserStatusEnum status)
-    {
-        await _sysNoticeUserRep.UpdateAsync(u => new SysNoticeUser
-        {
-            ReadStatus = status,
-            ReadTime = DateTime.Now
-        }, u => u.NoticeId == noticeId && u.UserId == userId);
-    }
-}

+ 3 - 3
Admin.NET/Admin.NET.Core/Service/OnlineUser/SysOnlineUserService.cs

@@ -48,20 +48,20 @@ public class SysOnlineUserService : IDynamicApiController, ITransient
     }
 
     /// <summary>
-    /// 发消息
+    /// 发布站内消息
     /// </summary>
     /// <param name="notice"></param>
     /// <param name="userIds"></param>
     /// <returns></returns>
     [NonAction]
-    public async Task AppendNotice(SysNotice notice, List<long> userIds)
+    public async Task PublicNotice(SysNotice notice, List<long> userIds)
     {
         var userList = await _sysOnlineUerRep.GetListAsync(m => userIds.Contains(m.UserId));
         if (!userList.Any()) return;
 
         foreach (var item in userList)
         {
-            await _onlineUserHubContext.Clients.Client(item.ConnectionId).AppendNotice(notice);
+            await _onlineUserHubContext.Clients.Client(item.ConnectionId).PublicNotice(notice);
         }
     }
 

+ 5 - 5
Admin.NET/Admin.NET.Core/Service/Org/SysOrgService.cs

@@ -13,8 +13,8 @@ public class SysOrgService : IDynamicApiController, ITransient
     private readonly SysUserRoleService _sysUserRoleService;
     private readonly SysRoleOrgService _sysRoleOrgService;
 
-    public SysOrgService(UserManager userManager, 
-        SqlSugarRepository<SysOrg> sysOrgRep,        
+    public SysOrgService(UserManager userManager,
+        SqlSugarRepository<SysOrg> sysOrgRep,
         SysCacheService sysCacheService,
         SysUserExtOrgService sysUserExtOrgService,
         SysUserRoleService sysUserRoleService,
@@ -174,7 +174,7 @@ public class SysOrgService : IDynamicApiController, ITransient
             return new List<long>();
 
         var userId = _userManager.UserId;
-        var orgIdList = _sysCacheService.GetOrgIdList(userId); // 取缓存
+        var orgIdList = _sysCacheService.Get<List<long>>(CacheConst.KeyOrgIdList + userId); // 取缓存
         if (orgIdList == null || orgIdList.Count < 1)
         {
             // 扩展机构集合
@@ -183,7 +183,7 @@ public class SysOrgService : IDynamicApiController, ITransient
             var orgList2 = await GetUserRoleOrgIdList(userId);
             // 机构并集
             orgIdList = orgList1.Select(u => u.OrgId).Union(orgList2).ToList();
-            _sysCacheService.SetOrgIdList(userId, orgIdList); // 存缓存
+            _sysCacheService.Set(CacheConst.KeyOrgIdList + userId, orgIdList); // 存缓存
         }
         return orgIdList;
     }
@@ -231,7 +231,7 @@ public class SysOrgService : IDynamicApiController, ITransient
         var orgIdList2 = await GetOrgIdListByDataScope(strongerDataScopeType);
 
         // 缓存当前用户最大角色数据范围
-        _sysCacheService.SetMaxDataScopeType(_userManager.UserId, strongerDataScopeType);
+        _sysCacheService.Set(CacheConst.KeyMaxDataScopeType + _userManager.UserId, strongerDataScopeType);
 
         // 并集机构集合
         return orgIdList1.Union(orgIdList2).ToList();

+ 0 - 1
Admin.NET/Admin.NET.Core/Service/Region/Dto/RegionInput.cs

@@ -20,7 +20,6 @@ public class PageRegionInput : BasePageInput
 
 public class RegionInput : BaseIdInput
 {
-
 }
 
 [NotTable]

+ 3 - 3
Admin.NET/Admin.NET.Core/Service/Role/SysRoleService.cs

@@ -104,7 +104,7 @@ public class SysRoleService : IDynamicApiController, ITransient
     public async Task UpdateRole(UpdateRoleInput input)
     {
         var adminRole = await _sysRoleRep.GetFirstAsync(u => u.Id == input.Id);
-        if (adminRole.Code == CommonConst.SysAdminRoleCode)
+        if (adminRole.Code == CommonConst.SysAdminRole)
             throw Oops.Oh(ErrorCodeEnum.D1020);
 
         var isExist = await _sysRoleRep.IsAnyAsync(u => (u.Name == input.Name || u.Code == input.Code) && u.Id != input.Id);
@@ -127,7 +127,7 @@ public class SysRoleService : IDynamicApiController, ITransient
     public async Task DeleteRole(DeleteRoleInput input)
     {
         var sysRole = await _sysRoleRep.GetFirstAsync(u => u.Id == input.Id);
-        if (sysRole.Code == CommonConst.SysAdminRoleCode)
+        if (sysRole.Code == CommonConst.SysAdminRole)
             throw Oops.Oh(ErrorCodeEnum.D1019);
 
         await _sysRoleRep.DeleteAsync(sysRole);
@@ -151,7 +151,7 @@ public class SysRoleService : IDynamicApiController, ITransient
     public async Task GrantRoleMenu(RoleMenuInput input)
     {
         var role = await _sysRoleRep.GetFirstAsync(u => u.Id == input.Id);
-        if (!_userManager.SuperAdmin && role.Code == CommonConst.SysAdminRoleCode)
+        if (!_userManager.SuperAdmin && role.Code == CommonConst.SysAdminRole)
             throw Oops.Oh(ErrorCodeEnum.D1021);
 
         await _sysRoleMenuService.GrantRoleMenu(input);

+ 87 - 14
Admin.NET/Admin.NET.Core/Service/Tenant/SysTenantService.cs

@@ -16,6 +16,9 @@ public class SysTenantService : IDynamicApiController, ITransient
     private readonly SqlSugarRepository<SysUserRole> _userRoleRep;
     private readonly SysUserRoleService _sysUserRoleService;
     private readonly SysRoleMenuService _sysRoleMenuService;
+    private readonly SysConfigService _sysConfigService;
+    private readonly SysCacheService _sysCacheService;
+    private readonly ISqlSugarClient _db;
 
     public SysTenantService(SqlSugarRepository<SysTenant> tenantRep,
         SqlSugarRepository<SysOrg> orgRep,
@@ -26,7 +29,10 @@ public class SysTenantService : IDynamicApiController, ITransient
         SqlSugarRepository<SysRoleMenu> sysRoleMenuRep,
         SqlSugarRepository<SysUserRole> userRoleRep,
         SysUserRoleService sysUserRoleService,
-        SysRoleMenuService sysRoleMenuService)
+        SysRoleMenuService sysRoleMenuService,
+        SysConfigService sysConfigService,
+        SysCacheService sysCacheService,
+        ISqlSugarClient db)
     {
         _tenantRep = tenantRep;
         _orgRep = orgRep;
@@ -38,6 +44,9 @@ public class SysTenantService : IDynamicApiController, ITransient
         _userRoleRep = userRoleRep;
         _sysUserRoleService = sysUserRoleService;
         _sysRoleMenuService = sysRoleMenuService;
+        _sysConfigService = sysConfigService;
+        _sysCacheService = sysCacheService;
+        _db = db;
     }
 
     /// <summary>
@@ -54,6 +63,16 @@ public class SysTenantService : IDynamicApiController, ITransient
             .ToPagedListAsync(input.Page, input.PageSize);
     }
 
+    /// <summary>
+    /// 获取库隔离的租户列表
+    /// </summary>
+    /// <returns></returns>
+    [NonAction]
+    public async Task<List<SysTenant>> GetTenantDbList()
+    {
+        return await _tenantRep.GetListAsync(u => u.TenantType == TenantTypeEnum.Db);
+    }
+
     /// <summary>
     /// 增加租户
     /// </summary>
@@ -62,16 +81,20 @@ public class SysTenantService : IDynamicApiController, ITransient
     [HttpPost("/sysTenant/add")]
     public async Task AddTenant(AddTenantInput input)
     {
-        var isExist = await _tenantRep.IsAnyAsync(u => u.Name == input.Name || u.AdminName == input.AdminName);
+        var isExist = await _tenantRep.IsAnyAsync(u => u.Name == input.Name ||
+            (u.AdminName == input.AdminName && input.TenantType == TenantTypeEnum.Id));
         if (isExist) throw Oops.Oh(ErrorCodeEnum.D1300);
 
-        var entity = input.Adapt<SysTenant>();
-        await _tenantRep.InsertAsync(entity);
-        await InitNewTenant(entity);
+        var tenant = input.Adapt<SysTenant>();
+        await _tenantRep.InsertAsync(tenant);
+        await UpdateTenantCache();
+
+        if (tenant.TenantType == TenantTypeEnum.Db) return;
+        await InitNewTenant(tenant);
     }
 
     /// <summary>
-    /// 新增租户初始化
+    /// 新增租户初始化(Id隔离)
     /// </summary>
     /// <param name="newTenant"></param>
     private async Task InitNewTenant(SysTenant newTenant)
@@ -94,7 +117,7 @@ public class SysTenantService : IDynamicApiController, ITransient
         var newRole = new SysRole
         {
             TenantId = tenantId,
-            Code = CommonConst.SysAdminRoleCode,
+            Code = CommonConst.SysAdminRole,
             Name = "租户管理员-" + companyName,
             DataScope = DataScopeEnum.All,
             Remark = companyName
@@ -111,11 +134,12 @@ public class SysTenantService : IDynamicApiController, ITransient
         await _posRep.InsertAsync(newPos);
 
         // 初始化租户管理员
+        var password = await _sysConfigService.GetConfigValue<string>(CommonConst.SysPassword);
         var newUser = new SysUser
         {
             TenantId = tenantId,
             Account = admin,
-            Password = MD5Encryption.Encrypt(CommonConst.SysPassword),
+            Password = MD5Encryption.Encrypt(password),
             NickName = newTenant.AdminName,
             Email = newTenant.Email,
             Phone = newTenant.Phone,
@@ -150,6 +174,7 @@ public class SysTenantService : IDynamicApiController, ITransient
             throw Oops.Oh(ErrorCodeEnum.D1023);
         var entity = await _tenantRep.GetFirstAsync(u => u.Id == input.Id);
         await _tenantRep.DeleteAsync(entity);
+        await UpdateTenantCache();
 
         // 删除与租户相关的表数据
         var userIds = users.Select(u => u.Id).ToList();
@@ -157,14 +182,12 @@ public class SysTenantService : IDynamicApiController, ITransient
 
         await _userRoleRep.AsDeleteable().Where(u => userIds.Contains(u.UserId)).ExecuteCommandAsync();
 
-        await _roleRep.AsDeleteable().Where(u => u.TenantId == input.Id).ExecuteCommandAsync();
-
         await _sysUserExtOrgRep.AsDeleteable().Where(u => userIds.Contains(u.UserId)).ExecuteCommandAsync();
 
-        var roles = await _roleRep.AsQueryable().Filter(null, true).Where(u => u.TenantId == input.Id).ToListAsync();
         await _roleRep.AsDeleteable().Where(u => u.TenantId == input.Id).ExecuteCommandAsync();
 
-        var roleIds = roles.Select(u => u.Id).ToList();
+        var roleIds = await _roleRep.AsQueryable().Filter(null, true)
+            .Where(u => u.TenantId == input.Id).Select(u => u.Id).ToListAsync();
         await _sysRoleMenuRep.AsDeleteable().Where(u => roleIds.Contains(u.RoleId)).ExecuteCommandAsync();
 
         await _orgRep.AsDeleteable().Where(u => u.TenantId == input.Id).ExecuteCommandAsync();
@@ -187,6 +210,7 @@ public class SysTenantService : IDynamicApiController, ITransient
         if (tenantAdminUser == null) return;
         tenantAdminUser.Account = entity.AdminName;
         await _userRep.Context.Updateable(tenantAdminUser).UpdateColumns(u => new { u.Account }).ExecuteCommandAsync();
+        await UpdateTenantCache();
     }
 
     /// <summary>
@@ -240,11 +264,24 @@ public class SysTenantService : IDynamicApiController, ITransient
     [HttpPost("/sysTenant/resetPwd")]
     public async Task ResetTenantPwd(TenantInput input)
     {
+        var password = await _sysConfigService.GetConfigValue<string>(CommonConst.SysPassword);
+
         var tenantAdminUser = await GetTenantAdminUser(input.Id);
-        tenantAdminUser.Password = MD5Encryption.Encrypt(CommonConst.SysPassword);
+        tenantAdminUser.Password = MD5Encryption.Encrypt(password);
         await _userRep.UpdateAsync(tenantAdminUser);
     }
 
+    /// <summary>
+    /// 获取租户
+    /// </summary>
+    /// <param name="tenantId"></param>
+    /// <returns></returns>
+    [NonAction]
+    public async Task<SysTenant> GetTenant(long tenantId)
+    {
+        return await _tenantRep.GetFirstAsync(u => u.Id == tenantId);
+    }
+
     /// <summary>
     /// 获取租户管理员用户
     /// </summary>
@@ -252,6 +289,42 @@ public class SysTenantService : IDynamicApiController, ITransient
     /// <returns></returns>
     private async Task<SysUser> GetTenantAdminUser(long tenantId)
     {
-        return await _userRep.AsQueryable().Filter(null, true).Where(u => u.TenantId == tenantId && u.AccountType == AccountTypeEnum.Admin).FirstAsync();
+        return await _userRep.GetFirstAsync(u => u.TenantId == tenantId && u.AccountType == AccountTypeEnum.Admin);
+    }
+
+    /// <summary>
+    /// 缓存所有租户
+    /// </summary>
+    /// <returns></returns>
+    [NonAction]
+    public async Task UpdateTenantCache()
+    {
+        _sysCacheService.Remove(CacheConst.KeyTenant);
+
+        var tenantList = await _tenantRep.GetListAsync();
+        _sysCacheService.Set(CacheConst.KeyTenant, tenantList);
+    }
+
+    /// <summary>
+    /// 创建租户数据库(根据默认库结构)
+    /// </summary>
+    /// <param name="input"></param>
+    /// <returns></returns>
+    [HttpPost("/sysTenant/createDb")]
+    public async Task CreateTenantDb(TenantInput input)
+    {
+        var tenant = await _tenantRep.GetFirstAsync(u => u.Id == input.Id);
+        if (tenant == null) return;
+
+        var dbConnection = new DbConnectionConfig
+        {
+            EnableInitDb = true,
+            DbType = tenant.DbType,
+            ConfigId = tenant.ConfigId,
+            ConnectionString = tenant.Connection,
+            IsAutoCloseConnection = true,
+        };
+
+        SqlSugarSetup.CreateDataBase(_db, dbConnection, tenant.Id);
     }
 }

+ 10 - 3
Admin.NET/Admin.NET.Core/Service/User/SysUserService.cs

@@ -11,18 +11,21 @@ public class SysUserService : IDynamicApiController, ITransient
     private readonly SysOrgService _sysOrgService;
     private readonly SysUserExtOrgService _sysUserExtOrgService;
     private readonly SysUserRoleService _sysUserRoleService;
+    private readonly SysConfigService _sysConfigService;
 
     public SysUserService(UserManager userManager,
         SqlSugarRepository<SysUser> sysUserRep,
         SysOrgService sysOrgService,
         SysUserExtOrgService sysUserExtOrgService,
-        SysUserRoleService sysUserRoleService)
+        SysUserRoleService sysUserRoleService,
+        SysConfigService sysConfigService)
     {
         _userManager = userManager;
         _sysUserRep = sysUserRep;
         _sysOrgService = sysOrgService;
         _sysUserExtOrgService = sysUserExtOrgService;
         _sysUserRoleService = sysUserRoleService;
+        _sysConfigService = sysConfigService;
     }
 
     /// <summary>
@@ -58,8 +61,10 @@ public class SysUserService : IDynamicApiController, ITransient
         var isExist = await _sysUserRep.IsAnyAsync(u => u.Account == input.Account);
         if (isExist) throw Oops.Oh(ErrorCodeEnum.D1003);
 
+        var password = await _sysConfigService.GetConfigValue<string>(CommonConst.SysPassword);
+
         var user = input.Adapt<SysUser>();
-        user.Password = MD5Encryption.Encrypt(CommonConst.SysPassword);
+        user.Password = MD5Encryption.Encrypt(password);
         var newUser = await _sysUserRep.AsInsertable(user).ExecuteReturnEntityAsync();
         input.Id = newUser.Id;
         await UpdateRoleAndExtOrg(input);
@@ -199,8 +204,10 @@ public class SysUserService : IDynamicApiController, ITransient
     [HttpPost("/sysUser/resetPwd")]
     public async Task<int> ResetUserPwd(ResetPwdUserInput input)
     {
+        var password = await _sysConfigService.GetConfigValue<string>(CommonConst.SysPassword);
+
         var user = await _sysUserRep.GetFirstAsync(u => u.Id == input.Id);
-        user.Password = MD5Encryption.Encrypt(CommonConst.SysPassword);
+        user.Password = MD5Encryption.Encrypt(password);
         return await _sysUserRep.AsUpdateable(user).UpdateColumns(u => u.Password).ExecuteCommandAsync();
     }
 

+ 18 - 26
Admin.NET/Admin.NET.Core/Service/User/UserManager.cs

@@ -5,59 +5,51 @@
 /// </summary>
 public class UserManager : IScoped
 {
-    private readonly SqlSugarRepository<SysUser> _sysUserRep;
     private readonly IHttpContextAccessor _httpContextAccessor;
+    private long _tenantId;
 
     public long UserId
     {
-        get => long.Parse(_httpContextAccessor.HttpContext.User.FindFirst(ClaimConst.UserId)?.Value);
+        get => long.Parse(_httpContextAccessor.HttpContext?.User.FindFirst(ClaimConst.UserId)?.Value);
+    }
+
+    public long TenantId
+    {
+        get
+        {
+            var tId = _httpContextAccessor.HttpContext?.User.FindFirst(ClaimConst.TenantId);
+            return tId == null ? _tenantId : long.Parse(tId.Value);
+        }
+        set => _tenantId = value;
     }
 
     public string Account
     {
-        get => _httpContextAccessor.HttpContext.User.FindFirst(ClaimConst.Account)?.Value;
+        get => _httpContextAccessor.HttpContext?.User.FindFirst(ClaimConst.Account)?.Value;
     }
 
     public string RealName
     {
-        get => _httpContextAccessor.HttpContext.User.FindFirst(ClaimConst.RealName)?.Value;
+        get => _httpContextAccessor.HttpContext?.User.FindFirst(ClaimConst.RealName)?.Value;
     }
 
     public bool SuperAdmin
     {
-        get => _httpContextAccessor.HttpContext.User.FindFirst(ClaimConst.AccountType)?.Value == ((int)AccountTypeEnum.SuperAdmin).ToString();
+        get => _httpContextAccessor.HttpContext?.User.FindFirst(ClaimConst.AccountType)?.Value == ((int)AccountTypeEnum.SuperAdmin).ToString();
     }
 
     public long OrgId
     {
-        get => long.Parse(_httpContextAccessor.HttpContext.User.FindFirst(ClaimConst.OrgId)?.Value);
+        get => long.Parse(_httpContextAccessor.HttpContext?.User.FindFirst(ClaimConst.OrgId)?.Value);
     }
 
     public string OpenId
     {
-        get => _httpContextAccessor.HttpContext.User.FindFirst(ClaimConst.OpenId)?.Value;
+        get => _httpContextAccessor.HttpContext?.User.FindFirst(ClaimConst.OpenId)?.Value;
     }
 
-    public SysUser User
+    public UserManager(IHttpContextAccessor httpContextAccessor)
     {
-        get => _sysUserRep.GetFirst(u => u.Id == UserId);
-    }
-
-    public UserManager(SqlSugarRepository<SysUser> sysUserRep,
-        IHttpContextAccessor httpContextAccessor)
-    {
-        _sysUserRep = sysUserRep;
         _httpContextAccessor = httpContextAccessor;
     }
-
-    /// <summary>
-    /// 获取用户信息
-    /// </summary>
-    /// <param name="userId"></param>
-    /// <returns></returns>
-    public async Task<SysUser> CheckUserAsync(long userId)
-    {
-        var user = await _sysUserRep.GetFirstAsync(u => u.Id == userId);
-        return user ?? throw Oops.Oh(ErrorCodeEnum.D1002);
-    }
 }

+ 23 - 2
Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarRepository.cs

@@ -10,7 +10,28 @@ public class SqlSugarRepository<T> : SimpleClient<T> where T : class, new()
 
     public SqlSugarRepository(ISqlSugarClient context = null) : base(context)
     {
-        iTenant = App.GetService<ISqlSugarClient>().AsTenant();
-        base.Context = iTenant.GetConnectionScopeWithAttr<T>();
+        iTenant = App.GetRequiredService<ISqlSugarClient>().AsTenant();
+
+        // 根据当前租户Id切换数据库
+        var tenantId = App.GetRequiredService<UserManager>().TenantId;
+        if (tenantId > 1)
+        {
+            var tenant = App.GetRequiredService<SysCacheService>().Get<List<SysTenant>>(CacheConst.KeyTenant).FirstOrDefault(u => u.Id == tenantId);
+            if (!iTenant.IsAnyConnection(tenant.ConfigId))
+            {
+                iTenant.AddConnection(new ConnectionConfig()
+                {
+                    ConfigId = tenant.ConfigId,
+                    ConnectionString = tenant.Connection,
+                    DbType = tenant.DbType,
+                    IsAutoCloseConnection = true
+                });
+            }
+            base.Context = iTenant.GetConnectionScope(tenant.ConfigId);
+        }
+        else
+        {
+            base.Context = iTenant.GetConnectionScopeWithAttr<T>();
+        }
     }
 }

+ 200 - 113
Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarSetup.cs

@@ -11,6 +11,34 @@ public static class SqlSugarSetup
     public static void AddSqlSugar(this IServiceCollection services)
     {
         var dbOptions = App.GetOptions<DbConnectionOptions>();
+        dbOptions.ConnectionConfigs.ForEach(config =>
+        {
+            SetDbConfig(config);
+        });
+
+        SqlSugarScope sqlSugar = new(dbOptions.ConnectionConfigs.Adapt<List<ConnectionConfig>>(), client =>
+        {
+            dbOptions.ConnectionConfigs.ForEach(config =>
+            {
+                var db = client.GetConnectionScope((string)config.ConfigId);
+                SetDbAop(db, config);
+            });
+        });
+
+        // 初始化数据库表结构及种子数据
+        InitDataBase(sqlSugar, dbOptions);
+
+        services.AddSingleton<ISqlSugarClient>(sqlSugar); // 单例注册
+        services.AddScoped(typeof(SqlSugarRepository<>)); // 仓储注册
+        services.AddUnitOfWork<SqlSugarUnitOfWork>(); // 注册事务与工作单元
+    }
+
+    /// <summary>
+    /// 配置连接属性
+    /// </summary>
+    /// <param name="config"></param>
+    public static void SetDbConfig(DbConnectionConfig config)
+    {
         var configureExternalServices = new ConfigureExternalServices
         {
             EntityService = (type, column) => // 修改列可空-1、带?问号 2、String类型若没有Required
@@ -21,127 +49,117 @@ public static class SqlSugarSetup
             },
             DataInfoCacheService = new SqlSugarCache(),
         };
-        dbOptions.ConnectionConfigs.ForEach(config =>
+        config.ConfigureExternalServices = configureExternalServices;
+        config.InitKeyType = InitKeyType.Attribute;
+        config.IsAutoCloseConnection = true;
+        config.MoreSettings = new ConnMoreSettings
         {
-            config.ConfigureExternalServices = configureExternalServices;
-            config.InitKeyType = InitKeyType.Attribute;
-            config.IsAutoCloseConnection = true;
-            config.MoreSettings = new ConnMoreSettings
-            {
-                IsAutoRemoveDataCache = true
-            };
-        });
+            IsAutoRemoveDataCache = true
+        };
+    }
 
-        SqlSugarScope sqlSugar = new(dbOptions.ConnectionConfigs.Adapt<List<ConnectionConfig>>(), client =>
-        {
-            dbOptions.ConnectionConfigs.ForEach(config =>
-            {
-                var db = client.GetConnectionScope((string)config.ConfigId);
+    /// <summary>
+    /// 配置Aop
+    /// </summary>
+    /// <param name="db"></param>
+    /// <param name="config"></param>
+    public static void SetDbAop(this SqlSugarScopeProvider db, DbConnectionConfig config)
+    {
+        // 设置超时时间
+        db.Ado.CommandTimeOut = 30;
 
-                // 设置超时时间
-                db.Ado.CommandTimeOut = 30;
+        // 打印SQL语句
+        db.Aop.OnLogExecuting = (sql, pars) =>
+        {
+            if (sql.StartsWith("SELECT", StringComparison.OrdinalIgnoreCase))
+                Console.ForegroundColor = ConsoleColor.Green;
+            if (sql.StartsWith("UPDATE", StringComparison.OrdinalIgnoreCase) || sql.StartsWith("INSERT", StringComparison.OrdinalIgnoreCase))
+                Console.ForegroundColor = ConsoleColor.White;
+            if (sql.StartsWith("DELETE", StringComparison.OrdinalIgnoreCase))
+                Console.ForegroundColor = ConsoleColor.Blue;
+            Console.WriteLine("【" + DateTime.Now + "——执行SQL】\r\n" + UtilMethods.GetSqlString(config.DbType, sql, pars) + "\r\n");
+            App.PrintToMiniProfiler("SqlSugar", "Info", sql + "\r\n" + db.Utilities.SerializeObject(pars.ToDictionary(it => it.ParameterName, it => it.Value)));
+        };
+        db.Aop.OnError = (ex) =>
+        {
+            if (ex.Parametres == null) return;
+            Console.ForegroundColor = ConsoleColor.Red;
+            var pars = db.Utilities.SerializeObject(((SugarParameter[])ex.Parametres).ToDictionary(it => it.ParameterName, it => it.Value));
+            Console.WriteLine("【" + DateTime.Now + "——错误SQL】\r\n" + UtilMethods.GetSqlString(config.DbType, ex.Sql, (SugarParameter[])ex.Parametres) + "\r\n");
+            App.PrintToMiniProfiler("SqlSugar", "Error", $"{ex.Message}{Environment.NewLine}{ex.Sql}{pars}{Environment.NewLine}");
+        };
 
-                // 打印SQL语句
-                db.Aop.OnLogExecuting = (sql, pars) =>
-                {
-                    if (sql.StartsWith("SELECT", StringComparison.OrdinalIgnoreCase))
-                        Console.ForegroundColor = ConsoleColor.Green;
-                    if (sql.StartsWith("UPDATE", StringComparison.OrdinalIgnoreCase) || sql.StartsWith("INSERT", StringComparison.OrdinalIgnoreCase))
-                        Console.ForegroundColor = ConsoleColor.White;
-                    if (sql.StartsWith("DELETE", StringComparison.OrdinalIgnoreCase))
-                        Console.ForegroundColor = ConsoleColor.Blue;
-                    Console.WriteLine("【" + DateTime.Now + "——执行SQL】\r\n" + UtilMethods.GetSqlString(config.DbType, sql, pars) + "\r\n");
-                    App.PrintToMiniProfiler("SqlSugar", "Info", sql + "\r\n" + db.Utilities.SerializeObject(pars.ToDictionary(it => it.ParameterName, it => it.Value)));
-                };
-                db.Aop.OnError = (ex) =>
+        // 数据审计
+        db.Aop.DataExecuting = (oldValue, entityInfo) =>
+        {
+            // 新增操作
+            if (entityInfo.OperationType == DataFilterType.InsertByObject)
+            {
+                // 主键(long类型)且没有值的---赋值雪花Id
+                if (entityInfo.EntityColumnInfo.IsPrimarykey && entityInfo.EntityColumnInfo.PropertyInfo.PropertyType == typeof(long))
                 {
-                    if (ex.Parametres == null) return;
-                    Console.ForegroundColor = ConsoleColor.Red;
-                    var pars = db.Utilities.SerializeObject(((SugarParameter[])ex.Parametres).ToDictionary(it => it.ParameterName, it => it.Value));
-                    Console.WriteLine("【" + DateTime.Now + "——错误SQL】\r\n" + UtilMethods.GetSqlString(config.DbType, ex.Sql, (SugarParameter[])ex.Parametres) + "\r\n");
-                    App.PrintToMiniProfiler("SqlSugar", "Error", $"{ex.Message}{Environment.NewLine}{ex.Sql}{pars}{Environment.NewLine}");
-                };
-
-                // 数据审计
-                db.Aop.DataExecuting = (oldValue, entityInfo) =>
+                    var id = entityInfo.EntityColumnInfo.PropertyInfo.GetValue(entityInfo.EntityValue);
+                    if (id == null || (long)id == 0)
+                        entityInfo.SetValue(Yitter.IdGenerator.YitIdHelper.NextId());
+                }
+                if (entityInfo.PropertyName == "CreateTime")
+                    entityInfo.SetValue(DateTime.Now);
+                if (App.User != null)
                 {
-                    // 新增操作
-                    if (entityInfo.OperationType == DataFilterType.InsertByObject)
+                    if (entityInfo.PropertyName == "TenantId")
                     {
-                        // 主键(long类型)且没有值的---赋值雪花Id
-                        if (entityInfo.EntityColumnInfo.IsPrimarykey && entityInfo.EntityColumnInfo.PropertyInfo.PropertyType == typeof(long))
-                        {
-                            var id = entityInfo.EntityColumnInfo.PropertyInfo.GetValue(entityInfo.EntityValue);
-                            if (id == null || (long)id == 0)
-                                entityInfo.SetValue(Yitter.IdGenerator.YitIdHelper.NextId());
-                        }
-                        if (entityInfo.PropertyName == "CreateTime")
-                            entityInfo.SetValue(DateTime.Now);
-                        if (App.User != null)
-                        {
-                            if (entityInfo.PropertyName == "TenantId")
-                            {
-                                var tenantId = ((dynamic)entityInfo.EntityValue).TenantId;
-                                if (tenantId == null || tenantId == 0)
-                                    entityInfo.SetValue(App.User.FindFirst(ClaimConst.TenantId)?.Value);
-                            }
-                            if (entityInfo.PropertyName == "CreateUserId")
-                                entityInfo.SetValue(App.User.FindFirst(ClaimConst.UserId)?.Value);
-                            if (entityInfo.PropertyName == "CreateOrgId")
-                                entityInfo.SetValue(App.User.FindFirst(ClaimConst.OrgId)?.Value);
-                        }
+                        var tenantId = ((dynamic)entityInfo.EntityValue).TenantId;
+                        if (tenantId == null || tenantId == 0)
+                            entityInfo.SetValue(App.User.FindFirst(ClaimConst.TenantId)?.Value);
                     }
-                    // 更新操作
-                    if (entityInfo.OperationType == DataFilterType.UpdateByObject)
-                    {
-                        if (entityInfo.PropertyName == "UpdateTime")
-                            entityInfo.SetValue(DateTime.Now);
-                        if (entityInfo.PropertyName == "UpdateUserId")
-                            entityInfo.SetValue(App.User?.FindFirst(ClaimConst.UserId)?.Value);
-                    }
-                };
-
-                // 差异日志
-                db.Aop.OnDiffLogEvent = async u =>
-                {
-                    if (!config.EnableDiffLog) return;
-
-                    var LogDiff = new SysLogDiff
-                    {
-                        // 操作后记录(字段描述、列名、值、表名、表描述)
-                        AfterData = JsonConvert.SerializeObject(u.AfterData),
-                        // 操作前记录(字段描述、列名、值、表名、表描述)
-                        BeforeData = JsonConvert.SerializeObject(u.BeforeData),
-                        // 传进来的对象
-                        BusinessData = JsonConvert.SerializeObject(u.BusinessData),
-                        // 枚举(insert、update、delete)
-                        DiffType = u.DiffType.ToString(),
-                        Sql = UtilMethods.GetSqlString(config.DbType, u.Sql, u.Parameters),
-                        Parameters = JsonConvert.SerializeObject(u.Parameters),
-                        Duration = u.Time == null ? 0 : (long)u.Time.Value.TotalMilliseconds
-                    };
-                    await client.GetConnectionScope(SqlSugarConst.ConfigId).Insertable(LogDiff).ExecuteCommandAsync();
-                    Console.ForegroundColor = ConsoleColor.Red;
-                    Console.WriteLine(DateTime.Now + $"\r\n**********差异日志开始**********\r\n{Environment.NewLine}{JsonConvert.SerializeObject(LogDiff)}{Environment.NewLine}**********差异日志结束**********\r\n");
-                };
-
-                // 配置实体假删除过滤器
-                SetDeletedEntityFilter(db);
-                // 配置租户过滤器
-                SetTenantEntityFilter(db);
-                // 配置用户机构范围过滤器
-                SetOrgEntityFilter(db);
-                // 配置自定义过滤器
-                SetCustomEntityFilter(db);
-            });
-        });
-
-        // 初始化数据库表结构及种子数据
-        InitDataBase(sqlSugar, dbOptions);
+                    if (entityInfo.PropertyName == "CreateUserId")
+                        entityInfo.SetValue(App.User.FindFirst(ClaimConst.UserId)?.Value);
+                    if (entityInfo.PropertyName == "CreateOrgId")
+                        entityInfo.SetValue(App.User.FindFirst(ClaimConst.OrgId)?.Value);
+                }
+            }
+            // 更新操作
+            if (entityInfo.OperationType == DataFilterType.UpdateByObject)
+            {
+                if (entityInfo.PropertyName == "UpdateTime")
+                    entityInfo.SetValue(DateTime.Now);
+                if (entityInfo.PropertyName == "UpdateUserId")
+                    entityInfo.SetValue(App.User?.FindFirst(ClaimConst.UserId)?.Value);
+            }
+        };
 
-        services.AddSingleton<ISqlSugarClient>(sqlSugar); // 单例注册
-        services.AddScoped(typeof(SqlSugarRepository<>)); // 注册仓储
-        services.AddUnitOfWork<SqlSugarUnitOfWork>(); // 注册事务与工作单元
+        //// 差异日志
+        //db.Aop.OnDiffLogEvent = async u =>
+        //{
+        //    if (!config.EnableDiffLog) return;
+
+        //    var LogDiff = new SysLogDiff
+        //    {
+        //        // 操作后记录(字段描述、列名、值、表名、表描述)
+        //        AfterData = JsonConvert.SerializeObject(u.AfterData),
+        //        // 操作前记录(字段描述、列名、值、表名、表描述)
+        //        BeforeData = JsonConvert.SerializeObject(u.BeforeData),
+        //        // 传进来的对象
+        //        BusinessData = JsonConvert.SerializeObject(u.BusinessData),
+        //        // 枚举(insert、update、delete)
+        //        DiffType = u.DiffType.ToString(),
+        //        Sql = UtilMethods.GetSqlString(config.DbType, u.Sql, u.Parameters),
+        //        Parameters = JsonConvert.SerializeObject(u.Parameters),
+        //        Duration = u.Time == null ? 0 : (long)u.Time.Value.TotalMilliseconds
+        //    };
+        //    await client.GetConnectionScope(SqlSugarConst.ConfigId).Insertable(LogDiff).ExecuteCommandAsync();
+        //    Console.ForegroundColor = ConsoleColor.Red;
+        //    Console.WriteLine(DateTime.Now + $"\r\n**********差异日志开始**********\r\n{Environment.NewLine}{JsonConvert.SerializeObject(LogDiff)}{Environment.NewLine}**********差异日志结束**********\r\n");
+        //};
+
+        // 配置实体假删除过滤器
+        SetDeletedEntityFilter(db);
+        // 配置租户过滤器
+        SetTenantEntityFilter(db);
+        // 配置用户机构范围过滤器
+        SetOrgEntityFilter(db);
+        // 配置自定义过滤器
+        SetCustomEntityFilter(db);
     }
 
     /// <summary>
@@ -208,6 +226,75 @@ public static class SqlSugarSetup
         }
     }
 
+    /// <summary>
+    /// 初始化数据库结构
+    /// </summary>
+    public static void CreateDataBase(ISqlSugarClient db, DbConnectionConfig config, long tenantId)
+    {
+        SetDbConfig(config);
+
+        var itenant = db.AsTenant();
+        // 创建数据库
+        if (!config.EnableInitDb || config.DbType == SqlSugar.DbType.Oracle) return;
+        itenant.AddConnection(config);
+        var dbProvider = itenant.GetConnectionScope(config.ConfigId);
+        SetDbAop(dbProvider, config);
+        dbProvider.DbMaintenance.CreateDatabase();
+
+        // 获取所有实体表-初始化表结构
+        var entityTypes = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass
+            && u.IsDefined(typeof(SugarTable), false) && !u.IsDefined(typeof(NotTableAttribute), false));
+        if (!entityTypes.Any()) return;
+        foreach (var entityType in entityTypes)
+        {
+            var tAtt = entityType.GetCustomAttribute<TenantAttribute>();
+            if (tAtt != null) continue;
+            var db2 = itenant.GetConnectionScope(config.ConfigId);
+            var splitTable = entityType.GetCustomAttribute<SplitTableAttribute>();
+            if (splitTable == null)
+                db2.CodeFirst.InitTables(entityType);
+            else
+                db2.CodeFirst.SplitTables().InitTables(entityType);
+        }
+
+        // 获取所有种子配置-初始化数据
+        var seedDataTypes = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass
+            && u.GetInterfaces().Any(i => i.HasImplementedRawGeneric(typeof(ISqlSugarEntitySeedData<>))));
+        if (!seedDataTypes.Any()) return;
+        foreach (var seedType in seedDataTypes)
+        {
+            var instance = Activator.CreateInstance(seedType);
+
+            var hasDataMethod = seedType.GetMethod("HasData");
+            var seedData = ((IEnumerable)hasDataMethod?.Invoke(instance, null))?.Cast<object>();
+            if (seedData == null) continue;
+
+            var entityType = seedType.GetInterfaces().First().GetGenericArguments().First();
+            var tAtt = entityType.GetCustomAttribute<TenantAttribute>();
+            if (tAtt != null) continue;
+            var db2 = itenant.GetConnectionScope(config.ConfigId);
+            var seedDataTable = seedData.ToList().ToDataTable();
+            seedDataTable.TableName = db.EntityMaintenance.GetEntityInfo(entityType).DbTableName;
+            // 设置租户Id
+            if (seedDataTable.Columns.Contains(SqlSugarConst.TenantId))
+            {
+                foreach (DataRow dr in seedDataTable.Rows)                
+                    dr[SqlSugarConst.TenantId] = tenantId;                
+            }
+            if (seedDataTable.Columns.Contains(SqlSugarConst.PrimaryKey))
+            {
+                var storage = db2.Storageable(seedDataTable).WhereColumns(SqlSugarConst.PrimaryKey).ToStorage();
+                storage.AsInsertable.ExecuteCommand();
+                storage.AsUpdateable.ExecuteCommand();
+            }
+            else // 没有主键或者不是预定义的主键(没主键有重复的可能)
+            {
+                var storage = db2.Storageable(seedDataTable).ToStorage();
+                storage.AsInsertable.ExecuteCommand();
+            }
+        }
+    }
+
     /// <summary>
     /// 配置实体假删除过滤器
     /// </summary>
@@ -305,7 +392,7 @@ public static class SqlSugarSetup
         if (tableFilterItemList == null)
         {
             // 获取用户所属机构
-            var orgIds = App.GetService<SysCacheService>().GetOrgIdList(long.Parse(userId));
+            var orgIds = App.GetService<SysCacheService>().Get<List<long>>(CacheConst.KeyOrgIdList + userId);
             if (orgIds == null || orgIds.Count == 0) return;
 
             // 获取业务实体数据表

+ 1 - 1
Admin.NET/Admin.NET.Web.Core/Admin.NET.Web.Core.csproj

@@ -11,7 +11,7 @@
   </ItemGroup>
 
   <ItemGroup>
-    <PackageReference Include="AspNet.Security.OAuth.Weixin" Version="6.0.12" />
+    <PackageReference Include="AspNet.Security.OAuth.Weixin" Version="6.0.14" />
     <PackageReference Include="IGeekFan.AspNetCore.Knife4jUI" Version="0.0.12" />
   </ItemGroup>
 

+ 2 - 1
Admin.NET/Admin.NET.Web.Core/Startup.cs

@@ -1,4 +1,5 @@
 using Admin.NET.Core;
+using Admin.NET.Core.Service;
 using AspNetCoreRateLimit;
 using Furion;
 using Furion.SpecificationDocument;
@@ -21,7 +22,7 @@ namespace Admin.NET.Web.Core;
 
 public class Startup : AppStartup
 {
-    public void ConfigureServices(IServiceCollection services)
+    public async void ConfigureServices(IServiceCollection services)
     {
         // 配置选项
         services.AddProjectOptions();

+ 175 - 37
Web/src/api-services/apis/sys-auth-api.ts

@@ -16,6 +16,8 @@ import { Configuration } from '../configuration';
 // Some imports not used depending on template conditions
 // @ts-ignore
 import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError } from '../base';
+import { AdminResultBoolean } from '../models';
+import { AdminResultListSysTenant } from '../models';
 import { AdminResultLoginOutput } from '../models';
 import { AdminResultLoginUserOutput } from '../models';
 import { AdminResultObject } from '../models';
@@ -29,12 +31,12 @@ export const SysAuthApiAxiosParamCreator = function (configuration?: Configurati
     return {
         /**
          * 
-         * @summary 生成图片验证码
+         * @summary 是否启用验证码
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        captchaGet: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
-            const localVarPath = `/captcha`;
+        captchaFlagGet: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/captchaFlag`;
             // use dummy base URL string because the URL constructor only accepts absolute URLs.
             const localVarUrlObj = new URL(localVarPath, 'https://example.com');
             let baseOptions;
@@ -65,33 +67,24 @@ export const SysAuthApiAxiosParamCreator = function (configuration?: Configurati
         },
         /**
          * 
-         * @summary 获取刷新Token
-         * @param {string} accessToken 
+         * @summary 生成图片验证码
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        getRefreshTokenPost: async (accessToken: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
-            // verify required parameter 'accessToken' is not null or undefined
-            if (accessToken === null || accessToken === undefined) {
-                throw new RequiredError('accessToken','Required parameter accessToken was null or undefined when calling getRefreshTokenPost.');
-            }
-            const localVarPath = `/getRefreshToken`;
+        captchaGet: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/captcha`;
             // 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: 'POST', ...baseOptions, ...options};
+            const localVarRequestOptions :AxiosRequestConfig = { method: 'GET', ...baseOptions, ...options};
             const localVarHeaderParameter = {} as any;
             const localVarQueryParameter = {} as any;
 
             // authentication Bearer required
 
-            if (accessToken !== undefined) {
-                localVarQueryParameter['accessToken'] = accessToken;
-            }
-
             const query = new URLSearchParams(localVarUrlObj.search);
             for (const key in localVarQueryParameter) {
                 query.set(key, localVarQueryParameter[key]);
@@ -189,6 +182,51 @@ export const SysAuthApiAxiosParamCreator = function (configuration?: Configurati
                 options: localVarRequestOptions,
             };
         },
+        /**
+         * 
+         * @summary 获取刷新Token
+         * @param {string} accessToken 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        refreshTokenPost: async (accessToken: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            // verify required parameter 'accessToken' is not null or undefined
+            if (accessToken === null || accessToken === undefined) {
+                throw new RequiredError('accessToken','Required parameter accessToken was null or undefined when calling refreshTokenPost.');
+            }
+            const localVarPath = `/refreshToken`;
+            // 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: 'POST', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+            // authentication Bearer required
+
+            if (accessToken !== undefined) {
+                localVarQueryParameter['accessToken'] = accessToken;
+            }
+
+            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 Swagger登录检查
@@ -275,6 +313,42 @@ export const SysAuthApiAxiosParamCreator = function (configuration?: Configurati
                 options: localVarRequestOptions,
             };
         },
+        /**
+         * 
+         * @summary 是否启用多库租户
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        tenantDbListGet: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/tenantDbList`;
+            // 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 获取用户信息
@@ -322,12 +396,12 @@ export const SysAuthApiFp = function(configuration?: Configuration) {
     return {
         /**
          * 
-         * @summary 生成图片验证码
+         * @summary 是否启用验证码
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async captchaGet(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultObject>>> {
-            const localVarAxiosArgs = await SysAuthApiAxiosParamCreator(configuration).captchaGet(options);
+        async captchaFlagGet(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultBoolean>>> {
+            const localVarAxiosArgs = await SysAuthApiAxiosParamCreator(configuration).captchaFlagGet(options);
             return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
                 const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
                 return axios.request(axiosRequestArgs);
@@ -335,13 +409,12 @@ export const SysAuthApiFp = function(configuration?: Configuration) {
         },
         /**
          * 
-         * @summary 获取刷新Token
-         * @param {string} accessToken 
+         * @summary 生成图片验证码
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async getRefreshTokenPost(accessToken: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultString>>> {
-            const localVarAxiosArgs = await SysAuthApiAxiosParamCreator(configuration).getRefreshTokenPost(accessToken, options);
+        async captchaGet(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultObject>>> {
+            const localVarAxiosArgs = await SysAuthApiAxiosParamCreator(configuration).captchaGet(options);
             return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
                 const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
                 return axios.request(axiosRequestArgs);
@@ -374,6 +447,20 @@ export const SysAuthApiFp = function(configuration?: Configuration) {
                 return axios.request(axiosRequestArgs);
             };
         },
+        /**
+         * 
+         * @summary 获取刷新Token
+         * @param {string} accessToken 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async refreshTokenPost(accessToken: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultString>>> {
+            const localVarAxiosArgs = await SysAuthApiAxiosParamCreator(configuration).refreshTokenPost(accessToken, options);
+            return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
+                const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
+                return axios.request(axiosRequestArgs);
+            };
+        },
         /**
          * 
          * @summary Swagger登录检查
@@ -402,6 +489,19 @@ export const SysAuthApiFp = function(configuration?: Configuration) {
                 return axios.request(axiosRequestArgs);
             };
         },
+        /**
+         * 
+         * @summary 是否启用多库租户
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async tenantDbListGet(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultListSysTenant>>> {
+            const localVarAxiosArgs = await SysAuthApiAxiosParamCreator(configuration).tenantDbListGet(options);
+            return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
+                const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
+                return axios.request(axiosRequestArgs);
+            };
+        },
         /**
          * 
          * @summary 获取用户信息
@@ -426,22 +526,21 @@ export const SysAuthApiFactory = function (configuration?: Configuration, basePa
     return {
         /**
          * 
-         * @summary 生成图片验证码
+         * @summary 是否启用验证码
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async captchaGet(options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultObject>> {
-            return SysAuthApiFp(configuration).captchaGet(options).then((request) => request(axios, basePath));
+        async captchaFlagGet(options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultBoolean>> {
+            return SysAuthApiFp(configuration).captchaFlagGet(options).then((request) => request(axios, basePath));
         },
         /**
          * 
-         * @summary 获取刷新Token
-         * @param {string} accessToken 
+         * @summary 生成图片验证码
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async getRefreshTokenPost(accessToken: string, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultString>> {
-            return SysAuthApiFp(configuration).getRefreshTokenPost(accessToken, options).then((request) => request(axios, basePath));
+        async captchaGet(options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultObject>> {
+            return SysAuthApiFp(configuration).captchaGet(options).then((request) => request(axios, basePath));
         },
         /**
          * 用户名/密码:superadmin/123456
@@ -462,6 +561,16 @@ export const SysAuthApiFactory = function (configuration?: Configuration, basePa
         async logoutPost(options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
             return SysAuthApiFp(configuration).logoutPost(options).then((request) => request(axios, basePath));
         },
+        /**
+         * 
+         * @summary 获取刷新Token
+         * @param {string} accessToken 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async refreshTokenPost(accessToken: string, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultString>> {
+            return SysAuthApiFp(configuration).refreshTokenPost(accessToken, options).then((request) => request(axios, basePath));
+        },
         /**
          * 
          * @summary Swagger登录检查
@@ -482,6 +591,15 @@ export const SysAuthApiFactory = function (configuration?: Configuration, basePa
         async swaggerSubmitUrlPostForm(userName?: string, password?: string, options?: AxiosRequestConfig): Promise<AxiosResponse<number>> {
             return SysAuthApiFp(configuration).swaggerSubmitUrlPostForm(userName, password, options).then((request) => request(axios, basePath));
         },
+        /**
+         * 
+         * @summary 是否启用多库租户
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async tenantDbListGet(options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultListSysTenant>> {
+            return SysAuthApiFp(configuration).tenantDbListGet(options).then((request) => request(axios, basePath));
+        },
         /**
          * 
          * @summary 获取用户信息
@@ -503,24 +621,23 @@ export const SysAuthApiFactory = function (configuration?: Configuration, basePa
 export class SysAuthApi extends BaseAPI {
     /**
      * 
-     * @summary 生成图片验证码
+     * @summary 是否启用验证码
      * @param {*} [options] Override http request option.
      * @throws {RequiredError}
      * @memberof SysAuthApi
      */
-    public async captchaGet(options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultObject>> {
-        return SysAuthApiFp(this.configuration).captchaGet(options).then((request) => request(this.axios, this.basePath));
+    public async captchaFlagGet(options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultBoolean>> {
+        return SysAuthApiFp(this.configuration).captchaFlagGet(options).then((request) => request(this.axios, this.basePath));
     }
     /**
      * 
-     * @summary 获取刷新Token
-     * @param {string} accessToken 
+     * @summary 生成图片验证码
      * @param {*} [options] Override http request option.
      * @throws {RequiredError}
      * @memberof SysAuthApi
      */
-    public async getRefreshTokenPost(accessToken: string, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultString>> {
-        return SysAuthApiFp(this.configuration).getRefreshTokenPost(accessToken, options).then((request) => request(this.axios, this.basePath));
+    public async captchaGet(options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultObject>> {
+        return SysAuthApiFp(this.configuration).captchaGet(options).then((request) => request(this.axios, this.basePath));
     }
     /**
      * 用户名/密码:superadmin/123456
@@ -543,6 +660,17 @@ export class SysAuthApi extends BaseAPI {
     public async logoutPost(options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
         return SysAuthApiFp(this.configuration).logoutPost(options).then((request) => request(this.axios, this.basePath));
     }
+    /**
+     * 
+     * @summary 获取刷新Token
+     * @param {string} accessToken 
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof SysAuthApi
+     */
+    public async refreshTokenPost(accessToken: string, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultString>> {
+        return SysAuthApiFp(this.configuration).refreshTokenPost(accessToken, options).then((request) => request(this.axios, this.basePath));
+    }
     /**
      * 
      * @summary Swagger登录检查
@@ -565,6 +693,16 @@ export class SysAuthApi extends BaseAPI {
     public async swaggerSubmitUrlPostForm(userName?: string, password?: string, options?: AxiosRequestConfig) : Promise<AxiosResponse<number>> {
         return SysAuthApiFp(this.configuration).swaggerSubmitUrlPostForm(userName, password, options).then((request) => request(this.axios, this.basePath));
     }
+    /**
+     * 
+     * @summary 是否启用多库租户
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof SysAuthApi
+     */
+    public async tenantDbListGet(options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultListSysTenant>> {
+        return SysAuthApiFp(this.configuration).tenantDbListGet(options).then((request) => request(this.axios, this.basePath));
+    }
     /**
      * 
      * @summary 获取用户信息

+ 32 - 32
Web/src/api-services/apis/sys-cache-api.ts

@@ -207,13 +207,12 @@ export const SysCacheApiAxiosParamCreator = function (configuration?: Configurat
         },
         /**
          * 
-         * @summary 获取缓存
-         * @param {string} [cacheKey] 
+         * @summary 获取所有缓存键名
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        sysCacheDetailGet: async (cacheKey?: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
-            const localVarPath = `/sysCache/detail`;
+        sysCacheKeyListGet: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/sysCache/keyList`;
             // use dummy base URL string because the URL constructor only accepts absolute URLs.
             const localVarUrlObj = new URL(localVarPath, 'https://example.com');
             let baseOptions;
@@ -226,10 +225,6 @@ export const SysCacheApiAxiosParamCreator = function (configuration?: Configurat
 
             // authentication Bearer required
 
-            if (cacheKey !== undefined) {
-                localVarQueryParameter['cacheKey'] = cacheKey;
-            }
-
             const query = new URLSearchParams(localVarUrlObj.search);
             for (const key in localVarQueryParameter) {
                 query.set(key, localVarQueryParameter[key]);
@@ -248,12 +243,13 @@ export const SysCacheApiAxiosParamCreator = function (configuration?: Configurat
         },
         /**
          * 
-         * @summary 获取所有缓存键名
+         * @summary 获取缓存值
+         * @param {string} [key] 
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        sysCacheKeyListGet: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
-            const localVarPath = `/sysCache/keyList`;
+        sysCacheValueGet: async (key?: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/sysCache/value`;
             // use dummy base URL string because the URL constructor only accepts absolute URLs.
             const localVarUrlObj = new URL(localVarPath, 'https://example.com');
             let baseOptions;
@@ -266,6 +262,10 @@ export const SysCacheApiAxiosParamCreator = function (configuration?: Configurat
 
             // authentication Bearer required
 
+            if (key !== undefined) {
+                localVarQueryParameter['key'] = key;
+            }
+
             const query = new URLSearchParams(localVarUrlObj.search);
             for (const key in localVarQueryParameter) {
                 query.set(key, localVarQueryParameter[key]);
@@ -352,13 +352,12 @@ export const SysCacheApiFp = function(configuration?: Configuration) {
         },
         /**
          * 
-         * @summary 获取缓存
-         * @param {string} [cacheKey] 
+         * @summary 获取所有缓存键名
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async sysCacheDetailGet(cacheKey?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultObject>>> {
-            const localVarAxiosArgs = await SysCacheApiAxiosParamCreator(configuration).sysCacheDetailGet(cacheKey, options);
+        async sysCacheKeyListGet(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultListString>>> {
+            const localVarAxiosArgs = await SysCacheApiAxiosParamCreator(configuration).sysCacheKeyListGet(options);
             return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
                 const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
                 return axios.request(axiosRequestArgs);
@@ -366,12 +365,13 @@ export const SysCacheApiFp = function(configuration?: Configuration) {
         },
         /**
          * 
-         * @summary 获取所有缓存键名
+         * @summary 获取缓存值
+         * @param {string} [key] 
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async sysCacheKeyListGet(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultListString>>> {
-            const localVarAxiosArgs = await SysCacheApiAxiosParamCreator(configuration).sysCacheKeyListGet(options);
+        async sysCacheValueGet(key?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultObject>>> {
+            const localVarAxiosArgs = await SysCacheApiAxiosParamCreator(configuration).sysCacheValueGet(key, options);
             return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
                 const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
                 return axios.request(axiosRequestArgs);
@@ -431,22 +431,22 @@ export const SysCacheApiFactory = function (configuration?: Configuration, baseP
         },
         /**
          * 
-         * @summary 获取缓存
-         * @param {string} [cacheKey] 
+         * @summary 获取所有缓存键名
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async sysCacheDetailGet(cacheKey?: string, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultObject>> {
-            return SysCacheApiFp(configuration).sysCacheDetailGet(cacheKey, options).then((request) => request(axios, basePath));
+        async sysCacheKeyListGet(options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultListString>> {
+            return SysCacheApiFp(configuration).sysCacheKeyListGet(options).then((request) => request(axios, basePath));
         },
         /**
          * 
-         * @summary 获取所有缓存键名
+         * @summary 获取缓存值
+         * @param {string} [key] 
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async sysCacheKeyListGet(options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultListString>> {
-            return SysCacheApiFp(configuration).sysCacheKeyListGet(options).then((request) => request(axios, basePath));
+        async sysCacheValueGet(key?: string, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultObject>> {
+            return SysCacheApiFp(configuration).sysCacheValueGet(key, options).then((request) => request(axios, basePath));
         },
     };
 };
@@ -507,23 +507,23 @@ export class SysCacheApi extends BaseAPI {
     }
     /**
      * 
-     * @summary 获取缓存
-     * @param {string} [cacheKey] 
+     * @summary 获取所有缓存键名
      * @param {*} [options] Override http request option.
      * @throws {RequiredError}
      * @memberof SysCacheApi
      */
-    public async sysCacheDetailGet(cacheKey?: string, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultObject>> {
-        return SysCacheApiFp(this.configuration).sysCacheDetailGet(cacheKey, options).then((request) => request(this.axios, this.basePath));
+    public async sysCacheKeyListGet(options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultListString>> {
+        return SysCacheApiFp(this.configuration).sysCacheKeyListGet(options).then((request) => request(this.axios, this.basePath));
     }
     /**
      * 
-     * @summary 获取所有缓存键名
+     * @summary 获取缓存值
+     * @param {string} [key] 
      * @param {*} [options] Override http request option.
      * @throws {RequiredError}
      * @memberof SysCacheApi
      */
-    public async sysCacheKeyListGet(options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultListString>> {
-        return SysCacheApiFp(this.configuration).sysCacheKeyListGet(options).then((request) => request(this.axios, this.basePath));
+    public async sysCacheValueGet(key?: string, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultObject>> {
+        return SysCacheApiFp(this.configuration).sysCacheValueGet(key, options).then((request) => request(this.axios, this.basePath));
     }
 }

+ 222 - 354
Web/src/api-services/apis/sys-notice-api.ts

@@ -17,11 +17,11 @@ import { Configuration } from '../configuration';
 // @ts-ignore
 import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError } from '../base';
 import { AddNoticeInput } from '../models';
-import { AdminResultNoticeDetailOutput } from '../models';
-import { AdminResultObject } from '../models';
-import { ChangeStatusNoticeInput } from '../models';
+import { AdminResultListSysNotice } from '../models';
+import { AdminResultSqlSugarPagedListSysNotice } from '../models';
+import { AdminResultSqlSugarPagedListSysNoticeUser } from '../models';
 import { DeleteNoticeInput } from '../models';
-import { NoticeStatusEnum } from '../models';
+import { NoticeInput } from '../models';
 import { NoticeTypeEnum } from '../models';
 import { UpdateNoticeInput } from '../models';
 /**
@@ -73,13 +73,13 @@ export const SysNoticeApiAxiosParamCreator = function (configuration?: Configura
         },
         /**
          * 
-         * @summary 修改通知公告状态
-         * @param {ChangeStatusNoticeInput} [body] 
+         * @summary 删除通知公告
+         * @param {DeleteNoticeInput} [body] 
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        sysNoticeChangeStatusPost: async (body?: ChangeStatusNoticeInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
-            const localVarPath = `/sysNotice/changeStatus`;
+        sysNoticeDeletePost: async (body?: DeleteNoticeInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/sysNotice/delete`;
             // use dummy base URL string because the URL constructor only accepts absolute URLs.
             const localVarUrlObj = new URL(localVarPath, 'https://example.com');
             let baseOptions;
@@ -114,26 +114,58 @@ export const SysNoticeApiAxiosParamCreator = function (configuration?: Configura
         },
         /**
          * 
-         * @summary 删除通知公告
-         * @param {DeleteNoticeInput} [body] 
+         * @summary 获取通知公告分页列表
+         * @param {string} [title] 标题
+         * @param {NoticeTypeEnum} [type] 类型(1通知 2公告)
+         * @param {number} [page] 当前页码
+         * @param {number} [pageSize] 页码容量
+         * @param {string} [field] 排序字段
+         * @param {string} [order] 排序方向
+         * @param {string} [descStr] 降序排序
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        sysNoticeDeletePost: async (body?: DeleteNoticeInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
-            const localVarPath = `/sysNotice/delete`;
+        sysNoticePageGet: async (title?: string, type?: NoticeTypeEnum, page?: number, pageSize?: number, field?: string, order?: string, descStr?: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/sysNotice/page`;
             // 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: 'POST', ...baseOptions, ...options};
+            const localVarRequestOptions :AxiosRequestConfig = { method: 'GET', ...baseOptions, ...options};
             const localVarHeaderParameter = {} as any;
             const localVarQueryParameter = {} as any;
 
             // authentication Bearer required
 
-            localVarHeaderParameter['Content-Type'] = 'application/json-patch+json';
+            if (title !== undefined) {
+                localVarQueryParameter['Title'] = title;
+            }
+
+            if (type !== undefined) {
+                localVarQueryParameter['Type'] = type;
+            }
+
+            if (page !== undefined) {
+                localVarQueryParameter['Page'] = page;
+            }
+
+            if (pageSize !== undefined) {
+                localVarQueryParameter['PageSize'] = pageSize;
+            }
+
+            if (field !== undefined) {
+                localVarQueryParameter['Field'] = field;
+            }
+
+            if (order !== undefined) {
+                localVarQueryParameter['Order'] = order;
+            }
+
+            if (descStr !== undefined) {
+                localVarQueryParameter['DescStr'] = descStr;
+            }
 
             const query = new URLSearchParams(localVarUrlObj.search);
             for (const key in localVarQueryParameter) {
@@ -145,8 +177,6 @@ export const SysNoticeApiAxiosParamCreator = function (configuration?: Configura
             localVarUrlObj.search = (new URLSearchParams(query)).toString();
             let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
             localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
-            const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
-            localVarRequestOptions.data =  needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
 
             return {
                 url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
@@ -155,17 +185,19 @@ export const SysNoticeApiAxiosParamCreator = function (configuration?: Configura
         },
         /**
          * 
-         * @summary 获取通知公告详情
-         * @param {number} id Id
+         * @summary 获取接收的通知公告(当前用户)
+         * @param {string} [title] 标题
+         * @param {NoticeTypeEnum} [type] 类型(1通知 2公告)
+         * @param {number} [page] 当前页码
+         * @param {number} [pageSize] 页码容量
+         * @param {string} [field] 排序字段
+         * @param {string} [order] 排序方向
+         * @param {string} [descStr] 降序排序
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        sysNoticeDetailGet: async (id: number, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
-            // verify required parameter 'id' is not null or undefined
-            if (id === null || id === undefined) {
-                throw new RequiredError('id','Required parameter id was null or undefined when calling sysNoticeDetailGet.');
-            }
-            const localVarPath = `/sysNotice/detail`;
+        sysNoticePageReceivedGet: async (title?: string, type?: NoticeTypeEnum, page?: number, pageSize?: number, field?: string, order?: string, descStr?: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/sysNotice/pageReceived`;
             // use dummy base URL string because the URL constructor only accepts absolute URLs.
             const localVarUrlObj = new URL(localVarPath, 'https://example.com');
             let baseOptions;
@@ -178,8 +210,32 @@ export const SysNoticeApiAxiosParamCreator = function (configuration?: Configura
 
             // authentication Bearer required
 
-            if (id !== undefined) {
-                localVarQueryParameter['Id'] = id;
+            if (title !== undefined) {
+                localVarQueryParameter['Title'] = title;
+            }
+
+            if (type !== undefined) {
+                localVarQueryParameter['Type'] = type;
+            }
+
+            if (page !== undefined) {
+                localVarQueryParameter['Page'] = page;
+            }
+
+            if (pageSize !== undefined) {
+                localVarQueryParameter['PageSize'] = pageSize;
+            }
+
+            if (field !== undefined) {
+                localVarQueryParameter['Field'] = field;
+            }
+
+            if (order !== undefined) {
+                localVarQueryParameter['Order'] = order;
+            }
+
+            if (descStr !== undefined) {
+                localVarQueryParameter['DescStr'] = descStr;
             }
 
             const query = new URLSearchParams(localVarUrlObj.search);
@@ -200,13 +256,13 @@ export const SysNoticeApiAxiosParamCreator = function (configuration?: Configura
         },
         /**
          * 
-         * @summary 更新通知公告
-         * @param {UpdateNoticeInput} [body] 
+         * @summary 发布通知公告
+         * @param {NoticeInput} [body] 
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        sysNoticeEditPost: async (body?: UpdateNoticeInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
-            const localVarPath = `/sysNotice/edit`;
+        sysNoticePublicPost: async (body?: NoticeInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/sysNotice/public`;
             // use dummy base URL string because the URL constructor only accepts absolute URLs.
             const localVarUrlObj = new URL(localVarPath, 'https://example.com');
             let baseOptions;
@@ -241,73 +297,26 @@ export const SysNoticeApiAxiosParamCreator = function (configuration?: Configura
         },
         /**
          * 
-         * @summary 分页查询通知公告
-         * @param {string} [title] 标题
-         * @param {string} [content] 内容
-         * @param {NoticeTypeEnum} [type] 类型(字典 1通知 2公告)
-         * @param {NoticeStatusEnum} [status] 状态(字典 0草稿 1发布 2撤回 3删除)
-         * @param {Array<number>} [noticeUserIdList] 通知到的人
-         * @param {number} [page] 当前页码
-         * @param {number} [pageSize] 页码容量
-         * @param {string} [field] 排序字段
-         * @param {string} [order] 排序方向
-         * @param {string} [descStr] 降序排序
+         * @summary 设置通知公告已读状态
+         * @param {NoticeInput} [body] 
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        sysNoticePageGet: async (title?: string, content?: string, type?: NoticeTypeEnum, status?: NoticeStatusEnum, noticeUserIdList?: Array<number>, page?: number, pageSize?: number, field?: string, order?: string, descStr?: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
-            const localVarPath = `/sysNotice/page`;
+        sysNoticeSetReadPost: async (body?: NoticeInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/sysNotice/setRead`;
             // 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 localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
             const localVarHeaderParameter = {} as any;
             const localVarQueryParameter = {} as any;
 
             // authentication Bearer required
 
-            if (title !== undefined) {
-                localVarQueryParameter['Title'] = title;
-            }
-
-            if (content !== undefined) {
-                localVarQueryParameter['Content'] = content;
-            }
-
-            if (type !== undefined) {
-                localVarQueryParameter['Type'] = type;
-            }
-
-            if (status !== undefined) {
-                localVarQueryParameter['Status'] = status;
-            }
-
-            if (noticeUserIdList) {
-                localVarQueryParameter['NoticeUserIdList'] = noticeUserIdList;
-            }
-
-            if (page !== undefined) {
-                localVarQueryParameter['Page'] = page;
-            }
-
-            if (pageSize !== undefined) {
-                localVarQueryParameter['PageSize'] = pageSize;
-            }
-
-            if (field !== undefined) {
-                localVarQueryParameter['Field'] = field;
-            }
-
-            if (order !== undefined) {
-                localVarQueryParameter['Order'] = order;
-            }
-
-            if (descStr !== undefined) {
-                localVarQueryParameter['DescStr'] = descStr;
-            }
+            localVarHeaderParameter['Content-Type'] = 'application/json-patch+json';
 
             const query = new URLSearchParams(localVarUrlObj.search);
             for (const key in localVarQueryParameter) {
@@ -319,6 +328,8 @@ export const SysNoticeApiAxiosParamCreator = function (configuration?: Configura
             localVarUrlObj.search = (new URLSearchParams(query)).toString();
             let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
             localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+            const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
+            localVarRequestOptions.data =  needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
 
             return {
                 url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
@@ -327,22 +338,12 @@ export const SysNoticeApiAxiosParamCreator = function (configuration?: Configura
         },
         /**
          * 
-         * @summary 获取接收的通知公告
-         * @param {string} [title] 标题
-         * @param {string} [content] 内容
-         * @param {NoticeTypeEnum} [type] 类型(字典 1通知 2公告)
-         * @param {NoticeStatusEnum} [status] 状态(字典 0草稿 1发布 2撤回 3删除)
-         * @param {Array<number>} [noticeUserIdList] 通知到的人
-         * @param {number} [page] 当前页码
-         * @param {number} [pageSize] 页码容量
-         * @param {string} [field] 排序字段
-         * @param {string} [order] 排序方向
-         * @param {string} [descStr] 降序排序
+         * @summary 获取未读的通知公告(当前用户)
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        sysNoticeReceivedGet: async (title?: string, content?: string, type?: NoticeTypeEnum, status?: NoticeStatusEnum, noticeUserIdList?: Array<number>, page?: number, pageSize?: number, field?: string, order?: string, descStr?: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
-            const localVarPath = `/sysNotice/received`;
+        sysNoticeUnReadListGet: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/sysNotice/unReadList`;
             // use dummy base URL string because the URL constructor only accepts absolute URLs.
             const localVarUrlObj = new URL(localVarPath, 'https://example.com');
             let baseOptions;
@@ -355,46 +356,6 @@ export const SysNoticeApiAxiosParamCreator = function (configuration?: Configura
 
             // authentication Bearer required
 
-            if (title !== undefined) {
-                localVarQueryParameter['Title'] = title;
-            }
-
-            if (content !== undefined) {
-                localVarQueryParameter['Content'] = content;
-            }
-
-            if (type !== undefined) {
-                localVarQueryParameter['Type'] = type;
-            }
-
-            if (status !== undefined) {
-                localVarQueryParameter['Status'] = status;
-            }
-
-            if (noticeUserIdList) {
-                localVarQueryParameter['NoticeUserIdList'] = noticeUserIdList;
-            }
-
-            if (page !== undefined) {
-                localVarQueryParameter['Page'] = page;
-            }
-
-            if (pageSize !== undefined) {
-                localVarQueryParameter['PageSize'] = pageSize;
-            }
-
-            if (field !== undefined) {
-                localVarQueryParameter['Field'] = field;
-            }
-
-            if (order !== undefined) {
-                localVarQueryParameter['Order'] = order;
-            }
-
-            if (descStr !== undefined) {
-                localVarQueryParameter['DescStr'] = descStr;
-            }
-
             const query = new URLSearchParams(localVarUrlObj.search);
             for (const key in localVarQueryParameter) {
                 query.set(key, localVarQueryParameter[key]);
@@ -413,73 +374,26 @@ export const SysNoticeApiAxiosParamCreator = function (configuration?: Configura
         },
         /**
          * 
-         * @summary 未处理消息
-         * @param {string} [title] 标题
-         * @param {string} [content] 内容
-         * @param {NoticeTypeEnum} [type] 类型(字典 1通知 2公告)
-         * @param {NoticeStatusEnum} [status] 状态(字典 0草稿 1发布 2撤回 3删除)
-         * @param {Array<number>} [noticeUserIdList] 通知到的人
-         * @param {number} [page] 当前页码
-         * @param {number} [pageSize] 页码容量
-         * @param {string} [field] 排序字段
-         * @param {string} [order] 排序方向
-         * @param {string} [descStr] 降序排序
+         * @summary 更新通知公告
+         * @param {UpdateNoticeInput} [body] 
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        sysNoticeUnreadGet: async (title?: string, content?: string, type?: NoticeTypeEnum, status?: NoticeStatusEnum, noticeUserIdList?: Array<number>, page?: number, pageSize?: number, field?: string, order?: string, descStr?: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
-            const localVarPath = `/sysNotice/unread`;
+        sysNoticeUpdatePost: async (body?: UpdateNoticeInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/sysNotice/update`;
             // 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 localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
             const localVarHeaderParameter = {} as any;
             const localVarQueryParameter = {} as any;
 
             // authentication Bearer required
 
-            if (title !== undefined) {
-                localVarQueryParameter['Title'] = title;
-            }
-
-            if (content !== undefined) {
-                localVarQueryParameter['Content'] = content;
-            }
-
-            if (type !== undefined) {
-                localVarQueryParameter['Type'] = type;
-            }
-
-            if (status !== undefined) {
-                localVarQueryParameter['Status'] = status;
-            }
-
-            if (noticeUserIdList) {
-                localVarQueryParameter['NoticeUserIdList'] = noticeUserIdList;
-            }
-
-            if (page !== undefined) {
-                localVarQueryParameter['Page'] = page;
-            }
-
-            if (pageSize !== undefined) {
-                localVarQueryParameter['PageSize'] = pageSize;
-            }
-
-            if (field !== undefined) {
-                localVarQueryParameter['Field'] = field;
-            }
-
-            if (order !== undefined) {
-                localVarQueryParameter['Order'] = order;
-            }
-
-            if (descStr !== undefined) {
-                localVarQueryParameter['DescStr'] = descStr;
-            }
+            localVarHeaderParameter['Content-Type'] = 'application/json-patch+json';
 
             const query = new URLSearchParams(localVarUrlObj.search);
             for (const key in localVarQueryParameter) {
@@ -491,6 +405,8 @@ export const SysNoticeApiAxiosParamCreator = function (configuration?: Configura
             localVarUrlObj.search = (new URLSearchParams(query)).toString();
             let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
             localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+            const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
+            localVarRequestOptions.data =  needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
 
             return {
                 url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
@@ -522,13 +438,13 @@ export const SysNoticeApiFp = function(configuration?: Configuration) {
         },
         /**
          * 
-         * @summary 修改通知公告状态
-         * @param {ChangeStatusNoticeInput} [body] 
+         * @summary 删除通知公告
+         * @param {DeleteNoticeInput} [body] 
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async sysNoticeChangeStatusPost(body?: ChangeStatusNoticeInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<void>>> {
-            const localVarAxiosArgs = await SysNoticeApiAxiosParamCreator(configuration).sysNoticeChangeStatusPost(body, options);
+        async sysNoticeDeletePost(body?: DeleteNoticeInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<void>>> {
+            const localVarAxiosArgs = await SysNoticeApiAxiosParamCreator(configuration).sysNoticeDeletePost(body, options);
             return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
                 const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
                 return axios.request(axiosRequestArgs);
@@ -536,13 +452,19 @@ export const SysNoticeApiFp = function(configuration?: Configuration) {
         },
         /**
          * 
-         * @summary 删除通知公告
-         * @param {DeleteNoticeInput} [body] 
+         * @summary 获取通知公告分页列表
+         * @param {string} [title] 标题
+         * @param {NoticeTypeEnum} [type] 类型(1通知 2公告)
+         * @param {number} [page] 当前页码
+         * @param {number} [pageSize] 页码容量
+         * @param {string} [field] 排序字段
+         * @param {string} [order] 排序方向
+         * @param {string} [descStr] 降序排序
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async sysNoticeDeletePost(body?: DeleteNoticeInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<void>>> {
-            const localVarAxiosArgs = await SysNoticeApiAxiosParamCreator(configuration).sysNoticeDeletePost(body, options);
+        async sysNoticePageGet(title?: string, type?: NoticeTypeEnum, page?: number, pageSize?: number, field?: string, order?: string, descStr?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultSqlSugarPagedListSysNotice>>> {
+            const localVarAxiosArgs = await SysNoticeApiAxiosParamCreator(configuration).sysNoticePageGet(title, type, page, pageSize, field, order, descStr, options);
             return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
                 const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
                 return axios.request(axiosRequestArgs);
@@ -550,13 +472,19 @@ export const SysNoticeApiFp = function(configuration?: Configuration) {
         },
         /**
          * 
-         * @summary 获取通知公告详情
-         * @param {number} id Id
+         * @summary 获取接收的通知公告(当前用户)
+         * @param {string} [title] 标题
+         * @param {NoticeTypeEnum} [type] 类型(1通知 2公告)
+         * @param {number} [page] 当前页码
+         * @param {number} [pageSize] 页码容量
+         * @param {string} [field] 排序字段
+         * @param {string} [order] 排序方向
+         * @param {string} [descStr] 降序排序
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async sysNoticeDetailGet(id: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultNoticeDetailOutput>>> {
-            const localVarAxiosArgs = await SysNoticeApiAxiosParamCreator(configuration).sysNoticeDetailGet(id, options);
+        async sysNoticePageReceivedGet(title?: string, type?: NoticeTypeEnum, page?: number, pageSize?: number, field?: string, order?: string, descStr?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultSqlSugarPagedListSysNoticeUser>>> {
+            const localVarAxiosArgs = await SysNoticeApiAxiosParamCreator(configuration).sysNoticePageReceivedGet(title, type, page, pageSize, field, order, descStr, options);
             return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
                 const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
                 return axios.request(axiosRequestArgs);
@@ -564,13 +492,13 @@ export const SysNoticeApiFp = function(configuration?: Configuration) {
         },
         /**
          * 
-         * @summary 更新通知公告
-         * @param {UpdateNoticeInput} [body] 
+         * @summary 发布通知公告
+         * @param {NoticeInput} [body] 
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async sysNoticeEditPost(body?: UpdateNoticeInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<void>>> {
-            const localVarAxiosArgs = await SysNoticeApiAxiosParamCreator(configuration).sysNoticeEditPost(body, options);
+        async sysNoticePublicPost(body?: NoticeInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<void>>> {
+            const localVarAxiosArgs = await SysNoticeApiAxiosParamCreator(configuration).sysNoticePublicPost(body, options);
             return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
                 const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
                 return axios.request(axiosRequestArgs);
@@ -578,22 +506,13 @@ export const SysNoticeApiFp = function(configuration?: Configuration) {
         },
         /**
          * 
-         * @summary 分页查询通知公告
-         * @param {string} [title] 标题
-         * @param {string} [content] 内容
-         * @param {NoticeTypeEnum} [type] 类型(字典 1通知 2公告)
-         * @param {NoticeStatusEnum} [status] 状态(字典 0草稿 1发布 2撤回 3删除)
-         * @param {Array<number>} [noticeUserIdList] 通知到的人
-         * @param {number} [page] 当前页码
-         * @param {number} [pageSize] 页码容量
-         * @param {string} [field] 排序字段
-         * @param {string} [order] 排序方向
-         * @param {string} [descStr] 降序排序
+         * @summary 设置通知公告已读状态
+         * @param {NoticeInput} [body] 
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async sysNoticePageGet(title?: string, content?: string, type?: NoticeTypeEnum, status?: NoticeStatusEnum, noticeUserIdList?: Array<number>, page?: number, pageSize?: number, field?: string, order?: string, descStr?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultObject>>> {
-            const localVarAxiosArgs = await SysNoticeApiAxiosParamCreator(configuration).sysNoticePageGet(title, content, type, status, noticeUserIdList, page, pageSize, field, order, descStr, options);
+        async sysNoticeSetReadPost(body?: NoticeInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<void>>> {
+            const localVarAxiosArgs = await SysNoticeApiAxiosParamCreator(configuration).sysNoticeSetReadPost(body, options);
             return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
                 const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
                 return axios.request(axiosRequestArgs);
@@ -601,22 +520,12 @@ export const SysNoticeApiFp = function(configuration?: Configuration) {
         },
         /**
          * 
-         * @summary 获取接收的通知公告
-         * @param {string} [title] 标题
-         * @param {string} [content] 内容
-         * @param {NoticeTypeEnum} [type] 类型(字典 1通知 2公告)
-         * @param {NoticeStatusEnum} [status] 状态(字典 0草稿 1发布 2撤回 3删除)
-         * @param {Array<number>} [noticeUserIdList] 通知到的人
-         * @param {number} [page] 当前页码
-         * @param {number} [pageSize] 页码容量
-         * @param {string} [field] 排序字段
-         * @param {string} [order] 排序方向
-         * @param {string} [descStr] 降序排序
+         * @summary 获取未读的通知公告(当前用户)
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async sysNoticeReceivedGet(title?: string, content?: string, type?: NoticeTypeEnum, status?: NoticeStatusEnum, noticeUserIdList?: Array<number>, page?: number, pageSize?: number, field?: string, order?: string, descStr?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultObject>>> {
-            const localVarAxiosArgs = await SysNoticeApiAxiosParamCreator(configuration).sysNoticeReceivedGet(title, content, type, status, noticeUserIdList, page, pageSize, field, order, descStr, options);
+        async sysNoticeUnReadListGet(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultListSysNotice>>> {
+            const localVarAxiosArgs = await SysNoticeApiAxiosParamCreator(configuration).sysNoticeUnReadListGet(options);
             return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
                 const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
                 return axios.request(axiosRequestArgs);
@@ -624,22 +533,13 @@ export const SysNoticeApiFp = function(configuration?: Configuration) {
         },
         /**
          * 
-         * @summary 未处理消息
-         * @param {string} [title] 标题
-         * @param {string} [content] 内容
-         * @param {NoticeTypeEnum} [type] 类型(字典 1通知 2公告)
-         * @param {NoticeStatusEnum} [status] 状态(字典 0草稿 1发布 2撤回 3删除)
-         * @param {Array<number>} [noticeUserIdList] 通知到的人
-         * @param {number} [page] 当前页码
-         * @param {number} [pageSize] 页码容量
-         * @param {string} [field] 排序字段
-         * @param {string} [order] 排序方向
-         * @param {string} [descStr] 降序排序
+         * @summary 更新通知公告
+         * @param {UpdateNoticeInput} [body] 
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async sysNoticeUnreadGet(title?: string, content?: string, type?: NoticeTypeEnum, status?: NoticeStatusEnum, noticeUserIdList?: Array<number>, page?: number, pageSize?: number, field?: string, order?: string, descStr?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultObject>>> {
-            const localVarAxiosArgs = await SysNoticeApiAxiosParamCreator(configuration).sysNoticeUnreadGet(title, content, type, status, noticeUserIdList, page, pageSize, field, order, descStr, options);
+        async sysNoticeUpdatePost(body?: UpdateNoticeInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<void>>> {
+            const localVarAxiosArgs = await SysNoticeApiAxiosParamCreator(configuration).sysNoticeUpdatePost(body, options);
             return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
                 const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
                 return axios.request(axiosRequestArgs);
@@ -666,100 +566,84 @@ export const SysNoticeApiFactory = function (configuration?: Configuration, base
         },
         /**
          * 
-         * @summary 修改通知公告状态
-         * @param {ChangeStatusNoticeInput} [body] 
+         * @summary 删除通知公告
+         * @param {DeleteNoticeInput} [body] 
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async sysNoticeChangeStatusPost(body?: ChangeStatusNoticeInput, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
-            return SysNoticeApiFp(configuration).sysNoticeChangeStatusPost(body, options).then((request) => request(axios, basePath));
+        async sysNoticeDeletePost(body?: DeleteNoticeInput, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
+            return SysNoticeApiFp(configuration).sysNoticeDeletePost(body, options).then((request) => request(axios, basePath));
         },
         /**
          * 
-         * @summary 删除通知公告
-         * @param {DeleteNoticeInput} [body] 
+         * @summary 获取通知公告分页列表
+         * @param {string} [title] 标题
+         * @param {NoticeTypeEnum} [type] 类型(1通知 2公告)
+         * @param {number} [page] 当前页码
+         * @param {number} [pageSize] 页码容量
+         * @param {string} [field] 排序字段
+         * @param {string} [order] 排序方向
+         * @param {string} [descStr] 降序排序
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async sysNoticeDeletePost(body?: DeleteNoticeInput, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
-            return SysNoticeApiFp(configuration).sysNoticeDeletePost(body, options).then((request) => request(axios, basePath));
+        async sysNoticePageGet(title?: string, type?: NoticeTypeEnum, page?: number, pageSize?: number, field?: string, order?: string, descStr?: string, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultSqlSugarPagedListSysNotice>> {
+            return SysNoticeApiFp(configuration).sysNoticePageGet(title, type, page, pageSize, field, order, descStr, options).then((request) => request(axios, basePath));
         },
         /**
          * 
-         * @summary 获取通知公告详情
-         * @param {number} id Id
+         * @summary 获取接收的通知公告(当前用户)
+         * @param {string} [title] 标题
+         * @param {NoticeTypeEnum} [type] 类型(1通知 2公告)
+         * @param {number} [page] 当前页码
+         * @param {number} [pageSize] 页码容量
+         * @param {string} [field] 排序字段
+         * @param {string} [order] 排序方向
+         * @param {string} [descStr] 降序排序
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async sysNoticeDetailGet(id: number, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultNoticeDetailOutput>> {
-            return SysNoticeApiFp(configuration).sysNoticeDetailGet(id, options).then((request) => request(axios, basePath));
+        async sysNoticePageReceivedGet(title?: string, type?: NoticeTypeEnum, page?: number, pageSize?: number, field?: string, order?: string, descStr?: string, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultSqlSugarPagedListSysNoticeUser>> {
+            return SysNoticeApiFp(configuration).sysNoticePageReceivedGet(title, type, page, pageSize, field, order, descStr, options).then((request) => request(axios, basePath));
         },
         /**
          * 
-         * @summary 更新通知公告
-         * @param {UpdateNoticeInput} [body] 
+         * @summary 发布通知公告
+         * @param {NoticeInput} [body] 
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async sysNoticeEditPost(body?: UpdateNoticeInput, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
-            return SysNoticeApiFp(configuration).sysNoticeEditPost(body, options).then((request) => request(axios, basePath));
+        async sysNoticePublicPost(body?: NoticeInput, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
+            return SysNoticeApiFp(configuration).sysNoticePublicPost(body, options).then((request) => request(axios, basePath));
         },
         /**
          * 
-         * @summary 分页查询通知公告
-         * @param {string} [title] 标题
-         * @param {string} [content] 内容
-         * @param {NoticeTypeEnum} [type] 类型(字典 1通知 2公告)
-         * @param {NoticeStatusEnum} [status] 状态(字典 0草稿 1发布 2撤回 3删除)
-         * @param {Array<number>} [noticeUserIdList] 通知到的人
-         * @param {number} [page] 当前页码
-         * @param {number} [pageSize] 页码容量
-         * @param {string} [field] 排序字段
-         * @param {string} [order] 排序方向
-         * @param {string} [descStr] 降序排序
+         * @summary 设置通知公告已读状态
+         * @param {NoticeInput} [body] 
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async sysNoticePageGet(title?: string, content?: string, type?: NoticeTypeEnum, status?: NoticeStatusEnum, noticeUserIdList?: Array<number>, page?: number, pageSize?: number, field?: string, order?: string, descStr?: string, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultObject>> {
-            return SysNoticeApiFp(configuration).sysNoticePageGet(title, content, type, status, noticeUserIdList, page, pageSize, field, order, descStr, options).then((request) => request(axios, basePath));
+        async sysNoticeSetReadPost(body?: NoticeInput, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
+            return SysNoticeApiFp(configuration).sysNoticeSetReadPost(body, options).then((request) => request(axios, basePath));
         },
         /**
          * 
-         * @summary 获取接收的通知公告
-         * @param {string} [title] 标题
-         * @param {string} [content] 内容
-         * @param {NoticeTypeEnum} [type] 类型(字典 1通知 2公告)
-         * @param {NoticeStatusEnum} [status] 状态(字典 0草稿 1发布 2撤回 3删除)
-         * @param {Array<number>} [noticeUserIdList] 通知到的人
-         * @param {number} [page] 当前页码
-         * @param {number} [pageSize] 页码容量
-         * @param {string} [field] 排序字段
-         * @param {string} [order] 排序方向
-         * @param {string} [descStr] 降序排序
+         * @summary 获取未读的通知公告(当前用户)
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async sysNoticeReceivedGet(title?: string, content?: string, type?: NoticeTypeEnum, status?: NoticeStatusEnum, noticeUserIdList?: Array<number>, page?: number, pageSize?: number, field?: string, order?: string, descStr?: string, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultObject>> {
-            return SysNoticeApiFp(configuration).sysNoticeReceivedGet(title, content, type, status, noticeUserIdList, page, pageSize, field, order, descStr, options).then((request) => request(axios, basePath));
+        async sysNoticeUnReadListGet(options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultListSysNotice>> {
+            return SysNoticeApiFp(configuration).sysNoticeUnReadListGet(options).then((request) => request(axios, basePath));
         },
         /**
          * 
-         * @summary 未处理消息
-         * @param {string} [title] 标题
-         * @param {string} [content] 内容
-         * @param {NoticeTypeEnum} [type] 类型(字典 1通知 2公告)
-         * @param {NoticeStatusEnum} [status] 状态(字典 0草稿 1发布 2撤回 3删除)
-         * @param {Array<number>} [noticeUserIdList] 通知到的人
-         * @param {number} [page] 当前页码
-         * @param {number} [pageSize] 页码容量
-         * @param {string} [field] 排序字段
-         * @param {string} [order] 排序方向
-         * @param {string} [descStr] 降序排序
+         * @summary 更新通知公告
+         * @param {UpdateNoticeInput} [body] 
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async sysNoticeUnreadGet(title?: string, content?: string, type?: NoticeTypeEnum, status?: NoticeStatusEnum, noticeUserIdList?: Array<number>, page?: number, pageSize?: number, field?: string, order?: string, descStr?: string, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultObject>> {
-            return SysNoticeApiFp(configuration).sysNoticeUnreadGet(title, content, type, status, noticeUserIdList, page, pageSize, field, order, descStr, options).then((request) => request(axios, basePath));
+        async sysNoticeUpdatePost(body?: UpdateNoticeInput, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
+            return SysNoticeApiFp(configuration).sysNoticeUpdatePost(body, options).then((request) => request(axios, basePath));
         },
     };
 };
@@ -784,106 +668,90 @@ export class SysNoticeApi extends BaseAPI {
     }
     /**
      * 
-     * @summary 修改通知公告状态
-     * @param {ChangeStatusNoticeInput} [body] 
+     * @summary 删除通知公告
+     * @param {DeleteNoticeInput} [body] 
      * @param {*} [options] Override http request option.
      * @throws {RequiredError}
      * @memberof SysNoticeApi
      */
-    public async sysNoticeChangeStatusPost(body?: ChangeStatusNoticeInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
-        return SysNoticeApiFp(this.configuration).sysNoticeChangeStatusPost(body, options).then((request) => request(this.axios, this.basePath));
+    public async sysNoticeDeletePost(body?: DeleteNoticeInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
+        return SysNoticeApiFp(this.configuration).sysNoticeDeletePost(body, options).then((request) => request(this.axios, this.basePath));
     }
     /**
      * 
-     * @summary 删除通知公告
-     * @param {DeleteNoticeInput} [body] 
+     * @summary 获取通知公告分页列表
+     * @param {string} [title] 标题
+     * @param {NoticeTypeEnum} [type] 类型(1通知 2公告)
+     * @param {number} [page] 当前页码
+     * @param {number} [pageSize] 页码容量
+     * @param {string} [field] 排序字段
+     * @param {string} [order] 排序方向
+     * @param {string} [descStr] 降序排序
      * @param {*} [options] Override http request option.
      * @throws {RequiredError}
      * @memberof SysNoticeApi
      */
-    public async sysNoticeDeletePost(body?: DeleteNoticeInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
-        return SysNoticeApiFp(this.configuration).sysNoticeDeletePost(body, options).then((request) => request(this.axios, this.basePath));
+    public async sysNoticePageGet(title?: string, type?: NoticeTypeEnum, page?: number, pageSize?: number, field?: string, order?: string, descStr?: string, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultSqlSugarPagedListSysNotice>> {
+        return SysNoticeApiFp(this.configuration).sysNoticePageGet(title, type, page, pageSize, field, order, descStr, options).then((request) => request(this.axios, this.basePath));
     }
     /**
      * 
-     * @summary 获取通知公告详情
-     * @param {number} id Id
+     * @summary 获取接收的通知公告(当前用户)
+     * @param {string} [title] 标题
+     * @param {NoticeTypeEnum} [type] 类型(1通知 2公告)
+     * @param {number} [page] 当前页码
+     * @param {number} [pageSize] 页码容量
+     * @param {string} [field] 排序字段
+     * @param {string} [order] 排序方向
+     * @param {string} [descStr] 降序排序
      * @param {*} [options] Override http request option.
      * @throws {RequiredError}
      * @memberof SysNoticeApi
      */
-    public async sysNoticeDetailGet(id: number, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultNoticeDetailOutput>> {
-        return SysNoticeApiFp(this.configuration).sysNoticeDetailGet(id, options).then((request) => request(this.axios, this.basePath));
+    public async sysNoticePageReceivedGet(title?: string, type?: NoticeTypeEnum, page?: number, pageSize?: number, field?: string, order?: string, descStr?: string, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultSqlSugarPagedListSysNoticeUser>> {
+        return SysNoticeApiFp(this.configuration).sysNoticePageReceivedGet(title, type, page, pageSize, field, order, descStr, options).then((request) => request(this.axios, this.basePath));
     }
     /**
      * 
-     * @summary 更新通知公告
-     * @param {UpdateNoticeInput} [body] 
+     * @summary 发布通知公告
+     * @param {NoticeInput} [body] 
      * @param {*} [options] Override http request option.
      * @throws {RequiredError}
      * @memberof SysNoticeApi
      */
-    public async sysNoticeEditPost(body?: UpdateNoticeInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
-        return SysNoticeApiFp(this.configuration).sysNoticeEditPost(body, options).then((request) => request(this.axios, this.basePath));
+    public async sysNoticePublicPost(body?: NoticeInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
+        return SysNoticeApiFp(this.configuration).sysNoticePublicPost(body, options).then((request) => request(this.axios, this.basePath));
     }
     /**
      * 
-     * @summary 分页查询通知公告
-     * @param {string} [title] 标题
-     * @param {string} [content] 内容
-     * @param {NoticeTypeEnum} [type] 类型(字典 1通知 2公告)
-     * @param {NoticeStatusEnum} [status] 状态(字典 0草稿 1发布 2撤回 3删除)
-     * @param {Array<number>} [noticeUserIdList] 通知到的人
-     * @param {number} [page] 当前页码
-     * @param {number} [pageSize] 页码容量
-     * @param {string} [field] 排序字段
-     * @param {string} [order] 排序方向
-     * @param {string} [descStr] 降序排序
+     * @summary 设置通知公告已读状态
+     * @param {NoticeInput} [body] 
      * @param {*} [options] Override http request option.
      * @throws {RequiredError}
      * @memberof SysNoticeApi
      */
-    public async sysNoticePageGet(title?: string, content?: string, type?: NoticeTypeEnum, status?: NoticeStatusEnum, noticeUserIdList?: Array<number>, page?: number, pageSize?: number, field?: string, order?: string, descStr?: string, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultObject>> {
-        return SysNoticeApiFp(this.configuration).sysNoticePageGet(title, content, type, status, noticeUserIdList, page, pageSize, field, order, descStr, options).then((request) => request(this.axios, this.basePath));
+    public async sysNoticeSetReadPost(body?: NoticeInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
+        return SysNoticeApiFp(this.configuration).sysNoticeSetReadPost(body, options).then((request) => request(this.axios, this.basePath));
     }
     /**
      * 
-     * @summary 获取接收的通知公告
-     * @param {string} [title] 标题
-     * @param {string} [content] 内容
-     * @param {NoticeTypeEnum} [type] 类型(字典 1通知 2公告)
-     * @param {NoticeStatusEnum} [status] 状态(字典 0草稿 1发布 2撤回 3删除)
-     * @param {Array<number>} [noticeUserIdList] 通知到的人
-     * @param {number} [page] 当前页码
-     * @param {number} [pageSize] 页码容量
-     * @param {string} [field] 排序字段
-     * @param {string} [order] 排序方向
-     * @param {string} [descStr] 降序排序
+     * @summary 获取未读的通知公告(当前用户)
      * @param {*} [options] Override http request option.
      * @throws {RequiredError}
      * @memberof SysNoticeApi
      */
-    public async sysNoticeReceivedGet(title?: string, content?: string, type?: NoticeTypeEnum, status?: NoticeStatusEnum, noticeUserIdList?: Array<number>, page?: number, pageSize?: number, field?: string, order?: string, descStr?: string, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultObject>> {
-        return SysNoticeApiFp(this.configuration).sysNoticeReceivedGet(title, content, type, status, noticeUserIdList, page, pageSize, field, order, descStr, options).then((request) => request(this.axios, this.basePath));
+    public async sysNoticeUnReadListGet(options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultListSysNotice>> {
+        return SysNoticeApiFp(this.configuration).sysNoticeUnReadListGet(options).then((request) => request(this.axios, this.basePath));
     }
     /**
      * 
-     * @summary 未处理消息
-     * @param {string} [title] 标题
-     * @param {string} [content] 内容
-     * @param {NoticeTypeEnum} [type] 类型(字典 1通知 2公告)
-     * @param {NoticeStatusEnum} [status] 状态(字典 0草稿 1发布 2撤回 3删除)
-     * @param {Array<number>} [noticeUserIdList] 通知到的人
-     * @param {number} [page] 当前页码
-     * @param {number} [pageSize] 页码容量
-     * @param {string} [field] 排序字段
-     * @param {string} [order] 排序方向
-     * @param {string} [descStr] 降序排序
+     * @summary 更新通知公告
+     * @param {UpdateNoticeInput} [body] 
      * @param {*} [options] Override http request option.
      * @throws {RequiredError}
      * @memberof SysNoticeApi
      */
-    public async sysNoticeUnreadGet(title?: string, content?: string, type?: NoticeTypeEnum, status?: NoticeStatusEnum, noticeUserIdList?: Array<number>, page?: number, pageSize?: number, field?: string, order?: string, descStr?: string, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultObject>> {
-        return SysNoticeApiFp(this.configuration).sysNoticeUnreadGet(title, content, type, status, noticeUserIdList, page, pageSize, field, order, descStr, options).then((request) => request(this.axios, this.basePath));
+    public async sysNoticeUpdatePost(body?: UpdateNoticeInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
+        return SysNoticeApiFp(this.configuration).sysNoticeUpdatePost(body, options).then((request) => request(this.axios, this.basePath));
     }
 }

+ 76 - 0
Web/src/api-services/apis/sys-tenant-api.ts

@@ -71,6 +71,47 @@ export const SysTenantApiAxiosParamCreator = function (configuration?: Configura
                 options: localVarRequestOptions,
             };
         },
+        /**
+         * 
+         * @summary 创建租户数据库(根据默认库结构)
+         * @param {TenantInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        sysTenantCreateDbPost: async (body?: TenantInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/sysTenant/createDb`;
+            // 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: 'POST', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+            // authentication Bearer required
+
+            localVarHeaderParameter['Content-Type'] = 'application/json-patch+json';
+
+            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};
+            const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
+            localVarRequestOptions.data =  needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
+
+            return {
+                url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
+                options: localVarRequestOptions,
+            };
+        },
         /**
          * 
          * @summary 删除租户
@@ -419,6 +460,20 @@ export const SysTenantApiFp = function(configuration?: Configuration) {
                 return axios.request(axiosRequestArgs);
             };
         },
+        /**
+         * 
+         * @summary 创建租户数据库(根据默认库结构)
+         * @param {TenantInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async sysTenantCreateDbPost(body?: TenantInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<void>>> {
+            const localVarAxiosArgs = await SysTenantApiAxiosParamCreator(configuration).sysTenantCreateDbPost(body, options);
+            return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
+                const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
+                return axios.request(axiosRequestArgs);
+            };
+        },
         /**
          * 
          * @summary 删除租户
@@ -542,6 +597,16 @@ export const SysTenantApiFactory = function (configuration?: Configuration, base
         async sysTenantAddPost(body?: AddTenantInput, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
             return SysTenantApiFp(configuration).sysTenantAddPost(body, options).then((request) => request(axios, basePath));
         },
+        /**
+         * 
+         * @summary 创建租户数据库(根据默认库结构)
+         * @param {TenantInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async sysTenantCreateDbPost(body?: TenantInput, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
+            return SysTenantApiFp(configuration).sysTenantCreateDbPost(body, options).then((request) => request(axios, basePath));
+        },
         /**
          * 
          * @summary 删除租户
@@ -639,6 +704,17 @@ export class SysTenantApi extends BaseAPI {
     public async sysTenantAddPost(body?: AddTenantInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
         return SysTenantApiFp(this.configuration).sysTenantAddPost(body, options).then((request) => request(this.axios, this.basePath));
     }
+    /**
+     * 
+     * @summary 创建租户数据库(根据默认库结构)
+     * @param {TenantInput} [body] 
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof SysTenantApi
+     */
+    public async sysTenantCreateDbPost(body?: TenantInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
+        return SysTenantApiFp(this.configuration).sysTenantCreateDbPost(body, options).then((request) => request(this.axios, this.basePath));
+    }
     /**
      * 
      * @summary 删除租户

+ 57 - 21
Web/src/api-services/models/add-notice-input.ts

@@ -20,35 +20,41 @@ import { NoticeTypeEnum } from './notice-type-enum';
  */
 export interface AddNoticeInput {
     /**
-     * 当前页码
+     * 雪花Id
      * @type {number}
      * @memberof AddNoticeInput
      */
-    page?: number;
+    id?: number;
     /**
-     * 页码容量
-     * @type {number}
+     * 创建时间
+     * @type {Date}
      * @memberof AddNoticeInput
      */
-    pageSize?: number;
+    createTime?: Date | null;
     /**
-     * 排序字段
-     * @type {string}
+     * 更新时间
+     * @type {Date}
      * @memberof AddNoticeInput
      */
-    field?: string | null;
+    updateTime?: Date | null;
     /**
-     * 排序方向
-     * @type {string}
+     * 创建者Id
+     * @type {number}
      * @memberof AddNoticeInput
      */
-    order?: string | null;
+    createUserId?: number | null;
     /**
-     * 降序排序
-     * @type {string}
+     * 修改者Id
+     * @type {number}
+     * @memberof AddNoticeInput
+     */
+    updateUserId?: number | null;
+    /**
+     * 软删除
+     * @type {boolean}
      * @memberof AddNoticeInput
      */
-    descStr?: string | null;
+    isDelete?: boolean;
     /**
      * 标题
      * @type {string}
@@ -66,17 +72,47 @@ export interface AddNoticeInput {
      * @type {NoticeTypeEnum}
      * @memberof AddNoticeInput
      */
-    type: NoticeTypeEnum;
+    type?: NoticeTypeEnum;
     /**
-     * 
-     * @type {NoticeStatusEnum}
+     * 发布人Id
+     * @type {number}
+     * @memberof AddNoticeInput
+     */
+    publicUserId?: number;
+    /**
+     * 发布人姓名
+     * @type {string}
      * @memberof AddNoticeInput
      */
-    status: NoticeStatusEnum;
+    publicUserName?: string | null;
     /**
-     * 通知到的人
-     * @type {Array<number>}
+     * 发布机构Id
+     * @type {number}
+     * @memberof AddNoticeInput
+     */
+    publicOrgId?: number;
+    /**
+     * 发布机构名称
+     * @type {string}
+     * @memberof AddNoticeInput
+     */
+    publicOrgName?: string | null;
+    /**
+     * 发布时间
+     * @type {Date}
+     * @memberof AddNoticeInput
+     */
+    publicTime?: Date;
+    /**
+     * 撤回时间
+     * @type {Date}
+     * @memberof AddNoticeInput
+     */
+    cancelTime?: Date;
+    /**
+     * 
+     * @type {NoticeStatusEnum}
      * @memberof AddNoticeInput
      */
-    noticeUserIdList: Array<number>;
+    status?: NoticeStatusEnum;
 }

+ 6 - 0
Web/src/api-services/models/add-tenant-input.ts

@@ -91,6 +91,12 @@ export interface AddTenantInput {
      * @memberof AddTenantInput
      */
     connection?: string | null;
+    /**
+     * 数据库标识
+     * @type {string}
+     * @memberof AddTenantInput
+     */
+    configId?: string | null;
     /**
      * 排序
      * @type {number}

+ 12 - 12
Web/src/api-services/models/admin-result-notice-detail-output.ts → Web/src/api-services/models/admin-result-list-sys-notice.ts

@@ -11,47 +11,47 @@
  * https://github.com/swagger-api/swagger-codegen.git
  * Do not edit the class manually.
  */
-import { NoticeDetailOutput } from './notice-detail-output';
+import { SysNotice } from './sys-notice';
 /**
  * 全局返回结果
  * @export
- * @interface AdminResultNoticeDetailOutput
+ * @interface AdminResultListSysNotice
  */
-export interface AdminResultNoticeDetailOutput {
+export interface AdminResultListSysNotice {
     /**
      * 状态码
      * @type {number}
-     * @memberof AdminResultNoticeDetailOutput
+     * @memberof AdminResultListSysNotice
      */
     code?: number;
     /**
      * 类型success、warning、error
      * @type {string}
-     * @memberof AdminResultNoticeDetailOutput
+     * @memberof AdminResultListSysNotice
      */
     type?: string | null;
     /**
      * 错误信息
      * @type {string}
-     * @memberof AdminResultNoticeDetailOutput
+     * @memberof AdminResultListSysNotice
      */
     message?: string | null;
     /**
-     * 
-     * @type {NoticeDetailOutput}
-     * @memberof AdminResultNoticeDetailOutput
+     * 数据
+     * @type {Array<SysNotice>}
+     * @memberof AdminResultListSysNotice
      */
-    result?: NoticeDetailOutput;
+    result?: Array<SysNotice> | null;
     /**
      * 附加数据
      * @type {any}
-     * @memberof AdminResultNoticeDetailOutput
+     * @memberof AdminResultListSysNotice
      */
     extras?: any | null;
     /**
      * 时间
      * @type {Date}
-     * @memberof AdminResultNoticeDetailOutput
+     * @memberof AdminResultListSysNotice
      */
     time?: Date;
 }

+ 57 - 0
Web/src/api-services/models/admin-result-list-sys-tenant.ts

@@ -0,0 +1,57 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * Admin.NET
+ * 让 .NET 开发更简单、更通用、更流行。前后端分离架构(.NET6/Vue3),开箱即用紧随前沿技术。<br/><a href='https://gitee.com/zuohuaijun/Admin.NET/'>https://gitee.com/zuohuaijun/Admin.NET</a>
+ *
+ * OpenAPI spec version: 1.0.0
+ * Contact: 515096995@qq.com
+ *
+ * NOTE: This class is auto generated by the swagger code generator program.
+ * https://github.com/swagger-api/swagger-codegen.git
+ * Do not edit the class manually.
+ */
+import { SysTenant } from './sys-tenant';
+/**
+ * 全局返回结果
+ * @export
+ * @interface AdminResultListSysTenant
+ */
+export interface AdminResultListSysTenant {
+    /**
+     * 状态码
+     * @type {number}
+     * @memberof AdminResultListSysTenant
+     */
+    code?: number;
+    /**
+     * 类型success、warning、error
+     * @type {string}
+     * @memberof AdminResultListSysTenant
+     */
+    type?: string | null;
+    /**
+     * 错误信息
+     * @type {string}
+     * @memberof AdminResultListSysTenant
+     */
+    message?: string | null;
+    /**
+     * 数据
+     * @type {Array<SysTenant>}
+     * @memberof AdminResultListSysTenant
+     */
+    result?: Array<SysTenant> | null;
+    /**
+     * 附加数据
+     * @type {any}
+     * @memberof AdminResultListSysTenant
+     */
+    extras?: any | null;
+    /**
+     * 时间
+     * @type {Date}
+     * @memberof AdminResultListSysTenant
+     */
+    time?: Date;
+}

+ 57 - 0
Web/src/api-services/models/admin-result-sql-sugar-paged-list-sys-notice-user.ts

@@ -0,0 +1,57 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * Admin.NET
+ * 让 .NET 开发更简单、更通用、更流行。前后端分离架构(.NET6/Vue3),开箱即用紧随前沿技术。<br/><a href='https://gitee.com/zuohuaijun/Admin.NET/'>https://gitee.com/zuohuaijun/Admin.NET</a>
+ *
+ * OpenAPI spec version: 1.0.0
+ * Contact: 515096995@qq.com
+ *
+ * NOTE: This class is auto generated by the swagger code generator program.
+ * https://github.com/swagger-api/swagger-codegen.git
+ * Do not edit the class manually.
+ */
+import { SqlSugarPagedListSysNoticeUser } from './sql-sugar-paged-list-sys-notice-user';
+/**
+ * 全局返回结果
+ * @export
+ * @interface AdminResultSqlSugarPagedListSysNoticeUser
+ */
+export interface AdminResultSqlSugarPagedListSysNoticeUser {
+    /**
+     * 状态码
+     * @type {number}
+     * @memberof AdminResultSqlSugarPagedListSysNoticeUser
+     */
+    code?: number;
+    /**
+     * 类型success、warning、error
+     * @type {string}
+     * @memberof AdminResultSqlSugarPagedListSysNoticeUser
+     */
+    type?: string | null;
+    /**
+     * 错误信息
+     * @type {string}
+     * @memberof AdminResultSqlSugarPagedListSysNoticeUser
+     */
+    message?: string | null;
+    /**
+     * 
+     * @type {SqlSugarPagedListSysNoticeUser}
+     * @memberof AdminResultSqlSugarPagedListSysNoticeUser
+     */
+    result?: SqlSugarPagedListSysNoticeUser;
+    /**
+     * 附加数据
+     * @type {any}
+     * @memberof AdminResultSqlSugarPagedListSysNoticeUser
+     */
+    extras?: any | null;
+    /**
+     * 时间
+     * @type {Date}
+     * @memberof AdminResultSqlSugarPagedListSysNoticeUser
+     */
+    time?: Date;
+}

+ 57 - 0
Web/src/api-services/models/admin-result-sql-sugar-paged-list-sys-notice.ts

@@ -0,0 +1,57 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * Admin.NET
+ * 让 .NET 开发更简单、更通用、更流行。前后端分离架构(.NET6/Vue3),开箱即用紧随前沿技术。<br/><a href='https://gitee.com/zuohuaijun/Admin.NET/'>https://gitee.com/zuohuaijun/Admin.NET</a>
+ *
+ * OpenAPI spec version: 1.0.0
+ * Contact: 515096995@qq.com
+ *
+ * NOTE: This class is auto generated by the swagger code generator program.
+ * https://github.com/swagger-api/swagger-codegen.git
+ * Do not edit the class manually.
+ */
+import { SqlSugarPagedListSysNotice } from './sql-sugar-paged-list-sys-notice';
+/**
+ * 全局返回结果
+ * @export
+ * @interface AdminResultSqlSugarPagedListSysNotice
+ */
+export interface AdminResultSqlSugarPagedListSysNotice {
+    /**
+     * 状态码
+     * @type {number}
+     * @memberof AdminResultSqlSugarPagedListSysNotice
+     */
+    code?: number;
+    /**
+     * 类型success、warning、error
+     * @type {string}
+     * @memberof AdminResultSqlSugarPagedListSysNotice
+     */
+    type?: string | null;
+    /**
+     * 错误信息
+     * @type {string}
+     * @memberof AdminResultSqlSugarPagedListSysNotice
+     */
+    message?: string | null;
+    /**
+     * 
+     * @type {SqlSugarPagedListSysNotice}
+     * @memberof AdminResultSqlSugarPagedListSysNotice
+     */
+    result?: SqlSugarPagedListSysNotice;
+    /**
+     * 附加数据
+     * @type {any}
+     * @memberof AdminResultSqlSugarPagedListSysNotice
+     */
+    extras?: any | null;
+    /**
+     * 时间
+     * @type {Date}
+     * @memberof AdminResultSqlSugarPagedListSysNotice
+     */
+    time?: Date;
+}

+ 1 - 1
Web/src/api-services/models/delete-notice-input.ts

@@ -18,7 +18,7 @@
  */
 export interface DeleteNoticeInput {
     /**
-     * Id
+     * 主键Id
      * @type {number}
      * @memberof DeleteNoticeInput
      */

+ 9 - 4
Web/src/api-services/models/index.ts

@@ -32,15 +32,16 @@ export * from './admin-result-list-sys-config';
 export * from './admin-result-list-sys-dict-data';
 export * from './admin-result-list-sys-dict-type';
 export * from './admin-result-list-sys-menu';
+export * from './admin-result-list-sys-notice';
 export * from './admin-result-list-sys-org';
 export * from './admin-result-list-sys-pos';
 export * from './admin-result-list-sys-region';
+export * from './admin-result-list-sys-tenant';
 export * from './admin-result-list-sys-user-ext-org';
 export * from './admin-result-list-table-column-ouput';
 export * from './admin-result-list-table-output';
 export * from './admin-result-login-output';
 export * from './admin-result-login-user-output';
-export * from './admin-result-notice-detail-output';
 export * from './admin-result-object';
 export * from './admin-result-sql-sugar-paged-list-sys-code-gen';
 export * from './admin-result-sql-sugar-paged-list-sys-config';
@@ -51,6 +52,8 @@ export * from './admin-result-sql-sugar-paged-list-sys-log-diff';
 export * from './admin-result-sql-sugar-paged-list-sys-log-ex';
 export * from './admin-result-sql-sugar-paged-list-sys-log-op';
 export * from './admin-result-sql-sugar-paged-list-sys-log-vis';
+export * from './admin-result-sql-sugar-paged-list-sys-notice';
+export * from './admin-result-sql-sugar-paged-list-sys-notice-user';
 export * from './admin-result-sql-sugar-paged-list-sys-online-user';
 export * from './admin-result-sql-sugar-paged-list-sys-region';
 export * from './admin-result-sql-sugar-paged-list-sys-role';
@@ -68,7 +71,6 @@ export * from './admin-result-we-chat-pay';
 export * from './admin-result-we-chat-pay-output';
 export * from './card-type-enum';
 export * from './change-pwd-input';
-export * from './change-status-notice-input';
 export * from './code-gen-config';
 export * from './create-entity-input';
 export * from './culture-level-enum';
@@ -111,10 +113,9 @@ export * from './menu-output';
 export * from './menu-type-enum';
 export * from './message-input';
 export * from './message-type-enum';
-export * from './notice-detail-output';
+export * from './notice-input';
 export * from './notice-status-enum';
 export * from './notice-type-enum';
-export * from './notice-user-read';
 export * from './notice-user-status-enum';
 export * from './request-type-enum';
 export * from './reset-pwd-user-input';
@@ -137,6 +138,8 @@ export * from './sql-sugar-paged-list-sys-log-diff';
 export * from './sql-sugar-paged-list-sys-log-ex';
 export * from './sql-sugar-paged-list-sys-log-op';
 export * from './sql-sugar-paged-list-sys-log-vis';
+export * from './sql-sugar-paged-list-sys-notice';
+export * from './sql-sugar-paged-list-sys-notice-user';
 export * from './sql-sugar-paged-list-sys-online-user';
 export * from './sql-sugar-paged-list-sys-region';
 export * from './sql-sugar-paged-list-sys-role';
@@ -161,6 +164,8 @@ export * from './sys-log-op';
 export * from './sys-log-vis';
 export * from './sys-menu';
 export * from './sys-menu-meta';
+export * from './sys-notice';
+export * from './sys-notice-user';
 export * from './sys-online-user';
 export * from './sys-org';
 export * from './sys-pos';

+ 6 - 0
Web/src/api-services/models/login-input.ts

@@ -41,4 +41,10 @@ export interface LoginInput {
      * @memberof LoginInput
      */
     code?: string | null;
+    /**
+     * 租户Id
+     * @type {number}
+     * @memberof LoginInput
+     */
+    tenantId?: number;
 }

+ 4 - 11
Web/src/api-services/models/change-status-notice-input.ts → Web/src/api-services/models/notice-input.ts

@@ -11,23 +11,16 @@
  * https://github.com/swagger-api/swagger-codegen.git
  * Do not edit the class manually.
  */
-import { NoticeStatusEnum } from './notice-status-enum';
 /**
  * 
  * @export
- * @interface ChangeStatusNoticeInput
+ * @interface NoticeInput
  */
-export interface ChangeStatusNoticeInput {
+export interface NoticeInput {
     /**
-     * Id
+     * 主键Id
      * @type {number}
-     * @memberof ChangeStatusNoticeInput
+     * @memberof NoticeInput
      */
     id: number;
-    /**
-     * 
-     * @type {NoticeStatusEnum}
-     * @memberof ChangeStatusNoticeInput
-     */
-    status: NoticeStatusEnum;
 }

+ 63 - 0
Web/src/api-services/models/sql-sugar-paged-list-sys-notice-user.ts

@@ -0,0 +1,63 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * Admin.NET
+ * 让 .NET 开发更简单、更通用、更流行。前后端分离架构(.NET6/Vue3),开箱即用紧随前沿技术。<br/><a href='https://gitee.com/zuohuaijun/Admin.NET/'>https://gitee.com/zuohuaijun/Admin.NET</a>
+ *
+ * OpenAPI spec version: 1.0.0
+ * Contact: 515096995@qq.com
+ *
+ * NOTE: This class is auto generated by the swagger code generator program.
+ * https://github.com/swagger-api/swagger-codegen.git
+ * Do not edit the class manually.
+ */
+import { SysNoticeUser } from './sys-notice-user';
+/**
+ * 分页泛型集合
+ * @export
+ * @interface SqlSugarPagedListSysNoticeUser
+ */
+export interface SqlSugarPagedListSysNoticeUser {
+    /**
+     * 页码
+     * @type {number}
+     * @memberof SqlSugarPagedListSysNoticeUser
+     */
+    page?: number;
+    /**
+     * 页容量
+     * @type {number}
+     * @memberof SqlSugarPagedListSysNoticeUser
+     */
+    pageSize?: number;
+    /**
+     * 总条数
+     * @type {number}
+     * @memberof SqlSugarPagedListSysNoticeUser
+     */
+    total?: number;
+    /**
+     * 总页数
+     * @type {number}
+     * @memberof SqlSugarPagedListSysNoticeUser
+     */
+    totalPages?: number;
+    /**
+     * 当前页集合
+     * @type {Array<SysNoticeUser>}
+     * @memberof SqlSugarPagedListSysNoticeUser
+     */
+    items?: Array<SysNoticeUser> | null;
+    /**
+     * 是否有上一页
+     * @type {boolean}
+     * @memberof SqlSugarPagedListSysNoticeUser
+     */
+    hasPrevPage?: boolean;
+    /**
+     * 是否有下一页
+     * @type {boolean}
+     * @memberof SqlSugarPagedListSysNoticeUser
+     */
+    hasNextPage?: boolean;
+}

+ 63 - 0
Web/src/api-services/models/sql-sugar-paged-list-sys-notice.ts

@@ -0,0 +1,63 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * Admin.NET
+ * 让 .NET 开发更简单、更通用、更流行。前后端分离架构(.NET6/Vue3),开箱即用紧随前沿技术。<br/><a href='https://gitee.com/zuohuaijun/Admin.NET/'>https://gitee.com/zuohuaijun/Admin.NET</a>
+ *
+ * OpenAPI spec version: 1.0.0
+ * Contact: 515096995@qq.com
+ *
+ * NOTE: This class is auto generated by the swagger code generator program.
+ * https://github.com/swagger-api/swagger-codegen.git
+ * Do not edit the class manually.
+ */
+import { SysNotice } from './sys-notice';
+/**
+ * 分页泛型集合
+ * @export
+ * @interface SqlSugarPagedListSysNotice
+ */
+export interface SqlSugarPagedListSysNotice {
+    /**
+     * 页码
+     * @type {number}
+     * @memberof SqlSugarPagedListSysNotice
+     */
+    page?: number;
+    /**
+     * 页容量
+     * @type {number}
+     * @memberof SqlSugarPagedListSysNotice
+     */
+    pageSize?: number;
+    /**
+     * 总条数
+     * @type {number}
+     * @memberof SqlSugarPagedListSysNotice
+     */
+    total?: number;
+    /**
+     * 总页数
+     * @type {number}
+     * @memberof SqlSugarPagedListSysNotice
+     */
+    totalPages?: number;
+    /**
+     * 当前页集合
+     * @type {Array<SysNotice>}
+     * @memberof SqlSugarPagedListSysNotice
+     */
+    items?: Array<SysNotice> | null;
+    /**
+     * 是否有上一页
+     * @type {boolean}
+     * @memberof SqlSugarPagedListSysNotice
+     */
+    hasPrevPage?: boolean;
+    /**
+     * 是否有下一页
+     * @type {boolean}
+     * @memberof SqlSugarPagedListSysNotice
+     */
+    hasNextPage?: boolean;
+}

+ 22 - 15
Web/src/api-services/models/notice-user-read.ts → Web/src/api-services/models/sys-notice-user.ts

@@ -12,34 +12,41 @@
  * Do not edit the class manually.
  */
 import { NoticeUserStatusEnum } from './notice-user-status-enum';
+import { SysNotice } from './sys-notice';
 /**
- * 
+ * 系统通知公告用户表
  * @export
- * @interface NoticeUserRead
+ * @interface SysNoticeUser
  */
-export interface NoticeUserRead {
+export interface SysNoticeUser {
     /**
-     * 用户Id
+     * 通知公告Id
      * @type {number}
-     * @memberof NoticeUserRead
+     * @memberof SysNoticeUser
      */
-    userId?: number;
+    noticeId?: number;
     /**
-     * 用户名称
-     * @type {string}
-     * @memberof NoticeUserRead
+     * 
+     * @type {SysNotice}
+     * @memberof SysNoticeUser
      */
-    userName?: string | null;
+    sysNotice?: SysNotice;
     /**
-     * 
-     * @type {NoticeUserStatusEnum}
-     * @memberof NoticeUserRead
+     * 用户Id
+     * @type {number}
+     * @memberof SysNoticeUser
      */
-    readStatus?: NoticeUserStatusEnum;
+    userId?: number;
     /**
      * 阅读时间
      * @type {Date}
-     * @memberof NoticeUserRead
+     * @memberof SysNoticeUser
      */
     readTime?: Date;
+    /**
+     * 
+     * @type {NoticeUserStatusEnum}
+     * @memberof SysNoticeUser
+     */
+    readStatus?: NoticeUserStatusEnum;
 }

+ 59 - 34
Web/src/api-services/models/notice-detail-output.ts → Web/src/api-services/models/sys-notice.ts

@@ -11,83 +11,108 @@
  * https://github.com/swagger-api/swagger-codegen.git
  * Do not edit the class manually.
  */
-import { NoticeUserRead } from './notice-user-read';
+import { NoticeStatusEnum } from './notice-status-enum';
+import { NoticeTypeEnum } from './notice-type-enum';
 /**
- * 系统通知公告详情参数
+ * 系统通知公告
  * @export
- * @interface NoticeDetailOutput
+ * @interface SysNotice
  */
-export interface NoticeDetailOutput {
+export interface SysNotice {
+    /**
+     * 雪花Id
+     * @type {number}
+     * @memberof SysNotice
+     */
+    id?: number;
+    /**
+     * 创建时间
+     * @type {Date}
+     * @memberof SysNotice
+     */
+    createTime?: Date | null;
+    /**
+     * 更新时间
+     * @type {Date}
+     * @memberof SysNotice
+     */
+    updateTime?: Date | null;
+    /**
+     * 创建者Id
+     * @type {number}
+     * @memberof SysNotice
+     */
+    createUserId?: number | null;
+    /**
+     * 修改者Id
+     * @type {number}
+     * @memberof SysNotice
+     */
+    updateUserId?: number | null;
+    /**
+     * 软删除
+     * @type {boolean}
+     * @memberof SysNotice
+     */
+    isDelete?: boolean;
     /**
      * 标题
      * @type {string}
-     * @memberof NoticeDetailOutput
+     * @memberof SysNotice
      */
-    title?: string | null;
+    title: string;
     /**
      * 内容
      * @type {string}
-     * @memberof NoticeDetailOutput
+     * @memberof SysNotice
      */
-    content?: string | null;
+    content: string;
     /**
-     * 类型(字典 1通知 2公告)
-     * @type {number}
-     * @memberof NoticeDetailOutput
+     * 
+     * @type {NoticeTypeEnum}
+     * @memberof SysNotice
      */
-    type?: number;
+    type?: NoticeTypeEnum;
     /**
      * 发布人Id
      * @type {number}
-     * @memberof NoticeDetailOutput
+     * @memberof SysNotice
      */
     publicUserId?: number;
     /**
      * 发布人姓名
      * @type {string}
-     * @memberof NoticeDetailOutput
+     * @memberof SysNotice
      */
     publicUserName?: string | null;
     /**
      * 发布机构Id
      * @type {number}
-     * @memberof NoticeDetailOutput
+     * @memberof SysNotice
      */
     publicOrgId?: number;
     /**
      * 发布机构名称
      * @type {string}
-     * @memberof NoticeDetailOutput
+     * @memberof SysNotice
      */
     publicOrgName?: string | null;
     /**
      * 发布时间
      * @type {Date}
-     * @memberof NoticeDetailOutput
+     * @memberof SysNotice
      */
     publicTime?: Date;
     /**
      * 撤回时间
      * @type {Date}
-     * @memberof NoticeDetailOutput
+     * @memberof SysNotice
      */
     cancelTime?: Date;
     /**
-     * 状态(字典 0草稿 1发布 2撤回 3删除)
-     * @type {number}
-     * @memberof NoticeDetailOutput
-     */
-    status?: number;
-    /**
-     * 通知到的用户Id集合
-     * @type {Array<string>}
-     * @memberof NoticeDetailOutput
-     */
-    noticeUserIdList?: Array<string> | null;
-    /**
-     * 通知到的用户阅读信息集合
-     * @type {Array<NoticeUserRead>}
-     * @memberof NoticeDetailOutput
+     * 
+     * @type {NoticeStatusEnum}
+     * @memberof SysNotice
      */
-    noticeUserReadInfoList?: Array<NoticeUserRead> | null;
+    status?: NoticeStatusEnum;
 }

+ 6 - 0
Web/src/api-services/models/sys-tenant.ts

@@ -103,6 +103,12 @@ export interface SysTenant {
      * @memberof SysTenant
      */
     connection?: string | null;
+    /**
+     * 数据库标识
+     * @type {string}
+     * @memberof SysTenant
+     */
+    configId?: string | null;
     /**
      * 排序
      * @type {number}

+ 53 - 23
Web/src/api-services/models/update-notice-input.ts

@@ -20,35 +20,41 @@ import { NoticeTypeEnum } from './notice-type-enum';
  */
 export interface UpdateNoticeInput {
     /**
-     * 当前页码
+     * 雪花Id
      * @type {number}
      * @memberof UpdateNoticeInput
      */
-    page?: number;
+    id?: number;
     /**
-     * 页码容量
-     * @type {number}
+     * 创建时间
+     * @type {Date}
      * @memberof UpdateNoticeInput
      */
-    pageSize?: number;
+    createTime?: Date | null;
     /**
-     * 排序字段
-     * @type {string}
+     * 更新时间
+     * @type {Date}
      * @memberof UpdateNoticeInput
      */
-    field?: string | null;
+    updateTime?: Date | null;
     /**
-     * 排序方向
-     * @type {string}
+     * 创建者Id
+     * @type {number}
      * @memberof UpdateNoticeInput
      */
-    order?: string | null;
+    createUserId?: number | null;
     /**
-     * 降序排序
-     * @type {string}
+     * 修改者Id
+     * @type {number}
+     * @memberof UpdateNoticeInput
+     */
+    updateUserId?: number | null;
+    /**
+     * 软删除
+     * @type {boolean}
      * @memberof UpdateNoticeInput
      */
-    descStr?: string | null;
+    isDelete?: boolean;
     /**
      * 标题
      * @type {string}
@@ -66,23 +72,47 @@ export interface UpdateNoticeInput {
      * @type {NoticeTypeEnum}
      * @memberof UpdateNoticeInput
      */
-    type: NoticeTypeEnum;
+    type?: NoticeTypeEnum;
     /**
-     * 
-     * @type {NoticeStatusEnum}
+     * 发布人Id
+     * @type {number}
      * @memberof UpdateNoticeInput
      */
-    status: NoticeStatusEnum;
+    publicUserId?: number;
     /**
-     * 通知到的人
-     * @type {Array<number>}
+     * 发布人姓名
+     * @type {string}
      * @memberof UpdateNoticeInput
      */
-    noticeUserIdList: Array<number>;
+    publicUserName?: string | null;
     /**
-     * Id
+     * 发布机构Id
      * @type {number}
      * @memberof UpdateNoticeInput
      */
-    id: number;
+    publicOrgId?: number;
+    /**
+     * 发布机构名称
+     * @type {string}
+     * @memberof UpdateNoticeInput
+     */
+    publicOrgName?: string | null;
+    /**
+     * 发布时间
+     * @type {Date}
+     * @memberof UpdateNoticeInput
+     */
+    publicTime?: Date;
+    /**
+     * 撤回时间
+     * @type {Date}
+     * @memberof UpdateNoticeInput
+     */
+    cancelTime?: Date;
+    /**
+     * 
+     * @type {NoticeStatusEnum}
+     * @memberof UpdateNoticeInput
+     */
+    status?: NoticeStatusEnum;
 }

+ 6 - 0
Web/src/api-services/models/update-tenant-input.ts

@@ -91,6 +91,12 @@ export interface UpdateTenantInput {
      * @memberof UpdateTenantInput
      */
     connection?: string | null;
+    /**
+     * 数据库标识
+     * @type {string}
+     * @memberof UpdateTenantInput
+     */
+    configId?: string | null;
     /**
      * 排序
      * @type {number}

+ 22 - 7
Web/src/layout/navBars/breadcrumb/user.vue

@@ -33,7 +33,7 @@
 			<i class="icon-skin iconfont" :title="$t('message.user.title3')"></i>
 		</div>
 		<div class="layout-navbars-breadcrumb-user-icon">
-			<el-popover placement="bottom" trigger="click" transition="el-zoom-in-top" :width="300" :persistent="false">
+			<el-popover placement="bottom" trigger="hover" transition="el-zoom-in-top" :width="300" :persistent="false">
 				<template #reference>
 					<el-badge :is-dot="true">
 						<el-icon :title="$t('message.user.title4')">
@@ -41,9 +41,7 @@
 						</el-icon>
 					</el-badge>
 				</template>
-				<template #default>
-					<UserNews />
-				</template>
+				<UserNews :noticeList="noticeList" />
 			</el-popover>
 		</div>
 		<div class="layout-navbars-breadcrumb-user-icon" @click="onScreenfullClick">
@@ -78,7 +76,7 @@
 <script lang="ts">
 import { ref, getCurrentInstance, computed, reactive, toRefs, onMounted, defineComponent } from 'vue';
 import { useRouter } from 'vue-router';
-import { ElMessageBox, ElMessage } from 'element-plus';
+import { ElMessageBox, ElMessage, ElNotification } from 'element-plus';
 import screenfull from 'screenfull';
 import { useI18n } from 'vue-i18n';
 import { storeToRefs } from 'pinia';
@@ -91,7 +89,7 @@ import Search from '/@/layout/navBars/breadcrumb/search.vue';
 
 import OnlineUser from '/@/views/system/onlineUser/index.vue';
 import { getAPI } from '/@/utils/axios-utils';
-import { SysAuthApi } from '/@/api-services/api';
+import { SysAuthApi, SysNoticeApi } from '/@/api-services/api';
 
 export default defineComponent({
 	name: 'layoutBreadcrumbUser',
@@ -110,6 +108,7 @@ export default defineComponent({
 			isScreenfull: false,
 			disabledI18n: 'zh-cn',
 			disabledSize: 'large',
+			noticeList: [] as any, // 站内信列表
 		});
 		// 设置分割样式
 		const layoutUserFlexNum = computed(() => {
@@ -236,12 +235,28 @@ export default defineComponent({
 			}
 		};
 		// 页面加载时
-		onMounted(() => {
+		onMounted(async () => {
 			if (Local.get('themeConfig')) {
 				initI18n();
 				initComponentSize();
 			}
+			// 加载未读的站内信
+			var res = await getAPI(SysNoticeApi).sysNoticeUnReadListGet();
+			state.noticeList = res.data.result ?? [];
+
+			// 接收站内信
+			proxy.signalR.on('PublicNotice', reciveNotice);
 		});
+		const reciveNotice = (msg: any) => {
+			state.noticeList.unshift(msg);
+
+			ElNotification({
+				title: '提示',
+				message: '您有一条新消息...',
+				type: 'info',
+				position: 'bottom-right',
+			});
+		};
 		return {
 			userInfos,
 			onLayoutSetingClick,

+ 89 - 85
Web/src/layout/navBars/breadcrumb/userNews.vue

@@ -1,115 +1,119 @@
 <template>
-	<div class="layout-navbars-breadcrumb-user-news">
-		<div class="head-box">
-			<div class="head-box-title">{{ $t('message.user.newTitle') }}</div>
-			<div class="head-box-btn" v-if="newsList.length > 0" @click="onAllReadClick">{{ $t('message.user.newBtn') }}</div>
-		</div>
-		<div class="content-box">
-			<template v-if="newsList.length > 0">
-				<div class="content-box-item" v-for="(v, k) in newsList" :key="k">
-					<div>{{ v.label }}</div>
-					<div class="content-box-msg">
-						{{ v.value }}
-					</div>
-					<div class="content-box-time">{{ v.time }}</div>
+	<div class="user-news-container">
+		<el-tabs stretch class="content-box">
+			<el-tab-pane label="站内信">
+				<template #label>
+					<el-icon><ele-Bell /></el-icon>
+					<span style="margin-left: 5px">站内信</span>
+				</template>
+				<div class="notice-box">
+					<template v-if="noticeList.length > 0">
+						<div class="notice-item" v-for="(v, k) in noticeList" :key="k" @click="viewNoticeDetail(v)" v-show="v.readStatus == 1 ? false : true">
+							<div class="notice-title">{{ v.type == 1 ? '【通知】' : '【公告】' }}{{ v.title }}</div>
+							<div class="notice-content">{{ removeHtmlSub(v.content) }}</div>
+							<div class="notice-time">{{ v.publicTime }}</div>
+							<el-divider border-style="dashed" style="margin: 10px 0" />
+						</div>
+					</template>
+					<el-empty description="空" v-else></el-empty>
 				</div>
+				<div class="notice-foot" @click="goToNotice" v-if="noticeList.length > 0">前往通知中心</div>
+			</el-tab-pane>
+			<el-tab-pane label="我的">
+				<template #label>
+					<el-icon><ele-Position /></el-icon>
+					<span style="margin-left: 5px">我的</span>
+				</template>
+				<div style="height: 400px; overflow-y: auto; padding-right: 10px">
+					<el-empty description="空"></el-empty>
+				</div>
+			</el-tab-pane>
+		</el-tabs>
+		<el-dialog v-model="state.dialogVisible" title="消息详情" draggable width="769px">
+			<p v-html="state.content"></p>
+			<template #footer>
+				<span class="dialog-footer">
+					<el-button type="primary" @click="state.dialogVisible = false">确认</el-button>
+				</span>
 			</template>
-			<el-empty :description="$t('message.user.newDesc')" v-else></el-empty>
-		</div>
-		<div class="foot-box" @click="onGoToGiteeClick" v-if="newsList.length > 0">{{ $t('message.user.newGo') }}</div>
+		</el-dialog>
 	</div>
 </template>
 
-<script lang="ts">
-import { reactive, toRefs, defineComponent } from 'vue';
+<script lang="ts" setup>
+import { reactive } from 'vue';
+import { SysNoticeApi } from '/@/api-services/api';
+import router from '/@/router';
+import commonFunction from '/@/utils/commonFunction';
+
+import { getAPI } from '/@/utils/axios-utils';
 
-export default defineComponent({
-	name: 'layoutBreadcrumbUserNews',
-	setup() {
-		const state = reactive({
-			newsList: [
-				{
-					label: '关于版本发布的通知',
-					value: 'vue-next-admin,基于 vue3 + CompositionAPI + typescript + vite + element plus,正式发布时间:2021年02月28日!',
-					time: '2020-12-08',
-				},
-				{
-					label: '关于学习交流的通知',
-					value: 'QQ群号码 665452019,欢迎小伙伴入群学习交流探讨!',
-					time: '2020-12-08',
-				},
-			],
-		});
-		// 全部已读点击
-		const onAllReadClick = () => {
-			state.newsList = [];
-		};
-		// 前往通知中心点击
-		const onGoToGiteeClick = () => {
-			window.open('https://gitee.com/lyt-top/vue-next-admin');
-		};
-		return {
-			onAllReadClick,
-			onGoToGiteeClick,
-			...toRefs(state),
-		};
-	},
+defineProps({
+	noticeList: Array as any,
 });
+const { removeHtmlSub } = commonFunction();
+const state = reactive({
+	dialogVisible: false,
+	content: '',
+});
+// 前往通知中心点击
+const goToNotice = () => {
+	router.push('/dashboard/notice');
+};
+// 查看消息详情
+const viewNoticeDetail = async (notice: any) => {
+	state.content = notice.content;
+	state.dialogVisible = true;
+
+	// 设置已读
+	notice.readStatus = 1;
+	await getAPI(SysNoticeApi).sysNoticeSetReadPost({ id: notice.id });
+};
 </script>
 
 <style scoped lang="scss">
-.layout-navbars-breadcrumb-user-news {
-	.head-box {
-		display: flex;
-		border-bottom: 1px solid var(--el-border-color-lighter);
-		box-sizing: border-box;
-		color: var(--el-text-color-primary);
-		justify-content: space-between;
-		height: 35px;
-		align-items: center;
-		.head-box-btn {
-			color: var(--el-color-primary);
-			font-size: 13px;
-			cursor: pointer;
-			opacity: 0.8;
+.user-news-container {
+	.content-box {
+		font-size: 12px;
+		.notice-box {
+			height: 400px;
+			padding-right: 10px;
+
+			margin-bottom: 35px;
 			&:hover {
-				opacity: 1;
+				overflow-y: scroll;
 			}
 		}
-	}
-	.content-box {
-		font-size: 13px;
-		.content-box-item {
-			padding-top: 12px;
-			&:last-of-type {
-				padding-bottom: 12px;
+		.notice-item {
+			&:hover {
+				background-color: rgba(#b8b8b8, 0.1);
 			}
-			.content-box-msg {
+			// .notice-title {
+			// 	color: var(--el-color-primary);
+			// }
+			.notice-content {
 				color: var(--el-text-color-secondary);
-				margin-top: 5px;
-				margin-bottom: 5px;
+				margin-top: 3px;
+				margin-bottom: 3px;
 			}
-			.content-box-time {
+			.notice-time {
 				color: var(--el-text-color-secondary);
+				text-align: right;
 			}
 		}
 	}
-	.foot-box {
+	.notice-foot {
 		height: 35px;
+		width: 100%;
 		color: var(--el-color-primary);
-		font-size: 13px;
+		font-size: 14px;
 		cursor: pointer;
-		opacity: 0.8;
+		position: absolute;
+		bottom: 0px;
+		background-color: #fff;
 		display: flex;
 		align-items: center;
 		justify-content: center;
-		border-top: 1px solid var(--el-border-color-lighter);
-		&:hover {
-			opacity: 1;
-		}
-	}
-	:deep(.el-empty__description p) {
-		font-size: 13px;
 	}
 }
 </style>

+ 2 - 0
Web/src/main.ts

@@ -5,6 +5,7 @@ import router from './router';
 import { directive } from '/@/utils/directive';
 import { i18n } from '/@/i18n/index';
 import other from '/@/utils/other';
+import { signalR } from '/@/views/system/onlineUser/signalR';
 
 import ElementPlus from 'element-plus';
 import 'element-plus/dist/index.css';
@@ -27,6 +28,7 @@ app.use(pinia).use(router).use(ElementPlus, { i18n: i18n.global.t }).use(VForm3)
 const globalProperties = {
 	mittBus: mitt(),
 	i18n,
+	signalR,
 };
 
 // 必须合并vue默认的变量,否则有问题

+ 1 - 1
Web/src/stores/themeConfig.ts

@@ -19,7 +19,7 @@ export const useThemeConfig = defineStore('themeConfig', {
 			 * 全局主题
 			 */
 			// 默认 primary 主题颜色
-			primary: '#FF5C00',
+			primary: '#0033CC', // '#FF5C00',
 			// 是否开启深色模式
 			isIsDark: false,
 

+ 8 - 6
Web/src/theme/element.scss

@@ -67,7 +67,7 @@
 ------------------------------- */
 // 鼠标 hover 时颜色
 .el-menu-hover-bg-color {
-	background-color: var(--el-color-primary-light-8) !important;
+	background-color: var(--el-color-primary-light-7) !important;
 	// border-right: solid 3px var(--el-color-primary);
 }
 // 默认样式修改
@@ -263,12 +263,14 @@
 	.el-button.is-text {
 		padding: 0;
 	}
-	// 标题背景色
-	--el-table-header-bg-color: #fafafa;
-	// 标题字体颜色
-	thead{
+	// 表头背景色
+	//--el-table-header-bg-color: var(--el-text-color-secondary);// #fafafa;
+	// 表头字体颜色
+	thead {
 		color: var(--el-text-color-regular);	
-		font-weight: normal;
+		th {
+			font-weight: 600;
+		}
 	}
 }
 // 分页组件靠右显示

+ 12 - 0
Web/src/utils/commonFunction.ts

@@ -53,6 +53,16 @@ export default function () {
 			}
 		});
 	};
+	// 去掉Html标签(取前面5个字符)
+	const removeHtmlSub = (value: string) => {
+		var str = value.replace(/<[^>]+>/g, '');
+		if (str.length > 50) return str.substring(0, 50) + '......';
+		else return str;
+	};
+	// 去掉Html标签
+	const removeHtml = (value: string) => {
+		return value.replace(/<[^>]+>/g, '');
+	};
 	return {
 		percentFormat,
 		dateFormatYMD,
@@ -61,5 +71,7 @@ export default function () {
 		scaleFormat,
 		scale2Format,
 		copyText,
+		removeHtmlSub,
+		removeHtml,
 	};
 }

+ 166 - 0
Web/src/views/home/notice/index.vue

@@ -0,0 +1,166 @@
+<template>
+	<div class="notice-container">
+		<el-card shadow="hover" :body-style="{ paddingBottom: '0' }">
+			<el-form :model="queryParams" ref="queryForm" :inline="true">
+				<el-form-item label="标题" prop="title">
+					<el-input placeholder="标题" clearable @keyup.enter="handleQuery" v-model="queryParams.title" />
+				</el-form-item>
+				<el-form-item label="类型" prop="type">
+					<el-select v-model="queryParams.type" placeholder="类型" clearable style="width: 100%">
+						<el-option label="通知" :value="1" />
+						<el-option label="公告" :value="2" />
+					</el-select>
+				</el-form-item>
+				<el-form-item>
+					<el-button icon="ele-Refresh" @click="resetQuery"> 重置 </el-button>
+					<el-button type="primary" icon="ele-Search" @click="handleQuery" v-auth="'sysNotice:page'"> 查询 </el-button>
+				</el-form-item>
+			</el-form>
+		</el-card>
+
+		<el-card shadow="hover" style="margin-top: 8px">
+			<el-table :data="noticeData" style="width: 100%" v-loading="loading" border :row-class-name="tableRowClassName">
+				<el-table-column type="index" label="序号" width="55" align="center" />
+				<el-table-column prop="sysNotice.title" label="标题" show-overflow-tooltip />
+				<el-table-column prop="sysNotice.content" label="内容" show-overflow-tooltip>
+					<template #default="scope"> {{ removeHtml(scope.row.sysNotice.content) }} </template>
+				</el-table-column>
+				<el-table-column prop="sysNotice.type" label="类型" width="100" align="center" show-overflow-tooltip>
+					<template #default="scope">
+						<el-tag v-if="scope.row.sysNotice.type === 1"> 通知 </el-tag>
+						<el-tag type="warning" v-else> 公告 </el-tag>
+					</template>
+				</el-table-column>
+				<el-table-column prop="sysNotice.createTime" label="创建时间" align="center" show-overflow-tooltip />
+				<el-table-column prop="readStatus" label="阅读状态" width="100" align="center" show-overflow-tooltip>
+					<template #default="scope">
+						<el-tag type="info" v-if="scope.row.readStatus === 1"> 已读 </el-tag>
+						<el-tag type="danger" v-else> 未读 </el-tag>
+					</template>
+				</el-table-column>
+				<el-table-column prop="sysNotice.publicUserName" label="发布者" align="center" show-overflow-tooltip />
+				<el-table-column prop="sysNotice.publicTime" label="发布时间" align="center" show-overflow-tooltip />
+				<el-table-column label="操作" width="80" fixed="right" align="center" show-overflow-tooltip>
+					<template #default="scope">
+						<el-button icon="ele-InfoFilled" size="small" text type="primary" @click="viewDetail(scope.row)"> 详情 </el-button>
+					</template>
+				</el-table-column>
+			</el-table>
+			<el-pagination
+				v-model:currentPage="tableParams.page"
+				v-model:page-size="tableParams.pageSize"
+				:total="tableParams.total"
+				:page-sizes="[10, 20, 50, 100]"
+				small
+				background
+				@size-change="handleSizeChange"
+				@current-change="handleCurrentChange"
+				layout="total, sizes, prev, pager, next, jumper"
+			/>
+		</el-card>
+		<el-dialog v-model="dialogVisible" title="消息详情" draggable width="769px">
+			<p v-html="content"></p>
+			<template #footer>
+				<span class="dialog-footer">
+					<el-button type="primary" @click="dialogVisible = false">确认</el-button>
+				</span>
+			</template>
+		</el-dialog>
+	</div>
+</template>
+
+<script lang="ts">
+import { toRefs, reactive, onMounted, defineComponent, onUnmounted, getCurrentInstance } from 'vue';
+import commonFunction from '/@/utils/commonFunction';
+
+import { getAPI } from '/@/utils/axios-utils';
+import { SysNoticeApi } from '/@/api-services/api';
+import { SysNoticeUser } from '/@/api-services/models';
+
+export default defineComponent({
+	name: 'notice',
+	components: {},
+	setup() {
+		const { proxy } = getCurrentInstance() as any;
+		const { removeHtml } = commonFunction();
+		const state = reactive({
+			loading: false,
+			noticeData: [] as Array<SysNoticeUser>,
+			queryParams: {
+				title: undefined,
+				type: undefined,
+			},
+			tableParams: {
+				page: 1,
+				pageSize: 10,
+				total: 0 as any,
+			},
+			editNoticeTitle: '',
+			dialogVisible: false,
+			content: '',
+		});
+		onMounted(async () => {
+			handleQuery();
+
+			proxy.mittBus.on('submitRefresh', () => {
+				handleQuery();
+			});
+		});
+		onUnmounted(() => {
+			proxy.mittBus.off('submitRefresh');
+		});
+		// 查询操作
+		const handleQuery = async () => {
+			state.loading = true;
+			var res = await getAPI(SysNoticeApi).sysNoticePageReceivedGet(state.queryParams.title, state.queryParams.type, state.tableParams.page, state.tableParams.pageSize);
+			state.noticeData = res.data.result?.items ?? [];
+			state.tableParams.total = res.data.result?.total;
+			state.loading = false;
+		};
+		// 重置操作
+		const resetQuery = () => {
+			state.queryParams.title = undefined;
+			state.queryParams.type = undefined;
+			handleQuery();
+		};
+		// 改变页面容量
+		const handleSizeChange = (val: number) => {
+			state.tableParams.pageSize = val;
+			handleQuery();
+		};
+		// 改变页码序号
+		const handleCurrentChange = (val: number) => {
+			state.tableParams.page = val;
+			handleQuery();
+		};
+		// 查看详情
+		const viewDetail = async (row: any) => {
+			state.content = row.sysNotice.content;
+			state.dialogVisible = true;
+
+			row.readStatus = 1;
+			await getAPI(SysNoticeApi).sysNoticeSetReadPost({ id: row.sysNotice.id });
+		};
+		// eslint-disable-next-line no-unused-vars
+		const tableRowClassName = ({ row, rowIndex }: { row: SysNoticeUser; rowIndex: number }) => {
+			return row.readStatus === 1 ? 'info-row' : '';
+		};
+		return {
+			handleQuery,
+			resetQuery,
+			viewDetail,
+			handleSizeChange,
+			handleCurrentChange,
+			tableRowClassName,
+			removeHtml,
+			...toRefs(state),
+		};
+	},
+});
+</script>
+
+<style lang="scss">
+// .el-table .info-row {
+// 	--el-table-tr-bg-color: var(--el-color-info-light-9);
+// }
+</style>

+ 40 - 13
Web/src/views/login/component/account.vue

@@ -1,9 +1,19 @@
 <template>
 	<el-form ref="ruleFormRef" :model="ruleForm" size="large" :rules="rules" class="login-content-form">
+		<el-form-item class="login-animation0" v-show="tenantList.length > 0">
+			<el-select v-model="ruleForm.tenantId" value-key="id" placeholder="租户名称" class="w100">
+				<template #prefix>
+					<el-icon>
+						<ele-OfficeBuilding />
+					</el-icon>
+				</template>
+				<el-option v-for="item in tenantList" :key="item.id" :label="item.name" :value="item.id" />
+			</el-select>
+		</el-form-item>
 		<el-form-item class="login-animation1" prop="account">
 			<el-input type="text" placeholder="请输入账号" v-model="ruleForm.account" clearable autocomplete="off">
 				<template #prefix>
-					<el-icon class="el-input__icon">
+					<el-icon>
 						<ele-User />
 					</el-icon>
 				</template>
@@ -12,7 +22,7 @@
 		<el-form-item class="login-animation2" prop="password">
 			<el-input :type="isShowPassword ? 'text' : 'password'" placeholder="请输入密码" v-model="ruleForm.password" autocomplete="off">
 				<template #prefix>
-					<el-icon class="el-input__icon">
+					<el-icon>
 						<ele-Unlock />
 					</el-icon>
 				</template>
@@ -21,11 +31,11 @@
 				</template>
 			</el-input>
 		</el-form-item>
-		<el-form-item class="login-animation3" prop="captcha">
+		<el-form-item class="login-animation3" prop="captcha" v-show="captchaEnabled">
 			<el-col :span="15">
-				<el-input type="text" maxlength="4" :placeholder="$t('message.account.accountPlaceholder3')" v-model="ruleForm.code" clearable autocomplete="off">
+				<el-input type="text" maxlength="4" :placeholder="$t('message.account.accountPlaceholder3')" v-model="ruleForm.code" clearable autocomplete="off" @keyup.enter="openVerify">
 					<template #prefix>
-						<el-icon class="el-input__icon">
+						<el-icon>
 							<ele-Position />
 						</el-icon>
 					</template>
@@ -75,7 +85,8 @@ import { formatAxis } from '/@/utils/formatTime';
 import { NextLoading } from '/@/utils/loading';
 
 import { getAPI } from '/@/utils/axios-utils';
-import { SysAuthApi } from '/@/api-services/apis/sys-auth-api';
+import { SysAuthApi } from '/@/api-services/api';
+import { SysTenant } from '/@/api-services/models';
 
 // 旋转图片滑块组件
 import DragVerifyImgRotate from '/@/components/dragVerify/dragVerifyImgRotate.vue';
@@ -98,8 +109,9 @@ export default defineComponent({
 			ruleForm: {
 				account: 'superadmin',
 				password: '123456',
-				code: '1234',
+				code: '',
 				codeId: 0,
+				tenantId: 0,
 			},
 			rules: {
 				account: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
@@ -113,8 +125,19 @@ export default defineComponent({
 			isPass: false,
 			verifyImg: verifyImg,
 			captchaImage: '',
+			captchaEnabled: true,
+			tenantList: [] as Array<SysTenant>,
 		});
-		onMounted(() => {
+		onMounted(async () => {
+			// 是否开启多库租户
+			var res = await getAPI(SysAuthApi).tenantDbListGet();
+			state.tenantList = res.data.result ?? [];
+			if (state.tenantList.length > 0) state.ruleForm.tenantId = state.tenantList[0].id ?? 0;
+
+			// 是否开启验证码验证
+			var res1 = await getAPI(SysAuthApi).captchaFlagGet();
+			state.captchaEnabled = res1.data.result ?? true;
+			if (!state.captchaEnabled) return;
 			getCaptcha();
 		});
 		// 获取验证码
@@ -184,15 +207,19 @@ export default defineComponent({
 			ruleFormRef.value.validate((valid: boolean) => {
 				if (!valid) return false;
 
-				state.verifyVisible = true;
-				state.isPass = false;
-				dragRef.value.reset();
+				if (!state.captchaEnabled) {
+					passVerify();
+				} else {
+					state.verifyVisible = true;
+					state.isPass = false;
+					dragRef.value.reset();
+				}
 			});
 		};
 		// 通过旋转验证
 		const passVerify = () => {
 			state.verifyVisible = false;
-			state.isPass = false;
+			state.isPass = true;
 			onSignIn();
 		};
 		return {
@@ -211,7 +238,7 @@ export default defineComponent({
 .login-content-form {
 	margin-top: 20px;
 
-	@for $i from 1 through 4 {
+	@for $i from 0 through 4 {
 		.login-animation#{$i} {
 			opacity: 0;
 			animation-name: error-num;

+ 6 - 7
Web/src/views/login/index.vue

@@ -1,12 +1,11 @@
 <template>
 	<div class="login-container">
 		<div class="login-icon-group">
-			<div class="login-icon-group-title">
+			<!-- <div class="login-icon-group-title">
 				<img :src="logoMini" />
-				<!-- <div class="login-icon-group-title-text font25">{{ getThemeConfig.globalViceTitle }}</div> -->
-			</div>
-			<el-carousel height="550px"
-				style="width: 100%; padding-right: 38%; top:50%; transform: translateY(-50%) translate3d(0, 0, 0);">
+				<div class="login-icon-group-title-text font25">{{ getThemeConfig.globalViceTitle }}</div>
+			</div> -->
+			<el-carousel height="550px" style="width: 100%; padding-right: 38%; top: 50%; transform: translateY(-50%) translate3d(0, 0, 0)">
 				<el-carousel-item>
 					<img :src="loginIconTwo" class="login-icon-group-icon" />
 				</el-carousel-item>
@@ -132,7 +131,7 @@ export default defineComponent({
 
 	.login-content {
 		width: 500px;
-		height: 500px;
+		height: 550px;
 		padding: 20px;
 		position: absolute;
 		right: 10%;
@@ -154,7 +153,7 @@ export default defineComponent({
 				font-size: 32px;
 				text-align: center;
 				//letter-spacing: 4px;
-				margin: 5px 0 30px;
+				margin: 5px 0 20px;
 				white-space: nowrap;
 				z-index: 5;
 				position: relative;

+ 2 - 2
Web/src/views/system/cache/index.vue

@@ -33,7 +33,7 @@
 							<el-button icon="ele-Delete" size="small" type="danger" @click="delCache" v-auth="'sysCache:delete'"> 删除缓存 </el-button>
 						</div>
 					</template>
-					<vue-json-pretty :data="cacheValue" showLength showIcon showLineNumber showSelectController style="background-color: #ffffff" />
+					<vue-json-pretty :data="cacheValue" showLength showIcon showLineNumber showSelectController />
 				</el-card>
 			</el-col>
 		</el-row>
@@ -119,7 +119,7 @@ export default defineComponent({
 
 			currentNode.value = node;
 			state.loading1 = true;
-			var res = await getAPI(SysCacheApi).sysCacheDetailGet(node.id);
+			var res = await getAPI(SysCacheApi).sysCacheValueGet(node.id);
 			state.cacheValue = res.data.result;
 			state.loading1 = false;
 		};

+ 1 - 1
Web/src/views/system/config/component/editConfig.vue

@@ -22,7 +22,7 @@
 						</el-form-item>
 					</el-col>
 					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
-						<el-form-item label="系统参数" prop="sysFlag" :rules="[{ required: true, message: '系统参数不能为空', trigger: 'blur' }]">
+						<el-form-item label="内置参数" prop="sysFlag" :rules="[{ required: true, message: '内置参数不能为空', trigger: 'blur' }]">
 							<el-radio-group v-model="ruleForm.sysFlag" :disabled="ruleForm.sysFlag == 1 && ruleForm.id != undefined">
 								<el-radio :label="1">是</el-radio>
 								<el-radio :label="2">否</el-radio>

+ 1 - 1
Web/src/views/system/config/index.vue

@@ -22,7 +22,7 @@
 				<el-table-column prop="name" label="配置名称" show-overflow-tooltip />
 				<el-table-column prop="code" label="配置编码" show-overflow-tooltip />
 				<el-table-column prop="value" label="属性值" show-overflow-tooltip />
-				<el-table-column prop="sysFlag" label="平台参数" width="100" align="center" show-overflow-tooltip>
+				<el-table-column prop="sysFlag" label="内置参数" width="100" align="center" show-overflow-tooltip>
 					<template #default="scope">
 						<el-tag v-if="scope.row.sysFlag === 1"> 是 </el-tag>
 						<el-tag type="danger" v-else> 否 </el-tag>

+ 2 - 2
Web/src/views/system/file/index.vue

@@ -37,7 +37,7 @@
 					</template>
 				</el-table-column>
 				<el-table-column prop="sizeKb" label="大小kb" align="center" show-overflow-tooltip />
-				<el-table-column prop="url" label="预览" align="center" show-overflow-tooltip>
+				<el-table-column prop="url" label="预览" align="center">
 					<template #default="scope">
 						<el-image
 							style="width: 60px; height: 60px"
@@ -46,8 +46,8 @@
 							:hide-on-click-modal="true"
 							:preview-src-list="[scope.row.url]"
 							:initial-index="0"
-							:z-index="10000"
 							fit="scale-down"
+							preview-teleported
 						/>
 					</template>
 				</el-table-column>

+ 2 - 2
Web/src/views/system/log/oplog/index.vue

@@ -28,9 +28,9 @@
 				<el-table-column prop="threadId" label="线程Id" show-overflow-tooltip />
 				<el-table-column prop="logDateTime" label="日志记录时间" align="center" show-overflow-tooltip />
 				<el-table-column prop="createTime" label="操作时间" align="center" show-overflow-tooltip />
-				<el-table-column label="操作" width="110" align="center" fixed="right" show-overflow-tooltip>
+				<el-table-column label="操作" width="80" align="center" fixed="right" show-overflow-tooltip>
 					<template #default="scope">
-						<el-button icon="ele-Edit" size="small" text type="primary" @click="viewDetail(scope.row)" v-auth="'sysOplog:page'">详情 </el-button>
+						<el-button icon="ele-InfoFilled" size="small" text type="primary" @click="viewDetail(scope.row)" v-auth="'sysOplog:page'">详情 </el-button>
 					</template>
 				</el-table-column>
 			</el-table>

+ 1 - 1
Web/src/views/system/menu/component/editMenu.vue

@@ -1,6 +1,6 @@
 <template>
 	<div class="sys-menu-container">
-		<el-dialog v-model="isShowDialog" :title="title" draggable width="769px">
+		<el-dialog v-model="isShowDialog" :title="title" draggable :close-on-click-modal="false" width="769px">
 			<el-form :model="ruleForm" ref="ruleFormRef" size="default" label-width="80px">
 				<el-row :gutter="35">
 					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">

+ 1 - 1
Web/src/views/system/menu/index.vue

@@ -109,7 +109,7 @@ export default defineComponent({
 		// 打开新增页面
 		const openAddMenu = () => {
 			state.editMenuTitle = '添加菜单';
-			editMenuRef.value.openDialog({});
+			editMenuRef.value.openDialog({ type: 2 });
 		};
 		// 打开编辑页面
 		const openEditMenu = (row: any) => {

+ 96 - 0
Web/src/views/system/notice/component/editNotice.vue

@@ -0,0 +1,96 @@
+<template>
+	<div class="sys-notice-container">
+		<el-dialog v-model="isShowDialog" :title="title" draggable :close-on-click-modal="false" width="800px">
+			<el-form :model="ruleForm" ref="ruleFormRef" size="default" label-width="80px">
+				<el-row :gutter="35">
+					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
+						<el-form-item label="标题" prop="title" :rules="[{ required: true, message: '标题不能为空', trigger: 'blur' }]">
+							<el-input v-model="ruleForm.title" placeholder="标题" clearable />
+						</el-form-item>
+					</el-col>
+					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
+						<el-form-item label="类型" prop="type" :rules="[{ required: true, message: '类型不能为空', trigger: 'blur' }]">
+							<el-select v-model="ruleForm.type" placeholder="类型" filterable allow-create default-first-option style="width: 100%">
+								<el-option label="通知" :value="1" />
+								<el-option label="公告" :value="2" />
+							</el-select>
+						</el-form-item>
+					</el-col>
+					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
+						<el-form-item label="内容" prop="content" :rules="[{ required: true, message: '内容不能为空', trigger: 'blur' }]">
+							<Editor v-model="ruleForm.content" />
+						</el-form-item>
+					</el-col>
+				</el-row>
+			</el-form>
+			<template #footer>
+				<span class="dialog-footer">
+					<el-button @click="cancel" size="default">取 消</el-button>
+					<el-button type="primary" @click="submit" size="default">确 定</el-button>
+				</span>
+			</template>
+		</el-dialog>
+	</div>
+</template>
+
+<script lang="ts">
+import { reactive, toRefs, defineComponent, getCurrentInstance, ref } from 'vue';
+import Editor from '/@/components/editor/index.vue';
+
+import { getAPI } from '/@/utils/axios-utils';
+import { SysNoticeApi } from '/@/api-services/api';
+import { UpdateNoticeInput } from '/@/api-services/models';
+
+export default defineComponent({
+	name: 'sysNoticeEdit',
+	components: { Editor },
+	props: {
+		title: {
+			type: String,
+			default: '',
+		},
+	},
+	setup() {
+		const { proxy } = getCurrentInstance() as any;
+		const ruleFormRef = ref();
+		const state = reactive({
+			isShowDialog: false,
+			ruleForm: {} as UpdateNoticeInput,
+		});
+		// 打开弹窗
+		const openDialog = (row: any) => {
+			state.ruleForm = row;
+			state.isShowDialog = true;
+		};
+		// 关闭弹窗
+		const closeDialog = () => {
+			proxy.mittBus.emit('submitRefresh');
+			state.isShowDialog = false;
+		};
+		// 取消
+		const cancel = () => {
+			state.isShowDialog = false;
+		};
+		// 提交
+		const submit = () => {
+			ruleFormRef.value.validate(async (valid: boolean) => {
+				if (!valid) return;
+				if (state.ruleForm.id != undefined && state.ruleForm.id > 0) {
+					await getAPI(SysNoticeApi).sysNoticeUpdatePost(state.ruleForm);
+				} else {
+					await getAPI(SysNoticeApi).sysNoticeAddPost(state.ruleForm);
+				}
+				closeDialog();
+			});
+		};
+		return {
+			ruleFormRef,
+			openDialog,
+			closeDialog,
+			cancel,
+			submit,
+			...toRefs(state),
+		};
+	},
+});
+</script>

+ 186 - 0
Web/src/views/system/notice/index.vue

@@ -0,0 +1,186 @@
+<template>
+	<div class="sys-notice-container">
+		<el-card shadow="hover" :body-style="{ paddingBottom: '0' }">
+			<el-form :model="queryParams" ref="queryForm" :inline="true">
+				<el-form-item label="标题" prop="title">
+					<el-input placeholder="标题" clearable @keyup.enter="handleQuery" v-model="queryParams.title" />
+				</el-form-item>
+				<el-form-item label="类型" prop="type">
+					<el-select v-model="queryParams.type" placeholder="类型" clearable style="width: 100%">
+						<el-option label="通知" :value="1" />
+						<el-option label="公告" :value="2" />
+					</el-select>
+				</el-form-item>
+				<el-form-item>
+					<el-button icon="ele-Refresh" @click="resetQuery"> 重置 </el-button>
+					<el-button type="primary" icon="ele-Search" @click="handleQuery" v-auth="'sysNotice:page'"> 查询 </el-button>
+					<el-button icon="ele-Plus" @click="openAddNotice" v-auth="'sysNotice:add'"> 新增 </el-button>
+				</el-form-item>
+			</el-form>
+		</el-card>
+
+		<el-card shadow="hover" style="margin-top: 8px">
+			<el-table :data="noticeData" style="width: 100%" v-loading="loading" border>
+				<el-table-column type="index" label="序号" width="55" align="center" />
+				<el-table-column prop="title" label="标题" show-overflow-tooltip />
+				<el-table-column prop="content" label="内容" show-overflow-tooltip>
+					<template #default="scope"> {{ removeHtml(scope.row.content) }} </template>
+				</el-table-column>
+				<el-table-column prop="type" label="类型" width="100" align="center" show-overflow-tooltip>
+					<template #default="scope">
+						<el-tag v-if="scope.row.type === 1"> 通知 </el-tag>
+						<el-tag type="warning" v-else> 公告 </el-tag>
+					</template>
+				</el-table-column>
+				<el-table-column prop="createTime" label="创建时间" align="center" show-overflow-tooltip />
+				<el-table-column prop="status" label="状态" width="100" align="center" show-overflow-tooltip>
+					<template #default="scope">
+						<el-tag type="info" v-if="scope.row.status === 1"> 已发布 </el-tag>
+						<el-tag type="warning" v-else> 未发布 </el-tag>
+					</template>
+				</el-table-column>
+				<el-table-column prop="publicUserName" label="发布者" align="center" show-overflow-tooltip />
+				<el-table-column prop="publicTime" label="发布时间" align="center" show-overflow-tooltip />
+				<el-table-column label="操作" width="200" fixed="right" align="center" show-overflow-tooltip>
+					<template #default="scope">
+						<el-button icon="ele-Position" size="small" text type="primary" @click="publicNotice(scope.row)" v-auth="'sysNotice:public'" :disabled="scope.row.status === 1"> 发布 </el-button>
+						<el-button icon="ele-Edit" size="small" text type="primary" @click="openEditNotice(scope.row)" v-auth="'sysNotice:update'" :disabled="scope.row.status === 1"> 编辑 </el-button>
+						<el-button icon="ele-Delete" size="small" text type="danger" @click="delNotice(scope.row)" v-auth="'sysNotice:delete'" :disabled="scope.row.status === 1"> 删除 </el-button>
+					</template>
+				</el-table-column>
+			</el-table>
+			<el-pagination
+				v-model:currentPage="tableParams.page"
+				v-model:page-size="tableParams.pageSize"
+				:total="tableParams.total"
+				:page-sizes="[10, 20, 50, 100]"
+				small
+				background
+				@size-change="handleSizeChange"
+				@current-change="handleCurrentChange"
+				layout="total, sizes, prev, pager, next, jumper"
+			/>
+		</el-card>
+		<EditNotice ref="editNoticeRef" :title="editNoticeTitle" />
+	</div>
+</template>
+
+<script lang="ts">
+import { toRefs, reactive, onMounted, ref, defineComponent, onUnmounted, getCurrentInstance } from 'vue';
+import { ElMessageBox, ElMessage } from 'element-plus';
+import commonFunction from '/@/utils/commonFunction';
+import EditNotice from '/@/views/system/notice/component/editNotice.vue';
+
+import { getAPI } from '/@/utils/axios-utils';
+import { SysNoticeApi } from '/@/api-services/api';
+import { SysNotice } from '/@/api-services/models';
+
+export default defineComponent({
+	name: 'sysNotice',
+	components: { EditNotice },
+	setup() {
+		const { proxy } = getCurrentInstance() as any;
+		const editNoticeRef = ref();
+		const { removeHtml } = commonFunction();
+		const state = reactive({
+			loading: false,
+			noticeData: [] as Array<SysNotice>,
+			queryParams: {
+				title: undefined,
+				type: undefined,
+			},
+			tableParams: {
+				page: 1,
+				pageSize: 10,
+				total: 0 as any,
+			},
+			editNoticeTitle: '',
+		});
+		onMounted(async () => {
+			handleQuery();
+
+			proxy.mittBus.on('submitRefresh', () => {
+				handleQuery();
+			});
+		});
+		onUnmounted(() => {
+			proxy.mittBus.off('submitRefresh');
+		});
+		// 查询操作
+		const handleQuery = async () => {
+			state.loading = true;
+			var res = await getAPI(SysNoticeApi).sysNoticePageGet(state.queryParams.title, state.queryParams.type, state.tableParams.page, state.tableParams.pageSize);
+			state.noticeData = res.data.result?.items ?? [];
+			state.tableParams.total = res.data.result?.total;
+			state.loading = false;
+		};
+		// 重置操作
+		const resetQuery = () => {
+			state.queryParams.title = undefined;
+			state.queryParams.type = undefined;
+			handleQuery();
+		};
+		// 打开新增页面
+		const openAddNotice = () => {
+			state.editNoticeTitle = '添加通知公告';
+			editNoticeRef.value.openDialog({});
+		};
+		// 打开编辑页面
+		const openEditNotice = (row: any) => {
+			state.editNoticeTitle = '编辑通知公告';
+			editNoticeRef.value.openDialog(row);
+		};
+		// 删除
+		const delNotice = (row: any) => {
+			ElMessageBox.confirm(`确定删除通知公告:【${row.title}】?`, '提示', {
+				confirmButtonText: '确定',
+				cancelButtonText: '取消',
+				type: 'warning',
+			})
+				.then(async () => {
+					await getAPI(SysNoticeApi).sysNoticeDeletePost({ id: row.id });
+					handleQuery();
+					ElMessage.success('删除成功');
+				})
+				.catch(() => {});
+		};
+		// 发布
+		const publicNotice = (row: any) => {
+			ElMessageBox.confirm(`确定发布通知公告:【${row.title}】,不可撤销?`, '提示', {
+				confirmButtonText: '确定',
+				cancelButtonText: '取消',
+				type: 'warning',
+			})
+				.then(async () => {
+					await getAPI(SysNoticeApi).sysNoticePublicPost({ id: row.id });
+					handleQuery();
+					ElMessage.success('发布成功');
+				})
+				.catch(() => {});
+		};
+		// 改变页面容量
+		const handleSizeChange = (val: number) => {
+			state.tableParams.pageSize = val;
+			handleQuery();
+		};
+		// 改变页码序号
+		const handleCurrentChange = (val: number) => {
+			state.tableParams.page = val;
+			handleQuery();
+		};
+		return {
+			handleQuery,
+			resetQuery,
+			editNoticeRef,
+			openAddNotice,
+			openEditNotice,
+			delNotice,
+			publicNotice,
+			handleSizeChange,
+			handleCurrentChange,
+			removeHtml,
+			...toRefs(state),
+		};
+	},
+});
+</script>

+ 23 - 61
Web/src/views/system/onlineUser/index.vue

@@ -48,14 +48,14 @@
 </template>
 
 <script setup lang="ts">
-import { reactive } from 'vue';
+import { getCurrentInstance, onMounted, reactive } from 'vue';
 import { ElMessageBox, ElNotification } from 'element-plus';
-import * as SignalR from '@microsoft/signalr';
 
-import { getAPI, getToken, clearAccessTokens } from '/@/utils/axios-utils';
+import { getAPI, clearAccessTokens } from '/@/utils/axios-utils';
 import { SysOnlineUserApi, SysAuthApi } from '/@/api-services/api';
 import { SysOnlineUser } from '/@/api-services/models';
 
+const { proxy } = getCurrentInstance() as any;
 const state = reactive({
 	loading: false,
 	isVisible: false,
@@ -71,68 +71,30 @@ const state = reactive({
 	onlineUserList: [] as Array<SysOnlineUser>, // 在线用户列表
 });
 
-// 初始化SignalR对象
-const connection = new SignalR.HubConnectionBuilder()
-	//.configureLogging(SignalR.LogLevel.Information)
-	.withUrl(`${import.meta.env.VITE_API_URL}/hubs/onlineUser?access_token=${getToken()}`)
-	.withAutomaticReconnect({
-		nextRetryDelayInMilliseconds: (a) => {
-			console.log(a);
-			return 5000; // 每5秒重连一次
-		},
-	})
-	.build();
-
-connection.keepAliveIntervalInMilliseconds = 15 * 1000; // 心跳检测15s
-connection.serverTimeoutInMilliseconds = 30 * 60 * 1000; // 超时时间30m
+onMounted(async () => {
+	handleQuery();
 
-// 启动连接
-connection.start().then(() => {
-	console.log('启动连接');
-});
-// 断开连接
-connection.onclose(async () => {
-	console.log('断开连接');
-});
-// 重连中
-connection.onreconnecting(() => {
-	ElNotification({
-		title: '提示',
-		message: '服务器已断线...',
-		type: 'error',
-		position: 'bottom-right',
+	// 在线用户列表
+	proxy.signalR.off('OnlineUserList');
+	proxy.signalR.on('OnlineUserList', (data: any) => {
+		state.onlineUserList = data.userList;
+		ElNotification({
+			title: '提示',
+			message: `${data.online ? `【${data.realName}】上线了` : `【${data.realName}】离开了`}`,
+			type: `${data.online ? 'info' : 'error'}`,
+			position: 'bottom-right',
+		});
 	});
-});
-// 重连成功
-connection.onreconnected(() => {
-	console.log('重连成功');
-});
+	// 强制下线
+	proxy.signalR.off('ForceOffline');
+	proxy.signalR.on('ForceOffline', async (data: any) => {
+		console.log('强制下线', data);
+		await proxy.signalR.stop();
 
-const reciveMessage = (msg: any) => {
-	console.log('接收消息:', msg);
-};
-
-// 接收消息
-connection.on('ReceiveMessage', reciveMessage);
-// 强制下线
-connection.on('ForceOffline', async (data: any) => {
-	console.log('强制下线', data);
-	await connection.stop();
-
-	await getAPI(SysAuthApi).logoutPost();
-	clearAccessTokens();
-});
-// 在线用户改变
-connection.on('OnlineUserChange', (data: any) => {
-	state.onlineUserList = data.userList;
-	ElNotification({
-		title: '提示',
-		message: `${data.online ? `【${data.realName}】上线了` : `【${data.realName}】离开了`}`,
-		type: `${data.online ? 'info' : 'error'}`,
-		position: 'bottom-right',
+		await getAPI(SysAuthApi).logoutPost();
+		clearAccessTokens();
 	});
 });
-
 // 打开页面
 const openDrawer = () => {
 	state.isVisible = true;
@@ -159,7 +121,7 @@ const forceOffline = async (row: any) => {
 		type: 'warning',
 	})
 		.then(async () => {
-			await connection.send('ForceOffline', { connectionId: row.connectionId }).catch(function (err) {
+			await proxy.signalR.send('ForceOffline', { connectionId: row.connectionId }).catch(function (err: any) {
 				console.log(err);
 			});
 		})

+ 44 - 0
Web/src/views/system/onlineUser/signalR.ts

@@ -0,0 +1,44 @@
+import * as SignalR from '@microsoft/signalr';
+import { ElNotification } from 'element-plus';
+import { getToken } from '/@/utils/axios-utils';
+
+// 初始化SignalR对象
+const connection = new SignalR.HubConnectionBuilder()
+	.configureLogging(SignalR.LogLevel.Information)
+	.withUrl(`${import.meta.env.VITE_API_URL}/hubs/onlineUser?access_token=${getToken()}`)
+	.withAutomaticReconnect({
+		nextRetryDelayInMilliseconds: (a) => {
+			console.log(a);
+			return 5000; // 每5秒重连一次
+		},
+	})
+	.build();
+
+connection.keepAliveIntervalInMilliseconds = 15 * 1000; // 心跳检测15s
+connection.serverTimeoutInMilliseconds = 30 * 60 * 1000; // 超时时间30m
+
+// 启动连接
+connection.start().then(() => {
+	console.log('启动连接');
+});
+// 断开连接
+connection.onclose(async () => {
+	console.log('断开连接');
+});
+// 重连中
+connection.onreconnecting(() => {
+	ElNotification({
+		title: '提示',
+		message: '服务器已断线...',
+		type: 'error',
+		position: 'bottom-right',
+	});
+});
+// 重连成功
+connection.onreconnected(() => {
+	console.log('重连成功');
+});
+
+connection.on('OnlineUserList', () => {});
+
+export { connection as signalR };

+ 1 - 1
Web/src/views/system/org/index.vue

@@ -110,7 +110,7 @@ export default defineComponent({
 		// 打开新增页面
 		const openAddOrg = () => {
 			state.editOrgTitle = '添加机构';
-			editOrgRef.value.openDialog({});
+			editOrgRef.value.openDialog({ status: 1 });
 		};
 		// 打开编辑页面
 		const openEditOrg = (row: any) => {

+ 1 - 1
Web/src/views/system/pos/index.vue

@@ -93,7 +93,7 @@ export default defineComponent({
 		// 打开新增页面
 		const openAddPos = () => {
 			state.editPosTitle = '添加职位';
-			editPosRef.value.openDialog({});
+			editPosRef.value.openDialog({ status: 1 });
 		};
 		// 打开编辑页面
 		const openEditPos = (row: any) => {

+ 1 - 1
Web/src/views/system/role/component/editRole.vue

@@ -1,6 +1,6 @@
 <template>
 	<div class="sys-role-container">
-		<el-dialog v-model="isShowDialog" :title="title" draggable width="769px">
+		<el-dialog v-model="isShowDialog" :title="title" draggable :close-on-click-modal="false" width="769px">
 			<el-form :model="ruleForm" ref="ruleFormRef" size="default" label-width="80px">
 				<el-row :gutter="35">
 					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">

+ 1 - 1
Web/src/views/system/server/index.vue

@@ -87,7 +87,7 @@
 				<el-tag round>
 					<div style="display: inline-flex">
 						<div style="">{{ d.name }}</div>
-						<div style="font-size: 9px; color: black; margin-left: 3px">{{ d.version }}</div>
+						<div style="font-size: 9px; margin-left: 3px">{{ d.version }}</div>
 					</div>
 				</el-tag>
 			</div>

+ 24 - 16
Web/src/views/system/tenant/component/editTenant.vue

@@ -3,6 +3,14 @@
 		<el-dialog v-model="isShowDialog" :title="title" draggable width="769px">
 			<el-form :model="ruleForm" ref="ruleFormRef" size="default" label-width="100px">
 				<el-row :gutter="35">
+					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
+						<el-form-item label="租户类型" :rules="[{ required: true, message: '租户类型不能为空', trigger: 'blur' }]">
+							<el-radio-group v-model="ruleForm.tenantType">
+								<el-radio :label="0">ID隔离</el-radio>
+								<el-radio :label="1">库隔离</el-radio>
+							</el-radio-group>
+						</el-form-item>
+					</el-col>
 					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
 						<el-form-item label="租户名称" prop="name" :rules="[{ required: true, message: '租户名称不能为空', trigger: 'blur' }]">
 							<el-input v-model="ruleForm.name" placeholder="租户名称" clearable />
@@ -10,7 +18,7 @@
 					</el-col>
 					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
 						<el-form-item label="管理员" prop="adminName" :rules="[{ required: true, message: '管理员不能为空', trigger: 'blur' }]">
-							<el-input v-model="ruleForm.adminName" placeholder="管理员" clearable />
+							<el-input v-model="ruleForm.adminName" placeholder="管理员" clearable :disabled="ruleForm.tenantType == 1" />
 						</el-form-item>
 					</el-col>
 					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
@@ -18,11 +26,6 @@
 							<el-input v-model="ruleForm.phone" placeholder="电话" clearable />
 						</el-form-item>
 					</el-col>
-					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
-						<el-form-item label="主机">
-							<el-input v-model="ruleForm.host" placeholder="主机" clearable />
-						</el-form-item>
-					</el-col>
 					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
 						<el-form-item label="邮箱">
 							<el-input v-model="ruleForm.email" placeholder="邮箱" clearable />
@@ -33,17 +36,14 @@
 							<el-input-number v-model="ruleForm.order" placeholder="排序" class="w100" />
 						</el-form-item>
 					</el-col>
-					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
-						<el-form-item label="租户类型" :rules="[{ required: true, message: '租户类型不能为空', trigger: 'blur' }]">
-							<el-radio-group v-model="ruleForm.tenantType">
-								<el-radio :label="0">ID隔离</el-radio>
-								<el-radio :label="1">库隔离</el-radio>
-							</el-radio-group>
+					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
+						<el-form-item label="主机">
+							<el-input v-model="ruleForm.host" placeholder="主机" clearable />
 						</el-form-item>
 					</el-col>
 					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
 						<el-form-item label="数据库类型">
-							<el-select v-model="ruleForm.dbType" placeholder="数据库类型" clearable style="width: 100%">
+							<el-select v-model="ruleForm.dbType" placeholder="数据库类型" clearable style="width: 100%" :disabled="ruleForm.tenantType == 0 && ruleForm.tenantType != undefined">
 								<el-option label="MySql" :value="0" />
 								<el-option label="SqlServer" :value="1" />
 								<el-option label="Sqlite" :value="2" />
@@ -63,9 +63,14 @@
 							</el-select>
 						</el-form-item>
 					</el-col>
-					<el-col :xs="24" :sm="4" :md="24" :lg="24" :xl="24" class="mb20">
+					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
+						<el-form-item label="数据库标识">
+							<el-input v-model="ruleForm.configId" placeholder="数据库标识" clearable :disabled="ruleForm.tenantType == 0 && ruleForm.tenantType != undefined" />
+						</el-form-item>
+					</el-col>
+					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
 						<el-form-item label="连接字符串">
-							<el-input v-model="ruleForm.connection" placeholder="连接字符串" clearable type="textarea" />
+							<el-input v-model="ruleForm.connection" placeholder="连接字符串" clearable type="textarea" :disabled="ruleForm.tenantType == 0 && ruleForm.tenantType != undefined" />
 						</el-form-item>
 					</el-col>
 					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
@@ -86,7 +91,7 @@
 </template>
 
 <script lang="ts">
-import { reactive, toRefs, defineComponent, getCurrentInstance, ref } from 'vue';
+import { reactive, toRefs, defineComponent, getCurrentInstance, ref, watch } from 'vue';
 
 import { getAPI } from '/@/utils/axios-utils';
 import { SysTenantApi } from '/@/api-services/api';
@@ -108,6 +113,9 @@ export default defineComponent({
 			isShowDialog: false,
 			ruleForm: {} as UpdateTenantInput,
 		});
+		watch(state, () => {
+			if (state.ruleForm.tenantType == 1) state.ruleForm.adminName = 'Administrator';
+		});
 		// 打开弹窗
 		const openDialog = (row: any) => {
 			state.ruleForm = row;

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels