@worm-vue3-print/canvas 1.2.0 → 1.2.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.
- package/README.md +76 -17
- package/dist/canvas.css +1 -1
- package/dist/components/CanvasArea.vue.d.ts +9 -1
- package/dist/components/DesignerToolbar.vue.d.ts +3 -0
- package/dist/components/PrintDesigner.vue.d.ts +2 -0
- package/dist/index.cjs +24 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +3121 -3055
- package/dist/index.js.map +1 -1
- package/dist/utils/scale.d.ts +3 -1
- package/package.json +1 -1
package/dist/index.cjs.map
CHANGED
|
@@ -1 +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/HelpButton.vue","../src/components/DesignerToolbar.vue","../src/components/LayerPanel.vue","../src/utils/field-groups.ts","../src/components/FieldTreePanel.vue","../src/components/LeftPanel.vue","../src/utils/ruler.ts","../src/composables/useDrag.ts","../src/composables/useResize.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/CellImage.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/composables/useAdsorb.ts","../src/composables/useAdsorbManager.ts","../src/components/CanvasPaper.vue","../src/components/Ruler.vue","../src/components/CanvasArea.vue","../src/utils/property-search.ts","../src/components/property/PropertySearch.vue","../src/components/property/PropertyGroup.vue","../src/components/property/StepperInput.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/help-content/getting-started.ts","../src/help-content/features.ts","../src/help-content/shortcuts.ts","../src/help-content/faq.ts","../src/help-content/changelog.ts","../src/help-content/index.ts","../src/components/HelpModal.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\n/** 列宽拖拽的最小列宽(mm),与属性面板列宽输入下限一致 */\nexport const MIN_COL_WIDTH_MM = 5\n\n/**\n * 列宽拖拽钳制(纯函数,不修改入参,调用方负责回写):\n * 返回目标列宽在 [MIN_COL_WIDTH_MM, maxTableWidth - 其余列和] 范围内的钳制值,\n * 结果保留 0.1mm 精度。maxTableWidth 为 Infinity 时不设总宽上限。\n */\nexport function clampResizedColumnWidth(\n colWidths: number[],\n index: number,\n targetMm: number,\n maxTableWidth: number,\n): number {\n const others = colWidths.reduce((s, w, i) => (i === index ? s : s + w), 0)\n const cap = maxTableWidth === Infinity\n ? Infinity\n : Math.max(MIN_COL_WIDTH_MM, maxTableWidth - others)\n const rounded = Math.round(targetMm * 10) / 10\n return Math.min(Math.max(rounded, MIN_COL_WIDTH_MM), cap)\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\n/** mm 转 px(基于 96dpi 屏幕) */\nexport function mmToPx(mm: number): number {\n return mm * (96 / 25.4)\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/** 最小缩放百分比,低于此值画布难以查看与操作;放大方向不设上限 */\nexport const MIN_SCALE_PERCENT = 25\n\n/** 将缩放百分比钳制到允许范围:仅保留下限,放大不设上限 */\nexport function clampScalePercent(percent: number): number {\n return Math.max(MIN_SCALE_PERCENT, percent)\n}\n\n/**\n * 滚轮缩放:乘性步进(默认 ×1.1 / ÷1.1),大倍数下仍保持平滑手感,\n * 返回取整后的百分比,避免浮点累加产生脏显示(如 110.00000001)\n * @param percent 当前缩放百分比\n * @param direction 1 放大,-1 缩小\n */\nexport function nextWheelScale(percent: number, direction: 1 | -1, factor = 1.1): number {\n const next = direction > 0 ? percent * factor : percent / factor\n return clampScalePercent(Math.round(next))\n}\n\n/** 计算适应窗口的缩放百分比,仅钳制最小缩放,放大不设上限 */\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 clampScalePercent(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 showRuler = ref(true)\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, showRuler, 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 <button\n class=\"help-button\"\n title=\"帮助文档\"\n @click=\"$emit('click')\"\n >\n <span class=\"help-icon\">?</span>\n </button>\n</template>\n\n<script setup lang=\"ts\">\ndefineEmits<{\n click: []\n}>()\n</script>\n\n<style scoped>\n.help-button {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: none;\n border-radius: 4px;\n background: transparent;\n cursor: pointer;\n transition: background-color 0.15s;\n}\n\n.help-button:hover {\n background: var(--pd-sidebar-hover, #f0f3f9);\n}\n\n.help-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n border-radius: 50%;\n background: var(--pd-accent, #165DFF);\n color: white;\n font-size: 12px;\n font-weight: 600;\n line-height: 1;\n}\n</style>\n","<template>\n <div class=\"designer-toolbar\">\n <!-- 文件 -->\n <div class=\"tb-group\">\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')\" data-tip=\"置顶\">⤒</button>\n <button class=\"tb-btn tb-icon\" @click=\"$emit('move-layer', 'up')\" data-tip=\"上移一层\">↑</button>\n <button class=\"tb-btn tb-icon\" @click=\"$emit('move-layer', 'down')\" data-tip=\"下移一层\">↓</button>\n <button class=\"tb-btn tb-icon\" @click=\"$emit('move-layer', 'bottom')\" data-tip=\"置底\">⤓</button>\n </div>\n <!-- 视图 -->\n <div class=\"tb-group\">\n <button class=\"tb-btn\" :class=\"{ on: showRuler }\" title=\"显示/隐藏标尺\" @click=\"$emit('toggle-ruler')\">\n <span class=\"dot\" /> 标尺\n </button>\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 <HelpButton @click=\"$emit('help')\" />\n </div>\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\">\nimport HelpButton from './HelpButton.vue'\n\nconst scale = defineModel<number>('scale', { default: 100 })\n\nwithDefaults(defineProps<{\n isEdit?: boolean\n canUndo?: boolean\n canRedo?: boolean\n hasMultiSelection?: boolean\n hasSelection?: boolean\n showRuler?: boolean\n showGrid?: boolean\n snapToGrid?: boolean\n showTableGhostBorder?: boolean\n selectedElementHasGroup?: boolean\n overlayVisible?: boolean\n /** 是否展示「加载默认布局」按钮(宿主注入 loadDefaultTemplate 时由 PrintDesigner 开启) */\n showLoadDefault?: boolean\n}>(), {\n showRuler: true,\n})\n\ndefineEmits<{\n preview: []\n save: []\n 'load-default': []\n undo: []\n redo: []\n align: [mode: string]\n 'move-layer': [direction: string]\n 'toggle-ruler': []\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 help: []\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-btn[data-tip] {\n position: relative;\n}\n.tb-btn[data-tip]::after {\n content: attr(data-tip);\n position: absolute;\n bottom: -32px;\n left: 50%;\n transform: translateX(-50%);\n padding: 4px 8px;\n font-size: 12px;\n color: #fff;\n background: rgba(30, 35, 48, .88);\n border-radius: 4px;\n white-space: nowrap;\n opacity: 0;\n pointer-events: none;\n transition: opacity .15s ease;\n z-index: 100;\n}\n.tb-btn[data-tip]:hover::after {\n opacity: 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","// 标尺刻度纯函数:步长选择与可见范围刻度生成\n\n/** 视口固定尺条厚度(px),CanvasArea 布局与左上角块共用 */\nexport const RULER_THICKNESS = 22\n\nexport interface RulerTick {\n /** 刻度在纸面坐标系上的位置(mm,可为负,表示纸张原点之外) */\n mm: number\n /** 是否为主刻度(带数字标签) */\n major: boolean\n label?: string\n}\n\n/** 漂亮数步长序列:1/2/5 × 10^n,单位 mm */\nconst STEP_SEQUENCE = [1, 2, 5, 10, 20, 50, 100, 200, 500, 1000] as const\n\n/**\n * 按缩放选择主刻度步长(mm):取漂亮数序列中使屏幕间距\n * 不小于 targetPx 的最小步长,保证任意缩放下标签不重叠\n * @param scale 画布缩放比例(1 = 100%)\n * @param targetPx 主刻度之间的目标屏幕间距(px)\n */\nexport function chooseMajorStepMM(scale: number, targetPx = 64): number {\n const pxPerMM = scale * (96 / 25.4)\n for (const step of STEP_SEQUENCE) {\n if (step * pxPerMM >= targetPx) return step\n }\n return STEP_SEQUENCE[STEP_SEQUENCE.length - 1]\n}\n\n/**\n * 次刻度步长:5 系(5/50/500…)五等分、2 系(2/20/200…)二等分、\n * 10 的幂从 10mm 起五等分(10→2mm、100→20mm),1mm 时无次刻度\n */\nexport function minorStepMM(majorStepMM: number): number | null {\n const exp = Math.floor(Math.log10(majorStepMM) + 1e-9)\n const base = majorStepMM / 10 ** exp // 归一化到 1 / 2 / 5\n if (base === 5 || (base === 1 && majorStepMM >= 10)) return majorStepMM / 5\n if (base === 2) return majorStepMM / 2\n return null\n}\n\n/** 消除浮点误差,保留到 0.001mm */\nfunction roundMM(mm: number): number {\n return Math.round(mm * 1000) / 1000\n}\n\n/**\n * 生成可见毫米范围内的全部刻度(升序):\n * 从首个对齐的次刻度开始,主刻度带数字标签\n * @param startMM 可见范围起点(纸面坐标,可为负)\n * @param endMM 可见范围终点\n * @param majorStepMM 主刻度步长(由 chooseMajorStepMM 选出)\n */\nexport function buildRulerTicks(\n startMM: number,\n endMM: number,\n majorStepMM: number,\n): RulerTick[] {\n if (endMM < startMM || majorStepMM <= 0) return []\n const minor = minorStepMM(majorStepMM)\n const fine = minor ?? majorStepMM\n const first = Math.ceil(startMM / fine - 1e-9) * fine\n const lastIndex = Math.floor((endMM - first) / fine + 1e-9)\n const ticks: RulerTick[] = []\n for (let i = 0; i <= lastIndex; i++) {\n const mm = roundMM(first + i * fine)\n const isMajor = Math.abs(mm / majorStepMM - Math.round(mm / majorStepMM)) < 1e-6\n if (isMajor) {\n ticks.push({ mm, major: true, label: String(mm) })\n } else {\n ticks.push({ mm, major: false })\n }\n }\n return ticks\n}\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","<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\" :style=\"svgStyle\"></svg>\n <img v-if=\"cellType === 'qrcode' && dataUrl\" :src=\"dataUrl\" alt=\"qrcode\" :style=\"imgStyle\" />\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, computed, 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 fit?: string\n maxWidth?: number\n maxHeight?: number\n}>()\n\nconst barcodeSvg = ref<SVGSVGElement | null>(null)\nconst svgOk = ref(false)\nconst dataUrl = ref('')\n\nconst svgStyle = computed(() => ({\n objectFit: (props.fit || 'contain') as any,\n maxWidth: props.maxWidth ? `${props.maxWidth}mm` : '100%',\n maxHeight: props.maxHeight ? `${props.maxHeight}mm` : '100%',\n}))\n\nconst imgStyle = computed(() => ({\n objectFit: (props.fit || 'contain') as any,\n maxWidth: props.maxWidth ? `${props.maxWidth}mm` : '100%',\n maxHeight: props.maxHeight ? `${props.maxHeight}mm` : '100%',\n}))\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","<!-- 表格单元格内图片渲染:设计态与预览态共用 -->\n<template>\n <div class=\"cell-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 { evaluateTemplate } from '../../utils/expression-eval'\nimport { DEFAULT_DEMO_DATA } from '../../utils/demo-data'\n\nconst props = defineProps<{\n value: string\n fit?: string\n maxWidth?: number\n maxHeight?: number\n designMode?: boolean\n data?: Record<string, any>[]\n}>()\n\nconst imageSrc = computed(() => {\n const raw = props.value || ''\n if (!raw) return ''\n \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 \n return raw\n})\n\n// 加载失败兜底\nconst hasError = ref(false)\nfunction onError() {\n hasError.value = true\n}\n\n// src 变化时重置错误态\nwatch(imageSrc, () => {\n hasError.value = false\n})\n\nconst imgStyle = computed(() => ({\n objectFit: (props.fit || 'contain') as any,\n maxWidth: props.maxWidth ? `${props.maxWidth}mm` : '100%',\n maxHeight: props.maxHeight ? `${props.maxHeight}mm` : '100%',\n}))\n</script>\n\n<style scoped>\n.cell-image {\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n overflow: hidden;\n}\n.cell-image img {\n max-width: 100%;\n max-height: 100%;\n display: block;\n}\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>","<!-- 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 :fit=\"cell.fit\"\n :max-width=\"cell.maxWidth\"\n :max-height=\"cell.maxHeight\"\n />\n <CellImage\n v-else-if=\"cell.cellType === 'image'\"\n :value=\"cell.formatter || ''\"\n :fit=\"cell.fit\"\n :max-width=\"cell.maxWidth\"\n :max-height=\"cell.maxHeight\"\n :design-mode=\"designMode\"\n :data=\"imageData\"\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=\"colResizeEnabled\" class=\"col-resize-layer\">\n <div\n v-for=\"i in colResizeBoundaries\"\n :key=\"i\"\n class=\"col-resize-handle\"\n role=\"separator\"\n :aria-label=\"'列宽手柄' + i\"\n :class=\"{ dragging: colResizeBoundary === i }\"\n :style=\"{ left: colBoundaryLeftMm(i) + 'mm' }\"\n @mousedown.stop.prevent=\"onColResizeStart(i, $event)\"\n />\n </div>\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, onUnmounted, 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, clampResizedColumnWidth,\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 CellImage from './CellImage.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 /** 画布缩放倍率(用于列宽拖拽 px→mm 换算) */\n scale?: number\n /** 打印数据(用于运行态图片等动态内容) */\n data?: Record<string, any>[]\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\n// 添加图片数据处理\nconst imageData = computed(() => {\n // 运行态:使用打印数据\n if (props.data) {\n return props.data\n }\n // 设计态:使用 demo 数据\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\n// ─── 列宽拖拽 ───\n// 设计态选中且未锁定即渲染列边界手柄:1..n-1 为内部列边界(= 第 i 列右边缘),\n// 拖拽时调整其左侧第 i-1 列宽,使边界跟随光标移动;n 为最后一列右边界,\n// 拖拽时调整末列宽(右拖增宽、左拖缩窄)。拖拽期间实时回写列宽,\n// mouseup 时同步元素尺寸并记一次历史(与右键菜单结构操作一致)。\nconst colResizeEnabled = computed(\n () => props.designMode && !!props.isSelected && !props.element.options.locked && colWidths.value.length >= 1,\n)\n/** 列边界索引(1..n),n 为最后一列右边界 */\nconst colResizeBoundaries = computed<number[]>(() =>\n Array.from({ length: colWidths.value.length }, (_, k) => k + 1),\n)\n/** 边界 i 的水平位置(mm)= 前 i 列宽度和;i=n 时即表格右边界 */\nfunction colBoundaryLeftMm(i: number): number {\n return colWidths.value.slice(0, i).reduce((s, w) => s + w, 0)\n}\n\nconst colResizeBoundary = ref<number | null>(null)\nlet resizeStartX = 0\nlet resizeStartWidth = 0\n\n/** 拖拽边界 i:始终调整其左侧第 i-1 列(即第 i 列)宽 = startWidth + deltaMm,\n * 让边界线跟随光标移动。clampResizedColumnWidth 负责最小列宽与总宽上限钳制。 */\nfunction onColResizeStart(i: number, e: MouseEvent) {\n if (!colResizeEnabled.value) return\n colResizeBoundary.value = i\n resizeStartX = e.clientX\n resizeStartWidth = colWidths.value[i - 1]!\n document.addEventListener('mousemove', onColResizeMove)\n document.addEventListener('mouseup', onColResizeEnd)\n}\n\nfunction onColResizeMove(e: MouseEvent) {\n if (colResizeBoundary.value === null) return\n const scale = props.scale || 1\n // 鼠标位移 px → mm:画布 transform:scale(props.scale) 下 1mm ≈ PX_PER_MM*scale px\n const deltaMm = (e.clientX - resizeStartX) / (scale * PX_PER_MM)\n const colIndex = colResizeBoundary.value - 1\n const widths = props.element.options.tableColWidths!\n widths[colIndex] = clampResizedColumnWidth(\n widths, colIndex, resizeStartWidth + deltaMm, editCtx.maxTableWidth.value,\n )\n // 实时同步元素 width = 列宽和:避免 table-layout:fixed 下表格 CSS width(100%)\n // 与列宽和失配导致浏览器按比例拉伸列,进而使边界线与右侧内容偏离光标。\n syncElementSize()\n}\n\nfunction onColResizeEnd() {\n document.removeEventListener('mousemove', onColResizeMove)\n document.removeEventListener('mouseup', onColResizeEnd)\n if (colResizeBoundary.value === null) return\n colResizeBoundary.value = null\n syncElementSize()\n editCtx.recordHistory()\n}\n\nonUnmounted(() => {\n document.removeEventListener('mousemove', onColResizeMove)\n document.removeEventListener('mouseup', onColResizeEnd)\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.col-resize-layer {\n position: absolute;\n inset: 0;\n pointer-events: none;\n z-index: 3;\n}\n.col-resize-handle {\n position: absolute;\n top: 0;\n bottom: 0;\n width: 6px;\n transform: translateX(-50%);\n cursor: col-resize;\n pointer-events: auto;\n}\n/* 手柄 hover/拖拽时显示主题色竖线,提示列边界位置 */\n.col-resize-handle::after {\n content: '';\n position: absolute;\n top: 0;\n bottom: 0;\n left: 50%;\n border-left: 1px solid transparent;\n}\n.col-resize-handle:hover::after,\n.col-resize-handle.dragging::after {\n border-left-color: var(--pd-accent, #165DFF);\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>\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 { mmToPx } from '../../utils/units'\n\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 contentComponent = computed(() => componentMap[props.element.printElementType.type])\n\n/** 仅表格元素需要虚拟虚线开关,避免其它元素根节点出现无关 attribute */\nconst contentAttrs = computed(() =>\n props.element.printElementType.type === 'table'\n ? { showTableGhostBorder: props.showTableGhostBorder, scale: props.scale }\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) * mmToPx(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) * mmToPx(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.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","// 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=\"paper-wrapper\"\n :style=\"wrapperStyle\"\n >\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 <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', '--guide-hit': guideHitPx }\n : { top: g.position + 'mm', left: '0', width: paperWidthMM + 'mm', '--guide-hit': guideHitPx }\"\n @mousedown.prevent.stop=\"onGuideDown($event, g)\"\n @dblclick.prevent.stop=\"g.id && emit('guide-remove', g.id)\"\n />\n </div>\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 { mmToPx } from '../utils/units'\nimport BaseElement from './elements/BaseElement.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 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 '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/** 参考线交互热区:换算到缩放前坐标,保证任意缩放比例下屏幕热区恒定 */\nconst guideHitPx = computed(() => `${8 / (props.scale || 1)}px`)\n\n/** wrapper 尺寸:缩放后的实际像素尺寸,让滚动容器正确感知内容大小 */\nconst wrapperStyle = computed(() => {\n const s = props.scale || 1\n const widthPx = mmToPx(paperWidthMM.value) * s\n const heightPx = mmToPx(paperHeightMM.value) * s\n return {\n width: widthPx + 'px',\n height: heightPx + 'px',\n position: 'relative' as const,\n }\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 const maxPosition = g.type === 'vertical' ? paperWidthMM.value : paperHeightMM.value\n const nextPosition = Math.min(Math.max(startPt + delta, 0), maxPosition)\n emit('guide-move', g.id!, nextPosition)\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: props.templateData.pageBackground || '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 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 boxSizing: 'border-box' as const,\n minHeight: paperHeightMM.value + 'mm',\n }\n})\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, '&').replace(/</g, '<').replace(/>/g, '>')\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/* wrapper:承载缩放后的实际尺寸,让滚动容器正确感知内容大小 */\n.paper-wrapper {\n /* 仅承载缩放后的布局尺寸(宽高 = 纸张尺寸 × scale,见 wrapperStyle)。\n 纸张固定以左上角为原点缩放(transform-origin: 0 0),wrapper 内不能再居中,\n 否则缩小时 flex 压缩布局宽度会使视觉宽度变为 W·s²、放大时纸张向右偏移;\n 水平居中统一由外层 .canvas-scroll 的 align-items: center 负责。 */\n display: block;\n}\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.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::before {\n content: '';\n position: absolute;\n pointer-events: auto;\n}\n.manual-guide.guide-vertical::before {\n top: 0;\n bottom: 0;\n left: 50%;\n width: var(--guide-hit, 8px);\n transform: translateX(-50%);\n}\n.manual-guide.guide-horizontal::before {\n left: 0;\n right: 0;\n top: 50%;\n height: var(--guide-hit, 8px);\n transform: translateY(-50%);\n}\n.manual-guide:hover { border-color: #EF4444 !important; }\n</style>\n","<!--\n 视口固定式标尺(单条)\n - 尺条固定在设计区边缘,不随纸张缩放/滚动;刻度随滚动平移、随缩放变密度\n - 横尺产生垂直参考线,竖尺产生水平参考线(与历史语义一致)\n - 在尺上按下并移动显示预览线,松开即生成参考线;主坐标超出尺长则取消\n-->\n<template>\n <canvas\n ref=\"canvasRef\"\n class=\"pd-ruler\"\n :class=\"`is-${orientation}`\"\n :style=\"cssSize\"\n @mousedown=\"onDown\"\n @mousemove=\"onHoverMove\"\n @mouseleave=\"onHoverLeave\"\n />\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, watch, onMounted, onBeforeUnmount } from 'vue'\nimport { mmToPx } from '../utils/units'\nimport {\n buildRulerTicks,\n chooseMajorStepMM,\n RULER_THICKNESS,\n} from '../utils/ruler'\n\nconst props = defineProps<{\n orientation: 'horizontal' | 'vertical'\n /** 尺条可见长度(屏幕 px,不随缩放变化) */\n viewportPx: number\n /** 纸张 0mm 点相对尺条起点的屏幕偏移(滚动时由父级实时更新) */\n originPx: number\n /** 纸张该方向长度(mm),用于边界标记与参考线落点限制 */\n paperLengthMM: number\n scale: number\n /** 鼠标在尺条轴向上的位置(屏幕 px),由画布 mousemove 转发 */\n cursorPx?: number | null\n}>()\n\nconst emit = defineEmits<{\n 'add-guide': [type: 'vertical' | 'horizontal', positionMm: number]\n /** 拖拽参考线过程中的虚线预览,null 表示隐藏 */\n 'guide-dragging': [mm: number | null]\n}>()\n\nconst horizontal = computed(() => props.orientation === 'horizontal')\n/** 横尺界定横向位置,产生的是垂直参考线 */\nconst guideType = computed<'vertical' | 'horizontal'>(() =>\n horizontal.value ? 'vertical' : 'horizontal',\n)\n\nconst canvasRef = ref<HTMLCanvasElement | null>(null)\n/** 鼠标悬停在尺条上的轴向位置(优先于外部传入的 cursorPx) */\nconst hoverPx = ref<number | null>(null)\nconst effectiveCursorPx = computed(() => hoverPx.value ?? props.cursorPx ?? null)\n\nconst cssSize = computed(() => {\n if (horizontal.value) {\n return { width: props.viewportPx + 'px', height: RULER_THICKNESS + 'px' }\n }\n return { width: RULER_THICKNESS + 'px', height: props.viewportPx + 'px' }\n})\n\nlet rafId = 0\nfunction scheduleDraw() {\n if (rafId) return\n rafId = requestAnimationFrame(() => {\n rafId = 0\n draw()\n })\n}\n\nfunction draw() {\n const canvas = canvasRef.value\n if (!canvas) return\n const ctx = canvas.getContext('2d')\n // happy-dom 等无 canvas 环境直接跳过绘制\n if (!ctx) return\n\n const dpr = window.devicePixelRatio || 1\n const length = Math.max(0, Math.round(props.viewportPx))\n const thickness = RULER_THICKNESS\n canvas.width = (horizontal.value ? length : thickness) * dpr\n canvas.height = (horizontal.value ? thickness : length) * dpr\n ctx.setTransform(dpr, 0, 0, dpr, 0, 0)\n\n const style = getComputedStyle(canvas)\n const bg = style.getPropertyValue('--pd-ruler-bg').trim() || '#F8F9FC'\n const fg = style.getPropertyValue('--pd-ruler').trim() || '#9AA1AF'\n const accent = style.getPropertyValue('--pd-accent').trim() || '#165DFF'\n\n // 背景\n ctx.fillStyle = bg\n ctx.fillRect(0, 0, horizontal.value ? length : thickness, horizontal.value ? thickness : length)\n\n const s = props.scale > 0 ? props.scale : 1\n const pxPerMM = mmToPx(1) * s\n if (pxPerMM <= 0) return\n\n // 可见毫米范围(含纸张外区域)\n const startMM = -props.originPx / pxPerMM\n const endMM = (length - props.originPx) / pxPerMM\n const majorStep = chooseMajorStepMM(s)\n const ticks = buildRulerTicks(startMM, endMM, majorStep)\n\n // 纸外刻度淡化处理:先画纸外,再画纸内\n drawTicks(ctx, ticks, pxPerMM, fg, true)\n drawTicks(ctx, ticks, pxPerMM, fg, false)\n\n // 纸张 0 / 末端边界标记\n drawPaperEdge(ctx, 0, accent)\n drawPaperEdge(ctx, props.paperLengthMM, accent)\n\n // 鼠标位置指示线\n const cursor = effectiveCursorPx.value\n if (cursor !== null && cursor >= 0 && cursor <= length) {\n ctx.strokeStyle = accent\n ctx.lineWidth = 1.5\n ctx.beginPath()\n if (horizontal.value) {\n const x = Math.round(cursor) + 0.5\n ctx.moveTo(x, 0)\n ctx.lineTo(x, thickness)\n } else {\n const y = Math.round(cursor) + 0.5\n ctx.moveTo(0, y)\n ctx.lineTo(thickness, y)\n }\n ctx.stroke()\n }\n}\n\nfunction drawTicks(\n ctx: CanvasRenderingContext2D,\n ticks: ReturnType<typeof buildRulerTicks>,\n pxPerMM: number,\n fg: string,\n outside: boolean,\n) {\n const thickness = RULER_THICKNESS\n ctx.strokeStyle = fg\n ctx.fillStyle = fg\n ctx.globalAlpha = outside ? 0.32 : 1\n ctx.lineWidth = 1\n ctx.font = '9px ui-monospace, Menlo, monospace'\n ctx.textBaseline = 'top'\n\n for (const tick of ticks) {\n const isOutside = tick.mm < 0 || tick.mm > props.paperLengthMM\n if (isOutside !== outside) continue\n const pos = Math.round(props.originPx + tick.mm * pxPerMM) + 0.5\n const len = tick.major ? 8 : 4\n ctx.beginPath()\n if (horizontal.value) {\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.value) {\n ctx.fillText(tick.label, pos + 2, 11)\n } else {\n ctx.save()\n // 旋转 -90° 后,文字沿屏幕 +x 方向铺开(9px 字体约占 9px)。\n // x=11 时文字落在 11..20px,完整处于 22px 尺宽内,\n // 且与横尺标签(y=11)对称;此前 x=18 会延伸到 27px 被裁切。\n ctx.translate(11, pos + 2)\n ctx.rotate(-Math.PI / 2)\n ctx.fillText(tick.label, 0, 0)\n ctx.restore()\n }\n }\n }\n ctx.globalAlpha = 1\n}\n\nfunction drawPaperEdge(ctx: CanvasRenderingContext2D, mm: number, color: string) {\n const pxPerMM = mmToPx(1) * (props.scale > 0 ? props.scale : 1)\n const pos = Math.round(props.originPx + mm * pxPerMM) + 0.5\n if (pos <= 0 || pos >= props.viewportPx) return\n ctx.strokeStyle = color\n ctx.globalAlpha = 0.55\n ctx.lineWidth = 1\n ctx.beginPath()\n if (horizontal.value) {\n ctx.moveTo(pos, 0)\n ctx.lineTo(pos, RULER_THICKNESS)\n } else {\n ctx.moveTo(0, pos)\n ctx.lineTo(RULER_THICKNESS, pos)\n }\n ctx.stroke()\n ctx.globalAlpha = 1\n}\n\nwatch(\n () => [props.viewportPx, props.originPx, props.paperLengthMM, props.scale, props.cursorPx, props.orientation],\n scheduleDraw,\n)\nonMounted(scheduleDraw)\nonBeforeUnmount(() => { if (rafId) cancelAnimationFrame(rafId) })\n\n// ─── 拖出参考线 ───\nlet dragging = false\n\nfunction axialFromEvent(e: MouseEvent): number | null {\n const canvas = canvasRef.value\n if (!canvas) return null\n const rect = canvas.getBoundingClientRect()\n const along = horizontal.value ? e.clientX - rect.left : e.clientY - rect.top\n // 主坐标超出尺条长度(含两端)即视为取消;横向/纵向另一方向不限制,允许拖入纸面\n if (along < 0 || along > props.viewportPx) return null\n const pxPerMM = mmToPx(1) * (props.scale > 0 ? props.scale : 1)\n return (along - props.originPx) / pxPerMM\n}\n\nfunction onDown(e: MouseEvent) {\n dragging = true\n e.preventDefault()\n window.addEventListener('mousemove', onWinMove)\n window.addEventListener('mouseup', onWinUp)\n updateDragPreview(e)\n}\n\nfunction onHoverMove(e: MouseEvent) {\n const canvas = canvasRef.value\n if (!canvas) return\n const rect = canvas.getBoundingClientRect()\n hoverPx.value = horizontal.value ? e.clientX - rect.left : e.clientY - rect.top\n scheduleDraw()\n}\n\nfunction onHoverLeave() {\n hoverPx.value = null\n scheduleDraw()\n}\n\nfunction updateDragPreview(e: MouseEvent) {\n const mm = axialFromEvent(e)\n emit('guide-dragging', mm)\n}\n\nfunction onWinMove(e: MouseEvent) {\n if (!dragging) return\n updateDragPreview(e)\n}\n\nfunction onWinUp(e: MouseEvent) {\n if (!dragging) return\n dragging = false\n window.removeEventListener('mousemove', onWinMove)\n window.removeEventListener('mouseup', onWinUp)\n const mm = axialFromEvent(e)\n if (mm !== null && mm >= 0 && mm <= props.paperLengthMM) {\n emit('add-guide', guideType.value, mm)\n }\n emit('guide-dragging', null)\n}\n\nonBeforeUnmount(() => {\n window.removeEventListener('mousemove', onWinMove)\n window.removeEventListener('mouseup', onWinUp)\n})\n</script>\n\n<style scoped>\n.pd-ruler {\n position: absolute;\n display: block;\n pointer-events: auto;\n cursor: crosshair;\n z-index: 1;\n background: var(--pd-ruler-bg, #f8f9fc);\n}\n.pd-ruler.is-horizontal {\n box-shadow: 0 1px 0 var(--pd-border-soft, #e9ecf2);\n}\n.pd-ruler.is-vertical {\n box-shadow: 1px 0 0 var(--pd-border-soft, #e9ecf2);\n}\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 @scroll=\"onScroll\"\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 @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 v-if=\"showRuler\" class=\"ruler-overlay\" :style=\"overlayStyle\">\n <div class=\"ruler-corner\" />\n <Ruler\n orientation=\"horizontal\"\n :viewport-px=\"rulerGeom.viewW\"\n :origin-px=\"rulerGeom.originX\"\n :paper-length-m-m=\"paperWidthMM\"\n :scale=\"rulerGeom.paperScale\"\n :cursor-px=\"rulerCursor.x\"\n @add-guide=\"(t: 'vertical' | 'horizontal', p: number) => emit('add-guide', t, p)\"\n @guide-dragging=\"(mm: number | null) => onGuideDragging('vertical', mm)\"\n />\n <Ruler\n orientation=\"vertical\"\n :viewport-px=\"rulerGeom.viewH\"\n :origin-px=\"rulerGeom.originY\"\n :paper-length-m-m=\"paperHeightMM\"\n :scale=\"rulerGeom.paperScale\"\n :cursor-px=\"rulerCursor.y\"\n @add-guide=\"(t: 'vertical' | 'horizontal', p: number) => emit('add-guide', t, p)\"\n @guide-dragging=\"(mm: number | null) => onGuideDragging('horizontal', mm)\"\n />\n </div>\n <!-- 从标尺拖出参考线时的预览虚线(fixed 定位,不能放进带 transform 的 overlay) -->\n <div\n v-if=\"guidePreview\"\n class=\"ruler-guide-preview\"\n :class=\"`guide-${guidePreview.type}`\"\n :style=\"guidePreviewStyle\"\n />\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, computed, watch, nextTick, onMounted, onBeforeUnmount } from 'vue'\nimport type { RuntimeElement, TemplateData, AlignLine } from '../types'\nimport { pxToMm, mmToPx } from '../utils/units'\nimport { nextWheelScale } from '../utils/scale'\nimport { getPaperDimensions } from '../utils/default-config'\nimport { RULER_THICKNESS } from '../utils/ruler'\nimport CanvasPaper from './CanvasPaper.vue'\nimport Ruler from './Ruler.vue'\n\nconst props = withDefaults(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 showRuler?: boolean\n}>(), {\n showRuler: true,\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// ─── 视口固定标尺:纸张几何测量与滚动/缩放同步 ───\nconst paperWidthMM = computed(() => getPaperDimensions(props.templateData).width)\nconst paperHeightMM = computed(() => getPaperDimensions(props.templateData).height)\n\n/** 纸张原点相对各尺条起点的屏幕偏移 + 尺条可见长度 */\nconst rulerGeom = reactive({ originX: 0, originY: 0, viewW: 0, viewH: 0, paperScale: 1 })\n/** 鼠标相对各尺条起点的屏幕位置,驱动尺上指示线 */\nconst rulerCursor = reactive<{ x: number | null; y: number | null }>({ x: null, y: null })\n/** 滚动偏移:绝对定位的标尺层会随滚动内容移动,用同向 transform 补偿以保持视口固定 */\nconst scrollPos = reactive({ x: 0, y: 0 })\nconst overlayStyle = computed(() => ({\n transform: `translate(${scrollPos.x}px, ${scrollPos.y}px)`,\n}))\n\nfunction measureRuler() {\n const area = rootRef.value\n // 读取纸张本体而非 wrapper:缩放时 wrapper 尺寸立即变为目标值,\n // 纸张本体有 150ms transform 过渡,标尺需要跟随实时视觉位置与比例。\n const paper = area?.querySelector('.hiprint-printPaper') as HTMLElement | null\n if (!area || !paper) return\n const ar = area.getBoundingClientRect()\n const pr = paper.getBoundingClientRect()\n const targetScale = props.scale || 1\n const measuredScale = pr.width / mmToPx(paperWidthMM.value)\n // 过渡终点附近消除子像素误差,静止时保持与业务 scale 完全一致\n rulerGeom.paperScale = Math.abs(measuredScale - targetScale) < 0.002\n ? targetScale\n : measuredScale\n rulerGeom.originX = pr.left - ar.left - RULER_THICKNESS\n rulerGeom.originY = pr.top - ar.top - RULER_THICKNESS\n rulerGeom.viewW = area.clientWidth - RULER_THICKNESS\n rulerGeom.viewH = area.clientHeight - RULER_THICKNESS\n}\n\nfunction onScroll() {\n scrollPos.x = rootRef.value?.scrollLeft ?? 0\n scrollPos.y = rootRef.value?.scrollTop ?? 0\n measureRuler()\n}\n\nlet resizeObserver: ResizeObserver | null = null\n/** 缩放切换后纸张有 150ms CSS 过渡,期间持续重测,刻度才不会跳变 */\nlet scaleMeasureRaf = 0\nfunction startScaleMeasureLoop() {\n cancelAnimationFrame(scaleMeasureRaf)\n const endAt = performance.now() + 220\n const loop = () => {\n measureRuler()\n if (performance.now() < endAt) scaleMeasureRaf = requestAnimationFrame(loop)\n }\n scaleMeasureRaf = requestAnimationFrame(loop)\n}\n\n/** 从标尺拖出参考线的预览态(纸面 mm 坐标) */\nconst guidePreview = ref<{ type: 'vertical' | 'horizontal'; mm: number } | null>(null)\nfunction onGuideDragging(type: 'vertical' | 'horizontal', mm: number | null) {\n guidePreview.value = mm === null ? null : { type, mm }\n}\nconst guidePreviewStyle = computed(() => {\n const g = guidePreview.value\n const paper = rootRef.value?.querySelector('.hiprint-printPaper') as HTMLElement | null\n if (!g || !paper) return {}\n // position: fixed,直接采用视口坐标(与框选选框一致)\n const pr = paper.getBoundingClientRect()\n const liveScale = pr.width / mmToPx(paperWidthMM.value)\n const along = mmToPx(g.mm) * (liveScale > 0 ? liveScale : (props.scale || 1))\n if (g.type === 'vertical') {\n return { left: pr.left + along + 'px', top: pr.top + 'px', height: pr.height + 'px' }\n }\n return { left: pr.left + 'px', top: pr.top + along + 'px', width: pr.width + 'px' }\n})\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 area = rootRef.value\n const paper = area?.querySelector('.hiprint-printPaper') as HTMLElement | null\n if (!area || !paper) return\n const areaRect = area.getBoundingClientRect()\n rulerCursor.x = e.clientX - areaRect.left - RULER_THICKNESS\n rulerCursor.y = e.clientY - areaRect.top - RULER_THICKNESS\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() {\n emit('coordinate', null)\n rulerCursor.x = null\n rulerCursor.y = null\n}\n\n/** Ctrl/Cmd+滚轮缩放:以鼠标位置为缩放中心,缩放前后保持鼠标下的内容点不动 */\nfunction onWheel(e: WheelEvent) {\n if (!(e.ctrlKey || e.metaKey)) return\n e.preventDefault()\n // props.scale 为小数;统一在百分比整数域做乘性步进,\n // 取消放大上限,同时避免浮点累加产生脏显示\n const oldScale = props.scale || 1\n const oldPercent = Math.round(oldScale * 100)\n const newPercent = nextWheelScale(oldPercent, e.deltaY > 0 ? -1 : 1)\n if (newPercent === oldPercent) return\n const newScale = newPercent / 100\n\n const container = rootRef.value\n // 记录鼠标下的内容点(相对滚动内容原点)。容器存在非对称 padding,\n // 换算时必须扣除,否则每次缩放锚点会漂移 pad*(ratio-1)\n let anchor: { x: number; y: number; ratio: number; mouseX: number; mouseY: number } | null = null\n if (container) {\n const rect = container.getBoundingClientRect()\n const cs = getComputedStyle(container)\n const padX = parseFloat(cs.paddingLeft) || 0\n const padY = parseFloat(cs.paddingTop) || 0\n anchor = {\n x: container.scrollLeft + (e.clientX - rect.left) - padX,\n y: container.scrollTop + (e.clientY - rect.top) - padY,\n ratio: newScale / oldScale,\n mouseX: e.clientX - rect.left,\n mouseY: e.clientY - rect.top,\n }\n }\n\n // 以百分比整数增量上报(父级 scale 为百分比)\n emit('zoom', newPercent - oldPercent)\n\n // 待新比例应用到 DOM 后再校正滚动位置:缩放前若该方向没有滚动条,\n // 提前写入 scrollTop/Left 会被浏览器钳制为 0,导致锚点失效\n if (container && anchor) {\n const a = anchor\n void nextTick(() => {\n const cs = getComputedStyle(container)\n const padX = parseFloat(cs.paddingLeft) || 0\n const padY = parseFloat(cs.paddingTop) || 0\n container.scrollLeft = a.x * a.ratio - a.mouseX + padX\n container.scrollTop = a.y * a.ratio - a.mouseY + padY\n })\n }\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\nonMounted(() => {\n nextTick(measureRuler)\n if (rootRef.value && typeof ResizeObserver !== 'undefined') {\n resizeObserver = new ResizeObserver(measureRuler)\n resizeObserver.observe(rootRef.value)\n }\n})\n\nwatch(() => props.scale, startScaleMeasureLoop)\nwatch([paperWidthMM, paperHeightMM], () => nextTick(measureRuler))\n\nonBeforeUnmount(() => {\n window.removeEventListener('mousemove', onMarqueeMove)\n window.removeEventListener('mouseup', onMarqueeUp)\n resizeObserver?.disconnect()\n cancelAnimationFrame(scaleMeasureRaf)\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 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 margin: 0 auto;\n width: fit-content;\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\n/* ─── 视口固定标尺 ─── */\n.ruler-overlay {\n position: absolute;\n inset: 0;\n pointer-events: none;\n z-index: 60;\n}\n.ruler-corner {\n position: absolute;\n top: 0;\n left: 0;\n width: 22px;\n height: 22px;\n background: var(--pd-ruler-bg, #f8f9fc);\n box-shadow: 1px 1px 0 var(--pd-border-soft, #e9ecf2);\n z-index: 2;\n}\n.ruler-overlay :deep(.pd-ruler.is-horizontal) {\n top: 0;\n left: 22px;\n}\n.ruler-overlay :deep(.pd-ruler.is-vertical) {\n top: 22px;\n left: 0;\n}\n/* 拖出参考线的预览虚线 */\n.ruler-guide-preview {\n position: fixed;\n pointer-events: none;\n z-index: 9997;\n}\n.ruler-guide-preview.guide-vertical {\n width: 0;\n border-left: 1px dashed var(--pd-accent, #165dff);\n}\n.ruler-guide-preview.guide-horizontal {\n height: 0;\n border-top: 1px dashed var(--pd-accent, #165dff);\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 <div class=\"pd-stepper\">\n <button\n type=\"button\"\n class=\"pd-step-btn pd-step-minus\"\n :disabled=\"atMin\"\n title=\"减小\"\n aria-label=\"减小\"\n @click=\"stepBy(-1)\"\n >−</button>\n <input\n type=\"number\"\n class=\"pd-input pd-step-input\"\n :value=\"draft\"\n :placeholder=\"placeholder\"\n :min=\"min\"\n :max=\"max\"\n :step=\"step\"\n @input=\"onInput\"\n @change=\"commit\"\n @blur=\"commit\"\n @keydown.enter.prevent=\"($event.target as HTMLInputElement).blur()\"\n />\n <button\n type=\"button\"\n class=\"pd-step-btn pd-step-plus\"\n :disabled=\"atMax\"\n title=\"增大\"\n aria-label=\"增大\"\n @click=\"stepBy(1)\"\n >+</button>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\n\nconst props = withDefaults(defineProps<{\n /** 数值;undefined 表示未设置(继承默认),输入框显示空占位 */\n modelValue?: number\n min?: number\n max?: number\n /** 步进单位,默认 1(整数);小数步进时按小数位数保留精度 */\n step?: number\n /** 未设置(继承默认)时输入框的占位提示 */\n placeholder?: string\n}>(), {\n step: 1,\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: number | undefined]\n}>()\n\n/** 步进小数位数:由 step 推导(0.5→1 位,0.25→2 位,0.1→1 位,1→0 位) */\nconst precision = computed(() => {\n const s = String(props.step)\n const dot = s.indexOf('.')\n return dot === -1 ? 0 : s.length - dot - 1\n})\n\n/** 按 step 精度取整,规避浮点误差(0.30000000000000004 → 0.3) */\nfunction roundTo(v: number): number {\n if (!Number.isFinite(v)) return 0\n return Number(v.toFixed(precision.value))\n}\n\n/** 当前有效值:undefined 表示未设置(继承默认) */\nconst current = computed<number | undefined>(() => {\n const v = props.modelValue\n if (v === undefined || v === null || !Number.isFinite(v)) return undefined\n return roundTo(v)\n})\n\n/** 输入框草稿:输入过程中保留原文,失焦/回车后按精度规范化 */\nconst draft = ref(current.value === undefined ? '' : String(current.value))\nwatch(current, (v) => {\n draft.value = v === undefined ? '' : String(v)\n})\n\n/** 步进基准:未设置时从 min(无 min 则为 0)起步 */\nconst base = computed(() => {\n if (current.value !== undefined) return current.value\n return props.min !== undefined ? props.min : 0\n})\n\nconst atMin = computed(() => props.min !== undefined && base.value <= props.min)\nconst atMax = computed(() => props.max !== undefined && base.value >= props.max)\n\n/** 夹取到 [min, max],并按 step 精度取整 */\nfunction clamp(v: number): number {\n let next = roundTo(v)\n if (props.min !== undefined && next < props.min) next = props.min\n if (props.max !== undefined && next > props.max) next = props.max\n return next\n}\n\nfunction stepBy(dir: 1 | -1) {\n if ((dir < 0 && atMin.value) || (dir > 0 && atMax.value)) return\n const next = clamp(base.value + dir * props.step)\n draft.value = String(next)\n emit('update:modelValue', next)\n}\n\nfunction onInput(e: Event) {\n draft.value = (e.target as HTMLInputElement).value\n}\n\n/** 失焦/回车提交:解析草稿并按精度取整;空值回退为当前值(未设置则保持未设置) */\nfunction commit() {\n const raw = draft.value.trim()\n if (raw === '') {\n if (current.value !== undefined) {\n draft.value = String(current.value)\n }\n return\n }\n const num = Number(raw)\n if (!Number.isFinite(num)) {\n draft.value = current.value === undefined ? '' : String(current.value)\n return\n }\n const next = clamp(num)\n draft.value = String(next)\n // change 与 blur 会先后触发,仅当值真正变化时 emit,避免重复提交\n if (next !== current.value) {\n emit('update:modelValue', next)\n }\n}\n</script>\n\n<style scoped>\n.pd-stepper {\n display: flex;\n align-items: center;\n width: 100%;\n}\n.pd-step-btn {\n width: 26px;\n height: 26px;\n flex-shrink: 0;\n border: 1px solid var(--pd-border, #d9dde6);\n background: var(--pd-field-bg, #f4f6fa);\n color: var(--pd-text, #2a2e37);\n font-size: 14px;\n line-height: 1;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background .14s ease, border-color .14s ease, color .14s ease;\n}\n.pd-step-btn:hover:not(:disabled) {\n background: var(--pd-sidebar-hover, #f0f3f9);\n border-color: var(--pd-text-faint, #b4b9c4);\n}\n.pd-step-btn:disabled {\n opacity: 0.45;\n cursor: not-allowed;\n}\n.pd-step-minus {\n border-radius: 6px 0 0 6px;\n border-right: none;\n}\n.pd-step-plus {\n border-radius: 0 6px 6px 0;\n border-left: none;\n}\n.pd-step-input.pd-input {\n border-radius: 0;\n min-width: 0;\n flex: 1;\n text-align: center;\n -moz-appearance: textfield;\n}\n.pd-step-input.pd-input::-webkit-outer-spin-button,\n.pd-step-input.pd-input::-webkit-inner-spin-button {\n -webkit-appearance: none;\n margin: 0;\n}\n</style>\n","<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 <StepperInput v-model=\"element.options.left\"\n :min=\"0\" />\n </div>\n <div class=\"pd-field\" v-show=\"showItem('ps-top')\"><span class=\"pd-label\">Y</span>\n <StepperInput v-model=\"element.options.top\"\n :min=\"0\" />\n </div>\n <div class=\"pd-field\" v-show=\"showItem('ps-width')\"><span class=\"pd-label\">W</span>\n <StepperInput v-model=\"element.options.width\"\n :min=\"4\" />\n </div>\n <div class=\"pd-field\" v-show=\"showItem('ps-height')\"><span class=\"pd-label\">H</span>\n <StepperInput v-model=\"element.options.height\"\n :min=\"4\" />\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'\nimport StepperInput from './StepperInput.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 <StepperInput v-model=\"element.options.fontSize\"\n :min=\"8\"\n :max=\"72\" />\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 <StepperInput v-model=\"element.options.lineHeight\"\n :min=\"0\"\n :max=\"100\" />\n </div>\n <div class=\"pd-field\" v-show=\"showItem('ap-letter-spacing')\"><span class=\"pd-label\">字间距</span>\n <StepperInput v-model=\"element.options.letterSpacing\"\n :min=\"0\"\n :max=\"20\"\n :step=\"0.5\" />\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'\nimport StepperInput from './StepperInput.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 <div class=\"ee-field-info\">\n <span class=\"ee-item-label\">{{ field.fieldLabel }}</span>\n <span class=\"ee-item-key\">{{ field.fieldKey }}</span>\n </div>\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=\"handleVariableDoubleClick(sv)\"\n >\n <div class=\"ee-field-info\">\n <span class=\"ee-item-label\">{{ sv.label }}</span>\n <span class=\"ee-item-key\">{{ sv.template }}</span>\n </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=\"handleFunctionDoubleClick(fn)\"\n >\n <div class=\"ee-field-info\">\n <span class=\"ee-item-label\">{{ fn.label }}</span>\n <span class=\"ee-item-key\">{{ fn.name }}()</span>\n </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=\"handleFunctionDoubleClick(fn)\"\n >\n <div class=\"ee-field-info\">\n <span class=\"ee-item-label\">{{ fn.label }}</span>\n <span class=\"ee-item-key\">{{ fn.name }}()</span>\n </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=\"双击左侧字段/变量/函数插入,或直接输入静态内容\"\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 静态数据直接输入即可,如:供应商名称<br>\n 动态解析字段、变量、函数必须用 {} 包裹<br>\n 示例:{SUM(supplier.name)}<br>\n 注意:只能嵌套一层\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(字段) - 计数<br>\n IF(条件, 真值, 假值) - 条件判断\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 {pageIndex} - 当前页码<br>\n {totalPages} - 总页数<br>\n {printDate} - 打印日期\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 静态文本:供应商名称<br>\n 动态字段:{supplier.name}<br>\n 函数调用:{SUM(amount)}<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// 当弹出框打开时,重置为外部传入值\nwatch(visible, (val) => {\n if (val) {\n localExpression.value = props.expression || ''\n }\n})\n\n// 字段双击:函数参数内插入裸字段(去大括号),其余场景保持 {字段} 包裹\nfunction handleFieldDoubleClick(field: PrintBusinessField) {\n const { insideParens } = getCursorRegion()\n insertAtCursor(insideParens ? field.fieldKey : `{${field.fieldKey}}`)\n}\n\n// 变量双击:函数参数内去大括号,其余场景保持 {变量} 原样\nfunction handleVariableDoubleClick(sv: { name: string; template: string }) {\n const { insideParens } = getCursorRegion()\n insertAtCursor(insideParens ? sv.template.replace(/^\\{|\\}$/g, '') : sv.template)\n}\n\n// 函数双击:已在 {…} 块内则裸插入,否则自动包裹大括号;光标定位到 () 内部\nfunction handleFunctionDoubleClick(fn: { name: string; template: string }) {\n const { insideBlock } = getCursorRegion()\n const text = insideBlock ? fn.template : `{${fn.template}}`\n const caretOffset = text.indexOf('(') + 1\n insertAtCursor(text, caretOffset)\n}\n\n// 根据光标位置判断插入上下文:是否在 {…} 表达式块内、是否在函数参数 (…) 内\nfunction getCursorRegion(): { insideBlock: boolean; insideParens: boolean } {\n const ta = textareaRef.value\n const start = ta?.selectionStart ?? localExpression.value.length\n const before = localExpression.value.substring(0, start)\n\n // 光标前最近的 { 未被 } 闭合 → 在表达式块内\n let insideBlock = false\n const lastBlockOpen = before.lastIndexOf('{')\n if (lastBlockOpen !== -1 && !before.slice(lastBlockOpen + 1).includes('}')) {\n insideBlock = true\n }\n\n // 光标前最近的 ( 未被 ) 闭合 → 在函数参数内\n let insideParens = false\n const lastParenOpen = before.lastIndexOf('(')\n if (lastParenOpen !== -1 && !before.slice(lastParenOpen + 1).includes(')')) {\n insideParens = true\n }\n\n return { insideBlock, insideParens }\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, caretOffset = text.length) {\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 const caretPos = start + caretOffset\n nextTick(() => {\n ta.focus()\n ta.selectionStart = ta.selectionEnd = caretPos\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: 6px 10px;\n margin-bottom: 2px;\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: 7px 10px;\n cursor: pointer;\n border-radius: 4px;\n margin-bottom: 2px;\n transition: background 0.15s;\n}\n.ee-field-info {\n display: flex;\n flex-direction: column;\n gap: 1px;\n}\n.ee-field-info .ee-item-label {\n font-size: 12px;\n color: var(--pd-text);\n}\n.ee-field-info .ee-item-key {\n font-size: 10px;\n color: var(--pd-text-muted);\n font-family: monospace;\n}\n\n.ee-list-item:hover {\n background: #ecf5ff;\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 <StepperInput v-model=\"element.options.tableDefaultFontSize\" :min=\"5\" :max=\"72\" placeholder=\"默认\" />\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 <StepperInput v-model=\"element.options.tableDefaultPadding\" :min=\"0\" :max=\"10\" :step=\"0.5\" placeholder=\"默认\" />\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 <StepperInput :model-value=\"w\" :min=\"5\" :max=\"200\" @update:model-value=\"onColWidthChange(i, $event)\" />\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'\nimport StepperInput from './StepperInput.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 <StepperInput v-model=\"element.options.borderWidth\"\n :min=\"0\"\n :max=\"20\"\n :step=\"0.25\" />\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'\nimport StepperInput from './StepperInput.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: 10px;\n}\n.border-row .pd-field {\n flex: 1;\n min-width: 0;\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 <StepperInput v-model=\"element.options.zIndex\"\n :min=\"0\"\n :max=\"999\" />\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'\nimport StepperInput from './StepperInput.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 <StepperInput :model-value=\"row.height\"\n :min=\"3\"\n :max=\"100\"\n :step=\"0.5\" @update:model-value=\"onHeightChange\" />\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'\nimport StepperInput from './StepperInput.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 <label class=\"pd-radio\"><input type=\"radio\" value=\"image\" :checked=\"mainCell.cellType === 'image'\" @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\" v-if=\"isBarcodeCell || isQrcodeCell || isImageCell\"><span class=\"pd-label\">缩放模式</span>\n <select :value=\"mainCell.fit || 'contain'\" class=\"pd-select\" @change=\"write(c => { c.fit = ($event.target as HTMLSelectElement).value as any })\">\n <option value=\"contain\">包含(保持比例)</option>\n <option value=\"cover\">覆盖(保持比例)</option>\n <option value=\"fill\">拉伸填满</option>\n <option value=\"none\">原始尺寸</option>\n <option value=\"scale-down\">缩小(保持比例)</option>\n </select>\n </div>\n <div class=\"pd-field\" v-if=\"isBarcodeCell || isQrcodeCell || isImageCell\"><span class=\"pd-label\">最大宽度 (mm)</span>\n <StepperInput :model-value=\"mainCell.maxWidth\"\n :min=\"1\"\n :max=\"200\"\n placeholder=\"默认\" @update:model-value=\"write(c => { c.maxWidth = $event ?? undefined })\" />\n </div>\n <div class=\"pd-field\" v-if=\"isBarcodeCell || isQrcodeCell || isImageCell\"><span class=\"pd-label\">最大高度 (mm)</span>\n <StepperInput :model-value=\"mainCell.maxHeight\"\n :min=\"1\"\n :max=\"200\"\n placeholder=\"默认\" @update:model-value=\"write(c => { c.maxHeight = $event ?? undefined })\" />\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 <StepperInput :model-value=\"mainCell.fontSize\"\n :min=\"5\"\n :max=\"72\"\n placeholder=\"默认\" @update:model-value=\"write(c => { c.fontSize = $event ?? 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 <div style=\"width: 112px; flex-shrink: 0\"><StepperInput v-model=\"borderWidth\"\n :min=\"0.25\"\n :max=\"5\"\n :step=\"0.25\" /></div>\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 <StepperInput :model-value=\"mainCell.padding\"\n :min=\"0\"\n :max=\"10\"\n :step=\"0.5\"\n placeholder=\"默认\" @update:model-value=\"write(c => { c.padding = $event ?? 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 StepperInput from './StepperInput.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')\nconst isImageCell = computed(() => mainCell.value.cellType === 'image')\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 // fit、maxWidth、maxHeight 对所有类型都有效,不再清除\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 <StepperInput :model-value=\"customWidth\"\n :min=\"25\"\n :max=\"2000\"\n @update:model-value=\"onCustomWidthChange\" />\n <span class=\"custom-size-x\">×</span>\n <StepperInput :model-value=\"customHeight\"\n :min=\"25\"\n :max=\"2000\"\n @update:model-value=\"onCustomHeightChange\" />\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 <div class=\"pd-field\"><span class=\"pd-label\">页面背景色</span>\n <div class=\"page-bg-row\">\n <PresetColorPicker v-model=\"pageBackgroundModel\" class=\"page-bg-picker\" />\n <button type=\"button\" class=\"pd-reset\" title=\"恢复为默认白色\" @click=\"onPageBackgroundReset\">默认</button>\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 <StepperInput :model-value=\"marginTop\" :min=\"0\" :max=\"50\" @update:model-value=\"onMarginTopChange\" />\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">下</span>\n <StepperInput :model-value=\"marginBottom\" :min=\"0\" :max=\"50\" @update:model-value=\"onMarginBottomChange\" />\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">左</span>\n <StepperInput :model-value=\"marginLeft\" :min=\"0\" :max=\"50\" @update:model-value=\"onMarginLeftChange\" />\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">右</span>\n <StepperInput :model-value=\"marginRight\" :min=\"0\" :max=\"50\" @update:model-value=\"onMarginRightChange\" />\n </div>\n </div>\n\n <h3 class=\"pd-divider\">三区高度 (mm)</h3>\n <div class=\"pd-field\"><span class=\"pd-label\">页眉高度</span>\n <StepperInput :model-value=\"headerHeight\" :min=\"0\" :max=\"100\" :step=\"0.1\" @update:model-value=\"onHeaderHeightChange\" />\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">页脚高度</span>\n <StepperInput :model-value=\"footerHeight\" :min=\"0\" :max=\"100\" :step=\"0.1\" @update:model-value=\"onFooterHeightChange\" />\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">首页叠加高度</span>\n <StepperInput :model-value=\"overlayHeight\" :min=\"0\" :max=\"200\" @update:model-value=\"onOverlayHeightChange\" />\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 StepperInput from './property/StepperInput.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 PresetColorPicker from './PresetColorPicker.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 pageBackgroundModel = computed({\n get: () => props.templateData?.pageBackground || '#ffffff',\n set: (v: string) => onPageBackgroundChange(v),\n})\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 onPageBackgroundChange(v: string) {\n const value = v && v.toLowerCase() !== '#ffffff' && v.toLowerCase() !== '#fff' ? v : undefined\n emitUpdate(value === undefined ? { pageBackground: undefined } : { pageBackground: value })\n}\n\nfunction onPageBackgroundReset() {\n emitUpdate({ pageBackground: undefined })\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.page-bg-row {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.page-bg-picker {\n flex: 1;\n min-width: 0;\n}\n.pd-reset {\n height: 26px;\n padding: 0 8px;\n border: 1px solid var(--pd-border, #d9dde6);\n border-radius: 5px;\n background: var(--pd-field-bg, #f4f6fa);\n color: var(--pd-text-muted, #8b909c);\n font-size: 12px;\n cursor: pointer;\n flex-shrink: 0;\n transition: all .14s ease;\n}\n.pd-reset:hover {\n color: var(--pd-accent, #165DFF);\n border-color: var(--pd-accent, #165DFF);\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) }} 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","export default {\n id: 'getting-started',\n title: '快速入门',\n content: `\n<h2>界面布局</h2>\n<p>打印模板设计器采用三栏布局:</p>\n<ul>\n <li><strong>左侧面板</strong>:字段树和图层管理,用于查看和管理画布上的元素</li>\n <li><strong>中间画布</strong>:设计区域,支持标尺、参考线、网格显示</li>\n <li><strong>右侧面板</strong>:属性设置和模板配置</li>\n <li><strong>顶部工具栏</strong>:常用操作按钮</li>\n <li><strong>底部状态栏</strong>:显示坐标、缩放比例、元素数量</li>\n</ul>\n\n<h2>添加第一个元素</h2>\n<ol>\n <li>从左侧面板选择元素类型(文本、图片、条码等)</li>\n <li>拖拽到画布上松开</li>\n <li>选中元素后,通过拖拽调整位置</li>\n <li>拖拽元素边角手柄调整大小</li>\n</ol>\n\n<h2>数据绑定基础</h2>\n<p>使用花括号 <code>{field.path}</code> 语法绑定数据字段:</p>\n<pre><code>供应商:{supplier.name}\n日期:{order.date}\n金额:{MONEY(order.total)}</code></pre>\n<p>双击元素可打开表达式编辑器配置绑定。</p>\n\n<h2>保存与预览</h2>\n<ul>\n <li>点击工具栏\"保存\"按钮,模板以 JSON 格式导出</li>\n <li>点击\"预览\"按钮查看打印效果</li>\n <li>模板数据包含页面设置、元素定义、样式配置</li>\n</ul>\n\n<h2>关于项目</h2>\n<p><strong>项目名称:</strong>worm-vue3-print</p>\n<p><strong>仓库地址:</strong><a href=\"https://gitee.com/liulong_oschina/worm-vue3-print\" target=\"_blank\" rel=\"noopener noreferrer\">https://gitee.com/liulong_oschina/worm-vue3-print</a></p>\n<p>基于 Vue 3 的可视化打印模板设计器,支持拖拽式模板编辑、表达式数据绑定和浏览器端打印预览。</p>\n `\n}\n","export default {\n id: 'features',\n title: '功能说明',\n content: `\n<h2>元素类型</h2>\n<table>\n <thead>\n <tr><th>类型</th><th>说明</th></tr>\n </thead>\n <tbody>\n <tr><td>文本</td><td>静态或动态文本,支持表达式绑定</td></tr>\n <tr><td>长文本</td><td>多行文本,支持自动换行</td></tr>\n <tr><td>数据表格</td><td>动态行列,支持分页、表头重复、序号/小计/汇总</td></tr>\n <tr><td>条形码</td><td>支持 code128 等多种码制</td></tr>\n <tr><td>二维码</td><td>支持 L/M/Q/H 纠错级别</td></tr>\n <tr><td>图片</td><td>静态或动态图片</td></tr>\n <tr><td>线条</td><td>水平线或垂直线</td></tr>\n <tr><td>形状</td><td>矩形、椭圆,支持边框和背景色</td></tr>\n <tr><td>HTML</td><td>自定义 HTML 内容</td></tr>\n <tr><td>页码</td><td>自动页码显示</td></tr>\n </tbody>\n</table>\n\n<h2>表达式编辑器</h2>\n<h3>基础语法</h3>\n<p>使用花括号 <code>{}</code> 包裹表达式,花括号外为字面文本。</p>\n\n<h3>内置函数</h3>\n<table>\n <thead>\n <tr><th>函数</th><th>说明</th><th>示例</th></tr>\n </thead>\n <tbody>\n <tr><td><code>MONEY(value)</code></td><td>金额格式化(千分位+两位小数)</td><td><code>{MONEY(order.total)}</code> -> \"69,543.75\"</td></tr>\n <tr><td><code>DATE(value, format)</code></td><td>日期格式化</td><td><code>{DATE(order.date, 'YYYY-MM-DD')}</code></td></tr>\n <tr><td><code>UPPER(value)</code></td><td>数字转大写金额</td><td><code>{UPPER(order.total)}</code> -> \"陆万玖仟伍佰肆拾叁元柒角伍分\"</td></tr>\n <tr><td><code>IF(cond, true, false)</code></td><td>条件判断</td><td><code>{IF(qty > 100, '大量', '少量')}</code></td></tr>\n <tr><td><code>CONCAT(str1, str2, ...)</code></td><td>字符串拼接</td><td><code>{CONCAT(name, '-', spec)}</code></td></tr>\n <tr><td><code>IFEMPTY(value, default)</code></td><td>空值默认</td><td><code>{IFEMPTY(remark, '无')}</code></td></tr>\n <tr><td><code>ROUND(num, decimals)</code></td><td>四舍五入</td><td><code>{ROUND(price, 2)}</code></td></tr>\n <tr><td><code>NOW()</code></td><td>当前日期</td><td><code>{NOW()}</code></td></tr>\n <tr><td><code>SUBSTR(str, start, len)</code></td><td>子字符串</td><td><code>{SUBSTR(name, 0, 3)}</code></td></tr>\n <tr><td><code>LEN(str)</code></td><td>字符串长度</td><td><code>{LEN(name)}</code></td></tr>\n <tr><td><code>PAD(value, len, char)</code></td><td>左侧补位</td><td><code>{PAD(qty, 5, '0')}</code></td></tr>\n </tbody>\n</table>\n\n<h3>聚合函数(表格小计/汇总行使用)</h3>\n<table>\n <thead>\n <tr><th>函数</th><th>说明</th></tr>\n </thead>\n <tbody>\n <tr><td><code>SUM(field)</code></td><td>求和</td></tr>\n <tr><td><code>AVG(field)</code></td><td>平均值</td></tr>\n <tr><td><code>COUNT(field)</code></td><td>计数</td></tr>\n <tr><td><code>MIN(field)</code></td><td>最小值</td></tr>\n <tr><td><code>MAX(field)</code></td><td>最大值</td></tr>\n </tbody>\n</table>\n\n<h3>系统变量</h3>\n<table>\n <thead>\n <tr><th>变量</th><th>说明</th></tr>\n </thead>\n <tbody>\n <tr><td><code>pageIndex</code></td><td>当前页码</td></tr>\n <tr><td><code>totalPages</code></td><td>总页数</td></tr>\n <tr><td><code>printDate</code></td><td>打印日期 (YYYY-MM-DD)</td></tr>\n <tr><td><code>printTime</code></td><td>打印时间戳</td></tr>\n </tbody>\n</table>\n\n<h2>数据表格配置</h2>\n<h3>行类型</h3>\n<ul>\n <li><strong>标题行 (header)</strong>:可设置每页重复显示</li>\n <li><strong>数据行 (data)</strong>:绑定列表数据源迭代显示</li>\n <li><strong>小计行 (subtotal)</strong>:当前页末尾显示汇总</li>\n <li><strong>汇总行 (summary)</strong>:仅最后一页显示</li>\n</ul>\n\n<h3>表格操作</h3>\n<ul>\n <li>右键菜单支持插入/删除行和列</li>\n <li>支持单元格合并/拆分</li>\n <li>支持边框预设:全部/外边框/内边框/无</li>\n <li>无边框表格设计态显示虚拟虚线</li>\n <li><strong>调整列宽</strong>:需要先在左侧面板的图层中选中对应的表格元素,然后才能在画布上拖动列宽分隔线</li>\n <li><strong>调整表格属性</strong>:必须确保当前没有任何单元格被选中。如有选中的单元格,先点击画布空白区域取消选中,再在图层中选择表格元素</li>\n <li><strong>单元格图片处理</strong>:若单元格中图片无法缩小,请将图片处理方式设置为\"缩小保持比例\"</li>\n</ul>\n\n<h2>对齐与吸附</h2>\n<h3>自动对齐</h3>\n<p>拖拽元素时自动显示对齐引导线:</p>\n<ul>\n <li>蓝色:左/顶对齐</li>\n <li>绿色:居中对齐</li>\n <li>橙色:右/底对齐</li>\n</ul>\n\n<h3>网格吸附</h3>\n<p>开启吸附功能后,元素自动吸附到网格点。</p>\n\n<h3>手动参考线</h3>\n<p>通过标尺区域拖拽添加参考线,参考线参与吸附检测。</p>\n\n<h2>图层管理</h2>\n<ul>\n <li>调整元素显示顺序(置顶/置底/上移/下移)</li>\n <li>显示/隐藏元素</li>\n <li>锁定/解锁元素(锁定后不可编辑)</li>\n</ul>\n\n<h2>三区布局</h2>\n<p>页面分为三个区域:</p>\n<ul>\n <li><strong>页眉 (header)</strong>:顶部区域</li>\n <li><strong>内容区 (content)</strong>:主体区域</li>\n <li><strong>页脚 (footer)</strong>:底部区域</li>\n</ul>\n<p>页眉/页脚支持的元素类型:文本、图片、线条、形状、条形码、二维码</p>\n\n<h2>水印配置</h2>\n<ul>\n <li>支持固定文本或绑定字段</li>\n <li>可设置旋转角度和透明度</li>\n <li>支持显示打印时间戳</li>\n</ul>\n `\n}\n","export default {\n id: 'shortcuts',\n title: '快捷键',\n content: `\n<h2>常用操作</h2>\n<table>\n <thead>\n <tr><th>快捷键</th><th>功能</th></tr>\n </thead>\n <tbody>\n <tr><td><code>Ctrl + C</code></td><td>复制选中元素</td></tr>\n <tr><td><code>Ctrl + V</code></td><td>粘贴元素(偏移 10mm)</td></tr>\n <tr><td><code>Ctrl + D</code></td><td>原地复制(偏移 5mm, 5mm)</td></tr>\n <tr><td><code>Ctrl + A</code></td><td>全选元素</td></tr>\n <tr><td><code>Delete / Backspace</code></td><td>删除选中元素</td></tr>\n <tr><td><code>Ctrl + Z</code></td><td>撤销</td></tr>\n <tr><td><code>Ctrl + Shift + Z</code> / <code>Ctrl + Y</code></td><td>重做</td></tr>\n </tbody>\n</table>\n\n<h2>元素移动</h2>\n<table>\n <thead>\n <tr><th>快捷键</th><th>功能</th></tr>\n </thead>\n <tbody>\n <tr><td><code>方向键</code></td><td>移动 1mm</td></tr>\n <tr><td><code>Shift + 方向键</code></td><td>移动 10mm</td></tr>\n <tr><td><code>Ctrl + 方向键</code></td><td>移动 0.5mm</td></tr>\n </tbody>\n</table>\n\n<h2>缩放控制</h2>\n<table>\n <thead>\n <tr><th>快捷键</th><th>功能</th></tr>\n </thead>\n <tbody>\n <tr><td><code>Ctrl + 1</code></td><td>重置缩放至 100%</td></tr>\n <tr><td><code>Ctrl + 0</code></td><td>适应窗口</td></tr>\n </tbody>\n</table>\n\n<h2>对齐操作(多选时)</h2>\n<table>\n <thead>\n <tr><th>快捷键</th><th>功能</th></tr>\n </thead>\n <tbody>\n <tr><td><code>Ctrl + L</code></td><td>左对齐</td></tr>\n <tr><td><code>Ctrl + R</code></td><td>右对齐</td></tr>\n <tr><td><code>Ctrl + E</code></td><td>水平居中</td></tr>\n <tr><td><code>Ctrl + T</code></td><td>顶对齐</td></tr>\n <tr><td><code>Ctrl + B</code></td><td>底对齐</td></tr>\n </tbody>\n</table>\n\n<h2>组合操作</h2>\n<table>\n <thead>\n <tr><th>快捷键</th><th>功能</th></tr>\n </thead>\n <tbody>\n <tr><td><code>Ctrl + G</code></td><td>组合选中元素</td></tr>\n <tr><td><code>Ctrl + Shift + G</code></td><td>取消组合</td></tr>\n </tbody>\n</table>\n\n<blockquote>\n <p><strong>注意</strong>:当焦点在输入框、文本框、下拉框内时,快捷键不生效。</p>\n</blockquote>\n `\n}\n","export default {\n id: 'faq',\n title: '常见问题',\n content: `\n<h2>如何调整纸张大小?</h2>\n<ol>\n <li>在右侧面板选择\"页面设置\"</li>\n <li>选择预设纸张(A4、A3、A5、Letter、Legal)</li>\n <li>或选择\"自定义\"输入宽度和高度(mm)</li>\n <li>设置方向:纵向(portrait)或横向(landscape)</li>\n</ol>\n\n<h2>如何处理分页?</h2>\n<p>数据表格支持自动分页:</p>\n<ol>\n <li>在表格属性中设置\"每页显示行数\"</li>\n <li>启用\"表头重复\"确保跨页时显示标题行</li>\n <li>添加小计行显示当前页汇总</li>\n <li>添加汇总行显示整表汇总</li>\n</ol>\n\n<h2>如何导入外部数据?</h2>\n<p>通过组件 props 传入数据:</p>\n<ul>\n <li><code>fields</code>:字段定义数组,用于字段树显示</li>\n <li><code>initialTemplate</code>:初始模板数据</li>\n <li><code>loadDefaultTemplate</code>:加载默认模板的回调函数</li>\n</ul>\n\n<h2>如何使用表达式绑定字段?</h2>\n<ol>\n <li>双击元素打开表达式编辑器</li>\n <li>使用 <code>{field.path}</code> 语法绑定字段</li>\n <li>使用内置函数格式化数据(如 <code>{MONEY(price)}</code>)</li>\n <li>点击确认保存</li>\n</ol>\n\n<h2>如何调整元素层级?</h2>\n<ol>\n <li>选中一个或多个元素</li>\n <li>点击工具栏的层级按钮:\n <ul>\n <li>⤒ 置顶</li>\n <li>↑ 上移一层</li>\n <li>↓ 下移一层</li>\n <li>⤓ 置底</li>\n </ul>\n </li>\n</ol>\n<p>或使用快捷键在图层面板中调整。</p>\n\n<h2>如何组合多个元素?</h2>\n<ol>\n <li>按住 Ctrl 逐个点击选中多个元素</li>\n <li>点击工具栏\"组合\"按钮,或按 <code>Ctrl + G</code></li>\n <li>组合后点击任一元素可选中整个组</li>\n <li>取消组合:选中组合后点击\"取消组合\",或按 <code>Ctrl + Shift + G</code></li>\n</ol>\n\n<h2>如何使用参考线?</h2>\n<ol>\n <li>在标尺区域拖拽添加参考线</li>\n <li>参考线自动参与吸附检测</li>\n <li>拖拽参考线可调整位置</li>\n <li>双击参考线可删除</li>\n</ol>\n\n<h2>如何预览打印效果?</h2>\n<ol>\n <li>点击工具栏\"预览\"按钮</li>\n <li>预览使用同构渲染管线,确保与实际打印一致</li>\n <li>可通过\"叠层对比\"功能对比设计稿与截图</li>\n</ol>\n\n<h2>模板数据格式是什么?</h2>\n<p>模板以 JSON 格式存储,包含:</p>\n<ul>\n <li><code>paperSize</code>:纸张大小</li>\n <li><code>orientation</code>:方向</li>\n <li><code>margins</code>:页边距</li>\n <li><code>header</code>:页眉配置</li>\n <li><code>footer</code>:页脚配置</li>\n <li><code>elements</code>:元素数组</li>\n <li><code>watermark</code>:水印配置</li>\n</ul>\n\n<h2>如何调整表格列宽?</h2>\n<ol>\n <li>在左侧面板的图层列表中,点击选中对应的表格元素</li>\n <li>此时画布上的表格会显示列宽分隔线</li>\n <li>拖动列宽分隔线即可调整列宽</li>\n</ol>\n<blockquote>\n <p><strong>注意</strong>:必须先选中表格元素,才能激活列宽拖动功能。</p>\n</blockquote>\n\n<h2>如何调整表格属性?</h2>\n<ol>\n <li>确保当前没有任何单元格被选中(如有选中,点击画布空白区域取消选中)</li>\n <li>在左侧面板的图层列表中,点击选中对应的表格元素</li>\n <li>右侧面板会显示表格属性设置</li>\n</ol>\n<blockquote>\n <p><strong>注意</strong>:如果存在选中的单元格,右侧面板将显示单元格属性而非表格属性。</p>\n</blockquote>\n `\n}\n","export default {\n id: 'changelog',\n title: '更新记录',\n content: `\n<h2>v1.2.0 <small>2026-09-10</small></h2>\n\n<h3>新增</h3>\n<ul>\n <li>帮助文档模态框(HelpModal):内置功能介绍、快捷键一览、常见问题与更新记录,按 Esc 或点击遮罩关闭。</li>\n <li>标尺参考线增强:支持从标尺拖拽添加参考线、双击编辑、删除,参考线对齐吸附实时显示。</li>\n <li>表格列宽拖拽新增末列右边界手柄:可直接拖拽末列右边界调整末列宽,受打印范围宽度与最小列宽 5mm 钳制。</li>\n</ul>\n\n<h3>变更</h3>\n<ul>\n <li>优化缩放逻辑:取消放大上限,支持滚轮乘性步进缩放,修复缩放锚点漂移问题。</li>\n <li>移除设计态元素左上角的 fx 绑定标签提示,简化元素视觉呈现。</li>\n</ul>\n\n<h3>文档</h3>\n<ul>\n <li>仓库根目录新增 <code>AGENTS.md</code>:AI 代理行为规范,明确代理在本仓库工作时的语言、专家态度、协作约定等强制要求。</li>\n <li>新增 <code>worm-vue3-print</code> 集成支持 skill:包含安装指南、集成 API、故障排查等参考文档。</li>\n</ul>\n\n<h3>修复</h3>\n<ul>\n <li>表格列宽拖拽存在的多个缺陷:\n <ul>\n <li>内部列边界向左拖时左列宽度不变,导致边界线不跟随光标。</li>\n <li>px → mm 单位换算缺失,拖拽距离存在约 3.78 倍偏差。</li>\n <li><code>table-layout: fixed</code> 下拖拽过程中表格 CSS <code>width(100%)</code> 与列宽和失配,导致浏览器按比例拉伸列,使边界线与右侧内容偏离光标。</li>\n <li>删除 <code>onColResizeStart</code> 中残留的 <code>document.title</code> 调试代码。</li>\n </ul>\n </li>\n</ul>\n\n<h2>v1.1.0 <small>2026-09-06</small></h2>\n\n<h3>新增</h3>\n<ul>\n <li>表格元素支持列宽拖拽:设计态选中表格后,在列边界悬停并拖动即可调整该列宽(左侧列),实时更新画布与元素尺寸;受打印范围宽度与最小列宽 5mm 钳制,拖拽结束后计入一次撤销历史。属性面板的列宽数值输入保留作为精确输入兜底。</li>\n <li>表格单元格支持图片类型:单元格可切换为图片类型,设计态支持选择图片与设置 fit/maxWidth/maxHeight,预览与打印输出完整渲染。</li>\n <li>条形码与二维码单元格支持 fit/maxWidth/maxHeight 属性。</li>\n <li>属性面板位置尺寸改用 StepperInput 控件:支持按钮微调数值;StepperInput 支持可选值列表和小数步进。</li>\n <li>新增统一颜色选择器并重构属性面板字段分组。</li>\n <li>支持页面(纸张)背景色 <code>pageBackground</code>,预览与打印/PDF 输出一致。</li>\n <li>支持 canvas 库模式构建与 npm 发布。</li>\n</ul>\n\n<h3>修复</h3>\n<ul>\n <li>打印/导出 PDF 保留元素背景色(<code>print-color-adjust: exact</code>)。</li>\n <li>打印预览保留元素重叠,表格下方跟随元素按设计坐标绝对定位并透传层级 z-index。</li>\n <li>打印页眉页脚区域贴页面底部,修复页边距失效。</li>\n <li>条形码渲染缺少 <code>object-fit: contain</code>。</li>\n <li>修复 canvas 测试在 vitest v4 + happy-dom 环境下 <code>localStorage</code> 未定义的问题,补充 mock 以兼容测试环境。</li>\n</ul>\n\n<h2>v1.0.0 <small>2026-09-02</small></h2>\n\n<h3>新增</h3>\n<ul>\n <li>首次开源发布。</li>\n <li><code>@worm-vue3-print/core</code>:模板表达式引擎与同构渲染管线(HTML 生成 / 分页 / 数据绑定)。</li>\n <li><code>@worm-vue3-print/canvas</code>:Vue 3 可视化打印模板设计器画布。</li>\n <li>渲染微服务拆分为独立仓库 <code>worm-vue3-print-render</code>(仅 Docker 部署,不上 npm)。</li>\n</ul>\n\n<blockquote>\n <p>完整更新记录请查阅仓库 <code>docs/中文/CHANGELOG.md</code> 与 <code>docs/en/CHANGELOG.en.md</code>。</p>\n</blockquote>\n `\n}\n","import gettingStarted from './getting-started'\nimport features from './features'\nimport shortcuts from './shortcuts'\nimport faq from './faq'\nimport changelog from './changelog'\n\nexport type HelpSection = {\n id: string\n title: string\n content: string\n}\n\nexport const helpSections: HelpSection[] = [\n gettingStarted,\n features,\n shortcuts,\n faq,\n changelog,\n]\n\nexport type { HelpSection as default }\n","<template>\n <Teleport to=\"body\">\n <Transition name=\"help-modal\">\n <div\n v-if=\"visible\"\n class=\"help-modal-overlay\"\n @click.self=\"$emit('close')\"\n >\n <div class=\"help-modal\">\n <div class=\"help-modal-header\">\n <div class=\"help-modal-title-wrap\">\n <h2 class=\"help-modal-title\">帮助文档</h2>\n <span class=\"help-modal-project\">worm-vue3-print</span>\n </div>\n <button\n class=\"help-modal-close\"\n title=\"关闭\"\n @click=\"$emit('close')\"\n >\n ×\n </button>\n </div>\n \n <div class=\"help-modal-body\">\n <div class=\"help-modal-sidebar\">\n <button\n v-for=\"section in sections\"\n :key=\"section.id\"\n :class=\"['help-tab', { active: activeTab === section.id }]\"\n @click=\"switchTab(section.id)\"\n >\n {{ section.title }}\n </button>\n </div>\n \n <div class=\"help-modal-content\">\n <div\n class=\"help-content\"\n v-html=\"currentContent\"\n />\n </div>\n </div>\n </div>\n </div>\n </Transition>\n </Teleport>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, watch, onMounted, onUnmounted } from 'vue'\nimport { helpSections } from '../help-content'\n\nconst props = withDefaults(defineProps<{\n visible: boolean\n initialTab?: string\n}>(), {\n initialTab: 'getting-started'\n})\n\nconst emit = defineEmits<{\n close: []\n 'update:tab': [tab: string]\n}>()\n\nconst sections = helpSections\nconst activeTab = ref(props.initialTab)\n\nconst STORAGE_KEY = 'worm-print-help-tab'\nonMounted(() => {\n const saved = localStorage.getItem(STORAGE_KEY)\n if (saved && sections.some(s => s.id === saved)) {\n activeTab.value = saved\n }\n})\n\nwatch(() => props.visible, (v) => {\n if (v) {\n const saved = localStorage.getItem(STORAGE_KEY)\n if (saved && sections.some(s => s.id === saved)) {\n activeTab.value = saved\n }\n }\n})\n\nfunction switchTab(tabId: string) {\n activeTab.value = tabId\n localStorage.setItem(STORAGE_KEY, tabId)\n emit('update:tab', tabId)\n}\n\nconst currentContent = computed(() => {\n const section = sections.find(s => s.id === activeTab.value)\n return section?.content || ''\n})\n\nfunction handleKeydown(e: KeyboardEvent) {\n if (e.key === 'Escape' && props.visible) {\n emit('close')\n }\n}\n\nonMounted(() => {\n document.addEventListener('keydown', handleKeydown)\n})\n\nonUnmounted(() => {\n document.removeEventListener('keydown', handleKeydown)\n})\n</script>\n\n<style scoped>\n.help-modal-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n}\n\n.help-modal {\n width: 800px;\n max-width: 90vw;\n height: 600px;\n max-height: 85vh;\n background: var(--pd-surface, #ffffff);\n border-radius: 8px;\n box-shadow: 0 4px 24px rgba(0, 0, 0, 0.15);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n.help-modal-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--pd-border, #d9dde6);\n}\n\n.help-modal-title {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--pd-text, #2a2e37);\n}\n\n.help-modal-title-wrap {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.help-modal-project {\n padding: 2px 8px;\n border-radius: 4px;\n background: var(--pd-accent-soft, rgba(22, 93, 255, 0.09));\n color: var(--pd-accent, #165DFF);\n font-size: 12px;\n font-weight: 500;\n}\n\n.help-modal-close {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: none;\n border-radius: 4px;\n background: transparent;\n color: var(--pd-text-muted, #8b909c);\n font-size: 20px;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.help-modal-close:hover {\n background: var(--pd-sidebar-hover, #f0f3f9);\n color: var(--pd-text, #2a2e37);\n}\n\n.help-modal-body {\n flex: 1;\n display: flex;\n overflow: hidden;\n}\n\n.help-modal-sidebar {\n width: 160px;\n padding: 12px;\n border-right: 1px solid var(--pd-border, #d9dde6);\n background: var(--pd-field-bg, #f4f6fa);\n overflow-y: auto;\n}\n\n.help-tab {\n display: block;\n width: 100%;\n padding: 10px 12px;\n margin-bottom: 4px;\n border: none;\n border-radius: 4px;\n background: transparent;\n color: var(--pd-text, #2a2e37);\n font-size: 13px;\n text-align: left;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.help-tab:hover {\n background: var(--pd-sidebar-hover, #f0f3f9);\n}\n\n.help-tab.active {\n background: var(--pd-accent-soft, rgba(22, 93, 255, 0.09));\n color: var(--pd-accent, #165DFF);\n font-weight: 500;\n}\n\n.help-modal-content {\n flex: 1;\n padding: 20px;\n overflow-y: auto;\n}\n\n.help-content {\n font-size: 14px;\n line-height: 1.6;\n color: var(--pd-text, #2a2e37);\n}\n\n.help-content :deep(h2) {\n margin: 0 0 16px;\n padding-bottom: 8px;\n border-bottom: 1px solid var(--pd-border-soft, #e9ecf2);\n font-size: 18px;\n font-weight: 600;\n}\n\n.help-content :deep(h3) {\n margin: 20px 0 12px;\n font-size: 15px;\n font-weight: 600;\n}\n\n.help-content :deep(p) {\n margin: 0 0 12px;\n}\n\n.help-content :deep(ul),\n.help-content :deep(ol) {\n margin: 0 0 12px;\n padding-left: 24px;\n}\n\n.help-content :deep(li) {\n margin-bottom: 4px;\n}\n\n.help-content :deep(code) {\n padding: 2px 6px;\n border-radius: 3px;\n background: var(--pd-field-bg, #f4f6fa);\n font-family: 'SF Mono', Monaco, monospace;\n font-size: 13px;\n}\n\n.help-content :deep(pre) {\n margin: 0 0 12px;\n padding: 12px;\n border-radius: 4px;\n background: var(--pd-field-bg, #f4f6fa);\n overflow-x: auto;\n}\n\n.help-content :deep(pre code) {\n padding: 0;\n background: transparent;\n}\n\n.help-content :deep(table) {\n width: 100%;\n margin: 0 0 12px;\n border-collapse: collapse;\n}\n\n.help-content :deep(th),\n.help-content :deep(td) {\n padding: 8px 12px;\n border: 1px solid var(--pd-border, #d9dde6);\n text-align: left;\n}\n\n.help-content :deep(th) {\n background: var(--pd-field-bg, #f4f6fa);\n font-weight: 600;\n}\n\n.help-content :deep(blockquote) {\n margin: 0 0 12px;\n padding: 12px 16px;\n border-left: 3px solid var(--pd-accent, #165DFF);\n background: var(--pd-accent-soft, rgba(22, 93, 255, 0.09));\n}\n\n.help-modal-enter-active,\n.help-modal-leave-active {\n transition: opacity 0.2s ease;\n}\n\n.help-modal-enter-active .help-modal,\n.help-modal-leave-active .help-modal {\n transition: transform 0.2s ease;\n}\n\n.help-modal-enter-from,\n.help-modal-leave-to {\n opacity: 0;\n}\n\n.help-modal-enter-from .help-modal,\n.help-modal-leave-to .help-modal {\n transform: scale(0.95);\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-ruler=\"showRuler\"\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 @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-ruler=\"showRuler = !showRuler\"\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 @help=\"helpVisible = true\"\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-ruler=\"showRuler\"\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\n <!-- 帮助文档模态框 -->\n <HelpModal\n :visible=\"helpVisible\"\n @close=\"helpVisible = false\"\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 { clampScalePercent } from '../utils/scale'\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 HelpModal from './HelpModal.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 preview: []\n save: [json: string]\n}>()\n\n// 帮助文档状态\nconst helpVisible = ref(false)\n\n// 装配层状态:面板折叠(localStorage 持久)+ 未保存 dirty\nconst { leftCollapsed, rightCollapsed, toggleLeft, toggleRight, dirty, markSaved } = useStudioChrome()\n\n// 设计器核心状态统一由 useDesignerState 管理\nconst {\n scale, showRuler, 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 = clampScalePercent(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 image: 'src',\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","MIN_COL_WIDTH_MM","clampResizedColumnWidth","targetMm","maxTableWidth","others","cap","rounded","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","mmToPx","mm","PT_KEYS","convertElement","el","round2","n","normalizeTemplateUnits","convert","els","PAPER_PRESETS","getPaperDimensions","MIN_SCALE_PERCENT","clampScalePercent","percent","nextWheelScale","direction","factor","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","showRuler","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","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","_createElementBlock","$emit","_createElementVNode","_useModel","__props","_openBlock","_hoisted_1","_hoisted_2","_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","_createVNode","HelpButton","_hoisted_15","_hoisted_16","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","FieldTreePanel","LayerPanel","d","RULER_THICKNESS","STEP_SEQUENCE","chooseMajorStepMM","targetPx","pxPerMM","minorStepMM","majorStepMM","exp","roundMM","buildRulerTicks","startMM","endMM","fine","lastIndex","ticks","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","V_ALIGN_FLEX","H_ALIGN_FLEX","textStyle","o","displayText","imageSrc","raw","hasError","onError","watch","imgStyle","ROW_TYPES","emitAction","payload","_createBlock","_Teleport","barcodeSvg","svgOk","dataUrl","svgStyle","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","imageData","isCodeCell","cellDisplay","_row","cellStyle","borderOpts","cellClass","dragAnchor","applySelection","onCellMouseDown","onCellMouseEnter","onCellDblClick","menu","reactive","onCellContextMenu","mergeReason","canSplit","rowTypeReason","cloned","syncElementSize","checkColWidthLimit","cw","maxW","onMenuAction","err","colResizeEnabled","colResizeBoundaries","colBoundaryLeftMm","colResizeBoundary","resizeStartX","resizeStartWidth","onColResizeStart","onColResizeMove","onColResizeEnd","deltaMm","colIndex","widths","_withModifiers","CellBarcode","CellImage","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","contentComponent","contentAttrs","elementStyle","posLabel","dragStartLeft","dragStartTop","dragConfig","info","finalDx","finalDy","sibling","setupDrag","cleanupDrag","watchEffect","resizeEnabled","cleanupResize","onDblClick","onDblClickCell","elementId","_unref","_resolveDynamicComponent","_mergeProps","p","useAdsorb","config","adsorbMin","adsorbLineMin","showAdsorbLine","guideLines","paperSize","SNAP_COLORS","snapColor","check","movingRect","lines","minDist","other","hPairs","vPairs","ok","dist","m2","hKeys","vKeys","adjustedM","seen","renderLines","clearLines","useAdsorbManager","requestAdsorb","clearGuides","contentRef","paperWidthMM","paperHeightMM","guideHitPx","wrapperStyle","widthPx","heightPx","zoneRectsMM","layerStyle","zoneElements","headerElements","footerElements","contentElements","currentDragZone","rawRequestAdsorb","guidePaperSize","showSnapIndicator","onGuideDown","startPt","MM_PER_PX","onMove","ev","delta","maxPosition","nextPosition","onUp","paperStyle","contentStyle","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","BaseElement","line","idx","horizontal","guideType","canvasRef","hoverPx","effectiveCursorPx","cssSize","rafId","scheduleDraw","draw","canvas","dpr","length","thickness","style","bg","fg","accent","majorStep","drawTicks","drawPaperEdge","cursor","outside","tick","onBeforeUnmount","dragging","axialFromEvent","along","onDown","onWinMove","onWinUp","updateDragPreview","onHoverMove","onHoverLeave","rootRef","rulerGeom","rulerCursor","scrollPos","overlayStyle","measureRuler","area","ar","pr","targetScale","measuredScale","onScroll","resizeObserver","scaleMeasureRaf","startScaleMeasureLoop","endAt","loop","guidePreview","onGuideDragging","guidePreviewStyle","liveScale","toPaperPoint","onDrop","fieldData","elementType","marquee","marqueeStart","isCanvasBackground","areaRect","xMm","yMm","onMouseLeave","onWheel","oldScale","oldPercent","newPercent","newScale","container","anchor","padX","padY","nextTick","onCanvasMouseDown","onMarqueeMove","onMarqueeUp","hitTestIds","paperRect","containMode","elLeft","elTop","elRight","elBottom","inter","contained","contextMenu","onContextMenu","elId","containerRect","closeContextMenu","handlePaste","handleSelectAll","handleClearSelection","action","CanvasPaper","Ruler","PROPERTY_REGISTRY","matchKeywords","search","keywords","searchProperties","itemKeys","matched","onSearch","isExpanded","iconChar","toggle","saveState","loadState","saved","_renderSlot","_ctx","precision","roundTo","current","draft","atMin","atMax","clamp","stepBy","dir","onInput","commit","_withKeys","showItem","PropertyGroup","StepperInput","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","onAreaKeydown","handled","close","open","trigger","panelWidth","panelHeight","margin","below","onDocumentPointerDown","onWindowCloseEvents","onKeydown","match","hex","full","part","red","green","blue","hh","r1","g1","b1","number","isTableType","PresetColorPicker","_hoisted_17","_hoisted_18","val","searchPlaceholder","localExpression","handleFieldDoubleClick","insideParens","getCursorRegion","insertAtCursor","handleVariableDoubleClick","sv","handleFunctionDoubleClick","insideBlock","caretOffset","textareaRef","lastBlockOpen","lastParenOpen","filteredSystemVars","systemVars","filteredAggregateFuncs","aggregateFunctions","filteredFormatFuncs","formatFunctions","previewResult","ta","end","after","caretPos","onConfirm","_hoisted_19","_hoisted_20","_hoisted_22","_hoisted_23","_hoisted_24","_hoisted_25","_hoisted_27","_hoisted_28","_hoisted_29","_hoisted_30","_hoisted_31","_hoisted_32","_hoisted_33","editorVisible","openEditor","ExpressionEditor","tableEditCtx","listFieldOptions","onSourceChange","onColWidthChange","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","isImageCell","onAlignChange","write","onValignChange","onCellTypeChange","openFormatterEditor","onFormatterEditorConfirm","borderStyle","borderWidth","borderColor","edgeChecks","currentBorder","onEdgesChange","edges","nb","side","doMerge","doSplit","_hoisted_21","_hoisted_35","_hoisted_37","_hoisted_39","_hoisted_40","_hoisted_42","_hoisted_43","_hoisted_45","_hoisted_46","_hoisted_47","_hoisted_48","_hoisted_49","_hoisted_50","_hoisted_51","_hoisted_52","_hoisted_53","_hoisted_54","_hoisted_55","_hoisted_56","_hoisted_58","_hoisted_59","_hoisted_60","ELEMENT_BINDING_REGISTRY","getTableCellBindings","rowType","rowIndex","cellIndex","listField","getElementBindings","element","staticBindings","dynamicBindings","paperPresets","isTextType","isImageType","isTableCellSelected","searchResult","matchedKeys","bindingDescriptors","c1","parsePath","targetPath","segment","baseName","indices","getBindingValue","setBindingValue","segments","lastKey","obj","onImageUploadSuccess","paperSizeModel","orientationModel","pageBackgroundModel","onPageBackgroundChange","marginTop","marginBottom","marginLeft","marginRight","headerHeight","footerHeight","overlayHeight","customWidth","customHeight","emitUpdate","onPaperSizeChange","onOrientationChange","onPageBackgroundReset","onCustomWidthChange","onCustomHeightChange","onMarginTopChange","onMarginBottomChange","onMarginLeftChange","onMarginRightChange","onHeaderHeightChange","onFooterHeightChange","onOverlayHeightChange","currentTab","PropertySearch","PositionSizeGroup","AppearanceGroup","desc","BindingControl","ImageContentUpload","TableRowGroup","TableCellGroup","TableSettingsGroup","BorderBgGroup","PaginationGroup","AdvancedGroup","_ps","_hoisted_26","gettingStarted","features","shortcuts","faq","changelog","helpSections","STORAGE_KEY","sections","switchTab","tabId","currentContent","handleKeydown","_Transition","section","LEFT_KEY","RIGHT_KEY","readStored","fallback","useStudioChrome","leftCollapsed","rightCollapsed","dirty","toggleLeft","toggleRight","markSaved","helpVisible","onUndo","onRedo","onAlign","onGroup","onUngroup","onDeleteElement","onDragStop","onDropElement","onDropField","onMoveLayer","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","HelpModal","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","rowHeights","SVG_NS","renderBarcodeSvg","renderQrSvg","level","modules","quiet","browserCodeRenderer","cellType","iframeRef","rendering","errorMsg","renderSeq","rerender","html","pageCount","print"],"mappings":"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"}
|
|
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/HelpButton.vue","../src/components/DesignerToolbar.vue","../src/components/LayerPanel.vue","../src/utils/field-groups.ts","../src/components/FieldTreePanel.vue","../src/components/LeftPanel.vue","../src/utils/ruler.ts","../src/composables/useDrag.ts","../src/composables/useResize.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/CellImage.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/composables/useAdsorb.ts","../src/composables/useAdsorbManager.ts","../src/components/CanvasPaper.vue","../src/components/Ruler.vue","../src/components/CanvasArea.vue","../src/utils/property-search.ts","../src/components/property/PropertySearch.vue","../src/components/property/PropertyGroup.vue","../src/components/property/StepperInput.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/help-content/getting-started.ts","../src/help-content/features.ts","../src/help-content/shortcuts.ts","../src/help-content/faq.ts","../src/help-content/changelog.ts","../src/help-content/index.ts","../src/components/HelpModal.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\n/** 列宽拖拽的最小列宽(mm),与属性面板列宽输入下限一致 */\nexport const MIN_COL_WIDTH_MM = 5\n\n/**\n * 列宽拖拽钳制(纯函数,不修改入参,调用方负责回写):\n * 返回目标列宽在 [MIN_COL_WIDTH_MM, maxTableWidth - 其余列和] 范围内的钳制值,\n * 结果保留 0.1mm 精度。maxTableWidth 为 Infinity 时不设总宽上限。\n */\nexport function clampResizedColumnWidth(\n colWidths: number[],\n index: number,\n targetMm: number,\n maxTableWidth: number,\n): number {\n const others = colWidths.reduce((s, w, i) => (i === index ? s : s + w), 0)\n const cap = maxTableWidth === Infinity\n ? Infinity\n : Math.max(MIN_COL_WIDTH_MM, maxTableWidth - others)\n const rounded = Math.round(targetMm * 10) / 10\n return Math.min(Math.max(rounded, MIN_COL_WIDTH_MM), cap)\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\n/** mm 转 px(基于 96dpi 屏幕) */\nexport function mmToPx(mm: number): number {\n return mm * (96 / 25.4)\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/** 最小缩放百分比,低于此值画布难以查看与操作;放大方向不设上限 */\nexport const MIN_SCALE_PERCENT = 25\n\n/** 适应窗口时允许的最小缩放百分比(可低于交互缩放下限,保证超大纸张也能整版容纳) */\nexport const FIT_SCALE_MIN_PERCENT = 5\n\n/** 将缩放百分比钳制到允许范围:仅保留下限,放大不设上限 */\nexport function clampScalePercent(percent: number): number {\n return Math.max(MIN_SCALE_PERCENT, percent)\n}\n\n/**\n * 滚轮缩放:乘性步进(默认 ×1.1 / ÷1.1),大倍数下仍保持平滑手感,\n * 返回取整后的百分比,避免浮点累加产生脏显示(如 110.00000001)\n * @param percent 当前缩放百分比\n * @param direction 1 放大,-1 缩小\n */\nexport function nextWheelScale(percent: number, direction: 1 | -1, factor = 1.1): number {\n const next = direction > 0 ? percent * factor : percent / factor\n return clampScalePercent(Math.round(next))\n}\n\n/** 计算适应窗口的缩放百分比,允许小于交互缩放下限,保证整版纸张可见 */\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.max(FIT_SCALE_MIN_PERCENT, 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 showRuler = ref(true)\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, showRuler, 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 <button\n class=\"help-button\"\n title=\"帮助文档\"\n @click=\"$emit('click')\"\n >\n <span class=\"help-icon\">?</span>\n </button>\n</template>\n\n<script setup lang=\"ts\">\ndefineEmits<{\n click: []\n}>()\n</script>\n\n<style scoped>\n.help-button {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: none;\n border-radius: 4px;\n background: transparent;\n cursor: pointer;\n transition: background-color 0.15s;\n}\n\n.help-button:hover {\n background: var(--pd-sidebar-hover, #f0f3f9);\n}\n\n.help-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n border-radius: 50%;\n background: var(--pd-accent, #165DFF);\n color: white;\n font-size: 12px;\n font-weight: 600;\n line-height: 1;\n}\n</style>\n","<template>\n <div class=\"designer-toolbar\">\n <!-- 文件 -->\n <div class=\"tb-group\">\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')\" data-tip=\"撤销\">↶</button>\n <button class=\"tb-btn tb-icon\" :disabled=\"!canRedo\" @click=\"$emit('redo')\" data-tip=\"重做\">↷</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')\" data-tip=\"置顶\">⤒</button>\n <button class=\"tb-btn tb-icon\" @click=\"$emit('move-layer', 'up')\" data-tip=\"上移一层\">↑</button>\n <button class=\"tb-btn tb-icon\" @click=\"$emit('move-layer', 'down')\" data-tip=\"下移一层\">↓</button>\n <button class=\"tb-btn tb-icon\" @click=\"$emit('move-layer', 'bottom')\" data-tip=\"置底\">⤓</button>\n </div>\n <!-- 视图 -->\n <div class=\"tb-group\">\n <button class=\"tb-btn\" :class=\"{ on: showRuler }\" data-tip=\"显示/隐藏标尺\" @click=\"$emit('toggle-ruler')\">\n <span class=\"dot\" /> 标尺\n </button>\n <button class=\"tb-btn\" :class=\"{ on: showGrid }\" data-tip=\"显示/隐藏网格背景\" @click=\"$emit('toggle-grid')\">\n <span class=\"dot\" /> 网格\n </button>\n <button class=\"tb-btn\" :class=\"{ on: showTableGhostBorder }\" data-tip=\"显示/隐藏无边框表格的虚拟虚线\" @click=\"$emit('toggle-table-ghost-border')\">\n <span class=\"dot\" /> 虚框\n </button>\n <button class=\"tb-btn\" :class=\"{ on: snapToGrid }\" data-tip=\"开启/关闭元素吸附到网格\" @click=\"$emit('toggle-snap')\">\n <span class=\"dot\" /> 吸附\n </button>\n <button class=\"tb-btn tb-icon\" @click=\"$emit('fit-window')\" data-tip=\"适应窗口\">⤢</button>\n <button class=\"tb-btn tb-icon\" @click=\"$emit('zoom', -10)\" data-tip=\"缩小\">−</button>\n <span class=\"tb-zoom\">{{ scale }}%</span>\n <button class=\"tb-btn tb-icon\" @click=\"$emit('zoom', 10)\" data-tip=\"放大\">+</button>\n </div>\n <!-- 操作 -->\n <div class=\"tb-spacer\" />\n <div class=\"tb-group\" v-if=\"showHelp\">\n <HelpButton @click=\"$emit('help')\" />\n </div>\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\">\nimport HelpButton from './HelpButton.vue'\n\nconst scale = defineModel<number>('scale', { default: 100 })\n\nwithDefaults(defineProps<{\n isEdit?: boolean\n canUndo?: boolean\n canRedo?: boolean\n hasMultiSelection?: boolean\n hasSelection?: boolean\n showRuler?: boolean\n showGrid?: boolean\n snapToGrid?: boolean\n showTableGhostBorder?: boolean\n selectedElementHasGroup?: boolean\n overlayVisible?: boolean\n /** 是否展示「加载默认布局」按钮(宿主注入 loadDefaultTemplate 时由 PrintDesigner 开启) */\n showLoadDefault?: boolean\n /** 是否展示帮助入口(工具栏帮助按钮);默认开启,传 false 关闭 */\n showHelp?: boolean\n}>(), {\n showRuler: true,\n showHelp: true,\n})\n\ndefineEmits<{\n preview: []\n save: []\n 'load-default': []\n undo: []\n redo: []\n align: [mode: string]\n 'move-layer': [direction: string]\n 'toggle-ruler': []\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 help: []\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: 100;\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-btn[data-tip] {\n position: relative;\n}\n.tb-btn[data-tip]::after {\n content: attr(data-tip);\n position: absolute;\n bottom: -32px;\n left: 50%;\n transform: translateX(-50%);\n padding: 4px 8px;\n font-size: 12px;\n color: #fff;\n background: rgba(30, 35, 48, .88);\n border-radius: 4px;\n white-space: nowrap;\n opacity: 0;\n pointer-events: none;\n transition: opacity .15s ease;\n z-index: 100;\n}\n.tb-btn[data-tip]:hover::after {\n opacity: 1;\n}\n.tb-btn:disabled[data-tip]::after {\n display: none;\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","// 标尺刻度纯函数:步长选择与可见范围刻度生成\n\n/** 视口固定尺条厚度(px),CanvasArea 布局与左上角块共用 */\nexport const RULER_THICKNESS = 22\n\nexport interface RulerTick {\n /** 刻度在纸面坐标系上的位置(mm,可为负,表示纸张原点之外) */\n mm: number\n /** 是否为主刻度(带数字标签) */\n major: boolean\n label?: string\n}\n\n/** 漂亮数步长序列:1/2/5 × 10^n,单位 mm */\nconst STEP_SEQUENCE = [1, 2, 5, 10, 20, 50, 100, 200, 500, 1000] as const\n\n/**\n * 按缩放选择主刻度步长(mm):取漂亮数序列中使屏幕间距\n * 不小于 targetPx 的最小步长,保证任意缩放下标签不重叠\n * @param scale 画布缩放比例(1 = 100%)\n * @param targetPx 主刻度之间的目标屏幕间距(px)\n */\nexport function chooseMajorStepMM(scale: number, targetPx = 64): number {\n const pxPerMM = scale * (96 / 25.4)\n for (const step of STEP_SEQUENCE) {\n if (step * pxPerMM >= targetPx) return step\n }\n return STEP_SEQUENCE[STEP_SEQUENCE.length - 1]\n}\n\n/**\n * 次刻度步长:5 系(5/50/500…)五等分、2 系(2/20/200…)二等分、\n * 10 的幂从 10mm 起五等分(10→2mm、100→20mm),1mm 时无次刻度\n */\nexport function minorStepMM(majorStepMM: number): number | null {\n const exp = Math.floor(Math.log10(majorStepMM) + 1e-9)\n const base = majorStepMM / 10 ** exp // 归一化到 1 / 2 / 5\n if (base === 5 || (base === 1 && majorStepMM >= 10)) return majorStepMM / 5\n if (base === 2) return majorStepMM / 2\n return null\n}\n\n/** 消除浮点误差,保留到 0.001mm */\nfunction roundMM(mm: number): number {\n return Math.round(mm * 1000) / 1000\n}\n\n/**\n * 生成可见毫米范围内的全部刻度(升序):\n * 从首个对齐的次刻度开始,主刻度带数字标签\n * @param startMM 可见范围起点(纸面坐标,可为负)\n * @param endMM 可见范围终点\n * @param majorStepMM 主刻度步长(由 chooseMajorStepMM 选出)\n */\nexport function buildRulerTicks(\n startMM: number,\n endMM: number,\n majorStepMM: number,\n): RulerTick[] {\n if (endMM < startMM || majorStepMM <= 0) return []\n const minor = minorStepMM(majorStepMM)\n const fine = minor ?? majorStepMM\n const first = Math.ceil(startMM / fine - 1e-9) * fine\n const lastIndex = Math.floor((endMM - first) / fine + 1e-9)\n const ticks: RulerTick[] = []\n for (let i = 0; i <= lastIndex; i++) {\n const mm = roundMM(first + i * fine)\n const isMajor = Math.abs(mm / majorStepMM - Math.round(mm / majorStepMM)) < 1e-6\n if (isMajor) {\n ticks.push({ mm, major: true, label: String(mm) })\n } else {\n ticks.push({ mm, major: false })\n }\n }\n return ticks\n}\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","<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\" :style=\"svgStyle\"></svg>\n <img v-if=\"cellType === 'qrcode' && dataUrl\" :src=\"dataUrl\" alt=\"qrcode\" :style=\"imgStyle\" />\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, computed, 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 fit?: string\n maxWidth?: number\n maxHeight?: number\n}>()\n\nconst barcodeSvg = ref<SVGSVGElement | null>(null)\nconst svgOk = ref(false)\nconst dataUrl = ref('')\n\nconst svgStyle = computed(() => ({\n objectFit: (props.fit || 'contain') as any,\n maxWidth: props.maxWidth ? `${props.maxWidth}mm` : '100%',\n maxHeight: props.maxHeight ? `${props.maxHeight}mm` : '100%',\n}))\n\nconst imgStyle = computed(() => ({\n objectFit: (props.fit || 'contain') as any,\n maxWidth: props.maxWidth ? `${props.maxWidth}mm` : '100%',\n maxHeight: props.maxHeight ? `${props.maxHeight}mm` : '100%',\n}))\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","<!-- 表格单元格内图片渲染:设计态与预览态共用 -->\n<template>\n <div class=\"cell-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 { evaluateTemplate } from '../../utils/expression-eval'\nimport { DEFAULT_DEMO_DATA } from '../../utils/demo-data'\n\nconst props = defineProps<{\n value: string\n fit?: string\n maxWidth?: number\n maxHeight?: number\n designMode?: boolean\n data?: Record<string, any>[]\n}>()\n\nconst imageSrc = computed(() => {\n const raw = props.value || ''\n if (!raw) return ''\n \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 \n return raw\n})\n\n// 加载失败兜底\nconst hasError = ref(false)\nfunction onError() {\n hasError.value = true\n}\n\n// src 变化时重置错误态\nwatch(imageSrc, () => {\n hasError.value = false\n})\n\nconst imgStyle = computed(() => ({\n objectFit: (props.fit || 'contain') as any,\n maxWidth: props.maxWidth ? `${props.maxWidth}mm` : '100%',\n maxHeight: props.maxHeight ? `${props.maxHeight}mm` : '100%',\n}))\n</script>\n\n<style scoped>\n.cell-image {\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n overflow: hidden;\n}\n.cell-image img {\n max-width: 100%;\n max-height: 100%;\n display: block;\n}\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>","<!-- 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 :fit=\"cell.fit\"\n :max-width=\"cell.maxWidth\"\n :max-height=\"cell.maxHeight\"\n />\n <CellImage\n v-else-if=\"cell.cellType === 'image'\"\n :value=\"cell.formatter || ''\"\n :fit=\"cell.fit\"\n :max-width=\"cell.maxWidth\"\n :max-height=\"cell.maxHeight\"\n :design-mode=\"designMode\"\n :data=\"imageData\"\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=\"colResizeEnabled\" class=\"col-resize-layer\">\n <div\n v-for=\"i in colResizeBoundaries\"\n :key=\"i\"\n class=\"col-resize-handle\"\n role=\"separator\"\n :aria-label=\"'列宽手柄' + i\"\n :class=\"{ dragging: colResizeBoundary === i }\"\n :style=\"{ left: colBoundaryLeftMm(i) + 'mm' }\"\n @mousedown.stop.prevent=\"onColResizeStart(i, $event)\"\n />\n </div>\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, onUnmounted, 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, clampResizedColumnWidth,\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 CellImage from './CellImage.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 /** 画布缩放倍率(用于列宽拖拽 px→mm 换算) */\n scale?: number\n /** 打印数据(用于运行态图片等动态内容) */\n data?: Record<string, any>[]\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\n// 添加图片数据处理\nconst imageData = computed(() => {\n // 运行态:使用打印数据\n if (props.data) {\n return props.data\n }\n // 设计态:使用 demo 数据\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\n// ─── 列宽拖拽 ───\n// 设计态选中且未锁定即渲染列边界手柄:1..n-1 为内部列边界(= 第 i 列右边缘),\n// 拖拽时调整其左侧第 i-1 列宽,使边界跟随光标移动;n 为最后一列右边界,\n// 拖拽时调整末列宽(右拖增宽、左拖缩窄)。拖拽期间实时回写列宽,\n// mouseup 时同步元素尺寸并记一次历史(与右键菜单结构操作一致)。\nconst colResizeEnabled = computed(\n () => props.designMode && !!props.isSelected && !props.element.options.locked && colWidths.value.length >= 1,\n)\n/** 列边界索引(1..n),n 为最后一列右边界 */\nconst colResizeBoundaries = computed<number[]>(() =>\n Array.from({ length: colWidths.value.length }, (_, k) => k + 1),\n)\n/** 边界 i 的水平位置(mm)= 前 i 列宽度和;i=n 时即表格右边界 */\nfunction colBoundaryLeftMm(i: number): number {\n return colWidths.value.slice(0, i).reduce((s, w) => s + w, 0)\n}\n\nconst colResizeBoundary = ref<number | null>(null)\nlet resizeStartX = 0\nlet resizeStartWidth = 0\n\n/** 拖拽边界 i:始终调整其左侧第 i-1 列(即第 i 列)宽 = startWidth + deltaMm,\n * 让边界线跟随光标移动。clampResizedColumnWidth 负责最小列宽与总宽上限钳制。 */\nfunction onColResizeStart(i: number, e: MouseEvent) {\n if (!colResizeEnabled.value) return\n colResizeBoundary.value = i\n resizeStartX = e.clientX\n resizeStartWidth = colWidths.value[i - 1]!\n document.addEventListener('mousemove', onColResizeMove)\n document.addEventListener('mouseup', onColResizeEnd)\n}\n\nfunction onColResizeMove(e: MouseEvent) {\n if (colResizeBoundary.value === null) return\n const scale = props.scale || 1\n // 鼠标位移 px → mm:画布 transform:scale(props.scale) 下 1mm ≈ PX_PER_MM*scale px\n const deltaMm = (e.clientX - resizeStartX) / (scale * PX_PER_MM)\n const colIndex = colResizeBoundary.value - 1\n const widths = props.element.options.tableColWidths!\n widths[colIndex] = clampResizedColumnWidth(\n widths, colIndex, resizeStartWidth + deltaMm, editCtx.maxTableWidth.value,\n )\n // 实时同步元素 width = 列宽和:避免 table-layout:fixed 下表格 CSS width(100%)\n // 与列宽和失配导致浏览器按比例拉伸列,进而使边界线与右侧内容偏离光标。\n syncElementSize()\n}\n\nfunction onColResizeEnd() {\n document.removeEventListener('mousemove', onColResizeMove)\n document.removeEventListener('mouseup', onColResizeEnd)\n if (colResizeBoundary.value === null) return\n colResizeBoundary.value = null\n syncElementSize()\n editCtx.recordHistory()\n}\n\nonUnmounted(() => {\n document.removeEventListener('mousemove', onColResizeMove)\n document.removeEventListener('mouseup', onColResizeEnd)\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.col-resize-layer {\n position: absolute;\n inset: 0;\n pointer-events: none;\n z-index: 3;\n}\n.col-resize-handle {\n position: absolute;\n top: 0;\n bottom: 0;\n width: 6px;\n transform: translateX(-50%);\n cursor: col-resize;\n pointer-events: auto;\n}\n/* 手柄 hover/拖拽时显示主题色竖线,提示列边界位置 */\n.col-resize-handle::after {\n content: '';\n position: absolute;\n top: 0;\n bottom: 0;\n left: 50%;\n border-left: 1px solid transparent;\n}\n.col-resize-handle:hover::after,\n.col-resize-handle.dragging::after {\n border-left-color: var(--pd-accent, #165DFF);\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>\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 { mmToPx } from '../../utils/units'\n\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 contentComponent = computed(() => componentMap[props.element.printElementType.type])\n\n/** 仅表格元素需要虚拟虚线开关,避免其它元素根节点出现无关 attribute */\nconst contentAttrs = computed(() =>\n props.element.printElementType.type === 'table'\n ? { showTableGhostBorder: props.showTableGhostBorder, scale: props.scale }\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) * mmToPx(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) * mmToPx(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.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","// 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=\"paper-wrapper\"\n :style=\"wrapperStyle\"\n >\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 <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', '--guide-hit': guideHitPx }\n : { top: g.position + 'mm', left: '0', width: paperWidthMM + 'mm', '--guide-hit': guideHitPx }\"\n @mousedown.prevent.stop=\"onGuideDown($event, g)\"\n @dblclick.prevent.stop=\"g.id && emit('guide-remove', g.id)\"\n />\n </div>\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 { mmToPx } from '../utils/units'\nimport BaseElement from './elements/BaseElement.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 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 '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/** 参考线交互热区:换算到缩放前坐标,保证任意缩放比例下屏幕热区恒定 */\nconst guideHitPx = computed(() => `${8 / (props.scale || 1)}px`)\n\n/** wrapper 尺寸:缩放后的实际像素尺寸,让滚动容器正确感知内容大小 */\nconst wrapperStyle = computed(() => {\n const s = props.scale || 1\n const widthPx = mmToPx(paperWidthMM.value) * s\n const heightPx = mmToPx(paperHeightMM.value) * s\n return {\n width: widthPx + 'px',\n height: heightPx + 'px',\n position: 'relative' as const,\n }\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 const maxPosition = g.type === 'vertical' ? paperWidthMM.value : paperHeightMM.value\n const nextPosition = Math.min(Math.max(startPt + delta, 0), maxPosition)\n emit('guide-move', g.id!, nextPosition)\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: props.templateData.pageBackground || '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 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 boxSizing: 'border-box' as const,\n minHeight: paperHeightMM.value + 'mm',\n }\n})\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, '&').replace(/</g, '<').replace(/>/g, '>')\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/* wrapper:承载缩放后的实际尺寸,让滚动容器正确感知内容大小 */\n.paper-wrapper {\n /* 仅承载缩放后的布局尺寸(宽高 = 纸张尺寸 × scale,见 wrapperStyle)。\n 纸张固定以左上角为原点缩放(transform-origin: 0 0),wrapper 内不能再居中,\n 否则缩小时 flex 压缩布局宽度会使视觉宽度变为 W·s²、放大时纸张向右偏移;\n 水平居中统一由外层 .canvas-scroll 的 align-items: center 负责。 */\n display: block;\n}\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.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::before {\n content: '';\n position: absolute;\n pointer-events: auto;\n}\n.manual-guide.guide-vertical::before {\n top: 0;\n bottom: 0;\n left: 50%;\n width: var(--guide-hit, 8px);\n transform: translateX(-50%);\n}\n.manual-guide.guide-horizontal::before {\n left: 0;\n right: 0;\n top: 50%;\n height: var(--guide-hit, 8px);\n transform: translateY(-50%);\n}\n.manual-guide:hover { border-color: #EF4444 !important; }\n</style>\n","<!--\n 视口固定式标尺(单条)\n - 尺条固定在设计区边缘,不随纸张缩放/滚动;刻度随滚动平移、随缩放变密度\n - 横尺产生垂直参考线,竖尺产生水平参考线(与历史语义一致)\n - 在尺上按下并移动显示预览线,松开即生成参考线;主坐标超出尺长则取消\n-->\n<template>\n <canvas\n ref=\"canvasRef\"\n class=\"pd-ruler\"\n :class=\"`is-${orientation}`\"\n :style=\"cssSize\"\n @mousedown=\"onDown\"\n @mousemove=\"onHoverMove\"\n @mouseleave=\"onHoverLeave\"\n />\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, watch, onMounted, onBeforeUnmount } from 'vue'\nimport { mmToPx } from '../utils/units'\nimport {\n buildRulerTicks,\n chooseMajorStepMM,\n RULER_THICKNESS,\n} from '../utils/ruler'\n\nconst props = defineProps<{\n orientation: 'horizontal' | 'vertical'\n /** 尺条可见长度(屏幕 px,不随缩放变化) */\n viewportPx: number\n /** 纸张 0mm 点相对尺条起点的屏幕偏移(滚动时由父级实时更新) */\n originPx: number\n /** 纸张该方向长度(mm),用于边界标记与参考线落点限制 */\n paperLengthMM: number\n scale: number\n /** 鼠标在尺条轴向上的位置(屏幕 px),由画布 mousemove 转发 */\n cursorPx?: number | null\n}>()\n\nconst emit = defineEmits<{\n 'add-guide': [type: 'vertical' | 'horizontal', positionMm: number]\n /** 拖拽参考线过程中的虚线预览,null 表示隐藏 */\n 'guide-dragging': [mm: number | null]\n}>()\n\nconst horizontal = computed(() => props.orientation === 'horizontal')\n/** 横尺界定横向位置,产生的是垂直参考线 */\nconst guideType = computed<'vertical' | 'horizontal'>(() =>\n horizontal.value ? 'vertical' : 'horizontal',\n)\n\nconst canvasRef = ref<HTMLCanvasElement | null>(null)\n/** 鼠标悬停在尺条上的轴向位置(优先于外部传入的 cursorPx) */\nconst hoverPx = ref<number | null>(null)\nconst effectiveCursorPx = computed(() => hoverPx.value ?? props.cursorPx ?? null)\n\nconst cssSize = computed(() => {\n if (horizontal.value) {\n return { width: props.viewportPx + 'px', height: RULER_THICKNESS + 'px' }\n }\n return { width: RULER_THICKNESS + 'px', height: props.viewportPx + 'px' }\n})\n\nlet rafId = 0\nfunction scheduleDraw() {\n if (rafId) return\n rafId = requestAnimationFrame(() => {\n rafId = 0\n draw()\n })\n}\n\nfunction draw() {\n const canvas = canvasRef.value\n if (!canvas) return\n const ctx = canvas.getContext('2d')\n // happy-dom 等无 canvas 环境直接跳过绘制\n if (!ctx) return\n\n const dpr = window.devicePixelRatio || 1\n const length = Math.max(0, Math.round(props.viewportPx))\n const thickness = RULER_THICKNESS\n canvas.width = (horizontal.value ? length : thickness) * dpr\n canvas.height = (horizontal.value ? thickness : length) * dpr\n ctx.setTransform(dpr, 0, 0, dpr, 0, 0)\n\n const style = getComputedStyle(canvas)\n const bg = style.getPropertyValue('--pd-ruler-bg').trim() || '#F8F9FC'\n const fg = style.getPropertyValue('--pd-ruler').trim() || '#9AA1AF'\n const accent = style.getPropertyValue('--pd-accent').trim() || '#165DFF'\n\n // 背景\n ctx.fillStyle = bg\n ctx.fillRect(0, 0, horizontal.value ? length : thickness, horizontal.value ? thickness : length)\n\n const s = props.scale > 0 ? props.scale : 1\n const pxPerMM = mmToPx(1) * s\n if (pxPerMM <= 0) return\n\n // 可见毫米范围(含纸张外区域)\n const startMM = -props.originPx / pxPerMM\n const endMM = (length - props.originPx) / pxPerMM\n const majorStep = chooseMajorStepMM(s)\n const ticks = buildRulerTicks(startMM, endMM, majorStep)\n\n // 纸外刻度淡化处理:先画纸外,再画纸内\n drawTicks(ctx, ticks, pxPerMM, fg, true)\n drawTicks(ctx, ticks, pxPerMM, fg, false)\n\n // 纸张 0 / 末端边界标记\n drawPaperEdge(ctx, 0, accent)\n drawPaperEdge(ctx, props.paperLengthMM, accent)\n\n // 鼠标位置指示线\n const cursor = effectiveCursorPx.value\n if (cursor !== null && cursor >= 0 && cursor <= length) {\n ctx.strokeStyle = accent\n ctx.lineWidth = 1.5\n ctx.beginPath()\n if (horizontal.value) {\n const x = Math.round(cursor) + 0.5\n ctx.moveTo(x, 0)\n ctx.lineTo(x, thickness)\n } else {\n const y = Math.round(cursor) + 0.5\n ctx.moveTo(0, y)\n ctx.lineTo(thickness, y)\n }\n ctx.stroke()\n }\n}\n\nfunction drawTicks(\n ctx: CanvasRenderingContext2D,\n ticks: ReturnType<typeof buildRulerTicks>,\n pxPerMM: number,\n fg: string,\n outside: boolean,\n) {\n const thickness = RULER_THICKNESS\n ctx.strokeStyle = fg\n ctx.fillStyle = fg\n ctx.globalAlpha = outside ? 0.32 : 1\n ctx.lineWidth = 1\n ctx.font = '9px ui-monospace, Menlo, monospace'\n ctx.textBaseline = 'top'\n\n for (const tick of ticks) {\n const isOutside = tick.mm < 0 || tick.mm > props.paperLengthMM\n if (isOutside !== outside) continue\n const pos = Math.round(props.originPx + tick.mm * pxPerMM) + 0.5\n const len = tick.major ? 8 : 4\n ctx.beginPath()\n if (horizontal.value) {\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.value) {\n ctx.fillText(tick.label, pos + 2, 11)\n } else {\n ctx.save()\n // 旋转 -90° 后,文字沿屏幕 +x 方向铺开(9px 字体约占 9px)。\n // x=11 时文字落在 11..20px,完整处于 22px 尺宽内,\n // 且与横尺标签(y=11)对称;此前 x=18 会延伸到 27px 被裁切。\n ctx.translate(11, pos + 2)\n ctx.rotate(-Math.PI / 2)\n ctx.fillText(tick.label, 0, 0)\n ctx.restore()\n }\n }\n }\n ctx.globalAlpha = 1\n}\n\nfunction drawPaperEdge(ctx: CanvasRenderingContext2D, mm: number, color: string) {\n const pxPerMM = mmToPx(1) * (props.scale > 0 ? props.scale : 1)\n const pos = Math.round(props.originPx + mm * pxPerMM) + 0.5\n if (pos <= 0 || pos >= props.viewportPx) return\n ctx.strokeStyle = color\n ctx.globalAlpha = 0.55\n ctx.lineWidth = 1\n ctx.beginPath()\n if (horizontal.value) {\n ctx.moveTo(pos, 0)\n ctx.lineTo(pos, RULER_THICKNESS)\n } else {\n ctx.moveTo(0, pos)\n ctx.lineTo(RULER_THICKNESS, pos)\n }\n ctx.stroke()\n ctx.globalAlpha = 1\n}\n\nwatch(\n () => [props.viewportPx, props.originPx, props.paperLengthMM, props.scale, props.cursorPx, props.orientation],\n scheduleDraw,\n)\nonMounted(scheduleDraw)\nonBeforeUnmount(() => { if (rafId) cancelAnimationFrame(rafId) })\n\n// ─── 拖出参考线 ───\nlet dragging = false\n\nfunction axialFromEvent(e: MouseEvent): number | null {\n const canvas = canvasRef.value\n if (!canvas) return null\n const rect = canvas.getBoundingClientRect()\n const along = horizontal.value ? e.clientX - rect.left : e.clientY - rect.top\n // 主坐标超出尺条长度(含两端)即视为取消;横向/纵向另一方向不限制,允许拖入纸面\n if (along < 0 || along > props.viewportPx) return null\n const pxPerMM = mmToPx(1) * (props.scale > 0 ? props.scale : 1)\n return (along - props.originPx) / pxPerMM\n}\n\nfunction onDown(e: MouseEvent) {\n dragging = true\n e.preventDefault()\n window.addEventListener('mousemove', onWinMove)\n window.addEventListener('mouseup', onWinUp)\n updateDragPreview(e)\n}\n\nfunction onHoverMove(e: MouseEvent) {\n const canvas = canvasRef.value\n if (!canvas) return\n const rect = canvas.getBoundingClientRect()\n hoverPx.value = horizontal.value ? e.clientX - rect.left : e.clientY - rect.top\n scheduleDraw()\n}\n\nfunction onHoverLeave() {\n hoverPx.value = null\n scheduleDraw()\n}\n\nfunction updateDragPreview(e: MouseEvent) {\n const mm = axialFromEvent(e)\n emit('guide-dragging', mm)\n}\n\nfunction onWinMove(e: MouseEvent) {\n if (!dragging) return\n updateDragPreview(e)\n}\n\nfunction onWinUp(e: MouseEvent) {\n if (!dragging) return\n dragging = false\n window.removeEventListener('mousemove', onWinMove)\n window.removeEventListener('mouseup', onWinUp)\n const mm = axialFromEvent(e)\n if (mm !== null && mm >= 0 && mm <= props.paperLengthMM) {\n emit('add-guide', guideType.value, mm)\n }\n emit('guide-dragging', null)\n}\n\nonBeforeUnmount(() => {\n window.removeEventListener('mousemove', onWinMove)\n window.removeEventListener('mouseup', onWinUp)\n})\n</script>\n\n<style scoped>\n.pd-ruler {\n position: absolute;\n display: block;\n pointer-events: auto;\n cursor: crosshair;\n z-index: 1;\n background: var(--pd-ruler-bg, #f8f9fc);\n}\n.pd-ruler.is-horizontal {\n box-shadow: 0 1px 0 var(--pd-border-soft, #e9ecf2);\n}\n.pd-ruler.is-vertical {\n box-shadow: 1px 0 0 var(--pd-border-soft, #e9ecf2);\n}\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 @scroll=\"onScroll\"\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 @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 v-if=\"showRuler\" class=\"ruler-overlay\" :style=\"overlayStyle\">\n <div class=\"ruler-corner\" />\n <Ruler\n orientation=\"horizontal\"\n :viewport-px=\"rulerGeom.viewW\"\n :origin-px=\"rulerGeom.originX\"\n :paper-length-m-m=\"paperWidthMM\"\n :scale=\"rulerGeom.paperScale\"\n :cursor-px=\"rulerCursor.x\"\n @add-guide=\"(t: 'vertical' | 'horizontal', p: number) => emit('add-guide', t, p)\"\n @guide-dragging=\"(mm: number | null) => onGuideDragging('vertical', mm)\"\n />\n <Ruler\n orientation=\"vertical\"\n :viewport-px=\"rulerGeom.viewH\"\n :origin-px=\"rulerGeom.originY\"\n :paper-length-m-m=\"paperHeightMM\"\n :scale=\"rulerGeom.paperScale\"\n :cursor-px=\"rulerCursor.y\"\n @add-guide=\"(t: 'vertical' | 'horizontal', p: number) => emit('add-guide', t, p)\"\n @guide-dragging=\"(mm: number | null) => onGuideDragging('horizontal', mm)\"\n />\n </div>\n <!-- 从标尺拖出参考线时的预览虚线(fixed 定位,不能放进带 transform 的 overlay) -->\n <div\n v-if=\"guidePreview\"\n class=\"ruler-guide-preview\"\n :class=\"`guide-${guidePreview.type}`\"\n :style=\"guidePreviewStyle\"\n />\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, computed, watch, nextTick, onMounted, onBeforeUnmount } from 'vue'\nimport type { RuntimeElement, TemplateData, AlignLine } from '../types'\nimport { pxToMm, mmToPx } from '../utils/units'\nimport { nextWheelScale, FIT_SCALE_MIN_PERCENT } from '../utils/scale'\nimport { getPaperDimensions } from '../utils/default-config'\nimport { RULER_THICKNESS } from '../utils/ruler'\nimport CanvasPaper from './CanvasPaper.vue'\nimport Ruler from './Ruler.vue'\n\nconst props = withDefaults(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 showRuler?: boolean\n}>(), {\n showRuler: true,\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// ─── 视口固定标尺:纸张几何测量与滚动/缩放同步 ───\nconst paperWidthMM = computed(() => getPaperDimensions(props.templateData).width)\nconst paperHeightMM = computed(() => getPaperDimensions(props.templateData).height)\n\n/** 纸张原点相对各尺条起点的屏幕偏移 + 尺条可见长度 */\nconst rulerGeom = reactive({ originX: 0, originY: 0, viewW: 0, viewH: 0, paperScale: 1 })\n/** 鼠标相对各尺条起点的屏幕位置,驱动尺上指示线 */\nconst rulerCursor = reactive<{ x: number | null; y: number | null }>({ x: null, y: null })\n/** 滚动偏移:绝对定位的标尺层会随滚动内容移动,用同向 transform 补偿以保持视口固定 */\nconst scrollPos = reactive({ x: 0, y: 0 })\nconst overlayStyle = computed(() => ({\n transform: `translate(${scrollPos.x}px, ${scrollPos.y}px)`,\n}))\n\nfunction measureRuler() {\n const area = rootRef.value\n // 读取纸张本体而非 wrapper:缩放时 wrapper 尺寸立即变为目标值,\n // 纸张本体有 150ms transform 过渡,标尺需要跟随实时视觉位置与比例。\n const paper = area?.querySelector('.hiprint-printPaper') as HTMLElement | null\n if (!area || !paper) return\n const ar = area.getBoundingClientRect()\n const pr = paper.getBoundingClientRect()\n const targetScale = props.scale || 1\n const measuredScale = pr.width / mmToPx(paperWidthMM.value)\n // 过渡终点附近消除子像素误差,静止时保持与业务 scale 完全一致\n rulerGeom.paperScale = Math.abs(measuredScale - targetScale) < 0.002\n ? targetScale\n : measuredScale\n rulerGeom.originX = pr.left - ar.left - RULER_THICKNESS\n rulerGeom.originY = pr.top - ar.top - RULER_THICKNESS\n rulerGeom.viewW = area.clientWidth - RULER_THICKNESS\n rulerGeom.viewH = area.clientHeight - RULER_THICKNESS\n}\n\nfunction onScroll() {\n scrollPos.x = rootRef.value?.scrollLeft ?? 0\n scrollPos.y = rootRef.value?.scrollTop ?? 0\n measureRuler()\n}\n\nlet resizeObserver: ResizeObserver | null = null\n/** 缩放切换后纸张有 150ms CSS 过渡,期间持续重测,刻度才不会跳变 */\nlet scaleMeasureRaf = 0\nfunction startScaleMeasureLoop() {\n cancelAnimationFrame(scaleMeasureRaf)\n const endAt = performance.now() + 220\n const loop = () => {\n measureRuler()\n if (performance.now() < endAt) scaleMeasureRaf = requestAnimationFrame(loop)\n }\n scaleMeasureRaf = requestAnimationFrame(loop)\n}\n\n/** 从标尺拖出参考线的预览态(纸面 mm 坐标) */\nconst guidePreview = ref<{ type: 'vertical' | 'horizontal'; mm: number } | null>(null)\nfunction onGuideDragging(type: 'vertical' | 'horizontal', mm: number | null) {\n guidePreview.value = mm === null ? null : { type, mm }\n}\nconst guidePreviewStyle = computed(() => {\n const g = guidePreview.value\n const paper = rootRef.value?.querySelector('.hiprint-printPaper') as HTMLElement | null\n if (!g || !paper) return {}\n // position: fixed,直接采用视口坐标(与框选选框一致)\n const pr = paper.getBoundingClientRect()\n const liveScale = pr.width / mmToPx(paperWidthMM.value)\n const along = mmToPx(g.mm) * (liveScale > 0 ? liveScale : (props.scale || 1))\n if (g.type === 'vertical') {\n return { left: pr.left + along + 'px', top: pr.top + 'px', height: pr.height + 'px' }\n }\n return { left: pr.left + 'px', top: pr.top + along + 'px', width: pr.width + 'px' }\n})\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 area = rootRef.value\n const paper = area?.querySelector('.hiprint-printPaper') as HTMLElement | null\n if (!area || !paper) return\n const areaRect = area.getBoundingClientRect()\n rulerCursor.x = e.clientX - areaRect.left - RULER_THICKNESS\n rulerCursor.y = e.clientY - areaRect.top - RULER_THICKNESS\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() {\n emit('coordinate', null)\n rulerCursor.x = null\n rulerCursor.y = null\n}\n\n/** Ctrl/Cmd+滚轮缩放:以鼠标位置为缩放中心,缩放前后保持鼠标下的内容点不动 */\nfunction onWheel(e: WheelEvent) {\n if (!(e.ctrlKey || e.metaKey)) return\n e.preventDefault()\n // props.scale 为小数;统一在百分比整数域做乘性步进,\n // 取消放大上限,同时避免浮点累加产生脏显示\n const oldScale = props.scale || 1\n const oldPercent = Math.round(oldScale * 100)\n const newPercent = nextWheelScale(oldPercent, e.deltaY > 0 ? -1 : 1)\n if (newPercent === oldPercent) return\n const newScale = newPercent / 100\n\n const container = rootRef.value\n // 记录鼠标下的内容点(相对滚动内容原点)。容器存在非对称 padding,\n // 换算时必须扣除,否则每次缩放锚点会漂移 pad*(ratio-1)\n let anchor: { x: number; y: number; ratio: number; mouseX: number; mouseY: number } | null = null\n if (container) {\n const rect = container.getBoundingClientRect()\n const cs = getComputedStyle(container)\n const padX = parseFloat(cs.paddingLeft) || 0\n const padY = parseFloat(cs.paddingTop) || 0\n anchor = {\n x: container.scrollLeft + (e.clientX - rect.left) - padX,\n y: container.scrollTop + (e.clientY - rect.top) - padY,\n ratio: newScale / oldScale,\n mouseX: e.clientX - rect.left,\n mouseY: e.clientY - rect.top,\n }\n }\n\n // 以百分比整数增量上报(父级 scale 为百分比)\n emit('zoom', newPercent - oldPercent)\n\n // 待新比例应用到 DOM 后再校正滚动位置:缩放前若该方向没有滚动条,\n // 提前写入 scrollTop/Left 会被浏览器钳制为 0,导致锚点失效\n if (container && anchor) {\n const a = anchor\n void nextTick(() => {\n const cs = getComputedStyle(container)\n const padX = parseFloat(cs.paddingLeft) || 0\n const padY = parseFloat(cs.paddingTop) || 0\n container.scrollLeft = a.x * a.ratio - a.mouseX + padX\n container.scrollTop = a.y * a.ratio - a.mouseY + padY\n })\n }\n}\n\n// ─── 适应窗口:一步到位(调用方已算好目标比例),以视口中心为锚点,\n// 与 Ctrl+滚轮同一管线;平滑动画由纸张 150ms transform 过渡自然产生 ───\nfunction fitToWindow(targetPercent: number) {\n const container = rootRef.value\n if (!container) return\n const target = Math.max(FIT_SCALE_MIN_PERCENT, Math.round(targetPercent))\n const cur = Math.round((props.scale || 1) * 100)\n if (target === cur) return\n\n // 锚点取视口几何中心(相对内容原点,扣除容器 padding),与 onWheel 换算一致\n const oldScale = props.scale || 1\n const newScale = target / 100\n const ratio = newScale / oldScale\n const cs = getComputedStyle(container)\n const padX = parseFloat(cs.paddingLeft) || 0\n const padY = parseFloat(cs.paddingTop) || 0\n const mouseX = container.clientWidth / 2\n const mouseY = container.clientHeight / 2\n const ax = container.scrollLeft + mouseX - padX\n const ay = container.scrollTop + mouseY - padY\n\n emit('zoom', target - cur)\n void nextTick(() => {\n const cs2 = getComputedStyle(container)\n const padX2 = parseFloat(cs2.paddingLeft) || 0\n const padY2 = parseFloat(cs2.paddingTop) || 0\n container.scrollLeft = ax * ratio - mouseX + padX2\n container.scrollTop = ay * ratio - mouseY + padY2\n })\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\nonMounted(() => {\n nextTick(measureRuler)\n if (rootRef.value && typeof ResizeObserver !== 'undefined') {\n resizeObserver = new ResizeObserver(measureRuler)\n resizeObserver.observe(rootRef.value)\n }\n})\n\nwatch(() => props.scale, startScaleMeasureLoop)\nwatch([paperWidthMM, paperHeightMM], () => nextTick(measureRuler))\n\n/** 适应窗口后将滚动位置归中。\n * 纸张有 150ms CSS transform 过渡,期间 scrollWidth/Height 持续变化,\n * 用多帧检测数值稳定后再设置居中,避免固定 setTimeout 落在过渡中间。 */\nfunction centerScroll() {\n const container = rootRef.value\n if (!container) return\n let stableFrames = 0\n let prevSW = 0, prevSH = 0\n const deadline = performance.now() + 800\n const loop = () => {\n const { scrollWidth: sw, scrollHeight: sh } = container\n if (sw === prevSW && sh === prevSH) {\n stableFrames++\n } else {\n stableFrames = 0\n }\n prevSW = sw; prevSH = sh\n if (stableFrames >= 2 || performance.now() > deadline) {\n const sw2 = container.scrollWidth, sh2 = container.scrollHeight\n const cw = container.clientWidth, ch = container.clientHeight\n container.scrollLeft = Math.max(0, (sw2 - cw) / 2)\n container.scrollTop = Math.max(0, (sh2 - ch) / 2)\n return\n }\n requestAnimationFrame(loop)\n }\n requestAnimationFrame(loop)\n}\n\ndefineExpose({ centerScroll, fitToWindow })\n\nonBeforeUnmount(() => {\n window.removeEventListener('mousemove', onMarqueeMove)\n window.removeEventListener('mouseup', onMarqueeUp)\n resizeObserver?.disconnect()\n cancelAnimationFrame(scaleMeasureRaf)\n})\n</script>\n\n<style scoped>\n.canvas-area {\n flex: 1;\n overflow: auto;\n /* flex + margin:auto:纸张在可视区内水平/垂直居中;内容超出容器时\n margin auto 自动退化为起点对齐,滚动条仍可达纸张两端 */\n display: flex;\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 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 /* 禁 dock 到容器的收缩,部件宽高始终以纸张真实尺寸为准 */\n flex: none;\n margin: auto;\n width: fit-content;\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\n/* ─── 视口固定标尺 ─── */\n.ruler-overlay {\n position: absolute;\n inset: 0;\n pointer-events: none;\n z-index: 60;\n}\n.ruler-corner {\n position: absolute;\n top: 0;\n left: 0;\n width: 22px;\n height: 22px;\n background: var(--pd-ruler-bg, #f8f9fc);\n box-shadow: 1px 1px 0 var(--pd-border-soft, #e9ecf2);\n z-index: 2;\n}\n.ruler-overlay :deep(.pd-ruler.is-horizontal) {\n top: 0;\n left: 22px;\n}\n.ruler-overlay :deep(.pd-ruler.is-vertical) {\n top: 22px;\n left: 0;\n}\n/* 拖出参考线的预览虚线 */\n.ruler-guide-preview {\n position: fixed;\n pointer-events: none;\n z-index: 9997;\n}\n.ruler-guide-preview.guide-vertical {\n width: 0;\n border-left: 1px dashed var(--pd-accent, #165dff);\n}\n.ruler-guide-preview.guide-horizontal {\n height: 0;\n border-top: 1px dashed var(--pd-accent, #165dff);\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 <div class=\"pd-stepper\">\n <button\n type=\"button\"\n class=\"pd-step-btn pd-step-minus\"\n :disabled=\"atMin\"\n title=\"减小\"\n aria-label=\"减小\"\n @click=\"stepBy(-1)\"\n >−</button>\n <input\n type=\"number\"\n class=\"pd-input pd-step-input\"\n :value=\"draft\"\n :placeholder=\"placeholder\"\n :min=\"min\"\n :max=\"max\"\n :step=\"step\"\n @input=\"onInput\"\n @change=\"commit\"\n @blur=\"commit\"\n @keydown.enter.prevent=\"($event.target as HTMLInputElement).blur()\"\n />\n <button\n type=\"button\"\n class=\"pd-step-btn pd-step-plus\"\n :disabled=\"atMax\"\n title=\"增大\"\n aria-label=\"增大\"\n @click=\"stepBy(1)\"\n >+</button>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\n\nconst props = withDefaults(defineProps<{\n /** 数值;undefined 表示未设置(继承默认),输入框显示空占位 */\n modelValue?: number\n min?: number\n max?: number\n /** 步进单位,默认 1(整数);小数步进时按小数位数保留精度 */\n step?: number\n /** 未设置(继承默认)时输入框的占位提示 */\n placeholder?: string\n}>(), {\n step: 1,\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: number | undefined]\n}>()\n\n/** 步进小数位数:由 step 推导(0.5→1 位,0.25→2 位,0.1→1 位,1→0 位) */\nconst precision = computed(() => {\n const s = String(props.step)\n const dot = s.indexOf('.')\n return dot === -1 ? 0 : s.length - dot - 1\n})\n\n/** 按 step 精度取整,规避浮点误差(0.30000000000000004 → 0.3) */\nfunction roundTo(v: number): number {\n if (!Number.isFinite(v)) return 0\n return Number(v.toFixed(precision.value))\n}\n\n/** 当前有效值:undefined 表示未设置(继承默认) */\nconst current = computed<number | undefined>(() => {\n const v = props.modelValue\n if (v === undefined || v === null || !Number.isFinite(v)) return undefined\n return roundTo(v)\n})\n\n/** 输入框草稿:输入过程中保留原文,失焦/回车后按精度规范化 */\nconst draft = ref(current.value === undefined ? '' : String(current.value))\nwatch(current, (v) => {\n draft.value = v === undefined ? '' : String(v)\n})\n\n/** 步进基准:未设置时从 min(无 min 则为 0)起步 */\nconst base = computed(() => {\n if (current.value !== undefined) return current.value\n return props.min !== undefined ? props.min : 0\n})\n\nconst atMin = computed(() => props.min !== undefined && base.value <= props.min)\nconst atMax = computed(() => props.max !== undefined && base.value >= props.max)\n\n/** 夹取到 [min, max],并按 step 精度取整 */\nfunction clamp(v: number): number {\n let next = roundTo(v)\n if (props.min !== undefined && next < props.min) next = props.min\n if (props.max !== undefined && next > props.max) next = props.max\n return next\n}\n\nfunction stepBy(dir: 1 | -1) {\n if ((dir < 0 && atMin.value) || (dir > 0 && atMax.value)) return\n const next = clamp(base.value + dir * props.step)\n draft.value = String(next)\n emit('update:modelValue', next)\n}\n\nfunction onInput(e: Event) {\n draft.value = (e.target as HTMLInputElement).value\n}\n\n/** 失焦/回车提交:解析草稿并按精度取整;空值回退为当前值(未设置则保持未设置) */\nfunction commit() {\n const raw = draft.value.trim()\n if (raw === '') {\n if (current.value !== undefined) {\n draft.value = String(current.value)\n }\n return\n }\n const num = Number(raw)\n if (!Number.isFinite(num)) {\n draft.value = current.value === undefined ? '' : String(current.value)\n return\n }\n const next = clamp(num)\n draft.value = String(next)\n // change 与 blur 会先后触发,仅当值真正变化时 emit,避免重复提交\n if (next !== current.value) {\n emit('update:modelValue', next)\n }\n}\n</script>\n\n<style scoped>\n.pd-stepper {\n display: flex;\n align-items: center;\n width: 100%;\n}\n.pd-step-btn {\n width: 26px;\n height: 26px;\n flex-shrink: 0;\n border: 1px solid var(--pd-border, #d9dde6);\n background: var(--pd-field-bg, #f4f6fa);\n color: var(--pd-text, #2a2e37);\n font-size: 14px;\n line-height: 1;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background .14s ease, border-color .14s ease, color .14s ease;\n}\n.pd-step-btn:hover:not(:disabled) {\n background: var(--pd-sidebar-hover, #f0f3f9);\n border-color: var(--pd-text-faint, #b4b9c4);\n}\n.pd-step-btn:disabled {\n opacity: 0.45;\n cursor: not-allowed;\n}\n.pd-step-minus {\n border-radius: 6px 0 0 6px;\n border-right: none;\n}\n.pd-step-plus {\n border-radius: 0 6px 6px 0;\n border-left: none;\n}\n.pd-step-input.pd-input {\n border-radius: 0;\n min-width: 0;\n flex: 1;\n text-align: center;\n -moz-appearance: textfield;\n}\n.pd-step-input.pd-input::-webkit-outer-spin-button,\n.pd-step-input.pd-input::-webkit-inner-spin-button {\n -webkit-appearance: none;\n margin: 0;\n}\n</style>\n","<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 <StepperInput v-model=\"element.options.left\"\n :min=\"0\" />\n </div>\n <div class=\"pd-field\" v-show=\"showItem('ps-top')\"><span class=\"pd-label\">Y</span>\n <StepperInput v-model=\"element.options.top\"\n :min=\"0\" />\n </div>\n <div class=\"pd-field\" v-show=\"showItem('ps-width')\"><span class=\"pd-label\">W</span>\n <StepperInput v-model=\"element.options.width\"\n :min=\"4\" />\n </div>\n <div class=\"pd-field\" v-show=\"showItem('ps-height')\"><span class=\"pd-label\">H</span>\n <StepperInput v-model=\"element.options.height\"\n :min=\"4\" />\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'\nimport StepperInput from './StepperInput.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 <StepperInput v-model=\"element.options.fontSize\"\n :min=\"8\"\n :max=\"72\" />\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 <StepperInput v-model=\"element.options.lineHeight\"\n :min=\"0\"\n :max=\"100\" />\n </div>\n <div class=\"pd-field\" v-show=\"showItem('ap-letter-spacing')\"><span class=\"pd-label\">字间距</span>\n <StepperInput v-model=\"element.options.letterSpacing\"\n :min=\"0\"\n :max=\"20\"\n :step=\"0.5\" />\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'\nimport StepperInput from './StepperInput.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 <div class=\"ee-field-info\">\n <span class=\"ee-item-label\">{{ field.fieldLabel }}</span>\n <span class=\"ee-item-key\">{{ field.fieldKey }}</span>\n </div>\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=\"handleVariableDoubleClick(sv)\"\n >\n <div class=\"ee-field-info\">\n <span class=\"ee-item-label\">{{ sv.label }}</span>\n <span class=\"ee-item-key\">{{ sv.template }}</span>\n </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=\"handleFunctionDoubleClick(fn)\"\n >\n <div class=\"ee-field-info\">\n <span class=\"ee-item-label\">{{ fn.label }}</span>\n <span class=\"ee-item-key\">{{ fn.name }}()</span>\n </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=\"handleFunctionDoubleClick(fn)\"\n >\n <div class=\"ee-field-info\">\n <span class=\"ee-item-label\">{{ fn.label }}</span>\n <span class=\"ee-item-key\">{{ fn.name }}()</span>\n </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=\"双击左侧字段/变量/函数插入,或直接输入静态内容\"\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 静态数据直接输入即可,如:供应商名称<br>\n 动态解析字段、变量、函数必须用 {} 包裹<br>\n 示例:{SUM(supplier.name)}<br>\n 注意:只能嵌套一层\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(字段) - 计数<br>\n IF(条件, 真值, 假值) - 条件判断\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 {pageIndex} - 当前页码<br>\n {totalPages} - 总页数<br>\n {printDate} - 打印日期\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 静态文本:供应商名称<br>\n 动态字段:{supplier.name}<br>\n 函数调用:{SUM(amount)}<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// 当弹出框打开时,重置为外部传入值\nwatch(visible, (val) => {\n if (val) {\n localExpression.value = props.expression || ''\n }\n})\n\n// 字段双击:函数参数内插入裸字段(去大括号),其余场景保持 {字段} 包裹\nfunction handleFieldDoubleClick(field: PrintBusinessField) {\n const { insideParens } = getCursorRegion()\n insertAtCursor(insideParens ? field.fieldKey : `{${field.fieldKey}}`)\n}\n\n// 变量双击:函数参数内去大括号,其余场景保持 {变量} 原样\nfunction handleVariableDoubleClick(sv: { name: string; template: string }) {\n const { insideParens } = getCursorRegion()\n insertAtCursor(insideParens ? sv.template.replace(/^\\{|\\}$/g, '') : sv.template)\n}\n\n// 函数双击:已在 {…} 块内则裸插入,否则自动包裹大括号;光标定位到 () 内部\nfunction handleFunctionDoubleClick(fn: { name: string; template: string }) {\n const { insideBlock } = getCursorRegion()\n const text = insideBlock ? fn.template : `{${fn.template}}`\n const caretOffset = text.indexOf('(') + 1\n insertAtCursor(text, caretOffset)\n}\n\n// 根据光标位置判断插入上下文:是否在 {…} 表达式块内、是否在函数参数 (…) 内\nfunction getCursorRegion(): { insideBlock: boolean; insideParens: boolean } {\n const ta = textareaRef.value\n const start = ta?.selectionStart ?? localExpression.value.length\n const before = localExpression.value.substring(0, start)\n\n // 光标前最近的 { 未被 } 闭合 → 在表达式块内\n let insideBlock = false\n const lastBlockOpen = before.lastIndexOf('{')\n if (lastBlockOpen !== -1 && !before.slice(lastBlockOpen + 1).includes('}')) {\n insideBlock = true\n }\n\n // 光标前最近的 ( 未被 ) 闭合 → 在函数参数内\n let insideParens = false\n const lastParenOpen = before.lastIndexOf('(')\n if (lastParenOpen !== -1 && !before.slice(lastParenOpen + 1).includes(')')) {\n insideParens = true\n }\n\n return { insideBlock, insideParens }\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, caretOffset = text.length) {\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 const caretPos = start + caretOffset\n nextTick(() => {\n ta.focus()\n ta.selectionStart = ta.selectionEnd = caretPos\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: 6px 10px;\n margin-bottom: 2px;\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: 7px 10px;\n cursor: pointer;\n border-radius: 4px;\n margin-bottom: 2px;\n transition: background 0.15s;\n}\n.ee-field-info {\n display: flex;\n flex-direction: column;\n gap: 1px;\n}\n.ee-field-info .ee-item-label {\n font-size: 12px;\n color: var(--pd-text);\n}\n.ee-field-info .ee-item-key {\n font-size: 10px;\n color: var(--pd-text-muted);\n font-family: monospace;\n}\n\n.ee-list-item:hover {\n background: #ecf5ff;\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 <StepperInput v-model=\"element.options.tableDefaultFontSize\" :min=\"5\" :max=\"72\" placeholder=\"默认\" />\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 <StepperInput v-model=\"element.options.tableDefaultPadding\" :min=\"0\" :max=\"10\" :step=\"0.5\" placeholder=\"默认\" />\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 <StepperInput :model-value=\"w\" :min=\"5\" :max=\"200\" @update:model-value=\"onColWidthChange(i, $event)\" />\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'\nimport StepperInput from './StepperInput.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 <StepperInput v-model=\"element.options.borderWidth\"\n :min=\"0\"\n :max=\"20\"\n :step=\"0.25\" />\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'\nimport StepperInput from './StepperInput.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: 10px;\n}\n.border-row .pd-field {\n flex: 1;\n min-width: 0;\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 <StepperInput v-model=\"element.options.zIndex\"\n :min=\"0\"\n :max=\"999\" />\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'\nimport StepperInput from './StepperInput.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 <StepperInput :model-value=\"row.height\"\n :min=\"3\"\n :max=\"100\"\n :step=\"0.5\" @update:model-value=\"onHeightChange\" />\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'\nimport StepperInput from './StepperInput.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 <label class=\"pd-radio\"><input type=\"radio\" value=\"image\" :checked=\"mainCell.cellType === 'image'\" @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\" v-if=\"isBarcodeCell || isQrcodeCell || isImageCell\"><span class=\"pd-label\">缩放模式</span>\n <select :value=\"mainCell.fit || 'contain'\" class=\"pd-select\" @change=\"write(c => { c.fit = ($event.target as HTMLSelectElement).value as any })\">\n <option value=\"contain\">包含(保持比例)</option>\n <option value=\"cover\">覆盖(保持比例)</option>\n <option value=\"fill\">拉伸填满</option>\n <option value=\"none\">原始尺寸</option>\n <option value=\"scale-down\">缩小(保持比例)</option>\n </select>\n </div>\n <div class=\"pd-field\" v-if=\"isBarcodeCell || isQrcodeCell || isImageCell\"><span class=\"pd-label\">最大宽度 (mm)</span>\n <StepperInput :model-value=\"mainCell.maxWidth\"\n :min=\"1\"\n :max=\"200\"\n placeholder=\"默认\" @update:model-value=\"write(c => { c.maxWidth = $event ?? undefined })\" />\n </div>\n <div class=\"pd-field\" v-if=\"isBarcodeCell || isQrcodeCell || isImageCell\"><span class=\"pd-label\">最大高度 (mm)</span>\n <StepperInput :model-value=\"mainCell.maxHeight\"\n :min=\"1\"\n :max=\"200\"\n placeholder=\"默认\" @update:model-value=\"write(c => { c.maxHeight = $event ?? undefined })\" />\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 <StepperInput :model-value=\"mainCell.fontSize\"\n :min=\"5\"\n :max=\"72\"\n placeholder=\"默认\" @update:model-value=\"write(c => { c.fontSize = $event ?? 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 <div style=\"width: 112px; flex-shrink: 0\"><StepperInput v-model=\"borderWidth\"\n :min=\"0.25\"\n :max=\"5\"\n :step=\"0.25\" /></div>\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 <StepperInput :model-value=\"mainCell.padding\"\n :min=\"0\"\n :max=\"10\"\n :step=\"0.5\"\n placeholder=\"默认\" @update:model-value=\"write(c => { c.padding = $event ?? 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 StepperInput from './StepperInput.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')\nconst isImageCell = computed(() => mainCell.value.cellType === 'image')\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 // fit、maxWidth、maxHeight 对所有类型都有效,不再清除\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 <StepperInput :model-value=\"customWidth\"\n :min=\"25\"\n :max=\"2000\"\n @update:model-value=\"onCustomWidthChange\" />\n <span class=\"custom-size-x\">×</span>\n <StepperInput :model-value=\"customHeight\"\n :min=\"25\"\n :max=\"2000\"\n @update:model-value=\"onCustomHeightChange\" />\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 <div class=\"pd-field\"><span class=\"pd-label\">页面背景色</span>\n <div class=\"page-bg-row\">\n <PresetColorPicker v-model=\"pageBackgroundModel\" class=\"page-bg-picker\" />\n <button type=\"button\" class=\"pd-reset\" title=\"恢复为默认白色\" @click=\"onPageBackgroundReset\">默认</button>\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 <StepperInput :model-value=\"marginTop\" :min=\"0\" :max=\"50\" @update:model-value=\"onMarginTopChange\" />\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">下</span>\n <StepperInput :model-value=\"marginBottom\" :min=\"0\" :max=\"50\" @update:model-value=\"onMarginBottomChange\" />\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">左</span>\n <StepperInput :model-value=\"marginLeft\" :min=\"0\" :max=\"50\" @update:model-value=\"onMarginLeftChange\" />\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">右</span>\n <StepperInput :model-value=\"marginRight\" :min=\"0\" :max=\"50\" @update:model-value=\"onMarginRightChange\" />\n </div>\n </div>\n\n <h3 class=\"pd-divider\">三区高度 (mm)</h3>\n <div class=\"pd-field\"><span class=\"pd-label\">页眉高度</span>\n <StepperInput :model-value=\"headerHeight\" :min=\"0\" :max=\"100\" :step=\"0.1\" @update:model-value=\"onHeaderHeightChange\" />\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">页脚高度</span>\n <StepperInput :model-value=\"footerHeight\" :min=\"0\" :max=\"100\" :step=\"0.1\" @update:model-value=\"onFooterHeightChange\" />\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">首页叠加高度</span>\n <StepperInput :model-value=\"overlayHeight\" :min=\"0\" :max=\"200\" @update:model-value=\"onOverlayHeightChange\" />\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 StepperInput from './property/StepperInput.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 PresetColorPicker from './PresetColorPicker.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 pageBackgroundModel = computed({\n get: () => props.templateData?.pageBackground || '#ffffff',\n set: (v: string) => onPageBackgroundChange(v),\n})\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 onPageBackgroundChange(v: string) {\n const value = v && v.toLowerCase() !== '#ffffff' && v.toLowerCase() !== '#fff' ? v : undefined\n emitUpdate(value === undefined ? { pageBackground: undefined } : { pageBackground: value })\n}\n\nfunction onPageBackgroundReset() {\n emitUpdate({ pageBackground: undefined })\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.page-bg-row {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.page-bg-picker {\n flex: 1;\n min-width: 0;\n}\n.pd-reset {\n height: 26px;\n padding: 0 8px;\n border: 1px solid var(--pd-border, #d9dde6);\n border-radius: 5px;\n background: var(--pd-field-bg, #f4f6fa);\n color: var(--pd-text-muted, #8b909c);\n font-size: 12px;\n cursor: pointer;\n flex-shrink: 0;\n transition: all .14s ease;\n}\n.pd-reset:hover {\n color: var(--pd-accent, #165DFF);\n border-color: var(--pd-accent, #165DFF);\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) }} 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","export default {\n id: 'getting-started',\n title: '快速入门',\n content: `\n<h2>界面布局</h2>\n<p>打印模板设计器采用三栏布局:</p>\n<ul>\n <li><strong>左侧面板</strong>:字段树和图层管理,用于查看和管理画布上的元素</li>\n <li><strong>中间画布</strong>:设计区域,支持标尺、参考线、网格显示</li>\n <li><strong>右侧面板</strong>:属性设置和模板配置</li>\n <li><strong>顶部工具栏</strong>:常用操作按钮</li>\n <li><strong>底部状态栏</strong>:显示坐标、缩放比例、元素数量</li>\n</ul>\n\n<h2>添加第一个元素</h2>\n<ol>\n <li>从左侧面板选择元素类型(文本、图片、条码等)</li>\n <li>拖拽到画布上松开</li>\n <li>选中元素后,通过拖拽调整位置</li>\n <li>拖拽元素边角手柄调整大小</li>\n</ol>\n\n<h2>数据绑定基础</h2>\n<p>使用花括号 <code>{field.path}</code> 语法绑定数据字段:</p>\n<pre><code>供应商:{supplier.name}\n日期:{order.date}\n金额:{MONEY(order.total)}</code></pre>\n<p>双击元素可打开表达式编辑器配置绑定。</p>\n\n<h2>保存与预览</h2>\n<ul>\n <li>点击工具栏\"保存\"按钮,模板以 JSON 格式导出</li>\n <li>点击\"预览\"按钮查看打印效果</li>\n <li>模板数据包含页面设置、元素定义、样式配置</li>\n</ul>\n\n<h2>关于项目</h2>\n<p><strong>项目名称:</strong>worm-vue3-print</p>\n<p><strong>仓库地址:</strong><a href=\"https://gitee.com/liulong_oschina/worm-vue3-print\" target=\"_blank\" rel=\"noopener noreferrer\">https://gitee.com/liulong_oschina/worm-vue3-print</a></p>\n<p>基于 Vue 3 的可视化打印模板设计器,支持拖拽式模板编辑、表达式数据绑定和浏览器端打印预览。</p>\n `\n}\n","export default {\n id: 'features',\n title: '功能说明',\n content: `\n<h2>元素类型</h2>\n<table>\n <thead>\n <tr><th>类型</th><th>说明</th></tr>\n </thead>\n <tbody>\n <tr><td>文本</td><td>静态或动态文本,支持表达式绑定</td></tr>\n <tr><td>长文本</td><td>多行文本,支持自动换行</td></tr>\n <tr><td>数据表格</td><td>动态行列,支持分页、表头重复、序号/小计/汇总</td></tr>\n <tr><td>条形码</td><td>支持 code128 等多种码制</td></tr>\n <tr><td>二维码</td><td>支持 L/M/Q/H 纠错级别</td></tr>\n <tr><td>图片</td><td>静态或动态图片</td></tr>\n <tr><td>线条</td><td>水平线或垂直线</td></tr>\n <tr><td>形状</td><td>矩形、椭圆,支持边框和背景色</td></tr>\n <tr><td>HTML</td><td>自定义 HTML 内容</td></tr>\n <tr><td>页码</td><td>自动页码显示</td></tr>\n </tbody>\n</table>\n\n<h2>表达式编辑器</h2>\n<h3>基础语法</h3>\n<p>使用花括号 <code>{}</code> 包裹表达式,花括号外为字面文本。</p>\n\n<h3>内置函数</h3>\n<table>\n <thead>\n <tr><th>函数</th><th>说明</th><th>示例</th></tr>\n </thead>\n <tbody>\n <tr><td><code>MONEY(value)</code></td><td>金额格式化(千分位+两位小数)</td><td><code>{MONEY(order.total)}</code> -> \"69,543.75\"</td></tr>\n <tr><td><code>DATE(value, format)</code></td><td>日期格式化</td><td><code>{DATE(order.date, 'YYYY-MM-DD')}</code></td></tr>\n <tr><td><code>UPPER(value)</code></td><td>数字转大写金额</td><td><code>{UPPER(order.total)}</code> -> \"陆万玖仟伍佰肆拾叁元柒角伍分\"</td></tr>\n <tr><td><code>IF(cond, true, false)</code></td><td>条件判断</td><td><code>{IF(qty > 100, '大量', '少量')}</code></td></tr>\n <tr><td><code>CONCAT(str1, str2, ...)</code></td><td>字符串拼接</td><td><code>{CONCAT(name, '-', spec)}</code></td></tr>\n <tr><td><code>IFEMPTY(value, default)</code></td><td>空值默认</td><td><code>{IFEMPTY(remark, '无')}</code></td></tr>\n <tr><td><code>ROUND(num, decimals)</code></td><td>四舍五入</td><td><code>{ROUND(price, 2)}</code></td></tr>\n <tr><td><code>NOW()</code></td><td>当前日期</td><td><code>{NOW()}</code></td></tr>\n <tr><td><code>SUBSTR(str, start, len)</code></td><td>子字符串</td><td><code>{SUBSTR(name, 0, 3)}</code></td></tr>\n <tr><td><code>LEN(str)</code></td><td>字符串长度</td><td><code>{LEN(name)}</code></td></tr>\n <tr><td><code>PAD(value, len, char)</code></td><td>左侧补位</td><td><code>{PAD(qty, 5, '0')}</code></td></tr>\n </tbody>\n</table>\n\n<h3>聚合函数(表格小计/汇总行使用)</h3>\n<table>\n <thead>\n <tr><th>函数</th><th>说明</th></tr>\n </thead>\n <tbody>\n <tr><td><code>SUM(field)</code></td><td>求和</td></tr>\n <tr><td><code>AVG(field)</code></td><td>平均值</td></tr>\n <tr><td><code>COUNT(field)</code></td><td>计数</td></tr>\n <tr><td><code>MIN(field)</code></td><td>最小值</td></tr>\n <tr><td><code>MAX(field)</code></td><td>最大值</td></tr>\n </tbody>\n</table>\n\n<h3>系统变量</h3>\n<table>\n <thead>\n <tr><th>变量</th><th>说明</th></tr>\n </thead>\n <tbody>\n <tr><td><code>pageIndex</code></td><td>当前页码</td></tr>\n <tr><td><code>totalPages</code></td><td>总页数</td></tr>\n <tr><td><code>printDate</code></td><td>打印日期 (YYYY-MM-DD)</td></tr>\n <tr><td><code>printTime</code></td><td>打印时间戳</td></tr>\n </tbody>\n</table>\n\n<h2>数据表格配置</h2>\n<h3>行类型</h3>\n<ul>\n <li><strong>标题行 (header)</strong>:可设置每页重复显示</li>\n <li><strong>数据行 (data)</strong>:绑定列表数据源迭代显示</li>\n <li><strong>小计行 (subtotal)</strong>:当前页末尾显示汇总</li>\n <li><strong>汇总行 (summary)</strong>:仅最后一页显示</li>\n</ul>\n\n<h3>表格操作</h3>\n<ul>\n <li>右键菜单支持插入/删除行和列</li>\n <li>支持单元格合并/拆分</li>\n <li>支持边框预设:全部/外边框/内边框/无</li>\n <li>无边框表格设计态显示虚拟虚线</li>\n <li><strong>调整列宽</strong>:需要先在左侧面板的图层中选中对应的表格元素,然后才能在画布上拖动列宽分隔线</li>\n <li><strong>调整表格属性</strong>:必须确保当前没有任何单元格被选中。如有选中的单元格,先点击画布空白区域取消选中,再在图层中选择表格元素</li>\n <li><strong>单元格图片处理</strong>:若单元格中图片无法缩小,请将图片处理方式设置为\"缩小保持比例\"</li>\n</ul>\n\n<h2>对齐与吸附</h2>\n<h3>自动对齐</h3>\n<p>拖拽元素时自动显示对齐引导线:</p>\n<ul>\n <li>蓝色:左/顶对齐</li>\n <li>绿色:居中对齐</li>\n <li>橙色:右/底对齐</li>\n</ul>\n\n<h3>网格吸附</h3>\n<p>开启吸附功能后,元素自动吸附到网格点。</p>\n\n<h3>手动参考线</h3>\n<p>通过标尺区域拖拽添加参考线,参考线参与吸附检测。</p>\n\n<h2>图层管理</h2>\n<ul>\n <li>调整元素显示顺序(置顶/置底/上移/下移)</li>\n <li>显示/隐藏元素</li>\n <li>锁定/解锁元素(锁定后不可编辑)</li>\n</ul>\n\n<h2>三区布局</h2>\n<p>页面分为三个区域:</p>\n<ul>\n <li><strong>页眉 (header)</strong>:顶部区域</li>\n <li><strong>内容区 (content)</strong>:主体区域</li>\n <li><strong>页脚 (footer)</strong>:底部区域</li>\n</ul>\n<p>页眉/页脚支持的元素类型:文本、图片、线条、形状、条形码、二维码</p>\n\n<h2>水印配置</h2>\n<ul>\n <li>支持固定文本或绑定字段</li>\n <li>可设置旋转角度和透明度</li>\n <li>支持显示打印时间戳</li>\n</ul>\n `\n}\n","export default {\n id: 'shortcuts',\n title: '快捷键',\n content: `\n<h2>常用操作</h2>\n<table>\n <thead>\n <tr><th>快捷键</th><th>功能</th></tr>\n </thead>\n <tbody>\n <tr><td><code>Ctrl + C</code></td><td>复制选中元素</td></tr>\n <tr><td><code>Ctrl + V</code></td><td>粘贴元素(偏移 10mm)</td></tr>\n <tr><td><code>Ctrl + D</code></td><td>原地复制(偏移 5mm, 5mm)</td></tr>\n <tr><td><code>Ctrl + A</code></td><td>全选元素</td></tr>\n <tr><td><code>Delete / Backspace</code></td><td>删除选中元素</td></tr>\n <tr><td><code>Ctrl + Z</code></td><td>撤销</td></tr>\n <tr><td><code>Ctrl + Shift + Z</code> / <code>Ctrl + Y</code></td><td>重做</td></tr>\n </tbody>\n</table>\n\n<h2>元素移动</h2>\n<table>\n <thead>\n <tr><th>快捷键</th><th>功能</th></tr>\n </thead>\n <tbody>\n <tr><td><code>方向键</code></td><td>移动 1mm</td></tr>\n <tr><td><code>Shift + 方向键</code></td><td>移动 10mm</td></tr>\n <tr><td><code>Ctrl + 方向键</code></td><td>移动 0.5mm</td></tr>\n </tbody>\n</table>\n\n<h2>缩放控制</h2>\n<table>\n <thead>\n <tr><th>快捷键</th><th>功能</th></tr>\n </thead>\n <tbody>\n <tr><td><code>Ctrl + 1</code></td><td>重置缩放至 100%</td></tr>\n <tr><td><code>Ctrl + 0</code></td><td>适应窗口</td></tr>\n </tbody>\n</table>\n\n<h2>对齐操作(多选时)</h2>\n<table>\n <thead>\n <tr><th>快捷键</th><th>功能</th></tr>\n </thead>\n <tbody>\n <tr><td><code>Ctrl + L</code></td><td>左对齐</td></tr>\n <tr><td><code>Ctrl + R</code></td><td>右对齐</td></tr>\n <tr><td><code>Ctrl + E</code></td><td>水平居中</td></tr>\n <tr><td><code>Ctrl + T</code></td><td>顶对齐</td></tr>\n <tr><td><code>Ctrl + B</code></td><td>底对齐</td></tr>\n </tbody>\n</table>\n\n<h2>组合操作</h2>\n<table>\n <thead>\n <tr><th>快捷键</th><th>功能</th></tr>\n </thead>\n <tbody>\n <tr><td><code>Ctrl + G</code></td><td>组合选中元素</td></tr>\n <tr><td><code>Ctrl + Shift + G</code></td><td>取消组合</td></tr>\n </tbody>\n</table>\n\n<blockquote>\n <p><strong>注意</strong>:当焦点在输入框、文本框、下拉框内时,快捷键不生效。</p>\n</blockquote>\n `\n}\n","export default {\n id: 'faq',\n title: '常见问题',\n content: `\n<h2>如何调整纸张大小?</h2>\n<ol>\n <li>在右侧面板选择\"页面设置\"</li>\n <li>选择预设纸张(A4、A3、A5、Letter、Legal)</li>\n <li>或选择\"自定义\"输入宽度和高度(mm)</li>\n <li>设置方向:纵向(portrait)或横向(landscape)</li>\n</ol>\n\n<h2>如何处理分页?</h2>\n<p>数据表格支持自动分页:</p>\n<ol>\n <li>在表格属性中设置\"每页显示行数\"</li>\n <li>启用\"表头重复\"确保跨页时显示标题行</li>\n <li>添加小计行显示当前页汇总</li>\n <li>添加汇总行显示整表汇总</li>\n</ol>\n\n<h2>如何导入外部数据?</h2>\n<p>通过组件 props 传入数据:</p>\n<ul>\n <li><code>fields</code>:字段定义数组,用于字段树显示</li>\n <li><code>initialTemplate</code>:初始模板数据</li>\n <li><code>loadDefaultTemplate</code>:加载默认模板的回调函数</li>\n</ul>\n\n<h2>如何使用表达式绑定字段?</h2>\n<ol>\n <li>双击元素打开表达式编辑器</li>\n <li>使用 <code>{field.path}</code> 语法绑定字段</li>\n <li>使用内置函数格式化数据(如 <code>{MONEY(price)}</code>)</li>\n <li>点击确认保存</li>\n</ol>\n\n<h2>如何调整元素层级?</h2>\n<ol>\n <li>选中一个或多个元素</li>\n <li>点击工具栏的层级按钮:\n <ul>\n <li>⤒ 置顶</li>\n <li>↑ 上移一层</li>\n <li>↓ 下移一层</li>\n <li>⤓ 置底</li>\n </ul>\n </li>\n</ol>\n<p>或使用快捷键在图层面板中调整。</p>\n\n<h2>如何组合多个元素?</h2>\n<ol>\n <li>按住 Ctrl 逐个点击选中多个元素</li>\n <li>点击工具栏\"组合\"按钮,或按 <code>Ctrl + G</code></li>\n <li>组合后点击任一元素可选中整个组</li>\n <li>取消组合:选中组合后点击\"取消组合\",或按 <code>Ctrl + Shift + G</code></li>\n</ol>\n\n<h2>如何使用参考线?</h2>\n<ol>\n <li>在标尺区域拖拽添加参考线</li>\n <li>参考线自动参与吸附检测</li>\n <li>拖拽参考线可调整位置</li>\n <li>双击参考线可删除</li>\n</ol>\n\n<h2>如何预览打印效果?</h2>\n<ol>\n <li>点击工具栏\"预览\"按钮</li>\n <li>预览使用同构渲染管线,确保与实际打印一致</li>\n <li>可通过\"叠层对比\"功能对比设计稿与截图</li>\n</ol>\n\n<h2>模板数据格式是什么?</h2>\n<p>模板以 JSON 格式存储,包含:</p>\n<ul>\n <li><code>paperSize</code>:纸张大小</li>\n <li><code>orientation</code>:方向</li>\n <li><code>margins</code>:页边距</li>\n <li><code>header</code>:页眉配置</li>\n <li><code>footer</code>:页脚配置</li>\n <li><code>elements</code>:元素数组</li>\n <li><code>watermark</code>:水印配置</li>\n</ul>\n\n<h2>如何调整表格列宽?</h2>\n<ol>\n <li>在左侧面板的图层列表中,点击选中对应的表格元素</li>\n <li>此时画布上的表格会显示列宽分隔线</li>\n <li>拖动列宽分隔线即可调整列宽</li>\n</ol>\n<blockquote>\n <p><strong>注意</strong>:必须先选中表格元素,才能激活列宽拖动功能。</p>\n</blockquote>\n\n<h2>如何调整表格属性?</h2>\n<ol>\n <li>确保当前没有任何单元格被选中(如有选中,点击画布空白区域取消选中)</li>\n <li>在左侧面板的图层列表中,点击选中对应的表格元素</li>\n <li>右侧面板会显示表格属性设置</li>\n</ol>\n<blockquote>\n <p><strong>注意</strong>:如果存在选中的单元格,右侧面板将显示单元格属性而非表格属性。</p>\n</blockquote>\n `\n}\n","export default {\n id: 'changelog',\n title: '更新记录',\n content: `\n<h2>v1.2.1 <small>2026-09-11</small></h2>\n\n<h3>变更</h3>\n<ul>\n <li>工具栏编辑区/层级区/视图区图标按钮统一使用 data-tip 自定义悬浮提示,补齐「网格」「吸附」缺失提示;提升提示层级,不再被画布顶部标尺遮挡。</li>\n <li>优化「适应窗口」:以视口中心为锚点一步缩放到位(与 Ctrl+滚轮同一缩放换算管线),缩放平滑过渡;允许低于交互缩放下限(最小可至 5%),超大纸张也能整版容纳,纸张在画布视口内水平垂直居中。</li>\n <li>新增 <code>showHelp</code> 配置:控制帮助入口(帮助按钮与帮助弹框)显示,默认开启,传入 <code>false</code> 即可隐藏。</li>\n</ul>\n\n<h3>修复</h3>\n<ul>\n <li>工具栏悬浮提示气泡被画布顶部固定标尺遮挡无法显示。</li>\n <li>「适应窗口」后超大纸张仍残留滚动条、纸张未在画布视口居中(垂直偏上)。</li>\n</ul>\n\n<h3>文档</h3>\n<ul>\n <li>新增打印设计工作台布局线框图文档(<code>docs/中文/打印设计工作台-布局线框图.md</code>),标注各区域名称、功能与对应组件文件。</li>\n</ul>\n\n<h2>v1.2.0 <small>2026-09-10</small></h2>\n\n<h3>新增</h3>\n<ul>\n <li>帮助文档模态框(HelpModal):内置功能介绍、快捷键一览、常见问题与更新记录,按 Esc 或点击遮罩关闭。</li>\n <li>标尺参考线增强:支持从标尺拖拽添加参考线、双击编辑、删除,参考线对齐吸附实时显示。</li>\n <li>表格列宽拖拽新增末列右边界手柄:可直接拖拽末列右边界调整末列宽,受打印范围宽度与最小列宽 5mm 钳制。</li>\n</ul>\n\n<h3>变更</h3>\n<ul>\n <li>优化缩放逻辑:取消放大上限,支持滚轮乘性步进缩放,修复缩放锚点漂移问题。</li>\n <li>移除设计态元素左上角的 fx 绑定标签提示,简化元素视觉呈现。</li>\n</ul>\n\n<h3>文档</h3>\n<ul>\n <li>仓库根目录新增 <code>AGENTS.md</code>:AI 代理行为规范,明确代理在本仓库工作时的语言、专家态度、协作约定等强制要求。</li>\n <li>新增 <code>worm-vue3-print</code> 集成支持 skill:包含安装指南、集成 API、故障排查等参考文档。</li>\n</ul>\n\n<h3>修复</h3>\n<ul>\n <li>表格列宽拖拽存在的多个缺陷:\n <ul>\n <li>内部列边界向左拖时左列宽度不变,导致边界线不跟随光标。</li>\n <li>px → mm 单位换算缺失,拖拽距离存在约 3.78 倍偏差。</li>\n <li><code>table-layout: fixed</code> 下拖拽过程中表格 CSS <code>width(100%)</code> 与列宽和失配,导致浏览器按比例拉伸列,使边界线与右侧内容偏离光标。</li>\n <li>删除 <code>onColResizeStart</code> 中残留的 <code>document.title</code> 调试代码。</li>\n </ul>\n </li>\n</ul>\n\n<h2>v1.1.0 <small>2026-09-06</small></h2>\n\n<h3>新增</h3>\n<ul>\n <li>表格元素支持列宽拖拽:设计态选中表格后,在列边界悬停并拖动即可调整该列宽(左侧列),实时更新画布与元素尺寸;受打印范围宽度与最小列宽 5mm 钳制,拖拽结束后计入一次撤销历史。属性面板的列宽数值输入保留作为精确输入兜底。</li>\n <li>表格单元格支持图片类型:单元格可切换为图片类型,设计态支持选择图片与设置 fit/maxWidth/maxHeight,预览与打印输出完整渲染。</li>\n <li>条形码与二维码单元格支持 fit/maxWidth/maxHeight 属性。</li>\n <li>属性面板位置尺寸改用 StepperInput 控件:支持按钮微调数值;StepperInput 支持可选值列表和小数步进。</li>\n <li>新增统一颜色选择器并重构属性面板字段分组。</li>\n <li>支持页面(纸张)背景色 <code>pageBackground</code>,预览与打印/PDF 输出一致。</li>\n <li>支持 canvas 库模式构建与 npm 发布。</li>\n</ul>\n\n<h3>修复</h3>\n<ul>\n <li>打印/导出 PDF 保留元素背景色(<code>print-color-adjust: exact</code>)。</li>\n <li>打印预览保留元素重叠,表格下方跟随元素按设计坐标绝对定位并透传层级 z-index。</li>\n <li>打印页眉页脚区域贴页面底部,修复页边距失效。</li>\n <li>条形码渲染缺少 <code>object-fit: contain</code>。</li>\n <li>修复 canvas 测试在 vitest v4 + happy-dom 环境下 <code>localStorage</code> 未定义的问题,补充 mock 以兼容测试环境。</li>\n</ul>\n\n<h2>v1.0.0 <small>2026-09-02</small></h2>\n\n<h3>新增</h3>\n<ul>\n <li>首次开源发布。</li>\n <li><code>@worm-vue3-print/core</code>:模板表达式引擎与同构渲染管线(HTML 生成 / 分页 / 数据绑定)。</li>\n <li><code>@worm-vue3-print/canvas</code>:Vue 3 可视化打印模板设计器画布。</li>\n <li>渲染微服务拆分为独立仓库 <code>worm-vue3-print-render</code>(仅 Docker 部署,不上 npm)。</li>\n</ul>\n\n<blockquote>\n <p>完整更新记录请查阅仓库 <code>docs/中文/CHANGELOG.md</code> 与 <code>docs/en/CHANGELOG.en.md</code>。</p>\n</blockquote>\n `\n}\n","import gettingStarted from './getting-started'\nimport features from './features'\nimport shortcuts from './shortcuts'\nimport faq from './faq'\nimport changelog from './changelog'\n\nexport type HelpSection = {\n id: string\n title: string\n content: string\n}\n\nexport const helpSections: HelpSection[] = [\n gettingStarted,\n features,\n shortcuts,\n faq,\n changelog,\n]\n\nexport type { HelpSection as default }\n","<template>\n <Teleport to=\"body\">\n <Transition name=\"help-modal\">\n <div\n v-if=\"visible\"\n class=\"help-modal-overlay\"\n @click.self=\"$emit('close')\"\n >\n <div class=\"help-modal\">\n <div class=\"help-modal-header\">\n <div class=\"help-modal-title-wrap\">\n <h2 class=\"help-modal-title\">帮助文档</h2>\n <span class=\"help-modal-project\">worm-vue3-print</span>\n </div>\n <button\n class=\"help-modal-close\"\n title=\"关闭\"\n @click=\"$emit('close')\"\n >\n ×\n </button>\n </div>\n \n <div class=\"help-modal-body\">\n <div class=\"help-modal-sidebar\">\n <button\n v-for=\"section in sections\"\n :key=\"section.id\"\n :class=\"['help-tab', { active: activeTab === section.id }]\"\n @click=\"switchTab(section.id)\"\n >\n {{ section.title }}\n </button>\n </div>\n \n <div class=\"help-modal-content\">\n <div\n class=\"help-content\"\n v-html=\"currentContent\"\n />\n </div>\n </div>\n </div>\n </div>\n </Transition>\n </Teleport>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, watch, onMounted, onUnmounted } from 'vue'\nimport { helpSections } from '../help-content'\n\nconst props = withDefaults(defineProps<{\n visible: boolean\n initialTab?: string\n}>(), {\n initialTab: 'getting-started'\n})\n\nconst emit = defineEmits<{\n close: []\n 'update:tab': [tab: string]\n}>()\n\nconst sections = helpSections\nconst activeTab = ref(props.initialTab)\n\nconst STORAGE_KEY = 'worm-print-help-tab'\nonMounted(() => {\n const saved = localStorage.getItem(STORAGE_KEY)\n if (saved && sections.some(s => s.id === saved)) {\n activeTab.value = saved\n }\n})\n\nwatch(() => props.visible, (v) => {\n if (v) {\n const saved = localStorage.getItem(STORAGE_KEY)\n if (saved && sections.some(s => s.id === saved)) {\n activeTab.value = saved\n }\n }\n})\n\nfunction switchTab(tabId: string) {\n activeTab.value = tabId\n localStorage.setItem(STORAGE_KEY, tabId)\n emit('update:tab', tabId)\n}\n\nconst currentContent = computed(() => {\n const section = sections.find(s => s.id === activeTab.value)\n return section?.content || ''\n})\n\nfunction handleKeydown(e: KeyboardEvent) {\n if (e.key === 'Escape' && props.visible) {\n emit('close')\n }\n}\n\nonMounted(() => {\n document.addEventListener('keydown', handleKeydown)\n})\n\nonUnmounted(() => {\n document.removeEventListener('keydown', handleKeydown)\n})\n</script>\n\n<style scoped>\n.help-modal-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n}\n\n.help-modal {\n width: 800px;\n max-width: 90vw;\n height: 600px;\n max-height: 85vh;\n background: var(--pd-surface, #ffffff);\n border-radius: 8px;\n box-shadow: 0 4px 24px rgba(0, 0, 0, 0.15);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n.help-modal-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--pd-border, #d9dde6);\n}\n\n.help-modal-title {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--pd-text, #2a2e37);\n}\n\n.help-modal-title-wrap {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.help-modal-project {\n padding: 2px 8px;\n border-radius: 4px;\n background: var(--pd-accent-soft, rgba(22, 93, 255, 0.09));\n color: var(--pd-accent, #165DFF);\n font-size: 12px;\n font-weight: 500;\n}\n\n.help-modal-close {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: none;\n border-radius: 4px;\n background: transparent;\n color: var(--pd-text-muted, #8b909c);\n font-size: 20px;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.help-modal-close:hover {\n background: var(--pd-sidebar-hover, #f0f3f9);\n color: var(--pd-text, #2a2e37);\n}\n\n.help-modal-body {\n flex: 1;\n display: flex;\n overflow: hidden;\n}\n\n.help-modal-sidebar {\n width: 160px;\n padding: 12px;\n border-right: 1px solid var(--pd-border, #d9dde6);\n background: var(--pd-field-bg, #f4f6fa);\n overflow-y: auto;\n}\n\n.help-tab {\n display: block;\n width: 100%;\n padding: 10px 12px;\n margin-bottom: 4px;\n border: none;\n border-radius: 4px;\n background: transparent;\n color: var(--pd-text, #2a2e37);\n font-size: 13px;\n text-align: left;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.help-tab:hover {\n background: var(--pd-sidebar-hover, #f0f3f9);\n}\n\n.help-tab.active {\n background: var(--pd-accent-soft, rgba(22, 93, 255, 0.09));\n color: var(--pd-accent, #165DFF);\n font-weight: 500;\n}\n\n.help-modal-content {\n flex: 1;\n padding: 20px;\n overflow-y: auto;\n}\n\n.help-content {\n font-size: 14px;\n line-height: 1.6;\n color: var(--pd-text, #2a2e37);\n}\n\n.help-content :deep(h2) {\n margin: 0 0 16px;\n padding-bottom: 8px;\n border-bottom: 1px solid var(--pd-border-soft, #e9ecf2);\n font-size: 18px;\n font-weight: 600;\n}\n\n.help-content :deep(h3) {\n margin: 20px 0 12px;\n font-size: 15px;\n font-weight: 600;\n}\n\n.help-content :deep(p) {\n margin: 0 0 12px;\n}\n\n.help-content :deep(ul),\n.help-content :deep(ol) {\n margin: 0 0 12px;\n padding-left: 24px;\n}\n\n.help-content :deep(li) {\n margin-bottom: 4px;\n}\n\n.help-content :deep(code) {\n padding: 2px 6px;\n border-radius: 3px;\n background: var(--pd-field-bg, #f4f6fa);\n font-family: 'SF Mono', Monaco, monospace;\n font-size: 13px;\n}\n\n.help-content :deep(pre) {\n margin: 0 0 12px;\n padding: 12px;\n border-radius: 4px;\n background: var(--pd-field-bg, #f4f6fa);\n overflow-x: auto;\n}\n\n.help-content :deep(pre code) {\n padding: 0;\n background: transparent;\n}\n\n.help-content :deep(table) {\n width: 100%;\n margin: 0 0 12px;\n border-collapse: collapse;\n}\n\n.help-content :deep(th),\n.help-content :deep(td) {\n padding: 8px 12px;\n border: 1px solid var(--pd-border, #d9dde6);\n text-align: left;\n}\n\n.help-content :deep(th) {\n background: var(--pd-field-bg, #f4f6fa);\n font-weight: 600;\n}\n\n.help-content :deep(blockquote) {\n margin: 0 0 12px;\n padding: 12px 16px;\n border-left: 3px solid var(--pd-accent, #165DFF);\n background: var(--pd-accent-soft, rgba(22, 93, 255, 0.09));\n}\n\n.help-modal-enter-active,\n.help-modal-leave-active {\n transition: opacity 0.2s ease;\n}\n\n.help-modal-enter-active .help-modal,\n.help-modal-leave-active .help-modal {\n transition: transform 0.2s ease;\n}\n\n.help-modal-enter-from,\n.help-modal-leave-to {\n opacity: 0;\n}\n\n.help-modal-enter-from .help-modal,\n.help-modal-leave-to .help-modal {\n transform: scale(0.95);\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-ruler=\"showRuler\"\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 :show-help=\"showHelp !== false\"\n v-model:scale=\"scale\"\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-ruler=\"showRuler = !showRuler\"\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 @help=\"helpVisible = true\"\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-ruler=\"showRuler\"\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\n <!-- 帮助文档模态框 -->\n <HelpModal\n :visible=\"helpVisible\"\n @close=\"helpVisible = false\"\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 { computeFitScale, FIT_SCALE_MIN_PERCENT } from '../utils/scale'\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 HelpModal from './HelpModal.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 /** 是否展示帮助入口(帮助按钮与帮助弹框);默认开启,传 false 关闭 */\n showHelp?: boolean\n}>()\n\nconst emit = defineEmits<{\n preview: []\n save: [json: string]\n}>()\n\n// 帮助文档状态\nconst helpVisible = ref(false)\n\n// showHelp 关闭时强制收起帮助弹框(并隐藏工具栏帮助入口)\nwatch(() => props.showHelp, (v) => {\n if (v === false) helpVisible.value = false\n})\n\n// 装配层状态:面板折叠(localStorage 持久)+ 未保存 dirty\nconst { leftCollapsed, rightCollapsed, toggleLeft, toggleRight, dirty, markSaved } = useStudioChrome()\n\n// 设计器核心状态统一由 useDesignerState 管理\nconst {\n scale, showRuler, 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,\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) {\n // canvas-area 有非对称 padding(上44/右28/下32/左44),\n // 需扣除后方为真实可用视口,否则 padding 会被算进可用空间,导致适应后仍有溢出\n const cs = getComputedStyle(el)\n const padX = parseFloat(cs.paddingLeft) + parseFloat(cs.paddingRight)\n const padY = parseFloat(cs.paddingTop) + parseFloat(cs.paddingBottom)\n const dim = getPaperDimensions(templateData.value)\n const MM_TO_PX = 96 / 25.4\n // 目标比例由纸张尺寸与可用视口算出;CanvasArea 的 fitToWindow\n // 以视口中心为锚点一步到位,平滑动画由纸张 transform 过渡产生\n const target = computeFitScale(\n el.clientWidth - padX,\n el.clientHeight - padY,\n dim.width * MM_TO_PX,\n dim.height * MM_TO_PX,\n )\n canvasAreaRef.value?.fitToWindow(target)\n }\n}\nfunction onZoom(delta: number) {\n // 交互缩放下限保持 25%;适应窗口动画可达更低(见 FIT_SCALE_MIN_PERCENT),故不再钳制到 25\n scale.value = Math.max(FIT_SCALE_MIN_PERCENT, 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 image: 'src',\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","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","MIN_COL_WIDTH_MM","clampResizedColumnWidth","targetMm","maxTableWidth","others","cap","rounded","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","mmToPx","mm","PT_KEYS","convertElement","el","round2","n","normalizeTemplateUnits","convert","els","PAPER_PRESETS","getPaperDimensions","MIN_SCALE_PERCENT","FIT_SCALE_MIN_PERCENT","clampScalePercent","percent","nextWheelScale","direction","factor","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","a","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","showRuler","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","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","_createElementBlock","$emit","_createElementVNode","_useModel","__props","_openBlock","_hoisted_1","_hoisted_2","_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","_createVNode","HelpButton","_hoisted_15","_hoisted_16","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","FieldTreePanel","LayerPanel","d","RULER_THICKNESS","STEP_SEQUENCE","chooseMajorStepMM","targetPx","pxPerMM","minorStepMM","majorStepMM","exp","roundMM","buildRulerTicks","startMM","endMM","fine","lastIndex","ticks","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","V_ALIGN_FLEX","H_ALIGN_FLEX","textStyle","o","displayText","imageSrc","raw","hasError","onError","watch","imgStyle","ROW_TYPES","emitAction","payload","_createBlock","_Teleport","barcodeSvg","svgOk","dataUrl","svgStyle","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","imageData","isCodeCell","cellDisplay","_row","cellStyle","borderOpts","cellClass","dragAnchor","applySelection","onCellMouseDown","onCellMouseEnter","onCellDblClick","menu","reactive","onCellContextMenu","mergeReason","canSplit","rowTypeReason","cloned","syncElementSize","checkColWidthLimit","cw","maxW","onMenuAction","err","colResizeEnabled","colResizeBoundaries","colBoundaryLeftMm","colResizeBoundary","resizeStartX","resizeStartWidth","onColResizeStart","onColResizeMove","onColResizeEnd","deltaMm","colIndex","widths","_withModifiers","CellBarcode","CellImage","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","contentComponent","contentAttrs","elementStyle","posLabel","dragStartLeft","dragStartTop","dragConfig","info","finalDx","finalDy","sibling","setupDrag","cleanupDrag","watchEffect","resizeEnabled","cleanupResize","onDblClick","onDblClickCell","elementId","_unref","_resolveDynamicComponent","_mergeProps","p","useAdsorb","config","adsorbMin","adsorbLineMin","showAdsorbLine","guideLines","paperSize","SNAP_COLORS","snapColor","check","movingRect","lines","minDist","other","hPairs","vPairs","ok","dist","m2","hKeys","vKeys","adjustedM","seen","renderLines","clearLines","useAdsorbManager","requestAdsorb","clearGuides","contentRef","paperWidthMM","paperHeightMM","guideHitPx","wrapperStyle","widthPx","heightPx","zoneRectsMM","layerStyle","zoneElements","headerElements","footerElements","contentElements","currentDragZone","rawRequestAdsorb","guidePaperSize","showSnapIndicator","onGuideDown","startPt","MM_PER_PX","onMove","ev","delta","maxPosition","nextPosition","onUp","paperStyle","contentStyle","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","BaseElement","line","idx","horizontal","guideType","canvasRef","hoverPx","effectiveCursorPx","cssSize","rafId","scheduleDraw","draw","canvas","dpr","length","thickness","style","bg","fg","accent","majorStep","drawTicks","drawPaperEdge","cursor","outside","tick","onBeforeUnmount","dragging","axialFromEvent","along","onDown","onWinMove","onWinUp","updateDragPreview","onHoverMove","onHoverLeave","rootRef","rulerGeom","rulerCursor","scrollPos","overlayStyle","measureRuler","area","ar","pr","targetScale","measuredScale","onScroll","resizeObserver","scaleMeasureRaf","startScaleMeasureLoop","endAt","loop","guidePreview","onGuideDragging","guidePreviewStyle","liveScale","toPaperPoint","onDrop","fieldData","elementType","marquee","marqueeStart","isCanvasBackground","areaRect","xMm","yMm","onMouseLeave","onWheel","oldScale","oldPercent","newPercent","newScale","container","anchor","padX","padY","nextTick","targetPercent","mouseX","mouseY","ax","ay","cs2","padX2","padY2","onCanvasMouseDown","onMarqueeMove","onMarqueeUp","hitTestIds","paperRect","containMode","elLeft","elTop","elRight","elBottom","inter","contained","contextMenu","onContextMenu","elId","containerRect","closeContextMenu","handlePaste","handleSelectAll","handleClearSelection","action","centerScroll","stableFrames","prevSW","prevSH","deadline","sw","sh","sw2","sh2","ch","CanvasPaper","Ruler","PROPERTY_REGISTRY","matchKeywords","search","keywords","searchProperties","itemKeys","matched","onSearch","isExpanded","iconChar","toggle","saveState","loadState","saved","_renderSlot","_ctx","precision","roundTo","current","draft","atMin","atMax","clamp","stepBy","dir","onInput","commit","_withKeys","showItem","PropertyGroup","StepperInput","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","onAreaKeydown","handled","close","open","trigger","panelWidth","panelHeight","margin","below","onDocumentPointerDown","onWindowCloseEvents","onKeydown","match","hex","full","part","red","green","blue","hh","r1","g1","b1","number","isTableType","PresetColorPicker","_hoisted_17","_hoisted_18","val","searchPlaceholder","localExpression","handleFieldDoubleClick","insideParens","getCursorRegion","insertAtCursor","handleVariableDoubleClick","sv","handleFunctionDoubleClick","insideBlock","caretOffset","textareaRef","lastBlockOpen","lastParenOpen","filteredSystemVars","systemVars","filteredAggregateFuncs","aggregateFunctions","filteredFormatFuncs","formatFunctions","previewResult","ta","end","after","caretPos","onConfirm","_hoisted_19","_hoisted_20","_hoisted_22","_hoisted_23","_hoisted_24","_hoisted_25","_hoisted_27","_hoisted_28","_hoisted_29","_hoisted_30","_hoisted_31","_hoisted_32","_hoisted_33","editorVisible","openEditor","ExpressionEditor","tableEditCtx","listFieldOptions","onSourceChange","onColWidthChange","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","isImageCell","onAlignChange","write","onValignChange","onCellTypeChange","openFormatterEditor","onFormatterEditorConfirm","borderStyle","borderWidth","borderColor","edgeChecks","currentBorder","onEdgesChange","edges","nb","side","doMerge","doSplit","_hoisted_21","_hoisted_35","_hoisted_37","_hoisted_39","_hoisted_40","_hoisted_42","_hoisted_43","_hoisted_45","_hoisted_46","_hoisted_47","_hoisted_48","_hoisted_49","_hoisted_50","_hoisted_51","_hoisted_52","_hoisted_53","_hoisted_54","_hoisted_55","_hoisted_56","_hoisted_58","_hoisted_59","_hoisted_60","ELEMENT_BINDING_REGISTRY","getTableCellBindings","rowType","rowIndex","cellIndex","listField","getElementBindings","element","staticBindings","dynamicBindings","paperPresets","isTextType","isImageType","isTableCellSelected","searchResult","matchedKeys","bindingDescriptors","c1","parsePath","targetPath","segment","baseName","indices","getBindingValue","setBindingValue","segments","lastKey","obj","onImageUploadSuccess","paperSizeModel","orientationModel","pageBackgroundModel","onPageBackgroundChange","marginTop","marginBottom","marginLeft","marginRight","headerHeight","footerHeight","overlayHeight","customWidth","customHeight","emitUpdate","onPaperSizeChange","onOrientationChange","onPageBackgroundReset","onCustomWidthChange","onCustomHeightChange","onMarginTopChange","onMarginBottomChange","onMarginLeftChange","onMarginRightChange","onHeaderHeightChange","onFooterHeightChange","onOverlayHeightChange","currentTab","PropertySearch","PositionSizeGroup","AppearanceGroup","desc","BindingControl","ImageContentUpload","TableRowGroup","TableCellGroup","TableSettingsGroup","BorderBgGroup","PaginationGroup","AdvancedGroup","_ps","_hoisted_26","gettingStarted","features","shortcuts","faq","changelog","helpSections","STORAGE_KEY","sections","switchTab","tabId","currentContent","handleKeydown","_Transition","section","LEFT_KEY","RIGHT_KEY","readStored","fallback","useStudioChrome","leftCollapsed","rightCollapsed","dirty","toggleLeft","toggleRight","markSaved","helpVisible","onUndo","onRedo","onAlign","onGroup","onUngroup","onDeleteElement","onDragStop","onDropElement","onDropField","onMoveLayer","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","HelpModal","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","rowHeights","SVG_NS","renderBarcodeSvg","renderQrSvg","level","modules","quiet","browserCodeRenderer","cellType","iframeRef","rendering","errorMsg","renderSeq","rerender","html","pageCount","print"],"mappings":"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"}
|