foggy-data-viewer 1.0.1-beta.0

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.
Files changed (34) hide show
  1. package/README.md +273 -0
  2. package/dist/favicon.svg +4 -0
  3. package/dist/index.js +1531 -0
  4. package/dist/index.umd +1 -0
  5. package/dist/style.css +1 -0
  6. package/package.json +51 -0
  7. package/src/App.vue +469 -0
  8. package/src/api/viewer.ts +163 -0
  9. package/src/components/DataTable.test.ts +533 -0
  10. package/src/components/DataTable.vue +810 -0
  11. package/src/components/DataTableWithSearch.test.ts +628 -0
  12. package/src/components/DataTableWithSearch.vue +277 -0
  13. package/src/components/DataViewer.vue +310 -0
  14. package/src/components/SearchToolbar.test.ts +521 -0
  15. package/src/components/SearchToolbar.vue +406 -0
  16. package/src/components/composables/index.ts +2 -0
  17. package/src/components/composables/useTableSelection.test.ts +248 -0
  18. package/src/components/composables/useTableSelection.ts +44 -0
  19. package/src/components/composables/useTableSummary.test.ts +341 -0
  20. package/src/components/composables/useTableSummary.ts +129 -0
  21. package/src/components/filters/BoolFilter.vue +103 -0
  22. package/src/components/filters/DateRangeFilter.vue +194 -0
  23. package/src/components/filters/NumberRangeFilter.vue +160 -0
  24. package/src/components/filters/SelectFilter.vue +464 -0
  25. package/src/components/filters/TextFilter.vue +230 -0
  26. package/src/components/filters/index.ts +5 -0
  27. package/src/examples/EnhancedTableExample.vue +136 -0
  28. package/src/index.ts +32 -0
  29. package/src/main.ts +14 -0
  30. package/src/types/index.ts +159 -0
  31. package/src/utils/README.md +140 -0
  32. package/src/utils/schemaHelper.test.ts +215 -0
  33. package/src/utils/schemaHelper.ts +44 -0
  34. package/src/vite-env.d.ts +7 -0
