pdd-skills 3.0.0

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 (261) hide show
  1. package/README.md +1478 -0
  2. package/bin/pdd.js +354 -0
  3. package/config/bpmn-rules.yaml +166 -0
  4. package/config/checkstyle.xml +105 -0
  5. package/config/eslint.config.js +48 -0
  6. package/config/pmd.xml +91 -0
  7. package/config/prd-rules.yaml +113 -0
  8. package/config/ruff.toml +45 -0
  9. package/config/sqlfluff.cfg +82 -0
  10. package/hooks/hook-executor.js +332 -0
  11. package/index.js +43 -0
  12. package/lib/api-routes.js +750 -0
  13. package/lib/api-server.js +408 -0
  14. package/lib/cache/cache-config.js +209 -0
  15. package/lib/cache/system-cache.js +852 -0
  16. package/lib/config-manager.js +373 -0
  17. package/lib/generate.js +528 -0
  18. package/lib/grpc/grpc-routes.js +1134 -0
  19. package/lib/grpc/grpc-server.js +912 -0
  20. package/lib/grpc/proto-definitions.js +1033 -0
  21. package/lib/init.js +172 -0
  22. package/lib/iteration/auto-fixer.js +1025 -0
  23. package/lib/iteration/auto-reviewer.js +923 -0
  24. package/lib/iteration/controller.js +577 -0
  25. package/lib/list.js +130 -0
  26. package/lib/mcp-server.js +548 -0
  27. package/lib/openclaw/api-integration.js +535 -0
  28. package/lib/openclaw/cli-integration.js +567 -0
  29. package/lib/openclaw/data-sync.js +845 -0
  30. package/lib/openclaw/openclaw-adapter.js +783 -0
  31. package/lib/plugin/example-plugins/code-stats/index.js +332 -0
  32. package/lib/plugin/example-plugins/code-stats/plugin.json +1 -0
  33. package/lib/plugin/example-plugins/custom-linter/index.js +472 -0
  34. package/lib/plugin/example-plugins/custom-linter/plugin.json +1 -0
  35. package/lib/plugin/example-plugins/hello-world/index.js +86 -0
  36. package/lib/plugin/example-plugins/hello-world/plugin.json +1 -0
  37. package/lib/plugin/plugin-manager.js +655 -0
  38. package/lib/plugin/plugin-sdk.js +565 -0
  39. package/lib/plugin/sandbox.js +627 -0
  40. package/lib/quality/rules/maintainability.js +418 -0
  41. package/lib/quality/rules/performance.js +498 -0
  42. package/lib/quality/rules/readability.js +441 -0
  43. package/lib/quality/rules/robustness.js +504 -0
  44. package/lib/quality/rules/security.js +444 -0
  45. package/lib/quality/scorer.js +576 -0
  46. package/lib/report.js +669 -0
  47. package/lib/sdk-base.js +301 -0
  48. package/lib/sdk-js.js +446 -0
  49. package/lib/sdk-python/README.md +546 -0
  50. package/lib/sdk-python/examples/basic_usage.py +450 -0
  51. package/lib/sdk-python/pdd_sdk/__init__.py +180 -0
  52. package/lib/sdk-python/pdd_sdk/client.py +1170 -0
  53. package/lib/sdk-python/pdd_sdk/events.py +423 -0
  54. package/lib/sdk-python/pdd_sdk/exceptions.py +158 -0
  55. package/lib/sdk-python/pdd_sdk/models.py +518 -0
  56. package/lib/sdk-python/pdd_sdk/utils.py +759 -0
  57. package/lib/token/budget-alert.js +367 -0
  58. package/lib/token/budget-manager.js +485 -0
  59. package/lib/update.js +54 -0
  60. package/lib/utils/logger.js +88 -0
  61. package/lib/verify.js +741 -0
  62. package/lib/version.js +52 -0
  63. package/lib/vm/README.md +102 -0
  64. package/lib/vm/dashboard/api-routes.js +669 -0
  65. package/lib/vm/dashboard/server.js +391 -0
  66. package/lib/vm/dashboard/sse.js +358 -0
  67. package/lib/vm/dashboard/static/css/dashboard.css +1378 -0
  68. package/lib/vm/dashboard/static/index.html +118 -0
  69. package/lib/vm/dashboard/static/js/app.js +949 -0
  70. package/lib/vm/dashboard/static/js/charts.js +913 -0
  71. package/lib/vm/dashboard/static/js/kanban-view.js +1053 -0
  72. package/lib/vm/dashboard/static/js/pipeline-view.js +463 -0
  73. package/lib/vm/dashboard/static/js/quality-view.js +598 -0
  74. package/lib/vm/dashboard/static/js/system-view.js +1021 -0
  75. package/lib/vm/data-provider.js +1191 -0
  76. package/lib/vm/event-bus.js +402 -0
  77. package/lib/vm/hooks/extract-hook.js +307 -0
  78. package/lib/vm/hooks/generate-hook.js +374 -0
  79. package/lib/vm/hooks/hook-interface.js +458 -0
  80. package/lib/vm/hooks/report-hook.js +331 -0
  81. package/lib/vm/hooks/verify-hook.js +454 -0
  82. package/lib/vm/models.js +1003 -0
  83. package/lib/vm/reconciler.js +855 -0
  84. package/lib/vm/scanner.js +988 -0
  85. package/lib/vm/state-schema.js +955 -0
  86. package/lib/vm/state-store.js +733 -0
  87. package/lib/vm/tui/components/card.js +339 -0
  88. package/lib/vm/tui/components/progress-bar.js +368 -0
  89. package/lib/vm/tui/components/sparkline.js +327 -0
  90. package/lib/vm/tui/components/status-light.js +294 -0
  91. package/lib/vm/tui/components/table.js +370 -0
  92. package/lib/vm/tui/input.js +335 -0
  93. package/lib/vm/tui/renderer.js +548 -0
  94. package/lib/vm/tui/screens/kanban-screen.js +397 -0
  95. package/lib/vm/tui/screens/overview-screen.js +357 -0
  96. package/lib/vm/tui/screens/quality-screen.js +336 -0
  97. package/lib/vm/tui/screens/system-screen.js +379 -0
  98. package/lib/vm/tui/tui.js +805 -0
  99. package/package.json +1 -0
  100. package/scripts/cso-analyzer.js +198 -0
  101. package/scripts/eval-runner.js +359 -0
  102. package/scripts/i18n-checker.js +109 -0
  103. package/scripts/linter/activiti-linter.js +272 -0
  104. package/scripts/linter/prd-linter.js +162 -0
  105. package/scripts/linter/report-generator.js +207 -0
  106. package/scripts/linter/run-linters.js +285 -0
  107. package/scripts/linter/sql-linter.js +166 -0
  108. package/scripts/token-analyzer.js +162 -0
  109. package/scripts/vm-test.js +180 -0
  110. package/skills/core/official-doc-writer/LICENSE +21 -0
  111. package/skills/core/official-doc-writer/README.md +232 -0
  112. package/skills/core/official-doc-writer/SKILL.md +475 -0
  113. package/skills/core/official-doc-writer/_meta.json +1 -0
  114. package/skills/core/official-doc-writer/document_generator.py +580 -0
  115. package/skills/core/official-doc-writer/evals/default-evals.json +1 -0
  116. package/skills/core/official-doc-writer/examples.md +150 -0
  117. package/skills/core/official-doc-writer/fonts/FONTS_LIST.md +45 -0
  118. package/skills/core/official-doc-writer/fonts/README.md +141 -0
  119. package/skills/core/official-doc-writer/fonts/SIMFANG.TTF +0 -0
  120. package/skills/core/official-doc-writer/fonts/SIMHEI.TTF +0 -0
  121. package/skills/core/official-doc-writer/fonts/SIMKAI.TTF +0 -0
  122. package/skills/core/official-doc-writer/fonts/SIMSUN.TTC +0 -0
  123. package/skills/core/official-doc-writer/fonts//346/226/271/346/255/243/345/260/217/346/240/207/345/256/213GBK.TTF +0 -0
  124. package/skills/core/official-doc-writer/references/GBT_9704-2012_/345/205/232/346/224/277/346/234/272/345/205/263/345/205/254/346/226/207/346/240/274/345/274/217.md +422 -0
  125. package/skills/core/official-doc-writer/scripts/__pycache__/generate_official_doc.cpython-313.pyc +0 -0
  126. package/skills/core/official-doc-writer/scripts/dialog_manager.py +564 -0
  127. package/skills/core/official-doc-writer/scripts/generate_official_doc.py +252 -0
  128. package/skills/core/official-doc-writer/scripts/install_fonts.py +390 -0
  129. package/skills/core/official-doc-writer/scripts/smart_prompts.py +363 -0
  130. package/skills/core/pdd-ba/SKILL.md +305 -0
  131. package/skills/core/pdd-ba/_meta.json +1 -0
  132. package/skills/core/pdd-ba/evals/default-evals.json +1 -0
  133. package/skills/core/pdd-code-reviewer/SKILL.md +378 -0
  134. package/skills/core/pdd-code-reviewer/_meta.json +1 -0
  135. package/skills/core/pdd-code-reviewer/evals/default-evals.json +1 -0
  136. package/skills/core/pdd-doc-change/SKILL.md +350 -0
  137. package/skills/core/pdd-doc-change/_meta.json +1 -0
  138. package/skills/core/pdd-doc-change/evals/default-evals.json +1 -0
  139. package/skills/core/pdd-doc-gardener/SKILL.md +248 -0
  140. package/skills/core/pdd-doc-gardener/_meta.json +1 -0
  141. package/skills/core/pdd-doc-gardener/evals/default-evals.json +1 -0
  142. package/skills/core/pdd-entropy-reduction/SKILL.md +360 -0
  143. package/skills/core/pdd-entropy-reduction/_meta.json +1 -0
  144. package/skills/core/pdd-entropy-reduction/evals/default-evals.json +1 -0
  145. package/skills/core/pdd-entropy-reduction/references/entropy-report-template.md +287 -0
  146. package/skills/core/pdd-entropy-reduction/references/golden-principles.md +573 -0
  147. package/skills/core/pdd-entropy-reduction/scripts/entropy_scan.py +712 -0
  148. package/skills/core/pdd-extract-features/SKILL.md +320 -0
  149. package/skills/core/pdd-extract-features/_meta.json +1 -0
  150. package/skills/core/pdd-extract-features/evals/default-evals.json +1 -0
  151. package/skills/core/pdd-generate-spec/SKILL.md +418 -0
  152. package/skills/core/pdd-generate-spec/_meta.json +1 -0
  153. package/skills/core/pdd-generate-spec/evals/default-evals.json +1 -0
  154. package/skills/core/pdd-implement-feature/SKILL.md +332 -0
  155. package/skills/core/pdd-implement-feature/_meta.json +1 -0
  156. package/skills/core/pdd-implement-feature/evals/default-evals.json +1 -0
  157. package/skills/core/pdd-main/SKILL.md +540 -0
  158. package/skills/core/pdd-main/_meta.json +1 -0
  159. package/skills/core/pdd-main/evals/default-evals.json +1 -0
  160. package/skills/core/pdd-main/evals/evals.json +215 -0
  161. package/skills/core/pdd-verify-feature/SKILL.md +474 -0
  162. package/skills/core/pdd-verify-feature/_meta.json +1 -0
  163. package/skills/core/pdd-verify-feature/evals/default-evals.json +1 -0
  164. package/skills/core/pdd-vm/evals/default-evals.json +1 -0
  165. package/skills/core/traffic-accident-assessor/LICENSE +29 -0
  166. package/skills/core/traffic-accident-assessor/SKILL.md +439 -0
  167. package/skills/core/traffic-accident-assessor/evals/evals.json +1 -0
  168. package/skills/core/traffic-accident-assessor/references/accident-types.md +369 -0
  169. package/skills/core/traffic-accident-assessor/references/liability-rules.md +287 -0
  170. package/skills/core/traffic-accident-assessor/references/traffic-laws.md +226 -0
  171. package/skills/core/traffic-accident-assessor/references//351/253/230/345/260/224/345/244/253/350/257/264/346/230/216/344/271/246.pdf +32576 -106
  172. package/skills/core/traffic-accident-assessor/scripts/generate_official_statement.py +588 -0
  173. package/skills/core/traffic-accident-assessor/scripts/generate_report.py +495 -0
  174. package/skills/core/traffic-accident-assessor/scripts/generate_statement.py +528 -0
  175. package/skills/core/traffic-accident-assessor.zip +0 -0
  176. package/skills/entropy/expert-arch-enforcer/SKILL.md +292 -0
  177. package/skills/entropy/expert-arch-enforcer/_meta.json +1 -0
  178. package/skills/entropy/expert-arch-enforcer/evals/default-evals.json +1 -0
  179. package/skills/entropy/expert-auto-refactor/SKILL.md +327 -0
  180. package/skills/entropy/expert-auto-refactor/_meta.json +1 -0
  181. package/skills/entropy/expert-auto-refactor/evals/default-evals.json +1 -0
  182. package/skills/entropy/expert-code-quality/SKILL.md +468 -0
  183. package/skills/entropy/expert-code-quality/_meta.json +1 -0
  184. package/skills/entropy/expert-code-quality/evals/default-evals.json +1 -0
  185. package/skills/entropy/expert-code-quality/evals/evals.json +109 -0
  186. package/skills/entropy/expert-code-quality/references/code-smells.md +605 -0
  187. package/skills/entropy/expert-code-quality/references/design-patterns.md +1111 -0
  188. package/skills/entropy/expert-code-quality/references/refactoring-catalog.md +1281 -0
  189. package/skills/entropy/expert-code-quality/references/solid-principles.md +524 -0
  190. package/skills/entropy/expert-entropy-auditor/SKILL.md +276 -0
  191. package/skills/entropy/expert-entropy-auditor/_meta.json +1 -0
  192. package/skills/entropy/expert-entropy-auditor/evals/default-evals.json +1 -0
  193. package/skills/expert/expert-activiti/SKILL.md +497 -0
  194. package/skills/expert/expert-activiti/_meta.json +1 -0
  195. package/skills/expert/expert-mysql/SKILL.md +832 -0
  196. package/skills/expert/expert-mysql/_meta.json +1 -0
  197. package/skills/expert/expert-performance/SKILL.md +379 -0
  198. package/skills/expert/expert-performance/_meta.json +1 -0
  199. package/skills/expert/expert-performance/evals/default-evals.json +1 -0
  200. package/skills/expert/expert-ruoyi/SKILL.md +472 -0
  201. package/skills/expert/expert-ruoyi/_meta.json +1 -0
  202. package/skills/expert/expert-security/SKILL.md +1341 -0
  203. package/skills/expert/expert-security/_meta.json +1 -0
  204. package/skills/expert/expert-security/evals/default-evals.json +1 -0
  205. package/skills/expert/software-architect/SKILL.md +350 -0
  206. package/skills/expert/software-architect/_meta.json +1 -0
  207. package/skills/expert/software-engineer/SKILL.md +437 -0
  208. package/skills/expert/software-engineer/_meta.json +1 -0
  209. package/skills/expert/software-engineer/architecture.md +130 -0
  210. package/skills/expert/software-engineer/patterns.md +151 -0
  211. package/skills/expert/software-engineer/testing.md +135 -0
  212. package/skills/expert/system-architect/SKILL.md +628 -0
  213. package/skills/expert/system-architect/_meta.json +1 -0
  214. package/skills/expert/system-architect/assets/templates/ARCHITECTURE.md +25 -0
  215. package/skills/expert/system-architect/assets/templates/README.md +44 -0
  216. package/skills/expert/system-architect/references/js-ts-standards.md +18 -0
  217. package/skills/expert/system-architect/references/python-standards.md +19 -0
  218. package/skills/expert/system-architect/references/scaffolding.md +61 -0
  219. package/skills/expert/system-architect/references/security-checklist.md +21 -0
  220. package/skills/openspec/openspec-apply-change/SKILL.md +156 -0
  221. package/skills/openspec/openspec-apply-change/_meta.json +1 -0
  222. package/skills/openspec/openspec-archive-change/SKILL.md +114 -0
  223. package/skills/openspec/openspec-archive-change/_meta.json +1 -0
  224. package/skills/openspec/openspec-bulk-archive-change/SKILL.md +246 -0
  225. package/skills/openspec/openspec-bulk-archive-change/_meta.json +1 -0
  226. package/skills/openspec/openspec-continue-change/SKILL.md +118 -0
  227. package/skills/openspec/openspec-continue-change/_meta.json +1 -0
  228. package/skills/openspec/openspec-explore/SKILL.md +288 -0
  229. package/skills/openspec/openspec-explore/_meta.json +1 -0
  230. package/skills/openspec/openspec-ff-change/SKILL.md +101 -0
  231. package/skills/openspec/openspec-ff-change/_meta.json +1 -0
  232. package/skills/openspec/openspec-new-change/SKILL.md +74 -0
  233. package/skills/openspec/openspec-new-change/_meta.json +1 -0
  234. package/skills/openspec/openspec-onboard/SKILL.md +554 -0
  235. package/skills/openspec/openspec-onboard/_meta.json +1 -0
  236. package/skills/openspec/openspec-sync-specs/SKILL.md +138 -0
  237. package/skills/openspec/openspec-sync-specs/_meta.json +1 -0
  238. package/skills/openspec/openspec-verify-change/SKILL.md +168 -0
  239. package/skills/openspec/openspec-verify-change/_meta.json +1 -0
  240. package/skills/pr/pdd-multi-review/SKILL.md +534 -0
  241. package/skills/pr/pdd-multi-review/_meta.json +1 -0
  242. package/skills/pr/pdd-pr-batch/SKILL.md +303 -0
  243. package/skills/pr/pdd-pr-batch/_meta.json +1 -0
  244. package/skills/pr/pdd-pr-create/SKILL.md +344 -0
  245. package/skills/pr/pdd-pr-create/_meta.json +1 -0
  246. package/skills/pr/pdd-pr-merge/SKILL.md +286 -0
  247. package/skills/pr/pdd-pr-merge/_meta.json +1 -0
  248. package/skills/pr/pdd-pr-review/SKILL.md +217 -0
  249. package/skills/pr/pdd-pr-review/_meta.json +1 -0
  250. package/skills/pr/pdd-task-manager/SKILL.md +636 -0
  251. package/skills/pr/pdd-task-manager/_meta.json +1 -0
  252. package/skills/pr/pdd-template-engine/SKILL.md +306 -0
  253. package/skills/pr/pdd-template-engine/_meta.json +1 -0
  254. package/templates/behavior-shaping/iron-law-template.md +87 -0
  255. package/templates/behavior-shaping/rationalization-template.md +62 -0
  256. package/templates/behavior-shaping/red-flags-template.md +70 -0
  257. package/templates/bilingual-template.md +139 -0
  258. package/templates/config/default.yaml +47 -0
  259. package/templates/project/default/README.md +31 -0
  260. package/templates/project/frontend/README.md +46 -0
  261. package/templates/project/java/README.md +48 -0
