Kaynağa Gözat

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

# Conflicts:
#	Web/package.json
多语言组件添加 DEEPSEEK 一键翻译功能
Cyrus Zhou 8 ay önce
ebeveyn
işleme
ce17de21fd

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

@@ -19,9 +19,9 @@
     <PackageReference Include="AspectCore.Extensions.Reflection" Version="2.4.0" />
     <PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
     <PackageReference Include="Elastic.Clients.Elasticsearch" Version="9.0.7" />
-    <PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.7.96" />
-    <PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.96" />
-    <PackageReference Include="Furion.Pure" Version="4.9.7.96" />
+    <PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.7.98" />
+    <PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.98" />
+    <PackageReference Include="Furion.Pure" Version="4.9.7.98" />
 	<PackageReference Include="Hardware.Info" Version="101.0.1.1" />
     <PackageReference Include="Hashids.net" Version="1.7.0" />
     <PackageReference Include="IPTools.China" Version="1.6.0" />
@@ -39,9 +39,9 @@
     <PackageReference Include="QRCoder" Version="1.6.0" />
     <PackageReference Include="RabbitMQ.Client" Version="7.1.2" />
     <PackageReference Include="SixLabors.ImageSharp.Web" Version="3.1.5" />
-    <PackageReference Include="SKIT.FlurlHttpClient.Wechat.Api" Version="3.10.0" />
-    <PackageReference Include="SKIT.FlurlHttpClient.Wechat.TenpayV3" Version="3.12.0" />
-    <PackageReference Include="SqlSugar.MongoDbCore" Version="5.1.4.220" />
+    <PackageReference Include="SKIT.FlurlHttpClient.Wechat.Api" Version="3.11.0" />
+    <PackageReference Include="SKIT.FlurlHttpClient.Wechat.TenpayV3" Version="3.13.0" />
+    <PackageReference Include="SqlSugar.MongoDbCore" Version="5.1.4.227" />
     <PackageReference Include="SqlSugarCore" Version="5.1.4.198" />
     <PackageReference Include="SSH.NET" Version="2025.0.0" />
     <PackageReference Include="System.Linq.Dynamic.Core" Version="1.6.6" />
@@ -71,7 +71,7 @@
     <PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" Version="9.0.7" />
     <PackageReference Include="Microsoft.AspNetCore.SignalR.StackExchangeRedis" Version="9.0.7" />
 	<PackageReference Include="Microsoft.PowerShell.SDK" Version="7.5.2" />
-	<PackageReference Include="XiHan.Framework.Utils" Version="0.11.5" />
+	<PackageReference Include="XiHan.Framework.Utils" Version="0.11.6" />
   </ItemGroup>
 
 </Project>

+ 14 - 0
Admin.NET/Admin.NET.Core/Service/LangText/Dto/SysLangTextInput.cs

@@ -259,3 +259,17 @@ public class ImportSysLangTextInput : BaseImportInput
     public string Content { get; set; }
     
 }
+/// <summary>
+/// 
+/// </summary>
+public class AiTranslateTextInput
+{
+    /// <summary>
+    /// 原文
+    /// </summary>
+    public string OriginalText { get; set; }
+    /// <summary>
+    /// 目标语言
+    /// </summary>
+    public string TargetLang { get; set; }
+}

+ 146 - 0
Admin.NET/Admin.NET.Core/Service/LangText/SysLangTextService.cs

@@ -6,6 +6,8 @@
 
 
 using AngleSharp.Dom;
+using Microsoft.AspNetCore.Components.Forms;
+using Newtonsoft.Json;
 
 namespace Admin.NET.Core.Service;
 
@@ -280,4 +282,148 @@ public partial class SysLangTextService : IDynamicApiController, ITransient
             return stream;
         }
     }
