移动系统liao
2025-06-20 9d2a0d8e8398ca94204bb191c99f6ad97de01a8c
增加客户相关表
9个文件已修改
7 文件已重命名
35个文件已添加
6523 ■■■■■ 已修改文件
Admin.NET/Admin.NET.Application/Admin.NET.Application.csproj 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/Admin.NET.Application/Configuration/CodeGen.json 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/Admin.NET.Application/Configuration/Swagger.json 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/Admin.NET.Application/Const/ApplicationConst.cs 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/Admin.NET.Web.Core/Admin.NET.Web.Core.csproj 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/Admin.NET.Web.Core/Handlers/JwtHandler.cs 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/Admin.NET.sln 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/FZCTB.NET.API.Application/FZCTB.NET.API.Application.csproj 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/FZCZTB.NET.MD/CutomerMd/FBS_Customer.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/FZCZTB.NET.MD/CutomerMd/FBS_CustomerRole.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/FZCZTB.NET.MD/CutomerMd/FBS_ExRole.cs 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/FZCZTB.NET.MD/CutomerMd/FBS_ExRoleMenu.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/FZCZTB.NET.MD/CutomerMd/FBS_Menu.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/FZCZTB.NET.MD/CutomerMd/FBS_Role.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/FZCZTB.NET.MD/CutomerMd/FBS_RoleMenu.cs 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/FZCZTB.NET.SYSService/CustomerSYS/CustomerManager.cs 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/FZCZTB.NET.SYSService/FZCZTB.NET.SYSService.csproj 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/FZCZTB.Net.CustomerSYSTem/CustomerSYSTemConst.cs 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/FZCZTB.Net.CustomerSYSTem/FZCZTB.Net.CustomerSYSTem.csproj 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/FZCZTB.Net.CustomerSYSTem/Service/FBS_Customer/Dto/FBS_CustomerDto.cs 241 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/FZCZTB.Net.CustomerSYSTem/Service/FBS_Customer/Dto/FBS_CustomerInput.cs 875 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/FZCZTB.Net.CustomerSYSTem/Service/FBS_Customer/Dto/FBS_CustomerOutput.cs 250 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/FZCZTB.Net.CustomerSYSTem/Service/FBS_Customer/FBS_CustomerService.cs 280 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/FZCZTB.Net.CustomerSYSTem/Service/FBS_ExRole/Dto/FBS_ExRoleDto.cs 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/FZCZTB.Net.CustomerSYSTem/Service/FBS_ExRole/Dto/FBS_ExRoleInput.cs 278 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/FZCZTB.Net.CustomerSYSTem/Service/FBS_ExRole/Dto/FBS_ExRoleOutput.cs 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/FZCZTB.Net.CustomerSYSTem/Service/FBS_ExRole/FBS_ExRoleService.cs 223 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/FZCZTB.Net.CustomerSYSTem/Service/FBS_Menu/Dto/FBS_MenuDto.cs 141 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/FZCZTB.Net.CustomerSYSTem/Service/FBS_Menu/Dto/FBS_MenuInput.cs 602 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/FZCZTB.Net.CustomerSYSTem/Service/FBS_Menu/Dto/FBS_MenuOutput.cs 150 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/FZCZTB.Net.CustomerSYSTem/Service/FBS_Menu/FBS_MenuService.cs 261 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/FZCZTB.Net.CustomerSYSTem/Service/FBS_Role/Dto/FBS_RoleDto.cs 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/FZCZTB.Net.CustomerSYSTem/Service/FBS_Role/Dto/FBS_RoleInput.cs 266 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/FZCZTB.Net.CustomerSYSTem/Service/FBS_Role/Dto/FBS_RoleOutput.cs 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/FZCZTB.Net.CustomerSYSTem/Service/FBS_Role/FBS_RoleService.cs 209 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/FZCZTB.TSCL.Application/Service/ADPenalty/ADPenaltyService.cs 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/FZCZTB.TSCL.Application/Service/ADPenalty/Dto/ADPenaltyInput.cs 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Web/src/api/Customer/fBS_Customer.ts 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Web/src/api/Customer/fBS_ExRole.ts 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Web/src/api/Customer/fBS_Menu.ts 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Web/src/api/Customer/fBS_Role.ts 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Web/src/api/Customer/fB_Customer.ts 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Web/src/api/Customer/fB_CustomerRole.ts 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Web/src/views/Customer/fBS_Customer/component/editDialog.vue 240 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Web/src/views/Customer/fBS_Customer/index.vue 310 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Web/src/views/Customer/fBS_ExRole/component/editDialog.vue 125 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Web/src/views/Customer/fBS_ExRole/index.vue 225 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Web/src/views/Customer/fBS_Menu/component/editDialog.vue 185 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Web/src/views/Customer/fBS_Menu/index.vue 311 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Web/src/views/Customer/fBS_Role/component/editDialog.vue 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Web/src/views/Customer/fBS_Role/index.vue 225 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/Admin.NET.Application/Admin.NET.Application.csproj
@@ -31,4 +31,8 @@
    <ProjectReference Include="..\Plugins\Admin.NET.Plugin.GoView\Admin.NET.Plugin.GoView.csproj" />
  </ItemGroup>
  <ItemGroup>
    <Folder Include="Service\" />
  </ItemGroup>
</Project>
Admin.NET/Admin.NET.Application/Configuration/CodeGen.json
@@ -6,6 +6,6 @@
    "EntityAssemblyNames": [ "Admin.NET.Core", "Admin.NET.Application", "FZCZTB.NET.MD" ], // 实体所在程序集(自行添加新建程序集名称)
    "BaseEntityNames": [ "EntityBaseId", "EntityBase", "EntityBaseDel", "EntityBaseOrg", "EntityBaseOrgDel", "EntityBaseTenant", "EntityBaseTenantDel", "EntityBaseTenantId", "EntityBaseTenantOrg", "EntityBaseTenantOrgDel" ], // 实体基类名称
    "FrontRootPath": "Web", // 前端项目根目录
    "BackendApplicationNamespaces": [ "Admin.NET.Application", "FZCZTB.TSCL.Application" ] // 后端生成到的项目(自行添加新建命名空间)
    "BackendApplicationNamespaces": [ "Admin.NET.Application", "FZCZTB.TSCL.Application", "FZCZTB.Net.CustomerSYSTem" ] // 后端生成到的项目(自行添加新建命名空间)
  }
}
Admin.NET/Admin.NET.Application/Configuration/Swagger.json
@@ -24,6 +24,13 @@
        "Description": "非政府采购交易平台",
        "Version": "1.0.0",
        "Order": 10000
      },
      {
        "Group": "FZCCustomerGroupName",
        "Title": "前端客户和系统设置",
        "Description": "非政府采购交易平台",
        "Version": "1.0.0",
        "Order": 10000
      }
    ],
    "DefaultGroupName": "Default", // 默认分组名
Admin.NET/Admin.NET.Application/Const/ApplicationConst.cs
@@ -15,4 +15,5 @@
    /// API分组名称
    /// </summary>
    public const string GroupName = "FZCCGPT";
}
Admin.NET/Admin.NET.Web.Core/Admin.NET.Web.Core.csproj
@@ -16,6 +16,8 @@
  <ItemGroup>
    <ProjectReference Include="..\Admin.NET.Application\Admin.NET.Application.csproj" />
    <ProjectReference Include="..\FZCTB.NET.API.Application\FZCTB.NET.API.Application.csproj" />
    <ProjectReference Include="..\FZCZTB.Net.CustomerSYSTem\FZCZTB.Net.CustomerSYSTem.csproj" />
    <ProjectReference Include="..\FZCZTB.TSCL.Application\FZCZTB.TSCL.Application.csproj" />
  </ItemGroup>
