diff --git a/main/manager-mobile/src/api/auth.ts b/main/manager-mobile/src/api/auth.ts index 07cc3fa8..83c0ecab 100644 --- a/main/manager-mobile/src/api/auth.ts +++ b/main/manager-mobile/src/api/auth.ts @@ -68,6 +68,7 @@ export interface PublicConfig { beianIcpNum: string beianGaNum: string name: string + sm2PublicKey: string } // 获取用户信息 diff --git a/main/manager-mobile/src/store/config.ts b/main/manager-mobile/src/store/config.ts index cb20b5fe..8abe4914 100644 --- a/main/manager-mobile/src/store/config.ts +++ b/main/manager-mobile/src/store/config.ts @@ -1,7 +1,7 @@ import type { PublicConfig } from '@/api/auth' +import { getPublicConfig } from '@/api/auth' import { defineStore } from 'pinia' import { ref } from 'vue' -import { getPublicConfig } from '@/api/auth' // 初始化状态 const initialConfigState: PublicConfig = { @@ -12,6 +12,7 @@ const initialConfigState: PublicConfig = { mobileAreaList: [], beianIcpNum: '', beianGaNum: '', + sm2PublicKey: '', name: import.meta.env.VITE_APP_TITLE, } diff --git a/main/manager-web/package-lock.json b/main/manager-web/package-lock.json index c104b60c..1b0c1a6e 100644 --- a/main/manager-web/package-lock.json +++ b/main/manager-web/package-lock.json @@ -10,13 +10,16 @@ "dependencies": { "core-js": "^3.41.0", "cross-env": "^7.0.3", + "dotenv": "^16.5.0", "element-ui": "^2.15.14", "flyio": "^0.6.14", "normalize.css": "^8.0.1", "opus-decoder": "^0.7.7", "opus-recorder": "^8.0.5", + "sm-crypto": "^0.3.13", "vue": "^2.6.14", "vue-axios": "^3.5.2", + "vue-i18n": "^8.28.2", "vue-router": "^3.6.5", "vuex": "^3.6.2", "xiaozhi": "file:" @@ -2540,6 +2543,16 @@ } } }, + "node_modules/@vue/cli-service/node_modules/dotenv": { + "version": "10.0.0", + "resolved": "https://registry.npmmirror.com/dotenv/-/dotenv-10.0.0.tgz", + "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=10" + } + }, "node_modules/@vue/cli-shared-utils": { "version": "5.0.8", "resolved": "https://registry.npmmirror.com/@vue/cli-shared-utils/-/cli-shared-utils-5.0.8.tgz", @@ -4776,12 +4789,15 @@ } }, "node_modules/dotenv": { - "version": "10.0.0", - "resolved": "https://registry.npmmirror.com/dotenv/-/dotenv-10.0.0.tgz", - "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", - "dev": true, + "version": "16.6.1", + "resolved": "https://registry.npmmirror.com/dotenv/-/dotenv-16.6.1.tgz", + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", + "license": "BSD-2-Clause", "engines": { - "node": ">=10" + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" } }, "node_modules/dotenv-expand": { @@ -10114,6 +10130,21 @@ "node": ">=8" } }, + "node_modules/sm-crypto": { + "version": "0.3.13", + "resolved": "https://registry.npmmirror.com/sm-crypto/-/sm-crypto-0.3.13.tgz", + "integrity": "sha512-ztNF+pZq6viCPMA1A6KKu3bgpkmYti5avykRHbcFIdSipFdkVmfUw2CnpM2kBJyppIalqvczLNM3wR8OQ0pT5w==", + "license": "MIT", + "dependencies": { + "jsbn": "^1.1.0" + } + }, + "node_modules/sm-crypto/node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", + "license": "MIT" + }, "node_modules/smob": { "version": "1.5.0", "resolved": "https://registry.npmmirror.com/smob/-/smob-1.5.0.tgz", @@ -11131,6 +11162,13 @@ "integrity": "sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==", "dev": true }, + "node_modules/vue-i18n": { + "version": "8.28.2", + "resolved": "https://registry.npmmirror.com/vue-i18n/-/vue-i18n-8.28.2.tgz", + "integrity": "sha512-C5GZjs1tYlAqjwymaaCPDjCyGo10ajUphiwA922jKt9n7KPpqR7oM1PCwYzhB/E7+nT3wfdG3oRre5raIT1rKA==", + "deprecated": "Vue I18n v8.x has reached EOL and is no longer actively maintained. About maintenance status, see https://vue-i18n.intlify.dev/guide/maintenance.html", + "license": "MIT" + }, "node_modules/vue-loader": { "version": "17.4.2", "resolved": "https://registry.npmmirror.com/vue-loader/-/vue-loader-17.4.2.tgz", diff --git a/main/manager-web/src/i18n/en.js b/main/manager-web/src/i18n/en.js index ae38c0e6..6d54d208 100644 --- a/main/manager-web/src/i18n/en.js +++ b/main/manager-web/src/i18n/en.js @@ -5,7 +5,7 @@ export default { 'login.requiredCaptcha': 'Captcha cannot be empty', 'login.requiredMobile': 'Please enter a valid mobile phone number', 'login.loginSuccess': 'Login successful!', - + // HeaderBar组件文本 'header.smartManagement': 'Agents', 'header.modelConfig': 'Models', @@ -38,7 +38,7 @@ export default { 'mcpToolCall.copyResult': 'Copy Result', 'mcpToolCall.noResultYet': 'No result yet', 'mcpToolCall.loadingToolList': 'Loading tool list...', - + // Tool names 'mcpToolCall.toolName.getDeviceStatus': 'View Device Status', 'mcpToolCall.toolName.setVolume': 'Set Volume', @@ -52,7 +52,7 @@ export default { 'mcpToolCall.toolName.snapshot': 'Screen Snapshot', 'mcpToolCall.toolName.previewImage': 'Preview Image', 'mcpToolCall.toolName.setDownloadUrl': 'Set Download URL', - + // Tool categories 'mcpToolCall.category.audio': 'Audio', 'mcpToolCall.category.display': 'Display', @@ -60,7 +60,7 @@ export default { 'mcpToolCall.category.system': 'System', 'mcpToolCall.category.assets': 'Assets', 'mcpToolCall.category.deviceInfo': 'Device Info', - + // Table categories and properties 'mcpToolCall.table.audioSpeaker': 'Audio Speaker', 'mcpToolCall.table.screen': 'Screen', @@ -80,7 +80,7 @@ export default { 'mcpToolCall.table.component': 'Component', 'mcpToolCall.table.property': 'Property', 'mcpToolCall.table.value': 'Value', - + 'mcpToolCall.prop.volume': 'Volume', 'mcpToolCall.prop.brightness': 'Brightness', 'mcpToolCall.prop.theme': 'Theme', @@ -112,7 +112,7 @@ export default { 'mcpToolCall.prop.url': 'URL', 'mcpToolCall.prop.quality': 'Quality', 'mcpToolCall.prop.question': 'Question', - + // Tool help texts 'mcpToolCall.help.getDeviceStatus': 'View the current running status of the device, including volume, screen, battery and other information.', 'mcpToolCall.help.setVolume': 'Adjust the volume of the device, please enter a value between 0-100.', @@ -126,7 +126,7 @@ export default { 'mcpToolCall.help.snapshot': 'Take a screenshot of the current screen and upload it to the specified URL.', 'mcpToolCall.help.previewImage': 'Preview images from the specified URL on the device screen.', 'mcpToolCall.help.setDownloadUrl': 'Set the download address for device resource files.', - + // Other text 'mcpToolCall.text.strong': 'Strong', 'mcpToolCall.text.medium': 'Medium', @@ -231,7 +231,7 @@ export default { // AddModelDialog component related 'addModelDialog.requiredSupplier': 'Please select a supplier', - + // Register page related 'register.title': 'Create Account', 'register.welcome': 'Welcome to XiaoZhi AI', @@ -632,7 +632,7 @@ export default { 'providerManagement.selectToDelete': 'Please select providers to delete first', 'providerManagement.confirmDelete': 'Are you sure to delete the selected {count} providers?', 'providerManagement.viewFields': 'View Fields', - + // Common Text 'common.all': 'All', 'common.search': 'Search', @@ -662,7 +662,7 @@ export default { 'common.confirm': 'Confirm', 'common.cancel': 'Cancel', 'common.sensitive': 'Sensitive', - + // Language switch 'language.zhCN': '中文简体', 'language.zhTW': '中文繁體', @@ -1030,7 +1030,7 @@ export default { 'agentTemplateManagement.batchDeleteFailed': 'Template batch deletion failed', 'agentTemplateManagement.deleteBackendError': 'Deletion failed, please check if the backend service is normal', 'agentTemplateManagement.deleteCancelled': 'Deletion cancelled', - + // templateQuickConfig 'templateQuickConfig.title': 'Module Quick Configuration', 'templateQuickConfig.agentSettings.agentName': 'Nickname', @@ -1050,7 +1050,6 @@ export default { 'info': 'Info', 'common.networkError': 'Network request failed', 'sm2.publicKeyNotConfigured': 'SM2 public key not configured, please contact administrator', - 'sm2.failedToGetPublicKey': 'Failed to get SM2 public key', 'sm2.encryptionFailed': 'Password encryption failed', 'sm2.keyGenerationFailed': 'Key pair generation failed', 'sm2.invalidPublicKey': 'Invalid public key format', diff --git a/main/manager-web/src/i18n/zh_CN.js b/main/manager-web/src/i18n/zh_CN.js index 28183c66..dc35ff5f 100644 --- a/main/manager-web/src/i18n/zh_CN.js +++ b/main/manager-web/src/i18n/zh_CN.js @@ -5,7 +5,7 @@ export default { 'login.requiredCaptcha': '验证码不能为空', 'login.requiredMobile': '请输入正确的手机号码', 'login.loginSuccess': '登录成功!', - + // HeaderBar组件文本 'header.smartManagement': '智能体管理', 'header.modelConfig': '模型配置', @@ -38,7 +38,7 @@ export default { 'mcpToolCall.copyResult': '复制结果', 'mcpToolCall.noResultYet': '暂无执行结果', 'mcpToolCall.loadingToolList': '正在获取工具列表...', - + // 工具名称 'mcpToolCall.toolName.getDeviceStatus': '查看设备状态', 'mcpToolCall.toolName.setVolume': '设置音量', @@ -52,7 +52,7 @@ export default { 'mcpToolCall.toolName.snapshot': '屏幕截图', 'mcpToolCall.toolName.previewImage': '预览图片', 'mcpToolCall.toolName.setDownloadUrl': '设置下载地址', - + // 工具分类 'mcpToolCall.category.audio': '音频', 'mcpToolCall.category.display': '显示', @@ -60,7 +60,7 @@ export default { 'mcpToolCall.category.system': '系统', 'mcpToolCall.category.assets': '资源', 'mcpToolCall.category.deviceInfo': '设备信息', - + // 表格分类和属性 'mcpToolCall.table.audioSpeaker': '音频扬声器', 'mcpToolCall.table.screen': '屏幕', @@ -80,7 +80,7 @@ export default { 'mcpToolCall.table.component': '组件', 'mcpToolCall.table.property': '属性', 'mcpToolCall.table.value': '值', - + 'mcpToolCall.prop.volume': '音量', 'mcpToolCall.prop.brightness': '亮度', 'mcpToolCall.prop.theme': '主题', @@ -112,7 +112,7 @@ export default { 'mcpToolCall.prop.url': 'URL', 'mcpToolCall.prop.quality': '质量', 'mcpToolCall.prop.question': '问题', - + // 工具帮助文本 'mcpToolCall.help.getDeviceStatus': '查看设备的当前运行状态,包括音量、屏幕、电池等信息。', 'mcpToolCall.help.setVolume': '调整设备的音量大小,请输入0-100之间的数值。', @@ -126,7 +126,7 @@ export default { 'mcpToolCall.help.snapshot': '对当前屏幕进行截图并上传到指定URL。', 'mcpToolCall.help.previewImage': '在设备屏幕上预览指定URL的图片。', 'mcpToolCall.help.setDownloadUrl': '设置设备资源文件的下载地址。', - + // 其他文本 'mcpToolCall.text.strong': '强', 'mcpToolCall.text.medium': '中', @@ -231,7 +231,7 @@ export default { // AddModelDialog组件相关 'addModelDialog.requiredSupplier': '请选择供应器', - + // 注册页面相关 'register.title': '创建账号', 'register.welcome': '欢迎使用小智AI', @@ -259,7 +259,7 @@ export default { 'register.requiredPassword': '密码不能为空', 'register.requiredCaptcha': '验证码不能为空', 'register.requiredMobileCaptcha': '请输入短信验证码', - + 'manualAddDeviceDialog.deviceType': '设备型号', 'manualAddDeviceDialog.deviceTypePlaceholder': '请选择设备型号', 'manualAddDeviceDialog.firmwareVersion': '固件版本', @@ -632,7 +632,7 @@ export default { 'providerManagement.selectToDelete': '请先选择需要删除的供应器', 'providerManagement.confirmDelete': '确定要删除选中的{count}个供应器吗?', 'providerManagement.viewFields': '查看字段', - + // 公共文本 'common.all': '全部', 'common.search': '搜索', @@ -1030,7 +1030,7 @@ export default { 'agentTemplateManagement.deleteFailed': '模板删除失败', 'agentTemplateManagement.batchDeleteFailed': '模板批量删除失败', 'agentTemplateManagement.deleteBackendError': '删除失败,请检查后端服务是否正常', - + // 模板快速配置页面文本 'templateQuickConfig.title': '模块快速配置', 'templateQuickConfig.agentSettings.agentName': '助手昵称', @@ -1051,7 +1051,6 @@ export default { 'common.networkError': '网络请求失败', // SM2加密相关错误消息 'sm2.publicKeyNotConfigured': 'SM2公钥未配置,请联系管理员', - 'sm2.failedToGetPublicKey': '获取SM2公钥失败', 'sm2.encryptionFailed': '密码加密失败', 'sm2.keyGenerationFailed': '密钥对生成失败', 'sm2.invalidPublicKey': '无效的公钥格式', diff --git a/main/manager-web/src/i18n/zh_TW.js b/main/manager-web/src/i18n/zh_TW.js index b34edd1d..3fda572e 100644 --- a/main/manager-web/src/i18n/zh_TW.js +++ b/main/manager-web/src/i18n/zh_TW.js @@ -5,7 +5,7 @@ export default { 'login.requiredCaptcha': '驗證碼不能為空', 'login.requiredMobile': '請輸入正確的手機號碼', 'login.loginSuccess': '登錄成功!', - + // HeaderBar组件文本 'header.smartManagement': '智能體管理', 'header.modelConfig': '模型配置', @@ -38,7 +38,7 @@ export default { 'mcpToolCall.copyResult': '複製結果', 'mcpToolCall.noResultYet': '暫無執行結果', 'mcpToolCall.loadingToolList': '正在獲取工具列表...', - + // 工具名稱 'mcpToolCall.toolName.getDeviceStatus': '查看設備狀態', 'mcpToolCall.toolName.setVolume': '設置音量', @@ -52,7 +52,7 @@ export default { 'mcpToolCall.toolName.snapshot': '螢幕截圖', 'mcpToolCall.toolName.previewImage': '預覽圖片', 'mcpToolCall.toolName.setDownloadUrl': '設置下載地址', - + // 工具分類 'mcpToolCall.category.audio': '音頻', 'mcpToolCall.category.display': '顯示', @@ -60,7 +60,7 @@ export default { 'mcpToolCall.category.system': '系統', 'mcpToolCall.category.assets': '資源', 'mcpToolCall.category.deviceInfo': '設備資訊', - + // 表格分類和屬性 'mcpToolCall.table.audioSpeaker': '音頻揚聲器', 'mcpToolCall.table.screen': '螢幕', @@ -80,7 +80,7 @@ export default { 'mcpToolCall.table.component': '組件', 'mcpToolCall.table.property': '屬性', 'mcpToolCall.table.value': '值', - + 'mcpToolCall.prop.volume': '音量', 'mcpToolCall.prop.brightness': '亮度', 'mcpToolCall.prop.theme': '主題', @@ -112,7 +112,7 @@ export default { 'mcpToolCall.prop.url': 'URL', 'mcpToolCall.prop.quality': '品質', 'mcpToolCall.prop.question': '問題', - + // 工具幫助文本 'mcpToolCall.help.getDeviceStatus': '查看設備的當前運行狀態,包括音量、螢幕、電池等資訊。', 'mcpToolCall.help.setVolume': '調整設備的音量大小,請輸入0-100之間的數值。', @@ -126,7 +126,7 @@ export default { 'mcpToolCall.help.snapshot': '對當前螢幕進行截圖並上傳到指定URL。', 'mcpToolCall.help.previewImage': '在設備螢幕上預覽指定URL的圖片。', 'mcpToolCall.help.setDownloadUrl': '設置設備資源文件的下載地址。', - + // 其他文本 'mcpToolCall.text.strong': '強', 'mcpToolCall.text.medium': '中', @@ -231,7 +231,7 @@ export default { // AddModelDialog組件相關 'addModelDialog.requiredSupplier': '請選擇供應器', - + // 註冊頁面相關 'register.title': '建立帳號', 'register.welcome': '歡迎使用小智慧AI', @@ -260,7 +260,7 @@ export default { 'register.requiredPassword': '密碼不能為空', 'register.requiredCaptcha': '驗證碼不能為空', 'register.requiredMobileCaptcha': '請輸入簡訊驗證碼', - + 'manualAddDeviceDialog.deviceType': '設備型號', 'manualAddDeviceDialog.deviceTypePlaceholder': '請選擇設備型號', 'manualAddDeviceDialog.firmwareVersion': '固件版本', @@ -549,41 +549,41 @@ export default { 'voiceprint.delete': '刪除聲紋', // 字典管理頁面文本 - 'dictManagement.pageTitle': '字典管理', - 'dictManagement.searchPlaceholder': '請輸入字典值標籤查詢', - 'dictManagement.search': '搜索', - 'dictManagement.dictTypeName': '字典類型名稱', - 'dictManagement.operation': '操作', - 'dictManagement.edit': '編輯', - 'dictManagement.dictLabel': '字典標籤', - 'dictManagement.dictValue': '字典值', - 'dictManagement.sort': '排序', - 'dictManagement.delete': '刪除', - 'dictManagement.selectAll': '全選', - 'dictManagement.deselectAll': '取消全選', - 'dictManagement.addDictType': '新增字典類型', - 'dictManagement.batchDeleteDictType': '批量刪除字典類型', - 'dictManagement.addDictData': '新增字典數據', - 'dictManagement.batchDeleteDictData': '批量刪除字典數據', - 'dictManagement.itemsPerPage': '{items}條/頁', - 'dictManagement.firstPage': '首頁', - 'dictManagement.prevPage': '上一頁', - 'dictManagement.nextPage': '下一頁', - 'dictManagement.totalRecords': '共{total}條記錄', - 'dictManagement.editDictType': '編輯字典類型', - 'dictManagement.editDictData': '編輯字典數據', - 'dictManagement.saveSuccess': '保存成功', - 'dictManagement.deleteSuccess': '刪除成功', - 'dictManagement.selectDictTypeToDelete': '請選擇要刪除的字典類型', - 'dictManagement.confirmDeleteDictType': '確定要刪除選中的字典類型嗎?', - 'dictManagement.confirm': '確定', - 'dictManagement.cancel': '取消', - 'dictManagement.selectDictTypeFirst': '請先選擇字典類型', - 'dictManagement.confirmDeleteDictData': '確定要刪除該字典數據嗎?', - 'dictManagement.selectDictDataToDelete': '請選擇要刪除的字典數據', - 'dictManagement.confirmBatchDeleteDictData': '確定要刪除選中的{count}個字典數據嗎?', + 'dictManagement.pageTitle': '字典管理', + 'dictManagement.searchPlaceholder': '請輸入字典值標籤查詢', + 'dictManagement.search': '搜索', + 'dictManagement.dictTypeName': '字典類型名稱', + 'dictManagement.operation': '操作', + 'dictManagement.edit': '編輯', + 'dictManagement.dictLabel': '字典標籤', + 'dictManagement.dictValue': '字典值', + 'dictManagement.sort': '排序', + 'dictManagement.delete': '刪除', + 'dictManagement.selectAll': '全選', + 'dictManagement.deselectAll': '取消全選', + 'dictManagement.addDictType': '新增字典類型', + 'dictManagement.batchDeleteDictType': '批量刪除字典類型', + 'dictManagement.addDictData': '新增字典數據', + 'dictManagement.batchDeleteDictData': '批量刪除字典數據', + 'dictManagement.itemsPerPage': '{items}條/頁', + 'dictManagement.firstPage': '首頁', + 'dictManagement.prevPage': '上一頁', + 'dictManagement.nextPage': '下一頁', + 'dictManagement.totalRecords': '共{total}條記錄', + 'dictManagement.editDictType': '編輯字典類型', + 'dictManagement.editDictData': '編輯字典數據', + 'dictManagement.saveSuccess': '保存成功', + 'dictManagement.deleteSuccess': '刪除成功', + 'dictManagement.selectDictTypeToDelete': '請選擇要刪除的字典類型', + 'dictManagement.confirmDeleteDictType': '確定要刪除選中的字典類型嗎?', + 'dictManagement.confirm': '確定', + 'dictManagement.cancel': '取消', + 'dictManagement.selectDictTypeFirst': '請先選擇字典類型', + 'dictManagement.confirmDeleteDictData': '確定要刪除該字典數據嗎?', + 'dictManagement.selectDictDataToDelete': '請選擇要刪除的字典數據', + 'dictManagement.confirmBatchDeleteDictData': '確定要刪除選中的{count}個字典數據嗎?', 'dictManagement.getDictDataFailed': '獲取字典數據失敗', - + // 用户信息 'user.info': '用戶信息', 'user.username': '用戶名', @@ -1006,31 +1006,31 @@ export default { 'providerDialog.batchDeleteFieldsSuccess': '成功刪除{count}個字段', // 預設角色管理頁面文本 - 'agentTemplateManagement.title': '預設角色管理', - 'agentTemplateManagement.templateName': '模板名稱', - 'agentTemplateManagement.action': '操作', - 'templateQuickConfig.saveSuccess': '配置保存成功', - 'templateQuickConfig.saveFailed': '配置保存失敗', - 'agentTemplateManagement.createTemplate': '建立模板', - 'agentTemplateManagement.editTemplate': '編輯模板', - 'agentTemplateManagement.deleteTemplate': '刪除模板', - 'agentTemplateManagement.deleteSuccess': '模板刪除成功', - 'agentTemplateManagement.batchDelete': '批次刪除', - 'agentTemplateManagement.batchDeleteSuccess': '批次刪除成功', - 'agentTemplateManagement.selectTemplate': '請選擇模板', - 'agentTemplateManagement.select': '選擇', - 'agentTemplateManagement.searchPlaceholder': '請輸入模板名稱搜尋', - 'agentTemplateManagement.search': '搜尋', - 'agentTemplateManagement.serialNumber': '序號', - 'agentTemplateManagement.selectAll': '全選', - 'agentTemplateManagement.deselectAll': '取消全選', - 'agentTemplateManagement.loading': '拼命加載中', - 'agentTemplateManagement.confirmSingleDelete': '確定要刪除這個模板嗎?', - 'agentTemplateManagement.confirmBatchDelete': '確定要刪除選中的 {count} 個模板嗎?', - 'agentTemplateManagement.deleteFailed': '模板刪除失敗', - 'agentTemplateManagement.batchDeleteFailed': '模板批次刪除失敗', + 'agentTemplateManagement.title': '預設角色管理', + 'agentTemplateManagement.templateName': '模板名稱', + 'agentTemplateManagement.action': '操作', + 'templateQuickConfig.saveSuccess': '配置保存成功', + 'templateQuickConfig.saveFailed': '配置保存失敗', + 'agentTemplateManagement.createTemplate': '建立模板', + 'agentTemplateManagement.editTemplate': '編輯模板', + 'agentTemplateManagement.deleteTemplate': '刪除模板', + 'agentTemplateManagement.deleteSuccess': '模板刪除成功', + 'agentTemplateManagement.batchDelete': '批次刪除', + 'agentTemplateManagement.batchDeleteSuccess': '批次刪除成功', + 'agentTemplateManagement.selectTemplate': '請選擇模板', + 'agentTemplateManagement.select': '選擇', + 'agentTemplateManagement.searchPlaceholder': '請輸入模板名稱搜尋', + 'agentTemplateManagement.search': '搜尋', + 'agentTemplateManagement.serialNumber': '序號', + 'agentTemplateManagement.selectAll': '全選', + 'agentTemplateManagement.deselectAll': '取消全選', + 'agentTemplateManagement.loading': '拼命加載中', + 'agentTemplateManagement.confirmSingleDelete': '確定要刪除這個模板嗎?', + 'agentTemplateManagement.confirmBatchDelete': '確定要刪除選中的 {count} 個模板嗎?', + 'agentTemplateManagement.deleteFailed': '模板刪除失敗', + 'agentTemplateManagement.batchDeleteFailed': '模板批次刪除失敗', 'agentTemplateManagement.deleteBackendError': '刪除失敗,請檢查後端服務是否正常', - + // 模板快速配置 'templateQuickConfig.title': '模組快速設定', 'templateQuickConfig.agentSettings.agentName': '助手暱稱', @@ -1052,7 +1052,6 @@ export default { // SM2加密相關錯誤消息 'sm2.publicKeyNotConfigured': 'SM2公鑰未配置,請聯繫管理員', - 'sm2.failedToGetPublicKey': '獲取SM2公鑰失敗', 'sm2.encryptionFailed': '密碼加密失敗', 'sm2.keyGenerationFailed': '金鑰對生成失敗', 'sm2.invalidPublicKey': '無效的公鑰格式', diff --git a/main/manager-web/src/store/index.js b/main/manager-web/src/store/index.js index 08dd5042..b6b61685 100644 --- a/main/manager-web/src/store/index.js +++ b/main/manager-web/src/store/index.js @@ -15,7 +15,8 @@ export default new Vuex.Store({ version: '', beianIcpNum: 'null', beianGaNum: 'null', - allowUserRegister: false + allowUserRegister: false, + sm2PublicKey: '' } }, getters: { diff --git a/main/manager-web/src/views/login.vue b/main/manager-web/src/views/login.vue index 2dd9761c..fc9c271e 100644 --- a/main/manager-web/src/views/login.vue +++ b/main/manager-web/src/views/login.vue @@ -148,9 +148,8 @@ import Api from "@/apis/api"; import VersionFooter from "@/components/VersionFooter.vue"; import i18n, { changeLanguage } from "@/i18n"; -import { getUUID, goToPage, showDanger, showSuccess, validateMobile, sm2Encrypt } from "@/utils"; +import { getUUID, goToPage, showDanger, showSuccess, sm2Encrypt, validateMobile } from "@/utils"; import { mapState } from "vuex"; -import Constant from "@/utils/constant"; export default { name: "login", @@ -162,6 +161,7 @@ export default { allowUserRegister: (state) => state.pubConfig.allowUserRegister, enableMobileRegister: (state) => state.pubConfig.enableMobileRegister, mobileAreaList: (state) => state.pubConfig.mobileAreaList, + sm2PublicKey: (state) => state.pubConfig.sm2PublicKey, }), // 获取当前语言 currentLanguage() { @@ -197,7 +197,6 @@ export default { captchaUrl: "", isMobileLogin: false, languageDropdownVisible: false, - serverPublicKey: "", // 服务器公钥 }; }, mounted() { @@ -206,38 +205,8 @@ export default { // 根据配置决定默认登录方式 this.isMobileLogin = this.enableMobileRegister; }); - // 获取服务器公钥 - this.getServerPublicKey(); }, methods: { - // 获取服务器公钥 - getServerPublicKey() { - // 先从本地存储获取 - const storedPublicKey = localStorage.getItem(Constant.STORAGE_KEY.PUBLIC_KEY); - if (storedPublicKey) { - this.serverPublicKey = storedPublicKey; - return; - } - - // 从公共配置接口获取公钥 - Api.user.getPubConfig( - (res) => { - if (res.data && res.data.data && res.data.data.sm2PublicKey) { - this.serverPublicKey = res.data.data.sm2PublicKey; - // 存储到本地 - localStorage.setItem(Constant.STORAGE_KEY.PUBLIC_KEY, this.serverPublicKey); - } else { - showDanger(this.$t('sm2.failedToGetPublicKey')); - } - }, - (err) => { - showDanger(this.$t('sm2.failedToGetPublicKey')); - } - ); - }, - - - fetchCaptcha() { if (this.$store.getters.getToken) { if (this.$route.path !== "/home") { @@ -316,40 +285,12 @@ export default { if (!this.validateInput(this.form.captcha, 'login.requiredCaptcha')) { return; } - - // 检查服务器公钥是否已获取,如果未获取则重新获取 - if (!this.serverPublicKey) { - try { - // 等待公钥获取完成 - await new Promise((resolve, reject) => { - this.getServerPublicKey(); - // 设置超时检查,最多等待3秒 - const checkInterval = setInterval(() => { - if (this.serverPublicKey) { - clearInterval(checkInterval); - resolve(); - } - }, 100); - - setTimeout(() => { - clearInterval(checkInterval); - if (!this.serverPublicKey) { - reject(new Error('获取公钥超时')); - } - }, 3000); - }); - } catch (error) { - showDanger(this.$t('sm2.failedToGetPublicKey')); - return; - } - } - // 加密密码 let encryptedPassword; try { // 拼接验证码和密码 const captchaAndPassword = this.form.captcha + this.form.password; - encryptedPassword = sm2Encrypt(this.serverPublicKey, captchaAndPassword); + encryptedPassword = sm2Encrypt(this.sm2PublicKey, captchaAndPassword); } catch (error) { console.error("密码加密失败:", error); showDanger(this.$t('sm2.encryptionFailed')); @@ -359,7 +300,7 @@ export default { const plainUsername = this.form.username; this.form.captchaId = this.captchaUuid; - + // 加密 const loginData = { username: plainUsername, @@ -377,7 +318,7 @@ export default { (err) => { // 直接使用后端返回的国际化消息 let errorMessage = err.data.msg || "登录失败"; - + showDanger(errorMessage); if ( err.data != null && @@ -410,8 +351,7 @@ export default { .login-type-container { margin: 10px 20px; display: flex; - justify-content: space-between; - align-items: center; + justify-content: center; } .title-language-dropdown { diff --git a/main/manager-web/src/views/register.vue b/main/manager-web/src/views/register.vue index b2ac7cb9..de54011e 100644 --- a/main/manager-web/src/views/register.vue +++ b/main/manager-web/src/views/register.vue @@ -45,9 +45,10 @@
-
-
-
-