|
@@ -205,6 +205,34 @@
|
|
|
</el-tooltip>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
+
|
|
|
+ <el-table-column prop="responsiblePerson" label="责任人">
|
|
|
+ <template #default="{ row }">
|
|
|
+ <el-tooltip
|
|
|
+ :content="getAllResponsiblePersonNames(row.responsiblePerson)"
|
|
|
+ placement="top"
|
|
|
+ :disabled="!row.responsiblePerson || row.responsiblePerson.length <= 2"
|
|
|
+ >
|
|
|
+ <span v-if="!row.editing" class="responsible-names">
|
|
|
+ {{ getResponsiblePersonNames(row.responsiblePerson) }}
|
|
|
+ </span>
|
|
|
+ <div v-else>
|
|
|
+ <el-button
|
|
|
+ @click="openResponsiblePersonDialog(row)"
|
|
|
+ type="primary"
|
|
|
+ size="small"
|
|
|
+ >
|
|
|
+ 选择责任人
|
|
|
+ </el-button>
|
|
|
+ <!--
|
|
|
+ <span v-if="row.editData.responsiblePersonNames" style="margin-left: 8px;">
|
|
|
+ {{ row.editData.responsiblePersonNames }}
|
|
|
+ </span> -->
|
|
|
+ </div>
|
|
|
+ </el-tooltip>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+
|
|
|
<el-table-column prop="remark" label="备注">
|
|
|
<template #default="{ row }">
|
|
|
<span v-if="!row.editing">{{ row.remark }}</span>
|
|
@@ -243,7 +271,7 @@
|
|
|
<el-dialog
|
|
|
v-model="deviceDialogVisible"
|
|
|
title="选择施工设备"
|
|
|
- width="800px"
|
|
|
+ width="1000px"
|
|
|
:before-close="handleDeviceDialogClose"
|
|
|
class="device-select-dialog"
|
|
|
>
|
|
@@ -283,6 +311,44 @@
|
|
|
</template>
|
|
|
</el-dialog>
|
|
|
|
|
|
+ <!-- 新增责任人选择对话框 -->
|
|
|
+ <el-dialog
|
|
|
+ v-model="responsiblePersonDialogVisible"
|
|
|
+ title="选择责任人"
|
|
|
+ width="1000px"
|
|
|
+ :before-close="handleResponsiblePersonDialogClose"
|
|
|
+ class="responsible-person-select-dialog"
|
|
|
+ >
|
|
|
+ <div class="transfer-container">
|
|
|
+ <el-transfer
|
|
|
+ v-model="selectedResponsiblePersonIds"
|
|
|
+ :data="responsiblePersonList"
|
|
|
+ :titles="['可选人员', '已选人员']"
|
|
|
+ :props="{ key: 'id', label: 'nickname' }"
|
|
|
+ filterable
|
|
|
+ class="transfer-component"
|
|
|
+ >
|
|
|
+ <template #default="{ option }">
|
|
|
+ <el-tooltip
|
|
|
+ effect="dark"
|
|
|
+ placement="top"
|
|
|
+ :content="`${option.nickname} - ${option.deptName || '未分配部门'}`"
|
|
|
+ >
|
|
|
+ <span class="transfer-option-text">
|
|
|
+ {{ option.nickname }} - {{ option.deptName || '未分配部门' }}
|
|
|
+ </span>
|
|
|
+ </el-tooltip>
|
|
|
+ </template>
|
|
|
+ </el-transfer>
|
|
|
+ </div>
|
|
|
+ <template #footer>
|
|
|
+ <span class="dialog-footer">
|
|
|
+ <el-button @click="handleResponsiblePersonDialogClose">取消</el-button>
|
|
|
+ <el-button type="primary" @click="confirmResponsiblePersonSelection">确定</el-button>
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
</template>
|
|
|
<script setup lang="ts">
|
|
|
|
|
@@ -297,6 +363,8 @@ import {ElMessageBox, ElMessage} from "element-plus";
|
|
|
import {useTagsViewStore} from "@/store/modules/tagsView";
|
|
|
import {companyLevelChildrenDepts} from "@/api/system/dept";
|
|
|
import { IotDeviceApi, IotDeviceVO } from '@/api/pms/device'
|
|
|
+import * as UserApi from "@/api/system/user";
|
|
|
+import {UserVO} from "@/api/system/user";
|
|
|
|
|
|
const { params, name } = useRoute() // 查询参数
|
|
|
const id = params.id
|
|
@@ -318,6 +386,12 @@ const projectList = ref<IotProjectInfoVO[]>([])
|
|
|
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
|
|
const loading = ref(true) // 列表的加载中
|
|
|
|
|
|
+// 新增责任人相关变量
|
|
|
+const responsiblePersonDialogVisible = ref(false);
|
|
|
+const responsiblePersonList = ref([]); // 所有责任人列表
|
|
|
+const selectedResponsiblePersonIds = ref([]); // 选中的责任人ID
|
|
|
+const currentEditingRowForResponsible = ref(null); // 当前正在编辑责任人的行
|
|
|
+
|
|
|
/** 项目信息 表单 */
|
|
|
defineOptions({ name: 'IotProjectTaskInfo' })
|
|
|
|
|
@@ -338,6 +412,7 @@ const formData = ref({
|
|
|
manufacturerId: undefined,
|
|
|
userName: undefined,
|
|
|
userId: undefined,
|
|
|
+ deptId: undefined, // 新增项目部门ID字段
|
|
|
})
|
|
|
|
|
|
const close = () => {
|
|
@@ -358,6 +433,7 @@ const getProjectInfo = (contractId: number) => {
|
|
|
formData.value.manufactureName = project.manufactureName;
|
|
|
formData.value.manufacturerId = project.manufacturerId;
|
|
|
formData.value.id = project.id;
|
|
|
+ formData.value.deptId = project.deptId; // 保存项目部门ID
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -442,6 +518,89 @@ const tableData = ref([
|
|
|
},
|
|
|
]);
|
|
|
|
|
|
+// 打开责任人选择对话框
|
|
|
+const openResponsiblePersonDialog = async (row) => {
|
|
|
+ if (!formData.value.deptId) {
|
|
|
+ ElMessage.warning('请先选择合同以确定项目部门');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ currentEditingRowForResponsible.value = row;
|
|
|
+ selectedResponsiblePersonIds.value = [...(row.editData.responsiblePerson || [])];
|
|
|
+
|
|
|
+ try {
|
|
|
+ const params = {
|
|
|
+ deptIds: [formData.value.deptId] // 使用当前项目所属部门的deptId
|
|
|
+ };
|
|
|
+ const response = await UserApi.companyDeptsEmployee(params);
|
|
|
+ responsiblePersonList.value = response;
|
|
|
+ responsiblePersonDialogVisible.value = true;
|
|
|
+ } catch (error) {
|
|
|
+ ElMessage.error('获取责任人列表失败');
|
|
|
+ console.error('获取责任人列表失败:', error);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 确认责任人选择
|
|
|
+const confirmResponsiblePersonSelection = () => {
|
|
|
+ if (currentEditingRowForResponsible.value) {
|
|
|
+ // 更新责任人ID
|
|
|
+ currentEditingRowForResponsible.value.editData.responsiblePerson = [...selectedResponsiblePersonIds.value];
|
|
|
+
|
|
|
+ // 更新责任人名称显示
|
|
|
+ const selectedPersons = responsiblePersonList.value.filter(person =>
|
|
|
+ selectedResponsiblePersonIds.value.includes(person.id)
|
|
|
+ );
|
|
|
+ currentEditingRowForResponsible.value.editData.responsiblePersonNames = selectedPersons
|
|
|
+ .map(person => person.nickname)
|
|
|
+ .join(', ');
|
|
|
+ }
|
|
|
+
|
|
|
+ responsiblePersonDialogVisible.value = false;
|
|
|
+};
|
|
|
+
|
|
|
+// 关闭责任人选择对话框
|
|
|
+const handleResponsiblePersonDialogClose = () => {
|
|
|
+ responsiblePersonDialogVisible.value = false;
|
|
|
+};
|
|
|
+
|
|
|
+// 根据责任人ID获取责任人名称
|
|
|
+const getResponsiblePersonNames = (responsiblePersonIds: number[]) => {
|
|
|
+ if (!responsiblePersonIds || responsiblePersonIds.length === 0) return '';
|
|
|
+
|
|
|
+ // 获取所有有效责任人名称
|
|
|
+ const personNames = responsiblePersonIds
|
|
|
+ .map(id => {
|
|
|
+ const person = responsiblePersonList.value.find(p => p.id === id);
|
|
|
+ return person ? person.nickname : '';
|
|
|
+ })
|
|
|
+ .filter(name => name !== undefined && name !== '');
|
|
|
+
|
|
|
+ if (personNames.length === 0) return '';
|
|
|
+
|
|
|
+ // 如果责任人数量超过2个,显示前两个加省略号
|
|
|
+ if (personNames.length > 2) {
|
|
|
+ return `${personNames[0]}, ${personNames[1]}...`;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 责任人数量不超过2个,正常显示所有
|
|
|
+ return personNames.join(', ');
|
|
|
+};
|
|
|
+
|
|
|
+// 获取所有责任人名称(用于tooltip提示)
|
|
|
+const getAllResponsiblePersonNames = (responsiblePersonIds: number[]) => {
|
|
|
+ if (!responsiblePersonIds || responsiblePersonIds.length === 0) return '无责任人';
|
|
|
+
|
|
|
+ const personNames = responsiblePersonIds
|
|
|
+ .map(id => {
|
|
|
+ const person = responsiblePersonList.value.find(p => p.id === id);
|
|
|
+ return person ? person.nickname : '未知人员';
|
|
|
+ })
|
|
|
+ .filter(name => name !== '未知人员');
|
|
|
+
|
|
|
+ return personNames.join(', ') || '无有效责任人';
|
|
|
+};
|
|
|
+
|
|
|
// 设备选择相关变量
|
|
|
const deviceDialogVisible = ref(false);
|
|
|
const currentEditingRow = ref(null);
|
|
@@ -522,10 +681,16 @@ const open = async () => {
|
|
|
|
|
|
// 1. 收集所有设备ID
|
|
|
const allDeviceIds = new Set<number>();
|
|
|
+ // 收集所有责任人ID
|
|
|
+ const allResponsiblePersonIds = new Set<number>();
|
|
|
+
|
|
|
data.list.forEach(item => {
|
|
|
if (item.deviceIds?.length) {
|
|
|
item.deviceIds.forEach(id => allDeviceIds.add(id));
|
|
|
}
|
|
|
+ if (item.responsiblePerson?.length) {
|
|
|
+ item.responsiblePerson.forEach(id => allResponsiblePersonIds.add(id));
|
|
|
+ }
|
|
|
});
|
|
|
|
|
|
// 2. 批量获取设备信息
|
|
@@ -543,6 +708,18 @@ const open = async () => {
|
|
|
});
|
|
|
}
|
|
|
|
|
|
+ // 批量获取责任人信息
|
|
|
+ if (allResponsiblePersonIds.size > 0) {
|
|
|
+ const personIdsArray = Array.from(allResponsiblePersonIds);
|
|
|
+ const params = {
|
|
|
+ userIds: personIdsArray
|
|
|
+ };
|
|
|
+ const persons = await UserApi.companyDeptsEmployee(params);
|
|
|
+
|
|
|
+ // 更新责任人列表
|
|
|
+ responsiblePersonList.value = persons;
|
|
|
+ }
|
|
|
+
|
|
|
tableData.value.forEach(item=>{
|
|
|
item.editData = {
|
|
|
...item,
|
|
@@ -689,6 +866,8 @@ const addNewRow = () => {
|
|
|
deptIds: [],
|
|
|
deviceIds: [],
|
|
|
deviceCodes: '',
|
|
|
+ responsiblePerson: [], // 新增责任人字段
|
|
|
+ responsiblePersonNames: '', // 新增责任人名称字段
|
|
|
remark:'',
|
|
|
editing: true,
|
|
|
editData: {
|
|
@@ -700,6 +879,8 @@ const addNewRow = () => {
|
|
|
deptIds: [],
|
|
|
deviceIds: [],
|
|
|
deviceCodes: '',
|
|
|
+ responsiblePerson: [], // 新增责任人字段
|
|
|
+ responsiblePersonNames: '', // 新增责任人名称字段
|
|
|
remark:'',
|
|
|
},
|
|
|
originalData: {},
|
|
@@ -724,6 +905,8 @@ const editRow = (row) => {
|
|
|
deptIds: row.deptIds,
|
|
|
deviceIds: row.deviceIds,
|
|
|
deviceCodes: row.deviceCodes,
|
|
|
+ responsiblePerson: row.responsiblePerson ? [...row.responsiblePerson] : [], // 复制责任人数组
|
|
|
+ responsiblePersonNames: row.responsiblePersonNames, // 复制责任人名称
|
|
|
remark: row.remark,
|
|
|
};
|
|
|
// 进入编辑状态
|
|
@@ -777,6 +960,9 @@ const saveRow = (row) => {
|
|
|
// row.deviceCodes = row.editData.deviceCodes;
|
|
|
// 关键修改:根据设备ID列表生成设备代码
|
|
|
|
|
|
+ row.responsiblePerson = row.editData.responsiblePerson; // 保存责任人ID
|
|
|
+ row.responsiblePersonNames = row.editData.responsiblePersonNames; // 保存责任人名称
|
|
|
+
|
|
|
if (currentEditingRow.value) {
|
|
|
// 更新设备ID
|
|
|
currentEditingRow.value.editData.deviceIds = [...selectedDeviceIds.value];
|
|
@@ -823,6 +1009,8 @@ const saveAll = () => {
|
|
|
row.deptIds = row.editData.deptIds;
|
|
|
row.deviceIds = row.editData.deviceIds;
|
|
|
row.deviceCodes = row.editData.deviceCodes;
|
|
|
+ row.responsiblePerson = row.editData.responsiblePerson; // 保存责任人ID
|
|
|
+ row.responsiblePersonNames = row.editData.responsiblePersonNames; // 保存责任人名称
|
|
|
row.remark = row.editData.remark;
|
|
|
}
|
|
|
});
|
|
@@ -843,6 +1031,8 @@ const cancelEdit = (row) => {
|
|
|
row.deptIds = row.originalData.deptIds;
|
|
|
row.deviceIds = row.originalData.deviceIds;
|
|
|
row.deviceCodes = row.originalData.deviceCodes;
|
|
|
+ row.responsiblePerson = row.originalData.responsiblePerson; // 恢复责任人ID
|
|
|
+ row.responsiblePersonNames = row.originalData.responsiblePersonNames; // 恢复责任人名称
|
|
|
row.remark = row.originalData.remark;
|
|
|
} else {
|
|
|
// 如果是新增行,则删除
|
|
@@ -885,6 +1075,12 @@ const deleteRow = (index) => {
|
|
|
/* 2. 穿梭框组件:控制宽度,避免过窄或过宽 */
|
|
|
.transfer-component {
|
|
|
width: 100%; /* 占对话框90%宽度,兼顾美观和内容显示 */
|
|
|
+ min-width: 600px;
|
|
|
+}
|
|
|
+
|
|
|
+/* 3. 直接调整 el-transfer 左右窗口的宽度 */
|
|
|
+:deep(.el-transfer-panel) {
|
|
|
+ width: 40% !important; /* 强制设置左右面板宽度,确保两侧面板对等 */
|
|
|
}
|
|
|
|
|
|
/* 3. 深度选择器:修改el-transfer选项样式(解决内容省略问题) */
|
|
@@ -910,4 +1106,16 @@ const deleteRow = (index) => {
|
|
|
max-width: 200px; /* 根据实际列宽调整 */
|
|
|
}
|
|
|
|
|
|
+:deep(.el-transfer-panel__list) {
|
|
|
+ width: 100% !important; /* 使面板内部内容宽度占满 */
|
|
|
+}
|
|
|
+
|
|
|
+/* 责任人名称显示区域样式 */
|
|
|
+.responsible-names {
|
|
|
+ white-space: nowrap;
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ max-width: 200px; /* 根据实际列宽调整 */
|
|
|
+}
|
|
|
+
|
|
|
</style>
|