Admin.NET/Admin.NET.Web.Core/Handlers/JwtHandler.cs
@@ -9,6 +9,7 @@
using Furion;
using Furion.Authorization;
using Furion.DataEncryption;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using System;
Admin.NET/Admin.NET.sln
@@ -36,6 +36,12 @@
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FZCZTB.NET.MD", "FZCZTB.NET.MD\FZCZTB.NET.MD.csproj", "{6D667B23-0499-4352-BCA6-C9F2E388710B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FZCZTB.Net.CustomerSYSTem", "FZCZTB.Net.CustomerSYSTem\FZCZTB.Net.CustomerSYSTem.csproj", "{72CBCF69-83C4-44DF-B066-7618D5672B03}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FZCTB.NET.API.Application", "FZCTB.NET.API.Application\FZCTB.NET.API.Application.csproj", "{D72E858B-FFBE-4055-8473-B4AAF6F18F30}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FZCZTB.NET.SYSService", "FZCZTB.NET.SYSService\FZCZTB.NET.SYSService.csproj", "{9E19230C-7A8F-4440-B5D9-27D0038C13F6}"
EndProject
Global
    GlobalSection(SolutionConfigurationPlatforms) = preSolution
        Debug|Any CPU = Debug|Any CPU
@@ -93,6 +99,18 @@
        {6D667B23-0499-4352-BCA6-C9F2E388710B}.Debug|Any CPU.Build.0 = Debug|Any CPU
        {6D667B23-0499-4352-BCA6-C9F2E388710B}.Release|Any CPU.ActiveCfg = Release|Any CPU
        {6D667B23-0499-4352-BCA6-C9F2E388710B}.Release|Any CPU.Build.0 = Release|Any CPU
        {72CBCF69-83C4-44DF-B066-7618D5672B03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
        {72CBCF69-83C4-44DF-B066-7618D5672B03}.Debug|Any CPU.Build.0 = Debug|Any CPU
        {72CBCF69-83C4-44DF-B066-7618D5672B03}.Release|Any CPU.ActiveCfg = Release|Any CPU
        {72CBCF69-83C4-44DF-B066-7618D5672B03}.Release|Any CPU.Build.0 = Release|Any CPU
        {D72E858B-FFBE-4055-8473-B4AAF6F18F30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
        {D72E858B-FFBE-4055-8473-B4AAF6F18F30}.Debug|Any CPU.Build.0 = Debug|Any CPU
        {D72E858B-FFBE-4055-8473-B4AAF6F18F30}.Release|Any CPU.ActiveCfg = Release|Any CPU
        {D72E858B-FFBE-4055-8473-B4AAF6F18F30}.Release|Any CPU.Build.0 = Release|Any CPU
        {9E19230C-7A8F-4440-B5D9-27D0038C13F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
        {9E19230C-7A8F-4440-B5D9-27D0038C13F6}.Debug|Any CPU.Build.0 = Debug|Any CPU
        {9E19230C-7A8F-4440-B5D9-27D0038C13F6}.Release|Any CPU.ActiveCfg = Release|Any CPU
        {9E19230C-7A8F-4440-B5D9-27D0038C13F6}.Release|Any CPU.Build.0 = Release|Any CPU
    EndGlobalSection
    GlobalSection(SolutionProperties) = preSolution
        HideSolutionNode = FALSE
Admin.NET/FZCTB.NET.API.Application/FZCTB.NET.API.Application.csproj
New file
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>
  <ItemGroup>
    <ProjectReference Include="..\Admin.NET.Application\Admin.NET.Application.csproj" />
    <ProjectReference Include="..\Admin.NET.Core\Admin.NET.Core.csproj" />
    <ProjectReference Include="..\FZCZTB.NET.MD\FZCZTB.NET.MD.csproj" />
  </ItemGroup>
</Project>
Admin.NET/FZCZTB.NET.MD/CutomerMd/FBS_Customer.cs
File was renamed from Admin.NET/FZCZTB.NET.MD/CutomerMd/FB_Customer.cs
@@ -18,11 +18,11 @@
/// <summary>
/// 客户表
/// </summary>
[SugarTable("FB_Customer", "客户表")]
[SugarTable("FBS_Customer", "客户表")]
[SugarIndex("index_{table}_A", nameof(Account), OrderByType.Asc)]
[SugarIndex("index_{table}_P", nameof(Phone), OrderByType.Asc)]
public partial class FB_Customer : EntityBaseTenant
public partial class FBS_Customer : EntityBaseTenant
{
    /// <summary>
    /// 账号
Admin.NET/FZCZTB.NET.MD/CutomerMd/FBS_CustomerRole.cs
File was renamed from Admin.NET/FZCZTB.NET.MD/CutomerMd/FB_CustomerRole.cs
@@ -13,9 +13,9 @@
using System.Threading.Tasks;
namespace FZCZTB.NET.MD.CutomerMd;
[SugarTable("FB_CustomerRole", "客户菜单表")]
[SugarTable("FBS_CustomerRole", "客户菜单表")]
public class FB_CustomerRole : EntityBaseId
public class FBS_CustomerRole : EntityBaseId
{
    /// <summary>
    /// 用户Id
Admin.NET/FZCZTB.NET.MD/CutomerMd/FBS_ExRole.cs
File was renamed from Admin.NET/FZCZTB.NET.MD/CutomerMd/FB_ExRole.cs
@@ -18,11 +18,11 @@
/// 登录即要选择的校色
/// </summary>
[SugarTable("FB_TenantMenu", "客户主分类角色")]
[SugarTable("FBS_TenantMenu", "客户主分类角色")]
[SugarIndex("index_{table}_N", nameof(Name), OrderByType.Asc)]
[SugarIndex("index_{table}_C", nameof(Code), OrderByType.Asc)]
[IncreTable]
public class FB_ExRole: EntityBaseTenantId
public class FBS_ExRole: EntityBaseTenant
{
    /// <summary>
    /// 名称
Admin.NET/FZCZTB.NET.MD/CutomerMd/FBS_ExRoleMenu.cs
File was renamed from Admin.NET/FZCZTB.NET.MD/CutomerMd/FB_ExRoleMenu.cs
@@ -16,9 +16,9 @@
/// <summary>
/// 系统租户菜单表
/// </summary>
[SugarTable("FB_TenantMenu", "系统租户菜单表")]
[SugarTable("FBS_TenantMenu", "系统租户菜单表")]
class FB_ExRoleMenu: EntityBaseId
class FBS_ExRoleMenu: EntityBaseId
{
    /// <summary>
    /// 租户Id
Admin.NET/FZCZTB.NET.MD/CutomerMd/FBS_Menu.cs
File was renamed from Admin.NET/FZCZTB.NET.MD/CutomerMd/FB_Menu.cs
@@ -17,11 +17,11 @@
/// <summary>
/// 
/// </summary>
[SugarTable("FB_Menu", "客户系统菜单表")]
[SugarTable("FBS_Menu", "客户系统菜单表")]
[SugarIndex("index_{table}_T", nameof(Title), OrderByType.Asc)]
[SugarIndex("index_{table}_T2", nameof(Type), OrderByType.Asc)]
public class FB_Menu: EntityBaseTenantId
public class FBS_Menu: EntityBaseTenant
{
    /// <summary>
    /// 父Id
Admin.NET/FZCZTB.NET.MD/CutomerMd/FBS_Role.cs
File was renamed from Admin.NET/FZCZTB.NET.MD/CutomerMd/FB_Role.cs
@@ -16,11 +16,11 @@
namespace FZCZTB.NET.MD.CutomerMd;
[SugarTable("FB_Role", "客户个性化角色")]
[SugarTable("FBS_Role", "客户个性化角色")]
[SugarIndex("index_{table}_N", nameof(Name), OrderByType.Asc)]
[SugarIndex("index_{table}_C", nameof(Code), OrderByType.Asc)]
public class FB_Role : EntityBaseTenant
public class FBS_Role : EntityBaseTenant
{
    /// <summary>
    /// 名称
Admin.NET/FZCZTB.NET.MD/CutomerMd/FBS_RoleMenu.cs
File was renamed from Admin.NET/FZCZTB.NET.MD/CutomerMd/FB_RoleMenu.cs
@@ -13,9 +13,9 @@
using System.Threading.Tasks;
namespace FZCZTB.NET.MD.CutomerMd;
[IncreTable]
[SugarTable("FB_Role", "个性化校色菜单")]
public class FB_RoleMenu: EntityBaseId
[SugarTable("FBS_Role", "个性化校色菜单")]
public class FBS_RoleMenu: EntityBaseId
{
    /// <summary>
Admin.NET/FZCZTB.NET.SYSService/CustomerSYS/CustomerManager.cs
New file
@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FZCZTB.NET.SYSService.CustomerSYS
{
    public class CustomerManager
    {
    }
}
Admin.NET/FZCZTB.NET.SYSService/FZCZTB.NET.SYSService.csproj
New file
@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>
  <ItemGroup>
    <ProjectReference Include="..\Admin.NET.Core\Admin.NET.Core.csproj" />
  </ItemGroup>
</Project>
Admin.NET/FZCZTB.Net.CustomerSYSTem/CustomerSYSTemConst.cs
New file
@@ -0,0 +1,17 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FZCZTB.Net.CustomerSYSTem;
public class CustomerSYSTemConst
{
    public const string GroupName = "FZCCustomerGroupName";
}
Admin.NET/FZCZTB.Net.CustomerSYSTem/FZCZTB.Net.CustomerSYSTem.csproj
New file
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>
  <ItemGroup>
    <ProjectReference Include="..\Admin.NET.Application\Admin.NET.Application.csproj" />
    <ProjectReference Include="..\Admin.NET.Core\Admin.NET.Core.csproj" />
    <ProjectReference Include="..\FZCZTB.NET.MD\FZCZTB.NET.MD.csproj" />
  </ItemGroup>
</Project>
Admin.NET/FZCZTB.Net.CustomerSYSTem/Service/FBS_Customer/Dto/FBS_CustomerDto.cs
New file
@@ -0,0 +1,241 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using Admin.NET.Core;
namespace FZCZTB.Net.CustomerSYSTem.Service.FBS_Customer.Dto;
/// <summary>
/// 客户表输出参数
/// </summary>
public class FBS_CustomerDto
{
    /// <summary>
    /// 主键Id
    /// </summary>
    public long Id { get; set; }
    /// <summary>
    /// 账号
    /// </summary>
    public string Account { get; set; }
    /// <summary>
    /// 密码
    /// </summary>
    public string Password { get; set; }
    /// <summary>
    /// 真实姓名
    /// </summary>
    public string RealName { get; set; }
    /// <summary>
    /// 昵称
    /// </summary>
    public string? NickName { get; set; }
    /// <summary>
    /// 头像
    /// </summary>
    public string? Avatar { get; set; }
    /// <summary>
    /// 性别
    /// </summary>
    public GenderEnum Sex { get; set; }
    /// <summary>
    /// 年龄
    /// </summary>
    public int Age { get; set; }
    /// <summary>
    /// 出生日期
    /// </summary>
    public DateTime? Birthday { get; set; }
    /// <summary>
    /// 民族
    /// </summary>
    public string? Nation { get; set; }
    /// <summary>
    /// 手机号码
    /// </summary>
    public string? Phone { get; set; }
    /// <summary>
    /// 证件类型
    /// </summary>
    public CardTypeEnum CardType { get; set; }
    /// <summary>
    /// 身份证号
    /// </summary>
    public string? IdCardNum { get; set; }
    /// <summary>
    /// 身份证
    /// </summary>
    public string? IdCardPath { get; set; }
    /// <summary>
    /// 邮箱
    /// </summary>
    public string? Email { get; set; }
    /// <summary>
    /// 地址
    /// </summary>
    public string? Address { get; set; }
    /// <summary>
    /// 文化程度
    /// </summary>
    public CultureLevelEnum CultureLevel { get; set; }
    /// <summary>
    /// 政治面貌
    /// </summary>
    public string? PoliticalOutlook { get; set; }
    /// <summary>
    /// 毕业院校
    /// </summary>
    public string? College { get; set; }
    /// <summary>
    /// 办公电话
    /// </summary>
    public string? OfficePhone { get; set; }
    /// <summary>
    /// 紧急联系人
    /// </summary>
    public string? EmergencyContact { get; set; }
    /// <summary>
    /// 紧急联系人电话
    /// </summary>
    public string? EmergencyPhone { get; set; }
    /// <summary>
    /// 紧急联系人地址
    /// </summary>
    public string? EmergencyAddress { get; set; }
    /// <summary>
    /// 个人简介
    /// </summary>
    public string? Introduction { get; set; }
    /// <summary>
    /// 排序
    /// </summary>
    public int OrderNo { get; set; }
    /// <summary>
    /// 状态
    /// </summary>
    public StatusEnum Status { get; set; }
    /// <summary>
    /// 备注
    /// </summary>
    public string? Remark { get; set; }
    /// <summary>
    /// 职级
    /// </summary>
    public string? PosLevel { get; set; }
    /// <summary>
    /// 职称
    /// </summary>
    public string? PosTitle { get; set; }
    /// <summary>
    /// 擅长领域
    /// </summary>
    public string? Expertise { get; set; }
    /// <summary>
    /// 办公区域
    /// </summary>
    public string? OfficeZone { get; set; }
    /// <summary>
    /// 办公室
    /// </summary>
    public string? Office { get; set; }
    /// <summary>
    /// 入职日期
    /// </summary>
    public DateTime? JoinDate { get; set; }
    /// <summary>
    /// 最新登录Ip
    /// </summary>
    public string? LastLoginIp { get; set; }
    /// <summary>
    /// 最新登录地点
    /// </summary>
    public string? LastLoginAddress { get; set; }
    /// <summary>
    /// 最新登录时间
    /// </summary>
    public DateTime? LastLoginTime { get; set; }
    /// <summary>
    /// 最新登录设备
    /// </summary>
    public string? LastLoginDevice { get; set; }
    /// <summary>
    /// 电子签名
    /// </summary>
    public string? Signature { get; set; }
    /// <summary>
    /// 租户Id
    /// </summary>
    public long? TenantId { get; set; }
    /// <summary>
    /// 创建时间
    /// </summary>
    public DateTime? CreateTime { get; set; }
    /// <summary>
    /// 更新时间
    /// </summary>
    public DateTime? UpdateTime { get; set; }
    /// <summary>
    /// 创建者Id
    /// </summary>
    public long? CreateUserId { get; set; }
    /// <summary>
    /// 创建者姓名
    /// </summary>
    public string? CreateUserName { get; set; }
    /// <summary>
    /// 修改者Id
    /// </summary>
    public long? UpdateUserId { get; set; }
    /// <summary>
    /// 修改者姓名
    /// </summary>
    public string? UpdateUserName { get; set; }
}
Admin.NET/FZCZTB.Net.CustomerSYSTem/Service/FBS_Customer/Dto/FBS_CustomerInput.cs
New file
@@ -0,0 +1,875 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using Admin.NET.Core;
using System.ComponentModel.DataAnnotations;
using Magicodes.ExporterAndImporter.Core;
using Magicodes.ExporterAndImporter.Excel;
namespace FZCZTB.Net.CustomerSYSTem.Service.FBS_Customer.Dto;
/// <summary>
/// 客户表基础输入参数
/// </summary>
public class FBS_CustomerBaseInput
{
    /// <summary>
    /// 主键Id
    /// </summary>
    public virtual long? Id { get; set; }
    /// <summary>
    /// 账号
    /// </summary>
    [Required(ErrorMessage = "账号不能为空")]
    public virtual string Account { get; set; }
    /// <summary>
    /// 密码
    /// </summary>
    [Required(ErrorMessage = "密码不能为空")]
    public virtual string Password { get; set; }
    /// <summary>
    /// 真实姓名
    /// </summary>
    [Required(ErrorMessage = "真实姓名不能为空")]
    public virtual string RealName { get; set; }
    /// <summary>
    /// 昵称
    /// </summary>
    public virtual string? NickName { get; set; }
    /// <summary>
    /// 头像
    /// </summary>
    public virtual string? Avatar { get; set; }
    /// <summary>
    /// 性别
    /// </summary>
    [Dict(nameof(GenderEnum), AllowNullValue = true)]
    [Required(ErrorMessage = "性别不能为空")]
    public virtual GenderEnum? Sex { get; set; }
    /// <summary>
    /// 年龄
    /// </summary>
    [Required(ErrorMessage = "年龄不能为空")]
    public virtual int? Age { get; set; }
    /// <summary>
    /// 出生日期
    /// </summary>
    public virtual DateTime? Birthday { get; set; }
    /// <summary>
    /// 民族
    /// </summary>
    public virtual string? Nation { get; set; }
    /// <summary>
    /// 手机号码
    /// </summary>
    public virtual string? Phone { get; set; }
    /// <summary>
    /// 证件类型
    /// </summary>
    [Dict(nameof(CardTypeEnum), AllowNullValue = true)]
    [Required(ErrorMessage = "证件类型不能为空")]
    public virtual CardTypeEnum? CardType { get; set; }
    /// <summary>
    /// 身份证号
    /// </summary>
    public virtual string? IdCardNum { get; set; }
    /// <summary>
    /// 身份证
    /// </summary>
    public virtual string? IdCardPath { get; set; }
    /// <summary>
    /// 邮箱
    /// </summary>
    public virtual string? Email { get; set; }
    /// <summary>
    /// 地址
    /// </summary>
    public virtual string? Address { get; set; }
    /// <summary>
    /// 文化程度
    /// </summary>
    [Dict(nameof(CultureLevelEnum), AllowNullValue = true)]
    [Required(ErrorMessage = "文化程度不能为空")]
    public virtual CultureLevelEnum? CultureLevel { get; set; }
    /// <summary>
    /// 政治面貌
    /// </summary>
    public virtual string? PoliticalOutlook { get; set; }
    /// <summary>
    /// 毕业院校
    /// </summary>
    public virtual string? College { get; set; }
    /// <summary>
    /// 办公电话
    /// </summary>
    public virtual string? OfficePhone { get; set; }
    /// <summary>
    /// 紧急联系人
    /// </summary>
    public virtual string? EmergencyContact { get; set; }
    /// <summary>
    /// 紧急联系人电话
    /// </summary>
    public virtual string? EmergencyPhone { get; set; }
    /// <summary>
    /// 紧急联系人地址
    /// </summary>
    public virtual string? EmergencyAddress { get; set; }
    /// <summary>
    /// 个人简介
    /// </summary>
    public virtual string? Introduction { get; set; }
    /// <summary>
    /// 排序
    /// </summary>
    [Required(ErrorMessage = "排序不能为空")]
    public virtual int? OrderNo { get; set; }
    /// <summary>
    /// 状态
    /// </summary>
    [Dict(nameof(StatusEnum), AllowNullValue = true)]
    [Required(ErrorMessage = "状态不能为空")]
    public virtual StatusEnum? Status { get; set; }
    /// <summary>
    /// 备注
    /// </summary>
    public virtual string? Remark { get; set; }
    /// <summary>
    /// 职级
    /// </summary>
    public virtual string? PosLevel { get; set; }
    /// <summary>
    /// 职称
    /// </summary>
    public virtual string? PosTitle { get; set; }
}
/// <summary>
/// 客户表分页查询输入参数
/// </summary>
public class PageFBS_CustomerInput : BasePageInput
{
    /// <summary>
    /// 账号
    /// </summary>
    public string Account { get; set; }
    /// <summary>
    /// 真实姓名
    /// </summary>
    public string RealName { get; set; }
    /// <summary>
    /// 昵称
    /// </summary>
    public string? NickName { get; set; }
    /// <summary>
    /// 证件类型
    /// </summary>
    [Dict(nameof(CardTypeEnum), AllowNullValue = true)]
    public CardTypeEnum? CardType { get; set; }
    /// <summary>
    /// 身份证
    /// </summary>
    public string? IdCardPath { get; set; }
    /// <summary>
    /// 文化程度
    /// </summary>
    [Dict(nameof(CultureLevelEnum), AllowNullValue = true)]
    public CultureLevelEnum? CultureLevel { get; set; }
    /// <summary>
    /// 毕业院校
    /// </summary>
    public string? College { get; set; }
    /// <summary>
    /// 办公电话
    /// </summary>
    public string? OfficePhone { get; set; }
    /// <summary>
    /// 紧急联系人
    /// </summary>
    public string? EmergencyContact { get; set; }
    /// <summary>
    /// 紧急联系人电话
    /// </summary>
    public string? EmergencyPhone { get; set; }
    /// <summary>
    /// 紧急联系人地址
    /// </summary>
    public string? EmergencyAddress { get; set; }
    /// <summary>
    /// 个人简介
    /// </summary>
    public string? Introduction { get; set; }
    /// <summary>
    /// 排序
    /// </summary>
    public int? OrderNo { get; set; }
    /// <summary>
    /// 状态
    /// </summary>
    [Dict(nameof(StatusEnum), AllowNullValue = true)]
    public StatusEnum? Status { get; set; }
    /// <summary>
    /// 备注
    /// </summary>
    public string? Remark { get; set; }
    /// <summary>
    /// 职级
    /// </summary>
    public string? PosLevel { get; set; }
    /// <summary>
    /// 职称
    /// </summary>
    public string? PosTitle { get; set; }
    /// <summary>
    /// 选中主键列表
    /// </summary>
    public List<long> SelectKeyList { get; set; }
}
/// <summary>
/// 客户表增加输入参数
/// </summary>
public class AddFBS_CustomerInput
{
    /// <summary>
    /// 账号
    /// </summary>
    [Required(ErrorMessage = "账号不能为空")]
    [MaxLength(32, ErrorMessage = "账号字符长度不能超过32")]
    public string Account { get; set; }
    /// <summary>
    /// 密码
    /// </summary>
    [Required(ErrorMessage = "密码不能为空")]
    [MaxLength(512, ErrorMessage = "密码字符长度不能超过512")]
    public string Password { get; set; }
    /// <summary>
    /// 真实姓名
    /// </summary>
    [Required(ErrorMessage = "真实姓名不能为空")]
    [MaxLength(32, ErrorMessage = "真实姓名字符长度不能超过32")]
    public string RealName { get; set; }
    /// <summary>
    /// 昵称
    /// </summary>
    [MaxLength(32, ErrorMessage = "昵称字符长度不能超过32")]
    public string? NickName { get; set; }
    /// <summary>
    /// 头像
    /// </summary>
    [MaxLength(512, ErrorMessage = "头像字符长度不能超过512")]
    public string? Avatar { get; set; }
    /// <summary>
    /// 性别
    /// </summary>
    [Dict(nameof(GenderEnum), AllowNullValue = true)]
    [Required(ErrorMessage = "性别不能为空")]
    public GenderEnum? Sex { get; set; }
    /// <summary>
    /// 年龄
    /// </summary>
    [Required(ErrorMessage = "年龄不能为空")]
    public int? Age { get; set; }
    /// <summary>
    /// 出生日期
    /// </summary>
    public DateTime? Birthday { get; set; }
    /// <summary>
    /// 民族
    /// </summary>
    [MaxLength(32, ErrorMessage = "民族字符长度不能超过32")]
    public string? Nation { get; set; }
    /// <summary>
    /// 手机号码
    /// </summary>
    [MaxLength(16, ErrorMessage = "手机号码字符长度不能超过16")]
    public string? Phone { get; set; }
    /// <summary>
    /// 证件类型
    /// </summary>
    [Dict(nameof(CardTypeEnum), AllowNullValue = true)]
    [Required(ErrorMessage = "证件类型不能为空")]
    public CardTypeEnum? CardType { get; set; }
    /// <summary>
    /// 身份证号
    /// </summary>
    [MaxLength(32, ErrorMessage = "身份证号字符长度不能超过32")]
    public string? IdCardNum { get; set; }
    /// <summary>
    /// 身份证
    /// </summary>
    [MaxLength(512, ErrorMessage = "身份证字符长度不能超过512")]
    public string? IdCardPath { get; set; }
    /// <summary>
    /// 邮箱
    /// </summary>
    [MaxLength(64, ErrorMessage = "邮箱字符长度不能超过64")]
    public string? Email { get; set; }
    /// <summary>
    /// 地址
    /// </summary>
    [MaxLength(256, ErrorMessage = "地址字符长度不能超过256")]
    public string? Address { get; set; }
    /// <summary>
    /// 文化程度
    /// </summary>
    [Dict(nameof(CultureLevelEnum), AllowNullValue = true)]
    [Required(ErrorMessage = "文化程度不能为空")]
    public CultureLevelEnum? CultureLevel { get; set; }
    /// <summary>
    /// 政治面貌
    /// </summary>
    [MaxLength(16, ErrorMessage = "政治面貌字符长度不能超过16")]
    public string? PoliticalOutlook { get; set; }
    /// <summary>
    /// 毕业院校
    /// </summary>
    [MaxLength(128, ErrorMessage = "毕业院校字符长度不能超过128")]
    public string? College { get; set; }
    /// <summary>
    /// 办公电话
    /// </summary>
    [MaxLength(16, ErrorMessage = "办公电话字符长度不能超过16")]
    public string? OfficePhone { get; set; }
    /// <summary>
    /// 紧急联系人
    /// </summary>
    [MaxLength(32, ErrorMessage = "紧急联系人字符长度不能超过32")]
    public string? EmergencyContact { get; set; }
    /// <summary>
    /// 紧急联系人电话
    /// </summary>
    [MaxLength(16, ErrorMessage = "紧急联系人电话字符长度不能超过16")]
    public string? EmergencyPhone { get; set; }
    /// <summary>
    /// 紧急联系人地址
    /// </summary>
    [MaxLength(256, ErrorMessage = "紧急联系人地址字符长度不能超过256")]
    public string? EmergencyAddress { get; set; }
    /// <summary>
    /// 个人简介
    /// </summary>
    [MaxLength(512, ErrorMessage = "个人简介字符长度不能超过512")]
    public string? Introduction { get; set; }
    /// <summary>
    /// 排序
    /// </summary>
    [Required(ErrorMessage = "排序不能为空")]
    public int? OrderNo { get; set; }
    /// <summary>
    /// 状态
    /// </summary>
    [Dict(nameof(StatusEnum), AllowNullValue = true)]
    [Required(ErrorMessage = "状态不能为空")]
    public StatusEnum? Status { get; set; }
    /// <summary>
    /// 备注
    /// </summary>
    [MaxLength(256, ErrorMessage = "备注字符长度不能超过256")]
    public string? Remark { get; set; }
    /// <summary>
    /// 职级
    /// </summary>
    [MaxLength(32, ErrorMessage = "职级字符长度不能超过32")]
    public string? PosLevel { get; set; }
    /// <summary>
    /// 职称
    /// </summary>
    [MaxLength(32, ErrorMessage = "职称字符长度不能超过32")]
    public string? PosTitle { get; set; }
}
/// <summary>
/// 客户表删除输入参数
/// </summary>
public class DeleteFBS_CustomerInput
{
    /// <summary>
    /// 主键Id
    /// </summary>
    [Required(ErrorMessage = "主键Id不能为空")]
    public long? Id { get; set; }
}
/// <summary>
/// 客户表更新输入参数
/// </summary>
public class UpdateFBS_CustomerInput
{
    /// <summary>
    /// 主键Id
    /// </summary>
    [Required(ErrorMessage = "主键Id不能为空")]
    public long? Id { get; set; }
    /// <summary>
    /// 账号
    /// </summary>
    [Required(ErrorMessage = "账号不能为空")]
    [MaxLength(32, ErrorMessage = "账号字符长度不能超过32")]
    public string Account { get; set; }
    /// <summary>
    /// 密码
    /// </summary>
    [Required(ErrorMessage = "密码不能为空")]
    [MaxLength(512, ErrorMessage = "密码字符长度不能超过512")]
    public string Password { get; set; }
    /// <summary>
    /// 真实姓名
    /// </summary>
    [Required(ErrorMessage = "真实姓名不能为空")]
    [MaxLength(32, ErrorMessage = "真实姓名字符长度不能超过32")]
    public string RealName { get; set; }
    /// <summary>
    /// 昵称
    /// </summary>
    [MaxLength(32, ErrorMessage = "昵称字符长度不能超过32")]
    public string? NickName { get; set; }
    /// <summary>
    /// 头像
    /// </summary>
    [MaxLength(512, ErrorMessage = "头像字符长度不能超过512")]
    public string? Avatar { get; set; }
    /// <summary>
    /// 性别
    /// </summary>
    [Dict(nameof(GenderEnum), AllowNullValue = true)]
    [Required(ErrorMessage = "性别不能为空")]
    public GenderEnum? Sex { get; set; }
    /// <summary>
    /// 年龄
    /// </summary>
    [Required(ErrorMessage = "年龄不能为空")]
    public int? Age { get; set; }
    /// <summary>
    /// 出生日期
    /// </summary>
    public DateTime? Birthday { get; set; }
    /// <summary>
    /// 民族
    /// </summary>
    [MaxLength(32, ErrorMessage = "民族字符长度不能超过32")]
    public string? Nation { get; set; }
    /// <summary>
    /// 手机号码
    /// </summary>
    [MaxLength(16, ErrorMessage = "手机号码字符长度不能超过16")]
    public string? Phone { get; set; }
    /// <summary>
    /// 证件类型
    /// </summary>
    [Dict(nameof(CardTypeEnum), AllowNullValue = true)]
    [Required(ErrorMessage = "证件类型不能为空")]
    public CardTypeEnum? CardType { get; set; }
    /// <summary>
    /// 身份证号
    /// </summary>
    [MaxLength(32, ErrorMessage = "身份证号字符长度不能超过32")]
    public string? IdCardNum { get; set; }
    /// <summary>
    /// 身份证
    /// </summary>
    [MaxLength(512, ErrorMessage = "身份证字符长度不能超过512")]
    public string? IdCardPath { get; set; }
    /// <summary>
    /// 邮箱
    /// </summary>
    [MaxLength(64, ErrorMessage = "邮箱字符长度不能超过64")]
    public string? Email { get; set; }
    /// <summary>
    /// 地址
    /// </summary>
    [MaxLength(256, ErrorMessage = "地址字符长度不能超过256")]
    public string? Address { get; set; }
    /// <summary>
    /// 文化程度
    /// </summary>
    [Dict(nameof(CultureLevelEnum), AllowNullValue = true)]
    [Required(ErrorMessage = "文化程度不能为空")]
    public CultureLevelEnum? CultureLevel { get; set; }
    /// <summary>
    /// 政治面貌
    /// </summary>
    [MaxLength(16, ErrorMessage = "政治面貌字符长度不能超过16")]
    public string? PoliticalOutlook { get; set; }
    /// <summary>
    /// 毕业院校
    /// </summary>
    [MaxLength(128, ErrorMessage = "毕业院校字符长度不能超过128")]
    public string? College { get; set; }
    /// <summary>
    /// 办公电话
    /// </summary>
    [MaxLength(16, ErrorMessage = "办公电话字符长度不能超过16")]
    public string? OfficePhone { get; set; }
    /// <summary>
    /// 紧急联系人
    /// </summary>
    [MaxLength(32, ErrorMessage = "紧急联系人字符长度不能超过32")]
    public string? EmergencyContact { get; set; }
    /// <summary>
    /// 紧急联系人电话
    /// </summary>
    [MaxLength(16, ErrorMessage = "紧急联系人电话字符长度不能超过16")]
    public string? EmergencyPhone { get; set; }
    /// <summary>
    /// 紧急联系人地址
    /// </summary>
    [MaxLength(256, ErrorMessage = "紧急联系人地址字符长度不能超过256")]
    public string? EmergencyAddress { get; set; }
    /// <summary>
    /// 个人简介
    /// </summary>
    [MaxLength(512, ErrorMessage = "个人简介字符长度不能超过512")]
    public string? Introduction { get; set; }
    /// <summary>
    /// 排序
    /// </summary>
    [Required(ErrorMessage = "排序不能为空")]
    public int? OrderNo { get; set; }
    /// <summary>
    /// 状态
    /// </summary>
    [Dict(nameof(StatusEnum), AllowNullValue = true)]
    [Required(ErrorMessage = "状态不能为空")]
    public StatusEnum? Status { get; set; }
    /// <summary>
    /// 备注
    /// </summary>
    [MaxLength(256, ErrorMessage = "备注字符长度不能超过256")]
    public string? Remark { get; set; }
    /// <summary>
    /// 职级
    /// </summary>
    [MaxLength(32, ErrorMessage = "职级字符长度不能超过32")]
    public string? PosLevel { get; set; }
    /// <summary>
    /// 职称
    /// </summary>
    [MaxLength(32, ErrorMessage = "职称字符长度不能超过32")]
    public string? PosTitle { get; set; }
}
/// <summary>
/// 客户表主键查询输入参数
/// </summary>
public class QueryByIdFBS_CustomerInput : DeleteFBS_CustomerInput
{
}
/// <summary>
/// 设置状态输入参数
/// </summary>
public class SetFBS_CustomerStatusInput : BaseStatusInput
{
}
/// <summary>
/// 客户表数据导入实体
/// </summary>
[ExcelImporter(SheetIndex = 1, IsOnlyErrorRows = true)]
public class ImportFBS_CustomerInput : BaseImportInput
{
    /// <summary>
    /// 账号
    /// </summary>
    [ImporterHeader(Name = "*账号")]
    [ExporterHeader("*账号", Format = "", Width = 25, IsBold = true)]
    public string Account { get; set; }
    /// <summary>
    /// 密码
    /// </summary>
    [ImporterHeader(Name = "*密码")]
    [ExporterHeader("*密码", Format = "", Width = 25, IsBold = true)]
    public string Password { get; set; }
    /// <summary>
    /// 真实姓名
    /// </summary>
    [ImporterHeader(Name = "*真实姓名")]
    [ExporterHeader("*真实姓名", Format = "", Width = 25, IsBold = true)]
    public string RealName { get; set; }
    /// <summary>
    /// 昵称
    /// </summary>
    [ImporterHeader(Name = "昵称")]
    [ExporterHeader("昵称", Format = "", Width = 25, IsBold = true)]
    public string? NickName { get; set; }
    /// <summary>
    /// 头像
    /// </summary>
    [ImporterHeader(Name = "头像")]
    [ExporterHeader("头像", Format = "", Width = 25, IsBold = true)]
    public string? Avatar { get; set; }
    /// <summary>
    /// 性别
    /// </summary>
    [ImporterHeader(Name = "*性别")]
    [ExporterHeader("*性别", Format = "", Width = 25, IsBold = true)]
    public GenderEnum? Sex { get; set; }
    /// <summary>
    /// 年龄
    /// </summary>
    [ImporterHeader(Name = "*年龄")]
    [ExporterHeader("*年龄", Format = "", Width = 25, IsBold = true)]
    public int? Age { get; set; }
    /// <summary>
    /// 出生日期
    /// </summary>
    [ImporterHeader(Name = "出生日期")]
    [ExporterHeader("出生日期", Format = "", Width = 25, IsBold = true)]
    public DateTime? Birthday { get; set; }
    /// <summary>
    /// 民族
    /// </summary>
    [ImporterHeader(Name = "民族")]
    [ExporterHeader("民族", Format = "", Width = 25, IsBold = true)]
    public string? Nation { get; set; }
    /// <summary>
    /// 手机号码
    /// </summary>
    [ImporterHeader(Name = "手机号码")]
    [ExporterHeader("手机号码", Format = "", Width = 25, IsBold = true)]
    public string? Phone { get; set; }
    /// <summary>
    /// 证件类型
    /// </summary>
    [ImporterHeader(Name = "*证件类型")]
    [ExporterHeader("*证件类型", Format = "", Width = 25, IsBold = true)]
    public CardTypeEnum? CardType { get; set; }
    /// <summary>
    /// 身份证号
    /// </summary>
    [ImporterHeader(Name = "身份证号")]
    [ExporterHeader("身份证号", Format = "", Width = 25, IsBold = true)]
    public string? IdCardNum { get; set; }
    /// <summary>
    /// 身份证
    /// </summary>
    [ImporterHeader(Name = "身份证")]
    [ExporterHeader("身份证", Format = "", Width = 25, IsBold = true)]
    public string? IdCardPath { get; set; }
    /// <summary>
    /// 邮箱
    /// </summary>
    [ImporterHeader(Name = "邮箱")]
    [ExporterHeader("邮箱", Format = "", Width = 25, IsBold = true)]
    public string? Email { get; set; }
    /// <summary>
    /// 地址
    /// </summary>
    [ImporterHeader(Name = "地址")]
    [ExporterHeader("地址", Format = "", Width = 25, IsBold = true)]
    public string? Address { get; set; }
    /// <summary>
    /// 文化程度
    /// </summary>
    [ImporterHeader(Name = "*文化程度")]
    [ExporterHeader("*文化程度", Format = "", Width = 25, IsBold = true)]
    public CultureLevelEnum? CultureLevel { get; set; }
    /// <summary>
    /// 政治面貌
    /// </summary>
    [ImporterHeader(Name = "政治面貌")]
    [ExporterHeader("政治面貌", Format = "", Width = 25, IsBold = true)]
    public string? PoliticalOutlook { get; set; }
    /// <summary>
    /// 毕业院校
    /// </summary>
    [ImporterHeader(Name = "毕业院校")]
    [ExporterHeader("毕业院校", Format = "", Width = 25, IsBold = true)]
    public string? College { get; set; }
    /// <summary>
    /// 办公电话
    /// </summary>
    [ImporterHeader(Name = "办公电话")]
    [ExporterHeader("办公电话", Format = "", Width = 25, IsBold = true)]
    public string? OfficePhone { get; set; }
    /// <summary>
    /// 紧急联系人
    /// </summary>
    [ImporterHeader(Name = "紧急联系人")]
    [ExporterHeader("紧急联系人", Format = "", Width = 25, IsBold = true)]
    public string? EmergencyContact { get; set; }
    /// <summary>
    /// 紧急联系人电话
    /// </summary>
    [ImporterHeader(Name = "紧急联系人电话")]
    [ExporterHeader("紧急联系人电话", Format = "", Width = 25, IsBold = true)]
    public string? EmergencyPhone { get; set; }
    /// <summary>
    /// 紧急联系人地址
    /// </summary>
    [ImporterHeader(Name = "紧急联系人地址")]
    [ExporterHeader("紧急联系人地址", Format = "", Width = 25, IsBold = true)]
    public string? EmergencyAddress { get; set; }
    /// <summary>
    /// 个人简介
    /// </summary>
    [ImporterHeader(Name = "个人简介")]
    [ExporterHeader("个人简介", Format = "", Width = 25, IsBold = true)]
    public string? Introduction { get; set; }
    /// <summary>
    /// 排序
    /// </summary>
    [ImporterHeader(Name = "*排序")]
    [ExporterHeader("*排序", Format = "", Width = 25, IsBold = true)]
    public int? OrderNo { get; set; }
    /// <summary>
    /// 状态
    /// </summary>
    [ImporterHeader(Name = "*状态")]
    [ExporterHeader("*状态", Format = "", Width = 25, IsBold = true)]
    public StatusEnum? Status { get; set; }
    /// <summary>
    /// 备注
    /// </summary>
    [ImporterHeader(Name = "备注")]
    [ExporterHeader("备注", Format = "", Width = 25, IsBold = true)]
    public string? Remark { get; set; }
    /// <summary>
    /// 职级
    /// </summary>
    [ImporterHeader(Name = "职级")]
    [ExporterHeader("职级", Format = "", Width = 25, IsBold = true)]
    public string? PosLevel { get; set; }
    /// <summary>
    /// 职称
    /// </summary>
    [ImporterHeader(Name = "职称")]
    [ExporterHeader("职称", Format = "", Width = 25, IsBold = true)]
    public string? PosTitle { get; set; }
}
Admin.NET/FZCZTB.Net.CustomerSYSTem/Service/FBS_Customer/Dto/FBS_CustomerOutput.cs
New file
@@ -0,0 +1,250 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using Admin.NET.Core;
using Magicodes.ExporterAndImporter.Core;
namespace FZCZTB.Net.CustomerSYSTem.Service.FBS_Customer.Dto;
/// <summary>
/// 客户表输出参数
/// </summary>
public class FBS_CustomerOutput
{
    /// <summary>
    /// 主键Id
    /// </summary>
    public long Id { get; set; }
    /// <summary>
    /// 账号
    /// </summary>
    public string Account { get; set; }
    /// <summary>
    /// 密码
    /// </summary>
    public string Password { get; set; }
    /// <summary>
    /// 真实姓名
    /// </summary>
    public string RealName { get; set; }
    /// <summary>
    /// 昵称
    /// </summary>
    public string? NickName { get; set; }
    /// <summary>
    /// 头像
    /// </summary>
    public string? Avatar { get; set; }
    /// <summary>
    /// 性别
    /// </summary>
    public GenderEnum Sex { get; set; }
    /// <summary>
    /// 年龄
    /// </summary>
    public int Age { get; set; }
    /// <summary>
    /// 出生日期
    /// </summary>
    public DateTime? Birthday { get; set; }
    /// <summary>
    /// 民族
    /// </summary>
    public string? Nation { get; set; }
    /// <summary>
    /// 手机号码
    /// </summary>
    public string? Phone { get; set; }
    /// <summary>
    /// 证件类型
    /// </summary>
    public CardTypeEnum CardType { get; set; }
    /// <summary>
    /// 身份证号
    /// </summary>
    public string? IdCardNum { get; set; }
    /// <summary>
    /// 身份证
    /// </summary>
    public string? IdCardPath { get; set; }
    /// <summary>
    /// 邮箱
    /// </summary>
    public string? Email { get; set; }
    /// <summary>
    /// 地址
    /// </summary>
    public string? Address { get; set; }
    /// <summary>
    /// 文化程度
    /// </summary>
    public CultureLevelEnum CultureLevel { get; set; }
    /// <summary>
    /// 政治面貌
    /// </summary>
    public string? PoliticalOutlook { get; set; }
    /// <summary>
    /// 毕业院校
    /// </summary>
    public string? College { get; set; }
    /// <summary>
    /// 办公电话
    /// </summary>
    public string? OfficePhone { get; set; }
    /// <summary>
    /// 紧急联系人
    /// </summary>
    public string? EmergencyContact { get; set; }
    /// <summary>
    /// 紧急联系人电话
    /// </summary>
    public string? EmergencyPhone { get; set; }
    /// <summary>
    /// 紧急联系人地址
    /// </summary>
    public string? EmergencyAddress { get; set; }
    /// <summary>
    /// 个人简介
    /// </summary>
    public string? Introduction { get; set; }
    /// <summary>
    /// 排序
    /// </summary>
    public int OrderNo { get; set; }
    /// <summary>
    /// 状态
    /// </summary>
    public StatusEnum Status { get; set; }
    /// <summary>
    /// 备注
    /// </summary>
    public string? Remark { get; set; }
    /// <summary>
    /// 职级
    /// </summary>
    public string? PosLevel { get; set; }
    /// <summary>
    /// 职称
    /// </summary>
    public string? PosTitle { get; set; }
    /// <summary>
    /// 擅长领域
    /// </summary>
    public string? Expertise { get; set; }
    /// <summary>
    /// 办公区域
    /// </summary>
    public string? OfficeZone { get; set; }
    /// <summary>
    /// 办公室
    /// </summary>
    public string? Office { get; set; }
    /// <summary>
    /// 入职日期
    /// </summary>
    public DateTime? JoinDate { get; set; }
    /// <summary>
    /// 最新登录Ip
    /// </summary>
    public string? LastLoginIp { get; set; }
    /// <summary>
    /// 最新登录地点
    /// </summary>
    public string? LastLoginAddress { get; set; }
    /// <summary>
    /// 最新登录时间
    /// </summary>
    public DateTime? LastLoginTime { get; set; }
    /// <summary>
    /// 最新登录设备
    /// </summary>
    public string? LastLoginDevice { get; set; }
    /// <summary>
    /// 电子签名
    /// </summary>
    public string? Signature { get; set; }
    /// <summary>
    /// 租户Id
    /// </summary>
    public long? TenantId { get; set; }
    /// <summary>
    /// 创建时间
    /// </summary>
    public DateTime? CreateTime { get; set; }
    /// <summary>
    /// 更新时间
    /// </summary>
    public DateTime? UpdateTime { get; set; }
    /// <summary>
    /// 创建者Id
    /// </summary>
    public long? CreateUserId { get; set; }
    /// <summary>
    /// 创建者姓名
    /// </summary>
    public string? CreateUserName { get; set; }
    /// <summary>
    /// 修改者Id
    /// </summary>
    public long? UpdateUserId { get; set; }
    /// <summary>
    /// 修改者姓名
    /// </summary>
    public string? UpdateUserName { get; set; }
}
/// <summary>
/// 客户表数据导入模板实体
/// </summary>
public class ExportFBS_CustomerOutput : ImportFBS_CustomerInput
{
    [ImporterHeader(IsIgnore = true)]
    [ExporterHeader(IsIgnore = true)]
    public override string Error { get; set; }
}
Admin.NET/FZCZTB.Net.CustomerSYSTem/Service/FBS_Customer/FBS_CustomerService.cs
New file
@@ -0,0 +1,280 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using Admin.NET.Core.Service;
using Microsoft.AspNetCore.Http;
using Furion.DatabaseAccessor;
using Furion.FriendlyException;
using Mapster;
using SqlSugar;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Mvc;
using Furion.DynamicApiController;
using Admin.NET.Core;
using FZCZTB.NET.MD.CutomerMd;
using Furion.DependencyInjection;
using FZCZTB.Net.CustomerSYSTem.Service.FBS_Customer.Dto;
namespace FZCZTB.Net.CustomerSYSTem;
/// <summary>
/// 客户表服务 🧩
/// </summary>
[ApiDescriptionSettings(CustomerSYSTemConst.GroupName, Order = 100)]
public class FBS_CustomerService : IDynamicApiController, ITransient
{
    private readonly SqlSugarRepository<FBS_Customer> _fBS_CustomerRep;
    private readonly ISqlSugarClient _sqlSugarClient;
    public FBS_CustomerService(SqlSugarRepository<FBS_Customer> fBS_CustomerRep, ISqlSugarClient sqlSugarClient)
    {
        _fBS_CustomerRep = fBS_CustomerRep;
        _sqlSugarClient = sqlSugarClient;
    }
    /// <summary>
    /// 分页查询客户表 🔖
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("分页查询客户表")]
    [ApiDescriptionSettings(Name = "Page"), HttpPost]
    public async Task<SqlSugarPagedList<FBS_CustomerOutput>> Page(PageFBS_CustomerInput input)
    {
        input.Keyword = input.Keyword?.Trim();
        var query = _fBS_CustomerRep.AsQueryable()
            .WhereIF(!string.IsNullOrWhiteSpace(input.Keyword), u => u.Account.Contains(input.Keyword) || u.RealName.Contains(input.Keyword) || u.NickName.Contains(input.Keyword) || u.IdCardPath.Contains(input.Keyword) || u.College.Contains(input.Keyword) || u.OfficePhone.Contains(input.Keyword) || u.EmergencyContact.Contains(input.Keyword) || u.EmergencyPhone.Contains(input.Keyword) || u.EmergencyAddress.Contains(input.Keyword) || u.Introduction.Contains(input.Keyword) || u.Remark.Contains(input.Keyword) || u.PosLevel.Contains(input.Keyword) || u.PosTitle.Contains(input.Keyword))
            .WhereIF(!string.IsNullOrWhiteSpace(input.Account), u => u.Account.Contains(input.Account.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.RealName), u => u.RealName.Contains(input.RealName.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.NickName), u => u.NickName.Contains(input.NickName.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.IdCardPath), u => u.IdCardPath.Contains(input.IdCardPath.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.College), u => u.College.Contains(input.College.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.OfficePhone), u => u.OfficePhone.Contains(input.OfficePhone.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.EmergencyContact), u => u.EmergencyContact.Contains(input.EmergencyContact.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.EmergencyPhone), u => u.EmergencyPhone.Contains(input.EmergencyPhone.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.EmergencyAddress), u => u.EmergencyAddress.Contains(input.EmergencyAddress.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.Introduction), u => u.Introduction.Contains(input.Introduction.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.Remark), u => u.Remark.Contains(input.Remark.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.PosLevel), u => u.PosLevel.Contains(input.PosLevel.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.PosTitle), u => u.PosTitle.Contains(input.PosTitle.Trim()))
            .WhereIF(input.CardType.HasValue, u => u.CardType == input.CardType)
            .WhereIF(input.CultureLevel.HasValue, u => u.CultureLevel == input.CultureLevel)
            .WhereIF(input.OrderNo != null, u => u.OrderNo == input.OrderNo)
            .WhereIF(input.Status.HasValue, u => u.Status == input.Status)
            .Select<FBS_CustomerOutput>();
        return await query.OrderBuilder(input).ToPagedListAsync(input.Page, input.PageSize);
    }
    /// <summary>
    /// 获取客户表详情 ℹ️
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("获取客户表详情")]
    [ApiDescriptionSettings(Name = "Detail"), HttpGet]
    public async Task<FBS_Customer> Detail([FromQuery] QueryByIdFBS_CustomerInput input)
    {
        return await _fBS_CustomerRep.GetFirstAsync(u => u.Id == input.Id);
    }
    /// <summary>
    /// 增加客户表 ➕
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("增加客户表")]
    [ApiDescriptionSettings(Name = "Add"), HttpPost]
    public async Task<long> Add(AddFBS_CustomerInput input)
    {
        var entity = input.Adapt<FBS_Customer>();
        return await _fBS_CustomerRep.InsertAsync(entity) ? entity.Id : 0;
    }
    /// <summary>
    /// 更新客户表 ✏️
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("更新客户表")]
    [ApiDescriptionSettings(Name = "Update"), HttpPost]
    public async Task Update(UpdateFBS_CustomerInput input)
    {
        var entity = input.Adapt<FBS_Customer>();
        await _fBS_CustomerRep.AsUpdateable(entity)
        .IgnoreColumns(u => new {
            u.Expertise,
            u.OfficeZone,
            u.Office,
            u.JoinDate,
            u.LastLoginIp,
            u.LastLoginAddress,
            u.LastLoginTime,
            u.LastLoginDevice,
            u.Signature,
        })
        .ExecuteCommandAsync();
    }
    /// <summary>
    /// 删除客户表 ❌
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("删除客户表")]
    [ApiDescriptionSettings(Name = "Delete"), HttpPost]
    public async Task Delete(DeleteFBS_CustomerInput input)
    {
        var entity = await _fBS_CustomerRep.GetFirstAsync(u => u.Id == input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D1002);
       // await _fBS_CustomerRep.FakeDeleteAsync(entity);   //假删除
        await _fBS_CustomerRep.DeleteAsync(entity);   //真删除
    }
    /// <summary>
    /// 批量删除客户表 ❌
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("批量删除客户表")]
    [ApiDescriptionSettings(Name = "BatchDelete"), HttpPost]
    public async Task<bool> BatchDelete([Required(ErrorMessage = "主键列表不能为空")]List<DeleteFBS_CustomerInput> input)
    {
        var exp = Expressionable.Create<FBS_Customer>();
        foreach (var row in input) exp = exp.Or(it => it.Id == row.Id);
        var list = await _fBS_CustomerRep.AsQueryable().Where(exp.ToExpression()).ToListAsync();
       // return await _fBS_CustomerRep.FakeDeleteAsync(list);   //假删除
        return await _fBS_CustomerRep.DeleteAsync(list);   //真删除
    }
    /// <summary>
    /// 设置客户表状态 🚫
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("设置客户表状态")]
    [ApiDescriptionSettings(Name = "SetStatus"), HttpPost]
    public async Task SetFBS_CustomerStatus(SetFBS_CustomerStatusInput input)
    {
        await _fBS_CustomerRep.AsUpdateable().SetColumns(u => u.Status, input.Status).Where(u => u.Id == input.Id).ExecuteCommandAsync();
    }
    /// <summary>
    /// 导出客户表记录 🔖
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("导出客户表记录")]
    [ApiDescriptionSettings(Name = "Export"), HttpPost, NonUnify]
    public async Task<IActionResult> Export(PageFBS_CustomerInput input)
    {
        var list = (await Page(input)).Items?.Adapt<List<ExportFBS_CustomerOutput>>() ?? new();
        if (input.SelectKeyList?.Count > 0) list = list.Where(x => input.SelectKeyList.Contains(x.Id)).ToList();
        return ExcelHelper.ExportTemplate(list, "客户表导出记录");
    }
    /// <summary>
    /// 下载客户表数据导入模板 ⬇️
    /// </summary>
    /// <returns></returns>
    [DisplayName("下载客户表数据导入模板")]
    [ApiDescriptionSettings(Name = "Import"), HttpGet, NonUnify]
    public IActionResult DownloadTemplate()
    {
        return ExcelHelper.ExportTemplate(new List<ExportFBS_CustomerOutput>(), "客户表导入模板");
    }
    private static readonly object _fBS_CustomerImportLock = new object();
    /// <summary>
    /// 导入客户表记录 💾
    /// </summary>
    /// <returns></returns>
    [DisplayName("导入客户表记录")]
    [ApiDescriptionSettings(Name = "Import"), HttpPost, NonUnify, UnitOfWork]
    public IActionResult ImportData([Required] IFormFile file)
    {
        lock (_fBS_CustomerImportLock)
        {
            var stream = ExcelHelper.ImportData<ImportFBS_CustomerInput, FBS_Customer>(file, (list, markerErrorAction) =>
            {
                _sqlSugarClient.Utilities.PageEach(list, 2048, pageItems =>
                {
                    // 校验并过滤必填基本类型为null的字段
                    var rows = pageItems.Where(x => {
                        if (!string.IsNullOrWhiteSpace(x.Error)) return false;
                        if (x.Sex == null){
                            x.Error = "性别不能为空";
                            return false;
                        }
                        if (!string.IsNullOrWhiteSpace(x.Error)) return false;
                        if (x.Age == null){
                            x.Error = "年龄不能为空";
                            return false;
                        }
                        if (!string.IsNullOrWhiteSpace(x.Error)) return false;
                        if (x.CardType == null){
                            x.Error = "证件类型不能为空";
                            return false;
                        }
                        if (!string.IsNullOrWhiteSpace(x.Error)) return false;
                        if (x.CultureLevel == null){
                            x.Error = "文化程度不能为空";
                            return false;
                        }
                        if (!string.IsNullOrWhiteSpace(x.Error)) return false;
                        if (x.OrderNo == null){
                            x.Error = "排序不能为空";
                            return false;
                        }
                        if (!string.IsNullOrWhiteSpace(x.Error)) return false;
                        if (x.Status == null){
                            x.Error = "状态不能为空";
                            return false;
                        }
                        return true;
                    }).Adapt<List<FBS_Customer>>();
                    var storageable = _fBS_CustomerRep.Context.Storageable(rows)
                        .SplitError(it => string.IsNullOrWhiteSpace(it.Item.Account), "账号不能为空")
                        .SplitError(it => it.Item.Account?.Length > 32, "账号长度不能超过32个字符")
                        .SplitError(it => string.IsNullOrWhiteSpace(it.Item.Password), "密码不能为空")
                        .SplitError(it => it.Item.Password?.Length > 512, "密码长度不能超过512个字符")
                        .SplitError(it => string.IsNullOrWhiteSpace(it.Item.RealName), "真实姓名不能为空")
                        .SplitError(it => it.Item.RealName?.Length > 32, "真实姓名长度不能超过32个字符")
                        .SplitError(it => it.Item.NickName?.Length > 32, "昵称长度不能超过32个字符")
                        .SplitError(it => it.Item.Avatar?.Length > 512, "头像长度不能超过512个字符")
                        .SplitError(it => it.Item.Nation?.Length > 32, "民族长度不能超过32个字符")
                        .SplitError(it => it.Item.Phone?.Length > 16, "手机号码长度不能超过16个字符")
                        .SplitError(it => it.Item.IdCardNum?.Length > 32, "身份证号长度不能超过32个字符")
                        .SplitError(it => it.Item.IdCardPath?.Length > 512, "身份证长度不能超过512个字符")
                        .SplitError(it => it.Item.Email?.Length > 64, "邮箱长度不能超过64个字符")
                        .SplitError(it => it.Item.Address?.Length > 256, "地址长度不能超过256个字符")
                        .SplitError(it => it.Item.PoliticalOutlook?.Length > 16, "政治面貌长度不能超过16个字符")
                        .SplitError(it => it.Item.College?.Length > 128, "毕业院校长度不能超过128个字符")
                        .SplitError(it => it.Item.OfficePhone?.Length > 16, "办公电话长度不能超过16个字符")
                        .SplitError(it => it.Item.EmergencyContact?.Length > 32, "紧急联系人长度不能超过32个字符")
                        .SplitError(it => it.Item.EmergencyPhone?.Length > 16, "紧急联系人电话长度不能超过16个字符")
                        .SplitError(it => it.Item.EmergencyAddress?.Length > 256, "紧急联系人地址长度不能超过256个字符")
                        .SplitError(it => it.Item.Introduction?.Length > 512, "个人简介长度不能超过512个字符")
                        .SplitError(it => it.Item.Remark?.Length > 256, "备注长度不能超过256个字符")
                        .SplitError(it => it.Item.PosLevel?.Length > 32, "职级长度不能超过32个字符")
                        .SplitError(it => it.Item.PosTitle?.Length > 32, "职称长度不能超过32个字符")
                        .SplitInsert(_ => true)
                        .ToStorage();
                    storageable.AsInsertable.ExecuteCommand();// 不存在插入
                    storageable.AsUpdateable.ExecuteCommand();// 存在更新
                    // 标记错误信息
                    markerErrorAction.Invoke(storageable, pageItems, rows);
                });
            });
            return stream;
        }
    }
}
Admin.NET/FZCZTB.Net.CustomerSYSTem/Service/FBS_ExRole/Dto/FBS_ExRoleDto.cs
New file
@@ -0,0 +1,86 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using Admin.NET.Core;
namespace FZCZTB.Net.CustomerSYSTem.Service.FBS_ExRole.Dto;
/// <summary>
/// 客户主分类角色输出参数
/// </summary>
public class FBS_ExRoleDto
{
    /// <summary>
    /// 主键Id
    /// </summary>
    public long Id { get; set; }
    /// <summary>
    /// 名称
    /// </summary>
    public string Name { get; set; }
    /// <summary>
    /// 编码
    /// </summary>
    public string? Code { get; set; }
    /// <summary>
    /// 排序
    /// </summary>
    public int OrderNo { get; set; }
    /// <summary>
    /// 数据范围
    /// </summary>
    public DataScopeEnum DataScope { get; set; }
    /// <summary>
    /// 备注
    /// </summary>
    public string? Remark { get; set; }
    /// <summary>
    /// 状态
    /// </summary>
    public StatusEnum Status { get; set; }
    /// <summary>
    /// 租户Id
    /// </summary>
    public long? TenantId { get; set; }
    /// <summary>
    /// 创建时间
    /// </summary>
    public DateTime? CreateTime { get; set; }
    /// <summary>
    /// 更新时间
    /// </summary>
    public DateTime? UpdateTime { get; set; }
    /// <summary>
    /// 创建者Id
    /// </summary>
    public long? CreateUserId { get; set; }
    /// <summary>
    /// 创建者姓名
    /// </summary>
    public string? CreateUserName { get; set; }
    /// <summary>
    /// 修改者Id
    /// </summary>
    public long? UpdateUserId { get; set; }
    /// <summary>
    /// 修改者姓名
    /// </summary>
    public string? UpdateUserName { get; set; }
}
Admin.NET/FZCZTB.Net.CustomerSYSTem/Service/FBS_ExRole/Dto/FBS_ExRoleInput.cs
New file
@@ -0,0 +1,278 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using Admin.NET.Core;
using System.ComponentModel.DataAnnotations;
using Magicodes.ExporterAndImporter.Core;
using Magicodes.ExporterAndImporter.Excel;
namespace FZCZTB.Net.CustomerSYSTem.Service.FBS_ExRole.Dto;
/// <summary>
/// 客户主分类角色基础输入参数
/// </summary>
public class FBS_ExRoleBaseInput
{
    /// <summary>
    /// 主键Id
    /// </summary>
    public virtual long? Id { get; set; }
    /// <summary>
    /// 名称
    /// </summary>
    [Required(ErrorMessage = "名称不能为空")]
    public virtual string Name { get; set; }
    /// <summary>
    /// 编码
    /// </summary>
    public virtual string? Code { get; set; }
    /// <summary>
    /// 排序
    /// </summary>
    [Required(ErrorMessage = "排序不能为空")]
    public virtual int? OrderNo { get; set; }
    /// <summary>
    /// 数据范围
    /// </summary>
    [Dict(nameof(DataScopeEnum), AllowNullValue = true)]
    [Required(ErrorMessage = "数据范围不能为空")]
    public virtual DataScopeEnum? DataScope { get; set; }
    /// <summary>
    /// 备注
    /// </summary>
    public virtual string? Remark { get; set; }
    /// <summary>
    /// 状态
    /// </summary>
    [Dict(nameof(StatusEnum), AllowNullValue = true)]
    [Required(ErrorMessage = "状态不能为空")]
    public virtual StatusEnum? Status { get; set; }
}
/// <summary>
/// 客户主分类角色分页查询输入参数
/// </summary>
public class PageFBS_ExRoleInput : BasePageInput
{
    /// <summary>
    /// 名称
    /// </summary>
    public string Name { get; set; }
    /// <summary>
    /// 编码
    /// </summary>
    public string? Code { get; set; }
    /// <summary>
    /// 排序
    /// </summary>
    public int? OrderNo { get; set; }
    /// <summary>
    /// 数据范围
    /// </summary>
    [Dict(nameof(DataScopeEnum), AllowNullValue = true)]
    public DataScopeEnum? DataScope { get; set; }
    /// <summary>
    /// 备注
    /// </summary>
    public string? Remark { get; set; }
    /// <summary>
    /// 状态
    /// </summary>
    [Dict(nameof(StatusEnum), AllowNullValue = true)]
    public StatusEnum? Status { get; set; }
    /// <summary>
    /// 选中主键列表
    /// </summary>
    public List<long> SelectKeyList { get; set; }
}
/// <summary>
/// 客户主分类角色增加输入参数
/// </summary>
public class AddFBS_ExRoleInput
{
    /// <summary>
    /// 名称
    /// </summary>
    [Required(ErrorMessage = "名称不能为空")]
    [MaxLength(64, ErrorMessage = "名称字符长度不能超过64")]
    public string Name { get; set; }
    /// <summary>
    /// 编码
    /// </summary>
    [MaxLength(64, ErrorMessage = "编码字符长度不能超过64")]
    public string? Code { get; set; }
    /// <summary>
    /// 排序
    /// </summary>
    [Required(ErrorMessage = "排序不能为空")]
    public int? OrderNo { get; set; }
    /// <summary>
    /// 数据范围
    /// </summary>
    [Dict(nameof(DataScopeEnum), AllowNullValue = true)]
    [Required(ErrorMessage = "数据范围不能为空")]
    public DataScopeEnum? DataScope { get; set; }
    /// <summary>
    /// 备注
    /// </summary>
    [MaxLength(128, ErrorMessage = "备注字符长度不能超过128")]
    public string? Remark { get; set; }
    /// <summary>
    /// 状态
    /// </summary>
    [Dict(nameof(StatusEnum), AllowNullValue = true)]
    [Required(ErrorMessage = "状态不能为空")]
    public StatusEnum? Status { get; set; }
}
/// <summary>
/// 客户主分类角色删除输入参数
/// </summary>
public class DeleteFBS_ExRoleInput
{
    /// <summary>
    /// 主键Id
    /// </summary>
    [Required(ErrorMessage = "主键Id不能为空")]
    public long? Id { get; set; }
}
/// <summary>
/// 客户主分类角色更新输入参数
/// </summary>
public class UpdateFBS_ExRoleInput
{
    /// <summary>
    /// 主键Id
    /// </summary>
    [Required(ErrorMessage = "主键Id不能为空")]
    public long? Id { get; set; }
    /// <summary>
    /// 名称
    /// </summary>
    [Required(ErrorMessage = "名称不能为空")]
    [MaxLength(64, ErrorMessage = "名称字符长度不能超过64")]
    public string Name { get; set; }
    /// <summary>
    /// 编码
    /// </summary>
    [MaxLength(64, ErrorMessage = "编码字符长度不能超过64")]
    public string? Code { get; set; }
    /// <summary>
    /// 排序
    /// </summary>
    [Required(ErrorMessage = "排序不能为空")]
    public int? OrderNo { get; set; }
    /// <summary>
    /// 数据范围
    /// </summary>
    [Dict(nameof(DataScopeEnum), AllowNullValue = true)]
    [Required(ErrorMessage = "数据范围不能为空")]
    public DataScopeEnum? DataScope { get; set; }
    /// <summary>
    /// 备注
    /// </summary>
    [MaxLength(128, ErrorMessage = "备注字符长度不能超过128")]
    public string? Remark { get; set; }
    /// <summary>
    /// 状态
    /// </summary>
    [Dict(nameof(StatusEnum), AllowNullValue = true)]
    [Required(ErrorMessage = "状态不能为空")]
    public StatusEnum? Status { get; set; }
}
/// <summary>
/// 客户主分类角色主键查询输入参数
/// </summary>
public class QueryByIdFBS_ExRoleInput : DeleteFBS_ExRoleInput
{
}
/// <summary>
/// 设置状态输入参数
/// </summary>
public class SetFBS_ExRoleStatusInput : BaseStatusInput
{
}
/// <summary>
/// 客户主分类角色数据导入实体
/// </summary>
[ExcelImporter(SheetIndex = 1, IsOnlyErrorRows = true)]
public class ImportFBS_ExRoleInput : BaseImportInput
{
    /// <summary>
    /// 名称
    /// </summary>
    [ImporterHeader(Name = "*名称")]
    [ExporterHeader("*名称", Format = "", Width = 25, IsBold = true)]
    public string Name { get; set; }
    /// <summary>
    /// 编码
    /// </summary>
    [ImporterHeader(Name = "编码")]
    [ExporterHeader("编码", Format = "", Width = 25, IsBold = true)]
    public string? Code { get; set; }
    /// <summary>
    /// 排序
    /// </summary>
    [ImporterHeader(Name = "*排序")]
    [ExporterHeader("*排序", Format = "", Width = 25, IsBold = true)]
    public int? OrderNo { get; set; }
    /// <summary>
    /// 数据范围
    /// </summary>
    [ImporterHeader(Name = "*数据范围")]
    [ExporterHeader("*数据范围", Format = "", Width = 25, IsBold = true)]
    public DataScopeEnum? DataScope { get; set; }
    /// <summary>
    /// 备注
    /// </summary>
    [ImporterHeader(Name = "备注")]
    [ExporterHeader("备注", Format = "", Width = 25, IsBold = true)]
    public string? Remark { get; set; }
    /// <summary>
    /// 状态
    /// </summary>
    [ImporterHeader(Name = "*状态")]
    [ExporterHeader("*状态", Format = "", Width = 25, IsBold = true)]
    public StatusEnum? Status { get; set; }
}
Admin.NET/FZCZTB.Net.CustomerSYSTem/Service/FBS_ExRole/Dto/FBS_ExRoleOutput.cs
New file
@@ -0,0 +1,95 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using Admin.NET.Core;
using Magicodes.ExporterAndImporter.Core;
namespace FZCZTB.Net.CustomerSYSTem.Service.FBS_ExRole.Dto;
/// <summary>
/// 客户主分类角色输出参数
/// </summary>
public class FBS_ExRoleOutput
{
    /// <summary>
    /// 主键Id
    /// </summary>
    public long Id { get; set; }
    /// <summary>
    /// 名称
    /// </summary>
    public string Name { get; set; }
    /// <summary>
    /// 编码
    /// </summary>
    public string? Code { get; set; }
    /// <summary>
    /// 排序
    /// </summary>
    public int OrderNo { get; set; }
    /// <summary>
    /// 数据范围
    /// </summary>
    public DataScopeEnum DataScope { get; set; }
    /// <summary>
    /// 备注
    /// </summary>
    public string? Remark { get; set; }
    /// <summary>
    /// 状态
    /// </summary>
    public StatusEnum Status { get; set; }
    /// <summary>
    /// 租户Id
    /// </summary>
    public long? TenantId { get; set; }
    /// <summary>
    /// 创建时间
    /// </summary>
    public DateTime? CreateTime { get; set; }
    /// <summary>
    /// 更新时间
    /// </summary>
    public DateTime? UpdateTime { get; set; }
    /// <summary>
    /// 创建者Id
    /// </summary>
    public long? CreateUserId { get; set; }
    /// <summary>
    /// 创建者姓名
    /// </summary>
    public string? CreateUserName { get; set; }
    /// <summary>
    /// 修改者Id
    /// </summary>
    public long? UpdateUserId { get; set; }
    /// <summary>
    /// 修改者姓名
    /// </summary>
    public string? UpdateUserName { get; set; }
}
/// <summary>
/// 客户主分类角色数据导入模板实体
/// </summary>
public class ExportFBS_ExRoleOutput : ImportFBS_ExRoleInput
{
    [ImporterHeader(IsIgnore = true)]
    [ExporterHeader(IsIgnore = true)]
    public override string Error { get; set; }
}
Admin.NET/FZCZTB.Net.CustomerSYSTem/Service/FBS_ExRole/FBS_ExRoleService.cs
New file
@@ -0,0 +1,223 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using Admin.NET.Core.Service;
using Microsoft.AspNetCore.Http;
using Furion.DatabaseAccessor;
using Furion.FriendlyException;
using Mapster;
using SqlSugar;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Mvc;
using Furion.DynamicApiController;
using Furion.DependencyInjection;
using Admin.NET.Core;
using FZCZTB.NET.MD.CutomerMd;
using FZCZTB.Net.CustomerSYSTem.Service.FBS_ExRole.Dto;
namespace FZCZTB.Net.CustomerSYSTem;
/// <summary>
/// 客户主分类角色服务 🧩
/// </summary>
[ApiDescriptionSettings(CustomerSYSTemConst.GroupName, Order = 100)]
public class FBS_ExRoleService : IDynamicApiController, ITransient
{
    private readonly SqlSugarRepository<FBS_ExRole> _fBS_ExRoleRep;
    private readonly ISqlSugarClient _sqlSugarClient;
    public FBS_ExRoleService(SqlSugarRepository<FBS_ExRole> fBS_ExRoleRep, ISqlSugarClient sqlSugarClient)
    {
        _fBS_ExRoleRep = fBS_ExRoleRep;
        _sqlSugarClient = sqlSugarClient;
    }
    /// <summary>
    /// 分页查询客户主分类角色 🔖
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("分页查询客户主分类角色")]
    [ApiDescriptionSettings(Name = "Page"), HttpPost]
    public async Task<SqlSugarPagedList<FBS_ExRoleOutput>> Page(PageFBS_ExRoleInput input)
    {
        input.Keyword = input.Keyword?.Trim();
        var query = _fBS_ExRoleRep.AsQueryable()
            .WhereIF(!string.IsNullOrWhiteSpace(input.Keyword), u => u.Name.Contains(input.Keyword) || u.Code.Contains(input.Keyword) || u.Remark.Contains(input.Keyword))
            .WhereIF(!string.IsNullOrWhiteSpace(input.Name), u => u.Name.Contains(input.Name.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.Code), u => u.Code.Contains(input.Code.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.Remark), u => u.Remark.Contains(input.Remark.Trim()))
            .WhereIF(input.OrderNo != null, u => u.OrderNo == input.OrderNo)
            .WhereIF(input.DataScope.HasValue, u => u.DataScope == input.DataScope)
            .WhereIF(input.Status.HasValue, u => u.Status == input.Status)
            .Select<FBS_ExRoleOutput>();
        return await query.OrderBuilder(input).ToPagedListAsync(input.Page, input.PageSize);
    }
    /// <summary>
    /// 获取客户主分类角色详情 ℹ️
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("获取客户主分类角色详情")]
    [ApiDescriptionSettings(Name = "Detail"), HttpGet]
    public async Task<FBS_ExRole> Detail([FromQuery] QueryByIdFBS_ExRoleInput input)
    {
        return await _fBS_ExRoleRep.GetFirstAsync(u => u.Id == input.Id);
    }
    /// <summary>
    /// 增加客户主分类角色 ➕
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("增加客户主分类角色")]
    [ApiDescriptionSettings(Name = "Add"), HttpPost]
    public async Task<long> Add(AddFBS_ExRoleInput input)
    {
        var entity = input.Adapt<FBS_ExRole>();
        return await _fBS_ExRoleRep.InsertAsync(entity) ? entity.Id : 0;
    }
    /// <summary>
    /// 更新客户主分类角色 ✏️
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("更新客户主分类角色")]
    [ApiDescriptionSettings(Name = "Update"), HttpPost]
    public async Task Update(UpdateFBS_ExRoleInput input)
    {
        var entity = input.Adapt<FBS_ExRole>();
        await _fBS_ExRoleRep.AsUpdateable(entity)
        .ExecuteCommandAsync();
    }
    /// <summary>
    /// 删除客户主分类角色 ❌
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("删除客户主分类角色")]
    [ApiDescriptionSettings(Name = "Delete"), HttpPost]
    public async Task Delete(DeleteFBS_ExRoleInput input)
    {
        var entity = await _fBS_ExRoleRep.GetFirstAsync(u => u.Id == input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D1002);
       // await _fBS_ExRoleRep.FakeDeleteAsync(entity);   //假删除
        await _fBS_ExRoleRep.DeleteAsync(entity);   //真删除
    }
    /// <summary>
    /// 批量删除客户主分类角色 ❌
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("批量删除客户主分类角色")]
    [ApiDescriptionSettings(Name = "BatchDelete"), HttpPost]
    public async Task<bool> BatchDelete([Required(ErrorMessage = "主键列表不能为空")]List<DeleteFBS_ExRoleInput> input)
    {
        var exp = Expressionable.Create<FBS_ExRole>();
        foreach (var row in input) exp = exp.Or(it => it.Id == row.Id);
        var list = await _fBS_ExRoleRep.AsQueryable().Where(exp.ToExpression()).ToListAsync();
      //  return await _fBS_ExRoleRep.FakeDeleteAsync(list);   //假删除
        return await _fBS_ExRoleRep.DeleteAsync(list);   //真删除
    }
    /// <summary>
    /// 设置客户主分类角色状态 🚫
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("设置客户主分类角色状态")]
    [ApiDescriptionSettings(Name = "SetStatus"), HttpPost]
    public async Task SetFBS_ExRoleStatus(SetFBS_ExRoleStatusInput input)
    {
        await _fBS_ExRoleRep.AsUpdateable().SetColumns(u => u.Status, input.Status).Where(u => u.Id == input.Id).ExecuteCommandAsync();
    }
    /// <summary>
    /// 导出客户主分类角色记录 🔖
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("导出客户主分类角色记录")]
    [ApiDescriptionSettings(Name = "Export"), HttpPost, NonUnify]
    public async Task<IActionResult> Export(PageFBS_ExRoleInput input)
    {
        var list = (await Page(input)).Items?.Adapt<List<ExportFBS_ExRoleOutput>>() ?? new();
        if (input.SelectKeyList?.Count > 0) list = list.Where(x => input.SelectKeyList.Contains(x.Id)).ToList();
        return ExcelHelper.ExportTemplate(list, "客户主分类角色导出记录");
    }
    /// <summary>
    /// 下载客户主分类角色数据导入模板 ⬇️
    /// </summary>
    /// <returns></returns>
    [DisplayName("下载客户主分类角色数据导入模板")]
    [ApiDescriptionSettings(Name = "Import"), HttpGet, NonUnify]
    public IActionResult DownloadTemplate()
    {
        return ExcelHelper.ExportTemplate(new List<ExportFBS_ExRoleOutput>(), "客户主分类角色导入模板");
    }
    private static readonly object _fBS_ExRoleImportLock = new object();
    /// <summary>
    /// 导入客户主分类角色记录 💾
    /// </summary>
    /// <returns></returns>
    [DisplayName("导入客户主分类角色记录")]
    [ApiDescriptionSettings(Name = "Import"), HttpPost, NonUnify, UnitOfWork]
    public IActionResult ImportData([Required] IFormFile file)
    {
        lock (_fBS_ExRoleImportLock)
        {
            var stream = ExcelHelper.ImportData<ImportFBS_ExRoleInput, FBS_ExRole>(file, (list, markerErrorAction) =>
            {
                _sqlSugarClient.Utilities.PageEach(list, 2048, pageItems =>
                {
                    // 校验并过滤必填基本类型为null的字段
                    var rows = pageItems.Where(x => {
                        if (!string.IsNullOrWhiteSpace(x.Error)) return false;
                        if (x.OrderNo == null){
                            x.Error = "排序不能为空";
                            return false;
                        }
                        if (!string.IsNullOrWhiteSpace(x.Error)) return false;
                        if (x.DataScope == null){
                            x.Error = "数据范围不能为空";
                            return false;
                        }
                        if (!string.IsNullOrWhiteSpace(x.Error)) return false;
                        if (x.Status == null){
                            x.Error = "状态不能为空";
                            return false;
                        }
                        return true;
                    }).Adapt<List<FBS_ExRole>>();
                    var storageable = _fBS_ExRoleRep.Context.Storageable(rows)
                        .SplitError(it => string.IsNullOrWhiteSpace(it.Item.Name), "名称不能为空")
                        .SplitError(it => it.Item.Name?.Length > 64, "名称长度不能超过64个字符")
                        .SplitError(it => it.Item.Code?.Length > 64, "编码长度不能超过64个字符")
                        .SplitError(it => it.Item.Remark?.Length > 128, "备注长度不能超过128个字符")
                        .SplitInsert(_ => true)
                        .ToStorage();
                    storageable.AsInsertable.ExecuteCommand();// 不存在插入
                    storageable.AsUpdateable.ExecuteCommand();// 存在更新
                    // 标记错误信息
                    markerErrorAction.Invoke(storageable, pageItems, rows);
                });
            });
            return stream;
        }
    }
}
Admin.NET/FZCZTB.Net.CustomerSYSTem/Service/FBS_Menu/Dto/FBS_MenuDto.cs
New file
@@ -0,0 +1,141 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using Admin.NET.Core;
namespace FZCZTB.Net.CustomerSYSTem.Service.FBS_Menu.Dto;
/// <summary>
/// 客户系统菜单表输出参数
/// </summary>
public class FBS_MenuDto
{
    /// <summary>
    /// 主键Id
    /// </summary>
    public long Id { get; set; }
    /// <summary>
    /// 父Id
    /// </summary>
    public long Pid { get; set; }
    /// <summary>
    /// 菜单类型
    /// </summary>
    public MenuTypeEnum Type { get; set; }
    /// <summary>
    /// 路由名称
    /// </summary>
    public string? Name { get; set; }
    /// <summary>
    /// 路由地址
    /// </summary>
    public string? Path { get; set; }
    /// <summary>
    /// 组件路径
    /// </summary>
    public string? Component { get; set; }
    /// <summary>
    /// 重定向
    /// </summary>
    public string? Redirect { get; set; }
    /// <summary>
    /// 权限标识
    /// </summary>
    public string? Permission { get; set; }
    /// <summary>
    /// 菜单名称
    /// </summary>
    public string Title { get; set; }
    /// <summary>
    /// 图标
    /// </summary>
    public string? Icon { get; set; }
    /// <summary>
    /// 是否内嵌
    /// </summary>
    public bool IsIframe { get; set; }
    /// <summary>
    /// 外链链接
    /// </summary>
    public string? OutLink { get; set; }
    /// <summary>
    /// 是否隐藏
    /// </summary>
    public bool IsHide { get; set; }
    /// <summary>
    /// 是否缓存
    /// </summary>
    public bool IsKeepAlive { get; set; }
    /// <summary>
    /// 是否固定
    /// </summary>
    public bool IsAffix { get; set; }
    /// <summary>
    /// 排序
    /// </summary>
    public int OrderNo { get; set; }
    /// <summary>
    /// 状态
    /// </summary>
    public StatusEnum Status { get; set; }
    /// <summary>
    /// 备注
    /// </summary>
    public string? Remark { get; set; }
    /// <summary>
    /// 租户Id
    /// </summary>
    public long? TenantId { get; set; }
    /// <summary>
    /// 创建时间
    /// </summary>
    public DateTime? CreateTime { get; set; }
    /// <summary>
    /// 更新时间
    /// </summary>
    public DateTime? UpdateTime { get; set; }
    /// <summary>
    /// 创建者Id
    /// </summary>
    public long? CreateUserId { get; set; }
    /// <summary>
    /// 创建者姓名
    /// </summary>
    public string? CreateUserName { get; set; }
    /// <summary>
    /// 修改者Id
    /// </summary>
    public long? UpdateUserId { get; set; }
    /// <summary>
    /// 修改者姓名
    /// </summary>
    public string? UpdateUserName { get; set; }
}
Admin.NET/FZCZTB.Net.CustomerSYSTem/Service/FBS_Menu/Dto/FBS_MenuInput.cs
New file
@@ -0,0 +1,602 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using Admin.NET.Core;
using System.ComponentModel.DataAnnotations;
using Magicodes.ExporterAndImporter.Core;
using Magicodes.ExporterAndImporter.Excel;
namespace FZCZTB.Net.CustomerSYSTem.Service.FBS_Menu.Dto;
/// <summary>
/// 客户系统菜单表基础输入参数
/// </summary>
public class FBS_MenuBaseInput
{
    /// <summary>
    /// 主键Id
    /// </summary>
    public virtual long? Id { get; set; }
    /// <summary>
    /// 父Id
    /// </summary>
    [Required(ErrorMessage = "父Id不能为空")]
    public virtual long? Pid { get; set; }
    /// <summary>
    /// 菜单类型
    /// </summary>
    [Dict(nameof(MenuTypeEnum), AllowNullValue = true)]
    [Required(ErrorMessage = "菜单类型不能为空")]
    public virtual MenuTypeEnum? Type { get; set; }
    /// <summary>
    /// 路由名称
    /// </summary>
    public virtual string? Name { get; set; }
    /// <summary>
    /// 路由地址
    /// </summary>
    public virtual string? Path { get; set; }
    /// <summary>
    /// 组件路径
    /// </summary>
    public virtual string? Component { get; set; }
    /// <summary>
    /// 重定向
    /// </summary>
    public virtual string? Redirect { get; set; }
    /// <summary>
    /// 权限标识
    /// </summary>
    public virtual string? Permission { get; set; }
    /// <summary>
    /// 菜单名称
    /// </summary>
    [Required(ErrorMessage = "菜单名称不能为空")]
    public virtual string Title { get; set; }
    /// <summary>
    /// 图标
    /// </summary>
    public virtual string? Icon { get; set; }
    /// <summary>
    /// 是否内嵌
    /// </summary>
    [Required(ErrorMessage = "是否内嵌不能为空")]
    public virtual bool? IsIframe { get; set; }
    /// <summary>
    /// 外链链接
    /// </summary>
    public virtual string? OutLink { get; set; }
    /// <summary>
    /// 是否隐藏
    /// </summary>
    [Required(ErrorMessage = "是否隐藏不能为空")]
    public virtual bool? IsHide { get; set; }
    /// <summary>
    /// 是否缓存
    /// </summary>
    [Required(ErrorMessage = "是否缓存不能为空")]
    public virtual bool? IsKeepAlive { get; set; }
    /// <summary>
    /// 是否固定
    /// </summary>
    [Required(ErrorMessage = "是否固定不能为空")]
    public virtual bool? IsAffix { get; set; }
    /// <summary>
    /// 排序
    /// </summary>
    [Required(ErrorMessage = "排序不能为空")]
    public virtual int? OrderNo { get; set; }
    /// <summary>
    /// 状态
    /// </summary>
    [Dict(nameof(StatusEnum), AllowNullValue = true)]
    [Required(ErrorMessage = "状态不能为空")]
    public virtual StatusEnum? Status { get; set; }
    /// <summary>
    /// 备注
    /// </summary>
    public virtual string? Remark { get; set; }
}
/// <summary>
/// 客户系统菜单表分页查询输入参数
/// </summary>
public class PageFBS_MenuInput : BasePageInput
{
    /// <summary>
    /// 父Id
    /// </summary>
    public long? Pid { get; set; }
    /// <summary>
    /// 菜单类型
    /// </summary>
    [Dict(nameof(MenuTypeEnum), AllowNullValue = true)]
    public MenuTypeEnum? Type { get; set; }
    /// <summary>
    /// 路由名称
    /// </summary>
    public string? Name { get; set; }
    /// <summary>
    /// 路由地址
    /// </summary>
    public string? Path { get; set; }
    /// <summary>
    /// 组件路径
    /// </summary>
    public string? Component { get; set; }
    /// <summary>
    /// 重定向
    /// </summary>
    public string? Redirect { get; set; }
    /// <summary>
    /// 权限标识
    /// </summary>
    public string? Permission { get; set; }
    /// <summary>
    /// 菜单名称
    /// </summary>
    public string Title { get; set; }
    /// <summary>
    /// 图标
    /// </summary>
    public string? Icon { get; set; }
    /// <summary>
    /// 是否内嵌
    /// </summary>
    public bool? IsIframe { get; set; }
    /// <summary>
    /// 外链链接
    /// </summary>
    public string? OutLink { get; set; }
    /// <summary>
    /// 是否隐藏
    /// </summary>
    public bool? IsHide { get; set; }
    /// <summary>
    /// 是否缓存
    /// </summary>
    public bool? IsKeepAlive { get; set; }
    /// <summary>
    /// 是否固定
    /// </summary>
    public bool? IsAffix { get; set; }
    /// <summary>
    /// 排序
    /// </summary>
    public int? OrderNo { get; set; }
    /// <summary>
    /// 状态
    /// </summary>
    [Dict(nameof(StatusEnum), AllowNullValue = true)]
    public StatusEnum? Status { get; set; }
    /// <summary>
    /// 备注
    /// </summary>
    public string? Remark { get; set; }
    /// <summary>
    /// 选中主键列表
    /// </summary>
    public List<long> SelectKeyList { get; set; }
}
/// <summary>
/// 客户系统菜单表增加输入参数
/// </summary>
public class AddFBS_MenuInput
{
    /// <summary>
    /// 父Id
    /// </summary>
    [Required(ErrorMessage = "父Id不能为空")]
    public long? Pid { get; set; }
    /// <summary>
    /// 菜单类型
    /// </summary>
    [Dict(nameof(MenuTypeEnum), AllowNullValue = true)]
    [Required(ErrorMessage = "菜单类型不能为空")]
    public MenuTypeEnum? Type { get; set; }
    /// <summary>
    /// 路由名称
    /// </summary>
    [MaxLength(64, ErrorMessage = "路由名称字符长度不能超过64")]
    public string? Name { get; set; }
    /// <summary>
    /// 路由地址
    /// </summary>
    [MaxLength(128, ErrorMessage = "路由地址字符长度不能超过128")]
    public string? Path { get; set; }
    /// <summary>
    /// 组件路径
    /// </summary>
    [MaxLength(128, ErrorMessage = "组件路径字符长度不能超过128")]
    public string? Component { get; set; }
    /// <summary>
    /// 重定向
    /// </summary>
    [MaxLength(128, ErrorMessage = "重定向字符长度不能超过128")]
    public string? Redirect { get; set; }
    /// <summary>
    /// 权限标识
    /// </summary>
    [MaxLength(128, ErrorMessage = "权限标识字符长度不能超过128")]
    public string? Permission { get; set; }
    /// <summary>
    /// 菜单名称
    /// </summary>
    [Required(ErrorMessage = "菜单名称不能为空")]
    [MaxLength(64, ErrorMessage = "菜单名称字符长度不能超过64")]
    public string Title { get; set; }
    /// <summary>
    /// 图标
    /// </summary>
    [MaxLength(128, ErrorMessage = "图标字符长度不能超过128")]
    public string? Icon { get; set; }
    /// <summary>
    /// 是否内嵌
    /// </summary>
    [Required(ErrorMessage = "是否内嵌不能为空")]
    public bool? IsIframe { get; set; }
    /// <summary>
    /// 外链链接
    /// </summary>
    [MaxLength(256, ErrorMessage = "外链链接字符长度不能超过256")]
    public string? OutLink { get; set; }
    /// <summary>
    /// 是否隐藏
    /// </summary>
    [Required(ErrorMessage = "是否隐藏不能为空")]
    public bool? IsHide { get; set; }
    /// <summary>
    /// 是否缓存
    /// </summary>
    [Required(ErrorMessage = "是否缓存不能为空")]
    public bool? IsKeepAlive { get; set; }
    /// <summary>
    /// 是否固定
    /// </summary>
    [Required(ErrorMessage = "是否固定不能为空")]
    public bool? IsAffix { get; set; }
    /// <summary>
    /// 排序
    /// </summary>
    [Required(ErrorMessage = "排序不能为空")]
    public int? OrderNo { get; set; }
    /// <summary>
    /// 状态
    /// </summary>
    [Dict(nameof(StatusEnum), AllowNullValue = true)]
    [Required(ErrorMessage = "状态不能为空")]
    public StatusEnum? Status { get; set; }
    /// <summary>
    /// 备注
    /// </summary>
    [MaxLength(256, ErrorMessage = "备注字符长度不能超过256")]
    public string? Remark { get; set; }
}
/// <summary>
/// 客户系统菜单表删除输入参数
/// </summary>
public class DeleteFBS_MenuInput
{
    /// <summary>
    /// 主键Id
    /// </summary>
    [Required(ErrorMessage = "主键Id不能为空")]
    public long? Id { get; set; }
}
/// <summary>
/// 客户系统菜单表更新输入参数
/// </summary>
public class UpdateFBS_MenuInput
{
    /// <summary>
    /// 主键Id
    /// </summary>
    [Required(ErrorMessage = "主键Id不能为空")]
    public long? Id { get; set; }
    /// <summary>
    /// 父Id
    /// </summary>
    [Required(ErrorMessage = "父Id不能为空")]
    public long? Pid { get; set; }
    /// <summary>
    /// 菜单类型
    /// </summary>
    [Dict(nameof(MenuTypeEnum), AllowNullValue = true)]
    [Required(ErrorMessage = "菜单类型不能为空")]
    public MenuTypeEnum? Type { get; set; }
    /// <summary>
    /// 路由名称
    /// </summary>
    [MaxLength(64, ErrorMessage = "路由名称字符长度不能超过64")]
    public string? Name { get; set; }
    /// <summary>
    /// 路由地址
    /// </summary>
    [MaxLength(128, ErrorMessage = "路由地址字符长度不能超过128")]
    public string? Path { get; set; }
    /// <summary>
    /// 组件路径
    /// </summary>
    [MaxLength(128, ErrorMessage = "组件路径字符长度不能超过128")]
    public string? Component { get; set; }
    /// <summary>
    /// 重定向
    /// </summary>
    [MaxLength(128, ErrorMessage = "重定向字符长度不能超过128")]
    public string? Redirect { get; set; }
    /// <summary>
    /// 权限标识
    /// </summary>
    [MaxLength(128, ErrorMessage = "权限标识字符长度不能超过128")]
    public string? Permission { get; set; }
    /// <summary>
    /// 菜单名称
    /// </summary>
    [Required(ErrorMessage = "菜单名称不能为空")]
    [MaxLength(64, ErrorMessage = "菜单名称字符长度不能超过64")]
    public string Title { get; set; }
    /// <summary>
    /// 图标
    /// </summary>
    [MaxLength(128, ErrorMessage = "图标字符长度不能超过128")]
    public string? Icon { get; set; }
    /// <summary>
    /// 是否内嵌
    /// </summary>
    [Required(ErrorMessage = "是否内嵌不能为空")]
    public bool? IsIframe { get; set; }
    /// <summary>
    /// 外链链接
    /// </summary>
    [MaxLength(256, ErrorMessage = "外链链接字符长度不能超过256")]
    public string? OutLink { get; set; }
    /// <summary>
    /// 是否隐藏
    /// </summary>
    [Required(ErrorMessage = "是否隐藏不能为空")]
    public bool? IsHide { get; set; }
    /// <summary>
    /// 是否缓存
    /// </summary>
    [Required(ErrorMessage = "是否缓存不能为空")]
    public bool? IsKeepAlive { get; set; }
    /// <summary>
    /// 是否固定
    /// </summary>
    [Required(ErrorMessage = "是否固定不能为空")]
    public bool? IsAffix { get; set; }
    /// <summary>
    /// 排序
    /// </summary>
    [Required(ErrorMessage = "排序不能为空")]
    public int? OrderNo { get; set; }
    /// <summary>
    /// 状态
    /// </summary>
    [Dict(nameof(StatusEnum), AllowNullValue = true)]
    [Required(ErrorMessage = "状态不能为空")]
    public StatusEnum? Status { get; set; }
    /// <summary>
    /// 备注
    /// </summary>
    [MaxLength(256, ErrorMessage = "备注字符长度不能超过256")]
    public string? Remark { get; set; }
}
/// <summary>
/// 客户系统菜单表主键查询输入参数
/// </summary>
public class QueryByIdFBS_MenuInput : DeleteFBS_MenuInput
{
}
/// <summary>
/// 设置状态输入参数
/// </summary>
public class SetFBS_MenuStatusInput : BaseStatusInput
{
}
/// <summary>
/// 客户系统菜单表数据导入实体
/// </summary>
[ExcelImporter(SheetIndex = 1, IsOnlyErrorRows = true)]
public class ImportFBS_MenuInput : BaseImportInput
{
    /// <summary>
    /// 父Id
    /// </summary>
    [ImporterHeader(Name = "*父Id")]
    [ExporterHeader("*父Id", Format = "", Width = 25, IsBold = true)]
    public long? Pid { get; set; }
    /// <summary>
    /// 菜单类型
    /// </summary>
    [ImporterHeader(Name = "*菜单类型")]
    [ExporterHeader("*菜单类型", Format = "", Width = 25, IsBold = true)]
    public MenuTypeEnum? Type { get; set; }
    /// <summary>
    /// 路由名称
    /// </summary>
    [ImporterHeader(Name = "路由名称")]
    [ExporterHeader("路由名称", Format = "", Width = 25, IsBold = true)]
    public string? Name { get; set; }
    /// <summary>
    /// 路由地址
    /// </summary>
    [ImporterHeader(Name = "路由地址")]
    [ExporterHeader("路由地址", Format = "", Width = 25, IsBold = true)]
    public string? Path { get; set; }
    /// <summary>
    /// 组件路径
    /// </summary>
    [ImporterHeader(Name = "组件路径")]
    [ExporterHeader("组件路径", Format = "", Width = 25, IsBold = true)]
    public string? Component { get; set; }
    /// <summary>
    /// 重定向
    /// </summary>
    [ImporterHeader(Name = "重定向")]
    [ExporterHeader("重定向", Format = "", Width = 25, IsBold = true)]
    public string? Redirect { get; set; }
    /// <summary>
    /// 权限标识
    /// </summary>
    [ImporterHeader(Name = "权限标识")]
    [ExporterHeader("权限标识", Format = "", Width = 25, IsBold = true)]
    public string? Permission { get; set; }
    /// <summary>
    /// 菜单名称
    /// </summary>
    [ImporterHeader(Name = "*菜单名称")]
    [ExporterHeader("*菜单名称", Format = "", Width = 25, IsBold = true)]
    public string Title { get; set; }
    /// <summary>
    /// 图标
    /// </summary>
    [ImporterHeader(Name = "图标")]
    [ExporterHeader("图标", Format = "", Width = 25, IsBold = true)]
    public string? Icon { get; set; }
    /// <summary>
    /// 是否内嵌
    /// </summary>
    [ImporterHeader(Name = "*是否内嵌")]
    [ExporterHeader("*是否内嵌", Format = "", Width = 25, IsBold = true)]
    public bool? IsIframe { get; set; }
    /// <summary>
    /// 外链链接
    /// </summary>
    [ImporterHeader(Name = "外链链接")]
    [ExporterHeader("外链链接", Format = "", Width = 25, IsBold = true)]
    public string? OutLink { get; set; }
    /// <summary>
    /// 是否隐藏
    /// </summary>
    [ImporterHeader(Name = "*是否隐藏")]
    [ExporterHeader("*是否隐藏", Format = "", Width = 25, IsBold = true)]
    public bool? IsHide { get; set; }
    /// <summary>
    /// 是否缓存
    /// </summary>
    [ImporterHeader(Name = "*是否缓存")]
    [ExporterHeader("*是否缓存", Format = "", Width = 25, IsBold = true)]
    public bool? IsKeepAlive { get; set; }
    /// <summary>
    /// 是否固定
    /// </summary>
    [ImporterHeader(Name = "*是否固定")]
    [ExporterHeader("*是否固定", Format = "", Width = 25, IsBold = true)]
    public bool? IsAffix { get; set; }
    /// <summary>
    /// 排序
    /// </summary>
    [ImporterHeader(Name = "*排序")]
    [ExporterHeader("*排序", Format = "", Width = 25, IsBold = true)]
    public int? OrderNo { get; set; }
    /// <summary>
    /// 状态
    /// </summary>
    [ImporterHeader(Name = "*状态")]
    [ExporterHeader("*状态", Format = "", Width = 25, IsBold = true)]
    public StatusEnum? Status { get; set; }
    /// <summary>
    /// 备注
    /// </summary>
    [ImporterHeader(Name = "备注")]
    [ExporterHeader("备注", Format = "", Width = 25, IsBold = true)]
    public string? Remark { get; set; }
}
Admin.NET/FZCZTB.Net.CustomerSYSTem/Service/FBS_Menu/Dto/FBS_MenuOutput.cs
New file
@@ -0,0 +1,150 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using Admin.NET.Core;
using Magicodes.ExporterAndImporter.Core;
namespace FZCZTB.Net.CustomerSYSTem.Service.FBS_Menu.Dto;
/// <summary>
/// 客户系统菜单表输出参数
/// </summary>
public class FBS_MenuOutput
{
    /// <summary>
    /// 主键Id
    /// </summary>
    public long Id { get; set; }
    /// <summary>
    /// 父Id
    /// </summary>
    public long Pid { get; set; }
    /// <summary>
    /// 菜单类型
    /// </summary>
    public MenuTypeEnum Type { get; set; }
    /// <summary>
    /// 路由名称
    /// </summary>
    public string? Name { get; set; }
    /// <summary>
    /// 路由地址
    /// </summary>
    public string? Path { get; set; }
    /// <summary>
    /// 组件路径
    /// </summary>
    public string? Component { get; set; }
    /// <summary>
    /// 重定向
    /// </summary>
    public string? Redirect { get; set; }
    /// <summary>
    /// 权限标识
    /// </summary>
    public string? Permission { get; set; }
    /// <summary>
    /// 菜单名称
    /// </summary>
    public string Title { get; set; }
    /// <summary>
    /// 图标
    /// </summary>
    public string? Icon { get; set; }
    /// <summary>
    /// 是否内嵌
    /// </summary>
    public bool IsIframe { get; set; }
    /// <summary>
    /// 外链链接
    /// </summary>
    public string? OutLink { get; set; }
    /// <summary>
    /// 是否隐藏
    /// </summary>
    public bool IsHide { get; set; }
    /// <summary>
    /// 是否缓存
    /// </summary>
    public bool IsKeepAlive { get; set; }
    /// <summary>
    /// 是否固定
    /// </summary>
    public bool IsAffix { get; set; }
    /// <summary>
    /// 排序
    /// </summary>
    public int OrderNo { get; set; }
    /// <summary>
    /// 状态
    /// </summary>
    public StatusEnum Status { get; set; }
    /// <summary>
    /// 备注
    /// </summary>
    public string? Remark { get; set; }
    /// <summary>
    /// 租户Id
    /// </summary>
    public long? TenantId { get; set; }
    /// <summary>
    /// 创建时间
    /// </summary>
    public DateTime? CreateTime { get; set; }
    /// <summary>
    /// 更新时间
    /// </summary>
    public DateTime? UpdateTime { get; set; }
    /// <summary>
    /// 创建者Id
    /// </summary>
    public long? CreateUserId { get; set; }
    /// <summary>
    /// 创建者姓名
    /// </summary>
    public string? CreateUserName { get; set; }
    /// <summary>
    /// 修改者Id
    /// </summary>
    public long? UpdateUserId { get; set; }
    /// <summary>
    /// 修改者姓名
    /// </summary>
    public string? UpdateUserName { get; set; }
}
/// <summary>
/// 客户系统菜单表数据导入模板实体
/// </summary>
public class ExportFBS_MenuOutput : ImportFBS_MenuInput
{
    [ImporterHeader(IsIgnore = true)]
    [ExporterHeader(IsIgnore = true)]
    public override string Error { get; set; }
}
Admin.NET/FZCZTB.Net.CustomerSYSTem/Service/FBS_Menu/FBS_MenuService.cs
New file
@@ -0,0 +1,261 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using Admin.NET.Core.Service;
using Microsoft.AspNetCore.Http;
using Furion.DatabaseAccessor;
using Furion.FriendlyException;
using Mapster;
using SqlSugar;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Mvc;
using Furion.DynamicApiController;
using Furion.DependencyInjection;
using Admin.NET.Core;
using FZCZTB.NET.MD.CutomerMd;
using FZCZTB.Net.CustomerSYSTem.Service.FBS_Menu.Dto;
namespace FZCZTB.Net.CustomerSYSTem;
/// <summary>
/// 客户系统菜单表服务 🧩
/// </summary>
[ApiDescriptionSettings(CustomerSYSTemConst.GroupName, Order = 100)]
public class FBS_MenuService : IDynamicApiController, ITransient
{
    private readonly SqlSugarRepository<FBS_Menu> _fBS_MenuRep;
    private readonly ISqlSugarClient _sqlSugarClient;
    public FBS_MenuService(SqlSugarRepository<FBS_Menu> fBS_MenuRep, ISqlSugarClient sqlSugarClient)
    {
        _fBS_MenuRep = fBS_MenuRep;
        _sqlSugarClient = sqlSugarClient;
    }
    /// <summary>
    /// 分页查询客户系统菜单表 🔖
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("分页查询客户系统菜单表")]
    [ApiDescriptionSettings(Name = "Page"), HttpPost]
    public async Task<SqlSugarPagedList<FBS_MenuOutput>> Page(PageFBS_MenuInput input)
    {
        input.Keyword = input.Keyword?.Trim();
        var query = _fBS_MenuRep.AsQueryable()
            .WhereIF(!string.IsNullOrWhiteSpace(input.Keyword), u => u.Name.Contains(input.Keyword) || u.Path.Contains(input.Keyword) || u.Component.Contains(input.Keyword) || u.Redirect.Contains(input.Keyword) || u.Permission.Contains(input.Keyword) || u.Title.Contains(input.Keyword) || u.Icon.Contains(input.Keyword) || u.OutLink.Contains(input.Keyword) || u.Remark.Contains(input.Keyword))
            .WhereIF(!string.IsNullOrWhiteSpace(input.Name), u => u.Name.Contains(input.Name.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.Path), u => u.Path.Contains(input.Path.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.Component), u => u.Component.Contains(input.Component.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.Redirect), u => u.Redirect.Contains(input.Redirect.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.Permission), u => u.Permission.Contains(input.Permission.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.Title), u => u.Title.Contains(input.Title.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.Icon), u => u.Icon.Contains(input.Icon.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.OutLink), u => u.OutLink.Contains(input.OutLink.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.Remark), u => u.Remark.Contains(input.Remark.Trim()))
            .WhereIF(input.Pid != null, u => u.Pid == input.Pid)
            .WhereIF(input.Type.HasValue, u => u.Type == input.Type)
            .WhereIF(input.OrderNo != null, u => u.OrderNo == input.OrderNo)
            .WhereIF(input.Status.HasValue, u => u.Status == input.Status)
            .Select<FBS_MenuOutput>();
        return await query.OrderBuilder(input).ToPagedListAsync(input.Page, input.PageSize);
    }
    /// <summary>
    /// 获取客户系统菜单表详情 ℹ️
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("获取客户系统菜单表详情")]
    [ApiDescriptionSettings(Name = "Detail"), HttpGet]
    public async Task<FBS_Menu> Detail([FromQuery] QueryByIdFBS_MenuInput input)
    {
        return await _fBS_MenuRep.GetFirstAsync(u => u.Id == input.Id);
    }
    /// <summary>
    /// 增加客户系统菜单表 ➕
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("增加客户系统菜单表")]
    [ApiDescriptionSettings(Name = "Add"), HttpPost]
    public async Task<long> Add(AddFBS_MenuInput input)
    {
        var entity = input.Adapt<FBS_Menu>();
        return await _fBS_MenuRep.InsertAsync(entity) ? entity.Id : 0;
    }
    /// <summary>
    /// 更新客户系统菜单表 ✏️
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("更新客户系统菜单表")]
    [ApiDescriptionSettings(Name = "Update"), HttpPost]
    public async Task Update(UpdateFBS_MenuInput input)
    {
        var entity = input.Adapt<FBS_Menu>();
        await _fBS_MenuRep.AsUpdateable(entity)
        .ExecuteCommandAsync();
    }
    /// <summary>
    /// 删除客户系统菜单表 ❌
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("删除客户系统菜单表")]
    [ApiDescriptionSettings(Name = "Delete"), HttpPost]
    public async Task Delete(DeleteFBS_MenuInput input)
    {
        var entity = await _fBS_MenuRep.GetFirstAsync(u => u.Id == input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D1002);
       // await _fBS_MenuRep.FakeDeleteAsync(entity);   //假删除
        await _fBS_MenuRep.DeleteAsync(entity);   //真删除
    }
    /// <summary>
    /// 批量删除客户系统菜单表 ❌
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("批量删除客户系统菜单表")]
    [ApiDescriptionSettings(Name = "BatchDelete"), HttpPost]
    public async Task<bool> BatchDelete([Required(ErrorMessage = "主键列表不能为空")]List<DeleteFBS_MenuInput> input)
    {
        var exp = Expressionable.Create<FBS_Menu>();
        foreach (var row in input) exp = exp.Or(it => it.Id == row.Id);
        var list = await _fBS_MenuRep.AsQueryable().Where(exp.ToExpression()).ToListAsync();
       // return await _fBS_MenuRep.FakeDeleteAsync(list);   //假删除
        return await _fBS_MenuRep.DeleteAsync(list);   //真删除
    }
    /// <summary>
    /// 设置客户系统菜单表状态 🚫
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("设置客户系统菜单表状态")]
    [ApiDescriptionSettings(Name = "SetStatus"), HttpPost]
    public async Task SetFBS_MenuStatus(SetFBS_MenuStatusInput input)
    {
        await _fBS_MenuRep.AsUpdateable().SetColumns(u => u.Status, input.Status).Where(u => u.Id == input.Id).ExecuteCommandAsync();
    }
    /// <summary>
    /// 导出客户系统菜单表记录 🔖
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("导出客户系统菜单表记录")]
    [ApiDescriptionSettings(Name = "Export"), HttpPost, NonUnify]
    public async Task<IActionResult> Export(PageFBS_MenuInput input)
    {
        var list = (await Page(input)).Items?.Adapt<List<ExportFBS_MenuOutput>>() ?? new();
        if (input.SelectKeyList?.Count > 0) list = list.Where(x => input.SelectKeyList.Contains(x.Id)).ToList();
        return ExcelHelper.ExportTemplate(list, "客户系统菜单表导出记录");
    }
    /// <summary>
    /// 下载客户系统菜单表数据导入模板 ⬇️
    /// </summary>
    /// <returns></returns>
    [DisplayName("下载客户系统菜单表数据导入模板")]
    [ApiDescriptionSettings(Name = "Import"), HttpGet, NonUnify]
    public IActionResult DownloadTemplate()
    {
        return ExcelHelper.ExportTemplate(new List<ExportFBS_MenuOutput>(), "客户系统菜单表导入模板");
    }
    private static readonly object _fBS_MenuImportLock = new object();
    /// <summary>
    /// 导入客户系统菜单表记录 💾
    /// </summary>
    /// <returns></returns>
    [DisplayName("导入客户系统菜单表记录")]
    [ApiDescriptionSettings(Name = "Import"), HttpPost, NonUnify, UnitOfWork]
    public IActionResult ImportData([Required] IFormFile file)
    {
        lock (_fBS_MenuImportLock)
        {
            var stream = ExcelHelper.ImportData<ImportFBS_MenuInput, FBS_Menu>(file, (list, markerErrorAction) =>
            {
                _sqlSugarClient.Utilities.PageEach(list, 2048, pageItems =>
                {
                    // 校验并过滤必填基本类型为null的字段
                    var rows = pageItems.Where(x => {
                        if (!string.IsNullOrWhiteSpace(x.Error)) return false;
                        if (x.Pid == null){
                            x.Error = "父Id不能为空";
                            return false;
                        }
                        if (!string.IsNullOrWhiteSpace(x.Error)) return false;
                        if (x.Type == null){
                            x.Error = "菜单类型不能为空";
                            return false;
                        }
                        if (!string.IsNullOrWhiteSpace(x.Error)) return false;
                        if (x.IsIframe == null){
                            x.Error = "是否内嵌不能为空";
                            return false;
                        }
                        if (!string.IsNullOrWhiteSpace(x.Error)) return false;
                        if (x.IsHide == null){
                            x.Error = "是否隐藏不能为空";
                            return false;
                        }
                        if (!string.IsNullOrWhiteSpace(x.Error)) return false;
                        if (x.IsKeepAlive == null){
                            x.Error = "是否缓存不能为空";
                            return false;
                        }
                        if (!string.IsNullOrWhiteSpace(x.Error)) return false;
                        if (x.IsAffix == null){
                            x.Error = "是否固定不能为空";
                            return false;
                        }
                        if (!string.IsNullOrWhiteSpace(x.Error)) return false;
                        if (x.OrderNo == null){
                            x.Error = "排序不能为空";
                            return false;
                        }
                        if (!string.IsNullOrWhiteSpace(x.Error)) return false;
                        if (x.Status == null){
                            x.Error = "状态不能为空";
                            return false;
                        }
                        return true;
                    }).Adapt<List<FBS_Menu>>();
                    var storageable = _fBS_MenuRep.Context.Storageable(rows)
                        .SplitError(it => it.Item.Name?.Length > 64, "路由名称长度不能超过64个字符")
                        .SplitError(it => it.Item.Path?.Length > 128, "路由地址长度不能超过128个字符")
                        .SplitError(it => it.Item.Component?.Length > 128, "组件路径长度不能超过128个字符")
                        .SplitError(it => it.Item.Redirect?.Length > 128, "重定向长度不能超过128个字符")
                        .SplitError(it => it.Item.Permission?.Length > 128, "权限标识长度不能超过128个字符")
                        .SplitError(it => string.IsNullOrWhiteSpace(it.Item.Title), "菜单名称不能为空")
                        .SplitError(it => it.Item.Title?.Length > 64, "菜单名称长度不能超过64个字符")
                        .SplitError(it => it.Item.Icon?.Length > 128, "图标长度不能超过128个字符")
                        .SplitError(it => it.Item.OutLink?.Length > 256, "外链链接长度不能超过256个字符")
                        .SplitError(it => it.Item.Remark?.Length > 256, "备注长度不能超过256个字符")
                        .SplitInsert(_ => true)
                        .ToStorage();
                    storageable.AsInsertable.ExecuteCommand();// 不存在插入
                    storageable.AsUpdateable.ExecuteCommand();// 存在更新
                    // 标记错误信息
                    markerErrorAction.Invoke(storageable, pageItems, rows);
                });
            });
            return stream;
        }
    }
}
Admin.NET/FZCZTB.Net.CustomerSYSTem/Service/FBS_Role/Dto/FBS_RoleDto.cs
New file
@@ -0,0 +1,86 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using Admin.NET.Core;
namespace FZCZTB.Net.CustomerSYSTem.Service.FBS_Role.Dto;
/// <summary>
/// 客户角色输出参数
/// </summary>
public class FBS_RoleDto
{
    /// <summary>
    /// 主键Id
    /// </summary>
    public long Id { get; set; }
    /// <summary>
    /// 名称
    /// </summary>
    public string? Name { get; set; }
    /// <summary>
    /// 编码
    /// </summary>
    public string? Code { get; set; }
    /// <summary>
    /// 排序
    /// </summary>
    public int? OrderNo { get; set; }
    /// <summary>
    /// 数据范围
    /// </summary>
    public DataScopeEnum DataScope { get; set; }
    /// <summary>
    /// 备注
    /// </summary>
    public string? Remark { get; set; }
    /// <summary>
    /// 状态
    /// </summary>
    public StatusEnum Status { get; set; }
    /// <summary>
    /// 租户Id
    /// </summary>
    public long? TenantId { get; set; }
    /// <summary>
    /// 创建时间
    /// </summary>
    public DateTime? CreateTime { get; set; }
    /// <summary>
    /// 更新时间
    /// </summary>
    public DateTime? UpdateTime { get; set; }
    /// <summary>
    /// 创建者Id
    /// </summary>
    public long? CreateUserId { get; set; }
    /// <summary>
    /// 创建者姓名
    /// </summary>
    public string? CreateUserName { get; set; }
    /// <summary>
    /// 修改者Id
    /// </summary>
    public long? UpdateUserId { get; set; }
    /// <summary>
    /// 修改者姓名
    /// </summary>
    public string? UpdateUserName { get; set; }
}
Admin.NET/FZCZTB.Net.CustomerSYSTem/Service/FBS_Role/Dto/FBS_RoleInput.cs
New file
@@ -0,0 +1,266 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using Admin.NET.Core;
using System.ComponentModel.DataAnnotations;
using Magicodes.ExporterAndImporter.Core;
using Magicodes.ExporterAndImporter.Excel;
namespace FZCZTB.Net.CustomerSYSTem.Service.FBS_Role.Dto;
/// <summary>
/// 客户角色基础输入参数
/// </summary>
public class FBS_RoleBaseInput
{
    /// <summary>
    /// 主键Id
    /// </summary>
    public virtual long? Id { get; set; }
    /// <summary>
    /// 名称
    /// </summary>
    public virtual string? Name { get; set; }
    /// <summary>
    /// 编码
    /// </summary>
    public virtual string? Code { get; set; }
    /// <summary>
    /// 排序
    /// </summary>
    public virtual int? OrderNo { get; set; }
    /// <summary>
    /// 数据范围
    /// </summary>
    [Dict(nameof(DataScopeEnum), AllowNullValue = true)]
    public virtual DataScopeEnum? DataScope { get; set; }
    /// <summary>
    /// 备注
    /// </summary>
    public virtual string? Remark { get; set; }
    /// <summary>
    /// 状态
    /// </summary>
    [Dict(nameof(StatusEnum), AllowNullValue = true)]
    public virtual StatusEnum? Status { get; set; }
}
/// <summary>
/// 客户角色分页查询输入参数
/// </summary>
public class PageFBS_RoleInput : BasePageInput
{
    /// <summary>
    /// 名称
    /// </summary>
    public string? Name { get; set; }
    /// <summary>
    /// 编码
    /// </summary>
    public string? Code { get; set; }
    /// <summary>
    /// 排序
    /// </summary>
    public int? OrderNo { get; set; }
    /// <summary>
    /// 数据范围
    /// </summary>
    [Dict(nameof(DataScopeEnum), AllowNullValue = true)]
    public DataScopeEnum? DataScope { get; set; }
    /// <summary>
    /// 备注
    /// </summary>
    public string? Remark { get; set; }
    /// <summary>
    /// 状态
    /// </summary>
    [Dict(nameof(StatusEnum), AllowNullValue = true)]
    public StatusEnum? Status { get; set; }
    /// <summary>
    /// 选中主键列表
    /// </summary>
    public List<long> SelectKeyList { get; set; }
}
/// <summary>
/// 客户角色增加输入参数
/// </summary>
public class AddFBS_RoleInput
{
    /// <summary>
    /// 名称
    /// </summary>
    [MaxLength(64, ErrorMessage = "名称字符长度不能超过64")]
    public string? Name { get; set; }
    /// <summary>
    /// 编码
    /// </summary>
    [MaxLength(64, ErrorMessage = "编码字符长度不能超过64")]
    public string? Code { get; set; }
    /// <summary>
    /// 排序
    /// </summary>
    public int? OrderNo { get; set; }
    /// <summary>
    /// 数据范围
    /// </summary>
    [Dict(nameof(DataScopeEnum), AllowNullValue = true)]
    public DataScopeEnum? DataScope { get; set; }
    /// <summary>
    /// 备注
    /// </summary>
    [MaxLength(128, ErrorMessage = "备注字符长度不能超过128")]
    public string? Remark { get; set; }
    /// <summary>
    /// 状态
    /// </summary>
    [Dict(nameof(StatusEnum), AllowNullValue = true)]
    public StatusEnum? Status { get; set; }
}
/// <summary>
/// 客户角色删除输入参数
/// </summary>
public class DeleteFBS_RoleInput
{
    /// <summary>
    /// 主键Id
    /// </summary>
    [Required(ErrorMessage = "主键Id不能为空")]
    public long? Id { get; set; }
}
/// <summary>
/// 客户角色更新输入参数
/// </summary>
public class UpdateFBS_RoleInput
{
    /// <summary>
    /// 主键Id
    /// </summary>
    [Required(ErrorMessage = "主键Id不能为空")]
    public long? Id { get; set; }
    /// <summary>
    /// 名称
    /// </summary>
    [MaxLength(64, ErrorMessage = "名称字符长度不能超过64")]
    public string? Name { get; set; }
    /// <summary>
    /// 编码
    /// </summary>
    [MaxLength(64, ErrorMessage = "编码字符长度不能超过64")]
    public string? Code { get; set; }
    /// <summary>
    /// 排序
    /// </summary>
    public int? OrderNo { get; set; }
    /// <summary>
    /// 数据范围
    /// </summary>
    [Dict(nameof(DataScopeEnum), AllowNullValue = true)]
    public DataScopeEnum? DataScope { get; set; }
    /// <summary>
    /// 备注
    /// </summary>
    [MaxLength(128, ErrorMessage = "备注字符长度不能超过128")]
    public string? Remark { get; set; }
    /// <summary>
    /// 状态
    /// </summary>
    [Dict(nameof(StatusEnum), AllowNullValue = true)]
    public StatusEnum? Status { get; set; }
}
/// <summary>
/// 客户角色主键查询输入参数
/// </summary>
public class QueryByIdFBS_RoleInput : DeleteFBS_RoleInput
{
}
/// <summary>
/// 设置状态输入参数
/// </summary>
public class SetFBS_RoleStatusInput : BaseStatusInput
{
}
/// <summary>
/// 客户角色数据导入实体
/// </summary>
[ExcelImporter(SheetIndex = 1, IsOnlyErrorRows = true)]
public class ImportFBS_RoleInput : BaseImportInput
{
    /// <summary>
    /// 名称
    /// </summary>
    [ImporterHeader(Name = "名称")]
    [ExporterHeader("名称", Format = "", Width = 25, IsBold = true)]
    public string? Name { get; set; }
    /// <summary>
    /// 编码
    /// </summary>
    [ImporterHeader(Name = "编码")]
    [ExporterHeader("编码", Format = "", Width = 25, IsBold = true)]
    public string? Code { get; set; }
    /// <summary>
    /// 排序
    /// </summary>
    [ImporterHeader(Name = "排序")]
    [ExporterHeader("排序", Format = "", Width = 25, IsBold = true)]
    public int? OrderNo { get; set; }
    /// <summary>
    /// 数据范围
    /// </summary>
    [ImporterHeader(Name = "数据范围")]
    [ExporterHeader("数据范围", Format = "", Width = 25, IsBold = true)]
    public DataScopeEnum? DataScope { get; set; }
    /// <summary>
    /// 备注
    /// </summary>
    [ImporterHeader(Name = "备注")]
    [ExporterHeader("备注", Format = "", Width = 25, IsBold = true)]
    public string? Remark { get; set; }
    /// <summary>
    /// 状态
    /// </summary>
    [ImporterHeader(Name = "状态")]
    [ExporterHeader("状态", Format = "", Width = 25, IsBold = true)]
    public StatusEnum? Status { get; set; }
}
Admin.NET/FZCZTB.Net.CustomerSYSTem/Service/FBS_Role/Dto/FBS_RoleOutput.cs
New file
@@ -0,0 +1,95 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using Admin.NET.Core;
using Magicodes.ExporterAndImporter.Core;
namespace FZCZTB.Net.CustomerSYSTem.Service.FBS_Role.Dto;
/// <summary>
/// 客户角色输出参数
/// </summary>
public class FBS_RoleOutput
{
    /// <summary>
    /// 主键Id
    /// </summary>
    public long Id { get; set; }
    /// <summary>
    /// 名称
    /// </summary>
    public string? Name { get; set; }
    /// <summary>
    /// 编码
    /// </summary>
    public string? Code { get; set; }
    /// <summary>
    /// 排序
    /// </summary>
    public int? OrderNo { get; set; }
    /// <summary>
    /// 数据范围
    /// </summary>
    public DataScopeEnum DataScope { get; set; }
    /// <summary>
    /// 备注
    /// </summary>
    public string? Remark { get; set; }
    /// <summary>
    /// 状态
    /// </summary>
    public StatusEnum Status { get; set; }
    /// <summary>
    /// 租户Id
    /// </summary>
    public long? TenantId { get; set; }
    /// <summary>
    /// 创建时间
    /// </summary>
    public DateTime? CreateTime { get; set; }
    /// <summary>
    /// 更新时间
    /// </summary>
    public DateTime? UpdateTime { get; set; }
    /// <summary>
    /// 创建者Id
    /// </summary>
    public long? CreateUserId { get; set; }
    /// <summary>
    /// 创建者姓名
    /// </summary>
    public string? CreateUserName { get; set; }
    /// <summary>
    /// 修改者Id
    /// </summary>
    public long? UpdateUserId { get; set; }
    /// <summary>
    /// 修改者姓名
    /// </summary>
    public string? UpdateUserName { get; set; }
}
/// <summary>
/// 客户角色数据导入模板实体
/// </summary>
public class ExportFBS_RoleOutput : ImportFBS_RoleInput
{
    [ImporterHeader(IsIgnore = true)]
    [ExporterHeader(IsIgnore = true)]
    public override string Error { get; set; }
}
Admin.NET/FZCZTB.Net.CustomerSYSTem/Service/FBS_Role/FBS_RoleService.cs
New file
@@ -0,0 +1,209 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using Admin.NET.Core.Service;
using Microsoft.AspNetCore.Http;
using Furion.DatabaseAccessor;
using Furion.FriendlyException;
using Mapster;
using SqlSugar;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Mvc;
using Furion.DynamicApiController;
using Furion.DependencyInjection;
using Admin.NET.Core;
using FZCZTB.NET.MD.CutomerMd;
using FZCZTB.Net.CustomerSYSTem.Service.FBS_Role.Dto;
using FZCZTB.Net.CustomerSYSTem;
/// <summary>
/// 客户角色服务 🧩
/// </summary>
[ApiDescriptionSettings(CustomerSYSTemConst.GroupName, Order = 100)]
public class FBS_RoleService : IDynamicApiController, ITransient
{
    private readonly SqlSugarRepository<FBS_Role> _fBS_RoleRep;
    private readonly ISqlSugarClient _sqlSugarClient;
    public FBS_RoleService(SqlSugarRepository<FBS_Role> fBS_RoleRep, ISqlSugarClient sqlSugarClient)
    {
        _fBS_RoleRep = fBS_RoleRep;
        _sqlSugarClient = sqlSugarClient;
    }
    /// <summary>
    /// 分页查询客户角色 🔖
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("分页查询客户角色")]
    [ApiDescriptionSettings(Name = "Page"), HttpPost]
    public async Task<SqlSugarPagedList<FBS_RoleOutput>> Page(PageFBS_RoleInput input)
    {
        input.Keyword = input.Keyword?.Trim();
        var query = _fBS_RoleRep.AsQueryable()
            .WhereIF(!string.IsNullOrWhiteSpace(input.Keyword), u => u.Name.Contains(input.Keyword) || u.Code.Contains(input.Keyword) || u.Remark.Contains(input.Keyword))
            .WhereIF(!string.IsNullOrWhiteSpace(input.Name), u => u.Name.Contains(input.Name.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.Code), u => u.Code.Contains(input.Code.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.Remark), u => u.Remark.Contains(input.Remark.Trim()))
            .WhereIF(input.OrderNo != null, u => u.OrderNo == input.OrderNo)
            .WhereIF(input.DataScope.HasValue, u => u.DataScope == input.DataScope)
            .WhereIF(input.Status.HasValue, u => u.Status == input.Status)
            .Select<FBS_RoleOutput>();
        return await query.OrderBuilder(input).ToPagedListAsync(input.Page, input.PageSize);
    }
    /// <summary>
    /// 获取客户角色详情 ℹ️
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("获取客户角色详情")]
    [ApiDescriptionSettings(Name = "Detail"), HttpGet]
    public async Task<FBS_Role> Detail([FromQuery] QueryByIdFBS_RoleInput input)
    {
        return await _fBS_RoleRep.GetFirstAsync(u => u.Id == input.Id);
    }
    /// <summary>
    /// 增加客户角色 ➕
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("增加客户角色")]
    [ApiDescriptionSettings(Name = "Add"), HttpPost]
    public async Task<long> Add(AddFBS_RoleInput input)
    {
        var entity = input.Adapt<FBS_Role>();
        return await _fBS_RoleRep.InsertAsync(entity) ? entity.Id : 0;
    }
    /// <summary>
    /// 更新客户角色 ✏️
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("更新客户角色")]
    [ApiDescriptionSettings(Name = "Update"), HttpPost]
    public async Task Update(UpdateFBS_RoleInput input)
    {
        var entity = input.Adapt<FBS_Role>();
        await _fBS_RoleRep.AsUpdateable(entity)
        .ExecuteCommandAsync();
    }
    /// <summary>
    /// 删除客户角色 ❌
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("删除客户角色")]
    [ApiDescriptionSettings(Name = "Delete"), HttpPost]
    public async Task Delete(DeleteFBS_RoleInput input)
    {
        var entity = await _fBS_RoleRep.GetFirstAsync(u => u.Id == input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D1002);
        // await _fBS_RoleRep.FakeDeleteAsync(entity);   //假删除
        await _fBS_RoleRep.DeleteAsync(entity);   //真删除
    }
    /// <summary>
    /// 批量删除客户角色 ❌
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("批量删除客户角色")]
    [ApiDescriptionSettings(Name = "BatchDelete"), HttpPost]
    public async Task<bool> BatchDelete([Required(ErrorMessage = "主键列表不能为空")] List<DeleteFBS_RoleInput> input)
    {
        var exp = Expressionable.Create<FBS_Role>();
        foreach (var row in input) exp = exp.Or(it => it.Id == row.Id);
        var list = await _fBS_RoleRep.AsQueryable().Where(exp.ToExpression()).ToListAsync();
        // return await _fBS_RoleRep.FakeDeleteAsync(list);   //假删除
        return await _fBS_RoleRep.DeleteAsync(list);   //真删除
    }
    /// <summary>
    /// 设置客户角色状态 🚫
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("设置客户角色状态")]
    [ApiDescriptionSettings(Name = "SetStatus"), HttpPost]
    public async Task SetFBS_RoleStatus(SetFBS_RoleStatusInput input)
    {
        await _fBS_RoleRep.AsUpdateable().SetColumns(u => u.Status, input.Status).Where(u => u.Id == input.Id).ExecuteCommandAsync();
    }
    /// <summary>
    /// 导出客户角色记录 🔖
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("导出客户角色记录")]
    [ApiDescriptionSettings(Name = "Export"), HttpPost, NonUnify]
    public async Task<IActionResult> Export(PageFBS_RoleInput input)
    {
        var list = (await Page(input)).Items?.Adapt<List<ExportFBS_RoleOutput>>() ?? new();
        if (input.SelectKeyList?.Count > 0) list = list.Where(x => input.SelectKeyList.Contains(x.Id)).ToList();
        return ExcelHelper.ExportTemplate(list, "客户角色导出记录");
    }
    /// <summary>
    /// 下载客户角色数据导入模板 ⬇️
    /// </summary>
    /// <returns></returns>
    [DisplayName("下载客户角色数据导入模板")]
    [ApiDescriptionSettings(Name = "Import"), HttpGet, NonUnify]
    public IActionResult DownloadTemplate()
    {
        return ExcelHelper.ExportTemplate(new List<ExportFBS_RoleOutput>(), "客户角色导入模板");
    }
    private static readonly object _fBS_RoleImportLock = new object();
    /// <summary>
    /// 导入客户角色记录 💾
    /// </summary>
    /// <returns></returns>
    [DisplayName("导入客户角色记录")]
    [ApiDescriptionSettings(Name = "Import"), HttpPost, NonUnify, UnitOfWork]
    public IActionResult ImportData([Required] IFormFile file)
    {
        lock (_fBS_RoleImportLock)
        {
            var stream = ExcelHelper.ImportData<ImportFBS_RoleInput, FBS_Role>(file, (list, markerErrorAction) =>
            {
                _sqlSugarClient.Utilities.PageEach(list, 2048, pageItems =>
                {
                    // 校验并过滤必填基本类型为null的字段
                    var rows = pageItems.Where(x =>
                    {
                        return true;
                    }).Adapt<List<FBS_Role>>();
                    var storageable = _fBS_RoleRep.Context.Storageable(rows)
                        .SplitError(it => it.Item.Name?.Length > 64, "名称长度不能超过64个字符")
                        .SplitError(it => it.Item.Code?.Length > 64, "编码长度不能超过64个字符")
                        .SplitError(it => it.Item.Remark?.Length > 128, "备注长度不能超过128个字符")
                        .SplitInsert(_ => true)
                        .ToStorage();
                    storageable.AsInsertable.ExecuteCommand();// 不存在插入
                    storageable.AsUpdateable.ExecuteCommand();// 存在更新
                    // 标记错误信息
                    markerErrorAction.Invoke(storageable, pageItems, rows);
                });
            });
            return stream;
        }
    }
}
Admin.NET/FZCZTB.TSCL.Application/Service/ADPenalty/ADPenaltyService.cs
@@ -92,9 +92,7 @@
    {
        var entity = input.Adapt<ADPenalty>();
        await _aDPenaltyRep.AsUpdateable(entity)
        .IgnoreColumns(u => new {
            u.Url,
        })
        .ExecuteCommandAsync();
    }
