浏览代码

增加多语言

vera_min 2 月之前
父节点
当前提交
b1817954dd

+ 205 - 7
src/i18n/pages/iotmanagerI18n/en.ts

@@ -33,7 +33,40 @@ export default {
 	},
 	device: {
 		product: "Product",
-		producDetail: {
+		baseType: "Basic Type",
+		extensionType: "Extension Type",
+		enable: "Enable",
+		disable: "Disable",
+		fullScreen: "Full Screen",
+		exitFullScreen: "Exit Full Screen",
+		tip1: "Please enter input parameters as a string. If it's an object string, it will be automatically converted to an object during execution",
+		tip2: "Execution results are displayed here",
+		tip3: "Save Script",
+		tip4: "Debug",
+		tip5: "Below are pre-built empty methods. Please do not modify the function names, just write the function content directly inside",
+		tip6: "This is device function call response data parsing",
+		tip7: "Write data processing code here",
+		tip8: "This is device function call send data parsing",
+		tip9: "Write data processing code here",
+		tip10: "Please enter executable script first",
+		runStatus: "Run Status",
+		deviceInfo: "Device Info",
+		thingModel: "Thing Model",
+		deviceFunction: "Device Function",
+		logManagement: "Log Management",
+		topicList: "Topic List",
+		deviceArchive: "Device Profile",
+		deviceStatus: "Device Status",
+		dataTime: "Data Time",
+		linkProtocol: "Link Protocol",
+		firmwareVersion: "Firmware Version",
+		registryTime: "Registration Time",
+		address: "Address",
+		deviceIdentifier: "Device Identifier",
+		deviceTimeout: "Device Timeout",
+		unitSecond: "s",
+		update: "Update",
+		productDetail: {
 			productInfo: "Product Information",
 			// Switch Status
 			enable: "ON",
@@ -72,6 +105,20 @@ export default {
 			deviceAccess: "Device Access",
 			dataParsing: "Data Parsing"
 		},
+		dialogI18n: {
+			addPro: "Add Product",
+			editPro: "Edit Product",
+			addPropertyDefinition: "Add Property Definition",
+			editPropertyDefinition: "Edit Property Definition",
+			editFunctionDefinition: "Edit Function Definition",
+			addFunctionDefinition: "Add Function Definition",
+			editOption: "Edit Option",
+			addOption: "Add Option",
+			editEventDefinition: "Edit Event Definition",
+			addEventDefinition: "Add Event Definition",
+			editTagDefinition: "Edit Tag Definition",
+			addTagDefinition: "Add Tag Definition"
+		},
 		tableI18nColumn: {
 			categoryName: "Category Name",
 			desc: "Description",
@@ -82,6 +129,10 @@ export default {
 			transportProtocol: "Transport Protocol",
 			deviceType: "Device Type",
 			status: "Status",
+			deviceName: "Device Name",
+			deviceType2: "Device Type",
+			lastOnlineTime: "Last Online Time",
+			desc2: "Description"
 		},
 		tableI18nAlarmType: {
 		},
@@ -96,27 +147,174 @@ export default {
 		tableI18nAction: {
 			addCategory: "Add Category",
 			editCategory: "Edit Category",
-			deviceManagement: "Device Management"
+			deviceManagement: "Device Management",
+			addProductCategory: "Add Product Category",
 		},
 		formI18nLabel: {
 			keyword: "Keyword",
 			type: "Type",
-			status: "Status"
+			status: "Status",
+			productKey: "Product Key",
+			productName: "Product Name",
+			productImage: "Product Image",
+			productCategory: "Product Category",
+			messageProtocol: "Message Protocol",
+			transportProtocol: "Transport Protocol",
+			authType: "Auth Type",
+			authUser: "Auth User",
+			authPasswd: "Auth Passwd",
+			accessToken: "Aceess Token",
+			certificateId: "Certificate Id",
+			deviceType: "Device Type",
+			desc: "Product Description",
+			propertyIdentifier: "Property Identifier",
+			propertyName: "Property Name",
+			dataType: "Data Type",
+			precision: "Precision",
+			unit: "Unit",
+			maxLength: "Max Length",
+			timeFormat: "Time Format",
+			booleanValue: "Boolean Value",
+			enumItems: "Enum Items",
+			jsonObject: "JSON Object",
+			parameterIdentifier: "Parameter Identifier",
+			parameterName: "Parameter Name",
+			elementType: "Element Type",
+			isReadOnly: "Is Read Only",
+			propertyDescription: "Description",
+			functionKey: "Function Key",
+			functionName: "Function Name",
+			functionInput: "Function Input",
+			functionOutput: "Function Output",
+			functionDescription: "Description",
+			parameterDescription: "Description",
+			eventKey: "Event Key",
+			eventName: "Event Name",
+			eventType: "Event Level",
+			eventDescription: "Description",
+			valueRange: "Value Range",
+			objectProperty: "Object Property",
+			tagKey: "Tag Key",
+			tagName: "Tag Name",
+			tagDescription: "Tag Description",
+			authDescription: "Authentication Description",
+			linkInfo: "Connection Information",
+			authConfig: "Authentication Configuration",
+			contactAdmin: "Please contact administrator",
+			productBind: "Associated Product",
+			deptIds: "Affiliated Organization",
+			deviceTag: "Device Tag"
 		},
 		formI18nPlaceholder: {
 			keyword: "Enter name or identifier",
 			type: "Type",
-			status: "Status"
+			status: "Status",
+			productKey: "Enter product identifier",
+			productName: "Enter product name",
+			productCategory: "Select category",
+			messageProtocol: "Select message protocol",
+			transportProtocol: "Select transport protocol",
+			authUser: "Enter username",
+			authPasswd: "Enter password",
+			accessToken: "Enter Aceess Token",
+			certificateId: "Select certificate",
+			desc: "Enter product description",
+			propertyIdentifier: "Enter property identifier",
+			propertyName: "Enter property name",
+			selectDataType: "Select data type",
+			inputPrecision: "Enter precision",
+			inputUnit: "Enter unit",
+			inputMaxLength: "Enter max length",
+			inputTimeFormat: "Enter time format",
+			inputTrueText: "Enter true text",
+			inputBooleanValue: "Enter boolean value",
+			inputFalseText: "Enter false text",
+			inputEnumText: "Enter enum text",
+			inputEnumValue: "Enter enum value",
+			selectElementType: "Select element type",
+			inputDescription: "Enter property description",
+			functionKey: "Enter function key",
+			functionName: "Enter function name",
+			functionDescription: "Enter function description",
+			parameterIdentifier: "Enter parameter identifier",
+			parameterName: "Enter parameter name",
+			parameterDescription: "Enter parameter description",
+			eventKey: "Enter event key",
+			eventName: "Enter event name",
+			eventDescription: "Enter event description",
+			valueRangeMin: "Minimum value",
+			valueRangeMax: "Maximum value",
+			propertyIdentifier1: "Property identifier",
+			propertyName1: "Property name",
+			tagKey: "Tag Key",
+			tagName: "Tag Name",
+			tagDescription: "Tag Description",
+			inputParameter: "Please enter parameters",
+			productBind: "Select product",
+			deptIds: "Select affiliated organization",
+			deviceTag: "Enter tag"
 		},
 		formI18nOption: {
 			device: "Device",
 			gateway: "Gateway",
 			subDevice: "Sub Device",
 			on: "Enabled",
-			off: "Disabled"
+			off: "Disabled",
+			readonly: "Read Only",
+			readWrite: "Read/Write",
+			info: "Information",
+			warning: "Warning",
+			fault: "Fault",
+			online: "Online",
+			offline: "Offline",
 		},
 		formI18nButton: {
-			addProduct: "Add Product"
+			addProduct: "Add Product",
+			addParameter: "Add Parameter",
+			collapse: "Collapse",
+			showMoreFilter: "More Filter",
+			batchEnable: "Batch Enable",
+			batchDisable: "Batch Disable",
+			importDevice: "Import Device",
+			exportDevice: "Export Device"
+		},
+		rules: {
+			productName: "Product name cannot be empty",
+			productNameMax32: "Product name cannot exceed 32 characters",
+			productNameValidator: "Product name cannot contain spaces",
+			productKey: "Product identifier cannot be empty",
+			productKeyValidator: "Product identifier cannot contain spaces",
+			messageProtocol: "Message protocol cannot be empty",
+			transportProtocol: "Access method cannot be empty",
+			categoryId: "Product category cannot be empty",
+			deviceType: "Device type cannot be empty",
+			// 属性定义相关验证规则
+			propertyName: "Property name cannot be empty",
+			propertyNameMax32: "Property name cannot exceed 32 characters",
+			propertyNameValidator: "Property name cannot contain spaces",
+			propertyKey: "Property identifier cannot be empty",
+			accessMode: "Please select access mode",
+			dataType: "Please select data type",
+			functionName: "Function name cannot be empty",
+			functionNameMax32: "Function name cannot exceed 32 characters",
+			functionNameValidator: "Function name cannot contain spaces",
+			functionKey: "Function identifier cannot be empty",
+			functionType: "Please select data type",
+			parameterName: "Parameter name cannot be empty",
+			parameterNameMax32: "Parameter name cannot exceed 32 characters",
+			parameterNameValidator: "Parameter name cannot contain spaces",
+			parameterKey: "Parameter identifier cannot be empty",
+			eventName: "Event name cannot be empty",
+			eventNameMax32: "Event name cannot exceed 32 characters",
+			eventNameValidator: "Event name cannot contain spaces",
+			eventKey: "Event identifier cannot be empty",
+			eventType: "Please select event type",
+			tagKeyName: "Tag name cannot be empty",
+			tagKeyMax32: "Tag name cannot exceed 32 characters",
+			tagKeyValidator: "Tag name cannot contain spaces",
+			tagKey: "Tag identifier cannot be empty",
+			tagAccessMode: "Please select access mode",
+			tagType: "Please select data type"
 		}
 	},
 	alarm: {
@@ -141,4 +339,4 @@ export default {
 			ignored: "Ignored"
 		}
 	}
-};
+};

+ 207 - 7
src/i18n/pages/iotmanagerI18n/zh-cn.ts

@@ -2,7 +2,7 @@
  * @Author: vera_min vera_min@163.com
  * @Date: 2025-08-05 12:42:31
  * @LastEditors: vera_min vera_min@163.com
- * @LastEditTime: 2025-08-08 23:12:36
+ * @LastEditTime: 2025-08-09 16:07:54
  * @FilePath: /sagoo-admin-ui/src/i18n/pages/iotmanagerI18n/zh-cn.ts
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
@@ -33,7 +33,40 @@ export default {
 	},
 	device: {
 		product: "产品",
-		producDetail: {
+		baseType: "基础类型",
+		extensionType: "扩展类型",
+		enable: "启用",
+		disable: "停用",
+		fullScreen: "全屏",
+		exitFullScreen: "退出全屏",
+		tip1: "请输入入参,以字符串的方式,如果是对象字符串会在执行时自动转换为对象再执行",
+		tip2: "此处显示执行结果",
+		tip3: "保存脚本",
+		tip4: "调试",
+		tip5: "下面是预制的空的方法,请不要修改函数名称,直接在内部编写函数即可",
+		tip6: "此处是设备功能调用应答数据解析",
+		tip7: "此处编写对数据的处理",
+		tip8: "此处是设备功能调用发送数据解析",
+		tip9: "此处编写对数据的处理",
+		tip10: "请先输入可执行脚本",
+		runStatus: "运行状态",
+		deviceInfo: "设备信息",
+		thingModel: "物模型",
+		deviceFunction: "设备功能",
+		logManagement: "日志管理",
+		topicList: "Topic列表",
+		deviceArchive: "设备档案",
+		deviceStatus: "设备状态",
+		dataTime: "数据时间",
+		linkProtocol: "链接协议",
+		firmwareVersion: "固件版本",
+		registryTime: "注册时间",
+		address: "详细地址",
+		deviceIdentifier: "设备标识",
+		deviceTimeout: "设备超时时间",
+		unitSecond: "秒",
+		update: "更新",
+		productDetail: {
 			productInfo: "产品信息",
 			// 开关状态
 			enable: "启用",
@@ -72,6 +105,20 @@ export default {
 			deviceAccess: "设备接入",
 			dataParsing: "数据解析"
 		},
+		dialogI18n: {
+			addPro: "新增产品",
+			editPro: "编辑产品",
+			addPropertyDefinition: "新增属性定义",
+			editPropertyDefinition: "修改属性定义",
+			editFunctionDefinition: "修改功能定义",
+			addFunctionDefinition: "新增功能定义",
+			editOption: "编辑参数",
+			addOption: "新增参数",	
+			editEventDefinition: "编辑事件定义",
+			addEventDefinition: "新增事件定义",
+			editTagDefinition: "编辑标签定义",
+			addTagDefinition: "新增标签定义"
+		},
 		tableI18nColumn: {
 			categoryName: "分类名称",
 			desc: "描述",
@@ -82,6 +129,10 @@ export default {
 			transportProtocol: "接入方式",
 			deviceType: "类型",
 			status: "状态",
+			deviceName: "设备名称",
+			deviceType2: "设备类型",
+			lastOnlineTime: "最后上线时间",
+			desc2: "说明"
 		},
 		tableI18nAlarmType: {
 		},
@@ -97,25 +148,174 @@ export default {
 			addCategory: "新增分类",
 			editCategory: "编辑分类",
 			deviceManagement: "设备管理",
+			addProductCategory: "新增产品分类",
 		},
 		formI18nLabel: {
 			keyword: "关键字",
 			type: "类型",
-			status: "状态"
+			status: "状态",
+			productKey: "产品标识",
+			productName: "产品名称",
+			productImage: "产品图片",
+			productCategory: "产品分类",
+			messageProtocol: "消息协议",
+			transportProtocol: "接入方式",
+			authType: "认证方式",
+			authUser: "用户名",
+			authPasswd: "密码",
+			accessToken: "Aceess Token",
+			certificateId: "认证证书",
+			deviceType: "设备类型",
+			desc: "产品描述",
+			propertyIdentifier: "属性定义标识",
+			propertyName: "属性定义名称",
+			dataType: "数据类型",
+			precision: "精度",
+			unit: "单位",
+			maxLength: "最大长度",
+			timeFormat: "时间格式",
+			booleanValue: "布尔值",
+			enumItems: "枚举项",
+			jsonObject: "JSON对象",
+			parameterIdentifier: "参数标识",
+			parameterName: "参数名称",
+			elementType: "元素类型",
+			isReadOnly: "是否只读",
+			propertyDescription: "属性定义描述",
+			functionKey: "功能定义标识",
+			functionName: "功能定义名称",
+			functionInput: "输入参数",
+			functionOutput: "输出参数",
+			functionDescription: "功能定义描述",
+			parameterDescription: "参数描述",
+			eventKey: "事件定义标识",
+			eventName: "事件定义名称",
+			eventType: "事件类型",
+			eventDescription: "事件定义描述",
+			valueRange: "取值范围",
+			objectProperty: "对象属性",
+			tagKey: "标签定义标识",
+			tagName: "标签定义名称",
+			tagDescription: "标签定义描述",
+			authDescription: "认证说明",
+			linkInfo: "链接信息",
+			authConfig: "认证配置",
+			contactAdmin: "请联系管理员",
+			productBind: "所属产品",
+			deptIds: "所属组织",
+			deviceTag: "设备标签"
 		},
 		formI18nPlaceholder: {
 			keyword: "输入名称或标识",
 			type: "类型",
-			status: "启用状态"
+			status: "启用状态",
+			productKey: "请输入产品标识",
+			productName: "请输入产品名称",
+			productCategory: "请选择分类",
+			messageProtocol: "请选择消息协议",
+			transportProtocol: "请选择接入方式",
+			authUser: "请输入用户名",
+			authPasswd: "请输入密码",
+			accessToken: "请输入Aceess Token",
+			certificateId: "请选择认证证书",
+			desc: "请输入产品描述",
+			propertyIdentifier: "请输入属性定义标识",
+			propertyName: "请输入属性定义名称",
+			selectDataType: "请选择数据类型",
+			inputPrecision: "请输入精度",
+			inputUnit: "请输入单位",
+			inputMaxLength: "请输入最大长度",
+			inputTimeFormat: "请输入时间格式",
+			inputTrueText: "请输入true时显示的文字",
+			inputBooleanValue: "请输入布尔值",
+			inputFalseText: "请输入false时显示的文字",
+			inputEnumText: "请输入枚举文本",
+			inputEnumValue: "请输入枚举值",
+			selectElementType: "请选择元素类型",
+			inputDescription: "请输入属性定义描述",
+			functionKey: "请输入功能定义标识",
+			functionName: "请输入功能定义名称",
+			functionDescription: "请输入功能定义描述",
+			parameterIdentifier: "请输入参数标识",
+			parameterName: "请输入参数名称",
+			parameterDescription: "请输入参数描述", 
+			eventKey: "请输入事件定义标识",
+			eventName: "请输入事件定义名称",
+			eventDescription: "请输入事件定义描述",
+			valueRangeMin: "最小值",
+			valueRangeMax: "最大值",
+			propertyIdentifier1: "属性标识",
+			propertyName1: "属性名称",
+			tagKey: "请输入标签定义标识",
+			tagName: "请输入标签定义名称",
+			tagDescription: "请输入标签定义描述",
+			inputParameter: "请输入参数",
+			productBind: "选择产品",
+			deptIds: "请选择所属组织",
+			deviceTag: "请输入标签"
 		},
 		formI18nOption: {
 			device: "设备",
 			gateway: "网关",
 			subDevice: "子设备",
 			on: "已启用",
-			off: "未启用"
+			off: "未启用",
+			readonly: "只读",
+			readWrite: "读写",
+			info: "信息",
+			warning: "告警",
+			fault: "故障",
+			online: "在线",
+			offline: "离线",
+		},
+		formI18nButton: {
+			addProduct: "新增产品",
+			addParameter: "新增参数",
+			collapse: "收起",
+			showMoreFilter: "更多筛选",
+			batchEnable: "批量启用",
+			batchDisable: "批量禁用",
+			importDevice: "导入设备",
+			exportDevice: "导出设备"
+		},
+		rules: {
+			productName: "产品名称不能为空",
+			productNameMax32: "产品名称不能超过32个字符",
+			productNameValidator: "产品名称不能包含空格",
+			productKey: "产品标识不能为空",
+			productKeyValidator: "产品标识不能包含空格",
+			messageProtocol: "消息协议不能为空",
+			transportProtocol: "接入方式不能为空",
+			categoryId: "产品分类不能为空",
+			deviceType: "设备类型不能为空",
+			// 属性定义相关验证规则
+			propertyName: "属性定义名称不能为空",
+			propertyNameMax32: "属性定义名称不能超过32个字符",
+			propertyNameValidator: "属性定义名称不能包含空格",
+			propertyKey: "属性定义标识不能为空",
+			accessMode: "请选择是否只读",
+			dataType: "请选择数据类型",
+			functionName: "功能定义名称不能为空",
+			functionNameMax32: "功能定义名称不能超过32个字符",
+			functionNameValidator: "功能定义名称不能包含空格",
+			functionKey: "功能定义标识不能为空",
+			functionType: "请选择数据类型",
+			parameterName: "参数名称不能为空",
+			parameterNameMax32: "参数名称不能超过32个字符",
+			parameterNameValidator: "参数名称不能包含空格",
+			parameterKey: "参数标识不能为空",
+			eventName: "事件定义名称不能为空",
+			eventNameMax32: "事件定义名称不能超过32个字符",
+			eventNameValidator: "事件定义名称不能包含空格", 
+			eventKey: "事件定义标识不能为空",
+			eventType: "请选择数据类型",
+			tagKeyName: "标签定义名称不能为空",
+			tagKeyMax32: "标签定义名称不能超过32个字符",
+			tagKeyValidator: "标签定义名称不能包含空格",
+			tagKey: "标签定义标识不能为空",
+			tagAccessMode: "请选择是否只读",
+			tagType: "请选择数据类型"
 		}
-			
 	},
 	alarm: {
 		tableI18nColumn: {
@@ -139,4 +339,4 @@ export default {
 			ignored: "已忽略"
 		}
 	}
-};
+};

+ 207 - 9
src/i18n/pages/iotmanagerI18n/zh-tw.ts

@@ -33,7 +33,40 @@ export default {
 	},
 	device: {
 		product: "產品",
-		producDetail: {
+		baseType: "基礎類型",
+		extensionType: "擴展類型",
+		enable: "啟用",
+		disable: "停用",
+		fullScreen: "全屏",
+		exitFullScreen: "退出全屏",
+		tip1: "請輸入入參,以字符串的方式,如果是對象字符串會在執行時自動轉換為對象再執行",
+		tip2: "此處顯示執行結果",
+		tip3: "保存腳本",
+		tip4: "調試",
+		tip5: "下面是預製的空的方法,請不要修改函數名稱,直接在內部編寫函數即可",
+		tip6: "此處是設備功能調用應答數據解析",
+		tip7: "此處編寫對數據的處理",
+		tip8: "此處是設備功能調用發送數據解析",
+		tip9: "此處編寫對數據的處理",
+		tip10: "請先輸入可執行腳本",
+		runStatus: "運行狀態",
+		deviceInfo: "設備信息",
+		thingModel: "物模型",
+		deviceFunction: "設備功能",
+		logManagement: "日誌管理",
+		topicList: "Topic列表",
+		deviceArchive: "設備檔案",
+		deviceStatus: "設備狀態",
+		dataTime: "資料時間",
+		linkProtocol: "鏈接協議",
+		firmwareVersion: "固件版本",
+		registryTime: "註冊時間",
+		address: "詳細地址",
+		deviceIdentifier: "設備標識",
+		deviceTimeout: "設備超時時間",
+		unitSecond: "秒",
+		update: "更新",
+		productDetail: {
 			productInfo: "產品資訊",
 			// 開關狀態
 			enable: "啟用",
@@ -72,6 +105,20 @@ export default {
 			deviceAccess: "設備接入",
 			dataParsing: "資料解析"
 		},
+		dialogI18n: {
+			addPro: "新增產品",
+			editPro: "編輯產品",
+			addPropertyDefinition: "新增屬性定義",
+			editPropertyDefinition: "編輯屬性定義",
+			editFunctionDefinition: "編輯功能定義",
+			addFunctionDefinition: "新增功能定義",
+			editOption: "編輯參數",
+			addOption: "新增參數",
+			editEventDefinition: "編輯事件定義",
+			addEventDefinition: "新增事件定義",
+			editTagDefinition: "編輯標籤定義",
+			addTagDefinition: "新增標籤定義"
+		},
 		tableI18nColumn: {
 			categoryName: "分類名稱",
 			desc: "描述",
@@ -81,7 +128,11 @@ export default {
 			category: "分類",
 			transportProtocol: "接入方式",
 			deviceType: "類型",
-			status: "狀態"
+			status: "狀態",
+			deviceName: "設備名稱",
+			deviceType2: "設備類型",
+			lastOnlineTime: "最後上線時間",
+			desc2: "說明"
 		},
 		tableI18nAlarmType: {
 		},
@@ -94,29 +145,176 @@ export default {
 			deleteProductMessage: "此操作將永久刪除產品:{name},是否繼續?"
 		},
 		tableI18nAction: {
-			addCategory: "添加分類",
+			addCategory: "新增分類",
 			editCategory: "編輯分類",
-			deviceManagement: "設備管理"
+			deviceManagement: "設備管理",
+			addProductCategory: "新增產品分類",
 		},
 		formI18nLabel: {
 			keyword: "關鍵字",
 			type: "類型",
-			status: "狀態"
+			status: "狀態",
+			productKey: "產品標識",
+			productName: "產品名稱",
+			productImage: "產品圖片",
+			productCategory: "產品分類",
+			messageProtocol: "消息協議",
+			transportProtocol: "接入方式",
+			authType: "認證方式",
+			authUser: "用戶名",
+			authPasswd: "密碼",
+			accessToken: "Aceess Token",
+			certificateId: "認證證書",
+			deviceType: "設備類型",
+			desc: "產品描述",
+			propertyIdentifier: "屬性定義標識",
+			propertyName: "屬性定義名稱",
+			dataType: "數據類型",
+			precision: "精度",
+			unit: "單位",
+			maxLength: "最大長度",
+			timeFormat: "時間格式",
+			booleanValue: "布林值",
+			enumItems: "枚舉項",
+			jsonObject: "JSON物件",
+			parameterIdentifier: "參數標識",
+			parameterName: "參數名稱",
+			elementType: "元素類型",
+			isReadOnly: "是否唯讀",
+			propertyDescription: "屬性定義描述",
+			functionKey: "功能定義標識",
+			functionName: "功能定義名稱",
+			functionInput: "輸入參數",
+			functionOutput: "輸出參數",
+			functionDescription: "功能定義描述",
+			parameterDescription: "參數描述",
+			eventKey: "事件定義標識",
+			eventName: "事件定義名稱",
+			eventType: "事件類型",
+			eventDescription: "事件定義描述",
+			valueRange: "取值範圍",
+			objectProperty: "對象屬性",
+			tagKey: "標籤定義標識",
+			tagName: "標籤定義名稱",
+			tagDescription: "標籤定義描述",
+			authDescription: "認證說明",
+			linkInfo: "鏈接信息",
+			authConfig: "認證配置",
+			contactAdmin: "請聯繫管理員",
+			productBind: "所屬產品",
+			deptIds: "所屬組織",
+			deviceTag: "設備標籤"
 		},
 		formI18nPlaceholder: {
 			keyword: "輸入名稱或標識",
 			type: "類型",
-			status: "啟用狀態"
+			status: "啟用狀態",
+			productKey: "請輸入產品標識",
+			productName: "請輸入產品名稱",
+			productCategory: "請選擇分類",
+			messageProtocol: "請選擇消息協議",
+			transportProtocol: "請選擇接入方式",
+			authUser: "請輸入用戶名",
+			authPasswd: "請輸入密碼",
+			accessToken: "請輸入Aceess Token",
+			certificateId: "請選擇認證證書",
+			desc: "請輸入產品描述",
+			propertyIdentifier: "請輸入屬性定義標識",
+			propertyName: "請輸入屬性定義名稱",
+			selectDataType: "請選擇數據類型",
+			inputPrecision: "請輸入精度",
+			inputUnit: "請輸入單位",
+			inputMaxLength: "請輸入最大長度",
+			inputTimeFormat: "請輸入時間格式",
+			inputTrueText: "請輸入true時顯示的文字",
+			inputBooleanValue: "請輸入布林值",
+			inputFalseText: "請輸入false時顯示的文字",
+			inputEnumText: "請輸入枚舉文本",
+			inputEnumValue: "請輸入枚舉值",
+			selectElementType: "請選擇元素類型",
+			inputDescription: "請輸入屬性定義描述",
+			functionKey: "請輸入功能定義標識",
+			functionName: "請輸入功能定義名稱",
+			functionDescription: "請輸入功能定義描述",
+			parameterIdentifier: "請輸入參數標識",
+			parameterName: "請輸入參數名稱",
+			parameterDescription: "請輸入參數描述",
+			eventKey: "請輸入事件定義標識",
+			eventName: "請輸入事件定義名稱",
+			eventDescription: "請輸入事件定義描述",
+			valueRangeMin: "最小值",
+			valueRangeMax: "最大值",
+			propertyIdentifier1: "屬性標識",
+			propertyName1: "屬性名稱",
+			tagKey: "請輸入標籤定義標識",
+			tagName: "請輸入標籤定義名稱",
+			tagDescription: "請輸入標籤定義描述",
+			inputParameter: "請輸入參數",
+			productBind: "選擇產品",
+			deptIds: "請選擇所属組織",
+			deviceTag: "請輸入標籤"
 		},
 		formI18nOption: {
 			device: "設備",
 			gateway: "網關",
 			subDevice: "子設備",
 			on: "已啟用",
-			off: "未啟用"
+			off: "未啟用",
+			readonly: "唯讀",
+			readWrite: "讀寫",
+			info: "資訊",
+			warning: "告警",
+			fault: "故障",
+			online: "在線",
+			offline: "離線",
 		},
 		formI18nButton: {
-			addProduct: "新增產品"
+			addProduct: "新增產品",
+			addParameter: "新增參數",
+			collapse: "收起",
+			showMoreFilter: "更多篩選",
+			batchEnable: "批量啟用",
+			batchDisable: "批量禁用",
+			importDevice: "导入设备",
+			exportDevice: "导出设备"
+		},
+		rules: {
+			productName: "產品名稱不能為空",
+			productNameMax32: "產品名稱不能超過32個字符",
+			productNameValidator: "產品名稱不能包含空格",
+			productKey: "產品標識不能為空",
+			productKeyValidator: "產品標識不能包含空格",
+			messageProtocol: "消息協議不能為空",
+			transportProtocol: "接入方式不能為空",
+			categoryId: "產品分類不能為空",
+			deviceType: "設備類型不能為空",
+			// 屬性定義相關驗證規則
+			propertyName: "屬性定義名稱不能為空",
+			propertyNameMax32: "屬性定義名稱不能超過32個字符",
+			propertyNameValidator: "屬性定義名稱不能包含空格",
+			propertyKey: "屬性定義標識不能為空",
+			accessMode: "請選擇是否唯讀",
+			dataType: "請選擇資料類型",
+			functionName: "功能定義名稱不能為空",
+			functionNameMax32: "功能定義名稱不能超過32個字符",
+			functionNameValidator: "功能定義名稱不能包含空格",
+			functionKey: "功能定義標識不能為空",
+			functionType: "請選擇資料類型",
+			parameterName: "參數名稱不能為空",
+			parameterNameMax32: "參數名稱不能超過32個字符",
+			parameterNameValidator: "參數名稱不能包含空格",
+			parameterKey: "參數標識不能為空",
+			eventName: "事件定義名稱不能為空",
+			eventNameMax32: "事件定義名稱不能超過32個字符",
+			eventNameValidator: "事件定義名稱不能包含空格",
+			eventKey: "事件定義標識不能為空",
+			eventType: "請選擇事件類型",
+			tagKeyName: "標籤定義名稱不能為空",
+			tagKeyMax32: "標籤定義名稱不能超過32個字符",
+			tagKeyValidator: "標籤定義名稱不能包含空格",
+			tagKey: "標籤定義標識不能為空",
+			tagAccessMode: "請選擇是否只讀",
+			tagType: "請選擇資料類型"
 		}
 	},
 	alarm: {
@@ -141,4 +339,4 @@ export default {
 			ignored: "已忽略"
 		}
 	}
-};
+};

+ 12 - 8
src/i18n/pages/tableI18n/en.ts

@@ -2,7 +2,7 @@
  * @Author: vera_min vera_min@163.com
  * @Date: 2025-08-06 01:16:57
  * @LastEditors: vera_min vera_min@163.com
- * @LastEditTime: 2025-08-06 14:37:43
+ * @LastEditTime: 2025-08-09 13:10:35
  * @FilePath: /sagoo-admin-ui/src/i18n/pages/tableI18n/en.ts
  * @Description: 表格国际化 - 英文
  */
@@ -17,18 +17,22 @@ export default {
 		deleteTitle: "Confirm",
 		confirmText: "Delete",
 		cancelText: "Cancel",
-		deleteSuccess: "Delete Success",
-		addSuccess: "Create Success",
-		addFailed: "Create Failed",
-		editSuccess: "Edit Success",
+		deleteSuccess: "Deleted successfully",
+		addSuccess: "Created successfully",
+		addFailed: "Failed to create",
+		editSuccess: "Updated successfully",
 		deleteSelectedMessage: "Are you sure you want to delete the selected data?",
-		selectDataFirst: "Please select the data to delete first."
+		selectDataFirst: "Please select the data to delete first.",
+		saveSuccess: "Saved successfully"
 	},
 	tableI18nAction: {
 		detail: "Detail",
 		handle: "Handle",
 		add: "Add",
 		edit: "Edit",
-		delete: "Delete"
+		delete: "Delete",
+		cancel: "Cancel",
+		query: "Query",
+		more: "More"
 	}
-};
+};

+ 7 - 3
src/i18n/pages/tableI18n/zh-cn.ts

@@ -22,13 +22,17 @@ export default {
 		addFailed: "新增失败",
 		editSuccess: "编辑成功",
 		deleteSelectedMessage: "你确定要删除所选数据?",
-		selectDataFirst: "请选择要删除的数据。"
+		selectDataFirst: "请选择要删除的数据。",
+		saveSuccess: "保存成功"
 	},
 	tableI18nAction: {
 		detail: "详情",
 		handle: "处理",
 		add: "新增",
 		edit: "编辑",
-		delete: "删除"
+		delete: "删除",
+		cancel: "取 消",
+		query: "查询",
+		more: "更多"
 	}
-};
+};

+ 6 - 2
src/i18n/pages/tableI18n/zh-tw.ts

@@ -23,12 +23,16 @@ export default {
 		editSuccess: "編輯成功",
 		deleteSelectedMessage: "你確定要刪除所選數據?",
 		selectDataFirst: "請選擇要刪除的數據。",
+		saveSuccess: "保存成功"
 	},
 	tableI18nAction: {
 		detail: "詳情",
 		handle: "處理",
 		add: "新增",
 		edit: "編輯",
-		delete: "刪除"
+		delete: "刪除",
+		cancel: "取 消",
+		query: "查詢",
+		more: "更多"
 	}
-};
+};

