|
|
@@ -0,0 +1,1308 @@
|
|
|
+<!-- eslint-disable no-useless-escape -->
|
|
|
+<!-- eslint-disable no-console -->
|
|
|
+<!-- eslint-disable unicorn/prefer-structured-clone -->
|
|
|
+<script lang="ts" setup>
|
|
|
+ import { reactive, ref, toRefs, unref, watch } from 'vue';
|
|
|
+
|
|
|
+ import { IWorkbookData } from '@univerjs/core';
|
|
|
+ import { DeviceInputEventType, ITextWatermarkConfig } from '@univerjs/engine-render';
|
|
|
+ import { SetSelectionsOperation, SetWorksheetActiveOperation, WorkbookEditablePermission } from '@univerjs/sheets';
|
|
|
+ import JsBarcode from 'jsbarcode';
|
|
|
+ import { debounce } from 'lodash-es';
|
|
|
+ import { storeToRefs } from 'pinia';
|
|
|
+ import QRCode from 'qrcode';
|
|
|
+
|
|
|
+ import JnpfUniverCellEchart from '../Design/univer/components/Echart/cell.vue';
|
|
|
+ import { CreateUnitProps, DeliverCellDataProps, DeliverFloatEchartOptionProps, DeliverFloatImageOptionProps, DesignStateProps } from './index';
|
|
|
+ import { useJnpfUniverStore } from './store';
|
|
|
+ import { JnpfFUniver } from './univer/facade';
|
|
|
+ import {
|
|
|
+ base64ToFile,
|
|
|
+ getParentCellPosWhenClearCell,
|
|
|
+ getParentCellPosWhenDelete,
|
|
|
+ getParentCellPosWhenInsert,
|
|
|
+ getParentCellPosWhenMove,
|
|
|
+ getParentCellPosWhenMoveCell,
|
|
|
+ isEmptyObject,
|
|
|
+ isNullOrUndefined,
|
|
|
+ } from './univer/utils';
|
|
|
+ import {
|
|
|
+ DefaultDialogSelectCellConfig,
|
|
|
+ DefaultFloatEchartOptions,
|
|
|
+ DefaultFloatImageOption,
|
|
|
+ DefaultPrintConfig,
|
|
|
+ DefaultWatermarkConfig,
|
|
|
+ JnpfCommandIds,
|
|
|
+ jnpfPaperPaddingTypeOptions,
|
|
|
+ jnpfPaperTypeOptions,
|
|
|
+ jnpfPrintAreaOptions,
|
|
|
+ jnpfPrintDirectionOptions,
|
|
|
+ jnpfPrintHAlignOptions,
|
|
|
+ jnpfPrintScaleOptions,
|
|
|
+ jnpfPrintVAlignOptions,
|
|
|
+ JnpfUniverDialogSelectCellKey,
|
|
|
+ } from './univer/utils/define';
|
|
|
+ import {
|
|
|
+ analysisCreateUnitData,
|
|
|
+ arrangeDesignWorkbookData,
|
|
|
+ arrangePreviewWorkbookData,
|
|
|
+ createUniverInstance,
|
|
|
+ judgeSheetHasCustomFloatDom,
|
|
|
+ onInsertedFloatEchart,
|
|
|
+ onInsertedFloatImage,
|
|
|
+ updateFloatStoreId,
|
|
|
+ } from './univer/utils/univer';
|
|
|
+ import { buildUUID } from './univer/utils/uuid';
|
|
|
+
|
|
|
+ import '@univerjs/design/lib/index.css';
|
|
|
+ import '@univerjs/ui/lib/index.css';
|
|
|
+ import '@univerjs/docs-ui/lib/index.css';
|
|
|
+ // import '@univerjs-pro/sheets-print/lib/index.css';
|
|
|
+ import '@univerjs/sheets-ui/lib/index.css';
|
|
|
+ import '@univerjs/sheets-formula-ui/lib/index.css';
|
|
|
+ import '@univerjs/sheets-numfmt-ui/lib/index.css';
|
|
|
+ import '@univerjs/sheets-filter-ui/lib/index.css';
|
|
|
+ import '@univerjs/sheets-sort-ui/lib/index.css';
|
|
|
+ import '@univerjs/sheets-data-validation-ui/lib/index.css';
|
|
|
+ import '@univerjs/sheets-conditional-formatting-ui/lib/index.css';
|
|
|
+ import '@univerjs/sheets-hyper-link-ui/lib/index.css';
|
|
|
+ import '@univerjs/drawing-ui/lib/index.css';
|
|
|
+ import '@univerjs/sheets-drawing-ui/lib/index.css';
|
|
|
+ import '@univerjs/thread-comment-ui/lib/index.css';
|
|
|
+ import '@univerjs/find-replace/lib/index.css';
|
|
|
+ import '@univerjs/sheets-crosshair-highlight/lib/index.css';
|
|
|
+ import '@univerjs/sheets-zen-editor/lib/index.css';
|
|
|
+ import '@univerjs/uniscript/lib/index.css';
|
|
|
+
|
|
|
+ defineOptions({ name: 'JnpfUniverDesign' });
|
|
|
+ const emits = defineEmits(['preview', 'focusFloatEchart', 'focusFloatImage', 'changeCell', 'changeDialogSelectCell']);
|
|
|
+
|
|
|
+ const state = reactive<DesignStateProps>({
|
|
|
+ activeSelections: [],
|
|
|
+ activeWorkbook: null,
|
|
|
+
|
|
|
+ activeWorkbookId: null,
|
|
|
+
|
|
|
+ activeWorksheet: null,
|
|
|
+
|
|
|
+ activeWorksheetId: null,
|
|
|
+ beforeCommandExecuteMonitor: null,
|
|
|
+ commandExecuteMonitor: null,
|
|
|
+ configDialogCellTarget: null,
|
|
|
+
|
|
|
+ containerEleId: null,
|
|
|
+ dialogCellInstance: null,
|
|
|
+
|
|
|
+ jnpfUniverAPI: null,
|
|
|
+ loading: false,
|
|
|
+
|
|
|
+ openDialogCell: false,
|
|
|
+ selectionChangeMonitor: null,
|
|
|
+ univer: null,
|
|
|
+
|
|
|
+ univerCreateMode: 'design',
|
|
|
+ });
|
|
|
+ const {
|
|
|
+ activeSelections,
|
|
|
+ activeWorkbook,
|
|
|
+ activeWorkbookId,
|
|
|
+ activeWorksheet,
|
|
|
+ activeWorksheetId,
|
|
|
+ beforeCommandExecuteMonitor,
|
|
|
+ commandExecuteMonitor,
|
|
|
+ configDialogCellTarget,
|
|
|
+ containerEleId,
|
|
|
+ dialogCellInstance,
|
|
|
+ jnpfUniverAPI,
|
|
|
+ loading,
|
|
|
+ openDialogCell,
|
|
|
+ selectionChangeMonitor,
|
|
|
+ univerCreateMode,
|
|
|
+ } = toRefs(state);
|
|
|
+
|
|
|
+ // 创建设计器的动态id
|
|
|
+ const dynamicJnpfUniverStoreId = `jnpfUniver_${buildUUID()}`;
|
|
|
+ state.containerEleId = dynamicJnpfUniverStoreId;
|
|
|
+
|
|
|
+ const jnpfUniverStore = useJnpfUniverStore(dynamicJnpfUniverStoreId);
|
|
|
+ const { dialogSelectCellDataCache, dialogSelectCellStateCache } = storeToRefs(jnpfUniverStore);
|
|
|
+
|
|
|
+ const jnpfUniverCellEchartRef = ref();
|
|
|
+
|
|
|
+ // 创建工作簿
|
|
|
+ function handleCreateDesignUnit(options?: CreateUnitProps) {
|
|
|
+ // 销毁实例
|
|
|
+ handleDisposeUnit();
|
|
|
+
|
|
|
+ const {
|
|
|
+ defaultActiveSheetId,
|
|
|
+ floatEcharts = {},
|
|
|
+ floatImages = {},
|
|
|
+ loading: createLoading = false,
|
|
|
+
|
|
|
+ mode = 'design',
|
|
|
+ readonly: isReadonly = false,
|
|
|
+ snapshot: workbookData,
|
|
|
+ uiContextMenu = true,
|
|
|
+
|
|
|
+ uiFooter = true,
|
|
|
+
|
|
|
+ uiHeader = true,
|
|
|
+
|
|
|
+ watermark = {},
|
|
|
+
|
|
|
+ darkMode = false,
|
|
|
+ } = options ?? {};
|
|
|
+
|
|
|
+ state.univerCreateMode = mode;
|
|
|
+ state.loading = createLoading;
|
|
|
+
|
|
|
+ const containerEle = getDesignContainerEle();
|
|
|
+ if (!containerEle) {
|
|
|
+ console.warn('报表构建失败');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新浮动元素的storeId
|
|
|
+ const workbookDataCache = workbookData ? updateFloatStoreId(workbookData, dynamicJnpfUniverStoreId) : '{}';
|
|
|
+ // 解析创建univer实例的快照数据
|
|
|
+ const realWorkbookData = workbookData ? analysisCreateUnitData(workbookDataCache, univerCreateMode.value, isReadonly) : {};
|
|
|
+
|
|
|
+ // 构建实例
|
|
|
+ const univerInstance = createUniverInstance({
|
|
|
+ container: containerEle,
|
|
|
+ contextMenu: uiContextMenu,
|
|
|
+ footer: uiFooter,
|
|
|
+ header: isReadonly ? false : uiHeader,
|
|
|
+ workbookData: realWorkbookData,
|
|
|
+ darkMode,
|
|
|
+ });
|
|
|
+
|
|
|
+ state.univer = univerInstance;
|
|
|
+ state.jnpfUniverAPI = JnpfFUniver.newAPI(univerInstance);
|
|
|
+
|
|
|
+ state.activeWorkbook = jnpfUniverAPI.value?.getActiveWorkbook();
|
|
|
+ state.activeWorkbookId = activeWorkbook.value?.getId();
|
|
|
+
|
|
|
+ // 改变默认激活的工作表
|
|
|
+ if (defaultActiveSheetId) {
|
|
|
+ jnpfUniverAPI.value?.executeCommand(SetWorksheetActiveOperation.id, {
|
|
|
+ subUnitId: defaultActiveSheetId,
|
|
|
+ unitId: activeWorkbookId.value,
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ state.activeWorksheet = activeWorkbook.value?.getActiveSheet();
|
|
|
+ state.activeWorksheetId = activeWorksheet.value?.getSheetId();
|
|
|
+
|
|
|
+ // 同步数据到store
|
|
|
+ jnpfUniverStore?.setJnpfUniverApiCache(jnpfUniverAPI.value);
|
|
|
+ jnpfUniverStore?.setUniverCreateModeCache(univerCreateMode.value);
|
|
|
+ jnpfUniverStore?.setFloatEchartDataCaches(floatEcharts);
|
|
|
+ jnpfUniverStore?.setFloatImageDataCaches(floatImages);
|
|
|
+
|
|
|
+ // 把store的动态id传给底层
|
|
|
+ jnpfUniverAPI.value?.getSheetsFloatDom()?.savePiniaStoreId(dynamicJnpfUniverStoreId);
|
|
|
+ jnpfUniverAPI.value?.getSheetsFloatEchart()?.savePiniaStoreId(dynamicJnpfUniverStoreId);
|
|
|
+ jnpfUniverAPI.value?.getSheetsFloatImage()?.savePiniaStoreId(dynamicJnpfUniverStoreId);
|
|
|
+
|
|
|
+ setWorkbookPermission(isReadonly); // 设置报表权限
|
|
|
+ bindUniverLifeCycle(realWorkbookData, watermark); // 绑定生命周期
|
|
|
+
|
|
|
+ bindSelectionChange(isReadonly); // 绑定选区变更事件
|
|
|
+ bindBeforeCommandExecute(); // 绑定监听命令执行之前
|
|
|
+ bindAfterCommandExecuted(isReadonly); // 绑定监听命令执行之后
|
|
|
+
|
|
|
+ // 表结构发生了变化
|
|
|
+ jnpfUniverAPI.value?.addEvent(jnpfUniverAPI.value?.Event?.SheetSkeletonChanged, (params: any) => {
|
|
|
+ correctCellEchartSizeDebounce(params);
|
|
|
+ });
|
|
|
+
|
|
|
+ // 这个丢出去后,外层所有的地方都可以用univer的api了
|
|
|
+ return {
|
|
|
+ jnpfUniverAPI: jnpfUniverAPI.value,
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置unit权限
|
|
|
+ function setWorkbookPermission(isReadonly: boolean) {
|
|
|
+ if (univerCreateMode.value === 'design' && !isReadonly) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ updateWorkbookPermission(false);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新权限控制
|
|
|
+ function updateWorkbookPermission(state: boolean) {
|
|
|
+ const permission = jnpfUniverAPI.value?.getPermission();
|
|
|
+
|
|
|
+ permission?.setWorkbookPermissionPoint(activeWorkbookId.value, WorkbookEditablePermission, state);
|
|
|
+ permission?.setPermissionDialogVisible(state);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 绑定univer的生命周期
|
|
|
+ function bindUniverLifeCycle(workbookData: IWorkbookData, watermarkInfo: any) {
|
|
|
+ if (!jnpfUniverAPI.value) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const univerHooks = jnpfUniverAPI.value?.getHooks();
|
|
|
+ const { config: watermarkConfig, show: showWatermark } = watermarkInfo ?? {};
|
|
|
+
|
|
|
+ jnpfUniverAPI.value?.addEvent(jnpfUniverAPI.value?.Event.LifeCycleChanged, (params: any) => {
|
|
|
+ const { stage } = params;
|
|
|
+
|
|
|
+ if (stage === 2) {
|
|
|
+ jnpfUniverAPI.value?.getSheetsFloatImage()?.cacheImages();
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // univerHooks?.onStarting(() => {});
|
|
|
+ univerHooks?.onReady(() => {
|
|
|
+ jnpfUniverAPI.value?.deleteWatermark();
|
|
|
+ });
|
|
|
+ univerHooks?.onRendered(() => {
|
|
|
+ // 预览和有水印配置时才显示水印
|
|
|
+ if (showWatermark && univerCreateMode.value === 'preview') {
|
|
|
+ jnpfUniverAPI.value?.addWatermark('text', { ...watermarkConfig });
|
|
|
+ }
|
|
|
+ // 0.5.3版本开始初始的情况下,不会执行onSelectionChange事件
|
|
|
+ jnpfUniverAPI.value?.executeCommand(SetSelectionsOperation.id, {
|
|
|
+ selections: [
|
|
|
+ {
|
|
|
+ range: {
|
|
|
+ endColumn: 0,
|
|
|
+ endRow: 0,
|
|
|
+ rangeType: 0,
|
|
|
+ startColumn: 0,
|
|
|
+ startRow: 0,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ subUnitId: activeWorksheetId.value,
|
|
|
+ type: 2,
|
|
|
+ unitId: activeWorkbookId.value,
|
|
|
+ });
|
|
|
+ });
|
|
|
+ univerHooks?.onSteady(() => {
|
|
|
+ /**
|
|
|
+ * 判断当前激活的工作表有没有图表,有图表的话loading层慢慢关一会儿
|
|
|
+ */
|
|
|
+ jnpfUniverAPI.value?.getFormula()?.executeCalculation();
|
|
|
+ const { resources = [] } = workbookData ?? {};
|
|
|
+ const activeWorksheetHasFloatDomState = resources.some((resource: any) => {
|
|
|
+ if (resource?.name !== 'SHEET_DRAWING_PLUGIN') {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ const parsedResourceData = JSON.parse(resource?.data || '{}');
|
|
|
+ const currentSheetResourceOption = parsedResourceData?.[activeWorksheetId.value];
|
|
|
+
|
|
|
+ return currentSheetResourceOption?.data && judgeSheetHasCustomFloatDom(currentSheetResourceOption.data);
|
|
|
+ });
|
|
|
+ if (activeWorksheetHasFloatDomState) {
|
|
|
+ setTimeout(() => {
|
|
|
+ loading.value = false;
|
|
|
+ }, 500);
|
|
|
+ } else {
|
|
|
+ loading.value = false;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 绑定选区变更事件
|
|
|
+ function bindSelectionChange(isReadonly: boolean) {
|
|
|
+ if (univerCreateMode.value !== 'design' || isReadonly) {
|
|
|
+ state.selectionChangeMonitor = null;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ state.selectionChangeMonitor = activeWorkbook.value?.onSelectionChange((params: any) => {
|
|
|
+ if (!params?.length) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ state.activeSelections = JSON.parse(JSON.stringify(params));
|
|
|
+
|
|
|
+ // 业务逻辑只选取第一选区的第一个单元格
|
|
|
+ const firstCell = params[0] ?? {};
|
|
|
+ const { startColumn, startRow } = firstCell;
|
|
|
+ const firstCellData = jnpfUniverAPI.value?.getSheetsCell()?.getCellData(startColumn, startRow) ?? {};
|
|
|
+
|
|
|
+ if (!isReadonly) {
|
|
|
+ if (openDialogCell.value) {
|
|
|
+ // 选择关联单元格操作
|
|
|
+ jnpfUniverStore?.setDialogSelectCellDataCache({
|
|
|
+ startColumn,
|
|
|
+ startRow,
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ // 暴露数据给业务层
|
|
|
+ emits('changeCell', {
|
|
|
+ cellData: JSON.parse(JSON.stringify(firstCellData)),
|
|
|
+ startColumn,
|
|
|
+ startRow,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 绑定监听命令执行之前
|
|
|
+ function bindBeforeCommandExecute() {
|
|
|
+ // 等待废弃
|
|
|
+ // beforeCommandExecuteMonitor.value = jnpfUniverAPI.value?.onBeforeCommandExecute((_command: any) => {});
|
|
|
+ }
|
|
|
+
|
|
|
+ // 绑定监听命令执行之后
|
|
|
+ function bindAfterCommandExecuted(isReadonly: boolean) {
|
|
|
+ state.commandExecuteMonitor = jnpfUniverAPI.value?.onCommandExecuted((command: any) => {
|
|
|
+ const { id: commandId } = command ?? {};
|
|
|
+
|
|
|
+ // 切换工作本
|
|
|
+ if (activeWorkbook.value && commandId === 'sheet.operation.set-worksheet-active') {
|
|
|
+ state.activeWorksheet = activeWorkbook.value?.getActiveSheet();
|
|
|
+ state.activeWorksheetId = activeWorksheet.value?.getSheetId();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 插入悬浮图表
|
|
|
+ if (commandId === JnpfCommandIds.insertedFloatEchart) {
|
|
|
+ onInsertedFloatEchart(jnpfUniverStore, command);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 聚焦某个悬浮图表
|
|
|
+ if (commandId === JnpfCommandIds.focusFloatEchart) {
|
|
|
+ const { drawingId } = command?.params ?? {};
|
|
|
+ if (!drawingId) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const res = jnpfUniverStore?.getFloatEchartDataByDrawingId(drawingId);
|
|
|
+ if (!res) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const { echartType, option } = res ?? {};
|
|
|
+ emits('focusFloatEchart', { drawingId, echartType, option } as DeliverFloatEchartOptionProps);
|
|
|
+ } else {
|
|
|
+ jnpfUniverAPI.value?.getSheetsFloatEchart()?.clearFocusDrawingId();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 插入悬浮图片
|
|
|
+ if (commandId === JnpfCommandIds.insertedFloatImage) {
|
|
|
+ onInsertedFloatImage(jnpfUniverStore, command);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 聚焦图片
|
|
|
+ if (commandId === JnpfCommandIds.focusFloatImage) {
|
|
|
+ const { drawingId } = command?.params ?? {};
|
|
|
+ if (!drawingId) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const res = jnpfUniverStore?.getFloatImageDataByDrawingId(drawingId);
|
|
|
+ if (!res) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const { imageType, option } = res ?? {};
|
|
|
+ emits('focusFloatImage', { drawingId, imageType, option } as DeliverFloatImageOptionProps);
|
|
|
+ } else {
|
|
|
+ jnpfUniverAPI.value?.getSheetsFloatImage()?.clearFocusDrawingId();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设计预览
|
|
|
+ if (commandId === JnpfCommandIds.preview) {
|
|
|
+ emits('preview');
|
|
|
+ }
|
|
|
+
|
|
|
+ if (univerCreateMode.value === 'design' && !isReadonly) {
|
|
|
+ // 操作单元格合并
|
|
|
+ if (commandId === 'sheet.command.add-worksheet-merge') {
|
|
|
+ correctCellEchartSize(command.params?.selections);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 取消单元格合并
|
|
|
+ if (commandId === 'sheet.mutation.remove-worksheet-merge') {
|
|
|
+ correctCellEchartSize(command.params?.ranges);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 新增行
|
|
|
+ if (commandId === 'sheet.mutation.insert-row') {
|
|
|
+ handleInsertRowAndCol(command.params, 'row');
|
|
|
+ }
|
|
|
+
|
|
|
+ // 新增列
|
|
|
+ if (commandId === 'sheet.mutation.insert-col') {
|
|
|
+ handleInsertRowAndCol(command.params, 'col');
|
|
|
+ }
|
|
|
+
|
|
|
+ // 删除行
|
|
|
+ if (commandId === 'sheet.mutation.remove-rows') {
|
|
|
+ handleDeleteRowAndCol(command.params, 'row');
|
|
|
+ }
|
|
|
+
|
|
|
+ // 删除列
|
|
|
+ if (commandId === 'sheet.mutation.remove-col') {
|
|
|
+ handleDeleteRowAndCol(command.params, 'col');
|
|
|
+ }
|
|
|
+
|
|
|
+ // 移动行
|
|
|
+ if (commandId === 'sheet.mutation.move-rows') {
|
|
|
+ handleMoveRowAndCol(command.params, 'row');
|
|
|
+ }
|
|
|
+
|
|
|
+ // 移动列
|
|
|
+ if (commandId === 'sheet.mutation.move-columns') {
|
|
|
+ handleMoveRowAndCol(command.params, 'col');
|
|
|
+ }
|
|
|
+
|
|
|
+ // 移动单元格【包含剪切】
|
|
|
+ if (commandId === 'sheet.mutation.move-range') {
|
|
|
+ handleMoveCell(command.params);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 清除单元格内容&全部
|
|
|
+ if (commandId === 'sheet.command.clear-selection-content' || commandId === 'sheet.command.clear-selection-all') {
|
|
|
+ handleClearCell();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 暴露 - 获取设计的工作簿数据
|
|
|
+ function getDesignWorkbookData() {
|
|
|
+ const snapshot = activeWorkbook.value ? activeWorkbook.value?.save() : null;
|
|
|
+ if (!snapshot) {
|
|
|
+ console.warn('获取快照失败');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const { floatEchartDataCaches = {}, floatImageDataCaches = {} } = jnpfUniverStore ?? {};
|
|
|
+ return arrangeDesignWorkbookData(snapshot, floatEchartDataCaches, floatImageDataCaches);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 暴露 - 获取预览的工作簿数据
|
|
|
+ function getPreviewWorkbookData() {
|
|
|
+ const designData = getDesignWorkbookData();
|
|
|
+
|
|
|
+ const { floatEchartToUniverImgDataCaches = {}, floatImageDataCaches = {} } = jnpfUniverStore ?? {};
|
|
|
+ const floatImageToUniverImgDataCaches: any = {};
|
|
|
+
|
|
|
+ for (const dataKey in floatImageDataCaches) {
|
|
|
+ floatImageToUniverImgDataCaches[floatImageDataCaches[dataKey].domId] = floatImageDataCaches[dataKey].option.src;
|
|
|
+ }
|
|
|
+
|
|
|
+ return arrangePreviewWorkbookData(designData, floatEchartToUniverImgDataCaches, floatImageToUniverImgDataCaches);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 暴露 - 更新悬浮图表配置
|
|
|
+ function updateFloatEchartConfig(config: DeliverFloatEchartOptionProps) {
|
|
|
+ const { drawingId, echartType, option } = config ?? {};
|
|
|
+
|
|
|
+ // 校验参数
|
|
|
+ if (!drawingId || !jnpfUniverAPI.value) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const originalFloatEchartData = jnpfUniverStore?.getFloatEchartDataByDrawingId(drawingId);
|
|
|
+ if (!originalFloatEchartData) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const updateFloatEchartData = {
|
|
|
+ ...originalFloatEchartData,
|
|
|
+ echartType,
|
|
|
+ option,
|
|
|
+ };
|
|
|
+
|
|
|
+ const floatEchartDataCaches = jnpfUniverStore?.floatEchartDataCaches ?? {};
|
|
|
+ const updateFloatEchartsData = {
|
|
|
+ ...floatEchartDataCaches,
|
|
|
+ [drawingId]: updateFloatEchartData,
|
|
|
+ };
|
|
|
+
|
|
|
+ jnpfUniverStore?.updateFocusedFloatEchartDataCache({
|
|
|
+ domId: originalFloatEchartData?.domId,
|
|
|
+ drawingId,
|
|
|
+ option,
|
|
|
+ });
|
|
|
+ jnpfUniverStore?.setFloatEchartDataCaches(updateFloatEchartsData);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 暴露 - 更新悬浮图片配置
|
|
|
+ function updateFloatImageConfig(config: DeliverFloatImageOptionProps) {
|
|
|
+ const { drawingId, imageType, option } = config ?? {};
|
|
|
+
|
|
|
+ // 校验参数
|
|
|
+ if (!drawingId || !jnpfUniverAPI.value) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const originalFloatImageData = jnpfUniverStore?.getFloatImageDataByDrawingId(drawingId);
|
|
|
+ if (!originalFloatImageData) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const updateFloatImageData = {
|
|
|
+ ...originalFloatImageData,
|
|
|
+ imageType,
|
|
|
+ option,
|
|
|
+ };
|
|
|
+
|
|
|
+ const floatImageDataCaches = jnpfUniverStore?.floatImageDataCaches ?? {};
|
|
|
+ const updateFloatImagesData = {
|
|
|
+ ...floatImageDataCaches,
|
|
|
+ [drawingId]: updateFloatImageData,
|
|
|
+ };
|
|
|
+
|
|
|
+ jnpfUniverStore?.updateFocusedFloatImageDataCache({
|
|
|
+ domId: originalFloatImageData?.domId,
|
|
|
+ drawingId,
|
|
|
+ option,
|
|
|
+ });
|
|
|
+ jnpfUniverStore?.setFloatImageDataCaches(updateFloatImagesData);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 暴露 - 更新单元格值【支持多个】
|
|
|
+ function updateCellsData(cellsData: DeliverCellDataProps[]) {
|
|
|
+ if (!cellsData?.length) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ cellsData?.forEach((config: any) => {
|
|
|
+ const { cellData: configuringCellData = {}, startColumn, startRow } = config ?? {};
|
|
|
+
|
|
|
+ if (isNullOrUndefined(startColumn) || isNullOrUndefined(startRow)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const oldCellData = jnpfUniverAPI.value?.getSheetsCell()?.getCellData(startColumn, startRow) ?? {};
|
|
|
+
|
|
|
+ const { custom = {}, v = '' } = configuringCellData;
|
|
|
+ const { type } = custom;
|
|
|
+
|
|
|
+ // 纯文本
|
|
|
+ if (!type || type === 'text') {
|
|
|
+ const newCellData = {
|
|
|
+ ...oldCellData,
|
|
|
+ custom: {
|
|
|
+ ...oldCellData?.custom,
|
|
|
+ ...custom,
|
|
|
+ type,
|
|
|
+ },
|
|
|
+ v,
|
|
|
+ };
|
|
|
+
|
|
|
+ delete newCellData?.t;
|
|
|
+ delete newCellData?.custom?.type;
|
|
|
+ // delete newCellData?.custom?.fillDirection;
|
|
|
+
|
|
|
+ if (isEmptyObject(newCellData?.custom)) {
|
|
|
+ delete newCellData?.custom;
|
|
|
+ }
|
|
|
+
|
|
|
+ handleSetCellData({ newCellData, startColumn, startRow });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 数据集
|
|
|
+ if (type === 'dataSource') {
|
|
|
+ const newCellData = {
|
|
|
+ ...oldCellData,
|
|
|
+ custom: {
|
|
|
+ ...oldCellData?.custom,
|
|
|
+ ...custom,
|
|
|
+ type,
|
|
|
+ },
|
|
|
+ t: 1,
|
|
|
+ v: isNullOrUndefined(v) || v === '' ? '' : `\${${v}}`,
|
|
|
+ };
|
|
|
+
|
|
|
+ delete newCellData?.p;
|
|
|
+
|
|
|
+ handleSetCellData({ newCellData, startColumn, startRow });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 参数
|
|
|
+ if (type === 'parameter') {
|
|
|
+ const newCellData = {
|
|
|
+ ...oldCellData,
|
|
|
+ custom: {
|
|
|
+ ...oldCellData?.custom,
|
|
|
+ ...custom,
|
|
|
+ type,
|
|
|
+ },
|
|
|
+ t: 1,
|
|
|
+ v: isNullOrUndefined(v) || v === '' ? '' : `\#{${v}}`,
|
|
|
+ };
|
|
|
+ delete newCellData?.p;
|
|
|
+
|
|
|
+ handleSetCellData({ newCellData, startColumn, startRow });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 单元格图表
|
|
|
+ if (type === 'chart') {
|
|
|
+ cellChartToImage(configuringCellData, startColumn, startRow);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 单元格二维码(暂不支持非静态)
|
|
|
+ if (type === 'qrCode') {
|
|
|
+ // 获取单元格的宽高
|
|
|
+ const targetCellSize = jnpfUniverAPI.value?.getSheetsCell()?.getTargetCellSize(startColumn, startRow);
|
|
|
+ if (!targetCellSize) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const { cellHeight, cellWidth } = targetCellSize;
|
|
|
+
|
|
|
+ // 强制生成正方形 ---- 取长宽中较小的一个数据作为边长
|
|
|
+ const sideLength = Math.min(cellWidth, cellHeight);
|
|
|
+ if (sideLength <= 0) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const { type: codeType, ...codeConfigRest } = custom?.qrCodeOption ?? {};
|
|
|
+
|
|
|
+ if (codeType !== 'static') {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ QRCode?.toDataURL(
|
|
|
+ v,
|
|
|
+ {
|
|
|
+ height: sideLength,
|
|
|
+ width: sideLength,
|
|
|
+ ...codeConfigRest,
|
|
|
+ },
|
|
|
+ (err, base64) => {
|
|
|
+ if (err) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ base64ToFile(base64, 'image.jpeg', 'image/jpeg')
|
|
|
+ .then((file: File) => {
|
|
|
+ jnpfUniverAPI.value?.getSheetsCellImage()?.insertCellImage(file, startRow, startColumn, {
|
|
|
+ ...configuringCellData,
|
|
|
+ custom: {
|
|
|
+ ...configuringCellData.custom,
|
|
|
+ height: sideLength,
|
|
|
+ width: sideLength,
|
|
|
+ },
|
|
|
+ });
|
|
|
+ })
|
|
|
+ .catch((error: Error) => {
|
|
|
+ console.log(error);
|
|
|
+ });
|
|
|
+ },
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ // 单元格条形码(暂不支持非静态)
|
|
|
+ if (type === 'jsbarcode') {
|
|
|
+ if (v === '' || isNullOrUndefined(v)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取单元格的宽高
|
|
|
+ const targetCellSize = jnpfUniverAPI.value?.getSheetsCell()?.getTargetCellSize(startColumn, startRow);
|
|
|
+ if (!targetCellSize) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const { cellHeight, cellWidth } = targetCellSize;
|
|
|
+ if (cellWidth <= 0 || cellHeight <= 0) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const { type: codeType, ...codeConfigRest } = custom?.jsbarcodeOption ?? {};
|
|
|
+
|
|
|
+ if (codeType !== 'static') {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 创建一个临时的 canvas 元素
|
|
|
+ const canvas = document.createElement('canvas');
|
|
|
+ // 设置 canvas 的宽度和高度,确保条形码适配这个区域
|
|
|
+ canvas.width = cellWidth;
|
|
|
+ canvas.height = cellHeight;
|
|
|
+
|
|
|
+ // 使用 jsbarcode 生成条形码
|
|
|
+ JsBarcode(canvas, v, {
|
|
|
+ ...codeConfigRest,
|
|
|
+ height: cellHeight,
|
|
|
+ });
|
|
|
+ const base64 = canvas.toDataURL();
|
|
|
+
|
|
|
+ // 销毁临时的 canvas 元素
|
|
|
+ canvas.width = 0;
|
|
|
+ canvas.height = 0;
|
|
|
+ canvas.remove();
|
|
|
+
|
|
|
+ base64ToFile(base64, 'image.jpeg', 'image/jpeg')
|
|
|
+ .then((file: File) => {
|
|
|
+ jnpfUniverAPI.value?.getSheetsCellImage()?.insertCellImage(file, startRow, startColumn, {
|
|
|
+ ...configuringCellData,
|
|
|
+ custom: {
|
|
|
+ ...configuringCellData.custom,
|
|
|
+ height: cellHeight,
|
|
|
+ width: cellWidth,
|
|
|
+ },
|
|
|
+ });
|
|
|
+ })
|
|
|
+ .catch((error: Error) => {
|
|
|
+ console.log(error);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置单元格值
|
|
|
+ function handleSetCellData(config: any) {
|
|
|
+ const { newCellData: cellData, startColumn, startRow } = config ?? {};
|
|
|
+ jnpfUniverAPI.value?.getSheetsCell()?.setCellData(startColumn, startRow, cellData); // 设置值
|
|
|
+
|
|
|
+ // 更新视图
|
|
|
+ jnpfUniverAPI.value?.getSheetsCell()?.refreshRangeCellsView(activeWorksheet.value?.getRange(startRow, startColumn));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取设计器容器Dom节点
|
|
|
+ function getDesignContainerEle() {
|
|
|
+ if (!containerEleId.value) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return document.getElementById(containerEleId.value) || false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 暴露 - 打开选择单元格的弹窗窗口
|
|
|
+ function getCellFromDialogSelect(targetCall: any) {
|
|
|
+ const { startColumn, startRow } = targetCall ?? {};
|
|
|
+ if (dialogCellInstance.value || isNullOrUndefined(startRow) || isNullOrUndefined(startColumn)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ updateWorkbookPermission(false); // 开启只读权限
|
|
|
+
|
|
|
+ configDialogCellTarget.value = { ...targetCall }; // 记录配置中的单元格
|
|
|
+ state.openDialogCell = true; // 打开弹窗
|
|
|
+
|
|
|
+ state.dialogCellInstance = activeWorkbook.value?.openDialog({
|
|
|
+ id: `dialogSelectCell${dynamicJnpfUniverStoreId}`,
|
|
|
+ children: {
|
|
|
+ label: JnpfUniverDialogSelectCellKey,
|
|
|
+ value: dynamicJnpfUniverStoreId,
|
|
|
+ },
|
|
|
+ ...DefaultDialogSelectCellConfig,
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 暴露 - 让聚焦中的单元格失焦(不失焦的话,最后编辑的单元格数据会缺失)
|
|
|
+ async function setCellEditVisible(): Promise<void> {
|
|
|
+ if (!jnpfUniverAPI.value) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 命令层
|
|
|
+ jnpfUniverAPI.value?.executeCommand('sheet.operation.set-cell-edit-visible', {
|
|
|
+ _eventType: DeviceInputEventType.PointerUp,
|
|
|
+ visible: false,
|
|
|
+ });
|
|
|
+
|
|
|
+ return new Promise(resolve => {
|
|
|
+ setTimeout(() => {
|
|
|
+ resolve();
|
|
|
+ }, 200);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 暴露 - 销毁工作簿
|
|
|
+ function handleDisposeUnit() {
|
|
|
+ const unitId = activeWorkbookId?.value; // 备份出来
|
|
|
+
|
|
|
+ if (unitId) {
|
|
|
+ try {
|
|
|
+ loading.value = true;
|
|
|
+
|
|
|
+ selectionChangeMonitor.value && selectionChangeMonitor.value?.dispose();
|
|
|
+ beforeCommandExecuteMonitor.value && beforeCommandExecuteMonitor.value?.dispose();
|
|
|
+ commandExecuteMonitor.value && commandExecuteMonitor.value?.dispose();
|
|
|
+ dialogCellInstance.value && dialogCellInstance.value?.dispose();
|
|
|
+
|
|
|
+ jnpfUniverAPI.value && jnpfUniverAPI.value?.disposeUnit(activeWorkbookId.value);
|
|
|
+
|
|
|
+ resetUniverState();
|
|
|
+ jnpfUniverStore?.resetStore();
|
|
|
+
|
|
|
+ loading.value = false;
|
|
|
+ console.log('工作簿已销毁');
|
|
|
+ } catch (error) {
|
|
|
+ console.warn(error);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 暴露 - 获取动态的store
|
|
|
+ function getDynamicStore() {
|
|
|
+ return jnpfUniverStore ?? null;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 暴露 - 获取工作簿id
|
|
|
+ function getActiveWorkbookId() {
|
|
|
+ return activeWorkbookId.value ?? null;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 暴露 - 获取激活的工作本id
|
|
|
+ function getActiveWorksheetId() {
|
|
|
+ return activeWorksheetId.value ?? null;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 暴露 - 获取默认的图表配置
|
|
|
+ function getDefaultFloatEchartOptions() {
|
|
|
+ return JSON.parse(JSON.stringify(DefaultFloatEchartOptions));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 暴露 - 获取默认的图片配置
|
|
|
+ function getDefaultFloatImageOption() {
|
|
|
+ return JSON.parse(JSON.stringify(DefaultFloatImageOption));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 暴露 - 获取默认的打印配置
|
|
|
+ function getPrintConfigs() {
|
|
|
+ return JSON.parse(
|
|
|
+ JSON.stringify({
|
|
|
+ defaultConfigForm: DefaultPrintConfig,
|
|
|
+ paperPaddingTypeOptions: jnpfPaperPaddingTypeOptions,
|
|
|
+ paperTypeOptions: jnpfPaperTypeOptions,
|
|
|
+ printAreaOptions: jnpfPrintAreaOptions,
|
|
|
+ printDirectionOptions: jnpfPrintDirectionOptions,
|
|
|
+ printHAlignOptions: jnpfPrintHAlignOptions,
|
|
|
+ printScaleOptions: jnpfPrintScaleOptions,
|
|
|
+ printVAlignOptions: jnpfPrintVAlignOptions,
|
|
|
+ }),
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ // 暴露 - 获取工作本的名称和id
|
|
|
+ function getSheetsInfo() {
|
|
|
+ if (!jnpfUniverAPI.value) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ return jnpfUniverAPI.value?.getActiveWorkbook()?.save()?.sheets;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 暴露 - 获取默认的水印配置
|
|
|
+ function getDefaultWatermarkConfig() {
|
|
|
+ return JSON.parse(JSON.stringify(DefaultWatermarkConfig));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 暴露 - 选中工作簿
|
|
|
+ function setWorksheetActiveOperation(sheetId: string) {
|
|
|
+ if (!sheetId) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ state.jnpfUniverAPI?.executeCommand(SetWorksheetActiveOperation.id, {
|
|
|
+ subUnitId: sheetId,
|
|
|
+ unitId: activeWorkbookId.value,
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 返回弹窗选中的单元格
|
|
|
+ function callbackDialogSelectCell() {
|
|
|
+ if (!dialogCellInstance.value) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ dialogCellInstance.value && dialogCellInstance.value?.dispose(); // 销毁弹窗
|
|
|
+ dialogCellInstance.value = null;
|
|
|
+
|
|
|
+ const selectCellCache = JSON.parse(JSON.stringify(dialogSelectCellDataCache.value)); // 临时存起来,不然选区变化的时候会被同步修改
|
|
|
+
|
|
|
+ const { startColumn, startRow } = (configDialogCellTarget.value ?? {}) as any;
|
|
|
+ jnpfUniverAPI.value?.getSheetsRange()?.recoveryRange(startRow, startColumn);
|
|
|
+ configDialogCellTarget.value = null;
|
|
|
+
|
|
|
+ updateWorkbookPermission(true);
|
|
|
+
|
|
|
+ state.openDialogCell = false;
|
|
|
+ jnpfUniverStore?.setDialogSelectCellDataCache(null);
|
|
|
+
|
|
|
+ emits('changeDialogSelectCell', selectCellCache);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 重置实例状态
|
|
|
+ function resetUniverState() {
|
|
|
+ state.univer = null;
|
|
|
+ state.jnpfUniverAPI = null;
|
|
|
+
|
|
|
+ state.containerEleId = null;
|
|
|
+
|
|
|
+ state.univerCreateMode = 'design';
|
|
|
+
|
|
|
+ state.activeWorkbook = null;
|
|
|
+ state.activeWorkbookId = null;
|
|
|
+ state.activeWorksheet = null;
|
|
|
+ state.activeWorksheetId = null;
|
|
|
+
|
|
|
+ state.selectionChangeMonitor = null;
|
|
|
+ state.activeSelections = [];
|
|
|
+
|
|
|
+ state.beforeCommandExecuteMonitor = null;
|
|
|
+ state.commandExecuteMonitor = null;
|
|
|
+
|
|
|
+ state.configDialogCellTarget = null;
|
|
|
+
|
|
|
+ state.openDialogCell = false;
|
|
|
+ state.dialogCellInstance = null;
|
|
|
+
|
|
|
+ state.loading = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理插入行和列
|
|
|
+ function handleInsertRowAndCol(params: any, axis: 'col' | 'row') {
|
|
|
+ const { range } = params;
|
|
|
+ const { endColumn = 0, endRow = 0, startColumn = 0, startRow = 0 } = range ?? {};
|
|
|
+ const offset = axis === 'row' ? endRow - startRow + 1 : endColumn - startColumn + 1;
|
|
|
+
|
|
|
+ const sheetsCellApi = jnpfUniverAPI.value?.getSheetsCell();
|
|
|
+
|
|
|
+ const allCellData = JSON.parse(JSON.stringify(sheetsCellApi?.getAllCellData())) ?? {};
|
|
|
+ Object.entries(allCellData).forEach(([rowKey, rowData]: [string, any]) => {
|
|
|
+ Object.entries(rowData).forEach(([colKey, colData]: [string, any]) => {
|
|
|
+ if (
|
|
|
+ !colData ||
|
|
|
+ !colData.custom ||
|
|
|
+ isEmptyObject(colData.custom) ||
|
|
|
+ (colData.custom?.leftParentCellType !== 'custom' && colData.custom?.topParentCellType !== 'custom')
|
|
|
+ ) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const updateCellData = {
|
|
|
+ ...allCellData[rowKey][colKey],
|
|
|
+ custom: {
|
|
|
+ ...getParentCellPosWhenInsert(range, axis, offset, colData.custom),
|
|
|
+ },
|
|
|
+ };
|
|
|
+ sheetsCellApi?.setCellData(colKey, rowKey, updateCellData);
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理删除行和列
|
|
|
+ function handleDeleteRowAndCol(params: any, axis: 'col' | 'row') {
|
|
|
+ const { range } = params;
|
|
|
+ const { endColumn = 0, endRow = 0, startColumn = 0, startRow = 0 } = range ?? {};
|
|
|
+ const offset = axis === 'row' ? endRow - startRow + 1 : endColumn - startColumn + 1;
|
|
|
+
|
|
|
+ const sheetsCellApi = jnpfUniverAPI.value?.getSheetsCell();
|
|
|
+
|
|
|
+ const allCellData = JSON.parse(JSON.stringify(sheetsCellApi?.getAllCellData())) ?? {};
|
|
|
+ Object.entries(allCellData).forEach(([rowKey, rowData]: [string, any]) => {
|
|
|
+ Object.entries(rowData).forEach(([colKey, colData]: [string, any]) => {
|
|
|
+ if (
|
|
|
+ !colData ||
|
|
|
+ !colData.custom ||
|
|
|
+ isEmptyObject(colData.custom) ||
|
|
|
+ (colData.custom?.leftParentCellType !== 'custom' && colData.custom?.topParentCellType !== 'custom')
|
|
|
+ ) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const updateCellData = {
|
|
|
+ ...allCellData[rowKey][colKey],
|
|
|
+ custom: {
|
|
|
+ ...getParentCellPosWhenDelete(range, axis, offset, colData.custom),
|
|
|
+ },
|
|
|
+ };
|
|
|
+ sheetsCellApi?.setCellData(colKey, rowKey, updateCellData); // 设置值
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理移动行和列
|
|
|
+ function handleMoveRowAndCol(params: any, axis: 'col' | 'row') {
|
|
|
+ const { sourceRange, targetRange } = params;
|
|
|
+
|
|
|
+ const isRow = axis === 'row';
|
|
|
+ const startKey = isRow ? 'startRow' : 'startColumn';
|
|
|
+ const endKey = isRow ? 'endRow' : 'endColumn';
|
|
|
+ const offset =
|
|
|
+ targetRange[startKey] > sourceRange[startKey]
|
|
|
+ ? targetRange[startKey] - sourceRange[startKey] - (sourceRange[endKey] - sourceRange[startKey] + 1)
|
|
|
+ : targetRange[startKey] < sourceRange[startKey]
|
|
|
+ ? targetRange[startKey] - sourceRange[startKey]
|
|
|
+ : 0;
|
|
|
+
|
|
|
+ const involved = axis === 'row' ? sourceRange.endRow - sourceRange.startRow + 1 : sourceRange.endColumn - sourceRange.startColumn + 1;
|
|
|
+
|
|
|
+ const sheetsCellApi = jnpfUniverAPI.value?.getSheetsCell();
|
|
|
+
|
|
|
+ const allCellData = JSON.parse(JSON.stringify(sheetsCellApi?.getAllCellData())) ?? {};
|
|
|
+ Object.entries(allCellData).forEach(([rowKey, rowData]: [string, any]) => {
|
|
|
+ Object.entries(rowData).forEach(([colKey, colData]: [string, any]) => {
|
|
|
+ if (
|
|
|
+ !colData ||
|
|
|
+ !colData.custom ||
|
|
|
+ isEmptyObject(colData.custom) ||
|
|
|
+ (colData.custom?.leftParentCellType !== 'custom' && colData.custom?.topParentCellType !== 'custom')
|
|
|
+ ) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const updateCellData = {
|
|
|
+ ...allCellData[rowKey][colKey],
|
|
|
+ custom: {
|
|
|
+ ...getParentCellPosWhenMove(sourceRange, targetRange, axis, offset, involved, colData.custom),
|
|
|
+ },
|
|
|
+ };
|
|
|
+ sheetsCellApi?.setCellData(colKey, rowKey, updateCellData); // 设置值
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理移动单元格
|
|
|
+ function handleMoveCell(params: any) {
|
|
|
+ const { fromRange, toRange } = params ?? {};
|
|
|
+
|
|
|
+ const isChangeRow = fromRange.startRow !== toRange.startRow; // 是否改变了纵向
|
|
|
+ const isChangeCol = fromRange.startColumn !== toRange.startColumn; // 是否改变了横向
|
|
|
+
|
|
|
+ const offsetRow = isChangeRow ? toRange.startRow - fromRange.startRow : 0; // 纵向偏移量
|
|
|
+ const offsetCol = isChangeCol ? toRange.startColumn - fromRange.startColumn : 0; // 横向偏移量
|
|
|
+
|
|
|
+ const sheetsCellApi = jnpfUniverAPI.value?.getSheetsCell();
|
|
|
+
|
|
|
+ const allCellData = JSON.parse(JSON.stringify(sheetsCellApi?.getAllCellData())) ?? {};
|
|
|
+ Object.entries(allCellData).forEach(([rowKey, rowData]: [string, any]) => {
|
|
|
+ Object.entries(rowData).forEach(([colKey, colData]: [string, any]) => {
|
|
|
+ if (
|
|
|
+ !colData ||
|
|
|
+ !colData.custom ||
|
|
|
+ isEmptyObject(colData.custom) ||
|
|
|
+ (colData.custom?.leftParentCellType !== 'custom' && colData.custom?.topParentCellType !== 'custom')
|
|
|
+ ) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const updateCellData = {
|
|
|
+ ...allCellData[rowKey][colKey],
|
|
|
+ custom: {
|
|
|
+ ...getParentCellPosWhenMoveCell(
|
|
|
+ fromRange,
|
|
|
+ {
|
|
|
+ offsetCol,
|
|
|
+ offsetRow,
|
|
|
+ },
|
|
|
+ colData.custom,
|
|
|
+ ),
|
|
|
+ },
|
|
|
+ };
|
|
|
+ sheetsCellApi?.setCellData(colKey, rowKey, updateCellData);
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 清除单元格内容和全部
|
|
|
+ function handleClearCell() {
|
|
|
+ const ranges = JSON.parse(JSON.stringify(activeSelections.value));
|
|
|
+ if (!ranges.length) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const sheetsCellApi = jnpfUniverAPI.value?.getSheetsCell();
|
|
|
+
|
|
|
+ const allCellData = JSON.parse(JSON.stringify(sheetsCellApi?.getAllCellData())) ?? {};
|
|
|
+ Object.entries(allCellData).forEach(([rowKey, rowData]: [string, any]) => {
|
|
|
+ Object.entries(rowData).forEach(([colKey, colData]: [string, any]) => {
|
|
|
+ if (
|
|
|
+ !colData ||
|
|
|
+ !colData.custom ||
|
|
|
+ isEmptyObject(colData.custom) ||
|
|
|
+ (colData.custom?.leftParentCellType !== 'custom' && colData.custom?.topParentCellType !== 'custom')
|
|
|
+ ) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const updateCellData = {
|
|
|
+ ...allCellData[rowKey][colKey],
|
|
|
+ custom: {
|
|
|
+ ...getParentCellPosWhenClearCell(ranges, colData.custom),
|
|
|
+ },
|
|
|
+ };
|
|
|
+ sheetsCellApi?.setCellData(colKey, rowKey, updateCellData); // 设置值
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置水印
|
|
|
+ function setWatermark(config: ITextWatermarkConfig) {
|
|
|
+ if (!jnpfUniverAPI.value) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ jnpfUniverAPI.value?.addWatermark('text', config);
|
|
|
+ } catch (error) {
|
|
|
+ console.error(error);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 清除水印
|
|
|
+ function clearWatermark() {
|
|
|
+ if (!jnpfUniverAPI.value) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ jnpfUniverAPI.value?.deleteWatermark();
|
|
|
+ } catch (error) {
|
|
|
+ console.error(error);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 纠正单元格图表尺寸
|
|
|
+ function correctCellEchartSize(ranges: any) {
|
|
|
+ if (!ranges) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const rangeArr: number[][] = [];
|
|
|
+ (ranges ?? []).forEach((range: any) => {
|
|
|
+ for (let row = range.startRow; row <= range.endRow; row++) {
|
|
|
+ for (let col = range.startColumn; col <= range.endColumn; col++) {
|
|
|
+ rangeArr.push([row, col]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ const uniqueArr = [...new Set(rangeArr.map(item => JSON.stringify(item)))].map(item => JSON.parse(item));
|
|
|
+
|
|
|
+ const sheetsCellApi = jnpfUniverAPI.value?.getSheetsCell();
|
|
|
+ const allCellData = JSON.parse(JSON.stringify(sheetsCellApi?.getAllCellData())) ?? {};
|
|
|
+
|
|
|
+ uniqueArr.forEach(([rowKey, colKey]: [number, number]) => {
|
|
|
+ const cellData = allCellData?.[rowKey]?.[colKey];
|
|
|
+ if (!cellData) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const { custom } = cellData ?? {};
|
|
|
+ if (!custom) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const { type } = custom ?? {};
|
|
|
+
|
|
|
+ if (type !== 'chart') {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ cellChartToImage(cellData, colKey, rowKey);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 单元图表转成图片
|
|
|
+ function cellChartToImage(cellData: any, startColumn: number, startRow: number) {
|
|
|
+ // 获取单元格的宽高
|
|
|
+ const targetCellSize = jnpfUniverAPI.value?.getSheetsCell()?.getTargetCellSize(startColumn, startRow);
|
|
|
+ if (!targetCellSize) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const { cellHeight, cellWidth } = targetCellSize;
|
|
|
+ if (cellWidth <= 0 || cellHeight <= 0) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const { custom } = cellData ?? {};
|
|
|
+
|
|
|
+ // 得到了echart的图片
|
|
|
+ const echartImg = unref(jnpfUniverCellEchartRef).render(custom, cellWidth, cellHeight);
|
|
|
+
|
|
|
+ // base64转成文件流后去插入图片
|
|
|
+ base64ToFile(echartImg, 'image.jpeg', 'image/jpeg')
|
|
|
+ .then((file: File) => {
|
|
|
+ jnpfUniverAPI.value?.getSheetsCellImage()?.insertCellImage(file, startRow, startColumn, {
|
|
|
+ ...cellData,
|
|
|
+ custom: {
|
|
|
+ ...cellData.custom,
|
|
|
+ height: cellHeight,
|
|
|
+ width: cellWidth,
|
|
|
+ },
|
|
|
+ });
|
|
|
+ })
|
|
|
+ .catch((error: Error) => {
|
|
|
+ console.log(error);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理纠正单元格图表尺寸,带3000ms 防抖
|
|
|
+ const correctCellEchartSizeDebounce = debounce((params: any) => {
|
|
|
+ correctCellEchartSize(params?.payload?.params?.ranges);
|
|
|
+ }, 300);
|
|
|
+
|
|
|
+ watch(
|
|
|
+ () => dialogSelectCellStateCache.value,
|
|
|
+ () => {
|
|
|
+ callbackDialogSelectCell();
|
|
|
+ },
|
|
|
+ );
|
|
|
+
|
|
|
+ defineExpose({
|
|
|
+ clearWatermark,
|
|
|
+ getActiveWorkbookId,
|
|
|
+ getActiveWorksheetId,
|
|
|
+ getCellFromDialogSelect,
|
|
|
+ getDefaultFloatEchartOptions,
|
|
|
+ getDefaultFloatImageOption,
|
|
|
+ getDefaultWatermarkConfig,
|
|
|
+ getDesignWorkbookData,
|
|
|
+ getDynamicStore,
|
|
|
+ getPreviewWorkbookData,
|
|
|
+ getPrintConfigs,
|
|
|
+ getSheetsInfo,
|
|
|
+ handleCreateDesignUnit,
|
|
|
+ handleDisposeUnit,
|
|
|
+ setCellEditVisible,
|
|
|
+ setWatermark,
|
|
|
+ setWorksheetActiveOperation,
|
|
|
+ updateCellsData,
|
|
|
+ updateFloatEchartConfig,
|
|
|
+ updateFloatImageConfig,
|
|
|
+ });
|
|
|
+</script>
|
|
|
+
|
|
|
+<template>
|
|
|
+ <div class="jnpf-univer-design-content" v-loading="loading">
|
|
|
+ <div :id="containerEleId" class="univer-design-container"></div>
|
|
|
+ </div>
|
|
|
+ <div id="cellEchartsContent" class="cell-echarts-content">
|
|
|
+ <JnpfUniverCellEchart ref="jnpfUniverCellEchartRef" :univer-create-mode="univerCreateMode" />
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+ .jnpf-univer-design-content {
|
|
|
+ position: relative;
|
|
|
+ flex: 1;
|
|
|
+ height: 100%;
|
|
|
+ overflow: hidden auto;
|
|
|
+
|
|
|
+ .univer-design-container {
|
|
|
+ width: 100%;
|
|
|
+ height: calc(100%);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .cell-echarts-content {
|
|
|
+ position: absolute;
|
|
|
+ inset: 0;
|
|
|
+ z-index: -1;
|
|
|
+ }
|
|
|
+</style>
|
|
|
+
|
|
|
+<style lang="scss">
|
|
|
+ .univer-pointer-events-auto.univer-fixed {
|
|
|
+ z-index: 1000 !important;
|
|
|
+ }
|
|
|
+</style>
|