Admin.NET/FZCZTB.TSCL.Application/Service/ADPenalty/Dto/ADPenaltyInput.cs
@@ -46,7 +46,12 @@
    /// 采购监督部门名称
    /// </summary>
    public virtual string? SupervisionDepartment { get; set; }
    /// <summary>
    /// 线上地址
    /// </summary>
    public string? Url { get; set; }
}
/// <summary>
@@ -113,7 +118,11 @@
    /// </summary>
    [MaxLength(255, ErrorMessage = "采购监督部门名称字符长度不能超过255")]
    public string? SupervisionDepartment { get; set; }
    /// <summary>
    /// 线上地址
    /// </summary>
    public string? Url { get; set; }
}
/// <summary>
@@ -167,7 +176,10 @@
    /// </summary>    
    [MaxLength(255, ErrorMessage = "采购监督部门名称字符长度不能超过255")]
    public string? SupervisionDepartment { get; set; }
    /// <summary>
    /// 线上地址
    /// </summary>
    public string? Url { get; set; }
}
/// <summary>
Web/src/api/Customer/fBS_Customer.ts
New file
@@ -0,0 +1,122 @@
import {useBaseApi} from '/@/api/base';
// 客户表接口服务
export const useFBS_CustomerApi = () => {
    const baseApi = useBaseApi("fBS_Customer");
    return {
        // 分页查询客户表
        page: baseApi.page,
        // 查看客户表详细
        detail: baseApi.detail,
        // 新增客户表
        add: baseApi.add,
        // 更新客户表
        update: baseApi.update,
        // 设置客户表状态
        setStatus: baseApi.setStatus,
        // 删除客户表
        delete: baseApi.delete,
        // 批量删除客户表
        batchDelete: baseApi.batchDelete,
        // 导出客户表数据
        exportData: baseApi.exportData,
        // 导入客户表数据
        importData: baseApi.importData,
        // 下载客户表数据导入模板
        downloadTemplate: baseApi.downloadTemplate,
    }
}
// 客户表实体
export interface FBS_Customer {
    // 主键Id
    id: number;
    // 账号
    account?: string;
    // 密码
    password?: string;
    // 真实姓名
    realName?: string;
    // 昵称
    nickName: string;
    // 头像
    avatar: string;
    // 性别
    sex?: number;
    // 年龄
    age?: number;
    // 出生日期
    birthday: string;
    // 民族
    nation: string;
    // 手机号码
    phone: string;
    // 证件类型
    cardType?: number;
    // 身份证号
    idCardNum: string;
    // 身份证
    idCardPath: string;
    // 邮箱
    email: string;
    // 地址
    address: string;
    // 文化程度
    cultureLevel?: number;
    // 政治面貌
    politicalOutlook: string;
    // 毕业院校
    college: string;
    // 办公电话
    officePhone: string;
    // 紧急联系人
    emergencyContact: string;
    // 紧急联系人电话
    emergencyPhone: string;
    // 紧急联系人地址
    emergencyAddress: string;
    // 个人简介
    introduction: string;
    // 排序
    orderNo?: number;
    // 状态
    status?: number;
    // 备注
    remark: string;
    // 职级
    posLevel: string;
    // 职称
    posTitle: string;
    // 擅长领域
    expertise: string;
    // 办公区域
    officeZone: string;
    // 办公室
    office: string;
    // 入职日期
    joinDate: string;
    // 最新登录Ip
    lastLoginIp: string;
    // 最新登录地点
    lastLoginAddress: string;
    // 最新登录时间
    lastLoginTime: string;
    // 最新登录设备
    lastLoginDevice: string;
    // 电子签名
    signature: string;
    // 租户Id
    tenantId: number;
    // 创建时间
    createTime: string;
    // 更新时间
    updateTime: string;
    // 创建者Id
    createUserId: number;
    // 创建者姓名
    createUserName: string;
    // 修改者Id
    updateUserId: number;
    // 修改者姓名
    updateUserName: string;
}
Web/src/api/Customer/fBS_ExRole.ts
New file
@@ -0,0 +1,60 @@
import {useBaseApi} from '/@/api/base';
// 客户主分类角色接口服务
export const useFBS_ExRoleApi = () => {
    const baseApi = useBaseApi("fBS_ExRole");
    return {
        // 分页查询客户主分类角色
        page: baseApi.page,
        // 查看客户主分类角色详细
        detail: baseApi.detail,
        // 新增客户主分类角色
        add: baseApi.add,
        // 更新客户主分类角色
        update: baseApi.update,
        // 设置客户主分类角色状态
        setStatus: baseApi.setStatus,
        // 删除客户主分类角色
        delete: baseApi.delete,
        // 批量删除客户主分类角色
        batchDelete: baseApi.batchDelete,
        // 导出客户主分类角色数据
        exportData: baseApi.exportData,
        // 导入客户主分类角色数据
        importData: baseApi.importData,
        // 下载客户主分类角色数据导入模板
        downloadTemplate: baseApi.downloadTemplate,
    }
}
// 客户主分类角色实体
export interface FBS_ExRole {
    // 主键Id
    id: number;
    // 名称
    name?: string;
    // 编码
    code: string;
    // 排序
    orderNo?: number;
    // 数据范围
    dataScope?: number;
    // 备注
    remark: string;
    // 状态
    status?: number;
    // 租户Id
    tenantId: number;
    // 创建时间
    createTime: string;
    // 更新时间
    updateTime: string;
    // 创建者Id
    createUserId: number;
    // 创建者姓名
    createUserName: string;
    // 修改者Id
    updateUserId: number;
    // 修改者姓名
    updateUserName: string;
}
Web/src/api/Customer/fBS_Menu.ts
New file
@@ -0,0 +1,82 @@
import {useBaseApi} from '/@/api/base';
// 客户系统菜单表接口服务
export const useFBS_MenuApi = () => {
    const baseApi = useBaseApi("fBS_Menu");
    return {
        // 分页查询客户系统菜单表
        page: baseApi.page,
        // 查看客户系统菜单表详细
        detail: baseApi.detail,
        // 新增客户系统菜单表
        add: baseApi.add,
        // 更新客户系统菜单表
        update: baseApi.update,
        // 设置客户系统菜单表状态
        setStatus: baseApi.setStatus,
        // 删除客户系统菜单表
        delete: baseApi.delete,
        // 批量删除客户系统菜单表
        batchDelete: baseApi.batchDelete,
        // 导出客户系统菜单表数据
        exportData: baseApi.exportData,
        // 导入客户系统菜单表数据
        importData: baseApi.importData,
        // 下载客户系统菜单表数据导入模板
        downloadTemplate: baseApi.downloadTemplate,
    }
}
// 客户系统菜单表实体
export interface FBS_Menu {
    // 主键Id
    id: number;
    // 父Id
    pid?: number;
    // 菜单类型
    type?: number;
    // 路由名称
    name: string;
    // 路由地址
    path: string;
    // 组件路径
    component: string;
    // 重定向
    redirect: string;
    // 权限标识
    permission: string;
    // 菜单名称
    title?: string;
    // 图标
    icon: string;
    // 是否内嵌
    isIframe?: boolean;
    // 外链链接
    outLink: string;
    // 是否隐藏
    isHide?: boolean;
    // 是否缓存
    isKeepAlive?: boolean;
    // 是否固定
    isAffix?: boolean;
    // 排序
    orderNo?: number;
    // 状态
    status?: number;
    // 备注
    remark: string;
    // 租户Id
    tenantId: number;
    // 创建时间
    createTime: string;
    // 更新时间
    updateTime: string;
    // 创建者Id
    createUserId: number;
    // 创建者姓名
    createUserName: string;
    // 修改者Id
    updateUserId: number;
    // 修改者姓名
    updateUserName: string;
}
Web/src/api/Customer/fBS_Role.ts
New file
@@ -0,0 +1,60 @@
import {useBaseApi} from '/@/api/base';
// 客户角色接口服务
export const useFBS_RoleApi = () => {
    const baseApi = useBaseApi("fBS_Role");
    return {
        // 分页查询客户角色
        page: baseApi.page,
        // 查看客户角色详细
        detail: baseApi.detail,
        // 新增客户角色
        add: baseApi.add,
        // 更新客户角色
        update: baseApi.update,
        // 设置客户角色状态
        setStatus: baseApi.setStatus,
        // 删除客户角色
        delete: baseApi.delete,
        // 批量删除客户角色
        batchDelete: baseApi.batchDelete,
        // 导出客户角色数据
        exportData: baseApi.exportData,
        // 导入客户角色数据
        importData: baseApi.importData,
        // 下载客户角色数据导入模板
        downloadTemplate: baseApi.downloadTemplate,
    }
}
// 客户角色实体
export interface FBS_Role {
    // 主键Id
    id: number;
    // 名称
    name: string;
    // 编码
    code: string;
    // 排序
    orderNo: number;
    // 数据范围
    dataScope: number;
    // 备注
    remark: string;
    // 状态
    status: number;
    // 租户Id
    tenantId: number;
    // 创建时间
    createTime: string;
    // 更新时间
    updateTime: string;
    // 创建者Id
    createUserId: number;
    // 创建者姓名
    createUserName: string;
    // 修改者Id
    updateUserId: number;
    // 修改者姓名
    updateUserName: string;
}
Web/src/api/Customer/fB_Customer.ts
New file
@@ -0,0 +1,122 @@
import {useBaseApi} from '/@/api/base';
// 客户表接口服务
export const useFB_CustomerApi = () => {
    const baseApi = useBaseApi("fB_Customer");
    return {
        // 分页查询客户表
        page: baseApi.page,
        // 查看客户表详细
        detail: baseApi.detail,
        // 新增客户表
        add: baseApi.add,
        // 更新客户表
        update: baseApi.update,
        // 设置客户表状态
        setStatus: baseApi.setStatus,
        // 删除客户表
        delete: baseApi.delete,
        // 批量删除客户表
        batchDelete: baseApi.batchDelete,
        // 导出客户表数据
        exportData: baseApi.exportData,
        // 导入客户表数据
        importData: baseApi.importData,
        // 下载客户表数据导入模板
        downloadTemplate: baseApi.downloadTemplate,
    }
}
// 客户表实体
export interface FB_Customer {
    // 主键Id
    id: number;
    // 账号
    account?: string;
    // 密码
    password?: string;
    // 真实姓名
    realName?: string;
    // 昵称
    nickName: string;
    // 头像
    avatar: string;
    // 性别
    sex?: number;
    // 年龄
    age?: number;
    // 出生日期
    birthday: string;
    // 民族
    nation: string;
    // 手机号码
    phone: string;
    // 证件类型
    cardType?: number;
    // 身份证号
    idCardNum: string;
    // 身份证
    idCardPath: string;
    // 邮箱
    email: string;
    // 地址
    address: string;
    // 文化程度
    cultureLevel?: number;
    // 政治面貌
    politicalOutlook: string;
    // 毕业院校
    college: string;
    // 办公电话
    officePhone: string;
    // 紧急联系人
    emergencyContact: string;
    // 紧急联系人电话
    emergencyPhone: string;
    // 紧急联系人地址
    emergencyAddress: string;
    // 个人简介
    introduction: string;
    // 排序
    orderNo?: number;
    // 状态
    status?: number;
    // 备注
    remark: string;
    // 职级
    posLevel: string;
    // 职称
    posTitle: string;
    // 擅长领域
    expertise: string;
    // 办公区域
    officeZone: string;
    // 办公室
    office: string;
    // 入职日期
    joinDate: string;
    // 最新登录Ip
    lastLoginIp: string;
    // 最新登录地点
    lastLoginAddress: string;
    // 最新登录时间
    lastLoginTime: string;
    // 最新登录设备
    lastLoginDevice: string;
    // 电子签名
    signature: string;
    // 租户Id
    tenantId: number;
    // 创建时间
    createTime: string;
    // 更新时间
    updateTime: string;
    // 创建者Id
    createUserId: number;
    // 创建者姓名
    createUserName: string;
    // 修改者Id
    updateUserId: number;
    // 修改者姓名
    updateUserName: string;
}
Web/src/api/Customer/fB_CustomerRole.ts
New file
@@ -0,0 +1,36 @@
import {useBaseApi} from '/@/api/base';
// 客户菜单表接口服务
export const useFB_CustomerRoleApi = () => {
    const baseApi = useBaseApi("fB_CustomerRole");
    return {
        // 分页查询客户菜单表
        page: baseApi.page,
        // 查看客户菜单表详细
        detail: baseApi.detail,
        // 新增客户菜单表
        add: baseApi.add,
        // 更新客户菜单表
        update: baseApi.update,
        // 删除客户菜单表
        delete: baseApi.delete,
        // 批量删除客户菜单表
        batchDelete: baseApi.batchDelete,
        // 导出客户菜单表数据
        exportData: baseApi.exportData,
        // 导入客户菜单表数据
        importData: baseApi.importData,
        // 下载客户菜单表数据导入模板
        downloadTemplate: baseApi.downloadTemplate,
    }
}
// 客户菜单表实体
export interface FB_CustomerRole {
    // 主键Id
    id: number;
    // 用户Id
    cutomerId?: number;
    // 角色Id
    roleId?: number;
}
Web/src/views/Customer/fBS_Customer/component/editDialog.vue
New file
@@ -0,0 +1,240 @@
<script lang="ts" name="fBS_Customer" setup>
import { ref, reactive, onMounted } from "vue";
import { ElMessage } from "element-plus";
import type { FormRules } from "element-plus";
import { formatDate } from '/@/utils/formatTime';
import { useFBS_CustomerApi } from '/@/api/Customer/fBS_Customer';
//父级传递来的函数,用于回调
const emit = defineEmits(["reloadTable"]);
const fBS_CustomerApi = useFBS_CustomerApi();
const ruleFormRef = ref();
const state = reactive({
    title: '',
    loading: false,
    showDialog: false,
    ruleForm: {} as any,
    stores: {},
    dropdownData: {} as any,
});
// 自行添加其他规则
const rules = ref<FormRules>({
  account: [{required: true, message: '请选择账号!', trigger: 'blur',},],
  password: [{required: true, message: '请选择密码!', trigger: 'blur',},],
  realName: [{required: true, message: '请选择真实姓名!', trigger: 'blur',},],
  sex: [{required: true, message: '请选择性别!', trigger: 'change',},],
  age: [{required: true, message: '请选择年龄!', trigger: 'blur',},],
  cardType: [{required: true, message: '请选择证件类型!', trigger: 'change',},],
  cultureLevel: [{required: true, message: '请选择文化程度!', trigger: 'change',},],
  orderNo: [{required: true, message: '请选择排序!', trigger: 'blur',},],
  status: [{required: true, message: '请选择状态!', trigger: 'change',},],
});
// 页面加载时
onMounted(async () => {
});
// 打开弹窗
const openDialog = async (row: any, title: string) => {
    state.title = title;
    row = row ?? { status: 1,orderNo: 100, };
    state.ruleForm = row.id ? await fBS_CustomerApi.detail(row.id).then(res => res.data.result) : JSON.parse(JSON.stringify(row));
    state.showDialog = true;
};
// 关闭弹窗
const closeDialog = () => {
    emit("reloadTable");
    state.showDialog = false;
};
// 提交
const submit = async () => {
    ruleFormRef.value.validate(async (isValid: boolean, fields?: any) => {
        if (isValid) {
            let values = state.ruleForm;
            await fBS_CustomerApi[state.ruleForm.id ? 'update' : 'add'](values);
            closeDialog();
        } else {
            ElMessage({
                message: `表单有${Object.keys(fields).length}处验证失败,请修改后再提交`,
                type: "error",
            });
        }
    });
};
//将属性或者函数暴露给父组件
defineExpose({ openDialog });
</script>
<template>
    <div class="fBS_Customer-container">
        <el-dialog v-model="state.showDialog" :width="800" draggable :close-on-click-modal="false">
            <template #header>
                <div style="color: #fff">
                    <span>{{ state.title }}</span>
                </div>
            </template>
            <el-form :model="state.ruleForm" ref="ruleFormRef" label-width="auto" :rules="rules">
                <el-row :gutter="35">
                    <el-form-item v-show="false">
                        <el-input v-model="state.ruleForm.id" />
                    </el-form-item>
                    <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20" >
                        <el-form-item label="账号" prop="account">
                            <el-input v-model="state.ruleForm.account" placeholder="请输入账号" maxlength="32" show-word-limit 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="password">
                            <el-input v-model="state.ruleForm.password" placeholder="请输入密码" maxlength="512" show-word-limit 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="realName">
                            <el-input v-model="state.ruleForm.realName" placeholder="请输入真实姓名" maxlength="32" show-word-limit 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="nickName">
                            <el-input v-model="state.ruleForm.nickName" placeholder="请输入昵称" maxlength="32" show-word-limit 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="avatar">
                            <el-input v-model="state.ruleForm.avatar" placeholder="请输入头像" maxlength="512" show-word-limit 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="sex">
                            <g-sys-dict v-model="state.ruleForm.sex" code="GenderEnum" render-as="select" placeholder="请选择性别" clearable filterable />
                        </el-form-item>
                    </el-col>
                    <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20" >
                        <el-form-item label="年龄" prop="age">
                            <el-input-number v-model="state.ruleForm.age" 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="birthday">
                            <el-date-picker v-model="state.ruleForm.birthday" type="date" placeholder="出生日期" />
                        </el-form-item>
                    </el-col>
                    <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20" >
                        <el-form-item label="民族" prop="nation">
                            <el-input v-model="state.ruleForm.nation" placeholder="请输入民族" maxlength="32" show-word-limit 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="phone">
                            <el-input v-model="state.ruleForm.phone" placeholder="请输入手机号码" maxlength="16" show-word-limit 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="cardType">
                            <g-sys-dict v-model="state.ruleForm.cardType" code="CardTypeEnum" render-as="select" placeholder="请选择证件类型" clearable filterable />
                        </el-form-item>
                    </el-col>
                    <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20" >
                        <el-form-item label="身份证号" prop="idCardNum">
                            <el-input v-model="state.ruleForm.idCardNum" placeholder="请输入身份证号" maxlength="32" show-word-limit 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="idCardPath">
                            <el-input v-model="state.ruleForm.idCardPath" placeholder="请输入身份证" maxlength="512" show-word-limit 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="email">
                            <el-input v-model="state.ruleForm.email" placeholder="请输入邮箱" maxlength="64" show-word-limit 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="address">
                            <el-input v-model="state.ruleForm.address" placeholder="请输入地址" maxlength="256" show-word-limit 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="cultureLevel">
                            <g-sys-dict v-model="state.ruleForm.cultureLevel" code="CultureLevelEnum" render-as="select" placeholder="请选择文化程度" clearable filterable />
                        </el-form-item>
                    </el-col>
                    <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20" >
                        <el-form-item label="政治面貌" prop="politicalOutlook">
                            <el-input v-model="state.ruleForm.politicalOutlook" placeholder="请输入政治面貌" maxlength="16" show-word-limit 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="college">
                            <el-input v-model="state.ruleForm.college" placeholder="请输入毕业院校" maxlength="128" show-word-limit 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="officePhone">
                            <el-input v-model="state.ruleForm.officePhone" placeholder="请输入办公电话" maxlength="16" show-word-limit 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="emergencyContact">
                            <el-input v-model="state.ruleForm.emergencyContact" placeholder="请输入紧急联系人" maxlength="32" show-word-limit 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="emergencyPhone">
                            <el-input v-model="state.ruleForm.emergencyPhone" placeholder="请输入紧急联系人电话" maxlength="16" show-word-limit 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="emergencyAddress">
                            <el-input v-model="state.ruleForm.emergencyAddress" placeholder="请输入紧急联系人地址" maxlength="256" show-word-limit 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="introduction">
                            <el-input v-model="state.ruleForm.introduction" placeholder="请输入个人简介" maxlength="512" show-word-limit 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="orderNo">
                            <el-input-number v-model="state.ruleForm.orderNo" placeholder="请输入排序" clearable />
                        </el-form-item>
                    </el-col>
                    <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20" v-if="state.ruleForm.id" >
                        <el-form-item label="状态" prop="status">
                            <g-sys-dict v-model="state.ruleForm.status" code="StatusEnum" render-as="select" placeholder="请选择状态" clearable filterable />
                        </el-form-item>
                    </el-col>
                    <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20" >
                        <el-form-item label="备注" prop="remark">
                            <el-input v-model="state.ruleForm.remark" placeholder="请输入备注" maxlength="256" show-word-limit 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="posLevel">
                            <el-input v-model="state.ruleForm.posLevel" placeholder="请输入职级" maxlength="32" show-word-limit 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="posTitle">
                            <el-input v-model="state.ruleForm.posTitle" placeholder="请输入职称" maxlength="32" show-word-limit clearable />
                        </el-form-item>
                    </el-col>
                </el-row>
            </el-form>
            <template #footer>
                <span class="dialog-footer">
                    <el-button @click="() => state.showDialog = false">取 消</el-button>
                    <el-button @click="submit" type="primary" v-reclick="1000">确 定</el-button>
                </span>
            </template>
        </el-dialog>
    </div>
