siluzan-tso-cli 1.1.29-beta.2 → 1.1.29-beta.21

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 (169) hide show
  1. package/README.md +1 -1
  2. package/dist/index.js +3174 -867
  3. package/dist/skill/AGENTS.md +30 -31
  4. package/dist/skill/SKILL.md +16 -33
  5. package/dist/skill/_meta.json +2 -2
  6. package/dist/skill/assets/campaign-create-keyword-test.fixed.json +10 -33
  7. package/dist/skill/assets/campaign-create-template.json +2 -0
  8. package/dist/skill/assets/campaign-create-template.md +114 -99
  9. package/dist/skill/assets/market-analysis-rules.md +55 -55
  10. package/dist/skill/assets/meta-period-report-rules.md +61 -60
  11. package/dist/skill/assets/pmax-asset-group-template.json +12 -4
  12. package/dist/skill/assets/pmax-asset-group-template.md +25 -0
  13. package/dist/skill/assets/pmax-brand-assets-template.json +25 -0
  14. package/dist/skill/assets/pmax-brand-assets-template.md +22 -0
  15. package/dist/skill/assets/pmax-brand-guidelines-enable-template.json +24 -0
  16. package/dist/skill/assets/pmax-brand-guidelines-enable-template.md +22 -0
  17. package/dist/skill/assets/pmax-create-template.json +41 -2
  18. package/dist/skill/assets/pmax-create-template.md +84 -51
  19. package/dist/skill/assets/pmax-lead-form-template.json +36 -0
  20. package/dist/skill/assets/pmax-lead-form-template.md +70 -0
  21. package/dist/skill/assets/pmax-signals-template.json +2 -6
  22. package/dist/skill/assets/pmax-whatsapp-template.json +26 -0
  23. package/dist/skill/assets/pmax-whatsapp-template.md +45 -0
  24. package/dist/skill/assets/website-diagnosis-rules.md +67 -67
  25. package/dist/skill/references/README.md +78 -65
  26. package/dist/skill/references/accounts/accounts.md +99 -105
  27. package/dist/skill/references/accounts/finance.md +23 -79
  28. package/dist/skill/references/accounts/open-account-by-media.md +84 -81
  29. package/dist/skill/references/accounts/open-account-google-ui.md +24 -24
  30. package/dist/skill/references/analytics/account-analytics.md +94 -103
  31. package/dist/skill/references/analytics/facebook-analysis-guide.md +61 -61
  32. package/dist/skill/references/analytics/google-analysis-batch.md +2 -2
  33. package/dist/skill/references/analytics/keyword-planner-workflows.md +22 -23
  34. package/dist/skill/references/analytics/market-analysis-guide.md +31 -25
  35. package/dist/skill/references/analytics/rag.md +20 -20
  36. package/dist/skill/references/analytics/reporting.md +4 -4
  37. package/dist/skill/references/analytics/website-diagnosis-guide.md +24 -24
  38. package/dist/skill/references/core/agent-conventions.md +136 -106
  39. package/dist/skill/references/core/cli-enums.md +47 -53
  40. package/dist/skill/references/core/playbooks.md +42 -41
  41. package/dist/skill/references/core/subagent-orchestration.md +40 -40
  42. package/dist/skill/references/core/tips.md +18 -61
  43. package/dist/skill/references/core/workflows.md +36 -29
  44. package/dist/skill/references/google-ads/google-ads-campaign-plan.md +25 -24
  45. package/dist/skill/references/google-ads/google-ads.md +81 -57
  46. package/dist/skill/references/google-ads/pmax-api.md +138 -34
  47. package/dist/skill/references/google-ads/rules/README.md +15 -15
  48. package/dist/skill/references/google-ads/rules/google-ads-account-audit.md +22 -22
  49. package/dist/skill/references/google-ads/rules/google-ads-compliance.md +27 -27
  50. package/dist/skill/references/google-ads/rules/google-ads-keyword-strategy.md +15 -15
  51. package/dist/skill/references/google-ads/rules/google-ads-keyword-taxonomy.md +32 -22
  52. package/dist/skill/references/google-ads/rules/google-ads-launch-plan-template.md +32 -30
  53. package/dist/skill/references/google-ads/rules/google-ads-pmax-guide.md +3 -1
  54. package/dist/skill/references/misc/tso-home.md +8 -8
  55. package/dist/skill/references/operations/clue.md +1 -1
  56. package/dist/skill/references/operations/forewarning.md +1 -1
  57. package/dist/skill/references/operations/hosted-automation-optimize-index.md +2 -2
  58. package/dist/skill/references/operations/hosted-automation-scenarios.md +5 -5
  59. package/dist/skill/references/operations/hosted-automation-self-control.md +15 -15
  60. package/dist/skill/references/operations/hosted-automation-user-catalog.md +13 -13
  61. package/dist/skill/references/operations/optimize.md +8 -8
  62. package/dist/skill/references/report-templates/README.md +45 -0
  63. package/dist/skill/references/report-templates/REPORT-WORKFLOW.md +114 -0
  64. package/dist/skill/references/report-templates/bing-period-report.md +65 -0
  65. package/dist/skill/references/report-templates/google-account-diagnosis-report.md +83 -0
  66. package/dist/skill/references/report-templates/google-ads-diagnosis.md +378 -0
  67. package/dist/skill/references/report-templates/google-inquiry-analysis.md +543 -0
  68. package/dist/skill/references/report-templates/google-period-report-excel.md +126 -0
  69. package/dist/skill/references/report-templates/google-period-report.md +60 -0
  70. package/dist/skill/references/report-templates/market-analysis-report.md +40 -0
  71. package/dist/skill/references/report-templates/meta-account-diagnosis-report.md +74 -0
  72. package/dist/skill/references/report-templates/meta-period-report-excel.md +230 -0
  73. package/dist/skill/references/report-templates/meta-period-report.md +219 -0
  74. package/dist/skill/references/report-templates/okki-weekly-google-client.md +217 -0
  75. package/dist/skill/references/report-templates/tiktok-period-report.md +56 -0
  76. package/dist/skill/references/report-templates/website-diagnosis-report.md +79 -0
  77. package/dist/skill/report-templates/README.md +16 -14
  78. package/dist/skill/report-templates/REPORT-WORKFLOW.md +13 -13
  79. package/dist/skill/report-templates/google-account-diagnosis-report.md +1 -1
  80. package/dist/skill/report-templates/google-ads-diagnosis.md +21 -21
  81. package/dist/skill/report-templates/google-inquiry-analysis.md +44 -44
  82. package/dist/skill/report-templates/google-period-report-excel.md +24 -24
  83. package/dist/skill/report-templates/google-period-report.md +23 -23
  84. package/dist/skill/report-templates/market-analysis-report.md +1 -1
  85. package/dist/skill/report-templates/meta-period-report-excel.md +72 -64
  86. package/dist/skill/report-templates/meta-period-report.html +706 -428
  87. package/dist/skill/report-templates/meta-period-report.md +61 -60
  88. package/dist/skill/report-templates/okki-weekly-google-client.md +26 -26
  89. package/dist/skill/report-templates/report-template-academic.html +1 -1
  90. package/dist/skill/report-templates/report-template-dark.html +1 -1
  91. package/dist/skill/report-templates/report-template-formal.html +1 -1
  92. package/dist/skill/report-templates/report-template-mobile.html +1 -1
  93. package/dist/skill/report-templates/report-template-onepager.html +1 -1
  94. package/dist/skill/report-templates/report-template-print.html +1 -1
  95. package/dist/skill/report-templates/report-template.html +1 -1
  96. package/dist/skill/report-templates/website-diagnosis-report.html +1731 -1653
  97. package/dist/skill/report-templates/website-diagnosis-report.md +21 -23
  98. package/dist/skill/scripts/install.ps1 +1 -1
  99. package/dist/skill/scripts/install.sh +1 -1
  100. package/dist/skill/snippets/handoff-p7-inquiry.md +5 -5
  101. package/eval/cases/accounts-entityid-vs-mediaccustomerid.scenario.json +2 -14
  102. package/eval/cases/accounts-mcc-bind-inquiry.scenario.json +1 -3
  103. package/eval/cases/accounts-single-balance-not-bulk.scenario.json +3 -14
  104. package/eval/cases/budget-display-not-raw-micros.scenario.json +1 -8
  105. package/eval/cases/clue-meta-leads-json.scenario.json +2 -14
  106. package/eval/cases/clue-tiktok-leads-json.scenario.json +2 -11
  107. package/eval/cases/destructive-account-delink-needs-confirm.scenario.json +3 -9
  108. package/eval/cases/destructive-forewarning-delete-needs-confirm.scenario.json +3 -9
  109. package/eval/cases/destructive-invoice-apply-needs-confirm.scenario.json +3 -9
  110. package/eval/cases/facebook-analysis-google-section-aliases.scenario.json +2 -11
  111. package/eval/cases/facebook-analysis-not-google-keywords.scenario.json +3 -10
  112. package/eval/cases/facebook-analysis-period-default.scenario.json +2 -14
  113. package/eval/cases/finance-invoice-info-list.scenario.json +3 -11
  114. package/eval/cases/forewarning-list-google.scenario.json +3 -14
  115. package/eval/cases/google-ads-no-structural-without-confirm.scenario.json +2 -6
  116. package/eval/cases/google-analysis-keywords-route.scenario.json +2 -14
  117. package/eval/cases/human-p1-multiturn.scenario.json +1 -5
  118. package/eval/cases/meta-single-balance-not-bulk.scenario.json +3 -17
  119. package/eval/cases/no-legacy-json-flag.scenario.json +2 -6
  120. package/eval/cases/open-account-google-noninteractive.scenario.json +1 -3
  121. package/eval/cases/open-account-tiktok-license-file.scenario.json +1 -3
  122. package/eval/cases/optimize-list-by-account.scenario.json +3 -11
  123. package/eval/cases/p1-single-account-profile.scenario.json +1 -11
  124. package/eval/cases/p2-balance-scan-bulk.scenario.json +2 -9
  125. package/eval/cases/p3-accounts-digest.scenario.json +1 -5
  126. package/eval/cases/p4-fb-meta-period-report.scenario.json +2 -12
  127. package/eval/cases/p4-period-report-window.scenario.json +1 -8
  128. package/eval/cases/pmax-asset-group-create-with-bg.scenario.json +15 -0
  129. package/eval/cases/pmax-brand-edit-routing.scenario.json +12 -0
  130. package/eval/cases/pmax-edit-not-campaign-edit.scenario.json +15 -0
  131. package/eval/cases/pmax-enable-brand-guidelines.scenario.json +15 -0
  132. package/eval/cases/pmax-no-assets-update-brand-fields.scenario.json +12 -0
  133. package/eval/cases/rag-before-keyword-expand.scenario.json +1 -11
  134. package/eval/cases/rag-list-then-query.scenario.json +2 -14
  135. package/eval/cases/report-list-google.scenario.json +2 -11
  136. package/eval/cases/report-push-list-google.scenario.json +2 -11
  137. package/eval/cases/setup-login-or-env.scenario.json +1 -3
  138. package/eval/cases/setup-siluzan-data-permission-env.scenario.json +1 -3
  139. package/eval/cases/tiktok-bc-bind-inquiry.scenario.json +2 -6
  140. package/eval/cases/time-range-user-delegates-default.scenario.json +1 -8
  141. package/eval/cases/tips-json-out-filtering.scenario.json +1 -3
  142. package/eval/cases/tips-large-json-pagination.scenario.json +1 -3
  143. package/eval/cases/uj-ad-campaign-validate-before-create-stub.scenario.json +2 -11
  144. package/eval/cases/uj-ad-outdoor-campgear-search-plan.scenario.json +1 -3
  145. package/eval/cases/uj-analytics-30d-pdf-campaign-device-geo.scenario.json +6 -18
  146. package/eval/cases/uj-analytics-compare-google-tiktok-last-month-roi.scenario.json +1 -8
  147. package/eval/cases/uj-analytics-google-weekly-trends-campaigns-keywords.scenario.json +2 -11
  148. package/eval/cases/uj-analytics-report-push-weekly-email.scenario.json +1 -3
  149. package/eval/cases/uj-finance-invoice-records-this-month.scenario.json +2 -11
  150. package/eval/cases/uj-life-newbie-siluzan-google-end-to-end.scenario.json +1 -4
  151. package/eval/cases/uj-ops-google-accounts-list-normal.scenario.json +2 -17
  152. package/eval/cases/uj-ops-google-yesterday-spend-conversions.scenario.json +2 -14
  153. package/eval/cases/uj-ops-pause-worst-adgroup-confirm.scenario.json +2 -6
  154. package/eval/cases/uj-ops-tiktok-leads-last-week.scenario.json +3 -17
  155. package/eval/cases/uj-patrol-cpc-spike-adgroups-over-15.scenario.json +1 -5
  156. package/eval/cases/uj-patrol-forewarning-create-daily-cap-3000.scenario.json +1 -3
  157. package/eval/cases/uj-patrol-forewarning-trigger-records.scenario.json +3 -17
  158. package/eval/cases/uj-patrol-google-balances-low.scenario.json +2 -11
  159. package/eval/cases/uj-roi-optimize-records-then-execute-cautiously.scenario.json +3 -14
  160. package/eval/cases/uj-roi-search-terms-add-negative-keywords.scenario.json +2 -14
  161. package/eval/stub-fixtures/facebook-analysis.json +24 -4
  162. package/eval/stub-fixtures/meta-overview.json +4 -1
  163. package/eval/stub-fixtures/pmax-asset-group-create-ok.json +12 -0
  164. package/eval/stub-fixtures/pmax-brand-assets-edit-ok.json +11 -0
  165. package/eval/stub-fixtures/pmax-brand-guidelines-enable-ok.json +11 -0
  166. package/eval/stub-fixtures/pmax-edit-ok.json +11 -0
  167. package/eval/stub-fixtures/pmax-get-bg-on.json +20 -0
  168. package/package.json +1 -1
  169. package/dist/skill/references/core/deliverable-preflight.md +0 -109
@@ -6,1572 +6,1619 @@
6
6
  生成:siluzan-tso website-diagnosis render --data ./diagnosis.json [--collect ./collect.json]
7
7
  -->
8
8
  <html lang="zh-CN">
