Sfoglia il codice sorgente

pms 设备调拨 功能优化

zhangcl 3 mesi fa
parent
commit
12132f4ebf
2 ha cambiato i file con 91 aggiunte e 128 eliminazioni
  1. 90 126
      src/views/pms/device/ConfigDeviceAllot.vue
  2. 1 2
      src/views/pms/device/DeptTree2.vue

+ 90 - 126
src/views/pms/device/ConfigDeviceAllot.vue

@@ -18,7 +18,7 @@
               @node-click="handleDeptDeviceTreeNodeClick"
             />
           </div>
-          <el-scrollbar height="400px">
+          <el-scrollbar height="500px">
             <el-checkbox-group v-model="selectedDevices">
               <div
                 v-for="device in simpleDevices"
@@ -38,46 +38,41 @@
       <el-col :span="12" class="col-height">
         <div class="card right-card">
           <h3>部门列表</h3>
-            <ContentWrap class="dept-tree-container" >
-              <DeptTree2 ref="deptTreeRef" v-model="selectedDeptId" height="100%" @update:modelValue="handleDeptChange"/>
-            </ContentWrap>
-
-          <div class="action-bar">
-
-          </div>
+          <ContentWrap class="dept-tree-container" height="400px">
+            <DeptTree2 ref="deptTreeRef" v-model="selectedDeptId" height="100%" @update:modelValue="handleDeptChange"/>
+          </ContentWrap>
         </div>
       </el-col>
     </el-row>
 
     <!-- 暂存关联列表 -->
-    <div class="temp-list card">
-      <h3>待提交的关联关系</h3>
-      <el-table :data="tempRelations" style="width: 100%">
-        <el-table-column prop="deviceNames" label="设备" width="200" />
-        <el-table-column prop="deptName" label="部门" />
-        <el-table-column prop="deptId" label="部门id" v-if="false"/>
-        <el-table-column label="操作" width="120">
-          <template #default="{ row }">
-            <el-button
-              type="danger"
-              size="small"
-              @click="removeTempRelation(row.deviceIds)"
-            >
-              删除
-            </el-button>
-          </template>
-        </el-table-column>
-      </el-table>
-
-      <div class="submit-area">
-        <el-button
-          type="primary"
-          size="large"
-          @click="submitRelations"
-          :disabled="tempRelations.length === 0"
-        >
-          提交全部关联关系
-        </el-button>
+    <div class="submit-area">
+      <el-button
+        type="primary"
+        size="large"
+        @click="submitRelations"
+        :disabled="tempRelations.length === 0"
+      >
+        保 存
+      </el-button>
+      <div class="temp-list card" v-if="false">
+        <h3>待提交的关联关系</h3>
+        <el-table :data="tempRelations" style="width: 100%">
+          <el-table-column prop="deviceNames" label="设备" width="200" />
+          <el-table-column prop="deptName" label="部门" />
+          <el-table-column prop="deptId" label="部门id" v-if="false"/>
+          <el-table-column label="操作" width="120">
+            <template #default="{ row }">
+              <el-button
+                type="danger"
+                size="small"
+                @click="removeTempRelation(row.deviceId)"
+              >
+                删除
+              </el-button>
+            </template>
+          </el-table-column>
+        </el-table>
       </div>
     </div>
   </div>
@@ -89,7 +84,6 @@ import { ElMessage } from 'element-plus'
 import {defaultProps, handleTree} from "@/utils/tree";
 import * as DeptApi from "@/api/system/dept";
 import {IotDeviceApi, IotDeviceVO} from "@/api/pms/device";
-import {IotDevicePersonApi, IotDevicePersonVO} from "@/api/pms/iotdeviceperson";
 import DeptTree2 from "@/views/pms/device/DeptTree2.vue";
 
 defineOptions({ name: 'ConfigDeviceAllot' })
@@ -120,46 +114,57 @@ const deptTreeRef = ref<InstanceType<typeof DeptTree2>>()
 const emit = defineEmits(['success', 'node-click']) // 定义 success 树点击 事件,用于操作成功后的回调
 
 // 响应式数据
-const tempRelations = ref<Array<{
-  deviceIds: []
+const tempRelationsMap = ref(new Map<number, {
   deviceId: number
   deviceNames: string
-  deptName: string
   deptId: number
-  reason: string
-}>>([])
+  deptName: string
+}>())
 
