<script lang="ts" setup>
|
import { nextTick, reactive, ref, toRefs, unref } from 'vue';
|
|
import { Button as AButton, Modal as AModal } from 'ant-design-vue';
|
|
import { CreateUnitProps } from '../Design/index';
|
import JnpfUniverDesign from '../Design/index.vue';
|
import { useJnpfUniverStore } from '../Design/store';
|
import JnpfUniverCellEchart from '../Design/univer/components/Echart/cell.vue';
|
import JnpfUniverFloatEchartVM from '../Design/univer/components/Echart/floatVM.vue';
|
|
const emits = defineEmits(['print']);
|
|
const jnpfUniverDesignPreviewRef = ref();
|
const jnpfUniverFloatEchartVMRef = ref();
|
const jnpfUniverCellEchartRef = ref();
|
|
const state = reactive<{
|
echartsImageCache: any;
|
internalOpen: boolean;
|
|
jnpfUniverAPI: any;
|
|
jnpfUniverStore: any;
|
}>({
|
echartsImageCache: {},
|
internalOpen: false,
|
|
jnpfUniverAPI: null,
|
|
jnpfUniverStore: null,
|
});
|
const { echartsImageCache, internalOpen, jnpfUniverStore } = toRefs(state);
|
|
// 创建预览实例
|
function handleCreatePreviewUnit(options?: CreateUnitProps) {
|
const { cellEcharts: cellEchartsObject, defaultActiveSheetId, floatEcharts, floatImages, snapshot } = options ?? {};
|
if (snapshot === undefined) {
|
console.warn('预览数据错误');
|
return;
|
}
|
|
state.internalOpen = true;
|
|
const updateSheets = JSON.parse(JSON.stringify(snapshot?.sheets ?? {}));
|
|
nextTick(() => {
|
// 单元格图表数据转成成数组
|
const cellEchartsArray = cellEchartsObjectToArray(cellEchartsObject);
|
|
// 单元格图表转单元格图片
|
cellEchartsArray.forEach(cellEchartOption => {
|
const { colKey, drawingId, height: echartHeight, option: echartOption, rowKey, sheetKey, width: echartWidth } = cellEchartOption;
|
|
const echartImg = unref(jnpfUniverCellEchartRef).render(echartOption, echartWidth, echartHeight);
|
|
try {
|
const targetDrawing = updateSheets?.[sheetKey]?.cellData?.[rowKey]?.[colKey]?.p?.drawings?.[drawingId];
|
|
updateSheets[sheetKey].cellData[rowKey][colKey].p.drawings[drawingId] = {
|
...targetDrawing,
|
source: echartImg,
|
};
|
} catch {
|
console.log('渲染单元格图表失败');
|
}
|
});
|
|
// 将单元格图表的图片更新到快照中
|
snapshot.sheets = JSON.parse(JSON.stringify(updateSheets));
|
|
// 构建univer实例
|
const { jnpfUniverAPI } = unref(jnpfUniverDesignPreviewRef)?.handleCreateDesignUnit({
|
defaultActiveSheetId,
|
floatEcharts,
|
floatImages,
|
loading: true,
|
mode: 'preview',
|
snapshot,
|
uiContextMenu: false,
|
uiHeader: false,
|
workbookReadonly: true,
|
});
|
state.jnpfUniverAPI = jnpfUniverAPI ?? null;
|
|
// 创建悬浮图表的图片
|
createFloatEchartsImage(floatEcharts);
|
});
|
}
|
|
// 打印
|
function handlePrint() {
|
const info = getInstanceInfo();
|
|
emits('print', { ...info });
|
}
|
|
// 导出
|
function handleExport() {
|
const info = getInstanceInfo();
|
|
console.log(info?.snapshot);
|
alert('看控制台的快照');
|
}
|
|
// 关闭弹窗 (建议有个时间缓存周期再关闭弹窗,要销毁设计器)
|
function handleCancel() {
|
unref(jnpfUniverDesignPreviewRef)?.handleDisposeUnit();
|
resetUniverState(); // 重置实例状态
|
}
|
|
// 单元格图表数据转成成数组
|
function cellEchartsObjectToArray(data: any) {
|
const res: any[] = [];
|
for (const sheetKey in data) {
|
const rows = data[sheetKey];
|
|
for (const rowKey in rows) {
|
const cols = rows[rowKey];
|
|
for (const colKey in cols) {
|
const { drawingId, height, option, width } = cols[colKey];
|
|
res.push({
|
colKey,
|
drawingId,
|
height,
|
option,
|
rowKey,
|
sheetKey,
|
width,
|
});
|
}
|
}
|
}
|
|
return res;
|
}
|
|
// 创建悬浮图表的图片信息
|
function createFloatEchartsImage(echarts: any) {
|
const dynamicJnpfUniverStoreId = unref(jnpfUniverDesignPreviewRef)?.getDynamicStoreId();
|
if (!dynamicJnpfUniverStoreId) {
|
return;
|
}
|
|
const jnpfUniverStore = useJnpfUniverStore(dynamicJnpfUniverStoreId);
|
state.jnpfUniverStore = jnpfUniverStore; // 先赋值给 state
|
|
const caches = { ...unref(jnpfUniverStore.floatEchartToUniverImgDataCaches) };
|
|
for (const sheetKey in echarts) {
|
const target = echarts[sheetKey];
|
|
const { domId, height, option, width } = target;
|
|
const res = unref(jnpfUniverFloatEchartVMRef).render(domId, option, width, height);
|
caches[res.domId] = res?.source ?? {};
|
|
Object.assign(state.echartsImageCache, caches); // 直接修改原对象,保持响应性
|
}
|
}
|
|
// 获取实例数据
|
function getInstanceInfo() {
|
jnpfUniverStore.value?.setFloatEchartToUniverImgDataCaches(echartsImageCache.value);
|
|
const { snapshot } = unref(jnpfUniverDesignPreviewRef)?.getPreviewWorkbookData();
|
const defaultActiveSheetId = unref(jnpfUniverDesignPreviewRef)?.getActiveWorksheetId();
|
|
return {
|
defaultActiveSheetId,
|
snapshot,
|
};
|
}
|
|
// 重置实例状态
|
function resetUniverState() {
|
state.jnpfUniverAPI = null;
|
state.jnpfUniverStore = null;
|
|
state.echartsImageCache = {};
|
}
|
|
defineExpose({ handleCreatePreviewUnit });
|
</script>
|
|
<template>
|
<AModal v-model:open="internalOpen" title="设计预览" width="100%" wrap-class-name="preview-full-modal" @cancel="handleCancel">
|
<!-- 测试按钮,随时可以删除掉 -->
|
<div class="buttons-wrap">
|
<AButton type="primary" @click="handlePrint">打印预览</AButton>
|
<AButton style="margin-left: 10px; background: deeppink" type="primary" @click="handleExport">导出快照</AButton>
|
</div>
|
|
<div class="jnpf-univer-preview-module">
|
<JnpfUniverDesign v-if="internalOpen" ref="jnpfUniverDesignPreviewRef" />
|
|
<div id="floatEchartVMContent" class="cell-echarts-vm-content">
|
<JnpfUniverFloatEchartVM ref="jnpfUniverFloatEchartVMRef" univer-create-mode="preview" />
|
</div>
|
<div id="cellEchartsContent" class="cell-echarts-content">
|
<JnpfUniverCellEchart ref="jnpfUniverCellEchartRef" univer-create-mode="preview" />
|
</div>
|
</div>
|
</AModal>
|
</template>
|
|
<style lang="scss">
|
.preview-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;
|
flex-direction: column;
|
|
.jnpf-univer-preview-module {
|
position: relative;
|
flex: 1;
|
}
|
}
|
|
.ant-modal-footer {
|
display: none;
|
}
|
|
// 隐藏的dom节点
|
.cell-echarts-content {
|
position: absolute;
|
inset: 0;
|
z-index: -1;
|
}
|
|
// 隐藏的dom节点
|
.cell-echarts-vm-content {
|
position: absolute;
|
inset: 0;
|
z-index: -2;
|
}
|
}
|
</style>
|