<template> <div class="operate"> <el-form ref="operateRuleForm" :model="form" :rules="rules"> <el-divider content-position="left">基本情况</el-divider> <el-row :gutter="20"> <el-col :span="8"> <el-form-item label="项目类别:" prop="projectTypeId"> <el-select v-model="form.projectTypeId" placeholder="请选择项目类别" style="width: 100%" @change="projectTypeChange"> <el-option v-for="dict in props.types" :key="dict.id" :label="dict.projectTypeName" :value="dict.id" /> </el-select> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="项目名称:" prop="projectName" class="formItem"> <el-input v-model="form.projectName" placeholder="请输入项目名称" /> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="项目昵称:" prop="projectName1" class="formItem"> <el-input v-model="form.projectName1" placeholder="请输入项目昵称" /> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="建设类别:" prop="buildCategory"> <el-select v-model="form.buildCategory" placeholder="请选择建设类别" style="width: 100%"> <el-option v-for="dict in props.buildCategory" :key="dict.value" :label="dict.label" :value="dict.value" /> </el-select> </el-form-item> </el-col> </el-row> <el-row :gutter="20"> <el-col :span="8"> <el-form-item label="汇水分区:" prop="drainagePartition"> <el-select v-model="form.drainagePartition" placeholder="请选择" style="width: 100%"> <el-option v-for="dict in drainage_partition" :key="dict.value" :label="dict.label" :value="dict.value" /> </el-select> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="计划日期:" prop="time" class="formItem"> <el-date-picker v-model="form.time" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" value-format="YYYY-MM-DD" /> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="完工日期:" prop="time1" class="formItem"> <el-date-picker type="date" v-model="form.projectCompleteTime" value-format="YYYY-MM-DD" start-placeholder="开始日期" /> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="规划条件:" prop="planCondition"> <el-input v-model="form.planCondition" placeholder="请输入规划条件" /> </el-form-item> </el-col> </el-row> <el-row :gutter="20"> <el-col :span="16"> <el-form-item label="项目位置:" prop="projectLocation"> <el-input v-model="form.projectLocationName" controls-position="right" placeholder="请输入"> <template #append> <el-button type="primary" @click="visible = true">获取经纬度</el-button> </template> </el-input> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="是否豁免项目:" prop="isProjectExempt"> <el-select v-model="form.isProjectExempt" placeholder="请选择" style="width: 100%"> <el-option label="是" value="1" /> <el-option label="否" value="0" /> </el-select> </el-form-item> </el-col> </el-row> <el-row :gutter="20" v-if="form.isProjectExempt == 1"> <el-col :span="20"> <el-form-item label="豁免证明文件:" prop="exemptFileSaveRequestList"> <ImageFileUpload listType="text" :limit="1" :saveFileArr="form.exemptFileSaveRequestList" refType="projectInfoNew" refField="investmentApproval" :fileType="['png', 'jpg', 'jpeg', 'pdf', 'txt']" /> </el-form-item> </el-col> </el-row> <el-row :gutter="20"> <el-col :span="8"> <el-form-item label="项目库类型:" prop="projectLibraryType" class="formItem"> <el-select v-model="form.projectLibraryType" placeholder="请选择项目库类型" style="width: 100%"> <el-option v-for="dict in props.projectLibraryType" :key="dict.value" :label="dict.label" :value="dict.value" /> </el-select> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="任务类型:" prop="taskType"> <el-select v-model="form.taskType" placeholder="请选择任务类型" style="width: 100%"> <el-option v-for="dict in task_type" :key="dict.value" :label="dict.label" :value="dict.value" /> </el-select> </el-form-item> </el-col> <el-col :span="8"> <!-- 任务类型为控源头时才选择规划分区 --> <el-form-item label="规划分区:" prop="controlPartitionNum"> <el-input v-model="form.controlPartitionNum" controls-position="right" placeholder="请输入"> <template #append> <el-button type="primary" @click="visibleArea = true">获取分区</el-button> </template> </el-input> </el-form-item> </el-col> </el-row> <el-row> <el-form-item label="项目概况:" prop="projectOverview" style="width: 100%"> <el-input type="textarea" v-model="form.projectOverview" placeholder="请输入项目概况" resize="none" /> </el-form-item> </el-row> <el-divider content-position="left">项目内容</el-divider> <el-card class="box-card" shadow="never" v-for="(item, index) in projectContentList"> <template #header> <div class="card-header"> <span>{{ item.label }}</span> </div> </template> <el-table :data="form[`list${index + 2}`]"> <el-table-column v-for="it in item.list" :label="it.propertyName" :prop="it.propertyKey"> <template #default="{ row }"> <el-input v-model="row[it.propertyKey]" /> </template> </el-table-column> </el-table> </el-card> <el-divider content-position="left">项目投资</el-divider> <el-row :gutter="20"> <el-col :span="12"> <el-form-item label="投资批复文件说明(已批复项目填写):" prop="investFileName"> <el-input v-model="form.investFileName" placeholder="请输入投资批复文件说明" /> </el-form-item> </el-col> <el-col :span="12"> <div class="upload"> <ImageFileUpload listType="text" :limit="1" :saveFileArr="form.sysFileSaveRequestList" refType="projectInfoNew" refField="investmentApproval" :fileType="['pdf', 'doc', 'docx', 'xlsx', 'xls', 'txt']" /> </div> </el-col> </el-row> <el-row :gutter="20"> <el-col :span="8"> <el-form-item label="项目总投资(含主体工程)(万元):" prop="totalInvest"> <el-input v-model="form.totalInvest" placeholder="请输入项目总投资" /> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="地方政府投资(万元):" prop="govermentInvest"> <el-input v-model="form.govermentInvest" placeholder="请输入地方政府投资" /> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="社会资本投入(万元):" prop="socialInvest"> <el-input v-model="form.socialInvest" placeholder="请输入社会资本投入" /> </el-form-item> </el-col> </el-row> <el-row :gutter="20"> <el-col :span="8"> <el-form-item label="项目运作模式:" prop="projectOperationPattern"> <el-select v-model="form.projectOperationPattern" placeholder="请选择项目运作模式" style="width: 100%"> <el-option v-for="dict in project_operation_pattern" :key="dict.value" :label="dict.label" :value="dict.value" /> </el-select> </el-form-item> </el-col> <el-col :span="10"> <el-form-item label="海绵相关投资(不含主体工程)(万元):" prop="spongeInvest"> <el-input v-model="form.spongeInvest" placeholder="请输入海绵相关投资" /> </el-form-item> </el-col> </el-row> <el-table :data="form.list1" v-if="projectInvestList[0]"> <el-table-column v-for="it in projectInvestList[0].list" :label="it.propertyName" :prop="it.propertyKey"> <template #default="{ row }"> <el-input v-model="row[it.propertyKey]" /> </template> </el-table-column> </el-table> <el-divider content-position="left">责任部门</el-divider> <el-row :gutter="20"> <el-col :span="8"> <el-form-item label="责任部门:" prop="chargeDepartment"> <el-input v-model="form.chargeDepartment" placeholder="请输入责任部门" /> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="责任人:" prop="chargeUser"> <el-input v-model="form.chargeUser" placeholder="请输入责任人" /> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="联系方式:" prop="phone"> <el-input v-model="form.phone" placeholder="请输入联系方式" /> </el-form-item> </el-col> </el-row> <el-row :gutter="20"> <el-col :span="8"> <el-form-item label="设计单位:" prop="designUnit"> <el-select v-model="form.designUnit" placeholder="请选择设计单位" filterable style="width: 100%"> <el-option v-for="dict in projectCompanyList3" :key="dict.id" :label="dict.unitName" :value="dict.id" /> </el-select> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="施工单位:" prop="constructUnit"> <el-select v-model="form.constructUnit" filterable placeholder="请选择施工单位" style="width: 100%"> <el-option v-for="dict in projectCompanyList" :key="dict.id" :label="dict.unitName" :value="dict.id" /> </el-select> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="运维单位:" prop="operationUnit"> <el-select v-model="form.operationUnit" filterable placeholder="请选择运维单位" style="width: 100%"> <el-option v-for="dict in projectCompanyList2" :key="dict.id" :label="dict.unitName" :value="dict.id" /> </el-select> </el-form-item> </el-col> </el-row> <el-divider content-position="left">建设进度</el-divider> <el-row :gutter="20"> <el-col :span="12"> <el-form-item label="建设状态:" prop="buildStatus"> <el-select v-model="form.buildStatus" placeholder="请选择建设状态" style="width: 100%"> <el-option v-for="dict in build_status" :key="dict.value" :label="dict.label" :value="dict.value" /> </el-select> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="建设进度:" prop="projectProgress"> <div style="display: flex; width: 100%"> <el-slider v-model="form.projectProgress" style="flex: 1" /> <span style="margin-left: 10px">{{ form.projectProgress + '%' }}</span> </div> </el-form-item> </el-col> </el-row> <el-row :gutter="20"> <el-col :span="12"> <el-form-item label="完成项目总投资(含主体工程)(万元):" prop="accomplishTotalInvest"> <el-input v-model="form.accomplishTotalInvest" placeholder="请输入完成项目总投资" /> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="完成海绵相关投资(不含主体工程)(万元):" prop="accomplishSpongeInvest"> <el-input v-model="form.accomplishSpongeInvest" placeholder="请输入完成海绵相关投资" /> </el-form-item> </el-col> </el-row> <el-row :gutter="20"> <el-col :span="12"> <el-form-item label="建设过程中照片:" prop="underWay"> <div class="upload"> <ImageFileUpload listType="picture-card" :limit="10" :saveFileArr="constractionFlieList" refType="projectInfoNew" refField="constraction" :fileType="['png', 'jpg', 'jpeg']" /> </div> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="建设完成后照片:" prop="complete"> <div class="upload"> <ImageFileUpload listType="picture-card" :limit="10" :saveFileArr="postConstractionFlieList" refType="projectInfoNew" refField="postConstraction" :fileType="['png', 'jpg', 'jpeg']" /> </div> </el-form-item> </el-col> </el-row> </el-form> <!-- 位置选择弹窗 --> <el-dialog v-model="visible" title="选择位置" :close-on-click-modal="false" width="800px"> <div class="mapBox"> <MapBox v-if="visible" :isShowSearch="true" :isShowTool="false" :isSelectAddress="true" :previousPoint="previousPoint" :previousPointName="previousPointName" @getPlace="getAddress" ></MapBox> </div> <template #footer> <div class="dialog-footer"> <el-button type="primary" @click="visible = false">确 定</el-button> </div> </template> </el-dialog> <!-- 规划分区 --> <el-dialog v-model="visibleArea" title="规划分区" :close-on-click-modal="false" width="1200px"> <projectionMap @getProjectArea="getProjectArea"></projectionMap> <template #footer> <div class="dialog-footer"> <el-button type="primary" @click="visibleArea = false">确 定</el-button> </div> </template> </el-dialog> </div> </template> <script setup> import { required } from '@/utils/validate-helper'; import projectionMap from './projectionAreaMap.vue'; import { useDicts } from '@/hooks'; import MapBox from '@/components/Map'; import { inheritAttr } from '@/utils/v3'; import { getProjectCompanyList, getProjectItemDescriptionConfigList, projectInfoNewAdd, projectInfoNewById, getFileLIst, projectInfoNewEdit, } from '@/api/project/projectInformationNew'; import ImageFileUpload from '@/components/ImageFileUpload'; const { proxy } = getCurrentInstance(); const emit = defineEmits(['close']); const { drainage_partition, task_type, project_operation_pattern, build_status } = useDicts(proxy); const props = defineProps({ curRow: { type: Object, default: () => ({}), }, opts: { type: Object, default: () => ({}), }, types: { type: Array, default: () => [], }, buildCategory: { type: Array, default: () => [], }, projectLibraryType: { type: Array, default: () => [], }, projectContentType: { type: Array, default: () => [], }, }); const { curRow, opts } = props; const form = reactive({ projectTypeId: '', projectName: '', buildCategory: '', drainagePartition: '', time: '', projectCompleteTime: proxy.moment(new Date()).format('YYYY-MM-DD'), startTime: '', endTime: '', projectLocation: '', controlPartitionNum: '', isProjectExempt: '0', exemptFileSaveRequestList: [], projectLocationName: '', planCondition: '', projectLibraryType: '', taskType: '', projectOverview: '', investFileName: '', totalInvest: '', govermentInvest: '', socialInvest: '', projectOperationPattern: '', spongeInvest: '', chargeDepartment: '', chargeUser: '', phone: '', designUnit: '', constructUnit: '', operationUnit: '', buildStatus: '', projectProgress: 0, accomplishTotalInvest: '', accomplishSpongeInvest: '', underWay: '', complete: '', fileName: '', list1: [{}], list2: [{}], list3: [{}], list4: [{}], sysFileSaveRequestList: [], }); const rules = reactive({ projectTypeId: required('项目类别'), projectName: required('项目名称'), buildCategory: required('建设类别'), drainagePartition: required('汇水分区'), time: required('项目日期'), projectLocation: required('项目位置'), isProjectExempt: required('豁免项目'), planCondition: required('规划条件'), projectLibraryType: required('项目库类型'), taskType: required('任务类型'), projectOverview: required('项目概况'), investFileName: required('投资批复文件说明'), totalInvest: required('项目总投资'), govermentInvest: required('地方政府投资'), socialInvest: required('社会资本投入'), projectOperationPattern: required('项目运作模式'), spongeInvest: required('海绵相关投资'), chargeDepartment: required('责任部门'), chargeUser: required('责任人'), phone: required('联系方式'), designUnit: required('设计单位'), constructUnit: required('施工单位'), operationUnit: required('运维单位'), }); const projectCompanyList = ref([]); const projectCompanyList2 = ref([]); const projectCompanyList3 = ref([]); const { unit_type } = proxy.useDict('unit_type'); const projectItemDescriptionConfigList = ref([]); const projectContentList = ref([]); const projectInvestList = ref([]); const visible = ref(false); const visibleArea = ref(false); const constractionFlieList = ref([]); const postConstractionFlieList = ref([]); const previousPoint = ref(''); const previousPointName = ref(''); // 获取位置 function getAddress(val) { form.projectLocation = val.lonLat.join(','); //经纬度 form.projectLocationName = val.caseAddress; //位置名称 console.log('获取位置信息--', val, form.projectLocation); } // 获取分区 function getProjectArea(val) { form.controlPartitionNum = val.projectionAreaName; } const submit = () => { proxy.$refs.operateRuleForm.validate(async (valid, fields) => { if (valid) { console.log('submit!', form); if (form.isProjectExempt == '0') form.exemptFileSaveRequestList = []; const projectItemDescriptionSaveRequestList = []; for (let i = 0; i < projectContentList.value.length; i++) { const formList = form[`list${i + 2}`]; const item = projectContentList.value[i]; for (const it of item.list) { for (const key in formList[0]) { if (Object.hasOwnProperty.call(formList[0], key)) { const element = formList[0][key]; if (key === it.propertyKey) { it.propertyValue = element; } } } projectItemDescriptionSaveRequestList.push(it); } } for (let j = 0; j < projectInvestList.value.length; j++) { const formList = form.list1; const item = projectInvestList.value[j]; for (const it of item.list) { for (const key in formList[0]) { if (Object.hasOwnProperty.call(formList[0], key)) { const element = formList[0][key]; if (key === it.propertyKey) { it.propertyValue = element; } } } projectItemDescriptionSaveRequestList.push(it); } } let sysFileSaveRequestList = JSON.parse(JSON.stringify(form.sysFileSaveRequestList)); sysFileSaveRequestList = sysFileSaveRequestList.concat(constractionFlieList.value, postConstractionFlieList.value); const params = { id: curRow?.id || '', ...form, startTime: form.time[0], endTime: form.time[1], projectItemDescriptionSaveRequestList, sysFileSaveRequestList, }; delete params.list1; delete params.list2; delete params.list3; delete params.list4; delete params.time; let methed = ''; if (params.id) { methed = projectInfoNewEdit; } else { methed = projectInfoNewAdd; } if (!methed) return; const res = await methed(params); if (res?.code !== 200) return; proxy.$modal.msgSuccess('操作成功!'); emit('close', opts.type); } else { console.log('error submit!', fields); } }); }; const getProjectCompanyLists = async () => { const res = await getProjectCompanyList(); if (res && res.code == 200) { let datas = res.data; // 施工单位 projectCompanyList.value = datas.filter(item => item.unitType == unit_type.value[0].value); // 运维单位 projectCompanyList2.value = datas.filter(item => item.unitType == unit_type.value[1].value); // 设计单位 projectCompanyList3.value = datas.filter(item => item.unitType == unit_type.value[2].value); } }; const getProjectItemDescriptionConfigLists = async () => { const res = await getProjectItemDescriptionConfigList({ projectTypeId: form.projectTypeId }); if (res?.code !== 200) return; projectItemDescriptionConfigList.value = res?.data || []; console.log(projectItemDescriptionConfigList); projectContentList.value = props.projectContentType.slice(0, 3).map((item, i) => { const list = projectItemDescriptionConfigList.value.filter(it => it.projectContentType === item.value); const obj = {}; for (const item of list) { obj[item.propertyKey] = ''; } form[`list${i + 2}`] = [obj]; return { list: JSON.parse(JSON.stringify(list)), label: item.label, }; }); projectInvestList.value = props.projectContentType.slice(3).map(item => { const list = projectItemDescriptionConfigList.value.filter(it => it.projectContentType === item.value); const obj = {}; for (const item of list) { obj[item.propertyKey] = ''; } form.list1 = [obj]; return { list: JSON.parse(JSON.stringify(list)), label: item.label, }; }); console.log(projectContentList, projectInvestList); }; const projectTypeChange = () => { form.list1 = [{}]; form.list2 = [{}]; form.list3 = [{}]; form.list4 = [{}]; getProjectItemDescriptionConfigLists(); }; const getDetail = async () => { const res = await projectInfoNewById(curRow.id); if (res?.code !== 200) return; console.log(res.data, 'ressssss'); previousPoint.value = res.data.projectLocation; previousPointName.value = res.data.projectName; form.time = [res.data.startTime, res.data.endTime]; inheritAttr(res.data, form); projectItemDescriptionConfigList.value = res?.data?.projectItemDescriptionList || []; console.log(projectItemDescriptionConfigList); projectContentList.value = props.projectContentType.slice(0, 3).map((item, i) => { const list = projectItemDescriptionConfigList.value.filter(it => it.projectContentType === item.value); const obj = {}; for (const item of list) { obj[item.propertyKey] = item.propertyValue; } form[`list${i + 2}`] = [obj]; return { list: JSON.parse(JSON.stringify(list)), label: item.label, }; }); projectInvestList.value = props.projectContentType.slice(3).map(item => { const list = projectItemDescriptionConfigList.value.filter(it => it.projectContentType === item.value); const obj = {}; for (const item of list) { obj[item.propertyKey] = item.propertyValue; } form.list1 = [obj]; return { list: JSON.parse(JSON.stringify(list)), label: item.label, }; }); getFileInfo(res.data.id, 'projectInfoNew', 'investmentApproval', data => { console.log(data); form.fileName = data?.[0]?.name || ''; if (data?.[0]) { form.sysFileSaveRequestList = [data[0]]; } }); res.data.sysFileList = res.data.sysFileList || []; for (const item of res.data.sysFileList) { item.refType = 'projectInfoNew'; } constractionFlieList.value = res.data.sysFileList.filter(item => item.refField === 'constraction'); postConstractionFlieList.value = res.data.sysFileList.filter(item => item.refField === 'postConstraction'); }; const getFileInfo = async (id, refType, refField, callback) => { const res = await getFileLIst({ refId: id, refType, refField }); if (res?.code !== 200) return; callback && callback(res.data); }; onMounted(() => { getProjectCompanyLists(); if (curRow?.id) { getDetail(); } else { if (props.types.length) { form.projectTypeId = props.types[0].id; getProjectItemDescriptionConfigLists(); } } }); defineExpose({ submit, }); </script> <style lang="scss" scoped> .operate { .box-card { margin-top: 10px; &:first-of-type { margin-top: 0; } } .tips { margin-left: 10px; line-height: 30px; } .upload { position: relative; .fileName { position: absolute; left: 0; top: 30px; white-space: nowrap; display: flex; align-items: center; .del { flex-shrink: 0; color: #f56c6c; cursor: pointer; margin-left: 10px; } } .imgBox { display: flex; flex-wrap: wrap; .img { margin-right: 10px; } } } .img { position: relative; width: 178px; height: 178px; img { width: 100%; height: 100%; } .mask { position: absolute; left: 0; right: 0; top: 0; bottom: 0; background-color: rgba(0, 0, 0, 0.5); display: none; .icon { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); color: #fff; } } &:hover { .mask { display: block; } } } } .mapBox { height: 600px; } </style>