feat: 新增投资项目退出反馈、进度报告、计划申请及退出计划等管理功能模块及相关组件

This commit is contained in:
2025-12-27 01:11:47 +08:00
parent b29d128e41
commit 915cb66b40
11 changed files with 968 additions and 684 deletions

View File

@@ -5,11 +5,12 @@
<div class="form-meta"> <div class="form-meta">
<div class="meta-item"> <div class="meta-item">
<span>{{ t('projectExitPlan.form.applyDepartmentLabel') }}</span> <span>{{ t('projectExitPlan.form.applyDepartmentLabel') }}</span>
<el-input v-model="formData.applicationDept" size="small" :placeholder="t('projectExitPlan.placeholder.input')" /> <el-input v-model="formData.applicationDept" size="small"
:placeholder="t('projectExitPlan.placeholder.input')" />
</div> </div>
<div class="meta-item"> <div class="meta-item">
<span>{{ t('projectExitPlan.form.applyDateLabel') }}</span> <span>{{ t('projectExitPlan.form.applyDateLabel') }}</span>
<span>{{new Date().toLocaleDateString('zh-CN')}}</span> <span>{{ new Date().toLocaleDateString('zh-CN') }}</span>
</div> </div>
</div> </div>
</div> </div>
@@ -20,7 +21,8 @@
<div class="table-cell label">{{ t('projectExitPlan.form.projectName') }}</div> <div class="table-cell label">{{ t('projectExitPlan.form.projectName') }}</div>
</template> </template>
<div class="table-cell value project-name-cell"> <div class="table-cell value project-name-cell">
<el-input v-model="formData.projectName" :placeholder="t('projectExitPlan.form.projectNamePlaceholder')" readonly> <el-input v-model="formData.projectName"
:placeholder="t('projectExitPlan.form.projectNamePlaceholder')" readonly>
<template #suffix> <template #suffix>
<el-icon class="cursor-pointer interactive-icon" @click="handleSelectProject"> <el-icon class="cursor-pointer interactive-icon" @click="handleSelectProject">
<FolderOpened /> <FolderOpened />
@@ -38,7 +40,8 @@
<div class="table-cell label">{{ t('projectExitPlan.form.exitSuggestion') }}</div> <div class="table-cell label">{{ t('projectExitPlan.form.exitSuggestion') }}</div>
</template> </template>
<div class="table-cell value"> <div class="table-cell value">
<el-input v-model="formData.exitRecommendation" :placeholder="t('projectExitPlan.placeholder.input')" /> <el-input v-model="formData.exitRecommendation"
:placeholder="t('projectExitPlan.placeholder.input')" />
</div> </div>
</el-form-item> </el-form-item>
@@ -65,7 +68,8 @@
<div class="table-cell label">{{ t('projectExitPlan.form.taskDescription') }}</div> <div class="table-cell label">{{ t('projectExitPlan.form.taskDescription') }}</div>
</template> </template>
<div class="table-cell value"> <div class="table-cell value">
<el-input v-model="formData.taskDescription" type="textarea" :rows="1" :placeholder="t('projectExitPlan.placeholder.input')" /> <el-input v-model="formData.taskDescription" type="textarea" :rows="1"
:placeholder="t('projectExitPlan.placeholder.input')" />
</div> </div>
</el-form-item> </el-form-item>
@@ -74,8 +78,10 @@
<div class="table-cell label">{{ t('projectExitPlan.form.executor') }}</div> <div class="table-cell label">{{ t('projectExitPlan.form.executor') }}</div>
</template> </template>
<div class="table-cell value"> <div class="table-cell value">
<el-select v-model="formData.executor" clearable :placeholder="t('projectExitPlan.form.executorPlaceholder')"> <el-select v-model="formData.executor" clearable
<el-option :label="t('projectExitPlan.form.executorPlaceholder')" value="executor-placeholder" /> :placeholder="t('projectExitPlan.form.executorPlaceholder')">
<el-option :label="t('projectExitPlan.form.executorPlaceholder')"
value="executor-placeholder" />
</el-select> </el-select>
</div> </div>
</el-form-item> </el-form-item>
@@ -85,23 +91,13 @@
<div class="table-cell label">{{ t('projectExitPlan.form.taskStartTime') }}</div> <div class="table-cell label">{{ t('projectExitPlan.form.taskStartTime') }}</div>
</template> </template>
<div class="table-cell value"> <div class="table-cell value">
<el-date-picker <el-date-picker v-model="formData.taskStartDate" type="date" value-format="YYYY-MM-DD"
v-model="formData.taskStartDate" :placeholder="t('projectExitPlan.placeholder.select')" style="width: 100%" />
type="date"
value-format="YYYY-MM-DD"
:placeholder="t('projectExitPlan.placeholder.select')"
style="width: 100%"
/>
</div> </div>
<div class="table-cell label">{{ t('projectExitPlan.form.taskEndTime') }}</div> <div class="table-cell label">{{ t('projectExitPlan.form.taskEndTime') }}</div>
<div class="table-cell value"> <div class="table-cell value">
<el-date-picker <el-date-picker v-model="formData.taskEndDate" type="date" value-format="YYYY-MM-DD"
v-model="formData.taskEndDate" :placeholder="t('projectExitPlan.placeholder.select')" style="width: 100%" />
type="date"
value-format="YYYY-MM-DD"
:placeholder="t('projectExitPlan.placeholder.select')"
style="width: 100%"
/>
</div> </div>
</el-form-item> </el-form-item>
</el-form> </el-form>
@@ -117,31 +113,39 @@
</el-form-item> </el-form-item>
</el-form> </el-form>
</template> </template>
<el-table :data="tableData" style="width: 100%" height="50vh" highlight-current-row border @current-change="handleSelectionChange"> <el-table :data="tableData" style="width: 100%" height="50vh" highlight-current-row border
@current-change="handleSelectionChange">
<el-table-column label="选择" width="80"> <el-table-column label="选择" width="80">
<template #default="scope"> <template #default="scope">
<div class="options" :class="active === scope.$index ? 'active' : ''"></div> <div class="options" :class="active === scope.$index ? 'active' : ''"></div>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="projectName" :label="t('projectLibrary.table.projectName')" min-width="200" /> <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="projectStartTime" :label="t('projectLibrary.table.projectImplementationStart')"
min-width="160" />
<el-table-column prop="projectNature" :label="t('projectLibrary.table.projectNature')" min-width="140"> <el-table-column prop="projectNature" :label="t('projectLibrary.table.projectNature')" min-width="140">
<template #default="{ row }"> <template #default="{ row }">
{{ projectNatureOptions.find((item: Enums) => item.value === row.projectNature)?.label }} {{projectNatureOptions.find((item: Enums) => item.value === row.projectNature)?.label}}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="projectOwnerUnit" :label="t('projectLibrary.table.projectOwnerUnit')" min-width="200" /> <el-table-column prop="projectOwnerUnit" :label="t('projectLibrary.table.projectOwnerUnit')"
min-width="200" />
<el-table-column prop="" label="项目实施单位" /> <el-table-column prop="" label="项目实施单位" />
<el-table-column prop="projectInvestmentDirection" :label="t('projectLibrary.table.projectDirection')" min-width="160" /> <el-table-column prop="projectInvestmentDirection" :label="t('projectLibrary.table.projectDirection')"
<el-table-column prop="mainBusinessTypes" :label="t('planApply.applySection.mainBusinessType')" min-width="160"> min-width="160" />
<el-table-column prop="mainBusinessTypes" :label="t('planApply.applySection.mainBusinessType')"
min-width="160">
<template #default="{ row }"> <template #default="{ row }">
{{ mainBusinessOptions.find((item: Enums) => item.value === row.mainBusinessTypes)?.label }} {{mainBusinessOptions.find((item: Enums) => item.value === row.mainBusinessTypes)?.label}}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="constructionStage" :label="t('projectLibrary.table.constructionStage')" min-width="120" /> <el-table-column prop="constructionStage" :label="t('projectLibrary.table.constructionStage')"
<el-table-column prop="investmentCategory" :label="t('projectLibrary.table.investmentCategory')" min-width="140"> min-width="120" />
<el-table-column prop="investmentCategory" :label="t('projectLibrary.table.investmentCategory')"
min-width="140">
<template #default="{ row }"> <template #default="{ row }">
{{ investmentCategoryOptions.find((item: Enums) => item.value === row.investmentCategory)?.label }} {{investmentCategoryOptions.find((item: Enums) => item.value === row.investmentCategory)?.label
}}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="" label="操作" fixed="right" width="100"> <el-table-column prop="" label="操作" fixed="right" width="100">
@@ -151,16 +155,10 @@
</el-table-column> </el-table-column>
</el-table> </el-table>
<div class="mt15 flex justify-end pagination-wrapper"> <div class="mt15 flex justify-end pagination-wrapper">
<el-pagination <el-pagination background layout="sizes, prev, pager, next, jumper, total" :total="total"
background :page-sizes="[10, 20, 50, 100]" v-model:page-size="queryForm.size"
layout="sizes, prev, pager, next, jumper, total" v-model:current-page="queryForm.page" @size-change="handlePageSizeChange"
:total="total" @current-change="handlePageChange" />
: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> </div>
<template #footer> <template #footer>
<el-button type="primary" @click="tableSubmit">确定</el-button> <el-button type="primary" @click="tableSubmit">确定</el-button>
@@ -190,7 +188,7 @@ const visible = ref<boolean>(false);
const visible2 = ref<boolean>(false); const visible2 = ref<boolean>(false);
const props = defineProps<{ const props = defineProps<{
modelValue?: ProjectTask; modelValue?: ProjectTask;
rules:FormRules; rules: FormRules;
}>(); }>();
const useForm = ref<FormInstance | undefined>(); const useForm = ref<FormInstance | undefined>();
const emit = defineEmits<{ const emit = defineEmits<{
@@ -202,11 +200,11 @@ const defaultForm: ProjectTask = {
projectName: '', projectName: '',
projectId: undefined, projectId: undefined,
exitRecommendation: '', exitRecommendation: '',
executionTask:'', executionTask: '',
taskDescription:'', taskDescription: '',
executor:'', executor: '',
taskStartDate:new Date().toISOString().substring(0,10), taskStartDate: new Date().toISOString().substring(0, 10),
taskEndDate:new Date().toISOString().substring(0,10), taskEndDate: new Date().toISOString().substring(0, 10),
}; };
const formData = reactive<ProjectTask>({ ...defaultForm, ...props.modelValue }); const formData = reactive<ProjectTask>({ ...defaultForm, ...props.modelValue });
@@ -238,17 +236,17 @@ const handlePageChange = (page: number) => {
getListOfProjects(); getListOfProjects();
}; };
getListOfProjects(); getListOfProjects();
const getListSearch = () =>{ const getListSearch = () => {
queryForm.value.page = 1; queryForm.value.page = 1;
getListOfProjects(); getListOfProjects();
} }
const handleReset = () =>{ const handleReset = () => {
queryForm.value.projectName = ''; queryForm.value.projectName = '';
} }
watch( watch(
formData, formData,
(newVal) => { (newVal) => {
console.log(newVal,'formData'); console.log(newVal, 'formData');
emit('update:modelValue', { ...newVal }); emit('update:modelValue', { ...newVal });
}, },
{ deep: true } { deep: true }
@@ -258,7 +256,7 @@ watch(
() => props.modelValue, () => props.modelValue,
(newVal) => { (newVal) => {
if (newVal) { if (newVal) {
console.log(newVal,'asdas'); console.log(newVal, 'asdas');
Object.assign(formData, newVal); Object.assign(formData, newVal);
} }
}, },
@@ -371,9 +369,11 @@ defineExpose({
.table-cell.value { .table-cell.value {
flex: 1; flex: 1;
} }
.table-row { .table-row {
margin: 0; margin: 0;
} }
.table-row.two-columns .table-cell.label { .table-row.two-columns .table-cell.label {
width: 160px; width: 160px;
} }
@@ -405,6 +405,7 @@ defineExpose({
.exit-plan-table :deep(.el-date-editor) { .exit-plan-table :deep(.el-date-editor) {
width: 100%; width: 100%;
} }
.options { .options {
width: 20px; width: 20px;
height: 20px; height: 20px;
@@ -412,6 +413,7 @@ defineExpose({
border: 1px solid var(--el-border-color); border: 1px solid var(--el-border-color);
border-radius: 50%; border-radius: 50%;
} }
.active { .active {
background-color: var(--el-color-primary); background-color: var(--el-color-primary);
color: white; color: white;
@@ -421,6 +423,7 @@ defineExpose({
height: 100%; height: 100%;
position: relative; position: relative;
} }
:deep(.el-form-item__label:before) { :deep(.el-form-item__label:before) {
left: 4px; left: 4px;
position: absolute; position: absolute;

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,8 @@
<template> <template>
<el-row class="page-title-row mb10"> <el-row class="page-title-row mb10">
<div class="page-title">{{ title ? title : t('progressReport.form.title') }}</div> <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-report-time">{{ t('progressReport.form.reportTime') }}: {{ formData.createTime || reportTime }}
</div>
<div class="page-unit">{{ t('progressReport.form.unit') }}</div> <div class="page-unit">{{ t('progressReport.form.unit') }}</div>
</el-row> </el-row>
<div class="project-progress-report-form"> <div class="project-progress-report-form">
@@ -10,55 +11,60 @@
<el-row :gutter="20" class="form-row"> <el-row :gutter="20" class="form-row">
<el-col :span="24"> <el-col :span="24">
<el-form-item :label="t('progressReport.form.projectName')" required prop="projectName"> <el-form-item :label="t('progressReport.form.projectName')" required prop="projectName">
<span>{{formData.projectName }}</span> <span>{{ formData.projectName }}</span>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-row :gutter="20" class="form-row"> <el-row :gutter="20" class="form-row">
<el-col :span="12"> <el-col :span="12">
<el-form-item :label="t('progressReport.form.projectStatus')" required prop="projectStatus"> <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> <span v-for="item in projectStatusOptions" :key="item.value">{{ formData.projectStatus ==
item.value ? item.label : '' }}</span>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item :label="t('progressReport.form.constructionStage')"> <el-form-item :label="t('progressReport.form.constructionStage')">
<span v-for="item in constructionStageOptions" :key="item.value">{{formData.constructionStage == item.value ? item.label : ''}}</span> <span v-for="item in constructionStageOptions" :key="item.value">{{ formData.constructionStage
==
item.value ? item.label : '' }}</span>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-row :gutter="20" class="form-row"> <el-row :gutter="20" class="form-row">
<el-col :span="12"> <el-col :span="12">
<el-form-item :label="t('progressReport.form.projectImplementationUnit')"> <el-form-item :label="t('progressReport.form.projectImplementationUnit')">
<span>{{formData.implementingBody}}</span> <span>{{ formData.implementingBody }}</span>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item :label="t('progressReport.form.totalInvestmentAmount')" required prop="projectTotalAmount"> <el-form-item :label="t('progressReport.form.totalInvestmentAmount')" required
<span>{{formData.projectTotalAmount }}</span> prop="projectTotalAmount">
<span>{{ formData.projectTotalAmount }}</span>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-row :gutter="20" class="form-row"> <el-row :gutter="20" class="form-row">
<el-col :span="12"> <el-col :span="12">
<el-form-item :label="t('progressReport.form.cumulativeInvestmentToMonthEnd')" required prop="cumulativeInvestmentToDate"> <el-form-item :label="t('progressReport.form.cumulativeInvestmentToMonthEnd')" required
<span>{{formData.cumulativeInvestmentToDate}}</span> prop="cumulativeInvestmentToDate">
<span>{{ formData.cumulativeInvestmentToDate }}</span>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item :label="t('progressReport.form.completionRate')" required prop="completionRate"> <el-form-item :label="t('progressReport.form.completionRate')" required prop="completionRate">
<span>{{formData.completionRate}}</span> <span>{{ formData.completionRate }}</span>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-row :gutter="20" class="form-row"> <el-row :gutter="20" class="form-row">
<el-col :span="12"> <el-col :span="12">
<el-form-item :label="t('progressReport.form.cumulativePaymentToMonthEnd')"> <el-form-item :label="t('progressReport.form.cumulativePaymentToMonthEnd')">
<span>{{formData.cumulativePaymentToDate}}</span> <span>{{ formData.cumulativePaymentToDate }}</span>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item :label="t('progressReport.form.paymentCompletionRate')"> <el-form-item :label="t('progressReport.form.paymentCompletionRate')">
<span>{{formData.paymentCompletionRate}}</span> <span>{{ formData.paymentCompletionRate }}</span>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@@ -69,19 +75,23 @@
<div class="panel-title">{{ t('progressReport.form.currentYearImageAmount') }}</div> <div class="panel-title">{{ t('progressReport.form.currentYearImageAmount') }}</div>
<div style="flex: 1;"> <div style="flex: 1;">
<el-form-item style="height: 82px;" :label="t('progressReport.form.reportYear')"> <el-form-item style="height: 82px;" :label="t('progressReport.form.reportYear')">
<span>{{formData.annualReport}}</span> <span>{{ formData.annualReport }}</span>
</el-form-item> </el-form-item>
<el-form-item style="height: 82px;" <el-form-item style="height: 82px;"
:label="t('progressReport.form.currentYearPlannedInvestment')" required prop="annualPlannedInvestment"> :label="t('progressReport.form.currentYearPlannedInvestment')" required
<span>{{formData.investmentTotalAmount ?? 0 + ' ' + t('progressReport.form.unitSuffix')}}</span> prop="annualPlannedInvestment">
<span>{{ formData.investmentTotalAmount ?? 0 + ' ' +
t('progressReport.form.unitSuffix') }}</span>
</el-form-item> </el-form-item>
<el-form-item style="height: 82px;" <el-form-item style="height: 82px;"
:label="t('progressReport.form.enterpriseCumulativeInvestmentToMonthEnd')" required prop="ytdRemainingInvestment"> :label="t('progressReport.form.enterpriseCumulativeInvestmentToMonthEnd')" required
<span>{{ formData.ytdRemainingInvestment + ' ' + t('progressReport.form.unitSuffix')}}</span> prop="ytdRemainingInvestment">
<span>{{ formData.ytdRemainingInvestment + ' ' +
t('progressReport.form.unitSuffix') }}</span>
</el-form-item> </el-form-item>
<el-form-item style="height: 82px;" <el-form-item style="height: 82px;"
:label="t('progressReport.form.investmentCompletionRate')"> :label="t('progressReport.form.investmentCompletionRate')">
<span>{{formData.investmentCompletionRate}}%</span> <span>{{ formData.investmentCompletionRate }}%</span>
</el-form-item> </el-form-item>
</div> </div>
</div> </div>
@@ -91,15 +101,15 @@
<div class="panel-title">{{ t('progressReport.form.currentYearPlannedAmount') }}</div> <div class="panel-title">{{ t('progressReport.form.currentYearPlannedAmount') }}</div>
<div style="flex: 1;"> <div style="flex: 1;">
<el-form-item style="height: 82px;" :label="t('progressReport.form.plannedPaymentAmount')"> <el-form-item style="height: 82px;" :label="t('progressReport.form.plannedPaymentAmount')">
<span>{{formData.plannedPayment + ' ' + t('progressReport.form.unitSuffix')}}</span> <span>{{ formData.plannedPayment + ' ' + t('progressReport.form.unitSuffix') }}</span>
</el-form-item> </el-form-item>
<el-form-item style="height: 82px;" <el-form-item style="height: 82px;"
:label="t('progressReport.form.completedPaymentAmount')"> :label="t('progressReport.form.completedPaymentAmount')">
<span>{{formData.actualPayment + ' ' + t('progressReport.form.unitSuffix')}}</span> <span>{{ formData.actualPayment + ' ' + t('progressReport.form.unitSuffix') }}</span>
</el-form-item> </el-form-item>
<el-form-item style="height: 82px;" <el-form-item style="height: 82px;"
:label="t('progressReport.form.plannedAmountPaymentCompletionRate')"> :label="t('progressReport.form.plannedAmountPaymentCompletionRate')">
<span>{{formData.investmentPlanCompletionRate}} %</span> <span>{{ formData.investmentPlanCompletionRate }} %</span>
</el-form-item> </el-form-item>
</div> </div>
</div> </div>
@@ -109,7 +119,7 @@
<el-row :gutter="20" class="form-row"> <el-row :gutter="20" class="form-row">
<el-col :span="24"> <el-col :span="24">
<el-form-item :label="t('progressReport.form.effectiveness')"> <el-form-item :label="t('progressReport.form.effectiveness')">
<span>{{formData.achievements}}</span> <span>{{ formData.achievements }}</span>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@@ -117,7 +127,7 @@
<el-row :gutter="20" class="form-row"> <el-row :gutter="20" class="form-row">
<el-col :span="24"> <el-col :span="24">
<el-form-item :label="t('progressReport.form.coordinationMatters')"> <el-form-item :label="t('progressReport.form.coordinationMatters')">
<span>{{formData.coordinationIssues}}</span> <span>{{ formData.coordinationIssues }}</span>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@@ -125,7 +135,7 @@
<el-row :gutter="20" class="form-row"> <el-row :gutter="20" class="form-row">
<el-col :span="24"> <el-col :span="24">
<el-form-item :label="t('progressReport.form.nextWorkArrangements')"> <el-form-item :label="t('progressReport.form.nextWorkArrangements')">
<span>{{formData.nextWorkPlan}}</span> <span>{{ formData.nextWorkPlan }}</span>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@@ -133,8 +143,9 @@
<el-row :gutter="20" class="form-row"> <el-row :gutter="20" class="form-row">
<el-col :span="24"> <el-col :span="24">
<el-form-item :label="t('progressReport.form.currentStageEvidenceMaterials')"> <el-form-item :label="t('progressReport.form.currentStageEvidenceMaterials')">
<uploadFile :modelValue="JSON.parse(formData.supportingDocuments || '[]') || []" @change="uploadChange" :fileSize="20" type="simple" :limit="10" <uploadFile :modelValue="JSON.parse(formData.supportingDocuments || '[]') || []"
:isShowTip="false" disabled></uploadFile> @change="uploadChange" :fileSize="20" type="simple" :limit="10" :isShowTip="false" disabled>
</uploadFile>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@@ -142,7 +153,7 @@
<el-row :gutter="20" class="form-row"> <el-row :gutter="20" class="form-row">
<el-col :span="24"> <el-col :span="24">
<el-form-item :label="t('progressReport.form.remark')"> <el-form-item :label="t('progressReport.form.remark')">
<span>{{formData.remarks}}</span> <span>{{ formData.remarks }}</span>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@@ -150,7 +161,8 @@
<el-row :gutter="20" class="form-row"> <el-row :gutter="20" class="form-row">
<el-col :span="24"> <el-col :span="24">
<el-form-item :label="t('progressReport.form.isLastDeclaration')"> <el-form-item :label="t('progressReport.form.isLastDeclaration')">
<span>{{formData.isFinalApplication == '1' ? t('progressReport.form.yes') : t('progressReport.form.no')}}</span> <span>{{ formData.isFinalApplication == '1' ? t('progressReport.form.yes') :
t('progressReport.form.no') }}</span>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@@ -200,8 +212,8 @@ export interface ProjectProgressReportFormData {
const props = defineProps<{ const props = defineProps<{
modelValue?: InvestmentProjectProgress; modelValue?: InvestmentProjectProgress;
rules?:FormRules; rules?: FormRules;
title?: string; title?: string;
}>(); }>();
const emit = defineEmits<{ const emit = defineEmits<{
@@ -209,37 +221,37 @@ const emit = defineEmits<{
}>(); }>();
const useForm = ref<FormInstance | undefined>() const useForm = ref<FormInstance | undefined>()
const defaultForm = reactive<InvestmentProjectProgress>({ const defaultForm = reactive<InvestmentProjectProgress>({
id: undefined, id: undefined,
projectName: '', projectName: '',
projectId: undefined, projectId: undefined,
projectStatus: '', projectStatus: '',
constructionStage: '', constructionStage: '',
implementingBody: '', implementingBody: '',
projectTotalAmount: undefined, projectTotalAmount: undefined,
cumulativeInvestmentToDate: undefined, cumulativeInvestmentToDate: undefined,
completionRate: undefined, completionRate: undefined,
cumulativePaymentToDate: undefined, cumulativePaymentToDate: undefined,
paymentCompletionRate: undefined, paymentCompletionRate: undefined,
annualReport: undefined, annualReport: undefined,
annualPlannedInvestment: undefined, annualPlannedInvestment: undefined,
ytdRemainingInvestment: undefined, ytdRemainingInvestment: undefined,
investmentCompletionRate: undefined, investmentCompletionRate: undefined,
plannedPayment: undefined, plannedPayment: undefined,
actualPayment: undefined, actualPayment: undefined,
investmentPlanCompletionRate: undefined, investmentPlanCompletionRate: undefined,
achievements: '', achievements: '',
coordinationIssues: '', coordinationIssues: '',
nextWorkPlan: '', nextWorkPlan: '',
supportingDocuments: '', supportingDocuments: '',
remarks: '', remarks: '',
isFinalApplication: undefined, isFinalApplication: undefined,
createBy: '', createBy: '',
createTime: '', createTime: '',
updateBy: '', updateBy: '',
updateTime: '', updateTime: '',
delFlag: '', delFlag: '',
processInstanceId: '', processInstanceId: '',
status: '', status: '',
}) })
const formData = reactive<InvestmentProjectProgress>({ ...defaultForm, ...props.modelValue }); const formData = reactive<InvestmentProjectProgress>({ ...defaultForm, ...props.modelValue });
const projectNameData = ref<ProjectPlanApplyFormItem[]>([]); const projectNameData = ref<ProjectPlanApplyFormItem[]>([]);
@@ -257,30 +269,30 @@ const queryForm = reactive<investmentProjectsPlanList>({
size: 10, size: 10,
}); });
const getProjectNameList = async () => { const getProjectNameList = async () => {
try { try {
const res = await investmentProjectsPlanPage(queryForm); const res = await investmentProjectsPlanPage(queryForm);
projectNameData.value = res.data?.records || []; projectNameData.value = res.data?.records || [];
total.value = res.data?.total || 0; total.value = res.data?.total || 0;
} catch (error) { } catch (error) {
console.error(error); console.error(error);
projectNameData.value = []; // 出错时设置为空数组 projectNameData.value = []; // 出错时设置为空数组
} }
} }
getProjectNameList(); getProjectNameList();
/** /**
* 初始化图片 * 初始化图片
* */ * */
const uploadChange = (_:any,data:any[]) =>{ const uploadChange = (_: any, data: any[]) => {
if (!data || Object.prototype.toString.call(data) !== '[object Array]' || data.length === 0){ if (!data || Object.prototype.toString.call(data) !== '[object Array]' || data.length === 0) {
formData.supportingDocuments = []; formData.supportingDocuments = [];
return; return;
} }
formData.supportingDocuments = data.map((item:any) => { formData.supportingDocuments = data.map((item: any) => {
return { return {
name: item.name, name: item.name,
url: item.url url: item.url
} }
}) })
} }
// 监听 formData 变化,同步到父组件 // 监听 formData 变化,同步到父组件
watch( watch(
@@ -296,18 +308,18 @@ watch(
() => props.modelValue, () => props.modelValue,
(newVal) => { (newVal) => {
if (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); Object.assign(formData, newVal);
} }
}, },
{ immediate: true, deep: true } { immediate: true, deep: true }
); );
defineExpose({ defineExpose({
validate: async () => { validate: async () => {
const isValid = await useForm.value?.validate(); const isValid = await useForm.value?.validate();
if (!isValid) return false if (!isValid) return false
return formData return formData
}, },
}) })
</script> </script>

View File

@@ -1,12 +1,12 @@
export interface InvestmentProjects { export interface InvestmentProjects {
id?: number; id?: number;
plannedInvestmentYear: string; plannedInvestmentYear: string;
plannedImageAmount: string; plannedImageAmount: string | number | null;
plannedPaymentAmount: string; plannedPaymentAmount: string | number | null;
selfFunding: string; selfFunding: string | number | null;
externalFunding: string; externalFunding: string | number | null;
fiscalFunding: string; fiscalFunding: string | number | null;
otherFunding: string; otherFunding: string | number | null;
fiscalFundingSource: string; fiscalFundingSource: string;
otherFundingSource: string; otherFundingSource: string;
} }
@@ -25,7 +25,7 @@ export interface EvaluationRecordEntitiesT {
createBy: string; createBy: string;
createTime: string createTime: string
} }
export interface ProjectPlanApplyFormItem{ export interface ProjectPlanApplyFormItem {
id?: any; id?: any;
projectName: string; projectName: string;
projectNature: string; projectNature: string;
@@ -75,7 +75,7 @@ export interface ProjectPlanApplyFormItem{
projectDesc: string; projectDesc: string;
promotionPlan: string; promotionPlan: string;
projectPreliminaryPlan: string; projectPreliminaryPlan: string;
projectPreliminaryPlanAttachment:any[] | string; projectPreliminaryPlanAttachment: any[] | string;
attachments: any[] | string; attachments: any[] | string;
remark: string; remark: string;
decisionType: string; decisionType: string;
@@ -89,16 +89,16 @@ export interface ProjectPlanApplyFormItem{
groupInvestmentDeptOpinion: string; groupInvestmentDeptOpinion: string;
submitUnitLeadershipOpinion: string; submitUnitLeadershipOpinion: string;
submitUnitMainLeadershipOpinion: string; submitUnitMainLeadershipOpinion: string;
planImageQuota:string; planImageQuota: string;
projectInvestmentEntities?:InvestmentProjects[]; projectInvestmentEntities?: InvestmentProjects[];
evaluationRecordEntities?:EvaluationRecordEntitiesT[]; evaluationRecordEntities?: EvaluationRecordEntitiesT[];
delFlag?: number; delFlag?: number;
projectId?: number; projectId?: number;
processInstanceId:string; processInstanceId: string;
status:number; status: number;
deptId:number deptId: number
} }
export interface ProjectPlanApplyFormData { export interface ProjectPlanApplyFormData {
entity:ProjectPlanApplyFormItem; entity: ProjectPlanApplyFormItem;
investmentProjects: InvestmentProjects[]; investmentProjects: InvestmentProjects[];
} }

View File

@@ -15,7 +15,8 @@
</el-button> </el-button>
</div> </div>
<div class="opinion-input"> <div class="opinion-input">
<el-input v-model="opinionText" type="textarea" :rows="4" :placeholder="t('workbench.approval.opinion.inputPlaceholder')" resize="vertical" /> <el-input v-model="opinionText" type="textarea" :rows="4"
:placeholder="t('workbench.approval.opinion.inputPlaceholder')" resize="vertical" />
</div> </div>
<!-- <div class="opinion-attachment"> <!-- <div class="opinion-attachment">
<el-icon class="attachment-icon"> <el-icon class="attachment-icon">
@@ -30,7 +31,8 @@
<!-- 撤回区域可撤回状态显示 --> <!-- 撤回区域可撤回状态显示 -->
<div v-if="status === 'withdrawable'" class="withdraw-section"> <div v-if="status === 'withdrawable'" class="withdraw-section">
<div class="withdraw-input"> <div class="withdraw-input">
<el-input v-model="opinionText" type="textarea" :rows="4" :placeholder="t('workbench.approval.opinion.inputPlaceholder')" resize="vertical" /> <el-input v-model="opinionText" type="textarea" :rows="4"
:placeholder="t('workbench.approval.opinion.inputPlaceholder')" resize="vertical" />
</div> </div>
<div class="withdraw-action"> <div class="withdraw-action">
<el-button type="primary" @click="handleWithdraw"> <el-button type="primary" @click="handleWithdraw">
@@ -58,10 +60,11 @@
</div> </div>
<div class="record-time">{{ item.showTime || '待审核' }}</div> <div class="record-time">{{ item.showTime || '待审核' }}</div>
</div> </div>
<!-- <div v-if="record.action" class="record-action">{{ record.action }}</div> --> <!-- <div v-if="record.action" class="record-action">{{ record.action }}</div> -->
<template v-if="record.id !== 'root' && item.status === 2"> <template v-if="record.id !== 'root' && item.status === 2">
<div class="record-status" :class="getStatusClass(item.approveDesc?.startsWith('拒绝原因:') ? 'rejected' : 'approved')"> <div class="record-status"
:class="getStatusClass(item.approveDesc?.startsWith('拒绝原因:') ? 'rejected' : 'approved')">
{{ getStatusLabel(item.approveDesc?.startsWith('拒绝原因:') ? 'rejected' : 'approved') }} {{ getStatusLabel(item.approveDesc?.startsWith('拒绝原因:') ? 'rejected' : 'approved') }}
</div> </div>
<div class="record-opinion"> <div class="record-opinion">
@@ -79,7 +82,8 @@
</div> </div>
</div> </div>
<template v-if="selectUser"> <template v-if="selectUser">
<EmployeesDialog :visible="selectUserDialog" :data="[]" type="user" @change="changeUser" @update:visible="(e:boolean) => selectUserDialog = e"/> <EmployeesDialog :visible="selectUserDialog" :data="[]" type="user" @change="changeUser"
@update:visible="(e: boolean) => selectUserDialog = e" />
</template> </template>
</div> </div>
</template> </template>
@@ -100,37 +104,37 @@ const selectUserDialog = ref<boolean>(false);
const nextNodeId = ref<string>(''); const nextNodeId = ref<string>('');
const isApprovalUser = computed(() => { const isApprovalUser = computed(() => {
const currentUserId = userInfo.userInfos.user?.userId const currentUserId = userInfo.userInfos.user?.userId
const currentNode = hierarchicalLookup(nodeList.value,taskDetails.value?.nodeId) const currentNode = hierarchicalLookup(nodeList.value, taskDetails.value?.nodeId)
const currentNodeUser = currentNode ?.userVoList?.find((item:any) => item.id === currentUserId) const currentNodeUser = currentNode?.userVoList?.find((item: any) => item.id === currentUserId)
selectUser.value = nextNodeIsSelectUser(nodeList.value,currentNode?.id) selectUser.value = nextNodeIsSelectUser(nodeList.value, currentNode?.id)
return currentNodeUser?.status === 1 return currentNodeUser?.status === 1
}) })
function hierarchicalLookup(nodeList:any[],nodeId:string):any { function hierarchicalLookup(nodeList: any[], nodeId: string): any {
for (const nodeItem of nodeList) { for (const nodeItem of nodeList) {
if (nodeItem.id === nodeId){ if (nodeItem.id === nodeId) {
return nodeItem return nodeItem
} }
if (nodeItem.children && nodeItem.children.length > 0){ if (nodeItem.children && nodeItem.children.length > 0) {
const children = hierarchicalLookup(nodeItem.children,nodeId) const children = hierarchicalLookup(nodeItem.children, nodeId)
if (children){ if (children) {
return children return children
} }
} }
if (nodeItem.branch && nodeItem.branch.length > 0){ if (nodeItem.branch && nodeItem.branch.length > 0) {
const branch = hierarchicalLookup(nodeItem.branch,nodeId) const branch = hierarchicalLookup(nodeItem.branch, nodeId)
if (branch){ if (branch) {
return branch return branch
} }
} }
} }
} }
function nextNodeIsSelectUser(nodeList:any[],currentNodeId:any):boolean{ function nextNodeIsSelectUser(nodeList: any[], currentNodeId: any): boolean {
if (!nodeList || nodeList.length === 0){ if (!nodeList || nodeList.length === 0) {
return false return false
} }
const index = nodeList.findIndex(item => item.id === currentNodeId) const index = nodeList.findIndex(item => item.id === currentNodeId)
if (index === -1){ if (index === -1) {
return false return false
} }
const node = nodeList[index + 1] const node = nodeList[index + 1]
@@ -138,25 +142,25 @@ function nextNodeIsSelectUser(nodeList:any[],currentNodeId:any):boolean{
return node?.selectUser || false return node?.selectUser || false
} }
interface UserVoList { interface UserVoList {
id: string; id: string;
name: string; name: string;
showTime?: string; showTime?: string;
avatar: string; avatar: string;
approveDesc?: string; approveDesc?: string;
operType?: string; operType?: string;
status: number; status: number;
} }
interface ApprovalRecord { interface ApprovalRecord {
id: string; id: string;
userVoList: UserVoList[]; userVoList: UserVoList[];
placeholder: string; placeholder: string;
status: number; status: number;
name: string; name: string;
type: number; type: number;
selectUser: boolean; selectUser: boolean;
multiple?: null; multiple?: null;
children?: ApprovalRecord[]; children?: ApprovalRecord[];
branch: { children: ApprovalRecord[] }[]; branch: { children: ApprovalRecord[] }[];
} }
const props = defineProps<{ const props = defineProps<{
@@ -194,7 +198,7 @@ const emit = defineEmits<{
(e: 'add-attachment'): void; (e: 'add-attachment'): void;
}>(); }>();
const obj = ref<any>({}) const obj = ref<any>({})
const changeUser = (checkedList: any[]) =>{ const changeUser = (checkedList: any[]) => {
obj.value[`${nextNodeId.value}_assignee_select`] = checkedList; obj.value[`${nextNodeId.value}_assignee_select`] = checkedList;
selectUser.value = false; selectUser.value = false;
selectUserDialog.value = false; selectUserDialog.value = false;
@@ -211,7 +215,7 @@ const handleApprove = async () => {
} }
approving.value = true approving.value = true
try { try {
if (selectUser.value && nextNodeId.value){ if (selectUser.value && nextNodeId.value) {
selectUserDialog.value = true; selectUserDialog.value = true;
return; return;
} }
@@ -374,6 +378,7 @@ onMounted(() => {
display: flex; display: flex;
/* gap: 8px; */ /* gap: 8px; */
margin-bottom: 16px; margin-bottom: 16px;
.el-button { .el-button {
flex: 1; flex: 1;
} }

View File

@@ -27,41 +27,45 @@
<!-- 标题描述上传附件 --> <!-- 标题描述上传附件 -->
<el-row class="mb10"> <el-row class="mb10">
<el-form :model="headerForm" label-width="80px" class="w-full" :rules="headerRequiredRule" ref="headerFormRef"> <el-form :model="headerForm" label-width="80px" class="w-full" :rules="headerRequiredRule"
ref="headerFormRef">
<el-form-item :label="t('planApply.headerForm.title')" prop="title"> <el-form-item :label="t('planApply.headerForm.title')" prop="title">
<el-input v-model="headerForm.title" :placeholder="t('planApply.headerForm.titlePlaceholder')"/> <el-input v-model="headerForm.title"
:placeholder="t('planApply.headerForm.titlePlaceholder')" />
</el-form-item> </el-form-item>
<el-form-item :label="t('planApply.headerForm.description')"> <el-form-item :label="t('planApply.headerForm.description')">
<el-input v-model="headerForm.description" :placeholder="t('planApply.headerForm.descriptionPlaceholder')"/> <el-input v-model="headerForm.description"
:placeholder="t('planApply.headerForm.descriptionPlaceholder')" />
</el-form-item> </el-form-item>
<el-form-item :label="t('planApply.headerForm.attachments')"> <el-form-item :label="t('planApply.headerForm.attachments')">
<UploadFile :modelValue="headerForm.attachments" :fileSize="20" type="simple" :limit="10" <UploadFile :modelValue="headerForm.attachments" :fileSize="20" type="simple" :limit="10"
@change="uploadChange"/> @change="uploadChange" />
</el-form-item> </el-form-item>
</el-form> </el-form>
</el-row> </el-row>
<ProjectPlanApplyForm v-model="formData" :rules="formDataRules" ref="formDataRef" :is-update="props.isUpdate"/> <ProjectPlanApplyForm v-model="formData" :rules="formDataRules" ref="formDataRef"
:is-update="props.isUpdate" />
</div> </div>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import {reactive, ref} from 'vue'; import { reactive, ref } from 'vue';
import {useI18n} from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import {useMessage} from '/@/hooks/message'; import { useMessage } from '/@/hooks/message';
import { import {
investmentProjectsPlanAdd, investmentProjectsPlanGetById, investmentProjectsPlanAdd, investmentProjectsPlanGetById,
investmentProjectsPlanUserDeptBelong investmentProjectsPlanUserDeptBelong
} from '/@/api/investment/investmentManagement'; } from '/@/api/investment/investmentManagement';
import ProjectPlanApplyForm from '/@/components/investment/common/ProjectPlanApplyForm.vue'; import ProjectPlanApplyForm from '/@/components/investment/common/ProjectPlanApplyForm.vue';
import type {ProjectPlanApplyFormData} from '/@/components/investment/interface/types'; import type { ProjectPlanApplyFormData } from '/@/components/investment/interface/types';
import type {FormInstance, FormRules} from 'element-plus'; import type { FormInstance, FormRules } from 'element-plus';
import UploadFile from '/@/components/Upload/index.vue'; import UploadFile from '/@/components/Upload/index.vue';
import {useRoute} from 'vue-router'; import { useRoute } from 'vue-router';
import {flowFn} from "/@/utils/flowFn"; import { flowFn } from "/@/utils/flowFn";
import {addFlowForm} from "/@/api/flow/flow"; import { addFlowForm } from "/@/api/flow/flow";
import {flowNameOptions} from "/@/hooks/enums"; import { flowNameOptions } from "/@/hooks/enums";
const props = defineProps({ const props = defineProps({
isUpdate: { isUpdate: {
@@ -69,7 +73,7 @@ const props = defineProps({
default: false default: false
} }
}) })
const {t} = useI18n(); const { t } = useI18n();
const message = useMessage(); const message = useMessage();
const route = useRoute(); const route = useRoute();
const submitLoading = ref(false); const submitLoading = ref(false);
@@ -78,7 +82,7 @@ const headerForm = reactive<{ title: string, description: string, attachments: a
description: '', description: '',
attachments: [] as any[], attachments: [] as any[],
}); });
const requiredRule = [{required: true, message: `${t('该字段必填')}`}]; const requiredRule = [{ required: true, message: `${t('该字段必填')}` }];
const headerRequiredRule = ref<FormRules<{ title: string, description: string, attachments: any[] | string }>>({ const headerRequiredRule = ref<FormRules<{ title: string, description: string, attachments: any[] | string }>>({
title: requiredRule, title: requiredRule,
}); });
@@ -150,9 +154,9 @@ const formData = ref<ProjectPlanApplyFormData>({
submitUnitLeadershipOpinion: '', submitUnitLeadershipOpinion: '',
submitUnitMainLeadershipOpinion: '', submitUnitMainLeadershipOpinion: '',
planImageQuota: '', planImageQuota: '',
status:1, status: 1,
processInstanceId:'', processInstanceId: '',
deptId:0, deptId: 0,
}, },
investmentProjects: [], investmentProjects: [],
}); });
@@ -203,40 +207,51 @@ const formDataRules = ref<FormRules<ProjectPlanApplyFormData>>({
'entity.financialFunds': requiredRule, 'entity.financialFunds': requiredRule,
'entity.planImageQuota': requiredRule, 'entity.planImageQuota': requiredRule,
'entity.planPaymentLimit': requiredRule, 'entity.planPaymentLimit': requiredRule,
'entity.projectApprovalFileNo':[{validator:(rule: any, value: any, callback: any) =>{ 'entity.projectApprovalFileNo': [{
if (formData.value.entity.isProjectApprovalCompleted === '1' && !value){ validator: (rule: any, value: any, callback: any) => {
callback(new Error(`${t('该字段必填')}`)); if (formData.value.entity.isProjectApprovalCompleted === '1' && !value) {
}else { callback(new Error(`${t('该字段必填')}`));
callback(); } else {
} callback();
},required:true,trigger: ['blur', 'change']}], }
'entity.projectApprovalFileInfo':[{validator:(rule: any, value: any, callback: any) =>{ }, required: true, trigger: ['blur', 'change']
if (formData.value.entity.isProjectApprovalCompleted === '1' && !value){ }],
callback(new Error(`${t('该字段必填')}`)); 'entity.projectApprovalFileInfo': [{
}else { validator: (rule: any, value: any, callback: any) => {
callback(); if (formData.value.entity.isProjectApprovalCompleted === '1' && !value) {
} callback(new Error(`${t('该字段必填')}`));
},required: true,trigger: ['blur', 'change']}], } else {
'entity.decisionProcedureFileNo':[{validator:(rule: any, value: any, callback: any) =>{ callback();
if (formData.value.entity.isDecisionProcedureCompleted === '1' && !value){ }
callback(new Error(`${t('该字段必填')}`)); }, required: true, trigger: ['blur', 'change']
}else { }],
callback(); 'entity.decisionProcedureFileNo': [{
} validator: (rule: any, value: any, callback: any) => {
},required:true,trigger: ['blur', 'change']}], if (formData.value.entity.isDecisionProcedureCompleted === '1' && !value) {
'entity.decisionFileInfo':[{validator:(rule: any, value: any, callback: any) =>{ callback(new Error(`${t('该字段必填')}`));
if (formData.value.entity.isDecisionProcedureCompleted === '1' && !value){ } else {
callback(new Error(`${t('该字段必填')}`)); callback();
}else { }
callback(); }, required: true, trigger: ['blur', 'change']
} }],
},required: true,trigger: ['blur', 'change']}], 'entity.decisionFileInfo': [{
validator: (rule: any, value: any, callback: any) => {
if (formData.value.entity.isDecisionProcedureCompleted === '1' && !value) {
callback(new Error(`${t('该字段必填')}`));
} else {
callback();
}
}, required: true, trigger: ['blur', 'change']
}],
}); });
const handleInitiateApproval = async () => { const handleInitiateApproval = async () => {
try { try {
const headerValid = await headerFormRef.value?.validate(); const headerValid = await headerFormRef.value?.validate().catch(() => false);
const valid = await formDataRef.value?.validateForm(); if (!headerValid) return;
if (!valid && !headerValid) return;
const valid = await formDataRef.value?.validateForm().catch(() => false);
if (!valid) return;
submitLoading.value = true; submitLoading.value = true;
let flowIdKey = '' let flowIdKey = ''
const data = await investmentProjectsPlanUserDeptBelong() const data = await investmentProjectsPlanUserDeptBelong()
@@ -256,7 +271,7 @@ const handleInitiateApproval = async () => {
default: default:
flowIdKey = props.isUpdate ? 'VITE_FLOWID_27' : 'VITE_FLOWID_23'; flowIdKey = props.isUpdate ? 'VITE_FLOWID_27' : 'VITE_FLOWID_23';
} }
const {processInstanceId} = await flowFn(flowIdKey, { const { processInstanceId } = await flowFn(flowIdKey, {
paramMap: {} paramMap: {}
}) })
const flowName = props.isUpdate ? 'investmentPlanUpdates' : 'investmentPlanRegistration'; const flowName = props.isUpdate ? 'investmentPlanUpdates' : 'investmentPlanRegistration';
@@ -271,7 +286,7 @@ const handleInitiateApproval = async () => {
formData.value.entity.processInstanceId = processInstanceId; formData.value.entity.processInstanceId = processInstanceId;
formData.value.entity.projectPreliminaryPlanAttachment = JSON.stringify(formData.value.entity.projectPreliminaryPlanAttachment); formData.value.entity.projectPreliminaryPlanAttachment = JSON.stringify(formData.value.entity.projectPreliminaryPlanAttachment);
formData.value.entity.status = 1 formData.value.entity.status = 1
Object.assign(formData.value.entity,{flowType:flowNameObj.value}) Object.assign(formData.value.entity, { flowType: flowNameObj.value })
const params = { const params = {
...formData.value, ...formData.value,
entity: { entity: {
@@ -281,14 +296,14 @@ const handleInitiateApproval = async () => {
} }
} }
investmentProjectsPlanAdd(params) investmentProjectsPlanAdd(params)
.then(() => { .then(() => {
submitLoading.value = false; submitLoading.value = false;
message.success(t('planApply.messages.initiateApproval')); message.success(t('planApply.messages.initiateApproval'));
}) })
.catch((err: any) => { .catch((err: any) => {
submitLoading.value = false; submitLoading.value = false;
message.error(err.msg); message.error(err.msg);
}); });
} catch (error) { } catch (error) {
console.log(error, 'error'); console.log(error, 'error');
} }
@@ -296,28 +311,32 @@ const handleInitiateApproval = async () => {
const saveLoading = ref<boolean>(false); const saveLoading = ref<boolean>(false);
const handleSaveDraft = async () => { const handleSaveDraft = async () => {
const headerValid = await headerFormRef.value?.validate(); try {
const valid = await formDataRef.value?.validateForm(); const headerValid = await headerFormRef.value?.validate().catch(() => false);
if (!valid && !headerValid) return; if (!headerValid) return;
saveLoading.value = true;
const flowName = props.isUpdate ? 'investmentPlanUpdates' : 'investmentPlanRegistration'; const valid = await formDataRef.value?.validateForm().catch(() => false);
const flowNameObj = flowNameOptions.filter(item => item.label === flowName)[0] if (!valid) return;
formData.value.entity.projectPreliminaryPlanAttachment = JSON.stringify(formData.value.entity.projectPreliminaryPlanAttachment);
formData.value.entity.status = 1 saveLoading.value = true;
Object.assign(formData.value.entity,{flowType:flowNameObj.value}) const flowName = props.isUpdate ? 'investmentPlanUpdates' : 'investmentPlanRegistration';
const params = { const flowNameObj = flowNameOptions.filter(item => item.label === flowName)[0]
...formData.value, formData.value.entity.projectPreliminaryPlanAttachment = JSON.stringify(formData.value.entity.projectPreliminaryPlanAttachment);
entity: { formData.value.entity.status = 1
...formData.value.entity, Object.assign(formData.value.entity, { flowType: flowNameObj.value })
attachments: formData.value.entity.attachments ? JSON.stringify(formData.value.entity.attachments) : '', const params = {
projectPreliminaryPlanAttachment: formData.value.entity.projectPreliminaryPlanAttachment ? JSON.stringify(formData.value.entity.projectPreliminaryPlanAttachment) : '' ...formData.value,
}, entity: {
temporaryStorage:{ ...formData.value.entity,
title: headerForm.title, attachments: formData.value.entity.attachments ? JSON.stringify(formData.value.entity.attachments) : '',
businessType: flowNameObj.value, projectPreliminaryPlanAttachment: formData.value.entity.projectPreliminaryPlanAttachment ? JSON.stringify(formData.value.entity.projectPreliminaryPlanAttachment) : ''
},
temporaryStorage: {
title: headerForm.title,
businessType: flowNameObj.value,
}
} }
} investmentProjectsPlanAdd(params)
investmentProjectsPlanAdd(params)
.then(() => { .then(() => {
saveLoading.value = false; saveLoading.value = false;
message.success('保存代发成功'); message.success('保存代发成功');
@@ -326,6 +345,9 @@ const handleSaveDraft = async () => {
saveLoading.value = false; saveLoading.value = false;
message.error(err.msg); message.error(err.msg);
}); });
} catch (error) {
console.log(error, 'error');
}
}; };
const handleLoadTemplate = () => { const handleLoadTemplate = () => {

View File

@@ -27,15 +27,19 @@
<!-- 标题描述上传附件 --> <!-- 标题描述上传附件 -->
<el-row class="mb10"> <el-row class="mb10">
<el-form :model="headerForm" label-width="80px" class="w-full"> <el-form :model="headerForm" :rules="headerFormRules" ref="headerFormRef" label-width="80px"
<el-form-item :label="t('progressReport.headerForm.title')"> class="w-full">
<el-input v-model="headerForm.title" :placeholder="t('progressReport.headerForm.titlePlaceholder')" /> <el-form-item :label="t('progressReport.headerForm.title')" prop="title" required>
<el-input v-model="headerForm.title"
:placeholder="t('progressReport.headerForm.titlePlaceholder')" />
</el-form-item> </el-form-item>
<el-form-item :label="t('progressReport.headerForm.description')"> <el-form-item :label="t('progressReport.headerForm.description')">
<el-input v-model="headerForm.description" :placeholder="t('progressReport.headerForm.descriptionPlaceholder')" /> <el-input v-model="headerForm.description"
:placeholder="t('progressReport.headerForm.descriptionPlaceholder')" />
</el-form-item> </el-form-item>
<el-form-item :label="t('progressReport.headerForm.attachments')"> <el-form-item :label="t('progressReport.headerForm.attachments')">
<UploadFile :modelValue="headerForm.attachments" @change="uploadChange" :fileSize="20" type="simple" :limit="10" /> <UploadFile :modelValue="headerForm.attachments" @change="uploadChange" :fileSize="20"
type="simple" :limit="10" />
</el-form-item> </el-form-item>
</el-form> </el-form>
</el-row> </el-row>
@@ -46,7 +50,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { reactive } from 'vue'; import { reactive, ref } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useMessage } from '/@/hooks/message'; import { useMessage } from '/@/hooks/message';
import ProjectProgressReportForm from '/@/components/investment/common/ProjectProgressReportForm.vue'; import ProjectProgressReportForm from '/@/components/investment/common/ProjectProgressReportForm.vue';
@@ -57,14 +61,18 @@ import {
getInvestmentProjectsProgressUserDeptBelongAPI getInvestmentProjectsProgressUserDeptBelongAPI
} from '/@/api/investment/progressOfInvestmentProjects'; } from '/@/api/investment/progressOfInvestmentProjects';
import UploadFile from "/@/components/Upload/index.vue"; import UploadFile from "/@/components/Upload/index.vue";
import {flowFn} from "/@/utils/flowFn"; import { flowFn } from "/@/utils/flowFn";
import {addFlowForm} from "/@/api/flow/flow"; import { addFlowForm } from "/@/api/flow/flow";
import {flowNameOptions} from "/@/hooks/enums"; import { flowNameOptions } from "/@/hooks/enums";
const { t } = useI18n(); const { t } = useI18n();
const message = useMessage(); const message = useMessage();
const headerForm = reactive<{ title: string; description: string; attachments: any[] | string}>({ const headerFormRef = ref<any>();
const headerFormRules = {
title: [{ required: true, message: '标题必填', trigger: ['blur', 'change'] }]
};
const headerForm = reactive<{ title: string; description: string; attachments: any[] | string }>({
title: '', title: '',
description: '', description: '',
attachments: [], attachments: [],
@@ -103,6 +111,7 @@ const formData = reactive<InvestmentProjectProgress>({
delFlag: '', delFlag: '',
processInstanceId: '', processInstanceId: '',
status: '', status: '',
deptId: '',
}); });
// 必填规则 // 必填规则
const requiredRule = [{ required: true, message: `${t('该字段必填')}` }]; const requiredRule = [{ required: true, message: `${t('该字段必填')}` }];
@@ -118,6 +127,10 @@ const formDataRef = ref<FormRules<InvestmentProjectProgress>>({
const handleInitiateApproval = async () => { const handleInitiateApproval = async () => {
// message.info(t('progressReport.messages.initiateApproval')); // message.info(t('progressReport.messages.initiateApproval'));
try { try {
const headerValid = await headerFormRef.value?.validate().catch(() => false);
if (!headerValid) {
return;
}
const valid = await formRef.value?.validate(); const valid = await formRef.value?.validate();
submitLoading.value = true; submitLoading.value = true;
let flowIdKey = ''; let flowIdKey = '';
@@ -139,10 +152,14 @@ const handleInitiateApproval = async () => {
flowIdKey = 'VITE_FLOWID_31'; flowIdKey = 'VITE_FLOWID_31';
} }
headerForm.attachments = JSON.stringify(headerForm.attachments); headerForm.attachments = JSON.stringify(headerForm.attachments);
const {processInstanceId} = await flowFn(flowIdKey,{ const flowResult = await flowFn(flowIdKey, {
paramMap:{ paramMap: {
} }
}) })
if (flowResult instanceof Error) {
throw flowResult;
}
const { processInstanceId } = flowResult;
const flowNameObj = flowNameOptions.filter(item => item.label === 'projectProgressDeclaration')[0] const flowNameObj = flowNameOptions.filter(item => item.label === 'projectProgressDeclaration')[0]
await addFlowForm({ await addFlowForm({
title: headerForm.title, title: headerForm.title,
@@ -154,9 +171,9 @@ const handleInitiateApproval = async () => {
valid.processInstanceId = processInstanceId; valid.processInstanceId = processInstanceId;
valid.supportingDocuments = JSON.stringify(valid.supportingDocuments); valid.supportingDocuments = JSON.stringify(valid.supportingDocuments);
valid.status = 1; valid.status = 1;
await addInvestmentProjectsProgressAPI(valid).then(()=>{ await addInvestmentProjectsProgressAPI(valid).then(() => {
message.success(t('common.success')); message.success(t('common.success'));
}).finally(()=>{ }).finally(() => {
submitLoading.value = false; submitLoading.value = false;
}).catch((err: any) => { }).catch((err: any) => {
submitLoading.value = false; submitLoading.value = false;
@@ -182,12 +199,12 @@ const handleSaveTemplate = () => {
const handleViewWorkflow = () => { const handleViewWorkflow = () => {
message.info(t('progressReport.messages.viewWorkflow')); message.info(t('progressReport.messages.viewWorkflow'));
}; };
const uploadChange = (_:any,data:any[]) =>{ const uploadChange = (_: any, data: any[]) => {
if (!data || Object.prototype.toString.call(data) !== '[object Array]' || data.length === 0){ if (!data || Object.prototype.toString.call(data) !== '[object Array]' || data.length === 0) {
headerForm.attachments = []; headerForm.attachments = [];
return; return;
} }
headerForm.attachments = data.map((item:any) => { headerForm.attachments = data.map((item: any) => {
return { return {
name: item.name, name: item.name,
url: item.url url: item.url

View File

@@ -1,8 +1,8 @@
<!-- 进度申报审核--> <!-- 进度申报审核-->
<script setup lang="ts"> <script setup lang="ts">
import {onMounted} from 'vue'; import { onMounted } from 'vue';
import ApprovalAction from '/@//components/workbench/common/ApprovalAction.vue'; import ApprovalAction from '/@//components/workbench/common/ApprovalAction.vue';
import {useRoute} from 'vue-router'; import { useRoute } from 'vue-router';
import ProjectProgressReportFormDeatils from '/@/components/investment/common/ProjectProgressReportFormDeatils.vue'; import ProjectProgressReportFormDeatils from '/@/components/investment/common/ProjectProgressReportFormDeatils.vue';
import { import {
getInvestmentProjectsProgressGetByProcessInstanceIdAPI, getInvestmentProjectsProgressGetByProcessInstanceIdAPI,
@@ -15,13 +15,13 @@ const taskId = ref<string>('0');
const status = ref<'pending' | 'reviewed' | 'withdrawable'>('pending'); const status = ref<'pending' | 'reviewed' | 'withdrawable'>('pending');
const projectId = ref<string>('0'); const projectId = ref<string>('0');
const detailFormData = ref<InvestmentProjectProgress>({} as InvestmentProjectProgress); const detailFormData = ref<InvestmentProjectProgress>({} as InvestmentProjectProgress);
const getProjectDetail = (id:string) =>{ const getProjectDetail = (id: string) => {
getInvestmentProjectsProgressGetByProcessInstanceIdAPI(id).then(res =>{ getInvestmentProjectsProgressGetByProcessInstanceIdAPI(id).then(res => {
detailFormData.value = res.data detailFormData.value = res.data
}); });
} }
onMounted(() =>{ onMounted(() => {
if (route.query.processInstanceId){ if (route.query.processInstanceId) {
taskId.value = <string>route.query.tId; taskId.value = <string>route.query.tId;
projectId.value = <string>route.query.processInstanceId; projectId.value = <string>route.query.processInstanceId;
getProjectDetail(projectId.value); getProjectDetail(projectId.value);
@@ -33,11 +33,12 @@ onMounted(() =>{
<el-card> <el-card>
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="isPreview ? 24 : 18"> <el-col :span="isPreview ? 24 : 18">
<FlowFormView :process-instance-id="projectId"/> <FlowFormView :process-instance-id="projectId" />
<ProjectProgressReportFormDeatils v-model="detailFormData" title="投资项目进度审核"/> <ProjectProgressReportFormDeatils v-model="detailFormData" title="投资项目进度审核" />
</el-col> </el-col>
<el-col :span="6" v-if="!isPreview"> <el-col :span="6" v-if="!isPreview">
<ApprovalAction :status="status" :approval-records="[]" :task-id="taskId" :process-instance-id="projectId"/> <ApprovalAction :status="status" :approval-records="[]" :task-id="taskId"
:process-instance-id="projectId" />
</el-col> </el-col>
</el-row> </el-row>
</el-card> </el-card>

View File

@@ -26,8 +26,9 @@
</el-row> </el-row>
<el-row class="mb10"> <el-row class="mb10">
<el-form :model="headerForm" label-width="80px" class="w-full"> <el-form :model="headerForm" :rules="headerFormRules" ref="headerFormRef" label-width="80px"
<el-form-item :label="t('projectExitFeedback.headerForm.title')"> class="w-full">
<el-form-item :label="t('projectExitFeedback.headerForm.title')" prop="title" required>
<el-input v-model="headerForm.title" <el-input v-model="headerForm.title"
:placeholder="t('projectExitFeedback.headerForm.titlePlaceholder')" /> :placeholder="t('projectExitFeedback.headerForm.titlePlaceholder')" />
</el-form-item> </el-form-item>
@@ -36,7 +37,8 @@
:placeholder="t('projectExitFeedback.headerForm.descriptionPlaceholder')" /> :placeholder="t('projectExitFeedback.headerForm.descriptionPlaceholder')" />
</el-form-item> </el-form-item>
<el-form-item :label="t('projectExitFeedback.headerForm.attachments')"> <el-form-item :label="t('projectExitFeedback.headerForm.attachments')">
<UploadFile :modelValue="headerForm.attachments" @change="uploadChange" :fileSize="20" type="simple" :limit="10" /> <UploadFile :modelValue="headerForm.attachments" @change="uploadChange" :fileSize="20"
type="simple" :limit="10" />
</el-form-item> </el-form-item>
</el-form> </el-form>
</el-row> </el-row>
@@ -47,20 +49,25 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { reactive } from 'vue'; import { reactive, ref } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useMessage } from '/@/hooks/message'; import { useMessage } from '/@/hooks/message';
import ProjectExitFeedbackForm from '/@/components/investment/common/ProjectExitFeedbackForm.vue'; import ProjectExitFeedbackForm from '/@/components/investment/common/ProjectExitFeedbackForm.vue';
import { ProjectExitFeedback } from '/@/views/invMid/projectExitFeedback/interface/type'; import { ProjectExitFeedback } from '/@/views/invMid/projectExitFeedback/interface/type';
import {addProjectExitPlanFeedback} from "/@/api/investment/projectExitPlan"; import { addProjectExitPlanFeedback } from "/@/api/investment/projectExitPlan";
import { ProjectTask } from "/@/views/invMid/projectExitPlan/interface/type";
import UploadFile from "/@/components/Upload/index.vue"; import UploadFile from "/@/components/Upload/index.vue";
import {flowFn} from "/@/utils/flowFn"; import { flowFn } from "/@/utils/flowFn";
import {addFlowForm} from "/@/api/flow/flow"; import { addFlowForm } from "/@/api/flow/flow";
import {flowNameOptions} from "/@/hooks/enums"; import { flowNameOptions } from "/@/hooks/enums";
const { t } = useI18n(); const { t } = useI18n();
const message = useMessage(); const message = useMessage();
const headerForm = reactive<{ title: string, description: string, attachments: any[] | string}>({ const headerFormRef = ref<any>();
const headerFormRules = {
title: [{ required: true, message: '标题必填', trigger: ['blur', 'change'] }]
};
const headerForm = reactive<{ title: string, description: string, attachments: any[] | string }>({
title: '', title: '',
description: '', description: '',
attachments: [] as any[], attachments: [] as any[],
@@ -68,47 +75,57 @@ const headerForm = reactive<{ title: string, description: string, attachments: a
const formData = ref<ProjectExitFeedback>({ const formData = ref<ProjectExitFeedback>({
exitTime: '', exitTime: '',
exitExecutor: '', exitExecutor: '',
exitRemark: '', exitRemark: '',
exitAttachment: '', exitAttachment: '',
deptId: '',
}); });
const submitLoading = ref(false); const submitLoading = ref(false);
const handleInitiateApproval = async () => { const handleInitiateApproval = async () => {
if (!formData.value.projectId){ const headerValid = await headerFormRef.value?.validate().catch(() => false);
message.error('项目名称必填'); if (!headerValid) {
return return;
} }
submitLoading.value = true; if (!formData.value.projectId) {
const attachments = JSON.stringify(headerForm.attachments); message.error('项目名称必填');
const {processInstanceId} = await flowFn('VITE_FLOWID_36',{ return
paramMap:{ }
// miu0ilc1tfa61_assignee_select: [ submitLoading.value = true;
// { const attachments = JSON.stringify(headerForm.attachments);
// "type": "user", const flowResult = await flowFn('VITE_FLOWID_36', {
// "id": "1", paramMap: {
// "name": "admin", // miu0ilc1tfa61_assignee_select: [
// "avatar": "/admin/sys-file/local/2a14ae08150e483c93e12ac8934173e2.png" // {
// } // "type": "user",
// ] // "id": "1",
} // "name": "admin",
}) // "avatar": "/admin/sys-file/local/2a14ae08150e483c93e12ac8934173e2.png"
const flowNameObj = flowNameOptions.filter(item => item.label === 'exitFeedback')[0] // }
await addFlowForm({ // ]
title: headerForm.title, }
description: headerForm.description, })
attachments, if (flowResult instanceof Error) {
processInstanceId, submitLoading.value = false;
flowType: flowNameObj.value throw flowResult;
}) }
formData.value.processInstanceId = processInstanceId; const { processInstanceId } = flowResult;
const exitAttachment = JSON.stringify(formData.value.exitAttachment); const flowNameObj = flowNameOptions.filter(item => item.label === 'exitFeedback')[0]
const params = { ...formData.value, exitAttachment } await addFlowForm({
addProjectExitPlanFeedback(params).then(()=>{ title: headerForm.title,
message.success(t('common.success')); description: headerForm.description,
}).catch((err: any) => { attachments,
message.error(err.msg); processInstanceId,
}).finally(() => { flowType: flowNameObj.value
submitLoading.value = false; })
}); formData.value.processInstanceId = processInstanceId;
const exitAttachment = JSON.stringify(formData.value.exitAttachment);
const params = { ...formData.value, exitAttachment } as ProjectTask;
addProjectExitPlanFeedback(params).then(() => {
message.success(t('common.success'));
}).catch((err: any) => {
message.error(err.msg);
}).finally(() => {
submitLoading.value = false;
});
}; };
const handleSaveDraft = () => { const handleSaveDraft = () => {
@@ -126,17 +143,17 @@ const handleSaveTemplate = () => {
const handleViewWorkflow = () => { const handleViewWorkflow = () => {
message.info(t('projectExitFeedback.messages.viewWorkflow')); message.info(t('projectExitFeedback.messages.viewWorkflow'));
}; };
const uploadChange = (_:any,data:any[]) =>{ const uploadChange = (_: any, data: any[]) => {
if (!data || Object.prototype.toString.call(data) !== '[object Array]' || data.length === 0){ if (!data || Object.prototype.toString.call(data) !== '[object Array]' || data.length === 0) {
headerForm.attachments = []; headerForm.attachments = [];
return; return;
} }
headerForm.attachments = data.map((item:any) => { headerForm.attachments = data.map((item: any) => {
return { return {
name: item.name, name: item.name,
url: item.url url: item.url
} }
}) })
} }
</script> </script>

View File

@@ -34,10 +34,12 @@ export interface ProjectExitFeedback {
/** 状态 */ /** 状态 */
status?: string; status?: string;
/** 项目id */ /** 项目id */
projectId?:number; projectId?: number;
/** 项目名称*/ /** 项目名称*/
projectName?:string; projectName?: string;
/** 部门id */
deptId: string;
} }
export interface paramsDataProjectExitPlanFeedback { export interface paramsDataProjectExitPlanFeedback {
@@ -48,31 +50,31 @@ export interface paramsDataProjectExitPlanFeedback {
exitRemark: string exitRemark: string
} }
export interface projectExitPlanFeedbackItem { export interface projectExitPlanFeedbackItem {
id?: number, id?: number,
projectName?: string, projectName?: string,
projectId?: number, projectId?: number,
exitRecommendation?: string, exitRecommendation?: string,
exitMethod?: string, exitMethod?: string,
executionTask?: string, executionTask?: string,
taskDescription?: string, taskDescription?: string,
executor?: string, executor?: string,
taskStartDate?: string, taskStartDate?: string,
taskEndDate?: string, taskEndDate?: string,
createBy?: string, createBy?: string,
createTime?: string, createTime?: string,
updateBy?: string, updateBy?: string,
updateTime?: string, updateTime?: string,
delFlag?: string, delFlag?: string,
processInstanceId?: string, processInstanceId?: string,
status?: string, status?: string,
reviewNotes?: string, reviewNotes?: string,
applicationDept?: string applicationDept?: string
} }
export interface feedbackResponseData { export interface feedbackResponseData {
total: number, total: number,
records: projectExitPlanFeedbackItem[]; records: projectExitPlanFeedbackItem[];
current: number, current: number,
size: number, size: number,
pages: number, pages: number,
} }

View File

@@ -1,53 +1,55 @@
<template> <template>
<div class="layout-padding"> <div class="layout-padding">
<div class="layout-padding-auto layout-padding-view"> <div class="layout-padding-auto layout-padding-view">
<el-row class="mb10"> <el-row class="mb10">
<div class="form-header-actions" style="width: 100%;"> <div class="form-header-actions" style="width: 100%;">
<div> <div>
<el-button type="primary" icon="Check" :loading="submitLoading" @click="handleInitiateApproval"> <el-button type="primary" icon="Check" :loading="submitLoading" @click="handleInitiateApproval">
{{ t('projectExitPlan.actions.initiateApproval') }} {{ t('projectExitPlan.actions.initiateApproval') }}
</el-button> </el-button>
<el-button icon="Document" @click="handleSaveDraft"> <el-button icon="Document" @click="handleSaveDraft">
{{ t('projectExitPlan.actions.saveDraft') }} {{ t('projectExitPlan.actions.saveDraft') }}
</el-button> </el-button>
<el-button icon="FolderOpened" @click="handleLoadTemplate"> <el-button icon="FolderOpened" @click="handleLoadTemplate">
{{ t('projectExitPlan.actions.loadTemplate') }} {{ t('projectExitPlan.actions.loadTemplate') }}
</el-button> </el-button>
<el-button icon="FolderAdd" @click="handleSaveTemplate"> <el-button icon="FolderAdd" @click="handleSaveTemplate">
{{ t('projectExitPlan.actions.saveTemplate') }} {{ t('projectExitPlan.actions.saveTemplate') }}
</el-button> </el-button>
</div> </div>
<div style="margin-left:auto;"> <div style="margin-left:auto;">
<el-button icon="View" @click="handleViewWorkflow"> <el-button icon="View" @click="handleViewWorkflow">
{{ t('projectExitPlan.actions.viewWorkflow') }} {{ t('projectExitPlan.actions.viewWorkflow') }}
</el-button> </el-button>
</div> </div>
</div> </div>
</el-row> </el-row>
<el-row class="mb10"> <el-row class="mb10">
<el-form :model="headerForm" label-width="80px" class="w-full"> <el-form :model="headerForm" :rules="headerFormRules" ref="headerFormRef" label-width="80px"
<el-form-item :label="t('projectExitPlan.headerForm.title')"> class="w-full">
<el-input v-model="headerForm.title" <el-form-item :label="t('projectExitPlan.headerForm.title')" prop="title" required>
:placeholder="t('projectExitPlan.headerForm.titlePlaceholder')" /> <el-input v-model="headerForm.title"
</el-form-item> :placeholder="t('projectExitPlan.headerForm.titlePlaceholder')" />
<el-form-item :label="t('projectExitPlan.headerForm.description')"> </el-form-item>
<el-input v-model="headerForm.description" <el-form-item :label="t('projectExitPlan.headerForm.description')">
:placeholder="t('projectExitPlan.headerForm.descriptionPlaceholder')" /> <el-input v-model="headerForm.description"
</el-form-item> :placeholder="t('projectExitPlan.headerForm.descriptionPlaceholder')" />
<el-form-item :label="t('projectExitPlan.headerForm.attachments')"> </el-form-item>
<UploadFile :modelValue="headerForm.attachments" @change="uploadChange" :fileSize="20" type="simple" :limit="10" /> <el-form-item :label="t('projectExitPlan.headerForm.attachments')">
</el-form-item> <UploadFile :modelValue="headerForm.attachments" @change="uploadChange" :fileSize="20"
</el-form> type="simple" :limit="10" />
</el-row> </el-form-item>
</el-form>
</el-row>
<ProjectExitPlanForm v-model="formData" :rules="rules" ref="formDataRef"/> <ProjectExitPlanForm v-model="formData" :rules="rules" ref="formDataRef" />
</div> </div>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { reactive } from 'vue'; import { reactive, ref } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useMessage } from '/@/hooks/message'; import { useMessage } from '/@/hooks/message';
@@ -56,28 +58,33 @@ import ProjectExitPlanForm from '/@/components/investment/common/ProjectExitPlan
import { FormRules } from 'element-plus'; import { FormRules } from 'element-plus';
import { addProjectExitPlan } from '/@/api/investment/projectExitPlan'; import { addProjectExitPlan } from '/@/api/investment/projectExitPlan';
import UploadFile from "/@/components/Upload/index.vue"; import UploadFile from "/@/components/Upload/index.vue";
import {flowFn} from "/@/utils/flowFn"; import { flowFn } from "/@/utils/flowFn";
import {addFlowForm} from "/@/api/flow/flow"; import { addFlowForm } from "/@/api/flow/flow";
import {flowNameOptions} from "/@/hooks/enums"; import { flowNameOptions } from "/@/hooks/enums";
const formDataRef = ref<HTMLFormElement | null>() const formDataRef = ref<HTMLFormElement | null>()
const { t } = useI18n(); const { t } = useI18n();
const message = useMessage(); const message = useMessage();
const headerForm = reactive<{ title: string, description: string, attachments: any[] | string}>({ const headerFormRef = ref<any>();
title: '', const headerFormRules = {
description: '', title: [{ required: true, message: '标题必填', trigger: ['blur', 'change'] }]
attachments: [] as any[], };
const headerForm = reactive<{ title: string, description: string, attachments: any[] | string }>({
title: '',
description: '',
attachments: [] as any[],
}); });
const formData = ref<ProjectTask>({ const formData = ref<ProjectTask>({
id: undefined, id: undefined,
projectName: '', projectName: '',
exitRecommendation: '', exitRecommendation: '',
executionTask:'', executionTask: '',
taskDescription:'', taskDescription: '',
executor:'', executor: '',
taskStartDate:new Date().toISOString().substring(0,10), taskStartDate: new Date().toISOString().substring(0, 10),
taskEndDate:new Date().toISOString().substring(0,10), taskEndDate: new Date().toISOString().substring(0, 10),
deptId: ''
}); });
const requiredRule = [{ required: true, message: `${t('该字段必填')}` }] const requiredRule = [{ required: true, message: `${t('该字段必填')}` }]
const rules = reactive<FormRules<ProjectTask>>({ const rules = reactive<FormRules<ProjectTask>>({
@@ -87,13 +94,17 @@ const rules = reactive<FormRules<ProjectTask>>({
const submitLoading = ref<boolean>(false); const submitLoading = ref<boolean>(false);
const handleInitiateApproval = async () => { const handleInitiateApproval = async () => {
try { try {
const valid = await formDataRef?.value?.validateRef(); const headerValid = await headerFormRef.value?.validate().catch(() => false);
if (!headerValid) {
return;
}
const valid = await formDataRef?.value?.validateRef();
if (!valid) return; if (!valid) return;
submitLoading.value = true; submitLoading.value = true;
const folowIdKey = 'VITE_FLOWID_35' const folowIdKey = 'VITE_FLOWID_35'
const attachments = JSON.stringify(headerForm.attachments); const attachments = JSON.stringify(headerForm.attachments);
const {processInstanceId} = await flowFn(folowIdKey,{ const flowResult = await flowFn(folowIdKey, {
paramMap:{ paramMap: {
// miu0ilc1tfa61_assignee_select: [ // miu0ilc1tfa61_assignee_select: [
// { // {
// "type": "user", // "type": "user",
@@ -104,6 +115,11 @@ const handleInitiateApproval = async () => {
// ] // ]
} }
}) })
if (flowResult instanceof Error) {
submitLoading.value = false;
throw flowResult;
}
const { processInstanceId } = flowResult;
const flowNameObj = flowNameOptions.filter(item => item.label === 'exitPlan')[0] const flowNameObj = flowNameOptions.filter(item => item.label === 'exitPlan')[0]
await addFlowForm({ await addFlowForm({
title: headerForm.title, title: headerForm.title,
@@ -113,14 +129,14 @@ const handleInitiateApproval = async () => {
flowType: flowNameObj.value flowType: flowNameObj.value
}) })
formData.value.processInstanceId = processInstanceId; formData.value.processInstanceId = processInstanceId;
addProjectExitPlan(formData.value).then((res:any) => { addProjectExitPlan(formData.value).then((res: any) => {
useMessage().success(t('common.success')); useMessage().success(t('common.success'));
}).catch((err:any) => { }).catch((err: any) => {
useMessage().error(err.msg); useMessage().error(err.msg);
}).finally(() => { }).finally(() => {
submitLoading.value = false; submitLoading.value = false;
}); });
}catch (e) { } catch (e) {
console.log(e); console.log(e);
submitLoading.value = false; submitLoading.value = false;
} }
@@ -128,26 +144,26 @@ const handleInitiateApproval = async () => {
}; };
const handleSaveDraft = () => { const handleSaveDraft = () => {
message.info(t('projectExitPlan.messages.saveDraft')); message.info(t('projectExitPlan.messages.saveDraft'));
}; };
const handleLoadTemplate = () => { const handleLoadTemplate = () => {
message.info(t('projectExitPlan.messages.loadTemplate')); message.info(t('projectExitPlan.messages.loadTemplate'));
}; };
const handleSaveTemplate = () => { const handleSaveTemplate = () => {
message.info(t('projectExitPlan.messages.saveTemplate')); message.info(t('projectExitPlan.messages.saveTemplate'));
}; };
const handleViewWorkflow = () => { const handleViewWorkflow = () => {
message.info(t('projectExitPlan.messages.viewWorkflow')); message.info(t('projectExitPlan.messages.viewWorkflow'));
}; };
const uploadChange = (_:any,data:any[]) =>{ const uploadChange = (_: any, data: any[]) => {
if (!data || Object.prototype.toString.call(data) !== '[object Array]' || data.length === 0){ if (!data || Object.prototype.toString.call(data) !== '[object Array]' || data.length === 0) {
headerForm.attachments = []; headerForm.attachments = [];
return; return;
} }
headerForm.attachments = data.map((item:any) => { headerForm.attachments = data.map((item: any) => {
return { return {
name: item.name, name: item.name,
url: item.url url: item.url
@@ -158,13 +174,13 @@ const uploadChange = (_:any,data:any[]) =>{
<style scoped> <style scoped>
.layout-container .layout-padding { .layout-container .layout-padding {
height: auto; height: auto;
overflow: auto; overflow: auto;
} }
.form-header-actions { .form-header-actions {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
} }
</style> </style>