Commit dbbb8bf6 authored by 单鹏辉's avatar 单鹏辉

fix: 修复看板乱码 + 添加状态/项目汇总

parent 9bcf0ea6
...@@ -3,18 +3,22 @@ ...@@ -3,18 +3,22 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>BOS 闂娓呭崟鎬昏</title> <title>BOS 问题清单总览</title>
<style> <style>
* { margin: 0; padding: 0; box-sizing: border-box; } * { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; background: #f5f7fa; color: #333; } body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Microsoft YaHei", sans-serif; background: #f5f7fa; color: #333; }
.header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 30px 40px; } .header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 30px 40px; }
.header h1 { font-size: 28px; margin-bottom: 8px; } .header h1 { font-size: 28px; margin-bottom: 8px; }
.header p { opacity: 0.9; font-size: 14px; } .header p { opacity: 0.9; font-size: 14px; }
.stats { display: flex; gap: 20px; margin-top: 20px; } .stats { display: flex; gap: 20px; margin-top: 20px; }
.stat-card { background: rgba(255,255,255,0.2); border-radius: 10px; padding: 15px 25px; } .stat-card { background: rgba(255,255,255,0.2); border-radius: 10px; padding: 15px 25px; min-width: 120px; }
.stat-card .number { font-size: 32px; font-weight: bold; } .stat-card .number { font-size: 32px; font-weight: bold; }
.stat-card .label { font-size: 12px; opacity: 0.9; } .stat-card .label { font-size: 12px; opacity: 0.9; }
.container { max-width: 1400px; margin: 30px auto; padding: 0 20px; } .container { max-width: 1400px; margin: 30px auto; padding: 0 20px; }
.tabs { display: flex; gap: 4px; margin-bottom: 20px; background: white; border-radius: 10px; padding: 4px; box-shadow: 0 2px 8px rgba(0,0,0,0.06); }
.tab { padding: 10px 20px; border-radius: 8px; cursor: pointer; font-size: 14px; transition: all 0.2s; border: none; background: transparent; }
.tab:hover { background: #f0f0f0; }
.tab.active { background: #667eea; color: white; }
.search-bar { margin-bottom: 20px; } .search-bar { margin-bottom: 20px; }
.search-bar input { width: 100%; padding: 12px 20px; border: 2px solid #e1e5ee; border-radius: 10px; font-size: 16px; outline: none; transition: border-color 0.3s; } .search-bar input { width: 100%; padding: 12px 20px; border: 2px solid #e1e5ee; border-radius: 10px; font-size: 16px; outline: none; transition: border-color 0.3s; }
.search-bar input:focus { border-color: #667eea; } .search-bar input:focus { border-color: #667eea; }
...@@ -23,112 +27,152 @@ body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans- ...@@ -23,112 +27,152 @@ body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-
.card:hover { transform: translateY(-2px); box-shadow: 0 8px 24px rgba(0,0,0,0.12); } .card:hover { transform: translateY(-2px); box-shadow: 0 8px 24px rgba(0,0,0,0.12); }
.card-header { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 12px; } .card-header { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 12px; }
.card-title { font-size: 16px; font-weight: 600; color: #1a1a2e; } .card-title { font-size: 16px; font-weight: 600; color: #1a1a2e; }
.card-badge { font-size: 11px; padding: 4px 10px; border-radius: 20px; font-weight: 500; } .card-badge { font-size: 11px; padding: 4px 10px; border-radius: 20px; font-weight: 500; white-space: nowrap; }
.badge-empty { background: #f0f0f0; color: #888; } .badge-empty { background: #f0f0f0; color: #888; }
.badge-active { background: #e8f5e9; color: #2e7d32; } .badge-active { background: #e8f5e9; color: #2e7d32; }
.card-meta { font-size: 12px; color: #888; margin-bottom: 8px; } .card-meta { font-size: 12px; color: #888; margin-bottom: 8px; }
.card-path { font-size: 11px; color: #aaa; font-family: monospace; word-break: break-all; } .card-path { font-size: 11px; color: #aaa; font-family: monospace; word-break: break-all; }
.footer { text-align: center; padding: 30px; color: #aaa; font-size: 12px; } .footer { text-align: center; padding: 30px; color: #aaa; font-size: 12px; }
.summary-section { margin-bottom: 30px; }
.summary-title { font-size: 18px; font-weight: 600; margin-bottom: 15px; color: #1a1a2e; }
.summary-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 12px; }
.summary-item { background: white; border-radius: 10px; padding: 15px; box-shadow: 0 2px 8px rgba(0,0,0,0.06); }
.summary-item .name { font-weight: 600; margin-bottom: 4px; }
.summary-item .count { color: #667eea; font-size: 24px; font-weight: bold; }
.summary-item .sub { font-size: 11px; color: #888; margin-top: 4px; }
.hidden { display: none !important; }
</style> </style>
</head> </head>
<body> <body>
<div class="header"> <div class="header">
<h1>BOS 闂娓呭崟鎬昏</h1> <h1>BOS 问题清单总览</h1>
<p>bos-project-kb 缁勭粐 路 鎵€鏈夊鎴烽棶棰樻竻鍗?/p> <p>bos-project-kb 组织 · 所有客户问题清单</p>
<div class="stats"> <div class="stats">
<div class="stat-card"> <div class="stat-card">
<div class="number">50</div> <div class="number" id="totalCount">0</div>
<div class="label">娓呭崟鎬绘暟</div> <div class="label">清单总数</div>
</div> </div>
<div class="stat-card"> <div class="stat-card">
<div class="number" id="totalIssues">0</div> <div class="number" id="totalIssues">0</div>
<div class="label">闂鎬绘暟</div> <div class="label">问题总数</div>
</div> </div>
<div class="stat-card"> <div class="stat-card">
<div class="number" id="emptyCount">0</div> <div class="number" id="emptyCount">0</div>
<div class="label">绌烘竻鍗?/div> <div class="label">空清单</div>
</div>
<div class="stat-card">
<div class="number" id="activeCount">0</div>
<div class="label">有数据</div>
</div> </div>
</div> </div>
</div> </div>
<div class="container"> <div class="container">
<div class="tabs">
<button class="tab active" onclick="switchTab('all')">全部清单</button>
<button class="tab" onclick="switchTab('byStatus')">按状态</button>
<button class="tab" onclick="switchTab('byProject')">按项目</button>
</div>
<div id="view-all">
<div class="search-bar"> <div class="search-bar">
<input type="text" id="searchInput" placeholder="鎼滅储娓呭崟鍚嶇О..." oninput="filterCards()"> <input type="text" id="searchInput" placeholder="搜索清单名称..." oninput="filterCards()">
</div> </div>
<div class="grid" id="ledgerGrid"></div> <div class="grid" id="ledgerGrid"></div>
</div>
<div id="view-byStatus" class="hidden">
<div class="summary-section">
<div class="summary-title">按状态汇总</div>
<div class="summary-grid" id="statusSummary"></div>
</div>
</div>
<div id="view-byProject" class="hidden">
<div class="summary-section">
<div class="summary-title">按项目汇总</div>
<div class="summary-grid" id="projectSummary"></div>
</div>
</div>
</div> </div>
<div class="footer">Generated: 2026-07-17 18:40 路 Powered by BOS Issue Ledger</div> <div class="footer">生成时间: 2026-07-17 18:47 · Powered by BOS Issue Ledger</div>
<script> <script>
const ledgers = [ const ledgers = [
{listId:'aerxi-ops-26', repo:'aerxi-project-kb', issues:0, kanban:'运维项目/aerxi-project-kb/aerxi-ops-26/aerxi-ops-26_看板.html'}, {listId:"CBF-ops-26",repo:"CBF",issues:0,kanban:"运维项目/CBF/CBF-ops-26/CBF-ops-26_看板.html",hasKanban:true},
{listId:'CBF-ops-26', repo:'CBF', issues:0, kanban:'运维项目/CBF/CBF-ops-26/CBF-ops-26_看板.html'}, {listId:"EP-ops-26",repo:"EP",issues:0,kanban:"运维项目/EP/EP-ops-26/EP-ops-26_看板.html",hasKanban:true},
{listId:'changji-ops-26', repo:'changji-project-kb', issues:0, kanban:'运维项目/changji-project-kb/changji-ops-26/changji-ops-26_看板.html'}, {listId:"GEO-ops-26",repo:"GEO-project-kb",issues:0,kanban:"运维项目/GEO-project-kb/GEO-ops-26/GEO-ops-26_看板.html",hasKanban:true},
{listId:'dadi-ops-26', repo:'dadi-project-kb', issues:0, kanban:'运维项目/dadi-project-kb/dadi-ops-26/dadi-ops-26_看板.html'}, {listId:"majesty-ops-26",repo:"Majesty-project-kb",issues:0,kanban:"运维项目/Majesty-project-kb/majesty-ops-26/majesty-ops-26_看板.html",hasKanban:true},
{listId:'daming-ops-26', repo:'daming-project-kb', issues:0, kanban:'运维项目/daming-project-kb/daming-ops-26/daming-ops-26_看板.html'}, {listId:"SCB-ops-26",repo:"SCB-project-kb",issues:0,kanban:"运维项目/SCB-project-kb/SCB-ops-26/SCB-ops-26_看板.html",hasKanban:true},
{listId:'dashang-ops-26', repo:'dashang-project-kb', issues:0, kanban:'运维项目/dashang-project-kb/dashang-ops-26/dashang-ops-26_看板.html'}, {listId:"aerxi-ops-26",repo:"aerxi-project-kb",issues:0,kanban:"运维项目/aerxi-project-kb/aerxi-ops-26/aerxi-ops-26_看板.html",hasKanban:true},
{listId:'dawang-ops-26', repo:'dawang-project-kb', issues:0, kanban:'运维项目/dawang-project-kb/dawang-ops-26/dawang-ops-26_看板.html'}, {listId:"changji-ops-26",repo:"changji-project-kb",issues:0,kanban:"运维项目/changji-project-kb/changji-ops-26/changji-ops-26_看板.html",hasKanban:true},
{listId:'dema-ops-26', repo:'dema-project-kb', issues:0, kanban:'运维项目/dema-project-kb/dema-ops-26/dema-ops-26_看板.html'}, {listId:"dadi-ops-26",repo:"dadi-project-kb",issues:0,kanban:"运维项目/dadi-project-kb/dadi-ops-26/dadi-ops-26_看板.html",hasKanban:true},
{listId:'EP-ops-26', repo:'EP', issues:0, kanban:'运维项目/EP/EP-ops-26/EP-ops-26_看板.html'}, {listId:"daming-ops-26",repo:"daming-project-kb",issues:0,kanban:"运维项目/daming-project-kb/daming-ops-26/daming-ops-26_看板.html",hasKanban:true},
{listId:'fenglong-ops-26', repo:'fenglong-project-kb', issues:0, kanban:'运维项目/fenglong-project-kb/fenglong-ops-26/fenglong-ops-26_看板.html'}, {listId:"dashang-ops-26",repo:"dashang-project-kb",issues:0,kanban:"运维项目/dashang-project-kb/dashang-ops-26/dashang-ops-26_看板.html",hasKanban:true},
{listId:'fukang-ops-26', repo:'fukang-project-kb', issues:0, kanban:'运维项目/fukang-project-kb/fukang-ops-26/fukang-ops-26_看板.html'}, {listId:"dawang-ops-26",repo:"dawang-project-kb",issues:0,kanban:"运维项目/dawang-project-kb/dawang-ops-26/dawang-ops-26_看板.html",hasKanban:true},
{listId:'gebijia-ops-26', repo:'gebijia-project-kb', issues:0, kanban:'运维项目/gebijia-project-kb/gebijia-ops-26/gebijia-ops-26_看板.html'}, {listId:"dema-ops-26",repo:"dema-project-kb",issues:0,kanban:"运维项目/dema-project-kb/dema-ops-26/dema-ops-26_看板.html",hasKanban:true},
{listId:'GEO-ops-26', repo:'GEO-project-kb', issues:0, kanban:'运维项目/GEO-project-kb/GEO-ops-26/GEO-ops-26_看板.html'}, {listId:"fenglong-ops-26",repo:"fenglong-project-kb",issues:0,kanban:"运维项目/fenglong-project-kb/fenglong-ops-26/fenglong-ops-26_看板.html",hasKanban:true},
{listId:'guanglian-ops-26', repo:'guanglian', issues:0, kanban:'运维项目/guanglian/guanglian-ops-26/guanglian-ops-26_看板.html'}, {listId:"fukang-ops-26",repo:"fukang-project-kb",issues:0,kanban:"运维项目/fukang-project-kb/fukang-ops-26/fukang-ops-26_看板.html",hasKanban:true},
{listId:'guohua-ops-26', repo:'guohua-project-kb', issues:0, kanban:'运维项目/guohua-project-kb/guohua-ops-26/guohua-ops-26_看板.html'}, {listId:"gebijia-ops-26",repo:"gebijia-project-kb",issues:0,kanban:"运维项目/gebijia-project-kb/gebijia-ops-26/gebijia-ops-26_看板.html",hasKanban:true},
{listId:'hengtian-ops-26', repo:'hengtian-project-kb', issues:0, kanban:'运维项目/hengtian-project-kb/hengtian-ops-26/hengtian-ops-26_看板.html'}, {listId:"guanglian-ops-26",repo:"guanglian",issues:0,kanban:"运维项目/guanglian/guanglian-ops-26/guanglian-ops-26_看板.html",hasKanban:true},
{listId:'hongxing-ops-26', repo:'hongxing-project-kb', issues:0, kanban:'运维项目/hongxing-project-kb/hongxing-ops-26/hongxing-ops-26_看板.html'}, {listId:"guohua-ops-26",repo:"guohua-project-kb",issues:0,kanban:"运维项目/guohua-project-kb/guohua-ops-26/guohua-ops-26_看板.html",hasKanban:true},
{listId:'huaxintong-ops-26', repo:'huaxintong-project-kb', issues:0, kanban:'运维项目/huaxintong-project-kb/huaxintong-ops-26/huaxintong-ops-26_看板.html'}, {listId:"hengtian-ops-26",repo:"hengtian-project-kb",issues:0,kanban:"运维项目/hengtian-project-kb/hengtian-ops-26/hengtian-ops-26_看板.html",hasKanban:true},
{listId:'huide-ops-26', repo:'huide-project-kb', issues:0, kanban:'运维项目/huide-project-kb/huide-ops-26/huide-ops-26_看板.html'}, {listId:"hongxing-ops-26",repo:"hongxing-project-kb",issues:0,kanban:"运维项目/hongxing-project-kb/hongxing-ops-26/hongxing-ops-26_看板.html",hasKanban:true},
{listId:'jinghongsheng-ops-26', repo:'jinghongsheng-project-kb', issues:0, kanban:'运维项目/jinghongsheng-project-kb/jinghongsheng-ops-26/jinghongsheng-ops-26_看板.html'}, {listId:"huaxintong-ops-26",repo:"huaxintong-project-kb",issues:0,kanban:"运维项目/huaxintong-project-kb/huaxintong-ops-26/huaxintong-ops-26_看板.html",hasKanban:true},
{listId:'jinhua-ops-26', repo:'jinhua-project-kb', issues:0, kanban:'运维项目/jinhua-project-kb/jinhua-ops-26/jinhua-ops-26_看板.html'}, {listId:"huide-ops-26",repo:"huide-project-kb",issues:0,kanban:"运维项目/huide-project-kb/huide-ops-26/huide-ops-26_看板.html",hasKanban:true},
{listId:'kangnuo-ops-26', repo:'kangnuo-project-kb', issues:0, kanban:'运维项目/kangnuo-project-kb/kangnuo-ops-26/kangnuo-ops-26_看板.html'}, {listId:"jinghongsheng-ops-26",repo:"jinghongsheng-project-kb",issues:0,kanban:"运维项目/jinghongsheng-project-kb/jinghongsheng-ops-26/jinghongsheng-ops-26_看板.html",hasKanban:true},
{listId:'latticework-ops-26', repo:'latticework-project-kb', issues:0, kanban:'运维项目/latticework-project-kb/latticework-ops-26/latticework-ops-26_看板.html'}, {listId:"jinhua-ops-26",repo:"jinhua-project-kb",issues:0,kanban:"运维项目/jinhua-project-kb/jinhua-ops-26/jinhua-ops-26_看板.html",hasKanban:true},
{listId:'lianchuangjie-ops-26', repo:'lianchuangjie', issues:0, kanban:'运维项目/lianchuangjie/lianchuangjie-ops-26/lianchuangjie-ops-26_看板.html'}, {listId:"kangnuo-ops-26",repo:"kangnuo-project-kb",issues:0,kanban:"运维项目/kangnuo-project-kb/kangnuo-ops-26/kangnuo-ops-26_看板.html",hasKanban:true},
{listId:'longteng-ops-26', repo:'longteng-project-kb', issues:0, kanban:'运维项目/longteng-project-kb/longteng-ops-26/longteng-ops-26_看板.html'}, {listId:"latticework-ops-26",repo:"latticework-project-kb",issues:0,kanban:"运维项目/latticework-project-kb/latticework-ops-26/latticework-ops-26_看板.html",hasKanban:true},
{listId:'mairui-ops-26', repo:'mairui-project-kb', issues:0, kanban:'运维项目/mairui-project-kb/mairui-ops-26/mairui-ops-26_看板.html'}, {listId:"lianchuangjie-ops-26",repo:"lianchuangjie",issues:0,kanban:"运维项目/lianchuangjie/lianchuangjie-ops-26/lianchuangjie-ops-26_看板.html",hasKanban:true},
{listId:'majesty-ops-26', repo:'Majesty-project-kb', issues:0, kanban:'运维项目/Majesty-project-kb/majesty-ops-26/majesty-ops-26_看板.html'}, {listId:"longteng-ops-26",repo:"longteng-project-kb",issues:0,kanban:"运维项目/longteng-project-kb/longteng-ops-26/longteng-ops-26_看板.html",hasKanban:true},
{listId:'meisheng-ops-26', repo:'meisheng-project-kb', issues:0, kanban:'运维项目/meisheng-project-kb/meisheng-ops-26/meisheng-ops-26_看板.html'}, {listId:"mairui-ops-26",repo:"mairui-project-kb",issues:0,kanban:"运维项目/mairui-project-kb/mairui-ops-26/mairui-ops-26_看板.html",hasKanban:true},
{listId:'nuoweiqi-ops-26', repo:'nuoweiqi-project-kb', issues:0, kanban:'运维项目/nuoweiqi-project-kb/nuoweiqi-ops-26/nuoweiqi-ops-26_看板.html'}, {listId:"meisheng-ops-26",repo:"meisheng-project-kb",issues:0,kanban:"运维项目/meisheng-project-kb/meisheng-ops-26/meisheng-ops-26_看板.html",hasKanban:true},
{listId:'pulasike-ops-26', repo:'pulasike-project-kb', issues:0, kanban:'运维项目/pulasike-project-kb/pulasike-ops-26/pulasike-ops-26_看板.html'}, {listId:"nuoweiqi-ops-26",repo:"nuoweiqi-project-kb",issues:0,kanban:"运维项目/nuoweiqi-project-kb/nuoweiqi-ops-26/nuoweiqi-ops-26_看板.html",hasKanban:true},
{listId:'rongda-ops-26', repo:'rongda-project-kb', issues:0, kanban:'运维项目/rongda-project-kb/rongda-ops-26/rongda-ops-26_看板.html'}, {listId:"pulasike-ops-26",repo:"pulasike-project-kb",issues:0,kanban:"运维项目/pulasike-project-kb/pulasike-ops-26/pulasike-ops-26_看板.html",hasKanban:true},
{listId:'sanpangdan-ops-26', repo:'sanpangdan-project-kb', issues:0, kanban:'运维项目/sanpangdan-project-kb/sanpangdan-ops-26/sanpangdan-ops-26_看板.html'}, {listId:"rongda-ops-26",repo:"rongda-project-kb",issues:0,kanban:"运维项目/rongda-project-kb/rongda-ops-26/rongda-ops-26_看板.html",hasKanban:true},
{listId:'SCB-ops-26', repo:'SCB-project-kb', issues:0, kanban:'运维项目/SCB-project-kb/SCB-ops-26/SCB-ops-26_看板.html'}, {listId:"sanpangdan-ops-26",repo:"sanpangdan-project-kb",issues:0,kanban:"运维项目/sanpangdan-project-kb/sanpangdan-ops-26/sanpangdan-ops-26_看板.html",hasKanban:true},
{listId:'shijierqian-ops-26', repo:'shijierqian-project-kb', issues:0, kanban:'运维项目/shijierqian-project-kb/shijierqian-ops-26/shijierqian-ops-26_看板.html'}, {listId:"shijierqian-ops-26",repo:"shijierqian-project-kb",issues:0,kanban:"运维项目/shijierqian-project-kb/shijierqian-ops-26/shijierqian-ops-26_看板.html",hasKanban:true},
{listId:'start-ops-26', repo:'start-project-kb', issues:0, kanban:'运维项目/start-project-kb/start-ops-26/start-ops-26_看板.html'}, {listId:"start-ops-26",repo:"start-project-kb",issues:0,kanban:"运维项目/start-project-kb/start-ops-26/start-ops-26_看板.html",hasKanban:true},
{listId:'taikang-ops-26', repo:'taikang-project-kb', issues:0, kanban:'运维项目/taikang-project-kb/taikang-ops-26/taikang-ops-26_看板.html'}, {listId:"taikang-ops-26",repo:"taikang-project-kb",issues:0,kanban:"运维项目/taikang-project-kb/taikang-ops-26/taikang-ops-26_看板.html",hasKanban:true},
{listId:'tianxing-ops-26', repo:'tianxing-project-kb', issues:0, kanban:'运维项目/tianxing-project-kb/tianxing-ops-26/tianxing-ops-26_看板.html'}, {listId:"tianxing-ops-26",repo:"tianxing-project-kb",issues:0,kanban:"运维项目/tianxing-project-kb/tianxing-ops-26/tianxing-ops-26_看板.html",hasKanban:true},
{listId:'tongcheng-ops-26', repo:'tongcheng-project-kb', issues:0, kanban:'运维项目/tongcheng-project-kb/tongcheng-ops-26/tongcheng-ops-26_看板.html'}, {listId:"tongcheng-ops-26",repo:"tongcheng-project-kb",issues:0,kanban:"运维项目/tongcheng-project-kb/tongcheng-ops-26/tongcheng-ops-26_看板.html",hasKanban:true},
{listId:'tuochen-ops-26', repo:'tuochen-project-KB', issues:0, kanban:'运维项目/tuochen-project-KB/tuochen-ops-26/tuochen-ops-26_看板.html'}, {listId:"tuochen-ops-26",repo:"tuochen-project-KB",issues:0,kanban:"运维项目/tuochen-project-KB/tuochen-ops-26/tuochen-ops-26_看板.html",hasKanban:true},
{listId:'wanhong-ops-26', repo:'wanhong-project-kb', issues:0, kanban:'运维项目/wanhong-project-kb/wanhong-ops-26/wanhong-ops-26_看板.html'}, {listId:"wanhong-ops-26",repo:"wanhong-project-kb",issues:0,kanban:"运维项目/wanhong-project-kb/wanhong-ops-26/wanhong-ops-26_看板.html",hasKanban:true},
{listId:'wanrun-ops-26', repo:'wanrun-project-kb', issues:0, kanban:'运维项目/wanrun-project-kb/wanrun-ops-26/wanrun-ops-26_看板.html'}, {listId:"wanrun-ops-26",repo:"wanrun-project-kb",issues:0,kanban:"运维项目/wanrun-project-kb/wanrun-ops-26/wanrun-ops-26_看板.html",hasKanban:true},
{listId:'yanlong-ops-26', repo:'yanlong-project-kb', issues:0, kanban:'运维项目/yanlong-project-kb/yanlong-ops-26/yanlong-ops-26_看板.html'}, {listId:"yanlong-ops-26",repo:"yanlong-project-kb",issues:0,kanban:"运维项目/yanlong-project-kb/yanlong-ops-26/yanlong-ops-26_看板.html",hasKanban:true},
{listId:'yidianyuan-ops-26', repo:'yidianyuan-project-kb', issues:0, kanban:'运维项目/yidianyuan-project-kb/yidianyuan-ops-26/yidianyuan-ops-26_看板.html'}, {listId:"yidianyuan-ops-26",repo:"yidianyuan-project-kb",issues:0,kanban:"运维项目/yidianyuan-project-kb/yidianyuan-ops-26/yidianyuan-ops-26_看板.html",hasKanban:true},
{listId:'zhixing-ops-26', repo:'zhixing', issues:0, kanban:'运维项目/zhixing/zhixing-ops-26/zhixing-ops-26_看板.html'}, {listId:"zhixing-ops-26",repo:"zhixing",issues:0,kanban:"运维项目/zhixing/zhixing-ops-26/zhixing-ops-26_看板.html",hasKanban:true},
{listId:'zhongdi-ops-26', repo:'zhongdi-project-kb', issues:0, kanban:'运维项目/zhongdi-project-kb/zhongdi-ops-26/zhongdi-ops-26_看板.html'}, {listId:"zhongdi-ops-26",repo:"zhongdi-project-kb",issues:0,kanban:"运维项目/zhongdi-project-kb/zhongdi-ops-26/zhongdi-ops-26_看板.html",hasKanban:true},
{listId:'zhonghailiqing-ops-26', repo:'zhonghailiqing-project-kb', issues:0, kanban:'运维项目/zhonghailiqing-project-kb/zhonghailiqing-ops-26/zhonghailiqing-ops-26_看板.html'}, {listId:"zhonghailiqing-ops-26",repo:"zhonghailiqing-project-kb",issues:0,kanban:"运维项目/zhonghailiqing-project-kb/zhonghailiqing-ops-26/zhonghailiqing-ops-26_看板.html",hasKanban:true},
{listId:'zhongyou-ops-26', repo:'zhongyou-project-kb', issues:0, kanban:'运维项目/zhongyou-project-kb/zhongyou-ops-26/zhongyou-ops-26_看板.html'}, {listId:"zhongyou-ops-26",repo:"zhongyou-project-kb",issues:0,kanban:"运维项目/zhongyou-project-kb/zhongyou-ops-26/zhongyou-ops-26_看板.html",hasKanban:true},
{listId:'zongxun-ops-26', repo:'zongxun-project-kb', issues:0, kanban:'运维项目/zongxun-project-kb/zongxun-ops-26/zongxun-ops-26_看板.html'} {listId:"zongxun-ops-26",repo:"zongxun-project-kb",issues:0,kanban:"运维项目/zongxun-project-kb/zongxun-ops-26/zongxun-ops-26_看板.html",hasKanban:true}
]; ];
const grid = document.getElementById('ledgerGrid'); // Stats
let totalIssues = 0; const totalCount = ledgers.length;
let emptyCount = 0; const totalIssues = ledgers.reduce((s, l) => s + l.issues, 0);
const emptyCount = ledgers.filter(l => l.issues === 0).length;
const activeCount = totalCount - emptyCount;
document.getElementById('totalCount').textContent = totalCount;
document.getElementById('totalIssues').textContent = totalIssues;
document.getElementById('emptyCount').textContent = emptyCount;
document.getElementById('activeCount').textContent = activeCount;
// Cards
const grid = document.getElementById('ledgerGrid');
ledgers.forEach(l => { ledgers.forEach(l => {
const card = document.createElement('a'); const card = document.createElement('a');
card.className = 'card'; card.className = 'card' + (l.hasKanban ? '' : ' no-kanban');
card.href = l.kanban; if (l.hasKanban) card.href = l.kanban;
card.dataset.name = l.name.toLowerCase(); card.dataset.name = l.listId.toLowerCase();
card.dataset.repo = l.repo.toLowerCase(); card.dataset.repo = l.repo.toLowerCase();
const issueCount = l.issues || 0; const issueCount = l.issues;
totalIssues += issueCount;
if (issueCount === 0) emptyCount++;
const badge = issueCount > 0 ? 'badge-active' : 'badge-empty'; const badge = issueCount > 0 ? 'badge-active' : 'badge-empty';
const badgeText = issueCount > 0 ? issueCount + ' 涓棶棰? : '绌烘竻鍗?; const badgeText = issueCount > 0 ? issueCount + ' 个问题' : '空清单';
card.innerHTML = ` card.innerHTML = `
<div class="card-header"> <div class="card-header">
...@@ -136,14 +180,54 @@ ledgers.forEach(l => { ...@@ -136,14 +180,54 @@ ledgers.forEach(l => {
<span class="card-badge ${badge}">${badgeText}</span> <span class="card-badge ${badge}">${badgeText}</span>
</div> </div>
<div class="card-meta">${l.repo}</div> <div class="card-meta">${l.repo}</div>
<div class="card-path">杩愮淮椤圭洰/${l.repo}/</div> <div class="card-path">运维项目/${l.repo}/</div>
`; `;
grid.appendChild(card); grid.appendChild(card);
}); });
document.getElementById('totalIssues').textContent = totalIssues; // Status summary
document.getElementById('emptyCount').textContent = emptyCount; const statusSummary = document.getElementById('statusSummary');
const statusData = [
{ name: '空清单', count: emptyCount, color: '#f0f0f0', textColor: '#888' },
{ name: '有问题 (1-10)', count: ledgers.filter(l => l.issues >= 1 && l.issues <= 10).length, color: '#fff3e0', textColor: '#e65100' },
{ name: '较多 (11-50)', count: ledgers.filter(l => l.issues >= 11 && l.issues <= 50).length, color: '#e8f5e9', textColor: '#2e7d32' },
{ name: '大量 (50+)', count: ledgers.filter(l => l.issues > 50).length, color: '#e3f2fd', textColor: '#1565c0' }
];
statusData.forEach(s => {
const div = document.createElement('div');
div.className = 'summary-item';
div.style.borderLeft = `4px solid ${s.textColor}`;
div.innerHTML = `<div class="name">${s.name}</div><div class="count" style="color:${s.textColor}">${s.count}</div>`;
statusSummary.appendChild(div);
});
// Project summary
const projectSummary = document.getElementById('projectSummary');
const projectMap = {};
ledgers.forEach(l => {
const proj = l.repo.replace('-project-kb', '').replace('-KB', '');
if (!projectMap[proj]) projectMap[proj] = { count: 0, issues: 0 };
projectMap[proj].count++;
projectMap[proj].issues += l.issues;
});
Object.keys(projectMap).sort().forEach(proj => {
const data = projectMap[proj];
const div = document.createElement('div');
div.className = 'summary-item';
div.innerHTML = `<div class="name">${proj}</div><div class="count">${data.issues}</div><div class="sub">${data.count} 个清单</div>`;
projectSummary.appendChild(div);
});
// Tab switch
function switchTab(tab) {
document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
event.target.classList.add('active');
document.getElementById('view-all').classList.toggle('hidden', tab !== 'all');
document.getElementById('view-byStatus').classList.toggle('hidden', tab !== 'byStatus');
document.getElementById('view-byProject').classList.toggle('hidden', tab !== 'byProject');
}
// Search filter
function filterCards() { function filterCards() {
const q = document.getElementById('searchInput').value.toLowerCase(); const q = document.getElementById('searchInput').value.toLowerCase();
document.querySelectorAll('.card').forEach(c => { document.querySelectorAll('.card').forEach(c => {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment