Bläddra i källkod

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

zuohuaijun 2 månader sedan
förälder
incheckning
03ebb165e1

+ 6 - 6
Admin.NET/Admin.NET.Application/Configuration/Alipay.json

@@ -1,4 +1,4 @@
-{
+{
   "$schema": "https://gitee.com/dotnetchina/Furion/raw/v4/schemas/v4/furion-schema.json",
 
   // 支付宝支付配置,文档地址:https://openhome.alipay.com/develop/sandbox/app
@@ -9,7 +9,7 @@
     "AuthUrl": "https://openauth-sandbox.dl.alipaydev.com/oauth2/publicAppAuthorize.htm", // 沙箱环境授权回调地址
     "AppAuthUrl": "http://xxxxxxxxxx", // 应用授权回调地址
     "NotifyUrl": "http://xxxxxxxxx/api/sysAlipay/Notify", // 应用网关地址
-    "RootCertPath": "Alipaycrt/alipayRootCert.crt", // 支付宝根证书存放路径
+    "RootCertPath": "AlipayCrt/alipayRootCert.crt", // 支付宝根证书存放路径
     "AccountList": [
       {
         "Name": "sandbox 默认应用",
@@ -17,8 +17,8 @@
         "SignType": "RSA2",
         "PrivateKey": "xxxxxxxxxxxxxxxxx",
         "EncryptKey": "xxxxxxxxxxxxxxxxxxxx",
-        "AppCertPath": "Alipaycrt/appPublicCert.crt", // 应用公钥证书存放路径
-        "AlipayPublicCertPath": "Alipaycrt/alipayPublicCert.crt" // 支付宝公钥证书存放路径
+        "AppCertPath": "AlipayCrt/appPublicCert.crt", // 应用公钥证书存放路径
+        "AlipayPublicCertPath": "AlipayCrt/alipayPublicCert.crt" // 支付宝公钥证书存放路径
       },
       {
         "Name": "sandbox 默认应用2",
@@ -26,8 +26,8 @@
         "SignType": "RSA2",
         "PrivateKey": "xxxxxxxxxxxxxxxxx",
         "EncryptKey": "xxxxxxxxxxxxxxxxxxxx",
-        "AppCertPath": "Alipaycrt/appPublicCert.crt", // 应用公钥证书存放路径
-        "AlipayPublicCertPath": "Alipaycrt/alipayPublicCert.crt" // 支付宝公钥证书存放路径
+        "AppCertPath": "AlipayCrt/appPublicCert.crt", // 应用公钥证书存放路径
+        "AlipayPublicCertPath": "AlipayCrt/alipayPublicCert.crt" // 支付宝公钥证书存放路径
       }
     ]
   }

+ 2 - 0
Admin.NET/Admin.NET.Core/Logging/DatabaseLoggingWriter.cs

@@ -72,6 +72,8 @@ public class DatabaseLoggingWriter : IDatabaseLoggingWriter, IDisposable
         if (string.IsNullOrEmpty(remoteIPv4))
             remoteIPv4 = loggingMonitor.remoteIPv4;
 
+        remoteIPv4 = remoteIPv4?.Split(',')?.FirstOrDefault()?.Trim();
+
         (string ipLocation, double? longitude, double? latitude) = CommonUtil.GetIpAddress(remoteIPv4);
 
         var browser = "";

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

@@ -8,7 +8,7 @@ namespace Admin.NET.Core;
 
 /// <summary>
 /// 系统字典值表种子数据
-/// </summary>
+/// </summary> 
 public class SysDictDataSeedData : ISqlSugarEntitySeedData<SysDictData>
 {
     /// <summary>
@@ -32,6 +32,7 @@ public class SysDictDataSeedData : ISqlSugarEntitySeedData<SysDictData>
             new SysDictData{ Id=1300000000110, DictTypeId=typeList[0].Id, Label="上传", Value="Upload", OrderNo=100, Remark="上传", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
             new SysDictData{ Id=1300000000111, DictTypeId=typeList[0].Id, Label="开关", Value="Switch", OrderNo=100, Remark="开关", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
             new SysDictData{ Id=1300000000112, DictTypeId=typeList[0].Id, Label="上传单文件", Value="Upload_SingleFile", OrderNo=120, Remark="上传单文件", Status=StatusEnum.Enable, CreateTime= DateTime.Now },
+            new SysDictData{ Id=1300000000113, DictTypeId=typeList[0].Id, Label="富文本编辑器", Value="Editor", OrderNo=130, Remark="富文本编辑器", Status=StatusEnum.Enable,   CreateTime=DateTime.Parse("2025-12-25 00:00:00") },
 
             new SysDictData{ Id=1300000000201, DictTypeId=typeList[1].Id, Label="等于", Value="==", OrderNo=1, Remark="等于", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
             new SysDictData{ Id=1300000000202, DictTypeId=typeList[1].Id, Label="模糊", Value="like", OrderNo=1, Remark="模糊", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },

+ 180 - 179
Admin.NET/Admin.NET.Core/Service/CodeGen/CustomViewEngine.cs

@@ -1,180 +1,181 @@
-// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
-//
-// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
-//
-// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
-
-namespace Admin.NET.Core.Service;
-
-/// <summary>
-/// 自定义模板引擎
-/// </summary>
-public class CustomViewEngine : ViewEngineModel
-{
-    /// <summary>
-    /// 库定位器
-    /// </summary>
-    public string ConfigId { get; set; } = SqlSugarConst.MainConfigId;
-
-    public string AuthorName { get; set; }
-
-    public string BusName { get; set; }
-
-    public string NameSpace { get; set; }
-
-    public string ClassName { get; set; }
-
-    public string LowerClassName { get; set; }
-
-    public string ProjectLastName { get; set; }
-
-    public string PagePath { get; set; } = "main";
-
-    public string PrintType { get; set; }
-
-    public string PrintName { get; set; }
-
-    public bool HasLikeQuery { get; set; }
-
-    public bool HasJoinTable { get; set; }
-
-    public bool HasEnumField { get; set; }
-
-    public bool HasDictField { get; set; }
-
-    public bool HasConstField { get; set; }
-
-    public bool HasSetStatus => TableField.Any(IsStatus);
-
-    public List<CodeGenConfig> TableField { get; set; }
-
-    public List<CodeGenConfig> ImportFieldList { get; set; }
-
-    public List<CodeGenConfig> UploadFieldList { get; set; }
-
-    public List<CodeGenConfig> QueryWhetherList { get; set; }
-
-    public List<CodeGenConfig> ApiTreeFieldList { get; set; }
-
-    public List<CodeGenConfig> DropdownFieldList { get; set; }
-
-    public List<CodeGenConfig> AddUpdateFieldList { get; set; }
-
-    public List<CodeGenConfig> PrimaryKeyFieldList { get; set; }
-
-    public List<TableUniqueConfigItem> TableUniqueConfigList { get; set; }
-
-    public List<CodeGenConfig> IgnoreUpdateFieldList => TableField.Where(u => u.WhetherAddUpdate == "N" && u.ColumnKey != "True" && u.WhetherCommon != "Y").ToList();
-
-    /// <summary>
-    /// 格式化主键查询条件
-    /// 例: PrimaryKeysFormat(" || ", "u.{0} == input.{0}")
-    /// 单主键返回 u.Id == input.Id
-    /// 组合主键返回 u.Id == input.Id || u.FkId == input.FkId
-    /// </summary>
-    /// <param name="separator">分隔符</param>
-    /// <param name="format">模板字符串</param>
-    /// <param name="lowerFirstLetter">字段首字母小写</param>
-    /// <returns></returns>
-    public string PrimaryKeysFormat(string separator, string format, bool lowerFirstLetter = false) => string.Join(separator, PrimaryKeyFieldList.Select(u => string.Format(format, lowerFirstLetter ? u.LowerPropertyName : u.PropertyName)));
-
-    /// <summary>
-    /// 注入的服务
-    /// </summary>
-    /// <returns></returns>
-    public Dictionary<string, string> InjectServiceMap
-    {
-        get
-        {
-            var injectMap = new Dictionary<string, string>();
-            if (UploadFieldList.Count > 0) injectMap.Add(nameof(SysFileService), ToLowerFirstLetter(nameof(SysFileService)));
-            if (DropdownFieldList.Count > 0 || ImportFieldList.Count > 0) injectMap.Add(nameof(ISqlSugarClient), ToLowerFirstLetter(nameof(ISqlSugarClient).TrimStart('I')));
-            if (ImportFieldList.Any(c => c.EffectType == "DictSelector")) injectMap.Add(nameof(SysDictTypeService), ToLowerFirstLetter(nameof(SysDictTypeService)));
-            return injectMap;
-        }
-    }
-
-    /// <summary>
-    /// 服务构造参数
-    /// </summary>
-    public string InjectServiceArgs => InjectServiceMap.Count > 0 ? ", " + string.Join(", ", InjectServiceMap.Select(kv => $"{kv.Key} {kv.Value}")) : "";
-
-    /// <summary>
-    /// 默认值列表
-    /// </summary>
-    public List<CodeGenConfig> DefaultValueList { get; set; }
-
-    /// <summary>
-    /// 判断字段是否为状态字段
-    /// </summary>
-    /// <param name="column"></param>
-    /// <returns></returns>
-    public bool IsStatus(CodeGenConfig column) => column.PropertyName == nameof(SysUser.Status) && column.NetType == nameof(StatusEnum);
-
-    /// <summary>
-    /// 获取首字母小写字符串
-    /// </summary>
-    /// <param name="text"></param>
-    /// <returns></returns>
-    public string ToLowerFirstLetter(string text) => string.IsNullOrWhiteSpace(text) ? text : text[..1].ToLower() + text[1..];
-
-    /// <summary>
-    /// 将基本字段类型转为可空类型
-    /// </summary>
-    /// <param name="netType"></param>
-    /// <returns></returns>
-    public string GetNullableNetType(string netType) => Regex.IsMatch(netType, "(.*?Enum|bool|char|int|long|double|float|decimal)[?]?") ? netType.TrimEnd('?') + "?" : netType;
-
-    /// <summary>
-    /// 获取前端表格列定义的属性
-    /// </summary>
-    /// <param name="column"></param>
-    /// <returns></returns>
-    public string GetElTableColumnCustomProperty(CodeGenConfig column)
-    {
-        var content = $"prop='{column.LowerPropertyName}' label='{column.ColumnComment}'";
-        if (IsStatus(column)) content += $" v-auth=\"'{LowerClassName}:setStatus'\"";
-        if (column.WhetherSortable == "Y") content += " sortable='custom'";
-        return content;
-    }
-
-    /// <summary>
-    /// 设置默认值
-    /// </summary>
-    /// <returns></returns>
-    public string GetAddDefaultValue()
-    {
-        var content = "";
-        if (DefaultValueList.Count == 0)
-        {
-            var status = TableField.FirstOrDefault(IsStatus);
-            var orderNo = TableField.FirstOrDefault(c => c.NetType.TrimEnd('?') == "int" && c.PropertyName == nameof(SysUser.OrderNo));
-            if (status != null) content += $"{status.LowerPropertyName}: {(int)StatusEnum.Enable},";
-            if (orderNo != null) content += $"{orderNo.LowerPropertyName}: 100,";
-        }
-        else
-        {
-            foreach (var item in DefaultValueList)
-            {
-                if (!string.IsNullOrWhiteSpace(item.DefaultValue))
-                {
-                    switch (item.EffectType)
-                    {
-                        case "InputNumber":
-                            content += $"{item.LowerPropertyName}: {item.DefaultValue},";
-                            break;
-
-                        case "Switch":
-                            content += $"{item.LowerPropertyName}: {(item.DefaultValue == "1" ? true.ToString().ToLower() : false.ToString().ToLower())},";
-                            break;
-
-                        default:
-                            content += $"{item.LowerPropertyName}: '{item.DefaultValue}',";
-                            break;
-                    }
-                }
-            }
-        }
-        return content;
-    }
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core.Service;
+
+/// <summary>
+/// 自定义模板引擎
+/// </summary>
+public class CustomViewEngine : ViewEngineModel
+{
+    /// <summary>
+    /// 库定位器
+    /// </summary>
+    public string ConfigId { get; set; } = SqlSugarConst.MainConfigId;
+
+    public string AuthorName { get; set; }
+
+    public string BusName { get; set; }
+
+    public string NameSpace { get; set; }
+
+    public string ClassName { get; set; }
+
+    public string LowerClassName { get; set; }
+
+    public string ProjectLastName { get; set; }
+
+    public string PagePath { get; set; } = "main";
+
+    public string PrintType { get; set; }
+
+    public string PrintName { get; set; }
+
+    public bool HasLikeQuery { get; set; }
+
+    public bool HasJoinTable { get; set; }
+
+    public bool HasEnumField { get; set; }
+
+    public bool HasDictField { get; set; }
+
+    public bool HasConstField { get; set; }
+
+    public bool HasSetStatus => TableField.Any(IsStatus);
+
+    public List<CodeGenConfig> TableField { get; set; }
+
+    public List<CodeGenConfig> ImportFieldList { get; set; }
+
+    public List<CodeGenConfig> UploadFieldList { get; set; }
+
+    public List<CodeGenConfig> QueryWhetherList { get; set; }
+
+    public List<CodeGenConfig> ApiTreeFieldList { get; set; }
+
+    public List<CodeGenConfig> DropdownFieldList { get; set; }
+
+    public List<CodeGenConfig> AddUpdateFieldList { get; set; }
+
+    public List<CodeGenConfig> PrimaryKeyFieldList { get; set; }
+
+    public List<TableUniqueConfigItem> TableUniqueConfigList { get; set; }
+
+    public List<CodeGenConfig> IgnoreUpdateFieldList => TableField.Where(u => u.WhetherAddUpdate == "N" && u.ColumnKey != "True" && u.WhetherCommon != "Y").ToList();
+
+    /// <summary>
+    /// 格式化主键查询条件
+    /// 例: PrimaryKeysFormat(" || ", "u.{0} == input.{0}")
+    /// 单主键返回 u.Id == input.Id
+    /// 组合主键返回 u.Id == input.Id || u.FkId == input.FkId
+    /// </summary>
+    /// <param name="separator">分隔符</param>
+    /// <param name="format">模板字符串</param>
+    /// <param name="lowerFirstLetter">字段首字母小写</param>
+    /// <returns></returns>
+    public string PrimaryKeysFormat(string separator, string format, bool lowerFirstLetter = false) => string.Join(separator, PrimaryKeyFieldList.Select(u => string.Format(format, lowerFirstLetter ? u.LowerPropertyName : u.PropertyName)));
+
+    /// <summary>
+    /// 注入的服务
+    /// </summary>
+    /// <returns></returns>
+    public Dictionary<string, string> InjectServiceMap
+    {
+        get
+        {
+            var injectMap = new Dictionary<string, string>();
+            if (UploadFieldList.Count > 0) injectMap.Add(nameof(SysFileService), ToLowerFirstLetter(nameof(SysFileService)));
+            if (DropdownFieldList.Count > 0 || ImportFieldList.Count > 0) injectMap.Add(nameof(ISqlSugarClient), ToLowerFirstLetter(nameof(ISqlSugarClient).TrimStart('I')));
+            if (ImportFieldList.Any(c => c.EffectType == "DictSelector")) injectMap.Add(nameof(SysDictTypeService), ToLowerFirstLetter(nameof(SysDictTypeService)));
+            return injectMap;
+        }
+    }
+
+    /// <summary>
+    /// 服务构造参数
+    /// </summary>
+    public string InjectServiceArgs => InjectServiceMap.Count > 0 ? ", " + string.Join(", ", InjectServiceMap.Select(kv => $"{kv.Key} {kv.Value}")) : "";
+
+    /// <summary>
+    /// 默认值列表
+    /// </summary>
+    public List<CodeGenConfig> DefaultValueList { get; set; }
+
+    /// <summary>
+    /// 判断字段是否为状态字段
+    /// </summary>
+    /// <param name="column"></param>
+    /// <returns></returns> 
+    public bool IsStatus(CodeGenConfig column) => column.NetType == nameof(StatusEnum);
+
+    /// <summary>
+    /// 获取首字母小写字符串
+    /// </summary>
+    /// <param name="text"></param>
+    /// <returns></returns>
+    public string ToLowerFirstLetter(string text) => string.IsNullOrWhiteSpace(text) ? text : text[..1].ToLower() + text[1..];
+
+    /// <summary>
+    /// 将基本字段类型转为可空类型
+    /// </summary>
+    /// <param name="netType"></param>
+    /// <returns></returns>
+    public string GetNullableNetType(string netType) => Regex.IsMatch(netType, "(.*?Enum|bool|char|int|long|double|float|decimal)[?]?") ? netType.TrimEnd('?') + "?" : netType;
+
+    /// <summary>
+    /// 获取前端表格列定义的属性
+    /// </summary>
+    /// <param name="column"></param>
+    /// <returns></returns>
+    public string GetElTableColumnCustomProperty(CodeGenConfig column)
+    {
+        var content = $"prop='{column.LowerPropertyName}' label='{column.ColumnComment}'";
+        if (IsStatus(column)) content += $" v-auth=\"'{LowerClassName}:setStatus'\"";
+        if (column.WhetherSortable == "Y") content += " sortable='custom'";
+        return content;
+    }
+
+    /// <summary>
+    /// 设置默认值
+    /// </summary>
+    /// <returns></returns>
+    public string GetAddDefaultValue()
+    {
+        var content = "";
+        if (DefaultValueList.Count == 0)
+        {
+            var status = TableField.FirstOrDefault(IsStatus);
+            var orderNo = TableField.FirstOrDefault(c => c.NetType.TrimEnd('?') == "int" && c.PropertyName == nameof(SysUser.OrderNo));
+            if (status != null) content += $"{status.LowerPropertyName}: {(int)StatusEnum.Enable},";
+            if (orderNo != null) content += $"{orderNo.LowerPropertyName}: 100,";
+        }
+        else
+        {
+            foreach (var item in DefaultValueList)
+            {
+                if (!string.IsNullOrWhiteSpace(item.DefaultValue))
+                {
+                    switch (item.EffectType)
+                    {
+                        case "InputNumber":
+                        case "EnumSelector"://枚举和数字框,通过正则提取 数字:如 ('0')
+                            content += $"{item.LowerPropertyName}: {Regex.Match(item.DefaultValue, @"\d+").Value},";
+                            break;
+                        case "Switch":
+                            content += $"{item.LowerPropertyName}: {(item.DefaultValue == "1" ? true.ToString().ToLower() : false.ToString().ToLower())},";
+                            break;
+                        case "DatePicker"://忽略适配日期格式  
+                            break;
+                        default:
+                            content += $"{item.LowerPropertyName}: \"{item.DefaultValue}\",";// 如果是字符串 DefaultValue=('男')
+                            break;
+                    }
+                }
+            }
+        }
+        return content;
+    }
 }

+ 94 - 0
Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenConfigService.cs

@@ -147,6 +147,100 @@ public class SysCodeGenConfigService : IDynamicApiController, ITransient
         provider.Insertable(codeGenConfigs).ExecuteCommand();
     }
 
+
+    /// <summary>
+    /// 批量更新代码字段:先删除再新增,会保留历史字段操作类型
+    /// </summary>
+    /// <param name="tableColumnOutputList"></param>
+    /// <param name="codeGenId"></param>
+    [NonAction]
+    public async Task UpdateList(List<ColumnOuput> tableColumnOutputList, long codeGenId)
+    {
+        if (tableColumnOutputList == null) return;
+
+        //获取历史数据
+        var oldList = await GetList(new CodeGenConfig() { CodeGenId = codeGenId, });
+        //删除历史数据
+        await DeleteCodeGenConfig(codeGenId);
+
+        var codeGenConfigs = new List<SysCodeGenConfig>();
+        var orderNo = 100;
+        foreach (var tableColumn in tableColumnOutputList)
+        {
+            var oldItem = oldList.FirstOrDefault(u => u.ColumnName == tableColumn.ColumnName);
+
+            var codeGenConfig = new SysCodeGenConfig();
+
+            var yesOrNo = YesNoEnum.Y.ToString();
+            if (Convert.ToBoolean(tableColumn.ColumnKey)) yesOrNo = YesNoEnum.N.ToString();
+
+            if (CodeGenUtil.IsCommonColumn(tableColumn.PropertyName))
+            {
+                codeGenConfig.WhetherCommon = YesNoEnum.Y.ToString();
+                yesOrNo = YesNoEnum.N.ToString();
+            }
+            else
+            {
+                codeGenConfig.WhetherCommon = YesNoEnum.N.ToString();
+            }
+
+            codeGenConfig.CodeGenId = codeGenId;
+            codeGenConfig.ColumnName = tableColumn.ColumnName; // 字段名
+            codeGenConfig.PropertyName = tableColumn.PropertyName;// 实体属性名
+            codeGenConfig.ColumnLength = tableColumn.ColumnLength;// 长度
+            codeGenConfig.ColumnComment = tableColumn.ColumnComment;
+            codeGenConfig.NetType = tableColumn.NetType;
+            codeGenConfig.DefaultValue = tableColumn.DefaultValue;
+            codeGenConfig.WhetherRetract = YesNoEnum.N.ToString();
+
+            // 生成代码时,主键并不是必要输入项,故一定要排除主键字段
+            codeGenConfig.WhetherRequired = (tableColumn.IsNullable || tableColumn.IsPrimarykey) ? YesNoEnum.N.ToString() : YesNoEnum.Y.ToString();
+            codeGenConfig.WhetherQuery = yesOrNo;
+            codeGenConfig.WhetherImport = yesOrNo;
+            codeGenConfig.WhetherAddUpdate = yesOrNo;
+            codeGenConfig.WhetherTable = yesOrNo;
+
+            codeGenConfig.ColumnKey = tableColumn.ColumnKey;
+
+            codeGenConfig.DataType = tableColumn.DataType;
+            codeGenConfig.EffectType = CodeGenUtil.DataTypeToEff(codeGenConfig.NetType);
+            codeGenConfig.QueryType = GetDefaultQueryType(codeGenConfig); // QueryTypeEnum.eq.ToString();
+            codeGenConfig.OrderNo = orderNo;
+
+            if (oldItem != null)
+            {
+                //如果历史存在,则继承
+                codeGenConfig.WhetherQuery = oldItem.WhetherQuery;
+                codeGenConfig.WhetherImport = oldItem.WhetherImport;
+                codeGenConfig.WhetherAddUpdate = oldItem.WhetherAddUpdate;
+                codeGenConfig.WhetherTable = oldItem.WhetherTable;
+
+                codeGenConfig.EffectType = oldItem.EffectType;
+                codeGenConfig.FkConfigId = oldItem.FkConfigId;
+                codeGenConfig.FkEntityName = oldItem.FkEntityName;
+                codeGenConfig.FkTableName = oldItem.FkTableName;
+                codeGenConfig.FkDisplayColumns = oldItem.FkDisplayColumns;
+                codeGenConfig.FkLinkColumnName = oldItem.FkLinkColumnName;
+                codeGenConfig.FkColumnNetType = oldItem.FkColumnNetType;
+
+            }
+
+            codeGenConfigs.Add(codeGenConfig);
+
+            if (!string.IsNullOrWhiteSpace(tableColumn.DictTypeCode))
+            {
+                codeGenConfig.QueryType = "==";
+                codeGenConfig.DictTypeCode = tableColumn.DictTypeCode;
+                codeGenConfig.EffectType = tableColumn.DictTypeCode.EndsWith("Enum") ? "EnumSelector" : "DictSelector";
+            }
+
+            orderNo += 10; // 每个配置排序间隔10
+        }
+        // 多库代码生成---这里要切回主库
+        var provider = _db.AsTenant().GetConnectionScope(SqlSugarConst.MainConfigId);
+        provider.Insertable(codeGenConfigs).ExecuteCommand();
+    }
+
     /// <summary>
     /// 默认查询类型
     /// </summary>

+ 28 - 0
Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenService.cs

@@ -123,6 +123,34 @@ public class SysCodeGenService : IDynamicApiController, ITransient
         }
     }
 
+
+    /// <summary>
+    /// 同步代码字段(保留历史作用类型) 🔖 
+    /// </summary>
+    /// <param name="input"></param>
+    /// <returns></returns>
+    [ApiDescriptionSettings(Name = "SyncField"), HttpPost]
+    [DisplayName("同步代码字段")]
+    public async Task SyncCodeFieldGen(UpdateCodeGenInput input)
+    {
+        var isExist = await _db.Queryable<SysCodeGen>().AnyAsync(u => u.TableName == input.TableName && u.Id != input.Id);
+        if (isExist) throw Oops.Oh(ErrorCodeEnum.D1400);
+        try
+        {
+            // 开启事务
+            _db.AsTenant().BeginTran();
+            await _codeGenConfigService.UpdateList(GetColumnList(input.Adapt<AddCodeGenInput>()), input.Id);
+            _db.AsTenant().CommitTran();
+        }
+        catch (Exception ex)
+        {
+            _db.AsTenant().RollbackTran();
+            throw Oops.Oh(ex);
+        }
+    }
+
+
+
     /// <summary>
     /// 删除代码生成 🔖
     /// </summary>

+ 135 - 130
Admin.NET/Admin.NET.Core/Service/File/Dto/FileInput.cs

@@ -1,131 +1,136 @@
-// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
-//
-// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
-//
-// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
-
-namespace Admin.NET.Core.Service;
-
-/// <summary>
-/// 文件分页查询
-/// </summary>
-public class PageFileInput : BasePageInput
-{
-    /// <summary>
-    /// 文件名称
-    /// </summary>
-    public string FileName { get; set; }
-
-    /// <summary>
-    /// 文件路径
-    /// </summary>
-    public string FilePath { get; set; }
-
-    /// <summary>
-    /// 文件后缀
-    /// </summary>
-    public string? Suffix { get; set; }
-
-    /// <summary>
-    /// 开始时间
-    /// </summary>
-    public DateTime? StartTime { get; set; }
-
-    /// <summary>
-    /// 结束时间
-    /// </summary>
-    public DateTime? EndTime { get; set; }
-}
-
-/// <summary>
-/// 上传文件
-/// </summary>
-public class UploadFileInput
-{
-    /// <summary>
-    /// 文件
-    /// </summary>
-    [Required]
-    public IFormFile File { get; set; }
-
-    /// <summary>
-    /// 文件类别
-    /// </summary>
-    public string FileType { get; set; }
-
-    /// <summary>
-    /// 是否公开
-    /// </summary>
-    public bool IsPublic { get; set; } = false;
-
-    /// <summary>
-    /// 允许格式:.jpeg.jpg.png.bmp.gif.tif
-    /// </summary>
-    public string AllowSuffix { get; set; }
-
-    /// <summary>
-    /// 指定存储桶名称
-    /// </summary>
-    public string? BucketName { get; set; }
-
-    /// <summary>
-    /// 指定存储提供者ID
-    /// </summary>
-    public long? ProviderId { get; set; }
-}
-
-/// <summary>
-/// 上传文件Base64
-/// </summary>
-public class UploadFileFromBase64Input
-{
-    /// <summary>
-    /// 文件名
-    /// </summary>
-    public string FileName { get; set; }
-
-    /// <summary>
-    /// 文件内容
-    /// </summary>
-    public string FileDataBase64 { get; set; }
-
-    /// <summary>
-    /// 文件类型( "image/jpeg",)
-    /// </summary>
-    public string ContentType { get; set; }
-}
-
-/// <summary>
-/// 查询关联查询输入
-/// </summary>
-public class RelationQueryInput
-{
-    /// <summary>
-    /// 关联对象名称
-    /// </summary>
-    public string RelationName { get; set; }
-
-    /// <summary>
-    /// 关联对象Id
-    /// </summary>
-    public long? RelationId { get; set; }
-
-    /// <summary>
-    /// 文件类型:多个以","分割
-    /// </summary>
-    public string FileTypes { get; set; }
-
-    /// <summary>
-    /// 所属Id
-    /// </summary>
-    public long? BelongId { get; set; }
-
-    /// <summary>
-    /// 文件类型分割
-    /// </summary>
-    /// <returns></returns>
-    public string[] GetFileTypeBS()
-    {
-        return FileTypes.Split(',');
-    }
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core.Service;
+
+/// <summary>
+/// 文件分页查询
+/// </summary>
+public class PageFileInput : BasePageInput
+{
+    /// <summary>
+    /// 文件名称
+    /// </summary>
+    public string FileName { get; set; }
+
+    /// <summary>
+    /// 文件路径
+    /// </summary>
+    public string FilePath { get; set; }
+
+    /// <summary>
+    /// 文件后缀
+    /// </summary>
+    public string? Suffix { get; set; }
+
+    /// <summary>
+    /// 开始时间
+    /// </summary>
+    public DateTime? StartTime { get; set; }
+
+    /// <summary>
+    /// 结束时间
+    /// </summary>
+    public DateTime? EndTime { get; set; }
+}
+
+/// <summary>
+/// 上传文件
+/// </summary>
+public class UploadFileInput
+{
+    /// <summary>
+    /// 文件
+    /// </summary>
+    [Required]
+    public IFormFile File { get; set; }
+
+    /// <summary>
+    /// 文件类别
+    /// </summary>
+    public string FileType { get; set; }
+
+    /// <summary>
+    /// 是否公开
+    /// </summary>
+    public bool IsPublic { get; set; } = false;
+
+    /// <summary>
+    /// 允许格式:.jpeg.jpg.png.bmp.gif.tif
+    /// </summary>
+    public string AllowSuffix { get; set; }
+
+    /// <summary>
+    /// 指定存储桶名称
+    /// </summary>
+    public string? BucketName { get; set; }
+
+    /// <summary>
+    /// 指定存储提供者ID
+    /// </summary>
+    public long? ProviderId { get; set; }
+    
+    /// <summary>
+    /// 业务数据Id
+    /// </summary>
+    public long? DataId { get; set; }
+}
+
+/// <summary>
+/// 上传文件Base64
+/// </summary>
+public class UploadFileFromBase64Input
+{
+    /// <summary>
+    /// 文件名
+    /// </summary>
+    public string FileName { get; set; }
+
+    /// <summary>
+    /// 文件内容
+    /// </summary>
+    public string FileDataBase64 { get; set; }
+
+    /// <summary>
+    /// 文件类型( "image/jpeg",)
+    /// </summary>
+    public string ContentType { get; set; }
+}
+
+/// <summary>
+/// 查询关联查询输入
+/// </summary>
+public class RelationQueryInput
+{
+    /// <summary>
+    /// 关联对象名称
+    /// </summary>
+    public string RelationName { get; set; }
+
+    /// <summary>
+    /// 关联对象Id
+    /// </summary>
+    public long? RelationId { get; set; }
+
+    /// <summary>
+    /// 文件类型:多个以","分割
+    /// </summary>
+    public string FileTypes { get; set; }
+
+    /// <summary>
+    /// 所属Id
+    /// </summary>
+    public long? BelongId { get; set; }
+
+    /// <summary>
+    /// 文件类型分割
+    /// </summary>
+    /// <returns></returns>
+    public string[] GetFileTypeBS()
+    {
+        return FileTypes.Split(',');
+    }
 }

+ 1 - 0
Admin.NET/Admin.NET.Core/Service/File/SysFileService.cs

@@ -329,6 +329,7 @@ public class SysFileService : IDynamicApiController, ITransient
         newFile.SizeKb = sizeKb;
         newFile.FilePath = path;
         newFile.FileMd5 = fileMd5;
+        newFile.DataId = input.DataId;
 
         var finalName = newFile.Id + suffix; // 文件最终名称
 

+ 9 - 3
Admin.NET/Admin.NET.Core/Service/Job/SysJobService.cs

@@ -385,8 +385,14 @@ public class SysJobService : IDynamicApiController, ITransient
     public async Task ClearExpireJobTriggerRecord(SysJobTriggerRecord input)
     {
         int keepRecords = 30;//保留记录条数
-        await _sysJobTriggerRecordRep.AsDeleteable().In(it => it.Id,
-         _sysJobTriggerRecordRep.AsQueryable().Skip(keepRecords).OrderByDescending(it => it.LastRunTime)
-         .Where(u => u.JobId == input.JobId && u.TriggerId == input.TriggerId).Select(it => it.Id)).ExecuteCommandAsync();//注意Select不要ToList(), ToList就2次查询了
+        // 使用CopyNew()创建新的数据库连接实例,避免连接冲突
+        var db = _sysJobTriggerRecordRep.AsSugarClient().CopyNew();
+        await db.Deleteable<SysJobTriggerRecord>().In(it => it.Id,
+            db.Queryable<SysJobTriggerRecord>()
+                .Skip(keepRecords)
+                .OrderByDescending(it => it.LastRunTime)
+                .Where(u => u.JobId == input.JobId && u.TriggerId == input.TriggerId)
+                .Select(it => it.Id) //注意Select不要ToList(), ToList就2次查询了
+        ).ExecuteCommandAsync();
     }
 }

+ 5 - 0
Admin.NET/Admin.NET.Core/Service/Menu/SysMenuService.cs

@@ -338,6 +338,11 @@ public class SysMenuService : IDynamicApiController, ITransient
         if (permissions != null) return permissions;
 
         var menuIdList = _userManager.SuperAdmin || _userManager.SysAdmin ? new() : await GetMenuIdList();
+        if(menuIdList.Count <= 0 && !_userManager.SuperAdmin)
+        {
+            //_sysCacheService.Set(CacheConst.KeyUserButton + userId, new List<string>(), TimeSpan.FromDays(7));
+            return new List<string>();
+        }
 
         permissions = await _sysMenuRep.AsQueryable()
             .InnerJoinIF<SysTenantMenu>(!_userManager.SuperAdmin, (u, t) => t.TenantId == _userManager.TenantId && u.Id == t.MenuId)

+ 11 - 0
Admin.NET/Admin.NET.Core/Service/Tenant/SysTenantService.cs

@@ -520,6 +520,9 @@ public class SysTenantService : IDynamicApiController, ITransient
         if (menuList.Where(u => !string.IsNullOrWhiteSpace(u.Name)).GroupBy(u => u.Name).Any(u => u.Count() > 1))
             throw Oops.Oh(ErrorCodeEnum.D4009);
 
+         //获取旧记录数据   原ID不能改变  种子初始化后  数据重复
+        var tenantMenuList = await _sysTenantMenuRep.AsQueryable().Where(u => u.TenantId == input.Id).ToListAsync();
+
         // 删除旧记录
         await _sysTenantMenuRep.AsDeleteable().Where(u => u.TenantId == input.Id).ExecuteCommandAsync();
 
@@ -530,6 +533,14 @@ public class SysTenantService : IDynamicApiController, ITransient
 
         // 保存租户菜单
         var sysTenantMenuList = input.MenuIdList.Select(menuId => new SysTenantMenu { TenantId = input.Id, MenuId = menuId }).ToList();
+        
+        //原ID不变
+        foreach (var item in sysTenantMenuList)
+        {
+            var tenantMenu = tenantMenuList.FirstOrDefault(u => u.TenantId == item.TenantId && u.MenuId == item.MenuId);
+            if (tenantMenu != null) item.Id = tenantMenu.Id;
+        }
+
         await _sysTenantMenuRep.InsertRangeAsync(sysTenantMenuList);
 
         // 清除菜单权限缓存

+ 20 - 7
Admin.NET/Admin.NET.Web.Entry/wwwroot/template/Service.cs.vm

@@ -65,7 +65,7 @@ public partial class @(Model.ClassName)Service : IDynamicApiController, ITransie
             } else if (column.NetType.TrimEnd('?') == "int" || column.NetType.TrimEnd('?') == "long") {
             @:.WhereIF(input.@(column.PropertyName) != null, u => u.@(column.PropertyName) @(column.QueryType) input.@(column.PropertyName))
             } else if (column.NetType.TrimEnd('?').EndsWith("Enum")) {
-            @:.WhereIF(input.@(column.PropertyName).HasValue, u => u.@(column.PropertyName) == (int)input.@(column.PropertyName))
+            @:.WhereIF(input.@(column.PropertyName).HasValue, u => u.@(column.PropertyName) == input.@(column.PropertyName))
             } else if (column.NetType.TrimEnd('?') == "DateTime" && column.QueryType == "~") {
             @:.WhereIF(input.@(column.PropertyName)Range?.Length == 2, u => u.@(column.PropertyName) >= input.@(column.PropertyName)Range[0] && u.@(column.PropertyName) <= input.@(column.PropertyName)Range[1])
             } else if (column.NetType.TrimEnd('?').EndsWith("bool")) {
@@ -165,9 +165,16 @@ public partial class @(Model.ClassName)Service : IDynamicApiController, ITransie
     [ApiDescriptionSettings(Name = "Delete"), HttpPost]
     public async Task Delete(Delete@(Model.ClassName)Input input)
     {
-        var entity = await _@(Model.LowerClassName)Rep.GetFirstAsync(u => @Model.PrimaryKeysFormat(" && ", "u.{0} == input.{0}")) ?? throw Oops.Oh(ErrorCodeEnum.D1002);
-        await _@(Model.LowerClassName)Rep.FakeDeleteAsync(entity);   //假删除
-        //await _@(Model.LowerClassName)Rep.DeleteAsync(entity);   //真删除
+        var entity = await _@(Model.LowerClassName)Rep.GetFirstAsync(u => @Model.PrimaryKeysFormat(" && ", "u.{0} == input.{0}")) ?? throw Oops.Oh(ErrorCodeEnum.D1002); 
+@{ 
+    @if(Model.TableField.Where(x => x.ColumnName == "IsDelete").Any())
+    {
+        @:await _@(Model.LowerClassName)Rep.FakeDeleteAsync(entity);   //假删除
+    }
+    else{
+        @:await _@(Model.LowerClassName)Rep.DeleteAsync(entity);   //真删除 
+    }
+}  
     }
 
     /// <summary>
@@ -182,9 +189,15 @@ public partial class @(Model.ClassName)Service : IDynamicApiController, ITransie
         var exp = Expressionable.Create<@(Model.ClassName)>();
         foreach (var row in input) exp = exp.Or(it => @Model.PrimaryKeysFormat(" && ", "it.{0} == row.{0}"));
         var list = await _@(Model.LowerClassName)Rep.AsQueryable().Where(exp.ToExpression()).ToListAsync();
-   
-        return await _@(Model.LowerClassName)Rep.FakeDeleteAsync(list);   //假删除
-        //return await _@(Model.LowerClassName)Rep.DeleteAsync(list);   //真删除
+@{ 
+    @if(Model.TableField.Where(x => x.ColumnName == "IsDelete").Any())
+    {
+        @:return await _@(Model.LowerClassName)Rep.FakeDeleteAsync(list);   //假删除
+    }
+    else{ 
+        @:return await _@(Model.LowerClassName)Rep.Context.Deleteable(list).ExecuteCommandAsync();   //真删除--返回受影响的行数
+    }
+}  
     }
     @if (Model.HasSetStatus) {
     @:

+ 7 - 3
Admin.NET/Admin.NET.Web.Entry/wwwroot/template/editDialog.vue.vm

@@ -13,7 +13,9 @@ import type { FormRules } from "element-plus";
 @:import { useUserInfo } from "/@@/stores/userInfo";
 }
 import { use@(Model.ClassName)Api } from '/@@/api/@(Model.PagePath)/@(Model.LowerClassName)';
-
+@if(@Model.TableField.Any(x=>x.EffectType == "Editor")){
+@:import Editor from '/@@/components/editor/index.vue';
+}
 //父级传递来的函数,用于回调
 const emit = defineEmits(["reloadTable"]);
 const @(Model.LowerClassName)Api = use@(Model.ClassName)Api();
@@ -103,8 +105,8 @@ defineExpose({ openDialog });
 					}
 					@foreach (var column in Model.AddUpdateFieldList) {
 					var showStatus = Model.IsStatus(column) ? $"v-if=\"state.ruleForm.{Model.PrimaryKeyFieldList.First().LowerPropertyName}\" " : "";
-					if (column.EffectType == "InputTextArea"){
-						@:<el-col :xs="24" class="mb20" @showStatus>
+					if (column.EffectType == "InputTextArea"||column.EffectType == "Editor"){
+					@:<el-col :xs="24" class="mb20" @showStatus>
 							} else{
 						@:<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20" @showStatus>
 							} 
@@ -168,6 +170,8 @@ defineExpose({ openDialog });
 							@:<el-switch v-model="state.ruleForm.@(column.LowerPropertyName)" />
 						} else if (column.EffectType == "DatePicker") {
 							@:<el-date-picker v-model="state.ruleForm.@(column.LowerPropertyName)" type="date" placeholder="@(column.ColumnComment)" />
+						}else if(@column.EffectType == "Editor"){
+							@:<Editor v-model:get-html="state.ruleForm.@(@column.LowerPropertyName)" /> 
 						} else {
 							var inputType = column.EffectType == "InputTextArea" ? "type=\"textarea\" " : "";
 					        var maxlength = column.ColumnLength > 0 ? $"maxlength=\"{column.ColumnLength}\" " : "";

+ 1 - 13
README.md

@@ -14,7 +14,7 @@
 </div>
 
 ## 🎁框架介绍
-Admin.NET 是基于 .NET6 (Furion/SqlSugar) 实现的通用权限开发框架,前端采用 Vue3+Element-plus+Vite5,整合众多优秀技术和框架,模块插件式开发。集成多租户、缓存、数据校验、鉴权、事件总线、动态API、通讯、远程请求、任务调度、打印等众多黑科技。代码结构简单清晰,注释详尽,易于上手与二次开发,即便是复杂业务逻辑也能迅速实现,真正实现“开箱即用”。
+Admin.NET 是基于 .NET8/10 (Furion/SqlSugar) 实现的通用权限开发框架,前端采用 Vue3+Element-plus+Vite5,整合众多优秀技术和框架,模块插件式开发。集成多租户、缓存、数据校验、鉴权、事件总线、动态API、通讯、远程请求、任务调度、打印等众多黑科技。代码结构简单清晰,注释详尽,易于上手与二次开发,即便是复杂业务逻辑也能迅速实现,真正实现“开箱即用”。
 
 面向中小企业快速开发平台框架,框架采用主流技术开发设计,前后端分离架构模式。完美适配国产化软硬件环境,支持国产中间件、国产数据库、麒麟操作系统、Windows、Linux部署使用;集成国密加解密插件,使用SM2、SM3、SM4等国密算法进行签名、数据完整性保护;软件层面全面遵循等级保护测评要求,完全符合等保、密评要求。
 
@@ -96,18 +96,6 @@ Admin.NET 是基于 .NET6 (Furion/SqlSugar) 实现的通用权限开发框架,
 25. APIJSON:适配腾讯APIJSON协议,支持后端0代码,[使用文档](https://github.com/liaozb/APIJSON.NET)。
 26. 数据库视图:基于SqlSugar生成查询SQL + 表实体维护视图,可维护性更强。
 
-## 🛒应用商城
-
-🎖️[iMES工厂管家](https://imes.625sc.com):一款基于.NetCore3.1和Vue3的MES管理系统。项目亮点:模版打印,Excel模版导出,自定义实体扩展,移动端精美设计,大屏设计等功能。
-
-<table>
-    <tr>
-        <td><img src="https://gitee.com/zuohuaijun/Admin.NET/raw/next/doc/shop/iMES/1.png"/></td>
-        <td><img src="https://gitee.com/zuohuaijun/Admin.NET/raw/next/doc/shop/iMES/2.png"/></td>
-        <td><img src="https://gitee.com/zuohuaijun/Admin.NET/raw/next/doc/shop/iMES/3.png"/></td>
-        <td><img src="https://gitee.com/zuohuaijun/Admin.NET/raw/next/doc/shop/iMES/4.png"/></td>
-    </tr>
-</table>
 
 ## 🎀捐赠支持
 ```

+ 78 - 0
Web/src/api-services/apis/sys-code-gen-api.ts

@@ -566,6 +566,58 @@ export const SysCodeGenApiAxiosParamCreator = function (configuration?: Configur
                 options: localVarRequestOptions,
             };
         },
+/**
+         * 
+         * @summary 同步代码字段 🔖
+         * @param {UpdateCodeGenInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */ 
+        apiSysCodeFieldGenPost: async (body?: UpdateCodeGenInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/api/sysCodeGen/syncField`;
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, 'https://example.com');
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
+            }
+            const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+            // authentication Bearer required
+            // http bearer authentication required
+            if (configuration && configuration.accessToken) {
+                const accessToken = typeof configuration.accessToken === 'function'
+                    ? await configuration.accessToken()
+                    : await configuration.accessToken;
+                localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
+            }
+
+            localVarHeaderParameter['Content-Type'] = 'application/json-patch+json';
+
+            const query = new URLSearchParams(localVarUrlObj.search);
+            for (const key in localVarQueryParameter) {
+                query.set(key, localVarQueryParameter[key]);
+            }
+            for (const key in options.params) {
+                query.set(key, options.params[key]);
+            }
+            localVarUrlObj.search = (new URLSearchParams(query)).toString();
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+            const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
+            localVarRequestOptions.data =  needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
+
+            return {
+                url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
+                options: localVarRequestOptions,
+            };
+        }
+        
+
+
+
     }
 };
 