package/dist/index.js ADDED
@@ -0,0 +1,1531 @@
1
+ import { defineComponent as U, ref as k, watch as P, computed as I, onMounted as ie, onUnmounted as ve, createElementBlock as _, openBlock as S, createElementVNode as y, createCommentVNode as L, withDirectives as ee, vModelText as te, withModifiers as H, Fragment as ae, renderList as oe, normalizeClass as W, toDisplayString as R, withKeys as de, resolveComponent as me, createVNode as Q, useAttrs as pe, useSlots as Te, provide as xe, renderSlot as Z, mergeProps as ue, toHandlers as he, withCtx as ge, h as q, createTextVNode as K, createBlock as Ee, resolveDynamicComponent as Me, createSlots as Ve, normalizeProps as Ie, guardReactiveProps as Oe } from "vue";
2
+ import Ae from "axios";
3
+ const Le = { class: "input-wrapper" }, Re = ["placeholder"], Ne = {
4
+ key: 0,
5
+ class: "filter-dropdown"
6
+ }, Be = ["onClick", "onMouseenter"], Pe = /* @__PURE__ */ U({
7
+ __name: "TextFilter",
8
+ props: {
9
+ field: {},
10
+ modelValue: {},
11
+ placeholder: { default: "搜索..." }
12
+ },
13
+ emits: ["update:modelValue"],
14
+ setup(u, { emit: h }) {
15
+ const i = u, d = h, e = k(""), l = k(!1), b = k(), t = k(0);
16
+ P(() => i.modelValue, (n) => {
17
+ if (!n || n.length === 0) {
18
+ e.value = "";
19
+ return;
20
+ }
21
+ const m = n[0];
22
+ m.op === "in" && Array.isArray(m.value) ? e.value = m.value.join(", ") : e.value = String(m.value || "").replace(/%/g, "");
23
+ }, { immediate: !0 });
24
+ const s = I(() => {
25
+ const n = e.value.trim();
26
+ return n ? [
27
+ { op: "=", label: `等于:${n}` },
28
+ { op: "right_like", label: `左匹配:${n}***` },
29
+ { op: "in", label: `批量查找:${n}` }
30
+ ] : [];
31
+ });
32
+ function a() {
33
+ e.value.trim() ? (l.value = !0, t.value = 0) : (l.value = !1, d("update:modelValue", null));
34
+ }
35
+ function o(n) {
36
+ const m = e.value.trim();
37
+ if (!m) return;
38
+ let g;
39
+ if (n === "in") {
40
+ const f = m.split(/[,,\s]+/).filter((C) => C.trim());
41
+ f.length === 1 ? g = { field: i.field, op: "=", value: f[0] } : g = { field: i.field, op: "in", value: f };
42
+ } else
43
+ g = { field: i.field, op: n, value: m };
44
+ d("update:modelValue", [g]), l.value = !1;
45
+ }
46
+ function c(n) {
47
+ if (!l.value || s.value.length === 0) {
48
+ n.key === "Enter" && e.value.trim() && (l.value = !0, t.value = 0);
49
+ return;
50
+ }
51
+ switch (n.key) {
52
+ case "ArrowDown":
53
+ n.preventDefault(), t.value = (t.value + 1) % s.value.length;
54
+ break;
55
+ case "ArrowUp":
56
+ n.preventDefault(), t.value = (t.value - 1 + s.value.length) % s.value.length;
57
+ break;
58
+ case "Enter":
59
+ n.preventDefault(), o(s.value[t.value].op);
60
+ break;
61
+ case "Escape":
62
+ l.value = !1;
63
+ break;
64
+ }
65
+ }
66
+ function w() {
67
+ e.value = "", l.value = !1, d("update:modelValue", null);
68
+ }
69
+ function D(n) {
70
+ b.value && !b.value.contains(n.target) && (l.value = !1);
71
+ }
72
+ return ie(() => {
73
+ document.addEventListener("click", D);
74
+ }), ve(() => {
75
+ document.removeEventListener("click", D);
76
+ }), (n, m) => (S(), _("div", {
77
+ ref_key: "containerRef",
78
+ ref: b,
79
+ class: "filter-text"
80
+ }, [
81
+ y("div", Le, [
82
+ ee(y("input", {
83
+ "onUpdate:modelValue": m[0] || (m[0] = (g) => e.value = g),
84
+ type: "text",
85
+ placeholder: u.placeholder,
86
+ onInput: a,
87
+ onKeydown: c,
88
+ onFocus: m[1] || (m[1] = (g) => e.value.trim() && (l.value = !0))
89
+ }, null, 40, Re), [
90
+ [te, e.value]
91
+ ]),
92
+ e.value ? (S(), _("span", {
93
+ key: 0,
94
+ class: "clear-btn",
95
+ onClick: H(w, ["stop"])
96
+ }, "×")) : L("", !0)
97
+ ]),
98
+ l.value && s.value.length > 0 ? (S(), _("div", Ne, [
99
+ (S(!0), _(ae, null, oe(s.value, (g, f) => (S(), _("div", {
100
+ key: g.op,
101
+ class: W(["filter-option", { highlighted: f === t.value }]),
102
+ onClick: (C) => o(g.op),
103
+ onMouseenter: (C) => t.value = f
104
+ }, R(g.label), 43, Be))), 128))
105
+ ])) : L("", !0)
106
+ ], 512));
107
+ }
108
+ }), z = (u, h) => {
109
+ const i = u.__vccOpts || u;
110
+ for (const [d, e] of h)
111
+ i[d] = e;
112
+ return i;
113
+ }, le = /* @__PURE__ */ z(Pe, [["__scopeId", "data-v-8fef729c"]]), Ue = { class: "filter-number-range" }, ze = ["placeholder"], Ye = ["placeholder"], Ge = /* @__PURE__ */ U({
114
+ __name: "NumberRangeFilter",
115
+ props: {
116
+ field: {},
117
+ modelValue: {},
118
+ placeholderMin: { default: "最小" },
119
+ placeholderMax: { default: "最大" }
120
+ },
121
+ emits: ["update:modelValue"],
122
+ setup(u, { emit: h }) {
123
+ const i = u, d = h, e = k(""), l = k("");
124
+ P(() => i.modelValue, (s) => {
125
+ if (!s || s.length === 0) {
126
+ e.value = "", l.value = "";
127
+ return;
128
+ }
129
+ const a = s.find((o) => o.op === "[]" || o.op === "[)");
130
+ if (a && Array.isArray(a.value)) {
131
+ const [o, c] = a.value;
132
+ e.value = o != null ? String(o) : "", l.value = c != null ? String(c) : "";
133
+ } else {
134
+ const o = s.find((w) => w.op === ">="), c = s.find((w) => w.op === "<=");
135
+ e.value = (o == null ? void 0 : o.value) != null ? String(o.value) : "", l.value = (c == null ? void 0 : c.value) != null ? String(c.value) : "";
136
+ }
137
+ }, { immediate: !0 });
138
+ function b() {
139
+ const s = e.value.trim(), a = l.value.trim();
140
+ if (!s && !a) {
141
+ d("update:modelValue", null);
142
+ return;
143
+ }
144
+ const o = s ? parseFloat(s) : null, c = a ? parseFloat(a) : null;
145
+ s && isNaN(o) || a && isNaN(c) || (o !== null && c !== null ? d("update:modelValue", [{
146
+ field: i.field,
147
+ op: "[]",
148
+ value: [o, c]
149
+ }]) : o !== null ? d("update:modelValue", [{
150
+ field: i.field,
151
+ op: ">=",
152
+ value: o
153
+ }]) : c !== null && d("update:modelValue", [{
154
+ field: i.field,
155
+ op: "<=",
156
+ value: c
157
+ }]));
158
+ }
159
+ function t() {
160
+ e.value = "", l.value = "", d("update:modelValue", null);
161
+ }
162
+ return (s, a) => (S(), _("div", Ue, [
163
+ ee(y("input", {
164
+ "onUpdate:modelValue": a[0] || (a[0] = (o) => e.value = o),
165
+ type: "text",
166
+ placeholder: u.placeholderMin,
167
+ onChange: b,
168
+ onKeyup: de(b, ["enter"])
169
+ }, null, 40, ze), [
170
+ [te, e.value]
171
+ ]),
172
+ a[2] || (a[2] = y("span", { class: "separator" }, "-", -1)),
173
+ ee(y("input", {
174
+ "onUpdate:modelValue": a[1] || (a[1] = (o) => l.value = o),
175
+ type: "text",
176
+ placeholder: u.placeholderMax,
177
+ onChange: b,
178
+ onKeyup: de(b, ["enter"])
179
+ }, null, 40, Ye), [
180
+ [te, l.value]
181
+ ]),
182
+ e.value || l.value ? (S(), _("span", {
183
+ key: 0,
184
+ class: "clear-btn",
185
+ onClick: t
186
+ }, "×")) : L("", !0)
187
+ ]));
188
+ }
189
+ }), be = /* @__PURE__ */ z(Ge, [["__scopeId", "data-v-e6401327"]]), je = { class: "filter-date-range" }, qe = /* @__PURE__ */ U({
190
+ __name: "DateRangeFilter",
191
+ props: {
192
+ field: {},
193
+ modelValue: {},
194
+ format: { default: "YYYY-MM-DD" },
195
+ showTime: { type: Boolean, default: !1 }
196
+ },
197
+ emits: ["update:modelValue"],
198
+ setup(u, { emit: h }) {
199
+ const i = u, d = h, e = k(null), l = I(() => {
200
+ var a;
201
+ return i.showTime || ((a = i.format) == null ? void 0 : a.includes("HH"));
202
+ }), b = I(() => l.value ? "YYYY-MM-DD HH:mm" : "YYYY-MM-DD");
203
+ P(() => i.modelValue, (a) => {
204
+ if (!a || a.length === 0) {
205
+ e.value = null;
206
+ return;
207
+ }
208
+ const o = a.find((c) => c.op === "[)" || c.op === "[]");
209
+ if (o && Array.isArray(o.value)) {
210
+ const [c, w] = o.value;
211
+ e.value = [
212
+ new Date(c.replace(" ", "T")),
213
+ new Date(w.replace(" ", "T"))
214
+ ];
215
+ } else {
216
+ const c = a.find((D) => D.op === ">="), w = a.find((D) => D.op === "<=" || D.op === "<");
217
+ if (c || w) {
218
+ const D = c ? new Date(String(c.value).replace(" ", "T")) : null, n = w ? new Date(String(w.value).replace(" ", "T")) : null;
219
+ D && n ? e.value = [D, n] : D ? e.value = [D, D] : n && (e.value = [n, n]);
220
+ } else
221
+ e.value = null;
222
+ }
223
+ }, { immediate: !0 });
224
+ function t(a) {
225
+ const o = a.getFullYear(), c = String(a.getMonth() + 1).padStart(2, "0"), w = String(a.getDate()).padStart(2, "0");
226
+ if (l.value) {
227
+ const D = String(a.getHours()).padStart(2, "0"), n = String(a.getMinutes()).padStart(2, "0"), m = String(a.getSeconds()).padStart(2, "0");
228
+ return `${o}-${c}-${w} ${D}:${n}:${m}`;
229
+ }
230
+ return `${o}-${c}-${w}`;
231
+ }
232
+ function s(a) {
233
+ if (!a || a.length !== 2) {
234
+ d("update:modelValue", null);
235
+ return;
236
+ }
237
+ const [o, c] = a, w = t(o);
238
+ let D;
239
+ if (l.value)
240
+ D = t(c);
241
+ else {
242
+ const n = new Date(c);
243
+ n.setDate(n.getDate() + 1), D = t(n);
244
+ }
245
+ d("update:modelValue", [{
246
+ field: i.field,
247
+ op: "[)",
248
+ value: [w, D]
249
+ }]);
250
+ }
251
+ return (a, o) => {
252
+ const c = me("el-date-picker");
253
+ return S(), _("div", je, [
254
+ Q(c, {
255
+ modelValue: e.value,
256
+ "onUpdate:modelValue": o[0] || (o[0] = (w) => e.value = w),
257
+ type: l.value ? "datetimerange" : "daterange",
258
+ format: b.value,
259
+ "range-separator": "~",
260
+ "start-placeholder": "开始",
261
+ "end-placeholder": "结束",
262
+ size: "small",
263
+ clearable: !0,
264
+ editable: !1,
265
+ onChange: s
266
+ }, null, 8, ["modelValue", "type", "format"])
267
+ ]);
268
+ };
269
+ }
270
+ }), ne = /* @__PURE__ */ z(qe, [["__scopeId", "data-v-4db2cb60"]]), We = {
271
+ key: 0,
272
+ class: "selected-text"
273
+ }, He = {
274
+ key: 1,
275
+ class: "placeholder-text"
276
+ }, Ke = ["title"], Qe = {
277
+ key: 0,
278
+ class: "filter-dropdown"
279
+ }, Je = { class: "search-box" }, Xe = { class: "options-container" }, Ze = {
280
+ key: 0,
281
+ class: "loading-hint"
282
+ }, et = ["onClick", "onMouseenter"], tt = ["checked"], at = { class: "option-label" }, lt = {
283
+ key: 0,
284
+ class: "no-data"
285
+ }, nt = {
286
+ key: 0,
287
+ class: "more-hint"
288
+ }, rt = {
289
+ key: 1,
290
+ class: "confirm-bar"
291
+ }, ot = { class: "selected-count" }, st = /* @__PURE__ */ U({
292
+ __name: "SelectFilter",
293
+ props: {
294
+ field: {},
295
+ modelValue: {},
296
+ options: {},
297
+ placeholder: { default: "请选择..." },
298
+ loading: { type: Boolean, default: !1 },
299
+ maxDisplayItems: { default: 100 }
300
+ },
301
+ emits: ["update:modelValue"],
302
+ setup(u, { emit: h }) {
303
+ const i = u, d = h, e = k(!1), l = k(!1), b = k(""), t = k(/* @__PURE__ */ new Set()), s = k(), a = k(0), o = k();
304
+ P(() => i.modelValue, ($) => {
305
+ if (t.value.clear(), !$ || $.length === 0) return;
306
+ const x = $[0];
307
+ x.op === "in" && Array.isArray(x.value) ? (l.value = !0, x.value.forEach((N) => t.value.add(N))) : x.op === "=" && (l.value = !1, t.value.add(x.value));
308
+ }, { immediate: !0 });
309
+ const c = I(() => {
310
+ if (!b.value.trim())
311
+ return i.options;
312
+ const $ = b.value.toLowerCase();
313
+ return i.options.filter(
314
+ (x) => x.label.toLowerCase().includes($) || String(x.value).toLowerCase().includes($)
315
+ );
316
+ }), w = I(() => c.value.slice(0, i.maxDisplayItems)), D = I(() => c.value.length > i.maxDisplayItems), n = I(() => {
317
+ if (t.value.size === 0)
318
+ return "";
319
+ const $ = i.options.filter((x) => t.value.has(x.value));
320
+ return $.length === 0 ? Array.from(t.value).join(", ") : $.length <= 2 ? $.map((x) => x.label).join(", ") : `已选 ${$.length} 项`;
321
+ });
322
+ function m() {
323
+ e.value = !e.value, e.value && (b.value = "", a.value = 0, setTimeout(() => {
324
+ var $;
325
+ return ($ = o.value) == null ? void 0 : $.focus();
326
+ }, 0));
327
+ }
328
+ function g() {
329
+ if (l.value = !l.value, !l.value && t.value.size > 1) {
330
+ const $ = t.value.values().next().value;
331
+ t.value.clear(), $ !== void 0 && t.value.add($), B();
332
+ }
333
+ }
334
+ function f($) {
335
+ return t.value.has($.value);
336
+ }
337
+ function C($) {
338
+ l.value ? t.value.has($.value) ? t.value.delete($.value) : t.value.add($.value) : (t.value.clear(), t.value.add($.value), B(), e.value = !1);
339
+ }
340
+ function V() {
341
+ B(), e.value = !1;
342
+ }
343
+ function B() {
344
+ if (t.value.size === 0) {
345
+ d("update:modelValue", null);
346
+ return;
347
+ }
348
+ l.value || t.value.size > 1 ? d("update:modelValue", [{
349
+ field: i.field,
350
+ op: "in",
351
+ value: Array.from(t.value)
352
+ }]) : d("update:modelValue", [{
353
+ field: i.field,
354
+ op: "=",
355
+ value: t.value.values().next().value
356
+ }]);
357
+ }
358
+ function j() {
359
+ t.value.clear(), b.value = "", e.value = !1, d("update:modelValue", null);
360
+ }
361
+ function T() {
362
+ a.value = 0;
363
+ }
364
+ function M($) {
365
+ if (!e.value) return;
366
+ const x = w.value;
367
+ if (x.length !== 0)
368
+ switch ($.key) {
369
+ case "ArrowDown":
370
+ $.preventDefault(), a.value = (a.value + 1) % x.length;
371
+ break;
372
+ case "ArrowUp":
373
+ $.preventDefault(), a.value = (a.value - 1 + x.length) % x.length;
374
+ break;
375
+ case "Enter":
376
+ $.preventDefault(), x[a.value] && C(x[a.value]);
377
+ break;
378
+ case "Escape":
379
+ e.value = !1;
380
+ break;
381
+ }
382
+ }
383
+ function Y($) {
384
+ s.value && !s.value.contains($.target) && (e.value && l.value && B(), e.value = !1);
385
+ }
386
+ return ie(() => {
387
+ document.addEventListener("click", Y);
388
+ }), ve(() => {
389
+ document.removeEventListener("click", Y);
390
+ }), ($, x) => (S(), _("div", {
391
+ ref_key: "containerRef",
392
+ ref: s,
393
+ class: "filter-select"
394
+ }, [
395
+ y("div", {
396
+ class: "select-input",
397
+ onClick: m
398
+ }, [
399
+ n.value ? (S(), _("span", We, R(n.value), 1)) : (S(), _("span", He, R(u.placeholder), 1)),
400
+ y("span", {
401
+ class: "toggle-multi",
402
+ onClick: H(g, ["stop"]),
403
+ title: l.value ? "切换单选" : "切换多选"
404
+ }, R(l.value ? "多" : "单"), 9, Ke),
405
+ n.value ? (S(), _("span", {
406
+ key: 2,
407
+ class: "clear-btn",
408
+ onClick: H(j, ["stop"])
409
+ }, "×")) : L("", !0)
410
+ ]),
411
+ e.value ? (S(), _("div", Qe, [
412
+ y("div", Je, [
413
+ ee(y("input", {
414
+ ref_key: "searchInputRef",
415
+ ref: o,
416
+ "onUpdate:modelValue": x[0] || (x[0] = (N) => b.value = N),
417
+ type: "text",
418
+ placeholder: "搜索...",
419
+ onClick: x[1] || (x[1] = H(() => {
420
+ }, ["stop"])),
421
+ onInput: T,
422
+ onKeydown: M
423
+ }, null, 544), [
424
+ [te, b.value]
425
+ ])
426
+ ]),
427
+ y("div", Xe, [
428
+ u.loading ? (S(), _("div", Ze, " 加载中... ")) : (S(), _(ae, { key: 1 }, [
429
+ (S(!0), _(ae, null, oe(w.value, (N, G) => (S(), _("div", {
430
+ key: String(N.value),
431
+ class: W(["filter-option", { selected: f(N), highlighted: G === a.value }]),
432
+ onClick: (X) => C(N),
433
+ onMouseenter: (X) => a.value = G
434
+ }, [
435
+ l.value ? (S(), _("input", {
436
+ key: 0,
437
+ type: "checkbox",
438
+ checked: f(N),
439
+ onClick: x[2] || (x[2] = H(() => {
440
+ }, ["stop"]))
441
+ }, null, 8, tt)) : L("", !0),
442
+ y("span", at, R(N.label), 1)
443
+ ], 42, et))), 128)),
444
+ w.value.length === 0 ? (S(), _("div", lt, " 无匹配数据 ")) : L("", !0)
445
+ ], 64))
446
+ ]),
447
+ D.value ? (S(), _("div", nt, " 还有 " + R(c.value.length - u.maxDisplayItems) + " 条,请输入关键词搜索 ", 1)) : L("", !0),
448
+ l.value ? (S(), _("div", rt, [
449
+ y("span", ot, "已选 " + R(t.value.size) + " 项", 1),
450
+ y("button", {
451
+ class: "confirm-btn",
452
+ onClick: V
453
+ }, "确定")
454
+ ])) : L("", !0)
455
+ ])) : L("", !0)
456
+ ], 512));
457
+ }
458
+ }), re = /* @__PURE__ */ z(st, [["__scopeId", "data-v-051a86c4"]]), it = { class: "filter-bool" }, ut = /* @__PURE__ */ U({
459
+ __name: "BoolFilter",
460
+ props: {
461
+ field: {},
462
+ modelValue: {},
463
+ trueLabel: { default: "是" },
464
+ falseLabel: { default: "否" }
465
+ },
466
+ emits: ["update:modelValue"],
467
+ setup(u, { emit: h }) {
468
+ const i = u, d = h, e = k(null);
469
+ P(() => i.modelValue, (b) => {
470
+ if (!b || b.length === 0) {
471
+ e.value = null;
472
+ return;
473
+ }
474
+ const t = b[0];
475
+ t.op === "=" ? e.value = t.value === !0 || t.value === "true" || t.value === 1 : e.value = null;
476
+ }, { immediate: !0 });
477
+ function l(b) {
478
+ e.value = b, b === null ? d("update:modelValue", null) : d("update:modelValue", [{
479
+ field: i.field,
480
+ op: "=",
481
+ value: b
482
+ }]);
483
+ }
484
+ return (b, t) => (S(), _("div", it, [
485
+ y("button", {
486
+ class: W({ active: e.value === null }),
487
+ onClick: t[0] || (t[0] = (s) => l(null))
488
+ }, " 全部 ", 2),
489
+ y("button", {
490
+ class: W({ active: e.value === !0 }),
491
+ onClick: t[1] || (t[1] = (s) => l(!0))
492
+ }, R(u.trueLabel), 3),
493
+ y("button", {
494
+ class: W({ active: e.value === !1 }),
495
+ onClick: t[2] || (t[2] = (s) => l(!1))
496
+ }, R(u.falseLabel), 3)
497
+ ]));
498
+ }
499
+ }), ye = /* @__PURE__ */ z(ut, [["__scopeId", "data-v-b6f20e4b"]]);
500
+ function ct() {
501
+ const u = k([]);
502
+ function h({ records: l }) {
503
+ u.value = l;
504
+ }
505
+ function i({ records: l }) {
506
+ u.value = l;
507
+ }
508
+ function d() {
509
+ u.value = [];
510
+ }
511
+ function e() {
512
+ return u.value.length;
513
+ }
514
+ return {
515
+ selectedRows: u,
516
+ onCheckboxChange: h,
517
+ onCheckboxAll: i,
518
+ clearSelection: d,
519
+ getSelectedCount: e
520
+ };
521
+ }
522
+ const fe = ["NUMBER", "MONEY", "BIGDECIMAL", "INTEGER", "BIGINT", "LONG"];
523
+ function dt(u) {
524
+ const h = k(null), i = I(() => u.value.filter(
525
+ (t) => {
526
+ var s;
527
+ return fe.includes(((s = t.type) == null ? void 0 : s.toUpperCase()) || "");
528
+ }
529
+ ));
530
+ function d(t) {
531
+ const s = {
532
+ _count: t.length
533
+ };
534
+ for (const a of i.value)
535
+ s[a.name] = t.reduce((o, c) => {
536
+ const w = c[a.name];
537
+ return o + (typeof w == "number" ? w : 0);
538
+ }, 0);
539
+ return s;
540
+ }
541
+ function e(t, s) {
542
+ if (t == null) return "";
543
+ if (typeof t != "number") return String(t);
544
+ const a = s == null ? void 0 : s.toUpperCase();
545
+ return a === "MONEY" || a === "NUMBER" || a === "BIGDECIMAL" ? t.toLocaleString("zh-CN", {
546
+ minimumFractionDigits: 2,
547
+ maximumFractionDigits: 2
548
+ }) : t.toLocaleString("zh-CN");
549
+ }
550
+ function l(t, s) {
551
+ var c, w, D;
552
+ const a = [], o = [];
553
+ for (let n = 0; n < t.length; n++) {
554
+ const g = t[n].field;
555
+ if (n === 0) {
556
+ a.push("选中"), o.push("合计");
557
+ continue;
558
+ }
559
+ if (n === 1) {
560
+ const f = s._count || 0, C = ((c = h.value) == null ? void 0 : c.total) || 0;
561
+ a.push(`${f} 条`), o.push(`${C} 条`);
562
+ continue;
563
+ }
564
+ if (g) {
565
+ const f = u.value.find((V) => V.name === g);
566
+ if (f && fe.includes(((w = f.type) == null ? void 0 : w.toUpperCase()) || "")) {
567
+ const V = s[g], B = (D = h.value) == null ? void 0 : D[g];
568
+ a.push(e(V, f == null ? void 0 : f.type)), o.push(e(B, f == null ? void 0 : f.type));
569
+ } else
570
+ a.push(null), o.push(null);
571
+ } else
572
+ a.push(null), o.push(null);
573
+ }
574
+ return [a, o];
575
+ }
576
+ function b(t) {
577
+ h.value = t;
578
+ }
579
+ return {
580
+ serverSummary: h,
581
+ measureColumns: i,
582
+ calculateSelectedSummary: d,
583
+ generateFooterData: l,
584
+ setServerSummary: b,
585
+ formatValue: e
586
+ };
587
+ }
588
+ const ft = { class: "data-table" }, vt = {
589
+ key: 0,
590
+ class: "data-table-toolbar"
591
+ }, mt = { class: "table-wrapper" }, pt = {
592
+ key: 1,
593
+ class: "data-table-footer"
594
+ }, ht = /* @__PURE__ */ U({
595
+ inheritAttrs: !1,
596
+ __name: "DataTable",
597
+ props: {
598
+ columns: {},
599
+ data: {},
600
+ total: {},
601
+ loading: { type: Boolean },
602
+ pageSize: { default: 50 },
603
+ showFilters: { type: Boolean, default: !0 },
604
+ initialSlice: {},
605
+ serverSummary: {},
606
+ filterOptionsLoader: {},
607
+ customFilterComponents: {}
608
+ },
609
+ emits: ["page-change", "sort-change", "filter-change", "row-click", "row-dblclick"],
610
+ setup(u, { expose: h, emit: i }) {
611
+ const d = pe(), e = u, l = i, b = Te(), t = k(), s = k({
612
+ currentPage: 1,
613
+ pageSize: e.pageSize,
614
+ total: e.total
615
+ }), a = k({
616
+ field: null,
617
+ order: null
618
+ }), o = k({}), c = k({}), w = k({}), D = I(() => e.columns), { selectedRows: n, onCheckboxChange: m, onCheckboxAll: g, clearSelection: f } = ct(), { serverSummary: C, calculateSelectedSummary: V, generateFooterData: B, setServerSummary: j } = dt(D);
619
+ P(() => e.serverSummary, (r) => {
620
+ j(r ?? null);
621
+ }, { immediate: !0 });
622
+ const T = I(() => {
623
+ var F;
624
+ const r = V(n.value), p = ((F = ce.value) == null ? void 0 : F.map((v) => {
625
+ var E;
626
+ return {
627
+ field: v.field,
628
+ type: (E = e.columns.find((A) => A.name === v.field)) == null ? void 0 : E.type
629
+ };
630
+ })) || [];
631
+ return B(p, r);
632
+ });
633
+ P(() => e.total, (r) => {
634
+ s.value.total = r;
635
+ }), P(() => e.initialSlice, (r) => {
636
+ if (!r || r.length === 0) return;
637
+ const p = {};
638
+ for (const F of r)
639
+ F.field && (p[F.field] || (p[F.field] = []), p[F.field].push(F));
640
+ o.value = p;
641
+ }, { immediate: !0 });
642
+ async function M(r) {
643
+ if (c.value[r])
644
+ return c.value[r];
645
+ if (!e.filterOptionsLoader)
646
+ return [];
647
+ w.value[r] = !0;
648
+ try {
649
+ const p = await e.filterOptionsLoader(r);
650
+ return c.value[r] = p, p;
651
+ } catch (p) {
652
+ return console.error("Failed to load dimension options:", p), [];
653
+ } finally {
654
+ w.value[r] = !1;
655
+ }
656
+ }
657
+ function Y(r) {
658
+ var F;
659
+ const p = (F = r.type) == null ? void 0 : F.toUpperCase();
660
+ switch (p) {
661
+ case "DAY":
662
+ case "DATE":
663
+ return "date";
664
+ case "DATETIME":
665
+ return "datetime";
666
+ }
667
+ if (r.filterType)
668
+ return r.filterType;
669
+ switch (p) {
670
+ case "NUMBER":
671
+ case "MONEY":
672
+ case "BIGDECIMAL":
673
+ case "INTEGER":
674
+ case "BIGINT":
675
+ case "LONG":
676
+ return "number";
677
+ case "BOOL":
678
+ case "BOOLEAN":
679
+ return "bool";
680
+ case "DICT":
681
+ return "dict";
682
+ default:
683
+ return "text";
684
+ }
685
+ }
686
+ function $(r) {
687
+ if (r.customFilterComponent)
688
+ return r.customFilterComponent;
689
+ const p = Y(r);
690
+ if (e.customFilterComponents && e.customFilterComponents[p])
691
+ return e.customFilterComponents[p];
692
+ switch (p) {
693
+ case "text":
694
+ return le;
695
+ case "number":
696
+ return be;
697
+ case "date":
698
+ return ne;
699
+ case "datetime":
700
+ return ne;
701
+ case "dict":
702
+ return re;
703
+ case "dimension":
704
+ return re;
705
+ case "bool":
706
+ return ye;
707
+ default:
708
+ return le;
709
+ }
710
+ }
711
+ function x(r) {
712
+ return r.endsWith("$id") ? r : r.includes("$") ? `${r.substring(0, r.indexOf("$"))}$id` : `${r}$id`;
713
+ }
714
+ function N(r) {
715
+ const p = Y(r), F = {
716
+ field: r.name,
717
+ modelValue: o.value[r.name] || null,
718
+ "onUpdate:modelValue": (v) => G(r.name, v)
719
+ };
720
+ switch (p) {
721
+ case "datetime":
722
+ return { ...F, showTime: !0, format: r.format };
723
+ case "date":
724
+ return { ...F, format: r.format };
725
+ case "dict":
726
+ return {
727
+ ...F,
728
+ options: r.dictItems || [],
729
+ placeholder: r.title || "请选择"
730
+ };
731
+ case "dimension": {
732
+ c.value[r.name] || M(r.name);
733
+ const v = x(r.name);
734
+ return {
735
+ ...F,
736
+ field: v,
737
+ // 使用正确的过滤字段($id)
738
+ modelValue: o.value[v] || o.value[r.name] || null,
739
+ "onUpdate:modelValue": (E) => G(v, E),
740
+ options: c.value[r.name] || [],
741
+ loading: w.value[r.name],
742
+ placeholder: r.title || "请选择"
743
+ };
744
+ }
745
+ default:
746
+ return F;
747
+ }
748
+ }
749
+ function G(r, p) {
750
+ p === null || p.length === 0 ? delete o.value[r] : o.value[r] = p, X();
751
+ }
752
+ function X() {
753
+ const r = [];
754
+ for (const p of Object.values(o.value))
755
+ p && p.length > 0 && r.push(...p);
756
+ l("filter-change", r);
757
+ }
758
+ function we(r) {
759
+ var F;
760
+ if (r.customFormatter)
761
+ return {
762
+ formatter: ({ cellValue: v }) => r.customFormatter(v)
763
+ };
764
+ switch ((F = r.type) == null ? void 0 : F.toUpperCase()) {
765
+ case "MONEY":
766
+ case "NUMBER":
767
+ case "BIGDECIMAL":
768
+ return {
769
+ formatter: ({ cellValue: v }) => v == null ? "" : typeof v == "number" ? v.toLocaleString("zh-CN", { minimumFractionDigits: 2, maximumFractionDigits: 2 }) : v
770
+ };
771
+ case "INTEGER":
772
+ case "BIGINT":
773
+ case "LONG":
774
+ return {
775
+ formatter: ({ cellValue: v }) => v == null ? "" : typeof v == "number" ? v.toLocaleString("zh-CN") : v
776
+ };
777
+ case "DAY":
778
+ case "DATE":
779
+ return {
780
+ formatter: ({ cellValue: v }) => v ? String(v).split("T")[0] : ""
781
+ };
782
+ case "DATETIME":
783
+ return {
784
+ minWidth: 160,
785
+ formatter: ({ cellValue: v }) => v ? String(v).replace("T", " ").substring(0, 19) : ""
786
+ };
787
+ case "BOOL":
788
+ case "BOOLEAN":
789
+ return {
790
+ formatter: ({ cellValue: v }) => v === !0 ? "是" : v === !1 ? "否" : ""
791
+ };
792
+ default:
793
+ return {};
794
+ }
795
+ }
796
+ function Se(r) {
797
+ const p = a.value.field === r ? a.value.order : null;
798
+ let F;
799
+ p === null ? F = "asc" : p === "asc" ? F = "desc" : F = null, a.value.field = F ? r : null, a.value.order = F, l("sort-change", a.value.field, a.value.order);
800
+ }
801
+ const ce = I(() => {
802
+ const r = a.value, p = {
803
+ type: "checkbox",
804
+ width: 50,
805
+ fixed: "left"
806
+ }, F = e.columns.map((v) => {
807
+ const E = {
808
+ field: v.name,
809
+ title: v.title || v.name,
810
+ width: v.width,
811
+ minWidth: v.minWidth ?? 120,
812
+ fixed: v.fixed,
813
+ sortable: !1,
814
+ // 禁用 vxe-table 内置排序,我们自己处理
815
+ ...we(v),
816
+ // 使用 slots 在表头渲染过滤器
817
+ slots: {
818
+ header: () => {
819
+ const O = r.field === v.name ? r.order : null;
820
+ return q("div", { class: "column-header-wrapper" }, [
821
+ q("div", {
822
+ class: "column-title",
823
+ onClick: () => Se(v.name)
824
+ }, [
825
+ q("span", { class: "title-text" }, v.title || v.name),
826
+ q(
827
+ "span",
828
+ { class: ["sort-icon", O ? `sort-${O}` : ""] },
829
+ O === "asc" ? " ↑" : O === "desc" ? " ↓" : " ↕"
830
+ )
831
+ ]),
832
+ e.showFilters && q("div", { class: "column-filter" }, [
833
+ ke(v)
834
+ ])
835
+ ]);
836
+ }
837
+ }
838
+ }, A = `column-${v.name}`;
839
+ return b[A] ? E.slots = {
840
+ ...E.slots,
841
+ default: ({ row: O }) => b[A]({ row: O, column: v, value: O[v.name] })
842
+ } : v.customRender && (E.slots = {
843
+ ...E.slots,
844
+ default: ({ row: O }) => v.customRender({ row: O, value: O[v.name] })
845
+ }), E;
846
+ });
847
+ return [p, ...F];
848
+ });
849
+ function ke(r) {
850
+ const p = `filter-${r.name}`;
851
+ if (b[p])
852
+ return b[p]({
853
+ column: r,
854
+ field: r.name,
855
+ modelValue: o.value[r.name] || null,
856
+ onChange: (E) => G(r.name, E)
857
+ });
858
+ const F = $(r), v = N(r);
859
+ return q(F, v);
860
+ }
861
+ const _e = I(() => {
862
+ const r = Object.keys(d).filter((F) => !F.startsWith("on")).reduce((F, v) => ({ ...F, [v]: d[v] }), {});
863
+ return { ...{
864
+ border: !0,
865
+ stripe: !0,
866
+ showOverflow: !0,
867
+ height: "auto",
868
+ loading: e.loading,
869
+ columnConfig: {
870
+ resizable: !0
871
+ },
872
+ rowConfig: {
873
+ isHover: !0
874
+ },
875
+ // checkbox 配置
876
+ checkboxConfig: {
877
+ highlight: !0,
878
+ trigger: "cell"
879
+ },
880
+ // footer 配置
881
+ showFooter: !0,
882
+ footerData: T.value,
883
+ // 表头行高需要容纳过滤器
884
+ headerRowClassName: e.showFilters ? "header-with-filter" : "",
885
+ pagerConfig: {
886
+ enabled: !0,
887
+ currentPage: s.value.currentPage,
888
+ pageSize: s.value.pageSize,
889
+ total: s.value.total,
890
+ pageSizes: [20, 50, 100, 200],
891
+ layouts: ["PrevPage", "JumpNumber", "NextPage", "Sizes", "FullJump", "Total"]
892
+ },
893
+ // 禁用 vxe-table 内置排序,我们自己处理
894
+ sortConfig: {
895
+ remote: !0
896
+ },
897
+ columns: ce.value,
898
+ data: e.data
899
+ }, ...r };
900
+ }), $e = I(() => {
901
+ const r = {};
902
+ Object.keys(d).forEach((E) => {
903
+ if (E.startsWith("on")) {
904
+ const A = E.slice(2, 3).toLowerCase() + E.slice(3);
905
+ r[A] = d[E];
906
+ }
907
+ });
908
+ const p = (E, A) => (...O) => {
909
+ E(...O), r[A] && r[A](...O);
910
+ }, v = { ...{
911
+ pageChange: p(({ currentPage: E, pageSize: A }) => {
912
+ s.value.currentPage = E, s.value.pageSize = A, l("page-change", E, A);
913
+ }, "pageChange"),
914
+ cellClick: p(({ row: E, column: A }) => {
915
+ const O = e.columns.find((se) => se.name === A.field);
916
+ O && l("row-click", E, O);
917
+ }, "cellClick"),
918
+ cellDblclick: p(({ row: E, column: A }) => {
919
+ const O = e.columns.find((se) => se.name === A.field);
920
+ O && l("row-dblclick", E, O);
921
+ }, "cellDblclick"),
922
+ checkboxChange: p(m, "checkboxChange"),
923
+ checkboxAll: p(g, "checkboxAll")
924
+ } };
925
+ return Object.keys(r).forEach((E) => {
926
+ v[E] || (v[E] = r[E]);
927
+ }), v;
928
+ });
929
+ function Fe() {
930
+ s.value.currentPage = 1;
931
+ }
932
+ function De() {
933
+ o.value = {}, X();
934
+ }
935
+ return h({
936
+ resetPagination: Fe,
937
+ clearFilters: De,
938
+ /** 获取当前过滤状态 (DSL slices) */
939
+ getFilters: () => {
940
+ const r = [];
941
+ for (const p of Object.values(o.value))
942
+ p && p.length > 0 && r.push(...p);
943
+ return r;
944
+ },
945
+ /** 设置过滤值 */
946
+ setFilter: G,
947
+ /** 获取 vxe-grid 实例 */
948
+ getGridInstance: () => t.value
949
+ }), xe("dataTableContext", {
950
+ columns: I(() => e.columns),
951
+ filters: o,
952
+ updateFilter: G
953
+ }), (r, p) => {
954
+ const F = me("vxe-grid");
955
+ return S(), _("div", ft, [
956
+ r.$slots.toolbar ? (S(), _("div", vt, [
957
+ Z(r.$slots, "toolbar", {}, void 0, !0)
958
+ ])) : L("", !0),
959
+ y("div", mt, [
960
+ Q(F, ue({
961
+ ref_key: "gridRef",
962
+ ref: t
963
+ }, _e.value, he($e.value)), {
964
+ empty: ge(() => [
965
+ Z(r.$slots, "empty", {}, () => [
966
+ p[0] || (p[0] = y("div", { class: "empty-data" }, "暂无数据", -1))
967
+ ], !0)
968
+ ]),
969
+ _: 3
970
+ }, 16)
971
+ ]),
972
+ r.$slots.footer ? (S(), _("div", pt, [
973
+ Z(r.$slots, "footer", {}, void 0, !0)
974
+ ])) : L("", !0)
975
+ ]);
976
+ };
977
+ }
978
+ }), Ce = /* @__PURE__ */ z(ht, [["__scopeId", "data-v-e12c7b39"]]), J = Ae.create({
979
+ baseURL: "/data-viewer/api",
980
+ timeout: 3e4,
981
+ headers: {
982
+ "Content-Type": "application/json"
983
+ }
984
+ });
985
+ async function gt(u) {
986
+ var i;
987
+ const h = await J.get(`/query/${u}/meta`);
988
+ if (!h.data || h.data.code !== 200)
989
+ throw new Error(((i = h.data) == null ? void 0 : i.msg) || "获取查询元数据失败");
990
+ return h.data.data;
991
+ }
992
+ async function bt(u, h) {
993
+ var d, e, l;
994
+ const i = await J.post(`/query/${u}/data`, h);
995
+ if (!i.data || i.data.code !== 200) {
996
+ if ((e = (d = i.data) == null ? void 0 : d.data) != null && e.expired)
997
+ return i.data.data;
998
+ throw new Error(((l = i.data) == null ? void 0 : l.msg) || "查询数据失败");
999
+ }
1000
+ return i.data.data;
1001
+ }
1002
+ async function yt(u, h) {
1003
+ return (await J.get(
1004
+ `/query/${u}/filter-options/${encodeURIComponent(h)}`
1005
+ )).data;
1006
+ }
1007
+ async function Ct(u) {
1008
+ var e;
1009
+ const h = await J.get(`/schema/${encodeURIComponent(u)}`);
1010
+ if (!h.data || h.data.code !== 200)
1011
+ throw new Error(((e = h.data) == null ? void 0 : e.msg) || "获取 QM Schema 失败");
1012
+ const i = h.data.data;
1013
+ if (!i || !i.fields)
1014
+ return [];
1015
+ const d = [];
1016
+ for (const [l, b] of Object.entries(i.fields)) {
1017
+ const t = b;
1018
+ d.push({
1019
+ name: l,
1020
+ title: t.name || l,
1021
+ type: t.type || "TEXT",
1022
+ filterable: t.filterable !== !1,
1023
+ aggregatable: t.aggregatable || !1,
1024
+ measure: t.measure || !1,
1025
+ filterType: t.filterType,
1026
+ dictId: t.dictId,
1027
+ format: t.format
1028
+ });
1029
+ }
1030
+ return d;
1031
+ }
1032
+ J.interceptors.response.use(
1033
+ (u) => u,
1034
+ (u) => {
1035
+ var h, i;
1036
+ return ((h = u.response) == null ? void 0 : h.status) === 410 ? Promise.reject(new Error("查询链接已过期,请重新获取")) : ((i = u.response) == null ? void 0 : i.status) === 404 ? Promise.reject(new Error("查询不存在")) : Promise.reject(u);
1037
+ }
1038
+ );
1039
+ function wt(u, h) {
1040
+ var b;
1041
+ const i = new Map(u.map((t) => [t.name, t])), d = new Map(((b = h.customizations) == null ? void 0 : b.map((t) => [t.name, t])) || []);
1042
+ return (h.showAll || !h.visibleColumns || h.visibleColumns.length === 0 ? u.map((t) => t.name) : h.visibleColumns).map((t) => {
1043
+ const s = i.get(t);
1044
+ if (!s)
1045
+ return console.warn(`Column "${t}" not found in QM schema`), null;
1046
+ const a = d.get(t);
1047
+ return {
1048
+ ...s,
1049
+ width: a == null ? void 0 : a.width,
1050
+ minWidth: (a == null ? void 0 : a.minWidth) ?? 120,
1051
+ fixed: a == null ? void 0 : a.fixed,
1052
+ customRender: a == null ? void 0 : a.render,
1053
+ customFilterComponent: a == null ? void 0 : a.filterComponent,
1054
+ customFormatter: a == null ? void 0 : a.formatter
1055
+ };
1056
+ }).filter((t) => t !== null);
1057
+ }
1058
+ const St = { class: "data-viewer" }, kt = { class: "viewer-header" }, _t = { class: "viewer-title" }, $t = { class: "viewer-info" }, Ft = {
1059
+ key: 0,
1060
+ class: "info-item"
1061
+ }, Dt = {
1062
+ key: 1,
1063
+ class: "info-item"
1064
+ }, Tt = {
1065
+ key: 2,
1066
+ class: "info-item"
1067
+ }, xt = ["disabled"], Et = {
1068
+ key: 0,
1069
+ class: "viewer-expired"
1070
+ }, Mt = {
1071
+ key: 1,
1072
+ class: "viewer-error"
1073
+ }, Vt = { class: "error-content" }, It = {
1074
+ key: 2,
1075
+ class: "viewer-main"
1076
+ }, Ot = /* @__PURE__ */ U({
1077
+ __name: "DataViewer",
1078
+ props: {
1079
+ queryId: {}
1080
+ },
1081
+ setup(u) {
1082
+ const h = u, i = k(!1), d = k(null), e = k(!1), l = k(null), b = k([]), t = k([]), s = k([]), a = k(0), o = k(null), c = k({
1083
+ start: 0,
1084
+ limit: 50,
1085
+ slice: [],
1086
+ orderBy: []
1087
+ }), w = k(), D = I(() => {
1088
+ var T;
1089
+ return ((T = l.value) == null ? void 0 : T.title) || "数据浏览器";
1090
+ }), n = I(() => {
1091
+ var T;
1092
+ return (T = l.value) != null && T.expiresAt ? new Date(l.value.expiresAt).toLocaleString("zh-CN") : "";
1093
+ });
1094
+ async function m() {
1095
+ try {
1096
+ i.value = !0, d.value = null, l.value = await gt(h.queryId), l.value.tableConfig.qmModel && (b.value = await Ct(l.value.tableConfig.qmModel), t.value = wt(b.value, l.value.tableConfig));
1097
+ } catch (T) {
1098
+ d.value = T instanceof Error ? T.message : "加载元数据失败";
1099
+ } finally {
1100
+ i.value = !1;
1101
+ }
1102
+ }
1103
+ async function g() {
1104
+ if (l.value)
1105
+ try {
1106
+ i.value = !0, d.value = null;
1107
+ const T = await bt(h.queryId, c.value);
1108
+ if (T.expired) {
1109
+ e.value = !0, d.value = T.errorMessage || "查询已过期";
1110
+ return;
1111
+ }
1112
+ if (!T.success) {
1113
+ d.value = T.errorMessage || "查询失败";
1114
+ return;
1115
+ }
1116
+ s.value = T.items, a.value = T.total, o.value = T.totalData ?? null;
1117
+ } catch (T) {
1118
+ d.value = T instanceof Error ? T.message : "加载数据失败";
1119
+ } finally {
1120
+ i.value = !1;
1121
+ }
1122
+ }
1123
+ function f(T, M) {
1124
+ c.value.start = (T - 1) * M, c.value.limit = M, g();
1125
+ }
1126
+ function C(T, M) {
1127
+ T && M ? c.value.orderBy = [{ field: T, order: M }] : c.value.orderBy = [], g();
1128
+ }
1129
+ function V(T) {
1130
+ var M;
1131
+ c.value.slice = T, c.value.start = 0, (M = w.value) == null || M.resetPagination(), g();
1132
+ }
1133
+ async function B(T) {
1134
+ try {
1135
+ return (await yt(h.queryId, T)).options || [];
1136
+ } catch (M) {
1137
+ return console.error("Failed to load filter options:", M), [];
1138
+ }
1139
+ }
1140
+ function j() {
1141
+ g();
1142
+ }
1143
+ return ie(async () => {
1144
+ await m(), l.value && (l.value.initialSlice && l.value.initialSlice.length > 0 && (c.value.slice = l.value.initialSlice), await g());
1145
+ }), (T, M) => {
1146
+ var Y, $, x, N;
1147
+ return S(), _("div", St, [
1148
+ y("header", kt, [
1149
+ y("h1", _t, R(D.value), 1),
1150
+ y("div", $t, [
1151
+ ($ = (Y = l.value) == null ? void 0 : Y.tableConfig) != null && $.qmModel ? (S(), _("span", Ft, [
1152
+ M[0] || (M[0] = K(" 模型: ", -1)),
1153
+ y("strong", null, R(l.value.tableConfig.qmModel), 1)
1154
+ ])) : L("", !0),
1155
+ (x = l.value) != null && x.estimatedRowCount ? (S(), _("span", Dt, [
1156
+ M[1] || (M[1] = K(" 预估行数: ", -1)),
1157
+ y("strong", null, R(l.value.estimatedRowCount.toLocaleString()), 1)
1158
+ ])) : L("", !0),
1159
+ n.value ? (S(), _("span", Tt, [
1160
+ M[2] || (M[2] = K(" 过期时间: ", -1)),
1161
+ y("strong", null, R(n.value), 1)
1162
+ ])) : L("", !0),
1163
+ y("button", {
1164
+ class: "refresh-btn",
1165
+ onClick: j,
1166
+ disabled: i.value
1167
+ }, " 刷新 ", 8, xt)
1168
+ ])
1169
+ ]),
1170
+ e.value ? (S(), _("div", Et, [...M[3] || (M[3] = [
1171
+ y("div", { class: "expired-content" }, [
1172
+ y("h2", null, "链接已过期"),
1173
+ y("p", null, "请联系AI助手重新生成查询链接")
1174
+ ], -1)
1175
+ ])])) : d.value && !s.value.length ? (S(), _("div", Mt, [
1176
+ y("div", Vt, [
1177
+ M[4] || (M[4] = y("h2", null, "加载失败", -1)),
1178
+ y("p", null, R(d.value), 1),
1179
+ y("button", { onClick: g }, "重试")
1180
+ ])
1181
+ ])) : (S(), _("main", It, [
1182
+ Q(Ce, {
1183
+ ref_key: "dataTableRef",
1184
+ ref: w,
1185
+ columns: t.value,
1186
+ data: s.value,
1187
+ total: a.value,
1188
+ loading: i.value,
1189
+ "initial-slice": (N = l.value) == null ? void 0 : N.initialSlice,
1190
+ "filter-options-loader": B,
1191
+ "server-summary": o.value,
1192
+ onPageChange: f,
1193
+ onSortChange: C,
1194
+ onFilterChange: V
1195
+ }, null, 8, ["columns", "data", "total", "loading", "initial-slice", "server-summary"])
1196
+ ])),
1197
+ M[5] || (M[5] = y("footer", { class: "viewer-footer" }, [
1198
+ y("span", null, "Foggy Data Viewer")
1199
+ ], -1))
1200
+ ]);
1201
+ };
1202
+ }
1203
+ }), Wt = /* @__PURE__ */ z(Ot, [["__scopeId", "data-v-25b92aeb"]]), At = { class: "search-fields" }, Lt = { class: "field-label" }, Rt = { class: "field-filter" }, Nt = {
1204
+ key: 0,
1205
+ class: "search-actions"
1206
+ }, Bt = /* @__PURE__ */ U({
1207
+ __name: "SearchToolbar",
1208
+ props: {
1209
+ columns: {},
1210
+ searchableFields: {},
1211
+ modelValue: {},
1212
+ layout: { default: "horizontal" },
1213
+ showActions: { type: Boolean, default: !0 },
1214
+ filterOptionsLoader: {}
1215
+ },
1216
+ emits: ["update:modelValue", "search", "reset"],
1217
+ setup(u, { expose: h, emit: i }) {
1218
+ const d = u, e = i, l = k({}), b = I(() => {
1219
+ let n = d.columns.filter((m) => m.filterable !== !1);
1220
+ return d.searchableFields && d.searchableFields.length > 0 && (n = n.filter((m) => d.searchableFields.includes(m.name))), n;
1221
+ });
1222
+ P(() => d.modelValue, (n) => {
1223
+ if (!n || n.length === 0) {
1224
+ l.value = {};
1225
+ return;
1226
+ }
1227
+ const m = {};
1228
+ for (const g of n)
1229
+ g.field && (m[g.field] || (m[g.field] = []), m[g.field].push(g));
1230
+ l.value = m;
1231
+ }, { immediate: !0 });
1232
+ function t(n) {
1233
+ var g;
1234
+ const m = (g = n.type) == null ? void 0 : g.toUpperCase();
1235
+ switch (m) {
1236
+ case "DAY":
1237
+ case "DATE":
1238
+ return "date";
1239
+ case "DATETIME":
1240
+ return "datetime";
1241
+ }
1242
+ if (n.filterType)
1243
+ return n.filterType;
1244
+ switch (m) {
1245
+ case "NUMBER":
1246
+ case "MONEY":
1247
+ case "BIGDECIMAL":
1248
+ case "INTEGER":
1249
+ case "BIGINT":
1250
+ case "LONG":
1251
+ return "number";
1252
+ case "BOOL":
1253
+ case "BOOLEAN":
1254
+ return "bool";
1255
+ case "DICT":
1256
+ return "dict";
1257
+ default:
1258
+ return "text";
1259
+ }
1260
+ }
1261
+ function s(n) {
1262
+ if (n.customFilterComponent)
1263
+ return n.customFilterComponent;
1264
+ switch (t(n)) {
1265
+ case "text":
1266
+ return le;
1267
+ case "number":
1268
+ return be;
1269
+ case "date":
1270
+ return ne;
1271
+ case "datetime":
1272
+ return ne;
1273
+ case "dict":
1274
+ return re;
1275
+ case "dimension":
1276
+ return re;
1277
+ case "bool":
1278
+ return ye;
1279
+ default:
1280
+ return le;
1281
+ }
1282
+ }
1283
+ function a(n) {
1284
+ const m = t(n), g = {
1285
+ field: n.name,
1286
+ modelValue: l.value[n.name] || null,
1287
+ "onUpdate:modelValue": (f) => o(n.name, f)
1288
+ };
1289
+ switch (m) {
1290
+ case "datetime":
1291
+ return { ...g, showTime: !0, format: n.format };
1292
+ case "date":
1293
+ return { ...g, format: n.format };
1294
+ case "dict":
1295
+ return {
1296
+ ...g,
1297
+ options: n.dictItems || [],
1298
+ placeholder: `请选择${n.title || n.name}`
1299
+ };
1300
+ case "dimension":
1301
+ return {
1302
+ ...g,
1303
+ options: [],
1304
+ loading: !1,
1305
+ placeholder: `请选择${n.title || n.name}`
1306
+ };
1307
+ default:
1308
+ return {
1309
+ ...g,
1310
+ placeholder: `搜索${n.title || n.name}...`
1311
+ };
1312
+ }
1313
+ }
1314
+ function o(n, m) {
1315
+ m === null || m.length === 0 ? delete l.value[n] : l.value[n] = m, c();
1316
+ }
1317
+ function c() {
1318
+ const n = [];
1319
+ for (const m of Object.values(l.value))
1320
+ m && m.length > 0 && n.push(...m);
1321
+ e("update:modelValue", n);
1322
+ }
1323
+ function w() {
1324
+ c(), e("search");
1325
+ }
1326
+ function D() {
1327
+ l.value = {}, e("update:modelValue", []), e("reset");
1328
+ }
1329
+ return h({
1330
+ /** 清空所有筛选 */
1331
+ clearFilters: D,
1332
+ /** 获取当前筛选条件 */
1333
+ getFilters: () => {
1334
+ const n = [];
1335
+ for (const m of Object.values(l.value))
1336
+ m && m.length > 0 && n.push(...m);
1337
+ return n;
1338
+ }
1339
+ }), (n, m) => (S(), _("div", {
1340
+ class: W(["search-toolbar", `layout-${u.layout}`])
1341
+ }, [
1342
+ y("div", At, [
1343
+ (S(!0), _(ae, null, oe(b.value, (g) => (S(), _("div", {
1344
+ key: g.name,
1345
+ class: "search-field-item"
1346
+ }, [
1347
+ y("label", Lt, R(g.title || g.name), 1),
1348
+ y("div", Rt, [
1349
+ (S(), Ee(Me(s(g)), ue({ ref_for: !0 }, a(g)), null, 16))
1350
+ ])
1351
+ ]))), 128))
1352
+ ]),
1353
+ u.showActions ? (S(), _("div", Nt, [
1354
+ y("button", {
1355
+ class: "btn btn-primary",
1356
+ onClick: w
1357
+ }, [...m[0] || (m[0] = [
1358
+ y("span", { class: "btn-icon" }, "🔍", -1),
1359
+ K(" 搜索 ", -1)
1360
+ ])]),
1361
+ y("button", {
1362
+ class: "btn btn-default",
1363
+ onClick: D
1364
+ }, [...m[1] || (m[1] = [
1365
+ y("span", { class: "btn-icon" }, "↻", -1),
1366
+ K(" 重置 ", -1)
1367
+ ])])
1368
+ ])) : L("", !0)
1369
+ ], 2));
1370
+ }
1371
+ }), Pt = /* @__PURE__ */ z(Bt, [["__scopeId", "data-v-efd07e5e"]]), Ut = { class: "data-table-with-search" }, zt = {
1372
+ key: 0,
1373
+ class: "search-toolbar-wrapper"
1374
+ }, Yt = { class: "data-table-wrapper" }, Gt = /* @__PURE__ */ U({
1375
+ inheritAttrs: !1,
1376
+ __name: "DataTableWithSearch",
1377
+ props: {
1378
+ columns: {},
1379
+ data: {},
1380
+ total: {},
1381
+ loading: { type: Boolean },
1382
+ pageSize: { default: 50 },
1383
+ showFilters: { type: Boolean, default: !0 },
1384
+ initialSlice: {},
1385
+ serverSummary: {},
1386
+ filterOptionsLoader: {},
1387
+ customFilterComponents: {},
1388
+ showSearchToolbar: { type: Boolean, default: !0 },
1389
+ searchableFields: {},
1390
+ searchLayout: { default: "horizontal" },
1391
+ showSearchActions: { type: Boolean, default: !0 },
1392
+ filterMergeMode: { default: "merge" }
1393
+ },
1394
+ emits: ["page-change", "sort-change", "filter-change", "row-click", "row-dblclick", "search", "reset"],
1395
+ setup(u, { expose: h, emit: i }) {
1396
+ const d = pe(), e = u, l = i, b = k(), t = k(), s = k([]), a = k([]), o = I(() => {
1397
+ if (e.filterMergeMode === "replace")
1398
+ return s.value.length > 0 ? s.value : a.value;
1399
+ {
1400
+ const f = [...s.value], C = new Set(s.value.map((V) => V.field));
1401
+ for (const V of a.value)
1402
+ C.has(V.field) || f.push(V);
1403
+ return f;
1404
+ }
1405
+ });
1406
+ function c(f) {
1407
+ s.value = f, l("filter-change", o.value);
1408
+ }
1409
+ function w() {
1410
+ l("search", s.value), l("filter-change", o.value);
1411
+ }
1412
+ function D() {
1413
+ s.value = [], l("reset"), l("filter-change", o.value);
1414
+ }
1415
+ function n(f) {
1416
+ a.value = f, l("filter-change", o.value);
1417
+ }
1418
+ const m = I(() => {
1419
+ const f = Object.keys(d).filter((C) => !C.startsWith("on")).reduce((C, V) => ({ ...C, [V]: d[V] }), {});
1420
+ return {
1421
+ columns: e.columns,
1422
+ data: e.data,
1423
+ total: e.total,
1424
+ loading: e.loading,
1425
+ pageSize: e.pageSize,
1426
+ showFilters: e.showFilters,
1427
+ initialSlice: e.initialSlice,
1428
+ serverSummary: e.serverSummary,
1429
+ filterOptionsLoader: e.filterOptionsLoader,
1430
+ customFilterComponents: e.customFilterComponents,
1431
+ ...f
1432
+ };
1433
+ }), g = I(() => {
1434
+ const f = {};
1435
+ return Object.keys(d).forEach((C) => {
1436
+ if (C.startsWith("on")) {
1437
+ const V = C.slice(2, 3).toLowerCase() + C.slice(3);
1438
+ f[V] = d[C];
1439
+ }
1440
+ }), {
1441
+ "page-change": (...C) => {
1442
+ l("page-change", ...C), f.pageChange && f.pageChange(...C);
1443
+ },
1444
+ "sort-change": (...C) => {
1445
+ l("sort-change", ...C), f.sortChange && f.sortChange(...C);
1446
+ },
1447
+ "filter-change": n,
1448
+ "row-click": (...C) => {
1449
+ l("row-click", ...C), f.rowClick && f.rowClick(...C);
1450
+ },
1451
+ "row-dblclick": (...C) => {
1452
+ l("row-dblclick", ...C), f.rowDblclick && f.rowDblclick(...C);
1453
+ }
1454
+ };
1455
+ });
1456
+ return h({
1457
+ /** 获取 SearchToolbar 实例 */
1458
+ getSearchToolbar: () => b.value,
1459
+ /** 获取 DataTable 实例 */
1460
+ getDataTable: () => t.value,
1461
+ /** 清空搜索工具栏筛选 */
1462
+ clearSearchFilters: () => {
1463
+ var f;
1464
+ return (f = b.value) == null ? void 0 : f.clearFilters();
1465
+ },
1466
+ /** 清空表头筛选 */
1467
+ clearTableFilters: () => {
1468
+ var f;
1469
+ return (f = t.value) == null ? void 0 : f.clearFilters();
1470
+ },
1471
+ /** 清空所有筛选 */
1472
+ clearAllFilters: () => {
1473
+ var f, C;
1474
+ (f = b.value) == null || f.clearFilters(), (C = t.value) == null || C.clearFilters();
1475
+ },
1476
+ /** 获取合并后的筛选条件 */
1477
+ getMergedFilters: () => o.value,
1478
+ /** 重置分页 */
1479
+ resetPagination: () => {
1480
+ var f;
1481
+ return (f = t.value) == null ? void 0 : f.resetPagination();
1482
+ }
1483
+ }), (f, C) => (S(), _("div", Ut, [
1484
+ u.showSearchToolbar ? (S(), _("div", zt, [
1485
+ Q(Pt, {
1486
+ ref_key: "searchToolbarRef",
1487
+ ref: b,
1488
+ columns: u.columns,
1489
+ "searchable-fields": u.searchableFields,
1490
+ layout: u.searchLayout,
1491
+ "show-actions": u.showSearchActions,
1492
+ "filter-options-loader": u.filterOptionsLoader,
1493
+ modelValue: s.value,
1494
+ "onUpdate:modelValue": [
1495
+ C[0] || (C[0] = (V) => s.value = V),
1496
+ c
1497
+ ],
1498
+ onSearch: w,
1499
+ onReset: D
1500
+ }, null, 8, ["columns", "searchable-fields", "layout", "show-actions", "filter-options-loader", "modelValue"])
1501
+ ])) : L("", !0),
1502
+ y("div", Yt, [
1503
+ Q(Ce, ue({
1504
+ ref_key: "dataTableRef",
1505
+ ref: t
1506
+ }, m.value, he(g.value)), Ve({ _: 2 }, [
1507
+ oe(f.$slots, (V, B) => ({
1508
+ name: B,
1509
+ fn: ge((j) => [
1510
+ Z(f.$slots, B, Ie(Oe(j || {})), void 0, !0)
1511
+ ])
1512
+ }))
1513
+ ]), 1040)
1514
+ ])
1515
+ ]));
1516
+ }
1517
+ }), Ht = /* @__PURE__ */ z(Gt, [["__scopeId", "data-v-690f5c67"]]);
1518
+ export {
1519
+ ye as BoolFilter,
1520
+ Ce as DataTable,
1521
+ Ht as DataTableWithSearch,
1522
+ Wt as DataViewer,
1523
+ ne as DateRangeFilter,
1524
+ be as NumberRangeFilter,
1525
+ Pt as SearchToolbar,
1526
+ re as SelectFilter,
1527
+ le as TextFilter,
1528
+ wt as buildTableColumns,
1529
+ ct as useTableSelection,
1530
+ dt as useTableSummary
1531
+ };