+ 6 - 6
src/views/iot/device/category/component/addOrEdit.vue

@@ -5,7 +5,7 @@
 				<el-row :gutter="35">
 					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
 						<!-- 上级分类 -->
-						<el-form-item :label="$t('message.formI18nLabel.parentCategory')" :label-width="currentLocale === 'en' ? '120px' : '90px'">
+						<el-form-item :label="$t('message.formI18nLabel.parentCategory')" :label-width="currentLocale == 'en' ? '120px' : '90px'">
 							<el-cascader :options="deptData" :props="{ checkStrictly: true, emitPath: false, value: 'id', label: 'name' }" :placeholder="$t('message.formI18nPlaceholder.parentCategory')" clearable class="w100" v-model="ruleForm.parentId">
 								<template #default="{ node, data }">
 									<span>{{ data.name }}</span>
@@ -16,7 +16,7 @@
 					</el-col>
 					<el-col :xs="24" :sm="12" :md="16" :lg="16" :xl="16">
 						<!-- 分类名称 -->
-						<el-form-item :label="$t('message.formI18nLabel.categoryName')" prop="name" :label-width="currentLocale === 'en' ? '120px' : '90px'">
+						<el-form-item :label="$t('message.formI18nLabel.categoryName')" prop="name" :label-width="currentLocale == 'en' ? '120px' : '90px'">
 							<el-input v-model="ruleForm.name" :placeholder="$t('message.formI18nPlaceholder.categoryName')" clearable></el-input>
 						</el-form-item>
 					</el-col>
@@ -28,13 +28,13 @@
 					</el-col>
 					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
 						<!-- 分类标识 -->
-						<el-form-item :label="$t('message.formI18nLabel.categoryKey')" prop="key" :label-width="currentLocale === 'en' ? '120px' : '90px'">
+						<el-form-item :label="$t('message.formI18nLabel.categoryKey')" prop="key" :label-width="currentLocale == 'en' ? '120px' : '90px'">
 							<el-input v-model="ruleForm.key" :placeholder="$t('message.formI18nPlaceholder.categoryKey')" clearable></el-input>
 						</el-form-item>
 					</el-col>
 					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
 						<!-- 描述 -->
-						<el-form-item :label="$t('message.formI18nLabel.desc')" prop="desc" :label-width="currentLocale === 'en' ? '120px' : '90px'">
+						<el-form-item :label="$t('message.formI18nLabel.desc')" prop="desc" :label-width="currentLocale == 'en' ? '120px' : '90px'">
 							<el-input v-model="ruleForm.desc" type="textarea" :placeholder="$t('message.formI18nPlaceholder.desc')" maxlength="150"></el-input>
 						</el-form-item>
 					</el-col>
@@ -42,8 +42,8 @@
 			</el-form>
 			<template #footer>
 				<span class="dialog-footer">
-					<el-button @click="onCancel">{{ $t('message.formI18nButton.cancel') }}</el-button>
-					<el-button type="primary" @click="onSubmit" :loading="loading">{{ ruleForm.id ? $t('message.formI18nButton.edit') : $t('message.formI18nButton.add') }}</el-button>
+					<el-button @click="onCancel">{{ $t('message.tableI18nAction.cancel‌') }}</el-button>
+					<el-button type="primary" @click="onSubmit" :loading="loading">{{ ruleForm.id ? $t('message.tableI18nAction.edit') : $t('message.tableI18nAction.add') }}</el-button>
 				</span>
 			</template>
 		</el-dialog>

+ 65 - 36
src/views/iot/device/instance/detail.vue

@@ -2,34 +2,41 @@
   <div class="page bg page-full">
     <div class="content">
       <div class="cont_box" style="align-items: center">
-        <div class="title">设备:{{ detail.name }}</div>
-        <el-tag v-if="areaData.status === 0" type="info" style="margin-left: 20px">未启用</el-tag>
-        <el-tag v-else-if="areaData.status === 1" type="danger" style="margin-left: 20px">离线</el-tag>
-        <el-tag v-else-if="areaData.status === 2" type="success" style="margin-left: 20px">在线</el-tag>
+        <!-- 设备 -->
+        <div class="title">{{$t('message.device.formI18nOption.device')}}:{{ detail.name }}</div>
+        <!-- 未启用 -->
+        <el-tag v-if="areaData.status === 0" type="info" style="margin-left: 20px">{{ $t('message.device.formI18nOption.off') }}</el-tag>
+        <!-- 离线 -->
+        <el-tag v-else-if="areaData.status === 1" type="danger" style="margin-left: 20px">{{ $t('message.device.formI18nOption.offline') }}</el-tag>
+        <!-- 在线 -->
+        <el-tag v-else-if="areaData.status === 2" type="success" style="margin-left: 20px">{{ $t('message.device.formI18nOption.online') }}</el-tag>
       </div>
     </div>
 
     <div class="content-box page-full-part page-full">
       <el-tabs v-model="activeName" @tab-click="handleClick">
-        <el-tab-pane label="运行状态" name="3">
+        <!-- 运行状态 -->
+        <el-tab-pane :label="$t('message.device.runStatus')" name="3">
           <div style="display: flex; flex-wrap: wrap">
             <div class="ant-card">
               <div class="ant-card-body">
                 <div class="cardflex">
-                  <div>设备状态</div>
+                  <div>{{ $t('message.device.deviceStatus') }}</div>
                   <div @click="getrunData()" style="cursor: pointer">
                     <el-icon style="font-size: 18px">
                       <ele-Refresh />
                     </el-icon>
                   </div>
                 </div>
-
-                <div class="statusname" v-if="areaData.status == 0">未启用</div>
-                <div class="statusname" v-if="areaData.status == 1">离线</div>
-                <div class="statusname" v-if="areaData.status == 2">在线</div>
+                <!-- 未启用 -->
+                <div class="statusname" v-if="areaData.status == 0">{{ $t('message.device.formI18nOption.off') }}</div>
+                <!-- 离线 -->
+                <div class="statusname" v-if="areaData.status == 1">{{ $t('message.device.formI18nOption.offline') }}</div>
+                <!-- 在线 -->
+                <div class="statusname" v-if="areaData.status == 2">{{ $t('message.device.formI18nOption.online') }}</div>
                 <div class="cardflex comtest">
-                  <div>数据时间</div>
-                  <div>{{ areaData.lastOnlineTime || "未启用" }}</div>
+                  <div>{{$t('message.device.dataTime')}}</div>
+                  <div>{{ areaData.lastOnlineTime || $t('message.device.formI18nOption.off') }}</div>
                 </div>
               </div>
             </div>
@@ -69,33 +76,46 @@
             </div>
           </div>
         </el-tab-pane>
-        <el-tab-pane label="设备信息" name="1">
+        <!-- 设备信息 -->
+        <el-tab-pane :label="$t('message.device.deviceInfo')" name="1">
           <div class="pro-box">
-            <div class="protitle">设备信息</div>
+            <div class="protitle">{{$t('message.device.deviceInfo')}}</div>
             <div>
-              <el-button size="small" type="primary" v-auth="'edit'" @click="onOpenEditDic(detail)">编辑</el-button>
+              <el-button size="small" type="primary" v-auth="'edit'" @click="onOpenEditDic(detail)">{{ $t('message.tableI18nAction.edit') }}</el-button>
             </div>
           </div>
 
           <el-descriptions class="margin-top" :column="3" border>
-            <el-descriptions-item label="设备标识">
+            <!-- 设备标识 -->
+            <el-descriptions-item :label="$t('message.device.deviceIdentifier')">
               <copy :text="detail.key"></copy>
             </el-descriptions-item>
-            <el-descriptions-item label="设备名称">{{ detail.name }}</el-descriptions-item>
-            <el-descriptions-item label="消息协议">{{ prodetail.messageProtocol }}</el-descriptions-item>
-            <el-descriptions-item label="产品标识">
+            <!-- 设备名称 -->
+            <el-descriptions-item :label="$t('message.device.tableI18nColumn.deviceName')">{{ detail.name }}</el-descriptions-item>
+            <!-- 消息协议 -->
+            <el-descriptions-item :label="$t('message.device.formI18nLabel.messageProtocol')">{{ prodetail.messageProtocol }}</el-descriptions-item>
+            <!-- 产品标识 -->
+            <el-descriptions-item :label="$t('message.device.formI18nLabel.productKey')">
               <copy :text="prodetail.key"></copy>
             </el-descriptions-item>
-            <el-descriptions-item label="产品名称">
+            <!-- 产品名称 -->
+            <el-descriptions-item :label="$t('message.device.formI18nLabel.productName')">
               <router-link :to="'/iotmanager/device/product/detail/' + prodetail.key" class="link-type">{{ detail.productName }} </router-link>
             </el-descriptions-item>
-            <el-descriptions-item label="链接协议">{{ prodetail.transportProtocol }}</el-descriptions-item>
-            <el-descriptions-item label="设备类型">{{ prodetail.deviceType }}</el-descriptions-item>
-            <el-descriptions-item label="固件版本">{{ detail.version }}</el-descriptions-item>
-            <el-descriptions-item label="注册时间">{{ detail.registryTime }}</el-descriptions-item>
-            <el-descriptions-item label="最后上线时间">{{ detail.lastOnlineTime || "" }}</el-descriptions-item>
-            <el-descriptions-item label="详细地址">{{ detail.address }}</el-descriptions-item>
-            <el-descriptions-item label="说明">{{ detail.desc }}</el-descriptions-item>
+            <!-- 链接协议 -->
+            <el-descriptions-item :label="$t('message.device.linkProtocol')">{{ prodetail.transportProtocol }}</el-descriptions-item>
+            <!-- 设备类型 -->
+            <el-descriptions-item :label="$t('message.device.tableI18nColumn.deviceType2')">{{ prodetail.deviceType }}</el-descriptions-item>
+            <!-- 固件版本 -->
+            <el-descriptions-item :label="$t('message.device.firmwareVersion')">{{ detail.version }}</el-descriptions-item>
+            <!-- 注册时间 -->
+            <el-descriptions-item :label="$t('message.device.registryTime')">{{ detail.registryTime }}</el-descriptions-item>
+            <!-- 最后上线时间 -->
+            <el-descriptions-item :label="$t('message.device.tableI18nColumn.lastOnlineTime')">{{ detail.lastOnlineTime || "" }}</el-descriptions-item>
+            <!-- 详细地址 -->
+            <el-descriptions-item :label="$t('message.device.address')">{{ detail.address }}</el-descriptions-item>
+            <!-- 说明 -->
+            <el-descriptions-item :label="$t('message.device.tableI18nColumn.desc2')">{{ detail.desc }}</el-descriptions-item>
             <el-descriptions-item :label="item.name" v-for="(item, index) in detail.tags" :key="index">{{ item.value }}</el-descriptions-item>
             <!-- <el-descriptions-item label="标签">
             <div class="capsule-wrapper">
@@ -108,15 +128,20 @@
           </el-descriptions>
           <div class="flex" style="margin-top: 20px">
             <el-input type="number" style="width: 380px; margin-right: 20px" v-model.number="detail.onlineTimeout">
-              <template #prepend>设备超时时间</template>
-              <template #append>秒</template>
+              <!-- 设备超时时间 -->
+              <template #prepend>{{$t('message.device.deviceTimeout')}}</template>
+              <!-- 秒 -->
+              <template #append>{{ $t('message.device.unitSecond') }}</template>
             </el-input>
+            <!-- 更新 -->
             <el-button type="primary" @click="onlineTimeoutUpdate">
-              <el-icon style="font-size: 18px"><ele-Refresh /></el-icon>更新</el-button
-            >
+              <el-icon style="font-size: 18px"><ele-Refresh /></el-icon>
+              {{ $t('message.device.update') }}
+            </el-button>
           </div>
         </el-tab-pane>
-        <el-tab-pane label="物模型" name="2">
+        <!-- 物模型 -->
+        <el-tab-pane :label="$t('message.device.thingModel')" name="2">
           <el-tabs type="border-card" v-model="activetab" @tab-click="wuhandleClick">
             <el-tab-pane label="属性定义" name="attr">
               <div class="wu-title">
@@ -243,10 +268,12 @@
           </el-tabs>
           <pagination v-show="tableData.total > 0" :total="tableData.total" v-model:page="tableData.param.pageNum" v-model:limit="tableData.param.pageSize" @pagination="getList()" />
         </el-tab-pane>
-        <el-tab-pane label="设备功能" name="5">
+        <!-- 设备功能 -->
+        <el-tab-pane :label="$t('message.device.deviceFunction')" name="5">
           <functionCom :device-key="detail.key" :product-key="prodetail.key" v-if="detail.key && prodetail.key && activeName === '5'"></functionCom>
         </el-tab-pane>
-        <el-tab-pane label="日志管理" name="4">
+        <!-- 日志管理 -->
+        <el-tab-pane :label="$t('message.device.logManagement')" name="4">
           <div class="system-user-search mb15">
             <el-form :model="logtableData.param" ref="logqueryRef" inline label-width="68px">
               <el-form-item label="日志类型" prop="types">
@@ -287,7 +314,8 @@
 
           <pagination v-show="logtableData.total > 0" :total="logtableData.total" v-model:page="logtableData.param.pageNum" v-model:limit="logtableData.param.pageSize" @pagination="getlog" />
         </el-tab-pane>
-        <el-tab-pane label="Topic列表" name="topic">
+        <!-- Topic列表 -->
+        <el-tab-pane :label="$t('message.device.topicList')" name="topic">
           SagooMqtt协议 ,涉及的topic如下:
           <el-table style="width: 100%; margin-top: 20px" :data="topicData" border>
             <el-table-column label="描述" prop="info" width="250" />
@@ -339,7 +367,8 @@
             <pagination v-show="deviceTableData.total > 0" :total="deviceTableData.total" v-model:page="deviceTableData.param.pageNum" v-model:limit="deviceTableData.param.pageSize" @pagination="getDeviceTableData" />
           </div>
         </el-tab-pane>
-        <el-tab-pane label="设备档案" name="7" v-if="deviceAssetData">
+        <!-- 设备档案 -->
+        <el-tab-pane :label="$t('message.device.deviceArchive')" name="7" v-if="deviceAssetData">
           <el-form label-width="110px">
             <div class="pro-box">
               <div class="protitle">设备档案</div>

+ 97 - 44
src/views/iot/device/instance/index.vue

@@ -4,36 +4,51 @@
       <div class="system-user-search mb15">
         <el-form :model="tableData.param" ref="queryRef" inline class="search-form">
           <div class="search-conditions">
-            <el-form-item label="关键字" prop="keyWord">
-              <el-input v-model="tableData.param.keyWord" placeholder="输入名称或标识" clearable style="width: 200px" @keyup.enter.native="typeList" />
+            <!-- 关键字 -->
+            <el-form-item :label="$t('message.device.formI18nLabel.keyword')" prop="keyWord">
+              <!-- 输入名称或标识 -->
+              <el-input v-model="tableData.param.keyWord" :placeholder="$t('message.device.formI18nPlaceholder.keyword')" clearable style="width: 200px" @keyup.enter.native="typeList" />
             </el-form-item>
             <!--          <el-form-item label="标识" prop="key">-->
             <!--            <el-input v-model="tableData.param.key" placeholder="请输入设备标识" clearable style="width: 150px" @keyup.enter.native="typeList" />-->
             <!--          </el-form-item>-->
-            <el-form-item label="状态" prop="status">
-              <el-select v-model="tableData.param.status" placeholder="状态" clearable style="width: 80px">
-                <el-option label="在线" :value="2" />
-                <el-option label="离线" :value="1" />
-                <el-option label="未启用" :value="0" />
+            <!-- 状态 -->
+            <el-form-item :label="$t('message.device.formI18nLabel.status')" prop="status">
+              <!-- 状态 -->
+              <el-select v-model="tableData.param.status" :placeholder="$t('message.device.formI18nLabel.status')" clearable style="width: 88px">
+                <!-- 在线 -->
+                <el-option :label="$t('message.device.formI18nOption.online')" :value="2" />
+                <!-- 离线 -->
+                <el-option :label="$t('message.device.formI18nOption.offline')" :value="1" />
+                <!-- 未启用 -->
+                <el-option :label="$t('message.device.formI18nOption.off')" :value="0" />
               </el-select>
             </el-form-item>
 
             <template v-if="showMoreFilter">
-              <el-form-item label="所属产品" prop="productKey">
-                <el-select v-model="tableData.param.productKey" style="width: 120px" filterable clearable placeholder="选择产品">
+              <!-- 所属产品 -->
+              <el-form-item :label="$t('message.device.formI18nLabel.productBind')" prop="productKey">
+                <!-- 选择产品 -->
+                <el-select v-model="tableData.param.productKey" style="width: 120px" filterable clearable :placeholder="$t('message.device.formI18nLabel.productBind')">
                   <el-option v-for="item in productData" :key="item.key" :label="item.name" :value="item.key" value-key="id"> </el-option>
                 </el-select>
               </el-form-item>
 
-              <el-form-item label="设备类型" prop="deviceTypes">
-                <el-select v-model="tableData.param.deviceTypes" multiple style="width: 260px" clearable placeholder="设备类型">
-                  <el-option label="设备" value="设备" />
-                  <el-option label="网关" value="网关" />
-                  <el-option label="子设备" value="子设备" />
+              <!-- 设备类型 -->
+              <el-form-item :label="$t('message.device.formI18nLabel.deviceType')" prop="deviceTypes">
+                <el-select v-model="tableData.param.deviceTypes" multiple style="width: 260px" clearable :placeholder="$t('message.device.formI18nLabel.deviceType')">
+                  <!-- 设备 -->
+                  <el-option :label="$t('message.device.formI18nOption.device')" value="设备" />
+                  <!-- 网关 -->
+                  <el-option :label="$t('message.device.formI18nOption.gateway')" value="网关" />
+                  <!-- 子设备 -->
+                  <el-option :label="$t('message.device.formI18nOption.subDevice')" value="子设备" />
                 </el-select>
               </el-form-item>
 
-              <el-form-item label="所属组织" prop="deptIds">
+              <!-- 所属组织 -->
+              <el-form-item :label="$t('message.device.formI18nLabel.deptIds')" prop="deptIds">
+                <!-- 请选择所属组织 -->
                 <el-cascader
                   v-model="tableData.param.deptIds"
                   :options="deptOptions"
@@ -47,21 +62,23 @@
                   }"
                   style="width: 200px"
                   clearable
-                  placeholder="请选择所属组织"
+                  :placeholder="$t('message.device.formI18nPlaceholder.deptIds')"
                   collapse-tags
                   collapse-tags-tooltip
                   filterable
                 />
               </el-form-item>
 
-              <el-form-item label="设备标签" prop="tags">
+              <!-- 设备标签 -->
+              <el-form-item :label="$t('message.device.formI18nLabel.deviceTag')" prop="tags">
+                <!-- 请输入标签 -->
                 <el-select
                   v-model="tableData.param.tags"
                   multiple
                   filterable
                   allow-create
                   default-first-option
-                  placeholder="请输入标签"
+                  :placeholder="$t('message.device.formI18nPlaceholder.deviceTag')"
                   style="width: 260px"
                   clearable
                 >
@@ -77,7 +94,8 @@
           <div class="search-actions">
             <el-form-item>
               <el-button link type="primary" @click="showMoreFilter = !showMoreFilter">
-                {{ showMoreFilter ? '收起' : '更多筛选' }}
+                <!-- 收起/更多筛选 -->
+                {{ showMoreFilter ? $t('message.device.formI18nButton.collapse') : $t('message.device.formI18nButton.showMoreFilter') }}
                 <el-icon class="el-icon--right">
                   <component :is="showMoreFilter ? 'ArrowUp' : 'ArrowDown'" />
                 </el-icon>
@@ -85,11 +103,12 @@
             </el-form-item>
 
             <el-form-item>
