新增PrintDot桥接功能,支持本地打印机连接和配置,优化打印模板设计,允许多页表格重复显示,改进打印预览和设计器界面,确保用户体验流畅。

This commit is contained in:
geht
2026-04-17 19:00:30 +08:00
parent 2bd4c5584d
commit efb6a9f838
14 changed files with 1196 additions and 110 deletions

View File

@@ -13,6 +13,7 @@
<a-button @click="sendBackward">下移图层</a-button>
<a-button @click="previewTemplate">即时预览</a-button>
<a-button @click="printTemplate">打印</a-button>
<a-button :loading="printDotLoading" @click="printTemplateViaPrintDot">PrintDot 打印</a-button>
<a-button type="primary" :loading="saving" @click="saveTemplate">保存模板</a-button>
</a-space>
</div>
@@ -135,8 +136,21 @@
<PageConfigModal v-model:open="pageConfigModalOpen" :schema="state.schema" @update-page="updatePage" />
<a-drawer v-model:open="previewVisible" title="即时预览" width="70%" placement="right">
<iframe class="preview-frame" :srcdoc="previewHtml"></iframe>
<a-drawer
v-model:open="previewVisible"
title="即时预览"
width="70%"
placement="right"
:body-style="{ padding: '12px 16px 20px', overflow: 'hidden' }"
>
<div class="native-instant-preview-host">
<iframe
class="preview-frame"
title="原生模板即时预览"
:srcdoc="previewHtml"
:style="{ height: `${previewDrawerIframeHeightPx}px` }"
/>
</div>
</a-drawer>
<FreeTableCellEditModal
@@ -293,6 +307,7 @@
import PropertiesPanel from './components/PropertiesPanel.vue';
import ToolbarPalette from './components/ToolbarPalette.vue';
import { printHtml } from './core/printService';
import { printNativeSchemaViaPrintDot } from '../utils/printNativeViaPrintDot';
import { renderNativePrintHtml, resolvePrintPageCount } from './core/printRenderer';
import { generateNativeMockDataObject } from './core/nativeMockData';
import { buildNativeTemplateStylePayload } from './core/nativeTemplateStyleSerialize';
@@ -328,6 +343,7 @@
} = useDesignerStore();
const templateId = ref('');
const saving = ref(false);
const printDotLoading = ref(false);
const previewVisible = ref(false);
const previewHtml = ref('');
const selectedTableColumn = ref<{ elementId: string; columnKey: string } | null>(null);
@@ -796,6 +812,20 @@
}
});
/** 与列表预览逻辑一致:按 resolvePrintPageCount 估算 iframe 高度,避免多页内容被单页裁切 */
const PREVIEW_MM_TO_CSS_PX = 96 / 25.4;
const previewDrawerIframeHeightPx = computed(() => {
const sch = state?.schema;
const hMm = Number(sch?.page?.heightMm);
if (!sch?.page || !Number.isFinite(hMm) || hMm <= 0) {
return 900;
}
const count = Math.max(1, resolvePrintPageCount(sch, previewData.value));
const gapPx = 12;
const padY = 24 * 2;
return Math.round(count * hMm * PREVIEW_MM_TO_CSS_PX + (count - 1) * gapPx + padY);
});
function generateMockData(options: { syncManual?: boolean; showMessage?: boolean } = {}) {
const { syncManual = false, showMessage = true } = options;
const mock = generateNativeMockDataObject(state.schema.elements, canvasJsonText.value);
@@ -921,6 +951,7 @@
if (payload?.innerBorder && typeof payload.innerBorder === 'object') {
base.innerBorder = { ...payload.innerBorder };
}
base.printRepeated = payload.printRepeated === true;
base.cells = Array.isArray(payload?.cells)
? payload.cells
.map((cell: any) => ({
@@ -1295,6 +1326,22 @@
printHtml(html);
}
async function printTemplateViaPrintDot() {
printDotLoading.value = true;
try {
await printNativeSchemaViaPrintDot({
schema: state.schema,
data: previewData.value,
jobName: String(meta.templateCode || '').trim() || 'native-print',
});
createMessage.success('已通过 PrintDot 提交打印');
} catch (error: any) {
createMessage.error(error?.message || 'PrintDot 打印失败');
} finally {
printDotLoading.value = false;
}
}
function handleDelete() {
removeSelected();
selectedTableColumn.value = null;
@@ -1976,10 +2023,23 @@
border-left: 1px solid #f0f0f0;
}
/* 高度由 :style 绑定 previewDrawerIframeHeightPx避免与多页内容冲突 */
.native-instant-preview-host {
max-height: calc(100vh - 120px);
overflow: auto;
padding: 12px;
box-sizing: border-box;
background: #f0f0f0;
border-radius: 6px;
}
.preview-frame {
display: block;
width: 100%;
height: calc(100vh - 120px);
min-height: 320px;
border: 1px solid #f0f0f0;
background: #fff;
box-sizing: border-box;
}
.image-analyze-modal-title {