前言

泛微E9版本的后台对于流程使用分析功能上还是比较欠缺的,公司使用OA系统的时间也比较久了,有很多没有必要的流程还存在在系统重,如果单条筛选工作量巨大,之前就发现DS对泛微数据库的结构记录的比较准确,索性就让DS帮我完成这一工作,再进阶成网页形式展现出来,也方便日后再做流程统计的时候查看。

效果图

image.png

最终版SQL代码

WITH CurrentFlows AS (
  SELECT 
    wb.id,
    wb.workflowname,
    wb.activeVersionID,
    wb.isvalid, -- 添加 isvalid 字段
    wb.workflowtype, -- 添加 workflowtype 字段
    MAX(wf.createdate) AS last_created
  FROM workflow_base wb
  JOIN workflow_requestbase wf ON wb.id = wf.workflowid
  WHERE wb.id = wb.activeVersionID OR wb.activeVersionID IS NULL
  GROUP BY wb.id, wb.workflowname, wb.activeVersionID, wb.isvalid, wb.workflowtype
),
TotalCounts AS (
  SELECT 
    wb.workflowname,
    COUNT(*) AS total_submissions,
    SUM(CASE WHEN wf.createdate >= '2025-01-01' AND wf.createdate < '2026-01-01' 
             THEN 1 ELSE 0 END) AS submissions_2025
  FROM workflow_base wb
  JOIN workflow_requestbase wf ON wb.id = wf.workflowid
  GROUP BY wb.workflowname
)
SELECT 
  cf.id AS 流程类型ID,
  cf.workflowname AS 流程类型名称,
  cf.activeVersionID AS 活动版本ID,

  -- 映射 isvalid 字段
  CASE cf.isvalid
    WHEN 0 THEN '无效'
    WHEN 1 THEN '有效'
    WHEN 2 THEN '测试'
    ELSE '未知状态'
  END AS 流程状态,

  -- 获取 workflowtype 的中文名称
  wt.typename AS 路径类型,

  tc.total_submissions AS 历史总提交次数,
  tc.submissions_2025 AS [2025年提交次数],
  cf.last_created AS 最后创建时间
FROM CurrentFlows cf
JOIN TotalCounts tc ON cf.workflowname = tc.workflowname
-- 关联 workflow_type 表获取路径类型中文名
LEFT JOIN workflow_type wt ON cf.workflowtype = wt.id
ORDER BY cf.last_created DESC;

最终版PHP代码

<?php
// 数据库配置信息
$serverName = "数据IP,1433";   // 服务器地址(IP:端口)
$databaseName = "数据表名";           // 数据库名称
$username = "数据库用户名";                    // 登录用户名
$password = "数据库密码";                 // 登录密码

// 连接选项
$connectionOptions = [
    "Database" => $databaseName,      // 目标数据库
    "Uid" => $username,               // 用户名
    "PWD" => $password,               // 密码
    "CharacterSet" => "UTF-8"          // 字符集
];

// 尝试连接数据库
$conn = sqlsrv_connect($serverName, $connectionOptions);

// 检查连接是否成功
if ($conn === false) {
    die("<div class='container mt-5'><h3>❌ 数据库连接失败!</h3><pre>" . print_r(sqlsrv_errors(SQLSRV_ERR_ALL), true) . "</pre></div>");
}

// 定义用户提供的 SQL 查询
$query = "
WITH CurrentFlows AS (
  SELECT 
    wb.id,
    wb.workflowname,
    wb.activeVersionID,
    wb.isvalid, 
    wb.workflowtype, 
    MAX(wf.createdate) AS last_created
  FROM workflow_base wb
  JOIN workflow_requestbase wf ON wb.id = wf.workflowid
  WHERE wb.id = wb.activeVersionID OR wb.activeVersionID IS NULL
  GROUP BY wb.id, wb.workflowname, wb.activeVersionID, wb.isvalid, wb.workflowtype
),
TotalCounts AS (
  SELECT 
    wb.workflowname,
    COUNT(*) AS total_submissions,
    SUM(CASE WHEN wf.createdate >= '2025-01-01' AND wf.createdate < '2026-01-01' 
             THEN 1 ELSE 0 END) AS submissions_2025
  FROM workflow_base wb
  JOIN workflow_requestbase wf ON wb.id = wf.workflowid
  GROUP BY wb.workflowname
)
SELECT 
  cf.id AS 流程类型ID,
  cf.workflowname AS 流程类型名称,
  cf.activeVersionID AS 活动版本ID,
  CASE cf.isvalid
    WHEN 0 THEN '无效'
    WHEN 1 THEN '有效'
    WHEN 2 THEN '测试'
    ELSE '未知状态'
  END AS 流程状态,
  wt.typename AS 路径类型,
  tc.total_submissions AS 历史总提交次数,
  tc.submissions_2025 AS [2025年提交次数],
  cf.last_created AS 最后创建时间
