ソースを参照

feat: 设备管理-设备-详情L:支持多语言

vera_min 1 ヶ月 前
コミット
17c0ffc4f7

+ 105 - 2
src/i18n/pages/iotmanagerI18n/en.ts

@@ -105,7 +105,103 @@ export default {
 			deviceAccess: "Device Access",
 			dataParsing: "Data Parsing",
 			operationSuccess: "Operate Successfully",
-			modelImportSuccess: "Model Import Successfully"
+			modelImportSuccess: "Model Import Successfully",
+			dataRecord: "Data Record",
+			time: "Time",
+			propertyValue: "Property Value"
+		},
+		deviceFunctionModule: {
+			emptyFunctionList: "No function list available, please add in the function definition of the thing model first",
+			parameterName: "Parameter Name",
+			inputType: "Input Type",
+			value: "Value",
+			executeResult: "Execution Result:",
+			execute: "Execute",
+			clear: "Clear",
+			tip1: "Remove outer single quotes from JSON.stringify(arr) result",
+			tip2: "Please enter",
+			tip3: "Please enter correct JSON array string format",
+			yes: "Yes",
+			no: "No",
+			enterFullParameter: "Please enter complete parameters"
+		},
+		logManagementModule: {
+			logType: "Log Type",
+			createdTime: "Created Time",
+			startDate: "Start Date",
+			endDate: "End Date",
+			search: "Search",
+			reset: "Reset",
+			type: "Type",
+			time: "Time",
+			content: "Content",
+			action: "Action",
+			view: "View",
+			viewContent: "Log Data Content",
+			close: "Close"
+		},
+		topicListModule: {
+			tips: "SagooMqtt protocol, related topics are as follows:",
+			description: "Description",
+			type: "Type",
+			topicClass: "Topic Class",
+			topic1: "Gateway batch upload events and properties (initiated by gateway)",
+			topic2: "Device reports properties (initiated by device)",
+			topic3: "Device reports events (initiated by device)",
+			request: "Request",
+			response: "Response"
+		},
+		subDeviceModule: {
+			subDevice: "Sub-device",
+			subDeviceList: "Sub-device List",
+			batchBinding: "Batch Binding",
+			batchUnbinding: "Batch Unbinding",
+			identifier: "Identifier",
+			deviceName: "Device Name",
+			productName: "Product Name",
+			status: "Status",
+			online: "Online",
+			offline: "Offline",
+			disabled: "Disabled",
+			activationTime: "Activation Time",
+			remark: "Remark",
+			action: "Action",
+			delete: "Delete",
+			detail: "Detail",
+			subDeviceDetail: "Sub-device Detail",
+			batchBindSubDevice: "Batch Bind Sub-device",
+			productKey: "Product Key",
+			selectProductKey: "Please select product key"
+		},
+		runStatusModule: {
+			trend: "Trend Chart",
+			history: "Historical Data",
+			recentHalfHour: "Last Half Hour",
+			recentHour: "Last 1 Hour",
+			recent12Hour: "Last 12 Hours",
+			to: "To",
+			startDate: "Start Date",
+			endDate: "End Date",
+			refresh: "Refresh",
+			export: "Export",
+			time: "Time",
+			propertyValue: "Property Value",
+			dataUnit: "Data Unit"
+		},
+		deviceThingModel: {
+			setAttr: "Set Attribute",
+			propertyKey: "Property Key",
+			propertyName: "Property Name",
+			dataType: "Data Type",
+			propertyValue: "Property Value",
+			propertyKeyPlaceholder: "Please enter property key",
+			propertyNamePlaceholder: "Please enter property name",
+			dataTypePlaceholder: "Please select data type",
+			propertyValuePlaceholder: "Please enter property value",
+			cancel: "Cancel",
+			set: "Set",
+			propertyValueError: "Please enter property value first!",
+			operationSuccess: "Operate successfully"
 		},
 		dialogI18n: {
 			addPro: "Add Product",
@@ -363,7 +459,14 @@ export default {
 			confirmDelete: "This operation will permanently delete device: '{name}', continue?",
 			deleteSuccessfully: "Deleted successfully",
 			deleteConfirm: "You are sure to delete the selected data?",
-			operationSuccessfully: "Operation successful"
+			operationSuccessfully: "Operate successfully",
+			batchUnbind: "Confirm batch unbinding?",
+			batchUnbindConfirm: "Please select data for batch unbinding.",
+			batchUnbindSuccessfully: "Unbinding successful",
+			deleteSubDevice: "This operation will permanently delete the sub-device: '{name}', continue?",
+			deleteSubDeviceSuccessfully: "Delete successful",
+			deleteMessage: "This operation will permanently delete the data, continue?",
+			selectMessage: "Please select data to delete."
 		}
 	},
 	// 级联管理

+ 105 - 2
src/i18n/pages/iotmanagerI18n/zh-cn.ts

@@ -105,7 +105,103 @@ export default {
 			deviceAccess: "设备接入",
 			dataParsing: "数据解析",
 			operationSuccess: "操作成功",
-			modelImportSuccess: "物模型导入成功"
+			modelImportSuccess: "物模型导入成功",
+			dataRecord: "数据记录",
+			time: "时间",
+			propertyValue: "属性值"
+		},
+		deviceFunctionModule: {
+			emptyFunctionList: "暂无功能列表,请先在物模型的功能定义中添加",
+			parameterName: "参数名称",
+			inputType: "输入类型",
+			value: "值",
+			executeResult: "执行结果:",
+			execute: "执行",
+			clear: "清空",
+			tip1: "JSON.stringify(arr)结果去掉外层单引号",
+			tip2: "请输入",
+			tip3: "请输入正确的JSON数组字符串格式",
+			yes: "是",
+			no: "否",
+			enterFullParameter: "请输入完整参数"
+		},
+		logManagementModule: {
+			logType: "日志类型",
+			createdTime: "创建时间",
+			startDate: "开始日期",
+			endDate: "结束日期",
+			search: "查询",
+			reset: "重置",
+			type: "类型",
+			time: "时间",
+			content: "内容",
+			action: "操作",
+			view: "查看",
+			viewContent: "日志数据内容",
+			close: "关闭"
+		},
+		topicListModule: {
+			tips: "SagooMqtt协议 ,涉及的topic如下:",
+			description: "描述",
+			type: "类型",
+			topicClass: "Topic类",
+			topic1: "网关批量上传事件和属性(网关发起)",
+			topic2: "设备上报属性(设备端发起)",
+			topic3: "设备上报事件(设备端发起)",
+			request: "请求",
+			response: "响应"
+		},
+		subDeviceModule: {
+			subDevice: "子设备",
+			subDeviceList: "子设备列表",
+			batchBinding: "批量绑定",
+			batchUnbinding: "批量解绑",
+			identifier: "标识",
+			deviceName: "设备名称",
+			productName: "产品名称",
+			status: "状态",
+			online: "在线",
+			offline: "离线",
+			disabled: "未启用",
+			activationTime: "激活时间",
+			remark: "说明",
+			action: "操作",
+			delete: "删除",
+			detail: "详情",
+			subDeviceDetail: "子设备详情",
+			batchBindSubDevice: "批量绑定子设备",
+			productKey: "所属产品",
+			selectProductKey: "请选择所属产品"
+		},
+		runStatusModule: {
+			trend: "趋势图",
+			history: "历史数据",
+			recentHalfHour: "最近半小时",
+			recentHour: "最近1小时",
+			recent12Hour: "最近12小时",
+			to: "至",
+			startDate: "开始日期",
+			endDate: "结束日期",
+			refresh: "刷新",
+			export: "导出",
+			time: "时间",
+			propertyValue: "属性值",
+			dataUnit: "数据单位"
+		},
+		deviceThingModel: {
+			setAttr: "设置属性",
+			propertyKey: "属性标识",
+			propertyName: "属性名称",
+			dataType: "数据类型",
+			propertyValue: "属性值",
+			propertyKeyPlaceholder: "请输入属性标识",
+			propertyNamePlaceholder: "请输入属性名称",
+			dataTypePlaceholder: "请选择数据类型",
+			propertyValuePlaceholder: "请输入属性值",
+			cancel: "取 消",
+			set: "设 置",
+			propertyValueError: "请先输入属性值!",
+			operationSuccess: "操作成功"
 		},
 		dialogI18n: {
 			addPro: "新增产品",
@@ -363,7 +459,14 @@ export default {
 			confirmDelete: "此操作将永久删除设备:'{name}',是否继续?",
 			deleteSuccessfully: "删除成功",
 			deleteConfirm: "你确定要删除所选数据?",
-			operationSuccessfully: "操作成功"
+			operationSuccessfully: "操作成功",
+			batchUnbind: "是否进行批量解绑?",
+			batchUnbindConfirm: "请选择要批量解绑的数据。",
+			batchUnbindSuccessfully: "解绑成功",
+			deleteSubDevice: "此操作将永久删除该子设备:'{name}', 是否继续?",
+			deleteSubDeviceSuccessfully: "删除成功",
+			deleteMessage: "此操作将永久删除该数据,是否继续?",
+			selectMessage: "请选择要删除的数据。",
 		}
 	},
 	// 级联管理

