소스 검색

Merge branch 'master' of http://47.99.164.66:3000/hzdyjs-xg/all-project

zlwu 1 년 전
부모
커밋
59c666a6f4

+ 142 - 6
web/src/views/bzrkh/teacherAssessment/submitDialog.vue

@@ -157,7 +157,14 @@
             </el-col>
             <el-col :span="8">
               <el-form-item>
-                <el-button type="info" plain @click="handleViewStudentViolations">学生违规处分信息查看</el-button>
+                <el-button 
+              :type="studentRecordsData ? 'success' : 'info'" 
+              :plain="!studentRecordsData" 
+              @click="handleViewStudentViolations"
+            >
+              <i :class="studentRecordsData ? 'el-icon-check' : 'el-icon-view'" style="margin-right: 4px;"></i>
+              {{ studentRecordsData ? '查看已加载的违规处分信息' : '学生违规处分信息查看' }}
+            </el-button>
               </el-form-item>
             </el-col>
           </el-row>
@@ -374,6 +381,28 @@
       <el-tabs v-model="studentRecordsActiveTab" type="border-card" style="margin-top: 16px">
         <!-- 违纪记录Tab -->
         <el-tab-pane label="违纪记录" name="discipline">
+          <!-- 扣分汇总信息 -->
+          <el-row :gutter="20" style="margin-bottom: 16px;">
+            <el-col :span="16">
+              <el-alert 
+                :title="`违纪记录扣分汇总: ${calculateTotalDeduction()} 分 (生效记录: ${getEffectiveDisciplineRecords().length} 条)`" 
+                type="warning" 
+                :closable="false"
+                show-icon
+              />
+            </el-col>
+            <el-col :span="8" style="text-align: right;">
+              <el-button 
+                type="primary" 
+                icon="Refresh" 
+                @click="applyDeductionToClassScore"
+                :disabled="calculateTotalDeduction() === 0"
+              >
+                重新同步到班级扣分
+              </el-button>
+            </el-col>
+          </el-row>
+          
           <el-table :data="studentRecordsData?.disciplineRecords || []" border style="width: 100%" max-height="400" empty-text="暂无违纪记录">
             <el-table-column type="index" label="序号" width="60" align="center" />
             <el-table-column prop="studentNo" label="学号" min-width="120" align="center" />
@@ -388,7 +417,12 @@
             <el-table-column prop="disciplineContent" label="处分内容" min-width="200" :show-overflow-tooltip="true" />
             <el-table-column prop="scoreDeduction" label="扣分" min-width="80" align="center">
               <template #default="scope">
-                <el-tag type="danger" size="small">{{ scope.row.scoreDeduction || 0 }}</el-tag>
+                <el-tag 
+                  :type="scope.row.status === '1' ? 'danger' : 'info'" 
+                  size="small"
+                >
+                  {{ scope.row.scoreDeduction || 0 }}
+                </el-tag>
               </template>
             </el-table-column>
             <el-table-column prop="status" label="状态" min-width="80" align="center">
@@ -440,6 +474,7 @@
 </template>
 
 <script setup name="SubmitDialog" lang="ts">
+import { watch, nextTick } from 'vue';
 import { getAssessmentSubmitDetail, submitAssessmentScore, submitAssessment, getClassStudentRecords } from '@/api/bzrkh/teacherAssessment';
 import {
   AssessmentDetailVO,
@@ -686,6 +721,9 @@ const loadAssessmentDetail = async () => {
       overallComment: monthlyScoreForm.overallComment
     });
     console.log('==================');
+    
+    // 自动加载学生违规处分信息数据
+    await autoLoadStudentRecords();
   } catch (error) {
     console.error('加载考核详情失败:', error);
     proxy?.$modal.msgError('加载考核详情失败,请检查网络连接或刷新页面重试');
@@ -697,7 +735,28 @@ const loadAssessmentDetail = async () => {
   }
 };
 