@@ -728,6 +780,20 @@ export const SysCodeGenApiFp = function(configuration?: Configuration) {
                 return axios.request(axiosRequestArgs);
             };
         },
+        /**
+         * 
+         * @summary 同步代码字段 🔖
+         * param {UpdateCodeGenInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async apiSysCodeFieldGenPost(body?: UpdateCodeGenInput,options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultListTableOutput>>> {
+            const localVarAxiosArgs = await SysCodeGenApiAxiosParamCreator(configuration).apiSysCodeFieldGenPost(body, options);
+            return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
+                const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
+                return axios.request(axiosRequestArgs);
+            };
+        },
     }
 };
 
@@ -976,4 +1042,16 @@ export class SysCodeGenApi extends BaseAPI {
     public async apiSysCodeGenUpdatePost(body?: UpdateCodeGenInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
         return SysCodeGenApiFp(this.configuration).apiSysCodeGenUpdatePost(body, options).then((request) => request(this.axios, this.basePath));
     }
+
+    /**
+     * 
+     * @summary 同步代码字段 🔖
+     * @param {UpdateCodeGenInput} [body] 
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof SysCodeGenApi
+     */
+    public async  apiSysCodeFieldGenPost(body?: UpdateCodeGenInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultListTableOutput>> {
+        return SysCodeGenApiFp(this.configuration).apiSysCodeFieldGenPost(body, options).then((request) => request(this.axios, this.basePath));
+    }
 }