+ 105 - 2
src/i18n/pages/iotmanagerI18n/zh-tw.ts

@@ -105,7 +105,103 @@ export default {
 			deviceAccess: "設備接入",
 			dataParsing: "資料解析",
 			operationSuccess: "操作成功",
-			modelImportSuccess: "物模型導入成功"
+			modelImportSuccess: "物模型導入成功",
+			dataRecord: "數據記錄",
+			time: "時間",
+			propertyValue: "屬性值"
+		},
+		deviceFunctionModule: {
+			emptyFunctionList: "暂无功能列表,请先在物模型的功能定义中添加",
+			parameterName: "参数名称",
+			inputType: "输入类型",
+			value: "值",
+			executeResult: "执行结果:",
+			execute: "执行",
+			clear: "清空",
+			tip1: "JSON.stringify(arr)结果去掉外层单引号",
+			tip2: "请输入",
+			tip3: "请输入正确的JSON数组字符串格式",
+			yes: "是",
+			no: "否",
+			enterFullParameter: "请输入完整参数"
+		},
+		logManagementModule: {
+			logType: "日誌類型",
+			createdTime: "創建時間",
+			startDate: "開始日期",
+			endDate: "結束日期",
+			search: "查詢",
+			reset: "重置",
+			type: "類型",
+			time: "時間",
+			content: "內容",
+			action: "操作",
+			view: "查看",
+			viewContent: "日誌數據內容",
+			close: "關閉"
+		},
+		topicListModule: {
+			tips: "SagooMqtt協議 ,涉及的topic如下:",
+			description: "描述",
+			type: "類型",
+			topicClass: "Topic類",
+			topic1: "網關批量上傳事件和屬性(網關發起)",
+			topic2: "設備上報屬性(設備端發起)",
+			topic3: "設備上報事件(設備端發起)",
+			request: "請求",
+			response: "響應"
+		},
+		subDeviceModule: {
+			subDevice: "子設備",
+			subDeviceList: "子設備列表",
+			batchBinding: "批量綁定",
+			batchUnbinding: "批量解綁",
+			identifier: "標識",
+			deviceName: "設備名稱",
+			productName: "產品名稱",
+			status: "狀態",
+			online: "在線",
+			offline: "離線",
+			disabled: "未啟用",
+			activationTime: "激活時間",
+			remark: "說明",
+			action: "操作",
+			delete: "刪除",
+			detail: "詳情",
+			subDeviceDetail: "子設備詳情",
+			batchBindSubDevice: "批量綁定子設備",
+			productKey: "所屬產品",
+			selectProductKey: "請選擇所屬產品"
+		},
+		runStatusModule: {
+			trend: "趨勢圖",
+			history: "歷史數據",
+			recentHalfHour: "最近半小時",
+			recentHour: "最近1小時",
+			recent12Hour: "最近12小時",
+			to: "至",
+			startDate: "開始日期",
+			endDate: "結束日期",
+			refresh: "刷新",
+			export: "導出",
+			time: "時間",
+			propertyValue: "屬性值",
+			dataUnit: "數據單位"
+		},
+		deviceThingModel: {
+			setAttr: "設置屬性",
+			propertyKey: "屬性標識",
+			propertyName: "屬性名稱",
+			dataType: "數據類型",
+			propertyValue: "屬性值",
+			propertyKeyPlaceholder: "請輸入屬性標識",
+			propertyNamePlaceholder: "請輸入屬性名稱",
+			dataTypePlaceholder: "請選擇數據類型",
+			propertyValuePlaceholder: "請輸入屬性值",
+			cancel: "取 消",
+			set: "設 置",
+			propertyValueError: "請先輸入屬性值!",
+			operationSuccess: "操作成功"
 		},
 		dialogI18n: {
 			addPro: "新增產品",
@@ -363,7 +459,14 @@ export default {
 			confirmDelete: "此操作將永久刪除設備:'{name}',是否繼續?",
 			deleteSuccessfully: "刪除成功",
 			deleteConfirm: "你確定要刪除所選數據?",
-			operationSuccessfully: "操作成功"
+			operationSuccessfully: "操作成功",
+			batchUnbind: "是否進行批量解綁?",
+			batchUnbindConfirm: "請選擇要批量解綁的數據。",
+			batchUnbindSuccessfully: "解綁成功",
+			deleteSubDevice: "此操作將永久刪除該子設備:'{name}', 是否繼續?",
+			deleteSubDeviceSuccessfully: "刪除成功",
+			deleteMessage: "此操作將永久刪除該數據,是否繼續?",
+			selectMessage: "請選擇要刪除的數據。"
 		}
 	},
 	// 级联管理

+ 25 - 14
src/views/iot/device/instance/component/chart.vue

@@ -13,37 +13,45 @@
 			</template>
 			<!-- 添加 tab 切换 -->
 			<el-tabs v-model="activeTab">
-				<el-tab-pane label="趋势图" name="trend">
+				<!-- 趋势图 -->
+				<el-tab-pane :label="$t('message.device.runStatusModule.trend')" name="trend">
 					<!-- 这里是 echarts 线图 -->
 					<div id="lineChart" ref="chartRef" class="chart-container" :class="{ 'chart-container-big': isFullscreen }"></div>
 				</el-tab-pane>
-				<el-tab-pane label="历史数据" name="history">
+				<!-- 历史数据 -->
+				<el-tab-pane :label="$t('message.device.runStatusModule.history')" name="history">
 					<!-- 历史日志数据表格 -->
 					<div class="history-container">
 						<div class="date-picker-container">
 							<el-radio-group v-model="historyDateRangeType" @change="chengDateRangeType">
-								<el-radio-button label="1">最近半小时</el-radio-button>
-								<el-radio-button label="2">最近1小时</el-radio-button>
-								<el-radio-button label="3">最近12小时</el-radio-button>
+								<!-- 最近半小时 -->
+								<el-radio-button label="1">{{ $t('message.device.runStatusModule.recentHalfHour') }}</el-radio-button>
+								<!-- 最近1小时 -->
+								<el-radio-button label="2">{{ $t('message.device.runStatusModule.recentHour') }}</el-radio-button>
+								<!-- 最近12小时 -->
+								<el-radio-button label="3">{{ $t('message.device.runStatusModule.recent12Hour') }}</el-radio-button>
 							</el-radio-group>