</template>
<style lang="scss" scoped>
:deep(.el-select), :deep(.el-input-number) {
  width: 100%;
}
</style>
Web/src/views/Customer/fBS_Customer/index.vue
New file
@@ -0,0 +1,310 @@
<script lang="ts" setup name="fBS_Customer">
import { ref, reactive, onMounted } from "vue";
import { auth } from '/@/utils/authFunction';
import { ElMessageBox, ElMessage } from "element-plus";
import { downloadStreamFile } from "/@/utils/download";
import { useFBS_CustomerApi } from '/@/api/Customer/fBS_Customer';
import editDialog from '/@/views/Customer/fBS_Customer/component/editDialog.vue'
import printDialog from '/@/views/system/print/component/hiprint/preview.vue'
import ModifyRecord from '/@/components/table/modifyRecord.vue';
import ImportData from "/@/components/table/importData.vue";
const fBS_CustomerApi = useFBS_CustomerApi();
const printDialogRef = ref();
const editDialogRef = ref();
const importDataRef = ref();
const state = reactive({
  exportLoading: false,
  tableLoading: false,
  stores: {},
  showAdvanceQueryUI: false,
  dropdownData: {} as any,
  selectData: [] as any[],
  tableQueryParams: {} as any,
  tableParams: {
    page: 1,
    pageSize: 20,
    total: 0,
    field: 'createTime', // 默认的排序字段
    order: 'descending', // 排序方向
    descStr: 'descending', // 降序排序的关键字符
  },
  tableData: [],
});
// 页面加载时
onMounted(async () => {
});
// 查询操作
const handleQuery = async (params: any = {}) => {
  state.tableLoading = true;
  state.tableParams = Object.assign(state.tableParams, params);
  const result = await fBS_CustomerApi.page(Object.assign(state.tableQueryParams, state.tableParams)).then(res => res.data.result);
  state.tableParams.total = result?.total;
  state.tableData = result?.items ?? [];
  state.tableLoading = false;
};
// 列排序
const sortChange = async (column: any) => {
  state.tableParams.field = column.prop;
  state.tableParams.order = column.order;
  await handleQuery();
};
// 删除
const delFBS_Customer = (row: any) => {
  ElMessageBox.confirm(`确定要删除吗?`, "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning",
  }).then(async () => {
    await fBS_CustomerApi.delete({ id: row.id });
    handleQuery();
    ElMessage.success("删除成功");
  }).catch(() => {});
};
// 批量删除
const batchDelFBS_Customer = () => {
  ElMessageBox.confirm(`确定要删除${state.selectData.length}条记录吗?`, "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning",
  }).then(async () => {
    await fBS_CustomerApi.batchDelete(state.selectData.map(u => ({ id: u.id }) )).then(res => {
      ElMessage.success(`成功批量删除${res.data.result}条记录`);
      handleQuery();
    });
  }).catch(() => {});
};
// 设置状态
const changeFBS_CustomerStatus = async (row: any) => {
  await fBS_CustomerApi.setStatus({ id: row.id, status: row.status }).then(() => ElMessage.success('状态设置成功'));
};
// 导出数据
const exportFBS_CustomerCommand = async (command: string) => {
  try {
    state.exportLoading = true;
    if (command === 'select') {
      const params = Object.assign({}, state.tableQueryParams, state.tableParams, { selectKeyList: state.selectData.map(u => u.id) });
      await fBS_CustomerApi.exportData(params).then(res => downloadStreamFile(res));
    } else if (command === 'current') {
      const params = Object.assign({}, state.tableQueryParams, state.tableParams);
      await fBS_CustomerApi.exportData(params).then(res => downloadStreamFile(res));
    } else if (command === 'all') {
      const params = Object.assign({}, state.tableQueryParams, state.tableParams, { page: 1, pageSize: 99999999 });
      await fBS_CustomerApi.exportData(params).then(res => downloadStreamFile(res));
    }
  } finally {
    state.exportLoading = false;
  }
}
handleQuery();
</script>
<template>
  <div class="fBS_Customer-container" v-loading="state.exportLoading">
    <el-card shadow="hover" :body-style="{ paddingBottom: '0' }">
      <el-form :model="state.tableQueryParams" ref="queryForm" labelWidth="90">
        <el-row>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10">
            <el-form-item label="关键字">
              <el-input v-model="state.tableQueryParams.keyword" clearable placeholder="请输入模糊查询关键字"/>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="账号">
              <el-input v-model="state.tableQueryParams.account" clearable placeholder="请输入账号"/>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="真实姓名">
              <el-input v-model="state.tableQueryParams.realName" clearable placeholder="请输入真实姓名"/>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="昵称">
              <el-input v-model="state.tableQueryParams.nickName" clearable placeholder="请输入昵称"/>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="证件类型">
              <g-sys-dict v-model="state.tableQueryParams.cardType" code="CardTypeEnum" render-as="select" placeholder="请选择证件类型" clearable filterable />
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="身份证">
              <el-input v-model="state.tableQueryParams.idCardPath" clearable placeholder="请输入身份证"/>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="文化程度">
              <g-sys-dict v-model="state.tableQueryParams.cultureLevel" code="CultureLevelEnum" render-as="select" placeholder="请选择文化程度" clearable filterable />
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="毕业院校">
              <el-input v-model="state.tableQueryParams.college" clearable placeholder="请输入毕业院校"/>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="办公电话">
              <el-input v-model="state.tableQueryParams.officePhone" clearable placeholder="请输入办公电话"/>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="紧急联系人">
              <el-input v-model="state.tableQueryParams.emergencyContact" clearable placeholder="请输入紧急联系人"/>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="紧急联系人电话">
              <el-input v-model="state.tableQueryParams.emergencyPhone" clearable placeholder="请输入紧急联系人电话"/>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="紧急联系人地址">
              <el-input v-model="state.tableQueryParams.emergencyAddress" clearable placeholder="请输入紧急联系人地址"/>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="个人简介">
              <el-input v-model="state.tableQueryParams.introduction" clearable placeholder="请输入个人简介"/>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="排序">
              <el-input-number v-model="state.tableQueryParams.orderNo"  clearable placeholder="请输入排序"/>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="状态">
              <g-sys-dict v-model="state.tableQueryParams.status" code="StatusEnum" render-as="select" placeholder="请选择状态" clearable filterable />
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="备注">
              <el-input v-model="state.tableQueryParams.remark" clearable placeholder="请输入备注"/>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="职级">
              <el-input v-model="state.tableQueryParams.posLevel" clearable placeholder="请输入职级"/>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="职称">
              <el-input v-model="state.tableQueryParams.posTitle" clearable placeholder="请输入职称"/>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10">
            <el-form-item >
              <el-button-group style="display: flex; align-items: center;">
                <el-button type="primary"  icon="ele-Search" @click="handleQuery" v-auth="'fBS_Customer:page'" v-reclick="1000"> 查询 </el-button>
                <el-button icon="ele-Refresh" @click="() => state.tableQueryParams = {}"> 重置 </el-button>
                <el-button icon="ele-ZoomIn" @click="() => state.showAdvanceQueryUI = true" v-if="!state.showAdvanceQueryUI" style="margin-left:5px;"> 高级查询 </el-button>
                <el-button icon="ele-ZoomOut" @click="() => state.showAdvanceQueryUI = false" v-if="state.showAdvanceQueryUI" style="margin-left:5px;"> 隐藏 </el-button>
                <el-button type="danger" style="margin-left:5px;" icon="ele-Delete" @click="batchDelFBS_Customer" :disabled="state.selectData.length == 0" v-auth="'fBS_Customer:batchDelete'"> 删除 </el-button>
                <el-button type="primary" style="margin-left:5px;" icon="ele-Plus" @click="editDialogRef.openDialog(null, '新增客户表')" v-auth="'fBS_Customer:add'"> 新增 </el-button>
                <el-dropdown :show-timeout="70" :hide-timeout="50" @command="exportFBS_CustomerCommand">
                  <el-button type="primary" style="margin-left:5px;" icon="ele-FolderOpened" v-reclick="20000" v-auth="'fBS_Customer:export'"> 导出 </el-button>
                  <template #dropdown>
                    <el-dropdown-menu>
                      <el-dropdown-item command="select" :disabled="state.selectData.length == 0">导出选中</el-dropdown-item>
                      <el-dropdown-item command="current">导出本页</el-dropdown-item>
                      <el-dropdown-item command="all">导出全部</el-dropdown-item>
                    </el-dropdown-menu>
                  </template>
                </el-dropdown>
                <el-button type="warning" style="margin-left:5px;" icon="ele-MostlyCloudy" @click="importDataRef.openDialog()" v-auth="'fBS_Customer:import'"> 导入 </el-button>
              </el-button-group>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
    </el-card>
    <el-card class="full-table" shadow="hover" style="margin-top: 5px">
      <el-table :data="state.tableData" @selection-change="(val: any[]) => { state.selectData = val; }" style="width: 100%" v-loading="state.tableLoading" tooltip-effect="light" row-key="id" @sort-change="sortChange" border>
        <el-table-column type="selection" width="40" align="center" v-if="auth('fBS_Customer:batchDelete') || auth('fBS_Customer:export')" />
        <el-table-column type="index" label="序号" width="55" align="center"/>
        <el-table-column prop='account' label='账号' sortable='custom' show-overflow-tooltip />
        <el-table-column prop='password' label='密码' show-overflow-tooltip />
        <el-table-column prop='realName' label='真实姓名' sortable='custom' show-overflow-tooltip />
        <el-table-column prop='nickName' label='昵称' sortable='custom' show-overflow-tooltip />
        <el-table-column prop='avatar' label='头像' show-overflow-tooltip />
        <el-table-column prop='sex' label='性别' show-overflow-tooltip>
          <template #default="scope">
            <g-sys-dict v-model="scope.row.sex" code="GenderEnum" />
          </template>
        </el-table-column>
        <el-table-column prop='age' label='年龄' show-overflow-tooltip />
        <el-table-column prop='birthday' label='出生日期' show-overflow-tooltip />
        <el-table-column prop='nation' label='民族' show-overflow-tooltip />
        <el-table-column prop='phone' label='手机号码' show-overflow-tooltip />
        <el-table-column prop='cardType' label='证件类型' show-overflow-tooltip>
          <template #default="scope">
            <g-sys-dict v-model="scope.row.cardType" code="CardTypeEnum" />
          </template>
        </el-table-column>
        <el-table-column prop='idCardNum' label='身份证号' show-overflow-tooltip />
        <el-table-column prop='idCardPath' label='身份证' show-overflow-tooltip />
        <el-table-column prop='email' label='邮箱' show-overflow-tooltip />
        <el-table-column prop='address' label='地址' show-overflow-tooltip />
        <el-table-column prop='cultureLevel' label='文化程度' show-overflow-tooltip>
          <template #default="scope">
            <g-sys-dict v-model="scope.row.cultureLevel" code="CultureLevelEnum" />
          </template>
        </el-table-column>
        <el-table-column prop='politicalOutlook' label='政治面貌' show-overflow-tooltip />
        <el-table-column prop='college' label='毕业院校' show-overflow-tooltip />
        <el-table-column prop='officePhone' label='办公电话' show-overflow-tooltip />
        <el-table-column prop='emergencyContact' label='紧急联系人' show-overflow-tooltip />
        <el-table-column prop='emergencyPhone' label='紧急联系人电话' show-overflow-tooltip />
        <el-table-column prop='emergencyAddress' label='紧急联系人地址' show-overflow-tooltip />
        <el-table-column prop='introduction' label='个人简介' show-overflow-tooltip />
        <el-table-column prop='orderNo' label='排序' show-overflow-tooltip />
        <el-table-column prop='status' label='状态' v-auth="'fBS_Customer:setStatus'" show-overflow-tooltip>
          <template #default="scope">
            <el-switch v-model="scope.row.status" :active-value="1" :inactive-value="2" size="small" @change="changeFBS_CustomerStatus(scope.row)" />
          </template>
        </el-table-column>
        <el-table-column prop='remark' label='备注' show-overflow-tooltip />
        <el-table-column prop='posLevel' label='职级' show-overflow-tooltip />
        <el-table-column prop='posTitle' label='职称' show-overflow-tooltip />
        <el-table-column label="修改记录" width="100" align="center" show-overflow-tooltip>
          <template #default="scope">
            <ModifyRecord :data="scope.row" />
          </template>
        </el-table-column>
        <el-table-column label="操作" width="140" align="center" fixed="right" show-overflow-tooltip v-if="auth('fBS_Customer:update') || auth('fBS_Customer:delete')">
          <template #default="scope">
            <el-button icon="ele-Edit" size="small" text type="primary" @click="editDialogRef.openDialog(scope.row, '编辑客户表')" v-auth="'fBS_Customer:update'"> 编辑 </el-button>
            <el-button icon="ele-Delete" size="small" text type="primary" @click="delFBS_Customer(scope.row)" v-auth="'fBS_Customer:delete'"> 删除 </el-button>
          </template>
        </el-table-column>
      </el-table>
      <el-pagination
              v-model:currentPage="state.tableParams.page"
              v-model:page-size="state.tableParams.pageSize"
              @size-change="(val: any) => handleQuery({ pageSize: val })"
              @current-change="(val: any) => handleQuery({ page: val })"
              layout="total, sizes, prev, pager, next, jumper"
              :page-sizes="[10, 20, 50, 100, 200, 500]"
              :total="state.tableParams.total"
              size="small"
              background />
      <ImportData ref="importDataRef" :import="fBS_CustomerApi.importData" :download="fBS_CustomerApi.downloadTemplate" v-auth="'fBS_Customer:import'" @refresh="handleQuery"/>
      <printDialog ref="printDialogRef" :title="'打印客户表'" @reloadTable="handleQuery" />
      <editDialog ref="editDialogRef" @reloadTable="handleQuery" />
    </el-card>
  </div>
