@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.mjs
CHANGED
|
@@ -697,17 +697,13 @@ var LoginForm = ({
|
|
|
697
697
|
const [codeSent, setCodeSent] = useState2(false);
|
|
698
698
|
const [loginError, setLoginError] = useState2(null);
|
|
699
699
|
const googleLogin = async () => {
|
|
700
|
-
console.log("Google login clicked");
|
|
701
700
|
};
|
|
702
701
|
const githubLogin = async () => {
|
|
703
|
-
console.log("GitHub login clicked");
|
|
704
702
|
};
|
|
705
703
|
const sendEmailCode = async (email2) => {
|
|
706
|
-
console.log("Send code to:", email2, "for app:", appName);
|
|
707
704
|
setCodeSent(true);
|
|
708
705
|
};
|
|
709
706
|
const loginWithEmail = async (email2, code2) => {
|
|
710
|
-
console.log("Login with email:", email2, "code:", code2);
|
|
711
707
|
if (onLoginSuccess) onLoginSuccess();
|
|
712
708
|
};
|
|
713
709
|
const clearError = () => {
|
|
@@ -1154,11 +1150,9 @@ var ElementSelectorProvider = ({ children }) => {
|
|
|
1154
1150
|
type: "ELEMENT_SELECTION_CANCELLED"
|
|
1155
1151
|
}, "*");
|
|
1156
1152
|
}
|
|
1157
|
-
console.log("\u{1F6AB} \u5143\u7D20\u9009\u62E9\u5DF2\u53D6\u6D88 (ESC)");
|
|
1158
1153
|
}, []);
|
|
1159
1154
|
const handleSelect = useCallback3((data) => {
|
|
1160
1155
|
sendElementSelectionToParent(data);
|
|
1161
|
-
console.log("\u{1F3AF} \u5143\u7D20\u5DF2\u9009\u4E2D:", data.element.tagName, data.sourceLocation?.file);
|
|
1162
1156
|
}, []);
|
|
1163
1157
|
useEffect5(() => {
|
|
1164
1158
|
const handleStartSelection = () => {
|
|
@@ -1513,7 +1507,6 @@ var ViteHMRDetector = class {
|
|
|
1513
1507
|
if (this.isInitialized) return;
|
|
1514
1508
|
this.setupViteErrorDetection();
|
|
1515
1509
|
this.isInitialized = true;
|
|
1516
|
-
console.log("[ViteHMRDetector] Vite HMR \u9519\u8BEF\u68C0\u6D4B\u5668\u521D\u59CB\u5316\u5B8C\u6210");
|
|
1517
1510
|
}
|
|
1518
1511
|
/**
|
|
1519
1512
|
* 销毁检测器
|
|
@@ -1564,10 +1557,8 @@ var ViteHMRDetector = class {
|
|
|
1564
1557
|
setTimeout(() => this.checkForCompileErrors(), 500);
|
|
1565
1558
|
});
|
|
1566
1559
|
hot.on("vite:beforeUpdate", () => {
|
|
1567
|
-
console.log("[ViteHMRDetector] HMR \u66F4\u65B0\u5F00\u59CB");
|
|
1568
1560
|
});
|
|
1569
1561
|
hot.on("vite:afterUpdate", () => {
|
|
1570
|
-
console.log("[ViteHMRDetector] HMR \u66F4\u65B0\u5B8C\u6210");
|
|
1571
1562
|
});
|
|
1572
1563
|
}
|
|
1573
1564
|
window.addEventListener("error", (event) => {
|
|
@@ -1605,7 +1596,6 @@ var ViteHMRDetector = class {
|
|
|
1605
1596
|
payload: errorPayload,
|
|
1606
1597
|
timestamp: Date.now()
|
|
1607
1598
|
});
|
|
1608
|
-
console.log("[ViteHMRDetector] Vite \u9519\u8BEF\u5DF2\u68C0\u6D4B\u5E76\u62A5\u544A:", errorPayload);
|
|
1609
1599
|
} catch (err) {
|
|
1610
1600
|
this.handleFallbackError(errorOverlay, err);
|
|
1611
1601
|
}
|
|
@@ -1878,20 +1868,16 @@ var HardRefreshManager = class {
|
|
|
1878
1868
|
clearedStorage: []
|
|
1879
1869
|
};
|
|
1880
1870
|
try {
|
|
1881
|
-
console.log("[HardRefreshManager] \u5F00\u59CB\u6267\u884C\u786C\u5237\u65B0...");
|
|
1882
1871
|
if (defaultOptions.clearCaches) {
|
|
1883
1872
|
const clearedCaches = await this.clearAllCaches();
|
|
1884
1873
|
result.clearedCaches = clearedCaches;
|
|
1885
|
-
console.log(`[HardRefreshManager] \u5DF2\u6E05\u9664 ${clearedCaches.length} \u4E2A\u7F13\u5B58`);
|
|
1886
1874
|
}
|
|
1887
1875
|
if (defaultOptions.unregisterServiceWorkers) {
|
|
1888
1876
|
const unregisteredCount = await this.unregisterServiceWorkers();
|
|
1889
1877
|
result.unregisteredWorkers = unregisteredCount;
|
|
1890
|
-
console.log(`[HardRefreshManager] \u5DF2\u6CE8\u9500 ${unregisteredCount} \u4E2A Service Worker`);
|
|
1891
1878
|
}
|
|
1892
1879
|
const clearedStorage = await this.clearStorage(defaultOptions);
|
|
1893
1880
|
result.clearedStorage = clearedStorage;
|
|
1894
|
-
console.log(`[HardRefreshManager] \u5DF2\u6E05\u9664\u5B58\u50A8: ${clearedStorage.join(", ")}`);
|
|
1895
1881
|
await this.forceReload(defaultOptions);
|
|
1896
1882
|
result.success = true;
|
|
1897
1883
|
return result;
|
|
@@ -2490,7 +2476,6 @@ var ComponentTreeGenerator = class {
|
|
|
2490
2476
|
maxTextLength: 100,
|
|
2491
2477
|
maxChildren: 50
|
|
2492
2478
|
};
|
|
2493
|
-
console.log("[ComponentTreeGenerator] \u7EC4\u4EF6\u6811\u751F\u6210\u5668\u521D\u59CB\u5316\u5B8C\u6210");
|
|
2494
2479
|
}
|
|
2495
2480
|
/** ----------------- 主要生成方法 ----------------- */
|
|
2496
2481
|
/**
|
|
@@ -2499,7 +2484,6 @@ var ComponentTreeGenerator = class {
|
|
|
2499
2484
|
generateComponentTree(rootElement) {
|
|
2500
2485
|
const startTime = Date.now();
|
|
2501
2486
|
const root = rootElement || document.body;
|
|
2502
|
-
console.log("[ComponentTreeGenerator] \u5F00\u59CB\u751F\u6210\u7EC4\u4EF6\u6811...");
|
|
2503
2487
|
const rootNode = this.generateNodeTree(root, 0);
|
|
2504
2488
|
const stats = this.calculateTreeStats(rootNode);
|
|
2505
2489
|
const componentTree = {
|
|
@@ -2520,7 +2504,6 @@ var ComponentTreeGenerator = class {
|
|
|
2520
2504
|
}
|
|
2521
2505
|
};
|
|
2522
2506
|
const generationTime = Date.now() - startTime;
|
|
2523
|
-
console.log(`[ComponentTreeGenerator] \u7EC4\u4EF6\u6811\u751F\u6210\u5B8C\u6210\uFF0C\u8017\u65F6 ${generationTime}ms\uFF0C\u8282\u70B9\u6570: ${stats.totalNodes}`);
|
|
2524
2507
|
return componentTree;
|
|
2525
2508
|
}
|
|
2526
2509
|
/**
|
|
@@ -2871,7 +2854,6 @@ var ComponentTreeGenerator = class {
|
|
|
2871
2854
|
*/
|
|
2872
2855
|
updateConfig(newConfig) {
|
|
2873
2856
|
this.config = { ...this.config, ...newConfig };
|
|
2874
|
-
console.log("[ComponentTreeGenerator] \u914D\u7F6E\u5DF2\u66F4\u65B0:", this.config);
|
|
2875
2857
|
}
|
|
2876
2858
|
/**
|
|
2877
2859
|
* 获取当前配置
|
|
@@ -2894,7 +2876,6 @@ var ComponentTreeGenerator = class {
|
|
|
2894
2876
|
* 销毁生成器
|
|
2895
2877
|
*/
|
|
2896
2878
|
destroy() {
|
|
2897
|
-
console.log("[ComponentTreeGenerator] \u7EC4\u4EF6\u6811\u751F\u6210\u5668\u5DF2\u9500\u6BC1");
|
|
2898
2879
|
}
|
|
2899
2880
|
};
|
|
2900
2881
|
|
|
@@ -3071,7 +3052,6 @@ var ErrorTracking = class {
|
|
|
3071
3052
|
this.viewDetector = null;
|
|
3072
3053
|
this.interactionTracking = null;
|
|
3073
3054
|
this.sendMessage = sendMessage;
|
|
3074
|
-
this.internalLog("log", "[ErrorTracking] \u9519\u8BEF\u8FFD\u8E2A\u6A21\u5757\u521D\u59CB\u5316\u5B8C\u6210");
|
|
3075
3055
|
}
|
|
3076
3056
|
/**
|
|
3077
3057
|
* 内部日志方法,避免被控制台拦截器捕获
|
|
@@ -3107,10 +3087,8 @@ var ErrorTracking = class {
|
|
|
3107
3087
|
this.setupConsoleInterception();
|
|
3108
3088
|
this.setupNetworkMonitoring();
|
|
3109
3089
|
this.initialized = true;
|
|
3110
|
-
this.internalLog("log", "[ErrorTracking] \u9519\u8BEF\u8FFD\u8E2A\u529F\u80FD\u5DF2\u542F\u7528");
|
|
3111
3090
|
setTimeout(() => {
|
|
3112
3091
|
this.fullyInitialized = true;
|
|
3113
|
-
this.internalLog("log", "[ErrorTracking] \u521D\u59CB\u5316\u5B8C\u6210\uFF0C\u63A7\u5236\u53F0\u62E6\u622A\u5DF2\u9ED8\u8BA4\u542F\u7528");
|
|
3114
3092
|
}, 1e3);
|
|
3115
3093
|
}
|
|
3116
3094
|
/**
|
|
@@ -3135,7 +3113,6 @@ var ErrorTracking = class {
|
|
|
3135
3113
|
source: "unhandledrejection"
|
|
3136
3114
|
});
|
|
3137
3115
|
});
|
|
3138
|
-
this.internalLog("log", "[ErrorTracking] \u5168\u5C40\u9519\u8BEF\u76D1\u542C\u5668\u5DF2\u8BBE\u7F6E");
|
|
3139
3116
|
}
|
|
3140
3117
|
/**
|
|
3141
3118
|
* 设置控制台拦截
|
|
@@ -3159,7 +3136,6 @@ var ErrorTracking = class {
|
|
|
3159
3136
|
}
|
|
3160
3137
|
};
|
|
3161
3138
|
});
|
|
3162
|
-
this.internalLog("log", "[ErrorTracking] \u63A7\u5236\u53F0\u62E6\u622A\u5DF2\u8BBE\u7F6E");
|
|
3163
3139
|
}
|
|
3164
3140
|
/**
|
|
3165
3141
|
* 安全地将控制台输出转发到父窗口
|
|
@@ -3179,6 +3155,20 @@ var ErrorTracking = class {
|
|
|
3179
3155
|
const fileInfo = this.extractFileInfoFromStack(fullStack);
|
|
3180
3156
|
const serializedArgs = args.map((arg) => DeepSerializer.quickSerialize(arg));
|
|
3181
3157
|
const message = serializedArgs.map((arg) => typeof arg === "string" ? arg : JSON.stringify(arg, null, 2)).join(" ") + (stack ? "\n" + stack : "");
|
|
3158
|
+
const lowerMessage = message.toLowerCase();
|
|
3159
|
+
const isFromVite = (fileInfo.filename || "").toLowerCase().includes("vite") || lowerMessage.includes("@vite") || lowerMessage.includes("vite") || lowerMessage.includes("hmr");
|
|
3160
|
+
const ignoreVitePatterns = [
|
|
3161
|
+
/\[vite\]\s*hot updated/i,
|
|
3162
|
+
/\[vite\]\s*connected/i,
|
|
3163
|
+
/\[vite\]\s*connecting/i,
|
|
3164
|
+
/\bhot updated\b/i,
|
|
3165
|
+
/\bhmr\b.*\bupdated\b/i
|
|
3166
|
+
];
|
|
3167
|
+
if (isFromVite && ignoreVitePatterns.some((re) => re.test(lowerMessage))) {
|
|
3168
|
+
return;
|
|
3169
|
+
}
|
|
3170
|
+
const hasErrorKeywords = /\b(error|failed|overlay|compile|exception)\b/.test(lowerMessage);
|
|
3171
|
+
const isViteHMRNonError = isFromVite && !hasErrorKeywords;
|
|
3182
3172
|
if (method === "error") {
|
|
3183
3173
|
const globalError = {
|
|
3184
3174
|
id: `console-error-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
@@ -3195,9 +3185,11 @@ var ErrorTracking = class {
|
|
|
3195
3185
|
pagePath: window.location.pathname + window.location.search + window.location.hash,
|
|
3196
3186
|
interactionTrail: [...window.__AUTO_ENGINEER_INTERACTION_TRAIL__ || []]
|
|
3197
3187
|
};
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3188
|
+
if (!isViteHMRNonError) {
|
|
3189
|
+
window.__AUTO_ENGINEER_ERRORS__ = window.__AUTO_ENGINEER_ERRORS__ || [];
|
|
3190
|
+
window.__AUTO_ENGINEER_ERRORS__.push(globalError);
|
|
3191
|
+
this.manageArrayLength(window.__AUTO_ENGINEER_ERRORS__, ERROR_CONFIG.MAX_ERRORS);
|
|
3192
|
+
}
|
|
3201
3193
|
}
|
|
3202
3194
|
const consoleLevelMap = {
|
|
3203
3195
|
log: "info",
|
|
@@ -3209,7 +3201,7 @@ var ErrorTracking = class {
|
|
|
3209
3201
|
this.sendMessage({
|
|
3210
3202
|
type: "CONSOLE_EVENT",
|
|
3211
3203
|
payload: {
|
|
3212
|
-
type: consoleLevelMap[method] === "info" ? "info" : consoleLevelMap[method] === "warning" ? "warning" : "error",
|
|
3204
|
+
type: consoleLevelMap[method] === "info" ? "info" : consoleLevelMap[method] === "warning" ? "warning" : consoleLevelMap[method] === "debug" ? "debug" : "error",
|
|
3213
3205
|
message,
|
|
3214
3206
|
logged_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3215
3207
|
filename: fileInfo.filename,
|
|
@@ -3230,19 +3222,47 @@ var ErrorTracking = class {
|
|
|
3230
3222
|
* 设置网络监控
|
|
3231
3223
|
*/
|
|
3232
3224
|
setupNetworkMonitoring() {
|
|
3225
|
+
const self = this;
|
|
3233
3226
|
const originalFetch = window.fetch;
|
|
3234
3227
|
window.fetch = async (...args) => {
|
|
3235
3228
|
const startTime = Date.now();
|
|
3236
3229
|
try {
|
|
3237
3230
|
const response = await originalFetch(...args);
|
|
3238
|
-
|
|
3231
|
+
self.logNetworkRequest(args, response, Date.now() - startTime);
|
|
3239
3232
|
return response;
|
|
3240
3233
|
} catch (error) {
|
|
3241
|
-
|
|
3234
|
+
const duration = Date.now() - startTime;
|
|
3235
|
+
const message = error && (error.message || String(error));
|
|
3236
|
+
const match = typeof message === "string" ? message.match(/^HTTP\s+(\d+):\s*(.*)$/i) : null;
|
|
3237
|
+
if (match) {
|
|
3238
|
+
const status = Number(match[1]);
|
|
3239
|
+
const statusText = match[2] || "";
|
|
3240
|
+
const stack = new Error().stack;
|
|
3241
|
+
const fileInfo = self.extractFileInfoFromStack(stack);
|
|
3242
|
+
self.sendMessage({
|
|
3243
|
+
type: "NETWORK_EVENT",
|
|
3244
|
+
payload: {
|
|
3245
|
+
type: "request_error",
|
|
3246
|
+
url: args[0],
|
|
3247
|
+
method: args[1]?.method || "GET",
|
|
3248
|
+
status,
|
|
3249
|
+
statusText,
|
|
3250
|
+
filename: fileInfo.filename,
|
|
3251
|
+
lineno: fileInfo.lineno,
|
|
3252
|
+
colno: fileInfo.colno,
|
|
3253
|
+
duration,
|
|
3254
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3255
|
+
pageUrl: window.location.href,
|
|
3256
|
+
interactionTrail: self.getRecentInteractions()
|
|
3257
|
+
},
|
|
3258
|
+
timestamp: Date.now()
|
|
3259
|
+
});
|
|
3260
|
+
} else {
|
|
3261
|
+
self.logNetworkError(args, error, duration);
|
|
3262
|
+
}
|
|
3242
3263
|
throw error;
|
|
3243
3264
|
}
|
|
3244
3265
|
};
|
|
3245
|
-
this.internalLog("log", "[ErrorTracking] \u7F51\u7EDC\u76D1\u63A7\u5DF2\u8BBE\u7F6E");
|
|
3246
3266
|
}
|
|
3247
3267
|
/**
|
|
3248
3268
|
* 记录网络请求
|
|
@@ -3534,14 +3554,12 @@ var ErrorTracking = class {
|
|
|
3534
3554
|
*/
|
|
3535
3555
|
enableConsoleInterception() {
|
|
3536
3556
|
this.fullyInitialized = true;
|
|
3537
|
-
this.internalLog("log", "[ErrorTracking] \u624B\u52A8\u542F\u7528\u63A7\u5236\u53F0\u62E6\u622A");
|
|
3538
3557
|
}
|
|
3539
3558
|
/**
|
|
3540
3559
|
* 手动禁用控制台拦截
|
|
3541
3560
|
*/
|
|
3542
3561
|
disableConsoleInterception() {
|
|
3543
3562
|
this.fullyInitialized = false;
|
|
3544
|
-
this.internalLog("log", "[ErrorTracking] \u624B\u52A8\u7981\u7528\u63A7\u5236\u53F0\u62E6\u622A");
|
|
3545
3563
|
}
|
|
3546
3564
|
/**
|
|
3547
3565
|
* 销毁错误追踪
|
|
@@ -3553,10 +3571,32 @@ var ErrorTracking = class {
|
|
|
3553
3571
|
}
|
|
3554
3572
|
});
|
|
3555
3573
|
this.initialized = false;
|
|
3556
|
-
this.internalLog("log", "[ErrorTracking] \u9519\u8BEF\u8FFD\u8E2A\u6A21\u5757\u5DF2\u9500\u6BC1");
|
|
3557
3574
|
}
|
|
3558
3575
|
};
|
|
3559
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
|
+
|
|
3560
3600
|
// src/utils/unified-error-handler/features/InteractionTracking.ts
|
|
3561
3601
|
var InteractionTracking = class {
|
|
3562
3602
|
constructor(sendMessage) {
|
|
@@ -3580,7 +3620,6 @@ var InteractionTracking = class {
|
|
|
3580
3620
|
this.debounceTimers = /* @__PURE__ */ new Map();
|
|
3581
3621
|
this.eventListeners = [];
|
|
3582
3622
|
this.sendMessage = sendMessage;
|
|
3583
|
-
console.log("[InteractionTracking] \u4EA4\u4E92\u8FFD\u8E2A\u6A21\u5757\u521D\u59CB\u5316\u5B8C\u6210");
|
|
3584
3623
|
}
|
|
3585
3624
|
/** ----------------- 主要控制方法 ----------------- */
|
|
3586
3625
|
/**
|
|
@@ -3596,7 +3635,6 @@ var InteractionTracking = class {
|
|
|
3596
3635
|
title: document.title,
|
|
3597
3636
|
timestamp: Date.now()
|
|
3598
3637
|
});
|
|
3599
|
-
console.log("[InteractionTracking] \u4EA4\u4E92\u8FFD\u8E2A\u5DF2\u5F00\u59CB");
|
|
3600
3638
|
}
|
|
3601
3639
|
/**
|
|
3602
3640
|
* 停止追踪
|
|
@@ -3605,7 +3643,6 @@ var InteractionTracking = class {
|
|
|
3605
3643
|
if (!this.isTracking) return;
|
|
3606
3644
|
this.removeEventListeners();
|
|
3607
3645
|
this.isTracking = false;
|
|
3608
|
-
console.log("[InteractionTracking] \u4EA4\u4E92\u8FFD\u8E2A\u5DF2\u505C\u6B62");
|
|
3609
3646
|
}
|
|
3610
3647
|
/** ----------------- 事件监听器设置 ----------------- */
|
|
3611
3648
|
/**
|
|
@@ -3918,11 +3955,9 @@ var InteractionTracking = class {
|
|
|
3918
3955
|
*/
|
|
3919
3956
|
getElementSelector(element) {
|
|
3920
3957
|
if (element.id) return `#${element.id}`;
|
|
3921
|
-
|
|
3922
|
-
|
|
3923
|
-
|
|
3924
|
-
return `.${classes[0]}`;
|
|
3925
|
-
}
|
|
3958
|
+
const classes = getElementClasses(element);
|
|
3959
|
+
if (classes.length > 0) {
|
|
3960
|
+
return `.${classes[0]}`;
|
|
3926
3961
|
}
|
|
3927
3962
|
const dataTestId = element.getAttribute("data-testid");
|
|
3928
3963
|
if (dataTestId) return `[data-testid="${dataTestId}"]`;
|
|
@@ -4035,1244 +4070,240 @@ var InteractionTracking = class {
|
|
|
4035
4070
|
destroy() {
|
|
4036
4071
|
this.stopTracking();
|
|
4037
4072
|
this.interactions = [];
|
|
4038
|
-
console.log("[InteractionTracking] \u4EA4\u4E92\u8FFD\u8E2A\u6A21\u5757\u5DF2\u9500\u6BC1");
|
|
4039
4073
|
}
|
|
4040
4074
|
};
|
|
4041
4075
|
|
|
4042
|
-
// src/utils/unified-error-handler/features/
|
|
4043
|
-
var
|
|
4076
|
+
// src/utils/unified-error-handler/features/MessageBridge.ts
|
|
4077
|
+
var getOriginalConsole2 = () => window.__originalConsole || {
|
|
4078
|
+
log: console.log.bind(console),
|
|
4079
|
+
warn: console.warn.bind(console),
|
|
4080
|
+
error: console.error.bind(console),
|
|
4081
|
+
info: console.info.bind(console),
|
|
4082
|
+
debug: console.debug.bind(console)
|
|
4083
|
+
};
|
|
4084
|
+
var MessageBridge = class {
|
|
4044
4085
|
constructor(sendMessage) {
|
|
4045
|
-
this.
|
|
4046
|
-
this.
|
|
4047
|
-
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
this.
|
|
4051
|
-
this.
|
|
4052
|
-
this.eventListeners = [];
|
|
4053
|
-
this.lastClickTimestamp = 0;
|
|
4054
|
-
this.lastClickTarget = null;
|
|
4055
|
-
this.mousePosition = { x: 0, y: 0 };
|
|
4056
|
-
this.sendMessage = sendMessage;
|
|
4057
|
-
this.initializeSelector();
|
|
4086
|
+
this.componentTreeGenerator = null;
|
|
4087
|
+
this.messageSender = createDefaultMessageSender({
|
|
4088
|
+
addTimestamp: true,
|
|
4089
|
+
enableDebugLog: false
|
|
4090
|
+
});
|
|
4091
|
+
this.sendMessage = sendMessage || this.messageSender.createSendFunction();
|
|
4092
|
+
this.setupMessageListener();
|
|
4058
4093
|
}
|
|
4059
|
-
/** -----------------
|
|
4094
|
+
/** ----------------- 依赖注入方法 ----------------- */
|
|
4060
4095
|
/**
|
|
4061
|
-
*
|
|
4096
|
+
* 设置组件树生成器
|
|
4062
4097
|
*/
|
|
4063
|
-
|
|
4064
|
-
this.
|
|
4065
|
-
this.createTooltip();
|
|
4066
|
-
this.createStyles();
|
|
4067
|
-
console.log("[ElementSelector] \u5143\u7D20\u9009\u62E9\u5668\u521D\u59CB\u5316\u5B8C\u6210");
|
|
4098
|
+
setComponentTreeGenerator(componentTreeGenerator) {
|
|
4099
|
+
this.componentTreeGenerator = componentTreeGenerator;
|
|
4068
4100
|
}
|
|
4101
|
+
/** ----------------- 消息监听设置 ----------------- */
|
|
4069
4102
|
/**
|
|
4070
|
-
*
|
|
4103
|
+
* 设置消息监听器
|
|
4071
4104
|
*/
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
this.rootElement = document.querySelector("#root") || document.body;
|
|
4077
|
-
if (this.rootElement) {
|
|
4078
|
-
break;
|
|
4105
|
+
setupMessageListener() {
|
|
4106
|
+
this.messageListener = (event) => {
|
|
4107
|
+
if (!this.isOriginAllowed(event.origin)) {
|
|
4108
|
+
return;
|
|
4079
4109
|
}
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
|
|
4085
|
-
}
|
|
4086
|
-
}
|
|
4087
|
-
/**
|
|
4088
|
-
* 创建工具提示
|
|
4089
|
-
*/
|
|
4090
|
-
createTooltip() {
|
|
4091
|
-
this.tooltip = document.createElement("div");
|
|
4092
|
-
this.tooltip.className = "element-selector-tooltip";
|
|
4093
|
-
this.tooltip.setAttribute("role", "tooltip");
|
|
4094
|
-
this.tooltip.style.display = "none";
|
|
4095
|
-
document.body.appendChild(this.tooltip);
|
|
4110
|
+
if (event.data && typeof event.data === "object" && event.data.type) {
|
|
4111
|
+
this.handleMessage(event.data);
|
|
4112
|
+
}
|
|
4113
|
+
};
|
|
4114
|
+
window.addEventListener("message", this.messageListener);
|
|
4096
4115
|
}
|
|
4097
4116
|
/**
|
|
4098
|
-
*
|
|
4117
|
+
* 检查来源是否被允许
|
|
4099
4118
|
*/
|
|
4100
|
-
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
|
|
4104
|
-
document.head.appendChild(this.styleElement);
|
|
4119
|
+
isOriginAllowed(origin) {
|
|
4120
|
+
return GLOBAL_CONFIG.ALLOWED_ORIGINS.some(
|
|
4121
|
+
(allowedOrigin) => origin.includes(allowedOrigin.replace("https://", "").replace("http://", ""))
|
|
4122
|
+
);
|
|
4105
4123
|
}
|
|
4124
|
+
/** ----------------- 主要消息处理方法 ----------------- */
|
|
4106
4125
|
/**
|
|
4107
|
-
*
|
|
4126
|
+
* 处理消息
|
|
4108
4127
|
*/
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
|
|
4137
|
-
|
|
4138
|
-
outline: ${this.config.SELECTED_BORDER_WIDTH} ${this.config.HIGHLIGHT_BORDER_STYLE} ${this.config.SELECTED_COLOR} !important;
|
|
4139
|
-
outline-offset: 3px !important;
|
|
4140
|
-
background-color: ${this.config.SELECTED_COLOR}15 !important;
|
|
4141
|
-
z-index: 9999;
|
|
4142
|
-
}
|
|
4143
|
-
|
|
4144
|
-
[data-element-selected][contenteditable] {
|
|
4145
|
-
outline: none !important;
|
|
4146
|
-
}
|
|
4147
|
-
|
|
4148
|
-
[data-element-hovered][data-full-width],
|
|
4149
|
-
[data-element-selected][data-full-width] {
|
|
4150
|
-
outline-offset: -5px !important;
|
|
4151
|
-
}
|
|
4152
|
-
|
|
4153
|
-
.element-selector-active {
|
|
4154
|
-
cursor: ${this.config.cursor} !important;
|
|
4155
|
-
}
|
|
4156
|
-
|
|
4157
|
-
.element-selector-active * {
|
|
4158
|
-
cursor: ${this.config.cursor} !important;
|
|
4159
|
-
}
|
|
4160
|
-
|
|
4161
|
-
/* \u963B\u6B62\u539F\u751F hover \u6548\u679C\u7684\u5168\u5C40\u6837\u5F0F */
|
|
4162
|
-
body.element-selector-active * {
|
|
4163
|
-
/* \u963B\u6B62\u539F\u751F CSS hover \u4F2A\u7C7B\u6548\u679C */
|
|
4164
|
-
transition: none !important;
|
|
4165
|
-
}
|
|
4166
|
-
|
|
4167
|
-
/* \u963B\u6B62\u6240\u6709 hover \u76F8\u5173\u7684 CSS \u4F2A\u7C7B\uFF0C\u4F46\u6392\u9664\u6211\u4EEC\u7684\u9009\u62E9\u5668\u5143\u7D20 */
|
|
4168
|
-
body.element-selector-active *:hover:not([data-element-selected]):not([data-element-hovered]) {
|
|
4169
|
-
background-color: inherit !important;
|
|
4170
|
-
color: inherit !important;
|
|
4171
|
-
border-color: inherit !important;
|
|
4172
|
-
box-shadow: inherit !important;
|
|
4173
|
-
transform: inherit !important;
|
|
4174
|
-
opacity: inherit !important;
|
|
4175
|
-
filter: inherit !important;
|
|
4176
|
-
}
|
|
4177
|
-
|
|
4178
|
-
/* \u786E\u4FDD\u6211\u4EEC\u7684\u9009\u62E9\u5668\u6837\u5F0F\u4F18\u5148\u7EA7\u6700\u9AD8 */
|
|
4179
|
-
body.element-selector-active [data-element-selected] {
|
|
4180
|
-
background-color: ${this.config.SELECTED_COLOR}15 !important;
|
|
4181
|
-
outline: ${this.config.SELECTED_BORDER_WIDTH} ${this.config.HIGHLIGHT_BORDER_STYLE} ${this.config.SELECTED_COLOR} !important;
|
|
4182
|
-
}
|
|
4183
|
-
|
|
4184
|
-
body.element-selector-active [data-element-hovered] {
|
|
4185
|
-
background-color: ${this.config.HIGHLIGHT_COLOR}20 !important;
|
|
4186
|
-
outline: ${this.config.HIGHLIGHT_BORDER_WIDTH} ${this.config.HIGHLIGHT_BORDER_STYLE} ${this.config.HIGHLIGHT_COLOR} !important;
|
|
4187
|
-
}
|
|
4188
|
-
|
|
4189
|
-
/* \u786E\u4FDD\u5DE5\u5177\u63D0\u793A\u4E0D\u53D7\u5F71\u54CD */
|
|
4190
|
-
body.element-selector-active .element-selector-tooltip {
|
|
4191
|
-
pointer-events: none !important;
|
|
4128
|
+
handleMessage(message) {
|
|
4129
|
+
try {
|
|
4130
|
+
const { type, payload } = message;
|
|
4131
|
+
switch (type) {
|
|
4132
|
+
case "SET_ELEMENT_CONTENT":
|
|
4133
|
+
this.handleSetElementContent(payload);
|
|
4134
|
+
break;
|
|
4135
|
+
case "SET_ELEMENT_ATTRS":
|
|
4136
|
+
this.handleSetElementAttrs(payload);
|
|
4137
|
+
break;
|
|
4138
|
+
case "DUPLICATE_ELEMENT_REQUESTED":
|
|
4139
|
+
this.handleDuplicateElementRequested(payload);
|
|
4140
|
+
break;
|
|
4141
|
+
case "EDIT_TEXT_REQUESTED":
|
|
4142
|
+
this.handleEditTextRequested(payload);
|
|
4143
|
+
break;
|
|
4144
|
+
// 组件树相关消息
|
|
4145
|
+
case "REQUEST_COMPONENT_TREE":
|
|
4146
|
+
this.handleRequestComponentTree();
|
|
4147
|
+
break;
|
|
4148
|
+
case "GET_PARENT_ELEMENT":
|
|
4149
|
+
this.handleGetParentElement(payload);
|
|
4150
|
+
break;
|
|
4151
|
+
// 样式相关消息
|
|
4152
|
+
case "SET_STYLESHEET":
|
|
4153
|
+
this.handleSetStylesheet(payload);
|
|
4154
|
+
break;
|
|
4155
|
+
default:
|
|
4156
|
+
break;
|
|
4192
4157
|
}
|
|
4193
|
-
|
|
4158
|
+
} catch (error) {
|
|
4159
|
+
console.error("[MessageBridge] \u5904\u7406\u6D88\u606F\u5931\u8D25:", error);
|
|
4160
|
+
this.sendMessage({
|
|
4161
|
+
type: "ERROR_EVENT",
|
|
4162
|
+
payload: {
|
|
4163
|
+
type: "message_handling",
|
|
4164
|
+
originalMessage: message,
|
|
4165
|
+
error: error instanceof Error ? error.message : String(error)
|
|
4166
|
+
},
|
|
4167
|
+
timestamp: Date.now()
|
|
4168
|
+
});
|
|
4169
|
+
}
|
|
4194
4170
|
}
|
|
4195
|
-
/** -----------------
|
|
4171
|
+
/** ----------------- 元素操作消息处理 ----------------- */
|
|
4196
4172
|
/**
|
|
4197
|
-
*
|
|
4173
|
+
* 处理设置元素内容
|
|
4198
4174
|
*/
|
|
4199
|
-
|
|
4200
|
-
if (
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4175
|
+
handleSetElementContent(payload) {
|
|
4176
|
+
if (!payload?.selector || !payload?.content) return;
|
|
4177
|
+
const elements = document.querySelectorAll(payload.selector);
|
|
4178
|
+
elements.forEach((element) => {
|
|
4179
|
+
if (element instanceof HTMLElement) {
|
|
4180
|
+
element.innerHTML = payload.content;
|
|
4181
|
+
}
|
|
4182
|
+
});
|
|
4206
4183
|
this.sendMessage({
|
|
4207
|
-
type: "
|
|
4208
|
-
payload: {
|
|
4184
|
+
type: "ELEMENT_EVENT",
|
|
4185
|
+
payload: {
|
|
4186
|
+
type: "content_updated",
|
|
4187
|
+
selector: payload.selector,
|
|
4188
|
+
content: payload.content,
|
|
4189
|
+
elementsUpdated: elements.length
|
|
4190
|
+
},
|
|
4191
|
+
timestamp: Date.now()
|
|
4209
4192
|
});
|
|
4210
4193
|
}
|
|
4211
4194
|
/**
|
|
4212
|
-
*
|
|
4195
|
+
* 处理设置元素属性
|
|
4213
4196
|
*/
|
|
4214
|
-
|
|
4215
|
-
if (!
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
this.hideTooltip();
|
|
4223
|
-
console.log("[ElementSelector] \u9009\u62E9\u5668\u5DF2\u7981\u7528");
|
|
4197
|
+
handleSetElementAttrs(payload) {
|
|
4198
|
+
if (!payload?.selector || !payload?.attrs) return;
|
|
4199
|
+
const elements = document.querySelectorAll(payload.selector);
|
|
4200
|
+
elements.forEach((element) => {
|
|
4201
|
+
Object.entries(payload.attrs).forEach(([key, value]) => {
|
|
4202
|
+
element.setAttribute(key, String(value));
|
|
4203
|
+
});
|
|
4204
|
+
});
|
|
4224
4205
|
this.sendMessage({
|
|
4225
|
-
type: "
|
|
4226
|
-
payload: {
|
|
4206
|
+
type: "ELEMENT_EVENT",
|
|
4207
|
+
payload: {
|
|
4208
|
+
type: "attrs_updated",
|
|
4209
|
+
selector: payload.selector,
|
|
4210
|
+
attrs: payload.attrs,
|
|
4211
|
+
elementsUpdated: elements.length
|
|
4212
|
+
},
|
|
4213
|
+
timestamp: Date.now()
|
|
4227
4214
|
});
|
|
4228
4215
|
}
|
|
4229
4216
|
/**
|
|
4230
|
-
*
|
|
4217
|
+
* 处理复制元素请求
|
|
4231
4218
|
*/
|
|
4232
|
-
|
|
4233
|
-
if (
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
|
|
4219
|
+
handleDuplicateElementRequested(payload) {
|
|
4220
|
+
if (!payload?.selector) return;
|
|
4221
|
+
const element = document.querySelector(payload.selector);
|
|
4222
|
+
if (element && element.parentElement) {
|
|
4223
|
+
const clone = element.cloneNode(true);
|
|
4224
|
+
clone.setAttribute("data-duplicated", "true");
|
|
4225
|
+
element.parentElement.appendChild(clone);
|
|
4226
|
+
this.sendMessage({
|
|
4227
|
+
type: "ELEMENT_EVENT",
|
|
4228
|
+
payload: {
|
|
4229
|
+
type: "duplicated",
|
|
4230
|
+
originalSelector: payload.selector,
|
|
4231
|
+
duplicatedElement: this.getElementInfo(clone)
|
|
4232
|
+
},
|
|
4233
|
+
timestamp: Date.now()
|
|
4234
|
+
});
|
|
4237
4235
|
}
|
|
4238
4236
|
}
|
|
4239
4237
|
/**
|
|
4240
|
-
*
|
|
4241
|
-
*/
|
|
4242
|
-
getSelectorState() {
|
|
4243
|
-
return {
|
|
4244
|
-
isActive: this.isActive,
|
|
4245
|
-
highlightedElement: this.highlightedElement ? this.getElementInfo(this.highlightedElement) : null,
|
|
4246
|
-
selectedElements: this.selectedElements.map((el) => this.getElementInfo(el)),
|
|
4247
|
-
config: { ...this.config }
|
|
4248
|
-
};
|
|
4249
|
-
}
|
|
4250
|
-
/** ----------------- 事件监听器管理 ----------------- */
|
|
4251
|
-
/**
|
|
4252
|
-
* 设置事件监听器
|
|
4238
|
+
* 处理编辑文本请求
|
|
4253
4239
|
*/
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
|
|
4259
|
-
|
|
4260
|
-
|
|
4261
|
-
|
|
4262
|
-
|
|
4263
|
-
|
|
4264
|
-
|
|
4265
|
-
|
|
4240
|
+
handleEditTextRequested(payload) {
|
|
4241
|
+
if (!payload?.selector) return;
|
|
4242
|
+
const element = document.querySelector(payload.selector);
|
|
4243
|
+
if (element instanceof HTMLElement) {
|
|
4244
|
+
element.setAttribute("contenteditable", "true");
|
|
4245
|
+
element.focus();
|
|
4246
|
+
const handleInput = () => {
|
|
4247
|
+
this.sendMessage({
|
|
4248
|
+
type: "ELEMENT_EVENT",
|
|
4249
|
+
payload: {
|
|
4250
|
+
type: "text_updated",
|
|
4251
|
+
selector: payload.selector,
|
|
4252
|
+
content: element.innerText
|
|
4253
|
+
},
|
|
4254
|
+
timestamp: Date.now()
|
|
4255
|
+
});
|
|
4256
|
+
};
|
|
4257
|
+
const handleBlur = () => {
|
|
4258
|
+
element.removeAttribute("contenteditable");
|
|
4259
|
+
element.removeEventListener("input", handleInput);
|
|
4260
|
+
element.removeEventListener("blur", handleBlur);
|
|
4261
|
+
this.sendMessage({
|
|
4262
|
+
type: "ELEMENT_EVENT",
|
|
4263
|
+
payload: {
|
|
4264
|
+
type: "edit_completed",
|
|
4265
|
+
selector: payload.selector,
|
|
4266
|
+
finalContent: element.innerText
|
|
4267
|
+
},
|
|
4268
|
+
timestamp: Date.now()
|
|
4269
|
+
});
|
|
4270
|
+
};
|
|
4271
|
+
element.addEventListener("input", handleInput);
|
|
4272
|
+
element.addEventListener("blur", handleBlur);
|
|
4273
|
+
}
|
|
4266
4274
|
}
|
|
4275
|
+
/** ----------------- 组件树相关消息处理 ----------------- */
|
|
4267
4276
|
/**
|
|
4268
|
-
*
|
|
4277
|
+
* 处理请求组件树
|
|
4269
4278
|
*/
|
|
4270
|
-
|
|
4271
|
-
|
|
4272
|
-
|
|
4279
|
+
handleRequestComponentTree() {
|
|
4280
|
+
if (!this.componentTreeGenerator) return;
|
|
4281
|
+
try {
|
|
4282
|
+
const rootElement = document.querySelector("#root") || document.body;
|
|
4283
|
+
const componentTree = this.componentTreeGenerator.generateComponentTree(rootElement);
|
|
4284
|
+
this.sendMessage({
|
|
4285
|
+
type: "COMPONENT_EVENT",
|
|
4286
|
+
payload: {
|
|
4287
|
+
type: "tree_response",
|
|
4288
|
+
...componentTree
|
|
4289
|
+
},
|
|
4290
|
+
timestamp: Date.now()
|
|
4291
|
+
});
|
|
4292
|
+
} catch (error) {
|
|
4293
|
+
const originalConsole = getOriginalConsole2();
|
|
4294
|
+
originalConsole.error("[MessageBridge] \u751F\u6210\u7EC4\u4EF6\u6811\u5931\u8D25:", error);
|
|
4295
|
+
this.sendMessage({
|
|
4296
|
+
type: "COMPONENT_EVENT",
|
|
4297
|
+
payload: {
|
|
4298
|
+
type: "tree_error",
|
|
4299
|
+
error: error instanceof Error ? error.message : String(error)
|
|
4300
|
+
},
|
|
4301
|
+
timestamp: Date.now()
|
|
4302
|
+
});
|
|
4303
|
+
}
|
|
4273
4304
|
}
|
|
4274
4305
|
/**
|
|
4275
|
-
*
|
|
4276
|
-
*/
|
|
4277
|
-
removeEventListeners() {
|
|
4278
|
-
this.eventListeners.forEach(({ element, event, handler }) => {
|
|
4279
|
-
element.removeEventListener(event, handler);
|
|
4280
|
-
});
|
|
4281
|
-
this.eventListeners = [];
|
|
4282
|
-
}
|
|
4283
|
-
/** ----------------- 事件处理方法 ----------------- */
|
|
4284
|
-
/**
|
|
4285
|
-
* 跟踪鼠标位置
|
|
4286
|
-
*/
|
|
4287
|
-
trackMousePosition(event) {
|
|
4288
|
-
this.mousePosition = { x: event.clientX, y: event.clientY };
|
|
4289
|
-
}
|
|
4290
|
-
/**
|
|
4291
|
-
* 处理鼠标悬停
|
|
4292
|
-
*/
|
|
4293
|
-
handleMouseOver(event) {
|
|
4294
|
-
if (!this.isActive) return;
|
|
4295
|
-
const target = event.target;
|
|
4296
|
-
if (!this.isSelectableElement(target)) return;
|
|
4297
|
-
this.highlightElement(target);
|
|
4298
|
-
this.updateTooltip(target);
|
|
4299
|
-
}
|
|
4300
|
-
/**
|
|
4301
|
-
* 处理鼠标离开
|
|
4302
|
-
*/
|
|
4303
|
-
handleMouseOut(event) {
|
|
4304
|
-
if (!this.isActive) return;
|
|
4305
|
-
this.clearHighlight();
|
|
4306
|
-
this.hideTooltip();
|
|
4307
|
-
}
|
|
4308
|
-
/**
|
|
4309
|
-
* 处理点击
|
|
4310
|
-
*/
|
|
4311
|
-
handleClick(event) {
|
|
4312
|
-
if (!this.isActive) return;
|
|
4313
|
-
const currentTimestamp = Date.now();
|
|
4314
|
-
const target = event.target;
|
|
4315
|
-
if (this.lastClickTarget === target && currentTimestamp - this.lastClickTimestamp < 100) {
|
|
4316
|
-
event.preventDefault();
|
|
4317
|
-
event.stopPropagation();
|
|
4318
|
-
return;
|
|
4319
|
-
}
|
|
4320
|
-
this.lastClickTimestamp = currentTimestamp;
|
|
4321
|
-
this.lastClickTarget = target;
|
|
4322
|
-
event.preventDefault();
|
|
4323
|
-
event.stopPropagation();
|
|
4324
|
-
if (!this.isSelectableElement(target)) return;
|
|
4325
|
-
if (event.metaKey || event.ctrlKey) {
|
|
4326
|
-
this.toggleElementSelection(target);
|
|
4327
|
-
} else {
|
|
4328
|
-
this.selectElement(target);
|
|
4329
|
-
}
|
|
4330
|
-
this.sendMessage({
|
|
4331
|
-
type: "ELEMENT_CLICKED",
|
|
4332
|
-
payload: {
|
|
4333
|
-
element: this.getElementInfo(target),
|
|
4334
|
-
isMultiSelect: event.metaKey || event.ctrlKey
|
|
4335
|
-
}
|
|
4336
|
-
});
|
|
4337
|
-
}
|
|
4338
|
-
/**
|
|
4339
|
-
* 处理双击
|
|
4340
|
-
*/
|
|
4341
|
-
handleDoubleClick(event) {
|
|
4342
|
-
if (!this.isActive) return;
|
|
4343
|
-
event.preventDefault();
|
|
4344
|
-
event.stopPropagation();
|
|
4345
|
-
const target = event.target;
|
|
4346
|
-
if (!this.isSelectableElement(target)) return;
|
|
4347
|
-
this.sendMessage({
|
|
4348
|
-
type: "ELEMENT_DOUBLE_CLICKED",
|
|
4349
|
-
payload: {
|
|
4350
|
-
element: this.getElementInfo(target)
|
|
4351
|
-
}
|
|
4352
|
-
});
|
|
4353
|
-
}
|
|
4354
|
-
/**
|
|
4355
|
-
* 处理滚动
|
|
4356
|
-
*/
|
|
4357
|
-
handleScroll() {
|
|
4358
|
-
if (!this.isActive) return;
|
|
4359
|
-
this.hideTooltip();
|
|
4360
|
-
}
|
|
4361
|
-
/**
|
|
4362
|
-
* 处理键盘事件
|
|
4363
|
-
*/
|
|
4364
|
-
handleKeyDown(event) {
|
|
4365
|
-
if (!this.isActive) return;
|
|
4366
|
-
const keyboardEvent = event;
|
|
4367
|
-
if (keyboardEvent.key === "Escape") {
|
|
4368
|
-
event.preventDefault();
|
|
4369
|
-
event.stopPropagation();
|
|
4370
|
-
this.disableSelector();
|
|
4371
|
-
}
|
|
4372
|
-
}
|
|
4373
|
-
/**
|
|
4374
|
-
* 阻止表单交互
|
|
4375
|
-
*/
|
|
4376
|
-
preventFormInteraction(event) {
|
|
4377
|
-
if (!this.isActive) return;
|
|
4378
|
-
const target = event.target;
|
|
4379
|
-
if (["input", "textarea", "select"].includes(target.tagName.toLowerCase())) {
|
|
4380
|
-
event.preventDefault();
|
|
4381
|
-
}
|
|
4382
|
-
}
|
|
4383
|
-
/**
|
|
4384
|
-
* 阻止所有交互
|
|
4385
|
-
*/
|
|
4386
|
-
preventAllInteraction(event) {
|
|
4387
|
-
if (this.isActive) {
|
|
4388
|
-
event.preventDefault();
|
|
4389
|
-
event.stopPropagation();
|
|
4390
|
-
return false;
|
|
4391
|
-
}
|
|
4392
|
-
}
|
|
4393
|
-
/** ----------------- 元素操作方法 ----------------- */
|
|
4394
|
-
/**
|
|
4395
|
-
* 高亮元素
|
|
4396
|
-
*/
|
|
4397
|
-
highlightElement(element) {
|
|
4398
|
-
this.clearHighlight();
|
|
4399
|
-
this.highlightedElement = element;
|
|
4400
|
-
element.setAttribute("data-element-hovered", "true");
|
|
4401
|
-
if (this.isFullWidthElement(element)) {
|
|
4402
|
-
element.setAttribute("data-full-width", "true");
|
|
4403
|
-
}
|
|
4404
|
-
}
|
|
4405
|
-
/**
|
|
4406
|
-
* 清除高亮
|
|
4407
|
-
*/
|
|
4408
|
-
clearHighlight() {
|
|
4409
|
-
if (this.highlightedElement) {
|
|
4410
|
-
this.highlightedElement.removeAttribute("data-element-hovered");
|
|
4411
|
-
this.highlightedElement.removeAttribute("data-full-width");
|
|
4412
|
-
this.highlightedElement = null;
|
|
4413
|
-
}
|
|
4414
|
-
}
|
|
4415
|
-
/**
|
|
4416
|
-
* 选择元素
|
|
4417
|
-
*/
|
|
4418
|
-
selectElement(element) {
|
|
4419
|
-
this.clearSelection();
|
|
4420
|
-
this.selectedElements = [element];
|
|
4421
|
-
element.setAttribute("data-element-selected", "true");
|
|
4422
|
-
if (this.isFullWidthElement(element)) {
|
|
4423
|
-
element.setAttribute("data-full-width", "true");
|
|
4424
|
-
}
|
|
4425
|
-
}
|
|
4426
|
-
/**
|
|
4427
|
-
* 切换元素选择状态
|
|
4428
|
-
*/
|
|
4429
|
-
toggleElementSelection(element) {
|
|
4430
|
-
const index = this.selectedElements.indexOf(element);
|
|
4431
|
-
if (index > -1) {
|
|
4432
|
-
this.selectedElements.splice(index, 1);
|
|
4433
|
-
element.removeAttribute("data-element-selected");
|
|
4434
|
-
element.removeAttribute("data-full-width");
|
|
4435
|
-
} else {
|
|
4436
|
-
this.selectedElements.push(element);
|
|
4437
|
-
element.setAttribute("data-element-selected", "true");
|
|
4438
|
-
if (this.isFullWidthElement(element)) {
|
|
4439
|
-
element.setAttribute("data-full-width", "true");
|
|
4440
|
-
}
|
|
4441
|
-
}
|
|
4442
|
-
}
|
|
4443
|
-
/**
|
|
4444
|
-
* 清除选择
|
|
4445
|
-
*/
|
|
4446
|
-
clearSelection() {
|
|
4447
|
-
this.selectedElements.forEach((element) => {
|
|
4448
|
-
element.removeAttribute("data-element-selected");
|
|
4449
|
-
element.removeAttribute("data-full-width");
|
|
4450
|
-
});
|
|
4451
|
-
this.selectedElements = [];
|
|
4452
|
-
}
|
|
4453
|
-
/** ----------------- 工具提示管理 ----------------- */
|
|
4454
|
-
/**
|
|
4455
|
-
* 更新工具提示
|
|
4456
|
-
*/
|
|
4457
|
-
updateTooltip(element) {
|
|
4458
|
-
if (!this.tooltip) return;
|
|
4459
|
-
const rect = element.getBoundingClientRect();
|
|
4460
|
-
const tagName = element.tagName.toLowerCase();
|
|
4461
|
-
this.tooltip.textContent = tagName;
|
|
4462
|
-
this.tooltip.style.display = "block";
|
|
4463
|
-
const isFullWidth = this.isFullWidthElement(element);
|
|
4464
|
-
if (isFullWidth) {
|
|
4465
|
-
this.tooltip.style.left = this.config.FULL_WIDTH_TOOLTIP_OFFSET + "px";
|
|
4466
|
-
this.tooltip.style.top = this.config.FULL_WIDTH_TOOLTIP_OFFSET + "px";
|
|
4467
|
-
} else {
|
|
4468
|
-
const top = Math.max(0, rect.top - 30);
|
|
4469
|
-
this.tooltip.style.left = `${Math.max(0, rect.left)}px`;
|
|
4470
|
-
this.tooltip.style.top = `${top}px`;
|
|
4471
|
-
}
|
|
4472
|
-
}
|
|
4473
|
-
/**
|
|
4474
|
-
* 隐藏工具提示
|
|
4475
|
-
*/
|
|
4476
|
-
hideTooltip() {
|
|
4477
|
-
if (this.tooltip) {
|
|
4478
|
-
this.tooltip.style.display = "none";
|
|
4479
|
-
}
|
|
4480
|
-
}
|
|
4481
|
-
/** ----------------- 按钮状态管理 ----------------- */
|
|
4482
|
-
/**
|
|
4483
|
-
* 管理按钮状态
|
|
4484
|
-
*/
|
|
4485
|
-
manageButtonStates(enable) {
|
|
4486
|
-
if (!this.rootElement) return;
|
|
4487
|
-
const buttons = this.rootElement.querySelectorAll('button, input[type="button"], input[type="submit"]');
|
|
4488
|
-
if (enable) {
|
|
4489
|
-
buttons.forEach((button) => {
|
|
4490
|
-
const btn = button;
|
|
4491
|
-
if (!btn.disabled) {
|
|
4492
|
-
btn.disabled = true;
|
|
4493
|
-
btn.setAttribute("data-selector-disabled", "true");
|
|
4494
|
-
}
|
|
4495
|
-
});
|
|
4496
|
-
} else {
|
|
4497
|
-
buttons.forEach((button) => {
|
|
4498
|
-
const btn = button;
|
|
4499
|
-
if (btn.hasAttribute("data-selector-disabled")) {
|
|
4500
|
-
btn.disabled = false;
|
|
4501
|
-
btn.removeAttribute("data-selector-disabled");
|
|
4502
|
-
}
|
|
4503
|
-
});
|
|
4504
|
-
}
|
|
4505
|
-
}
|
|
4506
|
-
/** ----------------- 新增的精确代码位置定位方法 ----------------- */
|
|
4507
|
-
/**
|
|
4508
|
-
* 检查元素是否有 howone ID
|
|
4509
|
-
*/
|
|
4510
|
-
hasHowoneId(element) {
|
|
4511
|
-
return element.hasAttribute("data-howone-id");
|
|
4512
|
-
}
|
|
4513
|
-
/**
|
|
4514
|
-
* 解析 howone ID
|
|
4515
|
-
*/
|
|
4516
|
-
parseHowoneId(element) {
|
|
4517
|
-
const howoneId = element.getAttribute("data-howone-id");
|
|
4518
|
-
if (!howoneId) return null;
|
|
4519
|
-
try {
|
|
4520
|
-
if (howoneId.includes(":")) {
|
|
4521
|
-
const parts = howoneId.split(":");
|
|
4522
|
-
if (parts.length >= 2) {
|
|
4523
|
-
return {
|
|
4524
|
-
filePath: parts[0],
|
|
4525
|
-
lineNumber: parseInt(parts[1], 10),
|
|
4526
|
-
col: parts[2] ? parseInt(parts[2], 10) : 0
|
|
4527
|
-
};
|
|
4528
|
-
}
|
|
4529
|
-
} else {
|
|
4530
|
-
const parsed = JSON.parse(howoneId);
|
|
4531
|
-
if (parsed.filePath && parsed.lineNumber) {
|
|
4532
|
-
return {
|
|
4533
|
-
filePath: parsed.filePath,
|
|
4534
|
-
lineNumber: parsed.lineNumber,
|
|
4535
|
-
col: parsed.col || 0
|
|
4536
|
-
};
|
|
4537
|
-
}
|
|
4538
|
-
}
|
|
4539
|
-
} catch (error) {
|
|
4540
|
-
console.warn("[ElementSelector] \u89E3\u6790 data-howone-id \u5931\u8D25:", error);
|
|
4541
|
-
}
|
|
4542
|
-
return null;
|
|
4543
|
-
}
|
|
4544
|
-
/**
|
|
4545
|
-
* 获取元素的代码位置
|
|
4546
|
-
*/
|
|
4547
|
-
getElementLocation(element) {
|
|
4548
|
-
return this.parseHowoneId(element);
|
|
4549
|
-
}
|
|
4550
|
-
/**
|
|
4551
|
-
* 提取元素数据(包含位置信息)
|
|
4552
|
-
*/
|
|
4553
|
-
extractElementData(element) {
|
|
4554
|
-
const location = this.getElementLocation(element);
|
|
4555
|
-
return {
|
|
4556
|
-
id: element.id || void 0,
|
|
4557
|
-
className: element.className || void 0,
|
|
4558
|
-
textContent: element.textContent?.trim().substring(0, 100) || void 0,
|
|
4559
|
-
filePath: location?.filePath,
|
|
4560
|
-
lineNumber: location?.lineNumber,
|
|
4561
|
-
col: location?.col,
|
|
4562
|
-
elementType: element.tagName.toLowerCase(),
|
|
4563
|
-
attrs: this.getElementAttributes(element)
|
|
4564
|
-
};
|
|
4565
|
-
}
|
|
4566
|
-
/**
|
|
4567
|
-
* 根据代码位置查找元素
|
|
4568
|
-
*/
|
|
4569
|
-
findElementsByLocation(filePath, lineNumber) {
|
|
4570
|
-
const elements = [];
|
|
4571
|
-
const elementsWithHowoneId = this.rootElement?.querySelectorAll("[data-howone-id]") || [];
|
|
4572
|
-
elementsWithHowoneId.forEach((element) => {
|
|
4573
|
-
const location = this.getElementLocation(element);
|
|
4574
|
-
if (location && location.filePath === filePath && location.lineNumber === lineNumber) {
|
|
4575
|
-
elements.push(element);
|
|
4576
|
-
}
|
|
4577
|
-
});
|
|
4578
|
-
return elements;
|
|
4579
|
-
}
|
|
4580
|
-
/**
|
|
4581
|
-
* 获取指定坐标位置的元素
|
|
4582
|
-
*/
|
|
4583
|
-
getElementAtPoint(x, y) {
|
|
4584
|
-
const originalDisplay = this.tooltip?.style.display;
|
|
4585
|
-
if (this.tooltip) {
|
|
4586
|
-
this.tooltip.style.display = "none";
|
|
4587
|
-
}
|
|
4588
|
-
const element = document.elementFromPoint(x, y);
|
|
4589
|
-
if (this.tooltip && originalDisplay) {
|
|
4590
|
-
this.tooltip.style.display = originalDisplay;
|
|
4591
|
-
}
|
|
4592
|
-
return element;
|
|
4593
|
-
}
|
|
4594
|
-
/** ----------------- 元素编辑功能 ----------------- */
|
|
4595
|
-
/**
|
|
4596
|
-
* 设置元素内容
|
|
4597
|
-
*/
|
|
4598
|
-
setElementContent(selector, content) {
|
|
4599
|
-
try {
|
|
4600
|
-
const element = document.querySelector(selector);
|
|
4601
|
-
if (!element) return false;
|
|
4602
|
-
if (element.tagName.toLowerCase() === "input" || element.tagName.toLowerCase() === "textarea") {
|
|
4603
|
-
element.value = content;
|
|
4604
|
-
} else {
|
|
4605
|
-
element.textContent = content;
|
|
4606
|
-
}
|
|
4607
|
-
this.sendMessage({
|
|
4608
|
-
type: "ELEMENT_CONTENT_UPDATED",
|
|
4609
|
-
payload: {
|
|
4610
|
-
selector,
|
|
4611
|
-
content,
|
|
4612
|
-
element: this.getElementInfo(element)
|
|
4613
|
-
}
|
|
4614
|
-
});
|
|
4615
|
-
return true;
|
|
4616
|
-
} catch (error) {
|
|
4617
|
-
console.error("[ElementSelector] \u8BBE\u7F6E\u5143\u7D20\u5185\u5BB9\u5931\u8D25:", error);
|
|
4618
|
-
return false;
|
|
4619
|
-
}
|
|
4620
|
-
}
|
|
4621
|
-
/**
|
|
4622
|
-
* 设置元素属性
|
|
4623
|
-
*/
|
|
4624
|
-
setElementAttributes(selector, attributes) {
|
|
4625
|
-
try {
|
|
4626
|
-
const element = document.querySelector(selector);
|
|
4627
|
-
if (!element) return false;
|
|
4628
|
-
Object.entries(attributes).forEach(([key, value]) => {
|
|
4629
|
-
if (value === null || value === void 0) {
|
|
4630
|
-
element.removeAttribute(key);
|
|
4631
|
-
} else {
|
|
4632
|
-
element.setAttribute(key, value);
|
|
4633
|
-
}
|
|
4634
|
-
});
|
|
4635
|
-
this.sendMessage({
|
|
4636
|
-
type: "ELEMENT_ATTRIBUTES_UPDATED",
|
|
4637
|
-
payload: {
|
|
4638
|
-
selector,
|
|
4639
|
-
attributes,
|
|
4640
|
-
element: this.getElementInfo(element)
|
|
4641
|
-
}
|
|
4642
|
-
});
|
|
4643
|
-
return true;
|
|
4644
|
-
} catch (error) {
|
|
4645
|
-
console.error("[ElementSelector] \u8BBE\u7F6E\u5143\u7D20\u5C5E\u6027\u5931\u8D25:", error);
|
|
4646
|
-
return false;
|
|
4647
|
-
}
|
|
4648
|
-
}
|
|
4649
|
-
/**
|
|
4650
|
-
* 复制元素
|
|
4651
|
-
*/
|
|
4652
|
-
duplicateElement(selector) {
|
|
4653
|
-
try {
|
|
4654
|
-
const element = document.querySelector(selector);
|
|
4655
|
-
if (!element || !element.parentNode) return false;
|
|
4656
|
-
const clonedElement = element.cloneNode(true);
|
|
4657
|
-
clonedElement.removeAttribute("data-blnk-id");
|
|
4658
|
-
element.parentNode.insertBefore(clonedElement, element.nextSibling);
|
|
4659
|
-
this.sendMessage({
|
|
4660
|
-
type: "ELEMENT_DUPLICATED",
|
|
4661
|
-
payload: {
|
|
4662
|
-
originalSelector: selector,
|
|
4663
|
-
duplicatedElement: this.getElementInfo(clonedElement)
|
|
4664
|
-
}
|
|
4665
|
-
});
|
|
4666
|
-
return true;
|
|
4667
|
-
} catch (error) {
|
|
4668
|
-
console.error("[ElementSelector] \u590D\u5236\u5143\u7D20\u5931\u8D25:", error);
|
|
4669
|
-
return false;
|
|
4670
|
-
}
|
|
4671
|
-
}
|
|
4672
|
-
/**
|
|
4673
|
-
* 启用文本编辑
|
|
4674
|
-
*/
|
|
4675
|
-
enableTextEditing(selector) {
|
|
4676
|
-
try {
|
|
4677
|
-
const element = document.querySelector(selector);
|
|
4678
|
-
if (!element) return false;
|
|
4679
|
-
element.setAttribute("contenteditable", "true");
|
|
4680
|
-
element.setAttribute("data-editing", "true");
|
|
4681
|
-
element.focus();
|
|
4682
|
-
const handleEditComplete = () => {
|
|
4683
|
-
element.removeAttribute("contenteditable");
|
|
4684
|
-
element.removeAttribute("data-editing");
|
|
4685
|
-
element.removeEventListener("blur", handleEditComplete);
|
|
4686
|
-
element.removeEventListener("keydown", handleKeyDown);
|
|
4687
|
-
this.sendMessage({
|
|
4688
|
-
type: "ELEMENT_TEXT_UPDATED",
|
|
4689
|
-
payload: {
|
|
4690
|
-
selector,
|
|
4691
|
-
content: element.textContent || "",
|
|
4692
|
-
element: this.getElementInfo(element)
|
|
4693
|
-
}
|
|
4694
|
-
});
|
|
4695
|
-
};
|
|
4696
|
-
const handleKeyDown = (event) => {
|
|
4697
|
-
const keyboardEvent = event;
|
|
4698
|
-
if (keyboardEvent.key === "Enter" && !keyboardEvent.shiftKey) {
|
|
4699
|
-
event.preventDefault();
|
|
4700
|
-
handleEditComplete();
|
|
4701
|
-
} else if (keyboardEvent.key === "Escape") {
|
|
4702
|
-
event.preventDefault();
|
|
4703
|
-
handleEditComplete();
|
|
4704
|
-
}
|
|
4705
|
-
};
|
|
4706
|
-
element.addEventListener("blur", handleEditComplete);
|
|
4707
|
-
element.addEventListener("keydown", handleKeyDown);
|
|
4708
|
-
return true;
|
|
4709
|
-
} catch (error) {
|
|
4710
|
-
console.error("[ElementSelector] \u542F\u7528\u6587\u672C\u7F16\u8F91\u5931\u8D25:", error);
|
|
4711
|
-
return false;
|
|
4712
|
-
}
|
|
4713
|
-
}
|
|
4714
|
-
/** ----------------- 高级交互功能 ----------------- */
|
|
4715
|
-
/**
|
|
4716
|
-
* 获取父元素
|
|
4717
|
-
*/
|
|
4718
|
-
getParentElement(selector) {
|
|
4719
|
-
try {
|
|
4720
|
-
const element = document.querySelector(selector);
|
|
4721
|
-
return element?.parentElement || null;
|
|
4722
|
-
} catch (error) {
|
|
4723
|
-
console.error("[ElementSelector] \u83B7\u53D6\u7236\u5143\u7D20\u5931\u8D25:", error);
|
|
4724
|
-
return null;
|
|
4725
|
-
}
|
|
4726
|
-
}
|
|
4727
|
-
/**
|
|
4728
|
-
* 外部悬停控制 - 通过选择器悬停元素
|
|
4729
|
-
*/
|
|
4730
|
-
hoverElementBySelector(selector) {
|
|
4731
|
-
try {
|
|
4732
|
-
const element = document.querySelector(selector);
|
|
4733
|
-
if (!element) return false;
|
|
4734
|
-
this.highlightElement(element);
|
|
4735
|
-
this.updateTooltip(element);
|
|
4736
|
-
return true;
|
|
4737
|
-
} catch (error) {
|
|
4738
|
-
console.error("[ElementSelector] \u5916\u90E8\u60AC\u505C\u63A7\u5236\u5931\u8D25:", error);
|
|
4739
|
-
return false;
|
|
4740
|
-
}
|
|
4741
|
-
}
|
|
4742
|
-
/**
|
|
4743
|
-
* 外部悬停控制 - 取消悬停
|
|
4744
|
-
*/
|
|
4745
|
-
unhoverElement() {
|
|
4746
|
-
this.clearHighlight();
|
|
4747
|
-
this.hideTooltip();
|
|
4748
|
-
}
|
|
4749
|
-
/** ----------------- 辅助方法 ----------------- */
|
|
4750
|
-
/**
|
|
4751
|
-
* 检查元素是否为全宽元素
|
|
4752
|
-
*/
|
|
4753
|
-
isFullWidthElement(element) {
|
|
4754
|
-
try {
|
|
4755
|
-
const rect = element.getBoundingClientRect();
|
|
4756
|
-
return Math.abs(rect.width - window.innerWidth) < 5;
|
|
4757
|
-
} catch (error) {
|
|
4758
|
-
console.warn("[ElementSelector] \u68C0\u67E5\u5168\u5BBD\u5143\u7D20\u5931\u8D25:", error);
|
|
4759
|
-
return false;
|
|
4760
|
-
}
|
|
4761
|
-
}
|
|
4762
|
-
/**
|
|
4763
|
-
* 检查元素是否可选择
|
|
4764
|
-
*/
|
|
4765
|
-
isSelectableElement(element) {
|
|
4766
|
-
if (!element || element === document.body || element === document.documentElement) {
|
|
4767
|
-
return false;
|
|
4768
|
-
}
|
|
4769
|
-
if (this.hasHowoneId(element)) {
|
|
4770
|
-
return true;
|
|
4771
|
-
}
|
|
4772
|
-
if (element.id === "howone-element-tooltip" || element.classList.contains("howone-tooltip")) {
|
|
4773
|
-
return false;
|
|
4774
|
-
}
|
|
4775
|
-
const tagName = element.tagName.toLowerCase();
|
|
4776
|
-
if (["script", "style", "meta", "link", "title"].includes(tagName)) {
|
|
4777
|
-
return false;
|
|
4778
|
-
}
|
|
4779
|
-
return true;
|
|
4780
|
-
}
|
|
4781
|
-
/**
|
|
4782
|
-
* 获取元素信息
|
|
4783
|
-
*/
|
|
4784
|
-
getElementInfo(element) {
|
|
4785
|
-
const location = this.getElementLocation(element);
|
|
4786
|
-
return {
|
|
4787
|
-
tagName: element.tagName.toLowerCase(),
|
|
4788
|
-
id: element.id || void 0,
|
|
4789
|
-
className: element.className || void 0,
|
|
4790
|
-
textContent: element.textContent?.trim().substring(0, 100) || void 0,
|
|
4791
|
-
attributes: this.getElementAttributes(element),
|
|
4792
|
-
selector: this.getElementSelector(element),
|
|
4793
|
-
boundingRect: element.getBoundingClientRect(),
|
|
4794
|
-
location: location || void 0
|
|
4795
|
-
};
|
|
4796
|
-
}
|
|
4797
|
-
/**
|
|
4798
|
-
* 获取元素属性
|
|
4799
|
-
*/
|
|
4800
|
-
getElementAttributes(element) {
|
|
4801
|
-
const attrs = {};
|
|
4802
|
-
const importantAttrs = ["id", "class", "data-testid", "data-howone-id", "data-component-path", "data-blnk-id", "href", "src", "type", "name"];
|
|
4803
|
-
importantAttrs.forEach((attr) => {
|
|
4804
|
-
const value = element.getAttribute(attr);
|
|
4805
|
-
if (value) {
|
|
4806
|
-
attrs[attr] = value;
|
|
4807
|
-
}
|
|
4808
|
-
});
|
|
4809
|
-
return attrs;
|
|
4810
|
-
}
|
|
4811
|
-
/**
|
|
4812
|
-
* 获取元素选择器
|
|
4813
|
-
*/
|
|
4814
|
-
getElementSelector(element) {
|
|
4815
|
-
const howoneId = element.getAttribute("data-howone-id");
|
|
4816
|
-
if (howoneId) {
|
|
4817
|
-
return `[data-howone-id="${howoneId}"]`;
|
|
4818
|
-
}
|
|
4819
|
-
if (element.id) {
|
|
4820
|
-
return `#${element.id}`;
|
|
4821
|
-
}
|
|
4822
|
-
const dataTestId = element.getAttribute("data-testid");
|
|
4823
|
-
if (dataTestId) {
|
|
4824
|
-
return `[data-testid="${dataTestId}"]`;
|
|
4825
|
-
}
|
|
4826
|
-
if (element.className) {
|
|
4827
|
-
const classes = element.className.split(" ").filter((c) => c.trim());
|
|
4828
|
-
if (classes.length > 0) {
|
|
4829
|
-
return `.${classes[0]}`;
|
|
4830
|
-
}
|
|
4831
|
-
}
|
|
4832
|
-
return element.tagName.toLowerCase();
|
|
4833
|
-
}
|
|
4834
|
-
/** ----------------- 公共接口方法 ----------------- */
|
|
4835
|
-
/**
|
|
4836
|
-
* 通过选择器高亮元素
|
|
4837
|
-
*/
|
|
4838
|
-
highlightElementBySelector(selector) {
|
|
4839
|
-
const element = document.querySelector(selector);
|
|
4840
|
-
if (element) {
|
|
4841
|
-
this.highlightElement(element);
|
|
4842
|
-
}
|
|
4843
|
-
}
|
|
4844
|
-
/**
|
|
4845
|
-
* 通过选择器取消高亮元素
|
|
4846
|
-
*/
|
|
4847
|
-
unhighlightElementBySelector(selector) {
|
|
4848
|
-
const element = document.querySelector(selector);
|
|
4849
|
-
if (element && element === this.highlightedElement) {
|
|
4850
|
-
this.clearHighlight();
|
|
4851
|
-
}
|
|
4852
|
-
}
|
|
4853
|
-
/**
|
|
4854
|
-
* 更新选中的元素
|
|
4855
|
-
*/
|
|
4856
|
-
updateSelectedElements(elements) {
|
|
4857
|
-
this.clearSelection();
|
|
4858
|
-
elements.forEach((elementData) => {
|
|
4859
|
-
const element = this.findElementByData(elementData);
|
|
4860
|
-
if (element) {
|
|
4861
|
-
this.selectedElements.push(element);
|
|
4862
|
-
element.setAttribute("data-element-selected", "true");
|
|
4863
|
-
if (this.isFullWidthElement(element)) {
|
|
4864
|
-
element.setAttribute("data-full-width", "true");
|
|
4865
|
-
}
|
|
4866
|
-
}
|
|
4867
|
-
});
|
|
4868
|
-
}
|
|
4869
|
-
/**
|
|
4870
|
-
* 根据数据查找元素
|
|
4871
|
-
*/
|
|
4872
|
-
findElementByData(elementData) {
|
|
4873
|
-
if (elementData.blinkId) {
|
|
4874
|
-
return document.querySelector(`[data-blnk-id="${elementData.blinkId}"]`);
|
|
4875
|
-
}
|
|
4876
|
-
if (elementData.id) {
|
|
4877
|
-
return document.getElementById(elementData.id);
|
|
4878
|
-
}
|
|
4879
|
-
if (elementData.selector) {
|
|
4880
|
-
return document.querySelector(elementData.selector);
|
|
4881
|
-
}
|
|
4882
|
-
return null;
|
|
4883
|
-
}
|
|
4884
|
-
/**
|
|
4885
|
-
* 销毁选择器
|
|
4886
|
-
*/
|
|
4887
|
-
destroy() {
|
|
4888
|
-
this.disableSelector();
|
|
4889
|
-
if (this.tooltip) {
|
|
4890
|
-
this.tooltip.remove();
|
|
4891
|
-
this.tooltip = null;
|
|
4892
|
-
}
|
|
4893
|
-
if (this.styleElement) {
|
|
4894
|
-
this.styleElement.remove();
|
|
4895
|
-
this.styleElement = null;
|
|
4896
|
-
}
|
|
4897
|
-
console.log("[ElementSelector] \u5143\u7D20\u9009\u62E9\u5668\u5DF2\u9500\u6BC1");
|
|
4898
|
-
}
|
|
4899
|
-
};
|
|
4900
|
-
|
|
4901
|
-
// src/utils/unified-error-handler/features/MessageBridge.ts
|
|
4902
|
-
var getOriginalConsole2 = () => window.__originalConsole || {
|
|
4903
|
-
log: console.log.bind(console),
|
|
4904
|
-
warn: console.warn.bind(console),
|
|
4905
|
-
error: console.error.bind(console),
|
|
4906
|
-
info: console.info.bind(console),
|
|
4907
|
-
debug: console.debug.bind(console)
|
|
4908
|
-
};
|
|
4909
|
-
var MessageBridge = class {
|
|
4910
|
-
constructor(sendMessage) {
|
|
4911
|
-
this.elementSelector = null;
|
|
4912
|
-
this.componentTreeGenerator = null;
|
|
4913
|
-
this.messageSender = createDefaultMessageSender({
|
|
4914
|
-
addTimestamp: true,
|
|
4915
|
-
enableDebugLog: false
|
|
4916
|
-
});
|
|
4917
|
-
this.sendMessage = sendMessage || this.messageSender.createSendFunction();
|
|
4918
|
-
this.setupMessageListener();
|
|
4919
|
-
console.log("[MessageBridge] \u6D88\u606F\u6865\u63A5\u5668\u521D\u59CB\u5316\u5B8C\u6210");
|
|
4920
|
-
}
|
|
4921
|
-
/** ----------------- 依赖注入方法 ----------------- */
|
|
4922
|
-
/**
|
|
4923
|
-
* 设置元素选择器
|
|
4924
|
-
*/
|
|
4925
|
-
setElementSelector(elementSelector2) {
|
|
4926
|
-
this.elementSelector = elementSelector2;
|
|
4927
|
-
}
|
|
4928
|
-
/**
|
|
4929
|
-
* 设置组件树生成器
|
|
4930
|
-
*/
|
|
4931
|
-
setComponentTreeGenerator(componentTreeGenerator) {
|
|
4932
|
-
this.componentTreeGenerator = componentTreeGenerator;
|
|
4933
|
-
}
|
|
4934
|
-
/** ----------------- 消息监听设置 ----------------- */
|
|
4935
|
-
/**
|
|
4936
|
-
* 设置消息监听器
|
|
4937
|
-
*/
|
|
4938
|
-
setupMessageListener() {
|
|
4939
|
-
this.messageListener = (event) => {
|
|
4940
|
-
if (!this.isOriginAllowed(event.origin)) {
|
|
4941
|
-
return;
|
|
4942
|
-
}
|
|
4943
|
-
if (event.data && typeof event.data === "object" && event.data.type) {
|
|
4944
|
-
this.handleMessage(event.data);
|
|
4945
|
-
}
|
|
4946
|
-
};
|
|
4947
|
-
window.addEventListener("message", this.messageListener);
|
|
4948
|
-
}
|
|
4949
|
-
/**
|
|
4950
|
-
* 检查来源是否被允许
|
|
4951
|
-
*/
|
|
4952
|
-
isOriginAllowed(origin) {
|
|
4953
|
-
return GLOBAL_CONFIG.ALLOWED_ORIGINS.some(
|
|
4954
|
-
(allowedOrigin) => origin.includes(allowedOrigin.replace("https://", "").replace("http://", ""))
|
|
4955
|
-
);
|
|
4956
|
-
}
|
|
4957
|
-
/** ----------------- 主要消息处理方法 ----------------- */
|
|
4958
|
-
/**
|
|
4959
|
-
* 处理消息
|
|
4960
|
-
*/
|
|
4961
|
-
handleMessage(message) {
|
|
4962
|
-
try {
|
|
4963
|
-
const { type, payload } = message;
|
|
4964
|
-
switch (type) {
|
|
4965
|
-
// 选择器相关消息
|
|
4966
|
-
case "TOGGLE_SELECTOR":
|
|
4967
|
-
this.handleToggleSelector(payload);
|
|
4968
|
-
break;
|
|
4969
|
-
case "ENABLE_SELECTOR":
|
|
4970
|
-
this.handleEnableElementSelector();
|
|
4971
|
-
break;
|
|
4972
|
-
case "DISABLE_SELECTOR":
|
|
4973
|
-
this.handleDisableElementSelector();
|
|
4974
|
-
break;
|
|
4975
|
-
case "GET_SELECTOR_STATE":
|
|
4976
|
-
this.handleGetSelectorState();
|
|
4977
|
-
break;
|
|
4978
|
-
// 元素操作消息
|
|
4979
|
-
case "HOVER_ELEMENT_BY_ID":
|
|
4980
|
-
this.handleHoverElementById(payload);
|
|
4981
|
-
break;
|
|
4982
|
-
case "UNHOVER_ELEMENT_BY_ID":
|
|
4983
|
-
this.handleUnhoverElementById(payload);
|
|
4984
|
-
break;
|
|
4985
|
-
case "HOVER_ELEMENT_REQUESTED":
|
|
4986
|
-
this.handleHoverElementRequested(payload);
|
|
4987
|
-
break;
|
|
4988
|
-
case "UNHOVER_ELEMENT_REQUESTED":
|
|
4989
|
-
this.handleUnhoverElementRequested(payload);
|
|
4990
|
-
break;
|
|
4991
|
-
case "SET_ELEMENT_CONTENT":
|
|
4992
|
-
this.handleSetElementContent(payload);
|
|
4993
|
-
break;
|
|
4994
|
-
case "SET_ELEMENT_ATTRS":
|
|
4995
|
-
this.handleSetElementAttrs(payload);
|
|
4996
|
-
break;
|
|
4997
|
-
case "DUPLICATE_ELEMENT_REQUESTED":
|
|
4998
|
-
this.handleDuplicateElementRequested(payload);
|
|
4999
|
-
break;
|
|
5000
|
-
case "EDIT_TEXT_REQUESTED":
|
|
5001
|
-
this.handleEditTextRequested(payload);
|
|
5002
|
-
break;
|
|
5003
|
-
case "UPDATE_SELECTED_ELEMENTS":
|
|
5004
|
-
this.handleUpdateSelectedElements(payload);
|
|
5005
|
-
break;
|
|
5006
|
-
// 新增的消息类型
|
|
5007
|
-
case "GET_ELEMENT_AT_POINT":
|
|
5008
|
-
this.handleGetElementAtPoint(payload);
|
|
5009
|
-
break;
|
|
5010
|
-
case "FIND_ELEMENTS_BY_LOCATION":
|
|
5011
|
-
this.handleFindElementsByLocation(payload);
|
|
5012
|
-
break;
|
|
5013
|
-
case "SET_ELEMENT_ATTRIBUTES":
|
|
5014
|
-
this.handleSetElementAttributes(payload);
|
|
5015
|
-
break;
|
|
5016
|
-
case "ENABLE_TEXT_EDITING":
|
|
5017
|
-
this.handleEnableTextEditing(payload);
|
|
5018
|
-
break;
|
|
5019
|
-
case "HOVER_ELEMENT_BY_SELECTOR":
|
|
5020
|
-
this.handleHoverElementBySelector(payload);
|
|
5021
|
-
break;
|
|
5022
|
-
case "UNHOVER_ELEMENT":
|
|
5023
|
-
this.handleUnhoverElement();
|
|
5024
|
-
break;
|
|
5025
|
-
// 组件树相关消息
|
|
5026
|
-
case "REQUEST_COMPONENT_TREE":
|
|
5027
|
-
this.handleRequestComponentTree();
|
|
5028
|
-
break;
|
|
5029
|
-
case "GET_PARENT_ELEMENT":
|
|
5030
|
-
this.handleGetParentElement(payload);
|
|
5031
|
-
break;
|
|
5032
|
-
// 样式相关消息
|
|
5033
|
-
case "SET_STYLESHEET":
|
|
5034
|
-
this.handleSetStylesheet(payload);
|
|
5035
|
-
break;
|
|
5036
|
-
default:
|
|
5037
|
-
break;
|
|
5038
|
-
}
|
|
5039
|
-
} catch (error) {
|
|
5040
|
-
console.error("[MessageBridge] \u5904\u7406\u6D88\u606F\u5931\u8D25:", error);
|
|
5041
|
-
this.sendMessage({
|
|
5042
|
-
type: "ERROR_EVENT",
|
|
5043
|
-
payload: {
|
|
5044
|
-
type: "message_handling",
|
|
5045
|
-
originalMessage: message,
|
|
5046
|
-
error: error instanceof Error ? error.message : String(error)
|
|
5047
|
-
},
|
|
5048
|
-
timestamp: Date.now()
|
|
5049
|
-
});
|
|
5050
|
-
}
|
|
5051
|
-
}
|
|
5052
|
-
/** ----------------- 选择器相关消息处理 ----------------- */
|
|
5053
|
-
/**
|
|
5054
|
-
* 处理切换选择器
|
|
5055
|
-
*/
|
|
5056
|
-
handleToggleSelector(payload) {
|
|
5057
|
-
if (!this.elementSelector) return;
|
|
5058
|
-
const shouldActivate = !!payload;
|
|
5059
|
-
if (shouldActivate) {
|
|
5060
|
-
this.elementSelector.enableSelector();
|
|
5061
|
-
} else {
|
|
5062
|
-
this.elementSelector.disableSelector();
|
|
5063
|
-
}
|
|
5064
|
-
}
|
|
5065
|
-
/**
|
|
5066
|
-
* 处理获取选择器状态
|
|
5067
|
-
*/
|
|
5068
|
-
handleGetSelectorState() {
|
|
5069
|
-
if (!this.elementSelector) return;
|
|
5070
|
-
const state = this.elementSelector.getSelectorState();
|
|
5071
|
-
this.sendMessage({
|
|
5072
|
-
type: "SELECTOR_EVENT",
|
|
5073
|
-
payload: {
|
|
5074
|
-
type: "state_response",
|
|
5075
|
-
...state
|
|
5076
|
-
},
|
|
5077
|
-
timestamp: Date.now()
|
|
5078
|
-
});
|
|
5079
|
-
}
|
|
5080
|
-
/**
|
|
5081
|
-
* 处理启用元素选择器
|
|
5082
|
-
*/
|
|
5083
|
-
handleEnableElementSelector() {
|
|
5084
|
-
if (!this.elementSelector) return;
|
|
5085
|
-
this.elementSelector.enableSelector();
|
|
5086
|
-
}
|
|
5087
|
-
/**
|
|
5088
|
-
* 处理禁用元素选择器
|
|
5089
|
-
*/
|
|
5090
|
-
handleDisableElementSelector() {
|
|
5091
|
-
if (!this.elementSelector) return;
|
|
5092
|
-
this.elementSelector.disableSelector();
|
|
5093
|
-
}
|
|
5094
|
-
/** ----------------- 元素操作消息处理 ----------------- */
|
|
5095
|
-
/**
|
|
5096
|
-
* 处理通过 ID 高亮元素
|
|
5097
|
-
*/
|
|
5098
|
-
handleHoverElementById(payload) {
|
|
5099
|
-
if (!this.elementSelector || !payload?.id) return;
|
|
5100
|
-
const selector = `#${payload.id}`;
|
|
5101
|
-
this.elementSelector.highlightElementBySelector(selector);
|
|
5102
|
-
}
|
|
5103
|
-
/**
|
|
5104
|
-
* 处理通过 ID 取消高亮元素
|
|
5105
|
-
*/
|
|
5106
|
-
handleUnhoverElementById(payload) {
|
|
5107
|
-
if (!this.elementSelector || !payload?.id) return;
|
|
5108
|
-
const selector = `#${payload.id}`;
|
|
5109
|
-
this.elementSelector.unhighlightElementBySelector(selector);
|
|
5110
|
-
}
|
|
5111
|
-
/**
|
|
5112
|
-
* 处理高亮元素请求
|
|
5113
|
-
*/
|
|
5114
|
-
handleHoverElementRequested(payload) {
|
|
5115
|
-
if (!this.elementSelector || !payload?.selector) return;
|
|
5116
|
-
this.elementSelector.highlightElementBySelector(payload.selector);
|
|
5117
|
-
}
|
|
5118
|
-
/**
|
|
5119
|
-
* 处理取消高亮元素请求
|
|
5120
|
-
*/
|
|
5121
|
-
handleUnhoverElementRequested(payload) {
|
|
5122
|
-
if (!this.elementSelector || !payload?.selector) return;
|
|
5123
|
-
this.elementSelector.unhighlightElementBySelector(payload.selector);
|
|
5124
|
-
}
|
|
5125
|
-
/**
|
|
5126
|
-
* 处理设置元素内容
|
|
5127
|
-
*/
|
|
5128
|
-
handleSetElementContent(payload) {
|
|
5129
|
-
if (!payload?.selector || !payload?.content) return;
|
|
5130
|
-
const elements = document.querySelectorAll(payload.selector);
|
|
5131
|
-
elements.forEach((element) => {
|
|
5132
|
-
if (element instanceof HTMLElement) {
|
|
5133
|
-
element.innerHTML = payload.content;
|
|
5134
|
-
}
|
|
5135
|
-
});
|
|
5136
|
-
this.sendMessage({
|
|
5137
|
-
type: "ELEMENT_EVENT",
|
|
5138
|
-
payload: {
|
|
5139
|
-
type: "content_updated",
|
|
5140
|
-
selector: payload.selector,
|
|
5141
|
-
content: payload.content,
|
|
5142
|
-
elementsUpdated: elements.length
|
|
5143
|
-
},
|
|
5144
|
-
timestamp: Date.now()
|
|
5145
|
-
});
|
|
5146
|
-
}
|
|
5147
|
-
/**
|
|
5148
|
-
* 处理设置元素属性
|
|
5149
|
-
*/
|
|
5150
|
-
handleSetElementAttrs(payload) {
|
|
5151
|
-
if (!payload?.selector || !payload?.attrs) return;
|
|
5152
|
-
const elements = document.querySelectorAll(payload.selector);
|
|
5153
|
-
elements.forEach((element) => {
|
|
5154
|
-
Object.entries(payload.attrs).forEach(([key, value]) => {
|
|
5155
|
-
element.setAttribute(key, String(value));
|
|
5156
|
-
});
|
|
5157
|
-
});
|
|
5158
|
-
this.sendMessage({
|
|
5159
|
-
type: "ELEMENT_EVENT",
|
|
5160
|
-
payload: {
|
|
5161
|
-
type: "attrs_updated",
|
|
5162
|
-
selector: payload.selector,
|
|
5163
|
-
attrs: payload.attrs,
|
|
5164
|
-
elementsUpdated: elements.length
|
|
5165
|
-
},
|
|
5166
|
-
timestamp: Date.now()
|
|
5167
|
-
});
|
|
5168
|
-
}
|
|
5169
|
-
/**
|
|
5170
|
-
* 处理复制元素请求
|
|
5171
|
-
*/
|
|
5172
|
-
handleDuplicateElementRequested(payload) {
|
|
5173
|
-
if (!payload?.selector) return;
|
|
5174
|
-
const element = document.querySelector(payload.selector);
|
|
5175
|
-
if (element && element.parentElement) {
|
|
5176
|
-
const clone = element.cloneNode(true);
|
|
5177
|
-
clone.setAttribute("data-duplicated", "true");
|
|
5178
|
-
element.parentElement.appendChild(clone);
|
|
5179
|
-
this.sendMessage({
|
|
5180
|
-
type: "ELEMENT_EVENT",
|
|
5181
|
-
payload: {
|
|
5182
|
-
type: "duplicated",
|
|
5183
|
-
originalSelector: payload.selector,
|
|
5184
|
-
duplicatedElement: this.getElementInfo(clone)
|
|
5185
|
-
},
|
|
5186
|
-
timestamp: Date.now()
|
|
5187
|
-
});
|
|
5188
|
-
}
|
|
5189
|
-
}
|
|
5190
|
-
/**
|
|
5191
|
-
* 处理编辑文本请求
|
|
5192
|
-
*/
|
|
5193
|
-
handleEditTextRequested(payload) {
|
|
5194
|
-
if (!payload?.selector) return;
|
|
5195
|
-
const element = document.querySelector(payload.selector);
|
|
5196
|
-
if (element instanceof HTMLElement) {
|
|
5197
|
-
element.setAttribute("contenteditable", "true");
|
|
5198
|
-
element.focus();
|
|
5199
|
-
const handleInput = () => {
|
|
5200
|
-
this.sendMessage({
|
|
5201
|
-
type: "ELEMENT_EVENT",
|
|
5202
|
-
payload: {
|
|
5203
|
-
type: "text_updated",
|
|
5204
|
-
selector: payload.selector,
|
|
5205
|
-
content: element.innerText
|
|
5206
|
-
},
|
|
5207
|
-
timestamp: Date.now()
|
|
5208
|
-
});
|
|
5209
|
-
};
|
|
5210
|
-
const handleBlur = () => {
|
|
5211
|
-
element.removeAttribute("contenteditable");
|
|
5212
|
-
element.removeEventListener("input", handleInput);
|
|
5213
|
-
element.removeEventListener("blur", handleBlur);
|
|
5214
|
-
this.sendMessage({
|
|
5215
|
-
type: "ELEMENT_EVENT",
|
|
5216
|
-
payload: {
|
|
5217
|
-
type: "edit_completed",
|
|
5218
|
-
selector: payload.selector,
|
|
5219
|
-
finalContent: element.innerText
|
|
5220
|
-
},
|
|
5221
|
-
timestamp: Date.now()
|
|
5222
|
-
});
|
|
5223
|
-
};
|
|
5224
|
-
element.addEventListener("input", handleInput);
|
|
5225
|
-
element.addEventListener("blur", handleBlur);
|
|
5226
|
-
}
|
|
5227
|
-
}
|
|
5228
|
-
/**
|
|
5229
|
-
* 处理更新选中元素
|
|
5230
|
-
*/
|
|
5231
|
-
handleUpdateSelectedElements(payload) {
|
|
5232
|
-
if (!this.elementSelector || !Array.isArray(payload)) return;
|
|
5233
|
-
this.elementSelector.updateSelectedElements(payload);
|
|
5234
|
-
this.sendMessage({
|
|
5235
|
-
type: "ELEMENT_EVENT",
|
|
5236
|
-
payload: {
|
|
5237
|
-
type: "selected_elements_updated",
|
|
5238
|
-
selectedElements: payload,
|
|
5239
|
-
count: payload.length
|
|
5240
|
-
},
|
|
5241
|
-
timestamp: Date.now()
|
|
5242
|
-
});
|
|
5243
|
-
}
|
|
5244
|
-
/** ----------------- 组件树相关消息处理 ----------------- */
|
|
5245
|
-
/**
|
|
5246
|
-
* 处理请求组件树
|
|
5247
|
-
*/
|
|
5248
|
-
handleRequestComponentTree() {
|
|
5249
|
-
if (!this.componentTreeGenerator) return;
|
|
5250
|
-
try {
|
|
5251
|
-
const rootElement = document.querySelector("#root") || document.body;
|
|
5252
|
-
const componentTree = this.componentTreeGenerator.generateComponentTree(rootElement);
|
|
5253
|
-
this.sendMessage({
|
|
5254
|
-
type: "COMPONENT_EVENT",
|
|
5255
|
-
payload: {
|
|
5256
|
-
type: "tree_response",
|
|
5257
|
-
...componentTree
|
|
5258
|
-
},
|
|
5259
|
-
timestamp: Date.now()
|
|
5260
|
-
});
|
|
5261
|
-
} catch (error) {
|
|
5262
|
-
const originalConsole = getOriginalConsole2();
|
|
5263
|
-
originalConsole.error("[MessageBridge] \u751F\u6210\u7EC4\u4EF6\u6811\u5931\u8D25:", error);
|
|
5264
|
-
this.sendMessage({
|
|
5265
|
-
type: "COMPONENT_EVENT",
|
|
5266
|
-
payload: {
|
|
5267
|
-
type: "tree_error",
|
|
5268
|
-
error: error instanceof Error ? error.message : String(error)
|
|
5269
|
-
},
|
|
5270
|
-
timestamp: Date.now()
|
|
5271
|
-
});
|
|
5272
|
-
}
|
|
5273
|
-
}
|
|
5274
|
-
/**
|
|
5275
|
-
* 处理获取父元素
|
|
4306
|
+
* 处理获取父元素
|
|
5276
4307
|
*/
|
|
5277
4308
|
handleGetParentElement(payload) {
|
|
5278
4309
|
if (!payload?.selector) return;
|
|
@@ -5364,11 +4395,9 @@ var MessageBridge = class {
|
|
|
5364
4395
|
if (dataTestId) return `[data-testid="${dataTestId}"]`;
|
|
5365
4396
|
const dataHowoneId = element.getAttribute("data-howone-id");
|
|
5366
4397
|
if (dataHowoneId) return `[data-howone-id="${dataHowoneId}"]`;
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
return `.${classes[0]}`;
|
|
5371
|
-
}
|
|
4398
|
+
const classes = getElementClasses(element);
|
|
4399
|
+
if (classes.length > 0) {
|
|
4400
|
+
return `.${classes[0]}`;
|
|
5372
4401
|
}
|
|
5373
4402
|
return element.tagName.toLowerCase();
|
|
5374
4403
|
}
|
|
@@ -5396,106 +4425,6 @@ var MessageBridge = class {
|
|
|
5396
4425
|
timestamp: Date.now()
|
|
5397
4426
|
});
|
|
5398
4427
|
}
|
|
5399
|
-
/** ----------------- 新增的消息处理方法 ----------------- */
|
|
5400
|
-
/**
|
|
5401
|
-
* 处理获取鼠标位置的元素
|
|
5402
|
-
*/
|
|
5403
|
-
handleGetElementAtPoint(payload) {
|
|
5404
|
-
if (!this.elementSelector) return;
|
|
5405
|
-
const element = this.elementSelector.getElementAtPoint(payload?.x, payload?.y);
|
|
5406
|
-
this.sendMessage({
|
|
5407
|
-
type: "ELEMENT_EVENT",
|
|
5408
|
-
payload: {
|
|
5409
|
-
type: "at_point_response",
|
|
5410
|
-
element: element ? this.getElementInfo(element) : null,
|
|
5411
|
-
coordinates: { x: payload?.x, y: payload?.y }
|
|
5412
|
-
},
|
|
5413
|
-
timestamp: Date.now()
|
|
5414
|
-
});
|
|
5415
|
-
}
|
|
5416
|
-
/**
|
|
5417
|
-
* 处理根据位置查找元素
|
|
5418
|
-
*/
|
|
5419
|
-
handleFindElementsByLocation(payload) {
|
|
5420
|
-
if (!this.elementSelector || !payload?.filePath || !payload?.lineNumber) return;
|
|
5421
|
-
const elements = this.elementSelector.findElementsByLocation(payload.filePath, payload.lineNumber);
|
|
5422
|
-
this.sendMessage({
|
|
5423
|
-
type: "ELEMENT_EVENT",
|
|
5424
|
-
payload: {
|
|
5425
|
-
type: "elements_by_location_response",
|
|
5426
|
-
elements: elements.map((el) => this.getElementInfo(el)),
|
|
5427
|
-
location: {
|
|
5428
|
-
filePath: payload.filePath,
|
|
5429
|
-
lineNumber: payload.lineNumber
|
|
5430
|
-
}
|
|
5431
|
-
},
|
|
5432
|
-
timestamp: Date.now()
|
|
5433
|
-
});
|
|
5434
|
-
}
|
|
5435
|
-
/**
|
|
5436
|
-
* 处理设置元素属性(新版本)
|
|
5437
|
-
*/
|
|
5438
|
-
handleSetElementAttributes(payload) {
|
|
5439
|
-
if (!this.elementSelector || !payload?.selector || !payload?.attributes) return;
|
|
5440
|
-
const success = this.elementSelector.setElementAttributes(payload.selector, payload.attributes);
|
|
5441
|
-
this.sendMessage({
|
|
5442
|
-
type: "ELEMENT_EVENT",
|
|
5443
|
-
payload: {
|
|
5444
|
-
type: "attributes_set_response",
|
|
5445
|
-
success,
|
|
5446
|
-
selector: payload.selector,
|
|
5447
|
-
attributes: payload.attributes
|
|
5448
|
-
},
|
|
5449
|
-
timestamp: Date.now()
|
|
5450
|
-
});
|
|
5451
|
-
}
|
|
5452
|
-
/**
|
|
5453
|
-
* 处理启用文本编辑
|
|
5454
|
-
*/
|
|
5455
|
-
handleEnableTextEditing(payload) {
|
|
5456
|
-
if (!this.elementSelector || !payload?.selector) return;
|
|
5457
|
-
const success = this.elementSelector.enableTextEditing(payload.selector);
|
|
5458
|
-
this.sendMessage({
|
|
5459
|
-
type: "ELEMENT_EVENT",
|
|
5460
|
-
payload: {
|
|
5461
|
-
type: "text_editing_enabled_response",
|
|
5462
|
-
success,
|
|
5463
|
-
selector: payload.selector
|
|
5464
|
-
},
|
|
5465
|
-
timestamp: Date.now()
|
|
5466
|
-
});
|
|
5467
|
-
}
|
|
5468
|
-
/**
|
|
5469
|
-
* 处理通过选择器悬停元素
|
|
5470
|
-
*/
|
|
5471
|
-
handleHoverElementBySelector(payload) {
|
|
5472
|
-
if (!this.elementSelector || !payload?.selector) return;
|
|
5473
|
-
const success = this.elementSelector.hoverElementBySelector(payload.selector);
|
|
5474
|
-
this.sendMessage({
|
|
5475
|
-
type: "ELEMENT_EVENT",
|
|
5476
|
-
payload: {
|
|
5477
|
-
type: "hovered_by_selector_response",
|
|
5478
|
-
success,
|
|
5479
|
-
selector: payload.selector
|
|
5480
|
-
},
|
|
5481
|
-
timestamp: Date.now()
|
|
5482
|
-
});
|
|
5483
|
-
}
|
|
5484
|
-
/**
|
|
5485
|
-
* 处理取消悬停元素
|
|
5486
|
-
*/
|
|
5487
|
-
handleUnhoverElement() {
|
|
5488
|
-
if (!this.elementSelector) return;
|
|
5489
|
-
this.elementSelector.unhoverElement();
|
|
5490
|
-
this.sendMessage({
|
|
5491
|
-
type: "ELEMENT_EVENT",
|
|
5492
|
-
payload: {
|
|
5493
|
-
type: "unhovered_response",
|
|
5494
|
-
success: true
|
|
5495
|
-
},
|
|
5496
|
-
timestamp: Date.now()
|
|
5497
|
-
});
|
|
5498
|
-
}
|
|
5499
4428
|
/** ----------------- 统一消息发送管理方法 ----------------- */
|
|
5500
4429
|
/**
|
|
5501
4430
|
* 获取统一的消息发送器实例
|
|
@@ -5529,7 +4458,6 @@ var MessageBridge = class {
|
|
|
5529
4458
|
window.removeEventListener("message", this.messageListener);
|
|
5530
4459
|
this.messageListener = void 0;
|
|
5531
4460
|
}
|
|
5532
|
-
console.log("[MessageBridge] \u6D88\u606F\u6865\u63A5\u5668\u5DF2\u9500\u6BC1");
|
|
5533
4461
|
}
|
|
5534
4462
|
};
|
|
5535
4463
|
|
|
@@ -5557,7 +4485,6 @@ var ErrorHandler = class {
|
|
|
5557
4485
|
enableInteractionTracking: true
|
|
5558
4486
|
};
|
|
5559
4487
|
this.config = { ...this.config, ...options };
|
|
5560
|
-
console.log("[ErrorHandler] \u5F00\u59CB\u521D\u59CB\u5316\u7EDF\u4E00\u9519\u8BEF\u5904\u7406\u5668...");
|
|
5561
4488
|
this.messageSender = createDefaultMessageSender({
|
|
5562
4489
|
addTimestamp: true,
|
|
5563
4490
|
enableDebugLog: false
|
|
@@ -5565,16 +4492,13 @@ var ErrorHandler = class {
|
|
|
5565
4492
|
const sendMessage = this.messageSender.createSendFunction();
|
|
5566
4493
|
this.errorTracking = new ErrorTracking(sendMessage);
|
|
5567
4494
|
this.interactionTracking = new InteractionTracking(sendMessage);
|
|
5568
|
-
this.elementSelector = new ElementSelector2(sendMessage);
|
|
5569
4495
|
this.messageBridge = new MessageBridge();
|
|
5570
4496
|
this.viewDetector = new ViewDetector();
|
|
5571
4497
|
this.hardRefreshManager = new HardRefreshManager(GLOBAL_CONFIG.ALLOWED_ORIGINS);
|
|
5572
4498
|
this.componentTreeGenerator = new ComponentTreeGenerator();
|
|
5573
4499
|
if (this.config.enableViteHMR && ViteHMRDetector.isViteEnvironment()) {
|
|
5574
4500
|
this.viteHMRDetector = new ViteHMRDetector(sendMessage);
|
|
5575
|
-
console.log("[ErrorHandler] Vite HMR \u68C0\u6D4B\u5668\u5DF2\u521D\u59CB\u5316");
|
|
5576
4501
|
}
|
|
5577
|
-
console.log("[ErrorHandler] \u6A21\u5757\u521D\u59CB\u5316\u5B8C\u6210");
|
|
5578
4502
|
}
|
|
5579
4503
|
/** ----------------- 主要初始化方法 ----------------- */
|
|
5580
4504
|
/**
|
|
@@ -5586,12 +4510,10 @@ var ErrorHandler = class {
|
|
|
5586
4510
|
return;
|
|
5587
4511
|
}
|
|
5588
4512
|
try {
|
|
5589
|
-
console.log("[ErrorHandler] \u5F00\u59CB\u521D\u59CB\u5316\u5404\u4E2A\u6A21\u5757...");
|
|
5590
4513
|
this.initializeCore();
|
|
5591
4514
|
this.setupModuleIntegration();
|
|
5592
4515
|
this.enableFeatures();
|
|
5593
4516
|
this.initialized = true;
|
|
5594
|
-
console.log("[ErrorHandler] \u521D\u59CB\u5316\u5B8C\u6210");
|
|
5595
4517
|
} catch (error) {
|
|
5596
4518
|
console.error("[ErrorHandler] \u521D\u59CB\u5316\u5931\u8D25:", error);
|
|
5597
4519
|
throw error;
|
|
@@ -5604,7 +4526,6 @@ var ErrorHandler = class {
|
|
|
5604
4526
|
this.initializeGlobalState();
|
|
5605
4527
|
this.setupDebugEndpoint();
|
|
5606
4528
|
this.errorTracking.initialize();
|
|
5607
|
-
console.log("[ErrorHandler] \u6838\u5FC3\u529F\u80FD\u521D\u59CB\u5316\u5B8C\u6210");
|
|
5608
4529
|
}
|
|
5609
4530
|
/**
|
|
5610
4531
|
* 初始化全局状态
|
|
@@ -5616,7 +4537,6 @@ var ErrorHandler = class {
|
|
|
5616
4537
|
if (!window.__AUTO_ENGINEER_INTERACTION_TRAIL__) {
|
|
5617
4538
|
window.__AUTO_ENGINEER_INTERACTION_TRAIL__ = [];
|
|
5618
4539
|
}
|
|
5619
|
-
console.log("[ErrorHandler] \u5168\u5C40\u72B6\u6001\u521D\u59CB\u5316\u5B8C\u6210");
|
|
5620
4540
|
}
|
|
5621
4541
|
/**
|
|
5622
4542
|
* 设置调试端点
|
|
@@ -5636,28 +4556,22 @@ var ErrorHandler = class {
|
|
|
5636
4556
|
* 设置模块间的协作
|
|
5637
4557
|
*/
|
|
5638
4558
|
setupModuleIntegration() {
|
|
5639
|
-
this.messageBridge.setElementSelector(this.elementSelector);
|
|
5640
4559
|
this.messageBridge.setComponentTreeGenerator(this.componentTreeGenerator);
|
|
5641
4560
|
this.errorTracking.setViewDetector(this.viewDetector);
|
|
5642
4561
|
this.errorTracking.setInteractionTracking(this.interactionTracking);
|
|
5643
|
-
console.log("[ErrorHandler] \u6A21\u5757\u96C6\u6210\u8BBE\u7F6E\u5B8C\u6210");
|
|
5644
4562
|
}
|
|
5645
4563
|
/**
|
|
5646
4564
|
* 启用功能模块
|
|
5647
4565
|
*/
|
|
5648
4566
|
enableFeatures() {
|
|
5649
|
-
console.log("[ErrorHandler] \u542F\u7528\u529F\u80FD\u6A21\u5757...");
|
|
5650
4567
|
if (this.config.enableInteractionTracking) {
|
|
5651
4568
|
this.interactionTracking.startTracking();
|
|
5652
|
-
console.log("[ErrorHandler] \u4EA4\u4E92\u8FFD\u8E2A\u5DF2\u542F\u7528");
|
|
5653
4569
|
}
|
|
5654
4570
|
if (this.viteHMRDetector) {
|
|
5655
4571
|
this.viteHMRDetector.initialize();
|
|
5656
|
-
console.log("[ErrorHandler] Vite HMR \u68C0\u6D4B\u5668\u5DF2\u542F\u7528");
|
|
5657
4572
|
}
|
|
5658
4573
|
this.handleHardRefreshLogic();
|
|
5659
4574
|
this.setupViewDetection();
|
|
5660
|
-
console.log("[ErrorHandler] \u529F\u80FD\u6A21\u5757\u542F\u7528\u5B8C\u6210");
|
|
5661
4575
|
}
|
|
5662
4576
|
/**
|
|
5663
4577
|
* 处理硬刷新逻辑
|
|
@@ -5666,7 +4580,6 @@ var ErrorHandler = class {
|
|
|
5666
4580
|
HardRefreshManager.cleanupRefreshParams();
|
|
5667
4581
|
const refreshStats = HardRefreshManager.getRefreshStats();
|
|
5668
4582
|
if (refreshStats.isHardRefresh) {
|
|
5669
|
-
console.log("[ErrorHandler] \u68C0\u6D4B\u5230\u786C\u5237\u65B0:", refreshStats);
|
|
5670
4583
|
this.messageSender.send({
|
|
5671
4584
|
type: "SYSTEM_EVENT",
|
|
5672
4585
|
payload: {
|
|
@@ -5687,7 +4600,6 @@ var ErrorHandler = class {
|
|
|
5687
4600
|
const currentView = this.viewDetector.getCurrentViewInfo();
|
|
5688
4601
|
if (currentView.title !== lastViewTitle) {
|
|
5689
4602
|
lastViewTitle = currentView.title;
|
|
5690
|
-
console.log("[ErrorHandler] \u89C6\u56FE\u53D8\u5316:", currentView);
|
|
5691
4603
|
}
|
|
5692
4604
|
};
|
|
5693
4605
|
setInterval(checkViewChange, 1e3);
|
|
@@ -5720,12 +4632,6 @@ var ErrorHandler = class {
|
|
|
5720
4632
|
getErrorStats() {
|
|
5721
4633
|
return this.errorTracking.getErrorStats();
|
|
5722
4634
|
}
|
|
5723
|
-
/**
|
|
5724
|
-
* 获取选择器状态
|
|
5725
|
-
*/
|
|
5726
|
-
getSelectorState() {
|
|
5727
|
-
return this.elementSelector.getSelectorState();
|
|
5728
|
-
}
|
|
5729
4635
|
/**
|
|
5730
4636
|
* 获取交互历史
|
|
5731
4637
|
*/
|
|
@@ -5759,30 +4665,11 @@ var ErrorHandler = class {
|
|
|
5759
4665
|
isViteEnvironment() {
|
|
5760
4666
|
return ViteHMRDetector.isViteEnvironment();
|
|
5761
4667
|
}
|
|
5762
|
-
/**
|
|
5763
|
-
* 启用元素选择器
|
|
5764
|
-
*/
|
|
5765
|
-
enableElementSelector() {
|
|
5766
|
-
this.elementSelector.enableSelector();
|
|
5767
|
-
}
|
|
5768
|
-
/**
|
|
5769
|
-
* 禁用元素选择器
|
|
5770
|
-
*/
|
|
5771
|
-
disableElementSelector() {
|
|
5772
|
-
this.elementSelector.disableSelector();
|
|
5773
|
-
}
|
|
5774
|
-
/**
|
|
5775
|
-
* 切换元素选择器状态
|
|
5776
|
-
*/
|
|
5777
|
-
toggleElementSelector() {
|
|
5778
|
-
this.elementSelector.toggleSelector();
|
|
5779
|
-
}
|
|
5780
4668
|
/**
|
|
5781
4669
|
* 更新配置
|
|
5782
4670
|
*/
|
|
5783
4671
|
updateConfig(newConfig) {
|
|
5784
4672
|
this.config = { ...this.config, ...newConfig };
|
|
5785
|
-
console.log("[ErrorHandler] \u914D\u7F6E\u5DF2\u66F4\u65B0:", this.config);
|
|
5786
4673
|
}
|
|
5787
4674
|
/**
|
|
5788
4675
|
* 销毁错误处理器
|
|
@@ -5791,7 +4678,6 @@ var ErrorHandler = class {
|
|
|
5791
4678
|
try {
|
|
5792
4679
|
this.errorTracking.destroy();
|
|
5793
4680
|
this.interactionTracking.destroy();
|
|
5794
|
-
this.elementSelector.destroy();
|
|
5795
4681
|
this.messageBridge.destroy();
|
|
5796
4682
|
if (this.viteHMRDetector) {
|
|
5797
4683
|
this.viteHMRDetector.destroy();
|
|
@@ -5801,7 +4687,6 @@ var ErrorHandler = class {
|
|
|
5801
4687
|
this.viewDetector.clearCache();
|
|
5802
4688
|
}
|
|
5803
4689
|
this.initialized = false;
|
|
5804
|
-
console.log("[ErrorHandler] \u5DF2\u9500\u6BC1");
|
|
5805
4690
|
} catch (error) {
|
|
5806
4691
|
const originalConsole = getOriginalConsole3();
|
|
5807
4692
|
originalConsole.error("[ErrorHandler] \u9500\u6BC1\u65F6\u53D1\u751F\u9519\u8BEF:", error);
|
|
@@ -5823,7 +4708,6 @@ var ErrorHandler = class {
|
|
|
5823
4708
|
errorStats: this.getErrorStats(),
|
|
5824
4709
|
currentView: this.getCurrentView(),
|
|
5825
4710
|
interactionHistory: this.getInteractionHistory(),
|
|
5826
|
-
selectorState: this.getSelectorState(),
|
|
5827
4711
|
isViteEnvironment: this.isViteEnvironment(),
|
|
5828
4712
|
timestamp: Date.now()
|
|
5829
4713
|
};
|
|
@@ -5847,7 +4731,6 @@ import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
|
5847
4731
|
var globalErrorHandler = null;
|
|
5848
4732
|
var initializeErrorHandler = () => {
|
|
5849
4733
|
if (!globalErrorHandler) {
|
|
5850
|
-
console.log("[HowOneProvider] \u5728\u6A21\u5757\u9876\u5C42\u521D\u59CB\u5316\u9519\u8BEF\u5904\u7406\u5668...");
|
|
5851
4734
|
globalErrorHandler = new ErrorHandler({
|
|
5852
4735
|
enableViteHMR: true,
|
|
5853
4736
|
enableElementSelector: true,
|
|
@@ -5855,7 +4738,6 @@ var initializeErrorHandler = () => {
|
|
|
5855
4738
|
});
|
|
5856
4739
|
globalErrorHandler.init();
|
|
5857
4740
|
window.__ERROR_HANDLER__ = globalErrorHandler;
|
|
5858
|
-
console.log("[HowOneProvider] \u9519\u8BEF\u5904\u7406\u5668\u5DF2\u5728\u6A21\u5757\u9876\u5C42\u521D\u59CB\u5316\u5B8C\u6210");
|
|
5859
4741
|
}
|
|
5860
4742
|
return globalErrorHandler;
|
|
5861
4743
|
};
|
|
@@ -5883,7 +4765,6 @@ var HowOneProvider = ({
|
|
|
5883
4765
|
urlToken = hashParams.get("access_token") || hashParams.get("token");
|
|
5884
4766
|
}
|
|
5885
4767
|
if (urlToken) {
|
|
5886
|
-
console.log("[HowOneProvider] Token captured from URL, storing to localStorage...");
|
|
5887
4768
|
setToken(urlToken);
|
|
5888
4769
|
setTokenState(urlToken);
|
|
5889
4770
|
setUser(parseUserFromToken(urlToken));
|
|
@@ -5893,7 +4774,6 @@ var HowOneProvider = ({
|
|
|
5893
4774
|
const newSearch = params.toString();
|
|
5894
4775
|
const newUrl = window.location.pathname + (newSearch ? "?" + newSearch : "");
|
|
5895
4776
|
window.history.replaceState({}, "", newUrl);
|
|
5896
|
-
console.log("[HowOneProvider] Token stored successfully, URL cleaned");
|
|
5897
4777
|
}
|
|
5898
4778
|
} catch (e) {
|
|
5899
4779
|
console.error("[HowOneProvider] Failed to capture token from URL:", e);
|
|
@@ -5908,7 +4788,6 @@ var HowOneProvider = ({
|
|
|
5908
4788
|
if (redirectOnUnauthenticated && !token && !user) {
|
|
5909
4789
|
const currentUrl = new URL(window.location.href);
|
|
5910
4790
|
if (!currentUrl.pathname.includes("/auth")) {
|
|
5911
|
-
console.log("[HowOneProvider] No token found, redirecting to auth page...");
|
|
5912
4791
|
try {
|
|
5913
4792
|
const authUrlObj = new URL(authUrl);
|
|
5914
4793
|
const redirectUri = window.location.href;
|
|
@@ -5916,7 +4795,6 @@ var HowOneProvider = ({
|
|
|
5916
4795
|
if (projectId) {
|
|
5917
4796
|
authUrlObj.searchParams.set("project_id", projectId);
|
|
5918
4797
|
}
|
|
5919
|
-
console.log("[HowOneProvider] Redirecting to:", authUrlObj.toString());
|
|
5920
4798
|
window.location.href = authUrlObj.toString();
|
|
5921
4799
|
} catch (error) {
|
|
5922
4800
|
console.error("[HowOneProvider] Failed to build auth URL:", error);
|
|
@@ -7196,7 +6074,6 @@ var SimpleErrorHandler = class {
|
|
|
7196
6074
|
this.setupErrorListeners();
|
|
7197
6075
|
this.setupCompatibility();
|
|
7198
6076
|
this.initialized = true;
|
|
7199
|
-
console.log("[\u7B80\u5316\u9519\u8BEF\u5904\u7406] \u521D\u59CB\u5316\u5B8C\u6210");
|
|
7200
6077
|
}
|
|
7201
6078
|
/**
|
|
7202
6079
|
* 设置错误监听器
|