9
+ <head>
10
+ <meta charset="UTF-8" />
11
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
12
+ <title>网站诊断报告</title>
13
+ <script>
14
+ (function () {
15
+ var k = "wd-report-theme";
16
+ var s = localStorage.getItem(k);
17
+ var dark =
18
+ s === "dark" ||
19
+ (s !== "light" && window.matchMedia("(prefers-color-scheme: dark)").matches);
20
+ if (dark) document.documentElement.setAttribute("data-theme", "dark");
21
+ })();
22
+ </script>
23
+ <script src="https://staticpn.siluzan.com/assets/slz/homeCDN/echarts.js"></script>
24
+ <style>
25
+ * {
26
+ box-sizing: border-box;
27
+ }
28
+
29
+ :root {
30
+ color-scheme: light;
31
+ --bg-page: #f5f7fa;
32
+ --surface: #ffffff;
33
+ --surface-muted: #f7f8fa;
34
+ --text-primary: #1d2129;
35
+ --text-secondary: #4e5969;
36
+ --text-muted: #86909c;
37
+ --border: #e5e6eb;
38
+ --border-light: #ebeef5;
39
+ --link: #165dff;
40
+ --accent: #165dff;
41
+ --shadow: rgba(0, 0, 0, 0.08);
42
+ --shadow-hover: rgba(0, 0, 0, 0.1);
43
+ --marketing-bg: linear-gradient(135deg, #f0f5ff 0%, #e8f3ff 100%);
44
+ --ring-track: #e5e6eb;
45
+ --table-head-bg: #f5f7fa;
46
+ --table-head-text: #909399;
47
+ --table-cell-text: #606266;
48
+ --table-title: #333333;
49
+ --priority-high-bg: #ffece8;
50
+ --priority-medium-bg: #fff3e8;
51
+ --priority-low-bg: #e8f8f2;
52
+ --lt-blue-bg: #eef6ff;
53
+ --lt-orange-bg: #fff7ec;
54
+ --lt-green-bg: #eafdf4;
55
+ --lt-purple-bg: #f4f2ff;
56
+ --status-excellent-bg: #e8f8f2;
57
+ --status-good-bg: #e8f3ff;
58
+ --status-normal-bg: #fff3e8;
59
+ --status-poor-bg: #ffece8;
60
+ --btn-theme-bg: #ffffff;
61
+ --btn-theme-border: #e5e6eb;
62
+ --btn-theme-text: #4e5969;
63
+ }
64
+
65
+ html[data-theme="dark"] {
66
+ color-scheme: dark;
67
+ --bg-page: #0f1419;
68
+ --surface: #1a1f26;
69
+ --surface-muted: #232a33;
70
+ --text-primary: #e8eaed;
71
+ --text-secondary: #a8b0bb;
72
+ --text-muted: #7a8490;
73
+ --border: #2e3742;
74
+ --border-light: #2a323d;
75
+ --link: #6ba1ff;
76
+ --accent: #4d8dff;
77
+ --shadow: rgba(0, 0, 0, 0.35);
78
+ --shadow-hover: rgba(0, 0, 0, 0.45);
79
+ --marketing-bg: linear-gradient(135deg, #1a2438 0%, #152030 100%);
80
+ --ring-track: #3a4452;
81
+ --table-head-bg: #232a33;
82
+ --table-head-text: #8b949e;
83
+ --table-cell-text: #a8b0bb;
84
+ --table-title: #c9d1d9;
85
+ --priority-high-bg: #3d2224;
86
+ --priority-medium-bg: #3d2e1a;
87
+ --priority-low-bg: #1a3328;
88
+ --lt-blue-bg: #1a2840;
89
+ --lt-orange-bg: #332818;
90
+ --lt-green-bg: #1a3328;
91
+ --lt-purple-bg: #2a2240;
92
+ --status-excellent-bg: #1a3328;
93
+ --status-good-bg: #1a2840;
94
+ --status-normal-bg: #332818;
95
+ --status-poor-bg: #3d2224;
96
+ --btn-theme-bg: #232a33;
97
+ --btn-theme-border: #2e3742;
98
+ --btn-theme-text: #a8b0bb;
99
+ }
100
+
101
+ body {
102
+ margin: 0;
103
+ font-family:
104
+ -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial,
105
+ "PingFang SC", "Microsoft YaHei", sans-serif;
106
+ background: var(--bg-page);
107
+ color: var(--text-primary);
108
+ transition:
109
+ background 0.2s ease,
110
+ color 0.2s ease;
111
+ }
112
+
113
+ a {
114
+ color: var(--link);
115
+ text-decoration: none;
116
+ }
117
+
118
+ a:hover {
119
+ text-decoration: underline;
120
+ }
121
+
122
+ #app {
123
+ min-height: 100vh;
124
+ }
125
+
126
+ /* common.scss */
127
+ .report-container {
128
+ background: var(--bg-page);
129
+ container-type: inline-size;
130
+ padding: 24px 16px 40px;
131
+ }
132
+
133
+ .report-content {
134
+ max-width: 1200px;
135
+ margin: 0 auto;
136
+ background: var(--surface);
137
+ border-radius: 8px;
138
+ padding: 28px;
139
+ box-shadow: 0 2px 8px var(--shadow);
140
+ transition:
141
+ background 0.2s ease,
142
+ box-shadow 0.2s ease;
143
+ }
144
+
145
+ .report-section {
146
+ margin-bottom: 40px;
147
+ background: var(--surface);
148
+ border-radius: 12px;
149
+ }
150
+
151
+ .report-section:last-child {
152
+ margin-bottom: 0;
153
+ }
154
+
155
+ .section-header {
156
+ margin-bottom: 20px;
157
+ }
158
+
159
+ .section-header h2 {
160
+ font-size: 24px;
161
+ font-weight: 600;
162
+ color: var(--text-primary);
163
+ margin: 0;
164
+ padding-bottom: 12px;
165
+ display: inline-block;
166
+ }
167
+
168
+ .marketing-text {
169
+ padding: 16px;
170
+ background: var(--marketing-bg);
171
+ border-left: 4px solid var(--accent);
172
+ border-radius: 4px;
173
+ margin-bottom: 24px;
174
+ font-size: 15px;
175
+ line-height: 1.8;
176
+ color: var(--text-primary);
177
+ }
178
+
179
+ .marketing-text p {
180
+ margin: 0;
181
+ }
182
+
183
+ .marketing-text strong {
184
+ color: var(--accent);
185
+ font-size: 20px;
186
+ font-weight: 700;
187
+ margin: 0 4px;
188
+ }
189
+
190
+ /* ReportHeader */
191
+ .report-header {
192
+ margin-bottom: 32px;
193
+ padding-bottom: 24px;
194
+ border-bottom: 2px solid var(--border);
195
+ }
196
+
197
+ .header-title-wrapper {
198
+ display: flex;
199
+ justify-content: space-between;
200
+ align-items: center;
201
+ margin-bottom: 16px;
202
+ }
203
+
204
+ .main-title {
205
+ flex: 1;
206
+ font-size: 32px;
207
+ font-weight: 700;
208
+ color: var(--text-primary);
209
+ margin: 0;
210
+ }
211
+
212
+ .header-actions {
213
+ display: flex;
214
+ align-items: center;
215
+ gap: 8px;
216
+ flex-shrink: 0;
217
+ }
218
+
219
+ .btn-theme {
220
+ display: flex;
221
+ align-items: center;
222
+ gap: 6px;
223
+ padding: 10px 16px;
224
+ background: var(--btn-theme-bg);
225
+ border: 1px solid var(--btn-theme-border);
226
+ border-radius: 6px;
227
+ color: var(--btn-theme-text);
228
+ font-size: 14px;
229
+ font-weight: 500;
230
+ cursor: pointer;
231
+ transition:
232
+ background 0.2s ease,
233
+ border-color 0.2s ease,
234
+ color 0.2s ease;
235
+ }
236
+
237
+ .btn-theme:hover {
238
+ border-color: var(--accent);
239
+ color: var(--accent);
240
+ }
241
+
242
+ .btn-export {
243
+ display: flex;
244
+ align-items: center;
245
+ gap: 6px;
246
+ padding: 10px 20px;
247
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
248
+ border: none;
249
+ border-radius: 6px;
250
+ color: #ffffff;
251
+ font-size: 14px;
252
+ font-weight: 500;
253
+ cursor: pointer;
254
+ box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3);
255
+ }
256
+
257
+ .btn-export:hover {
258
+ transform: translateY(-2px);
259
+ box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
260
+ }
261
+
262
+ .header-info {
263
+ display: flex;
264
+ align-items: center;
265
+ gap: 16px;
266
+ flex-wrap: wrap;
267
+ }
268
+
269
+ .info-item {
270
+ font-size: 15px;
271
+ color: var(--text-secondary);
272
+ font-weight: 500;
273
+ }
274
+
275
+ .info-separator {
276
+ color: var(--border);
277
+ font-size: 15px;
278
+ }
279
+
280
+ .website-url {
281
+ cursor: pointer;
282
+ color: var(--link) !important;
283
+ word-break: break-all;
284
+ }
9
285
 
