first commit

This commit is contained in:
2025-12-26 23:19:09 +08:00
commit b29d128e41
788 changed files with 100922 additions and 0 deletions

View File

@@ -0,0 +1,406 @@
<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";
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();
}
} 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>