diff --git a/web/src/views/cw/application/form.vue b/web/src/views/cw/application/form.vue
index 9639b93d..dd1a5636 100644
--- a/web/src/views/cw/application/form.vue
+++ b/web/src/views/cw/application/form.vue
@@ -215,53 +215,56 @@
@@ -710,14 +713,13 @@ const rules = {
startDate: [{ required: true, message: '请选择项目开始日期', trigger: 'change' }],
endDate: [{ required: true, message: '请选择项目结束日期', trigger: 'change' }],
totalInvestment: [
- { required: true, message: '请填写项目总投资', trigger: 'blur' },
{ type: 'number' as const, min: 0.01, message: '投资金额必须大于0', trigger: 'blur' }
]
};
// 计算属性
const canSubmit = computed(() => {
- return form.projectName && form.principal && form.totalInvestment > 0;
+ return form.projectName && form.principal && totalInvestmentCalculated.value > 0;
});
const hasBudgetData = computed(() => {
@@ -734,6 +736,26 @@ const yearlyTotals = computed(() => {
};
});
+// 市财政资金总额(基于分年度明细自动汇总)
+const totalMunicipalFiscalCalculated = computed(() => {
+ return (form.currentYearMunicipal || 0) + (form.nextYearMunicipal || 0) + (form.futureYearMunicipal || 0);
+});
+
+// 单位自筹总额(基于分年度明细自动汇总)
+const totalSelfFundingCalculated = computed(() => {
+ return (form.currentYearSelf || 0) + (form.nextYearSelf || 0) + (form.futureYearSelf || 0);
+});
+
+// 其他资金总额(基于分年度明细自动汇总)
+const totalOtherFundingCalculated = computed(() => {
+ return (form.currentYearOther || 0) + (form.nextYearOther || 0) + (form.futureYearOther || 0);
+});
+
+// 项目总投资(基于三个汇总字段自动计算)
+const totalInvestmentCalculated = computed(() => {
+ return totalMunicipalFiscalCalculated.value + totalSelfFundingCalculated.value + totalOtherFundingCalculated.value;
+});
+
// 分年度预算明细数据
const budgetBreakdownData = computed(() => {
const currentYear = parseInt(form.year) || new Date().getFullYear();
@@ -784,30 +806,22 @@ const updateBudgetBreakdown = (index: number) => {
recalculateTotalFromBreakdown();
};
-// 从分年度明细重新计算总投资
+// 从分年度明细重新计算总投资(使用计算属性)
const recalculateTotalFromBreakdown = () => {
- const totalMunicipal = (form.currentYearMunicipal || 0) + (form.nextYearMunicipal || 0) + (form.futureYearMunicipal || 0);
- const totalSelf = (form.currentYearSelf || 0) + (form.nextYearSelf || 0) + (form.futureYearSelf || 0);
- const totalOther = (form.currentYearOther || 0) + (form.nextYearOther || 0) + (form.futureYearOther || 0);
-
- form.totalMunicipalFiscal = totalMunicipal;
- form.totalSelfFunding = totalSelf;
- form.totalOtherFunding = totalOther;
- form.totalInvestment = totalMunicipal + totalSelf + totalOther;
+ // 使用计算属性自动同步到表单字段
+ form.totalMunicipalFiscal = totalMunicipalFiscalCalculated.value;
+ form.totalSelfFunding = totalSelfFundingCalculated.value;
+ form.totalOtherFunding = totalOtherFundingCalculated.value;
+ form.totalInvestment = totalInvestmentCalculated.value;
};
-// 计算预算汇总
+// 计算预算汇总(使用计算属性)
const calculateBudgetSummary = () => {
- // 计算各类资金的总和
- const totalMunicipal = (form.currentYearMunicipal || 0) + (form.nextYearMunicipal || 0) + (form.futureYearMunicipal || 0);
- const totalSelf = (form.currentYearSelf || 0) + (form.nextYearSelf || 0) + (form.futureYearSelf || 0);
- const totalOther = (form.currentYearOther || 0) + (form.nextYearOther || 0) + (form.futureYearOther || 0);
-
- // 更新总投资字段
- form.totalMunicipalFiscal = totalMunicipal;
- form.totalSelfFunding = totalSelf;
- form.totalOtherFunding = totalOther;
- form.totalInvestment = totalMunicipal + totalSelf + totalOther;
+ // 使用计算属性自动同步到表单字段
+ form.totalMunicipalFiscal = totalMunicipalFiscalCalculated.value;
+ form.totalSelfFunding = totalSelfFundingCalculated.value;
+ form.totalOtherFunding = totalOtherFundingCalculated.value;
+ form.totalInvestment = totalInvestmentCalculated.value;
// 更新图表
if (budgetChartInstance && hasBudgetData.value) {
@@ -820,9 +834,13 @@ const formatAmount = (amount: number): string => {
return amount ? amount.toFixed(2) : '0.00';
};
-// 计算总投资
-const calculateTotalInvestment = () => {
- form.totalInvestment = (form.totalMunicipalFiscal || 0) + (form.totalSelfFunding || 0) + (form.totalOtherFunding || 0);
+// 更新所有总投资相关字段(从分年度明细计算)
+const updateTotalInvestmentFromSubItems = () => {
+ // 自动同步所有计算值到表单字段(用于后端提交)
+ form.totalMunicipalFiscal = totalMunicipalFiscalCalculated.value;
+ form.totalSelfFunding = totalSelfFundingCalculated.value;
+ form.totalOtherFunding = totalOtherFundingCalculated.value;
+ form.totalInvestment = totalInvestmentCalculated.value;
// 更新图表
if (budgetChartInstance && hasBudgetData.value) {
@@ -830,6 +848,26 @@ const calculateTotalInvestment = () => {
}
};
+// 保留原函数名以兼容其他调用
+const calculateTotalInvestment = updateTotalInvestmentFromSubItems;
+
+// 监听分年度字段变化,自动同步所有总计字段
+watch(
+ () => [
+ form.currentYearMunicipal, form.nextYearMunicipal, form.futureYearMunicipal,
+ form.currentYearSelf, form.nextYearSelf, form.futureYearSelf,
+ form.currentYearOther, form.nextYearOther, form.futureYearOther
+ ],
+ () => {
+ // 同步计算值到表单字段(用于后端提交)
+ form.totalMunicipalFiscal = totalMunicipalFiscalCalculated.value;
+ form.totalSelfFunding = totalSelfFundingCalculated.value;
+ form.totalOtherFunding = totalOtherFundingCalculated.value;
+ form.totalInvestment = totalInvestmentCalculated.value;
+ },
+ { immediate: true }
+);
+
// 渲染预算图表
const renderBudgetChart = () => {
if (!budgetChartInstance) return;
@@ -999,6 +1037,9 @@ const handleSaveDraft = async () => {
try {
savingDraft.value = true;
+ // 同步计算的总投资到表单字段
+ form.totalInvestment = totalInvestmentCalculated.value;
+
// 如果当前在绩效指标步骤(第3步),校验分值占比总和
if (currentStep.value === 3 && form.performanceIndicators && form.performanceIndicators.length > 0) {
const validationResult = validatePerformanceIndicators();
@@ -1032,6 +1073,9 @@ const handleSubmit = async () => {
try {
submitting.value = true;
+ // 同步计算的总投资到表单字段
+ form.totalInvestment = totalInvestmentCalculated.value;
+
console.log('开始提交申报流程,form.id:', form.id);
// 先保存数据
diff --git a/web/src/views/cw/application/index.vue b/web/src/views/cw/application/index.vue
index 8e09d93b..6ebbb91f 100644
--- a/web/src/views/cw/application/index.vue
+++ b/web/src/views/cw/application/index.vue
@@ -1,61 +1,5 @@
-
-
-
-
-
-
-
-
-
-
{{ totalCount }}
-
总申报数
-
-
-
-
-
-
-
-
-
-
-
-
{{ approvedCount }}
-
已通过
-
-
-
-
-
-
-
-
-
-
-
-
{{ pendingCount }}
-
审批中
-
-
-
-
-
-
-
-
-
-
-
-
{{ draftCount }}
-
草稿
-
-
-
-
-
-
@@ -252,8 +196,7 @@ import {
delProjectApplication,
addProjectApplication,
updateProjectApplication,
- submitApplication,
- getApplicationStatistics
+ submitApplication
} from '@/api/cw/projectApplication';
import { startCustomApprovalProcess, type CwCustomApprovalRequest } from '@/api/cw/projectApproval';
import { getInfo } from '@/api/login';
@@ -308,11 +251,6 @@ export default {
form: {},
// 表单校验
rules: {},
- // 统计数据
- totalCount: 0,
- approvedCount: 0,
- pendingCount: 0,
- draftCount: 0,
// 审批流程选择对话框
approvalProcessDialog: {
visible: false,
@@ -324,7 +262,6 @@ export default {
},
created() {
this.getList();
- this.getStatistics();
},
methods: {
/** 查询项目申报列表 */
@@ -345,27 +282,6 @@ export default {
this.$message.error('获取数据失败,请检查网络连接或联系管理员');
});
},
- /** 获取统计数据 */
- getStatistics() {
- // 调用专门的统计API接口
- const year = this.queryParams.year ? parseInt(this.queryParams.year) : null;
- getApplicationStatistics(year)
- .then((response) => {
- const data = response.data;
- this.totalCount = data.totalCount || 0;
- this.approvedCount = data.approvedCount || 0;
- this.pendingCount = data.approvingCount || 0; // 注意:后端返回的是approvingCount
- this.draftCount = data.draftCount || 0;
- })
- .catch((error) => {
- console.error('获取统计数据失败:', error);
- // 如果API失败,使用本地计算作为后备方案
- this.totalCount = this.applicationList.length;
- this.approvedCount = this.applicationList.filter((item) => item.approvalStatus === 'approved').length;
- this.pendingCount = this.applicationList.filter((item) => item.approvalStatus === 'approving').length;
- this.draftCount = this.applicationList.filter((item) => item.approvalStatus === 'draft').length;
- });
- },
/** 取消按钮 */
cancel() {
this.open = false;
@@ -416,7 +332,6 @@ export default {
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
- this.getStatistics(); // 搜索时也更新统计数据
},
/** 重置按钮操作 */
resetQuery() {
@@ -463,14 +378,12 @@ export default {
this.$modal.msgSuccess('修改成功');
this.open = false;
this.getList();
- this.getStatistics(); // 修改后更新统计
});
} else {
addProjectApplication(this.form).then((response) => {
this.$modal.msgSuccess('新增成功');
this.open = false;
this.getList();
- this.getStatistics(); // 新增后更新统计
});
}
} else {
@@ -488,7 +401,6 @@ export default {
})
.then(() => {
this.getList();
- this.getStatistics(); // 删除后更新统计
this.$modal.msgSuccess('删除成功');
})
.catch(() => {});
@@ -565,9 +477,8 @@ export default {
this.approvalProcessDialog.applicationNo = null;
this.approvalProcessDialog.selectedAuditors = [];
- // 刷新列表和统计
+ // 刷新列表
this.getList();
- this.getStatistics();
this.$modal.msgSuccess('审批流程启动成功');
} catch (error) {
@@ -590,7 +501,6 @@ export default {
// 调用撤回接口
this.$modal.msgSuccess('撤回成功');
this.getList();
- this.getStatistics(); // 撤回后更新统计
})
.catch(() => {});
},
@@ -650,74 +560,6 @@ export default {
padding: 8px;
}
-/* 统计卡片样式 */
-.stats-row {
- margin-bottom: 20px;
-}
-
-.stat-card {
- border-radius: 12px;
- transition: all 0.3s ease;
- height: 90px;
- cursor: pointer;
-
- &:hover {
- transform: translateY(-2px);
- box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
- }
-
- .stat-content {
- display: flex;
- align-items: center;
- padding: 5px 16px;
- height: 100%;
- box-sizing: border-box;
-
- .stat-icon {
- font-size: 28px;
- margin-right: 15px;
- opacity: 0.9;
- }
-
- .stat-info {
- flex: 1;
-
- .stat-value {
- font-size: 24px;
- font-weight: bold;
- line-height: 1;
- margin-bottom: 4px;
- }
-
- .stat-label {
- font-size: 14px;
- opacity: 0.8;
- line-height: 1;
- }
- }
- }
-
- &.stat-card-primary {
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
- color: white;
- }
-
- &.stat-card-success {
- background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
- color: white;
- }
-
- &.stat-card-warning {
- background: linear-gradient(135deg, #ff9a56 0%, #ffad56 100%);
- color: white;
- }
-
- &.stat-card-info {
- background: linear-gradient(135deg, #a8edea 0%, #fed6e3 100%);
- color: #333;
- }
-}
-
/* 搜索按钮居中样式 */
.search-btn-container {
display: flex;
@@ -884,11 +726,6 @@ export default {
.page-container {
padding: 10px;
- .stats-row {
- .stat-card {
- margin-bottom: 10px;
- }
- }
}
}