</template>
<style scoped>
:deep(.el-input), :deep(.el-select), :deep(.el-input-number) {
  width: 100%;
}
</style>
Web/src/views/Customer/fBS_ExRole/component/editDialog.vue
New file
@@ -0,0 +1,125 @@
<script lang="ts" name="fBS_ExRole" setup>
import { ref, reactive, onMounted } from "vue";
import { ElMessage } from "element-plus";
import type { FormRules } from "element-plus";
import { formatDate } from '/@/utils/formatTime';
import { useFBS_ExRoleApi } from '/@/api/Customer/fBS_ExRole';
//父级传递来的函数,用于回调
const emit = defineEmits(["reloadTable"]);
const fBS_ExRoleApi = useFBS_ExRoleApi();
const ruleFormRef = ref();
const state = reactive({
    title: '',
    loading: false,
    showDialog: false,
    ruleForm: {} as any,
    stores: {},
    dropdownData: {} as any,
});
// 自行添加其他规则
const rules = ref<FormRules>({
  name: [{required: true, message: '请选择名称!', trigger: 'blur',},],
  orderNo: [{required: true, message: '请选择排序!', trigger: 'blur',},],
  dataScope: [{required: true, message: '请选择数据范围!', trigger: 'change',},],
  status: [{required: true, message: '请选择状态!', trigger: 'change',},],
});
// 页面加载时
onMounted(async () => {
});
// 打开弹窗
const openDialog = async (row: any, title: string) => {
    state.title = title;
    row = row ?? { status: 1,orderNo: 100, };
    state.ruleForm = row.id ? await fBS_ExRoleApi.detail(row.id).then(res => res.data.result) : JSON.parse(JSON.stringify(row));
    state.showDialog = true;
};
// 关闭弹窗
const closeDialog = () => {
    emit("reloadTable");
    state.showDialog = false;
};
// 提交
const submit = async () => {
    ruleFormRef.value.validate(async (isValid: boolean, fields?: any) => {
        if (isValid) {
            let values = state.ruleForm;
            await fBS_ExRoleApi[state.ruleForm.id ? 'update' : 'add'](values);
            closeDialog();
        } else {
            ElMessage({
                message: `表单有${Object.keys(fields).length}处验证失败,请修改后再提交`,
                type: "error",
            });
        }
    });
};
//将属性或者函数暴露给父组件
defineExpose({ openDialog });
</script>
<template>
    <div class="fBS_ExRole-container">
        <el-dialog v-model="state.showDialog" :width="800" draggable :close-on-click-modal="false">
            <template #header>
                <div style="color: #fff">
                    <span>{{ state.title }}</span>
                </div>
            </template>
            <el-form :model="state.ruleForm" ref="ruleFormRef" label-width="auto" :rules="rules">
                <el-row :gutter="35">
                    <el-form-item v-show="false">
                        <el-input v-model="state.ruleForm.id" />
                    </el-form-item>
                    <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20" >
                        <el-form-item label="名称" prop="name">
                            <el-input v-model="state.ruleForm.name" placeholder="请输入名称" maxlength="64" show-word-limit 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="code">
                            <el-input v-model="state.ruleForm.code" placeholder="请输入编码" maxlength="64" show-word-limit 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="orderNo">
                            <el-input-number v-model="state.ruleForm.orderNo" 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="dataScope">
                            <g-sys-dict v-model="state.ruleForm.dataScope" code="DataScopeEnum" render-as="select" placeholder="请选择数据范围" clearable filterable />
                        </el-form-item>
                    </el-col>
                    <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20" >
                        <el-form-item label="备注" prop="remark">
                            <el-input v-model="state.ruleForm.remark" placeholder="请输入备注" maxlength="128" show-word-limit clearable />
                        </el-form-item>
                    </el-col>
                    <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20" v-if="state.ruleForm.id" >
                        <el-form-item label="状态" prop="status">
                            <g-sys-dict v-model="state.ruleForm.status" code="StatusEnum" render-as="select" placeholder="请选择状态" clearable filterable />
                        </el-form-item>
                    </el-col>
                </el-row>
            </el-form>
            <template #footer>
                <span class="dialog-footer">
                    <el-button @click="() => state.showDialog = false">取 消</el-button>
                    <el-button @click="submit" type="primary" v-reclick="1000">确 定</el-button>
                </span>
            </template>
        </el-dialog>
    </div>
