@howone/sdk 0.2.2 → 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 +274 -1397
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +274 -1397
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -768,17 +768,13 @@ var LoginForm = ({
|
|
|
768
768
|
const [codeSent, setCodeSent] = (0, import_react2.useState)(false);
|
|
769
769
|
const [loginError, setLoginError] = (0, import_react2.useState)(null);
|
|
770
770
|
const googleLogin = async () => {
|
|
771
|
-
console.log("Google login clicked");
|
|
772
771
|
};
|
|
773
772
|
const githubLogin = async () => {
|
|
774
|
-
console.log("GitHub login clicked");
|
|
775
773
|
};
|
|
776
774
|
const sendEmailCode = async (email2) => {
|
|
777
|
-
console.log("Send code to:", email2, "for app:", appName);
|
|
778
775
|
setCodeSent(true);
|
|
779
776
|
};
|
|
780
777
|
const loginWithEmail = async (email2, code2) => {
|
|
781
|
-
console.log("Login with email:", email2, "code:", code2);
|
|
782
778
|
if (onLoginSuccess) onLoginSuccess();
|
|
783
779
|
};
|
|
784
780
|
const clearError = () => {
|
|
@@ -1225,11 +1221,9 @@ var ElementSelectorProvider = ({ children }) => {
|
|
|
1225
1221
|
type: "ELEMENT_SELECTION_CANCELLED"
|
|
1226
1222
|
}, "*");
|
|
1227
1223
|
}
|
|
1228
|
-
console.log("\u{1F6AB} \u5143\u7D20\u9009\u62E9\u5DF2\u53D6\u6D88 (ESC)");
|
|
1229
1224
|
}, []);
|
|
1230
1225
|
const handleSelect = (0, import_react7.useCallback)((data) => {
|
|
1231
1226
|
sendElementSelectionToParent(data);
|
|
1232
|
-
console.log("\u{1F3AF} \u5143\u7D20\u5DF2\u9009\u4E2D:", data.element.tagName, data.sourceLocation?.file);
|
|
1233
1227
|
}, []);
|
|
1234
1228
|
(0, import_react7.useEffect)(() => {
|
|
1235
1229
|
const handleStartSelection = () => {
|
|
@@ -1584,7 +1578,6 @@ var ViteHMRDetector = class {
|
|
|
1584
1578
|
if (this.isInitialized) return;
|
|
1585
1579
|
this.setupViteErrorDetection();
|
|
1586
1580
|
this.isInitialized = true;
|
|
1587
|
-
console.log("[ViteHMRDetector] Vite HMR \u9519\u8BEF\u68C0\u6D4B\u5668\u521D\u59CB\u5316\u5B8C\u6210");
|
|
1588
1581
|
}
|
|
1589
1582
|
/**
|
|
1590
1583
|
* 销毁检测器
|
|
@@ -1635,10 +1628,8 @@ var ViteHMRDetector = class {
|
|
|
1635
1628
|
setTimeout(() => this.checkForCompileErrors(), 500);
|
|
1636
1629
|
});
|
|
1637
1630
|
hot.on("vite:beforeUpdate", () => {
|
|
1638
|
-
console.log("[ViteHMRDetector] HMR \u66F4\u65B0\u5F00\u59CB");
|
|
1639
1631
|
});
|
|
1640
1632
|
hot.on("vite:afterUpdate", () => {
|
|
1641
|
-
console.log("[ViteHMRDetector] HMR \u66F4\u65B0\u5B8C\u6210");
|
|
1642
1633
|
});
|
|
1643
1634
|
}
|
|
1644
1635
|
window.addEventListener("error", (event) => {
|
|
@@ -1676,7 +1667,6 @@ var ViteHMRDetector = class {
|
|
|
1676
1667
|
payload: errorPayload,
|
|
1677
1668
|
timestamp: Date.now()
|
|
1678
1669
|
});
|
|
1679
|
-
console.log("[ViteHMRDetector] Vite \u9519\u8BEF\u5DF2\u68C0\u6D4B\u5E76\u62A5\u544A:", errorPayload);
|
|
1680
1670
|
} catch (err) {
|
|
1681
1671
|
this.handleFallbackError(errorOverlay, err);
|
|
1682
1672
|
}
|
|
@@ -1949,20 +1939,16 @@ var HardRefreshManager = class {
|
|
|
1949
1939
|
clearedStorage: []
|
|
1950
1940
|
};
|
|
1951
1941
|
try {
|
|
1952
|
-
console.log("[HardRefreshManager] \u5F00\u59CB\u6267\u884C\u786C\u5237\u65B0...");
|
|
1953
1942
|
if (defaultOptions.clearCaches) {
|
|
1954
1943
|
const clearedCaches = await this.clearAllCaches();
|
|
1955
1944
|
result.clearedCaches = clearedCaches;
|
|
1956
|
-
console.log(`[HardRefreshManager] \u5DF2\u6E05\u9664 ${clearedCaches.length} \u4E2A\u7F13\u5B58`);
|
|
1957
1945
|
}
|
|
1958
1946
|
if (defaultOptions.unregisterServiceWorkers) {
|
|
1959
1947
|
const unregisteredCount = await this.unregisterServiceWorkers();
|
|
1960
1948
|
result.unregisteredWorkers = unregisteredCount;
|
|
1961
|
-
console.log(`[HardRefreshManager] \u5DF2\u6CE8\u9500 ${unregisteredCount} \u4E2A Service Worker`);
|
|
1962
1949
|
}
|
|
1963
1950
|
const clearedStorage = await this.clearStorage(defaultOptions);
|
|
1964
1951
|
result.clearedStorage = clearedStorage;
|
|
1965
|
-
console.log(`[HardRefreshManager] \u5DF2\u6E05\u9664\u5B58\u50A8: ${clearedStorage.join(", ")}`);
|
|
1966
1952
|
await this.forceReload(defaultOptions);
|
|
1967
1953
|
result.success = true;
|
|
1968
1954
|
return result;
|
|
@@ -2561,7 +2547,6 @@ var ComponentTreeGenerator = class {
|
|
|
2561
2547
|
maxTextLength: 100,
|
|
2562
2548
|
maxChildren: 50
|
|
2563
2549
|
};
|
|
2564
|
-
console.log("[ComponentTreeGenerator] \u7EC4\u4EF6\u6811\u751F\u6210\u5668\u521D\u59CB\u5316\u5B8C\u6210");
|
|
2565
2550
|
}
|
|
2566
2551
|
/** ----------------- 主要生成方法 ----------------- */
|
|
2567
2552
|
/**
|
|
@@ -2570,7 +2555,6 @@ var ComponentTreeGenerator = class {
|
|
|
2570
2555
|
generateComponentTree(rootElement) {
|
|
2571
2556
|
const startTime = Date.now();
|
|
2572
2557
|
const root = rootElement || document.body;
|
|
2573
|
-
console.log("[ComponentTreeGenerator] \u5F00\u59CB\u751F\u6210\u7EC4\u4EF6\u6811...");
|
|
2574
2558
|
const rootNode = this.generateNodeTree(root, 0);
|
|
2575
2559
|
const stats = this.calculateTreeStats(rootNode);
|
|
2576
2560
|
const componentTree = {
|
|
@@ -2591,7 +2575,6 @@ var ComponentTreeGenerator = class {
|
|
|
2591
2575
|
}
|
|
2592
2576
|
};
|
|
2593
2577
|
const generationTime = Date.now() - startTime;
|
|
2594
|
-
console.log(`[ComponentTreeGenerator] \u7EC4\u4EF6\u6811\u751F\u6210\u5B8C\u6210\uFF0C\u8017\u65F6 ${generationTime}ms\uFF0C\u8282\u70B9\u6570: ${stats.totalNodes}`);
|
|
2595
2578
|
return componentTree;
|
|
2596
2579
|
}
|
|
2597
2580
|
/**
|
|
@@ -2942,7 +2925,6 @@ var ComponentTreeGenerator = class {
|
|
|
2942
2925
|
*/
|
|
2943
2926
|
updateConfig(newConfig) {
|
|
2944
2927
|
this.config = { ...this.config, ...newConfig };
|
|
2945
|
-
console.log("[ComponentTreeGenerator] \u914D\u7F6E\u5DF2\u66F4\u65B0:", this.config);
|
|
2946
2928
|
}
|
|
2947
2929
|
/**
|
|
2948
2930
|
* 获取当前配置
|
|
@@ -2965,7 +2947,6 @@ var ComponentTreeGenerator = class {
|
|
|
2965
2947
|
* 销毁生成器
|
|
2966
2948
|
*/
|
|
2967
2949
|
destroy() {
|
|
2968
|
-
console.log("[ComponentTreeGenerator] \u7EC4\u4EF6\u6811\u751F\u6210\u5668\u5DF2\u9500\u6BC1");
|
|
2969
2950
|
}
|
|
2970
2951
|
};
|
|
2971
2952
|
|
|
@@ -3142,7 +3123,6 @@ var ErrorTracking = class {
|
|
|
3142
3123
|
this.viewDetector = null;
|
|
3143
3124
|
this.interactionTracking = null;
|
|
3144
3125
|
this.sendMessage = sendMessage;
|
|
3145
|
-
this.internalLog("log", "[ErrorTracking] \u9519\u8BEF\u8FFD\u8E2A\u6A21\u5757\u521D\u59CB\u5316\u5B8C\u6210");
|
|
3146
3126
|
}
|
|
3147
3127
|
/**
|
|
3148
3128
|
* 内部日志方法,避免被控制台拦截器捕获
|
|
@@ -3178,10 +3158,8 @@ var ErrorTracking = class {
|
|
|
3178
3158
|
this.setupConsoleInterception();
|
|
3179
3159
|
this.setupNetworkMonitoring();
|
|
3180
3160
|
this.initialized = true;
|
|
3181
|
-
this.internalLog("log", "[ErrorTracking] \u9519\u8BEF\u8FFD\u8E2A\u529F\u80FD\u5DF2\u542F\u7528");
|
|
3182
3161
|
setTimeout(() => {
|
|
3183
3162
|
this.fullyInitialized = true;
|
|
3184
|
-
this.internalLog("log", "[ErrorTracking] \u521D\u59CB\u5316\u5B8C\u6210\uFF0C\u63A7\u5236\u53F0\u62E6\u622A\u5DF2\u9ED8\u8BA4\u542F\u7528");
|
|
3185
3163
|
}, 1e3);
|
|
3186
3164
|
}
|
|
3187
3165
|
/**
|
|
@@ -3206,7 +3184,6 @@ var ErrorTracking = class {
|
|
|
3206
3184
|
source: "unhandledrejection"
|
|
3207
3185
|
});
|
|
3208
3186
|
});
|
|
3209
|
-
this.internalLog("log", "[ErrorTracking] \u5168\u5C40\u9519\u8BEF\u76D1\u542C\u5668\u5DF2\u8BBE\u7F6E");
|
|
3210
3187
|
}
|
|
3211
3188
|
/**
|
|
3212
3189
|
* 设置控制台拦截
|
|
@@ -3230,7 +3207,6 @@ var ErrorTracking = class {
|
|
|
3230
3207
|
}
|
|
3231
3208
|
};
|
|
3232
3209
|
});
|
|
3233
|
-
this.internalLog("log", "[ErrorTracking] \u63A7\u5236\u53F0\u62E6\u622A\u5DF2\u8BBE\u7F6E");
|
|
3234
3210
|
}
|
|
3235
3211
|
/**
|
|
3236
3212
|
* 安全地将控制台输出转发到父窗口
|
|
@@ -3250,6 +3226,20 @@ var ErrorTracking = class {
|
|
|
3250
3226
|
const fileInfo = this.extractFileInfoFromStack(fullStack);
|
|
3251
3227
|
const serializedArgs = args.map((arg) => DeepSerializer.quickSerialize(arg));
|
|
3252
3228
|
const message = serializedArgs.map((arg) => typeof arg === "string" ? arg : JSON.stringify(arg, null, 2)).join(" ") + (stack ? "\n" + stack : "");
|
|
3229
|
+
const lowerMessage = message.toLowerCase();
|
|
3230
|
+
const isFromVite = (fileInfo.filename || "").toLowerCase().includes("vite") || lowerMessage.includes("@vite") || lowerMessage.includes("vite") || lowerMessage.includes("hmr");
|
|
3231
|
+
const ignoreVitePatterns = [
|
|
3232
|
+
/\[vite\]\s*hot updated/i,
|
|
3233
|
+
/\[vite\]\s*connected/i,
|
|
3234
|
+
/\[vite\]\s*connecting/i,
|
|
3235
|
+
/\bhot updated\b/i,
|
|
3236
|
+
/\bhmr\b.*\bupdated\b/i
|
|
3237
|
+
];
|
|
3238
|
+
if (isFromVite && ignoreVitePatterns.some((re) => re.test(lowerMessage))) {
|
|
3239
|
+
return;
|
|
3240
|
+
}
|
|
3241
|
+
const hasErrorKeywords = /\b(error|failed|overlay|compile|exception)\b/.test(lowerMessage);
|
|
3242
|
+
const isViteHMRNonError = isFromVite && !hasErrorKeywords;
|
|
3253
3243
|
if (method === "error") {
|
|
3254
3244
|
const globalError = {
|
|
3255
3245
|
id: `console-error-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
@@ -3266,9 +3256,11 @@ var ErrorTracking = class {
|
|
|
3266
3256
|
pagePath: window.location.pathname + window.location.search + window.location.hash,
|
|
3267
3257
|
interactionTrail: [...window.__AUTO_ENGINEER_INTERACTION_TRAIL__ || []]
|
|
3268
3258
|
};
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3259
|
+
if (!isViteHMRNonError) {
|
|
3260
|
+
window.__AUTO_ENGINEER_ERRORS__ = window.__AUTO_ENGINEER_ERRORS__ || [];
|
|
3261
|
+
window.__AUTO_ENGINEER_ERRORS__.push(globalError);
|
|
3262
|
+
this.manageArrayLength(window.__AUTO_ENGINEER_ERRORS__, ERROR_CONFIG.MAX_ERRORS);
|
|
3263
|
+
}
|
|
3272
3264
|
}
|
|
3273
3265
|
const consoleLevelMap = {
|
|
3274
3266
|
log: "info",
|
|
@@ -3280,7 +3272,7 @@ var ErrorTracking = class {
|
|
|
3280
3272
|
this.sendMessage({
|
|
3281
3273
|
type: "CONSOLE_EVENT",
|
|
3282
3274
|
payload: {
|
|
3283
|
-
type: consoleLevelMap[method] === "info" ? "info" : consoleLevelMap[method] === "warning" ? "warning" : "error",
|
|
3275
|
+
type: consoleLevelMap[method] === "info" ? "info" : consoleLevelMap[method] === "warning" ? "warning" : consoleLevelMap[method] === "debug" ? "debug" : "error",
|
|
3284
3276
|
message,
|
|
3285
3277
|
logged_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3286
3278
|
filename: fileInfo.filename,
|
|
@@ -3301,19 +3293,47 @@ var ErrorTracking = class {
|
|
|
3301
3293
|
* 设置网络监控
|
|
3302
3294
|
*/
|
|
3303
3295
|
setupNetworkMonitoring() {
|
|
3296
|
+
const self = this;
|
|
3304
3297
|
const originalFetch = window.fetch;
|
|
3305
3298
|
window.fetch = async (...args) => {
|
|
3306
3299
|
const startTime = Date.now();
|
|
3307
3300
|
try {
|
|
3308
3301
|
const response = await originalFetch(...args);
|
|
3309
|
-
|
|
3302
|
+
self.logNetworkRequest(args, response, Date.now() - startTime);
|
|
3310
3303
|
return response;
|
|
3311
3304
|
} catch (error) {
|
|
3312
|
-
|
|
3305
|
+
const duration = Date.now() - startTime;
|
|
3306
|
+
const message = error && (error.message || String(error));
|
|
3307
|
+
const match = typeof message === "string" ? message.match(/^HTTP\s+(\d+):\s*(.*)$/i) : null;
|
|
3308
|
+
if (match) {
|
|
3309
|
+
const status = Number(match[1]);
|
|
3310
|
+
const statusText = match[2] || "";
|
|
3311
|
+
const stack = new Error().stack;
|
|
3312
|
+
const fileInfo = self.extractFileInfoFromStack(stack);
|
|
3313
|
+
self.sendMessage({
|
|
3314
|
+
type: "NETWORK_EVENT",
|
|
3315
|
+
payload: {
|
|
3316
|
+
type: "request_error",
|
|
3317
|
+
url: args[0],
|
|
3318
|
+
method: args[1]?.method || "GET",
|
|
3319
|
+
status,
|
|
3320
|
+
statusText,
|
|
3321
|
+
filename: fileInfo.filename,
|
|
3322
|
+
lineno: fileInfo.lineno,
|
|
3323
|
+
colno: fileInfo.colno,
|
|
3324
|
+
duration,
|
|
3325
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3326
|
+
pageUrl: window.location.href,
|
|
3327
|
+
interactionTrail: self.getRecentInteractions()
|
|
3328
|
+
},
|
|
3329
|
+
timestamp: Date.now()
|
|
3330
|
+
});
|
|
3331
|
+
} else {
|
|
3332
|
+
self.logNetworkError(args, error, duration);
|
|
3333
|
+
}
|
|
3313
3334
|
throw error;
|
|
3314
3335
|
}
|
|
3315
3336
|
};
|
|
3316
|
-
this.internalLog("log", "[ErrorTracking] \u7F51\u7EDC\u76D1\u63A7\u5DF2\u8BBE\u7F6E");
|
|
3317
3337
|
}
|
|
3318
3338
|
/**
|
|
3319
3339
|
* 记录网络请求
|
|
@@ -3605,14 +3625,12 @@ var ErrorTracking = class {
|
|
|
3605
3625
|
*/
|
|
3606
3626
|
enableConsoleInterception() {
|
|
3607
3627
|
this.fullyInitialized = true;
|
|
3608
|
-
this.internalLog("log", "[ErrorTracking] \u624B\u52A8\u542F\u7528\u63A7\u5236\u53F0\u62E6\u622A");
|
|
3609
3628
|
}
|
|
3610
3629
|
/**
|
|
3611
3630
|
* 手动禁用控制台拦截
|
|
3612
3631
|
*/
|
|
3613
3632
|
disableConsoleInterception() {
|
|
3614
3633
|
this.fullyInitialized = false;
|
|
3615
|
-
this.internalLog("log", "[ErrorTracking] \u624B\u52A8\u7981\u7528\u63A7\u5236\u53F0\u62E6\u622A");
|
|
3616
3634
|
}
|
|
3617
3635
|
/**
|
|
3618
3636
|
* 销毁错误追踪
|
|
@@ -3624,10 +3642,32 @@ var ErrorTracking = class {
|
|
|
3624
3642
|
}
|
|
3625
3643
|
});
|
|
3626
3644
|
this.initialized = false;
|
|
3627
|
-
this.internalLog("log", "[ErrorTracking] \u9519\u8BEF\u8FFD\u8E2A\u6A21\u5757\u5DF2\u9500\u6BC1");
|
|
3628
3645
|
}
|
|
3629
3646
|
};
|
|
3630
3647
|
|
|
3648
|
+
// src/utils/unified-error-handler/utils/SelectorUtils.ts
|
|
3649
|
+
function getElementClasses(element) {
|
|
3650
|
+
const classAttr = element.getAttribute("class");
|
|
3651
|
+
if (classAttr && classAttr.trim().length > 0) {
|
|
3652
|
+
return dedupeAndClean(classAttr.split(/\s+/));
|
|
3653
|
+
}
|
|
3654
|
+
const anyEl = element;
|
|
3655
|
+
if (typeof anyEl.className === "string") {
|
|
3656
|
+
return dedupeAndClean(anyEl.className.split(/\s+/));
|
|
3657
|
+
}
|
|
3658
|
+
if (anyEl.className && typeof anyEl.className.baseVal === "string") {
|
|
3659
|
+
return dedupeAndClean(anyEl.className.baseVal.split(/\s+/));
|
|
3660
|
+
}
|
|
3661
|
+
if (anyEl.classList && anyEl.classList.length > 0) {
|
|
3662
|
+
return dedupeAndClean(Array.from(anyEl.classList));
|
|
3663
|
+
}
|
|
3664
|
+
return [];
|
|
3665
|
+
}
|
|
3666
|
+
function dedupeAndClean(arr) {
|
|
3667
|
+
const cleaned = arr.map((s) => s.trim()).filter(Boolean);
|
|
3668
|
+
return Array.from(new Set(cleaned));
|
|
3669
|
+
}
|
|
3670
|
+
|
|
3631
3671
|
// src/utils/unified-error-handler/features/InteractionTracking.ts
|
|
3632
3672
|
var InteractionTracking = class {
|
|
3633
3673
|
constructor(sendMessage) {
|
|
@@ -3651,7 +3691,6 @@ var InteractionTracking = class {
|
|
|
3651
3691
|
this.debounceTimers = /* @__PURE__ */ new Map();
|
|
3652
3692
|
this.eventListeners = [];
|
|
3653
3693
|
this.sendMessage = sendMessage;
|
|
3654
|
-
console.log("[InteractionTracking] \u4EA4\u4E92\u8FFD\u8E2A\u6A21\u5757\u521D\u59CB\u5316\u5B8C\u6210");
|
|
3655
3694
|
}
|
|
3656
3695
|
/** ----------------- 主要控制方法 ----------------- */
|
|
3657
3696
|
/**
|
|
@@ -3667,7 +3706,6 @@ var InteractionTracking = class {
|
|
|
3667
3706
|
title: document.title,
|
|
3668
3707
|
timestamp: Date.now()
|
|
3669
3708
|
});
|
|
3670
|
-
console.log("[InteractionTracking] \u4EA4\u4E92\u8FFD\u8E2A\u5DF2\u5F00\u59CB");
|
|
3671
3709
|
}
|
|
3672
3710
|
/**
|
|
3673
3711
|
* 停止追踪
|
|
@@ -3676,7 +3714,6 @@ var InteractionTracking = class {
|
|
|
3676
3714
|
if (!this.isTracking) return;
|
|
3677
3715
|
this.removeEventListeners();
|
|
3678
3716
|
this.isTracking = false;
|
|
3679
|
-
console.log("[InteractionTracking] \u4EA4\u4E92\u8FFD\u8E2A\u5DF2\u505C\u6B62");
|
|
3680
3717
|
}
|
|
3681
3718
|
/** ----------------- 事件监听器设置 ----------------- */
|
|
3682
3719
|
/**
|
|
@@ -3989,11 +4026,9 @@ var InteractionTracking = class {
|
|
|
3989
4026
|
*/
|
|
3990
4027
|
getElementSelector(element) {
|
|
3991
4028
|
if (element.id) return `#${element.id}`;
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
return `.${classes[0]}`;
|
|
3996
|
-
}
|
|
4029
|
+
const classes = getElementClasses(element);
|
|
4030
|
+
if (classes.length > 0) {
|
|
4031
|
+
return `.${classes[0]}`;
|
|
3997
4032
|
}
|
|
3998
4033
|
const dataTestId = element.getAttribute("data-testid");
|
|
3999
4034
|
if (dataTestId) return `[data-testid="${dataTestId}"]`;
|
|
@@ -4106,1244 +4141,240 @@ var InteractionTracking = class {
|
|
|
4106
4141
|
destroy() {
|
|
4107
4142
|
this.stopTracking();
|
|
4108
4143
|
this.interactions = [];
|
|
4109
|
-
console.log("[InteractionTracking] \u4EA4\u4E92\u8FFD\u8E2A\u6A21\u5757\u5DF2\u9500\u6BC1");
|
|
4110
4144
|
}
|
|
4111
4145
|
};
|
|
4112
4146
|
|
|
4113
|
-
// src/utils/unified-error-handler/features/
|
|
4114
|
-
var
|
|
4147
|
+
// src/utils/unified-error-handler/features/MessageBridge.ts
|
|
4148
|
+
var getOriginalConsole2 = () => window.__originalConsole || {
|
|
4149
|
+
log: console.log.bind(console),
|
|
4150
|
+
warn: console.warn.bind(console),
|
|
4151
|
+
error: console.error.bind(console),
|
|
4152
|
+
info: console.info.bind(console),
|
|
4153
|
+
debug: console.debug.bind(console)
|
|
4154
|
+
};
|
|
4155
|
+
var MessageBridge = class {
|
|
4115
4156
|
constructor(sendMessage) {
|
|
4116
|
-
this.
|
|
4117
|
-
this.
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
this.
|
|
4122
|
-
this.
|
|
4123
|
-
this.eventListeners = [];
|
|
4124
|
-
this.lastClickTimestamp = 0;
|
|
4125
|
-
this.lastClickTarget = null;
|
|
4126
|
-
this.mousePosition = { x: 0, y: 0 };
|
|
4127
|
-
this.sendMessage = sendMessage;
|
|
4128
|
-
this.initializeSelector();
|
|
4157
|
+
this.componentTreeGenerator = null;
|
|
4158
|
+
this.messageSender = createDefaultMessageSender({
|
|
4159
|
+
addTimestamp: true,
|
|
4160
|
+
enableDebugLog: false
|
|
4161
|
+
});
|
|
4162
|
+
this.sendMessage = sendMessage || this.messageSender.createSendFunction();
|
|
4163
|
+
this.setupMessageListener();
|
|
4129
4164
|
}
|
|
4130
|
-
/** -----------------
|
|
4165
|
+
/** ----------------- 依赖注入方法 ----------------- */
|
|
4131
4166
|
/**
|
|
4132
|
-
*
|
|
4167
|
+
* 设置组件树生成器
|
|
4133
4168
|
*/
|
|
4134
|
-
|
|
4135
|
-
this.
|
|
4136
|
-
this.createTooltip();
|
|
4137
|
-
this.createStyles();
|
|
4138
|
-
console.log("[ElementSelector] \u5143\u7D20\u9009\u62E9\u5668\u521D\u59CB\u5316\u5B8C\u6210");
|
|
4169
|
+
setComponentTreeGenerator(componentTreeGenerator) {
|
|
4170
|
+
this.componentTreeGenerator = componentTreeGenerator;
|
|
4139
4171
|
}
|
|
4172
|
+
/** ----------------- 消息监听设置 ----------------- */
|
|
4140
4173
|
/**
|
|
4141
|
-
*
|
|
4174
|
+
* 设置消息监听器
|
|
4142
4175
|
*/
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
this.rootElement = document.querySelector("#root") || document.body;
|
|
4148
|
-
if (this.rootElement) {
|
|
4149
|
-
break;
|
|
4176
|
+
setupMessageListener() {
|
|
4177
|
+
this.messageListener = (event) => {
|
|
4178
|
+
if (!this.isOriginAllowed(event.origin)) {
|
|
4179
|
+
return;
|
|
4150
4180
|
}
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
}
|
|
4157
|
-
}
|
|
4158
|
-
/**
|
|
4159
|
-
* 创建工具提示
|
|
4160
|
-
*/
|
|
4161
|
-
createTooltip() {
|
|
4162
|
-
this.tooltip = document.createElement("div");
|
|
4163
|
-
this.tooltip.className = "element-selector-tooltip";
|
|
4164
|
-
this.tooltip.setAttribute("role", "tooltip");
|
|
4165
|
-
this.tooltip.style.display = "none";
|
|
4166
|
-
document.body.appendChild(this.tooltip);
|
|
4181
|
+
if (event.data && typeof event.data === "object" && event.data.type) {
|
|
4182
|
+
this.handleMessage(event.data);
|
|
4183
|
+
}
|
|
4184
|
+
};
|
|
4185
|
+
window.addEventListener("message", this.messageListener);
|
|
4167
4186
|
}
|
|
4168
4187
|
/**
|
|
4169
|
-
*
|
|
4188
|
+
* 检查来源是否被允许
|
|
4170
4189
|
*/
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
document.head.appendChild(this.styleElement);
|
|
4190
|
+
isOriginAllowed(origin) {
|
|
4191
|
+
return GLOBAL_CONFIG.ALLOWED_ORIGINS.some(
|
|
4192
|
+
(allowedOrigin) => origin.includes(allowedOrigin.replace("https://", "").replace("http://", ""))
|
|
4193
|
+
);
|
|
4176
4194
|
}
|
|
4195
|
+
/** ----------------- 主要消息处理方法 ----------------- */
|
|
4177
4196
|
/**
|
|
4178
|
-
*
|
|
4197
|
+
* 处理消息
|
|
4179
4198
|
*/
|
|
4180
|
-
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
outline: ${this.config.SELECTED_BORDER_WIDTH} ${this.config.HIGHLIGHT_BORDER_STYLE} ${this.config.SELECTED_COLOR} !important;
|
|
4210
|
-
outline-offset: 3px !important;
|
|
4211
|
-
background-color: ${this.config.SELECTED_COLOR}15 !important;
|
|
4212
|
-
z-index: 9999;
|
|
4213
|
-
}
|
|
4214
|
-
|
|
4215
|
-
[data-element-selected][contenteditable] {
|
|
4216
|
-
outline: none !important;
|
|
4217
|
-
}
|
|
4218
|
-
|
|
4219
|
-
[data-element-hovered][data-full-width],
|
|
4220
|
-
[data-element-selected][data-full-width] {
|
|
4221
|
-
outline-offset: -5px !important;
|
|
4222
|
-
}
|
|
4223
|
-
|
|
4224
|
-
.element-selector-active {
|
|
4225
|
-
cursor: ${this.config.cursor} !important;
|
|
4226
|
-
}
|
|
4227
|
-
|
|
4228
|
-
.element-selector-active * {
|
|
4229
|
-
cursor: ${this.config.cursor} !important;
|
|
4230
|
-
}
|
|
4231
|
-
|
|
4232
|
-
/* \u963B\u6B62\u539F\u751F hover \u6548\u679C\u7684\u5168\u5C40\u6837\u5F0F */
|
|
4233
|
-
body.element-selector-active * {
|
|
4234
|
-
/* \u963B\u6B62\u539F\u751F CSS hover \u4F2A\u7C7B\u6548\u679C */
|
|
4235
|
-
transition: none !important;
|
|
4236
|
-
}
|
|
4237
|
-
|
|
4238
|
-
/* \u963B\u6B62\u6240\u6709 hover \u76F8\u5173\u7684 CSS \u4F2A\u7C7B\uFF0C\u4F46\u6392\u9664\u6211\u4EEC\u7684\u9009\u62E9\u5668\u5143\u7D20 */
|
|
4239
|
-
body.element-selector-active *:hover:not([data-element-selected]):not([data-element-hovered]) {
|
|
4240
|
-
background-color: inherit !important;
|
|
4241
|
-
color: inherit !important;
|
|
4242
|
-
border-color: inherit !important;
|
|
4243
|
-
box-shadow: inherit !important;
|
|
4244
|
-
transform: inherit !important;
|
|
4245
|
-
opacity: inherit !important;
|
|
4246
|
-
filter: inherit !important;
|
|
4247
|
-
}
|
|
4248
|
-
|
|
4249
|
-
/* \u786E\u4FDD\u6211\u4EEC\u7684\u9009\u62E9\u5668\u6837\u5F0F\u4F18\u5148\u7EA7\u6700\u9AD8 */
|
|
4250
|
-
body.element-selector-active [data-element-selected] {
|
|
4251
|
-
background-color: ${this.config.SELECTED_COLOR}15 !important;
|
|
4252
|
-
outline: ${this.config.SELECTED_BORDER_WIDTH} ${this.config.HIGHLIGHT_BORDER_STYLE} ${this.config.SELECTED_COLOR} !important;
|
|
4253
|
-
}
|
|
4254
|
-
|
|
4255
|
-
body.element-selector-active [data-element-hovered] {
|
|
4256
|
-
background-color: ${this.config.HIGHLIGHT_COLOR}20 !important;
|
|
4257
|
-
outline: ${this.config.HIGHLIGHT_BORDER_WIDTH} ${this.config.HIGHLIGHT_BORDER_STYLE} ${this.config.HIGHLIGHT_COLOR} !important;
|
|
4258
|
-
}
|
|
4259
|
-
|
|
4260
|
-
/* \u786E\u4FDD\u5DE5\u5177\u63D0\u793A\u4E0D\u53D7\u5F71\u54CD */
|
|
4261
|
-
body.element-selector-active .element-selector-tooltip {
|
|
4262
|
-
pointer-events: none !important;
|
|
4199
|
+
handleMessage(message) {
|
|
4200
|
+
try {
|
|
4201
|
+
const { type, payload } = message;
|
|
4202
|
+
switch (type) {
|
|
4203
|
+
case "SET_ELEMENT_CONTENT":
|
|
4204
|
+
this.handleSetElementContent(payload);
|
|
4205
|
+
break;
|
|
4206
|
+
case "SET_ELEMENT_ATTRS":
|
|
4207
|
+
this.handleSetElementAttrs(payload);
|
|
4208
|
+
break;
|
|
4209
|
+
case "DUPLICATE_ELEMENT_REQUESTED":
|
|
4210
|
+
this.handleDuplicateElementRequested(payload);
|
|
4211
|
+
break;
|
|
4212
|
+
case "EDIT_TEXT_REQUESTED":
|
|
4213
|
+
this.handleEditTextRequested(payload);
|
|
4214
|
+
break;
|
|
4215
|
+
// 组件树相关消息
|
|
4216
|
+
case "REQUEST_COMPONENT_TREE":
|
|
4217
|
+
this.handleRequestComponentTree();
|
|
4218
|
+
break;
|
|
4219
|
+
case "GET_PARENT_ELEMENT":
|
|
4220
|
+
this.handleGetParentElement(payload);
|
|
4221
|
+
break;
|
|
4222
|
+
// 样式相关消息
|
|
4223
|
+
case "SET_STYLESHEET":
|
|
4224
|
+
this.handleSetStylesheet(payload);
|
|
4225
|
+
break;
|
|
4226
|
+
default:
|
|
4227
|
+
break;
|
|
4263
4228
|
}
|
|
4264
|
-
|
|
4229
|
+
} catch (error) {
|
|
4230
|
+
console.error("[MessageBridge] \u5904\u7406\u6D88\u606F\u5931\u8D25:", error);
|
|
4231
|
+
this.sendMessage({
|
|
4232
|
+
type: "ERROR_EVENT",
|
|
4233
|
+
payload: {
|
|
4234
|
+
type: "message_handling",
|
|
4235
|
+
originalMessage: message,
|
|
4236
|
+
error: error instanceof Error ? error.message : String(error)
|
|
4237
|
+
},
|
|
4238
|
+
timestamp: Date.now()
|
|
4239
|
+
});
|
|
4240
|
+
}
|
|
4265
4241
|
}
|
|
4266
|
-
/** -----------------
|
|
4242
|
+
/** ----------------- 元素操作消息处理 ----------------- */
|
|
4267
4243
|
/**
|
|
4268
|
-
*
|
|
4244
|
+
* 处理设置元素内容
|
|
4269
4245
|
*/
|
|
4270
|
-
|
|
4271
|
-
if (
|
|
4272
|
-
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
|
|
4276
|
-
|
|
4246
|
+
handleSetElementContent(payload) {
|
|
4247
|
+
if (!payload?.selector || !payload?.content) return;
|
|
4248
|
+
const elements = document.querySelectorAll(payload.selector);
|
|
4249
|
+
elements.forEach((element) => {
|
|
4250
|
+
if (element instanceof HTMLElement) {
|
|
4251
|
+
element.innerHTML = payload.content;
|
|
4252
|
+
}
|
|
4253
|
+
});
|
|
4277
4254
|
this.sendMessage({
|
|
4278
|
-
type: "
|
|
4279
|
-
payload: {
|
|
4255
|
+
type: "ELEMENT_EVENT",
|
|
4256
|
+
payload: {
|
|
4257
|
+
type: "content_updated",
|
|
4258
|
+
selector: payload.selector,
|
|
4259
|
+
content: payload.content,
|
|
4260
|
+
elementsUpdated: elements.length
|
|
4261
|
+
},
|
|
4262
|
+
timestamp: Date.now()
|
|
4280
4263
|
});
|
|
4281
4264
|
}
|
|
4282
4265
|
/**
|
|
4283
|
-
*
|
|
4266
|
+
* 处理设置元素属性
|
|
4284
4267
|
*/
|
|
4285
|
-
|
|
4286
|
-
if (!
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4291
|
-
|
|
4292
|
-
|
|
4293
|
-
this.hideTooltip();
|
|
4294
|
-
console.log("[ElementSelector] \u9009\u62E9\u5668\u5DF2\u7981\u7528");
|
|
4268
|
+
handleSetElementAttrs(payload) {
|
|
4269
|
+
if (!payload?.selector || !payload?.attrs) return;
|
|
4270
|
+
const elements = document.querySelectorAll(payload.selector);
|
|
4271
|
+
elements.forEach((element) => {
|
|
4272
|
+
Object.entries(payload.attrs).forEach(([key, value]) => {
|
|
4273
|
+
element.setAttribute(key, String(value));
|
|
4274
|
+
});
|
|
4275
|
+
});
|
|
4295
4276
|
this.sendMessage({
|
|
4296
|
-
type: "
|
|
4297
|
-
payload: {
|
|
4277
|
+
type: "ELEMENT_EVENT",
|
|
4278
|
+
payload: {
|
|
4279
|
+
type: "attrs_updated",
|
|
4280
|
+
selector: payload.selector,
|
|
4281
|
+
attrs: payload.attrs,
|
|
4282
|
+
elementsUpdated: elements.length
|
|
4283
|
+
},
|
|
4284
|
+
timestamp: Date.now()
|
|
4298
4285
|
});
|
|
4299
4286
|
}
|
|
4300
4287
|
/**
|
|
4301
|
-
*
|
|
4288
|
+
* 处理复制元素请求
|
|
4302
4289
|
*/
|
|
4303
|
-
|
|
4304
|
-
if (
|
|
4305
|
-
|
|
4306
|
-
|
|
4307
|
-
|
|
4290
|
+
handleDuplicateElementRequested(payload) {
|
|
4291
|
+
if (!payload?.selector) return;
|
|
4292
|
+
const element = document.querySelector(payload.selector);
|
|
4293
|
+
if (element && element.parentElement) {
|
|
4294
|
+
const clone = element.cloneNode(true);
|
|
4295
|
+
clone.setAttribute("data-duplicated", "true");
|
|
4296
|
+
element.parentElement.appendChild(clone);
|
|
4297
|
+
this.sendMessage({
|
|
4298
|
+
type: "ELEMENT_EVENT",
|
|
4299
|
+
payload: {
|
|
4300
|
+
type: "duplicated",
|
|
4301
|
+
originalSelector: payload.selector,
|
|
4302
|
+
duplicatedElement: this.getElementInfo(clone)
|
|
4303
|
+
},
|
|
4304
|
+
timestamp: Date.now()
|
|
4305
|
+
});
|
|
4308
4306
|
}
|
|
4309
4307
|
}
|
|
4310
4308
|
/**
|
|
4311
|
-
*
|
|
4312
|
-
*/
|
|
4313
|
-
getSelectorState() {
|
|
4314
|
-
return {
|
|
4315
|
-
isActive: this.isActive,
|
|
4316
|
-
highlightedElement: this.highlightedElement ? this.getElementInfo(this.highlightedElement) : null,
|
|
4317
|
-
selectedElements: this.selectedElements.map((el) => this.getElementInfo(el)),
|
|
4318
|
-
config: { ...this.config }
|
|
4319
|
-
};
|
|
4320
|
-
}
|
|
4321
|
-
/** ----------------- 事件监听器管理 ----------------- */
|
|
4322
|
-
/**
|
|
4323
|
-
* 设置事件监听器
|
|
4309
|
+
* 处理编辑文本请求
|
|
4324
4310
|
*/
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
|
|
4311
|
+
handleEditTextRequested(payload) {
|
|
4312
|
+
if (!payload?.selector) return;
|
|
4313
|
+
const element = document.querySelector(payload.selector);
|
|
4314
|
+
if (element instanceof HTMLElement) {
|
|
4315
|
+
element.setAttribute("contenteditable", "true");
|
|
4316
|
+
element.focus();
|
|
4317
|
+
const handleInput = () => {
|
|
4318
|
+
this.sendMessage({
|
|
4319
|
+
type: "ELEMENT_EVENT",
|
|
4320
|
+
payload: {
|
|
4321
|
+
type: "text_updated",
|
|
4322
|
+
selector: payload.selector,
|
|
4323
|
+
content: element.innerText
|
|
4324
|
+
},
|
|
4325
|
+
timestamp: Date.now()
|
|
4326
|
+
});
|
|
4327
|
+
};
|
|
4328
|
+
const handleBlur = () => {
|
|
4329
|
+
element.removeAttribute("contenteditable");
|
|
4330
|
+
element.removeEventListener("input", handleInput);
|
|
4331
|
+
element.removeEventListener("blur", handleBlur);
|
|
4332
|
+
this.sendMessage({
|
|
4333
|
+
type: "ELEMENT_EVENT",
|
|
4334
|
+
payload: {
|
|
4335
|
+
type: "edit_completed",
|
|
4336
|
+
selector: payload.selector,
|
|
4337
|
+
finalContent: element.innerText
|
|
4338
|
+
},
|
|
4339
|
+
timestamp: Date.now()
|
|
4340
|
+
});
|
|
4341
|
+
};
|
|
4342
|
+
element.addEventListener("input", handleInput);
|
|
4343
|
+
element.addEventListener("blur", handleBlur);
|
|
4344
|
+
}
|
|
4337
4345
|
}
|
|
4346
|
+
/** ----------------- 组件树相关消息处理 ----------------- */
|
|
4338
4347
|
/**
|
|
4339
|
-
*
|
|
4348
|
+
* 处理请求组件树
|
|
4340
4349
|
*/
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
|
|
4350
|
+
handleRequestComponentTree() {
|
|
4351
|
+
if (!this.componentTreeGenerator) return;
|
|
4352
|
+
try {
|
|
4353
|
+
const rootElement = document.querySelector("#root") || document.body;
|
|
4354
|
+
const componentTree = this.componentTreeGenerator.generateComponentTree(rootElement);
|
|
4355
|
+
this.sendMessage({
|
|
4356
|
+
type: "COMPONENT_EVENT",
|
|
4357
|
+
payload: {
|
|
4358
|
+
type: "tree_response",
|
|
4359
|
+
...componentTree
|
|
4360
|
+
},
|
|
4361
|
+
timestamp: Date.now()
|
|
4362
|
+
});
|
|
4363
|
+
} catch (error) {
|
|
4364
|
+
const originalConsole = getOriginalConsole2();
|
|
4365
|
+
originalConsole.error("[MessageBridge] \u751F\u6210\u7EC4\u4EF6\u6811\u5931\u8D25:", error);
|
|
4366
|
+
this.sendMessage({
|
|
4367
|
+
type: "COMPONENT_EVENT",
|
|
4368
|
+
payload: {
|
|
4369
|
+
type: "tree_error",
|
|
4370
|
+
error: error instanceof Error ? error.message : String(error)
|
|
4371
|
+
},
|
|
4372
|
+
timestamp: Date.now()
|
|
4373
|
+
});
|
|
4374
|
+
}
|
|
4344
4375
|
}
|
|
4345
4376
|
/**
|
|
4346
|
-
*
|
|
4347
|
-
*/
|
|
4348
|
-
removeEventListeners() {
|
|
4349
|
-
this.eventListeners.forEach(({ element, event, handler }) => {
|
|
4350
|
-
element.removeEventListener(event, handler);
|
|
4351
|
-
});
|
|
4352
|
-
this.eventListeners = [];
|
|
4353
|
-
}
|
|
4354
|
-
/** ----------------- 事件处理方法 ----------------- */
|
|
4355
|
-
/**
|
|
4356
|
-
* 跟踪鼠标位置
|
|
4357
|
-
*/
|
|
4358
|
-
trackMousePosition(event) {
|
|
4359
|
-
this.mousePosition = { x: event.clientX, y: event.clientY };
|
|
4360
|
-
}
|
|
4361
|
-
/**
|
|
4362
|
-
* 处理鼠标悬停
|
|
4363
|
-
*/
|
|
4364
|
-
handleMouseOver(event) {
|
|
4365
|
-
if (!this.isActive) return;
|
|
4366
|
-
const target = event.target;
|
|
4367
|
-
if (!this.isSelectableElement(target)) return;
|
|
4368
|
-
this.highlightElement(target);
|
|
4369
|
-
this.updateTooltip(target);
|
|
4370
|
-
}
|
|
4371
|
-
/**
|
|
4372
|
-
* 处理鼠标离开
|
|
4373
|
-
*/
|
|
4374
|
-
handleMouseOut(event) {
|
|
4375
|
-
if (!this.isActive) return;
|
|
4376
|
-
this.clearHighlight();
|
|
4377
|
-
this.hideTooltip();
|
|
4378
|
-
}
|
|
4379
|
-
/**
|
|
4380
|
-
* 处理点击
|
|
4381
|
-
*/
|
|
4382
|
-
handleClick(event) {
|
|
4383
|
-
if (!this.isActive) return;
|
|
4384
|
-
const currentTimestamp = Date.now();
|
|
4385
|
-
const target = event.target;
|
|
4386
|
-
if (this.lastClickTarget === target && currentTimestamp - this.lastClickTimestamp < 100) {
|
|
4387
|
-
event.preventDefault();
|
|
4388
|
-
event.stopPropagation();
|
|
4389
|
-
return;
|
|
4390
|
-
}
|
|
4391
|
-
this.lastClickTimestamp = currentTimestamp;
|
|
4392
|
-
this.lastClickTarget = target;
|
|
4393
|
-
event.preventDefault();
|
|
4394
|
-
event.stopPropagation();
|
|
4395
|
-
if (!this.isSelectableElement(target)) return;
|
|
4396
|
-
if (event.metaKey || event.ctrlKey) {
|
|
4397
|
-
this.toggleElementSelection(target);
|
|
4398
|
-
} else {
|
|
4399
|
-
this.selectElement(target);
|
|
4400
|
-
}
|
|
4401
|
-
this.sendMessage({
|
|
4402
|
-
type: "ELEMENT_CLICKED",
|
|
4403
|
-
payload: {
|
|
4404
|
-
element: this.getElementInfo(target),
|
|
4405
|
-
isMultiSelect: event.metaKey || event.ctrlKey
|
|
4406
|
-
}
|
|
4407
|
-
});
|
|
4408
|
-
}
|
|
4409
|
-
/**
|
|
4410
|
-
* 处理双击
|
|
4411
|
-
*/
|
|
4412
|
-
handleDoubleClick(event) {
|
|
4413
|
-
if (!this.isActive) return;
|
|
4414
|
-
event.preventDefault();
|
|
4415
|
-
event.stopPropagation();
|
|
4416
|
-
const target = event.target;
|
|
4417
|
-
if (!this.isSelectableElement(target)) return;
|
|
4418
|
-
this.sendMessage({
|
|
4419
|
-
type: "ELEMENT_DOUBLE_CLICKED",
|
|
4420
|
-
payload: {
|
|
4421
|
-
element: this.getElementInfo(target)
|
|
4422
|
-
}
|
|
4423
|
-
});
|
|
4424
|
-
}
|
|
4425
|
-
/**
|
|
4426
|
-
* 处理滚动
|
|
4427
|
-
*/
|
|
4428
|
-
handleScroll() {
|
|
4429
|
-
if (!this.isActive) return;
|
|
4430
|
-
this.hideTooltip();
|
|
4431
|
-
}
|
|
4432
|
-
/**
|
|
4433
|
-
* 处理键盘事件
|
|
4434
|
-
*/
|
|
4435
|
-
handleKeyDown(event) {
|
|
4436
|
-
if (!this.isActive) return;
|
|
4437
|
-
const keyboardEvent = event;
|
|
4438
|
-
if (keyboardEvent.key === "Escape") {
|
|
4439
|
-
event.preventDefault();
|
|
4440
|
-
event.stopPropagation();
|
|
4441
|
-
this.disableSelector();
|
|
4442
|
-
}
|
|
4443
|
-
}
|
|
4444
|
-
/**
|
|
4445
|
-
* 阻止表单交互
|
|
4446
|
-
*/
|
|
4447
|
-
preventFormInteraction(event) {
|
|
4448
|
-
if (!this.isActive) return;
|
|
4449
|
-
const target = event.target;
|
|
4450
|
-
if (["input", "textarea", "select"].includes(target.tagName.toLowerCase())) {
|
|
4451
|
-
event.preventDefault();
|
|
4452
|
-
}
|
|
4453
|
-
}
|
|
4454
|
-
/**
|
|
4455
|
-
* 阻止所有交互
|
|
4456
|
-
*/
|
|
4457
|
-
preventAllInteraction(event) {
|
|
4458
|
-
if (this.isActive) {
|
|
4459
|
-
event.preventDefault();
|
|
4460
|
-
event.stopPropagation();
|
|
4461
|
-
return false;
|
|
4462
|
-
}
|
|
4463
|
-
}
|
|
4464
|
-
/** ----------------- 元素操作方法 ----------------- */
|
|
4465
|
-
/**
|
|
4466
|
-
* 高亮元素
|
|
4467
|
-
*/
|
|
4468
|
-
highlightElement(element) {
|
|
4469
|
-
this.clearHighlight();
|
|
4470
|
-
this.highlightedElement = element;
|
|
4471
|
-
element.setAttribute("data-element-hovered", "true");
|
|
4472
|
-
if (this.isFullWidthElement(element)) {
|
|
4473
|
-
element.setAttribute("data-full-width", "true");
|
|
4474
|
-
}
|
|
4475
|
-
}
|
|
4476
|
-
/**
|
|
4477
|
-
* 清除高亮
|
|
4478
|
-
*/
|
|
4479
|
-
clearHighlight() {
|
|
4480
|
-
if (this.highlightedElement) {
|
|
4481
|
-
this.highlightedElement.removeAttribute("data-element-hovered");
|
|
4482
|
-
this.highlightedElement.removeAttribute("data-full-width");
|
|
4483
|
-
this.highlightedElement = null;
|
|
4484
|
-
}
|
|
4485
|
-
}
|
|
4486
|
-
/**
|
|
4487
|
-
* 选择元素
|
|
4488
|
-
*/
|
|
4489
|
-
selectElement(element) {
|
|
4490
|
-
this.clearSelection();
|
|
4491
|
-
this.selectedElements = [element];
|
|
4492
|
-
element.setAttribute("data-element-selected", "true");
|
|
4493
|
-
if (this.isFullWidthElement(element)) {
|
|
4494
|
-
element.setAttribute("data-full-width", "true");
|
|
4495
|
-
}
|
|
4496
|
-
}
|
|
4497
|
-
/**
|
|
4498
|
-
* 切换元素选择状态
|
|
4499
|
-
*/
|
|
4500
|
-
toggleElementSelection(element) {
|
|
4501
|
-
const index = this.selectedElements.indexOf(element);
|
|
4502
|
-
if (index > -1) {
|
|
4503
|
-
this.selectedElements.splice(index, 1);
|
|
4504
|
-
element.removeAttribute("data-element-selected");
|
|
4505
|
-
element.removeAttribute("data-full-width");
|
|
4506
|
-
} else {
|
|
4507
|
-
this.selectedElements.push(element);
|
|
4508
|
-
element.setAttribute("data-element-selected", "true");
|
|
4509
|
-
if (this.isFullWidthElement(element)) {
|
|
4510
|
-
element.setAttribute("data-full-width", "true");
|
|
4511
|
-
}
|
|
4512
|
-
}
|
|
4513
|
-
}
|
|
4514
|
-
/**
|
|
4515
|
-
* 清除选择
|
|
4516
|
-
*/
|
|
4517
|
-
clearSelection() {
|
|
4518
|
-
this.selectedElements.forEach((element) => {
|
|
4519
|
-
element.removeAttribute("data-element-selected");
|
|
4520
|
-
element.removeAttribute("data-full-width");
|
|
4521
|
-
});
|
|
4522
|
-
this.selectedElements = [];
|
|
4523
|
-
}
|
|
4524
|
-
/** ----------------- 工具提示管理 ----------------- */
|
|
4525
|
-
/**
|
|
4526
|
-
* 更新工具提示
|
|
4527
|
-
*/
|
|
4528
|
-
updateTooltip(element) {
|
|
4529
|
-
if (!this.tooltip) return;
|
|
4530
|
-
const rect = element.getBoundingClientRect();
|
|
4531
|
-
const tagName = element.tagName.toLowerCase();
|
|
4532
|
-
this.tooltip.textContent = tagName;
|
|
4533
|
-
this.tooltip.style.display = "block";
|
|
4534
|
-
const isFullWidth = this.isFullWidthElement(element);
|
|
4535
|
-
if (isFullWidth) {
|
|
4536
|
-
this.tooltip.style.left = this.config.FULL_WIDTH_TOOLTIP_OFFSET + "px";
|
|
4537
|
-
this.tooltip.style.top = this.config.FULL_WIDTH_TOOLTIP_OFFSET + "px";
|
|
4538
|
-
} else {
|
|
4539
|
-
const top = Math.max(0, rect.top - 30);
|
|
4540
|
-
this.tooltip.style.left = `${Math.max(0, rect.left)}px`;
|
|
4541
|
-
this.tooltip.style.top = `${top}px`;
|
|
4542
|
-
}
|
|
4543
|
-
}
|
|
4544
|
-
/**
|
|
4545
|
-
* 隐藏工具提示
|
|
4546
|
-
*/
|
|
4547
|
-
hideTooltip() {
|
|
4548
|
-
if (this.tooltip) {
|
|
4549
|
-
this.tooltip.style.display = "none";
|
|
4550
|
-
}
|
|
4551
|
-
}
|
|
4552
|
-
/** ----------------- 按钮状态管理 ----------------- */
|
|
4553
|
-
/**
|
|
4554
|
-
* 管理按钮状态
|
|
4555
|
-
*/
|
|
4556
|
-
manageButtonStates(enable) {
|
|
4557
|
-
if (!this.rootElement) return;
|
|
4558
|
-
const buttons = this.rootElement.querySelectorAll('button, input[type="button"], input[type="submit"]');
|
|
4559
|
-
if (enable) {
|
|
4560
|
-
buttons.forEach((button) => {
|
|
4561
|
-
const btn = button;
|
|
4562
|
-
if (!btn.disabled) {
|
|
4563
|
-
btn.disabled = true;
|
|
4564
|
-
btn.setAttribute("data-selector-disabled", "true");
|
|
4565
|
-
}
|
|
4566
|
-
});
|
|
4567
|
-
} else {
|
|
4568
|
-
buttons.forEach((button) => {
|
|
4569
|
-
const btn = button;
|
|
4570
|
-
if (btn.hasAttribute("data-selector-disabled")) {
|
|
4571
|
-
btn.disabled = false;
|
|
4572
|
-
btn.removeAttribute("data-selector-disabled");
|
|
4573
|
-
}
|
|
4574
|
-
});
|
|
4575
|
-
}
|
|
4576
|
-
}
|
|
4577
|
-
/** ----------------- 新增的精确代码位置定位方法 ----------------- */
|
|
4578
|
-
/**
|
|
4579
|
-
* 检查元素是否有 howone ID
|
|
4580
|
-
*/
|
|
4581
|
-
hasHowoneId(element) {
|
|
4582
|
-
return element.hasAttribute("data-howone-id");
|
|
4583
|
-
}
|
|
4584
|
-
/**
|
|
4585
|
-
* 解析 howone ID
|
|
4586
|
-
*/
|
|
4587
|
-
parseHowoneId(element) {
|
|
4588
|
-
const howoneId = element.getAttribute("data-howone-id");
|
|
4589
|
-
if (!howoneId) return null;
|
|
4590
|
-
try {
|
|
4591
|
-
if (howoneId.includes(":")) {
|
|
4592
|
-
const parts = howoneId.split(":");
|
|
4593
|
-
if (parts.length >= 2) {
|
|
4594
|
-
return {
|
|
4595
|
-
filePath: parts[0],
|
|
4596
|
-
lineNumber: parseInt(parts[1], 10),
|
|
4597
|
-
col: parts[2] ? parseInt(parts[2], 10) : 0
|
|
4598
|
-
};
|
|
4599
|
-
}
|
|
4600
|
-
} else {
|
|
4601
|
-
const parsed = JSON.parse(howoneId);
|
|
4602
|
-
if (parsed.filePath && parsed.lineNumber) {
|
|
4603
|
-
return {
|
|
4604
|
-
filePath: parsed.filePath,
|
|
4605
|
-
lineNumber: parsed.lineNumber,
|
|
4606
|
-
col: parsed.col || 0
|
|
4607
|
-
};
|
|
4608
|
-
}
|
|
4609
|
-
}
|
|
4610
|
-
} catch (error) {
|
|
4611
|
-
console.warn("[ElementSelector] \u89E3\u6790 data-howone-id \u5931\u8D25:", error);
|
|
4612
|
-
}
|
|
4613
|
-
return null;
|
|
4614
|
-
}
|
|
4615
|
-
/**
|
|
4616
|
-
* 获取元素的代码位置
|
|
4617
|
-
*/
|
|
4618
|
-
getElementLocation(element) {
|
|
4619
|
-
return this.parseHowoneId(element);
|
|
4620
|
-
}
|
|
4621
|
-
/**
|
|
4622
|
-
* 提取元素数据(包含位置信息)
|
|
4623
|
-
*/
|
|
4624
|
-
extractElementData(element) {
|
|
4625
|
-
const location = this.getElementLocation(element);
|
|
4626
|
-
return {
|
|
4627
|
-
id: element.id || void 0,
|
|
4628
|
-
className: element.className || void 0,
|
|
4629
|
-
textContent: element.textContent?.trim().substring(0, 100) || void 0,
|
|
4630
|
-
filePath: location?.filePath,
|
|
4631
|
-
lineNumber: location?.lineNumber,
|
|
4632
|
-
col: location?.col,
|
|
4633
|
-
elementType: element.tagName.toLowerCase(),
|
|
4634
|
-
attrs: this.getElementAttributes(element)
|
|
4635
|
-
};
|
|
4636
|
-
}
|
|
4637
|
-
/**
|
|
4638
|
-
* 根据代码位置查找元素
|
|
4639
|
-
*/
|
|
4640
|
-
findElementsByLocation(filePath, lineNumber) {
|
|
4641
|
-
const elements = [];
|
|
4642
|
-
const elementsWithHowoneId = this.rootElement?.querySelectorAll("[data-howone-id]") || [];
|
|
4643
|
-
elementsWithHowoneId.forEach((element) => {
|
|
4644
|
-
const location = this.getElementLocation(element);
|
|
4645
|
-
if (location && location.filePath === filePath && location.lineNumber === lineNumber) {
|
|
4646
|
-
elements.push(element);
|
|
4647
|
-
}
|
|
4648
|
-
});
|
|
4649
|
-
return elements;
|
|
4650
|
-
}
|
|
4651
|
-
/**
|
|
4652
|
-
* 获取指定坐标位置的元素
|
|
4653
|
-
*/
|
|
4654
|
-
getElementAtPoint(x, y) {
|
|
4655
|
-
const originalDisplay = this.tooltip?.style.display;
|
|
4656
|
-
if (this.tooltip) {
|
|
4657
|
-
this.tooltip.style.display = "none";
|
|
4658
|
-
}
|
|
4659
|
-
const element = document.elementFromPoint(x, y);
|
|
4660
|
-
if (this.tooltip && originalDisplay) {
|
|
4661
|
-
this.tooltip.style.display = originalDisplay;
|
|
4662
|
-
}
|
|
4663
|
-
return element;
|
|
4664
|
-
}
|
|
4665
|
-
/** ----------------- 元素编辑功能 ----------------- */
|
|
4666
|
-
/**
|
|
4667
|
-
* 设置元素内容
|
|
4668
|
-
*/
|
|
4669
|
-
setElementContent(selector, content) {
|
|
4670
|
-
try {
|
|
4671
|
-
const element = document.querySelector(selector);
|
|
4672
|
-
if (!element) return false;
|
|
4673
|
-
if (element.tagName.toLowerCase() === "input" || element.tagName.toLowerCase() === "textarea") {
|
|
4674
|
-
element.value = content;
|
|
4675
|
-
} else {
|
|
4676
|
-
element.textContent = content;
|
|
4677
|
-
}
|
|
4678
|
-
this.sendMessage({
|
|
4679
|
-
type: "ELEMENT_CONTENT_UPDATED",
|
|
4680
|
-
payload: {
|
|
4681
|
-
selector,
|
|
4682
|
-
content,
|
|
4683
|
-
element: this.getElementInfo(element)
|
|
4684
|
-
}
|
|
4685
|
-
});
|
|
4686
|
-
return true;
|
|
4687
|
-
} catch (error) {
|
|
4688
|
-
console.error("[ElementSelector] \u8BBE\u7F6E\u5143\u7D20\u5185\u5BB9\u5931\u8D25:", error);
|
|
4689
|
-
return false;
|
|
4690
|
-
}
|
|
4691
|
-
}
|
|
4692
|
-
/**
|
|
4693
|
-
* 设置元素属性
|
|
4694
|
-
*/
|
|
4695
|
-
setElementAttributes(selector, attributes) {
|
|
4696
|
-
try {
|
|
4697
|
-
const element = document.querySelector(selector);
|
|
4698
|
-
if (!element) return false;
|
|
4699
|
-
Object.entries(attributes).forEach(([key, value]) => {
|
|
4700
|
-
if (value === null || value === void 0) {
|
|
4701
|
-
element.removeAttribute(key);
|
|
4702
|
-
} else {
|
|
4703
|
-
element.setAttribute(key, value);
|
|
4704
|
-
}
|
|
4705
|
-
});
|
|
4706
|
-
this.sendMessage({
|
|
4707
|
-
type: "ELEMENT_ATTRIBUTES_UPDATED",
|
|
4708
|
-
payload: {
|
|
4709
|
-
selector,
|
|
4710
|
-
attributes,
|
|
4711
|
-
element: this.getElementInfo(element)
|
|
4712
|
-
}
|
|
4713
|
-
});
|
|
4714
|
-
return true;
|
|
4715
|
-
} catch (error) {
|
|
4716
|
-
console.error("[ElementSelector] \u8BBE\u7F6E\u5143\u7D20\u5C5E\u6027\u5931\u8D25:", error);
|
|
4717
|
-
return false;
|
|
4718
|
-
}
|
|
4719
|
-
}
|
|
4720
|
-
/**
|
|
4721
|
-
* 复制元素
|
|
4722
|
-
*/
|
|
4723
|
-
duplicateElement(selector) {
|
|
4724
|
-
try {
|
|
4725
|
-
const element = document.querySelector(selector);
|
|
4726
|
-
if (!element || !element.parentNode) return false;
|
|
4727
|
-
const clonedElement = element.cloneNode(true);
|
|
4728
|
-
clonedElement.removeAttribute("data-blnk-id");
|
|
4729
|
-
element.parentNode.insertBefore(clonedElement, element.nextSibling);
|
|
4730
|
-
this.sendMessage({
|
|
4731
|
-
type: "ELEMENT_DUPLICATED",
|
|
4732
|
-
payload: {
|
|
4733
|
-
originalSelector: selector,
|
|
4734
|
-
duplicatedElement: this.getElementInfo(clonedElement)
|
|
4735
|
-
}
|
|
4736
|
-
});
|
|
4737
|
-
return true;
|
|
4738
|
-
} catch (error) {
|
|
4739
|
-
console.error("[ElementSelector] \u590D\u5236\u5143\u7D20\u5931\u8D25:", error);
|
|
4740
|
-
return false;
|
|
4741
|
-
}
|
|
4742
|
-
}
|
|
4743
|
-
/**
|
|
4744
|
-
* 启用文本编辑
|
|
4745
|
-
*/
|
|
4746
|
-
enableTextEditing(selector) {
|
|
4747
|
-
try {
|
|
4748
|
-
const element = document.querySelector(selector);
|
|
4749
|
-
if (!element) return false;
|
|
4750
|
-
element.setAttribute("contenteditable", "true");
|
|
4751
|
-
element.setAttribute("data-editing", "true");
|
|
4752
|
-
element.focus();
|
|
4753
|
-
const handleEditComplete = () => {
|
|
4754
|
-
element.removeAttribute("contenteditable");
|
|
4755
|
-
element.removeAttribute("data-editing");
|
|
4756
|
-
element.removeEventListener("blur", handleEditComplete);
|
|
4757
|
-
element.removeEventListener("keydown", handleKeyDown);
|
|
4758
|
-
this.sendMessage({
|
|
4759
|
-
type: "ELEMENT_TEXT_UPDATED",
|
|
4760
|
-
payload: {
|
|
4761
|
-
selector,
|
|
4762
|
-
content: element.textContent || "",
|
|
4763
|
-
element: this.getElementInfo(element)
|
|
4764
|
-
}
|
|
4765
|
-
});
|
|
4766
|
-
};
|
|
4767
|
-
const handleKeyDown = (event) => {
|
|
4768
|
-
const keyboardEvent = event;
|
|
4769
|
-
if (keyboardEvent.key === "Enter" && !keyboardEvent.shiftKey) {
|
|
4770
|
-
event.preventDefault();
|
|
4771
|
-
handleEditComplete();
|
|
4772
|
-
} else if (keyboardEvent.key === "Escape") {
|
|
4773
|
-
event.preventDefault();
|
|
4774
|
-
handleEditComplete();
|
|
4775
|
-
}
|
|
4776
|
-
};
|
|
4777
|
-
element.addEventListener("blur", handleEditComplete);
|
|
4778
|
-
element.addEventListener("keydown", handleKeyDown);
|
|
4779
|
-
return true;
|
|
4780
|
-
} catch (error) {
|
|
4781
|
-
console.error("[ElementSelector] \u542F\u7528\u6587\u672C\u7F16\u8F91\u5931\u8D25:", error);
|
|
4782
|
-
return false;
|
|
4783
|
-
}
|
|
4784
|
-
}
|
|
4785
|
-
/** ----------------- 高级交互功能 ----------------- */
|
|
4786
|
-
/**
|
|
4787
|
-
* 获取父元素
|
|
4788
|
-
*/
|
|
4789
|
-
getParentElement(selector) {
|
|
4790
|
-
try {
|
|
4791
|
-
const element = document.querySelector(selector);
|
|
4792
|
-
return element?.parentElement || null;
|
|
4793
|
-
} catch (error) {
|
|
4794
|
-
console.error("[ElementSelector] \u83B7\u53D6\u7236\u5143\u7D20\u5931\u8D25:", error);
|
|
4795
|
-
return null;
|
|
4796
|
-
}
|
|
4797
|
-
}
|
|
4798
|
-
/**
|
|
4799
|
-
* 外部悬停控制 - 通过选择器悬停元素
|
|
4800
|
-
*/
|
|
4801
|
-
hoverElementBySelector(selector) {
|
|
4802
|
-
try {
|
|
4803
|
-
const element = document.querySelector(selector);
|
|
4804
|
-
if (!element) return false;
|
|
4805
|
-
this.highlightElement(element);
|
|
4806
|
-
this.updateTooltip(element);
|
|
4807
|
-
return true;
|
|
4808
|
-
} catch (error) {
|
|
4809
|
-
console.error("[ElementSelector] \u5916\u90E8\u60AC\u505C\u63A7\u5236\u5931\u8D25:", error);
|
|
4810
|
-
return false;
|
|
4811
|
-
}
|
|
4812
|
-
}
|
|
4813
|
-
/**
|
|
4814
|
-
* 外部悬停控制 - 取消悬停
|
|
4815
|
-
*/
|
|
4816
|
-
unhoverElement() {
|
|
4817
|
-
this.clearHighlight();
|
|
4818
|
-
this.hideTooltip();
|
|
4819
|
-
}
|
|
4820
|
-
/** ----------------- 辅助方法 ----------------- */
|
|
4821
|
-
/**
|
|
4822
|
-
* 检查元素是否为全宽元素
|
|
4823
|
-
*/
|
|
4824
|
-
isFullWidthElement(element) {
|
|
4825
|
-
try {
|
|
4826
|
-
const rect = element.getBoundingClientRect();
|
|
4827
|
-
return Math.abs(rect.width - window.innerWidth) < 5;
|
|
4828
|
-
} catch (error) {
|
|
4829
|
-
console.warn("[ElementSelector] \u68C0\u67E5\u5168\u5BBD\u5143\u7D20\u5931\u8D25:", error);
|
|
4830
|
-
return false;
|
|
4831
|
-
}
|
|
4832
|
-
}
|
|
4833
|
-
/**
|
|
4834
|
-
* 检查元素是否可选择
|
|
4835
|
-
*/
|
|
4836
|
-
isSelectableElement(element) {
|
|
4837
|
-
if (!element || element === document.body || element === document.documentElement) {
|
|
4838
|
-
return false;
|
|
4839
|
-
}
|
|
4840
|
-
if (this.hasHowoneId(element)) {
|
|
4841
|
-
return true;
|
|
4842
|
-
}
|
|
4843
|
-
if (element.id === "howone-element-tooltip" || element.classList.contains("howone-tooltip")) {
|
|
4844
|
-
return false;
|
|
4845
|
-
}
|
|
4846
|
-
const tagName = element.tagName.toLowerCase();
|
|
4847
|
-
if (["script", "style", "meta", "link", "title"].includes(tagName)) {
|
|
4848
|
-
return false;
|
|
4849
|
-
}
|
|
4850
|
-
return true;
|
|
4851
|
-
}
|
|
4852
|
-
/**
|
|
4853
|
-
* 获取元素信息
|
|
4854
|
-
*/
|
|
4855
|
-
getElementInfo(element) {
|
|
4856
|
-
const location = this.getElementLocation(element);
|
|
4857
|
-
return {
|
|
4858
|
-
tagName: element.tagName.toLowerCase(),
|
|
4859
|
-
id: element.id || void 0,
|
|
4860
|
-
className: element.className || void 0,
|
|
4861
|
-
textContent: element.textContent?.trim().substring(0, 100) || void 0,
|
|
4862
|
-
attributes: this.getElementAttributes(element),
|
|
4863
|
-
selector: this.getElementSelector(element),
|
|
4864
|
-
boundingRect: element.getBoundingClientRect(),
|
|
4865
|
-
location: location || void 0
|
|
4866
|
-
};
|
|
4867
|
-
}
|
|
4868
|
-
/**
|
|
4869
|
-
* 获取元素属性
|
|
4870
|
-
*/
|
|
4871
|
-
getElementAttributes(element) {
|
|
4872
|
-
const attrs = {};
|
|
4873
|
-
const importantAttrs = ["id", "class", "data-testid", "data-howone-id", "data-component-path", "data-blnk-id", "href", "src", "type", "name"];
|
|
4874
|
-
importantAttrs.forEach((attr) => {
|
|
4875
|
-
const value = element.getAttribute(attr);
|
|
4876
|
-
if (value) {
|
|
4877
|
-
attrs[attr] = value;
|
|
4878
|
-
}
|
|
4879
|
-
});
|
|
4880
|
-
return attrs;
|
|
4881
|
-
}
|
|
4882
|
-
/**
|
|
4883
|
-
* 获取元素选择器
|
|
4884
|
-
*/
|
|
4885
|
-
getElementSelector(element) {
|
|
4886
|
-
const howoneId = element.getAttribute("data-howone-id");
|
|
4887
|
-
if (howoneId) {
|
|
4888
|
-
return `[data-howone-id="${howoneId}"]`;
|
|
4889
|
-
}
|
|
4890
|
-
if (element.id) {
|
|
4891
|
-
return `#${element.id}`;
|
|
4892
|
-
}
|
|
4893
|
-
const dataTestId = element.getAttribute("data-testid");
|
|
4894
|
-
if (dataTestId) {
|
|
4895
|
-
return `[data-testid="${dataTestId}"]`;
|
|
4896
|
-
}
|
|
4897
|
-
if (element.className) {
|
|
4898
|
-
const classes = element.className.split(" ").filter((c) => c.trim());
|
|
4899
|
-
if (classes.length > 0) {
|
|
4900
|
-
return `.${classes[0]}`;
|
|
4901
|
-
}
|
|
4902
|
-
}
|
|
4903
|
-
return element.tagName.toLowerCase();
|
|
4904
|
-
}
|
|
4905
|
-
/** ----------------- 公共接口方法 ----------------- */
|
|
4906
|
-
/**
|
|
4907
|
-
* 通过选择器高亮元素
|
|
4908
|
-
*/
|
|
4909
|
-
highlightElementBySelector(selector) {
|
|
4910
|
-
const element = document.querySelector(selector);
|
|
4911
|
-
if (element) {
|
|
4912
|
-
this.highlightElement(element);
|
|
4913
|
-
}
|
|
4914
|
-
}
|
|
4915
|
-
/**
|
|
4916
|
-
* 通过选择器取消高亮元素
|
|
4917
|
-
*/
|
|
4918
|
-
unhighlightElementBySelector(selector) {
|
|
4919
|
-
const element = document.querySelector(selector);
|
|
4920
|
-
if (element && element === this.highlightedElement) {
|
|
4921
|
-
this.clearHighlight();
|
|
4922
|
-
}
|
|
4923
|
-
}
|
|
4924
|
-
/**
|
|
4925
|
-
* 更新选中的元素
|
|
4926
|
-
*/
|
|
4927
|
-
updateSelectedElements(elements) {
|
|
4928
|
-
this.clearSelection();
|
|
4929
|
-
elements.forEach((elementData) => {
|
|
4930
|
-
const element = this.findElementByData(elementData);
|
|
4931
|
-
if (element) {
|
|
4932
|
-
this.selectedElements.push(element);
|
|
4933
|
-
element.setAttribute("data-element-selected", "true");
|
|
4934
|
-
if (this.isFullWidthElement(element)) {
|
|
4935
|
-
element.setAttribute("data-full-width", "true");
|
|
4936
|
-
}
|
|
4937
|
-
}
|
|
4938
|
-
});
|
|
4939
|
-
}
|
|
4940
|
-
/**
|
|
4941
|
-
* 根据数据查找元素
|
|
4942
|
-
*/
|
|
4943
|
-
findElementByData(elementData) {
|
|
4944
|
-
if (elementData.blinkId) {
|
|
4945
|
-
return document.querySelector(`[data-blnk-id="${elementData.blinkId}"]`);
|
|
4946
|
-
}
|
|
4947
|
-
if (elementData.id) {
|
|
4948
|
-
return document.getElementById(elementData.id);
|
|
4949
|
-
}
|
|
4950
|
-
if (elementData.selector) {
|
|
4951
|
-
return document.querySelector(elementData.selector);
|
|
4952
|
-
}
|
|
4953
|
-
return null;
|
|
4954
|
-
}
|
|
4955
|
-
/**
|
|
4956
|
-
* 销毁选择器
|
|
4957
|
-
*/
|
|
4958
|
-
destroy() {
|
|
4959
|
-
this.disableSelector();
|
|
4960
|
-
if (this.tooltip) {
|
|
4961
|
-
this.tooltip.remove();
|
|
4962
|
-
this.tooltip = null;
|
|
4963
|
-
}
|
|
4964
|
-
if (this.styleElement) {
|
|
4965
|
-
this.styleElement.remove();
|
|
4966
|
-
this.styleElement = null;
|
|
4967
|
-
}
|
|
4968
|
-
console.log("[ElementSelector] \u5143\u7D20\u9009\u62E9\u5668\u5DF2\u9500\u6BC1");
|
|
4969
|
-
}
|
|
4970
|
-
};
|
|
4971
|
-
|
|
4972
|
-
// src/utils/unified-error-handler/features/MessageBridge.ts
|
|
4973
|
-
var getOriginalConsole2 = () => window.__originalConsole || {
|
|
4974
|
-
log: console.log.bind(console),
|
|
4975
|
-
warn: console.warn.bind(console),
|
|
4976
|
-
error: console.error.bind(console),
|
|
4977
|
-
info: console.info.bind(console),
|
|
4978
|
-
debug: console.debug.bind(console)
|
|
4979
|
-
};
|
|
4980
|
-
var MessageBridge = class {
|
|
4981
|
-
constructor(sendMessage) {
|
|
4982
|
-
this.elementSelector = null;
|
|
4983
|
-
this.componentTreeGenerator = null;
|
|
4984
|
-
this.messageSender = createDefaultMessageSender({
|
|
4985
|
-
addTimestamp: true,
|
|
4986
|
-
enableDebugLog: false
|
|
4987
|
-
});
|
|
4988
|
-
this.sendMessage = sendMessage || this.messageSender.createSendFunction();
|
|
4989
|
-
this.setupMessageListener();
|
|
4990
|
-
console.log("[MessageBridge] \u6D88\u606F\u6865\u63A5\u5668\u521D\u59CB\u5316\u5B8C\u6210");
|
|
4991
|
-
}
|
|
4992
|
-
/** ----------------- 依赖注入方法 ----------------- */
|
|
4993
|
-
/**
|
|
4994
|
-
* 设置元素选择器
|
|
4995
|
-
*/
|
|
4996
|
-
setElementSelector(elementSelector2) {
|
|
4997
|
-
this.elementSelector = elementSelector2;
|
|
4998
|
-
}
|
|
4999
|
-
/**
|
|
5000
|
-
* 设置组件树生成器
|
|
5001
|
-
*/
|
|
5002
|
-
setComponentTreeGenerator(componentTreeGenerator) {
|
|
5003
|
-
this.componentTreeGenerator = componentTreeGenerator;
|
|
5004
|
-
}
|
|
5005
|
-
/** ----------------- 消息监听设置 ----------------- */
|
|
5006
|
-
/**
|
|
5007
|
-
* 设置消息监听器
|
|
5008
|
-
*/
|
|
5009
|
-
setupMessageListener() {
|
|
5010
|
-
this.messageListener = (event) => {
|
|
5011
|
-
if (!this.isOriginAllowed(event.origin)) {
|
|
5012
|
-
return;
|
|
5013
|
-
}
|
|
5014
|
-
if (event.data && typeof event.data === "object" && event.data.type) {
|
|
5015
|
-
this.handleMessage(event.data);
|
|
5016
|
-
}
|
|
5017
|
-
};
|
|
5018
|
-
window.addEventListener("message", this.messageListener);
|
|
5019
|
-
}
|
|
5020
|
-
/**
|
|
5021
|
-
* 检查来源是否被允许
|
|
5022
|
-
*/
|
|
5023
|
-
isOriginAllowed(origin) {
|
|
5024
|
-
return GLOBAL_CONFIG.ALLOWED_ORIGINS.some(
|
|
5025
|
-
(allowedOrigin) => origin.includes(allowedOrigin.replace("https://", "").replace("http://", ""))
|
|
5026
|
-
);
|
|
5027
|
-
}
|
|
5028
|
-
/** ----------------- 主要消息处理方法 ----------------- */
|
|
5029
|
-
/**
|
|
5030
|
-
* 处理消息
|
|
5031
|
-
*/
|
|
5032
|
-
handleMessage(message) {
|
|
5033
|
-
try {
|
|
5034
|
-
const { type, payload } = message;
|
|
5035
|
-
switch (type) {
|
|
5036
|
-
// 选择器相关消息
|
|
5037
|
-
case "TOGGLE_SELECTOR":
|
|
5038
|
-
this.handleToggleSelector(payload);
|
|
5039
|
-
break;
|
|
5040
|
-
case "ENABLE_SELECTOR":
|
|
5041
|
-
this.handleEnableElementSelector();
|
|
5042
|
-
break;
|
|
5043
|
-
case "DISABLE_SELECTOR":
|
|
5044
|
-
this.handleDisableElementSelector();
|
|
5045
|
-
break;
|
|
5046
|
-
case "GET_SELECTOR_STATE":
|
|
5047
|
-
this.handleGetSelectorState();
|
|
5048
|
-
break;
|
|
5049
|
-
// 元素操作消息
|
|
5050
|
-
case "HOVER_ELEMENT_BY_ID":
|
|
5051
|
-
this.handleHoverElementById(payload);
|
|
5052
|
-
break;
|
|
5053
|
-
case "UNHOVER_ELEMENT_BY_ID":
|
|
5054
|
-
this.handleUnhoverElementById(payload);
|
|
5055
|
-
break;
|
|
5056
|
-
case "HOVER_ELEMENT_REQUESTED":
|
|
5057
|
-
this.handleHoverElementRequested(payload);
|
|
5058
|
-
break;
|
|
5059
|
-
case "UNHOVER_ELEMENT_REQUESTED":
|
|
5060
|
-
this.handleUnhoverElementRequested(payload);
|
|
5061
|
-
break;
|
|
5062
|
-
case "SET_ELEMENT_CONTENT":
|
|
5063
|
-
this.handleSetElementContent(payload);
|
|
5064
|
-
break;
|
|
5065
|
-
case "SET_ELEMENT_ATTRS":
|
|
5066
|
-
this.handleSetElementAttrs(payload);
|
|
5067
|
-
break;
|
|
5068
|
-
case "DUPLICATE_ELEMENT_REQUESTED":
|
|
5069
|
-
this.handleDuplicateElementRequested(payload);
|
|
5070
|
-
break;
|
|
5071
|
-
case "EDIT_TEXT_REQUESTED":
|
|
5072
|
-
this.handleEditTextRequested(payload);
|
|
5073
|
-
break;
|
|
5074
|
-
case "UPDATE_SELECTED_ELEMENTS":
|
|
5075
|
-
this.handleUpdateSelectedElements(payload);
|
|
5076
|
-
break;
|
|
5077
|
-
// 新增的消息类型
|
|
5078
|
-
case "GET_ELEMENT_AT_POINT":
|
|
5079
|
-
this.handleGetElementAtPoint(payload);
|
|
5080
|
-
break;
|
|
5081
|
-
case "FIND_ELEMENTS_BY_LOCATION":
|
|
5082
|
-
this.handleFindElementsByLocation(payload);
|
|
5083
|
-
break;
|
|
5084
|
-
case "SET_ELEMENT_ATTRIBUTES":
|
|
5085
|
-
this.handleSetElementAttributes(payload);
|
|
5086
|
-
break;
|
|
5087
|
-
case "ENABLE_TEXT_EDITING":
|
|
5088
|
-
this.handleEnableTextEditing(payload);
|
|
5089
|
-
break;
|
|
5090
|
-
case "HOVER_ELEMENT_BY_SELECTOR":
|
|
5091
|
-
this.handleHoverElementBySelector(payload);
|
|
5092
|
-
break;
|
|
5093
|
-
case "UNHOVER_ELEMENT":
|
|
5094
|
-
this.handleUnhoverElement();
|
|
5095
|
-
break;
|
|
5096
|
-
// 组件树相关消息
|
|
5097
|
-
case "REQUEST_COMPONENT_TREE":
|
|
5098
|
-
this.handleRequestComponentTree();
|
|
5099
|
-
break;
|
|
5100
|
-
case "GET_PARENT_ELEMENT":
|
|
5101
|
-
this.handleGetParentElement(payload);
|
|
5102
|
-
break;
|
|
5103
|
-
// 样式相关消息
|
|
5104
|
-
case "SET_STYLESHEET":
|
|
5105
|
-
this.handleSetStylesheet(payload);
|
|
5106
|
-
break;
|
|
5107
|
-
default:
|
|
5108
|
-
break;
|
|
5109
|
-
}
|
|
5110
|
-
} catch (error) {
|
|
5111
|
-
console.error("[MessageBridge] \u5904\u7406\u6D88\u606F\u5931\u8D25:", error);
|
|
5112
|
-
this.sendMessage({
|
|
5113
|
-
type: "ERROR_EVENT",
|
|
5114
|
-
payload: {
|
|
5115
|
-
type: "message_handling",
|
|
5116
|
-
originalMessage: message,
|
|
5117
|
-
error: error instanceof Error ? error.message : String(error)
|
|
5118
|
-
},
|
|
5119
|
-
timestamp: Date.now()
|
|
5120
|
-
});
|
|
5121
|
-
}
|
|
5122
|
-
}
|
|
5123
|
-
/** ----------------- 选择器相关消息处理 ----------------- */
|
|
5124
|
-
/**
|
|
5125
|
-
* 处理切换选择器
|
|
5126
|
-
*/
|
|
5127
|
-
handleToggleSelector(payload) {
|
|
5128
|
-
if (!this.elementSelector) return;
|
|
5129
|
-
const shouldActivate = !!payload;
|
|
5130
|
-
if (shouldActivate) {
|
|
5131
|
-
this.elementSelector.enableSelector();
|
|
5132
|
-
} else {
|
|
5133
|
-
this.elementSelector.disableSelector();
|
|
5134
|
-
}
|
|
5135
|
-
}
|
|
5136
|
-
/**
|
|
5137
|
-
* 处理获取选择器状态
|
|
5138
|
-
*/
|
|
5139
|
-
handleGetSelectorState() {
|
|
5140
|
-
if (!this.elementSelector) return;
|
|
5141
|
-
const state = this.elementSelector.getSelectorState();
|
|
5142
|
-
this.sendMessage({
|
|
5143
|
-
type: "SELECTOR_EVENT",
|
|
5144
|
-
payload: {
|
|
5145
|
-
type: "state_response",
|
|
5146
|
-
...state
|
|
5147
|
-
},
|
|
5148
|
-
timestamp: Date.now()
|
|
5149
|
-
});
|
|
5150
|
-
}
|
|
5151
|
-
/**
|
|
5152
|
-
* 处理启用元素选择器
|
|
5153
|
-
*/
|
|
5154
|
-
handleEnableElementSelector() {
|
|
5155
|
-
if (!this.elementSelector) return;
|
|
5156
|
-
this.elementSelector.enableSelector();
|
|
5157
|
-
}
|
|
5158
|
-
/**
|
|
5159
|
-
* 处理禁用元素选择器
|
|
5160
|
-
*/
|
|
5161
|
-
handleDisableElementSelector() {
|
|
5162
|
-
if (!this.elementSelector) return;
|
|
5163
|
-
this.elementSelector.disableSelector();
|
|
5164
|
-
}
|
|
5165
|
-
/** ----------------- 元素操作消息处理 ----------------- */
|
|
5166
|
-
/**
|
|
5167
|
-
* 处理通过 ID 高亮元素
|
|
5168
|
-
*/
|
|
5169
|
-
handleHoverElementById(payload) {
|
|
5170
|
-
if (!this.elementSelector || !payload?.id) return;
|
|
5171
|
-
const selector = `#${payload.id}`;
|
|
5172
|
-
this.elementSelector.highlightElementBySelector(selector);
|
|
5173
|
-
}
|
|
5174
|
-
/**
|
|
5175
|
-
* 处理通过 ID 取消高亮元素
|
|
5176
|
-
*/
|
|
5177
|
-
handleUnhoverElementById(payload) {
|
|
5178
|
-
if (!this.elementSelector || !payload?.id) return;
|
|
5179
|
-
const selector = `#${payload.id}`;
|
|
5180
|
-
this.elementSelector.unhighlightElementBySelector(selector);
|
|
5181
|
-
}
|
|
5182
|
-
/**
|
|
5183
|
-
* 处理高亮元素请求
|
|
5184
|
-
*/
|
|
5185
|
-
handleHoverElementRequested(payload) {
|
|
5186
|
-
if (!this.elementSelector || !payload?.selector) return;
|
|
5187
|
-
this.elementSelector.highlightElementBySelector(payload.selector);
|
|
5188
|
-
}
|
|
5189
|
-
/**
|
|
5190
|
-
* 处理取消高亮元素请求
|
|
5191
|
-
*/
|
|
5192
|
-
handleUnhoverElementRequested(payload) {
|
|
5193
|
-
if (!this.elementSelector || !payload?.selector) return;
|
|
5194
|
-
this.elementSelector.unhighlightElementBySelector(payload.selector);
|
|
5195
|
-
}
|
|
5196
|
-
/**
|
|
5197
|
-
* 处理设置元素内容
|
|
5198
|
-
*/
|
|
5199
|
-
handleSetElementContent(payload) {
|
|
5200
|
-
if (!payload?.selector || !payload?.content) return;
|
|
5201
|
-
const elements = document.querySelectorAll(payload.selector);
|
|
5202
|
-
elements.forEach((element) => {
|
|
5203
|
-
if (element instanceof HTMLElement) {
|
|
5204
|
-
element.innerHTML = payload.content;
|
|
5205
|
-
}
|
|
5206
|
-
});
|
|
5207
|
-
this.sendMessage({
|
|
5208
|
-
type: "ELEMENT_EVENT",
|
|
5209
|
-
payload: {
|
|
5210
|
-
type: "content_updated",
|
|
5211
|
-
selector: payload.selector,
|
|
5212
|
-
content: payload.content,
|
|
5213
|
-
elementsUpdated: elements.length
|
|
5214
|
-
},
|
|
5215
|
-
timestamp: Date.now()
|
|
5216
|
-
});
|
|
5217
|
-
}
|
|
5218
|
-
/**
|
|
5219
|
-
* 处理设置元素属性
|
|
5220
|
-
*/
|
|
5221
|
-
handleSetElementAttrs(payload) {
|
|
5222
|
-
if (!payload?.selector || !payload?.attrs) return;
|
|
5223
|
-
const elements = document.querySelectorAll(payload.selector);
|
|
5224
|
-
elements.forEach((element) => {
|
|
5225
|
-
Object.entries(payload.attrs).forEach(([key, value]) => {
|
|
5226
|
-
element.setAttribute(key, String(value));
|
|
5227
|
-
});
|
|
5228
|
-
});
|
|
5229
|
-
this.sendMessage({
|
|
5230
|
-
type: "ELEMENT_EVENT",
|
|
5231
|
-
payload: {
|
|
5232
|
-
type: "attrs_updated",
|
|
5233
|
-
selector: payload.selector,
|
|
5234
|
-
attrs: payload.attrs,
|
|
5235
|
-
elementsUpdated: elements.length
|
|
5236
|
-
},
|
|
5237
|
-
timestamp: Date.now()
|
|
5238
|
-
});
|
|
5239
|
-
}
|
|
5240
|
-
/**
|
|
5241
|
-
* 处理复制元素请求
|
|
5242
|
-
*/
|
|
5243
|
-
handleDuplicateElementRequested(payload) {
|
|
5244
|
-
if (!payload?.selector) return;
|
|
5245
|
-
const element = document.querySelector(payload.selector);
|
|
5246
|
-
if (element && element.parentElement) {
|
|
5247
|
-
const clone = element.cloneNode(true);
|
|
5248
|
-
clone.setAttribute("data-duplicated", "true");
|
|
5249
|
-
element.parentElement.appendChild(clone);
|
|
5250
|
-
this.sendMessage({
|
|
5251
|
-
type: "ELEMENT_EVENT",
|
|
5252
|
-
payload: {
|
|
5253
|
-
type: "duplicated",
|
|
5254
|
-
originalSelector: payload.selector,
|
|
5255
|
-
duplicatedElement: this.getElementInfo(clone)
|
|
5256
|
-
},
|
|
5257
|
-
timestamp: Date.now()
|
|
5258
|
-
});
|
|
5259
|
-
}
|
|
5260
|
-
}
|
|
5261
|
-
/**
|
|
5262
|
-
* 处理编辑文本请求
|
|
5263
|
-
*/
|
|
5264
|
-
handleEditTextRequested(payload) {
|
|
5265
|
-
if (!payload?.selector) return;
|
|
5266
|
-
const element = document.querySelector(payload.selector);
|
|
5267
|
-
if (element instanceof HTMLElement) {
|
|
5268
|
-
element.setAttribute("contenteditable", "true");
|
|
5269
|
-
element.focus();
|
|
5270
|
-
const handleInput = () => {
|
|
5271
|
-
this.sendMessage({
|
|
5272
|
-
type: "ELEMENT_EVENT",
|
|
5273
|
-
payload: {
|
|
5274
|
-
type: "text_updated",
|
|
5275
|
-
selector: payload.selector,
|
|
5276
|
-
content: element.innerText
|
|
5277
|
-
},
|
|
5278
|
-
timestamp: Date.now()
|
|
5279
|
-
});
|
|
5280
|
-
};
|
|
5281
|
-
const handleBlur = () => {
|
|
5282
|
-
element.removeAttribute("contenteditable");
|
|
5283
|
-
element.removeEventListener("input", handleInput);
|
|
5284
|
-
element.removeEventListener("blur", handleBlur);
|
|
5285
|
-
this.sendMessage({
|
|
5286
|
-
type: "ELEMENT_EVENT",
|
|
5287
|
-
payload: {
|
|
5288
|
-
type: "edit_completed",
|
|
5289
|
-
selector: payload.selector,
|
|
5290
|
-
finalContent: element.innerText
|
|
5291
|
-
},
|
|
5292
|
-
timestamp: Date.now()
|
|
5293
|
-
});
|
|
5294
|
-
};
|
|
5295
|
-
element.addEventListener("input", handleInput);
|
|
5296
|
-
element.addEventListener("blur", handleBlur);
|
|
5297
|
-
}
|
|
5298
|
-
}
|
|
5299
|
-
/**
|
|
5300
|
-
* 处理更新选中元素
|
|
5301
|
-
*/
|
|
5302
|
-
handleUpdateSelectedElements(payload) {
|
|
5303
|
-
if (!this.elementSelector || !Array.isArray(payload)) return;
|
|
5304
|
-
this.elementSelector.updateSelectedElements(payload);
|
|
5305
|
-
this.sendMessage({
|
|
5306
|
-
type: "ELEMENT_EVENT",
|
|
5307
|
-
payload: {
|
|
5308
|
-
type: "selected_elements_updated",
|
|
5309
|
-
selectedElements: payload,
|
|
5310
|
-
count: payload.length
|
|
5311
|
-
},
|
|
5312
|
-
timestamp: Date.now()
|
|
5313
|
-
});
|
|
5314
|
-
}
|
|
5315
|
-
/** ----------------- 组件树相关消息处理 ----------------- */
|
|
5316
|
-
/**
|
|
5317
|
-
* 处理请求组件树
|
|
5318
|
-
*/
|
|
5319
|
-
handleRequestComponentTree() {
|
|
5320
|
-
if (!this.componentTreeGenerator) return;
|
|
5321
|
-
try {
|
|
5322
|
-
const rootElement = document.querySelector("#root") || document.body;
|
|
5323
|
-
const componentTree = this.componentTreeGenerator.generateComponentTree(rootElement);
|
|
5324
|
-
this.sendMessage({
|
|
5325
|
-
type: "COMPONENT_EVENT",
|
|
5326
|
-
payload: {
|
|
5327
|
-
type: "tree_response",
|
|
5328
|
-
...componentTree
|
|
5329
|
-
},
|
|
5330
|
-
timestamp: Date.now()
|
|
5331
|
-
});
|
|
5332
|
-
} catch (error) {
|
|
5333
|
-
const originalConsole = getOriginalConsole2();
|
|
5334
|
-
originalConsole.error("[MessageBridge] \u751F\u6210\u7EC4\u4EF6\u6811\u5931\u8D25:", error);
|
|
5335
|
-
this.sendMessage({
|
|
5336
|
-
type: "COMPONENT_EVENT",
|
|
5337
|
-
payload: {
|
|
5338
|
-
type: "tree_error",
|
|
5339
|
-
error: error instanceof Error ? error.message : String(error)
|
|
5340
|
-
},
|
|
5341
|
-
timestamp: Date.now()
|
|
5342
|
-
});
|
|
5343
|
-
}
|
|
5344
|
-
}
|
|
5345
|
-
/**
|
|
5346
|
-
* 处理获取父元素
|
|
4377
|
+
* 处理获取父元素
|
|
5347
4378
|
*/
|
|
5348
4379
|
handleGetParentElement(payload) {
|
|
5349
4380
|
if (!payload?.selector) return;
|
|
@@ -5435,11 +4466,9 @@ var MessageBridge = class {
|
|
|
5435
4466
|
if (dataTestId) return `[data-testid="${dataTestId}"]`;
|
|
5436
4467
|
const dataHowoneId = element.getAttribute("data-howone-id");
|
|
5437
4468
|
if (dataHowoneId) return `[data-howone-id="${dataHowoneId}"]`;
|
|
5438
|
-
|
|
5439
|
-
|
|
5440
|
-
|
|
5441
|
-
return `.${classes[0]}`;
|
|
5442
|
-
}
|
|
4469
|
+
const classes = getElementClasses(element);
|
|
4470
|
+
if (classes.length > 0) {
|
|
4471
|
+
return `.${classes[0]}`;
|
|
5443
4472
|
}
|
|
5444
4473
|
return element.tagName.toLowerCase();
|
|
5445
4474
|
}
|
|
@@ -5467,106 +4496,6 @@ var MessageBridge = class {
|
|
|
5467
4496
|
timestamp: Date.now()
|
|
5468
4497
|
});
|
|
5469
4498
|
}
|
|
5470
|
-
/** ----------------- 新增的消息处理方法 ----------------- */
|
|
5471
|
-
/**
|
|
5472
|
-
* 处理获取鼠标位置的元素
|
|
5473
|
-
*/
|
|
5474
|
-
handleGetElementAtPoint(payload) {
|
|
5475
|
-
if (!this.elementSelector) return;
|
|
5476
|
-
const element = this.elementSelector.getElementAtPoint(payload?.x, payload?.y);
|
|
5477
|
-
this.sendMessage({
|
|
5478
|
-
type: "ELEMENT_EVENT",
|
|
5479
|
-
payload: {
|
|
5480
|
-
type: "at_point_response",
|
|
5481
|
-
element: element ? this.getElementInfo(element) : null,
|
|
5482
|
-
coordinates: { x: payload?.x, y: payload?.y }
|
|
5483
|
-
},
|
|
5484
|
-
timestamp: Date.now()
|
|
5485
|
-
});
|
|
5486
|
-
}
|
|
5487
|
-
/**
|
|
5488
|
-
* 处理根据位置查找元素
|
|
5489
|
-
*/
|
|
5490
|
-
handleFindElementsByLocation(payload) {
|
|
5491
|
-
if (!this.elementSelector || !payload?.filePath || !payload?.lineNumber) return;
|
|
5492
|
-
const elements = this.elementSelector.findElementsByLocation(payload.filePath, payload.lineNumber);
|
|
5493
|
-
this.sendMessage({
|
|
5494
|
-
type: "ELEMENT_EVENT",
|
|
5495
|
-
payload: {
|
|
5496
|
-
type: "elements_by_location_response",
|
|
5497
|
-
elements: elements.map((el) => this.getElementInfo(el)),
|
|
5498
|
-
location: {
|
|
5499
|
-
filePath: payload.filePath,
|
|
5500
|
-
lineNumber: payload.lineNumber
|
|
5501
|
-
}
|
|
5502
|
-
},
|
|
5503
|
-
timestamp: Date.now()
|
|
5504
|
-
});
|
|
5505
|
-
}
|
|
5506
|
-
/**
|
|
5507
|
-
* 处理设置元素属性(新版本)
|
|
5508
|
-
*/
|
|
5509
|
-
handleSetElementAttributes(payload) {
|
|
5510
|
-
if (!this.elementSelector || !payload?.selector || !payload?.attributes) return;
|
|
5511
|
-
const success = this.elementSelector.setElementAttributes(payload.selector, payload.attributes);
|
|
5512
|
-
this.sendMessage({
|
|
5513
|
-
type: "ELEMENT_EVENT",
|
|
5514
|
-
payload: {
|
|
5515
|
-
type: "attributes_set_response",
|
|
5516
|
-
success,
|
|
5517
|
-
selector: payload.selector,
|
|
5518
|
-
attributes: payload.attributes
|
|
5519
|
-
},
|
|
5520
|
-
timestamp: Date.now()
|
|
5521
|
-
});
|
|
5522
|
-
}
|
|
5523
|
-
/**
|
|
5524
|
-
* 处理启用文本编辑
|
|
5525
|
-
*/
|
|
5526
|
-
handleEnableTextEditing(payload) {
|
|
5527
|
-
if (!this.elementSelector || !payload?.selector) return;
|
|
5528
|
-
const success = this.elementSelector.enableTextEditing(payload.selector);
|
|
5529
|
-
this.sendMessage({
|
|
5530
|
-
type: "ELEMENT_EVENT",
|
|
5531
|
-
payload: {
|
|
5532
|
-
type: "text_editing_enabled_response",
|
|
5533
|
-
success,
|
|
5534
|
-
selector: payload.selector
|
|
5535
|
-
},
|
|
5536
|
-
timestamp: Date.now()
|
|
5537
|
-
});
|
|
5538
|
-
}
|
|
5539
|
-
/**
|
|
5540
|
-
* 处理通过选择器悬停元素
|
|
5541
|
-
*/
|
|
5542
|
-
handleHoverElementBySelector(payload) {
|
|
5543
|
-
if (!this.elementSelector || !payload?.selector) return;
|
|
5544
|
-
const success = this.elementSelector.hoverElementBySelector(payload.selector);
|
|
5545
|
-
this.sendMessage({
|
|
5546
|
-
type: "ELEMENT_EVENT",
|
|
5547
|
-
payload: {
|
|
5548
|
-
type: "hovered_by_selector_response",
|
|
5549
|
-
success,
|
|
5550
|
-
selector: payload.selector
|
|
5551
|
-
},
|
|
5552
|
-
timestamp: Date.now()
|
|
5553
|
-
});
|
|
5554
|
-
}
|
|
5555
|
-
/**
|
|
5556
|
-
* 处理取消悬停元素
|
|
5557
|
-
*/
|
|
5558
|
-
handleUnhoverElement() {
|
|
5559
|
-
if (!this.elementSelector) return;
|
|
5560
|
-
this.elementSelector.unhoverElement();
|
|
5561
|
-
this.sendMessage({
|
|
5562
|
-
type: "ELEMENT_EVENT",
|
|
5563
|
-
payload: {
|
|
5564
|
-
type: "unhovered_response",
|
|
5565
|
-
success: true
|
|
5566
|
-
},
|
|
5567
|
-
timestamp: Date.now()
|
|
5568
|
-
});
|
|
5569
|
-
}
|
|
5570
4499
|
/** ----------------- 统一消息发送管理方法 ----------------- */
|
|
5571
4500
|
/**
|
|
5572
4501
|
* 获取统一的消息发送器实例
|
|
@@ -5600,7 +4529,6 @@ var MessageBridge = class {
|
|
|
5600
4529
|
window.removeEventListener("message", this.messageListener);
|
|
5601
4530
|
this.messageListener = void 0;
|
|
5602
4531
|
}
|
|
5603
|
-
console.log("[MessageBridge] \u6D88\u606F\u6865\u63A5\u5668\u5DF2\u9500\u6BC1");
|
|
5604
4532
|
}
|
|
5605
4533
|
};
|
|
5606
4534
|
|
|
@@ -5628,7 +4556,6 @@ var ErrorHandler = class {
|
|
|
5628
4556
|
enableInteractionTracking: true
|
|
5629
4557
|
};
|
|
5630
4558
|
this.config = { ...this.config, ...options };
|
|
5631
|
-
console.log("[ErrorHandler] \u5F00\u59CB\u521D\u59CB\u5316\u7EDF\u4E00\u9519\u8BEF\u5904\u7406\u5668...");
|
|
5632
4559
|
this.messageSender = createDefaultMessageSender({
|
|
5633
4560
|
addTimestamp: true,
|
|
5634
4561
|
enableDebugLog: false
|
|
@@ -5636,16 +4563,13 @@ var ErrorHandler = class {
|
|
|
5636
4563
|
const sendMessage = this.messageSender.createSendFunction();
|
|
5637
4564
|
this.errorTracking = new ErrorTracking(sendMessage);
|
|
5638
4565
|
this.interactionTracking = new InteractionTracking(sendMessage);
|
|
5639
|
-
this.elementSelector = new ElementSelector2(sendMessage);
|
|
5640
4566
|
this.messageBridge = new MessageBridge();
|
|
5641
4567
|
this.viewDetector = new ViewDetector();
|
|
5642
4568
|
this.hardRefreshManager = new HardRefreshManager(GLOBAL_CONFIG.ALLOWED_ORIGINS);
|
|
5643
4569
|
this.componentTreeGenerator = new ComponentTreeGenerator();
|
|
5644
4570
|
if (this.config.enableViteHMR && ViteHMRDetector.isViteEnvironment()) {
|
|
5645
4571
|
this.viteHMRDetector = new ViteHMRDetector(sendMessage);
|
|
5646
|
-
console.log("[ErrorHandler] Vite HMR \u68C0\u6D4B\u5668\u5DF2\u521D\u59CB\u5316");
|
|
5647
4572
|
}
|
|
5648
|
-
console.log("[ErrorHandler] \u6A21\u5757\u521D\u59CB\u5316\u5B8C\u6210");
|
|
5649
4573
|
}
|
|
5650
4574
|
/** ----------------- 主要初始化方法 ----------------- */
|
|
5651
4575
|
/**
|
|
@@ -5657,12 +4581,10 @@ var ErrorHandler = class {
|
|
|
5657
4581
|
return;
|
|
5658
4582
|
}
|
|
5659
4583
|
try {
|
|
5660
|
-
console.log("[ErrorHandler] \u5F00\u59CB\u521D\u59CB\u5316\u5404\u4E2A\u6A21\u5757...");
|
|
5661
4584
|
this.initializeCore();
|
|
5662
4585
|
this.setupModuleIntegration();
|
|
5663
4586
|
this.enableFeatures();
|
|
5664
4587
|
this.initialized = true;
|
|
5665
|
-
console.log("[ErrorHandler] \u521D\u59CB\u5316\u5B8C\u6210");
|
|
5666
4588
|
} catch (error) {
|
|
5667
4589
|
console.error("[ErrorHandler] \u521D\u59CB\u5316\u5931\u8D25:", error);
|
|
5668
4590
|
throw error;
|
|
@@ -5675,7 +4597,6 @@ var ErrorHandler = class {
|
|
|
5675
4597
|
this.initializeGlobalState();
|
|
5676
4598
|
this.setupDebugEndpoint();
|
|
5677
4599
|
this.errorTracking.initialize();
|
|
5678
|
-
console.log("[ErrorHandler] \u6838\u5FC3\u529F\u80FD\u521D\u59CB\u5316\u5B8C\u6210");
|
|
5679
4600
|
}
|
|
5680
4601
|
/**
|
|
5681
4602
|
* 初始化全局状态
|
|
@@ -5687,7 +4608,6 @@ var ErrorHandler = class {
|
|
|
5687
4608
|
if (!window.__AUTO_ENGINEER_INTERACTION_TRAIL__) {
|
|
5688
4609
|
window.__AUTO_ENGINEER_INTERACTION_TRAIL__ = [];
|
|
5689
4610
|
}
|
|
5690
|
-
console.log("[ErrorHandler] \u5168\u5C40\u72B6\u6001\u521D\u59CB\u5316\u5B8C\u6210");
|
|
5691
4611
|
}
|
|
5692
4612
|
/**
|
|
5693
4613
|
* 设置调试端点
|
|
@@ -5707,28 +4627,22 @@ var ErrorHandler = class {
|
|
|
5707
4627
|
* 设置模块间的协作
|
|
5708
4628
|
*/
|
|
5709
4629
|
setupModuleIntegration() {
|
|
5710
|
-
this.messageBridge.setElementSelector(this.elementSelector);
|
|
5711
4630
|
this.messageBridge.setComponentTreeGenerator(this.componentTreeGenerator);
|
|
5712
4631
|
this.errorTracking.setViewDetector(this.viewDetector);
|
|
5713
4632
|
this.errorTracking.setInteractionTracking(this.interactionTracking);
|
|
5714
|
-
console.log("[ErrorHandler] \u6A21\u5757\u96C6\u6210\u8BBE\u7F6E\u5B8C\u6210");
|
|
5715
4633
|
}
|
|
5716
4634
|
/**
|
|
5717
4635
|
* 启用功能模块
|
|
5718
4636
|
*/
|
|
5719
4637
|
enableFeatures() {
|
|
5720
|
-
console.log("[ErrorHandler] \u542F\u7528\u529F\u80FD\u6A21\u5757...");
|
|
5721
4638
|
if (this.config.enableInteractionTracking) {
|
|
5722
4639
|
this.interactionTracking.startTracking();
|
|
5723
|
-
console.log("[ErrorHandler] \u4EA4\u4E92\u8FFD\u8E2A\u5DF2\u542F\u7528");
|
|
5724
4640
|
}
|
|
5725
4641
|
if (this.viteHMRDetector) {
|
|
5726
4642
|
this.viteHMRDetector.initialize();
|
|
5727
|
-
console.log("[ErrorHandler] Vite HMR \u68C0\u6D4B\u5668\u5DF2\u542F\u7528");
|
|
5728
4643
|
}
|
|
5729
4644
|
this.handleHardRefreshLogic();
|
|
5730
4645
|
this.setupViewDetection();
|
|
5731
|
-
console.log("[ErrorHandler] \u529F\u80FD\u6A21\u5757\u542F\u7528\u5B8C\u6210");
|
|
5732
4646
|
}
|
|
5733
4647
|
/**
|
|
5734
4648
|
* 处理硬刷新逻辑
|
|
@@ -5737,7 +4651,6 @@ var ErrorHandler = class {
|
|
|
5737
4651
|
HardRefreshManager.cleanupRefreshParams();
|
|
5738
4652
|
const refreshStats = HardRefreshManager.getRefreshStats();
|
|
5739
4653
|
if (refreshStats.isHardRefresh) {
|
|
5740
|
-
console.log("[ErrorHandler] \u68C0\u6D4B\u5230\u786C\u5237\u65B0:", refreshStats);
|
|
5741
4654
|
this.messageSender.send({
|
|
5742
4655
|
type: "SYSTEM_EVENT",
|
|
5743
4656
|
payload: {
|
|
@@ -5758,7 +4671,6 @@ var ErrorHandler = class {
|
|
|
5758
4671
|
const currentView = this.viewDetector.getCurrentViewInfo();
|
|
5759
4672
|
if (currentView.title !== lastViewTitle) {
|
|
5760
4673
|
lastViewTitle = currentView.title;
|
|
5761
|
-
console.log("[ErrorHandler] \u89C6\u56FE\u53D8\u5316:", currentView);
|
|
5762
4674
|
}
|
|
5763
4675
|
};
|
|
5764
4676
|
setInterval(checkViewChange, 1e3);
|
|
@@ -5791,12 +4703,6 @@ var ErrorHandler = class {
|
|
|
5791
4703
|
getErrorStats() {
|
|
5792
4704
|
return this.errorTracking.getErrorStats();
|
|
5793
4705
|
}
|
|
5794
|
-
/**
|
|
5795
|
-
* 获取选择器状态
|
|
5796
|
-
*/
|
|
5797
|
-
getSelectorState() {
|
|
5798
|
-
return this.elementSelector.getSelectorState();
|
|
5799
|
-
}
|
|
5800
4706
|
/**
|
|
5801
4707
|
* 获取交互历史
|
|
5802
4708
|
*/
|
|
@@ -5830,30 +4736,11 @@ var ErrorHandler = class {
|
|
|
5830
4736
|
isViteEnvironment() {
|
|
5831
4737
|
return ViteHMRDetector.isViteEnvironment();
|
|
5832
4738
|
}
|
|
5833
|
-
/**
|
|
5834
|
-
* 启用元素选择器
|
|
5835
|
-
*/
|
|
5836
|
-
enableElementSelector() {
|
|
5837
|
-
this.elementSelector.enableSelector();
|
|
5838
|
-
}
|
|
5839
|
-
/**
|
|
5840
|
-
* 禁用元素选择器
|
|
5841
|
-
*/
|
|
5842
|
-
disableElementSelector() {
|
|
5843
|
-
this.elementSelector.disableSelector();
|
|
5844
|
-
}
|
|
5845
|
-
/**
|
|
5846
|
-
* 切换元素选择器状态
|
|
5847
|
-
*/
|
|
5848
|
-
toggleElementSelector() {
|
|
5849
|
-
this.elementSelector.toggleSelector();
|
|
5850
|
-
}
|
|
5851
4739
|
/**
|
|
5852
4740
|
* 更新配置
|
|
5853
4741
|
*/
|
|
5854
4742
|
updateConfig(newConfig) {
|
|
5855
4743
|
this.config = { ...this.config, ...newConfig };
|
|
5856
|
-
console.log("[ErrorHandler] \u914D\u7F6E\u5DF2\u66F4\u65B0:", this.config);
|
|
5857
4744
|
}
|
|
5858
4745
|
/**
|
|
5859
4746
|
* 销毁错误处理器
|
|
@@ -5862,7 +4749,6 @@ var ErrorHandler = class {
|
|
|
5862
4749
|
try {
|
|
5863
4750
|
this.errorTracking.destroy();
|
|
5864
4751
|
this.interactionTracking.destroy();
|
|
5865
|
-
this.elementSelector.destroy();
|
|
5866
4752
|
this.messageBridge.destroy();
|
|
5867
4753
|
if (this.viteHMRDetector) {
|
|
5868
4754
|
this.viteHMRDetector.destroy();
|
|
@@ -5872,7 +4758,6 @@ var ErrorHandler = class {
|
|
|
5872
4758
|
this.viewDetector.clearCache();
|
|
5873
4759
|
}
|
|
5874
4760
|
this.initialized = false;
|
|
5875
|
-
console.log("[ErrorHandler] \u5DF2\u9500\u6BC1");
|
|
5876
4761
|
} catch (error) {
|
|
5877
4762
|
const originalConsole = getOriginalConsole3();
|
|
5878
4763
|
originalConsole.error("[ErrorHandler] \u9500\u6BC1\u65F6\u53D1\u751F\u9519\u8BEF:", error);
|
|
@@ -5894,7 +4779,6 @@ var ErrorHandler = class {
|
|
|
5894
4779
|
errorStats: this.getErrorStats(),
|
|
5895
4780
|
currentView: this.getCurrentView(),
|
|
5896
4781
|
interactionHistory: this.getInteractionHistory(),
|
|
5897
|
-
selectorState: this.getSelectorState(),
|
|
5898
4782
|
isViteEnvironment: this.isViteEnvironment(),
|
|
5899
4783
|
timestamp: Date.now()
|
|
5900
4784
|
};
|
|
@@ -5918,7 +4802,6 @@ var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
|
5918
4802
|
var globalErrorHandler = null;
|
|
5919
4803
|
var initializeErrorHandler = () => {
|
|
5920
4804
|
if (!globalErrorHandler) {
|
|
5921
|
-
console.log("[HowOneProvider] \u5728\u6A21\u5757\u9876\u5C42\u521D\u59CB\u5316\u9519\u8BEF\u5904\u7406\u5668...");
|
|
5922
4805
|
globalErrorHandler = new ErrorHandler({
|
|
5923
4806
|
enableViteHMR: true,
|
|
5924
4807
|
enableElementSelector: true,
|
|
@@ -5926,7 +4809,6 @@ var initializeErrorHandler = () => {
|
|
|
5926
4809
|
});
|
|
5927
4810
|
globalErrorHandler.init();
|
|
5928
4811
|
window.__ERROR_HANDLER__ = globalErrorHandler;
|
|
5929
|
-
console.log("[HowOneProvider] \u9519\u8BEF\u5904\u7406\u5668\u5DF2\u5728\u6A21\u5757\u9876\u5C42\u521D\u59CB\u5316\u5B8C\u6210");
|
|
5930
4812
|
}
|
|
5931
4813
|
return globalErrorHandler;
|
|
5932
4814
|
};
|
|
@@ -5954,7 +4836,6 @@ var HowOneProvider = ({
|
|
|
5954
4836
|
urlToken = hashParams.get("access_token") || hashParams.get("token");
|
|
5955
4837
|
}
|
|
5956
4838
|
if (urlToken) {
|
|
5957
|
-
console.log("[HowOneProvider] Token captured from URL, storing to localStorage...");
|
|
5958
4839
|
setToken(urlToken);
|
|
5959
4840
|
setTokenState(urlToken);
|
|
5960
4841
|
setUser(parseUserFromToken(urlToken));
|
|
@@ -5964,7 +4845,6 @@ var HowOneProvider = ({
|
|
|
5964
4845
|
const newSearch = params.toString();
|
|
5965
4846
|
const newUrl = window.location.pathname + (newSearch ? "?" + newSearch : "");
|
|
5966
4847
|
window.history.replaceState({}, "", newUrl);
|
|
5967
|
-
console.log("[HowOneProvider] Token stored successfully, URL cleaned");
|
|
5968
4848
|
}
|
|
5969
4849
|
} catch (e) {
|
|
5970
4850
|
console.error("[HowOneProvider] Failed to capture token from URL:", e);
|
|
@@ -5979,7 +4859,6 @@ var HowOneProvider = ({
|
|
|
5979
4859
|
if (redirectOnUnauthenticated && !token && !user) {
|
|
5980
4860
|
const currentUrl = new URL(window.location.href);
|
|
5981
4861
|
if (!currentUrl.pathname.includes("/auth")) {
|
|
5982
|
-
console.log("[HowOneProvider] No token found, redirecting to auth page...");
|
|
5983
4862
|
try {
|
|
5984
4863
|
const authUrlObj = new URL(authUrl);
|
|
5985
4864
|
const redirectUri = window.location.href;
|
|
@@ -5987,7 +4866,6 @@ var HowOneProvider = ({
|
|
|
5987
4866
|
if (projectId) {
|
|
5988
4867
|
authUrlObj.searchParams.set("project_id", projectId);
|
|
5989
4868
|
}
|
|
5990
|
-
console.log("[HowOneProvider] Redirecting to:", authUrlObj.toString());
|
|
5991
4869
|
window.location.href = authUrlObj.toString();
|
|
5992
4870
|
} catch (error) {
|
|
5993
4871
|
console.error("[HowOneProvider] Failed to build auth URL:", error);
|
|
@@ -7267,7 +6145,6 @@ var SimpleErrorHandler = class {
|
|
|
7267
6145
|
this.setupErrorListeners();
|
|
7268
6146
|
this.setupCompatibility();
|
|
7269
6147
|
this.initialized = true;
|
|
7270
|
-
console.log("[\u7B80\u5316\u9519\u8BEF\u5904\u7406] \u521D\u59CB\u5316\u5B8C\u6210");
|
|
7271
6148
|
}
|
|
7272
6149
|
/**
|
|
7273
6150
|
* 设置错误监听器
|