+              <!-- 查询 -->
               <el-button type="primary" class="ml10" @click="typeList">
                 <el-icon>
                   <ele-Search />
                 </el-icon>
-                查询
+                {{ $t('message.tableI18nAction.query') }}
               </el-button>
               <!-- <el-button @click="resetQuery(queryRef)">
                 <el-icon>
@@ -97,56 +116,63 @@
                 </el-icon>
                 重置
               </el-button> -->
+              <!-- 新增 -->
               <el-button type="primary" class="ml10" @click="onOpenAddDic" v-auth="'add'">
                 <el-icon>
                   <ele-FolderAdd />
                 </el-icon>
-                新增
+                {{ $t('message.tableI18nAction.add') }}
               </el-button>
+              <!-- 删除 -->
               <el-button type="info" class="ml10" @click="onRowDel()" v-auth="'del'">
                 <el-icon>
                   <ele-Delete />
                 </el-icon>
-                删除
+                {{ $t('message.tableI18nAction.delete') }}
               </el-button>
 
               <el-dropdown>
+                <!-- 更多 -->
                 <el-button type="danger" class="ml10">
-                  更多
+                  {{ $t('message.tableI18nAction.more') }}
                   <el-icon class="el-icon--right"><arrow-down /></el-icon>
                 </el-button>
                 <template #dropdown>
                   <el-dropdown-menu>
                     <el-dropdown-item>
+                      <!-- 批量启用 -->
                       <el-button type="success" @click="setDeviceStatus1()">
                         <el-icon>
                           <ele-Open />
                         </el-icon>
-                        批量启用
+                        {{ $t('message.device.formI18nButton.batchEnable') }}
                       </el-button>
                     </el-dropdown-item>
                     <el-dropdown-item>
+                      <!-- 批量禁用 -->
                       <el-button type="warning" @click="setDeviceStatus0()">
                         <el-icon>
                           <ele-TurnOff />
                         </el-icon>
-                        批量禁用
+                        {{ $t('message.device.formI18nButton.batchDisable') }}
                       </el-button>
                     </el-dropdown-item>
                     <el-dropdown-item>
+                      <!-- 导入设备 -->
                       <el-button @click="onOpenexcelDic('upload')">
                         <el-icon>
                           <ele-Upload />
                         </el-icon>
-                        导入设备
+                        {{ $t('message.device.formI18nButton.importDevice') }}
                       </el-button>
                     </el-dropdown-item>
                     <el-dropdown-item>
+                      <!-- 导出设备 -->
                       <el-button @click="onOpenexcelDic('down')">
                         <el-icon>
                           <ele-Download />
                         </el-icon>
-                        导出设备
+                        {{ $t('message.device.formI18nButton.exportDevice') }}
                       </el-button>
                     </el-dropdown-item>
                   </el-dropdown-menu>
@@ -158,33 +184,48 @@
       </div>
       <el-table :data="tableData.data" style="width: 100%" @selection-change="handleSelectionChange" v-loading="tableData.loading">
         <el-table-column type="selection" width="55" align="center" />
-        <el-table-column label="标识" prop="key" min-width="150" show-overflow-tooltip v-col="'key'">
+        <!-- 标识 -->
+        <el-table-column :label="$t('message.device.tableI18nColumn.key')" prop="key" min-width="150" show-overflow-tooltip v-col="'key'">
           <template #default="{ row }">
             <copy :text="row.key"></copy>
           </template>
         </el-table-column>
-        <el-table-column label="设备名称" prop="name" min-width="160" show-overflow-tooltip v-col="'name'" />
-        <el-table-column label="设备类型" prop="product.deviceType" min-width="100" align="center" show-overflow-tooltip v-col="'deviceType'" />
-        <el-table-column label="所属产品" prop="productName" min-width="120" align="center" show-overflow-tooltip v-col="'productName'" />
-        <el-table-column prop="status" label="状态" min-width="80" align="center" v-col="'status'">
+        <!-- 设备名称 -->
+        <el-table-column :label="$t('message.device.tableI18nColumn.deviceName')" prop="name" min-width="160" show-overflow-tooltip v-col="'name'" />
+        <!-- 设备类型 -->
+        <el-table-column :label="$t('message.device.tableI18nColumn.deviceType2')" prop="product.deviceType" min-width="120" align="center" show-overflow-tooltip v-col="'deviceType'" />
+        <!-- 所属产品 -->
+        <el-table-column :label="$t('message.device.formI18nLabel.productBind')" prop="productName" min-width="160" align="center" show-overflow-tooltip v-col="'productName'" />
+        <!-- 状态 -->
+        <el-table-column prop="status" :label="$t('message.device.tableI18nColumn.status')" min-width="90" align="center" v-col="'status'">
           <template #default="scope">
-            <el-tag type="danger" size="small" v-if="scope.row.status == 1">离线</el-tag>
-            <el-tag type="success" size="small" v-if="scope.row.status == 2">在线</el-tag>
-            <el-tag type="info" size="small" v-if="scope.row.status == 0">未启用</el-tag>
+            <!-- 离线 -->
+            <el-tag type="danger" size="small" v-if="scope.row.status == 1">{{ $t('message.device.formI18nOption.offline') }}</el-tag>
+            <!-- 在线 -->
+            <el-tag type="success" size="small" v-if="scope.row.status == 2">{{ $t('message.device.formI18nOption.online') }}</el-tag>
+            <!-- 未启用 -->
+            <el-tag type="info" size="small" v-if="scope.row.status == 0">{{ $t('message.device.formI18nOption.off') }}</el-tag>
           </template>
         </el-table-column>
-        <el-table-column prop="lastOnlineTime" label="最后上线时间" align="center" width="160" v-col="'lastOnlineTime'"></el-table-column>
-        <el-table-column prop="desc" label="说明" show-overflow-tooltip v-col="'desc'"></el-table-column>
-
-        <el-table-column label="操作" width="180" align="center" fixed="right">
+        <!-- 最后上线时间  -->
+        <el-table-column prop="lastOnlineTime" :label="$t('message.device.tableI18nColumn.lastOnlineTime')" align="center" width="160" v-col="'lastOnlineTime'"></el-table-column>
+        <!-- 说明 -->
+        <el-table-column prop="desc" :label="$t('message.device.tableI18nColumn.desc2')" min-width="110" show-overflow-tooltip v-col="'desc'"></el-table-column>
+        <!-- 操作 -->
+        <el-table-column :label="$t('message.tableI18nColumn.operation')" width="200" align="center" fixed="right">
           <template #default="scope">
+            <!-- 详情 -->
             <router-link :to="'/iotmanager/device/instance/' + scope.row.key" class="link-type" style="padding-right: 12px;font-size: 12px;color: #409eff;" v-auth="'detail'">
-              <span>详情</span>
+              <span>{{ $t('message.tableI18nAction.detail') }}</span>
             </router-link>
-            <el-button size="small" text type="warning" @click="onOpenEditDic(scope.row)" v-auth="'edit'">修改</el-button>
-            <el-button size="small" text type="success" @click="onActionStatus(scope.row)" v-if="scope.row.status == 0" v-auth="'status'">启用</el-button>
-            <el-button size="small" text type="primary" @click="onActionStatus(scope.row)" v-if="scope.row.status > 0" v-auth="'status'">停用</el-button>
-            <el-button size="small" text type="info" @click="onRowDel(scope.row)" v-auth="'del'">删除</el-button>
+            <!-- 修改 -->
+            <el-button size="small" text type="warning" @click="onOpenEditDic(scope.row)" v-auth="'edit'">{{ $t('message.tableI18nAction.edit') }}</el-button>
+            <!-- 启用 -->
+            <el-button size="small" text type="success" @click="onActionStatus(scope.row)" v-if="scope.row.status == 0" v-auth="'status'">{{ $t('message.device.enable') }}</el-button>
+            <!-- 停用 -->
+            <el-button size="small" text type="primary" @click="onActionStatus(scope.row)" v-if="scope.row.status > 0" v-auth="'status'">{{ $t('message.device.disable') }}</el-button>
+            <!-- 删除 -->
+            <el-button size="small" text type="info" @click="onRowDel(scope.row)" v-auth="'del'">{{ $t('message.tableI18nAction.delete') }}</el-button>
           </template>
         </el-table-column>
       </el-table>