</template>
<style lang="scss" scoped>
:deep(.el-select), :deep(.el-input-number) {
  width: 100%;
}
</style>
Web/src/views/Customer/fBS_ExRole/index.vue
New file
@@ -0,0 +1,225 @@
<script lang="ts" setup name="fBS_ExRole">
import { ref, reactive, onMounted } from "vue";
import { auth } from '/@/utils/authFunction';
import { ElMessageBox, ElMessage } from "element-plus";
import { downloadStreamFile } from "/@/utils/download";
import { useFBS_ExRoleApi } from '/@/api/Customer/fBS_ExRole';
import editDialog from '/@/views/Customer/fBS_ExRole/component/editDialog.vue'
import printDialog from '/@/views/system/print/component/hiprint/preview.vue'
import ModifyRecord from '/@/components/table/modifyRecord.vue';
import ImportData from "/@/components/table/importData.vue";
const fBS_ExRoleApi = useFBS_ExRoleApi();
const printDialogRef = ref();
const editDialogRef = ref();
const importDataRef = ref();
const state = reactive({
  exportLoading: false,
  tableLoading: false,
  stores: {},
  showAdvanceQueryUI: false,
  dropdownData: {} as any,
  selectData: [] as any[],
  tableQueryParams: {} as any,
  tableParams: {
    page: 1,
    pageSize: 20,
    total: 0,
    field: 'createTime', // 默认的排序字段
    order: 'descending', // 排序方向
    descStr: 'descending', // 降序排序的关键字符
  },
  tableData: [],
});
// 页面加载时
onMounted(async () => {
});
// 查询操作
const handleQuery = async (params: any = {}) => {
  state.tableLoading = true;
  state.tableParams = Object.assign(state.tableParams, params);
  const result = await fBS_ExRoleApi.page(Object.assign(state.tableQueryParams, state.tableParams)).then(res => res.data.result);
  state.tableParams.total = result?.total;
  state.tableData = result?.items ?? [];
  state.tableLoading = false;
};
// 列排序
const sortChange = async (column: any) => {
  state.tableParams.field = column.prop;
  state.tableParams.order = column.order;
  await handleQuery();
};
// 删除
const delFBS_ExRole = (row: any) => {
  ElMessageBox.confirm(`确定要删除吗?`, "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning",
  }).then(async () => {
    await fBS_ExRoleApi.delete({ id: row.id });
    handleQuery();
    ElMessage.success("删除成功");
  }).catch(() => {});
};
// 批量删除
const batchDelFBS_ExRole = () => {
  ElMessageBox.confirm(`确定要删除${state.selectData.length}条记录吗?`, "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning",
  }).then(async () => {
    await fBS_ExRoleApi.batchDelete(state.selectData.map(u => ({ id: u.id }) )).then(res => {
      ElMessage.success(`成功批量删除${res.data.result}条记录`);
      handleQuery();
    });
  }).catch(() => {});
};
// 设置状态
const changeFBS_ExRoleStatus = async (row: any) => {
  await fBS_ExRoleApi.setStatus({ id: row.id, status: row.status }).then(() => ElMessage.success('状态设置成功'));
};
// 导出数据
const exportFBS_ExRoleCommand = async (command: string) => {
  try {
    state.exportLoading = true;
    if (command === 'select') {
      const params = Object.assign({}, state.tableQueryParams, state.tableParams, { selectKeyList: state.selectData.map(u => u.id) });
      await fBS_ExRoleApi.exportData(params).then(res => downloadStreamFile(res));
    } else if (command === 'current') {
      const params = Object.assign({}, state.tableQueryParams, state.tableParams);
      await fBS_ExRoleApi.exportData(params).then(res => downloadStreamFile(res));
    } else if (command === 'all') {
      const params = Object.assign({}, state.tableQueryParams, state.tableParams, { page: 1, pageSize: 99999999 });
      await fBS_ExRoleApi.exportData(params).then(res => downloadStreamFile(res));
    }
  } finally {
    state.exportLoading = false;
  }
}
handleQuery();
</script>
<template>
  <div class="fBS_ExRole-container" v-loading="state.exportLoading">
    <el-card shadow="hover" :body-style="{ paddingBottom: '0' }">
      <el-form :model="state.tableQueryParams" ref="queryForm" labelWidth="90">
        <el-row>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10">
            <el-form-item label="关键字">
              <el-input v-model="state.tableQueryParams.keyword" clearable placeholder="请输入模糊查询关键字"/>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="名称">
              <el-input v-model="state.tableQueryParams.name" clearable placeholder="请输入名称"/>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="编码">
              <el-input v-model="state.tableQueryParams.code" clearable placeholder="请输入编码"/>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="排序">
              <el-input-number v-model="state.tableQueryParams.orderNo"  clearable placeholder="请输入排序"/>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="数据范围">
              <g-sys-dict v-model="state.tableQueryParams.dataScope" code="DataScopeEnum" render-as="select" placeholder="请选择数据范围" clearable filterable />
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="备注">
              <el-input v-model="state.tableQueryParams.remark" clearable placeholder="请输入备注"/>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="状态">
              <g-sys-dict v-model="state.tableQueryParams.status" code="StatusEnum" render-as="select" placeholder="请选择状态" clearable filterable />
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10">
            <el-form-item >
              <el-button-group style="display: flex; align-items: center;">
                <el-button type="primary"  icon="ele-Search" @click="handleQuery" v-auth="'fBS_ExRole:page'" v-reclick="1000"> 查询 </el-button>
                <el-button icon="ele-Refresh" @click="() => state.tableQueryParams = {}"> 重置 </el-button>
                <el-button icon="ele-ZoomIn" @click="() => state.showAdvanceQueryUI = true" v-if="!state.showAdvanceQueryUI" style="margin-left:5px;"> 高级查询 </el-button>
                <el-button icon="ele-ZoomOut" @click="() => state.showAdvanceQueryUI = false" v-if="state.showAdvanceQueryUI" style="margin-left:5px;"> 隐藏 </el-button>
                <el-button type="danger" style="margin-left:5px;" icon="ele-Delete" @click="batchDelFBS_ExRole" :disabled="state.selectData.length == 0" v-auth="'fBS_ExRole:batchDelete'"> 删除 </el-button>
                <el-button type="primary" style="margin-left:5px;" icon="ele-Plus" @click="editDialogRef.openDialog(null, '新增客户主分类角色')" v-auth="'fBS_ExRole:add'"> 新增 </el-button>
                <el-dropdown :show-timeout="70" :hide-timeout="50" @command="exportFBS_ExRoleCommand">
                  <el-button type="primary" style="margin-left:5px;" icon="ele-FolderOpened" v-reclick="20000" v-auth="'fBS_ExRole:export'"> 导出 </el-button>
                  <template #dropdown>
                    <el-dropdown-menu>
                      <el-dropdown-item command="select" :disabled="state.selectData.length == 0">导出选中</el-dropdown-item>
                      <el-dropdown-item command="current">导出本页</el-dropdown-item>
                      <el-dropdown-item command="all">导出全部</el-dropdown-item>
                    </el-dropdown-menu>
                  </template>
                </el-dropdown>
                <el-button type="warning" style="margin-left:5px;" icon="ele-MostlyCloudy" @click="importDataRef.openDialog()" v-auth="'fBS_ExRole:import'"> 导入 </el-button>
              </el-button-group>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
    </el-card>
    <el-card class="full-table" shadow="hover" style="margin-top: 5px">
      <el-table :data="state.tableData" @selection-change="(val: any[]) => { state.selectData = val; }" style="width: 100%" v-loading="state.tableLoading" tooltip-effect="light" row-key="id" @sort-change="sortChange" border>
        <el-table-column type="selection" width="40" align="center" v-if="auth('fBS_ExRole:batchDelete') || auth('fBS_ExRole:export')" />
        <el-table-column type="index" label="序号" width="55" align="center"/>
        <el-table-column prop='name' label='名称' show-overflow-tooltip />
        <el-table-column prop='code' label='编码' show-overflow-tooltip />
        <el-table-column prop='orderNo' label='排序' show-overflow-tooltip />
        <el-table-column prop='dataScope' label='数据范围' show-overflow-tooltip>
          <template #default="scope">
            <g-sys-dict v-model="scope.row.dataScope" code="DataScopeEnum" />
          </template>
        </el-table-column>
        <el-table-column prop='remark' label='备注' show-overflow-tooltip />
        <el-table-column prop='status' label='状态' v-auth="'fBS_ExRole:setStatus'" show-overflow-tooltip>
          <template #default="scope">
            <el-switch v-model="scope.row.status" :active-value="1" :inactive-value="2" size="small" @change="changeFBS_ExRoleStatus(scope.row)" />
          </template>
        </el-table-column>
        <el-table-column label="修改记录" width="100" align="center" show-overflow-tooltip>
          <template #default="scope">
            <ModifyRecord :data="scope.row" />
          </template>
        </el-table-column>
        <el-table-column label="操作" width="140" align="center" fixed="right" show-overflow-tooltip v-if="auth('fBS_ExRole:update') || auth('fBS_ExRole:delete')">
          <template #default="scope">
            <el-button icon="ele-Edit" size="small" text type="primary" @click="editDialogRef.openDialog(scope.row, '编辑客户主分类角色')" v-auth="'fBS_ExRole:update'"> 编辑 </el-button>
            <el-button icon="ele-Delete" size="small" text type="primary" @click="delFBS_ExRole(scope.row)" v-auth="'fBS_ExRole:delete'"> 删除 </el-button>
          </template>
        </el-table-column>
      </el-table>
      <el-pagination
              v-model:currentPage="state.tableParams.page"
              v-model:page-size="state.tableParams.pageSize"
              @size-change="(val: any) => handleQuery({ pageSize: val })"
              @current-change="(val: any) => handleQuery({ page: val })"
              layout="total, sizes, prev, pager, next, jumper"
              :page-sizes="[10, 20, 50, 100, 200, 500]"
              :total="state.tableParams.total"
              size="small"
              background />
      <ImportData ref="importDataRef" :import="fBS_ExRoleApi.importData" :download="fBS_ExRoleApi.downloadTemplate" v-auth="'fBS_ExRole:import'" @refresh="handleQuery"/>
      <printDialog ref="printDialogRef" :title="'打印客户主分类角色'" @reloadTable="handleQuery" />
      <editDialog ref="editDialogRef" @reloadTable="handleQuery" />
    </el-card>
  </div>
