@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.js CHANGED
@@ -1578,7 +1578,6 @@ var ViteHMRDetector = class {
1578
1578
  if (this.isInitialized) return;
1579
1579
  this.setupViteErrorDetection();
1580
1580
  this.isInitialized = true;
1581
- console.log("[ViteHMRDetector] Vite HMR \u9519\u8BEF\u68C0\u6D4B\u5668\u521D\u59CB\u5316\u5B8C\u6210");
1582
1581
  }
1583
1582
  /**
1584
1583
  * 销毁检测器
@@ -1629,10 +1628,8 @@ var ViteHMRDetector = class {
1629
1628
  setTimeout(() => this.checkForCompileErrors(), 500);
1630
1629
  });
1631
1630
  hot.on("vite:beforeUpdate", () => {
1632
- console.log("[ViteHMRDetector] HMR \u66F4\u65B0\u5F00\u59CB");
1633
1631
  });
1634
1632
  hot.on("vite:afterUpdate", () => {
1635
- console.log("[ViteHMRDetector] HMR \u66F4\u65B0\u5B8C\u6210");
1636
1633
  });
1637
1634
  }
1638
1635
  window.addEventListener("error", (event) => {
@@ -1670,7 +1667,6 @@ var ViteHMRDetector = class {
1670
1667
  payload: errorPayload,
1671
1668
  timestamp: Date.now()
1672
1669
  });
1673
- console.log("[ViteHMRDetector] Vite \u9519\u8BEF\u5DF2\u68C0\u6D4B\u5E76\u62A5\u544A:", errorPayload);
1674
1670
  } catch (err) {
1675
1671
  this.handleFallbackError(errorOverlay, err);
1676
1672
  }
@@ -1943,20 +1939,16 @@ var HardRefreshManager = class {
1943
1939
  clearedStorage: []
1944
1940
  };
1945
1941
  try {
1946
- console.log("[HardRefreshManager] \u5F00\u59CB\u6267\u884C\u786C\u5237\u65B0...");
1947
1942
  if (defaultOptions.clearCaches) {
1948
1943
  const clearedCaches = await this.clearAllCaches();
1949
1944
  result.clearedCaches = clearedCaches;
1950
- console.log(`[HardRefreshManager] \u5DF2\u6E05\u9664 ${clearedCaches.length} \u4E2A\u7F13\u5B58`);
1951
1945
  }
1952
1946
  if (defaultOptions.unregisterServiceWorkers) {
1953
1947
  const unregisteredCount = await this.unregisterServiceWorkers();
1954
1948
  result.unregisteredWorkers = unregisteredCount;
1955
- console.log(`[HardRefreshManager] \u5DF2\u6CE8\u9500 ${unregisteredCount} \u4E2A Service Worker`);
1956
1949
  }
1957
1950
  const clearedStorage = await this.clearStorage(defaultOptions);
1958
1951
  result.clearedStorage = clearedStorage;
1959
- console.log(`[HardRefreshManager] \u5DF2\u6E05\u9664\u5B58\u50A8: ${clearedStorage.join(", ")}`);
1960
1952
  await this.forceReload(defaultOptions);
1961
1953
  result.success = true;
1962
1954
  return result;
@@ -2555,7 +2547,6 @@ var ComponentTreeGenerator = class {
2555
2547
  maxTextLength: 100,
2556
2548
  maxChildren: 50
2557
2549
  };
2558
- console.log("[ComponentTreeGenerator] \u7EC4\u4EF6\u6811\u751F\u6210\u5668\u521D\u59CB\u5316\u5B8C\u6210");
2559
2550
  }
2560
2551
  /** ----------------- 主要生成方法 ----------------- */
2561
2552
  /**
@@ -2564,7 +2555,6 @@ var ComponentTreeGenerator = class {
2564
2555
  generateComponentTree(rootElement) {
2565
2556
  const startTime = Date.now();
2566
2557
  const root = rootElement || document.body;
2567
- console.log("[ComponentTreeGenerator] \u5F00\u59CB\u751F\u6210\u7EC4\u4EF6\u6811...");
2568
2558
  const rootNode = this.generateNodeTree(root, 0);
2569
2559
  const stats = this.calculateTreeStats(rootNode);
2570
2560
  const componentTree = {
@@ -2585,7 +2575,6 @@ var ComponentTreeGenerator = class {
2585
2575
  }
2586
2576
  };
2587
2577
  const generationTime = Date.now() - startTime;
2588
- console.log(`[ComponentTreeGenerator] \u7EC4\u4EF6\u6811\u751F\u6210\u5B8C\u6210\uFF0C\u8017\u65F6 ${generationTime}ms\uFF0C\u8282\u70B9\u6570: ${stats.totalNodes}`);
2589
2578
  return componentTree;
2590
2579
  }
2591
2580
  /**
@@ -2936,7 +2925,6 @@ var ComponentTreeGenerator = class {
2936
2925
  */
2937
2926
  updateConfig(newConfig) {
2938
2927
  this.config = { ...this.config, ...newConfig };
2939
- console.log("[ComponentTreeGenerator] \u914D\u7F6E\u5DF2\u66F4\u65B0:", this.config);
2940
2928
  }
2941
2929
  /**
2942
2930
  * 获取当前配置
@@ -2959,7 +2947,6 @@ var ComponentTreeGenerator = class {
2959
2947
  * 销毁生成器
2960
2948
  */
2961
2949
  destroy() {
2962
- console.log("[ComponentTreeGenerator] \u7EC4\u4EF6\u6811\u751F\u6210\u5668\u5DF2\u9500\u6BC1");
2963
2950
  }
2964
2951
  };
2965
2952
 
@@ -3136,7 +3123,6 @@ var ErrorTracking = class {
3136
3123
  this.viewDetector = null;
3137
3124
  this.interactionTracking = null;
3138
3125
  this.sendMessage = sendMessage;
3139
- this.internalLog("log", "[ErrorTracking] \u9519\u8BEF\u8FFD\u8E2A\u6A21\u5757\u521D\u59CB\u5316\u5B8C\u6210");
3140
3126
  }
3141
3127
  /**
3142
3128
  * 内部日志方法,避免被控制台拦截器捕获
@@ -3172,10 +3158,8 @@ var ErrorTracking = class {
3172
3158
  this.setupConsoleInterception();
3173
3159
  this.setupNetworkMonitoring();
3174
3160
  this.initialized = true;
3175
- this.internalLog("log", "[ErrorTracking] \u9519\u8BEF\u8FFD\u8E2A\u529F\u80FD\u5DF2\u542F\u7528");
3176
3161
  setTimeout(() => {
3177
3162
  this.fullyInitialized = true;
3178
- this.internalLog("log", "[ErrorTracking] \u521D\u59CB\u5316\u5B8C\u6210\uFF0C\u63A7\u5236\u53F0\u62E6\u622A\u5DF2\u9ED8\u8BA4\u542F\u7528");
3179
3163
  }, 1e3);
3180
3164
  }
3181
3165
  /**
@@ -3200,7 +3184,6 @@ var ErrorTracking = class {
3200
3184
  source: "unhandledrejection"
3201
3185
  });
3202
3186
  });
3203
- this.internalLog("log", "[ErrorTracking] \u5168\u5C40\u9519\u8BEF\u76D1\u542C\u5668\u5DF2\u8BBE\u7F6E");
3204
3187
  }
3205
3188
  /**
3206
3189
  * 设置控制台拦截
@@ -3224,7 +3207,6 @@ var ErrorTracking = class {
3224
3207
  }
3225
3208
  };
3226
3209
  });
3227
- this.internalLog("log", "[ErrorTracking] \u63A7\u5236\u53F0\u62E6\u622A\u5DF2\u8BBE\u7F6E");
3228
3210
  }
3229
3211
  /**
3230
3212
  * 安全地将控制台输出转发到父窗口
@@ -3352,7 +3334,6 @@ var ErrorTracking = class {
3352
3334
  throw error;
3353
3335
  }
3354
3336
  };
3355
- this.internalLog("log", "[ErrorTracking] \u7F51\u7EDC\u76D1\u63A7\u5DF2\u8BBE\u7F6E");
3356
3337
  }
3357
3338
  /**
3358
3339
  * 记录网络请求
@@ -3644,14 +3625,12 @@ var ErrorTracking = class {
3644
3625
  */
3645
3626
  enableConsoleInterception() {
3646
3627
  this.fullyInitialized = true;
3647
- this.internalLog("log", "[ErrorTracking] \u624B\u52A8\u542F\u7528\u63A7\u5236\u53F0\u62E6\u622A");
3648
3628
  }
3649
3629
  /**
3650
3630
  * 手动禁用控制台拦截
3651
3631
  */
