wuzhen 1 год назад
Родитель
Сommit
8199dd38b1
2 измененных файлов с 80 добавлено и 199 удалено
  1. 78 34
      web/src/views/cw/application/form.vue
  2. 2 165
      web/src/views/cw/application/index.vue

+ 78 - 34
web/src/views/cw/application/form.vue

@@ -215,53 +215,56 @@
               <el-col :span="6">
                 <el-form-item label="项目总投资" prop="totalInvestment">
                   <el-input-number
-                    v-model="form.totalInvestment"
+                    :model-value="totalInvestmentCalculated"
                     :precision="2"
                     :min="0"
-                    :max="99999999"
                     placeholder="万元"
                     size="large"
                     style="width: 100%"
-                    @change="calculateTotalInvestment"
+                    :disabled="true"
+                    readonly
                   />
                 </el-form-item>
               </el-col>
               <el-col :span="6">
                 <el-form-item label="市财政资金" prop="totalMunicipalFiscal">
                   <el-input-number
-                    v-model="form.totalMunicipalFiscal"
+                    :model-value="totalMunicipalFiscalCalculated"
                     :precision="2"
                     :min="0"
                     placeholder="万元"
                     size="large"
                     style="width: 100%"
-                    @change="calculateTotalInvestment"
+                    disabled="true"
+                    readonly
                   />
                 </el-form-item>
               </el-col>
               <el-col :span="6">
                 <el-form-item label="单位自筹" prop="totalSelfFunding">
                   <el-input-number
-                    v-model="form.totalSelfFunding"
+                    :model-value="totalSelfFundingCalculated"
                     :precision="2"
                     :min="0"
                     placeholder="万元"
                     size="large"
                     style="width: 100%"
-                    @change="calculateTotalInvestment"
+                    disabled="true"
+                    readonly
                   />
                 </el-form-item>
               </el-col>
               <el-col :span="6">
                 <el-form-item label="其他资金" prop="totalOtherFunding">
                   <el-input-number
-                    v-model="form.totalOtherFunding"
+                    :model-value="totalOtherFundingCalculated"
                     :precision="2"
                     :min="0"
                     placeholder="万元"
                     size="large"
                     style="width: 100%"
-                    @change="calculateTotalInvestment"
+                    disabled="true"
+                    readonly
                   />
                 </el-form-item>
               </el-col>
@@ -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);
 
     // 先保存数据

+ 2 - 165
web/src/views/cw/application/index.vue

@@ -1,61 +1,5 @@
 <template>
   <div class="page-container">
-    <!-- 统计卡片区域 -->
-    <el-row :gutter="20" class="stats-row">
-      <el-col :span="6">
-        <div class="stat-card stat-card-primary">
-          <div class="stat-content">
-            <div class="stat-icon">
-              <el-icon><Document /></el-icon>
-            </div>
-            <div class="stat-info">
-              <div class="stat-value">{{ totalCount }}</div>
-              <div class="stat-label">总申报数</div>
-            </div>
-          </div>
-        </div>
-      </el-col>
-      <el-col :span="6">
-        <div class="stat-card stat-card-success">
-          <div class="stat-content">
-            <div class="stat-icon">
-              <el-icon><Check /></el-icon>
-            </div>
-            <div class="stat-info">
-              <div class="stat-value">{{ approvedCount }}</div>
-              <div class="stat-label">已通过</div>
-            </div>
-          </div>
-        </div>
-      </el-col>
-      <el-col :span="6">
-        <div class="stat-card stat-card-warning">
-          <div class="stat-content">
-            <div class="stat-icon">
-              <el-icon><Clock /></el-icon>
-            </div>
-            <div class="stat-info">
-              <div class="stat-value">{{ pendingCount }}</div>
-              <div class="stat-label">审批中</div>
-            </div>
-          </div>
-        </div>
-      </el-col>
-      <el-col :span="6">
-        <div class="stat-card stat-card-info">
-          <div class="stat-content">
-            <div class="stat-icon">
-              <el-icon><EditPen /></el-icon>
-            </div>
-            <div class="stat-info">
-              <div class="stat-value">{{ draftCount }}</div>
-              <div class="stat-label">草稿</div>
-            </div>
-          </div>
-        </div>
-      </el-col>
-    </el-row>
-
     <!-- 搜索区域 -->
     <el-card class="button-card" v-show="showSearch">
       <template #header>
@@ -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;
-      }
-    }
   }
 }
 </style>