+    private const string SOURCE_LANG = "zh-cn";
+    private const string API_URL = "https://api.deepseek.com/v1/chat/completions";
+    private const string DEEPSEEK_API_KEY = "你的 API KEY";
+    /// <summary>
+    /// DEEPSEEK 翻译接口
+    /// </summary>
+    /// <returns></returns>
+    [DisplayName("DEEPSEEK 翻译接口")]
+    [ApiDescriptionSettings(Name = "AiTranslateText"), HttpPost]
+    public async Task<string> AiTranslateText(AiTranslateTextInput input)
+    {
+        if (string.IsNullOrEmpty(DEEPSEEK_API_KEY))
+        {
+            throw new InvalidOperationException("环境变量 DEEPSEEK_API_KEY 未定义");
+        }
+
+        using (HttpClient client = new HttpClient())
+        {
+            // 构建请求头
+            client.DefaultRequestHeaders.Add("Authorization", $"Bearer {DEEPSEEK_API_KEY}");
+
+            // 构建系统提示词
+            string systemPrompt = BuildSystemPrompt(input.TargetLang);
+
+            // 构建请求体
+            var requestBody = new
+            {
+                model = "deepseek-chat",
+                messages = new[]
+                {
+                    new { role = "system", content = systemPrompt },
+                    new { role = "user", content = input.OriginalText }
+                },
+                temperature = 0.3,
+                max_tokens = 2000
+            };
+
+            // 使用 Newtonsoft.Json 序列化
+            var json = JsonConvert.SerializeObject(requestBody);
+            var content = new StringContent(json, Encoding.UTF8, "application/json");
+
+            // 发送请求
+            HttpResponseMessage response = await client.PostAsync(API_URL, content);
+
+            // 处理响应
+            string responseBody = await response.Content.ReadAsStringAsync();
+
+            if (!response.IsSuccessStatusCode)
+            {
+                // 使用 Newtonsoft.Json 反序列化错误响应
+                var errorResponse = JsonConvert.DeserializeObject<ErrorResponse>(responseBody);
+                string errorMsg = errorResponse?.error?.message ?? $"HTTP {response.StatusCode}: {response.ReasonPhrase}";
+                throw new HttpRequestException($"翻译API返回错误:{errorMsg}");
+            }
+
+            // 解析有效响应
+            var result = JsonConvert.DeserializeObject<TranslationResponse>(responseBody);
+
+            if (result?.choices == null || result.choices.Length == 0 ||
+                result.choices[0]?.message?.content == null)
+            {
+                throw new InvalidOperationException("API返回无效的翻译结果");
+            }
+
+            return result.choices[0].message.content.Trim();
+        }
+    }
+    // JSON 响应模型
+    private class TranslationResponse
+    {
+        public Choice[] choices { get; set; }
+    }
+
+    private class Choice
+    {
+        public Message message { get; set; }
+    }
+
+    private class Message
+    {
+        public string content { get; set; }
+    }
+
+    private class ErrorResponse
+    {
+        public ErrorInfo error { get; set; }
+    }
+
+    private class ErrorInfo
+    {
+        public string message { get; set; }
+    }
+    /// <summary>
+    /// 生成提示词
+    /// </summary>
+    /// <param name="targetLang"></param>
+    /// <returns></returns>
+    private static string BuildSystemPrompt(string targetLang)
+    {
+        return $@"作为企业软件系统专业翻译,严格遵守以下铁律:
+
+■ 核心原则
+1. 严格逐符号翻译({SOURCE_LANG}→{targetLang})
+2. 禁止添加/删除/改写任何内容
+3. 保持批量翻译的编号格式
+
+■ 符号保留规则
+! 所有符号必须原样保留:
+• 编程符号:\${{ }} <% %> @ # & | 
+• UI占位符:{{0}} %s [ ] 
+• 货币单位:¥100.00 kg cm²
+• 中文符号:【 】 《 》 :
+
+■ 中文符号位置规范
+# 三级处理机制:
+1. 成对符号必须保持完整结构:
+   ✓ 正确:【Warning】Text
+   ✗ 禁止:Warning【 】Text
+   
+2. 独立符号位置:
+   • 优先句尾 → Text】?
+   • 次选句首 → 】Text?
+   • 禁止句中 → Text】Text?
+
+3. 跨字符串符号处理:
+   • 前段含【时 → 保留在段尾(""Synchronize【"")
+   • 后段含】时 → 保留在段首(""】authorization data?"")
+   • 符号后接字母时添加空格:】 Authorization
+
+■ 语法规范
+• 外文 → 被动语态(""Item was created"")
+• 中文 → 主动语态(""已创建项目"")
+• 禁止推测上下文(只翻译当前字符串内容)
+
+■ 错误预防(绝对禁止)
+✗ 将中文符号改为西式符号(】→])
+✗ 移动非中文符号位置
+✗ 添加原文不存在的内容
+✗ 合并/拆分原始字符串
+
+■ 批量处理
+▸ 严格保持原始JSON结构
+▸ 语言键名精确匹配(zh-cn/en/it等)";
+    }
 }

+ 2 - 2
Admin.NET/Admin.NET.Core/Service/Tenant/SysTenantService.cs

@@ -125,8 +125,8 @@ public class SysTenantService : IDynamicApiController, ITransient
         var tenantId = long.Parse(App.User?.FindFirst(ClaimConst.TenantId)?.Value ?? "0");
         var host = App.HttpContext.Request.Host.Host.ToLower();
         var tenant = await _sysTenantRep.AsQueryable()
-            .WhereIF(tenantId > 0, u => u.Id == tenantId && SqlFunc.ToLower(u.Host).Equals(host))
-            .WhereIF(!(tenantId > 0), u => SqlFunc.ToLower(u.Host).Equals(host))
+            .WhereIF(tenantId > 0, u => u.Id == tenantId && SqlFunc.ToLower(u.Host).Contains(host))
+            .WhereIF(!(tenantId > 0), u => SqlFunc.ToLower(u.Host).Contains(host))
             .FirstAsync();
         tenant ??= await _sysTenantRep.GetFirstAsync(u => u.Id == SqlSugarConst.DefaultTenantId);
         _ = tenant ?? throw Oops.Oh(ErrorCodeEnum.D1002);

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

@@ -101,8 +101,8 @@ public class SysUserService : IDynamicApiController, ITransient
         // 禁止越权新增超级管理员和系统管理员
         if (_userManager.AccountType != AccountTypeEnum.SuperAdmin && input.AccountType is AccountTypeEnum.SuperAdmin or AccountTypeEnum.SysAdmin) throw Oops.Oh(ErrorCodeEnum.D1038);
 
-        var password = await _sysConfigService.GetConfigValue<string>(ConfigConst.SysPassword);
-
+        // 若没有设置密码则取默认密码
+        var password = !string.IsNullOrWhiteSpace(input.Password) ? input.Password : await _sysConfigService.GetConfigValue<string>(ConfigConst.SysPassword);
         var user = input.Adapt<SysUser>();
         user.Password = CryptogramUtil.Encrypt(password);
         var newUser = await _sysUserRep.AsInsertable(user).ExecuteReturnEntityAsync();

