vera_min 1 год назад
Родитель
Сommit
1b0415a359

+ 15 - 11
src/api/ice104/index.ts

@@ -9,32 +9,36 @@
 import { get, post, del, put,file } from '/@/utils/request_ice104';
 
 export default {
-  common:{
-    singleImg: (data: object) => post('/common/singleImg', data),
-  },
+  // 设备
   device: {
+    getAll: (params: object) => get('/device/all', params),
     getList: (params: object) => get('/device/list', params),
     addItem: (data: object) => post('/device/add', data),
     editItem: (data: object) => put('/device/edit', data),
     deleteItem: (data: object) => del('/device/delete', data),
+    detailItem: (number: any) => get('/device/get', { number }),
+  },
+  // 设备任务
+  job: {
+    getList: (params: object) => get('/device/job/list', params),
+    addItem: (data: object) => post('/device/job/add', data),
+    deleteItem: (data: object) => del('/device/job/delete', data),
+    editItem: (data: object) => put('/device/job/edit', data),
   },
+  // 模版
   template: {
     getAll: (params: object) => get('/template/all', params),
     getList: (params: object) => get('/template/list', params),
     addItem: (data: object) => post('/template/add', data),
     editItem: (data: object) => put('/template/edit', data),
-    deleteItem:  (data: object) => del('/template/delete', data),
-  },
-  deviceTask: {
-    getList: (params: object) => get('/device/job/list', params),
-    addItem: (data: object) => post('/device/job/add', data),
-    editItem: (data: object) => put('/device/job/edit', data),
-    deleteItem: (ids: number) => del('/device/job/delete', { ids }),
+    deleteItem: (data: object) => del('/template/delete', data),
+    detailItem: (number: any) => get('/template/get', { number }),
   },
+// 模版点位
   deviceTemplate: {
     getList: (params: object) => get('/device/template/list', params),
     addItem: (data: object) => post('/device/template/add', data),
     editItem: (data: object) => put('/device/template/edit', data),
-    deleteItem: (ids: number) => del('/device/template/delete', { ids }),
+    deleteItem: (data: object) => del('/device/template/delete', data),
   }
 }

+ 2 - 2
src/utils/request_ice104.ts

@@ -4,8 +4,8 @@ import getOrigin from '/@/utils/origin'
 
 // 配置新建一个 axios 实例
 const service = axios.create({
-	// baseURL: getOrigin(import.meta.env.VITE_ICE104_API),
-	baseURL: 'http://qt9nk7.natappfree.cc',
+	baseURL: getOrigin(import.meta.env.VITE_ICE104_API),
+	// baseURL: 'http://awzr9z.natappfree.cc',
 	timeout: 50000,
 	headers: { 'Content-Type': 'application/json' },
 });

+ 146 - 0
src/views/iot/ice104/device/component/addOrEditDeviceTask.vue

@@ -0,0 +1,146 @@
+<!-- 添加或者修改设备 -->
+<template>
+	<el-dialog
+		:title="isEdit ? '修改设备任务' : '添加设备任务'"
+		v-model="dialogVisible"
+		width="600px"
+		:before-close="clsoeDialog"
+		:close-on-click-modal="false"
+	>
+		<el-form ref="formRef" :rules="formRules" :model="ruleForm" label-position="left" label-width="120px" style="width: 90%; margin: 0 auto">
+			<el-form-item label="设备任务名称">
+				<el-input v-model="ruleForm.title" placeholder="请输入设备任务名称" />
+			</el-form-item>
+			<!-- <el-form-item label="所属设备">
+				<el-select v-model="ruleForm.deviceNumber" placeholder="请选择所属设备" class="width100">
+					<el-option :label="item.title" :value="item.number" v-for="(item, index) in deviceList" :key="index" />
+				</el-select>
+			</el-form-item> -->
+            <el-form-item label="执行间隔">
+				<el-input type="number" :min="0" v-model.number="ruleForm.interval" placeholder="请输入执行间隔" />
+			</el-form-item>
+			<el-form-item label="任务类型">
+				<el-select v-model="ruleForm.jobType" placeholder="请选择任务类型" class="width100">
+					<el-option v-for="dict in device_job_types" :key="dict.value" :label="dict.label" :value="dict.value"> </el-option>
+				</el-select>
+			</el-form-item>
+		</el-form>
+		<template #footer>
+			<el-button @click="clsoeDialog()"> 取 消 </el-button>
+			<el-button :loading="btnLoading" type="primary" @click="submitData"> 保 存 </el-button>
+		</template>
+	</el-dialog>
+</template>
+<script lang="ts" setup>
+import { computed, reactive, ref, onMounted, getCurrentInstance } from 'vue';
+import api from '/@/api/ice104/index';
+import { useI18n } from 'vue-i18n';
+import { ElMessage } from 'element-plus';
+import { useSearch } from '/@/hooks/useCommonIce104';
+import apiDevice from '/@/api/device';
+import { useRoute } from 'vue-router';
+
+const route = useRoute();
+
+const { proxy } = getCurrentInstance() as any;
+const { params, tableData, getList, loading } = useSearch(api.template.getAll, 'data', { title: '' });
+const { device_job_types } = proxy.useDict('device_job_types');
+getList();
+
+
+const dialogVisible = ref(false);
+const btnLoading = ref(false);
+// const deviceList = ref([]);
+const emit = defineEmits(['updateList']);
+const formRef = ref();
+const ruleForm = ref({
+	// number: route.params && route.params.id,
+    number: 0,
+	title: '',
+    deviceNumber: route.params && route.params.id,
+    interval: 0,
+    jobType: ''
+})
+const isEdit = ref(false);
+
+const formRules = computed(() => ({
+	number: [{ required: true, trigger: 'change', message: '请输入设备编码' }],
+}));
+const getRandom = (num:number) =>{
+    return Math.floor((Math.random()+Math.floor(Math.random()*9+1))*Math.pow(10,num-1));
+}
+const submitData = async () => {
+	formRef.value.validate((valid: boolean) => {
+		console.log(valid)
+		if (!valid) return
+		btnLoading.value = true
+		if (isEdit.value) {
+			// 修改
+			api.job.editItem({
+				...ruleForm.value,
+			})
+			.then(() => {
+				ElMessage({ type: 'success', message: '修改成功' })
+				emit('updateList')
+				closeDialog()
+			})
+			.finally(() => (btnLoading.value = false))
+		} else {
+			// 新增
+            ruleForm.value.number = getRandom(10);
+			api.job.addItem(ruleForm.value)
+			.then(() => {
+				ElMessage({ type: 'success', message: '添加成功' })
+				emit('updateList')
+				closeDialog()
+			})
+			.finally(() => (btnLoading.value = false))
+		}
+	})
+}
+
+/**
+ * 关闭弹窗
+ */
+const closeDialog = () => {
+  dialogVisible.value = false;
+  ruleForm.value = {
+	number: 0,
+	title: '',
+    deviceNumber: route.params && route.params.id,
+    interval: 0,
+    jobType: ''
+  }
+}
+
+
+const open = async (row: any) => {
+	dialogVisible.value = true
+	console.log(row)
+	if (row && row.number.toString()) {
+		console.log(row)
+        row.jobType = row.jobType.toString();
+		ruleForm.value = row;
+		isEdit.value = true;
+        console.log(ruleForm.value)
+	}else {
+		isEdit.value = false;
+	}
+}
+
+
+
+
+// 页面加载时
+onMounted(() => {
+    // getDeviceList();
+});
+
+defineExpose({ open })
+</script>
+
+<style lang="scss" scoped>
+.width100 {
+	width: 100%;
+}
+</style>

+ 109 - 0
src/views/iot/ice104/device/component/deviceTaskTable.vue

@@ -0,0 +1,109 @@
+<template>
+    <div>
+        <el-form :model="params" :inline="true" ref="queryRef">
+            <el-form-item label="任务名称" prop="title">
+                <el-input v-model="params.title" placeholder="请输入任务名称" clearablestyle="width: 240px" @keyup.enter.native="getList()" />
+            </el-form-item>
+            <el-form-item>
+                <el-button size="default" type="primary" class="ml10" @click="getList()">
+                    <el-icon>
+                        <ele-Search />
+                    </el-icon>
+                    查询
+                </el-button>
+                <el-button size="default" @click="resetQuery()">
+                    <el-icon>
+                        <ele-Refresh />
+                    </el-icon>
+                    重置
+                </el-button>
+                <el-button type="primary" @click="addOrEdit()">
+                    <el-icon>
+                        <ele-FolderAdd />
+                    </el-icon>
+                    新增任务
+                </el-button>
+            </el-form-item>
+        </el-form>
+        <el-table :data="tableData" style="width: 100%" v-loading="loading">
+            <el-table-column type="index" label="序号" width="80" align="center" />
+            <el-table-column prop="title" label="任务名称"  align="center" show-overflow-tooltip></el-table-column>
+            <el-table-column prop="deviceNumber" label="设备编码" min-width="120" align="center" show-overflow-tooltip></el-table-column>
+            <el-table-column prop="interval" label="执行间隔(s)" min-width="120" align="center" show-overflow-tooltip></el-table-column>
+            <el-table-column prop="interval" label="任务类型" min-width="120" align="center" show-overflow-tooltip>
+                <template #default="scope">
+						<el-tag type="info" size="small" v-if="scope.row.jobType == 100">总召唤</el-tag>
+						<el-tag type="info" size="small" v-if="scope.row.jobType == 101">电度召唤</el-tag>
+						<el-tag type="info" size="small" v-if="scope.row.jobType == 103">时钟同步</el-tag>
+					</template>
+            </el-table-column>
+             <el-table-column fixed="right" label="操作" width="100" align="center">
+                <template #default="scope">
+                    <el-button size="small" text type="primary" @click="addOrEdit(scope.row)">修改</el-button>
+                    <el-button size="small" text type="info" @click="onDel(scope.row)">删除</el-button>
+                </template>
+            </el-table-column>
+        </el-table>
+        <pagination v-if="params.total" :total="params.total" v-model:page="params.pageNum" v-model:limit="params.pageSize" @pagination="getList()" />
+        <EditForm ref="editFormRef" @updateList="getList()"></EditForm>
+    </div>
+</template>
+<script lang="ts" setup>
+import { computed, reactive, ref, onMounted } from 'vue';
+import api from '/@/api/ice104/index';
+import { useI18n } from 'vue-i18n';
+import { ElMessageBox, ElMessage } from 'element-plus';
+import { useSearch } from '/@/hooks/useCommonIce104';
+import apiDevice from '/@/api/device';
+import EditForm from './addOrEditDeviceTask.vue';
+import { useRoute } from 'vue-router';
+
+const route = useRoute();
+
+const { params, tableData, getList, loading } = useSearch(api.job.getList, 'data', { title: '', deviceNumber: route.params.id });
+
+const emit = defineEmits(['updateList']);
+const editFormRef = ref();
+const queryRef = ref();
+
+/**
+ * 新增设备任务
+ */
+const addOrEdit = async (row?: any) => {
+	editFormRef.value.open(row);
+};
+
+/**
+ * 单一删除
+ */
+const onDel = (row: any) => {
+	ElMessageBox.confirm(`此操作将删除接口:“${row.title}”,是否继续?`, '提示', {
+		confirmButtonText: '确认',
+		cancelButtonText: '取消',
+		type: 'warning',
+	}).then(async () => {
+		await api.job.deleteItem({number: row.number});
+		ElMessage.success('删除成功');
+		getList();
+	});
+};
+
+// 重置表单
+const resetQuery = () => {
+	queryRef.value.resetFields();
+	getList();
+};
+
+// 页面加载时
+onMounted(() => {
+    getList();
+});
+
+// defineExpose({ open })
+</script>
+
+<style lang="scss" scoped>
+.width100 {
+	width: 100%;
+}
+</style>