+ 1 - 1
Web/src/layout/navBars/tagsView/tagsView.vue

@@ -601,7 +601,7 @@ watch(
 	background-color: var(--el-color-white);
 	border-bottom: 1px solid var(--next-border-color-light);
 	position: relative;
-	z-index: 1999;
+	z-index: 199;
 	:deep(.el-scrollbar__wrap) {
 		overflow-x: auto !important;
 	}

+ 5 - 5
Web/src/views/system/codeGen/index.vue

@@ -37,11 +37,11 @@
 				<el-table-column label="操作" width="280" fixed="right" align="center" show-overflow-tooltip>
 					<template #default="scope">
 						<el-button icon="ele-Delete" size="small" text type="danger" title="删除" @click="deleConfig(scope.row)" />
-						<el-button icon="ele-Edit" size="small" text type="primary" title="编辑" @click="openEditDialog(scope.row)" />
+						<el-button icon="ele-Edit" size="small" text type="primary" title="编辑并完全刷新字段列表" @click="openEditDialog(scope.row)" />
 						<el-button icon="ele-CopyDocument" size="small" text type="primary" title="复制" @click="openCopyDialog(scope.row)" />
 						<el-button icon="ele-View" size="small" text type="primary" title="预览" @click="handlePreview(scope.row)" />
 						<el-button icon="ele-Setting" size="small" text type="primary" title="配置" @click="openConfigDialog(scope.row)" />
-						<el-button icon="ele-Refresh" size="small" text type="primary" title="同步" @click="syncCodeGen(scope.row)" />
+						<el-button icon="ele-Refresh" size="small" text type="primary" title="同步字段并保留历史字段作用类型" @click="syncCodeGen(scope.row)" />
 						<el-button icon="ele-Position" size="small" text type="primary" @click="handleGenerate(scope.row)">生成</el-button>
 					</template>
 				</el-table-column>
@@ -187,14 +187,14 @@ const deleConfig = (row: any) => {
 
 // 同步生成
 const syncCodeGen = async (row: any) => {
-  ElMessageBox.confirm(`确定要同步吗?`, '提示', {
+  ElMessageBox.confirm(`确定要同步吗? (保留历史字段作用类型)`, '提示', {
     confirmButtonText: '确定',
     cancelButtonText: '取消',
     type: 'warning',
   }).then(async () => {
-	await getAPI(SysCodeGenApi).apiSysCodeGenUpdatePost(row);
+	await getAPI(SysCodeGenApi).apiSysCodeFieldGenPost(row);
     handleQuery();
-    ElMessage.success('同步成功');
+    ElMessage.success('同步字段列表成功');
   }).catch(() => {});
 }