3652
3632
  disableConsoleInterception() {
3653
3633
  this.fullyInitialized = false;
3654
- this.internalLog("log", "[ErrorTracking] \u624B\u52A8\u7981\u7528\u63A7\u5236\u53F0\u62E6\u622A");
3655
3634
  }
3656
3635
  /**
3657
3636
  * 销毁错误追踪
@@ -3663,10 +3642,32 @@ var ErrorTracking = class {
3663
3642
  }
3664
3643
  });
3665
3644
  this.initialized = false;
3666
- this.internalLog("log", "[ErrorTracking] \u9519\u8BEF\u8FFD\u8E2A\u6A21\u5757\u5DF2\u9500\u6BC1");
3667
3645
  }
3668
3646
  };
3669
3647
 
3648
+ // src/utils/unified-error-handler/utils/SelectorUtils.ts
3649
+ function getElementClasses(element) {
3650
+ const classAttr = element.getAttribute("class");
3651
+ if (classAttr && classAttr.trim().length > 0) {
3652
+ return dedupeAndClean(classAttr.split(/\s+/));
3653
+ }
3654
+ const anyEl = element;
3655
+ if (typeof anyEl.className === "string") {
3656
+ return dedupeAndClean(anyEl.className.split(/\s+/));
3657
+ }
3658
+ if (anyEl.className && typeof anyEl.className.baseVal === "string") {
3659
+ return dedupeAndClean(anyEl.className.baseVal.split(/\s+/));
3660
+ }
3661
+ if (anyEl.classList && anyEl.classList.length > 0) {
3662
+ return dedupeAndClean(Array.from(anyEl.classList));
3663
+ }
3664
+ return [];
3665
+ }
3666
+ function dedupeAndClean(arr) {
3667
+ const cleaned = arr.map((s) => s.trim()).filter(Boolean);
3668
+ return Array.from(new Set(cleaned));
3669
+ }
3670
+
3670
3671
  // src/utils/unified-error-handler/features/InteractionTracking.ts
3671
3672
  var InteractionTracking = class {
3672
3673
  constructor(sendMessage) {
@@ -3690,7 +3691,6 @@ var InteractionTracking = class {
3690
3691
  this.debounceTimers = /* @__PURE__ */ new Map();
3691
3692
  this.eventListeners = [];
3692
3693
  this.sendMessage = sendMessage;
3693
- console.log("[InteractionTracking] \u4EA4\u4E92\u8FFD\u8E2A\u6A21\u5757\u521D\u59CB\u5316\u5B8C\u6210");
3694
3694
  }
3695
3695
  /** ----------------- 主要控制方法 ----------------- */
3696
3696
  /**
@@ -3706,7 +3706,6 @@ var InteractionTracking = class {
3706
3706
  title: document.title,
3707
3707
  timestamp: Date.now()
3708
3708
  });
3709
- console.log("[InteractionTracking] \u4EA4\u4E92\u8FFD\u8E2A\u5DF2\u5F00\u59CB");
3710
3709
  }
3711
3710
  /**
3712
3711
  * 停止追踪
@@ -3715,7 +3714,6 @@ var InteractionTracking = class {
3715
3714
  if (!this.isTracking) return;
3716
3715
  this.removeEventListeners();
3717
3716
  this.isTracking = false;
3718
- console.log("[InteractionTracking] \u4EA4\u4E92\u8FFD\u8E2A\u5DF2\u505C\u6B62");
3719
3717
  }
3720
3718
  /** ----------------- 事件监听器设置 ----------------- */
3721
3719
  /**
@@ -4028,979 +4026,121 @@ var InteractionTracking = class {
4028
4026
  */
