Browse Source

feat: 增加场景联动的绑定

yanglzh 1 năm trước cách đây
mục cha
commit
ce4b82a41f

+ 10 - 4
src/views/iot/projects/detail/device.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="tab-content h-full">
-    <div class="subtitle"><span></span> <el-button type="primary" size="small" @click="addDevice()">添加网关</el-button></div>
+    <div class="subtitle"><span></span> <el-button type="primary" size="small" @click="addDevice()">添加设备</el-button></div>
     <el-table :data="tableData" style="width: 100%" v-loading="loading" max-height="calc(100vh - 280px)">
       <el-table-column label="标识" prop="key" min-width="150" show-overflow-tooltip v-col="'key'">
         <template #default="{ row }">
@@ -27,7 +27,7 @@
       </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()" />
-    <el-dialog title="添加网关" v-model="isShowDialog" width="400">
+    <el-dialog title="添加设备" v-model="isShowDialog" width="400">
       <el-form v-if="isShowDialog">
         <el-form-item label="产品">
           <el-select v-model="form.productKey" @change="getDivices" filterable placeholder="选择产品" :clearable="false" style="width: 100%">
@@ -59,10 +59,11 @@ import { useRoute } from 'vue-router';
 import { ElMessage, ElMessageBox } from 'element-plus';
 const route = useRoute();
 
+const props = defineProps({ resourcesTypes: Number })
 const isShowDialog = ref(false)
 const productList = ref<any[]>([])
 const deviceList = ref<any[]>([])