@@ -0,0 +1,1378 @@
1
+ /**
2
+ * PDD Visual Manager - Dashboard Stylesheet (VM-B011)
3
+ *
4
+ * 完整的 CSS 样式系统,支持:
5
+ * - 亮色/暗色双主题切换
6
+ * - 响应式布局(桌面/平板/移动端)
7
+ * - 组件化样式(导航、卡片、表格、看板等)
8
+ *
9
+ * @version 1.0.0
10
+ */
11
+
12
+ /* ============================================================
13
+ CSS 变量 - 主题定义
14
+ ============================================================ */
15
+
16
+ /* 亮色主题 (默认) */
17
+ :root[data-theme="light"] {
18
+ /* 背景色 */
19
+ --bg-primary: #ffffff;
20
+ --bg-secondary: #f8f9fa;
21
+ --bg-tertiary: #e9ecef;
22
+
23
+ /* 文字颜色 */
24
+ --text-primary: #212529;
25
+ --text-secondary: #6c757d;
26
+ --text-muted: #adb5bd;
27
+
28
+ /* 边框与分割线 */
29
+ --border-color: #dee2e6;
30
+ --border-light: #e9ecef;
31
+
32
+ /* 语义化颜色 - 强调色 */
33
+ --accent: #4361ee;
34
+ --accent-hover: #3a56d4;
35
+ --accent-light: rgba(67, 97, 238, 0.1);
36
+
37
+ /* 语义化颜色 - 状态 */
38
+ --success: #38b000;
39
+ --success-bg: #d4edda;
40
+ --warning: #ffbe0b;
41
+ --warning-bg: #fff3cd;
42
+ --danger: #e63946;
43
+ --danger-bg: #f8d7da;
44
+ --info: #4cc9f0;
45
+ --info-bg: #cce5ff;
46
+
47
+ /* 阴影 */
48
+ --card-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
49
+ --card-hover-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
50
+ --modal-shadow: 0 20px 60px rgba(0, 0, 0, 0.15);
51
+
52
+ /* 圆角 */
53
+ --radius-sm: 4px;
54
+ --radius: 8px;
55
+ --radius-lg: 12px;
56
+ --radius-xl: 16px;
57
+
58
+ /* 过渡动画 */
59
+ --transition-fast: 0.15s ease;
60
+ --transition-normal: 0.2s ease;
61
+ --transition-slow: 0.3s ease;
62
+
63
+ /* 导航栏高度 */
64
+ --navbar-height: 56px;
65
+ --statusbar-height: 32px;
66
+ }
67
+
68
+ /* 暗色主题 */
69
+ :root[data-theme="dark"] {
70
+ /* 背景色 - 基于 Tokyo Night 配色方案 */
71
+ --bg-primary: #1a1b26;
72
+ --bg-secondary: #24283b;
73
+ --bg-tertiary: #292e42;
74
+
75
+ /* 文字颜色 */
76
+ --text-primary: #c0caf5;
77
+ --text-secondary: #565f89;
78
+ --text-muted: #414868;
79
+
80
+ /* 边框与分割线 */
81
+ --border-color: #414868;
82
+ --border-light: #363a52;
83
+
84
+ /* 语义化颜色 - 强调色 */
85
+ --accent: #7aa2f7;
86
+ --accent-hover: #6490ed;
87
+ --accent-light: rgba(122, 162, 247, 0.15);
88
+
89
+ /* 语义化颜色 - 状态 */
90
+ --success: #9ece6a;
91
+ --success-bg: rgba(158, 206, 106, 0.15);
92
+ --warning: #e0af68;
93
+ --warning-bg: rgba(224, 175, 104, 0.15);
94
+ --danger: #f7768e;
95
+ --danger-bg: rgba(247, 118, 142, 0.15);
96
+ --info: #7dcfff;
97
+ --info-bg: rgba(125, 207, 255, 0.15);
98
+
99
+ /* 阴影 */
100
+ --card-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
101
+ --card-hover-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
102
+ --modal-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
103
+
104
+ /* 其他保持不变 */
105
+ }
106
+
107
+ /* ============================================================
108
+ Reset & Base Styles
109
+ ============================================================ */
110
+
111
+ *, *::before, *::after {
112
+ box-sizing: border-box;
113
+ margin: 0;
114
+ padding: 0;
115
+ }
116
+
117
+ html {
118
+ font-size: 16px;
119
+ -webkit-text-size-adjust: 100%;
120
+ scroll-behavior: smooth;
121
+ }
122
+
123
+ body {
124
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans SC',
125
+ 'Helvetica Neue', Arial, sans-serif;
126
+ background-color: var(--bg-primary);
127
+ color: var(--text-primary);
128
+ line-height: 1.6;
129
+ min-height: 100vh;
130
+ display: flex;
131
+ flex-direction: column;
132
+ overflow-x: hidden;
133
+ antialiased;
134
+ -webkit-font-smoothing: antialiased;
135
+ -moz-osx-font-smoothing: grayscale;
136
+ }
137
+
138
+ /* 滚动条美化 */
139
+ ::-webkit-scrollbar {
140
+ width: 8px;
141
+ height: 8px;
142
+ }
143
+
144
+ ::-webkit-scrollbar-track {
145
+ background: var(--bg-secondary);
146
+ }
147
+
148
+ ::-webkit-scrollbar-thumb {
149
+ background: var(--border-color);
150
+ border-radius: 4px;
151
+ }
152
+
153
+ ::-webkit-scrollbar-thumb:hover {
154
+ background: var(--text-muted);
155
+ }
156
+
157
+ /* 选择文本的颜色 */
158
+ ::selection {
159
+ background: var(--accent);
160
+ color: #fff;
161
+ }
162
+
163
+ /* ============================================================
164
+ Navigation Bar
165
+ ============================================================ */
166
+
167
+ .navbar {
168
+ height: var(--navbar-height);
169
+ background: var(--bg-secondary);
170
+ border-bottom: 1px solid var(--border-color);
171
+ display: flex;
172
+ align-items: center;
173
+ padding: 0 20px;
174
+ position: sticky;
175
+ top: 0;
176
+ z-index: 100;
177
+ gap: 20px;
178
+ flex-shrink: 0;
179
+ }
180
+
181
+ .navbar-brand {
182
+ font-size: 18px;
183
+ font-weight: 700;
184
+ white-space: nowrap;
185
+ color: var(--text-primary);
186
+ user-select: none;
187
+ }
188
+
189
+ .navbar-tabs {
190
+ display: flex;
191
+ gap: 4px;
192
+ flex: 1;
193
+ justify-content: center;
194
+ }
195
+
196
+ .tab-btn {
197
+ padding: 8px 16px;
198
+ border: none;
199
+ background: transparent;
200
+ color: var(--text-secondary);
201
+ cursor: pointer;
202
+ border-radius: var(--radius-sm);
203
+ font-size: 14px;
204
+ font-weight: 500;
205
+ transition: all var(--transition-normal);
206
+ white-space: nowrap;
207
+ user-select: none;
208
+ }
209
+
210
+ .tab-btn:hover {
211
+ background: var(--border-color);
212
+ color: var(--text-primary);
213
+ }
214
+
215
+ .tab-btn.active {
216
+ background: var(--accent);
217
+ color: #ffffff;
218
+ box-shadow: 0 2px 4px rgba(67, 97, 238, 0.3);
219
+ }
220
+
221
+ .navbar-actions {
222
+ display: flex;
223
+ align-items: center;
224
+ gap: 12px;
225
+ flex-shrink: 0;
226
+ }
227
+
228
+ #theme-toggle {
229
+ padding: 6px 10px;
230
+ border: 1px solid var(--border-color);
231
+ background: var(--bg-primary);
232
+ cursor: pointer;
233
+ border-radius: var(--radius-sm);
234
+ font-size: 18px;
235
+ transition: all var(--transition-fast);
236
+ line-height: 1;
237
+ }
238
+
239
+ #theme-toggle:hover {
240
+ border-color: var(--accent);
241
+ transform: scale(1.05);
242
+ }
243
+
244
+ /* ============================================================
245
+ Status Dot (连接状态指示器)
246
+ ============================================================ */
247
+
248
+ .status-dot {
249
+ width: 10px;
250
+ height: 10px;
251
+ border-radius: 50%;
252
+ display: inline-block;
253
+ transition: all var(--transition-slow);
254
+ flex-shrink: 0;
255
+ }
256
+
257
+ .status-dot.online {
258
+ background: var(--success);
259
+ box-shadow: 0 0 8px var(--success), 0 0 16px rgba(56, 176, 0, 0.3);
260
+ animation: pulse-green 2s infinite;
261
+ }
262
+
263
+ .status-dot.offline {
264
+ background: var(--danger);
265
+ box-shadow: 0 0 8px var(--danger);
266
+ }
267
+
268
+ @keyframes pulse-green {
269
+ 0%, 100% { opacity: 1; }
270
+ 50% { opacity: 0.6; }
271
+ }
272
+
273
+ /* ============================================================
274
+ Main Content Area
275
+ ============================================================ */
276
+
277
+ #main-content {
278
+ flex: 1;
279
+ padding: 20px;
280
+ overflow-y: auto;
281
+ overflow-x: hidden;
282
+ }
283
+
284
+ .view {
285
+ display: none;
286
+ animation-duration: 0.3s;
287
+ animation-fill-mode: both;
288
+ }
289
+
290
+ .view.active {
291
+ display: block;
292
+ animation-name: fadeInUp;
293
+ }
294
+
295
+ @keyframes fadeInUp {
296
+ from {
297
+ opacity: 0;
298
+ transform: translateY(12px);
299
+ }
300
+ to {
301
+ opacity: 1;
302
+ transform: translateY(0);
303
+ }
304
+ }
305
+
306
+ /* ============================================================
307
+ Status Bar (底部状态栏)
308
+ ============================================================ */
309
+
310
+ .status-bar {
311
+ height: var(--statusbar-height);
312
+ background: var(--bg-secondary);
313
+ border-top: 1px solid var(--border-color);
314
+ display: flex;
315
+ align-items: center;
316
+ padding: 0 20px;
317
+ font-size: 12px;
318
+ color: var(--text-secondary);
319
+ gap: 24px;
320
+ flex-shrink: 0;
321
+ user-select: none;
322
+ }
323
+
324
+ .status-bar span {
325
+ display: flex;
326
+ align-items: center;
327
+ gap: 4px;
328
+ }
329
+
330
+ /* ============================================================
331
+ Card Component (通用卡片)
332
+ ============================================================ */
333
+
334
+ .card {
335
+ background: var(--bg-secondary);
336
+ border-radius: var(--radius);
337
+ border: 1px solid var(--border-color);
338
+ padding: 16px;
339
+ box-shadow: var(--card-shadow);
340
+ transition: box-shadow var(--transition-normal), transform var(--transition-normal);
341
+ }
342
+
343
+ .card:hover {
344
+ box-shadow: var(--card-hover-shadow);
345
+ }
346
+
347
+ .card-header {
348
+ font-size: 14px;
349
+ font-weight: 600;
350
+ margin-bottom: 12px;
351
+ display: flex;
352
+ justify-content: space-between;
353
+ align-items: center;
354
+ color: var(--text-primary);
355
+ }
356
+
357
+ .card-value {
358
+ font-size: 28px;
359
+ font-weight: 700;
360
+ color: var(--accent);
361
+ line-height: 1.2;
362
+ }
363
+
364
+ .card-subtitle {
365
+ font-size: 13px;
366
+ color: var(--text-secondary);
367
+ margin-top: 4px;
368
+ }
369
+
370
+ /* ============================================================
371
+ Grid Layouts (网格布局)
372
+ ============================================================ */
373
+
374
+ .grid-2 {
375
+ display: grid;
376
+ grid-template-columns: repeat(2, 1fr);
377
+ gap: 16px;
378
+ margin-bottom: 20px;
379
+ }
380
+
381
+ .grid-3 {
382
+ display: grid;
383
+ grid-template-columns: repeat(3, 1fr);
384
+ gap: 16px;
385
+ margin-bottom: 20px;
386
+ }
387
+
388
+ .grid-4 {
389
+ display: grid;
390
+ grid-template-columns: repeat(4, 1fr);
391
+ gap: 16px;
392
+ margin-bottom: 20px;
393
+ }
394
+
395
+ .grid-auto {
396
+ display: grid;
397
+ grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
398
+ gap: 16px;
399
+ margin-bottom: 20px;
400
+ }
401
+
402
+ /* ============================================================
403
+ Pipeline View (流水线视图)
404
+ ============================================================ */
405
+
406
+ .pipeline-container {
407
+ display: flex;
408
+ gap: 12px;
409
+ overflow-x: auto;
410
+ padding: 16px 0;
411
+ min-height: 200px;
412
+ }
413
+
414
+ .pipeline-stage {
415
+ min-width: 160px;
416
+ flex: 1;
417
+ max-width: 220px;
418
+ background: var(--bg-secondary);
419
+ border-radius: var(--radius);
420
+ border: 2px solid var(--border-color);
421
+ padding: 20px 16px;
422
+ text-align: center;
423
+ transition: all var(--transition-slow);
424
+ cursor: default;
425
+ position: relative;
426
+ }
427
+
428
+ .pipeline-stage:hover {
429
+ border-color: var(--accent);
430
+ transform: translateY(-4px);
431
+ box-shadow: var(--card-hover-shadow);
432
+ }
433
+
434
+ .pipeline-stage.active {
435
+ border-color: var(--accent);
436
+ background: var(--accent-light);
437
+ }
438
+
439
+ .pipeline-stage-icon {
440
+ font-size: 28px;
441
+ margin-bottom: 8px;
442
+ }
443
+
444
+ .pipeline-stage-count {
445
+ font-size: 36px;
446
+ font-weight: 700;
447
+ color: var(--accent);
448
+ line-height: 1;
449
+ }
450
+
451
+ .pipeline-stage-label {
452
+ font-size: 13px;
453
+ color: var(--text-secondary);
454
+ margin-top: 8px;
455
+ font-weight: 500;
456
+ }
457
+
458
+ .pipeline-progress {
459
+ height: 4px;
460
+ background: var(--border-color);
461
+ border-radius: 2px;
462
+ margin-top: 14px;
463
+ overflow: hidden;
464
+ }
465
+
466
+ .pipeline-progress-bar {
467
+ height: 100%;
468
+ background: linear-gradient(90deg, var(--accent), var(--info));
469
+ border-radius: 2px;
470
+ transition: width 0.5s ease;
471
+ }
472
+
473
+ /* 流水线阶段之间的箭头连接 */
474
+ .pipeline-arrow {
475
+ display: flex;
476
+ align-items: center;
477
+ color: var(--text-muted);
478
+ font-size: 20px;
479
+ flex-shrink: 0;
480
+ padding: 0 4px;
481
+ }
482
+
483
+ /* ============================================================
484
+ Kanban Board (看板视图)
485
+ ============================================================ */
486
+
487
+ .kanban-board {
488
+ display: flex;
489
+ gap: 12px;
490
+ overflow-x: auto;
491
+ min-height: 450px;
492
+ padding: 4px 0;
493
+ }
494
+
495
+ .kanban-column {
496
+ min-width: 260px;
497
+ width: 260px;
498
+ flex-shrink: 0;
499
+ background: var(--bg-secondary);
500
+ border-radius: var(--radius);
501
+ border: 1px solid var(--border-color);
502
+ display: flex;
503
+ flex-direction: column;
504
+ overflow: hidden;
505
+ }
506
+
507
+ .kanban-column-header {
508
+ padding: 14px 16px;
509
+ font-weight: 600;
510
+ font-size: 13px;
511
+ border-bottom: 1px solid var(--border-color);
512
+ display: flex;
513
+ justify-content: space-between;
514
+ align-items: center;
515
+ background: var(--bg-tertiary);
516
+ user-select: none;
517
+ }
518
+
519
+ .kanban-column-count {
520
+ background: var(--accent);
521
+ color: #fff;
522
+ padding: 2px 8px;
523
+ border-radius: 10px;
524
+ font-size: 11px;
525
+ font-weight: 600;
526
+ }
527
+
528
+ .kanban-column-body {
529
+ flex: 1;
530
+ padding: 10px;
531
+ overflow-y: auto;
532
+ display: flex;
533
+ flex-direction: column;
534
+ gap: 8px;
535
+ }
536
+
537
+ .kanban-card {
538
+ background: var(--bg-primary);
539
+ border: 1px solid var(--border-color);
540
+ border-radius: 6px;
541
+ padding: 14px;
542
+ cursor: pointer;
543
+ transition: all var(--transition-normal);
544
+ position: relative;
545
+ }
546
+
547
+ .kanban-card:hover {
548
+ border-color: var(--accent);
549
+ transform: translateY(-2px);
550
+ box-shadow: var(--card-shadow);
551
+ }
552
+
553
+ .kanban-card-name {
554
+ font-size: 14px;
555
+ font-weight: 600;
556
+ margin-bottom: 6px;
557
+ white-space: nowrap;
558
+ overflow: hidden;
559
+ text-overflow: ellipsis;
560
+ color: var(--text-primary);
561
+ }
562
+
563
+ .kanban-card-id {
564
+ font-size: 11px;
565
+ color: var(--text-muted);
566
+ margin-bottom: 8px;
567
+ font-family: 'Courier New', monospace;
568
+ }
569
+
570
+ .kanban-card-meta {
571
+ font-size: 12px;
572
+ color: var(--text-secondary);
573
+ display: flex;
574
+ justify-content: space-between;
575
+ align-items: center;
576
+ }
577
+
578
+ .kanban-card-progress {
579
+ height: 3px;
580
+ background: var(--border-light);
581
+ border-radius: 2px;
582
+ margin-top: 10px;
583
+ overflow: hidden;
584
+ }
585
+
586
+ .kanban-card-progress-bar {
587
+ height: 100%;
588
+ background: var(--success);
589
+ border-radius: 2px;
590
+ transition: width 0.3s ease;
591
+ }
592
+
593
+ /* Grade Badge (质量等级徽章) */
594
+ .grade-badge {
595
+ display: inline-block;
596
+ padding: 3px 10px;
597
+ border-radius: 12px;
598
+ font-size: 11px;
599
+ font-weight: 700;
600
+ letter-spacing: 0.5px;
601
+ }
602
+
603
+ .grade-S { background: var(--success-bg); color: var(--success); }
604
+ .grade-A { background: var(--info-bg); color: var(--accent); }
605
+ .grade-B { background: var(--warning-bg); color: var(--warning); }
606
+ .grade-C { background: var(--danger-bg); color: var(--danger); }
607
+ .grade-D, .grade-F { background: var(--danger-bg); color: var(--danger); }
608
+
609
+ /* Priority Badge (优先级徽章) */
610
+ .priority-badge {
611
+ display: inline-block;
612
+ padding: 2px 8px;
613
+ border-radius: 4px;
614
+ font-size: 11px;
615
+ font-weight: 600;
616
+ }
617
+
618
+ .priority-high { background: var(--danger-bg); color: var(--danger); }
619
+ .priority-medium { background: var(--warning-bg); color: var(--warning); }
620
+ .priority-low { background: var(--info-bg); color: var(--info); }
621
+
622
+ /* ============================================================
623
+ Modal Dialog (弹窗)
624
+ ============================================================ */
625
+
626
+ .modal-hidden {
627
+ display: none !important;
628
+ }
629
+
630
+ #modal-overlay {
631
+ position: fixed;
632
+ inset: 0;
633
+ background: rgba(0, 0, 0, 0.5);
634
+ backdrop-filter: blur(4px);
635
+ z-index: 200;
636
+ display: flex;
637
+ align-items: center;
638
+ justify-content: center;
639
+ animation: fadeIn 0.2s ease;
640
+ }
641
+
642
+ @keyframes fadeIn {
643
+ from { opacity: 0; }
644
+ to { opacity: 1; }
645
+ }
646
+
647
+ #modal-content {
648
+ background: var(--bg-primary);
649
+ border-radius: var(--radius-lg);
650
+ max-width: 720px;
651
+ width: 90%;
652
+ max-height: 85vh;
653
+ overflow-y: auto;
654
+ padding: 28px;
655
+ box-shadow: var(--modal-shadow);
656
+ animation: modalSlideIn 0.25s ease;
657
+ position: relative;
658
+ }
659
+
660
+ @keyframes modalSlideIn {
661
+ from {
662
+ opacity: 0;
663
+ transform: scale(0.95) translateY(-20px);
664
+ }
665
+ to {
666
+ opacity: 1;
667
+ transform: scale(1) translateY(0);
668
+ }
669
+ }
670
+
671
+ .modal-close {
672
+ float: right;
673
+ cursor: pointer;
674
+ font-size: 26px;
675
+ line-height: 1;
676
+ color: var(--text-secondary);
677
+ transition: color var(--transition-fast);
678
+ background: none;
679
+ border: none;
680
+ padding: 4px;
681
+ }
682
+
683
+ .modal-close:hover {
684
+ color: var(--danger);
685
+ }
686
+
687
+ .modal-title {
688
+ font-size: 18px;
689
+ font-weight: 700;
690
+ margin-bottom: 16px;
691
+ padding-right: 30px;
692
+ color: var(--text-primary);
693
+ }
694
+
695
+ .modal-body {
696
+ margin-bottom: 20px;
697
+ color: var(--text-secondary);
698
+ line-height: 1.7;
699
+ }
700
+
701
+ .modal-footer {
702
+ display: flex;
703
+ justify-content: flex-end;
704
+ gap: 10px;
705
+ padding-top: 16px;
706
+ border-top: 1px solid var(--border-color);
707
+ }
708
+
709
+ /* ============================================================
710
+ Data Table (数据表格)
711
+ ============================================================ */
712
+
713
+ .data-table {
714
+ width: 100%;
715
+ border-collapse: collapse;
716
+ font-size: 13px;
717
+ }
718
+
719
+ .data-table th,
720
+ .data-table td {
721
+ padding: 12px 14px;
722
+ text-align: left;
723
+ border-bottom: 1px solid var(--border-color);
724
+ }
725
+
726
+ .data-table th {
727
+ font-weight: 600;
728
+ background: var(--bg-secondary);
729
+ color: var(--text-primary);
730
+ position: sticky;
731
+ top: 0;
732
+ z-index: 10;
733
+ white-space: nowrap;
734
+ user-select: none;
735
+ }
736
+
737
+ .data-table tbody tr {
738
+ transition: background var(--transition-fast);
739
+ }
740
+
741
+ .data-table tbody tr:hover {
742
+ background: var(--accent-light);
743
+ }
744
+
745
+ .data-table td {
746
+ color: var(--text-secondary);
747
+ }
748
+
749
+ .table-container {
750
+ overflow-x: auto;
751
+ border: 1px solid var(--border-color);
752
+ border-radius: var(--radius);
753
+ background: var(--bg-primary);
754
+ }
755
+
756
+ /* ============================================================
757
+ Filter Bar (筛选工具栏)
758
+ ============================================================ */
759
+
760
+ .filter-bar {
761
+ display: flex;
762
+ gap: 10px;
763
+ margin-bottom: 16px;
764
+ flex-wrap: wrap;
765
+ align-items: center;
766
+ }
767
+
768
+ .filter-group {
769
+ display: flex;
770
+ align-items: center;
771
+ gap: 6px;
772
+ }
773
+
774
+ .filter-label {
775
+ font-size: 13px;
776
+ color: var(--text-secondary);
777
+ font-weight: 500;
778
+ }
779
+
780
+ .filter-select,
781
+ .filter-input {
782
+ padding: 8px 12px;
783
+ border: 1px solid var(--border-color);
784
+ border-radius: var(--radius-sm);
785
+ background: var(--bg-primary);
786
+ color: var(--text-primary);
787
+ font-size: 13px;
788
+ min-width: 140px;
789
+ transition: border-color var(--transition-fast);
790
+ }
791
+
792
+ .filter-select:focus,
793
+ .filter-input:focus {
794
+ outline: none;
795
+ border-color: var(--accent);
796
+ box-shadow: 0 0 0 3px var(--accent-light);
797
+ }
798
+
799
+ .btn {
800
+ padding: 8px 16px;
801
+ border: 1px solid var(--border-color);
802
+ border-radius: var(--radius-sm);
803
+ background: var(--bg-primary);
804
+ color: var(--text-primary);
805
+ font-size: 13px;
806
+ font-weight: 500;
807
+ cursor: pointer;
808
+ transition: all var(--transition-normal);
809
+ display: inline-flex;
810
+ align-items: center;
811
+ gap: 6px;
812
+ }
813
+
814
+ .btn:hover {
815
+ border-color: var(--accent);
816
+ color: var(--accent);
817
+ }
818
+
819
+ .btn-primary {
820
+ background: var(--accent);
821
+ color: #fff;
822
+ border-color: var(--accent);
823
+ }
824
+
825
+ .btn-primary:hover {
826
+ background: var(--accent-hover);
827
+ color: #fff;
828
+ }
829
+
830
+ .btn-success {
831
+ background: var(--success);
832
+ color: #fff;
833
+ border-color: var(--success);
834
+ }
835
+
836
+ .btn-danger {
837
+ background: var(--danger);
838
+ color: #fff;
839
+ border-color: var(--danger);
840
+ }
841
+
842
+ .btn-sm {
843
+ padding: 5px 10px;
844
+ font-size: 12px;
845
+ }
846
+
847
+ /* ============================================================
848
+ Progress Ring (圆环进度 - SVG/CSS)
849
+ ============================================================ */
850
+
851
+ .progress-ring-container {
852
+ display: inline-flex;
853
+ flex-direction: column;
854
+ align-items: center;
855
+ gap: 8px;
856
+ }
857
+
858
+ .progress-ring {
859
+ transform: rotate(-90deg);
860
+ }
861
+
862
+ .progress-ring-circle {
863
+ transition: stroke-dashoffset 0.5s ease;
864
+ stroke-linecap: round;
865
+ }
866
+
867
+ .progress-ring-text {
868
+ font-size: 14px;
869
+ font-weight: 600;
870
+ color: var(--text-primary);
871
+ }
872
+
873
+ .progress-ring-label {
874
+ font-size: 12px;
875
+ color: var(--text-secondary);
876
+ }
877
+
878
+ /* ============================================================
879
+ Toast Notifications (通知提示)
880
+ ============================================================ */
881
+
882
+ #toast-container {
883
+ position: fixed;
884
+ top: calc(var(--navbar-height) + 16px);
885
+ right: 16px;
886
+ z-index: 300;
887
+ display: flex;
888
+ flex-direction: column;
889
+ gap: 8px;
890
+ max-width: 380px;
891
+ pointer-events: none;
892
+ }
893
+
894
+ .toast {
895
+ background: var(--bg-primary);
896
+ border: 1px solid var(--border-color);
897
+ border-radius: var(--radius);
898
+ padding: 14px 18px;
899
+ box-shadow: var(--card-shadow);
900
+ display: flex;
901
+ align-items: flex-start;
902
+ gap: 10px;
903
+ animation: toastSlideIn 0.3s ease;
904
+ pointer-events: auto;
905
+ min-width: 280px;
906
+ }
907
+
908
+ .toast.removing {
909
+ animation: toastSlideOut 0.25s ease forwards;
910
+ }
911
+
912
+ @keyframes toastSlideIn {
913
+ from {
914
+ opacity: 0;
915
+ transform: translateX(100%);
916
+ }
917
+ to {
918
+ opacity: 1;
919
+ transform: translateX(0);
920
+ }
921
+ }
922
+
923
+ @keyframes toastSlideOut {
924
+ from {
925
+ opacity: 1;
926
+ transform: translateX(0);
927
+ }
928
+ to {
929
+ opacity: 0;
930
+ transform: translateX(100%);
931
+ }
932
+ }
933
+
934
+ .toast-icon {
935
+ font-size: 18px;
936
+ flex-shrink: 0;
937
+ line-height: 1;
938
+ }
939
+
940
+ .toast-message {
941
+ flex: 1;
942
+ font-size: 13px;
943
+ color: var(--text-primary);
944
+ line-height: 1.5;
945
+ }
946
+
947
+ .toast-close {
948
+ cursor: pointer;
949
+ color: var(--text-muted);
950
+ font-size: 16px;
951
+ background: none;
952
+ border: none;
953
+ padding: 0 2px;
954
+ flex-shrink: 0;
955
+ }
956
+
957
+ .toast-close:hover {
958
+ color: var(--text-primary);
959
+ }
960
+
961
+ .toast.success { border-left: 3px solid var(--success); }
962
+ .toast.warning { border-left: 3px solid var(--warning); }
963
+ .toast.error { border-left: 3px solid var(--danger); }
964
+ .toast.info { border-left: 3px solid var(--info); }
965
+
966
+ /* ============================================================
967
+ Quality View Components (质量视图组件)
968
+ ============================================================ */
969
+
970
+ .quality-grid {
971
+ display: grid;
972
+ grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
973
+ gap: 14px;
974
+ margin-bottom: 20px;
975
+ }
976
+
977
+ .quality-item {
978
+ background: var(--bg-secondary);
979
+ border: 1px solid var(--border-color);
980
+ border-radius: var(--radius);
981
+ padding: 16px;
982
+ text-align: center;
983
+ transition: all var(--transition-normal);
984
+ }
985
+
986
+ .quality-item:hover {
987
+ transform: translateY(-2px);
988
+ box-shadow: var(--card-shadow);
989
+ }
990
+
991
+ .quality-item-label {
992
+ font-size: 12px;
993
+ color: var(--text-secondary);
994
+ margin-bottom: 8px;
995
+ text-transform: uppercase;
996
+ letter-spacing: 0.5px;
997
+ }
998
+
999
+ .quality-item-value {
1000
+ font-size: 24px;
1001
+ font-weight: 700;
1002
+ color: var(--accent);
1003
+ }
1004
+
1005
+ .quality-item-unit {
1006
+ font-size: 12px;
1007
+ color: var(--text-muted);
1008
+ margin-left: 2px;
1009
+ }
1010
+
1011
+ /* Chart Container */
1012
+ .chart-container {
1013
+ background: var(--bg-secondary);
1014
+ border: 1px solid var(--border-color);
1015
+ border-radius: var(--radius);
1016
+ padding: 20px;
1017
+ margin-bottom: 20px;
1018
+ }
1019
+
1020
+ .chart-title {
1021
+ font-size: 14px;
1022
+ font-weight: 600;
1023
+ margin-bottom: 16px;
1024
+ color: var(--text-primary);
1025
+ }
1026
+
1027
+ .chart-canvas-wrapper {
1028
+ position: relative;
1029
+ width: 100%;
1030
+ height: 300px;
1031
+ }
1032
+
1033
+ /* ============================================================
1034
+ System View Components (系统视图组件)
1035
+ ============================================================ */
1036
+
1037
+ .system-metrics {
1038
+ display: grid;
1039
+ grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
1040
+ gap: 14px;
1041
+ margin-bottom: 20px;
1042
+ }
1043
+
1044
+ .metric-card {
1045
+ background: var(--bg-secondary);
1046
+ border: 1px solid var(--border-color);
1047
+ border-radius: var(--radius);
1048
+ padding: 16px;
1049
+ }
1050
+
1051
+ .metric-label {
1052
+ font-size: 12px;
1053
+ color: var(--text-secondary);
1054
+ margin-bottom: 6px;
1055
+ text-transform: uppercase;
1056
+ letter-spacing: 0.5px;
1057
+ }
1058
+
1059
+ .metric-value {
1060
+ font-size: 22px;
1061
+ font-weight: 700;
1062
+ color: var(--text-primary);
1063
+ font-family: 'Courier New', monospace;
1064
+ }
1065
+
1066
+ .metric-status {
1067
+ display: inline-flex;
1068
+ align-items: center;
1069
+ gap: 6px;
1070
+ margin-top: 8px;
1071
+ font-size: 12px;
1072
+ }
1073
+
1074
+ .metric-status-dot {
1075
+ width: 8px;
1076
+ height: 8px;
1077
+ border-radius: 50%;
1078
+ }
1079
+
1080
+ /* Log Viewer */
1081
+ .log-viewer {
1082
+ background: var(--bg-primary);
1083
+ border: 1px solid var(--border-color);
1084
+ border-radius: var(--radius);
1085
+ padding: 16px;
1086
+ font-family: 'Courier New', Consolas, monospace;
1087
+ font-size: 12px;
1088
+ max-height: 400px;
1089
+ overflow-y: auto;
1090
+ line-height: 1.6;
1091
+ }
1092
+
1093
+ .log-entry {
1094
+ padding: 2px 0;
1095
+ border-bottom: 1px solid var(--border-light);
1096
+ }
1097
+
1098
+ .log-entry:last-child {
1099
+ border-bottom: none;
1100
+ }
1101
+
1102
+ .log-timestamp {
1103
+ color: var(--text-muted);
1104
+ margin-right: 10px;
1105
+ }
1106
+
1107
+ .log-level-info { color: var(--info); }
1108
+ .log-level-warn { color: var(--warning); }
1109
+ .log-level-error { color: var(--danger); }
1110
+ .log-level-success { color: var(--success); }
1111
+
1112
+ /* Empty State (空状态占位) */
1113
+ .empty-state {
1114
+ text-align: center;
1115
+ padding: 60px 20px;
1116
+ color: var(--text-secondary);
1117
+ }
1118
+
1119
+ .empty-state-icon {
1120
+ font-size: 48px;
1121
+ margin-bottom: 16px;
1122
+ opacity: 0.5;
1123
+ }
1124
+
1125
+ .empty-state-text {
1126
+ font-size: 16px;
1127
+ margin-bottom: 8px;
1128
+ }
1129
+
1130
+ .empty-state-hint {
1131
+ font-size: 13px;
1132
+ color: var(--text-muted);
1133
+ }
1134
+
1135
+ /* Loading State (加载状态) */
1136
+ .loading-spinner {
1137
+ display: inline-block;
1138
+ width: 32px;
1139
+ height: 32px;
1140
+ border: 3px solid var(--border-color);
1141
+ border-top-color: var(--accent);
1142
+ border-radius: 50%;
1143
+ animation: spin 0.8s linear infinite;
1144
+ }
1145
+
1146
+ @keyframes spin {
1147
+ to { transform: rotate(360deg); }
1148
+ }
1149
+
1150
+ .loading-state {
1151
+ display: flex;
1152
+ flex-direction: column;
1153
+ align-items: center;
1154
+ justify-content: center;
1155
+ padding: 60px 20px;
1156
+ gap: 16px;
1157
+ color: var(--text-secondary);
1158
+ }
1159
+
1160
+ /* ============================================================
1161
+ Utility Classes (工具类)
1162
+ ============================================================ */
1163
+
1164
+ .text-success { color: var(--success); }
1165
+ .text-warning { color: var(--warning); }
1166
+ .text-danger { color: var(--danger); }
1167
+ .text-info { color: var(--info); }
1168
+ .text-accent { color: var(--accent); }
1169
+ .text-muted { color: var(--text-muted); }
1170
+
1171
+ .bg-success { background: var(--success-bg); }
1172
+ .bg-warning { background: var(--warning-bg); }
1173
+ .bg-danger { background: var(--danger-bg); }
1174
+ .bg-info { background: var(--info-bg); }
1175
+
1176
+ .flex-between { display: flex; justify-content: space-between; align-items: center; }
1177
+ .flex-center { display: flex; align-items: center; justify-content: center; }
1178
+ .flex-start { display: flex; align-items: center; justify-content: flex-start; }
1179
+ .flex-end { display: flex; align-items: center; justify-content: flex-end; }
1180
+
1181
+ .mt-10 { margin-top: 10px; }
1182
+ .mt-20 { margin-top: 20px; }
1183
+ .mb-10 { margin-bottom: 10px; }
1184
+ .mb-20 { margin-bottom: 20px; }
1185
+ .p-10 { padding: 10px; }
1186
+ .p-20 { padding: 20px; }
1187
+
1188
+ .text-center { text-align: center; }
1189
+ .text-right { text-align: right; }
1190
+ .font-bold { font-weight: 700; }
1191
+ .font-medium { font-weight: 500; }
1192
+
1193
+ .truncate {
1194
+ white-space: nowrap;
1195
+ overflow: hidden;
1196
+ text-overflow: ellipsis;
1197
+ }
1198
+
1199
+ .hidden { display: none !important; }
1200
+ .visible { display: block !important; }
1201
+
1202
+ /* ============================================================
1203
+ Responsive Design (响应式设计)
1204
+ ============================================================ */
1205
+
1206
+ /* 平板设备 (<= 768px) */
1207
+ @media (max-width: 768px) {
1208
+ :root {
1209
+ --navbar-height: 52px;
1210
+ }
1211
+
1212
+ .navbar {
1213
+ padding: 0 12px;
1214
+ gap: 12px;
1215
+ }
1216
+
1217
+ .navbar-brand {
1218
+ font-size: 15px;
1219
+ }
1220
+
1221
+ .navbar-tabs {
1222
+ gap: 2px;
1223
+ }
1224
+
1225
+ .tab-btn {
1226
+ padding: 6px 10px;
1227
+ font-size: 13px;
1228
+ }
1229
+
1230
+ #main-content {
1231
+ padding: 14px;
1232
+ }
1233
+
1234
+ .grid-3,
1235
+ .grid-4 {
1236
+ grid-template-columns: repeat(2, 1fr);
1237
+ }
1238
+
1239
+ .kanban-board {
1240
+ flex-direction: column;
1241
+ }
1242
+
1243
+ .kanban-column {
1244
+ width: 100%;
1245
+ min-width: auto;
1246
+ min-height: 200px;
1247
+ }
1248
+
1249
+ .pipeline-container {
1250
+ flex-direction: column;
1251
+ }
1252
+
1253
+ .pipeline-stage {
1254
+ max-width: 100%;
1255
+ min-width: auto;
1256
+ }
1257
+
1258
+ .pipeline-arrow {
1259
+ transform: rotate(90deg);
1260
+ padding: 4px 0;
1261
+ }
1262
+
1263
+ .status-bar {
1264
+ gap: 12px;
1265
+ font-size: 11px;
1266
+ padding: 0 12px;
1267
+ overflow-x: auto;
1268
+ }
1269
+
1270
+ #modal-content {
1271
+ width: 95%;
1272
+ padding: 20px;
1273
+ max-height: 90vh;
1274
+ }
1275
+
1276
+ .filter-bar {
1277
+ flex-direction: column;
1278
+ align-items: stretch;
1279
+ }
1280
+
1281
+ .filter-select,
1282
+ .filter-input {
1283
+ width: 100%;
1284
+ min-width: auto;
1285
+ }
1286
+ }
1287
+
1288
+ /* 手机设备 (<= 480px) */
1289
+ @media (max-width: 480px) {
1290
+ body {
1291
+ font-size: 14px;
1292
+ }
1293
+
1294
+ .grid-2,
1295
+ .grid-3,
1296
+ .grid-4 {
1297
+ grid-template-columns: 1fr;
1298
+ }
1299
+
1300
+ .navbar-brand {
1301
+ font-size: 14px;
1302
+ }
1303
+
1304
+ .tab-btn {
1305
+ padding: 5px 8px;
1306
+ font-size: 12px;
1307
+ }
1308
+
1309
+ .card-value {
1310
+ font-size: 24px;
1311
+ }
1312
+
1313
+ .data-table {
1314
+ font-size: 12px;
1315
+ }
1316
+
1317
+ .data-table th,
1318
+ .data-table td {
1319
+ padding: 8px 10px;
1320
+ }
1321
+ }
1322
+
1323
+ /* 小屏手机 (<= 375px) */
1324
+ @media (max-width: 375px) {
1325
+ .navbar-tabs {
1326
+ display: none;
1327
+ }
1328
+
1329
+ .navbar-actions {
1330
+ gap: 8px;
1331
+ }
1332
+
1333
+ #toast-container {
1334
+ left: 8px;
1335
+ right: 8px;
1336
+ max-width: none;
1337
+ }
1338
+ }
1339
+
1340
+ /* 大屏优化 (>= 1440px) */
1341
+ @media (min-width: 1440px) {
1342
+ #main-content {
1343
+ max-width: 1400px;
1344
+ margin: 0 auto;
1345
+ width: 100%;
1346
+ }
1347
+
1348
+ .kanban-column {
1349
+ min-width: 280px;
1350
+ }
1351
+ }
1352
+
1353
+ /* 打印样式 */
1354
+ @media print {
1355
+ .navbar,
1356
+ .status-bar,
1357
+ #theme-toggle,
1358
+ #connection-status,
1359
+ #modal-overlay,
1360
+ #toast-container {
1361
+ display: none !important;
1362
+ }
1363
+
1364
+ body {
1365
+ background: #fff;
1366
+ color: #000;
1367
+ }
1368
+
1369
+ .view {
1370
+ display: block !important;
1371
+ }
1372
+
1373
+ .card {
1374
+ break-inside: avoid;
1375
+ box-shadow: none;
1376
+ border: 1px solid #ccc;
1377
+ }
1378
+ }