@caoguo/maplibre-ai 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-KDLFIBBY.js +125 -0
- package/dist/chunk-KDLFIBBY.js.map +1 -0
- package/dist/chunk-KNL3QRD2.js +118 -0
- package/dist/chunk-KNL3QRD2.js.map +1 -0
- package/dist/debug/index.cjs +132 -0
- package/dist/debug/index.cjs.map +1 -0
- package/dist/debug/index.d.cts +109 -0
- package/dist/debug/index.d.ts +109 -0
- package/dist/debug/index.js +3 -0
- package/dist/debug/index.js.map +1 -0
- package/dist/index.cjs +255 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/stylegen/index.cjs +127 -0
- package/dist/stylegen/index.cjs.map +1 -0
- package/dist/stylegen/index.d.cts +65 -0
- package/dist/stylegen/index.d.ts +65 -0
- package/dist/stylegen/index.js +3 -0
- package/dist/stylegen/index.js.map +1 -0
- package/package.json +47 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
// src/debug/aiDebug.ts
|
|
2
|
+
function analyzePerformance(m) {
|
|
3
|
+
const issues = [];
|
|
4
|
+
if (m.fps !== void 0 && m.fps < 30) {
|
|
5
|
+
issues.push({
|
|
6
|
+
severity: "error",
|
|
7
|
+
title: "\u5E27\u7387\u8FC7\u4F4E",
|
|
8
|
+
detail: `\u5F53\u524D FPS=${m.fps}\uFF0C\u4F4E\u4E8E\u6D41\u7545\u9608\u503C 30`,
|
|
9
|
+
suggestion: "\u51CF\u5C11\u56FE\u5C42\u6570\u91CF\u3001\u542F\u7528 LOD \u6309\u9700\u52A0\u8F7D\u3001\u964D\u4F4E\u6570\u636E\u5BC6\u5EA6"
|
|
10
|
+
});
|
|
11
|
+
} else if (m.fps !== void 0 && m.fps < 60) {
|
|
12
|
+
issues.push({
|
|
13
|
+
severity: "warning",
|
|
14
|
+
title: "\u5E27\u7387\u504F\u4F4E",
|
|
15
|
+
detail: `\u5F53\u524D FPS=${m.fps}\uFF0C\u672A\u8FBE\u6EE1\u5E27`,
|
|
16
|
+
suggestion: "\u68C0\u67E5\u662F\u5426\u6709\u9891\u7E41 setData \u6216 re-render"
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
if (m.drawCalls !== void 0 && m.drawCalls > 100) {
|
|
20
|
+
issues.push({
|
|
21
|
+
severity: "warning",
|
|
22
|
+
title: "Draw call \u6570\u91CF\u5F02\u5E38",
|
|
23
|
+
detail: `Draw calls=${m.drawCalls}`,
|
|
24
|
+
suggestion: "\u5408\u5E76\u56FE\u5C42\uFF0C\u51CF\u5C11 paint \u5C5E\u6027\u590D\u6742\u5EA6\uFF08PRD \xA77.2 Shader \u8FC7\u590D\u6742\uFF09"
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
if (m.activeLayers !== void 0 && m.activeLayers > 50) {
|
|
28
|
+
issues.push({
|
|
29
|
+
severity: "warning",
|
|
30
|
+
title: "\u6D3B\u52A8\u56FE\u5C42\u8FC7\u591A",
|
|
31
|
+
detail: `\u6D3B\u52A8\u56FE\u5C42=${m.activeLayers}`,
|
|
32
|
+
suggestion: "\u5408\u5E76\u540C\u7C7B\u56FE\u5C42\uFF0C\u51CF\u5C11\u56FE\u5C42\u6570\u91CF"
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
if (m.longTasks !== void 0 && m.longTasks > 5) {
|
|
36
|
+
issues.push({
|
|
37
|
+
severity: "warning",
|
|
38
|
+
title: "\u4E3B\u7EBF\u7A0B\u957F\u4EFB\u52A1\u8FC7\u591A",
|
|
39
|
+
detail: `\u957F\u4EFB\u52A1\u6570=${m.longTasks}`,
|
|
40
|
+
suggestion: "\u68C0\u67E5\u9759\u6001\u6570\u636E\u662F\u5426\u610F\u5916\u89E6\u53D1 re-render\uFF08PRD \xA77.2 \u9891\u7E41\u91CD\u7ED8\uFF09"
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
return issues;
|
|
44
|
+
}
|
|
45
|
+
function analyzeTiles(m, overloadThreshold = 200) {
|
|
46
|
+
const hitRate = m.requested > 0 ? m.cached / m.requested : 0;
|
|
47
|
+
const avgLoadMs = m.requested > 0 ? m.totalLoadMs / m.requested : 0;
|
|
48
|
+
return {
|
|
49
|
+
hitRate,
|
|
50
|
+
avgLoadMs,
|
|
51
|
+
overloaded: m.requested > overloadThreshold
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function detectMemoryLeak(snapshots) {
|
|
55
|
+
if (snapshots.length < 2) {
|
|
56
|
+
return { suspectedLeak: false, growthRate: 0, snapshotCount: snapshots.length };
|
|
57
|
+
}
|
|
58
|
+
const sorted = [...snapshots].sort((a, b) => a.timestamp - b.timestamp);
|
|
59
|
+
const first = sorted[0];
|
|
60
|
+
const last = sorted[sorted.length - 1];
|
|
61
|
+
const dt = last.timestamp - first.timestamp;
|
|
62
|
+
const growthRate = dt > 0 ? (last.bytes - first.bytes) / dt : 0;
|
|
63
|
+
let monotonic = true;
|
|
64
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
65
|
+
if (sorted[i].bytes < sorted[i - 1].bytes) {
|
|
66
|
+
monotonic = false;
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
suspectedLeak: monotonic && growthRate > 0 && sorted.length >= 3,
|
|
72
|
+
growthRate,
|
|
73
|
+
snapshotCount: sorted.length
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
var DIAGNOSIS_RULES = [
|
|
77
|
+
{
|
|
78
|
+
id: "tile_overload",
|
|
79
|
+
problem: "\u74E6\u7247\u8FC7\u8F7D",
|
|
80
|
+
detect: (m) => (m.requested ?? 0) > 200,
|
|
81
|
+
suggestion: "\u589E\u52A0 simplification tolerance"
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
id: "shader_complex",
|
|
85
|
+
problem: "Shader \u8FC7\u590D\u6742",
|
|
86
|
+
detect: (m) => (m.drawCalls ?? 0) > 100,
|
|
87
|
+
suggestion: "\u5408\u5E76\u56FE\u5C42\uFF0C\u51CF\u5C11 paint \u5C5E\u6027\u590D\u6742\u5EA6"
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
id: "frequent_rerender",
|
|
91
|
+
problem: "\u9891\u7E41\u91CD\u7ED8",
|
|
92
|
+
detect: (m) => (m.longTasks ?? 0) > 5,
|
|
93
|
+
suggestion: "\u68C0\u67E5 data/source \u662F\u5426\u610F\u5916\u66F4\u65B0"
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
id: "label_overlap",
|
|
97
|
+
problem: "\u6807\u6CE8\u538B\u76D6",
|
|
98
|
+
detect: (m) => (m.activeLayers ?? 0) > 50,
|
|
99
|
+
suggestion: "\u542F\u7528\u6587\u5B57\u907F\u8BA9\u6216\u964D\u4F4E\u6807\u6CE8\u5BC6\u5EA6"
|
|
100
|
+
}
|
|
101
|
+
];
|
|
102
|
+
function suggestOptimizations(m) {
|
|
103
|
+
return DIAGNOSIS_RULES.filter((r) => r.detect(m)).map((r) => ({
|
|
104
|
+
id: r.id,
|
|
105
|
+
problem: r.problem,
|
|
106
|
+
suggestion: r.suggestion
|
|
107
|
+
}));
|
|
108
|
+
}
|
|
109
|
+
function diagnose(opts) {
|
|
110
|
+
const perfIssues = analyzePerformance(opts.perf);
|
|
111
|
+
const suggestions = suggestOptimizations({
|
|
112
|
+
...opts.perf,
|
|
113
|
+
...opts.tiles ?? {}
|
|
114
|
+
});
|
|
115
|
+
return {
|
|
116
|
+
perfIssues,
|
|
117
|
+
tiles: opts.tiles ? analyzeTiles(opts.tiles) : void 0,
|
|
118
|
+
memory: opts.memory ? detectMemoryLeak(opts.memory) : void 0,
|
|
119
|
+
suggestions
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export { DIAGNOSIS_RULES, analyzePerformance, analyzeTiles, detectMemoryLeak, diagnose, suggestOptimizations };
|
|
124
|
+
//# sourceMappingURL=chunk-KDLFIBBY.js.map
|
|
125
|
+
//# sourceMappingURL=chunk-KDLFIBBY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/debug/aiDebug.ts"],"names":[],"mappings":"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","file":"chunk-KDLFIBBY.js","sourcesContent":["/**\n * AI Debug 工具(PRD phase-3 §7)\n *\n * 功能点:\n * - AD-1 性能 Profiler 分析:分析渲染瓶颈\n * - AD-2 瓦片加载监控:实时显示瓦片请求/命中率/加载时间\n * - AD-3 内存泄漏检测:监控 GeoJSON/瓦片资源内存占用趋势\n * - AD-4 优化建议引擎:基于规则匹配常见问题\n *\n * 全部为纯函数,输入指标快照,输出诊断报告。\n */\n\n// ============================================================\n// 一、性能 Profiler 指标\n// ============================================================\nexport interface ProfilerMetrics {\n /** 帧率(fps) */\n fps?: number;\n /** Draw call 数量 */\n drawCalls?: number;\n /** 活动图层数 */\n activeLayers?: number;\n /** 主线程长任务数(>50ms) */\n longTasks?: number;\n /** 渲染耗时(ms) */\n renderTimeMs?: number;\n}\n\nexport interface ProfilerIssue {\n severity: 'info' | 'warning' | 'error';\n title: string;\n detail: string;\n suggestion: string;\n}\n\n/**\n * AD-1 性能 Profiler 分析\n */\nexport function analyzePerformance(m: ProfilerMetrics): ProfilerIssue[] {\n const issues: ProfilerIssue[] = [];\n\n if (m.fps !== undefined && m.fps < 30) {\n issues.push({\n severity: 'error',\n title: '帧率过低',\n detail: `当前 FPS=${m.fps},低于流畅阈值 30`,\n suggestion: '减少图层数量、启用 LOD 按需加载、降低数据密度',\n });\n } else if (m.fps !== undefined && m.fps < 60) {\n issues.push({\n severity: 'warning',\n title: '帧率偏低',\n detail: `当前 FPS=${m.fps},未达满帧`,\n suggestion: '检查是否有频繁 setData 或 re-render',\n });\n }\n\n if (m.drawCalls !== undefined && m.drawCalls > 100) {\n issues.push({\n severity: 'warning',\n title: 'Draw call 数量异常',\n detail: `Draw calls=${m.drawCalls}`,\n suggestion: '合并图层,减少 paint 属性复杂度(PRD §7.2 Shader 过复杂)',\n });\n }\n\n if (m.activeLayers !== undefined && m.activeLayers > 50) {\n issues.push({\n severity: 'warning',\n title: '活动图层过多',\n detail: `活动图层=${m.activeLayers}`,\n suggestion: '合并同类图层,减少图层数量',\n });\n }\n\n if (m.longTasks !== undefined && m.longTasks > 5) {\n issues.push({\n severity: 'warning',\n title: '主线程长任务过多',\n detail: `长任务数=${m.longTasks}`,\n suggestion: '检查静态数据是否意外触发 re-render(PRD §7.2 频繁重绘)',\n });\n }\n\n return issues;\n}\n\n// ============================================================\n// 二、瓦片加载监控(AD-2)\n// ============================================================\nexport interface TileMetrics {\n /** 已请求瓦片数 */\n requested: number;\n /** 命中缓存数 */\n cached: number;\n /** 总加载时间(ms) */\n totalLoadMs: number;\n}\n\nexport interface TileMonitorReport {\n /** 缓存命中率 */\n hitRate: number;\n /** 平均加载时间 */\n avgLoadMs: number;\n /** 是否瓦片过载 */\n overloaded: boolean;\n}\n\n/**\n * AD-2 瓦片加载监控\n */\nexport function analyzeTiles(m: TileMetrics, overloadThreshold = 200): TileMonitorReport {\n const hitRate = m.requested > 0 ? m.cached / m.requested : 0;\n const avgLoadMs = m.requested > 0 ? m.totalLoadMs / m.requested : 0;\n return {\n hitRate,\n avgLoadMs,\n overloaded: m.requested > overloadThreshold,\n };\n}\n\n// ============================================================\n// 三、内存泄漏检测(AD-3)\n// ============================================================\nexport interface MemorySnapshot {\n /** 时间戳 */\n timestamp: number;\n /** 占用字节 */\n bytes: number;\n}\n\nexport interface MemoryLeakReport {\n /** 是否疑似泄漏 */\n suspectedLeak: boolean;\n /** 增长率(bytes/ms) */\n growthRate: number;\n /** 快照数 */\n snapshotCount: number;\n}\n\n/**\n * AD-3 内存泄漏检测:分析内存占用趋势\n */\nexport function detectMemoryLeak(snapshots: MemorySnapshot[]): MemoryLeakReport {\n if (snapshots.length < 2) {\n return { suspectedLeak: false, growthRate: 0, snapshotCount: snapshots.length };\n }\n const sorted = [...snapshots].sort((a, b) => a.timestamp - b.timestamp);\n const first = sorted[0];\n const last = sorted[sorted.length - 1];\n const dt = last.timestamp - first.timestamp;\n const growthRate = dt > 0 ? (last.bytes - first.bytes) / dt : 0;\n\n // 持续增长 + 增长率 > 0 视为疑似泄漏\n let monotonic = true;\n for (let i = 1; i < sorted.length; i++) {\n if (sorted[i].bytes < sorted[i - 1].bytes) {\n monotonic = false;\n break;\n }\n }\n\n return {\n suspectedLeak: monotonic && growthRate > 0 && sorted.length >= 3,\n growthRate,\n snapshotCount: sorted.length,\n };\n}\n\n// ============================================================\n// 四、优化建议引擎(AD-4)\n// ============================================================\n/**\n * PRD §7.2 常见问题诊断规则\n */\nexport const DIAGNOSIS_RULES: Array<{\n id: string;\n /** 规则描述 */\n problem: string;\n /** 检测函数 */\n detect: (m: ProfilerMetrics & Partial<TileMetrics>) => boolean;\n /** 建议 */\n suggestion: string;\n}> = [\n {\n id: 'tile_overload',\n problem: '瓦片过载',\n detect: (m) => (m.requested ?? 0) > 200,\n suggestion: '增加 simplification tolerance',\n },\n {\n id: 'shader_complex',\n problem: 'Shader 过复杂',\n detect: (m) => (m.drawCalls ?? 0) > 100,\n suggestion: '合并图层,减少 paint 属性复杂度',\n },\n {\n id: 'frequent_rerender',\n problem: '频繁重绘',\n detect: (m) => (m.longTasks ?? 0) > 5,\n suggestion: '检查 data/source 是否意外更新',\n },\n {\n id: 'label_overlap',\n problem: '标注压盖',\n detect: (m) => (m.activeLayers ?? 0) > 50,\n suggestion: '启用文字避让或降低标注密度',\n },\n];\n\n/**\n * AD-4 优化建议引擎:运行规则匹配,返回命中的建议\n */\nexport function suggestOptimizations(\n m: ProfilerMetrics & Partial<TileMetrics>\n): Array<{ id: string; problem: string; suggestion: string }> {\n return DIAGNOSIS_RULES.filter((r) => r.detect(m)).map((r) => ({\n id: r.id,\n problem: r.problem,\n suggestion: r.suggestion,\n }));\n}\n\n/** 综合诊断(AD-1~AD-4 汇总) */\nexport interface DebugReport {\n perfIssues: ProfilerIssue[];\n tiles?: TileMonitorReport;\n memory?: MemoryLeakReport;\n suggestions: Array<{ id: string; problem: string; suggestion: string }>;\n}\n\nexport function diagnose(opts: {\n perf: ProfilerMetrics;\n tiles?: TileMetrics;\n memory?: MemorySnapshot[];\n}): DebugReport {\n const perfIssues = analyzePerformance(opts.perf);\n const suggestions = suggestOptimizations({\n ...opts.perf,\n ...(opts.tiles ?? {}),\n });\n return {\n perfIssues,\n tiles: opts.tiles ? analyzeTiles(opts.tiles) : undefined,\n memory: opts.memory ? detectMemoryLeak(opts.memory) : undefined,\n suggestions,\n };\n}\n"]}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// src/stylegen/styleGenerator.ts
|
|
2
|
+
var INDUSTRY_TEMPLATES = {
|
|
3
|
+
pipeline: { name: "\u7BA1\u7F51", primary: "#f59e0b", secondary: "#3b82f6", accent: "#ef4444", background: "#0b1320" },
|
|
4
|
+
grid: { name: "\u7535\u7F51", primary: "#f59e0b", secondary: "#ef4444", accent: "#3b82f6", background: "#0b1320" },
|
|
5
|
+
water: { name: "\u6C34\u7F51", primary: "#3b82f6", secondary: "#22d3ee", accent: "#4ade80", background: "#0b1320" },
|
|
6
|
+
transport: { name: "\u4EA4\u901A", primary: "#f59e0b", secondary: "#ef4444", accent: "#22d3ee", background: "#0b1320" },
|
|
7
|
+
compute: { name: "\u7B97\u529B", primary: "#a78bfa", secondary: "#3b82f6", accent: "#4ade80", background: "#0b1320" },
|
|
8
|
+
telecom: { name: "\u901A\u4FE1", primary: "#3b82f6", secondary: "#4ade80", accent: "#ef4444", background: "#0b1320" }
|
|
9
|
+
};
|
|
10
|
+
var CARRIER_STYLES = {
|
|
11
|
+
"\u4E2D\u56FD\u79FB\u52A8": { name: "\u4E2D\u56FD\u79FB\u52A8", primary: "#4ade80", secondary: "#166534", accent: "#22c55e", background: "#0b1320" },
|
|
12
|
+
"\u4E2D\u56FD\u8054\u901A": { name: "\u4E2D\u56FD\u8054\u901A", primary: "#ef4444", secondary: "#991b1b", accent: "#f87171", background: "#0b1320" },
|
|
13
|
+
"\u4E2D\u56FD\u7535\u4FE1": { name: "\u4E2D\u56FD\u7535\u4FE1", primary: "#3b82f6", secondary: "#1e40af", accent: "#60a5fa", background: "#0b1320" },
|
|
14
|
+
"\u4E2D\u56FD\u5E7F\u7535": { name: "\u4E2D\u56FD\u5E7F\u7535", primary: "#f59e0b", secondary: "#92400e", accent: "#fbbf24", background: "#0b1320" }
|
|
15
|
+
};
|
|
16
|
+
function extractDominantColor(pixels) {
|
|
17
|
+
if (pixels.length < 4) return "#000000";
|
|
18
|
+
const bucket = /* @__PURE__ */ new Map();
|
|
19
|
+
for (let i = 0; i < pixels.length; i += 16) {
|
|
20
|
+
const r2 = pixels[i];
|
|
21
|
+
const g2 = pixels[i + 1];
|
|
22
|
+
const b2 = pixels[i + 2];
|
|
23
|
+
const a = pixels[i + 3];
|
|
24
|
+
if (a === 0) continue;
|
|
25
|
+
const key = `${r2 >> 3},${g2 >> 3},${b2 >> 3}`;
|
|
26
|
+
bucket.set(key, (bucket.get(key) ?? 0) + 1);
|
|
27
|
+
}
|
|
28
|
+
let bestKey = "";
|
|
29
|
+
let bestCount = -1;
|
|
30
|
+
for (const [k, c] of bucket) {
|
|
31
|
+
if (c > bestCount) {
|
|
32
|
+
bestCount = c;
|
|
33
|
+
bestKey = k;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (!bestKey) return "#000000";
|
|
37
|
+
const [r, g, b] = bestKey.split(",").map((v) => (parseInt(v) << 3) + 4);
|
|
38
|
+
return rgbToHex(r, g, b);
|
|
39
|
+
}
|
|
40
|
+
function rgbToHex(r, g, b) {
|
|
41
|
+
return "#" + [r, g, b].map((v) => v.toString(16).padStart(2, "0")).join("");
|
|
42
|
+
}
|
|
43
|
+
function adjustBrightness(hex, factor) {
|
|
44
|
+
const { r, g, b } = hexToRgb(hex);
|
|
45
|
+
const nr = clamp(Math.round(r * factor));
|
|
46
|
+
const ng = clamp(Math.round(g * factor));
|
|
47
|
+
const nb = clamp(Math.round(b * factor));
|
|
48
|
+
return rgbToHex(nr, ng, nb);
|
|
49
|
+
}
|
|
50
|
+
function hexToRgb(hex) {
|
|
51
|
+
const h = hex.replace("#", "");
|
|
52
|
+
return {
|
|
53
|
+
r: parseInt(h.slice(0, 2), 16),
|
|
54
|
+
g: parseInt(h.slice(2, 4), 16),
|
|
55
|
+
b: parseInt(h.slice(4, 6), 16)
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function clamp(v) {
|
|
59
|
+
return Math.max(0, Math.min(255, v));
|
|
60
|
+
}
|
|
61
|
+
function generateBrandStyle(opts) {
|
|
62
|
+
const mode = opts.mode ?? "dark";
|
|
63
|
+
const primary = opts.brandColor;
|
|
64
|
+
const secondary = adjustBrightness(primary, 0.6);
|
|
65
|
+
const accent = adjustBrightness(primary, 1.4);
|
|
66
|
+
const background = mode === "dark" ? "#0b1320" : "#f8fafc";
|
|
67
|
+
return {
|
|
68
|
+
scheme: {
|
|
69
|
+
name: opts.name ?? "\u81EA\u5B9A\u4E49\u54C1\u724C",
|
|
70
|
+
primary,
|
|
71
|
+
secondary,
|
|
72
|
+
accent,
|
|
73
|
+
background
|
|
74
|
+
},
|
|
75
|
+
lineColor: primary,
|
|
76
|
+
pointColor: accent,
|
|
77
|
+
fillColor: primary,
|
|
78
|
+
background,
|
|
79
|
+
mode
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
function generateIndustryStyle(industry, mode = "dark") {
|
|
83
|
+
const scheme = INDUSTRY_TEMPLATES[industry];
|
|
84
|
+
const background = mode === "dark" ? "#0b1320" : "#f8fafc";
|
|
85
|
+
return {
|
|
86
|
+
scheme: { ...scheme, background },
|
|
87
|
+
lineColor: scheme.primary,
|
|
88
|
+
pointColor: scheme.accent,
|
|
89
|
+
fillColor: scheme.secondary,
|
|
90
|
+
background,
|
|
91
|
+
mode
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function generateCarrierStyle(carrier, mode = "dark") {
|
|
95
|
+
const scheme = CARRIER_STYLES[carrier] ?? CARRIER_STYLES["\u4E2D\u56FD\u79FB\u52A8"];
|
|
96
|
+
const background = mode === "dark" ? "#0b1320" : "#f8fafc";
|
|
97
|
+
return {
|
|
98
|
+
scheme: { ...scheme, background },
|
|
99
|
+
lineColor: scheme.primary,
|
|
100
|
+
pointColor: scheme.accent,
|
|
101
|
+
fillColor: scheme.secondary,
|
|
102
|
+
background,
|
|
103
|
+
mode
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
function toggleMode(style) {
|
|
107
|
+
const nextMode = style.mode === "dark" ? "light" : "dark";
|
|
108
|
+
return {
|
|
109
|
+
...style,
|
|
110
|
+
mode: nextMode,
|
|
111
|
+
background: nextMode === "dark" ? "#0b1320" : "#f8fafc",
|
|
112
|
+
scheme: { ...style.scheme, background: nextMode === "dark" ? "#0b1320" : "#f8fafc" }
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export { CARRIER_STYLES, INDUSTRY_TEMPLATES, adjustBrightness, extractDominantColor, generateBrandStyle, generateCarrierStyle, generateIndustryStyle, toggleMode };
|
|
117
|
+
//# sourceMappingURL=chunk-KNL3QRD2.js.map
|
|
118
|
+
//# sourceMappingURL=chunk-KNL3QRD2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/stylegen/styleGenerator.ts"],"names":["r","g","b"],"mappings":"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","file":"chunk-KNL3QRD2.js","sourcesContent":["/**\n * 样式生成器 v2(PRD phase-3 §8)\n *\n * 功能点:\n * - SG-1 色板提取:上传图片 → 提取主色调 → 生成配色方案\n * - SG-2 风格模板:预置 6 套行业模板(管网/电网/水网/交通/算力/通信)\n * - SG-3 品牌定制:输入品牌色 → 自动生成全套地图样式\n * - SG-4 运营商主题:三大运营商预设主题 + 自定义\n * - SG-5 昼夜切换:一键切换亮色/暗色模式\n */\n\n/** 行业风格模板类型(六张网) */\nexport type IndustryStyle = 'pipeline' | 'grid' | 'water' | 'transport' | 'compute' | 'telecom';\n\n/** 配色方案 */\nexport interface ColorScheme {\n /** 主色 */\n primary: string;\n /** 辅助色 */\n secondary: string;\n /** 强调色 */\n accent: string;\n /** 背景色 */\n background: string;\n /** 名称 */\n name: string;\n}\n\n/** 生成的地图样式(简化 style.json 配色片段) */\nexport interface GeneratedMapStyle {\n scheme: ColorScheme;\n /** 线要素配色 */\n lineColor: string;\n /** 点要素配色 */\n pointColor: string;\n /** 面要素配色 */\n fillColor: string;\n /** 底图背景 */\n background: string;\n /** 模式 */\n mode: 'light' | 'dark';\n}\n\n// ============================================================\n// SG-2 风格模板:6 套行业模板\n// ============================================================\nexport const INDUSTRY_TEMPLATES: Record<IndustryStyle, ColorScheme> = {\n pipeline: { name: '管网', primary: '#f59e0b', secondary: '#3b82f6', accent: '#ef4444', background: '#0b1320' },\n grid: { name: '电网', primary: '#f59e0b', secondary: '#ef4444', accent: '#3b82f6', background: '#0b1320' },\n water: { name: '水网', primary: '#3b82f6', secondary: '#22d3ee', accent: '#4ade80', background: '#0b1320' },\n transport: { name: '交通', primary: '#f59e0b', secondary: '#ef4444', accent: '#22d3ee', background: '#0b1320' },\n compute: { name: '算力', primary: '#a78bfa', secondary: '#3b82f6', accent: '#4ade80', background: '#0b1320' },\n telecom: { name: '通信', primary: '#3b82f6', secondary: '#4ade80', accent: '#ef4444', background: '#0b1320' },\n};\n\n// ============================================================\n// SG-4 运营商主题\n// ============================================================\nexport const CARRIER_STYLES: Record<string, ColorScheme> = {\n '中国移动': { name: '中国移动', primary: '#4ade80', secondary: '#166534', accent: '#22c55e', background: '#0b1320' },\n '中国联通': { name: '中国联通', primary: '#ef4444', secondary: '#991b1b', accent: '#f87171', background: '#0b1320' },\n '中国电信': { name: '中国电信', primary: '#3b82f6', secondary: '#1e40af', accent: '#60a5fa', background: '#0b1320' },\n '中国广电': { name: '中国广电', primary: '#f59e0b', secondary: '#92400e', accent: '#fbbf24', background: '#0b1320' },\n};\n\n// ============================================================\n// SG-1 色板提取\n// ============================================================\n/**\n * 从图片像素数据提取主色调。\n * @param pixels RGBA 像素数组(每 4 个值一个像素)\n * @returns 主色 hex(出现频率最高的量化色)\n */\nexport function extractDominantColor(pixels: Uint8ClampedArray): string {\n if (pixels.length < 4) return '#000000';\n const bucket = new Map<string, number>();\n // 采样(每 4px 取一个,提升性能)\n for (let i = 0; i < pixels.length; i += 16) {\n const r = pixels[i];\n const g = pixels[i + 1];\n const b = pixels[i + 2];\n const a = pixels[i + 3];\n if (a === 0) continue;\n // 量化到 32 级\n const key = `${r >> 3},${g >> 3},${b >> 3}`;\n bucket.set(key, (bucket.get(key) ?? 0) + 1);\n }\n let bestKey = '';\n let bestCount = -1;\n for (const [k, c] of bucket) {\n if (c > bestCount) {\n bestCount = c;\n bestKey = k;\n }\n }\n if (!bestKey) return '#000000';\n // 还原量化桶中心值(每桶 8 级,中心偏移 +4)\n const [r, g, b] = bestKey.split(',').map((v) => (parseInt(v) << 3) + 4);\n return rgbToHex(r, g, b);\n}\n\nfunction rgbToHex(r: number, g: number, b: number): string {\n return '#' + [r, g, b].map((v) => v.toString(16).padStart(2, '0')).join('');\n}\n\n/** 调整颜色亮度(用于生成辅助色) */\nexport function adjustBrightness(hex: string, factor: number): string {\n const { r, g, b } = hexToRgb(hex);\n const nr = clamp(Math.round(r * factor));\n const ng = clamp(Math.round(g * factor));\n const nb = clamp(Math.round(b * factor));\n return rgbToHex(nr, ng, nb);\n}\n\nfunction hexToRgb(hex: string): { r: number; g: number; b: number } {\n const h = hex.replace('#', '');\n return {\n r: parseInt(h.slice(0, 2), 16),\n g: parseInt(h.slice(2, 4), 16),\n b: parseInt(h.slice(4, 6), 16),\n };\n}\n\nfunction clamp(v: number): number {\n return Math.max(0, Math.min(255, v));\n}\n\n// ============================================================\n// SG-3 品牌定制:输入品牌色 → 生成全套样式\n// ============================================================\nexport interface BrandStyleOptions {\n /** 品牌主色(hex) */\n brandColor: string;\n /** 模式 */\n mode?: 'light' | 'dark';\n /** 名称 */\n name?: string;\n}\n\nexport function generateBrandStyle(opts: BrandStyleOptions): GeneratedMapStyle {\n const mode = opts.mode ?? 'dark';\n const primary = opts.brandColor;\n const secondary = adjustBrightness(primary, 0.6);\n const accent = adjustBrightness(primary, 1.4);\n const background = mode === 'dark' ? '#0b1320' : '#f8fafc';\n return {\n scheme: {\n name: opts.name ?? '自定义品牌',\n primary,\n secondary,\n accent,\n background,\n },\n lineColor: primary,\n pointColor: accent,\n fillColor: primary,\n background,\n mode,\n };\n}\n\n/** 从行业模板生成样式 */\nexport function generateIndustryStyle(industry: IndustryStyle, mode: 'light' | 'dark' = 'dark'): GeneratedMapStyle {\n const scheme = INDUSTRY_TEMPLATES[industry];\n const background = mode === 'dark' ? '#0b1320' : '#f8fafc';\n return {\n scheme: { ...scheme, background },\n lineColor: scheme.primary,\n pointColor: scheme.accent,\n fillColor: scheme.secondary,\n background,\n mode,\n };\n}\n\n/** 从运营商主题生成样式 */\nexport function generateCarrierStyle(carrier: string, mode: 'light' | 'dark' = 'dark'): GeneratedMapStyle {\n const scheme = CARRIER_STYLES[carrier] ?? CARRIER_STYLES['中国移动'];\n const background = mode === 'dark' ? '#0b1320' : '#f8fafc';\n return {\n scheme: { ...scheme, background },\n lineColor: scheme.primary,\n pointColor: scheme.accent,\n fillColor: scheme.secondary,\n background,\n mode,\n };\n}\n\n// ============================================================\n// SG-5 昼夜切换\n// ============================================================\nexport function toggleMode(style: GeneratedMapStyle): GeneratedMapStyle {\n const nextMode: 'light' | 'dark' = style.mode === 'dark' ? 'light' : 'dark';\n return {\n ...style,\n mode: nextMode,\n background: nextMode === 'dark' ? '#0b1320' : '#f8fafc',\n scheme: { ...style.scheme, background: nextMode === 'dark' ? '#0b1320' : '#f8fafc' },\n };\n}\n"]}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/debug/aiDebug.ts
|
|
4
|
+
function analyzePerformance(m) {
|
|
5
|
+
const issues = [];
|
|
6
|
+
if (m.fps !== void 0 && m.fps < 30) {
|
|
7
|
+
issues.push({
|
|
8
|
+
severity: "error",
|
|
9
|
+
title: "\u5E27\u7387\u8FC7\u4F4E",
|
|
10
|
+
detail: `\u5F53\u524D FPS=${m.fps}\uFF0C\u4F4E\u4E8E\u6D41\u7545\u9608\u503C 30`,
|
|
11
|
+
suggestion: "\u51CF\u5C11\u56FE\u5C42\u6570\u91CF\u3001\u542F\u7528 LOD \u6309\u9700\u52A0\u8F7D\u3001\u964D\u4F4E\u6570\u636E\u5BC6\u5EA6"
|
|
12
|
+
});
|
|
13
|
+
} else if (m.fps !== void 0 && m.fps < 60) {
|
|
14
|
+
issues.push({
|
|
15
|
+
severity: "warning",
|
|
16
|
+
title: "\u5E27\u7387\u504F\u4F4E",
|
|
17
|
+
detail: `\u5F53\u524D FPS=${m.fps}\uFF0C\u672A\u8FBE\u6EE1\u5E27`,
|
|
18
|
+
suggestion: "\u68C0\u67E5\u662F\u5426\u6709\u9891\u7E41 setData \u6216 re-render"
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
if (m.drawCalls !== void 0 && m.drawCalls > 100) {
|
|
22
|
+
issues.push({
|
|
23
|
+
severity: "warning",
|
|
24
|
+
title: "Draw call \u6570\u91CF\u5F02\u5E38",
|
|
25
|
+
detail: `Draw calls=${m.drawCalls}`,
|
|
26
|
+
suggestion: "\u5408\u5E76\u56FE\u5C42\uFF0C\u51CF\u5C11 paint \u5C5E\u6027\u590D\u6742\u5EA6\uFF08PRD \xA77.2 Shader \u8FC7\u590D\u6742\uFF09"
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
if (m.activeLayers !== void 0 && m.activeLayers > 50) {
|
|
30
|
+
issues.push({
|
|
31
|
+
severity: "warning",
|
|
32
|
+
title: "\u6D3B\u52A8\u56FE\u5C42\u8FC7\u591A",
|
|
33
|
+
detail: `\u6D3B\u52A8\u56FE\u5C42=${m.activeLayers}`,
|
|
34
|
+
suggestion: "\u5408\u5E76\u540C\u7C7B\u56FE\u5C42\uFF0C\u51CF\u5C11\u56FE\u5C42\u6570\u91CF"
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
if (m.longTasks !== void 0 && m.longTasks > 5) {
|
|
38
|
+
issues.push({
|
|
39
|
+
severity: "warning",
|
|
40
|
+
title: "\u4E3B\u7EBF\u7A0B\u957F\u4EFB\u52A1\u8FC7\u591A",
|
|
41
|
+
detail: `\u957F\u4EFB\u52A1\u6570=${m.longTasks}`,
|
|
42
|
+
suggestion: "\u68C0\u67E5\u9759\u6001\u6570\u636E\u662F\u5426\u610F\u5916\u89E6\u53D1 re-render\uFF08PRD \xA77.2 \u9891\u7E41\u91CD\u7ED8\uFF09"
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
return issues;
|
|
46
|
+
}
|
|
47
|
+
function analyzeTiles(m, overloadThreshold = 200) {
|
|
48
|
+
const hitRate = m.requested > 0 ? m.cached / m.requested : 0;
|
|
49
|
+
const avgLoadMs = m.requested > 0 ? m.totalLoadMs / m.requested : 0;
|
|
50
|
+
return {
|
|
51
|
+
hitRate,
|
|
52
|
+
avgLoadMs,
|
|
53
|
+
overloaded: m.requested > overloadThreshold
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
function detectMemoryLeak(snapshots) {
|
|
57
|
+
if (snapshots.length < 2) {
|
|
58
|
+
return { suspectedLeak: false, growthRate: 0, snapshotCount: snapshots.length };
|
|
59
|
+
}
|
|
60
|
+
const sorted = [...snapshots].sort((a, b) => a.timestamp - b.timestamp);
|
|
61
|
+
const first = sorted[0];
|
|
62
|
+
const last = sorted[sorted.length - 1];
|
|
63
|
+
const dt = last.timestamp - first.timestamp;
|
|
64
|
+
const growthRate = dt > 0 ? (last.bytes - first.bytes) / dt : 0;
|
|
65
|
+
let monotonic = true;
|
|
66
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
67
|
+
if (sorted[i].bytes < sorted[i - 1].bytes) {
|
|
68
|
+
monotonic = false;
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
suspectedLeak: monotonic && growthRate > 0 && sorted.length >= 3,
|
|
74
|
+
growthRate,
|
|
75
|
+
snapshotCount: sorted.length
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
var DIAGNOSIS_RULES = [
|
|
79
|
+
{
|
|
80
|
+
id: "tile_overload",
|
|
81
|
+
problem: "\u74E6\u7247\u8FC7\u8F7D",
|
|
82
|
+
detect: (m) => (m.requested ?? 0) > 200,
|
|
83
|
+
suggestion: "\u589E\u52A0 simplification tolerance"
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
id: "shader_complex",
|
|
87
|
+
problem: "Shader \u8FC7\u590D\u6742",
|
|
88
|
+
detect: (m) => (m.drawCalls ?? 0) > 100,
|
|
89
|
+
suggestion: "\u5408\u5E76\u56FE\u5C42\uFF0C\u51CF\u5C11 paint \u5C5E\u6027\u590D\u6742\u5EA6"
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
id: "frequent_rerender",
|
|
93
|
+
problem: "\u9891\u7E41\u91CD\u7ED8",
|
|
94
|
+
detect: (m) => (m.longTasks ?? 0) > 5,
|
|
95
|
+
suggestion: "\u68C0\u67E5 data/source \u662F\u5426\u610F\u5916\u66F4\u65B0"
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
id: "label_overlap",
|
|
99
|
+
problem: "\u6807\u6CE8\u538B\u76D6",
|
|
100
|
+
detect: (m) => (m.activeLayers ?? 0) > 50,
|
|
101
|
+
suggestion: "\u542F\u7528\u6587\u5B57\u907F\u8BA9\u6216\u964D\u4F4E\u6807\u6CE8\u5BC6\u5EA6"
|
|
102
|
+
}
|
|
103
|
+
];
|
|
104
|
+
function suggestOptimizations(m) {
|
|
105
|
+
return DIAGNOSIS_RULES.filter((r) => r.detect(m)).map((r) => ({
|
|
106
|
+
id: r.id,
|
|
107
|
+
problem: r.problem,
|
|
108
|
+
suggestion: r.suggestion
|
|
109
|
+
}));
|
|
110
|
+
}
|
|
111
|
+
function diagnose(opts) {
|
|
112
|
+
const perfIssues = analyzePerformance(opts.perf);
|
|
113
|
+
const suggestions = suggestOptimizations({
|
|
114
|
+
...opts.perf,
|
|
115
|
+
...opts.tiles ?? {}
|
|
116
|
+
});
|
|
117
|
+
return {
|
|
118
|
+
perfIssues,
|
|
119
|
+
tiles: opts.tiles ? analyzeTiles(opts.tiles) : void 0,
|
|
120
|
+
memory: opts.memory ? detectMemoryLeak(opts.memory) : void 0,
|
|
121
|
+
suggestions
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
exports.DIAGNOSIS_RULES = DIAGNOSIS_RULES;
|
|
126
|
+
exports.analyzePerformance = analyzePerformance;
|
|
127
|
+
exports.analyzeTiles = analyzeTiles;
|
|
128
|
+
exports.detectMemoryLeak = detectMemoryLeak;
|
|
129
|
+
exports.diagnose = diagnose;
|
|
130
|
+
exports.suggestOptimizations = suggestOptimizations;
|
|
131
|
+
//# sourceMappingURL=index.cjs.map
|
|
132
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/debug/aiDebug.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * AI Debug 工具(PRD phase-3 §7)\n *\n * 功能点:\n * - AD-1 性能 Profiler 分析:分析渲染瓶颈\n * - AD-2 瓦片加载监控:实时显示瓦片请求/命中率/加载时间\n * - AD-3 内存泄漏检测:监控 GeoJSON/瓦片资源内存占用趋势\n * - AD-4 优化建议引擎:基于规则匹配常见问题\n *\n * 全部为纯函数,输入指标快照,输出诊断报告。\n */\n\n// ============================================================\n// 一、性能 Profiler 指标\n// ============================================================\nexport interface ProfilerMetrics {\n /** 帧率(fps) */\n fps?: number;\n /** Draw call 数量 */\n drawCalls?: number;\n /** 活动图层数 */\n activeLayers?: number;\n /** 主线程长任务数(>50ms) */\n longTasks?: number;\n /** 渲染耗时(ms) */\n renderTimeMs?: number;\n}\n\nexport interface ProfilerIssue {\n severity: 'info' | 'warning' | 'error';\n title: string;\n detail: string;\n suggestion: string;\n}\n\n/**\n * AD-1 性能 Profiler 分析\n */\nexport function analyzePerformance(m: ProfilerMetrics): ProfilerIssue[] {\n const issues: ProfilerIssue[] = [];\n\n if (m.fps !== undefined && m.fps < 30) {\n issues.push({\n severity: 'error',\n title: '帧率过低',\n detail: `当前 FPS=${m.fps},低于流畅阈值 30`,\n suggestion: '减少图层数量、启用 LOD 按需加载、降低数据密度',\n });\n } else if (m.fps !== undefined && m.fps < 60) {\n issues.push({\n severity: 'warning',\n title: '帧率偏低',\n detail: `当前 FPS=${m.fps},未达满帧`,\n suggestion: '检查是否有频繁 setData 或 re-render',\n });\n }\n\n if (m.drawCalls !== undefined && m.drawCalls > 100) {\n issues.push({\n severity: 'warning',\n title: 'Draw call 数量异常',\n detail: `Draw calls=${m.drawCalls}`,\n suggestion: '合并图层,减少 paint 属性复杂度(PRD §7.2 Shader 过复杂)',\n });\n }\n\n if (m.activeLayers !== undefined && m.activeLayers > 50) {\n issues.push({\n severity: 'warning',\n title: '活动图层过多',\n detail: `活动图层=${m.activeLayers}`,\n suggestion: '合并同类图层,减少图层数量',\n });\n }\n\n if (m.longTasks !== undefined && m.longTasks > 5) {\n issues.push({\n severity: 'warning',\n title: '主线程长任务过多',\n detail: `长任务数=${m.longTasks}`,\n suggestion: '检查静态数据是否意外触发 re-render(PRD §7.2 频繁重绘)',\n });\n }\n\n return issues;\n}\n\n// ============================================================\n// 二、瓦片加载监控(AD-2)\n// ============================================================\nexport interface TileMetrics {\n /** 已请求瓦片数 */\n requested: number;\n /** 命中缓存数 */\n cached: number;\n /** 总加载时间(ms) */\n totalLoadMs: number;\n}\n\nexport interface TileMonitorReport {\n /** 缓存命中率 */\n hitRate: number;\n /** 平均加载时间 */\n avgLoadMs: number;\n /** 是否瓦片过载 */\n overloaded: boolean;\n}\n\n/**\n * AD-2 瓦片加载监控\n */\nexport function analyzeTiles(m: TileMetrics, overloadThreshold = 200): TileMonitorReport {\n const hitRate = m.requested > 0 ? m.cached / m.requested : 0;\n const avgLoadMs = m.requested > 0 ? m.totalLoadMs / m.requested : 0;\n return {\n hitRate,\n avgLoadMs,\n overloaded: m.requested > overloadThreshold,\n };\n}\n\n// ============================================================\n// 三、内存泄漏检测(AD-3)\n// ============================================================\nexport interface MemorySnapshot {\n /** 时间戳 */\n timestamp: number;\n /** 占用字节 */\n bytes: number;\n}\n\nexport interface MemoryLeakReport {\n /** 是否疑似泄漏 */\n suspectedLeak: boolean;\n /** 增长率(bytes/ms) */\n growthRate: number;\n /** 快照数 */\n snapshotCount: number;\n}\n\n/**\n * AD-3 内存泄漏检测:分析内存占用趋势\n */\nexport function detectMemoryLeak(snapshots: MemorySnapshot[]): MemoryLeakReport {\n if (snapshots.length < 2) {\n return { suspectedLeak: false, growthRate: 0, snapshotCount: snapshots.length };\n }\n const sorted = [...snapshots].sort((a, b) => a.timestamp - b.timestamp);\n const first = sorted[0];\n const last = sorted[sorted.length - 1];\n const dt = last.timestamp - first.timestamp;\n const growthRate = dt > 0 ? (last.bytes - first.bytes) / dt : 0;\n\n // 持续增长 + 增长率 > 0 视为疑似泄漏\n let monotonic = true;\n for (let i = 1; i < sorted.length; i++) {\n if (sorted[i].bytes < sorted[i - 1].bytes) {\n monotonic = false;\n break;\n }\n }\n\n return {\n suspectedLeak: monotonic && growthRate > 0 && sorted.length >= 3,\n growthRate,\n snapshotCount: sorted.length,\n };\n}\n\n// ============================================================\n// 四、优化建议引擎(AD-4)\n// ============================================================\n/**\n * PRD §7.2 常见问题诊断规则\n */\nexport const DIAGNOSIS_RULES: Array<{\n id: string;\n /** 规则描述 */\n problem: string;\n /** 检测函数 */\n detect: (m: ProfilerMetrics & Partial<TileMetrics>) => boolean;\n /** 建议 */\n suggestion: string;\n}> = [\n {\n id: 'tile_overload',\n problem: '瓦片过载',\n detect: (m) => (m.requested ?? 0) > 200,\n suggestion: '增加 simplification tolerance',\n },\n {\n id: 'shader_complex',\n problem: 'Shader 过复杂',\n detect: (m) => (m.drawCalls ?? 0) > 100,\n suggestion: '合并图层,减少 paint 属性复杂度',\n },\n {\n id: 'frequent_rerender',\n problem: '频繁重绘',\n detect: (m) => (m.longTasks ?? 0) > 5,\n suggestion: '检查 data/source 是否意外更新',\n },\n {\n id: 'label_overlap',\n problem: '标注压盖',\n detect: (m) => (m.activeLayers ?? 0) > 50,\n suggestion: '启用文字避让或降低标注密度',\n },\n];\n\n/**\n * AD-4 优化建议引擎:运行规则匹配,返回命中的建议\n */\nexport function suggestOptimizations(\n m: ProfilerMetrics & Partial<TileMetrics>\n): Array<{ id: string; problem: string; suggestion: string }> {\n return DIAGNOSIS_RULES.filter((r) => r.detect(m)).map((r) => ({\n id: r.id,\n problem: r.problem,\n suggestion: r.suggestion,\n }));\n}\n\n/** 综合诊断(AD-1~AD-4 汇总) */\nexport interface DebugReport {\n perfIssues: ProfilerIssue[];\n tiles?: TileMonitorReport;\n memory?: MemoryLeakReport;\n suggestions: Array<{ id: string; problem: string; suggestion: string }>;\n}\n\nexport function diagnose(opts: {\n perf: ProfilerMetrics;\n tiles?: TileMetrics;\n memory?: MemorySnapshot[];\n}): DebugReport {\n const perfIssues = analyzePerformance(opts.perf);\n const suggestions = suggestOptimizations({\n ...opts.perf,\n ...(opts.tiles ?? {}),\n });\n return {\n perfIssues,\n tiles: opts.tiles ? analyzeTiles(opts.tiles) : undefined,\n memory: opts.memory ? detectMemoryLeak(opts.memory) : undefined,\n suggestions,\n };\n}\n"]}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI Debug 工具(PRD phase-3 §7)
|
|
3
|
+
*
|
|
4
|
+
* 功能点:
|
|
5
|
+
* - AD-1 性能 Profiler 分析:分析渲染瓶颈
|
|
6
|
+
* - AD-2 瓦片加载监控:实时显示瓦片请求/命中率/加载时间
|
|
7
|
+
* - AD-3 内存泄漏检测:监控 GeoJSON/瓦片资源内存占用趋势
|
|
8
|
+
* - AD-4 优化建议引擎:基于规则匹配常见问题
|
|
9
|
+
*
|
|
10
|
+
* 全部为纯函数,输入指标快照,输出诊断报告。
|
|
11
|
+
*/
|
|
12
|
+
interface ProfilerMetrics {
|
|
13
|
+
/** 帧率(fps) */
|
|
14
|
+
fps?: number;
|
|
15
|
+
/** Draw call 数量 */
|
|
16
|
+
drawCalls?: number;
|
|
17
|
+
/** 活动图层数 */
|
|
18
|
+
activeLayers?: number;
|
|
19
|
+
/** 主线程长任务数(>50ms) */
|
|
20
|
+
longTasks?: number;
|
|
21
|
+
/** 渲染耗时(ms) */
|
|
22
|
+
renderTimeMs?: number;
|
|
23
|
+
}
|
|
24
|
+
interface ProfilerIssue {
|
|
25
|
+
severity: 'info' | 'warning' | 'error';
|
|
26
|
+
title: string;
|
|
27
|
+
detail: string;
|
|
28
|
+
suggestion: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* AD-1 性能 Profiler 分析
|
|
32
|
+
*/
|
|
33
|
+
declare function analyzePerformance(m: ProfilerMetrics): ProfilerIssue[];
|
|
34
|
+
interface TileMetrics {
|
|
35
|
+
/** 已请求瓦片数 */
|
|
36
|
+
requested: number;
|
|
37
|
+
/** 命中缓存数 */
|
|
38
|
+
cached: number;
|
|
39
|
+
/** 总加载时间(ms) */
|
|
40
|
+
totalLoadMs: number;
|
|
41
|
+
}
|
|
42
|
+
interface TileMonitorReport {
|
|
43
|
+
/** 缓存命中率 */
|
|
44
|
+
hitRate: number;
|
|
45
|
+
/** 平均加载时间 */
|
|
46
|
+
avgLoadMs: number;
|
|
47
|
+
/** 是否瓦片过载 */
|
|
48
|
+
overloaded: boolean;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* AD-2 瓦片加载监控
|
|
52
|
+
*/
|
|
53
|
+
declare function analyzeTiles(m: TileMetrics, overloadThreshold?: number): TileMonitorReport;
|
|
54
|
+
interface MemorySnapshot {
|
|
55
|
+
/** 时间戳 */
|
|
56
|
+
timestamp: number;
|
|
57
|
+
/** 占用字节 */
|
|
58
|
+
bytes: number;
|
|
59
|
+
}
|
|
60
|
+
interface MemoryLeakReport {
|
|
61
|
+
/** 是否疑似泄漏 */
|
|
62
|
+
suspectedLeak: boolean;
|
|
63
|
+
/** 增长率(bytes/ms) */
|
|
64
|
+
growthRate: number;
|
|
65
|
+
/** 快照数 */
|
|
66
|
+
snapshotCount: number;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* AD-3 内存泄漏检测:分析内存占用趋势
|
|
70
|
+
*/
|
|
71
|
+
declare function detectMemoryLeak(snapshots: MemorySnapshot[]): MemoryLeakReport;
|
|
72
|
+
/**
|
|
73
|
+
* PRD §7.2 常见问题诊断规则
|
|
74
|
+
*/
|
|
75
|
+
declare const DIAGNOSIS_RULES: Array<{
|
|
76
|
+
id: string;
|
|
77
|
+
/** 规则描述 */
|
|
78
|
+
problem: string;
|
|
79
|
+
/** 检测函数 */
|
|
80
|
+
detect: (m: ProfilerMetrics & Partial<TileMetrics>) => boolean;
|
|
81
|
+
/** 建议 */
|
|
82
|
+
suggestion: string;
|
|
83
|
+
}>;
|
|
84
|
+
/**
|
|
85
|
+
* AD-4 优化建议引擎:运行规则匹配,返回命中的建议
|
|
86
|
+
*/
|
|
87
|
+
declare function suggestOptimizations(m: ProfilerMetrics & Partial<TileMetrics>): Array<{
|
|
88
|
+
id: string;
|
|
89
|
+
problem: string;
|
|
90
|
+
suggestion: string;
|
|
91
|
+
}>;
|
|
92
|
+
/** 综合诊断(AD-1~AD-4 汇总) */
|
|
93
|
+
interface DebugReport {
|
|
94
|
+
perfIssues: ProfilerIssue[];
|
|
95
|
+
tiles?: TileMonitorReport;
|
|
96
|
+
memory?: MemoryLeakReport;
|
|
97
|
+
suggestions: Array<{
|
|
98
|
+
id: string;
|
|
99
|
+
problem: string;
|
|
100
|
+
suggestion: string;
|
|
101
|
+
}>;
|
|
102
|
+
}
|
|
103
|
+
declare function diagnose(opts: {
|
|
104
|
+
perf: ProfilerMetrics;
|
|
105
|
+
tiles?: TileMetrics;
|
|
106
|
+
memory?: MemorySnapshot[];
|
|
107
|
+
}): DebugReport;
|
|
108
|
+
|
|
109
|
+
export { DIAGNOSIS_RULES, type DebugReport, type MemoryLeakReport, type MemorySnapshot, type ProfilerIssue, type ProfilerMetrics, type TileMetrics, type TileMonitorReport, analyzePerformance, analyzeTiles, detectMemoryLeak, diagnose, suggestOptimizations };
|