diff --git a/src/editor/core/event/CanvasEvent.ts b/src/editor/core/event/CanvasEvent.ts index 95f1f4b..2618e7b 100644 --- a/src/editor/core/event/CanvasEvent.ts +++ b/src/editor/core/event/CanvasEvent.ts @@ -7,12 +7,14 @@ import { KeyMap } from "../../dataset/enum/Keymap" import { IElement } from "../../interface/Element" import { ICurrentPosition } from "../../interface/Position" import { writeTextByElementList } from "../../utils/clipboard" +import { zipElementList } from "../../utils/element" import { Cursor } from "../cursor/Cursor" import { Draw } from "../draw/Draw" import { HyperlinkParticle } from "../draw/particle/HyperlinkParticle" import { ImageParticle } from "../draw/particle/ImageParticle" import { TableTool } from "../draw/particle/table/TableTool" import { HistoryManager } from "../history/HistoryManager" +import { Listener } from "../listener/Listener" import { Position } from "../position/Position" import { RangeManager } from "../range/RangeManager" @@ -32,6 +34,7 @@ export class CanvasEvent { private imageParticle: ImageParticle private tableTool: TableTool private hyperlinkParticle: HyperlinkParticle + private listener: Listener constructor(draw: Draw) { this.isAllowDrag = false @@ -48,6 +51,7 @@ export class CanvasEvent { this.imageParticle = this.draw.getImageParticle() this.tableTool = this.draw.getTableTool() this.hyperlinkParticle = this.draw.getHyperlinkParticle() + this.listener = this.draw.getListener() } public register() { @@ -349,6 +353,12 @@ export class CanvasEvent { this.cut() } else if (evt.ctrlKey && evt.key === KeyMap.A) { this.selectAll() + } else if (evt.ctrlKey && evt.key === KeyMap.S) { + const saved = this.listener.saved + if (saved) { + saved(this.save()) + } + evt.preventDefault() } } @@ -445,4 +455,10 @@ export class CanvasEvent { this.isCompositing = false } + public save(): IElement[] { + const elementList = this.draw.getOriginalElementList() + const data = zipElementList(elementList) + return data + } + } \ No newline at end of file diff --git a/src/editor/core/listener/Listener.ts b/src/editor/core/listener/Listener.ts index 23d257d..2ea6760 100644 --- a/src/editor/core/listener/Listener.ts +++ b/src/editor/core/listener/Listener.ts @@ -3,6 +3,7 @@ import { IPageScaleChange, IPageSizeChange, IRangeStyleChange, + ISaved, IVisiblePageNoListChange } from "../../interface/Listener" @@ -13,6 +14,7 @@ export class Listener { public intersectionPageNoChange: IIntersectionPageNoChange | null public pageSizeChange: IPageSizeChange | null public pageScaleChange: IPageScaleChange | null + public saved: ISaved | null constructor() { this.rangeStyleChange = null @@ -20,6 +22,7 @@ export class Listener { this.intersectionPageNoChange = null this.pageSizeChange = null this.pageScaleChange = null + this.saved = null } } \ No newline at end of file diff --git a/src/editor/dataset/constant/Element.ts b/src/editor/dataset/constant/Element.ts index 8eac0f4..a2a32ba 100644 --- a/src/editor/dataset/constant/Element.ts +++ b/src/editor/dataset/constant/Element.ts @@ -1,6 +1,6 @@ import { IElement } from "../../interface/Element" -export const EDITOR_ELEMENT_STYLE = [ +export const EDITOR_ELEMENT_STYLE_ATTR = [ 'bold', 'color', 'highlight', @@ -24,4 +24,23 @@ export const EDITOR_ELEMENT_COPY_ATTR: Array = [ 'rowFlex', 'url', 'hyperlinkId' +] + +export const EDITOR_ELEMENT_ZIP_ATTR: Array = [ + 'type', + 'font', + 'size', + 'bold', + 'color', + 'italic', + 'highlight', + 'underline', + 'strikeout', + 'rowFlex', + 'trList', + 'width', + 'height', + 'url', + 'colgroup', + 'valueList' ] \ No newline at end of file diff --git a/src/editor/dataset/enum/Keymap.ts b/src/editor/dataset/enum/Keymap.ts index 3db5839..c79957a 100644 --- a/src/editor/dataset/enum/Keymap.ts +++ b/src/editor/dataset/enum/Keymap.ts @@ -8,6 +8,7 @@ export enum KeyMap { Down = "ArrowDown", A = "a", C = "c", + S = "s", X = "x", Y = "y", Z = "z" diff --git a/src/editor/interface/Listener.ts b/src/editor/interface/Listener.ts index 8f16c30..f3129a6 100644 --- a/src/editor/interface/Listener.ts +++ b/src/editor/interface/Listener.ts @@ -1,3 +1,4 @@ +import { IElement } from ".." import { RowFlex } from "../dataset/enum/Row" export interface IRangeStype { @@ -24,3 +25,5 @@ export type IIntersectionPageNoChange = (payload: number) => void export type IPageSizeChange = (payload: number) => void export type IPageScaleChange = (payload: number) => void + +export type ISaved = (payload: IElement[]) => void diff --git a/src/editor/utils/element.ts b/src/editor/utils/element.ts index bc2eacb..3868bbb 100644 --- a/src/editor/utils/element.ts +++ b/src/editor/utils/element.ts @@ -1,6 +1,7 @@ -import { getUUID } from "." +import { deepClone, getUUID } from "." import { ElementType, IElement } from ".." import { ZERO } from "../dataset/constant/Common" +import { EDITOR_ELEMENT_ZIP_ATTR } from "../dataset/constant/Element" export function formatElementList(elementList: IElement[]) { if (elementList[0]?.value !== ZERO) { @@ -59,4 +60,70 @@ export function formatElementList(elementList: IElement[]) { } i++ } -} \ No newline at end of file +} + +export function zipElementList(payload: IElement[]): IElement[] { + const elementList = deepClone(payload) + const zipElementListData: IElement[] = [] + let e = 0 + while (e < elementList.length) { + let element = elementList[e] + // 筛选所需项 + if (e === 0 && element.value === ZERO) { + e++ + continue + } + // 表格处理 + if (element.type === ElementType.TABLE) { + if (element.trList) { + for (let t = 0; t < element.trList.length; t++) { + const tr = element.trList[t] + delete tr.id + for (let d = 0; d < tr.tdList.length; d++) { + const td = tr.tdList[d] + tr.tdList[d] = { + colspan: td.colspan, + rowspan: td.rowspan, + value: zipElementList(td.value) + } + } + } + } + } else if (element.type === ElementType.HYPERLINK) { + // 超链接处理 + const hyperlinkId = element.hyperlinkId + const hyperlinkElement: IElement = { + type: ElementType.HYPERLINK, + value: '', + url: element.url + } + const valueList: IElement[] = [] + while (e < elementList.length) { + const hyperlinkE = elementList[e] + if (hyperlinkId !== hyperlinkE.hyperlinkId) { + e-- + break + } + delete hyperlinkE.type + delete hyperlinkE.url + valueList.push(hyperlinkE) + e++ + } + hyperlinkElement.valueList = zipElementList(valueList) + element = hyperlinkElement + } + // 压缩保留字段 + const newElement: IElement = { + value: element.value === ZERO ? `\n` : element.value, + } + EDITOR_ELEMENT_ZIP_ATTR.forEach(attr => { + const value = element[attr] as never + if (value !== undefined) { + newElement[attr] = value + } + }) + zipElementListData.push(newElement) + e++ + } + return zipElementListData +} diff --git a/src/editor/utils/index.ts b/src/editor/utils/index.ts index bddf5f2..19fde61 100644 --- a/src/editor/utils/index.ts +++ b/src/editor/utils/index.ts @@ -11,7 +11,7 @@ export function debounce(func: Function, delay: number) { } } -export function deepClone(obj: any) { +export function deepClone(obj: T): T { if (!obj || typeof obj !== 'object') { return obj } @@ -20,6 +20,7 @@ export function deepClone(obj: any) { newObj = obj.map(item => deepClone(item)) } else { Object.keys(obj).forEach((key) => { + // @ts-ignore return newObj[key] = deepClone(obj[key]) }) } diff --git a/src/main.ts b/src/main.ts index 481e157..dc66e01 100644 --- a/src/main.ts +++ b/src/main.ts @@ -194,7 +194,7 @@ window.onload = function () { }]) // 初始化编辑器 const container = document.querySelector('.editor')! - const instance = new Editor(container, data, { + const instance = new Editor(container, data, { margins: [100, 120, 100, 120] }) console.log('实例: ', instance) @@ -541,4 +541,8 @@ window.onload = function () { document.querySelector('.page-scale-percentage')!.innerText = `${Math.floor(payload * 10 * 10)}%` } + instance.listener.saved = function (payload) { + console.log('elementList: ', payload) + } + } \ No newline at end of file