This commit is contained in:
2025-12-27 16:44:46 +08:00
parent b674b78621
commit a8cb979339
12 changed files with 690 additions and 528 deletions

View File

@@ -172,7 +172,7 @@
</template>
<script setup lang="ts">
import { reactive, watch } from 'vue';
import { reactive, watch, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import { FolderOpened, OfficeBuilding } from '@element-plus/icons-vue';
import { investmentProjectsPlanGetById, investmentProjectsPlanPage } from '/@/api/investment/investmentManagement';
@@ -205,6 +205,7 @@ const defaultForm: ProjectTask = {
executor: '',
taskStartDate: new Date().toISOString().substring(0, 10),
taskEndDate: new Date().toISOString().substring(0, 10),
deptId: ''
};
const formData = reactive<ProjectTask>({ ...defaultForm, ...props.modelValue });

View File

@@ -452,8 +452,8 @@
</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 #default="{ $index }">
<el-radio v-model="selectedAnnualInvestmentIndex" :value="$index" />
</template>
</el-table-column>
<el-table-column :label="t('planApply.annualInvestmentInfo.table.index')" width="60" align="center">
@@ -488,9 +488,9 @@
'(万元)' }}</span>
</template>
<template #default="{ row }">
<el-input-number :precision="2" :controls="false" :min="0" :value-on-clear="null"
v-model="row.plannedPaymentAmount" :placeholder="t('planApply.placeholder.input')"
:class="{ 'is-error': row.plannedPaymentAmount === null }" />
<el-input-number :precision="2" :controls="false" readonly
:model-value="calculateRowPaymentLimit(row)"
:placeholder="t('planApply.placeholder.input')" />
</template>
</el-table-column>
<el-table-column :label="t('planApply.annualInvestmentInfo.table.fundingSources')" align="center">
@@ -659,7 +659,8 @@
</el-col>
</el-row>
</el-form>
<ProjectNameList :visible="visible" @emit:cancel="visible = false" @emit:confirm="projectNameFn" />
<ProjectNameList :visible="visible" :isSelect="false" :selectedId="''" @emit:cancel="visible = false"
@emit:confirm="projectNameFn" />
<LibrarySelect v-model="librarySelectVisible" @select="handleLibrarySelect" />
</div>
</template>
@@ -903,6 +904,18 @@ const safeParseFloat = (value: string | number | null): number => {
const parsed = typeof value === 'string' ? parseFloat(value) : value;
return isNaN(parsed) ? 0 : parsed;
};
// 计算表格每行的计划支付额度 = 自有资金 + 对外募集资金 + 财政资金 + 其他资金
const calculateRowPaymentLimit = (row: InvestmentProjects): number => {
const selfFunding = safeParseFloat(row.selfFunding);
const externalFunding = safeParseFloat(row.externalFunding);
const fiscalFunding = safeParseFloat(row.fiscalFunding);
const otherFunding = safeParseFloat(row.otherFunding);
const total = selfFunding + externalFunding + fiscalFunding + otherFunding;
// 同步更新 row.plannedPaymentAmount 以便后续计算汇总
row.plannedPaymentAmount = total;
return total;
};
// 监听投资计划数据变化
watch(() => formData.value.investmentProjects, (newValue) => {
if (!year.value) return;
@@ -1048,7 +1061,46 @@ const validateForm = async () => {
return Promise.resolve(true);
};
const projectNameFn = (row: any) => {
Object.assign(formData.value.entity, row);
// 映射 API 返回的字段名到表单字段名
const mappedData = {
...row,
// 资金相关字段映射
ownedFunds: row.enterpriseOwnFunds ?? row.ownedFunds ?? '',
financialFunds: row.governmentInvestmentFunds ?? row.financialFunds ?? '',
externalRaisedCapital: row.externalRaisedFunds ?? row.externalRaisedCapital ?? '',
otherFunds: row.otherFunds ?? '',
// 计划投资年度信息映射
planInvestmentYear: row.planInvestmentYear ?? '',
planImageQuota: row.planImageQuota ?? '',
planPaymentLimit: row.planPaymentLimit ?? '',
governmentFundSourceDesc: row.governmentFundSourceDesc ?? '',
otherFundSourceDesc: row.otherFundSourceDesc ?? '',
// 主业相关字段映射
isMainBusiness: row.isMainBusiness ?? '',
mainBusinessTypes: row.mainBusinessTypes ?? '',
mainBusinessCode: row.mainBusinessCode ?? '',
// 项目信息字段映射
projectInvestmentDirection: row.projectInvestmentDirection ?? '',
investmentDirectionSegmentation: row.investmentDirectionSegmentation ?? '',
isStrategicEmergingIndustries: row.isStrategicEmergingIndustries ?? '',
urbanStrategy: row.urbanStrategy ?? '',
isManufacturingIndustry: row.isManufacturingIndustry ?? '',
majorInvestmentProjects: row.majorInvestmentProjects ?? '',
// 决策信息字段映射
decisionType: row.decisionType ?? '',
isProjectApprovalCompleted: row.isProjectApprovalCompleted ?? '',
projectApprovalFileNo: row.projectApprovalFileNo ?? '',
projectApprovalFileInfo: row.projectApprovalFileInfo ?? '',
isDecisionProcedureCompleted: row.isDecisionProcedureCompleted ?? '',
decisionProcedureFileNo: row.decisionProcedureFileNo ?? '',
decisionFileInfo: row.decisionFileInfo ?? '',
// 其他字段映射
projectDesc: row.projectDesc ?? '',
progressDesc: row.progressDesc ?? '',
shareholdingRatio: row.shareholdingRatio ?? '',
isControllingStake: row.isControllingStake ?? '',
};
Object.assign(formData.value.entity, mappedData);
visible.value = false;
};
const handleLibrarySelect = (row: any) => {

View File

@@ -1,189 +1,231 @@
<template>
<div class="project-plan-apply-form border-r border-[#e5e7eb]">
<FlowFormView :process-instance-id="processInstanceId"/>
<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>
<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>
<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>
<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>
<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 :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>
<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 :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 :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 :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 :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 :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 :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 :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 :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 :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>
<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('reserveRegistration.basicInfo.mainBusinessCode')" required prop="entity.mainBusinessCode">
<span>{{formData.entity.mainBusinessTypes}}</span>
<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.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 :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('planApply.applySection.projectImplementationStart')" required prop="entity.projectStartTime">
<span>{{formData.entity.projectStartTime}}</span>
<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.projectImplementationEnd')" required prop="entity.projectEndTime">
<span>{{formData.entity.projectEndTime}}</span>
<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>
@@ -194,15 +236,17 @@
<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>
<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>
<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>
<span>{{ formData.entity.planPaymentLimit }}{{
t('planApply.investmentEstimate.unitSuffix') }}</span>
</el-form-item>
</div>
</div>
@@ -211,24 +255,33 @@
<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 :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 :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">
<el-form-item :label="t('planApply.investmentEstimate.externalRaisedFunds')" required
prop="entity.externalRaisedCapital">
<span>{{formData.entity.externalRaisedCapital}}{{ t('planApply.investmentEstimate.unitSuffix') }}</span>
<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 :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>
<span>{{ formData.entity.governmentFundSourceDesc }}</span>
</el-form-item>
<el-form-item :label="t('planApply.investmentEstimate.otherFundingDescription')">
<span>{{formData.entity.otherFundSourceDesc}}</span>
<span>{{ formData.entity.otherFundSourceDesc }}</span>
</el-form-item>
</div>
</div>
@@ -237,8 +290,9 @@
<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 :label="t('planApply.applySection.projectOverview')" required
prop="entity.projectDesc">
<span>{{ formData.entity.projectDesc }}</span>
</el-form-item>
</el-col>
</el-row>
@@ -246,18 +300,19 @@
<el-row class="form-row">
<el-col :span="24">
<el-form-item :label="t('planApply.applySection.projectInitialPlan')">
<span>{{formData.entity.projectPreliminaryPlan}}</span>
<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-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>
<span>{{ formData.entity.remark }}</span>
</el-form-item>
</el-col>
</el-row>
@@ -266,28 +321,35 @@
<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 :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 :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">
<el-form-item :label="t('planApply.investmentStatus.ourTotalInvestmentAmount')" required
prop="entity.ourInvestmentTotalAmount">
<span>{{formData.entity.ourInvestmentTotalAmount}}{{ t('planApply.investmentEstimate.unitSuffix') }}</span>
<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">
<el-form-item :label="t('planApply.investmentStatus.ourCumulativeInvestmentLastYear')" required
prop="entity.ourLastYearCompleted">
<span>{{formData.entity.ourLastYearCompleted}}{{ t('planApply.investmentEstimate.unitSuffix') }}</span>
<span>{{ formData.entity.ourLastYearCompleted }}{{ t('planApply.investmentEstimate.unitSuffix')
}}</span>
</el-form-item>
</el-col>
</el-row>
@@ -320,53 +382,53 @@
</el-table-column>
<el-table-column :label="t('planApply.annualInvestmentInfo.table.planYear')" min-width="140">
<template #default="{ row }">
<span>{{row.plannedInvestmentYear}}</span>
<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>
<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>
<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>
<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>
<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>
<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>
<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>
<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>
<span>{{ row.otherFundingSource }}{{ t('planApply.investmentEstimate.unitSuffix') }}</span>
</template>
</el-table-column>
</el-table-column>
</el-table>
@@ -374,13 +436,14 @@
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('planApply.decisionInfo.decisionType')">
<span>{{formData.entity.decisionType}}</span>
<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">
<el-form-item :label="t('planApply.decisionInfo.isCompleteEstablishmentProcedures')" required
prop="entity.isProjectApprovalCompleted">
<span>{{formData.entity.isProjectApprovalCompleted}}</span>
<span>{{ formData.entity.isProjectApprovalCompleted }}</span>
</el-form-item>
</el-col>
</el-row>
@@ -388,25 +451,26 @@
<el-row :gutter="20" class="form-row">
<el-col :span="12">
<el-form-item :label="t('planApply.decisionInfo.establishmentDocumentNumber')">
<span>{{formData.entity.projectApprovalFileNo}}</span>
<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>
<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 :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>
<span>{{ formData.entity.decisionProcedureFileNo }}</span>
</el-form-item>
</el-col>
</el-row>
@@ -414,7 +478,7 @@
<el-row :gutter="20" class="form-row">
<el-col :span="24">
<el-form-item :label="t('planApply.decisionInfo.decisionDocumentInfo')">
<span>{{formData.entity.decisionFileInfo}}</span>
<span>{{ formData.entity.decisionFileInfo }}</span>
</el-form-item>
</el-col>
</el-row>
@@ -425,32 +489,33 @@
<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
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;
modelValue?: ProjectPlanApplyFormData;
rules?: FormRules;
isEdit?: boolean;
title?: string;
processInstanceId?: string;
}>(), {
isEdit: true,
title:'',
processInstanceId:''
isEdit: true,
title: '',
processInstanceId: ''
});
const emit = defineEmits<{
@@ -458,85 +523,88 @@ const emit = defineEmits<{
}>();
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: '',
},
],
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: '',
processInstanceId: '',
status: 0,
deptId: 0
},
investmentProjects: [
{
plannedInvestmentYear: '',
plannedImageAmount: '',
plannedPaymentAmount: '',
selfFunding: '',
externalFunding: '',
fiscalFunding: '',
otherFunding: '',
fiscalFundingSource: '',
otherFundingSource: '',
},
],
};
const formData = ref<ProjectPlanApplyFormData>({ ...defaultForm });
@@ -584,7 +652,7 @@ watch(
() => props.modelValue,
newVal => {
Object.assign(formData.value, newVal || {});
formData.value.entity.planInvestmentYear = String(newVal?.entity?.planInvestmentYear);
formData.value.entity.planInvestmentYear = String(newVal?.entity?.planInvestmentYear);
// 如果有数据且没有选中,默认选中第一行
if (formData.value.investmentProjects.length > 0 && selectedAnnualInvestmentIndex.value === -1) {
selectedAnnualInvestmentIndex.value = 0;
@@ -594,7 +662,7 @@ watch(
);
watch(
()=> formData.value,
() => formData.value,
() => {
emit('update:modelValue', { ...formData.value });
},
@@ -604,7 +672,7 @@ const validateForm = () => {
return useForm.value?.validate();
}
defineExpose({
validateForm: validateForm
validateForm: validateForm
})
</script>

View File

@@ -1,7 +1,8 @@
<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-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">
@@ -11,26 +12,14 @@
<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"
/>
: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"
/>
<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>
@@ -40,24 +29,18 @@
<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>
: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-option v-for="item in constructionStageOptions" :key="item.value" :value="item.value"
:label="item.label" />
</el-select>
</el-form-item>
</el-col>
@@ -70,7 +53,8 @@
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="t('progressReport.form.totalInvestmentAmount')" required prop="projectTotalAmount">
<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>
@@ -80,7 +64,8 @@
</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-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>
@@ -125,14 +110,16 @@
: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">
: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">
: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>
@@ -210,8 +197,8 @@
<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" />
<UploadFile :modelValue="formData.supportingDocuments" @change="uploadChange"
:fileSize="20" type="simple" :limit="10" :isShowTip="false" />
</template>
</el-input>
</el-form-item>
@@ -284,7 +271,7 @@ export interface ProjectProgressReportFormData {
const props = defineProps<{
modelValue?: InvestmentProjectProgress;
rules?:FormRules;
rules?: FormRules;
}>();
const emit = defineEmits<{
@@ -292,37 +279,38 @@ const emit = defineEmits<{
}>();
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: '',
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: '',
deptId: ''
})
const formData = reactive<InvestmentProjectProgress>({ ...defaultForm, ...props.modelValue });
const projectNameData = ref<ProjectPlanApplyFormItem[]>([]);
@@ -340,14 +328,14 @@ const queryForm = reactive<investmentProjectsPlanList>({
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 = []; // 出错时设置为空数组
}
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();
/**
@@ -355,39 +343,39 @@ 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;
}
// 根据选中的项目ID查找对应的项目信息
const selectedProject = projectNameData.value.find(item =>
item.id == value
);
// 如果找到了对应的项目,则更新实施单位字段
if (selectedProject) {
formData.implementingBody = selectedProject.projectMainEntity || selectedProject.projectOwnerUnit || '';
formData.projectName = selectedProject.projectName || '';
formData.deptId = String(selectedProject.deptId);
}
}
/**
* 页码大小改变
* @param {number} pageSize - 新的页码大小
* */
const handlePageSizeChange = (pageSize: number) => {
queryForm.size = pageSize;
getProjectNameList();
queryForm.size = pageSize;
getProjectNameList();
}
/**
* 页码改变
* @param {number} page - 新的页码
* */
const handlePageChange = (page: number) => {
queryForm.page = page;
getProjectNameList();
queryForm.page = page;
getProjectNameList();
}
// 监听 formData 变化,同步到父组件
watch(
formData,
(newVal) => {
console.log(newVal);
console.log(newVal);
emit('update:modelValue', { ...newVal });
},
{ deep: true }
@@ -398,30 +386,30 @@ watch(
() => props.modelValue,
(newVal) => {
if (newVal) {
if (typeof newVal.annualReport === 'number') newVal.annualReport = newVal.annualReport.toString()
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
}
})
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
},
validate: async () => {
const isValid = await useForm.value?.validate();
if (!isValid) return false
return formData
},
})
</script>

View File

@@ -143,7 +143,7 @@
<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 || '[]') || []"
<uploadFile :modelValue="parseSupportingDocuments(formData.supportingDocuments)"
@change="uploadChange" :fileSize="20" type="simple" :limit="10" :isShowTip="false" disabled>
</uploadFile>
</el-form-item>
@@ -161,7 +161,7 @@
<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') :
<span>{{ formData.isFinalApplication === 1 ? t('progressReport.form.yes') :
t('progressReport.form.no') }}</span>
</el-form-item>
</el-col>
@@ -252,6 +252,7 @@ const defaultForm = reactive<InvestmentProjectProgress>({
delFlag: '',
processInstanceId: '',
status: '',
deptId: '',
})
const formData = reactive<InvestmentProjectProgress>({ ...defaultForm, ...props.modelValue });
const projectNameData = ref<ProjectPlanApplyFormItem[]>([]);
@@ -279,20 +280,33 @@ const getProjectNameList = async () => {
}
}
getProjectNameList();
/**
* 解析 supportingDocuments处理可能是字符串或数组的情况
*/
const parseSupportingDocuments = (value: string | { name: string; url: string }[] | undefined): { name: string; url: string }[] => {
if (!value) return [];
if (Array.isArray(value)) return value;
try {
return JSON.parse(value) || [];
} catch {
return [];
}
}
/**
* 初始化图片
* */
const uploadChange = (_: any, data: any[]) => {
if (!data || Object.prototype.toString.call(data) !== '[object Array]' || data.length === 0) {
formData.supportingDocuments = [];
formData.supportingDocuments = '[]';
return;
}
formData.supportingDocuments = data.map((item: any) => {
formData.supportingDocuments = JSON.stringify(data.map((item: any) => {
return {
name: item.name,
url: item.url
}
})
}));
}
// 监听 formData 变化,同步到父组件
watch(

View File

@@ -9,7 +9,8 @@
<el-row :gutter="20" class="instruction-grid">
<el-col v-for="field in instructionFields" :key="field.key" :span="field.span || 8">
<el-form-item :label="field.label" label-width="80px">
<el-input maxlength="255" v-model="instructionForm[field.key]" :placeholder="t('mixedRegister.placeholder.input')" />
<el-input maxlength="255" v-model="instructionForm[field.key]"
:placeholder="t('mixedRegister.placeholder.input')" />
</el-form-item>
</el-col>
</el-row>
@@ -24,26 +25,14 @@
<el-col v-for="field in basicInfoFields" :key="field.key" :span="field.span || 12" class="mb-4">
<el-form-item :label="field.label">
<!-- 日期时间选择器 -->
<el-date-picker
v-if="field.type && ['date', 'datetime'].includes(field.type)"
v-model="basicInfoForm[field.key]"
:type="field.type"
:placeholder="t('mixedRegister.placeholder.select')"
v-bind="field.fieldProps"
/>
<el-date-picker v-if="field.type && ['date', 'datetime', 'year'].includes(field.type)"
v-model="basicInfoForm[field.key]" :type="field.type"
:placeholder="t('mixedRegister.placeholder.select')" v-bind="field.fieldProps" />
<!-- 选择器 -->
<el-select
v-else-if="field.type === 'select'"
v-model="basicInfoForm[field.key]"
:placeholder="t('mixedRegister.placeholder.select')"
v-bind="field.fieldProps"
>
<el-option
v-for="item of field.fieldProps?.options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
<el-select v-else-if="field.type === 'select'" v-model="basicInfoForm[field.key]"
:placeholder="t('mixedRegister.placeholder.select')" v-bind="field.fieldProps">
<el-option v-for="item of field.fieldProps?.options" :key="item.value"
:label="item.label" :value="item.value" />
</el-select>
<div class="partner-name-cell w-full" v-else-if="isUpdate && field.key === 'projectName'">
<el-input v-model="basicInfoForm.projectName" maxlength="255"
@@ -52,11 +41,12 @@
<LibrarySelect v-model="librarySelectVisible" @select="handleLibrarySelect" />
</div>
<!-- 输入框 -->
<template v-else>
<el-input-number v-if="field.type === 'number'" :length="field.length" v-model="basicInfoForm[field.key]"
:controls="false" :min="0"/>
<el-input v-else maxlength="255" v-model="basicInfoForm[field.key]" :placeholder="t('mixedRegister.placeholder.input')" />
</template>
<template v-else>
<el-input-number v-if="field.type === 'number'" :length="field.length"
v-model="basicInfoForm[field.key]" :controls="false" :min="0" />
<el-input v-else maxlength="255" v-model="basicInfoForm[field.key]"
:placeholder="t('mixedRegister.placeholder.input')" />
</template>
</el-form-item>
</el-col>
</el-row>
@@ -101,7 +91,7 @@ const handleLibrarySelect = (row: any) => {
librarySelectVisible.value = false
}
const formRef = ref<FormInstance|null>(null)
const formRef = ref<FormInstance | null>(null)
const validate = async () => {
const isValid = await formRef.value?.validate()
if (isValid) {

View File

@@ -31,6 +31,20 @@ export default {
confirmB: 'Confirm',
cancelB: 'Cancel',
selectText: 'Select',
// Added missing translations
operateFail: 'Operation failed',
operateSuccess: 'Operation successful',
success: 'Success',
noDataText: 'No data',
exportOkText: 'Export task submitted',
backBtn: 'Back',
saveBtn: 'Save',
closeBtn: 'Close',
submitBtn: 'Submit',
deleteMessage: {
confirm: 'Are you sure you want to delete the selected data?',
success: 'Delete successful',
},
},
message: {
box: {

View File

@@ -29,7 +29,21 @@ export default {
isRequired: '必填项',
confirmB: '确认',
cancelB: '取消',
selectText: '选择'
selectText: '选择',
// 新增缺失的翻译
operateFail: '操作失败',
operateSuccess: '操作成功',
success: '成功',
noDataText: '暂无数据',
exportOkText: '导出任务已提交',
backBtn: '返回',
saveBtn: '保存',
closeBtn: '关闭',
submitBtn: '提交',
deleteMessage: {
confirm: '确定删除选中数据吗?',
success: '删除成功',
},
},
message: {
box: {

View File

@@ -11,7 +11,7 @@ import 'element-plus/dist/index.css';
* @param flowId
* @returns 流程实例ID或错误
*/
const handleUserSelection = (process: any, params: any,flowId:string): Promise<{ processInstanceId: string }> => {
const handleUserSelection = (process: any, params: any, flowId: string): Promise<{ processInstanceId: string }> => {
if (!params.paramMap) params.paramMap = {};
// eslint-disable-next-line no-async-promise-executor
@@ -25,10 +25,10 @@ const handleUserSelection = (process: any, params: any,flowId:string): Promise<{
let isResolved = false;
// 将 timeout 声明移到函数开头
let timeout:any;
let timeout: any;
// 动态导入组件
const {default: EmployeesDialog} = await import("/@/components/OrgSelector/employeesDialog.vue");
const { default: EmployeesDialog } = await import("/@/components/OrgSelector/employeesDialog.vue");
// 创建应用实例
const app = createApp({
@@ -40,8 +40,8 @@ const handleUserSelection = (process: any, params: any,flowId:string): Promise<{
setTimeout(async () => {
destroy();
try {
const res = await startProcessDirectly(flowId, params);
resolve(res);
const res = await startProcessDirectly(flowId, params);
resolve(res);
} catch (err) {
reject(err);
}
@@ -102,7 +102,7 @@ const handleUserSelection = (process: any, params: any,flowId:string): Promise<{
* @param params 流程参数
* @returns 流程实例ID或错误
*/
export const flowFn = async (flowIdKey: string, params: { paramMap?: Record<string, any>, startUserId?: string, processInstanceId?: string }): Promise<{ processInstanceId: string } | Error> => {
export const flowFn = async (flowIdKey: string, params: { paramMap?: Record<string, any>, startUserId?: string, processInstanceId?: string }): Promise<{ processInstanceId: string }> => {
const flowStore = useGlobalFlowStore();
try {
@@ -117,7 +117,7 @@ export const flowFn = async (flowIdKey: string, params: { paramMap?: Record<stri
// 3. 检查是否是"发起人自选"节点
if (process.childNode.placeHolder === '发起人自选') {
return await handleUserSelection(process, params,flowId);
return await handleUserSelection(process, params, flowId);
}
// 4. 直接启动流程
@@ -163,7 +163,7 @@ const startProcessDirectly = async (
flowId: string,
params: { paramMap?: Record<string, any>, startUserId?: string, processInstanceId?: string }
): Promise<{ processInstanceId: string }> => {
if (!params.paramMap){
if (!params.paramMap) {
params.paramMap = {};
}
const res = await startFlow({ flowId, ...params });

View File

@@ -7,17 +7,12 @@
<!-- Steps Navigation -->
<div class="flex-2 text-center max-w-[600px]">
<span
v-for="(step, index) in steps"
:key="index"
class="inline-block px-5 py-2.5 cursor-pointer"
<span v-for="(step, index) in steps" :key="index" class="inline-block px-5 py-2.5 cursor-pointer"
:class="{ 'border-b-2 border-primary text-primary': activeStep === index }"
@click="activeStep = index"
>
@click="activeStep = index">
<span
class="mr-1.5 inline-block w-6 h-6 text-base font-normal text-center leading-[22px] border rounded-full"
:class="[activeStep === index ? 'bg-primary text-white' : 'border-current']"
>
:class="[activeStep === index ? 'bg-primary text-white' : 'border-current']">
{{ index + 1 }}
</span>
<span class="text-lg font-medium">{{ $t(step.title) }}</span>
@@ -47,18 +42,18 @@
<div class="text-center">
<!-- Success Result -->
<el-result v-if="validateFlowStep === 3" icon="success" :title="$t('flow.checkSuccess')" :sub-title="$t('flow.checkSubSuccess')">
<el-result v-if="validateFlowStep === 3" icon="success" :title="$t('flow.checkSuccess')"
:sub-title="$t('flow.checkSubSuccess')">
<template #extra>
<el-button type="primary" :loading="isSubmitting" @click="submitFlow">{{ $t('flow.submit') }}</el-button>
<el-button type="primary" :loading="isSubmitting" @click="submitFlow">{{ $t('flow.submit')
}}</el-button>
</template>
</el-result>
<!-- Loading Result -->
<el-result
v-if="validateErrMsg.length === 0 && validateDialogShow && validatingShow && validateFlowStep < 3"
:title="$t('flow.checkIng')"
:sub-title="$t('flow.checkSubIng')"
>
:title="$t('flow.checkIng')" :sub-title="$t('flow.checkSubIng')">
<template #icon>
<span class="inline-block w-25 h-25" v-loading="true"></span>
</template>
@@ -68,7 +63,9 @@
<el-result v-if="validateErrMsg.length > 0" icon="error" title="检查失败">
<template #sub-title>
<div v-for="item in validateErrMsg" :key="item" class="text-red-500">
<el-icon><WarnTriangleFilled /></el-icon>
<el-icon>
<WarnTriangleFilled />
</el-icon>
{{ item }}
</div>
</template>
@@ -97,7 +94,7 @@ const step1Ref = ref();
const step2Ref = ref();
const step3Ref = ref();
const validateErrMsg = ref([]);
const validateErrMsg = ref<string[]>([]);
const activeStep = ref(0);
const validateFlowStep = ref(0);
@@ -109,7 +106,7 @@ const gotoEdit = () => {
activeStep.value = validateFlowStep.value;
validateDialogShow.value = false;
};
const publish = (t) => {
const publish = (_t?: Event) => {
validateErrMsg.value = [];
validateFlowStep.value = 0;
@@ -176,7 +173,7 @@ let step3NodeConfig = reactive({});
var paramGroupId = ref();
const checkStep1 = () => {
step1Ref.value.validate(function (valid, arr) {
step1Ref.value.validate(function (valid: boolean, arr: string[]) {
if (valid) {
validateFlowStep.value = 1;
@@ -191,7 +188,7 @@ const checkStep1 = () => {
});
};
const checkStep2 = () => {
step2Ref.value.validate(function (valid, arr) {
step2Ref.value.validate(function (valid: boolean, arr: string[]) {
if (valid) {
setTimeout(function () {
validateFlowStep.value = 2;
@@ -207,7 +204,7 @@ const checkStep2 = () => {
const checkStep3 = () => {
setTimeout(function () {
step3Ref.value.validate(function (valid, arr) {
step3Ref.value.validate(function (valid: boolean, arr: string[]) {
if (valid) {
validateFlowStep.value = 3;
} else {

View File

@@ -1,13 +1,6 @@
<template>
<el-drawer
v-model="visible"
:append-to-body="true"
title="审批人设置"
:show-close="false"
:size="550"
:before-close="saveApprover"
@open="openEvent"
>
<el-drawer v-model="visible" :append-to-body="true" title="审批人设置" :show-close="false" :size="550"
:before-close="saveApprover" @open="openEvent">
<el-tabs type="border-card">
<el-tab-pane label="设置审批人">
<el-radio-group v-model="approverConfig.assignedType" class="ml-4" @change="assignedTypeChangeEvent">
@@ -26,23 +19,28 @@
<template v-if="approverConfig.assignedType === 3">
<h4>选择角色</h4>
<select-show v-model:orgList="approverConfig.nodeUserList" type="role" :multiple="true"></select-show>
<select-show v-model:orgList="approverConfig.nodeUserList" type="role"
:multiple="true"></select-show>
</template>
<template v-if="approverConfig.assignedType === 1">
<h4>选择成员</h4>
<select-show v-model:orgList="approverConfig.nodeUserList" type="user" :multiple="true"></select-show>
<select-show v-model:orgList="approverConfig.nodeUserList" type="user"
:multiple="true"></select-show>
</template>
<template v-if="approverConfig.assignedType === 8">
<h4>人员控件</h4>
<el-select v-model="approverConfig.formUserId" clearable class="m-2" placeholder="请选择审批表单" size="large">
<el-option v-for="item in step2FormUserList" :key="item.field" :label="item.title" :value="item.field" />
<el-select v-model="approverConfig.formUserId" clearable class="m-2" placeholder="请选择审批表单"
size="large">
<el-option v-for="item in step2FormUserList" :key="item.field" :label="item.title"
:value="item.field" />
</el-select>
</template>
<template v-if="approverConfig.assignedType === 7">
<h4>审批终点</h4>
<span style="margin-right: 5px; font-size: 14px">到第</span>
<el-input-number v-model="approverConfig.deptLeaderLevel" :step="1" :min="1" :max="20" step-strictly size="small" />
<el-input-number v-model="approverConfig.deptLeaderLevel" :step="1" :min="1" :max="20" step-strictly
size="small" />
<span style="margin-left: 5px; font-size: 14px">级部门主管终止</span>
</template>
<template v-if="approverConfig.assignedType === 4">
@@ -52,17 +50,15 @@
<el-radio :label="true" size="large">多选</el-radio>
</el-radio-group>
</template>
<template
v-if="
((approverConfig.multiple === true && approverConfig.assignedType === 4) ||
(approverConfig.assignedType === 1 && approverConfig.nodeUserList.length > 1) ||
approverConfig.assignedType === 2 ||
approverConfig.assignedType === 3 ||
(approverConfig.assignedType === 7 && approverConfig.deptLeaderLevel > 1) ||
(approverConfig.assignedType === 8 && isMultiUserForm(approverConfig.formUserId))) &&
approverConfig.assignedType !== 5
"
>
<template v-if="
((approverConfig.multiple === true && approverConfig.assignedType === 4) ||
(approverConfig.assignedType === 1 && approverConfig.nodeUserList.length > 1) ||
approverConfig.assignedType === 2 ||
approverConfig.assignedType === 3 ||
(approverConfig.assignedType === 7 && (approverConfig.deptLeaderLevel ?? 0) > 1) ||
(approverConfig.assignedType === 8 && isMultiUserForm(approverConfig.formUserId))) &&
![5, 6].includes(approverConfig.assignedType ?? 0)
">
<h4>多人审批时采用的审批方式</h4>
<el-radio-group v-model="approverConfig.multipleMode" class="ml-4">
<p style="display: block; width: 100%">
@@ -79,19 +75,16 @@
<el-divider />
<h4>审批人为空时</h4>
<el-radio-group v-model="approverConfig.nobody.handler" class="ml-4">
<el-radio-group v-model="approverConfig.nobody!.handler" class="ml-4">
<el-radio label="TO_PASS" size="large">自动通过</el-radio>
<el-radio label="TO_REFUSE" size="large">自动拒绝</el-radio>
<el-radio label="TO_END" size="large">自动结束</el-radio>
<el-radio label="TO_ADMIN" size="large">转交给管理员</el-radio>
<el-radio label="TO_USER" size="large">指定人员</el-radio>
</el-radio-group>
<select-show
v-if="approverConfig?.nobody.handler === 'TO_USER'"
v-model:orgList="approverConfig.nobody.assignedUser"
type="user"
:multiple="false"
></select-show>
<select-show v-if="approverConfig.nobody?.handler === 'TO_USER'"
v-model:orgList="approverConfig.nobody!.assignedUser" type="user"
:multiple="approverConfig.assignedType === 4 ? (approverConfig.multiple ?? false) : false"></select-show>
<el-divider />
@@ -101,12 +94,8 @@
<el-radio label="TO_END" size="large">直接结束流程</el-radio>
<el-radio label="TO_NODE" size="large" v-if="rejectNodeList.length > 0">驳回到指定节点</el-radio>
</el-radio-group>
<el-select
v-if="approverConfig.refuse.handler === 'TO_NODE' && rejectNodeList.length > 0"
v-model="approverConfig.refuse.nodeId"
placeholder="驳回节点"
class="mb-2 w-1/2"
>
<el-select v-if="approverConfig.refuse.handler === 'TO_NODE' && rejectNodeList.length > 0"
v-model="approverConfig.refuse.nodeId" placeholder="驳回节点" class="mb-2 w-1/2">
<el-option v-for="item in rejectNodeList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</template>
@@ -121,7 +110,9 @@
</el-drawer>
</template>
<script setup lang="ts">
// @ts-ignore
import { setTypes } from '../../utils/const';
// @ts-ignore
import { useStore } from '../../stores/index';
import { useFlowStore } from '../../stores/flow';
import FormPerm from './components/formPerm.vue';
@@ -130,6 +121,37 @@ import selectShow from '/@/components/OrgSelector/index.vue';
import { validateNull } from '/@/utils/validate';
import other from '/@/utils/other';
import { processFormItemsWithPerms } from '/@/views/flow/workflow/utils/formPermissions';
import { ref, computed, watch } from 'vue';
// 定义 ApproverConfig 接口
interface NodeUser {
id: string | number;
name: string;
type?: string;
}
interface ApproverConfig {
id?: string;
assignedType?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8;
nodeUserList: NodeUser[];
formUserId?: string;
formUserName?: string;
deptLeaderLevel?: number;
multiple?: boolean;
multipleMode?: number;
nobody?: {
handler: string;
assignedUser: NodeUser[];
};
refuse?: {
handler: string;
nodeId?: string;
};
formPerms?: Record<string, string>;
eventConfig?: any;
operList?: { checked: boolean }[];
error?: boolean;
}
let flowStore = useFlowStore();
@@ -141,14 +163,14 @@ const processFormPermissions = () => {
// 驳回节点列表
const rejectNodeList = computed(() => {
let values = [];
let values: { id: string; name: string }[] = [];
const excType = [1];
const arr = {};
const obj = {};
const arr: Record<string, any[]> = {};
const obj: Record<string, any> = {};
produceSerialNodeList(undefined, flowStore.step3, arr, obj, true);
const k = arr[approverConfig.value.id];
const k = approverConfig.value.id ? arr[approverConfig.value.id] : undefined;
if (k == undefined) {
return [];
@@ -163,7 +185,7 @@ const rejectNodeList = computed(() => {
return values;
});
function produceSerialNodeList(parentId, process, nodeArr, nodeObj, noBranch) {
function produceSerialNodeList(parentId: any, process: any, nodeArr: Record<string, any[]>, nodeObj: Record<string, any>, noBranch: boolean) {
if (validateNull(process?.id)) {
return;
}
@@ -181,7 +203,7 @@ function produceSerialNodeList(parentId, process, nodeArr, nodeObj, noBranch) {
if ((parentType == 5 || parentType == 8) && !noBranch) {
nodeArr[nodeId] = [];
} else {
const arr1 = other.deepClone(p);
const arr1 = other.deepClone(p) as any[];
arr1.push(nodeId);
nodeArr[nodeId] = arr1;
}
@@ -211,7 +233,7 @@ const step2FormList = computed(() => {
});
const step2FormUserList = computed(() => {
return step2FormList.value.filter((res) => res.type === 'OrgSelector' && res.props?.type === 'user');
return step2FormList.value.filter((res: any) => res.type === 'OrgSelector' && res.props?.type === 'user');
});
const openEvent = () => {
@@ -232,7 +254,7 @@ const openEvent = () => {
// 这里可以进一步使用处理后的表单项
};
let approverConfig = ref({});
let approverConfig = ref<ApproverConfig>({ nodeUserList: [] });
let store = useStore();
let { setApproverConfig, setApprover } = store;
@@ -250,18 +272,18 @@ watch(approverConfigData, (val) => {
approverConfig.value = val.value;
});
//用户表单是否是多选
const isMultiUserForm = (id) => {
const isMultiUserForm = (id: any) => {
if (!id) {
return false;
}
return step2FormUserList.value.filter((res) => res.id === id)[0]?.props.multiple;
return step2FormUserList.value.filter((res: any) => res.id === id)[0]?.props.multiple;
};
//监听用户选择表单值变化
watch(
() => approverConfig.value.formUserId,
(val) => {
if (val) {
approverConfig.value.formUserName = step2FormUserList.value.filter((res) => res.field === val)[0].field;
approverConfig.value.formUserName = step2FormUserList.value.filter((res: any) => res.field === val)[0].field;
}
}
);
@@ -284,13 +306,13 @@ const closeDrawer = () => {
setApprover(false);
};
const checkApproval = (nodeConfig) => {
const checkApproval = (nodeConfig: ApproverConfig) => {
if (nodeConfig.assignedType == 1 || nodeConfig.assignedType == 3) {
//指定成员
if (nodeConfig.nodeUserList.length == 0) {
return false;
}
} else if (nodeConfig.assignedType == 8 && nodeConfig.formUserId.length == 0) {
} else if (nodeConfig.assignedType == 8 && (nodeConfig.formUserId?.length ?? 0) == 0) {
//表单
return false;
}

View File

@@ -24,18 +24,19 @@
</el-card>
<el-card shadow="never" class="header-card">
<el-form :model="headerForm" label-width="90px" class="header-form" :rules="headerRequiredRule" ref="headerFormRef">
<el-form :model="headerForm" label-width="90px" class="header-form" :rules="headerRequiredRule"
ref="headerFormRef">
<el-form-item :label="t('mixedRegister.header.title')" prop="title">
<el-input maxlength="255" v-model="headerForm.title"
:placeholder="t('mixedRegister.header.titlePlaceholder')"/>
:placeholder="t('mixedRegister.header.titlePlaceholder')" />
</el-form-item>
<el-form-item :label="t('mixedRegister.header.description')">
<el-input maxlength="255" v-model="headerForm.description"
:placeholder="t('mixedRegister.header.descriptionPlaceholder')"/>
:placeholder="t('mixedRegister.header.descriptionPlaceholder')" />
</el-form-item>
<el-form-item :label="t('mixedRegister.header.attachments')" class="upload-item">
<UploadFile :modelValue="headerForm.attachments" :fileSize="20" type="simple" :limit="10"
@change="(url: string, files: any[]) => (headerForm.attachments = files?.map((item: any) => ({ name: item.name, url: item.url })) || [])"/>
@change="(url: string, files: any[]) => (headerForm.attachments = files?.map((item: any) => ({ name: item.name, url: item.url })) || [])" />
</el-form-item>
</el-form>
</el-card>
@@ -43,20 +44,19 @@
<div class="page-title">{{ isUpdate ? t('mixedRegister.updateTitle') : t('mixedRegister.title') }}</div>
<MixedRegisterSections ref="formRef" :instruction-title="t('mixedRegister.sections.instruction')"
:basic-info-title="t('mixedRegister.sections.basic')"
:instruction-fields="instructionFields"
:instruction-form="instructionForm" :basic-info-fields="basicInfoFields"
:basic-info-form="basicInfoForm" :is-update="isUpdate"/>
:basic-info-title="t('mixedRegister.sections.basic')" :instruction-fields="instructionFields"
:instruction-form="instructionForm" :basic-info-fields="basicInfoFields"
:basic-info-form="basicInfoForm" :is-update="isUpdate" />
</div>
<templateTable/>
<templateTable />
</div>
</template>
<script setup lang="ts">
import {computed, reactive, ref, watch} from 'vue';
import {useI18n} from 'vue-i18n';
import {useMessage} from '/@/hooks/message';
import {addMixedReformAPI,getMixedReformByTemplateIdAPI, type MixedReformPayload} from '/@/api/investment/mixedReform';
import { computed, reactive, ref, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import { useMessage } from '/@/hooks/message';
import { addMixedReformAPI, getMixedReformByTemplateIdAPI, type MixedReformPayload } from '/@/api/investment/mixedReform';
import MixedRegisterSections from '/@/components/investment/mixedReform/MixedRegisterSections.vue';
import templateTable from "/@/components/templetTableComom/index.vue"
import {
@@ -69,11 +69,11 @@ import {
mixedReformMethodOptions,
mixedReformTypeOptions, recommended, yesOrNo
} from '/@/hooks/enums'
import {flowFn} from "/@/utils/flowFn";
import {addFlowForm} from '/@/api/flow/flow';
import {addTemplate, getMixedReformUserBelong} from "/@/api/common";
import type {FormInstance, FormRules} from "element-plus";
import {templateStore} from "/@/stores/template";
import { flowFn } from "/@/utils/flowFn";
import { addFlowForm } from '/@/api/flow/flow';
import { addTemplate, getMixedReformUserBelong } from "/@/api/common";
import type { FormInstance, FormRules } from "element-plus";
import { templateStore } from "/@/stores/template";
const temp = templateStore();
const props = defineProps({
@@ -83,7 +83,7 @@ const props = defineProps({
}
})
const {t} = useI18n();
const { t } = useI18n();
const message = useMessage();
const submitLoading = ref(false);
const formRef = ref<any>(null)
@@ -102,7 +102,7 @@ const initInstructionForm = {
contactPerson: '',
contactPhone: '',
}
const instructionForm = reactive({...initInstructionForm});
const instructionForm = reactive({ ...initInstructionForm });
const initBasicInfoForm = {
groupBelonging: '',
@@ -125,86 +125,86 @@ const initBasicInfoForm = {
mixedCompanyField: '',
industryChainCategory: ''
}
const basicInfoForm = reactive({...initBasicInfoForm});
const basicInfoForm = reactive({ ...initBasicInfoForm });
type InstructionFieldKey = keyof typeof instructionForm;
type BasicFieldKey = keyof typeof basicInfoForm;
const instructionFields = computed<Array<{ key: InstructionFieldKey; label: string }>>(() => [
{key: 'reportingUnit', label: t('mixedRegister.instructionFields.reportUnit')},
{key: 'contactPerson', label: t('mixedRegister.instructionFields.contact')},
{key: 'contactPhone', label: t('mixedRegister.instructionFields.contactMethod')},
{ key: 'reportingUnit', label: t('mixedRegister.instructionFields.reportUnit') },
{ key: 'contactPerson', label: t('mixedRegister.instructionFields.contact') },
{ key: 'contactPhone', label: t('mixedRegister.instructionFields.contactMethod') },
]);
const basicInfoFields = computed<Array<{ key: BasicFieldKey; label: string }>>(() => [
{key: 'groupBelonging', label: t('mixedRegister.basicFields.groupName')},
{key: 'projectYear', label: t('mixedRegister.basicFields.year')},
{key: 'projectName', label: t('mixedRegister.basicFields.projectName')},
{key: 'implementEnterprise', label: t('mixedRegister.basicFields.companyFullName')},
{key: 'enterpriseCreditCode', label: t('mixedRegister.basicFields.creditCode')},
{ key: 'groupBelonging', label: t('mixedRegister.basicFields.groupName') },
{ key: 'projectYear', label: t('mixedRegister.basicFields.year'), type: 'year', fieldProps: { valueFormat: 'YYYY' } },
{ key: 'projectName', label: t('mixedRegister.basicFields.projectName') },
{ key: 'implementEnterprise', label: t('mixedRegister.basicFields.companyFullName') },
{ key: 'enterpriseCreditCode', label: t('mixedRegister.basicFields.creditCode') },
{
key: 'partnerNature',
label: t('mixedRegister.basicFields.partnerNature'),
type: 'select',
fieldProps: {options: cooperationPartnerNatureOptions}
fieldProps: { options: cooperationPartnerNatureOptions }
},
{key: 'partnerName', label: t('mixedRegister.basicFields.partnerName')},
{key: 'progressStatus', label: t('mixedRegister.basicFields.progressStatus'),type: 'select',fieldProps: {options: recommended}},
{ key: 'partnerName', label: t('mixedRegister.basicFields.partnerName') },
{ key: 'progressStatus', label: t('mixedRegister.basicFields.progressStatus'), type: 'select', fieldProps: { options: recommended } },
{
key: 'estimatedCompletionTime',
label: t('mixedRegister.basicFields.expectedFinishTime'),
type: 'date',
fieldProps: {valueFormat: 'YYYY-MM-DD'}
fieldProps: { valueFormat: 'YYYY-MM-DD' }
},
{
key: 'mixedReformMethod',
label: t('mixedRegister.basicFields.mixedMode'),
type: 'select',
fieldProps: {options: mixedReformMethodOptions}
fieldProps: { options: mixedReformMethodOptions }
},
{key: 'isIndustryLeader', label: t('mixedRegister.basicFields.isIndustryBenchmark'),type: 'select',fieldProps: {options: yesOrNo}},
{ key: 'isIndustryLeader', label: t('mixedRegister.basicFields.isIndustryBenchmark'), type: 'select', fieldProps: { options: yesOrNo } },
{
key: 'mixedReformType',
label: t('mixedRegister.basicFields.mixedType'),
type: 'select',
fieldProps: {options: mixedReformTypeOptions}
fieldProps: { options: mixedReformTypeOptions }
},
{
key: 'projectStartTime',
label: t('mixedRegister.basicFields.projectStartTime'),
type: 'date',
fieldProps: {valueFormat: 'YYYY-MM-DD'}
fieldProps: { valueFormat: 'YYYY-MM-DD' }
},
{
key: 'actualCompletionTime',
label: t('mixedRegister.basicFields.completionTime'),
type: 'date',
fieldProps: {valueFormat: 'YYYY-MM-DD'}
fieldProps: { valueFormat: 'YYYY-MM-DD' }
},
{key: 'reformProgress', label: t('mixedRegister.basicFields.reformProgress'), span: 24,type: 'number',length: 20},
{ key: 'reformProgress', label: t('mixedRegister.basicFields.reformProgress'), span: 24, type: 'number', length: 20 },
{
key: 'mixedCompanyCategory',
label: t('mixedRegister.basicFields.mixedCompanyCategory'),
type: 'select',
fieldProps: {options: mixedCompanyCategoryOptions}
fieldProps: { options: mixedCompanyCategoryOptions }
},
{
key: 'mixedCompanyIndustry',
label: t('mixedRegister.basicFields.mixedCompanyIndustry'),
type: 'select',
fieldProps: {options: mixedCompanyIndustryOptions, filterable: true}
fieldProps: { options: mixedCompanyIndustryOptions, filterable: true }
},
{
key: 'mixedCompanyField',
label: t('mixedRegister.basicFields.mixedCompanyField'),
type: 'select',
fieldProps: {options: mixedCompanyFieldOptions}
fieldProps: { options: mixedCompanyFieldOptions }
},
{
key: 'industryChainCategory',
label: t('mixedRegister.basicFields.industryChainCategory'),
type: 'select',
fieldProps: {options: industryChainCategoryOptions, filterable: true}
fieldProps: { options: industryChainCategoryOptions, filterable: true }
}
]);
@@ -233,7 +233,7 @@ const handleSubmit = async () => {
flowIdKey = 'VITE_FLOWID_16'
}
}
const {processInstanceId} = await flowFn(flowIdKey, {
const { processInstanceId } = await flowFn(flowIdKey, {
paramMap: {},
})
const flowName = isUpdate ? 'mixedReformUpdate' : 'mixedReformRegistration'
@@ -245,7 +245,7 @@ const handleSubmit = async () => {
processInstanceId,
flowType: flowNameObj.value,
})
Object.assign(formData, {processInstanceId,status:1})
Object.assign(formData, { processInstanceId, status: 1 })
await addMixedReformAPI(formData);
message.success(t('mixedRegister.messages.submitSuccess'));
// 重置表单
@@ -274,18 +274,20 @@ const handleSaveDraft = async () => {
title: headerForm.title,
description: headerForm.description,
attachments: JSON.stringify(headerForm.attachments),
processInstanceId:'',
processInstanceId: '',
flowType: flowNameObj.value
})
Object.assign(formData, {status:0,temporaryStorage:{
businessType:flowNameObj.value,
title:headerForm.title,
}})
Object.assign(formData, {
status: 0, temporaryStorage: {
businessType: flowNameObj.value,
title: headerForm.title,
}
})
await addMixedReformAPI(formData);
message.success(t('mixedRegister.messages.submitSuccess') || '提交成功');
}catch (error: any){
} catch (error: any) {
message.error(error?.msg || error?.message || t('common.fail') || '提交失败');
}finally {
} finally {
saveLoading.value = false;
}
};
@@ -295,7 +297,7 @@ const handleLoadTemplate = () => {
const isUpdate = props.isUpdate;
const flowName = isUpdate ? 'mixedReformUpdate' : 'mixedReformRegistration'
const flowNameObj = flowNameOptions.filter(item => item.label === flowName)[0]
temp.changeTempShow(true,flowNameObj.value)
temp.changeTempShow(true, flowNameObj.value)
};
const saveTemplateLoading = ref(false);
const handleSaveTemplate = async () => {
@@ -310,13 +312,13 @@ const handleSaveTemplate = async () => {
const isUpdate = props.isUpdate;
const flowName = isUpdate ? 'mixedReformUpdate' : 'mixedReformRegistration'
const flowNameObj = flowNameOptions.filter(item => item.label === flowName)[0]
const {data: templateId}= await addTemplate({templateName:headerForm.title,templateType:flowNameObj.value})
Object.assign(formData, {status:0,templateId})
const { data: templateId } = await addTemplate({ templateName: headerForm.title, templateType: flowNameObj.value })
Object.assign(formData, { status: 0, templateId })
await addMixedReformAPI(formData);
message.success(t('mixedRegister.messages.submitSuccess'));
}catch (error: any) {
} catch (error: any) {
message.error(error?.msg || error?.message || t('common.fail'));
}finally {
} finally {
saveTemplateLoading.value = false;
}
};
@@ -324,7 +326,7 @@ const handleSaveTemplate = async () => {
const handleViewWorkflow = () => {
message.info(t('mixedRegister.messages.viewWorkflow'));
};
watch(() => tempId.value,()=>{
watch(() => tempId.value, () => {
getMixedReformByTemplateIdAPI(tempId.value).then(data => {
Object.assign(basicInfoForm, data.data);
Object.assign(instructionForm, {