518 lines
21 KiB
Vue
518 lines
21 KiB
Vue
<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: '',
|
|
deptId: ''
|
|
})
|
|
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 = String(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>
|