@howone/sdk 0.2.3 → 0.2.4
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/index.d.mts +0 -17
- package/dist/index.d.ts +0 -17
- package/dist/index.js +101 -1236
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +101 -1236
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1507,7 +1507,6 @@ var ViteHMRDetector = class {
|
|
|
1507
1507
|
if (this.isInitialized) return;
|
|
1508
1508
|
this.setupViteErrorDetection();
|
|
1509
1509
|
this.isInitialized = true;
|
|
1510
|
-
console.log("[ViteHMRDetector] Vite HMR \u9519\u8BEF\u68C0\u6D4B\u5668\u521D\u59CB\u5316\u5B8C\u6210");
|
|
1511
1510
|
}
|
|
1512
1511
|
/**
|
|
1513
1512
|
* 销毁检测器
|
|
@@ -1558,10 +1557,8 @@ var ViteHMRDetector = class {
|
|
|
1558
1557
|
setTimeout(() => this.checkForCompileErrors(), 500);
|
|
1559
1558
|
});
|
|
1560
1559
|
hot.on("vite:beforeUpdate", () => {
|
|
1561
|
-
console.log("[ViteHMRDetector] HMR \u66F4\u65B0\u5F00\u59CB");
|
|
1562
1560
|
});
|
|
1563
1561
|
hot.on("vite:afterUpdate", () => {
|
|
1564
|
-
console.log("[ViteHMRDetector] HMR \u66F4\u65B0\u5B8C\u6210");
|
|
1565
1562
|
});
|
|
1566
1563
|
}
|
|
1567
1564
|
window.addEventListener("error", (event) => {
|
|
@@ -1599,7 +1596,6 @@ var ViteHMRDetector = class {
|
|
|
1599
1596
|
payload: errorPayload,
|
|
1600
1597
|
timestamp: Date.now()
|
|
1601
1598
|
});
|
|
1602
|
-
console.log("[ViteHMRDetector] Vite \u9519\u8BEF\u5DF2\u68C0\u6D4B\u5E76\u62A5\u544A:", errorPayload);
|
|
1603
1599
|
} catch (err) {
|
|
1604
1600
|
this.handleFallbackError(errorOverlay, err);
|
|
1605
1601
|
}
|
|
@@ -1872,20 +1868,16 @@ var HardRefreshManager = class {
|
|
|
1872
1868
|
clearedStorage: []
|
|
1873
1869
|
};
|
|
1874
1870
|
try {
|
|
1875
|
-
console.log("[HardRefreshManager] \u5F00\u59CB\u6267\u884C\u786C\u5237\u65B0...");
|
|
1876
1871
|
if (defaultOptions.clearCaches) {
|
|
1877
1872
|
const clearedCaches = await this.clearAllCaches();
|
|
1878
1873
|
result.clearedCaches = clearedCaches;
|
|
1879
|
-
console.log(`[HardRefreshManager] \u5DF2\u6E05\u9664 ${clearedCaches.length} \u4E2A\u7F13\u5B58`);
|
|
1880
1874
|
}
|
|
1881
1875
|
if (defaultOptions.unregisterServiceWorkers) {
|
|
1882
1876
|
const unregisteredCount = await this.unregisterServiceWorkers();
|
|
1883
1877
|
result.unregisteredWorkers = unregisteredCount;
|
|
1884
|
-
console.log(`[HardRefreshManager] \u5DF2\u6CE8\u9500 ${unregisteredCount} \u4E2A Service Worker`);
|
|
1885
1878
|
}
|
|
1886
1879
|
const clearedStorage = await this.clearStorage(defaultOptions);
|
|
1887
1880
|
result.clearedStorage = clearedStorage;
|
|
1888
|
-
console.log(`[HardRefreshManager] \u5DF2\u6E05\u9664\u5B58\u50A8: ${clearedStorage.join(", ")}`);
|
|
1889
1881
|
await this.forceReload(defaultOptions);
|
|
1890
1882
|
result.success = true;
|
|
1891
1883
|
return result;
|
|
@@ -2484,7 +2476,6 @@ var ComponentTreeGenerator = class {
|
|
|
2484
2476
|
maxTextLength: 100,
|
|
2485
2477
|
maxChildren: 50
|
|
2486
2478
|
};
|
|
2487
|
-
console.log("[ComponentTreeGenerator] \u7EC4\u4EF6\u6811\u751F\u6210\u5668\u521D\u59CB\u5316\u5B8C\u6210");
|
|
2488
2479
|
}
|
|
2489
2480
|
/** ----------------- 主要生成方法 ----------------- */
|
|
2490
2481
|
/**
|
|
@@ -2493,7 +2484,6 @@ var ComponentTreeGenerator = class {
|
|
|
2493
2484
|
generateComponentTree(rootElement) {
|
|
2494
2485
|
const startTime = Date.now();
|
|
2495
2486
|
const root = rootElement || document.body;
|
|
2496
|
-
console.log("[ComponentTreeGenerator] \u5F00\u59CB\u751F\u6210\u7EC4\u4EF6\u6811...");
|
|
2497
2487
|
const rootNode = this.generateNodeTree(root, 0);
|
|
2498
2488
|
const stats = this.calculateTreeStats(rootNode);
|
|
2499
2489
|
const componentTree = {
|
|
@@ -2514,7 +2504,6 @@ var ComponentTreeGenerator = class {
|
|
|
2514
2504
|
}
|
|
2515
2505
|
};
|
|
2516
2506
|
const generationTime = Date.now() - startTime;
|
|
2517
|
-
console.log(`[ComponentTreeGenerator] \u7EC4\u4EF6\u6811\u751F\u6210\u5B8C\u6210\uFF0C\u8017\u65F6 ${generationTime}ms\uFF0C\u8282\u70B9\u6570: ${stats.totalNodes}`);
|
|
2518
2507
|
return componentTree;
|
|
2519
2508
|
}
|
|
2520
2509
|
/**
|
|
@@ -2865,7 +2854,6 @@ var ComponentTreeGenerator = class {
|
|
|
2865
2854
|
*/
|
|
2866
2855
|
updateConfig(newConfig) {
|
|
2867
2856
|
this.config = { ...this.config, ...newConfig };
|
|
2868
|
-
console.log("[ComponentTreeGenerator] \u914D\u7F6E\u5DF2\u66F4\u65B0:", this.config);
|
|
2869
2857
|
}
|
|
2870
2858
|
/**
|
|
2871
2859
|
* 获取当前配置
|
|
@@ -2888,7 +2876,6 @@ var ComponentTreeGenerator = class {
|
|
|
2888
2876
|
* 销毁生成器
|
|
2889
2877
|
*/
|
|
2890
2878
|
destroy() {
|
|
2891
|
-
console.log("[ComponentTreeGenerator] \u7EC4\u4EF6\u6811\u751F\u6210\u5668\u5DF2\u9500\u6BC1");
|
|
2892
2879
|
}
|
|
2893
2880
|
};
|
|
2894
2881
|
|
|
@@ -3065,7 +3052,6 @@ var ErrorTracking = class {
|
|
|
3065
3052
|
this.viewDetector = null;
|
|
3066
3053
|
this.interactionTracking = null;
|
|
3067
3054
|
this.sendMessage = sendMessage;
|
|
3068
|
-
this.internalLog("log", "[ErrorTracking] \u9519\u8BEF\u8FFD\u8E2A\u6A21\u5757\u521D\u59CB\u5316\u5B8C\u6210");
|
|
3069
3055
|
}
|
|
3070
3056
|
/**
|
|
3071
3057
|
* 内部日志方法,避免被控制台拦截器捕获
|
|
@@ -3101,10 +3087,8 @@ var ErrorTracking = class {
|
|
|
3101
3087
|
this.setupConsoleInterception();
|
|
3102
3088
|
this.setupNetworkMonitoring();
|
|
3103
3089
|
this.initialized = true;
|
|
3104
|
-
this.internalLog("log", "[ErrorTracking] \u9519\u8BEF\u8FFD\u8E2A\u529F\u80FD\u5DF2\u542F\u7528");
|
|
3105
3090
|
setTimeout(() => {
|
|
3106
3091
|
this.fullyInitialized = true;
|
|
3107
|
-
this.internalLog("log", "[ErrorTracking] \u521D\u59CB\u5316\u5B8C\u6210\uFF0C\u63A7\u5236\u53F0\u62E6\u622A\u5DF2\u9ED8\u8BA4\u542F\u7528");
|
|
3108
3092
|
}, 1e3);
|
|
3109
3093
|
}
|
|
3110
3094
|
/**
|
|
@@ -3129,7 +3113,6 @@ var ErrorTracking = class {
|
|
|
3129
3113
|
source: "unhandledrejection"
|
|
3130
3114
|
});
|
|
3131
3115
|
});
|
|
3132
|
-
this.internalLog("log", "[ErrorTracking] \u5168\u5C40\u9519\u8BEF\u76D1\u542C\u5668\u5DF2\u8BBE\u7F6E");
|
|
3133
3116
|
}
|
|
3134
3117
|
/**
|
|
3135
3118
|
* 设置控制台拦截
|
|
@@ -3153,7 +3136,6 @@ var ErrorTracking = class {
|
|
|
3153
3136
|
}
|
|
3154
3137
|
};
|
|
3155
3138
|
});
|
|
3156
|
-
this.internalLog("log", "[ErrorTracking] \u63A7\u5236\u53F0\u62E6\u622A\u5DF2\u8BBE\u7F6E");
|
|
3157
3139
|
}
|
|
3158
3140
|
/**
|
|
3159
3141
|
* 安全地将控制台输出转发到父窗口
|
|
@@ -3281,7 +3263,6 @@ var ErrorTracking = class {
|
|
|
3281
3263
|
throw error;
|
|
3282
3264
|
}
|
|
3283
3265
|
};
|
|
3284
|
-
this.internalLog("log", "[ErrorTracking] \u7F51\u7EDC\u76D1\u63A7\u5DF2\u8BBE\u7F6E");
|
|
3285
3266
|
}
|
|
3286
3267
|
/**
|
|
3287
3268
|
* 记录网络请求
|
|
@@ -3573,14 +3554,12 @@ var ErrorTracking = class {
|
|
|
3573
3554
|
*/
|
|
3574
3555
|
enableConsoleInterception() {
|
|
3575
3556
|
this.fullyInitialized = true;
|
|
3576
|
-
this.internalLog("log", "[ErrorTracking] \u624B\u52A8\u542F\u7528\u63A7\u5236\u53F0\u62E6\u622A");
|
|
3577
3557
|
}
|
|
3578
3558
|
/**
|
|
3579
3559
|
* 手动禁用控制台拦截
|
|
3580
3560
|
*/
|
|
3581
3561
|
disableConsoleInterception() {
|
|
3582
3562
|
this.fullyInitialized = false;
|
|
3583
|
-
this.internalLog("log", "[ErrorTracking] \u624B\u52A8\u7981\u7528\u63A7\u5236\u53F0\u62E6\u622A");
|
|
3584
3563
|
}
|
|
3585
3564
|
/**
|
|
3586
3565
|
* 销毁错误追踪
|
|
@@ -3592,10 +3571,32 @@ var ErrorTracking = class {
|
|
|
3592
3571
|
}
|
|
3593
3572
|
});
|
|
3594
3573
|
this.initialized = false;
|
|
3595
|
-
this.internalLog("log", "[ErrorTracking] \u9519\u8BEF\u8FFD\u8E2A\u6A21\u5757\u5DF2\u9500\u6BC1");
|
|
3596
3574
|
}
|
|
3597
3575
|
};
|
|
3598
3576
|
|
|
3577
|
+
// src/utils/unified-error-handler/utils/SelectorUtils.ts
|
|
3578
|
+
function getElementClasses(element) {
|
|
3579
|
+
const classAttr = element.getAttribute("class");
|
|
3580
|
+
if (classAttr && classAttr.trim().length > 0) {
|
|
3581
|
+
return dedupeAndClean(classAttr.split(/\s+/));
|
|
3582
|
+
}
|
|
3583
|
+
const anyEl = element;
|
|
3584
|
+
if (typeof anyEl.className === "string") {
|
|
3585
|
+
return dedupeAndClean(anyEl.className.split(/\s+/));
|
|
3586
|
+
}
|
|
3587
|
+
if (anyEl.className && typeof anyEl.className.baseVal === "string") {
|
|
3588
|
+
return dedupeAndClean(anyEl.className.baseVal.split(/\s+/));
|
|
3589
|
+
}
|
|
3590
|
+
if (anyEl.classList && anyEl.classList.length > 0) {
|
|
3591
|
+
return dedupeAndClean(Array.from(anyEl.classList));
|
|
3592
|
+
}
|
|
3593
|
+
return [];
|
|
3594
|
+
}
|
|
3595
|
+
function dedupeAndClean(arr) {
|
|
3596
|
+
const cleaned = arr.map((s) => s.trim()).filter(Boolean);
|
|
3597
|
+
return Array.from(new Set(cleaned));
|
|
3598
|
+
}
|
|
3599
|
+
|
|
3599
3600
|
// src/utils/unified-error-handler/features/InteractionTracking.ts
|
|
3600
3601
|
var InteractionTracking = class {
|
|
3601
3602
|
constructor(sendMessage) {
|
|
@@ -3619,7 +3620,6 @@ var InteractionTracking = class {
|
|
|
3619
3620
|
this.debounceTimers = /* @__PURE__ */ new Map();
|
|
3620
3621
|
this.eventListeners = [];
|
|
3621
3622
|
this.sendMessage = sendMessage;
|
|
3622
|
-
console.log("[InteractionTracking] \u4EA4\u4E92\u8FFD\u8E2A\u6A21\u5757\u521D\u59CB\u5316\u5B8C\u6210");
|
|
3623
3623
|
}
|
|
3624
3624
|
/** ----------------- 主要控制方法 ----------------- */
|
|
3625
3625
|
/**
|
|
@@ -3635,7 +3635,6 @@ var InteractionTracking = class {
|
|
|
3635
3635
|
title: document.title,
|
|
3636
3636
|
timestamp: Date.now()
|
|
3637
3637
|
});
|
|
3638
|
-
console.log("[InteractionTracking] \u4EA4\u4E92\u8FFD\u8E2A\u5DF2\u5F00\u59CB");
|
|
3639
3638
|
}
|
|
3640
3639
|
/**
|
|
3641
3640
|
* 停止追踪
|
|
@@ -3644,7 +3643,6 @@ var InteractionTracking = class {
|
|
|
3644
3643
|
if (!this.isTracking) return;
|
|
3645
3644
|
this.removeEventListeners();
|
|
3646
3645
|
this.isTracking = false;
|
|
3647
|
-
console.log("[InteractionTracking] \u4EA4\u4E92\u8FFD\u8E2A\u5DF2\u505C\u6B62");
|
|
3648
3646
|
}
|
|
3649
3647
|
/** ----------------- 事件监听器设置 ----------------- */
|
|
3650
3648
|
/**
|
|
@@ -3957,979 +3955,121 @@ var InteractionTracking = class {
|
|
|
3957
3955
|
*/
|
|
3958
3956
|
getElementSelector(element) {
|
|
3959
3957
|
if (element.id) return `#${element.id}`;
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
return `.${classes[0]}`;
|
|
3964
|
-
}
|
|
3958
|
+
const classes = getElementClasses(element);
|
|
3959
|
+
if (classes.length > 0) {
|
|
3960
|
+
return `.${classes[0]}`;
|
|
3965
3961
|
}
|
|
3966
3962
|
const dataTestId = element.getAttribute("data-testid");
|
|
3967
3963
|
if (dataTestId) return `[data-testid="${dataTestId}"]`;
|
|
3968
3964
|
const dataId = element.getAttribute("data-id");
|
|
3969
|
-
if (dataId) return `[data-id="${dataId}"]`;
|
|
3970
|
-
return element.tagName.toLowerCase();
|
|
3971
|
-
}
|
|
3972
|
-
/**
|
|
3973
|
-
* 检查是否为敏感输入
|
|
3974
|
-
*/
|
|
3975
|
-
isSensitiveInput(element) {
|
|
3976
|
-
if (!this.trackingConfig.sensitiveInputFilter) return false;
|
|
3977
|
-
const sensitiveTypes = ["password", "email", "tel", "ssn", "credit-card"];
|
|
3978
|
-
const sensitiveNames = ["password", "email", "phone", "ssn", "credit", "card", "cvv", "pin"];
|
|
3979
|
-
return sensitiveTypes.includes(element.type) || sensitiveNames.some(
|
|
3980
|
-
(name) => element.name?.toLowerCase().includes(name) || element.placeholder?.toLowerCase().includes(name) || element.id?.toLowerCase().includes(name)
|
|
3981
|
-
);
|
|
3982
|
-
}
|
|
3983
|
-
/**
|
|
3984
|
-
* 管理数组长度
|
|
3985
|
-
*/
|
|
3986
|
-
manageArrayLength(array, maxLength) {
|
|
3987
|
-
if (array.length > maxLength) {
|
|
3988
|
-
array.shift();
|
|
3989
|
-
}
|
|
3990
|
-
}
|
|
3991
|
-
/** ----------------- 公共接口方法 ----------------- */
|
|
3992
|
-
/**
|
|
3993
|
-
* 获取交互历史
|
|
3994
|
-
*/
|
|
3995
|
-
getInteractionHistory() {
|
|
3996
|
-
return [...this.interactions];
|
|
3997
|
-
}
|
|
3998
|
-
/**
|
|
3999
|
-
* 获取最近的交互记录
|
|
4000
|
-
*/
|
|
4001
|
-
getRecentInteractions(count = 8) {
|
|
4002
|
-
return this.interactions.slice(-count);
|
|
4003
|
-
}
|
|
4004
|
-
/**
|
|
4005
|
-
* 手动发送交互数据到父窗口(用于测试或特殊情况)
|
|
4006
|
-
*/
|
|
4007
|
-
sendInteractionData() {
|
|
4008
|
-
if (this.interactions.length === 0) return;
|
|
4009
|
-
this.sendMessage({
|
|
4010
|
-
type: "INTERACTION_EVENT",
|
|
4011
|
-
payload: {
|
|
4012
|
-
type: "summary",
|
|
4013
|
-
interactions: this.interactions,
|
|
4014
|
-
count: this.interactions.length,
|
|
4015
|
-
timeRange: {
|
|
4016
|
-
start: this.interactions[0]?.timestamp || Date.now(),
|
|
4017
|
-
end: this.interactions[this.interactions.length - 1]?.timestamp || Date.now()
|
|
4018
|
-
},
|
|
4019
|
-
summary: this.generateInteractionSummary()
|
|
4020
|
-
},
|
|
4021
|
-
timestamp: Date.now()
|
|
4022
|
-
});
|
|
4023
|
-
}
|
|
4024
|
-
/**
|
|
4025
|
-
* 生成交互摘要
|
|
4026
|
-
*/
|
|
4027
|
-
generateInteractionSummary() {
|
|
4028
|
-
const summary = {
|
|
4029
|
-
totalInteractions: this.interactions.length,
|
|
4030
|
-
typeCount: {},
|
|
4031
|
-
uniqueElements: /* @__PURE__ */ new Set(),
|
|
4032
|
-
timeSpan: 0
|
|
4033
|
-
};
|
|
4034
|
-
this.interactions.forEach((interaction) => {
|
|
4035
|
-
summary.typeCount[interaction.type] = (summary.typeCount[interaction.type] || 0) + 1;
|
|
4036
|
-
if (interaction.element) {
|
|
4037
|
-
summary.uniqueElements.add(interaction.element);
|
|
4038
|
-
}
|
|
4039
|
-
});
|
|
4040
|
-
if (this.interactions.length > 1) {
|
|
4041
|
-
summary.timeSpan = this.interactions[this.interactions.length - 1].timestamp - this.interactions[0].timestamp;
|
|
4042
|
-
}
|
|
4043
|
-
return {
|
|
4044
|
-
...summary,
|
|
4045
|
-
uniqueElements: Array.from(summary.uniqueElements),
|
|
4046
|
-
mostCommonType: Object.entries(summary.typeCount).sort(([, a], [, b]) => b - a)[0]?.[0] || "unknown"
|
|
4047
|
-
};
|
|
4048
|
-
}
|
|
4049
|
-
/**
|
|
4050
|
-
* 清除交互历史
|
|
4051
|
-
*/
|
|
4052
|
-
clearInteractionHistory() {
|
|
4053
|
-
this.interactions = [];
|
|
4054
|
-
}
|
|
4055
|
-
/**
|
|
4056
|
-
* 更新追踪配置
|
|
4057
|
-
*/
|
|
4058
|
-
updateConfig(newConfig) {
|
|
4059
|
-
this.trackingConfig = { ...this.trackingConfig, ...newConfig };
|
|
4060
|
-
if (this.isTracking) {
|
|
4061
|
-
this.removeEventListeners();
|
|
4062
|
-
this.setupEventListeners();
|
|
4063
|
-
}
|
|
4064
|
-
}
|
|
4065
|
-
/**
|
|
4066
|
-
* 获取追踪状态
|
|
4067
|
-
*/
|
|
4068
|
-
isTrackingActive() {
|
|
4069
|
-
return this.isTracking;
|
|
4070
|
-
}
|
|
4071
|
-
/**
|
|
4072
|
-
* 销毁交互追踪
|
|
4073
|
-
*/
|
|
4074
|
-
destroy() {
|
|
4075
|
-
this.stopTracking();
|
|
4076
|
-
this.interactions = [];
|
|
4077
|
-
console.log("[InteractionTracking] \u4EA4\u4E92\u8FFD\u8E2A\u6A21\u5757\u5DF2\u9500\u6BC1");
|
|
4078
|
-
}
|
|
4079
|
-
};
|
|
4080
|
-
|
|
4081
|
-
// src/utils/unified-error-handler/features/ElementSelector.ts
|
|
4082
|
-
var ElementSelector2 = class {
|
|
4083
|
-
constructor(sendMessage) {
|
|
4084
|
-
this.config = { ...DEFAULT_SELECTOR_CONFIG };
|
|
4085
|
-
this.isActive = false;
|
|
4086
|
-
this.highlightedElement = null;
|
|
4087
|
-
this.selectedElements = [];
|
|
4088
|
-
this.rootElement = null;
|
|
4089
|
-
this.tooltip = null;
|
|
4090
|
-
this.styleElement = null;
|
|
4091
|
-
this.eventListeners = [];
|
|
4092
|
-
this.lastClickTimestamp = 0;
|
|
4093
|
-
this.lastClickTarget = null;
|
|
4094
|
-
this.mousePosition = { x: 0, y: 0 };
|
|
4095
|
-
this.sendMessage = sendMessage;
|
|
4096
|
-
this.initializeSelector();
|
|
4097
|
-
}
|
|
4098
|
-
/** ----------------- 初始化方法 ----------------- */
|
|
4099
|
-
/**
|
|
4100
|
-
* 初始化选择器
|
|
4101
|
-
*/
|
|
4102
|
-
initializeSelector() {
|
|
4103
|
-
this.waitForRootElement();
|
|
4104
|
-
this.createTooltip();
|
|
4105
|
-
this.createStyles();
|
|
4106
|
-
}
|
|
4107
|
-
/**
|
|
4108
|
-
* 等待根元素加载
|
|
4109
|
-
*/
|
|
4110
|
-
async waitForRootElement() {
|
|
4111
|
-
const maxAttempts = 50;
|
|
4112
|
-
let attempts = 0;
|
|
4113
|
-
while (attempts < maxAttempts) {
|
|
4114
|
-
this.rootElement = document.querySelector("#root") || document.body;
|
|
4115
|
-
if (this.rootElement) {
|
|
4116
|
-
break;
|
|
4117
|
-
}
|
|
4118
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
4119
|
-
attempts++;
|
|
4120
|
-
}
|
|
4121
|
-
if (!this.rootElement) {
|
|
4122
|
-
this.rootElement = document.body;
|
|
4123
|
-
}
|
|
4124
|
-
}
|
|
4125
|
-
/**
|
|
4126
|
-
* 创建工具提示
|
|
4127
|
-
*/
|
|
4128
|
-
createTooltip() {
|
|
4129
|
-
this.tooltip = document.createElement("div");
|
|
4130
|
-
this.tooltip.className = "element-selector-tooltip";
|
|
4131
|
-
this.tooltip.setAttribute("role", "tooltip");
|
|
4132
|
-
this.tooltip.style.display = "none";
|
|
4133
|
-
document.body.appendChild(this.tooltip);
|
|
4134
|
-
}
|
|
4135
|
-
/**
|
|
4136
|
-
* 创建样式
|
|
4137
|
-
*/
|
|
4138
|
-
createStyles() {
|
|
4139
|
-
this.styleElement = document.createElement("style");
|
|
4140
|
-
this.styleElement.id = "element-selector-styles";
|
|
4141
|
-
this.styleElement.textContent = this.generateCSS();
|
|
4142
|
-
document.head.appendChild(this.styleElement);
|
|
4143
|
-
}
|
|
4144
|
-
/**
|
|
4145
|
-
* 生成 CSS 样式
|
|
4146
|
-
*/
|
|
4147
|
-
generateCSS() {
|
|
4148
|
-
return `
|
|
4149
|
-
.element-selector-tooltip {
|
|
4150
|
-
position: fixed;
|
|
4151
|
-
z-index: ${this.config.TOOLTIP_Z_INDEX};
|
|
4152
|
-
pointer-events: none;
|
|
4153
|
-
background-color: ${this.config.TOOLTIP_BACKGROUND};
|
|
4154
|
-
color: ${this.config.TOOLTIP_COLOR};
|
|
4155
|
-
padding: ${this.config.TOOLTIP_PADDING};
|
|
4156
|
-
border-radius: ${this.config.TOOLTIP_BORDER_RADIUS};
|
|
4157
|
-
font-size: ${this.config.TOOLTIP_FONT_SIZE};
|
|
4158
|
-
font-weight: bold;
|
|
4159
|
-
line-height: 1;
|
|
4160
|
-
white-space: nowrap;
|
|
4161
|
-
box-shadow: 0 2px 4px rgba(0,0,0,0.2);
|
|
4162
|
-
transition: opacity 0.2s ease-in-out;
|
|
4163
|
-
margin: 0;
|
|
4164
|
-
}
|
|
4165
|
-
|
|
4166
|
-
[data-element-hovered] {
|
|
4167
|
-
position: relative;
|
|
4168
|
-
outline: ${this.config.HIGHLIGHT_BORDER_WIDTH} ${this.config.HIGHLIGHT_BORDER_STYLE} ${this.config.HIGHLIGHT_COLOR} !important;
|
|
4169
|
-
outline-offset: 0 !important;
|
|
4170
|
-
background-color: ${this.config.HIGHLIGHT_COLOR}20 !important;
|
|
4171
|
-
z-index: 9999;
|
|
4172
|
-
}
|
|
4173
|
-
|
|
4174
|
-
[data-element-selected] {
|
|
4175
|
-
position: relative;
|
|
4176
|
-
outline: ${this.config.SELECTED_BORDER_WIDTH} ${this.config.HIGHLIGHT_BORDER_STYLE} ${this.config.SELECTED_COLOR} !important;
|
|
4177
|
-
outline-offset: 3px !important;
|
|
4178
|
-
background-color: ${this.config.SELECTED_COLOR}15 !important;
|
|
4179
|
-
z-index: 9999;
|
|
4180
|
-
}
|
|
4181
|
-
|
|
4182
|
-
[data-element-selected][contenteditable] {
|
|
4183
|
-
outline: none !important;
|
|
4184
|
-
}
|
|
4185
|
-
|
|
4186
|
-
[data-element-hovered][data-full-width],
|
|
4187
|
-
[data-element-selected][data-full-width] {
|
|
4188
|
-
outline-offset: -5px !important;
|
|
4189
|
-
}
|
|
4190
|
-
|
|
4191
|
-
.element-selector-active {
|
|
4192
|
-
cursor: ${this.config.cursor} !important;
|
|
4193
|
-
}
|
|
4194
|
-
|
|
4195
|
-
.element-selector-active * {
|
|
4196
|
-
cursor: ${this.config.cursor} !important;
|
|
4197
|
-
}
|
|
4198
|
-
|
|
4199
|
-
/* \u963B\u6B62\u539F\u751F hover \u6548\u679C\u7684\u5168\u5C40\u6837\u5F0F */
|
|
4200
|
-
body.element-selector-active * {
|
|
4201
|
-
/* \u963B\u6B62\u539F\u751F CSS hover \u4F2A\u7C7B\u6548\u679C */
|
|
4202
|
-
transition: none !important;
|
|
4203
|
-
}
|
|
4204
|
-
|
|
4205
|
-
/* \u963B\u6B62\u6240\u6709 hover \u76F8\u5173\u7684 CSS \u4F2A\u7C7B\uFF0C\u4F46\u6392\u9664\u6211\u4EEC\u7684\u9009\u62E9\u5668\u5143\u7D20 */
|
|
4206
|
-
body.element-selector-active *:hover:not([data-element-selected]):not([data-element-hovered]) {
|
|
4207
|
-
background-color: inherit !important;
|
|
4208
|
-
color: inherit !important;
|
|
4209
|
-
border-color: inherit !important;
|
|
4210
|
-
box-shadow: inherit !important;
|
|
4211
|
-
transform: inherit !important;
|
|
4212
|
-
opacity: inherit !important;
|
|
4213
|
-
filter: inherit !important;
|
|
4214
|
-
}
|
|
4215
|
-
|
|
4216
|
-
/* \u786E\u4FDD\u6211\u4EEC\u7684\u9009\u62E9\u5668\u6837\u5F0F\u4F18\u5148\u7EA7\u6700\u9AD8 */
|
|
4217
|
-
body.element-selector-active [data-element-selected] {
|
|
4218
|
-
background-color: ${this.config.SELECTED_COLOR}15 !important;
|
|
4219
|
-
outline: ${this.config.SELECTED_BORDER_WIDTH} ${this.config.HIGHLIGHT_BORDER_STYLE} ${this.config.SELECTED_COLOR} !important;
|
|
4220
|
-
}
|
|
4221
|
-
|
|
4222
|
-
body.element-selector-active [data-element-hovered] {
|
|
4223
|
-
background-color: ${this.config.HIGHLIGHT_COLOR}20 !important;
|
|
4224
|
-
outline: ${this.config.HIGHLIGHT_BORDER_WIDTH} ${this.config.HIGHLIGHT_BORDER_STYLE} ${this.config.HIGHLIGHT_COLOR} !important;
|
|
4225
|
-
}
|
|
4226
|
-
|
|
4227
|
-
/* \u786E\u4FDD\u5DE5\u5177\u63D0\u793A\u4E0D\u53D7\u5F71\u54CD */
|
|
4228
|
-
body.element-selector-active .element-selector-tooltip {
|
|
4229
|
-
pointer-events: none !important;
|
|
4230
|
-
}
|
|
4231
|
-
`;
|
|
4232
|
-
}
|
|
4233
|
-
/** ----------------- 选择器状态管理 ----------------- */
|
|
4234
|
-
/**
|
|
4235
|
-
* 启用选择器
|
|
4236
|
-
*/
|
|
4237
|
-
enableSelector() {
|
|
4238
|
-
if (this.isActive) return;
|
|
4239
|
-
this.isActive = true;
|
|
4240
|
-
document.body.classList.add("element-selector-active");
|
|
4241
|
-
this.setupEventListeners();
|
|
4242
|
-
this.manageButtonStates(true);
|
|
4243
|
-
this.sendMessage({
|
|
4244
|
-
type: "SELECTOR_ENABLED",
|
|
4245
|
-
payload: { isActive: true }
|
|
4246
|
-
});
|
|
4247
|
-
}
|
|
4248
|
-
/**
|
|
4249
|
-
* 禁用选择器
|
|
4250
|
-
*/
|
|
4251
|
-
disableSelector() {
|
|
4252
|
-
if (!this.isActive) return;
|
|
4253
|
-
this.isActive = false;
|
|
4254
|
-
document.body.classList.remove("element-selector-active");
|
|
4255
|
-
this.removeEventListeners();
|
|
4256
|
-
this.clearHighlight();
|
|
4257
|
-
this.clearSelection();
|
|
4258
|
-
this.manageButtonStates(false);
|
|
4259
|
-
this.hideTooltip();
|
|
4260
|
-
this.sendMessage({
|
|
4261
|
-
type: "SELECTOR_DISABLED",
|
|
4262
|
-
payload: { isActive: false }
|
|
4263
|
-
});
|
|
4264
|
-
}
|
|
4265
|
-
/**
|
|
4266
|
-
* 切换选择器状态
|
|
4267
|
-
*/
|
|
4268
|
-
toggleSelector() {
|
|
4269
|
-
if (this.isActive) {
|
|
4270
|
-
this.disableSelector();
|
|
4271
|
-
} else {
|
|
4272
|
-
this.enableSelector();
|
|
4273
|
-
}
|
|
4274
|
-
}
|
|
4275
|
-
/**
|
|
4276
|
-
* 获取选择器状态
|
|
4277
|
-
*/
|
|
4278
|
-
getSelectorState() {
|
|
4279
|
-
return {
|
|
4280
|
-
isActive: this.isActive,
|
|
4281
|
-
highlightedElement: this.highlightedElement ? this.getElementInfo(this.highlightedElement) : null,
|
|
4282
|
-
selectedElements: this.selectedElements.map((el) => this.getElementInfo(el)),
|
|
4283
|
-
config: { ...this.config }
|
|
4284
|
-
};
|
|
4285
|
-
}
|
|
4286
|
-
/** ----------------- 事件监听器管理 ----------------- */
|
|
4287
|
-
/**
|
|
4288
|
-
* 设置事件监听器
|
|
4289
|
-
*/
|
|
4290
|
-
setupEventListeners() {
|
|
4291
|
-
this.addEventListenerWithCleanup(document, "mouseover", this.handleMouseOver.bind(this), { passive: true });
|
|
4292
|
-
this.addEventListenerWithCleanup(document, "mouseout", this.handleMouseOut.bind(this), { passive: true });
|
|
4293
|
-
this.addEventListenerWithCleanup(document, "mousemove", this.trackMousePosition.bind(this), { passive: true });
|
|
4294
|
-
this.addEventListenerWithCleanup(document, "click", this.handleClick.bind(this), { capture: true });
|
|
4295
|
-
this.addEventListenerWithCleanup(document, "dblclick", this.handleDoubleClick.bind(this), { capture: true });
|
|
4296
|
-
this.addEventListenerWithCleanup(window, "scroll", this.handleScroll.bind(this), { passive: true });
|
|
4297
|
-
this.addEventListenerWithCleanup(document, "keydown", this.handleKeyDown.bind(this));
|
|
4298
|
-
this.addEventListenerWithCleanup(document, "mousedown", this.preventFormInteraction.bind(this), { capture: true });
|
|
4299
|
-
this.addEventListenerWithCleanup(document, "submit", this.preventAllInteraction.bind(this), { capture: true });
|
|
4300
|
-
this.addEventListenerWithCleanup(document, "touchstart", this.preventAllInteraction.bind(this), { capture: true });
|
|
4301
|
-
this.addEventListenerWithCleanup(document, "touchend", this.preventAllInteraction.bind(this), { capture: true });
|
|
4302
|
-
}
|
|
4303
|
-
/**
|
|
4304
|
-
* 添加事件监听器并记录以便清理
|
|
4305
|
-
*/
|
|
4306
|
-
addEventListenerWithCleanup(element, event, handler, options) {
|
|
4307
|
-
element.addEventListener(event, handler, options);
|
|
4308
|
-
this.eventListeners.push({ element, event, handler, options });
|
|
4309
|
-
}
|
|
4310
|
-
/**
|
|
4311
|
-
* 移除所有事件监听器
|
|
4312
|
-
*/
|
|
4313
|
-
removeEventListeners() {
|
|
4314
|
-
this.eventListeners.forEach(({ element, event, handler }) => {
|
|
4315
|
-
element.removeEventListener(event, handler);
|
|
4316
|
-
});
|
|
4317
|
-
this.eventListeners = [];
|
|
4318
|
-
}
|
|
4319
|
-
/** ----------------- 事件处理方法 ----------------- */
|
|
4320
|
-
/**
|
|
4321
|
-
* 跟踪鼠标位置
|
|
4322
|
-
*/
|
|
4323
|
-
trackMousePosition(event) {
|
|
4324
|
-
this.mousePosition = { x: event.clientX, y: event.clientY };
|
|
4325
|
-
}
|
|
4326
|
-
/**
|
|
4327
|
-
* 处理鼠标悬停
|
|
4328
|
-
*/
|
|
4329
|
-
handleMouseOver(event) {
|
|
4330
|
-
if (!this.isActive) return;
|
|
4331
|
-
const target = event.target;
|
|
4332
|
-
if (!this.isSelectableElement(target)) return;
|
|
4333
|
-
this.highlightElement(target);
|
|
4334
|
-
this.updateTooltip(target);
|
|
4335
|
-
}
|
|
4336
|
-
/**
|
|
4337
|
-
* 处理鼠标离开
|
|
4338
|
-
*/
|
|
4339
|
-
handleMouseOut(event) {
|
|
4340
|
-
if (!this.isActive) return;
|
|
4341
|
-
this.clearHighlight();
|
|
4342
|
-
this.hideTooltip();
|
|
4343
|
-
}
|
|
4344
|
-
/**
|
|
4345
|
-
* 处理点击
|
|
4346
|
-
*/
|
|
4347
|
-
handleClick(event) {
|
|
4348
|
-
if (!this.isActive) return;
|
|
4349
|
-
const currentTimestamp = Date.now();
|
|
4350
|
-
const target = event.target;
|
|
4351
|
-
if (this.lastClickTarget === target && currentTimestamp - this.lastClickTimestamp < 100) {
|
|
4352
|
-
event.preventDefault();
|
|
4353
|
-
event.stopPropagation();
|
|
4354
|
-
return;
|
|
4355
|
-
}
|
|
4356
|
-
this.lastClickTimestamp = currentTimestamp;
|
|
4357
|
-
this.lastClickTarget = target;
|
|
4358
|
-
event.preventDefault();
|
|
4359
|
-
event.stopPropagation();
|
|
4360
|
-
if (!this.isSelectableElement(target)) return;
|
|
4361
|
-
if (event.metaKey || event.ctrlKey) {
|
|
4362
|
-
this.toggleElementSelection(target);
|
|
4363
|
-
} else {
|
|
4364
|
-
this.selectElement(target);
|
|
4365
|
-
}
|
|
4366
|
-
this.sendMessage({
|
|
4367
|
-
type: "ELEMENT_CLICKED",
|
|
4368
|
-
payload: {
|
|
4369
|
-
element: this.getElementInfo(target),
|
|
4370
|
-
isMultiSelect: event.metaKey || event.ctrlKey
|
|
4371
|
-
}
|
|
4372
|
-
});
|
|
4373
|
-
}
|
|
4374
|
-
/**
|
|
4375
|
-
* 处理双击
|
|
4376
|
-
*/
|
|
4377
|
-
handleDoubleClick(event) {
|
|
4378
|
-
if (!this.isActive) return;
|
|
4379
|
-
event.preventDefault();
|
|
4380
|
-
event.stopPropagation();
|
|
4381
|
-
const target = event.target;
|
|
4382
|
-
if (!this.isSelectableElement(target)) return;
|
|
4383
|
-
this.sendMessage({
|
|
4384
|
-
type: "ELEMENT_DOUBLE_CLICKED",
|
|
4385
|
-
payload: {
|
|
4386
|
-
element: this.getElementInfo(target)
|
|
4387
|
-
}
|
|
4388
|
-
});
|
|
4389
|
-
}
|
|
4390
|
-
/**
|
|
4391
|
-
* 处理滚动
|
|
4392
|
-
*/
|
|
4393
|
-
handleScroll() {
|
|
4394
|
-
if (!this.isActive) return;
|
|
4395
|
-
this.hideTooltip();
|
|
4396
|
-
}
|
|
4397
|
-
/**
|
|
4398
|
-
* 处理键盘事件
|
|
4399
|
-
*/
|
|
4400
|
-
handleKeyDown(event) {
|
|
4401
|
-
if (!this.isActive) return;
|
|
4402
|
-
const keyboardEvent = event;
|
|
4403
|
-
if (keyboardEvent.key === "Escape") {
|
|
4404
|
-
event.preventDefault();
|
|
4405
|
-
event.stopPropagation();
|
|
4406
|
-
this.disableSelector();
|
|
4407
|
-
}
|
|
4408
|
-
}
|
|
4409
|
-
/**
|
|
4410
|
-
* 阻止表单交互
|
|
4411
|
-
*/
|
|
4412
|
-
preventFormInteraction(event) {
|
|
4413
|
-
if (!this.isActive) return;
|
|
4414
|
-
const target = event.target;
|
|
4415
|
-
if (["input", "textarea", "select"].includes(target.tagName.toLowerCase())) {
|
|
4416
|
-
event.preventDefault();
|
|
4417
|
-
}
|
|
4418
|
-
}
|
|
4419
|
-
/**
|
|
4420
|
-
* 阻止所有交互
|
|
4421
|
-
*/
|
|
4422
|
-
preventAllInteraction(event) {
|
|
4423
|
-
if (this.isActive) {
|
|
4424
|
-
event.preventDefault();
|
|
4425
|
-
event.stopPropagation();
|
|
4426
|
-
return false;
|
|
4427
|
-
}
|
|
4428
|
-
}
|
|
4429
|
-
/** ----------------- 元素操作方法 ----------------- */
|
|
4430
|
-
/**
|
|
4431
|
-
* 高亮元素
|
|
4432
|
-
*/
|
|
4433
|
-
highlightElement(element) {
|
|
4434
|
-
this.clearHighlight();
|
|
4435
|
-
this.highlightedElement = element;
|
|
4436
|
-
element.setAttribute("data-element-hovered", "true");
|
|
4437
|
-
if (this.isFullWidthElement(element)) {
|
|
4438
|
-
element.setAttribute("data-full-width", "true");
|
|
4439
|
-
}
|
|
4440
|
-
}
|
|
4441
|
-
/**
|
|
4442
|
-
* 清除高亮
|
|
4443
|
-
*/
|
|
4444
|
-
clearHighlight() {
|
|
4445
|
-
if (this.highlightedElement) {
|
|
4446
|
-
this.highlightedElement.removeAttribute("data-element-hovered");
|
|
4447
|
-
this.highlightedElement.removeAttribute("data-full-width");
|
|
4448
|
-
this.highlightedElement = null;
|
|
4449
|
-
}
|
|
4450
|
-
}
|
|
4451
|
-
/**
|
|
4452
|
-
* 选择元素
|
|
4453
|
-
*/
|
|
4454
|
-
selectElement(element) {
|
|
4455
|
-
this.clearSelection();
|
|
4456
|
-
this.selectedElements = [element];
|
|
4457
|
-
element.setAttribute("data-element-selected", "true");
|
|
4458
|
-
if (this.isFullWidthElement(element)) {
|
|
4459
|
-
element.setAttribute("data-full-width", "true");
|
|
4460
|
-
}
|
|
4461
|
-
}
|
|
4462
|
-
/**
|
|
4463
|
-
* 切换元素选择状态
|
|
4464
|
-
*/
|
|
4465
|
-
toggleElementSelection(element) {
|
|
4466
|
-
const index = this.selectedElements.indexOf(element);
|
|
4467
|
-
if (index > -1) {
|
|
4468
|
-
this.selectedElements.splice(index, 1);
|
|
4469
|
-
element.removeAttribute("data-element-selected");
|
|
4470
|
-
element.removeAttribute("data-full-width");
|
|
4471
|
-
} else {
|
|
4472
|
-
this.selectedElements.push(element);
|
|
4473
|
-
element.setAttribute("data-element-selected", "true");
|
|
4474
|
-
if (this.isFullWidthElement(element)) {
|
|
4475
|
-
element.setAttribute("data-full-width", "true");
|
|
4476
|
-
}
|
|
4477
|
-
}
|
|
4478
|
-
}
|
|
4479
|
-
/**
|
|
4480
|
-
* 清除选择
|
|
4481
|
-
*/
|
|
4482
|
-
clearSelection() {
|
|
4483
|
-
this.selectedElements.forEach((element) => {
|
|
4484
|
-
element.removeAttribute("data-element-selected");
|
|
4485
|
-
element.removeAttribute("data-full-width");
|
|
4486
|
-
});
|
|
4487
|
-
this.selectedElements = [];
|
|
4488
|
-
}
|
|
4489
|
-
/** ----------------- 工具提示管理 ----------------- */
|
|
4490
|
-
/**
|
|
4491
|
-
* 更新工具提示
|
|
4492
|
-
*/
|
|
4493
|
-
updateTooltip(element) {
|
|
4494
|
-
if (!this.tooltip) return;
|
|
4495
|
-
const rect = element.getBoundingClientRect();
|
|
4496
|
-
const tagName = element.tagName.toLowerCase();
|
|
4497
|
-
this.tooltip.textContent = tagName;
|
|
4498
|
-
this.tooltip.style.display = "block";
|
|
4499
|
-
const isFullWidth = this.isFullWidthElement(element);
|
|
4500
|
-
if (isFullWidth) {
|
|
4501
|
-
this.tooltip.style.left = this.config.FULL_WIDTH_TOOLTIP_OFFSET + "px";
|
|
4502
|
-
this.tooltip.style.top = this.config.FULL_WIDTH_TOOLTIP_OFFSET + "px";
|
|
4503
|
-
} else {
|
|
4504
|
-
const top = Math.max(0, rect.top - 30);
|
|
4505
|
-
this.tooltip.style.left = `${Math.max(0, rect.left)}px`;
|
|
4506
|
-
this.tooltip.style.top = `${top}px`;
|
|
4507
|
-
}
|
|
4508
|
-
}
|
|
4509
|
-
/**
|
|
4510
|
-
* 隐藏工具提示
|
|
4511
|
-
*/
|
|
4512
|
-
hideTooltip() {
|
|
4513
|
-
if (this.tooltip) {
|
|
4514
|
-
this.tooltip.style.display = "none";
|
|
4515
|
-
}
|
|
4516
|
-
}
|
|
4517
|
-
/** ----------------- 按钮状态管理 ----------------- */
|
|
4518
|
-
/**
|
|
4519
|
-
* 管理按钮状态
|
|
4520
|
-
*/
|
|
4521
|
-
manageButtonStates(enable) {
|
|
4522
|
-
if (!this.rootElement) return;
|
|
4523
|
-
const buttons = this.rootElement.querySelectorAll('button, input[type="button"], input[type="submit"]');
|
|
4524
|
-
if (enable) {
|
|
4525
|
-
buttons.forEach((button) => {
|
|
4526
|
-
const btn = button;
|
|
4527
|
-
if (!btn.disabled) {
|
|
4528
|
-
btn.disabled = true;
|
|
4529
|
-
btn.setAttribute("data-selector-disabled", "true");
|
|
4530
|
-
}
|
|
4531
|
-
});
|
|
4532
|
-
} else {
|
|
4533
|
-
buttons.forEach((button) => {
|
|
4534
|
-
const btn = button;
|
|
4535
|
-
if (btn.hasAttribute("data-selector-disabled")) {
|
|
4536
|
-
btn.disabled = false;
|
|
4537
|
-
btn.removeAttribute("data-selector-disabled");
|
|
4538
|
-
}
|
|
4539
|
-
});
|
|
4540
|
-
}
|
|
4541
|
-
}
|
|
4542
|
-
/** ----------------- 新增的精确代码位置定位方法 ----------------- */
|
|
4543
|
-
/**
|
|
4544
|
-
* 检查元素是否有 howone ID
|
|
4545
|
-
*/
|
|
4546
|
-
hasHowoneId(element) {
|
|
4547
|
-
return element.hasAttribute("data-howone-id");
|
|
4548
|
-
}
|
|
4549
|
-
/**
|
|
4550
|
-
* 解析 howone ID
|
|
4551
|
-
*/
|
|
4552
|
-
parseHowoneId(element) {
|
|
4553
|
-
const howoneId = element.getAttribute("data-howone-id");
|
|
4554
|
-
if (!howoneId) return null;
|
|
4555
|
-
try {
|
|
4556
|
-
if (howoneId.includes(":")) {
|
|
4557
|
-
const parts = howoneId.split(":");
|
|
4558
|
-
if (parts.length >= 2) {
|
|
4559
|
-
return {
|
|
4560
|
-
filePath: parts[0],
|
|
4561
|
-
lineNumber: parseInt(parts[1], 10),
|
|
4562
|
-
col: parts[2] ? parseInt(parts[2], 10) : 0
|
|
4563
|
-
};
|
|
4564
|
-
}
|
|
4565
|
-
} else {
|
|
4566
|
-
const parsed = JSON.parse(howoneId);
|
|
4567
|
-
if (parsed.filePath && parsed.lineNumber) {
|
|
4568
|
-
return {
|
|
4569
|
-
filePath: parsed.filePath,
|
|
4570
|
-
lineNumber: parsed.lineNumber,
|
|
4571
|
-
col: parsed.col || 0
|
|
4572
|
-
};
|
|
4573
|
-
}
|
|
4574
|
-
}
|
|
4575
|
-
} catch (error) {
|
|
4576
|
-
console.warn("[ElementSelector] \u89E3\u6790 data-howone-id \u5931\u8D25:", error);
|
|
4577
|
-
}
|
|
4578
|
-
return null;
|
|
4579
|
-
}
|
|
4580
|
-
/**
|
|
4581
|
-
* 获取元素的代码位置
|
|
4582
|
-
*/
|
|
4583
|
-
getElementLocation(element) {
|
|
4584
|
-
return this.parseHowoneId(element);
|
|
4585
|
-
}
|
|
4586
|
-
/**
|
|
4587
|
-
* 提取元素数据(包含位置信息)
|
|
4588
|
-
*/
|
|
4589
|
-
extractElementData(element) {
|
|
4590
|
-
const location = this.getElementLocation(element);
|
|
4591
|
-
return {
|
|
4592
|
-
id: element.id || void 0,
|
|
4593
|
-
className: element.className || void 0,
|
|
4594
|
-
textContent: element.textContent?.trim().substring(0, 100) || void 0,
|
|
4595
|
-
filePath: location?.filePath,
|
|
4596
|
-
lineNumber: location?.lineNumber,
|
|
4597
|
-
col: location?.col,
|
|
4598
|
-
elementType: element.tagName.toLowerCase(),
|
|
4599
|
-
attrs: this.getElementAttributes(element)
|
|
4600
|
-
};
|
|
4601
|
-
}
|
|
4602
|
-
/**
|
|
4603
|
-
* 根据代码位置查找元素
|
|
4604
|
-
*/
|
|
4605
|
-
findElementsByLocation(filePath, lineNumber) {
|
|
4606
|
-
const elements = [];
|
|
4607
|
-
const elementsWithHowoneId = this.rootElement?.querySelectorAll("[data-howone-id]") || [];
|
|
4608
|
-
elementsWithHowoneId.forEach((element) => {
|
|
4609
|
-
const location = this.getElementLocation(element);
|
|
4610
|
-
if (location && location.filePath === filePath && location.lineNumber === lineNumber) {
|
|
4611
|
-
elements.push(element);
|
|
4612
|
-
}
|
|
4613
|
-
});
|
|
4614
|
-
return elements;
|
|
4615
|
-
}
|
|
4616
|
-
/**
|
|
4617
|
-
* 获取指定坐标位置的元素
|
|
4618
|
-
*/
|
|
4619
|
-
getElementAtPoint(x, y) {
|
|
4620
|
-
const originalDisplay = this.tooltip?.style.display;
|
|
4621
|
-
if (this.tooltip) {
|
|
4622
|
-
this.tooltip.style.display = "none";
|
|
4623
|
-
}
|
|
4624
|
-
const element = document.elementFromPoint(x, y);
|
|
4625
|
-
if (this.tooltip && originalDisplay) {
|
|
4626
|
-
this.tooltip.style.display = originalDisplay;
|
|
4627
|
-
}
|
|
4628
|
-
return element;
|
|
4629
|
-
}
|
|
4630
|
-
/** ----------------- 元素编辑功能 ----------------- */
|
|
4631
|
-
/**
|
|
4632
|
-
* 设置元素内容
|
|
4633
|
-
*/
|
|
4634
|
-
setElementContent(selector, content) {
|
|
4635
|
-
try {
|
|
4636
|
-
const element = document.querySelector(selector);
|
|
4637
|
-
if (!element) return false;
|
|
4638
|
-
if (element.tagName.toLowerCase() === "input" || element.tagName.toLowerCase() === "textarea") {
|
|
4639
|
-
element.value = content;
|
|
4640
|
-
} else {
|
|
4641
|
-
element.textContent = content;
|
|
4642
|
-
}
|
|
4643
|
-
this.sendMessage({
|
|
4644
|
-
type: "ELEMENT_CONTENT_UPDATED",
|
|
4645
|
-
payload: {
|
|
4646
|
-
selector,
|
|
4647
|
-
content,
|
|
4648
|
-
element: this.getElementInfo(element)
|
|
4649
|
-
}
|
|
4650
|
-
});
|
|
4651
|
-
return true;
|
|
4652
|
-
} catch (error) {
|
|
4653
|
-
console.error("[ElementSelector] \u8BBE\u7F6E\u5143\u7D20\u5185\u5BB9\u5931\u8D25:", error);
|
|
4654
|
-
return false;
|
|
4655
|
-
}
|
|
4656
|
-
}
|
|
4657
|
-
/**
|
|
4658
|
-
* 设置元素属性
|
|
4659
|
-
*/
|
|
4660
|
-
setElementAttributes(selector, attributes) {
|
|
4661
|
-
try {
|
|
4662
|
-
const element = document.querySelector(selector);
|
|
4663
|
-
if (!element) return false;
|
|
4664
|
-
Object.entries(attributes).forEach(([key, value]) => {
|
|
4665
|
-
if (value === null || value === void 0) {
|
|
4666
|
-
element.removeAttribute(key);
|
|
4667
|
-
} else {
|
|
4668
|
-
element.setAttribute(key, value);
|
|
4669
|
-
}
|
|
4670
|
-
});
|
|
4671
|
-
this.sendMessage({
|
|
4672
|
-
type: "ELEMENT_ATTRIBUTES_UPDATED",
|
|
4673
|
-
payload: {
|
|
4674
|
-
selector,
|
|
4675
|
-
attributes,
|
|
4676
|
-
element: this.getElementInfo(element)
|
|
4677
|
-
}
|
|
4678
|
-
});
|
|
4679
|
-
return true;
|
|
4680
|
-
} catch (error) {
|
|
4681
|
-
console.error("[ElementSelector] \u8BBE\u7F6E\u5143\u7D20\u5C5E\u6027\u5931\u8D25:", error);
|
|
4682
|
-
return false;
|
|
4683
|
-
}
|
|
4684
|
-
}
|
|
4685
|
-
/**
|
|
4686
|
-
* 复制元素
|
|
4687
|
-
*/
|
|
4688
|
-
duplicateElement(selector) {
|
|
4689
|
-
try {
|
|
4690
|
-
const element = document.querySelector(selector);
|
|
4691
|
-
if (!element || !element.parentNode) return false;
|
|
4692
|
-
const clonedElement = element.cloneNode(true);
|
|
4693
|
-
clonedElement.removeAttribute("data-blnk-id");
|
|
4694
|
-
element.parentNode.insertBefore(clonedElement, element.nextSibling);
|
|
4695
|
-
this.sendMessage({
|
|
4696
|
-
type: "ELEMENT_DUPLICATED",
|
|
4697
|
-
payload: {
|
|
4698
|
-
originalSelector: selector,
|
|
4699
|
-
duplicatedElement: this.getElementInfo(clonedElement)
|
|
4700
|
-
}
|
|
4701
|
-
});
|
|
4702
|
-
return true;
|
|
4703
|
-
} catch (error) {
|
|
4704
|
-
console.error("[ElementSelector] \u590D\u5236\u5143\u7D20\u5931\u8D25:", error);
|
|
4705
|
-
return false;
|
|
4706
|
-
}
|
|
4707
|
-
}
|
|
4708
|
-
/**
|
|
4709
|
-
* 启用文本编辑
|
|
4710
|
-
*/
|
|
4711
|
-
enableTextEditing(selector) {
|
|
4712
|
-
try {
|
|
4713
|
-
const element = document.querySelector(selector);
|
|
4714
|
-
if (!element) return false;
|
|
4715
|
-
element.setAttribute("contenteditable", "true");
|
|
4716
|
-
element.setAttribute("data-editing", "true");
|
|
4717
|
-
element.focus();
|
|
4718
|
-
const handleEditComplete = () => {
|
|
4719
|
-
element.removeAttribute("contenteditable");
|
|
4720
|
-
element.removeAttribute("data-editing");
|
|
4721
|
-
element.removeEventListener("blur", handleEditComplete);
|
|
4722
|
-
element.removeEventListener("keydown", handleKeyDown);
|
|
4723
|
-
this.sendMessage({
|
|
4724
|
-
type: "ELEMENT_TEXT_UPDATED",
|
|
4725
|
-
payload: {
|
|
4726
|
-
selector,
|
|
4727
|
-
content: element.textContent || "",
|
|
4728
|
-
element: this.getElementInfo(element)
|
|
4729
|
-
}
|
|
4730
|
-
});
|
|
4731
|
-
};
|
|
4732
|
-
const handleKeyDown = (event) => {
|
|
4733
|
-
const keyboardEvent = event;
|
|
4734
|
-
if (keyboardEvent.key === "Enter" && !keyboardEvent.shiftKey) {
|
|
4735
|
-
event.preventDefault();
|
|
4736
|
-
handleEditComplete();
|
|
4737
|
-
} else if (keyboardEvent.key === "Escape") {
|
|
4738
|
-
event.preventDefault();
|
|
4739
|
-
handleEditComplete();
|
|
4740
|
-
}
|
|
4741
|
-
};
|
|
4742
|
-
element.addEventListener("blur", handleEditComplete);
|
|
4743
|
-
element.addEventListener("keydown", handleKeyDown);
|
|
4744
|
-
return true;
|
|
4745
|
-
} catch (error) {
|
|
4746
|
-
console.error("[ElementSelector] \u542F\u7528\u6587\u672C\u7F16\u8F91\u5931\u8D25:", error);
|
|
4747
|
-
return false;
|
|
4748
|
-
}
|
|
4749
|
-
}
|
|
4750
|
-
/** ----------------- 高级交互功能 ----------------- */
|
|
4751
|
-
/**
|
|
4752
|
-
* 获取父元素
|
|
4753
|
-
*/
|
|
4754
|
-
getParentElement(selector) {
|
|
4755
|
-
try {
|
|
4756
|
-
const element = document.querySelector(selector);
|
|
4757
|
-
return element?.parentElement || null;
|
|
4758
|
-
} catch (error) {
|
|
4759
|
-
console.error("[ElementSelector] \u83B7\u53D6\u7236\u5143\u7D20\u5931\u8D25:", error);
|
|
4760
|
-
return null;
|
|
4761
|
-
}
|
|
4762
|
-
}
|
|
4763
|
-
/**
|
|
4764
|
-
* 外部悬停控制 - 通过选择器悬停元素
|
|
4765
|
-
*/
|
|
4766
|
-
hoverElementBySelector(selector) {
|
|
4767
|
-
try {
|
|
4768
|
-
const element = document.querySelector(selector);
|
|
4769
|
-
if (!element) return false;
|
|
4770
|
-
this.highlightElement(element);
|
|
4771
|
-
this.updateTooltip(element);
|
|
4772
|
-
return true;
|
|
4773
|
-
} catch (error) {
|
|
4774
|
-
console.error("[ElementSelector] \u5916\u90E8\u60AC\u505C\u63A7\u5236\u5931\u8D25:", error);
|
|
4775
|
-
return false;
|
|
4776
|
-
}
|
|
3965
|
+
if (dataId) return `[data-id="${dataId}"]`;
|
|
3966
|
+
return element.tagName.toLowerCase();
|
|
4777
3967
|
}
|
|
4778
3968
|
/**
|
|
4779
|
-
*
|
|
3969
|
+
* 检查是否为敏感输入
|
|
4780
3970
|
*/
|
|
4781
|
-
|
|
4782
|
-
this.
|
|
4783
|
-
|
|
3971
|
+
isSensitiveInput(element) {
|
|
3972
|
+
if (!this.trackingConfig.sensitiveInputFilter) return false;
|
|
3973
|
+
const sensitiveTypes = ["password", "email", "tel", "ssn", "credit-card"];
|
|
3974
|
+
const sensitiveNames = ["password", "email", "phone", "ssn", "credit", "card", "cvv", "pin"];
|
|
3975
|
+
return sensitiveTypes.includes(element.type) || sensitiveNames.some(
|
|
3976
|
+
(name) => element.name?.toLowerCase().includes(name) || element.placeholder?.toLowerCase().includes(name) || element.id?.toLowerCase().includes(name)
|
|
3977
|
+
);
|
|
4784
3978
|
}
|
|
4785
|
-
/** ----------------- 辅助方法 ----------------- */
|
|
4786
3979
|
/**
|
|
4787
|
-
*
|
|
3980
|
+
* 管理数组长度
|
|
4788
3981
|
*/
|
|
4789
|
-
|
|
4790
|
-
|
|
4791
|
-
|
|
4792
|
-
return Math.abs(rect.width - window.innerWidth) < 5;
|
|
4793
|
-
} catch (error) {
|
|
4794
|
-
console.warn("[ElementSelector] \u68C0\u67E5\u5168\u5BBD\u5143\u7D20\u5931\u8D25:", error);
|
|
4795
|
-
return false;
|
|
3982
|
+
manageArrayLength(array, maxLength) {
|
|
3983
|
+
if (array.length > maxLength) {
|
|
3984
|
+
array.shift();
|
|
4796
3985
|
}
|
|
4797
3986
|
}
|
|
3987
|
+
/** ----------------- 公共接口方法 ----------------- */
|
|
4798
3988
|
/**
|
|
4799
|
-
*
|
|
3989
|
+
* 获取交互历史
|
|
4800
3990
|
*/
|
|
4801
|
-
|
|
4802
|
-
|
|
4803
|
-
return false;
|
|
4804
|
-
}
|
|
4805
|
-
if (this.hasHowoneId(element)) {
|
|
4806
|
-
return true;
|
|
4807
|
-
}
|
|
4808
|
-
if (element.id === "howone-element-tooltip" || element.classList.contains("howone-tooltip")) {
|
|
4809
|
-
return false;
|
|
4810
|
-
}
|
|
4811
|
-
const tagName = element.tagName.toLowerCase();
|
|
4812
|
-
if (["script", "style", "meta", "link", "title"].includes(tagName)) {
|
|
4813
|
-
return false;
|
|
4814
|
-
}
|
|
4815
|
-
return true;
|
|
3991
|
+
getInteractionHistory() {
|
|
3992
|
+
return [...this.interactions];
|
|
4816
3993
|
}
|
|
4817
3994
|
/**
|
|
4818
|
-
*
|
|
3995
|
+
* 获取最近的交互记录
|
|
4819
3996
|
*/
|
|
4820
|
-
|
|
4821
|
-
|
|
4822
|
-
return {
|
|
4823
|
-
tagName: element.tagName.toLowerCase(),
|
|
4824
|
-
id: element.id || void 0,
|
|
4825
|
-
className: element.className || void 0,
|
|
4826
|
-
textContent: element.textContent?.trim().substring(0, 100) || void 0,
|
|
4827
|
-
attributes: this.getElementAttributes(element),
|
|
4828
|
-
selector: this.getElementSelector(element),
|
|
4829
|
-
boundingRect: element.getBoundingClientRect(),
|
|
4830
|
-
location: location || void 0
|
|
4831
|
-
};
|
|
3997
|
+
getRecentInteractions(count = 8) {
|
|
3998
|
+
return this.interactions.slice(-count);
|
|
4832
3999
|
}
|
|
4833
4000
|
/**
|
|
4834
|
-
*
|
|
4001
|
+
* 手动发送交互数据到父窗口(用于测试或特殊情况)
|
|
4835
4002
|
*/
|
|
4836
|
-
|
|
4837
|
-
|
|
4838
|
-
|
|
4839
|
-
|
|
4840
|
-
|
|
4841
|
-
|
|
4842
|
-
|
|
4843
|
-
|
|
4003
|
+
sendInteractionData() {
|
|
4004
|
+
if (this.interactions.length === 0) return;
|
|
4005
|
+
this.sendMessage({
|
|
4006
|
+
type: "INTERACTION_EVENT",
|
|
4007
|
+
payload: {
|
|
4008
|
+
type: "summary",
|
|
4009
|
+
interactions: this.interactions,
|
|
4010
|
+
count: this.interactions.length,
|
|
4011
|
+
timeRange: {
|
|
4012
|
+
start: this.interactions[0]?.timestamp || Date.now(),
|
|
4013
|
+
end: this.interactions[this.interactions.length - 1]?.timestamp || Date.now()
|
|
4014
|
+
},
|
|
4015
|
+
summary: this.generateInteractionSummary()
|
|
4016
|
+
},
|
|
4017
|
+
timestamp: Date.now()
|
|
4844
4018
|
});
|
|
4845
|
-
return attrs;
|
|
4846
4019
|
}
|
|
4847
4020
|
/**
|
|
4848
|
-
*
|
|
4021
|
+
* 生成交互摘要
|
|
4849
4022
|
*/
|
|
4850
|
-
|
|
4851
|
-
const
|
|
4852
|
-
|
|
4853
|
-
|
|
4854
|
-
|
|
4855
|
-
|
|
4856
|
-
|
|
4857
|
-
|
|
4858
|
-
|
|
4859
|
-
|
|
4860
|
-
|
|
4861
|
-
}
|
|
4862
|
-
if (element.className) {
|
|
4863
|
-
const classes = element.className.split(" ").filter((c) => c.trim());
|
|
4864
|
-
if (classes.length > 0) {
|
|
4865
|
-
return `.${classes[0]}`;
|
|
4023
|
+
generateInteractionSummary() {
|
|
4024
|
+
const summary = {
|
|
4025
|
+
totalInteractions: this.interactions.length,
|
|
4026
|
+
typeCount: {},
|
|
4027
|
+
uniqueElements: /* @__PURE__ */ new Set(),
|
|
4028
|
+
timeSpan: 0
|
|
4029
|
+
};
|
|
4030
|
+
this.interactions.forEach((interaction) => {
|
|
4031
|
+
summary.typeCount[interaction.type] = (summary.typeCount[interaction.type] || 0) + 1;
|
|
4032
|
+
if (interaction.element) {
|
|
4033
|
+
summary.uniqueElements.add(interaction.element);
|
|
4866
4034
|
}
|
|
4035
|
+
});
|
|
4036
|
+
if (this.interactions.length > 1) {
|
|
4037
|
+
summary.timeSpan = this.interactions[this.interactions.length - 1].timestamp - this.interactions[0].timestamp;
|
|
4867
4038
|
}
|
|
4868
|
-
return
|
|
4039
|
+
return {
|
|
4040
|
+
...summary,
|
|
4041
|
+
uniqueElements: Array.from(summary.uniqueElements),
|
|
4042
|
+
mostCommonType: Object.entries(summary.typeCount).sort(([, a], [, b]) => b - a)[0]?.[0] || "unknown"
|
|
4043
|
+
};
|
|
4869
4044
|
}
|
|
4870
|
-
/** ----------------- 公共接口方法 ----------------- */
|
|
4871
4045
|
/**
|
|
4872
|
-
*
|
|
4046
|
+
* 清除交互历史
|
|
4873
4047
|
*/
|
|
4874
|
-
|
|
4875
|
-
|
|
4876
|
-
if (element) {
|
|
4877
|
-
this.highlightElement(element);
|
|
4878
|
-
}
|
|
4048
|
+
clearInteractionHistory() {
|
|
4049
|
+
this.interactions = [];
|
|
4879
4050
|
}
|
|
4880
4051
|
/**
|
|
4881
|
-
*
|
|
4052
|
+
* 更新追踪配置
|
|
4882
4053
|
*/
|
|
4883
|
-
|
|
4884
|
-
|
|
4885
|
-
if (
|
|
4886
|
-
this.
|
|
4054
|
+
updateConfig(newConfig) {
|
|
4055
|
+
this.trackingConfig = { ...this.trackingConfig, ...newConfig };
|
|
4056
|
+
if (this.isTracking) {
|
|
4057
|
+
this.removeEventListeners();
|
|
4058
|
+
this.setupEventListeners();
|
|
4887
4059
|
}
|
|
4888
4060
|
}
|
|
4889
4061
|
/**
|
|
4890
|
-
*
|
|
4891
|
-
*/
|
|
4892
|
-
updateSelectedElements(elements) {
|
|
4893
|
-
this.clearSelection();
|
|
4894
|
-
elements.forEach((elementData) => {
|
|
4895
|
-
const element = this.findElementByData(elementData);
|
|
4896
|
-
if (element) {
|
|
4897
|
-
this.selectedElements.push(element);
|
|
4898
|
-
element.setAttribute("data-element-selected", "true");
|
|
4899
|
-
if (this.isFullWidthElement(element)) {
|
|
4900
|
-
element.setAttribute("data-full-width", "true");
|
|
4901
|
-
}
|
|
4902
|
-
}
|
|
4903
|
-
});
|
|
4904
|
-
}
|
|
4905
|
-
/**
|
|
4906
|
-
* 根据数据查找元素
|
|
4062
|
+
* 获取追踪状态
|
|
4907
4063
|
*/
|
|
4908
|
-
|
|
4909
|
-
|
|
4910
|
-
return document.querySelector(`[data-blnk-id="${elementData.blinkId}"]`);
|
|
4911
|
-
}
|
|
4912
|
-
if (elementData.id) {
|
|
4913
|
-
return document.getElementById(elementData.id);
|
|
4914
|
-
}
|
|
4915
|
-
if (elementData.selector) {
|
|
4916
|
-
return document.querySelector(elementData.selector);
|
|
4917
|
-
}
|
|
4918
|
-
return null;
|
|
4064
|
+
isTrackingActive() {
|
|
4065
|
+
return this.isTracking;
|
|
4919
4066
|
}
|
|
4920
4067
|
/**
|
|
4921
|
-
*
|
|
4068
|
+
* 销毁交互追踪
|
|
4922
4069
|
*/
|
|
4923
4070
|
destroy() {
|
|
4924
|
-
this.
|
|
4925
|
-
|
|
4926
|
-
this.tooltip.remove();
|
|
4927
|
-
this.tooltip = null;
|
|
4928
|
-
}
|
|
4929
|
-
if (this.styleElement) {
|
|
4930
|
-
this.styleElement.remove();
|
|
4931
|
-
this.styleElement = null;
|
|
4932
|
-
}
|
|
4071
|
+
this.stopTracking();
|
|
4072
|
+
this.interactions = [];
|
|
4933
4073
|
}
|
|
4934
4074
|
};
|
|
4935
4075
|
|
|
@@ -4943,7 +4083,6 @@ var getOriginalConsole2 = () => window.__originalConsole || {
|
|
|
4943
4083
|
};
|
|
4944
4084
|
var MessageBridge = class {
|
|
4945
4085
|
constructor(sendMessage) {
|
|
4946
|
-
this.elementSelector = null;
|
|
4947
4086
|
this.componentTreeGenerator = null;
|
|
4948
4087
|
this.messageSender = createDefaultMessageSender({
|
|
4949
4088
|
addTimestamp: true,
|
|
@@ -4951,15 +4090,8 @@ var MessageBridge = class {
|
|
|
4951
4090
|
});
|
|
4952
4091
|
this.sendMessage = sendMessage || this.messageSender.createSendFunction();
|
|
4953
4092
|
this.setupMessageListener();
|
|
4954
|
-
console.log("[MessageBridge] \u6D88\u606F\u6865\u63A5\u5668\u521D\u59CB\u5316\u5B8C\u6210");
|
|
4955
4093
|
}
|
|
4956
4094
|
/** ----------------- 依赖注入方法 ----------------- */
|
|
4957
|
-
/**
|
|
4958
|
-
* 设置元素选择器
|
|
4959
|
-
*/
|
|
4960
|
-
setElementSelector(elementSelector2) {
|
|
4961
|
-
this.elementSelector = elementSelector2;
|
|
4962
|
-
}
|
|
4963
4095
|
/**
|
|
4964
4096
|
* 设置组件树生成器
|
|
4965
4097
|
*/
|
|
@@ -4997,32 +4129,6 @@ var MessageBridge = class {
|
|
|
4997
4129
|
try {
|
|
4998
4130
|
const { type, payload } = message;
|
|
4999
4131
|
switch (type) {
|
|
5000
|
-
// 选择器相关消息
|
|
5001
|
-
case "TOGGLE_SELECTOR":
|
|
5002
|
-
this.handleToggleSelector(payload);
|
|
5003
|
-
break;
|
|
5004
|
-
case "ENABLE_SELECTOR":
|
|
5005
|
-
this.handleEnableElementSelector();
|
|
5006
|
-
break;
|
|
5007
|
-
case "DISABLE_SELECTOR":
|
|
5008
|
-
this.handleDisableElementSelector();
|
|
5009
|
-
break;
|
|
5010
|
-
case "GET_SELECTOR_STATE":
|
|
5011
|
-
this.handleGetSelectorState();
|
|
5012
|
-
break;
|
|
5013
|
-
// 元素操作消息
|
|
5014
|
-
case "HOVER_ELEMENT_BY_ID":
|
|
5015
|
-
this.handleHoverElementById(payload);
|
|
5016
|
-
break;
|
|
5017
|
-
case "UNHOVER_ELEMENT_BY_ID":
|
|
5018
|
-
this.handleUnhoverElementById(payload);
|
|
5019
|
-
break;
|
|
5020
|
-
case "HOVER_ELEMENT_REQUESTED":
|
|
5021
|
-
this.handleHoverElementRequested(payload);
|
|
5022
|
-
break;
|
|
5023
|
-
case "UNHOVER_ELEMENT_REQUESTED":
|
|
5024
|
-
this.handleUnhoverElementRequested(payload);
|
|
5025
|
-
break;
|
|
5026
4132
|
case "SET_ELEMENT_CONTENT":
|
|
5027
4133
|
this.handleSetElementContent(payload);
|
|
5028
4134
|
break;
|
|
@@ -5035,28 +4141,6 @@ var MessageBridge = class {
|
|
|
5035
4141
|
case "EDIT_TEXT_REQUESTED":
|
|
5036
4142
|
this.handleEditTextRequested(payload);
|
|
5037
4143
|
break;
|
|
5038
|
-
case "UPDATE_SELECTED_ELEMENTS":
|
|
5039
|
-
this.handleUpdateSelectedElements(payload);
|
|
5040
|
-
break;
|
|
5041
|
-
// 新增的消息类型
|
|
5042
|
-
case "GET_ELEMENT_AT_POINT":
|
|
5043
|
-
this.handleGetElementAtPoint(payload);
|
|
5044
|
-
break;
|
|
5045
|
-
case "FIND_ELEMENTS_BY_LOCATION":
|
|
5046
|
-
this.handleFindElementsByLocation(payload);
|
|
5047
|
-
break;
|
|
5048
|
-
case "SET_ELEMENT_ATTRIBUTES":
|
|
5049
|
-
this.handleSetElementAttributes(payload);
|
|
5050
|
-
break;
|
|
5051
|
-
case "ENABLE_TEXT_EDITING":
|
|
5052
|
-
this.handleEnableTextEditing(payload);
|
|
5053
|
-
break;
|
|
5054
|
-
case "HOVER_ELEMENT_BY_SELECTOR":
|
|
5055
|
-
this.handleHoverElementBySelector(payload);
|
|
5056
|
-
break;
|
|
5057
|
-
case "UNHOVER_ELEMENT":
|
|
5058
|
-
this.handleUnhoverElement();
|
|
5059
|
-
break;
|
|
5060
4144
|
// 组件树相关消息
|
|
5061
4145
|
case "REQUEST_COMPONENT_TREE":
|
|
5062
4146
|
this.handleRequestComponentTree();
|
|
@@ -5084,79 +4168,7 @@ var MessageBridge = class {
|
|
|
5084
4168
|
});
|
|
5085
4169
|
}
|
|
5086
4170
|
}
|
|
5087
|
-
/** ----------------- 选择器相关消息处理 ----------------- */
|
|
5088
|
-
/**
|
|
5089
|
-
* 处理切换选择器
|
|
5090
|
-
*/
|
|
5091
|
-
handleToggleSelector(payload) {
|
|
5092
|
-
if (!this.elementSelector) return;
|
|
5093
|
-
const shouldActivate = !!payload;
|
|
5094
|
-
if (shouldActivate) {
|
|
5095
|
-
this.elementSelector.enableSelector();
|
|
5096
|
-
} else {
|
|
5097
|
-
this.elementSelector.disableSelector();
|
|
5098
|
-
}
|
|
5099
|
-
}
|
|
5100
|
-
/**
|
|
5101
|
-
* 处理获取选择器状态
|
|
5102
|
-
*/
|
|
5103
|
-
handleGetSelectorState() {
|
|
5104
|
-
if (!this.elementSelector) return;
|
|
5105
|
-
const state = this.elementSelector.getSelectorState();
|
|
5106
|
-
this.sendMessage({
|
|
5107
|
-
type: "SELECTOR_EVENT",
|
|
5108
|
-
payload: {
|
|
5109
|
-
type: "state_response",
|
|
5110
|
-
...state
|
|
5111
|
-
},
|
|
5112
|
-
timestamp: Date.now()
|
|
5113
|
-
});
|
|
5114
|
-
}
|
|
5115
|
-
/**
|
|
5116
|
-
* 处理启用元素选择器
|
|
5117
|
-
*/
|
|
5118
|
-
handleEnableElementSelector() {
|
|
5119
|
-
if (!this.elementSelector) return;
|
|
5120
|
-
this.elementSelector.enableSelector();
|
|
5121
|
-
}
|
|
5122
|
-
/**
|
|
5123
|
-
* 处理禁用元素选择器
|
|
5124
|
-
*/
|
|
5125
|
-
handleDisableElementSelector() {
|
|
5126
|
-
if (!this.elementSelector) return;
|
|
5127
|
-
this.elementSelector.disableSelector();
|
|
5128
|
-
}
|
|
5129
4171
|
/** ----------------- 元素操作消息处理 ----------------- */
|
|
5130
|
-
/**
|
|
5131
|
-
* 处理通过 ID 高亮元素
|
|
5132
|
-
*/
|
|
5133
|
-
handleHoverElementById(payload) {
|
|
5134
|
-
if (!this.elementSelector || !payload?.id) return;
|
|
5135
|
-
const selector = `#${payload.id}`;
|
|
5136
|
-
this.elementSelector.highlightElementBySelector(selector);
|
|
5137
|
-
}
|
|
5138
|
-
/**
|
|
5139
|
-
* 处理通过 ID 取消高亮元素
|
|
5140
|
-
*/
|
|
5141
|
-
handleUnhoverElementById(payload) {
|
|
5142
|
-
if (!this.elementSelector || !payload?.id) return;
|
|
5143
|
-
const selector = `#${payload.id}`;
|
|
5144
|
-
this.elementSelector.unhighlightElementBySelector(selector);
|
|
5145
|
-
}
|
|
5146
|
-
/**
|
|
5147
|
-
* 处理高亮元素请求
|
|
5148
|
-
*/
|
|
5149
|
-
handleHoverElementRequested(payload) {
|
|
5150
|
-
if (!this.elementSelector || !payload?.selector) return;
|
|
5151
|
-
this.elementSelector.highlightElementBySelector(payload.selector);
|
|
5152
|
-
}
|
|
5153
|
-
/**
|
|
5154
|
-
* 处理取消高亮元素请求
|
|
5155
|
-
*/
|
|
5156
|
-
handleUnhoverElementRequested(payload) {
|
|
5157
|
-
if (!this.elementSelector || !payload?.selector) return;
|
|
5158
|
-
this.elementSelector.unhighlightElementBySelector(payload.selector);
|
|
5159
|
-
}
|
|
5160
4172
|
/**
|
|
5161
4173
|
* 处理设置元素内容
|
|
5162
4174
|
*/
|
|
@@ -5260,22 +4272,6 @@ var MessageBridge = class {
|
|
|
5260
4272
|
element.addEventListener("blur", handleBlur);
|
|
5261
4273
|
}
|
|
5262
4274
|
}
|
|
5263
|
-
/**
|
|
5264
|
-
* 处理更新选中元素
|
|
5265
|
-
*/
|
|
5266
|
-
handleUpdateSelectedElements(payload) {
|
|
5267
|
-
if (!this.elementSelector || !Array.isArray(payload)) return;
|
|
5268
|
-
this.elementSelector.updateSelectedElements(payload);
|
|
5269
|
-
this.sendMessage({
|
|
5270
|
-
type: "ELEMENT_EVENT",
|
|
5271
|
-
payload: {
|
|
5272
|
-
type: "selected_elements_updated",
|
|
5273
|
-
selectedElements: payload,
|
|
5274
|
-
count: payload.length
|
|
5275
|
-
},
|
|
5276
|
-
timestamp: Date.now()
|
|
5277
|
-
});
|
|
5278
|
-
}
|
|
5279
4275
|
/** ----------------- 组件树相关消息处理 ----------------- */
|
|
5280
4276
|
/**
|
|
5281
4277
|
* 处理请求组件树
|
|
@@ -5399,11 +4395,9 @@ var MessageBridge = class {
|
|
|
5399
4395
|
if (dataTestId) return `[data-testid="${dataTestId}"]`;
|
|
5400
4396
|
const dataHowoneId = element.getAttribute("data-howone-id");
|
|
5401
4397
|
if (dataHowoneId) return `[data-howone-id="${dataHowoneId}"]`;
|
|
5402
|
-
|
|
5403
|
-
|
|
5404
|
-
|
|
5405
|
-
return `.${classes[0]}`;
|
|
5406
|
-
}
|
|
4398
|
+
const classes = getElementClasses(element);
|
|
4399
|
+
if (classes.length > 0) {
|
|
4400
|
+
return `.${classes[0]}`;
|
|
5407
4401
|
}
|
|
5408
4402
|
return element.tagName.toLowerCase();
|
|
5409
4403
|
}
|
|
@@ -5431,106 +4425,6 @@ var MessageBridge = class {
|
|
|
5431
4425
|
timestamp: Date.now()
|
|
5432
4426
|
});
|
|
5433
4427
|
}
|
|
5434
|
-
/** ----------------- 新增的消息处理方法 ----------------- */
|
|
5435
|
-
/**
|
|
5436
|
-
* 处理获取鼠标位置的元素
|
|
5437
|
-
*/
|
|
5438
|
-
handleGetElementAtPoint(payload) {
|
|
5439
|
-
if (!this.elementSelector) return;
|
|
5440
|
-
const element = this.elementSelector.getElementAtPoint(payload?.x, payload?.y);
|
|
5441
|
-
this.sendMessage({
|
|
5442
|
-
type: "ELEMENT_EVENT",
|
|
5443
|
-
payload: {
|
|
5444
|
-
type: "at_point_response",
|
|
5445
|
-
element: element ? this.getElementInfo(element) : null,
|
|
5446
|
-
coordinates: { x: payload?.x, y: payload?.y }
|
|
5447
|
-
},
|
|
5448
|
-
timestamp: Date.now()
|
|
5449
|
-
});
|
|
5450
|
-
}
|
|
5451
|
-
/**
|
|
5452
|
-
* 处理根据位置查找元素
|
|
5453
|
-
*/
|
|
5454
|
-
handleFindElementsByLocation(payload) {
|
|
5455
|
-
if (!this.elementSelector || !payload?.filePath || !payload?.lineNumber) return;
|
|
5456
|
-
const elements = this.elementSelector.findElementsByLocation(payload.filePath, payload.lineNumber);
|
|
5457
|
-
this.sendMessage({
|
|
5458
|
-
type: "ELEMENT_EVENT",
|
|
5459
|
-
payload: {
|
|
5460
|
-
type: "elements_by_location_response",
|
|
5461
|
-
elements: elements.map((el) => this.getElementInfo(el)),
|
|
5462
|
-
location: {
|
|
5463
|
-
filePath: payload.filePath,
|
|
5464
|
-
lineNumber: payload.lineNumber
|
|
5465
|
-
}
|
|
5466
|
-
},
|
|
5467
|
-
timestamp: Date.now()
|
|
5468
|
-
});
|
|
5469
|
-
}
|
|
5470
|
-
/**
|
|
5471
|
-
* 处理设置元素属性(新版本)
|
|
5472
|
-
*/
|
|
5473
|
-
handleSetElementAttributes(payload) {
|
|
5474
|
-
if (!this.elementSelector || !payload?.selector || !payload?.attributes) return;
|
|
5475
|
-
const success = this.elementSelector.setElementAttributes(payload.selector, payload.attributes);
|
|
5476
|
-
this.sendMessage({
|
|
5477
|
-
type: "ELEMENT_EVENT",
|
|
5478
|
-
payload: {
|
|
5479
|
-
type: "attributes_set_response",
|
|
5480
|
-
success,
|
|
5481
|
-
selector: payload.selector,
|
|
5482
|
-
attributes: payload.attributes
|
|
5483
|
-
},
|
|
5484
|
-
timestamp: Date.now()
|
|
5485
|
-
});
|
|
5486
|
-
}
|
|
5487
|
-
/**
|
|
5488
|
-
* 处理启用文本编辑
|
|
5489
|
-
*/
|
|
5490
|
-
handleEnableTextEditing(payload) {
|
|
5491
|
-
if (!this.elementSelector || !payload?.selector) return;
|
|
5492
|
-
const success = this.elementSelector.enableTextEditing(payload.selector);
|
|
5493
|
-
this.sendMessage({
|
|
5494
|
-
type: "ELEMENT_EVENT",
|
|
5495
|
-
payload: {
|
|
5496
|
-
type: "text_editing_enabled_response",
|
|
5497
|
-
success,
|
|
5498
|
-
selector: payload.selector
|
|
5499
|
-
},
|
|
5500
|
-
timestamp: Date.now()
|
|
5501
|
-
});
|
|
5502
|
-
}
|
|
5503
|
-
/**
|
|
5504
|
-
* 处理通过选择器悬停元素
|
|
5505
|
-
*/
|
|
5506
|
-
handleHoverElementBySelector(payload) {
|
|
5507
|
-
if (!this.elementSelector || !payload?.selector) return;
|
|
5508
|
-
const success = this.elementSelector.hoverElementBySelector(payload.selector);
|
|
5509
|
-
this.sendMessage({
|
|
5510
|
-
type: "ELEMENT_EVENT",
|
|
5511
|
-
payload: {
|
|
5512
|
-
type: "hovered_by_selector_response",
|
|
5513
|
-
success,
|
|
5514
|
-
selector: payload.selector
|
|
5515
|
-
},
|
|
5516
|
-
timestamp: Date.now()
|
|
5517
|
-
});
|
|
5518
|
-
}
|
|
5519
|
-
/**
|
|
5520
|
-
* 处理取消悬停元素
|
|
5521
|
-
*/
|
|
5522
|
-
handleUnhoverElement() {
|
|
5523
|
-
if (!this.elementSelector) return;
|
|
5524
|
-
this.elementSelector.unhoverElement();
|
|
5525
|
-
this.sendMessage({
|
|
5526
|
-
type: "ELEMENT_EVENT",
|
|
5527
|
-
payload: {
|
|
5528
|
-
type: "unhovered_response",
|
|
5529
|
-
success: true
|
|
5530
|
-
},
|
|
5531
|
-
timestamp: Date.now()
|
|
5532
|
-
});
|
|
5533
|
-
}
|
|
5534
4428
|
/** ----------------- 统一消息发送管理方法 ----------------- */
|
|
5535
4429
|
/**
|
|
5536
4430
|
* 获取统一的消息发送器实例
|
|
@@ -5564,7 +4458,6 @@ var MessageBridge = class {
|
|
|
5564
4458
|
window.removeEventListener("message", this.messageListener);
|
|
5565
4459
|
this.messageListener = void 0;
|
|
5566
4460
|
}
|
|
5567
|
-
console.log("[MessageBridge] \u6D88\u606F\u6865\u63A5\u5668\u5DF2\u9500\u6BC1");
|
|
5568
4461
|
}
|
|
5569
4462
|
};
|
|
5570
4463
|
|
|
@@ -5599,7 +4492,6 @@ var ErrorHandler = class {
|
|
|
5599
4492
|
const sendMessage = this.messageSender.createSendFunction();
|
|
5600
4493
|
this.errorTracking = new ErrorTracking(sendMessage);
|
|
5601
4494
|
this.interactionTracking = new InteractionTracking(sendMessage);
|
|
5602
|
-
this.elementSelector = new ElementSelector2(sendMessage);
|
|
5603
4495
|
this.messageBridge = new MessageBridge();
|
|
5604
4496
|
this.viewDetector = new ViewDetector();
|
|
5605
4497
|
this.hardRefreshManager = new HardRefreshManager(GLOBAL_CONFIG.ALLOWED_ORIGINS);
|
|
@@ -5664,7 +4556,6 @@ var ErrorHandler = class {
|
|
|
5664
4556
|
* 设置模块间的协作
|
|
5665
4557
|
*/
|
|
5666
4558
|
setupModuleIntegration() {
|
|
5667
|
-
this.messageBridge.setElementSelector(this.elementSelector);
|
|
5668
4559
|
this.messageBridge.setComponentTreeGenerator(this.componentTreeGenerator);
|
|
5669
4560
|
this.errorTracking.setViewDetector(this.viewDetector);
|
|
5670
4561
|
this.errorTracking.setInteractionTracking(this.interactionTracking);
|
|
@@ -5741,12 +4632,6 @@ var ErrorHandler = class {
|
|
|
5741
4632
|
getErrorStats() {
|
|
5742
4633
|
return this.errorTracking.getErrorStats();
|
|
5743
4634
|
}
|
|
5744
|
-
/**
|
|
5745
|
-
* 获取选择器状态
|
|
5746
|
-
*/
|
|
5747
|
-
getSelectorState() {
|
|
5748
|
-
return this.elementSelector.getSelectorState();
|
|
5749
|
-
}
|
|
5750
4635
|
/**
|
|
5751
4636
|
* 获取交互历史
|
|
5752
4637
|
*/
|
|
@@ -5780,24 +4665,6 @@ var ErrorHandler = class {
|
|
|
5780
4665
|
isViteEnvironment() {
|
|
5781
4666
|
return ViteHMRDetector.isViteEnvironment();
|
|
5782
4667
|
}
|
|
5783
|
-
/**
|
|
5784
|
-
* 启用元素选择器
|
|
5785
|
-
*/
|
|
5786
|
-
enableElementSelector() {
|
|
5787
|
-
this.elementSelector.enableSelector();
|
|
5788
|
-
}
|
|
5789
|
-
/**
|
|
5790
|
-
* 禁用元素选择器
|
|
5791
|
-
*/
|
|
5792
|
-
disableElementSelector() {
|
|
5793
|
-
this.elementSelector.disableSelector();
|
|
5794
|
-
}
|
|
5795
|
-
/**
|
|
5796
|
-
* 切换元素选择器状态
|
|
5797
|
-
*/
|
|
5798
|
-
toggleElementSelector() {
|
|
5799
|
-
this.elementSelector.toggleSelector();
|
|
5800
|
-
}
|
|
5801
4668
|
/**
|
|
5802
4669
|
* 更新配置
|
|
5803
4670
|
*/
|
|
@@ -5811,7 +4678,6 @@ var ErrorHandler = class {
|
|
|
5811
4678
|
try {
|
|
5812
4679
|
this.errorTracking.destroy();
|
|
5813
4680
|
this.interactionTracking.destroy();
|
|
5814
|
-
this.elementSelector.destroy();
|
|
5815
4681
|
this.messageBridge.destroy();
|
|
5816
4682
|
if (this.viteHMRDetector) {
|
|
5817
4683
|
this.viteHMRDetector.destroy();
|
|
@@ -5842,7 +4708,6 @@ var ErrorHandler = class {
|
|
|
5842
4708
|
errorStats: this.getErrorStats(),
|
|
5843
4709
|
currentView: this.getCurrentView(),
|
|
5844
4710
|
interactionHistory: this.getInteractionHistory(),
|
|
5845
|
-
selectorState: this.getSelectorState(),
|
|
5846
4711
|
isViteEnvironment: this.isViteEnvironment(),
|
|
5847
4712
|
timestamp: Date.now()
|
|
5848
4713
|
};
|