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