aifastdb-devplan 1.6.1 → 1.6.2

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.
Files changed (89) hide show
  1. package/dist/dev-plan-document-store.d.ts +13 -1
  2. package/dist/dev-plan-document-store.d.ts.map +1 -1
  3. package/dist/dev-plan-document-store.js +119 -0
  4. package/dist/dev-plan-document-store.js.map +1 -1
  5. package/dist/dev-plan-factory.d.ts.map +1 -1
  6. package/dist/dev-plan-factory.js +2 -1
  7. package/dist/dev-plan-factory.js.map +1 -1
  8. package/dist/dev-plan-graph-store.d.ts +64 -1
  9. package/dist/dev-plan-graph-store.d.ts.map +1 -1
  10. package/dist/dev-plan-graph-store.js +364 -2
  11. package/dist/dev-plan-graph-store.js.map +1 -1
  12. package/dist/dev-plan-interface.d.ts +24 -1
  13. package/dist/dev-plan-interface.d.ts.map +1 -1
  14. package/dist/dev-plan-migrate.d.ts +1 -0
  15. package/dist/dev-plan-migrate.d.ts.map +1 -1
  16. package/dist/dev-plan-migrate.js +28 -2
  17. package/dist/dev-plan-migrate.js.map +1 -1
  18. package/dist/index.d.ts +1 -1
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js.map +1 -1
  21. package/dist/mcp-server/index.js +119 -0
  22. package/dist/mcp-server/index.js.map +1 -1
  23. package/dist/types.d.ts +88 -1
  24. package/dist/types.d.ts.map +1 -1
  25. package/dist/types.js.map +1 -1
  26. package/dist/visualize/graph-canvas/api-compat.d.ts.map +1 -1
  27. package/dist/visualize/graph-canvas/api-compat.js +22 -12
  28. package/dist/visualize/graph-canvas/api-compat.js.map +1 -1
  29. package/dist/visualize/graph-canvas/core.d.ts.map +1 -1
  30. package/dist/visualize/graph-canvas/core.js +296 -4
  31. package/dist/visualize/graph-canvas/core.js.map +1 -1
  32. package/dist/visualize/graph-canvas/interaction.d.ts.map +1 -1
  33. package/dist/visualize/graph-canvas/interaction.js +11 -0
  34. package/dist/visualize/graph-canvas/interaction.js.map +1 -1
  35. package/dist/visualize/graph-canvas/layout-worker.d.ts.map +1 -1
  36. package/dist/visualize/graph-canvas/layout-worker.js +45 -9
  37. package/dist/visualize/graph-canvas/layout-worker.js.map +1 -1
  38. package/dist/visualize/graph-canvas/renderer.d.ts.map +1 -1
  39. package/dist/visualize/graph-canvas/renderer.js +164 -33
  40. package/dist/visualize/graph-canvas/renderer.js.map +1 -1
  41. package/dist/visualize/graph-canvas/styles.d.ts.map +1 -1
  42. package/dist/visualize/graph-canvas/styles.js +136 -121
  43. package/dist/visualize/graph-canvas/styles.js.map +1 -1
  44. package/dist/visualize/graph-canvas/viewport.d.ts.map +1 -1
  45. package/dist/visualize/graph-canvas/viewport.js +10 -0
  46. package/dist/visualize/graph-canvas/viewport.js.map +1 -1
  47. package/dist/visualize/server.js +149 -32
  48. package/dist/visualize/server.js.map +1 -1
  49. package/dist/visualize/template-core.d.ts +9 -0
  50. package/dist/visualize/template-core.d.ts.map +1 -0
  51. package/dist/visualize/template-core.js +714 -0
  52. package/dist/visualize/template-core.js.map +1 -0
  53. package/dist/visualize/template-data-loading.d.ts +7 -0
  54. package/dist/visualize/template-data-loading.d.ts.map +1 -0
  55. package/dist/visualize/template-data-loading.js +677 -0
  56. package/dist/visualize/template-data-loading.js.map +1 -0
  57. package/dist/visualize/template-detail-panel.d.ts +14 -0
  58. package/dist/visualize/template-detail-panel.d.ts.map +1 -0
  59. package/dist/visualize/template-detail-panel.js +553 -0
  60. package/dist/visualize/template-detail-panel.js.map +1 -0
  61. package/dist/visualize/template-graph-3d.d.ts +7 -0
  62. package/dist/visualize/template-graph-3d.d.ts.map +1 -0
  63. package/dist/visualize/template-graph-3d.js +1112 -0
  64. package/dist/visualize/template-graph-3d.js.map +1 -0
  65. package/dist/visualize/template-graph-vis.d.ts +8 -0
  66. package/dist/visualize/template-graph-vis.d.ts.map +1 -0
  67. package/dist/visualize/template-graph-vis.js +1204 -0
  68. package/dist/visualize/template-graph-vis.js.map +1 -0
  69. package/dist/visualize/template-html.d.ts +9 -0
  70. package/dist/visualize/template-html.d.ts.map +1 -0
  71. package/dist/visualize/template-html.js +484 -0
  72. package/dist/visualize/template-html.js.map +1 -0
  73. package/dist/visualize/template-pages.d.ts +7 -0
  74. package/dist/visualize/template-pages.d.ts.map +1 -0
  75. package/dist/visualize/template-pages.js +806 -0
  76. package/dist/visualize/template-pages.js.map +1 -0
  77. package/dist/visualize/template-stats-modal.d.ts +7 -0
  78. package/dist/visualize/template-stats-modal.d.ts.map +1 -0
  79. package/dist/visualize/template-stats-modal.js +406 -0
  80. package/dist/visualize/template-stats-modal.js.map +1 -0
  81. package/dist/visualize/template-styles.d.ts +9 -0
  82. package/dist/visualize/template-styles.d.ts.map +1 -0
  83. package/dist/visualize/template-styles.js +487 -0
  84. package/dist/visualize/template-styles.js.map +1 -0
  85. package/dist/visualize/template.d.ts +14 -3
  86. package/dist/visualize/template.d.ts.map +1 -1
  87. package/dist/visualize/template.js +38 -3475
  88. package/dist/visualize/template.js.map +1 -1
  89. package/package.json +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template-pages.js","sourceRoot":"","sources":["../../src/visualize/template-pages.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;AAEH,wCA4xBC;AA5xBD,SAAgB,cAAc;IAC5B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0xBR,CAAC;AACF,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * DevPlan 图可视化 — 统计弹层与刷新模块
