<script lang="ts" setup>
|
import { nextTick, reactive, ref, toRefs, unref, watch } from 'vue';
|
|
import { BasicModal, useModalInner } from '@jnpf/ui/modal';
|
import { JnpfUniver, JnpfUniverPrint } from '@jnpf/univer';
|
|
import { usePreferences } from '@vben/preferences';
|
|
import { useDebounceFn } from '@vueuse/core';
|
|
import logoImg from '#/assets/images/jnpf.png';
|
import { $t } from '#/locales';
|
|
import ConfigForm from './ConfigForm.vue';
|
|
defineOptions({ name: 'ReportPrint' });
|
|
interface State {
|
reportData: any;
|
formState: any;
|
jnpfUniverAPI: any;
|
configOptions: any;
|
sheetsOption: any;
|
loading: boolean;
|
printRenderTip: string;
|
configLoading: boolean;
|
internalOpen: boolean;
|
activeSheetFreeze: any;
|
watermarkCache: any;
|
}
|
const [registerModal, { closeModal }] = useModalInner(init);
|
const defaultRenderProgressTip = ' '; // 默认的加载文案
|
|
const state = reactive<State>({
|
reportData: {},
|
jnpfUniverAPI: null,
|
formState: {},
|
configOptions: {},
|
sheetsOption: [],
|
loading: false,
|
printRenderTip: defaultRenderProgressTip,
|
configLoading: false,
|
internalOpen: false,
|
activeSheetFreeze: {},
|
watermarkCache: {},
|
});
|
const { jnpfUniverAPI, formState, configOptions, sheetsOption, loading, printRenderTip, configLoading, internalOpen, activeSheetFreeze } = toRefs(state);
|
const { isDark } = usePreferences();
|
const jnpfUniverRef = ref();
|
const jnpfUniverPrintRef = ref();
|
const printConfigFormRef = ref();
|
|
const debounceHandlePrintConfig = useDebounceFn(() => {
|
handleChangePrintConfig(state.formState);
|
}, 300);
|
|
watch(
|
() => state.formState,
|
() => {
|
state.loading = true;
|
debounceHandlePrintConfig();
|
},
|
{ deep: true },
|
);
|
|
async function init(data) {
|
state.reportData = data;
|
state.loading = true;
|
state.internalOpen = true;
|
state.configLoading = true;
|
state.printRenderTip = defaultRenderProgressTip;
|
state.watermarkCache = { ...data.watermark };
|
|
const { snapshot, sheetId } = data ?? {};
|
state.activeSheetFreeze = snapshot?.sheets?.[sheetId]?.freeze ?? {};
|
|
handleCreate(data.snapshot);
|
}
|
// 创建报表实例
|
function handleCreate(snapshot) {
|
const defaultActiveSheetId = state.reportData.sheetId ?? null;
|
|
nextTick(() => {
|
const res = unref(jnpfUniverRef)?.handleCreateDesignUnit({
|
mode: 'print',
|
snapshot,
|
loading: false,
|
defaultActiveSheetId,
|
darkMode: isDark.value,
|
});
|
state.jnpfUniverAPI = res ? res?.jnpfUniverAPI : null;
|
|
state.jnpfUniverAPI?.getHooks()?.onSteady(() => {
|
const sheetsInfo = unref(jnpfUniverRef).getSheetsInfo() ?? {};
|
const partSheets: any = [];
|
state.sheetsOption = Object.values(sheetsInfo).map((item: any) => {
|
partSheets.push(item.id);
|
|
return {
|
id: item.id,
|
fullName: item.name,
|
};
|
});
|
|
const configOptions = unref(jnpfUniverRef).getPrintConfigs() ?? {};
|
configOptions.defaultConfigForm.partSheets = partSheets;
|
state.configOptions = configOptions;
|
|
state.formState = { ...state.configOptions.defaultConfigForm, workbookTitleText: state.reportData.fullName };
|
state.configLoading = false;
|
|
nextTick(() => {
|
unref(printConfigFormRef).handleChangedPrintAreaType();
|
});
|
});
|
});
|
}
|
// 销毁示例
|
function handleDisposeUnit() {
|
unref(jnpfUniverRef)?.handleDisposeUnit();
|
state.jnpfUniverAPI = null;
|
}
|
function handleCancel() {
|
handleDisposeUnit();
|
|
setTimeout(() => {
|
closeModal();
|
}, 500);
|
}
|
// 打印
|
function handlePrint() {
|
unref(jnpfUniverPrintRef)?.handleBrowserPrint();
|
}
|
function handleChangePrintConfig(config: any) {
|
state.printRenderTip = defaultRenderProgressTip;
|
|
if (state.jnpfUniverAPI) {
|
unref(jnpfUniverPrintRef)?.handlePrintRender(config, state.watermarkCache);
|
}
|
}
|
// 获取打印预览渲染进度
|
function getPreviewRenderProgress(res: any) {
|
const { total, rendered } = res ?? {};
|
|
if (total >= 10) state.printRenderTip = `共${total}页,已加载${rendered}页`;
|
if (rendered === total) {
|
state.loading = false;
|
|
/**
|
* 下面的内容主要是为了实现打印全部工作表
|
* 必须如此处理,不然打印所有工作表会出现缺失
|
*/
|
// 获取工作簿id
|
const activeWorkbook = state.jnpfUniverAPI?.getActiveWorkbook();
|
|
// 获取到所有的工作表
|
const sheets = activeWorkbook.save().sheets;
|
const sheetKeys = Object.keys(sheets);
|
const activeSubUnitId = activeWorkbook?.getActiveSheet()?.getSheetId();
|
|
// 自动缓存所有页签
|
function autoRenderAllSheets(index: number) {
|
if (index >= sheetKeys?.length) {
|
// 切换到最初激活的工作表
|
unref(jnpfUniverRef)?.setWorksheetActiveOperation(activeSubUnitId);
|
return;
|
}
|
|
const sheetKey = sheetKeys[index];
|
|
unref(jnpfUniverRef)?.setWorksheetActiveOperation(sheetKey);
|
|
setTimeout(() => {
|
autoRenderAllSheets(index + 1);
|
}, 100); // 加延迟才能切换命令执行无效
|
}
|
|
autoRenderAllSheets(0);
|
}
|
}
|
// 获取打印浏览器渲染进度
|
function getPrintRenderProgress(res: any) {
|
const { total, rendered } = res ?? {};
|
|
if (total >= 10) {
|
state.printRenderTip = `共${total}页,已准备${rendered}页`;
|
if (rendered === total) state.printRenderTip = '整理中...';
|
}
|
}
|
// 打印准备好了
|
function handleBrowserShow() {
|
state.loading = false;
|
}
|
async function handleClose() {
|
state.internalOpen = false;
|
return true;
|
}
|
</script>
|
|
<template>
|
<BasicModal
|
v-bind="$attrs"
|
@register="registerModal"
|
default-fullscreen
|
:footer="null"
|
:closable="false"
|
:keyboard="false"
|
:close-func="handleClose"
|
destroy-on-close
|
class="jnpf-full-modal full-modal designer-modal jnpf-report-print-modal">
|
<template #title>
|
<div class="jnpf-full-modal-header">
|
<div class="header-title">
|
<img :src="logoImg" class="header-logo" />
|
<span class="header-dot"></span>
|
<p class="header-txt">报表打印预览</p>
|
</div>
|
<a-space class="options" :size="10">
|
<a-button type="primary" :disabled="loading" @click="handlePrint()">{{ $t('common.printText') }}</a-button>
|
<a-button @click="handleCancel()">{{ $t('common.cancelText') }}</a-button>
|
</a-space>
|
</div>
|
</template>
|
<div class="print-container" v-loading="loading" :loading-tip="printRenderTip">
|
<div class="print-design-content">
|
<JnpfUniver v-if="internalOpen" ref="jnpfUniverRef" />
|
</div>
|
<div class="print-main-container">
|
<div class="main-warp">
|
<JnpfUniverPrint
|
ref="jnpfUniverPrintRef"
|
:jnpf-univer-api="jnpfUniverAPI"
|
@preview-render-progress="getPreviewRenderProgress"
|
@print-render-progress="getPrintRenderProgress"
|
@browser-print-show="handleBrowserShow" />
|
</div>
|
<div class="config-warp">
|
<ConfigForm
|
ref="printConfigFormRef"
|
v-if="!configLoading"
|
:form-state="formState"
|
:config-options="configOptions"
|
:sheets-option="sheetsOption"
|
:active-sheet-freeze="activeSheetFreeze" />
|
</div>
|
</div>
|
</div>
|
</BasicModal>
|
</template>
|
|
<style lang="scss">
|
.jnpf-full-modal.jnpf-report-print-modal {
|
.ant-modal-body > .scrollbar {
|
padding: 0 !important;
|
}
|
|
.print-container {
|
position: relative;
|
z-index: 1000;
|
flex: 1;
|
height: 100%;
|
|
.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;
|
|
.main-warp {
|
display: flex;
|
flex: 1 0 0;
|
height: 100%;
|
overflow: auto;
|
}
|
|
.config-warp {
|
flex: 270px 0 0;
|
min-width: 270px;
|
overflow: hidden auto;
|
|
.ant-radio-button-wrapper {
|
padding: 0 11px;
|
}
|
}
|
}
|
}
|
}
|
</style>
|