Browse Source

Merge branch 'master' of http://git.mydig.net/Sagoo-Cloud/sagoo-admin-ui

vera_min 2 years ago
parent
commit
34783af6fc

+ 5 - 1
src/api/device/index.ts

@@ -79,12 +79,16 @@ export default {
   tree: {
     getList: (params: object) => get('/product/device_tree/list', params),
     add: (params: object) => post('/product/device_tree/info/add', params),
-    edit: (params: object) => post('/product/device_tree/info/edit', params),
+    edit: (params: object) => put('/product/device_tree/info/edit', params),
     detail: (params: object) => get('/product/device_tree/info/detail', params),
     delete: (params: object) => del('/product/device_tree/info/del', params),
+    statistic: (params: object) => get('/envirotronics/device_tree/statistic', params),
+    record: (params: object) => get('/envirotronics/device_tree/record', params),
+    param: (params: object) => get('/envirotronics/device_tree/param', params),
   },
   device: {
     getList: (params: object) => get('/product/device/bind_list', params),
+    allList: (params: object) => get('/product/device/list', params),
     getSubList: (params: object) => get('/product/device/sub_list', params),
     mutipleBind: (data: object) => post('/product/device/bind_sub', data),
     mutipleUnbind: (data: object) => post('/product/device/unbind_sub', data),

+ 358 - 0
src/views/heating/monitor/realTimeStatistics/index.vue

@@ -0,0 +1,358 @@
+<template>
+  <div class="system-dic-container" style="background: #fff">
+    <LrLayout width="260px">
+      <template #left>
+        <div class="zl-tree-search">
+          <div class="flex zl-tree-search__filter">
+            <el-input v-model.trim="searchVal" placeholder="搜索">
+              <template #prefix>
+                <el-icon><Search /></el-icon>
+                <!-- <i class="iconfont icon-search" /> -->
+              </template>
+            </el-input>
+          </div>
+        </div>
+        <div class="zl-tree-search-scroll">
+          <el-scrollbar ref="zlTreeSearchScroll" height="100%" v-loading="treeLoading">
+            <el-tree
+              ref="zlTreeSearchRef"
+              v-if="!treeLoading"
+              :data="treeData"
+              :props="{
+                children: 'children',
+                label: 'name'
+              }"
+              :filter-node-method="filterNode"
+              :default-expand-all="true"
+              :node-key="'id'"
+              highlight-current
+              @node-click="nodeClick">
+              <template #default="{ node, data }">
+                <div class="custom-tree-node">
+                  <span class="tree-label">
+                    <i class="iconfont icon-wenjianjia icon-wjj mr8" />{{ node.label }}
+                  </span>
+                  <!-- <span class="tree-options" >
+                    <slot name="operate" :data="data">
+                      <el-dropdown @command="command => operateCmd(command, data)">
+                        <el-icon>
+                          <More></More>
+                        </el-icon>
+                        <template #dropdown>
+                          <el-dropdown-menu>
+                            <el-dropdown-item command="add">
+                              <el-icon>
+                                <Plus></Plus>
+                              </el-icon>
+                            </el-dropdown-item>
+                            <el-dropdown-item command="edit">
+                              <el-icon>
+                                <Edit></Edit>
+                              </el-icon>
+                            </el-dropdown-item>
+                            <el-dropdown-item command="delete">
+                              <el-icon>
+                                <Delete></Delete>
+                              </el-icon>
+                            </el-dropdown-item>
+                          </el-dropdown-menu>
+                        </template>
+                      </el-dropdown>
+                    </slot>
+                  </span> -->
+                </div>
+              </template>
+            </el-tree>
+          </el-scrollbar>
+        </div>
+      </template>
+      <template #right>
+        <!-- max-height="30vh" -->
+        <el-table :data="tableData.data" v-loading="tableData.loading" style="width: 100%; padding: 12px" >
+          <el-table-column :label="item.name + `${item.unit ? `(${item.unit})` : ''}`" :prop="item.key" v-for="(item, index) in tableData
+          .columns" :key="index" :show-overflow-tooltip="true" />
+        </el-table>
+
+        <div  style="text-align: center;padding: 28px;" v-if="(tableData.data.length)">暂无数据</div>
+      </template>
+    </LrLayout>
+
+  </div>
+</template>
+
+<script lang="ts">
+import { toRefs, reactive, onMounted, ref, defineComponent, getCurrentInstance } from 'vue';
+import { ElMessageBox, ElMessage, FormInstance } from 'element-plus';
+import api from '/@/api/device';
+import LrLayout from '/@/components/lrLayout/index.vue'
+import { Fold, Expand, More, Plus, Edit, Delete, Search } from '@element-plus/icons-vue'
+
+// 定义接口来定义对象的类型
+interface TableDataRow {
+  id: number;
+  name: string;
+  deviceType: string;
+  status: number;
+  desc: string;
+  createBy: string;
+}
+interface TableDataState {
+  ids: number[];
+  tableData: {
+    data: Array<TableDataRow>;
+      columns: Array<any>;
+    total: number;
+    loading: boolean;
+    param: {
+      pageNum: number;
+      pageSize: number;
+      name: string;
+      status: string;
+    };
+  };
+  treeData: any[]
+  deviceList: any[]
+  treeLoading: boolean
+  tabName: string
+  searchVal: string
+  treeDetail: any
+  unitData: any
+  ruleForm: any
+}
+
+export default defineComponent({
+  name: 'realTimeStatistics',
+  components: { LrLayout, Fold, Expand, More, Plus, Edit, Delete, Search },
+  setup() {
+    const { proxy } = getCurrentInstance() as any;
+    const addOrUpdateRef = ref();
+    const queryRef = ref();
+    const state = reactive<TableDataState>({
+      ids: [],
+      tableData: {
+        data: [],
+        columns: [],
+        total: 0,
+        loading: false,
+        param: {
+          pageNum: 1,
+          pageSize: 10,
+          status: '',
+          name: ''
+        },
+      },
+      treeData: [],
+      treeLoading: false,
+      tabName: '1',
+      searchVal: '',
+      treeDetail: {},
+      deviceList: [],
+			unitData: [
+				{ label: '秒', value: 1 },
+				{ label: '分', value: 2 },
+				{ label: '时', value: 3 },
+				{ label: '天', value: 4 },
+			],
+      ruleForm: {
+        duration: '',
+        timeUnit: '',
+        template: 'default',
+        category: 'default'
+      }
+    });
+    
+    // const { tree_types, tree_category } = proxy.useDict('tree_types', 'tree_category');
+    // 初始化表格数据
+    const initTableData = () => {
+      getTreeList();
+
+      nodeClick({ infoId:  1 })
+    };
+    const getTreeList = () => {
+      state.treeLoading = true;
+      api.tree.getList({}).then((res: any) => {
+        state.treeData = res.list;
+      }).finally(() => (state.treeLoading = false));
+    }
+    // 页面加载时
+    onMounted(() => {
+      initTableData();
+    });
+    /** 重置按钮操作 */
+    const resetQuery = (formEl: FormInstance | undefined) => {
+      if (!formEl) return;
+      formEl.resetFields();
+    };
+    // 多选框选中数据
+    const handleSelectionChange = (selection: TableDataRow[]) => {
+      state.ids = selection.map((item) => item.id);
+    };
+    const nodeClick = (data: any) => {
+      api.tree.statistic({ infoId: data.infoId })
+        .then((res: any) => {
+          state.tableData.columns = []
+          state.tableData.data = []
+          if (res.name) {
+            let header = res.header || []
+            let list = res.list || []
+            state.tableData.columns = header
+            state.tableData.data = list.map((item: any) => {
+              return {
+                time: item.time,
+                ...item.data
+              }
+            })
+            state.tableData.columns.unshift({ name: '时间', key: 'time' })
+          }
+          // state.treeDetail = res.data || {}
+        })
+    }
+    const onSaveTime = () => {
+      if (!state.treeDetail.id) {
+        ElMessage.warning('请选择节点树')
+        return
+      }
+      //修改
+      api.tree.edit({
+        ...state.treeDetail,
+        template: state.ruleForm.template,
+        category: state.ruleForm.category,
+        deviceKey: state.ruleForm.deviceKey,
+      }).then(() => {
+        ElMessage.success('修改成功');
+      });
+    }
+
+    const operateCmd = (type: string, data: any) => {
+      switch(type) {
+        case 'add':
+          addOrUpdateRef.value.openDialog(type, data)
+          break
+        case 'edit':
+          addOrUpdateRef.value.openDialog(type, data)
+          break
+        case 'delete':
+          ElMessageBox.confirm('是否删除该设备树', '提示', {
+            confirmButtonText: '确认',
+            cancelButtonText: '取消',
+            type: 'warning',
+          })
+            .then(() => {
+              api.tree.delete({ id: data.infoId }).then(() => {
+                ElMessage.success('删除成功');
+                getTreeList();
+              });
+            })
+            .catch(() => { });
+          break
+      }
+    }
+    return {
+      addOrUpdateRef,
+      queryRef,
+      resetQuery,
+      handleSelectionChange,
+      operateCmd,
+      getTreeList,
+      nodeClick,
+      ...toRefs(state),
+      onSaveTime
+    };
+  },
+});
+</script>
+
+<style scoped lang="scss">
+.zl-tree-search {
+  margin: 0 12px 0 0;
+  background-color: #fff;
+  border-radius: 4px;
+  &__filter {
+    padding: 4px 10px;
+    border-bottom: 1px solid #EAEAEA;
+  }
+}
+.zl-tree-search__filter :deep .el-input__wrapper {
+  box-shadow: none;
+}
+
+.custom-tree-node {
+  width: 100%;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  font-size: 14px;
+  padding-right: 8px;
+  &:hover {
+    .tree-options {
+      display: block;
+    }
+  }
+}
+:deep(.column-right) {
+  padding: 0;
+  background-color: transparent;
+}
+.icon-wjj {
+  font-size: 12px;
+  color: #C4C6CF;
+}
+
+table {
+  width: 100%;
+	border-collapse: collapse;
+	text-indent: initial;
+	border-spacing: 2px;
+}
+tbody {
+	box-sizing: border-box;
+	display: table-row-group;
+	vertical-align: middle;
+	border-color: inherit;
+}
+
+tr {
+	display: table-row;
+	vertical-align: inherit;
+	border-color: inherit;
+}
+.ant-descriptions-view {
+	width: 100%;
+	overflow: hidden;
+	border-radius: 4px;
+}
+.ant-descriptions-view {
+	border: 1px solid #e8e8e8;
+}
+.ant-descriptions-view table {
+	width: 100%;
+	table-layout: fixed;
+}
+.ant-descriptions-view > table {
+	table-layout: auto;
+}
+.ant-descriptions-row {
+	border-bottom: 1px solid #e8e8e8;
+}
+.ant-descriptions-item-label {
+	color: rgba(0, 0, 0, 0.85);
+	font-weight: 400;
+	font-size: 14px;
+	line-height: 1.5;
+}
+.ant-descriptions-item-label {
+	padding: 16px;
+	border-right: 1px solid #e8e8e8;
+}
+.ant-descriptions-item-label {
+	background-color: #fafafa;
+}
+.ant-descriptions-item-content {
+	padding: 16px;
+	border-right: 1px solid #e8e8e8;
+	display: table-cell;
+	color: rgba(0, 0, 0, 0.65);
+	font-size: 14px;
+	line-height: 1.5;
+}
+</style>

+ 177 - 0
src/views/heating/monitor/statisticsDetail/index.vue

@@ -0,0 +1,177 @@
+<template>
+  <div class="system-dic-container">
+    <el-card shadow="hover">
+      <div class="system-user-search mb15">
+        <el-form :model="tableData.param" ref="queryRef" :inline="true" label-width="68px">
+          <el-form-item label="区域" prop="area" style="width: 200px;">
+            <el-select v-model="tableData.param.area" placeholder="区域" clearable size="default" style="width: 200px">
+              <el-option v-for="item in areaOptions" :key="item" :label="item" :value="item" />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="管道序号" prop="name" style="width: 200px;">
+            <el-select v-model="tableData.param.name" placeholder="管道序号" clearable size="default" style="width: 200px">
+              <el-option v-for="item in nameOptions" :key="item" :label="item" :value="item" />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="输送单位" prop="company" style="width: 200px;">
+            <el-select v-model="tableData.param.company" placeholder="输送单位" clearable size="default" style="width: 200px">
+              <el-option v-for="item in companyOptions" :key="item" :label="item" :value="item" />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="创建时间" prop="dateRange">
+            <el-date-picker v-model="tableData.param.dateRange" size="default" style="width: 240px" value-format="YYYY-MM-DD" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
+          </el-form-item>
+          <el-form-item label="类型" prop="types" style="width: 200px;">
+            <el-select v-model="tableData.param.types" filterable clearable placeholder="请选择类型" style="width: 200px">
+              <el-option v-for="dict in tree_types_2" :key="dict.value" :label="dict.label" :value="dict.value"> </el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item>
+            <el-button size="default" type="primary" class="ml10" @click="typeList">
+              <el-icon>
+                <ele-Search />
+              </el-icon>
+              查询
+            </el-button>
+            <el-button size="default" @click="resetQuery(queryRef)">
+              <el-icon>
+                <ele-Refresh />
+              </el-icon>
+              重置
+            </el-button>
+          </el-form-item>
+        </el-form>
+      </div>
+      <el-table :data="tableData.data" style="width: 100%" @selection-change="handleSelectionChange" v-loading="tableData.loading">
+        <el-table-column label="管道" prop="name" :show-overflow-tooltip="true" />
+        <el-table-column label="区域名称" prop="area" :show-overflow-tooltip="true"/>
+        <el-table-column label="用量(m³)" prop="value" :show-overflow-tooltip="true" />
+        <el-table-column label="输送单位" prop="company" :show-overflow-tooltip="true" />
+        <el-table-column label="类型" prop="types" :show-overflow-tooltip="true"/>
+        <el-table-column label="输送时间" prop="datetime" align="center" width="180" ></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="typeList" />
+    </el-card>
+  </div>
+</template>
+
+<script lang="ts">
+import { toRefs, reactive, onMounted, ref, defineComponent, getCurrentInstance } from 'vue';
+import { ElMessageBox, ElMessage, FormInstance } from 'element-plus';
+import api from '/@/api/device';
+
+// 定义接口来定义对象的类型
+interface TableDataRow {
+  id: number;
+  name: string;
+  key: string;
+  status: number;
+  desc: string;
+  createBy: string;
+}
+interface TableDataState {
+  ids: number[];
+  tableData: {
+    data: Array<TableDataRow>;
+    total: number;
+    loading: boolean;
+    param: {
+      pageNum: number;
+      pageSize: number;
+      name: string;
+      area: string;
+      company: string;
+      types: string;
+      dateRange: string[];
+    };
+  };
+  nameOptions: string[];
+  areaOptions: string[];
+  companyOptions: string[];
+}
+
+export default defineComponent({
+  name: 'deviceInstance',
+  setup() {
+    const { proxy } = getCurrentInstance() as any;
+    const queryRef = ref();
+    const state = reactive<TableDataState>({
+      ids: [],
+      tableData: {
+        data: [],
+        total: 0,
+        loading: false,
+        param: {
+          pageNum: 1,
+          pageSize: 10,
+          name: '',
+          area: '',
+          company: '',
+          types: '',
+          dateRange: [],
+        },
+      },
+      nameOptions: [],
+      areaOptions: [],
+      companyOptions: []
+    });
+    const { tree_types_2 } = proxy.useDict('tree_types_2');
+    // 初始化表格数据
+    const initTableData = () => {
+      typeList();
+    };
+    const initParam = () => {
+      api.tree.param(state.tableData.param).then((res: any) => {
+        state.nameOptions = res.name || []
+        state.areaOptions = res.area || []
+        state.companyOptions = res.company || []
+      })
+    }
+    const typeList = () => {
+      state.tableData.loading = true;
+      api.tree.record(state.tableData.param).then((res: any) => {
+        state.tableData.data = res.list;
+        state.tableData.total = res.total;
+      }).finally(() => (state.tableData.loading = false));
+    };
+
+    // 页面加载时
+    onMounted(() => {
+      initTableData();
+      initParam()
+    });
+    /** 重置按钮操作 */
+    const resetQuery = (formEl: FormInstance | undefined) => {
+      if (!formEl) return;
+      formEl.resetFields();
+      typeList();
+    };
+    // 多选框选中数据
+    const handleSelectionChange = (selection: TableDataRow[]) => {
+      state.ids = selection.map((item) => item.id);
+    };
+    const onActionStatus = (item: TableDataRow[]) => {
+      if (item.status == 0) {
+        api.instance.devdeploy({ id: item.id }).then((res: any) => {
+          typeList();
+          ElMessage.success(res.message || '操作成功');
+        });
+      } else {
+        api.instance.devundeploy({ id: item.id }).then((res: any) => {
+          typeList();
+          ElMessage.success(res.message || '操作成功');
+        });
+      }
+    }
+    return {
+      queryRef,
+      onActionStatus,
+      typeList,
+      resetQuery,
+      handleSelectionChange,
+      tree_types_2,
+      ...toRefs(state),
+    };
+  },
+});
+</script>

+ 29 - 1
src/views/iot/device-tree/tree/component/edit.vue

@@ -58,6 +58,24 @@
 							<el-input v-model="ruleForm.deviceKey" placeholder="请输入设备标识" clearable></el-input>
 						</el-form-item>
 					</el-col>
+					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
+						<el-form-item label="设备所属区域" prop="area">
+							<el-input v-model="ruleForm.area" placeholder="请输入设备所属区域" clearable></el-input>
+						</el-form-item>
+					</el-col>
+					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
+						<el-form-item label="所属公司" prop="company">
+							<el-input v-model="ruleForm.company" placeholder="请输入所属公司" clearable></el-input>
+						</el-form-item>
+					</el-col>
+					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
+						<el-form-item label="类型" prop="types">
+							<el-select v-model="ruleForm.types" filterable clearable placeholder="请选择类型" class="w-35">
+								<el-option v-for="dict in tree_types_2" :key="dict.value" :label="dict.label" :value="dict.value"> </el-option>
+							</el-select>
+							<!-- <el-input v-model="ruleForm.types" placeholder="请输入所属公司" clearable></el-input> -->
+						</el-form-item>
+					</el-col>
 				</el-row>
 			</el-form>
 			<template #footer>
@@ -71,7 +89,7 @@
 </template>
 
 <script lang="ts">
-import { reactive, toRefs, defineComponent, ref, unref } from 'vue';
+import { reactive, toRefs, defineComponent, ref, unref, getCurrentInstance } from 'vue';
 import api from '/@/api/device';
 import { phoneValidate } from '/@/utils/validator';
 import { ElMessage } from 'element-plus';
@@ -85,6 +103,9 @@ interface RuleFormState {
 	contact: string;
 	phone: string;
 	deviceKey: string;
+	area: string;
+	company: string;
+	types: string;
 	parentId: string;
 	startDate: string;
 	endDate: string;
@@ -98,6 +119,9 @@ const baseForm: RuleFormState = {
 	contact: '',
 	phone: '',
 	deviceKey: '',
+	area: '',
+	company: '',
+	types: '',
 	parentId: '',
 	startDate: '',
 	endDate: '',
@@ -106,6 +130,7 @@ const baseForm: RuleFormState = {
 export default defineComponent({
 	name: 'deviceEditCate',
 	setup(prop, { emit }) {
+    const { proxy } = getCurrentInstance() as any;
 		const formRef = ref<HTMLElement | null>(null);
 		const state = reactive({
 			isShowDialog: false,
@@ -118,6 +143,8 @@ export default defineComponent({
 			},
 		});
 
+    const { tree_types_2 } = proxy.useDict('tree_types_2');
+
 		// 打开弹窗
 		const openDialog = (type: string, row?: any) => {
 			resetForm();
@@ -178,6 +205,7 @@ export default defineComponent({
 			onCancel,
 			onSubmit,
 			formRef,
+			tree_types_2,
 			...toRefs(state),
 		};
 	},

+ 0 - 622
src/views/iot/device-tree/tree/detail.vue

@@ -1,622 +0,0 @@
-<template>
-	<div class="system-dic-container">
-		<div class="content">
-			<div class="cont_box">
-				<div class="title">产品:{{ detail.name }}</div>
-				<div class="pro-status"><span :class="developer_status == 1 ? 'on' : 'off'"></span>{{ developer_status == 1 ? '已发布' : '未发布' }}</div>
-
-				<div class="pro-option" @click="CkOption"> {{ developer_status == 1 ? '停用' : '启用' }}</div>
-			</div>
-		</div>
-
-		<div class="content-box">
-			<el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
-				<el-tab-pane label="产品信息" name="1">
-					<div class="pro-box">
-						<div class="protitle">产品信息</div>
-						<el-button type="" :icon="Edit" class="buttonedit" @click="onOpenEditDic(detail)">编辑</el-button>
-					</div>
-
-					<div class="ant-descriptions-view">
-						<table>
-							<tbody>
-								<tr class="ant-descriptions-row">
-									<th class="ant-descriptions-item-label ant-descriptions-item-colon">产品标识</th>
-									<td class="ant-descriptions-item-content" colspan="1">{{ detail.key }}</td>
-									<th class="ant-descriptions-item-label ant-descriptions-item-colon">所属品类</th>
-									<td class="ant-descriptions-item-content" colspan="1">{{ detail.categoryName }}</td>
-									<!-- <th class="ant-descriptions-item-label ant-descriptions-item-colon">所属部门</th>
-									<td class="ant-descriptions-item-content" colspan="1">{{ detail.deptName }}</td> -->
-									<th class="ant-descriptions-item-label ant-descriptions-item-colon">设备类型</th>
-									<td class="ant-descriptions-item-content" colspan="1">{{ detail.deviceType }}</td>
-								</tr>
-								<tr class="ant-descriptions-row">
-									<th class="ant-descriptions-item-label ant-descriptions-item-colon">消息协议</th>
-									<td class="ant-descriptions-item-content" colspan="1">{{ detail.messageProtocol }}</td>
-									<th class="ant-descriptions-item-label ant-descriptions-item-colon">链接协议</th>
-									<td class="ant-descriptions-item-content" colspan="1">{{ detail.transportProtocol }}</td>
-
-								</tr>
-								<tr class="ant-descriptions-row">
-									<th class="ant-descriptions-item-label ant-descriptions-item-colon">描述</th>
-									<td class="ant-descriptions-item-content" colspan="5">{{ detail.desc }}</td>
-								</tr>
-							</tbody>
-						</table>
-					</div>
-				</el-tab-pane>
-				<el-tab-pane label="物模型" name="2">
-					<div class="wu-box">
-						<el-tabs type="border-card" v-model="activetab" @tab-click="wuhandleClick">
-							<el-tab-pane label="属性定义" name="attr">
-								<div class="wu-title">
-									<div class="title">属性定义</div>
-									<div><el-button type="primary" @click="onOpenEditAttr()">添加</el-button></div>
-								</div>
-
-								<el-table style="width: 100%" :data="tableData.data" v-if="activetab == 'attr'">
-									<el-table-column label="属性标识" align="center" prop="key" />
-									<el-table-column label="属性名称" prop="name" :show-overflow-tooltip="true" />
-									<el-table-column prop="valueType" label="数据类型" width="100" align="center">
-										<template #default="scope">
-											<span>{{ scope.row.valueType.type }}</span>
-										</template>
-									</el-table-column>
-									<el-table-column prop="decimals" label="精度" width="60" align="center">
-										<template #default="scope">
-											<span>{{ scope.row.valueType.decimals }}</span>
-										</template>
-									</el-table-column>
-									<el-table-column prop="unit" label="单位" width="60" align="center">
-										<template #default="scope">
-											<span>{{ scope.row.valueType.unit }}</span>
-										</template>
-									</el-table-column>
-									<el-table-column prop="accessMode" label="是否只读" 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>
-										</template>
-									</el-table-column>
-									<el-table-column label="说明" prop="desc" :show-overflow-tooltip="true" />
-									<el-table-column label="操作" width="300" align="center" fixed="right">
-										<template #default="scope">
-											<el-button size="small" text type="warning" @click="onEditAttr(scope.row)">修改</el-button>
-											<el-button size="small" text type="danger" @click="onRowDel(scope.row.key, 'attr')">删除</el-button>
-										</template>
-									</el-table-column>
-								</el-table>
-							</el-tab-pane>
-							<el-tab-pane label="功能定义" name="fun">
-								<div class="wu-title">
-									<div class="title">功能定义</div>
-									<div><el-button type="primary" @click="onOpenEditFun()">添加</el-button></div>
-								</div>
-
-								<el-table style="width: 100%" :data="tableData.data" v-if="activetab == 'fun'">
-									<el-table-column label="功能标识" align="center" prop="key" />
-									<el-table-column label="名称" prop="name" :show-overflow-tooltip="true" />
-
-									<el-table-column label="描述" prop="desc" :show-overflow-tooltip="true" />
-									<el-table-column label="操作" width="300" align="center" fixed="right">
-										<template #default="scope">
-											<el-button size="small" text type="warning" @click="onEditFun(scope.row)">修改</el-button>
-											<el-button size="small" text type="danger" @click="onRowDel(scope.row.key, 'fun')">删除</el-button>
-										</template>
-									</el-table-column>
-								</el-table>
-							</el-tab-pane>
-							<el-tab-pane label="事件定义" name="event">
-								<div class="wu-title">
-									<div class="title">事件定义</div>
-									<div><el-button type="primary" @click="onOpenEditEvent()">添加</el-button></div>
-								</div>
-
-								<el-table style="width: 100%" :data="tableData.data" v-if="activetab == 'event'">
-									<el-table-column label="事件标识" align="center" prop="key" />
-									<el-table-column label="名称" prop="name" :show-overflow-tooltip="true" />
-									<el-table-column prop="level" label="事件级别" width="120" align="center">
-										<template #default="scope">
-											<el-tag type="primary" 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>
-										</template>
-									</el-table-column>
-									<el-table-column label="描述" prop="desc" :show-overflow-tooltip="true" />
-
-									<el-table-column label="操作" width="300" align="center" fixed="right">
-										<template #default="scope">
-											<el-button size="small" text type="warning" @click="onEditEvent(scope.row)">修改</el-button>
-											<el-button size="small" text type="danger" @click="onRowDel(scope.row.key, 'event')">删除</el-button>
-										</template>
-									</el-table-column>
-								</el-table>
-							</el-tab-pane>
-							<el-tab-pane label="标签定义" name="tab">
-								<div class="wu-title">
-									<div class="title">标签定义</div>
-									<div><el-button type="primary" @click="onOpenEditTab()">添加</el-button></div>
-								</div>
-
-								<el-table style="width: 100%" :data="tableData.data" v-if="activetab == 'tab'">
-									<el-table-column label="属性标识" align="center" prop="key" />
-									<el-table-column label="属性名称" prop="name" :show-overflow-tooltip="true" />
-									<el-table-column prop="valueType" label="数据类型" 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">
-										<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>
-										</template>
-									</el-table-column>
-									<el-table-column label="描述" prop="desc" :show-overflow-tooltip="true" />
-									<el-table-column label="操作" width="300" align="center" fixed="right">
-										<template #default="scope">
-											<el-button size="small" text type="warning" @click="onEditTag(scope.row)">修改</el-button>
-											<el-button size="small" text type="danger" @click="onRowDel(scope.row.key, 'tab')">删除</el-button>
-										</template>
-									</el-table-column>
-								</el-table>
-							</el-tab-pane>
-						</el-tabs>
-						<pagination v-show="tableData.total > 0" :total="tableData.total" v-model:page="tableData.param.pageNum" v-model:limit="tableData.param.pageSize" @pagination="getList" />
-					</div>
-				</el-tab-pane>
-				<el-tab-pane label="设备接入" name="3">
-					<deviceIn></deviceIn>
-				</el-tab-pane>
-				<el-tab-pane label="数据解析" name="4" lazy>
-					<dataParse></dataParse>
-				</el-tab-pane>
-			</el-tabs>
-		</div>
-		<EditDic ref="editDicRef" @typeList="typeList" />
-		<EditAttr ref="editAttrRef" @typeList="getproperty" />
-		<EditFun ref="editFunRef" @typeList="getfunction" />
-		<EditEvent ref="editEventRef" @typeList="getevent" />
-		<EditTab ref="editTabRef" @typeList="gettab" />
-	</div>
-</template>
-<script lang="ts">
-import { toRefs, reactive, onMounted, ref, defineComponent } from 'vue';
-import { Delete, Edit, Search, Share, Upload } from '@element-plus/icons-vue';
-import { ElMessageBox, ElMessage, FormInstance } from 'element-plus';
-
-import EditDic from './component/editPro.vue';
-import deviceIn from './component/deviceIn.vue';
-import dataParse from './component/dataParse.vue';
-import EditAttr from './component/editAttr.vue';
-import EditFun from './component/editFun.vue';
-import EditEvent from './component/editEvent.vue';
-import EditTab from './component/editTab.vue';
-
-import { useRoute } from 'vue-router';
-
-import api from '/@/api/device';
-
-interface TableDataState {
-	ids: number[];
-	tableData: {
-		data: [];
-		total: number;
-		loading: boolean;
-		param: {
-			pageNum: number;
-			pageSize: number;
-			name: string;
-			deviceType: string;
-			status: string;
-			dateRange: string[];
-		};
-	};
-}
-export default defineComponent({
-	name: 'deviceEditPro',
-	components: { EditDic, EditAttr, EditFun, EditEvent, EditTab, deviceIn, dataParse },
-
-	setup(prop, context) {
-		const route = useRoute();
-		const editDicRef = ref();
-		const editAttrRef = ref();
-		const editFunRef = ref();
-		const editEventRef = ref();
-		const editTabRef = ref();
-		const state = reactive<TableDataState>({
-			isShowDialog: false,
-			activeName: '3', // 分类数据
-			activetab: 'attr', // 分类数据
-			detail: [],
-			developer_status: 0,
-			tableData: {
-				data: [],
-				total: 0,
-				loading: false,
-				param: {
-					pageNum: 1,
-					productId: route.params && route.params.id,
-					pageSize: 10,
-					status: '',
-					dateRange: [],
-				},
-			},
-		});
-
-		onMounted(() => {
-			const ids = route.params && route.params.id;
-			api.product.detail(ids).then((res: any) => {
-				state.detail = res.data;
-				state.developer_status = res.data.status
-			});
-
-			//第一次加载
-			api.model.property(state.tableData.param).then((res: any) => {
-				state.tableData.data = res.Data;
-				state.tableData.total = res.Total;
-			});
-		});
-
-
-
-		//编辑属性
-		const onEditAttr = (row: TableDataRow) => {
-			editAttrRef.value.openDialog(row, route.params.id);
-		};
-
-		//编辑功能
-		const onEditFun = (row: TableDataRow) => {
-			editFunRef.value.openDialog(row, route.params.id);
-		}
-
-
-		//编辑事件
-		const onEditEvent = (row: TableDataRow) => {
-			editEventRef.value.openDialog(row, route.params.id);
-		}
-
-		//编辑标签
-		const onEditTag = (row: TableDataRow) => {
-			editTabRef.value.openDialog(row, route.params.id);
-		}
-
-		//打开添加属性弹窗
-		const onOpenEditAttr = () => {
-			editAttrRef.value.openDialog({ product_id: route.params.id, id: 0, accessMode: 0 });
-		};
-
-		//打开添加功能弹窗
-		const onOpenEditFun = () => {
-			editFunRef.value.openDialog({ product_id: route.params.id, id: 0 });
-		};
-		//打开添加事件弹窗
-		const onOpenEditEvent = () => {
-			editEventRef.value.openDialog({ product_id: route.params.id, id: 0, level: 0 });
-		};
-
-		//打开添加事件弹窗
-		const onOpenEditTab = () => {
-			editTabRef.value.openDialog({ product_id: route.params.id, id: 0, accessMode: 0 });
-		};
-
-		// 打开修改产品弹窗
-		const onOpenEditDic = (row: TableDataRow) => {
-			editDicRef.value.openDialog(row);
-		};
-
-
-		// 删除产品
-		const onRowDel = (key, type) => {
-			let msg = `此操作将永久删除该数据吗?,是否继续?`;
-
-			if (key.length === 0) {
-				ElMessage.error('请选择要删除的数据。');
-				return;
-			}
-			ElMessageBox.confirm(msg, '提示', {
-				confirmButtonText: '确认',
-				cancelButtonText: '取消',
-				type: 'warning',
-			})
-				.then(() => {
-					if (type == 'attr') {
-						api.model.propertydel(route.params.id, key).then(() => {
-							ElMessage.success('删除成功');
-							getproperty();
-						});
-					}
-					if (type == 'fun') {
-						api.model.functiondel(route.params.id, key).then(() => {
-							ElMessage.success('删除成功');
-							getfunction();
-						});
-					}
-					if (type == 'event') {
-						api.model.eventdel(route.params.id, key).then(() => {
-							ElMessage.success('删除成功');
-							getevent();
-						});
-					}
-					if (type == 'tab') {
-						api.model.tagdel(route.params.id, key).then(() => {
-							ElMessage.success('删除成功');
-							tagdel();
-						});
-					}
-				})
-				.catch(() => { });
-		};
-
-
-		//根据不同类型获取列表
-		const getList = () => {
-			switch (state.activetab) {
-				case 'attr':
-					getproperty();
-					break;
-				case 'fun':
-					getfunction();
-					break;
-				case 'event':
-					getevent();
-					break;
-				case 'tab':
-					gettab();
-					break;
-			}
-		};
-
-		const getproperty = () => {
-			api.model.property(state.tableData.param).then((res: any) => {
-				state.tableData.data = res.Data;
-				state.tableData.total = res.Total;
-			});
-		};
-
-		const getfunction = () => {
-			api.model.function(state.tableData.param).then((res: any) => {
-				state.tableData.data = res.Data;
-				state.tableData.total = res.Total;
-			});
-		};
-		const getevent = () => {
-			api.model.event(state.tableData.param).then((res: any) => {
-				state.tableData.data = res.Data;
-				state.tableData.total = res.Total;
-			});
-		};
-
-		const gettab = () => {
-			api.model.tag(state.tableData.param).then((res: any) => {
-				state.tableData.data = res.Data;
-				state.tableData.total = res.Total;
-			});
-		};
-
-		const wuhandleClick = (tab: TabsPaneContext) => {
-			state.activetab = tab.props.name;
-			switch (tab.props.name) {
-				case 'attr':
-					getproperty();
-					break;
-				case 'fun':
-					getfunction();
-					break;
-				case 'event':
-					getevent();
-					break;
-				case 'tab':
-					gettab();
-					break;
-			}
-		};
-
-		const handleClick = (tab: TabsPaneContext, event: Event) => {
-			console.log(tab, event);
-		};
-
-		const CkOption = () => {
-
-			if (state.developer_status == 1) {
-				api.product.undeploy({ id: route.params.id }).then((res: any) => {
-					ElMessage.success('操作成功');
-					state.developer_status = 0;
-				});
-			} else {
-				api.product.deploy({ id: route.params.id }).then((res: any) => {
-					ElMessage.success('操作成功');
-					state.developer_status = 1;
-				});
-			}
-
-
-
-
-		}
-
-		return {
-			Edit,
-			editDicRef,
-			editAttrRef,
-			editFunRef,
-			editEventRef,
-			editTabRef,
-			CkOption,
-			onRowDel,
-			onEditFun,
-			onEditEvent,
-			onEditTag,
-			onEditAttr,
-			getList,
-			getproperty,
-			getfunction,
-			getevent,
-			gettab,
-			wuhandleClick,
-			onOpenEditTab,
-			onOpenEditEvent,
-			onOpenEditAttr,
-			onOpenEditFun,
-			onOpenEditDic,
-			handleClick,
-			...toRefs(state),
-		};
-	},
-});
-</script>
-<style>
-.content {
-	background: #fff;
-	width: 100%;
-	padding: 20px;
-}
-
-.content-box {
-	background: #fff;
-	width: 100%;
-	padding: 20px;
-	margin-top: 20px;
-}
-
-.cont_box {
-	display: flex;
-}
-
-.cont_box .title {
-	font-size: 24px;
-}
-
-.cont_box .pro-status {
-	line-height: 40px;
-	margin-left: 30px;
-}
-
-.cont_box .pro-status .on {
-	background: #52c41a;
-}
-
-.cont_box .pro-status .off {
-	background: #c41a1a;
-}
-
-.cont_box .pro-status span {
-	position: relative;
-	top: -1px;
-	display: inline-block;
-	width: 6px;
-	height: 6px;
-	vertical-align: middle;
-	border-radius: 50%;
-	margin-right: 5px;
-}
-
-.cont_box .pro-option {
-	line-height: 40px;
-	margin-left: 10px;
-	color: #1890ff;
-	cursor: pointer;
-}
-
-.content-box .pro-box {
-	display: flex;
-	padding: 10px;
-}
-
-.content-box .pro-box .protitle {
-	font-size: 18px;
-	font-weight: bold;
-	line-height: 35px;
-}
-
-.content-box .pro-box .buttonedit {
-	border: 0px;
-	color: #1890ff;
-}
-
-table {
-	border-collapse: collapse;
-	text-indent: initial;
-	border-spacing: 2px;
-}
-
-tbody {
-	box-sizing: border-box;
-	display: table-row-group;
-	vertical-align: middle;
-	border-color: inherit;
-}
-
-tr {
-	display: table-row;
-	vertical-align: inherit;
-	border-color: inherit;
-}
-
-.ant-descriptions-view {
-	width: 100%;
-	overflow: hidden;
-	border-radius: 4px;
-}
-
-.ant-descriptions-view {
-	border: 1px solid #e8e8e8;
-}
-
-.ant-descriptions-view table {
-	width: 100%;
-	table-layout: fixed;
-}
-
-.ant-descriptions-view>table {
-	table-layout: auto;
-}
-
-.ant-descriptions-row {
-	border-bottom: 1px solid #e8e8e8;
-}
-
-.ant-descriptions-item-label {
-	color: rgba(0, 0, 0, 0.85);
-	font-weight: 400;
-	font-size: 14px;
-	line-height: 1.5;
-}
-
-.ant-descriptions-item-label {
-	padding: 16px 24px;
-	border-right: 1px solid #e8e8e8;
-}
-
-.ant-descriptions-item-label {
-	background-color: #fafafa;
-}
-
-.ant-descriptions-item-content {
-	padding: 16px 24px;
-	border-right: 1px solid #e8e8e8;
-	display: table-cell;
-	color: rgba(0, 0, 0, 0.65);
-	font-size: 14px;
-	line-height: 1.5;
-}
-
-.wu-box {
-	border: #e8e8e8 solid 1px;
-	padding: 20px;
-	width: 100%;
-}
-
-.wu-box .wu-title {
-	display: flex;
-	flex-direction: row;
-	justify-content: space-between;
-	padding: 20px;
-	border-bottom: #e8e8e8 1px solid;
-}
-
-.wu-box .wu-title .title {
-	font-size: 18px;
-}</style>
-
-

+ 161 - 142
src/views/iot/device-tree/tree/index.vue

@@ -1,150 +1,159 @@
 <template>
-  <div class="system-dic-container">
-    <el-card shadow="hover">
-      <LrLayout width="260px">
-        <template #left>
-          <div class="zl-tree-search">
-            <div class="flex zl-tree-search__filter">
-              <el-input v-model.trim="searchVal" placeholder="搜索">
-                <template #prefix>
-                  <el-icon><Search /></el-icon>
-                  <!-- <i class="iconfont icon-search" /> -->
-                </template>
-              </el-input>
-            </div>
+  <div class="system-dic-container" style="background: #fff">
+    <LrLayout width="260px">
+      <template #left>
+        <div class="zl-tree-search">
+          <div class="flex zl-tree-search__filter">
+            <el-input v-model.trim="searchVal" placeholder="搜索">
+              <template #prefix>
+                <el-icon><Search /></el-icon>
+                <!-- <i class="iconfont icon-search" /> -->
+              </template>
+            </el-input>
           </div>
-          <div class="zl-tree-search-scroll">
-            <el-scrollbar ref="zlTreeSearchScroll" height="100%" v-loading="treeLoading">
-              <el-tree
-                ref="zlTreeSearchRef"
-                v-if="!treeLoading"
-                :data="treeData"
-                :props="{
-                  children: 'children',
-                  label: 'name'
-                }"
-                :filter-node-method="filterNode"
-                :default-expand-all="true"
-                :node-key="'id'"
-                highlight-current
-                @node-click="nodeClick">
-                <template #default="{ node, data }">
-                  <div class="custom-tree-node">
-                    <span class="tree-label">
-                      <i class="iconfont icon-wenjianjia icon-wjj mr8" />{{ node.label }}
-                    </span>
-                    <span class="tree-options" >
-                      <slot name="operate" :data="data">
-                        <el-dropdown @command="command => operateCmd(command, data)">
-                          <el-icon>
-                            <More></More>
-                          </el-icon>
-                          <template #dropdown>
-                            <el-dropdown-menu>
-                              <el-dropdown-item command="add">
-                                <el-icon>
-                                  <Plus></Plus>
-                                </el-icon>
-                              </el-dropdown-item>
-                              <el-dropdown-item command="edit">
-                                <el-icon>
-                                  <Edit></Edit>
-                                </el-icon>
-                              </el-dropdown-item>
-                              <el-dropdown-item command="delete">
-                                <el-icon>
-                                  <Delete></Delete>
-                                </el-icon>
-                              </el-dropdown-item>
-                            </el-dropdown-menu>
-                          </template>
-                        </el-dropdown>
-                      </slot>
-                    </span>
-                  </div>
-                </template>
-              </el-tree>
-            </el-scrollbar>
-          </div>
-        </template>
-        <template #right>
-          <!--  @tab-click="handleClick" -->
-          <el-tabs v-model="tabName">
-            <el-tab-pane label="设备树信息" name="1">
-              <table>
-                <tbody>
-                  <tr class="ant-descriptions-row">
-                    <th class="ant-descriptions-item-label ant-descriptions-item-colon">名称</th>
-                    <td class="ant-descriptions-item-content" colspan="1">{{ treeDetail.name }}</td>
-                    <th class="ant-descriptions-item-label ant-descriptions-item-colon">地址</th>
-                    <td class="ant-descriptions-item-content" colspan="1">{{ treeDetail.address }}</td>
-                    <th class="ant-descriptions-item-label ant-descriptions-item-colon">经度</th>
-                    <td class="ant-descriptions-item-content" colspan="1">{{ treeDetail.lng }}</td>
-                  </tr>
-                  <tr class="ant-descriptions-row">
-                    <th class="ant-descriptions-item-label ant-descriptions-item-colon">纬度</th>
-                    <td class="ant-descriptions-item-content" colspan="1">{{ treeDetail.lat }}</td>
-                    <th class="ant-descriptions-item-label ant-descriptions-item-colon">联系人</th>
-                    <td class="ant-descriptions-item-content" colspan="1">{{ treeDetail.contact }}</td>
-                    <th class="ant-descriptions-item-label ant-descriptions-item-colon">联系电话</th>
-                    <td class="ant-descriptions-item-content" colspan="1">{{ treeDetail.phone }}</td>
-                  </tr> 
-                  <tr class="ant-descriptions-row">
-                    <th class="ant-descriptions-item-label ant-descriptions-item-colon">服务周期:开始日期</th>
-                    <td class="ant-descriptions-item-content" colspan="1">{{ treeDetail.startDate }}</td>
-                    <th class="ant-descriptions-item-label ant-descriptions-item-colon">服务周期:截止日期</th>
-                    <td class="ant-descriptions-item-content" colspan="1">{{ treeDetail.endDate }}</td>
-                    <th class="ant-descriptions-item-label ant-descriptions-item-colon">图片</th>
-                    <td class="ant-descriptions-item-content" colspan="1">{{ treeDetail.image }}</td>
-                  </tr>
-                  <tr class="ant-descriptions-row">
-                    <th class="ant-descriptions-item-label ant-descriptions-item-colon">设备标识</th>
-                    <td class="ant-descriptions-item-content" colspan="5">{{ treeDetail.deviceKey }}</td>
-                  </tr>
-                </tbody>
-              </table>
-            </el-tab-pane>
-            <el-tab-pane label="时间周期" name="2">
-			        <el-form :model="ruleForm" ref="formRef" size="default" label-width="80px">
-                <!-- <el-form-item label="时间窗口" prop="duration">
-                  <div class="flex">
-                    <el-input v-model="ruleForm.duration" placeholder="请输入" class="w-35" />
-                    <el-select v-model="ruleForm.timeUnit" placeholder="请选择单位">
-                      <el-option v-for="item in unitData" :key="item.value" :label="item.label" :value="item.value" />
-                    </el-select>
-                  </div>
-                </el-form-item> -->
-                <el-form-item label="类型" prop="template">
-                  <el-select v-model="ruleForm.template" filterable clearable placeholder="请选择类型" class="w-35">
-                    <el-option v-for="dict in tree_types" :key="dict.value" :label="dict.label" :value="dict.value"> </el-option>
-                  </el-select>
-                </el-form-item>
-                <el-form-item label="分类" prop="category">
-                  <el-select v-model="ruleForm.category" filterable clearable placeholder="请选择分类" class="w-35">
-                    <el-option v-for="dict in tree_category" :key="dict.value" :label="dict.label" :value="dict.value"> </el-option>
+        </div>
+        <div class="zl-tree-search-scroll">
+          <el-scrollbar ref="zlTreeSearchScroll" height="100%" v-loading="treeLoading">
+            <el-tree
+              ref="zlTreeSearchRef"
+              v-if="!treeLoading"
+              :data="treeData"
+              :props="{
+                children: 'children',
+                label: 'name'
+              }"
+              :filter-node-method="filterNode"
+              :default-expand-all="true"
+              :node-key="'id'"
+              highlight-current
+              @node-click="nodeClick">
+              <template #default="{ node, data }">
+                <div class="custom-tree-node">
+                  <span class="tree-label">
+                    <i class="iconfont icon-wenjianjia icon-wjj mr8" />{{ node.label }}
+                  </span>
+                  <span class="tree-options" @click.stop>
+                    <slot name="operate" :data="data">
+                      <el-dropdown @command="command => operateCmd(command, data)">
+                        <el-icon>
+                          <More></More>
+                        </el-icon>
+                        <template #dropdown>
+                          <el-dropdown-menu>
+                            <el-dropdown-item command="add">
+                              <el-icon>
+                                <Plus></Plus>
+                              </el-icon>
+                            </el-dropdown-item>
+                            <el-dropdown-item command="edit">
+                              <el-icon>
+                                <Edit></Edit>
+                              </el-icon>
+                            </el-dropdown-item>
+                            <el-dropdown-item command="delete">
+                              <el-icon>
+                                <Delete></Delete>
+                              </el-icon>
+                            </el-dropdown-item>
+                          </el-dropdown-menu>
+                        </template>
+                      </el-dropdown>
+                    </slot>
+                  </span>
+                </div>
+              </template>
+            </el-tree>
+          </el-scrollbar>
+        </div>
+      </template>
+      <template #right>
+        <!--  @tab-click="handleClick" -->
+        <el-tabs v-model="tabName">
+          <el-tab-pane label="设备树信息" name="1">
+            <table>
+              <tbody>
+                <tr class="ant-descriptions-row">
+                  <th class="ant-descriptions-item-label ant-descriptions-item-colon">名称</th>
+                  <td class="ant-descriptions-item-content" colspan="1">{{ treeDetail.name }}</td>
+                  <th class="ant-descriptions-item-label ant-descriptions-item-colon">地址</th>
+                  <td class="ant-descriptions-item-content" colspan="1">{{ treeDetail.address }}</td>
+                  <th class="ant-descriptions-item-label ant-descriptions-item-colon">经度</th>
+                  <td class="ant-descriptions-item-content" colspan="1">{{ treeDetail.lng }}</td>
+                </tr>
+                <tr class="ant-descriptions-row">
+                  <th class="ant-descriptions-item-label ant-descriptions-item-colon">纬度</th>
+                  <td class="ant-descriptions-item-content" colspan="1">{{ treeDetail.lat }}</td>
+                  <th class="ant-descriptions-item-label ant-descriptions-item-colon">联系人</th>
+                  <td class="ant-descriptions-item-content" colspan="1">{{ treeDetail.contact }}</td>
+                  <th class="ant-descriptions-item-label ant-descriptions-item-colon">联系电话</th>
+                  <td class="ant-descriptions-item-content" colspan="1">{{ treeDetail.phone }}</td>
+                </tr> 
+                <tr class="ant-descriptions-row">
+                  <th class="ant-descriptions-item-label ant-descriptions-item-colon">服务周期:开始日期</th>
+                  <td class="ant-descriptions-item-content" colspan="1">{{ treeDetail.startDate }}</td>
+                  <th class="ant-descriptions-item-label ant-descriptions-item-colon">服务周期:截止日期</th>
+                  <td class="ant-descriptions-item-content" colspan="1">{{ treeDetail.endDate }}</td>
+                  <th class="ant-descriptions-item-label ant-descriptions-item-colon">图片</th>
+                  <td class="ant-descriptions-item-content" colspan="1">{{ treeDetail.image }}</td>
+                </tr>
+                <tr class="ant-descriptions-row">
+                  <th class="ant-descriptions-item-label ant-descriptions-item-colon">设备标识</th>
+                  <td class="ant-descriptions-item-content" colspan="1">{{ treeDetail.deviceKey }}</td>
+                  <th class="ant-descriptions-item-label ant-descriptions-item-colon">设备所属区域</th>
+                  <td class="ant-descriptions-item-content" colspan="1">{{ treeDetail.area }}</td>
+                  <th class="ant-descriptions-item-label ant-descriptions-item-colon">所属公司</th>
+                  <td class="ant-descriptions-item-content" colspan="1">{{ treeDetail.company }}</td>
+                </tr>
+                <tr class="ant-descriptions-row">
+                  <th class="ant-descriptions-item-label ant-descriptions-item-colon">类型</th>
+                  <td class="ant-descriptions-item-content" colspan="5">{{ treeDetail.types }}</td>
+                </tr>
+              </tbody>
+            </table>
+          </el-tab-pane>
+          <el-tab-pane label="时间周期" name="2">
+            <el-form :model="ruleForm" ref="formRef" size="default" label-width="80px">
+              <!-- <el-form-item label="时间窗口" prop="duration">
+                <div class="flex">
+                  <el-input v-model="ruleForm.duration" placeholder="请输入" class="w-35" />
+                  <el-select v-model="ruleForm.timeUnit" placeholder="请选择单位">
+                    <el-option v-for="item in unitData" :key="item.value" :label="item.label" :value="item.value" />
                   </el-select>
-                </el-form-item>
-                <el-form-item label=" " prop="category">
-                  <el-button type="primary" @click="onSaveTime">保存</el-button>
-                </el-form-item>
-              </el-form>
-            </el-tab-pane>
-            <el-tab-pane label="绑定实际设备" name="3">
-              <el-form-item label="选择设备" prop="deviceKey">
-                <el-select v-model="ruleForm.deviceKey" filterable placeholder="请选择设备">
-                  <el-option v-for="item in []" :key="item.key" :label="item.name" :value="item.key">
-                    <span style="float: left">{{ item.name }}</span>
-                    <span style="float: right; font-size: 13px">{{ item.key }}</span>
-                  </el-option>
+                </div>
+              </el-form-item> -->
+              <el-form-item label="类型" prop="template">
+                <el-select v-model="ruleForm.template" filterable clearable placeholder="请选择类型" class="w-35">
+                  <el-option v-for="dict in tree_types" :key="dict.value" :label="dict.label" :value="dict.value"> </el-option>
+                </el-select>
+              </el-form-item>
+              <el-form-item label="分类" prop="category">
+                <el-select v-model="ruleForm.category" filterable clearable placeholder="请选择分类" class="w-35">
+                  <el-option v-for="dict in tree_category" :key="dict.value" :label="dict.label" :value="dict.value"> </el-option>
                 </el-select>
               </el-form-item>
-            </el-tab-pane>
-          </el-tabs>
-        </template>
-      </LrLayout>
+              <el-form-item label=" " prop="category">
+                <el-button type="primary" @click="onSaveTime">保存</el-button>
+              </el-form-item>
+            </el-form>
+          </el-tab-pane>
+          <el-tab-pane label="绑定实际设备" name="3">
+            <el-form-item label="选择设备" prop="deviceKey">
+              <el-select v-model="ruleForm.deviceKey" filterable placeholder="请选择设备">
+                <el-option v-for="item in deviceList" :key="item.id" :label="item.name" :value="item.id">
+                  <span style="float: left">{{ item.name }}</span>
+                  <!-- <span style="float: right; font-size: 13px">{{ item.key }}</span> -->
+                </el-option>
+              </el-select>
+            </el-form-item>
+            <el-form-item label=" " prop="category">
+              <el-button type="primary" @click="onSaveTime">保存</el-button>
+            </el-form-item>
+          </el-tab-pane>
+        </el-tabs>
+      </template>
+    </LrLayout>
 
-      <AddOrUpdate ref="addOrUpdateRef" @finish="getTreeList"/>
-    </el-card>
+    <AddOrUpdate ref="addOrUpdateRef" @finish="getTreeList"/>
   </div>
 </template>
 
@@ -179,6 +188,7 @@ interface TableDataState {
     };
   };
   treeData: any[]
+  deviceList: any[]
   treeLoading: boolean
   tabName: string
   searchVal: string
@@ -212,6 +222,7 @@ export default defineComponent({
       tabName: '1',
       searchVal: '',
       treeDetail: {},
+      deviceList: [],
 			unitData: [
 				{ label: '秒', value: 1 },
 				{ label: '分', value: 2 },
@@ -230,6 +241,7 @@ export default defineComponent({
     // 初始化表格数据
     const initTableData = () => {
       getTreeList();
+      getDeviceList()
     };
     const getTreeList = () => {
       state.treeLoading = true;
@@ -237,6 +249,12 @@ export default defineComponent({
         state.treeData = res.list;
       }).finally(() => (state.treeLoading = false));
     }
+    const getDeviceList = () => {
+      api.device.allList({}).then((res: any) => {
+        state.deviceList = res.device || [];
+        console.log('res')
+      })
+    }
     const typeList = () => {
 
     };
@@ -269,7 +287,8 @@ export default defineComponent({
       api.tree.edit({
         ...state.treeDetail,
         template: state.ruleForm.template,
-        category: state.ruleForm.category
+        category: state.ruleForm.category,
+        deviceKey: state.ruleForm.deviceKey,
       }).then(() => {
         ElMessage.success('修改成功');
       });

+ 7 - 10
src/views/iot/device/instance/component/edit.vue

@@ -39,7 +39,7 @@
               <el-input v-model="ruleForm.authUser" placeholder="请输入用户名" />
             </el-form-item>
             <el-form-item label="密码" prop="authPasswd">
-              <el-input v-model="ruleForm.authPasswd" placeholder="请输入密码" />
+              <el-input type="password" v-model="ruleForm.authPasswd" placeholder="请输入密码" />
             </el-form-item>
           </template>
           <template v-else>
@@ -243,20 +243,17 @@ export default defineComponent({
         });
       });
     }
-    // 通过设备所属产品的传输协议来确定认证方式
-    const transportProtocolChange = (type: string) => {
-      if (type === 'mqtt_server') {
-        state.ruleForm.authType = 1
-      } else {
-        state.ruleForm.authType = 3
-      }
-    }
     // 所属产品变化的时候,更新产品详情
     const productIdChange = (productId: number) => {
       api.product.detail(productId).then((res: any) => {
         // console.log(res.data)
+        const { authType, authUser, authPasswd, accessToken, certificateId } = res.data
         state.product = res.data
-        transportProtocolChange(res.data.transportProtocol)
+        state.ruleForm.authType = authType
+        state.ruleForm.authUser = authUser
+        state.ruleForm.authPasswd = authPasswd
+        state.ruleForm.accessToken = accessToken
+        state.ruleForm.certificateId = certificateId
       })
     }
 

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

@@ -1,5 +1,6 @@
 <template>
 	<div class="device-function">
+		<el-empty description="暂无功能列表,请先在物模型的功能定义中添加" 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">
@@ -47,11 +48,19 @@ interface IListItem {
 }
 
 const list = ref<IListItem[]>([])
+const loading = ref(true)
+
+getData()
+
+function getData() {
+	loading.value = true
+	api.tabDeviceFucntion.getList({ key: props.productKey }).then((res: IListItem[]) => {
+		if (!res) return
+		res.forEach((item) => (item.result = ''))
+		list.value = res
+	}).finally(() => loading.value = false)
+}
 
-api.tabDeviceFucntion.getList({ key: props.productKey }).then((res: IListItem[]) => {
-	res.forEach((item) => (item.result = ''))
-	list.value = res
-})
 
 function run(row: IListItem) {
 	row.result = ''

+ 1 - 1
src/views/iot/device/instance/detail.vue

@@ -239,7 +239,7 @@
           </div>
         </el-tab-pane>
         <el-tab-pane label="设备功能" name="5">
-          <functionCom :device-key="detail.key" :product-key="prodetail.key"  v-if="detail.key && prodetail.key"></functionCom>
+          <functionCom :device-key="detail.key" :product-key="prodetail.key"  v-if="detail.key && prodetail.key && activeName==='5'"></functionCom>
         </el-tab-pane>
         <el-tab-pane label="日志管理" name="4">
           <div class="system-user-search mb15">

+ 12 - 15
src/views/iot/device/product/component/deviceIn.vue

@@ -9,32 +9,28 @@
 	<div class="text">{{ data.link }}</div>
 	<div class="title">认证配置</div>
 
-	<template v-if="data.authType === 1 || data.authType === 2">
-		<el-form-item label="认证方式" prop="">
-			<el-radio-group v-model="data.authType">
-				<el-radio :label="1">Basic</el-radio>
-				<el-radio :label="2">AccessToken</el-radio>
-			</el-radio-group>
+	<template v-if="!isAdmin">请联系管理员</template>
+	<template v-else-if="data.authType === 1 || data.authType === 2">
+		<el-form-item label="认证方式" prop="authType" label-width="80px" style="margin-bottom: 0;">
+			{{ data.authType === 1 ? 'Basic' : 'AccessToken' }}
 		</el-form-item>
 		<template v-if="data.authType === 1">
-			<el-form-item label="用户名" prop="authUser" label-width="80px">
-				<el-input v-model="data.authUser" readonly  style="width: 300px;" />
+			<el-form-item label="用户名" prop="authUser" label-width="80px" style="margin-bottom: 0;">
+				{{ data.authUser }}
 			</el-form-item>
 			<el-form-item label="密码" prop="authPasswd" label-width="80px">
-				<el-input v-model="data.authPasswd" readonly style="width: 300px;" />
+				{{ data.authPasswd }}
 			</el-form-item>
 		</template>
 		<template v-else>
 			<el-form-item label="Aceess Token" prop="accessToken">
-				<el-input v-model="data.accessToken" readonly/>
+				{{ data.accessToken }}
 			</el-form-item>
 		</template>
 	</template>
 	<template v-else-if="data.authType === 3">
-		<el-form-item label="认证证书" prop="certificateId">
-			<el-select v-model="data.certificateId" disabled>
-				<el-option v-for="cert in certList" :key="cert.id" :label="cert.name" :value="cert.id"> </el-option>
-			</el-select>
+		<el-form-item label="认证证书" prop="certificateName">
+			{{ data.certificateName }}
 		</el-form-item>
 	</template>
 </template>
@@ -46,7 +42,7 @@ import { useRoute } from 'vue-router';
 
 const route = useRoute();
 
-const certList = ref([])
+const isAdmin = localStorage.userId == '1'
 const data = reactive({
 	"name": "",
 	"protocol": "",
@@ -56,6 +52,7 @@ const data = reactive({
 	"authUser": "",
 	"authPasswd": "",
 	"accessToken": "",
+	"certificateName": "",
 	"certificateId": 0
 })
 

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

@@ -58,7 +58,7 @@
 							<el-input v-model="ruleForm.authUser" placeholder="请输入用户名" />
 						</el-form-item>
 						<el-form-item label="密码" prop="authPasswd">
-							<el-input v-model="ruleForm.authPasswd" placeholder="请输入密码" />
+							<el-input type="password" v-model="ruleForm.authPasswd" placeholder="请输入密码" />
 						</el-form-item>
 					</template>
 					<template v-else>