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,109 @@
<template>
<div>
<el-row class="mb10 header-meta">
<div class="meta-item">{{ t('cooperationUnit.reporterLabel') + displayReporter }}</div>
<div class="meta-item">{{ t('cooperationUnit.reportingUnitLabel') + displayUnit }}</div>
<div class="meta-item">{{ t('cooperationUnit.dateLabel') + displayDate }}</div>
<div class="meta-item">{{ t('cooperationUnit.serialNumber') + '--' }}</div>
</el-row>
<!-- 动态明细表按图示 -->
<el-table :data="data" border style="width: 100%;">
<el-table-column type="index" :label="t('cooperationUnit.index')" width="60" />
<el-table-column prop="cooperationName" :label="t('cooperationUnit.cooperationName')" min-width="200" />
<el-table-column prop="areaCode" :label="t('cooperationUnit.provinceCity')" min-width="240">
<template #default="scope">
{{ scope.row.areaCode }}
</template>
</el-table-column>
<el-table-column prop="cooperationNature" :label="t('cooperationUnit.cooperationNature')" min-width="140">
<template #default="{ row }">
{{ cooperationPartnerNatureOptions.find(item => item.value === row.cooperationNature)?.label || row.cooperationNature || '--' }}
</template>
</el-table-column>
<el-table-column prop="cooperationIndustry" :label="t('cooperationUnit.cooperationIndustry')" min-width="160" />
<el-table-column prop="proposedBusinessCooperation" :label="t('cooperationUnit.proposedBusinessCooperation')" min-width="180" />
<el-table-column prop="cooperationAdvantage" :label="t('cooperationUnit.cooperationAdvantage')" min-width="160" />
<el-table-column prop="cooperationStatus" :label="t('cooperationUnit.cooperationStatus')" min-width="140" />
<el-table-column prop="startTime" :label="t('cooperationUnit.startTime')" min-width="170" />
<el-table-column prop="endTime" :label="t('cooperationUnit.endTime')" min-width="170" />
<el-table-column prop="unitAddress" :label="t('cooperationUnit.unitAddress')" min-width="200" />
<el-table-column prop="unitContactPerson" :label="t('cooperationUnit.unitContactPerson')" min-width="150" />
<el-table-column prop="contactPersonDept" :label="t('cooperationUnit.contactPersonDept')" min-width="160" />
<el-table-column prop="contactPersonPhone" :label="t('cooperationUnit.contactPersonPhone')" min-width="160" />
<el-table-column prop="potentialCooperation" :label="t('cooperationUnit.potentialCooperation')" min-width="180" />
<el-table-column prop="businessConnectionCompany" :label="t('cooperationUnit.businessConnectionCompany')" min-width="200" />
<el-table-column prop="cooperationController" :label="t('cooperationUnit.actualController')" min-width="160" />
<el-table-column prop="shareholdingRatio" :label="t('cooperationUnit.shareholdingRatio')" min-width="140" />
</el-table>
</div>
</template>
<script lang="ts" name="bizInvestmentCooperationUnit" setup>
import { useI18n } from 'vue-i18n';
import { useUserInfo } from '/@/stores/userInfo';
import { formatDate } from '/@/utils/formatTime';
import { cooperationPartnerNatureOptions } from '/@/hooks/enums'
const props = defineProps({
isUpdate: {
type: Boolean,
default: false
},
data: {
type: Array,
default: () => ([])
}
})
const { t } = useI18n();
// 头部摘要显示
const userInfoStore = useUserInfo();
const displayReporter = (userInfoStore.userInfos.user?.username || '');
const displayUnit = (userInfoStore.userInfos.user?.deptName || '');
const displayDate = formatDate(new Date(), 'YYYY-mm-dd');
</script>
<style scoped>
.form-header-actions {
display: flex;
justify-content: space-between;
align-items: center;
}
.header-summary .title {
margin: 0 auto;
font-size: 18px;
font-weight: 600;
}
.header-meta {
display: flex;
justify-content: space-between;
align-items: center;
width: 50%;
margin: 0 auto;
}
.header-meta .meta-item {
color: var(--el-text-color-regular);
}
.required-star {
color: var(--el-color-danger);
margin-right: 2px;
}
.red-label {
color: var(--el-color-danger);
}
</style>
<style scoped>
.form-header-actions {
display: flex;
justify-content: space-between;
align-items: center;
}
</style>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,617 @@
<template>
<div class="project-basic-info-form">
<div class="form-section-title">{{ t('reserveRegistration.basicInfo.title') }}</div>
<el-form
label-width="220px"
class="project-form"
ref="formRef"
>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.basicInfo.applicant')">
{{ formData.applicant || '--' }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.basicInfo.applicationDate')">
{{ formData.applicationDate || '--' }}
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="24">
<el-form-item :label="t('reserveRegistration.basicInfo.applicationUnit')">
{{ formData.applicationUnit || '--' }}
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="24">
<el-form-item :label="t('reserveRegistration.basicInfo.projectName')">
{{ formData.projectName || '--' }}
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.basicInfo.projectMainUnit')">
{{ formData.projectMainUnit || '--' }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.basicInfo.projectOwnerUnit')">
{{ formData.projectOwnerUnit || '--' }}
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.basicInfo.projectStartDate')">
{{ formData.projectStartDate || '--' }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.basicInfo.projectEndDate')">
{{ formData.projectEndDate || '--' }}
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.basicInfo.investmentCategory')">
{{ investmentCategoryOptions.find(item => item.value === formData.investmentCategory)?.label || formData.investmentCategory || '--' }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.basicInfo.projectNature')">
{{ projectNatureOptions.find(item => item.value === formData.projectNature)?.label || formData.projectNature || '--' }}
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.basicInfo.projectManagerName')">
{{ formData.projectManagerName || '--' }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.basicInfo.contactNumber')">
{{ formData.contactNumber || '--' }}
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.basicInfo.projectSource')">
{{ projectSourceOptions.find(item => item.value === formData.projectSource)?.label || formData.projectSource || '--' }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.basicInfo.constructionNature')">
{{ constructionNatureOptions.find(item => item.value === formData.constructionNature)?.label || formData.constructionNature || '--' }}
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.basicInfo.keyProject')">
{{ formData.keyProject === 'yes' ? '是' : '否' }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.basicInfo.majorInvestmentProject')">
{{ formData.majorInvestmentProject || '--' }}
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="24">
<el-form-item :label="t('reserveRegistration.basicInfo.withinMainBusiness')">
{{ formData.withinMainBusiness || '--' }}
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.basicInfo.mainBusinessType')">
{{ formData.mainBusinessType || '--' }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.basicInfo.mainBusinessCode')">
{{ formData.mainBusinessCode || '--' }}
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.basicInfo.projectDirection')">
{{ formData.projectDirection || '--' }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.basicInfo.directionSubdivision')">
{{ formData.directionSubdivision || '--' }}
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.basicInfo.strategicEmergingIndustry')">
{{ formData.strategicEmergingIndustry || '--' }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.basicInfo.urbanStrategy')">
{{ formData.urbanStrategy || '--' }}
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.basicInfo.isManufacturing')">
{{ formData.isManufacturing || '--' }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.basicInfo.investmentRegion')">
{{ investmentAreaOptions.find(item => item.value === formData.investmentRegion)?.label || formData.investmentRegion || '--' }}
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.basicInfo.projectAddress')">
{{ formData.projectAddress || '--' }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.basicInfo.projectDetailedAddress')">
{{ formData.projectDetailedAddress || '--' }}
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.basicInfo.isControllingShareholder')">
{{ formData.isControllingShareholder || '--' }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.basicInfo.ourShareholdingRatio')">
{{ formData.ourShareholdingRatio || '--' }}
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.basicInfo.totalInvestmentAmount')">
{{ formData.totalInvestmentAmount || '--' }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.basicInfo.cumulativeInvestmentLastYear')">
{{ formData.cumulativeInvestmentLastYear || '--' }}
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.basicInfo.ourTotalInvestmentAmount')">
{{ formData.ourTotalInvestmentAmount || '--' }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.basicInfo.ourCumulativeInvestmentLastYear')">
{{ formData.ourCumulativeInvestmentLastYear || '--' }}
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="24">
<el-form-item :label="t('reserveRegistration.basicInfo.projectOverview')">
{{ formData.projectDesc || '--' }}
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="24">
<el-form-item :label="t('reserveRegistration.basicInfo.progressDescription')">
{{ formData.progressDesc || '--' }}
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="24">
<el-form-item :label="t('reserveRegistration.basicInfo.projectProposal')">
<div v-for="file of formData.projectProposal" :key="file.url" class="mr-4">
<a :href="`${baseURL}${file.url}`" target="_blank">
<el-button link type="primary">
{{ file.name }}
</el-button>
</a>
</div>
</el-form-item>
</el-col>
</el-row>
<div class="sub-section-title">{{ t('reserveRegistration.investmentEstimate.title') }}</div>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.investmentEstimate.enterpriseSelfFund')">
{{ formData.enterpriseSelfFund || '0' }}
{{ t('reserveRegistration.investmentEstimate.unitWanYuan') }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.investmentEstimate.governmentInvestmentFund')">
{{ formData.governmentInvestmentFund || '0' }}
{{ t('reserveRegistration.investmentEstimate.unitWanYuan') }}
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.investmentEstimate.externalRaisedFund')">
{{ formData.externalRaisedFund || '0' }}
{{ t('reserveRegistration.investmentEstimate.unitWanYuan') }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.investmentEstimate.otherFunds')">
{{ formData.otherFunds || '0' }}
{{ t('reserveRegistration.investmentEstimate.unitWanYuan') }}
</el-form-item>
</el-col>
</el-row>
<div class="sub-section-title">{{ t('reserveRegistration.partnerInfo.title') }}</div>
<el-form-item prop="partnerInfos" label-width="0">
<el-table :data="formData.cooperationUnits" border style="width: 100%;" highlight-current-row>
<el-table-column type="index" :label="t('reserveRegistration.partnerInfo.table.index')" width="60" />
<el-table-column prop="cooperationName" :label="t('reserveRegistration.partnerInfo.table.name')" />
<el-table-column prop="cooperationNature" :label="t('reserveRegistration.partnerInfo.table.nature')" />
<el-table-column prop="cooperationController" :label="t('reserveRegistration.partnerInfo.table.controller')" />
<el-table-column readonly prop="shareholdingRatio" :label="t('reserveRegistration.partnerInfo.table.share')" width="100">
<template #default="scope">
{{ scope.row.shareholdingRatio }}%
</template>
</el-table-column>
</el-table>
</el-form-item>
<div class="sub-section-title">{{ t('reserveRegistration.decisionInfo.title') }}</div>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.decisionInfo.decisionType')">
{{ formData.decisionType || '--' }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.decisionInfo.isCompleteEstablishmentProcedures')">
{{ formData.isCompleteEstablishmentProcedures === 'yes' ? '是' : '否' }}
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.decisionInfo.establishmentDocumentNumber')">
{{ formData.establishmentDocumentNumber || '--' }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.decisionInfo.establishmentDocumentInfo')">
{{ formData.establishmentDocumentInfo || '--' }}
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.decisionInfo.isCompleteDecisionProcedures')">
{{ formData.isCompleteDecisionProcedures === 'yes' ? '是' : '否' }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.decisionInfo.decisionProgramDocumentNumber')">
{{ formData.decisionProgramDocumentNumber || '--' }}
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="24">
<el-form-item :label="t('reserveRegistration.decisionInfo.decisionDocumentInfo')">
{{ formData.decisionDocumentInfo || '--' }}
</el-form-item>
</el-col>
</el-row>
<!-- <div class="sub-section-title">{{ t('reserveRegistration.reviewOpinions.title') }}</div>
<el-form-item :label="t('reserveRegistration.reviewOpinions.submitUnitOpinion')">
{{ formData.reviewOpinions.submitUnitOpinion || '--' }}
</el-form-item>
<el-form-item :label="t('reserveRegistration.reviewOpinions.groupInvestmentDeptOpinion')">
{{ formData.reviewOpinions.groupInvestmentDeptOpinion || '--' }}
</el-form-item>
<el-form-item :label="t('reserveRegistration.reviewOpinions.submitUnitLeadershipOpinion')">
{{ formData.reviewOpinions.submitUnitLeadershipOpinion || '--' }}
</el-form-item>
<el-form-item :label="t('reserveRegistration.reviewOpinions.submitUnitMainLeadershipOpinion')">
{{ formData.reviewOpinions.submitUnitMainLeadershipOpinion || '--' }}
</el-form-item> -->
</el-form>
</div>
</template>
<script lang="ts" setup>
import { reactive, watch, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import {
projectNatureOptions,
investmentCategoryOptions,
projectSourceOptions,
constructionNatureOptions,
investmentAreaOptions
} from '/@/hooks/enums'
import type { ExternalCooperationUnitItemT } from '/@/api/investment/cooperationUnit'
const { t } = useI18n();
export interface ProjectBasicInfoFormData {
applicant: string;
applicationUnit: string;
projectName: string;
projectMainUnit: string;
projectStartDate: string;
investmentCategory: string;
projectManagerName: string;
projectSource: string;
keyProject: string;
withinMainBusiness: string;
mainBusinessType: string;
projectDirection: string;
strategicEmergingIndustry: string;
isManufacturing: string;
projectAddress: string;
isControllingShareholder: string;
totalInvestmentAmount: string;
ourTotalInvestmentAmount: string;
projectDesc: string;
progressDesc: string;
projectProposal: any[];
applicationDate: string;
projectOwnerUnit: string;
projectEndDate: string;
projectNature: string;
contactNumber: string;
constructionNature: string;
majorInvestmentProject: string;
mainBusinessCode: string;
directionSubdivision: string;
urbanStrategy: string;
investmentRegion: string;
projectDetailedAddress: string;
ourShareholdingRatio: string;
cumulativeInvestmentLastYear: string;
ourCumulativeInvestmentLastYear: string;
enterpriseSelfFund: string;
externalRaisedFund: string;
governmentInvestmentFund: string;
otherFunds: string;
partnerInfos: PartnerInfo[];
decisionType: string;
isCompleteEstablishmentProcedures: string;
establishmentDocumentNumber: string;
establishmentDocumentInfo: string;
decisionProgramDocumentNumber: string;
decisionDocumentInfo: string;
isCompleteDecisionProcedures: string;
reviewOpinions: ReviewOpinions;
processInstanceId: string;
cooperationUnits?: ExternalCooperationUnitItemT[]
}
export interface PartnerInfo {
id?: string | number | null;
name: string;
nature: string;
controller: string;
share: string;
}
export interface ReviewOpinions {
submitUnitOpinion: string;
groupInvestmentDeptOpinion: string;
submitUnitLeadershipOpinion: string;
submitUnitMainLeadershipOpinion: string;
}
const props = defineProps<{
modelValue?: ProjectBasicInfoFormData;
}>();
const defaultPartnerRow: PartnerInfo = {
id: '',
name: '',
nature: '',
controller: '',
share: '',
};
const defaultFormData: ProjectBasicInfoFormData = {
applicant: '',
applicationUnit: '',
projectName: '',
projectMainUnit: '',
projectStartDate: '',
investmentCategory: '',
projectManagerName: '',
projectSource: '',
keyProject: '',
withinMainBusiness: '',
mainBusinessType: '',
projectDirection: '',
strategicEmergingIndustry: '',
isManufacturing: '',
projectAddress: '',
isControllingShareholder: '',
totalInvestmentAmount: '',
ourTotalInvestmentAmount: '',
projectDesc: '',
progressDesc: '',
projectProposal: [],
applicationDate: '',
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: '',
processInstanceId: '',
reviewOpinions: {
submitUnitOpinion: '',
groupInvestmentDeptOpinion: '',
submitUnitLeadershipOpinion: '',
submitUnitMainLeadershipOpinion: '',
},
};
const formData = reactive<ProjectBasicInfoFormData>({ ...defaultFormData });
watch(
() => props.modelValue,
newVal => {
Object.assign(
formData,
newVal
);
},
{ immediate: true, deep: true },
);
</script>
<style scoped>
.project-basic-info-form {
background: #fff;
border-radius: 4px;
padding: 20px;
}
.form-main-title {
font-size: 18px;
font-weight: 600;
text-align: center;
margin-bottom: 20px;
color: var(--el-text-color-primary);
}
.form-section-title {
font-size: 16px;
font-weight: 600;
color: var(--el-text-color-primary);
margin-bottom: 20px;
padding-left: 10px;
border-left: 4px solid #409eff;
}
.project-form {
width: 100%;
}
.form-row {
margin-bottom: 16px;
}
.form-row:last-of-type {
margin-bottom: 0;
}
:deep(.el-form-item__label) {
font-weight: 500;
}
:deep(.is-required .el-form-item__label) {
font-weight: 500;
/* color: var(--el-color-danger); */
}
:deep(.is-required .el-form-item__label)::before {
content: '*';
/* color: var(--el-color-danger); */
margin-right: 4px;
}
.sub-section-title {
font-size: 15px;
font-weight: 600;
color: var(--el-text-color-primary);
margin: 24px 0 12px;
padding-left: 10px;
border-left: 4px solid #409eff;
}
.partner-toolbar {
display: flex;
gap: 12px;
margin-bottom: 12px;
}
.partner-name-cell {
display: flex;
align-items: center;
gap: 8px;
}
.partner-name-cell :deep(.el-input) {
flex: 1;
}
:deep(.el-table th .cell) {
font-weight: 500;
}
</style>

View File

@@ -0,0 +1,137 @@
<template>
<div class="project-exit-feedback-form">
<div class="form-heading">{{ t('projectExitFeedback.form.title') }}</div>
<div class="feedback-table">
<div class="table-row">
<div class="table-cell label required">{{ t('projectExitFeedback.form.projectName') }}</div>
<div class="table-cell value project-name-cell" >
{{ formData.projectName }}
</div>
</div>
<div class="table-row">
<div class="table-cell label">{{ t('projectExitFeedback.form.exitTime') }}</div>
<div class="table-cell value">
{{ formData.exitTime }}
</div>
</div>
<div class="table-row">
<div class="table-cell label">{{ t('projectExitFeedback.form.exitExecutor') }}</div>
<div class="table-cell value">
{{ formData.exitExecutor }}
</div>
</div>
<div class="table-row">
<div class="table-cell label">{{ t('projectExitFeedback.form.exitDescription') }}</div>
<div class="table-cell value">
{{ formData.exitRemark }}
</div>
</div>
<div class="table-row">
<div class="table-cell label">{{ t('projectExitFeedback.form.exitFiles') }}</div>
<div class="table-cell value">
<UploadFile :modelValue="formData.exitAttachment ? JSON.parse(formData.exitAttachment as string) : []" :fileSize="20" disabled type="simple" :limit="10" :isShowTip="false" />
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { useI18n } from 'vue-i18n';
import { ProjectExitFeedback } from '/@/views/invMid/projectExitFeedback/interface/type';
const { t } = useI18n();
const props = defineProps<{
modelValue?: ProjectExitFeedback;
}>();
const formData = reactive<ProjectExitFeedback>({ ...props.modelValue });
watch(
() => props.modelValue,
(newVal) => {
if (newVal) {
Object.assign(formData, newVal);
}
},
{ immediate: true, deep: true }
);
</script>
<style scoped>
.project-exit-feedback-form {
background-color: #fff;
border-radius: 4px;
border: 1px solid var(--el-border-color-lighter);
padding: 24px;
}
.form-heading {
text-align: center;
font-size: 20px;
font-weight: 600;
color: var(--el-text-color-primary);
margin-bottom: 16px;
}
.feedback-table {
border: 1px solid var(--el-border-color);
}
.table-row {
display: flex;
border-top: 1px solid var(--el-border-color);
}
.table-row:first-of-type {
border-top: none;
}
.table-cell {
border-right: 1px solid var(--el-border-color);
padding: 12px;
display: flex;
align-items: center;
}
.table-cell:last-of-type {
border-right: none;
}
.table-cell.label {
width: 160px;
background-color: var(--el-fill-color-light);
font-weight: 500;
}
.table-cell.label.required::after {
content: '*';
color: var(--el-color-danger);
margin-left: 4px;
}
.table-cell.value {
flex: 1;
}
.interactive-icon {
color: var(--el-color-primary);
}
.feedback-table :deep(.el-input),
.feedback-table :deep(.el-select),
.feedback-table :deep(.el-date-editor),
.feedback-table :deep(.el-textarea) {
width: 100%;
}
.options {
width: 20px;
height: 20px;
cursor: pointer;
border: 1px solid var(--el-border-color);
border-radius: 50%;
}
.active {
background-color: var(--el-color-primary);
color: white;
}
</style>

View File

@@ -0,0 +1,290 @@
<template>
<div class="project-exit-feedback-form" :model="formData" :rules="rules" ref="formRef">
<div class="form-heading">{{ t('projectExitFeedback.form.title') }}</div>
<div class="feedback-table">
<div class="table-row">
<div class="table-cell label required">{{ t('projectExitFeedback.form.projectName') }}</div>
<div class="table-cell value project-name-cell" >
<el-input v-model="formData.projectName" :placeholder="t('projectExitFeedback.placeholder.projectName')" readonly>
<template #append>
<el-icon class="cursor-pointer interactive-icon" @click="handleSelectProject">
<FolderOpened />
</el-icon>
</template>
</el-input>
</div>
</div>
<div class="table-row">
<div class="table-cell label">{{ t('projectExitFeedback.form.exitTime') }}</div>
<div class="table-cell value">
<el-date-picker
v-model="formData.exitTime"
type="date"
value-format="YYYY-MM-DD"
:placeholder="t('projectExitFeedback.placeholder.select')"
style="width: 100%"
/>
</div>
</div>
<div class="table-row">
<div class="table-cell label">{{ t('projectExitFeedback.form.exitExecutor') }}</div>
<div class="table-cell value">
<el-input v-model="formData.exitExecutor" :placeholder="t('projectExitFeedback.placeholder.projectName')" readonly>
<template #append>
<el-icon class="cursor-pointer interactive-icon" @click="handleSelectUser">
<FolderOpened />
</el-icon>
</template>
</el-input>
</div>
</div>
<div class="table-row">
<div class="table-cell label">{{ t('projectExitFeedback.form.exitDescription') }}</div>
<div class="table-cell value">
<el-input v-model="formData.exitRemark" type="textarea" :rows="3" :placeholder="t('projectExitFeedback.placeholder.input')" />
</div>
</div>
<div class="table-row">
<div class="table-cell label">{{ t('projectExitFeedback.form.exitFiles') }}</div>
<div class="table-cell value">
<el-input :placeholder="t('projectExitFeedback.placeholder.selectAttachment')" readonly>
<template #append>
<UploadFile :modelValue="formData.exitAttachment" @change="handleChange" :fileSize="20" type="simple" :limit="10" :isShowTip="false" />
</template>
</el-input>
</div>
</div>
</div>
</div>
<el-dialog width="80%" title="关联列表" v-model="dialogShow" :close-on-click-modal="false">
<template #header> </template>
<el-table border :data="tableData" height="50vh" @current-change="handleSelectionChange">
<el-table-column label="选择" width="80">
<template #default="scope">
<div class="options" :class="active === scope.$index ? 'active' : ''"></div>
</template>
</el-table-column>
<el-table-column type="index" :label="t('projectExitPlanLibrary.table.index')" width="60" />
<el-table-column prop="projectName" :label="t('projectExitPlanLibrary.table.projectName')" min-width="180" />
<el-table-column prop="exitRecommendation" :label="t('projectExitPlanLibrary.table.exitSuggestion')" min-width="160" />
<el-table-column prop="exitMethod" :label="t('projectExitPlanLibrary.table.exitMethod')" min-width="140" />
<el-table-column prop="executionTask" :label="t('projectExitPlanLibrary.table.executionTask')" min-width="160" />
<el-table-column prop="taskDescription" :label="t('projectExitPlanLibrary.table.taskDescription')" min-width="200" show-overflow-tooltip />
<el-table-column prop="executor" :label="t('projectExitPlanLibrary.table.executor')" min-width="120" />
<el-table-column prop="taskStartDate" :label="t('projectExitPlanLibrary.table.taskStartTime')" min-width="140" />
<el-table-column prop="taskEndDate" :label="t('projectExitPlanLibrary.table.taskEndTime')" min-width="140" />
<el-table-column prop="applicationDept" :label="t('projectExitPlanLibrary.table.applyDepartment')" min-width="160" />
<el-table-column prop="reviewNotes" :label="t('projectExitPlanLibrary.table.submitMatter')" min-width="160" />
</el-table>
<div class="mt15 flex justify-end pagination-wrapper">
<el-pagination
background
layout="sizes, prev, pager, next, jumper, total"
:total="total"
:page-sizes="[10, 20, 50, 100]"
v-model:current-page="queryForm.page"
v-model:page-size="queryForm.size"
@size-change="handlePageSizeChange"
@current-change="handlePageChange"
/>
</div>
<template #footer>
<el-button type="primary" @click="confirmBtn">确定</el-button>
<el-button>取消</el-button>
</template>
</el-dialog>
<user-select :visible="userDialog" @ok="confirmUserBtn"/>
</template>
<script setup lang="ts">
import { reactive, ref, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import { FolderOpened } from '@element-plus/icons-vue';
import { ProjectExitFeedback } from '/@/views/invMid/projectExitFeedback/interface/type';
import userSelect from "/@/components/UserSelect/index.vue"
import { FormRules } from 'element-plus';
import { paramsDataProjectExitPlan, projectExitPlanItem } from '/@/views/invMid/projectExitPlan/interface/type';
import { getProjectExitPlanPage } from '/@/api/investment/projectExitPlan';
const { t } = useI18n();
const formRef = ref<HTMLFormElement | null>();
const rules = ref<FormRules<ProjectExitFeedback>>({});
const props = defineProps<{
modelValue?: ProjectExitFeedback;
}>();
const active = ref<number>(-1);
const queryForm = ref<paramsDataProjectExitPlan>({
projectName: '',
reviewNotes: '',
applicationDept: '',
page: 1,
size: 10,
});
const userDialog = ref(false)
const emit = defineEmits<{
(e: 'update:modelValue', value: ProjectExitFeedback): void;
}>();
const projectName = ref('');
const dialogShow = ref(false);
const formData = reactive<ProjectExitFeedback>({ ...props.modelValue });
const handleSelectProject = () => {
dialogShow.value = true;
};
const handlePageSizeChange = (size:number) =>{
queryForm.value.size = size;
getDataList();
}
const handlePageChange = (page:number) =>{
queryForm.value.page = page;
getDataList();
}
const tableData = ref<projectExitPlanItem[]>([]);
watch(()=>formData, () => {
emit('update:modelValue', { ...formData })
}, { deep: true,immediate: true});
watch(
() => props.modelValue,
(newVal) => {
if (newVal) {
Object.assign(formData, newVal);
}
},
{ immediate: true, deep: true }
);
interface ProjectExitPlanLibraryItem {
id: number;
projectName: string;
exitSuggestion: string;
exitMethod: string;
executionTask: string;
taskDescription: string;
executor: string;
taskStartTime: string;
taskEndTime: string;
applyDepartment: string;
submitMatter: string;
projectId?: number;
}
const total = ref<number>(0);
const selectedRows = ref<ProjectExitPlanLibraryItem>();
const handleSelectionChange = (rows: ProjectExitPlanLibraryItem) => {
selectedRows.value = rows;
projectName.value = selectedRows.value?.projectName;
active.value = tableData.value.findIndex((item) => item.id === rows.id);
};
const confirmBtn = () => {
emit('update:modelValue', {
...formData,
projectName:projectName.value,
projectId: selectedRows.value?.projectId,
});
dialogShow.value = false;
};
const getDataList = () => {
getProjectExitPlanPage(queryForm.value).then((res) => {
tableData.value = res.data.records;
total.value = res.data.total;
});
};
getDataList();
const handleSelectUser = () =>{
userDialog.value = true
}
const confirmUserBtn = (value:any) =>{
formData.exitExecutor = value?.name
}
const handleChange = (_:any, data:any[]) => {
if (!data || Object.prototype.toString.call(data) !== '[object Array]' || data.length === 0){
formData.exitAttachment = [];
return;
}
formData.exitAttachment = data.map((item:any) => {
return {
name: item.name,
url: item.url
}
})
}
</script>
<style scoped>
.project-exit-feedback-form {
background-color: #fff;
border-radius: 4px;
border: 1px solid var(--el-border-color-lighter);
padding: 24px;
}
.form-heading {
text-align: center;
font-size: 20px;
font-weight: 600;
color: var(--el-text-color-primary);
margin-bottom: 16px;
}
.feedback-table {
border: 1px solid var(--el-border-color);
}
.table-row {
display: flex;
border-top: 1px solid var(--el-border-color);
}
.table-row:first-of-type {
border-top: none;
}
.table-cell {
border-right: 1px solid var(--el-border-color);
padding: 12px;
display: flex;
align-items: center;
}
.table-cell:last-of-type {
border-right: none;
}
.table-cell.label {
width: 160px;
background-color: var(--el-fill-color-light);
font-weight: 500;
}
.table-cell.label.required::after {
content: '*';
color: var(--el-color-danger);
margin-left: 4px;
}
.table-cell.value {
flex: 1;
}
.interactive-icon {
color: var(--el-color-primary);
}
.feedback-table :deep(.el-input),
.feedback-table :deep(.el-select),
.feedback-table :deep(.el-date-editor),
.feedback-table :deep(.el-textarea) {
width: 100%;
}
.options {
width: 20px;
height: 20px;
cursor: pointer;
border: 1px solid var(--el-border-color);
border-radius: 50%;
}
.active {
background-color: var(--el-color-primary);
color: white;
}
</style>

View File

@@ -0,0 +1,428 @@
<template>
<div class="project-exit-plan-form">
<div class="form-heading">
<div class="form-title">{{ t('projectExitPlan.form.title') }}</div>
<div class="form-meta">
<div class="meta-item">
<span>{{ t('projectExitPlan.form.applyDepartmentLabel') }}</span>
<el-input v-model="formData.applicationDept" size="small" :placeholder="t('projectExitPlan.placeholder.input')" />
</div>
<div class="meta-item">
<span>{{ t('projectExitPlan.form.applyDateLabel') }}</span>
<span>{{new Date().toLocaleDateString('zh-CN')}}</span>
</div>
</div>
</div>
<el-form :model="formData" :rules="rules" ref="useForm" class="exit-plan-table">
<el-form-item class="table-row" prop="projectName" required>
<template #label>
<div class="table-cell label">{{ t('projectExitPlan.form.projectName') }}</div>
</template>
<div class="table-cell value project-name-cell">
<el-input v-model="formData.projectName" :placeholder="t('projectExitPlan.form.projectNamePlaceholder')" readonly>
<template #suffix>
<el-icon class="cursor-pointer interactive-icon" @click="handleSelectProject">
<FolderOpened />
</el-icon>
</template>
</el-input>
</div>
<div class="table-cell action">
<el-button text circle :icon="OfficeBuilding" class="action-btn" @click="handleSelectProject" />
</div>
</el-form-item>
<el-form-item class="table-row" prop="exitRecommendation" required>
<template #label>
<div class="table-cell label">{{ t('projectExitPlan.form.exitSuggestion') }}</div>
</template>
<div class="table-cell value">
<el-input v-model="formData.exitRecommendation" :placeholder="t('projectExitPlan.placeholder.input')" />
</div>
</el-form-item>
<el-form-item class="table-row">
<template #label>
<div class="table-cell label">{{ t('projectExitPlan.form.exitMethod') }}</div>
</template>
<div class="table-cell value">
<el-input v-model="formData.exitMethod" :placeholder="t('projectExitPlan.placeholder.input')" />
</div>
</el-form-item>
<el-form-item class="table-row">
<template #label>
<div class="table-cell label">{{ t('projectExitPlan.form.executionTask') }}</div>
</template>
<div class="table-cell value">
<el-input v-model="formData.executionTask" :placeholder="t('projectExitPlan.placeholder.input')" />
</div>
</el-form-item>
<el-form-item class="table-row">
<template #label>
<div class="table-cell label">{{ t('projectExitPlan.form.taskDescription') }}</div>
</template>
<div class="table-cell value">
<el-input v-model="formData.taskDescription" type="textarea" :rows="1" :placeholder="t('projectExitPlan.placeholder.input')" />
</div>
</el-form-item>
<el-form-item class="table-row">
<template #label>
<div class="table-cell label">{{ t('projectExitPlan.form.executor') }}</div>
</template>
<div class="table-cell value">
<el-select v-model="formData.executor" clearable :placeholder="t('projectExitPlan.form.executorPlaceholder')">
<el-option :label="t('projectExitPlan.form.executorPlaceholder')" value="executor-placeholder" />
</el-select>
</div>
</el-form-item>
<el-form-item class="table-row two-columns">
<template #label>
<div class="table-cell label">{{ t('projectExitPlan.form.taskStartTime') }}</div>
</template>
<div class="table-cell value">
<el-date-picker
v-model="formData.taskStartDate"
type="date"
value-format="YYYY-MM-DD"
:placeholder="t('projectExitPlan.placeholder.select')"
style="width: 100%"
/>
</div>
<div class="table-cell label">{{ t('projectExitPlan.form.taskEndTime') }}</div>
<div class="table-cell value">
<el-date-picker
v-model="formData.taskEndDate"
type="date"
value-format="YYYY-MM-DD"
:placeholder="t('projectExitPlan.placeholder.select')"
style="width: 100%"
/>
</div>
</el-form-item>
</el-form>
<el-dialog width="80%" title="关联列表" v-model="visible" :close-on-click-modal="false">
<template #header>
<el-form inline>
<el-form-item label="项目名称">
<el-input v-model="queryForm.projectName" placeholder="请输入项目名称" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="getListSearch">筛选</el-button>
<el-button @click="handleReset">重置</el-button>
</el-form-item>
</el-form>
</template>
<el-table :data="tableData" style="width: 100%" height="50vh" highlight-current-row border @current-change="handleSelectionChange">
<el-table-column label="选择" width="80">
<template #default="scope">
<div class="options" :class="active === scope.$index ? 'active' : ''"></div>
</template>
</el-table-column>
<el-table-column prop="projectName" :label="t('projectLibrary.table.projectName')" min-width="200" />
<el-table-column prop="projectStartTime" :label="t('projectLibrary.table.projectImplementationStart')" min-width="160" />
<el-table-column prop="projectNature" :label="t('projectLibrary.table.projectNature')" min-width="140">
<template #default="{ row }">
{{ projectNatureOptions.find((item: Enums) => item.value === row.projectNature)?.label }}
</template>
</el-table-column>
<el-table-column prop="projectOwnerUnit" :label="t('projectLibrary.table.projectOwnerUnit')" min-width="200" />
<el-table-column prop="" label="项目实施单位" />
<el-table-column prop="projectInvestmentDirection" :label="t('projectLibrary.table.projectDirection')" min-width="160" />
<el-table-column prop="mainBusinessTypes" :label="t('planApply.applySection.mainBusinessType')" min-width="160">
<template #default="{ row }">
{{ mainBusinessOptions.find((item: Enums) => item.value === row.mainBusinessTypes)?.label }}
</template>
</el-table-column>
<el-table-column prop="constructionStage" :label="t('projectLibrary.table.constructionStage')" min-width="120" />
<el-table-column prop="investmentCategory" :label="t('projectLibrary.table.investmentCategory')" min-width="140">
<template #default="{ row }">
{{ investmentCategoryOptions.find((item: Enums) => item.value === row.investmentCategory)?.label }}
</template>
</el-table-column>
<el-table-column prop="" label="操作" fixed="right" width="100">
<template #default="{ row }">
<el-button type="primary" link @click="handleDetail(row)">详情</el-button>
</template>
</el-table-column>
</el-table>
<div class="mt15 flex justify-end pagination-wrapper">
<el-pagination
background
layout="sizes, prev, pager, next, jumper, total"
:total="total"
:page-sizes="[10, 20, 50, 100]"
v-model:page-size="queryForm.size"
v-model:current-page="queryForm.page"
@size-change="handlePageSizeChange"
@current-change="handlePageChange"
/>
</div>
<template #footer>
<el-button type="primary" @click="tableSubmit">确定</el-button>
<el-button @click="visible = false">取消</el-button>
</template>
</el-dialog>
<el-dialog v-model="visible2" width="80%" title="项目详情">
<ProjectPlanApplyFormDetails v-model="detailFormData" :isEdit="false" />
</el-dialog>
</div>
</template>
<script setup lang="ts">
import { reactive, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import { FolderOpened, OfficeBuilding } from '@element-plus/icons-vue';
import { investmentProjectsPlanGetById, investmentProjectsPlanPage } from '/@/api/investment/investmentManagement';
import { investmentProjectsPlanList } from '/@/views/invMid/projectLibrary/interface/types';
import { ProjectPlanApplyFormItem } from '/@/components/investment/interface/types';
import { type Enums, investmentCategoryOptions, mainBusinessOptions, projectNatureOptions } from '/@/hooks/enums';
import type { ProjectTask } from '/@/views/invMid/projectExitPlan/interface/type';
import ProjectPlanApplyFormDetails from '/@/components/investment/common/ProjectPlanApplyFormDetails.vue';
import { type FormInstance, FormRules } from 'element-plus';
const { t } = useI18n();
const visible = ref<boolean>(false);
const visible2 = ref<boolean>(false);
const props = defineProps<{
modelValue?: ProjectTask;
rules:FormRules;
}>();
const useForm = ref<FormInstance | undefined>();
const emit = defineEmits<{
(e: 'update:modelValue', value: ProjectTask): void;
}>();
const defaultForm: ProjectTask = {
id: undefined,
projectName: '',
projectId: undefined,
exitRecommendation: '',
executionTask:'',
taskDescription:'',
executor:'',
taskStartDate:new Date().toISOString().substring(0,10),
taskEndDate:new Date().toISOString().substring(0,10),
};
const formData = reactive<ProjectTask>({ ...defaultForm, ...props.modelValue });
const total = ref<number>(0);
const queryForm = ref<investmentProjectsPlanList>({
page: 1,
size: 10,
projectName: '',
});
const tableData = ref<ProjectPlanApplyFormItem[]>([]);
const handleSelectProject = () => {
visible.value = true;
};
const getListOfProjects = async () => {
try {
const res = await investmentProjectsPlanPage(queryForm.value);
total.value = res.data.total as number;
tableData.value = res.data.records;
} catch (error: any) {
console.log(error);
}
};
const handlePageSizeChange = (size: number) => {
queryForm.value.size = size;
getListOfProjects();
};
const handlePageChange = (page: number) => {
queryForm.value.page = page;
getListOfProjects();
};
getListOfProjects();
const getListSearch = () =>{
queryForm.value.page = 1;
getListOfProjects();
}
const handleReset = () =>{
queryForm.value.projectName = '';
}
watch(
formData,
(newVal) => {
console.log(newVal,'formData');
emit('update:modelValue', { ...newVal });
},
{ deep: true }
);
watch(
() => props.modelValue,
(newVal) => {
if (newVal) {
console.log(newVal,'asdas');
Object.assign(formData, newVal);
}
},
{ immediate: true, deep: true }
);
const active = ref<number>(-1);
const selectItem = ref<string>('');
const selectId = ref<number>();
const handleSelectionChange = (val: any) => {
active.value = tableData.value.findIndex((item) => item.id === val.id);
selectItem.value = val.projectName;
selectId.value = val.id;
formData.deptId = val.deptId;
};
const tableSubmit = () => {
visible.value = false;
formData.projectName = selectItem.value;
formData.projectId = selectId.value;
};
const detailFormData = ref<any>({});
const handleDetail = (row: any) => {
visible2.value = true;
investmentProjectsPlanGetById(row.id).then((res) => {
detailFormData.value.entity = res.data;
detailFormData.value.investmentProjects = res.data.projectInvestmentEntities;
});
};
defineExpose({
validateRef: () => {
return useForm.value?.validate();
},
})
</script>
<style scoped>
.project-exit-plan-form {
background-color: #fff;
border: 1px solid var(--el-border-color-lighter);
border-radius: 4px;
padding: 24px;
}
.form-heading {
text-align: center;
margin-bottom: 20px;
}
.form-title {
font-size: 20px;
font-weight: 600;
margin-bottom: 8px;
}
.form-meta {
display: flex;
justify-content: center;
gap: 40px;
flex-wrap: wrap;
}
.meta-item {
display: flex;
align-items: center;
gap: 8px;
}
.meta-item :deep(.el-input),
.meta-item :deep(.el-date-editor) {
width: 180px;
}
.exit-plan-table {
border: 1px solid var(--el-border-color);
border-collapse: collapse;
}
.table-row {
display: flex;
border-top: 1px solid var(--el-border-color);
}
.table-row:first-of-type {
border-top: none;
}
.table-cell {
border-right: 1px solid var(--el-border-color);
padding: 12px;
display: flex;
align-items: center;
}
.table-cell:last-of-type {
border-right: none;
}
.table-cell.label {
width: 180px;
height: 100%;
background-color: var(--el-fill-color-light);
font-weight: 500;
}
.table-cell.label.required::after {
content: '*';
margin-left: 4px;
color: var(--el-color-danger);
}
.table-cell.value {
flex: 1;
}
.table-row {
margin: 0;
}
.table-row.two-columns .table-cell.label {
width: 160px;
}
.table-row.two-columns .table-cell.value {
flex: 1;
}
.project-name-cell {
flex: 1;
}
.table-cell.action {
width: 80px;
justify-content: center;
}
.interactive-icon {
color: var(--el-color-primary);
}
.action-btn {
font-size: 18px;
}
.exit-plan-table :deep(.el-input),
.exit-plan-table :deep(.el-select),
.exit-plan-table :deep(.el-textarea),
.exit-plan-table :deep(.el-date-editor) {
width: 100%;
}
.options {
width: 20px;
height: 20px;
cursor: pointer;
border: 1px solid var(--el-border-color);
border-radius: 50%;
}
.active {
background-color: var(--el-color-primary);
color: white;
}
:deep(.el-form-item--default .el-form-item__label) {
height: 100%;
position: relative;
}
:deep(.el-form-item__label:before) {
left: 4px;
position: absolute;
}
</style>

View File

@@ -0,0 +1,239 @@
<template>
<div class="project-exit-plan-form">
<div class="form-heading">
<div class="form-title">{{ title ? title : t('projectExitPlan.form.title') }}</div>
<div class="form-meta">
<div class="meta-item">
<span>{{ t('projectExitPlan.form.applyDepartmentLabel') }}</span>
<span>{{ formData.applicationDept }}</span>
</div>
<div class="meta-item">
<span>{{ t('projectExitPlan.form.applyDateLabel') }}</span>
<span>{{new Date().toLocaleDateString('zh-CN')}}</span>
</div>
</div>
</div>
<el-form :model="formData" class="exit-plan-table">
<el-form-item class="table-row" prop="projectName" required>
<template #label>
<div class="table-cell label">{{ t('projectExitPlan.form.projectName') }}</div>
</template>
<div class="table-cell value project-name-cell">
<span>{{ formData.projectName }}</span>
</div>
<div class="table-cell action">
</div>
</el-form-item>
<el-form-item class="table-row" prop="exitRecommendation" required>
<template #label>
<div class="table-cell label">{{ t('projectExitPlan.form.exitSuggestion') }}</div>
</template>
<div class="table-cell value">
<span>{{ formData.exitRecommendation }}</span>
</div>
</el-form-item>
<el-form-item class="table-row">
<template #label>
<div class="table-cell label">{{ t('projectExitPlan.form.exitMethod') }}</div>
</template>
<div class="table-cell value">
<span>{{ formData.exitMethod }}</span>
</div>
</el-form-item>
<el-form-item class="table-row">
<template #label>
<div class="table-cell label">{{ t('projectExitPlan.form.executionTask') }}</div>
</template>
<div class="table-cell value">
<span>{{ formData.executionTask }}</span>
</div>
</el-form-item>
<el-form-item class="table-row">
<template #label>
<div class="table-cell label">{{ t('projectExitPlan.form.taskDescription') }}</div>
</template>
<div class="table-cell value">
<span>{{ formData.taskDescription }}</span>
</div>
</el-form-item>
<el-form-item class="table-row">
<template #label>
<div class="table-cell label">{{ t('projectExitPlan.form.executor') }}</div>
</template>
<div class="table-cell value">
<span>{{ formData.executor }}</span>
</div>
</el-form-item>
<el-form-item class="table-row two-columns">
<template #label>
<div class="table-cell label">{{ t('projectExitPlan.form.taskStartTime') }}</div>
</template>
<div class="table-cell value">
<span>{{ formData.taskStartDate }}</span>
</div>
<div class="table-cell label">{{ t('projectExitPlan.form.taskEndTime') }}</div>
<div class="table-cell value">
<span>{{ formData.taskEndDate }}</span>
</div>
</el-form-item>
</el-form>
</div>
</template>
<script setup lang="ts">
import { reactive, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import type { ProjectTask } from '/@/views/invMid/projectExitPlan/interface/type';
const { t } = useI18n();
const props = defineProps<{
modelValue: ProjectTask;
title?: string;
}>();
const emit = defineEmits<{
(e: 'update:modelValue', value: ProjectTask): void;
}>();
const defaultForm: ProjectTask = {
id: undefined,
projectName: '',
projectId: undefined,
exitRecommendation: '',
executionTask:'',
taskDescription:'',
executor:'',
taskStartDate:new Date().toISOString().substring(0,10),
taskEndDate:new Date().toISOString().substring(0,10),
};
const formData = reactive<ProjectTask>({ ...defaultForm, ...props.modelValue });
watch(
formData,
(newVal) => {
emit('update:modelValue', { ...newVal });
},
{ deep: true }
);
watch(
() => props.modelValue,
(newVal) => {
if (newVal) {
Object.assign(formData, newVal);
}
},
{ immediate: true, deep: true }
);
</script>
<style scoped>
.project-exit-plan-form {
background-color: #fff;
border: 1px solid var(--el-border-color-lighter);
border-radius: 4px;
padding: 24px;
}
.form-heading {
text-align: center;
margin-bottom: 20px;
}
.form-title {
font-size: 20px;
font-weight: 600;
margin-bottom: 8px;
}
.form-meta {
display: flex;
justify-content: center;
gap: 40px;
flex-wrap: wrap;
}
.meta-item {
display: flex;
align-items: center;
gap: 8px;
}
.exit-plan-table {
border: 1px solid var(--el-border-color);
border-collapse: collapse;
}
.table-row {
display: flex;
border-top: 1px solid var(--el-border-color);
}
.table-row:first-of-type {
border-top: none;
}
.table-cell {
border-right: 1px solid var(--el-border-color);
padding: 12px;
display: flex;
align-items: center;
}
.table-cell:last-of-type {
border-right: none;
}
.table-cell.label {
width: 180px;
height: 100%;
background-color: var(--el-fill-color-light);
font-weight: 500;
}
.table-cell.label.required::after {
content: '*';
margin-left: 4px;
color: var(--el-color-danger);
}
.table-cell.value {
flex: 1;
}
.table-row {
margin: 0;
}
.table-row.two-columns .table-cell.label {
width: 160px;
}
.table-row.two-columns .table-cell.value {
flex: 1;
}
.project-name-cell {
flex: 1;
}
.table-cell.action {
width: 80px;
justify-content: center;
}
:deep(.el-form-item--default .el-form-item__label) {
height: 100%;
position: relative;
}
:deep(.el-form-item__label:before) {
left: 4px;
position: absolute;
}
</style>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,710 @@
<template>
<div class="project-plan-apply-form border-r border-[#e5e7eb]">
<FlowFormView :process-instance-id="processInstanceId"/>
<div style="display: flex;justify-content: space-between;align-items: center">
<div class="form-section-title">
{{ t('planApply.applySection.title') }}
</div>
<div class="page-title">{{ title ? title : '' }}</div>
<div class="page-unit">
{{ t('planApply.detail.unitLabel') }}
</div>
</div>
<el-form :model="formData" label-width="165px" class="plan-form" :rules="rules" ref="useForm">
<el-row :gutter="20" class="form-row">
<el-col :span="24">
<el-form-item :label="t('planApply.applySection.projectName')" required prop="entity.projectName">
<template #label>
<span style="color: var(--el-text-color-regular)">{{t('planApply.applySection.projectName')}}</span>
</template>
<span>{{formData.entity.projectName}}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('planApply.applySection.groupName')" required prop="entity.groupCompany">
<template #label>
<span style="color: var(--el-text-color-regular)">{{t('planApply.applySection.groupName')}}</span>
</template>
<span>{{formData.entity.groupCompany}}</span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('planApply.applySection.projectNature')">
<span>{{projectNatureOptions.find((item:Enums) => item.value === formData.entity.projectNature)?.label}}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('planApply.applySection.projectMainUnit')" required prop="entity.projectMainEntity">
<span>{{formData.entity.projectMainEntity}}</span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.basicInfo.projectOwnerUnit')">
<span>{{formData.entity.projectOwnerUnit}}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('planApply.applySection.investmentCategory')" required prop="entity.investmentCategory">
<template #label>
<span style="color: var(--el-text-color-regular)">{{t('planApply.applySection.investmentCategory')}}</span>
</template>
<span>{{investmentCategoryOptions.find((item:Enums) => item.value === formData.entity.investmentCategory)?.label}}</span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('planApply.applySection.investmentType')" required prop="entity.investmentArea">
<template #label>
<span style="color: var(--el-text-color-regular)">{{t('planApply.applySection.investmentType')}}</span>
</template>
<span>{{investmentAreaOptions.find((item:Enums) => item.value ===formData.entity.investmentArea)?.label}}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('planApply.applySection.projectAddress')" required prop="entity.projectAddress">
<template #label>
<span style="color: var(--el-text-color-regular)">{{t('planApply.applySection.projectAddress')}}</span>
</template>
<span>{{formData.entity.projectAddress}}</span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('planApply.applySection.projectDetailAddress')" required prop="entity.projectAddressDetail">
<template #label>
<span style="color: var(--el-text-color-regular)">{{t('planApply.applySection.projectDetailAddress')}}</span>
</template>
<span>{{formData.entity.projectAddressDetail}}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.basicInfo.projectDirection')" required prop="entity.projectInvestmentDirection">
<span>{{formData.entity.projectInvestmentDirection}}</span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.basicInfo.directionSubdivision')" required prop="entity.investmentDirectionSegmentation">
<template #label>
<span style="color: var(--el-text-color-regular)">{{t('reserveRegistration.basicInfo.directionSubdivision')}}</span>
</template>
<span>{{projectDirectionDetailsOptions.find((item:Enums) => item.value ===formData.entity.investmentDirectionSegmentation)?.label}}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.basicInfo.projectSource')" required prop="entity.projectSource">
<template #label>
<span style="color: var(--el-text-color-regular)">{{t('reserveRegistration.basicInfo.projectSource')}}</span>
</template>
<span>{{projectSourceOptions.find((item:Enums) => item.value === formData.entity.projectSource)?.label}}</span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('planApply.applySection.constructionNature')" required prop="entity.constructionNature">
<template #label>
<span style="color: var(--el-text-color-regular)">{{t('planApply.applySection.constructionNature')}}</span>
</template>
<span>{{constructionNatureOptions.find((item:Enums) => item.value === formData.entity.constructionNature)?.label}}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.basicInfo.majorInvestmentProject')" required prop="entity.majorInvestmentProjects">
<span>{{formData.entity.majorInvestmentProjects}}</span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('planApply.applySection.keyProject')" required prop="entity.keyProject">
<span>{{projectImportantOptions.find((item:Enums) => item.value === formData.entity.keyProject)?.label}}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span=" 12">
<el-form-item :label="t('planApply.applySection.isWithinMainBusiness')" required prop="entity.isMainBusiness">
<span>{{formData.entity.isMainBusiness == t('planApply.common.yes') ? t('planApply.common.yes') : t('planApply.common.no')}}</span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('planApply.applySection.mainBusinessType')" :required="formData.entity.isMainBusiness === t('planApply.common.yes')" prop="entity.mainBusinessTypes">
<span>{{mainBusinessOptions.find((item:Enums) => item.value === formData.entity.mainBusinessTypes)?.label}}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.basicInfo.mainBusinessCode')" required prop="entity.mainBusinessCode">
<span>{{formData.entity.mainBusinessTypes}}</span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('planApply.applySection.isManufacturing')" required prop="entity.isManufacturingIndustry">
<span>{{formData.entity.isManufacturingIndustry == t('planApply.common.yes') ? t('planApply.common.yes') : t('planApply.common.no')}}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('reserveRegistration.basicInfo.strategicEmergingIndustry')" required prop="entity.isStrategicEmergingIndustries">
<span>{{strategicIndustryOptions.find((item:Enums) => item.value === formData.entity.isStrategicEmergingIndustries)?.label}}</span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('planApply.applySection.cityStrategy')" required prop="entity.urbanStrategy">
<span>{{cityStrategyOptions.find((item:Enums) => item.value === formData.entity.urbanStrategy)?.label}}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('planApply.applySection.projectImplementationStart')" required prop="entity.projectStartTime">
<span>{{formData.entity.projectStartTime}}</span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('planApply.applySection.projectImplementationEnd')" required prop="entity.projectEndTime">
<span>{{formData.entity.projectEndTime}}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="plan-investment-block">
<el-col :span="12">
<div class="plan-investment-panel left-panel">
<div class="panel-title">{{ t('planApply.planInvestment.currentYearTotalTitle') }}</div>
<div style="flex: 1;">
<el-form-item style="height: 82px;" :label="t('planApply.planInvestment.planYear')">
<span>{{formData.entity.planInvestmentYear}}</span>
</el-form-item>
<el-form-item style="height: 82px;" :label="t('planApply.planInvestment.plannedImageQuota')"
required prop="entity.planImageQuota">
<span>{{formData.entity.planImageQuota}}{{ t('planApply.investmentEstimate.unitSuffix') }}</span>
</el-form-item>
<el-form-item style="height: 82px;" :label="t('planApply.planInvestment.annualPlanPayment')"
required prop="entity.planPaymentLimit">
<span>{{formData.entity.planPaymentLimit}}{{ t('planApply.investmentEstimate.unitSuffix') }}</span>
</el-form-item>
</div>
</div>
</el-col>
<el-col :span="12">
<div class="plan-investment-panel right-panel">
<div class="panel-title">{{ t('planApply.planInvestment.currentYearFundingTitle') }}</div>
<div style="flex: 1;">
<el-form-item :label="t('planApply.investmentEstimate.capitalFunding')" required prop="entity.ownedFunds">
<span>{{formData.entity.ownedFunds}}{{ t('planApply.investmentEstimate.unitSuffix') }}</span>
</el-form-item>
<el-form-item :label="t('planApply.investmentEstimate.financialFunding')" required prop="entity.financialFunds">
<span>{{formData.entity.financialFunds}}{{ t('planApply.investmentEstimate.unitSuffix') }}</span>
</el-form-item>
<el-form-item :label="t('planApply.investmentEstimate.externalRaisedFunds')" required prop="entity.externalRaisedCapital">
<span>{{formData.entity.externalRaisedCapital}}{{ t('planApply.investmentEstimate.unitSuffix') }}</span>
</el-form-item>
<el-form-item :label="t('planApply.investmentEstimate.otherFunding')" required prop="entity.otherFunds">
<span>{{formData.entity.otherFunds}}{{ t('planApply.investmentEstimate.unitSuffix') }}</span>
</el-form-item>
<el-form-item :label="t('planApply.investmentEstimate.financialFundingDescription')">
<span>{{formData.entity.governmentFundSourceDesc}}</span>
</el-form-item>
<el-form-item :label="t('planApply.investmentEstimate.otherFundingDescription')">
<span>{{formData.entity.otherFundSourceDesc}}</span>
</el-form-item>
</div>
</div>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="24">
<el-form-item :label="t('planApply.applySection.projectOverview')" required prop="entity.projectDesc">
<span>{{formData.entity.projectDesc}}</span>
</el-form-item>
</el-col>
</el-row>
<el-row class="form-row">
<el-col :span="24">
<el-form-item :label="t('planApply.applySection.projectInitialPlan')">
<span>{{formData.entity.projectPreliminaryPlan}}</span>
</el-form-item>
<el-form-item :label="t('planApply.headerForm.attachments')">
<UploadFile :modelValue="formData.entity.projectPreliminaryPlanAttachment" :fileSize="20" type="simple" :limit="10"/>
</el-form-item>
</el-col>
</el-row>
<el-row class="form-row">
<el-col :span="24">
<el-form-item :label="t('planApply.applySection.remark')">
<span>{{formData.entity.remark}}</span>
</el-form-item>
</el-col>
</el-row>
<div class="form-section-title">{{ t('planApply.investmentStatus.title') }}</div>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('planApply.investmentStatus.totalInvestmentAmount')" required prop="entity.projectTotalAmount">
<span>{{formData.entity.projectTotalAmount}}{{t('planApply.investmentEstimate.unitSuffix')}}</span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('planApply.investmentStatus.cumulativeInvestmentLastYear')" required prop="entity.lastYearCompleted">
<span>{{formData.entity.lastYearCompleted}}{{ t('planApply.investmentEstimate.unitSuffix') }}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('planApply.investmentStatus.ourTotalInvestmentAmount')" required prop="entity.ourInvestmentTotalAmount">
<span>{{formData.entity.ourInvestmentTotalAmount}}{{ t('planApply.investmentEstimate.unitSuffix') }}</span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('planApply.investmentStatus.ourCumulativeInvestmentLastYear')" required prop="entity.ourLastYearCompleted">
<span>{{formData.entity.ourLastYearCompleted}}{{ t('planApply.investmentEstimate.unitSuffix') }}</span>
</el-form-item>
</el-col>
</el-row>
<div class="form-section-title">{{ t('planApply.annualInvestmentInfo.title') }}</div>
<div class="table-actions" v-if="isEdit">
<el-button type="primary" @click="handleAddAnnualInvestment">
{{ t('planApply.annualInvestmentInfo.add') }}
</el-button>
<el-button @click="handleCopyAnnualInvestment">
{{ t('planApply.annualInvestmentInfo.copy') }}
</el-button>
<el-button @click="handleRemoveAnnualInvestment">
{{ t('planApply.annualInvestmentInfo.remove') }}
</el-button>
<el-button @click="handleRemoveAllAnnualInvestment">
{{ t('planApply.annualInvestmentInfo.removeAll') }}
</el-button>
</div>
<el-table :data="formData.investmentProjects" border style="width: 100%" class="annual-investment-table">
<el-table-column width="60" align="center">
<template>
<el-radio v-model="selectedAnnualInvestmentIndex" />
</template>
</el-table-column>
<el-table-column :label="t('planApply.annualInvestmentInfo.table.index')" width="60" align="center">
<template #default="{ $index }">
{{ $index + 1 }}
</template>
</el-table-column>
<el-table-column :label="t('planApply.annualInvestmentInfo.table.planYear')" min-width="140">
<template #default="{ row }">
<span>{{row.plannedInvestmentYear}}</span>
</template>
</el-table-column>
<el-table-column :label="t('planApply.annualInvestmentInfo.table.plannedImageQuota')" min-width="160">
<template #default="{ row }">
<span>{{row.plannedImageAmount}}{{ t('planApply.investmentEstimate.unitSuffix') }}</span>
</template>
</el-table-column>
<el-table-column :label="t('planApply.annualInvestmentInfo.table.annualPlanPayment')" min-width="160">
<template #default="{ row }">
<span>{{row.plannedPaymentAmount}}{{ t('planApply.investmentEstimate.unitSuffix') }}</span>
</template>
</el-table-column>
<el-table-column :label="t('planApply.annualInvestmentInfo.table.fundingSources')" align="center">
<el-table-column :label="t('planApply.annualInvestmentInfo.table.capitalFunding')" min-width="140">
<template #default="{ row }">
<span>{{row.selfFunding}}{{ t('planApply.investmentEstimate.unitSuffix') }}</span>
</template>
</el-table-column>
<el-table-column :label="t('planApply.annualInvestmentInfo.table.externalRaisedFunds')"
min-width="150">
<template #default="{ row }">
<span>{{row.fiscalFunding}}{{ t('planApply.investmentEstimate.unitSuffix') }}</span>
</template>
</el-table-column>
<el-table-column :label="t('planApply.annualInvestmentInfo.table.financialFunding')"
min-width="140">
<template #default="{ row }">
<span>{{row.fiscalFunding}}{{ t('planApply.investmentEstimate.unitSuffix') }} </span>
</template>
</el-table-column>
<el-table-column :label="t('planApply.annualInvestmentInfo.table.otherFunding')" min-width="140">
<template #default="{ row }">
<span>{{row.otherFunding}}{{ t('planApply.investmentEstimate.unitSuffix') }} </span>
</template>
</el-table-column>
<el-table-column :label="t('planApply.annualInvestmentInfo.table.financialFundingDescription')"
min-width="200">
<template #default="{ row }">
<span>{{row.fiscalFundingSource}}{{ t('planApply.investmentEstimate.unitSuffix') }}</span>
</template>
</el-table-column>
<el-table-column :label="t('planApply.annualInvestmentInfo.table.otherFundingDescription')"
min-width="200">
<template #default="{ row }">
<span>{{row.otherFundingSource}}{{ t('planApply.investmentEstimate.unitSuffix') }}</span>
</template>
</el-table-column>
</el-table-column>
</el-table>
<div class="form-section-title">{{ t('planApply.decisionInfo.title') }}</div>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('planApply.decisionInfo.decisionType')">
<span>{{formData.entity.decisionType}}</span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('planApply.decisionInfo.isCompleteEstablishmentProcedures')" required prop="entity.isProjectApprovalCompleted">
<span>{{formData.entity.isProjectApprovalCompleted}}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('planApply.decisionInfo.establishmentDocumentNumber')">
<span>{{formData.entity.projectApprovalFileNo}}</span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('planApply.decisionInfo.establishmentDocumentInfo')">
<span>{{formData.entity.projectApprovalFileInfo}}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('planApply.decisionInfo.isCompleteDecisionProcedures')" required prop="entity.isDecisionProcedureCompleted">
<span>{{formData.entity.isDecisionProcedureCompleted}}</span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('planApply.decisionInfo.decisionProgramDocumentNumber')">
<span>{{formData.entity.decisionProcedureFileNo}}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="24">
<el-form-item :label="t('planApply.decisionInfo.decisionDocumentInfo')">
<span>{{formData.entity.decisionFileInfo}}</span>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
</template>
<script lang="ts" setup>
import { ref, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import type { InvestmentProjects,ProjectPlanApplyFormData } from "../interface/types";
import {projectNatureOptions,
investmentAreaOptions,
investmentCategoryOptions,
projectDirectionDetailsOptions,
projectSourceOptions,
constructionNatureOptions,
projectImportantOptions,
mainBusinessOptions,
strategicIndustryOptions,
cityStrategyOptions, Enums
} from "/@/hooks/enums"
import type { FormInstance, FormRules } from 'element-plus';
import FlowFormView from '/@/components/workbench/common/FlowFormView.vue'
const { t } = useI18n();
const useForm = ref<FormInstance | undefined>();
const props = withDefaults(defineProps<{
modelValue?: ProjectPlanApplyFormData;
rules?: FormRules;
isEdit: boolean;
title:string;
processInstanceId: string;
}>(), {
isEdit: true,
title:'',
processInstanceId:''
});
const emit = defineEmits<{
(e: 'update:modelValue', value: ProjectPlanApplyFormData): void;
}>();
const defaultForm: ProjectPlanApplyFormData = {
entity:{
id:null,
projectName: '',
projectNature: '',
groupCompany: '',
projectOwnerUnit: '',
projectMainEntity: '',
projectDepartment: '',
investmentCategory: '',
investmentArea: '',
projectAddress: '',
projectAddressDetail: '',
projectInvestmentDirection: '',
totalInvestment: '',
investmentDirectionSegmentation: '',
projectBackground: '',
constructionNature: '',
constructionStage: '',
keyProject: '',
isMainBusiness: '',
mainBusinessTypes: '',
mainBusinessCode: '',
isManufacturingIndustry: '',
isStuckIndustry: '',
urbanStrategy: '',
projectSource: '',
majorInvestmentProjects: '',
isStrategicEmergingIndustries: '',
projectStartTime: '',
projectEndTime: '',
projectConstructionContent: '',
planInvestmentYear: '',
annualPlanTotal: '',
annualPlanInvestment: '',
planPaymentLimit: '',
plannedImageAmount: '',
ownedFunds: '',
financialFunds: '',
externalFunding: '',
externalRaisedCapital: '',
otherFunds: '',
governmentFundSourceDesc: '',
otherFundSourceDesc: '',
projectTotalAmount: '',
lastYearCompleted: '',
ourInvestmentTotalAmount: '',
ourLastYearCompleted: '',
projectDesc: '',
promotionPlan: '',
projectPreliminaryPlan: '',
projectPreliminaryPlanAttachment: '',
attachments: [],
remark: '',
decisionType: '',
isProjectApprovalCompleted: '',
isDecisionProcedureCompleted: '',
projectApprovalFileNo: '',
projectApprovalFileInfo: '',
decisionProcedureFileNo: '',
decisionFileInfo: '',
submitUnitOpinion: '',
groupInvestmentDeptOpinion: '',
submitUnitLeadershipOpinion: '',
submitUnitMainLeadershipOpinion: '',
planImageQuota:'',
},
investmentProjects: [
{
plannedInvestmentYear: '',
plannedImageAmount: '',
plannedPaymentAmount: '',
selfFunding: '',
externalFunding: '',
fiscalFunding: '',
otherFunding: '',
fiscalFundingSource: '',
otherFundingSource: '',
},
],
};
const formData = ref<ProjectPlanApplyFormData>({ ...defaultForm });
const selectedAnnualInvestmentIndex = ref<number>(formData.value.investmentProjects.length > 0 ? 0 : -1);
const handleAddAnnualInvestment = () => {
const newItem: InvestmentProjects = {
plannedInvestmentYear: '',
plannedImageAmount: '',
plannedPaymentAmount: '',
selfFunding: '',
externalFunding: '',
fiscalFunding: '',
otherFunding: '',
fiscalFundingSource: '',
otherFundingSource: '',
};
formData.value.investmentProjects.push(newItem);
selectedAnnualInvestmentIndex.value = formData.value.investmentProjects.length - 1;
};
const handleCopyAnnualInvestment = () => {
if (selectedAnnualInvestmentIndex.value >= 0 && selectedAnnualInvestmentIndex.value < formData.value.investmentProjects.length) {
const selectedItem = formData.value.investmentProjects[selectedAnnualInvestmentIndex.value];
const copiedItem: InvestmentProjects = { ...selectedItem };
formData.value.investmentProjects.push(copiedItem);
selectedAnnualInvestmentIndex.value = formData.value.investmentProjects.length - 1;
}
};
const handleRemoveAnnualInvestment = () => {
if (selectedAnnualInvestmentIndex.value >= 0 && selectedAnnualInvestmentIndex.value < formData.value.investmentProjects.length) {
formData.value.investmentProjects.splice(selectedAnnualInvestmentIndex.value, 1);
if (selectedAnnualInvestmentIndex.value >= formData.value.investmentProjects.length) {
selectedAnnualInvestmentIndex.value = formData.value.investmentProjects.length - 1;
}
}
};
const handleRemoveAllAnnualInvestment = () => {
formData.value.investmentProjects = [];
selectedAnnualInvestmentIndex.value = -1;
};
watch(
() => props.modelValue,
newVal => {
Object.assign(formData.value, newVal || {});
formData.value.entity.planInvestmentYear = String(newVal?.entity?.planInvestmentYear);
// 如果有数据且没有选中,默认选中第一行
if (formData.value.investmentProjects.length > 0 && selectedAnnualInvestmentIndex.value === -1) {
selectedAnnualInvestmentIndex.value = 0;
}
},
{ immediate: true, deep: true },
);
watch(
()=> formData.value,
() => {
emit('update:modelValue', { ...formData.value });
},
{ deep: true },
);
const validateForm = () => {
return useForm.value?.validate();
}
defineExpose({
validateForm: validateForm
})
</script>
<style scoped>
.page-title-row {
display: flex;
justify-content: center;
align-items: center;
position: relative;
}
.page-title {
font-size: 20px;
font-weight: 600;
}
.page-unit {
font-size: 14px;
color: var(--el-text-color-secondary);
}
.project-plan-apply-form {
background: #fff;
border-radius: 4px;
padding: 20px;
}
.form-section-title {
font-size: 16px;
font-weight: 600;
color: var(--el-text-color-primary);
margin: 24px 0 16px;
padding-left: 10px;
border-left: 4px solid var(--el-color-primary);
}
.plan-form {
width: 100%;
}
/* 表单 label 左对齐 */
.plan-form :deep(.el-form-item__label) {
text-align: left;
justify-content: flex-start;
}
/* 必填字段标签显示为红色 */
/*.plan-form :deep(.el-form-item.is-required .el-form-item__label) {
color: var(--el-color-danger);
}*/
.form-row {
margin-bottom: 16px;
margin-top: 16px;
}
.form-row:last-of-type {
margin-bottom: 0;
}
.sub-section-title {
font-size: 15px;
font-weight: 600;
color: var(--el-text-color-primary);
margin: 24px 0 16px;
}
.plan-investment-panel {
display: flex;
flex-direction: row;
align-items: center
}
.panel-title {
width: 200px;
padding-top: 0;
margin-top: 0;
}
.plan-investment-panel :deep(.el-form-item__label) {
padding-top: 0;
line-height: 32px;
}
.plan-investment-panel :deep(.el-form-item) {
align-items: center;
}
.table-actions {
margin-bottom: 16px;
display: flex;
gap: 12px;
}
.annual-investment-table {
width: 100%;
}
.annual-investment-table :deep(.el-table__body-wrapper) {
overflow-x: auto;
}
</style>

View File

@@ -0,0 +1,529 @@
<template>
<el-row class="page-title-row mb10">
<div class="page-title">{{ t('progressReport.form.title') }}</div>
<div class="page-report-time">{{ t('progressReport.form.reportTime') }}: {{formData.createTime || reportTime }}</div>
<div class="page-unit">{{ t('progressReport.form.unit') }}</div>
</el-row>
<div class="project-progress-report-form">
<div class="form-section-title">{{ t('progressReport.form.sectionTitle') }}</div>
<el-form :model="formData" label-width="200px" class="progress-form" :rules="rules" ref="useForm">
<el-row :gutter="20" class="form-row">
<el-col :span="24">
<el-form-item :label="t('progressReport.form.projectName')" required prop="projectName">
<el-select v-model="formData.projectId"
:placeholder="t('progressReport.form.selectPlaceholder')"
@change="handelSelectChange"
>
<el-option
v-for="item in projectNameData"
:key="item.id"
:label="item.projectName || ''"
:value="item.id"
/>
<template #footer>
<el-pagination
background
layout="sizes, prev, pager, next, jumper, total"
:total="total"
:page-sizes="[10, 20, 50, 100]"
v-model:page-size="queryForm.size"
v-model:current-page="queryForm.page"
@size-change="handlePageSizeChange"
@current-change="handlePageChange"
/>
</template>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('progressReport.form.projectStatus')" required prop="projectStatus">
<el-select v-model="formData.projectStatus"
:placeholder="t('progressReport.form.inputPlaceholder')"
clearable>
<el-option
v-for="item in projectStatusOptions" :key="item.value"
:value="item.value"
:label="item.label"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('progressReport.form.constructionStage')">
<el-select v-model="formData.constructionStage"
:placeholder="t('progressReport.form.selectPlaceholder')" clearable>
<el-option v-for="item in constructionStageOptions" :key="item.value"
:value="item.value"
:label="item.label"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('progressReport.form.projectImplementationUnit')">
<el-input v-model="formData.implementingBody"
:placeholder="t('progressReport.form.inputPlaceholder')" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('progressReport.form.totalInvestmentAmount')" required prop="projectTotalAmount">
<el-input v-model="formData.projectTotalAmount"
:placeholder="t('progressReport.form.inputPlaceholder')">
<template #append>{{ t('progressReport.form.unitSuffix') }}</template>
</el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('progressReport.form.cumulativeInvestmentToMonthEnd')" required prop="cumulativeInvestmentToDate">
<el-input v-model="formData.cumulativeInvestmentToDate"
:placeholder="t('progressReport.form.inputPlaceholder')">
<template #append>{{ t('progressReport.form.unitSuffix') }}</template>
</el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('progressReport.form.completionRate')" required prop="completionRate">
<el-input v-model="formData.completionRate"
:placeholder="t('progressReport.form.completionRatePlaceholder')">
<template #append>%</template>
</el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('progressReport.form.cumulativePaymentToMonthEnd')">
<el-input v-model="formData.cumulativePaymentToDate"
:placeholder="t('progressReport.form.inputPlaceholder')">
<template #append>{{ t('progressReport.form.unitSuffix') }}</template>
</el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('progressReport.form.paymentCompletionRate')">
<el-input v-model="formData.paymentCompletionRate"
:placeholder="t('progressReport.form.inputPlaceholder')">
<template #append>%</template>
</el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="plan-investment-block">
<el-col :span="12">
<div class="plan-investment-panel left-panel">
<div class="panel-title">{{ t('progressReport.form.currentYearImageAmount') }}</div>
<div style="flex: 1;">
<el-form-item style="height: 82px;" :label="t('progressReport.form.reportYear')">
<el-date-picker v-model="formData.annualReport" type="year" value-format="YYYY"
:placeholder="t('progressReport.form.selectYearPlaceholder')" style="width: 100%" />
</el-form-item>
<el-form-item style="height: 82px;"
:label="t('progressReport.form.currentYearPlannedInvestment')" required prop="annualPlannedInvestment">
<el-input v-model="formData.annualPlannedInvestment"
:placeholder="t('progressReport.form.inputPlaceholder')">
<template #append>{{ t('progressReport.form.unitSuffix') }}</template>
</el-input>
</el-form-item>
<el-form-item style="height: 82px;"
:label="t('progressReport.form.enterpriseCumulativeInvestmentToMonthEnd')" required prop="ytdRemainingInvestment">
<el-input v-model="formData.ytdRemainingInvestment"
:placeholder="t('progressReport.form.inputPlaceholder')">
<template #append>{{ t('progressReport.form.unitSuffix') }}</template>
</el-input>
</el-form-item>
<el-form-item style="height: 82px;"
:label="t('progressReport.form.investmentCompletionRate')">
<el-input v-model="formData.investmentCompletionRate"
:placeholder="t('progressReport.form.inputPlaceholder')">
<template #append>%</template>
</el-input>
</el-form-item>
</div>
</div>
</el-col>
<el-col :span="12">
<div class="plan-investment-panel right-panel">
<div class="panel-title">{{ t('progressReport.form.currentYearPlannedAmount') }}</div>
<div style="flex: 1;">
<el-form-item style="height: 82px;" :label="t('progressReport.form.plannedPaymentAmount')">
<el-input v-model="formData.plannedPayment"
:placeholder="t('progressReport.form.inputPlaceholder')">
<template #append>{{ t('progressReport.form.unitSuffix') }}</template>
</el-input>
</el-form-item>
<el-form-item style="height: 82px;"
:label="t('progressReport.form.completedPaymentAmount')">
<el-input v-model="formData.actualPayment"
:placeholder="t('progressReport.form.inputPlaceholder')">
<template #append>{{ t('progressReport.form.unitSuffix') }}</template>
</el-input>
</el-form-item>
<el-form-item style="height: 82px;"
:label="t('progressReport.form.plannedAmountPaymentCompletionRate')">
<el-input v-model="formData.investmentPlanCompletionRate"
:placeholder="t('progressReport.form.inputPlaceholder')">
<template #append>%</template>
</el-input>
</el-form-item>
</div>
</div>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="24">
<el-form-item :label="t('progressReport.form.effectiveness')">
<el-input v-model="formData.achievements"
:placeholder="t('progressReport.form.inputPlaceholder')" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="24">
<el-form-item :label="t('progressReport.form.coordinationMatters')">
<el-input v-model="formData.coordinationIssues"
:placeholder="t('progressReport.form.inputPlaceholder')" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="24">
<el-form-item :label="t('progressReport.form.nextWorkArrangements')">
<el-input v-model="formData.nextWorkPlan"
:placeholder="t('progressReport.form.inputPlaceholder')" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="24">
<el-form-item :label="t('progressReport.form.currentStageEvidenceMaterials')">
<el-input v-model="formData.supportingDocuments"
:placeholder="t('progressReport.form.selectAttachmentPlaceholder')" readonly>
<template #append>
<UploadFile :modelValue="formData.supportingDocuments" @change="uploadChange" :fileSize="20"
type="simple" :limit="10" :isShowTip="false" />
</template>
</el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="24">
<el-form-item :label="t('progressReport.form.remark')">
<el-input v-model="formData.remarks" :placeholder="t('progressReport.form.inputPlaceholder')" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="24">
<el-form-item :label="t('progressReport.form.isLastDeclaration')">
<el-select v-model="formData.isFinalApplication"
:placeholder="t('progressReport.form.selectPlaceholder')" clearable>
<el-option :label="t('progressReport.form.yes')" value="1" />
<el-option :label="t('progressReport.form.no')" value="0" />
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
</template>
<script lang="ts" setup>
import { reactive, computed, watch, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import { InvestmentProjectProgress } from '/@/views/invMid/progressReport/interface/type';
import { investmentProjectsPlanList } from '/@/views/invMid/projectLibrary/interface/types';
import { investmentProjectsPlanPage } from '/@/api/investment/investmentManagement';
import { ProjectPlanApplyFormItem } from '/@/components/investment/interface/types';
import { constructionStageOptions, projectStatusOptions } from '/@/hooks/enums';
import UploadFile from "/@/components/Upload/index.vue";
import { type FormInstance, FormRules } from 'element-plus';
const { t } = useI18n();
export interface ProjectProgressReportFormData {
projectName: string;
projectStatus: string;
constructionStage: string;
projectImplementationUnit: string;
totalInvestmentAmount: string;
cumulativeInvestmentToMonthEnd: string;
completionRate: string;
cumulativePaymentToMonthEnd: string;
paymentCompletionRate: string;
// 本年投资形象额
reportYear: string;
currentYearPlannedInvestment: string;
enterpriseCumulativeInvestmentToMonthEnd: string;
investmentCompletionRate: string;
// 本年投资计划额
plannedPaymentAmount: string;
completedPaymentAmount: string;
plannedAmountPaymentCompletionRate: string;
// 其他字段
effectiveness: string;
coordinationMatters: string;
nextWorkArrangements: string;
currentStageEvidenceMaterials: any[];
remark: string;
isLastDeclaration: string;
}
const props = defineProps<{
modelValue?: InvestmentProjectProgress;
rules?:FormRules;
}>();
const emit = defineEmits<{
(e: 'update:modelValue', value: InvestmentProjectProgress): void;
}>();
const useForm = ref<FormInstance | undefined>()
const defaultForm = reactive<InvestmentProjectProgress>({
id: undefined,
projectName: '',
projectId: undefined,
projectStatus: '',
constructionStage: '',
implementingBody: '',
projectTotalAmount: undefined,
cumulativeInvestmentToDate: undefined,
completionRate: undefined,
cumulativePaymentToDate: undefined,
paymentCompletionRate: undefined,
annualReport: undefined,
annualPlannedInvestment: undefined,
ytdRemainingInvestment: undefined,
investmentCompletionRate: undefined,
plannedPayment: undefined,
actualPayment: undefined,
investmentPlanCompletionRate: undefined,
achievements: '',
coordinationIssues: '',
nextWorkPlan: '',
supportingDocuments: '',
remarks: '',
isFinalApplication: undefined,
createBy: '',
createTime: '',
updateBy: '',
updateTime: '',
delFlag: '',
processInstanceId: '',
status: '',
})
const formData = reactive<InvestmentProjectProgress>({ ...defaultForm, ...props.modelValue });
const projectNameData = ref<ProjectPlanApplyFormItem[]>([]);
// 获取当前日期作为汇报时间
const reportTime = computed(() => {
const now = new Date();
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
const day = String(now.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
});
const total = ref(0)
const queryForm = reactive<investmentProjectsPlanList>({
page: 1,
size: 10,
});
const getProjectNameList = async () => {
try {
const res = await investmentProjectsPlanPage(queryForm);
projectNameData.value = res.data?.records || [];
total.value = res.data?.total || 0;
} catch (error) {
console.error(error);
projectNameData.value = []; // 出错时设置为空数组
}
}
getProjectNameList();
/**
* 项目选择改变
* @param {string | number} value - 选中的项目ID
*/
const handelSelectChange = (value: string | number) => {
// 根据选中的项目ID查找对应的项目信息
const selectedProject = projectNameData.value.find(item =>
item.id == value
);
// 如果找到了对应的项目,则更新实施单位字段
if (selectedProject) {
formData.implementingBody = selectedProject.projectMainEntity || selectedProject.projectOwnerUnit || '';
formData.projectName = selectedProject.projectName || '';
formData.deptId = selectedProject.deptId;
}
}
/**
* 页码大小改变
* @param {number} pageSize - 新的页码大小
* */
const handlePageSizeChange = (pageSize: number) => {
queryForm.size = pageSize;
getProjectNameList();
}
/**
* 页码改变
* @param {number} page - 新的页码
* */
const handlePageChange = (page: number) => {
queryForm.page = page;
getProjectNameList();
}
// 监听 formData 变化,同步到父组件
watch(
formData,
(newVal) => {
console.log(newVal);
emit('update:modelValue', { ...newVal });
},
{ deep: true }
);
// 监听 props.modelValue 变化,同步到 formData
watch(
() => props.modelValue,
(newVal) => {
if (newVal) {
if (typeof newVal.annualReport === 'number') newVal.annualReport = newVal.annualReport.toString()
Object.assign(formData, defaultForm, newVal);
}
},
{ immediate: true, deep: true }
);
const uploadChange = (_:any,data:any[]) =>{
if (!data || Object.prototype.toString.call(data) !== '[object Array]' || data.length === 0){
formData.supportingDocuments = [];
return;
}
formData.supportingDocuments = data.map((item:any) => {
return {
name: item.name,
url: item.url
}
})
}
defineExpose({
validate: async () => {
const isValid = await useForm.value?.validate();
if (!isValid) return false
return formData
},
})
</script>
<style scoped>
.page-title-row {
display: flex;
justify-content: center;
align-items: center;
position: relative;
margin-bottom: 20px;
}
.page-title {
font-size: 20px;
font-weight: 600;
text-align: center;
}
.page-report-time {
position: absolute;
left: 0;
font-size: 14px;
color: var(--el-text-color-secondary);
}
.page-unit {
position: absolute;
right: 0;
font-size: 14px;
color: var(--el-text-color-secondary);
}
.project-progress-report-form {
background: #fff;
border-radius: 4px;
padding: 20px;
border: 1px solid var(--el-border-color-light);
}
.form-section-title {
font-size: 16px;
font-weight: 600;
color: var(--el-text-color-primary);
margin: 0 0 20px;
padding-left: 10px;
border-left: 4px solid var(--el-color-primary);
}
.progress-form {
width: 100%;
}
/* 表单 label 左对齐 */
.progress-form :deep(.el-form-item__label) {
text-align: left;
justify-content: flex-start;
}
.form-row {
margin-bottom: 16px;
margin-top: 16px;
}
.form-row:last-of-type {
margin-bottom: 0;
}
.cursor-pointer {
cursor: pointer;
}
.plan-investment-block {
margin-top: 24px;
}
.plan-investment-panel {
display: flex;
flex-direction: row;
align-items: center;
background: #f0f7ff;
padding: 16px;
border-radius: 4px;
min-height: 414px;
}
.panel-title {
width: 200px;
padding-top: 0;
margin-top: 0;
font-size: 16px;
font-weight: 600;
color: var(--el-text-color-primary);
white-space: nowrap;
}
.plan-investment-panel :deep(.el-form-item__label) {
padding-top: 0;
line-height: 32px;
}
.plan-investment-panel :deep(.el-form-item) {
align-items: center;
}
</style>

View File

@@ -0,0 +1,415 @@
<template>
<el-row class="page-title-row mb10">
<div class="page-title">{{ title ? title : t('progressReport.form.title') }}</div>
<div class="page-report-time">{{ t('progressReport.form.reportTime') }}: {{formData.createTime || reportTime }}</div>
<div class="page-unit">{{ t('progressReport.form.unit') }}</div>
</el-row>
<div class="project-progress-report-form">
<div class="form-section-title">{{ t('progressReport.form.sectionTitle') }}</div>
<el-form :model="formData" label-width="200px" class="progress-form" :rules="rules" ref="useForm">
<el-row :gutter="20" class="form-row">
<el-col :span="24">
<el-form-item :label="t('progressReport.form.projectName')" required prop="projectName">
<span>{{formData.projectName }}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('progressReport.form.projectStatus')" required prop="projectStatus">
<span v-for="item in projectStatusOptions" :key="item.value">{{formData.projectStatus == item.value ? item.label : ''}}</span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('progressReport.form.constructionStage')">
<span v-for="item in constructionStageOptions" :key="item.value">{{formData.constructionStage == item.value ? item.label : ''}}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('progressReport.form.projectImplementationUnit')">
<span>{{formData.implementingBody}}</span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('progressReport.form.totalInvestmentAmount')" required prop="projectTotalAmount">
<span>{{formData.projectTotalAmount }}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('progressReport.form.cumulativeInvestmentToMonthEnd')" required prop="cumulativeInvestmentToDate">
<span>{{formData.cumulativeInvestmentToDate}}</span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('progressReport.form.completionRate')" required prop="completionRate">
<span>{{formData.completionRate}}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('progressReport.form.cumulativePaymentToMonthEnd')">
<span>{{formData.cumulativePaymentToDate}}</span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('progressReport.form.paymentCompletionRate')">
<span>{{formData.paymentCompletionRate}}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="plan-investment-block">
<el-col :span="12">
<div class="plan-investment-panel left-panel">
<div class="panel-title">{{ t('progressReport.form.currentYearImageAmount') }}</div>
<div style="flex: 1;">
<el-form-item style="height: 82px;" :label="t('progressReport.form.reportYear')">
<span>{{formData.annualReport}}</span>
</el-form-item>
<el-form-item style="height: 82px;"
:label="t('progressReport.form.currentYearPlannedInvestment')" required prop="annualPlannedInvestment">
<span>{{formData.investmentTotalAmount ?? 0 + ' ' + t('progressReport.form.unitSuffix')}}</span>
</el-form-item>
<el-form-item style="height: 82px;"
:label="t('progressReport.form.enterpriseCumulativeInvestmentToMonthEnd')" required prop="ytdRemainingInvestment">
<span>{{ formData.ytdRemainingInvestment + ' ' + t('progressReport.form.unitSuffix')}}</span>
</el-form-item>
<el-form-item style="height: 82px;"
:label="t('progressReport.form.investmentCompletionRate')">
<span>{{formData.investmentCompletionRate}}%</span>
</el-form-item>
</div>
</div>
</el-col>
<el-col :span="12">
<div class="plan-investment-panel right-panel">
<div class="panel-title">{{ t('progressReport.form.currentYearPlannedAmount') }}</div>
<div style="flex: 1;">
<el-form-item style="height: 82px;" :label="t('progressReport.form.plannedPaymentAmount')">
<span>{{formData.plannedPayment + ' ' + t('progressReport.form.unitSuffix')}}</span>
</el-form-item>
<el-form-item style="height: 82px;"
:label="t('progressReport.form.completedPaymentAmount')">
<span>{{formData.actualPayment + ' ' + t('progressReport.form.unitSuffix')}}</span>
</el-form-item>
<el-form-item style="height: 82px;"
:label="t('progressReport.form.plannedAmountPaymentCompletionRate')">
<span>{{formData.investmentPlanCompletionRate}} %</span>
</el-form-item>
</div>
</div>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="24">
<el-form-item :label="t('progressReport.form.effectiveness')">
<span>{{formData.achievements}}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="24">
<el-form-item :label="t('progressReport.form.coordinationMatters')">
<span>{{formData.coordinationIssues}}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="24">
<el-form-item :label="t('progressReport.form.nextWorkArrangements')">
<span>{{formData.nextWorkPlan}}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="24">
<el-form-item :label="t('progressReport.form.currentStageEvidenceMaterials')">
<uploadFile :modelValue="JSON.parse(formData.supportingDocuments || '[]') || []" @change="uploadChange" :fileSize="20" type="simple" :limit="10"
:isShowTip="false" disabled></uploadFile>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="24">
<el-form-item :label="t('progressReport.form.remark')">
<span>{{formData.remarks}}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="form-row">
<el-col :span="24">
<el-form-item :label="t('progressReport.form.isLastDeclaration')">
<span>{{formData.isFinalApplication == '1' ? t('progressReport.form.yes') : t('progressReport.form.no')}}</span>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
</template>
<script lang="ts" setup>
import { reactive, computed, watch, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import { InvestmentProjectProgress } from '/@/views/invMid/progressReport/interface/type';
import { investmentProjectsPlanList } from '/@/views/invMid/projectLibrary/interface/types';
import { investmentProjectsPlanPage } from '/@/api/investment/investmentManagement';
import { ProjectPlanApplyFormItem } from '/@/components/investment/interface/types';
import { constructionStageOptions, projectStatusOptions } from '/@/hooks/enums';
import { type FormInstance, FormRules } from 'element-plus';
import uploadFile from '/@/components/Upload/index.vue';
const { t } = useI18n();
export interface ProjectProgressReportFormData {
projectName: string;
projectStatus: string;
constructionStage: string;
projectImplementationUnit: string;
totalInvestmentAmount: string;
cumulativeInvestmentToMonthEnd: string;
completionRate: string;
cumulativePaymentToMonthEnd: string;
paymentCompletionRate: string;
// 本年投资形象额
reportYear: string;
currentYearPlannedInvestment: string;
enterpriseCumulativeInvestmentToMonthEnd: string;
investmentCompletionRate: string;
// 本年投资计划额
plannedPaymentAmount: string;
completedPaymentAmount: string;
plannedAmountPaymentCompletionRate: string;
// 其他字段
effectiveness: string;
coordinationMatters: string;
nextWorkArrangements: string;
currentStageEvidenceMaterials: any[];
remark: string;
isLastDeclaration: string;
}
const props = defineProps<{
modelValue?: InvestmentProjectProgress;
rules?:FormRules;
title?: string;
}>();
const emit = defineEmits<{
(e: 'update:modelValue', value: InvestmentProjectProgress): void;
}>();
const useForm = ref<FormInstance | undefined>()
const defaultForm = reactive<InvestmentProjectProgress>({
id: undefined,
projectName: '',
projectId: undefined,
projectStatus: '',
constructionStage: '',
implementingBody: '',
projectTotalAmount: undefined,
cumulativeInvestmentToDate: undefined,
completionRate: undefined,
cumulativePaymentToDate: undefined,
paymentCompletionRate: undefined,
annualReport: undefined,
annualPlannedInvestment: undefined,
ytdRemainingInvestment: undefined,
investmentCompletionRate: undefined,
plannedPayment: undefined,
actualPayment: undefined,
investmentPlanCompletionRate: undefined,
achievements: '',
coordinationIssues: '',
nextWorkPlan: '',
supportingDocuments: '',
remarks: '',
isFinalApplication: undefined,
createBy: '',
createTime: '',
updateBy: '',
updateTime: '',
delFlag: '',
processInstanceId: '',
status: '',
})
const formData = reactive<InvestmentProjectProgress>({ ...defaultForm, ...props.modelValue });
const projectNameData = ref<ProjectPlanApplyFormItem[]>([]);
// 获取当前日期作为汇报时间
const reportTime = computed(() => {
const now = new Date();
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
const day = String(now.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
});
const total = ref(0)
const queryForm = reactive<investmentProjectsPlanList>({
page: 1,
size: 10,
});
const getProjectNameList = async () => {
try {
const res = await investmentProjectsPlanPage(queryForm);
projectNameData.value = res.data?.records || [];
total.value = res.data?.total || 0;
} catch (error) {
console.error(error);
projectNameData.value = []; // 出错时设置为空数组
}
}
getProjectNameList();
/**
* 初始化图片
* */
const uploadChange = (_:any,data:any[]) =>{
if (!data || Object.prototype.toString.call(data) !== '[object Array]' || data.length === 0){
formData.supportingDocuments = [];
return;
}
formData.supportingDocuments = data.map((item:any) => {
return {
name: item.name,
url: item.url
}
})
}
// 监听 formData 变化,同步到父组件
watch(
formData,
(newVal) => {
emit('update:modelValue', { ...newVal });
},
{ deep: true }
);
// 监听 props.modelValue 变化,同步到 formData
watch(
() => props.modelValue,
(newVal) => {
if (newVal) {
if (typeof newVal.annualReport === 'number') newVal.annualReport = newVal.annualReport.toString()
Object.assign(formData, defaultForm, newVal);
}
},
{ immediate: true, deep: true }
);
defineExpose({
validate: async () => {
const isValid = await useForm.value?.validate();
if (!isValid) return false
return formData
},
})
</script>
<style scoped>
.page-title-row {
display: flex;
justify-content: center;
align-items: center;
position: relative;
margin-bottom: 20px;
}
.page-title {
font-size: 20px;
font-weight: 600;
text-align: center;
}
.page-report-time {
position: absolute;
left: 0;
font-size: 14px;
color: var(--el-text-color-secondary);
}
.page-unit {
position: absolute;
right: 0;
font-size: 14px;
color: var(--el-text-color-secondary);
}
.project-progress-report-form {
background: #fff;
border-radius: 4px;
padding: 20px;
border: 1px solid var(--el-border-color-light);
}
.form-section-title {
font-size: 16px;
font-weight: 600;
color: var(--el-text-color-primary);
margin: 0 0 20px;
padding-left: 10px;
border-left: 4px solid var(--el-color-primary);
}
.progress-form {
width: 100%;
}
/* 表单 label 左对齐 */
.progress-form :deep(.el-form-item__label) {
text-align: left;
justify-content: flex-start;
}
.form-row {
margin-bottom: 16px;
margin-top: 16px;
}
.form-row:last-of-type {
margin-bottom: 0;
}
.cursor-pointer {
cursor: pointer;
}
.plan-investment-block {
margin-top: 24px;
}
.plan-investment-panel {
display: flex;
flex-direction: row;
align-items: center;
background: #f0f7ff;
padding: 16px;
border-radius: 4px;
min-height: 414px;
}
.panel-title {
margin-right: 20px;
padding-top: 0;
margin-top: 0;
font-size: 16px;
font-weight: 600;
color: var(--el-text-color-primary);
white-space: nowrap;
}
.plan-investment-panel :deep(.el-form-item__label) {
padding-top: 0;
line-height: 32px;
}
.plan-investment-panel :deep(.el-form-item) {
align-items: center;
}
</style>