|
@@ -184,17 +184,16 @@
|
|
{{ getDeviceNames(row.deviceIds) }}
|
|
{{ getDeviceNames(row.deviceIds) }}
|
|
</span>
|
|
</span>
|
|
<div v-else>
|
|
<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>
|
|
</div>
|
|
</template>
|
|
</template>
|
|
</el-table-column>
|
|
</el-table-column>
|
|
@@ -231,6 +230,35 @@
|
|
<el-button @click="close">取 消</el-button>
|
|
<el-button @click="close">取 消</el-button>
|
|
</el-form>
|
|
</el-form>
|
|
</ContentWrap>
|
|
</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>
|
|
</template>
|
|
<script setup lang="ts">
|
|
<script setup lang="ts">
|
|
|
|
|
|
@@ -244,7 +272,7 @@ import {IotProjectTaskApi, IotProjectTaskVO} from "@/api/pms/iotprojecttask";
|
|
import {ElMessageBox, ElMessage} from "element-plus";
|
|
import {ElMessageBox, ElMessage} from "element-plus";
|
|
import {useTagsViewStore} from "@/store/modules/tagsView";
|
|
import {useTagsViewStore} from "@/store/modules/tagsView";
|
|
import {companyLevelChildrenDepts} from "@/api/system/dept";
|
|
import {companyLevelChildrenDepts} from "@/api/system/dept";
|
|
-import {IotDeviceVO} from "@/api/pms/device";
|
|
|
|
|
|
+import { IotDeviceApi, IotDeviceVO } from '@/api/pms/device'
|
|
|
|
|
|
const { params, name } = useRoute() // 查询参数
|
|
const { params, name } = useRoute() // 查询参数
|
|
const id = params.id
|
|
const id = params.id
|
|
@@ -255,6 +283,9 @@ const { t } = useI18n() // 国际化
|
|
const message = useMessage() // 消息弹窗
|
|
const message = useMessage() // 消息弹窗
|
|
const deptList = ref<Tree[]>([]) // 树形结构
|
|
const deptList = ref<Tree[]>([]) // 树形结构
|
|
const deviceList = ref<IotDeviceVO[]>([]) // 设备列表
|
|
const deviceList = ref<IotDeviceVO[]>([]) // 设备列表
|
|
|
|
+// 设备映射表(ID->设备对象)
|
|
|
|
+const deviceMap = ref<Record<number, IotDeviceVO>>({});
|
|
|
|
+
|
|
const dialogVisible = ref(true) // 弹窗的是否展示
|
|
const dialogVisible = ref(true) // 弹窗的是否展示
|
|
const dialogTitle = ref('') // 弹窗的标题
|
|
const dialogTitle = ref('') // 弹窗的标题
|
|
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
|
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
|
@@ -348,8 +379,27 @@ const getDeptNames = (deptIds) => {
|
|
};
|
|
};
|
|
|
|
|
|
// 根据设备ID集合获取设备名称
|
|
// 根据设备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([
|
|
const tableData = ref([
|
|
@@ -362,6 +412,8 @@ const tableData = ref([
|
|
technique: '',
|
|
technique: '',
|
|
workloadDesign: '',
|
|
workloadDesign: '',
|
|
deptIds: [],
|
|
deptIds: [],
|
|
|
|
+ deviceIds: [],
|
|
|
|
+ deviceCodes: '',
|
|
remark:'',
|
|
remark:'',
|
|
editData: {},
|
|
editData: {},
|
|
editing:true,
|
|
editing:true,
|
|
@@ -370,6 +422,73 @@ const tableData = ref([
|
|
projectId: ''
|
|
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 () => {
|
|
const open = async () => {
|
|
resetForm()
|
|
resetForm()
|
|
@@ -381,15 +500,42 @@ const open = async () => {
|
|
queryParams.id = id;
|
|
queryParams.id = id;
|
|
const data = await IotProjectTaskApi.getIotProjectTaskPage(queryParams);
|
|
const data = await IotProjectTaskApi.getIotProjectTaskPage(queryParams);
|
|
tableData.value = data.list
|
|
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=>{
|
|
tableData.value.forEach(item=>{
|
|
- item.editData={};
|
|
|
|
|
|
+ item.editData = {
|
|
|
|
+ ...item,
|
|
|
|
+ deviceIds: item.deviceIds ? [...item.deviceIds] : []
|
|
|
|
+ };
|
|
item.originalData={};
|
|
item.originalData={};
|
|
item.errors={};
|
|
item.errors={};
|
|
})
|
|
})
|
|
} finally {
|
|
} finally {
|
|
formLoading.value = false
|
|
formLoading.value = false
|
|
}
|
|
}
|
|
- }else{
|
|
|
|
|
|
+ } else {
|
|
formType.value = 'create';
|
|
formType.value = 'create';
|
|
}
|
|
}
|
|
// 如果有projectId参数,自动选中对应的合同
|
|
// 如果有projectId参数,自动选中对应的合同
|
|
@@ -439,7 +585,7 @@ const submitForm = async () => {
|
|
try {
|
|
try {
|
|
tableData.value.forEach(item=>{
|
|
tableData.value.forEach(item=>{
|
|
item.projectId = formData.value.id;
|
|
item.projectId = formData.value.id;
|
|
- item.deptId = useUserStore().getUser.deptId;
|
|
|
|
|
|
+ // item.deptId = useUserStore().getUser.deptId;
|
|
})
|
|
})
|
|
|
|
|
|
const data = {
|
|
const data = {
|
|
@@ -488,6 +634,7 @@ onMounted(async () => {
|
|
deptList.value = handleTree(await DeptApi.companyLevelChildrenDepts())
|
|
deptList.value = handleTree(await DeptApi.companyLevelChildrenDepts())
|
|
let deptId = useUserStore().getUser.deptId
|
|
let deptId = useUserStore().getUser.deptId
|
|
projectList.value = await IotProjectInfoApi.getIotProjectInfoUser(deptId);
|
|
projectList.value = await IotProjectInfoApi.getIotProjectInfoUser(deptId);
|
|
|
|
+ // 查询当前任务已经选中的设备信息
|
|
open();
|
|
open();
|
|
})
|
|
})
|
|
|
|
|
|
@@ -521,6 +668,8 @@ const addNewRow = () => {
|
|
technique: '',
|
|
technique: '',
|
|
workloadDesign: '',
|
|
workloadDesign: '',
|
|
deptIds: [],
|
|
deptIds: [],
|
|
|
|
+ deviceIds: [],
|
|
|
|
+ deviceCodes: '',
|
|
remark:'',
|
|
remark:'',
|
|
editing: true,
|
|
editing: true,
|
|
editData: {
|
|
editData: {
|
|
@@ -530,6 +679,8 @@ const addNewRow = () => {
|
|
technique: '',
|
|
technique: '',
|
|
workloadDesign: '',
|
|
workloadDesign: '',
|
|
deptIds: [],
|
|
deptIds: [],
|
|
|
|
+ deviceIds: [],
|
|
|
|
+ deviceCodes: '',
|
|
remark:'',
|
|
remark:'',
|
|
},
|
|
},
|
|
originalData: {},
|
|
originalData: {},
|
|
@@ -552,7 +703,9 @@ const editRow = (row) => {
|
|
technique: row.technique,
|
|
technique: row.technique,
|
|
workloadDesign: row.workloadDesign,
|
|
workloadDesign: row.workloadDesign,
|
|
deptIds: row.deptIds,
|
|
deptIds: row.deptIds,
|
|
- remark:row.remark,
|
|
|
|
|
|
+ deviceIds: row.deviceIds,
|
|
|
|
+ deviceCodes: row.deviceCodes,
|
|
|
|
+ remark: row.remark,
|
|
};
|
|
};
|
|
// 进入编辑状态
|
|
// 进入编辑状态
|
|
row.editing = true;
|
|
row.editing = true;
|
|
@@ -590,6 +743,23 @@ const saveRow = (row) => {
|
|
row.technique = row.editData.technique;
|
|
row.technique = row.editData.technique;
|
|
row.workloadDesign = row.editData.workloadDesign;
|
|
row.workloadDesign = row.editData.workloadDesign;
|
|
row.deptIds = row.editData.deptIds;
|
|
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.remark = row.editData.remark;
|
|
// 退出编辑状态
|
|
// 退出编辑状态
|
|
row.editing = false;
|
|
row.editing = false;
|
|
@@ -621,6 +791,8 @@ const saveAll = () => {
|
|
row.technique = row.editData.technique;
|
|
row.technique = row.editData.technique;
|
|
row.workloadDesign = row.editData.workloadDesign;
|
|
row.workloadDesign = row.editData.workloadDesign;
|
|
row.deptIds = row.editData.deptIds;
|
|
row.deptIds = row.editData.deptIds;
|
|
|
|
+ row.deviceIds = row.editData.deviceIds;
|
|
|
|
+ row.deviceCodes = row.editData.deviceCodes;
|
|
row.remark = row.editData.remark;
|
|
row.remark = row.editData.remark;
|
|
}
|
|
}
|
|
});
|
|
});
|
|
@@ -639,6 +811,8 @@ const cancelEdit = (row) => {
|
|
row.technique = row.originalData.technique;
|
|
row.technique = row.originalData.technique;
|
|
row.workloadDesign = row.originalData.workloadDesign;
|
|
row.workloadDesign = row.originalData.workloadDesign;
|
|
row.deptIds = row.originalData.deptIds;
|
|
row.deptIds = row.originalData.deptIds;
|
|
|
|
+ row.deviceIds = row.originalData.deviceIds;
|
|
|
|
+ row.deviceCodes = row.originalData.deviceCodes;
|
|
row.remark = row.originalData.remark;
|
|
row.remark = row.originalData.remark;
|
|
} else {
|
|
} else {
|
|
// 如果是新增行,则删除
|
|
// 如果是新增行,则删除
|
|
@@ -657,3 +831,18 @@ const deleteRow = (index) => {
|
|
ElMessage.success('行已删除');
|
|
ElMessage.success('行已删除');
|
|
};
|
|
};
|
|
</script>
|
|
</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>
|