@veltra/sheet 2.1.1 → 2.3.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 (212) hide show
  1. package/dist/components/report/binding-badge.js +100 -0
  2. package/dist/components/report/designer/cell-coords.js +46 -0
  3. package/dist/components/report/designer/col-widths.js +29 -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 +422 -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 +253 -0
  10. package/dist/components/report/designer/rules-dialog.js +118 -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/preview-grid-size.js +32 -0
  21. package/dist/components/report/report-designer.js +393 -0
  22. package/dist/components/report/report-viewer.js +124 -0
  23. package/dist/components/report/style.d.ts +17 -0
  24. package/dist/components/report/style.js +18 -0
  25. package/dist/components/report/style2.css +874 -0
  26. package/dist/components/report/use-report-designer.js +382 -0
  27. package/dist/components/report/use-report-viewer.js +55 -0
  28. package/dist/{vue → components/sheet}/formula-bar.js +1 -1
  29. package/dist/{vue → components/sheet}/formula-suggest-list.js +1 -1
  30. package/dist/{vue → components/sheet}/import-file.js +1 -1
  31. package/dist/{vue → components/sheet}/insert-count-menu-item.js +1 -1
  32. package/dist/{vue → components/sheet}/insert-image.js +1 -1
  33. package/dist/{vue → components/sheet}/popup-helpers.js +1 -1
  34. package/dist/{vue → components/sheet}/popups/border-popup.js +31 -3
  35. package/dist/{vue → components/sheet}/popups/border-preset-glyph.js +1 -1
  36. package/dist/{vue → components/sheet}/popups/export-popup.js +2 -2
  37. package/dist/{vue → components/sheet}/popups/fill-color-popup.js +3 -3
  38. package/dist/{vue → components/sheet}/popups/find-popup.js +1 -1
  39. package/dist/{vue → components/sheet}/popups/font-color-popup.js +3 -3
  40. package/dist/{vue → components/sheet}/popups/font-size-popup.js +3 -3
  41. package/dist/{vue → components/sheet}/popups/import.worker.d.ts +1 -1
  42. package/dist/{vue → components/sheet}/popups/import.worker.js +1 -1
  43. package/dist/{vue → components/sheet}/popups/insert-image-popup.js +1 -1
  44. package/dist/{vue → components/sheet}/sheet-context-menu.js +7 -4
  45. package/dist/{vue → components/sheet}/sheet-tabs.js +1 -1
  46. package/dist/{vue → components/sheet}/sheet-toolbar.js +1 -1
  47. package/dist/{vue → components/sheet}/sheet.js +16 -1
  48. package/dist/{vue → components/sheet}/use-find-replace.js +1 -1
  49. package/dist/{vue → components/sheet}/use-formula-ref-select.js +1 -1
  50. package/dist/{vue → components/sheet}/use-sheet-grid.js +22 -4
  51. package/dist/{vue → components/sheet}/use-sheet-state.js +6 -5
  52. package/dist/{vue → components/sheet}/use-sheet-tabs-bar.js +1 -1
  53. package/dist/{vue → components/sheet}/use-tool-groups.js +2 -2
  54. package/dist/{vue → components/sheet}/use-tool-popup.js +2 -2
  55. package/dist/{vue → components/sheet}/use-toolbar-scroll.js +1 -1
  56. package/dist/index.d.ts +17 -3
  57. package/dist/index.js +13 -3
  58. package/dist/report/binding.d.ts +83 -0
  59. package/dist/report/binding.js +332 -0
  60. package/dist/report/connector.d.ts +66 -0
  61. package/dist/report/connector.js +159 -0
  62. package/dist/report/export-xlsx.d.ts +17 -0
  63. package/dist/report/export-xlsx.js +92 -0
  64. package/dist/report/filter-bar.d.ts +10 -0
  65. package/dist/report/filter-bar.js +31 -0
  66. package/dist/report/index.d.ts +12 -0
  67. package/dist/report/params.d.ts +13 -0
  68. package/dist/report/params.js +61 -0
  69. package/dist/report/render/aggregate.js +169 -0
  70. package/dist/report/render/builder.d.ts +12 -0
  71. package/dist/report/render/builder.js +139 -0
  72. package/dist/report/render/coordinate.d.ts +25 -0
  73. package/dist/report/render/coordinate.js +733 -0
  74. package/dist/report/render/index.d.ts +14 -0
  75. package/dist/report/render/index.js +21 -0
  76. package/dist/report/render/style-resolver.js +50 -0
  77. package/dist/report/render/template-index.d.ts +24 -0
  78. package/dist/report/render/template-index.js +137 -0
  79. package/dist/report/rules/evaluate.d.ts +25 -0
  80. package/dist/report/rules/evaluate.js +82 -0
  81. package/dist/report/rules/index.d.ts +2 -0
  82. package/dist/report/template.d.ts +63 -0
  83. package/dist/report/template.js +83 -0
  84. package/dist/report/types.d.ts +85 -0
  85. package/dist/tools/apply-style.js +29 -0
  86. package/dist/tools/builtin.js +17 -17
  87. package/dist/tools/context.d.ts +39 -6
  88. package/dist/tools/context.js +38 -1
  89. package/dist/types/index.d.ts +3 -2
  90. package/dist/types/report-designer.d.ts +38 -0
  91. package/dist/types/report-viewer.d.ts +38 -0
  92. package/dist/types/sheet.d.ts +21 -1
  93. package/package.json +6 -8
  94. package/src/components/report/__test__/conditional-rules-helpers.test.ts +88 -0
  95. package/src/components/report/__test__/field-panel-helpers.test.ts +65 -0
  96. package/src/components/report/__test__/float-panel-position.test.ts +45 -0
  97. package/src/components/report/__test__/preview-grid-size.test.ts +63 -0
  98. package/src/components/report/__test__/report-designer.test.ts +464 -0
  99. package/src/components/report/__test__/report-viewer.test.ts +357 -0
  100. package/src/components/report/__test__/topology.test.ts +143 -0
  101. package/src/components/report/__test__/use-report-designer.test.ts +697 -0
  102. package/src/components/report/binding-badge.ts +92 -0
  103. package/src/components/report/designer/cell-coords.ts +94 -0
  104. package/src/components/report/designer/col-widths.ts +56 -0
  105. package/src/components/report/designer/conditional-rules/helpers.ts +189 -0
  106. package/src/components/report/designer/drop-highlight-overlay.vue +74 -0
  107. package/src/components/report/designer/float-panel.vue +431 -0
  108. package/src/components/report/designer/role.ts +32 -0
  109. package/src/components/report/designer/rule-preview.vue +40 -0
  110. package/src/components/report/designer/rule-row.vue +252 -0
  111. package/src/components/report/designer/rules-dialog.vue +110 -0
  112. package/src/components/report/designer/topology-overlay.vue +127 -0
  113. package/src/components/report/designer/topology.ts +124 -0
  114. package/src/components/report/designer/use-grid-overlay.ts +113 -0
  115. package/src/components/report/designer-hub.vue +198 -0
  116. package/src/components/report/field-panel-helpers.ts +44 -0
  117. package/src/components/report/field-panel.vue +136 -0
  118. package/src/components/report/filter-bar.vue +77 -0
  119. package/src/components/report/hub-connection-form.vue +124 -0
  120. package/src/components/report/hub-dataset-editor.vue +369 -0
  121. package/src/components/report/index.ts +2 -0
  122. package/src/components/report/preview-grid-size.ts +33 -0
  123. package/src/components/report/report-designer.vue +420 -0
  124. package/src/components/report/report-viewer.vue +136 -0
  125. package/src/components/report/style-designer.scss +587 -0
  126. package/src/components/report/style-hub.scss +292 -0
  127. package/src/components/report/style-viewer.scss +104 -0
  128. package/src/components/report/style.scss +3 -0
  129. package/src/components/report/style.ts +20 -0
  130. package/src/components/report/use-report-designer.ts +596 -0
  131. package/src/components/report/use-report-viewer.ts +88 -0
  132. package/src/{vue → components/sheet}/__test__/formula-bar.test.ts +37 -18
  133. package/src/{vue → components/sheet}/__test__/insert-image-popup.test.ts +1 -1
  134. package/src/{vue → components/sheet}/__test__/insert-image.test.ts +1 -1
  135. package/src/{vue → components/sheet}/__test__/sheet-component.test.ts +77 -3
  136. package/src/{vue → components/sheet}/__test__/sheet-context-menu.test.ts +4 -3
  137. package/src/{vue → components/sheet}/formula-bar.vue +1 -1
  138. package/src/{vue → components/sheet}/insert-image.ts +1 -1
  139. package/src/{vue → components/sheet}/popup-helpers.ts +1 -1
  140. package/src/{vue → components/sheet}/popups/border-popup.vue +32 -4
  141. package/src/{vue → components/sheet}/popups/export-popup.vue +2 -2
  142. package/src/{vue → components/sheet}/popups/fill-color-popup.vue +3 -3
  143. package/src/{vue → components/sheet}/popups/find-popup.vue +1 -1
  144. package/src/{vue → components/sheet}/popups/font-color-popup.vue +3 -3
  145. package/src/{vue → components/sheet}/popups/font-size-popup.vue +3 -3
  146. package/src/{vue → components/sheet}/popups/insert-image-popup.vue +1 -1
  147. package/src/{vue → components/sheet}/sheet-context-menu.ts +10 -4
  148. package/src/{vue → components/sheet}/sheet-toolbar.vue +2 -2
  149. package/src/{vue → components/sheet}/sheet.vue +6 -3
  150. package/src/{vue → components/sheet}/use-find-replace.ts +1 -1
  151. package/src/{vue → components/sheet}/use-sheet-grid.ts +23 -5
  152. package/src/{vue → components/sheet}/use-sheet-state.ts +11 -6
  153. package/src/{vue → components/sheet}/use-tool-groups.ts +2 -2
  154. package/src/{vue → components/sheet}/use-tool-popup.ts +2 -2
  155. package/src/index.ts +24 -188
  156. package/src/report/__test__/binding.test.ts +320 -0
  157. package/src/report/__test__/connector.test.ts +239 -0
  158. package/src/report/__test__/export-xlsx.test.ts +118 -0
  159. package/src/report/__test__/filter-bar.test.ts +58 -0
  160. package/src/report/__test__/params.test.ts +156 -0
  161. package/src/report/__test__/render.test.ts +830 -0
  162. package/src/report/__test__/rules.test.ts +131 -0
  163. package/src/report/__test__/template.test.ts +366 -0
  164. package/src/report/binding.ts +474 -0
  165. package/src/report/connector.ts +206 -0
  166. package/src/report/export-xlsx.ts +113 -0
  167. package/src/report/filter-bar.ts +36 -0
  168. package/src/report/index.ts +13 -0
  169. package/src/report/params.ts +96 -0
  170. package/src/report/render/__test__/aggregate.test.ts +16 -0
  171. package/src/report/render/__test__/coordinate.test.ts +405 -0
  172. package/src/report/render/aggregate.ts +261 -0
  173. package/src/report/render/builder.ts +211 -0
  174. package/src/report/render/coordinate.ts +1239 -0
  175. package/src/report/render/index.ts +30 -0
  176. package/src/report/render/style-resolver.ts +68 -0
  177. package/src/report/render/template-index.ts +200 -0
  178. package/src/report/rules/evaluate.ts +113 -0
  179. package/src/report/rules/index.ts +7 -0
  180. package/src/report/template.ts +145 -0
  181. package/src/report/types.ts +96 -0
  182. package/src/tools/__test__/apply-style.test.ts +129 -0
  183. package/src/tools/apply-style.ts +41 -0
  184. package/src/tools/builtin.ts +20 -20
  185. package/src/tools/context.ts +67 -4
  186. package/src/tools/index.ts +1 -0
  187. package/src/types/index.ts +2 -6
  188. package/src/types/report-designer.ts +38 -0
  189. package/src/types/report-viewer.ts +37 -0
  190. package/src/types/sheet.ts +26 -1
  191. /package/dist/{vue → components/sheet}/style.d.ts +0 -0
  192. /package/dist/{vue → components/sheet}/style.js +0 -0
  193. /package/dist/{vue → components/sheet}/style2.css +0 -0
  194. /package/dist/{vue → components/sheet}/use-formula-suggest.js +0 -0
  195. /package/src/{vue → components/sheet}/__test__/import-file.test.ts +0 -0
  196. /package/src/{vue → components/sheet}/__test__/insert-count-menu-item.test.ts +0 -0
  197. /package/src/{vue → components/sheet}/__test__/use-formula-ref-select.test.ts +0 -0
  198. /package/src/{vue → components/sheet}/__test__/use-formula-suggest.test.ts +0 -0
  199. /package/src/{vue → components/sheet}/formula-suggest-list.vue +0 -0
  200. /package/src/{vue → components/sheet}/import-file.ts +0 -0
  201. /package/src/{vue → components/sheet}/index.ts +0 -0
  202. /package/src/{vue → components/sheet}/insert-count-menu-item.vue +0 -0
  203. /package/src/{vue → components/sheet}/parsing.ts +0 -0
  204. /package/src/{vue → components/sheet}/popups/border-preset-glyph.vue +0 -0
  205. /package/src/{vue → components/sheet}/popups/import.worker.ts +0 -0
  206. /package/src/{vue → components/sheet}/sheet-tabs.vue +0 -0
  207. /package/src/{vue → components/sheet}/style.scss +0 -0
  208. /package/src/{vue → components/sheet}/style.ts +0 -0
  209. /package/src/{vue → components/sheet}/use-formula-ref-select.ts +0 -0
  210. /package/src/{vue → components/sheet}/use-formula-suggest.ts +0 -0
  211. /package/src/{vue → components/sheet}/use-sheet-tabs-bar.ts +0 -0
  212. /package/src/{vue → components/sheet}/use-toolbar-scroll.ts +0 -0
