@veltra/sheet 2.1.1 → 2.2.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 (202) hide show
  1. package/dist/components/report/binding-badge.js +76 -0
  2. package/dist/components/report/designer/cell-coords.js +46 -0
  3. package/dist/components/report/designer/col-widths.js +15 -0
  4. package/dist/components/report/designer/conditional-rules/helpers.js +139 -0
  5. package/dist/components/report/designer/drop-highlight-overlay.js +76 -0
  6. package/dist/components/report/designer/float-panel.js +385 -0
  7. package/dist/components/report/designer/role.js +17 -0
  8. package/dist/components/report/designer/rule-preview.js +33 -0
  9. package/dist/components/report/designer/rule-row.js +269 -0
  10. package/dist/components/report/designer/rules-dialog.js +135 -0
  11. package/dist/components/report/designer/topology-overlay.js +122 -0
  12. package/dist/components/report/designer/topology.js +64 -0
  13. package/dist/components/report/designer/use-grid-overlay.js +75 -0
  14. package/dist/components/report/designer-hub.js +177 -0
  15. package/dist/components/report/field-panel-helpers.js +33 -0
  16. package/dist/components/report/field-panel.js +132 -0
  17. package/dist/components/report/filter-bar.js +74 -0
  18. package/dist/components/report/hub-connection-form.js +145 -0
  19. package/dist/components/report/hub-dataset-editor.js +394 -0
  20. package/dist/components/report/report-designer.js +343 -0
  21. package/dist/components/report/report-viewer.js +111 -0
  22. package/dist/components/report/style.d.ts +17 -0
  23. package/dist/components/report/style.js +18 -0
  24. package/dist/components/report/style2.css +869 -0
  25. package/dist/components/report/use-report-designer.js +360 -0
  26. package/dist/components/report/use-report-viewer.js +50 -0
  27. package/dist/{vue → components/sheet}/formula-bar.js +1 -1
  28. package/dist/{vue → components/sheet}/formula-suggest-list.js +1 -1
  29. package/dist/{vue → components/sheet}/import-file.js +1 -1
  30. package/dist/{vue → components/sheet}/insert-count-menu-item.js +1 -1
  31. package/dist/{vue → components/sheet}/insert-image.js +1 -1
  32. package/dist/{vue → components/sheet}/popup-helpers.js +1 -1
  33. package/dist/{vue → components/sheet}/popups/border-popup.js +1 -1
  34. package/dist/{vue → components/sheet}/popups/border-preset-glyph.js +1 -1
  35. package/dist/{vue → components/sheet}/popups/export-popup.js +2 -2
  36. package/dist/{vue → components/sheet}/popups/fill-color-popup.js +1 -1
  37. package/dist/{vue → components/sheet}/popups/find-popup.js +1 -1
  38. package/dist/{vue → components/sheet}/popups/font-color-popup.js +1 -1
  39. package/dist/{vue → components/sheet}/popups/font-size-popup.js +1 -1
  40. package/dist/{vue → components/sheet}/popups/import.worker.d.ts +1 -1
  41. package/dist/{vue → components/sheet}/popups/import.worker.js +1 -1
  42. package/dist/{vue → components/sheet}/popups/insert-image-popup.js +1 -1
  43. package/dist/{vue → components/sheet}/sheet-context-menu.js +1 -1
  44. package/dist/{vue → components/sheet}/sheet-tabs.js +1 -1
  45. package/dist/{vue → components/sheet}/sheet-toolbar.js +1 -1
  46. package/dist/{vue → components/sheet}/sheet.js +8 -1
  47. package/dist/{vue → components/sheet}/use-find-replace.js +1 -1
  48. package/dist/{vue → components/sheet}/use-formula-ref-select.js +1 -1
  49. package/dist/{vue → components/sheet}/use-sheet-grid.js +10 -2
  50. package/dist/{vue → components/sheet}/use-sheet-state.js +3 -3
  51. package/dist/{vue → components/sheet}/use-sheet-tabs-bar.js +1 -1
  52. package/dist/{vue → components/sheet}/use-tool-groups.js +2 -2
  53. package/dist/{vue → components/sheet}/use-tool-popup.js +2 -2
  54. package/dist/{vue → components/sheet}/use-toolbar-scroll.js +1 -1
  55. package/dist/index.d.ts +17 -3
  56. package/dist/index.js +13 -3
  57. package/dist/report/binding.d.ts +45 -0
  58. package/dist/report/binding.js +175 -0
  59. package/dist/report/connector.d.ts +66 -0
  60. package/dist/report/connector.js +159 -0
  61. package/dist/report/export-xlsx.d.ts +19 -0
  62. package/dist/report/export-xlsx.js +95 -0
  63. package/dist/report/filter-bar.d.ts +10 -0
  64. package/dist/report/filter-bar.js +31 -0
  65. package/dist/report/index.d.ts +12 -0
  66. package/dist/report/params.d.ts +13 -0
  67. package/dist/report/params.js +61 -0
  68. package/dist/report/render/aggregate.js +157 -0
  69. package/dist/report/render/builder.d.ts +12 -0
  70. package/dist/report/render/builder.js +139 -0
  71. package/dist/report/render/coordinate.d.ts +25 -0
  72. package/dist/report/render/coordinate.js +733 -0
  73. package/dist/report/render/index.d.ts +14 -0
  74. package/dist/report/render/index.js +21 -0
  75. package/dist/report/render/style-resolver.js +50 -0
  76. package/dist/report/render/template-index.d.ts +24 -0
  77. package/dist/report/render/template-index.js +137 -0
  78. package/dist/report/rules/evaluate.d.ts +25 -0
  79. package/dist/report/rules/evaluate.js +82 -0
  80. package/dist/report/rules/index.d.ts +2 -0
  81. package/dist/report/template.d.ts +59 -0
  82. package/dist/report/template.js +80 -0
  83. package/dist/report/types.d.ts +85 -0
  84. package/dist/tools/context.d.ts +1 -1
  85. package/dist/types/index.d.ts +3 -2
  86. package/dist/types/report-designer.d.ts +36 -0
  87. package/dist/types/report-viewer.d.ts +38 -0
  88. package/dist/types/sheet.d.ts +17 -1
  89. package/package.json +3 -5
  90. package/src/components/report/__test__/conditional-rules-helpers.test.ts +87 -0
  91. package/src/components/report/__test__/field-panel-helpers.test.ts +65 -0
  92. package/src/components/report/__test__/float-panel-position.test.ts +45 -0
  93. package/src/components/report/__test__/report-designer.test.ts +388 -0
  94. package/src/components/report/__test__/report-viewer.test.ts +334 -0
  95. package/src/components/report/__test__/topology.test.ts +143 -0
  96. package/src/components/report/__test__/use-report-designer.test.ts +565 -0
  97. package/src/components/report/binding-badge.ts +73 -0
  98. package/src/components/report/designer/cell-coords.ts +94 -0
  99. package/src/components/report/designer/col-widths.ts +33 -0
  100. package/src/components/report/designer/conditional-rules/helpers.ts +186 -0
  101. package/src/components/report/designer/drop-highlight-overlay.vue +74 -0
  102. package/src/components/report/designer/float-panel.vue +387 -0
  103. package/src/components/report/designer/role.ts +32 -0
  104. package/src/components/report/designer/rule-preview.vue +40 -0
  105. package/src/components/report/designer/rule-row.vue +252 -0
  106. package/src/components/report/designer/rules-dialog.vue +126 -0
  107. package/src/components/report/designer/topology-overlay.vue +127 -0
  108. package/src/components/report/designer/topology.ts +124 -0
  109. package/src/components/report/designer/use-grid-overlay.ts +113 -0
  110. package/src/components/report/designer-hub.vue +198 -0
  111. package/src/components/report/field-panel-helpers.ts +44 -0
  112. package/src/components/report/field-panel.vue +136 -0
  113. package/src/components/report/filter-bar.vue +77 -0
  114. package/src/components/report/hub-connection-form.vue +124 -0
  115. package/src/components/report/hub-dataset-editor.vue +369 -0
  116. package/src/components/report/index.ts +2 -0
  117. package/src/components/report/report-designer.vue +356 -0
  118. package/src/components/report/report-viewer.vue +128 -0
  119. package/src/components/report/style-designer.scss +583 -0
  120. package/src/components/report/style-hub.scss +292 -0
  121. package/src/components/report/style-viewer.scss +104 -0
  122. package/src/components/report/style.scss +3 -0
  123. package/src/components/report/style.ts +20 -0
  124. package/src/components/report/use-report-designer.ts +547 -0
  125. package/src/components/report/use-report-viewer.ts +79 -0
  126. package/src/{vue → components/sheet}/__test__/formula-bar.test.ts +37 -18
  127. package/src/{vue → components/sheet}/__test__/insert-image-popup.test.ts +1 -1
  128. package/src/{vue → components/sheet}/__test__/insert-image.test.ts +1 -1
  129. package/src/{vue → components/sheet}/__test__/sheet-component.test.ts +40 -3
  130. package/src/{vue → components/sheet}/__test__/sheet-context-menu.test.ts +1 -1
  131. package/src/{vue → components/sheet}/formula-bar.vue +1 -1
  132. package/src/{vue → components/sheet}/insert-image.ts +1 -1
  133. package/src/{vue → components/sheet}/popup-helpers.ts +1 -1
  134. package/src/{vue → components/sheet}/popups/border-popup.vue +1 -1
  135. package/src/{vue → components/sheet}/popups/export-popup.vue +2 -2
  136. package/src/{vue → components/sheet}/popups/fill-color-popup.vue +1 -1
  137. package/src/{vue → components/sheet}/popups/find-popup.vue +1 -1
  138. package/src/{vue → components/sheet}/popups/font-color-popup.vue +1 -1
  139. package/src/{vue → components/sheet}/popups/font-size-popup.vue +1 -1
  140. package/src/{vue → components/sheet}/popups/insert-image-popup.vue +1 -1
  141. package/src/{vue → components/sheet}/sheet-context-menu.ts +2 -2
  142. package/src/{vue → components/sheet}/sheet-toolbar.vue +2 -2
  143. package/src/{vue → components/sheet}/sheet.vue +4 -3
  144. package/src/{vue → components/sheet}/use-find-replace.ts +1 -1
  145. package/src/{vue → components/sheet}/use-sheet-grid.ts +7 -3
  146. package/src/{vue → components/sheet}/use-sheet-state.ts +3 -3
  147. package/src/{vue → components/sheet}/use-tool-groups.ts +2 -2
  148. package/src/{vue → components/sheet}/use-tool-popup.ts +2 -2
  149. package/src/index.ts +24 -188
  150. package/src/report/__test__/binding.test.ts +218 -0
  151. package/src/report/__test__/connector.test.ts +218 -0
  152. package/src/report/__test__/export-xlsx.test.ts +118 -0
  153. package/src/report/__test__/filter-bar.test.ts +58 -0
  154. package/src/report/__test__/params.test.ts +156 -0
  155. package/src/report/__test__/render.test.ts +728 -0
  156. package/src/report/__test__/rules.test.ts +131 -0
  157. package/src/report/__test__/template.test.ts +355 -0
  158. package/src/report/binding.ts +243 -0
  159. package/src/report/connector.ts +205 -0
  160. package/src/report/export-xlsx.ts +118 -0
  161. package/src/report/filter-bar.ts +36 -0
  162. package/src/report/index.ts +13 -0
  163. package/src/report/params.ts +96 -0
  164. package/src/report/render/__test__/aggregate.test.ts +16 -0
  165. package/src/report/render/__test__/coordinate.test.ts +405 -0
  166. package/src/report/render/aggregate.ts +240 -0
  167. package/src/report/render/builder.ts +211 -0
  168. package/src/report/render/coordinate.ts +1239 -0
  169. package/src/report/render/index.ts +30 -0
  170. package/src/report/render/style-resolver.ts +68 -0
  171. package/src/report/render/template-index.ts +200 -0
  172. package/src/report/rules/evaluate.ts +113 -0
  173. package/src/report/rules/index.ts +7 -0
  174. package/src/report/template.ts +141 -0
  175. package/src/report/types.ts +96 -0
  176. package/src/tools/builtin.ts +2 -2
  177. package/src/types/index.ts +2 -6
  178. package/src/types/report-designer.ts +36 -0
  179. package/src/types/report-viewer.ts +37 -0
  180. package/src/types/sheet.ts +22 -1
  181. /package/dist/{vue → components/sheet}/style.d.ts +0 -0
  182. /package/dist/{vue → components/sheet}/style.js +0 -0
  183. /package/dist/{vue → components/sheet}/style2.css +0 -0
  184. /package/dist/{vue → components/sheet}/use-formula-suggest.js +0 -0
  185. /package/src/{vue → components/sheet}/__test__/import-file.test.ts +0 -0
  186. /package/src/{vue → components/sheet}/__test__/insert-count-menu-item.test.ts +0 -0
  187. /package/src/{vue → components/sheet}/__test__/use-formula-ref-select.test.ts +0 -0
  188. /package/src/{vue → components/sheet}/__test__/use-formula-suggest.test.ts +0 -0
  189. /package/src/{vue → components/sheet}/formula-suggest-list.vue +0 -0
  190. /package/src/{vue → components/sheet}/import-file.ts +0 -0
  191. /package/src/{vue → components/sheet}/index.ts +0 -0
  192. /package/src/{vue → components/sheet}/insert-count-menu-item.vue +0 -0
  193. /package/src/{vue → components/sheet}/parsing.ts +0 -0
  194. /package/src/{vue → components/sheet}/popups/border-preset-glyph.vue +0 -0
  195. /package/src/{vue → components/sheet}/popups/import.worker.ts +0 -0
  196. /package/src/{vue → components/sheet}/sheet-tabs.vue +0 -0
  197. /package/src/{vue → components/sheet}/style.scss +0 -0
  198. /package/src/{vue → components/sheet}/style.ts +0 -0
  199. /package/src/{vue → components/sheet}/use-formula-ref-select.ts +0 -0
  200. /package/src/{vue → components/sheet}/use-formula-suggest.ts +0 -0
  201. /package/src/{vue → components/sheet}/use-sheet-tabs-bar.ts +0 -0
  202. /package/src/{vue → components/sheet}/use-toolbar-scroll.ts +0 -0