+ 1 - 1
Admin.NET/Admin.NET.Core/Service/User/UserManager.cs

@@ -34,7 +34,7 @@ public class UserManager : IScoped
     public string RealName => _httpContextAccessor.HttpContext?.User.FindFirst(ClaimConst.RealName)?.Value;
 
     /// <summary>
-    /// 是否超级管理员
+    /// 账号类型
     /// </summary>
     public AccountTypeEnum? AccountType => int.TryParse(_httpContextAccessor.HttpContext?.User.FindFirst(ClaimConst.AccountType)?.Value, out var val) ? (AccountTypeEnum?)val : null;
 

+ 3 - 9
Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarSetup.cs

@@ -29,10 +29,9 @@ public static class SqlSugarSetup
 
         // 自定义 SqlSugar 雪花ID算法
         SnowFlakeSingle.WorkId = snowIdOpt.WorkerId;
-        StaticConfig.CustomSnowFlakeFunc = () =>
-        {
-            return YitIdHelper.NextId();
-        };
+        StaticConfig.CustomSnowFlakeFunc = YitIdHelper.NextId;
+        // 注册 MongoDb
+        InstanceFactory.CustomAssemblies = [typeof(SqlSugar.MongoDb.MongoDbProvider).Assembly];
         // 动态表达式 SqlFunc 支持,https://www.donet5.com/Home/Doc?typeId=2569
         StaticConfig.DynamicExpressionParserType = typeof(DynamicExpressionParser);
         StaticConfig.DynamicExpressionParsingConfig = new ParsingConfig
@@ -43,11 +42,6 @@ public static class SqlSugarSetup
         var dbOptions = App.GetConfig<DbConnectionOptions>("DbConnection", true);
         dbOptions.ConnectionConfigs.ForEach(SetDbConfig);
 