FROM CurrentFlows cf
JOIN TotalCounts tc ON cf.workflowname = tc.workflowname
LEFT JOIN workflow_type wt ON cf.workflowtype = wt.id
ORDER BY wt.typename ASC;
";

// 执行查询
$result = sqlsrv_query($conn, $query);

// 检查查询是否成功
if ($result === false) {
    die("<div class='container mt-5'><h3>❌ 查询执行失败!</h3><pre>" . print_r(sqlsrv_errors(SQLSRV_ERR_ALL), true) . "</pre></div>");
}

// 获取结果集并统计行数
$rows = [];
$rowCount = 0;
while ($row = sqlsrv_fetch_array($result, SQLSRV_FETCH_ASSOC)) {
    $rows[] = $row;
    $rowCount++;
}

// 释放资源并关闭连接
sqlsrv_free_stmt($result);
sqlsrv_close($conn);

// 处理路径类型字符串的函数
function cleanPathType($pathType) {
    // 如果包含特殊格式,提取中文名称
    if (preg_match('/~`~`\d+\s+([\x{4e00}-\x{9fa5}]+)/u', $pathType, $matches)) {
        return $matches[1]; // 返回匹配到的中文部分
    }
    // 如果包含"系统默认工作流"的变体,统一替换
    if (strpos($pathType, '系统默认工作流') !== false || 
        strpos($pathType, 'System default workflow') !== false ||
        strpos($pathType, '系統默認工作流') !== false) {
        return '系统默认工作流';
    }
    return $pathType;
}
?>

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>流程数据查询结果 - 增强版</title>
    <!-- 使用 BootCDN 的 Bootstrap 5.3.0 -->
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.3.0/css/bootstrap.min.css" rel="stylesheet">
    <!-- 引入 Bootstrap Icons -->
    <link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/bootstrap-icons/1.13.1/font/bootstrap-icons.css">
    <style>
        body {
            background: linear-gradient(135deg, #f5f7fa 0%, #e4edf5 100%);
            padding: 20px;
            font-family: 'Segoe UI', 'Microsoft YaHei', sans-serif;
        }
  
        .header-container {
            background: linear-gradient(to right, #4e73df, #224abe);
            color: white;
            padding: 25px 30px;
            border-radius: 10px;
            margin-bottom: 30px;
            box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
        }
  
        .table-container {
            background-color: white;
            border-radius: 10px;
            overflow: hidden;
            box-shadow: 0 5px 25px rgba(0, 0, 0, 0.08);
            margin-bottom: 30px;
            overflow-x: auto;
        }
  
        .table {
            min-width: 1200px;
            margin-bottom: 0;
        }
  
        .table thead th {
            background-color: #4e73df;
            color: white;
            font-weight: 600;
            vertical-align: middle;
            white-space: nowrap;
            cursor: pointer;
            position: relative;
            padding-right: 30px;
        }
  
        .table th, .table td {
            padding: 14px 16px;
            vertical-align: middle;
        }
  
        .sort-indicator {
            position: absolute;
            right: 10px;
            top: 50%;
            transform: translateY(-50%);
            opacity: 0.6;
        }
  
        .sort-active .sort-indicator {
            opacity: 1;
        }
  
        /* 指定居中显示的列 */
        .text-center {
            text-align: center !important;
        }
  
        .table-striped tbody tr:nth-of-type(odd) {
            background-color: rgba(78, 115, 223, 0.05);
        }
  
        .table-hover tbody tr:hover {
            background-color: rgba(78, 115, 223, 0.1);
            transition: background-color 0.3s;
        }
  
        .status-badge {
            display: inline-block;
            padding: 4px 10px;
            border-radius: 15px;
            font-size: 13px;
            font-weight: 500;
        }
  
        .valid {
            background-color: #d1e7dd;
            color: #0f5132;
        }
  
        .invalid {
            background-color: #f8d7da;
            color: #842029;
        }
  
        .testing {
            background-color: #fff3cd;
            color: #664d03;
        }
  
        .summary-card {
            background: white;
            border-radius: 10px;
            padding: 20px;
            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05);
        }
  
        .footer {
            text-align: center;
            color: #6c757d;
            font-size: 14px;
            margin-top: 30px;
            padding: 15px;
        }
  
        .highlight {
            font-weight: 600;
            color: #4e73df;
        }
  
        .scroll-hint {
            position: fixed;
            bottom: 20px;
            right: 20px;
            background: rgba(78, 115, 223, 0.9);
            color: white;
            padding: 8px 15px;
            border-radius: 20px;
            font-size: 14px;
            box-shadow: 0 3px 10px rgba(0, 0, 0, 0.2);
            display: none;
        }
  
        /* 序号列样式 */
        .serial-column {
            width: 60px;
            min-width: 60px;
            background-color: rgba(78, 115, 223, 0.1);
            text-align: center;
            font-weight: 600;
        }
  
        @media (max-width: 768px) {
            .header-container {
                padding: 15px;
            }
  
            h1 {
                font-size: 1.5rem;
            }
        }
  
        /* 筛选面板样式 */
        .filter-panel {
            background-color: white;
            border-radius: 10px;
            padding: 20px;
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05);
            margin-bottom: 25px;
            transition: all 0.3s ease;
        }
  
        .filter-header {
            cursor: pointer;
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 5px 0 15px;
            border-bottom: 1px solid #eaeaea;
            margin-bottom: 15px;
        }
  
        .filter-header h3 {
            margin: 0;
            font-size: 1.25rem;
            font-weight: 600;
            color: #4e73df;
        }
  
        .filter-header i {
            transition: transform 0.3s ease;
        }
  
        .filter-grid {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
            gap: 15px;
        }
  
        .filter-group {
            margin-bottom: 10px;
        }
  
        .filter-group label {
            display: block;
            margin-bottom: 5px;
            font-weight: 500;
            color: #495057;
            font-size: 0.9rem;
        }
  
        .filter-control {
            width: 100%;
            padding: 8px 12px;
            border: 1px solid #ced4da;
            border-radius: 5px;
            font-size: 0.9rem;
            transition: border-color 0.15s ease-in-out;
        }
  
        .filter-control:focus {
            border-color: #4e73df;
            outline: 0;
            box-shadow: 0 0 0 0.2rem rgba(78, 115, 223, 0.25);
        }
  
        .filter-actions {
            display: flex;
            justify-content: flex-end;
            gap: 10px;
            margin-top: 10px;
            padding-top: 15px;
            border-top: 1px solid #eaeaea;
        }
  
        /* 高亮匹配项 */
        .highlight {
            background-color: #fff3cd;
            font-weight: 600;
        }
  
        /* 响应式调整 */
        @media (max-width: 768px) {
            .filter-grid {
                grid-template-columns: 1fr;
            }
  
            .filter-actions {
                flex-direction: column;
            }
  
            .filter-actions .btn {
                width: 100%;
                margin-bottom: 5px;
            }
        }
    </style>