4029
4027
  getElementSelector(element) {
4030
4028
  if (element.id) return `#${element.id}`;
4031
- if (element.className) {
4032
- const classes = element.className.split(" ").filter((c) => c.trim());
4033
- if (classes.length > 0) {
4034
- return `.${classes[0]}`;
4035
- }
4029
+ const classes = getElementClasses(element);
4030
+ if (classes.length > 0) {
4031
+ return `.${classes[0]}`;
4036
4032
  }
4037
4033
  const dataTestId = element.getAttribute("data-testid");
4038
4034
  if (dataTestId) return `[data-testid="${dataTestId}"]`;
4039
4035
  const dataId = element.getAttribute("data-id");
4040
- if (dataId) return `[data-id="${dataId}"]`;
4041
- return element.tagName.toLowerCase();
4042
- }
4043
- /**
4044
- * 检查是否为敏感输入
4045
- */
4046
- isSensitiveInput(element) {
4047
- if (!this.trackingConfig.sensitiveInputFilter) return false;
4048
- const sensitiveTypes = ["password", "email", "tel", "ssn", "credit-card"];
4049
- const sensitiveNames = ["password", "email", "phone", "ssn", "credit", "card", "cvv", "pin"];
4050
- return sensitiveTypes.includes(element.type) || sensitiveNames.some(
4051
- (name) => element.name?.toLowerCase().includes(name) || element.placeholder?.toLowerCase().includes(name) || element.id?.toLowerCase().includes(name)
4052
- );
4053
- }
4054
- /**
4055
- * 管理数组长度
4056
- */
4057
- manageArrayLength(array, maxLength) {
4058
- if (array.length > maxLength) {
4059
- array.shift();
4060
- }
4061
- }
4062
- /** ----------------- 公共接口方法 ----------------- */
4063
- /**
4064
- * 获取交互历史
4065
- */
4066
- getInteractionHistory() {
4067
- return [...this.interactions];
4068
- }
4069
- /**
4070
- * 获取最近的交互记录
4071
- */
4072
- getRecentInteractions(count = 8) {
4073
- return this.interactions.slice(-count);
4074
- }
4075
- /**
4076
- * 手动发送交互数据到父窗口(用于测试或特殊情况)
4077
- */
4078
- sendInteractionData() {
4079
- if (this.interactions.length === 0) return;
4080
- this.sendMessage({
4081
- type: "INTERACTION_EVENT",
4082
- payload: {
4083
- type: "summary",
4084
- interactions: this.interactions,
4085
- count: this.interactions.length,
4086
- timeRange: {
4087
- start: this.interactions[0]?.timestamp || Date.now(),
4088
- end: this.interactions[this.interactions.length - 1]?.timestamp || Date.now()
4089
- },
4090
- summary: this.generateInteractionSummary()
4091
- },
4092
- timestamp: Date.now()
4093
- });
4094
- }
4095
- /**
4096
- * 生成交互摘要
4097
- */
4098
- generateInteractionSummary() {
4099
- const summary = {
4100
- totalInteractions: this.interactions.length,
4101
- typeCount: {},
4102
- uniqueElements: /* @__PURE__ */ new Set(),
4103
- timeSpan: 0
4104
- };
4105
- this.interactions.forEach((interaction) => {
4106
- summary.typeCount[interaction.type] = (summary.typeCount[interaction.type] || 0) + 1;
4107
- if (interaction.element) {
4108
- summary.uniqueElements.add(interaction.element);
4109
- }
4110
- });
4111
- if (this.interactions.length > 1) {
4112
- summary.timeSpan = this.interactions[this.interactions.length - 1].timestamp - this.interactions[0].timestamp;
4113
- }
4114
- return {
4115
- ...summary,
4116
- uniqueElements: Array.from(summary.uniqueElements),
4117
- mostCommonType: Object.entries(summary.typeCount).sort(([, a], [, b]) => b - a)[0]?.[0] || "unknown"
4118
- };
4119
- }
4120
- /**
4121
- * 清除交互历史
4122
- */
4123
- clearInteractionHistory() {
4124
- this.interactions = [];
4125
- }
4126
- /**
4127
- * 更新追踪配置
4128
- */
4129
- updateConfig(newConfig) {
4130
- this.trackingConfig = { ...this.trackingConfig, ...newConfig };
4131
- if (this.isTracking) {
4132
- this.removeEventListeners();
4133
- this.setupEventListeners();
4134
- }
4135
- }
4136
- /**
4137
- * 获取追踪状态
4138
- */
4139
- isTrackingActive() {
4140
- return this.isTracking;
4141
- }
4142
- /**
4143
- * 销毁交互追踪
4144
- */
4145
- destroy() {
4146
- this.stopTracking();
4147
- this.interactions = [];
4148
- console.log("[InteractionTracking] \u4EA4\u4E92\u8FFD\u8E2A\u6A21\u5757\u5DF2\u9500\u6BC1");
4149
- }
4150
- };
4151
-
4152
- // src/utils/unified-error-handler/features/ElementSelector.ts
4153
- var ElementSelector2 = class {
4154
- constructor(sendMessage) {
4155
- this.config = { ...DEFAULT_SELECTOR_CONFIG };
4156
- this.isActive = false;
4157
- this.highlightedElement = null;
4158
- this.selectedElements = [];
4159
- this.rootElement = null;
4160
- this.tooltip = null;
4161
- this.styleElement = null;
4162
- this.eventListeners = [];
4163
- this.lastClickTimestamp = 0;
4164
- this.lastClickTarget = null;
4165
- this.mousePosition = { x: 0, y: 0 };
4166
- this.sendMessage = sendMessage;
4167
- this.initializeSelector();
4168
- }
4169
- /** ----------------- 初始化方法 ----------------- */
4170
- /**
4171
- * 初始化选择器
4172
- */
4173
- initializeSelector() {
4174
- this.waitForRootElement();
4175
- this.createTooltip();
4176
- this.createStyles();
4177
- }
4178
- /**
4179
- * 等待根元素加载
4180
- */
4181
- async waitForRootElement() {
4182
- const maxAttempts = 50;
4183
- let attempts = 0;
4184
- while (attempts < maxAttempts) {
4185
- this.rootElement = document.querySelector("#root") || document.body;
4186
- if (this.rootElement) {
4187
- break;
4188
- }
4189
- await new Promise((resolve) => setTimeout(resolve, 100));
4190
- attempts++;
4191
- }
4192
- if (!this.rootElement) {
4193
- this.rootElement = document.body;
4194
- }
4195
- }
4196
- /**
4197
- * 创建工具提示
4198
- */
4199
- createTooltip() {
4200
- this.tooltip = document.createElement("div");
4201
- this.tooltip.className = "element-selector-tooltip";
4202
- this.tooltip.setAttribute("role", "tooltip");
4203
- this.tooltip.style.display = "none";
4204
- document.body.appendChild(this.tooltip);
4205
- }
4206
- /**
4207
- * 创建样式
4208
- */
4209
- createStyles() {
4210
- this.styleElement = document.createElement("style");
4211
- this.styleElement.id = "element-selector-styles";
4212
- this.styleElement.textContent = this.generateCSS();
4213
- document.head.appendChild(this.styleElement);
4214
- }
4215
- /**
4216
- * 生成 CSS 样式
4217
- */
4218
- generateCSS() {
4219
- return `
4220
- .element-selector-tooltip {
4221
- position: fixed;
4222
- z-index: ${this.config.TOOLTIP_Z_INDEX};
4223
- pointer-events: none;
4224
- background-color: ${this.config.TOOLTIP_BACKGROUND};
4225
- color: ${this.config.TOOLTIP_COLOR};
4226
- padding: ${this.config.TOOLTIP_PADDING};
4227
- border-radius: ${this.config.TOOLTIP_BORDER_RADIUS};
4228
- font-size: ${this.config.TOOLTIP_FONT_SIZE};
4229
- font-weight: bold;
4230
- line-height: 1;
4231
- white-space: nowrap;
4232
- box-shadow: 0 2px 4px rgba(0,0,0,0.2);
4233
- transition: opacity 0.2s ease-in-out;
4234
- margin: 0;
4235
- }
4236
-
4237
- [data-element-hovered] {
4238
- position: relative;
4239
- outline: ${this.config.HIGHLIGHT_BORDER_WIDTH} ${this.config.HIGHLIGHT_BORDER_STYLE} ${this.config.HIGHLIGHT_COLOR} !important;
4240
- outline-offset: 0 !important;
4241
- background-color: ${this.config.HIGHLIGHT_COLOR}20 !important;
4242
- z-index: 9999;
4243
- }
4244
-
4245
- [data-element-selected] {
4246
- position: relative;
4247
- outline: ${this.config.SELECTED_BORDER_WIDTH} ${this.config.HIGHLIGHT_BORDER_STYLE} ${this.config.SELECTED_COLOR} !important;
4248
- outline-offset: 3px !important;
4249
- background-color: ${this.config.SELECTED_COLOR}15 !important;
4250
- z-index: 9999;
4251
- }
4252
-
4253
- [data-element-selected][contenteditable] {
4254
- outline: none !important;
4255
- }
4256
-
4257
- [data-element-hovered][data-full-width],
4258
- [data-element-selected][data-full-width] {
4259
- outline-offset: -5px !important;
4260
- }
4261
-
4262
- .element-selector-active {
4263
- cursor: ${this.config.cursor} !important;
4264
- }
4265
-
4266
- .element-selector-active * {
4267
- cursor: ${this.config.cursor} !important;
4268
- }
4269
-
4270
- /* \u963B\u6B62\u539F\u751F hover \u6548\u679C\u7684\u5168\u5C40\u6837\u5F0F */
4271
- body.element-selector-active * {
4272
- /* \u963B\u6B62\u539F\u751F CSS hover \u4F2A\u7C7B\u6548\u679C */
4273
- transition: none !important;
4274
- }
4275
-
4276
- /* \u963B\u6B62\u6240\u6709 hover \u76F8\u5173\u7684 CSS \u4F2A\u7C7B\uFF0C\u4F46\u6392\u9664\u6211\u4EEC\u7684\u9009\u62E9\u5668\u5143\u7D20 */
4277
- body.element-selector-active *:hover:not([data-element-selected]):not([data-element-hovered]) {
4278
- background-color: inherit !important;
4279
- color: inherit !important;
4280
- border-color: inherit !important;
4281
- box-shadow: inherit !important;
4282
- transform: inherit !important;
4283
- opacity: inherit !important;
4284
- filter: inherit !important;
4285
- }
4286
-
4287
- /* \u786E\u4FDD\u6211\u4EEC\u7684\u9009\u62E9\u5668\u6837\u5F0F\u4F18\u5148\u7EA7\u6700\u9AD8 */
4288
- body.element-selector-active [data-element-selected] {
4289
- background-color: ${this.config.SELECTED_COLOR}15 !important;
4290
- outline: ${this.config.SELECTED_BORDER_WIDTH} ${this.config.HIGHLIGHT_BORDER_STYLE} ${this.config.SELECTED_COLOR} !important;
4291
- }
4292
-
4293
- body.element-selector-active [data-element-hovered] {
4294
- background-color: ${this.config.HIGHLIGHT_COLOR}20 !important;
4295
- outline: ${this.config.HIGHLIGHT_BORDER_WIDTH} ${this.config.HIGHLIGHT_BORDER_STYLE} ${this.config.HIGHLIGHT_COLOR} !important;
4296
- }
4297
-
4298
- /* \u786E\u4FDD\u5DE5\u5177\u63D0\u793A\u4E0D\u53D7\u5F71\u54CD */
4299
- body.element-selector-active .element-selector-tooltip {
4300
- pointer-events: none !important;
4301
- }
4302
- `;
4303
- }
4304
- /** ----------------- 选择器状态管理 ----------------- */
4305
- /**
4306
- * 启用选择器
4307
- */
4308
- enableSelector() {
4309
- if (this.isActive) return;
4310
- this.isActive = true;
4311
- document.body.classList.add("element-selector-active");
4312
- this.setupEventListeners();
4313
- this.manageButtonStates(true);
4314
- this.sendMessage({
4315
- type: "SELECTOR_ENABLED",
4316
- payload: { isActive: true }
4317
- });
4318
- }
4319
- /**
4320
- * 禁用选择器
4321
- */
4322
- disableSelector() {
4323
- if (!this.isActive) return;
4324
- this.isActive = false;
4325
- document.body.classList.remove("element-selector-active");
4326
- this.removeEventListeners();
4327
- this.clearHighlight();
4328
- this.clearSelection();
4329
- this.manageButtonStates(false);
4330
- this.hideTooltip();
4331
- this.sendMessage({
4332
- type: "SELECTOR_DISABLED",
4333
- payload: { isActive: false }
4334
- });
4335
- }
4336
- /**
4337
- * 切换选择器状态
4338
- */
4339
- toggleSelector() {
4340
- if (this.isActive) {
4341
- this.disableSelector();
4342
- } else {
4343
- this.enableSelector();
4344
- }
4345
- }
4346
- /**
4347
- * 获取选择器状态
4348
- */
4349
- getSelectorState() {
4350
- return {
4351
- isActive: this.isActive,
4352
- highlightedElement: this.highlightedElement ? this.getElementInfo(this.highlightedElement) : null,
4353
- selectedElements: this.selectedElements.map((el) => this.getElementInfo(el)),
4354
- config: { ...this.config }
4355
- };
4356
- }
4357
- /** ----------------- 事件监听器管理 ----------------- */
4358
- /**
4359
- * 设置事件监听器
4360
- */
4361
- setupEventListeners() {
4362
- this.addEventListenerWithCleanup(document, "mouseover", this.handleMouseOver.bind(this), { passive: true });
4363
- this.addEventListenerWithCleanup(document, "mouseout", this.handleMouseOut.bind(this), { passive: true });
4364
- this.addEventListenerWithCleanup(document, "mousemove", this.trackMousePosition.bind(this), { passive: true });
4365
- this.addEventListenerWithCleanup(document, "click", this.handleClick.bind(this), { capture: true });
4366
- this.addEventListenerWithCleanup(document, "dblclick", this.handleDoubleClick.bind(this), { capture: true });
4367
- this.addEventListenerWithCleanup(window, "scroll", this.handleScroll.bind(this), { passive: true });
4368
- this.addEventListenerWithCleanup(document, "keydown", this.handleKeyDown.bind(this));
4369
- this.addEventListenerWithCleanup(document, "mousedown", this.preventFormInteraction.bind(this), { capture: true });
4370
- this.addEventListenerWithCleanup(document, "submit", this.preventAllInteraction.bind(this), { capture: true });
4371
- this.addEventListenerWithCleanup(document, "touchstart", this.preventAllInteraction.bind(this), { capture: true });
4372
- this.addEventListenerWithCleanup(document, "touchend", this.preventAllInteraction.bind(this), { capture: true });
4373
- }
4374
- /**
4375
- * 添加事件监听器并记录以便清理
4376
- */
4377
- addEventListenerWithCleanup(element, event, handler, options) {
4378
- element.addEventListener(event, handler, options);
4379
- this.eventListeners.push({ element, event, handler, options });
4380
- }
4381
- /**
4382
- * 移除所有事件监听器
4383
- */
4384
- removeEventListeners() {
4385
- this.eventListeners.forEach(({ element, event, handler }) => {
4386
- element.removeEventListener(event, handler);
4387
- });
4388
- this.eventListeners = [];
4389
- }
4390
- /** ----------------- 事件处理方法 ----------------- */
4391
- /**
4392
- * 跟踪鼠标位置
4393
- */
4394
- trackMousePosition(event) {
4395
- this.mousePosition = { x: event.clientX, y: event.clientY };
4396
- }
4397
- /**
4398
- * 处理鼠标悬停
4399
- */
4400
- handleMouseOver(event) {
4401
- if (!this.isActive) return;
4402
- const target = event.target;
4403
- if (!this.isSelectableElement(target)) return;
4404
- this.highlightElement(target);
4405
- this.updateTooltip(target);
4406
- }
4407
- /**
4408
- * 处理鼠标离开
4409
- */
4410
- handleMouseOut(event) {
4411
- if (!this.isActive) return;
4412
- this.clearHighlight();
4413
- this.hideTooltip();
4414
- }
4415
- /**
4416
- * 处理点击
4417
- */
4418
- handleClick(event) {
4419
- if (!this.isActive) return;
4420
- const currentTimestamp = Date.now();
4421
- const target = event.target;
4422
- if (this.lastClickTarget === target && currentTimestamp - this.lastClickTimestamp < 100) {
4423
- event.preventDefault();
4424
- event.stopPropagation();
4425
- return;
4426
- }
4427
- this.lastClickTimestamp = currentTimestamp;
4428
- this.lastClickTarget = target;
4429
- event.preventDefault();
4430
- event.stopPropagation();
4431
- if (!this.isSelectableElement(target)) return;
4432
- if (event.metaKey || event.ctrlKey) {
4433
- this.toggleElementSelection(target);
4434
- } else {
4435
- this.selectElement(target);
4436
- }
4437
- this.sendMessage({
4438
- type: "ELEMENT_CLICKED",
4439
- payload: {
4440
- element: this.getElementInfo(target),
4441
- isMultiSelect: event.metaKey || event.ctrlKey
4442
- }
4443
- });
4444
- }
4445
- /**
4446
- * 处理双击
4447
- */
4448
- handleDoubleClick(event) {
4449
- if (!this.isActive) return;
4450
- event.preventDefault();
4451
- event.stopPropagation();
4452
- const target = event.target;
4453
- if (!this.isSelectableElement(target)) return;
4454
- this.sendMessage({
4455
- type: "ELEMENT_DOUBLE_CLICKED",
4456
- payload: {
4457
- element: this.getElementInfo(target)
4458
- }
4459
- });
4460
- }
4461
- /**
4462
- * 处理滚动
4463
- */
4464
- handleScroll() {
4465
- if (!this.isActive) return;
4466
- this.hideTooltip();
4467
- }
4468
- /**
4469
- * 处理键盘事件
4470
- */
4471
- handleKeyDown(event) {
4472
- if (!this.isActive) return;
4473
- const keyboardEvent = event;
4474
- if (keyboardEvent.key === "Escape") {
4475
- event.preventDefault();
4476
- event.stopPropagation();
4477
- this.disableSelector();
4478
- }
4479
- }
4480
- /**
4481
- * 阻止表单交互
4482
- */
4483
- preventFormInteraction(event) {
4484
- if (!this.isActive) return;
4485
- const target = event.target;
4486
- if (["input", "textarea", "select"].includes(target.tagName.toLowerCase())) {
4487
- event.preventDefault();
4488
- }
4489
- }
4490
- /**
4491
- * 阻止所有交互
4492
- */
4493
- preventAllInteraction(event) {
4494
- if (this.isActive) {
4495
- event.preventDefault();
4496
- event.stopPropagation();
4497
- return false;
4498
- }
4499
- }
4500
- /** ----------------- 元素操作方法 ----------------- */
4501
- /**
4502
- * 高亮元素
4503
- */
4504
- highlightElement(element) {
4505
- this.clearHighlight();
4506
- this.highlightedElement = element;
4507
- element.setAttribute("data-element-hovered", "true");
4508
- if (this.isFullWidthElement(element)) {
4509
- element.setAttribute("data-full-width", "true");
4510
- }
4511
- }
4512
- /**
4513
- * 清除高亮
4514
- */
4515
- clearHighlight() {
4516
- if (this.highlightedElement) {
4517
- this.highlightedElement.removeAttribute("data-element-hovered");
4518
- this.highlightedElement.removeAttribute("data-full-width");
4519
- this.highlightedElement = null;
4520
- }
4521
- }
4522
- /**
4523
- * 选择元素
4524
- */
4525
- selectElement(element) {
4526
- this.clearSelection();
4527
- this.selectedElements = [element];
4528
- element.setAttribute("data-element-selected", "true");
4529
- if (this.isFullWidthElement(element)) {
4530
- element.setAttribute("data-full-width", "true");
4531
- }
4532
- }
4533
- /**
4534
- * 切换元素选择状态
4535
- */
4536
- toggleElementSelection(element) {
4537
- const index = this.selectedElements.indexOf(element);
4538
- if (index > -1) {
4539
- this.selectedElements.splice(index, 1);
4540
- element.removeAttribute("data-element-selected");
4541
- element.removeAttribute("data-full-width");
4542
- } else {
4543
- this.selectedElements.push(element);
4544
- element.setAttribute("data-element-selected", "true");
4545
- if (this.isFullWidthElement(element)) {
4546
- element.setAttribute("data-full-width", "true");
4547
- }
4548
- }
4549
- }
4550
- /**
4551
- * 清除选择
4552
- */
4553
- clearSelection() {
4554
- this.selectedElements.forEach((element) => {
4555
- element.removeAttribute("data-element-selected");
4556
- element.removeAttribute("data-full-width");
4557
- });
4558
- this.selectedElements = [];
4559
- }
4560
- /** ----------------- 工具提示管理 ----------------- */
4561
- /**
4562
- * 更新工具提示
4563
- */
4564
- updateTooltip(element) {
4565
- if (!this.tooltip) return;
4566
- const rect = element.getBoundingClientRect();
4567
- const tagName = element.tagName.toLowerCase();
4568
- this.tooltip.textContent = tagName;
4569
- this.tooltip.style.display = "block";
4570
- const isFullWidth = this.isFullWidthElement(element);
4571
- if (isFullWidth) {
4572
- this.tooltip.style.left = this.config.FULL_WIDTH_TOOLTIP_OFFSET + "px";
4573
- this.tooltip.style.top = this.config.FULL_WIDTH_TOOLTIP_OFFSET + "px";
4574
- } else {
4575
- const top = Math.max(0, rect.top - 30);
4576
- this.tooltip.style.left = `${Math.max(0, rect.left)}px`;
4577
- this.tooltip.style.top = `${top}px`;
4578
- }
4579
- }
4580
- /**
4581
- * 隐藏工具提示
4582
- */
4583
- hideTooltip() {
4584
- if (this.tooltip) {
4585
- this.tooltip.style.display = "none";
4586
- }
4587
- }
4588
- /** ----------------- 按钮状态管理 ----------------- */
4589
- /**
4590
- * 管理按钮状态
4591
- */
4592
- manageButtonStates(enable) {
4593
- if (!this.rootElement) return;
4594
- const buttons = this.rootElement.querySelectorAll('button, input[type="button"], input[type="submit"]');
4595
- if (enable) {
4596
- buttons.forEach((button) => {
4597
- const btn = button;
4598
- if (!btn.disabled) {
4599
- btn.disabled = true;
4600
- btn.setAttribute("data-selector-disabled", "true");
4601
- }
4602
- });
4603
- } else {
4604
- buttons.forEach((button) => {
4605
- const btn = button;
4606
- if (btn.hasAttribute("data-selector-disabled")) {
4607
- btn.disabled = false;
4608
- btn.removeAttribute("data-selector-disabled");
4609
- }
4610
- });
4611
- }
4612
- }
4613
- /** ----------------- 新增的精确代码位置定位方法 ----------------- */
4614
- /**
4615
- * 检查元素是否有 howone ID
4616
- */
4617
- hasHowoneId(element) {
4618
- return element.hasAttribute("data-howone-id");
4619
- }
4620
- /**
4621
- * 解析 howone ID
4622
- */
4623
- parseHowoneId(element) {
4624
- const howoneId = element.getAttribute("data-howone-id");
4625
- if (!howoneId) return null;
4626
- try {
4627
- if (howoneId.includes(":")) {
4628
- const parts = howoneId.split(":");
4629
- if (parts.length >= 2) {
4630
- return {
4631
- filePath: parts[0],
4632
- lineNumber: parseInt(parts[1], 10),
4633
- col: parts[2] ? parseInt(parts[2], 10) : 0
4634
- };
4635
- }
4636
- } else {
4637
- const parsed = JSON.parse(howoneId);
4638
- if (parsed.filePath && parsed.lineNumber) {
4639
- return {
4640
- filePath: parsed.filePath,
4641
- lineNumber: parsed.lineNumber,
4642
- col: parsed.col || 0
4643
- };
4644
- }
4645
- }
4646
- } catch (error) {
4647
- console.warn("[ElementSelector] \u89E3\u6790 data-howone-id \u5931\u8D25:", error);
4648
- }
4649
- return null;
4650
- }
4651
- /**
4652
- * 获取元素的代码位置
4653
- */
4654
- getElementLocation(element) {
4655
- return this.parseHowoneId(element);
4656
- }
4657
- /**
4658
- * 提取元素数据(包含位置信息)
4659
- */
4660
- extractElementData(element) {
4661
- const location = this.getElementLocation(element);
4662
- return {
4663
- id: element.id || void 0,
4664
- className: element.className || void 0,
4665
- textContent: element.textContent?.trim().substring(0, 100) || void 0,
4666
- filePath: location?.filePath,
4667
- lineNumber: location?.lineNumber,
4668
- col: location?.col,
4669
- elementType: element.tagName.toLowerCase(),
4670
- attrs: this.getElementAttributes(element)
4671
- };
4672
- }
4673
- /**
4674
- * 根据代码位置查找元素
4675
- */
4676
- findElementsByLocation(filePath, lineNumber) {
4677
- const elements = [];
4678
- const elementsWithHowoneId = this.rootElement?.querySelectorAll("[data-howone-id]") || [];
4679
- elementsWithHowoneId.forEach((element) => {
4680
- const location = this.getElementLocation(element);
4681
- if (location && location.filePath === filePath && location.lineNumber === lineNumber) {
4682
- elements.push(element);
4683
- }
4684
- });
4685
- return elements;
4686
- }
4687
- /**
4688
- * 获取指定坐标位置的元素
4689
- */
4690
- getElementAtPoint(x, y) {
4691
- const originalDisplay = this.tooltip?.style.display;
4692
- if (this.tooltip) {
4693
- this.tooltip.style.display = "none";
4694
- }
4695
- const element = document.elementFromPoint(x, y);
4696
- if (this.tooltip && originalDisplay) {
4697
- this.tooltip.style.display = originalDisplay;
4698
- }
4699
- return element;
4700
- }
4701
- /** ----------------- 元素编辑功能 ----------------- */
4702
- /**
4703
- * 设置元素内容
4704
- */
4705
- setElementContent(selector, content) {
4706
- try {
4707
- const element = document.querySelector(selector);
4708
- if (!element) return false;
4709
- if (element.tagName.toLowerCase() === "input" || element.tagName.toLowerCase() === "textarea") {
4710
- element.value = content;
4711
- } else {
4712
- element.textContent = content;
4713
- }
4714
- this.sendMessage({
4715
- type: "ELEMENT_CONTENT_UPDATED",
4716
- payload: {
4717
- selector,
4718
- content,
4719
- element: this.getElementInfo(element)
4720
- }
4721
- });
4722
- return true;
4723
- } catch (error) {
4724
- console.error("[ElementSelector] \u8BBE\u7F6E\u5143\u7D20\u5185\u5BB9\u5931\u8D25:", error);
4725
- return false;
4726
- }
4727
- }
4728
- /**
4729
- * 设置元素属性
4730
- */
4731
- setElementAttributes(selector, attributes) {
4732
- try {
4733
- const element = document.querySelector(selector);
4734
- if (!element) return false;
4735
- Object.entries(attributes).forEach(([key, value]) => {
4736
- if (value === null || value === void 0) {
4737
- element.removeAttribute(key);
4738
- } else {
4739
- element.setAttribute(key, value);
4740
- }
4741
- });
4742
- this.sendMessage({
4743
- type: "ELEMENT_ATTRIBUTES_UPDATED",
4744
- payload: {
4745
- selector,
4746
- attributes,
4747
- element: this.getElementInfo(element)
4748
- }
4749
- });
4750
- return true;
4751
- } catch (error) {
4752
- console.error("[ElementSelector] \u8BBE\u7F6E\u5143\u7D20\u5C5E\u6027\u5931\u8D25:", error);
4753
- return false;
4754
- }
4755
- }
4756
- /**
4757
- * 复制元素
4758
- */
4759
- duplicateElement(selector) {
4760
- try {
4761
- const element = document.querySelector(selector);
4762
- if (!element || !element.parentNode) return false;
4763
- const clonedElement = element.cloneNode(true);
4764
- clonedElement.removeAttribute("data-blnk-id");
4765
- element.parentNode.insertBefore(clonedElement, element.nextSibling);
4766
- this.sendMessage({
4767
- type: "ELEMENT_DUPLICATED",
4768
- payload: {
4769
- originalSelector: selector,
4770
- duplicatedElement: this.getElementInfo(clonedElement)
4771
- }
4772
- });
4773
- return true;
4774
- } catch (error) {
4775
- console.error("[ElementSelector] \u590D\u5236\u5143\u7D20\u5931\u8D25:", error);
4776
- return false;
4777
- }
4778
- }
4779
- /**
4780
- * 启用文本编辑
4781
- */
4782
- enableTextEditing(selector) {
4783
- try {
4784
- const element = document.querySelector(selector);
4785
- if (!element) return false;
4786
- element.setAttribute("contenteditable", "true");
4787
- element.setAttribute("data-editing", "true");
4788
- element.focus();
4789
- const handleEditComplete = () => {
4790
- element.removeAttribute("contenteditable");
4791
- element.removeAttribute("data-editing");
4792
- element.removeEventListener("blur", handleEditComplete);
4793
- element.removeEventListener("keydown", handleKeyDown);
4794
- this.sendMessage({
4795
- type: "ELEMENT_TEXT_UPDATED",
4796
- payload: {
4797
- selector,
4798
- content: element.textContent || "",
4799
- element: this.getElementInfo(element)
4800
- }
4801
- });
4802
- };
4803
- const handleKeyDown = (event) => {
4804
- const keyboardEvent = event;
4805
- if (keyboardEvent.key === "Enter" && !keyboardEvent.shiftKey) {
4806
- event.preventDefault();
4807
- handleEditComplete();
4808
- } else if (keyboardEvent.key === "Escape") {
4809
- event.preventDefault();
4810
- handleEditComplete();
4811
- }
4812
- };
4813
- element.addEventListener("blur", handleEditComplete);
4814
- element.addEventListener("keydown", handleKeyDown);
4815
- return true;
4816
- } catch (error) {
4817
- console.error("[ElementSelector] \u542F\u7528\u6587\u672C\u7F16\u8F91\u5931\u8D25:", error);
4818
- return false;
4819
- }
4820
- }
4821
- /** ----------------- 高级交互功能 ----------------- */
4822
- /**
4823
- * 获取父元素
4824
- */
4825
- getParentElement(selector) {
4826
- try {
4827
- const element = document.querySelector(selector);
4828
- return element?.parentElement || null;
4829
- } catch (error) {
4830
- console.error("[ElementSelector] \u83B7\u53D6\u7236\u5143\u7D20\u5931\u8D25:", error);
4831
- return null;
4832
- }
4833
- }
4834
- /**
4835
- * 外部悬停控制 - 通过选择器悬停元素
4836
- */
4837
- hoverElementBySelector(selector) {
4838
- try {
4839
- const element = document.querySelector(selector);
4840
- if (!element) return false;
4841
- this.highlightElement(element);
4842
- this.updateTooltip(element);
4843
- return true;
4844
- } catch (error) {
4845
- console.error("[ElementSelector] \u5916\u90E8\u60AC\u505C\u63A7\u5236\u5931\u8D25:", error);
4846
- return false;
4847
- }
4036
+ if (dataId) return `[data-id="${dataId}"]`;
4037
+ return element.tagName.toLowerCase();
4848
4038
  }
4849
4039
  /**
4850
- * 外部悬停控制 - 取消悬停
4040
+ * 检查是否为敏感输入
4851
4041
  */
4852
- unhoverElement() {
4853
- this.clearHighlight();
4854
- this.hideTooltip();
4042
+ isSensitiveInput(element) {
4043
+ if (!this.trackingConfig.sensitiveInputFilter) return false;
4044
+ const sensitiveTypes = ["password", "email", "tel", "ssn", "credit-card"];
4045
+ const sensitiveNames = ["password", "email", "phone", "ssn", "credit", "card", "cvv", "pin"];
4046
+ return sensitiveTypes.includes(element.type) || sensitiveNames.some(
4047
+ (name) => element.name?.toLowerCase().includes(name) || element.placeholder?.toLowerCase().includes(name) || element.id?.toLowerCase().includes(name)
4048
+ );
4855
4049
  }
4856
- /** ----------------- 辅助方法 ----------------- */
4857
4050
  /**
4858
- * 检查元素是否为全宽元素
4051
+ * 管理数组长度
4859
4052
  */
4860
- isFullWidthElement(element) {
4861
- try {
4862
- const rect = element.getBoundingClientRect();
4863
- return Math.abs(rect.width - window.innerWidth) < 5;
4864
- } catch (error) {
4865
- console.warn("[ElementSelector] \u68C0\u67E5\u5168\u5BBD\u5143\u7D20\u5931\u8D25:", error);
4866
- return false;
4053
+ manageArrayLength(array, maxLength) {
4054
+ if (array.length > maxLength) {
4055
+ array.shift();
4867
4056
  }
4868
4057
  }
4058
+ /** ----------------- 公共接口方法 ----------------- */
4869
4059
  /**
4870
- * 检查元素是否可选择
4060
+ * 获取交互历史
4871
4061
  */
4872
- isSelectableElement(element) {
4873
- if (!element || element === document.body || element === document.documentElement) {
4874
- return false;
4875
- }
4876
- if (this.hasHowoneId(element)) {
4877
- return true;
4878
- }
4879
- if (element.id === "howone-element-tooltip" || element.classList.contains("howone-tooltip")) {
4880
- return false;
4881
- }
4882
- const tagName = element.tagName.toLowerCase();
4883
- if (["script", "style", "meta", "link", "title"].includes(tagName)) {
4884
- return false;
4885
- }
4886
- return true;
4062
+ getInteractionHistory() {
4063
+ return [...this.interactions];
4887
4064
  }
4888
4065
  /**
4889
- * 获取元素信息
4066
+ * 获取最近的交互记录
4890
4067
  */
4891
- getElementInfo(element) {
4892
- const location = this.getElementLocation(element);
4893
- return {
4894
- tagName: element.tagName.toLowerCase(),
4895
- id: element.id || void 0,
4896
- className: element.className || void 0,
4897
- textContent: element.textContent?.trim().substring(0, 100) || void 0,
4898
- attributes: this.getElementAttributes(element),
4899
- selector: this.getElementSelector(element),
4900
- boundingRect: element.getBoundingClientRect(),
4901
- location: location || void 0
4902
- };
4068
+ getRecentInteractions(count = 8) {
4069
+ return this.interactions.slice(-count);
4903
4070
  }
4904
4071
  /**
4905
- * 获取元素属性
4072
+ * 手动发送交互数据到父窗口(用于测试或特殊情况)
4906
4073
  */
4907
- getElementAttributes(element) {
4908
- const attrs = {};
4909
- const importantAttrs = ["id", "class", "data-testid", "data-howone-id", "data-component-path", "data-blnk-id", "href", "src", "type", "name"];
4910
- importantAttrs.forEach((attr) => {
4911
- const value = element.getAttribute(attr);
4912
- if (value) {
4913
- attrs[attr] = value;
4914
- }
4074
+ sendInteractionData() {
4075
+ if (this.interactions.length === 0) return;
4076
+ this.sendMessage({
4077
+ type: "INTERACTION_EVENT",
4078
+ payload: {
4079
+ type: "summary",
4080
+ interactions: this.interactions,
4081
+ count: this.interactions.length,
4082
+ timeRange: {
4083
+ start: this.interactions[0]?.timestamp || Date.now(),
4084
+ end: this.interactions[this.interactions.length - 1]?.timestamp || Date.now()
4085
+ },
4086
+ summary: this.generateInteractionSummary()
4087
+ },
4088
+ timestamp: Date.now()
4915
4089
  });
4916
- return attrs;
4917
4090
  }
4918
4091
  /**
4919
- * 获取元素选择器
4092
+ * 生成交互摘要
4920
4093
  */
4921
- getElementSelector(element) {
4922
- const howoneId = element.getAttribute("data-howone-id");
4923
- if (howoneId) {
4924
- return `[data-howone-id="${howoneId}"]`;
4925
- }
4926
- if (element.id) {
4927
- return `#${element.id}`;
4928
- }
4929
- const dataTestId = element.getAttribute("data-testid");
4930
- if (dataTestId) {
4931
- return `[data-testid="${dataTestId}"]`;
4932
- }
4933
- if (element.className) {
4934
- const classes = element.className.split(" ").filter((c) => c.trim());
4935
- if (classes.length > 0) {
4936
- return `.${classes[0]}`;
4094
+ generateInteractionSummary() {
4095
+ const summary = {
4096
+ totalInteractions: this.interactions.length,
4097
+ typeCount: {},
4098
+ uniqueElements: /* @__PURE__ */ new Set(),
4099
+ timeSpan: 0
4100
+ };
4101
+ this.interactions.forEach((interaction) => {
4102
+ summary.typeCount[interaction.type] = (summary.typeCount[interaction.type] || 0) + 1;
4103
+ if (interaction.element) {
4104
+ summary.uniqueElements.add(interaction.element);
4937
4105
  }
4106
+ });
4107
+ if (this.interactions.length > 1) {
4108
+ summary.timeSpan = this.interactions[this.interactions.length - 1].timestamp - this.interactions[0].timestamp;
4938
4109
  }
4939
- return element.tagName.toLowerCase();
4110
+ return {
4111
+ ...summary,
4112
+ uniqueElements: Array.from(summary.uniqueElements),
4113
+ mostCommonType: Object.entries(summary.typeCount).sort(([, a], [, b]) => b - a)[0]?.[0] || "unknown"
4114
+ };
4940
4115
  }
4941
- /** ----------------- 公共接口方法 ----------------- */
4942
4116
  /**
4943
- * 通过选择器高亮元素
4117
+ * 清除交互历史
4944
4118
  */
4945
- highlightElementBySelector(selector) {
4946
- const element = document.querySelector(selector);
4947
- if (element) {
4948
- this.highlightElement(element);
4949
- }
4119
+ clearInteractionHistory() {
4120
+ this.interactions = [];
4950
4121
  }
4951
4122
  /**
4952
- * 通过选择器取消高亮元素
4123
+ * 更新追踪配置
4953
4124
  */
4954
- unhighlightElementBySelector(selector) {
4955
- const element = document.querySelector(selector);
4956
- if (element && element === this.highlightedElement) {
4957
- this.clearHighlight();
4125
+ updateConfig(newConfig) {
4126
+ this.trackingConfig = { ...this.trackingConfig, ...newConfig };
4127
+ if (this.isTracking) {
4128
+ this.removeEventListeners();
4129
+ this.setupEventListeners();
4958
4130
  }
4959
4131
  }
4960
4132
  /**
4961
- * 更新选中的元素
4962
- */
4963
- updateSelectedElements(elements) {
4964
- this.clearSelection();
4965
- elements.forEach((elementData) => {
4966
- const element = this.findElementByData(elementData);
4967
- if (element) {
4968
- this.selectedElements.push(element);
4969
- element.setAttribute("data-element-selected", "true");
4970
- if (this.isFullWidthElement(element)) {
4971
- element.setAttribute("data-full-width", "true");
4972
- }
4973
- }
4974
- });
4975
- }
4976
- /**
4977
- * 根据数据查找元素
4133
+ * 获取追踪状态
4978
4134
  */
4979
- findElementByData(elementData) {
4980
- if (elementData.blinkId) {
4981
- return document.querySelector(`[data-blnk-id="${elementData.blinkId}"]`);
4982
- }
4983
- if (elementData.id) {
4984
- return document.getElementById(elementData.id);
4985
- }
4986
- if (elementData.selector) {
4987
- return document.querySelector(elementData.selector);
4988
- }
4989
- return null;
4135
+ isTrackingActive() {
4136
+ return this.isTracking;
4990
4137
  }
4991
4138
  /**
4992
- * 销毁选择器
4139
+ * 销毁交互追踪
4993
4140
  */
4994
4141
  destroy() {
4995
- this.disableSelector();
4996
- if (this.tooltip) {
4997
- this.tooltip.remove();
4998
- this.tooltip = null;
4999
- }
5000
- if (this.styleElement) {
5001
- this.styleElement.remove();
5002
- this.styleElement = null;
5003
- }
4142
+ this.stopTracking();
4143
+ this.interactions = [];
5004
4144
  }
5005
4145
  };
5006
4146
 
@@ -5014,7 +4154,6 @@ var getOriginalConsole2 = () => window.__originalConsole || {
5014
4154
  };
5015
4155
  var MessageBridge = class {
5016
4156
  constructor(sendMessage) {
5017
- this.elementSelector = null;
5018
4157
  this.componentTreeGenerator = null;
5019
4158
  this.messageSender = createDefaultMessageSender({
5020
4159
  addTimestamp: true,
@@ -5022,15 +4161,8 @@ var MessageBridge = class {
5022
4161
  });
5023
4162
  this.sendMessage = sendMessage || this.messageSender.createSendFunction();
5024
4163
  this.setupMessageListener();
5025
- console.log("[MessageBridge] \u6D88\u606F\u6865\u63A5\u5668\u521D\u59CB\u5316\u5B8C\u6210");
5026
4164
  }
5027
4165
  /** ----------------- 依赖注入方法 ----------------- */
5028
- /**
5029
- * 设置元素选择器
5030
- */
5031
- setElementSelector(elementSelector2) {
5032
- this.elementSelector = elementSelector2;
5033
- }
5034
4166
  /**
5035
4167
  * 设置组件树生成器
5036
4168
  */
@@ -5068,32 +4200,6 @@ var MessageBridge = class {
5068
4200
  try {
5069
4201
  const { type, payload } = message;
5070
4202
  switch (type) {
5071
- // 选择器相关消息
5072
- case "TOGGLE_SELECTOR":
5073
- this.handleToggleSelector(payload);
5074
- break;
5075
- case "ENABLE_SELECTOR":
5076
- this.handleEnableElementSelector();
5077
- break;
5078
- case "DISABLE_SELECTOR":
5079
- this.handleDisableElementSelector();
5080
- break;
5081
- case "GET_SELECTOR_STATE":
5082
- this.handleGetSelectorState();
5083
- break;
5084
- // 元素操作消息
5085
- case "HOVER_ELEMENT_BY_ID":
5086
- this.handleHoverElementById(payload);
5087
- break;
5088
- case "UNHOVER_ELEMENT_BY_ID":
5089
- this.handleUnhoverElementById(payload);
5090
- break;
5091
- case "HOVER_ELEMENT_REQUESTED":
5092
- this.handleHoverElementRequested(payload);
5093
- break;
5094
- case "UNHOVER_ELEMENT_REQUESTED":
5095
- this.handleUnhoverElementRequested(payload);
5096
- break;
5097
4203
  case "SET_ELEMENT_CONTENT":
5098
4204
  this.handleSetElementContent(payload);
5099
4205
  break;
@@ -5106,28 +4212,6 @@ var MessageBridge = class {
5106
4212
  case "EDIT_TEXT_REQUESTED":
5107
4213
  this.handleEditTextRequested(payload);
5108
4214
  break;
5109
- case "UPDATE_SELECTED_ELEMENTS":
5110
- this.handleUpdateSelectedElements(payload);
5111
- break;
5112
- // 新增的消息类型
5113
- case "GET_ELEMENT_AT_POINT":
5114
- this.handleGetElementAtPoint(payload);
5115
- break;
5116
- case "FIND_ELEMENTS_BY_LOCATION":
5117
- this.handleFindElementsByLocation(payload);
5118
- break;
5119
- case "SET_ELEMENT_ATTRIBUTES":
5120
- this.handleSetElementAttributes(payload);
5121
- break;
5122
- case "ENABLE_TEXT_EDITING":
5123
- this.handleEnableTextEditing(payload);
5124
- break;
5125
- case "HOVER_ELEMENT_BY_SELECTOR":
5126
- this.handleHoverElementBySelector(payload);
5127
- break;
5128
- case "UNHOVER_ELEMENT":
5129
- this.handleUnhoverElement();
5130
- break;
5131
4215
  // 组件树相关消息
5132
4216
  case "REQUEST_COMPONENT_TREE":
5133
4217
  this.handleRequestComponentTree();
@@ -5155,79 +4239,7 @@ var MessageBridge = class {
5155
4239
  });
5156
4240
  }
5157
4241
  }
5158
- /** ----------------- 选择器相关消息处理 ----------------- */
5159
- /**
5160
- * 处理切换选择器
5161
- */
5162
- handleToggleSelector(payload) {
5163
- if (!this.elementSelector) return;
5164
- const shouldActivate = !!payload;
5165
- if (shouldActivate) {
5166
- this.elementSelector.enableSelector();
5167
- } else {
5168
- this.elementSelector.disableSelector();
5169
- }
5170
- }
5171
- /**
5172
- * 处理获取选择器状态
5173
- */
5174
- handleGetSelectorState() {
5175
- if (!this.elementSelector) return;
5176
- const state = this.elementSelector.getSelectorState();
5177
- this.sendMessage({
5178
- type: "SELECTOR_EVENT",
5179
- payload: {
5180
- type: "state_response",
5181
- ...state
5182
- },
5183
- timestamp: Date.now()
5184
- });
5185
- }
5186
- /**
5187
- * 处理启用元素选择器
5188
- */
5189
- handleEnableElementSelector() {
5190
- if (!this.elementSelector) return;
5191
- this.elementSelector.enableSelector();
5192
- }
5193
- /**
5194
- * 处理禁用元素选择器
5195
- */
5196
- handleDisableElementSelector() {
5197
- if (!this.elementSelector) return;
5198
- this.elementSelector.disableSelector();
5199
- }
5200
4242
  /** ----------------- 元素操作消息处理 ----------------- */
5201
- /**
5202
- * 处理通过 ID 高亮元素
5203
- */
5204
- handleHoverElementById(payload) {
5205
- if (!this.elementSelector || !payload?.id) return;
5206
- const selector = `#${payload.id}`;
5207
- this.elementSelector.highlightElementBySelector(selector);
5208
- }
5209
- /**
5210
- * 处理通过 ID 取消高亮元素
5211
- */
5212
- handleUnhoverElementById(payload) {
5213
- if (!this.elementSelector || !payload?.id) return;
5214
- const selector = `#${payload.id}`;
5215
- this.elementSelector.unhighlightElementBySelector(selector);
5216
- }
5217
- /**
5218
- * 处理高亮元素请求
5219
- */
5220
- handleHoverElementRequested(payload) {
5221
- if (!this.elementSelector || !payload?.selector) return;
5222
- this.elementSelector.highlightElementBySelector(payload.selector);
5223
- }
5224
- /**
5225
- * 处理取消高亮元素请求
5226
- */
5227
- handleUnhoverElementRequested(payload) {
5228
- if (!this.elementSelector || !payload?.selector) return;
5229
- this.elementSelector.unhighlightElementBySelector(payload.selector);
5230
- }
5231
4243
  /**
5232
4244
  * 处理设置元素内容
5233
4245
  */
@@ -5331,22 +4343,6 @@ var MessageBridge = class {
5331
4343
  element.addEventListener("blur", handleBlur);
5332
4344
  }
5333
4345
  }
5334
- /**
5335
- * 处理更新选中元素
5336
- */
5337
- handleUpdateSelectedElements(payload) {
5338
- if (!this.elementSelector || !Array.isArray(payload)) return;
5339
- this.elementSelector.updateSelectedElements(payload);
5340
- this.sendMessage({
5341
- type: "ELEMENT_EVENT",
5342
- payload: {
5343
- type: "selected_elements_updated",
5344
- selectedElements: payload,
5345
- count: payload.length
5346
- },
5347
- timestamp: Date.now()
5348
- });
5349
- }
5350
4346
  /** ----------------- 组件树相关消息处理 ----------------- */
5351
4347
  /**
5352
4348
  * 处理请求组件树
@@ -5470,11 +4466,9 @@ var MessageBridge = class {
5470
4466
  if (dataTestId) return `[data-testid="${dataTestId}"]`;
5471
4467
  const dataHowoneId = element.getAttribute("data-howone-id");
5472
4468
  if (dataHowoneId) return `[data-howone-id="${dataHowoneId}"]`;
5473
- if (element.className) {
5474
- const classes = element.className.split(" ").filter((c) => c.trim());
5475
- if (classes.length > 0) {
5476
- return `.${classes[0]}`;
5477
- }
4469
+ const classes = getElementClasses(element);
4470
+ if (classes.length > 0) {
4471
+ return `.${classes[0]}`;
5478
4472
  }
5479
4473
  return element.tagName.toLowerCase();
5480
4474
  }
@@ -5502,106 +4496,6 @@ var MessageBridge = class {
5502
4496
  timestamp: Date.now()
5503
4497
  });
5504
4498
  }
5505
- /** ----------------- 新增的消息处理方法 ----------------- */
5506
- /**
5507
- * 处理获取鼠标位置的元素
5508
- */
5509
- handleGetElementAtPoint(payload) {
5510
- if (!this.elementSelector) return;
5511
- const element = this.elementSelector.getElementAtPoint(payload?.x, payload?.y);
5512
- this.sendMessage({
5513
- type: "ELEMENT_EVENT",
5514
- payload: {
5515
- type: "at_point_response",
5516
- element: element ? this.getElementInfo(element) : null,
5517
- coordinates: { x: payload?.x, y: payload?.y }
5518
- },
5519
- timestamp: Date.now()
5520
- });
5521
- }
5522
- /**
5523
- * 处理根据位置查找元素
5524
- */
5525
- handleFindElementsByLocation(payload) {
5526
- if (!this.elementSelector || !payload?.filePath || !payload?.lineNumber) return;
5527
- const elements = this.elementSelector.findElementsByLocation(payload.filePath, payload.lineNumber);
5528
- this.sendMessage({
5529
- type: "ELEMENT_EVENT",
5530
- payload: {
5531
- type: "elements_by_location_response",
5532
- elements: elements.map((el) => this.getElementInfo(el)),
5533
- location: {
5534
- filePath: payload.filePath,
5535
- lineNumber: payload.lineNumber
5536
- }
5537
- },
5538
- timestamp: Date.now()
5539
- });
5540
- }
5541
- /**
5542
- * 处理设置元素属性(新版本)
5543
- */
5544
- handleSetElementAttributes(payload) {
5545
- if (!this.elementSelector || !payload?.selector || !payload?.attributes) return;
5546
- const success = this.elementSelector.setElementAttributes(payload.selector, payload.attributes);
5547
- this.sendMessage({
5548
- type: "ELEMENT_EVENT",
5549
- payload: {
5550
- type: "attributes_set_response",
5551
- success,
5552
- selector: payload.selector,
5553
- attributes: payload.attributes
5554
- },
5555
- timestamp: Date.now()
5556
- });
5557
- }
5558
- /**
5559
- * 处理启用文本编辑
5560
- */
5561
- handleEnableTextEditing(payload) {
5562
- if (!this.elementSelector || !payload?.selector) return;
5563
- const success = this.elementSelector.enableTextEditing(payload.selector);
5564
- this.sendMessage({
5565
- type: "ELEMENT_EVENT",
5566
- payload: {
5567
- type: "text_editing_enabled_response",
5568
- success,
5569
- selector: payload.selector
5570
- },
5571
- timestamp: Date.now()
5572
- });
5573
- }
5574
- /**
5575
- * 处理通过选择器悬停元素
5576
- */
5577
- handleHoverElementBySelector(payload) {
5578
- if (!this.elementSelector || !payload?.selector) return;
5579
- const success = this.elementSelector.hoverElementBySelector(payload.selector);
5580
- this.sendMessage({
5581
- type: "ELEMENT_EVENT",
5582
- payload: {
5583
- type: "hovered_by_selector_response",
5584
- success,
5585
- selector: payload.selector
5586
- },
5587
- timestamp: Date.now()
5588
- });
5589
- }
5590
- /**
5591
- * 处理取消悬停元素
5592
- */
5593
- handleUnhoverElement() {
5594
- if (!this.elementSelector) return;
5595
- this.elementSelector.unhoverElement();
5596
- this.sendMessage({
5597
- type: "ELEMENT_EVENT",
5598
- payload: {
5599
- type: "unhovered_response",
5600
- success: true
5601
- },
5602
- timestamp: Date.now()
5603
- });
5604
- }
5605
4499
  /** ----------------- 统一消息发送管理方法 ----------------- */
5606
4500
  /**
5607
4501
  * 获取统一的消息发送器实例
@@ -5635,7 +4529,6 @@ var MessageBridge = class {
5635
4529
  window.removeEventListener("message", this.messageListener);
5636
4530
  this.messageListener = void 0;
5637
4531
  }
5638
- console.log("[MessageBridge] \u6D88\u606F\u6865\u63A5\u5668\u5DF2\u9500\u6BC1");
5639
4532
  }
5640
4533
  };
5641
4534
 
@@ -5670,7 +4563,6 @@ var ErrorHandler = class {
5670
4563
  const sendMessage = this.messageSender.createSendFunction();
5671
4564
  this.errorTracking = new ErrorTracking(sendMessage);
5672
4565
  this.interactionTracking = new InteractionTracking(sendMessage);
5673
- this.elementSelector = new ElementSelector2(sendMessage);
5674
4566
  this.messageBridge = new MessageBridge();
5675
4567
  this.viewDetector = new ViewDetector();
5676
4568
  this.hardRefreshManager = new HardRefreshManager(GLOBAL_CONFIG.ALLOWED_ORIGINS);
@@ -5735,7 +4627,6 @@ var ErrorHandler = class {
5735
4627
  * 设置模块间的协作
5736
4628
  */
5737
4629
  setupModuleIntegration() {
5738
- this.messageBridge.setElementSelector(this.elementSelector);
5739
4630
  this.messageBridge.setComponentTreeGenerator(this.componentTreeGenerator);
5740
4631
  this.errorTracking.setViewDetector(this.viewDetector);
5741
4632
  this.errorTracking.setInteractionTracking(this.interactionTracking);
@@ -5812,12 +4703,6 @@ var ErrorHandler = class {
5812
4703
  getErrorStats() {
5813
4704
  return this.errorTracking.getErrorStats();
5814
4705
  }
5815
- /**
5816
- * 获取选择器状态
5817
- */
5818
- getSelectorState() {
5819
- return this.elementSelector.getSelectorState();
5820
- }
5821
4706
  /**
5822
4707
  * 获取交互历史
5823
4708
  */
@@ -5851,24 +4736,6 @@ var ErrorHandler = class {
5851
4736
  isViteEnvironment() {
5852
4737
  return ViteHMRDetector.isViteEnvironment();
5853
4738
  }
5854
- /**
5855
- * 启用元素选择器
5856
- */
5857
- enableElementSelector() {
5858
- this.elementSelector.enableSelector();
5859
- }
5860
- /**
5861
- * 禁用元素选择器
5862
- */
5863
- disableElementSelector() {
5864
- this.elementSelector.disableSelector();
5865
- }
5866
- /**
5867
- * 切换元素选择器状态
5868
- */
5869
- toggleElementSelector() {
5870
- this.elementSelector.toggleSelector();
5871
- }
5872
4739
  /**
5873
4740
  * 更新配置
5874
4741
  */
@@ -5882,7 +4749,6 @@ var ErrorHandler = class {
5882
4749
  try {
5883
4750
  this.errorTracking.destroy();
5884
4751
  this.interactionTracking.destroy();
5885
- this.elementSelector.destroy();
5886
4752
  this.messageBridge.destroy();
5887
4753
  if (this.viteHMRDetector) {
5888
4754
  this.viteHMRDetector.destroy();
@@ -5913,7 +4779,6 @@ var ErrorHandler = class {
5913
4779
  errorStats: this.getErrorStats(),
5914
4780
  currentView: this.getCurrentView(),
5915
4781
  interactionHistory: this.getInteractionHistory(),
5916
- selectorState: this.getSelectorState(),
5917
4782
  isViteEnvironment: this.isViteEnvironment(),
5918
4783
  timestamp: Date.now()
5919
4784
  };
@@ -7095,7 +5960,7 @@ function createClient(opts) {
7095
5960
  function makeRequestFromBase(base) {
7096
5961
  return new request_default({
7097
5962
  baseURL: base,
7098
- timeout: 6e4,
5963
+ timeout: 3e5,
7099
5964
  interceptors: {
7100
5965
  requestInterceptor: (config) => {
7101
5966
  config.headers = config.headers || {};