<script lang="ts" setup>
|
import { nextTick, reactive, ref, toRefs, unref } from 'vue';
|
|
import { IWorkbookData } from '@univerjs/core';
|
import { SetWorksheetActiveOperation } from '@univerjs/sheets';
|
import { Button as AButton, Modal as AModal } from 'ant-design-vue';
|
|
import JnpfUniverDesign from '../Design/index.vue';
|
import { DefaultPrintConfig } from '../Design/univer/utils/define';
|
import JnpfUniverPrintForm from './Form/index.vue';
|
import JnpfUniverPrintRender from './Render/index.vue';
|
|
const jnpfUniverDesignPrintRef = ref();
|
const jnpfUniverPrintRenderRef = ref();
|
|
// 默认数据
|
const defaultRenderProgressTip = ' '; // 加载文案
|
const defaultFreezeStatus = {
|
colHasFreeze: false,
|
// 是否存在冻结项
|
rowHasFreeze: false,
|
};
|
|
interface State {
|
internalOpen: boolean;
|
|
jnpfUniverAPI: any;
|
loading: boolean;
|
|
printRenderTip: string;
|
|
sheetFreezeStatus: any;
|
}
|
const state = reactive<State>({
|
internalOpen: false,
|
|
jnpfUniverAPI: null,
|
loading: false,
|
|
printRenderTip: defaultRenderProgressTip,
|
|
sheetFreezeStatus: { ...defaultFreezeStatus },
|
});
|
const { internalOpen, jnpfUniverAPI, loading, printRenderTip, sheetFreezeStatus } = toRefs(state);
|
|
// 创建打印实例
|
function handleCreatePrintUnit(data: { defaultActiveSheetId?: string; snapshot: IWorkbookData }) {
|
state.internalOpen = true;
|
|
state.printRenderTip = defaultRenderProgressTip;
|
state.loading = true;
|
|
const { defaultActiveSheetId, snapshot } = data ?? {};
|
|
nextTick(() => {
|
const { jnpfUniverAPI: jnpfUniverAPICache } = unref(jnpfUniverDesignPrintRef)?.handleCreateDesignUnit({
|
defaultActiveSheetId,
|
loading: false,
|
mode: 'print',
|
snapshot,
|
});
|
state.jnpfUniverAPI = jnpfUniverAPICache ?? null;
|
|
// ??? 这个生命周期待测试,看能不能提前
|
jnpfUniverAPI.value?.getHooks()?.onSteady(() => {
|
// 获取激活的工作表id
|
const subUnitId = defaultActiveSheetId ?? jnpfUniverAPI.value?.getActiveWorkbook()?.getActiveSheet()?.getSheetId();
|
|
// 判断行列的冻结状态
|
const { xSplit = 0, ySplit = 0 } = snapshot?.sheets?.[subUnitId]?.freeze ?? {};
|
const colHasFreeze = xSplit > 0; // 列冻结(冻结左侧的列)
|
const rowHasFreeze = ySplit > 0; // 行冻结(冻结上方的行)
|
state.sheetFreezeStatus = {
|
colHasFreeze, // 列冻结
|
rowHasFreeze, // 行冻结
|
};
|
|
console.log('☕️ The underlying univer has been rendered, and the print preview page is being rendered.');
|
unref(jnpfUniverPrintRenderRef)?.handlePrintRender(JSON.parse(JSON.stringify(DefaultPrintConfig)));
|
});
|
});
|
}
|
|
// 变更打印配置
|
function handleChangePrintConfig(config: any) {
|
state.printRenderTip = defaultRenderProgressTip;
|
state.loading = true;
|
|
console.log('✋ You have switched the print configuration.');
|
unref(jnpfUniverPrintRenderRef)?.handlePrintRender(JSON.parse(JSON.stringify(config)));
|
}
|
|
// 获取打印预览渲染进度
|
function getPreviewRenderProgress(res: any) {
|
const { rendered, total } = res ?? {};
|
state.printRenderTip = `共${total}页,已加载${rendered}页`;
|
|
if (rendered === total) {
|
console.log('🎆 The preview page has been fully rendered.');
|
state.loading = false;
|
|
/**
|
* 下面的内容主要是为了实现打印全部工作表
|
* 必须如此处理,不然打印所有工作表会出现缺失
|
*/
|
// 获取工作簿id
|
const activeWorkbook = jnpfUniverAPI.value?.getActiveWorkbook();
|
const unitId = activeWorkbook?.getId();
|
|
// 获取到所有的工作表
|
const sheets = activeWorkbook.save().sheets;
|
const sheetKeys = Object.keys(sheets);
|
const activeSubUnitId = activeWorkbook?.getActiveSheet()?.getSheetId();
|
|
// 自动缓存所有页签
|
function autoRenderAllSheets(index: number) {
|
if (index >= sheetKeys?.length) {
|
// 切换到最初激活的工作表
|
jnpfUniverAPI.value?.executeCommand(SetWorksheetActiveOperation.id, {
|
subUnitId: activeSubUnitId,
|
unitId,
|
});
|
return;
|
}
|
|
const sheetKey = sheetKeys[index];
|
|
jnpfUniverAPI.value?.executeCommand(SetWorksheetActiveOperation.id, {
|
subUnitId: sheetKey,
|
unitId,
|
});
|
|
setTimeout(() => {
|
autoRenderAllSheets(index + 1);
|
}, 100); // 加延迟才能切换命令执行无效
|
}
|
|
autoRenderAllSheets(0);
|
}
|
}
|
|
// 执行浏览器打印
|
function handleBrowserPrint() {
|
state.printRenderTip = defaultRenderProgressTip;
|
state.loading = true;
|
|
unref(jnpfUniverPrintRenderRef)?.handleBrowserPrint();
|
}
|
|
// 获取打印浏览器渲染进度
|
function getPrintRenderProgress(res: any) {
|
const { rendered, total } = res ?? {};
|
|
state.printRenderTip = `共${total}页,已准备${rendered}页`;
|
|
if (rendered === total) {
|
state.printRenderTip = '整理中...';
|
}
|
}
|
|
// 打印准备好了
|
function handleBrowserShow() {
|
state.loading = false;
|
}
|
|
// 关闭弹窗(建议有个时间缓存周期再关闭弹窗,要销毁设计器)
|
function handleCancel() {
|
resetUniverState();
|
unref(jnpfUniverDesignPrintRef)?.handleDisposeUnit();
|
}
|
|
// 重置实例状态
|
function resetUniverState() {
|
state.jnpfUniverAPI = null;
|
state.loading = false;
|
state.printRenderTip = defaultRenderProgressTip;
|
state.sheetFreezeStatus = JSON.parse(JSON.stringify(defaultFreezeStatus));
|
|
unref(jnpfUniverPrintRenderRef)?.resetState();
|
}
|
|
defineExpose({ handleCreatePrintUnit });
|
</script>
|
|
<template>
|
<AModal v-model:open="internalOpen" title="打印预览" width="100%" wrap-class-name="print-full-modal" @cancel="handleCancel">
|
<div class="content-main" v-loading="loading" :loading-tip="printRenderTip">
|
<!-- 测试按钮,随时可以删除掉 -->
|
<div class="buttons-wrap">
|
<AButton type="primary" @click="handleBrowserPrint">浏览器打印</AButton>
|
</div>
|
|
<div class="print-container">
|
<!-- 设计器被隐藏-->
|
<div class="print-design-content">
|
<JnpfUniverDesign v-if="internalOpen" ref="jnpfUniverDesignPrintRef" />
|
</div>
|
|
<div class="print-main-container">
|
<!-- 视图效果-->
|
<JnpfUniverPrintRender
|
ref="jnpfUniverPrintRenderRef"
|
:jnpf-univer-api="jnpfUniverAPI"
|
@preview-render-progress="getPreviewRenderProgress"
|
@print-render-progress="getPrintRenderProgress"
|
@browser-print-show="handleBrowserShow" />
|
|
<!-- 配置表单-->
|
<JnpfUniverPrintForm
|
v-if="internalOpen"
|
:default-print-config="DefaultPrintConfig"
|
:sheet-freeze-status="sheetFreezeStatus"
|
@change="handleChangePrintConfig" />
|
</div>
|
</div>
|
</div>
|
</AModal>
|
</template>
|
|
<style lang="scss">
|
.print-full-modal {
|
.ant-modal {
|
top: 0;
|
max-width: 100%;
|
padding-bottom: 0;
|
margin: 0;
|
}
|
|
.ant-modal-content {
|
display: flex;
|
flex-direction: column;
|
height: calc(100vh);
|
padding: 20px 10px 0;
|
}
|
|
.ant-modal-body {
|
display: flex;
|
flex: 1;
|
|
.content-main {
|
display: flex;
|
flex: 1;
|
flex-direction: column;
|
}
|
|
.print-container {
|
position: relative;
|
flex: 1;
|
|
.print-design-content {
|
position: absolute;
|
inset: 0;
|
z-index: 2;
|
display: flex;
|
|
.jnpf-univer-design-content {
|
opacity: 0;
|
}
|
}
|
|
.print-main-container {
|
position: absolute;
|
inset: 0;
|
z-index: 99;
|
display: flex;
|
overflow: hidden;
|
background: #f2f3f4;
|
}
|
}
|
}
|
|
.ant-modal-footer {
|
display: none;
|
}
|
}
|
</style>
|