</head>
<body>
    <div class="container-fluid">
        <!-- 标题区域 -->
        <div class="header-container">
            <div class="row align-items-center">
                <div class="col-md-8">
                    <h1 class="mb-0"><i class="bi bi-diagram-3 me-2"></i>流程数据统计结果</h1>
                </div>
                <div class="col-md-4 text-md-end">
                    <div class="text-white-50">最后更新时间: <?= date('Y-m-d H:i:s') ?></div>
                </div>
            </div>
        </div>
  
        <!-- 筛选面板 -->
        <div class="filter-panel">
            <div class="filter-header" id="filterHeader">
                <h3><i class="bi bi-funnel me-2"></i>数据筛选面板</h3>
                <i class="bi bi-chevron-down" id="filterToggle"></i>
            </div>
  
            <div id="filterBody">
                <div class="filter-grid">
                    <div class="filter-group">
                        <label for="filterName">流程名称</label>
                        <input type="text" id="filterName" class="filter-control" placeholder="输入流程名称...">
                    </div>
  
                    <div class="filter-group">
                        <label for="filterStatus">流程状态</label>
                        <select id="filterStatus" class="filter-control">
                            <option value="">所有状态</option>
                            <option value="有效">有效</option>
                            <option value="无效">无效</option>
                            <option value="测试">测试</option>
                        </select>
                    </div>
  
                    <div class="filter-group">
                        <label for="filterPath">路径类型</label>
                        <input type="text" id="filterPath" class="filter-control" placeholder="输入路径类型...">
                    </div>
  
                    <div class="filter-group">
                        <label for="filterMinTotal">最小总提交数</label>
                        <input type="number" id="filterMinTotal" class="filter-control" placeholder="最小值">
                    </div>
  
                    <div class="filter-group">
                        <label for="filterMin2025">最小2025年提交数</label>
                        <input type="number" id="filterMin2025" class="filter-control" placeholder="最小值">
                    </div>
                </div>
  
                <div class="filter-actions">
                    <button id="resetFilters" class="btn btn-outline-secondary">
                        <i class="bi bi-x-circle me-1"></i> 重置筛选
                    </button>
                    <button id="applyFilters" class="btn btn-primary">
                        <i class="bi bi-filter me-1"></i> 应用筛选
                    </button>
                </div>
            </div>
        </div>
  
        <!-- 数据统计卡片 -->
        <div class="row mb-4">
            <div class="col-md-4 mb-3">
                <div class="summary-card h-100">
                    <div class="d-flex align-items-center">
                        <div class="bg-primary p-3 rounded-circle me-3">
                            <i class="fas fa-list-alt text-white fs-4"></i>
                        </div>
                        <div>
                            <div class="text-muted small">流程总数</div>
                            <div class="fs-3 fw-bold"><?= $rowCount ?></div>
                        </div>
                    </div>
                </div>
            </div>
  
            <div class="col-md-4 mb-3">
                <div class="summary-card h-100">
                    <div class="d-flex align-items-center">
                        <div class="bg-success p-3 rounded-circle me-3">
                            <i class="fas fa-check-circle text-white fs-4"></i>
                        </div>
                        <div>
                            <div class="text-muted small">有效流程</div>
                            <div class="fs-3 fw-bold">
                                <?= count(array_filter($rows, function($row) { 
                                    return $row['流程状态'] === '有效'; 
                                })) ?>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
  
            <div class="col-md-4 mb-3">
                <div class="summary-card h-100">
                    <div class="d-flex align-items-center">
                        <div class="bg-info p-3 rounded-circle me-3">
                            <i class="fas fa-calendar-alt text-white fs-4"></i>
                        </div>
                        <div>
                            <div class="text-muted small">2025年提交总数</div>
                            <div class="fs-3 fw-bold">
                                <?= array_sum(array_column($rows, '2025年提交次数')) ?>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
  
        <!-- 表格区域(带滚动条) -->
        <div class="table-container">
            <table class="table table-striped table-hover" id="dataTable">
                <thead>
                    <tr>
                        <th class="text-center serial-column">序号</th>
                        <th class="sortable" data-column="流程类型ID">
                            流程类型ID
                            <span class="sort-indicator"><i class="bi bi-arrow-down-up"></i></span>
                        </th>
                        <th class="sortable" data-column="流程类型名称">
                            流程类型名称
                            <span class="sort-indicator"><i class="bi bi-arrow-down-up"></i></span>
                        </th>
                        <th class="sortable" data-column="活动版本ID">
                            活动版本ID
                            <span class="sort-indicator"><i class="bi bi-arrow-down-up"></i></span>
                        </th>
                        <th class="sortable" data-column="流程状态">
                            流程状态
                            <span class="sort-indicator"><i class="bi bi-arrow-down-up"></i></span>
                        </th>
                        <th class="sortable" data-column="路径类型">
                            路径类型
                            <span class="sort-indicator"><i class="bi bi-arrow-down-up"></i></span>
                        </th>
                        <th class="sortable" data-column="历史总提交次数">
                            历史总提交次数
                            <span class="sort-indicator"><i class="bi bi-arrow-down-up"></i></span>
                        </th>
                        <th class="sortable" data-column="2025年提交次数">
                            2025年提交次数
                            <span class="sort-indicator"><i class="bi bi-arrow-down-up"></i></span>
                        </th>
                        <th class="sortable" data-column="最后创建时间">
                            最后创建时间
                            <span class="sort-indicator"><i class="bi bi-arrow-down-up"></i></span>
                        </th>
                    </tr>
                </thead>
                <tbody>
                    <?php if ($rowCount > 0): ?>
                        <?php $counter = 1; ?>
                        <?php foreach ($rows as $row): ?>
                            <tr>
                                <td class="serial-column text-center"><?= $counter++ ?></td>
                                <td class="text-center"><?= htmlspecialchars($row['流程类型ID'] ?? '') ?></td>
                                <td class="name-cell">
                                    <?php
                                    // 处理路径类型字符串
                                    $pathType = $row['流程类型名称'] ?? '';
                                    $cleanedPathType = cleanPathType($pathType);
                                    ?>
                                    <?= htmlspecialchars($cleanedPathType) ?>
                                </td>
                                <td class="text-center"><?= htmlspecialchars($row['活动版本ID'] ?? '') ?></td>
                                <td class="text-center status-cell">
                                    <span class="status-badge <?= 
                                            ($row['流程状态'] === '有效') ? 'valid' : 
                                            (($row['流程状态'] === '无效') ? 'invalid' : 
                                            (($row['流程状态'] === '测试') ? 'testing' : ''))
                                        ?>">
                                        <?= htmlspecialchars($row['流程状态'] ?? '') ?>
                                    </span>
                                </td>
                                <td class="path-cell">
                                    <?php
                                    // 处理路径类型字符串
                                    $pathType = $row['路径类型'] ?? '';
                                    $cleanedPathType = cleanPathType($pathType);
                                    ?>
                                    <?= htmlspecialchars($cleanedPathType) ?>
                                </td>
                                <td class="text-center total-submissions"><?= number_format($row['历史总提交次数'] ?? 0) ?></td>
                                <td class="text-center submissions-2025"><?= number_format($row['2025年提交次数'] ?? 0) ?></td>
                                <td class="text-center"><?= htmlspecialchars($row['最后创建时间'] ?? '') ?></td>
                            </tr>
                        <?php endforeach; ?>
                    <?php else: ?>
                        <tr>
                            <td colspan="9" class="text-center py-5">
                                <div class="text-muted">
                                    <i class="bi bi-inbox me-2"></i> 未查询到符合条件的记录
                                </div>
                            </td>
                        </tr>
                    <?php endif; ?>
                </tbody>
            </table>
        </div>
  
        <!-- 底部统计信息 -->
        <div class="d-flex justify-content-between align-items-center">
            <div class="text-muted">
                显示 <span class="fw-bold" id="visibleCount"><?= $rowCount ?></span> 条记录中的 
                <span class="fw-bold" id="filteredCount"><?= $rowCount ?></span> 条
            </div>
            <div>
                <button class="btn btn-outline-primary btn-sm me-2">
                    <i class="bi bi-download me-1"></i> 导出数据
                </button>
                <button class="btn btn-primary btn-sm" id="refreshData">
                    <i class="bi bi-arrow-repeat me-1"></i> 刷新数据
                </button>
            </div>
        </div>
  
        <!-- 页脚 -->
        <div class="footer">
            <div class="text-muted">
                <i class="bi bi-database me-1"></i> 数据源: ecology 数据库 | 
                <i class="bi bi-server me-1"></i> 服务器: 192.168.5.29
            </div>
        </div>
  
        <!-- 滚动提示(小屏幕显示) -->
        <div class="scroll-hint">
            <i class="bi bi-arrows-expand me-2"></i> 左右滑动查看完整表格
        </div>
    </div>
  
    <!-- 引入 Bootstrap JS -->
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.3.0/js/bootstrap.bundle.min.js"></script>
  
    <script>
        // 显示滚动提示(在小屏幕上)
        if (window.innerWidth < 992) {
            document.querySelector('.scroll-hint').style.display = 'block';
  
            // 3秒后自动隐藏提示
            setTimeout(() => {
                document.querySelector('.scroll-hint').style.opacity = '0';
                setTimeout(() => {
                    document.querySelector('.scroll-hint').style.display = 'none';
                }, 500);
            }, 3000);
        }
  
        // 排序状态管理
        let currentSort = {
            column: null,
            direction: 'asc' // 'asc' 或 'desc'
        };
  
        // 筛选功能实现
        document.addEventListener('DOMContentLoaded', function() {
            const filterHeader = document.getElementById('filterHeader');
            const filterBody = document.getElementById('filterBody');
            const filterToggle = document.getElementById('filterToggle');
            const applyFilters = document.getElementById('applyFilters');
            const resetFilters = document.getElementById('resetFilters');
            const refreshData = document.getElementById('refreshData');
  
            // 筛选面板折叠/展开功能
            filterHeader.addEventListener('click', function() {
                if (filterBody.style.display === 'none') {
                    filterBody.style.display = 'block';
                    filterToggle.classList.remove('bi-chevron-down');
                    filterToggle.classList.add('bi-chevron-up');
                } else {
                    filterBody.style.display = 'none';
                    filterToggle.classList.remove('bi-chevron-up');
                    filterToggle.classList.add('bi-chevron-down');
                }
            });
  
            // 应用筛选功能
            applyFilters.addEventListener('click', function() {
                applyFilterLogic();
            });
  
            // 重置筛选功能
            resetFilters.addEventListener('click', function() {
                document.getElementById('filterName').value = '';
                document.getElementById('filterStatus').value = '';
                document.getElementById('filterPath').value = '';
                document.getElementById('filterMinTotal').value = '';
                document.getElementById('filterMin2025').value = '';
  
                applyFilterLogic();
            });
  
            // 刷新数据
            refreshData.addEventListener('click', function() {
                location.reload();
            });
  
            // 筛选逻辑
            function applyFilterLogic() {
                const filterName = document.getElementById('filterName').value.toLowerCase();
                const filterStatus = document.getElementById('filterStatus').value;
                const filterPath = document.getElementById('filterPath').value.toLowerCase();
                const filterMinTotal = parseInt(document.getElementById('filterMinTotal').value) || 0;
                const filterMin2025 = parseInt(document.getElementById('filterMin2025').value) || 0;
  
                const rows = document.querySelectorAll('#dataTable tbody tr');
                let visibleCount = 0;
  
                rows.forEach(row => {
                    if (row.cells.length < 9) return;
  
                    const nameCell = row.querySelector('.name-cell');
                    const statusCell = row.querySelector('.status-cell');
                    const pathCell = row.querySelector('.path-cell');
                    const totalSubmissions = parseInt(row.querySelector('.total-submissions').textContent.replace(/,/g, ''));
                    const submissions2025 = parseInt(row.querySelector('.submissions-2025').textContent.replace(/,/g, ''));
  
                    // 移除之前的高亮效果
                    nameCell.innerHTML = nameCell.innerHTML.replace(/<span class="highlight">|<\/span>/g, '');
                    pathCell.innerHTML = pathCell.innerHTML.replace(/<span class="highlight">|<\/span>/g, '');
  
                    // 检查筛选条件
                    const nameMatch = nameCell.textContent.toLowerCase().includes(filterName);
                    const statusMatch = filterStatus === '' || statusCell.textContent.includes(filterStatus);
                    const pathMatch = pathCell.textContent.toLowerCase().includes(filterPath);
                    const totalMatch = totalSubmissions >= filterMinTotal;
                    const yearMatch = submissions2025 >= filterMin2025;
  
                    if (nameMatch && statusMatch && pathMatch && totalMatch && yearMatch) {
                        row.style.display = '';
                        visibleCount++;
  
                        // 高亮匹配文本
                        if (filterName) {
                            const regex = new RegExp(filterName, 'gi');
                            nameCell.innerHTML = nameCell.textContent.replace(regex, 
                                match => `<span class="highlight">${match}</span>`);
                        }
  
                        if (filterPath) {
                            const regex = new RegExp(filterPath, 'gi');
                            pathCell.innerHTML = pathCell.textContent.replace(regex, 
                                match => `<span class="highlight">${match}</span>`);
                        }
                    } else {
                        row.style.display = 'none';
                    }
                });
  
                // 更新计数
                document.getElementById('filteredCount').textContent = visibleCount;
  
                // 如果没有匹配项
                if (visibleCount === 0) {
                    document.querySelector('#dataTable tbody').innerHTML = `
                        <tr>
                            <td colspan="9" class="text-center py-5">
                                <div class="text-muted">
                                    <i class="bi bi-search me-2"></i> 没有找到匹配的记录
                                </div>
                            </td>
                        </tr>
                    `;
                }
            }
  
            // 为筛选输入框添加回车键支持
            const filterInputs = document.querySelectorAll('.filter-control');
            filterInputs.forEach(input => {
                input.addEventListener('keyup', function(event) {
                    if (event.key === 'Enter') {
                        applyFilterLogic();
                    }
                });
            });
  
            // 表格排序功能
            const sortableHeaders = document.querySelectorAll('th.sortable');
  
            sortableHeaders.forEach(header => {
                header.addEventListener('click', function() {
                    const column = this.getAttribute('data-column');
                    let direction = 'asc';
  
                    // 如果点击的是当前已排序的列,则切换排序方向
                    if (currentSort.column === column) {
                        direction = currentSort.direction === 'asc' ? 'desc' : 'asc';
                    } else {
                        // 重置所有排序指示器
                        sortableHeaders.forEach(h => {
                            h.classList.remove('sort-active');
                            const indicator = h.querySelector('.sort-indicator');
                            indicator.innerHTML = '<i class="bi bi-arrow-down-up"></i>';
                        });
                    }
  
                    // 更新当前排序状态
                    currentSort.column = column;
                    currentSort.direction = direction;
  
                    // 更新UI
                    this.classList.add('sort-active');
                    const indicator = this.querySelector('.sort-indicator');
                    indicator.innerHTML = direction === 'asc' 
                        ? '<i class="bi bi-arrow-up"></i>' 
                        : '<i class="bi bi-arrow-down"></i>';
  
                    // 执行排序
                    sortTable(column, direction);
                });
            });
  
            // 表格排序函数
            function sortTable(column, direction) {
                const table = document.getElementById('dataTable');
                const tbody = table.querySelector('tbody');
                const rows = Array.from(tbody.querySelectorAll('tr:not([style*="display: none"])'));
  
                // 如果没有行,则返回
                if (rows.length === 0) return;
  
                // 获取列索引
                let columnIndex;
                const headers = table.querySelectorAll('thead th');
                headers.forEach((header, index) => {
                    if (header.getAttribute('data-column') === column) {
                        columnIndex = index;
                    }
                });
  
                // 排序行
                rows.sort((a, b) => {
                    const aValue = a.cells[columnIndex].textContent.trim();
                    const bValue = b.cells[columnIndex].textContent.trim();
  
                    // 尝试转换为数字
                    const aNum = parseFloat(aValue.replace(/,/g, ''));
                    const bNum = parseFloat(bValue.replace(/,/g, ''));
  
                    // 尝试转换为日期
                    const aDate = new Date(aValue);
                    const bDate = new Date(bValue);
  
                    let comparison = 0;
  
                    // 数值比较
                    if (!isNaN(aNum) && !isNaN(bNum)) {
                        comparison = aNum - bNum;
                    } 
                    // 日期比较
                    else if (aDate instanceof Date && !isNaN(aDate) && bDate instanceof Date && !isNaN(bDate)) {
                        comparison = aDate - bDate;
                    } 
                    // 状态比较(特殊处理)
                    else if (column === '流程状态') {
                        const statusOrder = { '有效': 1, '测试': 2, '无效': 3 };
                        const aStatus = statusOrder[aValue] || 4;
                        const bStatus = statusOrder[bValue] || 4;
                        comparison = aStatus - bStatus;
                    } 
                    // 文本比较
                    else {
                        comparison = aValue.localeCompare(bValue);
                    }
  
                    return direction === 'asc' ? comparison : -comparison;
                });
  
                // 重新添加行到tbody
                rows.forEach(row => tbody.appendChild(row));
            }
        });
    </script>
</body>
</html>
最后修改:2025 年 08 月 16 日
如果觉得我的文章对你有用,请随意赞赏