</template>
<style scoped>
:deep(.el-input), :deep(.el-select), :deep(.el-input-number) {
  width: 100%;
}
</style>
Web/src/views/Customer/fBS_Menu/component/editDialog.vue
New file
@@ -0,0 +1,185 @@
<script lang="ts" name="fBS_Menu" setup>
import { ref, reactive, onMounted } from "vue";
import { ElMessage } from "element-plus";
import type { FormRules } from "element-plus";
import { formatDate } from '/@/utils/formatTime';
import { useFBS_MenuApi } from '/@/api/Customer/fBS_Menu';
//父级传递来的函数,用于回调
const emit = defineEmits(["reloadTable"]);
const fBS_MenuApi = useFBS_MenuApi();
const ruleFormRef = ref();
const state = reactive({
    title: '',
    loading: false,
    showDialog: false,
    ruleForm: {} as any,
    stores: {},
    dropdownData: {} as any,
});
// 自行添加其他规则
const rules = ref<FormRules>({
  pid: [{required: true, message: '请选择父Id!', trigger: 'blur',},],
  type: [{required: true, message: '请选择菜单类型!', trigger: 'change',},],
  title: [{required: true, message: '请选择菜单名称!', trigger: 'blur',},],
  isIframe: [{required: true, message: '请选择是否内嵌!', trigger: 'blur',},],
  isHide: [{required: true, message: '请选择是否隐藏!', trigger: 'blur',},],
  isKeepAlive: [{required: true, message: '请选择是否缓存!', trigger: 'blur',},],
  isAffix: [{required: true, message: '请选择是否固定!', trigger: 'blur',},],
  orderNo: [{required: true, message: '请选择排序!', trigger: 'blur',},],
  status: [{required: true, message: '请选择状态!', trigger: 'change',},],
});
// 页面加载时
onMounted(async () => {
});
// 打开弹窗
const openDialog = async (row: any, title: string) => {
    state.title = title;
    row = row ?? { status: 1,orderNo: 100, };
    state.ruleForm = row.id ? await fBS_MenuApi.detail(row.id).then(res => res.data.result) : JSON.parse(JSON.stringify(row));
    state.showDialog = true;
};
// 关闭弹窗
const closeDialog = () => {
    emit("reloadTable");
    state.showDialog = false;
};
// 提交
const submit = async () => {
    ruleFormRef.value.validate(async (isValid: boolean, fields?: any) => {
        if (isValid) {
            let values = state.ruleForm;
            await fBS_MenuApi[state.ruleForm.id ? 'update' : 'add'](values);
            closeDialog();
        } else {
            ElMessage({
                message: `表单有${Object.keys(fields).length}处验证失败,请修改后再提交`,
                type: "error",
            });
        }
    });
};
//将属性或者函数暴露给父组件
defineExpose({ openDialog });
</script>
<template>
    <div class="fBS_Menu-container">
        <el-dialog v-model="state.showDialog" :width="800" draggable :close-on-click-modal="false">
            <template #header>
                <div style="color: #fff">
                    <span>{{ state.title }}</span>
                </div>
            </template>
            <el-form :model="state.ruleForm" ref="ruleFormRef" label-width="auto" :rules="rules">
                <el-row :gutter="35">
                    <el-form-item v-show="false">
                        <el-input v-model="state.ruleForm.id" />
                    </el-form-item>
                    <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20" >
                        <el-form-item label="父Id" prop="pid">
                            <el-input v-model="state.ruleForm.pid" placeholder="请输入父Id" maxlength="19" show-word-limit 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">
                            <g-sys-dict v-model="state.ruleForm.type" code="MenuTypeEnum" render-as="select" placeholder="请选择菜单类型" clearable filterable />
                        </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">
                            <el-input v-model="state.ruleForm.name" placeholder="请输入路由名称" maxlength="64" show-word-limit 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="path">
                            <el-input v-model="state.ruleForm.path" placeholder="请输入路由地址" maxlength="128" show-word-limit 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="component">
                            <el-input v-model="state.ruleForm.component" placeholder="请输入组件路径" maxlength="128" show-word-limit 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="redirect">
                            <el-input v-model="state.ruleForm.redirect" placeholder="请输入重定向" maxlength="128" show-word-limit 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="permission">
                            <el-input v-model="state.ruleForm.permission" placeholder="请输入权限标识" maxlength="128" show-word-limit 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="title">
                            <el-input v-model="state.ruleForm.title" placeholder="请输入菜单名称" maxlength="64" show-word-limit 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="icon">
                            <el-input v-model="state.ruleForm.icon" placeholder="请输入图标" maxlength="128" show-word-limit 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="isIframe">
                            <el-switch v-model="state.ruleForm.isIframe" active-text="是" inactive-text="否" />
                        </el-form-item>
                    </el-col>
                    <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20" >
                        <el-form-item label="外链链接" prop="outLink">
                            <el-input v-model="state.ruleForm.outLink" placeholder="请输入外链链接" maxlength="256" show-word-limit 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="isHide">
                            <el-switch v-model="state.ruleForm.isHide" active-text="是" inactive-text="否" />
                        </el-form-item>
                    </el-col>
                    <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20" >
                        <el-form-item label="是否缓存" prop="isKeepAlive">
                            <el-switch v-model="state.ruleForm.isKeepAlive" active-text="是" inactive-text="否" />
                        </el-form-item>
                    </el-col>
                    <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20" >
                        <el-form-item label="是否固定" prop="isAffix">
                            <el-switch v-model="state.ruleForm.isAffix" active-text="是" inactive-text="否" />
                        </el-form-item>
                    </el-col>
                    <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20" >
                        <el-form-item label="排序" prop="orderNo">
                            <el-input-number v-model="state.ruleForm.orderNo" placeholder="请输入排序" clearable />
                        </el-form-item>
                    </el-col>
                    <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20" v-if="state.ruleForm.id" >
                        <el-form-item label="状态" prop="status">
                            <g-sys-dict v-model="state.ruleForm.status" code="StatusEnum" render-as="select" placeholder="请选择状态" clearable filterable />
                        </el-form-item>
                    </el-col>
                    <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20" >
                        <el-form-item label="备注" prop="remark">
                            <el-input v-model="state.ruleForm.remark" placeholder="请输入备注" maxlength="256" show-word-limit clearable />
                        </el-form-item>
                    </el-col>
                </el-row>
            </el-form>
            <template #footer>
                <span class="dialog-footer">
                    <el-button @click="() => state.showDialog = false">取 消</el-button>
                    <el-button @click="submit" type="primary" v-reclick="1000">确 定</el-button>
                </span>
            </template>
        </el-dialog>
    </div>
