@veltra/sheet 2.2.0 → 2.3.1

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 (86) hide show
  1. package/dist/components/report/binding-badge.js +45 -21
  2. package/dist/components/report/designer/col-widths.js +18 -4
  3. package/dist/components/report/designer/conditional-rules/helpers.js +3 -3
  4. package/dist/components/report/designer/float-panel.js +73 -36
  5. package/dist/components/report/designer/rule-row.js +111 -127
  6. package/dist/components/report/designer/rules-dialog.js +5 -22
  7. package/dist/components/report/hub-dataset-editor.js +16 -1
  8. package/dist/components/report/preview-grid-size.js +32 -0
  9. package/dist/components/report/report-designer.js +75 -25
  10. package/dist/components/report/report-viewer.js +38 -25
  11. package/dist/components/report/style2.css +44 -39
  12. package/dist/components/report/use-report-designer.js +34 -12
  13. package/dist/components/report/use-report-viewer.js +6 -1
  14. package/dist/components/sheet/popups/border-popup.js +30 -2
  15. package/dist/components/sheet/popups/fill-color-popup.js +4 -3
  16. package/dist/components/sheet/popups/font-color-popup.js +2 -2
  17. package/dist/components/sheet/popups/font-size-popup.js +2 -2
  18. package/dist/components/sheet/sheet-context-menu.js +6 -3
  19. package/dist/components/sheet/sheet.js +8 -0
  20. package/dist/components/sheet/use-sheet-grid.js +14 -4
  21. package/dist/components/sheet/use-sheet-state.js +3 -2
  22. package/dist/index.d.ts +2 -2
  23. package/dist/index.js +2 -2
  24. package/dist/report/binding.d.ts +49 -11
  25. package/dist/report/binding.js +186 -29
  26. package/dist/report/connector.js +1 -1
  27. package/dist/report/export-xlsx.d.ts +3 -5
  28. package/dist/report/export-xlsx.js +7 -10
  29. package/dist/report/index.d.ts +2 -2
  30. package/dist/report/render/aggregate.js +20 -8
  31. package/dist/report/template.d.ts +8 -4
  32. package/dist/report/template.js +5 -2
  33. package/dist/tools/apply-style.js +29 -0
  34. package/dist/tools/builtin.js +17 -17
  35. package/dist/tools/context.d.ts +38 -5
  36. package/dist/tools/context.js +38 -1
  37. package/dist/types/report-designer.d.ts +2 -0
  38. package/dist/types/report-viewer.d.ts +2 -2
  39. package/dist/types/sheet.d.ts +4 -0
  40. package/package.json +15 -6
  41. package/src/components/report/__test__/conditional-rules-helpers.test.ts +1 -0
  42. package/src/components/report/__test__/preview-grid-size.test.ts +63 -0
  43. package/src/components/report/__test__/report-designer.test.ts +76 -0
  44. package/src/components/report/__test__/report-viewer.test.ts +24 -1
  45. package/src/components/report/__test__/use-report-designer.test.ts +142 -10
  46. package/src/components/report/binding-badge.ts +39 -20
  47. package/src/components/report/designer/col-widths.ts +34 -11
  48. package/src/components/report/designer/conditional-rules/helpers.ts +6 -3
  49. package/src/components/report/designer/float-panel.vue +71 -27
  50. package/src/components/report/designer/rule-row.vue +67 -67
  51. package/src/components/report/designer/rules-dialog.vue +3 -19
  52. package/src/components/report/hub-dataset-editor.vue +19 -1
  53. package/src/components/report/preview-grid-size.ts +33 -0
  54. package/src/components/report/report-designer.vue +79 -15
  55. package/src/components/report/report-viewer.vue +37 -29
  56. package/src/components/report/style-designer.scss +45 -41
  57. package/src/components/report/use-report-designer.ts +63 -14
  58. package/src/components/report/use-report-viewer.ts +11 -2
  59. package/src/components/sheet/__test__/sheet-component.test.ts +37 -0
  60. package/src/components/sheet/__test__/sheet-context-menu.test.ts +3 -2
  61. package/src/components/sheet/popups/border-popup.vue +31 -3
  62. package/src/components/sheet/popups/fill-color-popup.vue +5 -4
  63. package/src/components/sheet/popups/font-color-popup.vue +2 -2
  64. package/src/components/sheet/popups/font-size-popup.vue +2 -2
  65. package/src/components/sheet/sheet-context-menu.ts +8 -2
  66. package/src/components/sheet/sheet.vue +2 -0
  67. package/src/components/sheet/use-sheet-grid.ts +17 -3
  68. package/src/components/sheet/use-sheet-state.ts +8 -3
  69. package/src/report/__test__/binding.test.ts +103 -1
  70. package/src/report/__test__/connector.test.ts +21 -0
  71. package/src/report/__test__/export-xlsx.test.ts +4 -4
  72. package/src/report/__test__/render.test.ts +102 -0
  73. package/src/report/__test__/template.test.ts +11 -0
  74. package/src/report/binding.ts +278 -47
  75. package/src/report/connector.ts +3 -2
  76. package/src/report/export-xlsx.ts +9 -14
  77. package/src/report/render/aggregate.ts +29 -8
  78. package/src/report/template.ts +8 -4
  79. package/src/tools/__test__/apply-style.test.ts +129 -0
  80. package/src/tools/apply-style.ts +41 -0
  81. package/src/tools/builtin.ts +18 -18
  82. package/src/tools/context.ts +67 -4
  83. package/src/tools/index.ts +1 -0
  84. package/src/types/report-designer.ts +2 -0
  85. package/src/types/report-viewer.ts +2 -2
  86. package/src/types/sheet.ts +4 -0
