+4
-3
@@ -163,16 +163,16 @@
|
||||
</div>
|
||||
<div class="menu-divider"></div>
|
||||
<div class="menu-item">
|
||||
<div class="menu-item__search">
|
||||
<div class="menu-item__search" data-menu="search">
|
||||
<i></i>
|
||||
</div>
|
||||
<div class="menu-item__search__collapse">
|
||||
<div class="menu-item__search__collapse" data-menu="search">
|
||||
<div class="menu-item__search__collapse__search">
|
||||
<input type="text" />
|
||||
<span>×</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="menu-item__print">
|
||||
<div class="menu-item__print" data-menu="print">
|
||||
<i></i>
|
||||
</div>
|
||||
</div>
|
||||
@@ -183,6 +183,7 @@
|
||||
<span>可见页码:<span class="page-no-list">1</span></span>
|
||||
<span>页面:<span class="page-no">1</span>/<span class="page-size">1</span></span>
|
||||
</div>
|
||||
<div class="editor-mode">编辑模式</div>
|
||||
<div>
|
||||
<div class="page-scale-minus">
|
||||
<i></i>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { IElement } from "../.."
|
||||
import { EditorMode } from "../../dataset/enum/Editor"
|
||||
import { RowFlex } from "../../dataset/enum/Row"
|
||||
import { IDrawImagePayload } from "../../interface/Draw"
|
||||
import { IWatermark } from "../../interface/Watermark"
|
||||
@@ -6,6 +7,7 @@ import { CommandAdapt } from "./CommandAdapt"
|
||||
|
||||
export class Command {
|
||||
|
||||
private static mode: Function
|
||||
private static cut: Function
|
||||
private static copy: Function
|
||||
private static paste: Function
|
||||
@@ -53,6 +55,7 @@ export class Command {
|
||||
private static insertElementList: Function
|
||||
|
||||
constructor(adapt: CommandAdapt) {
|
||||
Command.mode = adapt.mode.bind(adapt)
|
||||
Command.cut = adapt.cut.bind(adapt)
|
||||
Command.copy = adapt.copy.bind(adapt)
|
||||
Command.paste = adapt.paste.bind(adapt)
|
||||
@@ -101,6 +104,10 @@ export class Command {
|
||||
}
|
||||
|
||||
// 全局命令
|
||||
public executeMode(payload: EditorMode) {
|
||||
return Command.mode(payload)
|
||||
}
|
||||
|
||||
public executeCut() {
|
||||
return Command.cut()
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { WRAP, ZERO } from "../../dataset/constant/Common"
|
||||
import { EDITOR_ELEMENT_STYLE_ATTR, TEXTLIKE_ELEMENT_TYPE } from "../../dataset/constant/Element"
|
||||
import { defaultWatermarkOption } from "../../dataset/constant/Watermark"
|
||||
import { EditorContext } from "../../dataset/enum/Editor"
|
||||
import { EditorContext, EditorMode } from "../../dataset/enum/Editor"
|
||||
import { ElementType } from "../../dataset/enum/Element"
|
||||
import { ElementStyleKey } from "../../dataset/enum/ElementStyle"
|
||||
import { RowFlex } from "../../dataset/enum/Row"
|
||||
@@ -45,7 +45,19 @@ export class CommandAdapt {
|
||||
this.options = draw.getOptions()
|
||||
}
|
||||
|
||||
public mode(payload: EditorMode) {
|
||||
const mode = this.draw.getMode()
|
||||
if (mode === payload) return
|
||||
this.draw.setMode(payload)
|
||||
this.draw.render({
|
||||
isSetCursor: false,
|
||||
isSubmitHistory: false
|
||||
})
|
||||
}
|
||||
|
||||
public cut() {
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
if (isReadonly) return
|
||||
this.canvasEvent.cut()
|
||||
}
|
||||
|
||||
@@ -54,6 +66,8 @@ export class CommandAdapt {
|
||||
}
|
||||
|
||||
public async paste() {
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
if (isReadonly) return
|
||||
const text = await navigator.clipboard.readText()
|
||||
if (text) {
|
||||
this.canvasEvent.input(text)
|
||||
@@ -65,14 +79,20 @@ export class CommandAdapt {
|
||||
}
|
||||
|
||||
public undo() {
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
if (isReadonly) return
|
||||
this.historyManager.undo()
|
||||
}
|
||||
|
||||
public redo() {
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
if (isReadonly) return
|
||||
this.historyManager.redo()
|
||||
}
|
||||
|
||||
public painter() {
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
if (isReadonly) return
|
||||
const selection = this.range.getSelection()
|
||||
if (!selection) return
|
||||
const painterStyle: IElementStyle = {}
|
||||
@@ -89,6 +109,8 @@ export class CommandAdapt {
|
||||
}
|
||||
|
||||
public format() {
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
if (isReadonly) return
|
||||
const selection = this.range.getSelection()
|
||||
if (!selection) return
|
||||
selection.forEach(el => {
|
||||
@@ -103,6 +125,8 @@ export class CommandAdapt {
|
||||
}
|
||||
|
||||
public font(payload: string) {
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
if (isReadonly) return
|
||||
const selection = this.range.getSelection()
|
||||
if (!selection) return
|
||||
selection.forEach(el => {
|
||||
@@ -112,6 +136,8 @@ export class CommandAdapt {
|
||||
}
|
||||
|
||||
public sizeAdd() {
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
if (isReadonly) return
|
||||
const selection = this.range.getSelection()
|
||||
if (!selection) return
|
||||
const lessThanMaxSizeIndex = selection.findIndex(s => !s.size || s.size + 2 <= 72)
|
||||
@@ -128,6 +154,8 @@ export class CommandAdapt {
|
||||
}
|
||||
|
||||
public sizeMinus() {
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
if (isReadonly) return
|
||||
const selection = this.range.getSelection()
|
||||
if (!selection) return
|
||||
const greaterThanMaxSizeIndex = selection.findIndex(s => !s.size || s.size - 2 >= 8)
|
||||
@@ -144,6 +172,8 @@ export class CommandAdapt {
|
||||
}
|
||||
|
||||
public bold() {
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
if (isReadonly) return
|
||||
const selection = this.range.getSelection()
|
||||
if (!selection) return
|
||||
const noBoldIndex = selection.findIndex(s => !s.bold)
|
||||
@@ -154,6 +184,8 @@ export class CommandAdapt {
|
||||
}
|
||||
|
||||
public italic() {
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
if (isReadonly) return
|
||||
const selection = this.range.getSelection()
|
||||
if (!selection) return
|
||||
const noItalicIndex = selection.findIndex(s => !s.italic)
|
||||
@@ -164,6 +196,8 @@ export class CommandAdapt {
|
||||
}
|
||||
|
||||
public underline() {
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
if (isReadonly) return
|
||||
const selection = this.range.getSelection()
|
||||
if (!selection) return
|
||||
const noUnderlineIndex = selection.findIndex(s => !s.underline)
|
||||
@@ -174,6 +208,8 @@ export class CommandAdapt {
|
||||
}
|
||||
|
||||
public strikeout() {
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
if (isReadonly) return
|
||||
const selection = this.range.getSelection()
|
||||
if (!selection) return
|
||||
const noStrikeoutIndex = selection.findIndex(s => !s.strikeout)
|
||||
@@ -184,6 +220,8 @@ export class CommandAdapt {
|
||||
}
|
||||
|
||||
public superscript() {
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
if (isReadonly) return
|
||||
const selection = this.range.getSelection()
|
||||
if (!selection) return
|
||||
const superscriptIndex = selection.findIndex(s => s.type === ElementType.SUPERSCRIPT)
|
||||
@@ -205,6 +243,8 @@ export class CommandAdapt {
|
||||
}
|
||||
|
||||
public subscript() {
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
if (isReadonly) return
|
||||
const selection = this.range.getSelection()
|
||||
if (!selection) return
|
||||
const subscriptIndex = selection.findIndex(s => s.type === ElementType.SUBSCRIPT)
|
||||
@@ -226,6 +266,8 @@ export class CommandAdapt {
|
||||
}
|
||||
|
||||
public color(payload: string) {
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
if (isReadonly) return
|
||||
const selection = this.range.getSelection()
|
||||
if (!selection) return
|
||||
selection.forEach(el => {
|
||||
@@ -235,6 +277,8 @@ export class CommandAdapt {
|
||||
}
|
||||
|
||||
public highlight(payload: string) {
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
if (isReadonly) return
|
||||
const selection = this.range.getSelection()
|
||||
if (!selection) return
|
||||
selection.forEach(el => {
|
||||
@@ -244,6 +288,8 @@ export class CommandAdapt {
|
||||
}
|
||||
|
||||
public rowFlex(payload: RowFlex) {
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
if (isReadonly) return
|
||||
const { startIndex, endIndex } = this.range.getRange()
|
||||
if (!~startIndex && !~endIndex) return
|
||||
const pageNo = this.draw.getPageNo()
|
||||
@@ -268,6 +314,8 @@ export class CommandAdapt {
|
||||
}
|
||||
|
||||
public rowMargin(payload: number) {
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
if (isReadonly) return
|
||||
const { startIndex, endIndex } = this.range.getRange()
|
||||
if (!~startIndex && !~endIndex) return
|
||||
const pageNo = this.draw.getPageNo()
|
||||
@@ -292,6 +340,8 @@ export class CommandAdapt {
|
||||
}
|
||||
|
||||
public insertTable(row: number, col: number) {
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
if (isReadonly) return
|
||||
const { startIndex, endIndex } = this.range.getRange()
|
||||
if (!~startIndex && !~endIndex) return
|
||||
const elementList = this.draw.getElementList()
|
||||
@@ -341,6 +391,8 @@ export class CommandAdapt {
|
||||
}
|
||||
|
||||
public insertTableTopRow() {
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
if (isReadonly) return
|
||||
const positionContext = this.position.getPositionContext()
|
||||
if (!positionContext.isTable) return
|
||||
const { index, trIndex, tableId } = positionContext
|
||||
@@ -403,6 +455,8 @@ export class CommandAdapt {
|
||||
}
|
||||
|
||||
public insertTableBottomRow() {
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
if (isReadonly) return
|
||||
const positionContext = this.position.getPositionContext()
|
||||
if (!positionContext.isTable) return
|
||||
const { index, trIndex, tableId } = positionContext
|
||||
@@ -468,6 +522,8 @@ export class CommandAdapt {
|
||||
}
|
||||
|
||||
public insertTableLeftCol() {
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
if (isReadonly) return
|
||||
const positionContext = this.position.getPositionContext()
|
||||
if (!positionContext.isTable) return
|
||||
const { index, tdIndex, tableId } = positionContext
|
||||
@@ -524,6 +580,8 @@ export class CommandAdapt {
|
||||
}
|
||||
|
||||
public insertTableRightCol() {
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
if (isReadonly) return
|
||||
const positionContext = this.position.getPositionContext()
|
||||
if (!positionContext.isTable) return
|
||||
const { index, tdIndex, tableId } = positionContext
|
||||
@@ -580,6 +638,8 @@ export class CommandAdapt {
|
||||
}
|
||||
|
||||
public deleteTableRow() {
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
if (isReadonly) return
|
||||
const positionContext = this.position.getPositionContext()
|
||||
if (!positionContext.isTable) return
|
||||
const { index, trIndex } = positionContext
|
||||
@@ -631,6 +691,8 @@ export class CommandAdapt {
|
||||
}
|
||||
|
||||
public deleteTableCol() {
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
if (isReadonly) return
|
||||
const positionContext = this.position.getPositionContext()
|
||||
if (!positionContext.isTable) return
|
||||
const { index, tdIndex, trIndex } = positionContext
|
||||
@@ -687,6 +749,8 @@ export class CommandAdapt {
|
||||
}
|
||||
|
||||
public deleteTable() {
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
if (isReadonly) return
|
||||
const positionContext = this.position.getPositionContext()
|
||||
if (!positionContext.isTable) return
|
||||
const originalElementList = this.draw.getOriginalElementList()
|
||||
@@ -702,6 +766,8 @@ export class CommandAdapt {
|
||||
}
|
||||
|
||||
public mergeTableCell() {
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
if (isReadonly) return
|
||||
const positionContext = this.position.getPositionContext()
|
||||
if (!positionContext.isTable) return
|
||||
const { isCrossRowCol, startTdIndex, endTdIndex, startTrIndex, endTrIndex } = this.range.getRange()
|
||||
@@ -809,6 +875,8 @@ export class CommandAdapt {
|
||||
}
|
||||
|
||||
public cancelMergeTableCell() {
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
if (isReadonly) return
|
||||
const positionContext = this.position.getPositionContext()
|
||||
if (!positionContext.isTable) return
|
||||
const { index, tdIndex, trIndex } = positionContext
|
||||
@@ -869,6 +937,8 @@ export class CommandAdapt {
|
||||
}
|
||||
|
||||
public hyperlink(payload: IElement) {
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
if (isReadonly) return
|
||||
const { startIndex, endIndex } = this.range.getRange()
|
||||
if (!~startIndex && !~endIndex) return
|
||||
const elementList = this.draw.getElementList()
|
||||
@@ -893,6 +963,8 @@ export class CommandAdapt {
|
||||
}
|
||||
|
||||
public separator(payload: number[]) {
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
if (isReadonly) return
|
||||
const { startIndex, endIndex } = this.range.getRange()
|
||||
if (!~startIndex && !~endIndex) return
|
||||
const elementList = this.draw.getElementList()
|
||||
@@ -930,6 +1002,8 @@ export class CommandAdapt {
|
||||
}
|
||||
|
||||
public addWatermark(payload: IWatermark) {
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
if (isReadonly) return
|
||||
const options = this.draw.getOptions()
|
||||
const { color, size, opacity, font } = defaultWatermarkOption
|
||||
options.watermark.data = payload.data
|
||||
@@ -944,6 +1018,8 @@ export class CommandAdapt {
|
||||
}
|
||||
|
||||
public deleteWatermark() {
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
if (isReadonly) return
|
||||
const options = this.draw.getOptions()
|
||||
if (options.watermark && options.watermark.data) {
|
||||
options.watermark = { ...defaultWatermarkOption }
|
||||
@@ -955,6 +1031,8 @@ export class CommandAdapt {
|
||||
}
|
||||
|
||||
public image(payload: IDrawImagePayload) {
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
if (isReadonly) return
|
||||
const { startIndex, endIndex } = this.range.getRange()
|
||||
if (!~startIndex && !~endIndex) return
|
||||
const elementList = this.draw.getElementList()
|
||||
@@ -1102,6 +1180,8 @@ export class CommandAdapt {
|
||||
}
|
||||
|
||||
public insertElementList(payload: IElement[]) {
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
if (isReadonly) return
|
||||
if (!payload.length) return
|
||||
const { startIndex, endIndex } = this.range.getRange()
|
||||
if (!~startIndex && !~endIndex) return
|
||||
|
||||
@@ -16,6 +16,7 @@ interface IRenderPayload {
|
||||
|
||||
export class ContextMenu {
|
||||
|
||||
private draw: Draw
|
||||
private command: Command
|
||||
private range: RangeManager
|
||||
private position: Position
|
||||
@@ -25,6 +26,7 @@ export class ContextMenu {
|
||||
private contextMenuRelationShip: Map<HTMLDivElement, HTMLDivElement>
|
||||
|
||||
constructor(draw: Draw, command: Command) {
|
||||
this.draw = draw
|
||||
this.command = command
|
||||
this.range = draw.getRange()
|
||||
this.position = draw.getPosition()
|
||||
@@ -81,6 +83,8 @@ export class ContextMenu {
|
||||
}
|
||||
|
||||
private _getContext(): IContextMenuContext {
|
||||
// 是否是只读模式
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
const { isCrossRowCol: crossRowCol, startIndex, endIndex } = this.range.getRange()
|
||||
// 是否存在焦点
|
||||
const editorTextFocus = !!(~startIndex || ~endIndex)
|
||||
@@ -92,6 +96,7 @@ export class ContextMenu {
|
||||
// 是否存在跨行/列
|
||||
const isCrossRowCol = isInTable && !!crossRowCol
|
||||
return {
|
||||
isReadonly,
|
||||
editorHasSelection,
|
||||
editorTextFocus,
|
||||
isInTable,
|
||||
|
||||
@@ -6,7 +6,7 @@ export const globalMenus: IRegisterContextMenu[] = [
|
||||
name: '剪切',
|
||||
shortCut: 'Ctrl + X',
|
||||
when: (payload) => {
|
||||
return payload.editorHasSelection
|
||||
return !payload.isReadonly && payload.editorHasSelection
|
||||
},
|
||||
callback: (command: Command) => {
|
||||
command.executeCut()
|
||||
@@ -26,7 +26,7 @@ export const globalMenus: IRegisterContextMenu[] = [
|
||||
name: '粘贴',
|
||||
shortCut: 'Ctrl + V',
|
||||
when: (payload) => {
|
||||
return payload.editorTextFocus
|
||||
return !payload.isReadonly && payload.editorTextFocus
|
||||
},
|
||||
callback: (command: Command) => {
|
||||
command.executePaste()
|
||||
|
||||
@@ -9,7 +9,7 @@ export const tableMenus: IRegisterContextMenu[] = [
|
||||
name: '插入行列',
|
||||
icon: 'insert-row-col',
|
||||
when: (payload) => {
|
||||
return payload.isInTable
|
||||
return !payload.isReadonly && payload.isInTable
|
||||
},
|
||||
childMenus: [
|
||||
{
|
||||
@@ -50,7 +50,7 @@ export const tableMenus: IRegisterContextMenu[] = [
|
||||
name: '删除行列',
|
||||
icon: 'delete-row-col',
|
||||
when: (payload) => {
|
||||
return payload.isInTable
|
||||
return !payload.isReadonly && payload.isInTable
|
||||
},
|
||||
childMenus: [
|
||||
{
|
||||
@@ -83,7 +83,7 @@ export const tableMenus: IRegisterContextMenu[] = [
|
||||
name: '合并单元格',
|
||||
icon: 'merge-cell',
|
||||
when: (payload) => {
|
||||
return payload.isCrossRowCol
|
||||
return !payload.isReadonly && payload.isCrossRowCol
|
||||
},
|
||||
callback: (command: Command) => {
|
||||
command.executeMergeTableCell()
|
||||
@@ -93,7 +93,7 @@ export const tableMenus: IRegisterContextMenu[] = [
|
||||
name: '取消合并',
|
||||
icon: 'merge-cancel-cell',
|
||||
when: (payload) => {
|
||||
return payload.isInTable
|
||||
return !payload.isReadonly && payload.isInTable
|
||||
},
|
||||
callback: (command: Command) => {
|
||||
command.executeCancelMergeTableCell()
|
||||
|
||||
@@ -35,6 +35,7 @@ export class Cursor {
|
||||
}
|
||||
|
||||
public drawCursor() {
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
const cursorPosition = this.position.getCursorPosition()
|
||||
if (!cursorPosition) return
|
||||
// 设置光标代理
|
||||
@@ -60,7 +61,7 @@ export class Cursor {
|
||||
// 模拟光标显示
|
||||
this.cursorDom.style.left = `${cursorLeft}px`
|
||||
this.cursorDom.style.top = `${cursorTop}px`
|
||||
this.cursorDom.style.display = 'block'
|
||||
this.cursorDom.style.display = isReadonly ? 'none' : 'block'
|
||||
this.cursorDom.style.height = `${cursorHeight}px`
|
||||
setTimeout(() => {
|
||||
this.cursorDom.classList.add('cursor--animation')
|
||||
|
||||
@@ -33,6 +33,7 @@ import { SubscriptParticle } from "./particle/Subscript"
|
||||
import { SeparatorParticle } from "./particle/Separator"
|
||||
import { PageBreakParticle } from "./particle/PageBreak"
|
||||
import { Watermark } from "./frame/Watermark"
|
||||
import { EditorMode } from "../../dataset/enum/Editor"
|
||||
|
||||
export class Draw {
|
||||
|
||||
@@ -41,6 +42,7 @@ export class Draw {
|
||||
private pageList: HTMLCanvasElement[]
|
||||
private ctxList: CanvasRenderingContext2D[]
|
||||
private pageNo: number
|
||||
private mode: EditorMode
|
||||
private options: Required<IEditorOption>
|
||||
private position: Position
|
||||
private elementList: IElement[]
|
||||
@@ -85,6 +87,7 @@ export class Draw {
|
||||
this.pageList = []
|
||||
this.ctxList = []
|
||||
this.pageNo = 0
|
||||
this.mode = options.defaultMode
|
||||
this.options = options
|
||||
this.elementList = elementList
|
||||
this.listener = listener
|
||||
@@ -131,6 +134,18 @@ export class Draw {
|
||||
this.render({ isSetCursor: false })
|
||||
}
|
||||
|
||||
public getMode(): EditorMode {
|
||||
return this.mode
|
||||
}
|
||||
|
||||
public setMode(payload: EditorMode) {
|
||||
this.mode = payload
|
||||
}
|
||||
|
||||
public isReadonly() {
|
||||
return this.mode === EditorMode.READONLY
|
||||
}
|
||||
|
||||
public getWidth(): number {
|
||||
return Math.floor(this.options.width * this.options.scale)
|
||||
}
|
||||
@@ -650,7 +665,9 @@ export class Draw {
|
||||
} else if (element.type === ElementType.SEPARATOR) {
|
||||
this.separatorParticle.render(ctx, element, x, y)
|
||||
} else if (element.type === ElementType.PAGE_BREAK) {
|
||||
this.pageBreakParticle.render(ctx, element, x, y)
|
||||
if (this.mode !== EditorMode.CLEAN) {
|
||||
this.pageBreakParticle.render(ctx, element, x, y)
|
||||
}
|
||||
} else {
|
||||
this.textParticle.record(ctx, element, x, y + offsetY)
|
||||
}
|
||||
|
||||
@@ -146,6 +146,7 @@ export class CanvasEvent {
|
||||
|
||||
public mousedown(evt: MouseEvent) {
|
||||
if (evt.button === MouseEventButton.RIGHT) return
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
const target = evt.target as HTMLDivElement
|
||||
const pageIndex = target.dataset.index
|
||||
// 设置pageNo
|
||||
@@ -207,12 +208,12 @@ export class CanvasEvent {
|
||||
const curElement = elementList[curIndex]
|
||||
// 图片尺寸拖拽组件
|
||||
this.imageParticle.clearResizer()
|
||||
if (isDirectHitImage) {
|
||||
if (isDirectHitImage && !isReadonly) {
|
||||
this.imageParticle.drawResizer(curElement, positionList[curIndex])
|
||||
}
|
||||
// 表格工具组件
|
||||
this.tableTool.dispose()
|
||||
if (isTable) {
|
||||
if (isTable && !isReadonly) {
|
||||
const originalElementList = this.draw.getOriginalElementList()
|
||||
const originalPositionList = this.position.getOriginalPositionList()
|
||||
this.tableTool.render(originalElementList[index], originalPositionList[index])
|
||||
@@ -232,6 +233,7 @@ export class CanvasEvent {
|
||||
}
|
||||
|
||||
public keydown(evt: KeyboardEvent) {
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
const cursorPosition = this.position.getCursorPosition()
|
||||
if (!cursorPosition) return
|
||||
const elementList = this.draw.getElementList()
|
||||
@@ -240,6 +242,7 @@ export class CanvasEvent {
|
||||
const { startIndex, endIndex } = this.range.getRange()
|
||||
const isCollapsed = startIndex === endIndex
|
||||
if (evt.key === KeyMap.Backspace) {
|
||||
if (isReadonly) return
|
||||
// 判断是否允许删除
|
||||
if (elementList[index].value === ZERO && index === 0) {
|
||||
evt.preventDefault()
|
||||
@@ -254,6 +257,7 @@ export class CanvasEvent {
|
||||
this.range.setRange(curIndex, curIndex)
|
||||
this.draw.render({ curIndex })
|
||||
} else if (evt.key === KeyMap.Delete) {
|
||||
if (isReadonly) return
|
||||
if (!isCollapsed) {
|
||||
elementList.splice(startIndex + 1, endIndex - startIndex)
|
||||
} else {
|
||||
@@ -263,6 +267,7 @@ export class CanvasEvent {
|
||||
this.range.setRange(curIndex, curIndex)
|
||||
this.draw.render({ curIndex })
|
||||
} else if (evt.key === KeyMap.Enter) {
|
||||
if (isReadonly) return
|
||||
// 表格需要上下文信息
|
||||
const positionContext = this.position.getPositionContext()
|
||||
let restArg = {}
|
||||
@@ -283,6 +288,7 @@ export class CanvasEvent {
|
||||
this.range.setRange(curIndex, curIndex)
|
||||
this.draw.render({ curIndex })
|
||||
} else if (evt.key === KeyMap.Left) {
|
||||
if (isReadonly) return
|
||||
if (index > 0) {
|
||||
const curIndex = index - 1
|
||||
this.range.setRange(curIndex, curIndex)
|
||||
@@ -293,6 +299,7 @@ export class CanvasEvent {
|
||||
})
|
||||
}
|
||||
} else if (evt.key === KeyMap.Right) {
|
||||
if (isReadonly) return
|
||||
if (index < position.length - 1) {
|
||||
const curIndex = index + 1
|
||||
this.range.setRange(curIndex, curIndex)
|
||||
@@ -303,6 +310,7 @@ export class CanvasEvent {
|
||||
})
|
||||
}
|
||||
} else if (evt.key === KeyMap.Up || evt.key === KeyMap.Down) {
|
||||
if (isReadonly) return
|
||||
const { rowNo, index, coordinate: { leftTop, rightTop } } = cursorPosition
|
||||
if ((evt.key === KeyMap.Up && rowNo !== 0) || (evt.key === KeyMap.Down && rowNo !== this.draw.getRowCount())) {
|
||||
// 下一个光标点所在行位置集合
|
||||
@@ -344,18 +352,22 @@ export class CanvasEvent {
|
||||
})
|
||||
}
|
||||
} else if (evt.ctrlKey && evt.key === KeyMap.Z) {
|
||||
if (isReadonly) return
|
||||
this.historyManager.undo()
|
||||
evt.preventDefault()
|
||||
} else if (evt.ctrlKey && evt.key === KeyMap.Y) {
|
||||
if (isReadonly) return
|
||||
this.historyManager.redo()
|
||||
evt.preventDefault()
|
||||
} else if (evt.ctrlKey && evt.key === KeyMap.C) {
|
||||
this.copy()
|
||||
} else if (evt.ctrlKey && evt.key === KeyMap.X) {
|
||||
if (isReadonly) return
|
||||
this.cut()
|
||||
} else if (evt.ctrlKey && evt.key === KeyMap.A) {
|
||||
this.selectAll()
|
||||
} else if (evt.ctrlKey && evt.key === KeyMap.S) {
|
||||
if (isReadonly) return
|
||||
const saved = this.listener.saved
|
||||
if (saved) {
|
||||
saved(this.save())
|
||||
@@ -365,6 +377,8 @@ export class CanvasEvent {
|
||||
}
|
||||
|
||||
public input(data: string) {
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
if (isReadonly) return
|
||||
if (!this.cursor) return
|
||||
const cursorPosition = this.position.getCursorPosition()
|
||||
if (!data || !cursorPosition || this.isCompositing) return
|
||||
@@ -423,6 +437,8 @@ export class CanvasEvent {
|
||||
}
|
||||
|
||||
public cut() {
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
if (isReadonly) return
|
||||
const { startIndex, endIndex } = this.range.getRange()
|
||||
const elementList = this.draw.getElementList()
|
||||
if (startIndex !== endIndex) {
|
||||
|
||||
@@ -10,3 +10,9 @@ export enum EditorContext {
|
||||
PAGE = 'page',
|
||||
TABLE = 'table'
|
||||
}
|
||||
|
||||
export enum EditorMode {
|
||||
EDIT = 'edit',
|
||||
CLEAN = 'clean',
|
||||
READONLY = 'readonly'
|
||||
}
|
||||
+3
-1
@@ -13,7 +13,7 @@ import { globalMenus } from './core/contextmenu/menus/GlobalMenus'
|
||||
import { ContextMenu } from './core/contextmenu/ContextMenu'
|
||||
import { tableMenus } from './core/contextmenu/menus/tableMenus'
|
||||
import { IContextMenuContext, IRegisterContextMenu } from './interface/contextmenu/ContextMenu'
|
||||
import { EditorComponent } from './dataset/enum/Editor'
|
||||
import { EditorComponent, EditorMode } from './dataset/enum/Editor'
|
||||
import { EDITOR_COMPONENT } from './dataset/constant/Editor'
|
||||
import { IHeader } from './interface/Header'
|
||||
import { IWatermark } from './interface/Watermark'
|
||||
@@ -36,6 +36,7 @@ export default class Editor {
|
||||
...options.watermark
|
||||
}
|
||||
const editorOptions: Required<IEditorOption> = {
|
||||
defaultMode: EditorMode.EDIT,
|
||||
defaultType: 'TEXT',
|
||||
defaultFont: 'Yahei',
|
||||
defaultSize: 16,
|
||||
@@ -92,6 +93,7 @@ export default class Editor {
|
||||
export {
|
||||
Editor,
|
||||
RowFlex,
|
||||
EditorMode,
|
||||
ElementType,
|
||||
EditorComponent,
|
||||
EDITOR_COMPONENT
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { IElement } from ".."
|
||||
import { EditorMode } from "../dataset/enum/Editor"
|
||||
import { IHeader } from "./Header"
|
||||
import { IWatermark } from "./Watermark"
|
||||
|
||||
export interface IEditorOption {
|
||||
defaultMode?: EditorMode;
|
||||
defaultType?: string;
|
||||
defaultFont?: string;
|
||||
defaultSize?: number;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
export interface IContextMenuContext {
|
||||
isReadonly: boolean;
|
||||
editorHasSelection: boolean;
|
||||
editorTextFocus: boolean;
|
||||
isInTable: boolean;
|
||||
|
||||
+31
-1
@@ -1,6 +1,6 @@
|
||||
import './style.css'
|
||||
import prism from "prismjs"
|
||||
import Editor, { ElementType, IElement, RowFlex } from './editor'
|
||||
import Editor, { EditorMode, ElementType, IElement, RowFlex } from './editor'
|
||||
import { Dialog } from './components/dialog/Dialog'
|
||||
import { formatPrismToken } from './utils/prism'
|
||||
|
||||
@@ -623,6 +623,36 @@ window.onload = function () {
|
||||
instance.command.executePageScaleAdd()
|
||||
}
|
||||
|
||||
let modeIndex = 0
|
||||
const modeList = [{
|
||||
mode: EditorMode.EDIT,
|
||||
name: '编辑模式'
|
||||
}, {
|
||||
mode: EditorMode.CLEAN,
|
||||
name: '清洁模式'
|
||||
}, {
|
||||
mode: EditorMode.READONLY,
|
||||
name: '只读模式'
|
||||
}]
|
||||
const modeElement = document.querySelector<HTMLDivElement>('.editor-mode')!
|
||||
modeElement.onclick = function () {
|
||||
// 模式选择循环
|
||||
modeIndex === 2 ? modeIndex = 0 : modeIndex++
|
||||
// 设置模式
|
||||
const { name, mode } = modeList[modeIndex]
|
||||
modeElement.innerText = name
|
||||
instance.command.executeMode(mode)
|
||||
// 设置菜单栏权限视觉反馈
|
||||
const isReadonly = mode === EditorMode.READONLY
|
||||
const enableMenuList = ['search', 'print']
|
||||
document.querySelectorAll<HTMLDivElement>('.menu-item>div').forEach(dom => {
|
||||
const menu = dom.dataset.menu
|
||||
isReadonly && (!menu || !enableMenuList.includes(menu))
|
||||
? dom.classList.add('disable')
|
||||
: dom.classList.remove('disable')
|
||||
})
|
||||
}
|
||||
|
||||
// 内部事件监听
|
||||
instance.listener.rangeStyleChange = function (payload) {
|
||||
// 控件类型
|
||||
|
||||
+7
-1
@@ -167,7 +167,8 @@ ul {
|
||||
}
|
||||
|
||||
.menu-item__undo.no-allow,
|
||||
.menu-item__redo.no-allow {
|
||||
.menu-item__redo.no-allow,
|
||||
.menu-item>div.disable {
|
||||
color: #c0c4cc;
|
||||
cursor: not-allowed;
|
||||
opacity: 0.4;
|
||||
@@ -564,3 +565,8 @@ ul {
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.footer .editor-mode {
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
Reference in New Issue
Block a user