aifastdb-devplan 1.2.2 → 1.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dev-plan-factory.d.ts +40 -0
- package/dist/dev-plan-factory.d.ts.map +1 -1
- package/dist/dev-plan-factory.js +73 -0
- package/dist/dev-plan-factory.js.map +1 -1
- package/dist/mcp-server/index.js +108 -20
- package/dist/mcp-server/index.js.map +1 -1
- package/dist/visualize/server.js +19 -0
- package/dist/visualize/server.js.map +1 -1
- package/dist/visualize/template.d.ts.map +1 -1
- package/dist/visualize/template.js +457 -24
- package/dist/visualize/template.js.map +1 -1
- package/package.json +1 -1
|
@@ -28,6 +28,8 @@ function getVisualizationHTML(projectName) {
|
|
|
28
28
|
.sidebar-header { height: 56px; display: flex; align-items: center; justify-content: center; border-bottom: 1px solid #1e293b; cursor: pointer; flex-shrink: 0; overflow: hidden; transition: all 0.2s; padding: 0 8px; }
|
|
29
29
|
.sidebar-header:hover { background: #1e293b; }
|
|
30
30
|
.sidebar-logo { font-size: 18px; font-weight: 900; background: linear-gradient(90deg, #38bdf8, #818cf8, #a78bfa, #f472b6); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; white-space: nowrap; line-height: 1; }
|
|
31
|
+
.sidebar-menu-icon { display: flex; align-items: center; justify-content: center; color: #9ca3af; transition: color 0.2s; }
|
|
32
|
+
.sidebar-header:hover .sidebar-menu-icon { color: #e2e8f0; }
|
|
31
33
|
.sidebar-logo-full { display: none; }
|
|
32
34
|
.sidebar-logo-short { display: block; }
|
|
33
35
|
.sidebar.expanded .sidebar-header { justify-content: flex-start; padding: 0 16px; }
|
|
@@ -65,6 +67,8 @@ function getVisualizationHTML(projectName) {
|
|
|
65
67
|
.stat .num.blue { color: #3b82f6; }
|
|
66
68
|
.stat .num.purple { color: #8b5cf6; }
|
|
67
69
|
.stat .num.amber { color: #f59e0b; }
|
|
70
|
+
.stat.clickable { cursor: pointer; border-radius: 6px; padding: 2px 8px; margin: -2px -8px; transition: background 0.15s; }
|
|
71
|
+
.stat.clickable:hover { background: rgba(99,102,241,0.12); }
|
|
68
72
|
.progress-bar { width: 120px; height: 8px; background: #374151; border-radius: 4px; overflow: hidden; }
|
|
69
73
|
.progress-fill { height: 100%; background: linear-gradient(90deg, #10b981, #3b82f6); border-radius: 4px; transition: width 0.5s; }
|
|
70
74
|
|
|
@@ -140,6 +144,11 @@ function getVisualizationHTML(projectName) {
|
|
|
140
144
|
.legend { background: #1f2937; border-top: 1px solid #374151; padding: 6px 24px; display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 10px 20px; font-size: 12px; color: #9ca3af; }
|
|
141
145
|
.legend-filters { display: flex; align-items: center; gap: 8px; }
|
|
142
146
|
.legend-divider { width: 1px; height: 18px; background: #374151; }
|
|
147
|
+
.legend-refresh-btn { display: flex; align-items: center; justify-content: center; background: none; border: 1px solid #374151; border-radius: 4px; padding: 3px 6px; cursor: pointer; color: #9ca3af; transition: color 0.2s, border-color 0.2s, background 0.2s; }
|
|
148
|
+
.legend-refresh-btn:hover { color: #60a5fa; border-color: #60a5fa; background: rgba(96,165,250,0.08); }
|
|
149
|
+
.legend-refresh-btn:active { color: #3b82f6; }
|
|
150
|
+
.legend-refresh-btn.refreshing .legend-refresh-icon { animation: spin-refresh 0.8s linear infinite; }
|
|
151
|
+
@keyframes spin-refresh { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
|
|
143
152
|
.legend-sep { width: 100%; height: 0; }
|
|
144
153
|
.legend-item { display: flex; align-items: center; gap: 6px; }
|
|
145
154
|
.legend-icon { width: 12px; height: 12px; }
|
|
@@ -279,10 +288,81 @@ function getVisualizationHTML(projectName) {
|
|
|
279
288
|
.module-card-bar-fill { height: 100%; background: linear-gradient(90deg, #059669, #10b981); border-radius: 3px; }
|
|
280
289
|
.module-card-stats { display: flex; justify-content: space-between; font-size: 11px; color: #6b7280; }
|
|
281
290
|
|
|
291
|
+
/* ===== Docs Browser Page ===== */
|
|
292
|
+
.docs-page { display: flex; flex: 1; min-height: 0; overflow: hidden; background: #111827; }
|
|
293
|
+
.docs-sidebar { width: 280px; background: #1f2937; border-right: 1px solid #374151; display: flex; flex-direction: column; flex-shrink: 0; overflow: hidden; }
|
|
294
|
+
.docs-sidebar-header { padding: 16px 20px 12px; border-bottom: 1px solid #374151; flex-shrink: 0; }
|
|
295
|
+
.docs-sidebar-header h3 { font-size: 15px; font-weight: 700; color: #f3f4f6; margin-bottom: 8px; }
|
|
296
|
+
.docs-search { width: 100%; background: #111827; border: 1px solid #374151; border-radius: 6px; padding: 7px 10px; color: #e5e7eb; font-size: 12px; outline: none; transition: border-color 0.2s; }
|
|
297
|
+
.docs-search:focus { border-color: #6366f1; }
|
|
298
|
+
.docs-search::placeholder { color: #6b7280; }
|
|
299
|
+
.docs-group-list { overflow-y: auto; flex: 1; padding: 8px 0; scrollbar-width: thin; scrollbar-color: #374151 transparent; }
|
|
300
|
+
.docs-group-list::-webkit-scrollbar { width: 6px; }
|
|
301
|
+
.docs-group-list::-webkit-scrollbar-track { background: transparent; }
|
|
302
|
+
.docs-group-list::-webkit-scrollbar-thumb { background: #374151; border-radius: 3px; }
|
|
303
|
+
.docs-group { margin-bottom: 4px; }
|
|
304
|
+
.docs-group-title { display: flex; align-items: center; gap: 8px; padding: 8px 20px; font-size: 11px; font-weight: 700; color: #9ca3af; text-transform: uppercase; letter-spacing: 0.05em; cursor: pointer; user-select: none; transition: color 0.15s; }
|
|
305
|
+
.docs-group-title:hover { color: #d1d5db; }
|
|
306
|
+
.docs-group-title .docs-group-arrow { font-size: 9px; transition: transform 0.2s; color: #6b7280; }
|
|
307
|
+
.docs-group.collapsed .docs-group-arrow { transform: rotate(-90deg); }
|
|
308
|
+
.docs-group.collapsed .docs-group-items { display: none; }
|
|
309
|
+
.docs-group-count { font-size: 10px; color: #4b5563; font-weight: 500; margin-left: auto; }
|
|
310
|
+
.docs-item { display: flex; align-items: center; gap: 8px; padding: 7px 20px 7px 28px; cursor: pointer; transition: background 0.15s; font-size: 13px; color: #d1d5db; border-left: 3px solid transparent; }
|
|
311
|
+
.docs-item:hover { background: rgba(55,65,81,0.4); }
|
|
312
|
+
.docs-item.active { background: rgba(99,102,241,0.12); border-left-color: #6366f1; color: #a5b4fc; }
|
|
313
|
+
.docs-item-icon { font-size: 14px; flex-shrink: 0; opacity: 0.7; }
|
|
314
|
+
.docs-item-text { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
315
|
+
.docs-item-sub { font-size: 10px; color: #6b7280; flex-shrink: 0; }
|
|
316
|
+
|
|
317
|
+
.docs-content { flex: 1; display: flex; flex-direction: column; min-width: 0; overflow: hidden; }
|
|
318
|
+
.docs-content-header { padding: 16px 28px 12px; border-bottom: 1px solid #374151; flex-shrink: 0; display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; }
|
|
319
|
+
.docs-content-title { font-size: 20px; font-weight: 700; color: #f3f4f6; }
|
|
320
|
+
.docs-content-meta { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 4px; }
|
|
321
|
+
.docs-content-tag { font-size: 11px; padding: 2px 8px; border-radius: 4px; background: #374151; color: #9ca3af; }
|
|
322
|
+
.docs-content-tag.section { background: rgba(99,102,241,0.15); color: #a5b4fc; }
|
|
323
|
+
.docs-content-tag.version { background: rgba(16,185,129,0.15); color: #6ee7b7; }
|
|
324
|
+
.docs-content-body { flex: 1; overflow-y: auto; padding: 20px 28px 40px; scrollbar-width: thin; scrollbar-color: #374151 transparent; }
|
|
325
|
+
.docs-content-body::-webkit-scrollbar { width: 6px; }
|
|
326
|
+
.docs-content-body::-webkit-scrollbar-track { background: transparent; }
|
|
327
|
+
.docs-content-body::-webkit-scrollbar-thumb { background: #374151; border-radius: 3px; }
|
|
328
|
+
.docs-content-empty { flex: 1; display: flex; align-items: center; justify-content: center; color: #4b5563; font-size: 14px; flex-direction: column; gap: 8px; }
|
|
329
|
+
.docs-content-empty .empty-icon { font-size: 48px; opacity: 0.4; }
|
|
330
|
+
.docs-related { margin-top: 20px; border-top: 1px solid #374151; padding-top: 16px; }
|
|
331
|
+
.docs-related-title { font-size: 13px; font-weight: 600; color: #9ca3af; margin-bottom: 10px; display: flex; align-items: center; gap: 6px; }
|
|
332
|
+
.docs-related-item { display: flex; align-items: center; gap: 8px; padding: 5px 0; font-size: 12px; color: #d1d5db; }
|
|
333
|
+
.docs-related-item .rel-icon { width: 16px; height: 16px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 9px; flex-shrink: 0; }
|
|
334
|
+
|
|
282
335
|
/* Debug bar */
|
|
283
336
|
.debug { position: absolute; bottom: 0; left: 12px; background: rgba(31,41,55,0.9); border: 1px solid #374151; border-radius: 8px 8px 0 0; padding: 8px 12px; font-size: 11px; color: #9ca3af; z-index: 30; max-width: 400px; }
|
|
284
337
|
.debug .ok { color: #10b981; }
|
|
285
338
|
.debug .err { color: #f87171; }
|
|
339
|
+
|
|
340
|
+
/* Stats Modal — left side panel */
|
|
341
|
+
.stats-modal-overlay { display: none; position: fixed; inset: 0; z-index: 200; pointer-events: none; }
|
|
342
|
+
.stats-modal-overlay.active { display: block; }
|
|
343
|
+
.stats-modal { position: fixed; top: 0; bottom: 0; left: 48px; width: 300px; background: #1f2937; border-right: 1px solid #374151; display: flex; flex-direction: column; box-shadow: 4px 0 24px rgba(0,0,0,0.4); animation: modal-slide-in 0.2s ease; z-index: 201; pointer-events: auto; transition: left 0.25s ease; }
|
|
344
|
+
@keyframes modal-slide-in { from { opacity: 0; transform: translateX(-16px); } to { opacity: 1; transform: translateX(0); } }
|
|
345
|
+
.stats-modal-header { display: flex; align-items: center; justify-content: space-between; padding: 16px 20px; border-bottom: 1px solid #374151; }
|
|
346
|
+
.stats-modal-title { font-size: 15px; font-weight: 700; color: #f3f4f6; }
|
|
347
|
+
.stats-modal-count { font-size: 12px; color: #6b7280; margin-left: 8px; }
|
|
348
|
+
.stats-modal-close { background: none; border: none; color: #6b7280; font-size: 18px; cursor: pointer; padding: 4px 8px; border-radius: 4px; line-height: 1; }
|
|
349
|
+
.stats-modal-close:hover { background: #374151; color: #e5e7eb; }
|
|
350
|
+
.stats-modal-body { overflow-y: auto; padding: 8px 0; flex: 1; min-height: 0; scrollbar-width: thin; scrollbar-color: #374151 transparent; }
|
|
351
|
+
.stats-modal-body::-webkit-scrollbar { width: 6px; }
|
|
352
|
+
.stats-modal-body::-webkit-scrollbar-track { background: transparent; }
|
|
353
|
+
.stats-modal-body::-webkit-scrollbar-thumb { background: #374151; border-radius: 3px; }
|
|
354
|
+
.stats-modal-body::-webkit-scrollbar-thumb:hover { background: #4b5563; }
|
|
355
|
+
.stats-modal-item { display: flex; align-items: center; gap: 10px; padding: 10px 20px; cursor: pointer; transition: background 0.15s; }
|
|
356
|
+
.stats-modal-item:hover { background: #283344; }
|
|
357
|
+
.stats-modal-item-icon { font-size: 14px; flex-shrink: 0; width: 22px; text-align: center; }
|
|
358
|
+
.stats-modal-item-name { flex: 1; font-size: 13px; color: #e5e7eb; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
359
|
+
.stats-modal-item-badge { font-size: 11px; padding: 2px 8px; border-radius: 9999px; flex-shrink: 0; }
|
|
360
|
+
.stats-modal-item-badge.completed { background: rgba(16,185,129,0.15); color: #6ee7b7; }
|
|
361
|
+
.stats-modal-item-badge.in_progress { background: rgba(59,130,246,0.15); color: #93c5fd; }
|
|
362
|
+
.stats-modal-item-badge.pending { background: rgba(107,114,128,0.15); color: #9ca3af; }
|
|
363
|
+
.stats-modal-item-badge.cancelled { background: rgba(146,64,14,0.15); color: #fbbf24; }
|
|
364
|
+
.stats-modal-item-badge.active { background: rgba(16,185,129,0.15); color: #6ee7b7; }
|
|
365
|
+
.stats-modal-item-sub { font-size: 11px; color: #6b7280; flex-shrink: 0; font-family: monospace; }
|
|
286
366
|
</style>
|
|
287
367
|
</head>
|
|
288
368
|
<body>
|
|
@@ -290,7 +370,7 @@ function getVisualizationHTML(projectName) {
|
|
|
290
370
|
<!-- Sidebar -->
|
|
291
371
|
<div class="sidebar" id="sidebar">
|
|
292
372
|
<div class="sidebar-header" onclick="toggleSidebar()" title="展开/收起导航">
|
|
293
|
-
<span class="sidebar-
|
|
373
|
+
<span class="sidebar-menu-icon sidebar-logo-short"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/></svg></span>
|
|
294
374
|
<span class="sidebar-logo sidebar-logo-full">AiFastDb-DevPlan</span>
|
|
295
375
|
</div>
|
|
296
376
|
<div class="sidebar-nav">
|
|
@@ -305,11 +385,10 @@ function getVisualizationHTML(projectName) {
|
|
|
305
385
|
<span class="nav-item-badge">即将推出</span>
|
|
306
386
|
<span class="nav-tooltip">任务看板 (即将推出)</span>
|
|
307
387
|
</div>
|
|
308
|
-
<div class="nav-item
|
|
388
|
+
<div class="nav-item" data-page="docs" onclick="navTo('docs')">
|
|
309
389
|
<span class="nav-item-icon">📄</span>
|
|
310
390
|
<span class="nav-item-text">文档浏览</span>
|
|
311
|
-
<span class="nav-
|
|
312
|
-
<span class="nav-tooltip">文档浏览 (即将推出)</span>
|
|
391
|
+
<span class="nav-tooltip">文档浏览</span>
|
|
313
392
|
</div>
|
|
314
393
|
<div class="nav-item" data-page="stats" onclick="navTo('stats')">
|
|
315
394
|
<span class="nav-item-icon">📊</span>
|
|
@@ -363,6 +442,11 @@ function getVisualizationHTML(projectName) {
|
|
|
363
442
|
|
|
364
443
|
<!-- Legend + Filters (merged) -->
|
|
365
444
|
<div class="legend">
|
|
445
|
+
<!-- 刷新按钮 -->
|
|
446
|
+
<button class="legend-refresh-btn" id="legendRefreshBtn" onclick="manualRefresh()" title="刷新数据 (F5)">
|
|
447
|
+
<svg class="legend-refresh-icon" id="legendRefreshIcon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M21 2v6h-6"/><path d="M3 12a9 9 0 0 1 15-6.7L21 8"/><path d="M3 22v-6h6"/><path d="M21 12a9 9 0 0 1-15 6.7L3 16"/></svg>
|
|
448
|
+
</button>
|
|
449
|
+
<div class="legend-divider"></div>
|
|
366
450
|
<!-- 筛选复选框 -->
|
|
367
451
|
<label class="filter-check"><input type="checkbox" checked data-type="module" onchange="toggleFilter('module')"> 模块</label>
|
|
368
452
|
<label class="filter-check"><input type="checkbox" checked data-type="main-task" onchange="toggleFilter('main-task')"> 主任务</label>
|
|
@@ -384,6 +468,40 @@ function getVisualizationHTML(projectName) {
|
|
|
384
468
|
</div>
|
|
385
469
|
</div>
|
|
386
470
|
|
|
471
|
+
<!-- ===== PAGE: Docs Browser ===== -->
|
|
472
|
+
<div class="page-view" id="pageDocs">
|
|
473
|
+
<div class="docs-page">
|
|
474
|
+
<!-- Left: Document List -->
|
|
475
|
+
<div class="docs-sidebar">
|
|
476
|
+
<div class="docs-sidebar-header">
|
|
477
|
+
<h3>📄 文档库</h3>
|
|
478
|
+
<input type="text" class="docs-search" id="docsSearch" placeholder="搜索文档标题..." oninput="filterDocs()">
|
|
479
|
+
</div>
|
|
480
|
+
<div class="docs-group-list" id="docsGroupList">
|
|
481
|
+
<div style="text-align:center;padding:40px;color:#6b7280;font-size:12px;">加载中...</div>
|
|
482
|
+
</div>
|
|
483
|
+
</div>
|
|
484
|
+
<!-- Right: Document Content -->
|
|
485
|
+
<div class="docs-content">
|
|
486
|
+
<div class="docs-content-empty" id="docsEmptyState">
|
|
487
|
+
<div class="empty-icon">📄</div>
|
|
488
|
+
<div>选择左侧文档查看内容</div>
|
|
489
|
+
</div>
|
|
490
|
+
<div id="docsContentView" style="display:none;flex-direction:column;flex:1;min-height:0;">
|
|
491
|
+
<div class="docs-content-header">
|
|
492
|
+
<div>
|
|
493
|
+
<div class="docs-content-title" id="docsContentTitle">文档标题</div>
|
|
494
|
+
<div class="docs-content-meta" id="docsContentMeta"></div>
|
|
495
|
+
</div>
|
|
496
|
+
</div>
|
|
497
|
+
<div class="docs-content-body" id="docsContentBody">
|
|
498
|
+
<div class="doc-content" id="docsContentInner"></div>
|
|
499
|
+
</div>
|
|
500
|
+
</div>
|
|
501
|
+
</div>
|
|
502
|
+
</div>
|
|
503
|
+
</div>
|
|
504
|
+
|
|
387
505
|
<!-- ===== PAGE: Stats Dashboard ===== -->
|
|
388
506
|
<div class="page-view" id="pageStats">
|
|
389
507
|
<div class="stats-page" id="statsPageContent">
|
|
@@ -399,6 +517,17 @@ function getVisualizationHTML(projectName) {
|
|
|
399
517
|
</div>
|
|
400
518
|
</div>
|
|
401
519
|
|
|
520
|
+
<!-- Stats Modal -->
|
|
521
|
+
<div class="stats-modal-overlay" id="statsModalOverlay">
|
|
522
|
+
<div class="stats-modal">
|
|
523
|
+
<div class="stats-modal-header">
|
|
524
|
+
<div><span class="stats-modal-title" id="statsModalTitle">列表</span><span class="stats-modal-count" id="statsModalCount"></span></div>
|
|
525
|
+
<button class="stats-modal-close" onclick="closeStatsModal()">×</button>
|
|
526
|
+
</div>
|
|
527
|
+
<div class="stats-modal-body" id="statsModalBody"></div>
|
|
528
|
+
</div>
|
|
529
|
+
</div>
|
|
530
|
+
|
|
402
531
|
<script>
|
|
403
532
|
// ========== Sidebar ==========
|
|
404
533
|
function toggleSidebar() {
|
|
@@ -408,12 +537,23 @@ function toggleSidebar() {
|
|
|
408
537
|
var isExpanded = sidebar.classList.contains('expanded');
|
|
409
538
|
// 记住偏好
|
|
410
539
|
try { localStorage.setItem('devplan_sidebar_expanded', isExpanded ? '1' : '0'); } catch(e) {}
|
|
540
|
+
// 同步更新左侧弹层位置
|
|
541
|
+
updateStatsModalPosition();
|
|
411
542
|
// 通知 vis-network 重新适配尺寸
|
|
412
543
|
setTimeout(function() { if (network) network.redraw(); }, 300);
|
|
413
544
|
}
|
|
414
545
|
|
|
546
|
+
/** 根据侧边栏状态更新左侧弹层位置 */
|
|
547
|
+
function updateStatsModalPosition() {
|
|
548
|
+
var modal = document.querySelector('.stats-modal');
|
|
549
|
+
var sidebar = document.getElementById('sidebar');
|
|
550
|
+
if (modal && sidebar) {
|
|
551
|
+
modal.style.left = (sidebar.classList.contains('expanded') ? 200 : 48) + 'px';
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
|
|
415
555
|
var currentPage = 'graph';
|
|
416
|
-
var pageMap = { graph: 'pageGraph', stats: 'pageStats' };
|
|
556
|
+
var pageMap = { graph: 'pageGraph', stats: 'pageStats', docs: 'pageDocs' };
|
|
417
557
|
|
|
418
558
|
function navTo(page) {
|
|
419
559
|
// 仅支持已实现的页面
|
|
@@ -435,8 +575,12 @@ function navTo(page) {
|
|
|
435
575
|
|
|
436
576
|
currentPage = page;
|
|
437
577
|
|
|
578
|
+
// 离开图谱页面时关闭左侧弹层
|
|
579
|
+
if (page !== 'graph') closeStatsModal();
|
|
580
|
+
|
|
438
581
|
// 按需加载页面数据
|
|
439
582
|
if (page === 'stats') loadStatsPage();
|
|
583
|
+
if (page === 'docs') loadDocsPage();
|
|
440
584
|
if (page === 'graph' && network) {
|
|
441
585
|
setTimeout(function() { network.redraw(); network.fit(); }, 100);
|
|
442
586
|
}
|
|
@@ -449,6 +593,8 @@ function navTo(page) {
|
|
|
449
593
|
if (saved === '1') {
|
|
450
594
|
var sidebar = document.getElementById('sidebar');
|
|
451
595
|
if (sidebar) { sidebar.classList.add('expanded'); }
|
|
596
|
+
// 同步弹层初始位置
|
|
597
|
+
updateStatsModalPosition();
|
|
452
598
|
}
|
|
453
599
|
} catch(e) {}
|
|
454
600
|
})();
|
|
@@ -593,10 +739,10 @@ function nodeStyle(node, degree) {
|
|
|
593
739
|
var ns = calcNodeSize(t, degree || 0);
|
|
594
740
|
|
|
595
741
|
if (t === 'project') {
|
|
596
|
-
return { shape: 'star', size: ns.size, color: { background: '#f59e0b', border: '#d97706', highlight: { background: '#fbbf24', border: '#
|
|
742
|
+
return { shape: 'star', size: ns.size, color: { background: '#f59e0b', border: '#d97706', highlight: { background: '#fbbf24', border: '#fff' } }, font: { size: ns.fontSize, color: '#fff' }, borderWidth: 3 };
|
|
597
743
|
}
|
|
598
744
|
if (t === 'module') {
|
|
599
|
-
return { shape: 'diamond', size: ns.size, color: { background: '#059669', border: '#047857', highlight: { background: '#10b981', border: '#
|
|
745
|
+
return { shape: 'diamond', size: ns.size, color: { background: '#059669', border: '#047857', highlight: { background: '#10b981', border: '#fff' } }, font: { size: ns.fontSize, color: '#d1fae5' }, borderWidth: 2 };
|
|
600
746
|
}
|
|
601
747
|
if (t === 'main-task') {
|
|
602
748
|
return { shape: 'dot', size: ns.size, color: { background: sc.bg, border: sc.border, highlight: { background: sc.bg, border: '#fff' } }, font: { size: ns.fontSize, color: sc.font }, borderWidth: 2 };
|
|
@@ -605,7 +751,7 @@ function nodeStyle(node, degree) {
|
|
|
605
751
|
return { shape: 'dot', size: ns.size, color: { background: sc.bg, border: sc.border, highlight: { background: sc.bg, border: '#fff' } }, font: { size: ns.fontSize, color: sc.font }, borderWidth: 1 };
|
|
606
752
|
}
|
|
607
753
|
if (t === 'document') {
|
|
608
|
-
return { shape: 'box', size: ns.size, color: { background: '#7c3aed', border: '#6d28d9', highlight: { background: '#8b5cf6', border: '#
|
|
754
|
+
return { shape: 'box', size: ns.size, color: { background: '#7c3aed', border: '#6d28d9', highlight: { background: '#8b5cf6', border: '#fff' } }, font: { size: ns.fontSize, color: '#ddd6fe' }, borderWidth: 1 };
|
|
609
755
|
}
|
|
610
756
|
return { shape: 'dot', size: ns.size, color: { background: '#6b7280', border: '#4b5563' }, font: { size: ns.fontSize, color: '#9ca3af' } };
|
|
611
757
|
}
|
|
@@ -652,9 +798,9 @@ function renderStats(progress, graph) {
|
|
|
652
798
|
if (graph.nodes[i].type === 'module') moduleCount++;
|
|
653
799
|
}
|
|
654
800
|
bar.innerHTML =
|
|
655
|
-
'<div class="stat"><span class="num amber">' + moduleCount + '</span> 模块</div>' +
|
|
656
|
-
'<div class="stat"><span class="num blue">' + progress.mainTaskCount + '</span> 主任务</div>' +
|
|
657
|
-
'<div class="stat"><span class="num purple">' + progress.subTaskCount + '</span> 子任务</div>' +
|
|
801
|
+
'<div class="stat clickable" onclick="showStatsModal(\\x27module\\x27)" title="查看所有模块"><span class="num amber">' + moduleCount + '</span> 模块</div>' +
|
|
802
|
+
'<div class="stat clickable" onclick="showStatsModal(\\x27main-task\\x27)" title="查看所有主任务"><span class="num blue">' + progress.mainTaskCount + '</span> 主任务</div>' +
|
|
803
|
+
'<div class="stat clickable" onclick="showStatsModal(\\x27sub-task\\x27)" title="查看所有子任务"><span class="num purple">' + progress.subTaskCount + '</span> 子任务</div>' +
|
|
658
804
|
'<div class="stat"><span class="num green">' + progress.completedSubTasks + '/' + progress.subTaskCount + '</span> 已完成</div>' +
|
|
659
805
|
'<div class="stat"><div class="progress-bar"><div class="progress-fill" style="width:' + pct + '%"></div></div><span>' + pct + '%</span></div>';
|
|
660
806
|
}
|
|
@@ -1376,20 +1522,93 @@ function toggleFilter(type) {
|
|
|
1376
1522
|
renderGraph();
|
|
1377
1523
|
}
|
|
1378
1524
|
|
|
1379
|
-
// ==========
|
|
1380
|
-
|
|
1381
|
-
var
|
|
1525
|
+
// ========== Stats Modal ==========
|
|
1526
|
+
function showStatsModal(nodeType) {
|
|
1527
|
+
var titleMap = { 'module': '功能模块', 'main-task': '主任务', 'sub-task': '子任务' };
|
|
1528
|
+
var iconMap = { 'module': '◆', 'main-task': '●', 'sub-task': '·' };
|
|
1529
|
+
var items = [];
|
|
1530
|
+
for (var i = 0; i < allNodes.length; i++) {
|
|
1531
|
+
if (allNodes[i].type === nodeType) items.push(allNodes[i]);
|
|
1532
|
+
}
|
|
1533
|
+
// 排序:进行中 > 待开始 > 已完成 > 已取消
|
|
1534
|
+
var statusOrder = { in_progress: 0, pending: 1, completed: 2, cancelled: 3, active: 1 };
|
|
1535
|
+
items.sort(function(a, b) {
|
|
1536
|
+
var sa = (a.properties || {}).status || 'pending';
|
|
1537
|
+
var sb = (b.properties || {}).status || 'pending';
|
|
1538
|
+
return (statusOrder[sa] !== undefined ? statusOrder[sa] : 5) - (statusOrder[sb] !== undefined ? statusOrder[sb] : 5);
|
|
1539
|
+
});
|
|
1540
|
+
|
|
1541
|
+
document.getElementById('statsModalTitle').textContent = titleMap[nodeType] || nodeType;
|
|
1542
|
+
document.getElementById('statsModalCount').textContent = '(' + items.length + ')';
|
|
1382
1543
|
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1544
|
+
var html = '';
|
|
1545
|
+
for (var i = 0; i < items.length; i++) {
|
|
1546
|
+
var n = items[i];
|
|
1547
|
+
var p = n.properties || {};
|
|
1548
|
+
var st = p.status || (nodeType === 'module' ? 'active' : 'pending');
|
|
1549
|
+
var icon = iconMap[nodeType] || '●';
|
|
1550
|
+
html += '<div class="stats-modal-item" onclick="statsModalGoToNode(\\x27' + n.id + '\\x27)">';
|
|
1551
|
+
html += '<span class="stats-modal-item-icon">' + icon + '</span>';
|
|
1552
|
+
html += '<span class="stats-modal-item-name" title="' + escHtml(n.label) + '">' + escHtml(n.label) + '</span>';
|
|
1553
|
+
if (nodeType === 'main-task') {
|
|
1554
|
+
var subCount = 0; var subDone = 0;
|
|
1555
|
+
for (var j = 0; j < allNodes.length; j++) {
|
|
1556
|
+
if (allNodes[j].type === 'sub-task' && (allNodes[j].properties || {}).parentTaskId === p.taskId) {
|
|
1557
|
+
subCount++;
|
|
1558
|
+
if ((allNodes[j].properties || {}).status === 'completed') subDone++;
|
|
1559
|
+
}
|
|
1560
|
+
}
|
|
1561
|
+
if (subCount > 0) {
|
|
1562
|
+
html += '<span class="stats-modal-item-sub">' + subDone + '/' + subCount + '</span>';
|
|
1563
|
+
}
|
|
1564
|
+
}
|
|
1565
|
+
if (nodeType === 'module' && p.mainTaskCount !== undefined) {
|
|
1566
|
+
html += '<span class="stats-modal-item-sub">' + p.mainTaskCount + ' 任务</span>';
|
|
1567
|
+
}
|
|
1568
|
+
html += '<span class="stats-modal-item-badge ' + st + '">' + statusText(st) + '</span>';
|
|
1569
|
+
html += '</div>';
|
|
1570
|
+
}
|
|
1571
|
+
if (items.length === 0) {
|
|
1572
|
+
html = '<div style="text-align:center;padding:40px;color:#6b7280;">暂无数据</div>';
|
|
1573
|
+
}
|
|
1574
|
+
document.getElementById('statsModalBody').innerHTML = html;
|
|
1575
|
+
// 根据侧边栏状态调整弹层位置
|
|
1576
|
+
updateStatsModalPosition();
|
|
1577
|
+
document.getElementById('statsModalOverlay').classList.add('active');
|
|
1578
|
+
}
|
|
1579
|
+
|
|
1580
|
+
function closeStatsModal() {
|
|
1581
|
+
document.getElementById('statsModalOverlay').classList.remove('active');
|
|
1582
|
+
}
|
|
1583
|
+
|
|
1584
|
+
function statsModalGoToNode(nodeId) {
|
|
1585
|
+
if (network && nodesDataSet && nodesDataSet.get(nodeId)) {
|
|
1586
|
+
network.selectNodes([nodeId]);
|
|
1587
|
+
network.focus(nodeId, { scale: 1.2, animation: { duration: 400, easingFunction: 'easeInOutQuad' } });
|
|
1588
|
+
panelHistory = [];
|
|
1589
|
+
currentPanelNodeId = null;
|
|
1590
|
+
showPanel(nodeId);
|
|
1591
|
+
}
|
|
1389
1592
|
}
|
|
1390
1593
|
|
|
1391
|
-
|
|
1392
|
-
|
|
1594
|
+
// ========== Manual Refresh ==========
|
|
1595
|
+
var _refreshing = false;
|
|
1596
|
+
|
|
1597
|
+
/** 手动刷新:点击刷新按钮或按 F5 时触发(带旋转动画反馈) */
|
|
1598
|
+
function manualRefresh() {
|
|
1599
|
+
if (_refreshing) return;
|
|
1600
|
+
_refreshing = true;
|
|
1601
|
+
var btn = document.getElementById('legendRefreshBtn');
|
|
1602
|
+
if (btn) btn.classList.add('refreshing');
|
|
1603
|
+
log('手动刷新: 获取最新数据...', true);
|
|
1604
|
+
silentRefresh(function() {
|
|
1605
|
+
_refreshing = false;
|
|
1606
|
+
if (btn) btn.classList.remove('refreshing');
|
|
1607
|
+
});
|
|
1608
|
+
}
|
|
1609
|
+
|
|
1610
|
+
/** 静默刷新:只更新数据,不重建图谱(避免布局跳动)。onDone 回调在请求完成后触发。 */
|
|
1611
|
+
function silentRefresh(onDone) {
|
|
1393
1612
|
var graphApiUrl = '/api/graph?includeNodeDegree=' + (INCLUDE_NODE_DEGREE ? 'true' : 'false') +
|
|
1394
1613
|
'&enableBackendDegreeFallback=' + (ENABLE_BACKEND_DEGREE_FALLBACK ? 'true' : 'false');
|
|
1395
1614
|
Promise.all([
|
|
@@ -1437,8 +1656,10 @@ function silentRefresh() {
|
|
|
1437
1656
|
} else {
|
|
1438
1657
|
log('数据无变化 (' + new Date().toLocaleTimeString() + ')', true);
|
|
1439
1658
|
}
|
|
1659
|
+
if (typeof onDone === 'function') onDone();
|
|
1440
1660
|
}).catch(function(err) {
|
|
1441
|
-
log('
|
|
1661
|
+
log('刷新失败: ' + err.message, false);
|
|
1662
|
+
if (typeof onDone === 'function') onDone();
|
|
1442
1663
|
});
|
|
1443
1664
|
}
|
|
1444
1665
|
|
|
@@ -1495,7 +1716,219 @@ function updateNodeStyles() {
|
|
|
1495
1716
|
function startApp() {
|
|
1496
1717
|
log('vis-network 就绪, 开始加载数据...', true);
|
|
1497
1718
|
loadData();
|
|
1498
|
-
|
|
1719
|
+
}
|
|
1720
|
+
|
|
1721
|
+
// ========== Docs Browser ==========
|
|
1722
|
+
var docsLoaded = false;
|
|
1723
|
+
var docsData = []; // 全部文档列表
|
|
1724
|
+
var currentDocKey = ''; // 当前选中文档的 key (section|subSection)
|
|
1725
|
+
|
|
1726
|
+
/** Section 类型的中文名称映射 */
|
|
1727
|
+
var SECTION_NAMES = {
|
|
1728
|
+
overview: '概述', core_concepts: '核心概念', api_design: 'API 设计',
|
|
1729
|
+
file_structure: '文件结构', config: '配置', examples: '使用示例',
|
|
1730
|
+
technical_notes: '技术笔记', api_endpoints: 'API 端点',
|
|
1731
|
+
milestones: '里程碑', changelog: '变更记录', custom: '自定义'
|
|
1732
|
+
};
|
|
1733
|
+
|
|
1734
|
+
/** Section 图标映射 */
|
|
1735
|
+
var SECTION_ICONS = {
|
|
1736
|
+
overview: '📋', core_concepts: '🧠', api_design: '🔌',
|
|
1737
|
+
file_structure: '📁', config: '⚙️', examples: '💡',
|
|
1738
|
+
technical_notes: '🔬', api_endpoints: '🌐',
|
|
1739
|
+
milestones: '🏁', changelog: '📝', custom: '📎'
|
|
1740
|
+
};
|
|
1741
|
+
|
|
1742
|
+
function loadDocsPage() {
|
|
1743
|
+
if (docsLoaded && docsData.length > 0) return;
|
|
1744
|
+
var list = document.getElementById('docsGroupList');
|
|
1745
|
+
if (list) list.innerHTML = '<div style="text-align:center;padding:40px;color:#6b7280;font-size:12px;"><div class="spinner" style="margin:0 auto 12px;width:24px;height:24px;border-width:3px;"></div>加载文档列表...</div>';
|
|
1746
|
+
|
|
1747
|
+
fetch('/api/docs').then(function(r) { return r.json(); }).then(function(data) {
|
|
1748
|
+
docsData = data.docs || [];
|
|
1749
|
+
docsLoaded = true;
|
|
1750
|
+
renderDocsList(docsData);
|
|
1751
|
+
}).catch(function(err) {
|
|
1752
|
+
if (list) list.innerHTML = '<div style="text-align:center;padding:40px;color:#f87171;font-size:12px;">加载失败: ' + err.message + '<br><span style="cursor:pointer;color:#818cf8;text-decoration:underline;" onclick="docsLoaded=false;loadDocsPage();">重试</span></div>';
|
|
1753
|
+
});
|
|
1754
|
+
}
|
|
1755
|
+
|
|
1756
|
+
/** 将文档列表按 section 分组渲染 */
|
|
1757
|
+
function renderDocsList(docs) {
|
|
1758
|
+
var list = document.getElementById('docsGroupList');
|
|
1759
|
+
if (!list) return;
|
|
1760
|
+
|
|
1761
|
+
// 按 section 分组
|
|
1762
|
+
var groups = {};
|
|
1763
|
+
var groupOrder = [];
|
|
1764
|
+
for (var i = 0; i < docs.length; i++) {
|
|
1765
|
+
var d = docs[i];
|
|
1766
|
+
var sec = d.section;
|
|
1767
|
+
if (!groups[sec]) {
|
|
1768
|
+
groups[sec] = [];
|
|
1769
|
+
groupOrder.push(sec);
|
|
1770
|
+
}
|
|
1771
|
+
groups[sec].push(d);
|
|
1772
|
+
}
|
|
1773
|
+
|
|
1774
|
+
if (groupOrder.length === 0) {
|
|
1775
|
+
list.innerHTML = '<div style="text-align:center;padding:40px;color:#6b7280;font-size:12px;">暂无文档</div>';
|
|
1776
|
+
return;
|
|
1777
|
+
}
|
|
1778
|
+
|
|
1779
|
+
var html = '';
|
|
1780
|
+
for (var gi = 0; gi < groupOrder.length; gi++) {
|
|
1781
|
+
var sec = groupOrder[gi];
|
|
1782
|
+
var items = groups[sec];
|
|
1783
|
+
var secName = SECTION_NAMES[sec] || sec;
|
|
1784
|
+
var secIcon = SECTION_ICONS[sec] || '📄';
|
|
1785
|
+
|
|
1786
|
+
html += '<div class="docs-group" data-section="' + sec + '">';
|
|
1787
|
+
html += '<div class="docs-group-title" onclick="toggleDocsGroup(this)">';
|
|
1788
|
+
html += '<span class="docs-group-arrow">▼</span>';
|
|
1789
|
+
html += '<span>' + secIcon + ' ' + secName + '</span>';
|
|
1790
|
+
html += '<span class="docs-group-count">' + items.length + '</span>';
|
|
1791
|
+
html += '</div>';
|
|
1792
|
+
html += '<div class="docs-group-items">';
|
|
1793
|
+
|
|
1794
|
+
for (var ii = 0; ii < items.length; ii++) {
|
|
1795
|
+
var item = items[ii];
|
|
1796
|
+
var docKey = item.section + (item.subSection ? '|' + item.subSection : '');
|
|
1797
|
+
var isActive = docKey === currentDocKey ? ' active' : '';
|
|
1798
|
+
html += '<div class="docs-item' + isActive + '" data-key="' + escHtml(docKey) + '" onclick="selectDoc(\\x27' + docKey.replace(/'/g, "\\\\'") + '\\x27)">';
|
|
1799
|
+
html += '<span class="docs-item-icon">' + secIcon + '</span>';
|
|
1800
|
+
html += '<span class="docs-item-text" title="' + escHtml(item.title) + '">' + escHtml(item.title) + '</span>';
|
|
1801
|
+
if (item.subSection) {
|
|
1802
|
+
html += '<span class="docs-item-sub">' + escHtml(item.subSection) + '</span>';
|
|
1803
|
+
}
|
|
1804
|
+
html += '</div>';
|
|
1805
|
+
}
|
|
1806
|
+
|
|
1807
|
+
html += '</div></div>';
|
|
1808
|
+
}
|
|
1809
|
+
|
|
1810
|
+
list.innerHTML = html;
|
|
1811
|
+
}
|
|
1812
|
+
|
|
1813
|
+
/** 展开/折叠文档分组 */
|
|
1814
|
+
function toggleDocsGroup(el) {
|
|
1815
|
+
var group = el.closest('.docs-group');
|
|
1816
|
+
if (group) group.classList.toggle('collapsed');
|
|
1817
|
+
}
|
|
1818
|
+
|
|
1819
|
+
/** 搜索过滤文档列表 */
|
|
1820
|
+
function filterDocs() {
|
|
1821
|
+
var query = (document.getElementById('docsSearch').value || '').toLowerCase().trim();
|
|
1822
|
+
if (!query) {
|
|
1823
|
+
renderDocsList(docsData);
|
|
1824
|
+
return;
|
|
1825
|
+
}
|
|
1826
|
+
var filtered = [];
|
|
1827
|
+
for (var i = 0; i < docsData.length; i++) {
|
|
1828
|
+
var d = docsData[i];
|
|
1829
|
+
var text = (d.title || '') + ' ' + (d.section || '') + ' ' + (d.subSection || '');
|
|
1830
|
+
if (text.toLowerCase().indexOf(query) >= 0) {
|
|
1831
|
+
filtered.push(d);
|
|
1832
|
+
}
|
|
1833
|
+
}
|
|
1834
|
+
renderDocsList(filtered);
|
|
1835
|
+
}
|
|
1836
|
+
|
|
1837
|
+
/** 选中并加载文档内容 */
|
|
1838
|
+
function selectDoc(docKey) {
|
|
1839
|
+
currentDocKey = docKey;
|
|
1840
|
+
|
|
1841
|
+
// 更新左侧选中状态
|
|
1842
|
+
var items = document.querySelectorAll('.docs-item');
|
|
1843
|
+
for (var i = 0; i < items.length; i++) {
|
|
1844
|
+
items[i].classList.remove('active');
|
|
1845
|
+
if (items[i].getAttribute('data-key') === docKey) {
|
|
1846
|
+
items[i].classList.add('active');
|
|
1847
|
+
}
|
|
1848
|
+
}
|
|
1849
|
+
|
|
1850
|
+
// 解析 key
|
|
1851
|
+
var parts = docKey.split('|');
|
|
1852
|
+
var section = parts[0];
|
|
1853
|
+
var subSection = parts[1] || null;
|
|
1854
|
+
|
|
1855
|
+
// 显示内容区,隐藏空状态
|
|
1856
|
+
document.getElementById('docsEmptyState').style.display = 'none';
|
|
1857
|
+
var contentView = document.getElementById('docsContentView');
|
|
1858
|
+
contentView.style.display = 'flex';
|
|
1859
|
+
|
|
1860
|
+
// 显示加载状态
|
|
1861
|
+
document.getElementById('docsContentTitle').textContent = '加载中...';
|
|
1862
|
+
document.getElementById('docsContentMeta').innerHTML = '';
|
|
1863
|
+
document.getElementById('docsContentInner').innerHTML = '<div style="text-align:center;padding:40px;color:#6b7280;"><div class="spinner" style="margin:0 auto 12px;width:24px;height:24px;border-width:3px;"></div></div>';
|
|
1864
|
+
|
|
1865
|
+
// 请求文档内容
|
|
1866
|
+
var url = '/api/doc?section=' + encodeURIComponent(section);
|
|
1867
|
+
if (subSection) url += '&subSection=' + encodeURIComponent(subSection);
|
|
1868
|
+
|
|
1869
|
+
fetch(url).then(function(r) {
|
|
1870
|
+
if (!r.ok) throw new Error('HTTP ' + r.status);
|
|
1871
|
+
return r.json();
|
|
1872
|
+
}).then(function(doc) {
|
|
1873
|
+
renderDocContent(doc, section, subSection);
|
|
1874
|
+
}).catch(function(err) {
|
|
1875
|
+
document.getElementById('docsContentTitle').textContent = '加载失败';
|
|
1876
|
+
document.getElementById('docsContentInner').innerHTML = '<div style="text-align:center;padding:40px;color:#f87171;">加载失败: ' + escHtml(err.message) + '</div>';
|
|
1877
|
+
});
|
|
1878
|
+
}
|
|
1879
|
+
|
|
1880
|
+
/** 渲染文档内容到右侧面板 */
|
|
1881
|
+
function renderDocContent(doc, section, subSection) {
|
|
1882
|
+
var secName = SECTION_NAMES[section] || section;
|
|
1883
|
+
|
|
1884
|
+
// 标题
|
|
1885
|
+
document.getElementById('docsContentTitle').textContent = doc.title || secName;
|
|
1886
|
+
|
|
1887
|
+
// 元信息标签
|
|
1888
|
+
var metaHtml = '<span class="docs-content-tag section">' + secName + '</span>';
|
|
1889
|
+
if (subSection) {
|
|
1890
|
+
metaHtml += '<span class="docs-content-tag section">' + escHtml(subSection) + '</span>';
|
|
1891
|
+
}
|
|
1892
|
+
if (doc.version) {
|
|
1893
|
+
metaHtml += '<span class="docs-content-tag version">v' + escHtml(doc.version) + '</span>';
|
|
1894
|
+
}
|
|
1895
|
+
if (doc.updatedAt) {
|
|
1896
|
+
metaHtml += '<span class="docs-content-tag">' + fmtTime(doc.updatedAt) + '</span>';
|
|
1897
|
+
}
|
|
1898
|
+
document.getElementById('docsContentMeta').innerHTML = metaHtml;
|
|
1899
|
+
|
|
1900
|
+
// Markdown 内容
|
|
1901
|
+
var contentHtml = '';
|
|
1902
|
+
if (doc.content) {
|
|
1903
|
+
contentHtml = renderMarkdown(doc.content);
|
|
1904
|
+
} else {
|
|
1905
|
+
contentHtml = '<div style="text-align:center;padding:40px;color:#6b7280;">文档内容为空</div>';
|
|
1906
|
+
}
|
|
1907
|
+
|
|
1908
|
+
// 关联任务
|
|
1909
|
+
var relatedTasks = doc.relatedTasks || [];
|
|
1910
|
+
if (relatedTasks.length > 0) {
|
|
1911
|
+
contentHtml += '<div class="docs-related">';
|
|
1912
|
+
contentHtml += '<div class="docs-related-title">🔗 关联任务 (' + relatedTasks.length + ')</div>';
|
|
1913
|
+
for (var i = 0; i < relatedTasks.length; i++) {
|
|
1914
|
+
var t = relatedTasks[i];
|
|
1915
|
+
var tStatus = t.status || 'pending';
|
|
1916
|
+
var tIcon = tStatus === 'completed' ? '✓' : tStatus === 'in_progress' ? '▶' : '○';
|
|
1917
|
+
var iconBg = tStatus === 'completed' ? '#064e3b' : tStatus === 'in_progress' ? '#1e3a5f' : '#374151';
|
|
1918
|
+
var iconColor = tStatus === 'completed' ? '#6ee7b7' : tStatus === 'in_progress' ? '#93c5fd' : '#6b7280';
|
|
1919
|
+
contentHtml += '<div class="docs-related-item">';
|
|
1920
|
+
contentHtml += '<span class="rel-icon" style="background:' + iconBg + ';color:' + iconColor + ';">' + tIcon + '</span>';
|
|
1921
|
+
contentHtml += '<span style="flex:1;">' + escHtml(t.title) + '</span>';
|
|
1922
|
+
contentHtml += '<span style="font-size:10px;color:#6b7280;font-family:monospace;">' + escHtml(t.taskId) + '</span>';
|
|
1923
|
+
if (t.priority) {
|
|
1924
|
+
contentHtml += '<span class="status-badge priority-' + t.priority + '" style="font-size:10px;">' + t.priority + '</span>';
|
|
1925
|
+
}
|
|
1926
|
+
contentHtml += '</div>';
|
|
1927
|
+
}
|
|
1928
|
+
contentHtml += '</div>';
|
|
1929
|
+
}
|
|
1930
|
+
|
|
1931
|
+
document.getElementById('docsContentInner').innerHTML = contentHtml;
|
|
1499
1932
|
}
|
|
1500
1933
|
|
|
1501
1934
|
// ========== Stats Dashboard ==========
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"template.js","sourceRoot":"","sources":["../../src/visualize/template.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;AAEH,
|
|
1
|
+
{"version":3,"file":"template.js","sourceRoot":"","sources":["../../src/visualize/template.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;AAEH,oDAimEC;AAjmED,SAAgB,oBAAoB,CAAC,WAAmB;IACtD,OAAO;;;;;qBAKY,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iFAgZiD,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2BA6FjE,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA6mD9B,CAAC;AACT,CAAC"}
|