</template>
<style lang="scss" scoped>
:deep(.el-select), :deep(.el-input-number) {
  width: 100%;
}
</style>
Web/src/views/Customer/fBS_Menu/index.vue
New file
@@ -0,0 +1,311 @@
<script lang="ts" setup name="fBS_Menu">
import { ref, reactive, onMounted } from "vue";
import { auth } from '/@/utils/authFunction';
import { ElMessageBox, ElMessage } from "element-plus";
import { downloadStreamFile } from "/@/utils/download";
import { useFBS_MenuApi } from '/@/api/Customer/fBS_Menu';
import editDialog from '/@/views/Customer/fBS_Menu/component/editDialog.vue'
import printDialog from '/@/views/system/print/component/hiprint/preview.vue'
import ModifyRecord from '/@/components/table/modifyRecord.vue';
import ImportData from "/@/components/table/importData.vue";
const fBS_MenuApi = useFBS_MenuApi();
const printDialogRef = ref();
const editDialogRef = ref();
const importDataRef = ref();
const state = reactive({
  exportLoading: false,
  tableLoading: false,
  stores: {},
  showAdvanceQueryUI: false,
  dropdownData: {} as any,
  selectData: [] as any[],
  tableQueryParams: {} as any,
  tableParams: {
    page: 1,
    pageSize: 20,
    total: 0,
    field: 'createTime', // 默认的排序字段
    order: 'descending', // 排序方向
    descStr: 'descending', // 降序排序的关键字符
  },
  tableData: [],
});
// 页面加载时
onMounted(async () => {
});
// 查询操作
const handleQuery = async (params: any = {}) => {
  state.tableLoading = true;
  state.tableParams = Object.assign(state.tableParams, params);
  const result = await fBS_MenuApi.page(Object.assign(state.tableQueryParams, state.tableParams)).then(res => res.data.result);
  state.tableParams.total = result?.total;
  state.tableData = result?.items ?? [];
  state.tableLoading = false;
};
// 列排序
const sortChange = async (column: any) => {
  state.tableParams.field = column.prop;
  state.tableParams.order = column.order;
  await handleQuery();
};
// 删除
const delFBS_Menu = (row: any) => {
  ElMessageBox.confirm(`确定要删除吗?`, "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning",
  }).then(async () => {
    await fBS_MenuApi.delete({ id: row.id });
    handleQuery();
    ElMessage.success("删除成功");
  }).catch(() => {});
};
// 批量删除
const batchDelFBS_Menu = () => {
  ElMessageBox.confirm(`确定要删除${state.selectData.length}条记录吗?`, "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning",
  }).then(async () => {
    await fBS_MenuApi.batchDelete(state.selectData.map(u => ({ id: u.id }) )).then(res => {
      ElMessage.success(`成功批量删除${res.data.result}条记录`);
      handleQuery();
    });
  }).catch(() => {});
};
// 设置状态
const changeFBS_MenuStatus = async (row: any) => {
  await fBS_MenuApi.setStatus({ id: row.id, status: row.status }).then(() => ElMessage.success('状态设置成功'));
};
// 导出数据
const exportFBS_MenuCommand = async (command: string) => {
  try {
    state.exportLoading = true;
    if (command === 'select') {
      const params = Object.assign({}, state.tableQueryParams, state.tableParams, { selectKeyList: state.selectData.map(u => u.id) });
      await fBS_MenuApi.exportData(params).then(res => downloadStreamFile(res));
    } else if (command === 'current') {
      const params = Object.assign({}, state.tableQueryParams, state.tableParams);
      await fBS_MenuApi.exportData(params).then(res => downloadStreamFile(res));
    } else if (command === 'all') {
      const params = Object.assign({}, state.tableQueryParams, state.tableParams, { page: 1, pageSize: 99999999 });
      await fBS_MenuApi.exportData(params).then(res => downloadStreamFile(res));
    }
  } finally {
    state.exportLoading = false;
  }
}
handleQuery();
</script>
<template>
  <div class="fBS_Menu-container" v-loading="state.exportLoading">
    <el-card shadow="hover" :body-style="{ paddingBottom: '0' }">
      <el-form :model="state.tableQueryParams" ref="queryForm" labelWidth="90">
        <el-row>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10">
            <el-form-item label="关键字">
              <el-input v-model="state.tableQueryParams.keyword" clearable placeholder="请输入模糊查询关键字"/>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="父Id">
              <el-input v-model="state.tableQueryParams.pid" clearable placeholder="请输入父Id"/>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="菜单类型">
              <g-sys-dict v-model="state.tableQueryParams.type" code="MenuTypeEnum" render-as="select" placeholder="请选择菜单类型" clearable filterable />
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="路由名称">
              <el-input v-model="state.tableQueryParams.name" clearable placeholder="请输入路由名称"/>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="路由地址">
              <el-input v-model="state.tableQueryParams.path" clearable placeholder="请输入路由地址"/>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="组件路径">
              <el-input v-model="state.tableQueryParams.component" clearable placeholder="请输入组件路径"/>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="重定向">
              <el-input v-model="state.tableQueryParams.redirect" clearable placeholder="请输入重定向"/>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="权限标识">
              <el-input v-model="state.tableQueryParams.permission" clearable placeholder="请输入权限标识"/>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="菜单名称">
              <el-input v-model="state.tableQueryParams.title" clearable placeholder="请输入菜单名称"/>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="图标">
              <el-input v-model="state.tableQueryParams.icon" clearable placeholder="请输入图标"/>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="是否内嵌">
              <el-input v-model="state.tableQueryParams.isIframe" clearable placeholder="请输入是否内嵌"/>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="外链链接">
              <el-input v-model="state.tableQueryParams.outLink" clearable placeholder="请输入外链链接"/>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="是否隐藏">
              <el-input v-model="state.tableQueryParams.isHide" clearable placeholder="请输入是否隐藏"/>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="是否缓存">
              <el-input v-model="state.tableQueryParams.isKeepAlive" clearable placeholder="请输入是否缓存"/>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="是否固定">
              <el-input v-model="state.tableQueryParams.isAffix" clearable placeholder="请输入是否固定"/>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="排序">
              <el-input-number v-model="state.tableQueryParams.orderNo"  clearable placeholder="请输入排序"/>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="状态">
              <g-sys-dict v-model="state.tableQueryParams.status" code="StatusEnum" render-as="select" placeholder="请选择状态" clearable filterable />
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="备注">
              <el-input v-model="state.tableQueryParams.remark" clearable placeholder="请输入备注"/>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10">
            <el-form-item >
              <el-button-group style="display: flex; align-items: center;">
                <el-button type="primary"  icon="ele-Search" @click="handleQuery" v-auth="'fBS_Menu:page'" v-reclick="1000"> 查询 </el-button>
                <el-button icon="ele-Refresh" @click="() => state.tableQueryParams = {}"> 重置 </el-button>
                <el-button icon="ele-ZoomIn" @click="() => state.showAdvanceQueryUI = true" v-if="!state.showAdvanceQueryUI" style="margin-left:5px;"> 高级查询 </el-button>
                <el-button icon="ele-ZoomOut" @click="() => state.showAdvanceQueryUI = false" v-if="state.showAdvanceQueryUI" style="margin-left:5px;"> 隐藏 </el-button>
                <el-button type="danger" style="margin-left:5px;" icon="ele-Delete" @click="batchDelFBS_Menu" :disabled="state.selectData.length == 0" v-auth="'fBS_Menu:batchDelete'"> 删除 </el-button>
                <el-button type="primary" style="margin-left:5px;" icon="ele-Plus" @click="editDialogRef.openDialog(null, '新增客户系统菜单表')" v-auth="'fBS_Menu:add'"> 新增 </el-button>
                <el-dropdown :show-timeout="70" :hide-timeout="50" @command="exportFBS_MenuCommand">
                  <el-button type="primary" style="margin-left:5px;" icon="ele-FolderOpened" v-reclick="20000" v-auth="'fBS_Menu:export'"> 导出 </el-button>
                  <template #dropdown>
                    <el-dropdown-menu>
                      <el-dropdown-item command="select" :disabled="state.selectData.length == 0">导出选中</el-dropdown-item>
                      <el-dropdown-item command="current">导出本页</el-dropdown-item>
                      <el-dropdown-item command="all">导出全部</el-dropdown-item>
                    </el-dropdown-menu>
                  </template>
                </el-dropdown>
                <el-button type="warning" style="margin-left:5px;" icon="ele-MostlyCloudy" @click="importDataRef.openDialog()" v-auth="'fBS_Menu:import'"> 导入 </el-button>
              </el-button-group>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
    </el-card>
    <el-card class="full-table" shadow="hover" style="margin-top: 5px">
      <el-table :data="state.tableData" @selection-change="(val: any[]) => { state.selectData = val; }" style="width: 100%" v-loading="state.tableLoading" tooltip-effect="light" row-key="id" @sort-change="sortChange" border>
        <el-table-column type="selection" width="40" align="center" v-if="auth('fBS_Menu:batchDelete') || auth('fBS_Menu:export')" />
        <el-table-column type="index" label="序号" width="55" align="center"/>
        <el-table-column prop='pid' label='父Id' show-overflow-tooltip />
        <el-table-column prop='type' label='菜单类型' show-overflow-tooltip>
          <template #default="scope">
            <g-sys-dict v-model="scope.row.type" code="MenuTypeEnum" />
          </template>
        </el-table-column>
        <el-table-column prop='name' label='路由名称' show-overflow-tooltip />
        <el-table-column prop='path' label='路由地址' show-overflow-tooltip />
        <el-table-column prop='component' label='组件路径' show-overflow-tooltip />
        <el-table-column prop='redirect' label='重定向' show-overflow-tooltip />
        <el-table-column prop='permission' label='权限标识' show-overflow-tooltip />
        <el-table-column prop='title' label='菜单名称' show-overflow-tooltip />
        <el-table-column prop='icon' label='图标' show-overflow-tooltip />
        <el-table-column prop='isIframe' label='是否内嵌' show-overflow-tooltip>
          <template #default="scope">
            <el-tag v-if="scope.row.isIframe"> 是 </el-tag>
            <el-tag type="danger" v-else> 否 </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop='outLink' label='外链链接' show-overflow-tooltip />
        <el-table-column prop='isHide' label='是否隐藏' show-overflow-tooltip>
          <template #default="scope">
            <el-tag v-if="scope.row.isHide"> 是 </el-tag>
            <el-tag type="danger" v-else> 否 </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop='isKeepAlive' label='是否缓存' show-overflow-tooltip>
          <template #default="scope">
            <el-tag v-if="scope.row.isKeepAlive"> 是 </el-tag>
            <el-tag type="danger" v-else> 否 </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop='isAffix' label='是否固定' show-overflow-tooltip>
          <template #default="scope">
            <el-tag v-if="scope.row.isAffix"> 是 </el-tag>
            <el-tag type="danger" v-else> 否 </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop='orderNo' label='排序' show-overflow-tooltip />
        <el-table-column prop='status' label='状态' v-auth="'fBS_Menu:setStatus'" show-overflow-tooltip>
          <template #default="scope">
            <el-switch v-model="scope.row.status" :active-value="1" :inactive-value="2" size="small" @change="changeFBS_MenuStatus(scope.row)" />
          </template>
        </el-table-column>
        <el-table-column prop='remark' label='备注' show-overflow-tooltip />
        <el-table-column label="修改记录" width="100" align="center" show-overflow-tooltip>
          <template #default="scope">
            <ModifyRecord :data="scope.row" />
          </template>
        </el-table-column>
        <el-table-column label="操作" width="140" align="center" fixed="right" show-overflow-tooltip v-if="auth('fBS_Menu:update') || auth('fBS_Menu:delete')">
          <template #default="scope">
            <el-button icon="ele-Edit" size="small" text type="primary" @click="editDialogRef.openDialog(scope.row, '编辑客户系统菜单表')" v-auth="'fBS_Menu:update'"> 编辑 </el-button>
            <el-button icon="ele-Delete" size="small" text type="primary" @click="delFBS_Menu(scope.row)" v-auth="'fBS_Menu:delete'"> 删除 </el-button>
          </template>
        </el-table-column>
      </el-table>
      <el-pagination
              v-model:currentPage="state.tableParams.page"
              v-model:page-size="state.tableParams.pageSize"
              @size-change="(val: any) => handleQuery({ pageSize: val })"
              @current-change="(val: any) => handleQuery({ page: val })"
              layout="total, sizes, prev, pager, next, jumper"
              :page-sizes="[10, 20, 50, 100, 200, 500]"
              :total="state.tableParams.total"
              size="small"
              background />
      <ImportData ref="importDataRef" :import="fBS_MenuApi.importData" :download="fBS_MenuApi.downloadTemplate" v-auth="'fBS_Menu:import'" @refresh="handleQuery"/>
      <printDialog ref="printDialogRef" :title="'打印客户系统菜单表'" @reloadTable="handleQuery" />
      <editDialog ref="editDialogRef" @reloadTable="handleQuery" />
    </el-card>
  </div>
</template>
<style scoped>
:deep(.el-input), :deep(.el-select), :deep(.el-input-number) {
  width: 100%;
}
</style>
Web/src/views/Customer/fBS_Role/component/editDialog.vue
New file
@@ -0,0 +1,121 @@
<script lang="ts" name="fBS_Role" setup>
import { ref, reactive, onMounted } from "vue";
import { ElMessage } from "element-plus";
import type { FormRules } from "element-plus";
import { formatDate } from '/@/utils/formatTime';
import { useFBS_RoleApi } from '/@/api/Customer/fBS_Role';
//父级传递来的函数,用于回调
const emit = defineEmits(["reloadTable"]);
const fBS_RoleApi = useFBS_RoleApi();
const ruleFormRef = ref();
const state = reactive({
    title: '',
    loading: false,
    showDialog: false,
    ruleForm: {} as any,
    stores: {},
    dropdownData: {} as any,
});
// 自行添加其他规则
const rules = ref<FormRules>({
});
// 页面加载时
onMounted(async () => {
});
// 打开弹窗
const openDialog = async (row: any, title: string) => {
    state.title = title;
    row = row ?? { status: 1,orderNo: 100, };
    state.ruleForm = row.id ? await fBS_RoleApi.detail(row.id).then(res => res.data.result) : JSON.parse(JSON.stringify(row));
    state.showDialog = true;
};
// 关闭弹窗
const closeDialog = () => {
    emit("reloadTable");
    state.showDialog = false;
};
// 提交
const submit = async () => {
    ruleFormRef.value.validate(async (isValid: boolean, fields?: any) => {
        if (isValid) {
            let values = state.ruleForm;
            await fBS_RoleApi[state.ruleForm.id ? 'update' : 'add'](values);
            closeDialog();
        } else {
            ElMessage({
                message: `表单有${Object.keys(fields).length}处验证失败,请修改后再提交`,
                type: "error",
            });
        }
    });
};
//将属性或者函数暴露给父组件
defineExpose({ openDialog });
</script>
<template>
    <div class="fBS_Role-container">
        <el-dialog v-model="state.showDialog" :width="800" draggable :close-on-click-modal="false">
            <template #header>
                <div style="color: #fff">
                    <span>{{ state.title }}</span>
                </div>
            </template>
            <el-form :model="state.ruleForm" ref="ruleFormRef" label-width="auto" :rules="rules">
                <el-row :gutter="35">
                    <el-form-item v-show="false">
                        <el-input v-model="state.ruleForm.id" />
                    </el-form-item>
                    <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20" >
                        <el-form-item label="名称" prop="name">
                            <el-input v-model="state.ruleForm.name" placeholder="请输入名称" maxlength="64" show-word-limit 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="code">
                            <el-input v-model="state.ruleForm.code" placeholder="请输入编码" maxlength="64" show-word-limit 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="orderNo">
                            <el-input-number v-model="state.ruleForm.orderNo" 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="dataScope">
                            <g-sys-dict v-model="state.ruleForm.dataScope" code="DataScopeEnum" render-as="select" placeholder="请选择数据范围" clearable filterable />
                        </el-form-item>
                    </el-col>
                    <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20" >
                        <el-form-item label="备注" prop="remark">
                            <el-input v-model="state.ruleForm.remark" placeholder="请输入备注" maxlength="128" show-word-limit clearable />
                        </el-form-item>
                    </el-col>
                    <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20" v-if="state.ruleForm.id" >
                        <el-form-item label="状态" prop="status">
                            <g-sys-dict v-model="state.ruleForm.status" code="StatusEnum" render-as="select" placeholder="请选择状态" clearable filterable />
                        </el-form-item>
                    </el-col>
                </el-row>
            </el-form>
            <template #footer>
                <span class="dialog-footer">
                    <el-button @click="() => state.showDialog = false">取 消</el-button>
                    <el-button @click="submit" type="primary" v-reclick="1000">确 定</el-button>
                </span>
            </template>
        </el-dialog>
    </div>
</template>
<style lang="scss" scoped>
:deep(.el-select), :deep(.el-input-number) {
  width: 100%;
}
</style>
Web/src/views/Customer/fBS_Role/index.vue
New file
@@ -0,0 +1,225 @@
<script lang="ts" setup name="fBS_Role">
import { ref, reactive, onMounted } from "vue";
import { auth } from '/@/utils/authFunction';
import { ElMessageBox, ElMessage } from "element-plus";
import { downloadStreamFile } from "/@/utils/download";
import { useFBS_RoleApi } from '/@/api/Customer/fBS_Role';
import editDialog from '/@/views/Customer/fBS_Role/component/editDialog.vue'
import printDialog from '/@/views/system/print/component/hiprint/preview.vue'
import ModifyRecord from '/@/components/table/modifyRecord.vue';
import ImportData from "/@/components/table/importData.vue";
const fBS_RoleApi = useFBS_RoleApi();
const printDialogRef = ref();
const editDialogRef = ref();
const importDataRef = ref();
const state = reactive({
  exportLoading: false,
  tableLoading: false,
  stores: {},
  showAdvanceQueryUI: false,
  dropdownData: {} as any,
  selectData: [] as any[],
  tableQueryParams: {} as any,
  tableParams: {
    page: 1,
    pageSize: 20,
    total: 0,
    field: 'createTime', // 默认的排序字段
    order: 'descending', // 排序方向
    descStr: 'descending', // 降序排序的关键字符
  },
  tableData: [],
});
// 页面加载时
onMounted(async () => {
});
// 查询操作
const handleQuery = async (params: any = {}) => {
  state.tableLoading = true;
  state.tableParams = Object.assign(state.tableParams, params);
  const result = await fBS_RoleApi.page(Object.assign(state.tableQueryParams, state.tableParams)).then(res => res.data.result);
  state.tableParams.total = result?.total;
  state.tableData = result?.items ?? [];
  state.tableLoading = false;
};
// 列排序
const sortChange = async (column: any) => {
  state.tableParams.field = column.prop;
  state.tableParams.order = column.order;
  await handleQuery();
};
// 删除
const delFBS_Role = (row: any) => {
  ElMessageBox.confirm(`确定要删除吗?`, "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning",
  }).then(async () => {
    await fBS_RoleApi.delete({ id: row.id });
    handleQuery();
    ElMessage.success("删除成功");
  }).catch(() => {});
};
// 批量删除
const batchDelFBS_Role = () => {
  ElMessageBox.confirm(`确定要删除${state.selectData.length}条记录吗?`, "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning",
  }).then(async () => {
    await fBS_RoleApi.batchDelete(state.selectData.map(u => ({ id: u.id }) )).then(res => {
      ElMessage.success(`成功批量删除${res.data.result}条记录`);
      handleQuery();
    });
  }).catch(() => {});
};
// 设置状态
const changeFBS_RoleStatus = async (row: any) => {
  await fBS_RoleApi.setStatus({ id: row.id, status: row.status }).then(() => ElMessage.success('状态设置成功'));
};
// 导出数据
const exportFBS_RoleCommand = async (command: string) => {
  try {
    state.exportLoading = true;
    if (command === 'select') {
      const params = Object.assign({}, state.tableQueryParams, state.tableParams, { selectKeyList: state.selectData.map(u => u.id) });
      await fBS_RoleApi.exportData(params).then(res => downloadStreamFile(res));
    } else if (command === 'current') {
      const params = Object.assign({}, state.tableQueryParams, state.tableParams);
      await fBS_RoleApi.exportData(params).then(res => downloadStreamFile(res));
    } else if (command === 'all') {
      const params = Object.assign({}, state.tableQueryParams, state.tableParams, { page: 1, pageSize: 99999999 });
      await fBS_RoleApi.exportData(params).then(res => downloadStreamFile(res));
    }
  } finally {
    state.exportLoading = false;
  }
}
handleQuery();
</script>
<template>
  <div class="fBS_Role-container" v-loading="state.exportLoading">
    <el-card shadow="hover" :body-style="{ paddingBottom: '0' }">
      <el-form :model="state.tableQueryParams" ref="queryForm" labelWidth="90">
        <el-row>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10">
            <el-form-item label="关键字">
              <el-input v-model="state.tableQueryParams.keyword" clearable placeholder="请输入模糊查询关键字"/>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="名称">
              <el-input v-model="state.tableQueryParams.name" clearable placeholder="请输入名称"/>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="编码">
              <el-input v-model="state.tableQueryParams.code" clearable placeholder="请输入编码"/>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="排序">
              <el-input-number v-model="state.tableQueryParams.orderNo"  clearable placeholder="请输入排序"/>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="数据范围">
              <g-sys-dict v-model="state.tableQueryParams.dataScope" code="DataScopeEnum" render-as="select" placeholder="请选择数据范围" clearable filterable />
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="备注">
              <el-input v-model="state.tableQueryParams.remark" clearable placeholder="请输入备注"/>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="state.showAdvanceQueryUI">
            <el-form-item label="状态">
              <g-sys-dict v-model="state.tableQueryParams.status" code="StatusEnum" render-as="select" placeholder="请选择状态" clearable filterable />
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10">
            <el-form-item >
              <el-button-group style="display: flex; align-items: center;">
                <el-button type="primary"  icon="ele-Search" @click="handleQuery" v-auth="'fBS_Role:page'" v-reclick="1000"> 查询 </el-button>
                <el-button icon="ele-Refresh" @click="() => state.tableQueryParams = {}"> 重置 </el-button>
                <el-button icon="ele-ZoomIn" @click="() => state.showAdvanceQueryUI = true" v-if="!state.showAdvanceQueryUI" style="margin-left:5px;"> 高级查询 </el-button>
                <el-button icon="ele-ZoomOut" @click="() => state.showAdvanceQueryUI = false" v-if="state.showAdvanceQueryUI" style="margin-left:5px;"> 隐藏 </el-button>
                <el-button type="danger" style="margin-left:5px;" icon="ele-Delete" @click="batchDelFBS_Role" :disabled="state.selectData.length == 0" v-auth="'fBS_Role:batchDelete'"> 删除 </el-button>
                <el-button type="primary" style="margin-left:5px;" icon="ele-Plus" @click="editDialogRef.openDialog(null, '新增客户角色')" v-auth="'fBS_Role:add'"> 新增 </el-button>
                <el-dropdown :show-timeout="70" :hide-timeout="50" @command="exportFBS_RoleCommand">
                  <el-button type="primary" style="margin-left:5px;" icon="ele-FolderOpened" v-reclick="20000" v-auth="'fBS_Role:export'"> 导出 </el-button>
                  <template #dropdown>
                    <el-dropdown-menu>
                      <el-dropdown-item command="select" :disabled="state.selectData.length == 0">导出选中</el-dropdown-item>
                      <el-dropdown-item command="current">导出本页</el-dropdown-item>
                      <el-dropdown-item command="all">导出全部</el-dropdown-item>
                    </el-dropdown-menu>
                  </template>
                </el-dropdown>
                <el-button type="warning" style="margin-left:5px;" icon="ele-MostlyCloudy" @click="importDataRef.openDialog()" v-auth="'fBS_Role:import'"> 导入 </el-button>
              </el-button-group>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
    </el-card>
    <el-card class="full-table" shadow="hover" style="margin-top: 5px">
      <el-table :data="state.tableData" @selection-change="(val: any[]) => { state.selectData = val; }" style="width: 100%" v-loading="state.tableLoading" tooltip-effect="light" row-key="id" @sort-change="sortChange" border>
        <el-table-column type="selection" width="40" align="center" v-if="auth('fBS_Role:batchDelete') || auth('fBS_Role:export')" />
        <el-table-column type="index" label="序号" width="55" align="center"/>
        <el-table-column prop='name' label='名称' show-overflow-tooltip />
        <el-table-column prop='code' label='编码' show-overflow-tooltip />
        <el-table-column prop='orderNo' label='排序' show-overflow-tooltip />
        <el-table-column prop='dataScope' label='数据范围' show-overflow-tooltip>
          <template #default="scope">
            <g-sys-dict v-model="scope.row.dataScope" code="DataScopeEnum" />
          </template>
        </el-table-column>
        <el-table-column prop='remark' label='备注' show-overflow-tooltip />
        <el-table-column prop='status' label='状态' v-auth="'fBS_Role:setStatus'" show-overflow-tooltip>
          <template #default="scope">
            <el-switch v-model="scope.row.status" :active-value="1" :inactive-value="2" size="small" @change="changeFBS_RoleStatus(scope.row)" />
          </template>
        </el-table-column>
        <el-table-column label="修改记录" width="100" align="center" show-overflow-tooltip>
          <template #default="scope">
            <ModifyRecord :data="scope.row" />
          </template>
        </el-table-column>
        <el-table-column label="操作" width="140" align="center" fixed="right" show-overflow-tooltip v-if="auth('fBS_Role:update') || auth('fBS_Role:delete')">
          <template #default="scope">
            <el-button icon="ele-Edit" size="small" text type="primary" @click="editDialogRef.openDialog(scope.row, '编辑客户角色')" v-auth="'fBS_Role:update'"> 编辑 </el-button>
            <el-button icon="ele-Delete" size="small" text type="primary" @click="delFBS_Role(scope.row)" v-auth="'fBS_Role:delete'"> 删除 </el-button>
          </template>
        </el-table-column>
      </el-table>
      <el-pagination
              v-model:currentPage="state.tableParams.page"
              v-model:page-size="state.tableParams.pageSize"
              @size-change="(val: any) => handleQuery({ pageSize: val })"
              @current-change="(val: any) => handleQuery({ page: val })"
              layout="total, sizes, prev, pager, next, jumper"
              :page-sizes="[10, 20, 50, 100, 200, 500]"
              :total="state.tableParams.total"
              size="small"
              background />
      <ImportData ref="importDataRef" :import="fBS_RoleApi.importData" :download="fBS_RoleApi.downloadTemplate" v-auth="'fBS_Role:import'" @refresh="handleQuery"/>
      <printDialog ref="printDialogRef" :title="'打印客户角色'" @reloadTable="handleQuery" />
      <editDialog ref="editDialogRef" @reloadTable="handleQuery" />
    </el-card>
  </div>
</template>
<style scoped>
:deep(.el-input), :deep(.el-select), :deep(.el-input-number) {
  width: 100%;
}
</style>