10
- <head>
11
- <meta charset="UTF-8" />
12
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
13
- <title>网站诊断报告</title>
14
- <script>
15
- (function () {
16
- var k = "wd-report-theme";
17
- var s = localStorage.getItem(k);
18
- var dark = s === "dark" || (s !== "light" && window.matchMedia("(prefers-color-scheme: dark)").matches);
19
- if (dark) document.documentElement.setAttribute("data-theme", "dark");
20
- })();
21
- </script>
22
- <script src="https://staticpn.siluzan.com/assets/slz/homeCDN/chart.umd.min.js"></script>
23
- <style>
24
- * {
25
- box-sizing: border-box;
26
- }
27
-
28
- :root {
29
- color-scheme: light;
30
- --bg-page: #f5f7fa;
31
- --surface: #ffffff;
32
- --surface-muted: #f7f8fa;
33
- --text-primary: #1d2129;
34
- --text-secondary: #4e5969;
35
- --text-muted: #86909c;
36
- --border: #e5e6eb;
37
- --border-light: #ebeef5;
38
- --link: #165dff;
39
- --accent: #165dff;
40
- --shadow: rgba(0, 0, 0, 0.08);
41
- --shadow-hover: rgba(0, 0, 0, 0.1);
42
- --marketing-bg: linear-gradient(135deg, #f0f5ff 0%, #e8f3ff 100%);
43
- --ring-track: #e5e6eb;
44
- --table-head-bg: #f5f7fa;
45
- --table-head-text: #909399;
46
- --table-cell-text: #606266;
47
- --table-title: #333333;
48
- --priority-high-bg: #ffece8;
49
- --priority-medium-bg: #fff3e8;
50
- --priority-low-bg: #e8f8f2;
51
- --lt-blue-bg: #eef6ff;
52
- --lt-orange-bg: #fff7ec;
53
- --lt-green-bg: #eafdf4;
54
- --lt-purple-bg: #f4f2ff;
55
- --status-excellent-bg: #e8f8f2;
56
- --status-good-bg: #e8f3ff;
57
- --status-normal-bg: #fff3e8;
58
- --status-poor-bg: #ffece8;
59
- --btn-theme-bg: #ffffff;
60
- --btn-theme-border: #e5e6eb;
61
- --btn-theme-text: #4e5969;
62
- }
63
-
64
- html[data-theme="dark"] {
65
- color-scheme: dark;
66
- --bg-page: #0f1419;
67
- --surface: #1a1f26;
68
- --surface-muted: #232a33;
69
- --text-primary: #e8eaed;
70
- --text-secondary: #a8b0bb;
71
- --text-muted: #7a8490;
72
- --border: #2e3742;
73
- --border-light: #2a323d;
74
- --link: #6ba1ff;
75
- --accent: #4d8dff;
76
- --shadow: rgba(0, 0, 0, 0.35);
77
- --shadow-hover: rgba(0, 0, 0, 0.45);
78
- --marketing-bg: linear-gradient(135deg, #1a2438 0%, #152030 100%);
79
- --ring-track: #3a4452;
80
- --table-head-bg: #232a33;
81
- --table-head-text: #8b949e;
82
- --table-cell-text: #a8b0bb;
83
- --table-title: #c9d1d9;
84
- --priority-high-bg: #3d2224;
85
- --priority-medium-bg: #3d2e1a;
86
- --priority-low-bg: #1a3328;
87
- --lt-blue-bg: #1a2840;
88
- --lt-orange-bg: #332818;
89
- --lt-green-bg: #1a3328;
90
- --lt-purple-bg: #2a2240;
91
- --status-excellent-bg: #1a3328;
92
- --status-good-bg: #1a2840;
93
- --status-normal-bg: #332818;
94
- --status-poor-bg: #3d2224;
95
- --btn-theme-bg: #232a33;
96
- --btn-theme-border: #2e3742;
97
- --btn-theme-text: #a8b0bb;
98
- }
99
-
100
- body {
101
- margin: 0;
102
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial,
103
- "PingFang SC", "Microsoft YaHei", sans-serif;
104
- background: var(--bg-page);
105
- color: var(--text-primary);
106
- transition: background 0.2s ease, color 0.2s ease;
107
- }
108
-
109
- a {
110
- color: var(--link);
111
- text-decoration: none;
112
- }
113
-
114
- a:hover {
115
- text-decoration: underline;
116
- }
117
-
118
- #app {
119
- min-height: 100vh;
120
- }
121
-
122
- /* common.scss */
123
- .report-container {
124
- background: var(--bg-page);
125
- container-type: inline-size;
126
- padding: 24px 16px 40px;
127
- }
128
-
129
- .report-content {
130
- max-width: 1200px;
131
- margin: 0 auto;
132
- background: var(--surface);
133
- border-radius: 8px;
134
- padding: 28px;
135
- box-shadow: 0 2px 8px var(--shadow);
136
- transition: background 0.2s ease, box-shadow 0.2s ease;
137
- }
138
-
139
- .report-section {
140
- margin-bottom: 40px;
141
- background: var(--surface);
142
- border-radius: 12px;
143
- }
144
-
145
- .report-section:last-child {
146
- margin-bottom: 0;
147
- }
148
-
149
- .section-header {
150
- margin-bottom: 20px;
151
- }
152
-
153
- .section-header h2 {
154
- font-size: 24px;
155
- font-weight: 600;
156
- color: var(--text-primary);
157
- margin: 0;
158
- padding-bottom: 12px;
159
- display: inline-block;
160
- }
161
-
162
- .marketing-text {
163
- padding: 16px;
164
- background: var(--marketing-bg);
165
- border-left: 4px solid var(--accent);
166
- border-radius: 4px;
167
- margin-bottom: 24px;
168
- font-size: 15px;
169
- line-height: 1.8;
170
- color: var(--text-primary);
171
- }
172
-
173
- .marketing-text p {
174
- margin: 0;
175
- }
176
-
177
- .marketing-text strong {
178
- color: var(--accent);
179
- font-size: 20px;
180
- font-weight: 700;
181
- margin: 0 4px;
182
- }
183
-
184
- /* ReportHeader */
185
- .report-header {
186
- margin-bottom: 32px;
187
- padding-bottom: 24px;
188
- border-bottom: 2px solid var(--border);
189
- }
190
-
191
- .header-title-wrapper {
192
- display: flex;
193
- justify-content: space-between;
194
- align-items: center;
195
- margin-bottom: 16px;
196
- }
197
-
198
- .main-title {
199
- flex: 1;
200
- font-size: 32px;
201
- font-weight: 700;
202
- color: var(--text-primary);
203
- margin: 0;
204
- }
205
-
206
- .header-actions {
207
- display: flex;
208
- align-items: center;
209
- gap: 8px;
210
- flex-shrink: 0;
211
- }
212
-
213
- .btn-theme {
214
- display: flex;
215
- align-items: center;
216
- gap: 6px;
217
- padding: 10px 16px;
218
- background: var(--btn-theme-bg);
219
- border: 1px solid var(--btn-theme-border);
220
- border-radius: 6px;
221
- color: var(--btn-theme-text);
222
- font-size: 14px;
223
- font-weight: 500;
224
- cursor: pointer;
225
- transition: background 0.2s ease, border-color 0.2s ease, color 0.2s ease;
226
- }
227
-
228
- .btn-theme:hover {
229
- border-color: var(--accent);
230
- color: var(--accent);
231
- }
232
-
233
- .btn-export {
234
- display: flex;
235
- align-items: center;
236
- gap: 6px;
237
- padding: 10px 20px;
238
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
239
- border: none;
240
- border-radius: 6px;
241
- color: #ffffff;
242
- font-size: 14px;
243
- font-weight: 500;
244
- cursor: pointer;
245
- box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3);
246
- }
247
-
248
- .btn-export:hover {
249
- transform: translateY(-2px);
250
- box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
251
- }
252
-
253
- .header-info {
254
- display: flex;
255
- align-items: center;
256
- gap: 16px;
257
- flex-wrap: wrap;
258
- }
259
-
260
- .info-item {
261
- font-size: 15px;
262
- color: var(--text-secondary);
263
- font-weight: 500;
264
- }
265
-
266
- .info-separator {
267
- color: var(--border);
268
- font-size: 15px;
269
- }
270
-
271
- .website-url {
272
- cursor: pointer;
273
- color: var(--link) !important;
274
- word-break: break-all;
275
- }
276
-
277
- /* HealthOverview */
278
- .health-overview {
279
- display: flex;
280
- gap: 32px;
281
- margin-bottom: 24px;
282
- align-items: center;
283
- }
284
-
285
- .website-score-wrapper {
286
- display: flex;
287
- align-items: center;
288
- flex: 1;
289
- justify-content: center;
290
- }
291
-
292
- .score-ring-wrapper {
293
- flex-shrink: 0;
294
- display: flex;
295
- flex-direction: column;
296
- align-items: center;
297
- position: relative;
298
- padding: 20px;
299
- width: 250px;
300
- }
301
-
302
- .score-center {
303
- position: absolute;
304
- top: 110px;
305
- left: 50%;
306
- transform: translate(-50%, -50%);
307
- text-align: center;
308
- }
309
-
310
- .score-number {
311
- font-size: 42px;
312
- font-weight: 700;
313
- color: var(--text-primary);
314
- line-height: 1;
315
- }
316
-
317
- .score-total {
318
- font-size: 16px;
319
- color: var(--text-muted);
320
- margin-top: 4px;
321
- }
322
-
323
- .score-rating {
324
- margin-top: 12px;
325
- font-size: 20px;
326
- font-weight: 600;
327
- }
328
-
329
- .score-desc {
330
- margin-top: 8px;
331
- font-size: 14px;
332
- color: var(--text-secondary);
333
- text-align: center;
334
- max-width: 200px;
335
- line-height: 1.5;
336
- }
337
-
338
- .divider-line {
339
- width: 1px;
340
- height: 300px;
341
- background-color: var(--border);
342
- }
343
-
344
- .radar-chart {
345
- flex: 1;
346
- background: var(--surface);
347
- border-radius: 8px;
348
- padding: 16px;
349
- display: flex;
350
- flex-direction: column;
351
- }
352
-
353
- .radar-chart-title {
354
- text-align: center;
355
- font-size: 14px;
356
- color: var(--text-secondary);
357
- margin-top: 12px;
358
- font-weight: 500;
359
- }
360
-
361
- /* RiskMap */
362
- .risk-map-content {
363
- display: flex;
364
- gap: 24px;
365
- align-items: flex-start;
366
- }
367
-
368
- .bar-chart-wrapper {
369
- flex-shrink: 0;
370
- width: 40%;
371
- height: 294px;
372
- background: var(--surface);
373
- border: 1px solid var(--border);
374
- border-radius: 8px;
375
- padding: 16px;
376
- }
377
-
378
- .risk-table-wrapper {
379
- flex: 1;
380
- height: 327px;
381
- }
382
-
383
- .risk-table-title {
384
- height: 24px;
385
- font-size: 16px;
386
- font-weight: bold;
387
- text-align: right;
388
- color: var(--table-title);
389
- margin: 0 0 8px;
390
- }
391
-
392
- .risk-table {
393
- width: 100%;
394
- border-collapse: collapse;
395
- font-size: 14px;
396
- }
397
-
398
- .risk-table th,
399
- .risk-table td {
400
- border: 1px solid var(--border-light);
401
- padding: 10px 12px;
402
- color: var(--table-cell-text);
403
- }
404
-
405
- .risk-table th {
406
- background: var(--table-head-bg);
407
- color: var(--table-head-text);
408
- font-weight: 500;
409
- text-align: left;
410
- }
411
-
412
- .risk-table .tc {
413
- text-align: center;
414
- }
415
-
416
- /* ModuleDetail */
417
- .module-detail {
418
- margin-bottom: 32px;
419
- }
420
-
421
- .module-detail:last-child {
422
- margin-bottom: 0;
423
- }
424
-
425
- .module-header {
426
- display: flex;
427
- justify-content: space-between;
428
- align-items: center;
429
- margin-bottom: 16px;
430
- padding: 16px;
431
- background: var(--surface-muted);
432
- border-radius: 8px;
433
- gap: 16px;
434
- flex-wrap: wrap;
435
- }
436
-
437
- .module-header-left {
438
- display: flex;
439
- align-items: center;
440
- gap: 16px;
441
- flex: 1;
442
- flex-wrap: wrap;
443
- }
444
-
445
- .module-title {
446
- font-size: 18px;
447
- font-weight: 600;
448
- color: var(--text-primary);
449
- margin: 0;
450
- padding-left: 12px;
451
- border-left: 4px solid #165dff;
452
- white-space: nowrap;
453
- }
454
-
455
- .module-description {
456
- font-size: 14px;
457
- color: var(--text-secondary);
458
- line-height: 1.5;
459
- }
460
-
461
- .module-score-info {
462
- font-size: 14px;
463
- color: var(--text-secondary);
464
- white-space: nowrap;
465
- }
466
-
467
- .module-score-info .score-value {
468
- font-size: 20px;
469
- font-weight: 700;
470
- color: #35bd4b;
471
- margin: 0 4px;
472
- }
473
-
474
- .module-score-info .total-score-value {
475
- font-weight: 600;
476
- color: var(--text-primary);
477
- margin: 0 4px;
478
- }
479
-
480
- .module-items-grid {
481
- display: grid;
482
- gap: 20px;
483
- }
484
-
485
- .module-item-card {
486
- background: var(--surface);
487
- border: 1px solid var(--border);
488
- border-radius: 12px;
489
- padding: 20px;
490
- display: flex;
491
- flex-direction: column;
492
- gap: 16px;
493
- min-width: 0;
494
- }
495
-
496
- .module-item-card:hover {
497
- box-shadow: 0 4px 12px var(--shadow-hover);
498
- transform: translateY(-2px);
499
- }
500
-
501
- .module-item-card .card-header {
502
- display: flex;
503
- justify-content: space-between;
504
- align-items: flex-start;
505
- gap: 12px;
506
- }
507
-
508
- .item-title {
509
- font-size: 16px;
510
- font-weight: 600;
511
- color: var(--text-primary);
512
- margin: 0;
513
- flex: 1;
514
- line-height: 1.5;
515
- word-break: break-word;
516
- }
517
-
518
- .status-badge {
519
- flex-shrink: 0;
520
- padding: 4px 12px;
521
- border-radius: 4px;
522
- font-size: 12px;
523
- font-weight: 500;
524
- white-space: nowrap;
525
- }
526
-
527
- .item-description {
528
- font-size: 14px;
529
- color: var(--text-secondary);
530
- line-height: 1.6;
531
- margin: 0;
532
- word-break: break-word;
533
- }
534
-
535
- .score-info {
536
- display: flex;
537
- justify-content: space-between;
538
- align-items: center;
539
- margin-bottom: 8px;
540
- }
541
-
542
- .score-label {
543
- font-size: 14px;
544
- color: var(--text-muted);
545
- }
546
-
547
- .score-percentage {
548
- font-size: 16px;
549
- font-weight: 600;
550
- color: var(--text-primary);
551
- }
552
-
553
- .progress-bar {
554
- width: 100%;
555
- height: 12px;
556
- background: var(--ring-track);
557
- border-radius: 10px;
558
- overflow: hidden;
559
- }
560
-
561
- .progress-fill {
562
- height: 100%;
563
- border-radius: 12px;
564
- }
565
-
566
- .suggestion-box {
567
- display: flex;
568
- align-items: flex-start;
569
- gap: 8px;
570
- padding: 12px;
571
- border-left: 3px solid #ff7d00;
572
- border-radius: 4px;
573
- margin-top: 4px;
574
- }
575
-
576
- .suggestion-text {
577
- font-size: 13px;
578
- color: var(--text-secondary);
579
- line-height: 1.5;
580
- word-break: break-word;
581
- }
582
-
583
- /* LoadingSpeed */
584
- .loading-speed-section {
585
- margin-bottom: 24px;
586
- padding: 24px;
587
- background: var(--surface);
588
- border: 1px solid var(--border);
589
- border-radius: 12px;
590
- }
591
-
592
- .loading-speed-header {
593
- display: flex;
594
- justify-content: space-between;
595
- align-items: center;
596
- margin-bottom: 8px;
597
- }
598
-
599
- .loading-speed-title {
600
- font-size: 16px;
601
- font-weight: 600;
602
- color: var(--text-primary);
603
- margin: 0;
604
- }
605
-
606
- .loading-speed-status {
607
- padding: 4px 12px;
608
- border-radius: 4px;
609
- font-size: 12px;
610
- font-weight: 500;
611
- }
612
-
613
- .loading-speed-status.status-excellent {
614
- background: var(--status-excellent-bg);
615
- color: #00b42a;
616
- }
617
-
618
- .loading-speed-status.status-good {
619
- background: var(--status-good-bg);
620
- color: #165dff;
621
- }
622
-
623
- .loading-speed-status.status-normal {
624
- background: var(--status-normal-bg);
625
- color: #ff7d00;
626
- }
627
-
628
- .loading-speed-status.status-poor {
629
- background: var(--status-poor-bg);
630
- color: #f53f3f;
631
- }
632
-
633
- .loading-speed-desc {
634
- font-size: 14px;
635
- color: var(--text-secondary);
636
- margin: 0 0 24px;
637
- line-height: 1.6;
638
- }
639
-
640
- .loading-speed-charts {
641
- display: flex;
642
- justify-content: space-around;
643
- gap: 40px;
644
- margin-bottom: 24px;
645
- }
646
-
647
- .speed-chart-item {
648
- flex: 1;
649
- display: flex;
650
- flex-direction: column;
651
- align-items: center;
652
- }
653
-
654
- .chart-title {
655
- font-size: 14px;
656
- font-weight: 500;
657
- color: var(--text-primary);
658
- margin-bottom: 16px;
659
- }
660
-
661
- .speed-details {
662
- width: 100%;
663
- display: flex;
664
- flex-direction: column;
665
- gap: 8px;
666
- }
667
-
668
- .speed-detail-item {
669
- font-size: 13px;
670
- color: var(--text-secondary);
671
- text-align: center;
672
- }
673
-
674
- .speed-value {
675
- font-weight: 600;
676
- }
677
-
678
- .speed-legend {
679
- display: flex;
680
- justify-content: center;
681
- gap: 24px;
682
- padding-top: 16px;
683
- border-top: 1px solid var(--border);
684
- }
685
-
686
- .legend-item {
687
- display: flex;
688
- align-items: center;
689
- gap: 8px;
690
- }
691
-
692
- .legend-icon {
693
- width: 12px;
694
- height: 12px;
695
- border-radius: 2px;
696
- }
697
-
698
- .legend-text {
699
- font-size: 13px;
700
- color: var(--text-secondary);
701
- }
702
-
703
- /* PriorityPlan */
704
- .priority-columns {
705
- display: grid;
706
- grid-template-columns: repeat(3, 1fr);
707
- gap: 24px;
708
- }
709
-
710
- .priority-column {
711
- display: flex;
712
- flex-direction: column;
713
- padding: 20px;
714
- border-radius: 8px;
715
- }
716
-
717
- .priority-high {
718
- background: var(--priority-high-bg);
719
- }
720
-
721
- .priority-high .priority-title {
722
- color: #991b25;
723
- }
724
-
725
- .priority-high .priority-badge {
726
- color: #991b25;
727
- border: 1px solid #991b25;
728
- }
729
-
730
- .priority-high .item-bullet,
731
- .priority-high .impact-icon,
732
- .priority-high .impact-text {
733
- color: #f53f3f !important;
734
- }
735
-
736
- .priority-medium {
737
- background: var(--priority-medium-bg);
738
- --color: #ff7d00;
739
- }
740
-
741
- .priority-medium .priority-title {
742
- color: var(--color);
743
- }
744
-
745
- .priority-medium .priority-badge {
746
- color: var(--color);
747
- border: 1px solid var(--color);
748
- }
749
-
750
- .priority-medium .item-bullet,
751
- .priority-medium .impact-icon,
752
- .priority-medium .impact-text {
753
- color: var(--color) !important;
754
- }
755
-
756
- .priority-low {
757
- background: var(--priority-low-bg);
758
- --color: #00b42a;
759
- }
760
-
761
- .priority-low .priority-title {
762
- color: var(--color);
763
- }
764
-
765
- .priority-low .priority-badge {
766
- color: var(--color);
767
- border: 1px solid var(--color);
768
- }
769
-
770
- .priority-low .item-bullet,
771
- .priority-low .impact-icon,
772
- .priority-low .impact-text {
773
- color: var(--color) !important;
774
- }
775
-
776
- .priority-header-top {
777
- display: flex;
778
- align-items: center;
779
- gap: 12px;
780
- margin-bottom: 8px;
781
- }
782
-
783
- .priority-icon {
784
- font-size: 24px;
785
- line-height: 1;
786
- }
787
-
788
- .priority-info {
789
- display: flex;
790
- justify-content: space-between;
791
- align-items: center;
792
- flex: 1;
793
- gap: 8px;
794
- }
795
-
796
- .priority-title {
797
- font-size: 18px;
798
- font-weight: 700;
799
- margin: 0;
800
- line-height: 1.3;
801
- }
802
-
803
- .priority-subtitle {
804
- font-size: 13px;
805
- color: var(--text-secondary);
806
- margin: 0 0 0 36px;
807
- line-height: 1.5;
808
- }
809
-
810
- .priority-badge {
811
- padding: 4px 12px;
812
- border-radius: 4px;
813
- font-size: 13px;
814
- font-weight: 500;
815
- white-space: nowrap;
816
- background: transparent;
817
- }
818
-
819
- .priority-items {
820
- display: flex;
821
- flex-direction: column;
822
- gap: 16px;
823
- }
824
-
825
- .priority-item-card {
826
- --content-margin-left: 14px;
827
- background: var(--surface);
828
- border: 1px solid var(--border);
829
- border-radius: 8px;
830
- padding: 16px;
831
- }
832
-
833
- .priority-item-card .item-header {
834
- display: flex;
835
- align-items: center;
836
- gap: 8px;
837
- margin-bottom: 8px;
838
- }
839
-
840
- .item-bullet {
841
- font-size: 20px;
842
- line-height: 1.4;
843
- font-weight: bold;
844
- color: var(--text-primary);
845
- }
846
-
847
- .item-title-text {
848
- font-size: 15px;
849
- font-weight: 700;
850
- color: var(--text-primary);
851
- margin: 0;
852
- line-height: 1.4;
853
- }
854
-
855
- .priority-item-card .item-description {
856
- font-size: 14px;
857
- color: var(--text-secondary);
858
- line-height: 1.6;
859
- margin: 0 0 12px var(--content-margin-left);
860
- }
861
-
862
- .item-impact {
863
- display: flex;
864
- align-items: flex-start;
865
- gap: 4px;
866
- margin-left: var(--content-margin-left);
867
- }
868
-
869
- .impact-icon {
870
- flex-shrink: 0;
871
- font-size: 14px;
872
- font-weight: bold;
873
- line-height: 1.6;
874
- }
875
-
876
- .impact-text {
877
- font-size: 14px;
878
- line-height: 1.6;
879
- }
880
-
881
- /* LongtermValue */
882
- .longterm-cards {
883
- display: grid;
884
- grid-template-columns: repeat(2, 1fr);
885
- gap: 20px;
886
- }
887
-
888
- .longterm-card {
889
- display: flex;
890
- align-items: center;
891
- gap: 16px;
892
- padding: 24px;
893
- border-radius: 12px;
894
- border-left: 4px solid;
895
- }
896
-
897
- .longterm-card:hover {
898
- transform: translateY(-2px);
899
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
900
- }
901
-
902
- .card-blue {
903
- background: var(--lt-blue-bg);
904
- border-left-color: #165dff;
905
- }
906
-
907
- .card-orange {
908
- background: var(--lt-orange-bg);
909
- border-left-color: #ff7d00;
910
- }
911
-
912
- .card-green {
913
- background: var(--lt-green-bg);
914
- border-left-color: #00b42a;
915
- }
916
-
917
- .card-purple {
918
- background: var(--lt-purple-bg);
919
- border-left-color: #722ed1;
920
- }
921
-
922
- .card-blue .card-icon {
923
- --bgc: #dbeafe;
924
- }
925
-
926
- .card-orange .card-icon {
927
- --bgc: #ffedd5;
928
- }
929
-
930
- .card-green .card-icon {
931
- --bgc: #dcfce7;
932
- }
933
-
934
- .card-purple .card-icon {
935
- --bgc: #f3e8ff;
936
- }
937
-
938
- html[data-theme="dark"] .card-blue .card-icon {
939
- --bgc: #1e3a5f;
940
- }
941
-
942
- html[data-theme="dark"] .card-orange .card-icon {
943
- --bgc: #4a3520;
944
- }
945
-
946
- html[data-theme="dark"] .card-green .card-icon {
947
- --bgc: #1a4030;
948
- }
949
-
950
- html[data-theme="dark"] .card-purple .card-icon {
951
- --bgc: #3d2d5c;
952
- }
953
-
954
- .card-icon {
955
- flex-shrink: 0;
956
- width: 46px;
957
- height: 46px;
958
- display: flex;
959
- align-items: center;
960
- justify-content: center;
961
- font-size: 20px;
962
- border-radius: 50%;
963
- background-color: var(--bgc);
964
- }
965
-
966
- .card-title {
967
- font-size: 16px;
968
- font-weight: 700;
969
- color: var(--text-primary);
970
- margin: 0 0 8px;
971
- line-height: 1.3;
972
- }
973
-
974
- .card-desc {
975
- font-size: 14px;
976
- color: var(--text-secondary);
977
- margin: 0;
978
- line-height: 1.5;
979
- }
980
-
981
- @container (max-width: 860px) {
286
+ /* HealthOverview */
982
287
  .health-overview {
288
+ display: flex;
289
+ gap: 32px;
290
+ margin-bottom: 24px;
291
+ align-items: center;
292
+ }
293
+
294
+ .website-score-wrapper {
295
+ display: flex;
296
+ align-items: center;
297
+ flex: 1;
298
+ justify-content: center;
299
+ }
300
+
301
+ .score-ring-wrapper {
302
+ flex-shrink: 0;
303
+ display: flex;
983
304
  flex-direction: column;
984
- gap: 20px;
305
+ align-items: center;
306
+ position: relative;
307
+ padding: 20px;
308
+ width: 250px;
309
+ }
310
+
311
+ .score-center {
312
+ position: absolute;
313
+ top: 110px;
314
+ left: 50%;
315
+ transform: translate(-50%, -50%);
316
+ text-align: center;
317
+ }
318
+
319
+ .score-number {
320
+ font-size: 42px;
321
+ font-weight: 700;
322
+ color: var(--text-primary);
323
+ line-height: 1;
324
+ }
325
+
326
+ .score-total {
327
+ font-size: 16px;
328
+ color: var(--text-muted);
329
+ margin-top: 4px;
330
+ }
331
+
332
+ .score-rating {
333
+ margin-top: 12px;
334
+ font-size: 20px;
335
+ font-weight: 600;
336
+ }
337
+
338
+ .score-desc {
339
+ margin-top: 8px;
340
+ font-size: 14px;
341
+ color: var(--text-secondary);
342
+ text-align: center;
343
+ max-width: 200px;
344
+ line-height: 1.5;
985
345
  }
986
346
 
987
347
  .divider-line {
988
- width: 90%;
989
- height: 1px;
348
+ width: 1px;
349
+ height: 300px;
350
+ background-color: var(--border);
990
351
  }
991
352
 
992
353
  .radar-chart {
993
- width: 100%;
354
+ flex: 1;
355
+ background: var(--surface);
356
+ border-radius: 8px;
357
+ padding: 16px;
358
+ display: flex;
359
+ flex-direction: column;
994
360
  }
995
- }
996
361
 
997
- @container (max-width: 900px) {
362
+ .radar-chart-title {
363
+ text-align: center;
364
+ font-size: 14px;
365
+ color: var(--text-secondary);
366
+ margin-top: 12px;
367
+ font-weight: 500;
368
+ }
369
+
370
+ /* RiskMap */
998
371
  .risk-map-content {
999
- flex-direction: column;
372
+ display: flex;
373
+ gap: 24px;
374
+ align-items: flex-start;
1000
375
  }
1001
376
 
1002
377
  .bar-chart-wrapper {
1003
- width: 100%;
1004
- height: 300px;
378
+ flex-shrink: 0;
379
+ width: 40%;
380
+ height: 294px;
381
+ background: var(--surface);
382
+ border: 1px solid var(--border);
383
+ border-radius: 8px;
384
+ padding: 16px;
1005
385
  }
1006
386
 
1007
387
  .risk-table-wrapper {
1008
- width: 100%;
1009
- height: auto;
388
+ flex: 1;
389
+ height: 327px;
1010
390
  }
1011
391
 
1012
392
  .risk-table-title {
1013
- display: none;
393
+ height: 24px;
394
+ font-size: 16px;
395
+ font-weight: bold;
396
+ text-align: right;
397
+ color: var(--table-title);
398
+ margin: 0 0 8px;
1014
399
  }
1015
- }
1016
400
 
