@kc-one/smart-fill-sdk 0.0.1-beta.1 → 0.0.1-beta.2
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/README.md +4 -4
- package/dist/index.esm.js +408 -254
- package/dist/index.umd.cjs +6 -6
- package/dist/src/adapters/element.d.ts +3 -0
- package/dist/src/adapters/element.d.ts.map +1 -0
- package/dist/src/core/smart-fill-instance.d.ts.map +1 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/scanner/dom-scanner.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var c = (n, e, t) =>
|
|
4
|
-
const
|
|
5
|
-
class
|
|
1
|
+
var fe = Object.defineProperty;
|
|
2
|
+
var pe = (n, e, t) => e in n ? fe(n, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : n[e] = t;
|
|
3
|
+
var c = (n, e, t) => pe(n, typeof e != "symbol" ? e + "" : e, t);
|
|
4
|
+
const he = "https://loan.kdbank.cn";
|
|
5
|
+
class J extends Error {
|
|
6
6
|
constructor(t) {
|
|
7
7
|
super(t.message);
|
|
8
8
|
/** 结构化错误信息,含 code / stage / retryable */
|
|
@@ -10,26 +10,26 @@ class B extends Error {
|
|
|
10
10
|
this.name = "SmartFillException", this.smartFillError = t;
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
|
-
function
|
|
14
|
-
return new
|
|
13
|
+
function b(n, e, t, s = {}) {
|
|
14
|
+
return new J({ code: n, message: e, stage: t, ...s });
|
|
15
15
|
}
|
|
16
|
-
function
|
|
17
|
-
return n instanceof
|
|
16
|
+
function ge(n, e, t = "RECOGNIZE_FAILED") {
|
|
17
|
+
return n instanceof J ? n.smartFillError : {
|
|
18
18
|
code: t,
|
|
19
19
|
message: n instanceof Error ? n.message : String(n || "智能录入异常"),
|
|
20
20
|
stage: e,
|
|
21
21
|
retryable: e === "recognize"
|
|
22
22
|
};
|
|
23
23
|
}
|
|
24
|
-
function
|
|
24
|
+
function M(n = "sf") {
|
|
25
25
|
return `${n}_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`;
|
|
26
26
|
}
|
|
27
|
-
class
|
|
27
|
+
class me {
|
|
28
28
|
constructor(e) {
|
|
29
29
|
/** 会话 accessToken,写入请求头 seToken */
|
|
30
30
|
c(this, "seToken", "");
|
|
31
31
|
/** 网关根地址,见 config/defaults.ts */
|
|
32
|
-
c(this, "baseURL",
|
|
32
|
+
c(this, "baseURL", he);
|
|
33
33
|
this.config = e;
|
|
34
34
|
}
|
|
35
35
|
/** 设置会话 token,后续 request 自动携带 seToken 请求头 */
|
|
@@ -42,7 +42,7 @@ class re {
|
|
|
42
42
|
*/
|
|
43
43
|
async createSession() {
|
|
44
44
|
if (!/^seKey-[A-Za-z0-9_-]{6,}$/.test(this.config.apiKey))
|
|
45
|
-
throw
|
|
45
|
+
throw b("API_KEY_INVALID", "apiKey 格式不正确,应以 seKey- 开头。", "setup");
|
|
46
46
|
return {
|
|
47
47
|
apiKey: this.config.apiKey,
|
|
48
48
|
rulesVersion: "0.0.1"
|
|
@@ -91,12 +91,12 @@ class re {
|
|
|
91
91
|
userInputMsg: s || ""
|
|
92
92
|
})
|
|
93
93
|
}
|
|
94
|
-
), r =
|
|
94
|
+
), r = ye(i, e.fields, e.scanToken);
|
|
95
95
|
return {
|
|
96
96
|
scanToken: e.scanToken,
|
|
97
97
|
suggestions: r,
|
|
98
98
|
trace: i.trace || {
|
|
99
|
-
traceId:
|
|
99
|
+
traceId: M("trace"),
|
|
100
100
|
usedOcr: !!e.usedOcr,
|
|
101
101
|
usedAi: !0,
|
|
102
102
|
durationMs: Math.round(performance.now() - t)
|
|
@@ -115,15 +115,15 @@ class re {
|
|
|
115
115
|
method: "POST",
|
|
116
116
|
body: t
|
|
117
117
|
}
|
|
118
|
-
), i =
|
|
118
|
+
), i = xe(s);
|
|
119
119
|
if (!i)
|
|
120
|
-
throw
|
|
120
|
+
throw b("RECOGNIZE_FAILED", "图片识别未提取到文本内容。", "recognize");
|
|
121
121
|
return i;
|
|
122
122
|
}
|
|
123
123
|
/** 通用 fetch 封装:超时控制、trace 头、HTTP 错误映射为 SmartFillException */
|
|
124
124
|
async request(e, t) {
|
|
125
125
|
const s = new AbortController(), i = window.setTimeout(() => s.abort(), this.config.requestTimeoutMs ?? 3e4), r = new Headers(t.headers);
|
|
126
|
-
t.body && !(t.body instanceof FormData) && !r.has("Content-Type") && r.set("Content-Type", "application/json"), r.set("x-trace-id",
|
|
126
|
+
t.body && !(t.body instanceof FormData) && !r.has("Content-Type") && r.set("Content-Type", "application/json"), r.set("x-trace-id", M("trace")), this.seToken && r.set("seToken", `${this.seToken}`);
|
|
127
127
|
try {
|
|
128
128
|
const a = await fetch(`${this.baseURL}${e}`, {
|
|
129
129
|
...t,
|
|
@@ -131,19 +131,19 @@ class re {
|
|
|
131
131
|
signal: s.signal
|
|
132
132
|
});
|
|
133
133
|
if (!a.ok)
|
|
134
|
-
throw
|
|
134
|
+
throw b(ve(a.status), await a.text(), e.includes("session") ? "setup" : "recognize", {
|
|
135
135
|
retryable: a.status >= 500 || a.status === 429
|
|
136
136
|
});
|
|
137
137
|
return a.json();
|
|
138
138
|
} catch (a) {
|
|
139
|
-
throw a instanceof DOMException && a.name === "AbortError" ?
|
|
139
|
+
throw a instanceof DOMException && a.name === "AbortError" ? b("RECOGNIZE_TIMEOUT", "识别请求超时,请稍后重试。", "recognize", { retryable: !0 }) : a;
|
|
140
140
|
} finally {
|
|
141
141
|
window.clearTimeout(i);
|
|
142
142
|
}
|
|
143
143
|
}
|
|
144
144
|
}
|
|
145
|
-
const
|
|
146
|
-
function
|
|
145
|
+
const be = 0.95;
|
|
146
|
+
function ye(n, e, t) {
|
|
147
147
|
var r;
|
|
148
148
|
const s = new Map(e.map((a) => [a.fieldId, a]));
|
|
149
149
|
return (((r = n.data) == null ? void 0 : r.fieldValues) || []).filter((a) => !!(a != null && a.fieldId)).map((a) => {
|
|
@@ -154,24 +154,24 @@ function oe(n, e, t) {
|
|
|
154
154
|
label: a.label || (o == null ? void 0 : o.label) || a.fieldId,
|
|
155
155
|
value: a.value,
|
|
156
156
|
displayValue: a.value == null ? "" : String(a.value),
|
|
157
|
-
confidence:
|
|
157
|
+
confidence: Ee(a.confidence),
|
|
158
158
|
source: a.source || "ai",
|
|
159
159
|
warnings: a.warnings
|
|
160
160
|
};
|
|
161
161
|
});
|
|
162
162
|
}
|
|
163
|
-
function
|
|
164
|
-
return typeof n != "number" || Number.isNaN(n) ?
|
|
163
|
+
function Ee(n) {
|
|
164
|
+
return typeof n != "number" || Number.isNaN(n) ? be : n < 0 ? 0 : n > 1 ? 1 : n;
|
|
165
165
|
}
|
|
166
|
-
function
|
|
166
|
+
function xe(n) {
|
|
167
167
|
var t;
|
|
168
168
|
const e = typeof n.data == "string" ? n.data : ((t = n.data) == null ? void 0 : t.text) || n.text || "";
|
|
169
169
|
return String(e || "").trim();
|
|
170
170
|
}
|
|
171
|
-
function
|
|
171
|
+
function ve(n) {
|
|
172
172
|
return n === 401 ? "TOKEN_EXPIRED" : n === 403 ? "API_KEY_FORBIDDEN" : n === 404 ? "FORM_CONFIG_NOT_FOUND" : "RECOGNIZE_FAILED";
|
|
173
173
|
}
|
|
174
|
-
class
|
|
174
|
+
class Q {
|
|
175
175
|
constructor() {
|
|
176
176
|
c(this, "handlers", /* @__PURE__ */ new Map());
|
|
177
177
|
}
|
|
@@ -192,7 +192,7 @@ class Y {
|
|
|
192
192
|
this.handlers.clear();
|
|
193
193
|
}
|
|
194
194
|
}
|
|
195
|
-
class
|
|
195
|
+
class we {
|
|
196
196
|
constructor() {
|
|
197
197
|
/** 当前页面所有存活实例 */
|
|
198
198
|
c(this, "instances", /* @__PURE__ */ new Set());
|
|
@@ -216,24 +216,125 @@ class ue {
|
|
|
216
216
|
this.instances.forEach((e) => e.destroy()), this.instances.clear(), this.active = null;
|
|
217
217
|
}
|
|
218
218
|
}
|
|
219
|
-
const
|
|
219
|
+
const Se = [
|
|
220
|
+
".el-select",
|
|
221
|
+
".el-date-editor",
|
|
222
|
+
".el-time-picker",
|
|
223
|
+
".el-switch",
|
|
224
|
+
".el-checkbox-group",
|
|
225
|
+
".el-radio-group",
|
|
226
|
+
".el-cascader",
|
|
227
|
+
".el-input-number"
|
|
228
|
+
].join(", "), ke = {
|
|
229
|
+
name: "element",
|
|
230
|
+
match: (n) => n.matches(Se),
|
|
231
|
+
getValue: (n) => {
|
|
232
|
+
var t;
|
|
233
|
+
const e = n.element;
|
|
234
|
+
if (e)
|
|
235
|
+
return e.matches(".el-switch") ? e.classList.contains("is-checked") || e.getAttribute("aria-checked") === "true" : e.matches(".el-radio-group") ? Te(e, "radio") : e.matches(".el-checkbox-group") ? Le(e) : ((t = V(e)) == null ? void 0 : t.value) || e.textContent || void 0;
|
|
236
|
+
},
|
|
237
|
+
setValue: (n, e) => {
|
|
238
|
+
const t = n.element;
|
|
239
|
+
if (!t) return;
|
|
240
|
+
if (t.matches(".el-switch")) {
|
|
241
|
+
Ae(t, e);
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
if (t.matches(".el-radio-group")) {
|
|
245
|
+
Ce(t, "radio", e);
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
if (t.matches(".el-checkbox-group")) {
|
|
249
|
+
Ie(t, e);
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
const s = V(t);
|
|
253
|
+
if (s) {
|
|
254
|
+
Me(s, e);
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
t.dispatchEvent(new Event("change", { bubbles: !0 }));
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
function Ae(n, e) {
|
|
261
|
+
(n.classList.contains("is-checked") || n.getAttribute("aria-checked") === "true") !== Fe(e) && H(n);
|
|
262
|
+
}
|
|
263
|
+
function Ie(n, e) {
|
|
264
|
+
var i;
|
|
265
|
+
const t = new Set(Oe(e).map(S)), s = F(n, "checkbox");
|
|
266
|
+
for (const r of s) {
|
|
267
|
+
const a = ((i = r.input) == null ? void 0 : i.checked) || r.root.classList.contains("is-checked") || r.root.getAttribute("aria-checked") === "true", o = t.has(S(r.value)) || t.has(S(r.label));
|
|
268
|
+
a !== o && H(r.root);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
function Ce(n, e, t) {
|
|
272
|
+
const s = S(String(t ?? "")), i = F(n, e).find((r) => S(r.value) === s || S(r.label) === s);
|
|
273
|
+
i && H(i.root);
|
|
274
|
+
}
|
|
275
|
+
function Te(n, e) {
|
|
276
|
+
var t;
|
|
277
|
+
return (t = F(n, e).find((s) => {
|
|
278
|
+
var i;
|
|
279
|
+
return ((i = s.input) == null ? void 0 : i.checked) || s.root.classList.contains("is-checked");
|
|
280
|
+
})) == null ? void 0 : t.value;
|
|
281
|
+
}
|
|
282
|
+
function Le(n) {
|
|
283
|
+
return F(n, "checkbox").filter((e) => {
|
|
284
|
+
var t;
|
|
285
|
+
return ((t = e.input) == null ? void 0 : t.checked) || e.root.classList.contains("is-checked");
|
|
286
|
+
}).map((e) => e.value);
|
|
287
|
+
}
|
|
288
|
+
function F(n, e) {
|
|
289
|
+
return Array.from(n.querySelectorAll(`.el-${e}, [role="${e}"], input[type="${e}"]`)).map((t) => {
|
|
290
|
+
const s = t instanceof HTMLInputElement ? t : t.querySelector(`input[type="${e}"]`), i = t instanceof HTMLInputElement && t.closest(`.el-${e}, [role="${e}"]`) || t, r = ee(i.textContent || i.getAttribute("aria-label") || (s == null ? void 0 : s.value) || "");
|
|
291
|
+
return {
|
|
292
|
+
root: i,
|
|
293
|
+
input: s,
|
|
294
|
+
label: r,
|
|
295
|
+
value: i.getAttribute("value") || (s == null ? void 0 : s.value) || r
|
|
296
|
+
};
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
function V(n) {
|
|
300
|
+
return n.querySelector('input:not([type="hidden"]), textarea');
|
|
301
|
+
}
|
|
302
|
+
function Me(n, e) {
|
|
303
|
+
n.value = String(e ?? ""), n.dispatchEvent(new Event("input", { bubbles: !0 })), n.dispatchEvent(new Event("change", { bubbles: !0 })), n.dispatchEvent(new Event("blur", { bubbles: !0 }));
|
|
304
|
+
}
|
|
305
|
+
function H(n) {
|
|
306
|
+
n.dispatchEvent(new MouseEvent("click", { bubbles: !0, cancelable: !0, view: window }));
|
|
307
|
+
}
|
|
308
|
+
function Fe(n) {
|
|
309
|
+
return typeof n == "boolean" ? n : ["true", "1", "是", "开启", "启用", "yes", "y"].includes(String(n ?? "").trim().toLowerCase());
|
|
310
|
+
}
|
|
311
|
+
function Oe(n) {
|
|
312
|
+
return Array.isArray(n) ? n.map(String) : String(n ?? "").split(/[,,;;、]/).map((e) => e.trim()).filter(Boolean);
|
|
313
|
+
}
|
|
314
|
+
function S(n) {
|
|
315
|
+
return ee(n).toLowerCase();
|
|
316
|
+
}
|
|
317
|
+
function ee(n) {
|
|
318
|
+
return n.replace(/\s+/g, " ").trim();
|
|
319
|
+
}
|
|
320
|
+
const $e = [
|
|
220
321
|
/^(el|rc|ant|radix|headlessui|mui|chakra)-/i,
|
|
221
322
|
/[0-9a-f]{8,}/i,
|
|
222
323
|
/\d{6,}/
|
|
223
324
|
];
|
|
224
|
-
function
|
|
325
|
+
function x(n) {
|
|
225
326
|
const e = String(n || "").trim();
|
|
226
|
-
return !e ||
|
|
327
|
+
return !e || $e.some((t) => t.test(e)) ? "" : e;
|
|
227
328
|
}
|
|
228
|
-
function
|
|
329
|
+
function P(n) {
|
|
229
330
|
const e = (n.options || []).slice(0, 20).map((t) => `${t.label}:${String(t.value)}`).join("|");
|
|
230
|
-
return
|
|
331
|
+
return k(
|
|
231
332
|
[
|
|
232
333
|
n.fieldId,
|
|
233
334
|
n.tagName,
|
|
234
335
|
n.type,
|
|
235
|
-
|
|
236
|
-
|
|
336
|
+
x(n.name),
|
|
337
|
+
x(n.id),
|
|
237
338
|
n.label,
|
|
238
339
|
n.placeholder,
|
|
239
340
|
n.section,
|
|
@@ -241,11 +342,11 @@ function $(n) {
|
|
|
241
342
|
].join("::")
|
|
242
343
|
);
|
|
243
344
|
}
|
|
244
|
-
function
|
|
345
|
+
function k(n) {
|
|
245
346
|
return String(n ?? "").replace(/\s+/g, " ").trim().toLowerCase();
|
|
246
347
|
}
|
|
247
|
-
const
|
|
248
|
-
class
|
|
348
|
+
const O = /* @__PURE__ */ new WeakMap();
|
|
349
|
+
class q {
|
|
249
350
|
constructor(e, t, s = []) {
|
|
250
351
|
this.fields = e, this.schemas = t, this.adapters = s;
|
|
251
352
|
}
|
|
@@ -289,7 +390,7 @@ class D {
|
|
|
289
390
|
if (t != null && t.getValue) return t.getValue();
|
|
290
391
|
const s = this.matchAdapter(e);
|
|
291
392
|
if (s != null && s.getValue) return s.getValue(e);
|
|
292
|
-
const i =
|
|
393
|
+
const i = $(e);
|
|
293
394
|
if (i)
|
|
294
395
|
return i instanceof HTMLInputElement && i.type === "checkbox" ? i.checked : i instanceof HTMLInputElement && i.type === "radio" ? i.checked ? i.value : void 0 : i instanceof HTMLInputElement || i instanceof HTMLTextAreaElement || i instanceof HTMLSelectElement ? i.value : i.textContent;
|
|
295
396
|
}
|
|
@@ -302,9 +403,9 @@ class D {
|
|
|
302
403
|
await s.setValue(t);
|
|
303
404
|
return;
|
|
304
405
|
}
|
|
305
|
-
const i =
|
|
406
|
+
const i = $(e);
|
|
306
407
|
if (!i) throw new Error("页面中未找到对应字段");
|
|
307
|
-
if (e.fingerprint && e.fingerprint !==
|
|
408
|
+
if (e.fingerprint && e.fingerprint !== P({ ...e, tagName: i.tagName.toLowerCase() }))
|
|
308
409
|
throw new Error("字段结构已变化,请重新扫描");
|
|
309
410
|
if (e.disabled || e.readonly || i.hasAttribute("disabled") || i.hasAttribute("readonly"))
|
|
310
411
|
throw new Error("字段不可编辑");
|
|
@@ -313,49 +414,49 @@ class D {
|
|
|
313
414
|
await r.setValue(e, t);
|
|
314
415
|
return;
|
|
315
416
|
}
|
|
316
|
-
|
|
417
|
+
Ne(i, t), _e(i);
|
|
317
418
|
}
|
|
318
419
|
/** 匹配第一个适用的组件库适配器 */
|
|
319
420
|
matchAdapter(e) {
|
|
320
|
-
const t =
|
|
421
|
+
const t = $(e);
|
|
321
422
|
return t ? this.adapters.find((s) => s.match(t, e)) : void 0;
|
|
322
423
|
}
|
|
323
424
|
}
|
|
324
|
-
function
|
|
425
|
+
function $(n) {
|
|
325
426
|
var e;
|
|
326
|
-
return (e = n.element) != null && e.isConnected ? n.element : document.querySelector(`[data-smart-fill-id="${
|
|
427
|
+
return (e = n.element) != null && e.isConnected ? n.element : document.querySelector(`[data-smart-fill-id="${z(n.fieldId)}"]`);
|
|
327
428
|
}
|
|
328
|
-
function
|
|
429
|
+
function Ne(n, e) {
|
|
329
430
|
if (n instanceof HTMLInputElement && n.type === "checkbox")
|
|
330
431
|
n.checked = !!e;
|
|
331
432
|
else if (n instanceof HTMLInputElement && n.type === "radio") {
|
|
332
|
-
const t = document.querySelector(`input[type="radio"][name="${
|
|
433
|
+
const t = document.querySelector(`input[type="radio"][name="${z(n.name)}"][value="${z(String(e))}"]`);
|
|
333
434
|
(t || n).checked = !0;
|
|
334
435
|
} else n instanceof HTMLInputElement || n instanceof HTMLTextAreaElement || n instanceof HTMLSelectElement ? n.value = String(e ?? "") : n.isContentEditable && (n.textContent = String(e ?? ""));
|
|
335
436
|
n.dispatchEvent(new Event("input", { bubbles: !0 })), n.dispatchEvent(new Event("change", { bubbles: !0 }));
|
|
336
437
|
}
|
|
337
|
-
function
|
|
438
|
+
function _e(n) {
|
|
338
439
|
var s;
|
|
339
|
-
n.setAttribute("data-smart-fill-highlighted", "true"), (s =
|
|
440
|
+
n.setAttribute("data-smart-fill-highlighted", "true"), (s = O.get(n)) == null || s.abort();
|
|
340
441
|
const e = new AbortController(), t = (i) => {
|
|
341
|
-
i && "isTrusted" in i && !i.isTrusted || (n.removeAttribute("data-smart-fill-highlighted"), e.abort(),
|
|
442
|
+
i && "isTrusted" in i && !i.isTrusted || (n.removeAttribute("data-smart-fill-highlighted"), e.abort(), O.delete(n));
|
|
342
443
|
};
|
|
343
|
-
|
|
444
|
+
O.set(n, e), n.addEventListener("focus", t, { signal: e.signal }), n.addEventListener("pointerdown", t, { signal: e.signal }), n.addEventListener("keydown", t, { signal: e.signal }), n.addEventListener("input", t, { signal: e.signal }), n.addEventListener("change", t, { signal: e.signal });
|
|
344
445
|
}
|
|
345
446
|
function T(n, e, t, s, i) {
|
|
346
447
|
return { fieldId: n, label: e, attemptedValue: t, reason: s, reasonCode: i };
|
|
347
448
|
}
|
|
348
|
-
function
|
|
449
|
+
function z(n) {
|
|
349
450
|
return typeof CSS < "u" && CSS.escape ? CSS.escape(n) : n.replace(/["\\]/g, "\\$&");
|
|
350
451
|
}
|
|
351
|
-
const
|
|
452
|
+
const Re = [
|
|
352
453
|
{ key: "mobile", pattern: new RegExp("(?<!\\d)1[3-9]\\d{9}(?!\\d)", "g"), confidence: 0.98, reason: "手机号正则命中" },
|
|
353
454
|
{ key: "idCard", pattern: new RegExp("(?<!\\d)\\d{17}[\\dXx](?!\\d)", "g"), confidence: 0.96, reason: "身份证号正则命中" },
|
|
354
455
|
{ key: "email", pattern: /[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}/g, confidence: 0.95, reason: "邮箱正则命中" },
|
|
355
456
|
{ key: "bankCard", pattern: new RegExp("(?<!\\d)\\d{16,19}(?!\\d)", "g"), confidence: 0.9, reason: "银行卡号正则命中" },
|
|
356
457
|
{ key: "amount", pattern: /(?:金额|价格|费用|合计|总计)[::\s]*([0-9]+(?:\.[0-9]{1,2})?)/g, confidence: 0.88, reason: "金额关键词命中" },
|
|
357
458
|
{ key: "date", pattern: /\d{4}[-/.年]\d{1,2}[-/.月]\d{1,2}日?/g, confidence: 0.86, reason: "日期格式命中" }
|
|
358
|
-
],
|
|
459
|
+
], U = {
|
|
359
460
|
legalPerson: ["法人", "法定代表人", "法定代表", "企业法人", "legal person", "legal representative"],
|
|
360
461
|
emergencyContact: ["紧急联系人", "紧急联络人", "emergency contact"],
|
|
361
462
|
contact: ["联系人", "联络人", "联系人员", "contact"],
|
|
@@ -385,7 +486,7 @@ const ge = [
|
|
|
385
486
|
date: ["日期", "时间", "有效期", "date"],
|
|
386
487
|
applyDate: ["申请日期", "申请时间", "受理日期", "进件日期"],
|
|
387
488
|
bankCard: ["银行卡", "卡号", "bank", "bank card"]
|
|
388
|
-
},
|
|
489
|
+
}, te = {
|
|
389
490
|
mobile: "mobile",
|
|
390
491
|
legalPersonMobile: "mobile",
|
|
391
492
|
emergencyContactMobile: "mobile",
|
|
@@ -411,20 +512,20 @@ const ge = [
|
|
|
411
512
|
applyDate: "date",
|
|
412
513
|
bankCard: "bankCard"
|
|
413
514
|
};
|
|
414
|
-
class
|
|
515
|
+
class De {
|
|
415
516
|
/**
|
|
416
517
|
* 从文本中提取事实并匹配到 scan 字段。
|
|
417
518
|
* 按 confidence 降序分配,每个 fieldId 仅匹配一次(usedFieldIds 去重)。
|
|
418
519
|
*/
|
|
419
520
|
recognize(e, t, s) {
|
|
420
|
-
const i =
|
|
521
|
+
const i = Ze([...Pe(e), ...ze(e)]), r = /* @__PURE__ */ new Set(), a = [];
|
|
421
522
|
for (const o of i.sort((d, l) => l.confidence - d.confidence)) {
|
|
422
|
-
const d =
|
|
523
|
+
const d = Ke(o, t, r);
|
|
423
524
|
d && (a.push({
|
|
424
525
|
fieldId: d.fieldId,
|
|
425
526
|
scanToken: s,
|
|
426
527
|
label: d.label,
|
|
427
|
-
value:
|
|
528
|
+
value: qe(o.value, d),
|
|
428
529
|
displayValue: o.value,
|
|
429
530
|
confidence: o.confidence,
|
|
430
531
|
source: "local_rule",
|
|
@@ -434,75 +535,75 @@ class me {
|
|
|
434
535
|
return a;
|
|
435
536
|
}
|
|
436
537
|
}
|
|
437
|
-
function
|
|
538
|
+
function Pe(n) {
|
|
438
539
|
const e = [];
|
|
439
|
-
for (const t of
|
|
540
|
+
for (const t of Re)
|
|
440
541
|
for (const s of n.matchAll(t.pattern)) {
|
|
441
|
-
const i =
|
|
542
|
+
const i = ne(s[1] || s[0]);
|
|
442
543
|
e.push({
|
|
443
544
|
key: t.key,
|
|
444
545
|
value: i,
|
|
445
546
|
confidence: t.confidence,
|
|
446
547
|
reason: t.reason,
|
|
447
|
-
baseKey:
|
|
548
|
+
baseKey: te[t.key]
|
|
448
549
|
});
|
|
449
550
|
}
|
|
450
551
|
return e;
|
|
451
552
|
}
|
|
452
|
-
function
|
|
553
|
+
function ze(n) {
|
|
453
554
|
const e = [], t = n.split(/\r?\n|[;,;]/).map((s) => s.trim()).filter(Boolean);
|
|
454
555
|
for (const s of t) {
|
|
455
556
|
const i = s.match(/^[“"'`]?([^::=]{2,30})[”"'`]?[::=]\s*(.+)$/);
|
|
456
557
|
if (!i) continue;
|
|
457
|
-
const r =
|
|
558
|
+
const r = Ye(i[1]), a = ne(i[2]);
|
|
458
559
|
if (!(!r || !a))
|
|
459
|
-
for (const o of
|
|
560
|
+
for (const o of He(r, a))
|
|
460
561
|
e.push(o);
|
|
461
562
|
}
|
|
462
563
|
return e;
|
|
463
564
|
}
|
|
464
|
-
function
|
|
465
|
-
const t =
|
|
466
|
-
return
|
|
565
|
+
function He(n, e) {
|
|
566
|
+
const t = k(n), s = Be(e), i = [], r = Ue(t);
|
|
567
|
+
return p(t, h.applyDate) && i.push("applyDate"), p(t, h.applyAmount) && i.push("applyAmount"), p(t, h.companyName) && i.push("companyName"), p(t, h.detailAddress) && i.push("detailAddress"), p(t, h.address) && i.push("address"), (p(t, h.mobile) || s === "mobile") && r && N(i, r, "mobile"), (p(t, h.idCard) || s === "idCard") && r && N(i, r, "idCard"), (p(t, h.email) || s === "email") && r && N(i, r, "email"), (p(t, h.mobile) || s === "mobile") && i.push("mobile"), (p(t, h.idCard) || s === "idCard") && i.push("idCard"), (p(t, h.email) || s === "email") && i.push("email"), (p(t, h.bankCard) || s === "bankCard") && i.push("bankCard"), (p(t, h.amount) || s === "amount") && i.push("amount"), (p(t, h.date) || s === "date") && i.push("date"), Ge(i).map((a, o) => ({
|
|
467
568
|
key: a,
|
|
468
569
|
value: e,
|
|
469
570
|
confidence: Math.max(0.84, 0.96 - o * 0.04),
|
|
470
571
|
reason: r ? `键值对文本命中(${n},角色增强)` : `键值对文本命中(${n})`,
|
|
471
|
-
baseKey:
|
|
572
|
+
baseKey: te[a]
|
|
472
573
|
}));
|
|
473
574
|
}
|
|
474
|
-
function
|
|
575
|
+
function Ke(n, e, t) {
|
|
475
576
|
let s = null;
|
|
476
577
|
for (const i of e) {
|
|
477
578
|
if (t.has(i.fieldId)) continue;
|
|
478
|
-
const r =
|
|
579
|
+
const r = Ve(n, i);
|
|
479
580
|
r > ((s == null ? void 0 : s.score) ?? 0) && (s = { field: i, score: r });
|
|
480
581
|
}
|
|
481
582
|
return s && s.score >= 0.45 ? s.field : null;
|
|
482
583
|
}
|
|
483
|
-
function
|
|
484
|
-
const t =
|
|
584
|
+
function Ve(n, e) {
|
|
585
|
+
const t = k([e.fieldId, e.label, e.placeholder, e.name, e.id, e.section].join(" ")), s = h[n.key] || [n.key], i = h[n.baseKey] || [n.baseKey];
|
|
485
586
|
let r = 0;
|
|
486
|
-
return
|
|
587
|
+
return p(t, s) ? r += 0.95 : n.key !== n.baseKey && p(t, i) ? r += 0.68 : p(t, i) && (r += 0.82), t.includes(k(n.key)) && (r += 0.22), e.required && (r += 0.05), n.baseKey === "amount" && (e.type === "amount" || e.type === "number") && (r += 0.18), n.baseKey === "date" && e.type === "date" && (r += 0.18), n.baseKey === "address" && (e.type === "textarea" || e.type === "text") && (r += 0.12), ["name", "companyName", "email", "mobile", "idCard", "bankCard"].includes(n.baseKey) && e.type === "text" && (r += 0.08), Math.min(r, 1);
|
|
487
588
|
}
|
|
488
|
-
function
|
|
589
|
+
function qe(n, e) {
|
|
489
590
|
var t;
|
|
490
591
|
return e.type === "date" ? n.replace(/[年月/.]/g, "-").replace(/日/g, "").replace(/--/g, "-") : e.type === "number" || e.type === "amount" ? ((t = n.match(/[0-9]+(?:\.[0-9]+)?/)) == null ? void 0 : t[0]) ?? n : e.name && /mobile|phone|idcard|bankcard/i.test(e.name) || e.id && /mobile|phone|idcard|bankcard/i.test(e.id) || /mobile|phone|idcard|bankcard/i.test(e.fieldId) ? n.replace(/\s+/g, "") : n;
|
|
491
592
|
}
|
|
492
|
-
function
|
|
493
|
-
const e = Object.keys(
|
|
593
|
+
function Ue(n) {
|
|
594
|
+
const e = Object.keys(U).filter((t) => p(n, U[t]));
|
|
494
595
|
return e.length ? e.includes("emergencyContact") ? "emergencyContact" : e.includes("legalPerson") ? "legalPerson" : e.includes("spouse") ? "spouse" : "contact" : null;
|
|
495
596
|
}
|
|
496
|
-
function
|
|
597
|
+
function Be(n) {
|
|
497
598
|
const e = n.replace(/\s+/g, "");
|
|
498
599
|
return /^1[3-9]\d{9}$/.test(e) ? "mobile" : /^\d{17}[\dXx]$/.test(e) ? "idCard" : /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/.test(n) ? "email" : /^\d{16,19}$/.test(e) ? "bankCard" : /^\d{4}[-/.年]\d{1,2}[-/.月]\d{1,2}日?$/.test(n) ? "date" : /^[0-9]+(?:\.[0-9]{1,2})?$/.test(e) ? "amount" : /[省市区县路街道号栋室乡镇]/.test(n) ? "address" : /^[\u4e00-\u9fa5a-zA-Z·]{2,20}$/.test(n) ? "name" : "unknown";
|
|
499
600
|
}
|
|
500
601
|
function N(n, e, t) {
|
|
501
602
|
var i;
|
|
502
|
-
const s = (i =
|
|
603
|
+
const s = (i = je[e]) == null ? void 0 : i[t];
|
|
503
604
|
s && n.push(s);
|
|
504
605
|
}
|
|
505
|
-
const
|
|
606
|
+
const je = {
|
|
506
607
|
legalPerson: {
|
|
507
608
|
mobile: "legalPersonMobile",
|
|
508
609
|
idCard: "legalPersonIdCard",
|
|
@@ -523,17 +624,17 @@ const ke = {
|
|
|
523
624
|
name: "spouseName"
|
|
524
625
|
}
|
|
525
626
|
};
|
|
526
|
-
function
|
|
627
|
+
function Ye(n) {
|
|
527
628
|
return n.replace(/[“”"'`]/g, "").replace(/\s+/g, " ").trim();
|
|
528
629
|
}
|
|
529
|
-
function
|
|
630
|
+
function ne(n) {
|
|
530
631
|
return n.replace(/[,。;;]+$/g, "").replace(/^[“”"'`\s]+|[“”"'`\s]+$/g, "").trim();
|
|
531
632
|
}
|
|
532
|
-
function
|
|
533
|
-
const t =
|
|
534
|
-
return e.some((s) => t.includes(
|
|
633
|
+
function p(n, e) {
|
|
634
|
+
const t = k(n);
|
|
635
|
+
return e.some((s) => t.includes(k(s)));
|
|
535
636
|
}
|
|
536
|
-
function
|
|
637
|
+
function Ze(n) {
|
|
537
638
|
const e = /* @__PURE__ */ new Map();
|
|
538
639
|
for (const t of n) {
|
|
539
640
|
const s = `${t.key}::${t.value}`, i = e.get(s);
|
|
@@ -541,15 +642,24 @@ function Te(n) {
|
|
|
541
642
|
}
|
|
542
643
|
return [...e.values()];
|
|
543
644
|
}
|
|
544
|
-
function
|
|
645
|
+
function Ge(n) {
|
|
545
646
|
return [...new Set(n)];
|
|
546
647
|
}
|
|
547
|
-
const
|
|
648
|
+
const Xe = [
|
|
548
649
|
"input",
|
|
549
650
|
"textarea",
|
|
550
651
|
"select",
|
|
551
652
|
"[contenteditable]:not([contenteditable='false'])"
|
|
552
|
-
].join(", "),
|
|
653
|
+
].join(", "), se = [
|
|
654
|
+
".el-select",
|
|
655
|
+
".el-date-editor",
|
|
656
|
+
".el-time-picker",
|
|
657
|
+
".el-switch",
|
|
658
|
+
".el-checkbox-group",
|
|
659
|
+
".el-radio-group",
|
|
660
|
+
".el-cascader",
|
|
661
|
+
".el-input-number"
|
|
662
|
+
].join(", "), B = [
|
|
553
663
|
"dialog[open]",
|
|
554
664
|
"[role='dialog']",
|
|
555
665
|
"[aria-modal='true']",
|
|
@@ -563,8 +673,8 @@ const Le = [
|
|
|
563
673
|
".n-modal",
|
|
564
674
|
".popup",
|
|
565
675
|
".drawer"
|
|
566
|
-
].join(", "),
|
|
567
|
-
class
|
|
676
|
+
].join(", "), We = /* @__PURE__ */ new Set(["hidden", "submit", "button", "image", "reset", "file", "password"]);
|
|
677
|
+
class Je {
|
|
568
678
|
constructor(e = document) {
|
|
569
679
|
this.root = e;
|
|
570
680
|
}
|
|
@@ -575,7 +685,7 @@ class Me {
|
|
|
575
685
|
*/
|
|
576
686
|
scan(e = {}) {
|
|
577
687
|
var d;
|
|
578
|
-
const t =
|
|
688
|
+
const t = M("scan");
|
|
579
689
|
if ((d = e.registered) != null && d.length)
|
|
580
690
|
return {
|
|
581
691
|
scanToken: t,
|
|
@@ -589,7 +699,7 @@ class Me {
|
|
|
589
699
|
}
|
|
590
700
|
/** FieldSchema → FieldDescriptor,解析 element 并生成 fingerprint */
|
|
591
701
|
fromSchema(e, t) {
|
|
592
|
-
const s =
|
|
702
|
+
const s = at(e.element, this.root), i = {
|
|
593
703
|
fieldId: e.rowKey == null ? e.fieldId : `${e.fieldId}:${e.rowKey}`,
|
|
594
704
|
label: e.label,
|
|
595
705
|
type: e.type,
|
|
@@ -602,32 +712,32 @@ class Me {
|
|
|
602
712
|
element: s || void 0,
|
|
603
713
|
fingerprint: ""
|
|
604
714
|
};
|
|
605
|
-
return i.fingerprint =
|
|
715
|
+
return i.fingerprint = P({
|
|
606
716
|
...i,
|
|
607
717
|
tagName: s == null ? void 0 : s.tagName.toLowerCase()
|
|
608
718
|
}), i;
|
|
609
719
|
}
|
|
610
720
|
/** DOM 元素 → FieldDescriptor,自动推断 label/type 并写入 data-smart-fill-id */
|
|
611
721
|
fromElement(e, t, s) {
|
|
612
|
-
const i =
|
|
722
|
+
const i = Qe(e, t), r = nt(e), a = {
|
|
613
723
|
fieldId: i,
|
|
614
724
|
fingerprint: "",
|
|
615
725
|
scanToken: s,
|
|
616
|
-
type:
|
|
726
|
+
type: et(e),
|
|
617
727
|
localRuleMode: "inherit",
|
|
618
|
-
label:
|
|
619
|
-
placeholder:
|
|
620
|
-
name:
|
|
621
|
-
id:
|
|
622
|
-
section:
|
|
728
|
+
label: K(e),
|
|
729
|
+
placeholder: ie(e),
|
|
730
|
+
name: x(oe(e)) || void 0,
|
|
731
|
+
id: x(e.id) || void 0,
|
|
732
|
+
section: tt(e),
|
|
623
733
|
options: r,
|
|
624
|
-
required:
|
|
625
|
-
readonly: e
|
|
626
|
-
disabled: e
|
|
734
|
+
required: it(e),
|
|
735
|
+
readonly: st(e),
|
|
736
|
+
disabled: _(e),
|
|
627
737
|
source: "form_scan",
|
|
628
738
|
element: e
|
|
629
739
|
};
|
|
630
|
-
return a.fingerprint =
|
|
740
|
+
return a.fingerprint = P({
|
|
631
741
|
...a,
|
|
632
742
|
tagName: e.tagName.toLowerCase()
|
|
633
743
|
}), a;
|
|
@@ -635,7 +745,7 @@ class Me {
|
|
|
635
745
|
/** 解析扫描根节点,scanContainer 为 CSS 选择器 */
|
|
636
746
|
resolveRoot(e) {
|
|
637
747
|
if (e) {
|
|
638
|
-
const t =
|
|
748
|
+
const t = le(this.root, e);
|
|
639
749
|
if (t)
|
|
640
750
|
return t;
|
|
641
751
|
}
|
|
@@ -643,78 +753,121 @@ class Me {
|
|
|
643
753
|
}
|
|
644
754
|
/** 收集 root 下可见且可编辑的表单控件 */
|
|
645
755
|
collectVisibleFields(e) {
|
|
646
|
-
|
|
756
|
+
const t = Array.from(e.querySelectorAll(se)).filter((i) => !(i instanceof HTMLElement) || !j(i) || _(i) ? !1 : re(i));
|
|
757
|
+
return [...Array.from(e.querySelectorAll(Xe)).filter((i) => !(i instanceof HTMLElement) || !j(i) || rt(i) || i instanceof HTMLInputElement && We.has((i.type || "").toLowerCase()) ? !1 : !_(i) && !i.hasAttribute("readonly")), ...t];
|
|
647
758
|
}
|
|
648
759
|
/**
|
|
649
760
|
* 检测最应优先扫描的容器。
|
|
650
761
|
* 优先 activeElement 所在弹窗,否则取包含最多字段的弹窗容器。
|
|
651
762
|
*/
|
|
652
763
|
detectTopLayerContainer(e) {
|
|
653
|
-
const t = document.activeElement instanceof HTMLElement ? document.activeElement : null, s = t == null ? void 0 : t.closest(
|
|
764
|
+
const t = document.activeElement instanceof HTMLElement ? document.activeElement : null, s = t == null ? void 0 : t.closest(B);
|
|
654
765
|
if (s instanceof HTMLElement && e.some((r) => s.contains(r)))
|
|
655
766
|
return s;
|
|
656
|
-
const i = e.map((r) => r.closest(
|
|
767
|
+
const i = e.map((r) => r.closest(B)).filter((r) => r instanceof HTMLElement);
|
|
657
768
|
return i.length ? i.sort((r, a) => e.filter((o) => a.contains(o)).length - e.filter((o) => r.contains(o)).length)[0] : document.body;
|
|
658
769
|
}
|
|
659
770
|
}
|
|
660
|
-
function
|
|
771
|
+
function Qe(n, e) {
|
|
661
772
|
const t = n.getAttribute("data-smart-fill-id");
|
|
662
773
|
if (t)
|
|
663
774
|
return t;
|
|
664
|
-
const i =
|
|
775
|
+
const i = x(n.getAttribute("data-smart-fill-key")) || x(oe(n)) || x(n.id) || x(K(n)) || `smart-fill-${Date.now()}-${e}`;
|
|
665
776
|
return n.setAttribute("data-smart-fill-id", i), i;
|
|
666
777
|
}
|
|
667
|
-
function
|
|
778
|
+
function et(n) {
|
|
779
|
+
const e = ae(n);
|
|
780
|
+
if (e) return e;
|
|
668
781
|
if (n instanceof HTMLTextAreaElement) return "textarea";
|
|
669
782
|
if (n instanceof HTMLSelectElement) return "select";
|
|
670
783
|
if (n instanceof HTMLInputElement) {
|
|
671
|
-
const
|
|
672
|
-
if (
|
|
673
|
-
if (
|
|
674
|
-
if (
|
|
675
|
-
if (
|
|
784
|
+
const t = (n.type || "text").toLowerCase();
|
|
785
|
+
if (t === "radio") return "radio";
|
|
786
|
+
if (t === "checkbox") return "checkbox";
|
|
787
|
+
if (t === "date" || t === "month") return "date";
|
|
788
|
+
if (t === "number") return "number";
|
|
676
789
|
}
|
|
677
790
|
return "text";
|
|
678
791
|
}
|
|
679
|
-
function
|
|
792
|
+
function K(n) {
|
|
680
793
|
const e = n.getAttribute("aria-label");
|
|
681
794
|
if (e) return e.trim();
|
|
682
795
|
if (n.id) {
|
|
683
|
-
const r = document.querySelector(`label[for="${
|
|
684
|
-
if (r != null && r.textContent) return
|
|
796
|
+
const r = document.querySelector(`label[for="${ce(n.id)}"]`);
|
|
797
|
+
if (r != null && r.textContent) return y(r.textContent);
|
|
685
798
|
}
|
|
686
799
|
const t = n.closest("label");
|
|
687
|
-
if (t != null && t.textContent) return
|
|
800
|
+
if (t != null && t.textContent) return y(t.textContent);
|
|
688
801
|
const s = n.closest(".form-item, .ant-form-item, .el-form-item, .field, .form-row"), i = s == null ? void 0 : s.querySelector("label, .ant-form-item-label, .el-form-item__label, .label");
|
|
689
|
-
return i != null && i.textContent ?
|
|
802
|
+
return i != null && i.textContent ? y(i.textContent) : ie(n) || n.getAttribute("name") || n.id || "未命名字段";
|
|
690
803
|
}
|
|
691
|
-
function
|
|
692
|
-
|
|
804
|
+
function ie(n) {
|
|
805
|
+
var e;
|
|
806
|
+
return n.getAttribute("placeholder") || n.getAttribute("aria-placeholder") || ((e = n.querySelector("[placeholder]")) == null ? void 0 : e.getAttribute("placeholder")) || void 0;
|
|
693
807
|
}
|
|
694
|
-
function
|
|
808
|
+
function tt(n) {
|
|
695
809
|
const e = n.closest("fieldset, section, .panel, .card, .form-section"), t = e == null ? void 0 : e.querySelector("legend, h1, h2, h3, .title, .section-title");
|
|
696
|
-
return t != null && t.textContent ?
|
|
810
|
+
return t != null && t.textContent ? y(t.textContent) : void 0;
|
|
697
811
|
}
|
|
698
|
-
function
|
|
812
|
+
function nt(n) {
|
|
813
|
+
if (n.matches(".el-radio-group"))
|
|
814
|
+
return Array.from(n.querySelectorAll('.el-radio, [role="radio"], input[type="radio"]')).map((e) => {
|
|
815
|
+
var t;
|
|
816
|
+
return {
|
|
817
|
+
label: y(e.textContent || e.getAttribute("aria-label") || e.getAttribute("value") || ""),
|
|
818
|
+
value: e.getAttribute("value") || ((t = e.querySelector('input[type="radio"]')) == null ? void 0 : t.value) || y(e.textContent || "")
|
|
819
|
+
};
|
|
820
|
+
}).filter((e) => e.label || e.value);
|
|
821
|
+
if (n.matches(".el-checkbox-group"))
|
|
822
|
+
return Array.from(n.querySelectorAll('.el-checkbox, [role="checkbox"], input[type="checkbox"]')).map((e) => {
|
|
823
|
+
var t;
|
|
824
|
+
return {
|
|
825
|
+
label: y(e.textContent || e.getAttribute("aria-label") || e.getAttribute("value") || ""),
|
|
826
|
+
value: e.getAttribute("value") || ((t = e.querySelector('input[type="checkbox"]')) == null ? void 0 : t.value) || y(e.textContent || "")
|
|
827
|
+
};
|
|
828
|
+
}).filter((e) => e.label || e.value);
|
|
699
829
|
if (n instanceof HTMLSelectElement)
|
|
700
830
|
return Array.from(n.options).map((e) => ({
|
|
701
|
-
label:
|
|
831
|
+
label: y(e.textContent || e.label),
|
|
702
832
|
value: e.value
|
|
703
833
|
}));
|
|
704
834
|
if (n instanceof HTMLInputElement && (n.type === "radio" || n.type === "checkbox") && n.name)
|
|
705
|
-
return Array.from(document.querySelectorAll(`input[name="${
|
|
706
|
-
label:
|
|
835
|
+
return Array.from(document.querySelectorAll(`input[name="${ce(n.name)}"]`)).map((e) => ({
|
|
836
|
+
label: K(e),
|
|
707
837
|
value: e.value || !0
|
|
708
838
|
}));
|
|
709
839
|
}
|
|
710
|
-
function
|
|
840
|
+
function j(n) {
|
|
711
841
|
const e = window.getComputedStyle(n);
|
|
712
842
|
return e.display === "none" || e.visibility === "hidden" || Number(e.opacity) === 0 ? !1 : !!(n.offsetWidth || n.offsetHeight || n.getClientRects().length);
|
|
713
843
|
}
|
|
714
|
-
function
|
|
715
|
-
return n
|
|
844
|
+
function _(n) {
|
|
845
|
+
return n.hasAttribute("disabled") || n.getAttribute("aria-disabled") === "true" || n.classList.contains("is-disabled") || !!n.querySelector('[disabled], [aria-disabled="true"], .is-disabled');
|
|
846
|
+
}
|
|
847
|
+
function st(n) {
|
|
848
|
+
return n.hasAttribute("readonly") || !!n.querySelector("[readonly]");
|
|
849
|
+
}
|
|
850
|
+
function it(n) {
|
|
851
|
+
return n.hasAttribute("required") || n.getAttribute("aria-required") === "true" || !!n.querySelector('[required], [aria-required="true"]');
|
|
852
|
+
}
|
|
853
|
+
function rt(n) {
|
|
854
|
+
const e = n.closest(se);
|
|
855
|
+
return e instanceof HTMLElement ? re(e) : !1;
|
|
716
856
|
}
|
|
717
|
-
function
|
|
857
|
+
function re(n) {
|
|
858
|
+
return !!ae(n);
|
|
859
|
+
}
|
|
860
|
+
function ae(n) {
|
|
861
|
+
return n.matches(".el-select, .el-cascader") ? "select" : n.matches(".el-date-editor, .el-time-picker") ? "date" : n.matches(".el-switch") || n.matches(".el-checkbox-group") ? "checkbox" : n.matches(".el-radio-group") ? "radio" : n.matches(".el-input-number") ? "number" : null;
|
|
862
|
+
}
|
|
863
|
+
function oe(n) {
|
|
864
|
+
var e;
|
|
865
|
+
return n.getAttribute("name") || ((e = n.querySelector("[name]")) == null ? void 0 : e.getAttribute("name")) || n.getAttribute("data-smart-fill-key");
|
|
866
|
+
}
|
|
867
|
+
function at(n, e) {
|
|
868
|
+
return n instanceof HTMLElement ? n : typeof n == "string" ? le(e, n) : null;
|
|
869
|
+
}
|
|
870
|
+
function le(n, e) {
|
|
718
871
|
try {
|
|
719
872
|
const t = n.querySelector(e);
|
|
720
873
|
return t instanceof HTMLElement ? t : null;
|
|
@@ -722,14 +875,14 @@ function W(n, e) {
|
|
|
722
875
|
return null;
|
|
723
876
|
}
|
|
724
877
|
}
|
|
725
|
-
function
|
|
878
|
+
function y(n) {
|
|
726
879
|
return n.replace(/[*::]/g, "").replace(/\s+/g, " ").trim();
|
|
727
880
|
}
|
|
728
|
-
function
|
|
881
|
+
function ce(n) {
|
|
729
882
|
return typeof CSS < "u" && CSS.escape ? CSS.escape(n) : n.replace(/["\\]/g, "\\$&");
|
|
730
883
|
}
|
|
731
|
-
const
|
|
732
|
-
class
|
|
884
|
+
const R = 5, ot = 10 * 1024 * 1024, lt = 50 * 1024 * 1024;
|
|
885
|
+
class ct {
|
|
733
886
|
constructor(e) {
|
|
734
887
|
/** 面板宿主元素,挂载到 container 下 */
|
|
735
888
|
c(this, "host", null);
|
|
@@ -755,7 +908,7 @@ class Ke {
|
|
|
755
908
|
if (!this.dragState || !this.host || e.pointerId !== this.dragState.pointerId) return;
|
|
756
909
|
const t = e.clientX - this.dragState.startX, s = e.clientY - this.dragState.startY;
|
|
757
910
|
(Math.abs(t) > 3 || Math.abs(s) > 3) && (this.dragState.moved = !0);
|
|
758
|
-
const i = this.host.getBoundingClientRect(), r = Math.max(8, window.innerWidth - i.width - 8), a = Math.max(8, window.innerHeight - i.height - 8), o =
|
|
911
|
+
const i = this.host.getBoundingClientRect(), r = Math.max(8, window.innerWidth - i.width - 8), a = Math.max(8, window.innerHeight - i.height - 8), o = L(this.dragState.startLeft + t, 8, r), d = L(this.dragState.startTop + s, 8, a);
|
|
759
912
|
this.host.style.left = `${o}px`, this.host.style.top = `${d}px`;
|
|
760
913
|
});
|
|
761
914
|
c(this, "handleDragEnd", (e) => {
|
|
@@ -765,7 +918,7 @@ class Ke {
|
|
|
765
918
|
});
|
|
766
919
|
/** 面板聚焦或鼠标悬浮在图片区时接管全局粘贴图片 */
|
|
767
920
|
c(this, "handleDocumentPaste", (e) => {
|
|
768
|
-
const t =
|
|
921
|
+
const t = ut(e);
|
|
769
922
|
if (!t.length || !this.isOpen || !this.host)
|
|
770
923
|
return;
|
|
771
924
|
const s = document.activeElement, i = this.root instanceof ShadowRoot ? this.root.activeElement : null;
|
|
@@ -818,7 +971,7 @@ class Ke {
|
|
|
818
971
|
}
|
|
819
972
|
render(e) {
|
|
820
973
|
this.root && (this.root.innerHTML = `
|
|
821
|
-
<style>${
|
|
974
|
+
<style>${ft}</style>
|
|
822
975
|
${this.options.mode === "floating" ? `<button class="sf-float" type="button" data-role="open">${this.t("entry", "智能录入")}</button>` : ""}
|
|
823
976
|
<section class="sf-panel ${e ? "is-open" : ""} ${this.options.mode === "inline" ? "is-inline" : "is-floating"}" aria-label="智能录入面板">
|
|
824
977
|
<header class="sf-header">
|
|
@@ -835,7 +988,7 @@ class Ke {
|
|
|
835
988
|
</label>
|
|
836
989
|
<div class="sf-entry-grid">
|
|
837
990
|
<div class="sf-textarea-wrap">
|
|
838
|
-
<textarea class="sf-textarea" data-role="text" placeholder="${this.t("placeholder", "粘贴文本,如:姓名:张三 手机号:13800000000")}">${
|
|
991
|
+
<textarea class="sf-textarea" data-role="text" placeholder="${this.t("placeholder", "粘贴文本,如:姓名:张三 手机号:13800000000")}">${dt(this.inputText)}</textarea>
|
|
839
992
|
<div class="sf-textarea-actions">
|
|
840
993
|
<button class="sf-btn sf-btn-secondary" type="button" data-role="clear">${this.t("clear", "清空")}</button>
|
|
841
994
|
<button class="sf-btn sf-btn-primary" type="button" data-role="recognize">${this.t("recognize", "智能识别")}</button>
|
|
@@ -852,7 +1005,7 @@ class Ke {
|
|
|
852
1005
|
<circle cx="10" cy="10.5" r="1" fill="currentColor"/>
|
|
853
1006
|
</svg>
|
|
854
1007
|
</span>
|
|
855
|
-
<span class="sf-upload-hint">${this.t("uploadHint", `点击、拖拽、Ctrl + V 粘贴图片至此(最多 ${
|
|
1008
|
+
<span class="sf-upload-hint">${this.t("uploadHint", `点击、拖拽、Ctrl + V 粘贴图片至此(最多 ${R} 张)`)}</span>
|
|
856
1009
|
</span>
|
|
857
1010
|
<span class="sf-upload-btn" data-role="file-label">图片识别</span>
|
|
858
1011
|
</label>
|
|
@@ -896,8 +1049,8 @@ class Ke {
|
|
|
896
1049
|
}), (a = this.query('[data-role="text"]')) == null || a.addEventListener("input", (u) => {
|
|
897
1050
|
this.inputText = u.target.value;
|
|
898
1051
|
}), (o = this.query('[data-role="local-priority-toggle"]')) == null || o.addEventListener("change", (u) => {
|
|
899
|
-
var g,
|
|
900
|
-
this.localPriorityEnabled = u.target.checked, (
|
|
1052
|
+
var g, v;
|
|
1053
|
+
this.localPriorityEnabled = u.target.checked, (v = (g = this.options).onLocalPriorityChange) == null || v.call(g, this.localPriorityEnabled);
|
|
901
1054
|
}), (d = this.query('[data-role="clear"]')) == null || d.addEventListener("click", () => {
|
|
902
1055
|
this.clearFormState();
|
|
903
1056
|
}), (l = this.query('[data-role="recognize"]')) == null || l.addEventListener("click", () => {
|
|
@@ -926,15 +1079,15 @@ class Ke {
|
|
|
926
1079
|
this.resetSelectedFiles(), this.setError(this.t("invalidImageError", "请选择图片文件。"));
|
|
927
1080
|
return;
|
|
928
1081
|
}
|
|
929
|
-
if (t.length >
|
|
930
|
-
this.resetSelectedFiles(), this.setError(this.t("maxFilesError", `最多上传 ${
|
|
1082
|
+
if (t.length > R) {
|
|
1083
|
+
this.resetSelectedFiles(), this.setError(this.t("maxFilesError", `最多上传 ${R} 张图片。`));
|
|
931
1084
|
return;
|
|
932
1085
|
}
|
|
933
|
-
if (t.find((r) => r.size >
|
|
1086
|
+
if (t.find((r) => r.size > ot)) {
|
|
934
1087
|
this.resetSelectedFiles(), this.setError(this.t("maxSingleFileSizeError", "单张图片不能超过 10MB。"));
|
|
935
1088
|
return;
|
|
936
1089
|
}
|
|
937
|
-
if (t.reduce((r, a) => r + a.size, 0) >
|
|
1090
|
+
if (t.reduce((r, a) => r + a.size, 0) > lt) {
|
|
938
1091
|
this.resetSelectedFiles(), this.setError(this.t("maxTotalFileSizeError", "上传图片总大小不能超过 50MB。"));
|
|
939
1092
|
return;
|
|
940
1093
|
}
|
|
@@ -960,7 +1113,7 @@ class Ke {
|
|
|
960
1113
|
keepHostInViewport() {
|
|
961
1114
|
this.options.mode !== "floating" || !this.host || !this.host.style.left || !this.host.style.top || window.requestAnimationFrame(() => {
|
|
962
1115
|
if (!this.host) return;
|
|
963
|
-
const e = this.host.getBoundingClientRect(), t =
|
|
1116
|
+
const e = this.host.getBoundingClientRect(), t = L(e.left, 8, Math.max(8, window.innerWidth - e.width - 8)), s = L(e.top, 8, Math.max(8, window.innerHeight - e.height - 8));
|
|
964
1117
|
this.host.style.left = `${t}px`, this.host.style.top = `${s}px`;
|
|
965
1118
|
});
|
|
966
1119
|
}
|
|
@@ -973,7 +1126,7 @@ class Ke {
|
|
|
973
1126
|
return ((s = this.options.messages) == null ? void 0 : s[e]) || t;
|
|
974
1127
|
}
|
|
975
1128
|
}
|
|
976
|
-
function
|
|
1129
|
+
function dt(n) {
|
|
977
1130
|
return n.replace(/[&<>"']/g, (e) => ({
|
|
978
1131
|
"&": "&",
|
|
979
1132
|
"<": "<",
|
|
@@ -982,14 +1135,14 @@ function He(n) {
|
|
|
982
1135
|
"'": "'"
|
|
983
1136
|
})[e] || e);
|
|
984
1137
|
}
|
|
985
|
-
function
|
|
1138
|
+
function L(n, e, t) {
|
|
986
1139
|
return Math.min(Math.max(n, e), t);
|
|
987
1140
|
}
|
|
988
|
-
function
|
|
1141
|
+
function ut(n) {
|
|
989
1142
|
var t;
|
|
990
1143
|
return Array.from(((t = n.clipboardData) == null ? void 0 : t.items) || []).filter((s) => s.kind === "file" && s.type.startsWith("image/")).map((s) => s.getAsFile()).filter((s) => !!s);
|
|
991
1144
|
}
|
|
992
|
-
const
|
|
1145
|
+
const ft = `
|
|
993
1146
|
:host, .sf-panel { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; }
|
|
994
1147
|
:host(.sf-sdk-host-floating), .sf-sdk-host-floating { position: fixed; top: 24px; right: 24px; z-index: 2147483647; display: flex; flex-direction: column; align-items: flex-end; gap: 12px; width: min(420px, calc(100vw - 32px)); pointer-events: none; }
|
|
995
1148
|
.sf-float { align-self: flex-end; border: 0; border-radius: 999px; padding: 12px 18px; color: #fff; background: #2563eb; box-shadow: 0 10px 24px rgba(37,99,235,.3); cursor: move; user-select: none; touch-action: none; pointer-events: auto; }
|
|
@@ -1035,15 +1188,15 @@ const qe = `
|
|
|
1035
1188
|
[data-status="error"] { color: #dc2626; }
|
|
1036
1189
|
[data-status="warning"] { color: #d97706; }
|
|
1037
1190
|
[data-status="success"] { color: #16a34a; }
|
|
1038
|
-
`,
|
|
1039
|
-
class
|
|
1191
|
+
`, pt = 0.75;
|
|
1192
|
+
class ht {
|
|
1040
1193
|
constructor(e, t) {
|
|
1041
1194
|
/** 实例级事件总线,对应 instance.on(...) */
|
|
1042
|
-
c(this, "events", new
|
|
1195
|
+
c(this, "events", new Q());
|
|
1043
1196
|
/** 页面字段扫描器,root 来自 SmartFill.create({ root }) */
|
|
1044
1197
|
c(this, "scanner");
|
|
1045
1198
|
/** 浏览器端本地规则引擎,用于文本正则/键值对提取 */
|
|
1046
|
-
c(this, "ruleEngine", new
|
|
1199
|
+
c(this, "ruleEngine", new De());
|
|
1047
1200
|
/** Shadow DOM 面板,mount / mountFloatingButton 后可用(指向最后挂载的面板,用于状态展示) */
|
|
1048
1201
|
c(this, "panel", null);
|
|
1049
1202
|
/** 已挂载的全部面板(inline / floating 可同时存在),用于本地优先开关广播与销毁 */
|
|
@@ -1053,7 +1206,7 @@ class Be {
|
|
|
1053
1206
|
/** 业务方 registerFields 注册的字段;非空时 rescan 仅扫描这些字段 */
|
|
1054
1207
|
c(this, "registeredFields", []);
|
|
1055
1208
|
/** 组件库回填适配器链,如 AntD / Element 自定义控件 */
|
|
1056
|
-
c(this, "adapters", []);
|
|
1209
|
+
c(this, "adapters", [ke]);
|
|
1057
1210
|
/** 最近一次 rescan 结果;scanToken 用于识别/回填防过期校验 */
|
|
1058
1211
|
c(this, "scanResult", null);
|
|
1059
1212
|
/** recognize 完成后生成的自动回填候选,供面板展示与 applyAutoItems 使用 */
|
|
@@ -1064,7 +1217,7 @@ class Be {
|
|
|
1064
1217
|
c(this, "localPriorityEnabled", !1);
|
|
1065
1218
|
/** 实例是否已 destroy,销毁后所有公开方法抛 INSTANCE_DESTROYED */
|
|
1066
1219
|
c(this, "destroyed", !1);
|
|
1067
|
-
this.config = e, this.context = t, this.scanner = new
|
|
1220
|
+
this.config = e, this.context = t, this.scanner = new Je(e.root || document), this.localPriorityEnabled = vt(), this.context.manager.add(this);
|
|
1068
1221
|
}
|
|
1069
1222
|
/** 订阅实例事件,返回取消订阅函数 */
|
|
1070
1223
|
on(e, t) {
|
|
@@ -1085,7 +1238,7 @@ class Be {
|
|
|
1085
1238
|
for (const s of e) {
|
|
1086
1239
|
const i = s.rowKey == null ? s.fieldId : `${s.fieldId}:${s.rowKey}`;
|
|
1087
1240
|
if (t.has(i))
|
|
1088
|
-
throw
|
|
1241
|
+
throw b("UNSUPPORTED_PAGE", `字段 ${i} 重复注册。`, "scan");
|
|
1089
1242
|
t.add(i);
|
|
1090
1243
|
}
|
|
1091
1244
|
return this.registeredFields = e, this;
|
|
@@ -1099,14 +1252,14 @@ class Be {
|
|
|
1099
1252
|
this.assertAlive();
|
|
1100
1253
|
const t = typeof e == "string" ? document.querySelector(e) : e;
|
|
1101
1254
|
if (!t)
|
|
1102
|
-
throw
|
|
1103
|
-
const s =
|
|
1255
|
+
throw b("UNSUPPORTED_PAGE", "未找到智能录入挂载点。", "ui");
|
|
1256
|
+
const s = Z("inline", xt(e, t)), i = G(s, !0);
|
|
1104
1257
|
return this.createPanel("inline", s, i).mount(t), this;
|
|
1105
1258
|
}
|
|
1106
1259
|
/** 挂载右下角悬浮按钮 + 弹框(floating 模式) */
|
|
1107
1260
|
mountFloatingButton() {
|
|
1108
1261
|
this.assertAlive();
|
|
1109
|
-
const e =
|
|
1262
|
+
const e = Z("floating"), t = G(e, !1);
|
|
1110
1263
|
return this.createPanel("floating", e, t).mount(document.body), this;
|
|
1111
1264
|
}
|
|
1112
1265
|
/**
|
|
@@ -1115,7 +1268,7 @@ class Be {
|
|
|
1115
1268
|
*/
|
|
1116
1269
|
createPanel(e, t, s) {
|
|
1117
1270
|
let i;
|
|
1118
|
-
return i = new
|
|
1271
|
+
return i = new ct({
|
|
1119
1272
|
mode: e,
|
|
1120
1273
|
initialOpen: s,
|
|
1121
1274
|
messages: this.config.messages,
|
|
@@ -1128,17 +1281,17 @@ class Be {
|
|
|
1128
1281
|
}
|
|
1129
1282
|
/** 同步本地优先开关:更新内存态、写入 localStorage,并广播到其他已挂载面板 */
|
|
1130
1283
|
handleLocalPriorityChange(e, t) {
|
|
1131
|
-
this.localPriorityEnabled = e,
|
|
1284
|
+
this.localPriorityEnabled = e, wt(e);
|
|
1132
1285
|
for (const s of this.panels)
|
|
1133
1286
|
s !== t && s.setLocalPriorityEnabled(e);
|
|
1134
1287
|
}
|
|
1135
1288
|
/** 打开面板并触发 rescan,同时激活当前实例(关闭其他实例面板) */
|
|
1136
1289
|
async open(e = this.panel) {
|
|
1137
|
-
this.assertAlive(), e && (this.context.manager.activate(this), this.panel = e, e.setOpen(!0),
|
|
1290
|
+
this.assertAlive(), e && (this.context.manager.activate(this), this.panel = e, e.setOpen(!0), X(this.panelStorageKeys.get(e), !0), await this.rescan());
|
|
1138
1291
|
}
|
|
1139
1292
|
/** 关闭面板(不销毁实例) */
|
|
1140
1293
|
close(e = this.panel) {
|
|
1141
|
-
e && (this.panel = e, e.setOpen(!1),
|
|
1294
|
+
e && (this.panel = e, e.setOpen(!1), X(this.panelStorageKeys.get(e), !1));
|
|
1142
1295
|
}
|
|
1143
1296
|
/**
|
|
1144
1297
|
* 扫描页面可回填字段。
|
|
@@ -1155,7 +1308,7 @@ class Be {
|
|
|
1155
1308
|
registered: t,
|
|
1156
1309
|
maxFields: this.config.maxFields
|
|
1157
1310
|
}), !this.scanResult.fields.length)
|
|
1158
|
-
throw
|
|
1311
|
+
throw b("NO_FIELDS_FOUND", "当前页面未找到可回填字段。", "scan");
|
|
1159
1312
|
return this.events.emit("scanCompleted", {
|
|
1160
1313
|
scanToken: this.scanResult.scanToken,
|
|
1161
1314
|
fieldCount: this.scanResult.fields.length
|
|
@@ -1177,28 +1330,28 @@ class Be {
|
|
|
1177
1330
|
async recognize(e) {
|
|
1178
1331
|
var r, a, o;
|
|
1179
1332
|
this.assertAlive();
|
|
1180
|
-
const t = this.scanResult || await this.rescan(), s =
|
|
1333
|
+
const t = this.scanResult || await this.rescan(), s = M("trace"), i = performance.now();
|
|
1181
1334
|
this.events.emit("recognizing", { scanToken: t.scanToken, traceId: s }), (r = this.panel) == null || r.setBusy(!0, "识别中...");
|
|
1182
1335
|
try {
|
|
1183
|
-
const d = t.fields.filter((m) =>
|
|
1336
|
+
const d = t.fields.filter((m) => yt(m.localRuleMode, this.localPriorityEnabled)), l = t.fields.filter((m) => m.localRuleMode !== "only"), { text: u, usedOcr: g } = await this.context.client.resolveInputText({
|
|
1184
1337
|
text: e.text,
|
|
1185
1338
|
images: e.images,
|
|
1186
1339
|
onStatusChange: (m) => {
|
|
1187
|
-
var
|
|
1340
|
+
var I, w, C;
|
|
1188
1341
|
if (m === "image_uploading") {
|
|
1189
|
-
(
|
|
1342
|
+
(I = this.panel) == null || I.setStatus("图片上传中...");
|
|
1190
1343
|
return;
|
|
1191
1344
|
}
|
|
1192
1345
|
if (m === "image_recognizing") {
|
|
1193
|
-
(
|
|
1346
|
+
(w = this.panel) == null || w.setStatus("图片识别中...");
|
|
1194
1347
|
return;
|
|
1195
1348
|
}
|
|
1196
|
-
(
|
|
1349
|
+
(C = this.panel) == null || C.setStatus("识别中...");
|
|
1197
1350
|
}
|
|
1198
|
-
}),
|
|
1199
|
-
let
|
|
1351
|
+
}), v = u ? this.ruleEngine.recognize(u, d, t.scanToken) : [];
|
|
1352
|
+
let E;
|
|
1200
1353
|
if (!l.length)
|
|
1201
|
-
|
|
1354
|
+
E = Y(t.scanToken, s, v, i, void 0, g);
|
|
1202
1355
|
else
|
|
1203
1356
|
try {
|
|
1204
1357
|
const m = await this.context.client.recognize({
|
|
@@ -1209,35 +1362,35 @@ class Be {
|
|
|
1209
1362
|
usedOcr: g,
|
|
1210
1363
|
fields: l,
|
|
1211
1364
|
onStatusChange: () => {
|
|
1212
|
-
var
|
|
1213
|
-
(
|
|
1365
|
+
var w;
|
|
1366
|
+
(w = this.panel) == null || w.setStatus("识别中...");
|
|
1214
1367
|
}
|
|
1215
1368
|
});
|
|
1216
1369
|
m.trace.durationMs = m.trace.durationMs || Math.round(performance.now() - i);
|
|
1217
|
-
const
|
|
1218
|
-
|
|
1219
|
-
m.suggestions.filter((
|
|
1370
|
+
const I = bt(
|
|
1371
|
+
v,
|
|
1372
|
+
m.suggestions.filter((w) => l.some((C) => C.fieldId === w.fieldId))
|
|
1220
1373
|
);
|
|
1221
|
-
|
|
1374
|
+
E = { ...m, suggestions: I };
|
|
1222
1375
|
} catch (m) {
|
|
1223
|
-
if (!
|
|
1376
|
+
if (!v.length)
|
|
1224
1377
|
throw m;
|
|
1225
|
-
|
|
1378
|
+
E = Y(
|
|
1226
1379
|
t.scanToken,
|
|
1227
1380
|
s,
|
|
1228
|
-
|
|
1381
|
+
v,
|
|
1229
1382
|
i,
|
|
1230
1383
|
[g ? "后端识别失败,已使用 OCR 文本触发本地识别继续回填。" : "后端识别失败,已启用本地识别继续回填。"],
|
|
1231
1384
|
g
|
|
1232
1385
|
);
|
|
1233
1386
|
}
|
|
1234
|
-
return this.autoApplyState =
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1387
|
+
return this.autoApplyState = gt(
|
|
1388
|
+
E.scanToken,
|
|
1389
|
+
E.trace.traceId,
|
|
1390
|
+
E.suggestions,
|
|
1238
1391
|
t,
|
|
1239
1392
|
this.registeredFields
|
|
1240
|
-
), this.events.emit("recognized",
|
|
1393
|
+
), this.events.emit("recognized", E), (a = this.panel) == null || a.setAutoApplyState(this.autoApplyState), await this.applyAutoItems(this.autoApplyState), E;
|
|
1241
1394
|
} catch (d) {
|
|
1242
1395
|
throw this.emitError(d, "recognize"), d;
|
|
1243
1396
|
} finally {
|
|
@@ -1252,9 +1405,9 @@ class Be {
|
|
|
1252
1405
|
async apply(e) {
|
|
1253
1406
|
var i;
|
|
1254
1407
|
if (this.assertAlive(), !this.scanResult)
|
|
1255
|
-
throw
|
|
1408
|
+
throw b("SCAN_TOKEN_EXPIRED", "请先扫描字段后再回填。", "apply");
|
|
1256
1409
|
this.events.emit("applying", { scanToken: e.scanToken, count: e.values.length });
|
|
1257
|
-
const s = await new
|
|
1410
|
+
const s = await new q(this.scanResult.fields, this.registeredFields, this.adapters).apply(e);
|
|
1258
1411
|
return this.events.emit("applied", s), (i = this.panel) == null || i.setApplyResult(s), s;
|
|
1259
1412
|
}
|
|
1260
1413
|
/**
|
|
@@ -1264,10 +1417,10 @@ class Be {
|
|
|
1264
1417
|
async applyAutoItems(e) {
|
|
1265
1418
|
var o, d;
|
|
1266
1419
|
if (!this.scanResult)
|
|
1267
|
-
throw
|
|
1268
|
-
const t =
|
|
1420
|
+
throw b("SCAN_TOKEN_EXPIRED", "请先扫描字段后再回填。", "apply");
|
|
1421
|
+
const t = mt(e), s = e.items.filter((l) => de(l)).map((l) => ({ fieldId: l.fieldId, value: l.value, source: l.source }));
|
|
1269
1422
|
this.events.emit("applying", { scanToken: e.scanToken, count: s.length }), (o = this.panel) == null || o.setStatus("识别完成,正在自动回填...");
|
|
1270
|
-
const r = await new
|
|
1423
|
+
const r = await new q(this.scanResult.fields, this.registeredFields, this.adapters).apply({ scanToken: e.scanToken, values: s }), a = {
|
|
1271
1424
|
...r,
|
|
1272
1425
|
skipped: [...t, ...r.skipped],
|
|
1273
1426
|
warnings: [
|
|
@@ -1287,20 +1440,20 @@ class Be {
|
|
|
1287
1440
|
}
|
|
1288
1441
|
assertAlive() {
|
|
1289
1442
|
if (this.destroyed)
|
|
1290
|
-
throw
|
|
1443
|
+
throw b("INSTANCE_DESTROYED", "实例已销毁。", "ui");
|
|
1291
1444
|
}
|
|
1292
1445
|
emitError(e, t) {
|
|
1293
1446
|
var i;
|
|
1294
|
-
const s =
|
|
1447
|
+
const s = ge(e, t);
|
|
1295
1448
|
this.events.emit("error", s), (i = this.panel) == null || i.setError(s.message);
|
|
1296
1449
|
}
|
|
1297
1450
|
}
|
|
1298
|
-
function
|
|
1451
|
+
function gt(n, e, t, s, i) {
|
|
1299
1452
|
return {
|
|
1300
1453
|
scanToken: n,
|
|
1301
1454
|
traceId: e,
|
|
1302
1455
|
items: t.map((r) => {
|
|
1303
|
-
const a = s.fields.find((l) => l.fieldId === r.fieldId), o = i.find((l) => l.fieldId === r.fieldId), d = o != null && o.getValue ? o.getValue() :
|
|
1456
|
+
const a = s.fields.find((l) => l.fieldId === r.fieldId), o = i.find((l) => l.fieldId === r.fieldId), d = o != null && o.getValue ? o.getValue() : Et(a == null ? void 0 : a.element);
|
|
1304
1457
|
return {
|
|
1305
1458
|
applyItemId: `${r.fieldId}_${Math.random().toString(36).slice(2, 8)}`,
|
|
1306
1459
|
fieldId: r.fieldId,
|
|
@@ -1318,12 +1471,12 @@ function Ye(n, e, t, s, i) {
|
|
|
1318
1471
|
})
|
|
1319
1472
|
};
|
|
1320
1473
|
}
|
|
1321
|
-
function
|
|
1474
|
+
function de(n) {
|
|
1322
1475
|
var e;
|
|
1323
|
-
return n.confidence >=
|
|
1476
|
+
return n.confidence >= pt && !((e = n.warnings) != null && e.length);
|
|
1324
1477
|
}
|
|
1325
|
-
function
|
|
1326
|
-
return n.items.filter((e) => !
|
|
1478
|
+
function mt(n) {
|
|
1479
|
+
return n.items.filter((e) => !de(e)).map((e) => {
|
|
1327
1480
|
var t, s;
|
|
1328
1481
|
return {
|
|
1329
1482
|
fieldId: e.fieldId,
|
|
@@ -1334,7 +1487,7 @@ function je(n) {
|
|
|
1334
1487
|
};
|
|
1335
1488
|
});
|
|
1336
1489
|
}
|
|
1337
|
-
function
|
|
1490
|
+
function bt(n, e) {
|
|
1338
1491
|
const t = /* @__PURE__ */ new Map();
|
|
1339
1492
|
for (const s of e)
|
|
1340
1493
|
t.set(s.fieldId, s);
|
|
@@ -1342,10 +1495,10 @@ function Ze(n, e) {
|
|
|
1342
1495
|
t.has(s.fieldId) || t.set(s.fieldId, s);
|
|
1343
1496
|
return [...t.values()];
|
|
1344
1497
|
}
|
|
1345
|
-
function
|
|
1498
|
+
function yt(n, e) {
|
|
1346
1499
|
return n === "only" ? !0 : n === "off" ? !1 : e;
|
|
1347
1500
|
}
|
|
1348
|
-
function
|
|
1501
|
+
function Y(n, e, t, s, i, r = !1) {
|
|
1349
1502
|
return {
|
|
1350
1503
|
scanToken: n,
|
|
1351
1504
|
suggestions: t,
|
|
@@ -1358,21 +1511,21 @@ function K(n, e, t, s, i, r = !1) {
|
|
|
1358
1511
|
}
|
|
1359
1512
|
};
|
|
1360
1513
|
}
|
|
1361
|
-
function
|
|
1514
|
+
function Et(n) {
|
|
1362
1515
|
if (n)
|
|
1363
1516
|
return n instanceof HTMLInputElement && n.type === "checkbox" ? n.checked : n instanceof HTMLInputElement || n instanceof HTMLTextAreaElement || n instanceof HTMLSelectElement ? n.value : n.textContent;
|
|
1364
1517
|
}
|
|
1365
|
-
function
|
|
1518
|
+
function Z(n, e = "default") {
|
|
1366
1519
|
const t = typeof location < "u" ? location.pathname : "unknown-page", s = e.replace(/[^\w-]/g, "_") || "default";
|
|
1367
1520
|
return `smart-fill:${n}:${t}:${s}:open`;
|
|
1368
1521
|
}
|
|
1369
|
-
function
|
|
1522
|
+
function xt(n, e) {
|
|
1370
1523
|
if (typeof n == "string") return n;
|
|
1371
1524
|
if (e.id) return `#${e.id}`;
|
|
1372
1525
|
const t = typeof e.className == "string" ? e.className.trim().split(/\s+/).filter(Boolean)[0] : "";
|
|
1373
1526
|
return t ? `.${t}` : e.tagName.toLowerCase();
|
|
1374
1527
|
}
|
|
1375
|
-
function
|
|
1528
|
+
function G(n, e) {
|
|
1376
1529
|
try {
|
|
1377
1530
|
const t = window.localStorage.getItem(n);
|
|
1378
1531
|
return t == null ? e : t === "1";
|
|
@@ -1380,60 +1533,60 @@ function V(n, e) {
|
|
|
1380
1533
|
return e;
|
|
1381
1534
|
}
|
|
1382
1535
|
}
|
|
1383
|
-
function
|
|
1536
|
+
function X(n, e) {
|
|
1384
1537
|
if (n)
|
|
1385
1538
|
try {
|
|
1386
1539
|
window.localStorage.setItem(n, e ? "1" : "0");
|
|
1387
1540
|
} catch {
|
|
1388
1541
|
}
|
|
1389
1542
|
}
|
|
1390
|
-
function
|
|
1543
|
+
function ue() {
|
|
1391
1544
|
return `smart-fill:${typeof location < "u" ? location.pathname : "unknown-page"}:local-priority`;
|
|
1392
1545
|
}
|
|
1393
|
-
function
|
|
1546
|
+
function vt() {
|
|
1394
1547
|
try {
|
|
1395
|
-
return window.localStorage.getItem(
|
|
1548
|
+
return window.localStorage.getItem(ue()) === "1";
|
|
1396
1549
|
} catch {
|
|
1397
1550
|
return !1;
|
|
1398
1551
|
}
|
|
1399
1552
|
}
|
|
1400
|
-
function
|
|
1553
|
+
function wt(n) {
|
|
1401
1554
|
try {
|
|
1402
|
-
window.localStorage.setItem(
|
|
1555
|
+
window.localStorage.setItem(ue(), n ? "1" : "0");
|
|
1403
1556
|
} catch {
|
|
1404
1557
|
}
|
|
1405
1558
|
}
|
|
1406
|
-
const
|
|
1407
|
-
class
|
|
1559
|
+
const f = { status: "idle" }, D = new Q(), W = new we();
|
|
1560
|
+
class St {
|
|
1408
1561
|
/** 初始化 SDK:校验 apiKey、创建会话、获取 accessToken */
|
|
1409
1562
|
static async setup(e) {
|
|
1410
1563
|
if (typeof window > "u")
|
|
1411
|
-
return
|
|
1412
|
-
if (
|
|
1413
|
-
return
|
|
1414
|
-
if (
|
|
1415
|
-
return
|
|
1416
|
-
|
|
1417
|
-
const t = new
|
|
1418
|
-
return
|
|
1419
|
-
throw
|
|
1420
|
-
}),
|
|
1564
|
+
return f.status = "ready", kt();
|
|
1565
|
+
if (f.status === "ready" && f.apiKey === e.apiKey && f.session)
|
|
1566
|
+
return f.session;
|
|
1567
|
+
if (f.status === "loading" && f.apiKey === e.apiKey && f.promise)
|
|
1568
|
+
return f.promise;
|
|
1569
|
+
f.apiKey && f.apiKey !== e.apiKey && W.destroyAll();
|
|
1570
|
+
const t = new me(e);
|
|
1571
|
+
return f.status = "loading", f.apiKey = e.apiKey, f.client = t, f.promise = t.createSession().then((s) => (console.log("SmartFill session created:", s), t.setAccessToken(s.apiKey), f.status = "ready", f.session = s, D.emit("ready", { apiKey: e.apiKey }), s)).catch((s) => {
|
|
1572
|
+
throw f.status = "error", s;
|
|
1573
|
+
}), f.promise;
|
|
1421
1574
|
}
|
|
1422
1575
|
/** 创建页面实例,必须在 setup ready 后调用 */
|
|
1423
1576
|
static create(e = {}) {
|
|
1424
1577
|
if (typeof window > "u")
|
|
1425
|
-
return
|
|
1426
|
-
if (
|
|
1427
|
-
throw
|
|
1428
|
-
return new
|
|
1429
|
-
client:
|
|
1430
|
-
manager:
|
|
1578
|
+
return A();
|
|
1579
|
+
if (f.status !== "ready" || !f.client)
|
|
1580
|
+
throw b("SDK_NOT_READY", "请先 await SmartFill.setup({ apiKey })。", "setup");
|
|
1581
|
+
return new ht(e, {
|
|
1582
|
+
client: f.client,
|
|
1583
|
+
manager: W
|
|
1431
1584
|
});
|
|
1432
1585
|
}
|
|
1433
1586
|
}
|
|
1434
1587
|
/** 订阅全局事件(目前仅 ready) */
|
|
1435
|
-
c(
|
|
1436
|
-
function
|
|
1588
|
+
c(St, "on", D.on.bind(D));
|
|
1589
|
+
function kt() {
|
|
1437
1590
|
return {
|
|
1438
1591
|
apiKey: "server-mock",
|
|
1439
1592
|
accessToken: "server-mock",
|
|
@@ -1443,16 +1596,16 @@ function tt() {
|
|
|
1443
1596
|
rulesVersion: "server"
|
|
1444
1597
|
};
|
|
1445
1598
|
}
|
|
1446
|
-
function
|
|
1599
|
+
function A(n) {
|
|
1447
1600
|
const e = () => {
|
|
1448
1601
|
};
|
|
1449
1602
|
return {
|
|
1450
1603
|
on: e,
|
|
1451
|
-
useAdapter: () =>
|
|
1452
|
-
registerFields: () =>
|
|
1604
|
+
useAdapter: () => A(),
|
|
1605
|
+
registerFields: () => A(),
|
|
1453
1606
|
unregisterFields: e,
|
|
1454
|
-
mount: () =>
|
|
1455
|
-
mountFloatingButton: () =>
|
|
1607
|
+
mount: () => A(),
|
|
1608
|
+
mountFloatingButton: () => A(),
|
|
1456
1609
|
open: async () => {
|
|
1457
1610
|
},
|
|
1458
1611
|
close: e,
|
|
@@ -1466,7 +1619,7 @@ function S(n) {
|
|
|
1466
1619
|
destroy: e
|
|
1467
1620
|
};
|
|
1468
1621
|
}
|
|
1469
|
-
const
|
|
1622
|
+
const It = {
|
|
1470
1623
|
name: "native",
|
|
1471
1624
|
/** 匹配 input / textarea / select 原生控件 */
|
|
1472
1625
|
match: (n) => n instanceof HTMLInputElement || n instanceof HTMLTextAreaElement || n instanceof HTMLSelectElement,
|
|
@@ -1481,12 +1634,13 @@ const st = {
|
|
|
1481
1634
|
}
|
|
1482
1635
|
};
|
|
1483
1636
|
export {
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1637
|
+
he as DEFAULT_BASE_URL,
|
|
1638
|
+
q as DomFiller,
|
|
1639
|
+
Je as DomScanner,
|
|
1640
|
+
ke as ElementAdapter,
|
|
1641
|
+
Q as EventBus,
|
|
1642
|
+
De as LocalRuleEngine,
|
|
1643
|
+
It as NativeAdapter,
|
|
1644
|
+
St as SmartFill,
|
|
1645
|
+
ht as SmartFillInstance
|
|
1492
1646
|
};
|