<template> <!-- 项目审批、计划管理 --> <div class="publicContainer"> <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch"> <el-form-item label="项目名称:" prop="projectName"> <el-input v-model="queryParams.projectName" placeholder="请输入项目名称" clearable @keyup.enter="handleQuery" style="width: 240px" /> </el-form-item> <el-form-item label="计划时间" prop="timer"> <el-date-picker style="width: 240px" format="YYYY-MM-DD" value-format="YYYY-MM-DD" v-model="queryParams.timer" type="daterange" unlink-panels range-separator="至" start-placeholder="开始时间" end-placeholder="结束时间" /> </el-form-item> <el-form-item> <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button> <el-button icon="Refresh" @click="resetQuery">重置</el-button> </el-form-item> </el-form> <!-- 操作栏 --> <el-row :gutter="10" class="mb8"> <el-col :span="1.5"> <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['system:post:add']">新增</el-button> </el-col> <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar> </el-row> <!-- 表格 --> <el-table v-loading="loading" :data="postList" @selection-change="handleSelectionChange" max-height="500"> <el-table-column label="序号" type="index" width="60" /> <el-table-column :label="i.label" :prop="i.props" show-overflow-tooltip v-for="i in projectPlanCloum"> <template #default="{ row }" v-if="i.props == 'startTime'"> {{ row.startTime.substring(0, 10) }} </template> <template #default="{ row }" v-if="i.props == 'endTime'"> {{ row.endTime.substring(0, 10) }} </template> </el-table-column> <el-table-column label="操作" width="250" class-name="small-padding fixed-width"> <template #default="scope"> <el-button link type="primary" icon="View" @click="handleUpdate(scope.row, 1)">详情</el-button> <el-button link type="warning" icon="Edit" @click="handleUpdate(scope.row, 2)" v-hasPermi="['system:post:edit']">修改</el-button> <el-button link type="danger" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:post:remove']">删除</el-button> </template> </el-table-column> </el-table> <!-- 分页 --> <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" /> <!-- 添加或修改项目计划信息对话框 --> <el-dialog :title="title" v-model="open" width="1390px"> <el-form ref="postRef" :model="form" label-width="120px" :inline="true" :disabled="isShow == 1" :rules="projectPlanRules"> <div class="biaoti">基本信息</div> <el-form-item label="项目名称:" style="width: 45%" prop="projectNo"> <el-select :disabled="isShow == 2" v-model="form.projectNo" placeholder="请选择项目" clearable style="width: 100%" @change="TouBiaoInfo(ProjectListData, 'add')" > <el-option v-for="(dict, index) in ProjectListData" :key="dict.projectNo" :label="dict.projectName" :value="dict.projectNo" /> </el-select> </el-form-item> <el-form-item label="项目编号:" style="width: 45%" prop="projectNo"> <el-input disabled v-model="form.projectNo" placeholder="请先选择项目" /> </el-form-item> <el-form-item label="项目开始日期:" style="width: 45%" prop="startTime"> <el-date-picker style="width: 100%" disabled v-model="form.startTime" type="date" placeholder="请选择项目开始日期" format="YYYY-MM-DD" value-format="YYYY-MM-DD" /> </el-form-item> <el-form-item label="项目交付日期:" style="width: 45%" prop="endTime"> <el-date-picker style="width: 100%" disabled v-model="form.endTime" type="date" placeholder="请选择项目交付日期" format="YYYY-MM-DD" value-format="YYYY-MM-DD" /> </el-form-item> <el-form-item label="项目填报日期:" style="width: 45%" prop="projectFillTime"> <el-date-picker style="width: 100%" v-model="form.projectFillTime" type="date" placeholder="请选择项目填报日期" format="YYYY-MM-DD" value-format="YYYY-MM-DD" /> </el-form-item> <el-form-item label="项目责任人:" style="width: 45%" prop="chargeUser"> <el-input v-model="form.chargeUser" placeholder="请输入项目责任人" disabled /> </el-form-item> <el-form-item label="备注:" prop="remark" style="width: 92.5%"> <el-input v-model="form.remark" :autosize="{ minRows: 5, maxRows: 7 }" type="textarea" placeholder="请输入备注" /> </el-form-item> <el-form-item label="附件:" style="width: 93%"> <ImageFileUpload :limit="3" :saveFileArr="fileList1" :listType="'text'" :fileType="['csv', 'xls', 'xlsx']" :refField="'coverPhotos'" :refType="'proProjectPlanInfo'" ></ImageFileUpload> </el-form-item> <el-divider content-position="left">进度汇报明细</el-divider> <!-- <div style="text-align: right;" v-show="isAddProjetc"> --> <div style="text-align: right"> <el-button type="primary" @click="onCheck({}, 1, '新增项目节点')">新增项目节点</el-button> </div> <el-table :data="tableData" style="width: 100%" row-key="id" default-expand-all :tree-prop="{ children: 'children' }"> <el-table-column prop="nodeName" label="一级节点" width="180" /> <el-table-column prop="planStartTime" label="计划日期起" /> <el-table-column prop="planEndTime" label="计划日期止" /> <el-table-column prop="estimatedWorkHours" label="预算工时" /> <el-table-column prop="dutyUserId" label="负责人"> <template #default="{ row }"> <span>{{ getStateName(row.dutyUserId) }}</span> </template> </el-table-column> <el-table-column prop="outputData" label="输出资料" /> <el-table-column prop="remark" label="备注" /> <el-table-column label="操作" class-name="nodename" fixde="right" width="250"> <template #default="{ row }"> <el-button v-show="row.tier == 1 || row.tier == 2" link type="success" @click="onCheck(row, 1, `新增${row.tier == 1 ? '二级节点' : '三级节点'}`)" >新增{{ row.tier == 1 ? '二级' : '三级' }}节点</el-button > <el-button link type="primary" @click="onCheck(row, 2, `编辑${row.tier == 1 ? '一级节点' : row.tier == 2 ? '二级节点' : '三级节点'}`)" >编辑</el-button > <el-button link type="danger" @click="onCheck(row, 3)">删除</el-button> </template> </el-table-column> </el-table> </el-form> <template #footer> <div class="dialog-footer"> <el-button v-if="isShow != 1" type="primary" @click="submitForm">保 存</el-button> <el-button @click="cancel">关闭</el-button> </div> </template> </el-dialog> <el-dialog :title="editDalgotitle" v-model="editDalgo" width="800px"> <el-form label-width="auto" ref="ruleFormAdd1" :model="FormList" v-if="editDalgo"> <el-form-item label="一级节点:" prop="nodeName" v-if="!appryList.tier" :rules="[{ required: true, message: '节点不能为空', trigger: 'blur' }]" > <el-input v-model="FormList.nodeName" placeholder="请输入一级节点" /> </el-form-item> <el-form-item label="二级节点:" prop="nodeName2" v-if="appryList.tier == 1" :rules="[{ required: true, message: '节点不能为空', trigger: 'blur' }]" > <el-input v-model="FormList.nodeName2" placeholder="请输入二级节点" /> </el-form-item> <el-form-item label="三级节点:" prop="nodeName3" v-if="appryList.tier == 2" :rules="[{ required: true, message: '节点不能为空', trigger: 'blur' }]" > <el-input v-model="FormList.nodeName3" placeholder="请输入三级节点" /> </el-form-item> <el-form-item label="关键里程碑:" prop="keyMilestone" :rules="[ { required: true, message: '关键里程碑不能为空', trigger: 'change', }, ]" > <el-radio-group v-model="FormList.keyMilestone" class="ml-4" :disabled="appryList.tier"> <el-radio :label="1" size="large">是</el-radio> <el-radio :label="0" size="large">否</el-radio> </el-radio-group> </el-form-item> <el-form-item label="计划开始日期:" prop="planStartTime" :rules="[ { required: true, message: '计划开始日期不能为空', trigger: 'change', }, ]" > <el-date-picker style="width: 100%" clearable format="YYYY-MM-DD" value-format="YYYY-MM-DD" v-model="FormList.planStartTime" type="date" range-separator="到" placeholder="请选择计划开始日期" :disabled-date="disabledDate" /> </el-form-item> <el-form-item label="计划结束日期:" prop="planEndTime" :rules="[ { required: true, message: '计划结束日期不能为空', trigger: 'change', }, ]" > <el-date-picker clearable style="width: 100%" format="YYYY-MM-DD" value-format="YYYY-MM-DD" v-model="FormList.planEndTime" type="date" range-separator="到" placeholder="请选择计划结束日期" :disabled-date="disabledDate" /> </el-form-item> <el-form-item label="负责人:" prop="dutyUserId" :rules="[{ required: true, message: '负责人不能为空', trigger: 'change' }]"> <el-select clearable v-model="FormList.dutyUserId" class="m-2" placeholder="请选择负责人" size="mini" style="width: 100%"> <el-option v-for="item in personList" :key="item.userId" :label="item.nickName" :value="item.userId + ''" /> </el-select> </el-form-item> <el-form-item label="输出资料:" prop="outputData"> <el-input v-model="FormList.outputData" placeholder="请输入输出资料" /> </el-form-item> <el-form-item label="预算工时:" prop="estimatedWorkHours"> <el-input style="width: 100%" v-model="FormList.estimatedWorkHours" type="number" placeholder="请输入预算工时" /> </el-form-item> <el-form-item label="备注:" prop="remark"> <el-input style="width: 100%" v-model="FormList.remark" type="textarea" placeholder="请输入备注" /> </el-form-item> <el-form-item label="排序号:" prop="sort"> <el-input style="width: 100%" v-model="FormList.sort" type="number" placeholder="请输入排序号" /> </el-form-item> </el-form> <div style="text-align: right; margin-right: 20px"> <el-button type="primary" @click="editClick('ruleFormAdd1')">确定</el-button> <el-button @click="editDalgoClosed">关闭</el-button> </div> </el-dialog> <!-- 编辑 --> <el-dialog :title="editDalgotitle" v-model="editDalgo2" width="800px"> <el-form label-width="auto" ref="ruleFormAdd2" :model="FormList" v-if="editDalgo2"> <el-form-item label="一级节点:" prop="nodeName" v-if="appryList.tier == 1" :rules="[{ required: true, message: '节点不能为空', trigger: 'change' }]" > <el-input v-model="FormList.nodeName" placeholder="请输入一级节点" /> </el-form-item> <el-form-item label="二级节点:" prop="nodeName" v-if="appryList.tier == 2" :rules="[{ required: true, message: '节点不能为空', trigger: 'change' }]" > <el-input v-model="FormList.nodeName" placeholder="请输入二级节点" /> </el-form-item> <el-form-item label="三级节点:" prop="nodeName" v-if="appryList.tier == 3" :rules="[{ required: true, message: '节点不能为空', trigger: 'change' }]" > <el-input v-model="FormList.nodeName" placeholder="请输入三级节点" /> </el-form-item> <el-form-item label="关键里程碑:" prop="keyMilestone" :rules="[ { required: true, message: '关键里程碑不能为空', trigger: 'change', }, ]" > <el-radio-group v-model="FormList.keyMilestone" class="ml-4" :disabled="[2, 3].includes(appryList.tier)"> <el-radio :label="1" size="large">是</el-radio> <el-radio :label="0" size="large">否</el-radio> </el-radio-group> </el-form-item> <el-form-item label="计划开始日期:" prop="planStartTime" :rules="[ { required: true, message: '计划开始日期不能为空', trigger: 'change', }, ]" > <el-date-picker clearable format="YYYY-MM-DD" value-format="YYYY-MM-DD" v-model="FormList.planStartTime" type="date" range-separator="到" placeholder="请选择计划开始日期" :disabled-date="disabledDate" /> </el-form-item> <el-form-item label="计划结束日期:" prop="planEndTime" :rules="[ { required: true, message: '计划结束日期能为空', trigger: 'change', }, ]" > <el-date-picker clearable format="YYYY-MM-DD" value-format="YYYY-MM-DD" v-model="FormList.planEndTime" type="date" range-separator="到" placeholder="请选择计划结束日期" :disabled-date="disabledDate" /> </el-form-item> <el-form-item label="负责人:" prop="dutyUserId" :rules="[{ required: true, message: '负责人不能为空', trigger: 'change' }]"> <el-select clearable v-model="FormList.dutyUserId" class="m-2" placeholder="请选择负责人" size="mini" style="width: 100%"> <el-option v-for="item in personList" :key="item.userId" :label="item.nickName" :value="item.userId + ''" /> </el-select> </el-form-item> <el-form-item label="输出资料:" prop="outputData"> <el-input v-model="FormList.outputData" placeholder="请输入输出资料" /> </el-form-item> <el-form-item label="预算工时:" prop="estimatedWorkHours"> <el-input style="width: 100%" v-model="FormList.estimatedWorkHours" type="number" placeholder="请输入预算工时" /> </el-form-item> <el-form-item label="备注:" prop="remark"> <el-input style="width: 100%" v-model="FormList.remark" type="textarea" placeholder="请输入备注" /> </el-form-item> <el-form-item label="排序号:" prop="sort"> <el-input style="width: 100%" v-model="FormList.sort" type="number" placeholder="请输入排序号" /> </el-form-item> </el-form> <div style="text-align: right"> <el-button type="primary" @click="editClick('ruleFormAdd2')">确定</el-button> <el-button @click="editDalgoClosed">关闭</el-button> </div> </el-dialog> </div> </template> <script setup name="Post"> import { projectPlanInfoPage, projectPlanInfoAdd, projectPlanInfoIDS, projectPlanInfoID, projectPlanInfoEdit, projectInfoList, FileSystemList, projectInfoSelectByProjectNo, projectPlanTemplateList, getNodeCodeToUuid, } from '@/api/project/tenderReview'; import { userList } from '@/api/project/noticeReward'; import { getToken } from '@/utils/auth'; import { ElMessage, ElMessageBox } from 'element-plus'; import emgBox from '@/utils/ElMessageBox'; import { projectPlanRules } from '@/utils/rules'; import { projectPlanCloum } from '@/utils/cloums'; import ImageFileUpload from '@/components/ImageFileUpload/index.vue'; //图片文件上传 const { proxy } = getCurrentInstance(); const postList = ref([]); const open = ref(false); const loading = ref(true); const showSearch = ref(true); const ids = ref([]); const single = ref(true); const multiple = ref(true); const total = ref(0); const title = ref(''); const editDalgotitle = ref(''); const editDalgo = ref(false); const isAddProjetc = ref(false); const FormList = ref({ keyMilestone: 0 }); const personList = ref([]); const ProjectListData = ref([]); const uploadHeader = ref({ Authorization: 'Bearer ' + getToken(), }); const isShow = ref(); const data = reactive({ form: {}, queryParams: { pageNum: 1, pageSize: 10, projectName: undefined, timer: '', startTime: '', endTime: '', }, rules: { projectName: [{ required: true, message: '项目计划信息编码不能为空', trigger: 'blur' }], }, }); const tableData = ref([]); const disabledDate = time => { let curInfo = null; if (editDalgo.value) { curInfo = appryList.value; } else if (editDalgo2.value) { const nodeCode = appryList.value.nodeCode; curInfo = getParentNode(tableData.value, nodeCode) || null; } if (!curInfo?.planStartTime || !curInfo?.planEndTime) return false; let disabled = false; if (time.getTime() < Date.parse(curInfo.planStartTime + ' 00:00:00') || time.getTime() > Date.parse(curInfo.planEndTime + ' 23:59:59')) { disabled = true; } return disabled; }; const getParentNode = (list, nodeCode) => { // 遍历树节点 for (let node of list) { // 如果当前节点就是目标节点的父节点,直接返回当前节点id if (node.children && node.children.some(child => child.nodeCode === nodeCode)) { return node; } // 否则继续遍历当前节点的子节点 if (node.children) { const parentNode = getParentNode(node.children, nodeCode); if (parentNode !== null) { return parentNode; } } } // 如果没有找到父节点,则返回null return null; }; const getStateName = r => { let a = ''; personList.value.map(i => { if (i.userId == r) { a = i; } }); return a.nickName; }; const { queryParams, form, rules } = toRefs(data); /** 文件上传 */ const fileList1 = ref([]); function handlePreview(file) { console.log(file); return ElMessageBox.confirm(`下载此文件: ${file.name}?`).then( () => window.open(file.url), () => false ); } function beforeRemove(file) { return true; } /** 搜索项目计划信息列表 */ function getList() { loading.value = true; if (queryParams.value.timer) { queryParams.value.planStartTime = queryParams.value.timer[0]; queryParams.value.planEndTime = queryParams.value.timer[1]; } else { queryParams.value.planStartTime = ''; queryParams.value.planEndTime = ''; } if (queryParams.value.timer2) { queryParams.value.actualFinishStartTime = queryParams.value.timer2[0]; queryParams.value.actualFinishEndTime = queryParams.value.timer2[1]; } else { queryParams.value.actualFinishStartTime = ''; queryParams.value.actualFinishEndTime = ''; } projectPlanInfoPage(queryParams.value).then(response => { postList.value = response.data; total.value = response.total; loading.value = false; }); } /** 取消按钮 */ function cancel() { open.value = false; reset(); } /** 表单重置 */ function reset() { form.value = { id: undefined, projectNo: undefined, startTime: undefined, endTime: undefined, projectFillTime: undefined, chargeUser: undefined, remark: undefined, }; proxy.resetForm('postRef'); } /** 搜索按钮操作 */ function handleQuery() { if (queryParams.value.timer) { queryParams.value.startTime = queryParams.value.timer[0]; queryParams.value.endTime = queryParams.value.timer[1]; } else { queryParams.value.startTime = ''; queryParams.value.endTime = ''; } queryParams.value.pageNum = 1; getList(); } /** 重置按钮操作 */ function resetQuery() { proxy.resetForm('queryRef'); queryParams.value.timer = []; queryParams.value.timer2 = []; handleQuery(); } /** 多选框选中数据 */ function handleSelectionChange(selection) { ids.value = selection.map(item => item.id); single.value = selection.length != 1; multiple.value = !selection.length; } /** 新增按钮操作 */ function handleAdd(t) { isShow.value = t; reset(); open.value = true; title.value = '项目计划信息新增'; tableData.value = []; fileList1.value = []; nextTick(() => { proxy.$refs['postRef'].resetFields(); }); } /** 修改按钮操作 */ function handleUpdate(row, t) { isShow.value = t; reset(); const id = row.id || ids.value; projectPlanInfoID(id).then(response => { let d1 = response.data; open.value = true; title.value = '项目计划信息修改'; let time = response.data.projectFillTime; tableData.value = response.data.projectPlanInventoryList; projectInfoSelectByProjectNo(row.projectNo).then(response => { form.value = { ...response.data, ...d1 }; form.value.id = id; form.value.projectFillTime = time; console.log('response.data ', response.data); }); }); // 获取文件列表 FileSystemList({ refId: id, refType: 'proProjectPlanInfo', }).then(({ data }) => { fileList1.value = data; }); } /** 提交按钮 */ function submitForm() { console.log(); proxy.$refs['postRef'].validate(valid => { if (valid) { form.value.projectPlanInventorySaveRequestList = tableData.value; form.value.fileSaveRequestList = []; fileList1.value.forEach(element => { // 基本信息 if (element.hasOwnProperty('response')) { element.response.data.refType = 'proProjectPlanInfo'; form.value.fileSaveRequestList.push(element.response.data); } else { form.value.fileSaveRequestList.push(element); } }); if (form.value.id) { projectPlanInfoEdit(form.value).then(({ code }) => { if (code == 200) { proxy.$modal.msgSuccess('修改成功'); open.value = false; getList(); } }); } else { projectPlanInfoAdd(form.value).then(({ code }) => { if (code == 200) { proxy.$modal.msgSuccess('新增成功'); open.value = false; getList(); } }); } } }); } /** 删除按钮操作 */ function handleDelete(row) { const ids = row.id || ids.value; proxy.$modal .confirm('是否确认删除该数据项?') .then(function () { return projectPlanInfoIDS(ids); }) .then(() => { getList(); proxy.$modal.msgSuccess('删除成功'); }) .catch(() => {}); } /** 导出按钮操作 */ function handleExport() { proxy.download( 'system/post/export', { ...queryParams.value, }, `post_${new Date().getTime()}.xlsx` ); } /**获取所有的项目数据 */ function loadProjerctListData() { projectInfoList().then(response => { ProjectListData.value = response.data; }); } /**项目下拉框选择 */ let al = ref(); function TouBiaoInfo(val, type) { al.value = val; projectInfoSelectByProjectNoM(val, type); } function projectInfoSelectByProjectNoM(val, type) { let arra = val.filter(k => { return k.projectNo == form.value.projectNo; }); let pid = arra[0].projectTypeId; FormList.value.projectTypeId = pid; projectInfoSelectByProjectNo(arra[0].projectNo).then(response => { form.value.startTime = response.data.startTime; form.value.endTime = response.data.endTime; form.value.chargeUser = response.data.chargeUser; // let params = { projectTypeId: pid }; projectPlanTemplateList(pid).then(({ data }) => { tableData.value = data; isAddProjetc.value = true; }); }); } //删除 编辑 新增 let isAdit = ref(); // let let appryList = ref({}); const editDalgo2 = ref(false); function onCheck(t, y, tittle) { console.log(t, 'rowrow'); editDalgotitle.value = tittle; appryList.value = t; isAdit.value = y; if (y == 3) { if (t?.children?.length > 0) { emgBox(t, projectPlanDeleteM, '该节点下有子节点您确定删除吗?'); } else { projectPlanDeleteM(t); } } else if (y == 2) { editDalgo2.value = true; FormList.value = t; } else { editDalgo.value = true; FormList.value = { keyMilestone: 0 }; nextTick(() => { proxy.$refs.ruleFormAdd1.resetFields(); }); } } function deleteData(data, nodeCode) { let newData = data.filter(x => x.nodeCode !== nodeCode); newData.forEach(x => x.children && (x.children = deleteData(x.children, nodeCode))); return newData; } const projectPlanDeleteM = ({ nodeCode }) => { tableData.value = deleteData(tableData.value, nodeCode); }; function editDalgoClosed() { editDalgo.value = false; editDalgo2.value = false; } //新增确定 编辑确定 function editClick(t) { proxy.$refs[t].validate(valid => { if (valid) { if (isAdit.value == 2) { if (!appryList.value.children) { appryList.value.children = []; } else { let arrar = appryList.value.children; } appryList.value = FormList.value; } else { getNodeCodeToUuid().then(({ data }) => { FormList.value.nodeCode = data; if (!appryList.value.children) { appryList.value.children = []; } if (appryList.value.tier == 1) { FormList.value.nodeName = FormList.value.nodeName2; FormList.value.tier = 2; FormList.value.parentNodeCode = appryList.value.nodeCode; appryList.value.children.push(FormList.value); FormList.value = { keyMilestone: 0 }; } if (appryList.value.tier == 2) { FormList.value.nodeName = FormList.value.nodeName3; FormList.value.projectTypeId = appryList.value.projectTypeId; FormList.value.parentNodeCode = appryList.value.nodeCode; FormList.value.tier = 3; appryList.value.children.push(FormList.value); FormList.value = { keyMilestone: 0 }; } if (!appryList.value.tier) { appryList.value.nodeCode = data; appryList.value.parentNodeCode = 0; FormList.value.tier = 1; console.log(FormList.value, 999); tableData.value.push(FormList.value); FormList.value = { keyMilestone: 0 }; } }); } editDalgo.value = false; editDalgo2.value = false; } }); } const userListM = async () => { let { data } = await userList(); personList.value = data; }; getList(); loadProjerctListData(); userListM(); </script> <style scoped lang="scss"> .biaoti { font-weight: 900; font-size: 18px; margin: 20px 0; } td.twoChildren_td, td.twoChildren_td1 { text-align: center; min-width: 130px; } td.twoChildren_td1 { min-width: 170px; text-align: left; } td.border_td { border-bottom: 1.5px solid #ddd; } .flex { display: flex; justify-content: center; align-items: center; flex-direction: column; } :deep(.nodename.el-table__cell > .cell) { padding: 0; width: 100%; text-align: center; } </style>