@@ -0,0 +1,253 @@
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, renderList, toDisplayString, unref, withCtx } from "vue";
4
+ import { UButton, UButtonGroup, UInput, UNumberInput, UPalette, USelect } from "@veltra/desktop";
5
+ import { bem } from "@veltra/utils";
6
+ //#region src/components/report/designer/rule-row.vue
7
+ const _hoisted_1 = { title: "背景" };
8
+ const _hoisted_2 = { title: "文字" };
9
+ const _sfc_main = /*@__PURE__*/ defineComponent({
10
+ name: "UReportRuleRow",
11
+ __name: "rule-row",
12
+ props: {
13
+ rule: {},
14
+ bindingField: {},
15
+ datasetFields: {}
16
+ },
17
+ emits: ["update:rule", "remove"],
18
+ setup(__props, { emit: __emit }) {
19
+ const props = __props;
20
+ const emit = __emit;
21
+ const cls = bem("report-rule-row");
22
+ const evalFieldType = computed(() => resolveEvalFieldType(props.rule, props.bindingField, props.datasetFields));
23
+ const operatorOptions = computed(() => operatorsForFieldType(evalFieldType.value));
24
+ const numericField = computed(() => isNumericFieldType(evalFieldType.value));
25
+ const fieldOptions = computed(() => ruleEvalFieldOptions(props.bindingField, props.datasetFields));
26
+ const betweenStart = computed(() => readBetweenValue(props.rule.value, 0, evalFieldType.value));
27
+ const betweenEnd = computed(() => readBetweenValue(props.rule.value, 1, evalFieldType.value));
28
+ const scalarNumber = computed(() => {
29
+ const raw = props.rule.value;
30
+ if (typeof raw === "number" && Number.isFinite(raw)) return raw;
31
+ const parsed = Number(raw);
32
+ return Number.isFinite(parsed) ? parsed : 0;
33
+ });
34
+ function patchRule(patch) {
35
+ emit("update:rule", {
36
+ ...props.rule,
37
+ ...patch
38
+ });
39
+ }
40
+ function onEvalField(field) {
41
+ const next = {};
42
+ if (!field) next.field = void 0;
43
+ else next.field = field;
44
+ const nextType = resolveEvalFieldType({
45
+ ...props.rule,
46
+ ...next
47
+ }, props.bindingField, props.datasetFields);
48
+ const operator = operatorsForFieldType(nextType)[0]?.value ?? props.rule.operator;
49
+ next.operator = operator;
50
+ next.value = coerceValueForOperator(operator, nextType, props.rule.value);
51
+ patchRule(next);
52
+ }
53
+ function onScope(scope) {
54
+ patchRule({ scope: scope === "cell" ? void 0 : scope });
55
+ }
56
+ function onOperator(operator) {
57
+ patchRule({
58
+ operator,
59
+ value: coerceValueForOperator(operator, evalFieldType.value, props.rule.value)
60
+ });
61
+ }
62
+ function patchValue(value) {
63
+ patchRule({ value });
64
+ }
65
+ function patchBetween(index, next) {
66
+ patchRule({ value: writeBetweenValue(props.rule.value, index, next, evalFieldType.value) });
67
+ }
68
+ function patchFillColor(color) {
69
+ patchRule({ style: {
70
+ ...props.rule.style,
71
+ fill: color ? { color } : void 0
72
+ } });
73
+ }
74
+ function patchFontColor(color) {
75
+ patchRule({ style: {
76
+ ...props.rule.style,
77
+ font: {
78
+ ...props.rule.style.font,
79
+ color: color || void 0
80
+ }
81
+ } });
82
+ }
83
+ function toggleBold() {
84
+ const bold = !props.rule.style.font?.bold;
85
+ patchRule({ style: {
86
+ ...props.rule.style,
87
+ font: {
88
+ ...props.rule.style.font,
89
+ bold: bold || void 0
90
+ }
91
+ } });
92
+ }
93
+ function toggleItalic() {
94
+ const italic = !props.rule.style.font?.italic;
95
+ patchRule({ style: {
96
+ ...props.rule.style,
97
+ font: {
98
+ ...props.rule.style.font,
99
+ italic: italic || void 0
100
+ }
101
+ } });
102
+ }
103
+ return (_ctx, _cache) => {
104
+ return openBlock(), createElementBlock("div", { class: normalizeClass(unref(cls).b) }, [
105
+ createElementVNode("span", {
106
+ class: normalizeClass(unref(cls).e("handle")),
107
+ title: "拖拽排序"
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), {
112
+ size: "small",
113
+ class: normalizeClass(unref(cls).e("field-select")),
114
+ "model-value": __props.rule.field ?? unref(""),
115
+ options: fieldOptions.value,
116
+ "onUpdate:modelValue": onEvalField
117
+ }, null, 8, [
118
+ "class",
119
+ "model-value",
120
+ "options"
121
+ ]),
122
+ createVNode(unref(USelect), {
123
+ size: "small",
124
+ class: normalizeClass(unref(cls).e("operator")),
125
+ "model-value": __props.rule.operator,
126
+ options: operatorOptions.value,
127
+ "onUpdate:modelValue": onOperator
128
+ }, null, 8, [
129
+ "class",
130
+ "model-value",
131
+ "options"
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,
136
+ size: "small",
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), {
141
+ key: 1,
142
+ size: "small",
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), {
149
+ key: 2,
150
+ size: "small",
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,
156
+ size: "small",
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), {
190
+ size: "small",
191
+ class: normalizeClass(unref(cls).e("toggle")),
192
+ type: __props.rule.style.font?.bold ? "primary" : void 0,
193
+ plain: "",
194
+ title: "加粗",
195
+ onClick: toggleBold
196
+ }, {
197
+ default: withCtx(() => [..._cache[7] || (_cache[7] = [createTextVNode(" B ", -1)])]),
198
+ _: 1
199
+ }, 8, ["class", "type"]), createVNode(unref(UButton), {
200
+ size: "small",
201
+ class: normalizeClass(unref(cls).e("toggle")),
202
+ type: __props.rule.style.font?.italic ? "primary" : void 0,
203
+ plain: "",
204
+ title: "斜体",
205
+ onClick: toggleItalic
206
+ }, {
207
+ default: withCtx(() => [..._cache[8] || (_cache[8] = [createTextVNode(" I ", -1)])]),
208
+ _: 1
209
+ }, 8, ["class", "type"])]),
210
+ _: 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))]),
235
+ _: 1
236
+ })
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"])
248
+ ], 2);
249
+ };
250
+ }
251
+ });
252
+ //#endregion
253
+ export { _sfc_main as default };
@@ -0,0 +1,118 @@
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 confirm() {
44
+ emit("save", cloneRulesFromDraft(draftItems.value));
45
+ visible.value = false;
46
+ }
47
+ function onClose() {
48
+ visible.value = false;
49
+ }
50
+ return (_ctx, _cache) => {
51
+ return openBlock(), createBlock(unref(UDialog), {
52
+ modelValue: visible.value,
53
+ "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => visible.value = $event),
54
+ title: "条件样式",
55
+ style: {
56
+ "width": "min(600px, 92vw)",
57
+ "max-height": "85vh"
58
+ },
59
+ onClose
60
+ }, {
61
+ footer: withCtx(() => [createVNode(unref(UButton), {
62
+ size: "small",
63
+ onClick: _cache[0] || (_cache[0] = ($event) => visible.value = false)
64
+ }, {
65
+ default: withCtx(() => [..._cache[3] || (_cache[3] = [createTextVNode("取消", -1)])]),
66
+ _: 1
67
+ }), createVNode(unref(UButton), {
68
+ size: "small",
69
+ type: "primary",
70
+ onClick: confirm
71
+ }, {
72
+ default: withCtx(() => [..._cache[4] || (_cache[4] = [createTextVNode("确定", -1)])]),
73
+ _: 1
74
+ })]),
75
+ default: withCtx(() => [createElementVNode("div", { class: normalizeClass(unref(cls).b) }, [
76
+ createElementVNode("p", { class: normalizeClass(unref(cls).e("hint")) }, "规则按顺序叠加。整行高亮适合明细表,交叉表会染满整行。", 2),
77
+ draftItems.value.length ? (openBlock(), createElementBlock("ul", {
78
+ key: 0,
79
+ ref_key: "parentRef",
80
+ ref: parentRef,
81
+ class: normalizeClass(unref(cls).e("list"))
82
+ }, [(openBlock(true), createElementBlock(Fragment, null, renderList(draftItems.value, (item, index) => {
83
+ return openBlock(), createElementBlock("li", {
84
+ key: item.id,
85
+ class: normalizeClass(unref(cls).e("item"))
86
+ }, [createVNode(_sfc_main$1, {
87
+ rule: item.rule,
88
+ "binding-field": __props.bindingField,
89
+ "dataset-fields": __props.datasetFields,
90
+ "onUpdate:rule": ($event) => item.rule = $event,
91
+ onRemove: ($event) => removeRule(index)
92
+ }, null, 8, [
93
+ "rule",
94
+ "binding-field",
95
+ "dataset-fields",
96
+ "onUpdate:rule",
97
+ "onRemove"
98
+ ])], 2);
99
+ }), 128))], 2)) : (openBlock(), createElementBlock("p", {
100
+ key: 1,
101
+ class: normalizeClass(unref(cls).e("empty"))
102
+ }, "还没有规则。", 2)),
103
+ createVNode(unref(UButton), {
104
+ size: "small",
105
+ plain: "",
106
+ onClick: addRule
107
+ }, {
108
+ default: withCtx(() => [..._cache[2] || (_cache[2] = [createTextVNode("添加规则", -1)])]),
109
+ _: 1
110
+ })
111
+ ], 2)]),
112
+ _: 1
113
+ }, 8, ["modelValue"]);
114
+ };
115
+ }
116
+ });
117
+ //#endregion
118
+ 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 };