feat:data persistence
This commit is contained in:
@@ -7,12 +7,14 @@ import { KeyMap } from "../../dataset/enum/Keymap"
|
|||||||
import { IElement } from "../../interface/Element"
|
import { IElement } from "../../interface/Element"
|
||||||
import { ICurrentPosition } from "../../interface/Position"
|
import { ICurrentPosition } from "../../interface/Position"
|
||||||
import { writeTextByElementList } from "../../utils/clipboard"
|
import { writeTextByElementList } from "../../utils/clipboard"
|
||||||
|
import { zipElementList } from "../../utils/element"
|
||||||
import { Cursor } from "../cursor/Cursor"
|
import { Cursor } from "../cursor/Cursor"
|
||||||
import { Draw } from "../draw/Draw"
|
import { Draw } from "../draw/Draw"
|
||||||
import { HyperlinkParticle } from "../draw/particle/HyperlinkParticle"
|
import { HyperlinkParticle } from "../draw/particle/HyperlinkParticle"
|
||||||
import { ImageParticle } from "../draw/particle/ImageParticle"
|
import { ImageParticle } from "../draw/particle/ImageParticle"
|
||||||
import { TableTool } from "../draw/particle/table/TableTool"
|
import { TableTool } from "../draw/particle/table/TableTool"
|
||||||
import { HistoryManager } from "../history/HistoryManager"
|
import { HistoryManager } from "../history/HistoryManager"
|
||||||
|
import { Listener } from "../listener/Listener"
|
||||||
import { Position } from "../position/Position"
|
import { Position } from "../position/Position"
|
||||||
import { RangeManager } from "../range/RangeManager"
|
import { RangeManager } from "../range/RangeManager"
|
||||||
|
|
||||||
@@ -32,6 +34,7 @@ export class CanvasEvent {
|
|||||||
private imageParticle: ImageParticle
|
private imageParticle: ImageParticle
|
||||||
private tableTool: TableTool
|
private tableTool: TableTool
|
||||||
private hyperlinkParticle: HyperlinkParticle
|
private hyperlinkParticle: HyperlinkParticle
|
||||||
|
private listener: Listener
|
||||||
|
|
||||||
constructor(draw: Draw) {
|
constructor(draw: Draw) {
|
||||||
this.isAllowDrag = false
|
this.isAllowDrag = false
|
||||||
@@ -48,6 +51,7 @@ export class CanvasEvent {
|
|||||||
this.imageParticle = this.draw.getImageParticle()
|
this.imageParticle = this.draw.getImageParticle()
|
||||||
this.tableTool = this.draw.getTableTool()
|
this.tableTool = this.draw.getTableTool()
|
||||||
this.hyperlinkParticle = this.draw.getHyperlinkParticle()
|
this.hyperlinkParticle = this.draw.getHyperlinkParticle()
|
||||||
|
this.listener = this.draw.getListener()
|
||||||
}
|
}
|
||||||
|
|
||||||
public register() {
|
public register() {
|
||||||
@@ -349,6 +353,12 @@ export class CanvasEvent {
|
|||||||
this.cut()
|
this.cut()
|
||||||
} else if (evt.ctrlKey && evt.key === KeyMap.A) {
|
} else if (evt.ctrlKey && evt.key === KeyMap.A) {
|
||||||
this.selectAll()
|
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
|
this.isCompositing = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public save(): IElement[] {
|
||||||
|
const elementList = this.draw.getOriginalElementList()
|
||||||
|
const data = zipElementList(elementList)
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,7 @@ import {
|
|||||||
IPageScaleChange,
|
IPageScaleChange,
|
||||||
IPageSizeChange,
|
IPageSizeChange,
|
||||||
IRangeStyleChange,
|
IRangeStyleChange,
|
||||||
|
ISaved,
|
||||||
IVisiblePageNoListChange
|
IVisiblePageNoListChange
|
||||||
} from "../../interface/Listener"
|
} from "../../interface/Listener"
|
||||||
|
|
||||||
@@ -13,6 +14,7 @@ export class Listener {
|
|||||||
public intersectionPageNoChange: IIntersectionPageNoChange | null
|
public intersectionPageNoChange: IIntersectionPageNoChange | null
|
||||||
public pageSizeChange: IPageSizeChange | null
|
public pageSizeChange: IPageSizeChange | null
|
||||||
public pageScaleChange: IPageScaleChange | null
|
public pageScaleChange: IPageScaleChange | null
|
||||||
|
public saved: ISaved | null
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.rangeStyleChange = null
|
this.rangeStyleChange = null
|
||||||
@@ -20,6 +22,7 @@ export class Listener {
|
|||||||
this.intersectionPageNoChange = null
|
this.intersectionPageNoChange = null
|
||||||
this.pageSizeChange = null
|
this.pageSizeChange = null
|
||||||
this.pageScaleChange = null
|
this.pageScaleChange = null
|
||||||
|
this.saved = null
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { IElement } from "../../interface/Element"
|
import { IElement } from "../../interface/Element"
|
||||||
|
|
||||||
export const EDITOR_ELEMENT_STYLE = [
|
export const EDITOR_ELEMENT_STYLE_ATTR = [
|
||||||
'bold',
|
'bold',
|
||||||
'color',
|
'color',
|
||||||
'highlight',
|
'highlight',
|
||||||
@@ -24,4 +24,23 @@ export const EDITOR_ELEMENT_COPY_ATTR: Array<keyof IElement> = [
|
|||||||
'rowFlex',
|
'rowFlex',
|
||||||
'url',
|
'url',
|
||||||
'hyperlinkId'
|
'hyperlinkId'
|
||||||
|
]
|
||||||
|
|
||||||
|
export const EDITOR_ELEMENT_ZIP_ATTR: Array<keyof IElement> = [
|
||||||
|
'type',
|
||||||
|
'font',
|
||||||
|
'size',
|
||||||
|
'bold',
|
||||||
|
'color',
|
||||||
|
'italic',
|
||||||
|
'highlight',
|
||||||
|
'underline',
|
||||||
|
'strikeout',
|
||||||
|
'rowFlex',
|
||||||
|
'trList',
|
||||||
|
'width',
|
||||||
|
'height',
|
||||||
|
'url',
|
||||||
|
'colgroup',
|
||||||
|
'valueList'
|
||||||
]
|
]
|
||||||
@@ -8,6 +8,7 @@ export enum KeyMap {
|
|||||||
Down = "ArrowDown",
|
Down = "ArrowDown",
|
||||||
A = "a",
|
A = "a",
|
||||||
C = "c",
|
C = "c",
|
||||||
|
S = "s",
|
||||||
X = "x",
|
X = "x",
|
||||||
Y = "y",
|
Y = "y",
|
||||||
Z = "z"
|
Z = "z"
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { IElement } from ".."
|
||||||
import { RowFlex } from "../dataset/enum/Row"
|
import { RowFlex } from "../dataset/enum/Row"
|
||||||
|
|
||||||
export interface IRangeStype {
|
export interface IRangeStype {
|
||||||
@@ -24,3 +25,5 @@ export type IIntersectionPageNoChange = (payload: number) => void
|
|||||||
export type IPageSizeChange = (payload: number) => void
|
export type IPageSizeChange = (payload: number) => void
|
||||||
|
|
||||||
export type IPageScaleChange = (payload: number) => void
|
export type IPageScaleChange = (payload: number) => void
|
||||||
|
|
||||||
|
export type ISaved = (payload: IElement[]) => void
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { getUUID } from "."
|
import { deepClone, getUUID } from "."
|
||||||
import { ElementType, IElement } from ".."
|
import { ElementType, IElement } from ".."
|
||||||
import { ZERO } from "../dataset/constant/Common"
|
import { ZERO } from "../dataset/constant/Common"
|
||||||
|
import { EDITOR_ELEMENT_ZIP_ATTR } from "../dataset/constant/Element"
|
||||||
|
|
||||||
export function formatElementList(elementList: IElement[]) {
|
export function formatElementList(elementList: IElement[]) {
|
||||||
if (elementList[0]?.value !== ZERO) {
|
if (elementList[0]?.value !== ZERO) {
|
||||||
@@ -59,4 +60,70 @@ export function formatElementList(elementList: IElement[]) {
|
|||||||
}
|
}
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export function debounce(func: Function, delay: number) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function deepClone(obj: any) {
|
export function deepClone<T>(obj: T): T {
|
||||||
if (!obj || typeof obj !== 'object') {
|
if (!obj || typeof obj !== 'object') {
|
||||||
return obj
|
return obj
|
||||||
}
|
}
|
||||||
@@ -20,6 +20,7 @@ export function deepClone(obj: any) {
|
|||||||
newObj = obj.map(item => deepClone(item))
|
newObj = obj.map(item => deepClone(item))
|
||||||
} else {
|
} else {
|
||||||
Object.keys(obj).forEach((key) => {
|
Object.keys(obj).forEach((key) => {
|
||||||
|
// @ts-ignore
|
||||||
return newObj[key] = deepClone(obj[key])
|
return newObj[key] = deepClone(obj[key])
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-1
@@ -194,7 +194,7 @@ window.onload = function () {
|
|||||||
}])
|
}])
|
||||||
// 初始化编辑器
|
// 初始化编辑器
|
||||||
const container = document.querySelector<HTMLDivElement>('.editor')!
|
const container = document.querySelector<HTMLDivElement>('.editor')!
|
||||||
const instance = new Editor(container, data, {
|
const instance = new Editor(container, <IElement[]>data, {
|
||||||
margins: [100, 120, 100, 120]
|
margins: [100, 120, 100, 120]
|
||||||
})
|
})
|
||||||
console.log('实例: ', instance)
|
console.log('实例: ', instance)
|
||||||
@@ -541,4 +541,8 @@ window.onload = function () {
|
|||||||
document.querySelector<HTMLSpanElement>('.page-scale-percentage')!.innerText = `${Math.floor(payload * 10 * 10)}%`
|
document.querySelector<HTMLSpanElement>('.page-scale-percentage')!.innerText = `${Math.floor(payload * 10 * 10)}%`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
instance.listener.saved = function (payload) {
|
||||||
|
console.log('elementList: ', payload)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user