@@ -315,9 +356,11 @@ export default defineComponent({
         keys = state.keys;
       }
       if (keys.length === 0) {
+        // 请选择要操作的数据。
         ElMessage.error('请选择要操作的数据。');
         return;
       }
+      // 确认要批量启用这些设备吗?
       ElMessageBox.confirm("确认要批量启用这些设备吗?", '提示', {
         confirmButtonText: '确认',
         cancelButtonText: '取消',
@@ -326,6 +369,7 @@ export default defineComponent({
         .then(() => {
           batchLoading.value = true
           api.device.setDeviceStatus({ ids: keys, status: 1 }).then(() => {
+            // 启用成功
             ElMessage.success('启用成功');
             typeList();
           }).finally(() => batchLoading.value = false)
@@ -342,9 +386,11 @@ export default defineComponent({
         keys = state.keys;
       }
       if (keys.length === 0) {
+        // 请选择要操作的数据。
         ElMessage.error('请选择要操作的数据。');
         return;
       }
+      // 确认要批量禁用这些设备吗?
       ElMessageBox.confirm("确认要批量禁用这些设备吗?", '提示', {
         confirmButtonText: '确认',
         cancelButtonText: '取消',
@@ -353,6 +399,7 @@ export default defineComponent({
         .then(() => {
           batchLoading.value = true
           api.device.setDeviceStatus({ ids: keys, status: 0 }).then(() => {
+            // 禁用成功
             ElMessage.success('禁用成功');
             typeList();
           }).finally(() => batchLoading.value = false)
@@ -361,15 +408,18 @@ export default defineComponent({
     }
     // 删除产品
     const onRowDel = (row?: TableDataRow) => {
+      // 你确定要删除所选数据?
       let msg = '你确定要删除所选数据?';
       let keys: string[] = [];
       if (row) {
+        // 此操作将永久删除设备:"${row.name}",是否继续?
         msg = `此操作将永久删除设备:"${row.name}",是否继续?`;
         keys = [row.key];
       } else {
         keys = state.keys;
       }
       if (keys.length === 0) {
+        // 请选择要删除的数据。
         ElMessage.error('请选择要删除的数据。');
         return;
       }
@@ -380,6 +430,7 @@ export default defineComponent({
       })
         .then(() => {
           api.instance.del(keys).then(() => {
+            // 删除成功
             ElMessage.success('删除成功');
             typeList();
           });
@@ -408,11 +459,13 @@ export default defineComponent({
       if (item.status == 0) {
         api.instance.devdeploy(item.key).then((res: any) => {
           typeList();
+          // 操作成功
           ElMessage.success(res.message || '操作成功');
         });
       } else {
         api.instance.devundeploy(item.key).then((res: any) => {
           typeList();
+          // 操作成功
           ElMessage.success(res.message || '操作成功');
         });
       }

+ 40 - 24
src/views/iot/device/product/component/dataParse.vue

@@ -1,8 +1,10 @@
 <template>
 	<div class="data-parse-wrapper" style="position: relative" ref="wrapperRef">
 		<div class="full-screen-btn">
-			<el-icon v-if="!isFullScreen" @click="toggleFullScreen" title="全屏"><FullScreen /></el-icon>
-			<el-icon v-else @click="toggleFullScreen" title="退出全屏"><Close /></el-icon>
+			<!-- fullScreen -->
+			<el-icon v-if="!isFullScreen" @click="toggleFullScreen" :title="$t('message.device.fullScreen')"><FullScreen /></el-icon>
+			<!-- exitFullScreen -->
+			<el-icon v-else @click="toggleFullScreen" :title="$t('message.device.exitFullScreen')"><Close /></el-icon>
 		</div>
 		<div class="flex" style="align-items: stretch">
 			<codeEditor class="params flex1" ref="mirrorRef" style="height: calc(100vh - 310px)" mode="javascript" :content="script || emptyFunction"></codeEditor>
@@ -11,48 +13,61 @@
 					<el-radio-button label="parse">parse</el-radio-button>
 					<el-radio-button label="send">send</el-radio-button>
 				</el-radio-group>
+				<!-- 请输入入参,以字符串的方式,如果是对象字符串会在执行时自动转换为对象再执行 -->
 				<el-input
 					class="input"
 					v-model="inputData"
 					type="textarea"
-					placeholder="请输入入参,以字符串的方式,如果是对象字符串会在执行时自动转换为对象再执行"
+					:placeholder="$t('message.device.tip1')"
 				></el-input>
-				<el-input class="input" v-model="outputData" type="textarea" readonly placeholder="此处显示执行结果"></el-input>
+				<!-- 此处显示执行结果 -->
+				<el-input class="input" v-model="outputData" type="textarea" readonly :placeholder="$t('message.device.tip2')"></el-input>
 			</div>
 		</div>
-		<el-button type="primary" style="margin-top: 20px" v-auth="'save'" @click="saveCode">保存脚本</el-button>
-		<el-button type="primary" style="margin-top: 20px" v-auth="'debug'" :loading="runing" @click="mock">调试</el-button>
+		<!-- 保存脚本 -->
+		<el-button type="primary" style="margin-top: 20px" v-auth="'save'" @click="saveCode">{{ $t('message.device.tip3') }}</el-button>
+		<!-- 调试 -->
+		<el-button type="primary" style="margin-top: 20px" v-auth="'debug'" :loading="runing" @click="mock">{{ $t('message.device.tip4') }}</el-button>
 	</div>
 </template>
 
 <script lang="ts" setup>
-import { onMounted, ref, onUnmounted } from 'vue'
+import { onMounted, ref, onUnmounted, computed } from 'vue'
 import codeEditor from '/@/components/codeEditor/index.vue'
 import { ElMessage } from 'element-plus'
 import api from '/@/api/device'
 import { useRoute } from 'vue-router'
 import { FullScreen, Close } from '@element-plus/icons-vue'
+import { useI18n } from 'vue-i18n'
+const { t } = useI18n()
+// tip5: "下面是预制的空的方法,请不要修改函数名称,直接在内部编写函数即可",
+// tip6: "此处是设备功能调用应答数据解析",
+// tip7: "此处编写对数据的处理",
+// tip8: "此处是设备功能调用发送数据解析",
+// tip9: "此处编写对数据的处理",
+// tip10: "请先输入可执行脚本",
+const emptyFunction = computed(() => 
+`
+	// ${t('message.device.tip5')}
 
-const emptyFunction = `
-// 下面是预制的空的方法,请不要修改函数名称,直接在内部编写函数即可
-
-// 此处是设备功能调用应答数据解析
-function parse (data) {
+	// ${t('message.device.tip6')}
+	function parse (data) {
 
-	// 此处编写对数据的处理
+		// ${t('message.device.tip7')}
 
-	return data
-}
+		return data
+	}
 
 
-// 此处是设备功能调用发送数据解析
-function send (data) {
+	// ${t('message.device.tip8')}
+	function send (data) {
 
-	// 此处编写对数据的处理
+		// ${t('message.device.tip9')}
 
-	return data
-}
+		return data
+	}
 `
+);
 
 const route = useRoute()
 
@@ -149,7 +164,7 @@ function toSave(data: string) {
 			scriptInfo: data,
 		})
 		.then(() => {
-			ElMessage.success('保存成功')
+			ElMessage.success(t('message.tableI18nConfirm.saveSuccess'))
 			emit('updateScript', data)
 		})
 }
@@ -176,13 +191,14 @@ async function mock() {
 	outputData.value = ''
 
 	await validate()
-
-	if (!inputData.value) return ElMessage.error('请输入参数')
+  // 请输入参数
+	if (!inputData.value) return ElMessage.error(t('message.device.formI18nPlaceholder.inputParameter'))
 
 	const funStr = mirrorRef.value.getValue()
 
 	if (funStr === '') {
-		return ElMessage.error('请先输入可执行脚本')
+		// 请先输入可执行脚本
+		return ElMessage.error(t('message.device.tip10'))
 	}
 
 	// 远程调试

+ 21 - 10
src/views/iot/device/product/component/deviceIn.vue

@@ -1,35 +1,46 @@
 <template>
-	<div class="title">接入方式</div>
+	<!-- 接入方式 -->
+	<div class="title">{{ $t('message.device.formI18nLabel.transportProtocol') }}</div>
 	<div class="text">{{ data.name }}</div>
-	<div class="title">消息协议</div>
+	<!-- 消息协议 -->
+	<div class="title">{{ $t('message.device.formI18nLabel.messageProtocol') }}</div>
 	<div class="text">{{ data.protocol }}</div>
-	<div class="title">认证说明</div>
+	<!-- 认证说明 -->
+	<div class="title">{{ $t('message.device.formI18nLabel.authDescription') }}</div>
 	<div class="text">{{ data.description }}</div>
-	<div class="title">链接信息</div>
+	<!-- 链接信息 -->
+	<div class="title">{{ $t('message.device.formI18nLabel.linkInfo') }}</div>
 	<div class="text">{{ data.link }}</div>
-	<div class="title">认证配置</div>
+	<!-- 认证配置 -->
+	<div class="title">{{ $t('message.device.formI18nLabel.authConfig') }}</div>
 
-	<template v-if="!isAdmin">请联系管理员</template>
+	<!-- 请联系管理员 -->
+	<template v-if="!isAdmin">{{ $t('message.device.formI18nLabel.contactAdmin') }}</template>
 	<template v-else-if="data.authType === 1 || data.authType === 2">
-		<el-form-item label="认证方式" prop="authType" label-width="80px" style="margin-bottom: 0;">
+		<!-- 认证方式 -->
+		<el-form-item :label="$t('message.device.formI18nLabel.authType')" prop="authType" label-width="80px" style="margin-bottom: 0;">
 			{{ data.authType === 1 ? 'Basic' : 'AccessToken' }}
 		</el-form-item>
 		<template v-if="data.authType === 1">
-			<el-form-item label="用户名" prop="authUser" label-width="80px" style="margin-bottom: 0;">
+			<!-- 用户名 -->
+			<el-form-item :label="$t('message.device.formI18nLabel.authUser')" prop="authUser" label-width="80px" style="margin-bottom: 0;">
 				{{ data.authUser }}
 			</el-form-item>
-			<el-form-item label="密码" prop="authPasswd" label-width="80px">
+			<!-- 密码 -->
+			<el-form-item :label="$t('message.device.formI18nLabel.authPasswd')" prop="authPasswd" label-width="80px">
 				{{ data.authPasswd }}
 			</el-form-item>
 		</template>
 		<template v-else>
+			<!-- Aceess Token -->
 			<el-form-item label="Aceess Token" prop="accessToken">
 				{{ data.accessToken }}
 			</el-form-item>
 		</template>
 	</template>
 	<template v-else-if="data.authType === 3">
-		<el-form-item label="认证证书" prop="certificateName">
+		<!-- 认证证书 -->
+		<el-form-item :label="$t('message.device.formI18nLabel.certificateId')" prop="certificateName">
 			{{ data.certificateName }}
 		</el-form-item>
 	</template>

+ 406 - 345
src/views/iot/device/product/component/editAttr.vue

@@ -1,58 +1,105 @@
 <template>
 	<div class="system-edit-dic-container">
-		<el-dialog :title="(ruleForm.id !== 0 ? '修改' : '添加') + '属性定义'" v-model="isShowDialog" width="769px">
-			<el-form :model="ruleForm" ref="formRef" :rules="rules" label-width="120px">
-				<el-form-item label="属性定义标识" prop="key">
-					<el-input v-model="ruleForm.key" placeholder="请输入属性定义标识" :disabled="ruleForm.id !== 0 ? true : false" />
+		<!-- 新增属性定义/编辑属性定义 -->
+		<el-dialog
+			:title="ruleForm.id !== 0 ? $t('message.device.dialogI18n.editPropertyDefinition') : $t('message.device.dialogI18n.addPropertyDefinition')"
+			v-model="isShowDialog"
+			width="769px"
+		>
+			<!-- 根据当前语言设置label-width -->
+			<el-form :model="ruleForm" ref="formRef" :rules="rules" :label-width="currentLocale == 'en' ? '150px' : '120px'">
+				<!-- 属性定义标识 -->
+				<el-form-item :label="$t('message.device.formI18nLabel.propertyIdentifier')" prop="key">
+					<!-- 请输入属性定义标识 -->
+					<el-input
+						v-model="ruleForm.key"
+						:placeholder="$t('message.device.formI18nPlaceholder.propertyIdentifier')"
+						:disabled="ruleForm.id !== 0 ? true : false"
+					/>
 				</el-form-item>
-				<el-form-item label="属性定义名称" prop="name">
-					<el-input v-model.trim="ruleForm.name" placeholder="请输入属性定义名称" />
+				<!-- 属性定义名称 -->
+				<el-form-item :label="$t('message.device.formI18nLabel.propertyName')" prop="name">
+					<!-- 请输入属性定义名称 -->
+					<el-input v-model.trim="ruleForm.name" :placeholder="$t('message.device.formI18nPlaceholder.propertyName')" />
 				</el-form-item>
 
-				<el-form-item label="数据类型" prop="type">
-					<el-select v-model="valueType.type" placeholder="请选择数据类型" @change="seletChange" :disabled="ruleForm.id !== 0 ? true : false">
-						<el-option-group v-for="group in typeData" :key="group.label" :label="group.label">
-							<el-option v-for="item in group.options" :key="item.type" :label="item.title" :value="item.type" />
-						</el-option-group>
-					</el-select>
+				<!-- 数据类型 -->
+				<el-form-item :label="$t('message.device.formI18nLabel.dataType')" prop="type">
+					<template v-if="typeData.length > 0">
+						<!-- 请选择数据类型 -->
+						<el-select
+							v-model="valueType.type"
+							:placeholder="$t('message.device.formI18nPlaceholder.selectDataType')"
+							@change="seletChange"
+							:disabled="ruleForm.id !== 0 ? true : false"
+						>
+							<el-option-group v-for="group in typeData" :key="group.label" :label="group.label">
+								<el-option v-for="item in group.options" :key="item.type" :label="item.title" :value="item.type" />
+							</el-option-group>
+						</el-select>
+					</template>
 				</el-form-item>
 
 				<!--根据数据类型输出不同表单-->
 
-				<el-form-item label="精度" prop="decimals" v-if="type == 'float' || type == 'double'">
-					<el-input v-model="valueType.decimals" placeholder="请输入精度" />
+				<!-- 精度 -->
+				<el-form-item :label="$t('message.device.formI18nLabel.precision')" prop="decimals" v-if="type == 'float' || type == 'double'">
+					<!-- 请输入精度 -->
+					<el-input v-model="valueType.decimals" :placeholder="$t('message.device.formI18nPlaceholder.precision')" />
 				</el-form-item>
 
-				<el-form-item label="单位" prop="unit" v-if="type == 'int' || type == 'long' || type == 'float' || type == 'double'">
-					<el-input v-model="valueType.unit" placeholder="请输入单位" />
+				<!-- 单位 -->
+				<el-form-item
+					:label="$t('message.device.formI18nLabel.unit')"
+					prop="unit"
+					v-if="type == 'int' || type == 'long' || type == 'float' || type == 'double'"
+				>
+					<!-- 请输入单位 -->
+					<el-input v-model="valueType.unit" :placeholder="$t('message.device.formI18nPlaceholder.inputUnit')" />
 				</el-form-item>
 
-				<el-form-item label="最大长度" prop="maxLength" v-if="type == 'string'">
-					<el-input v-model="valueType.maxLength" placeholder="请输入最大长度" />
+				<!-- 最大长度 -->
+				<el-form-item :label="$t('message.device.formI18nLabel.maxLength')" prop="maxLength" v-if="type == 'string'">
+					<!-- 请输入最大长度 -->
+					<el-input v-model="valueType.maxLength" :placeholder="$t('message.device.formI18nPlaceholder.inputMaxLength')" />
 				</el-form-item>
 
-				<el-form-item label="时间格式" prop="maxLength" v-if="type == 'date'">
-					<el-input v-model="valueType.maxLength" placeholder="请输入时间格式" />
+				<!-- 时间格式 -->
+				<el-form-item :label="$t('message.device.formI18nLabel.timeFormat')" prop="maxLength" v-if="type == 'date'">
+					<!-- 请输入时间格式 -->
+					<el-input v-model="valueType.maxLength" :placeholder="$t('message.device.formI18nPlaceholder.inputTimeFormat')" />
 				</el-form-item>
 
-				<el-form-item label="布尔值" prop="trueText" v-if="type == 'boolean'">
+				<!-- 布尔值 -->
+				<el-form-item :label="$t('message.device.formI18nLabel.booleanValue')" prop="trueText" v-if="type == 'boolean'">
 					<div class="input-box flex-row">
-						<el-input v-model="valueType.trueText" placeholder="请输入true时显示的文字" /><span style="margin: 0px 10px">~</span>
-						<el-input v-model="valueType.trueValue" placeholder="请输入布尔值" disabled />
+						<!-- 请输入true时显示的文字 -->
+						<el-input v-model="valueType.trueText" :placeholder="$t('message.device.formI18nPlaceholder.inputTrueText')" /><span
+							style="margin: 0px 10px"
+							>~</span
+						>
+						<!-- 请输入布尔值 -->
+						<el-input v-model="valueType.trueValue" :placeholder="$t('message.device.formI18nPlaceholder.inputBooleanValue')" disabled />
 					</div>
 
 					<div class="input-box flex-row">
-						<el-input v-model="valueType.falseText" placeholder="请输入false时显示的文字" /> <span style="margin: 0px 10px">~</span>
-						<el-input v-model="valueType.falseValue" placeholder="请输入布尔值" disabled />
+						<!-- 请输入false时显示的文字 -->
+						<el-input v-model="valueType.falseText" :placeholder="$t('message.device.formI18nPlaceholder.inputFalseText')" />
+						<span style="margin: 0px 10px">~</span>
+						<!-- 请输入布尔值 -->
+						<el-input v-model="valueType.falseValue" :placeholder="$t('message.device.formI18nPlaceholder.inputBooleanValue')" disabled />
 					</div>
 				</el-form-item>
 
-				<el-form-item label="枚举项" prop="maxLength" v-if="type == 'enum'">
+				<!-- 枚举项 -->
+				<el-form-item :label="$t('message.device.formI18nLabel.enumItems')" prop="maxLength" v-if="type == 'enum'">
 					<div class="input-box flex-row" v-for="(item, index) in enumdata" :key="index">
-						<el-input v-model="item.text" placeholder="请输入枚举文本" /><span style="margin: 0px 10px"><el-icon>
-								<Right />
-							</el-icon></span>
-						<el-input v-model="item.value" placeholder="请输入枚举值" />
+						<!-- 请输入枚举文本 -->
+						<el-input v-model="item.text" :placeholder="$t('message.device.formI18nPlaceholder.inputEnumText')" /><span style="margin: 0px 10px"
+							><el-icon> <Right /> </el-icon
+						></span>
+						<!-- 请输入枚举值 -->
+						<el-input v-model="item.value" :placeholder="$t('message.device.formI18nPlaceholder.inputEnumValue')" />
 						<div class="input-option">
 							<el-icon @click="addEnum" v-if="index == 0">
 								<Plus />
@@ -64,15 +111,20 @@
 					</div>
 				</el-form-item>
 
-				<el-form-item label="JSON对象" prop="maxLength" v-if="type == 'object'">
+				<el-form-item :label="$t('message.device.formI18nLabel.jsonObject')" prop="maxLength" v-if="type == 'object'">
 					<div v-for="(item, index) in jsondata" :key="index" class="jslist">
 						<div class="jsonlist">
-							<div>参数标识:{{ item.key }}</div>
-							<div>参数名称:{{ item.name }}</div>
-							<div>数据类型:{{ item.valueType.type }}</div>
+							<!-- 参数标识:{{ item.key }} -->
+							<div>{{ $t('message.device.formI18nLabel.parameterIdentifier') }}:{{ item.key }}</div>
+							<!-- 参数名称:{{ item.name }} -->
+							<div>{{ $t('message.device.formI18nLabel.parameterName') }}:{{ item.name }}</div>
+							<!-- 数据类型:{{ item.valueType.type }} -->
+							<div>{{ $t('message.device.formI18nLabel.dataType') }}:{{ item.valueType.type }}</div>
 							<div class="jsonoption">
-								<el-link type="primary" @click="editjson(index)">编辑</el-link>
-								<el-link type="primary" @click="deljson(index)">删除</el-link>
+								<!-- 编辑 -->
+								<el-link type="primary" @click="editjson(index)">{{ $t('message.tableI18nAction.edit') }}</el-link>
+								<!-- 删除 -->
+								<el-link type="primary" @click="deljson(index)">{{ $t('message.tableI18nAction.delete') }}</el-link>
 							</div>
 						</div>
 					</div>
@@ -82,54 +134,81 @@
 							<el-icon>
 								<Plus />
 							</el-icon>
-							<div>添加参数</div>
+							<!-- 添加参数 -->
+							<div>{{ $t('message.device.formI18nButton.addParameter') }}</div>
 						</div>
 					</div>
 				</el-form-item>
 
 				<div v-if="type == 'array'">
-					<el-form-item label="元素类型" prop="types">
-						<el-select v-model="elementType.type" placeholder="请选择元素类型" @change="seletChanges">
+					<!-- 元素类型 -->
+					<el-form-item :label="$t('message.device.formI18nLabel.elementType')" prop="types">
+						<!-- 请选择元素类型 -->
+						<el-select v-model="elementType.type" :placeholder="$t('message.device.formI18nPlaceholder.selectElementType')" @change="seletChanges">
 							<el-option-group v-for="group in typeData" :key="group.label" :label="group.label">
 								<el-option v-for="item in group.options" :key="item.type" :label="item.title" :value="item.type" :disabled="item.type == 'array'" />
 							</el-option-group>
 						</el-select>
 					</el-form-item>
 
-					<el-form-item label="精度" prop="decimals" v-if="types == 'float' || types == 'double'">
-						<el-input v-model="elementType.decimals" placeholder="请输入精度" />
+					<!-- 精度 -->
+					<el-form-item :label="$t('message.device.formI18nLabel.precision')" prop="decimals" v-if="types == 'float' || types == 'double'">
+						<!-- 请输入精度 -->
+						<el-input v-model="elementType.decimals" :placeholder="$t('message.device.formI18nPlaceholder.inputPrecision')" />
 					</el-form-item>
 
-					<el-form-item label="单位" prop="unit" v-if="types == 'int' || types == 'long' || types == 'float' || types == 'double'">
-						<el-input v-model="elementType.unit" placeholder="请输入单位" />
+					<!-- 单位 -->
+					<el-form-item
+						:label="$t('message.device.formI18nLabel.unit')"
+						prop="unit"
+						v-if="types == 'int' || types == 'long' || types == 'float' || types == 'double'"
+					>
+						<!-- 请输入单位 -->
+						<el-input v-model="elementType.unit" :placeholder="$t('message.device.formI18nPlaceholder.inputUnit')" />
 					</el-form-item>
 
-					<el-form-item label="最大长度" prop="maxLength" v-if="types == 'string'">
-						<el-input v-model="elementType.maxLength" placeholder="请输入最大长度" />
+					<!-- 最大长度 -->
+					<el-form-item :label="$t('message.device.formI18nLabel.maxLength')" prop="maxLength" v-if="types == 'string'">
+						<!-- 请输入最大长度 -->
+						<el-input v-model="elementType.maxLength" :placeholder="$t('message.device.formI18nPlaceholder.inputMaxLength')" />
 					</el-form-item>
 
-					<el-form-item label="时间格式" prop="maxLength" v-if="types == 'date'">
-						<el-input v-model="elementType.maxLength" placeholder="请输入时间格式" />
+					<!-- 时间格式 -->
+					<el-form-item :label="$t('message.device.formI18nLabel.timeFormat')" prop="maxLength" v-if="types == 'date'">
+						<!-- 请输入时间格式 -->
+						<el-input v-model="elementType.maxLength" :placeholder="$t('message.device.formI18nPlaceholder.inputTimeFormat')" />
 					</el-form-item>
 
-					<el-form-item label="布尔值" prop="maxLength" v-if="types == 'boolean'">
+					<!-- 布尔值 -->
+					<el-form-item :label="$t('message.device.formI18nLabel.booleanValue')" prop="maxLength" v-if="types == 'boolean'">
 						<div class="input-box flex-row">
-							<el-input v-model="elementType.trueText" placeholder="请输入true时显示的文字" /><span style="margin: 0px 10px">~</span>
-							<el-input v-model="elementType.trueValue" placeholder="请输入布尔值" disabled />
+							<!-- 请输入true时显示的文字 -->
+							<el-input v-model="elementType.trueText" :placeholder="$t('message.device.formI18nPlaceholder.inputTrueText')" /><span
+								style="margin: 0px 10px"
+								>~</span
+							>
+							<!-- 请输入布尔值 -->
+							<el-input v-model="elementType.trueValue" :placeholder="$t('message.device.formI18nPlaceholder.inputBooleanValue')" disabled />
 						</div>
 
 						<div class="input-box flex-row">
-							<el-input v-model="elementType.falseText" placeholder="请输入false时显示的文字" /> <span style="margin: 0px 10px">~</span>
-							<el-input v-model="elementType.falseValue" placeholder="请输入布尔值" disabled />
+							<!-- 请输入false时显示的文字 -->
+							<el-input v-model="elementType.falseText" :placeholder="$t('message.device.formI18nPlaceholder.inputFalseText')" />
+							<span style="margin: 0px 10px">~</span>
+							<!-- 请输入布尔值 -->
+							<el-input v-model="elementType.falseValue" :placeholder="$t('message.device.formI18nPlaceholder.inputBooleanValue')" disabled />
 						</div>
 					</el-form-item>
 
-					<el-form-item label="枚举项" prop="maxLength" v-if="types == 'enum'">
+					<!-- 枚举项 -->
+					<el-form-item :label="$t('message.device.formI18nLabel.enumItems')" prop="maxLength" v-if="types == 'enum'">
 						<div class="input-box flex-row" v-for="(item, index) in enumdata" :key="index">
-							<el-input v-model="item.text" placeholder="请输入枚举文本" /><span style="margin: 0px 10px"><el-icon>
-									<Right />
-								</el-icon></span>
-							<el-input v-model="item.value" placeholder="请输入枚举值" />
+							<!-- 请输入枚举文本 -->
+							<el-input v-model="item.text" :placeholder="$t('message.device.formI18nPlaceholder.inputEnumText')" /><span style="margin: 0px 10px"
+								><el-icon> <Right /> </el-icon
+							></span>
+							<!-- 请输入枚举值 -->
+							<el-input v-model="item.value" :placeholder="$t('message.device.formI18nPlaceholder.inputEnumValue')" />
 							<div class="input-option">
 								<el-icon @click="addEnum" v-if="index == 0">
 									<Plus />
@@ -142,16 +221,20 @@
 					</el-form-item>
 				</div>
 
-
-				<el-form-item label="JSON对象" prop="maxLength" v-if="types == 'object'">
+				<el-form-item :label="$t('message.device.formI18nLabel.jsonObject')" prop="maxLength" v-if="types == 'object'">
 					<div v-for="(item, index) in jsondata" :key="index" class="jslist">
 						<div class="jsonlist">
-							<div>参数标识:{{ item.key }}</div>
-							<div>参数名称:{{ item.name }}</div>
-							<div>数据类型:{{ item.valueType.type }}</div>
+							<!-- 参数标识:{{ item.key }} -->
+							<div>{{ $t('message.device.formI18nLabel.parameterIdentifier') }}:{{ item.key }}</div>
+							<!-- 参数名称:{{ item.name }} -->
+							<div>{{ $t('message.device.formI18nLabel.parameterName') }}:{{ item.name }}</div>
+							<!-- 数据类型:{{ item.valueType.type }} -->
+							<div>{{ $t('message.device.formI18nLabel.dataType') }}:{{ item.valueType.type }}</div>
 							<div class="jsonoption">
-								<el-link type="primary" @click="editjson(index)">编辑</el-link>
-								<el-link type="primary" @click="deljson(index)">删除</el-link>
+								<!-- 编辑 -->
+								<el-link type="primary" @click="editjson(index)">{{ $t('message.tableI18nAction.edit') }}</el-link>
+								<!-- 删除 -->
+								<el-link type="primary" @click="deljson(index)">{{ $t('message.tableI18nAction.delete') }}</el-link>
 							</div>
 						</div>
 					</div>
@@ -161,27 +244,36 @@
 							<el-icon>
 								<Plus />
 							</el-icon>
-							<div>添加参数</div>
+							<!-- 添加参数 -->
+							<div>{{ $t('message.tableI18nAction.addParameter') }}</div>
 						</div>
 					</div>
 				</el-form-item>
 
 				<!--根据数据类型输出不同表单-->
-
-				<el-form-item label="是否只读" prop="accessMode">
+				<!-- 是否只读 -->
+				<el-form-item :label="$t('message.device.formI18nLabel.isReadOnly')" prop="accessMode">
 					<el-radio-group v-model="ruleForm.accessMode">
-						<el-radio :label="1">只读</el-radio>
-						<el-radio :label="0">读写</el-radio>
+						<!-- 1:只读 -->
+						<el-radio :label="1">{{ $t('message.device.formI18nOption.readonly') }}</el-radio>
+						<!-- 0:读写 -->
+						<el-radio :label="0">{{ $t('message.device.formI18nOption.readWrite') }}</el-radio>
 					</el-radio-group>
 				</el-form-item>
-				<el-form-item label="属性定义描述" prop="desc">
-					<el-input v-model="ruleForm.desc" type="textarea" placeholder="请输入属性定义描述"></el-input>
+				<!-- 属性定义描述 -->
+				<el-form-item :label="$t('message.device.formI18nLabel.propertyDescription')" prop="desc">
+					<!-- 请输入属性定义描述 -->
+					<el-input v-model="ruleForm.desc" type="textarea" :placeholder="$t('message.device.formI18nPlaceholder.inputDescription')"></el-input>
 				</el-form-item>
 			</el-form>
 			<template #footer>
 				<span class="dialog-footer">
-					<el-button @click="onCancel">取 消</el-button>
-					<el-button type="primary" @click="onSubmit">{{ ruleForm.id !== 0 ? '修 改' : '添 加' }}</el-button>
+					<!-- 取消 -->
+					<el-button @click="onCancel">{{ $t('message.tableI18nAction.cancel') }}</el-button>
+					<!-- 编辑/添加 -->
+					<el-button type="primary" @click="onSubmit">{{
+						ruleForm.id !== 0 ? $t('message.tableI18nAction.edit') : $t('message.tableI18nAction.add')
+					}}</el-button>
 				</span>
 			</template>
 		</el-dialog>
@@ -189,32 +281,23 @@
 	</div>
 </template>
 
-<script lang="ts">
-import { reactive, toRefs, defineComponent, ref, unref } from 'vue';
-import api from '/@/api/device';
-import { Plus, Minus, Right } from '@element-plus/icons-vue';
-import EditOption from './editOption.vue';
-import { ElMessage } from 'element-plus';
-import { validateNoSpace } from '/@/utils/validator';
-
-interface RuleFormState {
-	id: number;
-	productKey: string;
-  deviceKey: string;
-	name: string;
-	dictType: string;
-	valueType: Object;
-	status: number;
-	desc: string;
-}
-interface DicState {
-	isShowDialog: boolean;
-	ruleForm: RuleFormState;
-	typeData: RuleFormState[];
-	rules: {};
-}
+<script lang="ts" setup>
+import { computed, ref, unref } from 'vue'
+import api from '/@/api/device'
+import { Plus, Minus, Right } from '@element-plus/icons-vue'
+import EditOption from './editOption.vue'
+import { ElMessage } from 'element-plus'
+import { validateNoSpace } from '/@/utils/validator'
+import { useI18n } from 'vue-i18n'
+
+// 国际化
+const { locale, t } = useI18n()
 
-const valueType = {
+const currentLocale = computed(() => locale.value)
+
+const emit = defineEmits(['typeList'])
+
+const valueTypeModule = {
 	type: '',
 	maxLength: '',
 	trueText: '是',
@@ -223,268 +306,248 @@ const valueType = {
 	falseValue: false,
 }
 
-export default defineComponent({
-	name: 'deviceEditPro',
-	components: { Plus, Minus, Right, EditOption },
-	setup(prop, { emit }) {
-		const formRef = ref<HTMLElement | null>(null);
-		const editOptionRef = ref();
-		const state = reactive<DicState>({
-			isShowDialog: false,
-			typeData: [], //
-			type: '',
-			types: '',
-			productKey: '',
-			valueType: JSON.parse(JSON.stringify(valueType)),
-			elementType: JSON.parse(JSON.stringify(valueType)),
-			enumdata: [
-				{
-					text: '',
-					value: '',
-				},
-			],
-
-			jsondata: [],
-
-			ruleForm: {
-				id: 0,
-				productKey: '',
-        deviceKey: '',
-				name: '',
-				key: '',
-				transportProtocol: '',
-				accessMode: 1,
-				status: 1,
-				valueType: JSON.parse(JSON.stringify(valueType)),
-				desc: '',
-			},
-			rules: {
-				name: [{ required: true, message: '属性定义名称不能为空', trigger: 'blur' },
-				{ max: 32, message: '属性定义名称不能超过32个字符', trigger: 'blur' },
-				{ validator: validateNoSpace, message: '属性定义名称不能包含空格', trigger: 'blur' }
-				],
-				key: [{ required: true, message: '属性定义标识不能为空', trigger: 'blur' }],
-				accessMode: [{ required: true, message: '请选择是否只读', trigger: 'blur' }],
-				type: [{ required: true, message: '请选择数据类型', trigger: 'blur' }],
-			},
-		});
-
-		// 打开弹窗
-		const openDialog = (row: RuleFormState | null, productKey: string | null) => {
-      resetForm();
-
-			api.product.getDataType({ status: -1 }).then((res: any) => {
-				const datat = Object.values(res.dataType);
-				datat.forEach((item, index) => {
-					if (index == 0) {
-						datat[index]['label'] = '基础类型';
-						datat[index]['options'] = item;
-					} else {
-						datat[index]['label'] = '扩展类型';
-						datat[index]['options'] = item;
-					}
-				});
-				state.typeData = datat || [];
-			});
-			state.ruleForm = row;
-			if (row.valueType) {
-				state.ruleForm = row;
-
-				state.productKey = productKey;
-        state.deviceKey = row.deviceKey;
-        state.valueType = row.valueType;
-				state.ruleForm.valueType.type = row.valueType.type;
-				state.ruleForm.type = row.valueType.type;
-				state.type = row.valueType.type;
-				state.ruleForm.accessMode = row.accessMode;
-				if (row.valueType.elementType) {
-					state.elementType = row.valueType.elementType;
-					state.types = row.valueType.elementType.type;
-				}
-
-				if (row.type == 'enum') {
-					state.enumdata = row.valueType.elements;
-				}
-
-				if (row.type == 'object') {
-					state.jsondata = JSON.parse(JSON.stringify(row.valueType.properties));
-				}
-
-				if (row.type == 'array' && state.types == 'enum') {
-					state.enumdata = row.valueType.elementType.elements
-				}
-				if (row.type == 'array' && state.types == 'object') {
-					state.jsondata = JSON.parse(JSON.stringify(row.valueType.elementType.properties));
-				}
+const formRef = ref<HTMLElement | null>(null)
+const editOptionRef = ref()
+const rules = computed(() => ({
+	name: [
+		// 属性定义名称不能为空
+		{ required: true, message: t('message.device.rules.propertyName'), trigger: 'blur' },
+		// 属性定义名称不能超过32个字符
+		{ max: 32, message: t('message.device.rules.propertyNameMax32'), trigger: 'blur' },
+		// 属性定义名称不能包含空格
+		{ validator: validateNoSpace, message: t('message.device.rules.propertyNameValidator'), trigger: 'blur' },
+	],
+	// 属性定义标识不能为空
+	key: [{ required: true, message: t('message.device.rules.propertyKey'), trigger: 'blur' }],
+	// 请选择是否只读
+	accessMode: [{ required: true, message: t('message.device.rules.accessMode'), trigger: 'blur' }],
+	// 请选择数据类型
+	type: [{ required: true, message: t('message.device.rules.selectDataType'), trigger: 'blur' }],
+}))
+const ruleForm = ref<any>({
+	id: 0,
+	productKey: '',
+	deviceKey: '',
+	name: '',
+	key: '',
+	transportProtocol: '',
+	accessMode: 1,
+	status: 1,
+	valueType: JSON.parse(JSON.stringify(valueTypeModule)),
+	desc: '',
+})
+
+const jsondata = ref<any>([])
+const isShowDialog = ref(false)
+const elementType = ref(JSON.parse(JSON.stringify(valueTypeModule)))
+const valueType = ref(JSON.parse(JSON.stringify(valueTypeModule)))
+const typeData = ref([])
+const enumdata = ref([
+	{
+		text: '',
+		value: '',
+	},
+])
+const type = ref('')
+const types = ref('')
+const productKey = ref<any>('')
+
+// 打开弹窗
+const openDialog = (row: any, productKeys: string | null) => {
+	resetForm()
+
+	api.product.getDataType({ status: -1 }).then((res: any) => {
+		const datat: any = Object.values(res.dataType)
+		datat.forEach((item: any, index: any) => {
+			if (index == 0) {
+				datat[index]['label'] = t('message.device.baseType')
+				datat[index]['options'] = item
+			} else {
+				datat[index]['label'] = t('message.device.extensionType')
+				datat[index]['options'] = item
 			}
+		})
+		typeData.value = datat || []
+	})
+	ruleForm.value = row
+	if (row.valueType) {
+		ruleForm.value = row
+
+		productKey.value = productKeys
+		// deviceKey.value = row.deviceKey
+		valueType.value = row.valueType
+		ruleForm.value.valueType.type = row.valueType.type
+		ruleForm.value.type = row.valueType.type
+		type.value = row.valueType.type
+		ruleForm.value.accessMode = row.accessMode
+		if (row.valueType.elementType) {
+			elementType.value = row.valueType.elementType
+			types.value = row.valueType.elementType.type
+		}
 
+		if (row.type == 'enum') {
+			enumdata.value = row.valueType.elements
+		}
 
-			state.isShowDialog = true;
-		};
-		const resetForm = () => {
-			state.ruleForm = {
-				name: '',
-				key: '',
-				transportProtocol: '',
-				accessMode: 1,
-				status: 1,
-				valueType: JSON.parse(JSON.stringify(valueType)),
-				desc: '',
-
-			};
-			state.type = '';
-			state.types = '';
-			state.valueType = JSON.parse(JSON.stringify(valueType));
-			state.elementType = JSON.parse(JSON.stringify(valueType));
-			state.jsondata = [];
-			state.enumdata = [{
-				text: '',
-				value: '',
-			},];
-		};
-
-		const seletChange = (val) => {
-			state.type = val;
-			state.ruleForm.type = val;
-		};
-		const seletChanges = (val) => {
-			state.types = val;
-		};
-
-		const addEnum = () => {
-			state.enumdata.push({
-				text: '',
-				value: '',
-			});
-		};
-		const delEnum = (index) => {
-			state.enumdata.splice(index, 1);
-		};
-
-		const editjson = (index) => {
-
-			editOptionRef.value.openDialog(state.jsondata[index]);
+		if (row.type == 'object') {
+			jsondata.value = JSON.parse(JSON.stringify(row.valueType.properties))
+		}
 
+		if (row.type == 'array' && types.value == 'enum') {
+			enumdata.value = row.valueType.elementType.elements
 		}
-		const deljson = (index) => {
-			state.jsondata.splice(index, 1);
+		if (row.type == 'array' && types.value == 'object') {
+			jsondata.value = JSON.parse(JSON.stringify(row.valueType.elementType.properties))
 		}
+	}
 
-		const addJson = () => {
-			editOptionRef.value.openDialog({ productKey: '', id: 0 });
-		};
-		const getOptionData = (data) => {
-			state.jsondata.push(data);
-		};
-		// 关闭弹窗
-		const closeDialog = () => {
-			state.isShowDialog = false;
-		};
-		// 取消
-		const onCancel = () => {
-			closeDialog();
-		};
-		// 新增
-		const onSubmit = () => {
-			const formWrap = unref(formRef) as any;
-			if (!formWrap) return;
-			formWrap.validate((valid: boolean) => {
-				if (valid) {
-					if (state.ruleForm.id !== 0) {
-						//修改
-						if (state.type == 'enum') {
-							state.valueType.elements = state.enumdata;
-						}
+	isShowDialog.value = true
+}
+const resetForm = () => {
+	ruleForm.value = {
+		name: '',
+		key: '',
+		transportProtocol: '',
+		accessMode: 1,
+		status: 1,
+		valueType: JSON.parse(JSON.stringify(valueType)),
+		desc: '',
+	}
+	type.value = ''
+	types.value = ''
+	valueType.value = JSON.parse(JSON.stringify(valueType))
+	elementType.value = JSON.parse(JSON.stringify(valueType))
+	jsondata.value = []
+	enumdata.value = [
+		{
+			text: '',
+			value: '',
+		},
+	]
+}
 
-						if (state.type == 'object') {
-							state.valueType.properties = state.jsondata;
-						}
+const seletChange = (val: string) => {
+	type.value = val
+	ruleForm.value.type = val
+}
+const seletChanges = (val: string) => {
+	types.value = val
+}
 
-						if (state.type == 'array') {
-							state.valueType.elementType = state.elementType;
-							//如果是选中数组,并选择了枚举
-							if (state.types == 'enum') {
-								state.valueType.elementType = {
-									elements: state.enumdata,
-									type: 'enum'
-								}
-							}
-							//如果是选中数组,并选择了object
-							if (state.types == 'object') {
-								state.valueType.elementType = {
-									properties: state.jsondata,
-									type: 'object'
-								}
-							}
-						}
+const addEnum = () => {
+	enumdata.value.push({
+		text: '',
+		value: '',
+	})
+}
+const delEnum = (index: number) => {
+	enumdata.value.splice(index, 1)
+}
 
-						state.ruleForm.valueType = state.valueType;
-						state.ruleForm.productKey = state.productKey
-						api.model.propertyedit(state.ruleForm).then(() => {
-							ElMessage.success('属性定义类型修改成功');
-							closeDialog(); // 关闭弹窗
-							emit('typeList');
-						});
-					} else {
-						//添加
-						if (state.type == 'enum') {
-							state.valueType.elements = state.enumdata;
-						}
+const editjson = (index: number) => {
+	editOptionRef.value.openDialog(jsondata.value[index])
+}
+const deljson = (index: number) => {
+	jsondata.value.splice(index, 1)
+}
 
-						if (state.type == 'object') {
-							state.valueType.properties = state.jsondata;
-						}
+const addJson = () => {
+	editOptionRef.value.openDialog({ productKey: '', id: 0 })
+}
+const getOptionData = (data: any) => {
+	jsondata.value.push(data)
+}
+// 关闭弹窗
+const closeDialog = () => {
+	isShowDialog.value = false
+}
+// 取消
+const onCancel = () => {
+	closeDialog()
+}
+// 新增
+const onSubmit = () => {
+	const formWrap = unref(formRef) as any
+	if (!formWrap) return
+	formWrap.validate((valid: boolean) => {
+		if (valid) {
+			if (ruleForm.value.id !== 0) {
+				//修改
+				if (type.value == 'enum') {
+					valueType.value.elements = enumdata.value
+				}
+
+				if (type.value == 'object') {
+					valueType.value.properties = jsondata.value
+				}
 
-						if (state.type == 'array') {
-							state.valueType.elementType = state.elementType;
-							//如果是选中数组,并选择了枚举
-							if (state.types == 'enum') {
-								state.valueType.elementType = {
-									elements: state.enumdata,
-									type: 'enum'
-								}
-							}
-							//如果是选中数组,并选择了object
-							if (state.types == 'object') {
-								state.valueType.elementType = {
-									properties: state.jsondata,
-									type: 'object'
-								}
-							}
+				if (type.value == 'array') {
+					valueType.value.elementType = elementType.value
+					//如果是选中数组,并选择了枚举
+					if (types.value == 'enum') {
+						valueType.value.elementType = {
+							elements: enumdata.value,
+							type: 'enum',
 						}
+					}
+					//如果是选中数组,并选择了object
+					if (types.value == 'object') {
+						valueType.value.elementType = {
+							properties: jsondata.value,
+							type: 'object',
+						}
+					}
+				}
+
+				ruleForm.value.valueType = valueType.value
+				ruleForm.value.productKey = productKey.value
+				api.model.propertyedit(ruleForm.value).then(() => {
+					ElMessage.success(t('message.tableI18nConfirm.editSuccess'))
+					closeDialog() // 关闭弹窗
+					emit('typeList')
+				})
+			} else {
+				//添加
+				if (type.value == 'enum') {
+					valueType.value.elements = enumdata.value
+				}
+
+				if (type.value == 'object') {
+					valueType.value.properties = jsondata.value
+				}
 
-						state.ruleForm.valueType = state.valueType;
-						api.model.propertyadd(state.ruleForm).then(() => {
-							ElMessage.success('属性定义类型添加成功');
-							closeDialog(); // 关闭弹窗
-							emit('typeList');
-						});
+				if (type.value == 'array') {
+					valueType.value.elementType = elementType.value
+					//如果是选中数组,并选择了枚举
+					if (types.value == 'enum') {
+						valueType.value.elementType = {
+							elements: enumdata.value,
+							type: 'enum',
+						}
+					}
+					//如果是选中数组,并选择了object
+					if (types.value == 'object') {
+						valueType.value.elementType = {
+							properties: jsondata.value,
+							type: 'object',
+						}
 					}
 				}
-			});
-		};
-
-		return {
-			editOptionRef,
-			getOptionData,
-			openDialog,
-			deljson,
-			editjson,
-			addEnum,
-			delEnum,
-			addJson,
-			seletChange,
-			seletChanges,
-			closeDialog,
-			onCancel,
-			onSubmit,
-			formRef,
-			...toRefs(state),
-		};
-	},
-});
+
+				ruleForm.value.valueType = valueType.value
+				api.model.propertyadd(ruleForm.value).then(() => {
+					ElMessage.success(t('message.tableI18nConfirm.addSuccess'))
+					closeDialog() // 关闭弹窗
+					emit('typeList')
+				})
+			}
+		}
+	})
+}
+
+defineExpose({ openDialog })
 </script>
-<style scoped>
+<style scoped lang="scss">
 .input-box {
 	display: flex;
 	flex-direction: row;
@@ -524,8 +587,6 @@ export default defineComponent({
 	justify-content: space-between;
 }
 
-.jsonoption {}
-
 .jsonoption a {
 	margin: 0px 10px;
 }

+ 68 - 36
src/views/iot/device/product/component/editEvent.vue

@@ -1,31 +1,46 @@
 <template>
 	<div class="system-edit-dic-container">
-		<el-dialog :title="(ruleForm.id !== 0 ? '修改' : '添加') + '事件定义'" v-model="isShowDialog" width="769px">
-			<el-form :model="ruleForm" ref="formRef" :rules="rules" label-width="120px">
-				<el-form-item label="事件定义标识" prop="key">
-					<el-input v-model="ruleForm.key" placeholder="请输入事件定义标识" :disabled="ruleForm.id !== 0 ? true : false" />
+		<!-- 编辑事件定义 / 新增事件定义 -->
+		<el-dialog :title="ruleForm.id !== 0 ? $t('message.device.dialogI18n.editEventDefinition') : $t('message.device.dialogI18n.addEventDefinition')" v-model="isShowDialog" width="769px">
+			<el-form :model="ruleForm" ref="formRef" :rules="rules" :label-width="currentLocale == 'en' ? '150px' : '120px'">
+				<!-- 事件定义标识 -->
+				<el-form-item :label="$t('message.device.formI18nLabel.eventKey')" prop="key">
+					<!-- 请输入事件定义标识 -->
+					<el-input v-model="ruleForm.key" :placeholder="$t('message.device.formI18nPlaceholder.eventKey')" :disabled="ruleForm.id !== 0 ? true : false" />
 				</el-form-item>
-				<el-form-item label="事件定义名称" prop="name">
-					<el-input v-model="ruleForm.name" placeholder="请输入事件定义名称" />
+				<!-- 事件定义名称 -->
+				<el-form-item :label="$t('message.device.formI18nLabel.eventName')" prop="name">
+					<!-- 请输入事件定义名称 -->
+					<el-input v-model="ruleForm.name" :placeholder="$t('message.device.formI18nPlaceholder.eventName')" />
 				</el-form-item>
 
-				<el-form-item label="事件类型" prop="level">
+				<!-- 事件类型 -->
+				<el-form-item :label="$t('message.device.formI18nLabel.eventType')" prop="level">
 					<el-radio-group v-model="ruleForm.level">
-						<el-radio :label="0">信息</el-radio>
-						<el-radio :label="1">告警</el-radio>
-						<el-radio :label="2">故障</el-radio>
+						<!-- 信息 -->
+						<el-radio :label="0">{{ $t('message.device.formI18nOption.info') }}</el-radio>
+						<!-- 告警 -->
+						<el-radio :label="1">{{ $t('message.device.formI18nOption.warning') }}</el-radio>
+						<!-- 故障 -->
+						<el-radio :label="2">{{ $t('message.device.formI18nOption.fault') }}</el-radio>
 					</el-radio-group>
 				</el-form-item>
 
-				<el-form-item label="输出参数" prop="maxLength">
+				<!-- 输出参数 -->
+				<el-form-item :label="$t('message.device.formI18nLabel.functionOutput')" prop="maxLength">
 					<div v-for="(item, index) in outputsdata" :key="index" class="jslist">
 						<div class="jsonlist">
-							<div>参数标识:{{ item.key }}</div>
-							<div>参数名称:{{ item.name }}</div>
-							<div>数据类型:{{ item.valueType.type }}</div>
+							<!-- 参数标识 -->
+							<div>{{ $t('message.device.formI18nLabel.parameterIdentifier') }}:{{ item.key }}</div>
+							<!-- 参数名称 -->
+							<div>{{ $t('message.device.formI18nLabel.parameterName') }}:{{ item.name }}</div>
+							<!-- 数据类型 -->
+							<div>{{ $t('message.device.formI18nLabel.dataType') }}:{{ item.valueType.type }}</div>
 							<div class="jsonoption">
-								<el-link type="primary" @click="editjson(index, 'fun')">编辑</el-link>
-								<el-link type="primary" @click="deljson(index, 'fun')">删除</el-link>
+								<!-- 编辑 -->
+								<el-link type="primary" @click="editjson(index, 'fun')">{{ $t('message.tableI18nAction.edit') }}</el-link>
+								<!-- 删除 -->
+								<el-link type="primary" @click="deljson(index, 'fun')">{{ $t('message.tableI18nAction.delete') }}</el-link>
 							</div>
 						</div>
 					</div>
@@ -35,19 +50,24 @@
 							<el-icon>
 								<Plus />
 							</el-icon>
-							<div>添加参数</div>
+							<!-- 添加参数 -->
+							<div>{{ $t('message.device.formI18nButton.addParameter') }}</div>
 						</div>
 					</div>
 				</el-form-item>
 
-				<el-form-item label="事件定义描述	" prop="desc">
-					<el-input v-model="ruleForm.desc" type="textarea" placeholder="请输入事件定义描述"></el-input>
+				<!-- 事件定义描述 -->
+				<el-form-item :label="$t('message.device.formI18nLabel.eventDescription')" prop="desc">
+					<!-- 请输入事件定义描述 -->
+					<el-input v-model="ruleForm.desc" type="textarea" :placeholder="$t('message.device.formI18nPlaceholder.eventDescription')"></el-input>
 				</el-form-item>
 			</el-form>
 			<template #footer>
 				<span class="dialog-footer">
-					<el-button @click="onCancel">取 消</el-button>
-					<el-button type="primary" @click="onSubmit">{{ ruleForm.id !== 0 ? '修 改' : '添 加' }}</el-button>
+					<!-- 取消 -->
+					<el-button @click="onCancel">{{ $t('message.tableI18nAction.cancel') }}</el-button>
+					<!-- 编辑 / 新增 -->
+					<el-button type="primary" @click="onSubmit">{{ ruleForm.id !== 0 ? $t('message.tableI18nAction.edit') : $t('message.tableI18nAction.add') }}</el-button>
 				</span>
 			</template>
 		</el-dialog>
@@ -56,12 +76,13 @@
 </template>
 
 <script lang="ts">
-import { reactive, toRefs, defineComponent, ref, unref } from 'vue';
+import { reactive, toRefs, defineComponent, ref, unref, computed } from 'vue';
 import api from '/@/api/device';
 import { Plus, Minus, Right } from '@element-plus/icons-vue';
 import EditOption from './editOption.vue';
 import { validateNoSpace } from '/@/utils/validator';
 import { ElMessage } from 'element-plus';
+import { useI18n } from 'vue-i18n';
 
 interface RuleFormState {
 	id?: number;
@@ -85,7 +106,7 @@ interface DicState {
 	enumdata: any[];
 	outputsdata: any[];
 	elementType: any;
-	rules: any;
+	// rules: any;
 }
 
 const form = {
@@ -105,6 +126,24 @@ export default defineComponent({
 	setup(prop, { emit }) {
 		const formRef = ref<HTMLElement | null>(null);
 		const editOptionRef = ref();
+		const { t, locale } = useI18n();
+		const currentLocale = computed(() => locale.value);	
+		const rules = computed(() => {
+			return {
+				name: [
+					// 事件定义名称不能为空
+					{ required: true, message: t('message.device.rules.eventName'), trigger: 'blur' },
+					// 事件定义名称不能超过32个字符
+					{ max: 32, message: t('message.device.rules.eventNameMax32'), trigger: 'blur' },
+					// 事件定义名称不能包含空格
+					{ validator: validateNoSpace, message: t('message.device.rules.eventNameValidator'), trigger: 'blur' }
+				],
+				// 事件定义标识不能为空
+				key: [{ required: true, message: t('message.device.rules.eventKey'), trigger: 'blur' }],
+				// 请选择数据类型
+				type: [{ required: true, message: t('message.device.rules.eventType'), trigger: 'blur' }],
+			}
+		});
 		const state = reactive<DicState>({
 			isShowDialog: false,
 			typeData: [], //
@@ -123,16 +162,7 @@ export default defineComponent({
 			],
 			jsondata: [],
 			outputsdata: [],
-			ruleForm: JSON.parse(JSON.stringify(form)),
-			rules: {
-				name: [
-					{ required: true, message: '事件定义名称不能为空', trigger: 'blur' },
-					{ max: 32, message: '事件定义名称不能超过32个字符', trigger: 'blur' },
-					{ validator: validateNoSpace, message: '事件定义名称不能包含空格', trigger: 'blur' }
-				],
-				key: [{ required: true, message: '事件定义标识不能为空', trigger: 'blur' }],
-				type: [{ required: true, message: '请选择数据类型', trigger: 'blur' }],
-			},
+			ruleForm: JSON.parse(JSON.stringify(form))
 		});
 
 		// 打开弹窗
@@ -143,9 +173,11 @@ export default defineComponent({
 				const datat: any[] = Object.values(res.dataType);
 				datat.forEach((item, index) => {
 					if (index == 0) {
+						// 基础类型
 						datat[index]['label'] = '基础类型';
 						datat[index]['options'] = item;
 					} else {
+						// 扩展类型
 						datat[index]['label'] = '扩展类型';
 						datat[index]['options'] = item;
 					}
@@ -236,6 +268,7 @@ export default defineComponent({
 					}
 
 					theApi(state.ruleForm).then(() => {
+						// 事件定义类型操作成功
 						ElMessage.success('事件定义类型操作成功');
 						closeDialog(); // 关闭弹窗
 						emit('typeList');
@@ -245,6 +278,8 @@ export default defineComponent({
 		};
 
 		return {
+			rules,
+			currentLocale,
 			editOptionRef,
 			getOptionData,
 			openDialog,
@@ -303,9 +338,6 @@ export default defineComponent({
 	flex-direction: row;
 	justify-content: space-between;
 }
-
-.jsonoption {}
-
 .jsonoption a {
 	margin: 0px 10px;
 }

+ 202 - 240
src/views/iot/device/product/component/editFun.vue

@@ -1,23 +1,34 @@
 <template>
 	<div class="system-edit-dic-container">
-		<el-dialog :title="(ruleForm.id !== 0 ? '修改' : '添加') + '功能定义'" v-model="isShowDialog" width="769px">
+		<!-- 新增功能定义/编辑功能定义 -->
+		<el-dialog :title="ruleForm.id !== 0 ? $t('message.device.dialogI18n.editFunctionDefinition') : $t('message.device.dialogI18n.addFunctionDefinition')" v-model="isShowDialog" width="769px">
 			<el-form :model="ruleForm" ref="formRef" :rules="rules" label-width="120px">
-				<el-form-item label="功能定义标识" prop="key">
-					<el-input v-model="ruleForm.key" placeholder="请输入功能定义标识" :disabled="ruleForm.id !== 0 ? true : false" />
+				<!-- 功能定义标识 -->
+				<el-form-item :label="$t('message.device.formI18nLabel.functionKey')" prop="key">
+					<!-- 请输入功能定义标识 -->
+					<el-input v-model="ruleForm.key" :placeholder="$t('message.device.formI18nPlaceholder.functionKey')" :disabled="ruleForm.id !== 0 ? true : false" />
 				</el-form-item>
-				<el-form-item label="功能定义名称" prop="name">
-					<el-input v-model="ruleForm.name" placeholder="请输入功能定义名称" />
+				<!-- 功能定义名称 -->
+				<el-form-item :label="$t('message.device.formI18nLabel.functionName')" prop="name">
+					<!-- 请输入功能定义名称 -->
+					<el-input v-model="ruleForm.name" :placeholder="$t('message.device.formI18nPlaceholder.functionName')" />
 				</el-form-item>
 
-				<el-form-item label="输入参数" prop="maxLength">
+				<!-- 输入参数 -->
+				<el-form-item :label="$t('message.device.formI18nLabel.functionInput')" prop="maxLength">
 					<div v-for="(item, index) in inputsdata" :key="index" class="jslist">
 						<div class="jsonlist">
-							<div>参数标识:{{ item.key }}</div>
-							<div>参数名称:{{ item.name }}</div>
-							<div>数据类型:{{ item.valueType.type }}</div>
+							<!-- 参数标识 -->
+							<div>{{ $t('message.device.formI18nLabel.parameterIdentifier') }}:{{ item.key }}</div>
+							<!-- 参数名称 -->
+							<div>{{ $t('message.device.formI18nLabel.parameterName') }}:{{ item.name }}</div>
+							<!-- 数据类型 -->
+							<div>{{ $t('message.device.formI18nLabel.dataType') }}:{{ item.valueType.type }}</div>
 							<div class="jsonoption">
-								<el-link type="primary" @click="editjson(index, 'fun')">编辑</el-link>
-								<el-link type="primary" @click="deljson(index, 'fun')">删除</el-link>
+								<!-- 编辑 -->
+								<el-link type="primary" @click="editjson(index, 'fun')">{{ $t('message.tableI18nAction.edit') }}</el-link>
+								<!-- 删除 -->
+								<el-link type="primary" @click="deljson(index, 'fun')">{{ $t('message.tableI18nAction.delete') }}</el-link>
 							</div>
 						</div>
 					</div>
@@ -27,20 +38,27 @@
 							<el-icon>
 								<Plus />
 							</el-icon>
-							<div>添加参数</div>
+							<!-- 添加参数 -->
+							<div>{{ $t('message.device.formI18nButton.addParameter') }}</div>
 						</div>
 					</div>
 				</el-form-item>
 
-				<el-form-item label="输出参数" prop="">
+				<!-- 输出参数 -->
+				<el-form-item :label="$t('message.device.formI18nLabel.functionOutput')" prop="">
 					<div v-for="(item, index) in outputsdata" :key="index" class="jslist">
 						<div class="jsonlist">
-							<div>参数标识:{{ item.key }}</div>
-							<div>参数名称:{{ item.name }}</div>
-							<div>数据类型:{{ item.valueType.type }}</div>
+							<!-- 参数标识 -->
+							<div>{{ $t('message.device.formI18nLabel.parameterIdentifier') }}:{{ item.key }}</div>
+							<!-- 参数名称 -->
+							<div>{{ $t('message.device.formI18nLabel.parameterName') }}:{{ item.name }}</div>
+							<!-- 数据类型 -->
+							<div>{{ $t('message.device.formI18nLabel.dataType') }}:{{ item.valueType.type }}</div>
 							<div class="jsonoption">
-								<el-link type="primary" @click="editjsonOut(index)">编辑</el-link>
-								<el-link type="primary" @click="deljsonOut(index, 'fun')">删除</el-link>
+								<!-- 编辑 -->
+								<el-link type="primary" @click="editjsonOut(index)">{{ $t('message.tableI18nAction.edit') }}</el-link>
+								<!-- 删除 -->
+								<el-link type="primary" @click="deljsonOut(index, 'fun')">{{ $t('message.tableI18nAction.delete') }}</el-link>
 							</div>
 						</div>
 					</div>
@@ -50,19 +68,23 @@
 							<el-icon>
 								<Plus />
 							</el-icon>
-							<div>添加参数</div>
+							<!-- 添加参数 -->
+							<div>{{ $t('message.device.formI18nButton.addParameter') }}</div>
 						</div>
 					</div>
 				</el-form-item>
-
-				<el-form-item label="功能定义描述	" prop="desc">
-					<el-input v-model="ruleForm.desc" type="textarea" placeholder="请输入功能定义描述"></el-input>
+				<!-- 功能定义描述 -->
+				<el-form-item :label="$t('message.device.formI18nLabel.functionDescription')" prop="desc">
+					<!-- 请输入功能定义描述 -->
+					<el-input v-model="ruleForm.desc" type="textarea" :placeholder="$t('message.device.formI18nPlaceholder.functionDescription')"></el-input>
 				</el-form-item>
 			</el-form>
 			<template #footer>
 				<span class="dialog-footer">
-					<el-button @click="onCancel">取 消</el-button>
-					<el-button type="primary" @click="onSubmit">{{ ruleForm.id !== 0 ? '修 改' : '添 加' }}</el-button>
+					<!-- 取消 -->
+					<el-button @click="onCancel">{{ $t('message.tableI18nAction.cancel') }}</el-button>
+					<!-- 编辑 / 新增 -->
+					<el-button type="primary" @click="onSubmit">{{ ruleForm.id !== 0 ? $t('message.tableI18nAction.edit') : $t('message.tableI18nAction.add') }}</el-button>
 				</span>
 			</template>
 		</el-dialog>
@@ -71,42 +93,29 @@
 	</div>
 </template>
 
-<script lang="ts">
-import { reactive, toRefs, defineComponent, ref, unref } from 'vue';
-import api from '/@/api/device';
-import { Plus, Minus, Right } from '@element-plus/icons-vue';
-import EditOption from './editOption.vue';
-import { validateNoSpace } from '/@/utils/validator';
+<script lang="ts" setup>
+import { reactive, toRefs, defineComponent, ref, unref, computed } from 'vue'
+import api from '/@/api/device'
+import { Plus, Minus, Right } from '@element-plus/icons-vue'
+import EditOption from './editOption.vue'
+import { validateNoSpace } from '/@/utils/validator'
+import { ElMessage } from 'element-plus'
+import { useI18n } from 'vue-i18n';
 
-import { ElMessage } from 'element-plus';
+const { locale, t } = useI18n();
 
 interface RuleFormState {
-	id?: number;
-	key: string;
-	productKey: string;
-	name: string;
-	type: string;
-	dictType: string;
-	valueType: Object;
-	inputs: any;
-	outputs: any;
-	status: number;
-	desc: string;
-}
-interface DicState {
-	isShowDialog: boolean;
-	productKey: string;
-	type: string;
-	types: string;
-	ruleForm: RuleFormState;
-	typeData: any[];
-	inputsdata: any[];
-	outputsdata: any[];
-	jsondata: any[];
-	elementType: any;
-	enumdata: any;
-	valueType: any;
-	rules: {};
+	id?: number
+	key: string
+	productKey: string
+	name: string
+	type: string
+	dictType: string
+	valueType: Object
+	inputs: any
+	outputs: any
+	status: number
+	desc: string
 }
 
 const form = {
@@ -125,199 +134,154 @@ const form = {
 	desc: '',
 }
 
-export default defineComponent({
-	name: 'deviceEditPro',
-	components: { Plus, Minus, Right, EditOption },
-	setup(prop, { emit }) {
-		const formRef = ref<HTMLElement | null>(null);
-		const editOptionRef = ref();
-		const editOptionOutRef = ref();
-		const state = reactive<DicState>({
-			isShowDialog: false,
-			typeData: [], //
-			type: '',
-			types: '',
-			productKey: '',
-			valueType: {
-				type: '',
-				maxLength: '',
-				trueText: '是',
-				trueValue: 'true',
-				falseText: '否',
-				falseValue: 'false',
-			},
-			elementType: {
-				type: '',
-				maxLength: '',
-			},
-			enumdata: [
-				{
-					text: '',
-					value: '',
-				},
-			],
-			jsondata: [],
-			inputsdata: [],
-			outputsdata: [],
-			ruleForm: JSON.parse(JSON.stringify(form)),
-			rules: {
-				name: [{ required: true, message: '功能定义名称不能为空', trigger: 'blur' },
-				{ max: 32, message: '功能定义名称不能超过32个字符', trigger: 'blur' },
-				{ validator: validateNoSpace, message: '功能定义名称不能包含空格', trigger: 'blur' }
-				],
-				key: [{ required: true, message: '功能定义标识不能为空', trigger: 'blur' }],
-				type: [{ required: true, message: '请选择数据类型', trigger: 'blur' }],
-			},
-		});
-
-		// 打开弹窗
-		const openDialog = (row: RuleFormState, productKey: string) => {
-			resetForm();
-			state.ruleForm = row;
-			state.productKey = productKey;
-			state.inputsdata = row.inputs || [];
-			state.outputsdata = row.outputs || [];
-			state.isShowDialog = true;
-
-		};
-		const resetForm = () => {
-			state.ruleForm = JSON.parse(JSON.stringify(form))
-			state.type = '';
-			state.types = '';
-			state.inputsdata = [];
-			state.outputsdata = [];
-			state.elementType = [];
-			state.valueType = {};
-		};
-
-		const seletChange = (val: string) => {
-			state.type = val;
-			state.ruleForm.type = val;
+const emit = defineEmits(['typeList'])
 
-		};
-		const seletChanges = (val: string) => {
-			state.types = val;
-		};
+const formRef = ref<HTMLElement | null>(null)
+const editOptionRef = ref()
+const editOptionOutRef = ref()
+const isShowDialog = ref(false)
+const type = ref('')
+const types = ref('')
+const productKey = ref('')
+// const valueType = ref<any>({
+// 	type: '',
+// 	maxLength: '',
+// 	trueText: '是',
+// 	trueValue: 'true',
+// 	falseText: '否',
+// 	falseValue: 'false',
+// })
+const elementType = ref({
+	type: '',
+	maxLength: '',
+})
+const jsondata = ref<any>([])
+const inputsdata = ref<any>([])
+const outputsdata = ref<any>([])
+const ruleForm = ref(JSON.parse(JSON.stringify(form)))
+const rules = computed(() => ({
+	name: [
+		// 功能定义名称不能为空
+		{ required: true, message: t('message.device.rules.functionName'), trigger: 'blur' },
+		// 功能定义名称不能超过32个字符
+		{ max: 32, message: t('message.device.rules.functionNameMax32'), trigger: 'blur' },
+		// 功能定义名称不能包含空格
+		{ validator: validateNoSpace, message: t('message.device.rules.functionNameValidator'), trigger: 'blur' },
+	],
+	// 功能定义标识不能为空
+	key: [{ required: true, message: t('message.device.rules.functionKey'), trigger: 'blur' }],
+	// 请选择数据类型
+	type: [{ required: true, message: t('message.device.rules.functionType'), trigger: 'blur' }],
+}))
 
-		const addEnum = () => {
-			state.enumdata.push({
-				text: '',
-				value: '',
-			});
-		};
-		const delEnum = (index: number) => {
-			state.enumdata.splice(index, 1);
-		};
+// 打开弹窗
+const openDialog = (row: RuleFormState, productKeyData: string) => {
+	resetForm()
+	ruleForm.value = row
+	productKey.value = productKeyData
+	inputsdata.value = row.inputs || []
+	outputsdata.value = row.outputs || []
+	isShowDialog.value = true
+}
+const resetForm = () => {
+	ruleForm.value = JSON.parse(JSON.stringify(form))
+	type.value = ''
+	types.value = ''
+	inputsdata.value = []
+	outputsdata.value = []
+	elementType.value = {
+		type: '',
+		maxLength: '',
+	}
+}
 
-		const editjson = (index: number, type: string) => {
-			if (type == 'fun') {
-				editOptionRef.value.openDialog(state.inputsdata[index]);
-			} else {
-				editOptionRef.value.openDialog(state.jsondata[index]);
 
-			}
-		}
+const editjson = (index: number, type: string) => {
+	if (type == 'fun') {
+		editOptionRef.value.openDialog(inputsdata.value[index])
+	} else {
+		editOptionRef.value.openDialog(jsondata.value[index])
+	}
+}
 
-		const deljson = (index: number, type: string) => {
-			if (type == 'fun') {
-				state.inputsdata.splice(index, 1);
-			} else {
-				state.jsondata.splice(index, 1);
-			}
-		};
+const deljson = (index: number, type: string) => {
+	if (type == 'fun') {
+		inputsdata.value.splice(index, 1)
+	} else {
+		jsondata.value.splice(index, 1)
+	}
+}
 
-		const deljsonOut = (index: number, type: string) => {
-			if (type == 'fun') {
-				state.outputsdata.splice(index, 1);
-			} else {
-				state.outputsdata.splice(index, 1);
-			}
-		};
+const deljsonOut = (index: number, type: string) => {
+	if (type == 'fun') {
+		outputsdata.value.splice(index, 1)
+	} else {
+		outputsdata.value.splice(index, 1)
+	}
+}
 
-		const editjsonOut = (index: number) => {
-			editOptionOutRef.value.openDialog(state.outputsdata[index]);
-		}
+const editjsonOut = (index: number) => {
+	editOptionOutRef.value.openDialog(outputsdata.value[index])
+}
 
-		const addJson = (type: string) => {
-			editOptionRef.value.openDialog({ productKey: '', id: 0, type_data: type });
-		};
+const addJson = (type: string) => {
+	editOptionRef.value.openDialog({ productKey: '', id: 0, type_data: type })
+}
 
-		const addJsonOut = (type: string) => {
-			editOptionOutRef.value.openDialog({ productKey: '', id: 0, type_data: type });
-		};
+const addJsonOut = (type: string) => {
+	editOptionOutRef.value.openDialog({ productKey: '', id: 0, type_data: type })
+}
 
-		const getOptionData = (data: any, type_data: any) => {
-			if (type_data == 'fun') {
-				state.inputsdata.push(data);
-			} else {
-				state.jsondata.push(data);
-			}
-		};
-		const getOptionDataOut = (data: any, type_data: any) => {
-			if (type_data == 'fun') {
-				state.outputsdata.push(data);
+const getOptionData = (data: any, type_data: any) => {
+	if (type_data == 'fun') {
+		inputsdata.value.push(data)
+	} else {
+		jsondata.value.push(data)
+	}
+}
+const getOptionDataOut = (data: any, type_data: any) => {
+	if (type_data == 'fun') {
+		outputsdata.value.push(data)
+	} else {
+		outputsdata.value.push(data)
+	}
+}
+// 关闭弹窗
+const closeDialog = () => {
+	isShowDialog.value = false
+}
+// 取消
+const onCancel = () => {
+	closeDialog()
+}
+// 新增
+const onSubmit = () => {
+	const formWrap = unref(formRef) as any
+	if (!formWrap) return
+	formWrap.validate((valid: boolean) => {
+		if (valid) {
+			ruleForm.value.inputs = inputsdata.value
+			ruleForm.value.outputs = outputsdata.value
+			if (ruleForm.value.id !== 0) {
+				ruleForm.value.productKey = productKey.value
+				api.model.functionedit(ruleForm.value).then(() => {
+					// 编辑成功
+					ElMessage.success(t('message.tableI18nConfirm.editSuccess'))
+					closeDialog() // 关闭弹窗
+					emit('typeList')
+				})
 			} else {
-				state.outputsdata.push(data);
+				api.model.functionadd(ruleForm.value).then(() => {
+					// 新增成功
+					ElMessage.success(t('message.tableI18nConfirm.addSuccess'))
+					closeDialog() // 关闭弹窗
+					emit('typeList')
+				})
 			}
-		};
-		// 关闭弹窗
-		const closeDialog = () => {
-			state.isShowDialog = false;
-		};
-		// 取消
-		const onCancel = () => {
-			closeDialog();
-		};
-		// 新增
-		const onSubmit = () => {
-			const formWrap = unref(formRef) as any;
-			if (!formWrap) return;
-			formWrap.validate((valid: boolean) => {
-				if (valid) {
-					state.ruleForm.inputs = state.inputsdata;
-					state.ruleForm.outputs = state.outputsdata;
-					if (state.ruleForm.id !== 0) {
-						state.ruleForm.productKey = state.productKey;
-						api.model.functionedit(state.ruleForm).then(() => {
-							ElMessage.success('功能定义类型修改成功');
-							closeDialog(); // 关闭弹窗
-							emit('typeList');
-						});
-					} else {
-						api.model.functionadd(state.ruleForm).then(() => {
-							ElMessage.success('功能定义类型添加成功');
-							closeDialog(); // 关闭弹窗
-							emit('typeList');
-						});
-					}
-				}
-			});
-		};
-
-		return {
-			editOptionRef,
-			editOptionOutRef,
-			getOptionData,
-			getOptionDataOut,
-			openDialog,
-			editjson,
-			editjsonOut,
-			deljson,
-			deljsonOut,
-			addEnum,
-			delEnum,
-			addJson,
-			addJsonOut,
-			seletChange,
-			seletChanges,
-			closeDialog,
-			onCancel,
-			onSubmit,
-			formRef,
-			...toRefs(state),
-		};
-	},
-});
+		}
+	})
+}
+defineExpose({ openDialog })
 </script>
 <style scoped>
 .input-box {
@@ -359,8 +323,6 @@ export default defineComponent({
 	justify-content: space-between;
 }
 
-.jsonoption {}
-
 .jsonoption a {
 	margin: 0px 10px;
 }

+ 54 - 31
src/views/iot/device/product/component/editOption.vue

@@ -1,16 +1,23 @@
 <template>
 	<div class="system-edit-dic-container">
-		<el-dialog :title="(typeof ruleForm.valueType !== 'undefined' ? '修改' : '添加') + '参数'" v-model="isShowDialog" width="769px">
-			<el-form :model="ruleForm" ref="formRef" :rules="rules" label-width="120px">
-				<el-form-item label="参数标识" prop="key">
-					<el-input v-model="ruleForm.key" placeholder="请输入参数标识" />
+		<!-- 编辑参数 / 新增参数 -->
+		<el-dialog :title="typeof ruleForm.valueType !== 'undefined' ? $t('message.device.dialogI18n.editOption') : $t('message.device.dialogI18n.addOption')" v-model="isShowDialog" width="769px">
+			<el-form :model="ruleForm" ref="formRef" :rules="rules" :label-width="currentLocale == 'en' ? '150px' : '120px'">
+				<!-- 参数标识 -->
+				<el-form-item :label="$t('message.device.formI18nLabel.parameterIdentifier')" prop="key">
+					<!-- 请输入参数标识 -->
+					<el-input v-model="ruleForm.key" :placeholder="$t('message.device.formI18nPlaceholder.parameterIdentifier')" />
 				</el-form-item>
-				<el-form-item label="参数名称" prop="name">
-					<el-input v-model="ruleForm.name" placeholder="请输入参数名称" />
+				<!-- 参数名称 -->
+				<el-form-item :label="$t('message.device.formI18nLabel.parameterName')" prop="name">
+					<!-- 请输入参数名称 -->
+					<el-input v-model="ruleForm.name" :placeholder="$t('message.device.formI18nPlaceholder.parameterName')" />
 				</el-form-item>
 
-				<el-form-item label="数据类型" prop="type">
-					<el-select v-model="valueType.type" placeholder="请选择数据类型" @change="seletChange">
+				<!-- 数据类型 -->
+				<el-form-item :label="$t('message.device.formI18nLabel.dataType')" prop="type">
+					<!-- 请选择数据类型 -->
+					<el-select v-model="valueType.type" :placeholder="$t('message.device.formI18nPlaceholder.dataType')" @change="seletChange">
 						<el-option-group v-for="group in typeData" :key="group.label" :label="group.label">
 							<el-option v-for="item in group.options" :key="item.type" :label="item.title" :value="item.type" />
 						</el-option-group>
@@ -19,8 +26,10 @@
 
 				<TypeItem :valueType="valueType" :typeData="typeData"></TypeItem>
 				<div v-if="type == 'array'">
-					<el-form-item label="元素类型" prop="type">
-						<el-select v-model="elementType.type" placeholder="请选择元素类型" @change="seletChanges">
+				<!-- 元素类型 -->
+					<el-form-item :label="$t('message.device.formI18nLabel.elementType')" prop="type">
+						<!-- 请选择元素类型 -->
+						<el-select v-model="elementType.type" :placeholder="$t('message.device.formI18nPlaceholder.elementType')" @change="seletChanges">
 							<el-option-group v-for="group in typeData" :key="group.label" :label="group.label">
 								<el-option v-for="item in group.options" :key="item.type" :label="item.title" :value="item.type" :disabled="['array', 'enum'].includes(item.type)" />
 							</el-option-group>
@@ -28,15 +37,18 @@
 					</el-form-item>
 					<TypeItem :valueType="elementType" :typeData="typeData"></TypeItem>
 				</div>
-
-				<el-form-item label="参数描述	" prop="desc">
-					<el-input v-model="ruleForm.desc" type="textarea" placeholder="请输入参数描述"></el-input>
+				<!-- 参数描述 -->
+				<el-form-item :label="$t('message.device.formI18nLabel.parameterDescription')" prop="desc">
+					<!-- 请输入参数描述 -->
+					<el-input v-model="ruleForm.desc" type="textarea" :placeholder="$t('message.device.formI18nPlaceholder.parameterDescription')"></el-input>
 				</el-form-item>
 			</el-form>
 			<template #footer>
 				<span class="dialog-footer">
-					<el-button @click="onCancel">取 消</el-button>
-					<el-button type="primary" @click="onSubmit">{{ typeof ruleForm.valueType !== 'undefined' ? '修 改' : '添 加' }}</el-button>
+					<!-- 取 消 -->
+					<el-button @click="onCancel">{{ $t('message.tableI18nAction.cancel') }}</el-button>
+					<!-- 编辑 / 新增 -->
+					<el-button type="primary" @click="onSubmit">{{ typeof ruleForm.valueType !== 'undefined' ? $t('message.tableI18nAction.edit') : $t('message.tableI18nAction.add') }}</el-button>
 				</span>
 			</template>
 		</el-dialog>
@@ -44,16 +56,16 @@
 </template>
 
 <script lang="ts">
-import { reactive, toRefs, defineComponent, ref, unref } from 'vue';
+import { reactive, toRefs, defineComponent, ref, unref, computed } from 'vue';
 import api from '/@/api/device';
 import TypeItem from './typeItem.vue';
 import { Plus, Minus, Right } from '@element-plus/icons-vue';
 import { ElMessage } from 'element-plus';
 import { validateNoSpace } from '/@/utils/validator';
+import { useI18n } from 'vue-i18n';
 
 interface stateType {
 	isShowDialog: boolean
-	rules: any
 	ruleForm: any
 	valueType: any
 	typeData: any
@@ -100,7 +112,22 @@ export default defineComponent({
 	components: { Plus, Minus, Right, TypeItem },
 	setup(prop, { emit }) {
 		const formRef = ref<HTMLElement | null>(null);
-
+		const { locale, t } = useI18n();
+		const currentLocale = computed(() => locale.value)
+		const rules = computed(() => ({
+			name: [
+				// 参数名称不能为空
+				{ required: true, message: t('message.device.rules.parameterName'), trigger: 'blur' },
+				// 参数名称不能超过32个字符
+				{ max: 32, message: t('message.device.rules.parameterNameMax32'), trigger: 'blur' },
+				//  参数名称不能包含空格
+				{ validator: validateNoSpace, message: t('message.device.rules.parameterNameValidator'), trigger: 'blur' }
+			],
+			// 参数标识不能为空
+			key: [{ required: true, message: t('message.device.rules.parameterKey'), trigger: 'blur' }],
+			// 请选择是否只读
+			accessMode: [{ required: true, message: t('message.device.rules.accessMode'), trigger: 'blur' }],
+		}));
 		const state = reactive<stateType>({
 			isShowDialog: false,
 			typeData: [], //
@@ -124,16 +151,7 @@ export default defineComponent({
 				status: 1,
 				valueType: {},
 				desc: '',
-			},
-			rules: {
-				name: [
-					{ required: true, message: '参数名称不能为空', trigger: 'blur' },
-					{ max: 32, message: '参数名称不能超过32个字符', trigger: 'blur' },
-					{ validator: validateNoSpace, message: '参数名称不能包含空格', trigger: 'blur' }
-				],
-				key: [{ required: true, message: '参数标识不能为空', trigger: 'blur' }],
-				accessMode: [{ required: true, message: '请选择是否只读', trigger: 'blur' }],
-			},
+			}
 		});
 
 		// 打开弹窗
@@ -144,10 +162,12 @@ export default defineComponent({
 				const datat: any = Object.values(res.dataType);
 				datat.forEach((item: any, index: number) => {
 					if (index == 0) {
-						datat[index]['label'] = '基础类型';
+						// 基础类型
+						datat[index]['label'] = t('message.device.baseType');
 						datat[index]['options'] = item;
 					} else {
-						datat[index]['label'] = '扩展类型';
+						// 基础类型
+						datat[index]['label'] = t('message.device.extensionType');
 						datat[index]['options'] = item;
 					}
 				});
@@ -235,7 +255,8 @@ export default defineComponent({
 						}
 
 						state.ruleForm.valueType = state.valueType;
-						ElMessage.success('参数类型添加成功');
+						// 新增成功
+						ElMessage.success(t('message.tableI18nConfirm.addSuccess'));
 						closeDialog(); // 关闭弹窗
 						emit('typeList', state.ruleForm, state.ruleForm.type_data);
 					}
@@ -244,6 +265,8 @@ export default defineComponent({
 		};
 
 		return {
+			currentLocale,
+			rules,
 			openDialog,
 			addEnum,
 			delEnum,

+ 107 - 66
src/views/iot/device/product/component/editPro.vue

@@ -1,19 +1,26 @@
 <template>
   <div class="system-edit-dic-container">
-    <el-dialog :title="(ruleForm.id !== 0 ? '修改' : '添加') + '产品'" v-model="isShowDialog" width="769px">
-      <el-form :model="ruleForm" ref="formRef" :rules="rules" label-width="100px">
-        <el-form-item label="产品标识" prop="key">
-          <el-input v-model="ruleForm.key" placeholder="请输入产品标识" :disabled="ruleForm.id" />
+    <!-- 编辑产品/新增产品 -->
+    <el-dialog :title="ruleForm.id !== 0 ? $t('message.device.dialogI18n.editPro') : $t('message.device.dialogI18n.addPro')" v-model="isShowDialog" width="769px">
+      <el-form :model="ruleForm" ref="formRef" :rules="rules"  :label-width="currentLocale == 'en' ? '150px' : '120px'">
+        <!-- 产品标识 -->
+        <el-form-item :label="$t('message.device.formI18nLabel.productKey')" prop="key">
+          <!-- 请输入产品标识 -->
+          <el-input v-model="ruleForm.key" :placeholder="$t('message.device.formI18nPlaceholder.productKey')" :disabled="ruleForm.id" />
         </el-form-item>
-        <el-form-item label="产品名称" prop="name">
-          <el-input v-model="ruleForm.name" placeholder="请输入产品名称" />
+        <!-- 产品名称 -->
+        <el-form-item :label="$t('message.device.formI18nLabel.productName')" prop="name">
+          <!-- 请输入产品名称 -->
+          <el-input v-model="ruleForm.name" :placeholder="$t('message.device.formI18nPlaceholder.productName')" />
         </el-form-item>
-        <el-form-item label="产品图片" prop="imageUrl">
+        <!-- 产品图片 -->
+        <el-form-item :label="$t('message.device.formI18nLabel.productImage')" prop="imageUrl">
           <uploadVue :img="imageUrl" @set-img="handleAvatarSuccess"></uploadVue>
         </el-form-item>
-
-        <el-form-item label="产品分类" prop="categoryId">
-          <el-cascader :options="cateData" :props="{ checkStrictly: true, emitPath: false, value: 'id', label: 'name' }" placeholder="请选择分类" class="w" clearable v-model="ruleForm.categoryId">
+        <!-- 产品分类 -->
+        <el-form-item :label="$t('message.device.formI18nLabel.productCategory')" prop="categoryId">
+          <!-- 请选择分类 -->
+          <el-cascader :options="cateData" :props="{ checkStrictly: true, emitPath: false, value: 'id', label: 'name' }" :placeholder="$t('message.device.formI18nPlaceholder.productCategory')" clearable v-model="ruleForm.categoryId">
             <template #default="{ node, data }">
               <span>{{ data.name }}</span>
               <span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
@@ -21,80 +28,100 @@
           </el-cascader>
 
           <!-- 添加产品分类 -->
-          <el-button type="success" @click="onOpenAddCategory()" style="margin-left: 5px">添加产品分类</el-button>
+          <el-button type="success" @click="onOpenAddCategory()" style="margin-left: 5px">{{ $t('message.device.tableI18nAction.addProductCategory') }}</el-button>
         </el-form-item>
-
-        <el-form-item label="消息协议" prop="messageProtocol">
-          <el-select v-model="ruleForm.messageProtocol" placeholder="请选择消息协议">
+        <!-- 消息协议 -->
+        <el-form-item :label="$t('message.device.formI18nLabel.messageProtocol')" prop="messageProtocol">
+          <!-- 请选择消息协议 -->
+          <el-select v-model="ruleForm.messageProtocol" :placeholder="$t('message.device.formI18nPlaceholder.messageProtocol')">
             <el-option v-for="dict in messageData" :key="dict.types" :label="dict.title" :value="dict.name"> </el-option>
             <!-- 增加系统默认的mqtt选项 -->
             <el-option label="Sagoo Mqtt" value="SagooMqtt"> </el-option>
           </el-select>
         </el-form-item>
-
-        <el-form-item label="接入方式" prop="transportProtocol">
-          <el-select v-model="ruleForm.transportProtocol" placeholder="请选择接入方式" @change="transportProtocolChange">
+        <!-- 接入方式 -->
+        <el-form-item :label="$t('message.device.formI18nLabel.transportProtocol')" prop="transportProtocol">
+          <!-- 请选择接入方式 -->
+          <el-select v-model="ruleForm.transportProtocol" :placeholder="$t('message.device.formI18nPlaceholder.transportProtocol')" @change="transportProtocolChange">
             <el-option v-for="dict in network_server_type" :key="dict.value" :label="dict.label" :value="dict.value"> </el-option>
           </el-select>
         </el-form-item>
-        <!-- 1,mqtt协议设备的认证
-	在添加设备的页面,增加MQTT服务协议设备的认证方式的处理。
-	当传输协议选择为:MQTT服务的时候,下面出现 认证方式的下拉列,分别为Basic、AccessToken接入两个下拉选项。
-	Basic方式:
-	选择这个方式的时候:页面出现,用户名及密码输入框。
-	AccessToken接入方式:
-	选择这个方式的时候:页面出现 Aceess Token的输入框
-	2,TCP及其它协议认证
-	这些配合【网络组件】功能中涉及到的设备通讯协议认证的处理。如果涉及到证书的,需要调用【证书管理】功能维护的证书列表。 -->
-        <!-- 设备认证、网络组件服务增加认证方式authType(1=Basic,2=AccessToken,3=证书)
-				涉及接口:产品添加、编辑、扩展信息更新;设备添加、编辑;网络组件服务添加、编辑 -->
+        <!-- 
+          1,mqtt协议设备的认证
+            在添加设备的页面,增加MQTT服务协议设备的认证方式的处理。
+            当传输协议选择为:MQTT服务的时候,下面出现 认证方式的下拉列,分别为Basic、AccessToken接入两个下拉选项。
+            Basic方式:
+            选择这个方式的时候:页面出现,用户名及密码输入框。
+            AccessToken接入方式:
+            选择这个方式的时候:页面出现 Aceess Token的输入框
+          2,TCP及其它协议认证
+          这些配合【网络组件】功能中涉及到的设备通讯协议认证的处理。如果涉及到证书的,需要调用【证书管理】功能维护的证书列表。 
+        -->
+        <!-- 
+          设备认证、网络组件服务增加认证方式authType(1=Basic,2=AccessToken,3=证书)
+          涉及接口:产品添加、编辑、扩展信息更新;设备添加、编辑;网络组件服务添加、编辑 
+        -->
         <!-- 设备认证 -->
         <template v-if="ruleForm.authType === 1 || ruleForm.authType === 2">
-          <el-form-item label="认证方式" prop="">
+          <!-- 认证方式 -->
+          <el-form-item :label="$t('message.device.formI18nLabel.authType')" prop="">
             <el-radio-group v-model="ruleForm.authType">
               <el-radio :label="1">Basic</el-radio>
               <el-radio :label="2">AccessToken</el-radio>
             </el-radio-group>
           </el-form-item>
           <template v-if="ruleForm.authType === 1">
-            <el-form-item label="用户名" prop="authUser">
-              <el-input v-model="ruleForm.authUser" placeholder="请输入用户名" />
+            <!-- 用户名 -->
+            <el-form-item :label="$t('message.device.formI18nLabel.authUser')" prop="authUser">
+              <el-input v-model="ruleForm.authUser" :placeholder="$t('message.device.formI18nPlaceholder.authUser')" />
             </el-form-item>
-            <el-form-item label="密码" prop="authPasswd">
-              <el-input type="password" v-model="ruleForm.authPasswd" placeholder="请输入密码" />
+            <!-- 密码 -->
+            <el-form-item :label="$t('message.device.formI18nLabel.authPasswd')" prop="authPasswd">
+              <el-input type="password" v-model="ruleForm.authPasswd" :placeholder="$t('message.device.formI18nPlaceholder.authPasswd')" />
             </el-form-item>
           </template>
           <template v-else>
-            <el-form-item label="Aceess Token" prop="accessToken">
-              <el-input v-model="ruleForm.accessToken" placeholder="请输入Aceess Token" />
+            <!-- Aceess Token -->
+            <el-form-item :label="$t('message.device.formI18nLabel.accessToken')" prop="accessToken">
+              <!-- 请输入Aceess Token -->
+              <el-input v-model="ruleForm.accessToken" :placeholder="$t('message.device.formI18nPlaceholder.accessToken')" />
             </el-form-item>
           </template>
         </template>
         <template v-else-if="ruleForm.authType === 3">
-          <el-form-item label="认证证书" prop="certificateId">
-            <el-select v-model="ruleForm.certificateId" placeholder="请选择证书">
+          <!-- 认证证书 -->
+          <el-form-item :label="$t('message.device.formI18nLabel.certificate')" prop="certificateId">
+            <!-- 请选择证书 -->
+            <el-select v-model="ruleForm.certificateId" :placeholder="$t('message.device.formI18nPlaceholder.certificateId')">
               <el-option v-for="cert in certList" :key="cert.id" :label="cert.name" :value="cert.id"> </el-option>
             </el-select>
           </el-form-item>
         </template>
-
-        <el-form-item label="设备类型" prop="deviceType">
+        <!-- 设备类型 -->
+        <el-form-item :label="$t('message.device.formI18nLabel.deviceType')" prop="deviceType">
           <el-radio-group v-model="ruleForm.deviceType">
-            <el-radio label="设备">设备</el-radio>
-            <el-radio label="网关">网关</el-radio>
+            <!-- 设备 -->
+            <el-radio label="设备">{{ $t('message.device.formI18nOption.device') }}</el-radio>
+            <!-- 网关 -->
+            <el-radio label="网关">{{ $t('message.device.formI18nOption.gateway') }}</el-radio>
             <!-- <el-radio label="设备">直连设备</el-radio>
             <el-radio label="网关">网关设备</el-radio> -->
-            <el-radio label="子设备">子设备</el-radio>
+            <!-- 子设备 -->
+            <el-radio label="子设备">{{ $t('message.device.formI18nOption.subDevice') }}</el-radio>
           </el-radio-group>
         </el-form-item>
-        <el-form-item label="产品描述	" prop="desc">
-          <el-input v-model="ruleForm.desc" type="textarea" placeholder="请输入产品描述"></el-input>
+        <!-- 产品描述 -->
+        <el-form-item :label="$t('message.device.formI18nLabel.desc')" prop="desc">
+          <!-- 请输入产品描述 -->
+          <el-input v-model="ruleForm.desc" type="textarea" :placeholder="$t('message.device.formI18nPlaceholder.desc')"></el-input>
         </el-form-item>
       </el-form>
       <template #footer>
         <span class="dialog-footer">
-          <el-button @click="onCancel">取 消</el-button>
-          <el-button type="primary" @click="onSubmit" :loading="submitLoading">{{ ruleForm.id !== 0 ? "修 改" : "添 加" }}</el-button>
+          <!-- 取 消 -->
+          <el-button @click="onCancel">{{ $t('message.tableI18nAction.cancel') }}</el-button>
+          <!-- 编辑 / 添加 -->
+          <el-button type="primary" @click="onSubmit" :loading="submitLoading">{{ ruleForm.id ? $t('message.tableI18nAction.edit') : $t('message.tableI18nAction.add') }}</el-button>
         </span>
       </template>
     </el-dialog>
@@ -103,7 +130,7 @@
 </template>
 
 <script lang="ts">
-import { reactive, toRefs, defineComponent, ref, unref, getCurrentInstance } from "vue";
+import { reactive, toRefs, defineComponent, ref, unref, getCurrentInstance, computed } from "vue";
 import api from "/@/api/device";
 import certApi from "/@/api/certificateManagement";
 import uploadVue from "/@/components/upload/index.vue";
@@ -112,6 +139,8 @@ import { validateNoSpace } from "/@/utils/validator";
 import { ElMessage, UploadProps } from "element-plus";
 import getOrigin from "/@/utils/origin";
 import EditCategory from "/@/views/iot/device/category/component/addOrEdit.vue";
+import { useI18n } from 'vue-i18n';
+
 
 interface RuleFormState {
   id: number;
@@ -138,7 +167,6 @@ interface DicState {
   messageData: any[];
   network_protocols: any[];
   tranData: any[];
-  rules: {};
   imageUrl: string;
   singleImg: string;
 }
@@ -174,6 +202,32 @@ export default defineComponent({
     const certList = ref<any[]>([]);
     const submitLoading = ref(false);
     const editCategoryRef = ref();
+    const { locale, t } = useI18n();
+    const currentLocale = computed(() => locale.value);	
+    const rules = computed(() => ({
+        name: [
+          // 产品名称不能为空
+          { required: true, message: t("message.device.rules.productName"), trigger: "change" },
+          // 产品名称不能超过32个字符
+          { max: 32, message: t("message.device.rules.productNameMax32"), trigger: "change" },
+          // 产品名称不能包含空格
+          { validator: validateNoSpace, message: t("message.device.rules.productNameValidator"), trigger: "change" },
+        ],
+        key: [
+          // 产品标识不能为空
+          { required: true, message: t("message.device.rules.productKey"), trigger: "change" },
+          // 产品标识不能包含空格
+          { validator: validateNoSpace, message: t("message.device.rules.productKeyValidator"), trigger: "change" },
+        ],
+        // 消息协议不能为空
+        messageProtocol: [{ required: true, message: t("message.device.rules.messageProtocol"), trigger: "change" }],
+        // 接入方式不能为空
+        transportProtocol: [{ required: true, message: t("message.device.rules.transportProtocol"), trigger: "change" }],
+        // 产品分类不能为空
+        categoryId: [{ required: true, message: t("message.device.rules.categoryId"), trigger: "change" }],
+        // 设备类型不能为空
+        deviceType: [{ required: true, message: t("message.device.rules.deviceType"), trigger: "change" }],
+      }))
 
     const state = reactive<DicState>({
       isShowDialog: false,
@@ -186,22 +240,7 @@ export default defineComponent({
       singleImg: baseURL + "/product/icon/upload",
       ruleForm: {
         ...form,
-      },
-      rules: {
-        name: [
-          { required: true, message: "产品名称不能为空", trigger: "change" },
-          { max: 32, message: "产品名称不能超过32个字符", trigger: "change" },
-          { validator: validateNoSpace, message: "产品名称不能包含空格", trigger: "change" },
-        ],
-        key: [
-          { required: true, message: "产品标识不能为空", trigger: "change" },
-          { validator: validateNoSpace, message: "产品标识不能包含空格", trigger: "change" },
-        ],
-        messageProtocol: [{ required: true, message: "消息协议不能为空", trigger: "change" }],
-        transportProtocol: [{ required: true, message: "接入方式不能为空", trigger: "change" }],
-        categoryId: [{ required: true, message: "产品分类不能为空", trigger: "change" }],
-        deviceType: [{ required: true, message: "设备类型不能为空", trigger: "change" }],
-      },
+      }
     });
 
     const handleAvatarSuccess: UploadProps["onSuccess"] = (response) => {
@@ -282,7 +321,7 @@ export default defineComponent({
             api.product
               .edit(state.ruleForm)
               .then(() => {
-                ElMessage.success("产品修改成功");
+                ElMessage.success(t("message.tableI18nConfirm.editSuccess"));
                 closeDialog(); // 关闭弹窗
                 emit("typeList");
               })
@@ -292,7 +331,7 @@ export default defineComponent({
             api.product
               .add(state.ruleForm)
               .then(() => {
-                ElMessage.success("产品添加成功");
+                ElMessage.success(t("message.tableI18nConfirm.addSuccess"));
                 closeDialog(); // 关闭弹窗
                 emit("typeList");
               })
@@ -313,6 +352,8 @@ export default defineComponent({
     };
 
     return {
+      rules,
+      currentLocale,
       transportProtocolChange,
       submitLoading,
       certList,

+ 145 - 74
src/views/iot/device/product/component/editTab.vue

@@ -1,16 +1,23 @@
 <template>
 	<div class="system-edit-dic-container">
-		<el-dialog :title="(ruleForm.id !== 0 ? '修改' : '添加') + '标签定义'" v-model="isShowDialog" width="769px">
+		<!-- 编辑标签定义/新增标签定义 -->
+		<el-dialog :title="ruleForm.id !== 0 ? $t('message.device.dialogI18n.editTagDefinition') : $t('message.device.dialogI18n.addTagDefinition')" v-model="isShowDialog" width="769px">
 			<el-form :model="ruleForm" ref="formRef" :rules="rules" label-width="120px">
-				<el-form-item label="标签定义标识" prop="key">
-					<el-input v-model="ruleForm.key" placeholder="请输入标签定义标识" :disabled="ruleForm.id !== 0 ? true : false" />
+				<!-- 标签定义标识 -->
+				<el-form-item :label="$t('message.device.formI18nLabel.tagKey')" prop="key">
+					<!-- 请输入标签定义标识 -->
+					<el-input v-model="ruleForm.key" :placeholder="$t('message.device.formI18nPlaceholder.tagKey')" :disabled="ruleForm.id !== 0 ? true : false" />
 				</el-form-item>
-				<el-form-item label="标签定义名称" prop="name">
-					<el-input v-model="ruleForm.name" placeholder="请输入标签定义名称" />
+				<!-- 标签定义名称 -->
+				<el-form-item :label="$t('message.device.formI18nLabel.tagName')" prop="name">
+					<!-- 请输入标签定义名称 -->
+					<el-input v-model="ruleForm.name" :placeholder="$t('message.device.formI18nPlaceholder.tagName')" />
 				</el-form-item>
 
-				<el-form-item label="数据类型" prop="type">
-					<el-select v-model="valueType.type" placeholder="请选择数据类型" @change="seletChange">
+				<!-- 数据类型 -->
+				<el-form-item :label="$t('message.device.formI18nLabel.dataType')" prop="type">
+					<!-- 请选择数据类型 -->
+					<el-select v-model="valueType.type" :placeholder="$t('message.device.formI18nPlaceholder.selectDataType')" @change="seletChange">
 						<el-option-group v-for="group in typeData" :key="group.label" :label="group.label">
 							<el-option v-for="item in group.options" :key="item.type" :label="item.title" :value="item.type" />
 						</el-option-group>
@@ -19,40 +26,56 @@
 
 				<!--根据数据类型输出不同表单-->
 
-				<el-form-item label="精度" prop="decimals" v-if="type == 'float' || type == 'double'">
-					<el-input v-model="valueType.decimals" placeholder="请输入精度" />
+				<!-- 精度 -->
+				<el-form-item :label="$t('message.device.formI18nLabel.precision')" prop="decimals" v-if="type == 'float' || type == 'double'">
+					<!-- 请输入精度 -->
+					<el-input v-model="valueType.decimals" :placeholder="$t('message.device.formI18nPlaceholder.inputPrecision')" />
 				</el-form-item>
 
-				<el-form-item label="单位" prop="unit" v-if="type == 'int' || type == 'long' || type == 'float' || type == 'double'">
-					<el-input v-model="valueType.unit" placeholder="请输入单位" />
+				<!-- 单位 -->
+				<el-form-item :label="$t('message.device.formI18nLabel.unit')" prop="unit" v-if="type == 'int' || type == 'long' || type == 'float' || type == 'double'">
+					<!-- 请输入单位 -->
+					<el-input v-model="valueType.unit" :placeholder="$t('message.device.formI18nPlaceholder.inputUnit')" />
 				</el-form-item>
 
-				<el-form-item label="最大长度" prop="maxLength" v-if="type == 'string'">
-					<el-input v-model="valueType.maxLength" placeholder="请输入最大长度" />
+					<!-- 最大长度 -->
+				<el-form-item :label="$t('message.device.formI18nLabel.maxLength')" prop="maxLength" v-if="type == 'string'">
+					<!-- 请输入最大长度 -->
+					<el-input v-model="valueType.maxLength" :placeholder="$t('message.device.formI18nPlaceholder.inputMaxLength')" />
 				</el-form-item>
 
-				<el-form-item label="时间格式" prop="maxLength" v-if="type == 'date'">
-					<el-input v-model="valueType.maxLength" placeholder="请输入时间格式" />
+				<!-- 时间格式 -->
+				<el-form-item :label="$t('message.device.formI18nLabel.timeFormat')" prop="maxLength" v-if="type == 'date'">
+					<!-- 请输入时间格式 -->
+					<el-input v-model="valueType.maxLength" :placeholder="$t('message.device.formI18nPlaceholder.inputTimeFormat')" />
 				</el-form-item>
 
-				<el-form-item label="布尔值11" prop="trueText" v-if="type == 'boolean'">
+				<!-- 布尔值 -->
+				<el-form-item :label="$t('message.device.formI18nLabel.booleanValue')" prop="trueText" v-if="type == 'boolean'">
 					<div class="input-box flex-row">
-						<el-input v-model="valueType.trueText" placeholder="请输入true时显示的文字" /><span style="margin: 0px 10px">~</span>
-						<el-input v-model="valueType.trueValue" placeholder="请输入布尔值" disabled />
+						<!-- 请输入true时显示的文字 -->
+						<el-input v-model="valueType.trueText" :placeholder="$t('message.device.formI18nPlaceholder.inputTrueText')" /><span style="margin: 0px 10px">~</span>
+						<!-- 请输入布尔值 -->
+						<el-input v-model="valueType.trueValue" :placeholder="$t('message.device.formI18nPlaceholder.inputBooleanValue')" disabled />
 					</div>
 
 					<div class="input-box flex-row">
-						<el-input v-model="valueType.falseText" placeholder="请输入false时显示的文字" /> <span style="margin: 0px 10px">~</span>
-						<el-input v-model="valueType.falseValue" placeholder="请输入布尔值" disabled />
+						<!-- 请输入false时显示的文字 -->
+						<el-input v-model="valueType.falseText" :placeholder="$t('message.device.formI18nPlaceholder.inputFalseText')" /> <span style="margin: 0px 10px">~</span>
+						<!-- 请输入布尔值 -->
+						<el-input v-model="valueType.falseValue" :placeholder="$t('message.device.formI18nPlaceholder.inputBooleanValue')" disabled />
 					</div>
 				</el-form-item>
 
-				<el-form-item label="枚举项" prop="maxLength" v-if="type == 'enum'">
+				<!-- 枚举项 -->	
+				<el-form-item :label="$t('message.device.formI18nLabel.enumValue')" prop="maxLength" v-if="type == 'enum'">
 					<div class="input-box flex-row" v-for="(item, index) in enumdata" :key="index">
-						<el-input v-model="item.text" placeholder="请输入枚举文本" /><span style="margin: 0px 10px"><el-icon>
+						<!-- 请输入枚举文本 -->
+						<el-input v-model="item.text" :placeholder="$t('message.device.formI18nPlaceholder.inputEnumText')" /><span style="margin: 0px 10px"><el-icon>
 								<Right />
 							</el-icon></span>
-						<el-input v-model="item.value" placeholder="请输入枚举值" />
+						<!-- 请输入枚举值 -->
+						<el-input v-model="item.value" :placeholder="$t('message.device.formI18nPlaceholder.inputEnumValue')" />
 						<div class="input-option">
 							<el-icon @click="addEnum" v-if="index == 0">
 								<Plus />
@@ -64,14 +87,17 @@
 					</div>
 				</el-form-item>
 
-				<el-form-item label="JSON对象" prop="maxLength" v-if="type == 'object'">
+				<!-- JSON对象 -->
+				<el-form-item :label="$t('message.device.formI18nLabel.jsonObject')" prop="maxLength" v-if="type == 'object'">
 					<div v-for="(item, index) in jsondata" :key="index" class="jslist">
 						<div class="jsonlist">
-							<div>参数名称:</div>
+							<!-- 参数名称 -->
+							<div>{{$t('message.device.formI18nLabel.jsonObject')}}:</div>
 							<div style="width: 60%">{{ item.name }}</div>
 							<div class="jsonoption">
 								<!-- <el-link type="primary">编辑</el-link> -->
-								<el-link type="primary" @click="deljson(index)">删除</el-link>
+								<!-- 删除 -->
+								<el-link type="primary" @click="deljson(index)">{{ $t('message.tableI18nAction.delete') }}</el-link>
 							</div>
 						</div>
 					</div>
@@ -81,54 +107,73 @@
 							<el-icon>
 								<Plus />
 							</el-icon>
-							<div>添加参数</div>
+							<!-- 添加参数 -->
+							<div>{{ $t('message.device.formI18nButton.addParameter') }}</div>
 						</div>
 					</div>
 				</el-form-item>
 
 				<div v-if="type == 'array'">
-					<el-form-item label="元素类型" prop="types">
-						<el-select v-model="elementType.type" placeholder="请选择元素类型" @change="seletChanges">
+					<!-- 元素类型 -->
+					<el-form-item :label="$t('message.device.formI18nLabel.elementType')" prop="types">
+						<!-- 请选择元素类型 -->
+						<el-select v-model="elementType.type" :placeholder="$t('message.device.formI18nPlaceholder.selectElementType')" @change="seletChanges">
 							<el-option-group v-for="group in typeData" :key="group.label" :label="group.label">
 								<el-option v-for="item in group.options" :key="item.type" :label="item.title" :value="item.type" :disabled="item.type == 'array'" />
 							</el-option-group>
 						</el-select>
 					</el-form-item>
 
-					<el-form-item label="精度" prop="decimals" v-if="types == 'float' || types == 'double'">
-						<el-input v-model="elementType.decimals" placeholder="请输入精度" />
+					<!-- 精度 -->
+					<el-form-item :label="$t('message.device.formI18nLabel.precision')" prop="decimals" v-if="types == 'float' || types == 'double'">
+						<!-- 请输入精度 -->
+						<el-input v-model="elementType.decimals" :placeholder="$t('message.device.formI18nPlaceholder.inputPrecision')" />
 					</el-form-item>
 
-					<el-form-item label="单位" prop="unit" v-if="types == 'int' || types == 'long' || types == 'float' || types == 'double'">
-						<el-input v-model="elementType.unit" placeholder="请输入单位" />
+					<!-- 单位 -->
+					<el-form-item :label="$t('message.device.formI18nLabel.unit')" prop="unit" v-if="types == 'int' || types == 'long' || types == 'float' || types == 'double'">
+						<!-- 请输入单位 -->
+						<el-input v-model="elementType.unit" :placeholder="$t('message.device.formI18nPlaceholder.inputUnit')" />
 					</el-form-item>
 
-					<el-form-item label="最大长度" prop="maxLength" v-if="types == 'string'">
-						<el-input v-model="elementType.maxLength" placeholder="请输入最大长度" />
+					<!-- 最大长度 -->
+					<el-form-item :label="$t('message.device.formI18nLabel.maxLength')" prop="maxLength" v-if="types == 'string'">
+						<!-- 请输入最大长度 -->
+						<el-input v-model="elementType.maxLength" :placeholder="$t('message.device.formI18nPlaceholder.inputMaxLength')" />
 					</el-form-item>
 
-					<el-form-item label="时间格式" prop="maxLength" v-if="types == 'date'">
-						<el-input v-model="elementType.maxLength" placeholder="请输入时间格式" />
+					<!-- 时间格式 -->
+					<el-form-item :label="$t('message.device.formI18nLabel.timeFormat')" prop="maxLength" v-if="types == 'date'">
+						<!-- 请输入时间格式 -->
+						<el-input v-model="elementType.maxLength" :placeholder="$t('message.device.formI18nPlaceholder.inputTimeFormat')" />
 					</el-form-item>
 
-					<el-form-item label="布尔值" prop="maxLength" v-if="types == 'boolean'">
+					<!-- 布尔值 -->
+					<el-form-item :label="$t('message.device.formI18nLabel.booleanValue')" prop="maxLength" v-if="types == 'boolean'">
 						<div class="input-box flex-row">
-							<el-input v-model="elementType.trueText" placeholder="请输入true时显示的文字" /><span style="margin: 0px 10px">~</span>
-							<el-input v-model="elementType.trueValue" placeholder="请输入布尔值" disabled />
+							<!-- 请输入true时显示的文字 -->
+							<el-input v-model="elementType.trueText" :placeholder="$t('message.device.formI18nPlaceholder.inputTrueText')" /><span style="margin: 0px 10px">~</span>
+							<!-- 请输入布尔值 -->
+							<el-input v-model="elementType.trueValue" :placeholder="$t('message.device.formI18nPlaceholder.inputBooleanValue')" disabled />
 						</div>
 
 						<div class="input-box flex-row">
-							<el-input v-model="elementType.falseText" placeholder="请输入false时显示的文字" /> <span style="margin: 0px 10px">~</span>
-							<el-input v-model="elementType.falseValue" placeholder="请输入布尔值" disabled />
+							<!-- 请输入false时显示的文字 -->
+							<el-input v-model="elementType.falseText" :placeholder="$t('message.device.formI18nPlaceholder.inputFalseText')" /> <span style="margin: 0px 10px">~</span>
+							<!-- 请输入布尔值 -->
+							<el-input v-model="elementType.falseValue" :placeholder="$t('message.device.formI18nPlaceholder.inputBooleanValue')" disabled />
 						</div>
 					</el-form-item>
 
-					<el-form-item label="枚举项" prop="maxLength" v-if="types == 'enum'">
+					<!-- 枚举项 -->
+					<el-form-item :label="$t('message.device.formI18nLabel.enumValue')" prop="maxLength" v-if="types == 'enum'">
 						<div class="input-box flex-row" v-for="(item, index) in enumdata" :key="index">
-							<el-input v-model="item.text" placeholder="请输入枚举文本" /><span style="margin: 0px 10px"><el-icon>
+							<!-- 请输入枚举文本 -->
+							<el-input v-model="item.text" :placeholder="$t('message.device.formI18nPlaceholder.inputEnumText')" /><span style="margin: 0px 10px"><el-icon>
 									<Right />
 								</el-icon></span>
-							<el-input v-model="item.value" placeholder="请输入枚举值" />
+								<!-- 请输入枚举文本 -->
+							<el-input v-model="item.value" :placeholder="$t('message.device.formI18nPlaceholder.inputEnumValue')" />
 							<div class="input-option">
 								<el-icon @click="addEnum" v-if="index == 0">
 									<Plus />
@@ -141,14 +186,18 @@
 					</el-form-item>
 				</div>
 
-				<el-form-item label="JSON对象" prop="maxLength" v-if="types == 'object'">
+				<!-- JSON对象 -->
+				<el-form-item :label="$t('message.device.formI18nLabel.jsonObject')" prop="maxLength" v-if="types == 'object'">
 					<div v-for="(item, index) in jsondata" :key="index" class="jslist">
 						<div class="jsonlist">
-							<div>参数名称:</div>
+							<!-- 参数名称 -->
+							<div>{{$t('message.device.formI18nLabel.parameterName')}}:</div>
 							<div style="width: 60%">{{ item.name }}</div>
 							<div class="jsonoption">
-								<el-link type="primary">编辑</el-link>
-								<el-link type="primary">删除</el-link>
+								<!-- 编辑 -->
+								<el-link type="primary">{{ $t('message.tableI18nAction.edit') }}</el-link>
+								<!-- 删除 -->
+								<el-link type="primary">{{ $t('message.tableI18nAction.delete') }}</el-link>
 							</div>
 						</div>
 					</div>
@@ -158,27 +207,36 @@
 							<el-icon>
 								<Plus />
 							</el-icon>
-							<div>添加参数</div>
+							<!-- 添加参数 -->
+							<div>{{ $t('message.device.formI18nButton.addParameter') }}</div>
 						</div>
 					</div>
 				</el-form-item>
 
 				<!--根据数据类型输出不同表单-->
 
-				<el-form-item label="是否只读" prop="accessMode">
+				<!-- 是否只读 -->
+				<el-form-item :label="$t('message.device.formI18nLabel.isReadOnly')" prop="accessMode">
 					<el-radio-group v-model="ruleForm.accessMode">
-						<el-radio :label="1">只读</el-radio>
-						<el-radio :label="0">读写</el-radio>
+						<!-- 只读 -->
+						<el-radio :label="1">{{ $t('message.device.formI18nOption.readonly') }}</el-radio>
+						<!-- 读写 -->
+						<el-radio :label="0">{{ $t('message.device.formI18nOption.readWrite') }}</el-radio>
 					</el-radio-group>
 				</el-form-item>
-				<el-form-item label="标签定义描述	" prop="desc">
-					<el-input v-model="ruleForm.desc" type="textarea" placeholder="请输入标签定义描述"></el-input>
+
+				<!-- 标签定义描述 -->
+				<el-form-item :label="$t('message.device.formI18nLabel.tagDescription')" prop="desc">
+					<!-- 请输入标签定义描述 -->
+					<el-input v-model="ruleForm.desc" type="textarea" :placeholder="$t('message.device.formI18nPlaceholder.tagDescription')"></el-input>
 				</el-form-item>
 			</el-form>
 			<template #footer>
 				<span class="dialog-footer">
-					<el-button @click="onCancel">取 消</el-button>
-					<el-button type="primary" @click="onSubmit">{{ ruleForm.id !== 0 ? '修 改' : '添 加' }}</el-button>
+					<!-- 取消 -->
+					<el-button @click="onCancel">{{ $t('message.tableI18nAction.cancel') }}</el-button>
+					<!-- 新增/编辑 -->
+					<el-button type="primary" @click="onSubmit">{{ ruleForm.id !== 0 ? $t('message.tableI18nAction.edit') : $t('message.tableI18nAction.add') }}</el-button>
 				</span>
 			</template>
 		</el-dialog>
@@ -187,12 +245,12 @@
 </template>
 
 <script lang="ts">
-import { reactive, toRefs, defineComponent, ref, unref } from 'vue';
+import { reactive, toRefs, defineComponent, ref, unref, computed } from 'vue';
 import api from '/@/api/device';
 import { Plus, Minus, Right } from '@element-plus/icons-vue';
 import EditOption from './editOption.vue';
 import { validateNoSpace } from '/@/utils/validator';
-
+import { useI18n } from 'vue-i18n';
 import { ElMessage } from 'element-plus';
 
 interface RuleFormState {
@@ -219,7 +277,7 @@ interface DicState {
 	jsondata: any;
 	typeData: any[];
 	enumdata: any[];
-	rules: {};
+	// rules: {};
 }
 
 const ruleForm = {
@@ -245,6 +303,23 @@ export default defineComponent({
 	setup(prop, { emit }) {
 		const formRef = ref<HTMLElement | null>(null);
 		const editOptionRef = ref();
+		const { t, locale } = useI18n();
+		const rules = computed(() => ({
+			name: [
+				// 标签定义名称不能为空
+				{ required: true, message: t('message.device.rules.tagKeyName'), trigger: 'blur' },
+				// 标签定义名称不能超过32个字符
+				{ max: 32, message: t('message.device.rules.tagKeyMax32'), trigger: 'blur' },
+				// 标签定义名称不能包含空格
+				{ validator: validateNoSpace, message: t('message.device.rules.tagKeyValidator'), trigger: 'blur' }
+			],
+			// 标签定义标识不能为空
+			key: [{ required: true, message: t('message.device.rules.tagKey'), trigger: 'blur' }],
+			// 请选择是否只读
+			accessMode: [{ required: true, message: t('message.device.rules.tagAccessMode'), trigger: 'blur' }],
+			// 请选择数据类型
+			type: [{ required: true, message: t('message.device.rules.tagType'), trigger: 'blur' }],
+		}))
 		const state = reactive<DicState>({
 			isShowDialog: false,
 			typeData: [], //
@@ -273,16 +348,7 @@ export default defineComponent({
 			jsondata: [],
 
 			ruleForm: JSON.parse(JSON.stringify(ruleForm)),
-			rules: {
-				name: [
-					{ required: true, message: '标签定义名称不能为空', trigger: 'blur' },
-					{ max: 32, message: '标签定义名称不能超过32个字符', trigger: 'blur' },
-					{ validator: validateNoSpace, message: '标签定义名称不能包含空格', trigger: 'blur' }
-				],
-				key: [{ required: true, message: '标签定义标识不能为空', trigger: 'blur' }],
-				accessMode: [{ required: true, message: '请选择是否只读', trigger: 'blur' }],
-				type: [{ required: true, message: '请选择数据类型', trigger: 'blur' }],
-			},
+
 		});
 
 		// 打开弹窗
@@ -293,10 +359,12 @@ export default defineComponent({
 				const datat = Object.values(res.dataType) as any[];
 				datat.forEach((item, index) => {
 					if (index == 0) {
-						datat[index]['label'] = '基础类型';
+						// 基础类型
+						datat[index]['label'] = t('message.device.baseType');
 						datat[index]['options'] = item;
 					} else {
-						datat[index]['label'] = '扩展类型';
+						// 扩展类型
+						datat[index]['label'] = t('message.device.extendType');
 						datat[index]['options'] = item;
 					}
 				});
@@ -423,7 +491,8 @@ export default defineComponent({
 						state.ruleForm.productKey = state.productKey;
 
 						api.model.tagedit(state.ruleForm).then(() => {
-							ElMessage.success('标签定义类型修改成功');
+							// 标签定义类型修改成功
+							ElMessage.success(t('message.tableI18nConfirm.editSuccess'));
 							closeDialog(); // 关闭弹窗
 							emit('typeList');
 						});
@@ -456,7 +525,8 @@ export default defineComponent({
 
 						state.ruleForm.valueType = state.valueType;
 						api.model.tagadd(state.ruleForm).then(() => {
-							ElMessage.success('标签定义类型添加成功');
+							// 标签定义类型添加成功
+							ElMessage.success(t('message.tableI18nConfirm.addSuccess'));
 							closeDialog(); // 关闭弹窗
 							emit('typeList');
 						});
@@ -466,6 +536,7 @@ export default defineComponent({
 		};
 
 		return {
+			rules,
 			editOptionRef,
 			getOptionData,
 			openDialog,

+ 42 - 25
src/views/iot/device/product/component/typeItem.vue

@@ -2,49 +2,62 @@
   <div class="type-item">
     <template v-if="['int', 'long', 'float', 'double'].includes(valueType.type)">
       <div class="flex-row" style="margin-bottom: 0;">
-        <el-form-item label="取值范围" prop="min" class="flex1">
-          <el-input v-model="valueType.min" type="number" @input="setNull(valueType, 'min', $event)" placeholder="最小值" />
+        <!-- 取值范围 -->
+        <el-form-item :label="$t('message.device.formI18nLabel.valueRange')" prop="min" class="flex1">
+          <!-- 最小值 -->
+          <el-input v-model="valueType.min" type="number" @input="setNull(valueType, 'min', $event)" :placeholder="$t('message.device.formI18nPlaceholder.valueRangeMin')" />
         </el-form-item>
         <div class="split" style="margin-bottom: 20px;">~</div>
         <el-form-item prop="max" class="flex1" label-width="0">
-          <el-input v-model="valueType.max" type="number" @input="setNull(valueType, 'max', $event)" placeholder="最大值" />
+          <!-- 最大值 -->
+          <el-input v-model="valueType.max" type="number" @input="setNull(valueType, 'max', $event)" :placeholder="$t('message.device.formI18nPlaceholder.valueRangeMax')" />
         </el-form-item>
       </div>
-      <el-form-item label="单位" prop="unit">
-        <el-input v-model="valueType.unit" placeholder="请输入单位" />
+      <!-- 单位 -->
+      <el-form-item :label="$t('message.device.formI18nLabel.unit')" prop="unit">
+        <!-- 请输入单位 -->
+        <el-input v-model="valueType.unit" :placeholder="$t('message.device.formI18nPlaceholder.inputUnit')" />
       </el-form-item>
     </template>
-
-    <el-form-item label="精度" prop="decimals" v-if="['float', 'double'].includes(valueType.type)">
-      <el-input v-model="valueType.decimals" type="number" placeholder="请输入精度" />
+    <!-- 精度 -->
+    <el-form-item :label="$t('message.device.formI18nLabel.precision')" prop="decimals" v-if="['float', 'double'].includes(valueType.type)">
+      <!-- 请输入精度 -->
+      <el-input v-model="valueType.decimals" type="number" :placeholder="$t('message.device.formI18nPlaceholder.inputPrecision')" />
     </el-form-item>
 
-
-    <el-form-item label="最大长度" prop="maxLength" v-if="valueType.type === 'string'">
-      <el-input v-model="valueType.maxLength" type="number" placeholder="请输入最大长度" />
+    <!-- 最大长度 -->
+    <el-form-item :label="$t('message.device.formI18nLabel.maxLength')" prop="maxLength" v-if="valueType.type === 'string'">
+      <!-- 请输入最大长度 -->
+      <el-input v-model="valueType.maxLength" type="number" :placeholder="$t('message.device.formI18nPlaceholder.inputMaxLength')" />
     </el-form-item>
-
-    <el-form-item label="布尔值" v-else-if="valueType.type === 'boolean'">
+    <!-- 布尔值-->
+    <el-form-item :label="$t('message.device.formI18nLabel.booleanValue')" v-else-if="valueType.type === 'boolean'">
       <div class="input-box flex-row">
-        <el-input v-model="valueType.trueText" placeholder="请输入true时显示的文字" /><span style="margin: 0px 10px">~</span>
-        <el-input v-model="valueType.trueValue" placeholder="请输入布尔值" disabled />
+        <!-- 请输入true时显示的文字 -->
+        <el-input v-model="valueType.trueText" :laceholder="$t('message.device.formI18nPlaceholder.inputTrueText')" /><span style="margin: 0px 10px">~</span>
+        <!-- 请输入布尔值 -->
+        <el-input v-model="valueType.trueValue" :placeholder="$t('message.device.formI18nPlaceholder.inputBooleanValue')" disabled />
       </div>
 
       <div class="input-box flex-row">
-        <el-input v-model="valueType.falseText" placeholder="请输入false时显示的文字" /> <span style="margin: 0px 10px">~</span>
-        <el-input v-model="valueType.falseValue" placeholder="请输入布尔值" disabled />
+        <!-- 请输入false时显示的文字 -->
+        <el-input v-model="valueType.falseText" :placeholder="$t('message.device.formI18nPlaceholder.inputFalseText')" /> <span style="margin: 0px 10px">~</span>
+        <!-- 请输入布尔值 -->
+        <el-input v-model="valueType.falseValue" :placeholder="$t('message.device.formI18nPlaceholder.inputBooleanValue')" disabled />
       </div>
     </el-form-item>
-
-    <el-form-item label="枚举项" prop="" v-else-if="valueType.type === 'enum'">
+    <!-- 枚举项 -->
+    <el-form-item :label="$t('message.device.formI18nLabel.enumItems')" prop="" v-else-if="valueType.type === 'enum'">
       <div class="input-box flex-row" v-for="(item, index) in valueType.elements" :key="index">
-        <el-input v-model="item.text" placeholder="请输入枚举文本" />
+        <!-- 请输入枚举文本 -->
+        <el-input v-model="item.text" :placeholder="$t('message.device.formI18nPlaceholder.inputEnumText')" />
         <span style="margin: 0px 10px">
           <el-icon>
             <Right />
           </el-icon>
         </span>
-        <el-input v-model="item.value" placeholder="请输入枚举值" />
+        <!-- 请输入枚举值 -->
+        <el-input v-model="item.value" :placeholder="$t('message.device.formI18nPlaceholder.inputEnumValue')" />
         <div class="input-option">
           <el-icon @click="addEnum" v-if="index == 0">
             <Plus />
@@ -55,12 +68,16 @@
         </div>
       </div>
     </el-form-item>
-    <el-form-item label="对象属性" prop="" v-else-if="valueType.type === 'object'">
+    <!-- 对象属性 -->
+    <el-form-item :label="$t('message.device.formI18nLabel.objectProperty')" prop="" v-else-if="valueType.type === 'object'">
       <div class="w-full" v-for="(item, index) in valueType.properties" :key="index">
         <div class="flex-row">
-          <el-input v-model="item.key" placeholder="属性标识" class="flex1" />
-          <el-input v-model="item.name" placeholder="属性名称" class="flex1" />
-          <el-select v-model="item.valueType.type" placeholder="请选择元素类型" style="width: 140px;">
+          <!-- 属性标识 -->
+          <el-input v-model="item.key" :placeholder="$t('message.device.formI18nPlaceholder.propertyIdentifier1')" class="flex1" />
+          <!-- 属性名称 -->
+          <el-input v-model="item.name" :placeholder="$t('message.device.formI18nPlaceholder.propertyName1')" class="flex1" />
+          <!-- 请选择元素类型 -->
+          <el-select v-model="item.valueType.type" :placeholder="$t('message.device.formI18nPlaceholder.selectElementType')" style="width: 140px;">
             <el-option-group v-for="group in typeData" :key="group.label" :label="group.label">
               <el-option v-for="item in group.options" :key="item.type" :label="item.title" :value="item.type" :disabled="['array', 'object', 'enum', 'date'].includes(item.type)" />
             </el-option-group>

+ 45 - 63
src/views/iot/device/product/detail.vue

@@ -5,40 +5,40 @@
 				<!-- 产品 -->
 				<div class="title">{{ `${$t('message.device.product')}:${detail.name}` }}</div>
 				<!-- <el-tag :type="developer_status == 1 ? 'success' : 'danger'" style="margin:0 20px;">{{ developer_status == 1 ? '已发布' : '未发布' }}</el-tag> -->
-				<el-switch v-auth="'startOrStop'" style="margin:0 20px;" v-model="developer_status" inline-prompt :active-value="1" :inactive-value="0" :active-text="$t('message.device.producDetail.enable')" :inactive-text="$t('message.device.producDetail.disable')" @change="CkOption"></el-switch>
+				<el-switch v-auth="'startOrStop'" style="margin:0 20px;" v-model="developer_status" inline-prompt :active-value="1" :inactive-value="0" :active-text="$t('message.device.productDetail.enable')" :inactive-text="$t('message.device.productDetail.disable')" @change="CkOption"></el-switch>
 			</div>
 		</div>
 
 		<el-tabs v-model="activeName" style="padding: 0 20px;" @tab-click="handleClick">
 			<!-- 产品信息 -->
-			<el-tab-pane :label="$t('message.device.producDetail.productInfo')" name="1">
+			<el-tab-pane :label="$t('message.device.productDetail.productInfo')" name="1">
 				<div class="pro-box">
-					<div class="protitle">{{$t('message.device.producDetail.productInfo')}}</div>
+					<div class="protitle">{{$t('message.device.productDetail.productInfo')}}</div>
 					<!-- 编辑 -->
 					<el-button type="" :icon="Edit" class="buttonedit" v-auth="'edit'" @click="onOpenEditDic(detail)">{{ $t('message.tableI18nAction.edit') }}</el-button>
 				</div>
 
 				<el-descriptions class="margin-top" :column="3" border>
 					<!-- 产品标识 -->
-					<el-descriptions-item :label="$t('message.device.producDetail.productIdentifier')"><copy :text="detail.key"></copy></el-descriptions-item>
+					<el-descriptions-item :label="$t('message.device.productDetail.productIdentifier')"><copy :text="detail.key"></copy></el-descriptions-item>
 					<!-- 产品分类 -->
-					<el-descriptions-item :label="$t('message.device.producDetail.productCategory')">{{ detail.categoryName }}</el-descriptions-item>
+					<el-descriptions-item :label="$t('message.device.productDetail.productCategory')">{{ detail.categoryName }}</el-descriptions-item>
 					<!-- 设备类型 -->
-					<el-descriptions-item :label="$t('message.device.producDetail.deviceType')">{{ detail.deviceType }}</el-descriptions-item>
+					<el-descriptions-item :label="$t('message.device.productDetail.deviceType')">{{ detail.deviceType }}</el-descriptions-item>
 					<!-- 产品图片 -->
-					<el-descriptions-item :label="$t('message.device.producDetail.productImage')">
+					<el-descriptions-item :label="$t('message.device.productDetail.productImage')">
 						<el-image style="width: 80px; height: 80px" :src="detail.icon" :previewSrcList="[detail.icon]" fit="contain">
 							<template #error>
 								<div class="image-slot">
 									<ele-Picture style="width: 30px;" />
 									<!-- 加载失败 -->
-									{{ $t('message.device.producDetail.loadFailed') }}
+									{{ $t('message.device.productDetail.loadFailed') }}
 								</div>
 							</template>
 						</el-image>
 					</el-descriptions-item>
 					<!-- 消息协议 -->
-					<el-descriptions-item :label="$t('message.device.producDetail.messageProtocol')">{{ detail.messageProtocol }}</el-descriptions-item>
+					<el-descriptions-item :label="$t('message.device.productDetail.messageProtocol')">{{ detail.messageProtocol }}</el-descriptions-item>
 					<!-- 接入方式 -->
 					<el-descriptions-item :label="$t('message.device.tableI18nColumn.transportProtocol')">{{ detail.transportProtocol }}</el-descriptions-item>
 					<!-- 描述 -->
@@ -46,12 +46,12 @@
 				</el-descriptions>
 			</el-tab-pane>
 			<!-- 物模型 -->
-			<el-tab-pane :label="$t('message.device.producDetail.thingModel')" name="2">
+			<el-tab-pane :label="$t('message.device.productDetail.thingModel')" name="2">
 				<el-tabs type="border-card" v-model="activetab" @tab-click="wuhandleClick">
 					<!-- 属性定义 -->
-					<el-tab-pane :label="$t('message.device.producDetail.propertyDefinition')" name="attr">
+					<el-tab-pane :label="$t('message.device.productDetail.propertyDefinition')" name="attr">
 						<div class="wu-title">
-							<div class="title">{{$t('message.device.producDetail.propertyDefinition')}}</div>
+							<div class="title">{{$t('message.device.productDetail.propertyDefinition')}}</div>
 							<!-- 新增 -->
 							<div>
 								<el-button size="small" type="primary" v-auth="'edit'" @click="onOpenEditAttr()">{{$t('message.tableI18nAction.add')}}</el-button>
@@ -60,38 +60,38 @@
 
 						<el-table style="width: 100%" :data="tableData.data" v-loading="tableData.loading" v-if="activetab == 'attr'">
 							<!-- 属性标识 -->
-							<el-table-column :label="$t('message.device.producDetail.propertyIdentifier')" align="center" prop="key" />
+							<el-table-column :label="$t('message.device.productDetail.propertyIdentifier')" align="center" prop="key" />
 							<!-- 属性名称 -->
-							<el-table-column :label="$t('message.device.producDetail.propertyName')" prop="name" show-overflow-tooltip />
+							<el-table-column :label="$t('message.device.productDetail.propertyName')" prop="name" show-overflow-tooltip />
 							<!-- 数据类型 -->
-							<el-table-column prop="valueType" :label="$t('message.device.producDetail.dataType')" width="100" align="center">
+							<el-table-column prop="valueType" :label="$t('message.device.productDetail.dataType')" width="100" align="center">
 								<template #default="scope">
 									<span>{{ scope.row.valueType.type }}</span>
 								</template>
 							</el-table-column>
 							<!-- 精度 -->
-							<el-table-column prop="decimals" :label="$t('message.device.producDetail.precision')" :width="currentLang == 'en' ? '100' : '60'" align="center">
+							<el-table-column prop="decimals" :label="$t('message.device.productDetail.precision')" :width="currentLang == 'en' ? '100' : '60'" align="center">
 								<template #default="scope">
 									<span>{{ scope.row.valueType.decimals }}</span>
 								</template>
 							</el-table-column>
 							<!-- 单位 -->
-							<el-table-column prop="unit" :label="$t('message.device.producDetail.unit')" width="60" align="center">
+							<el-table-column prop="unit" :label="$t('message.device.productDetail.unit')" width="60" align="center">
 								<template #default="scope">
 									<span>{{ scope.row.valueType.unit }}</span>
 								</template>
 							</el-table-column>
 							<!-- 是否只读 -->
-							<el-table-column prop="accessMode" :label="$t('message.device.producDetail.readOnly')" width="120" align="center">
+							<el-table-column prop="accessMode" :label="$t('message.device.productDetail.readOnly')" width="120" align="center">
 								<template #default="scope">
 									<!-- 只读 -->
-									<el-tag type="info" size="small" v-if="scope.row.accessMode">{{ $t('message.device.producDetail.readonly') }}</el-tag>
+									<el-tag type="info" size="small" v-if="scope.row.accessMode">{{ $t('message.device.productDetail.readonly') }}</el-tag>
 									<!-- 读写 -->
-									<el-tag type="success" size="small" v-else>{{ $t('message.device.producDetail.readWrite') }}</el-tag>
+									<el-tag type="success" size="small" v-else>{{ $t('message.device.productDetail.readWrite') }}</el-tag>
 								</template>
 							</el-table-column>
 							<!-- 说明 -->
-							<el-table-column :label="$t('message.device.producDetail.remark')" prop="desc" show-overflow-tooltip />
+							<el-table-column :label="$t('message.device.productDetail.remark')" prop="desc" show-overflow-tooltip />
 							<!-- 操作 -->
 							<el-table-column :label="$t('message.tableI18nColumn.operation')" width="120" align="center" fixed="right">
 								<template #default="scope">
@@ -102,9 +102,9 @@
 						</el-table>
 					</el-tab-pane>
 					<!-- 功能定义 -->
-					<el-tab-pane :label="$t('message.device.producDetail.functionDefinition')" name="fun">
+					<el-tab-pane :label="$t('message.device.productDetail.functionDefinition')" name="fun">
 						<div class="wu-title">
-							<div class="title">{{$t('message.device.producDetail.functionDefinition')}}</div>
+							<div class="title">{{$t('message.device.productDetail.functionDefinition')}}</div>
 							<!-- 新增 -->
 							<div>
 								<el-button size="small" type="primary" v-auth="'add'" @click="onOpenEditFun()">{{$t('message.tableI18nAction.add')}}</el-button>
@@ -112,8 +112,8 @@
 						</div>
 
 						<el-table style="width: 100%" :data="tableData.data" v-if="activetab == 'fun'">
-							<el-table-column :label="$t('message.device.producDetail.functionIdentifier')" align="center" prop="key" />
-							<el-table-column :label="$t('message.device.producDetail.name')" prop="name" show-overflow-tooltip />
+							<el-table-column :label="$t('message.device.productDetail.functionIdentifier')" align="center" prop="key" />
+							<el-table-column :label="$t('message.device.productDetail.name')" prop="name" show-overflow-tooltip />
 							<!-- 描述 -->
 							<el-table-column :label="$t('message.tableI18nColumn.des')" prop="desc" show-overflow-tooltip />
 							<!-- 操作 -->
@@ -128,9 +128,9 @@
 						</el-table>
 					</el-tab-pane>
 					<!-- 事件定义 -->
-					<el-tab-pane :label="$t('message.device.producDetail.eventDefinition')" name="event">
+					<el-tab-pane :label="$t('message.device.productDetail.eventDefinition')" name="event">
 						<div class="wu-title">
-							<div class="title">{{$t('message.device.producDetail.eventDefinition')}}</div>
+							<div class="title">{{$t('message.device.productDetail.eventDefinition')}}</div>
 							<div>
 								<el-button size="small" type="primary" v-auth="'add'" @click="onOpenEditEvent()">{{$t('message.tableI18nAction.add')}}</el-button>
 							</div>
@@ -138,18 +138,18 @@
 
 						<el-table style="width: 100%" :data="tableData.data" v-if="activetab == 'event'">
 							<!-- 事件标识 -->
-							<el-table-column :label="$t('message.device.producDetail.eventIdentifier')" align="center" prop="key" />
+							<el-table-column :label="$t('message.device.productDetail.eventIdentifier')" align="center" prop="key" />
 							<!-- 事件名称 -->
-							<el-table-column :label="$t('message.device.producDetail.name')" prop="name" show-overflow-tooltip />
+							<el-table-column :label="$t('message.device.productDetail.name')" prop="name" show-overflow-tooltip />
 							<!-- 事件级别 -->
-							<el-table-column prop="level" :label="$t('message.device.producDetail.eventLevel')" width="120" align="center">
+							<el-table-column prop="level" :label="$t('message.device.productDetail.eventLevel')" width="120" align="center">
 								<template #default="scope">
 									<!-- 普通 -->
-									<el-tag size="small" v-if="scope.row.level == 0">{{ $t('message.device.producDetail.normal') }}</el-tag>
+									<el-tag size="small" v-if="scope.row.level == 0">{{ $t('message.device.productDetail.normal') }}</el-tag>
 									<!-- 警告 -->
-									<el-tag type="warning" size="small" v-if="scope.row.level == 1">{{ $t('message.device.producDetail.warning') }}</el-tag>
+									<el-tag type="warning" size="small" v-if="scope.row.level == 1">{{ $t('message.device.productDetail.warning') }}</el-tag>
 									<!-- 紧急 -->
-									<el-tag type="danger" size="small" v-if="scope.row.level == 2">{{ $t('message.device.producDetail.urgent') }}</el-tag>
+									<el-tag type="danger" size="small" v-if="scope.row.level == 2">{{ $t('message.device.productDetail.urgent') }}</el-tag>
 								</template>
 							</el-table-column>
 							<!-- 描述 -->
@@ -166,10 +166,10 @@
 						</el-table>
 					</el-tab-pane>
 					<!-- 标签定义 -->
-					<el-tab-pane :label="$t('message.device.producDetail.tagDefinition')" name="tab">
+					<el-tab-pane :label="$t('message.device.productDetail.tagDefinition')" name="tab">
 						<div class="wu-title">
 							<!-- 标签定义 -->
-							<div class="title">{{ $t('message.device.producDetail.tagDefinition') }}</div>
+							<div class="title">{{ $t('message.device.productDetail.tagDefinition') }}</div>
 							<!-- 添加 -->
 							<div>
 								<el-button size="small" type="primary" v-auth="'add'" @click="onOpenEditTab()">{{ $t('message.tableI18nAction.add') }}</el-button>
@@ -178,22 +178,22 @@
 
 						<el-table style="width: 100%" :data="tableData.data" v-if="activetab == 'tab'">
 							<!-- 标签标识 -->
-							<el-table-column :label="$t('message.device.producDetail.propertyIdentifier')" align="center" prop="key" />
+							<el-table-column :label="$t('message.device.productDetail.propertyIdentifier')" align="center" prop="key" />
 							<!-- 属性名称 -->
-							<el-table-column :label="$t('message.device.producDetail.propertyName')" prop="name" show-overflow-tooltip />
+							<el-table-column :label="$t('message.device.productDetail.propertyName')" prop="name" show-overflow-tooltip />
 							<!-- 数据类型 -->
-							<el-table-column prop="valueType" :label="$t('message.device.producDetail.dataType')" width="120" align="center">
+							<el-table-column prop="valueType" :label="$t('message.device.productDetail.dataType')" width="120" align="center">
 								<template #default="scope">
 									<span>{{ scope.row.valueType.type }}</span>
 								</template>
 							</el-table-column>
 							<!-- 是否只读 -->
-							<el-table-column prop="accessMode" :label="$t('message.device.producDetail.readOnly')" width="120" align="center">
+							<el-table-column prop="accessMode" :label="$t('message.device.productDetail.readOnly')" width="120" align="center">
 								<template #default="scope">
 									<!-- 只读 -->
-									<el-tag type="info" size="small" v-if="scope.row.accessMode">{{ $t('message.device.producDetail.readonly') }}</el-tag>
+									<el-tag type="info" size="small" v-if="scope.row.accessMode">{{ $t('message.device.productDetail.readonly') }}</el-tag>
 									<!-- 读写 -->
-									<el-tag type="success" size="small" v-else>{{ $t('message.device.producDetail.readWrite') }}</el-tag>
+									<el-tag type="success" size="small" v-else>{{ $t('message.device.productDetail.readWrite') }}</el-tag>
 								</template>
 							</el-table-column>
 							<!-- 描述 -->
@@ -216,7 +216,7 @@
 							<!-- 导入物模型 -->
 							<el-button size="small">
 								<el-icon> <ele-Upload /> </el-icon>
-								{{ $t('message.device.producDetail.importModel') }}
+								{{ $t('message.device.productDetail.importModel') }}
 							</el-button>
 						</el-upload>
 						<!-- 导出物模型 -->
@@ -224,18 +224,18 @@
 							<el-icon>
 								<ele-Download />
 							</el-icon>
-							{{ $t('message.device.producDetail.exportModel') }}
+							{{ $t('message.device.productDetail.exportModel') }}
 						</el-button>
 					</div>
 				</div>
 				<pagination v-show="tableData.total > 0" :total="tableData.total" v-model:page="tableData.param.pageNum" v-model:limit="tableData.param.pageSize" @pagination="getList()" />
 			</el-tab-pane>
 			<!-- 设备接入 -->
-			<el-tab-pane :label="$t('message.device.producDetail.deviceAccess')" name="3">
+			<el-tab-pane :label="$t('message.device.productDetail.deviceAccess')" name="3">
 				<deviceIn></deviceIn>
 			</el-tab-pane>
 			<!-- 数据解析 -->
-			<el-tab-pane :label="$t('message.device.producDetail.dataParsing')" name="4" lazy>
+			<el-tab-pane :label="$t('message.device.productDetail.dataParsing')" name="4" lazy>
 				<dataParse v-if="activeName === '4'" :script="detail.scriptInfo" @updateScript="updateScript">
 				</dataParse>
 			</el-tab-pane>
@@ -324,24 +324,6 @@ const currentLang = computed(() => locale.value);
 				dateRange: [],
 			},
 		});
-		// const state = reactive<TableDataState>({
-		// 	activeName: '1', // 分类数据
-		// 	activetab: 'attr', // 分类数据
-		// 	detail: {},
-		// 	developer_status: 0,
-		// 	tableData: {
-		// 		data: [],
-		// 		total: 0,
-		// 		loading: false,
-		// 		param: {
-		// 			pageNum: 1,
-		// 			productKey: route.params?.id,
-		// 			pageSize: 20,
-		// 			status: '',
-		// 			dateRange: [],
-		// 		},
-		// 	},
-		// });
 
 		onMounted(() => {
 			productDetail()

+ 2 - 2
src/views/iot/projects/filter/attrEdit.vue

@@ -11,7 +11,7 @@
         <el-input v-model.trim="formData.unit" placeholder="输入属性名称" />
       </el-form-item>
       <el-form-item label="" prop="">
-        <el-button @click="cancle">取消</el-button>
+        <el-button @click="cancel">取消</el-button>
         <el-button type="primary" @click="onSubmit">确定</el-button>
       </el-form-item>
     </el-form>
@@ -78,7 +78,7 @@ const open = async (code: string, row?: any) => {
   }
 };
 
-function cancle() {
+function cancel() {
   showDialog.value = false;
 }
 

+ 2 - 2
src/views/iot/projects/filter/bindDeviceForm.vue

@@ -10,7 +10,7 @@
       <pagination v-if="params.total" :total="params.total" v-model:page="params.pageNum" v-model:limit="params.pageSize" @pagination="getList()" />
     </div>
     <div style="float: right">
-      <el-button @click="cancle">取消</el-button>
+      <el-button @click="cancel">取消</el-button>
       <el-button type="primary" @click="onSubmit">绑定设备</el-button>
     </div>
   </el-dialog>
@@ -60,7 +60,7 @@ const open = async (templateseCode: string) => {
   getList();
 };
 
-function cancle() {
+function cancel() {
   showDialog.value = false;
 }
 

+ 2 - 2
src/views/iot/projects/filter/edit-dialog.vue

@@ -1,6 +1,6 @@
 <template>
   <el-dialog class="api-edit" v-model="showDialog" :title="`${formData?.id ? '编辑模板' : '新增模板'}`" width="500px" :close-on-click-modal="false" :close-on-press-escape="false">
-    <EditVue ref="editRef" v-if="showDialog" @getList="getList" @cancle="cancle"></EditVue>
+    <EditVue ref="editRef" v-if="showDialog" @getList="getList" @cancel="cancel"></EditVue>
   </el-dialog>
 </template>
 
@@ -27,7 +27,7 @@ function getList() {
   showDialog.value = false;
 }
 
-function cancle() {
+function cancel() {
   showDialog.value = false;
 }
 

+ 4 - 4
src/views/iot/projects/filter/edit.vue

@@ -4,7 +4,7 @@
       <el-input v-model.trim="formData.name" placeholder="输入模板名称" />
     </el-form-item>
     <el-form-item label="" prop="">
-      <el-button @click="cancle">取消</el-button>
+      <el-button @click="cancel">取消</el-button>
       <el-button type="primary" @click="onSubmit">确定</el-button>
     </el-form-item>
   </el-form>
@@ -16,7 +16,7 @@ import api from '/@/api/projects';
 import { ruleRequired } from '/@/utils/validator';
 import { ElMessage } from 'element-plus';
 
-const emit = defineEmits(['getList', 'cancle']);
+const emit = defineEmits(['getList', 'cancel']);
 
 const showDialog = ref(false);
 const formRef = ref();
@@ -52,8 +52,8 @@ const resetForm = async () => {
   formRef.value && formRef.value.resetFields();
 };
 
-const cancle = () => {
-  emit('cancle');
+const cancel = () => {
+  emit('cancel');
 };
 
 const open = async (row?: any) => {

+ 2 - 2
src/views/iot/projects/list/edit-dialog.vue

@@ -1,6 +1,6 @@
 <template>
   <el-dialog class="api-edit" v-model="showDialog" :title="`${formData?.id ? '编辑项目' : '新增项目'}`" width="600px" :close-on-click-modal="false" :close-on-press-escape="false">
-    <EditVue ref="editRef" v-if="showDialog" @getList="getList" @cancle="cancle"></EditVue>
+    <EditVue ref="editRef" v-if="showDialog" @getList="getList" @cancel="cancel"></EditVue>
   </el-dialog>
 </template>
 
@@ -27,7 +27,7 @@ function getList() {
   showDialog.value = false;
 }
 
-function cancle() {
+function cancel() {
   showDialog.value = false;
 }
 

+ 4 - 4
src/views/iot/projects/list/edit.vue

@@ -23,7 +23,7 @@
       <el-input v-model.trim="formData.repairMobile" placeholder="输入维修电话" />
     </el-form-item>
     <el-form-item label="" prop="">
-      <el-button @click="cancle">取消</el-button>
+      <el-button @click="cancel">取消</el-button>
       <el-button type="primary" @click="onSubmit">确定</el-button>
     </el-form-item>
   </el-form>
@@ -36,7 +36,7 @@ import { ruleRequired } from '/@/utils/validator';
 import { ElMessage } from 'element-plus';
 import data from 'province-city-china/dist/level.json'
 
-const emit = defineEmits(['getList', 'cancle']);
+const emit = defineEmits(['getList', 'cancel']);
 
 const showDialog = ref(false);
 const formRef = ref();
@@ -110,8 +110,8 @@ const resetForm = async () => {
   formRef.value && formRef.value.resetFields();
 };
 
-const cancle = () => {
-  emit('cancle');
+const cancel = () => {
+  emit('cancel');
 };
 
 const open = async (row?: any) => {

+ 2 - 2
src/views/modules/iotCard/platformManage/addOrEditItem.vue

@@ -46,7 +46,7 @@
 
 <script lang="ts" setup>
 import api from '/@/api/modules/iotCard';
-import { ref, unref } from 'vue';
+import { ref, unref, computed } from 'vue';
 import { ElMessage } from 'element-plus';
 import { useI18n } from 'vue-i18n';
 
@@ -73,7 +73,7 @@ const ruleForm = ref({
   ...baseForm
 })
 
-const rules = ref({
+const rules = computed(() => ({
   types: [{ required: true, message: t('message.iotCard.platformManage.addOrEdit.validation.platformType'), trigger: 'change' }],
   name: [{ required: true, message: t('message.iotCard.platformManage.addOrEdit.validation.name'), trigger: 'change' }],
   userId: [{ required: true, message: t('message.iotCard.platformManage.addOrEdit.validation.userId'), trigger: 'change' }],