Pārlūkot izejas kodu

Merge branches 'v2' and 'v2' of https://gitee.com/zuohuaijun/Admin.NET into v2

# Conflicts:
#	Web/package.json
#	Web/src/main.ts
Cyrus Zhou 8 mēneši atpakaļ
vecāks
revīzija
7024ce9564
39 mainītis faili ar 825 papildinājumiem un 272 dzēšanām
  1. 22 22
      Admin.NET/Admin.NET.Core/Admin.NET.Core.csproj
  2. 2 2
      Admin.NET/Admin.NET.Core/Enum/ErrorCodeEnum.cs
  3. 3 3
      Admin.NET/Admin.NET.Core/Service/Auth/SysAuthService.cs
  4. 4 0
      Admin.NET/Admin.NET.Core/Service/Menu/Dto/MenuInput.cs
  5. 21 2
      Admin.NET/Admin.NET.Core/Service/Menu/SysMenuService.cs
  6. 42 0
      Admin.NET/Admin.NET.Core/Service/Org/Dto/OrgTreeOutput.cs
  7. 48 4
      Admin.NET/Admin.NET.Core/Service/Org/SysOrgService.cs
  8. 2 2
      Admin.NET/Admin.NET.Core/Service/User/SysUserService.cs
  9. 22 22
      Admin.NET/Admin.NET.Test/Admin.NET.Test.csproj
  10. 1 1
      Admin.NET/Admin.NET.Web.Core/Admin.NET.Web.Core.csproj
  11. 1 1
      Admin.NET/Admin.NET.Web.Entry/Admin.NET.Web.Entry.csproj
  12. 1 1
      Admin.NET/Plugins/Admin.NET.Plugin.ApprovalFlow/Admin.NET.Plugin.ApprovalFlow.csproj
  13. 1 1
      Admin.NET/Plugins/Admin.NET.Plugin.ReZero/Admin.NET.Plugin.ReZero.csproj
  14. 2 2
      Web/package.json
  15. 85 0
      Web/src/api-services/apis/sys-menu-api.ts
  16. 120 0
      Web/src/api-services/apis/sys-org-api.ts
  17. 4 4
      Web/src/api-services/apis/sys-user-api.ts
  18. 71 0
      Web/src/api-services/models/admin-result-list-org-tree-output.ts
  19. 3 0
      Web/src/api-services/models/index.ts
  20. 37 0
      Web/src/api-services/models/menu-status-input.ts
  21. 71 0
      Web/src/api-services/models/org-tree-output.ts
  22. 1 1
      Web/src/components/table/modifyRecord.vue
  23. 136 118
      Web/src/components/table/search.vue
  24. 1 1
      Web/src/layout/footer/index.vue
  25. 13 3
      Web/src/layout/navBars/topBar/user.vue
  26. 4 0
      Web/src/main.ts
  27. 13 0
      Web/src/theme/element.scss
  28. 7 7
      Web/src/views/system/cache/index.vue
  29. 36 14
      Web/src/views/system/menu/index.vue
  30. 4 4
      Web/src/views/system/org/component/orgTree.vue
  31. 7 7
      Web/src/views/system/org/index.vue
  32. 1 1
      Web/src/views/system/pos/index.vue
  33. 7 7
      Web/src/views/system/region/index.vue
  34. 6 6
      Web/src/views/system/stressTest/index.vue
  35. 2 2
      Web/src/views/system/template/index.vue
  36. 6 6
      Web/src/views/system/update/index.vue
  37. 11 21
      Web/src/views/system/user/index.vue
  38. 4 4
      Web/src/views/system/userRegWay/component/editRegWay.vue
  39. 3 3
      一键净化项目.bat

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

@@ -14,15 +14,15 @@
 
   <ItemGroup>
     <PackageReference Include="AlibabaCloud.SDK.Dysmsapi20170525" Version="4.0.0" />
-    <PackageReference Include="AlipaySDKNet.Standard" Version="4.9.627" />
+    <PackageReference Include="AlipaySDKNet.Standard" Version="4.9.712" />
     <PackageReference Include="AngleSharp" Version="1.3.0" />
     <PackageReference Include="AspectCore.Extensions.Reflection" Version="2.4.0" />
     <PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
-    <PackageReference Include="Elastic.Clients.Elasticsearch" Version="9.0.7" />
-    <PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.7.105" />
-    <PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.105" />
-    <PackageReference Include="Furion.Pure" Version="4.9.7.105" />
-	<PackageReference Include="Hardware.Info" Version="101.0.1.1" />
+    <PackageReference Include="Elastic.Clients.Elasticsearch" Version="9.1.0" />
+    <PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.7.108" />
+    <PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.108" />
+    <PackageReference Include="Furion.Pure" Version="4.9.7.108" />
+    <PackageReference Include="Hardware.Info" Version="101.0.1.1" />
     <PackageReference Include="Hashids.net" Version="1.7.0" />
     <PackageReference Include="IPTools.China" Version="1.6.0" />
     <PackageReference Include="IPTools.International" Version="1.6.0" />
@@ -33,45 +33,45 @@
     <PackageReference Include="MailKit" Version="4.13.0" />
     <PackageReference Include="MiniExcel" Version="1.41.3" />
     <PackageReference Include="MiniWord" Version="0.9.2" />
-    <PackageReference Include="NewLife.Redis" Version="6.3.2025.701" />
+    <PackageReference Include="NewLife.Redis" Version="6.3.2025.801" />
     <PackageReference Include="Novell.Directory.Ldap.NETStandard" Version="4.0.0" />
-	<PackageReference Include="OnceMi.AspNetCore.OSS" Version="1.2.0" />
+    <PackageReference Include="OnceMi.AspNetCore.OSS" Version="1.2.0" />
     <PackageReference Include="QRCoder" Version="1.6.0" />
     <PackageReference Include="RabbitMQ.Client" Version="7.1.2" />
     <PackageReference Include="SixLabors.ImageSharp.Web" Version="3.1.5" />
     <PackageReference Include="SKIT.FlurlHttpClient.Wechat.Api" Version="3.11.0" />
     <PackageReference Include="SKIT.FlurlHttpClient.Wechat.TenpayV3" Version="3.13.0" />
-    <PackageReference Include="SqlSugar.MongoDbCore" Version="5.1.4.232" />
-    <PackageReference Include="SqlSugarCore" Version="5.1.4.198" />
+    <PackageReference Include="SqlSugar.MongoDbCore" Version="5.1.4.247" />
+    <PackageReference Include="SqlSugarCore" Version="5.1.4.199" />
     <PackageReference Include="SSH.NET" Version="2025.0.0" />
-    <PackageReference Include="System.Linq.Dynamic.Core" Version="1.6.6" />
+    <PackageReference Include="System.Linq.Dynamic.Core" Version="1.6.7" />
     <PackageReference Include="System.Net.Http" Version="4.3.4" />
     <PackageReference Include="System.Private.Uri" Version="4.3.2" />
     <PackageReference Include="TencentCloudSDK.Sms" Version="3.0.1273" />
     <PackageReference Include="UAParser" Version="3.1.47" />
     <PackageReference Include="Yitter.IdGenerator" Version="1.0.14" />
-    <PackageReference Include="BouncyCastle.Cryptography" Version="2.6.1" Aliases="BouncyCastleV2" />
+    <PackageReference Include="BouncyCastle.Cryptography" Version="2.6.2" Aliases="BouncyCastleV2" />
   </ItemGroup>
 
   <ItemGroup Condition=" '$(TargetFramework)' == 'net8.0' ">
     <PackageReference Include="AspNet.Security.OAuth.Gitee" Version="8.3.0" />
     <PackageReference Include="AspNet.Security.OAuth.Weixin" Version="8.3.0" />
-    <PackageReference Include="Lazy.Captcha.Core" Version="2.2.0" />
-    <PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="8.0.11" />
-    <PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" Version="8.0.11" />
-    <PackageReference Include="Microsoft.AspNetCore.SignalR.StackExchangeRedis" Version="8.0.11" />
-	<PackageReference Include="Microsoft.PowerShell.SDK" Version="7.4.11" />  
+    <PackageReference Include="Lazy.Captcha.Core" Version="2.2.2" />
+    <PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="8.0.19" />
+    <PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" Version="8.0.19" />
+    <PackageReference Include="Microsoft.AspNetCore.SignalR.StackExchangeRedis" Version="8.0.19" />
+    <PackageReference Include="Microsoft.PowerShell.SDK" Version="7.4.11" />
   </ItemGroup>
 
   <ItemGroup Condition=" '$(TargetFramework)' == 'net9.0' ">
     <PackageReference Include="AspNet.Security.OAuth.Gitee" Version="9.4.0" />
     <PackageReference Include="AspNet.Security.OAuth.Weixin" Version="9.4.0" />
     <PackageReference Include="Lazy.Captcha.Core" Version="2.1.0" />
-    <PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="9.0.7" />
-    <PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" Version="9.0.7" />
-    <PackageReference Include="Microsoft.AspNetCore.SignalR.StackExchangeRedis" Version="9.0.7" />
-	<PackageReference Include="Microsoft.PowerShell.SDK" Version="7.5.2" />
-	<PackageReference Include="XiHan.Framework.Utils" Version="0.11.6" />
+    <PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="9.0.8" />
+    <PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" Version="9.0.8" />
+    <PackageReference Include="Microsoft.AspNetCore.SignalR.StackExchangeRedis" Version="9.0.8" />
+    <PackageReference Include="Microsoft.PowerShell.SDK" Version="7.5.2" />
+    <PackageReference Include="XiHan.Framework.Utils" Version="0.11.7" />
   </ItemGroup>
 
 </Project>

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