@@ -1,25 +1,20 @@
1
1
  import { RULE_SCOPE_OPTIONS, coerceValueForOperator, isNumericFieldType, operatorsForFieldType, readBetweenValue, resolveEvalFieldType, ruleEvalFieldOptions, writeBetweenValue } from "./conditional-rules/helpers.js";
2
2
  import _sfc_main$1 from "./rule-preview.js";
3
- import { Fragment, computed, createBlock, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, normalizeClass, openBlock, unref, withCtx } from "vue";
4
- import { UButton, UInput, UNumberInput, UPalette, USelect } from "@veltra/desktop";
3
+ import { Fragment, computed, createBlock, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, normalizeClass, openBlock, renderList, toDisplayString, unref, withCtx } from "vue";
4
+ import { UButton, UButtonGroup, UInput, UNumberInput, UPalette, USelect } from "@veltra/desktop";
5
5
  import { bem } from "@veltra/utils";
6
6
  //#region src/components/report/designer/rule-row.vue
7
+ const _hoisted_1 = { title: "背景" };
8
+ const _hoisted_2 = { title: "文字" };
7
9
  const _sfc_main = /*@__PURE__*/ defineComponent({
8
10
  name: "UReportRuleRow",
9
11
  __name: "rule-row",
10
12
  props: {
11
13
  rule: {},
12
14
  bindingField: {},
13
- datasetFields: {},
14
- index: {},
15
- total: {}
15
+ datasetFields: {}
16
16
  },
17
- emits: [
18
- "update:rule",
19
- "remove",
20
- "move-up",
21
- "move-down"
22
- ],
17
+ emits: ["update:rule", "remove"],
23
18
  setup(__props, { emit: __emit }) {
24
19
  const props = __props;
25
20
  const emit = __emit;
@@ -28,10 +23,6 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
28
23
  const operatorOptions = computed(() => operatorsForFieldType(evalFieldType.value));
29
24
  const numericField = computed(() => isNumericFieldType(evalFieldType.value));
30
25
  const fieldOptions = computed(() => ruleEvalFieldOptions(props.bindingField, props.datasetFields));
31
- const scopeOptions = computed(() => RULE_SCOPE_OPTIONS.map((option) => ({
32
- value: option.value,
33
- label: option.label
34
- })));
35
26
  const betweenStart = computed(() => readBetweenValue(props.rule.value, 0, evalFieldType.value));
36
27
  const betweenEnd = computed(() => readBetweenValue(props.rule.value, 1, evalFieldType.value));
37
28
  const scalarNumber = computed(() => {
@@ -48,7 +39,7 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
48
39
  }
49
40
  function onEvalField(field) {
50
41
  const next = {};
51
- if (field === void 0) next.field = void 0;
42
+ if (!field) next.field = void 0;
52
43
  else next.field = field;
53
44
  const nextType = resolveEvalFieldType({
54
45
  ...props.rule,
@@ -114,153 +105,146 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
114
105
  createElementVNode("span", {
115
106
  class: normalizeClass(unref(cls).e("handle")),
116
107
  title: "拖拽排序"
117
- }, "≡", 2),
118
- createElementVNode("div", { class: normalizeClass(unref(cls).e("main")) }, [
119
- createElementVNode("div", { class: normalizeClass(unref(cls).e("meta")) }, [createVNode(unref(USelect), {
108
+ }, "⋮⋮", 2),
109
+ createElementVNode("div", { class: normalizeClass(unref(cls).e("main")) }, [createElementVNode("div", { class: normalizeClass(unref(cls).e("when")) }, [
110
+ createElementVNode("span", { class: normalizeClass(unref(cls).e("lead")) }, "当", 2),
111
+ createVNode(unref(USelect), {
120
112
  size: "small",
121
113
  class: normalizeClass(unref(cls).e("field-select")),
122
- "model-value": __props.rule.field,
114
+ "model-value": __props.rule.field ?? unref(""),
123
115
  options: fieldOptions.value,
124
- placeholder: "求值字段",
125
116
  "onUpdate:modelValue": onEvalField
126
117
  }, null, 8, [
127
118
  "class",
128
119
  "model-value",
129
120
  "options"
130
- ]), createVNode(unref(USelect), {
121
+ ]),
122
+ createVNode(unref(USelect), {
131
123
  size: "small",
132
- class: normalizeClass(unref(cls).e("scope-select")),
133
- "model-value": __props.rule.scope ?? "cell",
134
- options: scopeOptions.value,
135
- "onUpdate:modelValue": onScope
124
+ class: normalizeClass(unref(cls).e("operator")),
125
+ "model-value": __props.rule.operator,
126
+ options: operatorOptions.value,
127
+ "onUpdate:modelValue": onOperator
136
128
  }, null, 8, [
137
129
  "class",
138
130
  "model-value",
139
131
  "options"
140
- ])], 2),
141
- createElementVNode("div", { class: normalizeClass(unref(cls).e("condition")) }, [
142
- createVNode(unref(USelect), {
132
+ ]),
133
+ createElementVNode("div", { class: normalizeClass(unref(cls).e("value")) }, [__props.rule.operator === "between" ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
134
+ numericField.value ? (openBlock(), createBlock(unref(UNumberInput), {
135
+ key: 0,
143
136
  size: "small",
144
- class: normalizeClass(unref(cls).e("operator")),
145
- "model-value": __props.rule.operator,
146
- options: operatorOptions.value,
147
- "onUpdate:modelValue": onOperator
148
- }, null, 8, [
149
- "class",
150
- "model-value",
151
- "options"
152
- ]),
153
- createElementVNode("div", { class: normalizeClass(unref(cls).e("value")) }, [__props.rule.operator === "between" ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
154
- numericField.value ? (openBlock(), createBlock(unref(UNumberInput), {
155
- key: 0,
156
- size: "small",
157
- class: normalizeClass(unref(cls).e("between-input")),
158
- "model-value": betweenStart.value,
159
- "onUpdate:modelValue": _cache[0] || (_cache[0] = (v) => patchBetween(0, v ?? 0))
160
- }, null, 8, ["class", "model-value"])) : (openBlock(), createBlock(unref(UInput), {
161
- key: 1,
162
- size: "small",
163
- class: normalizeClass(unref(cls).e("between-input")),
164
- "model-value": String(betweenStart.value),
165
- "onUpdate:modelValue": _cache[1] || (_cache[1] = (v) => patchBetween(0, String(v ?? "")))
166
- }, null, 8, ["class", "model-value"])),
167
- createElementVNode("span", { class: normalizeClass(unref(cls).e("between-sep")) }, "至", 2),
168
- numericField.value ? (openBlock(), createBlock(unref(UNumberInput), {
169
- key: 2,
170
- size: "small",
171
- class: normalizeClass(unref(cls).e("between-input")),
172
- "model-value": betweenEnd.value,
173
- "onUpdate:modelValue": _cache[2] || (_cache[2] = (v) => patchBetween(1, v ?? 0))
174
- }, null, 8, ["class", "model-value"])) : (openBlock(), createBlock(unref(UInput), {
175
- key: 3,
176
- size: "small",
177
- class: normalizeClass(unref(cls).e("between-input")),
178
- "model-value": String(betweenEnd.value),
179
- "onUpdate:modelValue": _cache[3] || (_cache[3] = (v) => patchBetween(1, String(v ?? "")))
180
- }, null, 8, ["class", "model-value"]))
181
- ], 64)) : __props.rule.operator === "contains" || !numericField.value && __props.rule.operator === "eq" ? (openBlock(), createBlock(unref(UInput), {
137
+ class: normalizeClass(unref(cls).e("between-input")),
138
+ "model-value": betweenStart.value,
139
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = (v) => patchBetween(0, v ?? 0))
140
+ }, null, 8, ["class", "model-value"])) : (openBlock(), createBlock(unref(UInput), {
182
141
  key: 1,
183
142
  size: "small",
184
- class: normalizeClass(unref(cls).e("scalar-input")),
185
- "model-value": String(__props.rule.value ?? ""),
186
- placeholder: "比较值",
187
- "onUpdate:modelValue": _cache[4] || (_cache[4] = (v) => patchValue(String(v ?? "")))
188
- }, null, 8, ["class", "model-value"])) : (openBlock(), createBlock(unref(UNumberInput), {
143
+ class: normalizeClass(unref(cls).e("between-input")),
144
+ "model-value": String(betweenStart.value),
145
+ "onUpdate:modelValue": _cache[1] || (_cache[1] = (v) => patchBetween(0, String(v ?? "")))
146
+ }, null, 8, ["class", "model-value"])),
147
+ createElementVNode("span", { class: normalizeClass(unref(cls).e("between-sep")) }, "至", 2),
148
+ numericField.value ? (openBlock(), createBlock(unref(UNumberInput), {
189
149
  key: 2,
190
150
  size: "small",
191
- class: normalizeClass(unref(cls).e("scalar-input")),
192
- "model-value": scalarNumber.value,
193
- "onUpdate:modelValue": _cache[5] || (_cache[5] = (v) => patchValue(v ?? 0))
194
- }, null, 8, ["class", "model-value"]))], 2),
195
- createVNode(_sfc_main$1, {
196
- class: normalizeClass(unref(cls).e("preview")),
197
- rule: __props.rule
198
- }, null, 8, ["class", "rule"])
199
- ], 2),
200
- createElementVNode("div", { class: normalizeClass(unref(cls).e("style")) }, [
201
- createElementVNode("span", { class: normalizeClass(unref(cls).e("style-label")) }, "背景", 2),
202
- createVNode(unref(UPalette), {
151
+ class: normalizeClass(unref(cls).e("between-input")),
152
+ "model-value": betweenEnd.value,
153
+ "onUpdate:modelValue": _cache[2] || (_cache[2] = (v) => patchBetween(1, v ?? 0))
154
+ }, null, 8, ["class", "model-value"])) : (openBlock(), createBlock(unref(UInput), {
155
+ key: 3,
203
156
  size: "small",
204
- "model-value": __props.rule.style.fill?.color ?? "",
205
- "onUpdate:modelValue": patchFillColor
206
- }, null, 8, ["model-value"]),
207
- createElementVNode("span", { class: normalizeClass(unref(cls).e("style-label")) }, "字体", 2),
208
- createVNode(unref(UPalette), {
209
- size: "small",
210
- "model-value": __props.rule.style.font?.color ?? "",
211
- "onUpdate:modelValue": patchFontColor
212
- }, null, 8, ["model-value"]),
213
- createVNode(unref(UButton), {
157
+ class: normalizeClass(unref(cls).e("between-input")),
158
+ "model-value": String(betweenEnd.value),
159
+ "onUpdate:modelValue": _cache[3] || (_cache[3] = (v) => patchBetween(1, String(v ?? "")))
160
+ }, null, 8, ["class", "model-value"]))
161
+ ], 64)) : __props.rule.operator === "contains" || !numericField.value && __props.rule.operator === "eq" ? (openBlock(), createBlock(unref(UInput), {
162
+ key: 1,
163
+ size: "small",
164
+ class: normalizeClass(unref(cls).e("scalar-input")),
165
+ "model-value": String(__props.rule.value ?? ""),
166
+ placeholder: "比较值",
167
+ "onUpdate:modelValue": _cache[4] || (_cache[4] = (v) => patchValue(String(v ?? "")))
168
+ }, null, 8, ["class", "model-value"])) : (openBlock(), createBlock(unref(UNumberInput), {
169
+ key: 2,
170
+ size: "small",
171
+ class: normalizeClass(unref(cls).e("scalar-input")),
172
+ "model-value": scalarNumber.value,
173
+ "onUpdate:modelValue": _cache[5] || (_cache[5] = (v) => patchValue(v ?? 0))
174
+ }, null, 8, ["class", "model-value"]))], 2),
175
+ createElementVNode("span", { class: normalizeClass(unref(cls).e("lead")) }, "时", 2)
176
+ ], 2), createElementVNode("div", { class: normalizeClass(unref(cls).e("then")) }, [
177
+ createElementVNode("span", { class: normalizeClass(unref(cls).e("lead")) }, "样式", 2),
178
+ createElementVNode("span", _hoisted_1, [createVNode(unref(UPalette), {
179
+ size: "small",
180
+ "model-value": __props.rule.style.fill?.color ?? "",
181
+ "onUpdate:modelValue": patchFillColor
182
+ }, null, 8, ["model-value"])]),
183
+ createElementVNode("span", _hoisted_2, [createVNode(unref(UPalette), {
184
+ size: "small",
185
+ "model-value": __props.rule.style.font?.color ?? "",
186
+ "onUpdate:modelValue": patchFontColor
187
+ }, null, 8, ["model-value"])]),
188
+ createVNode(unref(UButtonGroup), null, {
189
+ default: withCtx(() => [createVNode(unref(UButton), {
214
190
  size: "small",
215
191
  class: normalizeClass(unref(cls).e("toggle")),
216
192
  type: __props.rule.style.font?.bold ? "primary" : void 0,
217
193
  plain: "",
194
+ title: "加粗",
218
195
  onClick: toggleBold
219
196
  }, {
220
- default: withCtx(() => [..._cache[9] || (_cache[9] = [createTextVNode(" B ", -1)])]),
197
+ default: withCtx(() => [..._cache[7] || (_cache[7] = [createTextVNode(" B ", -1)])]),
221
198
  _: 1
222
- }, 8, ["class", "type"]),
223
- createVNode(unref(UButton), {
199
+ }, 8, ["class", "type"]), createVNode(unref(UButton), {
224
200
  size: "small",
225
201
  class: normalizeClass(unref(cls).e("toggle")),
226
202
  type: __props.rule.style.font?.italic ? "primary" : void 0,
227
203
  plain: "",
204
+ title: "斜体",
228
205
  onClick: toggleItalic
229
206
  }, {
230
- default: withCtx(() => [..._cache[10] || (_cache[10] = [createTextVNode(" I ", -1)])]),
207
+ default: withCtx(() => [..._cache[8] || (_cache[8] = [createTextVNode(" I ", -1)])]),
231
208
  _: 1
232
- }, 8, ["class", "type"])
233
- ], 2)
234
- ], 2),
235
- createElementVNode("div", { class: normalizeClass(unref(cls).e("actions")) }, [
236
- createVNode(unref(UButton), {
237
- size: "small",
238
- text: "",
239
- disabled: __props.index === 0,
240
- onClick: _cache[6] || (_cache[6] = ($event) => emit("move-up"))
241
- }, {
242
- default: withCtx(() => [..._cache[11] || (_cache[11] = [createTextVNode("↑", -1)])]),
209
+ }, 8, ["class", "type"])]),
243
210
  _: 1
244
- }, 8, ["disabled"]),
245
- createVNode(unref(UButton), {
246
- size: "small",
247
- text: "",
248
- disabled: __props.index >= __props.total - 1,
249
- onClick: _cache[7] || (_cache[7] = ($event) => emit("move-down"))
250
- }, {
251
- default: withCtx(() => [..._cache[12] || (_cache[12] = [createTextVNode(" ↓ ", -1)])]),
252
- _: 1
253
- }, 8, ["disabled"]),
254
- createVNode(unref(UButton), {
255
- size: "small",
256
- text: "",
257
- type: "danger",
258
- onClick: _cache[8] || (_cache[8] = ($event) => emit("remove"))
259
- }, {
260
- default: withCtx(() => [..._cache[13] || (_cache[13] = [createTextVNode("删除", -1)])]),
211
+ }),
212
+ createVNode(_sfc_main$1, {
213
+ class: normalizeClass(unref(cls).e("preview")),
214
+ rule: __props.rule
215
+ }, null, 8, ["class", "rule"]),
216
+ createElementVNode("span", { class: normalizeClass(unref(cls).e("lead")) }, "应用到", 2),
217
+ createVNode(unref(UButtonGroup), null, {
218
+ default: withCtx(() => [(openBlock(true), createElementBlock(Fragment, null, renderList(unref(RULE_SCOPE_OPTIONS), (option) => {
219
+ return openBlock(), createBlock(unref(UButton), {
220
+ key: option.value,
221
+ size: "small",
222
+ plain: "",
223
+ type: (__props.rule.scope ?? "cell") === option.value ? "primary" : void 0,
224
+ title: option.value === "row" ? "染满物理输出行(交叉表会盖住同行所有列)" : "只改本格",
225
+ onClick: ($event) => onScope(option.value)
226
+ }, {
227
+ default: withCtx(() => [createTextVNode(toDisplayString(option.label), 1)]),
228
+ _: 2
229
+ }, 1032, [
230
+ "type",
231
+ "title",
232
+ "onClick"
233
+ ]);
234
+ }), 128))]),
261
235
  _: 1
262
236
  })
263
- ], 2)
237
+ ], 2)], 2),
238
+ createVNode(unref(UButton), {
239
+ size: "small",
240
+ text: "",
241
+ type: "danger",
242
+ class: normalizeClass(unref(cls).e("remove")),
243
+ onClick: _cache[6] || (_cache[6] = ($event) => emit("remove"))
244
+ }, {
245
+ default: withCtx(() => [..._cache[9] || (_cache[9] = [createTextVNode(" 删除 ", -1)])]),
246
+ _: 1
247
+ }, 8, ["class"])
264
248
  ], 2);
