@worm-vue3-print/core 1.3.6 → 1.3.8

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.
@@ -1,18 +1,20 @@
1
1
  /*!
2
- * @worm-vue3-print/core v1.3.6
2
+ * @worm-vue3-print/core v1.3.8
3
3
  * Copyright (c) 2026 worm <liu_long_qqcom@qq.com>
4
4
  * SPDX-FileCopyrightText: 2026 worm <liu_long_qqcom@qq.com>
5
5
  * SPDX-License-Identifier: MIT
6
6
  */
7
7
  import {
8
8
  TemplateEngine
9
- } from "../chunk-GLNQXOMO.js";
9
+ } from "../chunk-ZKHVOCU5.js";
10
10
  import {
11
11
  BARCODE_BAR_HEIGHT_MODULES,
12
12
  BARCODE_MARGIN_BOTTOM_MODULES,
13
13
  BARCODE_MODULE_WIDTH_MM,
14
14
  BARCODE_QUIET_ZONE_MODULES,
15
15
  BARCODE_TEXT_FONT_SIZE_MODULES,
16
+ CROP_SCALE_MAX,
17
+ CROP_SCALE_MIN,
16
18
  DEFAULT_SHRINK_MIN_FONT_SIZE_PT,
17
19
  ELEMENT_BORDER_SIDES,
18
20
  MIN_SHRINK_FONT_SIZE_PT,
@@ -26,7 +28,10 @@ import {
26
28
  cellFitCapMm,
27
29
  cellFitKey,
28
30
  cellFitWidthMm,
31
+ cellImageBoxMm,
29
32
  count,
33
+ cropScalePct,
34
+ cropStyleDeclarations,
30
35
  divideNumbers,
31
36
  floorFontSize,
32
37
  formatDate,
@@ -49,10 +54,11 @@ import {
49
54
  roundFontSize,
50
55
  roundHalfEven,
51
56
  roundUp,
57
+ sanitizeObjectPosition,
52
58
  subtractNumbers,
53
59
  sum,
54
60
  toUpperCaseAmount
55
- } from "../chunk-JQUJ7AF3.js";
61
+ } from "../chunk-TQJGFV2V.js";
56
62
 
57
63
  // src/designer/utils/scale.ts
58
64
  var MIN_SCALE_PERCENT = 25;
@@ -71,6 +77,36 @@ function computeFitScale(containerW, containerH, paperW, paperH, ratio = 0.9) {
71
77
  return Math.max(FIT_SCALE_MIN_PERCENT, pct);
72
78
  }
73
79
 
80
+ // src/designer/utils/toolbar-overflow.ts
81
+ var DEFAULT_GAP = 2;
82
+ function resolveToolbarOverflow(input) {
83
+ const gap = input.gap ?? DEFAULT_GAP;
84
+ const chain = [...input.units].sort((a, b) => a.order - b.order);
85
+ if (input.available <= 0) return { movedIds: [], overflowRemains: false };
86
+ if (chain.some((u) => u.width <= 0)) return { movedIds: [], overflowRemains: false };
87
+ const fits = (moved2) => {
88
+ const inline = chain.filter((u) => !moved2.has(u.id));
89
+ const used = input.pinned + inline.reduce((sum2, u) => sum2 + u.width + gap, 0) + (moved2.size > 0 ? input.moreTriggerWidth + gap : 0);
90
+ return used <= input.available;
91
+ };
92
+ if (fits(/* @__PURE__ */ new Set())) return { movedIds: [], overflowRemains: false };
93
+ const moved = /* @__PURE__ */ new Set();
94
+ for (const unit of chain) {
95
+ moved.add(unit.id);
96
+ if (fits(moved)) return { movedIds: [...moved], overflowRemains: false };
97
+ }
98
+ return { movedIds: [...moved], overflowRemains: true };
99
+ }
100
+
101
+ // src/designer/utils/overlay-placement.ts
102
+ function resolveOverlayPlacement(input) {
103
+ const gap = input.gap ?? 4;
104
+ const below = input.boundaryBottom - input.triggerBottom - gap;
105
+ const above = input.triggerTop - input.boundaryTop - gap;
106
+ if (below >= input.overlayHeight) return "down";
107
+ return above > below ? "up" : "down";
108
+ }
109
+
74
110
  // src/designer/utils/migrate.ts
75
111
  var PT_KEYS = ["left", "top", "width", "height"];
76
112
  function convertElement(el) {
@@ -777,7 +813,27 @@ var PROPERTY_REGISTRY = [
777
813
  { key: "ap-letter-spacing", keywords: ["\u5B57\u95F4\u8DDD", "letterspacing"] },
778
814
  { key: "ap-text-fit", keywords: ["\u6EA2\u51FA", "\u6EA2\u51FA\u663E\u793A", "\u622A\u65AD", "\u81EA\u52A8\u7F29\u5C0F", "\u81EA\u9002\u5E94\u884C\u9AD8", "textfit", "overflow"] },
779
815
  { key: "ap-shrink-min", keywords: ["\u6700\u5C0F\u5B57\u53F7", "\u7F29\u653E\u4E0B\u9650", "shrinkminfontsize"] },
780
- { key: "ap-word-wrap", keywords: ["\u81EA\u52A8\u6362\u884C", "\u4E0D\u6362\u884C", "wordwrap"] }
816
+ { key: "ap-word-wrap", keywords: ["\u81EA\u52A8\u6362\u884C", "\u4E0D\u6362\u884C", "wordwrap"] },
817
+ {
818
+ key: "ap-long-text-indent",
819
+ keywords: ["\u9996\u884C\u7F29\u8FDB", "\u7F29\u8FDB", "indent", "longtextindent", "\u4E24\u5B57\u7B26", "\u6BB5\u9996"],
820
+ tip: "\u957F\u6587\u672C\u6BCF\u6BB5\u9996\u884C\u7A7A\u51FA\u7684\u5BBD\u5EA6\uFF0C\u5355\u4F4D\u300C\u5B57\u7B26\u300D\uFF1A\u586B 2 \u5373\u7F29\u8FDB\u4E24\u4E2A\u6C49\u5B57\u5BBD\uFF08\u4E2D\u6587\u6392\u7248\u60EF\u4F8B\uFF09\uFF0C\u6309 em \u843D\u7EB8\u2014\u2014\u5B57\u53F7\u88AB\u300C\u81EA\u52A8\u7F29\u5C0F\u300D\u538B\u5C0F\u65F6\u7F29\u8FDB\u540C\u6B65\u53D8\u7A84\u3002\u4EC5\u957F\u6587\u672C\u5143\u7D20\u751F\u6548\uFF0C\u5199\u5728\u666E\u901A\u6587\u672C\u4E0A\u4E0D\u751F\u6548"
821
+ },
822
+ {
823
+ key: "ap-img-fit",
824
+ keywords: ["\u7F29\u653E\u6A21\u5F0F", "\u62C9\u4F38", "\u7B49\u6BD4", "fit", "contain", "cover", "\u586B\u5145", "\u88C1\u526A", "\u526A\u88C1", "\u951A\u70B9"],
825
+ tip: "\u56FE\u7247\u5728\u5143\u7D20\u6846\u5185\u7684\u7F29\u653E\u65B9\u5F0F\uFF1A\u5305\u542B\uFF1D\u5B8C\u6574\u663E\u793A\u3001\u53EF\u80FD\u7559\u767D\uFF1B\u526A\u88C1\uFF1D\u94FA\u6EE1\u6846\u5E76\u6309\u300C\u88C1\u526A\u951A\u70B9\u300D\u53D6\u4E00\u5757\uFF1B\u62C9\u4F38\uFF1D\u586B\u6EE1\u6846\u4F1A\u53D8\u5F62\uFF1B\u539F\u59CB\u5C3A\u5BF8\u4E0E\u7F29\u5C0F\u4E0D\u653E\u5927\u3002\u753B\u5E03\u4E0E\u4E09\u6761\u51FA\u7EB8\u94FE\u8DEF\u540C\u4E00\u53E3\u5F84\uFF08\u7F3A\u7701\u5305\u542B\uFF09"
826
+ },
827
+ {
828
+ key: "ap-img-object-position",
829
+ keywords: ["\u88C1\u526A\u951A\u70B9", "\u526A\u88C1\u951A\u70B9", "\u951A\u70B9", "objectposition", "object-position", "\u5BF9\u9F50\u70B9", "\u4E0A\u79FB", "\u5934\u9876"],
830
+ tip: "\u53D6\u4F4D\uFF08\u4EC5\u300C\u526A\u88C1\u300D\u6863\u6709\u8FD9\u4E00\u884C\uFF09\uFF1A\u526A\u88C1\u628A\u56FE\u7B49\u6BD4\u94FA\u6EE1\u5143\u7D20\u6846\uFF0C\u591A\u51FA\u6765\u7684\u90A3\u4E00\u6761\u8FB9\u6309\u8FD9\u91CC\u9009\u7684\u4F4D\u7F6E\u53D6\u820D\u3002\u5148\u9009\u4F4D\u7F6E\u6863\uFF08\u8D34\u8FB9\uFF0F\u5C45\u4E2D\uFF0F\u8D34\u53E6\u4E00\u5934\uFF09\uFF0C\u518D\u6309\u767E\u5206\u6BD4\u5FAE\u8C03\uFF0C0 \u8D34\u5DE6\uFF0F\u8D34\u9876\uFF0C100 \u632A\u5230\u53E6\u4E00\u5934\uFF0C\u6C34\u5E73\u4E0E\u5782\u76F4\u5404\u81EA\u72EC\u7ACB\uFF1B\u7F3A\u7701\u53D6\u6B63\u4E2D\u95F4\uFF08\u4FDD\u4F4F\u8BC1\u4EF6\u7167\u5934\u9876\u5C31\u9009\u9876\u90E8\uFF09\u3002\u5176\u4F59\u7F29\u653E\u6A21\u5F0F\u56FE\u6BD4\u6846\u5C0F\u6216\u521A\u597D\u94FA\u6EE1\uFF0C\u6CA1\u6709\u53EF\u88C1\u7684\u8FB9\uFF0C\u6240\u4EE5\u4E0D\u51FA\u672C\u884C"
831
+ },
832
+ {
833
+ key: "ap-img-fit-scale",
834
+ keywords: ["\u653E\u5927\u6BD4\u4F8B", "\u526A\u88C1\u653E\u5927", "\u653E\u5927\u500D\u6570", "\u53D6\u666F", "\u88C1\u5207\u8303\u56F4", "fitscale", "zoom"],
835
+ tip: "\u526A\u88C1\u653E\u5927\uFF1A\u7B49\u6BD4\u94FA\u6EE1\u4E4B\u540E\u628A\u753B\u9762\u518D\u63A8\u5927\u8FD9\u4E48\u591A\uFF0C\u4E24\u8F74\u624D\u771F\u7684\u5404\u591A\u51FA\u4E00\u6761\u8FB9\u53EF\u88C1\u2014\u2014\u56FE\u4E0E\u6846\u540C\u6BD4\u4F8B\u65F6\u4E0D\u653E\u5927\u5C31\u4EC0\u4E48\u90FD\u88C1\u4E0D\u6389\u3002100\uFF1D\u4E0D\u653E\u5927\uFF08\u7F3A\u7701\uFF09\uFF0C\u4E0A\u9650 400\uFF1B\u8D85\u51FA\u6846\u7684\u90E8\u5206\u7531\u5143\u7D20\u6846\u88C1\u6389\u3002\u951A\u70B9\u9009\u4E2D\u7684\u90A3\u4E00\u70B9\u65E2\u662F\u53D6\u4F4D\u7684\u9489\u4F4F\u70B9\u3001\u4E5F\u662F\u653E\u5927\u7684\u4E2D\u5FC3\uFF0C\u4E24\u8005\u5171\u7528\u540C\u4E00\u4E2A\u503C\u3002\u4EC5\u300C\u526A\u88C1\u300D\u6863\u751F\u6548\uFF0C\u5176\u4F59\u7F29\u653E\u6A21\u5F0F\u4E0D\u51FA\u672C\u884C"
836
+ }
781
837
  ]
782
838
  },
783
839
  {
@@ -790,6 +846,11 @@ var PROPERTY_REGISTRY = [
790
846
  { key: "cd-show-text", keywords: ["\u663E\u793A\u6587\u672C", "\u6761\u7801\u6587\u672C", "\u663E\u793A\u6570\u5B57"] },
791
847
  { key: "cd-font-size", keywords: ["\u6761\u7801\u5B57\u53F7", "\u6587\u672C\u5B57\u53F7"] },
792
848
  { key: "cd-ec-level", keywords: ["\u7EA0\u9519\u7EA7\u522B", "\u5BB9\u9519", "qrcodelevel"] },
849
+ {
850
+ key: "cd-quiet-zone",
851
+ keywords: ["\u9759\u533A", "\u9759\u533A\u5BBD\u5EA6", "\u767D\u8FB9", "\u7A7A\u767D\u8FB9", "\u7559\u767D", "\u94FA\u6EE1", "quietzone"],
852
+ tip: "\u4E8C\u7EF4\u7801\u56DB\u5468\u7559\u51FA\u7684\u7A7A\u767D\u683C\u6570\uFF1A0 \u5373\u4E0D\u7559\u767D\u8FB9\u3001\u7801\u9762\u7B49\u6BD4\u94FA\u6EE1\u5143\u7D20\u6846\uFF08\u6B64\u65F6\u9760\u6846\u5916\u7684\u767D\u7EB8\u5145\u5F53\u9759\u533A\uFF09\uFF1B\u6570\u503C\u8D8A\u5927\u767D\u8FB9\u8D8A\u5BBD\u3001\u7801\u9762\u5728\u6846\u5185\u8D8A\u5C0F\uFF08\u7F3A\u7701 0\uFF0C\u9700 ISO/IEC 18004 \u63A8\u8350\u9759\u533A\u65F6\u586B 4\uFF09"
853
+ },
793
854
  { key: "cd-fit", keywords: ["\u7F29\u653E\u6A21\u5F0F", "\u62C9\u4F38", "\u7B49\u6BD4", "fit", "contain", "cover"] },
794
855
  { key: "cd-max-width", keywords: ["\u6700\u5927\u5BBD\u5EA6", "\u6700\u5927\u5BBD", "maxwidth"] },
795
856
  { key: "cd-max-height", keywords: ["\u6700\u5927\u9AD8\u5EA6", "\u6700\u5927\u9AD8", "maxheight"] }
@@ -844,6 +905,13 @@ var PROPERTY_REGISTRY = [
844
905
  ]
845
906
  }
846
907
  ];
908
+ function propertyTip(key) {
909
+ for (const group of PROPERTY_REGISTRY) {
910
+ const hit = group.items.find((item) => item.key === key);
911
+ if (hit) return hit.tip ?? "";
912
+ }
913
+ return "";
914
+ }
847
915
  function matchKeywords(search, keywords) {
848
916
  const s = search.trim().toLowerCase();
849
917
  if (!s) {
@@ -866,6 +934,321 @@ function searchProperties(search) {
866
934
  return { groups, itemKeys };
867
935
  }
868
936
 
937
+ // src/designer/utils/engine.ts
938
+ var engine = new TemplateEngine();
939
+
940
+ // src/designer/utils/expression-eval.ts
941
+ var EXTENDED_FUNCTIONS = {
942
+ MONEY: formatMoney,
943
+ CONCAT: (...args) => args.filter((v) => v != null).join(""),
944
+ IF: ifFn,
945
+ FORMAT: (value) => {
946
+ if (typeof value !== "number") return String(value);
947
+ return value.toLocaleString("zh-CN", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
948
+ },
949
+ SUBSTR: (str, start, len) => String(str).slice(start, len ? start + len : void 0),
950
+ LEN: (str) => String(str).length,
951
+ // 四则运算(与 +/-/*// 运算符同一套数值语义,供不方便写运算符的场景使用)
952
+ ADD: addNumbers,
953
+ SUB: subtractNumbers,
954
+ MUL: multiplyNumbers,
955
+ DIV: divideNumbers,
956
+ // 数值修约
957
+ ROUND: round,
958
+ ROUNDUP: roundUp,
959
+ CEIL: roundUp,
960
+ ROUNDDOWN: roundDown,
961
+ FLOOR: roundDown,
962
+ ROUNDBANK: roundHalfEven,
963
+ NOW: () => (/* @__PURE__ */ new Date()).toISOString().split("T")[0],
964
+ IFEMPTY: (value, defaultVal) => value != null && value !== "" ? String(value) : defaultVal,
965
+ PAD: (value, len, char) => String(value).padStart(len, char),
966
+ REPLACE: (str, from, to) => String(str).replace(new RegExp(from, "g"), to),
967
+ JSON: (value) => JSON.stringify(value, null, 2),
968
+ DATE: formatDate,
969
+ UPPER: toUpperCaseAmount
970
+ };
971
+ for (const [name, fn] of Object.entries(EXTENDED_FUNCTIONS)) {
972
+ engine.registerFunction(name, fn);
973
+ }
974
+ function aggregate(fn, field, rows) {
975
+ switch (fn.toUpperCase()) {
976
+ case "SUM":
977
+ return sum(rows, field);
978
+ case "AVG":
979
+ return avg(rows, field);
980
+ case "COUNT":
981
+ return count(rows, field);
982
+ case "MIN":
983
+ return min(rows, field);
984
+ case "MAX":
985
+ return max(rows, field);
986
+ default:
987
+ return 0;
988
+ }
989
+ }
990
+ function safeEval(expr, context, _callableNames) {
991
+ return engine.evaluate(expr, context);
992
+ }
993
+ function evaluateTemplate(text, ctx) {
994
+ if (!text) return "";
995
+ if (!text.includes("{")) return text;
996
+ const rows = Array.isArray(ctx.rows) ? ctx.rows : [];
997
+ let processedText = text.replace(/\{([^}]+)\}/g, (_match, inner) => {
998
+ let expr = inner.trim();
999
+ expr = expr.replace(/\b(SUM|AVG|COUNT|MIN|MAX)\(([^)]+)\)/g, (_m, fn, arg) => {
1000
+ const field = arg.trim().replace(/^['"]|['"]$/g, "");
1001
+ return String(aggregate(fn, field, rows));
1002
+ });
1003
+ return `{${expr}}`;
1004
+ });
1005
+ try {
1006
+ const result = engine.render(processedText, ctx);
1007
+ return result;
1008
+ } catch {
1009
+ return text;
1010
+ }
1011
+ }
1012
+
1013
+ // src/designer/utils/demo-data.ts
1014
+ function getDemoData() {
1015
+ return DEFAULT_DEMO_DATA;
1016
+ }
1017
+ var DEFAULT_DEMO_DATA = {
1018
+ supplier: {
1019
+ name: "\u946B\u8FBE\u4E94\u91D1\u6709\u9650\u516C\u53F8",
1020
+ phone: "0571-88776655",
1021
+ address: "\u676D\u5DDE\u5E02\u8427\u5C71\u533A\u7ECF\u6D4E\u5F00\u53D1\u533A88\u53F7"
1022
+ },
1023
+ receiver: {
1024
+ name: "\u674E\u56DB",
1025
+ phone: "13912345678",
1026
+ address: "\u676D\u5DDE\u5E02\u4F59\u676D\u533A\u6587\u4E00\u897F\u8DEF998\u53F7"
1027
+ },
1028
+ order: {
1029
+ no: "PO20260801001",
1030
+ date: "2026-08-01",
1031
+ total: 69543.75
1032
+ },
1033
+ // 50 条商品明细, 用于验证多页分页效果
1034
+ goods: [
1035
+ { name: "\u78B3\u94A2\u87BA\u4E1D M8", spec: "M14\xD710", unit: "\u4E2A", qty: 100, price: 0.5, amount: 50, remark: "A\u7EA7" },
1036
+ { name: "\u4E0D\u9508\u94A2\u87BA\u6BCD M10", spec: "M16\xD711", unit: "\u5957", qty: 117, price: 0.75, amount: 87.75, remark: "" },
1037
+ { name: "\u5F39\u7C27\u57AB\u5708 M12", spec: "M6\xD712", unit: "\u76D2", qty: 134, price: 1, amount: 134, remark: "" },
1038
+ { name: "\u516D\u89D2\u87BA\u6813 M14", spec: "M5\xD713", unit: "\u652F", qty: 151, price: 1.25, amount: 188.75, remark: "" },
1039
+ { name: "\u5185\u516D\u89D2\u87BA\u9489 M16", spec: "M20\xD714", unit: "\u888B", qty: 168, price: 1.5, amount: 252, remark: "" },
1040
+ { name: "\u5E73\u57AB\u5708 M6", spec: "M4\xD715", unit: "\u4EF6", qty: 185, price: 1.75, amount: 323.75, remark: "" },
1041
+ { name: "\u81EA\u653B\u87BA\u9489 M5", spec: "M3\xD716", unit: "\u6839", qty: 202, price: 2, amount: 404, remark: "" },
1042
+ { name: "\u53CC\u5934\u87BA\u67F1 M20", spec: "M8\xD717", unit: "\u5305", qty: 219, price: 2.25, amount: 492.75, remark: "A\u7EA7" },
1043
+ { name: "\u7D27\u5B9A\u87BA\u9489 M4", spec: "M10\xD718", unit: "\u53EA", qty: 236, price: 2.5, amount: 590, remark: "" },
1044
+ { name: "\u5341\u5B57\u76D8\u5934\u9489 M3", spec: "M12\xD719", unit: "\u7EC4", qty: 253, price: 2.75, amount: 695.75, remark: "" },
1045
+ { name: "\u78B3\u94A2\u87BA\u4E1D M8", spec: "M14\xD720", unit: "\u4E2A", qty: 270, price: 3, amount: 810, remark: "" },
1046
+ { name: "\u4E0D\u9508\u94A2\u87BA\u6BCD M10", spec: "M16\xD721", unit: "\u5957", qty: 287, price: 3.25, amount: 932.75, remark: "" },
1047
+ { name: "\u5F39\u7C27\u57AB\u5708 M12", spec: "M6\xD722", unit: "\u76D2", qty: 304, price: 3.5, amount: 1064, remark: "" },
1048
+ { name: "\u516D\u89D2\u87BA\u6813 M14", spec: "M5\xD723", unit: "\u652F", qty: 321, price: 3.75, amount: 1203.75, remark: "" },
1049
+ { name: "\u5185\u516D\u89D2\u87BA\u9489 M16", spec: "M20\xD724", unit: "\u888B", qty: 338, price: 4, amount: 1352, remark: "A\u7EA7" },
1050
+ { name: "\u5E73\u57AB\u5708 M6", spec: "M4\xD725", unit: "\u4EF6", qty: 355, price: 4.25, amount: 1508.75, remark: "" },
1051
+ { name: "\u81EA\u653B\u87BA\u9489 M5", spec: "M3\xD726", unit: "\u6839", qty: 372, price: 4.5, amount: 1674, remark: "" },
1052
+ { name: "\u53CC\u5934\u87BA\u67F1 M20", spec: "M8\xD727", unit: "\u5305", qty: 389, price: 4.75, amount: 1847.75, remark: "" },
1053
+ { name: "\u7D27\u5B9A\u87BA\u9489 M4", spec: "M10\xD728", unit: "\u53EA", qty: 406, price: 5, amount: 2030, remark: "" },
1054
+ { name: "\u5341\u5B57\u76D8\u5934\u9489 M3", spec: "M12\xD729", unit: "\u7EC4", qty: 423, price: 5.25, amount: 2220.75, remark: "" },
1055
+ { name: "\u78B3\u94A2\u87BA\u4E1D M8", spec: "M14\xD730", unit: "\u4E2A", qty: 440, price: 0.5, amount: 220, remark: "" },
1056
+ { name: "\u4E0D\u9508\u94A2\u87BA\u6BCD M10", spec: "M16\xD731", unit: "\u5957", qty: 457, price: 0.75, amount: 342.75, remark: "A\u7EA7" },
1057
+ { name: "\u5F39\u7C27\u57AB\u5708 M12", spec: "M6\xD732", unit: "\u76D2", qty: 474, price: 1, amount: 474, remark: "" },
1058
+ { name: "\u516D\u89D2\u87BA\u6813 M14", spec: "M5\xD733", unit: "\u652F", qty: 491, price: 1.25, amount: 613.75, remark: "" },
1059
+ { name: "\u5185\u516D\u89D2\u87BA\u9489 M16", spec: "M20\xD734", unit: "\u888B", qty: 508, price: 1.5, amount: 762, remark: "" },
1060
+ { name: "\u5E73\u57AB\u5708 M6", spec: "M4\xD735", unit: "\u4EF6", qty: 525, price: 1.75, amount: 918.75, remark: "" },
1061
+ { name: "\u81EA\u653B\u87BA\u9489 M5", spec: "M3\xD736", unit: "\u6839", qty: 542, price: 2, amount: 1084, remark: "" },
1062
+ { name: "\u53CC\u5934\u87BA\u67F1 M20", spec: "M8\xD737", unit: "\u5305", qty: 559, price: 2.25, amount: 1257.75, remark: "" },
1063
+ { name: "\u7D27\u5B9A\u87BA\u9489 M4", spec: "M10\xD738", unit: "\u53EA", qty: 576, price: 2.5, amount: 1440, remark: "A\u7EA7" },
1064
+ { name: "\u5341\u5B57\u76D8\u5934\u9489 M3", spec: "M12\xD739", unit: "\u7EC4", qty: 593, price: 2.75, amount: 1630.75, remark: "" },
1065
+ { name: "\u78B3\u94A2\u87BA\u4E1D M8", spec: "M14\xD740", unit: "\u4E2A", qty: 610, price: 3, amount: 1830, remark: "" },
1066
+ { name: "\u4E0D\u9508\u94A2\u87BA\u6BCD M10", spec: "M16\xD741", unit: "\u5957", qty: 627, price: 3.25, amount: 2037.75, remark: "" },
1067
+ { name: "\u5F39\u7C27\u57AB\u5708 M12", spec: "M6\xD742", unit: "\u76D2", qty: 644, price: 3.5, amount: 2254, remark: "" },
1068
+ { name: "\u516D\u89D2\u87BA\u6813 M14", spec: "M5\xD743", unit: "\u652F", qty: 661, price: 3.75, amount: 2478.75, remark: "" },
1069
+ { name: "\u5185\u516D\u89D2\u87BA\u9489 M16", spec: "M20\xD744", unit: "\u888B", qty: 678, price: 4, amount: 2712, remark: "" },
1070
+ { name: "\u5E73\u57AB\u5708 M6", spec: "M4\xD745", unit: "\u4EF6", qty: 695, price: 4.25, amount: 2953.75, remark: "A\u7EA7" },
1071
+ { name: "\u81EA\u653B\u87BA\u9489 M5", spec: "M3\xD746", unit: "\u6839", qty: 712, price: 4.5, amount: 3204, remark: "" },
1072
+ { name: "\u53CC\u5934\u87BA\u67F1 M20", spec: "M8\xD747", unit: "\u5305", qty: 729, price: 4.75, amount: 3462.75, remark: "" },
1073
+ { name: "\u7D27\u5B9A\u87BA\u9489 M4", spec: "M10\xD748", unit: "\u53EA", qty: 746, price: 5, amount: 3730, remark: "" },
1074
+ { name: "\u5341\u5B57\u76D8\u5934\u9489 M3", spec: "M12\xD749", unit: "\u7EC4", qty: 763, price: 5.25, amount: 4005.75, remark: "" },
1075
+ { name: "\u78B3\u94A2\u87BA\u4E1D M8", spec: "M14\xD710", unit: "\u4E2A", qty: 780, price: 0.5, amount: 390, remark: "" },
1076
+ { name: "\u4E0D\u9508\u94A2\u87BA\u6BCD M10", spec: "M16\xD711", unit: "\u5957", qty: 797, price: 0.75, amount: 597.75, remark: "" },
1077
+ { name: "\u5F39\u7C27\u57AB\u5708 M12", spec: "M6\xD712", unit: "\u76D2", qty: 814, price: 1, amount: 814, remark: "A\u7EA7" },
1078
+ { name: "\u516D\u89D2\u87BA\u6813 M14", spec: "M5\xD713", unit: "\u652F", qty: 831, price: 1.25, amount: 1038.75, remark: "" },
1079
+ { name: "\u5185\u516D\u89D2\u87BA\u9489 M16", spec: "M20\xD714", unit: "\u888B", qty: 848, price: 1.5, amount: 1272, remark: "" },
1080
+ { name: "\u5E73\u57AB\u5708 M6", spec: "M4\xD715", unit: "\u4EF6", qty: 865, price: 1.75, amount: 1513.75, remark: "" },
1081
+ { name: "\u81EA\u653B\u87BA\u9489 M5", spec: "M3\xD716", unit: "\u6839", qty: 882, price: 2, amount: 1764, remark: "" },
1082
+ { name: "\u53CC\u5934\u87BA\u67F1 M20", spec: "M8\xD717", unit: "\u5305", qty: 899, price: 2.25, amount: 2022.75, remark: "" },
1083
+ { name: "\u7D27\u5B9A\u87BA\u9489 M4", spec: "M10\xD718", unit: "\u53EA", qty: 916, price: 2.5, amount: 2290, remark: "" },
1084
+ { name: "\u5341\u5B57\u76D8\u5934\u9489 M3", spec: "M12\xD719", unit: "\u7EC4", qty: 933, price: 2.75, amount: 2565.75, remark: "A\u7EA7" }
1085
+ ]
1086
+ };
1087
+
1088
+ // src/designer/utils/crop-anchor.ts
1089
+ var AXIS_X = { left: 0, center: 50, right: 100 };
1090
+ var AXIS_Y = { top: 0, center: 50, bottom: 100 };
1091
+ function clampPct(v) {
1092
+ if (!Number.isFinite(v)) return 50;
1093
+ return Math.round(Math.min(100, Math.max(0, v)));
1094
+ }
1095
+ function roundMm(v) {
1096
+ return Math.round(v * 100) / 100;
1097
+ }
1098
+ function buildCropAnchor(x, y) {
1099
+ const cx = clampPct(x);
1100
+ const cy = clampPct(y);
1101
+ if (cx === 50 && cy === 50) return void 0;
1102
+ return `${cx}% ${cy}%`;
1103
+ }
1104
+ function asPct(token) {
1105
+ return /^\d+(?:\.\d+)?%$/.test(token) ? parseFloat(token) : void 0;
1106
+ }
1107
+ function parseCropAnchor(value) {
1108
+ const raw = (value ?? "").trim();
1109
+ if (!raw) return { kind: "empty" };
1110
+ const tokens = raw.toLowerCase().split(/\s+/);
1111
+ let x;
1112
+ let y;
1113
+ for (let i = 0; i < tokens.length; i++) {
1114
+ const t = tokens[i];
1115
+ const pct = asPct(t);
1116
+ if (i === 0) {
1117
+ if (t in AXIS_X) x = AXIS_X[t];
1118
+ else if (pct !== void 0) x = pct;
1119
+ else if (t in AXIS_Y) y = AXIS_Y[t];
1120
+ else return { kind: "custom", raw: value };
1121
+ } else {
1122
+ if (t in AXIS_Y && y === void 0) y = AXIS_Y[t];
1123
+ else if (pct !== void 0 && x === void 0) x = pct;
1124
+ else if (pct !== void 0 && y === void 0) y = pct;
1125
+ else if (t in AXIS_X && x === void 0) x = AXIS_X[t];
1126
+ else return { kind: "custom", raw: value };
1127
+ }
1128
+ }
1129
+ return { kind: "axes", x: clampPct(x ?? 50), y: clampPct(y ?? 50) };
1130
+ }
1131
+ var MM_PER_PX = 25.4 / 96;
1132
+ function contentMm(box) {
1133
+ const { widthMm, heightMm, naturalWidth, naturalHeight } = box;
1134
+ if (!naturalWidth || !naturalHeight || !widthMm || !heightMm) return null;
1135
+ const k = widthMm / naturalWidth;
1136
+ const l = heightMm / naturalHeight;
1137
+ const zoom = (cropScalePct(box.fit, box.scalePct) ?? CROP_SCALE_MIN) / 100;
1138
+ switch (box.fit || "contain") {
1139
+ // 拉伸填满:图被钉成框,两轴都挪不动(放大比例只给剪裁档,这里不受影响)
1140
+ case "fill":
1141
+ return { w: widthMm, h: heightMm };
1142
+ case "cover": {
1143
+ const s = Math.max(k, l) * zoom;
1144
+ return { w: naturalWidth * s, h: naturalHeight * s };
1145
+ }
1146
+ // 原始尺寸不缩放:按图片内在像素尺寸绘制
1147
+ case "none":
1148
+ return { w: naturalWidth * MM_PER_PX, h: naturalHeight * MM_PER_PX };
1149
+ case "scale-down": {
1150
+ const s = Math.min(1, Math.min(k, l));
1151
+ return { w: naturalWidth * s, h: naturalHeight * s };
1152
+ }
1153
+ default: {
1154
+ const s = Math.min(k, l);
1155
+ return { w: naturalWidth * s, h: naturalHeight * s };
1156
+ }
1157
+ }
1158
+ }
1159
+ function resolveCropTravel(box) {
1160
+ const c = contentMm(box);
1161
+ if (!c) return { x: null, y: null };
1162
+ return {
1163
+ x: roundMm(Math.abs(box.widthMm - c.w)),
1164
+ y: roundMm(Math.abs(box.heightMm - c.h))
1165
+ };
1166
+ }
1167
+ function cropWindow(box, x, y) {
1168
+ const c = contentMm(box);
1169
+ if (!c) return null;
1170
+ const fx = Math.min(1, box.widthMm / c.w);
1171
+ const fy = Math.min(1, box.heightMm / c.h);
1172
+ return {
1173
+ leftPct: (1 - fx) * clampPct(x),
1174
+ topPct: (1 - fy) * clampPct(y),
1175
+ widthPct: fx * 100,
1176
+ heightPct: fy * 100
1177
+ };
1178
+ }
1179
+ function resolveDesignImageSrc(raw) {
1180
+ const value = String(raw ?? "");
1181
+ if (!value) return "";
1182
+ return value.includes("{") ? String(evaluateTemplate(value, DEFAULT_DEMO_DATA)) : value;
1183
+ }
1184
+ var CROP_AXIS_OPTIONS = {
1185
+ vertical: [
1186
+ { value: 0, label: "\u9876\u90E8" },
1187
+ { value: 50, label: "\u5C45\u4E2D" },
1188
+ { value: 100, label: "\u5E95\u90E8" }
1189
+ ],
1190
+ horizontal: [
1191
+ { value: 0, label: "\u5DE6\u4FA7" },
1192
+ { value: 50, label: "\u5C45\u4E2D" },
1193
+ { value: 100, label: "\u53F3\u4FA7" }
1194
+ ]
1195
+ };
1196
+ var CROP_GRID_OPTIONS = [
1197
+ { x: 0, y: 0, label: "\u5DE6\u4E0A" },
1198
+ { x: 50, y: 0, label: "\u4E0A\u4E2D" },
1199
+ { x: 100, y: 0, label: "\u53F3\u4E0A" },
1200
+ { x: 0, y: 50, label: "\u5DE6\u4E2D" },
1201
+ { x: 50, y: 50, label: "\u5C45\u4E2D" },
1202
+ { x: 100, y: 50, label: "\u53F3\u4E2D" },
1203
+ { x: 0, y: 100, label: "\u5DE6\u4E0B" },
1204
+ { x: 50, y: 100, label: "\u4E0B\u4E2D" },
1205
+ { x: 100, y: 100, label: "\u53F3\u4E0B" }
1206
+ ];
1207
+ var IMAGE_FIT_OPTIONS = [
1208
+ { value: "contain", label: "\u5305\u542B\uFF08\u4FDD\u6301\u6BD4\u4F8B\uFF09" },
1209
+ { value: "cover", label: "\u526A\u88C1\uFF08\u7B49\u6BD4\u94FA\u6EE1\u540E\u88C1\u8FB9\uFF09" },
1210
+ { value: "fill", label: "\u62C9\u4F38\u586B\u6EE1" },
1211
+ { value: "none", label: "\u539F\u59CB\u5C3A\u5BF8" },
1212
+ { value: "scale-down", label: "\u7F29\u5C0F\uFF08\u4FDD\u6301\u6BD4\u4F8B\uFF09" }
1213
+ ];
1214
+ var CROP_SAMPLE_IMAGE = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMjAiIGhlaWdodD0iMTIwIiB2aWV3Qm94PSIwIDAgMTIwIDEyMCI+PHJlY3Qgd2lkdGg9IjEyMCIgaGVpZ2h0PSIxMjAiIGZpbGw9IiNmZmZmZmYiLz48cGF0aCBkPSJNNDAgMFYxMjBNODAgMFYxMjBNMCA0MEgxMjBNMCA4MEgxMjAiIHN0cm9rZT0iI2VlZjFmNiIgc3Ryb2tlLXdpZHRoPSIxIi8+PGNpcmNsZSBjeD0iMjAiIGN5PSIyMCIgcj0iMy41IiBmaWxsPSIjOGI5NWE1Ii8+PGNpcmNsZSBjeD0iMTAwIiBjeT0iMjAiIHI9IjMuNSIgZmlsbD0iIzhiOTVhNSIvPjxjaXJjbGUgY3g9IjIwIiBjeT0iMTAwIiByPSIzLjUiIGZpbGw9IiM4Yjk1YTUiLz48Y2lyY2xlIGN4PSIxMDAiIGN5PSIxMDAiIHI9IjMuNSIgZmlsbD0iIzhiOTVhNSIvPjxjaXJjbGUgY3g9IjYwIiBjeT0iMjAiIHI9IjciIGZpbGw9IiNjMDM5MmIiLz48Y2lyY2xlIGN4PSI2MCIgY3k9IjEwMCIgcj0iNyIgZmlsbD0iIzFmNGZhMyIvPjxjaXJjbGUgY3g9IjIwIiBjeT0iNjAiIHI9IjciIGZpbGw9IiMyYzdhNGEiLz48Y2lyY2xlIGN4PSIxMDAiIGN5PSI2MCIgcj0iNyIgZmlsbD0iI2UwN2EyMCIvPjxjaXJjbGUgY3g9IjYwIiBjeT0iNjAiIHI9IjE0IiBmaWxsPSJub25lIiBzdHJva2U9IiMyZjNhNGEiIHN0cm9rZS13aWR0aD0iNCIvPjxjaXJjbGUgY3g9IjYwIiBjeT0iNjAiIHI9IjYiIGZpbGw9IiMyZjNhNGEiLz48L3N2Zz4=";
1215
+ var CROP_SAMPLE_NOTE = "\u56FE\u7247\u8FD8\u6CA1\u8BBE\u7F6E\uFF0C\u4E0A\u9762\u6309\u5185\u7F6E\u793A\u4F8B\u56FE\u6F14\u793A\u53D6\u4F4D\uFF1B\u6362\u4E0A\u771F\u56FE\u540E\u6863\u4F4D\u4E0E\u53EF\u632A\u91CF\u6309\u771F\u56FE\u91CD\u7B97";
1216
+ function resolveCropPreview(resolvedSrc) {
1217
+ const value = String(resolvedSrc ?? "").trim();
1218
+ if (!value || value.includes("{") || value.includes("}")) return { src: CROP_SAMPLE_IMAGE, isSample: true };
1219
+ return { src: value, isSample: false };
1220
+ }
1221
+ function cropAxisLabel(axis) {
1222
+ return axis === "vertical" ? "\u5782\u76F4\u4F4D\u7F6E (%)" : "\u6C34\u5E73\u4F4D\u7F6E (%)";
1223
+ }
1224
+ var CROP_SCALE_LABEL = "\u653E\u5927\u6BD4\u4F8B (%)";
1225
+ function cropAxisNote(travel, keepRaw = false) {
1226
+ if (keepRaw) return "\u5DF2\u4FDD\u7559\u6A21\u677F\u91CC\u7684\u539F\u503C\uFF1B\u6539\u52A8\u4E0B\u9762\u4EFB\u4E00\u9879\u5C31\u6574\u4F53\u66FF\u6362\u6210\u65B0\u7684\u53D6\u4F4D";
1227
+ const { x, y } = travel;
1228
+ if (x === null || y === null) return "";
1229
+ if (x > 0 && y > 0) return `\u6C34\u5E73\u53EF\u632A ${x}mm\u3001\u5782\u76F4\u53EF\u632A ${y}mm\uFF1A0 \u8D34\u5DE6\uFF0F\u8D34\u9876\uFF0C100 \u8D34\u53F3\uFF0F\u8D34\u5E95`;
1230
+ if (x > 0) return `\u6C34\u5E73\u53EF\u632A ${x}mm\uFF1B\u5782\u76F4\u8FD9\u4E00\u8F74\u5DF2\u8D34\u6EE1\uFF0C\u632A\u4E0D\u52A8`;
1231
+ if (y > 0) return `\u5782\u76F4\u53EF\u632A ${y}mm\uFF1B\u6C34\u5E73\u8FD9\u4E00\u8F74\u5DF2\u8D34\u6EE1\uFF0C\u632A\u4E0D\u52A8`;
1232
+ return "\u8FD9\u4E2A\u7F29\u653E\u4E0B\u56FE\u4E0E\u6846\u6B63\u597D\u4E00\u6837\u5927\uFF0C\u4E24\u8F74\u90FD\u6CA1\u6709\u53EF\u632A\u7684\u4F59\u91CF";
1233
+ }
1234
+ function cropAxisFields(travel, x, y) {
1235
+ return [
1236
+ { name: "horizontal", label: cropAxisLabel("horizontal"), value: x, travelMm: travel.x },
1237
+ { name: "vertical", label: cropAxisLabel("vertical"), value: y, travelMm: travel.y }
1238
+ ];
1239
+ }
1240
+ function cropPresetOptions(travel, x, y) {
1241
+ const movX = travel.x !== null && travel.x > 0;
1242
+ const movY = travel.y !== null && travel.y > 0;
1243
+ if (movY && !movX) {
1244
+ return CROP_AXIS_OPTIONS.vertical.map((o) => ({ value: `${x},${o.value}`, label: o.label }));
1245
+ }
1246
+ if (movX && !movY) {
1247
+ return CROP_AXIS_OPTIONS.horizontal.map((o) => ({ value: `${o.value},${y}`, label: o.label }));
1248
+ }
1249
+ return CROP_GRID_OPTIONS.map((o) => ({ value: `${o.x},${o.y}`, label: o.label }));
1250
+ }
1251
+
869
1252
  // src/designer/utils/field-groups.ts
870
1253
  function groupFields(fields) {
871
1254
  const sorted = [...fields].sort((a, b) => (a.sortOrder ?? 0) - (b.sortOrder ?? 0));
@@ -979,157 +1362,6 @@ function getElementBindings(element) {
979
1362
  return [...staticBindings, ...dynamicBindings];
980
1363
  }
981
1364
 
982
- // src/designer/utils/demo-data.ts
983
- function getDemoData() {
984
- return DEFAULT_DEMO_DATA;
985
- }
986
- var DEFAULT_DEMO_DATA = {
987
- supplier: {
988
- name: "\u946B\u8FBE\u4E94\u91D1\u6709\u9650\u516C\u53F8",
989
- phone: "0571-88776655",
990
- address: "\u676D\u5DDE\u5E02\u8427\u5C71\u533A\u7ECF\u6D4E\u5F00\u53D1\u533A88\u53F7"
991
- },
992
- receiver: {
993
- name: "\u674E\u56DB",
994
- phone: "13912345678",
995
- address: "\u676D\u5DDE\u5E02\u4F59\u676D\u533A\u6587\u4E00\u897F\u8DEF998\u53F7"
996
- },
997
- order: {
998
- no: "PO20260801001",
999
- date: "2026-08-01",
1000
- total: 69543.75
1001
- },
1002
- // 50 条商品明细, 用于验证多页分页效果
1003
- goods: [
1004
- { name: "\u78B3\u94A2\u87BA\u4E1D M8", spec: "M14\xD710", unit: "\u4E2A", qty: 100, price: 0.5, amount: 50, remark: "A\u7EA7" },
1005
- { name: "\u4E0D\u9508\u94A2\u87BA\u6BCD M10", spec: "M16\xD711", unit: "\u5957", qty: 117, price: 0.75, amount: 87.75, remark: "" },
1006
- { name: "\u5F39\u7C27\u57AB\u5708 M12", spec: "M6\xD712", unit: "\u76D2", qty: 134, price: 1, amount: 134, remark: "" },
1007
- { name: "\u516D\u89D2\u87BA\u6813 M14", spec: "M5\xD713", unit: "\u652F", qty: 151, price: 1.25, amount: 188.75, remark: "" },
1008
- { name: "\u5185\u516D\u89D2\u87BA\u9489 M16", spec: "M20\xD714", unit: "\u888B", qty: 168, price: 1.5, amount: 252, remark: "" },
1009
- { name: "\u5E73\u57AB\u5708 M6", spec: "M4\xD715", unit: "\u4EF6", qty: 185, price: 1.75, amount: 323.75, remark: "" },
1010
- { name: "\u81EA\u653B\u87BA\u9489 M5", spec: "M3\xD716", unit: "\u6839", qty: 202, price: 2, amount: 404, remark: "" },
1011
- { name: "\u53CC\u5934\u87BA\u67F1 M20", spec: "M8\xD717", unit: "\u5305", qty: 219, price: 2.25, amount: 492.75, remark: "A\u7EA7" },
1012
- { name: "\u7D27\u5B9A\u87BA\u9489 M4", spec: "M10\xD718", unit: "\u53EA", qty: 236, price: 2.5, amount: 590, remark: "" },
1013
- { name: "\u5341\u5B57\u76D8\u5934\u9489 M3", spec: "M12\xD719", unit: "\u7EC4", qty: 253, price: 2.75, amount: 695.75, remark: "" },
1014
- { name: "\u78B3\u94A2\u87BA\u4E1D M8", spec: "M14\xD720", unit: "\u4E2A", qty: 270, price: 3, amount: 810, remark: "" },
1015
- { name: "\u4E0D\u9508\u94A2\u87BA\u6BCD M10", spec: "M16\xD721", unit: "\u5957", qty: 287, price: 3.25, amount: 932.75, remark: "" },
1016
- { name: "\u5F39\u7C27\u57AB\u5708 M12", spec: "M6\xD722", unit: "\u76D2", qty: 304, price: 3.5, amount: 1064, remark: "" },
1017
- { name: "\u516D\u89D2\u87BA\u6813 M14", spec: "M5\xD723", unit: "\u652F", qty: 321, price: 3.75, amount: 1203.75, remark: "" },
1018
- { name: "\u5185\u516D\u89D2\u87BA\u9489 M16", spec: "M20\xD724", unit: "\u888B", qty: 338, price: 4, amount: 1352, remark: "A\u7EA7" },
1019
- { name: "\u5E73\u57AB\u5708 M6", spec: "M4\xD725", unit: "\u4EF6", qty: 355, price: 4.25, amount: 1508.75, remark: "" },
1020
- { name: "\u81EA\u653B\u87BA\u9489 M5", spec: "M3\xD726", unit: "\u6839", qty: 372, price: 4.5, amount: 1674, remark: "" },
1021
- { name: "\u53CC\u5934\u87BA\u67F1 M20", spec: "M8\xD727", unit: "\u5305", qty: 389, price: 4.75, amount: 1847.75, remark: "" },
1022
- { name: "\u7D27\u5B9A\u87BA\u9489 M4", spec: "M10\xD728", unit: "\u53EA", qty: 406, price: 5, amount: 2030, remark: "" },
1023
- { name: "\u5341\u5B57\u76D8\u5934\u9489 M3", spec: "M12\xD729", unit: "\u7EC4", qty: 423, price: 5.25, amount: 2220.75, remark: "" },
1024
- { name: "\u78B3\u94A2\u87BA\u4E1D M8", spec: "M14\xD730", unit: "\u4E2A", qty: 440, price: 0.5, amount: 220, remark: "" },
1025
- { name: "\u4E0D\u9508\u94A2\u87BA\u6BCD M10", spec: "M16\xD731", unit: "\u5957", qty: 457, price: 0.75, amount: 342.75, remark: "A\u7EA7" },
1026
- { name: "\u5F39\u7C27\u57AB\u5708 M12", spec: "M6\xD732", unit: "\u76D2", qty: 474, price: 1, amount: 474, remark: "" },
1027
- { name: "\u516D\u89D2\u87BA\u6813 M14", spec: "M5\xD733", unit: "\u652F", qty: 491, price: 1.25, amount: 613.75, remark: "" },
1028
- { name: "\u5185\u516D\u89D2\u87BA\u9489 M16", spec: "M20\xD734", unit: "\u888B", qty: 508, price: 1.5, amount: 762, remark: "" },
1029
- { name: "\u5E73\u57AB\u5708 M6", spec: "M4\xD735", unit: "\u4EF6", qty: 525, price: 1.75, amount: 918.75, remark: "" },
1030
- { name: "\u81EA\u653B\u87BA\u9489 M5", spec: "M3\xD736", unit: "\u6839", qty: 542, price: 2, amount: 1084, remark: "" },
1031
- { name: "\u53CC\u5934\u87BA\u67F1 M20", spec: "M8\xD737", unit: "\u5305", qty: 559, price: 2.25, amount: 1257.75, remark: "" },
1032
- { name: "\u7D27\u5B9A\u87BA\u9489 M4", spec: "M10\xD738", unit: "\u53EA", qty: 576, price: 2.5, amount: 1440, remark: "A\u7EA7" },
1033
- { name: "\u5341\u5B57\u76D8\u5934\u9489 M3", spec: "M12\xD739", unit: "\u7EC4", qty: 593, price: 2.75, amount: 1630.75, remark: "" },
1034
- { name: "\u78B3\u94A2\u87BA\u4E1D M8", spec: "M14\xD740", unit: "\u4E2A", qty: 610, price: 3, amount: 1830, remark: "" },
1035
- { name: "\u4E0D\u9508\u94A2\u87BA\u6BCD M10", spec: "M16\xD741", unit: "\u5957", qty: 627, price: 3.25, amount: 2037.75, remark: "" },
1036
- { name: "\u5F39\u7C27\u57AB\u5708 M12", spec: "M6\xD742", unit: "\u76D2", qty: 644, price: 3.5, amount: 2254, remark: "" },
1037
- { name: "\u516D\u89D2\u87BA\u6813 M14", spec: "M5\xD743", unit: "\u652F", qty: 661, price: 3.75, amount: 2478.75, remark: "" },
1038
- { name: "\u5185\u516D\u89D2\u87BA\u9489 M16", spec: "M20\xD744", unit: "\u888B", qty: 678, price: 4, amount: 2712, remark: "" },
1039
- { name: "\u5E73\u57AB\u5708 M6", spec: "M4\xD745", unit: "\u4EF6", qty: 695, price: 4.25, amount: 2953.75, remark: "A\u7EA7" },
1040
- { name: "\u81EA\u653B\u87BA\u9489 M5", spec: "M3\xD746", unit: "\u6839", qty: 712, price: 4.5, amount: 3204, remark: "" },
1041
- { name: "\u53CC\u5934\u87BA\u67F1 M20", spec: "M8\xD747", unit: "\u5305", qty: 729, price: 4.75, amount: 3462.75, remark: "" },
1042
- { name: "\u7D27\u5B9A\u87BA\u9489 M4", spec: "M10\xD748", unit: "\u53EA", qty: 746, price: 5, amount: 3730, remark: "" },
1043
- { name: "\u5341\u5B57\u76D8\u5934\u9489 M3", spec: "M12\xD749", unit: "\u7EC4", qty: 763, price: 5.25, amount: 4005.75, remark: "" },
1044
- { name: "\u78B3\u94A2\u87BA\u4E1D M8", spec: "M14\xD710", unit: "\u4E2A", qty: 780, price: 0.5, amount: 390, remark: "" },
1045
- { name: "\u4E0D\u9508\u94A2\u87BA\u6BCD M10", spec: "M16\xD711", unit: "\u5957", qty: 797, price: 0.75, amount: 597.75, remark: "" },
1046
- { name: "\u5F39\u7C27\u57AB\u5708 M12", spec: "M6\xD712", unit: "\u76D2", qty: 814, price: 1, amount: 814, remark: "A\u7EA7" },
1047
- { name: "\u516D\u89D2\u87BA\u6813 M14", spec: "M5\xD713", unit: "\u652F", qty: 831, price: 1.25, amount: 1038.75, remark: "" },
1048
- { name: "\u5185\u516D\u89D2\u87BA\u9489 M16", spec: "M20\xD714", unit: "\u888B", qty: 848, price: 1.5, amount: 1272, remark: "" },
1049
- { name: "\u5E73\u57AB\u5708 M6", spec: "M4\xD715", unit: "\u4EF6", qty: 865, price: 1.75, amount: 1513.75, remark: "" },
1050
- { name: "\u81EA\u653B\u87BA\u9489 M5", spec: "M3\xD716", unit: "\u6839", qty: 882, price: 2, amount: 1764, remark: "" },
1051
- { name: "\u53CC\u5934\u87BA\u67F1 M20", spec: "M8\xD717", unit: "\u5305", qty: 899, price: 2.25, amount: 2022.75, remark: "" },
1052
- { name: "\u7D27\u5B9A\u87BA\u9489 M4", spec: "M10\xD718", unit: "\u53EA", qty: 916, price: 2.5, amount: 2290, remark: "" },
1053
- { name: "\u5341\u5B57\u76D8\u5934\u9489 M3", spec: "M12\xD719", unit: "\u7EC4", qty: 933, price: 2.75, amount: 2565.75, remark: "A\u7EA7" }
1054
- ]
1055
- };
1056
-
1057
- // src/designer/utils/engine.ts
1058
- var engine = new TemplateEngine();
1059
-
1060
- // src/designer/utils/expression-eval.ts
1061
- var EXTENDED_FUNCTIONS = {
1062
- MONEY: formatMoney,
1063
- CONCAT: (...args) => args.filter((v) => v != null).join(""),
1064
- IF: ifFn,
1065
- FORMAT: (value) => {
1066
- if (typeof value !== "number") return String(value);
1067
- return value.toLocaleString("zh-CN", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
1068
- },
1069
- SUBSTR: (str, start, len) => String(str).slice(start, len ? start + len : void 0),
1070
- LEN: (str) => String(str).length,
1071
- // 四则运算(与 +/-/*// 运算符同一套数值语义,供不方便写运算符的场景使用)
1072
- ADD: addNumbers,
1073
- SUB: subtractNumbers,
1074
- MUL: multiplyNumbers,
1075
- DIV: divideNumbers,
1076
- // 数值修约
1077
- ROUND: round,
1078
- ROUNDUP: roundUp,
1079
- CEIL: roundUp,
1080
- ROUNDDOWN: roundDown,
1081
- FLOOR: roundDown,
1082
- ROUNDBANK: roundHalfEven,
1083
- NOW: () => (/* @__PURE__ */ new Date()).toISOString().split("T")[0],
1084
- IFEMPTY: (value, defaultVal) => value != null && value !== "" ? String(value) : defaultVal,
1085
- PAD: (value, len, char) => String(value).padStart(len, char),
1086
- REPLACE: (str, from, to) => String(str).replace(new RegExp(from, "g"), to),
1087
- JSON: (value) => JSON.stringify(value, null, 2),
1088
- DATE: formatDate,
1089
- UPPER: toUpperCaseAmount
1090
- };
1091
- for (const [name, fn] of Object.entries(EXTENDED_FUNCTIONS)) {
1092
- engine.registerFunction(name, fn);
1093
- }
1094
- function aggregate(fn, field, rows) {
1095
- switch (fn.toUpperCase()) {
1096
- case "SUM":
1097
- return sum(rows, field);
1098
- case "AVG":
1099
- return avg(rows, field);
1100
- case "COUNT":
1101
- return count(rows, field);
1102
- case "MIN":
1103
- return min(rows, field);
1104
- case "MAX":
1105
- return max(rows, field);
1106
- default:
1107
- return 0;
1108
- }
1109
- }
1110
- function safeEval(expr, context, _callableNames) {
1111
- return engine.evaluate(expr, context);
1112
- }
1113
- function evaluateTemplate(text, ctx) {
1114
- if (!text) return "";
1115
- if (!text.includes("{")) return text;
1116
- const rows = Array.isArray(ctx.rows) ? ctx.rows : [];
1117
- let processedText = text.replace(/\{([^}]+)\}/g, (_match, inner) => {
1118
- let expr = inner.trim();
1119
- expr = expr.replace(/\b(SUM|AVG|COUNT|MIN|MAX)\(([^)]+)\)/g, (_m, fn, arg) => {
1120
- const field = arg.trim().replace(/^['"]|['"]$/g, "");
1121
- return String(aggregate(fn, field, rows));
1122
- });
1123
- return `{${expr}}`;
1124
- });
1125
- try {
1126
- const result = engine.render(processedText, ctx);
1127
- return result;
1128
- } catch {
1129
- return text;
1130
- }
1131
- }
1132
-
1133
1365
  // src/designer/utils/binding.ts
1134
1366
  function createFieldElement(field) {
1135
1367
  return createRuntimeElement("text", {
@@ -1658,6 +1890,13 @@ export {
1658
1890
  BARCODE_MODULE_WIDTH_MM,
1659
1891
  BARCODE_QUIET_ZONE_MODULES,
1660
1892
  BARCODE_TEXT_FONT_SIZE_MODULES,
1893
+ CROP_AXIS_OPTIONS,
1894
+ CROP_GRID_OPTIONS,
1895
+ CROP_SAMPLE_IMAGE,
1896
+ CROP_SAMPLE_NOTE,
1897
+ CROP_SCALE_LABEL,
1898
+ CROP_SCALE_MAX,
1899
+ CROP_SCALE_MIN,
1661
1900
  DEFAULT_DEMO_DATA,
1662
1901
  DEFAULT_SHRINK_MIN_FONT_SIZE_PT,
1663
1902
  ELEMENT_BINDING_REGISTRY,
@@ -1665,6 +1904,7 @@ export {
1665
1904
  EXTENDED_FUNCTIONS,
1666
1905
  FIT_SCALE_MIN_PERCENT,
1667
1906
  GHOST_BORDER_CSS,
1907
+ IMAGE_FIT_OPTIONS,
1668
1908
  LABEL_PAPER_GROUP,
1669
1909
  MIN_COL_WIDTH_MM,
1670
1910
  MIN_SCALE_PERCENT,
@@ -1681,12 +1921,14 @@ export {
1681
1921
  barcodeAvailableBoxMm,
1682
1922
  barcodePreferredModuleWidthMm,
1683
1923
  barcodeUnitsPerModule,
1924
+ buildCropAnchor,
1684
1925
  buildRulerTicks,
1685
1926
  calcResizeRect,
1686
1927
  canMergeReason,
1687
1928
  cellFitCapMm,
1688
1929
  cellFitKey,
1689
1930
  cellFitWidthMm,
1931
+ cellImageBoxMm,
1690
1932
  chooseMajorStepMM,
1691
1933
  clampResizedColumnWidth,
1692
1934
  clampScalePercent,
@@ -1698,6 +1940,13 @@ export {
1698
1940
  createDefaultTable,
1699
1941
  createFieldElement,
1700
1942
  createRuntimeElement,
1943
+ cropAxisFields,
1944
+ cropAxisLabel,
1945
+ cropAxisNote,
1946
+ cropPresetOptions,
1947
+ cropScalePct,
1948
+ cropStyleDeclarations,
1949
+ cropWindow,
1701
1950
  deleteCol,
1702
1951
  deleteRow,
1703
1952
  engine,
@@ -1729,18 +1978,26 @@ export {
1729
1978
  normalizeSelection,
1730
1979
  normalizeTemplateUnits,
1731
1980
  parseCellFitKey,
1981
+ parseCropAnchor,
1982
+ propertyTip,
1732
1983
  ptToMm,
1733
1984
  pxToMm,
1734
1985
  resolveBarcodeDesignValue,
1735
1986
  resolveBarcodeSize,
1736
1987
  resolveCellBorderCss,
1737
1988
  resolveCellTextFit,
1989
+ resolveCropPreview,
1990
+ resolveCropTravel,
1991
+ resolveDesignImageSrc,
1738
1992
  resolveElementBorder,
1739
1993
  resolveElementTextFit,
1994
+ resolveOverlayPlacement,
1740
1995
  resolveShrinkMinFontSize,
1741
1996
  resolveTextBinding,
1997
+ resolveToolbarOverflow,
1742
1998
  roundFontSize,
1743
1999
  safeEval,
2000
+ sanitizeObjectPosition,
1744
2001
  searchProperties,
1745
2002
  setHeaderRepeat,
1746
2003
  setRowType,