-const resourcesTypes = 1
+const resourcesTypes = props.resourcesTypes
 const projectsCode = route.params.id
 
 const baseForm = {
@@ -84,7 +85,12 @@ getSourceList();
 function getSourceList() {
   api.getProjectResourcesByCode({ projectsCode }).then((res: any) => {
     params.keys = (res || []).filter((item: any) => item.resourcesTypes === resourcesTypes).map((item: any) => item.resourcesKey)
-    getList();
+    if (!params.keys.length) {
+      params.pageNum = 1
+      tableData.value = []
+    } else {
+      getList();
+    }
   })
 }
 

+ 11 - 14
src/views/iot/projects/detail/index.vue

@@ -1,32 +1,29 @@
 <template>
   <div class="page">
     <el-card shadow="nover" class="small-padding">
-      <el-tabs :model-value="'4'" size="small" class="h-full">
-        <el-tab-pane label="场景概况" name="0">
-          <InfoVue></InfoVue>
+      <el-tabs :model-value="'1'" size="small" class="h-full">
+        <el-tab-pane label="网关和设备" name="1" lazy>
+          <DeviceVue :resourcesTypes="1"></DeviceVue>
         </el-tab-pane>
-        <el-tab-pane label="组态应用" name="2">
+        <el-tab-pane label="场景联动" name="4" lazy>
+          <SceneVue :resourcesTypes="4"></SceneVue>
+        </el-tab-pane>
+        <el-tab-pane label="组态应用" name="2" lazy>
           <TopoVue></TopoVue>
         </el-tab-pane>
-        <el-tab-pane label="视频监控" name="3">
+        <el-tab-pane label="视频监控" name="3" lazy>
           <VideoVue></VideoVue>
         </el-tab-pane>
-        <el-tab-pane label="网关和设备" name="1">
-          <DeviceVue></DeviceVue>
-        </el-tab-pane>
-        <el-tab-pane label="场景联动" name="4">
-          <DeviceVue></DeviceVue>
-        </el-tab-pane>
       </el-tabs>
     </el-card>
   </div>
 </template>
 
 <script lang="ts" setup>
-import InfoVue from './info.vue'
 import TopoVue from './topo.vue'
 import VideoVue from './video.vue'
 import DeviceVue from './device.vue'
+import SceneVue from './scene.vue'
 
 // 资源类型 resourcesTypes
 //  设备  1
@@ -36,8 +33,8 @@ import DeviceVue from './device.vue'
 
 </script>
 <style scoped lang="scss">
-::v-deep{
-  .subtitle{
+::v-deep {
+  .subtitle {
     display: flex;
     justify-content: space-between;
     height: 24px;

+ 136 - 0
src/views/iot/projects/detail/scene.vue

@@ -0,0 +1,136 @@
+<template>
+  <div class="tab-content h-full">
+    <div class="subtitle"><span></span> <el-button type="primary" size="small" @click="addDevice()">添加场景</el-button></div>
+    <el-table :data="tableData" style="width: 100%" v-loading="loading" max-height="calc(100vh - 280px)">
+      <el-table-column prop="id" label="ID" min-width="100" show-overflow-tooltip></el-table-column>
+      <el-table-column prop="name" label="场景名称" show-overflow-tooltip></el-table-column>
+      <el-table-column prop="sceneType" label="触发方式" align="center">
+        <template #default="scope">
+          <el-tag size="small" v-if="scope.row.sceneType == 'device'">设备触发</el-tag>
+          <el-tag size="small" v-if="scope.row.sceneType == 'manual'">手动触发</el-tag>
+          <el-tag size="small" v-if="scope.row.sceneType == 'timer'">定时触发</el-tag>
+        </template>
+      </el-table-column>
+
+      <el-table-column prop="status" label="状态" align="center">
+        <template #default="scope">
+          <el-tag size="small" type="success" v-if="scope.row.status == 1">启用</el-tag>
+          <el-tag size="small" type="info" v-if="scope.row.status == 0">禁用</el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column prop="description" label="场景描述" show-overflow-tooltip></el-table-column>
+      <el-table-column prop="createdAt" label="创建时间" width="160" align="center"></el-table-column>
+      <el-table-column label="操作" width="120" align="center">
+        <template #default="scope">
+          <el-button size="small" text type="primary" v-auth="'xxx'" @click="$router.push('/iotmanager/scene/manage/' + scope.row.id)">场景详情</el-button>
+          <el-button size="small" text type="warning" v-auth="'xxx'" @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()" />
+    <el-dialog title="添加场景" v-model="isShowDialog" width="400">
+      <el-form v-if="isShowDialog">
+        <el-form-item label="场景" style="margin-bottom: 0;">
+          <el-select v-model="form.resourcesKey" filterable placeholder="选择场景" :clearable="false" style="width: 100%">
+            <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
+          </el-select>
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button @click="onCancel">取 消</el-button>
+          <el-button type="primary" @click="onSubmit">确 定</el-button>
+        </span>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script lang="ts" setup>
+import { reactive, ref } from 'vue';
+import sceneApi from '/@/api/scene';
+import api from '/@/api/projects';
+import { useSearch } from '/@/hooks/useCommon';
+import { useRoute } from 'vue-router';
+import { ElMessage, ElMessageBox } from 'element-plus';
+import { stat } from 'fs';
+import { pa } from 'element-plus/es/locale';
+const route = useRoute();
+
+const props = defineProps({ resourcesTypes: Number })
+const isShowDialog = ref(false)
+const options = ref<any[]>([])
+const deviceList = ref<any[]>([])
+const resourcesTypes = props.resourcesTypes
+const projectsCode = route.params.id
+
+const baseForm = {
+  resourcesKey: '',
+  projectsCode,
+  resourcesTypes
+}
+
+const form = reactive({
+  ...baseForm
+})
+
+const { params, tableData, getList, loading } = useSearch<any[]>(sceneApi.manage.getList, 'Data', { ids: [], status: undefined });
+
+getOptions();
+getSourceList();
+
+function getSourceList() {
+  api.getProjectResourcesByCode({ projectsCode }).then((res: any) => {
+    params.ids = (res || []).filter((item: any) => item.resourcesTypes === resourcesTypes).map((item: any) => item.resourcesKey)
+    if (!params.ids.length) {
+      params.pageNum = 1
+      tableData.value = []
+    } else {
+      getList();
+    }
+  })
+}
+
+
+function getOptions() {
+  sceneApi.manage.getList({ status: -1, pageNum: 1, pageSize: 500 }).then((res: any) => {
+    options.value = (res?.list || []).map((item: any) => ({ label: item.name, value: item.id }))
+  })
+}
+
+function onCancel() {
+  Object.assign(form, baseForm)
+  isShowDialog.value = false
+}
+
+function onSubmit() {
+  if (!form.resourcesKey) return ElMessage('请先选择场景')
+  api.bindResources(form).then((res: any) => {
+    onCancel()
+    getSourceList()
+    ElMessage.success('添加成功')
+  })
+}
+
+function addDevice() {
+  isShowDialog.value = true
+}
+
+function onDel(row: any) {
+  ElMessageBox.confirm(`确定要解绑该场景?`, '提示', {
+    confirmButtonText: '确认',
+    cancelButtonText: '取消',
+    type: 'warning',
+  }).then(() => {
+    api.unbindResources({
+      projectsCode,
+      resourcesTypes,
+      resourcesKey: row.id
+    }).then(() => {
+      getSourceList()
+      ElMessage.success('解绑成功')
+    })
+  });
+}
+
+</script>

+ 0 - 2
src/views/iot/scene/manage/index.vue

@@ -46,7 +46,6 @@
 						<el-tag size="small" v-if="scope.row.sceneType == 'timer'">定时触发</el-tag>
 					</template>
 				</el-table-column>
-
 				<el-table-column prop="status" label="状态" align="center" v-col="'status'">
 					<template #default="scope">
 						<el-tag size="small" type="success" v-if="scope.row.status == 1">启用</el-tag>
@@ -54,7 +53,6 @@
 					</template>
 				</el-table-column>
 				<el-table-column prop="description" label="场景描述" show-overflow-tooltip v-col="'description'"></el-table-column>
-
 				<el-table-column prop="createdAt" label="创建时间" width="160" align="center" v-col="'createdAt'"></el-table-column>
 				<el-table-column label="操作" width="200" align="center">
 					<template #default="scope">