-// 添加设备选择监听
-watch([selectedDevices, selectedDeptId], () => {
-  updateTempRelations();
-}, {deep: true})
+// 计算属性转换 Map 为数组
+const tempRelations = computed(() =>
+  Array.from(tempRelationsMap.value.values())
+)
 
 const updateTempRelations = () => {
-  if (!selectedDeptId.value || selectedDevices.value.length === 0) return;
+  if (!selectedDeptId.value) {
+    // 未选择部门时清除所有关联
+    tempRelationsMap.value.clear()
+    return
+  }
+
+  // 获取部门信息
+  const treeNode = deptTreeRef.value?.treeRef?.getNode(selectedDeptId.value)
+  const deptName = treeNode?.data?.name || '未知部门'
 
-  const treeNode = deptTreeRef.value?.treeRef?.getNode(selectedDeptId.value);
-  const deptName = treeNode?.data?.name || '未知部门';
+  // 创建当前应该存在的设备集合
+  const currentDeviceIds = new Set(selectedDevices.value)
+
+  // 清理无效关联(包含:1.当前部门外的关联 2.未选中的设备)
+  Array.from(tempRelationsMap.value.entries()).forEach(([deviceId, relation]) => {
+    if (relation.deptId !== selectedDeptId.value || !currentDeviceIds.has(deviceId)) {
+      tempRelationsMap.value.delete(deviceId)
+    }
+  })
 
-  const newRelations = selectedDevices.value
-    .map(deviceId => {
-      const device = simpleDevices.value.find(d => d.id === deviceId);
-      return device ? {
-        deviceIds: [deviceId],
-        deviceId: deviceId,
+  // 添加/更新当前选中设备的关联
+  selectedDevices.value.forEach(deviceId => {
+    const device = simpleDevices.value.find(d => d.id === deviceId)
+    if (device) {
+      tempRelationsMap.value.set(deviceId, {
+        deviceId,
         deviceNames: `${device.deviceCode} (${device.deviceName})`,
-        deptId: selectedDeptId.value,
-        deptName: deptName
-      } : null;
-    })
-    .filter(Boolean);
-
-  tempRelations.value = [
-    ...tempRelations.value.filter(r =>
-      !selectedDevices.value.includes(r.deviceId)
-    ),
-    ...newRelations
-  ];
-};
+        deptId: selectedDeptId.value as number,
+        deptName
+      })
+    }
+  })
+}
+
+// 添加设备选择监听
+watch([selectedDevices, selectedDeptId], () => {
+  updateTempRelations();
+}, {deep: true, immediate: true, debounce: 100})
 
 // 修改部门变更处理方法
 const handleDeptChange = (deptId) => {
@@ -167,11 +172,11 @@ const handleDeptChange = (deptId) => {
   updateTempRelations()
 }
 
-
 /** 处理 部门-设备 树 被点击 */
 const handleDeptDeviceTreeNodeClick = async (row: { [key: string]: any }) => {
   emit('node-click', row)
   formData.value.deptId = row.id
+  selectedDevices.value = []
   await getDeviceList()
 }
 
@@ -187,13 +192,9 @@ const getDeviceList = async () => {
   }
 }
 
-const removeTempRelation = (deviceIds: number[]) => {
-  tempRelations.value = tempRelations.value.filter(
-    r => !deviceIds.includes(r.deviceId)
-  );
-  selectedDevices.value = selectedDevices.value.filter(
-    id => !deviceIds.includes(id)
-  );
+const removeTempRelation = (deviceId: number) => {
+  tempRelationsMap.value.delete(deviceId)
+  selectedDevices.value = selectedDevices.value.filter(id => id !== deviceId)
 };
 
 const submitRelations = async () => {
@@ -237,6 +238,15 @@ onMounted(async () => {
   padding: 20px;
   margin-bottom: 20px;
   background: white;
+  display: flex;
+  flex-direction: column;
+  height: 100%; /* 根据实际需要调整整体高度 */
+  box-shadow: 0 2px 12px 0 rgba(0,0,0,0.1);
+  transition: box-shadow 0.2s;
+}
+
+.card:hover {
+  box-shadow: 0 4px 16px rgba(0,0,0,0.15);
 }
 
 .list-item {
@@ -264,7 +274,7 @@ onMounted(async () => {
 }
 
 .submit-area {
-  margin-top: 20px;
+  margin-top: 5px;
   text-align: center;
 }
 
@@ -273,49 +283,6 @@ h3 {
   color: #303133;
 }
 
-.radio-item {
-  width: 100%;
-  padding: 8px 12px;
-  border-bottom: 1px solid #f0f0f0;
-}
-
-.radio-item .el-radio {
-  width: 100%;
-  height: 100%;
-}
-
-.radio-item .el-radio__label {
-  display: block;
-  white-space: nowrap;
-  overflow: hidden;
-  text-overflow: ellipsis;
-}
-
-.dept-node {
-  display: flex;
-  align-items: center;
-  gap: 8px;
-  width: 100%;
-  padding: 5px 0;
-
-  :deep(.el-radio) {
-    flex: 1;
-    .el-radio__label {
-      font-size: 14px;
-    }
-  }
-
-  .el-tag {
-    margin-left: auto;
-  }
-}
-
-.card {
-  display: flex;
-  flex-direction: column;
-  height: 600px; /* 根据实际需要调整整体高度 */
-}
-
 .dept-select {
   flex-shrink: 0; /* 防止搜索框被压缩 */
 }
@@ -350,11 +317,6 @@ h3 {
   overflow: hidden;
 }
 
-/* 确保内容区域填充高度 */
-.h-full {
-  height: 100%;
-}
-
 /* 调整树形组件内部滚动 */
 :deep(.el-tree) {
   height: 100%;
@@ -364,12 +326,14 @@ h3 {
 .equal-height-row {
   display: flex;
   align-items: stretch; /* 关键:等高布局 */
+  /* height: 500px; */
 }
 
 .col-height {
   display: flex;
   flex-direction: column;
-  min-height: 600px; /* 统一最小高度 */
+  min-height: 400px;/* 统一最小高度 */
+  /* height: 100% !important; */
 }
 
 </style>

+ 1 - 2
src/views/pms/device/DeptTree2.vue

@@ -63,7 +63,7 @@ const setHeight = () => {
   if (!treeContainer.value) return
   const windowHeight = window.innerHeight
   const containerTop = treeContainer.value.offsetTop
-  treeContainer.value.style.height = `${windowHeight * 0.78}px` // 60px 底部预留
+  treeContainer.value.style.height = `${windowHeight * 0.68}px` // 60px 底部预留
 }
 const handleMenuClick = (action) => {
   switch(action) {
@@ -170,7 +170,6 @@ onUnmounted(() => {
 .tree-container {
   height: v-bind(height);
   overflow: auto; /* 关键:允许滚动 */
-
   :deep(.el-tree) {
     min-height: 100%; /* 确保树撑满容器 */
     > .el-tree-node {