|
|
@@ -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 {
|