-        //注册DLL防止找不到DLL(扔在程序启动时)
-        InstanceFactory.CustomAssemblies = new System.Reflection.Assembly[] {
-            typeof(SqlSugar.MongoDb.MongoDbProvider).Assembly
-        };
-
         SqlSugarScope sqlSugar = new(dbOptions.ConnectionConfigs.Adapt<List<ConnectionConfig>>(), db =>
         {
             dbOptions.ConnectionConfigs.ForEach(config =>

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

@@ -12,11 +12,11 @@
     </PropertyGroup>
 
     <ItemGroup>
-      <PackageReference Include="Furion.Xunit" Version="4.9.7.96" />
+      <PackageReference Include="Furion.Xunit" Version="4.9.7.98" />
       <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
       <PackageReference Include="Selenium.Support" Version="4.34.0" />
       <PackageReference Include="Selenium.WebDriver" Version="4.34.0" />
-      <PackageReference Include="Selenium.WebDriver.MSEdgeDriver" Version="138.0.3351.65" />
+      <PackageReference Include="Selenium.WebDriver.MSEdgeDriver" Version="138.0.3351.83" />
       <PackageReference Include="xunit.assert" Version="2.9.3" />
     </ItemGroup>
 

+ 56 - 0
Web/lang/index.json

@@ -12381,5 +12381,61 @@
     "zh-tw": "列】",
     "en": "Column】",
     "it": "Colonna】"
+  },
+  "2jq3sh5": {
+    "zh-cn": "请输入: ",
+    "zh-hk": "請輸入:",
+    "zh-tw": "請輸入:",
+    "en": "Please enter:",
+    "it": "Inserisci:"
+  },
+  "1tjku4": {
+    "zh-cn": "AI翻译",
+    "zh-hk": "AI翻譯",
+    "zh-tw": "AI翻譯",
+    "en": "AI Translation",
+    "it": "Traduzione AI"
+  },
+  "fymq3d16": {
+    "zh-cn": "作为企业软件系统专业翻译,严格遵守以下铁律:\n\n■ 核心原则\n1. 严格逐符号翻译(",
+    "zh-hk": "作為企業軟件系統專業翻譯,嚴格遵守以下鐵律:",
+    "zh-tw": "作為企業軟體系統專業翻譯,嚴格遵守以下鐵律:",
+    "en": "As a professional enterprise software system translator, strictly adhere to the following iron rules:",
+    "it": "Come traduttore professionale di sistemi software aziendali, aderisco rigorosamente ai seguenti principi:"
+  },
+  "7p37ouhk": {
+    "zh-cn": ")\n2. 禁止添加/删除/改写任何内容\n3. 保持批量翻译的编号格式\n\n■ 符号保留规则\n! 所有符号必须原样保留:\n• 编程符号:\\${ } <% %> @ # & | \n• UI占位符:{0} %s [ ] \n• 货币单位:¥100.00 kg cm²\n• 中文符号:【 】 《 》 :\n\n■ 中文符号位置规范\n# 三级处理机制:\n1. 成对符号必须保持完整结构:\n   ✓ 正确:【Warning】Text\n   ✗ 禁止:Warning【 】Text\n   \n2. 独立符号位置:\n   • 优先句尾 → Text】?\n   • 次选句首 → 】Text?\n   • 禁止句中 → Text】Text?\n\n3. 跨字符串符号处理:\n   • 前段含【时 → 保留在段尾(\"Synchronize【\")\n   • 后段含】时 → 保留在段首(\"】authorization data?\")\n   • 符号后接字母时添加空格:】 Authorization\n\n■ 语法规范\n• 外文 → 被动语态(\"Item was created\")\n• 中文 → 主动语态(\"已创建项目\")\n• 禁止推测上下文(只翻译当前字符串内容)\n\n■ 错误预防(绝对禁止)\n✗ 将中文符号改为西式符号(】→])\n✗ 移动非中文符号位置\n✗ 添加原文不存在的内容\n✗ 合并/拆分原始字符串\n\n■ 批量处理\n▸ 严格保持原始JSON结构\n▸ 语言键名精确匹配(zh-cn/en/it等)",
+    "zh-hk": ")",
+    "zh-tw": ")",
+    "en": ")",
+    "it": ")"
+  },
+  "qhx1eya": {
+    "zh-cn": "翻译API返回错误:",
+    "zh-hk": "翻譯API返回錯誤:",
+    "zh-tw": "翻譯API返回錯誤:",
+    "en": "Translation API returned an error:",
+    "it": "Errore API traduzione:"
+  },
+  "s7bystp": {
+    "zh-cn": "环境变量 DEEPSEEK_API_KEY 未定义",
+    "zh-hk": "環境變量 DEEPSEEK_API_KEY 未定義",
+    "zh-tw": "環境變數 DEEPSEEK_API_KEY 未定義",
+    "en": "Environment variable DEEPSEEK_API_KEY not defined",
+    "it": "Variabile d'ambiente DEEPSEEK_API_KEY non definita"
+  },
+  "k2ng5l4": {
+    "zh-cn": "验证失败",
+    "zh-hk": "驗證失敗",
+    "zh-tw": "驗證失敗",
+    "en": "Verification failed",
+    "it": "Validazione fallita"
+  },
+  "kw130t7": {
+    "zh-cn": "正在翻译...",
+    "zh-hk": "正在翻譯...",
+    "zh-tw": "正在翻譯...",
+    "en": "Translating...",
+    "it": "Traduzione in corso..."
   }
 }

+ 10 - 10
Web/package.json

@@ -2,7 +2,7 @@
 	"name": "admin.net",
 	"type": "module",
 	"version": "2.4.33",
-	"lastBuildTime": "2025.07.12",
+	"lastBuildTime": "2025.07.19",
 	"description": "Admin.NET 站在巨人肩膀上的 .NET 通用权限开发框架",
 	"author": "zuohuaijun",
 	"license": "MIT",
@@ -44,10 +44,10 @@
 		"json-editor-vue": "^0.18.1",
 		"jsplumb": "^2.15.6",
 		"lodash-es": "^4.17.21",
-		"md-editor-v3": "^5.7.1",
+		"md-editor-v3": "^5.8.2",
 		"mitt": "^3.0.1",
 		"monaco-editor": "^0.52.2",
-		"mqtt": "^5.13.2",
+		"mqtt": "^5.13.3",
 		"nprogress": "^0.2.0",
 		"pinia": "^3.0.3",
 		"print-js": "^1.6.0",
@@ -56,7 +56,7 @@
 		"qs": "^6.14.0",
 		"relation-graph": "^2.2.11",
 		"screenfull": "^6.0.2",
-		"sm-crypto-v2": "^1.12.0",
+		"sm-crypto-v2": "^1.13.0",
 		"sortablejs": "^1.15.6",
 		"splitpanes": "^4.0.4",
 		"vcrontab-3": "^3.3.22",
@@ -66,7 +66,7 @@
 		"vue-demi": "^0.14.10",
 		"vue-draggable-plus": "^0.6.0",
 		"vue-grid-layout": "3.0.0-beta1",
-		"vue-i18n": "^11.1.9",
+		"vue-i18n": "^11.1.10",
 		"vue-json-pretty": "^2.5.0",
 		"vue-plugin-hiprint": "^0.0.60",
 		"vue-router": "^4.5.1",
@@ -82,25 +82,25 @@
 		"@types/node": "^22.16.4",
 		"@types/nprogress": "^0.2.3",
 		"@types/sortablejs": "^1.15.8",
-		"@typescript-eslint/eslint-plugin": "^8.36.0",
-		"@typescript-eslint/parser": "^8.36.0",
+		"@typescript-eslint/eslint-plugin": "^8.37.0",
+		"@typescript-eslint/parser": "^8.37.0",
 		"@vitejs/plugin-vue": "^6.0.0",
 		"@vitejs/plugin-vue-jsx": "^5.0.1",
 		"@vue/compiler-sfc": "^3.5.17",
 		"cli-progress": "^3.12.0",
-		"code-inspector-plugin": "^0.20.15",
+		"code-inspector-plugin": "^0.20.17",
 		"colors": "^1.4.0",
 		"dotenv": "^17.2.0",
 		"eslint": "^9.31.0",
 		"eslint-plugin-vue": "^10.3.0",
 		"globals": "^16.3.0",
-		"less": "^4.3.0",
+		"less": "^4.4.0",
 		"prettier": "^3.6.2",
 		"rollup-plugin-visualizer": "^6.0.3",
 		"sass": "^1.89.2",
 		"terser": "^5.43.1",
 		"typescript": "^5.8.3",
-		"vite": "^7.0.4",
+		"vite": "^7.0.5",
 		"vite-auto-i18n-plugin": "^1.1.5",
 		"vite-plugin-cdn-import": "^1.0.1",
 		"vite-plugin-compression2": "^2.2.0",

+ 1 - 0
Web/src/api-services/api.ts

@@ -29,6 +29,7 @@ export * from './apis/sys-file-api';
 export * from './apis/sys-job-api';
 export * from './apis/sys-lang-api';
 export * from './apis/sys-lang-text-api';
+export * from './apis/sys-lang-text-cache-api';
 export * from './apis/sys-ldap-api';
 export * from './apis/sys-log-diff-api';
 export * from './apis/sys-log-ex-api';

+ 78 - 0
Web/src/api-services/apis/sys-lang-text-api.ts

@@ -20,7 +20,9 @@ import { AddSysLangTextInput } from '../models';
 import { AdminResultInt64 } from '../models';
 import { AdminResultListSysLangTextOutput } from '../models';
 import { AdminResultSqlSugarPagedListSysLangTextOutput } from '../models';
+import { AdminResultString } from '../models';
 import { AdminResultSysLangText } from '../models';
+import { AiTranslateTextInput } from '../models';
 import { DeleteSysLangTextInput } from '../models';
 import { ImportSysLangTextInput } from '../models';
 import { ListSysLangTextInput } from '../models';
@@ -73,6 +75,47 @@ export const SysLangTextApiAxiosParamCreator = function (configuration?: Configu
                 options: localVarRequestOptions,
             };
         },