265
249
  };
266
250
  }
@@ -40,15 +40,6 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
40
40
  function removeRule(index) {
41
41
  draftItems.value = draftItems.value.filter((_, i) => i !== index);
42
42
  }
43
- function moveRule(index, delta) {
44
- const target = index + delta;
45
- if (target < 0 || target >= draftItems.value.length) return;
46
- const next = [...draftItems.value];
47
- const [item] = next.splice(index, 1);
48
- if (!item) return;
49
- next.splice(target, 0, item);
50
- draftItems.value = next;
51
- }
52
43
  function confirm() {
53
44
  emit("save", cloneRulesFromDraft(draftItems.value));
54
45
  visible.value = false;
@@ -62,7 +53,7 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
62
53
  "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => visible.value = $event),
63
54
  title: "条件样式",
64
55
  style: {
65
- "width": "min(960px, 92vw)",
56
+ "width": "min(600px, 92vw)",
66
57
  "max-height": "85vh"
67
58
  },
68
59
  onClose
@@ -82,7 +73,7 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
82
73
  _: 1
83
74
  })]),
84
75
  default: withCtx(() => [createElementVNode("div", { class: normalizeClass(unref(cls).b) }, [
85
- createElementVNode("p", { class: normalizeClass(unref(cls).e("hint")) }, " 按列表顺序依次求值并合并样式。可指定求值字段(默认同绑定格字段);作用范围为「整行」时染满物理输出行(含横向展开列与静态格)。交叉表下整行高亮会覆盖同行所有列,明细行报表更合适。 ", 2),
76
+ createElementVNode("p", { class: normalizeClass(unref(cls).e("hint")) }, "规则按顺序叠加。整行高亮适合明细表,交叉表会染满整行。", 2),
86
77
  draftItems.value.length ? (openBlock(), createElementBlock("ul", {
87
78
  key: 0,
88
79
  ref_key: "parentRef",
@@ -96,27 +87,19 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
96
87
  rule: item.rule,
97
88
  "binding-field": __props.bindingField,
98
89
  "dataset-fields": __props.datasetFields,
99
- index,
100
- total: draftItems.value.length,
101
90
  "onUpdate:rule": ($event) => item.rule = $event,
102
- onRemove: ($event) => removeRule(index),
103
- onMoveUp: ($event) => moveRule(index, -1),
104
- onMoveDown: ($event) => moveRule(index, 1)
91
+ onRemove: ($event) => removeRule(index)
105
92
  }, null, 8, [
106
93
  "rule",
107
94
  "binding-field",
108
95
  "dataset-fields",
109
- "index",
110
- "total",
111
96
  "onUpdate:rule",
112
- "onRemove",
113
- "onMoveUp",
114
- "onMoveDown"
97
+ "onRemove"
115
98
  ])], 2);
116
99
  }), 128))], 2)) : (openBlock(), createElementBlock("p", {
117
100
  key: 1,
118
101
  class: normalizeClass(unref(cls).e("empty"))
119
- }, "暂无规则,点击下方按钮添加。", 2)),
102
+ }, "还没有规则。", 2)),
120
103
  createVNode(unref(UButton), {
121
104
  size: "small",
122
105
  plain: "",
@@ -66,11 +66,25 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
66
66
  resetPreview();
67
67
  runDescribe();
68
68
  }, { immediate: true });