-/** 查看学生违规处分信息 */
+/** 自动加载学生违规处分信息数据(后台加载,不显示弹窗) */
+const autoLoadStudentRecords = async () => {
+  if (!props.classId || !props.planId) {
+    console.warn('缺少必要参数(班级ID或计划ID),跳过自动加载学生违规处分数据');
+    return;
+  }
+
+  console.log('🔄 开始自动加载学生违规处分数据...');
+  try {
+    const res = await getClassStudentRecords(props.classId, props.planId);
+    studentRecordsData.value = res.data;
+    
+    // 自动同步违纪记录扣分到班级扣分字段(不显示提示消息)
+    autoSyncDeductionToClassScore(false);
+    console.log('✅ 学生违规处分数据自动加载完成');
+  } catch (error) {
+    console.error('❌ 自动加载学生违规处分数据失败:', error);
+    // 静默失败,不显示错误提示(避免影响主要功能)
+  }
+};
+
+/** 查看学生违规处分信息(点击按钮时调用) */
 const handleViewStudentViolations = async () => {
   if (!props.classId || !props.planId) {
     proxy?.$modal.msgError('缺少必要参数(班级ID或计划ID)');
@@ -709,9 +768,19 @@ const handleViewStudentViolations = async () => {
 
   studentRecordsLoading.value = true;
   try {
-    const res = await getClassStudentRecords(props.classId, props.planId);
-    studentRecordsData.value = res.data;
-    studentRecordsVisible.value = true;
+    // 如果数据已经加载过,直接显示弹窗
+    if (studentRecordsData.value?.disciplineRecords || studentRecordsData.value?.rewardRecords) {
+      studentRecordsVisible.value = true;
+      console.log('📋 使用已加载的学生违规处分数据显示弹窗');
+    } else {
+      // 否则重新加载数据
+      const res = await getClassStudentRecords(props.classId, props.planId);
+      studentRecordsData.value = res.data;
+      studentRecordsVisible.value = true;
+    }
+    
+    // 手动查看时也重新同步一次扣分(显示提示消息)
+    autoSyncDeductionToClassScore(true);
   } catch (error) {
     console.error('查询学生违纪记录和奖励记录失败:', error);
     proxy?.$modal.msgError('查询学生违纪记录和奖励记录失败');
@@ -720,6 +789,73 @@ const handleViewStudentViolations = async () => {
   }
 };
 
+/** 获取生效的违纪记录 */
+const getEffectiveDisciplineRecords = () => {
+  if (!studentRecordsData.value?.disciplineRecords) {
+    return [];
+  }
+  // 只统计状态为'1'(生效)的违纪记录
+  return studentRecordsData.value.disciplineRecords.filter(record => record.status === '1');
+};
+
+/** 计算违纪记录总扣分 */
+const calculateTotalDeduction = () => {
+  const effectiveRecords = getEffectiveDisciplineRecords();
+  return effectiveRecords.reduce((total, record) => {
+    const deduction = Number(record.scoreDeduction) || 0;
+    return total + deduction;
+  }, 0);
+};
+
+/** 自动同步违纪记录扣分到班级扣分字段 */
+const autoSyncDeductionToClassScore = (showMessage = true) => {
+  const totalDeduction = calculateTotalDeduction();
+  
+  // 自动将汇总的扣分设置到班级扣分字段
+  managementEffectivenessForm.classDeduction = totalDeduction;
+  // 自动计算50%计
+  calculateDeductionHalf();
+  
+  if (totalDeduction > 0 && showMessage) {
+    proxy?.$modal.msgSuccess(`已自动同步违纪记录扣分汇总 ${totalDeduction} 分到班级扣分字段`);
+  }
+};
+
+// 监听学生违纪记录数据变化,自动同步扣分
+watch(() => studentRecordsData.value?.disciplineRecords, (newRecords) => {
+  if (newRecords && studentRecordsVisible.value) {
+    // 延迟执行,确保数据完全加载,但不显示提示消息
+    nextTick(() => {
+      autoSyncDeductionToClassScore(false);
+    });
+  }
+}, { deep: true });
+
+/** 将违纪记录扣分汇总应用到班级扣分字段 */
+const applyDeductionToClassScore = () => {
+  const totalDeduction = calculateTotalDeduction();
+  
+  if (totalDeduction === 0) {
+    proxy?.$modal.msgWarning('当前没有生效的违纪记录扣分可以应用');
+    return;
+  }
+
+  // 确认应用操作
+  proxy?.$modal.confirm(`确定要将违纪记录扣分汇总 ${totalDeduction} 分重新应用到班级扣分字段吗?`).then(() => {
+    // 将汇总的扣分设置到班级扣分字段
+    managementEffectivenessForm.classDeduction = totalDeduction;
+    // 自动计算50%计
+    calculateDeductionHalf();
+    
+    proxy?.$modal.msgSuccess(`已重新应用违纪记录扣分汇总 ${totalDeduction} 分到班级扣分字段`);
+    
+    // 关闭学生记录弹窗
+    studentRecordsVisible.value = false;
+  }).catch(() => {
+    // 用户取消操作
+  });
+};
+
 /** 保存考核数据 */
 const handleSubmit = async () => {
   try {

+ 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>

+ 36 - 160
web/src/views/cw/projectApproval/index.vue

@@ -1,60 +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">{{ completedCount }}</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">{{ runningCount }}</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><Timer /></el-icon>
-            </div>
-            <div class="stat-info">
-              <div class="stat-value">{{ waitingCount }}</div>
-              <div class="stat-label">等待中</div>
-            </div>
-          </div>
-        </div>
-      </el-col>
-    </el-row>
 
     <!-- 搜索区域 -->
     <el-card class="button-card" v-show="showSearch">
@@ -162,7 +107,8 @@
           <el-table-column type="selection" width="55" align="center" fixed="left" />
           <el-table-column label="申报编号" align="center" prop="applicationNo" min-width="140" />
           <el-table-column label="流程名称" align="center" prop="processName" min-width="180" show-overflow-tooltip />
-          <el-table-column label="流程状态" align="center" prop="processStatus" width="120">
+          <!-- 🔧 临时隐藏流程状态和进度列,避免显示不准确数据 -->
+          <!-- <el-table-column label="流程状态" align="center" prop="processStatus" width="120">
             <template #default="scope">
               <el-tag :type="getProcessStatusType(scope.row.processStatus)" effect="light">
                 {{ getProcessStatusText(scope.row.processStatus) }}
@@ -173,7 +119,7 @@
             <template #default="scope">
               <span class="progress-text">{{ scope.row.currentNode }}/{{ scope.row.totalNodes }}</span>
             </template>
-          </el-table-column>
+          </el-table-column> -->
           <el-table-column label="提交人" align="center" prop="submitterName" min-width="100" />
           <el-table-column label="开始时间" align="center" prop="startTime" min-width="160">
             <template #default="scope">
@@ -338,7 +284,7 @@ import { ElMessage, ElMessageBox } from 'element-plus';
 import type { FormInstance } from 'element-plus';
 import RightToolbar from '@/components/RightToolbar/index.vue';
 import Pagination from '@/components/Pagination/index.vue';
-import { Clock, CircleCheck, Search, Refresh, Plus, View, Check, Close, CircleClose, Document, Timer } from '@element-plus/icons-vue';
+import { Clock, CircleCheck, Search, Refresh, Plus, View, Check, Close, CircleClose } from '@element-plus/icons-vue';
 
 // 这里需要创建对应的API文件
 import {
@@ -384,11 +330,6 @@ const processList = ref([]);
 const loading = ref(false);
 const total = ref(0);
 
-// 统计数据
-const totalCount = ref(0);
-const completedCount = ref(0);
-const runningCount = ref(0);
-const waitingCount = ref(0);
 
 // 选择状态
 const ids = ref<Array<string | number>>([]);
@@ -488,8 +429,6 @@ const getList = async () => {
       data: processList.value
     });
 
-    // 更新统计数据
-    getStatistics();
   } catch (error) {
     console.error('获取流程列表失败:', error);
     ElMessage.error('获取流程列表失败');
@@ -500,21 +439,6 @@ const getList = async () => {
   }
 };
 
-// 获取统计数据
-const getStatistics = () => {
-  try {
-    totalCount.value = processList.value.length;
-    completedCount.value = processList.value.filter((item: any) => item.processStatus === 'completed').length;
-    runningCount.value = processList.value.filter((item: any) => item.processStatus === 'running').length;
-    waitingCount.value = processList.value.filter((item: any) => item.processStatus === 'waiting').length;
-  } catch (error) {
-    console.error('获取统计数据失败:', error);
-    totalCount.value = 0;
-    completedCount.value = 0;
-    runningCount.value = 0;
-    waitingCount.value = 0;
-  }
-};
 
 // 搜索
 const handleQuery = () => {
@@ -632,21 +556,30 @@ const handleViewPending = async () => {
       totalCount = 0;
     }
 
-    // 字段映射:将后端CwApprovalRecordVo字段映射为前端表格期望的字段
+    // 🔧 优化字段映射:将后端CwApprovalRecordVo字段映射为前端表格期望的字段
     processList.value = rawData.map((item) => ({
       ...item,
       // 核心字段映射
       processName: item.projectName || item.processName || '未知项目',
-      // 待审批状态应该是running,这样审批按钮才会显示
-      processStatus: item.nodeStatus === 'waiting' ? 'running' : item.nodeStatus || item.processStatus || 'pending',
+      // 🔧 修复流程状态映射逻辑
+      processStatus: (() => {
+        // 优先使用后端计算的processStatus
+        if (item.processStatus) return item.processStatus
+        // 根据nodeStatus映射前端期望的状态
+        if (item.nodeStatus === 'waiting') return 'running'
+        if (item.nodeStatus === 'approved') return 'completed'
+        if (item.nodeStatus === 'rejected') return 'rejected'
+        if (item.nodeStatus === 'processing') return 'running'
+        return 'pending'
+      })(),
       submitterName: item.applicantName || item.submitterName || '未知',
-      // 使用后端返回的正确值(不再设置默认值)
-      totalNodes: item.totalNodes,
-      currentNode: item.currentNode,
+      // 🔧 修复进度字段,确保有默认值且不为0
+      totalNodes: item.totalNodes && item.totalNodes > 0 ? item.totalNodes : 3, // 默认3个节点:部门->院领导->财务
+      currentNode: item.currentNode && item.currentNode > 0 ? item.currentNode : item.nodeOrder || 1,
       // 保持时间字段
       startTime: item.submitTime || item.startTime || item.createTime,
       endTime: item.approvalTime || item.endTime
-    }));
+    }))
     total.value = totalCount;
 
     console.log('解析后数据:', { count: processList.value.length, total: total.value, data: processList.value });
@@ -689,20 +622,30 @@ const handleViewProcessed = async () => {
       totalCount = 0;
     }
 
-    // 字段映射:将后端CwApprovalRecordVo字段映射为前端表格期望的字段
+    // 🔧 优化字段映射:将后端CwApprovalRecordVo字段映射为前端表格期望的字段
     processList.value = rawData.map((item) => ({
       ...item,
       // 核心字段映射
       processName: item.projectName || item.processName || '未知项目',
-      processStatus: item.nodeStatus || item.processStatus || 'completed',
+      // 🔧 修复已审批状态映射逻辑
+      processStatus: (() => {
+        // 优先使用后端计算的processStatus
+        if (item.processStatus) return item.processStatus
+        // 根据nodeStatus映射前端期望的状态
+        if (item.nodeStatus === 'approved') return 'completed'
+        if (item.nodeStatus === 'rejected') return 'rejected'
+        if (item.nodeStatus === 'waiting') return 'running'
+        if (item.nodeStatus === 'processing') return 'running'
+        return 'completed' // 已审批默认为完成状态
+      })(),
       submitterName: item.applicantName || item.submitterName || '未知',
-      // 使用后端返回的正确值(不再设置默认值)
-      totalNodes: item.totalNodes,
-      currentNode: item.currentNode,
+      // 🔧 修复进度字段,确保有默认值且不为0
+      totalNodes: item.totalNodes && item.totalNodes > 0 ? item.totalNodes : 3, // 默认3个节点:部门->院领导->财务
+      currentNode: item.currentNode && item.currentNode > 0 ? item.currentNode : item.nodeOrder || 1,
       // 保持时间字段
       startTime: item.submitTime || item.startTime || item.createTime,
       endTime: item.approvalTime || item.endTime
-    }));
+    }))
     total.value = totalCount;
 
     console.log('解析后数据:', { count: processList.value.length, total: total.value, data: processList.value });
@@ -935,73 +878,6 @@ onMounted(() => {
   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 {