@howone/sdk 0.2.3 → 0.2.5

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