69
+ /** 立即把草稿 SQL 落入数据集(v-model 实时、change 失焦才发且提交有 debounce),供预览同步拿到最新 SQL */
70
+ function flushSqlDraft(datasetId) {
71
+ if (sqlTimer) {
72
+ clearTimeout(sqlTimer);
73
+ sqlTimer = void 0;
74
+ }
75
+ const current = dataset.value;
76
+ if (!current || current.sql === sqlDraft.value) return;
77
+ props.hub.updateDataset(datasetId, { sql: sqlDraft.value });
78
+ runDescribe();
79
+ }
69
80
  function onSqlChange(value) {
70
81
  sqlDraft.value = value;
82
+ const datasetId = props.datasetId;
71
83
  if (sqlTimer) clearTimeout(sqlTimer);
72
84
  sqlTimer = setTimeout(() => {
73
- props.hub.updateDataset(props.datasetId, { sql: value });
85
+ sqlTimer = void 0;
86
+ if (props.datasetId !== datasetId) return;
87
+ props.hub.updateDataset(datasetId, { sql: value });
74
88
  runDescribe();
75
89
  }, 280);
76
90
  }
@@ -104,6 +118,7 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
104
118
  }));
105
119
  });
106
120
  async function runPreview() {
121
+ flushSqlDraft(props.datasetId);
107
122
  previewing.value = true;
108
123
  previewError.value = "";
109
124
  const result = await props.hub.previewDataset(props.datasetId);
@@ -0,0 +1,32 @@
1
+ //#region src/components/report/preview-grid-size.ts
2
+ /**
3
+ * 报表预览网格尺寸:只铺到实际内容,不用设计态 canvas / 50×10 下限。
4
+ *
5
+ * - `template`:取数前的静态结构,按 cells/merges/meta 包围盒(忽略 snapshot.rows/cols,
6
+ * 那是设计网格声明尺寸,会带出空白格)
7
+ * - `filled`:行保留展开布局的 `snapshot.rows`(可能含无存值的空扩展行);列按包围盒收敛
8
+ * (Filled Report 的 `cols` 常被 `max(layout, template.cols)` 撑到设计态列数)
9
+ */
10
+ function previewGridSize(snapshot, mode) {
11
+ let maxRow = -1;
12
+ let maxCol = -1;
13
+ const grow = (row, col) => {
14
+ if (row > maxRow) maxRow = row;
15
+ if (col > maxCol) maxCol = col;
16
+ };
17
+ for (const cell of snapshot.cells) grow(cell.row, cell.col);
18
+ for (const merge of snapshot.merges) grow(merge.end.row, merge.end.col);
19
+ for (const item of snapshot.meta ?? []) grow(item.row, item.col);
20
+ const boundRows = maxRow + 1;
21
+ const boundCols = maxCol + 1;
22
+ if (mode === "filled") return {
23
+ rows: Math.max(boundRows, snapshot.rows, 1),
24
+ cols: Math.max(boundCols, 1)
25
+ };
26
+ return {
27
+ rows: Math.max(boundRows, 1),
28
+ cols: Math.max(boundCols, 1)
29
+ };
30
+ }
31
+ //#endregion
32
+ export { previewGridSize };