Browse Source

pms 任务 选择设备

zhangcl 1 month ago
parent
commit
ca49da8edf
2 changed files with 212 additions and 18 deletions
  1. 5 0
      src/api/pms/device/index.ts
  2. 207 18
      src/views/pms/iotprojecttask/IotProjectTaskForm.vue

+ 5 - 0
src/api/pms/device/index.ts

@@ -84,6 +84,11 @@ export const IotDeviceApi = {
     return await request.get({ url: `/rq/iot-device/deviceAssociateBomPage`, params })
   },
 
+  // 项目-任务 根据选择的部门筛选设备 忽略数据权限
+  getDevicesByDepts: async (params: any) => {
+    return await request.get({ url: `/rq/iot-device/getDevicesByDepts`, params })
+  },
+
   // 查询 设备 bom关联 列表
   deviceAssociateBomList: async (params: any) => {
     return await request.get({ url: `/rq/iot-device/deviceAssociateBomList`, params })

+ 207 - 18
src/views/pms/iotprojecttask/IotProjectTaskForm.vue

@@ -184,17 +184,16 @@
                 {{ getDeviceNames(row.deviceIds) }}
               </span>
               <div v-else>
-                <el-tree-select
-                  multiple
-                  v-model="row.editData.deviceIds"
-                  :data="deviceList"
-                  :props="defaultProps"
-                  check-strictly
-                  node-key="id"
-                  filterable
-                  placeholder="请选择施工设备"
-                  clearable
-                />
+                <el-button
+                  @click="openDeviceDialog(row)"
+                  type="primary"
+                  size="small"
+                >
+                  选择设备
+                </el-button>
+                <span v-if="row.editData.deviceCodes" style="margin-left: 8px;">
+                  {{ row.editData.deviceCodes }}
+                </span>
               </div>
             </template>
           </el-table-column>
@@ -231,6 +230,35 @@
       <el-button @click="close">取 消</el-button>
     </el-form>
   </ContentWrap>
+
+  <!-- 设备选择对话框 -->
+  <el-dialog
+    v-model="deviceDialogVisible"
+    title="选择施工设备"
+    width="800px"
+    :before-close="handleDeviceDialogClose"
+  >
+    <el-transfer
+      v-model="selectedDeviceIds"
+      :data="filteredDeviceList"
+      :titles="['可选设备', '已选设备']"
+      :props="{ key: 'id', label: 'deviceCode' }"
+      filterable
+      style="text-align: left; display: inline-block"
+      @change="handleTransferChange"
+    >
+      <template #default="{ option }">
+        <span>{{ option.deviceCode }} - {{ option.deviceName }}</span>
+      </template>
+    </el-transfer>
+    <template #footer>
+      <span class="dialog-footer">
+        <el-button @click="handleDeviceDialogClose">取消</el-button>
+        <el-button type="primary" @click="confirmDeviceSelection">确定</el-button>
+      </span>
+    </template>
+  </el-dialog>
+
 </template>
 <script setup lang="ts">
 
@@ -244,7 +272,7 @@ import {IotProjectTaskApi, IotProjectTaskVO} from "@/api/pms/iotprojecttask";
 import {ElMessageBox, ElMessage} from "element-plus";
 import {useTagsViewStore} from "@/store/modules/tagsView";
 import {companyLevelChildrenDepts} from "@/api/system/dept";
-import {IotDeviceVO} from "@/api/pms/device";
+import { IotDeviceApi, IotDeviceVO } from '@/api/pms/device'
 
 const { params, name } = useRoute() // 查询参数
 const id = params.id
@@ -255,6 +283,9 @@ const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 const deptList = ref<Tree[]>([]) // 树形结构
 const deviceList = ref<IotDeviceVO[]>([]) // 设备列表
+// 设备映射表(ID->设备对象)
+const deviceMap = ref<Record<number, IotDeviceVO>>({});
+
 const dialogVisible = ref(true) // 弹窗的是否展示
 const dialogTitle = ref('') // 弹窗的标题
 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
@@ -348,8 +379,27 @@ const getDeptNames = (deptIds) => {
 };
 
 // 根据设备ID集合获取设备名称
-const getDeviceNames = (deviceIds) => {
-  return '';
+/* const getDeviceNames = (deviceIds) => {
+  if (!deviceIds || deviceIds.length === 0) return '';
+
+  const names = [];
+  deviceIds.forEach(id => {
+    const device = deviceList.value.find(d => d.id === id);
+    if (device) {
+      names.push(device.deviceCode);
+    }
+  });
+  return names.join(', ');
+}; */
+
+const getDeviceNames = (deviceIds: number[]) => {
+  if (!deviceIds || deviceIds.length === 0) return '';
+  return deviceIds.map(id => deviceMap.value[id]?.deviceCode || '未知设备')
+    .filter(name => name !== '未知设备')
+    .join(', ');
+
+
+
 };
 
 const tableData = ref([
@@ -362,6 +412,8 @@ const tableData = ref([
     technique: '',
     workloadDesign: '',
     deptIds: [],
+    deviceIds: [],
+    deviceCodes: '',
     remark:'',
     editData: {},
     editing:true,
@@ -370,6 +422,73 @@ const tableData = ref([
     projectId: ''
   },
 ]);
+
+// 设备选择相关变量
+const deviceDialogVisible = ref(false);
+const currentEditingRow = ref(null);
+const selectedDeviceIds = ref([]);
+const filteredDeviceList = ref([]);
+
+// 打开设备选择对话框
+const openDeviceDialog = async (row) => {
+  if (!row.editData.deptIds || row.editData.deptIds.length === 0) {
+    ElMessage.warning('请先选择施工队伍');
+    return;
+  }
+
+  currentEditingRow.value = row;
+  selectedDeviceIds.value = [...(row.editData.deviceIds || [])];
+
+  try {
+    const params = {
+      deptIds: row.editData.deptIds
+    };
+    const data = await IotDeviceApi.getDevicesByDepts(params);
+
+    filteredDeviceList.value = data;
+    deviceDialogVisible.value = true;
+
+  } catch (error) {
+    ElMessage.error('获取设备列表失败');
+    console.error('获取设备列表失败:', error);
+  }
+};
+
+// 处理穿梭框变化
+const handleTransferChange = (value, direction, movedKeys) => {
+  // 可以添加额外的处理逻辑
+};
+
+// 确认设备选择
+const confirmDeviceSelection = () => {
+  if (currentEditingRow.value) {
+    selectedDeviceIds.value.forEach(id => {
+      const device = filteredDeviceList.value.find(d => d.id === id);
+      if (device && !deviceMap.value[id]) {
+        deviceMap.value[id] = device;
+      }
+    });
+
+    // 更新设备ID
+    currentEditingRow.value.editData.deviceIds = [...selectedDeviceIds.value];
+
+    // 更新设备代码显示
+    const selectedDevices = filteredDeviceList.value.filter(device =>
+      selectedDeviceIds.value.includes(device.id)
+    );
+    currentEditingRow.value.editData.deviceCodes = selectedDevices
+      .map(device => device.deviceCode)
+      .join(', ');
+  }
+
+  deviceDialogVisible.value = false;
+};
+
+// 关闭设备选择对话框
+const handleDeviceDialogClose = () => {
+  deviceDialogVisible.value = false;
+};
+
 /** 打开弹窗 */
 const open = async () => {
   resetForm()
@@ -381,15 +500,42 @@ const open = async () => {
       queryParams.id = id;
       const data = await IotProjectTaskApi.getIotProjectTaskPage(queryParams);
       tableData.value = data.list
+
+      // 1. 收集所有设备ID
+      const allDeviceIds = new Set<number>();
+      data.list.forEach(item => {
+        if (item.deviceIds?.length) {
+          item.deviceIds.forEach(id => allDeviceIds.add(id));
+        }
+      });
+
+      // 2. 批量获取设备信息
+      if (allDeviceIds.size > 0) {
+        const deviceIdsArray = Array.from(allDeviceIds);
+        const devices = await IotDeviceApi.getDevicesByDepts({
+          deviceIds: deviceIdsArray
+        });
+
+        // 3. 更新设备列表和映射表
+        deviceList.value = devices;
+        deviceMap.value = {};
+        devices.forEach(device => {
+          deviceMap.value[device.id] = device;
+        });
+      }
+
       tableData.value.forEach(item=>{
-        item.editData={};
+        item.editData = {
+          ...item,
+          deviceIds: item.deviceIds ? [...item.deviceIds] : []
+        };
         item.originalData={};
         item.errors={};
       })
     } finally {
       formLoading.value = false
     }
-  }else{
+  } else {
     formType.value = 'create';
   }
   // 如果有projectId参数,自动选中对应的合同
@@ -439,7 +585,7 @@ const submitForm = async () => {
   try {
     tableData.value.forEach(item=>{
       item.projectId = formData.value.id;
-      item.deptId = useUserStore().getUser.deptId;
+      // item.deptId = useUserStore().getUser.deptId;
     })
 
     const data = {
@@ -488,6 +634,7 @@ onMounted(async () => {
   deptList.value = handleTree(await DeptApi.companyLevelChildrenDepts())
   let deptId = useUserStore().getUser.deptId
   projectList.value = await IotProjectInfoApi.getIotProjectInfoUser(deptId);
+  // 查询当前任务已经选中的设备信息
   open();
 })
 
@@ -521,6 +668,8 @@ const addNewRow = () => {
     technique: '',
     workloadDesign: '',
     deptIds: [],
+    deviceIds: [],
+    deviceCodes: '',
     remark:'',
     editing: true,
     editData: {
@@ -530,6 +679,8 @@ const addNewRow = () => {
       technique: '',
       workloadDesign: '',
       deptIds: [],
+      deviceIds: [],
+      deviceCodes: '',
       remark:'',
     },
     originalData: {},
@@ -552,7 +703,9 @@ const editRow = (row) => {
     technique: row.technique,
     workloadDesign: row.workloadDesign,
     deptIds: row.deptIds,
-    remark:row.remark,
+    deviceIds: row.deviceIds,
+    deviceCodes: row.deviceCodes,
+    remark: row.remark,
   };
   // 进入编辑状态
   row.editing = true;
@@ -590,6 +743,23 @@ const saveRow = (row) => {
   row.technique = row.editData.technique;
   row.workloadDesign = row.editData.workloadDesign;
   row.deptIds = row.editData.deptIds;
+  row.deviceIds = row.editData.deviceIds;
+  // row.deviceCodes = row.editData.deviceCodes;
+  // 关键修改:根据设备ID列表生成设备代码
+
+  if (currentEditingRow.value) {
+    // 更新设备ID
+    currentEditingRow.value.editData.deviceIds = [...selectedDeviceIds.value];
+    // 更新设备代码显示
+    const selectedDevices = filteredDeviceList.value.filter(device =>
+      selectedDeviceIds.value.includes(device.id)
+    );
+    currentEditingRow.value.editData.deviceCodes = selectedDevices
+      .map(device => device.deviceCode)
+      .join(', ');
+    row.deviceCodes = currentEditingRow.value.editData.deviceCodes;
+  }
+
   row.remark = row.editData.remark;
   // 退出编辑状态
   row.editing = false;
@@ -621,6 +791,8 @@ const saveAll = () => {
       row.technique = row.editData.technique;
       row.workloadDesign = row.editData.workloadDesign;
       row.deptIds = row.editData.deptIds;
+      row.deviceIds = row.editData.deviceIds;
+      row.deviceCodes = row.editData.deviceCodes;
       row.remark = row.editData.remark;
     }
   });
@@ -639,6 +811,8 @@ const cancelEdit = (row) => {
     row.technique = row.originalData.technique;
     row.workloadDesign = row.originalData.workloadDesign;
     row.deptIds = row.originalData.deptIds;
+    row.deviceIds = row.originalData.deviceIds;
+    row.deviceCodes = row.originalData.deviceCodes;
     row.remark = row.originalData.remark;
   } else {
     // 如果是新增行,则删除
@@ -657,3 +831,18 @@ const deleteRow = (index) => {
   ElMessage.success('行已删除');
 };
 </script>
+
+<style scoped>
+.edit-input {
+  margin-right: 10px;
+}
+.error-message {
+  color: #f56c6c;
+  font-size: 12px;
+  margin-top: 5px;
+}
+.action-cell {
+  display: flex;
+  gap: 8px;
+}
+</style>