@@ -32,9 +32,9 @@ public enum ErrorCodeEnum
     D0010,
 
     /// <summary>
-    /// 密码不正确
+    /// 账号或密码不正确
     /// </summary>
-    [ErrorCodeItemMetadata("密码不正确")]
+    [ErrorCodeItemMetadata("账号或密码不正确")]
     D1000,
 
     /// <summary>

+ 3 - 3
Admin.NET/Admin.NET.Core/Service/Auth/SysAuthService.cs

@@ -71,8 +71,8 @@ public class SysAuthService : IDynamicApiController, ITransient
         var keyPasswordErrorTimes = $"{CacheConst.KeyPasswordErrorTimes}{input.Account}";
         var passwordErrorTimes = _sysCacheService.Get<int>(keyPasswordErrorTimes);
         var passwordMaxErrorTimes = await _sysConfigService.GetConfigValue<int>(ConfigConst.SysPasswordMaxErrorTimes);
-        // 若未配置或误配置为0、负数, 则默认密码错误次数最大为10
-        if (passwordMaxErrorTimes < 1) passwordMaxErrorTimes = 10;
+        // 若未配置或误配置为0、负数, 则默认密码错误次数最大为5
+        if (passwordMaxErrorTimes < 1) passwordMaxErrorTimes = 5;
         if (passwordErrorTimes > passwordMaxErrorTimes) throw Oops.Oh(ErrorCodeEnum.D1027);
 
         // 判断是否开启验证码,其校验验证码
@@ -122,7 +122,7 @@ public class SysAuthService : IDynamicApiController, ITransient
             .WhereIF(tenantId > 0, u => (u.AccountType == AccountTypeEnum.SuperAdmin || u.TenantId == tenantId))
             .WhereIF(!string.IsNullOrWhiteSpace(account), u => u.Account.Equals(account))
             .WhereIF(!string.IsNullOrWhiteSpace(phone), u => u.Phone.Equals(phone)).FirstAsync();
-        _ = user ?? throw Oops.Oh(ErrorCodeEnum.D0009);
+        _ = user ?? throw Oops.Oh(ErrorCodeEnum.D1000);
 
         // 租户是否存在或已禁用
         var tenant = await _sysUserRep.ChangeRepository<SqlSugarRepository<SysTenant>>().AsQueryable()

+ 4 - 0
Admin.NET/Admin.NET.Core/Service/Menu/Dto/MenuInput.cs

@@ -44,4 +44,8 @@ public class UpdateMenuInput : AddMenuInput
 
 public class DeleteMenuInput : BaseIdInput
 {
+}
+
+public class MenuStatusInput : BaseStatusInput
+{
 }

+ 21 - 2
Admin.NET/Admin.NET.Core/Service/Menu/SysMenuService.cs

@@ -250,6 +250,24 @@ public class SysMenuService : IDynamicApiController, ITransient
     }
 
     /// <summary>
+    /// 设置菜单状态 🔖
+    /// </summary>
+    /// <param name="input"></param>
+    /// <returns></returns>
+    [UnitOfWork]
+    [DisplayName("设置菜单状态")]
+    public virtual async Task<int> SetStatus(MenuStatusInput input)
+    {
+        if (_userManager.UserId == input.Id)
+            throw Oops.Oh(ErrorCodeEnum.D1026);
+
+        var menu = await _sysMenuRep.GetByIdAsync(input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D1002);
+        menu.Status = input.Status;
+        var rows = await _sysMenuRep.AsUpdateable(menu).UpdateColumns(u => new { u.Status }).ExecuteCommandAsync();
+        return rows;
+    }
+
+    /// <summary>
     /// 增加和编辑时检查菜单数据
     /// </summary>
     /// <param name="menu"></param>
@@ -291,9 +309,10 @@ public class SysMenuService : IDynamicApiController, ITransient
 
         var menuIdList = _userManager.SuperAdmin || _userManager.SysAdmin ? new() : await GetMenuIdList();
 
-        permissions = await _sysMenuRep.AsQueryable().Where(u => u.Type == MenuTypeEnum.Btn)
-            .WhereIF(menuIdList.Count > 0, u => menuIdList.Contains(u.Id))
+        permissions = await _sysMenuRep.AsQueryable()
             .InnerJoinIF<SysTenantMenu>(!_userManager.SuperAdmin, (u, t) => t.TenantId == _userManager.TenantId && u.Id == t.MenuId)
+            .Where(u => u.Type == MenuTypeEnum.Btn)
+            .WhereIF(menuIdList.Count > 0, u => menuIdList.Contains(u.Id))
             .Select(u => u.Permission).ToListAsync();
 
         _sysCacheService.Set(CacheConst.KeyUserButton + userId, permissions, TimeSpan.FromDays(7));

+ 42 - 0
Admin.NET/Admin.NET.Core/Service/Org/Dto/OrgTreeOutput.cs

@@ -0,0 +1,42 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core.Service;
+
+/// <summary>
+/// 机构树形输出
+/// </summary>
+public class OrgTreeOutput
+{
+    /// <summary>
+    /// 主键Id
+    /// </summary>
+    [SugarColumn(IsTreeKey = true)]
+    public long Id { get; set; }
+    /// <summary>
+    /// 租户Id
+    /// </summary>
+    public long TenantId { get; set; }
+    /// <summary>
+    /// 父Id
+    /// </summary>
+    public long Pid { get; set; }
+
+    /// <summary>
+    /// 名称
+    /// </summary>
+    public string Name { get; set; }
+
+    /// <summary>
+    /// 机构子项
+    /// </summary>
+    public List<OrgTreeOutput> Children { get; set; }
+
+    /// <summary>
+    /// 是否禁止选中
+    /// </summary>
+    public bool Disabled { get; set; }
+}

+ 48 - 4
Admin.NET/Admin.NET.Core/Service/Org/SysOrgService.cs

@@ -44,10 +44,7 @@ public class SysOrgService : IDynamicApiController, ITransient
         // 获取拥有的机构Id集合
         var userOrgIdList = await GetUserOrgIdList();
 
-        var queryable = _sysOrgRep.AsQueryable()
-            .WhereIF(_userManager.SuperAdmin && input.TenantId > 0, u => u.TenantId == input.TenantId)
-            .OrderBy(u => new { u.OrderNo, u.Id });
-
+        var queryable = _sysOrgRep.AsQueryable().WhereIF(input.TenantId > 0, u => u.TenantId == input.TenantId).OrderBy(u => new { u.OrderNo, u.Id });
         // 带条件筛选时返回列表数据
         if (!string.IsNullOrWhiteSpace(input.Name) || !string.IsNullOrWhiteSpace(input.Code) || !string.IsNullOrWhiteSpace(input.Type))
         {
@@ -94,6 +91,53 @@ public class SysOrgService : IDynamicApiController, ITransient
     }
 
     /// <summary>
+    /// 获取机构树 🔖
+    /// </summary>
+    /// <param name="input"></param>
+    /// <returns></returns>
+    [DisplayName("获取机构树")]
+    public async Task<List<OrgTreeOutput>> GetTree([FromQuery] OrgInput input)
+    {
+        // 获取拥有的机构Id集合
+        var userOrgIdList = await GetUserOrgIdList();
+
+        var queryable = _sysOrgRep.AsQueryable().WhereIF(input.TenantId > 0, u => u.TenantId == input.TenantId).OrderBy(u => new { u.OrderNo, u.Id });
+        List<OrgTreeOutput> orgTree;
+        if (_userManager.SuperAdmin)
+        {
+            orgTree = await queryable.Select<OrgTreeOutput>().ToTreeAsync(u => u.Children, u => u.Pid, input.Id);
+        }
+        else
+        {
+            orgTree = await queryable.Select<OrgTreeOutput>().ToTreeAsync(u => u.Children, u => u.Pid, input.Id, userOrgIdList.Select(d => (object)d).ToArray());
+            // 递归禁用没权限的机构(防止用户修改或创建无权的机构和用户)
+            HandlerOrgTree(orgTree, userOrgIdList);
+        }
+
+        var sysOrg = await _sysOrgRep.AsQueryable().Select<OrgTreeOutput>().FirstAsync(u => u.Id == input.Id);
+        if (sysOrg == null) return orgTree;
+
+        sysOrg.Children = orgTree;
+        orgTree = new List<OrgTreeOutput> { sysOrg };
+        return orgTree;
+    }
+
+    /// <summary>
+    /// 递归禁用没权限的机构
+    /// </summary>
+    /// <param name="orgTree"></param>
+    /// <param name="userOrgIdList"></param>
+    private static void HandlerOrgTree(List<OrgTreeOutput> orgTree, List<long> userOrgIdList)
+    {
+        foreach (var org in orgTree)
+        {
+            org.Disabled = !userOrgIdList.Contains(org.Id); // 设置禁用/不可选择
+            if (org.Children != null)
+                HandlerOrgTree(org.Children, userOrgIdList);
+        }
+    }
+
+    /// <summary>
     /// 增加机构 🔖
     /// </summary>
     /// <param name="input"></param>

+ 2 - 2
Admin.NET/Admin.NET.Core/Service/User/SysUserService.cs

@@ -297,9 +297,9 @@ public class SysUserService : IDynamicApiController, ITransient
     /// </summary>
     /// <returns></returns>
     [DisplayName("查询用户组织机构信息")]
-    public virtual async Task<List<SysOrg>> GetOrgInfo()
+    public virtual async Task<List<OrgTreeOutput>> GetOrgInfo()
     {
-        return await _sysOrgService.GetList(new OrgInput { Id = 0 });
+        return await _sysOrgService.GetTree(new OrgInput { Id = 0 });
     }
 
     /// <summary>

