@worm-vue3-print/canvas 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/README.md +54 -0
  2. package/dist/canvas.css +1 -0
  3. package/dist/components/CanvasArea.vue.d.ts +102 -0
  4. package/dist/components/CanvasPaper.vue.d.ts +50 -0
  5. package/dist/components/DesignerToolbar.vue.d.ts +59 -0
  6. package/dist/components/ExpressionEditor.vue.d.ts +16 -0
  7. package/dist/components/FieldTreePanel.vue.d.ts +11 -0
  8. package/dist/components/LayerPanel.vue.d.ts +14 -0
  9. package/dist/components/LeftPanel.vue.d.ts +24 -0
  10. package/dist/components/PresetColorPicker.vue.d.ts +10 -0
  11. package/dist/components/PrintDesigner.vue.d.ts +27 -0
  12. package/dist/components/PrintHtmlPreview.vue.d.ts +23 -0
  13. package/dist/components/PropertyPanel.vue.d.ts +23 -0
  14. package/dist/components/Ruler.vue.d.ts +12 -0
  15. package/dist/components/StatusBar.vue.d.ts +14 -0
  16. package/dist/components/WatermarkConfig.vue.d.ts +12 -0
  17. package/dist/components/elements/BarcodeElement.vue.d.ts +9 -0
  18. package/dist/components/elements/BaseElement.vue.d.ts +45 -0
  19. package/dist/components/elements/CellBarcode.vue.d.ts +10 -0
  20. package/dist/components/elements/HtmlElement.vue.d.ts +9 -0
  21. package/dist/components/elements/ImageElement.vue.d.ts +9 -0
  22. package/dist/components/elements/LineElement.vue.d.ts +7 -0
  23. package/dist/components/elements/LongTextElement.vue.d.ts +9 -0
  24. package/dist/components/elements/PageNumberElement.vue.d.ts +9 -0
  25. package/dist/components/elements/QrcodeElement.vue.d.ts +9 -0
  26. package/dist/components/elements/ShapeElement.vue.d.ts +7 -0
  27. package/dist/components/elements/TableContextMenu.vue.d.ts +19 -0
  28. package/dist/components/elements/TableElement.vue.d.ts +17 -0
  29. package/dist/components/elements/TextElement.vue.d.ts +9 -0
  30. package/dist/components/property/AdvancedGroup.vue.d.ts +13 -0
  31. package/dist/components/property/AppearanceGroup.vue.d.ts +10 -0
  32. package/dist/components/property/BindingControl.vue.d.ts +13 -0
  33. package/dist/components/property/BorderBgGroup.vue.d.ts +9 -0
  34. package/dist/components/property/CodeGroup.vue.d.ts +13 -0
  35. package/dist/components/property/ImageContentUpload.vue.d.ts +10 -0
  36. package/dist/components/property/PaginationGroup.vue.d.ts +9 -0
  37. package/dist/components/property/PositionSizeGroup.vue.d.ts +9 -0
  38. package/dist/components/property/PropertyGroup.vue.d.ts +19 -0
  39. package/dist/components/property/PropertySearch.vue.d.ts +7 -0
  40. package/dist/components/property/TableCellGroup.vue.d.ts +12 -0
  41. package/dist/components/property/TableRowGroup.vue.d.ts +8 -0
  42. package/dist/components/property/TableSettingsGroup.vue.d.ts +8 -0
  43. package/dist/composables/useAdsorb.d.ts +26 -0
  44. package/dist/composables/useAdsorbManager.d.ts +31 -0
  45. package/dist/composables/useAlign.d.ts +5 -0
  46. package/dist/composables/useBindingDisplay.d.ts +11 -0
  47. package/dist/composables/useClipboard.d.ts +251 -0
  48. package/dist/composables/useDesignerState.d.ts +1149 -0
  49. package/dist/composables/useDrag.d.ts +51 -0
  50. package/dist/composables/useGroup.d.ts +7 -0
  51. package/dist/composables/useGuides.d.ts +12 -0
  52. package/dist/composables/useHistory.d.ts +31 -0
  53. package/dist/composables/useHostAdapter.d.ts +4 -0
  54. package/dist/composables/useKeyboard.d.ts +22 -0
  55. package/dist/composables/useResize.d.ts +26 -0
  56. package/dist/composables/useSelection.d.ts +26 -0
  57. package/dist/composables/useStudioChrome.d.ts +8 -0
  58. package/dist/composables/useTableSelection.d.ts +10 -0
  59. package/dist/index.cjs +4 -0
  60. package/dist/index.cjs.map +1 -0
  61. package/dist/index.d.ts +9 -0
  62. package/dist/index.js +6444 -0
  63. package/dist/index.js.map +1 -0
  64. package/dist/render/browser-code-renderer.d.ts +3 -0
  65. package/dist/render/browser-pagination.d.ts +17 -0
  66. package/dist/types.d.ts +282 -0
  67. package/dist/utils/binding-registry.d.ts +8 -0
  68. package/dist/utils/binding.d.ts +16 -0
  69. package/dist/utils/default-config.d.ts +13 -0
  70. package/dist/utils/demo-data.d.ts +2 -0
  71. package/dist/utils/element-factory.d.ts +4 -0
  72. package/dist/utils/engine.d.ts +2 -0
  73. package/dist/utils/expression-eval.d.ts +30 -0
  74. package/dist/utils/field-groups.d.ts +21 -0
  75. package/dist/utils/migrate.d.ts +2 -0
  76. package/dist/utils/preset-colors.d.ts +2 -0
  77. package/dist/utils/property-search.d.ts +18 -0
  78. package/dist/utils/ruler.d.ts +7 -0
  79. package/dist/utils/scale.d.ts +2 -0
  80. package/dist/utils/table-matrix.d.ts +61 -0
  81. package/dist/utils/units.d.ts +4 -0
  82. package/dist/utils/zone-layout.d.ts +27 -0
  83. package/package.json +55 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../src/utils/table-matrix.ts","../src/utils/element-factory.ts","../src/utils/engine.ts","../src/utils/demo-data.ts","../src/utils/expression-eval.ts","../src/utils/binding.ts","../src/utils/units.ts","../src/utils/migrate.ts","../src/utils/default-config.ts","../src/utils/scale.ts","../src/utils/zone-layout.ts","../src/composables/useSelection.ts","../src/composables/useClipboard.ts","../src/composables/useAlign.ts","../src/composables/useGroup.ts","../src/composables/useHistory.ts","../src/composables/useKeyboard.ts","../src/composables/useDesignerState.ts","../src/composables/useGuides.ts","../src/composables/useTableSelection.ts","../src/composables/useHostAdapter.ts","../src/components/DesignerToolbar.vue","../src/components/LayerPanel.vue","../src/utils/field-groups.ts","../src/components/FieldTreePanel.vue","../src/components/LeftPanel.vue","../src/composables/useDrag.ts","../src/composables/useResize.ts","../src/composables/useBindingDisplay.ts","../src/components/elements/TextElement.vue","../src/components/elements/ImageElement.vue","../src/components/elements/LongTextElement.vue","../src/components/elements/TableContextMenu.vue","../src/components/elements/CellBarcode.vue","../src/components/elements/TableElement.vue","../src/components/elements/LineElement.vue","../src/components/elements/ShapeElement.vue","../src/components/elements/BarcodeElement.vue","../src/components/elements/QrcodeElement.vue","../src/components/elements/HtmlElement.vue","../src/components/elements/PageNumberElement.vue","../src/components/elements/BaseElement.vue","../src/utils/ruler.ts","../src/components/Ruler.vue","../src/composables/useAdsorb.ts","../src/composables/useAdsorbManager.ts","../src/components/CanvasPaper.vue","../src/components/CanvasArea.vue","../src/utils/property-search.ts","../src/components/property/PropertySearch.vue","../src/components/property/PropertyGroup.vue","../src/components/property/PositionSizeGroup.vue","../src/utils/preset-colors.ts","../src/components/PresetColorPicker.vue","../src/components/property/AppearanceGroup.vue","../src/components/ExpressionEditor.vue","../src/components/property/BindingControl.vue","../src/components/property/TableSettingsGroup.vue","../src/components/property/BorderBgGroup.vue","../src/components/property/AdvancedGroup.vue","../src/components/property/PaginationGroup.vue","../src/components/property/ImageContentUpload.vue","../src/components/property/TableRowGroup.vue","../src/components/property/TableCellGroup.vue","../src/utils/binding-registry.ts","../src/components/PropertyPanel.vue","../src/components/StatusBar.vue","../src/composables/useStudioChrome.ts","../src/components/PrintDesigner.vue","../src/render/browser-pagination.ts","../src/render/browser-code-renderer.ts","../src/components/PrintHtmlPreview.vue"],"sourcesContent":["// web/src/components/print/utils/table-matrix.ts\n// Excel 风格表格矩阵结构操作纯函数库。\n// 约定:函数原地修改传入的 rows/colWidths;返回 string 的函数以非空字符串为拒绝原因。\nimport type { TableRow, TableRowType, TableCell, TableCellBorder, ElementOptions } from '../types'\n\nexport interface CellRect { r1: number; c1: number; r2: number; c2: number }\n\n/** 单元格 ID 生成器:使用闭包隔离的计数器,避免全局变量冲突 */\nfunction createCellIdGenerator() {\n let seq = 0\n return function genCellId(): string {\n seq += 1\n return `cell-${Date.now().toString(36)}-${seq}`\n }\n}\n\n/** 行 ID 生成器:使用闭包隔离的计数器 */\nfunction createRowIdGenerator() {\n let seq = 0\n return function genRowId(): string {\n seq += 1\n return `row-${Date.now().toString(36)}-${seq}`\n }\n}\n\n// 模块级单例:同一模块内共享计数器\nconst genCellId = createCellIdGenerator()\nconst genRowId = createRowIdGenerator()\n\nconst DEFAULT_BORDER: TableCellBorder = { width: 0.75, style: 'solid', color: '#333333' }\n\n/** JSON 深拷贝:兼容 Vue reactive Proxy(structuredClone 对 Proxy 抛 DataCloneError) */\nfunction deepClone<T>(v: T): T {\n return JSON.parse(JSON.stringify(v)) as T\n}\n\nexport function createCell(partial?: Partial<TableCell>): TableCell {\n return {\n id: genCellId(),\n borders: {\n top: { ...DEFAULT_BORDER }, right: { ...DEFAULT_BORDER },\n bottom: { ...DEFAULT_BORDER }, left: { ...DEFAULT_BORDER },\n },\n ...partial,\n }\n}\n\n/** 默认新建表格:3 列 × 4 行(标题/数据/小计/汇总),列宽均分 50mm,表格组件默认显示当前页小计行 */\nexport function createDefaultTable(): { rows: TableRow[]; colWidths: number[] } {\n const colWidths = [50, 50, 50]\n const mk = (type: TableRowType, repeat?: boolean): TableRow => ({\n id: genRowId(),\n type,\n height: 8,\n ...(repeat !== undefined ? { repeatOnPage: repeat } : {}),\n cells: colWidths.map(() => createCell()),\n })\n const header = mk('header', true)\n header.cells.forEach((c, i) => { c.formatter = `列${i + 1}`; c.align = 'center'; c.fontWeight = 'bold' })\n return { rows: [header, mk('data'), mk('subtotal'), mk('summary')], colWidths }\n}\n\n/** 定位覆盖 (r,c) 的主格坐标(自身非 merged 即为主格) */\nexport function findMainCell(rows: TableRow[], r: number, c: number): { r: number; c: number } {\n if (!rows[r]!.cells[c]!.merged) { return { r, c } }\n for (let ri = r; ri >= 0; ri--) {\n for (let ci = c; ci >= 0; ci--) {\n const cell = rows[ri]!.cells[ci]!\n if (cell.merged) { continue }\n const rs = cell.rowspan ?? 1\n const cs = cell.colspan ?? 1\n if (ri + rs - 1 >= r && ci + cs - 1 >= c) { return { r: ri, c: ci } }\n }\n }\n return { r, c }\n}\n\n/** 主格覆盖矩形 */\nexport function getSpanRect(rows: TableRow[], r: number, c: number): CellRect {\n const main = findMainCell(rows, r, c)\n const cell = rows[main.r]!.cells[main.c]!\n return {\n r1: main.r, c1: main.c,\n r2: main.r + (cell.rowspan ?? 1) - 1,\n c2: main.c + (cell.colspan ?? 1) - 1,\n }\n}\n\n/** 由锚点/焦点推导矩形选区,并迭代扩展至完整包含所有跨越的合并格 */\nexport function normalizeSelection(\n rows: TableRow[], a: { r: number; c: number }, b: { r: number; c: number },\n): CellRect {\n let rect: CellRect = {\n r1: Math.min(a.r, b.r), c1: Math.min(a.c, b.c),\n r2: Math.max(a.r, b.r), c2: Math.max(a.c, b.c),\n }\n for (;;) {\n let changed = false\n for (let r = rect.r1; r <= rect.r2; r++) {\n for (let c = rect.c1; c <= rect.c2; c++) {\n const span = getSpanRect(rows, r, c)\n const merged: CellRect = {\n r1: Math.min(rect.r1, span.r1), c1: Math.min(rect.c1, span.c1),\n r2: Math.max(rect.r2, span.r2), c2: Math.max(rect.c2, span.c2),\n }\n if (merged.r1 !== rect.r1 || merged.c1 !== rect.c1 || merged.r2 !== rect.r2 || merged.c2 !== rect.c2) {\n rect = merged\n changed = true\n }\n }\n }\n if (!changed) { return rect }\n }\n}\n\n/** 合并合法性校验,返回拒绝原因或 null */\nexport function canMergeReason(rows: TableRow[], rect: CellRect): string | null {\n const cellCount = (rect.r2 - rect.r1 + 1) * (rect.c2 - rect.c1 + 1)\n if (cellCount < 2) { return '至少选择 2 个单元格' }\n const types = new Set<TableRowType>()\n for (let r = rect.r1; r <= rect.r2; r++) { types.add(rows[r]!.type) }\n if (types.size > 1) { return '合并区域不能跨越不同类型的行' }\n // 与已有合并区部分重叠:normalize 后矩形应与选区一致\n const norm = normalizeSelection(rows, { r: rect.r1, c: rect.c1 }, { r: rect.r2, c: rect.c2 })\n if (norm.r1 !== rect.r1 || norm.c1 !== rect.c1 || norm.r2 !== rect.r2 || norm.c2 !== rect.c2) {\n return '选区与已有合并区域部分重叠'\n }\n return null\n}\n\n/** 合并:左上为主格,非空内容空格拼接并入主格 */\nexport function mergeCells(rows: TableRow[], rect: CellRect): void {\n const main = rows[rect.r1]!.cells[rect.c1]!\n const contents: string[] = []\n for (let r = rect.r1; r <= rect.r2; r++) {\n for (let c = rect.c1; c <= rect.c2; c++) {\n const cell = rows[r]!.cells[c]!\n if (cell.formatter) { contents.push(cell.formatter) }\n if (r === rect.r1 && c === rect.c1) { continue }\n cell.merged = true\n cell.rowspan = 1\n cell.colspan = 1\n cell.formatter = ''\n }\n }\n main.rowspan = rect.r2 - rect.r1 + 1\n main.colspan = rect.c2 - rect.c1 + 1\n main.formatter = contents.join(' ')\n}\n\n/** 拆分选区内所有合并格:占位格恢复并复制主格样式 */\nexport function splitCells(rows: TableRow[], rect: CellRect): void {\n for (let r = rect.r1; r <= rect.r2; r++) {\n for (let c = rect.c1; c <= rect.c2; c++) {\n const cell = rows[r]!.cells[c]!\n if (!cell.merged && ((cell.rowspan ?? 1) > 1 || (cell.colspan ?? 1) > 1)) {\n const span = getSpanRect(rows, r, c)\n const styleSrc = cell\n for (let sr = span.r1; sr <= span.r2; sr++) {\n for (let sc = span.c1; sc <= span.c2; sc++) {\n const t = rows[sr]!.cells[sc]!\n t.merged = false\n t.rowspan = 1\n t.colspan = 1\n copyCellStyle(styleSrc, t)\n }\n }\n cell.rowspan = 1\n cell.colspan = 1\n }\n }\n }\n}\n\nfunction copyCellStyle(src: TableCell, dst: TableCell): void {\n if (src === dst) { return }\n dst.align = src.align\n dst.valign = src.valign\n dst.fontSize = src.fontSize\n dst.fontWeight = src.fontWeight\n dst.color = src.color\n dst.backgroundColor = src.backgroundColor\n dst.borders = src.borders ? deepClone(src.borders) : undefined\n dst.padding = src.padding\n dst.wordWrap = src.wordWrap\n}\n\n/** 插入行。index 为参照行,position 决定插在其上方或下方 */\nexport function insertRow(rows: TableRow[], index: number, position: 'above' | 'below'): void {\n const insertAt = position === 'above' ? index : index + 1\n const ref = rows[index]!\n const colCount = ref.cells.length\n // 参照行为 data 时新行降级为 header(data 全表唯一)\n const type: TableRowType = ref.type === 'data' ? 'header' : ref.type\n const newRow: TableRow = {\n id: `row-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`,\n type,\n height: ref.height,\n cells: Array.from({ length: colCount }, () => createCell()),\n }\n // 处理跨越插入边界的纵向合并:主格 rowspan+1,新行对应格置 merged\n for (let c = 0; c < colCount; c++) {\n if (insertAt > 0 && insertAt < rows.length) {\n const span = getSpanRect(rows, insertAt - 1, c)\n if (span.r1 < insertAt && span.r2 >= insertAt) {\n const main = rows[span.r1]!.cells[span.c1]!\n main.rowspan = (main.rowspan ?? 1) + 1\n newRow.cells[c]!.merged = true\n }\n }\n }\n rows.splice(insertAt, 0, newRow)\n}\n\n/** 删除行;主格在被删行时移交下一行 */\nexport function deleteRow(rows: TableRow[], index: number): string | null {\n if (rows.length <= 1) { return '不能删除最后一行' }\n const row = rows[index]!\n const colCount = row.cells.length\n for (let c = 0; c < colCount; c++) {\n const cell = row.cells[c]!\n if (!cell.merged && (cell.rowspan ?? 1) > 1) {\n // 主格在被删行:移交到下一行\n const next = rows[index + 1]!.cells[c]!\n Object.assign(next, deepClone(cell), { id: next.id })\n next.rowspan = (cell.rowspan ?? 1) - 1\n next.merged = false\n } else if (cell.merged) {\n // 被删行处于某纵向合并中间:主格 rowspan-1\n const span = getSpanRect(rows, index, c)\n if (span.r1 < index && span.c1 === c) {\n const main = rows[span.r1]!.cells[span.c1]!\n main.rowspan = (main.rowspan ?? 1) - 1\n }\n }\n }\n rows.splice(index, 1)\n return null\n}\n\n/** 插入列 */\nexport function insertCol(\n rows: TableRow[], colWidths: number[], index: number, position: 'left' | 'right',\n): void {\n const insertAt = position === 'left' ? index : index + 1\n colWidths.splice(insertAt, 0, colWidths[index]!)\n for (const row of rows) {\n const newCell = createCell()\n if (insertAt > 0 && insertAt < row.cells.length) {\n const r = rows.indexOf(row)\n const span = getSpanRect(rows, r, insertAt - 1)\n if (span.c1 < insertAt && span.c2 >= insertAt) {\n const main = rows[span.r1]!.cells[span.c1]!\n // 每个横跨行都会命中一次,只在主格所在行加 colspan\n if (r === span.r1) { main.colspan = (main.colspan ?? 1) + 1 }\n newCell.merged = true\n }\n }\n row.cells.splice(insertAt, 0, newCell)\n }\n}\n\n/** 删除列;主格在被删列时移交右侧列 */\nexport function deleteCol(rows: TableRow[], colWidths: number[], index: number): string | null {\n if (colWidths.length <= 1) { return '不能删除最后一列' }\n for (let r = 0; r < rows.length; r++) {\n const cell = rows[r]!.cells[index]!\n if (!cell.merged && (cell.colspan ?? 1) > 1) {\n const next = rows[r]!.cells[index + 1]!\n Object.assign(next, deepClone(cell), { id: next.id })\n next.colspan = (cell.colspan ?? 1) - 1\n next.merged = false\n } else if (cell.merged) {\n const span = getSpanRect(rows, r, index)\n if (span.c1 < index && span.r1 === r) {\n const main = rows[span.r1]!.cells[span.c1]!\n main.colspan = (main.colspan ?? 1) - 1\n }\n }\n }\n for (const row of rows) { row.cells.splice(index, 1) }\n colWidths.splice(index, 1)\n return null\n}\n\n/** 行类型变更校验 + 写入。约束:header 顶部连续;data 唯一;subtotal/summary 在 data 之后;subtotal 在 summary 之前 */\nexport function setRowType(\n rows: TableRow[], index: number, type: TableRowType,\n): string | null {\n if (type === 'data') {\n const existing = rows.findIndex((r, i) => r.type === 'data' && i !== index)\n if (existing >= 0) { return `数据行已存在(第 ${existing + 1} 行),全表最多一行` }\n }\n if (type === 'header') {\n // 设置后 header 行必须从第 0 行起连续\n for (let i = 0; i < index; i++) {\n if (rows[i]!.type !== 'header') { return '标题行必须从表格顶部连续设置' }\n }\n }\n if (type === 'subtotal' || type === 'summary') {\n const dataIdx = rows.findIndex(r => r.type === 'data')\n if (dataIdx < 0) { return '请先设置数据行,小计/汇总行必须位于数据行之后' }\n if (index < dataIdx) { return '小计/汇总行必须位于数据行之后' }\n }\n if (type === 'subtotal') {\n // 目标状态:本行设为小计后,其上方(index 之前)不得存在汇总行(小计必须位于汇总行之前)\n if (rows.slice(0, index).some(r => r.type === 'summary')) {\n return '小计行必须位于汇总行之前'\n }\n }\n if (type === 'summary') {\n if (rows.slice(index + 1).some(r => r.type === 'subtotal')) {\n return '汇总行必须位于小计行之后'\n }\n }\n // 取消 header 时校验剩余 header 仍连续(中间行取消会断开)\n if (rows[index]!.type === 'header' && type !== 'header') {\n for (let i = index + 1; i < rows.length; i++) {\n if (rows[i]!.type === 'header') { return '取消该标题行会导致标题行不连续,请先调整后续标题行' }\n }\n }\n rows[index]!.type = type\n if (type !== 'header') { delete rows[index]!.repeatOnPage }\n return null\n}\n\nexport type BorderPreset = 'all' | 'outer' | 'inner' | 'none'\n\n/** 按预设批量写边框;none 时清空选区内所有格的 borders */\nexport function applyBorderPreset(\n rows: TableRow[], rect: CellRect, preset: BorderPreset, border: TableCellBorder,\n): void {\n for (let r = rect.r1; r <= rect.r2; r++) {\n for (let c = rect.c1; c <= rect.c2; c++) {\n const cell = rows[r]!.cells[c]!\n if (cell.merged) { continue }\n if (preset === 'none') {\n delete cell.borders\n continue\n }\n const span = getSpanRect(rows, r, c)\n const atTop = span.r1 === rect.r1\n const atBottom = span.r2 === rect.r2\n const atLeft = span.c1 === rect.c1\n const atRight = span.c2 === rect.c2\n const b = { ...(cell.borders ?? {}) }\n if (preset === 'all') {\n b.top = { ...border }; b.bottom = { ...border }; b.left = { ...border }; b.right = { ...border }\n } else if (preset === 'outer') {\n if (atTop) { b.top = { ...border } }\n if (atBottom) { b.bottom = { ...border } }\n if (atLeft) { b.left = { ...border } }\n if (atRight) { b.right = { ...border } }\n } else if (preset === 'inner') {\n if (!atTop) { b.top = { ...border } }\n if (!atBottom) { b.bottom = { ...border } }\n if (!atLeft) { b.left = { ...border } }\n if (!atRight) { b.right = { ...border } }\n }\n cell.borders = b\n }\n }\n}\n\n/** 设计态下无边框单元格的辅助虚线:与背景网格线同风格(浅灰虚线),略深保证可读 */\nexport const GHOST_BORDER_CSS = '1px dashed rgba(0,0,0,0.18)'\n\n/**\n * 解析单元格某条边的最终 CSS border 值。\n * - 有真实边框(style 非 none)→ 返回 `${width}pt ${style} ${color}`\n * - 设计态且开关开启、且该边无边框 → 返回虚拟虚线(仅设计稿展示,不影响预览/打印)\n * - 其余情况(预览态 / 开关关闭)→ 'none'\n */\nexport function resolveCellBorderCss(\n b: TableCellBorder | undefined,\n opts: { designMode?: boolean; showGhostBorder?: boolean } = {},\n): string {\n if (b && b.style !== 'none') return `${b.width}pt ${b.style} ${b.color}`\n if (opts.designMode && opts.showGhostBorder !== false) return GHOST_BORDER_CSS\n return 'none'\n}\n\n/** 表格元素尺寸派生:options.width/height 恒等于列宽和/行高和(mm),与渲染端一致 */\nexport function syncTableElementSize(options: ElementOptions): void {\n const wMm = (options.tableColWidths ?? []).reduce((s, w) => s + w, 0)\n const hMm = (options.tableRows ?? []).reduce((s, r) => s + r.height, 0)\n options.width = Math.round(wMm * 100) / 100\n options.height = Math.round(hMm * 100) / 100\n}\n","// web/src/components/print/utils/element-factory.ts\nimport type { RuntimeElement, ElementType, ElementOptions } from '../types'\nimport { createDefaultTable } from './table-matrix'\n\nexport function generateId(): string {\n return `el-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`\n}\n\nexport function createDefaultOptions(type: ElementType): ElementOptions {\n // pt → mm:20/50/120/20 → 7/17.6/42.3/7.1\n const base: ElementOptions = { left: 7, top: 17.6, width: 42.3, height: 7.1 }\n\n switch (type) {\n case 'text':\n return { ...base, formatter: '文本', fontSize: 12, textAlign: 'left', height: 5.3 }\n case 'image':\n return { ...base, width: 28.2, height: 28.2, fit: 'contain' }\n case 'longText':\n return { ...base, width: 141.1, height: 28.2, fontSize: 12, lineHeight: 18 }\n case 'table': {\n const { rows, colWidths } = createDefaultTable()\n const totalW = colWidths.reduce((s, w) => s + w, 0)\n const totalH = rows.reduce((s, r) => s + r.height, 0)\n return {\n ...base, width: totalW, height: totalH, // 表格尺寸由列宽/行高(mm)派生,与渲染端一致\n tableMode: 'dynamic',\n tableRows: rows,\n tableColWidths: colWidths,\n tableDefaultFontSize: 10,\n tableDefaultColor: '#333333',\n tableDefaultPadding: 1,\n fields: [],\n tablePagination: { enabled: true },\n }\n }\n case 'hline':\n return { ...base, width: 70.6, height: 1.8, borderWidth: 0.75 }\n case 'vline':\n return { ...base, width: 1.8, height: 35.3, borderWidth: 0.75 }\n case 'rect':\n return { ...base, width: 28.2, height: 28.2, borderWidth: 1, borderColor: '#333' }\n case 'oval':\n return { ...base, width: 28.2, height: 28.2, borderWidth: 1, borderColor: '#333' }\n case 'barcode':\n return { ...base, width: 56.4, height: 14.1, title: '条形码', barcodeType: 'code128', testData: '12345678' }\n case 'qrcode':\n return { ...base, width: 28.2, height: 28.2, title: '二维码', testData: 'qrcode' }\n case 'html':\n return { ...base, width: 28.2, height: 28.2 }\n default:\n return base\n }\n}\n\nexport function createRuntimeElement(type: ElementType, options?: Partial<ElementOptions>): RuntimeElement {\n const typeMetaMap: Record<ElementType, { title: string }> = {\n text: { title: '文本' },\n image: { title: '图片' },\n longText: { title: '长文' },\n table: { title: '表格' },\n hline: { title: '横线' },\n vline: { title: '竖线' },\n rect: { title: '矩形' },\n oval: { title: '椭圆' },\n barcode: { title: '条形码' },\n qrcode: { title: '二维码' },\n html: { title: 'HTML' },\n pageNumber: { title: '页码' },\n }\n\n return {\n id: generateId(),\n options: { ...createDefaultOptions(type), ...options },\n printElementType: { type, title: typeMetaMap[type]?.title || type },\n }\n}\n","// 打印设计器核心自持的表达式引擎单例。\n// 独立于宿主(不依赖 @/utils),便于整体抽离为开源包;扩展函数由 ./expression-eval 注册。\nimport { TemplateEngine } from '@worm-vue3-print/core'\n\nexport const engine = new TemplateEngine()\n","// web/src/components/print/utils/demo-data.ts\n// 采购收货单默认预览 demo 数据: 嵌套结构, 与字段树定义一致\n\nexport function getDemoData(): Record<string, any> {\n return DEFAULT_DEMO_DATA\n}\n\nexport const DEFAULT_DEMO_DATA: Record<string, any> = {\n supplier: {\n name: '鑫达五金有限公司',\n phone: '0571-88776655',\n address: '杭州市萧山区经济开发区88号',\n },\n receiver: {\n name: '李四',\n phone: '13912345678',\n address: '杭州市余杭区文一西路998号',\n },\n order: {\n no: 'PO20260801001',\n date: '2026-08-01',\n total: 69543.75,\n },\n // 50 条商品明细, 用于验证多页分页效果\n goods: [\n { name: '碳钢螺丝 M8', spec: 'M14×10', unit: '个', qty: 100, price: 0.50, amount: 50, remark: 'A级' },\n { name: '不锈钢螺母 M10', spec: 'M16×11', unit: '套', qty: 117, price: 0.75, amount: 87.75, remark: '' },\n { name: '弹簧垫圈 M12', spec: 'M6×12', unit: '盒', qty: 134, price: 1, amount: 134, remark: '' },\n { name: '六角螺栓 M14', spec: 'M5×13', unit: '支', qty: 151, price: 1.25, amount: 188.75, remark: '' },\n { name: '内六角螺钉 M16', spec: 'M20×14', unit: '袋', qty: 168, price: 1.50, amount: 252, remark: '' },\n { name: '平垫圈 M6', spec: 'M4×15', unit: '件', qty: 185, price: 1.75, amount: 323.75, remark: '' },\n { name: '自攻螺钉 M5', spec: 'M3×16', unit: '根', qty: 202, price: 2, amount: 404, remark: '' },\n { name: '双头螺柱 M20', spec: 'M8×17', unit: '包', qty: 219, price: 2.25, amount: 492.75, remark: 'A级' },\n { name: '紧定螺钉 M4', spec: 'M10×18', unit: '只', qty: 236, price: 2.50, amount: 590, remark: '' },\n { name: '十字盘头钉 M3', spec: 'M12×19', unit: '组', qty: 253, price: 2.75, amount: 695.75, remark: '' },\n { name: '碳钢螺丝 M8', spec: 'M14×20', unit: '个', qty: 270, price: 3, amount: 810, remark: '' },\n { name: '不锈钢螺母 M10', spec: 'M16×21', unit: '套', qty: 287, price: 3.25, amount: 932.75, remark: '' },\n { name: '弹簧垫圈 M12', spec: 'M6×22', unit: '盒', qty: 304, price: 3.50, amount: 1064, remark: '' },\n { name: '六角螺栓 M14', spec: 'M5×23', unit: '支', qty: 321, price: 3.75, amount: 1203.75, remark: '' },\n { name: '内六角螺钉 M16', spec: 'M20×24', unit: '袋', qty: 338, price: 4, amount: 1352, remark: 'A级' },\n { name: '平垫圈 M6', spec: 'M4×25', unit: '件', qty: 355, price: 4.25, amount: 1508.75, remark: '' },\n { name: '自攻螺钉 M5', spec: 'M3×26', unit: '根', qty: 372, price: 4.50, amount: 1674, remark: '' },\n { name: '双头螺柱 M20', spec: 'M8×27', unit: '包', qty: 389, price: 4.75, amount: 1847.75, remark: '' },\n { name: '紧定螺钉 M4', spec: 'M10×28', unit: '只', qty: 406, price: 5, amount: 2030, remark: '' },\n { name: '十字盘头钉 M3', spec: 'M12×29', unit: '组', qty: 423, price: 5.25, amount: 2220.75, remark: '' },\n { name: '碳钢螺丝 M8', spec: 'M14×30', unit: '个', qty: 440, price: 0.50, amount: 220, remark: '' },\n { name: '不锈钢螺母 M10', spec: 'M16×31', unit: '套', qty: 457, price: 0.75, amount: 342.75, remark: 'A级' },\n { name: '弹簧垫圈 M12', spec: 'M6×32', unit: '盒', qty: 474, price: 1, amount: 474, remark: '' },\n { name: '六角螺栓 M14', spec: 'M5×33', unit: '支', qty: 491, price: 1.25, amount: 613.75, remark: '' },\n { name: '内六角螺钉 M16', spec: 'M20×34', unit: '袋', qty: 508, price: 1.50, amount: 762, remark: '' },\n { name: '平垫圈 M6', spec: 'M4×35', unit: '件', qty: 525, price: 1.75, amount: 918.75, remark: '' },\n { name: '自攻螺钉 M5', spec: 'M3×36', unit: '根', qty: 542, price: 2, amount: 1084, remark: '' },\n { name: '双头螺柱 M20', spec: 'M8×37', unit: '包', qty: 559, price: 2.25, amount: 1257.75, remark: '' },\n { name: '紧定螺钉 M4', spec: 'M10×38', unit: '只', qty: 576, price: 2.50, amount: 1440, remark: 'A级' },\n { name: '十字盘头钉 M3', spec: 'M12×39', unit: '组', qty: 593, price: 2.75, amount: 1630.75, remark: '' },\n { name: '碳钢螺丝 M8', spec: 'M14×40', unit: '个', qty: 610, price: 3, amount: 1830, remark: '' },\n { name: '不锈钢螺母 M10', spec: 'M16×41', unit: '套', qty: 627, price: 3.25, amount: 2037.75, remark: '' },\n { name: '弹簧垫圈 M12', spec: 'M6×42', unit: '盒', qty: 644, price: 3.50, amount: 2254, remark: '' },\n { name: '六角螺栓 M14', spec: 'M5×43', unit: '支', qty: 661, price: 3.75, amount: 2478.75, remark: '' },\n { name: '内六角螺钉 M16', spec: 'M20×44', unit: '袋', qty: 678, price: 4, amount: 2712, remark: '' },\n { name: '平垫圈 M6', spec: 'M4×45', unit: '件', qty: 695, price: 4.25, amount: 2953.75, remark: 'A级' },\n { name: '自攻螺钉 M5', spec: 'M3×46', unit: '根', qty: 712, price: 4.50, amount: 3204, remark: '' },\n { name: '双头螺柱 M20', spec: 'M8×47', unit: '包', qty: 729, price: 4.75, amount: 3462.75, remark: '' },\n { name: '紧定螺钉 M4', spec: 'M10×48', unit: '只', qty: 746, price: 5, amount: 3730, remark: '' },\n { name: '十字盘头钉 M3', spec: 'M12×49', unit: '组', qty: 763, price: 5.25, amount: 4005.75, remark: '' },\n { name: '碳钢螺丝 M8', spec: 'M14×10', unit: '个', qty: 780, price: 0.50, amount: 390, remark: '' },\n { name: '不锈钢螺母 M10', spec: 'M16×11', unit: '套', qty: 797, price: 0.75, amount: 597.75, remark: '' },\n { name: '弹簧垫圈 M12', spec: 'M6×12', unit: '盒', qty: 814, price: 1, amount: 814, remark: 'A级' },\n { name: '六角螺栓 M14', spec: 'M5×13', unit: '支', qty: 831, price: 1.25, amount: 1038.75, remark: '' },\n { name: '内六角螺钉 M16', spec: 'M20×14', unit: '袋', qty: 848, price: 1.50, amount: 1272, remark: '' },\n { name: '平垫圈 M6', spec: 'M4×15', unit: '件', qty: 865, price: 1.75, amount: 1513.75, remark: '' },\n { name: '自攻螺钉 M5', spec: 'M3×16', unit: '根', qty: 882, price: 2, amount: 1764, remark: '' },\n { name: '双头螺柱 M20', spec: 'M8×17', unit: '包', qty: 899, price: 2.25, amount: 2022.75, remark: '' },\n { name: '紧定螺钉 M4', spec: 'M10×18', unit: '只', qty: 916, price: 2.50, amount: 2290, remark: '' },\n { name: '十字盘头钉 M3', spec: 'M12×19', unit: '组', qty: 933, price: 2.75, amount: 2565.75, remark: 'A级' },\n ],\n}\n","// web/src/components/print/utils/expression-eval.ts\n// 包装共享引擎,保持原有 API 兼容\n\nimport { engine } from './engine'\nimport {\n formatMoney,\n formatDate,\n toUpperCaseAmount,\n ifFn,\n sum,\n avg,\n count,\n min,\n max,\n} from '@worm-vue3-print/core'\n\n// 扩展函数库(保持原有导出)\nexport const EXTENDED_FUNCTIONS = {\n MONEY: formatMoney,\n CONCAT: (...args: any[]) => args.filter(v => v != null).join(''),\n IF: ifFn,\n FORMAT: (value: any) => {\n if (typeof value !== 'number') return String(value)\n return value.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })\n },\n SUBSTR: (str: string, start: number, len?: number) => String(str).slice(start, len ? start + len : undefined),\n LEN: (str: string) => String(str).length,\n ROUND: (num: number, decimals: number) => Number(Number(num).toFixed(decimals)),\n NOW: () => new Date().toISOString().split('T')[0],\n IFEMPTY: (value: any, defaultVal: string) => (value != null && value !== '' ? String(value) : defaultVal),\n PAD: (value: any, len: number, char: string) => String(value).padStart(len, char),\n REPLACE: (str: string, from: string, to: string) => String(str).replace(new RegExp(from, 'g'), to),\n JSON: (value: any) => JSON.stringify(value, null, 2),\n DATE: formatDate,\n UPPER: toUpperCaseAmount,\n} satisfies Record<string, (...args: any[]) => any>\n\n// 注册所有扩展函数到共享引擎\nfor (const [name, fn] of Object.entries(EXTENDED_FUNCTIONS)) {\n engine.registerFunction(name, fn)\n}\n\n// ─── 聚合函数 ───\n\nfunction aggregate(fn: string, field: string, rows: Record<string, any>[]): number {\n switch (fn.toUpperCase()) {\n case 'SUM': return sum(rows, field)\n case 'AVG': return avg(rows, field)\n case 'COUNT': return count(rows, field)\n case 'MIN': return min(rows, field)\n case 'MAX': return max(rows, field)\n default: return 0\n }\n}\n\n/**\n * 在受限沙箱内求值表达式\n * @param expr 表达式字符串\n * @param context 上下文变量\n * @param _callableNames 保留参数,实际使用共享引擎\n */\nexport function safeEval(expr: string, context: Record<string, any>, _callableNames?: string[]): any {\n return engine.evaluate(expr, context)\n}\n\n/**\n * 模板字符串求值:{表达式} 内 safeEval 求值,外为字面文本。\n * 聚合函数 SUM/AVG/COUNT/MIN/MAX(field) 预处理(需 ctx.rows)。\n * 单个 {expr} 求值失败时保留原 {expr} 文本。\n */\nexport function evaluateTemplate(text: string, ctx: Record<string, any>): string {\n if (!text) return ''\n if (!text.includes('{')) return text\n const rows: Record<string, any>[] = Array.isArray(ctx.rows) ? ctx.rows : []\n \n // 预处理聚合函数\n let processedText = text.replace(/\\{([^}]+)\\}/g, (_match, inner) => {\n let expr = inner.trim()\n // 聚合函数预处理:SUM(field) -> 数值字面量\n expr = expr.replace(/\\b(SUM|AVG|COUNT|MIN|MAX)\\(([^)]+)\\)/g, (_m: string, fn: string, arg: string) => {\n const field = arg.trim().replace(/^['\"]|['\"]$/g, '')\n return String(aggregate(fn, field, rows))\n })\n return `{${expr}}`\n })\n \n // 使用共享引擎渲染\n try {\n const result = engine.render(processedText, ctx)\n return result\n } catch {\n // 降级:保留原表达式\n return text\n }\n}\n","// web/src/components/print/utils/binding.ts\nimport type { RuntimeElement } from '../types'\nimport { createRuntimeElement } from './element-factory'\nimport { engine } from './engine'\nimport { DEFAULT_DEMO_DATA } from './demo-data'\nimport './expression-eval'\n\n/** 从业务字段创建带 formatter 绑定的文本元素 */\nexport function createFieldElement(field: { fieldKey: string; fieldLabel: string }): RuntimeElement {\n return createRuntimeElement('text', {\n formatter: `{${field.fieldKey}}`,\n title: field.fieldLabel,\n })\n}\n\n/** 非设计态文本内容解析:用共享引擎渲染 formatter */\nexport function resolveTextBinding(\n options: { formatter?: string },\n data?: Record<string, any>[],\n): string {\n if (options.formatter) {\n if (!data || data.length === 0) return ''\n const row = data[0]\n try {\n return engine.render(options.formatter, row ?? {})\n } catch {\n return options.formatter\n }\n }\n return ''\n}\n\n/** 按路径取 demo 数据值,数组节点取首项 */\nfunction lookupDemoPath(path: string): any {\n let cur: any = DEFAULT_DEMO_DATA\n for (const seg of path.split('.')) {\n if (cur == null) return undefined\n cur = Array.isArray(cur) ? cur[0]?.[seg] : cur[seg]\n }\n return cur\n}\n\n/**\n * 设计态条码/二维码单元格取值:{field} 占位符替换为 demo 数据\n * (列表字段取数据源首项,全局字段按路径取),无匹配回退通用示例码值\n */\nexport function resolveBarcodeDesignValue(\n formatter: string | undefined,\n listSource?: Record<string, any>[],\n): string {\n const first = listSource?.[0]\n const resolved = (formatter ?? '')\n .replace(/\\{([^{}]+)\\}/g, (_, expr: string) => {\n const key = expr.trim()\n const v = key.includes('.')\n ? lookupDemoPath(key)\n : (first?.[key] ?? lookupDemoPath(key))\n return v == null ? '' : String(v)\n })\n .trim()\n return resolved || '1234567890128'\n}\n","// web/src/components/print/utils/units.ts\n\n/** pt 转 mm */\nexport function ptToMm(pt: number): number {\n return pt / 2.83464566929\n}\n\n/** px 转 mm(基于 96dpi 屏幕) */\nexport function pxToMm(px: number): number {\n return px * (25.4 / 96)\n}\n","// web/src/components/print/utils/migrate.ts\n// 存量模板元素坐标 pt → mm 迁移(旧数据无 unit 标记,默认按 pt 处理)\nimport type { TemplateData, PrintElementData } from '../types'\nimport { ptToMm } from './units'\n\nconst PT_KEYS = ['left', 'top', 'width', 'height'] as const\n\nfunction convertElement(el: PrintElementData): PrintElementData {\n const options = { ...el.options }\n for (const key of PT_KEYS) {\n const v = options[key]\n if (typeof v === 'number' && Number.isFinite(v)) {\n ;(options as Record<string, unknown>)[key] = round2(ptToMm(v))\n }\n }\n return { ...el, options }\n}\n\nfunction round2(n: number): number {\n return Math.round(n * 100) / 100\n}\n\nexport function normalizeTemplateUnits(data: TemplateData): TemplateData {\n if (data.unit === 'mm') return data\n const convert = (els?: PrintElementData[]): PrintElementData[] => els?.map(convertElement) ?? []\n return {\n ...data,\n unit: 'mm',\n elements: convert(data.elements),\n header: data.header ? { ...data.header, elements: convert(data.header.elements) } : data.header,\n footer: data.footer ? { ...data.footer, elements: convert(data.footer.elements) } : data.footer,\n firstPageOverlay: data.firstPageOverlay\n ? { ...data.firstPageOverlay, elements: convert(data.firstPageOverlay.elements) }\n : data.firstPageOverlay,\n }\n}\n","// web/src/components/print/utils/default-config.ts\nimport type { TemplateData } from '../types'\n\nexport const PAPER_PRESETS: Record<string, { width: number; height: number }> = {\n A4: { width: 210, height: 297 },\n A3: { width: 297, height: 420 },\n A5: { width: 148, height: 210 },\n Letter: { width: 216, height: 279 },\n Legal: { width: 216, height: 356 },\n}\n\n/**\n * 获取纸张原始宽高(mm,未应用方向)\n * CUSTOM 时读取 customWidth/customHeight,缺省回退 A4\n */\nexport function getPaperDimensions(t: Pick<TemplateData, 'paperSize' | 'orientation' | 'customWidth' | 'customHeight'>): { width: number; height: number } {\n let base: { width: number; height: number }\n if (t.paperSize === 'CUSTOM') {\n base = {\n width: t.customWidth ?? 210,\n height: t.customHeight ?? 297,\n }\n } else {\n base = PAPER_PRESETS[t.paperSize] || PAPER_PRESETS['A4']!\n }\n return t.orientation === 'landscape'\n ? { width: base.height, height: base.width }\n : base\n}\n","// web/src/components/print/utils/scale.ts\n// 缩放计算纯函数\n\n/** 计算适应窗口的缩放百分比,clamp 到 [50,200] */\nexport function computeFitScale(\n containerW: number,\n containerH: number,\n paperW: number,\n paperH: number,\n ratio = 0.9,\n): number {\n if (paperW <= 0 || paperH <= 0) return 100\n const fit = Math.min(containerW / paperW, containerH / paperH) * ratio\n const pct = Math.round(fit * 100)\n return Math.min(200, Math.max(50, pct))\n}\n","// web/src/components/print/utils/zone-layout.ts\n// 页眉/页脚/内容三区几何计算与归区逻辑(区域元素坐标相对区域左上角,mm)\nimport type { RuntimeElement, TemplateData, ElementZone } from '../types'\nimport { getPaperDimensions } from './default-config'\n\n/** 允许放入页眉/页脚的元素类型 */\nexport const ZONE_ALLOWED_TYPES = ['text', 'image', 'hline', 'vline', 'rect', 'oval', 'barcode', 'qrcode']\n\nexport interface ZoneRectPt {\n left: number\n top: number\n width: number\n height: number\n}\n\n/** 纸张宽高(mm,含方向;CUSTOM 读取 customWidth/customHeight,缺省回退 A4) */\nexport function getPaperSizeMM(t: TemplateData): { width: number; height: number } {\n return getPaperDimensions(t)\n}\n\n/** 三区在纸面坐标系中的矩形(mm),布局:上边距→页眉→内容→页脚→下边距 */\nexport function getZoneRects(t: TemplateData): Record<ElementZone, ZoneRectPt> {\n const paper = getPaperSizeMM(t)\n const m = t.margins\n const headerH = t.header.height\n const footerH = t.footer.height\n const contentW = paper.width - m.left - m.right\n const contentH = paper.height - m.top - m.bottom - headerH - footerH\n const rect = (l: number, tp: number, w: number, h: number): ZoneRectPt => ({\n left: l, top: tp, width: w, height: h,\n })\n return {\n header: rect(m.left, m.top, contentW, headerH),\n content: rect(m.left, m.top + headerH, contentW, contentH),\n footer: rect(m.left, paper.height - m.bottom - footerH, contentW, footerH),\n }\n}\n\n/** 纸面 mm 坐标 → 命中区域(高度为 0 的区域不参与命中) */\nexport function zoneFromPaperPoint(t: TemplateData, _x: number, y: number): ElementZone {\n const r = getZoneRects(t)\n if (r.footer.height > 0 && y >= r.footer.top) return 'footer'\n if (r.header.height > 0 && y < r.header.top + r.header.height) return 'header'\n return 'content'\n}\n\n/** 将元素局部坐标 clamp 到区域矩形内(原地修改) */\nexport function clampToZone(el: RuntimeElement, zone: ZoneRectPt): void {\n const o = el.options\n o.width = Math.min(o.width, zone.width)\n o.height = Math.min(o.height, zone.height)\n o.left = Math.min(Math.max(0, o.left), zone.width - o.width)\n o.top = Math.min(Math.max(0, o.top), zone.height - o.height)\n}\n\n/**\n * 拖拽/缩放结束后按元素中心点归区:\n * 跨区时换算坐标并改写 zone;页眉/页脚内 clamp;类型不允许时拒绝跨入并 clamp 回内容区。\n */\nexport function finalizeElementZone(\n el: RuntimeElement,\n t: TemplateData,\n): { rejected: boolean } {\n const rects = getZoneRects(t)\n const fromZone: ElementZone = el.zone || 'content'\n const from = rects[fromZone]\n const cx = from.left + el.options.left + el.options.width / 2\n const cy = from.top + el.options.top + el.options.height / 2\n let target = zoneFromPaperPoint(t, cx, cy)\n let rejected = false\n if (target !== 'content' && !ZONE_ALLOWED_TYPES.includes(el.printElementType.type)) {\n target = 'content'\n rejected = true\n }\n if (target !== fromZone) {\n const to = rects[target]\n el.options.left = from.left + el.options.left - to.left\n el.options.top = from.top + el.options.top - to.top\n el.zone = target\n }\n if (target !== 'content') {\n clampToZone(el, rects[target])\n } else if (rejected) {\n clampToZone(el, rects.content)\n }\n return { rejected }\n}\n","// web/src/components/print/composables/useSelection.ts\nimport { ref, computed, type InjectionKey, type Ref } from 'vue'\nimport type { RuntimeElement } from '../types'\n\n/** 通过 provide/inject 共享选中状态,每个 BaseElement 精确追踪自身是否被选中 */\nexport const SELECTED_IDS_KEY: InjectionKey<Ref<Set<string>>> = Symbol('selected-ids')\n/** 框选实时预选状态:拖拽过程中高亮即将选中的元素,提交后转为正式选中 */\nexport const PREVIEW_IDS_KEY: InjectionKey<Ref<Set<string>>> = Symbol('preview-ids')\n\nexport function useSelection(elements: { value: RuntimeElement[] }) {\n const selectedIds = ref<Set<string>>(new Set())\n // 框选预选:拖拽中实时计算,提交时拷贝进 selectedIds\n const previewIds = ref<Set<string>>(new Set())\n\n const selectedElements = computed(() =>\n elements.value.filter(e => selectedIds.value.has(e.id))\n )\n\n const hasSelection = computed(() => selectedIds.value.size > 0)\n\n function select(id: string, multiple = false) {\n if (multiple) {\n const s = new Set(selectedIds.value)\n if (s.has(id)) { s.delete(id) } else { s.add(id) }\n selectedIds.value = s\n } else {\n selectedIds.value = new Set([id])\n }\n }\n\n function clearSelection() {\n selectedIds.value = new Set()\n }\n\n function selectAll(allIds: string[]) {\n selectedIds.value = new Set(allIds)\n }\n\n /** 设置框选预选集合(拖拽中实时调用) */\n function setPreview(ids: string[]) {\n previewIds.value = new Set(ids)\n }\n /** 清除预选 */\n function clearPreview() {\n previewIds.value = new Set()\n }\n /** 提交预选:将预选集合转为正式选中,并清空预选 */\n function commitPreview() {\n selectedIds.value = new Set(previewIds.value)\n previewIds.value = new Set()\n }\n\n function getSelectionBounds(): { left: number; top: number; width: number; height: number } | null {\n const els = selectedElements.value\n if (els.length === 0) return null\n let minL = Infinity, minT = Infinity, maxR = -Infinity, maxB = -Infinity\n els.forEach(e => {\n minL = Math.min(minL, e.options.left)\n minT = Math.min(minT, e.options.top)\n maxR = Math.max(maxR, e.options.left + e.options.width)\n maxB = Math.max(maxB, e.options.top + e.options.height)\n })\n return { left: minL, top: minT, width: maxR - minL, height: maxB - minT }\n }\n\n return { selectedIds, selectedElements, hasSelection, select, clearSelection, selectAll, getSelectionBounds, previewIds, setPreview, clearPreview, commitPreview }\n}\n","// web/src/components/print/composables/useClipboard.ts\nimport { ref } from 'vue'\nimport type { RuntimeElement, PrintElementData } from '../types'\nimport { generateId } from '../utils/element-factory'\n\nexport function useClipboard() {\n const clipboard = ref<PrintElementData[] | null>(null)\n\n function copy(elements: RuntimeElement[]) {\n clipboard.value = elements.map(e => ({\n options: { ...e.options },\n printElementType: { ...e.printElementType },\n }))\n }\n\n function paste(offset = 10): RuntimeElement[] | null {\n if (!clipboard.value) return null\n return clipboard.value.map(item => ({\n id: generateId(),\n options: {\n ...item.options,\n left: item.options.left + offset,\n top: item.options.top + offset,\n },\n printElementType: { ...item.printElementType },\n }))\n }\n\n function hasData() { return clipboard.value !== null && clipboard.value.length > 0 }\n\n return { clipboard, copy, paste, hasData }\n}\n","// web/src/components/print/composables/useAlign.ts\nimport type { RuntimeElement } from '../types'\n\nexport type AlignMode = 'left' | 'right' | 'top' | 'bottom' | 'vertical' | 'horizontal' | 'distributeHor' | 'distributeVer'\n\nexport function useAlign() {\n function align(elements: RuntimeElement[], mode: AlignMode) {\n if (elements.length < 2) return\n\n const bounds = {\n minLeft: Math.min(...elements.map(e => e.options.left)),\n maxRight: Math.max(...elements.map(e => e.options.left + e.options.width)),\n minTop: Math.min(...elements.map(e => e.options.top)),\n maxBottom: Math.max(...elements.map(e => e.options.top + e.options.height)),\n }\n\n switch (mode) {\n case 'left':\n elements.forEach(e => { e.options.left = bounds.minLeft })\n break\n case 'right':\n elements.forEach(e => { e.options.left = bounds.maxRight - e.options.width })\n break\n case 'top':\n elements.forEach(e => { e.options.top = bounds.minTop })\n break\n case 'bottom':\n elements.forEach(e => { e.options.top = bounds.maxBottom - e.options.height })\n break\n case 'vertical': {\n const centerX = bounds.minLeft + (bounds.maxRight - bounds.minLeft) / 2\n elements.forEach(e => { e.options.left = centerX - e.options.width / 2 })\n break\n }\n case 'horizontal': {\n const centerY = bounds.minTop + (bounds.maxBottom - bounds.minTop) / 2\n elements.forEach(e => { e.options.top = centerY - e.options.height / 2 })\n break\n }\n case 'distributeHor': {\n const sorted = [...elements].sort((a, b) => a.options.left - b.options.left)\n const totalW = sorted.reduce((s, e) => s + e.options.width, 0)\n const gap = (bounds.maxRight - bounds.minLeft - totalW) / (sorted.length - 1)\n let x = bounds.minLeft\n sorted.forEach(e => { e.options.left = x; x += e.options.width + gap })\n break\n }\n case 'distributeVer': {\n const sorted = [...elements].sort((a, b) => a.options.top - b.options.top)\n const totalH = sorted.reduce((s, e) => s + e.options.height, 0)\n const gap = (bounds.maxBottom - bounds.minTop - totalH) / (sorted.length - 1)\n let y = bounds.minTop\n sorted.forEach(e => { e.options.top = y; y += e.options.height + gap })\n break\n }\n }\n }\n\n return { align }\n}\n","// web/src/components/print/composables/useGroup.ts\n// 元素编组/组合逻辑\nimport type { RuntimeElement } from '../types'\n\nexport function generateGroupId(): string {\n return `grp-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`\n}\n\nexport function useGroup() {\n function group(elements: RuntimeElement[], selectedIds: Set<string>): RuntimeElement[] {\n const selected = elements.filter(e => selectedIds.has(e.id))\n if (selected.length < 2) return elements\n\n const groupId = generateGroupId()\n return elements.map(e =>\n selectedIds.has(e.id) ? { ...e, options: { ...e.options, groupId } } : e\n )\n }\n\n function ungroup(elements: RuntimeElement[], selectedIds: Set<string>): RuntimeElement[] {\n const selected = elements.filter(e => selectedIds.has(e.id))\n // 收集选中元素中涉及的 groupId\n const groupIds = new Set(selected.map(e => e.options.groupId).filter(Boolean))\n\n return elements.map(e =>\n e.options.groupId && groupIds.has(e.options.groupId)\n ? { ...e, options: { ...e.options, groupId: undefined } }\n : e\n )\n }\n\n /** 获取与选中元素同组的所有元素 ID */\n function getGroupedIds(elements: RuntimeElement[], selectedId: string): Set<string> {\n const el = elements.find(e => e.id === selectedId)\n if (!el?.options.groupId) return new Set([selectedId])\n\n const ids = new Set<string>()\n for (const e of elements) {\n if (e.options.groupId === el.options.groupId) {\n ids.add(e.id)\n }\n }\n return ids\n }\n\n return { group, ungroup, getGroupedIds }\n}\n","// web/src/components/print/composables/useHistory.ts\nimport { ref } from 'vue'\nimport type { TemplateData } from '../types'\n\nexport interface HistoryState {\n elements: any[]\n templateData?: TemplateData\n}\n\nexport interface UseHistoryOptions {\n /** 历史记录上限,默认 50 步 */\n maxSteps?: number\n /** 是否启用增量快照(减少内存占用),默认 false */\n useIncremental?: boolean\n}\n\n/**\n * 撤销/重做历史管理(操作级快照粒度)。\n *\n * 语义说明:\n * - `push(state)` 记录一次操作后的快照(检查点),并清空 redo 栈。\n * - `undo(currentState?)` 弹出栈顶检查点(当前状态)压入 redo 栈,\n * 返回新的栈顶(即上一个待恢复状态);栈空时返回 null。\n * - `redo(currentState?)` 弹出 redo 栈顶(待重做状态)压回 undo 栈并返回。\n * - 所有快照均做 JSON 深拷贝,避免外部对象突变污染历史。\n *\n * 调用约定:若希望\"撤销到初始状态\",应在首次操作前先 `push(initialState)`。\n */\nexport function useHistory(options?: UseHistoryOptions) {\n const maxSteps = options?.maxSteps ?? 50\n const useIncremental = options?.useIncremental ?? false\n const undoStack = ref<HistoryState[]>([])\n const redoStack = ref<HistoryState[]>([])\n\n const canUndo = ref(false)\n const canRedo = ref(false)\n\n function updateFlags() {\n canUndo.value = undoStack.value.length > 0\n canRedo.value = redoStack.value.length > 0\n }\n\n /** 深拷贝快照,避免外部对象突变污染历史 */\n function clone(state: HistoryState | undefined): HistoryState {\n return {\n elements: JSON.parse(JSON.stringify(state?.elements ?? [])),\n templateData: JSON.parse(JSON.stringify(state?.templateData ?? {})),\n }\n }\n\n /** 增量快照:只记录元素变更,templateData 只记录非 elements 部分 */\n function cloneIncremental(state: HistoryState): HistoryState {\n const clonedElements = JSON.parse(JSON.stringify(state.elements))\n const td = state.templateData\n if (!td) return { elements: clonedElements }\n return {\n elements: clonedElements,\n templateData: {\n paperSize: td.paperSize,\n orientation: td.orientation,\n margins: { ...td.margins },\n header: { height: td.header.height, elements: [] },\n footer: { height: td.footer.height, elements: [] },\n firstPageOverlay: { height: td.firstPageOverlay.height, elements: [] },\n elements: [], // 元素已在顶层存储\n customWidth: td.customWidth,\n customHeight: td.customHeight,\n watermark: td.watermark ? { ...td.watermark } : undefined,\n guides: td.guides ? [...td.guides] : undefined,\n },\n }\n }\n\n function cloneState(state: HistoryState): HistoryState {\n return useIncremental ? cloneIncremental(state) : clone(state)\n }\n\n /** 记录操作后快照(深拷贝),并清空 redo 栈 */\n function push(state: HistoryState) {\n undoStack.value.push(cloneState(state))\n // 新操作清空 redo 栈\n redoStack.value = []\n // 超出上限丢弃最早\n if (undoStack.value.length > maxSteps) {\n undoStack.value.shift()\n }\n updateFlags()\n }\n\n /**\n * 撤销:弹出当前栈顶检查点(压入 redo 栈),返回上一个待恢复状态。\n * @param currentState 可选,若提供则用其替代弹出的检查点压入 redo 栈\n * (显式传入当前实时状态时使用)\n */\n function undo(currentState?: HistoryState): HistoryState | null {\n if (undoStack.value.length === 0) return null\n const popped = undoStack.value.pop()!\n redoStack.value.push(currentState ? cloneState(currentState) : clone(popped))\n updateFlags()\n // 返回新的栈顶(上一个待恢复状态);栈空表示无更早历史\n return undoStack.value.length > 0\n ? clone(undoStack.value[undoStack.value.length - 1])\n : null\n }\n\n /**\n * 重做:弹出 redo 栈顶(待重做状态)压回 undo 栈并返回。\n * @param currentState 可选,若提供则用其替代弹出的状态压回 undo 栈\n */\n function redo(currentState?: HistoryState): HistoryState | null {\n if (redoStack.value.length === 0) return null\n const popped = redoStack.value.pop()!\n undoStack.value.push(currentState ? cloneState(currentState) : clone(popped))\n updateFlags()\n return clone(popped)\n }\n\n /** 清空全部历史 */\n function clear() {\n undoStack.value = []\n redoStack.value = []\n updateFlags()\n }\n\n return { push, undo, redo, canUndo, canRedo, clear }\n}\n","// web/src/components/print/composables/useKeyboard.ts\n\nexport interface KeyboardHandlers {\n onMove?: (dx: number, dy: number) => void\n onDelete?: () => void\n onCopy?: () => void\n onPaste?: () => void\n onSelectAll?: () => void\n onUndo?: () => void\n onRedo?: () => void\n onDuplicate?: () => void\n onResetZoom?: () => void\n onAlignLeft?: () => void\n onAlignRight?: () => void\n onAlignCenterH?: () => void\n onAlignTop?: () => void\n onAlignBottom?: () => void\n onGroup?: () => void\n onUngroup?: () => void\n}\n\nconst STEP = 1 // mm\nconst STEP_LARGE = 10\nconst STEP_SMALL = 0.5\n\nexport function useKeyboard(handlers: KeyboardHandlers) {\n function onKeyDown(e: KeyboardEvent) {\n const tag = (e.target as HTMLElement).tagName\n if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT') return\n\n const ctrl = e.ctrlKey || e.metaKey\n\n // 方向键:Shift=大步,Ctrl=微步,默认标准步\n if (e.key.startsWith('Arrow')) {\n e.preventDefault()\n const step = e.shiftKey ? STEP_LARGE : e.ctrlKey ? STEP_SMALL : STEP\n const dx = e.key === 'ArrowLeft' ? -step : e.key === 'ArrowRight' ? step : 0\n const dy = e.key === 'ArrowUp' ? -step : e.key === 'ArrowDown' ? step : 0\n handlers.onMove?.(dx, dy)\n return\n }\n\n if (e.key === 'Delete' || e.key === 'Backspace') {\n e.preventDefault()\n handlers.onDelete?.()\n return\n }\n\n // Ctrl+0 适应窗口需容器尺寸,由 PrintDesigner 单独监听,此处不处理\n if (ctrl) {\n const k = e.key.toLowerCase()\n if (k === 'c') { e.preventDefault(); handlers.onCopy?.() }\n else if (k === 'v') { e.preventDefault(); handlers.onPaste?.() }\n else if (k === 'a') { e.preventDefault(); handlers.onSelectAll?.() }\n else if (k === 'd') { e.preventDefault(); handlers.onDuplicate?.() }\n else if (k === 'z') { e.preventDefault(); e.shiftKey ? handlers.onRedo?.() : handlers.onUndo?.() }\n else if (k === 'y') { e.preventDefault(); handlers.onRedo?.() }\n else if (k === '1') { e.preventDefault(); handlers.onResetZoom?.() }\n else if (k === 'l') { e.preventDefault(); handlers.onAlignLeft?.() }\n else if (k === 'r') { e.preventDefault(); handlers.onAlignRight?.() }\n else if (k === 'e') { e.preventDefault(); handlers.onAlignCenterH?.() }\n else if (k === 't') { e.preventDefault(); handlers.onAlignTop?.() }\n else if (k === 'b') { e.preventDefault(); handlers.onAlignBottom?.() }\n else if (k === 'g') { e.preventDefault(); e.shiftKey ? handlers.onUngroup?.() : handlers.onGroup?.() }\n }\n }\n\n function setup() { document.addEventListener('keydown', onKeyDown) }\n function cleanup() { document.removeEventListener('keydown', onKeyDown) }\n\n return { setup, cleanup }\n}\n","// web/src/components/print/composables/useDesignerState.ts\n// 设计器核心状态管理:模板数据/选择/历史/剪贴板/编组/键盘/序列化\nimport { ref, computed, onMounted, onUnmounted } from 'vue'\nimport type {\n RuntimeElement, ElementType, ElementZone, PrintBusinessField, TemplateData,\n TableSelection, PrintElementData,\n} from '../types'\nimport { createRuntimeElement, generateId } from '../utils/element-factory'\nimport { createFieldElement } from '../utils/binding'\nimport { normalizeTemplateUnits } from '../utils/migrate'\nimport { syncTableElementSize } from '../utils/table-matrix'\nimport { getPaperDimensions } from '../utils/default-config'\nimport { computeFitScale } from '../utils/scale'\nimport {\n getZoneRects, zoneFromPaperPoint, clampToZone, finalizeElementZone, ZONE_ALLOWED_TYPES,\n} from '../utils/zone-layout'\nimport { useSelection } from './useSelection'\nimport { useClipboard } from './useClipboard'\nimport { useAlign, type AlignMode } from './useAlign'\nimport { useGroup } from './useGroup'\nimport { useHistory, type HistoryState } from './useHistory'\nimport { useKeyboard } from './useKeyboard'\n\nexport interface DesignerStateOptions {\n initialTemplate?: TemplateData\n initialElements?: RuntimeElement[]\n initialFields?: PrintBusinessField[]\n}\n\n/** 创建默认模板数据 */\nexport function createDefaultTemplate(): TemplateData {\n return {\n paperSize: 'A4',\n orientation: 'portrait',\n unit: 'mm',\n margins: { top: 10, right: 10, bottom: 10, left: 10 },\n header: { height: 10, elements: [] },\n footer: { height: 10, elements: [] },\n firstPageOverlay: { height: 0, elements: [] },\n elements: [],\n watermark: {},\n }\n}\n\n/** 三区元素合并为统一运行时元素池(补建 id、打 zone 标) */\nexport function toRuntimePool(data: TemplateData): TemplateData {\n const mk = (els: PrintElementData[], zone: ElementZone): RuntimeElement[] =>\n (els ?? []).map(e => {\n const options = { ...e.options }\n // 表格尺寸恒由列宽/行高派生(mm),加载时重算以自愈历史污染数据\n if ((e.printElementType?.type ?? e.type) === 'table') {\n syncTableElementSize(options)\n }\n return {\n id: e.id || generateId(),\n zone,\n options,\n printElementType: { ...e.printElementType },\n }\n })\n return {\n ...data,\n margins: { ...data.margins },\n header: { height: data.header?.height ?? 10, elements: [] },\n footer: { height: data.footer?.height ?? 10, elements: [] },\n firstPageOverlay: {\n height: data.firstPageOverlay?.height ?? 0,\n elements: [...(data.firstPageOverlay?.elements ?? [])],\n },\n guides: [...(data.guides ?? [])],\n elements: [\n ...mk(data.elements ?? [], 'content'),\n ...mk(data.header?.elements ?? [], 'header'),\n ...mk(data.footer?.elements ?? [], 'footer'),\n ],\n }\n}\n\nexport function useDesignerState(options: DesignerStateOptions = {}) {\n const scale = ref(100)\n const showGrid = ref(true)\n const snapToGrid = ref(false)\n // 设计态下无边框表格单元格的虚拟虚线边框开关(默认开启)\n const showTableGhostBorder = ref(true)\n\n // 单一模板状态(三区元素归一化进运行时元素池)\n const templateData = ref<TemplateData>(\n toRuntimePool(options.initialTemplate || createDefaultTemplate())\n )\n\n // 内容区主体元素(快捷访问)\n // 优化:setter 直接修改 elements 属性,避免展开替换整个 templateData 触发全量通知\n const elements = computed({\n get: () => templateData.value.elements as RuntimeElement[],\n set: (els: RuntimeElement[]) => {\n templateData.value.elements = els\n },\n })\n\n const fields = ref<PrintBusinessField[]>(options.initialFields || [])\n\n const { selectedIds, selectedElements, select, clearSelection, selectAll: selectAllIds, previewIds, setPreview, clearPreview, commitPreview } = useSelection(elements)\n\n // 编组\n const { group: groupElements, ungroup: ungroupElements } = useGroup()\n\n // 复制粘贴 / 对齐 / 撤销重做\n const { copy: copyElements, paste: pasteElements, hasData: hasClipboardData } = useClipboard()\n const { align } = useAlign()\n const { push: pushHistory, undo: undoHistory, redo: redoHistory, canUndo, canRedo } = useHistory()\n\n const selectedElement = computed(() => {\n if (selectedIds.value.size === 0) return null\n const id = selectedIds.value.values().next().value\n return elements.value.find(e => e.id === id) || null\n })\n\n // 表格单元格选区(Excel 风格表格编辑)\n const tableSelection = ref<TableSelection | null>(null)\n function setTableSelection(s: TableSelection | null) {\n tableSelection.value = s\n }\n\n /** 当前设计器状态的深拷贝快照(用于历史记录) */\n function getHistoryState(): HistoryState {\n return {\n elements: elements.value.map(e => ({\n id: e.id,\n zone: e.zone,\n // JSON 深拷贝:tableRows 等嵌套结构若浅拷会在撤销时共享引用\n options: JSON.parse(JSON.stringify(e.options)),\n printElementType: { ...e.printElementType },\n })),\n templateData: {\n paperSize: templateData.value.paperSize,\n orientation: templateData.value.orientation,\n margins: { ...templateData.value.margins },\n header: { height: templateData.value.header.height, elements: [] },\n footer: { height: templateData.value.footer.height, elements: [] },\n firstPageOverlay: { height: templateData.value.firstPageOverlay.height, elements: [] },\n elements: [], // 元素已在顶层存储,避免重复\n customWidth: templateData.value.customWidth,\n customHeight: templateData.value.customHeight,\n watermark: templateData.value.watermark ? { ...templateData.value.watermark } : undefined,\n guides: [...(templateData.value.guides ?? [])],\n },\n }\n }\n\n function recordHistory() {\n pushHistory(getHistoryState())\n }\n\n function undo() {\n const state = undoHistory(getHistoryState())\n if (state?.templateData) {\n templateData.value = { ...state.templateData, elements: state.elements }\n }\n }\n\n function redo() {\n const state = redoHistory(getHistoryState())\n if (state?.templateData) {\n templateData.value = { ...state.templateData, elements: state.elements }\n }\n }\n\n function copy() {\n copyElements(selectedElements.value)\n }\n\n /** 剪切:复制到剪贴板后删除选中元素 */\n function cutSelected() {\n copyElements(selectedElements.value)\n deleteSelected()\n }\n\n function paste() {\n const pasted = pasteElements()\n if (pasted && pasted.length > 0) {\n elements.value.push(...pasted)\n recordHistory()\n }\n }\n\n /** Ctrl+D 原地复制:复用剪贴板克隆选中元素,叠加小幅偏移 */\n function duplicateSelected() {\n copyElements(selectedElements.value)\n const pasted = pasteElements()\n if (pasted && pasted.length > 0) {\n pasted.forEach(e => { e.options.left += 5; e.options.top += 5 })\n elements.value.push(...pasted)\n select(pasted[0]!.id, false)\n recordHistory()\n }\n }\n\n /** Ctrl+1 重置缩放至 100% */\n function resetZoom() {\n scale.value = 100\n }\n\n const hasClipboard = computed(() => hasClipboardData())\n\n let moveSessionActive = false\n let moveDebounceTimer: ReturnType<typeof setTimeout> | null = null\n const MOVE_SESSION_GAP_MS = 300\n\n function moveSelected(dx: number, dy: number) {\n const movable = selectedElements.value.filter(e => !e.options.locked)\n if (movable.length === 0) return\n movable.forEach(e => {\n e.options.left += dx\n e.options.top += dy\n })\n if (!moveSessionActive) {\n moveSessionActive = true\n recordHistory()\n }\n if (moveDebounceTimer) clearTimeout(moveDebounceTimer)\n moveDebounceTimer = setTimeout(() => {\n moveSessionActive = false\n moveDebounceTimer = null\n }, MOVE_SESSION_GAP_MS)\n }\n\n function selectAll() {\n selectAllIds(elements.value.map(e => e.id))\n }\n\n function alignSelected(mode: AlignMode) {\n align(selectedElements.value, mode)\n recordHistory()\n }\n\n function groupSelected() {\n elements.value = groupElements(elements.value, selectedIds.value)\n recordHistory()\n }\n\n function ungroupSelected() {\n elements.value = ungroupElements(elements.value, selectedIds.value)\n recordHistory()\n }\n\n function deleteSelected() {\n if (selectedIds.value.size === 0) return\n elements.value = elements.value.filter(e => !selectedIds.value.has(e.id))\n clearSelection()\n recordHistory()\n }\n\n // 键盘快捷键\n const { setup: setupKeyboard, cleanup: cleanupKeyboard } = useKeyboard({\n onMove: moveSelected,\n onDelete: deleteSelected,\n onCopy: copy,\n onPaste: paste,\n onSelectAll: selectAll,\n onUndo: undo,\n onRedo: redo,\n onDuplicate: duplicateSelected,\n onResetZoom: resetZoom,\n // 多选对齐快捷键:Ctrl+L 左对齐 / Ctrl+R 右对齐 / Ctrl+E 水平居中 / Ctrl+T 顶对齐 / Ctrl+B 底对齐\n onAlignLeft: () => alignSelected('left'),\n onAlignRight: () => alignSelected('right'),\n onAlignCenterH: () => alignSelected('vertical'),\n onAlignTop: () => alignSelected('top'),\n onAlignBottom: () => alignSelected('bottom'),\n // 编组快捷键:Ctrl+G 组合 / Ctrl+Shift+G 取消组合\n onGroup: groupSelected,\n onUngroup: ungroupSelected,\n })\n\n let draggingBeforeState: HistoryState | null = null\n\n function dragStart() {\n draggingBeforeState = getHistoryState()\n }\n\n function dragStop() {\n if (!draggingBeforeState) return\n // 拖拽/缩放结束:对位置或尺寸变化的元素做归区收尾(跨区换算 + 区域 clamp)\n const before = new Map(draggingBeforeState.elements.map(e => [e.id, e]))\n let rejected = false\n for (const el of elements.value) {\n const prev = before.get(el.id)\n if (!prev) continue\n const moved = prev.options.left !== el.options.left\n || prev.options.top !== el.options.top\n || prev.options.width !== el.options.width\n || prev.options.height !== el.options.height\n if (moved && finalizeElementZone(el, templateData.value).rejected) {\n rejected = true\n }\n }\n if (rejected) {\n alert('该元素类型不能放入页眉/页脚')\n }\n const sig = (e: RuntimeElement) =>\n `${e.id}:${e.zone || 'content'}:${e.options.left},${e.options.top},${e.options.width},${e.options.height}`\n const beforeIds = draggingBeforeState.elements.map(sig).join('|')\n const afterIds = getHistoryState().elements.map(sig).join('|')\n draggingBeforeState = null\n if (beforeIds !== afterIds) {\n recordHistory()\n }\n }\n\n /** 按落点将新元素放入对应区域;页眉/页脚不允许的类型拒绝并提示 */\n function placeAtDropPoint(el: RuntimeElement, dropPoint: { x: number; y: number }): boolean {\n // dropPoint 为 mm(由 CanvasArea.toPaperPoint 返回)\n const zone = zoneFromPaperPoint(templateData.value, dropPoint.x, dropPoint.y)\n if (zone !== 'content' && !ZONE_ALLOWED_TYPES.includes(el.printElementType.type)) {\n alert('该元素类型不能放入页眉/页脚')\n return false\n }\n const rect = getZoneRects(templateData.value)[zone] // mm\n el.zone = zone\n // 元素 options 以 mm 存储:落点相对区域左上角的偏移即 mm 坐标\n el.options.left = dropPoint.x - rect.left\n el.options.top = dropPoint.y - rect.top\n if (zone !== 'content') {\n clampToZone(el, rect)\n }\n return true\n }\n\n function addElement(type: string, dropPoint?: { x: number; y: number }) {\n const el = createRuntimeElement(type as ElementType)\n if (dropPoint && !placeAtDropPoint(el, dropPoint)) return\n elements.value.push(el)\n select(el.id, false)\n recordHistory()\n }\n\n function addFieldElement(field: { fieldKey: string; fieldLabel: string }, dropPoint?: { x: number; y: number }) {\n const el = createFieldElement(field)\n if (dropPoint && !placeAtDropPoint(el, dropPoint)) return\n elements.value.push(el)\n select(el.id, false)\n recordHistory()\n }\n\n function moveLayer(direction: string) {\n if (selectedIds.value.size === 0) return\n const id = selectedIds.value.values().next().value\n const el = elements.value.find(e => e.id === id)\n if (!el) return\n const currentZ = el.options.zIndex ?? 0\n const allZ = elements.value.map(e => e.options.zIndex ?? 0)\n const maxZ = Math.max(...allZ, 0)\n const minZ = Math.min(...allZ, 0)\n switch (direction) {\n case 'top': el.options.zIndex = maxZ + 1; break\n case 'bottom': el.options.zIndex = minZ - 1; break\n case 'up': el.options.zIndex = currentZ + 1; break\n case 'down': el.options.zIndex = currentZ - 1; break\n }\n recordHistory()\n }\n\n /** 适应窗口:根据容器尺寸(px)与纸张尺寸(mm->px)计算缩放 */\n function fitToWindow(containerW: number, containerH: number) {\n const { width, height } = getPaperDimensions(templateData.value)\n const MM_TO_PX = 96 / 25.4\n scale.value = computeFitScale(containerW, containerH, width * MM_TO_PX, height * MM_TO_PX)\n }\n\n function updateTemplateData(data: TemplateData) {\n templateData.value = { ...data }\n recordHistory()\n }\n\n /** 当前设计器状态序列化为模板 JSON(单一出口,按 zone 拆回三区,保留 id/type 供渲染服务使用) */\n function getTemplateJson(): TemplateData {\n const all = elements.value\n const ser = (zone: ElementZone) => all\n .filter(e => (e.zone || 'content') === zone)\n .map(e => ({\n id: e.id,\n type: e.printElementType.type,\n options: { ...e.options },\n printElementType: { ...e.printElementType },\n }))\n return {\n unit: 'mm' as const,\n ...templateData.value,\n header: { ...templateData.value.header, elements: ser('header') },\n footer: { ...templateData.value.footer, elements: ser('footer') },\n // 首页叠加层也需补 id/type\n firstPageOverlay: {\n ...templateData.value.firstPageOverlay,\n elements: templateData.value.firstPageOverlay.elements.map(e => ({\n id: e.id || generateId(),\n type: e.printElementType?.type || 'text',\n options: { ...e.options },\n printElementType: { ...e.printElementType },\n })),\n },\n elements: ser('content'),\n guides: [...(templateData.value.guides ?? [])],\n }\n }\n\n /** 加载模板数据(三区合并进运行时元素池;旧数据按 pt 迁移为 mm) */\n function loadTemplate(data: TemplateData, els?: RuntimeElement[]) {\n const migrated = normalizeTemplateUnits(data)\n templateData.value = toRuntimePool(migrated)\n if (els) {\n templateData.value = {\n ...templateData.value,\n elements: els.map(e => ({\n ...e,\n id: e.id || generateId(),\n zone: e.zone || 'content',\n options: { ...e.options },\n printElementType: { ...e.printElementType },\n })),\n }\n }\n pushHistory(getHistoryState())\n }\n\n // 记录设计器初始状态快照\n pushHistory(getHistoryState())\n\n onMounted(() => setupKeyboard())\n onUnmounted(() => {\n cleanupKeyboard()\n if (moveDebounceTimer) {\n clearTimeout(moveDebounceTimer)\n moveDebounceTimer = null\n }\n })\n\n return {\n scale, showGrid, snapToGrid, showTableGhostBorder,\n templateData, elements, fields,\n selectedIds, selectedElements, selectedElement, select, clearSelection, selectAll,\n previewIds, setPreview, clearPreview, commitPreview,\n hasClipboard, copy, paste, cutSelected,\n tableSelection, setTableSelection,\n canUndo, canRedo, undo, redo,\n recordHistory,\n alignSelected, groupSelected, ungroupSelected, deleteSelected,\n duplicateSelected, resetZoom,\n dragStart, dragStop,\n addElement, addFieldElement, moveLayer, fitToWindow, updateTemplateData,\n getTemplateJson, loadTemplate,\n }\n}\n","// web/src/components/print/composables/useGuides.ts\n// 手动参考线管理:增删改 + 吸附目标生成,增删改入历史栈\nimport { computed, type Ref } from 'vue'\nimport type { TemplateData, AlignLine } from '../types'\n\nlet guideSeq = 0\nfunction genId(): string {\n guideSeq += 1\n return `guide-${guideSeq}`\n}\n\nexport function useGuides(templateData: Ref<TemplateData>, recordHistory: () => void) {\n const guides = computed(() => templateData.value.guides ?? [])\n\n function mutate(fn: (list: AlignLine[]) => AlignLine[]) {\n templateData.value = {\n ...templateData.value,\n guides: fn([...(templateData.value.guides ?? [])]),\n }\n recordHistory()\n }\n\n function addGuide(type: 'vertical' | 'horizontal', position: number) {\n mutate(list => { list.push({ type, position, id: genId() }); return list })\n }\n function moveGuide(id: string, position: number) {\n mutate(list => list.map(g => g.id === id ? { ...g, position } : g))\n }\n function removeGuide(id: string) {\n mutate(list => list.filter(g => g.id !== id))\n }\n function getGuidePositions(): { vertical: number[]; horizontal: number[] } {\n const v: number[] = [], h: number[] = []\n for (const g of guides.value) {\n if (g.type === 'vertical') v.push(g.position)\n else h.push(g.position)\n }\n return { vertical: v, horizontal: h }\n }\n\n return { guides, addGuide, moveGuide, removeGuide, getGuidePositions }\n}\n","// 表格单元格选区跨组件共享契约:PrintDesigner provide,TableElement/PropertyPanel inject\nimport type { InjectionKey, Ref } from 'vue'\nimport type { TableSelection } from '../types'\n\nexport interface TableEditContext {\n tableSelection: Ref<TableSelection | null>\n setTableSelection: (s: TableSelection | null) => void\n recordHistory: () => void\n /** 页面打印范围宽度(mm)= 纸宽 - 左右边距,表格总列宽不得超过 */\n maxTableWidth: Ref<number>\n}\n\nexport const TABLE_EDIT_KEY: InjectionKey<TableEditContext> = Symbol('table-edit')\n","// 宿主能力注入键:开源核心不直接发请求、不内置业务字典,相关能力/数据由\n// PrintDesigner 经 props 接收后 provide,深层组件通过 inject 获取。\nimport type { ComputedRef, InjectionKey } from 'vue'\nimport type { UploadImageFn } from '../types'\n\n/** 图片上传适配器:PrintDesigner provide,ImageContentUpload inject */\nexport const UPLOAD_IMAGE_KEY: InjectionKey<ComputedRef<UploadImageFn | undefined>> =\n Symbol('print-upload-image')\n","<template>\n <div class=\"designer-toolbar\">\n <!-- 文件 -->\n <div class=\"tb-group\">\n <button class=\"tb-btn tb-icon\" title=\"返回\" @click=\"$emit('back')\">←</button>\n <span class=\"tb-mark\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <rect x=\"5\" y=\"3\" width=\"14\" height=\"18\" rx=\"2.5\" />\n <line x1=\"8.5\" y1=\"8.5\" x2=\"15.5\" y2=\"8.5\" />\n <line x1=\"8.5\" y1=\"12.5\" x2=\"15.5\" y2=\"12.5\" />\n <line x1=\"8.5\" y1=\"16.5\" x2=\"12.5\" y2=\"16.5\" />\n </svg>\n </span>\n <div class=\"tb-title\">\n <span class=\"tb-title-name\">{{ isEdit ? '编辑模板' : '新建模板' }}</span>\n <span class=\"tb-title-sub\">印刷工作台</span>\n </div>\n </div>\n <!-- 编辑 -->\n <div class=\"tb-group\">\n <button class=\"tb-btn tb-icon\" :disabled=\"!canUndo\" @click=\"$emit('undo')\" title=\"撤销\">↶</button>\n <button class=\"tb-btn tb-icon\" :disabled=\"!canRedo\" @click=\"$emit('redo')\" title=\"重做\">↷</button>\n </div>\n <!-- 对齐分布(多选) -->\n <div class=\"tb-group\" v-if=\"hasMultiSelection\">\n <button class=\"tb-btn tb-icon\" @click=\"$emit('align', 'left')\" title=\"左对齐\">⇤</button>\n <button class=\"tb-btn tb-icon\" @click=\"$emit('align', 'right')\" title=\"右对齐\">⇥</button>\n <button class=\"tb-btn tb-icon\" @click=\"$emit('align', 'top')\" title=\"顶对齐\">⇡</button>\n <button class=\"tb-btn tb-icon\" @click=\"$emit('align', 'bottom')\" title=\"底对齐\">⇣</button>\n <button class=\"tb-btn tb-icon\" @click=\"$emit('align', 'vertical')\" title=\"水平居中\">↔</button>\n <button class=\"tb-btn tb-icon\" @click=\"$emit('align', 'horizontal')\" title=\"垂直居中\">↕</button>\n <button class=\"tb-btn tb-icon\" @click=\"$emit('align', 'distributeHor')\" title=\"水平分布\">⇔</button>\n <button class=\"tb-btn tb-icon\" @click=\"$emit('align', 'distributeVer')\" title=\"垂直分布\">⇕</button>\n </div>\n <!-- 组合 -->\n <div class=\"tb-group\" v-if=\"hasMultiSelection\">\n <button class=\"tb-btn\" @click=\"$emit('group')\" title=\"组合\">组合</button>\n </div>\n <div class=\"tb-group\" v-if=\"!hasMultiSelection && selectedElementHasGroup\">\n <button class=\"tb-btn\" @click=\"$emit('ungroup')\" title=\"取消组合\">取消组合</button>\n </div>\n <!-- 层级 -->\n <div class=\"tb-group\" v-if=\"hasSelection\">\n <button class=\"tb-btn tb-icon\" @click=\"$emit('move-layer', 'top')\" title=\"置顶\">⤒</button>\n <button class=\"tb-btn tb-icon\" @click=\"$emit('move-layer', 'up')\" title=\"上移\">↑</button>\n <button class=\"tb-btn tb-icon\" @click=\"$emit('move-layer', 'down')\" title=\"下移\">↓</button>\n <button class=\"tb-btn tb-icon\" @click=\"$emit('move-layer', 'bottom')\" title=\"置底\">⤓</button>\n </div>\n <!-- 视图 -->\n <div class=\"tb-group\">\n <button class=\"tb-btn\" :class=\"{ on: showGrid }\" @click=\"$emit('toggle-grid')\">\n <span class=\"dot\" /> 网格\n </button>\n <button class=\"tb-btn\" :class=\"{ on: showTableGhostBorder }\" title=\"显示/隐藏无边框表格的虚拟虚线\" @click=\"$emit('toggle-table-ghost-border')\">\n <span class=\"dot\" /> 虚框\n </button>\n <button class=\"tb-btn\" :class=\"{ on: snapToGrid }\" @click=\"$emit('toggle-snap')\">\n <span class=\"dot\" /> 吸附\n </button>\n <button class=\"tb-btn tb-icon\" @click=\"$emit('fit-window')\" title=\"适应窗口\">⤢</button>\n <button class=\"tb-btn tb-icon\" @click=\"$emit('zoom', -10)\" title=\"缩小\">−</button>\n <span class=\"tb-zoom\">{{ scale }}%</span>\n <button class=\"tb-btn tb-icon\" @click=\"$emit('zoom', 10)\" title=\"放大\">+</button>\n </div>\n <!-- 操作 -->\n <div class=\"tb-spacer\" />\n <div class=\"tb-group\">\n <button class=\"tb-btn\" @click=\"$emit('add-overlay-element')\">首页专属</button>\n <button class=\"tb-btn\" :class=\"{ warn: overlayVisible }\" @click=\"$emit('toggle-overlay')\">叠层对比</button>\n </div>\n <div class=\"tb-group\">\n <button v-if=\"showLoadDefault\" class=\"btn-secondary\" @click=\"$emit('load-default')\">加载默认布局</button>\n <button class=\"btn-secondary\" @click=\"$emit('preview')\">预览</button>\n <button class=\"btn-primary\" @click=\"$emit('save')\">保存</button>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nconst scale = defineModel<number>('scale', { default: 100 })\n\ndefineProps<{\n isEdit?: boolean\n canUndo?: boolean\n canRedo?: boolean\n hasMultiSelection?: boolean\n hasSelection?: boolean\n showGrid?: boolean\n snapToGrid?: boolean\n showTableGhostBorder?: boolean\n selectedElementHasGroup?: boolean\n overlayVisible?: boolean\n /** 是否展示「加载默认布局」按钮(宿主注入 loadDefaultTemplate 时由 PrintDesigner 开启) */\n showLoadDefault?: boolean\n}>()\n\ndefineEmits<{\n back: []\n preview: []\n save: []\n 'load-default': []\n undo: []\n redo: []\n align: [mode: string]\n 'move-layer': [direction: string]\n 'toggle-grid': []\n 'toggle-snap': []\n 'toggle-table-ghost-border': []\n 'toggle-overlay': []\n group: []\n ungroup: []\n 'add-overlay-element': []\n 'fit-window': []\n zoom: [delta: number]\n}>()\n</script>\n\n<style scoped>\n.designer-toolbar {\n display: flex;\n align-items: center;\n gap: 2px;\n padding: 0 12px;\n height: 50px;\n background: var(--pd-surface, #ffffff);\n border-bottom: 1px solid var(--pd-border-soft, #e9ecf2);\n box-shadow: 0 1px 2px rgba(23, 32, 60, .04), 0 6px 16px -12px rgba(23, 32, 60, .25);\n flex-shrink: 0;\n position: relative;\n z-index: 20;\n}\n.tb-group {\n display: flex;\n align-items: center;\n gap: 2px;\n padding: 0 8px;\n}\n.tb-group + .tb-group {\n border-left: 1px solid var(--pd-border-soft, #e9ecf2);\n}\n.tb-btn {\n height: 30px;\n min-width: 30px;\n padding: 0 8px;\n border-radius: 6px;\n border: 1px solid transparent;\n background: transparent;\n color: var(--pd-text-muted, #8b909c);\n font-size: 12px;\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 5px;\n transition: background .14s ease, color .14s ease, border-color .14s ease, box-shadow .14s ease;\n}\n.tb-btn:hover {\n color: var(--pd-text, #2a2e37);\n background: var(--pd-sidebar-hover, #f0f3f9);\n}\n.tb-btn:active {\n background: var(--pd-border-soft, #e9ecf2);\n}\n.tb-btn:disabled {\n opacity: .32;\n cursor: default;\n background: transparent;\n color: var(--pd-text-faint, #b4b9c4);\n}\n.tb-btn.on {\n color: var(--pd-accent, #165DFF);\n background: var(--pd-accent-soft, rgba(22, 93, 255, .09));\n font-weight: 600;\n}\n.tb-btn.warn {\n color: var(--pd-accent-secondary, #f56c6c);\n background: var(--pd-danger-soft, rgba(245, 108, 108, .10));\n font-weight: 600;\n}\n.tb-btn .dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: var(--pd-text-faint, #b4b9c4);\n display: inline-block;\n transition: background .14s ease, box-shadow .14s ease;\n}\n.tb-btn.on .dot {\n background: var(--pd-accent, #165DFF);\n box-shadow: 0 0 0 3px rgba(22, 93, 255, .12);\n}\n.tb-icon {\n font-size: 15px;\n line-height: 1;\n}\n.tb-mark {\n width: 28px;\n height: 28px;\n margin-right: 2px;\n border-radius: 8px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n color: #fff;\n background: linear-gradient(150deg, var(--pd-accent-2, #3D7BFF), var(--pd-accent, #165DFF));\n box-shadow: 0 3px 8px rgba(22, 93, 255, .28), inset 0 1px 0 rgba(255, 255, 255, .22);\n flex-shrink: 0;\n}\n.tb-mark svg {\n width: 16px;\n height: 16px;\n}\n.tb-title {\n display: flex;\n flex-direction: column;\n line-height: 1.2;\n padding-left: 6px;\n}\n.tb-title-name {\n font-size: 13px;\n font-weight: 600;\n color: var(--pd-text, #2a2e37);\n letter-spacing: .2px;\n}\n.tb-title-sub {\n font-size: 10px;\n color: var(--pd-text-muted, #8b909c);\n letter-spacing: .8px;\n}\n.tb-zoom {\n font-size: 12px;\n color: var(--pd-text, #2a2e37);\n font-variant-numeric: tabular-nums;\n min-width: 46px;\n text-align: center;\n}\n.tb-spacer {\n flex: 1;\n}\n.btn-primary,\n.btn-secondary {\n height: 32px;\n padding: 0 16px;\n border-radius: 7px;\n font-size: 13px;\n font-weight: 600;\n cursor: pointer;\n transition: filter .14s ease, background .14s ease, border-color .14s ease, box-shadow .14s ease;\n}\n.btn-secondary {\n background: var(--pd-field-bg, #f4f6fa);\n color: var(--pd-text-muted, #606266);\n border: 1px solid var(--pd-border, #d9dde6);\n}\n.btn-secondary:hover {\n border-color: var(--pd-accent, #165DFF);\n color: var(--pd-accent, #165DFF);\n background: var(--pd-accent-soft, rgba(22, 93, 255, .06));\n}\n.btn-primary {\n background: linear-gradient(180deg, var(--pd-accent-2, #3D7BFF), var(--pd-accent, #165DFF));\n color: #fff;\n border: none;\n box-shadow: 0 3px 10px rgba(22, 93, 255, .28), inset 0 1px 0 rgba(255, 255, 255, .18);\n}\n.btn-primary:hover {\n filter: brightness(1.07);\n box-shadow: 0 5px 14px rgba(22, 93, 255, .34), inset 0 1px 0 rgba(255, 255, 255, .18);\n}\n.btn-primary:active {\n filter: brightness(.97);\n}\n</style>\n","<template>\n <div class=\"layer-panel\">\n <div class=\"panel-title\">图层</div>\n <div\n v-for=\"layer in sortedLayers\"\n :key=\"layer.id\"\n class=\"layer-item\"\n :class=\"{ active: selectedIds.has(layer.id) }\"\n @click=\"$emit('select', layer.id, false)\"\n >\n <span class=\"layer-icon\">{{ layerIcon(layer) }}</span>\n <span class=\"layer-name\">{{ layerName(layer) }}</span>\n <span v-if=\"zoneTag(layer)\" class=\"layer-zone\">{{ zoneTag(layer) }}</span>\n <span class=\"layer-zindex\">z:{{ layer.options.zIndex ?? 0 }}</span>\n </div>\n <div class=\"layer-actions\" v-if=\"sortedLayers.length > 0\">\n <button type=\"button\" class=\"pd-button small\" @click=\"$emit('move-layer', 'top')\" title=\"置顶\">\n ⤒\n </button>\n <button type=\"button\" class=\"pd-button small\" @click=\"$emit('move-layer', 'up')\" title=\"上移\">\n ↑\n </button>\n <button type=\"button\" class=\"pd-button small\" @click=\"$emit('move-layer', 'down')\" title=\"下移\">\n ↓\n </button>\n <button type=\"button\" class=\"pd-button small\" @click=\"$emit('move-layer', 'bottom')\" title=\"置底\">\n ⤓\n </button>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport type { RuntimeElement } from '../types'\n\nconst props = defineProps<{\n elements: RuntimeElement[]\n selectedIds: Set<string>\n}>()\n\ndefineEmits<{\n select: [id: string, multiple: boolean]\n 'move-layer': [direction: string]\n}>()\n\nconst sortedLayers = computed(() =>\n [...props.elements].sort((a, b) => (b.options.zIndex ?? 0) - (a.options.zIndex ?? 0))\n)\n\nconst elementIconMap: Record<string, string> = {\n text: 'T',\n longText: '¶',\n table: '⊞',\n image: '🖼',\n barcode: '≡',\n qrcode: '▣',\n hline: '—',\n vline: '|',\n rect: '□',\n oval: '○',\n html: '<>',\n}\n\nfunction layerIcon(el: RuntimeElement): string {\n return elementIconMap[el.printElementType.type] || '?'\n}\n\nfunction layerName(el: RuntimeElement): string {\n return el.options.title || el.printElementType.title || el.printElementType.type\n}\n\nfunction zoneTag(el: RuntimeElement): string {\n if (el.zone === 'header') return '页眉'\n if (el.zone === 'footer') return '页脚'\n return ''\n}\n</script>\n\n<style scoped>\n.layer-panel {\n border-top: 1px solid var(--pd-border);\n padding: 8px 12px;\n height: 100%;\n box-sizing: border-box;\n overflow-y: auto;\n}\n.panel-title {\n font-size: 11px;\n color: var(--pd-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 8px;\n}\n.layer-item {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 4px 6px;\n margin-bottom: 2px;\n border-radius: 4px;\n cursor: pointer;\n font-size: 12px;\n transition: background 0.1s;\n}\n.layer-item:hover {\n background: var(--pd-sidebar-hover, #f0f2f5);\n}\n.layer-item.active {\n background: rgba(22, 93, 255, 0.10);\n color: var(--pd-accent, #165DFF);\n box-shadow: inset 2px 0 0 var(--pd-accent, #165DFF);\n}\n.layer-icon {\n width: 18px;\n text-align: center;\n font-size: 12px;\n color: var(--pd-text-muted, #909399);\n}\n.layer-name {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n color: var(--pd-text, #303133);\n}\n.layer-zone {\n flex-shrink: 0;\n padding: 0 4px;\n font-size: 10px;\n line-height: 14px;\n color: var(--pd-ink-green, #67c23a);\n background: rgba(103, 194, 58, 0.1);\n border-radius: 3px;\n}\n.layer-zindex {\n font-size: 10px;\n color: var(--pd-text-muted, #909399);\n font-variant-numeric: tabular-nums;\n}\n.layer-actions {\n display: flex;\n gap: 4px;\n margin-top: 8px;\n}\n</style>\n","import type { PrintBusinessField } from '../types'\n\nexport interface FieldGroup {\n /** 分组键(fieldKey 首段);空串表示无分组的顶层字段 */\n key: string\n /** 分组显示名:取容器字段的 fieldLabel,缺省回退为 key */\n label: string\n /** 是否明细列表分组(容器字段 fieldType === 'list') */\n isList: boolean\n /** 分组下的叶子字段 */\n fields: PrintBusinessField[]\n}\n\n/**\n * 将宿主扁平字段按 fieldKey 首段分组:\n * - 带点路径(supplier.name、goods.spec)归入首段分组;\n * - 无点且作为其它字段前缀的记录视为分组容器(如 supplier/goods),\n * 容器提供分组名称,fieldType='list' 标识明细列表(表格数据源);\n * - 无点且无子字段的记录作为独立顶层字段。\n */\nexport function groupFields(fields: PrintBusinessField[]): FieldGroup[] {\n const sorted = [...fields].sort((a, b) => (a.sortOrder ?? 0) - (b.sortOrder ?? 0))\n const groupMap = new Map<string, FieldGroup>()\n const groupOrder: string[] = []\n\n for (const f of sorted) {\n const dot = f.fieldKey.indexOf('.')\n if (dot === -1) continue\n const key = f.fieldKey.slice(0, dot)\n let g = groupMap.get(key)\n if (!g) {\n g = { key, label: key, isList: false, fields: [] }\n groupMap.set(key, g)\n groupOrder.push(key)\n }\n g.fields.push(f)\n }\n\n const groups: FieldGroup[] = []\n const standalone: PrintBusinessField[] = []\n for (const f of sorted) {\n if (f.fieldKey.includes('.')) continue\n const g = groupMap.get(f.fieldKey)\n if (g) {\n // 容器记录:提供分组名称,列表容器(fieldType='list')用于表格数据源选择\n g.label = f.fieldLabel\n g.isList = f.fieldType === 'list'\n } else {\n standalone.push(f)\n }\n }\n if (standalone.length) groups.push({ key: '', label: '', isList: false, fields: standalone })\n for (const key of groupOrder) groups.push(groupMap.get(key)!)\n return groups\n}\n\n/** 按关键字过滤分组(匹配字段名/字段 key),无叶子的分组剔除 */\nexport function filterGroups(groups: FieldGroup[], keyword: string): FieldGroup[] {\n const kw = keyword.trim().toLowerCase()\n if (!kw) return groups\n return groups\n .map(g => ({\n ...g,\n fields: g.fields.filter(\n f => f.fieldLabel.toLowerCase().includes(kw) || f.fieldKey.toLowerCase().includes(kw),\n ),\n }))\n .filter(g => g.fields.length > 0)\n}\n","<template>\n <div class=\"field-tree-panel\">\n <div class=\"panel-title\">业务字段</div>\n <input v-model=\"searchText\" class=\"pd-input search-input\" type=\"search\" placeholder=\"搜索字段...\" aria-label=\"搜索字段\" />\n <div class=\"tree-container\">\n <template v-for=\"group in filteredGroups\" :key=\"group.key || '_top'\">\n <div\n v-if=\"group.key\"\n class=\"field-group-header\"\n :class=\"{ 'is-list': group.isList }\"\n @click=\"toggleGroup(group.key)\"\n >\n <span class=\"expand-icon\">{{ collapsedGroups.has(group.key) && !searching ? '▶' : '▼' }}</span>\n <span class=\"node-icon\">{{ group.isList ? '📋' : '📁' }}</span>\n <span class=\"group-label\">{{ group.label }}</span>\n </div>\n <div v-show=\"!group.key || searching || !collapsedGroups.has(group.key)\">\n <div\n v-for=\"field in group.fields\"\n :key=\"field.fieldKey\"\n class=\"field-row\"\n draggable=\"true\"\n :style=\"{ paddingLeft: (group.key ? 22 : 8) + 'px' }\"\n @dragstart=\"onDragStart($event, field)\"\n >\n <span class=\"node-icon\">📄</span>\n <span class=\"node-label\">{{ field.fieldLabel }}</span>\n <span class=\"node-key\">({{ field.fieldKey }})</span>\n </div>\n </div>\n </template>\n </div>\n <p v-if=\"filteredGroups.length === 0\" class=\"pd-empty\">暂无字段</p>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed } from 'vue'\nimport type { PrintBusinessField } from '../types'\nimport { groupFields, filterGroups } from '../utils/field-groups'\n\nconst props = defineProps<{\n fields: PrintBusinessField[]\n}>()\n\nconst emit = defineEmits<{\n 'field-drag': [field: PrintBusinessField]\n}>()\n\nconst searchText = ref('')\nconst collapsedGroups = ref<Set<string>>(new Set())\n\nconst searching = computed(() => !!searchText.value.trim())\nconst filteredGroups = computed(() =>\n filterGroups(groupFields(props.fields), searchText.value),\n)\n\nfunction toggleGroup(key: string) {\n const next = new Set(collapsedGroups.value)\n if (next.has(key)) next.delete(key)\n else next.add(key)\n collapsedGroups.value = next\n}\n\nfunction onDragStart(event: DragEvent, field: PrintBusinessField) {\n // 拖拽载荷为完整字段路径(如 goods.spec),与打印数据结构一致\n event.dataTransfer?.setData('fieldData', JSON.stringify({ fieldKey: field.fieldKey, fieldLabel: field.fieldLabel }))\n if (event.dataTransfer) event.dataTransfer.effectAllowed = 'copy'\n emit('field-drag', field)\n}\n</script>\n\n<style scoped>\n.field-tree-panel {\n padding: 0;\n}\n.panel-title {\n font-size: 11px;\n color: var(--pd-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n padding: 4px 0 8px;\n margin-bottom: 8px;\n border-bottom: 1px solid var(--pd-border);\n}\n.search-input {\n margin-bottom: 8px;\n}\n.tree-container {\n overflow-y: auto;\n min-height: 0;\n}\n.field-group-header {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 5px 8px;\n border-radius: 4px;\n font-size: 13px;\n color: var(--pd-text, #303133);\n cursor: pointer;\n user-select: none;\n transition: background 0.1s;\n}\n.field-group-header:hover {\n background: var(--pd-sidebar-hover, #f0f2f5);\n}\n.field-group-header.is-list {\n color: var(--pd-accent, #165DFF);\n font-weight: 500;\n}\n.expand-icon {\n width: 12px;\n font-size: 8px;\n flex-shrink: 0;\n color: var(--pd-text-muted, #909399);\n}\n.field-row {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 5px 8px;\n border-radius: 4px;\n font-size: 13px;\n color: var(--pd-text, #303133);\n cursor: grab;\n user-select: none;\n transition: background 0.1s;\n}\n.field-row:hover {\n background: var(--pd-sidebar-hover, #f0f2f5);\n}\n.node-icon {\n font-size: 14px;\n flex-shrink: 0;\n filter: saturate(.6);\n opacity: .9;\n}\n.node-label {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.node-key {\n font-size: 11px;\n color: var(--pd-text-muted, #909399);\n flex-shrink: 0;\n}\n.group-label {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n</style>\n","<template>\n <div class=\"left-panel\" :class=\"{ collapsed }\">\n <!-- 折叠态:竖排图标,点击即展开对应页签 -->\n <div v-if=\"collapsed\" class=\"left-collapsed\">\n <button class=\"lc-btn\" title=\"展开素材台\" @click=\"expandTab(activeTab)\">»</button>\n <button class=\"lc-btn\" :class=\"{ on: activeTab === 'elements' }\" title=\"元素\" @click=\"expandTab('elements')\">▦</button>\n <button class=\"lc-btn\" :class=\"{ on: activeTab === 'fields' }\" title=\"字段\" @click=\"expandTab('fields')\">⊛</button>\n <button class=\"lc-btn\" :class=\"{ on: activeTab === 'layers' }\" title=\"图层\" @click=\"expandTab('layers')\">≡</button>\n </div>\n <template v-else>\n <div class=\"left-head\">\n <span class=\"left-title\">素材台</span>\n <button class=\"collapse-btn\" title=\"收起素材台\" @click=\"$emit('toggle-collapse')\">«</button>\n </div>\n <div class=\"pd-tabs left-tabs\">\n <div class=\"pd-tab-bar\" role=\"tablist\">\n <button type=\"button\" class=\"pd-tab\" :class=\"{ active: activeTab === 'elements' }\" @click=\"activeTab = 'elements'\">元素</button>\n <button type=\"button\" class=\"pd-tab\" :class=\"{ active: activeTab === 'fields' }\" @click=\"activeTab = 'fields'\">字段</button>\n <button type=\"button\" class=\"pd-tab\" :class=\"{ active: activeTab === 'layers' }\" @click=\"activeTab = 'layers'\">图层</button>\n </div>\n <div v-show=\"activeTab === 'elements'\" class=\"pd-tab-pane\" role=\"tabpanel\">\n <div class=\"panel-title\">拖拽元素到画布</div>\n <div\n v-for=\"item in elementTypes\"\n :key=\"item.type\"\n class=\"material-card\"\n draggable=\"true\"\n @dragstart=\"onDragStart($event, item.type)\"\n >\n <span class=\"material-icon\">{{ item.icon }}</span>\n <span class=\"material-label\">{{ item.label }}</span>\n </div>\n </div>\n <div v-show=\"activeTab === 'fields'\" class=\"pd-tab-pane\" role=\"tabpanel\">\n <FieldTreePanel\n :fields=\"fields\"\n @field-drag=\"onFieldDrag\"\n />\n </div>\n <div v-show=\"activeTab === 'layers'\" class=\"pd-tab-pane\" role=\"tabpanel\">\n <LayerPanel\n :elements=\"elements\"\n :selected-ids=\"selectedIds\"\n @select=\"(id: string, m: boolean) => $emit('select', id, m)\"\n @move-layer=\"(d: string) => $emit('move-layer', d)\"\n @toggle-visible=\"(id: string) => $emit('toggle-visible', id)\"\n @toggle-locked=\"(id: string) => $emit('toggle-locked', id)\"\n />\n </div>\n </div>\n </template>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref } from 'vue'\nimport type { ElementType, PrintBusinessField, RuntimeElement } from '../types'\nimport LayerPanel from './LayerPanel.vue'\nimport FieldTreePanel from './FieldTreePanel.vue'\n\ndefineProps<{\n fields: PrintBusinessField[]\n elements: RuntimeElement[]\n selectedIds: Set<string>\n collapsed: boolean\n}>()\n\nconst emit = defineEmits<{\n select: [id: string, multiple: boolean]\n 'move-layer': [direction: string]\n 'toggle-visible': [id: string]\n 'toggle-locked': [id: string]\n 'field-drag': [field: PrintBusinessField]\n 'toggle-collapse': []\n}>()\n\nconst activeTab = ref('elements')\n\nconst elementTypes: { type: ElementType; label: string; icon: string }[] = [\n { type: 'text', label: '文本', icon: 'T' },\n { type: 'barcode', label: '条形码', icon: '▍▍' },\n { type: 'qrcode', label: '二维码', icon: '▦' },\n { type: 'image', label: '图片', icon: '▧' },\n { type: 'table', label: '表格', icon: '⊞' },\n { type: 'longText', label: '长文', icon: '¶' },\n { type: 'hline', label: '横线', icon: '―' },\n { type: 'vline', label: '竖线', icon: '│' },\n { type: 'rect', label: '矩形', icon: '▭' },\n { type: 'oval', label: '椭圆', icon: '◯' },\n { type: 'html', label: 'HTML', icon: '<>' },\n]\n\nfunction onDragStart(event: DragEvent, type: string) {\n event.dataTransfer?.setData('elementType', type)\n}\n\nfunction onFieldDrag(field: PrintBusinessField) {\n emit('field-drag', field)\n}\n\nfunction expandTab(tab: string) {\n activeTab.value = tab\n emit('toggle-collapse')\n}\n</script>\n\n<style scoped>\n.left-panel {\n width: 224px;\n min-width: 224px;\n background: var(--pd-sidebar, #ffffff);\n border-right: 1px solid var(--pd-border-soft, #e9ecf2);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n transition: width .18s ease;\n}\n.left-panel.collapsed {\n width: 36px;\n min-width: 36px;\n border-right: 1px solid var(--pd-border-soft, #e9ecf2);\n}\n.left-collapsed {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n padding-top: 12px;\n flex: 1;\n}\n.lc-btn {\n width: 26px;\n height: 26px;\n border-radius: 6px;\n border: 1px solid transparent;\n background: transparent;\n color: var(--pd-text-muted, #8b909c);\n font-size: 12px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all .14s ease;\n}\n.lc-btn:hover {\n color: var(--pd-text, #2a2e37);\n background: var(--pd-sidebar-hover, #f0f3f9);\n}\n.lc-btn.on {\n color: var(--pd-accent, #165DFF);\n background: var(--pd-accent-soft, rgba(22, 93, 255, .09));\n}\n.left-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n height: 42px;\n padding: 0 12px;\n flex-shrink: 0;\n border-bottom: 1px solid var(--pd-border-soft, #e9ecf2);\n}\n.left-title {\n font-size: 12px;\n font-weight: 600;\n color: var(--pd-text, #2a2e37);\n letter-spacing: 1.2px;\n display: inline-flex;\n align-items: center;\n gap: 7px;\n}\n.left-title::before {\n content: \"\";\n width: 3px;\n height: 12px;\n border-radius: 2px;\n background: linear-gradient(180deg, var(--pd-accent-2, #3D7BFF), var(--pd-accent, #165DFF));\n}\n.collapse-btn {\n border: none;\n background: transparent;\n color: var(--pd-text-muted, #8b909c);\n font-size: 14px;\n cursor: pointer;\n width: 24px;\n height: 24px;\n border-radius: 5px;\n transition: all .14s ease;\n}\n.collapse-btn:hover {\n color: var(--pd-text, #2a2e37);\n background: var(--pd-sidebar-hover, #f0f3f9);\n}\n.left-tabs {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n.left-tabs .pd-tab-pane {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n padding: 12px;\n}\n.panel-title {\n font-size: 11px;\n color: var(--pd-text-muted, #8b909c);\n letter-spacing: .6px;\n padding: 2px 2px 8px;\n margin-bottom: 10px;\n border-bottom: 1px solid var(--pd-border-soft, #e9ecf2);\n}\n.material-card {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 8px 10px;\n margin-bottom: 7px;\n border: 1px solid var(--pd-border-soft, #e9ecf2);\n border-radius: 8px;\n background: var(--pd-field-bg, #f4f6fa);\n cursor: grab;\n user-select: none;\n transition: border-color .14s ease, background .14s ease, transform .14s ease, box-shadow .14s ease;\n}\n.material-card:hover {\n border-color: rgba(22, 93, 255, .45);\n background: var(--pd-surface, #ffffff);\n transform: translateY(-1px);\n box-shadow: var(--pd-shadow-sm, 0 1px 2px rgba(23, 32, 60, .05));\n}\n.material-card:active {\n cursor: grabbing;\n transform: translateY(0);\n}\n.material-icon {\n width: 30px;\n height: 24px;\n border: 1px dashed var(--pd-border, #d9dde6);\n border-radius: 5px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 11px;\n color: var(--pd-accent, #165DFF);\n background: var(--pd-surface, #ffffff);\n flex-shrink: 0;\n transition: border-color .14s ease, background .14s ease;\n}\n.material-card:hover .material-icon {\n border-style: solid;\n border-color: var(--pd-accent, #165DFF);\n background: var(--pd-accent-soft, rgba(22, 93, 255, .09));\n}\n.material-label {\n font-size: 12.5px;\n color: var(--pd-text, #2a2e37);\n}\n</style>\n","// web/src/components/print/composables/useDrag.ts\nimport { ref } from 'vue'\nimport type { AdsorbResult } from '../types'\n\nexport interface DragOptions {\n axis?: 'x' | 'y'\n disabled?: boolean\n getScale?: () => number\n /** 拖拽过程中每帧回调,提供修正后的绝对坐标(调用方用 transform 做视觉跟随) */\n onDrag: (pos: { left: number; top: number }) => void\n /** 拖拽结束回调,提供最终坐标与修饰符信息(调用方一次性写入响应式数据) */\n onDragEnd?: (pos: { left: number; top: number }, info: { altKey: boolean }) => void\n onStart?: (info: { altKey: boolean }) => void\n onStop?: () => void\n onAdsorb?: (pos: { left: number; top: number; width: number; height: number }) => AdsorbResult\n}\n\nexport function useDrag(target: { value: HTMLElement | null }, options: DragOptions) {\n const isDragging = ref(false)\n /** 拖拽预览状态:半透明副本的绝对坐标与尺寸(pt),供上层渲染预览层 */\n const dragPreview = ref<{ left: number; top: number; width: number; height: number } | null>(null)\n\n let startX = 0, startY = 0\n let startLeft = 0, startTop = 0\n // 记录 mousedown 时的 altKey,供 onDragEnd 判定是否复制\n let downAltKey = false\n\n function onMouseDown(e: MouseEvent) {\n if (options.disabled) return\n // 忽略 resize 手柄点击\n const targetEl = e.target\n if (!(targetEl instanceof HTMLElement) || targetEl.classList.contains('resize-handle')) return\n\n isDragging.value = true\n downAltKey = e.altKey\n startX = e.clientX\n startY = e.clientY\n\n const el = target.value\n if (!el) return\n startLeft = parseFloat(el.style.left) || 0\n startTop = parseFloat(el.style.top) || 0\n // 初始化拖拽预览副本(记录起始位置与尺寸)\n dragPreview.value = {\n left: startLeft,\n top: startTop,\n width: parseFloat(el.style.width) || 0,\n height: parseFloat(el.style.height) || 0,\n }\n\n options.onStart?.({ altKey: downAltKey })\n\n document.addEventListener('mousemove', onMouseMove)\n document.addEventListener('mouseup', onMouseUp)\n e.preventDefault()\n }\n\n /** 由鼠标坐标计算吸附修正后的绝对坐标 */\n function computePos(e: MouseEvent) {\n const scale = options.getScale?.() ?? 1\n let newLeft = startLeft + (e.clientX - startX) / scale\n let newTop = startTop + (e.clientY - startY) / scale\n\n if (options.axis === 'x') newTop = startTop\n if (options.axis === 'y') newLeft = startLeft\n\n if (options.onAdsorb) {\n const el = target.value\n if (el) {\n const w = parseFloat(el.style.width) || 0\n const h = parseFloat(el.style.height) || 0\n const result = options.onAdsorb({ left: newLeft, top: newTop, width: w, height: h })\n newLeft = result.left\n newTop = result.top\n }\n }\n return { left: newLeft, top: newTop }\n }\n\n function onMouseMove(e: MouseEvent) {\n const pos = computePos(e)\n // 更新预览副本位置(响应式,供渲染层实时跟随)\n if (dragPreview.value) {\n dragPreview.value.left = pos.left\n dragPreview.value.top = pos.top\n }\n options.onDrag(pos)\n }\n\n function onMouseUp(e: MouseEvent) {\n isDragging.value = false\n const pos = computePos(e)\n // 一次性通知调用方最终坐标与修饰符,写入响应式数据\n options.onDragEnd?.(pos, { altKey: downAltKey })\n options.onStop?.()\n // 清空预览副本\n dragPreview.value = null\n\n document.removeEventListener('mousemove', onMouseMove)\n document.removeEventListener('mouseup', onMouseUp)\n }\n\n function cleanup() {\n const el = target.value\n if (el) {\n el.removeEventListener('mousedown', onMouseDown)\n }\n document.removeEventListener('mousemove', onMouseMove)\n document.removeEventListener('mouseup', onMouseUp)\n }\n\n function setup() {\n cleanup()\n const el = target.value\n if (el) {\n el.addEventListener('mousedown', onMouseDown)\n }\n }\n\n return { isDragging, dragPreview, setup, cleanup }\n}\n","// web/src/components/print/composables/useResize.ts\nimport type { ResizePoint } from '../types'\n\nexport interface ResizeRect {\n left: number\n top: number\n width: number\n height: number\n}\n\nexport interface ResizeOptions {\n minWidth?: number\n minHeight?: number\n getScale?: () => number\n /** 缩放起始时读取元素当前矩形(mm) */\n getRect: () => ResizeRect\n onResize: (rect: ResizeRect) => void\n onStart?: () => void\n onStop?: () => void\n}\n\n/** 8 方位缩放手柄,供模板 v-for 渲染 */\nexport const RESIZE_POINTS: ResizePoint[] = ['nw', 'n', 'ne', 'e', 'se', 's', 'sw', 'w']\n\n/** 根据方位与位移计算缩放后矩形(纯函数) */\nexport function calcResizeRect(\n point: ResizePoint,\n startRect: ResizeRect,\n dx: number,\n dy: number,\n minW: number,\n minH: number,\n): ResizeRect {\n let { left, top, width, height } = startRect\n\n switch (point) {\n case 'e': width = Math.max(minW, startRect.width + dx); break\n case 'w': width = Math.max(minW, startRect.width - dx); left = startRect.left + startRect.width - width; break\n case 's': height = Math.max(minH, startRect.height + dy); break\n case 'n': height = Math.max(minH, startRect.height - dy); top = startRect.top + startRect.height - height; break\n case 'se': width = Math.max(minW, startRect.width + dx); height = Math.max(minH, startRect.height + dy); break\n case 'sw': width = Math.max(minW, startRect.width - dx); left = startRect.left + startRect.width - width; height = Math.max(minH, startRect.height + dy); break\n case 'ne': width = Math.max(minW, startRect.width + dx); height = Math.max(minH, startRect.height - dy); top = startRect.top + startRect.height - height; break\n case 'nw': width = Math.max(minW, startRect.width - dx); left = startRect.left + startRect.width - width; height = Math.max(minH, startRect.height - dy); top = startRect.top + startRect.height - height; break\n }\n\n return { left, top, width, height }\n}\n\n/** 缩放交互逻辑:手柄由组件模板渲染,mousedown 时调用 startResize */\nexport function useResize(options: ResizeOptions) {\n let startX = 0, startY = 0\n let startRect: ResizeRect = { left: 0, top: 0, width: 0, height: 0 }\n let activePoint: ResizePoint | null = null\n\n function startResize(point: ResizePoint, e: MouseEvent) {\n activePoint = point\n startX = e.clientX\n startY = e.clientY\n startRect = { ...options.getRect() }\n options.onStart?.()\n document.addEventListener('mousemove', onResizeMove)\n document.addEventListener('mouseup', onResizeEnd)\n e.preventDefault()\n }\n\n function onResizeMove(e: MouseEvent) {\n if (!activePoint) {\n return\n }\n const scale = options.getScale?.() || 1\n const dx = (e.clientX - startX) / scale\n const dy = (e.clientY - startY) / scale\n const minW = options.minWidth || 20\n const minH = options.minHeight || 20\n options.onResize(calcResizeRect(activePoint, startRect, dx, dy, minW, minH))\n }\n\n function onResizeEnd() {\n activePoint = null\n options.onStop?.()\n document.removeEventListener('mousemove', onResizeMove)\n document.removeEventListener('mouseup', onResizeEnd)\n }\n\n function cleanup() {\n document.removeEventListener('mousemove', onResizeMove)\n document.removeEventListener('mouseup', onResizeEnd)\n }\n\n return { startResize, cleanup }\n}\n","import { getDemoData } from '../utils/demo-data'\n\ninterface BindingDisplayState {\n status: 'unbound' | 'bound' | 'warning' | 'error'\n badge: string\n badgeColor: string\n demoPreview: string\n warning?: string\n}\n\nfunction getNestedValue(obj: any, path: string): any {\n return path.split('.').reduce((current, key) => current?.[key], obj)\n}\n\nexport function useBindingDisplay() {\n function getBindingDisplayState(element: any): BindingDisplayState {\n const formatter = element.options.formatter\n const title = element.options.title\n\n if (!formatter) {\n return {\n status: 'unbound',\n badge: title || '文本',\n badgeColor: '#909399',\n demoPreview: title || '文本',\n }\n }\n\n const demoData = getDemoData()\n // 简单预览:从 formatter 中提取字段名并查找 demo 数据\n const fieldMatch = formatter.match(/\\{([^}]+)\\}/)\n if (fieldMatch) {\n const fieldPath = fieldMatch[1]\n const demoValue = getNestedValue(demoData, fieldPath)\n return {\n status: 'bound',\n badge: `fx ${formatter}`,\n badgeColor: '#409EFF',\n demoPreview: demoValue != null ? String(demoValue) : formatter,\n }\n }\n\n return {\n status: 'bound',\n badge: `fx ${formatter}`,\n badgeColor: '#409EFF',\n demoPreview: formatter,\n }\n }\n\n return { getBindingDisplayState }\n}\n","<template>\n <div class=\"print-text\" :style=\"textStyle\">\n {{ displayText }}\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport type { RuntimeElement } from '../../types'\nimport { resolveTextBinding } from '../../utils/binding'\n\nconst props = defineProps<{\n element: RuntimeElement\n data?: Record<string, any>[]\n designMode?: boolean\n}>()\n\nconst V_ALIGN_FLEX: Record<string, string> = { top: 'flex-start', middle: 'center', bottom: 'flex-end' }\nconst H_ALIGN_FLEX: Record<string, string> = { left: 'flex-start', center: 'center', right: 'flex-end' }\n\nconst textStyle = computed(() => {\n const o = props.element.options\n return {\n fontSize: (o.fontSize || 12) + 'pt',\n fontWeight: o.fontWeight || 'normal',\n fontFamily: o.fontFamily || 'inherit',\n color: o.color || '#333',\n backgroundColor: o.backgroundColor || 'transparent',\n textAlign: o.textAlign || 'left',\n lineHeight: o.lineHeight ? o.lineHeight + 'pt' : 'normal',\n letterSpacing: o.letterSpacing ? o.letterSpacing + 'pt' : 'normal',\n textDecoration: o.textDecoration || 'none',\n padding: `${o.contentPaddingTop || 0}pt ${o.contentPaddingRight || 0}pt ${o.contentPaddingBottom || 0}pt ${o.contentPaddingLeft || 0}pt`,\n width: '100%',\n height: '100%',\n boxSizing: 'border-box' as const,\n overflow: 'hidden',\n ...(o.verticalAlign\n ? {\n display: 'flex',\n alignItems: V_ALIGN_FLEX[o.verticalAlign] ?? 'flex-start',\n justifyContent: H_ALIGN_FLEX[o.textAlign || 'left'] ?? 'flex-start',\n }\n : {}),\n }\n})\n\nconst displayText = computed(() => {\n if (props.designMode) {\n if (props.element.options.testData) {\n return props.element.options.testData\n }\n return props.element.options.formatter || '文本'\n }\n return resolveTextBinding(props.element.options, props.data)\n})\n</script>\n","<template>\n <div class=\"print-image\">\n <img v-if=\"imageSrc && !hasError\" :src=\"imageSrc\" :style=\"imgStyle\" @error=\"onError\" />\n <div v-else class=\"image-placeholder\">图片</div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport type { RuntimeElement } from '../../types'\nimport { evaluateTemplate } from '../../utils/expression-eval'\nimport { DEFAULT_DEMO_DATA } from '../../utils/demo-data'\n\nconst props = defineProps<{\n element: RuntimeElement\n data?: Record<string, any>[]\n designMode?: boolean\n}>()\n\nconst imageSrc = computed(() => {\n const raw = props.element.options.src || ''\n if (!raw) return ''\n // {字段} 表达式:设计态用 demo 数据求值,运行态用打印数据求值\n if (raw.includes('{')) {\n if (props.designMode) {\n return evaluateTemplate(raw, DEFAULT_DEMO_DATA)\n }\n return evaluateTemplate(raw, props.data?.[0] || {})\n }\n // 相对路径(如 /docfiles/...)经站点同源 + dev/prod 代理可直接访问;绝对 URL 原样使用\n return raw\n})\n\n// 加载失败兜底:显示占位,避免破图阻塞 PDF 就绪判定\nconst hasError = ref(false)\nfunction onError() {\n hasError.value = true\n}\n// src 变化时重置错误态\nwatch(imageSrc, () => {\n hasError.value = false\n})\n\nconst imgStyle = computed(() => ({\n objectFit: (props.element.options.fit || 'contain') as any,\n}))\n</script>\n\n<style scoped>\n.print-image { width: 100%; height: 100%; overflow: hidden; }\n.print-image img { width: 100%; height: 100%; display: block; }\n.image-placeholder {\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #bbb;\n font-size: 12px;\n border: 1px dashed #ddd;\n box-sizing: border-box;\n}\n</style>\n","<template>\n <div class=\"print-longtext\" :style=\"textStyle\">\n {{ displayText }}\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport type { RuntimeElement } from '../../types'\nimport { resolveTextBinding } from '../../utils/binding'\n\nconst props = defineProps<{\n element: RuntimeElement\n data?: Record<string, any>[]\n designMode?: boolean\n}>()\n\nconst V_ALIGN_FLEX: Record<string, string> = { top: 'flex-start', middle: 'center', bottom: 'flex-end' }\nconst H_ALIGN_FLEX: Record<string, string> = { left: 'flex-start', center: 'center', right: 'flex-end' }\n\nconst textStyle = computed(() => {\n const o = props.element.options\n return {\n fontSize: (o.fontSize || 12) + 'pt',\n fontWeight: o.fontWeight || 'normal',\n fontFamily: o.fontFamily || 'inherit',\n color: o.color || '#333',\n backgroundColor: o.backgroundColor || 'transparent',\n textAlign: o.textAlign || 'left',\n lineHeight: o.lineHeight ? o.lineHeight + 'pt' : '1.5',\n letterSpacing: o.letterSpacing ? o.letterSpacing + 'pt' : 'normal',\n textIndent: o.longTextIndent ? o.longTextIndent + 'pt' : '0',\n width: '100%',\n height: '100%',\n overflow: 'hidden',\n wordBreak: 'break-all' as const,\n boxSizing: 'border-box' as const,\n ...(o.verticalAlign\n ? {\n display: 'flex',\n alignItems: V_ALIGN_FLEX[o.verticalAlign] ?? 'flex-start',\n justifyContent: H_ALIGN_FLEX[o.textAlign || 'left'] ?? 'flex-start',\n }\n : {}),\n }\n})\n\nconst displayText = computed(() => {\n if (props.designMode) {\n if (props.element.options.formatter) return props.element.options.formatter\n return '长文本内容'\n }\n return resolveTextBinding(props.element.options, props.data)\n})\n</script>\n","<!-- 表格右键菜单:行列增删/合并拆分/行类型切换 -->\n<template>\n <Teleport to=\"body\">\n <div\n v-if=\"visible\"\n class=\"table-ctx-menu\"\n :style=\"{ left: x + 'px', top: y + 'px' }\"\n @mousedown.stop\n >\n <div class=\"menu-item\" @click=\"emitAction('insert-row-above')\">在上方插入行</div>\n <div class=\"menu-item\" @click=\"emitAction('insert-row-below')\">在下方插入行</div>\n <div\n class=\"menu-item\"\n :class=\"{ disabled: !canDeleteRow }\"\n @click=\"canDeleteRow && emitAction('delete-row')\"\n >\n 删除行\n </div>\n <div class=\"menu-divider\" />\n <div class=\"menu-item\" @click=\"emitAction('insert-col-left')\">在左侧插入列</div>\n <div class=\"menu-item\" @click=\"emitAction('insert-col-right')\">在右侧插入列</div>\n <div\n class=\"menu-item\"\n :class=\"{ disabled: !canDeleteCol }\"\n @click=\"canDeleteCol && emitAction('delete-col')\"\n >\n 删除列\n </div>\n <div class=\"menu-divider\" />\n <div\n class=\"menu-item\"\n :class=\"{ disabled: !!mergeDisabledReason }\"\n :title=\"mergeDisabledReason || ''\"\n @click=\"!mergeDisabledReason && emitAction('merge')\"\n >\n 合并单元格\n </div>\n <div\n class=\"menu-item\"\n :class=\"{ disabled: !canSplit }\"\n @click=\"canSplit && emitAction('split')\"\n >\n 拆分单元格\n </div>\n <div class=\"menu-divider\" />\n <div class=\"menu-group-title\">行类型</div>\n <div\n v-for=\"t in ROW_TYPES\"\n :key=\"t.value\"\n class=\"menu-item\"\n :class=\"{ disabled: !!rowTypeDisabledReason(t.value), active: currentRowType === t.value }\"\n :title=\"rowTypeDisabledReason(t.value) || ''\"\n @click=\"!rowTypeDisabledReason(t.value) && emitAction('set-row-type', t.value)\"\n >\n {{ t.label }}\n </div>\n </div>\n </Teleport>\n</template>\n\n<script setup lang=\"ts\">\nimport type { TableRowType } from '../../types'\n\nconst ROW_TYPES: { value: TableRowType; label: string }[] = [\n { value: 'header', label: '标题行' },\n { value: 'data', label: '数据行' },\n { value: 'subtotal', label: '小计行' },\n { value: 'summary', label: '汇总行' },\n]\n\ndefineProps<{\n visible: boolean\n x: number\n y: number\n canDeleteRow: boolean\n canDeleteCol: boolean\n mergeDisabledReason: string | null\n canSplit: boolean\n currentRowType: TableRowType | null\n rowTypeDisabledReason: (t: TableRowType) => string | null\n}>()\n\nconst emit = defineEmits<{ action: [name: string, payload?: string] }>()\n\nfunction emitAction(name: string, payload?: string) {\n emit('action', name, payload)\n}\n</script>\n\n<style scoped>\n.table-ctx-menu {\n position: fixed;\n z-index: 3000;\n min-width: 140px;\n padding: 4px 0;\n background: #fff;\n border: 1px solid #dcdfe6;\n border-radius: 4px;\n box-shadow: 0 2px 12px rgba(0, 0, 0, 0.15);\n font-size: 13px;\n}\n.menu-item {\n padding: 5px 14px;\n cursor: pointer;\n color: #333;\n}\n.menu-item:hover {\n background: #f5f7fa;\n}\n.menu-item.disabled {\n color: #c0c4cc;\n cursor: not-allowed;\n}\n.menu-item.active {\n color: #165DFF;\n}\n.menu-divider {\n height: 1px;\n margin: 4px 0;\n background: #ebeef5;\n}\n.menu-group-title {\n padding: 4px 14px;\n font-size: 12px;\n color: #909399;\n}\n</style>\n","<!-- 表格单元格内条形码/二维码渲染:设计态与预览态共用,按值生成图形 -->\n<template>\n <div class=\"cell-barcode\">\n <svg v-show=\"cellType === 'barcode' && svgOk\" ref=\"barcodeSvg\" preserveAspectRatio=\"xMidYMid meet\"></svg>\n <img v-if=\"cellType === 'qrcode' && dataUrl\" :src=\"dataUrl\" alt=\"qrcode\" />\n <span v-if=\"!svgOk && cellType === 'barcode'\" class=\"cell-barcode-fallback\">{{ value || '条码' }}</span>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, onMounted, watch } from 'vue'\nimport JsBarcode from 'jsbarcode'\nimport QRCode from 'qrcode'\n\nconst props = defineProps<{\n cellType: 'barcode' | 'qrcode'\n value: string\n barcodeType?: string\n qrCodeLevel?: string\n showText?: boolean\n}>()\n\nconst barcodeSvg = ref<SVGSVGElement | null>(null)\nconst svgOk = ref(false)\nconst dataUrl = ref('')\n\nfunction renderBarcode() {\n svgOk.value = false\n if (!barcodeSvg.value) return\n try {\n JsBarcode(barcodeSvg.value, props.value, {\n format: (props.barcodeType || 'CODE128') as any,\n width: 1,\n height: 28,\n displayValue: props.showText !== false,\n fontSize: 9,\n margin: 0,\n })\n svgOk.value = true\n } catch { /* 码值不符合码制时回退文本占位 */ }\n}\n\nasync function renderQrcode() {\n if (!props.value) {\n dataUrl.value = ''\n return\n }\n try {\n dataUrl.value = await QRCode.toDataURL(props.value, {\n width: 96,\n margin: 1,\n errorCorrectionLevel: ((props.qrCodeLevel || 'M') as 'L' | 'M' | 'Q' | 'H'),\n })\n } catch {\n dataUrl.value = ''\n }\n}\n\nfunction render() {\n if (props.cellType === 'barcode') renderBarcode()\n else renderQrcode()\n}\n\nonMounted(render)\nwatch(() => [props.cellType, props.value, props.barcodeType, props.qrCodeLevel, props.showText], render)\n</script>\n\n<style scoped>\n.cell-barcode { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; overflow: hidden; }\n/* JsBarcode svg 自带 viewBox,100% + preserveAspectRatio 使条码按单元格等比缩放填满 */\n.cell-barcode svg { width: 100%; height: 100%; }\n.cell-barcode img { max-width: 100%; max-height: 100%; }\n.cell-barcode-fallback { font-style: italic; opacity: 0.6; }\n</style>\n","<!-- Excel 风格表格元素:单元格矩阵编辑器(选区/右键菜单/双击编辑) -->\n<template>\n <div class=\"print-table\" :class=\"{ 'design-mode': designMode }\" @contextmenu.prevent>\n <table ref=\"tableRef\" :style=\"{ fontSize: defaultFontSize + 'pt', color: defaultColor }\">\n <colgroup>\n <col v-for=\"(w, i) in colWidths\" :key=\"i\" :style=\"{ width: w + 'mm' }\" />\n </colgroup>\n <tbody>\n <tr v-for=\"(row, ri) in rows\" :key=\"row.id\" :style=\"{ height: row.height + 'mm' }\">\n <template v-for=\"(cell, ci) in row.cells\" :key=\"cell.id\">\n <td\n v-if=\"!cell.merged\"\n :rowspan=\"cell.rowspan || 1\"\n :colspan=\"cell.colspan || 1\"\n :class=\"cellClass(ri, ci)\"\n :style=\"cellStyle(row, cell)\"\n @mousedown.left=\"onCellMouseDown(ri, ci, $event)\"\n @mouseenter=\"onCellMouseEnter(ri, ci)\"\n @dblclick.stop=\"onCellDblClick(ri, ci)\"\n @contextmenu.prevent.stop=\"onCellContextMenu(ri, ci, $event)\"\n >\n <CellBarcode\n v-if=\"isCodeCell(cell)\"\n :cell-type=\"cell.cellType as 'barcode' | 'qrcode'\"\n :value=\"cellDisplay(row, cell)\"\n :barcode-type=\"cell.barcodeType\"\n :qr-code-level=\"cell.qrCodeLevel\"\n :show-text=\"cell.showBarcodeText\"\n />\n <span v-else-if=\"row.type === 'data'\" class=\"data-placeholder\">\n {{ cellDisplay(row, cell) }}\n </span>\n <template v-else>{{ cellDisplay(row, cell) }}</template>\n </td>\n </template>\n </tr>\n </tbody>\n </table>\n <!-- 行类型徽标(仅设计态且元素被选中) -->\n <div v-if=\"designMode && isSelected\" class=\"row-badges\">\n <span\n v-for=\"(row, ri) in rows\"\n :key=\"row.id\"\n class=\"row-badge\"\n :style=\"{ top: badgeTopMm(ri) + 'mm', height: badgeHeightMm(ri) + 'mm' }\"\n >\n {{ ROW_TYPE_BADGE[row.type] }}\n </span>\n </div>\n <TableContextMenu\n :visible=\"menu.visible\"\n :x=\"menu.x\"\n :y=\"menu.y\"\n :can-delete-row=\"rows.length > 1\"\n :can-delete-col=\"colWidths.length > 1\"\n :merge-disabled-reason=\"mergeReason\"\n :can-split=\"canSplit\"\n :current-row-type=\"selection ? rows[selection.r1]?.type ?? null : null\"\n :row-type-disabled-reason=\"rowTypeReason\"\n @action=\"onMenuAction\"\n />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, inject, onMounted, reactive, ref, watch } from 'vue'\nimport type { RuntimeElement, TableRow, TableCell, TableRowType } from '../../types'\nimport {\n normalizeSelection, canMergeReason, mergeCells, splitCells,\n insertRow, deleteRow, insertCol, deleteCol, setRowType, syncTableElementSize,\n resolveCellBorderCss,\n} from '../../utils/table-matrix'\nimport { TABLE_EDIT_KEY, type TableEditContext } from '../../composables/useTableSelection'\nimport TableContextMenu from './TableContextMenu.vue'\nimport CellBarcode from './CellBarcode.vue'\nimport { resolveBarcodeDesignValue } from '../../utils/binding'\nimport { DEFAULT_DEMO_DATA } from '../../utils/demo-data'\n\nconst ROW_TYPE_BADGE: Record<TableRowType, string> = {\n header: '题', data: '数', subtotal: '小', summary: '汇',\n}\n\nconst props = defineProps<{\n element: RuntimeElement\n designMode?: boolean\n isSelected?: boolean\n /** 设计态下无边框单元格是否显示虚拟虚线(默认 true) */\n showTableGhostBorder?: boolean\n}>()\n\nconst emit = defineEmits<{\n 'dblclick-element': [id: string]\n 'dblclick-cell': [elementId: string, r: number, c: number]\n}>()\n\n// PrintDesigner 注入:选区共享 + 历史提交(非设计态如 PDF 预览无注入,提供空实现)\nconst editCtx = inject<TableEditContext>(TABLE_EDIT_KEY, {\n tableSelection: ref(null),\n setTableSelection: () => {},\n recordHistory: () => {},\n maxTableWidth: ref(Infinity),\n})\n\nconst rows = computed<TableRow[]>(() => props.element.options.tableRows ?? [])\nconst colWidths = computed<number[]>(() => props.element.options.tableColWidths ?? [])\nconst defaultFontSize = computed(() => props.element.options.tableDefaultFontSize ?? 10)\nconst defaultColor = computed(() => props.element.options.tableDefaultColor ?? '#333333')\n\n/** 当前元素的选区(全局选区属于本元素时才生效) */\nconst selection = computed(() => {\n const s = editCtx.tableSelection.value\n return s && s.elementId === props.element.id ? s : null\n})\n\nfunction rowTopMm(ri: number): number {\n let t = 0\n for (let i = 0; i < ri; i++) t += rows.value[i]!.height\n return t\n}\n\n// ─── 设计态实测尺寸自愈 ───\n// HTML 表格行高只是「最小高度」:单元格内容换行、大字号/大 padding 都会把行撑高,\n// 实际渲染高度可能大于行高和(打印端 overflow:visible 并按实测高度分页,行为一致)。\n// 设计框体(虚线选框/选中框/位置标签/吸附对齐)需跟随 <table> 实测高度,\n// 否则选中时示意虚线框与表格真实占用高度不一致。\nconst tableRef = ref<HTMLTableElement | null>(null)\n\n/** 96dpi 下 1mm ≈ 3.78px(与 render/browser-pagination 测量遍同一常量) */\nconst PX_PER_MM = 3.7795275591\n/** 实测高度与模型高度差小于该值(mm)时不回写,避免无意义抖动 */\nconst HEIGHT_EPSILON_MM = 0.1\n\n/** 各行实测布局(mm):行被内容撑高时,行类型徽标按实测位置/高度对齐 */\nconst rowLayoutMm = ref<{ top: number; height: number }[]>([])\n\nfunction measureTable() {\n if (!props.designMode) return\n const table = tableRef.value\n if (!table) return\n const tableHpx = table.offsetHeight\n if (tableHpx <= 0) return // 画布未挂载/隐藏(无布局)时跳过\n const o = props.element.options\n const tableHmm = tableHpx / PX_PER_MM\n if (Math.abs(tableHmm - (o.height ?? 0)) > HEIGHT_EPSILON_MM) {\n o.height = Math.round(tableHmm * 100) / 100\n }\n // tr.offsetTop 与 table.offsetTop 同属一个 offsetParent(.print-table 为 relative)\n const baseTop = table.offsetTop\n rowLayoutMm.value = Array.from(table.rows).map(tr => ({\n top: (tr.offsetTop - baseTop) / PX_PER_MM,\n height: tr.offsetHeight / PX_PER_MM,\n }))\n}\n\n/** 行徽标顶距:优先实测位置,未测量时回退行高累加 */\nfunction badgeTopMm(ri: number): number {\n return rowLayoutMm.value[ri]?.top ?? rowTopMm(ri)\n}\n\n/** 行徽标高:优先实测高度,未测量时回退配置行高 */\nfunction badgeHeightMm(ri: number): number {\n return rowLayoutMm.value[ri]?.height ?? rows.value[ri]?.height ?? 0\n}\n\n// 表格结构/内容/样式任意变化后,在 DOM 更新完毕时实测(post 钩子保证读到新布局)\nwatch(\n () => [props.element.options, props.designMode],\n () => measureTable(),\n { deep: true, flush: 'post' },\n)\n\nonMounted(() => {\n measureTable()\n // Web 字体加载完成后字宽可能变化导致换行变化,补测一次\n document.fonts?.ready.then(() => measureTable())\n})\n\n// ─── 单元格显示与样式 ───\n\n/** demo 数据中 data 行迭代用的列表(与服务端 resolveListSource 优先级一致) */\nconst demoList = computed<Record<string, any>[] | undefined>(() => {\n const ds = props.element.options.dataSource\n if (ds && Array.isArray(DEFAULT_DEMO_DATA[ds])) return DEFAULT_DEMO_DATA[ds]\n for (const v of Object.values(DEFAULT_DEMO_DATA)) {\n if (Array.isArray(v)) return v as Record<string, any>[]\n }\n return undefined\n})\n\nfunction isCodeCell(cell: TableCell): boolean {\n return cell.cellType === 'barcode' || cell.cellType === 'qrcode'\n}\n\nfunction cellDisplay(_row: TableRow, cell: TableCell): string {\n if (isCodeCell(cell)) {\n return resolveBarcodeDesignValue(cell.formatter, demoList.value)\n }\n return cell.formatter || ''\n}\n\nfunction cellStyle(_row: TableRow, cell: TableCell): Record<string, string> {\n const o = props.element.options\n // 设计态下无边框边补虚拟虚线(仅设计稿展示,预览/打印输出不受影响)\n const borderOpts = { designMode: props.designMode, showGhostBorder: props.showTableGhostBorder }\n return {\n fontFamily: cell.fontFamily || 'inherit',\n textAlign: cell.align ?? 'left',\n verticalAlign: cell.valign ?? 'middle',\n fontSize: (cell.fontSize ?? defaultFontSize.value) + 'pt',\n fontWeight: cell.fontWeight ?? 'normal',\n color: cell.color ?? defaultColor.value,\n backgroundColor: cell.backgroundColor ?? 'transparent',\n borderTop: resolveCellBorderCss(cell.borders?.top, borderOpts),\n borderRight: resolveCellBorderCss(cell.borders?.right, borderOpts),\n borderBottom: resolveCellBorderCss(cell.borders?.bottom, borderOpts),\n borderLeft: resolveCellBorderCss(cell.borders?.left, borderOpts),\n padding: (cell.padding ?? o.tableDefaultPadding ?? 1) + 'mm',\n whiteSpace: (cell.wordWrap ?? true) ? 'normal' : 'nowrap',\n overflow: (cell.wordWrap ?? true) ? 'visible' : 'hidden',\n }\n}\n\nfunction cellClass(ri: number, ci: number): Record<string, boolean> {\n const s = selection.value\n const inSel = !!s && ri >= s.r1 && ri <= s.r2 && ci >= s.c1 && ci <= s.c2\n return { 'cell-selected': inSel, 'row-data-bg': rows.value[ri]!.type === 'data' }\n}\n\n// ─── 选区交互 ───\n\nconst dragAnchor = ref<{ r: number; c: number } | null>(null)\n\nfunction applySelection(a: { r: number; c: number }, b: { r: number; c: number }) {\n const rect = normalizeSelection(rows.value, a, b)\n editCtx.setTableSelection({ elementId: props.element.id, ...rect })\n}\n\nfunction onCellMouseDown(r: number, c: number, e: MouseEvent) {\n if (!props.designMode || !props.isSelected) return\n e.stopPropagation() // 阻止画布拖拽元素\n if (e.shiftKey && selection.value) {\n applySelection({ r: selection.value.r1, c: selection.value.c1 }, { r, c })\n } else {\n dragAnchor.value = { r, c }\n applySelection({ r, c }, { r, c })\n }\n window.addEventListener('mouseup', () => { dragAnchor.value = null }, { once: true })\n}\n\nfunction onCellMouseEnter(r: number, c: number) {\n if (dragAnchor.value) applySelection(dragAnchor.value, { r, c })\n}\n\n// ─── 双击编辑 ───\n\nfunction onCellDblClick(r: number, c: number) {\n if (!props.designMode) return\n // 单元格双击:上报单元格坐标,由 PrintDesigner 打开该单元格的表达式编辑器\n emit('dblclick-cell', props.element.id, r, c)\n}\n\n// ─── 右键菜单 ───\n\nconst menu = reactive({ visible: false, x: 0, y: 0 })\n\nfunction onCellContextMenu(r: number, c: number, e: MouseEvent) {\n if (!props.designMode || !props.isSelected) return\n const s = selection.value\n const inSel = s && r >= s.r1 && r <= s.r2 && c >= s.c1 && c <= s.c2\n if (!inSel) applySelection({ r, c }, { r, c })\n menu.x = e.clientX\n menu.y = e.clientY\n menu.visible = true\n window.addEventListener('mousedown', () => { menu.visible = false }, { once: true })\n}\n\nconst mergeReason = computed(() => {\n const s = selection.value\n if (!s) return '未选择单元格'\n return canMergeReason(rows.value, s)\n})\n\nconst canSplit = computed(() => {\n const s = selection.value\n if (!s) return false\n for (let r = s.r1; r <= s.r2; r++) {\n for (let c = s.c1; c <= s.c2; c++) {\n const cell = rows.value[r]!.cells[c]!\n if (!cell.merged && ((cell.rowspan ?? 1) > 1 || (cell.colspan ?? 1) > 1)) return true\n }\n }\n return false\n})\n\nfunction rowTypeReason(t: TableRowType): string | null {\n const s = selection.value\n if (!s) return '未选择单元格'\n if (s.r1 !== s.r2) return '行类型仅支持单行设置'\n // 试算校验:在 JSON 深拷贝上执行(兼容 reactive Proxy)\n const cloned = JSON.parse(JSON.stringify(rows.value)) as TableRow[]\n return setRowType(cloned, s.r1, t)\n}\n\nfunction syncElementSize() {\n // 尺寸派生统一走共享函数:width/height 恒为列宽和/行高和(mm)\n syncTableElementSize(props.element.options)\n}\n\n/** 插入列前检查:新列复制相邻列宽,总列宽不得超过页面打印范围宽度 */\nfunction checkColWidthLimit(cw: number[], index: number): string | null {\n const maxW = editCtx.maxTableWidth.value\n const totalW = cw.reduce((s, w) => s + w, 0) + cw[index]!\n if (totalW > maxW) {\n return `插入后表格总宽 ${Math.round(totalW * 10) / 10}mm 超过打印范围宽度 ${maxW}mm,请先缩小列宽`\n }\n return null\n}\n\nfunction onMenuAction(name: string, payload?: string) {\n const s = selection.value\n if (!s) return\n menu.visible = false\n const o = props.element.options\n const rs = o.tableRows!\n const cw = o.tableColWidths!\n let err: string | null = null\n switch (name) {\n case 'insert-row-above': insertRow(rs, s.r1, 'above'); break\n case 'insert-row-below': insertRow(rs, s.r2, 'below'); break\n case 'delete-row': err = deleteRow(rs, s.r1); break\n case 'insert-col-left': err = checkColWidthLimit(cw, s.c1); if (!err) insertCol(rs, cw, s.c1, 'left'); break\n case 'insert-col-right': err = checkColWidthLimit(cw, s.c2); if (!err) insertCol(rs, cw, s.c2, 'right'); break\n case 'delete-col': err = deleteCol(rs, cw, s.c1); break\n case 'merge': mergeCells(rs, s); break\n case 'split': splitCells(rs, s); break\n case 'set-row-type':\n err = setRowType(rs, s.r1, payload as TableRowType)\n break\n }\n if (err) {\n alert(err)\n return\n }\n editCtx.setTableSelection(null) // 结构变化后选区坐标失效,清空\n syncElementSize()\n editCtx.recordHistory()\n}\n</script>\n\n<style scoped>\n.print-table {\n position: relative;\n width: 100%;\n height: 100%;\n}\n.print-table table {\n border-collapse: collapse;\n table-layout: fixed;\n width: 100%;\n}\n.print-table td {\n box-sizing: border-box;\n word-break: break-all;\n}\n.cell-selected {\n outline: 2px solid #165DFF;\n outline-offset: -2px;\n background-color: rgba(22, 93, 255, 0.08);\n}\n.row-data-bg {\n background-image: repeating-linear-gradient(\n 45deg,\n rgba(22, 93, 255, 0.04) 0 6px,\n transparent 6px 12px\n );\n}\n.data-placeholder {\n color: #909399;\n font-style: italic;\n}\n.cell-editor {\n width: 100%;\n border: none;\n outline: none;\n background: #fffbe6;\n font: inherit;\n}\n.row-badges {\n position: absolute;\n left: -16px;\n top: 0;\n width: 14px;\n}\n.row-badge {\n position: absolute;\n width: 14px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 10px;\n color: #909399;\n background: #f5f7fa;\n border-radius: 2px;\n}\n</style>\n","<template>\n <div class=\"print-line\" :style=\"lineStyle\" />\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport type { RuntimeElement } from '../../types'\n\nconst props = defineProps<{\n element: RuntimeElement\n}>()\n\nconst isHline = computed(() => props.element.printElementType.type === 'hline')\n\nconst lineStyle = computed(() => {\n const o = props.element.options\n const bw = (o.borderWidth || 0.75) + 'pt'\n const bs = o.borderStyle || 'solid'\n const bc = o.borderColor || '#333'\n if (isHline.value) {\n return { width: '100%', height: '0', borderTop: `${bw} ${bs} ${bc}`, boxSizing: 'border-box' as const }\n }\n return { width: '0', height: '100%', borderLeft: `${bw} ${bs} ${bc}`, boxSizing: 'border-box' as const }\n})\n</script>","<template>\n <div class=\"print-shape\" :style=\"shapeStyle\" />\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport type { RuntimeElement } from '../../types'\n\nconst props = defineProps<{\n element: RuntimeElement\n}>()\n\nconst isOval = computed(() => props.element.printElementType.type === 'oval')\n\nconst shapeStyle = computed(() => {\n const o = props.element.options\n return {\n width: '100%',\n height: '100%',\n borderWidth: (o.borderWidth || 1) + 'pt',\n borderStyle: (o.borderStyle || 'solid') as string,\n borderColor: o.borderColor || '#333',\n backgroundColor: o.backgroundColor || 'transparent',\n borderRadius: isOval.value ? '50%' : '0',\n boxSizing: 'border-box' as const,\n }\n})\n</script>\n","<template>\n <div class=\"print-barcode\" ref=\"containerRef\">\n <svg ref=\"svgRef\" preserveAspectRatio=\"xMidYMid meet\"></svg>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, onMounted, watch } from 'vue'\nimport JsBarcode from 'jsbarcode'\nimport { resolveTextBinding } from '../../utils/binding'\nimport type { RuntimeElement } from '../../types'\n\nconst props = defineProps<{\n element: RuntimeElement\n data?: Record<string, any>[]\n designMode?: boolean\n}>()\n\nconst svgRef = ref<SVGSVGElement | null>(null)\n\n// 画布元素尺寸单位为 mm,浏览器 96dpi 下 1mm = 96/25.4 px\nconst MM_TO_PX = 96 / 25.4\n\nfunction render() {\n if (!svgRef.value) return\n const o = props.element.options\n const value = (props.designMode ? (o.testData || o.formatter) : resolveTextBinding(o, props.data)) || '条码'\n const showText = !o.hideTitle\n const fontSizePx = (o.fontSize || 12) * (96 / 72) // pt → px\n const totalPx = (o.height || 40) * MM_TO_PX // 元素高度 mm → px\n const textH = showText ? fontSizePx + 4 : 0 // 文本区预留\n const barH = Math.max(8, totalPx - textH) // 条码图形高度\n try {\n JsBarcode(svgRef.value, value, {\n format: (o.barcodeType || 'CODE128') as any,\n width: o.barWidth ? o.barWidth / 2 : 1,\n height: barH,\n displayValue: showText,\n fontSize: fontSizePx,\n margin: 2,\n })\n } catch { /* ignore render errors */ }\n}\n\nonMounted(render)\nwatch(\n () => [\n props.element.options.formatter,\n props.element.options.testData,\n props.element.options.barcodeType,\n props.element.options.width,\n props.element.options.height,\n props.element.options.barWidth,\n props.element.options.hideTitle,\n props.element.options.fontSize,\n ],\n render,\n)\n</script>\n\n<style scoped>\n.print-barcode { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; overflow: hidden; }\n/* JsBarcode 生成的 svg 自带 viewBox,width/height 100% 时等比缩放填满容器,随元素宽高变化 */\n.print-barcode svg { width: 100%; height: 100%; }\n</style>\n","<template>\n <div class=\"print-qrcode\">\n <img v-if=\"dataUrl\" :src=\"dataUrl\" alt=\"qrcode\" />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, onMounted, watch } from 'vue'\nimport QRCode from 'qrcode'\nimport { resolveTextBinding } from '../../utils/binding'\nimport type { RuntimeElement } from '../../types'\n\nconst props = defineProps<{\n element: RuntimeElement\n data?: Record<string, any>[]\n designMode?: boolean\n}>()\n\n// 改用 toDataURL 渲染为 <img>:纳入统一图片加载屏障,规避 canvas 在 PDF 中偶发空白\nconst dataUrl = ref('')\n\nasync function render() {\n const o = props.element.options\n const value = (props.designMode ? (o.testData || o.formatter) : resolveTextBinding(o, props.data)) || '二维码'\n const size = Math.min(o.width || 80, o.height || 80)\n try {\n dataUrl.value = await QRCode.toDataURL(value, {\n width: size,\n margin: 1,\n errorCorrectionLevel: (String(o.qrCodeLevel ?? 'M') as 'L' | 'M' | 'Q' | 'H'),\n })\n } catch {\n dataUrl.value = ''\n }\n}\n\nonMounted(render)\nwatch(() => [props.element.options.formatter, props.element.options.testData], render)\n</script>\n\n<style scoped>\n.print-qrcode { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; overflow: hidden; }\n.print-qrcode img { max-width: 100%; max-height: 100%; }\n</style>\n","<template>\n <div class=\"print-html\" v-html=\"htmlContent\" />\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport DOMPurify from 'dompurify'\nimport type { RuntimeElement } from '../../types'\nimport { evaluateTemplate } from '../../utils/expression-eval'\n\nconst props = defineProps<{\n element: RuntimeElement\n data?: Record<string, any>[]\n designMode?: boolean\n}>()\n\nconst htmlContent = computed(() => {\n if (props.element.options.formatter) {\n const row = props.data && props.data.length > 0 ? props.data[0] : {}\n const result = evaluateTemplate(props.element.options.formatter, row ?? {})\n return result ? DOMPurify.sanitize(result) : ''\n }\n return '<div style=\"background:#e0e0e0;width:100%;height:100%;display:flex;align-items:center;justify-content:center;font-size:10pt;color:#999\">HTML</div>'\n})\n</script>\n\n<style scoped>\n.print-html { width: 100%; height: 100%; overflow: hidden; }\n</style>\n","<template>\n <div class=\"page-number-element\" :style=\"textStyle\">\n {{ displayText }}\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport type { RuntimeElement } from '../../types'\n\nconst props = defineProps<{\n element: RuntimeElement\n data?: Record<string, any>[]\n designMode?: boolean\n}>()\n\nconst textStyle = computed(() => {\n const o = props.element.options\n return {\n fontSize: (o.fontSize || 12) + 'pt',\n fontWeight: o.fontWeight || 'normal',\n fontFamily: o.fontFamily || 'inherit',\n color: o.color || '#333',\n textAlign: (o.textAlign || 'left') as 'left' | 'center' | 'right',\n lineHeight: o.lineHeight ? o.lineHeight + 'pt' : 'normal',\n letterSpacing: o.letterSpacing ? o.letterSpacing + 'pt' : 'normal',\n }\n})\n\nconst displayText = computed(() => {\n if (props.designMode) {\n return props.element.options.title || '{pageIndex}/{totalPages}'\n }\n // 运行时由 print-render 渲染端按分页填充 {pageIndex}/{totalPages}\n return props.element.options.title || ''\n})\n</script>\n\n<style scoped>\n.page-number-element {\n width: 100%;\n height: 100%;\n overflow: hidden;\n}\n</style>\n","<template>\n <div\n ref=\"elRef\"\n class=\"print-element\"\n :class=\"{\n selected: isSelected,\n previewed: isPreviewed,\n 'design-mode': designMode,\n locked: element.options.locked,\n hidden: element.options.visible === false,\n 'drag-ghost': isDragging,\n [`type-${element.printElementType.type}`]: true,\n [`zone-${zone || 'content'}`]: true,\n }\"\n :style=\"elementStyle\"\n @mousedown.stop=\"onMouseDown\"\n @dblclick.stop=\"onDblClick\"\n @contextmenu.prevent.stop=\"$emit('contextmenu', element.id, $event)\"\n >\n <component\n :is=\"contentComponent\"\n :element=\"element\"\n :data=\"printData\"\n :design-mode=\"designMode\"\n :is-selected=\"isSelected\"\n v-bind=\"contentAttrs\"\n @dblclick-cell=\"onDblClickCell\"\n />\n\n <!-- 拖拽半透明预览副本 -->\n <div v-if=\"isDragging\" class=\"drag-preview\" />\n\n <div v-if=\"resizeEnabled\" class=\"resize-handles\">\n <div\n v-for=\"p in RESIZE_POINTS\"\n :key=\"p\"\n :class=\"['resize-handle', `handle-${p}`]\"\n @mousedown.stop=\"startResize(p, $event)\"\n />\n </div>\n\n <div v-if=\"isSelected && designMode\" class=\"selected-indicator\">\n <div class=\"position-label\">{{ posLabel }}</div>\n </div>\n <div v-if=\"designMode && bindingState\" class=\"binding-badge\" :style=\"{ color: bindingState.badgeColor }\">\n {{ bindingState.badge }}\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, inject, markRaw, reactive, ref, watchEffect, onMounted, onUnmounted } from 'vue'\nimport type { RuntimeElement, ElementRect, AdsorbResult } from '../../types'\nimport { useDrag } from '../../composables/useDrag'\nimport type { DragOptions } from '../../composables/useDrag'\nimport { generateId } from '../../utils/element-factory'\nimport { useResize, RESIZE_POINTS } from '../../composables/useResize'\nimport { useBindingDisplay } from '../../composables/useBindingDisplay'\nimport { SELECTED_IDS_KEY, PREVIEW_IDS_KEY } from '../../composables/useSelection'\nimport TextElement from './TextElement.vue'\nimport ImageElement from './ImageElement.vue'\nimport LongTextElement from './LongTextElement.vue'\nimport TableElement from './TableElement.vue'\nimport LineElement from './LineElement.vue'\nimport ShapeElement from './ShapeElement.vue'\nimport BarcodeElement from './BarcodeElement.vue'\nimport QrcodeElement from './QrcodeElement.vue'\nimport HtmlElement from './HtmlElement.vue'\nimport PageNumberElement from './PageNumberElement.vue'\n\nconst props = defineProps<{\n element: RuntimeElement\n /** @deprecated 通过 inject 获取,保留用于向后兼容 */\n isSelected?: boolean\n designMode?: boolean\n printData?: Record<string, any>[]\n scale?: number\n allElements?: RuntimeElement[]\n snapToGrid?: boolean\n /** 设计态下无边框表格单元格的虚拟虚线开关(透传给 TableElement) */\n showTableGhostBorder?: boolean\n /** 元素所在区域(影响设计态边框颜色) */\n zone?: 'content' | 'header' | 'footer' | 'overlay'\n /** 由 CanvasPaper 层吸附管理器提供:同步返回吸附修正结果并渲染引导线 */\n adsorbHandler?: (rect: ElementRect) => AdsorbResult\n clearAdsorbGuides?: () => void\n}>()\n\nconst emit = defineEmits<{\n select: [id: string, multiple: boolean]\n 'update:element': [element: RuntimeElement]\n 'drag-start': []\n 'drag-stop': []\n 'dblclick-element': [id: string]\n 'dblclick-cell': [elementId: string, r: number, c: number]\n 'contextmenu': [id: string, e: MouseEvent]\n 'clone-element': [element: RuntimeElement, position: { left: number; top: number }]\n}>()\n\nconst elRef = ref<HTMLElement | null>(null)\n\n// 通过 inject 精确追踪自身选中状态,避免父组件因 selectedIds 变化全量重渲染\nconst injectedSelectedIds = inject(SELECTED_IDS_KEY, null)\nconst isSelected = computed(() => {\n if (injectedSelectedIds?.value) {\n return injectedSelectedIds.value.has(props.element.id)\n }\n return props.isSelected ?? false\n})\n\n// 框选实时预选高亮(未提交前)\nconst injectedPreviewIds = inject(PREVIEW_IDS_KEY, null)\nconst isPreviewed = computed(() => injectedPreviewIds?.value.has(props.element.id) ?? false)\n\nconst componentMap: Record<string, any> = {\n text: markRaw(TextElement),\n image: markRaw(ImageElement),\n longText: markRaw(LongTextElement),\n table: markRaw(TableElement),\n hline: markRaw(LineElement),\n vline: markRaw(LineElement),\n rect: markRaw(ShapeElement),\n oval: markRaw(ShapeElement),\n barcode: markRaw(BarcodeElement),\n qrcode: markRaw(QrcodeElement),\n html: markRaw(HtmlElement),\n pageNumber: markRaw(PageNumberElement),\n}\n\nconst { getBindingDisplayState } = useBindingDisplay()\n\nconst bindingState = computed(() => {\n if (!props.designMode) return null\n return getBindingDisplayState(props.element)\n})\n\nconst contentComponent = computed(() => componentMap[props.element.printElementType.type])\n\n/** 仅表格元素需要虚拟虚线开关,避免其它元素根节点出现无关 attribute */\nconst contentAttrs = computed(() =>\n props.element.printElementType.type === 'table'\n ? { showTableGhostBorder: props.showTableGhostBorder }\n : {},\n)\n\nconst elementStyle = computed(() => {\n const o = props.element.options\n return {\n position: 'absolute' as const,\n left: o.left + 'mm',\n top: o.top + 'mm',\n width: o.width + 'mm',\n height: o.height + 'mm',\n zIndex: o.zIndex || 'auto',\n }\n})\n\nconst posLabel = computed(() => {\n const o = props.element.options\n return `x:${Math.round(o.left)} y:${Math.round(o.top)} ${Math.round(o.width)}×${Math.round(o.height)}mm`\n})\n\n// 吸附检测与引导线由 CanvasPaper 层的 useAdsorbManager 统一管理\n\n// 拖拽:拖拽期间用 CSS transform 做视觉跟随,不触发响应式更新;\n// mouseup 时通过 onDragEnd 一次性写入最终坐标。\nlet dragStartLeft = 0\nlet dragStartTop = 0\nconst dragConfig = reactive<DragOptions>({\n disabled: !props.designMode || !!props.element.options.locked,\n getScale: () => props.scale || 1,\n // 拖拽中:仅设置 style.transform,不修改响应式数据\n onDrag: (pos) => {\n const dx = pos.left - dragStartLeft\n const dy = pos.top - dragStartTop\n if (elRef.value) {\n elRef.value.style.transform = `translate(${dx}mm, ${dy}mm)`\n }\n // 同组元素拖拽跟随:拖拽期间不处理,mouseup 时通过 onDragEnd 一次性更新响应式坐标\n },\n // 拖拽结束:一次性写入最终坐标,清除 transform\n onDragEnd: (pos, info) => {\n // Alt+拖拽:在落点生成副本,原元素留在原位不动\n if (info.altKey) {\n const clone = JSON.parse(JSON.stringify(props.element)) as RuntimeElement\n clone.id = generateId()\n clone.options.left = pos.left\n clone.options.top = pos.top\n // 通过 emit 事件通知父组件处理克隆,而非直接操作 props\n emit('clone-element', clone, { left: pos.left, top: pos.top })\n if (elRef.value) {\n elRef.value.style.transform = ''\n }\n return\n }\n const finalDx = pos.left - dragStartLeft\n const finalDy = pos.top - dragStartTop\n // 写入主元素响应式坐标\n props.element.options.left = pos.left\n props.element.options.top = pos.top\n if (elRef.value) {\n elRef.value.style.transform = ''\n }\n // 同组元素一次性更新坐标(响应式写入,Vue 自动刷新 DOM)\n if (props.element.options.groupId && props.allElements) {\n for (const sibling of props.allElements) {\n if (sibling.id !== props.element.id && sibling.options.groupId === props.element.options.groupId) {\n sibling.options.left += finalDx\n sibling.options.top += finalDy\n }\n }\n }\n },\n onStart: () => {\n // 记录拖拽起始坐标(用于计算 transform 偏移量)\n dragStartLeft = props.element.options.left\n dragStartTop = props.element.options.top\n emit('select', props.element.id, false)\n emit('drag-start')\n },\n onStop: () => {\n props.clearAdsorbGuides?.()\n emit('drag-stop')\n },\n onAdsorb: (pos) => {\n // 网格吸附\n let left = pos.left\n let top = pos.top\n if (props.snapToGrid) {\n const grid = 5 // 5mm\n left = Math.round(pos.left / grid) * grid\n top = Math.round(pos.top / grid) * grid\n }\n\n // 元素间吸附交给 CanvasPaper 层管理器(含引导线渲染)\n if (props.adsorbHandler) {\n return props.adsorbHandler({\n id: props.element.id,\n left,\n top,\n width: props.element.options.width,\n height: props.element.options.height,\n })\n }\n return { left, top, lines: [] }\n },\n})\nconst { setup: setupDrag, cleanup: cleanupDrag, isDragging } = useDrag(elRef, dragConfig)\n\n// 锁定/设计态变化时自动同步拖拽禁用标志(useDrag.onMouseDown 实时读取 dragConfig.disabled)\nwatchEffect(() => {\n dragConfig.disabled = !props.designMode || !!props.element.options.locked\n})\n\n// 缩放:手柄由模板渲染,resizeEnabled 控制显隐;table 尺寸由列宽/行高派生,禁用缩放\nconst resizeEnabled = computed(\n () =>\n isSelected.value &&\n !!props.designMode &&\n !props.element.options.locked &&\n props.element.printElementType.type !== 'table',\n)\n\nconst { startResize, cleanup: cleanupResize } = useResize({\n minWidth: 3.5,\n minHeight: 3.5,\n getScale: () => props.scale || 1,\n getRect: () => ({\n left: props.element.options.left,\n top: props.element.options.top,\n width: props.element.options.width,\n height: props.element.options.height,\n }),\n onResize: (rect) => {\n props.element.options.left = rect.left\n props.element.options.top = rect.top\n props.element.options.width = rect.width\n props.element.options.height = rect.height\n },\n // 复用 drag-start/drag-stop 事件链记录历史:onStart 记录缩放前快照,\n // onStop 触发 PrintDesigner.onDragStop 的前后对比(含 width/height)入栈。\n onStart: () => {\n emit('drag-start')\n },\n onStop: () => {\n emit('drag-stop')\n },\n})\n\nfunction onMouseDown(e: MouseEvent) {\n if (!props.designMode) return\n emit('select', props.element.id, e.ctrlKey || e.metaKey)\n}\n\nfunction onDblClick() {\n if (!props.designMode) return\n emit('dblclick-element', props.element.id)\n}\n\n/** 表格单元格双击转发(仅表格元素的 TableElement 会触发) */\nfunction onDblClickCell(elementId: string, r: number, c: number) {\n if (!props.designMode) return\n emit('dblclick-cell', elementId, r, c)\n}\n\nonMounted(() => {\n // 始终挂载拖拽监听:useDrag.onMouseDown 在事件触发时实时读取 dragConfig.disabled,\n // 即使元素加载时 locked:true 也能正确门控;解锁后 locked watcher 更新 disabled 即生效。\n if (props.designMode) {\n setupDrag()\n }\n})\n\nfunction cleanup() {\n cleanupDrag()\n cleanupResize()\n props.clearAdsorbGuides?.()\n}\n\nonUnmounted(() => {\n cleanup()\n})\n</script>\n\n<style scoped>\n.print-element {\n box-sizing: border-box;\n cursor: pointer;\n user-select: none;\n}\n/* 设计态下所有元素显示浅灰虚线边框,标示占位空间大小 */\n.print-element.design-mode {\n outline: 1px dashed #C3C9D6;\n}\n/* 页眉/页脚区域元素:油墨绿虚线 */\n.print-element.design-mode.zone-header,\n.print-element.design-mode.zone-footer {\n outline: 1px dashed var(--pd-ink-green, #67c23a);\n}\n/* 首页叠加区域元素:青色虚线 */\n.print-element.design-mode.zone-overlay {\n outline: 1px dashed #06B6D4;\n}\n.print-element.selected {\n outline: 1.5px solid var(--pd-accent, #165DFF);\n background: rgba(22, 93, 255, 0.04);\n}\n/* 框选实时预选:墨蓝高亮(未提交) */\n.print-element.previewed {\n outline: 1.5px solid rgba(22, 93, 255, 0.5);\n background: rgba(22, 93, 255, 0.1);\n}\n.print-element.design-mode:hover {\n outline: 1px dashed var(--pd-accent, #165DFF);\n}\n.print-element.locked {\n cursor: not-allowed;\n}\n.print-element.locked:not(.selected) {\n outline: 1.5px dashed #999;\n}\n.print-element.hidden {\n opacity: 0.3;\n pointer-events: none;\n}\n/* 拖拽半透明预览:拖拽中元素变淡,叠加虚线副本框 */\n.print-element.drag-ghost {\n opacity: 0.4;\n}\n.drag-preview {\n position: absolute;\n inset: 0;\n border: 2px dashed var(--pd-accent, #165DFF);\n pointer-events: none;\n z-index: 1000;\n box-sizing: border-box;\n}\n.selected-indicator {\n position: absolute;\n top: -18px;\n left: 0;\n font-size: 10px;\n white-space: nowrap;\n pointer-events: none;\n z-index: 20;\n}\n.position-label {\n background: var(--pd-accent, #165DFF);\n color: #fff;\n padding: 1px 6px;\n border-radius: 3px;\n font-family: ui-monospace, 'SF Mono', Menlo, monospace;\n font-size: 10px;\n font-variant-numeric: tabular-nums;\n letter-spacing: 0;\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);\n}\n.binding-badge {\n position: absolute;\n top: -1px;\n left: -1px;\n font-size: 9px;\n font-family: monospace;\n padding: 1px 4px;\n background: rgba(255, 255, 255, 0.92);\n border: 1px solid currentColor;\n border-radius: 2px;\n line-height: 1.4;\n max-width: calc(100% - 4px);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n pointer-events: none;\n z-index: 1;\n}\n.resize-handles {\n position: absolute;\n inset: 0;\n pointer-events: none;\n}\n.resize-handle {\n position: absolute;\n width: 7px;\n height: 7px;\n background: var(--pd-handle, #165DFF);\n border: 1.5px solid #fff;\n border-radius: 2px;\n box-sizing: border-box;\n transform: translate(-50%, -50%);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.18);\n z-index: 10;\n pointer-events: auto;\n}\n.handle-nw { top: 0; left: 0; cursor: nw-resize; }\n.handle-n { top: 0; left: 50%; cursor: n-resize; }\n.handle-ne { top: 0; left: 100%; cursor: ne-resize; }\n.handle-e { top: 50%; left: 100%; cursor: e-resize; }\n.handle-se { top: 100%; left: 100%; cursor: se-resize; }\n.handle-s { top: 100%; left: 50%; cursor: s-resize; }\n.handle-sw { top: 100%; left: 0; cursor: sw-resize; }\n.handle-w { top: 50%; left: 0; cursor: w-resize; }\n</style>\n","export interface RulerTick {\n mm: number\n major: boolean\n label?: string\n}\n\n/** 生成标尺刻度:5mm 小刻度,10mm 大刻度 + 数字标签 */\nexport function buildRulerTicks(lengthMM: number): RulerTick[] {\n const ticks: RulerTick[] = []\n for (let mm = 0; mm <= lengthMM + 1e-9; mm += 5) {\n const rounded = Math.round(mm * 100) / 100\n const major = rounded % 10 === 0\n if (major) {\n ticks.push({ mm: rounded, major, label: String(rounded) })\n } else {\n ticks.push({ mm: rounded, major })\n }\n }\n return ticks\n}\n","<template>\n <canvas ref=\"canvasRef\" class=\"pd-ruler\" :style=\"cssSize\" @mousedown=\"onDown\" />\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, watch, onMounted } from 'vue'\nimport { buildRulerTicks } from '../utils/ruler'\n\nconst MM_TO_PX = 96 / 25.4\nconst THICKNESS = 16\n\nconst props = defineProps<{\n orientation: 'horizontal' | 'vertical'\n lengthMM: number\n scale?: number\n}>()\nconst emit = defineEmits<{ 'add-guide': [type: 'vertical' | 'horizontal', positionMm: number] }>()\n\nconst canvasRef = ref<HTMLCanvasElement | null>(null)\n\nconst cssSize = computed(() => {\n if (props.orientation === 'horizontal') {\n return { width: props.lengthMM + 'mm', height: THICKNESS + 'px' }\n }\n return { width: THICKNESS + 'px', height: props.lengthMM + 'mm' }\n})\n\nfunction draw() {\n const canvas = canvasRef.value\n if (!canvas) return\n const dpr = window.devicePixelRatio || 1\n const lengthPx = props.lengthMM * MM_TO_PX\n const horizontal = props.orientation === 'horizontal'\n canvas.width = (horizontal ? lengthPx : THICKNESS) * dpr\n canvas.height = (horizontal ? THICKNESS : lengthPx) * dpr\n const ctx = canvas.getContext('2d')\n if (!ctx) return\n ctx.scale(dpr, dpr)\n\n const style = getComputedStyle(canvas)\n const bg = style.getPropertyValue('--pd-ruler-bg').trim() || '#FFFFFF'\n const fg = style.getPropertyValue('--pd-ruler').trim() || '#9CA3AF'\n\n ctx.fillStyle = bg\n ctx.fillRect(0, 0, horizontal ? lengthPx : THICKNESS, horizontal ? THICKNESS : lengthPx)\n\n ctx.strokeStyle = fg\n ctx.fillStyle = fg\n ctx.lineWidth = 1\n ctx.font = '8px ui-monospace, Menlo, monospace'\n\n for (const tick of buildRulerTicks(props.lengthMM)) {\n const pos = Math.round(tick.mm * MM_TO_PX) + 0.5\n const len = tick.major ? 8 : 4\n ctx.beginPath()\n if (horizontal) {\n ctx.moveTo(pos, 0)\n ctx.lineTo(pos, len)\n } else {\n ctx.moveTo(0, pos)\n ctx.lineTo(len, pos)\n }\n ctx.stroke()\n if (tick.major && tick.label) {\n if (horizontal) {\n ctx.fillText(tick.label, pos + 2, 14)\n } else {\n ctx.save()\n ctx.translate(12, pos + 2)\n ctx.rotate(-Math.PI / 2)\n ctx.fillText(tick.label, -ctx.measureText(tick.label).width, 0)\n ctx.restore()\n }\n }\n }\n}\n\nwatch(() => [props.lengthMM, props.orientation], draw)\nonMounted(draw)\n\n// ─── 拖出生成参考线 ───\nlet dragging = false\nfunction onDown(e: MouseEvent) {\n dragging = true\n e.preventDefault()\n window.addEventListener('mousemove', onMove)\n window.addEventListener('mouseup', onUp)\n}\nfunction onMove() {\n // 拖动中不显示预览,mouseup 时生成\n}\nfunction onUp(e: MouseEvent) {\n if (!dragging) return\n dragging = false\n window.removeEventListener('mousemove', onMove)\n window.removeEventListener('mouseup', onUp)\n const canvas = canvasRef.value\n if (!canvas) return\n const rect = canvas.getBoundingClientRect()\n const s = props.scale ?? 1\n const offset = props.orientation === 'horizontal'\n ? (e.clientX - rect.left) / s\n : (e.clientY - rect.top) / s\n const posMM = offset / MM_TO_PX\n if (posMM > 0 && posMM < props.lengthMM) {\n emit('add-guide', props.orientation === 'horizontal' ? 'horizontal' : 'vertical', posMM)\n }\n}\n</script>\n\n<style scoped>\n.pd-ruler {\n position: absolute;\n top: 0;\n left: 0;\n pointer-events: auto;\n cursor: crosshair;\n z-index: 5;\n display: block;\n}\n/* 横尺压下沿、竖尺压右沿,构成 L 型制图尺框 */\n.pd-ruler:nth-of-type(1) {\n box-shadow: 0 1px 0 var(--pd-border-soft, #e9ecf2);\n}\n.pd-ruler:nth-of-type(2) {\n box-shadow: 1px 0 0 var(--pd-border-soft, #e9ecf2);\n}\n</style>\n","// web/src/components/print/composables/useAdsorb.ts\nimport { ref, type Ref } from 'vue'\nimport type { ElementRect, AlignLine, AdsorbResult } from '../types'\n\nexport interface AdsorbConfig {\n adsorbMin?: number\n adsorbLineMin?: number\n showAdsorbLine?: boolean\n}\n\nexport function useAdsorb(config: AdsorbConfig = {}) {\n const adsorbMin = config.adsorbMin ?? 1\n const adsorbLineMin = config.adsorbLineMin ?? 2\n const showAdsorbLine = config.showAdsorbLine ?? true\n\n /** 引导线响应式数据,由模板 v-for 渲染 */\n const guideLines: Ref<AlignLine[]> = ref([])\n\n /** 纸张尺寸(mm),用于引导线贯穿整页 */\n const paperSize = ref({ width: 0, height: 0 })\n\n /** 对齐类型颜色:左/顶端蓝,居中绿,右/底橘 */\n const SNAP_COLORS: Record<'left' | 'center' | 'right' | 'top' | 'middle' | 'bottom', string> = {\n left: '#3b82f6',\n center: '#10b981',\n right: '#f59e0b',\n top: '#3b82f6',\n middle: '#10b981',\n bottom: '#f59e0b',\n }\n\n /** 根据移动元素对齐点(mk)返回引导线颜色 */\n function snapColor(mk: string): string {\n if (mk === 'vCenter') return SNAP_COLORS.center\n if (mk === 'hCenter') return SNAP_COLORS.middle\n return SNAP_COLORS[mk as keyof typeof SNAP_COLORS] ?? SNAP_COLORS.left\n }\n\n function check(\n movingRect: ElementRect,\n others: ElementRect[],\n guideLines?: { vertical: number[]; horizontal: number[] },\n ): AdsorbResult {\n let left = movingRect.left\n let top = movingRect.top\n const lines: AlignLine[] = []\n\n const m = {\n left: movingRect.left,\n right: movingRect.left + movingRect.width,\n vCenter: movingRect.left + movingRect.width / 2,\n top: movingRect.top,\n bottom: movingRect.top + movingRect.height,\n hCenter: movingRect.top + movingRect.height / 2,\n }\n\n let minDist = Infinity\n\n for (const other of others) {\n if (other.id === movingRect.id) continue\n const o = {\n left: other.left,\n right: other.left + other.width,\n vCenter: other.left + other.width / 2,\n top: other.top,\n bottom: other.top + other.height,\n hCenter: other.top + other.height / 2,\n }\n\n const hPairs: [keyof typeof m, keyof typeof o][] = [\n ['left', 'left'], ['left', 'vCenter'], ['left', 'right'],\n ['vCenter', 'left'], ['vCenter', 'vCenter'], ['vCenter', 'right'],\n ['right', 'left'], ['right', 'vCenter'], ['right', 'right'],\n ]\n const vPairs: [keyof typeof m, keyof typeof o][] = [\n ['top', 'top'], ['top', 'hCenter'], ['top', 'bottom'],\n ['hCenter', 'top'], ['hCenter', 'hCenter'], ['hCenter', 'bottom'],\n ['bottom', 'top'], ['bottom', 'hCenter'], ['bottom', 'bottom'],\n ]\n\n for (const [mk, ok] of hPairs) {\n const dist = Math.abs(m[mk] - o[ok])\n if (dist <= adsorbMin && dist < minDist) {\n minDist = dist\n left = movingRect.left + (o[ok] - m[mk])\n }\n }\n for (const [mk, ok] of vPairs) {\n const dist = Math.abs(m[mk] - o[ok])\n if (dist <= adsorbMin && dist < minDist) {\n minDist = dist\n top = movingRect.top + (o[ok] - m[mk])\n }\n }\n }\n\n // 手动参考线吸附:垂直参考线(position=X)参与水平方向,水平参考线参与垂直方向\n if (guideLines) {\n const m2 = {\n left, right: left + movingRect.width, vCenter: left + movingRect.width / 2,\n top, bottom: top + movingRect.height, hCenter: top + movingRect.height / 2,\n }\n const hKeys: (keyof typeof m2)[] = ['left', 'vCenter', 'right']\n for (const pos of guideLines.vertical) {\n for (const k of hKeys) {\n const d = Math.abs(m2[k] - pos)\n if (d <= adsorbMin && d < minDist) { minDist = d; left = movingRect.left + (pos - m2[k]) }\n }\n }\n const vKeys: (keyof typeof m2)[] = ['top', 'hCenter', 'bottom']\n for (const pos of guideLines.horizontal) {\n for (const k of vKeys) {\n const d = Math.abs(m2[k] - pos)\n if (d <= adsorbMin && d < minDist) { minDist = d; top = movingRect.top + (pos - m2[k]) }\n }\n }\n }\n\n const adjustedM = {\n left, right: left + movingRect.width,\n vCenter: left + movingRect.width / 2,\n top, bottom: top + movingRect.height,\n hCenter: top + movingRect.height / 2,\n }\n\n if (showAdsorbLine) {\n const seen = new Set<string>()\n for (const other of others) {\n if (other.id === movingRect.id) continue\n const o = {\n left: other.left,\n right: other.left + other.width,\n vCenter: other.left + other.width / 2,\n top: other.top,\n bottom: other.top + other.height,\n hCenter: other.top + other.height / 2,\n }\n\n const hPairs: [keyof typeof adjustedM, keyof typeof o][] = [\n ['left', 'left'], ['left', 'vCenter'], ['left', 'right'],\n ['vCenter', 'left'], ['vCenter', 'vCenter'], ['vCenter', 'right'],\n ['right', 'left'], ['right', 'vCenter'], ['right', 'right'],\n ]\n const vPairs: [keyof typeof adjustedM, keyof typeof o][] = [\n ['top', 'top'], ['top', 'hCenter'], ['top', 'bottom'],\n ['hCenter', 'top'], ['hCenter', 'hCenter'], ['hCenter', 'bottom'],\n ['bottom', 'top'], ['bottom', 'hCenter'], ['bottom', 'bottom'],\n ]\n\n for (const [mk, ok] of hPairs) {\n const dist = Math.abs(adjustedM[mk] - o[ok])\n // 吸附(dist <= adsorbMin)或近距(adsorbMin < dist <= adsorbLineMin)均绘制竖直引导线\n if (dist <= adsorbLineMin) {\n const key = `v:${o[ok]}`\n if (!seen.has(key)) {\n seen.add(key)\n lines.push({ type: 'vertical', position: o[ok], id: other.id, color: snapColor(mk) })\n }\n }\n }\n for (const [mk, ok] of vPairs) {\n const dist = Math.abs(adjustedM[mk] - o[ok])\n if (dist <= adsorbLineMin) {\n const key = `h:${o[ok]}`\n if (!seen.has(key)) {\n seen.add(key)\n lines.push({ type: 'horizontal', position: o[ok], id: other.id, color: snapColor(mk) })\n }\n }\n }\n }\n }\n\n if (guideLines) {\n for (const pos of guideLines.vertical) {\n if (!lines.some(l => l.type === 'vertical' && l.position === pos)) {\n lines.push({ type: 'vertical', position: pos })\n }\n }\n for (const pos of guideLines.horizontal) {\n if (!lines.some(l => l.type === 'horizontal' && l.position === pos)) {\n lines.push({ type: 'horizontal', position: pos })\n }\n }\n }\n\n return { left, top, lines }\n }\n\n /** 更新引导线(Vue 响应式,不再直接操作 DOM) */\n function renderLines(lines: AlignLine[], paperW: number, paperH: number) {\n guideLines.value = lines\n paperSize.value = { width: paperW, height: paperH }\n }\n\n /** 清除引导线 */\n function clearLines() {\n guideLines.value = []\n }\n\n return { check, renderLines, clearLines, guideLines, paperSize }\n}\n","// web/src/components/print/composables/useAdsorbManager.ts\n// 吸附管理器:在 CanvasPaper 层创建单例,统一处理吸附检测与引导线渲染\n// BaseElement 拖拽时通过函数 props 调用 requestAdsorb / clearGuides\nimport type { RuntimeElement, ElementRect, AdsorbResult } from '../types'\nimport { useAdsorb, type AdsorbConfig } from './useAdsorb'\n\nexport interface AdsorbManagerOptions {\n getElements: () => RuntimeElement[]\n /** 纸张尺寸(mm),用于引导线贯穿整页 */\n getPaperSize: () => { width: number; height: number }\n /** 手动参考线位置(mm),参与吸附 */\n getGuides?: () => { vertical: number[]; horizontal: number[] }\n config?: AdsorbConfig\n}\n\nexport function useAdsorbManager(options: AdsorbManagerOptions) {\n const { check, renderLines, clearLines, guideLines, paperSize } = useAdsorb(\n options.config ?? { adsorbMin: 1, adsorbLineMin: 2, showAdsorbLine: true }\n )\n\n function requestAdsorb(movingRect: ElementRect): AdsorbResult {\n const others = options.getElements()\n .filter(e => e.id !== movingRect.id)\n .map(e => ({\n id: e.id,\n left: e.options.left,\n top: e.options.top,\n width: e.options.width,\n height: e.options.height,\n } as ElementRect))\n const result = check(movingRect, others, options.getGuides?.())\n const paper = options.getPaperSize()\n renderLines(result.lines, paper.width, paper.height)\n return result\n }\n\n function clearGuides() {\n clearLines()\n }\n\n return { requestAdsorb, clearGuides, guideLines, paperSize }\n}\n","<template>\n <div\n class=\"hiprint-printPaper\"\n :style=\"paperStyle\"\n >\n <div\n class=\"hiprint-printPaper-content\"\n ref=\"contentRef\"\n :style=\"contentStyle\"\n >\n <!-- 刻度标尺 -->\n <template v-if=\"showRulerComputed\">\n <Ruler orientation=\"horizontal\" :length-m-m=\"paperWidthMM\" :scale=\"scale\" @add-guide=\"(t: 'vertical' | 'horizontal', p: number) => emit('add-guide', t, p)\" />\n <Ruler orientation=\"vertical\" :length-m-m=\"paperHeightMM\" :scale=\"scale\" @add-guide=\"(t: 'vertical' | 'horizontal', p: number) => emit('add-guide', t, p)\" />\n </template>\n <!-- 网格背景 -->\n <div\n v-if=\"showGrid && designMode\"\n class=\"grid-bg\"\n :style=\"gridBgStyle\"\n />\n <!-- 吸附高亮指示点(吸附发生时闪烁) -->\n <div\n v-if=\"snapIndicator\"\n :key=\"snapIndicator.key\"\n class=\"snap-indicator\"\n :style=\"{\n left: snapIndicator.left + 'mm',\n top: snapIndicator.top + 'mm',\n }\"\n />\n\n <!-- 水印渲染层(在所有元素之下) -->\n <div\n v-if=\"watermarkVisible\"\n class=\"watermark-layer\"\n :style=\"watermarkStyle\"\n />\n\n <!-- ─── 三段式区域层:上边距→页眉→内容→页脚→下边距 ─── -->\n <!-- 页眉层 -->\n <div\n class=\"zone-layer zone-header\"\n :class=\"{ 'design-mode': designMode }\"\n :style=\"layerStyle(zoneRectsMM.header)\"\n >\n <span v-if=\"designMode\" class=\"zone-label\">页眉</span>\n <BaseElement\n v-for=\"el in headerElements\"\n :key=\"el.id\"\n :element=\"el\"\n :design-mode=\"designMode\"\n :print-data=\"printData\"\n :scale=\"scale\"\n :all-elements=\"headerElements\"\n :snap-to-grid=\"snapToGrid\"\n :show-table-ghost-border=\"showTableGhostBorder\"\n zone=\"header\"\n :adsorb-handler=\"requestAdsorb\"\n :clear-adsorb-guides=\"clearGuides\"\n @select=\"onSelectElement\"\n @drag-start=\"$emit('drag-start')\"\n @drag-stop=\"$emit('drag-stop')\"\n @dblclick-element=\"(id: string) => $emit('dblclick-element', id)\"\n @dblclick-cell=\"(id: string, r: number, c: number) => $emit('dblclick-cell', id, r, c)\"\n @contextmenu=\"(id: string, e: MouseEvent) => $emit('contextmenu', id, e)\"\n @clone-element=\"(el, pos) => $emit('clone-element', el, pos)\"\n />\n <div\n v-if=\"designMode\"\n class=\"zone-resize-handle handle-bottom\"\n @mousedown.prevent.stop=\"startZoneResize('header', $event)\"\n >\n <div v-if=\"zoneResizing?.zone === 'header'\" class=\"zone-height-tip\">\n {{ templateData.header.height.toFixed(1) }}mm\n </div>\n </div>\n </div>\n\n <!-- 内容层 -->\n <div\n class=\"zone-layer zone-content\"\n :class=\"{ 'design-mode': designMode }\"\n :style=\"layerStyle(zoneRectsMM.content)\"\n >\n <!-- 首页叠加占位(本次不可编辑) -->\n <div\n v-if=\"designMode && templateData.firstPageOverlay.height > 0\"\n class=\"zone-overlay\"\n :style=\"{ height: templateData.firstPageOverlay.height + 'mm' }\"\n >\n <span class=\"zone-label\">首页叠加</span>\n </div>\n <BaseElement\n v-for=\"el in contentElements\"\n :key=\"el.id\"\n :element=\"el\"\n :design-mode=\"designMode\"\n :print-data=\"printData\"\n :scale=\"scale\"\n :all-elements=\"contentElements\"\n :snap-to-grid=\"snapToGrid\"\n :show-table-ghost-border=\"showTableGhostBorder\"\n zone=\"content\"\n :adsorb-handler=\"requestAdsorb\"\n :clear-adsorb-guides=\"clearGuides\"\n @select=\"onSelectElement\"\n @drag-start=\"$emit('drag-start')\"\n @drag-stop=\"$emit('drag-stop')\"\n @dblclick-element=\"(id: string) => $emit('dblclick-element', id)\"\n @dblclick-cell=\"(id: string, r: number, c: number) => $emit('dblclick-cell', id, r, c)\"\n @contextmenu=\"(id: string, e: MouseEvent) => $emit('contextmenu', id, e)\"\n @clone-element=\"(el, pos) => $emit('clone-element', el, pos)\"\n />\n </div>\n\n <!-- 页脚层 -->\n <div\n class=\"zone-layer zone-footer\"\n :class=\"{ 'design-mode': designMode }\"\n :style=\"layerStyle(zoneRectsMM.footer)\"\n >\n <span v-if=\"designMode\" class=\"zone-label\">页脚</span>\n <BaseElement\n v-for=\"el in footerElements\"\n :key=\"el.id\"\n :element=\"el\"\n :design-mode=\"designMode\"\n :print-data=\"printData\"\n :scale=\"scale\"\n :all-elements=\"footerElements\"\n :snap-to-grid=\"snapToGrid\"\n :show-table-ghost-border=\"showTableGhostBorder\"\n zone=\"footer\"\n :adsorb-handler=\"requestAdsorb\"\n :clear-adsorb-guides=\"clearGuides\"\n @select=\"onSelectElement\"\n @drag-start=\"$emit('drag-start')\"\n @drag-stop=\"$emit('drag-stop')\"\n @dblclick-element=\"(id: string) => $emit('dblclick-element', id)\"\n @dblclick-cell=\"(id: string, r: number, c: number) => $emit('dblclick-cell', id, r, c)\"\n @contextmenu=\"(id: string, e: MouseEvent) => $emit('contextmenu', id, e)\"\n @clone-element=\"(el, pos) => $emit('clone-element', el, pos)\"\n />\n <div\n v-if=\"designMode\"\n class=\"zone-resize-handle handle-top\"\n @mousedown.prevent.stop=\"startZoneResize('footer', $event)\"\n >\n <div v-if=\"zoneResizing?.zone === 'footer'\" class=\"zone-height-tip\">\n {{ templateData.footer.height.toFixed(1) }}mm\n </div>\n </div>\n </div>\n\n <!-- 吸附引导线(v-for 渲染,拖拽结束后自动清除) -->\n <div\n v-for=\"(line, idx) in guideLines\"\n :key=\"idx\"\n class=\"adsorb-guide\"\n :class=\"[`guide-${line.type}`]\"\n :style=\"line.type === 'vertical'\n ? { left: line.position + 'mm', top: '0', height: guidePaperSize.height + 'mm', borderLeftColor: line.color || 'var(--pd-accent-secondary, #f56c6c)' }\n : { top: line.position + 'mm', left: '0', width: guidePaperSize.width + 'mm', borderTopColor: line.color || 'var(--pd-accent-secondary, #f56c6c)' }\"\n />\n <!-- 手动参考线(常驻,可拖动/双击删除) -->\n <div\n v-for=\"g in guides\"\n :key=\"'mg-' + g.id\"\n class=\"manual-guide\"\n :class=\"[`guide-${g.type}`]\"\n :style=\"g.type === 'vertical'\n ? { left: g.position + 'mm', top: '0', height: paperHeightMM + 'mm' }\n : { top: g.position + 'mm', left: '0', width: paperWidthMM + 'mm' }\"\n @mousedown.prevent.stop=\"onGuideDown($event, g)\"\n @dblclick.prevent.stop=\"g.id && emit('guide-remove', g.id)\"\n />\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref, onUnmounted } from 'vue'\nimport type { RuntimeElement, TemplateData, ElementRect, ElementZone, AlignLine } from '../types'\nimport { getPaperDimensions } from '../utils/default-config'\nimport BaseElement from './elements/BaseElement.vue'\nimport Ruler from './Ruler.vue'\nimport { useAdsorbManager } from '../composables/useAdsorbManager'\n\nconst props = defineProps<{\n templateData: TemplateData\n runtimeElements: RuntimeElement[]\n designMode?: boolean\n printData?: Record<string, any>[]\n scale?: number\n showRuler?: boolean\n showGrid?: boolean\n snapToGrid?: boolean\n showTableGhostBorder?: boolean\n guides?: AlignLine[]\n}>()\n\nconst emit = defineEmits<{\n select: [id: string, multiple: boolean]\n 'drag-start': []\n 'drag-stop': []\n 'dblclick-element': [id: string]\n 'dblclick-cell': [elementId: string, r: number, c: number]\n 'contextmenu': [id: string, e: MouseEvent]\n 'zone-height-change': [zone: 'header' | 'footer', height: number]\n 'zone-height-commit': [zone: 'header' | 'footer']\n 'add-guide': [type: 'vertical' | 'horizontal', positionMm: number]\n 'guide-move': [id: string, positionMm: number]\n 'guide-remove': [id: string]\n 'clone-element': [element: RuntimeElement, position: { left: number; top: number }]\n}>()\n\nconst contentRef = ref<HTMLElement | null>(null)\n\n/** 根据纸张尺寸和方向计算宽高(mm) */\nconst paperWidthMM = computed(() => {\n return getPaperDimensions(props.templateData).width\n})\nconst paperHeightMM = computed(() => {\n return getPaperDimensions(props.templateData).height\n})\n\n/** 三区矩形(mm,纸面坐标系):上边距→页眉→内容→页脚→下边距 */\nconst zoneRectsMM = computed(() => {\n const m = props.templateData.margins\n const headerH = props.templateData.header.height\n const footerH = props.templateData.footer.height\n const contentW = paperWidthMM.value - m.left - m.right\n return {\n header: { left: m.left, top: m.top, width: contentW, height: headerH },\n content: {\n left: m.left,\n top: m.top + headerH,\n width: contentW,\n height: paperHeightMM.value - m.top - m.bottom - headerH - footerH,\n },\n footer: {\n left: m.left,\n top: paperHeightMM.value - m.bottom - footerH,\n width: contentW,\n height: footerH,\n },\n }\n})\n\nfunction layerStyle(r: { left: number; top: number; width: number; height: number }) {\n return {\n position: 'absolute' as const,\n left: r.left + 'mm',\n top: r.top + 'mm',\n width: r.width + 'mm',\n height: r.height + 'mm',\n }\n}\n\n// 优化:一次遍历完成三区分类,避免三次全量 filter\nconst zoneElements = computed(() => {\n const result = { header: [] as RuntimeElement[], footer: [] as RuntimeElement[], content: [] as RuntimeElement[] }\n for (const el of props.runtimeElements) {\n if (el.zone === 'header') result.header.push(el)\n else if (el.zone === 'footer') result.footer.push(el)\n else result.content.push(el)\n }\n return result\n})\nconst headerElements = computed(() => zoneElements.value.header)\nconst footerElements = computed(() => zoneElements.value.footer)\nconst contentElements = computed(() => zoneElements.value.content)\n\n// 吸附管理器:仅同区元素间吸附,引导线通过 Vue 响应式渲染\nlet currentDragZone: ElementZone = 'content'\n\nconst { requestAdsorb: rawRequestAdsorb, clearGuides, guideLines, paperSize: guidePaperSize } = useAdsorbManager({\n // 优化:直接使用预计算的 zoneElements,避免每次拖拽都 filter\n getElements: () => zoneElements.value[currentDragZone],\n getPaperSize: () => {\n const r = zoneRectsMM.value[currentDragZone]\n return { width: r.width, height: r.height }\n },\n getGuides: () => {\n const v: number[] = [], h: number[] = []\n for (const g of props.guides ?? []) {\n if (g.type === 'vertical') v.push(g.position)\n else h.push(g.position)\n }\n return { vertical: v, horizontal: h }\n },\n})\n\nfunction requestAdsorb(rect: ElementRect): ReturnType<typeof rawRequestAdsorb> {\n const el = props.runtimeElements.find(e => e.id === rect.id)\n currentDragZone = el?.zone || 'content'\n const result = rawRequestAdsorb(rect)\n // 位置被修正即发生吸附,在元素中心闪烁网格高亮点\n if (result.left !== rect.left || result.top !== rect.top) {\n showSnapIndicator(result.left + rect.width / 2, result.top + rect.height / 2)\n }\n return result\n}\n\n/** 拖动手动参考线 */\nfunction onGuideDown(e: MouseEvent, g: AlignLine) {\n const startPt = g.position\n const startX = e.clientX, startY = e.clientY\n const s = props.scale ?? 1\n const MM_PER_PX = 25.4 / 96\n const onMove = (ev: MouseEvent) => {\n const delta = (g.type === 'vertical' ? (ev.clientX - startX) : (ev.clientY - startY)) / s * MM_PER_PX\n emit('guide-move', g.id!, startPt + delta)\n }\n const onUp = () => {\n window.removeEventListener('mousemove', onMove)\n window.removeEventListener('mouseup', onUp)\n }\n window.addEventListener('mousemove', onMove)\n window.addEventListener('mouseup', onUp)\n}\n\nconst paperStyle = computed(() => ({\n width: paperWidthMM.value + 'mm',\n minHeight: paperHeightMM.value + 'mm',\n background: 'var(--pd-paper, #fff)',\n boxShadow: 'var(--pd-shadow-paper, 0 1px 2px rgba(0,0,0,.12), 0 8px 24px rgba(0,0,0,.08))',\n margin: '0 auto',\n overflow: 'hidden',\n position: 'relative' as const,\n transform: props.scale ? `scale(${props.scale})` : undefined,\n transformOrigin: '0 0',\n}))\n\nconst contentStyle = computed(() => {\n const m = props.templateData.margins\n return {\n padding: `${m.top}mm ${m.right}mm ${m.bottom}mm ${m.left}mm`,\n position: 'relative' as const,\n minHeight: paperHeightMM.value + 'mm',\n }\n})\n\nconst showRulerComputed = computed(() => props.showRuler !== false && !!props.designMode)\n\nconst gridBgStyle = computed(() => {\n const size = 5 // mm\n // 虚线网格:SVG 平铺图案,颜色调淡避免干扰元素视觉\n const svg = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\"><path d=\"M0 .5H20M.5 0V20\" fill=\"none\" stroke=\"rgba(0,0,0,0.08)\" stroke-width=\"1\" stroke-dasharray=\"4 4\"/></svg>`\n return {\n backgroundImage: `url(\"data:image/svg+xml,${encodeURIComponent(svg)}\")`,\n backgroundSize: `${size}mm ${size}mm`,\n backgroundPosition: '0 0',\n }\n})\n\n// ─── 吸附高亮指示 ───\nlet snapSeq = 0\nlet snapTimer: ReturnType<typeof setTimeout> | null = null\nconst snapIndicator = ref<{ left: number; top: number; key: number } | null>(null)\n\n/** 在吸附对齐位置闪烁一个高亮点 */\nfunction showSnapIndicator(left: number, top: number) {\n snapSeq += 1\n snapIndicator.value = { left, top, key: snapSeq }\n if (snapTimer) clearTimeout(snapTimer)\n snapTimer = setTimeout(() => {\n snapIndicator.value = null\n }, 300)\n}\n\n// ─── 水印渲染 ───\nconst watermarkVisible = computed(() => {\n const w = props.templateData.watermark\n if (!w) return false\n // 向后兼容:如果没有 mode 字段,使用 content\n if (!w.mode || w.mode === 'fixed') {\n return !!w.content && w.content.trim().length > 0\n }\n // 绑定字段模式\n return !!w.binding\n})\n\nconst watermarkStyle = computed(() => {\n const w = props.templateData.watermark || {}\n const color = w.color || '#cccccc'\n const opacity = w.opacity ?? 0.15\n const rotate = w.rotate ?? -30\n // 获取水印文本\n let text = getWatermarkText(w)\n if (w.timestamp) {\n const now = new Date()\n const ts = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')} ${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}`\n text = text ? `${text} ${ts}` : ts\n }\n return {\n position: 'absolute' as const,\n top: '0',\n left: '0',\n width: '100%',\n height: '100%',\n pointerEvents: 'none' as const,\n zIndex: '0',\n overflow: 'hidden',\n opacity: String(opacity),\n backgroundImage: buildWatermarkSvg(text, color, rotate),\n backgroundRepeat: 'repeat',\n }\n})\n\n/** 获取水印文本(支持绑定字段) */\nfunction getWatermarkText(w: { mode?: 'fixed' | 'binding'; content?: string; binding?: string; testData?: string }): string {\n // 向后兼容:如果没有 mode 字段,使用 content\n if (!w.mode || w.mode === 'fixed') {\n return w.content || ''\n }\n // 绑定字段模式\n if (w.binding) {\n // 从打印数据中取值\n const printData = props.printData?.[0]\n if (printData && printData[w.binding] !== undefined && printData[w.binding] !== null) {\n return String(printData[w.binding])\n }\n // 回退到测试值\n return w.testData || `[${w.binding}]`\n }\n return ''\n}\n\n/** 用内联 SVG 生成水印背景图案 */\nfunction buildWatermarkSvg(text: string, color: string, rotate: number): string {\n const escaped = text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')\n const svg = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"260\" height=\"180\">\n <text x=\"130\" y=\"90\" font-size=\"16\" fill=\"${color}\" text-anchor=\"middle\" dominant-baseline=\"middle\" transform=\"rotate(${rotate},130,90)\">${escaped}</text>\n </svg>`\n return `url(\"data:image/svg+xml,${encodeURIComponent(svg)}\")`\n}\n\n// ─── 页眉/页脚高度拖拽 ───\nconst zoneResizing = ref<{ zone: 'header' | 'footer'; startY: number; startH: number } | null>(null)\n\nfunction startZoneResize(zone: 'header' | 'footer', e: MouseEvent) {\n // 防止重复绑定:先清理再绑定\n cleanupZoneResize()\n zoneResizing.value = { zone, startY: e.clientY, startH: props.templateData[zone].height }\n window.addEventListener('mousemove', onZoneResizeMove)\n window.addEventListener('mouseup', onZoneResizeUp)\n}\n\nfunction onZoneResizeMove(e: MouseEvent) {\n if (!zoneResizing.value) return\n const { zone, startY, startH } = zoneResizing.value\n const dyPx = (e.clientY - startY) / (props.scale || 1)\n const dyMM = dyPx * 25.4 / 96\n const delta = zone === 'header' ? dyMM : -dyMM\n // 0.1mm 步进;上限 100mm 与属性面板一致,且保证内容区至少 10mm\n const maxH = Math.min(\n 100,\n paperHeightMM.value - props.templateData.margins.top - props.templateData.margins.bottom\n - (zone === 'header' ? props.templateData.footer.height : props.templateData.header.height)\n - 10,\n )\n const h = Math.min(maxH, Math.max(0, Math.round((startH + delta) * 10) / 10))\n emit('zone-height-change', zone, h)\n}\n\nfunction onZoneResizeUp() {\n if (!zoneResizing.value) return\n const zone = zoneResizing.value.zone\n zoneResizing.value = null\n window.removeEventListener('mousemove', onZoneResizeMove)\n window.removeEventListener('mouseup', onZoneResizeUp)\n emit('zone-height-commit', zone)\n}\n\n/** 清理区域拖拽事件监听器 */\nfunction cleanupZoneResize() {\n window.removeEventListener('mousemove', onZoneResizeMove)\n window.removeEventListener('mouseup', onZoneResizeUp)\n zoneResizing.value = null\n}\n\nonUnmounted(() => {\n cleanupZoneResize()\n if (snapTimer) clearTimeout(snapTimer)\n})\n\nfunction onSelectElement(id: string, multiple: boolean) {\n emit('select', id, multiple)\n}\n\ndefineExpose({ contentRef })\n</script>\n\n<style scoped>\n/* 纸张缩放平滑过渡(配合鼠标位置缩放中心) */\n.hiprint-printPaper {\n transition: transform 0.15s ease-out;\n}\n/* ─── 三段式区域层 ─── */\n.zone-layer {\n box-sizing: border-box;\n}\n.zone-layer.zone-header.design-mode,\n.zone-layer.zone-footer.design-mode {\n outline: 1px dashed var(--pd-ink-green, #67c23a);\n background: rgba(103, 194, 58, 0.04);\n}\n.zone-layer.zone-content.design-mode {\n outline: 1px dashed #C3C9D6;\n}\n.zone-overlay {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n outline: 1px dashed #06B6D4;\n background: rgba(6, 182, 212, 0.04);\n box-sizing: border-box;\n pointer-events: none;\n z-index: 1;\n}\n.zone-label {\n position: absolute;\n top: 2px;\n right: 4px;\n font-size: 9px;\n color: #909399;\n pointer-events: none;\n user-select: none;\n}\n/* 区域高度拖拽手柄 */\n.zone-resize-handle {\n position: absolute;\n left: 0;\n width: 100%;\n height: 6px;\n cursor: ns-resize;\n z-index: 5;\n}\n.zone-resize-handle.handle-bottom {\n bottom: -3px;\n}\n.zone-resize-handle.handle-top {\n top: -3px;\n}\n.zone-resize-handle:hover {\n background: rgba(16, 185, 129, 0.25);\n}\n.zone-height-tip {\n position: absolute;\n right: 4px;\n top: -22px;\n padding: 1px 6px;\n font-size: 11px;\n color: #fff;\n background: #10B981;\n border-radius: 3px;\n white-space: nowrap;\n pointer-events: none;\n}\n/* 刻度标尺由 Ruler.vue Canvas 绘制 */\n.grid-bg {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n pointer-events: none;\n z-index: 0;\n}\n/* 吸附高亮指示点 */\n.snap-indicator {\n position: absolute;\n width: 6px;\n height: 6px;\n background: var(--pd-accent, #165DFF);\n border-radius: 50%;\n transform: translate(-50%, -50%);\n pointer-events: none;\n z-index: 10;\n animation: snap-pulse 0.3s ease-out;\n}\n@keyframes snap-pulse {\n from { transform: translate(-50%, -50%) scale(2); opacity: 0.5; }\n to { transform: translate(-50%, -50%) scale(1); opacity: 0; }\n}\n/* 水印层 */\n.watermark-layer {\n pointer-events: none;\n}\n/* 吸附引导线 */\n.adsorb-guide {\n position: absolute;\n pointer-events: none;\n z-index: 9999;\n}\n.adsorb-guide.guide-vertical {\n border-left: 1px dashed var(--pd-accent-secondary, #f56c6c);\n}\n.adsorb-guide.guide-horizontal {\n border-top: 1px dashed var(--pd-accent-secondary, #f56c6c);\n}\n/* 手动参考线 */\n.manual-guide { position: absolute; pointer-events: auto; z-index: 9998; cursor: move; }\n.manual-guide.guide-vertical { border-left: 1px solid #3B82F6; width: 0; }\n.manual-guide.guide-horizontal { border-top: 1px solid #3B82F6; height: 0; }\n.manual-guide:hover { border-color: #EF4444 !important; }\n</style>\n","<template>\n <div\n ref=\"rootRef\"\n class=\"canvas-area\"\n @dragover.prevent\n @drop=\"onDrop\"\n @mousedown=\"onCanvasMouseDown\"\n @mousemove=\"onMouseMove\"\n @mouseleave=\"onMouseLeave\"\n @wheel=\"onWheel\"\n @contextmenu.prevent=\"onContextMenu\"\n >\n <div class=\"canvas-scroll\">\n <CanvasPaper\n :template-data=\"templateData\"\n :runtime-elements=\"elements\"\n :design-mode=\"true\"\n :print-data=\"[]\"\n :scale=\"scale\"\n :show-grid=\"showGrid\"\n :snap-to-grid=\"snapToGrid\"\n :show-table-ghost-border=\"showTableGhostBorder\"\n :guides=\"guides\"\n @select=\"onSelectElement\"\n @add-guide=\"(t: 'vertical' | 'horizontal', p: number) => $emit('add-guide', t, p)\"\n @guide-move=\"(id: string, p: number) => $emit('guide-move', id, p)\"\n @guide-remove=\"(id: string) => $emit('guide-remove', id)\"\n @drag-start=\"$emit('drag-start')\"\n @drag-stop=\"$emit('drag-stop')\"\n @dblclick-element=\"(id: string) => $emit('dblclick-element', id)\"\n @dblclick-cell=\"(id: string, r: number, c: number) => $emit('dblclick-cell', id, r, c)\"\n @contextmenu=\"(id: string, e: MouseEvent) => onContextMenu(e, id)\"\n @zone-height-change=\"(zone: 'header' | 'footer', h: number) => $emit('zone-height-change', zone, h)\"\n @zone-height-commit=\"(zone: 'header' | 'footer') => $emit('zone-height-commit', zone)\"\n @clone-element=\"(el, pos) => $emit('clone-element', el, pos)\"\n />\n <!-- 叠层对比截图 -->\n <div v-if=\"overlayVisible && screenshotUrl\" class=\"overlay-layer\">\n <img :src=\"screenshotUrl\" class=\"overlay-image\" :style=\"{ opacity: overlayOpacity ?? 0.5 }\" />\n </div>\n </div>\n\n <!-- 框选选框 -->\n <div\n v-if=\"marquee.visible\"\n class=\"marquee-selection\"\n :style=\"{\n left: marquee.x + 'px',\n top: marquee.y + 'px',\n width: marquee.w + 'px',\n height: marquee.h + 'px',\n }\"\n />\n\n <!-- 右键菜单 -->\n <div\n v-if=\"contextMenu.visible\"\n class=\"context-menu\"\n :style=\"{ left: contextMenu.x + 'px', top: contextMenu.y + 'px' }\"\n >\n <template v-if=\"contextMenu.targetId\">\n <div class=\"context-menu-item\" @click=\"emitAction('copy')\">复制</div>\n <div class=\"context-menu-item\" @click=\"emitAction('cut')\">剪切</div>\n <div class=\"context-menu-item\" :class=\"{ disabled: !hasClipboard }\" @click=\"emitAction('paste')\">粘贴</div>\n <div class=\"context-menu-item\" @click=\"emitAction('delete')\">删除</div>\n <div class=\"context-menu-sep\" />\n <div class=\"context-menu-item\" @click=\"emitAction('move-layer', 'top')\">置顶</div>\n <div class=\"context-menu-item\" @click=\"emitAction('move-layer', 'up')\">上移</div>\n <div class=\"context-menu-item\" @click=\"emitAction('move-layer', 'down')\">下移</div>\n <div class=\"context-menu-item\" @click=\"emitAction('move-layer', 'bottom')\">置底</div>\n <div class=\"context-menu-sep\" />\n <div class=\"context-menu-item\" @click=\"emitAction('group')\">编组 Ctrl+G</div>\n <div class=\"context-menu-item\" :class=\"{ disabled: !selectedElementHasGroup }\" @click=\"emitAction('ungroup')\">取消编组 Ctrl+Shift+G</div>\n </template>\n <template v-else>\n <div class=\"context-menu-item\" :class=\"{ disabled: !hasClipboard }\" @click=\"handlePaste\">粘贴</div>\n <div class=\"context-menu-item\" @click=\"handleSelectAll\">全选</div>\n <div class=\"context-menu-item\" @click=\"handleClearSelection\">取消选择</div>\n </template>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, reactive, onBeforeUnmount } from 'vue'\nimport type { RuntimeElement, TemplateData, AlignLine } from '../types'\nimport { pxToMm } from '../utils/units'\nimport CanvasPaper from './CanvasPaper.vue'\n\nconst props = defineProps<{\n templateData: TemplateData\n elements: RuntimeElement[]\n scale: number\n showGrid?: boolean\n snapToGrid?: boolean\n showTableGhostBorder?: boolean\n hasClipboard?: boolean\n guides?: AlignLine[]\n overlayVisible?: boolean\n screenshotUrl?: string\n overlayOpacity?: number\n selectedElementHasGroup?: boolean\n}>()\n\nconst emit = defineEmits<{\n select: [id: string, multiple: boolean]\n 'drop-element': [type: string, dropPoint?: { x: number; y: number }]\n 'drop-field': [field: { fieldKey: string; fieldLabel: string }, dropPoint?: { x: number; y: number }]\n 'drag-start': []\n 'drag-stop': []\n 'dblclick-element': [id: string]\n 'dblclick-cell': [elementId: string, r: number, c: number]\n 'zone-height-change': [zone: 'header' | 'footer', height: number]\n 'zone-height-commit': [zone: 'header' | 'footer']\n 'select-all': []\n 'clear-selection': []\n 'preview': [ids: string[]]\n 'commit-preview': []\n 'paste': []\n 'copy': []\n 'cut': []\n 'delete': []\n 'move-layer': [direction: string]\n group: []\n ungroup: []\n 'coordinate': [pos: { x: number; y: number } | null]\n 'add-guide': [type: 'vertical' | 'horizontal', positionMm: number]\n 'guide-move': [id: string, positionMm: number]\n 'guide-remove': [id: string]\n 'zoom': [delta: number]\n 'clone-element': [element: RuntimeElement, position: { left: number; top: number }]\n}>()\n\nfunction onSelectElement(id: string, multiple: boolean) {\n emit('select', id, multiple)\n}\n\nconst rootRef = ref<HTMLElement | null>(null)\n\n/** 客户端坐标 → 纸面 mm 坐标;纸张未挂载或落点在纸外时返回 undefined(走默认落位) */\nfunction toPaperPoint(e: DragEvent): { x: number; y: number } | undefined {\n const paper = rootRef.value?.querySelector('.hiprint-printPaper') as HTMLElement | null\n if (!paper) return undefined\n const rect = paper.getBoundingClientRect()\n const scale = props.scale || 1\n const x = pxToMm((e.clientX - rect.left) / scale)\n const y = pxToMm((e.clientY - rect.top) / scale)\n if (x < 0 || y < 0) return undefined\n return { x, y }\n}\n\nfunction onDrop(e: DragEvent) {\n const dropPoint = toPaperPoint(e)\n const fieldData = e.dataTransfer?.getData('fieldData')\n if (fieldData) {\n try {\n const field = JSON.parse(fieldData) as { fieldKey: string; fieldLabel: string }\n emit('drop-field', field, dropPoint)\n return\n } catch {\n // 解析失败,忽略\n }\n }\n const elementType = e.dataTransfer?.getData('elementType')\n if (elementType) {\n emit('drop-element', elementType, dropPoint)\n }\n}\n\n// ─── 鼠标框选 ───\nconst marquee = reactive({ visible: false, x: 0, y: 0, w: 0, h: 0 })\nlet marqueeStart = { x: 0, y: 0 }\n\n/** 判断点击目标是否为画布空白区域(非元素) */\nfunction isCanvasBackground(target: EventTarget | null): boolean {\n if (!target || !(target instanceof HTMLElement)) return false\n // 点击在画布容器、滚动层、纸张本身上视为空白区域\n if (target === rootRef.value) return true\n if (target.classList.contains('canvas-scroll')) return true\n if (target.classList.contains('hiprint-printPaper')) return true\n if (target.classList.contains('hiprint-printPaper-content')) return true\n if (target.classList.contains('zone-layer')) return true\n if (target.classList.contains('grid-bg')) return true\n if (target.classList.contains('watermark-layer')) return true\n return false\n}\n\nconst MM_TO_PX = 96 / 25.4\nfunction onMouseMove(e: MouseEvent) {\n const paper = rootRef.value?.querySelector('.hiprint-printPaper') as HTMLElement | null\n if (!paper) return\n const rect = paper.getBoundingClientRect()\n const s = props.scale || 1\n const xMm = pxToMm((e.clientX - rect.left) / s)\n const yMm = pxToMm((e.clientY - rect.top) / s)\n if (xMm < 0 || yMm < 0) { emit('coordinate', null); return }\n emit('coordinate', { x: xMm, y: yMm })\n}\nfunction onMouseLeave() { emit('coordinate', null) }\n\n/** Ctrl/Cmd+滚轮缩放:以鼠标位置为缩放中心,缩放前后保持鼠标下的内容点不动 */\nfunction onWheel(e: WheelEvent) {\n if (!(e.ctrlKey || e.metaKey)) return\n e.preventDefault()\n const oldScale = props.scale\n const newScale = Math.max(0.25, Math.min(3, oldScale + (e.deltaY > 0 ? -0.1 : 0.1)))\n if (newScale === oldScale) return\n\n // 缩放中心换算:scroll' = (scroll + mouse) * ratio - mouse\n const container = rootRef.value\n if (container) {\n const rect = container.getBoundingClientRect()\n const mouseX = e.clientX - rect.left\n const mouseY = e.clientY - rect.top\n const ratio = newScale / oldScale\n container.scrollLeft = (container.scrollLeft + mouseX) * ratio - mouseX\n container.scrollTop = (container.scrollTop + mouseY) * ratio - mouseY\n }\n\n // 以百分比增量上报(父级 scale 为百分比)\n emit('zoom', (newScale - oldScale) * 100)\n}\n\nfunction onCanvasMouseDown(e: MouseEvent) {\n // 右键由 contextmenu 处理\n if (e.button === 2) return\n if (!isCanvasBackground(e.target)) return\n\n // 点击空白区域取消选择\n emit('clear-selection')\n\n // 启动框选\n marqueeStart = { x: e.clientX, y: e.clientY }\n marquee.visible = true\n marquee.x = e.clientX\n marquee.y = e.clientY\n marquee.w = 0\n marquee.h = 0\n\n window.addEventListener('mousemove', onMarqueeMove)\n window.addEventListener('mouseup', onMarqueeUp)\n}\n\n/** 框选命中测试:左->右拖=交集,右->左拖=包含;返回命中元素 id */\nfunction hitTestIds(): string[] {\n if (marquee.w < 3 || marquee.h < 3) return []\n const paper = rootRef.value?.querySelector('.hiprint-printPaper') as HTMLElement | null\n if (!paper) return []\n const paperRect = paper.getBoundingClientRect()\n const s = props.scale || 1\n // marquee.x 是选框左边缘;小于起点 x 表示从右向左拖(包含模式)\n const containMode = marquee.x < marqueeStart.x\n const ids: string[] = []\n for (const el of props.elements) {\n if (el.options.visible === false || el.options.locked) continue\n const elLeft = paperRect.left + el.options.left * MM_TO_PX * s\n const elTop = paperRect.top + el.options.top * MM_TO_PX * s\n const elRight = elLeft + el.options.width * MM_TO_PX * s\n const elBottom = elTop + el.options.height * MM_TO_PX * s\n const inter = elLeft < marquee.x + marquee.w && elRight > marquee.x\n && elTop < marquee.y + marquee.h && elBottom > marquee.y\n const contained = elLeft >= marquee.x && elRight <= marquee.x + marquee.w\n && elTop >= marquee.y && elBottom <= marquee.y + marquee.h\n if (containMode ? contained : inter) ids.push(el.id)\n }\n return ids\n}\n\nfunction onMarqueeMove(e: MouseEvent) {\n const dx = e.clientX - marqueeStart.x\n const dy = e.clientY - marqueeStart.y\n marquee.x = dx >= 0 ? marqueeStart.x : e.clientX\n marquee.y = dy >= 0 ? marqueeStart.y : e.clientY\n marquee.w = Math.abs(dx)\n marquee.h = Math.abs(dy)\n // 实时预选高亮\n emit('preview', hitTestIds())\n}\n\nfunction onMarqueeUp() {\n window.removeEventListener('mousemove', onMarqueeMove)\n window.removeEventListener('mouseup', onMarqueeUp)\n\n const ids = hitTestIds()\n emit('preview', ids) // 确保预选为最终状态\n if (ids.length > 0) emit('commit-preview')\n else emit('clear-selection')\n emit('preview', []) // 清除预选高亮\n\n marquee.visible = false\n}\n\n// ─── 右键菜单 ───\nconst contextMenu = reactive({ visible: false, x: 0, y: 0, targetId: null as string | null })\n\nfunction onContextMenu(e: MouseEvent, elId?: string) {\n // 元素右键:由 BaseElement 上抛(已 stop);空白右键:无 elId,仅背景区域弹菜单\n if (!elId && !isCanvasBackground(e.target)) return\n const containerRect = rootRef.value?.getBoundingClientRect()\n if (!containerRect) return\n contextMenu.x = e.clientX - containerRect.left\n contextMenu.y = e.clientY - containerRect.top\n contextMenu.targetId = elId ?? null\n contextMenu.visible = true\n\n // 点击其他区域关闭:先清理旧监听器防止重复绑定\n window.removeEventListener('mousedown', closeContextMenu)\n setTimeout(() => {\n window.addEventListener('mousedown', closeContextMenu, { once: true })\n }, 0)\n}\n\nfunction closeContextMenu() {\n contextMenu.visible = false\n window.removeEventListener('mousedown', closeContextMenu)\n}\n\nfunction handlePaste() {\n contextMenu.visible = false\n if (props.hasClipboard) emit('paste')\n}\n\nfunction handleSelectAll() {\n contextMenu.visible = false\n emit('select-all')\n}\n\nfunction handleClearSelection() {\n contextMenu.visible = false\n emit('clear-selection')\n}\n\n/** 元素右键菜单动作派发 */\nfunction emitAction(action: string, arg?: string) {\n contextMenu.visible = false\n if (action === 'copy') emit('copy')\n else if (action === 'cut') emit('cut')\n else if (action === 'paste') emit('paste')\n else if (action === 'delete') emit('delete')\n else if (action === 'move-layer') emit('move-layer', arg!)\n else if (action === 'group') emit('group')\n else if (action === 'ungroup' && props.selectedElementHasGroup) emit('ungroup')\n}\n\nonBeforeUnmount(() => {\n window.removeEventListener('mousemove', onMarqueeMove)\n window.removeEventListener('mouseup', onMarqueeUp)\n})\n</script>\n\n<style scoped>\n.canvas-area {\n flex: 1;\n overflow: auto;\n /* 制图垫:略深冷灰 + 极淡点阵,让白纸浮起 */\n background-color: var(--pd-canvas-bg, #e6e9f0);\n background-image: radial-gradient(circle, rgba(23, 32, 60, .13) 1px, transparent 1.2px);\n background-size: 20px 20px;\n background-position: center;\n display: flex;\n justify-content: center;\n padding: 44px 28px 32px 44px;\n position: relative;\n}\n.canvas-scroll {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 20px;\n position: relative;\n}\n/* 叠层对比 */\n.overlay-layer {\n position: absolute;\n top: 0;\n left: 0;\n pointer-events: none;\n z-index: 100;\n}\n.overlay-image {\n width: 100%;\n display: block;\n}\n/* 框选选框 */\n.marquee-selection {\n position: fixed;\n border: 1.5px solid rgba(22, 93, 255, 0.7);\n background: rgba(22, 93, 255, 0.08);\n border-radius: 2px;\n pointer-events: none;\n z-index: 10000;\n}\n/* 右键菜单 */\n.context-menu {\n position: absolute;\n background: var(--pd-surface, #ffffff);\n border: 1px solid var(--pd-border-soft, #e9ecf2);\n border-radius: 8px;\n box-shadow: var(--pd-shadow-md, 0 10px 28px rgba(23, 32, 60, .12));\n padding: 5px;\n z-index: 10001;\n min-width: 132px;\n}\n.context-menu-item {\n padding: 7px 12px;\n border-radius: 5px;\n font-size: 12.5px;\n cursor: pointer;\n color: var(--pd-text, #2a2e37);\n user-select: none;\n transition: background .12s ease, color .12s ease;\n}\n.context-menu-item:hover {\n background: var(--pd-accent-soft, rgba(22, 93, 255, .09));\n color: var(--pd-accent, #165DFF);\n}\n.context-menu-item.disabled {\n color: var(--pd-text-faint, #b4b9c4);\n cursor: not-allowed;\n}\n.context-menu-item.disabled:hover {\n background: transparent;\n color: var(--pd-text-faint, #b4b9c4);\n}\n.context-menu-sep {\n height: 1px;\n background: var(--pd-border-soft, #e9ecf2);\n margin: 5px 8px;\n}\n</style>\n","/** 属性面板搜索注册表:分组 → 表单项 → 关键词 */\nexport interface PropertyItem {\n key: string\n keywords: string[]\n}\n\nexport interface PropertyGroupDef {\n group: string\n groupLabel: string\n items: PropertyItem[]\n}\n\nexport const PROPERTY_REGISTRY: PropertyGroupDef[] = [\n {\n group: 'position-size',\n groupLabel: '位置与尺寸',\n items: [\n { key: 'ps-left', keywords: ['X', '横坐标', 'left', '位置'] },\n { key: 'ps-top', keywords: ['Y', '纵坐标', 'top', '位置'] },\n { key: 'ps-width', keywords: ['W', '宽度', 'width', '尺寸'] },\n { key: 'ps-height', keywords: ['H', '高度', 'height', '尺寸'] },\n ],\n },\n {\n group: 'appearance',\n groupLabel: '外观',\n items: [\n { key: 'ap-font-size', keywords: ['字体大小', 'fontsize', '字号'] },\n { key: 'ap-font-weight', keywords: ['字体粗细', '粗体', 'bold'] },\n { key: 'ap-align', keywords: ['对齐', 'align'] },\n { key: 'ap-vertical-align', keywords: ['垂直对齐', 'verticalalign', '顶对齐', '底对齐'] },\n { key: 'ap-color', keywords: ['颜色', 'color'] },\n { key: 'ap-bg-color', keywords: ['背景色', 'background'] },\n { key: 'ap-line-height', keywords: ['行高', 'lineheight'] },\n { key: 'ap-letter-spacing', keywords: ['字间距', 'letterspacing'] },\n ],\n },\n {\n group: 'content',\n groupLabel: '内容',\n items: [\n { key: 'ct-title', keywords: ['内容', '文本', 'title'] },\n { key: 'ct-formatter', keywords: ['格式化', '表达式', 'formatter'] },\n { key: 'ct-table-mode', keywords: ['数据模式', '静态布局', '动态数据'] },\n { key: 'ct-table-source', keywords: ['数据源', '列表字段'] },\n { key: 'ct-table-font', keywords: ['默认字号', '默认颜色', '默认内边距'] },\n { key: 'ct-table-cols', keywords: ['列宽', '表格列'] },\n ],\n },\n {\n group: 'border-bg',\n groupLabel: '边框与背景',\n items: [\n { key: 'bb-border-width', keywords: ['边框宽度', 'border'] },\n { key: 'bb-border-color', keywords: ['边框颜色'] },\n { key: 'bb-bg-color', keywords: ['背景色', 'background'] },\n ],\n },\n {\n group: 'binding',\n groupLabel: '字段绑定',\n items: [\n { key: 'bd-formatter', keywords: ['格式化', '表达式', 'formatter', 'fx', '字段', '绑定', 'field'] },\n { key: 'bd-content', keywords: ['内容', '表达式', '文本', '变量'] },\n ],\n },\n {\n group: 'pagination',\n groupLabel: '分页',\n items: [\n { key: 'pg-enabled', keywords: ['分页', 'pagination', '启用分页'] },\n { key: 'pg-pageable', keywords: ['参与分页', 'pageable'] },\n { key: 'pg-keep-with-next', keywords: ['同页', 'keepWithNext'] },\n ],\n },\n {\n group: 'advanced',\n groupLabel: '高级',\n items: [\n { key: 'ad-locked', keywords: ['锁定', 'lock'] },\n { key: 'ad-fixed', keywords: ['每页重复', 'repeat'] },\n { key: 'ad-z-index', keywords: ['层级', 'zindex'] },\n { key: 'ad-delete', keywords: ['删除'] },\n ],\n },\n]\n\n/** 正向包含匹配:任一关键词包含搜索词即命中;空搜索恒命中 */\nexport function matchKeywords(search: string, keywords: string[]): boolean {\n const s = search.trim().toLowerCase()\n if (!s) {\n return true\n }\n return keywords.some(k => k.toLowerCase().includes(s))\n}\n\n/** 计算命中的分组与表单项 key 集合 */\nexport function searchProperties(search: string): { groups: string[]; itemKeys: Set<string> } {\n const groups: string[] = []\n const itemKeys = new Set<string>()\n for (const g of PROPERTY_REGISTRY) {\n const matched = g.items.filter(item => matchKeywords(search, [...item.keywords, g.groupLabel]))\n if (matched.length > 0) {\n groups.push(g.group)\n for (const item of matched) {\n itemKeys.add(item.key)\n }\n }\n }\n return { groups, itemKeys }\n}\n","<template>\n <div class=\"property-search\">\n <input\n v-model=\"searchText\"\n class=\"pd-input\"\n type=\"search\"\n placeholder=\"搜索属性...\"\n aria-label=\"搜索属性\"\n @input=\"onSearch\"\n >\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref } from 'vue'\n\nconst searchText = ref('')\nconst emit = defineEmits<{ search: [text: string] }>()\n\nfunction onSearch() {\n emit('search', searchText.value)\n}\n</script>\n\n<style scoped>\n.property-search {\n padding: 0 0 10px;\n background: transparent;\n}\n</style>\n","<template>\n <div class=\"property-group\" :class=\"{ 'is-expanded': isExpanded }\">\n <div class=\"group-header\" @click=\"toggle\">\n <span class=\"group-icon\">{{ iconChar }}</span>\n <span class=\"group-title\">{{ title }}</span>\n <span class=\"expand-icon\">{{ isExpanded ? '▾' : '▸' }}</span>\n </div>\n <div v-show=\"isExpanded\" class=\"group-content\">\n <slot />\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, onMounted } from 'vue'\n\nconst props = defineProps<{\n title: string\n icon: string\n defaultExpanded?: boolean\n groupKey: string\n}>()\n\nconst isExpanded = ref(props.defaultExpanded ?? true)\n\nconst iconMap: Record<string, string> = {\n Document: '≡',\n Brush: '◧',\n Setting: '⚙',\n}\nconst iconChar = iconMap[props.icon] || '•'\n\nfunction toggle() {\n isExpanded.value = !isExpanded.value\n saveState()\n}\n\nfunction saveState() {\n const key = `property-group-${props.groupKey}`\n try {\n localStorage.setItem(key, String(isExpanded.value))\n } catch {\n // 隐私模式或存储满,忽略持久化失败\n }\n}\n\nfunction loadState() {\n const key = `property-group-${props.groupKey}`\n try {\n const saved = localStorage.getItem(key)\n if (saved !== null) {\n isExpanded.value = saved === 'true'\n }\n } catch {\n // 读取失败保持默认展开状态\n }\n}\n\nonMounted(() => {\n loadState()\n})\n</script>\n\n<style scoped>\n.property-group {\n border: 1px solid var(--pd-border-soft, #e9ecf2);\n border-radius: 8px;\n margin-bottom: 10px;\n background: var(--pd-surface, #ffffff);\n overflow: hidden;\n transition: border-color .14s ease, box-shadow .14s ease;\n}\n.property-group:last-child {\n margin-bottom: 2px;\n}\n.property-group.is-expanded {\n border-color: var(--pd-border-soft, #e9ecf2);\n}\n.group-header {\n display: flex;\n align-items: center;\n padding: 9px 12px;\n cursor: pointer;\n user-select: none;\n background: var(--pd-field-bg, #f4f6fa);\n transition: background .14s ease;\n}\n.group-header:hover {\n background: var(--pd-sidebar-hover, #f0f3f9);\n}\n.property-group.is-expanded .group-header {\n border-bottom: 1px solid var(--pd-border-soft, #e9ecf2);\n}\n.group-icon {\n margin-right: 8px;\n color: var(--pd-accent, #165DFF);\n}\n.group-title {\n flex: 1;\n font-size: 12px;\n font-weight: 600;\n color: var(--pd-text, #2a2e37);\n letter-spacing: .3px;\n}\n.expand-icon {\n color: var(--pd-text-muted, #8b909c);\n font-size: 10px;\n}\n.group-content {\n padding: 10px 12px 12px;\n background: var(--pd-surface, #ffffff);\n}\n</style>","<template>\n <PropertyGroup title=\"位置与尺寸\" icon=\"Location\" default-expanded group-key=\"position-size\">\n <form class=\"pd-form\" @submit.prevent>\n <div class=\"position-grid\">\n <div class=\"pd-field\" v-show=\"showItem('ps-left')\"><span class=\"pd-label\">X</span>\n <input type=\"number\" class=\"pd-input\" v-model.number=\"element.options.left\"\n :min=\"0\"\n :step=\"0.01\" />\n </div>\n <div class=\"pd-field\" v-show=\"showItem('ps-top')\"><span class=\"pd-label\">Y</span>\n <input type=\"number\" class=\"pd-input\" v-model.number=\"element.options.top\"\n :min=\"0\"\n :step=\"0.01\" />\n </div>\n <div class=\"pd-field\" v-show=\"showItem('ps-width')\"><span class=\"pd-label\">W</span>\n <input type=\"number\" class=\"pd-input\" v-model.number=\"element.options.width\"\n :min=\"3.5\"\n :step=\"0.01\" />\n </div>\n <div class=\"pd-field\" v-show=\"showItem('ps-height')\"><span class=\"pd-label\">H</span>\n <input type=\"number\" class=\"pd-input\" v-model.number=\"element.options.height\"\n :min=\"3.5\"\n :step=\"0.01\" />\n </div>\n </div>\n </form>\n </PropertyGroup>\n</template>\n\n<script setup lang=\"ts\">\nimport type { RuntimeElement } from '../../types'\nimport PropertyGroup from './PropertyGroup.vue'\n\nconst props = defineProps<{\n element: RuntimeElement\n matchedKeys?: Set<string>\n searching?: boolean\n}>()\n\nfunction showItem(key: string): boolean {\n if (!props.searching) {\n return true\n }\n return props.matchedKeys?.has(key) ?? true\n}\n</script>\n\n<style scoped>\n.position-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 8px;\n}\n</style>\n","/** 打印设计器常见预设颜色(12 色) */\nexport const PRESET_COLORS = [\n '#000000',\n '#333333',\n '#666666',\n '#999999',\n '#cccccc',\n '#ffffff',\n '#e53935',\n '#fb8c00',\n '#1e88e5',\n '#43a047',\n '#8d6e63',\n '#00acc1',\n] as const\n","<template>\n <button\n ref=\"triggerRef\"\n type=\"button\"\n class=\"preset-color-trigger\"\n :aria-expanded=\"visible\"\n aria-haspopup=\"dialog\"\n :title=\"modelValue || '自动'\"\n @click=\"toggle\"\n >\n <span class=\"preset-color-swatch\" :style=\"{ background: normalizedValue }\"></span>\n </button>\n\n <Teleport to=\"body\">\n <div\n v-if=\"visible\"\n ref=\"panelRef\"\n class=\"preset-color-panel\"\n role=\"dialog\"\n aria-label=\"颜色选择\"\n :style=\"panelStyle\"\n @pointerdown.stop\n >\n <div class=\"picker-preview\">\n <span class=\"picker-current\" :style=\"{ background: activeColor }\"></span>\n <input\n v-model=\"hexInput\"\n class=\"picker-hex\"\n type=\"text\"\n maxlength=\"7\"\n spellcheck=\"false\"\n aria-label=\"颜色值\"\n @input=\"onHexInput\"\n />\n </div>\n\n <div\n ref=\"areaRef\"\n class=\"picker-area\"\n :style=\"{ '--picker-hue': `${Math.round(hue)}deg` }\"\n aria-label=\"自定义颜色\"\n tabindex=\"0\"\n @pointerdown=\"startAreaDrag\"\n @pointermove=\"moveAreaDrag\"\n @pointerup=\"endAreaDrag\"\n @pointercancel=\"endAreaDrag\"\n @keydown=\"onAreaKeydown\"\n >\n <span class=\"picker-handle\" :style=\"{ left: `${saturation * 100}%`, top: `${(1 - value) * 100}%`, background: activeColor }\"></span>\n </div>\n\n <input\n v-model.number=\"hueModel\"\n class=\"picker-hue\"\n type=\"range\"\n min=\"0\"\n max=\"360\"\n step=\"1\"\n aria-label=\"色相\"\n />\n\n <div class=\"picker-heading\">常用颜色</div>\n <div class=\"preset-color-grid\">\n <button\n v-for=\"color in PRESET_COLORS\"\n :key=\"color\"\n type=\"button\"\n class=\"preset-color-item\"\n :class=\"{ active: color.toLowerCase() === activeColor.toLowerCase() }\"\n :style=\"{ background: color }\"\n :title=\"color\"\n :aria-label=\"color\"\n @click=\"select(color)\"\n ></button>\n </div>\n </div>\n </Teleport>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'\nimport { PRESET_COLORS } from '../utils/preset-colors'\n\nconst props = defineProps<{\n modelValue?: string\n}>()\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string]\n}>()\n\nconst visible = ref(false)\nconst triggerRef = ref<HTMLElement>()\nconst panelRef = ref<HTMLElement>()\nconst areaRef = ref<HTMLElement>()\nconst panelStyle = ref<Record<string, string>>({})\n\nconst hue = ref(0)\nconst saturation = ref(0)\nconst value = ref(0)\nconst hexInput = ref('#000000')\nconst areaDragging = ref(false)\n\nconst normalizedValue = computed({\n get: () => props.modelValue || '#000000',\n set: (color: string) => emit('update:modelValue', color),\n})\n\nconst activeColor = computed(() => {\n return rgbToHex(hsvToRgb(hue.value, saturation.value, value.value))\n})\n\nconst hueModel = computed({\n get: () => Math.round(hue.value),\n set: (degree: number) => setHsv(clampDegree(degree), saturation.value, value.value),\n})\n\nwatch(normalizedValue, syncFromColor, { immediate: true })\n\nfunction select(color: string) {\n hexInput.value = color.toUpperCase()\n syncFromColor(color)\n emit('update:modelValue', color)\n}\n\nfunction onHexInput(event: Event) {\n const input = event.target as HTMLInputElement\n const color = input.value.trim()\n if (!parseHex(color)) return\n syncFromColor(color)\n emit('update:modelValue', normalizeHex(color))\n}\n\nfunction syncFromColor(color: string) {\n const rgb = parseHex(color)\n if (!rgb) return\n const hsv = rgbToHsv(rgb.r, rgb.g, rgb.b)\n hue.value = hsv.h\n saturation.value = hsv.s\n value.value = hsv.v\n hexInput.value = normalizeHex(color).toUpperCase()\n}\n\nfunction setHsv(h: number, s: number, v: number) {\n hue.value = clampDegree(h)\n saturation.value = clamp01(s)\n value.value = clamp01(v)\n hexInput.value = activeColor.value.toUpperCase()\n emit('update:modelValue', activeColor.value)\n}\n\nfunction startAreaDrag(event: PointerEvent) {\n const area = event.currentTarget as HTMLElement\n area.setPointerCapture(event.pointerId)\n areaDragging.value = true\n setAreaFromEvent(event)\n}\n\nfunction moveAreaDrag(event: PointerEvent) {\n if (!areaDragging.value) return\n setAreaFromEvent(event)\n}\n\nfunction endAreaDrag(event: PointerEvent) {\n areaDragging.value = false\n const area = event.currentTarget as HTMLElement\n if (area.hasPointerCapture(event.pointerId)) {\n area.releasePointerCapture(event.pointerId)\n }\n}\n\nfunction setAreaFromEvent(event: PointerEvent) {\n const area = areaRef.value\n if (!area) return\n const rect = area.getBoundingClientRect()\n const s = clamp01((event.clientX - rect.left) / rect.width)\n const v = clamp01(1 - (event.clientY - rect.top) / rect.height)\n setHsv(hue.value, s, v)\n}\n\nfunction onAreaKeydown(event: KeyboardEvent) {\n const step = event.shiftKey ? 0.1 : 0.02\n let handled = true\n if (event.key === 'ArrowLeft') setHsv(hue.value, saturation.value - step, value.value)\n else if (event.key === 'ArrowRight') setHsv(hue.value, saturation.value + step, value.value)\n else if (event.key === 'ArrowUp') setHsv(hue.value, saturation.value, value.value + step)\n else if (event.key === 'ArrowDown') setHsv(hue.value, saturation.value, value.value - step)\n else handled = false\n if (handled) event.preventDefault()\n}\n\nfunction toggle() {\n visible.value ? close() : open()\n}\n\nasync function open() {\n const trigger = triggerRef.value\n if (!trigger) return\n syncFromColor(normalizedValue.value)\n visible.value = true\n await nextTick()\n const rect = trigger.getBoundingClientRect()\n const panelWidth = 190\n const panelHeight = panelRef.value?.offsetHeight ?? 216\n const margin = 8\n const left = Math.min(rect.left, window.innerWidth - panelWidth - margin)\n const below = rect.bottom + 6\n const top = below + panelHeight > window.innerHeight - margin\n ? Math.max(margin, rect.top - panelHeight - 6)\n : below\n\n panelStyle.value = {\n left: `${Math.max(margin, left)}px`,\n top: `${top}px`,\n }\n}\n\nfunction close() {\n visible.value = false\n}\n\nfunction onDocumentPointerDown(event: PointerEvent) {\n const target = event.target as Node\n if (triggerRef.value?.contains(target) || panelRef.value?.contains(target)) return\n close()\n}\n\nfunction onWindowCloseEvents() {\n if (visible.value) close()\n}\n\nfunction onKeydown(event: KeyboardEvent) {\n if (event.key === 'Escape' && visible.value) close()\n}\n\nfunction parseHex(color: string): { r: number; g: number; b: number } | null {\n const match = /^#?([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(color.trim())\n if (!match) return null\n const hex = match[1]!\n const full = hex.length === 3\n ? hex.split('').map(char => char + char).join('')\n : hex\n return {\n r: Number.parseInt(full.slice(0, 2), 16),\n g: Number.parseInt(full.slice(2, 4), 16),\n b: Number.parseInt(full.slice(4, 6), 16),\n }\n}\n\nfunction normalizeHex(color: string): string {\n const rgb = parseHex(color)\n return rgb ? rgbToHex(rgb) : '#000000'\n}\n\nfunction rgbToHex({ r, g, b }: { r: number; g: number; b: number }): string {\n return `#${[r, g, b].map(part => Math.round(clamp01(part / 255) * 255).toString(16).padStart(2, '0')).join('')}`\n}\n\nfunction rgbToHsv(r: number, g: number, b: number): { h: number; s: number; v: number } {\n const red = r / 255\n const green = g / 255\n const blue = b / 255\n const max = Math.max(red, green, blue)\n const min = Math.min(red, green, blue)\n const delta = max - min\n let h = 0\n if (delta !== 0) {\n if (max === red) h = ((green - blue) / delta) % 6\n else if (max === green) h = (blue - red) / delta + 2\n else h = (red - green) / delta + 4\n h *= 60\n if (h < 0) h += 360\n }\n return { h, s: max === 0 ? 0 : delta / max, v: max }\n}\n\nfunction hsvToRgb(h: number, s: number, v: number): { r: number; g: number; b: number } {\n const c = v * s\n const hh = (((h % 360) + 360) % 360) / 60\n const x = c * (1 - Math.abs((hh % 2) - 1))\n const [r1, g1, b1] = hh < 1 ? [c, x, 0]\n : hh < 2 ? [x, c, 0]\n : hh < 3 ? [0, c, x]\n : hh < 4 ? [0, x, c]\n : hh < 5 ? [x, 0, c]\n : [c, 0, x]\n const m = v - c\n return { r: (r1 + m) * 255, g: (g1 + m) * 255, b: (b1 + m) * 255 }\n}\n\nfunction clampDegree(degree: number): number {\n return (((Number.isFinite(degree) ? degree : 0) % 360) + 360) % 360\n}\n\nfunction clamp01(number: number): number {\n return Math.min(1, Math.max(0, Number.isFinite(number) ? number : 0))\n}\n\nonMounted(() => {\n document.addEventListener('pointerdown', onDocumentPointerDown, true)\n window.addEventListener('scroll', onWindowCloseEvents, true)\n window.addEventListener('resize', onWindowCloseEvents)\n document.addEventListener('keydown', onKeydown)\n})\n\nonBeforeUnmount(() => {\n document.removeEventListener('pointerdown', onDocumentPointerDown, true)\n window.removeEventListener('scroll', onWindowCloseEvents, true)\n window.removeEventListener('resize', onWindowCloseEvents)\n document.removeEventListener('keydown', onKeydown)\n})\n</script>\n\n<style scoped>\n.preset-color-trigger {\n display: flex;\n align-items: center;\n width: 100%;\n min-height: 26px;\n padding: 1px;\n border: 1px solid var(--pd-border, #d9dde6);\n border-radius: 6px;\n background: #fff;\n cursor: pointer;\n transition: border-color .14s ease, box-shadow .14s ease;\n}\n\n.preset-color-trigger:hover,\n.preset-color-trigger[aria-expanded=\"true\"] {\n border-color: var(--pd-accent, #165DFF);\n}\n\n.preset-color-trigger:focus-visible {\n outline: none;\n border-color: var(--pd-accent, #165DFF);\n box-shadow: 0 0 0 2px rgb(22 93 255 / 12%);\n}\n\n.preset-color-swatch {\n width: 100%;\n height: 22px;\n border-radius: 4px;\n background-image: linear-gradient(45deg, #e9ecef 25%, transparent 25%, transparent 75%, #e9ecef 75%);\n background-size: 8px 8px;\n background-position: 0 0, 4px 4px;\n}\n\n.preset-color-panel {\n position: fixed;\n z-index: 3000;\n width: 190px;\n padding: 10px;\n border: 1px solid var(--pd-border, #d9dde6);\n border-radius: 8px;\n background: #fff;\n box-shadow: 0 8px 24px rgb(23 32 60 / 16%);\n}\n\n.picker-preview {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 8px;\n}\n\n.picker-current {\n flex: 0 0 26px;\n height: 24px;\n border: 1px solid rgb(0 0 0 / 12%);\n border-radius: 5px;\n}\n\n.picker-hex {\n flex: 1;\n min-width: 0;\n height: 24px;\n padding: 0 6px;\n border: 1px solid var(--pd-border, #d9dde6);\n border-radius: 5px;\n color: var(--pd-text, #303133);\n font: inherit;\n font-size: 11px;\n text-transform: uppercase;\n}\n\n.picker-hex:focus {\n outline: none;\n border-color: var(--pd-accent, #165DFF);\n box-shadow: 0 0 0 2px rgb(22 93 255 / 12%);\n}\n\n.picker-area {\n position: relative;\n height: 100px;\n border: 1px solid rgb(0 0 0 / 12%);\n border-radius: 6px;\n overflow: hidden;\n cursor: crosshair;\n touch-action: none;\n background:\n linear-gradient(to top, #000, transparent),\n linear-gradient(to right, #fff, hsl(var(--picker-hue) 100% 50%));\n}\n\n.picker-handle {\n position: absolute;\n width: 12px;\n height: 12px;\n border: 2px solid #fff;\n border-radius: 50%;\n transform: translate(-50%, -50%);\n box-shadow: 0 0 3px rgb(0 0 0 / 45%);\n pointer-events: none;\n}\n\n.picker-hue {\n width: 100%;\n height: 14px;\n margin: 10px 0 0;\n appearance: none;\n border: 1px solid rgb(0 0 0 / 12%);\n border-radius: 999px;\n background: linear-gradient(to right, #f00, #ff0, #0f0, #0ff, #00f, #f0f, #f00);\n cursor: pointer;\n}\n\n.picker-hue::-webkit-slider-thumb {\n appearance: none;\n width: 12px;\n height: 12px;\n border: 2px solid #fff;\n border-radius: 50%;\n background: transparent;\n box-shadow: 0 0 3px rgb(0 0 0 / 45%);\n}\n\n.picker-hue::-moz-range-thumb {\n width: 8px;\n height: 8px;\n border: 2px solid #fff;\n border-radius: 50%;\n background: transparent;\n box-shadow: 0 0 3px rgb(0 0 0 / 45%);\n}\n\n.picker-heading {\n margin-top: 10px;\n margin-bottom: 6px;\n font-size: 11px;\n color: var(--pd-text-muted, #909399);\n}\n\n.preset-color-grid {\n display: grid;\n grid-template-columns: repeat(6, 1fr);\n gap: 5px;\n}\n\n.preset-color-item {\n width: 22px;\n height: 22px;\n padding: 0;\n border: 1px solid rgb(0 0 0 / 12%);\n border-radius: 5px;\n cursor: pointer;\n}\n\n.preset-color-item.active {\n box-shadow: 0 0 0 2px #fff, 0 0 0 3px var(--pd-accent, #165DFF);\n}\n</style>\n","<template>\n <PropertyGroup title=\"外观\" icon=\"Brush\" default-expanded group-key=\"appearance\">\n <form class=\"pd-form\" @submit.prevent>\n <template v-if=\"isTextType\">\n <div class=\"pd-field\" v-show=\"showItem('ap-font-size')\"><span class=\"pd-label\">字体大小</span>\n <input type=\"number\" class=\"pd-input\" v-model.number=\"element.options.fontSize\"\n :min=\"8\"\n :max=\"72\"\n style=\"width: 100%\" />\n </div>\n <div class=\"pd-field\" v-show=\"showItem('ap-font-weight')\"><span class=\"pd-label\">字体粗细</span>\n <select class=\"pd-select\" v-model=\"element.options.fontWeight\" style=\"width: 100%\">\n <option value=\"normal\">正常</option>\n <option value=\"bold\">粗体</option>\n <option value=\"bolder\">更粗</option>\n <option value=\"lighter\">细体</option>\n </select>\n </div>\n <div class=\"pd-field\" v-show=\"showItem('ap-align')\"><span class=\"pd-label\">对齐</span>\n <div class=\"pd-radio-group\" role=\"radiogroup\">\n <label class=\"pd-radio\"><input type=\"radio\" v-model=\"element.options.textAlign\" value=\"left\"><span>左</span></label>\n <label class=\"pd-radio\"><input type=\"radio\" v-model=\"element.options.textAlign\" value=\"center\"><span>中</span></label>\n <label class=\"pd-radio\"><input type=\"radio\" v-model=\"element.options.textAlign\" value=\"right\"><span>右</span></label>\n </div>\n </div>\n <div class=\"pd-field\" v-show=\"showItem('ap-vertical-align')\"><span class=\"pd-label\">垂直对齐</span>\n <div class=\"pd-radio-group\" role=\"radiogroup\">\n <label class=\"pd-radio\"><input type=\"radio\" v-model=\"element.options.verticalAlign\" value=\"top\"><span>顶</span></label>\n <label class=\"pd-radio\"><input type=\"radio\" v-model=\"element.options.verticalAlign\" value=\"middle\"><span>中</span></label>\n <label class=\"pd-radio\"><input type=\"radio\" v-model=\"element.options.verticalAlign\" value=\"bottom\"><span>底</span></label>\n </div>\n </div>\n <div class=\"color-row\">\n <div class=\"pd-field\" v-show=\"showItem('ap-color')\"><span class=\"pd-label\">颜色</span>\n <PresetColorPicker v-model=\"element.options.color\" />\n </div>\n <div class=\"pd-field\" v-show=\"showItem('ap-bg-color')\"><span class=\"pd-label\">背景色</span>\n <PresetColorPicker v-model=\"element.options.backgroundColor\" />\n </div>\n </div>\n <div class=\"pd-field\" v-show=\"showItem('ap-line-height')\"><span class=\"pd-label\">行高</span>\n <input type=\"number\" class=\"pd-input\" v-model.number=\"element.options.lineHeight\"\n :min=\"0\"\n :max=\"100\"\n style=\"width: 100%\" />\n </div>\n <div class=\"pd-field\" v-show=\"showItem('ap-letter-spacing')\"><span class=\"pd-label\">字间距</span>\n <input type=\"number\" class=\"pd-input\" v-model.number=\"element.options.letterSpacing\"\n :min=\"0\"\n :max=\"20\"\n :step=\"0.5\"\n style=\"width: 100%\" />\n </div>\n </template>\n\n <p class=\"pd-empty\" v-if=\"!isTextType && !isTableType\">当前元素不支持外观设置</p>\n </form>\n </PropertyGroup>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport type { RuntimeElement } from '../../types'\nimport PresetColorPicker from '../PresetColorPicker.vue'\nimport PropertyGroup from './PropertyGroup.vue'\n\nconst props = defineProps<{\n element: RuntimeElement\n isTextType: boolean\n matchedKeys?: Set<string>\n searching?: boolean\n}>()\n\nfunction showItem(key: string): boolean {\n if (!props.searching) {\n return true\n }\n return props.matchedKeys?.has(key) ?? true\n}\n\nconst isTableType = computed(() => {\n return props.element.printElementType.type === 'table'\n})\n</script>\n\n<style scoped>\n.color-row {\n display: flex;\n gap: 16px;\n}</style>","<template>\n <div v-if=\"visible\" class=\"pd-dialog-overlay\" @keydown.esc=\"visible = false\">\n <section class=\"pd-dialog pd-dialog-large\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"expression-editor-title\">\n <header class=\"pd-dialog-header\">\n <strong id=\"expression-editor-title\">编辑表达式</strong>\n <button type=\"button\" class=\"pd-close\" aria-label=\"关闭\" @click=\"visible = false\">×</button>\n </header>\n <div class=\"expression-editor\">\n <!-- 左侧导航栏 -->\n <div class=\"ee-nav\">\n <div class=\"ee-nav-title\">类型</div>\n <div class=\"ee-nav-tabs\">\n <div\n class=\"ee-nav-tab\"\n :class=\"{ active: activeTab === 'field' }\"\n @click=\"activeTab = 'field'\"\n >\n 📁 字段\n </div>\n <div\n class=\"ee-nav-tab\"\n :class=\"{ active: activeTab === 'variable' }\"\n @click=\"activeTab = 'variable'\"\n >\n 🔧 变量\n </div>\n <div\n class=\"ee-nav-tab\"\n :class=\"{ active: activeTab === 'function' }\"\n @click=\"activeTab = 'function'\"\n >\n ⚡ 函数\n </div>\n </div>\n </div>\n\n <!-- 中间内容区 -->\n <div class=\"ee-content\">\n <div class=\"ee-content-search\">\n <input class=\"pd-input\" v-model=\"searchText\"\n :placeholder=\"searchPlaceholder\" />\n </div>\n <div class=\"ee-content-list\">\n <!-- 字段列表(按 fieldKey 首段分组:supplier.*/receiver.*/goods.* 等) -->\n <template v-if=\"activeTab === 'field'\">\n <template v-for=\"group in filteredGroups\" :key=\"group.key || '_top'\">\n <div v-if=\"group.key\" class=\"ee-field-group\" :class=\"{ 'is-list': group.isList }\">\n <span class=\"ee-field-group-icon\">{{ group.isList ? '📋' : '📁' }}</span>\n <span>{{ group.label }}</span>\n </div>\n <div\n v-for=\"field in group.fields\"\n :key=\"field.fieldKey\"\n class=\"ee-list-item ee-field-item\"\n :style=\"{ paddingLeft: group.key ? '22px' : '10px' }\"\n @dblclick=\"handleFieldDoubleClick(field)\"\n >\n <label class=\"ee-field-row\">\n <input\n type=\"checkbox\"\n class=\"pd-checkbox\"\n :checked=\"selectedFields.has(field.fieldKey)\"\n @change=\"toggleField(field)\"\n @click.stop\n />\n <span class=\"ee-item-label\">{{ field.fieldLabel }}</span>\n <span class=\"ee-item-key\">{{ field.fieldKey }}</span>\n </label>\n </div>\n </template>\n <p v-if=\"filteredGroups.length === 0\" class=\"pd-empty\">暂无字段</p>\n </template>\n\n <!-- 变量列表 -->\n <template v-if=\"activeTab === 'variable'\">\n <div\n v-for=\"sv in filteredSystemVars\"\n :key=\"sv.name\"\n class=\"ee-list-item\"\n @dblclick=\"handleItemDoubleClick(sv.template)\"\n >\n <div class=\"ee-item-label\">{{ sv.label }}</div>\n <div class=\"ee-item-key\">{{ sv.name }}</div>\n </div>\n </template>\n\n <!-- 函数列表 -->\n <template v-if=\"activeTab === 'function'\">\n <div class=\"ee-func-group\">\n <div class=\"ee-func-group-title\">聚合函数</div>\n <div\n v-for=\"fn in filteredAggregateFuncs\"\n :key=\"fn.name\"\n class=\"ee-list-item\"\n @dblclick=\"handleAggregateDoubleClick(fn)\"\n >\n <div class=\"ee-item-label\">{{ fn.label }}</div>\n <div class=\"ee-item-key\">{{ fn.name }}</div>\n </div>\n </div>\n <div class=\"ee-func-group\">\n <div class=\"ee-func-group-title\">格式化函数</div>\n <div\n v-for=\"fn in filteredFormatFuncs\"\n :key=\"fn.name\"\n class=\"ee-list-item\"\n @dblclick=\"handleItemDoubleClick(fn.template)\"\n >\n <div class=\"ee-item-label\">{{ fn.label }}</div>\n <div class=\"ee-item-key\">{{ fn.name }}</div>\n </div>\n </div>\n </template>\n </div>\n </div>\n\n <!-- 右侧编辑区 -->\n <div class=\"ee-editor\">\n <div class=\"ee-editor-section\">\n <div class=\"ee-editor-title\">表达式编辑</div>\n <textarea\n ref=\"textareaRef\"\n v-model=\"localExpression\"\n class=\"ee-textarea\"\n rows=\"6\"\n placeholder=\"双击左侧字段/函数插入表达式,如: {fieldKey} 或 SUM(amount)\"\n />\n </div>\n\n <div class=\"ee-editor-section\">\n <div class=\"ee-editor-title\">预览结果</div>\n <div class=\"ee-preview\" :class=\"{ 'ee-preview-error': previewResult === '(表达式错误)' }\">{{ previewResult }}</div>\n </div>\n\n <div class=\"ee-help-section\">\n <div class=\"ee-help-title\">帮助信息</div>\n <div class=\"ee-help-grid\">\n <div class=\"ee-help-card ee-help-field\">\n <div class=\"ee-help-card-title\">字段绑定</div>\n <div class=\"ee-help-card-content\">\n 使用 {字段名} 格式<br>\n 示例: {order.no}\n </div>\n </div>\n <div class=\"ee-help-card ee-help-function\">\n <div class=\"ee-help-card-title\">函数使用</div>\n <div class=\"ee-help-card-content\">\n SUM(字段) - 求和<br>\n AVG(字段) - 平均值<br>\n COUNT(字段) - 计数\n </div>\n </div>\n <div class=\"ee-help-card ee-help-variable\">\n <div class=\"ee-help-card-title\">系统变量</div>\n <div class=\"ee-help-card-content\">\n {page} - 当前页码<br>\n {total} - 总页数<br>\n {row} - 当前行号\n </div>\n </div>\n <div class=\"ee-help-card ee-help-conditional\">\n <div class=\"ee-help-card-title\">条件判断</div>\n <div class=\"ee-help-card-content\">\n IF(条件, 真值, 假值)<br>\n 示例: IF(amount>1000, \"大单\", \"小单\")\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n <footer class=\"pd-dialog-footer\">\n <button type=\"button\" class=\"pd-button\" @click=\"visible = false\">取消</button>\n <button type=\"button\" class=\"pd-button primary\" @click=\"onConfirm\">确定</button>\n </footer>\n </section>\n</div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, watch, nextTick } from 'vue'\nimport type { PrintBusinessField } from '../types'\nimport { evaluateTemplate } from '../utils/expression-eval'\nimport { DEFAULT_DEMO_DATA } from '../utils/demo-data'\nimport { groupFields, filterGroups } from '../utils/field-groups'\n\nconst props = defineProps<{\n modelValue: boolean\n expression: string\n /** 宿主传入的业务字段(字段页数据源) */\n fields?: PrintBusinessField[]\n}>()\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: boolean]\n 'update:expression': [value: string]\n}>()\n\nconst visible = computed({\n get: () => props.modelValue,\n set: (val) => emit('update:modelValue', val),\n})\n\n// 新增状态\nconst activeTab = ref<'field' | 'variable' | 'function'>('field')\n\n// 搜索占位符\nconst searchPlaceholder = computed(() => {\n switch (activeTab.value) {\n case 'field': return '搜索字段...'\n case 'variable': return '搜索变量...'\n case 'function': return '搜索函数...'\n default: return '搜索...'\n }\n})\n\n// 字段列表(宿主注入的扁平业务字段,按 fieldKey 首段分组展示)\nconst searchText = ref('')\nconst filteredGroups = computed(() =>\n filterGroups(groupFields(props.fields ?? []), searchText.value),\n)\n\n// 字段多选模式\nconst selectedFields = ref<Set<string>>(new Set())\n\nfunction toggleField(field: PrintBusinessField) {\n const key = field.fieldKey\n const next = new Set(selectedFields.value)\n if (next.has(key)) {\n next.delete(key)\n } else {\n next.add(key)\n }\n selectedFields.value = next\n}\n\n// 当弹出框打开时,根据当前 expression 值尝试匹配已选字段\nwatch(visible, (val) => {\n if (val) {\n // 每次打开时重置为外部传入值,避免携带上次编辑残留\n localExpression.value = props.expression || ''\n const found = (props.fields ?? []).find(\n f => props.expression === f.fieldKey || props.expression === `{${f.fieldKey}}`,\n )\n if (found) {\n selectedFields.value = new Set([found.fieldKey])\n }\n } else {\n selectedFields.value = new Set()\n }\n})\n\n// 字段双击处理\nfunction handleFieldDoubleClick(field: PrintBusinessField) {\n insertAtCursor(`{${field.fieldKey}}`)\n}\n\n// 聚合函数双击 — 自动填充选中字段\nfunction handleAggregateDoubleClick(fn: { name: string; template: string }) {\n if (selectedFields.value.size > 0) {\n const fields = Array.from(selectedFields.value).join(', ')\n insertAtCursor(`${fn.name}(${fields})`)\n } else {\n insertAtCursor(fn.template)\n }\n}\n\n// 通用双击处理(变量和格式化函数)\nfunction handleItemDoubleClick(text: string) {\n insertAtCursor(text)\n}\n\n// 过滤后的系统变量\nconst filteredSystemVars = computed(() => {\n if (!searchText.value.trim()) return systemVars\n const keyword = searchText.value.trim().toLowerCase()\n return systemVars.filter(sv =>\n sv.label.toLowerCase().includes(keyword) ||\n sv.name.toLowerCase().includes(keyword)\n )\n})\n\n// 过滤后的聚合函数\nconst filteredAggregateFuncs = computed(() => {\n if (!searchText.value.trim()) return aggregateFunctions\n const keyword = searchText.value.trim().toLowerCase()\n return aggregateFunctions.filter(fn =>\n fn.label.toLowerCase().includes(keyword) || fn.name.toLowerCase().includes(keyword)\n )\n})\n\n// 过滤后的格式化函数\nconst filteredFormatFuncs = computed(() => {\n if (!searchText.value.trim()) return formatFunctions\n const keyword = searchText.value.trim().toLowerCase()\n return formatFunctions.filter(fn =>\n fn.label.toLowerCase().includes(keyword) || fn.name.toLowerCase().includes(keyword)\n )\n})\n\n// 表达式编辑模式\nconst localExpression = ref(props.expression || '')\nconst textareaRef = ref<HTMLTextAreaElement | null>(null)\n\nwatch(() => props.expression, (val) => {\n localExpression.value = val || ''\n})\n\nconst aggregateFunctions = [\n { name: 'SUM', label: '求和', template: 'SUM()' },\n { name: 'AVG', label: '平均值', template: 'AVG()' },\n { name: 'COUNT', label: '计数', template: 'COUNT()' },\n { name: 'MIN', label: '最小值', template: 'MIN()' },\n { name: 'MAX', label: '最大值', template: 'MAX()' },\n]\n\nconst formatFunctions = [\n { name: 'MONEY', label: '金额格式化', template: 'MONEY()' },\n { name: 'DATE', label: '日期格式化', template: 'DATE()' },\n { name: 'UPPER', label: '大写金额', template: 'UPPER()' },\n { name: 'IF', label: '条件判断', template: 'IF()' },\n]\n\nconst systemVars = [\n { name: 'pageIndex', label: '当前页码', template: '{pageIndex}' },\n { name: 'totalPages', label: '总页数', template: '{totalPages}' },\n { name: 'printDate', label: '打印日期', template: '{printDate}' },\n { name: 'printTime', label: '打印时间', template: '{printTime}' },\n]\n\nconst previewResult = computed(() => {\n if (!localExpression.value.trim()) return '(输入表达式后预览)'\n try {\n const ctx = {\n ...DEFAULT_DEMO_DATA,\n // 系统变量示例值,与渲染端一致(print-render 在生成 HTML 时替换)\n pageIndex: 1,\n totalPages: 1,\n printDate: new Date().toISOString().split('T')[0],\n printTime: Date.now(),\n }\n const result = evaluateTemplate(localExpression.value, ctx)\n if (result === undefined || result === null) return '(无法计算)'\n return String(result)\n } catch (e) {\n return '(表达式错误)'\n }\n})\n\nfunction insertAtCursor(text: string) {\n const ta = textareaRef.value\n if (!ta) {\n localExpression.value += text\n return\n }\n const start = ta.selectionStart\n const end = ta.selectionEnd\n const before = localExpression.value.substring(0, start)\n const after = localExpression.value.substring(end)\n localExpression.value = before + text + after\n nextTick(() => {\n ta.focus()\n ta.selectionStart = ta.selectionEnd = start + text.length\n })\n}\n\nfunction onConfirm() {\n emit('update:expression', localExpression.value)\n visible.value = false\n}\n</script>\n\n<style scoped>\n/* 主容器 */\n.expression-editor {\n display: flex;\n height: 450px;\n gap: 0;\n}\n\n/* 左侧导航 */\n.ee-nav {\n width: 100px;\n background: var(--pd-sidebar);\n border-right: 1px solid var(--pd-border);\n display: flex;\n flex-direction: column;\n flex-shrink: 0;\n}\n\n.ee-nav-title {\n padding: 10px;\n border-bottom: 1px solid var(--pd-border);\n font-weight: 600;\n font-size: 13px;\n color: var(--pd-text);\n text-align: center;\n}\n\n.ee-nav-tabs {\n flex: 1;\n display: flex;\n flex-direction: column;\n padding: 6px;\n gap: 4px;\n}\n\n.ee-nav-tab {\n padding: 8px 10px;\n border-radius: 6px;\n cursor: pointer;\n font-size: 12px;\n text-align: center;\n transition: all 0.2s;\n}\n\n.ee-nav-tab.active {\n background: var(--pd-accent);\n color: white;\n}\n\n.ee-nav-tab:not(.active) {\n background: white;\n border: 1px solid var(--pd-border);\n color: var(--pd-text);\n}\n\n.ee-nav-tab:hover:not(.active) {\n background: #ecf5ff;\n border-color: var(--pd-accent);\n}\n\n/* 中间内容区 */\n.ee-content {\n width: 300px;\n display: flex;\n flex-direction: column;\n border-right: 1px solid var(--pd-border);\n flex-shrink: 0;\n}\n\n.ee-content-search {\n padding: 10px;\n border-bottom: 1px solid var(--pd-border);\n}\n\n.ee-content-list {\n flex: 1;\n padding: 8px;\n overflow-y: auto;\n min-height: 0;\n}\n\n/* 函数分组 */\n.ee-func-group {\n margin-bottom: 12px;\n}\n\n.ee-func-group-title {\n font-size: 11px;\n font-weight: 600;\n color: var(--pd-text-muted);\n padding: 4px 10px 6px;\n border-bottom: 1px solid var(--pd-border);\n margin-bottom: 4px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n/* 字段分组标题 */\n.ee-field-group {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 6px 10px;\n font-size: 12px;\n font-weight: 600;\n color: var(--pd-text);\n}\n.ee-field-group.is-list {\n color: var(--pd-accent, #165DFF);\n}\n.ee-field-group-icon {\n font-size: 13px;\n filter: saturate(.6);\n}\n/* 列表项 */\n.ee-list-item {\n padding: 8px 10px;\n cursor: pointer;\n border-radius: 4px;\n margin-bottom: 4px;\n transition: all 0.2s;\n}\n.ee-field-row {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n.ee-field-row .ee-item-label {\n flex: 1;\n}\n\n.ee-list-item:hover {\n background: #ecf5ff;\n border-color: var(--pd-accent);\n}\n\n.ee-list-item .ee-item-label {\n font-size: 12px;\n color: var(--pd-text);\n}\n\n.ee-list-item .ee-item-key {\n font-size: 10px;\n color: var(--pd-text-muted);\n font-family: monospace;\n margin-top: 2px;\n}\n\n/* 右侧编辑区 */\n.ee-editor {\n flex: 1;\n display: flex;\n flex-direction: column;\n background: var(--pd-sidebar);\n min-width: 0;\n}\n\n.ee-editor-section {\n padding: 12px;\n border-bottom: 1px solid var(--pd-border);\n}\n\n.ee-editor-title {\n font-size: 11px;\n color: var(--pd-text-muted);\n margin-bottom: 6px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n/* 表达式编辑框 */\n.ee-textarea {\n width: 100%;\n border: 1px solid var(--pd-border);\n border-radius: 6px;\n padding: 10px;\n font-family: monospace;\n font-size: 13px;\n resize: vertical;\n box-sizing: border-box;\n min-height: 100px;\n}\n\n.ee-textarea:focus {\n outline: none;\n border-color: var(--pd-accent);\n}\n\n/* 预览结果 */\n.ee-preview {\n padding: 10px;\n background: var(--pd-bg);\n border: 1px solid var(--pd-border);\n border-radius: 6px;\n min-height: 30px;\n font-size: 13px;\n color: var(--pd-text);\n line-height: 1.6;\n}\n\n.ee-preview-error {\n color: #e53e3e;\n background: #fef2f2;\n border-color: #fecaca;\n}\n\n/* 帮助信息 */\n.ee-help-section {\n flex: 1;\n padding: 12px;\n overflow-y: auto;\n min-height: 0;\n}\n\n.ee-help-title {\n font-size: 11px;\n color: var(--pd-text-muted);\n margin-bottom: 8px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.ee-help-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 8px;\n}\n\n.ee-help-card {\n border-radius: 6px;\n padding: 10px;\n}\n\n.ee-help-card-title {\n font-size: 12px;\n font-weight: 600;\n margin-bottom: 4px;\n}\n\n.ee-help-card-content {\n font-size: 11px;\n line-height: 1.5;\n color: var(--pd-text);\n}\n\n.ee-help-field {\n background: #f0f9ff;\n border: 1px solid #bae6fd;\n}\n\n.ee-help-field .ee-help-card-title {\n color: #0369a1;\n}\n\n.ee-help-function {\n background: #f0fdf4;\n border: 1px solid #bbf7d0;\n}\n\n.ee-help-function .ee-help-card-title {\n color: #166534;\n}\n\n.ee-help-variable {\n background: #fefce8;\n border: 1px solid #fde68a;\n}\n\n.ee-help-variable .ee-help-card-title {\n color: #854d0e;\n}\n\n.ee-help-conditional {\n background: #fdf2f8;\n border: 1px solid #fbcfe8;\n}\n\n.ee-help-conditional .ee-help-card-title {\n color: #9d174d;\n}\n\n/* 弹窗内容区域 */\n.expression-editor {\n max-height: min(600px, 80vh);\n overflow-y: auto;\n padding: 16px;\n}\n</style>\n","<template>\n <div class=\"pd-field\"><span class=\"pd-label\">{{ descriptor.label }}</span>\n <input :value=\"modelValue\" class=\"pd-input\"\n :placeholder=\"descriptor.placeholder || '输入内容,支持 {字段} 表达式'\"\n @input=\"emit('update:modelValue', ($event.target as HTMLInputElement).value)\"\n @dblclick=\"openEditor\" />\n </div>\n <ExpressionEditor\n v-model=\"editorVisible\"\n :fields=\"fields\"\n :expression=\"modelValue\"\n @update:expression=\"(v: string) => emit('update:modelValue', v)\"\n />\n</template>\n\n<script setup lang=\"ts\">\nimport { ref } from 'vue'\nimport type { BindingDescriptor, PrintBusinessField } from '../../types'\nimport ExpressionEditor from '../ExpressionEditor.vue'\n\nconst props = defineProps<{\n descriptor: BindingDescriptor\n modelValue: string\n fields?: PrintBusinessField[]\n}>()\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', value: string): void\n}>()\n\nconst editorVisible = ref(false)\n\nfunction openEditor() {\n editorVisible.value = true\n}\n</script>\n\n<style scoped>\n.binding-control {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n</style>","<template>\n <PropertyGroup title=\"表格设置\" icon=\"Grid\" default-expanded group-key=\"table-settings\">\n <form class=\"pd-form\" @submit.prevent>\n <div class=\"pd-field\"><span class=\"pd-label\">列表数据源字段</span>\n <select :value=\"element.options.dataSource\" class=\"pd-select\"\n style=\"width: 100%\" @change=\"onSourceChange(($event.target as HTMLSelectElement).value)\">\n <option v-for=\"f in listFieldOptions\" :key=\"f.value\" :value=\"f.value\">{{ f.label }}</option>\n </select>\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">默认字号 (pt)</span>\n <input type=\"number\" class=\"pd-input\" v-model.number=\"element.options.tableDefaultFontSize\" :min=\"5\" :max=\"72\" />\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">默认文字颜色</span>\n <PresetColorPicker v-model=\"element.options.tableDefaultColor\" />\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">默认内边距 (mm)</span>\n <input type=\"number\" class=\"pd-input\" v-model.number=\"element.options.tableDefaultPadding\" :min=\"0\" :max=\"10\" :step=\"0.5\" />\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">列宽 (mm)</span>\n <div v-for=\"(w, i) in element.options.tableColWidths\" :key=\"i\" class=\"col-width-row\">\n <span style=\"width: 60px\">列{{ i + 1 }}</span>\n <input :value=\"w\" type=\"number\" class=\"pd-input\" :min=\"5\" :max=\"200\" :step=\"1\" @input=\"onColWidthChange(i, ($event.target as HTMLInputElement).valueAsNumber)\" />\n </div>\n </div>\n </form>\n </PropertyGroup>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, inject } from 'vue'\nimport PresetColorPicker from '../PresetColorPicker.vue'\nimport type { RuntimeElement, PrintBusinessField } from '../../types'\nimport { TABLE_EDIT_KEY } from '../../composables/useTableSelection'\nimport { syncTableElementSize } from '../../utils/table-matrix'\nimport PropertyGroup from './PropertyGroup.vue'\n\nconst props = defineProps<{\n element: RuntimeElement\n fields: PrintBusinessField[]\n}>()\n\nconst tableEditCtx = inject(TABLE_EDIT_KEY, null)\n\n/** 列表数据源选项:宿主以 fieldType='list' 声明明细列表字段 */\nconst listFieldOptions = computed(() => {\n return props.fields\n .filter(f => f.fieldType === 'list')\n .map(f => ({ label: f.fieldLabel, value: f.fieldKey }))\n})\n\nfunction onSourceChange(v: string) {\n props.element.options.dataSource = v || undefined\n tableEditCtx?.recordHistory()\n}\n\nfunction onColWidthChange(i: number, v: number | undefined) {\n if (v === undefined) return\n const widths = props.element.options.tableColWidths!\n const maxW = tableEditCtx?.maxTableWidth.value ?? Infinity\n const othersW = widths.reduce((s, w, idx) => idx === i ? s : s + w, 0)\n if (othersW + v > maxW) {\n const clamped = Math.max(5, Math.round((maxW - othersW) * 10) / 10)\n alert(`表格总宽不能超过打印范围宽度 ${maxW}mm,列${i + 1} 已调整为 ${clamped}mm`)\n widths[i] = clamped\n } else {\n widths[i] = v\n }\n syncTableElementSize(props.element.options)\n tableEditCtx?.recordHistory()\n}\n</script>\n\n<style scoped>\n.col-width-row {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 4px;\n width: 100%;\n}\n</style>","<template>\n <PropertyGroup title=\"边框与背景\" icon=\"Picture\" default-expanded group-key=\"border-bg\">\n <form class=\"pd-form\" @submit.prevent>\n <div class=\"border-row\">\n <div class=\"pd-field\" v-show=\"showItem('bb-border-width')\"><span class=\"pd-label\">边框宽度</span>\n <input type=\"number\" class=\"pd-input\" v-model.number=\"element.options.borderWidth\"\n :min=\"0\"\n :max=\"20\"\n :step=\"0.25\"\n />\n </div>\n <div class=\"pd-field\" v-show=\"showItem('bb-border-color')\"><span class=\"pd-label\">边框颜色</span>\n <PresetColorPicker v-model=\"element.options.borderColor\" />\n </div>\n </div>\n <div class=\"pd-field\" v-show=\"showItem('bb-bg-color')\"><span class=\"pd-label\">背景色</span>\n <PresetColorPicker v-model=\"element.options.backgroundColor\" />\n </div>\n </form>\n </PropertyGroup>\n</template>\n\n<script setup lang=\"ts\">\nimport type { RuntimeElement } from '../../types'\nimport PresetColorPicker from '../PresetColorPicker.vue'\nimport PropertyGroup from './PropertyGroup.vue'\n\nconst props = defineProps<{\n element: RuntimeElement\n matchedKeys?: Set<string>\n searching?: boolean\n}>()\n\nfunction showItem(key: string): boolean {\n if (!props.searching) {\n return true\n }\n return props.matchedKeys?.has(key) ?? true\n}\n</script>\n\n<style scoped>\n.border-row {\n display: flex;\n gap: 16px;\n}</style>","<template>\n <PropertyGroup title=\"高级设置\" icon=\"Setting\" group-key=\"advanced\">\n <form class=\"pd-form\" @submit.prevent>\n <div class=\"advanced-row\">\n <div class=\"pd-field\" v-show=\"showItem('ad-locked')\"><span class=\"pd-label\">锁定</span>\n <input type=\"checkbox\" class=\"pd-switch\" v-model=\"element.options.locked\" />\n </div>\n <div class=\"pd-field\" v-show=\"showItem('ad-fixed')\"><span class=\"pd-label\">每页重复</span>\n <input type=\"checkbox\" class=\"pd-switch\" v-model=\"element.options.fixed\" />\n </div>\n </div>\n <div class=\"pd-field\" v-show=\"showItem('ad-z-index')\"><span class=\"pd-label\">层级</span>\n <input type=\"number\" class=\"pd-input\" v-model.number=\"element.options.zIndex\"\n :min=\"0\"\n :max=\"999\"\n style=\"width: 100%\" />\n </div>\n <div class=\"pd-field\" v-show=\"showItem('ad-delete')\">\n <button type=\"button\" class=\"pd-button danger\" @click=\"$emit('delete-element')\">\n 删除元素\n </button>\n </div>\n </form>\n </PropertyGroup>\n</template>\n\n<script setup lang=\"ts\">\nimport type { RuntimeElement } from '../../types'\nimport PropertyGroup from './PropertyGroup.vue'\n\nconst props = defineProps<{\n element: RuntimeElement\n matchedKeys?: Set<string>\n searching?: boolean\n}>()\n\nfunction showItem(key: string): boolean {\n if (!props.searching) {\n return true\n }\n return props.matchedKeys?.has(key) ?? true\n}\n\ndefineEmits<{\n 'delete-element': []\n}>()\n</script>\n\n<style scoped>\n.advanced-row {\n display: flex;\n gap: 16px;\n}\n</style>\n","<template>\n <PropertyGroup title=\"分页配置\" icon=\"Document\" group-key=\"pagination\">\n <form class=\"pd-form\" @submit.prevent>\n <!-- 表格元素分页配置 -->\n <template v-if=\"isTable\">\n <div class=\"pd-field\" v-show=\"showItem('pg-enabled')\"><span class=\"pd-label\">启用分页</span>\n <input type=\"checkbox\" class=\"pd-switch\" :checked=\"tablePaginationEnabled\" @change=\"onTablePaginationChange(($event.target as HTMLInputElement).checked)\" />\n </div>\n </template>\n <!-- 非表格元素分页配置 -->\n <template v-else>\n <div class=\"pd-field\" v-show=\"showItem('pg-pageable')\"><span class=\"pd-label\">参与分页</span>\n <input type=\"checkbox\" class=\"pd-switch\" :checked=\"paginationPageable\" @change=\"onPageableChange(($event.target as HTMLInputElement).checked)\" />\n </div>\n <div class=\"pd-field\" v-show=\"showItem('pg-keep-with-next')\"><span class=\"pd-label\">与下元素同页</span>\n <input type=\"checkbox\" class=\"pd-switch\" :checked=\"paginationKeepWithNext\" @change=\"onKeepWithNextChange(($event.target as HTMLInputElement).checked)\" />\n </div>\n </template>\n </form>\n </PropertyGroup>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport type { RuntimeElement } from '../../types'\nimport PropertyGroup from './PropertyGroup.vue'\n\nconst props = defineProps<{\n element: RuntimeElement\n matchedKeys?: Set<string>\n searching?: boolean\n}>()\n\nconst isTable = computed(() => props.element.printElementType.type === 'table')\n\n// 表格分页\nconst tablePaginationEnabled = computed({\n get: () => props.element.options.tablePagination?.enabled ?? true,\n set: () => { /* 由 change 处理 */ },\n})\n\nfunction onTablePaginationChange(checked: boolean) {\n props.element.options.tablePagination = {\n enabled: checked,\n }\n}\n\n// 非表格分页\nconst paginationPageable = computed({\n get: () => props.element.options.pagination?.pageable ?? true,\n set: () => { /* 由 change 处理 */ },\n})\n\nconst paginationKeepWithNext = computed({\n get: () => props.element.options.pagination?.keepWithNext ?? false,\n set: () => { /* 由 change 处理 */ },\n})\n\nfunction onPageableChange(checked: boolean) {\n props.element.options.pagination = {\n pageable: checked,\n keepWithNext: paginationKeepWithNext.value,\n }\n}\n\nfunction onKeepWithNextChange(checked: boolean) {\n props.element.options.pagination = {\n pageable: paginationPageable.value,\n keepWithNext: checked,\n }\n}\n\nfunction showItem(key: string): boolean {\n if (!props.searching) return true\n return props.matchedKeys?.has(key) ?? true\n}\n</script>\n","<template>\n <div class=\"image-content-upload\">\n <label class=\"pd-button small upload-label\" :class=\"{ disabled: uploadDisabled }\">\n <svg class=\"pd-icon\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path fill=\"currentColor\" d=\"M12 3l4 4h-3v7h-2V7H8zm-7 12h14v5H5Z\" /></svg>\n {{ uploading ? '上传中...' : '上传图片' }}\n <input\n class=\"visually-hidden\"\n type=\"file\"\n accept=\"image/*\"\n :disabled=\"uploadDisabled\"\n @change=\"handleFileChange\"\n >\n </label>\n <p class=\"upload-tip\">支持 jpg/png/gif/bmp/webp/svg 等图片,上传后填入相对路径</p>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, inject, computed } from 'vue'\nimport { UPLOAD_IMAGE_KEY } from '../../composables/useHostAdapter'\n\nconst props = defineProps<{ disabled?: boolean }>()\n\nconst emit = defineEmits<{ success: [url: string] }>()\n\nconst uploading = ref(false)\n// 宿主注入的图片上传适配器;未注入时上传不可用\nconst uploadImage = inject(UPLOAD_IMAGE_KEY, computed(() => undefined))\nconst uploadDisabled = computed(() => props.disabled || uploading.value || !uploadImage.value)\n\nasync function handleFileChange(event: Event) {\n const input = event.target as HTMLInputElement\n const file = input.files?.[0]\n if (!file) return\n if (!file.type.startsWith('image/')) {\n alert('仅支持上传图片文件')\n input.value = ''\n return\n }\n if (!uploadImage.value) {\n alert('图片上传能力未配置')\n input.value = ''\n return\n }\n uploading.value = true\n try {\n const url = await uploadImage.value(file)\n if (url) {\n emit('success', url)\n } else {\n alert('图片上传失败')\n }\n } catch (err) {\n alert(err instanceof Error ? err.message : '图片上传失败')\n } finally {\n uploading.value = false\n input.value = ''\n }\n}\n</script>\n\n<style scoped>\n.image-content-upload {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 4px;\n margin-top: 4px;\n}\n.upload-label {\n cursor: pointer;\n}\n.upload-label.disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n.upload-tip {\n margin: 0;\n font-size: 11px;\n color: var(--pd-text-muted, #909399);\n}\n.visually-hidden {\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n}\n</style>\n","<!-- 表格行属性分组:行类型/行高/每页重复(小计行按页重复) -->\n<template>\n <PropertyGroup title=\"行属性\" icon=\"Grid\" default-expanded group-key=\"table-row\">\n <form class=\"pd-form\" @submit.prevent>\n <div class=\"pd-field\"><span class=\"pd-label\">行类型</span>\n <select :value=\"row.type\" class=\"pd-select\" style=\"width: 100%\" @change=\"onTypeChange(($event.target as HTMLSelectElement).value as TableRowType)\">\n <option value=\"header\">标题行</option>\n <option value=\"data\">数据行</option>\n <option value=\"subtotal\">小计行(每页小计)</option>\n <option value=\"summary\">汇总行</option>\n </select>\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">行高 (mm)</span>\n <input :value=\"row.height\" type=\"number\" class=\"pd-input\"\n :min=\"3\"\n :max=\"100\"\n :step=\"0.5\"\n style=\"width: 100%\" @input=\"onHeightChange(($event.target as HTMLInputElement).valueAsNumber)\" />\n </div>\n <div class=\"pd-field\" v-if=\"row.type === 'header'\"><span class=\"pd-label\">每页顶部重复</span>\n <input :checked=\"row.repeatOnPage ?? false\" type=\"checkbox\" class=\"pd-switch\" @input=\"onRepeatChange(!!($event.target as HTMLInputElement).checked)\" />\n </div>\n </form>\n </PropertyGroup>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, inject } from 'vue'\nimport type { RuntimeElement, TableSelection, TableRowType } from '../../types'\nimport { setRowType, syncTableElementSize } from '../../utils/table-matrix'\nimport { TABLE_EDIT_KEY } from '../../composables/useTableSelection'\nimport PropertyGroup from './PropertyGroup.vue'\n\nconst props = defineProps<{ element: RuntimeElement; selection: TableSelection }>()\nconst ctx = inject(TABLE_EDIT_KEY)!\n\nconst row = computed(() => props.element.options.tableRows![props.selection.r1]!)\n\nfunction onTypeChange(t: TableRowType) {\n const err = setRowType(\n props.element.options.tableRows!,\n props.selection.r1,\n t,\n )\n if (err) {\n alert(err)\n return\n }\n ctx.recordHistory()\n}\n\nfunction onHeightChange(v: number | undefined) {\n if (v === undefined) return\n row.value.height = v\n syncTableElementSize(props.element.options)\n ctx.recordHistory()\n}\n\nfunction onRepeatChange(v: boolean) {\n row.value.repeatOnPage = v\n ctx.recordHistory()\n}\n</script>\n","<!-- 表格单元格分组:格式化/样式/边框/合并拆分 -->\n<template>\n <PropertyGroup title=\"单元格\" icon=\"Menu\" default-expanded group-key=\"table-cell\">\n <form class=\"pd-form\" @submit.prevent>\n <div class=\"pd-field\"><span class=\"pd-label\">单元格类型</span>\n <div class=\"pd-radio-group\" role=\"radiogroup\">\n <label class=\"pd-radio\"><input type=\"radio\" value=\"text\" :checked=\"(mainCell.cellType || 'text') === 'text'\" @change=\"onCellTypeChange(($event.target as HTMLInputElement).value)\"><span>文本</span></label>\n <label class=\"pd-radio\"><input type=\"radio\" value=\"barcode\" :checked=\"mainCell.cellType === 'barcode'\" @change=\"onCellTypeChange(($event.target as HTMLInputElement).value)\"><span>条形码</span></label>\n <label class=\"pd-radio\"><input type=\"radio\" value=\"qrcode\" :checked=\"mainCell.cellType === 'qrcode'\" @change=\"onCellTypeChange(($event.target as HTMLInputElement).value)\"><span>二维码</span></label>\n </div>\n </div>\n\n <div class=\"pd-field\" v-if=\"isBarcodeCell\"><span class=\"pd-label\">码制</span>\n <select :value=\"mainCell.barcodeType || 'CODE128'\" class=\"pd-select\" @change=\"write(c => { c.barcodeType = ($event.target as HTMLSelectElement).value || undefined })\">\n <option value=\"CODE128\">CODE128(通用)</option>\n <option value=\"EAN13\">EAN13(商品码)</option>\n <option value=\"EAN8\">EAN8</option>\n <option value=\"UPC\">UPC</option>\n <option value=\"CODE39\">CODE39</option>\n <option value=\"ITF14\">ITF14</option>\n </select>\n </div>\n <div class=\"pd-field\" v-if=\"isBarcodeCell\"><span class=\"pd-label\">显示文本</span>\n <input :checked=\"mainCell.showBarcodeText !== false\" type=\"checkbox\" class=\"pd-switch\" @input=\"write(c => { c.showBarcodeText = !!($event.target as HTMLInputElement).checked })\" />\n </div>\n <div class=\"pd-field\" v-if=\"isQrcodeCell\"><span class=\"pd-label\">纠错级别</span>\n <select :value=\"mainCell.qrCodeLevel || 'M'\" class=\"pd-select\" @change=\"write(c => { c.qrCodeLevel = ($event.target as HTMLSelectElement).value || undefined })\">\n <option value=\"L\">L(最低,容量大)</option>\n <option value=\"M\">M(推荐)</option>\n <option value=\"Q\">Q</option>\n <option value=\"H\">H(最高)</option>\n </select>\n </div>\n\n <div class=\"pd-field\"><span class=\"pd-label\">内容</span>\n <input :value=\"mainCell.formatter || ''\" class=\"pd-input\"\n placeholder=\"输入内容,支持 {字段} 表达式\"\n @input=\"write(c => { c.formatter = ($event.target as HTMLInputElement).value || undefined })\"\n @dblclick=\"openFormatterEditor\" />\n </div>\n\n <div class=\"pd-field\"><span class=\"pd-label\">水平对齐</span>\n <div class=\"pd-radio-group\" role=\"radiogroup\">\n <label class=\"pd-radio\"><input type=\"radio\" value=\"left\" :checked=\"mainCell.align === 'left'\" @change=\"onAlignChange(($event.target as HTMLInputElement).value)\"><span>左</span></label>\n <label class=\"pd-radio\"><input type=\"radio\" value=\"center\" :checked=\"mainCell.align === 'center'\" @change=\"onAlignChange(($event.target as HTMLInputElement).value)\"><span>中</span></label>\n <label class=\"pd-radio\"><input type=\"radio\" value=\"right\" :checked=\"mainCell.align === 'right'\" @change=\"onAlignChange(($event.target as HTMLInputElement).value)\"><span>右</span></label>\n </div>\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">垂直对齐</span>\n <div class=\"pd-radio-group\" role=\"radiogroup\">\n <label class=\"pd-radio\"><input type=\"radio\" value=\"top\" :checked=\"mainCell.valign === 'top'\" @change=\"onValignChange(($event.target as HTMLInputElement).value)\"><span>上</span></label>\n <label class=\"pd-radio\"><input type=\"radio\" value=\"middle\" :checked=\"mainCell.valign === 'middle'\" @change=\"onValignChange(($event.target as HTMLInputElement).value)\"><span>中</span></label>\n <label class=\"pd-radio\"><input type=\"radio\" value=\"bottom\" :checked=\"mainCell.valign === 'bottom'\" @change=\"onValignChange(($event.target as HTMLInputElement).value)\"><span>下</span></label>\n </div>\n </div>\n <div class=\"cell-style-grid\">\n <div class=\"pd-field\"><span class=\"pd-label\">字体</span>\n <select :value=\"mainCell.fontFamily\" class=\"pd-select\"\n placeholder=\"继承默认\" @change=\"write(c => { c.fontFamily = ($event.target as HTMLSelectElement).value || undefined })\">\n <option value=\"SimSun\">宋体</option>\n <option value=\"SimHei\">黑体</option>\n <option value=\"Microsoft YaHei\">微软雅黑</option>\n <option value=\"KaiTi\">楷体</option>\n <option value=\"FangSong\">仿宋</option>\n <option value=\"Arial\">Arial</option>\n </select>\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">字号 (pt)</span>\n <input :value=\"mainCell.fontSize\" type=\"number\" class=\"pd-input\"\n :min=\"5\"\n :max=\"72\" @input=\"write(c => { c.fontSize = ($event.target as HTMLInputElement).valueAsNumber ?? undefined })\" />\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">加粗</span>\n <input :checked=\"mainCell.fontWeight === 'bold'\" type=\"checkbox\" class=\"pd-switch\" @input=\"write(c => { c.fontWeight = ($event.target as HTMLInputElement).checked ? 'bold' : undefined })\" />\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">文字颜色</span>\n <PresetColorPicker :model-value=\"mainCell.color\" @update:model-value=\"write(c => { c.color = $event })\" />\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">背景色</span>\n <PresetColorPicker :model-value=\"mainCell.backgroundColor\" @update:model-value=\"write(c => { c.backgroundColor = $event })\" />\n </div>\n </div>\n\n <h3 class=\"pd-divider\">边框</h3>\n <div class=\"border-style-row\">\n <select class=\"pd-select\" v-model=\"borderStyle\" style=\"width: 90px\">\n <option value=\"solid\">实线</option>\n <option value=\"dashed\">虚线</option>\n <option value=\"dotted\">点线</option>\n <option value=\"double\">双线</option>\n </select>\n <input type=\"number\" class=\"pd-input\" v-model.number=\"borderWidth\"\n :min=\"0.25\"\n :max=\"5\"\n :step=\"0.25\"\n style=\"width: 90px\" />\n <PresetColorPicker v-model=\"borderColor\" />\n </div>\n <div class=\"pd-button-group border-presets\">\n <button type=\"button\" class=\"pd-button small\" @click=\"preset('all')\">全部</button>\n <button type=\"button\" class=\"pd-button small\" @click=\"preset('outer')\">外侧</button>\n <button type=\"button\" class=\"pd-button small\" @click=\"preset('inner')\">内部</button>\n <button type=\"button\" class=\"pd-button small\" @click=\"preset('none')\">无</button>\n </div>\n <div class=\"pd-checkbox-group\">\n <label class=\"pd-checkbox\"><input type=\"checkbox\" v-model=\"edgeChecks\" value=\"top\" @change=\"onEdgesChange($event)\"><span>上</span></label>\n <label class=\"pd-checkbox\"><input type=\"checkbox\" v-model=\"edgeChecks\" value=\"right\" @change=\"onEdgesChange($event)\"><span>右</span></label>\n <label class=\"pd-checkbox\"><input type=\"checkbox\" v-model=\"edgeChecks\" value=\"bottom\" @change=\"onEdgesChange($event)\"><span>下</span></label>\n <label class=\"pd-checkbox\"><input type=\"checkbox\" v-model=\"edgeChecks\" value=\"left\" @change=\"onEdgesChange($event)\"><span>左</span></label>\n </div>\n\n <div class=\"pd-field\"><span class=\"pd-label\">内边距 (mm)</span>\n <input :value=\"mainCell.padding\" type=\"number\" class=\"pd-input\"\n :min=\"0\"\n :max=\"10\"\n :step=\"0.5\" @input=\"write(c => { c.padding = ($event.target as HTMLInputElement).valueAsNumber ?? undefined })\" />\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">自动换行</span>\n <input :checked=\"mainCell.wordWrap ?? true\" type=\"checkbox\" class=\"pd-switch\" @input=\"write(c => { c.wordWrap = !!($event.target as HTMLInputElement).checked })\" />\n </div>\n\n <div class=\"merge-btns\">\n <button type=\"button\" class=\"pd-button small\" :disabled=\"!!mergeReason\" :title=\"mergeReason || ''\" @click=\"doMerge\">\n 合并单元格\n </button>\n <button type=\"button\" class=\"pd-button small\" :disabled=\"!canSplit\" @click=\"doSplit\">拆分单元格</button>\n </div>\n </form>\n </PropertyGroup>\n\n <ExpressionEditor\n v-model=\"formatterEditorVisible\"\n :fields=\"fields\"\n :expression=\"pendingFormatterValue\"\n @update:expression=\"onFormatterEditorConfirm\"\n />\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, inject, ref } from 'vue'\nimport type {\n RuntimeElement, TableSelection, TableCell, TableCellBorder, TableCellBorders, TableCellType, TextAlign,\n PrintBusinessField,\n} from '../../types'\nimport {\n canMergeReason, mergeCells, splitCells, applyBorderPreset, findMainCell, type BorderPreset,\n} from '../../utils/table-matrix'\nimport { TABLE_EDIT_KEY } from '../../composables/useTableSelection'\nimport PropertyGroup from './PropertyGroup.vue'\nimport ExpressionEditor from '../ExpressionEditor.vue'\nimport PresetColorPicker from '../PresetColorPicker.vue'\n\nconst props = defineProps<{\n element: RuntimeElement\n selection: TableSelection\n fields: PrintBusinessField[]\n}>()\nconst ctx = inject(TABLE_EDIT_KEY)!\n\nconst rows = computed(() => props.element.options.tableRows!)\n\nconst mainCell = computed<TableCell>(() => {\n const m = findMainCell(rows.value, props.selection.r1, props.selection.c1)\n return rows.value[m.r]!.cells[m.c]!\n})\n\nconst formatterEditorVisible = ref(false)\nconst pendingFormatterValue = ref('')\n\nconst isBarcodeCell = computed(() => mainCell.value.cellType === 'barcode')\nconst isQrcodeCell = computed(() => mainCell.value.cellType === 'qrcode')\n\nfunction onAlignChange(v: string) {\n write(c => { c.align = v as TextAlign })\n}\n\nfunction onValignChange(v: string) {\n write(c => { c.valign = v as TableCell['valign'] })\n}\n\nfunction onCellTypeChange(v: string) {\n write(c => {\n c.cellType = v === 'text' ? undefined : (v as TableCellType)\n if (v !== 'barcode') {\n c.barcodeType = undefined\n c.showBarcodeText = undefined\n }\n if (v !== 'qrcode') c.qrCodeLevel = undefined\n })\n}\n\nfunction openFormatterEditor() {\n pendingFormatterValue.value = mainCell.value.formatter || ''\n formatterEditorVisible.value = true\n}\n\nfunction onFormatterEditorConfirm(val: string) {\n write(c => { c.formatter = val || undefined })\n}\n\nfunction write(fn: (c: TableCell) => void) {\n const s = props.selection\n for (let r = s.r1; r <= s.r2; r++) {\n for (let c = s.c1; c <= s.c2; c++) {\n const cell = rows.value[r]!.cells[c]!\n if (!cell.merged) fn(cell)\n }\n }\n ctx.recordHistory()\n}\n\nconst borderStyle = ref<TableCellBorder['style']>('solid')\nconst borderWidth = ref(0.75)\nconst borderColor = ref('#333333')\nconst edgeChecks = ref<string[]>([])\n\nfunction currentBorder(): TableCellBorder {\n return { width: borderWidth.value, style: borderStyle.value, color: borderColor.value }\n}\n\nfunction preset(p: BorderPreset) {\n applyBorderPreset(rows.value, props.selection, p, currentBorder())\n ctx.recordHistory()\n}\n\nfunction onEdgesChange(event: Event) {\n const input = event.target as HTMLInputElement\n const edges = new Set(edgeChecks.value)\n if (input.checked) edges.add(input.value)\n else edges.delete(input.value)\n edgeChecks.value = [...edges]\n const b = currentBorder()\n write(c => {\n const nb = { ...(c.borders ?? {}) } as Record<string, TableCellBorder | undefined>\n for (const side of ['top', 'right', 'bottom', 'left']) {\n if (edges.has(side)) nb[side] = { ...b }\n else delete nb[side]\n }\n c.borders = nb as TableCellBorders\n })\n}\n\nconst mergeReason = computed(() => canMergeReason(rows.value, props.selection))\n\nconst canSplit = computed(() => {\n const s = props.selection\n for (let r = s.r1; r <= s.r2; r++) {\n for (let c = s.c1; c <= s.c2; c++) {\n const cell = rows.value[r]!.cells[c]!\n if (!cell.merged && ((cell.rowspan ?? 1) > 1 || (cell.colspan ?? 1) > 1)) return true\n }\n }\n return false\n})\n\nfunction doMerge() {\n mergeCells(rows.value, props.selection)\n ctx.recordHistory()\n}\n\nfunction doSplit() {\n splitCells(rows.value, props.selection)\n ctx.recordHistory()\n}\n\ndefineExpose({ openFormatterEditor })\n</script>\n\n<style scoped>\n.cell-style-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 0 8px;\n}\n.border-style-row {\n display: flex;\n gap: 6px;\n margin-bottom: 8px;\n}\n.border-presets {\n margin-bottom: 8px;\n}\n.merge-btns {\n margin-top: 8px;\n display: flex;\n gap: 8px;\n}\n.field-row {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n}\n</style>\n","import type { BindingDescriptor } from '../types'\n\n/**\n * 元素绑定声明注册表\n * 每个元素类型声明其支持的 formatter 绑定位置\n */\nexport const ELEMENT_BINDING_REGISTRY: Record<string, BindingDescriptor[]> = {\n text: [\n { targetPath: 'options.formatter', label: '内容', dataSource: 'main' },\n ],\n longText: [\n { targetPath: 'options.formatter', label: '内容', dataSource: 'main' },\n { targetPath: 'options.styler', label: '样式', dataSource: 'main' },\n ],\n barcode: [\n { targetPath: 'options.formatter', label: '内容', dataSource: 'main' },\n ],\n qrcode: [\n { targetPath: 'options.formatter', label: '内容', dataSource: 'main' },\n ],\n image: [\n { targetPath: 'options.src', label: '内容', dataSource: 'main', placeholder: '输入图片路径,支持 /docfiles/... 相对路径、绝对 URL 或 {字段} 表达式' },\n ],\n table: [],\n}\n\nexport function getTableCellBindings(\n rowType: string,\n rowIndex: number,\n cellIndex: number,\n listField?: string,\n): BindingDescriptor[] {\n if (rowType === 'data') {\n return [{\n targetPath: `options.tableRows[${rowIndex}].cells[${cellIndex}].formatter`,\n label: '内容',\n dataSource: 'list',\n listField,\n placeholder: '{name}',\n }]\n }\n if (rowType === 'subtotal') {\n return [{\n targetPath: `options.tableRows[${rowIndex}].cells[${cellIndex}].formatter`,\n label: '内容',\n dataSource: 'subtotal',\n placeholder: '{MONEY(SUM(amount))}',\n }]\n }\n if (rowType === 'summary') {\n return [{\n targetPath: `options.tableRows[${rowIndex}].cells[${cellIndex}].formatter`,\n label: '内容',\n dataSource: 'summary',\n placeholder: '{MONEY(SUM(amount))}',\n }]\n }\n return [{\n targetPath: `options.tableRows[${rowIndex}].cells[${cellIndex}].formatter`,\n label: '内容',\n dataSource: 'main',\n placeholder: '合计: {order.total}',\n }]\n}\n\nexport function getElementBindings(element: any): BindingDescriptor[] {\n const type = element.printElementType.type\n const staticBindings = ELEMENT_BINDING_REGISTRY[type] ?? []\n const dynamicBindings: BindingDescriptor[] = []\n\n if (type === 'table') {\n const listField = element.options.dataSource\n for (const [ri, row] of (element.options.tableRows ?? []).entries()) {\n for (const [ci, cell] of row.cells.entries()) {\n if (cell.merged) continue\n dynamicBindings.push(...getTableCellBindings(row.type, ri, ci, listField))\n }\n }\n }\n\n return [...staticBindings, ...dynamicBindings]\n}\n","<template>\n <div class=\"property-panel\" :class=\"{ collapsed }\">\n <!-- 折叠态:竖排图标,点击即展开对应页签 -->\n <div v-if=\"collapsed\" class=\"prop-collapsed\">\n <button class=\"pc-btn\" title=\"展开属性台\" @click=\"expandTab(currentTab)\">«</button>\n <button class=\"pc-btn\" :class=\"{ on: currentTab === 'element' }\" title=\"元素属性\" @click=\"expandTab('element')\">▦</button>\n <button class=\"pc-btn\" :class=\"{ on: currentTab === 'page' }\" title=\"页面属性\" @click=\"expandTab('page')\">▤</button>\n </div>\n <template v-else>\n <div class=\"prop-head\">\n <span class=\"prop-title\">属性台</span>\n <button class=\"collapse-btn\" title=\"收起属性台\" @click=\"$emit('toggle-collapse')\">»</button>\n </div>\n <div class=\"pd-tabs prop-tabs\">\n <div class=\"pd-tab-bar\" role=\"tablist\">\n <button type=\"button\" class=\"pd-tab\" :class=\"{ active: (activeTab || 'page') === 'element' }\" @click=\"$emit('update:activeTab', 'element')\">元素属性</button>\n <button type=\"button\" class=\"pd-tab\" :class=\"{ active: (activeTab || 'page') === 'page' }\" @click=\"$emit('update:activeTab', 'page')\">页面属性</button>\n </div>\n <div v-show=\"(activeTab || 'page') === 'element'\" class=\"pd-tab-pane\" role=\"tabpanel\">\n <template v-if=\"element\">\n <PropertySearch @search=\"onSearch\" />\n <div class=\"property-content\">\n <PositionSizeGroup v-if=\"filteredGroups.includes('position-size') && !isTableCellSelected\" :element=\"element\" :matched-keys=\"matchedKeys\" :searching=\"searching\" />\n <AppearanceGroup v-if=\"filteredGroups.includes('appearance')\" :element=\"element\" :is-text-type=\"isTextType\" :matched-keys=\"matchedKeys\" :searching=\"searching\" />\n <PropertyGroup v-if=\"filteredGroups.includes('binding')\" title=\"内容\" icon=\"Document\" default-expanded group-key=\"binding\">\n <BindingControl\n v-for=\"desc in bindingDescriptors\"\n :key=\"desc.targetPath\"\n :descriptor=\"desc\"\n :fields=\"fields\"\n :model-value=\"getBindingValue(desc.targetPath)\"\n @update:model-value=\"(v: string) => setBindingValue(desc.targetPath, v)\"\n />\n <ImageContentUpload\n v-if=\"isImageType\"\n @success=\"onImageUploadSuccess\"\n />\n </PropertyGroup>\n <!-- 表格行/单元格属性(需有选区) -->\n <template v-if=\"isTableType && tableSelection && tableSelection.elementId === element!.id\">\n <TableRowGroup :element=\"element!\" :selection=\"tableSelection\" />\n <TableCellGroup :element=\"element!\" :selection=\"tableSelection\" :fields=\"fields\" />\n </template>\n <!-- 表格设置(表格元素时显示) -->\n <TableSettingsGroup\n v-if=\"isTableType && filteredGroups.includes('content')\"\n :element=\"element!\"\n :fields=\"fields\"\n />\n <BorderBgGroup v-if=\"filteredGroups.includes('border-bg')\" :element=\"element\" :matched-keys=\"matchedKeys\" :searching=\"searching\" />\n <!-- 分页配置(表格元素) -->\n <PaginationGroup\n v-if=\"filteredGroups.includes('pagination') && isTableType\"\n :element=\"element\"\n :matched-keys=\"matchedKeys\"\n :searching=\"searching\"\n />\n <!-- 分页配置(非表格元素) -->\n <PaginationGroup\n v-if=\"filteredGroups.includes('pagination') && !isTableType\"\n :element=\"element\"\n :matched-keys=\"matchedKeys\"\n :searching=\"searching\"\n />\n <AdvancedGroup v-if=\"filteredGroups.includes('advanced')\" :element=\"element\" :matched-keys=\"matchedKeys\" :searching=\"searching\" @delete-element=\"$emit('delete-element')\" />\n </div>\n </template>\n <p class=\"pd-empty\" v-else>请在画布中选择一个元素</p>\n </div>\n\n <div v-show=\"(activeTab || 'page') === 'page'\" class=\"pd-tab-pane\" role=\"tabpanel\">\n <form class=\"pd-form\" @submit.prevent>\n <h3 class=\"pd-divider\">纸张设置</h3>\n\n <div class=\"pd-field\"><span class=\"pd-label\">纸张尺寸</span>\n <select :value=\"paperSizeModel\" class=\"pd-select\" @change=\"onPaperSizeChange(($event.target as HTMLSelectElement).value)\" style=\"width: 100%\">\n <option v-for=\"(_ps, key) in paperPresets\" :key=\"key\" :value=\"key\">{{ key }}</option>\n <option value=\"CUSTOM\">自定义</option>\n </select>\n </div>\n <div class=\"pd-field\" v-if=\"paperSizeModel === 'CUSTOM'\"><span class=\"pd-label\">自定义宽高 (mm)</span>\n <div class=\"custom-size-grid\">\n <input :value=\"customWidth\" type=\"number\" class=\"pd-input\"\n @input=\"onCustomWidthChange(($event.target as HTMLInputElement).valueAsNumber)\"\n :min=\"25\"\n :max=\"2000\"\n :step=\"1\"\n style=\"width: 100%\" />\n <span class=\"custom-size-x\">×</span>\n <input :value=\"customHeight\" type=\"number\" class=\"pd-input\"\n @input=\"onCustomHeightChange(($event.target as HTMLInputElement).valueAsNumber)\"\n :min=\"25\"\n :max=\"2000\"\n :step=\"1\"\n style=\"width: 100%\" />\n </div>\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">方向</span>\n <div class=\"pd-radio-group\" role=\"radiogroup\">\n <label class=\"pd-radio\"><input type=\"radio\" value=\"portrait\" :checked=\"orientationModel === 'portrait'\" @change=\"onOrientationChange(($event.target as HTMLInputElement).value)\"><span>纵向</span></label>\n <label class=\"pd-radio\"><input type=\"radio\" value=\"landscape\" :checked=\"orientationModel === 'landscape'\" @change=\"onOrientationChange(($event.target as HTMLInputElement).value)\"><span>横向</span></label>\n </div>\n </div>\n\n <h3 class=\"pd-divider\">页边距 (mm)</h3>\n <div class=\"margin-grid\">\n <div class=\"pd-field\"><span class=\"pd-label\">上</span>\n <input :value=\"marginTop\" type=\"number\" class=\"pd-input\" @input=\"onMarginTopChange(($event.target as HTMLInputElement).valueAsNumber)\" :min=\"0\" :max=\"50\" :step=\"1\" style=\"width: 100%\" />\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">下</span>\n <input :value=\"marginBottom\" type=\"number\" class=\"pd-input\" @input=\"onMarginBottomChange(($event.target as HTMLInputElement).valueAsNumber)\" :min=\"0\" :max=\"50\" :step=\"1\" style=\"width: 100%\" />\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">左</span>\n <input :value=\"marginLeft\" type=\"number\" class=\"pd-input\" @input=\"onMarginLeftChange(($event.target as HTMLInputElement).valueAsNumber)\" :min=\"0\" :max=\"50\" :step=\"1\" style=\"width: 100%\" />\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">右</span>\n <input :value=\"marginRight\" type=\"number\" class=\"pd-input\" @input=\"onMarginRightChange(($event.target as HTMLInputElement).valueAsNumber)\" :min=\"0\" :max=\"50\" :step=\"1\" style=\"width: 100%\" />\n </div>\n </div>\n\n <h3 class=\"pd-divider\">三区高度 (mm)</h3>\n <div class=\"pd-field\"><span class=\"pd-label\">页眉高度</span>\n <input :value=\"headerHeight\" type=\"number\" class=\"pd-input\" @input=\"onHeaderHeightChange(($event.target as HTMLInputElement).valueAsNumber)\" :min=\"0\" :max=\"100\" :step=\"0.1\" style=\"width: 100%\" />\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">页脚高度</span>\n <input :value=\"footerHeight\" type=\"number\" class=\"pd-input\" @input=\"onFooterHeightChange(($event.target as HTMLInputElement).valueAsNumber)\" :min=\"0\" :max=\"100\" :step=\"0.1\" style=\"width: 100%\" />\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">首页叠加高度</span>\n <input :value=\"overlayHeight\" type=\"number\" class=\"pd-input\" @input=\"onOverlayHeightChange(($event.target as HTMLInputElement).valueAsNumber)\" :min=\"0\" :max=\"200\" style=\"width: 100%\" />\n </div>\n </form>\n </div>\n </div>\n </template>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport type { RuntimeElement, PrintBusinessField, TemplateData, TableSelection } from '../types'\nimport { PAPER_PRESETS } from '../utils/default-config'\nimport { searchProperties } from '../utils/property-search'\nimport PropertySearch from './property/PropertySearch.vue'\nimport PositionSizeGroup from './property/PositionSizeGroup.vue'\nimport AppearanceGroup from './property/AppearanceGroup.vue'\nimport PropertyGroup from './property/PropertyGroup.vue'\nimport BindingControl from './property/BindingControl.vue'\nimport TableSettingsGroup from './property/TableSettingsGroup.vue'\nimport BorderBgGroup from './property/BorderBgGroup.vue'\nimport AdvancedGroup from './property/AdvancedGroup.vue'\nimport PaginationGroup from './property/PaginationGroup.vue'\nimport ImageContentUpload from './property/ImageContentUpload.vue'\nimport TableRowGroup from './property/TableRowGroup.vue'\nimport TableCellGroup from './property/TableCellGroup.vue'\nimport { getElementBindings, getTableCellBindings } from '../utils/binding-registry'\nimport type { BindingDescriptor } from '../types'\n\nconst props = defineProps<{\n element: RuntimeElement | null\n templateData?: TemplateData\n fields: PrintBusinessField[]\n activeTab?: 'element' | 'page'\n tableSelection?: TableSelection | null\n recordHistory?: () => void\n collapsed: boolean\n}>()\n\nconst emit = defineEmits<{\n 'delete-element': []\n 'update:templateData': [data: TemplateData]\n 'update:activeTab': [tab: 'element' | 'page']\n 'toggle-collapse': []\n}>()\n\nconst paperPresets = PAPER_PRESETS\nconst searchText = ref('')\n\nconst isTextType = computed(() => {\n if (!props.element) return false\n return ['text', 'longText'].includes(props.element.printElementType.type)\n})\n\nconst isImageType = computed(() => {\n if (!props.element) return false\n return props.element.printElementType.type === 'image'\n})\n\n/** 是否处于表格单元格选中态:单元格的位置与宽高由行高/列宽控制,隐藏「位置与尺寸」组 */\nconst isTableCellSelected = computed(() => {\n if (!props.element) return false\n if (props.element.printElementType.type !== 'table') return false\n return !!props.tableSelection && props.tableSelection.elementId === props.element.id\n})\n\nconst isTableType = computed(() => {\n if (!props.element) return false\n return props.element.printElementType.type === 'table'\n})\n\nconst searchResult = computed(() => searchProperties(searchText.value))\nconst filteredGroups = computed(() => searchResult.value.groups)\nconst matchedKeys = computed(() => searchResult.value.itemKeys)\nconst searching = computed(() => !!searchText.value.trim())\n\nconst bindingDescriptors = computed<BindingDescriptor[]>(() => {\n if (!props.element) return []\n\n // 当有表格选区时,只返回选中单元格的绑定描述符\n if (props.element.printElementType.type === 'table' && props.tableSelection) {\n const { r1, c1 } = props.tableSelection\n const rows = props.element.options.tableRows\n if (rows && rows[r1]) {\n const row = rows[r1]\n const listField = props.element.options.fields?.[0]?.dataSource\n return getTableCellBindings(row.type, r1, c1, listField)\n }\n }\n\n return getElementBindings(props.element)\n})\n\n/**\n * 统一解析带点分段与数组下标的 targetPath 为段/索引混排数组\n * 例:'options.formatter' → ['options','formatter']\n * 例:'options.tableRows[0].cells[1].formatter' → ['options','tableRows',0,'cells',1,'formatter']\n */\nfunction parsePath(targetPath: string): (string | number)[] {\n return targetPath.split('.').flatMap(segment => {\n const match = segment.match(/^([^\\[]+)((?:\\[\\d+\\])*)$/)\n if (!match) return [segment]\n const baseName = match[1]!\n const indices = [...match[2]!.matchAll(/\\[(\\d+)\\]/g)].map(m => Number(m[1]!))\n return [baseName, ...indices]\n })\n}\n\nfunction getBindingValue(targetPath: string): string {\n if (!props.element) return ''\n const segments = parsePath(targetPath)\n const result = segments.reduce((current, seg) => {\n if (current === null || current === undefined) return ''\n return current[seg as keyof typeof current]\n }, props.element as any)\n return result ?? ''\n}\n\nfunction setBindingValue(targetPath: string, value: string) {\n if (!props.element) return\n const segments = parsePath(targetPath)\n const lastKey = segments.pop()!\n const obj = segments.reduce((current, seg) => {\n if (current[seg] === undefined || current[seg] === null) current[seg] = {}\n return current[seg]\n }, props.element as any)\n obj[lastKey] = value || undefined\n props.recordHistory?.()\n}\n\nfunction onSearch(text: string) {\n searchText.value = text\n}\n\n/** 图片上传成功:将相对路径写入 options.src(内容输入框绑定路径) */\nfunction onImageUploadSuccess(url: string) {\n if (!props.element) return\n setBindingValue('options.src', url)\n}\n\n// ─── 页面属性模型(直接读写 templateData) ───\n\nconst paperSizeModel = computed(() => props.templateData?.paperSize || 'A4')\nconst orientationModel = computed(() => props.templateData?.orientation || 'portrait')\n\nconst marginTop = computed(() => props.templateData?.margins.top ?? 10)\nconst marginBottom = computed(() => props.templateData?.margins.bottom ?? 10)\nconst marginLeft = computed(() => props.templateData?.margins.left ?? 10)\nconst marginRight = computed(() => props.templateData?.margins.right ?? 10)\n\nconst headerHeight = computed(() => props.templateData?.header.height ?? 10)\nconst footerHeight = computed(() => props.templateData?.footer.height ?? 10)\nconst overlayHeight = computed(() => props.templateData?.firstPageOverlay.height ?? 0)\n\nconst customWidth = computed(() => props.templateData?.customWidth ?? 210)\nconst customHeight = computed(() => props.templateData?.customHeight ?? 297)\n\nfunction emitUpdate(partial: Partial<TemplateData>) {\n if (!props.templateData) return\n emit('update:templateData', { ...props.templateData, ...partial })\n}\n\nfunction onPaperSizeChange(size: string) {\n if (size === 'CUSTOM') {\n emitUpdate({ paperSize: 'CUSTOM' })\n return\n }\n if (!paperPresets[size]) return\n emitUpdate({ paperSize: size as TemplateData['paperSize'] })\n}\n\nfunction onOrientationChange(val: string | number | boolean | undefined) {\n emitUpdate({ orientation: String(val) as TemplateData['orientation'] })\n}\n\nfunction onCustomWidthChange(v: number | undefined) {\n if (v === undefined) return\n emitUpdate({ customWidth: v })\n}\n\nfunction onCustomHeightChange(v: number | undefined) {\n if (v === undefined) return\n emitUpdate({ customHeight: v })\n}\n\nfunction onMarginTopChange(v: number | undefined) {\n if (v === undefined) return\n emitUpdate({ margins: { ...props.templateData!.margins, top: v } })\n}\nfunction onMarginBottomChange(v: number | undefined) {\n if (v === undefined) return\n emitUpdate({ margins: { ...props.templateData!.margins, bottom: v } })\n}\nfunction onMarginLeftChange(v: number | undefined) {\n if (v === undefined) return\n emitUpdate({ margins: { ...props.templateData!.margins, left: v } })\n}\nfunction onMarginRightChange(v: number | undefined) {\n if (v === undefined) return\n emitUpdate({ margins: { ...props.templateData!.margins, right: v } })\n}\n\nfunction onHeaderHeightChange(v: number | undefined) {\n if (v === undefined) return\n emitUpdate({ header: { ...props.templateData!.header, height: v } })\n}\n\nfunction onFooterHeightChange(v: number | undefined) {\n if (v === undefined) return\n emitUpdate({ footer: { ...props.templateData!.footer, height: v } })\n}\n\nfunction onOverlayHeightChange(v: number | undefined) {\n if (v === undefined) return\n emitUpdate({\n firstPageOverlay: { ...props.templateData!.firstPageOverlay, height: v },\n })\n}\n\nconst currentTab = computed(() => props.activeTab || 'page')\n\nfunction expandTab(tab: 'element' | 'page') {\n emit('update:activeTab', tab)\n emit('toggle-collapse')\n}\n</script>\n\n<style scoped>\n.property-panel {\n width: 280px;\n min-width: 280px;\n background: var(--pd-sidebar, #ffffff);\n border-left: 1px solid var(--pd-border-soft, #e9ecf2);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n transition: width .18s ease;\n}\n.property-panel.collapsed {\n width: 36px;\n min-width: 36px;\n border-left: 1px solid var(--pd-border-soft, #e9ecf2);\n}\n.prop-collapsed {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n padding-top: 12px;\n flex: 1;\n}\n.pc-btn {\n width: 26px;\n height: 26px;\n border-radius: 6px;\n border: 1px solid transparent;\n background: transparent;\n color: var(--pd-text-muted, #8b909c);\n font-size: 12px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all .14s ease;\n}\n.pc-btn:hover {\n color: var(--pd-text, #2a2e37);\n background: var(--pd-sidebar-hover, #f0f3f9);\n}\n.pc-btn.on {\n color: var(--pd-accent, #165DFF);\n background: var(--pd-accent-soft, rgba(22, 93, 255, .09));\n}\n.prop-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n height: 42px;\n padding: 0 12px;\n flex-shrink: 0;\n border-bottom: 1px solid var(--pd-border-soft, #e9ecf2);\n}\n.prop-title {\n font-size: 12px;\n font-weight: 600;\n color: var(--pd-text, #2a2e37);\n letter-spacing: 1.2px;\n display: inline-flex;\n align-items: center;\n gap: 7px;\n}\n.prop-title::before {\n content: \"\";\n width: 3px;\n height: 12px;\n border-radius: 2px;\n background: linear-gradient(180deg, var(--pd-accent-2, #3D7BFF), var(--pd-accent, #165DFF));\n}\n.collapse-btn {\n border: none;\n background: transparent;\n color: var(--pd-text-muted, #8b909c);\n font-size: 14px;\n cursor: pointer;\n width: 24px;\n height: 24px;\n border-radius: 5px;\n transition: all .14s ease;\n}\n.collapse-btn:hover {\n color: var(--pd-text, #2a2e37);\n background: var(--pd-sidebar-hover, #f0f3f9);\n}\n.prop-tabs {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n.prop-tabs .pd-tab-pane {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n padding: 12px;\n}\n.property-content {\n padding: 0;\n}\n.margin-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 0 12px;\n}\n.custom-size-grid {\n display: grid;\n grid-template-columns: 1fr auto 1fr;\n align-items: center;\n gap: 4px;\n width: 100%;\n}\n.custom-size-x {\n color: var(--pd-text-muted, #8b909c);\n font-size: 12px;\n}\n</style>\n","<template>\n <div class=\"status-bar\">\n <span class=\"status-item coord\" v-if=\"coordinate\">\n x:{{ coordinate.x.toFixed(1) }}&nbsp;y:{{ coordinate.y.toFixed(1) }}mm\n </span>\n <span class=\"status-item\">缩放 {{ scale }}%</span>\n <span class=\"status-item\">元素 {{ elementCount }}{{ selectedCount ? ` (选中 ${selectedCount})` : '' }}</span>\n <span class=\"status-dirty\" :class=\"{ on: dirty }\">\n <span class=\"dirty-dot\" />{{ dirty ? '未保存' : '已保存' }}\n </span>\n <span class=\"status-item status-paper\">{{ paper }}</span>\n </div>\n</template>\n\n<script setup lang=\"ts\">\ndefineProps<{\n coordinate: { x: number; y: number } | null\n scale: number\n elementCount: number\n selectedCount: number\n paper: string\n dirty: boolean\n}>()\n</script>\n\n<style scoped>\n.status-bar {\n display: flex;\n align-items: center;\n gap: 20px;\n height: 30px;\n padding: 0 16px;\n background: var(--pd-surface, #ffffff);\n border-top: 1px solid var(--pd-border-soft, #e9ecf2);\n box-shadow: 0 -1px 2px rgba(23, 32, 60, .03);\n font-size: 11.5px;\n color: var(--pd-text-muted, #8b909c);\n user-select: none;\n flex-shrink: 0;\n}\n.status-item {\n white-space: nowrap;\n font-variant-numeric: tabular-nums;\n display: inline-flex;\n align-items: center;\n}\n.coord {\n font-variant-numeric: tabular-nums;\n color: var(--pd-text, #2a2e37);\n}\n.status-paper {\n margin-left: auto;\n font-variant-numeric: tabular-nums;\n color: var(--pd-accent, #165DFF);\n font-weight: 600;\n}\n.status-dirty {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n white-space: nowrap;\n color: var(--pd-text-muted, #8b909c);\n}\n.status-dirty.on {\n color: var(--pd-accent-secondary, #f56c6c);\n}\n.dirty-dot {\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background: var(--pd-ink-green, #67c23a);\n}\n.status-dirty.on .dirty-dot {\n background: var(--pd-accent-secondary, #f56c6c);\n box-shadow: 0 0 0 3px rgba(245, 108, 108, .14);\n animation: dirty-pulse 1.6s ease-in-out infinite;\n}\n@keyframes dirty-pulse {\n 0%, 100% { box-shadow: 0 0 0 2px rgba(245, 108, 108, .12); }\n 50% { box-shadow: 0 0 0 4px rgba(245, 108, 108, .05); }\n}\n@media (prefers-reduced-motion: reduce) {\n .status-dirty.on .dirty-dot { animation: none; }\n}\n</style>\n","import { ref, watch } from 'vue'\n\nconst LEFT_KEY = 'print-studio:left'\nconst RIGHT_KEY = 'print-studio:right'\n\nfunction readStored(key: string, fallback: boolean): boolean {\n try {\n const raw = localStorage.getItem(key)\n return raw === null ? fallback : raw === '1'\n } catch {\n return fallback\n }\n}\n\nexport function useStudioChrome() {\n const leftCollapsed = ref(readStored(LEFT_KEY, false))\n const rightCollapsed = ref(readStored(RIGHT_KEY, false))\n const dirty = ref(false)\n\n watch(leftCollapsed, v => { try { localStorage.setItem(LEFT_KEY, v ? '1' : '0') } catch { /* ignore */ } }, { flush: 'sync' })\n watch(rightCollapsed, v => { try { localStorage.setItem(RIGHT_KEY, v ? '1' : '0') } catch { /* ignore */ } }, { flush: 'sync' })\n\n function toggleLeft() { leftCollapsed.value = !leftCollapsed.value }\n function toggleRight() { rightCollapsed.value = !rightCollapsed.value }\n function markSaved() { dirty.value = false }\n\n return { leftCollapsed, rightCollapsed, toggleLeft, toggleRight, dirty, markSaved }\n}\n","<template>\n <div class=\"designer-container\">\n <DesignerToolbar\n :is-edit=\"isEdit\"\n :can-undo=\"canUndo\"\n :can-redo=\"canRedo\"\n :has-multi-selection=\"selectedIds.size >= 2\"\n :has-selection=\"selectedIds.size >= 1\"\n :show-grid=\"showGrid\"\n :snap-to-grid=\"snapToGrid\"\n :show-table-ghost-border=\"showTableGhostBorder\"\n :selected-element-has-group=\"selectedElement?.options.groupId ? true : false\"\n :overlay-visible=\"overlayVisible\"\n :show-load-default=\"!!loadDefaultTemplate\"\n v-model:scale=\"scale\"\n @back=\"$emit('back')\"\n @preview=\"$emit('preview')\"\n @save=\"handleSave\"\n @load-default=\"handleLoadDefault\"\n @undo=\"onUndo\"\n @redo=\"onRedo\"\n @align=\"(mode: string) => onAlign(mode as AlignMode)\"\n @move-layer=\"onMoveLayer\"\n @toggle-grid=\"showGrid = !showGrid\"\n @toggle-snap=\"snapToGrid = !snapToGrid\"\n @toggle-table-ghost-border=\"showTableGhostBorder = !showTableGhostBorder\"\n @toggle-overlay=\"toggleOverlay\"\n @group=\"onGroup\"\n @ungroup=\"onUngroup\"\n @add-overlay-element=\"onAddOverlayElement\"\n @fit-window=\"onFitWindow\"\n @zoom=\"onZoom\"\n />\n\n <!-- 三栏布局 -->\n <div class=\"designer-body\">\n <LeftPanel\n :fields=\"fields\"\n :elements=\"elements\"\n :selected-ids=\"selectedIds\"\n :collapsed=\"leftCollapsed\"\n @select=\"onSelectElement\"\n @move-layer=\"onMoveLayer\"\n @toggle-visible=\"onToggleVisible\"\n @toggle-locked=\"onToggleLocked\"\n @toggle-collapse=\"toggleLeft\"\n />\n <CanvasArea\n ref=\"canvasAreaRef\"\n :template-data=\"templateData\"\n :elements=\"elements\"\n :scale=\"scale / 100\"\n :show-grid=\"showGrid\"\n :snap-to-grid=\"snapToGrid\"\n :show-table-ghost-border=\"showTableGhostBorder\"\n :has-clipboard=\"hasClipboard\"\n :guides=\"guides\"\n :overlay-visible=\"overlayVisible\"\n :screenshot-url=\"screenshotUrl\"\n :overlay-opacity=\"overlayOpacity\"\n :selected-element-has-group=\"selectedElement?.options.groupId ? true : false\"\n @select=\"onSelectElement\"\n @drop-element=\"onDropElement\"\n @drop-field=\"onDropField\"\n @drag-start=\"onDragStart\"\n @drag-stop=\"onDragStop\"\n @dblclick-element=\"onDblClickElement\"\n @dblclick-cell=\"onDblClickCell\"\n @zone-height-change=\"onZoneHeightChange\"\n @zone-height-commit=\"onZoneHeightCommit\"\n @select-all=\"selectAll\"\n @clear-selection=\"clearSelection\"\n @preview=\"setPreview\"\n @commit-preview=\"commitPreview\"\n @paste=\"paste\"\n @copy=\"copy\"\n @cut=\"cutSelected\"\n @delete=\"onDeleteElement\"\n @move-layer=\"onMoveLayer\"\n @coordinate=\"onCoordinate\"\n @group=\"onGroup\"\n @ungroup=\"onUngroup\"\n @add-guide=\"addGuide\"\n @guide-move=\"moveGuide\"\n @guide-remove=\"removeGuide\"\n @zoom=\"onZoom\"\n @clone-element=\"onCloneElement\"\n />\n <PropertyPanel\n :element=\"selectedElement\"\n :template-data=\"templateData\"\n :fields=\"fields\"\n :table-selection=\"tableSelection\"\n :record-history=\"recordHistory\"\n :collapsed=\"rightCollapsed\"\n v-model:active-tab=\"activePropertyTab\"\n @delete-element=\"onDeleteElement\"\n @update:template-data=\"onTemplateDataChanged\"\n @toggle-collapse=\"toggleRight\"\n />\n </div>\n <StatusBar\n :coordinate=\"coordinate\"\n :scale=\"scale\"\n :element-count=\"elements.length\"\n :selected-count=\"selectedIds.size\"\n :paper=\"paperLabel\"\n :dirty=\"dirty\"\n />\n\n <!-- 设计稿双击元素/单元格打开的表达式编辑器 -->\n <ExpressionEditor\n v-model=\"dblEditorVisible\"\n :fields=\"fields\"\n :expression=\"dblEditorExpression\"\n @update:expression=\"onDblEditorConfirm\"\n />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport '../styles/native-controls.css'\nimport { ref, watch, provide, computed, onMounted, onUnmounted } from 'vue'\nimport type { RuntimeElement, PrintBusinessField, TemplateData, TableCell, RequestScreenshotFn, UploadImageFn } from '../types'\nimport { useDesignerState } from '../composables/useDesignerState'\nimport { useGuides } from '../composables/useGuides'\nimport { TABLE_EDIT_KEY } from '../composables/useTableSelection'\nimport { SELECTED_IDS_KEY, PREVIEW_IDS_KEY } from '../composables/useSelection'\nimport { getZoneRects } from '../utils/zone-layout'\nimport { getPaperDimensions } from '../utils/default-config'\nimport { DEFAULT_DEMO_DATA } from '../utils/demo-data'\nimport { findMainCell } from '../utils/table-matrix'\nimport { UPLOAD_IMAGE_KEY } from '../composables/useHostAdapter'\nimport type { AlignMode } from '../composables/useAlign'\nimport DesignerToolbar from './DesignerToolbar.vue'\nimport LeftPanel from './LeftPanel.vue'\nimport CanvasArea from './CanvasArea.vue'\nimport PropertyPanel from './PropertyPanel.vue'\nimport StatusBar from './StatusBar.vue'\nimport ExpressionEditor from './ExpressionEditor.vue'\nimport { useStudioChrome } from '../composables/useStudioChrome'\n\nconst props = defineProps<{\n initialTemplate?: TemplateData\n initialElements?: RuntimeElement[]\n fields?: PrintBusinessField[]\n isEdit?: boolean\n /** 截图适配器(叠层对比):未注入时该功能不可用 */\n requestScreenshot?: RequestScreenshotFn\n /** 图片上传适配器:未注入时图片上传不可用 */\n uploadImage?: UploadImageFn\n /** 加载默认布局回调(宿主实现业务逻辑;未注入时工具栏不展示该按钮),返回 null/undefined 视为无默认布局 */\n loadDefaultTemplate?: () => TemplateData | Promise<TemplateData | null | undefined> | null | undefined\n}>()\n\nconst emit = defineEmits<{\n back: []\n preview: []\n save: [json: string]\n}>()\n\n// 装配层状态:面板折叠(localStorage 持久)+ 未保存 dirty\nconst { leftCollapsed, rightCollapsed, toggleLeft, toggleRight, dirty, markSaved } = useStudioChrome()\n\n// 设计器核心状态统一由 useDesignerState 管理\nconst {\n scale, showGrid, snapToGrid, showTableGhostBorder,\n templateData, elements, fields,\n selectedIds, selectedElement, select, clearSelection, selectAll,\n previewIds, setPreview, commitPreview,\n hasClipboard, copy, paste, cutSelected,\n canUndo, canRedo, undo: onUndo, redo: onRedo,\n alignSelected: onAlign,\n groupSelected: onGroup, ungroupSelected: onUngroup, deleteSelected: onDeleteElement,\n dragStart: onDragStart, dragStop: onDragStop,\n addElement: onDropElement, addFieldElement: onDropField,\n moveLayer: onMoveLayer, updateTemplateData, fitToWindow,\n getTemplateJson, loadTemplate,\n tableSelection, setTableSelection, recordHistory,\n} = useDesignerState({\n initialTemplate: props.initialTemplate,\n initialElements: props.initialElements,\n initialFields: props.fields,\n})\n\n// 未保存信号:任何元素/模板数据变化点亮\nwatch([elements, templateData], () => { dirty.value = true }, { deep: true })\n\nconst { guides, addGuide, moveGuide, removeGuide } = useGuides(templateData, recordHistory)\n\n// 表格单元格编辑上下文\nconst maxTableWidth = computed(() => {\n const t = templateData.value\n const { width: paperW } = getPaperDimensions(t)\n return paperW - t.margins.left - t.margins.right\n})\nprovide(TABLE_EDIT_KEY, { tableSelection, setTableSelection, recordHistory, maxTableWidth })\nprovide(SELECTED_IDS_KEY, selectedIds)\nprovide(PREVIEW_IDS_KEY, previewIds)\n\nprovide(UPLOAD_IMAGE_KEY, computed(() => props.uploadImage))\nwatch(selectedElement, el => {\n if (!el || el.printElementType.type !== 'table') setTableSelection(null)\n})\n\nconst canvasAreaRef = ref<InstanceType<typeof CanvasArea> | null>(null)\n\n// 叠层对比模式\nconst overlayVisible = ref(false)\nconst screenshotUrl = ref('')\nconst overlayOpacity = ref(0.5)\n\nasync function toggleOverlay() {\n if (overlayVisible.value) {\n overlayVisible.value = false\n return\n }\n const templateJson = getTemplateJson()\n if (!templateJson) {\n alert('模板数据为空')\n return\n }\n if (!props.requestScreenshot) {\n alert('截图服务未配置')\n return\n }\n try {\n const blob = await props.requestScreenshot({ templateJson, printData: DEFAULT_DEMO_DATA })\n if (screenshotUrl.value) URL.revokeObjectURL(screenshotUrl.value)\n screenshotUrl.value = URL.createObjectURL(blob)\n overlayVisible.value = true\n } catch {\n alert('截图生成失败')\n }\n}\n\n// 状态栏:鼠标坐标(纸面 mm)\nconst coordinate = ref<{ x: number; y: number } | null>(null)\nfunction onCoordinate(pos: { x: number; y: number } | null) { coordinate.value = pos }\n\nconst paperLabel = computed(() => {\n const t = templateData.value\n const dim = getPaperDimensions(t)\n const orient = t.orientation === 'landscape' ? '横向' : '纵向'\n return `${t.paperSize} ${orient} ${Math.round(dim.width)}×${Math.round(dim.height)}mm`\n})\n\nfunction onFitWindow() {\n const el = (canvasAreaRef.value as any)?.$el as HTMLElement | undefined\n if (el) fitToWindow(el.clientWidth, el.clientHeight)\n}\nfunction onZoom(delta: number) {\n scale.value = Math.min(200, Math.max(50, scale.value + delta))\n}\n\n// Ctrl+0 适应窗口:需容器尺寸,由本组件单独监听(useKeyboard 不处理)\nfunction onKeyFitWindow(e: KeyboardEvent) {\n const tag = (e.target as HTMLElement).tagName\n if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT') return\n if ((e.ctrlKey || e.metaKey) && e.key === '0') {\n e.preventDefault()\n onFitWindow()\n }\n}\nonMounted(() => document.addEventListener('keydown', onKeyFitWindow))\nonUnmounted(() => document.removeEventListener('keydown', onKeyFitWindow))\n\nfunction onTemplateDataChanged(data: TemplateData) {\n const prevHeader = templateData.value.header.height\n const prevFooter = templateData.value.footer.height\n updateTemplateData(data)\n if (data.header.height < prevHeader) warnZoneOverflow('header')\n if (data.footer.height < prevFooter) warnZoneOverflow('footer')\n}\n\nfunction onZoneHeightChange(zone: 'header' | 'footer', height: number) {\n templateData.value = {\n ...templateData.value,\n [zone]: { ...templateData.value[zone], height },\n }\n}\n\nfunction onZoneHeightCommit(zone: 'header' | 'footer') {\n updateTemplateData({ ...templateData.value })\n warnZoneOverflow(zone)\n}\n\nfunction warnZoneOverflow(zone: 'header' | 'footer') {\n const rect = getZoneRects(templateData.value)[zone]\n const overflow = elements.value.some(e => e.zone === zone\n && (e.options.top + e.options.height > rect.height\n || e.options.left + e.options.width > rect.width))\n if (overflow) {\n alert(`${zone === 'header' ? '页眉' : '页脚'}高度已小于区域内元素,请手动调整元素位置`)\n }\n}\n\nfunction onAddOverlayElement() {\n const overlay = templateData.value.firstPageOverlay\n const newEl = {\n options: { left: 0, top: 0, width: 50, height: 10, title: '首页叠加' },\n printElementType: { type: 'text' as const, title: '首页叠加' },\n }\n templateData.value = {\n ...templateData.value,\n firstPageOverlay: { ...overlay, elements: [...overlay.elements, newEl] },\n }\n}\n\nconst onSelectElement = select\n\nfunction onToggleVisible(id: string) {\n const el = elements.value.find(e => e.id === id)\n if (el) el.options.visible = el.options.visible === false ? true : false\n}\n\nfunction onToggleLocked(id: string) {\n const el = elements.value.find(e => e.id === id)\n if (el) el.options.locked = !el.options.locked\n}\n\nconst activePropertyTab = ref<'element' | 'page'>('page')\nwatch(selectedElement, (el) => {\n activePropertyTab.value = el ? 'element' : 'page'\n})\n\n/** 双击可打开表达式编辑器的元素类型 → 对应表达式字段(无内容表达式的类型不在此列) */\nconst DBL_EDITABLE_FIELD: Record<string, string> = {\n text: 'formatter',\n longText: 'formatter',\n barcode: 'formatter',\n qrcode: 'formatter',\n}\nconst dblEditorVisible = ref(false)\nconst dblEditTarget = ref<\n { kind: 'element'; element: RuntimeElement; field: string } | { kind: 'cell'; cell: TableCell } | null\n>(null)\nconst dblEditorExpression = ref('')\n\nfunction onDblClickElement(id: string) {\n const el = elements.value.find(e => e.id === id)\n if (!el) return\n select(id, false)\n activePropertyTab.value = 'element'\n // 锁定元素不弹编辑器(保持选中,避免绕过锁定护栏)\n if (el.options.locked) return\n const field = DBL_EDITABLE_FIELD[el.printElementType.type]\n if (!field) return\n dblEditTarget.value = { kind: 'element', element: el, field }\n dblEditorExpression.value = (el.options as any)[field] || ''\n dblEditorVisible.value = true\n}\n\nfunction onDblClickCell(elId: string, r: number, c: number) {\n const el = elements.value.find(e => e.id === elId)\n if (!el) return\n select(elId, false)\n activePropertyTab.value = 'element'\n if (el.options.locked) return\n const rows = el.options.tableRows ?? []\n const main = findMainCell(rows, r, c)\n const cell = rows[main.r]?.cells[main.c]\n if (!cell) return\n dblEditTarget.value = { kind: 'cell', cell }\n dblEditorExpression.value = cell.formatter || ''\n dblEditorVisible.value = true\n}\n\nfunction onDblEditorConfirm(value: string) {\n const t = dblEditTarget.value\n if (t?.kind === 'element') {\n ;(t.element.options as any)[t.field] = value || undefined\n } else if (t?.kind === 'cell') {\n t.cell.formatter = value || undefined\n }\n recordHistory()\n dblEditorVisible.value = false\n dblEditTarget.value = null\n}\n\n/** Alt+拖拽克隆元素:将克隆元素添加到元素池并选中 */\nfunction onCloneElement(el: RuntimeElement, _pos: { left: number; top: number }) {\n elements.value.push(el)\n select(el.id, false)\n recordHistory()\n}\n\nwatch(() => props.initialTemplate, (t) => {\n if (t) loadTemplate(t, props.initialElements)\n})\nwatch(() => props.initialElements, (els) => {\n if (els && !props.initialTemplate) {\n templateData.value = {\n ...templateData.value,\n elements: els.map(e => ({ ...e, options: { ...e.options }, printElementType: { ...e.printElementType } })),\n }\n }\n})\nwatch(() => props.fields, (f) => { fields.value = f || [] })\n\ndefineExpose({ getTemplateJson })\n\nasync function handleLoadDefault() {\n if (!props.loadDefaultTemplate) return\n if (!confirm('将覆盖当前画布内容,是否继续?')) return\n try {\n const tpl = await props.loadDefaultTemplate()\n if (!tpl) {\n alert('未获取到默认布局')\n return\n }\n loadTemplate(tpl)\n alert('默认布局已加载')\n } catch {\n alert('加载默认布局失败')\n }\n}\n\nfunction handleSave() {\n emit('save', JSON.stringify(getTemplateJson()))\n markSaved()\n}\n</script>\n\n<style scoped>\n.designer-container {\n /* ── 精工排版工作台令牌:冷灰底 + 白纸 + 蓝墨点缀 ── */\n --pd-bg: #f3f5f9; /* 应用底色 / 内嵌控件底 */\n --pd-surface: #ffffff; /* 工具栏、状态栏、面板表面 */\n --pd-field-bg: #f4f6fa; /* 卡片、内嵌输入槽 */\n --pd-sidebar: #ffffff;\n --pd-sidebar-hover: #f0f3f9;\n --pd-canvas-bg: #e6e9f0; /* 排版垫:略深,托起纸张 */\n --pd-paper: #FFFFFF;\n --pd-accent: #165DFF;\n --pd-accent-2: #3D7BFF;\n --pd-accent-soft: rgba(22, 93, 255, .09);\n --pd-accent-secondary: #f56c6c;\n --pd-danger-soft: rgba(245, 108, 108, .10);\n --pd-ink-green: #67c23a;\n --pd-text: #2a2e37;\n --pd-text-muted: #8b909c;\n --pd-text-faint: #b4b9c4;\n --pd-border: #d9dde6;\n --pd-border-soft: #e9ecf2;\n --pd-handle: #165DFF;\n --pd-ruler: #9aa1af;\n --pd-ruler-bg: #f8f9fc;\n --pd-ruler-cursor: #165DFF;\n --pd-radius: 6px;\n --pd-shadow-sm: 0 1px 2px rgba(23, 32, 60, .05);\n --pd-shadow-md: 0 2px 8px rgba(23, 32, 60, .06), 0 10px 28px rgba(23, 32, 60, .07);\n --pd-shadow-paper: 0 0 0 1px rgba(23, 32, 60, .05),\n 0 1px 2px rgba(23, 32, 60, .06),\n 0 8px 20px rgba(23, 32, 60, .08),\n 0 26px 60px rgba(23, 32, 60, .15);\n height: 100%;\n display: flex;\n flex-direction: column;\n background: var(--pd-bg);\n}\n.designer-body {\n flex: 1;\n display: flex;\n overflow: hidden;\n}\n</style>\n","// print-canvas/src/render/browser-pagination.ts\n// 浏览器内两遍渲染:隐藏 iframe 写入测量 HTML → 读取元素实测高度 →\n// 复用 print-core 分页算法 → 生成最终多页 HTML(与 print-render 的 pdf-render 同款逻辑)。\n\nimport {\n bindData,\n generateHtml,\n paginate,\n getPaperDimensions,\n} from '@worm-vue3-print/core'\nimport type {\n PrintTemplateData,\n MeasuredElement,\n PageLayout,\n CodeRenderer,\n} from '@worm-vue3-print/core'\n\n/** 96dpi 下 1mm ≈ 3.78px(与服务端 page.evaluate 一致) */\nconst PX_PER_MM = 3.7795275591\n/** 字体/图片等待兜底超时 */\nconst READY_TIMEOUT_MS = 3000\n\nexport interface BrowserRenderResult {\n /** 最终多页 HTML 字符串 */\n html: string\n /** 总页数 */\n pageCount: number\n /** 分页布局(调试/高级用途) */\n pageLayouts: PageLayout[]\n}\n\n/**\n * 浏览器内完成「数据绑定 → 测量 → 分页 → 最终 HTML」全流程。\n * @param template 模板 JSON(设计器 TemplateData 结构兼容)\n * @param printData 业务数据\n * @param baseUrl 图片相对路径拼接前缀\n * @param codeRenderer 条码渲染器(browserCodeRenderer)\n */\nexport async function renderHtmlPages(\n template: PrintTemplateData,\n printData?: Record<string, any> | Record<string, any>[],\n baseUrl?: string,\n codeRenderer?: CodeRenderer,\n): Promise<BrowserRenderResult> {\n // Step 1: 数据绑定\n const boundTemplate = bindData(template, printData, baseUrl)\n\n // Step 2: 第一遍测量(隐藏 iframe)\n const measuredElements = await measureElements(boundTemplate, codeRenderer)\n\n // Step 3: 分页计算(与服务端同一套算法)\n const pageLayouts = paginate(boundTemplate, measuredElements)\n\n // Step 4: 最终多页 HTML\n const html = generateHtml(boundTemplate, pageLayouts, printData as Record<string, any>, {\n codeRenderer,\n })\n\n return { html, pageCount: pageLayouts.length, pageLayouts }\n}\n\n// ─── 隐藏 iframe 测量 ───\n\n/** 渲染测量模式 HTML 到离屏 iframe,读取每个元素的实际高度(mm) */\nasync function measureElements(\n template: PrintTemplateData,\n codeRenderer?: CodeRenderer,\n): Promise<Map<string, MeasuredElement>> {\n const paper = getPaperDimensions(template)\n const measureHtml = generateHtml(template, [], undefined, {\n isMeasurementPass: true,\n codeRenderer,\n })\n\n const iframe = document.createElement('iframe')\n iframe.setAttribute('aria-hidden', 'true')\n // 禁用 display:none(会导致 offsetHeight=0);移出视口 + 不可见即可\n iframe.style.cssText =\n `position:fixed;left:-10000px;top:0;width:${paper.width}mm;height:${paper.height}mm;` +\n 'border:0;visibility:hidden;pointer-events:none;'\n document.body.appendChild(iframe)\n\n try {\n const win = iframe.contentWindow\n const doc = iframe.contentDocument\n if (!win || !doc) throw new Error('无法创建测量 iframe')\n\n doc.open()\n doc.write(measureHtml)\n doc.close()\n\n await waitForRenderReady(win)\n\n const measurements = readMeasurements(doc)\n\n // 转换为 Map(表格元素补算重复表头段高度),与服务端 pdf-render 一致\n const measuredMap = new Map<string, MeasuredElement>()\n const elementIndex = new Map(template.elements.map(el => [el.id, el]))\n for (const m of measurements) {\n const el = elementIndex.get(m.id)\n const repeatCount: number = el?.options?._repeatHeaderCount ?? 0\n measuredMap.set(m.id, {\n id: m.id,\n measuredHeight: m.height,\n measuredRowHeights: m.rowHeights,\n repeatHeaderHeight: m.rowHeights && repeatCount > 0\n ? m.rowHeights.slice(0, repeatCount).reduce((s: number, h: number) => s + h, 0)\n : 0,\n })\n }\n return measuredMap\n } finally {\n iframe.remove()\n }\n}\n\n/** 等待 iframe 文档加载完成、字体就绪、图片解码完成(带超时兜底) */\nfunction waitForRenderReady(win: Window): Promise<void> {\n return new Promise(resolve => {\n let settled = false\n const finish = () => {\n if (!settled) {\n settled = true\n resolve()\n }\n }\n const timer = setTimeout(finish, READY_TIMEOUT_MS)\n\n const run = async () => {\n try {\n const fonts = (win.document as Document & { fonts?: FontFaceSet }).fonts\n if (fonts?.ready) {\n await Promise.race([fonts.ready, timeout(READY_TIMEOUT_MS)])\n }\n await Promise.race([waitForImages(win.document), timeout(READY_TIMEOUT_MS)])\n } catch {\n // 测量兜底:即使资源加载失败也继续\n } finally {\n clearTimeout(timer)\n finish()\n }\n }\n\n if (win.document.readyState === 'complete') {\n void run()\n } else {\n win.addEventListener('load', () => void run(), { once: true })\n // load 事件意外缺失时兜底\n setTimeout(finish, READY_TIMEOUT_MS)\n }\n })\n}\n\nfunction timeout(ms: number): Promise<never> {\n return new Promise((_resolve, reject) => setTimeout(() => reject(new Error('timeout')), ms))\n}\n\n/** 等待文档内全部图片完成(成功或失败均放行) */\nfunction waitForImages(doc: Document): Promise<void> {\n const imgs = Array.from(doc.images ?? [])\n return Promise.all(\n imgs.map(img =>\n img.complete\n ? Promise.resolve()\n : new Promise<void>(resolve => {\n img.addEventListener('load', () => resolve(), { once: true })\n img.addEventListener('error', () => resolve(), { once: true })\n }),\n ),\n ).then(() => undefined)\n}\n\n/** 读取 [data-measure-id] 元素高度与表格行高(逻辑同服务端 page.evaluate) */\nfunction readMeasurements(doc: Document): Array<{\n id: string\n height: number\n rowHeights?: number[]\n}> {\n const result: Array<{ id: string; height: number; rowHeights?: number[] }> = []\n const elements = doc.querySelectorAll('[data-measure-id]')\n for (const el of elements) {\n const htmlEl = el as HTMLElement\n const id = htmlEl.getAttribute('data-measure-id')\n if (!id) continue\n const heightPx = htmlEl.offsetHeight\n\n const table = htmlEl.querySelector('table.print-table')\n if (table) {\n const rowHeights: number[] = []\n const rows = table.querySelectorAll('tbody > tr[data-row-index]')\n for (const row of rows) {\n rowHeights.push((row as HTMLElement).offsetHeight / PX_PER_MM)\n }\n result.push({ id, height: heightPx / PX_PER_MM, rowHeights })\n } else {\n result.push({ id, height: heightPx / PX_PER_MM })\n }\n }\n return result\n}\n","// print-canvas/src/render/browser-code-renderer.ts\n// 浏览器侧 CodeRenderer:jsbarcode(条形码)+ qrcode(二维码矩阵拼 SVG),纯前端无服务依赖。\n\nimport JsBarcode from 'jsbarcode'\nimport QRCode from 'qrcode'\nimport type { CodeRenderer, CodeRenderOptions } from '@worm-vue3-print/core'\n\nconst SVG_NS = 'http://www.w3.org/2000/svg'\n\n/** 条形码:jsbarcode 渲染到离体 SVG 元素,取 outerHTML */\nfunction renderBarcodeSvg(value: string, opts: CodeRenderOptions): string {\n const svg = document.createElementNS(SVG_NS, 'svg') as SVGSVGElement\n JsBarcode(svg as unknown as SVGElement, value, {\n format: (opts.barcodeType || 'CODE128') as unknown as string,\n width: Math.max(1, (opts.barWidth ?? 2) / 2),\n height: 30,\n displayValue: opts.showText !== false,\n fontSize: opts.fontSize ?? 10,\n margin: 0,\n marginBottom: 2,\n })\n return svg.outerHTML\n}\n\n/** 二维码:QRCode.create 同步取模块矩阵,拼接 SVG(静态白边 4 模块) */\nfunction renderQrSvg(value: string, opts: CodeRenderOptions): string {\n const level = (opts.qrCodeLevel ?? 'M').toUpperCase()\n const qr = QRCode.create(value, {\n errorCorrectionLevel: (['L', 'M', 'Q', 'H'].includes(level) ? level : 'M') as 'L' | 'M' | 'Q' | 'H',\n })\n const modules = qr.modules\n const size = modules.size\n const dot = 4\n const quiet = 4 * dot\n const dim = size * dot + quiet * 2\n let rects = ''\n for (let y = 0; y < size; y++) {\n for (let x = 0; x < size; x++) {\n if (modules.get(x, y)) {\n rects += `<rect x=\"${quiet + x * dot}\" y=\"${quiet + y * dot}\" width=\"${dot}\" height=\"${dot}\" fill=\"#000\"/>`\n }\n }\n }\n return `<svg xmlns=\"${SVG_NS}\" viewBox=\"0 0 ${dim} ${dim}\" width=\"${dim}\" height=\"${dim}\" shape-rendering=\"crispEdges\">${rects}</svg>`\n}\n\n/** 浏览器条码/二维码渲染器;码值非法或为空时抛错,由渲染管线降级文本占位 */\nexport const browserCodeRenderer: CodeRenderer = {\n render(value: string, cellType: 'barcode' | 'qrcode', opts: CodeRenderOptions = {}): string {\n if (!value) throw new Error('empty barcode value')\n return cellType === 'qrcode' ? renderQrSvg(value, opts) : renderBarcodeSvg(value, opts)\n },\n}\n","<!--\n PrintHtmlPreview:浏览器端 HTML 打印预览(不依赖服务端 PDF)。\n 内部完成 数据绑定 → 隐藏 iframe 测量 → 分页 → 多页 HTML 渲染;\n 父组件通过 ref 调用 print() 触发浏览器原生打印(@page 控制纸张与分页)。\n-->\n<template>\n <div class=\"print-html-preview\">\n <div v-if=\"errorMsg\" class=\"print-html-preview-error\">\n <span>预览渲染失败:{{ errorMsg }}</span>\n </div>\n <div v-else-if=\"rendering\" class=\"print-html-preview-loading\">预览渲染中…</div>\n <iframe\n v-show=\"!rendering && !errorMsg\"\n ref=\"iframeRef\"\n class=\"print-html-preview-iframe\"\n title=\"打印预览\"\n />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, watch, onBeforeUnmount } from 'vue'\nimport type { PrintTemplateData } from '@worm-vue3-print/core'\nimport { renderHtmlPages } from '../render/browser-pagination'\nimport { browserCodeRenderer } from '../render/browser-code-renderer'\n\nconst props = defineProps<{\n /** 模板 JSON(设计器 TemplateData 结构兼容) */\n templateJson?: Record<string, any> | null\n /** 业务打印数据 */\n printData?: Record<string, any> | Record<string, any>[]\n /** 图片相对路径拼接前缀(与服务端 baseUrl 同源) */\n baseUrl?: string\n}>()\n\nconst emit = defineEmits<{\n /** 渲染完成,回传总页数 */\n rendered: [pageCount: number]\n /** 渲染失败 */\n error: [message: string]\n}>()\n\nconst iframeRef = ref<HTMLIFrameElement>()\nconst rendering = ref(false)\nconst errorMsg = ref('')\n/** 渲染序列:过期的渲染结果丢弃,避免快速重渲染竞态 */\nlet renderSeq = 0\n\nasync function rerender() {\n if (!props.templateJson) {\n errorMsg.value = ''\n rendering.value = false\n return\n }\n const seq = ++renderSeq\n rendering.value = true\n errorMsg.value = ''\n try {\n const { html, pageCount } = await renderHtmlPages(\n props.templateJson as PrintTemplateData,\n props.printData,\n props.baseUrl,\n browserCodeRenderer,\n )\n if (seq !== renderSeq) return\n const doc = iframeRef.value?.contentWindow?.document\n if (doc) {\n doc.open()\n doc.write(html)\n doc.close()\n }\n emit('rendered', pageCount)\n } catch (e) {\n if (seq !== renderSeq) return\n errorMsg.value = e instanceof Error ? e.message : '未知错误'\n emit('error', errorMsg.value)\n } finally {\n if (seq === renderSeq) rendering.value = false\n }\n}\n\n/** 触发浏览器原生打印(iframe 内 @page 规则控制纸张尺寸与分页) */\nfunction print() {\n const win = iframeRef.value?.contentWindow\n if (!win) return\n win.focus()\n win.print()\n}\n\nwatch(\n () => [props.templateJson, props.printData, props.baseUrl],\n () => void rerender(),\n { immediate: true, deep: true },\n)\n\nonBeforeUnmount(() => {\n renderSeq++\n})\n\ndefineExpose({ print, rerender })\n</script>\n\n<style scoped>\n.print-html-preview {\n width: 100%;\n height: 100%;\n position: relative;\n background: #e9ebee;\n}\n.print-html-preview-iframe {\n width: 100%;\n height: 100%;\n border: 0;\n background: #fff;\n}\n.print-html-preview-loading,\n.print-html-preview-error {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #909399;\n font-size: 14px;\n}\n.print-html-preview-error {\n color: #f56c6c;\n}\n</style>\n"],"names":["createCellIdGenerator","seq","createRowIdGenerator","genCellId","genRowId","DEFAULT_BORDER","deepClone","v","createCell","partial","createDefaultTable","colWidths","mk","type","repeat","header","c","i","findMainCell","rows","r","ri","ci","cell","rs","cs","getSpanRect","main","normalizeSelection","a","b","rect","changed","span","merged","canMergeReason","types","norm","mergeCells","contents","splitCells","styleSrc","sr","sc","t","copyCellStyle","src","dst","insertRow","index","position","insertAt","ref","colCount","newRow","deleteRow","row","next","insertCol","newCell","deleteCol","setRowType","existing","dataIdx","applyBorderPreset","preset","border","atTop","atBottom","atLeft","atRight","GHOST_BORDER_CSS","resolveCellBorderCss","opts","syncTableElementSize","options","wMm","s","w","hMm","generateId","createDefaultOptions","base","totalW","totalH","createRuntimeElement","typeMetaMap","engine","TemplateEngine","getDemoData","DEFAULT_DEMO_DATA","EXTENDED_FUNCTIONS","formatMoney","args","ifFn","value","str","start","len","num","decimals","defaultVal","char","from","to","formatDate","toUpperCaseAmount","name","fn","aggregate","field","sum","avg","count","min","max","evaluateTemplate","text","ctx","processedText","_match","inner","expr","_m","arg","createFieldElement","resolveTextBinding","data","lookupDemoPath","path","cur","seg","resolveBarcodeDesignValue","formatter","listSource","first","_","key","ptToMm","pt","pxToMm","px","PT_KEYS","convertElement","el","round2","n","normalizeTemplateUnits","convert","els","PAPER_PRESETS","getPaperDimensions","computeFitScale","containerW","containerH","paperW","paperH","ratio","fit","pct","ZONE_ALLOWED_TYPES","getPaperSizeMM","getZoneRects","paper","m","headerH","footerH","contentW","contentH","l","tp","h","zoneFromPaperPoint","_x","y","clampToZone","zone","finalizeElementZone","rects","fromZone","cx","cy","target","rejected","SELECTED_IDS_KEY","PREVIEW_IDS_KEY","useSelection","elements","selectedIds","previewIds","selectedElements","computed","e","hasSelection","select","id","multiple","clearSelection","selectAll","allIds","setPreview","ids","clearPreview","commitPreview","getSelectionBounds","minL","minT","maxR","maxB","useClipboard","clipboard","copy","paste","offset","item","hasData","useAlign","align","mode","bounds","centerX","centerY","sorted","gap","x","generateGroupId","useGroup","group","groupId","ungroup","selected","groupIds","getGroupedIds","selectedId","useHistory","undoStack","redoStack","canUndo","canRedo","updateFlags","clone","state","cloneState","push","undo","currentState","popped","redo","clear","STEP","STEP_LARGE","STEP_SMALL","useKeyboard","handlers","onKeyDown","tag","ctrl","step","dx","dy","k","setup","cleanup","createDefaultTemplate","toRuntimePool","useDesignerState","scale","showGrid","snapToGrid","showTableGhostBorder","templateData","fields","selectAllIds","groupElements","ungroupElements","copyElements","pasteElements","hasClipboardData","pushHistory","undoHistory","redoHistory","selectedElement","tableSelection","setTableSelection","getHistoryState","recordHistory","cutSelected","deleteSelected","pasted","duplicateSelected","resetZoom","hasClipboard","moveSessionActive","moveDebounceTimer","MOVE_SESSION_GAP_MS","moveSelected","movable","alignSelected","groupSelected","ungroupSelected","setupKeyboard","cleanupKeyboard","draggingBeforeState","dragStart","dragStop","before","prev","sig","beforeIds","afterIds","placeAtDropPoint","dropPoint","addElement","addFieldElement","moveLayer","direction","currentZ","allZ","maxZ","minZ","fitToWindow","width","height","MM_TO_PX","updateTemplateData","getTemplateJson","all","ser","loadTemplate","migrated","onMounted","onUnmounted","guideSeq","genId","useGuides","guides","mutate","addGuide","list","moveGuide","g","removeGuide","getGuidePositions","TABLE_EDIT_KEY","UPLOAD_IMAGE_KEY","_useModel","__props","_openBlock","_createElementBlock","_hoisted_1","_createElementVNode","_hoisted_2","$emit","_hoisted_3","_hoisted_4","_toDisplayString","_cache","_hoisted_5","_hoisted_6","_hoisted_7","_hoisted_8","_hoisted_9","_hoisted_10","_hoisted_11","_hoisted_12","_normalizeClass","_hoisted_13","_hoisted_14","_hoisted_15","props","sortedLayers","elementIconMap","layerIcon","layerName","zoneTag","_Fragment","_renderList","layer","$event","groupFields","groupMap","groupOrder","f","dot","groups","standalone","filterGroups","keyword","kw","emit","__emit","searchText","collapsedGroups","searching","filteredGroups","toggleGroup","onDragStart","event","_normalizeStyle","activeTab","elementTypes","onFieldDrag","expandTab","tab","_withDirectives","_createVNode","FieldTreePanel","LayerPanel","d","useDrag","isDragging","dragPreview","startX","startY","startLeft","startTop","downAltKey","onMouseDown","targetEl","onMouseMove","onMouseUp","computePos","newLeft","newTop","result","pos","RESIZE_POINTS","calcResizeRect","point","startRect","minW","minH","left","top","useResize","activePoint","startResize","onResizeMove","onResizeEnd","getNestedValue","obj","current","useBindingDisplay","getBindingDisplayState","element","title","demoData","fieldMatch","fieldPath","demoValue","V_ALIGN_FLEX","H_ALIGN_FLEX","textStyle","o","displayText","imageSrc","raw","hasError","onError","watch","imgStyle","ROW_TYPES","emitAction","payload","_createBlock","_Teleport","barcodeSvg","svgOk","dataUrl","renderBarcode","JsBarcode","renderQrcode","QRCode","render","_vShow","PX_PER_MM","HEIGHT_EPSILON_MM","ROW_TYPE_BADGE","editCtx","inject","defaultFontSize","defaultColor","selection","rowTopMm","tableRef","rowLayoutMm","measureTable","table","tableHpx","tableHmm","baseTop","tr","badgeTopMm","badgeHeightMm","demoList","ds","isCodeCell","cellDisplay","_row","cellStyle","borderOpts","cellClass","dragAnchor","applySelection","onCellMouseDown","onCellMouseEnter","onCellDblClick","menu","reactive","onCellContextMenu","mergeReason","canSplit","rowTypeReason","cloned","syncElementSize","checkColWidthLimit","cw","maxW","onMenuAction","err","_withModifiers","CellBarcode","TableContextMenu","isHline","lineStyle","bw","bs","bc","isOval","shapeStyle","svgRef","showText","fontSizePx","totalPx","textH","barH","size","htmlContent","DOMPurify","elRef","injectedSelectedIds","isSelected","injectedPreviewIds","isPreviewed","componentMap","markRaw","TextElement","ImageElement","LongTextElement","TableElement","LineElement","ShapeElement","BarcodeElement","QrcodeElement","HtmlElement","PageNumberElement","bindingState","contentComponent","contentAttrs","elementStyle","posLabel","dragStartLeft","dragStartTop","dragConfig","info","finalDx","finalDy","sibling","setupDrag","cleanupDrag","watchEffect","resizeEnabled","cleanupResize","onDblClick","onDblClickCell","elementId","_unref","_resolveDynamicComponent","_mergeProps","p","buildRulerTicks","lengthMM","ticks","mm","rounded","major","THICKNESS","canvasRef","cssSize","draw","canvas","dpr","lengthPx","horizontal","style","bg","fg","tick","dragging","onDown","onMove","onUp","posMM","useAdsorb","config","adsorbMin","adsorbLineMin","showAdsorbLine","guideLines","paperSize","SNAP_COLORS","snapColor","check","movingRect","others","lines","minDist","other","hPairs","vPairs","ok","dist","m2","hKeys","vKeys","adjustedM","seen","renderLines","clearLines","useAdsorbManager","requestAdsorb","clearGuides","contentRef","paperWidthMM","paperHeightMM","zoneRectsMM","layerStyle","zoneElements","headerElements","footerElements","contentElements","currentDragZone","rawRequestAdsorb","guidePaperSize","showSnapIndicator","onGuideDown","startPt","MM_PER_PX","ev","delta","paperStyle","contentStyle","showRulerComputed","gridBgStyle","snapSeq","snapTimer","snapIndicator","watermarkVisible","watermarkStyle","color","opacity","rotate","getWatermarkText","now","ts","buildWatermarkSvg","printData","escaped","svg","zoneResizing","startZoneResize","cleanupZoneResize","onZoneResizeMove","onZoneResizeUp","startH","dyMM","maxH","onSelectElement","__expose","Ruler","BaseElement","line","idx","rootRef","toPaperPoint","onDrop","fieldData","elementType","marquee","marqueeStart","isCanvasBackground","xMm","yMm","onMouseLeave","onWheel","oldScale","newScale","container","mouseX","mouseY","onCanvasMouseDown","onMarqueeMove","onMarqueeUp","hitTestIds","paperRect","containMode","elLeft","elTop","elRight","elBottom","inter","contained","contextMenu","onContextMenu","elId","containerRect","closeContextMenu","handlePaste","handleSelectAll","handleClearSelection","action","onBeforeUnmount","CanvasPaper","PROPERTY_REGISTRY","matchKeywords","search","keywords","searchProperties","itemKeys","matched","onSearch","isExpanded","iconChar","toggle","saveState","loadState","saved","_renderSlot","_ctx","showItem","PropertyGroup","PRESET_COLORS","visible","triggerRef","panelRef","areaRef","panelStyle","hue","saturation","hexInput","areaDragging","normalizedValue","activeColor","rgbToHex","hsvToRgb","hueModel","degree","setHsv","clampDegree","syncFromColor","onHexInput","parseHex","normalizeHex","rgb","hsv","rgbToHsv","clamp01","startAreaDrag","setAreaFromEvent","moveAreaDrag","endAreaDrag","area","onAreaKeydown","handled","close","open","trigger","nextTick","panelWidth","panelHeight","margin","below","onDocumentPointerDown","onWindowCloseEvents","onKeydown","match","hex","full","part","red","green","blue","hh","r1","g1","b1","number","isTableType","PresetColorPicker","_hoisted_16","_hoisted_17","_hoisted_18","val","searchPlaceholder","selectedFields","toggleField","localExpression","found","handleFieldDoubleClick","insertAtCursor","handleAggregateDoubleClick","handleItemDoubleClick","filteredSystemVars","systemVars","sv","filteredAggregateFuncs","aggregateFunctions","filteredFormatFuncs","formatFunctions","textareaRef","previewResult","ta","end","after","onConfirm","_hoisted_19","_hoisted_20","_hoisted_22","_hoisted_23","_hoisted_24","_hoisted_26","_hoisted_27","_hoisted_28","_hoisted_29","_hoisted_30","_hoisted_31","editorVisible","openEditor","ExpressionEditor","tableEditCtx","listFieldOptions","onSourceChange","onColWidthChange","widths","othersW","clamped","isTable","tablePaginationEnabled","onTablePaginationChange","checked","paginationPageable","paginationKeepWithNext","onPageableChange","onKeepWithNextChange","uploading","uploadImage","uploadDisabled","handleFileChange","input","file","url","onTypeChange","onHeightChange","onRepeatChange","mainCell","formatterEditorVisible","pendingFormatterValue","isBarcodeCell","isQrcodeCell","onAlignChange","write","onValignChange","onCellTypeChange","openFormatterEditor","onFormatterEditorConfirm","borderStyle","borderWidth","borderColor","edgeChecks","currentBorder","onEdgesChange","edges","nb","side","doMerge","doSplit","_hoisted_21","_hoisted_25","_hoisted_33","_hoisted_34","_hoisted_36","_hoisted_38","_hoisted_40","_hoisted_41","_hoisted_42","_hoisted_43","_hoisted_44","_hoisted_45","_hoisted_46","_hoisted_47","_hoisted_48","_hoisted_49","_hoisted_51","_hoisted_53","_hoisted_54","_hoisted_55","ELEMENT_BINDING_REGISTRY","getTableCellBindings","rowType","rowIndex","cellIndex","listField","getElementBindings","staticBindings","dynamicBindings","paperPresets","isTextType","isImageType","isTableCellSelected","searchResult","matchedKeys","bindingDescriptors","c1","parsePath","targetPath","segment","baseName","indices","getBindingValue","setBindingValue","segments","lastKey","onImageUploadSuccess","paperSizeModel","orientationModel","marginTop","marginBottom","marginLeft","marginRight","headerHeight","footerHeight","overlayHeight","customWidth","customHeight","emitUpdate","onPaperSizeChange","onOrientationChange","onCustomWidthChange","onCustomHeightChange","onMarginTopChange","onMarginBottomChange","onMarginLeftChange","onMarginRightChange","onHeaderHeightChange","onFooterHeightChange","onOverlayHeightChange","currentTab","PropertySearch","PositionSizeGroup","AppearanceGroup","desc","BindingControl","ImageContentUpload","TableRowGroup","TableCellGroup","TableSettingsGroup","BorderBgGroup","PaginationGroup","AdvancedGroup","_ps","_hoisted_35","LEFT_KEY","RIGHT_KEY","readStored","fallback","useStudioChrome","leftCollapsed","rightCollapsed","dirty","toggleLeft","toggleRight","markSaved","onUndo","onRedo","onAlign","onGroup","onUngroup","onDeleteElement","onDragStop","onDropElement","onDropField","onMoveLayer","maxTableWidth","provide","canvasAreaRef","overlayVisible","screenshotUrl","overlayOpacity","toggleOverlay","templateJson","blob","coordinate","onCoordinate","paperLabel","dim","orient","onFitWindow","onZoom","onKeyFitWindow","onTemplateDataChanged","prevHeader","prevFooter","onZoneHeightChange","onZoneHeightCommit","warnZoneOverflow","onAddOverlayElement","overlay","newEl","onToggleVisible","onToggleLocked","activePropertyTab","DBL_EDITABLE_FIELD","dblEditorVisible","dblEditTarget","dblEditorExpression","onDblClickElement","onDblEditorConfirm","onCloneElement","_pos","handleLoadDefault","tpl","handleSave","DesignerToolbar","LeftPanel","CanvasArea","PropertyPanel","StatusBar","READY_TIMEOUT_MS","renderHtmlPages","template","baseUrl","codeRenderer","boundTemplate","bindData","measuredElements","measureElements","pageLayouts","paginate","generateHtml","measureHtml","iframe","win","doc","waitForRenderReady","measurements","readMeasurements","measuredMap","elementIndex","repeatCount","resolve","settled","finish","timer","run","fonts","timeout","waitForImages","ms","_resolve","reject","imgs","img","htmlEl","heightPx","rowHeights","SVG_NS","renderBarcodeSvg","renderQrSvg","level","modules","quiet","browserCodeRenderer","cellType","iframeRef","rendering","errorMsg","renderSeq","rerender","html","pageCount","print"],"mappings":"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"}