3
+ *
4
+ * 包含: 统计弹层 (打开/关闭/渲染)、手动刷新 (F5/按钮)。
5
+ */
6
+ export declare function getStatsModalScript(): string;
7
+ //# sourceMappingURL=template-stats-modal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template-stats-modal.d.ts","sourceRoot":"","sources":["../../src/visualize/template-stats-modal.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,wBAAgB,mBAAmB,IAAI,MAAM,CA4Y5C"}
@@ -0,0 +1,406 @@
1
+ "use strict";
2
+ /**
3
+ * DevPlan 图可视化 — 统计弹层与刷新模块
4
+ *
5
+ * 包含: 统计弹层 (打开/关闭/渲染)、手动刷新 (F5/按钮)。
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.getStatsModalScript = getStatsModalScript;
9
+ function getStatsModalScript() {
10
+ return `
11
+ // ========== Stats Modal ==========
12
+ function showStatsModal(nodeType) {
13
+ // 文档类型使用全局文档列表组件
14
+ if (nodeType === 'document') {
15
+ showDocModal();
16
+ return;
17
+ }
18
+
19
+ var titleMap = { 'module': '功能模块', 'main-task': '主任务', 'sub-task': '子任务' };
20
+ var iconMap = { 'module': '◆', 'main-task': '●', 'sub-task': '·' };
21
+ var items = [];
22
+ for (var i = 0; i < allNodes.length; i++) {
23
+ if (allNodes[i].type === nodeType) items.push(allNodes[i]);
24
+ }
25
+ // 排序:进行中 > 待开始 > 已完成 > 已取消
26
+ var statusOrder = { in_progress: 0, pending: 1, completed: 2, cancelled: 3, active: 1 };
27
+ items.sort(function(a, b) {
28
+ var sa = (a.properties || {}).status || 'pending';
29
+ var sb = (b.properties || {}).status || 'pending';
30
+ return (statusOrder[sa] !== undefined ? statusOrder[sa] : 5) - (statusOrder[sb] !== undefined ? statusOrder[sb] : 5);
31
+ });
32
+
33
+ document.getElementById('statsModalTitle').textContent = titleMap[nodeType] || nodeType;
34
+ document.getElementById('statsModalCount').textContent = '(' + items.length + ')';
35
+
36
+ var html = '';
37
+ for (var i = 0; i < items.length; i++) {
38
+ var n = items[i];
39
+ var p = n.properties || {};
40
+ var st = p.status || (nodeType === 'module' ? 'active' : 'pending');
41
+ var icon = iconMap[nodeType] || '●';
42
+ html += '<div class="stats-modal-item" onclick="statsModalGoToNode(\\x27' + n.id + '\\x27)">';
43
+ html += '<span class="stats-modal-item-icon">' + icon + '</span>';
44
+ html += '<span class="stats-modal-item-name" title="' + escHtml(n.label) + '">' + escHtml(n.label) + '</span>';
45
+ if (nodeType === 'main-task') {
46
+ var subCount = 0; var subDone = 0;
47
+ for (var j = 0; j < allNodes.length; j++) {
48
+ if (allNodes[j].type === 'sub-task' && (allNodes[j].properties || {}).parentTaskId === p.taskId) {
49
+ subCount++;
50
+ if ((allNodes[j].properties || {}).status === 'completed') subDone++;
51
+ }
52
+ }
53
+ if (subCount > 0) {
54
+ html += '<span class="stats-modal-item-sub">' + subDone + '/' + subCount + '</span>';
55
+ }
56
+ }
57
+ if (nodeType === 'module' && p.mainTaskCount !== undefined) {
58
+ html += '<span class="stats-modal-item-sub">' + p.mainTaskCount + ' 任务</span>';
59
+ }
60
+ html += '<span class="stats-modal-item-badge ' + st + '">' + statusText(st) + '</span>';
61
+ html += '</div>';
62
+ }
63
+ if (items.length === 0) {
64
+ html = '<div style="text-align:center;padding:40px;color:#6b7280;">暂无数据</div>';
65
+ }
66
+ document.getElementById('statsModalBody').innerHTML = html;
67
+ // 根据侧边栏状态调整弹层位置
68
+ updateStatsModalPosition();
69
+ document.getElementById('statsModalOverlay').classList.add('active');
70
+ }
71
+
72
+ // ========== 全局文档列表弹层 (Phase-18: 与文档浏览页共用同一组件) ==========
73
+
74
+ /** 显示文档弹层 — 复用文档浏览页的 UI 样式和搜索功能 */
75
+ function showDocModal() {
76
+ document.getElementById('statsModalTitle').textContent = '📄 文档库';
77
+ document.getElementById('statsModalCount').textContent = '';
78
+
79
+ // 在 modal body 中渲染搜索栏 + 文档列表容器(复用文档浏览页 CSS 类名)
80
+ var bodyHtml = '';
81
+ // 置顶搜索栏
82
+ bodyHtml += '<div class="doc-modal-search-sticky">';
83
+ bodyHtml += '<div class="docs-search-wrap">';
84
+ bodyHtml += '<input type="text" class="docs-search" id="docModalSearch" placeholder="搜索文档标题..." oninput="filterDocModal()">';
85
+ bodyHtml += '<button class="docs-search-clear" id="docModalSearchClear" onclick="clearDocModalSearch()" title="清空搜索">✕</button>';
86
+ bodyHtml += '</div></div>';
87
+ // 文档分组列表容器
88
+ bodyHtml += '<div id="docModalGroupList" style="padding:8px 0;">';
89
+ bodyHtml += '<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>';
90
+ bodyHtml += '</div>';
91
+
92
+ document.getElementById('statsModalBody').innerHTML = bodyHtml;
93
+ updateStatsModalPosition();
94
+ document.getElementById('statsModalOverlay').classList.add('active');
95
+
96
+ // 加载文档数据(全局共享,已加载则直接使用缓存)
97
+ loadDocsData(function(data, err) {
98
+ if (err) {
99
+ var list = document.getElementById('docModalGroupList');
100
+ if (list) list.innerHTML = '<div style="text-align:center;padding:40px;color:#f87171;font-size:12px;">加载失败: ' + err.message + '</div>';
101
+ return;
102
+ }
103
+ document.getElementById('statsModalCount').textContent = '(' + docsData.length + ')';
104
+ renderDocsList(docsData, 'docModalGroupList', 'globalDocSelect');
105
+ });
106
+ }
107
+
108
+ /** 文档弹层搜索过滤 */
109
+ function filterDocModal() {
110
+ toggleSearchClear('docModalSearch', 'docModalSearchClear');
111
+ filterDocs('docModalSearch', 'docModalGroupList', 'globalDocSelect');
112
+ }
113
+
114
+ /** 文档弹层清空搜索 */
115
+ function clearDocModalSearch() {
116
+ clearDocsSearch('docModalSearch', 'docModalSearchClear', 'docModalGroupList', 'globalDocSelect');
117
+ }
118
+
119
+ /** 从图谱页文档弹层选中文档:关闭弹层 → 跳转文档浏览页 → 打开该文档 */
120
+ function globalDocSelect(docKey) {
121
+ closeStatsModal();
122
+ navTo('docs');
123
+ // 确保文档浏览页数据已加载后再选中对应文档
124
+ loadDocsData(function() {
125
+ renderDocsList(docsData); // 确保文档浏览页左侧列表已渲染
126
+ setTimeout(function() { selectDoc(docKey); }, 50);
127
+ });
128
+ }
129
+
130
+ /** 显示 Prompt 列表弹层(异步从 /api/prompts 加载) */
131
+ function showPromptModal() {
132
+ document.getElementById('statsModalTitle').textContent = '💬 Prompt 日志';
133
+ document.getElementById('statsModalCount').textContent = '(加载中...)';
134
+ document.getElementById('statsModalBody').innerHTML = '<div style="text-align:center;padding:40px;color:#6b7280;"><div class="spinner" style="margin:0 auto 12px;width:24px;height:24px;border:2px solid #374151;border-top-color:#818cf8;border-radius:50%;animation:spin 0.6s linear infinite;"></div>加载 Prompt...</div>';
135
+ updateStatsModalPosition();
136
+ document.getElementById('statsModalOverlay').classList.add('active');
137
+
138
+ fetch('/api/prompts').then(function(r) { return r.json(); }).then(function(data) {
139
+ var prompts = data.prompts || [];
140
+ document.getElementById('statsModalCount').textContent = '(' + prompts.length + ')';
141
+
142
+ if (prompts.length === 0) {
143
+ document.getElementById('statsModalBody').innerHTML = '<div style="text-align:center;padding:40px;color:#6b7280;">暂无 Prompt 记录</div>';
144
+ return;
145
+ }
146
+
147
+ // 按日期分组(最新在前)
148
+ var grouped = {};
149
+ var dateOrder = [];
150
+ for (var i = 0; i < prompts.length; i++) {
151
+ var p = prompts[i];
152
+ var date = p.createdAt ? new Date(p.createdAt).toISOString().slice(0, 10) : 'unknown';
153
+ if (!grouped[date]) { grouped[date] = []; dateOrder.push(date); }
154
+ grouped[date].push(p);
155
+ }
156
+
157
+ var html = '';
158
+ for (var di = 0; di < dateOrder.length; di++) {
159
+ var date = dateOrder[di];
160
+ var items = grouped[date];
161
+ html += '<div style="margin-bottom:4px;">';
162
+ html += '<div style="padding:8px 20px;font-size:11px;font-weight:700;color:#9ca3af;text-transform:uppercase;letter-spacing:0.05em;display:flex;align-items:center;gap:6px;">';
163
+ html += '<span>📅 ' + escHtml(date) + '</span>';
164
+ html += '<span style="margin-left:auto;font-size:10px;color:#4b5563;">' + items.length + '</span>';
165
+ html += '</div>';
166
+
167
+ for (var ii = 0; ii < items.length; ii++) {
168
+ var p = items[ii];
169
+ var timeStr = p.createdAt ? new Date(p.createdAt).toLocaleTimeString() : '';
170
+ var tagHtml = '';
171
+ if (p.tags && p.tags.length > 0) {
172
+ for (var ti = 0; ti < Math.min(p.tags.length, 3); ti++) {
173
+ tagHtml += '<span style="font-size:10px;padding:1px 5px;border-radius:3px;background:rgba(139,92,246,0.15);color:#a78bfa;border:1px solid rgba(139,92,246,0.25);white-space:nowrap;">' + escHtml(p.tags[ti]) + '</span>';
174
+ }
175
+ if (p.tags.length > 3) tagHtml += '<span style="font-size:10px;color:#6b7280;">+' + (p.tags.length - 3) + '</span>';
176
+ }
177
+
178
+ // 用户原始输入(截取预览)
179
+ var rawContent = (p.content || '').trim();
180
+ var contentPreview = rawContent.length > 120 ? rawContent.substring(0, 117) + '...' : rawContent;
181
+ // AI 理解
182
+ var aiText = (p.aiInterpretation || '').trim();
183
+ var aiPreview = aiText.length > 120 ? aiText.substring(0, 117) + '...' : aiText;
184
+ // 摘要
185
+ var summaryText = (p.summary || '').trim();
186
+
187
+ // 唯一展开 ID
188
+ var expandId = 'prompt-expand-' + date + '-' + ii;
189
+
190
+ html += '<div class="stats-modal-item" style="flex-direction:column;align-items:flex-start;gap:4px;padding:10px 20px;cursor:pointer;" onclick="togglePromptExpand(\\'' + expandId + '\\')">';
191
+
192
+ // 第一行:序号 + 摘要/预览 + 时间
193
+ html += '<div style="display:flex;align-items:center;gap:8px;width:100%;">';
194
+ html += '<span style="font-size:12px;font-weight:700;color:#ec4899;flex-shrink:0;">#' + (p.promptIndex || (ii + 1)) + '</span>';
195
+ html += '<span class="stats-modal-item-name" title="' + escHtml(summaryText || contentPreview) + '" style="font-size:13px;">' + escHtml(summaryText || contentPreview) + '</span>';
196
+ html += '<span style="font-size:10px;color:#6b7280;flex-shrink:0;margin-left:auto;white-space:nowrap;">' + timeStr + '</span>';
197
+ html += '</div>';
198
+
199
+ // 标签行
200
+ if (p.relatedTaskId || tagHtml) {
201
+ html += '<div style="display:flex;align-items:center;gap:6px;padding-left:28px;flex-wrap:wrap;">';
202
+ if (p.relatedTaskId) {
203
+ html += '<span style="font-size:10px;padding:1px 5px;border-radius:3px;background:rgba(16,185,129,0.15);color:#34d399;border:1px solid rgba(16,185,129,0.25);white-space:nowrap;">📌 ' + escHtml(p.relatedTaskId) + '</span>';
204
+ }
205
+ html += tagHtml;
206
+ html += '</div>';
207
+ }
208
+
209
+ // 展开区域(默认隐藏)— 用户原始输入 + AI 理解
210
+ html += '<div id="' + expandId + '" style="display:none;width:100%;padding-top:6px;border-top:1px solid rgba(75,85,99,0.3);margin-top:4px;">';
211
+
212
+ // 用户原始输入
213
+ html += '<div style="margin-bottom:8px;">';
214
+ html += '<div style="font-size:10px;font-weight:600;color:#9ca3af;margin-bottom:3px;display:flex;align-items:center;gap:4px;">💬 用户原始输入</div>';
215
+ html += '<div style="font-size:12px;color:#d1d5db;background:rgba(31,41,55,0.5);padding:8px 10px;border-radius:6px;border:1px solid rgba(75,85,99,0.3);white-space:pre-wrap;word-break:break-word;max-height:200px;overflow-y:auto;line-height:1.5;">' + escHtml(rawContent || '(未记录)') + '</div>';
216
+ html += '</div>';
217
+
218
+ // AI 理解
219
+ if (aiText) {
220
+ html += '<div style="margin-bottom:4px;">';
221
+ html += '<div style="font-size:10px;font-weight:600;color:#9ca3af;margin-bottom:3px;display:flex;align-items:center;gap:4px;">🤖 AI 理解</div>';
222
+ html += '<div style="font-size:12px;color:#a5b4fc;background:rgba(67,56,202,0.12);padding:8px 10px;border-radius:6px;border:1px solid rgba(99,102,241,0.2);white-space:pre-wrap;word-break:break-word;max-height:200px;overflow-y:auto;line-height:1.5;">' + escHtml(aiText) + '</div>';
223
+ html += '</div>';
224
+ }
225
+
226
+ html += '</div>'; // end expand
227
+ html += '</div>'; // end item
228
+ }
229
+ html += '</div>';
230
+ }
231
+ document.getElementById('statsModalBody').innerHTML = html;
232
+ }).catch(function(err) {
233
+ document.getElementById('statsModalBody').innerHTML = '<div style="text-align:center;padding:40px;color:#f87171;">加载失败: ' + escHtml(err.message) + '</div>';
234
+ });
235
+ }
236
+
237
+ /** 切换 Prompt 展开/折叠 */
238
+ function togglePromptExpand(expandId) {
239
+ var el = document.getElementById(expandId);
240
+ if (!el) return;
241
+ if (el.style.display === 'none') {
242
+ el.style.display = 'block';
243
+ } else {
244
+ el.style.display = 'none';
245
+ }
246
+ }
247
+
248
+ function closeStatsModal() {
249
+ document.getElementById('statsModalOverlay').classList.remove('active');
250
+ }
251
+
252
+ function statsModalGoToNode(nodeId) {
253
+ // 兼容所有引擎: 优先 nodesDataSet,fallback 到 getNodeById (3D 等引擎)
254
+ var nodeExists = (nodesDataSet && nodesDataSet.get(nodeId)) || getNodeById(nodeId);
255
+ if (network && nodeExists) {
256
+ if (typeof network.selectNodes === 'function') {
257
+ network.selectNodes([nodeId]);
258
+ }
259
+ highlightConnectedEdges(nodeId);
260
+ // 3D 模式下不触发摄像机聚焦 — 摄像机效果仅在画布双击节点时激发
261
+ if (!USE_3D && typeof network.focus === 'function') {
262
+ network.focus(nodeId, { scale: 1.2, animation: { duration: 400, easingFunction: 'easeInOutQuad' } });
263
+ }
264
+ panelHistory = [];
265
+ currentPanelNodeId = null;
266
+ showPanel(nodeId);
267
+ }
268
+ }
269
+
270
+
271
+ // ========== Manual Refresh ==========
272
+ var _refreshing = false;
273
+
274
+ /** 手动刷新:点击刷新按钮或按 F5 时触发(带旋转动画反馈) */
275
+ function manualRefresh() {
276
+ if (_refreshing) return;
277
+ _refreshing = true;
278
+ var btn = document.getElementById('legendRefreshBtn');
279
+ if (btn) btn.classList.add('refreshing');
280
+ log('手动刷新: 获取最新数据...', true);
281
+ silentRefresh(function() {
282
+ _refreshing = false;
283
+ if (btn) btn.classList.remove('refreshing');
284
+ });
285
+ }
286
+
287
+ /** 静默刷新:只更新数据,不重建图谱(避免布局跳动)。onDone 回调在请求完成后触发。 */
288
+ function silentRefresh(onDone) {
289
+ // Phase-10: If in tiered mode, refresh only what's loaded
290
+ var graphApiUrl;
291
+ if (!USE_3D && tieredLoadState.l0l1Loaded && !tieredLoadState.l2Loaded) {
292
+ // Only refresh L0+L1 nodes (tiered mode — not all loaded yet)
293
+ var loadedTypes = TIER_L0L1_TYPES.slice();
294
+ // Add types for expanded phases
295
+ if (Object.keys(tieredLoadState.expandedPhases).length > 0) {
296
+ loadedTypes = loadedTypes.concat(TIER_L2_TYPES).concat(TIER_L3_TYPES);
297
+ }
298
+ graphApiUrl = '/api/graph/paged?offset=0&limit=5000&entityTypes=' + loadedTypes.join(',');
299
+ } else {
300
+ graphApiUrl = '/api/graph?includeNodeDegree=' + (INCLUDE_NODE_DEGREE ? 'true' : 'false') +
301
+ '&enableBackendDegreeFallback=' + (ENABLE_BACKEND_DEGREE_FALLBACK ? 'true' : 'false');
302
+ }
303
+ Promise.all([
304
+ fetch(graphApiUrl).then(function(r) { return r.json(); }),
305
+ fetch('/api/progress').then(function(r) { return r.json(); })
306
+ ]).then(function(results) {
307
+ var graphRes = results[0];
308
+ var progressRes = results[1];
309
+ var newNodes = graphRes.nodes || [];
310
+ var newEdges = graphRes.edges || [];
311
+
312
+ // 检查数据是否有变化(通过节点数量和状态快照比较)
313
+ var changed = false;
314
+ if (newNodes.length !== allNodes.length || newEdges.length !== allEdges.length) {
315
+ changed = true;
316
+ } else {
317
+ // 比较每个节点的状态
318
+ var oldStatusMap = {};
319
+ for (var i = 0; i < allNodes.length; i++) {
320
+ var n = allNodes[i];
321
+ oldStatusMap[n.id] = (n.properties || {}).status || '';
322
+ }
323
+ for (var i = 0; i < newNodes.length; i++) {
324
+ var n = newNodes[i];
325
+ var oldStatus = oldStatusMap[n.id];
326
+ var newStatus = (n.properties || {}).status || '';
327
+ if (oldStatus !== newStatus) {
328
+ changed = true;
329
+ break;
330
+ }
331
+ }
332
+ }
333
+
334
+ if (changed) {
335
+ log('检测到数据变化, 更新图谱...', true);
336
+ allNodes = newNodes;
337
+ allEdges = newEdges;
338
+ renderStats(progressRes, graphRes);
339
+ // 仅更新节点样式而非重建整个图谱,以保持当前布局
340
+ if (nodesDataSet && network) {
341
+ updateNodeStyles();
342
+ } else {
343
+ renderGraph();
344
+ }
345
+ } else {
346
+ log('数据无变化 (' + new Date().toLocaleTimeString() + ')', true);
347
+ }
348
+ if (typeof onDone === 'function') onDone();
349
+ }).catch(function(err) {
350
+ log('刷新失败: ' + err.message, false);
351
+ if (typeof onDone === 'function') onDone();
352
+ });
353
+ }
354
+
355
+ /** 增量更新节点样式(不重建布局) */
356
+ function updateNodeStyles() {
357
+ try {
358
+ // 构建当前可见节点的 ID 和新数据映射
359
+ var newNodeMap = {};
360
+ for (var i = 0; i < allNodes.length; i++) {
361
+ newNodeMap[allNodes[i].id] = allNodes[i];
362
+ }
363
+
364
+ // 更新已有节点的样式和大小
365
+ var currentIds = nodesDataSet.getIds();
366
+ for (var i = 0; i < currentIds.length; i++) {
367
+ var id = currentIds[i];
368
+ var newData = newNodeMap[id];
369
+ if (newData && !hiddenTypes[newData.type]) {
370
+ var deg = getNodeDegree(newData);
371
+ var s = nodeStyle(newData, deg);
372
+ nodesDataSet.update({
373
+ id: id,
374
+ label: newData.label,
375
+ size: s.size,
376
+ color: s.color,
377
+ font: s.font,
378
+ _props: newData.properties || {}
379
+ });
380
+ }
381
+ }
382
+
383
+ // 处理新增/删除的节点 — 如果有结构变化,完整重建
384
+ var visibleNewNodes = allNodes.filter(function(n) { return !hiddenTypes[n.type]; });
385
+ if (visibleNewNodes.length !== currentIds.length) {
386
+ renderGraph();
387
+ }
388
+
389
+ // 增量更新后重新检查呼吸灯
390
+ var updatedInProg = getInProgressMainTaskIds();
391
+ if (updatedInProg.length > 0 && !breathAnimId) {
392
+ startBreathAnimation();
393
+ } else if (updatedInProg.length === 0 && breathAnimId) {
394
+ stopBreathAnimation();
395
+ }
396
+
397
+ log('节点样式已更新 (' + new Date().toLocaleTimeString() + ')', true);
398
+ } catch (err) {
399
+ log('增量更新失败, 完整重建: ' + err.message, false);
400
+ renderGraph();
401
+ }
402
+ }
403
+
404
+ `;
405
+ }
406
+ //# sourceMappingURL=template-stats-modal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template-stats-modal.js","sourceRoot":"","sources":["../../src/visualize/template-stats-modal.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;AAEH,kDA4YC;AA5YD,SAAgB,mBAAmB;IACjC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0YR,CAAC;AACF,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * DevPlan 图可视化 — CSS 样式模块
3
+ *
4
+ * 从 template.ts 拆分出的全部 CSS 样式定义。
5
+ * 包含: 布局、侧边栏、头部、统计栏、图谱容器、详情面板、图例、
6
+ * 设置页、统计仪表盘、文档浏览、RAG 聊天、统计弹层等样式。
7
+ */
8
+ export declare function getStyles(): string;
9
+ //# sourceMappingURL=template-styles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template-styles.d.ts","sourceRoot":"","sources":["../../src/visualize/template-styles.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,wBAAgB,SAAS,IAAI,MAAM,CA2dlC"}