+							<!-- 至/开始日期/结束日期 -->
 							<el-date-picker
 								v-model="params.dateRange"
 								:disabled-date="disabledDate"
 								type="datetimerange"
-								range-separator="至"
-								start-placeholder="开始日期"
-								end-placeholder="结束日期"
+								:range-separator="$t('message.device.runStatusModule.to')"
+								:start-placeholder="$t('message.device.runStatusModule.startDate')"
+								:end-placeholder="$t('message.device.runStatusModule.endDate')"
 								format="YYYY-MM-DD HH:mm:ss"
 								value-format="YYYY-MM-DD HH:mm:ss"
 								@change="dateRangeChange()"
 								style="width: 220px"
 							/>
 							<div class="flex">
+								<!-- 刷新 -->
 								<el-button type="primary" plain @click="refresh"
-									><el-icon><Refresh /></el-icon>刷新</el-button
+									><el-icon><Refresh /></el-icon>{{ $t('message.device.runStatusModule.refresh') }}</el-button
 								>
+								<!-- 导出 -->
 								<el-button type="info" plain @click="exportData"
-									><el-icon><Download /></el-icon>导出</el-button
+									><el-icon><Download /></el-icon>{{ $t('message.device.runStatusModule.export') }}</el-button
 								>
 							</div>
 						</div>
@@ -54,9 +62,12 @@
 							v-loading="historyLoading"
 							:max-height="isFullscreen ? 'calc(100vh - 250px)' : 'calc(90vh - 300px)'"
 						>
-							<el-table-column prop="dataTime" label="时间" align="center" />
-							<el-table-column prop="dataValue" label="属性值" align="center" />
-							<el-table-column prop="unit" label="数据单位" align="center">
+							<!-- 时间 -->
+							<el-table-column prop="dataTime" :label="$t('message.device.runStatusModule.time')" align="center" />
+							<!-- 属性值 -->
+							<el-table-column prop="dataValue" :label="$t('message.device.runStatusModule.propertyValue')" align="center" />
+							<!-- 数据单位 -->
+							<el-table-column prop="unit" :label="$t('message.device.runStatusModule.dataUnit')" align="center">
 								<template #default>{{ data.unit }}</template>
 							</el-table-column>
 						</el-table>
@@ -79,7 +90,7 @@
 </template>
 
 <script lang="ts" setup>
-import { ref, reactive, watch, nextTick, onBeforeUnmount, onMounted } from 'vue'
+import { ref, reactive, watch, nextTick, onBeforeUnmount } from 'vue'
 import api from '/@/api/device'
 import * as echarts from 'echarts'
 import dayjs from 'dayjs'

+ 27 - 13
src/views/iot/device/instance/component/function.vue

@@ -1,32 +1,42 @@
 <template>
 	<div class="device-function">
-		<el-empty description="暂无功能列表,请先在物模型的功能定义中添加" v-if="!loading && !list.length"></el-empty>
+		<!-- 暂无功能列表,请先在物模型的功能定义中添加 -->
+		<el-empty :description="$t('message.device.deviceFunctionModule.emptyFunctionList')" v-if="!loading && !list.length"></el-empty>
 		<el-tabs tab-position="left">
 			<el-tab-pane :label="item.name" v-for="item in list" :key="item.key">
 				<div class="table-wrapper">
 					<el-table :data="item.inputs || []" border>
-						<el-table-column prop="name" label="参数名称" />
-						<el-table-column prop="valueType.type" label="输入类型" />
-						<el-table-column prop="name" label="值" min-width="200">
+						<!-- 参数名称 -->
+						<el-table-column prop="name" :label="$t('message.device.deviceFunctionModule.parameterName')" />
+						<!-- 输入类型 -->
+						<el-table-column prop="valueType.type" :label="$t('message.device.deviceFunctionModule.inputType')" />
+						<!-- 值 -->
+						<el-table-column prop="name" :label="$t('message.device.deviceFunctionModule.value')" min-width="200">
 							<template #default="{ row }">
 								<el-select v-model="row.value" clearable v-if="row.valueType.type === 'enum'" style="width: 100% !important;">
 									<el-option v-for="item in row.valueType.elements" :key="item.value" :value="item.value" :label="item.text"></el-option>
 								</el-select>
 								<el-radio-group v-model="row.value" v-else-if="row.valueType.type === 'boolean'">
-									<el-radio :label="true">{{ row.valueType.trueText || '是' }}</el-radio>
-									<el-radio :label="false">{{ row.valueType.falseText || '否' }}</el-radio>
+									<!-- 是 -->
+									<el-radio :label="true">{{ row.valueType.trueText || $t('message.device.deviceFunctionModule.yes') }}</el-radio>
+									<!-- 否 -->
+									<el-radio :label="false">{{ row.valueType.falseText || $t('message.device.deviceFunctionModule.no') }}</el-radio>
 								</el-radio-group>
-								<el-input v-model="row.value" clearable v-else :placeholder="row.valueType.type === 'array' ? 'JSON.stringify(arr)结果去掉外层单引号' : '请输入'">
+								<!-- JSON.stringify(arr)结果去掉外层单引号 / 请输入 -->
+								<el-input v-model="row.value" clearable v-else :placeholder="row.valueType.type === 'array' ? $t('message.device.deviceFunctionModule.tip1') : $t('message.device.deviceFunctionModule.tip2')">
 									<template v-if="row.valueType.unit" #append>{{ row.valueType.unit }}</template>
 								</el-input>
 							</template>
 						</el-table-column>
 					</el-table>
-					<el-input type="textarea" :value="item.result" class="result" read-only placeholder="执行结果:"> </el-input>
+					<!-- 执行结果: -->
+					<el-input type="textarea" :value="item.result" class="result" read-only :placeholder="$t('message.device.deviceFunctionModule.executeResult')"> </el-input>
 				</div>
 				<div class="btn">
-					<el-button type="primary" :loading="item.loading" @click="run(item)" :disabled="status!==2">执行</el-button>
-					<el-button @click="clear(item)" :disabled="status!==2">清空</el-button>
+					<!-- 执行 -->
+					<el-button type="primary" :loading="item.loading" @click="run(item)" :disabled="status!==2">{{ $t('message.device.deviceFunctionModule.execute') }}</el-button>
+					<!-- 清空 -->
+					<el-button @click="clear(item)" :disabled="status!==2">{{ $t('message.device.deviceFunctionModule.clear') }}</el-button>
 				</div>
 			</el-tab-pane>
 		</el-tabs>
@@ -37,6 +47,9 @@
 import { ref } from 'vue'
 import { ElMessage } from 'element-plus'
 import api from '/@/api/device'