1017
- @container (max-width: 1200px) {
1018
- .priority-columns {
1019
- grid-template-columns: 1fr;
401
+ .risk-table {
402
+ width: 100%;
403
+ border-collapse: collapse;
404
+ font-size: 14px;
1020
405
  }
1021
406
 
1022
- .priority-items {
1023
- display: grid !important;
1024
- grid-template-columns: repeat(2, 1fr) !important;
407
+ .risk-table th,
408
+ .risk-table td {
409
+ border: 1px solid var(--border-light);
410
+ padding: 10px 12px;
411
+ color: var(--table-cell-text);
412
+ }
413
+
414
+ .risk-table th {
415
+ background: var(--table-head-bg);
416
+ color: var(--table-head-text);
417
+ font-weight: 500;
418
+ text-align: left;
419
+ }
420
+
421
+ .risk-table .tc {
422
+ text-align: center;
423
+ }
424
+
425
+ /* ModuleDetail */
426
+ .module-detail {
427
+ margin-bottom: 32px;
428
+ }
429
+
430
+ .module-detail:last-child {
431
+ margin-bottom: 0;
432
+ }
433
+
434
+ .module-header {
435
+ display: flex;
436
+ justify-content: space-between;
437
+ align-items: center;
438
+ margin-bottom: 16px;
439
+ padding: 16px;
440
+ background: var(--surface-muted);
441
+ border-radius: 8px;
442
+ gap: 16px;
443
+ flex-wrap: wrap;
444
+ }
445
+
446
+ .module-header-left {
447
+ display: flex;
448
+ align-items: center;
449
+ gap: 16px;
450
+ flex: 1;
451
+ flex-wrap: wrap;
452
+ }
453
+
454
+ .module-title {
455
+ font-size: 18px;
456
+ font-weight: 600;
457
+ color: var(--text-primary);
458
+ margin: 0;
459
+ padding-left: 12px;
460
+ border-left: 4px solid #165dff;
461
+ white-space: nowrap;
462
+ }
463
+
464
+ .module-description {
465
+ font-size: 14px;
466
+ color: var(--text-secondary);
467
+ line-height: 1.5;
468
+ }
469
+
470
+ .module-score-info {
471
+ font-size: 14px;
472
+ color: var(--text-secondary);
473
+ white-space: nowrap;
474
+ }
475
+
476
+ .module-score-info .score-value {
477
+ font-size: 20px;
478
+ font-weight: 700;
479
+ color: #35bd4b;
480
+ margin: 0 4px;
481
+ }
482
+
483
+ .module-score-info .total-score-value {
484
+ font-weight: 600;
485
+ color: var(--text-primary);
486
+ margin: 0 4px;
487
+ }
488
+
489
+ .module-items-grid {
490
+ display: grid;
491
+ gap: 20px;
492
+ }
493
+
494
+ .module-item-card {
495
+ background: var(--surface);
496
+ border: 1px solid var(--border);
497
+ border-radius: 12px;
498
+ padding: 20px;
499
+ display: flex;
500
+ flex-direction: column;
1025
501
  gap: 16px;
502
+ min-width: 0;
503
+ }
504
+
505
+ .module-item-card:hover {
506
+ box-shadow: 0 4px 12px var(--shadow-hover);
507
+ transform: translateY(-2px);
508
+ }
509
+
510
+ .module-item-card .card-header {
511
+ display: flex;
512
+ justify-content: space-between;
513
+ align-items: flex-start;
514
+ gap: 12px;
515
+ }
516
+
517
+ .item-title {
518
+ font-size: 16px;
519
+ font-weight: 600;
520
+ color: var(--text-primary);
521
+ margin: 0;
522
+ flex: 1;
523
+ line-height: 1.5;
524
+ word-break: break-word;
525
+ }
526
+
527
+ .status-badge {
528
+ flex-shrink: 0;
529
+ padding: 4px 12px;
530
+ border-radius: 4px;
531
+ font-size: 12px;
532
+ font-weight: 500;
533
+ white-space: nowrap;
534
+ }
535
+
536
+ .item-description {
537
+ font-size: 14px;
538
+ color: var(--text-secondary);
539
+ line-height: 1.6;
540
+ margin: 0;
541
+ word-break: break-word;
542
+ }
543
+
544
+ .score-info {
545
+ display: flex;
546
+ justify-content: space-between;
547
+ align-items: center;
548
+ margin-bottom: 8px;
549
+ }
550
+
551
+ .score-label {
552
+ font-size: 14px;
553
+ color: var(--text-muted);
554
+ }
555
+
556
+ .score-percentage {
557
+ font-size: 16px;
558
+ font-weight: 600;
559
+ color: var(--text-primary);
560
+ }
561
+
562
+ .progress-bar {
563
+ width: 100%;
564
+ height: 12px;
565
+ background: var(--ring-track);
566
+ border-radius: 10px;
567
+ overflow: hidden;
568
+ }
569
+
570
+ .progress-fill {
571
+ height: 100%;
572
+ border-radius: 12px;
573
+ }
574
+
575
+ .suggestion-box {
576
+ display: flex;
577
+ align-items: flex-start;
578
+ gap: 8px;
579
+ padding: 12px;
580
+ border-left: 3px solid #ff7d00;
581
+ border-radius: 4px;
582
+ margin-top: 4px;
583
+ }
584
+
585
+ .suggestion-text {
586
+ font-size: 13px;
587
+ color: var(--text-secondary);
588
+ line-height: 1.5;
589
+ word-break: break-word;
590
+ }
591
+
592
+ /* LoadingSpeed */
593
+ .loading-speed-section {
594
+ margin-bottom: 24px;
595
+ padding: 24px;
596
+ background: var(--surface);
597
+ border: 1px solid var(--border);
598
+ border-radius: 12px;
599
+ }
600
+
601
+ .loading-speed-header {
602
+ display: flex;
603
+ justify-content: space-between;
604
+ align-items: center;
605
+ margin-bottom: 8px;
606
+ }
607
+
608
+ .loading-speed-title {
609
+ font-size: 16px;
610
+ font-weight: 600;
611
+ color: var(--text-primary);
612
+ margin: 0;
613
+ }
614
+
615
+ .loading-speed-status {
616
+ padding: 4px 12px;
617
+ border-radius: 4px;
618
+ font-size: 12px;
619
+ font-weight: 500;
620
+ }
621
+
622
+ .loading-speed-status.status-excellent {
623
+ background: var(--status-excellent-bg);
624
+ color: #00b42a;
625
+ }
626
+
627
+ .loading-speed-status.status-good {
628
+ background: var(--status-good-bg);
629
+ color: #165dff;
630
+ }
631
+
632
+ .loading-speed-status.status-normal {
633
+ background: var(--status-normal-bg);
634
+ color: #ff7d00;
635
+ }
636
+
637
+ .loading-speed-status.status-poor {
638
+ background: var(--status-poor-bg);
639
+ color: #f53f3f;
640
+ }
641
+
642
+ .loading-speed-desc {
643
+ font-size: 14px;
644
+ color: var(--text-secondary);
645
+ margin: 0 0 24px;
646
+ line-height: 1.6;
1026
647
  }
1027
- }
1028
648
 
1029
- @media (max-width: 768px) {
1030
649
  .loading-speed-charts {
650
+ display: flex;
651
+ justify-content: space-around;
652
+ gap: 40px;
653
+ margin-bottom: 24px;
654
+ }
655
+
656
+ .speed-chart-item {
657
+ flex: 1;
658
+ display: flex;
1031
659
  flex-direction: column;
1032
660
  align-items: center;
1033
661
  }
1034
662
 
1035
- .longterm-cards {
1036
- grid-template-columns: 1fr;
663
+ .chart-title {
664
+ font-size: 14px;
665
+ font-weight: 500;
666
+ color: var(--text-primary);
667
+ margin-bottom: 16px;
1037
668
  }
1038
669
 
1039
- .main-title {
1040
- font-size: 24px;
670
+ .speed-details {
671
+ width: 100%;
672
+ display: flex;
673
+ flex-direction: column;
674
+ gap: 8px;
1041
675
  }
1042
676
 
1043
- .header-title-wrapper {
677
+ .speed-detail-item {
678
+ font-size: 13px;
679
+ color: var(--text-secondary);
680
+ text-align: center;
681
+ }
682
+
683
+ .speed-value {
684
+ font-weight: 600;
685
+ }
686
+
687
+ .speed-legend {
688
+ display: flex;
689
+ justify-content: center;
690
+ gap: 24px;
691
+ padding-top: 16px;
692
+ border-top: 1px solid var(--border);
693
+ }
694
+
695
+ .legend-item {
696
+ display: flex;
697
+ align-items: center;
698
+ gap: 8px;
699
+ }
700
+
701
+ .legend-icon {
702
+ width: 12px;
703
+ height: 12px;
704
+ border-radius: 2px;
705
+ }
706
+
707
+ .legend-text {
708
+ font-size: 13px;
709
+ color: var(--text-secondary);
710
+ }
711
+
712
+ /* PriorityPlan */
713
+ .priority-columns {
714
+ display: grid;
715
+ grid-template-columns: repeat(3, 1fr);
716
+ gap: 24px;
717
+ }
718
+
719
+ .priority-column {
720
+ display: flex;
1044
721
  flex-direction: column;
1045
- align-items: flex-start;
722
+ padding: 20px;
723
+ border-radius: 8px;
724
+ }
725
+
726
+ .priority-high {
727
+ background: var(--priority-high-bg);
728
+ }
729
+
730
+ .priority-high .priority-title {
731
+ color: #991b25;
732
+ }
733
+
734
+ .priority-high .priority-badge {
735
+ color: #991b25;
736
+ border: 1px solid #991b25;
737
+ }
738
+
739
+ .priority-high .item-bullet,
740
+ .priority-high .impact-icon,
741
+ .priority-high .impact-text {
742
+ color: #f53f3f !important;
743
+ }
744
+
745
+ .priority-medium {
746
+ background: var(--priority-medium-bg);
747
+ --color: #ff7d00;
748
+ }
749
+
750
+ .priority-medium .priority-title {
751
+ color: var(--color);
752
+ }
753
+
754
+ .priority-medium .priority-badge {
755
+ color: var(--color);
756
+ border: 1px solid var(--color);
757
+ }
758
+
759
+ .priority-medium .item-bullet,
760
+ .priority-medium .impact-icon,
761
+ .priority-medium .impact-text {
762
+ color: var(--color) !important;
763
+ }
764
+
765
+ .priority-low {
766
+ background: var(--priority-low-bg);
767
+ --color: #00b42a;
768
+ }
769
+
770
+ .priority-low .priority-title {
771
+ color: var(--color);
772
+ }
773
+
774
+ .priority-low .priority-badge {
775
+ color: var(--color);
776
+ border: 1px solid var(--color);
777
+ }
778
+
779
+ .priority-low .item-bullet,
780
+ .priority-low .impact-icon,
781
+ .priority-low .impact-text {
782
+ color: var(--color) !important;
783
+ }
784
+
785
+ .priority-header-top {
786
+ display: flex;
787
+ align-items: center;
1046
788
  gap: 12px;
789
+ margin-bottom: 8px;
1047
790
  }
1048
791
 
1049
- .module-items-grid {
1050
- grid-template-columns: 1fr !important;
792
+ .priority-icon {
793
+ font-size: 24px;
794
+ line-height: 1;
795
+ }
796
+
797
+ .priority-info {
798
+ display: flex;
799
+ justify-content: space-between;
800
+ align-items: center;
801
+ flex: 1;
802
+ gap: 8px;
803
+ }
804
+
805
+ .priority-title {
806
+ font-size: 18px;
807
+ font-weight: 700;
808
+ margin: 0;
809
+ line-height: 1.3;
810
+ }
811
+
812
+ .priority-subtitle {
813
+ font-size: 13px;
814
+ color: var(--text-secondary);
815
+ margin: 0 0 0 36px;
816
+ line-height: 1.5;
817
+ }
818
+
819
+ .priority-badge {
820
+ padding: 4px 12px;
821
+ border-radius: 4px;
822
+ font-size: 13px;
823
+ font-weight: 500;
824
+ white-space: nowrap;
825
+ background: transparent;
1051
826
  }
1052
827
 
1053
828
  .priority-items {
1054
- grid-template-columns: 1fr !important;
829
+ display: flex;
830
+ flex-direction: column;
831
+ gap: 16px;
1055
832
  }
1056
- }
1057
833
 
1058
- @media print {
1059
- body {
834
+ .priority-item-card {
835
+ --content-margin-left: 14px;
1060
836
  background: var(--surface);
837
+ border: 1px solid var(--border);
838
+ border-radius: 8px;
839
+ padding: 16px;
1061
840
  }
1062
841
 
1063
- .report-container {
1064
- padding: 0;
1065
- background: var(--surface);
842
+ .priority-item-card .item-header {
843
+ display: flex;
844
+ align-items: center;
845
+ gap: 8px;
846
+ margin-bottom: 8px;
1066
847
  }
1067
848
 
1068
- .report-content {
1069
- box-shadow: none;
849
+ .item-bullet {
850
+ font-size: 20px;
851
+ line-height: 1.4;
852
+ font-weight: bold;
853
+ color: var(--text-primary);
1070
854
  }
1071
855
 
1072
- .btn-export,
1073
- .btn-theme {
1074
- display: none;
856
+ .item-title-text {
857
+ font-size: 15px;
858
+ font-weight: 700;
859
+ color: var(--text-primary);
860
+ margin: 0;
861
+ line-height: 1.4;
1075
862
  }
1076
863
 
1077
- .report-section {
1078
- break-inside: avoid;
1079
- }
1080
- }
1081
- </style>
1082
- </head>
1083
-
1084
- <body>
1085
- <div id="app"></div>
1086
- <script>
1087
- window.__WEBSITE_DIAGNOSIS__ = window.__WEBSITE_DIAGNOSIS__ || null;
1088
- </script>
1089
- <script>
1090
-
1091
- /**
1092
- * 网站诊断报告运行时 — 对齐 MarkAI WebsiteAnalysisReport/v3
1093
- * 数据源:window.__WEBSITE_DIAGNOSIS__(与 getWebsiteDiagnosisData.data 同结构)
1094
- */
1095
- (function () {
1096
- "use strict";
1097
-
1098
- const THEME_KEY = "wd-report-theme";
1099
- let radarChartInst = null;
1100
- let riskChartInst = null;
1101
- let chartModulesCache = [];
1102
- let chartRiskCache = [];
1103
-
1104
- function isDarkTheme() {
1105
- return document.documentElement.getAttribute("data-theme") === "dark";
1106
- }
1107
-
1108
- function getChartTheme() {
1109
- const dark = isDarkTheme();
1110
- return {
1111
- axisName: dark ? "#a8b0bb" : "#4e5969",
1112
- splitArea: dark ? ["#1a1f26", "#232a33"] : ["#ffffff", "#f7f8fa"],
1113
- axisLabel: dark ? "#a8b0bb" : "#666666",
1114
- };
864
+ .priority-item-card .item-description {
865
+ font-size: 14px;
866
+ color: var(--text-secondary);
867
+ line-height: 1.6;
868
+ margin: 0 0 12px var(--content-margin-left);
1115
869
  }
1116
870
 
1117
- function getRingTrackColor() {
1118
- return (
1119
- getComputedStyle(document.documentElement).getPropertyValue("--ring-track").trim() || "#e5e6eb"
1120
- );
871
+ .item-impact {
872
+ display: flex;
873
+ align-items: flex-start;
874
+ gap: 4px;
875
+ margin-left: var(--content-margin-left);
1121
876
  }
1122
877
 
1123
- function updateThemeToggleLabel() {
1124
- const btn = document.getElementById("btn-theme-toggle");
1125
- if (btn) btn.textContent = isDarkTheme() ? "☀️ 白天" : "🌙 夜晚";
878
+ .impact-icon {
879
+ flex-shrink: 0;
880
+ font-size: 14px;
881
+ font-weight: bold;
882
+ line-height: 1.6;
1126
883
  }
1127
884
 
1128
- function updateScoreRingTracks() {
1129
- const track = getRingTrackColor();
1130
- document
1131
- .querySelectorAll(".score-ring circle:first-of-type, .speed-ring circle:first-of-type")
1132
- .forEach((el) => el.setAttribute("stroke", track));
885
+ .impact-text {
886
+ font-size: 14px;
887
+ line-height: 1.6;
1133
888
  }
1134
889
 
1135
- function refreshCharts() {
1136
- const theme = getChartTheme();
1137
- if (radarChartInst && chartModulesCache.length) {
1138
- radarChartInst.setOption({
1139
- radar: {
1140
- axisName: { color: theme.axisName },
1141
- splitArea: { areaStyle: { color: theme.splitArea } },
1142
- },
1143
- });
1144
- radarChartInst.resize();
1145
- }
1146
- if (riskChartInst && chartRiskCache.length) {
1147
- riskChartInst.setOption({
1148
- yAxis: { axisLabel: { color: theme.axisLabel } },
1149
- series: [{ label: { color: theme.axisLabel } }, {}],
1150
- });
1151
- riskChartInst.resize();
1152
- }
1153
- updateScoreRingTracks();
890
+ /* LongtermValue */
891
+ .longterm-cards {
892
+ display: grid;
893
+ grid-template-columns: repeat(2, 1fr);
894
+ gap: 20px;
1154
895
  }
1155
896
 
1156
- function applyTheme(theme) {
1157
- document.documentElement.setAttribute("data-theme", theme === "dark" ? "dark" : "light");
1158
- localStorage.setItem(THEME_KEY, theme);
1159
- updateThemeToggleLabel();
1160
- refreshCharts();
897
+ .longterm-card {
898
+ display: flex;
899
+ align-items: center;
900
+ gap: 16px;
901
+ padding: 24px;
902
+ border-radius: 12px;
903
+ border-left: 4px solid;
1161
904
  }
1162
905
 
1163
- function toggleTheme() {
1164
- applyTheme(isDarkTheme() ? "light" : "dark");
906
+ .longterm-card:hover {
907
+ transform: translateY(-2px);
908
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
1165
909
  }
1166
910
 
1167
- function ensureTheme() {
1168
- const stored = localStorage.getItem(THEME_KEY);
1169
- if (stored === "light" || stored === "dark") {
1170
- document.documentElement.setAttribute("data-theme", stored === "dark" ? "dark" : "light");
1171
- } else if (!document.documentElement.hasAttribute("data-theme")) {
1172
- document.documentElement.setAttribute("data-theme", "light");
1173
- }
911
+ .card-blue {
912
+ background: var(--lt-blue-bg);
913
+ border-left-color: #165dff;
1174
914
  }
1175
915
 
1176
- ensureTheme();
1177
-
1178
- const ItemStatus = {
1179
- Excellent: "优秀",
1180
- Good: "良好",
1181
- Normal: "一般",
1182
- Poor: "较差",
1183
- Full: "完整",
1184
- NeedImprove: "需优化",
1185
- Absent: "缺失",
1186
- };
1187
-
1188
- const PAGE_SCORE_LEVEL = [
1189
- { id: "s1", level: "优秀", description: "可直接投放广告", color: "#00b42a", min: 90 },
1190
- { id: "s2", level: "良好", description: "小幅优化后可直接投放广告", color: "#00b42a", min: 80, max: 89.99 },
1191
- { id: "s3", level: "一般", description: "需要重点优化", color: "#ff7d00", min: 70, max: 79.99 },
1192
- { id: "s4", level: "较差", description: "需要大幅改进优化", color: "#f53f3f", min: 60, max: 69.99 },
1193
- { id: "s5", level: "不建议投放", description: "不建议投放广告,需要全面整改", color: "#f53f3f", max: 59.99 },
1194
- ];
1195
-
1196
- const INDUSTRY_TEXT_MAP = [
1197
- { status: "优秀", content: "网站表现优秀,远高于行业平均值,可放心开启广告投放", min: 90 },
1198
- { status: "良好", content: "网站处于行业中上水平,具备良好的优化基础", min: 80, max: 89 },
1199
- { status: "一般", content: "网站略低于行业平均值,建议进行针对性优化", min: 70, max: 79 },
1200
- { status: "不佳", content: "网站低于行业平均值,需要重点优化", min: 60, max: 69 },
1201
- { status: "较差", content: "网站远低于行业标准,建议马上优化", max: 59.99 },
1202
- ];
1203
-
1204
- const CORE_ISSUES_DATA = [
1205
- { id: "ci1", issue: "首屏缺乏清晰CTA", impact: "广告落地页效果差", priority: "高" },
1206
- { id: "ci2", issue: "转化跟踪未部署", impact: "无法归因广告效果", priority: "高" },
1207
- { id: "ci3", issue: "移动端显示异常", impact: "移动端转化下降15%–25%", priority: "高" },
1208
- { id: "ci4", issue: "页面加载缓慢", impact: "首屏加载慢", priority: "高" },
1209
- { id: "ci5", issue: "导航栏与清晰度", impact: "用户找不到关键信息", priority: "中" },
1210
- { id: "ci6", issue: "表单复杂或缺乏清晰", impact: "用户找不到关键信息", priority: "中" },
1211
- { id: "ci7", issue: "类目页与详情页内容不匹配", impact: "广告相关性低", priority: "中" },
1212
- { id: "ci8", issue: "网站语言与广告不一致", impact: "用户体验差", priority: "中" },
1213
- { id: "ci9", issue: "缺少社媒分享入口", impact: "二次传播效率低", priority: "低" },
1214
- { id: "ci10", issue: "品牌风格不统一", impact: "品牌可信度低", priority: "低" },
1215
- ];
1216
-
1217
- const PRIORITY_GROUP_DATA = [
1218
- {
1219
- 优先级: "高",
1220
- 执行周期: "1-2周",
1221
- 影响内容: "影响转化和广告投放",
1222
- 优化项: [
1223
- {
1224
- 优化方向: "核心Banner与首屏CTA",
1225
- 具体任务: "优化Banner图片清晰度、风格统一;突出首屏核心CTA和价值主张",
1226
- 广告影响说明: "提升Landing Page Experience评分,降低跳出率,直接影响Quality Score",
1227
- },
1228
- {
1229
- 优化方向: "转化跟踪部署",
1230
- 具体任务: "部署GA4、GTM、Facebook Pixe等;设置表单提交、电话点击事件",
1231
- 广告影响说明: "完整数据采集,支持自动出价和再营销,提高广告ROI",
1232
- },
1233
- {
1234
- 优化方向: "移动端适配优化",
1235
- 具体任务: "响应式布局优化;按钮触控目标≥44px;检查移动端首屏加载",
1236
- 广告影响说明: "移动端体验直接影响广告质量分和移动端转化率",
1237
- },
1238
- {
1239
- 优化方向: "页面加载速度优化",
1240
- 具体任务: "压缩图片、JS/CSS;使用缓存/CDN;优化首屏加载",
1241
- 广告影响说明: "提升Google Ads速度评分,降低CPC成本,提高广告排名",
1242
- },
1243
- ],
1244
- },
1245
- {
1246
- 优先级: "中",
1247
- 执行周期: "2-4周",
1248
- 影响内容: "影响用户体验",
1249
- 优化项: [
1250
- {
1251
- 优化方向: "导航栏与页面布局调整",
1252
- 具体任务: "栏目精简,导航层级≤3;首屏信息层级清晰",
1253
- 广告影响说明: "提升用户体验,降低跳出率,增加表单提交概率",
1254
- },
1255
- {
1256
- 优化方向: "表单优化",
1257
- 具体任务: "字段≤6个,必填≤4个;自动校验和清晰错误提示",
1258
- 广告影响说明: "提升表单提交率,增加转化量,优化广告ROI",
1259
- },
1260
- {
1261
- 优化方向: "产品类目页与详情页内容优化",
1262
- 具体任务: "每页英文说明≥200词;每产品≥3张高清图;规格参数齐全",
1263
- 广告影响说明: "提高Ad Relevance和转化率,降低广告质量分惩罚",
1264
- },
1265
- ],
1266
- },
1267
- {
1268
- 优先级: "低",
1269
- 执行周期: "1-3个月",
1270
- 影响内容: "优化细节提高美观或品牌感",
1271
- 优化项: [
1272
- {
1273
- 优化方向: "全站语言统一",
1274
- 具体任务: "全站英文(除语言切换外)",
1275
- 广告影响说明: "保证广告与落地页语言一致,提升Ad Relevance",
1276
- },
1277
- {
1278
- 优化方向: "品牌视觉统一",
1279
- 具体任务: "图片、Banner风格统一;字体、Logo、配色一致",
1280
- 广告影响说明: "提升品牌认知度和广告可信度,间接增加转化",
1281
- },
1282
- {
1283
- 优化方向: "社媒分享功能完善",
1284
- 具体任务: "添加OG标签、社交媒体Card;配置社媒分享按钮",
1285
- 广告影响说明: "提升社交可分享性,辅助再营销和广告推广",
1286
- },
1287
- ],
1288
- },
1289
- ];
1290
-
1291
- /** 对齐 useWebsiteGuide/config allModuleConfigs(仅渲染所需字段) */
1292
- const ALL_MODULE_CONFIGS = [
1293
- {
1294
- id: "m1",
1295
- name: "网站内容及结构诊断",
1296
- abbreviation: "内容与结构",
1297
- desc: "评估网站结构合理性",
1298
- 优先级: "高",
1299
- 影响程度: 5,
1300
- 改进难度: 5,
1301
- items: [
1302
- { id: "m1i1", name: "Banner轮播图", fullMarks: 5 },
1303
- { id: "m1i2", name: "导航栏", fullMarks: 2 },
1304
- { id: "m1i3", name: "首页信息布局", fullMarks: 4 },
1305
- { id: "m1i4", name: "产品类目页", fullMarks: 2 },
1306
- { id: "m1i5", name: "产品详情页", fullMarks: 4 },
1307
- { id: "m1i6", name: "公司介绍页", fullMarks: 3 },
1308
- { id: "m1i7", name: "联系我们页", fullMarks: 4 },
1309
- { id: "m1i8", name: "表单提交流程", fullMarks: 4 },
1310
- { id: "m1i9", name: "社交媒体链接", fullMarks: 2 },
1311
- ],
1312
- },
1313
- {
1314
- id: "m2",
1315
- name: "网站性能诊断",
1316
- abbreviation: "网站技术性能",
1317
- desc: "评估网站的基础性能指标",
1318
- 优先级: "高",
1319
- 影响程度: 5,
1320
- 改进难度: 3,
1321
- items: [
1322
- { id: "m2i1", name: "加载速度", fullMarks: 8, isShowCardOnReport: false },
1323
- { id: "m2i2", name: "HTTPS安全", fullMarks: 5 },
1324
- { id: "m2i3", name: "404页面", fullMarks: 4 },
1325
- { id: "m2i4", name: "图片清晰度", fullMarks: 4 },
1326
- { id: "m2i5", name: "移动端适配", fullMarks: 4 },
1327
- ],
1328
- },
1329
- {
1330
- id: "m3",
1331
- name: "营销基础与广告落地页诊断",
1332
- abbreviation: "营销基础与落地页",
1333
- desc: "评估网站内容是否适合开启线上营销",
1334
- 优先级: "中",
1335
- 影响程度: 3,
1336
- 改进难度: 2,
1337
- items: [
1338
- { id: "m3i1", name: "企业邮箱", fullMarks: 6 },
1339
- { id: "m3i2", name: "联系电话", fullMarks: 3 },
1340
- { id: "m3i4", name: "语言一致性", fullMarks: 3 },
1341
- { id: "m3i5", name: "地址地图", fullMarks: 3 },
1342
- ],
1343
- },
1344
- {
1345
- id: "m4",
1346
- name: "用户体验与转化分析诊断",
1347
- abbreviation: "用户体验与转化",
1348
- desc: "评估网站内容的用户友好度",
1349
- 优先级: "中",
1350
- 影响程度: 3,
1351
- 改进难度: 4,
1352
- items: [
1353
- { id: "m4i1", name: "页面布局", fullMarks: 3 },
1354
- { id: "m4i2", name: "CTA按钮", fullMarks: 5 },
1355
- { id: "m4i3", name: "表单体验", fullMarks: 3 },
1356
- { id: "m4i4", name: "内容可读性", fullMarks: 3 },
1357
- { id: "m4i5", name: "社媒分享可扩展性", fullMarks: 1 },
1358
- ],
1359
- },
1360
- {
1361
- id: "m5",
1362
- name: "媒体广告投放辅助检查",
1363
- abbreviation: "广告辅助检查",
1364
- desc: "评估网站内容是否适合开启广告投放",
1365
- 优先级: "低",
1366
- 影响程度: 2,
1367
- 改进难度: 2,
1368
- items: [
1369
- { id: "m5i1", name: "落地页速度", fullMarks: 3 },
1370
- { id: "m5i2", name: "询盘转化路径", fullMarks: 4 },
1371
- { id: "m5i4", name: "跟踪与分析", fullMarks: 3 },
1372
- ],
1373
- },
1374
- {
1375
- id: "m6",
1376
- name: "社交媒体辅助检查",
1377
- abbreviation: "网站是否适合开启社交媒体",
1378
- desc: "评估网站内容是否适合引用到社交媒体",
1379
- 优先级: "低",
1380
- 影响程度: 2,
1381
- 改进难度: 1,
1382
- items: [
1383
- { id: "m6i1", name: "内容可引用性", fullMarks: 2 },
1384
- { id: "m6i2", name: "内容可分享性", fullMarks: 2 },
1385
- { id: "m6i3", name: "视觉风格统一", fullMarks: 1 },
1386
- ],
1387
- },
1388
- ];
1389
-
1390
- function formatDate(dateString) {
1391
- if (!dateString) return "";
1392
- const d = new Date(dateString);
1393
- if (Number.isNaN(d.getTime())) return "";
1394
- const pad = (n) => String(n).padStart(2, "0");
1395
- return `${d.getFullYear()}年${pad(d.getMonth() + 1)}月${pad(d.getDate())}日 ${pad(d.getHours())}:${pad(d.getMinutes())}`;
1396
- }
1397
-
1398
- function calcPercentage(score, totalScore) {
1399
- if (!totalScore) return 0;
1400
- return Math.round((Number(score) / Number(totalScore)) * 100);
1401
- }
1402
-
1403
- function getRatingInfo(ratingId, score) {
1404
- if (ratingId) {
1405
- const hit = PAGE_SCORE_LEVEL.find((x) => x.id === ratingId);
1406
- if (hit) return hit;
1407
- }
1408
- const s = Number(score) || 0;
1409
- for (const info of PAGE_SCORE_LEVEL) {
1410
- if (info.min != null && info.max != null && s >= info.min && s <= info.max) return info;
1411
- if (info.min != null && info.max == null && s >= info.min) return info;
1412
- if (info.max != null && info.min == null && s <= info.max) return info;
1413
- }
1414
- return PAGE_SCORE_LEVEL[PAGE_SCORE_LEVEL.length - 1];
916
+ .card-orange {
917
+ background: var(--lt-orange-bg);
918
+ border-left-color: #ff7d00;
1415
919
  }
1416
920
 
1417
- function getIndustryInfo(score) {
1418
- const s = Number(score) || 0;
1419
- for (const item of INDUSTRY_TEXT_MAP) {
1420
- if (item.min != null && item.max != null && s >= item.min && s <= item.max) return item;
1421
- if (item.min != null && item.max == null && s >= item.min) return item;
1422
- if (item.max != null && item.min == null && s < item.max + 1) return item;
1423
- }
1424
- return INDUSTRY_TEXT_MAP[INDUSTRY_TEXT_MAP.length - 1];
1425
- }
1426
-
1427
- function getPriorityDisplay(priority) {
1428
- if (priority === "高" || priority === "High") return "🔴 高";
1429
- if (priority === "低" || priority === "Low") return "🟢 低";
1430
- return "🟡 中";
1431
- }
1432
-
1433
- function getStarDisplay(level) {
1434
- const n = Math.max(0, Math.min(5, Number(level) || 0));
1435
- return "⭐".repeat(n);
1436
- }
1437
-
1438
- /** 对齐 useWebsiteGuide/utils parseAIResultData */
1439
- function parseAIResultData(value) {
1440
- if (!value) return {};
1441
- if (value.websiteGuideResult) return value.websiteGuideResult;
1442
-
1443
- const data = { ...value };
1444
- if (!data.coreIssues || !Array.isArray(data.coreIssues)) data.coreIssues = [];
1445
-
1446
- if (data.modules && Array.isArray(data.modules)) {
1447
- data.modules = data.modules.map((module) => {
1448
- const moduleConfig = ALL_MODULE_CONFIGS.find((c) => c.id === module.id);
1449
- if (!moduleConfig) return module;
1450
-
1451
- const enrichedModule = {
1452
- ...module,
1453
- desc: moduleConfig.desc,
1454
- name: moduleConfig.name,
1455
- abbreviation: moduleConfig.abbreviation,
1456
- priority: moduleConfig.优先级,
1457
- impact: moduleConfig.影响程度,
1458
- difficulty: moduleConfig.改进难度,
1459
- totalScore: +moduleConfig.items.reduce((sum, item) => sum + item.fullMarks, 0).toFixed(2),
1460
- };
1461
-
1462
- if (module.items && Array.isArray(module.items)) {
1463
- enrichedModule.items = module.items.map((item) => {
1464
- const itemConfig = moduleConfig.items.find((c) => c.id === item.id);
1465
- if (!itemConfig) return item;
1466
- return {
1467
- ...item,
1468
- isShowCardOnReport: itemConfig.isShowCardOnReport !== false,
1469
- name: itemConfig.name,
1470
- totalScore: itemConfig.fullMarks,
1471
- };
1472
- });
1473
- enrichedModule.score = +enrichedModule.items
1474
- .reduce((sum, item) => sum + (Number(item.score) || 0), 0)
1475
- .toFixed(2);
1476
- }
1477
- return enrichedModule;
1478
- });
921
+ .card-green {
922
+ background: var(--lt-green-bg);
923
+ border-left-color: #00b42a;
924
+ }
1479
925
 
1480
- data.score = data.modules.reduce((sum, module) => sum + (Number(module.score) || 0), 0);
1481
- const correctRating = getRatingInfo(undefined, data.score);
1482
- if (correctRating) data.ratingId = correctRating.id;
1483
- }
926
+ .card-purple {
927
+ background: var(--lt-purple-bg);
928
+ border-left-color: #722ed1;
929
+ }
1484
930
 
1485
- if (data.coreIssuesIds && Array.isArray(data.coreIssuesIds)) {
1486
- data.coreIssues = CORE_ISSUES_DATA.filter((item) => data.coreIssuesIds.includes(item.id));
1487
- }
931
+ .card-blue .card-icon {
932
+ --bgc: #dbeafe;
933
+ }
934
+
935
+ .card-orange .card-icon {
936
+ --bgc: #ffedd5;
937
+ }
938
+
939
+ .card-green .card-icon {
940
+ --bgc: #dcfce7;
941
+ }
942
+
943
+ .card-purple .card-icon {
944
+ --bgc: #f3e8ff;
945
+ }
946
+
947
+ html[data-theme="dark"] .card-blue .card-icon {
948
+ --bgc: #1e3a5f;
949
+ }
1488
950
 
1489
- data.lighthouseResult = data.lighthouseResult || data.lighthouse || null;
1490
- return data;
951
+ html[data-theme="dark"] .card-orange .card-icon {
952
+ --bgc: #4a3520;
1491
953
  }
1492
954
 
1493
- function getItemStatusStyle(item) {
1494
- const orange = [ItemStatus.NeedImprove, ItemStatus.Normal];
1495
- const red = [ItemStatus.Poor, ItemStatus.Absent];
1496
- const green = [ItemStatus.Full, ItemStatus.Excellent, ItemStatus.Good];
1497
- const status = ItemStatus[item.status];
1498
- if (orange.includes(status)) return { color: "#ff7d00", backgroundColor: "#fff3e8" };
1499
- if (red.includes(status)) return { color: "#f53f3f", backgroundColor: "#ffece8" };
1500
- if (green.includes(status)) return { color: "#00b42a", backgroundColor: "#e8f8f2" };
1501
- return { color: "#4e5969", backgroundColor: "#f7f8fa" };
955
+ html[data-theme="dark"] .card-green .card-icon {
956
+ --bgc: #1a4030;
1502
957
  }
1503
958
 
1504
- function getModuleItemsGridColumns(items) {
1505
- const len = (items || []).filter((item) => item.isShowCardOnReport !== false).length;
1506
- if (len <= 2 || len % 2 === 0) return 2;
1507
- return 3;
959
+ html[data-theme="dark"] .card-purple .card-icon {
960
+ --bgc: #3d2d5c;
1508
961
  }
1509
962
 
1510
- function getSpeedColor(score) {
1511
- if (score >= 90) return "#00b42a";
1512
- if (score >= 50) return "#ff7d00";
1513
- return "#f53f3f";
963
+ .card-icon {
964
+ flex-shrink: 0;
965
+ width: 46px;
966
+ height: 46px;
967
+ display: flex;
968
+ align-items: center;
969
+ justify-content: center;
970
+ font-size: 20px;
971
+ border-radius: 50%;
972
+ background-color: var(--bgc);
1514
973
  }
1515
974
 
1516
- function getSpeedInfo(value) {
1517
- const v = Number(value) || 0;
1518
- if (v <= 2.5) return { color: "#00b42a", backgroundColor: "#e8f8f2", statusText: "优秀" };
1519
- if (v <= 4) return { color: "#ff7d00", backgroundColor: "#fff3e8", statusText: "需改进" };
1520
- return { color: "#f53f3f", backgroundColor: "#ffece8", statusText: "较差" };
975
+ .card-title {
976
+ font-size: 16px;
977
+ font-weight: 700;
978
+ color: var(--text-primary);
979
+ margin: 0 0 8px;
980
+ line-height: 1.3;
1521
981
  }
1522
982
 
1523
- function formatTimeSeconds(val) {
1524
- if (!val) return "0秒";
1525
- return `${val}秒`;
983
+ .card-desc {
984
+ font-size: 14px;
985
+ color: var(--text-secondary);
986
+ margin: 0;
987
+ line-height: 1.5;
1526
988
  }
1527
989
 
1528
- function getLoadingSpeedStatus(desktopScore, mobileScore) {
1529
- const avg = (Number(desktopScore) + Number(mobileScore)) / 2;
1530
- if (avg >= 90) return "优秀";
1531
- if (avg >= 70) return "良好";
1532
- if (avg >= 50) return "一般";
1533
- return "需优化";
990
+ @container (max-width: 860px) {
991
+ .health-overview {
992
+ flex-direction: column;
993
+ gap: 20px;
994
+ }
995
+
996
+ .divider-line {
997
+ width: 90%;
998
+ height: 1px;
999
+ }
1000
+
1001
+ .radar-chart {
1002
+ width: 100%;
1003
+ }
1534
1004
  }
1535
1005
 
1536
- function getLoadingSpeedStatusClass(desktopScore, mobileScore) {
1537
- const avg = (Number(desktopScore) + Number(mobileScore)) / 2;
1538
- if (avg >= 90) return "status-excellent";
1539
- if (avg >= 70) return "status-good";
1540
- if (avg >= 50) return "status-normal";
1541
- return "status-poor";
1006
+ @container (max-width: 900px) {
1007
+ .risk-map-content {
1008
+ flex-direction: column;
1009
+ }
1010
+
1011
+ .bar-chart-wrapper {
1012
+ width: 100%;
1013
+ height: 300px;
1014
+ }
1015
+
1016
+ .risk-table-wrapper {
1017
+ width: 100%;
1018
+ height: auto;
1019
+ }
1020
+
1021
+ .risk-table-title {
1022
+ display: none;
1023
+ }
1542
1024
  }
1543
1025
 
1544
- function getFinalStatusDescription(lh) {
1545
- const desktop = lh?.desktop?.speedIndex;
1546
- const mobile = lh?.mobile?.speedIndex;
1547
- const avg = (Number(desktop) + Number(mobile)) / 2;
1548
- const finalStatus = getSpeedInfo(avg);
1549
- if (finalStatus.statusText === "优秀") {
1550
- return "网站加载速度快,页面响应及时,达到行业领先水平";
1026
+ @container (max-width: 1200px) {
1027
+ .priority-columns {
1028
+ grid-template-columns: 1fr;
1029
+ }
1030
+
1031
+ .priority-items {
1032
+ display: grid !important;
1033
+ grid-template-columns: repeat(2, 1fr) !important;
1034
+ gap: 16px;
1551
1035
  }
1552
- return "网站加载速度较慢,建议进行全面优化,提升页面性能";
1553
1036
  }
1554
1037
 
1555
- function escapeHtml(s) {
1556
- return String(s ?? "")
1557
- .replace(/&/g, "&amp;")
1558
- .replace(/</g, "&lt;")
1559
- .replace(/>/g, "&gt;")
1560
- .replace(/"/g, "&quot;");
1038
+ @media (max-width: 768px) {
1039
+ .loading-speed-charts {
1040
+ flex-direction: column;
1041
+ align-items: center;
1042
+ }
1043
+
1044
+ .longterm-cards {
1045
+ grid-template-columns: 1fr;
1046
+ }
1047
+
1048
+ .main-title {
1049
+ font-size: 24px;
1050
+ }
1051
+
1052
+ .header-title-wrapper {
1053
+ flex-direction: column;
1054
+ align-items: flex-start;
1055
+ gap: 12px;
1056
+ }
1057
+
1058
+ .module-items-grid {
1059
+ grid-template-columns: 1fr !important;
1060
+ }
1061
+
1062
+ .priority-items {
1063
+ grid-template-columns: 1fr !important;
1064
+ }
1065
+ }
1066
+
1067
+ @media print {
1068
+ body {
1069
+ background: var(--surface);
1070
+ }
1071
+
1072
+ .report-container {
1073
+ padding: 0;
1074
+ background: var(--surface);
1075
+ }
1076
+
1077
+ .report-content {
1078
+ box-shadow: none;
1079
+ }
1080
+
1081
+ .btn-export,
1082
+ .btn-theme {
1083
+ display: none;
1084
+ }
1085
+
1086
+ .report-section {
1087
+ break-inside: avoid;
1088
+ }
1561
1089
  }
1090
+ </style>
1091
+ </head>
1092
+
1093
+ <body>
1094
+ <div id="app"></div>
1095
+ <script>
1096
+ window.__WEBSITE_DIAGNOSIS__ = window.__WEBSITE_DIAGNOSIS__ || null;
1097
+ </script>
1098
+ <script>
1099
+ /**
1100
+ * 网站诊断报告运行时 — 对齐 MarkAI WebsiteAnalysisReport/v3
1101
+ * 数据源:window.__WEBSITE_DIAGNOSIS__(与 getWebsiteDiagnosisData.data 同结构)
1102
+ */
1103
+ (function () {
1104
+ "use strict";
1105
+
1106
+ const THEME_KEY = "wd-report-theme";
1107
+ let radarChartInst = null;
1108
+ let riskChartInst = null;
1109
+ let chartModulesCache = [];
1110
+ let chartRiskCache = [];
1111
+
1112
+ function isDarkTheme() {
1113
+ return document.documentElement.getAttribute("data-theme") === "dark";
1114
+ }
1115
+
1116
+ function getChartTheme() {
1117
+ const dark = isDarkTheme();
1118
+ return {
1119
+ axisName: dark ? "#a8b0bb" : "#4e5969",
1120
+ splitArea: dark ? ["#1a1f26", "#232a33"] : ["#ffffff", "#f7f8fa"],
1121
+ axisLabel: dark ? "#a8b0bb" : "#666666",
1122
+ };
1123
+ }
1124
+
1125
+ function getRingTrackColor() {
1126
+ return (
1127
+ getComputedStyle(document.documentElement).getPropertyValue("--ring-track").trim() ||
1128
+ "#e5e6eb"
1129
+ );
1130
+ }
1131
+
1132
+ function updateThemeToggleLabel() {
1133
+ const btn = document.getElementById("btn-theme-toggle");
1134
+ if (btn) btn.textContent = isDarkTheme() ? "☀️ 白天" : "🌙 夜晚";
1135
+ }
1136
+
1137
+ function updateScoreRingTracks() {
1138
+ const track = getRingTrackColor();
1139
+ document
1140
+ .querySelectorAll(".score-ring circle:first-of-type, .speed-ring circle:first-of-type")
1141
+ .forEach((el) => el.setAttribute("stroke", track));
1142
+ }
1143
+
1144
+ function refreshCharts() {
1145
+ const theme = getChartTheme();
1146
+ if (radarChartInst && chartModulesCache.length) {
1147
+ radarChartInst.setOption({
1148
+ radar: {
1149
+ axisName: { color: theme.axisName },
1150
+ splitArea: { areaStyle: { color: theme.splitArea } },
1151
+ },
1152
+ });
1153
+ radarChartInst.resize();
1154
+ }
1155
+ if (riskChartInst && chartRiskCache.length) {
1156
+ riskChartInst.setOption({
1157
+ yAxis: { axisLabel: { color: theme.axisLabel } },
1158
+ series: [{ label: { color: theme.axisLabel } }, {}],
1159
+ });
1160
+ riskChartInst.resize();
1161
+ }
1162
+ updateScoreRingTracks();
1163
+ }
1164
+
1165
+ function applyTheme(theme) {
1166
+ document.documentElement.setAttribute("data-theme", theme === "dark" ? "dark" : "light");
1167
+ localStorage.setItem(THEME_KEY, theme);
1168
+ updateThemeToggleLabel();
1169
+ refreshCharts();
1170
+ }
1171
+
1172
+ function toggleTheme() {
1173
+ applyTheme(isDarkTheme() ? "light" : "dark");
1174
+ }
1175
+
1176
+ function ensureTheme() {
1177
+ const stored = localStorage.getItem(THEME_KEY);
1178
+ if (stored === "light" || stored === "dark") {
1179
+ document.documentElement.setAttribute(
1180
+ "data-theme",
1181
+ stored === "dark" ? "dark" : "light",
1182
+ );
1183
+ } else if (!document.documentElement.hasAttribute("data-theme")) {
1184
+ document.documentElement.setAttribute("data-theme", "light");
1185
+ }
1186
+ }
1187
+
1188
+ ensureTheme();
1189
+
1190
+ const ItemStatus = {
1191
+ Excellent: "优秀",
1192
+ Good: "良好",
1193
+ Normal: "一般",
1194
+ Poor: "较差",
1195
+ Full: "完整",
1196
+ NeedImprove: "需优化",
1197
+ Absent: "缺失",
1198
+ };
1199
+
1200
+ const PAGE_SCORE_LEVEL = [
1201
+ { id: "s1", level: "优秀", description: "可直接投放广告", color: "#00b42a", min: 90 },
1202
+ {
1203
+ id: "s2",
1204
+ level: "良好",
1205
+ description: "小幅优化后可直接投放广告",
1206
+ color: "#00b42a",
1207
+ min: 80,
1208
+ max: 89.99,
1209
+ },
1210
+ {
1211
+ id: "s3",
1212
+ level: "一般",
1213
+ description: "需要重点优化",
1214
+ color: "#ff7d00",
1215
+ min: 70,
1216
+ max: 79.99,
1217
+ },
1218
+ {
1219
+ id: "s4",
1220
+ level: "较差",
1221
+ description: "需要大幅改进优化",
1222
+ color: "#f53f3f",
1223
+ min: 60,
1224
+ max: 69.99,
1225
+ },
1226
+ {
1227
+ id: "s5",
1228
+ level: "不建议投放",
1229
+ description: "不建议投放广告,需要全面整改",
1230
+ color: "#f53f3f",
1231
+ max: 59.99,
1232
+ },
1233
+ ];
1234
+
1235
+ const INDUSTRY_TEXT_MAP = [
1236
+ {
1237
+ status: "优秀",
1238
+ content: "网站表现优秀,远高于行业平均值,可放心开启广告投放",
1239
+ min: 90,
1240
+ },
1241
+ { status: "良好", content: "网站处于行业中上水平,具备良好的优化基础", min: 80, max: 89 },
1242
+ { status: "一般", content: "网站略低于行业平均值,建议进行针对性优化", min: 70, max: 79 },
1243
+ { status: "不佳", content: "网站低于行业平均值,需要重点优化", min: 60, max: 69 },
1244
+ { status: "较差", content: "网站远低于行业标准,建议马上优化", max: 59.99 },
1245
+ ];
1246
+
1247
+ const CORE_ISSUES_DATA = [
1248
+ { id: "ci1", issue: "首屏缺乏清晰CTA", impact: "广告落地页效果差", priority: "高" },
1249
+ { id: "ci2", issue: "转化跟踪未部署", impact: "无法归因广告效果", priority: "高" },
1250
+ { id: "ci3", issue: "移动端显示异常", impact: "移动端转化下降15%–25%", priority: "高" },
1251
+ { id: "ci4", issue: "页面加载缓慢", impact: "首屏加载慢", priority: "高" },
1252
+ { id: "ci5", issue: "导航栏与清晰度", impact: "用户找不到关键信息", priority: "中" },
1253
+ { id: "ci6", issue: "表单复杂或缺乏清晰", impact: "用户找不到关键信息", priority: "中" },
1254
+ { id: "ci7", issue: "类目页与详情页内容不匹配", impact: "广告相关性低", priority: "中" },
1255
+ { id: "ci8", issue: "网站语言与广告不一致", impact: "用户体验差", priority: "中" },
1256
+ { id: "ci9", issue: "缺少社媒分享入口", impact: "二次传播效率低", priority: "低" },
1257
+ { id: "ci10", issue: "品牌风格不统一", impact: "品牌可信度低", priority: "低" },
1258
+ ];
1259
+
1260
+ const PRIORITY_GROUP_DATA = [
1261
+ {
1262
+ 优先级: "高",
1263
+ 执行周期: "1-2周",
1264
+ 影响内容: "影响转化和广告投放",
1265
+ 优化项: [
1266
+ {
1267
+ 优化方向: "核心Banner与首屏CTA",
1268
+ 具体任务: "优化Banner图片清晰度、风格统一;突出首屏核心CTA和价值主张",
1269
+ 广告影响说明: "提升Landing Page Experience评分,降低跳出率,直接影响Quality Score",
1270
+ },
1271
+ {
1272
+ 优化方向: "转化跟踪部署",
1273
+ 具体任务: "部署GA4、GTM、Facebook Pixe等;设置表单提交、电话点击事件",
1274
+ 广告影响说明: "完整数据采集,支持自动出价和再营销,提高广告ROI",
1275
+ },
1276
+ {
1277
+ 优化方向: "移动端适配优化",
1278
+ 具体任务: "响应式布局优化;按钮触控目标≥44px;检查移动端首屏加载",
1279
+ 广告影响说明: "移动端体验直接影响广告质量分和移动端转化率",
1280
+ },
1281
+ {
1282
+ 优化方向: "页面加载速度优化",
1283
+ 具体任务: "压缩图片、JS/CSS;使用缓存/CDN;优化首屏加载",
1284
+ 广告影响说明: "提升Google Ads速度评分,降低CPC成本,提高广告排名",
1285
+ },
1286
+ ],
1287
+ },
1288
+ {
1289
+ 优先级: "中",
1290
+ 执行周期: "2-4周",
1291
+ 影响内容: "影响用户体验",
1292
+ 优化项: [
1293
+ {
1294
+ 优化方向: "导航栏与页面布局调整",
1295
+ 具体任务: "栏目精简,导航层级≤3;首屏信息层级清晰",
1296
+ 广告影响说明: "提升用户体验,降低跳出率,增加表单提交概率",
1297
+ },
1298
+ {
1299
+ 优化方向: "表单优化",
1300
+ 具体任务: "字段≤6个,必填≤4个;自动校验和清晰错误提示",
1301
+ 广告影响说明: "提升表单提交率,增加转化量,优化广告ROI",
1302
+ },
1303
+ {
1304
+ 优化方向: "产品类目页与详情页内容优化",
1305
+ 具体任务: "每页英文说明≥200词;每产品≥3张高清图;规格参数齐全",
1306
+ 广告影响说明: "提高Ad Relevance和转化率,降低广告质量分惩罚",
1307
+ },
1308
+ ],
1309
+ },
1310
+ {
1311
+ 优先级: "低",
1312
+ 执行周期: "1-3个月",
1313
+ 影响内容: "优化细节提高美观或品牌感",
1314
+ 优化项: [
1315
+ {
1316
+ 优化方向: "全站语言统一",
1317
+ 具体任务: "全站英文(除语言切换外)",
1318
+ 广告影响说明: "保证广告与落地页语言一致,提升Ad Relevance",
1319
+ },
1320
+ {
1321
+ 优化方向: "品牌视觉统一",
1322
+ 具体任务: "图片、Banner风格统一;字体、Logo、配色一致",
1323
+ 广告影响说明: "提升品牌认知度和广告可信度,间接增加转化",
1324
+ },
1325
+ {
1326
+ 优化方向: "社媒分享功能完善",
1327
+ 具体任务: "添加OG标签、社交媒体Card;配置社媒分享按钮",
1328
+ 广告影响说明: "提升社交可分享性,辅助再营销和广告推广",
1329
+ },
1330
+ ],
1331
+ },
1332
+ ];
1333
+
1334
+ /** 对齐 useWebsiteGuide/config allModuleConfigs(仅渲染所需字段) */
1335
+ const ALL_MODULE_CONFIGS = [
1336
+ {
1337
+ id: "m1",
1338
+ name: "网站内容及结构诊断",
1339
+ abbreviation: "内容与结构",
1340
+ desc: "评估网站结构合理性",
1341
+ 优先级: "高",
1342
+ 影响程度: 5,
1343
+ 改进难度: 5,
1344
+ items: [
1345
+ { id: "m1i1", name: "Banner轮播图", fullMarks: 5 },
1346
+ { id: "m1i2", name: "导航栏", fullMarks: 2 },
1347
+ { id: "m1i3", name: "首页信息布局", fullMarks: 4 },
1348
+ { id: "m1i4", name: "产品类目页", fullMarks: 2 },
1349
+ { id: "m1i5", name: "产品详情页", fullMarks: 4 },
1350
+ { id: "m1i6", name: "公司介绍页", fullMarks: 3 },
1351
+ { id: "m1i7", name: "联系我们页", fullMarks: 4 },
1352
+ { id: "m1i8", name: "表单提交流程", fullMarks: 4 },
1353
+ { id: "m1i9", name: "社交媒体链接", fullMarks: 2 },
1354
+ ],
1355
+ },
1356
+ {
1357
+ id: "m2",
1358
+ name: "网站性能诊断",
1359
+ abbreviation: "网站技术性能",
1360
+ desc: "评估网站的基础性能指标",
1361
+ 优先级: "高",
1362
+ 影响程度: 5,
1363
+ 改进难度: 3,
1364
+ items: [
1365
+ { id: "m2i1", name: "加载速度", fullMarks: 8, isShowCardOnReport: false },
1366
+ { id: "m2i2", name: "HTTPS安全", fullMarks: 5 },
1367
+ { id: "m2i3", name: "404页面", fullMarks: 4 },
1368
+ { id: "m2i4", name: "图片清晰度", fullMarks: 4 },
1369
+ { id: "m2i5", name: "移动端适配", fullMarks: 4 },
1370
+ ],
1371
+ },
1372
+ {
1373
+ id: "m3",
1374
+ name: "营销基础与广告落地页诊断",
1375
+ abbreviation: "营销基础与落地页",
1376
+ desc: "评估网站内容是否适合开启线上营销",
1377
+ 优先级: "中",
1378
+ 影响程度: 3,
1379
+ 改进难度: 2,
1380
+ items: [
1381
+ { id: "m3i1", name: "企业邮箱", fullMarks: 6 },
1382
+ { id: "m3i2", name: "联系电话", fullMarks: 3 },
1383
+ { id: "m3i4", name: "语言一致性", fullMarks: 3 },
1384
+ { id: "m3i5", name: "地址地图", fullMarks: 3 },
1385
+ ],
1386
+ },
1387
+ {
1388
+ id: "m4",
1389
+ name: "用户体验与转化分析诊断",
1390
+ abbreviation: "用户体验与转化",
1391
+ desc: "评估网站内容的用户友好度",
1392
+ 优先级: "中",
1393
+ 影响程度: 3,
1394
+ 改进难度: 4,
1395
+ items: [
1396
+ { id: "m4i1", name: "页面布局", fullMarks: 3 },
1397
+ { id: "m4i2", name: "CTA按钮", fullMarks: 5 },
1398
+ { id: "m4i3", name: "表单体验", fullMarks: 3 },
1399
+ { id: "m4i4", name: "内容可读性", fullMarks: 3 },
1400
+ { id: "m4i5", name: "社媒分享可扩展性", fullMarks: 1 },
1401
+ ],
1402
+ },
1403
+ {
1404
+ id: "m5",
1405
+ name: "媒体广告投放辅助检查",
1406
+ abbreviation: "广告辅助检查",
1407
+ desc: "评估网站内容是否适合开启广告投放",
1408
+ 优先级: "低",
1409
+ 影响程度: 2,
1410
+ 改进难度: 2,
1411
+ items: [
1412
+ { id: "m5i1", name: "落地页速度", fullMarks: 3 },
1413
+ { id: "m5i2", name: "询盘转化路径", fullMarks: 4 },
1414
+ { id: "m5i4", name: "跟踪与分析", fullMarks: 3 },
1415
+ ],
1416
+ },
1417
+ {
1418
+ id: "m6",
1419
+ name: "社交媒体辅助检查",
1420
+ abbreviation: "网站是否适合开启社交媒体",
1421
+ desc: "评估网站内容是否适合引用到社交媒体",
1422
+ 优先级: "低",
1423
+ 影响程度: 2,
1424
+ 改进难度: 1,
1425
+ items: [
1426
+ { id: "m6i1", name: "内容可引用性", fullMarks: 2 },
1427
+ { id: "m6i2", name: "内容可分享性", fullMarks: 2 },
1428
+ { id: "m6i3", name: "视觉风格统一", fullMarks: 1 },
1429
+ ],
1430
+ },
1431
+ ];
1432
+
1433
+ function formatDate(dateString) {
1434
+ if (!dateString) return "";
1435
+ const d = new Date(dateString);
1436
+ if (Number.isNaN(d.getTime())) return "";
1437
+ const pad = (n) => String(n).padStart(2, "0");
1438
+ return `${d.getFullYear()}年${pad(d.getMonth() + 1)}月${pad(d.getDate())}日 ${pad(d.getHours())}:${pad(d.getMinutes())}`;
1439
+ }
1562
1440
 
1563
- function renderLoadingSpeed(lh) {
1564
- if (!lh) return "";
1565
- const desktopScore = lh.desktop?.score || 0;
1566
- const mobileScore = lh.mobile?.score || 0;
1567
- const statusClass = getLoadingSpeedStatusClass(desktopScore, mobileScore);
1568
- const statusText = getLoadingSpeedStatus(desktopScore, mobileScore);
1441
+ function calcPercentage(score, totalScore) {
1442
+ if (!totalScore) return 0;
1443
+ return Math.round((Number(score) / Number(totalScore)) * 100);
1444
+ }
1569
1445
 
1570
- const ring = (score, prefix) => {
1446
+ function getRatingInfo(ratingId, score) {
1447
+ if (ratingId) {
1448
+ const hit = PAGE_SCORE_LEVEL.find((x) => x.id === ratingId);
1449
+ if (hit) return hit;
1450
+ }
1571
1451
  const s = Number(score) || 0;
1572
- const color = getSpeedColor(s);
1573
- const d = lh[prefix] || {};
1574
- return `
1452
+ for (const info of PAGE_SCORE_LEVEL) {
1453
+ if (info.min != null && info.max != null && s >= info.min && s <= info.max) return info;
1454
+ if (info.min != null && info.max == null && s >= info.min) return info;
1455
+ if (info.max != null && info.min == null && s <= info.max) return info;
1456
+ }
1457
+ return PAGE_SCORE_LEVEL[PAGE_SCORE_LEVEL.length - 1];
1458
+ }
1459
+
1460
+ function getIndustryInfo(score) {
1461
+ const s = Number(score) || 0;
1462
+ for (const item of INDUSTRY_TEXT_MAP) {
1463
+ if (item.min != null && item.max != null && s >= item.min && s <= item.max) return item;
1464
+ if (item.min != null && item.max == null && s >= item.min) return item;
1465
+ if (item.max != null && item.min == null && s < item.max + 1) return item;
1466
+ }
1467
+ return INDUSTRY_TEXT_MAP[INDUSTRY_TEXT_MAP.length - 1];
1468
+ }
1469
+
1470
+ function getPriorityDisplay(priority) {
1471
+ if (priority === "高" || priority === "High") return "🔴 高";
1472
+ if (priority === "低" || priority === "Low") return "🟢 低";
1473
+ return "🟡 中";
1474
+ }
1475
+
1476
+ function getStarDisplay(level) {
1477
+ const n = Math.max(0, Math.min(5, Number(level) || 0));
1478
+ return "⭐".repeat(n);
1479
+ }
1480
+
1481
+ /** 对齐 useWebsiteGuide/utils parseAIResultData */
1482
+ function parseAIResultData(value) {
1483
+ if (!value) return {};
1484
+ if (value.websiteGuideResult) return value.websiteGuideResult;
1485
+
1486
+ const data = { ...value };
1487
+ if (!data.coreIssues || !Array.isArray(data.coreIssues)) data.coreIssues = [];
1488
+
1489
+ if (data.modules && Array.isArray(data.modules)) {
1490
+ data.modules = data.modules.map((module) => {
1491
+ const moduleConfig = ALL_MODULE_CONFIGS.find((c) => c.id === module.id);
1492
+ if (!moduleConfig) return module;
1493
+
1494
+ const enrichedModule = {
1495
+ ...module,
1496
+ desc: moduleConfig.desc,
1497
+ name: moduleConfig.name,
1498
+ abbreviation: moduleConfig.abbreviation,
1499
+ priority: moduleConfig.优先级,
1500
+ impact: moduleConfig.影响程度,
1501
+ difficulty: moduleConfig.改进难度,
1502
+ totalScore: +moduleConfig.items
1503
+ .reduce((sum, item) => sum + item.fullMarks, 0)
1504
+ .toFixed(2),
1505
+ };
1506
+
1507
+ if (module.items && Array.isArray(module.items)) {
1508
+ enrichedModule.items = module.items.map((item) => {
1509
+ const itemConfig = moduleConfig.items.find((c) => c.id === item.id);
1510
+ if (!itemConfig) return item;
1511
+ return {
1512
+ ...item,
1513
+ isShowCardOnReport: itemConfig.isShowCardOnReport !== false,
1514
+ name: itemConfig.name,
1515
+ totalScore: itemConfig.fullMarks,
1516
+ };
1517
+ });
1518
+ enrichedModule.score = +enrichedModule.items
1519
+ .reduce((sum, item) => sum + (Number(item.score) || 0), 0)
1520
+ .toFixed(2);
1521
+ }
1522
+ return enrichedModule;
1523
+ });
1524
+
1525
+ data.score = data.modules.reduce((sum, module) => sum + (Number(module.score) || 0), 0);
1526
+ const correctRating = getRatingInfo(undefined, data.score);
1527
+ if (correctRating) data.ratingId = correctRating.id;
1528
+ }
1529
+
1530
+ if (data.coreIssuesIds && Array.isArray(data.coreIssuesIds)) {
1531
+ data.coreIssues = CORE_ISSUES_DATA.filter((item) =>
1532
+ data.coreIssuesIds.includes(item.id),
1533
+ );
1534
+ }
1535
+
1536
+ data.lighthouseResult = data.lighthouseResult || data.lighthouse || null;
1537
+ return data;
1538
+ }
1539
+
1540
+ function getItemStatusStyle(item) {
1541
+ const orange = [ItemStatus.NeedImprove, ItemStatus.Normal];
1542
+ const red = [ItemStatus.Poor, ItemStatus.Absent];
1543
+ const green = [ItemStatus.Full, ItemStatus.Excellent, ItemStatus.Good];
1544
+ const status = ItemStatus[item.status];
1545
+ if (orange.includes(status)) return { color: "#ff7d00", backgroundColor: "#fff3e8" };
1546
+ if (red.includes(status)) return { color: "#f53f3f", backgroundColor: "#ffece8" };
1547
+ if (green.includes(status)) return { color: "#00b42a", backgroundColor: "#e8f8f2" };
1548
+ return { color: "#4e5969", backgroundColor: "#f7f8fa" };
1549
+ }
1550
+
1551
+ function getModuleItemsGridColumns(items) {
1552
+ const len = (items || []).filter((item) => item.isShowCardOnReport !== false).length;
1553
+ if (len <= 2 || len % 2 === 0) return 2;
1554
+ return 3;
1555
+ }
1556
+
1557
+ function getSpeedColor(score) {
1558
+ if (score >= 90) return "#00b42a";
1559
+ if (score >= 50) return "#ff7d00";
1560
+ return "#f53f3f";
1561
+ }
1562
+
1563
+ function getSpeedInfo(value) {
1564
+ const v = Number(value) || 0;
1565
+ if (v <= 2.5) return { color: "#00b42a", backgroundColor: "#e8f8f2", statusText: "优秀" };
1566
+ if (v <= 4) return { color: "#ff7d00", backgroundColor: "#fff3e8", statusText: "需改进" };
1567
+ return { color: "#f53f3f", backgroundColor: "#ffece8", statusText: "较差" };
1568
+ }
1569
+
1570
+ function formatTimeSeconds(val) {
1571
+ if (!val) return "0秒";
1572
+ return `${val}秒`;
1573
+ }
1574
+
1575
+ function getLoadingSpeedStatus(desktopScore, mobileScore) {
1576
+ const avg = (Number(desktopScore) + Number(mobileScore)) / 2;
1577
+ if (avg >= 90) return "优秀";
1578
+ if (avg >= 70) return "良好";
1579
+ if (avg >= 50) return "一般";
1580
+ return "需优化";
1581
+ }
1582
+
1583
+ function getLoadingSpeedStatusClass(desktopScore, mobileScore) {
1584
+ const avg = (Number(desktopScore) + Number(mobileScore)) / 2;
1585
+ if (avg >= 90) return "status-excellent";
1586
+ if (avg >= 70) return "status-good";
1587
+ if (avg >= 50) return "status-normal";
1588
+ return "status-poor";
1589
+ }
1590
+
1591
+ function getFinalStatusDescription(lh) {
1592
+ const desktop = lh?.desktop?.speedIndex;
1593
+ const mobile = lh?.mobile?.speedIndex;
1594
+ const avg = (Number(desktop) + Number(mobile)) / 2;
1595
+ const finalStatus = getSpeedInfo(avg);
1596
+ if (finalStatus.statusText === "优秀") {
1597
+ return "网站加载速度快,页面响应及时,达到行业领先水平";
1598
+ }
1599
+ return "网站加载速度较慢,建议进行全面优化,提升页面性能";
1600
+ }
1601
+
1602
+ function escapeHtml(s) {
1603
+ return String(s ?? "")
1604
+ .replace(/&/g, "&amp;")
1605
+ .replace(/</g, "&lt;")
1606
+ .replace(/>/g, "&gt;")
1607
+ .replace(/"/g, "&quot;");
1608
+ }
1609
+
1610
+ function renderLoadingSpeed(lh) {
1611
+ if (!lh) return "";
1612
+ const desktopScore = lh.desktop?.score || 0;
1613
+ const mobileScore = lh.mobile?.score || 0;
1614
+ const statusClass = getLoadingSpeedStatusClass(desktopScore, mobileScore);
1615
+ const statusText = getLoadingSpeedStatus(desktopScore, mobileScore);
1616
+
1617
+ const ring = (score, prefix) => {
1618
+ const s = Number(score) || 0;
1619
+ const color = getSpeedColor(s);
1620
+ const d = lh[prefix] || {};
1621
+ return `
1575
1622
  <div class="speed-chart-item">
1576
1623
  <div class="chart-title">${prefix === "desktop" ? "PC端加载速度 💻" : "移动端加载速度 📱"}</div>
1577
1624
  <div class="speed-ring">
@@ -1587,9 +1634,9 @@
1587
1634
  <div class="speed-detail-item">完全加载时间:<span class="speed-value" style="color:${getSpeedInfo(d.speedIndex || 0).color}">${formatTimeSeconds(d.speedIndex)}</span></div>
1588
1635
  </div>
1589
1636
  </div>`;
1590
- };
1637
+ };
1591
1638
 
1592
- return `
1639
+ return `
1593
1640
  <div class="loading-speed-section">
1594
1641
  <div class="loading-speed-header">
1595
1642
  <h4 class="loading-speed-title">加载速度</h4>
@@ -1603,24 +1650,24 @@
1603
1650
  <div class="legend-item"><span class="legend-icon" style="background:#00b42a"></span><span class="legend-text">90-100</span></div>
1604
1651
  </div>
1605
1652
  </div>`;
1606
- }
1653
+ }
1607
1654
 
1608
- function renderModuleDetail(module, index, lighthouseResult) {
1609
- const cols = getModuleItemsGridColumns(module.items);
1610
- const cards = (module.items || [])
1611
- .filter((item) => item.isShowCardOnReport !== false)
1612
- .map((item) => {
1613
- const style = getItemStatusStyle(item);
1614
- const pct = calcPercentage(item.score, item.totalScore);
1615
- const statusLabel = ItemStatus[item.status] || item.status || "正常";
1616
- const suggestion =
1617
- item.suggestion && pct < 100
1618
- ? `<div class="suggestion-box" style="border-left-color:${style.color};background-color:${style.backgroundColor}">
1655
+ function renderModuleDetail(module, index, lighthouseResult) {
1656
+ const cols = getModuleItemsGridColumns(module.items);
1657
+ const cards = (module.items || [])
1658
+ .filter((item) => item.isShowCardOnReport !== false)
1659
+ .map((item) => {
1660
+ const style = getItemStatusStyle(item);
1661
+ const pct = calcPercentage(item.score, item.totalScore);
1662
+ const statusLabel = ItemStatus[item.status] || item.status || "正常";
1663
+ const suggestion =
1664
+ item.suggestion && pct < 100
1665
+ ? `<div class="suggestion-box" style="border-left-color:${style.color};background-color:${style.backgroundColor}">
1619
1666
  <span class="suggestion-icon">💡</span>
1620
1667
  <span class="suggestion-text">${escapeHtml(item.suggestion)}</span>
1621
1668
  </div>`
1622
- : "";
1623
- return `
1669
+ : "";
1670
+ return `
1624
1671
  <div class="module-item-card">
1625
1672
  <div class="card-header">
1626
1673
  <h4 class="item-title">${escapeHtml(item.name)}</h4>
@@ -1638,13 +1685,13 @@
1638
1685
  </div>
1639
1686
  ${suggestion}
1640
1687
  </div>`;
1641
- })
1642
- .join("");
1688
+ })
1689
+ .join("");
1643
1690
 
1644
- const loading =
1645
- module.id === "m2" && lighthouseResult ? renderLoadingSpeed(lighthouseResult) : "";
1691
+ const loading =
1692
+ module.id === "m2" && lighthouseResult ? renderLoadingSpeed(lighthouseResult) : "";
1646
1693
 
1647
- return `
1694
+ return `
1648
1695
  <div class="module-detail">
1649
1696
  <div class="module-header">
1650
1697
  <div class="module-header-left">
@@ -1656,30 +1703,34 @@
1656
1703
  ${loading}
1657
1704
  <div class="module-items-grid" style="grid-template-columns:repeat(${cols}, 1fr)">${cards}</div>
1658
1705
  </div>`;
1659
- }
1706
+ }
1660
1707
 
1661
- function renderPriorityPlan() {
1662
- return PRIORITY_GROUP_DATA.map((group) => {
1663
- const cls =
1664
- group.优先级 === "高"
1665
- ? "priority-high"
1666
- : group.优先级 === "中"
1667
- ? "priority-medium"
1668
- : "priority-low";
1669
- const title =
1670
- group.优先级 === "高" ? "急需优化!" : group.优先级 === "中" ? "建议优化" : "推荐优化";
1671
- const icon = group.优先级 === "高" ? "🔥" : group.优先级 === "中" ? "💡" : "🚩";
1672
- const items = group.优化项
1673
- .map(
1674
- (item) => `
1708
+ function renderPriorityPlan() {
1709
+ return PRIORITY_GROUP_DATA.map((group) => {
1710
+ const cls =
1711
+ group.优先级 === "高"
1712
+ ? "priority-high"
1713
+ : group.优先级 === "中"
1714
+ ? "priority-medium"
1715
+ : "priority-low";
1716
+ const title =
1717
+ group.优先级 === "高"
1718
+ ? "急需优化!"
1719
+ : group.优先级 === "中"
1720
+ ? "建议优化"
1721
+ : "推荐优化";
1722
+ const icon = group.优先级 === "高" ? "🔥" : group.优先级 === "中" ? "💡" : "🚩";
1723
+ const items = group.优化项
1724
+ .map(
1725
+ (item) => `
1675
1726
  <div class="priority-item-card">
1676
1727
  <div class="item-header"><span class="item-bullet">•</span><h4 class="item-title-text">${escapeHtml(item.优化方向)}</h4></div>
1677
1728
  <p class="item-description">${escapeHtml(item.具体任务)}</p>
1678
1729
  <div class="item-impact"><span class="impact-icon">↑</span><span class="impact-text">${escapeHtml(item.广告影响说明)}</span></div>
1679
1730
  </div>`,
1680
- )
1681
- .join("");
1682
- return `
1731
+ )
1732
+ .join("");
1733
+ return `
1683
1734
  <div class="priority-column ${cls}">
1684
1735
  <div class="priority-header">
1685
1736
  <div class="priority-header-top">
@@ -1693,19 +1744,39 @@
1693
1744
  </div>
1694
1745
  <div class="priority-items">${items}</div>
1695
1746
  </div>`;
1696
- }).join("");
1697
- }
1747
+ }).join("");
1748
+ }
1698
1749
 
1699
- function renderLongtermValue() {
1700
- const cards = [
1701
- { cls: "card-blue", icon: "📊", title: "季度诊断与复盘", desc: "定期评估优化效果,调整策略方向" },
1702
- { cls: "card-orange", icon: "📋", title: "数据仪表盘持续追踪", desc: "实时监控核心指标波动,及时发现问题" },
1703
- { cls: "card-green", icon: "🧪", title: "A/B测试与投放策略联动", desc: "通过科学测试优化广告创意与落地页" },
1704
- { cls: "card-purple", icon: "🎯", title: "监控核心指标", desc: "CPL、转化率、广告ROI、首屏加载速度全方位监测" },
1705
- ];
1706
- return cards
1707
- .map(
1708
- (c) => `
1750
+ function renderLongtermValue() {
1751
+ const cards = [
1752
+ {
1753
+ cls: "card-blue",
1754
+ icon: "📊",
1755
+ title: "季度诊断与复盘",
1756
+ desc: "定期评估优化效果,调整策略方向",
1757
+ },
1758
+ {
1759
+ cls: "card-orange",
1760
+ icon: "📋",
1761
+ title: "数据仪表盘持续追踪",
1762
+ desc: "实时监控核心指标波动,及时发现问题",
1763
+ },
1764
+ {
1765
+ cls: "card-green",
1766
+ icon: "🧪",
1767
+ title: "A/B测试与投放策略联动",
1768
+ desc: "通过科学测试优化广告创意与落地页",
1769
+ },
1770
+ {
1771
+ cls: "card-purple",
1772
+ icon: "🎯",
1773
+ title: "监控核心指标",
1774
+ desc: "CPL、转化率、广告ROI、首屏加载速度全方位监测",
1775
+ },
1776
+ ];
1777
+ return cards
1778
+ .map(
1779
+ (c) => `
1709
1780
  <div class="longterm-card ${c.cls}">
1710
1781
  <div class="card-icon"><span>${c.icon}</span></div>
1711
1782
  <div class="card-content">
@@ -1713,115 +1784,116 @@
1713
1784
  <p class="card-desc">${c.desc}</p>
1714
1785
  </div>
1715
1786
  </div>`,
1716
- )
1717
- .join("");
1718
- }
1719
-
1720
- function initRadarChart(el, modules) {
1721
- if (!window.echarts || !el) return null;
1722
- const theme = getChartTheme();
1723
- const chart = echarts.init(el);
1724
- chart.setOption({
1725
- radar: {
1726
- indicator: modules.map((m) => ({ name: m.abbreviation, max: m.totalScore })),
1727
- radius: "60%",
1728
- splitNumber: 4,
1729
- axisName: { color: theme.axisName, fontSize: 12 },
1730
- splitArea: { areaStyle: { color: theme.splitArea } },
1731
- },
1732
- series: [
1733
- {
1734
- type: "radar",
1735
- data: [
1736
- {
1737
- value: modules.map((m) => Number(m.score) || 0),
1738
- name: "评分",
1739
- areaStyle: { color: "rgba(22, 93, 255, 0.2)" },
1740
- lineStyle: { color: "#165dff", width: 2 },
1741
- itemStyle: { color: "#165dff" },
1742
- },
1743
- ],
1787
+ )
1788
+ .join("");
1789
+ }
1790
+
1791
+ function initRadarChart(el, modules) {
1792
+ if (!window.echarts || !el) return null;
1793
+ const theme = getChartTheme();
1794
+ const chart = echarts.init(el);
1795
+ chart.setOption({
1796
+ radar: {
1797
+ indicator: modules.map((m) => ({ name: m.abbreviation, max: m.totalScore })),
1798
+ radius: "60%",
1799
+ splitNumber: 4,
1800
+ axisName: { color: theme.axisName, fontSize: 12 },
1801
+ splitArea: { areaStyle: { color: theme.splitArea } },
1744
1802
  },
1745
- ],
1746
- });
1747
- return chart;
1748
- }
1749
-
1750
- function initRiskBarChart(el, riskMapData) {
1751
- if (!window.echarts || !el) return null;
1752
- const theme = getChartTheme();
1753
- const data = [...riskMapData].reverse();
1754
- const moduleNames = data.map((v) => v.module);
1755
- const totalScores = data.map((v) => Number((v.score || "").split("/")[1]) || 0);
1756
- const actualScores = data.map((v) => Number((v.score || "").split("/")[0]) || 0);
1757
- const chart = echarts.init(el);
1758
- chart.setOption({
1759
- tooltip: { trigger: "axis", axisPointer: { type: "shadow" } },
1760
- grid: { left: "8px", right: "65px", top: "0", bottom: "0", containLabel: true },
1761
- xAxis: { type: "value", show: false, max: Math.max(...totalScores, 1) },
1762
- yAxis: {
1763
- type: "category",
1764
- data: moduleNames,
1765
- axisLabel: {
1766
- color: theme.axisLabel,
1767
- fontSize: 12,
1768
- formatter: (value) => {
1769
- const maxChars = 8;
1770
- if (value.length <= maxChars) return value;
1771
- const lines = [];
1772
- for (let i = 0; i < value.length; i += maxChars) lines.push(value.slice(i, i + maxChars));
1773
- return lines.join("\n");
1803
+ series: [
1804
+ {
1805
+ type: "radar",
1806
+ data: [
1807
+ {
1808
+ value: modules.map((m) => Number(m.score) || 0),
1809
+ name: "评分",
1810
+ areaStyle: { color: "rgba(22, 93, 255, 0.2)" },
1811
+ lineStyle: { color: "#165dff", width: 2 },
1812
+ itemStyle: { color: "#165dff" },
1813
+ },
1814
+ ],
1774
1815
  },
1775
- },
1776
- axisLine: { show: false },
1777
- axisTick: { show: false },
1778
- },
1779
- series: [
1780
- {
1781
- name: "总分",
1782
- type: "bar",
1783
- data: totalScores,
1784
- barWidth: 20,
1785
- itemStyle: { color: "#0099FF", borderRadius: [0, 4, 4, 0] },
1786
- label: {
1787
- show: true,
1788
- position: "right",
1789
- formatter: (p) => `${actualScores[p.dataIndex]}/${p.value}`,
1816
+ ],
1817
+ });
1818
+ return chart;
1819
+ }
1820
+
1821
+ function initRiskBarChart(el, riskMapData) {
1822
+ if (!window.echarts || !el) return null;
1823
+ const theme = getChartTheme();
1824
+ const data = [...riskMapData].reverse();
1825
+ const moduleNames = data.map((v) => v.module);
1826
+ const totalScores = data.map((v) => Number((v.score || "").split("/")[1]) || 0);
1827
+ const actualScores = data.map((v) => Number((v.score || "").split("/")[0]) || 0);
1828
+ const chart = echarts.init(el);
1829
+ chart.setOption({
1830
+ tooltip: { trigger: "axis", axisPointer: { type: "shadow" } },
1831
+ grid: { left: "8px", right: "65px", top: "0", bottom: "0", containLabel: true },
1832
+ xAxis: { type: "value", show: false, max: Math.max(...totalScores, 1) },
1833
+ yAxis: {
1834
+ type: "category",
1835
+ data: moduleNames,
1836
+ axisLabel: {
1790
1837
  color: theme.axisLabel,
1791
1838
  fontSize: 12,
1839
+ formatter: (value) => {
1840
+ const maxChars = 8;
1841
+ if (value.length <= maxChars) return value;
1842
+ const lines = [];
1843
+ for (let i = 0; i < value.length; i += maxChars)
1844
+ lines.push(value.slice(i, i + maxChars));
1845
+ return lines.join("\n");
1846
+ },
1792
1847
  },
1793
- z: 1,
1794
- },
1795
- {
1796
- name: "得分",
1797
- type: "bar",
1798
- data: actualScores,
1799
- barWidth: 20,
1800
- barGap: "-100%",
1801
- itemStyle: { color: "#00CC00", borderRadius: [0, 4, 4, 0] },
1802
- z: 2,
1848
+ axisLine: { show: false },
1849
+ axisTick: { show: false },
1803
1850
  },
1804
- ],
1805
- });
1806
- return chart;
1807
- }
1808
-
1809
- function renderReport(raw) {
1810
- const data = parseAIResultData(raw);
1811
- const rating = getRatingInfo(data.ratingId, data.score);
1812
- const industry = getIndustryInfo(data.score);
1813
- const ratingColor = rating.color;
1814
- const riskMapData = (data.modules || []).map((module) => ({
1815
- module: module.abbreviation,
1816
- score: `${module.score}/${module.totalScore}`,
1817
- priority: getPriorityDisplay(module.priority),
1818
- impact: getStarDisplay(module.impact),
1819
- difficulty: getStarDisplay(module.difficulty),
1820
- }));
1821
-
1822
- const dash = ((Number(data.score) || 0) / 100) * 471;
1823
-
1824
- document.getElementById("app").innerHTML = `
1851
+ series: [
1852
+ {
1853
+ name: "总分",
1854
+ type: "bar",
1855
+ data: totalScores,
1856
+ barWidth: 20,
1857
+ itemStyle: { color: "#0099FF", borderRadius: [0, 4, 4, 0] },
1858
+ label: {
1859
+ show: true,
1860
+ position: "right",
1861
+ formatter: (p) => `${actualScores[p.dataIndex]}/${p.value}`,
1862
+ color: theme.axisLabel,
1863
+ fontSize: 12,
1864
+ },
1865
+ z: 1,
1866
+ },
1867
+ {
1868
+ name: "得分",
1869
+ type: "bar",
1870
+ data: actualScores,
1871
+ barWidth: 20,
1872
+ barGap: "-100%",
1873
+ itemStyle: { color: "#00CC00", borderRadius: [0, 4, 4, 0] },
1874
+ z: 2,
1875
+ },
1876
+ ],
1877
+ });
1878
+ return chart;
1879
+ }
1880
+
1881
+ function renderReport(raw) {
1882
+ const data = parseAIResultData(raw);
1883
+ const rating = getRatingInfo(data.ratingId, data.score);
1884
+ const industry = getIndustryInfo(data.score);
1885
+ const ratingColor = rating.color;
1886
+ const riskMapData = (data.modules || []).map((module) => ({
1887
+ module: module.abbreviation,
1888
+ score: `${module.score}/${module.totalScore}`,
1889
+ priority: getPriorityDisplay(module.priority),
1890
+ impact: getStarDisplay(module.impact),
1891
+ difficulty: getStarDisplay(module.difficulty),
1892
+ }));
1893
+
1894
+ const dash = ((Number(data.score) || 0) / 100) * 471;
1895
+
1896
+ document.getElementById("app").innerHTML = `
1825
1897
  <div class="report-container">
1826
1898
  <div class="report-content" id="report-root">
1827
1899
  <div class="report-header">
@@ -1884,11 +1956,11 @@
1884
1956
  <table class="risk-table">
1885
1957
  <thead><tr><th>模块</th><th>得分</th><th>影响程度</th><th>改进难度</th></tr></thead>
1886
1958
  <tbody>${riskMapData
1887
- .map(
1888
- (row) =>
1889
- `<tr><td>${escapeHtml(row.module)}</td><td class="tc">${escapeHtml(row.score)}</td><td class="tc">${row.impact}</td><td class="tc">${row.difficulty}</td></tr>`,
1890
- )
1891
- .join("")}</tbody>
1959
+ .map(
1960
+ (row) =>
1961
+ `<tr><td>${escapeHtml(row.module)}</td><td class="tc">${escapeHtml(row.score)}</td><td class="tc">${row.impact}</td><td class="tc">${row.difficulty}</td></tr>`,
1962
+ )
1963
+ .join("")}</tbody>
1892
1964
  </table>
1893
1965
  </div>
1894
1966
  </div>
@@ -1916,32 +1988,38 @@
1916
1988
  </div>
1917
1989
  </div>`;
1918
1990
 
1919
- chartModulesCache = data.modules || [];
1920
- chartRiskCache = riskMapData;
1921
- radarChartInst = initRadarChart(document.getElementById("chart-radar"), chartModulesCache);
1922
- riskChartInst = initRiskBarChart(document.getElementById("chart-risk-bar"), chartRiskCache);
1923
-
1924
- document.getElementById("btn-theme-toggle")?.addEventListener("click", toggleTheme);
1925
- updateThemeToggleLabel();
1926
- updateScoreRingTracks();
1927
-
1928
- const resize = () => {
1929
- radarChartInst?.resize();
1930
- riskChartInst?.resize();
1931
- };
1932
- window.addEventListener("resize", resize);
1933
- }
1934
-
1935
- if (window.__WEBSITE_DIAGNOSIS__) {
1936
- if (document.readyState === "loading") {
1937
- document.addEventListener("DOMContentLoaded", () => renderReport(window.__WEBSITE_DIAGNOSIS__));
1938
- } else {
1939
- renderReport(window.__WEBSITE_DIAGNOSIS__);
1991
+ chartModulesCache = data.modules || [];
1992
+ chartRiskCache = riskMapData;
1993
+ radarChartInst = initRadarChart(
1994
+ document.getElementById("chart-radar"),
1995
+ chartModulesCache,
1996
+ );
1997
+ riskChartInst = initRiskBarChart(
1998
+ document.getElementById("chart-risk-bar"),
1999
+ chartRiskCache,
2000
+ );
2001
+
2002
+ document.getElementById("btn-theme-toggle")?.addEventListener("click", toggleTheme);
2003
+ updateThemeToggleLabel();
2004
+ updateScoreRingTracks();
2005
+
2006
+ const resize = () => {
2007
+ radarChartInst?.resize();
2008
+ riskChartInst?.resize();
2009
+ };
2010
+ window.addEventListener("resize", resize);
1940
2011
  }
1941
- }
1942
- })();
1943
-
1944
- </script>
1945
- </body>
1946
2012
 
1947
- </html>
2013
+ if (window.__WEBSITE_DIAGNOSIS__) {
2014
+ if (document.readyState === "loading") {
2015
+ document.addEventListener("DOMContentLoaded", () =>
2016
+ renderReport(window.__WEBSITE_DIAGNOSIS__),
2017
+ );
2018
+ } else {
2019
+ renderReport(window.__WEBSITE_DIAGNOSIS__);
2020
+ }
2021
+ }
2022
+ })();
2023
+ </script>
2024
+ </body>
2025
+ </html>