@worm-vue3-print/canvas 1.3.0 → 1.3.2
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/dist/canvas.css +1 -1
- package/dist/components/CanvasArea.vue.d.ts +0 -5
- package/dist/components/LayerPanel.vue.d.ts +4 -0
- package/dist/components/LeftPanel.vue.d.ts +4 -0
- package/dist/index.cjs +90 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +3692 -3531
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/composables/useSelection.ts","../src/composables/useClipboard.ts","../src/composables/useHistory.ts","../src/composables/useDesignerState.ts","../src/composables/useGuides.ts","../src/composables/useTableSelection.ts","../src/composables/useHostAdapter.ts","../src/composables/useFontCatalog.ts","../src/composables/useDocumentFontFace.ts","../src/components/HelpButton.vue","../src/components/DesignerToolbar.vue","../src/components/LayerPanel.vue","../src/components/FieldTreePanel.vue","../src/components/LeftPanel.vue","../src/composables/useDrag.ts","../src/composables/useShrinkFit.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/components/property/PropertySearch.vue","../src/components/property/PropertyGroup.vue","../src/components/property/StepperInput.vue","../src/components/property/PositionSizeGroup.vue","../src/components/PresetColorPicker.vue","../src/components/property/FontSelect.vue","../src/components/property/AppearanceGroup.vue","../src/components/property/CodeGroup.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/components/WatermarkConfig.vue","../src/components/property/DesignBackgroundConfig.vue","../src/components/property/TilingConfig.vue","../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/components/PageTabs.vue","../src/composables/useStudioChrome.ts","../src/components/PrintDesigner.vue","../src/components/PrintHtmlPreview.vue"],"sourcesContent":["// web/src/components/print/composables/useSelection.ts\nimport { ref, computed, type InjectionKey, type Ref } from 'vue'\nimport type { RuntimeElement } from '@worm-vue3-print/core/designer'\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 '@worm-vue3-print/core/designer'\nimport { generateId, generateGroupId } from '@worm-vue3-print/core/designer'\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 // 组 ID 重映射:粘贴副本绝不能与原组共用 groupId,否则拖一个全跟着动、无法拆分。\n // 仅当同一组在本次粘贴中出现 ≥2 个成员时才保留成组(分配新 ID);\n // 只复制了组内单个成员的,剥离 groupId,避免残留无意义的组身份。\n const groupCounts = new Map<string, number>()\n for (const item of clipboard.value) {\n const gid = item.options.groupId\n if (gid) groupCounts.set(gid, (groupCounts.get(gid) ?? 0) + 1)\n }\n const groupIdMap = new Map<string, string | undefined>()\n for (const [gid, count] of groupCounts) {\n groupIdMap.set(gid, count >= 2 ? generateGroupId() : undefined)\n }\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 groupId: item.options.groupId\n ? groupIdMap.get(item.options.groupId)\n : undefined,\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/useHistory.ts\nimport { ref } from 'vue'\nimport type { TemplateData } from '@worm-vue3-print/core/designer'\n\nexport interface HistoryState {\n elements: any[]\n templateData?: TemplateData\n /** 多页面快照:整份页面数组(深拷贝) */\n pages?: TemplateData[]\n /** 多页面快照:录制时的激活页索引 */\n activePageIndex?: number\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 const cloned: HistoryState = {\n elements: JSON.parse(JSON.stringify(state?.elements ?? [])),\n templateData: JSON.parse(JSON.stringify(state?.templateData ?? {})),\n }\n if (state?.pages) {\n cloned.pages = JSON.parse(JSON.stringify(state.pages))\n if (state.activePageIndex !== undefined) cloned.activePageIndex = state.activePageIndex\n }\n return cloned\n }\n\n /** 增量快照:只记录元素变更,templateData 只记录非 elements 部分 */\n function cloneIncremental(state: HistoryState): HistoryState {\n const clonedElements = JSON.parse(JSON.stringify(state.elements))\n const result: HistoryState = { elements: clonedElements }\n if (state.pages) {\n result.pages = JSON.parse(JSON.stringify(state.pages))\n if (state.activePageIndex !== undefined) result.activePageIndex = state.activePageIndex\n }\n const td = state.templateData\n if (td) {\n result.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 return result\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/useDesignerState.ts\n// 设计器核心状态管理:模板数据/选择/历史/剪贴板/编组/键盘/序列化\nimport { ref, computed, onMounted, onUnmounted } from 'vue'\nimport type {\n RuntimeElement, ElementType, ElementZone, PrintBusinessField, TemplateData,\n TableSelection, PrintElementData, MultiPageTemplateData,\n} from '@worm-vue3-print/core/designer'\nimport { createRuntimeElement, generateId } from '@worm-vue3-print/core/designer'\nimport { createFieldElement } from '@worm-vue3-print/core/designer'\nimport { normalizeTemplateUnits } from '@worm-vue3-print/core/designer'\nimport { syncTableElementSize } from '@worm-vue3-print/core/designer'\nimport { getPaperDimensions } from '@worm-vue3-print/core/designer'\nimport { computeFitScale } from '@worm-vue3-print/core/designer'\nimport {\n getZoneRects, zoneFromPaperPoint, clampToZone, finalizeElementZone, ZONE_ALLOWED_TYPES,\n} from '@worm-vue3-print/core/designer'\nimport { useSelection } from './useSelection'\nimport { useClipboard } from './useClipboard'\nimport { useAlign, type AlignMode } from '@worm-vue3-print/core/designer'\nimport { useGroup } from '@worm-vue3-print/core/designer'\nimport { useHistory, type HistoryState } from './useHistory'\nimport { useKeyboard } from '@worm-vue3-print/core/designer'\n\nexport interface DesignerStateOptions {\n initialTemplate?: TemplateData | MultiPageTemplateData\n initialElements?: RuntimeElement[]\n initialFields?: PrintBusinessField[]\n}\n\n/** 拼版模板只允许单页:增页入口(新增/复制)被拦截时的提示文案 */\nexport const TILING_SINGLE_PAGE_TIP = '开启拼版后只能有一个设计页面'\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\n/** 解析初始模板为运行时页面池:多页 wrapper 展开,单页归一为单元素数组 */\nfunction resolveInitialPages(initial?: TemplateData | MultiPageTemplateData): TemplateData[] {\n const withDefaultName = (p: TemplateData, i: number): TemplateData => {\n const rt = toRuntimePool(normalizeTemplateUnits(p))\n // 无名页面补存固定默认名:页签显示若依赖位置回退(页面 ${i+1}),\n // 页面重排后索引变化会导致页签名漂移并与已存储页名重名(如「页面 1」变「页面 2」)\n if (!rt.name) rt.name = `页面 ${i + 1}`\n return rt\n }\n if (!initial) return [withDefaultName(createDefaultTemplate(), 0)]\n const list = Array.isArray((initial as MultiPageTemplateData).pages)\n ? (initial as MultiPageTemplateData).pages\n : [initial as TemplateData]\n return list.length ? list.map(withDefaultName) : [withDefaultName(createDefaultTemplate(), 0)]\n}\n\n/** 单页运行时池序列化回三区模板 JSON(按 zone 拆回,补 id/type) */\nfunction serializePage(page: TemplateData): TemplateData {\n const all = page.elements as RuntimeElement[]\n const ser = (zone: ElementZone) => all\n .filter(e => (e.zone || 'content') === zone)\n .map(e => ({ id: e.id, type: e.printElementType.type, options: { ...e.options }, printElementType: { ...e.printElementType } }))\n return {\n unit: 'mm' as const, ...page,\n header: { ...page.header, elements: ser('header') },\n footer: { ...page.footer, elements: ser('footer') },\n firstPageOverlay: {\n ...page.firstPageOverlay,\n elements: (page.firstPageOverlay?.elements ?? []).map(e => ({\n id: e.id || generateId(), type: e.printElementType?.type || 'text',\n options: { ...e.options }, printElementType: { ...e.printElementType },\n })),\n },\n elements: ser('content'),\n guides: [...(page.guides ?? [])],\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 // 多页面模板:pages 列表 + 当前激活页\n const pages = ref<TemplateData[]>(resolveInitialPages(options.initialTemplate))\n const activePageIndex = ref(0)\n const templateData = ref<TemplateData>(pages.value[0] ?? toRuntimePool(createDefaultTemplate()))\n\n /** 拼版开关:任一页开启拼版即视为拼版模板。拼版按「一张纸铺多个标签」排版,与多页面互斥 */\n const tilingEnabled = computed(() => pages.value.some(p => p.tiling?.enabled === true))\n\n /**\n * 拼版模板的单页闸门:拦截新增/复制页面并提示,避免用户拼出非法多页拼版模板。\n * 返回 true 表示已拦截,调用方应直接 return。\n */\n function blockPageAddIfTiling(): boolean {\n if (!tilingEnabled.value) return false\n alert(TILING_SINGLE_PAGE_TIP)\n return true\n }\n\n function flushActivePage() {\n pages.value[activePageIndex.value] = templateData.value\n }\n\n function switchPage(i: number) {\n if (i < 0 || i >= pages.value.length) return\n flushActivePage()\n activePageIndex.value = i\n templateData.value = pages.value[i]!\n resetPageSelection()\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, getGroupedIds } = 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 resetPageSelection() {\n clearSelection()\n setTableSelection(null)\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 outputRotation: templateData.value.outputRotation,\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 pages: JSON.parse(JSON.stringify(pages.value)),\n activePageIndex: activePageIndex.value,\n }\n }\n\n function recordHistory() {\n pushHistory(getHistoryState())\n }\n\n /** 从历史快照取「激活页」元素(多页读 pages[activePageIndex],单页回退 elements) */\n function historyActiveElements(state: HistoryState): any[] {\n return state.pages?.[state.activePageIndex ?? 0]?.elements ?? state.elements\n }\n\n function undo() {\n const state = undoHistory(getHistoryState())\n if (state?.pages) {\n pages.value = state.pages\n activePageIndex.value = state.activePageIndex ?? 0\n templateData.value = pages.value[activePageIndex.value] ?? pages.value[0]!\n resetPageSelection()\n } else 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?.pages) {\n pages.value = state.pages\n activePageIndex.value = state.activePageIndex ?? 0\n templateData.value = pages.value[activePageIndex.value] ?? pages.value[0]!\n resetPageSelection()\n } else 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 /**\n * 画布/图层面板点击选择:普通点击组内任一成员 → 选中整组;\n * Ctrl/⌘ 多选仍按单元素切换,不做整组扩展。\n */\n function selectElement(id: string, multiple = false) {\n if (multiple) {\n select(id, true)\n return\n }\n selectedIds.value = new Set(getGroupedIds(elements.value, id))\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 = historyActiveElements(draggingBeforeState).map(sig).join('|')\n const afterIds = historyActiveElements(getHistoryState()).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 // 收敛引用:templateData 被重新赋值后同步回 pages,避免 renamePage 等原地改丢失\n pages.value[activePageIndex.value] = templateData.value\n if (pages.value.length > 1) {\n const paper = {\n paperSize: data.paperSize, orientation: data.orientation,\n outputRotation: data.outputRotation,\n customWidth: data.customWidth, customHeight: data.customHeight,\n }\n for (const p of pages.value) Object.assign(p, paper)\n }\n recordHistory()\n }\n\n /** 当前设计器状态序列化为模板 JSON(单一出口:多页出 wrapper,单页出裸值) */\n function getTemplateJson(): TemplateData | MultiPageTemplateData {\n flushActivePage()\n if (pages.value.length <= 1) return serializePage(pages.value[0]!)\n return { version: 1, pages: pages.value.map(serializePage) }\n }\n\n /** 加载模板数据(多页 wrapper 展开;三区合并进运行时元素池;旧数据按 pt 迁移为 mm) */\n function loadTemplate(data: TemplateData | MultiPageTemplateData, els?: RuntimeElement[]) {\n pages.value = resolveInitialPages(data)\n activePageIndex.value = 0\n templateData.value = pages.value[0]!\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 // 收敛引用:templateData 被重新赋值后同步回 pages[0]\n pages.value[activePageIndex.value] = templateData.value\n }\n pushHistory(getHistoryState())\n }\n\n /** 新增页默认名:从「页面 N」递增取第一个未被占用的名字,避免与现存页重名 */\n function nextDefaultPageName(): string {\n const used = new Set(pages.value.map(p => p.name))\n let n = pages.value.length + 1\n while (used.has(`页面 ${n}`)) n++\n return `页面 ${n}`\n }\n\n /** 新增页面:继承当前页纸张,激活并定位到新页;开启拼版时禁止增页 */\n function addPage() {\n if (blockPageAddIfTiling()) return\n flushActivePage()\n const base = pages.value[activePageIndex.value] ?? createDefaultTemplate()\n const np = toRuntimePool({\n ...createDefaultTemplate(),\n paperSize: base.paperSize, orientation: base.orientation,\n customWidth: base.customWidth, customHeight: base.customHeight,\n name: nextDefaultPageName(),\n })\n pages.value.push(np)\n activePageIndex.value = pages.value.length - 1\n templateData.value = np\n resetPageSelection()\n recordHistory()\n }\n\n /** 复制当前页:重建元素 id 避免同文档冲突,插入当前页之后并激活;开启拼版时禁止增页 */\n function duplicatePage() {\n if (blockPageAddIfTiling()) return\n flushActivePage()\n const src = pages.value[activePageIndex.value]!\n const cp: TemplateData = JSON.parse(JSON.stringify(src))\n cp.name = `${src.name ?? `页面 ${activePageIndex.value + 1}`} 副本`\n cp.elements = cp.elements.map((e: any) => ({ ...e, id: generateId() }))\n cp.firstPageOverlay = { ...cp.firstPageOverlay, elements: (cp.firstPageOverlay?.elements ?? []).map((e: any) => ({ ...e, id: generateId() })) }\n pages.value.splice(activePageIndex.value + 1, 0, cp)\n switchPage(activePageIndex.value + 1)\n recordHistory()\n }\n\n function deletePage(i: number) {\n if (pages.value.length <= 1) return\n flushActivePage()\n pages.value.splice(i, 1)\n if (i < activePageIndex.value) activePageIndex.value--\n else if (i === activePageIndex.value && activePageIndex.value >= pages.value.length) activePageIndex.value = pages.value.length - 1\n templateData.value = pages.value[activePageIndex.value]!\n resetPageSelection()\n recordHistory()\n }\n\n function renamePage(i: number, name: string) {\n if (pages.value[i]) pages.value[i].name = name\n }\n\n function movePage(from: number, to: number) {\n if (from === to) return\n flushActivePage()\n const [moved] = pages.value.splice(from, 1)\n pages.value.splice(to, 0, moved!)\n activePageIndex.value = to\n templateData.value = moved!\n resetPageSelection()\n recordHistory()\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, tilingEnabled,\n pages, activePageIndex, switchPage, addPage, duplicatePage, deletePage, renamePage, movePage,\n selectedIds, selectedElements, selectedElement, select, selectElement, 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 '@worm-vue3-print/core/designer'\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 '@worm-vue3-print/core/designer'\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 { UploadDesignBackgroundFn, UploadImageFn } from '@worm-vue3-print/core/designer'\nimport type { FontOption } from './useFontCatalog'\n\n/** 图片上传适配器:PrintDesigner provide,ImageContentUpload inject */\nexport const UPLOAD_IMAGE_KEY: InjectionKey<ComputedRef<UploadImageFn | undefined>> =\n Symbol('print-upload-image')\n\n/** 设计背景上传适配器:PrintDesigner provide,DesignBackgroundConfig inject */\nexport const UPLOAD_DESIGN_BACKGROUND_KEY: InjectionKey<ComputedRef<UploadDesignBackgroundFn | undefined>> =\n Symbol('print-upload-design-background')\n\n/** 字体目录(模板声明字体):PrintDesigner provide,属性面板 inject */\nexport const FONT_CATALOG_KEY: InjectionKey<ComputedRef<readonly FontOption[]>> =\n Symbol('print-font-catalog')\n","// 字体下拉的数据源:模板级字体声明(宿主经 PrintDesigner 的 fonts prop 传入)。\n// 声明随模板保存、由各端按 @font-face 加载,设计器不查询任何出图端的系统字体。\nimport { computed, inject, toValue, type ComputedRef, type MaybeRefOrGetter } from 'vue'\nimport type { PrintFontDeclaration } from '@worm-vue3-print/core'\nimport { FONT_CATALOG_KEY } from './useHostAdapter'\n\n/** 下拉候选项:family 写入模板,label 仅用于界面展示 */\nexport interface FontOption {\n family: string\n label?: string\n}\n\n/** 空目录:宿主未声明字体时的兜底 */\nexport const EMPTY_FONT_CATALOG: ComputedRef<readonly FontOption[]> = computed(() => [])\n\n/**\n * 由 PrintDesigner 调用:把模板字体声明整理为下拉候选项。\n * 去空白、丢空值、族名大小写不敏感去重,保留声明顺序(顺序即宿主期望的优先级)。\n */\nexport function useFontCatalog(\n declarations?: MaybeRefOrGetter<readonly PrintFontDeclaration[] | undefined>,\n): { catalog: ComputedRef<readonly FontOption[]> } {\n const catalog = computed<readonly FontOption[]>(() => {\n const out: FontOption[] = []\n const seen = new Set<string>()\n for (const font of toValue(declarations) ?? []) {\n const family = font?.family?.trim()\n if (!family) continue\n const key = family.toLowerCase()\n if (seen.has(key)) continue\n seen.add(key)\n const label = font.label?.trim()\n out.push(label ? { family, label } : { family })\n }\n return out\n })\n return { catalog }\n}\n\n/** 由深层组件调用(属性面板):未注入时回退空目录,组件可独立挂载 */\nexport function useInjectedFontCatalog(): ComputedRef<readonly FontOption[]> {\n return inject(FONT_CATALOG_KEY, EMPTY_FONT_CATALOG)\n}\n\n/** 在目录中按族名查找(大小写不敏感) */\nexport function findFontOption(\n fonts: readonly FontOption[],\n family?: string,\n): FontOption | undefined {\n const key = family?.trim().toLowerCase()\n if (!key) return undefined\n return fonts.find(f => f.family.trim().toLowerCase() === key)\n}\n\n/** 下拉选项文案:有展示名时补上真实族名(写入模板的值) */\nexport function fontOptionLabel(option: FontOption): string {\n return option.label ? `${option.label}(${option.family})` : option.family\n}\n\n/** 匹配用键:小写并去掉全部空白,使用户输入 `ya hei` 与 `yahei` 等价 */\nexport function normalizeFontQuery(value: string): string {\n return value.toLowerCase().replace(/\\s+/g, '')\n}\n\n/**\n * 匹配档位,越小越靠前:\n * 0 完全相等 · 1 前缀 · 2 子串 · 3 子序列(首字母缩写式) · -1 不匹配\n */\nfunction matchRank(nameKey: string, queryKey: string): number {\n if (nameKey === queryKey) return 0\n if (nameKey.startsWith(queryKey)) return 1\n if (nameKey.includes(queryKey)) return 2\n let cursor = 0\n for (const char of nameKey) {\n if (char === queryKey[cursor]) cursor++\n if (cursor === queryKey.length) return 3\n }\n return -1\n}\n\n/**\n * 模糊过滤字体目录:完全相等 > 前缀 > 子串 > 子序列,同档保持目录原有顺序\n * (目录顺序由宿主声明决定,过滤不应打乱)。\n * 族名与展示名(label)都参与匹配,设计者按业务名搜也能命中。\n */\nexport function filterFontOptions(\n fonts: readonly FontOption[],\n query: string,\n): FontOption[] {\n const queryKey = normalizeFontQuery(query.trim())\n if (!queryKey) return [...fonts]\n return fonts\n .map((font, index) => ({ font, index, rank: fontMatchRank(font, queryKey) }))\n .filter(item => item.rank >= 0)\n .sort((a, b) => a.rank - b.rank || a.index - b.index)\n .map(item => item.font)\n}\n\n/** 族名与展示名取更优的一档;两者都不命中返回 -1 */\nfunction fontMatchRank(font: FontOption, queryKey: string): number {\n const byFamily = matchRank(normalizeFontQuery(font.family), queryKey)\n if (!font.label) return byFamily\n const byLabel = matchRank(normalizeFontQuery(font.label), queryKey)\n if (byFamily < 0) return byLabel\n return byLabel < 0 ? byFamily : Math.min(byFamily, byLabel)\n}\n","// 把模板声明字体的 @font-face 注入设计器所在文档:\n// 否则画布只能用系统字体渲染,出图却用模板的 webfont,所见非所得。\nimport { onUnmounted, toValue, useId, watchEffect, type MaybeRefOrGetter } from 'vue'\n\nconst STYLE_ID_PREFIX = 'print-designer-font-face'\n\nexport function useDocumentFontFace(css: MaybeRefOrGetter<string>): void {\n // 每实例唯一,多个设计器同页时不产生重复 id(与 FontSelect 的列表 id 同一处理)\n const styleId = `${STYLE_ID_PREFIX}-${useId()}`\n let el: HTMLStyleElement | undefined\n\n watchEffect(() => {\n const text = toValue(css)\n if (!text) {\n el?.remove()\n el = undefined\n return\n }\n if (!el) {\n el = document.createElement('style')\n el.id = styleId\n document.head.appendChild(el)\n }\n el.textContent = text\n })\n\n onUnmounted(() => {\n el?.remove()\n el = undefined\n })\n}\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 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 /** 是否展示帮助入口(工具栏帮助按钮);默认开启,传 false 关闭 */\n showHelp?: boolean\n}>(), {\n showRuler: true,\n showHelp: true,\n})\n\ndefineEmits<{\n preview: []\n save: []\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 '@worm-vue3-print/core/designer'\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","<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 '@worm-vue3-print/core/designer'\nimport { groupFields, filterGroups } from '@worm-vue3-print/core/designer'\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 '@worm-vue3-print/core/designer'\nimport LayerPanel from './LayerPanel.vue'\nimport FieldTreePanel from './FieldTreePanel.vue'\n\ndefineProps<{\n fields: PrintBusinessField[]\n elements: RuntimeElement[]\n selectedIds: Set<string>\n collapsed: boolean\n}>()\n\nconst emit = defineEmits<{\n select: [id: string, multiple: boolean]\n 'move-layer': [direction: string]\n 'toggle-visible': [id: string]\n 'toggle-locked': [id: string]\n 'field-drag': [field: PrintBusinessField]\n 'toggle-collapse': []\n}>()\n\nconst activeTab = ref('elements')\n\nconst elementTypes: { type: ElementType; label: string; icon: string }[] = [\n { type: 'text', label: '文本', icon: 'T' },\n { type: 'barcode', label: '条形码', icon: '▍▍' },\n { type: 'qrcode', label: '二维码', icon: '▦' },\n { type: 'image', label: '图片', icon: '▧' },\n { type: 'table', label: '表格', icon: '⊞' },\n { type: 'longText', label: '长文', icon: '¶' },\n { type: 'hline', label: '横线', icon: '―' },\n { type: 'vline', label: '竖线', icon: '│' },\n { type: 'rect', label: '矩形', icon: '▭' },\n { type: 'oval', label: '椭圆', icon: '◯' },\n { type: 'html', label: 'HTML', icon: '<>' },\n]\n\nfunction onDragStart(event: DragEvent, type: string) {\n event.dataTransfer?.setData('elementType', type)\n}\n\nfunction onFieldDrag(field: PrintBusinessField) {\n emit('field-drag', field)\n}\n\nfunction expandTab(tab: string) {\n activeTab.value = tab\n emit('toggle-collapse')\n}\n</script>\n\n<style scoped>\n.left-panel {\n width: 224px;\n min-width: 224px;\n background: var(--pd-sidebar, #ffffff);\n border-right: 1px solid var(--pd-border-soft, #e9ecf2);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n transition: width .18s ease;\n}\n.left-panel.collapsed {\n width: 36px;\n min-width: 36px;\n border-right: 1px solid var(--pd-border-soft, #e9ecf2);\n}\n.left-collapsed {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n padding-top: 12px;\n flex: 1;\n}\n.lc-btn {\n width: 26px;\n height: 26px;\n border-radius: 6px;\n border: 1px solid transparent;\n background: transparent;\n color: var(--pd-text-muted, #8b909c);\n font-size: 12px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all .14s ease;\n}\n.lc-btn:hover {\n color: var(--pd-text, #2a2e37);\n background: var(--pd-sidebar-hover, #f0f3f9);\n}\n.lc-btn.on {\n color: var(--pd-accent, #165DFF);\n background: var(--pd-accent-soft, rgba(22, 93, 255, .09));\n}\n.left-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n height: 42px;\n padding: 0 12px;\n flex-shrink: 0;\n border-bottom: 1px solid var(--pd-border-soft, #e9ecf2);\n}\n.left-title {\n font-size: 12px;\n font-weight: 600;\n color: var(--pd-text, #2a2e37);\n letter-spacing: 1.2px;\n display: inline-flex;\n align-items: center;\n gap: 7px;\n}\n.left-title::before {\n content: \"\";\n width: 3px;\n height: 12px;\n border-radius: 2px;\n background: linear-gradient(180deg, var(--pd-accent-2, #3D7BFF), var(--pd-accent, #165DFF));\n}\n.collapse-btn {\n border: none;\n background: transparent;\n color: var(--pd-text-muted, #8b909c);\n font-size: 14px;\n cursor: pointer;\n width: 24px;\n height: 24px;\n border-radius: 5px;\n transition: all .14s ease;\n}\n.collapse-btn:hover {\n color: var(--pd-text, #2a2e37);\n background: var(--pd-sidebar-hover, #f0f3f9);\n}\n.left-tabs {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n.left-tabs .pd-tab-pane {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n padding: 12px;\n}\n.panel-title {\n font-size: 11px;\n color: var(--pd-text-muted, #8b909c);\n letter-spacing: .6px;\n padding: 2px 2px 8px;\n margin-bottom: 10px;\n border-bottom: 1px solid var(--pd-border-soft, #e9ecf2);\n}\n.material-card {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 8px 10px;\n margin-bottom: 7px;\n border: 1px solid var(--pd-border-soft, #e9ecf2);\n border-radius: 8px;\n background: var(--pd-field-bg, #f4f6fa);\n cursor: grab;\n user-select: none;\n transition: border-color .14s ease, background .14s ease, transform .14s ease, box-shadow .14s ease;\n}\n.material-card:hover {\n border-color: rgba(22, 93, 255, .45);\n background: var(--pd-surface, #ffffff);\n transform: translateY(-1px);\n box-shadow: var(--pd-shadow-sm, 0 1px 2px rgba(23, 32, 60, .05));\n}\n.material-card:active {\n cursor: grabbing;\n transform: translateY(0);\n}\n.material-icon {\n width: 30px;\n height: 24px;\n border: 1px dashed var(--pd-border, #d9dde6);\n border-radius: 5px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 11px;\n color: var(--pd-accent, #165DFF);\n background: var(--pd-surface, #ffffff);\n flex-shrink: 0;\n transition: border-color .14s ease, background .14s ease;\n}\n.material-card:hover .material-icon {\n border-style: solid;\n border-color: var(--pd-accent, #165DFF);\n background: var(--pd-accent-soft, rgba(22, 93, 255, .09));\n}\n.material-label {\n font-size: 12.5px;\n color: var(--pd-text, #2a2e37);\n}\n</style>\n","// web/src/components/print/composables/useDrag.ts\nimport { ref } from 'vue'\nimport type { AdsorbResult } from '@worm-vue3-print/core/designer'\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 // 仅响应左键,右键/中键不启动拖拽(右键由 contextmenu 处理)\n if (e.button !== 0) return\n // 忽略 resize 手柄点击;条码等 SVG 元素的 e.target 是 SVGElement,需一并放行(classList 在 Element 基类上)\n const targetEl = e.target\n if (!(targetEl instanceof Element) || 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","// 自动缩小(textFit='shrink')在画布上的落地:\n// 与打印管线共用 core 的 fitTextNode(同一套二分算法),\n// 使「设计态看到的字号」就是「出纸的字号」,不出现预览/出纸两副面孔。\nimport { nextTick, onMounted, watchEffect, type Ref } from 'vue'\nimport { fitTextNode } from '@worm-vue3-print/core/browser'\n\n/** 容器自身(元素级缩小)与后代(单元格级缩小)中所有缩放下限节点 */\nfunction fitTargets(root: HTMLElement): HTMLElement[] {\n const targets: HTMLElement[] = []\n if (root.getAttribute('data-fit') === 'shrink') targets.push(root)\n root.querySelectorAll<HTMLElement>('[data-fit=\"shrink\"]').forEach(node => targets.push(node))\n return targets\n}\n\n/**\n * 复原:曾被缩过(data-fit-size)但当前已不在缩小模式的节点,把字号写回基准值。\n * 不做这一步,从「自动缩小」切回「截断」时会残留上一次缩小后的字号。\n */\nfunction restoreFitted(root: HTMLElement): void {\n root.querySelectorAll<HTMLElement>('[data-fit-size]').forEach(node => {\n if (node.getAttribute('data-fit') === 'shrink') return\n node.removeAttribute('data-fit-size')\n const base = node.getAttribute('data-fit-base')\n if (base) node.style.fontSize = `${base}pt`\n else node.style.removeProperty('font-size')\n })\n}\n\n/**\n * @param root 元素根节点(元素级缩小挂在根上,单元格级挂在根的后代上)\n * @param trigger 依赖采集:字号/尺寸/内容/模式变化时重新适配\n */\nexport function useShrinkFit(root: Ref<HTMLElement | null>, trigger: () => unknown): void {\n const apply = (): void => {\n const el = root.value\n if (!el) return\n fitTargets(el).forEach(fitTextNode)\n restoreFitted(el)\n }\n // flush: 'post' 保证在 DOM 更新后测量;Vue 只在绑定值变化时重写内联样式,不会冲掉适配结果\n watchEffect(() => {\n void trigger()\n void nextTick(apply)\n }, { flush: 'post' })\n onMounted(() => {\n void nextTick(apply)\n })\n}\n","<template>\n <div\n ref=\"rootRef\"\n class=\"print-text\"\n :style=\"textStyle\"\n :data-fit=\"fit === 'shrink' ? 'shrink' : undefined\"\n :data-fit-base=\"String(baseFontSize)\"\n :data-fit-min=\"String(fitMinPt)\"\n >\n {{ displayText }}\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport type { RuntimeElement } from '@worm-vue3-print/core/designer'\nimport { resolveTextBinding } from '@worm-vue3-print/core/designer'\nimport { resolveElementTextFit, resolveShrinkMinFontSize } from '@worm-vue3-print/core/designer'\nimport { useShrinkFit } from '../../composables/useShrinkFit'\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 rootRef = ref<HTMLElement | null>(null)\n\n/** 溢出显示形式:截断 / 自动缩小 / 自适应行高(未配置时文本元素默认截断) */\nconst fit = computed(() => resolveElementTextFit('text', props.element.options))\nconst baseFontSize = computed(() => props.element.options.fontSize || 12)\nconst fitMinPt = computed(() => resolveShrinkMinFontSize(props.element.options.shrinkMinFontSize))\n\nconst textStyle = computed(() => {\n const o = props.element.options\n const autoHeight = fit.value === 'autoHeight'\n return {\n fontSize: baseFontSize.value + '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 // 自适应行高:不锁定高度,内容撑开;其余形式锁高度并裁剪\n height: autoHeight ? 'auto' : '100%',\n boxSizing: 'border-box' as const,\n overflow: autoHeight ? 'visible' : 'hidden',\n ...(o.wordWrap === false ? { whiteSpace: 'nowrap' as const, textOverflow: 'ellipsis' 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.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\nuseShrinkFit(rootRef, () => [\n fit.value,\n baseFontSize.value,\n fitMinPt.value,\n props.element.options.width,\n props.element.options.height,\n props.element.options.wordWrap,\n props.element.options.letterSpacing,\n props.element.options.lineHeight,\n displayText.value,\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 '@worm-vue3-print/core/designer'\nimport { evaluateTemplate } from '@worm-vue3-print/core/designer'\nimport { DEFAULT_DEMO_DATA } from '@worm-vue3-print/core/designer'\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\n ref=\"rootRef\"\n class=\"print-longtext\"\n :style=\"textStyle\"\n :data-fit=\"fit === 'shrink' ? 'shrink' : undefined\"\n :data-fit-base=\"String(baseFontSize)\"\n :data-fit-min=\"String(fitMinPt)\"\n >\n {{ displayText }}\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport type { RuntimeElement } from '@worm-vue3-print/core/designer'\nimport { resolveTextBinding } from '@worm-vue3-print/core/designer'\nimport { resolveElementTextFit, resolveShrinkMinFontSize } from '@worm-vue3-print/core/designer'\nimport { useShrinkFit } from '../../composables/useShrinkFit'\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 rootRef = ref<HTMLElement | null>(null)\n\n/** 溢出显示形式:长文本未配置时默认自适应行高(与打印端一致) */\nconst fit = computed(() => resolveElementTextFit('longText', props.element.options))\nconst baseFontSize = computed(() => props.element.options.fontSize || 12)\nconst fitMinPt = computed(() => resolveShrinkMinFontSize(props.element.options.shrinkMinFontSize))\n\nconst textStyle = computed(() => {\n const o = props.element.options\n const autoHeight = fit.value === 'autoHeight'\n return {\n fontSize: baseFontSize.value + '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 // 自适应行高:不锁定高度,内容撑开;其余形式锁高度并裁剪\n height: autoHeight ? 'auto' : '100%',\n overflow: autoHeight ? 'visible' : 'hidden',\n wordBreak: 'break-all' as const,\n boxSizing: 'border-box' as const,\n ...(o.wordWrap === false ? { whiteSpace: 'nowrap' as const, textOverflow: 'ellipsis' 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\nuseShrinkFit(rootRef, () => [\n fit.value,\n baseFontSize.value,\n fitMinPt.value,\n props.element.options.width,\n props.element.options.height,\n props.element.options.wordWrap,\n props.element.options.lineHeight,\n displayText.value,\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 '@worm-vue3-print/core/designer'\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=\"par\" :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'\nimport {\n BARCODE_BAR_HEIGHT_MODULES,\n BARCODE_MARGIN_BOTTOM_MODULES,\n BARCODE_QUIET_ZONE_MODULES,\n BARCODE_TEXT_FONT_SIZE_MODULES,\n barcodeAvailableBoxMm,\n barcodeUnitsPerModule,\n resolveBarcodeSize,\n} from '@worm-vue3-print/core/designer'\n\nconst props = defineProps<{\n cellType: 'barcode' | 'qrcode'\n value: string\n barcodeType?: string\n qrCodeLevel?: string\n /**\n * 条形码下方是否显示文本,缺省视为「显示」(与出图端 `showBarcodeText` 同口径)。\n * 注意:Vue 会把缺省的布尔 prop 转成 false,调用方必须显式传 `cell.showBarcodeText !== false`。\n */\n showText?: boolean\n fit?: string\n maxWidth?: number\n maxHeight?: number\n /** 打印机分辨率(点/英寸):给出后条形码尺寸吸附到整数打印点 */\n printerDpi?: number\n /** 单元格可用宽度(mm),点对齐用 */\n targetWidthMm?: number\n /** 单元格可用高度(mm),点对齐用 */\n targetHeightMm?: number\n /** 条码模块宽度倍率(2-4),缺省 2(与独立条码元素同口径) */\n barWidth?: number\n /** 条码下方文本字号(相对条高,条高为 30),缺省 BARCODE_TEXT_FONT_SIZE_MODULES */\n barFontSize?: number\n}>()\n\nconst barcodeSvg = ref<SVGSVGElement | null>(null)\nconst svgOk = ref(false)\nconst dataUrl = ref('')\n/** 结算后的落纸尺寸(mm);结算失败时为 null(回退等比缩放到单元格内) */\nconst size = ref<{ width: string; height: string } | null>(null)\n\n/**\n * 缩放模式 → preserveAspectRatio(内联 svg 不支持 object-fit)。\n * 单元格条码尺寸由条宽与打印机分辨率结算后显式给出,这里只用于二维码图片与兜底情形。\n */\nconst FIT_TO_PAR = {\n contain: 'xMidYMid meet',\n cover: 'xMidYMid slice',\n fill: 'none',\n none: 'xMidYMid meet',\n 'scale-down': 'xMidYMid meet',\n} as const\n\nconst par = computed(\n () => FIT_TO_PAR[(props.fit || 'contain') as keyof typeof FIT_TO_PAR] ?? 'xMidYMid meet',\n)\n\nconst svgStyle = computed(() => {\n // 结算尺寸就是最终 mm(条宽 / 打印机 dpi / 可用框三者算出),不再叠加缩放限制,避免二次缩放\n if (size.value) {\n return { width: size.value.width, height: size.value.height }\n }\n return {\n maxWidth: props.maxWidth ? `${props.maxWidth}mm` : '100%',\n maxHeight: props.maxHeight ? `${props.maxHeight}mm` : '100%',\n }\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\n/**\n * 与出图端(browser-code-renderer)共用同一份 jsbarcode 参数:\n * 单元格现在支持 barWidth 倍率,unitPerModule = barWidth / 2(与独立条码元素同口径)。\n */\nfunction renderBarcode() {\n svgOk.value = false\n size.value = null\n if (!barcodeSvg.value) return\n const unitPerModule = barcodeUnitsPerModule(props.barWidth)\n try {\n JsBarcode(barcodeSvg.value, props.value, {\n format: (props.barcodeType || 'CODE128') as any,\n width: unitPerModule,\n height: BARCODE_BAR_HEIGHT_MODULES * unitPerModule,\n displayValue: props.showText !== false,\n fontSize: (props.barFontSize ?? BARCODE_TEXT_FONT_SIZE_MODULES) * unitPerModule,\n // 静区只留左右(与出图端同参):上下留白会白白吃掉单元格高度\n margin: 0,\n marginLeft: BARCODE_QUIET_ZONE_MODULES * unitPerModule,\n marginRight: BARCODE_QUIET_ZONE_MODULES * unitPerModule,\n marginTop: 0,\n marginBottom: BARCODE_MARGIN_BOTTOM_MODULES * unitPerModule,\n })\n } catch {\n return /* 码值不符合码制:回退文本占位 */\n }\n svgOk.value = true\n\n // 与出图端共用同一份结算算法:条宽定首选尺寸,有 dpi 时吸附到整数打印点,可用宽高不足则等比缩小\n const viewBox = readViewBox(barcodeSvg.value)\n const settled = viewBox\n ? resolveBarcodeSize({\n unitWidth: viewBox.width / unitPerModule,\n unitHeight: viewBox.height / unitPerModule,\n // 最大宽高并入可用框(与出图端同一助手),作为结算上限而非事后 CSS 缩放\n boxWidthMm: barcodeAvailableBoxMm(props.targetWidthMm, props.maxWidth),\n boxHeightMm: barcodeAvailableBoxMm(props.targetHeightMm, props.maxHeight),\n dpi: props.printerDpi,\n barWidth: props.barWidth,\n })\n : null\n size.value = settled ? { width: `${settled.widthMm}mm`, height: `${settled.heightMm}mm` } : null\n // 抗锯齿会在条边缘生成灰像素,热敏头只有黑白两态 → 与出图端一致地关掉\n barcodeSvg.value.setAttribute('shape-rendering', 'crispEdges')\n}\n\n/** jsbarcode 会把 viewBox 写成 \"0 0 W H\";解析失败时返回 null(不启用点对齐) */\nfunction readViewBox(svg: SVGSVGElement): { width: number; height: number } | null {\n const parts = (svg.getAttribute('viewBox') ?? '').trim().split(/[\\s,]+/).map(Number)\n if (parts.length !== 4 || parts.some(v => !Number.isFinite(v))) return null\n return { width: parts[2]!, height: parts[3]! }\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(\n () => [\n props.cellType, props.value, props.barcodeType, props.qrCodeLevel, props.showText,\n props.printerDpi, props.targetWidthMm, props.targetHeightMm,\n props.barWidth, props.barFontSize, props.maxWidth, props.maxHeight,\n ],\n render,\n)\n</script>\n\n<style scoped>\n.cell-barcode { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; overflow: hidden; }\n/* 条码 svg 自带 viewBox 与结算后的显式 mm 尺寸(内联 style),这里只做溢出兜底 */\n.cell-barcode svg { max-width: 100%; max-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 '@worm-vue3-print/core/designer'\nimport { DEFAULT_DEMO_DATA } from '@worm-vue3-print/core/designer'\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 ref=\"rootRef\" 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 !== false\"\n :fit=\"cell.fit\"\n :max-width=\"cell.maxWidth\"\n :max-height=\"cell.maxHeight\"\n :printer-dpi=\"cell.printerDpi\"\n :target-width-mm=\"cellBoxWidthMm(ci, cell)\"\n :target-height-mm=\"cellCapMm(ri, cell)\"\n :bar-width=\"cell.barWidth\"\n :bar-font-size=\"cell.barFontSize\"\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 <!-- 截断 / 自动缩小:内容包定高容器(max-height = 可用高度),超出即裁 -->\n <div\n v-else-if=\"needsFitBox(cell)\"\n class=\"cell-fit\"\n :style=\"cellFitStyle(cell, ri)\"\n :data-fit=\"cellTextFit(cell) === 'shrink' ? 'shrink' : undefined\"\n :data-fit-base=\"String(cellBaseFontSize(cell))\"\n :data-fit-min=\"String(resolveShrinkMinFontSize(cell.shrinkMinFontSize))\"\n :data-fit-mm=\"cellCapMm(ri, cell)\"\n >\n <span v-if=\"row.type === 'data'\" class=\"data-placeholder\">\n {{ cellDisplay(row, cell) }}\n </span>\n <template v-else>{{ cellDisplay(row, cell) }}</template>\n </div>\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 '@worm-vue3-print/core/designer'\nimport {\n normalizeSelection, canMergeReason, mergeCells, splitCells,\n insertRow, deleteRow, insertCol, deleteCol, setRowType, syncTableElementSize,\n resolveCellBorderCss, clampResizedColumnWidth,\n} from '@worm-vue3-print/core/designer'\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 '@worm-vue3-print/core/designer'\nimport { DEFAULT_DEMO_DATA } from '@worm-vue3-print/core/designer'\nimport type { TextFit } from '@worm-vue3-print/core/designer'\nimport { cellFitCapMm, cellFitWidthMm, resolveCellTextFit, resolveShrinkMinFontSize } from '@worm-vue3-print/core/designer'\nimport { useShrinkFit } from '../../composables/useShrinkFit'\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/** 元素根节点:单元格自动缩小(data-fit)挂在其后代上,统一由此适配 */\nconst rootRef = ref<HTMLElement | 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\n// ─── 文字溢出显示形式(截断 / 自动缩小 / 自适应行高) ───\n\n/** 单元格溢出形式;与打印端 resolveCellTextFit 同一判定 */\nfunction cellTextFit(cell: TableCell): TextFit {\n return resolveCellTextFit(cell)\n}\n\n/** 截断与自动缩小都需要定高容器;自适应行高由单元格自身撑高 */\nfunction needsFitBox(cell: TableCell): boolean {\n return cellTextFit(cell) !== 'autoHeight'\n}\n\n/** 单元格基准字号:自动缩小的起点(与打印端 data-fit-base 同口径) */\nfunction cellBaseFontSize(cell: TableCell): number {\n return cell.fontSize ?? defaultFontSize.value\n}\n\n/** 可用内容高度(mm):所跨行高之和扣除内边距与边框,与打印端同一函数 */\nfunction cellCapMm(ri: number, cell: TableCell): number {\n return cellFitCapMm(rows.value, ri, cell, props.element.options.tableDefaultPadding ?? 1)\n}\n\n/** 可用内容宽度(mm):所跨列宽之和扣除内边距与边框,与打印端同一函数;列宽缺失时为 0 */\nfunction cellBoxWidthMm(ci: number, cell: TableCell): number {\n return cellFitWidthMm(colWidths.value, ci, cell, props.element.options.tableDefaultPadding ?? 1)\n}\n\nfunction cellFitStyle(cell: TableCell, ri: number): Record<string, string> {\n return {\n maxHeight: cellCapMm(ri, cell) + 'mm',\n overflow: 'hidden',\n ...(cell.wordWrap === false ? { whiteSpace: 'nowrap', textOverflow: 'ellipsis' } : {}),\n }\n}\n\n// 单元格自动缩小:与打印端共用 core 的二分算法,设计态字号即出纸字号\nuseShrinkFit(rootRef, () => [\n props.designMode,\n props.data?.length,\n colWidths.value.join(','),\n defaultFontSize.value,\n props.element.options.tableDefaultPadding,\n rows.value\n .map(row => `${row.height}:${row.cells.map(c => `${c.formatter ?? ''}|${c.fontSize ?? ''}|${c.wordWrap ?? ''}|${c.textFit ?? ''}|${c.colspan ?? 1}`).join('~')}`)\n .join(','),\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 // 仅响应左键,右键不拖动列宽\n if (e.button !== 0) 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 '@worm-vue3-print/core/designer'\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 '@worm-vue3-print/core/designer'\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=\"preserveAspectRatio\" :style=\"svgStyle\"></svg>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, onMounted, watch } from 'vue'\nimport JsBarcode from 'jsbarcode'\nimport { resolveTextBinding } from '@worm-vue3-print/core/designer'\nimport {\n BARCODE_BAR_HEIGHT_MODULES,\n BARCODE_MARGIN_BOTTOM_MODULES,\n BARCODE_QUIET_ZONE_MODULES,\n BARCODE_TEXT_FONT_SIZE_MODULES,\n barcodeAvailableBoxMm,\n barcodeUnitsPerModule,\n resolveBarcodeSize,\n} from '@worm-vue3-print/core/designer'\nimport type { RuntimeElement } from '@worm-vue3-print/core/designer'\n\nconst props = defineProps<{\n element: RuntimeElement\n data?: Record<string, any>[]\n designMode?: boolean\n}>()\n\nconst svgRef = ref<SVGSVGElement | null>(null)\n/** 结算后的落纸尺寸(mm):与出图端同源(条宽定首选 → DPI 吸附 → 框不够等比缩小) */\nconst size = ref<{ width: string; height: string } | null>(null)\n\n/**\n * 缩放模式 → preserveAspectRatio(内联 svg 不支持 object-fit)。\n * 条码尺寸由条宽与打印机分辨率结算,不再被拉伸填满元素框,故这里只作兜底:\n * 结算尺寸缺失(viewBox 解析失败等极端情形)时才让 CSS 接管等比适配。\n */\nconst FIT_TO_PAR = {\n contain: 'xMidYMid meet',\n cover: 'xMidYMid slice',\n fill: 'none',\n none: 'xMidYMid meet',\n 'scale-down': 'xMidYMid meet',\n} as const\n\nconst preserveAspectRatio = computed(\n () => FIT_TO_PAR[(props.element.options.fit || 'contain') as keyof typeof FIT_TO_PAR] ?? 'xMidYMid meet',\n)\n\n/**\n * 显式给出结算后的 mm 尺寸(与出图端同一份算法),未结算成功时回退等比缩放到元素框内。\n */\nconst svgStyle = computed(() => {\n if (size.value) {\n return { width: size.value.width, height: size.value.height }\n }\n return { maxWidth: '100%', maxHeight: '100%' }\n})\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 unitPerModule = barcodeUnitsPerModule(o.barWidth)\n try {\n JsBarcode(svgRef.value, value, {\n format: (o.barcodeType || 'CODE128') as any,\n width: unitPerModule,\n height: BARCODE_BAR_HEIGHT_MODULES * unitPerModule,\n displayValue: !o.hideTitle,\n fontSize: (o.fontSize ?? BARCODE_TEXT_FONT_SIZE_MODULES) * unitPerModule,\n // 静区只留左右(与出图端同参):上下留白会白白吃掉元素高度\n margin: 0,\n marginLeft: BARCODE_QUIET_ZONE_MODULES * unitPerModule,\n marginRight: BARCODE_QUIET_ZONE_MODULES * unitPerModule,\n marginTop: 0,\n marginBottom: BARCODE_MARGIN_BOTTOM_MODULES * unitPerModule,\n })\n } catch {\n size.value = null\n return /* 码值不符合码制:保留空白 svg */\n }\n\n // 与出图端共用同一份结算算法:条宽定首选尺寸,有 dpi 时吸附到整数打印点,框不够则等比缩小\n const viewBox = readViewBox(svgRef.value)\n const settled = viewBox\n ? resolveBarcodeSize({\n unitWidth: viewBox.width / unitPerModule,\n unitHeight: viewBox.height / unitPerModule,\n // 最大宽高并入可用框:与出图端一致地作为结算上限,而不是事后用 CSS 再缩一次\n boxWidthMm: barcodeAvailableBoxMm(o.width, o.maxWidth),\n boxHeightMm: barcodeAvailableBoxMm(o.height, o.maxHeight),\n dpi: o.printerDpi,\n barWidth: o.barWidth,\n })\n : null\n size.value = settled ? { width: `${settled.widthMm}mm`, height: `${settled.heightMm}mm` } : null\n // 抗锯齿会在条边缘生成灰像素,热敏头只有黑白两态 → 与出图端一致地关掉\n svgRef.value.setAttribute('shape-rendering', 'crispEdges')\n}\n\n/** jsbarcode 会把 viewBox 写成 \"0 0 W H\";解析失败时返回 null(不启用点对齐) */\nfunction readViewBox(svg: SVGSVGElement): { width: number; height: number } | null {\n const parts = (svg.getAttribute('viewBox') ?? '').trim().split(/[\\s,]+/).map(Number)\n if (parts.length !== 4 || parts.some(v => !Number.isFinite(v))) return null\n return { width: parts[2]!, height: parts[3]! }\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.printerDpi,\n props.element.options.hideTitle,\n props.element.options.fontSize,\n props.element.options.maxWidth,\n props.element.options.maxHeight,\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/* 非点对齐模式:SVG 使用固有尺寸(由 barWidth 决定),约束在容器内 */\n.print-barcode svg { max-width: 100%; max-height: 100%; }\n</style>\n","<template>\n <div class=\"print-qrcode\">\n <img v-if=\"dataUrl\" :src=\"dataUrl\" alt=\"qrcode\" :style=\"imgStyle\" />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, onMounted, watch } from 'vue'\nimport QRCode from 'qrcode'\nimport { resolveTextBinding } from '@worm-vue3-print/core/designer'\nimport type { RuntimeElement } from '@worm-vue3-print/core/designer'\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\n/** 最大宽高(mm)与出图端 codeImgHtml 的 max-width/max-height 同口径 */\nconst imgStyle = computed(() => {\n const o = props.element.options\n return {\n objectFit: (o.fit || 'contain') as any,\n maxWidth: o.maxWidth ? `${o.maxWidth}mm` : '100%',\n maxHeight: o.maxHeight ? `${o.maxHeight}mm` : '100%',\n }\n})\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(\n () => [props.element.options.formatter, props.element.options.testData, props.element.options.qrCodeLevel],\n render,\n)\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 '@worm-vue3-print/core/designer'\nimport { evaluateTemplate } from '@worm-vue3-print/core/designer'\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 '@worm-vue3-print/core/designer'\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 '@worm-vue3-print/core/designer'\nimport { useDrag } from '../../composables/useDrag'\nimport type { DragOptions } from '../../composables/useDrag'\nimport { generateId } from '@worm-vue3-print/core/designer'\nimport { useResize, RESIZE_POINTS } from '@worm-vue3-print/core/designer'\nimport { mmToPx } from '@worm-vue3-print/core/designer'\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 // 单个元素克隆不继承原组身份,否则克隆体会与原组串在一起、无法独立操作\n clone.options.groupId = undefined\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 // 仅左键触发选中,右键交给 contextmenu 菜单\n if (e.button !== 0) 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","// 吸附逻辑的 Vue 适配层:引导线/纸张尺寸保持响应式状态,\n// 吸附坐标与引导线计算全部委托 @worm-vue3-print/core/designer 的纯函数。\nimport { ref, type Ref } from 'vue'\nimport {\n computeAdsorb,\n type AdsorbConfig,\n type ElementRect,\n type AlignLine,\n type AdsorbResult,\n} from '@worm-vue3-print/core/designer'\n\nexport type { AdsorbConfig }\n\nexport function useAdsorb(config: AdsorbConfig = {}) {\n /** 引导线响应式数据,由模板 v-for 渲染 */\n const guideLines: Ref<AlignLine[]> = ref([])\n\n /** 纸张尺寸(mm),用于引导线贯穿整页 */\n const paperSize = ref({ width: 0, height: 0 })\n\n function check(\n movingRect: ElementRect,\n others: ElementRect[],\n guides?: { vertical: number[]; horizontal: number[] },\n ): AdsorbResult {\n return computeAdsorb(movingRect, others, guides, config)\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 '@worm-vue3-print/core/designer'\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 <!-- 设计背景(定位底图):仅设计画布显示,位于纸张最底层,不参与打印管线 -->\n <div\n v-if=\"designMode && designBackground?.src && !backgroundLoadFailed\"\n class=\"design-background\"\n :style=\"designBackgroundStyle\"\n >\n <img\n :src=\"designBackground.src\"\n draggable=\"false\"\n alt=\"\"\n @error=\"onBackgroundError\"\n >\n </div>\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 <!-- 水印渲染层(在所有元素之下):显式矢量瓦片,与打印端共用 core 的瓦片网格 -->\n <div\n v-if=\"watermarkLayout\"\n class=\"watermark-layer\"\n :style=\"{ opacity: String(watermarkLayout.opacity) }\"\n >\n <svg\n v-for=\"(tile, idx) in watermarkLayout.tiles\"\n :key=\"idx\"\n class=\"watermark-tile\"\n :width=\"tile.widthMm + 'mm'\"\n :height=\"tile.heightMm + 'mm'\"\n :viewBox=\"`0 0 ${watermarkLayout.tileWidthPx} ${watermarkLayout.tileHeightPx}`\"\n :style=\"{ left: tile.leftMm + 'mm', top: tile.topMm + 'mm' }\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <text\n :x=\"watermarkLayout.tileWidthPx / 2\"\n :y=\"watermarkLayout.tileHeightPx / 2\"\n :font-size=\"watermarkLayout.fontSizePx\"\n :fill=\"watermarkLayout.color\"\n text-anchor=\"middle\"\n dominant-baseline=\"middle\"\n :transform=\"`rotate(${watermarkLayout.rotate},${watermarkLayout.tileWidthPx / 2},${watermarkLayout.tileHeightPx / 2})`\"\n >{{ watermarkLayout.text }}</text>\n </svg>\n </div>\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, watch, onUnmounted } from 'vue'\nimport type { RuntimeElement, TemplateData, ElementRect, ElementZone, AlignLine } from '@worm-vue3-print/core/designer'\nimport { getPaperDimensions } from '@worm-vue3-print/core/designer'\nimport { mmToPx } from '@worm-vue3-print/core/designer'\nimport { resolveWatermarkLayout } from '@worm-vue3-print/core'\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// ─── 设计背景(仅设计画布显示,旋转为 90° 步进;90/270 交换宽高后居中再绕纸心旋转)───\nconst designBackground = computed(() => props.templateData.designBackground)\nconst backgroundLoadFailed = ref(false)\nwatch(() => designBackground.value?.src, () => { backgroundLoadFailed.value = false })\n\nconst normalizedBackgroundRotation = computed<0 | 90 | 180 | 270>(() => {\n const r = designBackground.value?.rotation\n return r === 90 || r === 180 || r === 270 ? r : 0\n})\n\nconst designBackgroundStyle = computed(() => {\n const rotation = normalizedBackgroundRotation.value\n const swapped = rotation === 90 || rotation === 270\n const layerW = swapped ? paperHeightMM.value : paperWidthMM.value\n const layerH = swapped ? paperWidthMM.value : paperHeightMM.value\n const style: Record<string, string> = {\n width: layerW + 'mm',\n height: layerH + 'mm',\n left: (paperWidthMM.value - layerW) / 2 + 'mm',\n top: (paperHeightMM.value - layerH) / 2 + 'mm',\n }\n if (rotation !== 0) style.transform = `rotate(${rotation}deg)`\n return style\n})\n\nfunction onBackgroundError() {\n backgroundLoadFailed.value = true\n console.warn('[print-designer] 设计背景图加载失败:', designBackground.value?.src)\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 // 仅响应左键,右键不拖动参考线\n if (e.button !== 0) return\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// ─── 水印渲染(复用 core 同构逻辑:与预览/打印完全一致) ───\n// 与打印端同源:几何(瓦片网格)由 core 计算,画布只负责渲染;\n// 水印不可见或文本为空时返回 null(core 内部判定),不渲染水印层。\nconst watermarkLayout = computed(() => resolveWatermarkLayout(\n props.templateData.watermark,\n props.printData,\n { width: paperWidthMM.value, height: paperHeightMM.value },\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 if (e.button !== 0) return\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/* 纸张缩放平滑过渡(配合鼠标位置缩放中心);适应窗口时由 JS 临时禁用 */\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/* 设计背景:铺满纸张最底层,不拦截任何指针事件 */\n.design-background {\n position: absolute;\n z-index: 0;\n overflow: hidden;\n pointer-events: none;\n}\n.design-background img {\n display: block;\n width: 100%;\n height: 100%;\n object-fit: fill;\n pointer-events: none;\n user-select: none;\n -webkit-user-drag: 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/* 水印层:覆盖整页、位于所有元素之下(几何由 core 的瓦片网格给出,mm 定位) */\n.watermark-layer {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n z-index: 0;\n overflow: hidden;\n pointer-events: none;\n}\n.watermark-tile {\n position: absolute;\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 '@worm-vue3-print/core/designer'\nimport {\n buildRulerTicks,\n chooseMajorStepMM,\n RULER_THICKNESS,\n} from '@worm-vue3-print/core/designer'\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 // 仅响应左键,右键不从标尺拖出参考线\n if (e.button !== 0) return\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 <!-- 右键菜单:fixed 定位脱离滚动容器,避免撑大 scrollWidth/Height 触发滚动条 -->\n <div\n v-if=\"contextMenu.visible\"\n ref=\"contextMenuRef\"\n class=\"context-menu\"\n :style=\"{\n left: (contextMenu.x + contextMenu.flipX) + 'px',\n top: (contextMenu.y + contextMenu.flipY) + 'px',\n }\"\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 '@worm-vue3-print/core/designer'\nimport { pxToMm, mmToPx } from '@worm-vue3-print/core/designer'\nimport { nextWheelScale, MIN_SCALE_PERCENT, FIT_SCALE_MIN_PERCENT } from '@worm-vue3-print/core/designer'\nimport { getPaperDimensions } from '@worm-vue3-print/core/designer'\nimport { RULER_THICKNESS } from '@worm-vue3-print/core/designer'\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/**\n * 统一缩放入口:所有缩放交互(滚轮 / 按钮 / 适应窗口)共用同一管线。\n * 以容器内锚点 (anchorX/Y,相对容器的 client 坐标,含 padding) 为不动点,\n * 缩放后在 nextTick 校正滚动位置,保证锚点下的内容不漂移。\n */\nfunction applyZoom(\n targetPercent: number,\n anchorX: number,\n anchorY: number,\n minPercent: number,\n) {\n const container = rootRef.value\n if (!container) return\n const target = Math.max(minPercent, Math.round(targetPercent))\n const cur = Math.round((props.scale || 1) * 100)\n if (target === cur) return\n\n const oldScale = props.scale || 1\n const ratio = (target / 100) / oldScale\n\n // 容器存在非对称 padding,换算锚点时必须扣除,否则每次缩放锚点会漂移 pad*(ratio-1)\n const cs = getComputedStyle(container)\n const padX = parseFloat(cs.paddingLeft) || 0\n const padY = parseFloat(cs.paddingTop) || 0\n const ax = container.scrollLeft + anchorX - padX\n const ay = container.scrollTop + anchorY - padY\n\n // 以百分比整数增量上报(父级 scale 为百分比)\n emit('zoom', target - cur)\n\n // 待新比例应用到 DOM 后再校正滚动位置:缩放前若该方向没有滚动条,\n // 提前写入 scrollTop/Left 会被浏览器钳制为 0,导致锚点失效\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 - anchorX + padX2\n container.scrollTop = ay * ratio - anchorY + padY2\n })\n}\n\n/** Ctrl/Cmd+滚轮缩放:乘性步进,以鼠标位置为缩放中心,保持鼠标下的内容点不动 */\nfunction onWheel(e: WheelEvent) {\n if (!(e.ctrlKey || e.metaKey)) return\n e.preventDefault()\n const container = rootRef.value\n if (!container) return\n const oldPercent = Math.round((props.scale || 1) * 100)\n const newPercent = nextWheelScale(oldPercent, e.deltaY > 0 ? -1 : 1)\n if (newPercent === oldPercent) return\n const rect = container.getBoundingClientRect()\n applyZoom(newPercent, e.clientX - rect.left, e.clientY - rect.top, MIN_SCALE_PERCENT)\n}\n\n/** 工具栏放大/缩小按钮:与滚轮相同的乘性步进,以视口几何中心为锚点 */\nfunction zoomByStep(direction: 1 | -1) {\n const container = rootRef.value\n if (!container) return\n const cur = Math.round((props.scale || 1) * 100)\n // nextWheelScale 内部已做整数取整与 25% 下限钳制,与滚轮完全一致\n const target = nextWheelScale(cur, direction)\n applyZoom(target, container.clientWidth / 2, container.clientHeight / 2, MIN_SCALE_PERCENT)\n}\n\n// ─── 适应窗口:一步到位(调用方已算好目标比例),以视口中心为锚点,\n// 与 Ctrl+滚轮同一管线;不做缩放动画:临时禁用纸张 transform 过渡,\n// 待新比例应用到 DOM 后恢复,不影响滚轮/工具栏缩放的 150ms 动画 ───\nfunction fitToWindow(targetPercent: number) {\n const container = rootRef.value\n if (!container) return\n const paper = container.querySelector('.hiprint-printPaper') as HTMLElement | null\n const prevTransition = paper?.style.transition ?? ''\n if (paper) paper.style.transition = 'none'\n // 适应窗口允许低于交互缩放下限(见 FIT_SCALE_MIN_PERCENT),保证超大纸张整版可见\n applyZoom(\n targetPercent,\n container.clientWidth / 2,\n container.clientHeight / 2,\n FIT_SCALE_MIN_PERCENT,\n )\n void nextTick(() => {\n if (paper) paper.style.transition = prevTransition\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// ─── 右键菜单 ───\n// 菜单使用 position: fixed,坐标为视口坐标(e.clientX/Y),脱离 overflow:auto\n// 容器,避免菜单撑大 scrollWidth/Height 而出现滚动条导致画布抖动\nconst contextMenu = reactive({\n visible: false,\n x: 0,\n y: 0,\n /** 右/下边缘空间不足时的翻转移位(负值),由实际菜单尺寸测量得出 */\n flipX: 0,\n flipY: 0,\n targetId: null as string | null,\n})\nconst contextMenuRef = ref<HTMLElement | null>(null)\n\nfunction onContextMenu(e: MouseEvent, elId?: string) {\n // 元素右键:由 BaseElement 上抛(已 stop);空白右键:无 elId,仅背景区域弹菜单\n if (!elId && !isCanvasBackground(e.target)) return\n contextMenu.targetId = elId ?? null\n contextMenu.visible = true\n contextMenu.x = e.clientX\n contextMenu.y = e.clientY\n contextMenu.flipX = 0\n contextMenu.flipY = 0\n\n // 菜单渲染后按实际尺寸做视口边缘翻转,防止右下区域右键时菜单溢出屏幕\n void nextTick(() => {\n const menu = contextMenuRef.value\n if (!menu) return\n const rect = menu.getBoundingClientRect()\n const gap = 4\n if (e.clientX + rect.width + gap > window.innerWidth) {\n contextMenu.flipX = -rect.width\n }\n if (e.clientY + rect.height + gap > window.innerHeight) {\n contextMenu.flipY = -rect.height\n }\n })\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, zoomByStep })\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 /* 横向:常驻滚动条轨道预留占位;竖向:用 scrollbar-gutter 预留槽位\n (无溢出时不渲染轨道,视觉更干净)。二者保证缩放/窗口尺寸变化导致\n 滚动条出现或消失时不挤压画布,避免抖动 */\n overflow-x: scroll;\n overflow-y: auto;\n scrollbar-gutter: stable;\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/* 右键菜单:fixed 定位,不参与滚动容器的内容尺寸计算,避免出现滚动条 */\n.context-menu {\n position: fixed;\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","<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 '@worm-vue3-print/core/designer'\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","<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=\"swatchStyle\"></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\" :class=\"{ 'is-empty': !modelValue }\" :style=\"modelValue ? { background: activeColor } : undefined\"></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\">\n <span>常用颜色</span>\n <button\n v-if=\"clearable\"\n type=\"button\"\n class=\"picker-clear\"\n :disabled=\"!modelValue\"\n title=\"清除选中的颜色\"\n @click=\"selectNone\"\n >\n <svg viewBox=\"0 0 16 16\" width=\"12\" height=\"12\" aria-hidden=\"true\">\n <path d=\"M3 3l10 10M13 3L3 13\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" fill=\"none\"/>\n </svg>\n 清除\n </button>\n </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: !!modelValue && color.toLowerCase() === modelValue.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 '@worm-vue3-print/core/designer'\n\nconst props = withDefaults(defineProps<{\n modelValue?: string\n /** 是否允许清除颜色,边框等颜色必填场景可关闭 */\n clearable?: boolean\n}>(), {\n clearable: true,\n})\n\nconst emit = defineEmits<{\n /** 空字符串表示清除颜色(恢复默认/继承) */\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(() => props.modelValue || '#000000')\n\n/** 色块样式:无颜色时显示透明棋盘格 */\nconst swatchStyle = computed(() => (\n props.modelValue\n ? { background: props.modelValue }\n : { background: 'transparent' }\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(() => props.modelValue, (color) => {\n // 无颜色时输入框与预览置空,HSV 保持上一次状态,方便用户重新选色\n if (!color) {\n hexInput.value = ''\n return\n }\n syncFromColor(color)\n}, { immediate: true })\n\nfunction select(color: string) {\n hexInput.value = color.toUpperCase()\n syncFromColor(color)\n emit('update:modelValue', color)\n}\n\n/** 清除颜色:标题栏「清除」按钮 */\nfunction selectNone() {\n if (!props.clearable) return\n emit('update:modelValue', '')\n}\n\nfunction onHexInput(event: Event) {\n const input = event.target as HTMLInputElement\n const color = input.value.trim()\n // 输入框清空时同步清除颜色(仅在允许清除时)\n if (!color) {\n if (props.clearable) emit('update:modelValue', '')\n return\n }\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 if (props.modelValue) 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 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.picker-current.is-empty {\n position: relative;\n background-color: #fff;\n}\n\n.picker-current.is-empty::after {\n content: '';\n position: absolute;\n inset: 3px;\n background:\n linear-gradient(to top right, transparent calc(50% - 0.7px), #f53f3f calc(50% - 0.7px), #f53f3f calc(50% + 0.7px), transparent calc(50% + 0.7px));\n border-radius: 3px;\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 display: flex;\n align-items: center;\n justify-content: space-between;\n margin-top: 10px;\n margin-bottom: 6px;\n font-size: 11px;\n color: var(--pd-text-muted, #909399);\n}\n\n/* 标题栏右侧的清除按钮 */\n.picker-clear {\n display: inline-flex;\n align-items: center;\n gap: 3px;\n padding: 2px 6px;\n border: none;\n border-radius: 4px;\n background: transparent;\n font-size: 11px;\n line-height: 1;\n color: var(--pd-text-muted, #909399);\n cursor: pointer;\n}\n\n.picker-clear:hover:not(:disabled) {\n background: rgb(0 0 0 / 6%);\n color: var(--pd-danger, #f53f3f);\n}\n\n.picker-clear:disabled {\n opacity: .45;\n cursor: not-allowed;\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 <div class=\"font-select\">\n <input\n v-model=\"text\"\n class=\"pd-input font-select-input\"\n type=\"text\"\n role=\"combobox\"\n aria-autocomplete=\"list\"\n autocomplete=\"off\"\n :placeholder=\"placeholder\"\n :aria-expanded=\"open\"\n :aria-controls=\"listId\"\n :aria-activedescendant=\"activeRowId\"\n @focus=\"onOpen\"\n @click=\"onClick\"\n @input=\"onInput\"\n @keydown.down.prevent=\"move(1)\"\n @keydown.up.prevent=\"move(-1)\"\n @keydown.enter.prevent=\"onEnter\"\n @keydown.esc.prevent=\"onCancel\"\n @blur=\"onCancel\"\n />\n <ul v-if=\"open\" :id=\"listId\" ref=\"listRef\" class=\"font-select-list\" role=\"listbox\">\n <li\n v-for=\"(row, index) in rows\"\n :id=\"`${listId}-${index}`\"\n :key=\"row.key\"\n class=\"font-select-option\"\n :class=\"{ 'is-active': index === highlighted, 'is-muted': row.kind === 'unknown' || row.kind === 'free' }\"\n role=\"option\"\n :aria-selected=\"row.selected\"\n @mousedown.prevent=\"pick(row)\"\n >{{ row.label }}</li>\n </ul>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, nextTick, ref, useId, watch } from 'vue'\nimport {\n filterFontOptions,\n findFontOption,\n fontOptionLabel,\n normalizeFontQuery,\n useInjectedFontCatalog,\n} from '../../composables/useFontCatalog'\n\nconst props = withDefaults(defineProps<{\n /** 当前族名;undefined 表示未设置,走全局兜底字体栈 */\n modelValue?: string\n /** 空值行文案(同时用作输入框 placeholder) */\n placeholder?: string\n}>(), {\n placeholder: '默认',\n})\n\nconst emit = defineEmits<{ 'update:model-value': [value: string | undefined] }>()\n\nconst catalog = useInjectedFontCatalog()\n\n/** 每实例独立的列表 id,供 combobox 的 aria 关联使用 */\nconst listId = `font-select-list-${useId()}`\n\nconst listRef = ref<HTMLUListElement | null>(null)\n/** 输入框显示值:未提交时与 modelValue 不一致,提交或取消后回到 modelValue 的展示名 */\nconst text = ref(toDisplayName(props.modelValue))\n/** 过滤词:展开时为空表示「列出全部」 */\nconst query = ref('')\nconst open = ref(false)\n/** 高亮行下标;-1 表示无高亮(此时 Enter 不提交任何东西) */\nconst highlighted = ref(-1)\n\ninterface FontRow {\n key: string\n kind: 'clear' | 'unknown' | 'font' | 'free'\n label: string\n /** 提交值;clear 行为 undefined */\n value?: string\n selected: boolean\n}\n\n/**\n * 模板当前值不在声明字体内时(如导入了使用系统字体的旧模板)必须保留一行,\n * 否则设计者会以为该字体在打开面板时被清掉了。\n */\nconst unknownFamily = computed(() => {\n const current = props.modelValue?.trim()\n if (!current) return ''\n return findFontOption(catalog.value, current) ? '' : current\n})\n\nconst rows = computed<FontRow[]>(() => {\n const current = (props.modelValue ?? '').trim()\n const make = (kind: FontRow['kind'], key: string, label: string, value?: string): FontRow => ({\n kind,\n key,\n label,\n value,\n selected: (value ?? '') === current,\n })\n\n const typed = query.value.trim()\n // 过滤时不展示空值行与未知行:此时 Enter 应当落在命中项或用户输入的字体名上\n if (!typed) {\n const out: FontRow[] = [make('clear', '__clear__', props.placeholder)]\n if (unknownFamily.value) {\n out.push(make('unknown', '__unknown__', `${unknownFamily.value}(未知)`, unknownFamily.value))\n }\n for (const font of catalog.value) {\n out.push(make('font', font.family, fontOptionLabel(font), font.family))\n }\n return out\n }\n\n const matched = filterFontOptions(catalog.value, typed).map(font =>\n make('font', font.family, fontOptionLabel(font), font.family),\n )\n // 清单外字体名可直接录入:一条都没命中时才补「使用「xxx」」,\n // 有命中项时补这行只会成为方向键路径上的噪音。\n if (!matched.length) {\n const family = resolveTypedFamily(typed)\n matched.push(make('free', '__free__', `使用「${family}」`, family))\n }\n return matched\n})\n\n/** 输入的是展示名(label)时,写进模板的必须是真实族名,否则字体静默失效 */\nfunction resolveTypedFamily(typed: string): string {\n const key = normalizeFontQuery(typed)\n const hit = catalog.value.find(font => font.label && normalizeFontQuery(font.label) === key)\n return hit?.family ?? typed\n}\n\n/**\n * 展示名:宿主用 prop 声明了 label 的字体在输入框里显示 label(业务名),\n * 便于识别;写入模板的始终是族名,展示与存储分离。\n */\nfunction toDisplayName(family?: string): string {\n const key = family?.trim()\n if (!key) return ''\n return findFontOption(catalog.value, key)?.label ?? key\n}\n\nconst activeRowId = computed(() =>\n open.value && highlighted.value >= 0 ? `${listId}-${highlighted.value}` : undefined,\n)\n\n/** 当前值所在行;用于展开时把高亮落在已选字体上,避免误按 Enter 改掉字体 */\nfunction currentRowIndex(): number {\n const current = (props.modelValue ?? '').trim()\n return rows.value.findIndex(row => (row.value ?? '') === current)\n}\n\nfunction onOpen(): void {\n if (open.value) return\n open.value = true\n query.value = ''\n highlighted.value = currentRowIndex()\n}\n\n/** 点击输入框只负责重新展开(Esc 收起后再次点开),不改动已输入内容 */\nfunction onClick(): void {\n open.value = true\n}\n\nfunction onInput(): void {\n open.value = true\n query.value = text.value\n highlighted.value = rows.value.length ? 0 : -1\n}\n\nfunction move(delta: number): void {\n if (!open.value) {\n onOpen()\n return\n }\n const last = rows.value.length - 1\n if (last < 0) return\n highlighted.value = Math.min(Math.max(highlighted.value + delta, 0), last)\n scrollActiveIntoView()\n}\n\nfunction scrollActiveIntoView(): void {\n void nextTick(() => {\n const el = listRef.value?.children[highlighted.value] as HTMLElement | undefined\n el?.scrollIntoView?.({ block: 'nearest' })\n })\n}\n\nfunction onEnter(): void {\n if (!open.value) return\n const row = rows.value[highlighted.value]\n if (row) {\n pick(row)\n return\n }\n const typed = query.value.trim()\n if (typed) {\n const family = resolveTypedFamily(typed)\n pick({ kind: 'free', key: '__free__', label: family, value: family, selected: false })\n }\n}\n\nfunction pick(row: FontRow): void {\n text.value = toDisplayName(row.value)\n query.value = ''\n open.value = false\n highlighted.value = -1\n emit('update:model-value', row.value)\n}\n\nfunction onCancel(): void {\n open.value = false\n query.value = ''\n highlighted.value = -1\n text.value = toDisplayName(props.modelValue)\n}\n\nwatch(() => props.modelValue, value => { text.value = toDisplayName(value) })\n</script>\n\n<style scoped>\n.font-select-input {\n width: 100%;\n}\n.font-select-list {\n margin-top: 4px;\n max-height: 200px;\n overflow-y: auto;\n padding: 2px;\n border: 1px solid var(--pd-border, #d9dde6);\n border-radius: 6px;\n background: var(--pd-surface, #ffffff);\n list-style: none;\n}\n.font-select-option {\n padding: 4px 6px;\n border-radius: 4px;\n font-size: 12px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n cursor: pointer;\n}\n.font-select-option.is-active {\n background: var(--pd-sidebar-hover, #f0f3f9);\n}\n.font-select-option.is-muted {\n color: var(--pd-text-muted, #8b909c);\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-family')\"><span class=\"pd-label\">字体</span>\n <FontSelect v-model=\"element.options.fontFamily\" />\n </div>\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 <div class=\"pd-field\" v-show=\"showItem('ap-text-fit')\"><span class=\"pd-label\">文字溢出</span>\n <select class=\"pd-select\" :value=\"textFit\" style=\"width: 100%\" @change=\"onTextFitChange\">\n <option value=\"clip\">截断</option>\n <option value=\"shrink\">自动缩小</option>\n <option value=\"autoHeight\">自适应行高</option>\n </select>\n </div>\n <div class=\"pd-field\" v-if=\"textFit === 'shrink'\" v-show=\"showItem('ap-shrink-min')\"><span class=\"pd-label\">最小字号 (pt)</span>\n <StepperInput :model-value=\"element.options.shrinkMinFontSize\"\n :min=\"1\"\n :max=\"72\"\n :step=\"0.5\"\n placeholder=\"默认 6\"\n @update:model-value=\"element.options.shrinkMinFontSize = $event ?? undefined\" />\n </div>\n <div class=\"pd-field\" v-show=\"showItem('ap-word-wrap')\"><span class=\"pd-label\">自动换行</span>\n <input :checked=\"element.options.wordWrap !== false\" type=\"checkbox\" class=\"pd-switch\"\n @input=\"element.options.wordWrap = ($event.target as HTMLInputElement).checked ? undefined : false\" />\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 '@worm-vue3-print/core/designer'\nimport { resolveElementTextFit, type TextFit } from '@worm-vue3-print/core/designer'\nimport PresetColorPicker from '../PresetColorPicker.vue'\nimport PropertyGroup from './PropertyGroup.vue'\nimport StepperInput from './StepperInput.vue'\nimport FontSelect from './FontSelect.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\n/** 溢出形式:未配置时按元素类型取默认(文本=截断、长文本=自适应行高) */\nconst textFit = computed<TextFit>(() =>\n resolveElementTextFit(props.element.printElementType.type || 'text', props.element.options),\n)\n\nfunction onTextFitChange(e: Event) {\n props.element.options.textFit = (e.target as HTMLSelectElement).value as TextFit\n}\n</script>\n\n<style scoped>\n.color-row {\n display: flex;\n gap: 12px;\n}\n.color-row > .pd-field {\n flex: 1 1 0;\n min-width: 0;\n}</style>","<!-- 条形码/二维码配置分组:码制/条宽/显示文本/字号/纠错级别 + 自定义设置(缩放模式/最大宽高) -->\n<template>\n <PropertyGroup title=\"条码设置\" icon=\"Postcard\" default-expanded group-key=\"code\">\n <form class=\"pd-form\" @submit.prevent>\n <template v-if=\"isBarcode\">\n <div class=\"pd-field\" v-show=\"showItem('cd-type')\"><span class=\"pd-label\">码制</span>\n <select class=\"pd-select\" :value=\"barcodeType\" @change=\"onBarcodeTypeChange\">\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-show=\"showItem('cd-dpi')\"><span class=\"pd-label\">打印机分辨率</span>\n <select class=\"pd-select\" :value=\"dpiValue\" @change=\"onDpiChange\">\n <option value=\"\">不指定(按条宽渲染)</option>\n <option value=\"203\">203 dpi(8 点/mm)</option>\n <option value=\"300\">300 dpi(11.8 点/mm)</option>\n <option value=\"600\">600 dpi(23.6 点/mm)</option>\n </select>\n </div>\n <p class=\"pd-hint\" v-show=\"showItem('cd-dpi')\">填写后条宽吸附到整数打印点(消除出纸「条宽忽宽忽窄」):条码先按条宽渲染,可用宽度够就原样落纸,不够才整体等比缩小</p>\n <div class=\"pd-field\" v-show=\"showItem('cd-bar-width')\"><span class=\"pd-label\">条宽(倍率)</span>\n <StepperInput :model-value=\"element.options.barWidth ?? 2\"\n :min=\"2\"\n :max=\"4\"\n :step=\"0.5\"\n @update:model-value=\"element.options.barWidth = $event; emitChange()\" />\n </div>\n <p class=\"pd-hint\" v-show=\"showItem('cd-bar-width')\">{{ dotAligned\n ? '已设置打印机分辨率:条宽会被吸附到最近的整数打印点(DPI 优先于毫米值),元素框放不下时整体等比缩小'\n : '热敏/针式打印建议 3 及以上:决定条码的落纸尺寸,条越粗出纸后条宽越稳定' }}</p>\n <div class=\"pd-field\" v-show=\"showItem('cd-show-text')\"><span class=\"pd-label\">显示文本</span>\n <input :checked=\"element.options.hideTitle !== true\" type=\"checkbox\" class=\"pd-switch\"\n @input=\"element.options.hideTitle = ($event.target as HTMLInputElement).checked ? undefined : true; emitChange()\" />\n </div>\n <div class=\"pd-field\" v-show=\"showItem('cd-font-size')\"><span class=\"pd-label\">文本字号(相对条高,条高为 30)</span>\n <StepperInput :model-value=\"element.options.fontSize\"\n :min=\"5\"\n :max=\"24\"\n placeholder=\"默认 10\"\n @update:model-value=\"element.options.fontSize = $event ?? undefined; emitChange()\" />\n </div>\n </template>\n\n <template v-else-if=\"isQrcode\">\n <div class=\"pd-field\" v-show=\"showItem('cd-ec-level')\"><span class=\"pd-label\">纠错级别</span>\n <select class=\"pd-select\" :value=\"String(element.options.qrCodeLevel ?? 'M')\"\n @change=\"element.options.qrCodeLevel = ($event.target as HTMLSelectElement).value; emitChange()\">\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 </template>\n\n <h3 class=\"pd-divider\">自定义设置</h3>\n <p class=\"pd-hint\" v-if=\"isBarcode\">条码尺寸由「条宽」与「打印机分辨率」结算:宽度足够时按条宽原样落纸,不足时整体等比缩小;拉伸会把条宽变成非整数,故条形码不提供缩放模式,可用「最大宽高」限制上限</p>\n <div class=\"pd-field\" v-if=\"!isBarcode\" v-show=\"showItem('cd-fit')\"><span class=\"pd-label\">缩放模式</span>\n <select class=\"pd-select\" :value=\"element.options.fit || 'contain'\" @change=\"onFitChange\">\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-show=\"showItem('cd-max-width')\"><span class=\"pd-label\">最大宽度 (mm)</span>\n <StepperInput :model-value=\"element.options.maxWidth\"\n :min=\"1\"\n :max=\"200\"\n placeholder=\"默认\"\n @update:model-value=\"element.options.maxWidth = $event ?? undefined; emitChange()\" />\n </div>\n <div class=\"pd-field\" v-show=\"showItem('cd-max-height')\"><span class=\"pd-label\">最大高度 (mm)</span>\n <StepperInput :model-value=\"element.options.maxHeight\"\n :min=\"1\"\n :max=\"200\"\n placeholder=\"默认\"\n @update:model-value=\"element.options.maxHeight = $event ?? undefined; emitChange()\" />\n </div>\n </form>\n </PropertyGroup>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport type { RuntimeElement } from '@worm-vue3-print/core/designer'\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\nconst emit = defineEmits<{ change: [] }>()\n\nconst isBarcode = computed(() => props.element.printElementType.type === 'barcode')\nconst isQrcode = computed(() => props.element.printElementType.type === 'qrcode')\n\n/**\n * 码制归一化为大写的 jsbarcode 格式名。\n * jsbarcode 对格式名大小写不敏感,但存量模板存有小写(元素工厂缺省 `code128`),\n * 不归一化会导致下拉框匹配不到选项、显示为空。\n */\nconst barcodeType = computed(() => (props.element.options.barcodeType || 'CODE128').toUpperCase())\n\n/** 打印机分辨率:'' 表示不启用点对齐(保持原有按框缩放行为) */\nconst dpiValue = computed(() => (props.element.options.printerDpi ? String(props.element.options.printerDpi) : ''))\nconst hasPrinterDpi = computed(() => !!props.element.options.printerDpi)\n/** 点对齐只作用于条形码(二维码模块数固定,尺寸由 fit/最大宽高决定) */\nconst dotAligned = computed(() => isBarcode.value && hasPrinterDpi.value)\n\nfunction onDpiChange(e: Event) {\n const value = Number((e.target as HTMLSelectElement).value)\n props.element.options.printerDpi = value > 0 ? value : undefined\n emitChange()\n}\n\nfunction onBarcodeTypeChange(e: Event) {\n const value = (e.target as HTMLSelectElement).value\n props.element.options.barcodeType = value === 'CODE128' ? undefined : value\n emitChange()\n}\n\nfunction onFitChange(e: Event) {\n props.element.options.fit = (e.target as HTMLSelectElement).value || undefined\n emitChange()\n}\n\nfunction showItem(key: string): boolean {\n if (!props.searching) {\n return true\n }\n return props.matchedKeys?.has(key) ?? true\n}\n\nfunction emitChange() {\n emit('change')\n}\n</script>\n","<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 '@worm-vue3-print/core/designer'\nimport { evaluateTemplate } from '@worm-vue3-print/core/designer'\nimport { DEFAULT_DEMO_DATA } from '@worm-vue3-print/core/designer'\nimport { groupFields, filterGroups } from '@worm-vue3-print/core/designer'\nimport { resolveSystemVariables } from '@worm-vue3-print/core'\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 // 系统变量取值与渲染端同一实现(resolveSystemVariables),保证预览与打印一致\n ...resolveSystemVariables(),\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 '@worm-vue3-print/core/designer'\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 '@worm-vue3-print/core/designer'\nimport { TABLE_EDIT_KEY } from '../../composables/useTableSelection'\nimport { syncTableElementSize } from '@worm-vue3-print/core/designer'\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 '@worm-vue3-print/core/designer'\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 '@worm-vue3-print/core/designer'\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 '@worm-vue3-print/core/designer'\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 '@worm-vue3-print/core/designer'\nimport { setRowType, syncTableElementSize } from '@worm-vue3-print/core/designer'\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=\"isBarcodeCell\"><span class=\"pd-label\">条宽(倍率)</span>\n <StepperInput :model-value=\"mainCell.barWidth ?? 2\"\n :min=\"2\"\n :max=\"4\"\n :step=\"0.5\"\n @update:model-value=\"write(c => { c.barWidth = $event })\" />\n </div>\n <p class=\"pd-hint\" v-if=\"isBarcodeCell\">{{ dotAligned\n ? '已设置打印机分辨率:条宽会被吸附到最近的整数打印点(DPI 优先于毫米值),单元格放不下时整体等比缩小'\n : '热敏/针式打印建议 3 及以上:决定条码的落纸尺寸,条越粗出纸后条宽越稳定' }}</p>\n <div class=\"pd-field\" v-if=\"isBarcodeCell\"><span class=\"pd-label\">文本字号(相对条高,条高为 30)</span>\n <StepperInput :model-value=\"mainCell.barFontSize ?? 10\"\n :min=\"5\"\n :max=\"24\"\n placeholder=\"默认 10\"\n @update:model-value=\"write(c => { c.barFontSize = $event ?? undefined })\" />\n </div>\n <div class=\"pd-field\" v-if=\"isBarcodeCell\"><span class=\"pd-label\">打印机分辨率</span>\n <select :value=\"mainCell.printerDpi ? String(mainCell.printerDpi) : ''\" class=\"pd-select\" @change=\"onPrinterDpiChange(($event.target as HTMLSelectElement).value)\">\n <option value=\"\">不指定(按条宽渲染)</option>\n <option value=\"203\">203 dpi(8 点/mm)</option>\n <option value=\"300\">300 dpi(11.8 点/mm)</option>\n <option value=\"600\">600 dpi(23.6 点/mm)</option>\n </select>\n </div>\n <p class=\"pd-hint\" v-if=\"isBarcodeCell\">填写后条宽吸附到整数打印点(消除出纸「条宽忽宽忽窄」):条码先按条宽渲染,可用宽度够就原样落纸,不够才整体等比缩小</p>\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 <p class=\"pd-hint\" v-if=\"isBarcodeCell\">单元格条码尺寸由「条宽」与「打印机分辨率」结算:可用宽度足够时按条宽原样落纸,不足时整体等比缩小;拉伸会把条宽变成非整数,故条形码不提供缩放模式,可用「最大宽高」限制上限</p>\n <div class=\"pd-field\" v-if=\"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 cell-font-field\"><span class=\"pd-label\">字体</span>\n <FontSelect\n :model-value=\"mainCell.fontFamily\"\n placeholder=\"继承默认\"\n @update:model-value=\"write(c => { c.fontFamily = $event })\"\n />\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\" :clearable=\"false\" />\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 <div class=\"pd-field\" v-if=\"isTextCell\"><span class=\"pd-label\">文字溢出</span>\n <select class=\"pd-select\" :value=\"cellTextFit\" style=\"width: 100%\" @change=\"onTextFitChange\">\n <option value=\"clip\">截断</option>\n <option value=\"shrink\">自动缩小</option>\n <option value=\"autoHeight\">自适应行高</option>\n </select>\n </div>\n <div class=\"pd-field\" v-if=\"isTextCell && cellTextFit === 'shrink'\"><span class=\"pd-label\">最小字号 (pt)</span>\n <StepperInput :model-value=\"mainCell.shrinkMinFontSize\"\n :min=\"1\"\n :max=\"72\"\n :step=\"0.5\"\n placeholder=\"默认 6\"\n @update:model-value=\"write(c => { c.shrinkMinFontSize = $event ?? undefined })\" />\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 '@worm-vue3-print/core/designer'\nimport {\n canMergeReason, mergeCells, splitCells, applyBorderPreset, findMainCell, type BorderPreset,\n resolveCellTextFit, type TextFit,\n} from '@worm-vue3-print/core/designer'\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'\nimport FontSelect from './FontSelect.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/** 条码点对齐:仅条形码单元格 + 已配打印机分辨率;此时缩放模式与最大宽高不参与 */\nconst dotAligned = computed(() => isBarcodeCell.value && !!mainCell.value.printerDpi)\n\n/** 文字溢出形式仅对文本单元格有意义(码值/图片由 fit/maxWidth 控制) */\nconst isTextCell = computed(() => !isBarcodeCell.value && !isQrcodeCell.value && !isImageCell.value)\n/** 未配置时:不换行→截断,否则自适应行高(与打印端同一判定) */\nconst cellTextFit = computed(() => resolveCellTextFit(mainCell.value))\n\nfunction onTextFitChange(e: Event) {\n const value = (e.target as HTMLSelectElement).value as TextFit\n write(c => { c.textFit = value })\n}\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 onPrinterDpiChange(v: string) {\n const dpi = Number(v)\n write(c => { c.printerDpi = dpi > 0 ? dpi : undefined })\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 c.printerDpi = 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/* 字体含输入框 + 查询按钮 + 状态提示,半栏放不下,独占一行 */\n.cell-font-field {\n grid-column: 1 / -1;\n /* 栅格行距为 0,独占一行时需自己与下方「字号 / 加粗」留出间距 */\n padding-bottom: 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","<template>\n <div class=\"watermark-config\">\n <h3 class=\"pd-divider\">水印</h3>\n <form class=\"pd-form\" @submit.prevent>\n <!-- 单一表达式输入:纯文本即静态水印,含 {字段}/函数/字段路径即按表达式解析 -->\n <div class=\"pd-field\"><span class=\"pd-label\">水印表达式</span>\n <input\n class=\"pd-input\"\n v-model=\"expressionText\"\n placeholder=\"直接输入文字,或用表达式:{order.no}、{printDate}\"\n title=\"双击或点「编辑表达式」打开表达式弹框\"\n @input=\"onTextInput\"\n @dblclick=\"openExpressionEditor\"\n />\n <button type=\"button\" class=\"pd-button small\" @click=\"openExpressionEditor\">编辑表达式</button>\n </div>\n <div v-if=\"isExpression\" class=\"pd-field\"><span class=\"pd-label\">测试值</span>\n <input class=\"pd-input\" v-model=\"testData\" placeholder=\"表达式取不到值时预览显示\" @input=\"onChange\" />\n </div>\n <ExpressionEditor\n v-model=\"exprEditorVisible\"\n :fields=\"fields\"\n :expression=\"expressionText\"\n @update:expression=\"onExpressionChange\"\n />\n\n <!-- 公共设置 -->\n <div class=\"pd-field\"><span class=\"pd-label\">旋转角度</span>\n <input type=\"range\" class=\"pd-range\" v-model.number=\"localConfig.rotate\" :min=\"-90\" :max=\"90\" :step=\"5\" @change=\"onChange\" />\n <span class=\"pd-hint\">{{ localConfig.rotate }}°</span>\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">颜色</span>\n <PresetColorPicker :model-value=\"localConfig.color\" @update:model-value=\"onColorChange\" />\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">透明度</span>\n <input type=\"range\" class=\"pd-range\" v-model.number=\"localConfig.opacity\" :min=\"0.05\" :max=\"0.5\" :step=\"0.05\" @change=\"onChange\" />\n <span class=\"pd-hint\">{{ localConfig.opacity.toFixed(2) }}</span>\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">密度</span>\n <select class=\"pd-select\" v-model=\"density\" style=\"width: 100%\" @change=\"onChange\">\n <option v-for=\"(p, key) in densityPresets\" :key=\"key\" :value=\"key\">{{ p.label }}({{ p.width }}×{{ p.height }})</option>\n <option value=\"custom\">自定义</option>\n </select>\n </div>\n <template v-if=\"density === 'custom'\">\n <div class=\"pd-field\"><span class=\"pd-label\">瓦片宽</span>\n <input type=\"number\" class=\"pd-input\" v-model.number=\"localConfig.tileWidth\" :min=\"minTileWidth\" :step=\"10\" @change=\"onChange\" />\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">瓦片高</span>\n <input type=\"number\" class=\"pd-input\" v-model.number=\"localConfig.tileHeight\" :min=\"minTileHeight\" :step=\"10\" @change=\"onChange\" />\n </div>\n </template>\n </form>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, reactive, ref, watch } from 'vue'\nimport type { WatermarkOptions, PrintBusinessField } from '@worm-vue3-print/core/designer'\nimport { WATERMARK_DENSITY_PRESETS, WATERMARK_DEFAULTS } from '@worm-vue3-print/core'\nimport PresetColorPicker from './PresetColorPicker.vue'\nimport ExpressionEditor from './ExpressionEditor.vue'\n\nconst props = defineProps<{\n modelValue?: WatermarkOptions\n fields?: PrintBusinessField[]\n}>()\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: WatermarkOptions]\n}>()\n\nconst densityPresets = WATERMARK_DENSITY_PRESETS\nconst minTileWidth = WATERMARK_DEFAULTS.minTileWidth\nconst minTileHeight = WATERMARK_DEFAULTS.minTileHeight\n\n/**\n * 判断输入是「表达式」还是「静态文本」:\n * - 含花括号:{order.no}、{CONCAT(...)}、第{pageIndex}页\n * - 函数调用:CONCAT('单号:', order.no)\n * - 字段路径:order.no(与 core binding 模式的路径解析一致)\n * 其余(含中文标语)按静态水印处理。\n */\nfunction isExpressionText(text: string): boolean {\n const t = text.trim()\n if (!t) return false\n if (/[{}]/.test(t)) return true\n if (/^[A-Za-z_$][\\w$]*\\s*\\(/.test(t)) return true\n return /^[A-Za-z_$][\\w$]*(\\.[\\w$]+)+$/.test(t)\n}\n\n/** 取模板里的水印文本:binding 模式取 binding,其余取 content */\nfunction readText(v?: WatermarkOptions): string {\n if (!v) return ''\n return v.mode === 'binding' ? (v.binding ?? '') : (v.content ?? '')\n}\n\nconst expressionText = ref(readText(props.modelValue))\nconst testData = ref(props.modelValue?.testData || '')\nconst exprEditorVisible = ref(false)\n// 当前按哪种模式落盘;文本被编辑时按内容重新判定\nconst activeMode = ref<'fixed' | 'binding'>(props.modelValue?.mode === 'binding' ? 'binding' : 'fixed')\n\nconst localConfig = reactive({\n rotate: props.modelValue?.rotate ?? WATERMARK_DEFAULTS.rotate,\n color: props.modelValue?.color || WATERMARK_DEFAULTS.color,\n opacity: props.modelValue?.opacity ?? WATERMARK_DEFAULTS.opacity,\n tileWidth: props.modelValue?.tileWidth ?? WATERMARK_DEFAULTS.tileWidth,\n tileHeight: props.modelValue?.tileHeight ?? WATERMARK_DEFAULTS.tileHeight,\n})\n\n/** 是否表达式模式(决定是否展示测试值;纯文本水印用不到) */\nconst isExpression = computed(() => activeMode.value === 'binding')\n\nwatch(() => props.modelValue, (val) => {\n if (!val) return\n expressionText.value = readText(val)\n // 模板未改动文本时沿用原模式(兼容 binding 存的是无花括号路径的存量模板)\n activeMode.value = val.mode === 'binding' ? 'binding' : 'fixed'\n testData.value = val.testData || ''\n localConfig.rotate = val.rotate ?? WATERMARK_DEFAULTS.rotate\n localConfig.color = val.color || WATERMARK_DEFAULTS.color\n localConfig.opacity = val.opacity ?? WATERMARK_DEFAULTS.opacity\n localConfig.tileWidth = val.tileWidth ?? WATERMARK_DEFAULTS.tileWidth\n localConfig.tileHeight = val.tileHeight ?? WATERMARK_DEFAULTS.tileHeight\n}, { deep: true })\n\nconst density = computed({\n get(): string {\n const { tileWidth, tileHeight } = localConfig\n for (const [key, preset] of Object.entries(densityPresets)) {\n if (tileWidth === preset.width && tileHeight === preset.height) return key\n }\n return 'custom'\n },\n set(value: string) {\n const preset = densityPresets[value]\n if (preset) {\n localConfig.tileWidth = preset.width\n localConfig.tileHeight = preset.height\n }\n },\n})\n\n/** 文本变化(输入框 / 弹框):按内容重新判定表达式或静态文本 */\nfunction onTextChanged() {\n activeMode.value = isExpressionText(expressionText.value) ? 'binding' : 'fixed'\n onChange()\n}\n\nfunction onTextInput() {\n onTextChanged()\n}\n\nfunction openExpressionEditor() {\n exprEditorVisible.value = true\n}\n\nfunction onExpressionChange(value: string) {\n expressionText.value = value\n onTextChanged()\n}\n\nfunction onColorChange(value: string) {\n localConfig.color = value\n onChange()\n}\n\n/** 统一落盘:表达式写 binding,静态文本写 content(core 两种模式都支持) */\nfunction onChange() {\n const base = {\n testData: testData.value,\n rotate: localConfig.rotate,\n color: localConfig.color,\n opacity: localConfig.opacity,\n tileWidth: localConfig.tileWidth,\n tileHeight: localConfig.tileHeight,\n }\n emit('update:modelValue', activeMode.value === 'binding'\n ? { ...base, mode: 'binding', binding: expressionText.value, content: '' }\n : { ...base, mode: 'fixed', content: expressionText.value, binding: '' })\n}\n</script>\n\n<style scoped>\n.watermark-config {\n padding: 0 4px;\n}\n\n.pd-hint {\n margin-left: 8px;\n font-size: 12px;\n color: #909399;\n min-width: 32px;\n}\n</style>\n","<template>\n <div class=\"design-background-config\">\n <h3 class=\"pd-divider\">设计背景</h3>\n <p class=\"design-background-tip\">仅设计器显示,用于套打定位,不会出现在预览和打印中</p>\n\n <template v-if=\"modelValue?.src\">\n <div class=\"design-background-path\" :title=\"modelValue.src\">{{ modelValue.src }}</div>\n <div class=\"design-background-actions\">\n <button type=\"button\" class=\"pd-button small rotate-btn\" @click=\"onRotate\">\n 旋转({{ rotation }}°)\n </button>\n <button type=\"button\" class=\"pd-button small remove-btn\" @click=\"onRemove\">移除</button>\n </div>\n </template>\n\n <label v-else class=\"pd-button small upload-label\" :class=\"{ disabled: uploadDisabled }\">\n {{ uploading ? '上传中...' : '上传背景图' }}\n <input\n class=\"visually-hidden\"\n type=\"file\"\n accept=\"image/*\"\n :disabled=\"uploadDisabled\"\n @change=\"onFileChange\"\n >\n </label>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, inject, ref } from 'vue'\nimport type { DesignBackground } from '@worm-vue3-print/core/designer'\nimport { UPLOAD_DESIGN_BACKGROUND_KEY } from '../../composables/useHostAdapter'\n\nconst props = defineProps<{ modelValue?: DesignBackground }>()\nconst emit = defineEmits<{ 'update:modelValue': [value: DesignBackground | undefined] }>()\n\nconst uploading = ref(false)\nconst uploadDesignBackground = inject(UPLOAD_DESIGN_BACKGROUND_KEY, computed(() => undefined))\nconst uploadDisabled = computed(() => uploading.value || !uploadDesignBackground.value)\n\nconst rotation = computed(() => props.modelValue?.rotation ?? 0)\n\nasync function onFileChange(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 (!uploadDesignBackground.value) {\n alert('设计背景上传能力未配置')\n input.value = ''\n return\n }\n uploading.value = true\n try {\n const src = await uploadDesignBackground.value(file)\n if (src) {\n emit('update:modelValue', { src, rotation: 0 })\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\nfunction onRotate() {\n if (!props.modelValue?.src) return\n const next = ((rotation.value + 90) % 360) as DesignBackground['rotation']\n emit('update:modelValue', { src: props.modelValue.src, rotation: next })\n}\n\nfunction onRemove() {\n emit('update:modelValue', undefined)\n}\n</script>\n\n<style scoped>\n.design-background-config {\n padding: 0 4px;\n}\n.design-background-tip {\n margin: 2px 0 6px;\n font-size: 11px;\n line-height: 1.4;\n color: var(--pd-text-muted, #909399);\n}\n.design-background-path {\n margin-bottom: 6px;\n padding: 4px 6px;\n font-size: 11px;\n color: var(--pd-text-regular, #606266);\n background: var(--pd-fill-light, #f5f7fa);\n border-radius: 3px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.design-background-actions {\n display: flex;\n gap: 6px;\n}\n.upload-label {\n cursor: pointer;\n}\n.upload-label.disabled {\n opacity: 0.6;\n cursor: not-allowed;\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","<template>\n <div class=\"tiling-config\" data-test=\"tiling-config\">\n <h3 class=\"pd-divider\">拼版打印</h3>\n <p class=\"pd-hint\">把标签按「列 × 行」铺到一张大纸上批量打印</p>\n\n <div class=\"pd-field\">\n <label class=\"tiling-switch\">\n <input\n type=\"checkbox\"\n :checked=\"cfg.enabled\"\n :disabled=\"labelContinuous\"\n @change=\"onEnabledChange(($event.target as HTMLInputElement).checked)\"\n >\n <span>启用拼版</span>\n </label>\n <p v-if=\"labelContinuous\" class=\"pd-hint tiling-error\">连续纸不支持拼版</p>\n </div>\n\n <template v-if=\"cfg.enabled && !labelContinuous\">\n <div class=\"pd-field\">\n <span class=\"pd-label\">目标纸张</span>\n <select\n class=\"pd-select\"\n style=\"width: 100%\"\n :value=\"cfg.sheetPaperSize ?? 'A4'\"\n @change=\"onSheetPaperChange(($event.target as HTMLSelectElement).value)\"\n >\n <option v-for=\"key in sheetPresetKeys\" :key=\"key\" :value=\"key\">{{ PAPER_PRESETS[key]?.label ?? key }}</option>\n <option value=\"CUSTOM\">自定义</option>\n </select>\n </div>\n\n <div v-if=\"cfg.sheetPaperSize === 'CUSTOM'\" class=\"pd-field\">\n <span class=\"pd-label\">目标纸宽高 (mm)</span>\n <div class=\"custom-size-grid\">\n <StepperInput\n :model-value=\"cfg.sheetCustomWidth\"\n :min=\"25\"\n :max=\"2000\"\n @update:model-value=\"patch({ sheetCustomWidth: $event })\"\n />\n <span class=\"custom-size-x\">×</span>\n <StepperInput\n :model-value=\"cfg.sheetCustomHeight\"\n :min=\"25\"\n :max=\"2000\"\n @update:model-value=\"patch({ sheetCustomHeight: $event })\"\n />\n </div>\n </div>\n\n <div v-else class=\"pd-field\">\n <span class=\"pd-label\">目标纸方向</span>\n <div class=\"pd-radio-group\" role=\"radiogroup\">\n <label class=\"pd-radio\">\n <input\n type=\"radio\"\n value=\"portrait\"\n :checked=\"(cfg.sheetOrientation ?? 'portrait') === 'portrait'\"\n @change=\"patch({ sheetOrientation: 'portrait' })\"\n ><span>纵向</span>\n </label>\n <label class=\"pd-radio\">\n <input\n type=\"radio\"\n value=\"landscape\"\n :checked=\"cfg.sheetOrientation === 'landscape'\"\n @change=\"patch({ sheetOrientation: 'landscape' })\"\n ><span>横向</span>\n </label>\n </div>\n </div>\n\n <h3 class=\"pd-divider\">拼版留白 (mm)</h3>\n <div class=\"margin-grid\">\n <div class=\"pd-field\"><span class=\"pd-label\">上</span>\n <StepperInput\n :model-value=\"cfg.sheetMargin.top\" :min=\"0\" :max=\"100\"\n @update:model-value=\"patchMargin('top', $event)\"\n />\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">下</span>\n <StepperInput\n :model-value=\"cfg.sheetMargin.bottom\" :min=\"0\" :max=\"100\"\n @update:model-value=\"patchMargin('bottom', $event)\"\n />\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">左</span>\n <StepperInput\n :model-value=\"cfg.sheetMargin.left\" :min=\"0\" :max=\"100\"\n @update:model-value=\"patchMargin('left', $event)\"\n />\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">右</span>\n <StepperInput\n :model-value=\"cfg.sheetMargin.right\" :min=\"0\" :max=\"100\"\n @update:model-value=\"patchMargin('right', $event)\"\n />\n </div>\n </div>\n\n <h3 class=\"pd-divider\">格间距与列数</h3>\n <div class=\"pd-field\"><span class=\"pd-label\">横向间距</span>\n <StepperInput\n :model-value=\"cfg.gapX\" :min=\"0\" :max=\"50\"\n @update:model-value=\"patch({ gapX: $event ?? 0 })\"\n />\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">纵向间距</span>\n <StepperInput\n :model-value=\"cfg.gapY\" :min=\"0\" :max=\"50\"\n @update:model-value=\"patch({ gapY: $event ?? 0 })\"\n />\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">列数</span>\n <StepperInput\n :model-value=\"cfg.columns\" :min=\"1\" :max=\"columnMax\"\n @update:model-value=\"patch({ columns: $event ?? 1 })\"\n />\n </div>\n\n <p\n v-for=\"issue in issues\"\n :key=\"issue.code\"\n class=\"pd-hint tiling-error\"\n >{{ issue.message }}</p>\n <p v-if=\"!issues.length && summary\" class=\"pd-hint tiling-summary\">{{ summary }}</p>\n </template>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport type { TemplateData } from '@worm-vue3-print/core/designer'\nimport { PAPER_PRESETS, isContinuousPaperSize } from '@worm-vue3-print/core/designer'\nimport {\n TILE_DEFAULTS,\n computeMaxColumns,\n computeTileLayout,\n resolveSheetMm,\n validateTiling,\n} from '@worm-vue3-print/core'\nimport type { TilingOptions } from '@worm-vue3-print/core'\nimport StepperInput from './StepperInput.vue'\n\nconst props = defineProps<{\n modelValue?: TilingOptions\n /** 完整模板:校验与摘要都需要标签纸尺寸/朝向,必须传 */\n templateData?: TemplateData\n}>()\n\nconst emit = defineEmits<{ 'update:modelValue': [value: TilingOptions] }>()\n\n/** 目标纸张可选预设:排除连续纸(含小票纸)与 CUSTOM(后者由下拉的「自定义」项承担) */\nconst sheetPresetKeys = Object.keys(PAPER_PRESETS)\n .filter(k => k !== 'CUSTOM' && !PAPER_PRESETS[k]?.continuous)\n\nconst labelContinuous = computed(() => isContinuousPaperSize(props.templateData?.paperSize))\n\n/**\n * 展示态配置:缺省字段补 TILE_DEFAULTS;未配置过拼版的模板 enabled 视为 false\n * (否则开关会显示成「已开启」)。\n */\nconst cfg = computed<TilingOptions>(() => ({\n ...TILE_DEFAULTS,\n ...(props.modelValue ?? {}),\n enabled: props.modelValue?.enabled ?? false,\n sheetMargin: { ...TILE_DEFAULTS.sheetMargin, ...(props.modelValue?.sheetMargin ?? {}) },\n}))\n\n/** 以当前配置构造的完整模板,供 core 的校验与布局纯函数使用(单一真实来源) */\nconst tilingTemplate = computed<TemplateData | undefined>(() =>\n props.templateData ? { ...props.templateData, tiling: cfg.value } : undefined)\n\nconst issues = computed(() =>\n tilingTemplate.value ? validateTiling(tilingTemplate.value) : [])\n\n/** 本纸最多可放列数;纯几何、不抛错,超宽时也能给出上限用于约束输入 */\nconst columnMax = computed(() => {\n const t = tilingTemplate.value\n if (!t) return 1\n return Math.max(computeMaxColumns(t), 1)\n})\n\nconst layout = computed(() => {\n const t = tilingTemplate.value\n if (!t || issues.value.length) return undefined\n try {\n return computeTileLayout(t)\n } catch {\n return undefined\n }\n})\n\nconst summary = computed(() => {\n const l = layout.value\n const t = tilingTemplate.value\n if (!l || !t) return ''\n const s = resolveSheetMm(t)\n const name = cfg.value.sheetPaperSize === 'CUSTOM' ? '自定义' : (cfg.value.sheetPaperSize ?? 'A4')\n const dir = cfg.value.sheetPaperSize === 'CUSTOM'\n ? ''\n : (cfg.value.sheetOrientation === 'landscape' ? ' 横向' : ' 纵向')\n return `目标纸 ${name}${dir} ${s.width}×${s.height}mm · ${l.columns} 列 × ${l.rows} 行 = 每张 ${l.perSheet} 格`\n})\n\nfunction patch(partial: Partial<TilingOptions>) {\n emit('update:modelValue', { ...cfg.value, ...partial })\n}\n\nfunction patchMargin(side: 'top' | 'right' | 'bottom' | 'left', value: number | undefined) {\n patch({ sheetMargin: { ...cfg.value.sheetMargin, [side]: value ?? 0 } })\n}\n\n/** 切换目标纸张:切到 CUSTOM 时补上当前解析尺寸,避免出现空宽高 */\nfunction onSheetPaperChange(value: string) {\n if (value !== 'CUSTOM') {\n patch({ sheetPaperSize: value as TilingOptions['sheetPaperSize'] })\n return\n }\n const t = tilingTemplate.value\n const current = t ? resolveSheetMm(t) : { width: 210, height: 297 }\n patch({\n sheetPaperSize: 'CUSTOM',\n sheetCustomWidth: cfg.value.sheetCustomWidth ?? current.width,\n sheetCustomHeight: cfg.value.sheetCustomHeight ?? current.height,\n })\n}\n\n/**\n * 打开开关时写入 TILE_DEFAULTS 并按纸面收敛列数:\n * 目标纸很小时默认 2 列可能直接非法到连保存都被拦,这里收敛为能放下的列数。\n * 关闭时保留其余字段(再次打开不丢配置)。\n */\nfunction onEnabledChange(next: boolean) {\n if (!next) {\n patch({ enabled: false })\n return\n }\n const max = columnMax.value\n const columns = max >= 1 ? Math.min(TILE_DEFAULTS.columns, max) : 1\n patch({ ...TILE_DEFAULTS, columns })\n}\n</script>\n\n<style scoped>\n.tiling-config {\n padding: 0 4px;\n}\n.tiling-switch {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n cursor: pointer;\n}\n.tiling-error {\n color: #f56c6c;\n}\n.tiling-summary {\n color: var(--pd-text-regular, #606266);\n}\n</style>\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 <!-- 条码/二维码设置(码制、条宽、缩放模式、最大宽高等) -->\n <CodeGroup v-if=\"filteredGroups.includes('code') && isCodeType\" :element=\"element\" :matched-keys=\"matchedKeys\" :searching=\"searching\" @change=\"recordHistory?.()\" />\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 <optgroup v-for=\"group in paperPresetGroups\" :key=\"group.group\" :label=\"group.group\">\n <option v-for=\"item in group.items\" :key=\"item.key\" :value=\"item.key\">{{ item.label }}</option>\n </optgroup>\n <option value=\"CUSTOM\">自定义宽高</option>\n </select>\n </div>\n <p v-if=\"labelPaper\" class=\"pd-hint\">标签纸默认整张给内容区:已取消页边距与页眉页脚,可在下方自行改回</p>\n <div class=\"pd-field\" v-if=\"continuousPaper || paperSizeModel === 'CUSTOM'\"><span class=\"pd-label\">{{ continuousPaper ? '纸宽 (mm)' : '自定义宽高 (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 <template v-if=\"paperSizeModel === 'CUSTOM'\">\n <span class=\"custom-size-x\">×</span>\n <StepperInput :model-value=\"customHeight\"\n :min=\"25\"\n :max=\"2000\"\n @update:model-value=\"onCustomHeightChange\" />\n </template>\n </div>\n </div>\n <div class=\"pd-field\" v-if=\"!continuousPaper\"><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 <p class=\"pd-hint\">切换即交换纸张长宽(设计稿内容随之铺在该尺寸上)</p>\n </div>\n <div class=\"pd-field\" v-if=\"!continuousPaper && !tilingEnabled\"><span class=\"pd-label\">内容旋转角度</span>\n <div class=\"pd-radio-group pd-radio-group--2col\" role=\"radiogroup\">\n <label class=\"pd-radio\"><input type=\"radio\" value=\"0\" :checked=\"outputRotationModel === 0\" @change=\"onOutputRotationChange(($event.target as HTMLInputElement).value)\"><span>0°</span></label>\n <label class=\"pd-radio\"><input type=\"radio\" value=\"90\" :checked=\"outputRotationModel === 90\" @change=\"onOutputRotationChange(($event.target as HTMLInputElement).value)\"><span>90°</span></label>\n <label class=\"pd-radio\"><input type=\"radio\" value=\"180\" :checked=\"outputRotationModel === 180\" @change=\"onOutputRotationChange(($event.target as HTMLInputElement).value)\"><span>180°</span></label>\n <label class=\"pd-radio\"><input type=\"radio\" value=\"270\" :checked=\"outputRotationModel === 270\" @change=\"onOutputRotationChange(($event.target as HTMLInputElement).value)\"><span>270°</span></label>\n </div>\n <p class=\"pd-hint\">整页内容旋转对应角度出纸;90°/270° 时纸张长宽互换以贴合内容,内容不变形不裁切;0° 为不旋转(默认)</p>\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 <DesignBackgroundConfig\n :model-value=\"designBackgroundModel\"\n @update:model-value=\"onDesignBackgroundChange\"\n />\n\n <TilingConfig\n v-if=\"!multiPage\"\n :model-value=\"templateData?.tiling\"\n :template-data=\"templateData\"\n @update:model-value=\"emitUpdate({ tiling: $event })\"\n />\n\n <h3 class=\"pd-divider\">页边距 (mm)</h3>\n <p v-if=\"continuousPaper\" class=\"pd-hint\">底部边距即连续纸走纸留白</p>\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=\"100\" @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\n <WatermarkConfig :model-value=\"watermarkModel\" :fields=\"fields\" @update:model-value=\"onWatermarkChange\" />\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 '@worm-vue3-print/core/designer'\nimport { PAPER_PRESETS, isContinuousPaperSize, isLabelPaperSize, labelPaperDefaults } from '@worm-vue3-print/core/designer'\nimport { searchProperties } from '@worm-vue3-print/core/designer'\nimport PropertySearch from './property/PropertySearch.vue'\nimport PositionSizeGroup from './property/PositionSizeGroup.vue'\nimport AppearanceGroup from './property/AppearanceGroup.vue'\nimport CodeGroup from './property/CodeGroup.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 WatermarkConfig from './WatermarkConfig.vue'\nimport DesignBackgroundConfig from './property/DesignBackgroundConfig.vue'\nimport TilingConfig from './property/TilingConfig.vue'\nimport type { WatermarkOptions } from '@worm-vue3-print/core/designer'\nimport { getElementBindings, getTableCellBindings } from '@worm-vue3-print/core/designer'\nimport type { BindingDescriptor } from '@worm-vue3-print/core/designer'\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 multiPage?: 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\n/** 纸张下拉分组:按 PAPER_PRESETS 的 group 聚合,保持预设声明顺序;多页时过滤连续纸(小票纸/热敏卷纸) */\nconst paperPresetGroups = computed(() => {\n const groups: { group: string; items: { key: string; label: string }[] }[] = []\n for (const [key, preset] of Object.entries(PAPER_PRESETS)) {\n if (props.multiPage && isContinuousPaperSize(key)) continue\n const group = preset.group ?? '其他'\n let bucket = groups.find(g => g.group === group)\n if (!bucket) {\n bucket = { group, items: [] }\n groups.push(bucket)\n }\n bucket.items.push({ key, label: preset.label ?? key })\n }\n return groups\n})\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 isCodeType = computed(() => {\n if (!props.element) return false\n return ['barcode', 'qrcode'].includes(props.element.printElementType.type)\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')\n/** 连续纸(含小票纸):强制纵向、纸宽可调、出纸高度按内容推导;多页模式不可用 */\nconst continuousPaper = computed(() => !props.multiPage && isContinuousPaperSize(paperSizeModel.value))\n/** 标签纸:切到该纸型时已套用「无页边距、无页眉页脚」默认版面 */\nconst labelPaper = computed(() => isLabelPaperSize(paperSizeModel.value))\nconst orientationModel = computed(() => props.templateData?.orientation || 'portrait')\n/** 拼版(标签铺格)无出纸方向概念,隐藏出纸方向控件 */\nconst tilingEnabled = computed(() => !!props.templateData?.tiling?.enabled)\n/**\n * 内容旋转角度:缺省 0(不旋转);可设为 90/180/270,整页内容旋转对应角度出纸。\n * 渲染端仅在固定纸(非连续纸、非拼版)场景按角度旋转整页。\n */\nconst outputRotationModel = computed(() => props.templateData?.outputRotation ?? 0)\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 ?? PAPER_PRESETS[paperSizeModel.value]?.width ?? 210)\nconst customHeight = computed(() => props.templateData?.customHeight ?? 297)\n\nconst designBackgroundModel = computed(() => props.templateData?.designBackground)\n\nfunction onDesignBackgroundChange(value: TemplateData['designBackground'] | undefined) {\n if (!props.templateData) return\n if (!value) {\n const rest = { ...props.templateData }\n delete rest.designBackground\n emit('update:templateData', rest)\n return\n }\n emitUpdate({ designBackground: value })\n}\n\n/** 水印配置(缺省时给空对象,WatermarkConfig 内部按默认值展示) */\nconst watermarkModel = computed<WatermarkOptions>(() => props.templateData?.watermark ?? {})\n\nfunction onWatermarkChange(value: WatermarkOptions) {\n emitUpdate({ watermark: value })\n}\n\nfunction emitUpdate(partial: Partial<TemplateData>) {\n if (!props.templateData) return\n const next = {\n ...props.templateData,\n ...partial,\n } as TemplateData\n emit('update:templateData', next)\n}\n\nfunction onPaperSizeChange(size: string) {\n if (!props.templateData) return\n if (isContinuousPaperSize(size)) {\n // 连续纸默认:纵向、底边距 0(走纸留白由用户配置);\n // 纸宽取 customWidth,切到具体小票纸预设时清掉旧自定义宽度,回到预设纸宽\n emitUpdate({\n paperSize: size as TemplateData['paperSize'],\n customWidth: size === 'CONTINUOUS' ? props.templateData?.customWidth ?? 80 : undefined,\n orientation: 'portrait',\n margins: {\n ...props.templateData!.margins,\n bottom: props.templateData?.margins.bottom ?? 0,\n },\n })\n return\n }\n if (size === 'CUSTOM') {\n emitUpdate({ paperSize: 'CUSTOM' })\n return\n }\n if (!PAPER_PRESETS[size]) return\n if (isLabelPaperSize(size)) {\n // 标签纸默认:整张纸都给内容区(无页边距、无页眉页脚),用户仍可在下方自行改回\n emitUpdate({ paperSize: size as TemplateData['paperSize'], ...labelPaperDefaults(props.templateData) })\n return\n }\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 onOutputRotationChange(val: string | number | boolean | undefined) {\n emitUpdate({ outputRotation: Number(val) as TemplateData['outputRotation'] })\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.pd-hint {\n margin: 2px 0 6px;\n color: var(--pd-text-muted, #8b909c);\n font-size: 12px;\n line-height: 1.4;\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 position: relative;\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>水印内容用统一的「水印表达式」输入:直接输入文字即为静态水印;写成 <code>{order.no}</code>、<code>CONCAT(...)</code> 等即按表达式解析</li>\n <li>点击「编辑表达式」(或双击输入框)打开表达式弹框,可直接选择业务字段与系统变量:打印日期 <code>{printDate}</code>、打印时间 <code>{printTime}</code>、当前页码 <code>{pageIndex}</code>、总页数 <code>{totalPages}</code>;表达式取不到值时回退到测试值</li>\n <li>可设置旋转角度(-90°~90°)、颜色与透明度</li>\n <li>支持调节水印密度(密/中/疏/自定义瓦片尺寸),以及设置水印颜色</li>\n <li>水印在画布、浏览器预览、服务端 PDF、静默打印四端渲染一致</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)、针式打印纸(全等分 / 二等分 / 三等分)、标签纸(80×60、60×40、40×30)、小票纸(57 / 80 / 110mm)</li>\n <li>或选择\"自定义\"输入宽度和高度(mm);\"连续纸\"可自定义纸宽,出纸高度按内容自动推导</li>\n <li>设置方向:纵向(portrait)或横向(landscape);切换即交换纸张长宽,设计稿内容随之铺在该尺寸上。连续纸与小票纸固定纵向</li>\n <li>内容旋转角度:0° / 90° / 180° / 270°,整页内容旋转对应角度出纸。90° / 270° 时纸张长宽互换以贴合旋转后的内容,设计稿内容保持原方向、不变形不裁切;0° 为不旋转(默认)。连续纸与小票纸固定纵向、无旋转概念</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</ul>\n<p>模板加载 / 重置(如「加载默认布局」)由宿主实现:把新的模板数据赋给 <code>initialTemplate</code> 即可重载画布。</p>\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<h2>为什么部分页面有水印、部分页面没有?</h2>\n<ol>\n <li>水印是<strong>按模板</strong>独立设置的,每一个设计的模板都需要单独配置自己的水印信息,不会自动继承其他模板。</li>\n <li>如果出现部分页面存在水印、部分页面没有水印的情况,说明该页面所在的模板没有为自身设置水印。</li>\n <li>为模板添加水印:进入该模板专属页面,在右侧的\"页面属性\"中找到\"水印\"配置项进行设计即可。</li>\n</ol>\n<blockquote>\n <p><strong>提示</strong>:水印配置保存在模板 JSON 的 <code>watermark</code> 字段中,仅对当前模板生效。</p>\n</blockquote>\n `\n}\n","export default {\n id: 'changelog',\n title: '更新记录',\n content: `\n<h2>v1.3.0 <small>2026-09-20</small></h2>\n\n<h3>新增</h3>\n<ul>\n <li><strong>多页面模板</strong>:一份文书可以由版式不同的多个页面按固定顺序组成(如「封面 + 正文 + 条款」),各页绑定同一份数据,下一次出纸就是完整的一份文档。顶部页面栏支持新增、复制、删除、前移/后移、双击重命名与点击切换;删到只剩一页时自动回到单页模式。</li>\n <li><strong>内容旋转角度</strong>:页面属性新增「内容旋转角度」(0° / 90° / 180° / 270°),支持横版设计、竖版出纸——内容整体旋转填满出纸版面,不缩放也不裁切。</li>\n <li><strong>设计背景(套打底图)</strong>:页面属性支持上传、90° 步进旋转与移除底图,照着现成单据排版更省力。底图只在设计画布显示,预览与打印都不会输出。</li>\n</ul>\n\n<h3>变更</h3>\n<ul>\n <li><strong>条码尺寸</strong>:条形码(元素与表格单元格)不再拉伸填满元素框,改为按「条宽 → 打印机分辨率 → 等比缩小」结算:默认条宽下每模块 0.25mm,装得下就按原尺寸落纸;设置了「打印机分辨率」(203/300/600)时吸附到整数打印点;宽度不足时整体等比缩小。要更大的条码请调大「条宽」,需要上限请用「最大宽高」——条形码不再提供「缩放模式」。<strong>同一份旧模板的条码会变小</strong>,这是让出纸条宽保持稳定所必需的。</li>\n <li><strong>文字溢出</strong>:文本元素与表格单元格支持「截断 / 自动缩小 / 自适应行高」三种显示形式(属性面板「文字溢出」),缺省值与原有行为一致,存量模板不受影响。</li>\n <li><strong>标签纸</strong>:纸张切到标签纸(80×60 / 60×40 / 40×30mm)时默认取消页边距与页眉页脚,整张纸都给内容区;只在切换纸型时套用一次,之后仍可自行改回,存量模板不会被改写。</li>\n <li><strong>多页面约束</strong>:纸张设置对所有页生效,页边距、页眉页脚、首页叠加、水印与内容元素则按页各自独立;多页模式下隐藏拼版配置、禁用连续纸。</li>\n</ul>\n\n<h3>修复</h3>\n<ul>\n <li>多页面模板页面重排后页签名漂移、删除页面后再新增出现重名。</li>\n <li>条形码经热敏打印机出纸条宽忽宽忽窄、边缘发灰;条宽倍率在不同模式下视觉不一致。</li>\n <li>元素堆叠与显式编组在分页时被拆散;单击编组内的任一成员改为选中整组。</li>\n <li>水印经真实打印机出纸被放大约 3 倍、位置偏移、平铺错乱(改为逐块矢量瓦片渲染)。</li>\n <li>小纸张模板(如 80×60mm 自定义纸)输出多出一张空白首页。</li>\n</ul>\n\n<h2>v1.2.2 <small>2026-09-11</small></h2>\n\n<h3>变更</h3>\n<ul>\n <li><code>@worm-vue3-print/core</code> 新增子路径 <code>/designer</code>:框架无关的设计器内核,包含完整模板模型类型、通用工具(元素工厂、表格矩阵、单位换算、模板迁移、标尺等)与纯交互逻辑(对齐、分组、键盘、缩放、吸附计算),不依赖 Vue/React。</li>\n <li><code>@worm-vue3-print/core</code> 新增子路径 <code>/browser</code>:浏览器侧渲染适配器(<code>renderHtmlPages</code> 两遍分页渲染、条形码/二维码渲染器)。</li>\n <li>设计器模型、工具与纯逻辑下沉至 core 子路径,canvas 仅保留 Vue 适配层;公共 API 保持不变,core 主入口仍为零运行时依赖,为后续多框架适配打下基础。</li>\n</ul>\n\n<h3>修复</h3>\n<ul>\n <li>修复工具栏放大/缩小按钮直接线性改缩放比例、未做滚动锚点校正导致画面漂移的问题;按钮缩放改为与 Ctrl+滚轮一致的乘性步进,并以视口中心为锚点(与「适应窗口」同一缩放管线)。</li>\n</ul>\n\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","<template>\n <div class=\"page-tabs\" @mouseover=\"onTipOver\" @mouseout=\"onTipOut\" @mouseleave=\"hideTip\">\n <div class=\"page-tabs-list\">\n <template v-for=\"(p, i) in pages\" :key=\"i\">\n <input\n v-if=\"editingIndex === i\"\n v-model=\"renameText\"\n class=\"page-tab-rename\"\n data-test=\"page-rename-input\"\n @blur=\"commitRename(i)\"\n @keydown.enter=\"commitRename(i)\"\n @keydown.esc=\"cancelRename\"\n />\n <button\n v-else\n class=\"page-tab\"\n :class=\"{ active: i === activeIndex }\"\n :data-tip=\"p.name ? `${p.name}(双击重命名)` : '双击重命名'\"\n @click=\"$emit('select', i)\"\n @dblclick=\"startRename(i)\"\n >\n {{ p.name || `页面 ${i + 1}` }}\n </button>\n </template>\n </div>\n <div class=\"page-tabs-actions\">\n <button data-test=\"add-page\" :data-tip=\"addTip\" :disabled=\"tilingEnabled\" @click=\"$emit('add')\">+</button>\n <button data-test=\"duplicate-page\" :data-tip=\"duplicateTip\" :disabled=\"tilingEnabled\" @click=\"$emit('duplicate')\">⧉</button>\n <button data-test=\"delete-page\" :data-tip=\"multi ? `删除当前页「${activeName}」` : '仅多页面模板可删除页面'\" :disabled=\"!multi\" @click=\"$emit('delete', activeIndex)\">✕</button>\n <button data-test=\"move-left\" :data-tip=\"`前移「${activeName}」`\" :disabled=\"activeIndex <= 0\" @click=\"$emit('move', activeIndex, activeIndex - 1)\">←</button>\n <button data-test=\"move-right\" :data-tip=\"`后移「${activeName}」`\" :disabled=\"activeIndex >= pages.length - 1\" @click=\"$emit('move', activeIndex, activeIndex + 1)\">→</button>\n </div>\n <!-- 自定义 tooltip:fixed 定位挂在本组件根下,不受页签列表 overflow 裁剪,z-index 高于画布各层 -->\n <div v-if=\"tip\" class=\"page-tabs-tip\" :style=\"{ left: `${tip.x}px`, top: `${tip.y}px` }\">{{ tip.text }}</div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, onUnmounted } from 'vue'\nimport type { TemplateData } from '@worm-vue3-print/core/designer'\nimport { TILING_SINGLE_PAGE_TIP } from '../composables/useDesignerState'\n\nconst props = defineProps<{\n pages: TemplateData[]\n activeIndex: number\n /** 多页模式(≥2 页)才可删除;单页回落单模板 */\n multi: boolean\n /** 已开启拼版:拼版模板只允许一个设计页面,禁用增页入口 */\n tilingEnabled?: boolean\n}>()\n\nconst emit = defineEmits<{\n select: [index: number]\n add: []\n duplicate: []\n delete: [index: number]\n rename: [index: number, name: string]\n move: [from: number, to: number]\n}>()\n\n// 行内重命名:双击页签进入编辑,blur/Enter 提交,Esc 取消\nconst editingIndex = ref(-1)\nconst renameText = ref('')\n\n/** 当前激活页名:用于操作按钮 tooltip 的上下文提示 */\nconst activeName = computed(() => props.pages[props.activeIndex]?.name || `页面 ${props.activeIndex + 1}`)\n\n/** 增页按钮 tooltip:拼版开启时改为「不可增页」的原因说明 */\nconst addTip = computed(() =>\n props.tilingEnabled ? TILING_SINGLE_PAGE_TIP : '新增页面(在当前页后追加空白页)')\nconst duplicateTip = computed(() =>\n props.tilingEnabled ? TILING_SINGLE_PAGE_TIP : `复制当前页「${activeName.value}」`)\n\nfunction startRename(i: number) {\n editingIndex.value = i\n renameText.value = props.pages[i]?.name ?? ''\n}\n\nfunction commitRename(i: number) {\n if (editingIndex.value !== i) return\n const name = renameText.value.trim()\n if (name) emit('rename', i, name)\n editingIndex.value = -1\n}\n\nfunction cancelRename() {\n editingIndex.value = -1\n}\n\n// 自定义 tooltip:事件委托到根节点,读 data-tip 与目标位置,延迟 300ms 显示避免滑过闪烁\ninterface TipState { text: string; x: number; y: number }\nconst tip = ref<TipState | null>(null)\nlet tipTimer: ReturnType<typeof setTimeout> | null = null\n\nfunction showTipFor(el: HTMLElement) {\n const text = el.dataset.tip\n if (!text) return\n const rect = el.getBoundingClientRect()\n // 水平以目标中心对齐并夹取到视口内(粗夹即可,translateX(-50%) 后偏差可忽略)\n const x = Math.min(Math.max(rect.left + rect.width / 2, 80), window.innerWidth - 80)\n tip.value = { text, x, y: rect.bottom + 6 }\n}\n\nfunction onTipOver(e: MouseEvent) {\n const el = (e.target as HTMLElement).closest?.('[data-tip]') as HTMLElement | null\n if (!el) return\n if (tipTimer) clearTimeout(tipTimer)\n tipTimer = setTimeout(() => showTipFor(el), 300)\n}\n\nfunction onTipOut(e: MouseEvent) {\n const el = (e.target as HTMLElement).closest?.('[data-tip]') as HTMLElement | null\n // 在同一目标内部移动(子元素间切换)不隐藏\n if (el && (e.relatedTarget as HTMLElement | null)?.closest?.('[data-tip]') === el) return\n hideTip()\n}\n\nfunction hideTip() {\n if (tipTimer) { clearTimeout(tipTimer); tipTimer = null }\n tip.value = null\n}\n\nonUnmounted(hideTip)\n</script>\n\n<style scoped>\n.page-tabs {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 4px 12px;\n background: var(--pd-sidebar, #fff);\n border-bottom: 1px solid var(--pd-border, #d9dde6);\n flex-shrink: 0;\n}\n.page-tabs-list {\n display: flex;\n gap: 4px;\n overflow-x: auto;\n align-items: center;\n}\n.page-tab {\n padding: 4px 12px;\n border: 1px solid var(--pd-border, #d9dde6);\n border-radius: 4px;\n background: transparent;\n cursor: pointer;\n white-space: nowrap;\n color: var(--pd-text, #2a2e37);\n font-size: 12px;\n}\n.page-tab.active {\n background: var(--pd-accent, #165DFF);\n color: #fff;\n}\n.page-tab-rename {\n padding: 4px 8px;\n width: 96px;\n border: 1px solid var(--pd-accent, #165DFF);\n border-radius: 4px;\n font-size: 12px;\n color: var(--pd-text, #2a2e37);\n outline: none;\n}\n.page-tabs-actions {\n display: flex;\n gap: 4px;\n margin-left: auto;\n}\n.page-tabs-actions button {\n padding: 4px 8px;\n border: 1px solid var(--pd-border, #d9dde6);\n border-radius: 4px;\n background: transparent;\n cursor: pointer;\n color: var(--pd-text-muted, #8b909c);\n font-size: 12px;\n line-height: 1;\n}\n.page-tabs-actions button:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n.page-tabs-tip {\n position: fixed;\n z-index: 9999;\n transform: translateX(-50%);\n padding: 4px 8px;\n border-radius: 4px;\n background: rgba(42, 46, 55, 0.92);\n color: #fff;\n font-size: 12px;\n line-height: 1.4;\n white-space: nowrap;\n pointer-events: none;\n}\n</style>\n","import { ref, watch } from 'vue'\n\nconst LEFT_KEY = 'print-studio:left'\nconst RIGHT_KEY = 'print-studio:right'\n\nfunction readStored(key: string, fallback: boolean): boolean {\n try {\n const raw = localStorage.getItem(key)\n return raw === null ? fallback : raw === '1'\n } catch {\n return fallback\n }\n}\n\nexport function useStudioChrome() {\n const leftCollapsed = ref(readStored(LEFT_KEY, false))\n const rightCollapsed = ref(readStored(RIGHT_KEY, false))\n const dirty = ref(false)\n\n watch(leftCollapsed, v => { try { localStorage.setItem(LEFT_KEY, v ? '1' : '0') } catch { /* ignore */ } }, { flush: 'sync' })\n watch(rightCollapsed, v => { try { localStorage.setItem(RIGHT_KEY, v ? '1' : '0') } catch { /* ignore */ } }, { flush: 'sync' })\n\n function toggleLeft() { leftCollapsed.value = !leftCollapsed.value }\n function toggleRight() { rightCollapsed.value = !rightCollapsed.value }\n function markSaved() { dirty.value = false }\n\n return { leftCollapsed, rightCollapsed, toggleLeft, toggleRight, dirty, markSaved }\n}\n","<template>\n <div class=\"designer-container\">\n <DesignerToolbar\n :is-edit=\"isEdit\"\n :can-undo=\"canUndo\"\n :can-redo=\"canRedo\"\n :has-multi-selection=\"selectedIds.size >= 2\"\n :has-selection=\"selectedIds.size >= 1\"\n :show-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-help=\"showHelp !== false\"\n v-model:scale=\"scale\"\n @preview=\"$emit('preview')\"\n @save=\"handleSave\"\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=\"onToolbarZoom\"\n @help=\"helpVisible = true\"\n />\n\n <!-- 页面栏:多页签 + 新增/复制/删除/排序 -->\n <PageTabs\n :pages=\"pages\"\n :active-index=\"activePageIndex\"\n :multi=\"pages.length > 1\"\n :tiling-enabled=\"tilingEnabled\"\n @select=\"switchPage\"\n @add=\"addPage\"\n @duplicate=\"duplicatePage\"\n @delete=\"deletePage\"\n @rename=\"renamePage\"\n @move=\"movePage\"\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 :multi-page=\"pages.length > 1\"\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, UploadDesignBackgroundFn, MultiPageTemplateData } from '@worm-vue3-print/core/designer'\nimport type { PrintFontDeclaration, PrintTemplateData, MultiPageTemplateData as PrintMultiPageTemplateData } from '@worm-vue3-print/core'\nimport { buildFontFaceCss, validateTiling, normalizeTemplate } from '@worm-vue3-print/core'\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 '@worm-vue3-print/core/designer'\nimport { getPaperDimensions, PAPER_PRESETS } from '@worm-vue3-print/core/designer'\nimport { DEFAULT_DEMO_DATA } from '@worm-vue3-print/core/designer'\nimport { findMainCell } from '@worm-vue3-print/core/designer'\nimport { computeFitScale, FIT_SCALE_MIN_PERCENT } from '@worm-vue3-print/core/designer'\nimport {\n UPLOAD_IMAGE_KEY,\n UPLOAD_DESIGN_BACKGROUND_KEY,\n FONT_CATALOG_KEY,\n} from '../composables/useHostAdapter'\nimport { useFontCatalog } from '../composables/useFontCatalog'\nimport { useDocumentFontFace } from '../composables/useDocumentFontFace'\nimport type { AlignMode } from '@worm-vue3-print/core/designer'\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 PageTabs from './PageTabs.vue'\nimport { useStudioChrome } from '../composables/useStudioChrome'\n\nconst props = defineProps<{\n initialTemplate?: TemplateData | MultiPageTemplateData\n initialElements?: RuntimeElement[]\n fields?: PrintBusinessField[]\n isEdit?: boolean\n /** 截图适配器(叠层对比):未注入时该功能不可用 */\n requestScreenshot?: RequestScreenshotFn\n /** 图片上传适配器:未注入时图片上传不可用 */\n uploadImage?: UploadImageFn\n /** 设计背景图上传适配器:未注入时背景上传入口禁用;返回值须为完整图片路径 */\n uploadDesignBackground?: UploadDesignBackgroundFn\n /** 是否展示帮助入口(帮助按钮与帮助弹框);默认开启,传 false 关闭 */\n showHelp?: boolean\n /**\n * 模板级字体声明(宿主配置):设计器据此注入 @font-face、在字体下拉中列出,\n * 并在保存/预览/截图时同步写入模板 JSON,供服务端与客户端出图使用同一份字体。\n */\n fonts?: readonly PrintFontDeclaration[]\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, tilingEnabled,\n selectedIds, selectedElement, select, selectElement, 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 pages, activePageIndex, switchPage, addPage, duplicatePage, deletePage, renamePage, movePage,\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))\nprovide(UPLOAD_DESIGN_BACKGROUND_KEY, computed(() => props.uploadDesignBackground))\n\nconst { catalog: fontCatalog } = useFontCatalog(computed(() => props.fonts))\nprovide(FONT_CATALOG_KEY, fontCatalog)\n\n/** 画布文档注入同一份 @font-face,保证设计期所见即出图所得 */\nuseDocumentFontFace(computed(() => buildFontFaceCss(props.fonts)))\n\n/**\n * 保存/预览/截图统一取这一份:把 prop 配置的字体同步写进模板 JSON,\n * 渲染端(服务端 / 客户端 / 浏览器)只认模板里的声明。宿主未配置时保留模板自带声明。\n */\nfunction templateJsonWithFonts(): TemplateData | MultiPageTemplateData {\n const json = getTemplateJson()\n if (!props.fonts?.length) return json\n if (Array.isArray((json as MultiPageTemplateData).pages)) {\n return { ...(json as MultiPageTemplateData), pages: (json as MultiPageTemplateData).pages.map(p => ({ ...p, fonts: [...props.fonts!] })) }\n }\n return { ...(json as TemplateData), fonts: [...props.fonts] }\n}\n\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 = templateJsonWithFonts()\n if (!templateJson) {\n alert('模板数据为空')\n return\n }\n if (!props.requestScreenshot) {\n alert('截图服务未配置')\n return\n }\n try {\n // 叠层对比针对当前激活页生成截图:多页模板取 activePage 单页模板\n const mp = templateJson as MultiPageTemplateData\n const activeTemplate: TemplateData = Array.isArray(mp.pages)\n ? mp.pages[activePageIndex.value]!\n : (templateJson as TemplateData)\n const blob = await props.requestScreenshot({ templateJson: activeTemplate, 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 const name = PAPER_PRESETS[t.paperSize]?.label ?? t.paperSize\n const base = `${name} ${orient} ${Math.round(dim.width)}×${Math.round(dim.height)}mm`\n // 出纸旋转角度非 0 时,状态栏明确提示(设计稿内容不旋转,仅整页内容旋转出纸)\n const rot = t.outputRotation\n if (rot) {\n return `${base}(旋转${rot}°)`\n }\n return base\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/**\n * 工具栏放大/缩小按钮:委托 CanvasArea.zoomByStep,\n * 与滚轮缩放共用乘性步进与锚点校正(以视口中心为不动点),\n * 避免直接改 scale 导致画面相对滚动位置漂移。\n * @param delta 工具栏固定传 ±10,仅用于判定放大/缩小方向\n */\nfunction onToolbarZoom(delta: number) {\n canvasAreaRef.value?.zoomByStep(delta > 0 ? 1 : -1)\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\n// 普通点击走分组感知:点组内成员选中整组;Ctrl/⌘ 多选按单元素切换\nconst onSelectElement = selectElement\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\n/**\n * 拼版配置校验(仅开启拼版时生效):列数超宽等非法配置不允许保存。\n * 输入过程只预警不阻断,真正的闸门在这里与 handleSave 上。\n */\nconst tilingIssues = computed(() => {\n const t = templateData.value\n if (t?.tiling?.enabled !== true) return []\n return validateTiling(t)\n})\n\ndefineExpose({\n getTemplateJson: templateJsonWithFonts,\n /**\n * 模板校验入口:`getTemplateJson()` 是绕过 handleSave 的旁路,\n * 宿主在导出/另存链路需自行调用本方法拦截非法配置。\n */\n validateTemplate: () => tilingIssues.value,\n})\n\nfunction handleSave() {\n // 非法拼版配置:给出原因并把用户带到「页面属性」页签,不落盘\n const issues = tilingIssues.value\n if (issues.length) {\n alert(issues[0].message)\n activePropertyTab.value = 'page'\n return\n }\n const json = templateJsonWithFonts()\n // 多页模板:保存前做归一化校验(纸张尺寸一致、禁连续纸/拼版),非法则阻断\n if (Array.isArray((json as MultiPageTemplateData).pages)) {\n try { normalizeTemplate(json as PrintTemplateData | PrintMultiPageTemplateData) } catch (e) { alert(e instanceof Error ? e.message : String(e)); return }\n }\n emit('save', JSON.stringify(json))\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","<!--\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 '@worm-vue3-print/core/browser'\nimport { browserCodeRenderer } from '@worm-vue3-print/core/browser'\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 * 相对路径字体基址。缺省不拼接:预览 iframe 与设计器同源,\n * 相对字体 URL 由页面 origin 解析,与画布注入 @font-face 的行为一致。\n * 字体与页面不同源时(如字体放 CDN)传绝对基址。\n */\n fontBaseUrl?: string\n}>()\n\nconst emit = defineEmits<{\n /** 渲染完成,回传总页数与份数(对象数据=1,数组=数组长度) */\n rendered: [pageCount: number, copies: 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, copies } = await renderHtmlPages(\n props.templateJson as PrintTemplateData,\n props.printData,\n props.baseUrl,\n browserCodeRenderer,\n { fontBaseUrl: props.fontBaseUrl },\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, copies)\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, props.fontBaseUrl],\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":["SELECTED_IDS_KEY","PREVIEW_IDS_KEY","useSelection","elements","selectedIds","ref","previewIds","selectedElements","computed","e","hasSelection","select","id","multiple","s","clearSelection","selectAll","allIds","setPreview","ids","clearPreview","commitPreview","getSelectionBounds","els","minL","minT","maxR","maxB","useClipboard","clipboard","copy","paste","offset","groupCounts","item","gid","groupIdMap","count","generateGroupId","generateId","hasData","useHistory","options","undoStack","redoStack","canUndo","canRedo","updateFlags","clone","state","cloned","cloneState","push","undo","currentState","popped","redo","clear","TILING_SINGLE_PAGE_TIP","createDefaultTemplate","toRuntimePool","data","mk","zone","syncTableElementSize","resolveInitialPages","initial","withDefaultName","p","i","rt","normalizeTemplateUnits","list","serializePage","page","all","ser","useDesignerState","scale","showRuler","showGrid","snapToGrid","showTableGhostBorder","pages","activePageIndex","templateData","tilingEnabled","blockPageAddIfTiling","flushActivePage","switchPage","resetPageSelection","fields","selectAllIds","groupElements","ungroupElements","getGroupedIds","useGroup","copyElements","pasteElements","hasClipboardData","align","useAlign","pushHistory","undoHistory","redoHistory","selectedElement","tableSelection","setTableSelection","getHistoryState","recordHistory","historyActiveElements","cutSelected","deleteSelected","pasted","duplicateSelected","resetZoom","hasClipboard","moveSessionActive","moveDebounceTimer","MOVE_SESSION_GAP_MS","moveSelected","dx","dy","movable","alignSelected","mode","selectElement","groupSelected","ungroupSelected","setupKeyboard","cleanupKeyboard","useKeyboard","draggingBeforeState","dragStart","dragStop","before","rejected","el","prev","finalizeElementZone","sig","beforeIds","afterIds","placeAtDropPoint","dropPoint","zoneFromPaperPoint","ZONE_ALLOWED_TYPES","rect","getZoneRects","clampToZone","addElement","type","createRuntimeElement","addFieldElement","field","createFieldElement","moveLayer","direction","currentZ","allZ","maxZ","minZ","fitToWindow","containerW","containerH","width","height","getPaperDimensions","MM_TO_PX","computeFitScale","updateTemplateData","paper","getTemplateJson","loadTemplate","nextDefaultPageName","used","n","addPage","base","np","duplicatePage","src","cp","deletePage","renamePage","name","movePage","from","to","moved","onMounted","onUnmounted","guideSeq","genId","useGuides","guides","mutate","fn","addGuide","position","moveGuide","g","removeGuide","getGuidePositions","v","h","TABLE_EDIT_KEY","UPLOAD_IMAGE_KEY","UPLOAD_DESIGN_BACKGROUND_KEY","FONT_CATALOG_KEY","EMPTY_FONT_CATALOG","useFontCatalog","declarations","out","seen","font","toValue","family","key","label","useInjectedFontCatalog","inject","findFontOption","fonts","f","fontOptionLabel","option","normalizeFontQuery","value","matchRank","nameKey","queryKey","cursor","char","filterFontOptions","query","index","fontMatchRank","a","b","byFamily","byLabel","STYLE_ID_PREFIX","useDocumentFontFace","css","styleId","useId","watchEffect","text","_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","emit","__emit","searchText","collapsedGroups","searching","filteredGroups","filterGroups","groupFields","toggleGroup","next","onDragStart","event","group","_normalizeStyle","activeTab","elementTypes","onFieldDrag","expandTab","tab","_withDirectives","FieldTreePanel","LayerPanel","m","d","useDrag","target","isDragging","dragPreview","startX","startY","startLeft","startTop","downAltKey","onMouseDown","targetEl","onMouseMove","onMouseUp","computePos","newLeft","newTop","w","result","pos","cleanup","setup","fitTargets","root","targets","node","restoreFitted","useShrinkFit","trigger","apply","fitTextNode","nextTick","V_ALIGN_FLEX","H_ALIGN_FLEX","rootRef","fit","resolveElementTextFit","baseFontSize","fitMinPt","resolveShrinkMinFontSize","textStyle","o","autoHeight","displayText","resolveTextBinding","imageSrc","raw","evaluateTemplate","DEFAULT_DEMO_DATA","hasError","onError","watch","imgStyle","ROW_TYPES","emitAction","payload","_createBlock","_Teleport","t","barcodeSvg","svgOk","dataUrl","size","FIT_TO_PAR","par","svgStyle","renderBarcode","unitPerModule","barcodeUnitsPerModule","JsBarcode","BARCODE_BAR_HEIGHT_MODULES","BARCODE_TEXT_FONT_SIZE_MODULES","BARCODE_QUIET_ZONE_MODULES","BARCODE_MARGIN_BOTTOM_MODULES","viewBox","readViewBox","settled","resolveBarcodeSize","barcodeAvailableBoxMm","svg","parts","renderQrcode","QRCode","render","_vShow","PX_PER_MM","HEIGHT_EPSILON_MM","ROW_TYPE_BADGE","editCtx","rows","colWidths","defaultFontSize","defaultColor","selection","rowTopMm","ri","tableRef","rowLayoutMm","measureTable","table","tableHpx","tableHmm","baseTop","tr","badgeTopMm","badgeHeightMm","demoList","ds","imageData","isCodeCell","cell","cellDisplay","_row","resolveBarcodeDesignValue","cellStyle","borderOpts","resolveCellBorderCss","cellTextFit","resolveCellTextFit","needsFitBox","cellBaseFontSize","cellCapMm","cellFitCapMm","cellBoxWidthMm","ci","cellFitWidthMm","cellFitStyle","row","c","cellClass","dragAnchor","applySelection","normalizeSelection","onCellMouseDown","r","onCellMouseEnter","onCellDblClick","menu","reactive","onCellContextMenu","mergeReason","canMergeReason","canSplit","rowTypeReason","setRowType","syncElementSize","checkColWidthLimit","cw","maxW","totalW","onMenuAction","rs","err","insertRow","deleteRow","insertCol","deleteCol","mergeCells","splitCells","colResizeEnabled","colResizeBoundaries","_","k","colBoundaryLeftMm","colResizeBoundary","resizeStartX","resizeStartWidth","onColResizeStart","onColResizeMove","onColResizeEnd","deltaMm","colIndex","widths","clampResizedColumnWidth","_withModifiers","CellBarcode","CellImage","_unref","TableContextMenu","isHline","lineStyle","bw","bs","bc","isOval","shapeStyle","svgRef","preserveAspectRatio","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","mmToPx","info","finalDx","finalDy","sibling","left","top","setupDrag","cleanupDrag","resizeEnabled","startResize","cleanupResize","useResize","onDblClick","onDblClickCell","elementId","_resolveDynamicComponent","_mergeProps","RESIZE_POINTS","useAdsorb","config","guideLines","paperSize","check","movingRect","others","computeAdsorb","renderLines","lines","paperW","paperH","clearLines","useAdsorbManager","requestAdsorb","clearGuides","contentRef","paperWidthMM","paperHeightMM","designBackground","backgroundLoadFailed","normalizedBackgroundRotation","designBackgroundStyle","rotation","swapped","layerW","layerH","style","onBackgroundError","guideHitPx","wrapperStyle","widthPx","heightPx","zoneRectsMM","headerH","footerH","contentW","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","watermarkLayout","resolveWatermarkLayout","zoneResizing","startZoneResize","cleanupZoneResize","onZoneResizeMove","onZoneResizeUp","startH","dyMM","maxH","onSelectElement","__expose","tile","idx","BaseElement","line","horizontal","guideType","canvasRef","hoverPx","effectiveCursorPx","cssSize","RULER_THICKNESS","rafId","scheduleDraw","draw","canvas","ctx","dpr","length","thickness","bg","fg","accent","pxPerMM","startMM","endMM","majorStep","chooseMajorStepMM","ticks","buildRulerTicks","drawTicks","drawPaperEdge","x","y","outside","tick","len","mm","color","onBeforeUnmount","dragging","axialFromEvent","along","onDown","onWinMove","onWinUp","updateDragPreview","onHoverMove","onHoverLeave","rulerGeom","rulerCursor","scrollPos","overlayStyle","measureRuler","area","ar","pr","targetScale","measuredScale","onScroll","resizeObserver","scaleMeasureRaf","startScaleMeasureLoop","endAt","loop","guidePreview","onGuideDragging","guidePreviewStyle","liveScale","toPaperPoint","pxToMm","onDrop","fieldData","elementType","marquee","marqueeStart","isCanvasBackground","areaRect","xMm","yMm","onMouseLeave","applyZoom","targetPercent","anchorX","anchorY","minPercent","container","cur","oldScale","ratio","cs","padX","padY","ax","ay","cs2","padX2","padY2","onWheel","oldPercent","newPercent","nextWheelScale","MIN_SCALE_PERCENT","zoomByStep","prevTransition","FIT_SCALE_MIN_PERCENT","onCanvasMouseDown","onMarqueeMove","onMarqueeUp","hitTestIds","paperRect","containMode","elLeft","elTop","elRight","elBottom","inter","contained","contextMenu","contextMenuRef","onContextMenu","elId","gap","closeContextMenu","handlePaste","handleSelectAll","handleClearSelection","action","arg","centerScroll","stableFrames","prevSW","prevSH","deadline","sw","sh","sw2","sh2","ch","CanvasPaper","Ruler","onSearch","isExpanded","iconChar","toggle","saveState","loadState","saved","_renderSlot","_ctx","precision","dot","roundTo","current","draft","atMin","atMax","clamp","stepBy","dir","onInput","commit","num","_withKeys","showItem","PropertyGroup","StepperInput","visible","triggerRef","panelRef","areaRef","panelStyle","hue","saturation","hexInput","areaDragging","normalizedValue","swatchStyle","activeColor","rgbToHex","hsvToRgb","hueModel","degree","setHsv","clampDegree","syncFromColor","selectNone","onHexInput","parseHex","normalizeHex","rgb","hsv","rgbToHsv","clamp01","startAreaDrag","setAreaFromEvent","moveAreaDrag","endAreaDrag","onAreaKeydown","step","handled","close","open","panelWidth","panelHeight","margin","below","onDocumentPointerDown","onWindowCloseEvents","onKeydown","match","hex","full","part","red","green","blue","max","min","hh","r1","g1","b1","number","PRESET_COLORS","catalog","listId","listRef","toDisplayName","highlighted","unknownFamily","make","kind","typed","matched","resolveTypedFamily","activeRowId","currentRowIndex","onOpen","onClick","move","last","scrollActiveIntoView","onEnter","pick","onCancel","isTableType","textFit","onTextFitChange","FontSelect","PresetColorPicker","_hoisted_17","_hoisted_18","_hoisted_19","_hoisted_21","_hoisted_22","_hoisted_24","isBarcode","isQrcode","barcodeType","dpiValue","hasPrinterDpi","dotAligned","onDpiChange","emitChange","onBarcodeTypeChange","onFitChange","val","searchPlaceholder","localExpression","handleFieldDoubleClick","insideParens","getCursorRegion","insertAtCursor","handleVariableDoubleClick","sv","handleFunctionDoubleClick","insideBlock","caretOffset","start","textareaRef","lastBlockOpen","lastParenOpen","filteredSystemVars","systemVars","keyword","filteredAggregateFuncs","aggregateFunctions","filteredFormatFuncs","formatFunctions","previewResult","resolveSystemVariables","ta","end","after","caretPos","onConfirm","_hoisted_20","_hoisted_23","_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","findMainCell","formatterEditorVisible","pendingFormatterValue","isBarcodeCell","isQrcodeCell","isImageCell","isTextCell","write","onAlignChange","onValignChange","onPrinterDpiChange","dpi","onCellTypeChange","openFormatterEditor","onFormatterEditorConfirm","borderStyle","borderWidth","borderColor","edgeChecks","currentBorder","preset","applyBorderPreset","onEdgesChange","edges","nb","side","doMerge","doSplit","_hoisted_26","_hoisted_34","_hoisted_36","_hoisted_38","_hoisted_39","_hoisted_40","_hoisted_42","_hoisted_44","_hoisted_46","_hoisted_47","_hoisted_48","_hoisted_49","_hoisted_51","_hoisted_52","_hoisted_53","_hoisted_54","_hoisted_55","_hoisted_56","_hoisted_57","_hoisted_58","_hoisted_59","_hoisted_60","_hoisted_61","_hoisted_62","_hoisted_64","_hoisted_66","_hoisted_67","_hoisted_68","_hoisted_69","densityPresets","WATERMARK_DENSITY_PRESETS","minTileWidth","WATERMARK_DEFAULTS","minTileHeight","isExpressionText","readText","expressionText","testData","exprEditorVisible","activeMode","localConfig","isExpression","density","tileWidth","tileHeight","onTextChanged","onChange","onTextInput","openExpressionEditor","onExpressionChange","onColorChange","uploadDesignBackground","onFileChange","onRotate","onRemove","_createTextVNode","sheetPresetKeys","PAPER_PRESETS","labelContinuous","isContinuousPaperSize","cfg","TILE_DEFAULTS","tilingTemplate","issues","validateTiling","columnMax","computeMaxColumns","layout","computeTileLayout","summary","l","resolveSheetMm","patch","partial","patchMargin","onSheetPaperChange","onEnabledChange","columns","issue","paperPresetGroups","groups","bucket","isTextType","isImageType","isCodeType","isTableCellSelected","searchResult","searchProperties","matchedKeys","bindingDescriptors","c1","listField","getTableCellBindings","getElementBindings","parsePath","targetPath","segment","baseName","indices","getBindingValue","seg","setBindingValue","segments","lastKey","obj","onImageUploadSuccess","paperSizeModel","continuousPaper","labelPaper","isLabelPaperSize","orientationModel","outputRotationModel","pageBackgroundModel","onPageBackgroundChange","marginTop","marginBottom","marginLeft","marginRight","headerHeight","footerHeight","overlayHeight","customWidth","customHeight","designBackgroundModel","onDesignBackgroundChange","rest","emitUpdate","watermarkModel","onWatermarkChange","onPaperSizeChange","labelPaperDefaults","onOrientationChange","onOutputRotationChange","onPageBackgroundReset","onCustomWidthChange","onCustomHeightChange","onMarginTopChange","onMarginBottomChange","onMarginLeftChange","onMarginRightChange","onHeaderHeightChange","onFooterHeightChange","onOverlayHeightChange","currentTab","PropertySearch","PositionSizeGroup","AppearanceGroup","CodeGroup","desc","BindingControl","ImageContentUpload","TableRowGroup","TableCellGroup","TableSettingsGroup","BorderBgGroup","PaginationGroup","AdvancedGroup","DesignBackgroundConfig","TilingConfig","_hoisted_35","_hoisted_37","_hoisted_41","_hoisted_43","WatermarkConfig","gettingStarted","features","shortcuts","faq","changelog","helpSections","STORAGE_KEY","sections","switchTab","tabId","currentContent","handleKeydown","_Transition","section","editingIndex","renameText","activeName","addTip","duplicateTip","startRename","commitRename","cancelRename","tip","tipTimer","showTipFor","onTipOver","onTipOut","hideTip","LEFT_KEY","RIGHT_KEY","readStored","fallback","useStudioChrome","leftCollapsed","rightCollapsed","dirty","toggleLeft","toggleRight","markSaved","helpVisible","onUndo","onRedo","onAlign","onGroup","onUngroup","onDeleteElement","onDragStop","onDropElement","onDropField","onMoveLayer","maxTableWidth","provide","fontCatalog","buildFontFaceCss","templateJsonWithFonts","json","canvasAreaRef","overlayVisible","screenshotUrl","overlayOpacity","toggleOverlay","templateJson","mp","activeTemplate","blob","coordinate","onCoordinate","paperLabel","dim","orient","rot","onFitWindow","onZoom","onToolbarZoom","onKeyFitWindow","tag","onTemplateDataChanged","prevHeader","prevFooter","onZoneHeightChange","onZoneHeightCommit","warnZoneOverflow","onAddOverlayElement","overlay","newEl","onToggleVisible","onToggleLocked","activePropertyTab","DBL_EDITABLE_FIELD","dblEditorVisible","dblEditTarget","dblEditorExpression","onDblClickElement","main","onDblEditorConfirm","onCloneElement","_pos","tilingIssues","handleSave","normalizeTemplate","DesignerToolbar","PageTabs","LeftPanel","CanvasArea","PropertyPanel","StatusBar","HelpModal","iframeRef","rendering","errorMsg","renderSeq","rerender","seq","html","pageCount","copies","renderHtmlPages","browserCodeRenderer","doc","print","win"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/composables/useSelection.ts","../src/composables/useClipboard.ts","../src/composables/useHistory.ts","../src/composables/useDesignerState.ts","../src/composables/useGuides.ts","../src/composables/useTableSelection.ts","../src/composables/useHostAdapter.ts","../src/composables/useFontCatalog.ts","../src/composables/useDocumentFontFace.ts","../src/components/HelpButton.vue","../src/components/DesignerToolbar.vue","../src/components/LayerPanel.vue","../src/components/FieldTreePanel.vue","../src/components/LeftPanel.vue","../src/composables/useDrag.ts","../src/composables/useShrinkFit.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/components/property/PropertySearch.vue","../src/components/property/PropertyGroup.vue","../src/components/property/StepperInput.vue","../src/components/property/PositionSizeGroup.vue","../src/components/PresetColorPicker.vue","../src/components/property/FontSelect.vue","../src/components/property/AppearanceGroup.vue","../src/components/property/CodeGroup.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/components/WatermarkConfig.vue","../src/components/property/DesignBackgroundConfig.vue","../src/components/property/TilingConfig.vue","../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/components/PageTabs.vue","../src/composables/useStudioChrome.ts","../src/components/PrintDesigner.vue","../src/components/PrintHtmlPreview.vue"],"sourcesContent":["// web/src/components/print/composables/useSelection.ts\nimport { ref, computed, type InjectionKey, type Ref } from 'vue'\nimport type { RuntimeElement } from '@worm-vue3-print/core/designer'\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 '@worm-vue3-print/core/designer'\nimport { generateId, generateGroupId } from '@worm-vue3-print/core/designer'\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 // 组 ID 重映射:粘贴副本绝不能与原组共用 groupId,否则拖一个全跟着动、无法拆分。\n // 仅当同一组在本次粘贴中出现 ≥2 个成员时才保留成组(分配新 ID);\n // 只复制了组内单个成员的,剥离 groupId,避免残留无意义的组身份。\n const groupCounts = new Map<string, number>()\n for (const item of clipboard.value) {\n const gid = item.options.groupId\n if (gid) groupCounts.set(gid, (groupCounts.get(gid) ?? 0) + 1)\n }\n const groupIdMap = new Map<string, string | undefined>()\n for (const [gid, count] of groupCounts) {\n groupIdMap.set(gid, count >= 2 ? generateGroupId() : undefined)\n }\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 groupId: item.options.groupId\n ? groupIdMap.get(item.options.groupId)\n : undefined,\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/useHistory.ts\nimport { ref } from 'vue'\nimport type { TemplateData } from '@worm-vue3-print/core/designer'\n\nexport interface HistoryState {\n elements: any[]\n templateData?: TemplateData\n /** 多页面快照:整份页面数组(深拷贝) */\n pages?: TemplateData[]\n /** 多页面快照:录制时的激活页索引 */\n activePageIndex?: number\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 const cloned: HistoryState = {\n elements: JSON.parse(JSON.stringify(state?.elements ?? [])),\n templateData: JSON.parse(JSON.stringify(state?.templateData ?? {})),\n }\n if (state?.pages) {\n cloned.pages = JSON.parse(JSON.stringify(state.pages))\n if (state.activePageIndex !== undefined) cloned.activePageIndex = state.activePageIndex\n }\n return cloned\n }\n\n /** 增量快照:只记录元素变更,templateData 只记录非 elements 部分 */\n function cloneIncremental(state: HistoryState): HistoryState {\n const clonedElements = JSON.parse(JSON.stringify(state.elements))\n const result: HistoryState = { elements: clonedElements }\n if (state.pages) {\n result.pages = JSON.parse(JSON.stringify(state.pages))\n if (state.activePageIndex !== undefined) result.activePageIndex = state.activePageIndex\n }\n const td = state.templateData\n if (td) {\n result.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 return result\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/useDesignerState.ts\n// 设计器核心状态管理:模板数据/选择/历史/剪贴板/编组/键盘/序列化\nimport { ref, computed, onMounted, onUnmounted } from 'vue'\nimport type {\n RuntimeElement, ElementType, ElementZone, PrintBusinessField, TemplateData,\n TableSelection, PrintElementData, MultiPageTemplateData,\n} from '@worm-vue3-print/core/designer'\nimport { createRuntimeElement, generateId } from '@worm-vue3-print/core/designer'\nimport { createFieldElement } from '@worm-vue3-print/core/designer'\nimport { normalizeTemplateUnits } from '@worm-vue3-print/core/designer'\nimport { syncTableElementSize } from '@worm-vue3-print/core/designer'\nimport { getPaperDimensions } from '@worm-vue3-print/core/designer'\nimport { computeFitScale } from '@worm-vue3-print/core/designer'\nimport {\n getZoneRects, zoneFromPaperPoint, clampToZone, finalizeElementZone, ZONE_ALLOWED_TYPES,\n} from '@worm-vue3-print/core/designer'\nimport { useSelection } from './useSelection'\nimport { useClipboard } from './useClipboard'\nimport { useAlign, type AlignMode } from '@worm-vue3-print/core/designer'\nimport { useGroup } from '@worm-vue3-print/core/designer'\nimport { useHistory, type HistoryState } from './useHistory'\nimport { useKeyboard } from '@worm-vue3-print/core/designer'\n\nexport interface DesignerStateOptions {\n initialTemplate?: TemplateData | MultiPageTemplateData\n initialElements?: RuntimeElement[]\n initialFields?: PrintBusinessField[]\n}\n\n/** 拼版模板只允许单页:增页入口(新增/复制)被拦截时的提示文案 */\nexport const TILING_SINGLE_PAGE_TIP = '开启拼版后只能有一个设计页面'\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\n/** 解析初始模板为运行时页面池:多页 wrapper 展开,单页归一为单元素数组 */\nfunction resolveInitialPages(initial?: TemplateData | MultiPageTemplateData): TemplateData[] {\n const withDefaultName = (p: TemplateData, i: number): TemplateData => {\n const rt = toRuntimePool(normalizeTemplateUnits(p))\n // 无名页面补存固定默认名:页签显示若依赖位置回退(页面 ${i+1}),\n // 页面重排后索引变化会导致页签名漂移并与已存储页名重名(如「页面 1」变「页面 2」)\n if (!rt.name) rt.name = `页面 ${i + 1}`\n return rt\n }\n if (!initial) return [withDefaultName(createDefaultTemplate(), 0)]\n const list = Array.isArray((initial as MultiPageTemplateData).pages)\n ? (initial as MultiPageTemplateData).pages\n : [initial as TemplateData]\n return list.length ? list.map(withDefaultName) : [withDefaultName(createDefaultTemplate(), 0)]\n}\n\n/** 单页运行时池序列化回三区模板 JSON(按 zone 拆回,补 id/type) */\nfunction serializePage(page: TemplateData): TemplateData {\n const all = page.elements as RuntimeElement[]\n const ser = (zone: ElementZone) => all\n .filter(e => (e.zone || 'content') === zone)\n .map(e => ({ id: e.id, type: e.printElementType.type, options: { ...e.options }, printElementType: { ...e.printElementType } }))\n return {\n unit: 'mm' as const, ...page,\n header: { ...page.header, elements: ser('header') },\n footer: { ...page.footer, elements: ser('footer') },\n firstPageOverlay: {\n ...page.firstPageOverlay,\n elements: (page.firstPageOverlay?.elements ?? []).map(e => ({\n id: e.id || generateId(), type: e.printElementType?.type || 'text',\n options: { ...e.options }, printElementType: { ...e.printElementType },\n })),\n },\n elements: ser('content'),\n guides: [...(page.guides ?? [])],\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 // 多页面模板:pages 列表 + 当前激活页\n const pages = ref<TemplateData[]>(resolveInitialPages(options.initialTemplate))\n const activePageIndex = ref(0)\n const templateData = ref<TemplateData>(pages.value[0] ?? toRuntimePool(createDefaultTemplate()))\n\n /** 拼版开关:任一页开启拼版即视为拼版模板。拼版按「一张纸铺多个标签」排版,与多页面互斥 */\n const tilingEnabled = computed(() => pages.value.some(p => p.tiling?.enabled === true))\n\n /**\n * 拼版模板的单页闸门:拦截新增/复制页面并提示,避免用户拼出非法多页拼版模板。\n * 返回 true 表示已拦截,调用方应直接 return。\n */\n function blockPageAddIfTiling(): boolean {\n if (!tilingEnabled.value) return false\n alert(TILING_SINGLE_PAGE_TIP)\n return true\n }\n\n function flushActivePage() {\n pages.value[activePageIndex.value] = templateData.value\n }\n\n function switchPage(i: number) {\n if (i < 0 || i >= pages.value.length) return\n flushActivePage()\n activePageIndex.value = i\n templateData.value = pages.value[i]!\n resetPageSelection()\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, getGroupedIds } = 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 resetPageSelection() {\n clearSelection()\n setTableSelection(null)\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 outputRotation: templateData.value.outputRotation,\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 pages: JSON.parse(JSON.stringify(pages.value)),\n activePageIndex: activePageIndex.value,\n }\n }\n\n function recordHistory() {\n pushHistory(getHistoryState())\n }\n\n /** 从历史快照取「激活页」元素(多页读 pages[activePageIndex],单页回退 elements) */\n function historyActiveElements(state: HistoryState): any[] {\n return state.pages?.[state.activePageIndex ?? 0]?.elements ?? state.elements\n }\n\n function undo() {\n const state = undoHistory(getHistoryState())\n if (state?.pages) {\n pages.value = state.pages\n activePageIndex.value = state.activePageIndex ?? 0\n templateData.value = pages.value[activePageIndex.value] ?? pages.value[0]!\n resetPageSelection()\n } else 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?.pages) {\n pages.value = state.pages\n activePageIndex.value = state.activePageIndex ?? 0\n templateData.value = pages.value[activePageIndex.value] ?? pages.value[0]!\n resetPageSelection()\n } else 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 /**\n * 画布/图层面板点击选择:普通点击组内任一成员 → 选中整组;\n * Ctrl/⌘ 多选仍按单元素切换,不做整组扩展。\n */\n function selectElement(id: string, multiple = false) {\n if (multiple) {\n select(id, true)\n return\n }\n selectedIds.value = new Set(getGroupedIds(elements.value, id))\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 = historyActiveElements(draggingBeforeState).map(sig).join('|')\n const afterIds = historyActiveElements(getHistoryState()).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 // 收敛引用:templateData 被重新赋值后同步回 pages,避免 renamePage 等原地改丢失\n pages.value[activePageIndex.value] = templateData.value\n if (pages.value.length > 1) {\n const paper = {\n paperSize: data.paperSize, orientation: data.orientation,\n outputRotation: data.outputRotation,\n customWidth: data.customWidth, customHeight: data.customHeight,\n }\n for (const p of pages.value) Object.assign(p, paper)\n }\n recordHistory()\n }\n\n /** 当前设计器状态序列化为模板 JSON(单一出口:多页出 wrapper,单页出裸值) */\n function getTemplateJson(): TemplateData | MultiPageTemplateData {\n flushActivePage()\n if (pages.value.length <= 1) return serializePage(pages.value[0]!)\n return { version: 1, pages: pages.value.map(serializePage) }\n }\n\n /** 加载模板数据(多页 wrapper 展开;三区合并进运行时元素池;旧数据按 pt 迁移为 mm) */\n function loadTemplate(data: TemplateData | MultiPageTemplateData, els?: RuntimeElement[]) {\n pages.value = resolveInitialPages(data)\n activePageIndex.value = 0\n templateData.value = pages.value[0]!\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 // 收敛引用:templateData 被重新赋值后同步回 pages[0]\n pages.value[activePageIndex.value] = templateData.value\n }\n pushHistory(getHistoryState())\n }\n\n /** 新增页默认名:从「页面 N」递增取第一个未被占用的名字,避免与现存页重名 */\n function nextDefaultPageName(): string {\n const used = new Set(pages.value.map(p => p.name))\n let n = pages.value.length + 1\n while (used.has(`页面 ${n}`)) n++\n return `页面 ${n}`\n }\n\n /** 新增页面:继承当前页纸张,激活并定位到新页;开启拼版时禁止增页 */\n function addPage() {\n if (blockPageAddIfTiling()) return\n flushActivePage()\n const base = pages.value[activePageIndex.value] ?? createDefaultTemplate()\n const np = toRuntimePool({\n ...createDefaultTemplate(),\n paperSize: base.paperSize, orientation: base.orientation,\n customWidth: base.customWidth, customHeight: base.customHeight,\n name: nextDefaultPageName(),\n })\n pages.value.push(np)\n activePageIndex.value = pages.value.length - 1\n templateData.value = np\n resetPageSelection()\n recordHistory()\n }\n\n /** 复制当前页:重建元素 id 避免同文档冲突,插入当前页之后并激活;开启拼版时禁止增页 */\n function duplicatePage() {\n if (blockPageAddIfTiling()) return\n flushActivePage()\n const src = pages.value[activePageIndex.value]!\n const cp: TemplateData = JSON.parse(JSON.stringify(src))\n cp.name = `${src.name ?? `页面 ${activePageIndex.value + 1}`} 副本`\n cp.elements = cp.elements.map((e: any) => ({ ...e, id: generateId() }))\n cp.firstPageOverlay = { ...cp.firstPageOverlay, elements: (cp.firstPageOverlay?.elements ?? []).map((e: any) => ({ ...e, id: generateId() })) }\n pages.value.splice(activePageIndex.value + 1, 0, cp)\n switchPage(activePageIndex.value + 1)\n recordHistory()\n }\n\n function deletePage(i: number) {\n if (pages.value.length <= 1) return\n flushActivePage()\n pages.value.splice(i, 1)\n if (i < activePageIndex.value) activePageIndex.value--\n else if (i === activePageIndex.value && activePageIndex.value >= pages.value.length) activePageIndex.value = pages.value.length - 1\n templateData.value = pages.value[activePageIndex.value]!\n resetPageSelection()\n recordHistory()\n }\n\n function renamePage(i: number, name: string) {\n if (pages.value[i]) pages.value[i].name = name\n }\n\n function movePage(from: number, to: number) {\n if (from === to) return\n flushActivePage()\n const [moved] = pages.value.splice(from, 1)\n pages.value.splice(to, 0, moved!)\n activePageIndex.value = to\n templateData.value = moved!\n resetPageSelection()\n recordHistory()\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, tilingEnabled,\n pages, activePageIndex, switchPage, addPage, duplicatePage, deletePage, renamePage, movePage,\n selectedIds, selectedElements, selectedElement, select, selectElement, 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 '@worm-vue3-print/core/designer'\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 '@worm-vue3-print/core/designer'\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 { UploadDesignBackgroundFn, UploadImageFn } from '@worm-vue3-print/core/designer'\nimport type { FontOption } from './useFontCatalog'\n\n/** 图片上传适配器:PrintDesigner provide,ImageContentUpload inject */\nexport const UPLOAD_IMAGE_KEY: InjectionKey<ComputedRef<UploadImageFn | undefined>> =\n Symbol('print-upload-image')\n\n/** 设计背景上传适配器:PrintDesigner provide,DesignBackgroundConfig inject */\nexport const UPLOAD_DESIGN_BACKGROUND_KEY: InjectionKey<ComputedRef<UploadDesignBackgroundFn | undefined>> =\n Symbol('print-upload-design-background')\n\n/** 字体目录(模板声明字体):PrintDesigner provide,属性面板 inject */\nexport const FONT_CATALOG_KEY: InjectionKey<ComputedRef<readonly FontOption[]>> =\n Symbol('print-font-catalog')\n","// 字体下拉的数据源:模板级字体声明(宿主经 PrintDesigner 的 fonts prop 传入)。\n// 声明随模板保存、由各端按 @font-face 加载,设计器不查询任何出图端的系统字体。\nimport { computed, inject, toValue, type ComputedRef, type MaybeRefOrGetter } from 'vue'\nimport type { PrintFontDeclaration } from '@worm-vue3-print/core'\nimport { FONT_CATALOG_KEY } from './useHostAdapter'\n\n/** 下拉候选项:family 写入模板,label 仅用于界面展示 */\nexport interface FontOption {\n family: string\n label?: string\n}\n\n/** 空目录:宿主未声明字体时的兜底 */\nexport const EMPTY_FONT_CATALOG: ComputedRef<readonly FontOption[]> = computed(() => [])\n\n/**\n * 由 PrintDesigner 调用:把模板字体声明整理为下拉候选项。\n * 去空白、丢空值、族名大小写不敏感去重,保留声明顺序(顺序即宿主期望的优先级)。\n */\nexport function useFontCatalog(\n declarations?: MaybeRefOrGetter<readonly PrintFontDeclaration[] | undefined>,\n): { catalog: ComputedRef<readonly FontOption[]> } {\n const catalog = computed<readonly FontOption[]>(() => {\n const out: FontOption[] = []\n const seen = new Set<string>()\n for (const font of toValue(declarations) ?? []) {\n const family = font?.family?.trim()\n if (!family) continue\n const key = family.toLowerCase()\n if (seen.has(key)) continue\n seen.add(key)\n const label = font.label?.trim()\n out.push(label ? { family, label } : { family })\n }\n return out\n })\n return { catalog }\n}\n\n/** 由深层组件调用(属性面板):未注入时回退空目录,组件可独立挂载 */\nexport function useInjectedFontCatalog(): ComputedRef<readonly FontOption[]> {\n return inject(FONT_CATALOG_KEY, EMPTY_FONT_CATALOG)\n}\n\n/** 在目录中按族名查找(大小写不敏感) */\nexport function findFontOption(\n fonts: readonly FontOption[],\n family?: string,\n): FontOption | undefined {\n const key = family?.trim().toLowerCase()\n if (!key) return undefined\n return fonts.find(f => f.family.trim().toLowerCase() === key)\n}\n\n/** 下拉选项文案:有展示名时补上真实族名(写入模板的值) */\nexport function fontOptionLabel(option: FontOption): string {\n return option.label ? `${option.label}(${option.family})` : option.family\n}\n\n/** 匹配用键:小写并去掉全部空白,使用户输入 `ya hei` 与 `yahei` 等价 */\nexport function normalizeFontQuery(value: string): string {\n return value.toLowerCase().replace(/\\s+/g, '')\n}\n\n/**\n * 匹配档位,越小越靠前:\n * 0 完全相等 · 1 前缀 · 2 子串 · 3 子序列(首字母缩写式) · -1 不匹配\n */\nfunction matchRank(nameKey: string, queryKey: string): number {\n if (nameKey === queryKey) return 0\n if (nameKey.startsWith(queryKey)) return 1\n if (nameKey.includes(queryKey)) return 2\n let cursor = 0\n for (const char of nameKey) {\n if (char === queryKey[cursor]) cursor++\n if (cursor === queryKey.length) return 3\n }\n return -1\n}\n\n/**\n * 模糊过滤字体目录:完全相等 > 前缀 > 子串 > 子序列,同档保持目录原有顺序\n * (目录顺序由宿主声明决定,过滤不应打乱)。\n * 族名与展示名(label)都参与匹配,设计者按业务名搜也能命中。\n */\nexport function filterFontOptions(\n fonts: readonly FontOption[],\n query: string,\n): FontOption[] {\n const queryKey = normalizeFontQuery(query.trim())\n if (!queryKey) return [...fonts]\n return fonts\n .map((font, index) => ({ font, index, rank: fontMatchRank(font, queryKey) }))\n .filter(item => item.rank >= 0)\n .sort((a, b) => a.rank - b.rank || a.index - b.index)\n .map(item => item.font)\n}\n\n/** 族名与展示名取更优的一档;两者都不命中返回 -1 */\nfunction fontMatchRank(font: FontOption, queryKey: string): number {\n const byFamily = matchRank(normalizeFontQuery(font.family), queryKey)\n if (!font.label) return byFamily\n const byLabel = matchRank(normalizeFontQuery(font.label), queryKey)\n if (byFamily < 0) return byLabel\n return byLabel < 0 ? byFamily : Math.min(byFamily, byLabel)\n}\n","// 把模板声明字体的 @font-face 注入设计器所在文档:\n// 否则画布只能用系统字体渲染,出图却用模板的 webfont,所见非所得。\nimport { onUnmounted, toValue, useId, watchEffect, type MaybeRefOrGetter } from 'vue'\n\nconst STYLE_ID_PREFIX = 'print-designer-font-face'\n\nexport function useDocumentFontFace(css: MaybeRefOrGetter<string>): void {\n // 每实例唯一,多个设计器同页时不产生重复 id(与 FontSelect 的列表 id 同一处理)\n const styleId = `${STYLE_ID_PREFIX}-${useId()}`\n let el: HTMLStyleElement | undefined\n\n watchEffect(() => {\n const text = toValue(css)\n if (!text) {\n el?.remove()\n el = undefined\n return\n }\n if (!el) {\n el = document.createElement('style')\n el.id = styleId\n document.head.appendChild(el)\n }\n el.textContent = text\n })\n\n onUnmounted(() => {\n el?.remove()\n el = undefined\n })\n}\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=\"撤销\"><Undo2 :size=\"15\" /></button>\n <button class=\"tb-btn tb-icon\" :disabled=\"!canRedo\" @click=\"$emit('redo')\" data-tip=\"重做\"><Redo2 :size=\"15\" /></button>\n </div>\n <!-- 对齐分布(多选) -->\n <div class=\"tb-group\" v-if=\"hasMultiSelection\">\n <button class=\"tb-btn tb-icon\" @click=\"$emit('align', 'left')\" data-tip=\"左对齐\"><AlignStartVertical :size=\"15\" /></button>\n <button class=\"tb-btn tb-icon\" @click=\"$emit('align', 'right')\" data-tip=\"右对齐\"><AlignEndVertical :size=\"15\" /></button>\n <button class=\"tb-btn tb-icon\" @click=\"$emit('align', 'top')\" data-tip=\"顶对齐\"><AlignStartHorizontal :size=\"15\" /></button>\n <button class=\"tb-btn tb-icon\" @click=\"$emit('align', 'bottom')\" data-tip=\"底对齐\"><AlignEndHorizontal :size=\"15\" /></button>\n <button class=\"tb-btn tb-icon\" @click=\"$emit('align', 'vertical')\" data-tip=\"水平居中\"><AlignCenterVertical :size=\"15\" /></button>\n <button class=\"tb-btn tb-icon\" @click=\"$emit('align', 'horizontal')\" data-tip=\"垂直居中\"><AlignCenterHorizontal :size=\"15\" /></button>\n <button class=\"tb-btn tb-icon\" @click=\"$emit('align', 'distributeHor')\" data-tip=\"水平分布\"><AlignHorizontalSpaceBetween :size=\"15\" /></button>\n <button class=\"tb-btn tb-icon\" @click=\"$emit('align', 'distributeVer')\" data-tip=\"垂直分布\"><AlignVerticalSpaceBetween :size=\"15\" /></button>\n </div>\n <!-- 组合 -->\n <div class=\"tb-group\" v-if=\"hasMultiSelection || selectedElementHasGroup\">\n <button v-if=\"hasMultiSelection\" class=\"tb-btn tb-icon\" @click=\"$emit('group')\" data-tip=\"组合 (Ctrl+G)\"><GroupIcon :size=\"15\" /></button>\n <button v-if=\"selectedElementHasGroup\" class=\"tb-btn tb-icon\" @click=\"$emit('ungroup')\" data-tip=\"取消组合 (Ctrl+Shift+G)\"><UngroupIcon :size=\"15\" /></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=\"置顶\"><ArrowUpToLine :size=\"15\" /></button>\n <button class=\"tb-btn tb-icon\" @click=\"$emit('move-layer', 'up')\" data-tip=\"上移一层\"><ArrowUp :size=\"15\" /></button>\n <button class=\"tb-btn tb-icon\" @click=\"$emit('move-layer', 'down')\" data-tip=\"下移一层\"><ArrowDown :size=\"15\" /></button>\n <button class=\"tb-btn tb-icon\" @click=\"$emit('move-layer', 'bottom')\" data-tip=\"置底\"><ArrowDownToLine :size=\"15\" /></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=\"适应窗口\"><Maximize :size=\"15\" /></button>\n <button class=\"tb-btn tb-icon\" @click=\"$emit('zoom', -10)\" data-tip=\"缩小\"><ZoomOut :size=\"15\" /></button>\n <span class=\"tb-zoom\">{{ scale }}%</span>\n <button class=\"tb-btn tb-icon\" @click=\"$emit('zoom', 10)\" data-tip=\"放大\"><ZoomIn :size=\"15\" /></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\" data-tip=\"添加一个仅在首页叠加显示的页眉/页脚元素\" @click=\"$emit('add-overlay-element')\">首页专属</button>\n <button class=\"tb-btn\" :class=\"{ warn: overlayVisible }\" data-tip=\"叠加显示渲染截图,与设计稿对比效果\" @click=\"$emit('toggle-overlay')\">叠层对比</button>\n </div>\n <div class=\"tb-group\">\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 {\n Undo2,\n Redo2,\n AlignStartVertical,\n AlignEndVertical,\n AlignStartHorizontal,\n AlignEndHorizontal,\n AlignCenterVertical,\n AlignCenterHorizontal,\n AlignHorizontalSpaceBetween,\n AlignVerticalSpaceBetween,\n ArrowUpToLine,\n ArrowUp,\n ArrowDown,\n ArrowDownToLine,\n Maximize,\n ZoomOut,\n ZoomIn,\n Group as GroupIcon,\n Ungroup as UngroupIcon,\n} from 'lucide-vue-next'\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 /** 是否展示帮助入口(工具栏帮助按钮);默认开启,传 false 关闭 */\n showHelp?: boolean\n}>(), {\n showRuler: true,\n showHelp: true,\n})\n\ndefineEmits<{\n preview: []\n save: []\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, $event.ctrlKey || $event.metaKey)\"\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 <ArrowUpToLine :size=\"14\" />\n </button>\n <button type=\"button\" class=\"pd-button small\" @click=\"$emit('move-layer', 'up')\" title=\"上移\">\n <ArrowUp :size=\"14\" />\n </button>\n <button type=\"button\" class=\"pd-button small\" @click=\"$emit('move-layer', 'down')\" title=\"下移\">\n <ArrowDown :size=\"14\" />\n </button>\n <button type=\"button\" class=\"pd-button small\" @click=\"$emit('move-layer', 'bottom')\" title=\"置底\">\n <ArrowDownToLine :size=\"14\" />\n </button>\n </div>\n <div class=\"layer-actions\" v-if=\"canGroup || canUngroup\">\n <button type=\"button\" class=\"pd-button small\" v-if=\"canGroup\" @click=\"$emit('group')\" title=\"组合 (Ctrl+G)\">\n <GroupIcon :size=\"14\" />\n </button>\n <button type=\"button\" class=\"pd-button small\" v-if=\"canUngroup\" @click=\"$emit('ungroup')\" title=\"取消组合 (Ctrl+Shift+G)\">\n <UngroupIcon :size=\"14\" />\n </button>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { ArrowUpToLine, ArrowUp, ArrowDown, ArrowDownToLine, Group as GroupIcon, Ungroup as UngroupIcon } from 'lucide-vue-next'\nimport type { RuntimeElement } from '@worm-vue3-print/core/designer'\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 group: []\n ungroup: []\n}>()\n\nconst selectedElements = computed(() => props.elements.filter(e => props.selectedIds.has(e.id)))\nconst canGroup = computed(() => selectedElements.value.length >= 2)\nconst canUngroup = computed(() => selectedElements.value.some(e => !!e.options.groupId))\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","<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 '@worm-vue3-print/core/designer'\nimport { groupFields, filterGroups } from '@worm-vue3-print/core/designer'\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 @group=\"$emit('group')\"\n @ungroup=\"$emit('ungroup')\"\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 '@worm-vue3-print/core/designer'\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 group: []\n ungroup: []\n 'toggle-visible': [id: string]\n 'toggle-locked': [id: string]\n 'field-drag': [field: PrintBusinessField]\n 'toggle-collapse': []\n}>()\n\nconst activeTab = ref('elements')\n\nconst elementTypes: { type: ElementType; label: string; icon: string }[] = [\n { type: 'text', label: '文本', icon: 'T' },\n { type: 'barcode', label: '条形码', icon: '▍▍' },\n { type: 'qrcode', label: '二维码', icon: '▦' },\n { type: 'image', label: '图片', icon: '▧' },\n { type: 'table', label: '表格', icon: '⊞' },\n { type: 'longText', label: '长文', icon: '¶' },\n { type: 'hline', label: '横线', icon: '―' },\n { type: 'vline', label: '竖线', icon: '│' },\n { type: 'rect', label: '矩形', icon: '▭' },\n { type: 'oval', label: '椭圆', icon: '◯' },\n { type: 'html', label: 'HTML', icon: '<>' },\n]\n\nfunction onDragStart(event: DragEvent, type: string) {\n event.dataTransfer?.setData('elementType', type)\n}\n\nfunction onFieldDrag(field: PrintBusinessField) {\n emit('field-drag', field)\n}\n\nfunction expandTab(tab: string) {\n activeTab.value = tab\n emit('toggle-collapse')\n}\n</script>\n\n<style scoped>\n.left-panel {\n width: 224px;\n min-width: 224px;\n background: var(--pd-sidebar, #ffffff);\n border-right: 1px solid var(--pd-border-soft, #e9ecf2);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n transition: width .18s ease;\n}\n.left-panel.collapsed {\n width: 36px;\n min-width: 36px;\n border-right: 1px solid var(--pd-border-soft, #e9ecf2);\n}\n.left-collapsed {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n padding-top: 12px;\n flex: 1;\n}\n.lc-btn {\n width: 26px;\n height: 26px;\n border-radius: 6px;\n border: 1px solid transparent;\n background: transparent;\n color: var(--pd-text-muted, #8b909c);\n font-size: 12px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all .14s ease;\n}\n.lc-btn:hover {\n color: var(--pd-text, #2a2e37);\n background: var(--pd-sidebar-hover, #f0f3f9);\n}\n.lc-btn.on {\n color: var(--pd-accent, #165DFF);\n background: var(--pd-accent-soft, rgba(22, 93, 255, .09));\n}\n.left-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n height: 42px;\n padding: 0 12px;\n flex-shrink: 0;\n border-bottom: 1px solid var(--pd-border-soft, #e9ecf2);\n}\n.left-title {\n font-size: 12px;\n font-weight: 600;\n color: var(--pd-text, #2a2e37);\n letter-spacing: 1.2px;\n display: inline-flex;\n align-items: center;\n gap: 7px;\n}\n.left-title::before {\n content: \"\";\n width: 3px;\n height: 12px;\n border-radius: 2px;\n background: linear-gradient(180deg, var(--pd-accent-2, #3D7BFF), var(--pd-accent, #165DFF));\n}\n.collapse-btn {\n border: none;\n background: transparent;\n color: var(--pd-text-muted, #8b909c);\n font-size: 14px;\n cursor: pointer;\n width: 24px;\n height: 24px;\n border-radius: 5px;\n transition: all .14s ease;\n}\n.collapse-btn:hover {\n color: var(--pd-text, #2a2e37);\n background: var(--pd-sidebar-hover, #f0f3f9);\n}\n.left-tabs {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n.left-tabs .pd-tab-pane {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n padding: 12px;\n}\n.panel-title {\n font-size: 11px;\n color: var(--pd-text-muted, #8b909c);\n letter-spacing: .6px;\n padding: 2px 2px 8px;\n margin-bottom: 10px;\n border-bottom: 1px solid var(--pd-border-soft, #e9ecf2);\n}\n.material-card {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 8px 10px;\n margin-bottom: 7px;\n border: 1px solid var(--pd-border-soft, #e9ecf2);\n border-radius: 8px;\n background: var(--pd-field-bg, #f4f6fa);\n cursor: grab;\n user-select: none;\n transition: border-color .14s ease, background .14s ease, transform .14s ease, box-shadow .14s ease;\n}\n.material-card:hover {\n border-color: rgba(22, 93, 255, .45);\n background: var(--pd-surface, #ffffff);\n transform: translateY(-1px);\n box-shadow: var(--pd-shadow-sm, 0 1px 2px rgba(23, 32, 60, .05));\n}\n.material-card:active {\n cursor: grabbing;\n transform: translateY(0);\n}\n.material-icon {\n width: 30px;\n height: 24px;\n border: 1px dashed var(--pd-border, #d9dde6);\n border-radius: 5px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 11px;\n color: var(--pd-accent, #165DFF);\n background: var(--pd-surface, #ffffff);\n flex-shrink: 0;\n transition: border-color .14s ease, background .14s ease;\n}\n.material-card:hover .material-icon {\n border-style: solid;\n border-color: var(--pd-accent, #165DFF);\n background: var(--pd-accent-soft, rgba(22, 93, 255, .09));\n}\n.material-label {\n font-size: 12.5px;\n color: var(--pd-text, #2a2e37);\n}\n</style>\n","// web/src/components/print/composables/useDrag.ts\nimport { ref } from 'vue'\nimport type { AdsorbResult } from '@worm-vue3-print/core/designer'\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 // 仅响应左键,右键/中键不启动拖拽(右键由 contextmenu 处理)\n if (e.button !== 0) return\n // 忽略 resize 手柄点击;条码等 SVG 元素的 e.target 是 SVGElement,需一并放行(classList 在 Element 基类上)\n const targetEl = e.target\n if (!(targetEl instanceof Element) || 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","// 自动缩小(textFit='shrink')在画布上的落地:\n// 与打印管线共用 core 的 fitTextNode(同一套二分算法),\n// 使「设计态看到的字号」就是「出纸的字号」,不出现预览/出纸两副面孔。\nimport { nextTick, onMounted, watchEffect, type Ref } from 'vue'\nimport { fitTextNode } from '@worm-vue3-print/core/browser'\n\n/** 容器自身(元素级缩小)与后代(单元格级缩小)中所有缩放下限节点 */\nfunction fitTargets(root: HTMLElement): HTMLElement[] {\n const targets: HTMLElement[] = []\n if (root.getAttribute('data-fit') === 'shrink') targets.push(root)\n root.querySelectorAll<HTMLElement>('[data-fit=\"shrink\"]').forEach(node => targets.push(node))\n return targets\n}\n\n/**\n * 复原:曾被缩过(data-fit-size)但当前已不在缩小模式的节点,把字号写回基准值。\n * 不做这一步,从「自动缩小」切回「截断」时会残留上一次缩小后的字号。\n */\nfunction restoreFitted(root: HTMLElement): void {\n root.querySelectorAll<HTMLElement>('[data-fit-size]').forEach(node => {\n if (node.getAttribute('data-fit') === 'shrink') return\n node.removeAttribute('data-fit-size')\n const base = node.getAttribute('data-fit-base')\n if (base) node.style.fontSize = `${base}pt`\n else node.style.removeProperty('font-size')\n })\n}\n\n/**\n * @param root 元素根节点(元素级缩小挂在根上,单元格级挂在根的后代上)\n * @param trigger 依赖采集:字号/尺寸/内容/模式变化时重新适配\n */\nexport function useShrinkFit(root: Ref<HTMLElement | null>, trigger: () => unknown): void {\n const apply = (): void => {\n const el = root.value\n if (!el) return\n fitTargets(el).forEach(fitTextNode)\n restoreFitted(el)\n }\n // flush: 'post' 保证在 DOM 更新后测量;Vue 只在绑定值变化时重写内联样式,不会冲掉适配结果\n watchEffect(() => {\n void trigger()\n void nextTick(apply)\n }, { flush: 'post' })\n onMounted(() => {\n void nextTick(apply)\n })\n}\n","<template>\n <div\n ref=\"rootRef\"\n class=\"print-text\"\n :style=\"textStyle\"\n :data-fit=\"fit === 'shrink' ? 'shrink' : undefined\"\n :data-fit-base=\"String(baseFontSize)\"\n :data-fit-min=\"String(fitMinPt)\"\n >\n {{ displayText }}\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport type { RuntimeElement } from '@worm-vue3-print/core/designer'\nimport { resolveTextBinding } from '@worm-vue3-print/core/designer'\nimport { resolveElementTextFit, resolveShrinkMinFontSize } from '@worm-vue3-print/core/designer'\nimport { useShrinkFit } from '../../composables/useShrinkFit'\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 rootRef = ref<HTMLElement | null>(null)\n\n/** 溢出显示形式:截断 / 自动缩小 / 自适应行高(未配置时文本元素默认截断) */\nconst fit = computed(() => resolveElementTextFit('text', props.element.options))\nconst baseFontSize = computed(() => props.element.options.fontSize || 12)\nconst fitMinPt = computed(() => resolveShrinkMinFontSize(props.element.options.shrinkMinFontSize))\n\nconst textStyle = computed(() => {\n const o = props.element.options\n const autoHeight = fit.value === 'autoHeight'\n return {\n fontSize: baseFontSize.value + '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 // 自适应行高:不锁定高度,内容撑开;其余形式锁高度并裁剪\n height: autoHeight ? 'auto' : '100%',\n boxSizing: 'border-box' as const,\n overflow: autoHeight ? 'visible' : 'hidden',\n ...(o.wordWrap === false ? { whiteSpace: 'nowrap' as const, textOverflow: 'ellipsis' 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.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\nuseShrinkFit(rootRef, () => [\n fit.value,\n baseFontSize.value,\n fitMinPt.value,\n props.element.options.width,\n props.element.options.height,\n props.element.options.wordWrap,\n props.element.options.letterSpacing,\n props.element.options.lineHeight,\n displayText.value,\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 '@worm-vue3-print/core/designer'\nimport { evaluateTemplate } from '@worm-vue3-print/core/designer'\nimport { DEFAULT_DEMO_DATA } from '@worm-vue3-print/core/designer'\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\n ref=\"rootRef\"\n class=\"print-longtext\"\n :style=\"textStyle\"\n :data-fit=\"fit === 'shrink' ? 'shrink' : undefined\"\n :data-fit-base=\"String(baseFontSize)\"\n :data-fit-min=\"String(fitMinPt)\"\n >\n {{ displayText }}\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport type { RuntimeElement } from '@worm-vue3-print/core/designer'\nimport { resolveTextBinding } from '@worm-vue3-print/core/designer'\nimport { resolveElementTextFit, resolveShrinkMinFontSize } from '@worm-vue3-print/core/designer'\nimport { useShrinkFit } from '../../composables/useShrinkFit'\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 rootRef = ref<HTMLElement | null>(null)\n\n/** 溢出显示形式:长文本未配置时默认自适应行高(与打印端一致) */\nconst fit = computed(() => resolveElementTextFit('longText', props.element.options))\nconst baseFontSize = computed(() => props.element.options.fontSize || 12)\nconst fitMinPt = computed(() => resolveShrinkMinFontSize(props.element.options.shrinkMinFontSize))\n\nconst textStyle = computed(() => {\n const o = props.element.options\n const autoHeight = fit.value === 'autoHeight'\n return {\n fontSize: baseFontSize.value + '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 // 自适应行高:不锁定高度,内容撑开;其余形式锁高度并裁剪\n height: autoHeight ? 'auto' : '100%',\n overflow: autoHeight ? 'visible' : 'hidden',\n wordBreak: 'break-all' as const,\n boxSizing: 'border-box' as const,\n ...(o.wordWrap === false ? { whiteSpace: 'nowrap' as const, textOverflow: 'ellipsis' 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\nuseShrinkFit(rootRef, () => [\n fit.value,\n baseFontSize.value,\n fitMinPt.value,\n props.element.options.width,\n props.element.options.height,\n props.element.options.wordWrap,\n props.element.options.lineHeight,\n displayText.value,\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 '@worm-vue3-print/core/designer'\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=\"par\" :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'\nimport {\n BARCODE_BAR_HEIGHT_MODULES,\n BARCODE_MARGIN_BOTTOM_MODULES,\n BARCODE_QUIET_ZONE_MODULES,\n BARCODE_TEXT_FONT_SIZE_MODULES,\n barcodeAvailableBoxMm,\n barcodeUnitsPerModule,\n resolveBarcodeSize,\n} from '@worm-vue3-print/core/designer'\n\nconst props = defineProps<{\n cellType: 'barcode' | 'qrcode'\n value: string\n barcodeType?: string\n qrCodeLevel?: string\n /**\n * 条形码下方是否显示文本,缺省视为「显示」(与出图端 `showBarcodeText` 同口径)。\n * 注意:Vue 会把缺省的布尔 prop 转成 false,调用方必须显式传 `cell.showBarcodeText !== false`。\n */\n showText?: boolean\n fit?: string\n maxWidth?: number\n maxHeight?: number\n /** 打印机分辨率(点/英寸):给出后条形码尺寸吸附到整数打印点 */\n printerDpi?: number\n /** 单元格可用宽度(mm),点对齐用 */\n targetWidthMm?: number\n /** 单元格可用高度(mm),点对齐用 */\n targetHeightMm?: number\n /** 条码模块宽度倍率(2-4),缺省 2(与独立条码元素同口径) */\n barWidth?: number\n /** 条码下方文本字号(相对条高,条高为 30),缺省 BARCODE_TEXT_FONT_SIZE_MODULES */\n barFontSize?: number\n}>()\n\nconst barcodeSvg = ref<SVGSVGElement | null>(null)\nconst svgOk = ref(false)\nconst dataUrl = ref('')\n/** 结算后的落纸尺寸(mm);结算失败时为 null(回退等比缩放到单元格内) */\nconst size = ref<{ width: string; height: string } | null>(null)\n\n/**\n * 缩放模式 → preserveAspectRatio(内联 svg 不支持 object-fit)。\n * 单元格条码尺寸由条宽与打印机分辨率结算后显式给出,这里只用于二维码图片与兜底情形。\n */\nconst FIT_TO_PAR = {\n contain: 'xMidYMid meet',\n cover: 'xMidYMid slice',\n fill: 'none',\n none: 'xMidYMid meet',\n 'scale-down': 'xMidYMid meet',\n} as const\n\nconst par = computed(\n () => FIT_TO_PAR[(props.fit || 'contain') as keyof typeof FIT_TO_PAR] ?? 'xMidYMid meet',\n)\n\nconst svgStyle = computed(() => {\n // 结算尺寸就是最终 mm(条宽 / 打印机 dpi / 可用框三者算出),不再叠加缩放限制,避免二次缩放\n if (size.value) {\n return { width: size.value.width, height: size.value.height }\n }\n return {\n maxWidth: props.maxWidth ? `${props.maxWidth}mm` : '100%',\n maxHeight: props.maxHeight ? `${props.maxHeight}mm` : '100%',\n }\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\n/**\n * 与出图端(browser-code-renderer)共用同一份 jsbarcode 参数:\n * 单元格现在支持 barWidth 倍率,unitPerModule = barWidth / 2(与独立条码元素同口径)。\n */\nfunction renderBarcode() {\n svgOk.value = false\n size.value = null\n if (!barcodeSvg.value) return\n const unitPerModule = barcodeUnitsPerModule(props.barWidth)\n try {\n JsBarcode(barcodeSvg.value, props.value, {\n format: (props.barcodeType || 'CODE128') as any,\n width: unitPerModule,\n height: BARCODE_BAR_HEIGHT_MODULES * unitPerModule,\n displayValue: props.showText !== false,\n fontSize: (props.barFontSize ?? BARCODE_TEXT_FONT_SIZE_MODULES) * unitPerModule,\n // 静区只留左右(与出图端同参):上下留白会白白吃掉单元格高度\n margin: 0,\n marginLeft: BARCODE_QUIET_ZONE_MODULES * unitPerModule,\n marginRight: BARCODE_QUIET_ZONE_MODULES * unitPerModule,\n marginTop: 0,\n marginBottom: BARCODE_MARGIN_BOTTOM_MODULES * unitPerModule,\n })\n } catch {\n return /* 码值不符合码制:回退文本占位 */\n }\n svgOk.value = true\n\n // 与出图端共用同一份结算算法:条宽定首选尺寸,有 dpi 时吸附到整数打印点,可用宽高不足则等比缩小\n const viewBox = readViewBox(barcodeSvg.value)\n const settled = viewBox\n ? resolveBarcodeSize({\n unitWidth: viewBox.width / unitPerModule,\n unitHeight: viewBox.height / unitPerModule,\n // 最大宽高并入可用框(与出图端同一助手),作为结算上限而非事后 CSS 缩放\n boxWidthMm: barcodeAvailableBoxMm(props.targetWidthMm, props.maxWidth),\n boxHeightMm: barcodeAvailableBoxMm(props.targetHeightMm, props.maxHeight),\n dpi: props.printerDpi,\n barWidth: props.barWidth,\n })\n : null\n size.value = settled ? { width: `${settled.widthMm}mm`, height: `${settled.heightMm}mm` } : null\n // 抗锯齿会在条边缘生成灰像素,热敏头只有黑白两态 → 与出图端一致地关掉\n barcodeSvg.value.setAttribute('shape-rendering', 'crispEdges')\n}\n\n/** jsbarcode 会把 viewBox 写成 \"0 0 W H\";解析失败时返回 null(不启用点对齐) */\nfunction readViewBox(svg: SVGSVGElement): { width: number; height: number } | null {\n const parts = (svg.getAttribute('viewBox') ?? '').trim().split(/[\\s,]+/).map(Number)\n if (parts.length !== 4 || parts.some(v => !Number.isFinite(v))) return null\n return { width: parts[2]!, height: parts[3]! }\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(\n () => [\n props.cellType, props.value, props.barcodeType, props.qrCodeLevel, props.showText,\n props.printerDpi, props.targetWidthMm, props.targetHeightMm,\n props.barWidth, props.barFontSize, props.maxWidth, props.maxHeight,\n ],\n render,\n)\n</script>\n\n<style scoped>\n.cell-barcode { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; overflow: hidden; }\n/* 条码 svg 自带 viewBox 与结算后的显式 mm 尺寸(内联 style),这里只做溢出兜底 */\n.cell-barcode svg { max-width: 100%; max-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 '@worm-vue3-print/core/designer'\nimport { DEFAULT_DEMO_DATA } from '@worm-vue3-print/core/designer'\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 ref=\"rootRef\" 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 !== false\"\n :fit=\"cell.fit\"\n :max-width=\"cell.maxWidth\"\n :max-height=\"cell.maxHeight\"\n :printer-dpi=\"cell.printerDpi\"\n :target-width-mm=\"cellBoxWidthMm(ci, cell)\"\n :target-height-mm=\"cellCapMm(ri, cell)\"\n :bar-width=\"cell.barWidth\"\n :bar-font-size=\"cell.barFontSize\"\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 <!-- 截断 / 自动缩小:内容包定高容器(max-height = 可用高度),超出即裁 -->\n <div\n v-else-if=\"needsFitBox(cell)\"\n class=\"cell-fit\"\n :style=\"cellFitStyle(cell, ri)\"\n :data-fit=\"cellTextFit(cell) === 'shrink' ? 'shrink' : undefined\"\n :data-fit-base=\"String(cellBaseFontSize(cell))\"\n :data-fit-min=\"String(resolveShrinkMinFontSize(cell.shrinkMinFontSize))\"\n :data-fit-mm=\"cellCapMm(ri, cell)\"\n >\n <span v-if=\"row.type === 'data'\" class=\"data-placeholder\">\n {{ cellDisplay(row, cell) }}\n </span>\n <template v-else>{{ cellDisplay(row, cell) }}</template>\n </div>\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 '@worm-vue3-print/core/designer'\nimport {\n normalizeSelection, canMergeReason, mergeCells, splitCells,\n insertRow, deleteRow, insertCol, deleteCol, setRowType, syncTableElementSize,\n resolveCellBorderCss, clampResizedColumnWidth,\n} from '@worm-vue3-print/core/designer'\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 '@worm-vue3-print/core/designer'\nimport { DEFAULT_DEMO_DATA } from '@worm-vue3-print/core/designer'\nimport type { TextFit } from '@worm-vue3-print/core/designer'\nimport { cellFitCapMm, cellFitWidthMm, resolveCellTextFit, resolveShrinkMinFontSize } from '@worm-vue3-print/core/designer'\nimport { useShrinkFit } from '../../composables/useShrinkFit'\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/** 元素根节点:单元格自动缩小(data-fit)挂在其后代上,统一由此适配 */\nconst rootRef = ref<HTMLElement | 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\n// ─── 文字溢出显示形式(截断 / 自动缩小 / 自适应行高) ───\n\n/** 单元格溢出形式;与打印端 resolveCellTextFit 同一判定 */\nfunction cellTextFit(cell: TableCell): TextFit {\n return resolveCellTextFit(cell)\n}\n\n/** 截断与自动缩小都需要定高容器;自适应行高由单元格自身撑高 */\nfunction needsFitBox(cell: TableCell): boolean {\n return cellTextFit(cell) !== 'autoHeight'\n}\n\n/** 单元格基准字号:自动缩小的起点(与打印端 data-fit-base 同口径) */\nfunction cellBaseFontSize(cell: TableCell): number {\n return cell.fontSize ?? defaultFontSize.value\n}\n\n/** 可用内容高度(mm):所跨行高之和扣除内边距与边框,与打印端同一函数 */\nfunction cellCapMm(ri: number, cell: TableCell): number {\n return cellFitCapMm(rows.value, ri, cell, props.element.options.tableDefaultPadding ?? 1)\n}\n\n/** 可用内容宽度(mm):所跨列宽之和扣除内边距与边框,与打印端同一函数;列宽缺失时为 0 */\nfunction cellBoxWidthMm(ci: number, cell: TableCell): number {\n return cellFitWidthMm(colWidths.value, ci, cell, props.element.options.tableDefaultPadding ?? 1)\n}\n\nfunction cellFitStyle(cell: TableCell, ri: number): Record<string, string> {\n return {\n maxHeight: cellCapMm(ri, cell) + 'mm',\n overflow: 'hidden',\n ...(cell.wordWrap === false ? { whiteSpace: 'nowrap', textOverflow: 'ellipsis' } : {}),\n }\n}\n\n// 单元格自动缩小:与打印端共用 core 的二分算法,设计态字号即出纸字号\nuseShrinkFit(rootRef, () => [\n props.designMode,\n props.data?.length,\n colWidths.value.join(','),\n defaultFontSize.value,\n props.element.options.tableDefaultPadding,\n rows.value\n .map(row => `${row.height}:${row.cells.map(c => `${c.formatter ?? ''}|${c.fontSize ?? ''}|${c.wordWrap ?? ''}|${c.textFit ?? ''}|${c.colspan ?? 1}`).join('~')}`)\n .join(','),\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 // 仅响应左键,右键不拖动列宽\n if (e.button !== 0) 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 '@worm-vue3-print/core/designer'\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 '@worm-vue3-print/core/designer'\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=\"preserveAspectRatio\" :style=\"svgStyle\"></svg>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, onMounted, watch } from 'vue'\nimport JsBarcode from 'jsbarcode'\nimport { resolveTextBinding } from '@worm-vue3-print/core/designer'\nimport {\n BARCODE_BAR_HEIGHT_MODULES,\n BARCODE_MARGIN_BOTTOM_MODULES,\n BARCODE_QUIET_ZONE_MODULES,\n BARCODE_TEXT_FONT_SIZE_MODULES,\n barcodeAvailableBoxMm,\n barcodeUnitsPerModule,\n resolveBarcodeSize,\n} from '@worm-vue3-print/core/designer'\nimport type { RuntimeElement } from '@worm-vue3-print/core/designer'\n\nconst props = defineProps<{\n element: RuntimeElement\n data?: Record<string, any>[]\n designMode?: boolean\n}>()\n\nconst svgRef = ref<SVGSVGElement | null>(null)\n/** 结算后的落纸尺寸(mm):与出图端同源(条宽定首选 → DPI 吸附 → 框不够等比缩小) */\nconst size = ref<{ width: string; height: string } | null>(null)\n\n/**\n * 缩放模式 → preserveAspectRatio(内联 svg 不支持 object-fit)。\n * 条码尺寸由条宽与打印机分辨率结算,不再被拉伸填满元素框,故这里只作兜底:\n * 结算尺寸缺失(viewBox 解析失败等极端情形)时才让 CSS 接管等比适配。\n */\nconst FIT_TO_PAR = {\n contain: 'xMidYMid meet',\n cover: 'xMidYMid slice',\n fill: 'none',\n none: 'xMidYMid meet',\n 'scale-down': 'xMidYMid meet',\n} as const\n\nconst preserveAspectRatio = computed(\n () => FIT_TO_PAR[(props.element.options.fit || 'contain') as keyof typeof FIT_TO_PAR] ?? 'xMidYMid meet',\n)\n\n/**\n * 显式给出结算后的 mm 尺寸(与出图端同一份算法),未结算成功时回退等比缩放到元素框内。\n */\nconst svgStyle = computed(() => {\n if (size.value) {\n return { width: size.value.width, height: size.value.height }\n }\n return { maxWidth: '100%', maxHeight: '100%' }\n})\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 unitPerModule = barcodeUnitsPerModule(o.barWidth)\n try {\n JsBarcode(svgRef.value, value, {\n format: (o.barcodeType || 'CODE128') as any,\n width: unitPerModule,\n height: BARCODE_BAR_HEIGHT_MODULES * unitPerModule,\n displayValue: !o.hideTitle,\n fontSize: (o.fontSize ?? BARCODE_TEXT_FONT_SIZE_MODULES) * unitPerModule,\n // 静区只留左右(与出图端同参):上下留白会白白吃掉元素高度\n margin: 0,\n marginLeft: BARCODE_QUIET_ZONE_MODULES * unitPerModule,\n marginRight: BARCODE_QUIET_ZONE_MODULES * unitPerModule,\n marginTop: 0,\n marginBottom: BARCODE_MARGIN_BOTTOM_MODULES * unitPerModule,\n })\n } catch {\n size.value = null\n return /* 码值不符合码制:保留空白 svg */\n }\n\n // 与出图端共用同一份结算算法:条宽定首选尺寸,有 dpi 时吸附到整数打印点,框不够则等比缩小\n const viewBox = readViewBox(svgRef.value)\n const settled = viewBox\n ? resolveBarcodeSize({\n unitWidth: viewBox.width / unitPerModule,\n unitHeight: viewBox.height / unitPerModule,\n // 最大宽高并入可用框:与出图端一致地作为结算上限,而不是事后用 CSS 再缩一次\n boxWidthMm: barcodeAvailableBoxMm(o.width, o.maxWidth),\n boxHeightMm: barcodeAvailableBoxMm(o.height, o.maxHeight),\n dpi: o.printerDpi,\n barWidth: o.barWidth,\n })\n : null\n size.value = settled ? { width: `${settled.widthMm}mm`, height: `${settled.heightMm}mm` } : null\n // 抗锯齿会在条边缘生成灰像素,热敏头只有黑白两态 → 与出图端一致地关掉\n svgRef.value.setAttribute('shape-rendering', 'crispEdges')\n}\n\n/** jsbarcode 会把 viewBox 写成 \"0 0 W H\";解析失败时返回 null(不启用点对齐) */\nfunction readViewBox(svg: SVGSVGElement): { width: number; height: number } | null {\n const parts = (svg.getAttribute('viewBox') ?? '').trim().split(/[\\s,]+/).map(Number)\n if (parts.length !== 4 || parts.some(v => !Number.isFinite(v))) return null\n return { width: parts[2]!, height: parts[3]! }\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.printerDpi,\n props.element.options.hideTitle,\n props.element.options.fontSize,\n props.element.options.maxWidth,\n props.element.options.maxHeight,\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/* 非点对齐模式:SVG 使用固有尺寸(由 barWidth 决定),约束在容器内 */\n.print-barcode svg { max-width: 100%; max-height: 100%; }\n</style>\n","<template>\n <div class=\"print-qrcode\">\n <img v-if=\"dataUrl\" :src=\"dataUrl\" alt=\"qrcode\" :style=\"imgStyle\" />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, onMounted, watch } from 'vue'\nimport QRCode from 'qrcode'\nimport { resolveTextBinding } from '@worm-vue3-print/core/designer'\nimport type { RuntimeElement } from '@worm-vue3-print/core/designer'\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\n/** 最大宽高(mm)与出图端 codeImgHtml 的 max-width/max-height 同口径 */\nconst imgStyle = computed(() => {\n const o = props.element.options\n return {\n objectFit: (o.fit || 'contain') as any,\n maxWidth: o.maxWidth ? `${o.maxWidth}mm` : '100%',\n maxHeight: o.maxHeight ? `${o.maxHeight}mm` : '100%',\n }\n})\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(\n () => [props.element.options.formatter, props.element.options.testData, props.element.options.qrCodeLevel],\n render,\n)\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 '@worm-vue3-print/core/designer'\nimport { evaluateTemplate } from '@worm-vue3-print/core/designer'\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 '@worm-vue3-print/core/designer'\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 '@worm-vue3-print/core/designer'\nimport { useDrag } from '../../composables/useDrag'\nimport type { DragOptions } from '../../composables/useDrag'\nimport { generateId } from '@worm-vue3-print/core/designer'\nimport { useResize, RESIZE_POINTS } from '@worm-vue3-print/core/designer'\nimport { mmToPx } from '@worm-vue3-print/core/designer'\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 // 单个元素克隆不继承原组身份,否则克隆体会与原组串在一起、无法独立操作\n clone.options.groupId = undefined\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 // 选中由模板 mousedown 处理器统一负责;此处不得重复 emit,\n // 否则会把 Ctrl+点击刚加入的多选重置为单选\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 // 仅左键触发选中,右键交给 contextmenu 菜单\n if (e.button !== 0) 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","// 吸附逻辑的 Vue 适配层:引导线/纸张尺寸保持响应式状态,\n// 吸附坐标与引导线计算全部委托 @worm-vue3-print/core/designer 的纯函数。\nimport { ref, type Ref } from 'vue'\nimport {\n computeAdsorb,\n type AdsorbConfig,\n type ElementRect,\n type AlignLine,\n type AdsorbResult,\n} from '@worm-vue3-print/core/designer'\n\nexport type { AdsorbConfig }\n\nexport function useAdsorb(config: AdsorbConfig = {}) {\n /** 引导线响应式数据,由模板 v-for 渲染 */\n const guideLines: Ref<AlignLine[]> = ref([])\n\n /** 纸张尺寸(mm),用于引导线贯穿整页 */\n const paperSize = ref({ width: 0, height: 0 })\n\n function check(\n movingRect: ElementRect,\n others: ElementRect[],\n guides?: { vertical: number[]; horizontal: number[] },\n ): AdsorbResult {\n return computeAdsorb(movingRect, others, guides, config)\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 '@worm-vue3-print/core/designer'\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 <!-- 设计背景(定位底图):仅设计画布显示,位于纸张最底层,不参与打印管线 -->\n <div\n v-if=\"designMode && designBackground?.src && !backgroundLoadFailed\"\n class=\"design-background\"\n :style=\"designBackgroundStyle\"\n >\n <img\n :src=\"designBackground.src\"\n draggable=\"false\"\n alt=\"\"\n @error=\"onBackgroundError\"\n >\n </div>\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 <!-- 水印渲染层(在所有元素之下):显式矢量瓦片,与打印端共用 core 的瓦片网格 -->\n <div\n v-if=\"watermarkLayout\"\n class=\"watermark-layer\"\n :style=\"{ opacity: String(watermarkLayout.opacity) }\"\n >\n <svg\n v-for=\"(tile, idx) in watermarkLayout.tiles\"\n :key=\"idx\"\n class=\"watermark-tile\"\n :width=\"tile.widthMm + 'mm'\"\n :height=\"tile.heightMm + 'mm'\"\n :viewBox=\"`0 0 ${watermarkLayout.tileWidthPx} ${watermarkLayout.tileHeightPx}`\"\n :style=\"{ left: tile.leftMm + 'mm', top: tile.topMm + 'mm' }\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <text\n :x=\"watermarkLayout.tileWidthPx / 2\"\n :y=\"watermarkLayout.tileHeightPx / 2\"\n :font-size=\"watermarkLayout.fontSizePx\"\n :fill=\"watermarkLayout.color\"\n text-anchor=\"middle\"\n dominant-baseline=\"middle\"\n :transform=\"`rotate(${watermarkLayout.rotate},${watermarkLayout.tileWidthPx / 2},${watermarkLayout.tileHeightPx / 2})`\"\n >{{ watermarkLayout.text }}</text>\n </svg>\n </div>\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, watch, onUnmounted } from 'vue'\nimport type { RuntimeElement, TemplateData, ElementRect, ElementZone, AlignLine } from '@worm-vue3-print/core/designer'\nimport { getPaperDimensions } from '@worm-vue3-print/core/designer'\nimport { mmToPx } from '@worm-vue3-print/core/designer'\nimport { resolveWatermarkLayout } from '@worm-vue3-print/core'\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// ─── 设计背景(仅设计画布显示,旋转为 90° 步进;90/270 交换宽高后居中再绕纸心旋转)───\nconst designBackground = computed(() => props.templateData.designBackground)\nconst backgroundLoadFailed = ref(false)\nwatch(() => designBackground.value?.src, () => { backgroundLoadFailed.value = false })\n\nconst normalizedBackgroundRotation = computed<0 | 90 | 180 | 270>(() => {\n const r = designBackground.value?.rotation\n return r === 90 || r === 180 || r === 270 ? r : 0\n})\n\nconst designBackgroundStyle = computed(() => {\n const rotation = normalizedBackgroundRotation.value\n const swapped = rotation === 90 || rotation === 270\n const layerW = swapped ? paperHeightMM.value : paperWidthMM.value\n const layerH = swapped ? paperWidthMM.value : paperHeightMM.value\n const style: Record<string, string> = {\n width: layerW + 'mm',\n height: layerH + 'mm',\n left: (paperWidthMM.value - layerW) / 2 + 'mm',\n top: (paperHeightMM.value - layerH) / 2 + 'mm',\n }\n if (rotation !== 0) style.transform = `rotate(${rotation}deg)`\n return style\n})\n\nfunction onBackgroundError() {\n backgroundLoadFailed.value = true\n console.warn('[print-designer] 设计背景图加载失败:', designBackground.value?.src)\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 // 仅响应左键,右键不拖动参考线\n if (e.button !== 0) return\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// ─── 水印渲染(复用 core 同构逻辑:与预览/打印完全一致) ───\n// 与打印端同源:几何(瓦片网格)由 core 计算,画布只负责渲染;\n// 水印不可见或文本为空时返回 null(core 内部判定),不渲染水印层。\nconst watermarkLayout = computed(() => resolveWatermarkLayout(\n props.templateData.watermark,\n props.printData,\n { width: paperWidthMM.value, height: paperHeightMM.value },\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 if (e.button !== 0) return\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/* 纸张缩放平滑过渡(配合鼠标位置缩放中心);适应窗口时由 JS 临时禁用 */\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/* 设计背景:铺满纸张最底层,不拦截任何指针事件 */\n.design-background {\n position: absolute;\n z-index: 0;\n overflow: hidden;\n pointer-events: none;\n}\n.design-background img {\n display: block;\n width: 100%;\n height: 100%;\n object-fit: fill;\n pointer-events: none;\n user-select: none;\n -webkit-user-drag: 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/* 水印层:覆盖整页、位于所有元素之下(几何由 core 的瓦片网格给出,mm 定位) */\n.watermark-layer {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n z-index: 0;\n overflow: hidden;\n pointer-events: none;\n}\n.watermark-tile {\n position: absolute;\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 '@worm-vue3-print/core/designer'\nimport {\n buildRulerTicks,\n chooseMajorStepMM,\n RULER_THICKNESS,\n} from '@worm-vue3-print/core/designer'\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 // 仅响应左键,右键不从标尺拖出参考线\n if (e.button !== 0) return\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 <!-- 右键菜单:fixed 定位脱离滚动容器,避免撑大 scrollWidth/Height 触发滚动条 -->\n <div\n v-if=\"contextMenu.visible\"\n ref=\"contextMenuRef\"\n class=\"context-menu\"\n :style=\"{\n left: (contextMenu.x + contextMenu.flipX) + 'px',\n top: (contextMenu.y + contextMenu.flipY) + 'px',\n }\"\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 </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 '@worm-vue3-print/core/designer'\nimport { pxToMm, mmToPx } from '@worm-vue3-print/core/designer'\nimport { nextWheelScale, MIN_SCALE_PERCENT, FIT_SCALE_MIN_PERCENT } from '@worm-vue3-print/core/designer'\nimport { getPaperDimensions } from '@worm-vue3-print/core/designer'\nimport { RULER_THICKNESS } from '@worm-vue3-print/core/designer'\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 /** 是否显示视口固定标尺,默认开启 */\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 '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/**\n * 统一缩放入口:所有缩放交互(滚轮 / 按钮 / 适应窗口)共用同一管线。\n * 以容器内锚点 (anchorX/Y,相对容器的 client 坐标,含 padding) 为不动点,\n * 缩放后在 nextTick 校正滚动位置,保证锚点下的内容不漂移。\n */\nfunction applyZoom(\n targetPercent: number,\n anchorX: number,\n anchorY: number,\n minPercent: number,\n) {\n const container = rootRef.value\n if (!container) return\n const target = Math.max(minPercent, Math.round(targetPercent))\n const cur = Math.round((props.scale || 1) * 100)\n if (target === cur) return\n\n const oldScale = props.scale || 1\n const ratio = (target / 100) / oldScale\n\n // 容器存在非对称 padding,换算锚点时必须扣除,否则每次缩放锚点会漂移 pad*(ratio-1)\n const cs = getComputedStyle(container)\n const padX = parseFloat(cs.paddingLeft) || 0\n const padY = parseFloat(cs.paddingTop) || 0\n const ax = container.scrollLeft + anchorX - padX\n const ay = container.scrollTop + anchorY - padY\n\n // 以百分比整数增量上报(父级 scale 为百分比)\n emit('zoom', target - cur)\n\n // 待新比例应用到 DOM 后再校正滚动位置:缩放前若该方向没有滚动条,\n // 提前写入 scrollTop/Left 会被浏览器钳制为 0,导致锚点失效\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 - anchorX + padX2\n container.scrollTop = ay * ratio - anchorY + padY2\n })\n}\n\n/** Ctrl/Cmd+滚轮缩放:乘性步进,以鼠标位置为缩放中心,保持鼠标下的内容点不动 */\nfunction onWheel(e: WheelEvent) {\n if (!(e.ctrlKey || e.metaKey)) return\n e.preventDefault()\n const container = rootRef.value\n if (!container) return\n const oldPercent = Math.round((props.scale || 1) * 100)\n const newPercent = nextWheelScale(oldPercent, e.deltaY > 0 ? -1 : 1)\n if (newPercent === oldPercent) return\n const rect = container.getBoundingClientRect()\n applyZoom(newPercent, e.clientX - rect.left, e.clientY - rect.top, MIN_SCALE_PERCENT)\n}\n\n/** 工具栏放大/缩小按钮:与滚轮相同的乘性步进,以视口几何中心为锚点 */\nfunction zoomByStep(direction: 1 | -1) {\n const container = rootRef.value\n if (!container) return\n const cur = Math.round((props.scale || 1) * 100)\n // nextWheelScale 内部已做整数取整与 25% 下限钳制,与滚轮完全一致\n const target = nextWheelScale(cur, direction)\n applyZoom(target, container.clientWidth / 2, container.clientHeight / 2, MIN_SCALE_PERCENT)\n}\n\n// ─── 适应窗口:一步到位(调用方已算好目标比例),以视口中心为锚点,\n// 与 Ctrl+滚轮同一管线;不做缩放动画:临时禁用纸张 transform 过渡,\n// 待新比例应用到 DOM 后恢复,不影响滚轮/工具栏缩放的 150ms 动画 ───\nfunction fitToWindow(targetPercent: number) {\n const container = rootRef.value\n if (!container) return\n const paper = container.querySelector('.hiprint-printPaper') as HTMLElement | null\n const prevTransition = paper?.style.transition ?? ''\n if (paper) paper.style.transition = 'none'\n // 适应窗口允许低于交互缩放下限(见 FIT_SCALE_MIN_PERCENT),保证超大纸张整版可见\n applyZoom(\n targetPercent,\n container.clientWidth / 2,\n container.clientHeight / 2,\n FIT_SCALE_MIN_PERCENT,\n )\n void nextTick(() => {\n if (paper) paper.style.transition = prevTransition\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// ─── 右键菜单 ───\n// 菜单使用 position: fixed,坐标为视口坐标(e.clientX/Y),脱离 overflow:auto\n// 容器,避免菜单撑大 scrollWidth/Height 而出现滚动条导致画布抖动\nconst contextMenu = reactive({\n visible: false,\n x: 0,\n y: 0,\n /** 右/下边缘空间不足时的翻转移位(负值),由实际菜单尺寸测量得出 */\n flipX: 0,\n flipY: 0,\n targetId: null as string | null,\n})\nconst contextMenuRef = ref<HTMLElement | null>(null)\n\nfunction onContextMenu(e: MouseEvent, elId?: string) {\n // 元素右键:由 BaseElement 上抛(已 stop);空白右键:无 elId,仅背景区域弹菜单\n if (!elId && !isCanvasBackground(e.target)) return\n contextMenu.targetId = elId ?? null\n contextMenu.visible = true\n contextMenu.x = e.clientX\n contextMenu.y = e.clientY\n contextMenu.flipX = 0\n contextMenu.flipY = 0\n\n // 菜单渲染后按实际尺寸做视口边缘翻转,防止右下区域右键时菜单溢出屏幕\n void nextTick(() => {\n const menu = contextMenuRef.value\n if (!menu) return\n const rect = menu.getBoundingClientRect()\n const gap = 4\n if (e.clientX + rect.width + gap > window.innerWidth) {\n contextMenu.flipX = -rect.width\n }\n if (e.clientY + rect.height + gap > window.innerHeight) {\n contextMenu.flipY = -rect.height\n }\n })\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}\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, zoomByStep })\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 /* 横向:常驻滚动条轨道预留占位;竖向:用 scrollbar-gutter 预留槽位\n (无溢出时不渲染轨道,视觉更干净)。二者保证缩放/窗口尺寸变化导致\n 滚动条出现或消失时不挤压画布,避免抖动 */\n overflow-x: scroll;\n overflow-y: auto;\n scrollbar-gutter: stable;\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/* 右键菜单:fixed 定位,不参与滚动容器的内容尺寸计算,避免出现滚动条 */\n.context-menu {\n position: fixed;\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","<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 '@worm-vue3-print/core/designer'\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","<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=\"swatchStyle\"></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\" :class=\"{ 'is-empty': !modelValue }\" :style=\"modelValue ? { background: activeColor } : undefined\"></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\">\n <span>常用颜色</span>\n <button\n v-if=\"clearable\"\n type=\"button\"\n class=\"picker-clear\"\n :disabled=\"!modelValue\"\n title=\"清除选中的颜色\"\n @click=\"selectNone\"\n >\n <svg viewBox=\"0 0 16 16\" width=\"12\" height=\"12\" aria-hidden=\"true\">\n <path d=\"M3 3l10 10M13 3L3 13\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" fill=\"none\"/>\n </svg>\n 清除\n </button>\n </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: !!modelValue && color.toLowerCase() === modelValue.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 '@worm-vue3-print/core/designer'\n\nconst props = withDefaults(defineProps<{\n modelValue?: string\n /** 是否允许清除颜色,边框等颜色必填场景可关闭 */\n clearable?: boolean\n}>(), {\n clearable: true,\n})\n\nconst emit = defineEmits<{\n /** 空字符串表示清除颜色(恢复默认/继承) */\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(() => props.modelValue || '#000000')\n\n/** 色块样式:无颜色时显示透明棋盘格 */\nconst swatchStyle = computed(() => (\n props.modelValue\n ? { background: props.modelValue }\n : { background: 'transparent' }\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(() => props.modelValue, (color) => {\n // 无颜色时输入框与预览置空,HSV 保持上一次状态,方便用户重新选色\n if (!color) {\n hexInput.value = ''\n return\n }\n syncFromColor(color)\n}, { immediate: true })\n\nfunction select(color: string) {\n hexInput.value = color.toUpperCase()\n syncFromColor(color)\n emit('update:modelValue', color)\n}\n\n/** 清除颜色:标题栏「清除」按钮 */\nfunction selectNone() {\n if (!props.clearable) return\n emit('update:modelValue', '')\n}\n\nfunction onHexInput(event: Event) {\n const input = event.target as HTMLInputElement\n const color = input.value.trim()\n // 输入框清空时同步清除颜色(仅在允许清除时)\n if (!color) {\n if (props.clearable) emit('update:modelValue', '')\n return\n }\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 if (props.modelValue) 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 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.picker-current.is-empty {\n position: relative;\n background-color: #fff;\n}\n\n.picker-current.is-empty::after {\n content: '';\n position: absolute;\n inset: 3px;\n background:\n linear-gradient(to top right, transparent calc(50% - 0.7px), #f53f3f calc(50% - 0.7px), #f53f3f calc(50% + 0.7px), transparent calc(50% + 0.7px));\n border-radius: 3px;\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 display: flex;\n align-items: center;\n justify-content: space-between;\n margin-top: 10px;\n margin-bottom: 6px;\n font-size: 11px;\n color: var(--pd-text-muted, #909399);\n}\n\n/* 标题栏右侧的清除按钮 */\n.picker-clear {\n display: inline-flex;\n align-items: center;\n gap: 3px;\n padding: 2px 6px;\n border: none;\n border-radius: 4px;\n background: transparent;\n font-size: 11px;\n line-height: 1;\n color: var(--pd-text-muted, #909399);\n cursor: pointer;\n}\n\n.picker-clear:hover:not(:disabled) {\n background: rgb(0 0 0 / 6%);\n color: var(--pd-danger, #f53f3f);\n}\n\n.picker-clear:disabled {\n opacity: .45;\n cursor: not-allowed;\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 <div class=\"font-select\">\n <input\n v-model=\"text\"\n class=\"pd-input font-select-input\"\n type=\"text\"\n role=\"combobox\"\n aria-autocomplete=\"list\"\n autocomplete=\"off\"\n :placeholder=\"placeholder\"\n :aria-expanded=\"open\"\n :aria-controls=\"listId\"\n :aria-activedescendant=\"activeRowId\"\n @focus=\"onOpen\"\n @click=\"onClick\"\n @input=\"onInput\"\n @keydown.down.prevent=\"move(1)\"\n @keydown.up.prevent=\"move(-1)\"\n @keydown.enter.prevent=\"onEnter\"\n @keydown.esc.prevent=\"onCancel\"\n @blur=\"onCancel\"\n />\n <ul v-if=\"open\" :id=\"listId\" ref=\"listRef\" class=\"font-select-list\" role=\"listbox\">\n <li\n v-for=\"(row, index) in rows\"\n :id=\"`${listId}-${index}`\"\n :key=\"row.key\"\n class=\"font-select-option\"\n :class=\"{ 'is-active': index === highlighted, 'is-muted': row.kind === 'unknown' || row.kind === 'free' }\"\n role=\"option\"\n :aria-selected=\"row.selected\"\n @mousedown.prevent=\"pick(row)\"\n >{{ row.label }}</li>\n </ul>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, nextTick, ref, useId, watch } from 'vue'\nimport {\n filterFontOptions,\n findFontOption,\n fontOptionLabel,\n normalizeFontQuery,\n useInjectedFontCatalog,\n} from '../../composables/useFontCatalog'\n\nconst props = withDefaults(defineProps<{\n /** 当前族名;undefined 表示未设置,走全局兜底字体栈 */\n modelValue?: string\n /** 空值行文案(同时用作输入框 placeholder) */\n placeholder?: string\n}>(), {\n placeholder: '默认',\n})\n\nconst emit = defineEmits<{ 'update:model-value': [value: string | undefined] }>()\n\nconst catalog = useInjectedFontCatalog()\n\n/** 每实例独立的列表 id,供 combobox 的 aria 关联使用 */\nconst listId = `font-select-list-${useId()}`\n\nconst listRef = ref<HTMLUListElement | null>(null)\n/** 输入框显示值:未提交时与 modelValue 不一致,提交或取消后回到 modelValue 的展示名 */\nconst text = ref(toDisplayName(props.modelValue))\n/** 过滤词:展开时为空表示「列出全部」 */\nconst query = ref('')\nconst open = ref(false)\n/** 高亮行下标;-1 表示无高亮(此时 Enter 不提交任何东西) */\nconst highlighted = ref(-1)\n\ninterface FontRow {\n key: string\n kind: 'clear' | 'unknown' | 'font' | 'free'\n label: string\n /** 提交值;clear 行为 undefined */\n value?: string\n selected: boolean\n}\n\n/**\n * 模板当前值不在声明字体内时(如导入了使用系统字体的旧模板)必须保留一行,\n * 否则设计者会以为该字体在打开面板时被清掉了。\n */\nconst unknownFamily = computed(() => {\n const current = props.modelValue?.trim()\n if (!current) return ''\n return findFontOption(catalog.value, current) ? '' : current\n})\n\nconst rows = computed<FontRow[]>(() => {\n const current = (props.modelValue ?? '').trim()\n const make = (kind: FontRow['kind'], key: string, label: string, value?: string): FontRow => ({\n kind,\n key,\n label,\n value,\n selected: (value ?? '') === current,\n })\n\n const typed = query.value.trim()\n // 过滤时不展示空值行与未知行:此时 Enter 应当落在命中项或用户输入的字体名上\n if (!typed) {\n const out: FontRow[] = [make('clear', '__clear__', props.placeholder)]\n if (unknownFamily.value) {\n out.push(make('unknown', '__unknown__', `${unknownFamily.value}(未知)`, unknownFamily.value))\n }\n for (const font of catalog.value) {\n out.push(make('font', font.family, fontOptionLabel(font), font.family))\n }\n return out\n }\n\n const matched = filterFontOptions(catalog.value, typed).map(font =>\n make('font', font.family, fontOptionLabel(font), font.family),\n )\n // 清单外字体名可直接录入:一条都没命中时才补「使用「xxx」」,\n // 有命中项时补这行只会成为方向键路径上的噪音。\n if (!matched.length) {\n const family = resolveTypedFamily(typed)\n matched.push(make('free', '__free__', `使用「${family}」`, family))\n }\n return matched\n})\n\n/** 输入的是展示名(label)时,写进模板的必须是真实族名,否则字体静默失效 */\nfunction resolveTypedFamily(typed: string): string {\n const key = normalizeFontQuery(typed)\n const hit = catalog.value.find(font => font.label && normalizeFontQuery(font.label) === key)\n return hit?.family ?? typed\n}\n\n/**\n * 展示名:宿主用 prop 声明了 label 的字体在输入框里显示 label(业务名),\n * 便于识别;写入模板的始终是族名,展示与存储分离。\n */\nfunction toDisplayName(family?: string): string {\n const key = family?.trim()\n if (!key) return ''\n return findFontOption(catalog.value, key)?.label ?? key\n}\n\nconst activeRowId = computed(() =>\n open.value && highlighted.value >= 0 ? `${listId}-${highlighted.value}` : undefined,\n)\n\n/** 当前值所在行;用于展开时把高亮落在已选字体上,避免误按 Enter 改掉字体 */\nfunction currentRowIndex(): number {\n const current = (props.modelValue ?? '').trim()\n return rows.value.findIndex(row => (row.value ?? '') === current)\n}\n\nfunction onOpen(): void {\n if (open.value) return\n open.value = true\n query.value = ''\n highlighted.value = currentRowIndex()\n}\n\n/** 点击输入框只负责重新展开(Esc 收起后再次点开),不改动已输入内容 */\nfunction onClick(): void {\n open.value = true\n}\n\nfunction onInput(): void {\n open.value = true\n query.value = text.value\n highlighted.value = rows.value.length ? 0 : -1\n}\n\nfunction move(delta: number): void {\n if (!open.value) {\n onOpen()\n return\n }\n const last = rows.value.length - 1\n if (last < 0) return\n highlighted.value = Math.min(Math.max(highlighted.value + delta, 0), last)\n scrollActiveIntoView()\n}\n\nfunction scrollActiveIntoView(): void {\n void nextTick(() => {\n const el = listRef.value?.children[highlighted.value] as HTMLElement | undefined\n el?.scrollIntoView?.({ block: 'nearest' })\n })\n}\n\nfunction onEnter(): void {\n if (!open.value) return\n const row = rows.value[highlighted.value]\n if (row) {\n pick(row)\n return\n }\n const typed = query.value.trim()\n if (typed) {\n const family = resolveTypedFamily(typed)\n pick({ kind: 'free', key: '__free__', label: family, value: family, selected: false })\n }\n}\n\nfunction pick(row: FontRow): void {\n text.value = toDisplayName(row.value)\n query.value = ''\n open.value = false\n highlighted.value = -1\n emit('update:model-value', row.value)\n}\n\nfunction onCancel(): void {\n open.value = false\n query.value = ''\n highlighted.value = -1\n text.value = toDisplayName(props.modelValue)\n}\n\nwatch(() => props.modelValue, value => { text.value = toDisplayName(value) })\n</script>\n\n<style scoped>\n.font-select-input {\n width: 100%;\n}\n.font-select-list {\n margin-top: 4px;\n max-height: 200px;\n overflow-y: auto;\n padding: 2px;\n border: 1px solid var(--pd-border, #d9dde6);\n border-radius: 6px;\n background: var(--pd-surface, #ffffff);\n list-style: none;\n}\n.font-select-option {\n padding: 4px 6px;\n border-radius: 4px;\n font-size: 12px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n cursor: pointer;\n}\n.font-select-option.is-active {\n background: var(--pd-sidebar-hover, #f0f3f9);\n}\n.font-select-option.is-muted {\n color: var(--pd-text-muted, #8b909c);\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-family')\"><span class=\"pd-label\">字体</span>\n <FontSelect v-model=\"element.options.fontFamily\" />\n </div>\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 <div class=\"pd-field\" v-show=\"showItem('ap-text-fit')\"><span class=\"pd-label\">文字溢出</span>\n <select class=\"pd-select\" :value=\"textFit\" style=\"width: 100%\" @change=\"onTextFitChange\">\n <option value=\"clip\">截断</option>\n <option value=\"shrink\">自动缩小</option>\n <option value=\"autoHeight\">自适应行高</option>\n </select>\n </div>\n <div class=\"pd-field\" v-if=\"textFit === 'shrink'\" v-show=\"showItem('ap-shrink-min')\"><span class=\"pd-label\">最小字号 (pt)</span>\n <StepperInput :model-value=\"element.options.shrinkMinFontSize\"\n :min=\"1\"\n :max=\"72\"\n :step=\"0.5\"\n placeholder=\"默认 6\"\n @update:model-value=\"element.options.shrinkMinFontSize = $event ?? undefined\" />\n </div>\n <div class=\"pd-field\" v-show=\"showItem('ap-word-wrap')\"><span class=\"pd-label\">自动换行</span>\n <input :checked=\"element.options.wordWrap !== false\" type=\"checkbox\" class=\"pd-switch\"\n @input=\"element.options.wordWrap = ($event.target as HTMLInputElement).checked ? undefined : false\" />\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 '@worm-vue3-print/core/designer'\nimport { resolveElementTextFit, type TextFit } from '@worm-vue3-print/core/designer'\nimport PresetColorPicker from '../PresetColorPicker.vue'\nimport PropertyGroup from './PropertyGroup.vue'\nimport StepperInput from './StepperInput.vue'\nimport FontSelect from './FontSelect.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\n/** 溢出形式:未配置时按元素类型取默认(文本=截断、长文本=自适应行高) */\nconst textFit = computed<TextFit>(() =>\n resolveElementTextFit(props.element.printElementType.type || 'text', props.element.options),\n)\n\nfunction onTextFitChange(e: Event) {\n props.element.options.textFit = (e.target as HTMLSelectElement).value as TextFit\n}\n</script>\n\n<style scoped>\n.color-row {\n display: flex;\n gap: 12px;\n}\n.color-row > .pd-field {\n flex: 1 1 0;\n min-width: 0;\n}</style>","<!-- 条形码/二维码配置分组:码制/条宽/显示文本/字号/纠错级别 + 自定义设置(缩放模式/最大宽高) -->\n<template>\n <PropertyGroup title=\"条码设置\" icon=\"Postcard\" default-expanded group-key=\"code\">\n <form class=\"pd-form\" @submit.prevent>\n <template v-if=\"isBarcode\">\n <div class=\"pd-field\" v-show=\"showItem('cd-type')\"><span class=\"pd-label\">码制</span>\n <select class=\"pd-select\" :value=\"barcodeType\" @change=\"onBarcodeTypeChange\">\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-show=\"showItem('cd-dpi')\"><span class=\"pd-label\">打印机分辨率</span>\n <select class=\"pd-select\" :value=\"dpiValue\" @change=\"onDpiChange\">\n <option value=\"\">不指定(按条宽渲染)</option>\n <option value=\"203\">203 dpi(8 点/mm)</option>\n <option value=\"300\">300 dpi(11.8 点/mm)</option>\n <option value=\"600\">600 dpi(23.6 点/mm)</option>\n </select>\n </div>\n <p class=\"pd-hint\" v-show=\"showItem('cd-dpi')\">填写后条宽吸附到整数打印点(消除出纸「条宽忽宽忽窄」):条码先按条宽渲染,可用宽度够就原样落纸,不够才整体等比缩小</p>\n <div class=\"pd-field\" v-show=\"showItem('cd-bar-width')\"><span class=\"pd-label\">条宽(倍率)</span>\n <StepperInput :model-value=\"element.options.barWidth ?? 2\"\n :min=\"2\"\n :max=\"4\"\n :step=\"0.5\"\n @update:model-value=\"element.options.barWidth = $event; emitChange()\" />\n </div>\n <p class=\"pd-hint\" v-show=\"showItem('cd-bar-width')\">{{ dotAligned\n ? '已设置打印机分辨率:条宽会被吸附到最近的整数打印点(DPI 优先于毫米值),元素框放不下时整体等比缩小'\n : '热敏/针式打印建议 3 及以上:决定条码的落纸尺寸,条越粗出纸后条宽越稳定' }}</p>\n <div class=\"pd-field\" v-show=\"showItem('cd-show-text')\"><span class=\"pd-label\">显示文本</span>\n <input :checked=\"element.options.hideTitle !== true\" type=\"checkbox\" class=\"pd-switch\"\n @input=\"element.options.hideTitle = ($event.target as HTMLInputElement).checked ? undefined : true; emitChange()\" />\n </div>\n <div class=\"pd-field\" v-show=\"showItem('cd-font-size')\"><span class=\"pd-label\">文本字号(相对条高,条高为 30)</span>\n <StepperInput :model-value=\"element.options.fontSize\"\n :min=\"5\"\n :max=\"24\"\n placeholder=\"默认 10\"\n @update:model-value=\"element.options.fontSize = $event ?? undefined; emitChange()\" />\n </div>\n </template>\n\n <template v-else-if=\"isQrcode\">\n <div class=\"pd-field\" v-show=\"showItem('cd-ec-level')\"><span class=\"pd-label\">纠错级别</span>\n <select class=\"pd-select\" :value=\"String(element.options.qrCodeLevel ?? 'M')\"\n @change=\"element.options.qrCodeLevel = ($event.target as HTMLSelectElement).value; emitChange()\">\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 </template>\n\n <h3 class=\"pd-divider\">自定义设置</h3>\n <p class=\"pd-hint\" v-if=\"isBarcode\">条码尺寸由「条宽」与「打印机分辨率」结算:宽度足够时按条宽原样落纸,不足时整体等比缩小;拉伸会把条宽变成非整数,故条形码不提供缩放模式,可用「最大宽高」限制上限</p>\n <div class=\"pd-field\" v-if=\"!isBarcode\" v-show=\"showItem('cd-fit')\"><span class=\"pd-label\">缩放模式</span>\n <select class=\"pd-select\" :value=\"element.options.fit || 'contain'\" @change=\"onFitChange\">\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-show=\"showItem('cd-max-width')\"><span class=\"pd-label\">最大宽度 (mm)</span>\n <StepperInput :model-value=\"element.options.maxWidth\"\n :min=\"1\"\n :max=\"200\"\n placeholder=\"默认\"\n @update:model-value=\"element.options.maxWidth = $event ?? undefined; emitChange()\" />\n </div>\n <div class=\"pd-field\" v-show=\"showItem('cd-max-height')\"><span class=\"pd-label\">最大高度 (mm)</span>\n <StepperInput :model-value=\"element.options.maxHeight\"\n :min=\"1\"\n :max=\"200\"\n placeholder=\"默认\"\n @update:model-value=\"element.options.maxHeight = $event ?? undefined; emitChange()\" />\n </div>\n </form>\n </PropertyGroup>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport type { RuntimeElement } from '@worm-vue3-print/core/designer'\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\nconst emit = defineEmits<{ change: [] }>()\n\nconst isBarcode = computed(() => props.element.printElementType.type === 'barcode')\nconst isQrcode = computed(() => props.element.printElementType.type === 'qrcode')\n\n/**\n * 码制归一化为大写的 jsbarcode 格式名。\n * jsbarcode 对格式名大小写不敏感,但存量模板存有小写(元素工厂缺省 `code128`),\n * 不归一化会导致下拉框匹配不到选项、显示为空。\n */\nconst barcodeType = computed(() => (props.element.options.barcodeType || 'CODE128').toUpperCase())\n\n/** 打印机分辨率:'' 表示不启用点对齐(保持原有按框缩放行为) */\nconst dpiValue = computed(() => (props.element.options.printerDpi ? String(props.element.options.printerDpi) : ''))\nconst hasPrinterDpi = computed(() => !!props.element.options.printerDpi)\n/** 点对齐只作用于条形码(二维码模块数固定,尺寸由 fit/最大宽高决定) */\nconst dotAligned = computed(() => isBarcode.value && hasPrinterDpi.value)\n\nfunction onDpiChange(e: Event) {\n const value = Number((e.target as HTMLSelectElement).value)\n props.element.options.printerDpi = value > 0 ? value : undefined\n emitChange()\n}\n\nfunction onBarcodeTypeChange(e: Event) {\n const value = (e.target as HTMLSelectElement).value\n props.element.options.barcodeType = value === 'CODE128' ? undefined : value\n emitChange()\n}\n\nfunction onFitChange(e: Event) {\n props.element.options.fit = (e.target as HTMLSelectElement).value || undefined\n emitChange()\n}\n\nfunction showItem(key: string): boolean {\n if (!props.searching) {\n return true\n }\n return props.matchedKeys?.has(key) ?? true\n}\n\nfunction emitChange() {\n emit('change')\n}\n</script>\n","<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 filteredMathFuncs\"\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(条件, 真值, 假值) - 条件判断<br>\n 四则运算:{qty * price}、{ADD(qty, 1)}<br>\n 修约:ROUND 四舍五入 / ROUNDUP 进一 / ROUNDDOWN 去尾 / ROUNDBANK 四舍六入五成双\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, \"大单\", \"小单\")}<br>\n 运算并修约:{ROUND(qty * price, 2)}\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 '@worm-vue3-print/core/designer'\nimport { evaluateTemplate } from '@worm-vue3-print/core/designer'\nimport { DEFAULT_DEMO_DATA } from '@worm-vue3-print/core/designer'\nimport { groupFields, filterGroups } from '@worm-vue3-print/core/designer'\nimport { resolveSystemVariables } from '@worm-vue3-print/core'\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 filteredMathFuncs = computed(() => {\n if (!searchText.value.trim()) return mathFunctions\n const keyword = searchText.value.trim().toLowerCase()\n return mathFunctions.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 mathFunctions = [\n { name: 'ADD', label: '相加', template: 'ADD()' },\n { name: 'SUB', label: '相减', template: 'SUB()' },\n { name: 'MUL', label: '相乘', template: 'MUL()' },\n { name: 'DIV', label: '相除', template: 'DIV()' },\n { name: 'ROUND', label: '四舍五入', template: 'ROUND()' },\n { name: 'ROUNDUP', label: '进一法', template: 'ROUNDUP()' },\n { name: 'ROUNDDOWN', label: '去尾法', template: 'ROUNDDOWN()' },\n { name: 'ROUNDBANK', label: '四舍六入五成双', template: 'ROUNDBANK()' },\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 // 系统变量取值与渲染端同一实现(resolveSystemVariables),保证预览与打印一致\n ...resolveSystemVariables(),\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 '@worm-vue3-print/core/designer'\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 '@worm-vue3-print/core/designer'\nimport { TABLE_EDIT_KEY } from '../../composables/useTableSelection'\nimport { syncTableElementSize } from '@worm-vue3-print/core/designer'\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 '@worm-vue3-print/core/designer'\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 '@worm-vue3-print/core/designer'\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 '@worm-vue3-print/core/designer'\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'\">\n <span class=\"pd-label\" title=\"多级表头作为一个结构整体重复,勾选后表头区所有行都会在每页顶部重复\">表头每页重复</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 '@worm-vue3-print/core/designer'\nimport { setRowType, setHeaderRepeat, syncTableElementSize } from '@worm-vue3-print/core/designer'\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\n/** 作用于整个表头区:多级表头是跨行合并的结构整体,只勾单行会让续片表头断裂 */\nfunction onRepeatChange(v: boolean) {\n setHeaderRepeat(props.element.options.tableRows!, 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=\"isBarcodeCell\"><span class=\"pd-label\">条宽(倍率)</span>\n <StepperInput :model-value=\"mainCell.barWidth ?? 2\"\n :min=\"2\"\n :max=\"4\"\n :step=\"0.5\"\n @update:model-value=\"write(c => { c.barWidth = $event })\" />\n </div>\n <p class=\"pd-hint\" v-if=\"isBarcodeCell\">{{ dotAligned\n ? '已设置打印机分辨率:条宽会被吸附到最近的整数打印点(DPI 优先于毫米值),单元格放不下时整体等比缩小'\n : '热敏/针式打印建议 3 及以上:决定条码的落纸尺寸,条越粗出纸后条宽越稳定' }}</p>\n <div class=\"pd-field\" v-if=\"isBarcodeCell\"><span class=\"pd-label\">文本字号(相对条高,条高为 30)</span>\n <StepperInput :model-value=\"mainCell.barFontSize ?? 10\"\n :min=\"5\"\n :max=\"24\"\n placeholder=\"默认 10\"\n @update:model-value=\"write(c => { c.barFontSize = $event ?? undefined })\" />\n </div>\n <div class=\"pd-field\" v-if=\"isBarcodeCell\"><span class=\"pd-label\">打印机分辨率</span>\n <select :value=\"mainCell.printerDpi ? String(mainCell.printerDpi) : ''\" class=\"pd-select\" @change=\"onPrinterDpiChange(($event.target as HTMLSelectElement).value)\">\n <option value=\"\">不指定(按条宽渲染)</option>\n <option value=\"203\">203 dpi(8 点/mm)</option>\n <option value=\"300\">300 dpi(11.8 点/mm)</option>\n <option value=\"600\">600 dpi(23.6 点/mm)</option>\n </select>\n </div>\n <p class=\"pd-hint\" v-if=\"isBarcodeCell\">填写后条宽吸附到整数打印点(消除出纸「条宽忽宽忽窄」):条码先按条宽渲染,可用宽度够就原样落纸,不够才整体等比缩小</p>\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 <p class=\"pd-hint\" v-if=\"isBarcodeCell\">单元格条码尺寸由「条宽」与「打印机分辨率」结算:可用宽度足够时按条宽原样落纸,不足时整体等比缩小;拉伸会把条宽变成非整数,故条形码不提供缩放模式,可用「最大宽高」限制上限</p>\n <div class=\"pd-field\" v-if=\"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 cell-font-field\"><span class=\"pd-label\">字体</span>\n <FontSelect\n :model-value=\"mainCell.fontFamily\"\n placeholder=\"继承默认\"\n @update:model-value=\"write(c => { c.fontFamily = $event })\"\n />\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\" :clearable=\"false\" />\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 <div class=\"pd-field\" v-if=\"isTextCell\"><span class=\"pd-label\">文字溢出</span>\n <select class=\"pd-select\" :value=\"cellTextFit\" style=\"width: 100%\" @change=\"onTextFitChange\">\n <option value=\"clip\">截断</option>\n <option value=\"shrink\">自动缩小</option>\n <option value=\"autoHeight\">自适应行高</option>\n </select>\n </div>\n <div class=\"pd-field\" v-if=\"isTextCell && cellTextFit === 'shrink'\"><span class=\"pd-label\">最小字号 (pt)</span>\n <StepperInput :model-value=\"mainCell.shrinkMinFontSize\"\n :min=\"1\"\n :max=\"72\"\n :step=\"0.5\"\n placeholder=\"默认 6\"\n @update:model-value=\"write(c => { c.shrinkMinFontSize = $event ?? undefined })\" />\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 '@worm-vue3-print/core/designer'\nimport {\n canMergeReason, mergeCells, splitCells, applyBorderPreset, findMainCell, type BorderPreset,\n resolveCellTextFit, type TextFit,\n} from '@worm-vue3-print/core/designer'\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'\nimport FontSelect from './FontSelect.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/** 条码点对齐:仅条形码单元格 + 已配打印机分辨率;此时缩放模式与最大宽高不参与 */\nconst dotAligned = computed(() => isBarcodeCell.value && !!mainCell.value.printerDpi)\n\n/** 文字溢出形式仅对文本单元格有意义(码值/图片由 fit/maxWidth 控制) */\nconst isTextCell = computed(() => !isBarcodeCell.value && !isQrcodeCell.value && !isImageCell.value)\n/** 未配置时:不换行→截断,否则自适应行高(与打印端同一判定) */\nconst cellTextFit = computed(() => resolveCellTextFit(mainCell.value))\n\nfunction onTextFitChange(e: Event) {\n const value = (e.target as HTMLSelectElement).value as TextFit\n write(c => { c.textFit = value })\n}\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 onPrinterDpiChange(v: string) {\n const dpi = Number(v)\n write(c => { c.printerDpi = dpi > 0 ? dpi : undefined })\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 c.printerDpi = 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/* 字体含输入框 + 查询按钮 + 状态提示,半栏放不下,独占一行 */\n.cell-font-field {\n grid-column: 1 / -1;\n /* 栅格行距为 0,独占一行时需自己与下方「字号 / 加粗」留出间距 */\n padding-bottom: 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","<template>\n <div class=\"watermark-config\">\n <h3 class=\"pd-divider\">水印</h3>\n <form class=\"pd-form\" @submit.prevent>\n <!-- 单一表达式输入:纯文本即静态水印,含 {字段}/函数/字段路径即按表达式解析 -->\n <div class=\"pd-field\"><span class=\"pd-label\">水印表达式</span>\n <input\n class=\"pd-input\"\n v-model=\"expressionText\"\n placeholder=\"直接输入文字,或用表达式:{order.no}、{printDate}\"\n title=\"双击或点「编辑表达式」打开表达式弹框\"\n @input=\"onTextInput\"\n @dblclick=\"openExpressionEditor\"\n />\n <button type=\"button\" class=\"pd-button small\" @click=\"openExpressionEditor\">编辑表达式</button>\n </div>\n <div v-if=\"isExpression\" class=\"pd-field\"><span class=\"pd-label\">测试值</span>\n <input class=\"pd-input\" v-model=\"testData\" placeholder=\"表达式取不到值时预览显示\" @input=\"onChange\" />\n </div>\n <ExpressionEditor\n v-model=\"exprEditorVisible\"\n :fields=\"fields\"\n :expression=\"expressionText\"\n @update:expression=\"onExpressionChange\"\n />\n\n <!-- 公共设置 -->\n <div class=\"pd-field\"><span class=\"pd-label\">旋转角度</span>\n <input type=\"range\" class=\"pd-range\" v-model.number=\"localConfig.rotate\" :min=\"-90\" :max=\"90\" :step=\"5\" @change=\"onChange\" />\n <span class=\"pd-hint\">{{ localConfig.rotate }}°</span>\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">颜色</span>\n <PresetColorPicker :model-value=\"localConfig.color\" @update:model-value=\"onColorChange\" />\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">透明度</span>\n <input type=\"range\" class=\"pd-range\" v-model.number=\"localConfig.opacity\" :min=\"0.05\" :max=\"0.5\" :step=\"0.05\" @change=\"onChange\" />\n <span class=\"pd-hint\">{{ localConfig.opacity.toFixed(2) }}</span>\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">密度</span>\n <select class=\"pd-select\" v-model=\"density\" style=\"width: 100%\" @change=\"onChange\">\n <option v-for=\"(p, key) in densityPresets\" :key=\"key\" :value=\"key\">{{ p.label }}({{ p.width }}×{{ p.height }})</option>\n <option value=\"custom\">自定义</option>\n </select>\n </div>\n <template v-if=\"density === 'custom'\">\n <div class=\"pd-field\"><span class=\"pd-label\">瓦片宽</span>\n <input type=\"number\" class=\"pd-input\" v-model.number=\"localConfig.tileWidth\" :min=\"minTileWidth\" :step=\"10\" @change=\"onChange\" />\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">瓦片高</span>\n <input type=\"number\" class=\"pd-input\" v-model.number=\"localConfig.tileHeight\" :min=\"minTileHeight\" :step=\"10\" @change=\"onChange\" />\n </div>\n </template>\n </form>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, reactive, ref, watch } from 'vue'\nimport type { WatermarkOptions, PrintBusinessField } from '@worm-vue3-print/core/designer'\nimport { WATERMARK_DENSITY_PRESETS, WATERMARK_DEFAULTS } from '@worm-vue3-print/core'\nimport PresetColorPicker from './PresetColorPicker.vue'\nimport ExpressionEditor from './ExpressionEditor.vue'\n\nconst props = defineProps<{\n modelValue?: WatermarkOptions\n fields?: PrintBusinessField[]\n}>()\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: WatermarkOptions]\n}>()\n\nconst densityPresets = WATERMARK_DENSITY_PRESETS\nconst minTileWidth = WATERMARK_DEFAULTS.minTileWidth\nconst minTileHeight = WATERMARK_DEFAULTS.minTileHeight\n\n/**\n * 判断输入是「表达式」还是「静态文本」:\n * - 含花括号:{order.no}、{CONCAT(...)}、第{pageIndex}页\n * - 函数调用:CONCAT('单号:', order.no)\n * - 字段路径:order.no(与 core binding 模式的路径解析一致)\n * 其余(含中文标语)按静态水印处理。\n */\nfunction isExpressionText(text: string): boolean {\n const t = text.trim()\n if (!t) return false\n if (/[{}]/.test(t)) return true\n if (/^[A-Za-z_$][\\w$]*\\s*\\(/.test(t)) return true\n return /^[A-Za-z_$][\\w$]*(\\.[\\w$]+)+$/.test(t)\n}\n\n/** 取模板里的水印文本:binding 模式取 binding,其余取 content */\nfunction readText(v?: WatermarkOptions): string {\n if (!v) return ''\n return v.mode === 'binding' ? (v.binding ?? '') : (v.content ?? '')\n}\n\nconst expressionText = ref(readText(props.modelValue))\nconst testData = ref(props.modelValue?.testData || '')\nconst exprEditorVisible = ref(false)\n// 当前按哪种模式落盘;文本被编辑时按内容重新判定\nconst activeMode = ref<'fixed' | 'binding'>(props.modelValue?.mode === 'binding' ? 'binding' : 'fixed')\n\nconst localConfig = reactive({\n rotate: props.modelValue?.rotate ?? WATERMARK_DEFAULTS.rotate,\n color: props.modelValue?.color || WATERMARK_DEFAULTS.color,\n opacity: props.modelValue?.opacity ?? WATERMARK_DEFAULTS.opacity,\n tileWidth: props.modelValue?.tileWidth ?? WATERMARK_DEFAULTS.tileWidth,\n tileHeight: props.modelValue?.tileHeight ?? WATERMARK_DEFAULTS.tileHeight,\n})\n\n/** 是否表达式模式(决定是否展示测试值;纯文本水印用不到) */\nconst isExpression = computed(() => activeMode.value === 'binding')\n\nwatch(() => props.modelValue, (val) => {\n if (!val) return\n expressionText.value = readText(val)\n // 模板未改动文本时沿用原模式(兼容 binding 存的是无花括号路径的存量模板)\n activeMode.value = val.mode === 'binding' ? 'binding' : 'fixed'\n testData.value = val.testData || ''\n localConfig.rotate = val.rotate ?? WATERMARK_DEFAULTS.rotate\n localConfig.color = val.color || WATERMARK_DEFAULTS.color\n localConfig.opacity = val.opacity ?? WATERMARK_DEFAULTS.opacity\n localConfig.tileWidth = val.tileWidth ?? WATERMARK_DEFAULTS.tileWidth\n localConfig.tileHeight = val.tileHeight ?? WATERMARK_DEFAULTS.tileHeight\n}, { deep: true })\n\nconst density = computed({\n get(): string {\n const { tileWidth, tileHeight } = localConfig\n for (const [key, preset] of Object.entries(densityPresets)) {\n if (tileWidth === preset.width && tileHeight === preset.height) return key\n }\n return 'custom'\n },\n set(value: string) {\n const preset = densityPresets[value]\n if (preset) {\n localConfig.tileWidth = preset.width\n localConfig.tileHeight = preset.height\n }\n },\n})\n\n/** 文本变化(输入框 / 弹框):按内容重新判定表达式或静态文本 */\nfunction onTextChanged() {\n activeMode.value = isExpressionText(expressionText.value) ? 'binding' : 'fixed'\n onChange()\n}\n\nfunction onTextInput() {\n onTextChanged()\n}\n\nfunction openExpressionEditor() {\n exprEditorVisible.value = true\n}\n\nfunction onExpressionChange(value: string) {\n expressionText.value = value\n onTextChanged()\n}\n\nfunction onColorChange(value: string) {\n localConfig.color = value\n onChange()\n}\n\n/** 统一落盘:表达式写 binding,静态文本写 content(core 两种模式都支持) */\nfunction onChange() {\n const base = {\n testData: testData.value,\n rotate: localConfig.rotate,\n color: localConfig.color,\n opacity: localConfig.opacity,\n tileWidth: localConfig.tileWidth,\n tileHeight: localConfig.tileHeight,\n }\n emit('update:modelValue', activeMode.value === 'binding'\n ? { ...base, mode: 'binding', binding: expressionText.value, content: '' }\n : { ...base, mode: 'fixed', content: expressionText.value, binding: '' })\n}\n</script>\n\n<style scoped>\n.watermark-config {\n padding: 0 4px;\n}\n\n.pd-hint {\n margin-left: 8px;\n font-size: 12px;\n color: #909399;\n min-width: 32px;\n}\n</style>\n","<template>\n <div class=\"design-background-config\">\n <h3 class=\"pd-divider\">设计背景</h3>\n <p class=\"design-background-tip\">仅设计器显示,用于套打定位,不会出现在预览和打印中</p>\n\n <template v-if=\"modelValue?.src\">\n <div class=\"design-background-path\" :title=\"modelValue.src\">{{ modelValue.src }}</div>\n <div class=\"design-background-actions\">\n <button type=\"button\" class=\"pd-button small rotate-btn\" @click=\"onRotate\">\n 旋转({{ rotation }}°)\n </button>\n <button type=\"button\" class=\"pd-button small remove-btn\" @click=\"onRemove\">移除</button>\n </div>\n </template>\n\n <label v-else class=\"pd-button small upload-label\" :class=\"{ disabled: uploadDisabled }\">\n {{ uploading ? '上传中...' : '上传背景图' }}\n <input\n class=\"visually-hidden\"\n type=\"file\"\n accept=\"image/*\"\n :disabled=\"uploadDisabled\"\n @change=\"onFileChange\"\n >\n </label>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, inject, ref } from 'vue'\nimport type { DesignBackground } from '@worm-vue3-print/core/designer'\nimport { UPLOAD_DESIGN_BACKGROUND_KEY } from '../../composables/useHostAdapter'\n\nconst props = defineProps<{ modelValue?: DesignBackground }>()\nconst emit = defineEmits<{ 'update:modelValue': [value: DesignBackground | undefined] }>()\n\nconst uploading = ref(false)\nconst uploadDesignBackground = inject(UPLOAD_DESIGN_BACKGROUND_KEY, computed(() => undefined))\nconst uploadDisabled = computed(() => uploading.value || !uploadDesignBackground.value)\n\nconst rotation = computed(() => props.modelValue?.rotation ?? 0)\n\nasync function onFileChange(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 (!uploadDesignBackground.value) {\n alert('设计背景上传能力未配置')\n input.value = ''\n return\n }\n uploading.value = true\n try {\n const src = await uploadDesignBackground.value(file)\n if (src) {\n emit('update:modelValue', { src, rotation: 0 })\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\nfunction onRotate() {\n if (!props.modelValue?.src) return\n const next = ((rotation.value + 90) % 360) as DesignBackground['rotation']\n emit('update:modelValue', { src: props.modelValue.src, rotation: next })\n}\n\nfunction onRemove() {\n emit('update:modelValue', undefined)\n}\n</script>\n\n<style scoped>\n.design-background-config {\n padding: 0 4px;\n}\n.design-background-tip {\n margin: 2px 0 6px;\n font-size: 11px;\n line-height: 1.4;\n color: var(--pd-text-muted, #909399);\n}\n.design-background-path {\n margin-bottom: 6px;\n padding: 4px 6px;\n font-size: 11px;\n color: var(--pd-text-regular, #606266);\n background: var(--pd-fill-light, #f5f7fa);\n border-radius: 3px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.design-background-actions {\n display: flex;\n gap: 6px;\n}\n.upload-label {\n cursor: pointer;\n}\n.upload-label.disabled {\n opacity: 0.6;\n cursor: not-allowed;\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","<template>\n <div class=\"tiling-config\" data-test=\"tiling-config\">\n <h3 class=\"pd-divider\">拼版打印</h3>\n <p class=\"pd-hint\">把标签按「列 × 行」铺到一张大纸上批量打印</p>\n\n <div class=\"pd-field\">\n <label class=\"tiling-switch\">\n <input\n type=\"checkbox\"\n :checked=\"cfg.enabled\"\n :disabled=\"labelContinuous\"\n @change=\"onEnabledChange(($event.target as HTMLInputElement).checked)\"\n >\n <span>启用拼版</span>\n </label>\n <p v-if=\"labelContinuous\" class=\"pd-hint tiling-error\">连续纸不支持拼版</p>\n </div>\n\n <template v-if=\"cfg.enabled && !labelContinuous\">\n <div class=\"pd-field\">\n <span class=\"pd-label\">目标纸张</span>\n <select\n class=\"pd-select\"\n style=\"width: 100%\"\n :value=\"cfg.sheetPaperSize ?? 'A4'\"\n @change=\"onSheetPaperChange(($event.target as HTMLSelectElement).value)\"\n >\n <option v-for=\"key in sheetPresetKeys\" :key=\"key\" :value=\"key\">{{ PAPER_PRESETS[key]?.label ?? key }}</option>\n <option value=\"CUSTOM\">自定义</option>\n </select>\n </div>\n\n <div v-if=\"cfg.sheetPaperSize === 'CUSTOM'\" class=\"pd-field\">\n <span class=\"pd-label\">目标纸宽高 (mm)</span>\n <div class=\"custom-size-grid\">\n <StepperInput\n :model-value=\"cfg.sheetCustomWidth\"\n :min=\"25\"\n :max=\"2000\"\n @update:model-value=\"patch({ sheetCustomWidth: $event })\"\n />\n <span class=\"custom-size-x\">×</span>\n <StepperInput\n :model-value=\"cfg.sheetCustomHeight\"\n :min=\"25\"\n :max=\"2000\"\n @update:model-value=\"patch({ sheetCustomHeight: $event })\"\n />\n </div>\n </div>\n\n <div v-else class=\"pd-field\">\n <span class=\"pd-label\">目标纸方向</span>\n <div class=\"pd-radio-group\" role=\"radiogroup\">\n <label class=\"pd-radio\">\n <input\n type=\"radio\"\n value=\"portrait\"\n :checked=\"(cfg.sheetOrientation ?? 'portrait') === 'portrait'\"\n @change=\"patch({ sheetOrientation: 'portrait' })\"\n ><span>纵向</span>\n </label>\n <label class=\"pd-radio\">\n <input\n type=\"radio\"\n value=\"landscape\"\n :checked=\"cfg.sheetOrientation === 'landscape'\"\n @change=\"patch({ sheetOrientation: 'landscape' })\"\n ><span>横向</span>\n </label>\n </div>\n </div>\n\n <h3 class=\"pd-divider\">拼版留白 (mm)</h3>\n <div class=\"margin-grid\">\n <div class=\"pd-field\"><span class=\"pd-label\">上</span>\n <StepperInput\n :model-value=\"cfg.sheetMargin.top\" :min=\"0\" :max=\"100\"\n @update:model-value=\"patchMargin('top', $event)\"\n />\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">下</span>\n <StepperInput\n :model-value=\"cfg.sheetMargin.bottom\" :min=\"0\" :max=\"100\"\n @update:model-value=\"patchMargin('bottom', $event)\"\n />\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">左</span>\n <StepperInput\n :model-value=\"cfg.sheetMargin.left\" :min=\"0\" :max=\"100\"\n @update:model-value=\"patchMargin('left', $event)\"\n />\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">右</span>\n <StepperInput\n :model-value=\"cfg.sheetMargin.right\" :min=\"0\" :max=\"100\"\n @update:model-value=\"patchMargin('right', $event)\"\n />\n </div>\n </div>\n\n <h3 class=\"pd-divider\">格间距与列数</h3>\n <div class=\"pd-field\"><span class=\"pd-label\">横向间距</span>\n <StepperInput\n :model-value=\"cfg.gapX\" :min=\"0\" :max=\"50\"\n @update:model-value=\"patch({ gapX: $event ?? 0 })\"\n />\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">纵向间距</span>\n <StepperInput\n :model-value=\"cfg.gapY\" :min=\"0\" :max=\"50\"\n @update:model-value=\"patch({ gapY: $event ?? 0 })\"\n />\n </div>\n <div class=\"pd-field\"><span class=\"pd-label\">列数</span>\n <StepperInput\n :model-value=\"cfg.columns\" :min=\"1\" :max=\"columnMax\"\n @update:model-value=\"patch({ columns: $event ?? 1 })\"\n />\n </div>\n\n <p\n v-for=\"issue in issues\"\n :key=\"issue.code\"\n class=\"pd-hint tiling-error\"\n >{{ issue.message }}</p>\n <p v-if=\"!issues.length && summary\" class=\"pd-hint tiling-summary\">{{ summary }}</p>\n </template>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport type { TemplateData } from '@worm-vue3-print/core/designer'\nimport { PAPER_PRESETS, isContinuousPaperSize } from '@worm-vue3-print/core/designer'\nimport {\n TILE_DEFAULTS,\n computeMaxColumns,\n computeTileLayout,\n resolveSheetMm,\n validateTiling,\n} from '@worm-vue3-print/core'\nimport type { TilingOptions } from '@worm-vue3-print/core'\nimport StepperInput from './StepperInput.vue'\n\nconst props = defineProps<{\n modelValue?: TilingOptions\n /** 完整模板:校验与摘要都需要标签纸尺寸/朝向,必须传 */\n templateData?: TemplateData\n}>()\n\nconst emit = defineEmits<{ 'update:modelValue': [value: TilingOptions] }>()\n\n/** 目标纸张可选预设:排除连续纸(含小票纸)与 CUSTOM(后者由下拉的「自定义」项承担) */\nconst sheetPresetKeys = Object.keys(PAPER_PRESETS)\n .filter(k => k !== 'CUSTOM' && !PAPER_PRESETS[k]?.continuous)\n\nconst labelContinuous = computed(() => isContinuousPaperSize(props.templateData?.paperSize))\n\n/**\n * 展示态配置:缺省字段补 TILE_DEFAULTS;未配置过拼版的模板 enabled 视为 false\n * (否则开关会显示成「已开启」)。\n */\nconst cfg = computed<TilingOptions>(() => ({\n ...TILE_DEFAULTS,\n ...(props.modelValue ?? {}),\n enabled: props.modelValue?.enabled ?? false,\n sheetMargin: { ...TILE_DEFAULTS.sheetMargin, ...(props.modelValue?.sheetMargin ?? {}) },\n}))\n\n/** 以当前配置构造的完整模板,供 core 的校验与布局纯函数使用(单一真实来源) */\nconst tilingTemplate = computed<TemplateData | undefined>(() =>\n props.templateData ? { ...props.templateData, tiling: cfg.value } : undefined)\n\nconst issues = computed(() =>\n tilingTemplate.value ? validateTiling(tilingTemplate.value) : [])\n\n/** 本纸最多可放列数;纯几何、不抛错,超宽时也能给出上限用于约束输入 */\nconst columnMax = computed(() => {\n const t = tilingTemplate.value\n if (!t) return 1\n return Math.max(computeMaxColumns(t), 1)\n})\n\nconst layout = computed(() => {\n const t = tilingTemplate.value\n if (!t || issues.value.length) return undefined\n try {\n return computeTileLayout(t)\n } catch {\n return undefined\n }\n})\n\nconst summary = computed(() => {\n const l = layout.value\n const t = tilingTemplate.value\n if (!l || !t) return ''\n const s = resolveSheetMm(t)\n const name = cfg.value.sheetPaperSize === 'CUSTOM' ? '自定义' : (cfg.value.sheetPaperSize ?? 'A4')\n const dir = cfg.value.sheetPaperSize === 'CUSTOM'\n ? ''\n : (cfg.value.sheetOrientation === 'landscape' ? ' 横向' : ' 纵向')\n return `目标纸 ${name}${dir} ${s.width}×${s.height}mm · ${l.columns} 列 × ${l.rows} 行 = 每张 ${l.perSheet} 格`\n})\n\nfunction patch(partial: Partial<TilingOptions>) {\n emit('update:modelValue', { ...cfg.value, ...partial })\n}\n\nfunction patchMargin(side: 'top' | 'right' | 'bottom' | 'left', value: number | undefined) {\n patch({ sheetMargin: { ...cfg.value.sheetMargin, [side]: value ?? 0 } })\n}\n\n/** 切换目标纸张:切到 CUSTOM 时补上当前解析尺寸,避免出现空宽高 */\nfunction onSheetPaperChange(value: string) {\n if (value !== 'CUSTOM') {\n patch({ sheetPaperSize: value as TilingOptions['sheetPaperSize'] })\n return\n }\n const t = tilingTemplate.value\n const current = t ? resolveSheetMm(t) : { width: 210, height: 297 }\n patch({\n sheetPaperSize: 'CUSTOM',\n sheetCustomWidth: cfg.value.sheetCustomWidth ?? current.width,\n sheetCustomHeight: cfg.value.sheetCustomHeight ?? current.height,\n })\n}\n\n/**\n * 打开开关时写入 TILE_DEFAULTS 并按纸面收敛列数:\n * 目标纸很小时默认 2 列可能直接非法到连保存都被拦,这里收敛为能放下的列数。\n * 关闭时保留其余字段(再次打开不丢配置)。\n */\nfunction onEnabledChange(next: boolean) {\n if (!next) {\n patch({ enabled: false })\n return\n }\n const max = columnMax.value\n const columns = max >= 1 ? Math.min(TILE_DEFAULTS.columns, max) : 1\n patch({ ...TILE_DEFAULTS, columns })\n}\n</script>\n\n<style scoped>\n.tiling-config {\n padding: 0 4px;\n}\n.tiling-switch {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n cursor: pointer;\n}\n.tiling-error {\n color: #f56c6c;\n}\n.tiling-summary {\n color: var(--pd-text-regular, #606266);\n}\n</style>\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 <!-- 条码/二维码设置(码制、条宽、缩放模式、最大宽高等) -->\n <CodeGroup v-if=\"filteredGroups.includes('code') && isCodeType\" :element=\"element\" :matched-keys=\"matchedKeys\" :searching=\"searching\" @change=\"recordHistory?.()\" />\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 <optgroup v-for=\"group in paperPresetGroups\" :key=\"group.group\" :label=\"group.group\">\n <option v-for=\"item in group.items\" :key=\"item.key\" :value=\"item.key\">{{ item.label }}</option>\n </optgroup>\n <option value=\"CUSTOM\">自定义宽高</option>\n </select>\n </div>\n <p v-if=\"labelPaper\" class=\"pd-hint\">标签纸默认整张给内容区:已取消页边距与页眉页脚,可在下方自行改回</p>\n <div class=\"pd-field\" v-if=\"continuousPaper || paperSizeModel === 'CUSTOM'\"><span class=\"pd-label\">{{ continuousPaper ? '纸宽 (mm)' : '自定义宽高 (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 <template v-if=\"paperSizeModel === 'CUSTOM'\">\n <span class=\"custom-size-x\">×</span>\n <StepperInput :model-value=\"customHeight\"\n :min=\"25\"\n :max=\"2000\"\n @update:model-value=\"onCustomHeightChange\" />\n </template>\n </div>\n </div>\n <div class=\"pd-field\" v-if=\"!continuousPaper\"><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 <p class=\"pd-hint\">切换即交换纸张长宽(设计稿内容随之铺在该尺寸上)</p>\n </div>\n <div class=\"pd-field\" v-if=\"!continuousPaper && !tilingEnabled\"><span class=\"pd-label\">内容旋转角度</span>\n <div class=\"pd-radio-group pd-radio-group--2col\" role=\"radiogroup\">\n <label class=\"pd-radio\"><input type=\"radio\" value=\"0\" :checked=\"outputRotationModel === 0\" @change=\"onOutputRotationChange(($event.target as HTMLInputElement).value)\"><span>0°</span></label>\n <label class=\"pd-radio\"><input type=\"radio\" value=\"90\" :checked=\"outputRotationModel === 90\" @change=\"onOutputRotationChange(($event.target as HTMLInputElement).value)\"><span>90°</span></label>\n <label class=\"pd-radio\"><input type=\"radio\" value=\"180\" :checked=\"outputRotationModel === 180\" @change=\"onOutputRotationChange(($event.target as HTMLInputElement).value)\"><span>180°</span></label>\n <label class=\"pd-radio\"><input type=\"radio\" value=\"270\" :checked=\"outputRotationModel === 270\" @change=\"onOutputRotationChange(($event.target as HTMLInputElement).value)\"><span>270°</span></label>\n </div>\n <p class=\"pd-hint\">整页内容旋转对应角度出纸;90°/270° 时纸张长宽互换以贴合内容,内容不变形不裁切;0° 为不旋转(默认)</p>\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 <DesignBackgroundConfig\n :model-value=\"designBackgroundModel\"\n @update:model-value=\"onDesignBackgroundChange\"\n />\n\n <TilingConfig\n v-if=\"!multiPage\"\n :model-value=\"templateData?.tiling\"\n :template-data=\"templateData\"\n @update:model-value=\"emitUpdate({ tiling: $event })\"\n />\n\n <h3 class=\"pd-divider\">页边距 (mm)</h3>\n <p v-if=\"continuousPaper\" class=\"pd-hint\">底部边距即连续纸走纸留白</p>\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=\"100\" @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\n <WatermarkConfig :model-value=\"watermarkModel\" :fields=\"fields\" @update:model-value=\"onWatermarkChange\" />\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 '@worm-vue3-print/core/designer'\nimport { PAPER_PRESETS, isContinuousPaperSize, isLabelPaperSize, labelPaperDefaults } from '@worm-vue3-print/core/designer'\nimport { searchProperties } from '@worm-vue3-print/core/designer'\nimport PropertySearch from './property/PropertySearch.vue'\nimport PositionSizeGroup from './property/PositionSizeGroup.vue'\nimport AppearanceGroup from './property/AppearanceGroup.vue'\nimport CodeGroup from './property/CodeGroup.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 WatermarkConfig from './WatermarkConfig.vue'\nimport DesignBackgroundConfig from './property/DesignBackgroundConfig.vue'\nimport TilingConfig from './property/TilingConfig.vue'\nimport type { WatermarkOptions } from '@worm-vue3-print/core/designer'\nimport { getElementBindings, getTableCellBindings } from '@worm-vue3-print/core/designer'\nimport type { BindingDescriptor } from '@worm-vue3-print/core/designer'\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 multiPage?: 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\n/** 纸张下拉分组:按 PAPER_PRESETS 的 group 聚合,保持预设声明顺序;多页时过滤连续纸(小票纸/热敏卷纸) */\nconst paperPresetGroups = computed(() => {\n const groups: { group: string; items: { key: string; label: string }[] }[] = []\n for (const [key, preset] of Object.entries(PAPER_PRESETS)) {\n if (props.multiPage && isContinuousPaperSize(key)) continue\n const group = preset.group ?? '其他'\n let bucket = groups.find(g => g.group === group)\n if (!bucket) {\n bucket = { group, items: [] }\n groups.push(bucket)\n }\n bucket.items.push({ key, label: preset.label ?? key })\n }\n return groups\n})\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 isCodeType = computed(() => {\n if (!props.element) return false\n return ['barcode', 'qrcode'].includes(props.element.printElementType.type)\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')\n/** 连续纸(含小票纸):强制纵向、纸宽可调、出纸高度按内容推导;多页模式不可用 */\nconst continuousPaper = computed(() => !props.multiPage && isContinuousPaperSize(paperSizeModel.value))\n/** 标签纸:切到该纸型时已套用「无页边距、无页眉页脚」默认版面 */\nconst labelPaper = computed(() => isLabelPaperSize(paperSizeModel.value))\nconst orientationModel = computed(() => props.templateData?.orientation || 'portrait')\n/** 拼版(标签铺格)无出纸方向概念,隐藏出纸方向控件 */\nconst tilingEnabled = computed(() => !!props.templateData?.tiling?.enabled)\n/**\n * 内容旋转角度:缺省 0(不旋转);可设为 90/180/270,整页内容旋转对应角度出纸。\n * 渲染端仅在固定纸(非连续纸、非拼版)场景按角度旋转整页。\n */\nconst outputRotationModel = computed(() => props.templateData?.outputRotation ?? 0)\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 ?? PAPER_PRESETS[paperSizeModel.value]?.width ?? 210)\nconst customHeight = computed(() => props.templateData?.customHeight ?? 297)\n\nconst designBackgroundModel = computed(() => props.templateData?.designBackground)\n\nfunction onDesignBackgroundChange(value: TemplateData['designBackground'] | undefined) {\n if (!props.templateData) return\n if (!value) {\n const rest = { ...props.templateData }\n delete rest.designBackground\n emit('update:templateData', rest)\n return\n }\n emitUpdate({ designBackground: value })\n}\n\n/** 水印配置(缺省时给空对象,WatermarkConfig 内部按默认值展示) */\nconst watermarkModel = computed<WatermarkOptions>(() => props.templateData?.watermark ?? {})\n\nfunction onWatermarkChange(value: WatermarkOptions) {\n emitUpdate({ watermark: value })\n}\n\nfunction emitUpdate(partial: Partial<TemplateData>) {\n if (!props.templateData) return\n const next = {\n ...props.templateData,\n ...partial,\n } as TemplateData\n emit('update:templateData', next)\n}\n\nfunction onPaperSizeChange(size: string) {\n if (!props.templateData) return\n if (isContinuousPaperSize(size)) {\n // 连续纸默认:纵向、底边距 0(走纸留白由用户配置);\n // 纸宽取 customWidth,切到具体小票纸预设时清掉旧自定义宽度,回到预设纸宽\n emitUpdate({\n paperSize: size as TemplateData['paperSize'],\n customWidth: size === 'CONTINUOUS' ? props.templateData?.customWidth ?? 80 : undefined,\n orientation: 'portrait',\n margins: {\n ...props.templateData!.margins,\n bottom: props.templateData?.margins.bottom ?? 0,\n },\n })\n return\n }\n if (size === 'CUSTOM') {\n emitUpdate({ paperSize: 'CUSTOM' })\n return\n }\n if (!PAPER_PRESETS[size]) return\n if (isLabelPaperSize(size)) {\n // 标签纸默认:整张纸都给内容区(无页边距、无页眉页脚),用户仍可在下方自行改回\n emitUpdate({ paperSize: size as TemplateData['paperSize'], ...labelPaperDefaults(props.templateData) })\n return\n }\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 onOutputRotationChange(val: string | number | boolean | undefined) {\n emitUpdate({ outputRotation: Number(val) as TemplateData['outputRotation'] })\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.pd-hint {\n margin: 2px 0 6px;\n color: var(--pd-text-muted, #8b909c);\n font-size: 12px;\n line-height: 1.4;\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 position: relative;\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)}\n合计:{ROUND(qty * price, 2)}</code></pre>\n<p>花括号内可直接写四则运算(<code>{qty * price}</code>),也可用 <code>ADD</code> / <code>SUB</code> / <code>MUL</code> / <code>DIV</code> 函数;\n需要保留几位小数时用 <code>ROUND</code>(四舍五入)、<code>ROUNDUP</code>(进一)、<code>ROUNDDOWN</code>(去尾)或 <code>ROUNDBANK</code>(四舍六入五成双)。</p>\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>四舍五入(位数缺省 2)</td><td><code>{ROUND(price, 2)}</code></td></tr>\n <tr><td><code>ROUNDUP(n, d)</code> / <code>CEIL(n, d)</code></td><td>进一法(远离零)</td><td><code>{ROUNDUP(price, 2)}</code></td></tr>\n <tr><td><code>ROUNDDOWN(n, d)</code> / <code>FLOOR(n, d)</code></td><td>去尾法(朝零)</td><td><code>{ROUNDDOWN(price, 2)}</code></td></tr>\n <tr><td><code>ROUNDBANK(n, d)</code></td><td>四舍六入五成双(GB/T 8170)</td><td><code>{ROUNDBANK(price, 2)}</code></td></tr>\n <tr><td><code>ADD(a, b, ...)</code></td><td>相加(变参)</td><td><code>{ADD(qty, 1)}</code></td></tr>\n <tr><td><code>SUB(a, b, ...)</code></td><td>相减</td><td><code>{SUB(total, discount)}</code></td></tr>\n <tr><td><code>MUL(a, b, ...)</code></td><td>相乘(变参)</td><td><code>{MUL(qty, price)}</code></td></tr>\n <tr><td><code>DIV(a, b)</code></td><td>相除(除数为 0 返回 0)</td><td><code>{DIV(total, qty)}</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<h3>组合</h3>\n<p>选中多个元素后(Ctrl/⌘+点击或空白处框选),可通过工具栏按钮、图层面板按钮或 <code>Ctrl + G</code> 将它们组合为一组;取消组合用 <code>Ctrl + Shift + G</code>。组合后:</p>\n<ul>\n <li>点击任一成员即选中整组,拖动任一成员整组跟动</li>\n <li><strong>打印时整组强制在同一页</strong>,不会跨页拆分</li>\n</ul>\n<p><strong>注意:</strong>组内元素的总高度不能超过纸张内容区,否则整组移到新页后,超出部分仍会被裁掉。组太高时请拆分为多个小组或取消组合。</p>\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>水印内容用统一的「水印表达式」输入:直接输入文字即为静态水印;写成 <code>{order.no}</code>、<code>CONCAT(...)</code> 等即按表达式解析</li>\n <li>点击「编辑表达式」(或双击输入框)打开表达式弹框,可直接选择业务字段与系统变量:打印日期 <code>{printDate}</code>、打印时间 <code>{printTime}</code>、当前页码 <code>{pageIndex}</code>、总页数 <code>{totalPages}</code>;表达式取不到值时回退到测试值</li>\n <li>可设置旋转角度(-90°~90°)、颜色与透明度</li>\n <li>支持调节水印密度(密/中/疏/自定义瓦片尺寸),以及设置水印颜色</li>\n <li>水印在画布、浏览器预览、服务端 PDF、静默打印四端渲染一致</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>Ctrl / ⌘ + 点击</code></td><td>在画布或图层面板中逐个加选/取消选择元素</td></tr>\n <tr><td><code>空白处拖拽框选</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)、针式打印纸(全等分 / 二等分 / 三等分)、标签纸(80×60、60×40、40×30)、小票纸(57 / 80 / 110mm)</li>\n <li>或选择\"自定义\"输入宽度和高度(mm);\"连续纸\"可自定义纸宽,出纸高度按内容自动推导</li>\n <li>设置方向:纵向(portrait)或横向(landscape);切换即交换纸张长宽,设计稿内容随之铺在该尺寸上。连续纸与小票纸固定纵向</li>\n <li>内容旋转角度:0° / 90° / 180° / 270°,整页内容旋转对应角度出纸。90° / 270° 时纸张长宽互换以贴合旋转后的内容,设计稿内容保持原方向、不变形不裁切;0° 为不旋转(默认)。连续纸与小票纸固定纵向、无旋转概念</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 <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</ul>\n<p>模板加载 / 重置(如「加载默认布局」)由宿主实现:把新的模板数据赋给 <code>initialTemplate</code> 即可重载画布。</p>\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(Mac 为 ⌘)在画布或左侧图层面板中逐个点击元素,逐个加入/移出选择</li>\n <li>在画布<strong>空白区域</strong>按下并拖动进行框选(起点落在元素上时会变为选中或拖动该元素,不会启动框选):\n <ul>\n <li>从左上向右下拖动:与选框<strong>相交</strong>的元素即被选中</li>\n <li>从右下向左上拖动:仅<strong>完全包围</strong>的元素被选中</li>\n </ul>\n </li>\n <li>按 <code>Ctrl + A</code> 全选当前页元素</li>\n</ol>\n\n<h2>如何组合多个元素?</h2>\n<ol>\n <li>按住 Ctrl(Mac 为 ⌘)逐个点击,或用空白处框选选中多个元素</li>\n <li>点击工具栏\"组合\"按钮、图层面板底部的组合按钮,或按 <code>Ctrl + G</code></li>\n <li>组合后点击任一成员可选中整组;拖动任一成员整组跟动;打印时整组强制同页</li>\n <li>取消组合:选中组内任一成员后点击\"取消组合\"(工具栏或图层面板),或按 <code>Ctrl + Shift + G</code></li>\n</ol>\n<p><strong>注意:</strong>组合元素会强制打印在同一页,引擎不会为它跨页拆分。组合前请确认组内元素的总高度(从最高点到最低点)不超过纸张内容区,否则整组虽会移到新的一页,超出页面的部分仍会被裁掉。组太高时请拆分为多个小组,或取消组合。</p>\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<h2>为什么部分页面有水印、部分页面没有?</h2>\n<ol>\n <li>水印是<strong>按模板</strong>独立设置的,每一个设计的模板都需要单独配置自己的水印信息,不会自动继承其他模板。</li>\n <li>如果出现部分页面存在水印、部分页面没有水印的情况,说明该页面所在的模板没有为自身设置水印。</li>\n <li>为模板添加水印:进入该模板专属页面,在右侧的\"页面属性\"中找到\"水印\"配置项进行设计即可。</li>\n</ol>\n<blockquote>\n <p><strong>提示</strong>:水印配置保存在模板 JSON 的 <code>watermark</code> 字段中,仅对当前模板生效。</p>\n</blockquote>\n `\n}\n","export default {\n id: 'changelog',\n title: '更新记录',\n content: `\n<h2>v1.3.2 <small>2026-09-26</small></h2>\n\n<h3>修复</h3>\n<ul>\n <li><strong>表格下方间距不再变大</strong>:放在表格下方的元素(合计行、签名栏等),此前打印到纸上时间距会被莫名拉大(设计台上看着正常)。现在以设计台上看到的表格底部为准,出纸与所见一致。</li>\n <li><strong>翻页后不再互相叠压</strong>:表格断页续到新一页后,页尾的组合元素此前会和续排内容叠在一起。现在换页后各元素从上到下顺排,组合依然整组同页、放不下就整组移到下一页。</li>\n</ul>\n\n<h3>改进</h3>\n<ul>\n <li><strong>组合与多选更好用</strong>:画布和图层面板都支持 Ctrl/⌘ 点击加选;只要选中内容里有组成员,「取消组合」就会出现;组合/取消组合可在工具栏、图层面板底部按钮或 <code>Ctrl+G</code> / <code>Ctrl+Shift+G</code> 完成。帮助文档补充了框选规则与组合说明。</li>\n <li><strong>图标焕新</strong>:工具栏与图层面板图标统一为新风格,全部带悬停提示;组合/取消组合使用专属图标。</li>\n</ul>\n\n<h2>v1.3.1 <small>2026-09-21</small></h2>\n\n<h3>新增</h3>\n<ul>\n <li><strong>数值运算与修约</strong>:表达式新增四则函数 <code>ADD</code> / <code>SUB</code> / <code>MUL</code> / <code>DIV</code>,以及修约函数 <code>ROUND</code>(四舍五入)、<code>ROUNDUP</code>(进一)、<code>ROUNDDOWN</code>(去尾)、<code>ROUNDBANK</code>(四舍六入五成双)。位数可省略(默认两位),写负数则修约到整十/整百。表达式编辑器「函数」页新增「数值运算」分组,双击即可插入。</li>\n <li><strong>四则运算更准</strong>:直接写 <code>{qty * price}</code> 时,数字字符串按数值参与运算、不再出现 <code>0.30000000000000004</code> 这类浮点尾巴、除以 0 不再印出 <code>Infinity</code>。</li>\n <li><strong>在线示例更好上手</strong>:示例库新增「综合示例模板」(多级表头 + 表格内图片 / 条形码 / 二维码混排),进入页面即自动载入;新增「自定义字段与数据」弹窗,可直接在页面上增删字段、编辑多份打印数据。在线预览已支持静态托管,可直接打开网页体验。</li>\n</ul>\n\n<h3>变更</h3>\n<ul>\n <li><strong>静默打印 SDK 并入 core</strong>:原 <code>@worm-vue3-print/client</code> 不再单独安装,改为从 <code>@worm-vue3-print/core/client</code> 导入;<code>PrintClient</code> 等能力保持不变,core 也不会因此增加依赖。</li>\n</ul>\n\n<h3>修复</h3>\n<ul>\n <li><code>ROUND(1.005, 2)</code> 此前得到 <code>1</code>(应为 <code>1.01</code>)、<code>ROUND(2.675, 2)</code> 得到 <code>2.67</code>(应为 <code>2.68</code>)——改为按十进制精确修约。</li>\n <li>页码、打印日期此前只能在花括号里单独使用(<code>{pageIndex}</code>),一旦参与运算或函数(<code>{pageIndex + 1}</code>、<code>{ADD(pageIndex,1)}</code>、<code>{DATE(printDate,'YYYY')}</code>)就会被原样印出。现在这些写法都会按所在页真实求值,页眉/页脚、表格单元格同样生效。</li>\n <li><strong>多级表头跨页不再丢层级</strong>:表头有好几层时,翻页后第二层往下曾经整段消失(只重复了最上面一行)。现在「表头每页重复」按整个表头区生效——表头里任意一层勾了,每一页都会完整印出全部层级;新增表头行也会自动跟随同一设置,不用担心漏勾。</li>\n</ul>\n\n<h2>v1.3.0 <small>2026-09-20</small></h2>\n\n<h3>新增</h3>\n<ul>\n <li><strong>多页面模板</strong>:一份文书可以由版式不同的多个页面按固定顺序组成(如「封面 + 正文 + 条款」),各页绑定同一份数据,下一次出纸就是完整的一份文档。顶部页面栏支持新增、复制、删除、前移/后移、双击重命名与点击切换;删到只剩一页时自动回到单页模式。</li>\n <li><strong>内容旋转角度</strong>:页面属性新增「内容旋转角度」(0° / 90° / 180° / 270°),支持横版设计、竖版出纸——内容整体旋转填满出纸版面,不缩放也不裁切。</li>\n <li><strong>设计背景(套打底图)</strong>:页面属性支持上传、90° 步进旋转与移除底图,照着现成单据排版更省力。底图只在设计画布显示,预览与打印都不会输出。</li>\n</ul>\n\n<h3>变更</h3>\n<ul>\n <li><strong>条码尺寸</strong>:条形码(元素与表格单元格)不再拉伸填满元素框,改为按「条宽 → 打印机分辨率 → 等比缩小」结算:默认条宽下每模块 0.25mm,装得下就按原尺寸落纸;设置了「打印机分辨率」(203/300/600)时吸附到整数打印点;宽度不足时整体等比缩小。要更大的条码请调大「条宽」,需要上限请用「最大宽高」——条形码不再提供「缩放模式」。<strong>同一份旧模板的条码会变小</strong>,这是让出纸条宽保持稳定所必需的。</li>\n <li><strong>文字溢出</strong>:文本元素与表格单元格支持「截断 / 自动缩小 / 自适应行高」三种显示形式(属性面板「文字溢出」),缺省值与原有行为一致,存量模板不受影响。</li>\n <li><strong>标签纸</strong>:纸张切到标签纸(80×60 / 60×40 / 40×30mm)时默认取消页边距与页眉页脚,整张纸都给内容区;只在切换纸型时套用一次,之后仍可自行改回,存量模板不会被改写。</li>\n <li><strong>多页面约束</strong>:纸张设置对所有页生效,页边距、页眉页脚、首页叠加、水印与内容元素则按页各自独立;多页模式下隐藏拼版配置、禁用连续纸。</li>\n</ul>\n\n<h3>修复</h3>\n<ul>\n <li>多页面模板页面重排后页签名漂移、删除页面后再新增出现重名。</li>\n <li>条形码经热敏打印机出纸条宽忽宽忽窄、边缘发灰;条宽倍率在不同模式下视觉不一致。</li>\n <li>元素堆叠与显式组合在分页时被拆散;单击组合内的任一成员改为选中整组。</li>\n <li>水印经真实打印机出纸被放大约 3 倍、位置偏移、平铺错乱(改为逐块矢量瓦片渲染)。</li>\n <li>小纸张模板(如 80×60mm 自定义纸)输出多出一张空白首页。</li>\n</ul>\n\n<h2>v1.2.2 <small>2026-09-11</small></h2>\n\n<h3>变更</h3>\n<ul>\n <li><code>@worm-vue3-print/core</code> 新增子路径 <code>/designer</code>:框架无关的设计器内核,包含完整模板模型类型、通用工具(元素工厂、表格矩阵、单位换算、模板迁移、标尺等)与纯交互逻辑(对齐、分组、键盘、缩放、吸附计算),不依赖 Vue/React。</li>\n <li><code>@worm-vue3-print/core</code> 新增子路径 <code>/browser</code>:浏览器侧渲染适配器(<code>renderHtmlPages</code> 两遍分页渲染、条形码/二维码渲染器)。</li>\n <li>设计器模型、工具与纯逻辑下沉至 core 子路径,canvas 仅保留 Vue 适配层;公共 API 保持不变,core 主入口仍为零运行时依赖,为后续多框架适配打下基础。</li>\n</ul>\n\n<h3>修复</h3>\n<ul>\n <li>修复工具栏放大/缩小按钮直接线性改缩放比例、未做滚动锚点校正导致画面漂移的问题;按钮缩放改为与 Ctrl+滚轮一致的乘性步进,并以视口中心为锚点(与「适应窗口」同一缩放管线)。</li>\n</ul>\n\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","<template>\n <div class=\"page-tabs\" @mouseover=\"onTipOver\" @mouseout=\"onTipOut\" @mouseleave=\"hideTip\">\n <div class=\"page-tabs-list\">\n <template v-for=\"(p, i) in pages\" :key=\"i\">\n <input\n v-if=\"editingIndex === i\"\n v-model=\"renameText\"\n class=\"page-tab-rename\"\n data-test=\"page-rename-input\"\n @blur=\"commitRename(i)\"\n @keydown.enter=\"commitRename(i)\"\n @keydown.esc=\"cancelRename\"\n />\n <button\n v-else\n class=\"page-tab\"\n :class=\"{ active: i === activeIndex }\"\n :data-tip=\"p.name ? `${p.name}(双击重命名)` : '双击重命名'\"\n @click=\"$emit('select', i)\"\n @dblclick=\"startRename(i)\"\n >\n {{ p.name || `页面 ${i + 1}` }}\n </button>\n </template>\n </div>\n <div class=\"page-tabs-actions\">\n <button data-test=\"add-page\" :data-tip=\"addTip\" :disabled=\"tilingEnabled\" @click=\"$emit('add')\">+</button>\n <button data-test=\"duplicate-page\" :data-tip=\"duplicateTip\" :disabled=\"tilingEnabled\" @click=\"$emit('duplicate')\">⧉</button>\n <button data-test=\"delete-page\" :data-tip=\"multi ? `删除当前页「${activeName}」` : '仅多页面模板可删除页面'\" :disabled=\"!multi\" @click=\"$emit('delete', activeIndex)\">✕</button>\n <button data-test=\"move-left\" :data-tip=\"`前移「${activeName}」`\" :disabled=\"activeIndex <= 0\" @click=\"$emit('move', activeIndex, activeIndex - 1)\">←</button>\n <button data-test=\"move-right\" :data-tip=\"`后移「${activeName}」`\" :disabled=\"activeIndex >= pages.length - 1\" @click=\"$emit('move', activeIndex, activeIndex + 1)\">→</button>\n </div>\n <!-- 自定义 tooltip:fixed 定位挂在本组件根下,不受页签列表 overflow 裁剪,z-index 高于画布各层 -->\n <div v-if=\"tip\" class=\"page-tabs-tip\" :style=\"{ left: `${tip.x}px`, top: `${tip.y}px` }\">{{ tip.text }}</div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, onUnmounted } from 'vue'\nimport type { TemplateData } from '@worm-vue3-print/core/designer'\nimport { TILING_SINGLE_PAGE_TIP } from '../composables/useDesignerState'\n\nconst props = defineProps<{\n pages: TemplateData[]\n activeIndex: number\n /** 多页模式(≥2 页)才可删除;单页回落单模板 */\n multi: boolean\n /** 已开启拼版:拼版模板只允许一个设计页面,禁用增页入口 */\n tilingEnabled?: boolean\n}>()\n\nconst emit = defineEmits<{\n select: [index: number]\n add: []\n duplicate: []\n delete: [index: number]\n rename: [index: number, name: string]\n move: [from: number, to: number]\n}>()\n\n// 行内重命名:双击页签进入编辑,blur/Enter 提交,Esc 取消\nconst editingIndex = ref(-1)\nconst renameText = ref('')\n\n/** 当前激活页名:用于操作按钮 tooltip 的上下文提示 */\nconst activeName = computed(() => props.pages[props.activeIndex]?.name || `页面 ${props.activeIndex + 1}`)\n\n/** 增页按钮 tooltip:拼版开启时改为「不可增页」的原因说明 */\nconst addTip = computed(() =>\n props.tilingEnabled ? TILING_SINGLE_PAGE_TIP : '新增页面(在当前页后追加空白页)')\nconst duplicateTip = computed(() =>\n props.tilingEnabled ? TILING_SINGLE_PAGE_TIP : `复制当前页「${activeName.value}」`)\n\nfunction startRename(i: number) {\n editingIndex.value = i\n renameText.value = props.pages[i]?.name ?? ''\n}\n\nfunction commitRename(i: number) {\n if (editingIndex.value !== i) return\n const name = renameText.value.trim()\n if (name) emit('rename', i, name)\n editingIndex.value = -1\n}\n\nfunction cancelRename() {\n editingIndex.value = -1\n}\n\n// 自定义 tooltip:事件委托到根节点,读 data-tip 与目标位置,延迟 300ms 显示避免滑过闪烁\ninterface TipState { text: string; x: number; y: number }\nconst tip = ref<TipState | null>(null)\nlet tipTimer: ReturnType<typeof setTimeout> | null = null\n\nfunction showTipFor(el: HTMLElement) {\n const text = el.dataset.tip\n if (!text) return\n const rect = el.getBoundingClientRect()\n // 水平以目标中心对齐并夹取到视口内(粗夹即可,translateX(-50%) 后偏差可忽略)\n const x = Math.min(Math.max(rect.left + rect.width / 2, 80), window.innerWidth - 80)\n tip.value = { text, x, y: rect.bottom + 6 }\n}\n\nfunction onTipOver(e: MouseEvent) {\n const el = (e.target as HTMLElement).closest?.('[data-tip]') as HTMLElement | null\n if (!el) return\n if (tipTimer) clearTimeout(tipTimer)\n tipTimer = setTimeout(() => showTipFor(el), 300)\n}\n\nfunction onTipOut(e: MouseEvent) {\n const el = (e.target as HTMLElement).closest?.('[data-tip]') as HTMLElement | null\n // 在同一目标内部移动(子元素间切换)不隐藏\n if (el && (e.relatedTarget as HTMLElement | null)?.closest?.('[data-tip]') === el) return\n hideTip()\n}\n\nfunction hideTip() {\n if (tipTimer) { clearTimeout(tipTimer); tipTimer = null }\n tip.value = null\n}\n\nonUnmounted(hideTip)\n</script>\n\n<style scoped>\n.page-tabs {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 4px 12px;\n background: var(--pd-sidebar, #fff);\n border-bottom: 1px solid var(--pd-border, #d9dde6);\n flex-shrink: 0;\n}\n.page-tabs-list {\n display: flex;\n gap: 4px;\n overflow-x: auto;\n align-items: center;\n}\n.page-tab {\n padding: 4px 12px;\n border: 1px solid var(--pd-border, #d9dde6);\n border-radius: 4px;\n background: transparent;\n cursor: pointer;\n white-space: nowrap;\n color: var(--pd-text, #2a2e37);\n font-size: 12px;\n}\n.page-tab.active {\n background: var(--pd-accent, #165DFF);\n color: #fff;\n}\n.page-tab-rename {\n padding: 4px 8px;\n width: 96px;\n border: 1px solid var(--pd-accent, #165DFF);\n border-radius: 4px;\n font-size: 12px;\n color: var(--pd-text, #2a2e37);\n outline: none;\n}\n.page-tabs-actions {\n display: flex;\n gap: 4px;\n margin-left: auto;\n}\n.page-tabs-actions button {\n padding: 4px 8px;\n border: 1px solid var(--pd-border, #d9dde6);\n border-radius: 4px;\n background: transparent;\n cursor: pointer;\n color: var(--pd-text-muted, #8b909c);\n font-size: 12px;\n line-height: 1;\n}\n.page-tabs-actions button:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n.page-tabs-tip {\n position: fixed;\n z-index: 9999;\n transform: translateX(-50%);\n padding: 4px 8px;\n border-radius: 4px;\n background: rgba(42, 46, 55, 0.92);\n color: #fff;\n font-size: 12px;\n line-height: 1.4;\n white-space: nowrap;\n pointer-events: none;\n}\n</style>\n","import { ref, watch } from 'vue'\n\nconst LEFT_KEY = 'print-studio:left'\nconst RIGHT_KEY = 'print-studio:right'\n\nfunction readStored(key: string, fallback: boolean): boolean {\n try {\n const raw = localStorage.getItem(key)\n return raw === null ? fallback : raw === '1'\n } catch {\n return fallback\n }\n}\n\nexport function useStudioChrome() {\n const leftCollapsed = ref(readStored(LEFT_KEY, false))\n const rightCollapsed = ref(readStored(RIGHT_KEY, false))\n const dirty = ref(false)\n\n watch(leftCollapsed, v => { try { localStorage.setItem(LEFT_KEY, v ? '1' : '0') } catch { /* ignore */ } }, { flush: 'sync' })\n watch(rightCollapsed, v => { try { localStorage.setItem(RIGHT_KEY, v ? '1' : '0') } catch { /* ignore */ } }, { flush: 'sync' })\n\n function toggleLeft() { leftCollapsed.value = !leftCollapsed.value }\n function toggleRight() { rightCollapsed.value = !rightCollapsed.value }\n function markSaved() { dirty.value = false }\n\n return { leftCollapsed, rightCollapsed, toggleLeft, toggleRight, dirty, markSaved }\n}\n","<template>\n <div class=\"designer-container\">\n <DesignerToolbar\n :is-edit=\"isEdit\"\n :can-undo=\"canUndo\"\n :can-redo=\"canRedo\"\n :has-multi-selection=\"selectedIds.size >= 2\"\n :has-selection=\"selectedIds.size >= 1\"\n :show-ruler=\"showRuler\"\n :show-grid=\"showGrid\"\n :snap-to-grid=\"snapToGrid\"\n :show-table-ghost-border=\"showTableGhostBorder\"\n :selected-element-has-group=\"selectedHasGroup\"\n :overlay-visible=\"overlayVisible\"\n :show-help=\"showHelp !== false\"\n v-model:scale=\"scale\"\n @preview=\"$emit('preview')\"\n @save=\"handleSave\"\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=\"onToolbarZoom\"\n @help=\"helpVisible = true\"\n />\n\n <!-- 页面栏:多页签 + 新增/复制/删除/排序 -->\n <PageTabs\n :pages=\"pages\"\n :active-index=\"activePageIndex\"\n :multi=\"pages.length > 1\"\n :tiling-enabled=\"tilingEnabled\"\n @select=\"switchPage\"\n @add=\"addPage\"\n @duplicate=\"duplicatePage\"\n @delete=\"deletePage\"\n @rename=\"renamePage\"\n @move=\"movePage\"\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 @group=\"onGroup\"\n @ungroup=\"onUngroup\"\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 @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 @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 :multi-page=\"pages.length > 1\"\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, UploadDesignBackgroundFn, MultiPageTemplateData } from '@worm-vue3-print/core/designer'\nimport type { PrintFontDeclaration, PrintTemplateData, MultiPageTemplateData as PrintMultiPageTemplateData } from '@worm-vue3-print/core'\nimport { buildFontFaceCss, validateTiling, normalizeTemplate } from '@worm-vue3-print/core'\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 '@worm-vue3-print/core/designer'\nimport { getPaperDimensions, PAPER_PRESETS } from '@worm-vue3-print/core/designer'\nimport { DEFAULT_DEMO_DATA } from '@worm-vue3-print/core/designer'\nimport { findMainCell } from '@worm-vue3-print/core/designer'\nimport { computeFitScale, FIT_SCALE_MIN_PERCENT } from '@worm-vue3-print/core/designer'\nimport {\n UPLOAD_IMAGE_KEY,\n UPLOAD_DESIGN_BACKGROUND_KEY,\n FONT_CATALOG_KEY,\n} from '../composables/useHostAdapter'\nimport { useFontCatalog } from '../composables/useFontCatalog'\nimport { useDocumentFontFace } from '../composables/useDocumentFontFace'\nimport type { AlignMode } from '@worm-vue3-print/core/designer'\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 PageTabs from './PageTabs.vue'\nimport { useStudioChrome } from '../composables/useStudioChrome'\n\nconst props = defineProps<{\n initialTemplate?: TemplateData | MultiPageTemplateData\n initialElements?: RuntimeElement[]\n fields?: PrintBusinessField[]\n isEdit?: boolean\n /** 截图适配器(叠层对比):未注入时该功能不可用 */\n requestScreenshot?: RequestScreenshotFn\n /** 图片上传适配器:未注入时图片上传不可用 */\n uploadImage?: UploadImageFn\n /** 设计背景图上传适配器:未注入时背景上传入口禁用;返回值须为完整图片路径 */\n uploadDesignBackground?: UploadDesignBackgroundFn\n /** 是否展示帮助入口(帮助按钮与帮助弹框);默认开启,传 false 关闭 */\n showHelp?: boolean\n /**\n * 模板级字体声明(宿主配置):设计器据此注入 @font-face、在字体下拉中列出,\n * 并在保存/预览/截图时同步写入模板 JSON,供服务端与客户端出图使用同一份字体。\n */\n fonts?: readonly PrintFontDeclaration[]\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, tilingEnabled,\n selectedIds, selectedElement, selectedElements, select, selectElement, 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 pages, activePageIndex, switchPage, addPage, duplicatePage, deletePage, renamePage, movePage,\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\n// 任一选中元素带组即显示「取消组合」:点选组成员会整组扩展为多选,首个元素未必含组\nconst selectedHasGroup = computed(() => selectedElements.value.some(e => !!e.options.groupId))\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))\nprovide(UPLOAD_DESIGN_BACKGROUND_KEY, computed(() => props.uploadDesignBackground))\n\nconst { catalog: fontCatalog } = useFontCatalog(computed(() => props.fonts))\nprovide(FONT_CATALOG_KEY, fontCatalog)\n\n/** 画布文档注入同一份 @font-face,保证设计期所见即出图所得 */\nuseDocumentFontFace(computed(() => buildFontFaceCss(props.fonts)))\n\n/**\n * 保存/预览/截图统一取这一份:把 prop 配置的字体同步写进模板 JSON,\n * 渲染端(服务端 / 客户端 / 浏览器)只认模板里的声明。宿主未配置时保留模板自带声明。\n */\nfunction templateJsonWithFonts(): TemplateData | MultiPageTemplateData {\n const json = getTemplateJson()\n if (!props.fonts?.length) return json\n if (Array.isArray((json as MultiPageTemplateData).pages)) {\n return { ...(json as MultiPageTemplateData), pages: (json as MultiPageTemplateData).pages.map(p => ({ ...p, fonts: [...props.fonts!] })) }\n }\n return { ...(json as TemplateData), fonts: [...props.fonts] }\n}\n\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 = templateJsonWithFonts()\n if (!templateJson) {\n alert('模板数据为空')\n return\n }\n if (!props.requestScreenshot) {\n alert('截图服务未配置')\n return\n }\n try {\n // 叠层对比针对当前激活页生成截图:多页模板取 activePage 单页模板\n const mp = templateJson as MultiPageTemplateData\n const activeTemplate: TemplateData = Array.isArray(mp.pages)\n ? mp.pages[activePageIndex.value]!\n : (templateJson as TemplateData)\n const blob = await props.requestScreenshot({ templateJson: activeTemplate, 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 const name = PAPER_PRESETS[t.paperSize]?.label ?? t.paperSize\n const base = `${name} ${orient} ${Math.round(dim.width)}×${Math.round(dim.height)}mm`\n // 出纸旋转角度非 0 时,状态栏明确提示(设计稿内容不旋转,仅整页内容旋转出纸)\n const rot = t.outputRotation\n if (rot) {\n return `${base}(旋转${rot}°)`\n }\n return base\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/**\n * 工具栏放大/缩小按钮:委托 CanvasArea.zoomByStep,\n * 与滚轮缩放共用乘性步进与锚点校正(以视口中心为不动点),\n * 避免直接改 scale 导致画面相对滚动位置漂移。\n * @param delta 工具栏固定传 ±10,仅用于判定放大/缩小方向\n */\nfunction onToolbarZoom(delta: number) {\n canvasAreaRef.value?.zoomByStep(delta > 0 ? 1 : -1)\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\n// 普通点击走分组感知:点组内成员选中整组;Ctrl/⌘ 多选按单元素切换\nconst onSelectElement = selectElement\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\n/**\n * 拼版配置校验(仅开启拼版时生效):列数超宽等非法配置不允许保存。\n * 输入过程只预警不阻断,真正的闸门在这里与 handleSave 上。\n */\nconst tilingIssues = computed(() => {\n const t = templateData.value\n if (t?.tiling?.enabled !== true) return []\n return validateTiling(t)\n})\n\ndefineExpose({\n getTemplateJson: templateJsonWithFonts,\n /**\n * 模板校验入口:`getTemplateJson()` 是绕过 handleSave 的旁路,\n * 宿主在导出/另存链路需自行调用本方法拦截非法配置。\n */\n validateTemplate: () => tilingIssues.value,\n})\n\nfunction handleSave() {\n // 非法拼版配置:给出原因并把用户带到「页面属性」页签,不落盘\n const issues = tilingIssues.value\n if (issues.length) {\n alert(issues[0].message)\n activePropertyTab.value = 'page'\n return\n }\n const json = templateJsonWithFonts()\n // 多页模板:保存前做归一化校验(纸张尺寸一致、禁连续纸/拼版),非法则阻断\n if (Array.isArray((json as MultiPageTemplateData).pages)) {\n try { normalizeTemplate(json as PrintTemplateData | PrintMultiPageTemplateData) } catch (e) { alert(e instanceof Error ? e.message : String(e)); return }\n }\n emit('save', JSON.stringify(json))\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","<!--\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 '@worm-vue3-print/core/browser'\nimport { browserCodeRenderer } from '@worm-vue3-print/core/browser'\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 * 相对路径字体基址。缺省不拼接:预览 iframe 与设计器同源,\n * 相对字体 URL 由页面 origin 解析,与画布注入 @font-face 的行为一致。\n * 字体与页面不同源时(如字体放 CDN)传绝对基址。\n */\n fontBaseUrl?: string\n}>()\n\nconst emit = defineEmits<{\n /** 渲染完成,回传总页数与份数(对象数据=1,数组=数组长度) */\n rendered: [pageCount: number, copies: 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, copies } = await renderHtmlPages(\n props.templateJson as PrintTemplateData,\n props.printData,\n props.baseUrl,\n browserCodeRenderer,\n { fontBaseUrl: props.fontBaseUrl },\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, copies)\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, props.fontBaseUrl],\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":["SELECTED_IDS_KEY","PREVIEW_IDS_KEY","useSelection","elements","selectedIds","ref","previewIds","selectedElements","computed","e","hasSelection","select","id","multiple","s","clearSelection","selectAll","allIds","setPreview","ids","clearPreview","commitPreview","getSelectionBounds","els","minL","minT","maxR","maxB","useClipboard","clipboard","copy","paste","offset","groupCounts","item","gid","groupIdMap","count","generateGroupId","generateId","hasData","useHistory","options","undoStack","redoStack","canUndo","canRedo","updateFlags","clone","state","cloned","cloneState","push","undo","currentState","popped","redo","clear","TILING_SINGLE_PAGE_TIP","createDefaultTemplate","toRuntimePool","data","mk","zone","syncTableElementSize","resolveInitialPages","initial","withDefaultName","p","i","rt","normalizeTemplateUnits","list","serializePage","page","all","ser","useDesignerState","scale","showRuler","showGrid","snapToGrid","showTableGhostBorder","pages","activePageIndex","templateData","tilingEnabled","blockPageAddIfTiling","flushActivePage","switchPage","resetPageSelection","fields","selectAllIds","groupElements","ungroupElements","getGroupedIds","useGroup","copyElements","pasteElements","hasClipboardData","align","useAlign","pushHistory","undoHistory","redoHistory","selectedElement","tableSelection","setTableSelection","getHistoryState","recordHistory","historyActiveElements","cutSelected","deleteSelected","pasted","duplicateSelected","resetZoom","hasClipboard","moveSessionActive","moveDebounceTimer","MOVE_SESSION_GAP_MS","moveSelected","dx","dy","movable","alignSelected","mode","selectElement","groupSelected","ungroupSelected","setupKeyboard","cleanupKeyboard","useKeyboard","draggingBeforeState","dragStart","dragStop","before","rejected","el","prev","finalizeElementZone","sig","beforeIds","afterIds","placeAtDropPoint","dropPoint","zoneFromPaperPoint","ZONE_ALLOWED_TYPES","rect","getZoneRects","clampToZone","addElement","type","createRuntimeElement","addFieldElement","field","createFieldElement","moveLayer","direction","currentZ","allZ","maxZ","minZ","fitToWindow","containerW","containerH","width","height","getPaperDimensions","MM_TO_PX","computeFitScale","updateTemplateData","paper","getTemplateJson","loadTemplate","nextDefaultPageName","used","n","addPage","base","np","duplicatePage","src","cp","deletePage","renamePage","name","movePage","from","to","moved","onMounted","onUnmounted","guideSeq","genId","useGuides","guides","mutate","fn","addGuide","position","moveGuide","g","removeGuide","getGuidePositions","v","h","TABLE_EDIT_KEY","UPLOAD_IMAGE_KEY","UPLOAD_DESIGN_BACKGROUND_KEY","FONT_CATALOG_KEY","EMPTY_FONT_CATALOG","useFontCatalog","declarations","out","seen","font","toValue","family","key","label","useInjectedFontCatalog","inject","findFontOption","fonts","f","fontOptionLabel","option","normalizeFontQuery","value","matchRank","nameKey","queryKey","cursor","char","filterFontOptions","query","index","fontMatchRank","a","b","byFamily","byLabel","STYLE_ID_PREFIX","useDocumentFontFace","css","styleId","useId","watchEffect","text","_createElementBlock","$emit","_createElementVNode","_useModel","__props","_openBlock","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","_toDisplayString","_cache","_hoisted_5","_createVNode","_unref","Undo2","Redo2","_hoisted_8","AlignStartVertical","AlignEndVertical","AlignStartHorizontal","AlignEndHorizontal","AlignCenterVertical","AlignCenterHorizontal","AlignHorizontalSpaceBetween","AlignVerticalSpaceBetween","_hoisted_9","GroupIcon","UngroupIcon","_hoisted_10","ArrowUpToLine","ArrowUp","ArrowDown","ArrowDownToLine","_hoisted_11","_normalizeClass","Maximize","ZoomOut","_hoisted_12","ZoomIn","_hoisted_13","HelpButton","_hoisted_14","_hoisted_15","props","canGroup","canUngroup","sortedLayers","elementIconMap","layerIcon","layerName","zoneTag","_Fragment","_renderList","layer","$event","_hoisted_6","_hoisted_7","emit","__emit","searchText","collapsedGroups","searching","filteredGroups","filterGroups","groupFields","toggleGroup","next","onDragStart","event","group","_normalizeStyle","activeTab","elementTypes","onFieldDrag","expandTab","tab","_withDirectives","FieldTreePanel","LayerPanel","m","d","useDrag","target","isDragging","dragPreview","startX","startY","startLeft","startTop","downAltKey","onMouseDown","targetEl","onMouseMove","onMouseUp","computePos","newLeft","newTop","w","result","pos","cleanup","setup","fitTargets","root","targets","node","restoreFitted","useShrinkFit","trigger","apply","fitTextNode","nextTick","V_ALIGN_FLEX","H_ALIGN_FLEX","rootRef","fit","resolveElementTextFit","baseFontSize","fitMinPt","resolveShrinkMinFontSize","textStyle","o","autoHeight","displayText","resolveTextBinding","imageSrc","raw","evaluateTemplate","DEFAULT_DEMO_DATA","hasError","onError","watch","imgStyle","ROW_TYPES","emitAction","payload","_createBlock","_Teleport","t","barcodeSvg","svgOk","dataUrl","size","FIT_TO_PAR","par","svgStyle","renderBarcode","unitPerModule","barcodeUnitsPerModule","JsBarcode","BARCODE_BAR_HEIGHT_MODULES","BARCODE_TEXT_FONT_SIZE_MODULES","BARCODE_QUIET_ZONE_MODULES","BARCODE_MARGIN_BOTTOM_MODULES","viewBox","readViewBox","settled","resolveBarcodeSize","barcodeAvailableBoxMm","svg","parts","renderQrcode","QRCode","render","_vShow","PX_PER_MM","HEIGHT_EPSILON_MM","ROW_TYPE_BADGE","editCtx","rows","colWidths","defaultFontSize","defaultColor","selection","rowTopMm","ri","tableRef","rowLayoutMm","measureTable","table","tableHpx","tableHmm","baseTop","tr","badgeTopMm","badgeHeightMm","demoList","ds","imageData","isCodeCell","cell","cellDisplay","_row","resolveBarcodeDesignValue","cellStyle","borderOpts","resolveCellBorderCss","cellTextFit","resolveCellTextFit","needsFitBox","cellBaseFontSize","cellCapMm","cellFitCapMm","cellBoxWidthMm","ci","cellFitWidthMm","cellFitStyle","row","c","cellClass","dragAnchor","applySelection","normalizeSelection","onCellMouseDown","r","onCellMouseEnter","onCellDblClick","menu","reactive","onCellContextMenu","mergeReason","canMergeReason","canSplit","rowTypeReason","setRowType","syncElementSize","checkColWidthLimit","cw","maxW","totalW","onMenuAction","rs","err","insertRow","deleteRow","insertCol","deleteCol","mergeCells","splitCells","colResizeEnabled","colResizeBoundaries","_","k","colBoundaryLeftMm","colResizeBoundary","resizeStartX","resizeStartWidth","onColResizeStart","onColResizeMove","onColResizeEnd","deltaMm","colIndex","widths","clampResizedColumnWidth","_withModifiers","CellBarcode","CellImage","TableContextMenu","isHline","lineStyle","bw","bs","bc","isOval","shapeStyle","svgRef","preserveAspectRatio","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","mmToPx","info","finalDx","finalDy","sibling","left","top","setupDrag","cleanupDrag","resizeEnabled","startResize","cleanupResize","useResize","onDblClick","onDblClickCell","elementId","_resolveDynamicComponent","_mergeProps","RESIZE_POINTS","useAdsorb","config","guideLines","paperSize","check","movingRect","others","computeAdsorb","renderLines","lines","paperW","paperH","clearLines","useAdsorbManager","requestAdsorb","clearGuides","contentRef","paperWidthMM","paperHeightMM","designBackground","backgroundLoadFailed","normalizedBackgroundRotation","designBackgroundStyle","rotation","swapped","layerW","layerH","style","onBackgroundError","guideHitPx","wrapperStyle","widthPx","heightPx","zoneRectsMM","headerH","footerH","contentW","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","watermarkLayout","resolveWatermarkLayout","zoneResizing","startZoneResize","cleanupZoneResize","onZoneResizeMove","onZoneResizeUp","startH","dyMM","maxH","onSelectElement","__expose","tile","idx","BaseElement","line","horizontal","guideType","canvasRef","hoverPx","effectiveCursorPx","cssSize","RULER_THICKNESS","rafId","scheduleDraw","draw","canvas","ctx","dpr","length","thickness","bg","fg","accent","pxPerMM","startMM","endMM","majorStep","chooseMajorStepMM","ticks","buildRulerTicks","drawTicks","drawPaperEdge","x","y","outside","tick","len","mm","color","onBeforeUnmount","dragging","axialFromEvent","along","onDown","onWinMove","onWinUp","updateDragPreview","onHoverMove","onHoverLeave","rulerGeom","rulerCursor","scrollPos","overlayStyle","measureRuler","area","ar","pr","targetScale","measuredScale","onScroll","resizeObserver","scaleMeasureRaf","startScaleMeasureLoop","endAt","loop","guidePreview","onGuideDragging","guidePreviewStyle","liveScale","toPaperPoint","pxToMm","onDrop","fieldData","elementType","marquee","marqueeStart","isCanvasBackground","areaRect","xMm","yMm","onMouseLeave","applyZoom","targetPercent","anchorX","anchorY","minPercent","container","cur","oldScale","ratio","cs","padX","padY","ax","ay","cs2","padX2","padY2","onWheel","oldPercent","newPercent","nextWheelScale","MIN_SCALE_PERCENT","zoomByStep","prevTransition","FIT_SCALE_MIN_PERCENT","onCanvasMouseDown","onMarqueeMove","onMarqueeUp","hitTestIds","paperRect","containMode","elLeft","elTop","elRight","elBottom","inter","contained","contextMenu","contextMenuRef","onContextMenu","elId","gap","closeContextMenu","handlePaste","handleSelectAll","handleClearSelection","action","arg","centerScroll","stableFrames","prevSW","prevSH","deadline","sw","sh","sw2","sh2","ch","CanvasPaper","Ruler","onSearch","isExpanded","iconChar","toggle","saveState","loadState","saved","_renderSlot","_ctx","precision","dot","roundTo","current","draft","atMin","atMax","clamp","stepBy","dir","onInput","commit","num","_withKeys","showItem","PropertyGroup","StepperInput","visible","triggerRef","panelRef","areaRef","panelStyle","hue","saturation","hexInput","areaDragging","normalizedValue","swatchStyle","activeColor","rgbToHex","hsvToRgb","hueModel","degree","setHsv","clampDegree","syncFromColor","selectNone","onHexInput","parseHex","normalizeHex","rgb","hsv","rgbToHsv","clamp01","startAreaDrag","setAreaFromEvent","moveAreaDrag","endAreaDrag","onAreaKeydown","step","handled","close","open","panelWidth","panelHeight","margin","below","onDocumentPointerDown","onWindowCloseEvents","onKeydown","match","hex","full","part","red","green","blue","max","min","hh","r1","g1","b1","number","PRESET_COLORS","catalog","listId","listRef","toDisplayName","highlighted","unknownFamily","make","kind","typed","matched","resolveTypedFamily","activeRowId","currentRowIndex","onOpen","onClick","move","last","scrollActiveIntoView","onEnter","pick","onCancel","isTableType","textFit","onTextFitChange","FontSelect","PresetColorPicker","_hoisted_16","_hoisted_17","_hoisted_18","_hoisted_19","_hoisted_21","_hoisted_22","_hoisted_24","isBarcode","isQrcode","barcodeType","dpiValue","hasPrinterDpi","dotAligned","onDpiChange","emitChange","onBarcodeTypeChange","onFitChange","val","searchPlaceholder","localExpression","handleFieldDoubleClick","insideParens","getCursorRegion","insertAtCursor","handleVariableDoubleClick","sv","handleFunctionDoubleClick","insideBlock","caretOffset","start","textareaRef","lastBlockOpen","lastParenOpen","filteredSystemVars","systemVars","keyword","filteredAggregateFuncs","aggregateFunctions","filteredMathFuncs","mathFunctions","filteredFormatFuncs","formatFunctions","previewResult","resolveSystemVariables","ta","end","after","caretPos","onConfirm","_hoisted_20","_hoisted_23","_hoisted_25","_hoisted_27","_hoisted_28","_hoisted_29","_hoisted_30","_hoisted_32","_hoisted_33","_hoisted_34","_hoisted_35","_hoisted_36","_hoisted_37","_hoisted_38","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","setHeaderRepeat","mainCell","findMainCell","formatterEditorVisible","pendingFormatterValue","isBarcodeCell","isQrcodeCell","isImageCell","isTextCell","write","onAlignChange","onValignChange","onPrinterDpiChange","dpi","onCellTypeChange","openFormatterEditor","onFormatterEditorConfirm","borderStyle","borderWidth","borderColor","edgeChecks","currentBorder","preset","applyBorderPreset","onEdgesChange","edges","nb","side","doMerge","doSplit","_hoisted_26","_hoisted_31","_hoisted_39","_hoisted_40","_hoisted_42","_hoisted_44","_hoisted_46","_hoisted_47","_hoisted_48","_hoisted_49","_hoisted_51","_hoisted_52","_hoisted_53","_hoisted_54","_hoisted_55","_hoisted_56","_hoisted_57","_hoisted_58","_hoisted_59","_hoisted_60","_hoisted_61","_hoisted_62","_hoisted_64","_hoisted_66","_hoisted_67","_hoisted_68","_hoisted_69","densityPresets","WATERMARK_DENSITY_PRESETS","minTileWidth","WATERMARK_DEFAULTS","minTileHeight","isExpressionText","readText","expressionText","testData","exprEditorVisible","activeMode","localConfig","isExpression","density","tileWidth","tileHeight","onTextChanged","onChange","onTextInput","openExpressionEditor","onExpressionChange","onColorChange","uploadDesignBackground","onFileChange","onRotate","onRemove","_createTextVNode","sheetPresetKeys","PAPER_PRESETS","labelContinuous","isContinuousPaperSize","cfg","TILE_DEFAULTS","tilingTemplate","issues","validateTiling","columnMax","computeMaxColumns","layout","computeTileLayout","summary","l","resolveSheetMm","patch","partial","patchMargin","onSheetPaperChange","onEnabledChange","columns","issue","paperPresetGroups","groups","bucket","isTextType","isImageType","isCodeType","isTableCellSelected","searchResult","searchProperties","matchedKeys","bindingDescriptors","c1","listField","getTableCellBindings","getElementBindings","parsePath","targetPath","segment","baseName","indices","getBindingValue","seg","setBindingValue","segments","lastKey","obj","onImageUploadSuccess","paperSizeModel","continuousPaper","labelPaper","isLabelPaperSize","orientationModel","outputRotationModel","pageBackgroundModel","onPageBackgroundChange","marginTop","marginBottom","marginLeft","marginRight","headerHeight","footerHeight","overlayHeight","customWidth","customHeight","designBackgroundModel","onDesignBackgroundChange","rest","emitUpdate","watermarkModel","onWatermarkChange","onPaperSizeChange","labelPaperDefaults","onOrientationChange","onOutputRotationChange","onPageBackgroundReset","onCustomWidthChange","onCustomHeightChange","onMarginTopChange","onMarginBottomChange","onMarginLeftChange","onMarginRightChange","onHeaderHeightChange","onFooterHeightChange","onOverlayHeightChange","currentTab","PropertySearch","PositionSizeGroup","AppearanceGroup","CodeGroup","desc","BindingControl","ImageContentUpload","TableRowGroup","TableCellGroup","TableSettingsGroup","BorderBgGroup","PaginationGroup","AdvancedGroup","DesignBackgroundConfig","TilingConfig","_hoisted_41","_hoisted_43","WatermarkConfig","gettingStarted","features","shortcuts","faq","changelog","helpSections","STORAGE_KEY","sections","switchTab","tabId","currentContent","handleKeydown","_Transition","section","editingIndex","renameText","activeName","addTip","duplicateTip","startRename","commitRename","cancelRename","tip","tipTimer","showTipFor","onTipOver","onTipOut","hideTip","LEFT_KEY","RIGHT_KEY","readStored","fallback","useStudioChrome","leftCollapsed","rightCollapsed","dirty","toggleLeft","toggleRight","markSaved","helpVisible","onUndo","onRedo","onAlign","onGroup","onUngroup","onDeleteElement","onDragStop","onDropElement","onDropField","onMoveLayer","selectedHasGroup","maxTableWidth","provide","fontCatalog","buildFontFaceCss","templateJsonWithFonts","json","canvasAreaRef","overlayVisible","screenshotUrl","overlayOpacity","toggleOverlay","templateJson","mp","activeTemplate","blob","coordinate","onCoordinate","paperLabel","dim","orient","rot","onFitWindow","onZoom","onToolbarZoom","onKeyFitWindow","tag","onTemplateDataChanged","prevHeader","prevFooter","onZoneHeightChange","onZoneHeightCommit","warnZoneOverflow","onAddOverlayElement","overlay","newEl","onToggleVisible","onToggleLocked","activePropertyTab","DBL_EDITABLE_FIELD","dblEditorVisible","dblEditTarget","dblEditorExpression","onDblClickElement","main","onDblEditorConfirm","onCloneElement","_pos","tilingIssues","handleSave","normalizeTemplate","DesignerToolbar","PageTabs","LeftPanel","CanvasArea","PropertyPanel","StatusBar","HelpModal","iframeRef","rendering","errorMsg","renderSeq","rerender","seq","html","pageCount","copies","renderHtmlPages","browserCodeRenderer","doc","print","win"],"mappings":"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AAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgIX,GCnIAC,KAAe;AAAA,EACb,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAA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"}
|