+import { useI18n } from 'vue-i18n';
+
+const { t } = useI18n()
 
 const props = defineProps({
 	productKey: String,
@@ -72,8 +85,8 @@ function run(row: IListItem) {
 
 	// 如果是布尔类型,不需要校验,其他类型不能为空
 	const notValid = row.inputs.some((item) => item.value === null || item.value === '' || item.value === undefined)
-
-	if (notValid) return ElMessage.info('请输入完整参数')
+	// 请输入完整参数
+	if (notValid) return ElMessage.info(t('message.device.deviceFunctionModule.enterFullParameter'))
 
 	const params: any = {}
 	row.inputs.forEach(({ key, value, valueType }) => {
@@ -85,7 +98,8 @@ function run(row: IListItem) {
 				}
 				params[key] = newValue
 			} catch (error: any) {
-				ElMessage.error('请输入正确的JSON数组字符串格式')
+				// 请输入正确的JSON数组字符串格式
+				ElMessage.error(t('message.device.deviceFunctionModule.tip3'))
 				throw (error)
 			}
 		} else if (['int', 'float', 'double'].includes(valueType.type)) {

+ 6 - 4
src/views/iot/device/instance/component/list.vue

@@ -3,8 +3,8 @@
 		<el-dialog v-model="isShowDialog" :show-close="false" width="850px" :fullscreen="dialogFullScreen">
 			<template #header="{ close, titleId, titleClass }">
 				<div class="my-header">
-					<h4 :id="titleId" :class="titleClass">数据记录</h4>
-
+					<!-- 数据记录 -->
+					<h4 :id="titleId" :class="titleClass">{{ $t('message.device.productDetail.dataRecord') }}</h4>
 					<div>
 						<!-- <i
 							class="iconfont"
@@ -24,8 +24,10 @@
 			</template>
 
 			<el-table :data="tableData.data" size="small" style="width: 100%" v-loading="tableData.loading" max-height="50vh">
-				<el-table-column label="时间" prop="ts" align="center" width="180" />
-				<el-table-column label="属性值" prop="value" align="center" show-overflow-tooltip />
+				<!-- 时间 -->
+				<el-table-column :label="$t('message.device.productDetail.time')" prop="ts" align="center" width="180" />
+				<!-- 属性值 -->
+				<el-table-column :label="$t('message.device.productDetail.propertyValue')" prop="value" align="center" show-overflow-tooltip />
 			</el-table>
 			<pagination
 				v-show="tableData.total > 0"

+ 33 - 16
src/views/iot/device/instance/component/setAttr.vue

@@ -1,22 +1,31 @@
 <template>
-  <el-dialog title="设置属性" v-model="visiable" width="600px" append-to-body>
-    <el-form :model="data" ref="queryRef" label-width="68px">
-      <el-form-item label="属性标识" prop="key">
-        <el-input v-model="data.key" disabled placeholder="请输入属性标识" clearable />
+  <!-- 设置属性 -->
+  <el-dialog :title="$t('message.device.deviceThingModel.setAttr')" v-model="visiable" width="600px" append-to-body>
+    <el-form :model="data" ref="queryRef" :label-width="currentLang === 'en' ? '110px' : '80px'">
+      <!-- 属性标识 -->
+      <el-form-item :label="$t('message.device.deviceThingModel.propertyKey')" prop="key" required>
+        <!-- 请输入属性标识 -->
+        <el-input v-model="data.key" disabled :placeholder="$t('message.device.deviceThingModel.propertyKeyPlaceholder')" clearable />
       </el-form-item>
-      <el-form-item label="属性名称" prop="name">
-        <el-input v-model="data.name" disabled placeholder="请输入属性名称" clearable />
+      <!-- 属性名称 -->
+      <el-form-item :label="$t('message.device.deviceThingModel.propertyName')" prop="name">
+        <!-- 请输入属性名称 -->
+        <el-input v-model="data.name" disabled :placeholder="$t('message.device.deviceThingModel.propertyNamePlaceholder')" clearable />
       </el-form-item>
-      <el-form-item label="数据类型" prop="type">
-        <el-select v-model="data.valueType.type" placeholder="请选择数据类型" disabled style="width: 100%;">
+      <!-- 数据类型 -->
+      <el-form-item :label="$t('message.device.deviceThingModel.dataType')" prop="type">
+        <!-- 请选择数据类型 -->
+        <el-select v-model="data.valueType.type" :placeholder="$t('message.device.deviceThingModel.dataTypePlaceholder')" disabled style="width: 100%;">
           <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>
-      <el-form-item label="属性值" prop="value">
+      <!-- 属性值 -->
+      <el-form-item :label="$t('message.device.deviceThingModel.propertyValue')" prop="value">
         <template v-if="['int', 'long', 'float', 'double', 'date'].includes(data.valueType.type)">
-          <el-input type="number" v-model.number="data.value" placeholder="请输入属性值" clearable>
+          <!-- 请输入属性值 -->
+          <el-input type="number" v-model.number="data.value" :placeholder="$t('message.device.deviceThingModel.propertyValuePlaceholder')" clearable>
             <template v-if="data.valueType.unit" #append>{{ data.valueType.unit }}</template>
           </el-input>
         </template>
@@ -26,7 +35,8 @@
           </el-select>
         </template>
         <template v-else>
-          <el-input v-model="data.value" placeholder="请输入属性值" clearable>
+          <!-- 请输入属性值 -->
+          <el-input v-model="data.value" :placeholder="$t('message.device.deviceThingModel.propertyValuePlaceholder')" clearable>
             <template v-if="data.valueType.unit" #append>{{ data.valueType.unit }}</template>
           </el-input>
         </template>
@@ -34,20 +44,25 @@
     </el-form>
     <template #footer>
       <span class="dialog-footer">
-        <el-button @click="visiable = false">取 消</el-button>
-        <el-button type="primary" @click="onSubmit" :loading="loading">设 置</el-button>
+        <!-- 取 消 -->
+        <el-button @click="visiable = false">{{ $t('message.device.deviceThingModel.cancel') }}</el-button>
+        <!-- 设 置 -->
+        <el-button type="primary" @click="onSubmit" :loading="loading">{{ $t('message.device.deviceThingModel.set') }}</el-button>
       </span>
     </template>
   </el-dialog>
 </template>
 
 <script lang="ts" setup>
-import { reactive, ref } from 'vue';
+import { reactive, ref, computed } from 'vue';
 import api from '/@/api/device';
 import { ElMessage } from 'element-plus';
+import { useI18n } from 'vue-i18n';
+const { t, locale } = useI18n();
 const props = defineProps({
   deviceKey: String,
 })
+const currentLang = computed(() => locale.value)
 const visiable = ref(false)
 const loading = ref(false)
 const typeData = ref<any[]>([])
@@ -88,7 +103,8 @@ function show(row: any) {
 }
 
 function onSubmit() {
-  if (data.value === '' || data.value === null || data.value === undefined) return ElMessage('请先输入属性值!')
+  // 请先输入属性值!
+  if (data.value === '' || data.value === null || data.value === undefined) return ElMessage(t('message.device.deviceThingModel.propertyValueError'))
   loading.value = true
   api.product.propertySet({
     deviceKey: props.deviceKey,
@@ -98,7 +114,8 @@ function onSubmit() {
   }).then(() => {
     Object.assign(data, { ...form })
     visiable.value = false
-    ElMessage.success('操作成功')
+    // 操作成功
+    ElMessage.success(t('message.device.deviceThingModel.operationSuccess'))
   }).finally(() => loading.value = false)
 }
 

+ 2 - 1
src/views/iot/device/instance/component/subDevice.vue

@@ -1,5 +1,6 @@
 <template>
-	<el-dialog title="子设备详情" v-model="showDialog" fullscreen width="80%">
+	<!-- 子设备详情 -->
+	<el-dialog :title="$t('message.device.subDeviceModule.subDeviceDetail')" v-model="showDialog" fullscreen width="80%">
 		<DetailVue :deviceKey="deviceKey" v-if="showDialog"></DetailVue>
 	</el-dialog>
 </template>

+ 26 - 14
src/views/iot/device/instance/component/subDeviceMutipleBind.vue

@@ -1,34 +1,46 @@
 <template>
 	<div class="mutiple-bind-dialog-wrap">
-		<el-dialog title="批量绑定子设备" v-model="isShowDialog" width="90%">
+		<!-- 批量绑定子设备 -->
+		<el-dialog :title="$t('message.device.subDeviceModule.batchBindSubDevice')" v-model="isShowDialog" width="90%">
 			<el-form :model="ruleForm" ref="formRef" :rules="rules" size="small" label-width="110px">
-				<el-form-item label="所属产品" prop="productKey">
-					<el-select @change="handleChange" v-model="ruleForm.productKey" placeholder="请选择所属产品" style="width: 300px;">
+				<!-- 所属产品 -->
+				<el-form-item :label="$t('message.device.subDeviceModule.productKey')" prop="productKey">
+					<!-- 请选择所属产品 -->
+					<el-select @change="handleChange" v-model="ruleForm.productKey" :placeholder="$t('message.device.subDeviceModule.selectProductKey')" style="width: 300px;">
 						<el-option v-for="item in productData" :key="item.key" :label="item.name" :value="item.key" />
 					</el-select>
-					<el-button style="margin-left: 20px;" :disabled="!deviceKeyList.length" v-auth="'mutipleBind'" type="primary" @click="confirmBind()">批量绑定</el-button>
+					<!-- 批量绑定 -->
+					<el-button style="margin-left: 20px;" :disabled="!deviceKeyList.length" v-auth="'mutipleBind'" type="primary" @click="confirmBind()">{{ $t('message.device.subDeviceModule.batchBinding') }}</el-button>
 
 				</el-form-item>
 			</el-form>
 			<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" width="130" show-overflow-tooltip v-col="'key'">
+				<!-- 标识 -->
+				<el-table-column :label="$t('message.device.subDeviceModule.identifier')" prop="key" width="130" show-overflow-tooltip v-col="'key'">
 					<template #default="{ row }">
 						<copy :text="row.key"></copy>
 					</template>
 				</el-table-column>
-				<el-table-column label="设备名称" prop="name" show-overflow-tooltip v-col="'name'" />
-				<el-table-column label="产品名称" prop="product.name" show-overflow-tooltip v-col="'productName'" />
-
-				<el-table-column prop="status" label="状态" width="100" align="center" v-col="'status'">
+				<!-- 设备名称 -->
+				<el-table-column :label="$t('message.device.subDeviceModule.deviceName')" prop="name" show-overflow-tooltip v-col="'name'" />
+				<!-- 产品名称 -->
+				<el-table-column :label="$t('message.device.subDeviceModule.productName')" prop="product.name" show-overflow-tooltip v-col="'productName'" />
+				<!-- 状态 -->
+				<el-table-column prop="status" :label="$t('message.device.subDeviceModule.status')" width="100" align="center" v-col="'status'">
 					<template #default="scope">
-						<el-tag type="info" 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="info" size="small" v-if="scope.row.status == 1">{{ $t('message.device.subDeviceModule.offline') }}</el-tag>
+						<!-- 在线 -->
+						<el-tag type="success" size="small" v-if="scope.row.status == 2">{{ $t('message.device.subDeviceModule.online') }}</el-tag>
+						<!-- 未启用 -->
+						<el-tag type="info" size="small" v-if="scope.row.status == 0">{{ $t('message.device.subDeviceModule.disabled') }}</el-tag>
 					</template>
 				</el-table-column>
-				<el-table-column prop="registryTime" label="激活时间" align="center" width="150" v-col="'registryTime'"></el-table-column>
-				<el-table-column prop="desc" label="说明" v-col="'desc'"></el-table-column>
+				<!-- 激活时间 -->
+				<el-table-column prop="registryTime" :label="$t('message.device.subDeviceModule.activationTime')" align="center" width="150" v-col="'registryTime'"></el-table-column>
+				<!-- 说明 -->
+				<el-table-column prop="desc" :label="$t('message.device.subDeviceModule.remark')" v-col="'desc'"></el-table-column>
 
 			</el-table>
 			<pagination v-show="tableData.total > 0" :total="tableData.total" v-model:page="tableData.param.pageNum" v-model:limit="tableData.param.pageSize" @pagination="getDeviceList" />

+ 194 - 112
src/views/iot/device/instance/detail.vue

@@ -144,7 +144,7 @@
           <el-tabs type="border-card" v-model="activetab" @tab-click="wuhandleClick">
             <!-- 属性定义 -->
             <el-tab-pane :label="$t('message.device.productDetail.propertyDefinition')" name="attr">
-              <div class="wu-title">
+              <div class="wu-title pane-btn-wrap">
                 <div class="title"></div>
                 <!-- 新增 -->
                 <div>
@@ -199,82 +199,112 @@
                 </el-table-column>
               </el-table>
             </el-tab-pane>
-            <el-tab-pane label="功能定义" name="fun">
-              <div class="wu-title">
+            <!-- 功能定义 -->
+            <el-tab-pane :label="$t('message.device.productDetail.functionDefinition')" name="fun">
+              <div class="wu-title pane-btn-wrap">
                 <div class="title"></div>
                 <div>
-                  <el-button size="small" type="primary" v-auth="'add'" :disabled="!canEdit" @click="onOpenEditFun()">添加</el-button>
+                  <el-button size="small" type="primary" v-auth="'add'" :disabled="!canEdit" @click="onOpenEditFun()">{{$t('message.tableI18nAction.add')}}</el-button>
                 </div>
               </div>
 
               <el-table style="width: 100%" :data="tableData.data" v-loading="tableLoading" v-if="activetab == 'fun'">
-                <el-table-column label="功能标识" align="center" prop="key" />
-                <el-table-column label="名称" prop="name" show-overflow-tooltip />
-
-                <el-table-column label="描述" prop="desc" show-overflow-tooltip />
-                <el-table-column label="操作" width="300" align="center" fixed="right">
+                <!-- 功能标识 -->
+                <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.device.productDetail.remark')" prop="desc" show-overflow-tooltip />
+                <!-- 操作 -->
+                <el-table-column :label="$t('message.tableI18nColumn.operation')" width="300" align="center" fixed="right">
                   <template #default="scope">
-                    <el-button size="small" text type="warning" v-auth="'edit'" :disabled="!canEdit" @click="onEditFun(scope.row)">修改</el-button>
-                    <el-button size="small" text type="danger" v-auth="'del'" :disabled="!canEdit" @click="onRowDel(scope.row.key, 'fun')">删除</el-button>
+                    <!-- 编辑 -->
+                    <el-button size="small" text type="warning" v-auth="'edit'" :disabled="!canEdit" @click="onEditFun(scope.row)">{{ $t('message.tableI18nAction.edit') }}</el-button>
+                    <!-- 删除 -->
+                    <el-button size="small" text type="danger" v-auth="'del'" :disabled="!canEdit" @click="onRowDel(scope.row.key, 'fun')">{{ $t('message.tableI18nAction.delete') }}</el-button>
                   </template>
                 </el-table-column>
               </el-table>
             </el-tab-pane>
-            <el-tab-pane label="事件定义" name="event">
-              <div class="wu-title">
+            <!-- 事件定义 -->
+            <el-tab-pane :label="$t('message.device.productDetail.eventDefinition')" name="event">
+              <div class="wu-title pane-btn-wrap">
                 <div class="title"></div>
                 <div>
-                  <el-button type="primary" size="small" v-auth="'add'" :disabled="!canEdit" @click="onOpenEditEvent()">添加</el-button>
+                  <!-- 新增 -->
+                  <el-button type="primary" size="small" v-auth="'add'" :disabled="!canEdit" @click="onOpenEditEvent()">{{ $t('message.tableI18nAction.add') }}</el-button>
                 </div>
               </div>
 
               <el-table style="width: 100%" :data="tableData.data" v-loading="tableLoading" v-if="activetab == 'event'">
-                <el-table-column label="事件标识" align="center" prop="key" />
-                <el-table-column label="名称" prop="name" show-overflow-tooltip />
-                <el-table-column prop="level" label="事件级别" width="120" align="center">
+                <!-- 事件标识 -->
+                <el-table-column :label="$t('message.device.productDetail.eventIdentifier')" align="center" prop="key" />
+                <!-- 名称 -->
+                <el-table-column :label="$t('message.device.productDetail.name')" prop="name" show-overflow-tooltip />
+                <!-- 事件级别 -->
+                <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">普通</el-tag>
-                    <el-tag type="warning" size="small" v-if="scope.row.level == 1">警告</el-tag>
-                    <el-tag type="danger" size="small" v-if="scope.row.level == 2">紧急</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.productDetail.warning') }}</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>
-                <el-table-column label="描述" prop="desc" show-overflow-tooltip />
-
-                <el-table-column label="操作" width="300" align="center" fixed="right">
+                <!-- 描述 -->
+                <el-table-column :label="$t('message.device.productDetail.remark')" prop="desc" show-overflow-tooltip />
+                <!-- 操作 -->
+                <el-table-column :label="$t('message.tableI18nColumn.operation')" width="300" align="center" fixed="right">
                   <template #default="scope">
-                    <el-button size="small" text type="warning" v-auth="'edit'" :disabled="!canEdit" @click="onEditEvent(scope.row)">修改</el-button>
-                    <el-button size="small" text type="danger" v-auth="'del'" :disabled="!canEdit" @click="onRowDel(scope.row.key, 'event')">删除</el-button>
+                    <!-- 编辑 -->
+                     <!-- :disabled="!canEdit" -->
+                    <el-button size="small" text type="warning" v-auth="'edit'" :disabled="!canEdit" @click="onEditEvent(scope.row)">{{ $t('message.tableI18nAction.edit') }}</el-button>
+                    <!-- 删除 -->
+                    <el-button size="small" text type="danger" v-auth="'del'" :disabled="!canEdit" @click="onRowDel(scope.row.key, 'event')">{{ $t('message.tableI18nAction.delete') }}</el-button>
                   </template>
                 </el-table-column>
               </el-table>
             </el-tab-pane>
-            <el-tab-pane label="标签定义" name="tab">
-              <div class="wu-title">
+            <!-- 标签定义 -->
+            <el-tab-pane :label="$t('message.device.productDetail.tagDefinition')" name="tab">
+              <div class="wu-title pane-btn-wrap">
                 <div class="title"></div>
                 <div>
-                  <el-button size="small" type="primary" v-auth="'add'" :disabled="!canEdit" @click="onOpenEditTab()">添加</el-button>
+                  <!-- 新增 -->
+                  <el-button size="small" type="primary" v-auth="'add'" :disabled="!canEdit" @click="onOpenEditTab()">{{ $t('message.tableI18nAction.add') }}</el-button>
                 </div>
               </div>
 
               <el-table style="width: 100%" :data="tableData.data" v-loading="tableLoading" v-if="activetab == 'tab'">
-                <el-table-column label="属性标识" align="center" prop="key" />
-                <el-table-column label="属性名称" prop="name" show-overflow-tooltip />
-                <el-table-column prop="valueType" label="数据类型" width="120" align="center">
+                <!-- 属性标识 -->
+                <el-table-column :label="$t('message.device.productDetail.propertyIdentifier')" align="center" prop="key" />
+                <!-- 属性名称 -->
+                <el-table-column :label="$t('message.device.productDetail.propertyName')"  prop="name" show-overflow-tooltip />
+                <!-- 数据类型 -->
+                <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="是否只读" 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">只读</el-tag>
-                    <el-tag type="success" size="small" v-else>读写</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.productDetail.readWrite') }}</el-tag>
                   </template>
                 </el-table-column>
-                <el-table-column label="描述" prop="desc" show-overflow-tooltip />
-                <el-table-column label="操作" width="300" align="center" fixed="right">
+                <!-- 描述 -->
+                <el-table-column :label="$t('message.device.productDetail.remark')" prop="desc" show-overflow-tooltip />
+                <!-- 操作 -->
+                <el-table-column :label="$t('message.tableI18nColumn.operation')" width="300" align="center" fixed="right">
                   <template #default="scope">
-                    <el-button size="small" text type="warning" v-auth="'edit'" :disabled="!canEdit" @click="onEditTag(scope.row)">修改</el-button>
-                    <el-button size="small" text type="danger" v-auth="'del'" :disabled="!canEdit" @click="onRowDel(scope.row.key, 'tab')">删除</el-button>
+                    <!-- 编辑 -->
+                    <el-button size="small" text type="warning" v-auth="'edit'" :disabled="!canEdit" @click="onEditTag(scope.row)">{{ $t('message.tableI18nAction.edit') }}</el-button>
+                    <!-- 删除 -->
+                    <el-button size="small" text type="danger" v-auth="'del'" :disabled="!canEdit" @click="onRowDel(scope.row.key, 'tab')">{{ $t('message.tableI18nAction.delete') }}</el-button>
                   </template>
                 </el-table-column>
               </el-table>
@@ -289,39 +319,49 @@
         <!-- 日志管理 -->
         <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">
-                <el-select v-model="logtableData.param.types" placeholder="日志类型" clearable>
+            <el-form :model="logtableData.param" ref="logqueryRef" inline :label-width="currentLang === 'en' ? '70px' : '68px'"> 
+              <!-- 日志类型 -->
+              <el-form-item :label="$t('message.device.logManagementModule.logType')" prop="types">
+                <!-- 日志类型 -->
+                <el-select v-model="logtableData.param.types" :placeholder="$t('message.device.logManagementModule.logType')" clearable>
                   <el-option v-for="item in logTypeData" :key="item" :label="item" :value="item" />
                 </el-select>
               </el-form-item>
-              <el-form-item label="创建时间" prop="dateRange">
-                <el-date-picker v-model="logtableData.param.dateRange" value-format="YYYY-MM-DD" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
+              <!-- 创建时间 -->
+              <el-form-item :label="$t('message.device.logManagementModule.createdTime')" prop="dateRange" :label-width="currentLang === 'en' ? '110px' : '68px'">
+                <!-- 开始日期/结束日期 -->
+                <el-date-picker v-model="logtableData.param.dateRange" value-format="YYYY-MM-DD" type="daterange" range-separator="-" :start-placeholder="$t('message.device.logManagementModule.startDate')" :end-placeholder="$t('message.device.logManagementModule.endDate')"></el-date-picker>
               </el-form-item>
               <el-form-item>
+                <!-- 查询 -->
                 <el-button type="primary" class="ml10" @click="getlog">
                   <el-icon>
                     <ele-Search />
                   </el-icon>
-                  查询
+                  {{ $t('message.device.logManagementModule.search') }}
                 </el-button>
+                <!-- 重置 -->
                 <el-button @click="resetQuery(logqueryRef)">
                   <el-icon>
                     <ele-Refresh />
                   </el-icon>
-                  重置
+                  {{ $t('message.device.logManagementModule.reset') }}
                 </el-button>
               </el-form-item>
             </el-form>
           </div>
           <el-table style="width: 100%" :data="logtableData.data">
-            <el-table-column label="类型" align="center" prop="type" />
-            <el-table-column label="时间" prop="ts" show-overflow-tooltip />
-
-            <el-table-column label="内容" prop="content" show-overflow-tooltip />
-            <el-table-column label="操作" width="300" align="center" fixed="right">
+            <!-- 类型 -->
+            <el-table-column :label="$t('message.device.logManagementModule.type')" align="center" prop="type" />
+            <!-- 时间 -->
+            <el-table-column :label="$t('message.device.logManagementModule.time')" prop="ts" show-overflow-tooltip />
+            <!-- 内容 -->
+            <el-table-column :label="$t('message.device.logManagementModule.content')" prop="content" show-overflow-tooltip />
+            <!-- 操作 -->
+            <el-table-column :label="$t('message.device.logManagementModule.action')" width="300" align="center" fixed="right">
               <template #default="scope">
-                <el-button size="small" text type="warning" @click="onLogDetail(scope.row)">查看</el-button>
+                <!-- 查看 -->
+                <el-button size="small" text type="warning" @click="onLogDetail(scope.row)">{{ $t('message.device.logManagementModule.view') }}</el-button>
               </template>
             </el-table-column>
           </el-table>
@@ -330,11 +370,15 @@
         </el-tab-pane>
         <!-- Topic列表 -->
         <el-tab-pane :label="$t('message.device.topicList')" name="topic">
-          SagooMqtt协议 ,涉及的topic如下:
+          <!-- SagooMqtt协议 ,涉及的topic如下: -->
+          {{$t('message.device.topicListModule.tips')}}
           <el-table style="width: 100%; margin-top: 20px" :data="topicData" border>
-            <el-table-column label="描述" prop="info" width="250" />
-            <el-table-column label="类型" prop="type" width="80" align="center" />
-            <el-table-column label="Topic类" prop="url">
+            <!-- 描述 -->
+            <el-table-column :label="$t('message.device.topicListModule.description')" prop="info" width="250" />
+            <!-- 类型 -->
+            <el-table-column :label="$t('message.device.topicListModule.type')" prop="type" width="80" align="center" />
+            <!-- Topic类 -->
+            <el-table-column :label="$t('message.device.topicListModule.topicClass')" prop="url">
               <template #default="{ row }">
                 <copy :text="row.url"></copy>
               </template>
@@ -342,39 +386,51 @@
           </el-table>
           <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 v-if="prodetail.deviceType == '网关'" label="子设备" name="6">
+        <!-- 子设备 -->
+        <el-tab-pane v-if="prodetail.deviceType == '网关'" :label="$t('message.device.subDeviceModule.subDevice')" name="6">
           <div class="wu-box">
-            <div class="wu-title">
-              <div class="title">子设备列表</div>
+            <div class="wu-title pane-btn-wrap">
+              <!-- 子设备列表 -->
+              <div class="title">{{$t('message.device.subDeviceModule.subDeviceList')}}</div>
               <div>
-                <el-button v-auth="'mutipleBind'" type="primary" @click="onOpenMutipleBind()">批量绑定</el-button>
-                <el-button v-auth="'cancleMutipleBind'" :disabled="!deviceKeyList.length" type="primary" @click="mutipleUnbind()">批量解绑</el-button>
+                <el-button v-auth="'mutipleBind'" type="primary" @click="onOpenMutipleBind()">{{$t('message.device.subDeviceModule.batchBinding')}}</el-button>
+                <el-button v-auth="'cancleMutipleBind'" :disabled="!deviceKeyList.length" type="primary" @click="mutipleUnbind()">{{$t('message.device.subDeviceModule.batchUnbinding')}}</el-button>
               </div>
             </div>
             <el-table :data="deviceTableData.data" style="width: 100%" @selection-change="handleSelectionChange" v-loading="deviceTableData.loading">
               <el-table-column type="selection" width="55" align="center" />
-              <el-table-column label="标识" prop="key" width="130" show-overflow-tooltip>
+              <!-- 标识 -->
+              <el-table-column :label="$t('message.device.subDeviceModule.identifier')" prop="key" width="130" show-overflow-tooltip>
                 <template #default="{ row }">
                   <copy :text="row.key"></copy>
                 </template>
               </el-table-column>
-              <el-table-column label="设备名称" prop="name" show-overflow-tooltip />
-              <el-table-column label="产品名称" prop="productName" show-overflow-tooltip />
-
-              <el-table-column prop="status" label="状态" width="100" align="center">
+              <!-- 设备名称 -->
+              <el-table-column :label="$t('message.device.subDeviceModule.deviceName')" prop="name" show-overflow-tooltip />
+              <!-- 产品名称 -->
+              <el-table-column :label="$t('message.device.subDeviceModule.productName')" prop="productName" show-overflow-tooltip />
+              <!-- 状态 -->
+              <el-table-column prop="status" :label="$t('message.device.subDeviceModule.status')" width="100" align="center">
                 <template #default="scope">
-                  <el-tag type="info" 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="info" size="small" v-if="scope.row.status == 1">{{ $t('message.device.subDeviceModule.offline') }}</el-tag>
+                  <!-- 在线 -->
+                  <el-tag type="success" size="small" v-if="scope.row.status == 2">{{ $t('message.device.subDeviceModule.online') }}</el-tag>
+                  <!-- 未启用 -->
+                  <el-tag type="info" size="small" v-if="scope.row.status == 0">{{ $t('message.device.subDeviceModule.disabled') }}</el-tag>
                 </template>
               </el-table-column>
-              <el-table-column prop="registryTime" label="激活时间" align="center" width="150"></el-table-column>
-              <el-table-column prop="desc" label="说明"></el-table-column>
-
-              <el-table-column label="操作" width="160" align="center" fixed="right">
+              <!-- 激活时间 -->
+              <el-table-column prop="registryTime" :label="$t('message.device.subDeviceModule.activationTime')" align="center" width="150"></el-table-column>
+              <!-- 说明 -->
+              <el-table-column prop="desc" :label="$t('message.device.subDeviceModule.remark')"></el-table-column>
+              <!-- 操作 -->
+              <el-table-column :label="$t('message.device.subDeviceModule.action')" align="center" width="160" fixed="right">
                 <template #default="scope">
-                  <el-button size="small" text type="danger" v-auth="'del'" @click="deleteSubDevice(scope.row)">删除</el-button>
-                  <el-button size="small" text type="warning" v-auth="'detail'" @click="onOpenDetail(scope.row)">详情</el-button>
+                  <!-- 删除 -->
+                  <el-button size="small" text type="danger" v-auth="'del'" @click="deleteSubDevice(scope.row)">{{ $t('message.device.subDeviceModule.delete') }}</el-button>
+                  <!-- 详情 -->
+                  <el-button size="small" text type="warning" v-auth="'detail'" @click="onOpenDetail(scope.row)">{{ $t('message.device.subDeviceModule.detail') }}</el-button>
                 </template>
               </el-table-column>
             </el-table>
@@ -385,9 +441,11 @@
         <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>
+              <!-- 设备档案 -->
+              <div class="protitle">{{ $t('message.device.deviceArchive') }}</div>
               <div>
-                <el-button size="small" type="primary" v-auth="'edit'" @click="onOpenEditAsset" :disabled="!canEdit">编辑</el-button>
+                <!-- 编辑 -->
+                <el-button size="small" type="primary" v-auth="'edit'" @click="onOpenEditAsset" :disabled="!canEdit">{{ $t('message.tableI18nAction.edit') }}</el-button>
               </div>
             </div>
 
@@ -426,12 +484,13 @@
     <!-- 编辑设备档案 -->
     <EditAssetRef ref="editAssetRef" @getList="getDeviceAssetMetadata"></EditAssetRef>
 
-    <el-dialog v-model="dialogVisible" title="日志数据内容" width="30%">
+    <!-- 日志数据内容 -->
+    <el-dialog v-model="dialogVisible" :title="$t('message.device.logManagementModule.viewContent')" width="30%">
       <JsonViewer :value="jsonData" boxed sort theme="jv-dark" />
 
       <template #footer>
         <span class="dialog-footer">
-          <el-button @click="dialogVisible = false">关闭</el-button>
+          <el-button @click="dialogVisible = false">{{ $t('message.device.logManagementModule.close') }}</el-button>  
         </span>
       </template>
     </el-dialog>
@@ -625,35 +684,47 @@ export default defineComponent({
             ? [
                 {
                   url: `/sys/${res.data.productKey}/${deviceKey}/thing/event/property/pack/post`,
-                  info: "网关批量上传事件和属性(网关发起)",
-                  type: "请求",
+                  // 网关批量上传事件和属性(网关发起)
+                  info: t('message.device.topicListModule.topic1'),
+                  // 请求
+                  type: t('message.device.topicListModule.request'),
                 },
                 {
                   url: `/sys/${res.data.productKey}/${deviceKey}/thing/event/property/pack/post_reply`,
-                  info: "网关批量上传事件和属性(网关发起)",
-                  type: "响应",
+                  // 网关批量上传事件和属性(网关发起)
+                  info: t('message.device.topicListModule.topic1'),
+                  // 响应
+                  type: t('message.device.topicListModule.response'),
                 },
               ]
             : [
                 {
                   url: `/sys/${res.data.productKey}/${deviceKey}/thing/event/property/post`,
-                  info: "设备上报属性(设备端发起)",
-                  type: "请求",
+                    // 设备上报属性(设备端发起)
+                  info:  t('message.device.topicListModule.topic2'),
+                  // 请求
+                  type: t('message.device.topicListModule.request'),
                 },
                 {
                   url: `/sys/${res.data.productKey}/${deviceKey}/thing/event/property/post_reply`,
-                  info: "设备上报属性(设备端发起)",
-                  type: "响应",
+                  // 设备上报属性(设备端发起)
+                  info: t('message.device.topicListModule.topic2'),
+                  // 响应
+                  type: t('message.device.topicListModule.response'),
                 },
                 {
                   url: `/sys/${res.data.productKey}/${deviceKey}/thing/event/${"${eventIdentifier}"}/post`,
-                  info: "设备上报事件(设备端发起)",
-                  type: "请求",
+                  // 设备上报事件(设备端发起)
+                  info: t('message.device.topicListModule.topic3'),
+                  // 请求
+                  type: t('message.device.topicListModule.request'),
                 },
                 {
                   url: `/sys/${res.data.productKey}/${deviceKey}/thing/event/${"${eventIdentifier}"}/post_reply`,
-                  info: "设备上报事件(设备端发起)",
-                  type: "响应",
+                  // 设备上报事件(设备端发起)
+                  info: t('message.device.topicListModule.topic3'),
+                  // 响应
+                  type: t('message.device.topicListModule.response'),
                 },
               ];
 
@@ -698,14 +769,17 @@ export default defineComponent({
     };
 
     const mutipleUnbind = () => {
-      let msg = "是否进行批量解绑?";
+      // 是否进行批量解绑?
+      let msg = t('message.device.message.batchUnbind');
       if (state.deviceKeyList.length === 0) {
-        ElMessage.error("请选择要批量解绑的数据。");
+        // 请选择要批量解绑的数据。
+        ElMessage.error(t('message.device.message.batchUnbindConfirm'));
         return;
       }
-      ElMessageBox.confirm(msg, "提示", {
-        confirmButtonText: "确认",
-        cancelButtonText: "取消",
+      ElMessageBox.confirm(msg, 
+      t('message.tableI18nConfirm.deleteTitle'), {
+        confirmButtonText: t('message.tableI18nConfirm.confirmText'),
+        cancelButtonText: t('message.tableI18nConfirm.cancelText'),
         type: "warning",
       })
         .then(() => {
@@ -715,7 +789,8 @@ export default defineComponent({
               subKeys: state.deviceKeyList,
             })
             .then(() => {
-              ElMessage.success("解绑成功");
+              // 解绑成功
+              ElMessage.success(t('message.device.message.batchUnbindSuccessfully'));
               // typeList();
               getDeviceTableData();
             });
@@ -727,7 +802,7 @@ export default defineComponent({
       state.deviceTableData.data = [];
       state.deviceTableData.param.gatewayKey = state.detail.key;
       api.device.getList(state.deviceTableData.param).then((res: any) => {
-        state.deviceTableData.data = res.list;
+        state.deviceTableData.data = res.lis;
         state.deviceTableData.total = res.Total;
       });
     };
@@ -744,13 +819,18 @@ export default defineComponent({
 
     // 删除子设备
     const deleteSubDevice = (row: any) => {
-      ElMessageBox.confirm(`此操作将永久删除该子设备:${row.name}, 是否继续?`, "提示", {
-        confirmButtonText: "删除",
-        cancelButtonText: "取消",
-        type: "warning",
-      }).then(() => {
+      // 此操作将永久删除该子设备:${row.name}, 是否继续?
+      ElMessageBox.confirm(
+        t('message.device.message.deleteSubDevice', { name: row.name }),
+        t('message.tableI18nConfirm.deleteTitle'),
+        {
+          confirmButtonText: t('message.tableI18nConfirm.confirmText'),
+          cancelButtonText: t('message.tableI18nConfirm.cancelText'),
+          type: "warning",
+        }
+      ).then(() => {
         api.product.deleteSubDevice(row.id).then(() => {
-          ElMessage.success("删除成功");
+          ElMessage.success(t('message.device.message.deleteSubDeviceSuccessfully'));
           getDeviceTableData();
         });
       });
@@ -826,39 +906,41 @@ export default defineComponent({
 
     // 删除产品
     const onRowDel = (key: string, type: string) => {
-      let msg = `此操作将永久删除该数据,是否继续?`;
+      // 此操作将永久删除该数据,是否继续?
+      let msg = t('message.device.message.deleteMessage');
 
       if (key.length === 0) {
-        ElMessage.error("请选择要删除的数据。");
+        // 请选择要删除的数据。
+        ElMessage.error(t('message.device.message.selectMessage'));
         return;
       }
-      ElMessageBox.confirm(msg, "提示", {
-        confirmButtonText: "确认",
-        cancelButtonText: "取消",
+      ElMessageBox.confirm(msg, t('message.tableI18nConfirm.deleteTitle'), {
+        confirmButtonText: t('message.tableI18nConfirm.confirmText'),
+        cancelButtonText: t('message.tableI18nConfirm.cancelText'),
         type: "warning",
       })
         .then(() => {
           if (type == "attr") {
             api.model.propertydel(state.productKey, key).then(() => {
-              ElMessage.success("删除成功");
+              ElMessage.success(t('message.device.message.deleteSubDeviceSuccessfully'));
               getproperty();
             });
           }
           if (type == "fun") {
             api.model.functiondel(state.productKey, key).then(() => {
-              ElMessage.success("删除成功");
+              ElMessage.success(t('message.device.message.deleteSubDeviceSuccessfully'));
               getfunction();
             });
           }
           if (type == "event") {
             api.model.eventdel(state.productKey, key).then(() => {
-              ElMessage.success("删除成功");
+              ElMessage.success(t('message.device.message.deleteSubDeviceSuccessfully'));
               getevent();
             });
           }
           if (type == "tab") {
             api.model.tagdel(state.productKey, key).then(() => {
-              ElMessage.success("删除成功");
+              ElMessage.success(t('message.device.message.deleteSubDeviceSuccessfully'));
               gettab();
             });
           }