+ 42 - 8
src/views/iot/ice104/device/component/edit.vue

@@ -3,7 +3,7 @@
 		:title="isEdit ? '修改设备' : '添加设备'"
 		v-model="dialogVisible"
 		width="600px"
-		:before-close="clsoeDialog"
+		:before-close="closeDialog"
 		:close-on-click-modal="false"
 	>
 		<el-form ref="formRef" :rules="formRules" :model="ruleForm" label-position="left" label-width="120px" style="width: 90%; margin: 0 auto">
@@ -21,34 +21,41 @@
 			</el-form-item>
 			<el-form-item label="模版编号">
 				<el-select v-model="ruleForm.templateNumber" placeholder="请选择模版编号" class="width100">
-					<el-option :label="item.title" :value="item.number" v-for="(item, index) in tableData" :key="index"></el-option>
+					<el-option :label="item.title" :value="item.number" v-for="(item, index) in tableData" :key="index" />
 				</el-select>
 			</el-form-item>
 			<el-form-item label="产品key">
-				<el-input v-model="ruleForm.productKey" placeholder="请输入产品key" />
+				<el-select @change="handleProductChange" v-model="ruleForm.productKey" placeholder="请选择产品key" class="width100">
+					<el-option :label="item.name" :value="item.key" v-for="(item, index) in productList" :key="index" />
+				</el-select>
 			</el-form-item>
-			<el-form-item label="设备key">
-				<el-input v-model="ruleForm.deviceKey" placeholder="请输入设备key" />
+			<el-form-item label="设备key" v-if="ruleForm.productKey">
+				<el-select v-model="ruleForm.deviceKey" placeholder="请选择设备key" class="width100">
+					<el-option :label="item.name" :value="item.key" v-for="(item, index) in deviceList" :key="index" />
+				</el-select>
 			</el-form-item>
 		</el-form>
 		<template #footer>
-			<el-button @click="clsoeDialog()"> 取 消 </el-button>
+			<el-button @click="closeDialog()"> 取 消 </el-button>
 			<el-button :loading="btnLoading" type="primary" @click="submitData"> 保 存 </el-button>
 		</template>
 	</el-dialog>
 </template>
 <script lang="ts" setup>
-import { computed, reactive, ref } from 'vue';
+import { computed, reactive, ref, onMounted } from 'vue';
 import api from '/@/api/ice104/index';
 import { useI18n } from 'vue-i18n';
 import { ElMessage } from 'element-plus';
 import { useSearch } from '/@/hooks/useCommonIce104';
+import apiDevice from '/@/api/device';
 
 const { params, tableData, getList, loading } = useSearch(api.template.getAll, 'data', { title: '' });
 getList();
 
 const dialogVisible = ref(false);
 const btnLoading = ref(false);
+const productList = ref([]);
+const deviceList = ref([]);
 const emit = defineEmits(['updateList']);
 const formRef = ref();
 const ruleForm = ref({
@@ -95,13 +102,28 @@ const submitData = async () => {
 	})
 }
 