+ 22 - 22
Admin.NET/Admin.NET.Test/Admin.NET.Test.csproj

@@ -1,26 +1,26 @@
 <Project Sdk="Microsoft.NET.Sdk">
-    <PropertyGroup>
-        <TargetFrameworks>net8.0;net9.0</TargetFrameworks>
-        <NoWarn>1701;1702;1591;8632</NoWarn>
-        <DocumentationFile></DocumentationFile>
-        <ImplicitUsings>enable</ImplicitUsings>
-        <PreserveCompilationContext>true</PreserveCompilationContext>
-        <Nullable>disable</Nullable>
-        <GenerateDocumentationFile>True</GenerateDocumentationFile>
-        <Copyright>Admin.NET</Copyright>
-        <Description>Admin.NET 通用权限开发平台</Description>
-    </PropertyGroup>
+  <PropertyGroup>
+    <TargetFrameworks>net8.0;net9.0</TargetFrameworks>
+    <NoWarn>1701;1702;1591;8632</NoWarn>
+    <DocumentationFile></DocumentationFile>
+    <ImplicitUsings>enable</ImplicitUsings>
+    <PreserveCompilationContext>true</PreserveCompilationContext>
+    <Nullable>disable</Nullable>
+    <GenerateDocumentationFile>True</GenerateDocumentationFile>
+    <Copyright>Admin.NET</Copyright>
+    <Description>Admin.NET 通用权限开发平台</Description>
+  </PropertyGroup>
 
-    <ItemGroup>
-      <PackageReference Include="Furion.Xunit" Version="4.9.7.105" />
-      <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
-      <PackageReference Include="Selenium.Support" Version="4.34.0" />
-      <PackageReference Include="Selenium.WebDriver" Version="4.34.0" />
-      <PackageReference Include="Selenium.WebDriver.MSEdgeDriver" Version="138.0.3351.95" />
-      <PackageReference Include="xunit.assert" Version="2.9.3" />
-    </ItemGroup>
+  <ItemGroup>
+    <PackageReference Include="Furion.Xunit" Version="4.9.7.108" />
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
+    <PackageReference Include="Selenium.Support" Version="4.34.0" />
+    <PackageReference Include="Selenium.WebDriver" Version="4.34.0" />
+    <PackageReference Include="Selenium.WebDriver.MSEdgeDriver" Version="138.0.3351.121" />
+    <PackageReference Include="xunit.assert" Version="2.9.3" />
+  </ItemGroup>
 
-    <ItemGroup>
-        <ProjectReference Include="..\Admin.NET.Core\Admin.NET.Core.csproj" />
-    </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\Admin.NET.Core\Admin.NET.Core.csproj" />
+  </ItemGroup>
 </Project>

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

@@ -11,7 +11,7 @@
 
   <ItemGroup>
     <PackageReference Include="IGeekFan.AspNetCore.Knife4jUI" Version="0.0.16" />
-    <PackageReference Include="System.Security.Cryptography.Pkcs" Version="9.0.7" />
+    <PackageReference Include="System.Security.Cryptography.Pkcs" Version="9.0.8" />
   </ItemGroup>
 
   <ItemGroup>

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

@@ -53,7 +53,7 @@
       <CopyToOutputDirectory>Never</CopyToOutputDirectory>
     </EmbeddedResource>
   </ItemGroup>
-	
+
   <ItemGroup>
     <Content Update="wwwroot\upload\logo.png">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>

+ 1 - 1
Admin.NET/Plugins/Admin.NET.Plugin.ApprovalFlow/Admin.NET.Plugin.ApprovalFlow.csproj

@@ -22,5 +22,5 @@
   <ItemGroup>
     <ProjectReference Include="..\..\Admin.NET.Core\Admin.NET.Core.csproj" />
   </ItemGroup>
-	
+
 </Project>

+ 1 - 1
Admin.NET/Plugins/Admin.NET.Plugin.ReZero/Admin.NET.Plugin.ReZero.csproj

@@ -26,7 +26,7 @@
   <ItemGroup>
     <PackageReference Include="DocumentFormat.OpenXml" Version="3.3.0" />
     <PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="4.14.0" />
-    <PackageReference Include="Rezero.Api" Version="1.8.24" />
+    <PackageReference Include="Rezero.Api" Version="1.8.25" />
   </ItemGroup>
 
   <ItemGroup>

+ 2 - 2
Web/package.json

@@ -126,7 +126,7 @@
 			"json-editor-vue",
 			"vue-demi"
 		],
-		"overrides": {
+        "overrides": {
 			"rollup": "4.43.0"
 		}
 	},
@@ -149,4 +149,4 @@
 		"vue-next-admin",
 		"next-admin"
 	]
-}
+}

+ 85 - 0
Web/src/api-services/apis/sys-menu-api.ts

@@ -18,11 +18,13 @@ import { Configuration } from '../configuration';
 // @ts-ignore
 import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError } from '../base';
 import { AddMenuInput } from '../models';
+import { AdminResultInt32 } from '../models';
 import { AdminResultInt64 } from '../models';
 import { AdminResultListMenuOutput } from '../models';
 import { AdminResultListString } from '../models';
 import { AdminResultListSysMenu } from '../models';
 import { DeleteMenuInput } from '../models';
