410 lines
16 KiB
Vue
410 lines
16 KiB
Vue
<template>
|
|
<div class="layout-padding">
|
|
<div class="layout-padding-auto layout-padding-view">
|
|
<!-- 顶部操作按钮 -->
|
|
<el-row class="mb10">
|
|
<div class="form-header-actions" style="width: 100%;">
|
|
<div>
|
|
<el-button type="primary" icon="Check" :loading="submitLoading" @click="handleInitiateApproval">
|
|
{{ t('reserveRegistration.initiateApproval') }}
|
|
</el-button>
|
|
<el-button icon="Document" @click="handleSaveDraft" :loading="saveLoading">
|
|
{{ t('reserveRegistration.saveDraft') }}
|
|
</el-button>
|
|
<el-button icon="FolderOpened" @click="handleLoadTemplate">
|
|
{{ t('reserveRegistration.loadTemplate') }}
|
|
</el-button>
|
|
<el-button icon="FolderAdd" @click="handleSaveTemplate">
|
|
{{ t('reserveRegistration.saveTemplate') }}
|
|
</el-button>
|
|
</div>
|
|
<div style="margin-left:auto;">
|
|
<el-button icon="View" @click="handleViewWorkflow" :loading="viewLoading">
|
|
{{ t('reserveRegistration.viewWorkflow') }}
|
|
</el-button>
|
|
</div>
|
|
</div>
|
|
</el-row>
|
|
|
|
<!-- 标题、描述、上传附件 -->
|
|
<el-row class="mb10">
|
|
<el-form :model="headerForm" label-width="80px" class="w-full" :rules="headerRequiredRule" ref="headerFormRef">
|
|
<el-form-item :label="t('reserveRegistration.formTitle')" prop="title">
|
|
<el-input v-model="headerForm.title" :placeholder="t('reserveRegistration.titlePlaceholder')" maxlength="255"/>
|
|
</el-form-item>
|
|
<el-form-item :label="t('reserveRegistration.description')">
|
|
<el-input v-model="headerForm.description"
|
|
:placeholder="t('reserveRegistration.descriptionPlaceholder')" maxlength="255"/>
|
|
</el-form-item>
|
|
<el-form-item :label="t('reserveRegistration.uploadAttachment')">
|
|
<UploadFile :modelValue="headerForm.attachments" :fileSize="20" type="simple" :limit="10"
|
|
@change="(url: string, files: any[]) => headerForm.attachments = files?.map((item: any) => ({ name: item.name, url: item.url })) || []" />
|
|
</el-form-item>
|
|
</el-form>
|
|
</el-row>
|
|
|
|
<!-- 项目基本信息表单 -->
|
|
<ProjectBasicInfoForm
|
|
ref="basicInfoFormRef"
|
|
:model-value="projectFormData"
|
|
:mainTitle="isUpdate ? t('reserveRegistration.updateTitle') : t('reserveRegistration.title')"
|
|
:is-update="isUpdate"
|
|
/>
|
|
<template-table-common />
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import {computed, reactive, ref, watch} from 'vue';
|
|
import {useI18n} from 'vue-i18n';
|
|
import {useMessage} from '/@/hooks/message';
|
|
import type {ProjectBasicInfoFormData} from '/@/components/investment/common/ProjectBasicInfoForm.vue';
|
|
import ProjectBasicInfoForm from '/@/components/investment/common/ProjectBasicInfoForm.vue';
|
|
import {
|
|
addReserveInvestmentProjectAPI,
|
|
getReserveInvestmentProjectsByTemplateIdAPI
|
|
} from '/@/api/investment/reserveRegistration';
|
|
import templateTableCommon from "/@/components/templetTableComom/index.vue"
|
|
import {useUserInfo} from '/@/stores/userInfo';
|
|
import {formatDate} from '/@/utils/formatTime';
|
|
import {flowFn} from "/@/utils/flowFn";
|
|
import {addFlowForm} from '/@/api/flow/flow';
|
|
import {flowNameOptions} from '/@/hooks/enums';
|
|
import {addTemplate, getUserDeptBelong} from "/@/api/common";
|
|
import {templateStore} from "/@/stores/template";
|
|
import type {FormInstance, FormRules} from "element-plus";
|
|
import {useRouter} from "vue-router";
|
|
|
|
const router = useRouter();
|
|
const temp = templateStore();
|
|
const props = defineProps({
|
|
isUpdate: {
|
|
type: Boolean,
|
|
default: false
|
|
}
|
|
})
|
|
|
|
const { t } = useI18n();
|
|
const message = useMessage();
|
|
const submitLoading = ref(false);
|
|
|
|
const headerForm = reactive({
|
|
id: '',
|
|
title: '',
|
|
description: '',
|
|
attachments: [] as any[],
|
|
});
|
|
const headerRequiredRule = ref<FormRules>({
|
|
title: [{ required: true, message: t('该字段必传'), trigger: 'blur' }],
|
|
});
|
|
const headerFormRef = ref<FormInstance>();
|
|
const userInfoStore = useUserInfo();
|
|
const currentApplicant = computed(() => userInfoStore.userInfos.user?.username || '');
|
|
const currentApplicationUnit = computed(() => userInfoStore.userInfos.user?.deptName || '');
|
|
const currentApplicationDate = computed(() => formatDate(new Date(), 'YYYY-mm-dd'));
|
|
|
|
const createDefaultProjectFormData = (): ProjectBasicInfoFormData => ({
|
|
applicant: currentApplicant.value,
|
|
applicationUnit: currentApplicationUnit.value,
|
|
projectName: '',
|
|
projectMainUnit: '',
|
|
projectStartDate: '',
|
|
investmentCategory: '',
|
|
projectManagerName: '',
|
|
projectSource: '',
|
|
keyProject: '',
|
|
withinMainBusiness: '',
|
|
mainBusinessType: '',
|
|
projectDirection: '',
|
|
strategicEmergingIndustry: '',
|
|
isManufacturing: '',
|
|
projectAddress: '',
|
|
isControllingShareholder: '',
|
|
totalInvestmentAmount: '',
|
|
ourTotalInvestmentAmount: '',
|
|
projectDesc: '',
|
|
progressDesc: '',
|
|
projectProposal: [],
|
|
applicationDate: currentApplicationDate.value,
|
|
projectOwnerUnit: '',
|
|
projectEndDate: '',
|
|
projectNature: '',
|
|
contactNumber: '',
|
|
constructionNature: '',
|
|
majorInvestmentProject: '',
|
|
mainBusinessCode: '',
|
|
directionSubdivision: '',
|
|
urbanStrategy: '',
|
|
investmentRegion: '',
|
|
projectDetailedAddress: '',
|
|
ourShareholdingRatio: '',
|
|
cumulativeInvestmentLastYear: '',
|
|
ourCumulativeInvestmentLastYear: '',
|
|
enterpriseSelfFund: '',
|
|
externalRaisedFund: '',
|
|
governmentInvestmentFund: '',
|
|
otherFunds: '',
|
|
partnerInfos: [],
|
|
decisionType: '',
|
|
isCompleteEstablishmentProcedures: '',
|
|
establishmentDocumentNumber: '',
|
|
establishmentDocumentInfo: '',
|
|
decisionProgramDocumentNumber: '',
|
|
decisionDocumentInfo: '',
|
|
isCompleteDecisionProcedures: '',
|
|
reviewOpinions: {
|
|
submitUnitOpinion: '',
|
|
groupInvestmentDeptOpinion: '',
|
|
submitUnitLeadershipOpinion: '',
|
|
submitUnitMainLeadershipOpinion: '',
|
|
},
|
|
processInstanceId: '',
|
|
status: 1
|
|
});
|
|
|
|
const projectFormData = reactive<ProjectBasicInfoFormData>(createDefaultProjectFormData());
|
|
|
|
watch(currentApplicant, val => {
|
|
if (!projectFormData.applicant) {
|
|
projectFormData.applicant = val;
|
|
}
|
|
});
|
|
watch(currentApplicationUnit, val => {
|
|
if (!projectFormData.applicationUnit) {
|
|
projectFormData.applicationUnit = val;
|
|
}
|
|
});
|
|
watch(currentApplicationDate, val => {
|
|
if (!projectFormData.applicationDate) {
|
|
projectFormData.applicationDate = val;
|
|
}
|
|
});
|
|
|
|
const resetHeaderForm = () => {
|
|
headerForm.id = '';
|
|
headerForm.title = '';
|
|
headerForm.description = '';
|
|
headerForm.attachments = [];
|
|
};
|
|
|
|
const resetProjectForm = () => {
|
|
const defaults = createDefaultProjectFormData();
|
|
Object.assign(projectFormData, defaults);
|
|
projectFormData.projectProposal = [];
|
|
if (projectFormData.partnerInfos?.length) {
|
|
projectFormData.partnerInfos.splice(0, projectFormData.partnerInfos.length);
|
|
}
|
|
Object.assign(projectFormData.reviewOpinions, defaults.reviewOpinions);
|
|
};
|
|
|
|
|
|
const toNumber = (value: string | number | undefined | null) => {
|
|
if (value === '' || value === undefined || value === null) return undefined;
|
|
const num = Number(value);
|
|
return Number.isFinite(num) ? num : undefined;
|
|
};
|
|
|
|
const extractPartnerIds = () => {
|
|
if (!Array.isArray(projectFormData.partnerInfos)) return [] as Array<string | number>;
|
|
return projectFormData.partnerInfos
|
|
.map(item => item?.id)
|
|
.filter((id): id is string | number => id !== undefined && id !== null && id !== '');
|
|
};
|
|
|
|
const buildSubmitPayload = () => ({
|
|
id: headerForm.id || undefined,
|
|
parentId: projectFormData.parentId || undefined,
|
|
projectName: projectFormData.projectName,
|
|
projectOwnerUnit: projectFormData.projectOwnerUnit,
|
|
projectMainEntity: projectFormData.projectMainUnit,
|
|
projectStartTime: projectFormData.projectStartDate,
|
|
projectEndTime: projectFormData.projectEndDate,
|
|
investmentCategory: projectFormData.investmentCategory,
|
|
projectNature: projectFormData.projectNature,
|
|
projectLeaderName: projectFormData.projectManagerName,
|
|
projectLeaderPhone: projectFormData.contactNumber,
|
|
projectSource: projectFormData.projectSource,
|
|
constructionNature: projectFormData.constructionNature,
|
|
keyProject: projectFormData.keyProject,
|
|
majorInvestmentProjects: projectFormData.majorInvestmentProject,
|
|
isMainBusiness: projectFormData.withinMainBusiness,
|
|
mainBusinessTypes: projectFormData.mainBusinessType,
|
|
mainBusinessCode: projectFormData.mainBusinessCode,
|
|
projectInvestmentDirection: projectFormData.projectDirection,
|
|
investmentDirectionSegmentation: projectFormData.directionSubdivision,
|
|
isStrategicEmergingIndustries: projectFormData.strategicEmergingIndustry,
|
|
urbanStrategy: projectFormData.urbanStrategy,
|
|
isManufacturingIndustry: projectFormData.isManufacturing,
|
|
investmentArea: projectFormData.investmentRegion,
|
|
projectAddress: projectFormData.projectAddress,
|
|
projectAddressDetail: projectFormData.projectDetailedAddress,
|
|
isControllingStake: projectFormData.isControllingShareholder,
|
|
shareholdingRatio: toNumber(projectFormData.ourShareholdingRatio),
|
|
projectTotalAmount: toNumber(projectFormData.totalInvestmentAmount),
|
|
lastYearCompleted: toNumber(projectFormData.cumulativeInvestmentLastYear),
|
|
ourInvestmentTotalAmount: toNumber(projectFormData.ourTotalInvestmentAmount),
|
|
ourLastYearCompleted: toNumber(projectFormData.ourCumulativeInvestmentLastYear),
|
|
projectDesc: projectFormData.projectDesc,
|
|
attachmentUrl: projectFormData.projectProposal,
|
|
enterpriseOwnFunds: toNumber(projectFormData.enterpriseSelfFund),
|
|
governmentInvestmentFunds: toNumber(projectFormData.governmentInvestmentFund),
|
|
externalRaisedFunds: toNumber(projectFormData.externalRaisedFund),
|
|
otherFunds: toNumber(projectFormData.otherFunds),
|
|
decisionType: projectFormData.decisionType,
|
|
isProjectApprovalCompleted: projectFormData.isCompleteEstablishmentProcedures,
|
|
projectApprovalFileNo: projectFormData.establishmentDocumentNumber,
|
|
projectApprovalFileInfo: projectFormData.establishmentDocumentInfo,
|
|
isDecisionProcedureCompleted: projectFormData.isCompleteDecisionProcedures,
|
|
decisionProcedureFileNo: projectFormData.decisionProgramDocumentNumber,
|
|
decisionFileInfo: projectFormData.decisionDocumentInfo,
|
|
processInstanceId: projectFormData.processInstanceId,
|
|
progressDesc: projectFormData.progressDesc,
|
|
partnerIds: extractPartnerIds(),
|
|
status:1,
|
|
flowType: 0,
|
|
temporaryStorage:undefined,
|
|
templateId:undefined,
|
|
businessType:undefined,
|
|
deptId:projectFormData.deptId
|
|
});
|
|
|
|
const basicInfoFormRef = ref()
|
|
const handleInitiateApproval = async () => {
|
|
if (submitLoading.value) return;
|
|
const re = await headerFormRef.value?.validate()
|
|
if (!re) return;
|
|
const basicInfoFormData = await basicInfoFormRef.value?.validate()
|
|
Object.assign(projectFormData, basicInfoFormData)
|
|
submitLoading.value = true;
|
|
try {
|
|
let flowIdKey = props.isUpdate ? 'VITE_FLOWID_5' : 'VITE_FLOWID_1'
|
|
const data = await getUserDeptBelong()
|
|
if(data.data === 1){
|
|
flowIdKey = props.isUpdate ?'VITE_FLOWID_5' : 'VITE_FLOWID_1'
|
|
}else if (data.data === 2){
|
|
flowIdKey = props.isUpdate ?'VITE_FLOWID_6' : 'VITE_FLOWID_2'
|
|
}else if (data.data === 3){
|
|
flowIdKey = props.isUpdate ?'VITE_FLOWID_7' : 'VITE_FLOWID_3'
|
|
}else if (data.data === 4){
|
|
flowIdKey = props.isUpdate ?'VITE_FLOWID_8' : 'VITE_FLOWID_4'
|
|
}
|
|
const { processInstanceId } = await flowFn(flowIdKey, { paramMap: {} });
|
|
const flowName = props.isUpdate ? 'reserveUpdate' : 'reserveRegistration'
|
|
const flowNameObj = flowNameOptions.filter(item => item.label === flowName)[0]
|
|
await addFlowForm({
|
|
title: headerForm.title,
|
|
description: headerForm.description,
|
|
attachments: JSON.stringify(headerForm.attachments),
|
|
processInstanceId,
|
|
flowType: flowNameObj.value
|
|
})
|
|
const payload = buildSubmitPayload();
|
|
payload.processInstanceId = processInstanceId
|
|
payload.flowType = flowNameObj.value
|
|
if (payload) {
|
|
await addReserveInvestmentProjectAPI({
|
|
...payload,
|
|
attachmentUrl: payload.attachmentUrl ? JSON.stringify(payload.attachmentUrl) : '',
|
|
});
|
|
message.success(t('common.success'));
|
|
resetHeaderForm();
|
|
resetProjectForm();
|
|
await router.push('/flow/task/started')
|
|
}
|
|
} catch (error: any) {
|
|
message.error(error?.msg || error?.message || t('common.fail'));
|
|
} finally {
|
|
submitLoading.value = false;
|
|
}
|
|
};
|
|
const saveLoading = ref(false);
|
|
const handleSaveDraft = async () => {
|
|
if (saveLoading.value) return;
|
|
const basicInfoFormData = await basicInfoFormRef.value?.validate()
|
|
Object.assign(projectFormData, basicInfoFormData)
|
|
saveLoading.value = true;
|
|
try {
|
|
const flowName = props.isUpdate ? 'reserveUpdate' : 'reserveRegistration'
|
|
const flowNameObj = flowNameOptions.filter(item => item.label === flowName)[0]
|
|
const payload = buildSubmitPayload();
|
|
payload.flowType = flowNameObj.value
|
|
payload.status = 0
|
|
if (payload) {
|
|
await addReserveInvestmentProjectAPI({
|
|
...payload,
|
|
attachmentUrl: payload.attachmentUrl ? JSON.stringify(payload.attachmentUrl) : '',
|
|
temporaryStorage: {
|
|
id: payload.id,
|
|
businessType:flowNameObj.value,
|
|
title:headerForm.title,
|
|
}
|
|
});
|
|
message.success(t('common.success'));
|
|
resetHeaderForm();
|
|
resetProjectForm();
|
|
}
|
|
}catch (error: any){
|
|
message.error(error?.msg || error?.message || t('common.fail'));
|
|
} finally{
|
|
saveLoading.value = false;
|
|
}
|
|
};
|
|
const tempId = computed(() => temp.temp_id);
|
|
const handleLoadTemplate = () => {
|
|
const flowName = props.isUpdate ? 'reserveUpdate' : 'reserveRegistration'
|
|
const flowNameObj = flowNameOptions.filter(item => item.label === flowName)[0]
|
|
temp.changeTempShow(true,flowNameObj.value);
|
|
};
|
|
watch(()=> tempId.value,()=>{
|
|
getReserveInvestmentProjectsByTemplateIdAPI(tempId.value).then(data => {
|
|
Object.assign(projectFormData, data);
|
|
})
|
|
})
|
|
const viewLoading = ref(false);
|
|
const handleSaveTemplate = async () => {
|
|
const re = await headerFormRef.value?.validate()
|
|
if (!re) return;
|
|
if (viewLoading.value) return;
|
|
const basicInfoFormData = await basicInfoFormRef.value?.validate()
|
|
Object.assign(projectFormData, basicInfoFormData)
|
|
viewLoading.value = true;
|
|
try {
|
|
const flowName = props.isUpdate ? 'reserveUpdate' : 'reserveRegistration'
|
|
const flowNameObj = flowNameOptions.filter(item => item.label === flowName)[0]
|
|
const {data: templateId}= await addTemplate({templateName:headerForm.title,templateType:flowNameObj.value});
|
|
const payload = buildSubmitPayload();
|
|
payload.templateId = templateId;
|
|
payload.flowType = flowNameObj.value
|
|
payload.status = 0;
|
|
if (payload) {
|
|
await addReserveInvestmentProjectAPI(payload);
|
|
message.success(t('common.success'));
|
|
resetHeaderForm();
|
|
resetProjectForm();
|
|
}
|
|
}catch (error: any){
|
|
message.error(error?.msg || error?.message || t('common.fail'));
|
|
} finally{
|
|
viewLoading.value = false;
|
|
}
|
|
};
|
|
|
|
const handleViewWorkflow = () => {
|
|
message.info(t('reserveRegistration.viewWorkflowClicked'));
|
|
// TODO: 实现查看流程逻辑
|
|
};
|
|
</script>
|
|
|
|
<style scoped>
|
|
.layout-container .layout-padding-view {
|
|
overflow: auto;
|
|
}
|
|
|
|
.form-header-actions {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
}
|
|
</style>
|