@@ -0,0 +1,269 @@
1
+ import { RULE_SCOPE_OPTIONS, coerceValueForOperator, isNumericFieldType, operatorsForFieldType, readBetweenValue, resolveEvalFieldType, ruleEvalFieldOptions, writeBetweenValue } from "./conditional-rules/helpers.js";
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";
5
+ import { bem } from "@veltra/utils";
6
+ //#region src/components/report/designer/rule-row.vue
7
+ const _sfc_main = /*@__PURE__*/ defineComponent({
8
+ name: "UReportRuleRow",
9
+ __name: "rule-row",
10
+ props: {
11
+ rule: {},
12
+ bindingField: {},
13
+ datasetFields: {},
14
+ index: {},
15
+ total: {}
16
+ },
17
+ emits: [
18
+ "update:rule",
19
+ "remove",
20
+ "move-up",
21
+ "move-down"
22
+ ],
23
+ setup(__props, { emit: __emit }) {
24
+ const props = __props;
25
+ const emit = __emit;
26
+ const cls = bem("report-rule-row");
27
+ const evalFieldType = computed(() => resolveEvalFieldType(props.rule, props.bindingField, props.datasetFields));
28
+ const operatorOptions = computed(() => operatorsForFieldType(evalFieldType.value));
29
+ const numericField = computed(() => isNumericFieldType(evalFieldType.value));
30
+ 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
+ const betweenStart = computed(() => readBetweenValue(props.rule.value, 0, evalFieldType.value));
36
+ const betweenEnd = computed(() => readBetweenValue(props.rule.value, 1, evalFieldType.value));
37
+ const scalarNumber = computed(() => {
38
+ const raw = props.rule.value;
39
+ if (typeof raw === "number" && Number.isFinite(raw)) return raw;
40
+ const parsed = Number(raw);
41
+ return Number.isFinite(parsed) ? parsed : 0;
42
+ });
43
+ function patchRule(patch) {
44
+ emit("update:rule", {
45
+ ...props.rule,
46
+ ...patch
47
+ });
48
+ }
49
+ function onEvalField(field) {
50
+ const next = {};
51
+ if (field === void 0) next.field = void 0;
52
+ else next.field = field;
53
+ const nextType = resolveEvalFieldType({
54
+ ...props.rule,
55
+ ...next
56
+ }, props.bindingField, props.datasetFields);
57
+ const operator = operatorsForFieldType(nextType)[0]?.value ?? props.rule.operator;
58
+ next.operator = operator;
59
+ next.value = coerceValueForOperator(operator, nextType, props.rule.value);
60
+ patchRule(next);
61
+ }
62
+ function onScope(scope) {
63
+ patchRule({ scope: scope === "cell" ? void 0 : scope });
64
+ }
65
+ function onOperator(operator) {
66
+ patchRule({
67
+ operator,
68
+ value: coerceValueForOperator(operator, evalFieldType.value, props.rule.value)
69
+ });
70
+ }
71
+ function patchValue(value) {
72
+ patchRule({ value });
73
+ }
74
+ function patchBetween(index, next) {
75
+ patchRule({ value: writeBetweenValue(props.rule.value, index, next, evalFieldType.value) });
76
+ }
77
+ function patchFillColor(color) {
78
+ patchRule({ style: {
79
+ ...props.rule.style,
80
+ fill: color ? { color } : void 0
81
+ } });
82
+ }
83
+ function patchFontColor(color) {
84
+ patchRule({ style: {
85
+ ...props.rule.style,
86
+ font: {
87
+ ...props.rule.style.font,
88
+ color: color || void 0
89
+ }
90
+ } });
91
+ }
92
+ function toggleBold() {
93
+ const bold = !props.rule.style.font?.bold;
94
+ patchRule({ style: {
95
+ ...props.rule.style,
96
+ font: {
97
+ ...props.rule.style.font,
98
+ bold: bold || void 0
99
+ }
100
+ } });
101
+ }
102
+ function toggleItalic() {
103
+ const italic = !props.rule.style.font?.italic;
104
+ patchRule({ style: {
105
+ ...props.rule.style,
106
+ font: {
107
+ ...props.rule.style.font,
108
+ italic: italic || void 0
109
+ }
110
+ } });
111
+ }
112
+ return (_ctx, _cache) => {
113
+ return openBlock(), createElementBlock("div", { class: normalizeClass(unref(cls).b) }, [
114
+ createElementVNode("span", {
115
+ class: normalizeClass(unref(cls).e("handle")),
116
+ title: "拖拽排序"
117
+ }, "≡", 2),
118
+ createElementVNode("div", { class: normalizeClass(unref(cls).e("main")) }, [
119
+ createElementVNode("div", { class: normalizeClass(unref(cls).e("meta")) }, [createVNode(unref(USelect), {
120
+ size: "small",
121
+ class: normalizeClass(unref(cls).e("field-select")),
122
+ "model-value": __props.rule.field,
123
+ options: fieldOptions.value,
124
+ placeholder: "求值字段",
125
+ "onUpdate:modelValue": onEvalField
126
+ }, null, 8, [
127
+ "class",
128
+ "model-value",
129
+ "options"
130
+ ]), createVNode(unref(USelect), {
131
+ 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
136
+ }, null, 8, [
137
+ "class",
138
+ "model-value",
139
+ "options"
140
+ ])], 2),
141
+ createElementVNode("div", { class: normalizeClass(unref(cls).e("condition")) }, [
142
+ createVNode(unref(USelect), {
143
+ 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), {
182
+ key: 1,
183
+ 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), {
189
+ key: 2,
190
+ 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), {
203
+ 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), {
214
+ size: "small",
215
+ class: normalizeClass(unref(cls).e("toggle")),
216
+ type: __props.rule.style.font?.bold ? "primary" : void 0,
217
+ plain: "",
218
+ onClick: toggleBold
219
+ }, {
220
+ default: withCtx(() => [..._cache[9] || (_cache[9] = [createTextVNode(" B ", -1)])]),
221
+ _: 1
222
+ }, 8, ["class", "type"]),
223
+ createVNode(unref(UButton), {
224
+ size: "small",
225
+ class: normalizeClass(unref(cls).e("toggle")),
226
+ type: __props.rule.style.font?.italic ? "primary" : void 0,
227
+ plain: "",
228
+ onClick: toggleItalic
229
+ }, {
230
+ default: withCtx(() => [..._cache[10] || (_cache[10] = [createTextVNode(" I ", -1)])]),
231
+ _: 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)])]),
243
+ _: 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)])]),
261
+ _: 1
262
+ })
263
+ ], 2)
264
+ ], 2);
265
+ };
266
+ }
267
+ });
268
+ //#endregion
269
+ export { _sfc_main as default };
@@ -0,0 +1,135 @@
1
+ import { cloneRulesFromDraft, createDraftItem, initDraftFromRules } from "./conditional-rules/helpers.js";
2
+ import _sfc_main$1 from "./rule-row.js";
3
+ import { Fragment, computed, createBlock, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, normalizeClass, openBlock, ref, renderList, unref, watch, withCtx } from "vue";
4
+ import { UButton, UDialog } from "@veltra/desktop";
5
+ import { bem } from "@veltra/utils";
6
+ import { animations, useDnD } from "@veltra/compositions";
7
+ //#region src/components/report/designer/rules-dialog.vue
8
+ const _sfc_main = /*@__PURE__*/ defineComponent({
9
+ name: "UReportRulesDialog",
10
+ __name: "rules-dialog",
11
+ props: {
12
+ modelValue: { type: Boolean },
13
+ rules: {},
14
+ bindingField: {},
15
+ datasetFields: { default: () => [] },
16
+ fieldType: { default: "number" }
17
+ },
18
+ emits: ["update:modelValue", "save"],
19
+ setup(__props, { emit: __emit }) {
20
+ const props = __props;
21
+ const emit = __emit;
22
+ const cls = bem("report-rules-dialog");
23
+ const draftItems = ref([]);
24
+ const { parentRef } = useDnD({
25
+ values: draftItems,
26
+ dragHandle: ".u-report-rule-row__handle",
27
+ plugins: [animations()]
28
+ });
29
+ const visible = computed({
30
+ get: () => props.modelValue,
31
+ set: (value) => emit("update:modelValue", value)
32
+ });
33
+ watch(() => props.modelValue, (open) => {
34
+ if (!open) return;
35
+ draftItems.value = initDraftFromRules(props.rules, props.fieldType, props.bindingField);
36
+ });
37
+ function addRule() {
38
+ draftItems.value = [...draftItems.value, createDraftItem(void 0, props.fieldType, props.bindingField)];
39
+ }
40
+ function removeRule(index) {
41
+ draftItems.value = draftItems.value.filter((_, i) => i !== index);
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
+ function confirm() {
53
+ emit("save", cloneRulesFromDraft(draftItems.value));
54
+ visible.value = false;
55
+ }
56
+ function onClose() {
57
+ visible.value = false;
58
+ }
59
+ return (_ctx, _cache) => {
60
+ return openBlock(), createBlock(unref(UDialog), {
61
+ modelValue: visible.value,
62
+ "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => visible.value = $event),
63
+ title: "条件样式",
64
+ style: {
65
+ "width": "min(960px, 92vw)",
66
+ "max-height": "85vh"
67
+ },
68
+ onClose
69
+ }, {
70
+ footer: withCtx(() => [createVNode(unref(UButton), {
71
+ size: "small",
72
+ onClick: _cache[0] || (_cache[0] = ($event) => visible.value = false)
73
+ }, {
74
+ default: withCtx(() => [..._cache[3] || (_cache[3] = [createTextVNode("取消", -1)])]),
75
+ _: 1
76
+ }), createVNode(unref(UButton), {
77
+ size: "small",
78
+ type: "primary",
79
+ onClick: confirm
80
+ }, {
81
+ default: withCtx(() => [..._cache[4] || (_cache[4] = [createTextVNode("确定", -1)])]),
82
+ _: 1
83
+ })]),
84
+ default: withCtx(() => [createElementVNode("div", { class: normalizeClass(unref(cls).b) }, [
85
+ createElementVNode("p", { class: normalizeClass(unref(cls).e("hint")) }, " 按列表顺序依次求值并合并样式。可指定求值字段(默认同绑定格字段);作用范围为「整行」时染满物理输出行(含横向展开列与静态格)。交叉表下整行高亮会覆盖同行所有列,明细行报表更合适。 ", 2),
86
+ draftItems.value.length ? (openBlock(), createElementBlock("ul", {
87
+ key: 0,
88
+ ref_key: "parentRef",
89
+ ref: parentRef,
90
+ class: normalizeClass(unref(cls).e("list"))
91
+ }, [(openBlock(true), createElementBlock(Fragment, null, renderList(draftItems.value, (item, index) => {
92
+ return openBlock(), createElementBlock("li", {
93
+ key: item.id,
94
+ class: normalizeClass(unref(cls).e("item"))
95
+ }, [createVNode(_sfc_main$1, {
96
+ rule: item.rule,
97
+ "binding-field": __props.bindingField,
98
+ "dataset-fields": __props.datasetFields,
99
+ index,
100
+ total: draftItems.value.length,
101
+ "onUpdate:rule": ($event) => item.rule = $event,
102
+ onRemove: ($event) => removeRule(index),
103
+ onMoveUp: ($event) => moveRule(index, -1),
104
+ onMoveDown: ($event) => moveRule(index, 1)
105
+ }, null, 8, [
106
+ "rule",
107
+ "binding-field",
108
+ "dataset-fields",
109
+ "index",
110
+ "total",
111
+ "onUpdate:rule",
112
+ "onRemove",
113
+ "onMoveUp",
114
+ "onMoveDown"
115
+ ])], 2);
116
+ }), 128))], 2)) : (openBlock(), createElementBlock("p", {
117
+ key: 1,
118
+ class: normalizeClass(unref(cls).e("empty"))
119
+ }, "暂无规则,点击下方按钮添加。", 2)),
120
+ createVNode(unref(UButton), {
121
+ size: "small",
122
+ plain: "",
123
+ onClick: addRule
124
+ }, {
125
+ default: withCtx(() => [..._cache[2] || (_cache[2] = [createTextVNode("添加规则", -1)])]),
126
+ _: 1
127
+ })
128
+ ], 2)]),
129
+ _: 1
130
+ }, 8, ["modelValue"]);
131
+ };
132
+ }
133
+ });
134
+ //#endregion
135
+ export { _sfc_main as default };
@@ -0,0 +1,122 @@
1
+ import { readCellOverlayRect, readGridOverlaySize, useGridOverlaySync } from "./use-grid-overlay.js";
2
+ import { buildTopologyArcPath, collectTopologyLinks } from "./topology.js";
3
+ import { Fragment, computed, createCommentVNode, createElementBlock, createElementVNode, defineComponent, normalizeClass, openBlock, ref, renderList, toRef, unref } from "vue";
4
+ import { bem } from "@veltra/utils";
5
+ //#region src/components/report/designer/topology-overlay.vue
6
+ const _hoisted_1 = ["width", "height"];
7
+ const _hoisted_2 = ["d", "marker-end"];
8
+ const _sfc_main = /*@__PURE__*/ defineComponent({
9
+ name: "UReportTopologyOverlay",
10
+ __name: "topology-overlay",
11
+ props: {
12
+ cell: {},
13
+ binding: {},
14
+ entries: {},
15
+ metaTick: {},
16
+ hostEl: {},
17
+ getGrid: { type: Function },
18
+ getBindingAt: { type: Function }
19
+ },
20
+ setup(__props) {
21
+ const props = __props;
22
+ const cls = bem("report-topology");
23
+ const instanceId = Math.random().toString(36).slice(2, 8);
24
+ const rowArrowMarkerId = `u-report-topology-row-arrow-${instanceId}`;
25
+ const colArrowMarkerId = `u-report-topology-col-arrow-${instanceId}`;
26
+ const hostEl = toRef(props, "hostEl");
27
+ const svgWidth = ref(0);
28
+ const svgHeight = ref(0);
29
+ const arcPaths = ref([]);
30
+ const inView = ref(false);
31
+ const visible = computed(() => !!props.binding && !!props.cell && inView.value && arcPaths.value.length > 0);
32
+ function updateOverlay() {
33
+ const cell = props.cell;
34
+ const binding = props.binding;
35
+ const host = props.hostEl;
36
+ if (!cell || !binding || !host) {
37
+ inView.value = false;
38
+ arcPaths.value = [];
39
+ return;
40
+ }
41
+ const size = readGridOverlaySize(host);
42
+ if (!size) {
43
+ inView.value = false;
44
+ arcPaths.value = [];
45
+ return;
46
+ }
47
+ svgWidth.value = size.width;
48
+ svgHeight.value = size.height;
49
+ const links = collectTopologyLinks(cell, binding, props.entries, props.getBindingAt);
50
+ const paths = [];
51
+ for (const link of links) {
52
+ const fromRect = readCellOverlayRect(link.from, host, props.getGrid);
53
+ const toRect = readCellOverlayRect(link.to, host, props.getGrid);
54
+ if (!fromRect || !toRect) continue;
55
+ paths.push({
56
+ direction: link.direction,
57
+ path: buildTopologyArcPath({
58
+ x: fromRect.centerX,
59
+ y: fromRect.centerY
60
+ }, {
61
+ x: toRect.centerX,
62
+ y: toRect.centerY
63
+ })
64
+ });
65
+ }
66
+ arcPaths.value = paths;
67
+ inView.value = paths.length > 0;
68
+ }
69
+ useGridOverlaySync({
70
+ hostEl,
71
+ getGrid: () => props.getGrid(),
72
+ watchSources: () => [
73
+ props.cell?.row,
74
+ props.cell?.col,
75
+ props.binding,
76
+ props.metaTick,
77
+ props.hostEl
78
+ ],
79
+ update: updateOverlay
80
+ });
81
+ return (_ctx, _cache) => {
82
+ return visible.value ? (openBlock(), createElementBlock("svg", {
83
+ key: 0,
84
+ class: normalizeClass(unref(cls).b),
85
+ width: svgWidth.value,
86
+ height: svgHeight.value,
87
+ "aria-hidden": "true"
88
+ }, [createElementVNode("defs", null, [createElementVNode("marker", {
89
+ id: rowArrowMarkerId,
90
+ markerWidth: "8",
91
+ markerHeight: "8",
92
+ refX: "6",
93
+ refY: "4",
94
+ orient: "auto",
95
+ markerUnits: "strokeWidth"
96
+ }, [..._cache[0] || (_cache[0] = [createElementVNode("path", {
97
+ d: "M0,0 L8,4 L0,8 Z",
98
+ fill: "var(--u-color-primary, #2563eb)"
99
+ }, null, -1)])]), createElementVNode("marker", {
100
+ id: colArrowMarkerId,
101
+ markerWidth: "8",
102
+ markerHeight: "8",
103
+ refX: "6",
104
+ refY: "4",
105
+ orient: "auto",
106
+ markerUnits: "strokeWidth"
107
+ }, [..._cache[1] || (_cache[1] = [createElementVNode("path", {
108
+ d: "M0,0 L8,4 L0,8 Z",
109
+ fill: "var(--u-color-warning, #d97706)"
110
+ }, null, -1)])])]), (openBlock(true), createElementBlock(Fragment, null, renderList(arcPaths.value, (item, index) => {
111
+ return openBlock(), createElementBlock("path", {
112
+ key: index,
113
+ class: normalizeClass([unref(cls).e("arc"), unref(cls).em("arc", item.direction)]),
114
+ d: item.path,
115
+ "marker-end": `url(#${item.direction === "row" ? rowArrowMarkerId : colArrowMarkerId})`
116
+ }, null, 10, _hoisted_2);
117
+ }), 128))], 10, _hoisted_1)) : createCommentVNode("v-if", true);
118
+ };
119
+ }
120
+ });
121
+ //#endregion
122
+ export { _sfc_main as default };
@@ -0,0 +1,64 @@
1
+ //#region src/components/report/designer/topology.ts
2
+ function linkKey(from, to, direction) {
3
+ return `${direction}:${from.row},${from.col}->${to.row},${to.col}`;
4
+ }
5
+ function sameAddress(a, b) {
6
+ return a.row === b.row && a.col === b.col;
7
+ }
8
+ function pushLink(links, seen, from, to, direction) {
9
+ const key = linkKey(from, to, direction);
10
+ if (seen.has(key)) return;
11
+ links.push({
12
+ from,
13
+ to,
14
+ direction
15
+ });
16
+ seen.add(key);
17
+ }
18
+ /** 查找将指定格作为行方向父格的绑定格 */
19
+ function findCellsWithRowParent(parent, entries) {
20
+ const children = [];
21
+ for (const { addr, binding } of entries) if (binding.rowParent && sameAddress(binding.rowParent, parent)) children.push(addr);
22
+ return children;
23
+ }
24
+ /** 查找将指定格作为列方向父格的绑定格 */
25
+ function findCellsWithColParent(parent, entries) {
26
+ const children = [];
27
+ for (const { addr, binding } of entries) if (binding.colParent && sameAddress(binding.colParent, parent)) children.push(addr);
28
+ return children;
29
+ }
30
+ /** 收集选中格相关的拓扑连线:沿 rowParent / colParent 链上行、下行到直接子绑定 */
31
+ function collectTopologyLinks(cell, binding, entries, getBindingAt) {
32
+ const links = [];
33
+ const seen = /* @__PURE__ */ new Set();
34
+ let rowCursor = cell;
35
+ let rowBinding = binding;
36
+ while (rowBinding?.rowParent) {
37
+ const parent = rowBinding.rowParent;
38
+ pushLink(links, seen, rowCursor, parent, "row");
39
+ rowCursor = parent;
40
+ rowBinding = getBindingAt(parent);
41
+ }
42
+ let colCursor = cell;
43
+ let colBinding = binding;
44
+ while (colBinding?.colParent) {
45
+ const parent = colBinding.colParent;
46
+ pushLink(links, seen, colCursor, parent, "col");
47
+ colCursor = parent;
48
+ colBinding = getBindingAt(parent);
49
+ }
50
+ for (const child of findCellsWithRowParent(cell, entries)) pushLink(links, seen, child, cell, "row");
51
+ for (const child of findCellsWithColParent(cell, entries)) pushLink(links, seen, child, cell, "col");
52
+ return links;
53
+ }
54
+ /** 子格 → 父格的二次贝塞尔弧线路径 */
55
+ function buildTopologyArcPath(from, to) {
56
+ const dx = to.x - from.x;
57
+ const dy = to.y - from.y;
58
+ const lift = Math.min(48, Math.max(16, (Math.hypot(dx, dy) || 1) * .35));
59
+ const cx = (from.x + to.x) / 2;
60
+ const cy = (from.y + to.y) / 2 - lift * Math.sign(dy || -1);
61
+ return `M ${from.x} ${from.y} Q ${cx} ${cy} ${to.x} ${to.y}`;
62
+ }
63
+ //#endregion
64
+ export { buildTopologyArcPath, collectTopologyLinks, findCellsWithColParent, findCellsWithRowParent };
@@ -0,0 +1,75 @@
1
+ import { getCellOverlayRect, resolveGridOverlayLayout } from "./cell-coords.js";
2
+ import { onBeforeUnmount, watch } from "vue";
3
+ //#region src/components/report/designer/use-grid-overlay.ts
4
+ /** 网格滚动时重算 overlay 坐标;避免在 props 不稳定时重复绑定监听 */
5
+ function useGridOverlaySync(options) {
6
+ let offScroll;
7
+ let rafId = 0;
8
+ function scheduleUpdate() {
9
+ cancelAnimationFrame(rafId);
10
+ rafId = requestAnimationFrame(options.update);
11
+ }
12
+ function bindScroll() {
13
+ offScroll?.();
14
+ offScroll = void 0;
15
+ const grid = options.getGrid();
16
+ if (!grid) return;
17
+ const table = grid.getTable();
18
+ const onScroll = () => scheduleUpdate();
19
+ const scrollEvent = "scroll";
20
+ table.on(scrollEvent, onScroll);
21
+ offScroll = () => table.off(scrollEvent, onScroll);
22
+ }
23
+ watch(options.watchSources, () => {
24
+ bindScroll();
25
+ scheduleUpdate();
26
+ }, {
27
+ immediate: true,
28
+ flush: "post"
29
+ });
30
+ onBeforeUnmount(() => {
31
+ cancelAnimationFrame(rafId);
32
+ offScroll?.();
33
+ });
34
+ }
35
+ function readCellOverlayRect(cell, host, getGrid) {
36
+ const grid = getGrid();
37
+ if (!grid) return null;
38
+ const resolved = resolveGridOverlayLayout(host);
39
+ if (!resolved) return null;
40
+ return getCellOverlayRect(grid, cell, resolved.layout);
41
+ }
42
+ function readGridOverlaySize(host) {
43
+ const resolved = resolveGridOverlayLayout(host);
44
+ if (!resolved) return null;
45
+ const { layout } = resolved;
46
+ return {
47
+ width: layout.viewW + layout.offsetX,
48
+ height: layout.viewH + layout.offsetY
49
+ };
50
+ }
51
+ /** 悬浮编辑卡锚点:空间按网格画布(非宿主顶)计算,避免顶行格误判为上方可放 */
52
+ function resolveBindingFloatPanelPosition(rect, layout, panelWidth, panelHeight, hostWidth, options) {
53
+ const gap = options?.gap ?? 8;
54
+ const edgePad = options?.edgePad ?? 10;
55
+ const gridTop = layout.offsetY;
56
+ const gridBottom = layout.offsetY + layout.viewH;
57
+ let left = rect.centerX;
58
+ const halfW = panelWidth / 2;
59
+ left = Math.max(edgePad + halfW, Math.min(hostWidth - edgePad - halfW, left));
60
+ const spaceAbove = rect.top - gridTop;
61
+ const spaceBelow = gridBottom - rect.bottom;
62
+ const need = panelHeight + gap;
63
+ let placement = spaceAbove >= need || spaceAbove >= spaceBelow ? "above" : "below";
64
+ if (placement === "above" && rect.top - gap - panelHeight < gridTop + edgePad) {
65
+ if (spaceBelow >= need || spaceBelow > spaceAbove) placement = "below";
66
+ }
67
+ const top = placement === "above" ? rect.top - gap : rect.bottom + gap;
68
+ return {
69
+ placement,
70
+ left: Math.round(left),
71
+ top: Math.round(top)
72
+ };
73
+ }
74
+ //#endregion
75
+ export { readCellOverlayRect, readGridOverlaySize, resolveBindingFloatPanelPosition, useGridOverlaySync };