first commit

This commit is contained in:
2025-12-26 23:19:09 +08:00
commit b29d128e41
788 changed files with 100922 additions and 0 deletions

View File

@@ -0,0 +1,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>