+import { MenuStatusInput } from '../models';
 import { MenuTypeEnum } from '../models';
 import { UpdateMenuInput } from '../models';
 /**
@@ -273,6 +275,54 @@ export const SysMenuApiAxiosParamCreator = function (configuration?: Configurati
         },
         /**
          * 
+         * @summary 设置菜单状态 🔖
+         * @param {MenuStatusInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        apiSysMenuSetStatusPost: async (body?: MenuStatusInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/api/sysMenu/setStatus`;
+            // 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
+            // http bearer authentication required
+            if (configuration && configuration.accessToken) {
+                const accessToken = typeof configuration.accessToken === 'function'
+                    ? await configuration.accessToken()
+                    : await configuration.accessToken;
+                localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
+            }
+
+            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 更新菜单 🔖
          * @param {UpdateMenuInput} [body] 
          * @param {*} [options] Override http request option.
@@ -400,6 +450,20 @@ export const SysMenuApiFp = function(configuration?: Configuration) {
         },
         /**
          * 
+         * @summary 设置菜单状态 🔖
+         * @param {MenuStatusInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async apiSysMenuSetStatusPost(body?: MenuStatusInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultInt32>>> {
+            const localVarAxiosArgs = await SysMenuApiAxiosParamCreator(configuration).apiSysMenuSetStatusPost(body, options);
+            return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
+                const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
+                return axios.request(axiosRequestArgs);
+            };
+        },
+        /**
+         * 
          * @summary 更新菜单 🔖
          * @param {UpdateMenuInput} [body] 
          * @param {*} [options] Override http request option.
@@ -473,6 +537,16 @@ export const SysMenuApiFactory = function (configuration?: Configuration, basePa
         },
         /**
          * 
+         * @summary 设置菜单状态 🔖
+         * @param {MenuStatusInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async apiSysMenuSetStatusPost(body?: MenuStatusInput, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultInt32>> {
+            return SysMenuApiFp(configuration).apiSysMenuSetStatusPost(body, options).then((request) => request(axios, basePath));
+        },
+        /**
+         * 
          * @summary 更新菜单 🔖
          * @param {UpdateMenuInput} [body] 
          * @param {*} [options] Override http request option.
@@ -548,6 +622,17 @@ export class SysMenuApi extends BaseAPI {
     }
     /**
      * 
+     * @summary 设置菜单状态 🔖
+     * @param {MenuStatusInput} [body] 
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof SysMenuApi
+     */
+    public async apiSysMenuSetStatusPost(body?: MenuStatusInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultInt32>> {
+        return SysMenuApiFp(this.configuration).apiSysMenuSetStatusPost(body, options).then((request) => request(this.axios, this.basePath));
+    }
+    /**
+     * 
      * @summary 更新菜单 🔖
      * @param {UpdateMenuInput} [body] 
      * @param {*} [options] Override http request option.

+ 120 - 0
Web/src/api-services/apis/sys-org-api.ts

@@ -19,6 +19,7 @@ import { Configuration } from '../configuration';
 import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError } from '../base';
 import { AddOrgInput } from '../models';
 import { AdminResultInt64 } from '../models';
+import { AdminResultListOrgTreeOutput } from '../models';
 import { AdminResultListSysOrg } from '../models';
 import { DeleteOrgInput } from '../models';
 import { UpdateOrgInput } from '../models';
@@ -198,6 +199,78 @@ export const SysOrgApiAxiosParamCreator = function (configuration?: Configuratio
         },
         /**
          * 
+         * @summary 获取机构树 🔖
+         * @param {number} id 主键Id
+         * @param {string} [name] 名称
+         * @param {string} [code] 编码
+         * @param {string} [type] 机构类型
+         * @param {number} [tenantId] 租户Id
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        apiSysOrgTreeGet: async (id: number, name?: string, code?: string, type?: string, tenantId?: 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 apiSysOrgTreeGet.');
+            }
+            const localVarPath = `/api/sysOrg/tree`;
+            // 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
+            // http bearer authentication required
+            if (configuration && configuration.accessToken) {
+                const accessToken = typeof configuration.accessToken === 'function'
+                    ? await configuration.accessToken()
+                    : await configuration.accessToken;
+                localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
+            }
+
+            if (name !== undefined) {
+                localVarQueryParameter['Name'] = name;
+            }
+
+            if (code !== undefined) {
+                localVarQueryParameter['Code'] = code;
+            }
+
+            if (type !== undefined) {
+                localVarQueryParameter['Type'] = type;
+            }
+
+            if (tenantId !== undefined) {
+                localVarQueryParameter['TenantId'] = tenantId;
+            }
+
+            if (id !== undefined) {
+                localVarQueryParameter['Id'] = id;
+            }
+
+            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 更新机构 🔖
          * @param {UpdateOrgInput} [body] 
          * @param {*} [options] Override http request option.
@@ -301,6 +374,24 @@ export const SysOrgApiFp = function(configuration?: Configuration) {
         },
         /**
          * 
+         * @summary 获取机构树 🔖
+         * @param {number} id 主键Id
+         * @param {string} [name] 名称
+         * @param {string} [code] 编码
+         * @param {string} [type] 机构类型
+         * @param {number} [tenantId] 租户Id
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async apiSysOrgTreeGet(id: number, name?: string, code?: string, type?: string, tenantId?: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultListOrgTreeOutput>>> {
+            const localVarAxiosArgs = await SysOrgApiAxiosParamCreator(configuration).apiSysOrgTreeGet(id, name, code, type, tenantId, options);
+            return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
+                const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
+                return axios.request(axiosRequestArgs);
+            };
+        },
+        /**
+         * 
          * @summary 更新机构 🔖
          * @param {UpdateOrgInput} [body] 
          * @param {*} [options] Override http request option.
@@ -358,6 +449,20 @@ export const SysOrgApiFactory = function (configuration?: Configuration, basePat
         },
         /**
          * 
+         * @summary 获取机构树 🔖
+         * @param {number} id 主键Id
+         * @param {string} [name] 名称
+         * @param {string} [code] 编码
+         * @param {string} [type] 机构类型
+         * @param {number} [tenantId] 租户Id
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async apiSysOrgTreeGet(id: number, name?: string, code?: string, type?: string, tenantId?: number, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultListOrgTreeOutput>> {
+            return SysOrgApiFp(configuration).apiSysOrgTreeGet(id, name, code, type, tenantId, options).then((request) => request(axios, basePath));
+        },
+        /**
+         * 
          * @summary 更新机构 🔖
          * @param {UpdateOrgInput} [body] 
          * @param {*} [options] Override http request option.
@@ -415,6 +520,21 @@ export class SysOrgApi extends BaseAPI {
     }
     /**
      * 
+     * @summary 获取机构树 🔖
+     * @param {number} id 主键Id
+     * @param {string} [name] 名称
+     * @param {string} [code] 编码
+     * @param {string} [type] 机构类型
+     * @param {number} [tenantId] 租户Id
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof SysOrgApi
+     */
+    public async apiSysOrgTreeGet(id: number, name?: string, code?: string, type?: string, tenantId?: number, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultListOrgTreeOutput>> {
+        return SysOrgApiFp(this.configuration).apiSysOrgTreeGet(id, name, code, type, tenantId, options).then((request) => request(this.axios, this.basePath));
+    }
+    /**
+     * 
      * @summary 更新机构 🔖
      * @param {UpdateOrgInput} [body] 
      * @param {*} [options] Override http request option.

+ 4 - 4
Web/src/api-services/apis/sys-user-api.ts

@@ -21,7 +21,7 @@ import { AddUserInput } from '../models';
 import { AdminResultInt32 } from '../models';
 import { AdminResultInt64 } from '../models';
 import { AdminResultListInt64 } from '../models';
-import { AdminResultListSysOrg } from '../models';
+import { AdminResultListOrgTreeOutput } from '../models';
 import { AdminResultListSysUserExtOrg } from '../models';
 import { AdminResultSqlSugarPagedListUserOutput } from '../models';
 import { AdminResultString } from '../models';
@@ -754,7 +754,7 @@ export const SysUserApiFp = function(configuration?: Configuration) {
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async apiSysUserOrgInfoGet(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultListSysOrg>>> {
+        async apiSysUserOrgInfoGet(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultListOrgTreeOutput>>> {
             const localVarAxiosArgs = await SysUserApiAxiosParamCreator(configuration).apiSysUserOrgInfoGet(options);
             return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
                 const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
@@ -947,7 +947,7 @@ export const SysUserApiFactory = function (configuration?: Configuration, basePa
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async apiSysUserOrgInfoGet(options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultListSysOrg>> {
+        async apiSysUserOrgInfoGet(options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultListOrgTreeOutput>> {
             return SysUserApiFp(configuration).apiSysUserOrgInfoGet(options).then((request) => request(axios, basePath));
         },
         /**
@@ -1112,7 +1112,7 @@ export class SysUserApi extends BaseAPI {
      * @throws {RequiredError}
      * @memberof SysUserApi
      */
-    public async apiSysUserOrgInfoGet(options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultListSysOrg>> {
+    public async apiSysUserOrgInfoGet(options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultListOrgTreeOutput>> {
         return SysUserApiFp(this.configuration).apiSysUserOrgInfoGet(options).then((request) => request(this.axios, this.basePath));
     }
     /**

+ 71 - 0
Web/src/api-services/models/admin-result-list-org-tree-output.ts

@@ -0,0 +1,71 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * Admin.NET 通用权限开发平台
+ * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。<br/><u><b><font color='FF0000'> 👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!</font></b></u>
+ *
+ * OpenAPI spec version: 1.0.0
+ * 
+ *
+ * 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 { OrgTreeOutput } from './org-tree-output';
+ /**
+ * 全局返回结果
+ *
+ * @export
+ * @interface AdminResultListOrgTreeOutput
+ */
+export interface AdminResultListOrgTreeOutput {
+
+    /**
+     * 状态码
+     *
+     * @type {number}
+     * @memberof AdminResultListOrgTreeOutput
+     */
+    code?: number;
+
+    /**
+     * 类型success、warning、error
+     *
+     * @type {string}
+     * @memberof AdminResultListOrgTreeOutput
+     */
+    type?: string | null;
+
+    /**
+     * 错误信息
+     *
+     * @type {string}
+     * @memberof AdminResultListOrgTreeOutput
+     */
+    message?: string | null;
+
+    /**
+     * 数据
+     *
+     * @type {Array<OrgTreeOutput>}
+     * @memberof AdminResultListOrgTreeOutput
+     */
+    result?: Array<OrgTreeOutput> | null;
+
+    /**
+     * 附加数据
+     *
+     * @type {any}
+     * @memberof AdminResultListOrgTreeOutput
+     */
+    extras?: any | null;
+
+    /**
+     * 时间
+     *
+     * @type {Date}
+     * @memberof AdminResultListOrgTreeOutput
+     */
+    time?: Date;
+}

+ 3 - 0
Web/src/api-services/models/index.ts

@@ -44,6 +44,7 @@ export * from './admin-result-list-enum-type-output';
 export * from './admin-result-list-int64';
 export * from './admin-result-list-log-vis-output';
 export * from './admin-result-list-menu-output';
+export * from './admin-result-list-org-tree-output';
 export * from './admin-result-list-role-output';
 export * from './admin-result-list-string';
 export * from './admin-result-list-sys-config';
@@ -242,6 +243,7 @@ export * from './mapping-type';
 export * from './member-info';
 export * from './member-types';
 export * from './menu-output';
+export * from './menu-status-input';
 export * from './menu-type-enum';
 export * from './message-input';
 export * from './message-template-send-input';
@@ -260,6 +262,7 @@ export * from './notice-user-status-enum';
 export * from './number-format-info';
 export * from './open-access-input';
 export * from './open-access-output';
+export * from './org-tree-output';
 export * from './page-config-input';
 export * from './page-dict-data-input';
 export * from './page-dict-type-input';

+ 37 - 0
Web/src/api-services/models/menu-status-input.ts

@@ -0,0 +1,37 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * Admin.NET 通用权限开发平台
+ * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。<br/><u><b><font color='FF0000'> 👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!</font></b></u>
+ *
+ * OpenAPI spec version: 1.0.0
+ * 
+ *
+ * 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 { StatusEnum } from './status-enum';
+ /**
+ * 
+ *
+ * @export
+ * @interface MenuStatusInput
+ */
+export interface MenuStatusInput {
+
+    /**
+     * 主键Id
+     *
+     * @type {number}
+     * @memberof MenuStatusInput
+     */
+    id: number;
+
+    /**
+     * @type {StatusEnum}
+     * @memberof MenuStatusInput
+     */
+    status?: StatusEnum;
+}

+ 71 - 0
Web/src/api-services/models/org-tree-output.ts

@@ -0,0 +1,71 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * Admin.NET 通用权限开发平台
+ * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。<br/><u><b><font color='FF0000'> 👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!</font></b></u>
+ *
+ * OpenAPI spec version: 1.0.0
+ * 
+ *
+ * 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 { OrgTreeOutput } from './org-tree-output';
+ /**
+ * 机构树形输出
+ *
+ * @export
+ * @interface OrgTreeOutput
+ */
+export interface OrgTreeOutput {
+
+    /**
+     * 主键Id
+     *
+     * @type {number}
+     * @memberof OrgTreeOutput
+     */
+    id?: number;
+
+    /**
+     * 租户Id
+     *
+     * @type {number}
+     * @memberof OrgTreeOutput
+     */
+    tenantId?: number;
+
+    /**
+     * 父Id
+     *
+     * @type {number}
+     * @memberof OrgTreeOutput
+     */
+    pid?: number;
+
+    /**
+     * 名称
+     *
+     * @type {string}
+     * @memberof OrgTreeOutput
+     */
+    name?: string | null;
+
+    /**
+     * 机构子项
+     *
+     * @type {Array<OrgTreeOutput>}
+     * @memberof OrgTreeOutput
+     */
+    children?: Array<OrgTreeOutput> | null;
+
+    /**
+     * 是否禁止选中
+     *
+     * @type {boolean}
+     * @memberof OrgTreeOutput
+     */
+    disabled?: boolean;
+}

+ 1 - 1
Web/src/components/table/modifyRecord.vue

@@ -1,5 +1,5 @@
 <template>
-	<el-popover placement="bottom" width="280" trigger="hover">
+	<el-popover placement="bottom" width="280" trigger="hover" :show-after="600">
 		<template #reference>
 			<el-text type="primary" class="cursor-default">
 				<el-icon><ele-InfoFilled /></el-icon>详情

+ 136 - 118
Web/src/components/table/search.vue

@@ -1,106 +1,112 @@
 <template>
-	<div class="table-search-container" v-if="props.search.length > 0">
-		<el-form ref="tableSearchRef" :model="state.innerModelValue" label-width="100px" class="table-form">
-			<el-row :gutter="20">
-				<!-- <el-col :xs="12" :sm="8" :md="8" :lg="6" :xl="4" class="mb20"></el-col> -->
-				<el-col :xs="12" :sm="5" :md="5" :lg="6" :xl="4" v-for="(val, key) in search" :key="key" v-show="key < 3 || state.isToggle">
-					<template v-if="val.type">
-						<el-form-item
-							label-width="auto"
-							:label="val.label"
-							:prop="val.prop"
-							:rules="[{ required: val.required, message: `${val.label}不能为空`, trigger: val.type === 'input' ? 'blur' : 'change' }]"
-						>
-							<el-input
-								v-model="state.innerModelValue[val.prop]"
-								v-bind="val.comProps"
-								:placeholder="val.placeholder"
-								:clearable="!val.required"
-								v-if="val.type === 'input'"
-								@keyup.enter="onSearch(tableSearchRef)"
-								@change="val.change"
-								class="w100"
-							/>
-							<el-date-picker
-								v-model="state.innerModelValue[val.prop]"
-								v-bind="val.comProps"
-								type="date"
-								:placeholder="val.placeholder"
-								:clearable="!val.required"
-								v-else-if="val.type === 'date'"
-								@change="val.change"
-								class="w100"
-							/>
-							<el-date-picker
-								v-model="state.innerModelValue[val.prop]"
-								v-bind="val.comProps"
-								type="monthrange"
-								value-format="YYYY/MM/DD"
-								:placeholder="val.placeholder"
-								:clearable="!val.required"
-								v-else-if="val.type === 'monthrange'"
-								@change="val.change"
-								class="w100"
-							/>
-							<el-date-picker
-								v-model="state.innerModelValue[val.prop]"
-								v-bind="val.comProps"
-								type="daterange"
-								value-format="YYYY/MM/DD"
-								range-separator="至"
-								start-placeholder="开始日期"
-								end-placeholder="结束日期"
-								:clearable="!val.required"
-								:shortcuts="shortcuts"
-								:default-time="defaultTime"
-								v-else-if="val.type === 'daterange'"
-								@change="val.change"
-								class="w100"
-							/>
-							<el-select
-								v-model="state.innerModelValue[val.prop]"
-								v-bind="val.comProps"
-								:clearable="!val.required"
-								:placeholder="val.placeholder"
-								v-else-if="val.type === 'select'"
-								@change="val.change"
-								class="w100"
-							>
-								<el-option v-for="item in getSelectOptions(val)" :key="item.value" :label="item.label" :value="item.value" />
-							</el-select>
-							<el-cascader
-								v-else-if="val.type === 'cascader' && val.cascaderData"
-								:options="val.cascaderData"
-								:clearable="!val.required"
-								filterable
-								:props="val.cascaderProps ? val.cascaderProps : state.cascaderProps"
-								:placeholder="val.placeholder"
-								@change="val.change"
-								class="w100"
-								v-bind="val.comProps"
-								v-model="state.innerModelValue[val.prop]"
-							>
-							</el-cascader>
-						</el-form-item>
-					</template>
-				</el-col>
-				<el-col :xs="12" :sm="9" :md="9" :lg="6" :xl="4">
-					<el-form-item class="table-form-btn" label-width="auto">
-						<div>
-							<!-- 使用el-button-group会导致具有type属性的按钮的右边框无法显示 -->
-							<!-- <el-button-group> -->
-							<el-button plain type="primary" icon="ele-Search" @click="onSearch(tableSearchRef)"> 查询 </el-button>
-							<el-button icon="ele-Refresh" @click="onReset(tableSearchRef)" style="margin-left: 12px"> 重置 </el-button>
-							<!-- </el-button-group> -->
-						</div>
-					</el-form-item>
-				</el-col>
-			</el-row>
-			<el-divider style="margin-top: 5px" v-if="search.length > 3">
-				<el-button :icon="state.isToggle ? 'ele-ArrowUpBold' : 'ele-ArrowDownBold'" class="divider-btn" @click="state.isToggle = !state.isToggle"> </el-button>
-			</el-divider>
-		</el-form>
-	</div>
+	<div style="display: flex;">
+        <!-- <div class="table-search-container"> -->
+        <div :class="['table-search-container', { 'table-search-flex': search.length > defaultShowCount }]">
+            <el-form ref="tableSearchRef" :model="state.innerModelValue" :inline="true" label-width="100px">
+                <span v-for="(val, key) in search" :key="key" v-show="key < defaultShowCount || state.isToggle">
+                    <template v-if="val.type">
+                        <el-form-item
+                                label-width="auto"
+                                :label="val.label"
+                                :prop="val.prop"
+                                :rules="[{ required: val.required, message: `${val.label}不能为空`, trigger: val.type === 'input' ? 'blur' : 'change' }]"
+                            >
+                                <el-input
+                                    v-model="state.innerModelValue[val.prop]"
+                                    v-bind="val.comProps"
+                                    :placeholder="val.placeholder"
+                                    :clearable="!val.required"
+                                    v-if="val.type === 'input'"
+                                    @keyup.enter="onSearch(tableSearchRef)"
+                                    @change="val.change"
+                                />
+                                <el-date-picker
+                                    v-model="state.innerModelValue[val.prop]"
+                                    v-bind="val.comProps"
+                                    type="date"
+                                    :placeholder="val.placeholder"
+                                    :clearable="!val.required"
+                                    v-else-if="val.type === 'date'"
+                                    @change="val.change"
+                                />
+                                <el-date-picker
+                                    v-model="state.innerModelValue[val.prop]"
+                                    v-bind="val.comProps"
+                                    type="monthrange"
+                                    value-format="YYYY/MM/DD"
+                                    :placeholder="val.placeholder"
+                                    :clearable="!val.required"
+                                    v-else-if="val.type === 'monthrange'"
+                                    @change="val.change"
+                                />
+                                <el-date-picker
+                                    v-model="state.innerModelValue[val.prop]"
+                                    v-bind="val.comProps"
+                                    type="daterange"
+                                    value-format="YYYY/MM/DD"
+                                    range-separator="至"
+                                    start-placeholder="开始日期"
+                                    end-placeholder="结束日期"
+                                    :clearable="!val.required"
+                                    :shortcuts="shortcuts"
+                                    :default-time="defaultTime"
+                                    v-else-if="val.type === 'daterange'"
+                                    @change="val.change"
+                                />
+                                <el-select
+                                    v-model="state.innerModelValue[val.prop]"
+                                    v-bind="val.comProps"
+                                    :clearable="!val.required"
+                                    :placeholder="val.placeholder"
+                                    v-else-if="val.type === 'select'"
+                                    @change="val.change"
+                                >
+                                    <el-option v-for="item in getSelectOptions(val)" :key="item.value" :label="item.label" :value="item.value" />
+                                </el-select>
+                                <el-cascader
+                                    v-else-if="val.type === 'cascader' && val.cascaderData"
+                                    :options="val.cascaderData"
+                                    :clearable="!val.required"
+                                    filterable
+                                    :props="val.cascaderProps ? val.cascaderProps : state.cascaderProps"
+                                    :placeholder="val.placeholder"
+                                    @change="val.change"
+                                    v-bind="val.comProps"
+                                    v-model="state.innerModelValue[val.prop]"
+                                >
+                                </el-cascader>
+                        </el-form-item>
+                    </template>
+                </span>
+            </el-form>
+        </div>
+        <div v-if="search.length > defaultShowCount" class="table-search-more">
+            <el-form :inline="true">
+                <el-form-item>
+                    <el-button text @click="state.isToggle = !state.isToggle"
+                    >更多查询
+                        <el-icon class="el-icon--right">
+                            <ele-ArrowUpBold v-if="state.isToggle" />
+                            <ele-ArrowDownBold v-else />
+                        </el-icon>
+                </el-button>
+                    
+                    
+                </el-form-item>
+            </el-form>
+        </div>
+        <div class="table-search-btn">
+            <el-form :inline="true">
+                <el-form-item>
+                    <!-- 使用el-button-group会导致具有type属性的按钮的右边框无法显示 -->
+                    <!-- <el-button-group> -->
+                    <el-button plain type="primary" icon="ele-Search" @click="onSearch(tableSearchRef)"> 查询 </el-button>
+                    <el-button icon="ele-Refresh" @click="onReset(tableSearchRef)" style="margin-left: 12px"> 重置 </el-button>
+                    <!-- </el-button-group> -->
+                </el-form-item>
+            </el-form>
+        </div>
+    </div>
 </template>
 
 <script setup lang="ts" name="makeTableDemoSearch">
@@ -121,6 +127,11 @@ const props = defineProps({
 		type: Object,
 		default: () => ({}),
 	},
+    // 默认显示几个查询条件,超过则隐藏,点击更多展开
+    defaultShowCount: {
+        type: Number,
+        default: 5,
+    },
 });
 
 // 定义子组件向父组件传值/事件
@@ -209,24 +220,31 @@ const shortcuts = [
 </script>
 
 <style scoped lang="scss">
+.table-search-flex {
+    flex: 1;
+}
+
 .table-search-container {
-	display: flex;
-
-	.table-form {
-		flex: 1;
-
-		.table-form-btn-toggle {
-			white-space: nowrap;
-			user-select: none;
-			display: flex;
-			align-items: center;
-			color: var(--el-color-primary);
-		}
-	}
+    //flex: 1;
+
+    :deep(.el-form-item--small .el-form-item__label) {
+        padding: 0 8px 0 0;
+    }
 }
 
-.divider-btn {
-	height: 20px;
-	border-radius: 10px;
+.table-search-more {
+	border-right: 1px solid var(--el-card-border-color);
+}
+
+.table-search-btn {
+    width: 184px;
+
+    // 右侧查询重置按钮随展开垂直居中
+    // .el-form--inline {
+    //     height: 100%;
+	// 	.el-form-item--small.el-form-item,.el-form-item:last-of-type {
+    //         height: calc(100% - 10px);
+    //     }
+	// }
 }
 </style>

+ 1 - 1
Web/src/layout/footer/index.vue

@@ -21,7 +21,7 @@ const { themeConfig } = storeToRefs(storesThemeConfig);
 	display: flex;
     line-height: 30px;
     height: 30px;
-    background: #fff;
+    background: var(--el-bg-color);
     border-top: 1px solid var(--el-border-color-light);
 
 	&-warp {

+ 13 - 3
Web/src/layout/navBars/topBar/user.vue

@@ -35,7 +35,7 @@
 			<i class="icon-skin iconfont" title="布局配置"></i>
 		</div>
 		<div class="layout-navbars-breadcrumb-user-icon">
-			<el-popover placement="bottom" trigger="hover" transition="el-zoom-in-top" :width="300" :persistent="false">
+			<el-popover placement="bottom" trigger="click" transition="el-zoom-in-top" :width="300" :persistent="false">
 				<template #reference>
 					<el-badge :is-dot="hasUnreadNotice">
 						<el-icon title="消息">
@@ -55,7 +55,7 @@
 				<ele-User />
 			</el-icon>
 		</div>
-		<el-dropdown :show-timeout="70" :hide-timeout="50" size="large" @command="onHandleCommandClick">
+		<el-dropdown :show-timeout="70" :hide-timeout="50" trigger="click" size="large" @command="onHandleCommandClick">
 			<span class="layout-navbars-breadcrumb-user-link">
 				<el-tooltip effect="dark" placement="left">
 					<template #content>
@@ -69,7 +69,7 @@
 					<img :src="userInfos.avatar" class="layout-navbars-breadcrumb-user-link-photo mr5" />
 				</el-tooltip>
 				{{ userInfos.realName == '' ? userInfos.account : userInfos.realName }}
-				<el-icon class="el-icon--right">
+				<el-icon class="dropdown-icon">
 					<ele-ArrowDown />
 				</el-icon>
 			</span>
@@ -323,12 +323,22 @@ const receiveNotice = (msg: any) => {
 		display: flex;
 		align-items: center;
 		white-space: nowrap;
+        cursor: pointer;
 
 		&-photo {
 			width: 25px;
 			height: 25px;
 			border-radius: 100%;
 		}
+
+        .dropdown-icon {
+            transition: transform 0.3s; /* 添加过渡效果 */
+        }
+        &:has(.dropdown-icon)[aria-expanded=true] {
+            .dropdown-icon {
+                transform: rotate(180deg);
+            }
+        }
 	}
 
 	&-icon {

+ 4 - 0
Web/src/main.ts

@@ -6,6 +6,7 @@ import router from '/@/router';
 import { directive } from '/@/directive/index';
 import other from '/@/utils/other';
 import ElementPlus from 'element-plus';
+import { ElTooltip, ElTable } from 'element-plus'
 import '/@/theme/index.scss';
 // 动画库
 import 'animate.css';
@@ -35,4 +36,7 @@ app.component('GSysDict', sysDict);
 // 注册全局多语言组件
 app.component('GMultiLangInput', multiLangInput);
 
+const TooltipProps = ElTooltip.props
+TooltipProps.showAfter = { type: Number, default: 800 }; // 设置全局tooltip延时显示时间为800毫秒
+
 app.use(pinia).use(router).use(ElementPlus).use(VueGridLayout).use(VForm3).use(VueSignaturePad).use(vue3TreeOrg).mount('#app');

+ 13 - 0
Web/src/theme/element.scss

@@ -545,3 +545,16 @@ $--el-table-text-color: #fb6d49;
 		}
 	}
 }
+
+
+/* Splitter 分隔面板
+------------------------------- */
+.smallbar-el-splitter {
+    .el-splitter-bar {
+        width: 8px !important;
+
+        .el-splitter-bar__dragger {
+            height: 100px !important;
+        }
+    }
+}

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

@@ -4,8 +4,8 @@
 			<NoticeBar text="系统缓存数据管理,请慎重操作!" style="margin: 4px" />
 		</div>
 
-		<splitpanes class="default-theme">
-			<pane size="20">
+		<el-splitter class="smallbar-el-splitter">
+			<el-splitter-panel size="20%" :min="200">
 				<el-card shadow="hover" header="缓存列表" v-loading="state.loading" style="height: 100%" body-style="height:100%; overflow:auto">
 					<template #header>
 						<div class="card-header">
@@ -31,8 +31,8 @@
 						accordion
 					/>
 				</el-card>
-			</pane>
-			<pane size="80">
+			</el-splitter-panel>
+			<el-splitter-panel :min="200">
 				<el-card shadow="hover" header="缓存数据" v-loading="state.loading1" style="height: 100%" body-style="height:100%; overflow:auto">
 					<template #header>
 						<div class="card-header">
@@ -42,8 +42,8 @@
 					</template>
 					<vue-json-pretty :data="state.cacheValue" showLength showIcon showLineNumber showSelectController style="padding-bottom: 60px" />
 				</el-card>
-			</pane>
-		</splitpanes>
+			</el-splitter-panel>
+		</el-splitter>
 	</div>
 </template>
 
@@ -53,7 +53,7 @@ import { ElMessageBox, ElMessage, ElTree } from 'element-plus';
 import NoticeBar from '/@/components/noticeBar/index.vue';
 import VueJsonPretty from 'vue-json-pretty';
 import 'vue-json-pretty/lib/styles.css';
-import { Splitpanes, Pane } from 'splitpanes';
+//import { Splitpanes, Pane } from 'splitpanes';
 import 'splitpanes/dist/splitpanes.css';
 
 import { getAPI } from '/@/utils/axios-utils';

+ 36 - 14
Web/src/views/system/menu/index.vue

@@ -4,29 +4,34 @@
 			<el-form :model="state.queryParams" ref="queryForm" :inline="true">
 				<el-form-item label="租户" v-if="userStore.userInfos.accountType == 999">
 					<el-select v-model="state.queryParams.tenantId" placeholder="租户" style="width: 100%">
-						<el-option :value="item.value" :label="`${item.label} (${item.host})`" v-for="(item, index) in state.tenantList" :key="index" />
+						<el-option :value="item.value" :label="`${item.label} (${item.host})`"
+							v-for="(item, index) in state.tenantList" :key="index" />
 					</el-select>
 				</el-form-item>
 				<el-form-item label="菜单名称">
 					<el-input v-model="state.queryParams.title" placeholder="菜单名称" clearable />
 				</el-form-item>
 				<el-form-item label="类型">
-          <g-sys-dict v-model="state.queryParams.type" code="MenuTypeEnum" render-as="select" placeholder="类型" clearable />
+					<g-sys-dict v-model="state.queryParams.type" code="MenuTypeEnum" render-as="select" placeholder="类型"
+						clearable />
 				</el-form-item>
 				<el-form-item>
 					<el-button-group>
-						<el-button type="primary" icon="ele-Search" @click="handleQuery" v-auth="'sysMenu:list'"> 查询 </el-button>
+						<el-button type="primary" icon="ele-Search" @click="handleQuery" v-auth="'sysMenu:list'"> 查询
+						</el-button>
 						<el-button icon="ele-Refresh" @click="resetQuery"> 重置 </el-button>
 					</el-button-group>
 				</el-form-item>
 				<el-form-item>
-					<el-button type="primary" icon="ele-Plus" @click="openAddMenu" v-auth="'sysMenu:add'"> 新增 </el-button>
+					<el-button type="primary" icon="ele-Plus" @click="openAddMenu" v-auth="'sysMenu:add'"> 新增
+					</el-button>
 				</el-form-item>
 			</el-form>
 		</el-card>
 
 		<el-card class="full-table" shadow="hover" style="margin-top: 5px">
-			<el-table :data="state.menuData" v-loading="state.loading" row-key="id" :tree-props="{ children: 'children', hasChildren: 'hasChildren' }" border>
+			<el-table :data="state.menuData" v-loading="state.loading" row-key="id"
+				:tree-props="{ children: 'children', hasChildren: 'hasChildren' }" border>
 				<el-table-column label="菜单名称" header-align="center" show-overflow-tooltip>
 					<template #default="scope">
 						<SvgIcon :name="scope.row.icon" />
@@ -35,7 +40,7 @@
 				</el-table-column>
 				<el-table-column label="类型" width="70" align="center" show-overflow-tooltip>
 					<template #default="scope">
-            <g-sys-dict v-model="scope.row.type" code="MenuTypeEnum" />
+						<g-sys-dict v-model="scope.row.type" code="MenuTypeEnum" />
 					</template>
 				</el-table-column>
 				<el-table-column prop="path" label="路由路径" header-align="center" show-overflow-tooltip />
@@ -44,7 +49,8 @@
 				<el-table-column prop="orderNo" label="排序" width="70" align="center" show-overflow-tooltip />
 				<el-table-column label="状态" width="80" align="center" show-overflow-tooltip>
 					<template #default="scope">
-            <g-sys-dict v-model="scope.row.status" code="StatusEnum" />
+						<el-switch v-model="scope.row.status" :active-value="1" :inactive-value="2" size="small"
+							@change="changeStatus(scope.row)" v-auth="'sysUser:setStatus'" />
 					</template>
 				</el-table-column>
 				<el-table-column label="修改记录" width="100" align="center" show-overflow-tooltip>
@@ -54,15 +60,19 @@
 				</el-table-column>
 				<el-table-column label="操作" width="210" fixed="right" align="center" show-overflow-tooltip>
 					<template #default="scope">
-						<el-button icon="ele-Edit" text type="primary" @click="openEditMenu(scope.row)" v-auth="'sysMenu:update'"> 编辑 </el-button>
-						<el-button icon="ele-Delete" text type="danger" @click="delMenu(scope.row)" v-auth="'sysMenu:delete'"> 删除 </el-button>
-						<el-button icon="ele-CopyDocument" text type="primary" @click="openCopyMenu(scope.row)" v-auth="'sysMenu:add'"> 复制 </el-button>
+						<el-button icon="ele-Edit" text type="primary" @click="openEditMenu(scope.row)"
+							v-auth="'sysMenu:update'"> 编辑 </el-button>
+						<el-button icon="ele-Delete" text type="danger" @click="delMenu(scope.row)"
+							v-auth="'sysMenu:delete'"> 删除 </el-button>
+						<el-button icon="ele-CopyDocument" text type="primary" @click="openCopyMenu(scope.row)"
+							v-auth="'sysMenu:add'"> 复制 </el-button>
 					</template>
 				</el-table-column>
 			</el-table>
 		</el-card>
 
-		<EditMenu ref="editMenuRef" :title="state.editMenuTitle" :menuData="state.allMenuData" @handleQuery="handleQuery" />
+		<EditMenu ref="editMenuRef" :title="state.editMenuTitle" :menuData="state.allMenuData"
+			@handleQuery="handleQuery" />
 	</div>
 </template>
 
@@ -73,9 +83,9 @@ import EditMenu from '/@/views/system/menu/component/editMenu.vue';
 import ModifyRecord from '/@/components/table/modifyRecord.vue';
 
 import { getAPI } from '/@/utils/axios-utils';
-import {SysMenuApi, SysTenantApi} from '/@/api-services/api';
+import { SysMenuApi, SysTenantApi } from '/@/api-services/api';
 import { SysMenu, UpdateMenuInput } from '/@/api-services/models';
-import {useUserInfo} from "/@/stores/userInfo";
+import { useUserInfo } from "/@/stores/userInfo";
 
 const userStore = useUserInfo();
 const editMenuRef = ref<InstanceType<typeof EditMenu>>();
@@ -159,6 +169,18 @@ const delMenu = (row: any) => {
 			handleQuery();
 			ElMessage.success('删除成功');
 		})
-		.catch(() => {});
+		.catch(() => { });
+};
+
+// 修改状态
+const changeStatus = async (row: any) => {
+	await getAPI(SysMenuApi)
+		.apiSysMenuSetStatusPost({ id: row.id, status: row.status })
+		.then(() => {
+			ElMessage.success('菜单状态设置成功');
+		})
+		.catch(() => {
+			row.status = row.status == 1 ? 2 : 1;
+		});
 };
 </script>

+ 4 - 4
Web/src/views/system/org/component/orgTree.vue

@@ -63,7 +63,7 @@ import { Search, MoreFilled } from '@element-plus/icons-vue';
 
 import { getAPI } from '/@/utils/axios-utils';
 import {SysOrgApi, SysTenantApi} from '/@/api-services/api';
-import { SysOrg } from '/@/api-services/models';
+import { OrgTreeOutput, SysOrg } from '/@/api-services/models';
 import { useUserInfo } from "/@/stores/userInfo";
 
 const props = defineProps({
@@ -76,9 +76,9 @@ const state = reactive({
 	loading: false,
 	tenantList: [] as Array<any>,
 	tenantId: props.tenantId as number,
-	orgData: [] as Array<SysOrg>,
+	orgData: [] as Array<OrgTreeOutput>,
 	isShowCheckbox: false,
-	ownOrgData: [] as Array<SysOrg>,
+	ownOrgData: [] as Array<OrgTreeOutput>,
 });
 
 onMounted( async () => {
@@ -94,7 +94,7 @@ watch(filterText, (val) => {
 
 const initTreeData = async () => {
 	state.loading = true;
-	const res = await getAPI(SysOrgApi).apiSysOrgListGet(0, undefined, undefined, undefined, state.tenantId);
+	const res = await getAPI(SysOrgApi).apiSysOrgTreeGet(0, undefined, undefined, undefined, state.tenantId);
 	state.orgData = res.data.result ?? [];
 	state.loading = false;
 };

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

@@ -1,10 +1,10 @@
 <template>
     <div class="sys-org-container">
-        <splitpanes class="default-theme">
-            <pane size="20">
+        <el-splitter class="smallbar-el-splitter">
+            <el-splitter-panel size="20%" :min="200">
                 <OrgTree ref="orgTreeRef" @node-click="nodeClick" />
-            </pane>
-            <pane size="80" style="overflow: auto; display: flex; flex-direction: column; background-color: #fff;">
+            </el-splitter-panel>
+            <el-splitter-panel :min="200" style="overflow: auto; display: flex; flex-direction: column;">
                 <el-card shadow="hover" :body-style="{ padding: 5 }">
                     <el-form :model="state.queryParams" ref="queryForm" :inline="true">
                         <el-form-item label="机构名称">
@@ -64,8 +64,8 @@
                         </el-table-column>
                     </el-table>
                 </el-card>
-            </pane>
-        </splitpanes>
+            </el-splitter-panel>
+        </el-splitter>
 
         <EditOrg ref="editOrgRef" :title="state.editOrgTitle" :orgData="state.orgTreeData" @reload="handleQuery" />
     </div>
@@ -74,7 +74,7 @@
 <script lang="ts" setup name="sysOrg">
 import { onMounted, reactive, ref } from 'vue';
 import { ElMessageBox, ElMessage } from 'element-plus';
-import { Splitpanes, Pane } from 'splitpanes';
+//import { Splitpanes, Pane } from 'splitpanes';
 import 'splitpanes/dist/splitpanes.css';
 import { getAPI } from '/@/utils/axios-utils';
 import { SysOrgApi } from '/@/api-services/api';

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

@@ -35,7 +35,7 @@
 				</el-table-column>
 				<el-table-column prop="userList" label="人员明细" width="120" align="center" show-overflow-tooltip >
 					<template #default="scope">
-						<el-popover placement="bottom" width="280" trigger="hover" v-if="scope.row.userList?.length">
+						<el-popover placement="bottom" width="280" trigger="hover" :show-after="600" v-if="scope.row.userList?.length">
 							<template #reference>
 								<el-text type="primary" class="cursor-default">
 									<el-icon><ele-InfoFilled /></el-icon>人员明细

+ 7 - 7
Web/src/views/system/region/index.vue

@@ -1,10 +1,10 @@
 <template>
 	<div class="sys-region-container">
-		<splitpanes class="default-theme">
-			<pane size="20">
+		<el-splitter class="smallbar-el-splitter">
+			<el-splitter-panel size="20%" :min="200">
 				<RegionTree ref="regionTreeRef" @node-click="nodeClick" />
-			</pane>
-			<pane size="80" style="overflow: auto; display: flex; flex-direction: column; background-color: #fff;">
+			</el-splitter-panel>
+			<el-splitter-panel :min="200" style="overflow: auto; display: flex; flex-direction: column;">
 				<el-card class="full-table" shadow="hover">
 					<el-form :model="state.queryParams" ref="queryForm" :inline="true">
 						<el-form-item label="行政名称">
@@ -49,8 +49,8 @@
 						layout="total, sizes, prev, pager, next, jumper"
 					/>
 				</el-card>
-			</pane>
-		</splitpanes>
+			</el-splitter-panel>
+		</el-splitter>
 
 		<EditRegion ref="editRegionRef" :title="state.editRegionTitle" @handleQuery="handleQuery" />
 	</div>
@@ -59,7 +59,7 @@
 <script lang="ts" setup name="sysRegion">
 import { onMounted, reactive, ref } from 'vue';
 import { ElMessageBox, ElMessage, ElNotification } from 'element-plus';
-import { Splitpanes, Pane } from 'splitpanes';
+//import { Splitpanes, Pane } from 'splitpanes';
 import 'splitpanes/dist/splitpanes.css';
 
 import RegionTree from '/@/views/system/region/component/regionTree.vue';

+ 6 - 6
Web/src/views/system/stressTest/index.vue

@@ -3,8 +3,8 @@
 		<div>
 			<NoticeBar text="接口压测会占用服务器大量的内存资源,请慎重操作!" style="margin: 4px" />
 		</div>
-		<splitpanes class="default-theme overlay-hidden">
-			<pane size="20" class="vh100">
+		<el-splitter class="smallbar-el-splitter overlay-hidden">
+			<el-splitter-panel size="20%" :min="200">
 				<el-card class="vh80" shadow="hover" header="接口列表" v-loading="state.loading">
 					<el-row :gutter="35">
 						<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb10">
@@ -37,8 +37,8 @@
 						</template>
 					</el-tree>
 				</el-card>
-			</pane>
-			<pane size="80" class="vh100">
+			</el-splitter-panel>
+			<el-splitter-panel :min="200">
 				<el-card class="main-container vh80" shadow="hover" header="缓存数据" v-loading="state.loading" body-style="height:100vh; overflow:auto">
 					<template #header>
 						<el-button type="primary" @click="showDialog(undefined)">开始测试</el-button>
@@ -105,8 +105,8 @@
 						</el-descriptions-item>
 					</el-descriptions>
 				</el-card>
-			</pane>
-		</splitpanes>
+			</el-splitter-panel>
+		</el-splitter>
 		<EditStressTest ref="editStressTestRef" @refreshData="refreshData" />
 	</div>
 </template>

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

@@ -1,6 +1,6 @@
 <template>
 	<div class="sys-config-container">
-		<el-card shadow="hover" :body-style="{ paddingBottom: '0' }">
+		<el-card shadow="hover" :body-style="{ paddingBottom: 5 }">
 			<TableSearch :search="tb.tableData.search" @search="onSearch" />
 		</el-card>
 		<el-card class="full-table" shadow="hover" style="margin-top: 5px">
@@ -70,7 +70,7 @@ const tb = reactive<TableDemoState>({
 		},
 		// 搜索表单,动态生成(传空数组时,将不显示搜索,type有3种类型:input,date,select)
 		search: [
-			{ label: '名称', prop: 'name', placeholder: '搜索模板名称', required: false, type: 'input' },
+            { label: '名称', prop: 'name', placeholder: '搜索模板名称', required: false, type: 'input' },
 			{ label: '编码', prop: 'code', placeholder: '搜索模板编码', required: false, type: 'input' },
 			{ label: '类型', prop: 'type', placeholder: '搜索模板类型', required: false, type: 'select', dictCode: 'TemplateTypeEnum' },
 		],

+ 6 - 6
Web/src/views/system/update/index.vue

@@ -187,7 +187,7 @@ onUnmounted(() => {
 .sys-update-container {
     display: flex;
     height: 100%;
-    background-color: #f0f2f5;
+    background-color: var(--next-bg-main-color);
 }
 
 .backup-list-description {
@@ -196,14 +196,14 @@ onUnmounted(() => {
 }
 
 .backup-list {
-    background-color: #ffffff;
+    background-color: var(--el-bg-color);
     padding: 20px;
     /* box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); */
     border-radius: 4px;
     transition: box-shadow 0.3s ease-in-out;
     max-height: 100%;
     overflow: hidden;
-    border: 1px solid rgba(0, 0, 0, 0.1);
+    border: var(--el-border);
 }
 
 .backup-items {
@@ -242,17 +242,17 @@ onUnmounted(() => {
     margin-left: 5px;
     display: flex;
     flex-direction: column;
-    background-color: #ffffff;
+    background-color: var(--el-bg-color);
     border-radius: 4px;
     /* box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); */
     transition: box-shadow 0.3s ease-in-out;
-    border: 1px solid rgba(0, 0, 0, 0.1);
+    border: var(--el-border);
 }
 
 .toolbar {
     /* margin-bottom: 5px; */
     padding: 5px 0;
-    background-color: #ffffff;
+    background-color: var(--el-bg-color);
     border-radius: 4px;
     /* box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1); */
     display: flex;

+ 11 - 21
Web/src/views/system/user/index.vue

@@ -1,21 +1,11 @@
 <template>
 	<div class="sys-user-container">
-		<splitpanes class="default-theme">
-			<pane size="20">
+		<el-splitter class="smallbar-el-splitter">
+			<el-splitter-panel size="20%" :min="200">
 				<OrgTree ref="orgTreeRef" @node-click="nodeClick" />
-			</pane>
-			<pane size="80" style="overflow: auto; display: flex; flex-direction: column; background-color: #fff;">
-                <!-- <el-collapse :before-collapse="() => {return false}" @icon-click="(handleQuery)">
-                    <el-collapse-item>
-                        <template #title>
-                            <el-button>aDefault</el-button>
-
-                        </template>
-                        <div slot="title"><el-button>aDefault</el-button></div>
-                        <div slot="default"><el-button>Default</el-button></div>
-                    </el-collapse-item>
-                </el-collapse> -->
-				<el-card shadow="hover" :body-style="{ padding: 5 }">
+			</el-splitter-panel>
+			<el-splitter-panel :min="200" style="overflow: auto; display: flex; flex-direction: column;">
+                <el-card shadow="hover" :body-style="{ padding: 5 }">
 					<el-form :model="state.queryParams" ref="queryForm" :inline="true">
 						<el-form-item label="账号">
 							<el-input v-model="state.queryParams.account" placeholder="账号" clearable />
@@ -127,8 +117,8 @@
 						:page-sizes="[10, 20, 50, 100]" size="small" background @size-change="handleSizeChange"
 						@current-change="handleCurrentChange" layout="total, sizes, prev, pager, next, jumper" />
 				</el-card>
-			</pane>
-		</splitpanes>
+			</el-splitter-panel>
+		</el-splitter>
 
 		<EditUser ref="editUserRef" :title="state.editUserTitle" :orgData="state.orgTreeData" @handleQuery="handleQuery" />
 	</div>
@@ -141,11 +131,11 @@ import OrgTree from '/@/views/system/org/component/orgTree.vue';
 import EditUser from '/@/views/system/user/component/editUser.vue';
 import ModifyRecord from '/@/components/table/modifyRecord.vue';
 import CallBar from '/@/components/callTel/callBar.vue';
-import { Splitpanes, Pane } from 'splitpanes';
+//import { Splitpanes, Pane } from 'splitpanes';
 import 'splitpanes/dist/splitpanes.css';
 import { getAPI } from '/@/utils/axios-utils';
 import { SysUserApi, SysOrgApi } from '/@/api-services/api';
-import { SysUser, SysOrg, UpdateUserInput } from '/@/api-services/models';
+import { SysUser, UpdateUserInput, OrgOutput } from '/@/api-services/models';
 
 const orgTreeRef = ref<InstanceType<typeof OrgTree>>();
 const editUserRef = ref<InstanceType<typeof EditUser>>();
@@ -153,7 +143,7 @@ const state = reactive({
 	loading: false,
 	tenantList: [] as Array<any>,
 	userData: [] as Array<SysUser>,
-	orgTreeData: [] as Array<SysOrg>,
+	orgTreeData: [] as Array<OrgOutput>,
 	queryParams: {
 		orgId: -1,
 		account: undefined,
@@ -178,7 +168,7 @@ onMounted(async () => {
 // 查询机构数据
 const loadOrgData = async () => {
 	state.loading = true;
-	let res = await getAPI(SysOrgApi).apiSysOrgListGet(0);
+	let res = await getAPI(SysOrgApi).apiSysOrgTreeGet(0);
 	state.orgTreeData = res.data.result ?? [];
 	state.loading = false;
 };

+ 4 - 4
Web/src/views/system/userRegWay/component/editRegWay.vue

@@ -73,8 +73,8 @@
 <script lang="ts" setup name="sysEditTenant">
 import { onMounted, reactive, ref } from 'vue';
 import { getAPI } from '/@/utils/axios-utils';
-import {SysOrgApi, SysPosApi, SysRoleApi, SysUserRegWayApi} from '/@/api-services/api';
-import {AccountTypeEnum, RoleOutput, SysOrg, SysPos, UpdateUserRegWayInput} from '/@/api-services/models';
+import { SysOrgApi, SysPosApi, SysRoleApi, SysUserRegWayApi } from '/@/api-services/api';
+import { OrgTreeOutput, RoleOutput, SysPos, UpdateUserRegWayInput } from '/@/api-services/models';
 
 const props = defineProps({
 	title: String,
@@ -87,7 +87,7 @@ const state = reactive({
 	isShowDialog: false,
 	file: undefined as any,
 	ruleForm: {} as UpdateUserRegWayInput,
-	orgData: [] as Array<SysOrg>,
+	orgData: [] as Array<OrgTreeOutput>,
 	posData: [] as Array<SysPos>, // 职位数据
 	roleData: [] as Array<RoleOutput>, // 角色数据
 });
@@ -96,7 +96,7 @@ onMounted(async () => {
 	state.loading = true;
 	state.posData = await getAPI(SysPosApi).apiSysPosListGet().then(res => res.data.result ?? []);
 	state.roleData = await getAPI(SysRoleApi).apiSysRoleListGet().then(res => res.data.result ?? []);
-	state.orgData = await getAPI(SysOrgApi).apiSysOrgListGet(0).then(res => res.data.result ?? []);
+	state.orgData = await getAPI(SysOrgApi).apiSysOrgTreeGet(0).then(res => res.data.result ?? []);
 	state.loading = false;
 });
 

+ 3 - 3
一键净化项目.bat

@@ -1,11 +1,11 @@
 @echo OFF
  :begin
- REM 删除前端文件及文件夹
+ REM 鍒犻櫎鍓嶇�鏂囦欢鍙婃枃浠跺す
  DEL /f /s /q ".\Web\node_modules\*.*"
  RD /s /q ".\Web\node_modules"
- REM 循环删除指定文件夹下的文件夹
+ REM 寰�幆鍒犻櫎鎸囧畾鏂囦欢澶逛笅鐨勬枃浠跺す
  FOR /d /r ".\Admin.NET\" %%b in (bin,obj,public) do rd /s /q "%%b"
- ECHO 【处理完毕,按任意键退出】
+ ECHO 銆愬�鐞嗗畬姣曪紝鎸変换鎰忛敭閫€鍑恒€�
  PAUSE>NUL
  EXIT
  GOTO BEGIN