+const handleProductChange = (data:any) => {
+	console.log(data)
+	ruleForm.value.deviceKey = "";
+	let findItem:any = productList.value.find((v: any) => v.key === data);
+	console.log(findItem)
+	getDeviceList(findItem.id)
+}
+
+const getDeviceList = (id:number) => {
+	apiDevice.device.allList({productId: id}).then((res: any) => {
+		console.log(res)
+		deviceList.value = res.device
+	})
+}
+
 /**
  * 关闭弹窗
  */
 const closeDialog = () => {
   dialogVisible.value = false;
   ruleForm.value = {
-	id: '',
+	// id: '',
 	number: '',
 	title: '',
 	commonAddr: '',
@@ -125,6 +147,18 @@ const open = async (row: any) => {
 	}
 }
 
+
+const getDeviceProduct = () => {
+	apiDevice.product.getLists({}).then((res: any) => {
+		productList.value = res.product
+	})
+}
+
+// 页面加载时
+onMounted(() => {
+	getDeviceProduct();
+});
+
 defineExpose({ open })
 </script>
 

+ 134 - 0
src/views/iot/ice104/device/component/editDeviceForm.vue

@@ -0,0 +1,134 @@
+<template>
+    <el-form ref="formRef" :rules="formRules" :model="ruleForm" label-position="left" label-width="120px" style="width: 70%;">
+        <el-form-item label="设备编码" prop="number">
+            <el-input :disabled="isEdit" v-model="ruleForm.number" placeholder="请输入设备编码" />
+        </el-form-item>
+        <el-form-item label="名称">
+            <el-input v-model="ruleForm.title" placeholder="请输入名称" />
+        </el-form-item>
+        <el-form-item label="设备通用地址">
+            <el-input type="number" v-model.number="ruleForm.commonAddr" placeholder="请输入设备通用地址" />
+        </el-form-item>
+        <el-form-item label="mac地址">
+            <el-input v-model="ruleForm.subCode" placeholder="请输入mac地址" />
+        </el-form-item>
+        <el-form-item label="模版编号">
+            <el-select v-model="ruleForm.templateNumber" placeholder="请选择模版编号" class="width100">
+                <el-option :label="item.title" :value="item.number" v-for="(item, index) in tableData" :key="index" />
+            </el-select>
+        </el-form-item>
+        <el-form-item label="产品key">
+            <el-select @change="(val) => handleProductChange(val, true)" v-model="ruleForm.productKey" placeholder="请选择产品key" class="width100">
+                <el-option :label="item.name" :value="item.key" v-for="(item, index) in productList" :key="index" />
+            </el-select>
+        </el-form-item>
+        <el-form-item label="设备key" v-if="ruleForm.productKey">
+            <el-select v-model="ruleForm.deviceKey" placeholder="请选择设备key" class="width100">
+                <el-option :label="item.name" :value="item.key" v-for="(item, index) in deviceList" :key="index" />
+            </el-select>
+        </el-form-item>
+        <el-form-item>
+            <el-button type="primary" :loading="btnLoading" @click="submitData"> 保 存 </el-button>
+        </el-form-item>
+    </el-form>
+</template>
+<script lang="ts" setup>
+import { computed, reactive, ref, onMounted } from 'vue';
+import api from '/@/api/ice104/index';
+import { useI18n } from 'vue-i18n';
+import { ElMessage } from 'element-plus';
+import { useSearch } from '/@/hooks/useCommonIce104';
+import apiDevice from '/@/api/device';
+
+const { params, tableData, getList, loading } = useSearch(api.template.getAll, 'data', { title: '' });
+getList();
+
+const btnLoading = ref(false);
+const productList = ref([]);
+const deviceList = ref([]);
+const emit = defineEmits(['updateList']);
+const formRef = ref();
+const ruleForm = ref({
+	number: '',
+	title: '',
+	commonAddr: '',
+	subCode: '',
+	templateNumber: '',
+	productKey: '',
+	deviceKey: '',
+})
+const isEdit = ref(false);
+
+const formRules = computed(() => ({
+	number: [{ required: true, trigger: 'change', message: '请输入设备编码' }],
+}));
+
+const submitData = async () => {
+	formRef.value.validate((valid: boolean) => {
+		console.log(valid)
+		if (!valid) return
+		btnLoading.value = true
+		if (isEdit.value) {
+			// 修改
+			api.device.editItem({
+				...ruleForm.value,
+			})
+			.then(() => {
+				ElMessage({ type: 'success', message: '修改成功' })
+				emit('updateList')
+			})
+			.finally(() => (btnLoading.value = false))
+		}
+	})
+}
+
+const handleProductChange = (data:any, isClear: boolean) => {
+	if(isClear) {
+		ruleForm.value.deviceKey = "";
+	}
+	let findItem:any = productList.value.find((v: any) => v.key === data);
+	console.log(findItem)
+	if(!findItem) return;
+	getDeviceList(findItem.id)
+}
+
+const getDeviceList = (id:number) => {
+	apiDevice.device.allList({productId: id}).then((res: any) => {
+		console.log(res)
+		deviceList.value = res.device
+	})
+}
+
+
+const open = async (row: any) => {
+	console.log(row)
+	if (row && row.number.toString()) {
+		console.log(row)
+		ruleForm.value = row;
+		isEdit.value = true;
+		handleProductChange(ruleForm.value.productKey, false)
+	}else {
+		isEdit.value = false;
+	}
+}
+
+
+const getDeviceProduct = () => {
+	apiDevice.product.getLists({}).then((res: any) => {
+		productList.value = res.product
+	})
+}
+
+// 页面加载时
+onMounted(() => {
+	getDeviceProduct();
+});
+
+defineExpose({ open })
+</script>
+
+<style lang="scss" scoped>
+.width100 {
+	width: 100%;
+}
+</style>

+ 148 - 0
src/views/iot/ice104/device/detail.vue

@@ -0,0 +1,148 @@
+<!--
+ * @Author: vera_min vera_min@163.com
+ * @Date: 2023-10-23 17:05:57
+ * @LastEditors: vera_min vera_min@163.com
+ * @LastEditTime: 2023-10-25 10:11:06
+ * @FilePath: /sagoo-admin-ui/src/views/iot/ice104/index.vue
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+-->
+<template>
+	<div class="page page-full">
+		<el-card shadow="hover" class="page-full-part">
+			<el-tabs
+				v-model="activeName"
+				class="demo-tabs"
+				@tab-click="handleClick"
+			>
+				<el-tab-pane label="设备详情" name="1">
+					<EditDeviceForm ref="editFormRef" />
+				</el-tab-pane>
+				<el-tab-pane label="设备任务" name="2">
+					<DeviceTaskTable />
+				</el-tab-pane>
+			</el-tabs>
+			<!-- <div style="height: 100px;"></div>
+			<div class="search">
+				<el-form :model="params" :inline="true" ref="queryRef">
+					<el-form-item label="设备名称" prop="title">
+						<el-input v-model="params.title" placeholder="请输入设备名称" clearablestyle="width: 240px" @keyup.enter.native="getList()" />
+					</el-form-item>
+					<el-form-item>
+						<el-button size="default" type="primary" class="ml10" @click="getList()">
+							<el-icon>
+								<ele-Search />
+							</el-icon>
+							查询
+						</el-button>
+						<el-button size="default" @click="resetQuery()">
+							<el-icon>
+								<ele-Refresh />
+							</el-icon>
+							重置
+						</el-button>
+						<el-button type="primary" @click="addOrEdit()">
+							<el-icon>
+								<ele-FolderAdd />
+							</el-icon>
+							新增设备
+						</el-button>
+					</el-form-item>
+				</el-form>
+			</div>
+			<el-table :data="tableData" style="width: 100%" v-loading="loading">
+				<el-table-column type="index" label="序号" width="80" align="center" />
+				<el-table-column prop="title" label="设备名称"  align="center" show-overflow-tooltip></el-table-column>
+				<el-table-column prop="commonAddr" label="设备通用地址" min-width="120" align="center" show-overflow-tooltip></el-table-column>
+				<el-table-column prop="subCode" label="mac地址" min-width="120" align="center" show-overflow-tooltip></el-table-column>
+				<el-table-column prop="templateNumber" label="模版编号" align="center" show-overflow-tooltip></el-table-column>
+				<el-table-column prop="productKey" label="产品key" align="center" show-overflow-tooltip></el-table-column>
+				<el-table-column prop="deviceKey" label="设备key" align="center" show-overflow-tooltip></el-table-column>
+
+				<el-table-column prop="number" label="设备编码" min-width="120" align="center" show-overflow-tooltip></el-table-column>
+				<el-table-column prop="createdAt" label="创建时间" min-width="160" align="center"></el-table-column>
+				<el-table-column prop="updatedAt" label="更新时间" min-width="160" align="center"></el-table-column>
+				<el-table-column fixed="right" label="操作" width="100" align="center">
+					<template #default="scope">
+						<el-button size="small" text type="primary" @click="addOrEdit(scope.row)">详情</el-button>
+						<el-button size="small" text type="info" @click="onDel(scope.row)">删除</el-button>
+					</template>
+				</el-table-column>
+			</el-table>
+			<pagination v-if="params.total" :total="params.total" v-model:page="params.page" v-model:limit="params.size" @pagination="getList()" />
+		 -->
+		</el-card>
+		
+	</div>
+</template>
+
+<script lang="ts" setup>
+import { ref, onMounted } from 'vue';
+import EditDeviceForm from './component/editDeviceForm.vue';
+import DeviceTaskTable from './component/deviceTaskTable.vue';
+
+import api from '/@/api/ice104/index';
+import { ElMessageBox, ElMessage } from 'element-plus';
+import { useSearch } from '/@/hooks/useCommonIce104';
+import { useRoute } from 'vue-router';
+import type { TabsPaneContext } from 'element-plus'
+
+const route = useRoute();
+const editFormRef = ref();
+const detailFormData = ref({});
+const queryRef = ref();
+
+const activeName = ref('1')
+
+
+
+const { params, tableData, getList, loading } = useSearch(api.device.getList, 'data', { title: '' });
+
+getList();
+
+
+
+const handleClick = (tab: TabsPaneContext, event: Event) => {
+  console.log(tab, event)
+}
+
+const addOrEdit = async (row?: any) => {
+	
+};
+
+// 重置表单
+const resetQuery = () => {
+	queryRef.value.resetFields();
+	getList();
+};
+
+const onDel = (row: any) => {
+	ElMessageBox.confirm(`此操作将删除接口:“${row.title}”,是否继续?`, '提示', {
+		confirmButtonText: '确认',
+		cancelButtonText: '取消',
+		type: 'warning',
+	}).then(async () => {
+		await api.device.deleteItem({number: row.number});
+		ElMessage.success('删除成功');
+		getList();
+	});
+};
+
+/**
+ * 获取设备详情
+ */
+const initDeviceInfo = async () => {
+	const res = await api.device.detailItem(route.params && route.params.id)
+	console.log(res)
+	detailFormData.value = res.data;
+	editFormRef.value.open(res.data);
+}
+	// 页面加载时
+	onMounted(() => {
+		// const id: = route.params && route.params.id;
+		// console.log(id)
+		initDeviceInfo()
+	});
+	
+
+
+</script>

+ 28 - 10
src/views/iot/ice104/device/index.vue

@@ -31,7 +31,7 @@
 							<el-icon>
 								<ele-FolderAdd />
 							</el-icon>
-							新增
+							新增设备
 						</el-button>
 					</el-form-item>
 				</el-form>
@@ -39,48 +39,62 @@
 			<el-table :data="tableData" style="width: 100%" v-loading="loading">
 				<el-table-column type="index" label="序号" width="80" align="center" />
 				<el-table-column prop="title" label="设备名称"  align="center" show-overflow-tooltip></el-table-column>
-				<el-table-column prop="number" label="设备编码" min-width="120" align="center" show-overflow-tooltip></el-table-column>
+				<el-table-column prop="commonAddr" label="设备通用地址" min-width="120" align="center" show-overflow-tooltip></el-table-column>
 				<el-table-column prop="subCode" label="mac地址" min-width="120" align="center" show-overflow-tooltip></el-table-column>
-				<el-table-column prop="commonAddr" label="通用设备地址" min-width="120" align="center" show-overflow-tooltip></el-table-column>
 				<el-table-column prop="templateNumber" label="模版编号" align="center" show-overflow-tooltip></el-table-column>
 				<el-table-column prop="productKey" label="产品key" align="center" show-overflow-tooltip></el-table-column>
 				<el-table-column prop="deviceKey" label="设备key" align="center" show-overflow-tooltip></el-table-column>
+
+				<el-table-column prop="number" label="设备编码" min-width="120" align="center" show-overflow-tooltip></el-table-column>
 				<el-table-column prop="createdAt" label="创建时间" min-width="160" align="center"></el-table-column>
 				<el-table-column prop="updatedAt" label="更新时间" min-width="160" align="center"></el-table-column>
 				<el-table-column fixed="right" label="操作" width="100" align="center">
 					<template #default="scope">
-						<el-button size="small" text type="primary" @click="addOrEdit(scope.row)">编辑</el-button>
+						<el-button size="small" text type="primary" @click="toDetailPage(scope.row)">详情</el-button>
 						<el-button size="small" text type="info" @click="onDel(scope.row)">删除</el-button>
 					</template>
 				</el-table-column>
 			</el-table>
-			<pagination v-if="params.total" :total="params.total" v-model:page="params.page" v-model:limit="params.size" @pagination="getList()" />
+			<pagination v-if="params.total" :total="params.total" v-model:page="params.pageNum" v-model:limit="params.pageSize" @pagination="getList()" />
 		</el-card>
 		<EditForm ref="editFormRef" @updateList="getList()"></EditForm>
 	</div>
 </template>
 
 <script lang="ts" setup>
-import { ref } from 'vue';
+import { ref, onMounted } from 'vue';
 import EditForm from './component/edit.vue';
 import api from '/@/api/ice104/index';
 import { ElMessageBox, ElMessage } from 'element-plus';
 import { useSearch } from '/@/hooks/useCommonIce104';
+import { useRouter } from 'vue-router';
 
+const router = useRouter();
 const editFormRef = ref();
-const detailFormRef = ref();
 const queryRef = ref();
 
+
 const { params, tableData, getList, loading } = useSearch(api.device.getList, 'data', { title: '' });
 
 getList();
 
+/**
+ * 去往设备详情页面
+ */
+const toDetailPage = async (row?: any) => {
+	// editFormRef.value.open(row);
+	// router.push('/monitor/notice');
+	
+	// router.push(`/iotmanager/network/tunnel/edit/${route.params && route.params.id}`)
+	router.push(`/ice104/device/detail/${row.number}`)
+};
+
+/**
+ * 新增设备
+ */
 const addOrEdit = async (row?: any) => {
 	editFormRef.value.open(row);
 };
-const viewDetail = async (row: any) => {
-	detailFormRef.value.open(row);
-};
 
 // 重置表单
 const resetQuery = () => {
@@ -88,6 +102,9 @@ const resetQuery = () => {
 	getList();
 };
 
+/**
+ * 单一删除
+ */
 const onDel = (row: any) => {
 	ElMessageBox.confirm(`此操作将删除接口:“${row.title}”,是否继续?`, '提示', {
 		confirmButtonText: '确认',
@@ -99,4 +116,5 @@ const onDel = (row: any) => {
 		getList();
 	});
 };
+
 </script>

+ 0 - 268
src/views/iot/ice104/deviceTask/component/detail.vue

@@ -1,268 +0,0 @@
-<template>
-	<el-dialog title="设备通道详情" v-model="dialogVisible" width="900px" :before-close="clsoeDialog" :close-on-click-modal="false">
-		<el-tabs v-model="activeName">
-			<el-tab-pane label="通道信息" name="1">
-				<el-form ref="dataForm" :rules="rules" :model="temp" label-position="left" label-width="120px" style="width: 90%; margin: 0 auto">
-					<el-form-item label="通道名称" prop="title">
-						<el-input v-model="temp.title" placeholder="请输入通道名称" />
-					</el-form-item>
-					<el-form-item label="注册码" prop="number">
-						<el-input v-model="temp.number" placeholder="请输入注册码" />
-					</el-form-item>
-					<el-form-item label="设备地址" prop="slaveId">
-						<el-input v-model.number="temp.slaveId" placeholder="请输入设备地址" />
-					</el-form-item>
-					<!-- <el-form-item label="调度周期(秒)" prop="interval">
-            <el-input v-model="temp.interval" placeholder="请输入调度周期" />
-          </el-form-item> -->
-					<el-form-item label="" prop="">
-						<div align="right">
-							<el-button @click="clsoeDialog"> 取 消 </el-button>
-							<el-button type="primary" @click="updateData()"> 保 存 </el-button>
-						</div>
-					</el-form-item>
-				</el-form>
-			</el-tab-pane>
-			<el-tab-pane label="任务" name="2">
-				<div class="filter-container">
-					<el-button class="filter-item" type="primary" icon="el-icon-circle-plus-outline" @click="handleCreate"> 添加任务 </el-button>
-				</div>
-
-				<el-table :key="tableKey" v-loading="listLoading" :data="taskList" border fit highlight-current-row style="width: 100%">
-					<el-table-column label="标题" prop="Job.title" align="center"></el-table-column>
-					<el-table-column label="调度周期" prop="Job.interval" align="center"></el-table-column>
-					<el-table-column label="转发格式" prop="encoding" align="center">
-						<template #default="{ row }">
-							{{ getCodingLabel(row) }}
-						</template>
-					</el-table-column>
-					<el-table-column label="mqtt主题" prop="Job.publishTopic" align="center"></el-table-column>
-					<el-table-column label="模板" prop="Template.title" align="center"></el-table-column>
-					<el-table-column label="操作" align="center" width="200">
-						<template #default="{ row, $index }">
-							<el-button type="primary" size="mini" @click="handleUpdate(row)"> 详情 </el-button>
-							<el-button v-if="row.status != 'deleted'" size="mini" type="danger" @click="handleDelete(row, $index)"> 删除 </el-button>
-						</template>
-					</el-table-column>
-				</el-table>
-
-				<pagination v-if="total > 0" :total="total" v-model:page="listQuery.page" v-model:limit="listQuery.size" @pagination="getList()" />
-				<TaskDialog ref="taskDialog" :formatOptions="formatOptions" @finish="getList" />
-			</el-tab-pane>
-			<el-tab-pane label="通道码流" name="3">
-				<div>
-					<el-button :type="evsrc ? 'info' : 'primary'" @click="openEv()">开始</el-button>
-					<el-button :type="evsrc ? 'primary' : 'info'" :disabled="!evsrc" @click="closeEv()">停止</el-button>
-					<el-button type="defualt" @click="clearLog()">清空</el-button>
-					<el-button type="info" style="margin-left: 150px" @click="downloadLog()">下载报文</el-button>
-					<ul id="logContainer" ref="logContainer"></ul>
-				</div>
-			</el-tab-pane>
-		</el-tabs>
-	</el-dialog>
-</template>
-
-<script lang="ts">
-import { ElMessage } from 'element-plus';
-import api from '/@/api/device/modbus';
-import getOrigin from '/@/utils/origin';
-import TaskDialog from './taskDialog.vue';
-
-export default {
-	components: { TaskDialog },
-	data() {
-		return {
-			temp: {
-				title: '',
-				number: '',
-				templateNumber: '',
-				slaveId: '',
-				interval: '',
-			},
-			rules: {
-				title: [{ required: true, message: '请输入通道名称', trigger: 'blur' }],
-				number: [{ required: true, message: '请输入注册码', trigger: 'blur' }],
-				slaveId: [{ required: true, message: '请输入设备地址', trigger: 'blur' }],
-				templateNumber: [{ required: true, message: '请输入设备模板', trigger: 'change' }],
-			},
-			dialogVisible: false,
-			activeName: '1',
-			taskList: [],
-			listLoading: false,
-			total: 0,
-			tableKey: 0,
-			listQuery: {
-				page: 1,
-				size: 10,
-			},
-			evsrc: null as any,
-			count: 0,
-			templateOptions: [],
-			formatOptions: [],
-		};
-	},
-	watch: {
-		activeName: 'handleTabClick',
-	},
-
-	methods: {
-		open(row: any) {
-			this.temp = { ...row };
-			this.getDict();
-			this.dialogVisible = true;
-		},
-		downloadLog() {
-			window.open(getOrigin(import.meta.env.VITE_MODBUS_API) + '/debug/export_message?number=' + this.temp.number);
-		},
-		clsoeDialog() {
-			this.dialogVisible = false;
-			this.activeName = '1';
-			(this.$refs['dataForm'] as any).resetFields();
-			this.closeEv();
-		},
-		updateData() {
-			(this.$refs['dataForm'] as any).validate((valid: boolean) => {
-				if (valid) {
-					const tempData = Object.assign({}, this.temp);
-					api.channel.editDevice(tempData).then(() => {
-						this.$emit('getList');
-						this.clsoeDialog();
-						ElMessage.success('操作成功!');
-					});
-				}
-			});
-		},
-		// tab 切换
-		handleTabClick() {
-			this.closeEv(false);
-			if (this.activeName === '2') {
-				// 任务
-				this.getList();
-			} else if (this.activeName === '3') {
-				// 码流
-				// this.initEv()
-			}
-		},
-		handleFilter() {
-			this.listQuery.page = 1;
-			this.getList();
-		},
-		// 获取字典数据
-		getDict() {
-			api.getDict({ code: 'forwardFormat' }).then((data: any) => {
-				this.formatOptions = data.list || [];
-			});
-		},
-		// 获取任务list
-		getList() {
-			this.listLoading = true;
-			api.task
-				.getList(this.listQuery)
-				.then((res: any) => {
-					this.taskList = res.list || [];
-					this.total = res.Total;
-				})
-				.finally(() => {
-					this.listLoading = false;
-				});
-		},
-		handleDelete(row: any) {
-			this.$confirm('是否确认删除任务名称为"' + row.Job.title + '"的数据项?', '警告', {
-				confirmButtonText: '确定',
-				cancelButtonText: '取消',
-				type: 'warning',
-			})
-				.then(function () {
-					return api.task.deleteDeviceJob({ number: row.Job.number });
-				})
-				.then(() => {
-					this.handleFilter();
-					ElMessage.success('删除成功!');
-				})
-				.catch(function () { });
-		},
-		handleCreate() {
-			(this.$refs.taskDialog as any).openDialog({
-				dialogStatus: 'create',
-				deviceNumber: this.temp.number,
-			});
-		},
-		handleUpdate(row: any) {
-			(this.$refs.taskDialog as any).openDialog({
-				dialogStatus: 'update',
-				row,
-				deviceNumber: this.temp.number,
-			});
-		},
-		// 码流
-		initEv() {
-			if (this.evsrc) return;
-			// this.evsrc = new EventSource(`http://one.server.mydig.net/debug?number=${this.temp.number}`);
-			this.evsrc = new EventSource(`${getOrigin(import.meta.env.VITE_MODBUS_API)}/debug?number=${this.temp.number}`);
-			let that = this;
-			this.evsrc.onmessage = function (ev: any) {
-				try {
-					let obj = JSON.parse(ev.data);
-					if (obj.deviceId === that.temp.number) {
-						let color = obj.type === 'request' ? '#F56C6C' : '#409EFF';
-						let content = `${obj.type === 'request' ? '请求:' : '应答:'} ${obj.msg}`;
-						this.$refs.logContainer.insertAdjacentHTML('afterbegin', `<li style="color: ${color}">${content}</li>`);
-					}
-				} catch (_e) {
-					// @ts-ignore
-					// console.log('error', e);
-				}
-			};
-			// this.evsrc.onerror = function (_ev: any) {
-				// @ts-ignore
-				// console.log('readyState = ' + ev.currentTarget.readyState);
-			// };
-		},
-		openEv() {
-			(this.$refs.logContainer as any).insertAdjacentHTML('beforeEnd', `<li style="color: #000;">开始...</li>`);
-			this.initEv();
-		},
-		closeEv(log = true) {
-			this.evsrc && this.evsrc.close();
-			this.evsrc = null;
-			this.count = 0;
-			// this.clearLog()
-			if (log) {
-				(this.$refs.logContainer as any).insertAdjacentHTML('beforeEnd', `<li style="color: #000;">停止...</li>`);
-			}
-		},
-		// 清空码流
-		clearLog() {
-			(this.$refs.logContainer as any).innerHTML = '';
-		},
-		getCodingLabel(row: any) {
-			const item = this.formatOptions.find((item: any) => item.value === row.Job.encoding) as any;
-			return item.title;
-		},
-	},
-};
-</script>
-
-<style lang="scss" scoped>
-.filter-container {
-	margin-bottom: 10px;
-}
-
-.filter-item {
-	margin-right: 10px;
-}
-
-#logContainer {
-	height: 400px;
-	overflow: auto;
-	border: 1px solid #ddd;
-	padding: 10px;
-	padding-left: 20px;
-	border-radius: 8px;
-	margin-top: 10px;
-	word-wrap: break-word;
-	word-break: normal;
-	background-color: #f2f2f2;
-	line-height: 22px;
-}
-</style>

+ 0 - 80
src/views/iot/ice104/deviceTask/component/edit.vue

@@ -1,80 +0,0 @@
-<template>
-	<el-dialog title="添加设备通道" v-model="dialogVisible" width="600px" :before-close="clsoeDialog" :close-on-click-modal="false">
-		<el-form ref="dataForm" :rules="rules" :model="temp" label-position="left" label-width="120px" style="width: 90%; margin: 0 auto">
-			<el-form-item label="通道名称" prop="title">
-				<el-input v-model="temp.title" placeholder="请输入通道名称" />
-			</el-form-item>
-			<el-form-item label="注册码" prop="number">
-				<el-input v-model="temp.number" placeholder="请输入注册码" />
-			</el-form-item>
-			<el-form-item label="设备地址" prop="slaveId">
-				<el-input v-model.number="temp.slaveId" placeholder="请输入设备地址" />
-			</el-form-item>
-		</el-form>
-		<div slot="footer" class="dialog-footer">
-			<el-button @click="clsoeDialog()"> 取 消 </el-button>
-			<el-button type="primary" @click="createData()"> 保 存 </el-button>
-		</div>
-	</el-dialog>
-</template>
-<script lang="ts">
-import api from '/@/api/device/modbus';
-import { ElMessage } from 'element-plus';
-export default {
-	data() {
-		return {
-			temp: {
-				title: '',
-				number: '',
-				templateNumber: '',
-				slaveId: '',
-				interval: '',
-			},
-			rules: {
-				title: [{ required: true, message: '请输入通道名称', trigger: 'blur' }],
-				number: [{ required: true, message: '请输入注册码', trigger: 'blur' }],
-				slaveId: [{ required: true, message: '请输入设备地址', trigger: 'blur' }],
-			},
-			dialogVisible: false,
-			listLoading: false,
-			templateOptions: [],
-		};
-	},
-
-	methods: {
-		open() {
-			// this.getList();
-			this.dialogVisible = true;
-		},
-		clsoeDialog() {
-			(this.$refs.dataForm as any).resetFields();
-			this.dialogVisible = false;
-		},
-		// 获取模板数据
-		getList() {
-			this.listLoading = true;
-			api.channel
-				.getList({ page: 1, size: 50 })
-				.then((data: any) => {
-					this.templateOptions = data.list || [];
-				})
-				.finally(() => {
-					this.listLoading = false;
-				});
-		},
-		createData() {
-			(this.$refs['dataForm'] as any).validate((valid: boolean) => {
-				if (valid) {
-					api.channel.addDevice(this.temp).then(() => {
-						this.$emit('getList');
-						this.clsoeDialog();
-						ElMessage.success('操作成功!');
-					});
-				}
-			});
-		},
-	},
-};
-</script>
-
-<style lang="scss" scoped></style>

+ 0 - 139
src/views/iot/ice104/deviceTask/component/taskDialog.vue

@@ -1,139 +0,0 @@
-<template>
-	<el-dialog :title="textMap[dialogStatus]" v-model="dialogVisible" width="600px" :before-close="clsoeDialog" append-to-body :close-on-click-modal="false">
-		<el-form ref="dataForm" :rules="rules" :model="temp" label-position="left" label-width="120px" style="width: 400px; margin: 0 auto">
-			<el-form-item label="标题" prop="title">
-				<el-input v-model="temp.title" placeholder="请输入标题" />
-			</el-form-item>
-			<el-form-item label="调度周期" prop="interval">
-				<el-input v-model="temp.interval" placeholder="请输入调度周期" />
-			</el-form-item>
-			<el-form-item label="转发格式" prop="encoding">
-				<el-select v-model="temp.encoding" placeholder="请选择转发格式" style="width: 100%">
-					<el-option v-for="item in formatOptions" :key="item.value" :label="item.title" :value="item.value"> </el-option>
-				</el-select>
-				<!-- <el-input v-model="temp.encoding" placeholder="请输入转发格式"/> -->
-			</el-form-item>
-			<el-form-item label="mqtt主题" prop="publishTopic">
-				<el-input v-model="temp.publishTopic" placeholder="请输入mqtt主题" />
-			</el-form-item>
-			<el-form-item label="设备模板" prop="templateNumber">
-				<el-select v-model="temp.templateNumber" filterable placeholder="请选择设备模板" style="width: 100%">
-					<el-option v-for="item in templateOptions" :key="item.number" :label="item.title" :value="item.number"> </el-option>
-				</el-select>
-			</el-form-item>
-		</el-form>
-		<div slot="footer" class="dialog-footer">
-			<el-button @click="clsoeDialog"> 取 消 </el-button>
-			<el-button type="primary" @click="dialogStatus === 'create' ? createData() : updateData()"> 保 存 </el-button>
-		</div>
-	</el-dialog>
-</template>
-
-<script lang="ts">
-import api from '/@/api/device/modbus';
-import { ElMessage } from 'element-plus';
-
-export default {
-	components: {},
-	props: {
-		formatOptions: {
-			default: () => [],
-		},
-	},
-	data() {
-		return {
-			temp: {
-				title: '',
-				interval: '20s',
-				encoding: 'json',
-				publishTopic: '',
-				deviceNumber: '',
-				number: '',
-				templateNumber: '',
-			},
-			rules: {
-				title: [{ required: true, message: '请输入模板名称', trigger: 'change' }],
-				publishTopic: [{ required: true, message: '请输入mqtt主题', trigger: 'change' }],
-				mode: [{ required: true, message: '请选择模式', trigger: 'change' }],
-				templateNumber: [{ required: true, message: '请选择模式', trigger: 'change' }],
-			},
-			dialogVisible: false,
-			listLoading: false,
-			dialogStatus: '',
-			textMap: {
-				update: '任务详情',
-				create: '添加任务',
-			},
-			templateOptions: '',
-		};
-	},
-
-	methods: {
-		openDialog({ dialogStatus, row, deviceNumber }) {
-			this.dialogStatus = dialogStatus;
-			this.temp.deviceNumber = deviceNumber;
-			if (row) {
-				// this.temp = { ...row }
-				this.temp.number = row.Job.number;
-				this.temp.title = row.Job.title;
-				this.temp.interval = row.Job.interval;
-				this.temp.encoding = row.Job.encoding;
-				this.temp.publishTopic = row.Job.publishTopic;
-				this.temp.templateNumber = row?.Template?.number;
-			}
-			// this.getDict()
-			this.getTemplateList();
-			this.dialogVisible = true;
-		},
-		clsoeDialog() {
-			this.dialogVisible = false;
-			this.temp = {
-				title: '',
-				interval: '20s',
-				encoding: 'json',
-				publishTopic: '',
-				deviceNumber: '',
-				number: '',
-				templateNumber: '',
-			};
-			(this.$refs['dataForm'] as any).resetFields();
-		},
-		// 获取模板数据
-		getTemplateList() {
-			this.listLoading = true;
-			api.template
-				.getList({ page: 1, size: 50 })
-				.then((res: any) => {
-					this.templateOptions = res.list || [];
-				})
-				.finally(() => {
-					this.listLoading = false;
-				});
-		},
-		createData() {
-			(this.$refs['dataForm'] as any).validate((valid: boolean) => {
-				if (valid) {
-					api.task.addDeviceJob(this.temp).then(() => {
-						this.$emit('finish');
-						this.clsoeDialog();
-						ElMessage.success('操作成功!');
-					});
-				}
-			});
-		},
-		updateData() {
-			(this.$refs['dataForm'] as any).validate((valid: boolean) => {
-				if (valid) {
-					api.task.editDeviceJob(this.temp).then(() => {
-						this.$emit('finish');
-						this.clsoeDialog();
-						ElMessage.success('操作成功!');
-					});
-				}
-			});
-		},
-	},
-};
-</script>
-
-<style lang="scss" scoped></style>

+ 0 - 107
src/views/iot/ice104/deviceTask/index.vue

@@ -1,107 +0,0 @@
-<!--
- * @Author: vera_min vera_min@163.com
- * @Date: 2023-10-23 17:05:57
- * @LastEditors: vera_min vera_min@163.com
- * @LastEditTime: 2023-10-25 10:11:06
- * @FilePath: /sagoo-admin-ui/src/views/iot/ice104/index.vue
- * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
--->
-<template>
-	<div class="page page-full">
-		<el-card shadow="hover" class="page-full-part">
-			<div class="search">
-				<el-form :model="params" :inline="true" ref="queryRef">
-					<el-form-item label="设备执行名称" prop="title">
-						<el-input v-model="params.title" placeholder="请输入设备执行名称" clearablestyle="width: 240px" @keyup.enter.native="getList(1)" />
-					</el-form-item>
-					<el-form-item>
-						<el-button size="default" type="primary" class="ml10" @click="getList(1)">
-							<el-icon>
-								<ele-Search />
-							</el-icon>
-							查询
-						</el-button>
-						<el-button size="default" @click="resetQuery()">
-							<el-icon>
-								<ele-Refresh />
-							</el-icon>
-							重置
-						</el-button>
-						<el-button type="primary" @click="addOrEdit()" v-auth="'add'">
-							<el-icon>
-								<ele-FolderAdd />
-							</el-icon>
-							新增
-						</el-button>
-					</el-form-item>
-				</el-form>
-			</div>
-			<el-table :data="tableData" style="width: 100%" v-loading="loading">
-				<el-table-column type="index" label="序号" width="80" align="center" />
-				<el-table-column prop="title" label="名称"  align="center" show-overflow-tooltip></el-table-column>
-				<el-table-column prop="number" label="编码"  align="center" show-overflow-tooltip></el-table-column>
-				<el-table-column prop="deviceNumber" label="设备编号"  align="center" show-overflow-tooltip></el-table-column>
-				<el-table-column prop="interval" label="执行间隔"  align="center" show-overflow-tooltip></el-table-column>
-				<el-table-column prop="jobType" label="job类型" align="center" show-overflow-tooltip>
-					<!-- 100-》总召唤,101-》电度召唤,103-》时钟同步 -->
-					<template #default="scope">
-						<el-tag type="info" size="small" v-if="scope.row.jobType == 100">总召唤</el-tag>
-						<el-tag type="info" size="small" v-if="scope.row.jobType == 101">电度召唤</el-tag>
-						<el-tag type="info" size="small" v-if="scope.row.jobType == 103">时钟同步</el-tag>
-					</template>
-				</el-table-column>
-				<el-table-column fixed="right" label="操作" width="100" align="center">
-					<template #default="scope">
-						<el-button size="small" text type="primary" @click="viewDetail(scope.row)">编辑</el-button>
-						<el-button size="small" text type="info" @click="onDel(scope.row)">删除</el-button>
-					</template>
-				</el-table-column>
-			</el-table>
-			<pagination v-if="params.total" :total="params.total" v-model:page="params.page" v-model:limit="params.size" @pagination="getList()" />
-		</el-card>
-		<EditForm ref="editFormRef" @getList="getList(1)"></EditForm>
-		<detailForm ref="detailFormRef" @getList="getList()"></detailForm>
-	</div>
-</template>
-
-<script lang="ts" setup>
-import { ref } from 'vue';
-import EditForm from './component/edit.vue';
-import detailForm from './component/detail.vue';
-import api from '/@/api/ice104/index';
-import { ElMessageBox, ElMessage } from 'element-plus';
-import { useSearch } from '/@/hooks/useCommonIce104';
-
-const editFormRef = ref();
-const detailFormRef = ref();
-const queryRef = ref();
-
-const { params, tableData, getList, loading } = useSearch(api.deviceTask.getList, 'data', { title: '' });
-
-getList();
-
-const addOrEdit = async (row?: any) => {
-	editFormRef.value.open(row);
-};
-const viewDetail = async (row: any) => {
-	detailFormRef.value.open(row);
-};
-
-// 重置表单
-const resetQuery = () => {
-	queryRef.value.resetFields();
-	getList(1);
-};
-
-const onDel = (row: any) => {
-	ElMessageBox.confirm(`此操作将删除接口:“${row.title}”,是否继续?`, '提示', {
-		confirmButtonText: '确认',
-		cancelButtonText: '取消',
-		type: 'warning',
-	}).then(async () => {
-		await api.channel.deleteDevice({ number: row.number });
-		ElMessage.success('删除成功');
-		getList(1);
-	});
-};
-</script>

+ 0 - 268
src/views/iot/ice104/deviceTemplate/component/detail.vue

@@ -1,268 +0,0 @@
-<template>
-	<el-dialog title="设备通道详情" v-model="dialogVisible" width="900px" :before-close="clsoeDialog" :close-on-click-modal="false">
-		<el-tabs v-model="activeName">
-			<el-tab-pane label="通道信息" name="1">
-				<el-form ref="dataForm" :rules="rules" :model="temp" label-position="left" label-width="120px" style="width: 90%; margin: 0 auto">
-					<el-form-item label="通道名称" prop="title">
-						<el-input v-model="temp.title" placeholder="请输入通道名称" />
-					</el-form-item>
-					<el-form-item label="注册码" prop="number">
-						<el-input v-model="temp.number" placeholder="请输入注册码" />
-					</el-form-item>
-					<el-form-item label="设备地址" prop="slaveId">
-						<el-input v-model.number="temp.slaveId" placeholder="请输入设备地址" />
-					</el-form-item>
-					<!-- <el-form-item label="调度周期(秒)" prop="interval">
-            <el-input v-model="temp.interval" placeholder="请输入调度周期" />
-          </el-form-item> -->
-					<el-form-item label="" prop="">
-						<div align="right">
-							<el-button @click="clsoeDialog"> 取 消 </el-button>
-							<el-button type="primary" @click="updateData()"> 保 存 </el-button>
-						</div>
-					</el-form-item>
-				</el-form>
-			</el-tab-pane>
-			<el-tab-pane label="任务" name="2">
-				<div class="filter-container">
-					<el-button class="filter-item" type="primary" icon="el-icon-circle-plus-outline" @click="handleCreate"> 添加任务 </el-button>
-				</div>
-
-				<el-table :key="tableKey" v-loading="listLoading" :data="taskList" border fit highlight-current-row style="width: 100%">
-					<el-table-column label="标题" prop="Job.title" align="center"></el-table-column>
-					<el-table-column label="调度周期" prop="Job.interval" align="center"></el-table-column>
-					<el-table-column label="转发格式" prop="encoding" align="center">
-						<template #default="{ row }">
-							{{ getCodingLabel(row) }}
-						</template>
-					</el-table-column>
-					<el-table-column label="mqtt主题" prop="Job.publishTopic" align="center"></el-table-column>
-					<el-table-column label="模板" prop="Template.title" align="center"></el-table-column>
-					<el-table-column label="操作" align="center" width="200">
-						<template #default="{ row, $index }">
-							<el-button type="primary" size="mini" @click="handleUpdate(row)"> 详情 </el-button>
-							<el-button v-if="row.status != 'deleted'" size="mini" type="danger" @click="handleDelete(row, $index)"> 删除 </el-button>
-						</template>
-					</el-table-column>
-				</el-table>
-
-				<pagination v-if="total > 0" :total="total" v-model:page="listQuery.page" v-model:limit="listQuery.size" @pagination="getList()" />
-				<TaskDialog ref="taskDialog" :formatOptions="formatOptions" @finish="getList" />
-			</el-tab-pane>
-			<el-tab-pane label="通道码流" name="3">
-				<div>
-					<el-button :type="evsrc ? 'info' : 'primary'" @click="openEv()">开始</el-button>
-					<el-button :type="evsrc ? 'primary' : 'info'" :disabled="!evsrc" @click="closeEv()">停止</el-button>
-					<el-button type="defualt" @click="clearLog()">清空</el-button>
-					<el-button type="info" style="margin-left: 150px" @click="downloadLog()">下载报文</el-button>
-					<ul id="logContainer" ref="logContainer"></ul>
-				</div>
-			</el-tab-pane>
-		</el-tabs>
-	</el-dialog>
-</template>
-
-<script lang="ts">
-import { ElMessage } from 'element-plus';
-import api from '/@/api/device/modbus';
-import getOrigin from '/@/utils/origin';
-import TaskDialog from './taskDialog.vue';
-
-export default {
-	components: { TaskDialog },
-	data() {
-		return {
-			temp: {
-				title: '',
-				number: '',
-				templateNumber: '',
-				slaveId: '',
-				interval: '',
-			},
-			rules: {
-				title: [{ required: true, message: '请输入通道名称', trigger: 'blur' }],
-				number: [{ required: true, message: '请输入注册码', trigger: 'blur' }],
-				slaveId: [{ required: true, message: '请输入设备地址', trigger: 'blur' }],
-				templateNumber: [{ required: true, message: '请输入设备模板', trigger: 'change' }],
-			},
-			dialogVisible: false,
-			activeName: '1',
-			taskList: [],
-			listLoading: false,
-			total: 0,
-			tableKey: 0,
-			listQuery: {
-				page: 1,
-				size: 10,
-			},
-			evsrc: null as any,
-			count: 0,
-			templateOptions: [],
-			formatOptions: [],
-		};
-	},
-	watch: {
-		activeName: 'handleTabClick',
-	},
-
-	methods: {
-		open(row: any) {
-			this.temp = { ...row };
-			this.getDict();
-			this.dialogVisible = true;
-		},
-		downloadLog() {
-			window.open(getOrigin(import.meta.env.VITE_MODBUS_API) + '/debug/export_message?number=' + this.temp.number);
-		},
-		clsoeDialog() {
-			this.dialogVisible = false;
-			this.activeName = '1';
-			(this.$refs['dataForm'] as any).resetFields();
-			this.closeEv();
-		},
-		updateData() {
-			(this.$refs['dataForm'] as any).validate((valid: boolean) => {
-				if (valid) {
-					const tempData = Object.assign({}, this.temp);
-					api.channel.editDevice(tempData).then(() => {
-						this.$emit('getList');
-						this.clsoeDialog();
-						ElMessage.success('操作成功!');
-					});
-				}
-			});
-		},
-		// tab 切换
-		handleTabClick() {
-			this.closeEv(false);
-			if (this.activeName === '2') {
-				// 任务
-				this.getList();
-			} else if (this.activeName === '3') {
-				// 码流
-				// this.initEv()
-			}
-		},
-		handleFilter() {
-			this.listQuery.page = 1;
-			this.getList();
-		},
-		// 获取字典数据
-		getDict() {
-			api.getDict({ code: 'forwardFormat' }).then((data: any) => {
-				this.formatOptions = data.list || [];
-			});
-		},
-		// 获取任务list
-		getList() {
-			this.listLoading = true;
-			api.task
-				.getList(this.listQuery)
-				.then((res: any) => {
-					this.taskList = res.list || [];
-					this.total = res.Total;
-				})
-				.finally(() => {
-					this.listLoading = false;
-				});
-		},
-		handleDelete(row: any) {
-			this.$confirm('是否确认删除任务名称为"' + row.Job.title + '"的数据项?', '警告', {
-				confirmButtonText: '确定',
-				cancelButtonText: '取消',
-				type: 'warning',
-			})
-				.then(function () {
-					return api.task.deleteDeviceJob({ number: row.Job.number });
-				})
-				.then(() => {
-					this.handleFilter();
-					ElMessage.success('删除成功!');
-				})
-				.catch(function () { });
-		},
-		handleCreate() {
-			(this.$refs.taskDialog as any).openDialog({
-				dialogStatus: 'create',
-				deviceNumber: this.temp.number,
-			});
-		},
-		handleUpdate(row: any) {
-			(this.$refs.taskDialog as any).openDialog({
-				dialogStatus: 'update',
-				row,
-				deviceNumber: this.temp.number,
-			});
-		},
-		// 码流
-		initEv() {
-			if (this.evsrc) return;
-			// this.evsrc = new EventSource(`http://one.server.mydig.net/debug?number=${this.temp.number}`);
-			this.evsrc = new EventSource(`${getOrigin(import.meta.env.VITE_MODBUS_API)}/debug?number=${this.temp.number}`);
-			let that = this;
-			this.evsrc.onmessage = function (ev: any) {
-				try {
-					let obj = JSON.parse(ev.data);
-					if (obj.deviceId === that.temp.number) {
-						let color = obj.type === 'request' ? '#F56C6C' : '#409EFF';
-						let content = `${obj.type === 'request' ? '请求:' : '应答:'} ${obj.msg}`;
-						this.$refs.logContainer.insertAdjacentHTML('afterbegin', `<li style="color: ${color}">${content}</li>`);
-					}
-				} catch (_e) {
-					// @ts-ignore
-					// console.log('error', e);
-				}
-			};
-			// this.evsrc.onerror = function (_ev: any) {
-				// @ts-ignore
-				// console.log('readyState = ' + ev.currentTarget.readyState);
-			// };
-		},
-		openEv() {
-			(this.$refs.logContainer as any).insertAdjacentHTML('beforeEnd', `<li style="color: #000;">开始...</li>`);
-			this.initEv();
-		},
-		closeEv(log = true) {
-			this.evsrc && this.evsrc.close();
-			this.evsrc = null;
-			this.count = 0;
-			// this.clearLog()
-			if (log) {
-				(this.$refs.logContainer as any).insertAdjacentHTML('beforeEnd', `<li style="color: #000;">停止...</li>`);
-			}
-		},
-		// 清空码流
-		clearLog() {
-			(this.$refs.logContainer as any).innerHTML = '';
-		},
-		getCodingLabel(row: any) {
-			const item = this.formatOptions.find((item: any) => item.value === row.Job.encoding) as any;
-			return item.title;
-		},
-	},
-};
-</script>
-
-<style lang="scss" scoped>
-.filter-container {
-	margin-bottom: 10px;
-}
-
-.filter-item {
-	margin-right: 10px;
-}
-
-#logContainer {
-	height: 400px;
-	overflow: auto;
-	border: 1px solid #ddd;
-	padding: 10px;
-	padding-left: 20px;
-	border-radius: 8px;
-	margin-top: 10px;
-	word-wrap: break-word;
-	word-break: normal;
-	background-color: #f2f2f2;
-	line-height: 22px;
-}
-</style>

+ 0 - 80
src/views/iot/ice104/deviceTemplate/component/edit.vue

@@ -1,80 +0,0 @@
-<template>
-	<el-dialog title="添加设备通道" v-model="dialogVisible" width="600px" :before-close="clsoeDialog" :close-on-click-modal="false">
-		<el-form ref="dataForm" :rules="rules" :model="temp" label-position="left" label-width="120px" style="width: 90%; margin: 0 auto">
-			<el-form-item label="通道名称" prop="title">
-				<el-input v-model="temp.title" placeholder="请输入通道名称" />
-			</el-form-item>
-			<el-form-item label="注册码" prop="number">
-				<el-input v-model="temp.number" placeholder="请输入注册码" />
-			</el-form-item>
-			<el-form-item label="设备地址" prop="slaveId">
-				<el-input v-model.number="temp.slaveId" placeholder="请输入设备地址" />
-			</el-form-item>
-		</el-form>
-		<div slot="footer" class="dialog-footer">
-			<el-button @click="clsoeDialog()"> 取 消 </el-button>
-			<el-button type="primary" @click="createData()"> 保 存 </el-button>
-		</div>
-	</el-dialog>
-</template>
-<script lang="ts">
-import api from '/@/api/device/modbus';
-import { ElMessage } from 'element-plus';
-export default {
-	data() {
-		return {
-			temp: {
-				title: '',
-				number: '',
-				templateNumber: '',
-				slaveId: '',
-				interval: '',
-			},
-			rules: {
-				title: [{ required: true, message: '请输入通道名称', trigger: 'blur' }],
-				number: [{ required: true, message: '请输入注册码', trigger: 'blur' }],
-				slaveId: [{ required: true, message: '请输入设备地址', trigger: 'blur' }],
-			},
-			dialogVisible: false,
-			listLoading: false,
-			templateOptions: [],
-		};
-	},
-
-	methods: {
-		open() {
-			// this.getList();
-			this.dialogVisible = true;
-		},
-		clsoeDialog() {
-			(this.$refs.dataForm as any).resetFields();
-			this.dialogVisible = false;
-		},
-		// 获取模板数据
-		getList() {
-			this.listLoading = true;
-			api.channel
-				.getList({ page: 1, size: 50 })
-				.then((data: any) => {
-					this.templateOptions = data.list || [];
-				})
-				.finally(() => {
-					this.listLoading = false;
-				});
-		},
-		createData() {
-			(this.$refs['dataForm'] as any).validate((valid: boolean) => {
-				if (valid) {
-					api.channel.addDevice(this.temp).then(() => {
-						this.$emit('getList');
-						this.clsoeDialog();
-						ElMessage.success('操作成功!');
-					});
-				}
-			});
-		},
-	},
-};
-</script>
-
-<style lang="scss" scoped></style>

+ 0 - 139
src/views/iot/ice104/deviceTemplate/component/taskDialog.vue

@@ -1,139 +0,0 @@
-<template>
-	<el-dialog :title="textMap[dialogStatus]" v-model="dialogVisible" width="600px" :before-close="clsoeDialog" append-to-body :close-on-click-modal="false">
-		<el-form ref="dataForm" :rules="rules" :model="temp" label-position="left" label-width="120px" style="width: 400px; margin: 0 auto">
-			<el-form-item label="标题" prop="title">
-				<el-input v-model="temp.title" placeholder="请输入标题" />
-			</el-form-item>
-			<el-form-item label="调度周期" prop="interval">
-				<el-input v-model="temp.interval" placeholder="请输入调度周期" />
-			</el-form-item>
-			<el-form-item label="转发格式" prop="encoding">
-				<el-select v-model="temp.encoding" placeholder="请选择转发格式" style="width: 100%">
-					<el-option v-for="item in formatOptions" :key="item.value" :label="item.title" :value="item.value"> </el-option>
-				</el-select>
-				<!-- <el-input v-model="temp.encoding" placeholder="请输入转发格式"/> -->
-			</el-form-item>
-			<el-form-item label="mqtt主题" prop="publishTopic">
-				<el-input v-model="temp.publishTopic" placeholder="请输入mqtt主题" />
-			</el-form-item>
-			<el-form-item label="设备模板" prop="templateNumber">
-				<el-select v-model="temp.templateNumber" filterable placeholder="请选择设备模板" style="width: 100%">
-					<el-option v-for="item in templateOptions" :key="item.number" :label="item.title" :value="item.number"> </el-option>
-				</el-select>
-			</el-form-item>
-		</el-form>
-		<div slot="footer" class="dialog-footer">
-			<el-button @click="clsoeDialog"> 取 消 </el-button>
-			<el-button type="primary" @click="dialogStatus === 'create' ? createData() : updateData()"> 保 存 </el-button>
-		</div>
-	</el-dialog>
-</template>
-
-<script lang="ts">
-import api from '/@/api/device/modbus';
-import { ElMessage } from 'element-plus';
-
-export default {
-	components: {},
-	props: {
-		formatOptions: {
-			default: () => [],
-		},
-	},
-	data() {
-		return {
-			temp: {
-				title: '',
-				interval: '20s',
-				encoding: 'json',
-				publishTopic: '',
-				deviceNumber: '',
-				number: '',
-				templateNumber: '',
-			},
-			rules: {
-				title: [{ required: true, message: '请输入模板名称', trigger: 'change' }],
-				publishTopic: [{ required: true, message: '请输入mqtt主题', trigger: 'change' }],
-				mode: [{ required: true, message: '请选择模式', trigger: 'change' }],
-				templateNumber: [{ required: true, message: '请选择模式', trigger: 'change' }],
-			},
-			dialogVisible: false,
-			listLoading: false,
-			dialogStatus: '',
-			textMap: {
-				update: '任务详情',
-				create: '添加任务',
-			},
-			templateOptions: '',
-		};
-	},
-
-	methods: {
-		openDialog({ dialogStatus, row, deviceNumber }) {
-			this.dialogStatus = dialogStatus;
-			this.temp.deviceNumber = deviceNumber;
-			if (row) {
-				// this.temp = { ...row }
-				this.temp.number = row.Job.number;
-				this.temp.title = row.Job.title;
-				this.temp.interval = row.Job.interval;
-				this.temp.encoding = row.Job.encoding;
-				this.temp.publishTopic = row.Job.publishTopic;
-				this.temp.templateNumber = row?.Template?.number;
-			}
-			// this.getDict()
-			this.getTemplateList();
-			this.dialogVisible = true;
-		},
-		clsoeDialog() {
-			this.dialogVisible = false;
-			this.temp = {
-				title: '',
-				interval: '20s',
-				encoding: 'json',
-				publishTopic: '',
-				deviceNumber: '',
-				number: '',
-				templateNumber: '',
-			};
-			(this.$refs['dataForm'] as any).resetFields();
-		},
-		// 获取模板数据
-		getTemplateList() {
-			this.listLoading = true;
-			api.template
-				.getList({ page: 1, size: 50 })
-				.then((res: any) => {
-					this.templateOptions = res.list || [];
-				})
-				.finally(() => {
-					this.listLoading = false;
-				});
-		},
-		createData() {
-			(this.$refs['dataForm'] as any).validate((valid: boolean) => {
-				if (valid) {
-					api.task.addDeviceJob(this.temp).then(() => {
-						this.$emit('finish');
-						this.clsoeDialog();
-						ElMessage.success('操作成功!');
-					});
-				}
-			});
-		},
-		updateData() {
-			(this.$refs['dataForm'] as any).validate((valid: boolean) => {
-				if (valid) {
-					api.task.editDeviceJob(this.temp).then(() => {
-						this.$emit('finish');
-						this.clsoeDialog();
-						ElMessage.success('操作成功!');
-					});
-				}
-			});
-		},
-	},
-};
-</script>
-
-<style lang="scss" scoped></style>

+ 0 - 101
src/views/iot/ice104/deviceTemplate/index.vue

@@ -1,101 +0,0 @@
-<!--
- * @Author: vera_min vera_min@163.com
- * @Date: 2023-10-23 17:05:57
- * @LastEditors: vera_min vera_min@163.com
- * @LastEditTime: 2023-10-25 10:11:06
- * @FilePath: /sagoo-admin-ui/src/views/iot/ice104/index.vue
- * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
--->
-<template>
-	<div class="page page-full">
-		<el-card shadow="hover" class="page-full-part">
-			<div class="search">
-				<el-form :model="params" :inline="true" ref="queryRef">
-					<el-form-item label="设备模版名称" prop="title">
-						<el-input v-model="params.title" placeholder="请输入设备模版名称" clearablestyle="width: 240px" @keyup.enter.native="getList(1)" />
-					</el-form-item>
-					<el-form-item>
-						<el-button size="default" type="primary" class="ml10" @click="getList(1)">
-							<el-icon>
-								<ele-Search />
-							</el-icon>
-							查询
-						</el-button>
-						<el-button size="default" @click="resetQuery()">
-							<el-icon>
-								<ele-Refresh />
-							</el-icon>
-							重置
-						</el-button>
-						<el-button type="primary" @click="addOrEdit()" v-auth="'add'">
-							<el-icon>
-								<ele-FolderAdd />
-							</el-icon>
-							新增
-						</el-button>
-					</el-form-item>
-				</el-form>
-			</div>
-			<el-table :data="tableData" style="width: 100%" v-loading="loading">
-				<el-table-column type="index" label="序号" width="80" align="center" />
-				<el-table-column prop="title" label="名称"  align="center" show-overflow-tooltip></el-table-column>
-				<el-table-column prop="dtId" label="点位id"  align="center" show-overflow-tooltip></el-table-column>
-				<el-table-column prop="templateNumber" label="模版编号"  align="center" show-overflow-tooltip></el-table-column>
-				<el-table-column prop="dataAttribName" label="数据项编码"  align="center" show-overflow-tooltip></el-table-column>
-				<el-table-column prop="dataAddress" label="数据项点位"  align="center" show-overflow-tooltip></el-table-column>
-				<el-table-column prop="dataCoef" label="倍率"  align="center" show-overflow-tooltip></el-table-column>
-				<el-table-column fixed="right" label="操作" width="100" align="center">
-					<template #default="scope">
-						<el-button size="small" text type="primary" @click="viewDetail(scope.row)">编辑</el-button>
-						<el-button size="small" text type="info" @click="onDel(scope.row)">删除</el-button>
-					</template>
-				</el-table-column>
-			</el-table>
-			<pagination v-if="params.total" :total="params.total" v-model:page="params.page" v-model:limit="params.size" @pagination="getList()" />
-		</el-card>
-		<EditForm ref="editFormRef" @getList="getList(1)"></EditForm>
-		<detailForm ref="detailFormRef" @getList="getList()"></detailForm>
-	</div>
-</template>
-
-<script lang="ts" setup>
-import { ref } from 'vue';
-import EditForm from './component/edit.vue';
-import detailForm from './component/detail.vue';
-import api from '/@/api/ice104/index';
-import { ElMessageBox, ElMessage } from 'element-plus';
-import { useSearch } from '/@/hooks/useCommonIce104';
-
-const editFormRef = ref();
-const detailFormRef = ref();
-const queryRef = ref();
-
-const { params, tableData, getList, loading } = useSearch(api.deviceTemplate.getList, 'data', { title: '' });
-
-getList();
-
-const addOrEdit = async (row?: any) => {
-	editFormRef.value.open(row);
-};
-const viewDetail = async (row: any) => {
-	detailFormRef.value.open(row);
-};
-
-// 重置表单
-const resetQuery = () => {
-	queryRef.value.resetFields();
-	getList(1);
-};
-
-const onDel = (row: any) => {
-	ElMessageBox.confirm(`此操作将删除接口:“${row.title}”,是否继续?`, '提示', {
-		confirmButtonText: '确认',
-		cancelButtonText: '取消',
-		type: 'warning',
-	}).then(async () => {
-		await api.channel.deleteDevice({ number: row.number });
-		ElMessage.success('删除成功');
-		getList(1);
-	});
-};
-</script>

+ 133 - 0
src/views/iot/ice104/template/component/addOrEditTemplateTask.vue

@@ -0,0 +1,133 @@
+<!-- 添加或者修改设备 -->
+<template>
+	<el-dialog
+		:title="isEdit ? '修改模版点位' : '添加模版点位'"
+		v-model="dialogVisible"
+		width="600px"
+		:before-close="clsoeDialog"
+		:close-on-click-modal="false"
+	>
+		<el-form ref="formRef" :rules="formRules" :model="ruleForm" label-position="left" label-width="120px" style="width: 90%; margin: 0 auto">
+			<el-form-item label="点位名称" prop="title">
+				<el-input v-model="ruleForm.title" placeholder="请输入点位名称" />
+			</el-form-item>
+			<el-form-item label="数据项编码" prop="dataAttribName">
+				<el-input v-model="ruleForm.dataAttribName" placeholder="请输入数据项编码" />
+			</el-form-item>
+			<el-form-item label="数据项点位" prop="dataAddress">
+				<el-input type="number" :min="0" v-model.number="ruleForm.dataAddress" placeholder="请输入数据项点位" />
+			</el-form-item>
+			<el-form-item label="倍率" prop="dataCoef">
+				<el-input v-model="ruleForm.dataCoef" placeholder="请输入倍率" />
+			</el-form-item>
+
+		</el-form>
+		<template #footer>
+			<el-button @click="clsoeDialog()"> 取 消 </el-button>
+			<el-button :loading="btnLoading" type="primary" @click="submitData"> 保 存 </el-button>
+		</template>
+	</el-dialog>
+</template>
+<script lang="ts" setup>
+import { computed, reactive, ref, onMounted } from 'vue';
+import api from '/@/api/ice104/index';
+import { ElMessage } from 'element-plus';
+import { useSearch } from '/@/hooks/useCommonIce104';
+import apiDevice from '/@/api/device';
+import { useRoute } from 'vue-router';
+
+const { params, tableData, getList, loading } = useSearch(api.template.getAll, 'data', { title: '' });
+getList();
+
+const route = useRoute();
+
+const dialogVisible = ref(false);
+const btnLoading = ref(false);
+const emit = defineEmits(['updateList']);
+
+const formRef = ref();
+const ruleForm = ref({
+    dtId: 0,
+	title: '',
+	templateNumber: route.params && route.params.id,
+	dataAttribName: '',
+	dataAddress: 0,
+	DataCoef: ''
+})
+const isEdit = ref(false);
+
+const formRules = computed(() => ({
+	title: [{ required: true, trigger: 'blur', message: '请输入点位名称' }],
+	dataAttribName: [{ required: true, trigger: 'blur', message: '请输入数据项编码' }],
+	dataAddress: [{ required: true, trigger: 'blur', message: '请输入数据项点位' }],
+	dataCoef: [{ required: true, trigger: 'blur', message: '请输入倍率' }],
+}));
+const getRandom = (num:number) =>{
+    return Math.floor((Math.random()+Math.floor(Math.random()*9+1))*Math.pow(10,num-1));
+}
+const submitData = async () => {
+	formRef.value.validate((valid: boolean) => {
+		console.log(valid)
+		if (!valid) return
+		btnLoading.value = true
+		if (isEdit.value) {
+			// 修改
+			api.deviceTemplate.editItem({
+				...ruleForm.value,
+			})
+			.then(() => {
+				ElMessage({ type: 'success', message: '修改成功' })
+				emit('updateList')
+				closeDialog()
+			})
+			.finally(() => (btnLoading.value = false))
+		} else {
+			// 新增
+            ruleForm.value.dtId = getRandom(10);
+			api.deviceTemplate.addItem(ruleForm.value)
+			.then(() => {
+				ElMessage({ type: 'success', message: '添加成功' })
+				emit('updateList')
+				closeDialog()
+			})
+			.finally(() => (btnLoading.value = false))
+		}
+	})
+}
+
+/**
+ * 关闭弹窗
+ */
+const closeDialog = () => {
+  dialogVisible.value = false;
+  ruleForm.value = {
+    dtId: 0,
+	title: '',
+	templateNumber: route.params && route.params.id,
+	dataAttribName: '',
+	dataAddress: 0,
+	DataCoef: ''
+  }
+}
+
+
+const open = async (row: any) => {
+	dialogVisible.value = true
+	console.log(row)
+	if (row && row.dtId.toString()) {
+		row.DataCoef = row.dataCoef
+		ruleForm.value = row;
+		isEdit.value = true;
+	}else {
+		isEdit.value = false;
+	}
+}
+
+defineExpose({ open })
+</script>
+
+<style lang="scss" scoped>
+.width100 {
+	width: 100%;
+}
+</style>

+ 94 - 0
src/views/iot/ice104/template/component/editTemplateForm.vue

@@ -0,0 +1,94 @@
+<template>
+    <el-form ref="formRef" :rules="formRules" :model="ruleForm" label-position="left" label-width="120px" style="width: 70%;">
+        <el-form-item label="模版编码" prop="number">
+            <el-input disabled v-model="ruleForm.number" placeholder="请输入模版编码" />
+        </el-form-item>
+        <el-form-item label="名称">
+            <el-input v-model="ruleForm.title" placeholder="请输入名称" />
+        </el-form-item>
+        <el-form-item label="状态">
+            <el-switch
+                v-model="ruleForm.status"
+                inline-prompt
+                active-text="开"
+                inactive-text="关"
+                :active-value="1"
+                :inactive-value="0"
+                width="80"
+            />
+        </el-form-item>
+        
+        <el-form-item label="备注">
+            <el-input type="textarea" v-model="ruleForm.remarks" placeholder="请输入备注信息" />
+        </el-form-item>
+
+        <el-form-item>
+            <el-button type="primary" :loading="btnLoading" @click="submitData"> 保 存 </el-button>
+        </el-form-item>
+    </el-form>
+</template>
+<script lang="ts" setup>
+import { computed, reactive, ref, onMounted } from 'vue';
+import api from '/@/api/ice104/index';
+import { useI18n } from 'vue-i18n';
+import { ElMessage } from 'element-plus';
+import { useSearch } from '/@/hooks/useCommonIce104';
+import apiDevice from '/@/api/device';
+
+const { params, tableData, getList, loading } = useSearch(api.template.getAll, 'data', { title: '' });
+getList();
+
+const btnLoading = ref(false);
+
+const emit = defineEmits(['updateList']);
+const formRef = ref();
+const ruleForm = ref({
+    number: '',
+	title: '',
+	status: 1,
+	remarks: "",
+	mode: 0
+})
+
+const formRules = computed(() => ({
+	number: [{ required: true, trigger: 'change', message: '请输入设备编码' }],
+}));
+
+const submitData = async () => {
+	formRef.value.validate((valid: boolean) => {
+		console.log(valid)
+		if (!valid) return
+		btnLoading.value = true
+		// 修改
+        api.template.editItem({
+            ...ruleForm.value,
+        })
+        .then(() => {
+            ElMessage({ type: 'success', message: '修改成功' })
+            emit('updateList')
+        })
+        .finally(() => (btnLoading.value = false))
+	})
+}
+
+const open = async (row: any) => {
+	console.log(row)
+	if (row && row.number.toString()) {
+		console.log(row)
+		ruleForm.value = row;
+	}
+}
+
+// 页面加载时
+onMounted(() => {
+
+});
+
+defineExpose({ open })
+</script>
+
+<style lang="scss" scoped>
+.width100 {
+	width: 100%;
+}
+</style>

+ 103 - 0
src/views/iot/ice104/template/component/templateTaskTable.vue

@@ -0,0 +1,103 @@
+<template>
+    <div>
+        <el-form :model="params" :inline="true" ref="queryRef">
+            <el-form-item label="点位名称" prop="title">
+                <el-input v-model="params.title" placeholder="请输入点位名称" clearablestyle="width: 240px" @keyup.enter.native="getList()" />
+            </el-form-item>
+            <el-form-item>
+                <el-button size="default" type="primary" class="ml10" @click="getList()">
+                    <el-icon>
+                        <ele-Search />
+                    </el-icon>
+                    查询
+                </el-button>
+                <el-button size="default" @click="resetQuery()">
+                    <el-icon>
+                        <ele-Refresh />
+                    </el-icon>
+                    重置
+                </el-button>
+                <el-button type="primary" @click="addOrEdit()">
+                    <el-icon>
+                        <ele-FolderAdd />
+                    </el-icon>
+                    新增点位
+                </el-button>
+            </el-form-item>
+        </el-form>
+        <el-table :data="tableData" style="width: 100%" v-loading="loading">
+            <el-table-column type="index" label="序号" width="80" align="center" />
+            <el-table-column prop="title" label="点位名称"  align="center" show-overflow-tooltip></el-table-column>
+            <el-table-column prop="dataAttribName" label="数据项编码" min-width="120" align="center" show-overflow-tooltip></el-table-column>
+            <el-table-column prop="dataAddress" label="数据项点位" min-width="120" align="center" show-overflow-tooltip></el-table-column>
+            <el-table-column prop="dataCoef" label="倍率" min-width="120" align="center" show-overflow-tooltip></el-table-column>
+             <el-table-column fixed="right" label="操作" width="100" align="center">
+                <template #default="scope">
+                    <el-button size="small" text type="primary" @click="addOrEdit(scope.row)">修改</el-button>
+                    <el-button size="small" text type="info" @click="onDel(scope.row)">删除</el-button>
+                </template>
+            </el-table-column>
+        </el-table>
+        <pagination v-if="params.total" :total="params.total" v-model:page="params.pageNum" v-model:limit="params.pageSize" @pagination="getList()" />
+        <EditForm ref="editFormRef" @updateList="getList()"></EditForm>
+    </div>
+</template>
+<script lang="ts" setup>
+import { computed, reactive, ref, onMounted } from 'vue';
+import api from '/@/api/ice104/index';
+import { useI18n } from 'vue-i18n';
+import { ElMessageBox, ElMessage } from 'element-plus';
+import { useSearch } from '/@/hooks/useCommonIce104';
+import apiDevice from '/@/api/device';
+import EditForm from './addOrEditTemplateTask.vue';
+import { useRoute } from 'vue-router';
+
+const route = useRoute();
+
+const { params, tableData, getList, loading } = useSearch(api.deviceTemplate.getList, 'data', { title: '', templateNumber: route.params.id });
+
+const emit = defineEmits(['updateList']);
+const editFormRef = ref();
+const queryRef = ref();
+
+/**
+ * 新增设备任务
+ */
+const addOrEdit = async (row?: any) => {
+	editFormRef.value.open(row);
+};
+
+/**
+ * 单一删除
+ */
+const onDel = (row: any) => {
+	ElMessageBox.confirm(`此操作将删除接口:“${row.title}”,是否继续?`, '提示', {
+		confirmButtonText: '确认',
+		cancelButtonText: '取消',
+		type: 'warning',
+	}).then(async () => {
+		await api.deviceTemplate.deleteItem({number: row.number});
+		ElMessage.success('删除成功');
+		getList();
+	});
+};
+
+// 重置表单
+const resetQuery = () => {
+	queryRef.value.resetFields();
+	getList();
+};
+
+// 页面加载时
+onMounted(() => {
+    getList();
+});
+
+// defineExpose({ open })
+</script>
+
+<style lang="scss" scoped>
+.width100 {
+	width: 100%;
+}
+</style>

+ 97 - 0
src/views/iot/ice104/template/detail.vue

@@ -0,0 +1,97 @@
+<!--
+ * @Author: vera_min vera_min@163.com
+ * @Date: 2023-10-23 17:05:57
+ * @LastEditors: vera_min vera_min@163.com
+ * @LastEditTime: 2023-10-25 10:11:06
+ * @FilePath: /sagoo-admin-ui/src/views/iot/ice104/index.vue
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+-->
+<template>
+	<div class="page page-full">
+		<el-card shadow="hover" class="page-full-part">
+			<el-tabs
+				v-model="activeName"
+				@tab-click="handleClick"
+			>
+				<el-tab-pane label="模版详情" name="1">
+					<EditTemplateForm ref="editFormRef" />
+				</el-tab-pane>
+				<el-tab-pane label="模版点位" name="2">
+					<TemplateTaskTable />
+				</el-tab-pane>
+			</el-tabs>
+		</el-card>
+	</div>
+</template>
+
+<script lang="ts" setup>
+import { ref, onMounted } from 'vue';
+import EditTemplateForm from './component/editTemplateForm.vue';
+import TemplateTaskTable from './component/templateTaskTable.vue';
+
+import api from '/@/api/ice104/index';
+import { ElMessageBox, ElMessage } from 'element-plus';
+import { useSearch } from '/@/hooks/useCommonIce104';
+import { useRoute } from 'vue-router';
+import type { TabsPaneContext } from 'element-plus'
+
+const route = useRoute();
+const editFormRef = ref();
+const detailFormData = ref({});
+const queryRef = ref();
+
+const activeName = ref('1')
+
+
+
+const { params, tableData, getList, loading } = useSearch(api.device.getList, 'data', { title: '' });
+
+getList();
+
+
+
+const handleClick = (tab: TabsPaneContext, event: Event) => {
+  console.log(tab, event)
+}
+
+const addOrEdit = async (row?: any) => {
+	
+};
+
+// 重置表单
+const resetQuery = () => {
+	queryRef.value.resetFields();
+	getList();
+};
+
+const onDel = (row: any) => {
+	ElMessageBox.confirm(`此操作将删除接口:“${row.title}”,是否继续?`, '提示', {
+		confirmButtonText: '确认',
+		cancelButtonText: '取消',
+		type: 'warning',
+	}).then(async () => {
+		await api.device.deleteItem({number: row.number});
+		ElMessage.success('删除成功');
+		getList();
+	});
+};
+
+/**
+ * 获取设备详情
+ */
+const initTemplateInfo = async () => {
+	const res = await api.template.detailItem(route.params && route.params.id)
+	console.log(res)
+	detailFormData.value = res.data;
+	editFormRef.value.open(res.data);
+}
+// 页面加载时
+onMounted(() => {
+	// const id: = route.params && route.params.id;
+	// console.log(id)
+	initTemplateInfo()
+});
+	
+
+
+</script>

+ 15 - 2
src/views/iot/ice104/template/index.vue

@@ -31,7 +31,7 @@
 							<el-icon>
 								<ele-FolderAdd />
 							</el-icon>
-							新增
+							新增模版
 						</el-button>
 					</el-form-item>
 				</el-form>
@@ -49,7 +49,7 @@
 				<el-table-column prop="remarks" label="备注" align="center" show-overflow-tooltip></el-table-column>
 				<el-table-column fixed="right" label="操作" width="100" align="center">
 					<template #default="scope">
-						<el-button size="small" text type="primary" @click="addOrEdit(scope.row)">编辑</el-button>
+						<el-button size="small" text type="primary" @click="toDetailPage(scope.row)">详情</el-button>
 						<el-button size="small" text type="info" @click="onDel(scope.row)">删除</el-button>
 					</template>
 				</el-table-column>
@@ -66,6 +66,9 @@ import EditForm from './component/edit.vue';
 import api from '/@/api/ice104/index';
 import { ElMessageBox, ElMessage } from 'element-plus';
 import { useSearch } from '/@/hooks/useCommonIce104';
+import { useRouter } from 'vue-router';
+
+const router = useRouter();
 
 const editFormRef = ref();
 const detailFormRef = ref();
@@ -78,6 +81,16 @@ getList();
 const addOrEdit = async (row?: any) => {
 	editFormRef.value.open(row);
 };
+/**
+ * 去往设备详情页面
+ */
+const toDetailPage = async (row?: any) => {
+	// editFormRef.value.open(row);
+	// router.push('/monitor/notice');
+	
+	// router.push(`/iotmanager/network/tunnel/edit/${route.params && route.params.id}`)
+	router.push(`/ice104/template/detail/${row.number}`)
+};
 
 // 重置表单
 const resetQuery = () => {