You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
668 lines
21 KiB
668 lines
21 KiB
<template> |
|
<el-dialog |
|
append-to-body="false" |
|
:title="title" |
|
:model-value="openShow" |
|
width="80%" |
|
@close="handleClose" |
|
fullscreen |
|
> |
|
<!-- 单个 Form 包裹所有内容(基础信息 + 表格) --> |
|
<el-form ref="addForm" :model="addForm" :rules="addRules" label-width="140px"> |
|
<!-- 项目基础信息表单 --> |
|
<el-row> |
|
<el-col :span="8"> |
|
<el-form-item label="项目名称" prop="projectName"> |
|
<el-input :disabled="isDetail" v-model="addForm.projectName"></el-input> |
|
</el-form-item> |
|
</el-col> |
|
<el-col :span="8"> |
|
<el-form-item label="项目类型" prop="bcId"> |
|
<el-select :disabled="isDetail" v-model="addForm.bcId" clearable filterable> |
|
<el-option |
|
v-for="(item, index) in projectType" |
|
:label="item.dictValue" |
|
:value="item.dictKey" |
|
></el-option> |
|
</el-select> |
|
</el-form-item> |
|
</el-col> |
|
<el-col :span="8"> |
|
<el-form-item label="制单部门" prop="touchingDeptId"> |
|
<el-select |
|
:disabled="isDetail" |
|
v-model="addForm.touchingDeptId" |
|
clearable |
|
filterable |
|
@change="handleChange('touchingDeptId')" |
|
> |
|
<el-option |
|
v-for="(item, index) in deplList" |
|
:label="item.deptName" |
|
:value="item.id" |
|
></el-option> |
|
</el-select> |
|
</el-form-item> |
|
</el-col> |
|
</el-row> |
|
<el-row> |
|
<el-col :span="24"> |
|
<el-form-item label="项目背景" prop="projectBackcloth"> |
|
<el-input |
|
:disabled="isDetail" |
|
type="textarea" |
|
v-model="addForm.projectBackcloth" |
|
></el-input> |
|
</el-form-item> |
|
</el-col> |
|
</el-row> |
|
<el-row> |
|
<el-col :span="24"> |
|
<el-form-item label="项目目标" prop="projectTarget"> |
|
<el-input |
|
:disabled="isDetail" |
|
type="textarea" |
|
v-model="addForm.projectTarget" |
|
></el-input> |
|
</el-form-item> |
|
</el-col> |
|
</el-row> |
|
<el-row> |
|
<el-col :span="24"> |
|
<el-form-item label="预期效果" prop="desiredResult"> |
|
<el-input |
|
:disabled="isDetail" |
|
type="textarea" |
|
v-model="addForm.desiredResult" |
|
></el-input> |
|
</el-form-item> |
|
</el-col> |
|
</el-row> |
|
<el-row> |
|
<el-col :span="8"> |
|
<el-form-item label="项目负责人" prop="projectHeadId"> |
|
<el-select |
|
:disabled="isDetail" |
|
v-model="addForm.projectHeadId" |
|
clearable |
|
filterable |
|
@change="handleChange('projectHeadId')" |
|
> |
|
<el-option |
|
v-for="item in memberList" |
|
:label="item.realName" |
|
:value="item.id" |
|
></el-option> |
|
</el-select> |
|
</el-form-item> |
|
</el-col> |
|
<el-col :span="8"> |
|
<el-form-item label="成员名称" prop="memberName"> |
|
<el-select |
|
:disabled="isDetail" |
|
v-model="addForm.memberName" |
|
multiple |
|
placeholder="请选择成员名称" |
|
clearable |
|
filterable |
|
> |
|
<el-option |
|
v-for="item in memberList" |
|
:label="item.realName" |
|
:value="item.id" |
|
></el-option> |
|
</el-select> |
|
</el-form-item> |
|
</el-col> |
|
</el-row> |
|
<el-row> |
|
<el-col :span="8"> |
|
<el-form-item label="项目支持人" prop="projectSupportMan"> |
|
<el-select |
|
:disabled="isDetail" |
|
v-model="addForm.projectSupportMan" |
|
clearable |
|
filterable |
|
> |
|
<el-option |
|
v-for="item in memberList" |
|
:label="item.realName" |
|
:value="item.id" |
|
></el-option> |
|
</el-select> |
|
</el-form-item> |
|
</el-col> |
|
<el-col :span="8"> |
|
<el-form-item label="项目开始时间" prop="projectStartTime"> |
|
<el-date-picker |
|
:disabled="isDetail" |
|
style="width: 100%" |
|
v-model="addForm.projectStartTime" |
|
type="date" |
|
placeholder="选择日期" |
|
format="YYYY-MM-DD" |
|
value-format="YYYY-MM-DD" |
|
> |
|
</el-date-picker> |
|
</el-form-item> |
|
</el-col> |
|
<el-col :span="8"> |
|
<el-form-item label="项目结束预期时间" prop="projectDesiredEnd"> |
|
<el-date-picker |
|
:disabled="isDetail" |
|
style="width: 100%" |
|
v-model="addForm.projectDesiredEnd" |
|
type="date" |
|
placeholder="选择日期" |
|
format="YYYY-MM-DD" |
|
value-format="YYYY-MM-DD" |
|
></el-date-picker> |
|
</el-form-item> |
|
</el-col> |
|
</el-row> |
|
|
|
<!-- 里程碑表格操作 --> |
|
<div style="margin: 10px 0" v-if="!isDetail"> |
|
<el-button type="primary" @click="handleOpenDialog">插入一行</el-button> |
|
<el-button type="danger" @click="delTable">删除选中行</el-button> |
|
</div> |
|
<!-- 全局错误提示 --> |
|
<div v-if="formError" class="error-message" style="color: #f56c6c; margin-bottom: 10px"> |
|
{{ formError }} |
|
</div> |
|
<!-- 里程碑表格 --> |
|
<el-table |
|
:data="addForm.stoneList" |
|
ref="detailTable" |
|
border |
|
@select="selectChange" |
|
class="table_project" |
|
> |
|
<el-table-column type="selection"></el-table-column> |
|
<el-table-column type="index" width="80" label="序号"></el-table-column> |
|
<el-table-column align="center" :width="isDetail ? '120' : ''" label="里程碑计划"> |
|
<template #header> |
|
<span><i style="color: red">*</i>里程碑计划</span> |
|
</template> |
|
<template #default="scope"> |
|
<template v-if="!isDetail"> |
|
<el-form-item |
|
label-width="0" |
|
:prop="`stoneList[${scope.$index}].milestonePlan`" |
|
:rules="addRules.milestonePlan" |
|
> |
|
<el-input |
|
v-model="scope.row.milestonePlan" |
|
placeholder="请输入里程碑计划" |
|
></el-input> |
|
</el-form-item> |
|
</template> |
|
<template v-else> |
|
<span>{{ scope.row.milestonePlan }}</span> |
|
</template> |
|
</template> |
|
</el-table-column> |
|
<el-table-column |
|
align="center" |
|
:width="isDetail ? '120' : ''" |
|
label="里程碑负责人" |
|
prop="milestoneMan" |
|
> |
|
<template #header> |
|
<span><i style="color: red">*</i>里程碑负责人</span> |
|
</template> |
|
<template #default="scope"> |
|
<template v-if="!isDetail"> |
|
<el-form-item |
|
label-width="0" |
|
:prop="`stoneList[${scope.$index}].milestoneMan`" |
|
:rules="addRules.milestoneMan" |
|
> |
|
<el-select |
|
v-model="scope.row.milestoneMan" |
|
placeholder="请选择里程碑负责人" |
|
clearable |
|
filterable |
|
> |
|
<el-option |
|
v-for="item in memberList" |
|
:label="item.realName" |
|
:value="item.id" |
|
></el-option> |
|
</el-select> |
|
</el-form-item> |
|
</template> |
|
<template v-else> |
|
<span>{{ scope.row.milestoneMan }}</span> |
|
</template> |
|
</template> |
|
</el-table-column> |
|
<el-table-column |
|
align="center" |
|
:width="isDetail ? '120' : ''" |
|
label="里程碑输出物" |
|
prop="outputMaterial" |
|
> |
|
<template #header> |
|
<span><i style="color: red">*</i>里程碑输出物</span> |
|
</template> |
|
<template #default="scope"> |
|
<template v-if="!isDetail"> |
|
<el-form-item |
|
label-width="0" |
|
:prop="`stoneList[${scope.$index}].outputMaterial`" |
|
:rules="addRules.outputMaterial" |
|
> |
|
<el-input |
|
v-model="scope.row.outputMaterial" |
|
placeholder="请输入里程碑输出物" |
|
></el-input> |
|
</el-form-item> |
|
</template> |
|
<template v-else> |
|
<span>{{ scope.row.outputMaterial }}</span> |
|
</template> |
|
</template> |
|
</el-table-column> |
|
<el-table-column |
|
align="center" |
|
:width="isDetail ? '180' : ''" |
|
label="里程碑节点" |
|
prop="milestoneNode" |
|
> |
|
<template #header> |
|
<span><i style="color: red">*</i>里程碑节点</span> |
|
</template> |
|
<template #default="scope"> |
|
<template v-if="!isDetail"> |
|
<el-form-item |
|
label-width="0" |
|
:prop="`stoneList[${scope.$index}].milestoneNode`" |
|
:rules="addRules.milestoneNode" |
|
> |
|
<el-date-picker |
|
v-model="scope.row.milestoneNode" |
|
type="date" |
|
placeholder="选择日期时间" |
|
style="width: 100%" |
|
format="YYYY-MM-DD HH:mm:ss" |
|
value-format="YYYY-MM-DD HH:mm:ss" |
|
/> |
|
</el-form-item> |
|
</template> |
|
<template v-else> |
|
<span>{{ scope.row.milestoneNode }}</span> |
|
</template> |
|
</template> |
|
</el-table-column> |
|
<!-- 详情页专属列 --> |
|
<el-table-column |
|
v-if="isDetail" |
|
align="center" |
|
label="执行类型" |
|
prop="executeType" |
|
:width="isDetail ? '120' : ''" |
|
></el-table-column> |
|
<el-table-column |
|
v-if="isDetail" |
|
align="center" |
|
label="延期时间" |
|
prop="delayTime" |
|
:width="isDetail ? '120' : ''" |
|
></el-table-column> |
|
<el-table-column |
|
v-if="isDetail" |
|
align="center" |
|
label="核查结果" |
|
prop="checkResult" |
|
:width="isDetail ? '120' : ''" |
|
></el-table-column> |
|
<el-table-column |
|
v-if="isDetail" |
|
align="center" |
|
label="核查人" |
|
prop="checkMan" |
|
:width="isDetail ? '120' : ''" |
|
></el-table-column> |
|
<el-table-column |
|
v-if="isDetail" |
|
align="center" |
|
label="评价等级" |
|
prop="grade" |
|
:width="isDetail ? '120' : ''" |
|
></el-table-column> |
|
<el-table-column |
|
v-if="isDetail" |
|
align="center" |
|
label="评价人" |
|
prop="gradeMan" |
|
:width="isDetail ? '120' : ''" |
|
></el-table-column> |
|
<el-table-column |
|
v-if="isDetail" |
|
width="200" |
|
align="center" |
|
label="业务领导评价" |
|
prop="evaluate" |
|
:width="isDetail ? '120' : ''" |
|
></el-table-column> |
|
<el-table-column v-if="isDetail" align="center" label="附件" :width="isDetail ? '120' : ''"> |
|
<el-button type="text">附件</el-button> |
|
</el-table-column> |
|
<!-- 通用操作列 --> |
|
<!-- <el-table-column label="操作"> |
|
<template #default="scope"> |
|
<el-button plain type="danger" @click="handleDelTable(scope.$index)">删除</el-button> |
|
</template> |
|
</el-table-column> --> |
|
</el-table> |
|
</el-form> |
|
<!-- 弹窗底部按钮 --> |
|
<template #footer> |
|
<span class="dialog-footer"> |
|
<el-button @click="handleClose">取 消</el-button> |
|
<el-button type="primary" @click="handleSubmitForm">确 定</el-button> |
|
</span> |
|
</template> |
|
</el-dialog> |
|
</template> |
|
|
|
<script> |
|
import { addProcess, getProcessDetail, getDeplList } from '@/api/flowManagement/index'; |
|
import { getRoleUserList } from '@/api/processManagement/taskDispatch'; |
|
import { getDictionary } from '@/api/system/dict'; |
|
|
|
export default { |
|
name: 'AddDialog', |
|
props: { |
|
title: { |
|
type: String, |
|
required: true, |
|
}, |
|
visible: { |
|
type: Boolean, |
|
required: true, |
|
default: false, |
|
}, |
|
rowItem: { |
|
type: Object, |
|
required: true, |
|
default: () => ({}), |
|
}, |
|
}, |
|
data() { |
|
return { |
|
formError: '', |
|
addRules: { |
|
projectName: [{ required: true, message: '请填写项目名称', trigger: ['blur', 'submit'] }], |
|
bcId: [{ required: true, message: '请选择项目类型', trigger: ['change', 'submit'] }], |
|
touchingDept: [ |
|
{ required: true, message: '请选择制单部门', trigger: ['change', 'submit'] }, |
|
], |
|
projectBackcloth: [ |
|
{ required: true, message: '请填写项目背景', trigger: ['blur', 'submit'] }, |
|
], |
|
projectTarget: [{ required: true, message: '请填写项目目标', trigger: ['blur', 'submit'] }], |
|
desiredResult: [{ required: true, message: '请填写预期效果', trigger: ['blur', 'submit'] }], |
|
projectHeadId: [ |
|
{ required: true, message: '请选择项目负责人', trigger: ['change', 'submit'] }, |
|
], |
|
memberName: [{ required: true, message: '请选择成员名称', trigger: ['change', 'submit'] }], |
|
projectSupportMan: [ |
|
{ required: true, message: '请选择项目支持人', trigger: ['change', 'submit'] }, |
|
], |
|
projectStartTime: [ |
|
{ required: true, message: '请选择项目开始时间', trigger: ['change', 'submit'] }, |
|
], |
|
projectDesiredEnd: [ |
|
{ required: true, message: '请选择项目结束预期时间', trigger: ['change', 'submit'] }, |
|
], |
|
stoneList: [ |
|
{ |
|
required: true, |
|
message: '请至少添加一行里程碑数据', |
|
trigger: 'submit', |
|
type: 'array', |
|
}, |
|
{ |
|
validator: (rule, value, callback) => { |
|
if (value.length === 0) { |
|
callback(new Error('请至少添加一行里程碑数据')); |
|
} else { |
|
callback(); |
|
} |
|
}, |
|
trigger: 'submit', |
|
}, |
|
], |
|
|
|
// 里程碑数组项字段校验 |
|
milestonePlan: [ |
|
{ required: true, message: '请填写里程碑计划', trigger: ['blur', 'submit'] }, |
|
], |
|
milestoneMan: [ |
|
{ required: true, message: '请选择里程碑负责人', trigger: ['change', 'submit'] }, |
|
], |
|
outputMaterial: [ |
|
{ required: true, message: '请输入里程碑输出物', trigger: ['blur', 'submit'] }, |
|
], |
|
milestoneNode: [ |
|
{ required: true, message: '请选择里程碑节点', trigger: ['change', 'submit'] }, |
|
], |
|
}, |
|
memberList: [], //人员列表 |
|
projectType: [], //项目类型 |
|
deplList: [], //部门列表 |
|
openShow: false, |
|
addForm: { |
|
stoneList: [], |
|
}, |
|
}; |
|
}, |
|
computed: { |
|
// 判断是否为详情页 |
|
isDetail() { |
|
return this.title === '详情'; |
|
}, |
|
}, |
|
mounted() { |
|
this.openShow = this.visible; |
|
this.getRoleUserList(); |
|
this.getDictionary(); |
|
this.getDeplList(); |
|
if (this.title === '详情' || this.title === '修改') { |
|
this.getDetails(); |
|
} |
|
}, |
|
methods: { |
|
handleChange(type) { |
|
// 制单部门 |
|
if (type == 'touchingDeptId') { |
|
let sel = this.deplList.filter(item => item.id == this.addForm.touchingDeptId)[0]; |
|
this.addForm.touchingDept = sel.deptName; |
|
} |
|
// 项目负责人 |
|
if (type == 'projectHeadId') { |
|
let sel = this.memberList.filter(item => item.id == this.addForm.projectHeadId)[0]; |
|
this.addForm.projectHead = sel.realName; |
|
} |
|
}, |
|
// 获取部门列表 |
|
getDeplList() { |
|
getDeplList().then(res => { |
|
// console.log(res.data.data, 'res'); |
|
this.deplList = res.data.data; |
|
}); |
|
}, |
|
// 获取人员 |
|
getRoleUserList() { |
|
getRoleUserList({ size: 999999, current: 1 }).then(res => { |
|
this.memberList = res.data.data.records; |
|
}); |
|
}, |
|
// 获取项目类型 getDictionary |
|
getDictionary() { |
|
getDictionary({ code: 'flow_project_type' }).then(res => { |
|
this.projectType = res.data.data; |
|
}); |
|
}, |
|
// 获取详情数据 |
|
getDetails() { |
|
getProcessDetail(this.rowItem.id).then(res => { |
|
console.log(res.data.data, 'res'); |
|
this.addForm = res.data.data; |
|
// 安全地处理 memberName 回显 |
|
if (res.data.data.memberName) { |
|
this.addForm.memberName = String(res.data.data.memberName) |
|
.split(',') |
|
.map(id => id.trim()) |
|
.filter(Boolean); |
|
} else { |
|
this.addForm.memberName = []; |
|
} |
|
}); |
|
}, |
|
handleClose(type) { |
|
this.formError = ''; |
|
this.openShow = false; |
|
this.$emit('close ', type); |
|
}, |
|
selectChange(list, row) { |
|
row._select = !row._select; |
|
}, |
|
// 删除选中行 |
|
delTable() { |
|
this.addForm.stoneList = this.addForm.stoneList.filter(row => !row._select); |
|
}, |
|
// 插入里程碑行 |
|
handleOpenDialog() { |
|
const newRow = { |
|
id: 0, |
|
fmProjectApplication: {}, |
|
attachList: [], // 附件列表默认空数组 |
|
paId: 0, |
|
paIndex: `${(this.addForm.stoneList?.length || 0) + 1}`, |
|
milestonePlan: '', |
|
milestoneMan: '', |
|
outputMaterial: '', |
|
milestoneNode: '', |
|
milestoneMemo: '', |
|
evolve: '', |
|
lastPlan: '', |
|
grade: -32768, |
|
score: 0, |
|
executeResult: 0, |
|
executeType: '', |
|
delayTime: '', |
|
checkResult: 0, |
|
checkMan: '', |
|
checkTime: '', |
|
gradeMan: '', |
|
evaluate: '', |
|
okTime: '', |
|
delayDate: false, |
|
fileId: '', |
|
}; |
|
if (!this.addForm.stoneList) this.addForm.stoneList = []; |
|
this.addForm.stoneList.push(newRow); |
|
|
|
// this.$emit('open-dialog', newRow); // 通知父组件 |
|
}, |
|
// 删除里程碑行 |
|
handleDelTable(index) { |
|
this.$confirm('确定删除该条数据么?', '提示', { |
|
confirmButtonText: '确定', |
|
cancelButtonText: '取消', |
|
type: 'warning', |
|
}) |
|
.then(() => { |
|
this.addForm.stoneList.splice(index, 1); |
|
this.$message.success('删除成功'); |
|
this.$emit('del-table', index); // 通知父组件 |
|
}) |
|
.catch(() => {}); |
|
}, |
|
formatSubmitData(form) { |
|
const submitData = JSON.parse(JSON.stringify(form)); |
|
if (Array.isArray(submitData.memberName)) { |
|
submitData.memberName = submitData.memberName.map(item => String(item)).join(','); |
|
} |
|
submitData.stoneList = submitData.stoneList.map(row => { |
|
const { fmProjectApplication, attachList, paIndex, ...validData } = row; |
|
return validData; |
|
}); |
|
return submitData; |
|
}, |
|
// 提交 |
|
async handleSubmitForm() { |
|
this.formError = ''; |
|
if (this.addForm.stoneList.length === 0) { |
|
return this.$message.error('立项申请数据不能为空!'); |
|
} |
|
this.$refs.addForm.validate((isValid, invalidFields) => { |
|
if (!isValid) { |
|
this.formError = '存在未完善的字段,请检查红色提示'; |
|
this.$nextTick(() => { |
|
const firstError = document.querySelector('.el-form-item.is-error'); |
|
if (firstError) { |
|
firstError.scrollIntoView({ behavior: 'smooth', block: 'center' }); |
|
} |
|
}); |
|
return; |
|
} |
|
const submitData = this.formatSubmitData(this.addForm); |
|
submitData.projectStartTime = submitData.projectStartTime + ' 00:00:00'; |
|
submitData.projectDesiredEnd = submitData.projectDesiredEnd + ' 00:00:00'; |
|
if (this.title === '详情') { |
|
updateProcess({ ...submitDat, approvalStatus: 1 }).then(res => { |
|
this.$message.success('修改成功'); |
|
this.handleClose(true); |
|
}); |
|
return; |
|
} else { |
|
addProcess({ ...submitData, approvalStatus: 1 }).then(res => { |
|
this.$message.success('提交成功'); |
|
this.handleClose(true); |
|
}); |
|
} |
|
}); |
|
}, |
|
}, |
|
}; |
|
</script> |
|
|
|
<style lang="scss" scoped> |
|
// 优化表单字段样式 |
|
:deep(.el-table .el-form-item) { |
|
margin-bottom: 0; // 去掉默认边距 |
|
} |
|
|
|
// 错误提示样式优化 |
|
:deep(.table_project .el-form-item__error) { |
|
font-size: 12px; |
|
white-space: nowrap; |
|
z-index: 10; |
|
background: #fff; |
|
padding: 2px 4px; |
|
border: 1px solid #f56c6c; |
|
border-radius: 4px; |
|
} |
|
|
|
.el-table__row { |
|
height: 80px !important; |
|
} |
|
|
|
.el-table__cell { |
|
vertical-align: middle !important; |
|
} |
|
|
|
.error-message { |
|
font-size: 14px; |
|
line-height: 1.5; |
|
} |
|
:deep(.el-table .el-table__cell) { |
|
height: 50px !important; |
|
padding: 0 !important; |
|
line-height: 50px !important; |
|
} |
|
</style>
|
|
|