+        /**
+         * 
+         * @summary DEEPSEEK 翻译接口
+         * @param {AiTranslateTextInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        apiSysLangTextAiTranslateTextPost: async (body?: AiTranslateTextInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/api/sysLangText/aiTranslateText`;
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, 'https://example.com');
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
+            }
+            const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+            // authentication Bearer required
+
+            localVarHeaderParameter['Content-Type'] = 'application/json-patch+json';
+
+            const query = new URLSearchParams(localVarUrlObj.search);
+            for (const key in localVarQueryParameter) {
+                query.set(key, localVarQueryParameter[key]);
+            }
+            for (const key in options.params) {
+                query.set(key, options.params[key]);
+            }
+            localVarUrlObj.search = (new URLSearchParams(query)).toString();
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+            const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
+            localVarRequestOptions.data =  needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
+
+            return {
+                url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
+                options: localVarRequestOptions,
+            };
+        },
         /**
          * 
          * @summary 批量删除翻译表 ❌
@@ -517,6 +560,20 @@ export const SysLangTextApiFp = function(configuration?: Configuration) {
                 return axios.request(axiosRequestArgs);
             };
         },
+        /**
+         * 
+         * @summary DEEPSEEK 翻译接口
+         * @param {AiTranslateTextInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async apiSysLangTextAiTranslateTextPost(body?: AiTranslateTextInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultString>>> {
+            const localVarAxiosArgs = await SysLangTextApiAxiosParamCreator(configuration).apiSysLangTextAiTranslateTextPost(body, options);
+            return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
+                const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
+                return axios.request(axiosRequestArgs);
+            };
+        },
         /**
          * 
          * @summary 批量删除翻译表 ❌
@@ -675,6 +732,16 @@ export const SysLangTextApiFactory = function (configuration?: Configuration, ba
         async apiSysLangTextAddPost(body?: AddSysLangTextInput, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultInt64>> {
             return SysLangTextApiFp(configuration).apiSysLangTextAddPost(body, options).then((request) => request(axios, basePath));
         },
+        /**
+         * 
+         * @summary DEEPSEEK 翻译接口
+         * @param {AiTranslateTextInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async apiSysLangTextAiTranslateTextPost(body?: AiTranslateTextInput, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultString>> {
+            return SysLangTextApiFp(configuration).apiSysLangTextAiTranslateTextPost(body, options).then((request) => request(axios, basePath));
+        },
         /**
          * 
          * @summary 批量删除翻译表 ❌
@@ -795,6 +862,17 @@ export class SysLangTextApi extends BaseAPI {
     public async apiSysLangTextAddPost(body?: AddSysLangTextInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultInt64>> {
         return SysLangTextApiFp(this.configuration).apiSysLangTextAddPost(body, options).then((request) => request(this.axios, this.basePath));
     }
+    /**
+     * 
+     * @summary DEEPSEEK 翻译接口
+     * @param {AiTranslateTextInput} [body] 
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof SysLangTextApi
+     */
+    public async apiSysLangTextAiTranslateTextPost(body?: AiTranslateTextInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultString>> {
+        return SysLangTextApiFp(this.configuration).apiSysLangTextAiTranslateTextPost(body, options).then((request) => request(this.axios, this.basePath));
+    }
     /**
      * 
      * @summary 批量删除翻译表 ❌

+ 270 - 0
Web/src/api-services/apis/sys-lang-text-cache-api.ts

@@ -0,0 +1,270 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * Admin.NET 通用权限开发平台
+ * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。<br/><u><b><font color='FF0000'> 👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!</font></b></u>
+ *
+ * OpenAPI spec version: 1.0.0
+ * 
+ *
+ * NOTE: This class is auto generated by the swagger code generator program.
+ * https://github.com/swagger-api/swagger-codegen.git
+ * Do not edit the class manually.
+ */
+import globalAxios, { AxiosResponse, AxiosInstance, AxiosRequestConfig } from 'axios';
+import { Configuration } from '../configuration';
+// Some imports not used depending on template conditions
+// @ts-ignore
+import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError } from '../base';
+/**
+ * SysLangTextCacheApi - axios parameter creator
+ * @export
+ */
+export const SysLangTextCacheApiAxiosParamCreator = function (configuration?: Configuration) {
+    return {
+        /**
+         * 
+         * @summary 删除缓存
+         * @param {string} entityName 
+         * @param {string} fieldName 
+         * @param {number} entityId 
+         * @param {string} langCode 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        apiSysLangTextCacheCacheEntityNameFieldNameEntityIdLangCodeDelete: async (entityName: string, fieldName: string, entityId: number, langCode: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            // verify required parameter 'entityName' is not null or undefined
+            if (entityName === null || entityName === undefined) {
+                throw new RequiredError('entityName','Required parameter entityName was null or undefined when calling apiSysLangTextCacheCacheEntityNameFieldNameEntityIdLangCodeDelete.');
+            }
+            // verify required parameter 'fieldName' is not null or undefined
+            if (fieldName === null || fieldName === undefined) {
+                throw new RequiredError('fieldName','Required parameter fieldName was null or undefined when calling apiSysLangTextCacheCacheEntityNameFieldNameEntityIdLangCodeDelete.');
+            }
+            // verify required parameter 'entityId' is not null or undefined
+            if (entityId === null || entityId === undefined) {
+                throw new RequiredError('entityId','Required parameter entityId was null or undefined when calling apiSysLangTextCacheCacheEntityNameFieldNameEntityIdLangCodeDelete.');
+            }
+            // verify required parameter 'langCode' is not null or undefined
+            if (langCode === null || langCode === undefined) {
+                throw new RequiredError('langCode','Required parameter langCode was null or undefined when calling apiSysLangTextCacheCacheEntityNameFieldNameEntityIdLangCodeDelete.');
+            }
+            const localVarPath = `/api/sysLangTextCache/cache/{entityName}/{fieldName}/{entityId}/{langCode}`
+                .replace(`{${"entityName"}}`, encodeURIComponent(String(entityName)))
+                .replace(`{${"fieldName"}}`, encodeURIComponent(String(fieldName)))
+                .replace(`{${"entityId"}}`, encodeURIComponent(String(entityId)))
+                .replace(`{${"langCode"}}`, encodeURIComponent(String(langCode)));
+            // 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: 'DELETE', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+            // authentication Bearer required
+
+            const query = new URLSearchParams(localVarUrlObj.search);
+            for (const key in localVarQueryParameter) {
+                query.set(key, localVarQueryParameter[key]);
+            }
+            for (const key in options.params) {
+                query.set(key, options.params[key]);
+            }
+            localVarUrlObj.search = (new URLSearchParams(query)).toString();
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+
+            return {
+                url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
+                options: localVarRequestOptions,
+            };
+        },
+        /**
+         * 
+         * @summary 更新缓存
+         * @param {string} entityName 
+         * @param {string} fieldName 
+         * @param {number} entityId 
+         * @param {string} langCode 
+         * @param {string} newValue 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        apiSysLangTextCacheCacheEntityNameFieldNameEntityIdLangCodeNewValuePut: async (entityName: string, fieldName: string, entityId: number, langCode: string, newValue: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            // verify required parameter 'entityName' is not null or undefined
+            if (entityName === null || entityName === undefined) {
+                throw new RequiredError('entityName','Required parameter entityName was null or undefined when calling apiSysLangTextCacheCacheEntityNameFieldNameEntityIdLangCodeNewValuePut.');
+            }
+            // verify required parameter 'fieldName' is not null or undefined
+            if (fieldName === null || fieldName === undefined) {
+                throw new RequiredError('fieldName','Required parameter fieldName was null or undefined when calling apiSysLangTextCacheCacheEntityNameFieldNameEntityIdLangCodeNewValuePut.');
+            }
+            // verify required parameter 'entityId' is not null or undefined
+            if (entityId === null || entityId === undefined) {
+                throw new RequiredError('entityId','Required parameter entityId was null or undefined when calling apiSysLangTextCacheCacheEntityNameFieldNameEntityIdLangCodeNewValuePut.');
+            }
+            // verify required parameter 'langCode' is not null or undefined
+            if (langCode === null || langCode === undefined) {
+                throw new RequiredError('langCode','Required parameter langCode was null or undefined when calling apiSysLangTextCacheCacheEntityNameFieldNameEntityIdLangCodeNewValuePut.');
+            }
+            // verify required parameter 'newValue' is not null or undefined
+            if (newValue === null || newValue === undefined) {
+                throw new RequiredError('newValue','Required parameter newValue was null or undefined when calling apiSysLangTextCacheCacheEntityNameFieldNameEntityIdLangCodeNewValuePut.');
+            }
+            const localVarPath = `/api/sysLangTextCache/cache/{entityName}/{fieldName}/{entityId}/{langCode}/{newValue}`
+                .replace(`{${"entityName"}}`, encodeURIComponent(String(entityName)))
+                .replace(`{${"fieldName"}}`, encodeURIComponent(String(fieldName)))
+                .replace(`{${"entityId"}}`, encodeURIComponent(String(entityId)))
+                .replace(`{${"langCode"}}`, encodeURIComponent(String(langCode)))
+                .replace(`{${"newValue"}}`, encodeURIComponent(String(newValue)));
+            // 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: 'PUT', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+            // authentication Bearer required
+
+            const query = new URLSearchParams(localVarUrlObj.search);
+            for (const key in localVarQueryParameter) {
+                query.set(key, localVarQueryParameter[key]);
+            }
+            for (const key in options.params) {
+                query.set(key, options.params[key]);
+            }
+            localVarUrlObj.search = (new URLSearchParams(query)).toString();
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+
+            return {
+                url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
+                options: localVarRequestOptions,
+            };
+        },
+    }
+};
+
+/**
+ * SysLangTextCacheApi - functional programming interface
+ * @export
+ */
+export const SysLangTextCacheApiFp = function(configuration?: Configuration) {
+    return {
+        /**
+         * 
+         * @summary 删除缓存
+         * @param {string} entityName 
+         * @param {string} fieldName 
+         * @param {number} entityId 
+         * @param {string} langCode 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async apiSysLangTextCacheCacheEntityNameFieldNameEntityIdLangCodeDelete(entityName: string, fieldName: string, entityId: number, langCode: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<void>>> {
+            const localVarAxiosArgs = await SysLangTextCacheApiAxiosParamCreator(configuration).apiSysLangTextCacheCacheEntityNameFieldNameEntityIdLangCodeDelete(entityName, fieldName, entityId, langCode, options);
+            return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
+                const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
+                return axios.request(axiosRequestArgs);
+            };
+        },
+        /**
+         * 
+         * @summary 更新缓存
+         * @param {string} entityName 
+         * @param {string} fieldName 
+         * @param {number} entityId 
+         * @param {string} langCode 
+         * @param {string} newValue 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async apiSysLangTextCacheCacheEntityNameFieldNameEntityIdLangCodeNewValuePut(entityName: string, fieldName: string, entityId: number, langCode: string, newValue: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<void>>> {
+            const localVarAxiosArgs = await SysLangTextCacheApiAxiosParamCreator(configuration).apiSysLangTextCacheCacheEntityNameFieldNameEntityIdLangCodeNewValuePut(entityName, fieldName, entityId, langCode, newValue, options);
+            return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
+                const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
+                return axios.request(axiosRequestArgs);
+            };
+        },
+    }
+};
+
+/**
+ * SysLangTextCacheApi - factory interface
+ * @export
+ */
+export const SysLangTextCacheApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) {
+    return {
+        /**
+         * 
+         * @summary 删除缓存
+         * @param {string} entityName 
+         * @param {string} fieldName 
+         * @param {number} entityId 
+         * @param {string} langCode 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async apiSysLangTextCacheCacheEntityNameFieldNameEntityIdLangCodeDelete(entityName: string, fieldName: string, entityId: number, langCode: string, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
+            return SysLangTextCacheApiFp(configuration).apiSysLangTextCacheCacheEntityNameFieldNameEntityIdLangCodeDelete(entityName, fieldName, entityId, langCode, options).then((request) => request(axios, basePath));
+        },
+        /**
+         * 
+         * @summary 更新缓存
+         * @param {string} entityName 
+         * @param {string} fieldName 
+         * @param {number} entityId 
+         * @param {string} langCode 
+         * @param {string} newValue 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async apiSysLangTextCacheCacheEntityNameFieldNameEntityIdLangCodeNewValuePut(entityName: string, fieldName: string, entityId: number, langCode: string, newValue: string, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
+            return SysLangTextCacheApiFp(configuration).apiSysLangTextCacheCacheEntityNameFieldNameEntityIdLangCodeNewValuePut(entityName, fieldName, entityId, langCode, newValue, options).then((request) => request(axios, basePath));
+        },
+    };
+};
+
+/**
+ * SysLangTextCacheApi - object-oriented interface
+ * @export
+ * @class SysLangTextCacheApi
+ * @extends {BaseAPI}
+ */
+export class SysLangTextCacheApi extends BaseAPI {
+    /**
+     * 
+     * @summary 删除缓存
+     * @param {string} entityName 
+     * @param {string} fieldName 
+     * @param {number} entityId 
+     * @param {string} langCode 
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof SysLangTextCacheApi
+     */
+    public async apiSysLangTextCacheCacheEntityNameFieldNameEntityIdLangCodeDelete(entityName: string, fieldName: string, entityId: number, langCode: string, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
+        return SysLangTextCacheApiFp(this.configuration).apiSysLangTextCacheCacheEntityNameFieldNameEntityIdLangCodeDelete(entityName, fieldName, entityId, langCode, options).then((request) => request(this.axios, this.basePath));
+    }
+    /**
+     * 
+     * @summary 更新缓存
+     * @param {string} entityName 
+     * @param {string} fieldName 
+     * @param {number} entityId 
+     * @param {string} langCode 
+     * @param {string} newValue 
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof SysLangTextCacheApi
+     */
+    public async apiSysLangTextCacheCacheEntityNameFieldNameEntityIdLangCodeNewValuePut(entityName: string, fieldName: string, entityId: number, langCode: string, newValue: string, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
+        return SysLangTextCacheApiFp(this.configuration).apiSysLangTextCacheCacheEntityNameFieldNameEntityIdLangCodeNewValuePut(entityName, fieldName, entityId, langCode, newValue, options).then((request) => request(this.axios, this.basePath));
+    }
+}

+ 106 - 0
Web/src/api-services/models/page-sys-lang-text-input.ts

@@ -0,0 +1,106 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * Admin.NET 通用权限开发平台
+ * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。<br/><u><b><font color='FF0000'> 👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!</font></b></u>
+ *
+ * OpenAPI spec version: 1.0.0
+ * 
+ *
+ * NOTE: This class is auto generated by the swagger code generator program.
+ * https://github.com/swagger-api/swagger-codegen.git
+ * Do not edit the class manually.
+ */
+import { Filter } from './filter';
+import { Search } from './search';
+/**
+ * 翻译表分页查询输入参数
+ * @export
+ * @interface PageSysLangTextInput
+ */
+export interface PageSysLangTextInput {
+    /**
+     * 
+     * @type {Search}
+     * @memberof PageSysLangTextInput
+     */
+    search?: Search;
+    /**
+     * 模糊查询关键字
+     * @type {string}
+     * @memberof PageSysLangTextInput
+     */
+    keyword?: string | null;
+    /**
+     * 
+     * @type {Filter}
+     * @memberof PageSysLangTextInput
+     */
+    filter?: Filter;
+    /**
+     * 当前页码
+     * @type {number}
+     * @memberof PageSysLangTextInput
+     */
+    page?: number;
+    /**
+     * 页码容量
+     * @type {number}
+     * @memberof PageSysLangTextInput
+     */
+    pageSize?: number;
+    /**
+     * 排序字段
+     * @type {string}
+     * @memberof PageSysLangTextInput
+     */
+    field?: string | null;
+    /**
+     * 排序方向
+     * @type {string}
+     * @memberof PageSysLangTextInput
+     */
+    order?: string | null;
+    /**
+     * 降序排序
+     * @type {string}
+     * @memberof PageSysLangTextInput
+     */
+    descStr?: string | null;
+    /**
+     * 所属实体名
+     * @type {string}
+     * @memberof PageSysLangTextInput
+     */
+    entityName?: string | null;
+    /**
+     * 所属实体ID
+     * @type {number}
+     * @memberof PageSysLangTextInput
+     */
+    entityId?: number | null;
+    /**
+     * 字段名
+     * @type {string}
+     * @memberof PageSysLangTextInput
+     */
+    fieldName?: string | null;
+    /**
+     * 语言代码
+     * @type {string}
+     * @memberof PageSysLangTextInput
+     */
+    langCode?: string | null;
+    /**
+     * 翻译内容
+     * @type {string}
+     * @memberof PageSysLangTextInput
+     */
+    content?: string | null;
+    /**
+     * 选中主键列表
+     * @type {Array<number>}
+     * @memberof PageSysLangTextInput
+     */
+    selectKeyList?: Array<number> | null;
+}

+ 29 - 12
Web/src/components/multiLangInput/index.vue

@@ -15,7 +15,7 @@
                 <el-row :gutter="35">
                     <el-col v-for="lang in languages" :key="lang.code" :span="24">
                         <el-form-item :label="lang.label">
-                            <el-input v-model="multiLangValue[lang.code]" :placeholder="`请输入 ${lang.label}`"
+                            <el-input v-model="multiLangValue[lang.code]" :placeholder="`请输入: ${lang.label}`"
                                 clearable />
                         </el-form-item>
                     </el-col>
@@ -23,6 +23,7 @@
             </el-form>
 
             <template #footer>
+                <el-button @click="aiTranslation">AI翻译</el-button>
                 <el-button @click="closeDialog">关闭</el-button>
                 <el-button type="primary" @click="confirmDialog">确认修改</el-button>
             </template>
@@ -31,12 +32,13 @@
 </template>
 
 <script setup lang="ts">
-import { ref, computed, onMounted } from 'vue';
+import { ref, computed, onMounted, reactive } from 'vue';
 import { useLangStore } from '/@/stores/useLangStore';
 import { Local } from '/@/utils/storage';
 import { getAPI } from '/@/utils/axios-utils';
 import { SysLangTextApi } from '/@/api-services/api';
 import { ElMessage } from 'element-plus';
+
 const ruleFormRef = ref();
 
 const fetchMultiLang = async () => {
@@ -93,29 +95,44 @@ onMounted(async () => {
         activeLang.value = languages.value[0].code;
     }
 });
-
+const aiTranslation = async () => {
+    languages.value.forEach(async (element: { code: string | number; value: string | number; }) => {
+        if (element.code == currentLang.value) {
+            return;
+        }
+        multiLangValue.value[element.code] = '正在翻译...';
+        try {
+            const text = await getAPI(SysLangTextApi).apiSysLangTextAiTranslateTextPost({ originalText: props.modelValue, targetLang: element.value }).then(res => res.data.result);
+            if (text) {
+                multiLangValue.value[element.code] = text;
+            } else {
+                multiLangValue.value[element.code] = '';
+            }
+        } catch (e: any) {
+            multiLangValue.value[element.code] = '';
+            ElMessage.warning(e.message);
+        }
+    });
+}
 
 // 打开对话框(点击按钮)
-const openDialog = async () => {    
+const openDialog = async () => {
     multiLangValue.value = {};
     const res = await fetchMultiLang();
-    languages.value.forEach(element => {
-        multiLangValue.value[element.code] = props.modelValue;
-    });
-    res.forEach(element => {
+    multiLangValue.value[currentLang.value] = props.modelValue;
+    res.forEach((element: { langCode: string | number; content: string; }) => {
         multiLangValue.value[element.langCode] = element.content;
     });
     dialogVisible.value = true;
-	ruleFormRef.value?.resetFields();
+    ruleFormRef.value?.resetFields();
 };
 
 // 关闭对话框(只是关闭)
 const closeDialog = () => {
     dialogVisible.value = false;
     multiLangValue.value = {};
-	ruleFormRef.value?.resetFields();
+    ruleFormRef.value?.resetFields();
 };
-// 提交
 
 // 确认按钮(更新 + 关闭)
 const confirmDialog = async () => {
@@ -143,7 +160,7 @@ const confirmDialog = async () => {
         ElMessage.error('保存失败!');
     }
     dialogVisible.value = false;
-	ruleFormRef.value?.resetFields();
+    ruleFormRef.value?.resetFields();
 };
 </script>