feat: add list element
This commit is contained in:
+34
@@ -152,6 +152,40 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="menu-item__list">
|
||||||
|
<i title="列表"></i>
|
||||||
|
<div class="options">
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<label>取消列表</label>
|
||||||
|
</li>
|
||||||
|
<li data-list-type="ol" data-list-style='decimal'>
|
||||||
|
<label>有序列表:</label>
|
||||||
|
<ol>
|
||||||
|
<li>________</li>
|
||||||
|
</ol>
|
||||||
|
</li>
|
||||||
|
<li data-list-type="ul" data-list-style='disc'>
|
||||||
|
<label>实心圆点列表:</label>
|
||||||
|
<ul style="list-style-type: disc;">
|
||||||
|
<li>________</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li data-list-type="ul" data-list-style='circle'>
|
||||||
|
<label>空心圆点列表:</label>
|
||||||
|
<ul style="list-style-type: circle;">
|
||||||
|
<li>________</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li data-list-type="ul" data-list-style='square'>
|
||||||
|
<label>空心方块列表:</label>
|
||||||
|
<ul style="list-style-type: square;">
|
||||||
|
<li>________</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="menu-divider"></div>
|
<div class="menu-divider"></div>
|
||||||
<div class="menu-item">
|
<div class="menu-item">
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path fill="#3D4757" d="M7 12h7v1H7zm0-5h7v1H7zm0-5h7v1H7zM3 4V2H2V1h2v3h1v1H2V4h1z"/><path d="M2 6h3v1H2V6zm0 3h3v1H2V9z" fill="#4F4F4F"/><path fill="#3D4757" fill-rule="nonzero" d="M4.5 6L5 7l-2.5 3L2 9z"/><path d="M4 14l-1-2H2v-1h3v1H4l1 2v1H2v-1h2z" fill="#3D4757"/></g></svg>
|
||||||
|
After Width: | Height: | Size: 398 B |
@@ -1,4 +1,4 @@
|
|||||||
import { IElement, ImageDisplay, INavigateInfo, TableBorder, TitleLevel, VerticalAlign } from '../..'
|
import { IElement, ImageDisplay, INavigateInfo, ListStyle, ListType, TableBorder, TitleLevel, VerticalAlign } from '../..'
|
||||||
import { EditorMode, PageMode, PaperDirection } from '../../dataset/enum/Editor'
|
import { EditorMode, PageMode, PaperDirection } from '../../dataset/enum/Editor'
|
||||||
import { RowFlex } from '../../dataset/enum/Row'
|
import { RowFlex } from '../../dataset/enum/Row'
|
||||||
import { IDrawImagePayload, IPainterOptions } from '../../interface/Draw'
|
import { IDrawImagePayload, IPainterOptions } from '../../interface/Draw'
|
||||||
@@ -34,6 +34,7 @@ export class Command {
|
|||||||
private static color: CommandAdapt['color']
|
private static color: CommandAdapt['color']
|
||||||
private static highlight: CommandAdapt['highlight']
|
private static highlight: CommandAdapt['highlight']
|
||||||
private static title: CommandAdapt['title']
|
private static title: CommandAdapt['title']
|
||||||
|
private static list: CommandAdapt['list']
|
||||||
private static left: CommandAdapt['rowFlex']
|
private static left: CommandAdapt['rowFlex']
|
||||||
private static center: CommandAdapt['rowFlex']
|
private static center: CommandAdapt['rowFlex']
|
||||||
private static right: CommandAdapt['rowFlex']
|
private static right: CommandAdapt['rowFlex']
|
||||||
@@ -111,6 +112,7 @@ export class Command {
|
|||||||
Command.color = adapt.color.bind(adapt)
|
Command.color = adapt.color.bind(adapt)
|
||||||
Command.highlight = adapt.highlight.bind(adapt)
|
Command.highlight = adapt.highlight.bind(adapt)
|
||||||
Command.title = adapt.title.bind(adapt)
|
Command.title = adapt.title.bind(adapt)
|
||||||
|
Command.list = adapt.list.bind(adapt)
|
||||||
Command.left = adapt.rowFlex.bind(adapt)
|
Command.left = adapt.rowFlex.bind(adapt)
|
||||||
Command.center = adapt.rowFlex.bind(adapt)
|
Command.center = adapt.rowFlex.bind(adapt)
|
||||||
Command.right = adapt.rowFlex.bind(adapt)
|
Command.right = adapt.rowFlex.bind(adapt)
|
||||||
@@ -262,7 +264,7 @@ export class Command {
|
|||||||
return Command.highlight(payload)
|
return Command.highlight(payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 标题、对齐方式
|
// 标题、对齐方式、列表
|
||||||
public executeTitle(payload: TitleLevel | null) {
|
public executeTitle(payload: TitleLevel | null) {
|
||||||
return Command.title(payload)
|
return Command.title(payload)
|
||||||
}
|
}
|
||||||
@@ -287,6 +289,10 @@ export class Command {
|
|||||||
return Command.rowMargin(payload)
|
return Command.rowMargin(payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public executeList(listType: ListType | null, listStyle?: ListStyle) {
|
||||||
|
return Command.list(listType, listStyle)
|
||||||
|
}
|
||||||
|
|
||||||
// 表格、图片上传、超链接、搜索、打印
|
// 表格、图片上传、超链接、搜索、打印
|
||||||
public executeInsertTable(row: number, col: number) {
|
public executeInsertTable(row: number, col: number) {
|
||||||
return Command.insertTable(row, col)
|
return Command.insertTable(row, col)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { ControlComponent, ImageDisplay } from '../../dataset/enum/Control'
|
|||||||
import { EditorContext, EditorMode, PageMode, PaperDirection } from '../../dataset/enum/Editor'
|
import { EditorContext, EditorMode, PageMode, PaperDirection } from '../../dataset/enum/Editor'
|
||||||
import { ElementType } from '../../dataset/enum/Element'
|
import { ElementType } from '../../dataset/enum/Element'
|
||||||
import { ElementStyleKey } from '../../dataset/enum/ElementStyle'
|
import { ElementStyleKey } from '../../dataset/enum/ElementStyle'
|
||||||
|
import { ListStyle, ListType } from '../../dataset/enum/List'
|
||||||
import { RowFlex } from '../../dataset/enum/Row'
|
import { RowFlex } from '../../dataset/enum/Row'
|
||||||
import { TableBorder } from '../../dataset/enum/table/Table'
|
import { TableBorder } from '../../dataset/enum/table/Table'
|
||||||
import { TitleLevel } from '../../dataset/enum/Title'
|
import { TitleLevel } from '../../dataset/enum/Title'
|
||||||
@@ -107,9 +108,9 @@ export class CommandAdapt {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (!isCollapsed) {
|
if (!isCollapsed) {
|
||||||
elementList.splice(startIndex + 1, endIndex - startIndex)
|
this.draw.spliceElementList(elementList, startIndex + 1, endIndex - startIndex)
|
||||||
} else {
|
} else {
|
||||||
elementList.splice(startIndex, 1)
|
this.draw.spliceElementList(elementList, startIndex, 1)
|
||||||
}
|
}
|
||||||
const curIndex = isCollapsed ? startIndex - 1 : startIndex
|
const curIndex = isCollapsed ? startIndex - 1 : startIndex
|
||||||
this.range.setRange(curIndex, curIndex)
|
this.range.setRange(curIndex, curIndex)
|
||||||
@@ -386,25 +387,12 @@ export class CommandAdapt {
|
|||||||
if (isReadonly) return
|
if (isReadonly) return
|
||||||
const { startIndex, endIndex } = this.range.getRange()
|
const { startIndex, endIndex } = this.range.getRange()
|
||||||
if (!~startIndex && !~endIndex) return
|
if (!~startIndex && !~endIndex) return
|
||||||
// 需要改变的元素列表
|
|
||||||
let changeElementList: IElement[] = []
|
|
||||||
const elementList = this.draw.getElementList()
|
const elementList = this.draw.getElementList()
|
||||||
if (startIndex === endIndex) {
|
// 需要改变的元素列表
|
||||||
// 选区行信息
|
const changeElementList = startIndex === endIndex
|
||||||
const rangeRow = this.range.getRangeParagraph()
|
? this.range.getRangeElementList()
|
||||||
if (!rangeRow) return
|
: elementList.slice(startIndex + 1, endIndex + 1)
|
||||||
const positionList = this.position.getPositionList()
|
if (!changeElementList || !changeElementList.length) return
|
||||||
for (let p = 0; p < positionList.length; p++) {
|
|
||||||
const position = positionList[p]
|
|
||||||
const rowArray = rangeRow.get(position.pageNo)
|
|
||||||
if (!rowArray) continue
|
|
||||||
if (rowArray.includes(position.rowNo)) {
|
|
||||||
changeElementList.push(elementList[p])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
changeElementList = elementList.slice(startIndex + 1, endIndex + 1)
|
|
||||||
}
|
|
||||||
// 设置值
|
// 设置值
|
||||||
const titleId = getUUID()
|
const titleId = getUUID()
|
||||||
const titleOptions = this.draw.getOptions().title
|
const titleOptions = this.draw.getOptions().title
|
||||||
@@ -432,6 +420,35 @@ export class CommandAdapt {
|
|||||||
this.draw.render({ curIndex, isSetCursor })
|
this.draw.render({ curIndex, isSetCursor })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public list(listType: ListType | null, listStyle?: ListStyle) {
|
||||||
|
const isReadonly = this.draw.isReadonly()
|
||||||
|
if (isReadonly) return
|
||||||
|
const { startIndex, endIndex } = this.range.getRange()
|
||||||
|
if (!~startIndex && !~endIndex) return
|
||||||
|
// 需要改变的元素列表
|
||||||
|
const changeElementList = this.range.getRangeElementList()
|
||||||
|
if (!changeElementList || !changeElementList.length) return
|
||||||
|
// 设置值
|
||||||
|
const listId = getUUID()
|
||||||
|
changeElementList.forEach(el => {
|
||||||
|
if (listType) {
|
||||||
|
el.listId = listId
|
||||||
|
el.listType = listType
|
||||||
|
el.listStyle = listStyle
|
||||||
|
} else {
|
||||||
|
if (el.listId) {
|
||||||
|
delete el.listId
|
||||||
|
delete el.listType
|
||||||
|
delete el.listStyle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// 光标定位
|
||||||
|
const isSetCursor = startIndex === endIndex
|
||||||
|
const curIndex = isSetCursor ? endIndex : startIndex
|
||||||
|
this.draw.render({ curIndex, isSetCursor })
|
||||||
|
}
|
||||||
|
|
||||||
public rowFlex(payload: RowFlex) {
|
public rowFlex(payload: RowFlex) {
|
||||||
const isReadonly = this.draw.isReadonly()
|
const isReadonly = this.draw.isReadonly()
|
||||||
if (isReadonly) return
|
if (isReadonly) return
|
||||||
@@ -528,9 +545,9 @@ export class CommandAdapt {
|
|||||||
})
|
})
|
||||||
const curIndex = startIndex + 1
|
const curIndex = startIndex + 1
|
||||||
if (startIndex === endIndex) {
|
if (startIndex === endIndex) {
|
||||||
elementList.splice(curIndex, 0, element)
|
this.draw.spliceElementList(elementList, curIndex, 0, element)
|
||||||
} else {
|
} else {
|
||||||
elementList.splice(curIndex, endIndex - startIndex, element)
|
this.draw.spliceElementList(elementList, curIndex, endIndex - startIndex, element)
|
||||||
}
|
}
|
||||||
this.range.setRange(curIndex, curIndex)
|
this.range.setRange(curIndex, curIndex)
|
||||||
this.draw.render({ curIndex, isSetCursor: false })
|
this.draw.render({ curIndex, isSetCursor: false })
|
||||||
@@ -1140,9 +1157,9 @@ export class CommandAdapt {
|
|||||||
if (!newElementList) return
|
if (!newElementList) return
|
||||||
const start = startIndex + 1
|
const start = startIndex + 1
|
||||||
if (startIndex === endIndex) {
|
if (startIndex === endIndex) {
|
||||||
elementList.splice(start, 0, ...newElementList)
|
this.draw.spliceElementList(elementList, start, 0, ...newElementList)
|
||||||
} else {
|
} else {
|
||||||
elementList.splice(start, endIndex - startIndex, ...newElementList)
|
this.draw.spliceElementList(elementList, start, endIndex - startIndex, ...newElementList)
|
||||||
}
|
}
|
||||||
const curIndex = start + newElementList.length - 1
|
const curIndex = start + newElementList.length - 1
|
||||||
this.range.setRange(curIndex, curIndex)
|
this.range.setRange(curIndex, curIndex)
|
||||||
@@ -1192,7 +1209,7 @@ export class CommandAdapt {
|
|||||||
const elementList = this.draw.getElementList()
|
const elementList = this.draw.getElementList()
|
||||||
const [leftIndex, rightIndex] = hyperRange
|
const [leftIndex, rightIndex] = hyperRange
|
||||||
// 删除元素
|
// 删除元素
|
||||||
elementList.splice(leftIndex, rightIndex - leftIndex + 1)
|
this.draw.spliceElementList(elementList, leftIndex, rightIndex - leftIndex + 1)
|
||||||
this.draw.getHyperlinkParticle().clearHyperlinkPopup()
|
this.draw.getHyperlinkParticle().clearHyperlinkPopup()
|
||||||
// 重置画布
|
// 重置画布
|
||||||
const newIndex = leftIndex - 1
|
const newIndex = leftIndex - 1
|
||||||
@@ -1268,10 +1285,10 @@ export class CommandAdapt {
|
|||||||
}
|
}
|
||||||
// 从行头增加分割线
|
// 从行头增加分割线
|
||||||
if (startIndex !== 0 && elementList[startIndex].value === ZERO) {
|
if (startIndex !== 0 && elementList[startIndex].value === ZERO) {
|
||||||
elementList.splice(startIndex, 1, newElement)
|
this.draw.spliceElementList(elementList, startIndex, 1, newElement)
|
||||||
curIndex = startIndex - 1
|
curIndex = startIndex - 1
|
||||||
} else {
|
} else {
|
||||||
elementList.splice(startIndex + 1, 0, newElement)
|
this.draw.spliceElementList(elementList, startIndex + 1, 0, newElement)
|
||||||
curIndex = startIndex
|
curIndex = startIndex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1339,9 +1356,9 @@ export class CommandAdapt {
|
|||||||
}
|
}
|
||||||
const curIndex = startIndex + 1
|
const curIndex = startIndex + 1
|
||||||
if (startIndex === endIndex) {
|
if (startIndex === endIndex) {
|
||||||
elementList.splice(curIndex, 0, element)
|
this.draw.spliceElementList(elementList, curIndex, 0, element)
|
||||||
} else {
|
} else {
|
||||||
elementList.splice(curIndex, endIndex - startIndex, element)
|
this.draw.spliceElementList(elementList, curIndex, endIndex - startIndex, element)
|
||||||
}
|
}
|
||||||
this.range.setRange(curIndex, curIndex)
|
this.range.setRange(curIndex, curIndex)
|
||||||
this.draw.render({ curIndex })
|
this.draw.render({ curIndex })
|
||||||
@@ -1411,7 +1428,7 @@ export class CommandAdapt {
|
|||||||
const curIndex = index + tableDiffCount
|
const curIndex = index + tableDiffCount
|
||||||
const tableElement = tableElementList[curIndex]
|
const tableElement = tableElementList[curIndex]
|
||||||
if (curGroupId === match.groupId) {
|
if (curGroupId === match.groupId) {
|
||||||
tableElementList.splice(curIndex, 1)
|
this.draw.spliceElementList(tableElementList, curIndex, 1)
|
||||||
tableDiffCount--
|
tableDiffCount--
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -1420,7 +1437,7 @@ export class CommandAdapt {
|
|||||||
if (p === 0) {
|
if (p === 0) {
|
||||||
tableElement.value = value
|
tableElement.value = value
|
||||||
} else {
|
} else {
|
||||||
tableElementList.splice(curIndex + p, 0, {
|
this.draw.spliceElementList(tableElementList, curIndex + p, 0, {
|
||||||
...tableElement,
|
...tableElement,
|
||||||
value
|
value
|
||||||
})
|
})
|
||||||
@@ -1440,7 +1457,7 @@ export class CommandAdapt {
|
|||||||
firstMatchIndex = m
|
firstMatchIndex = m
|
||||||
}
|
}
|
||||||
if (curGroupId === match.groupId) {
|
if (curGroupId === match.groupId) {
|
||||||
elementList.splice(curIndex, 1)
|
this.draw.spliceElementList(elementList, curIndex, 1)
|
||||||
pageDiffCount--
|
pageDiffCount--
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -1449,7 +1466,7 @@ export class CommandAdapt {
|
|||||||
if (p === 0) {
|
if (p === 0) {
|
||||||
element.value = value
|
element.value = value
|
||||||
} else {
|
} else {
|
||||||
elementList.splice(curIndex + p, 0, {
|
this.draw.spliceElementList(elementList, curIndex + p, 0, {
|
||||||
...element,
|
...element,
|
||||||
value
|
value
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -52,7 +52,8 @@ import { I18n } from '../i18n/I18n'
|
|||||||
import { ImageObserver } from '../observer/ImageObserver'
|
import { ImageObserver } from '../observer/ImageObserver'
|
||||||
import { Zone } from '../zone/Zone'
|
import { Zone } from '../zone/Zone'
|
||||||
import { Footer } from './frame/Footer'
|
import { Footer } from './frame/Footer'
|
||||||
import { INLINE_ELEMENT_TYPE } from '../../dataset/constant/Element'
|
import { EDITOR_ELEMENT_CONTEXT_ATTR, INLINE_ELEMENT_TYPE } from '../../dataset/constant/Element'
|
||||||
|
import { ListParticle } from './particle/ListParticle'
|
||||||
|
|
||||||
export class Draw {
|
export class Draw {
|
||||||
|
|
||||||
@@ -100,6 +101,7 @@ export class Draw {
|
|||||||
private subscriptParticle: SubscriptParticle
|
private subscriptParticle: SubscriptParticle
|
||||||
private checkboxParticle: CheckboxParticle
|
private checkboxParticle: CheckboxParticle
|
||||||
private blockParticle: BlockParticle
|
private blockParticle: BlockParticle
|
||||||
|
private listParticle: ListParticle
|
||||||
private control: Control
|
private control: Control
|
||||||
private workerManager: WorkerManager
|
private workerManager: WorkerManager
|
||||||
private scrollObserver: ScrollObserver
|
private scrollObserver: ScrollObserver
|
||||||
@@ -164,6 +166,7 @@ export class Draw {
|
|||||||
this.subscriptParticle = new SubscriptParticle()
|
this.subscriptParticle = new SubscriptParticle()
|
||||||
this.checkboxParticle = new CheckboxParticle(this)
|
this.checkboxParticle = new CheckboxParticle(this)
|
||||||
this.blockParticle = new BlockParticle(this)
|
this.blockParticle = new BlockParticle(this)
|
||||||
|
this.listParticle = new ListParticle(this)
|
||||||
this.control = new Control(this)
|
this.control = new Control(this)
|
||||||
|
|
||||||
this.scrollObserver = new ScrollObserver(this)
|
this.scrollObserver = new ScrollObserver(this)
|
||||||
@@ -435,6 +438,18 @@ export class Draw {
|
|||||||
return this.footerElementList
|
return this.footerElementList
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public formatElementContext(anchorElement: IElement, targetElement: IElement) {
|
||||||
|
for (let i = 0; i < EDITOR_ELEMENT_CONTEXT_ATTR.length; i++) {
|
||||||
|
const attr = EDITOR_ELEMENT_CONTEXT_ATTR[i]
|
||||||
|
const value = anchorElement[attr] as never
|
||||||
|
if (value !== undefined) {
|
||||||
|
targetElement[attr] = value
|
||||||
|
} else {
|
||||||
|
delete targetElement[attr]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public insertElementList(payload: IElement[]) {
|
public insertElementList(payload: IElement[]) {
|
||||||
if (!payload.length) return
|
if (!payload.length) return
|
||||||
const isPartRangeInControlOutside = this.control.isPartRangeInControlOutside()
|
const isPartRangeInControlOutside = this.control.isPartRangeInControlOutside()
|
||||||
@@ -455,18 +470,9 @@ export class Draw {
|
|||||||
const isCollapsed = startIndex === endIndex
|
const isCollapsed = startIndex === endIndex
|
||||||
const start = startIndex + 1
|
const start = startIndex + 1
|
||||||
if (!isCollapsed) {
|
if (!isCollapsed) {
|
||||||
elementList.splice(start, endIndex - startIndex)
|
this.spliceElementList(elementList, start, endIndex - startIndex)
|
||||||
}
|
|
||||||
const positionContext = this.position.getPositionContext()
|
|
||||||
for (let i = 0; i < payload.length; i++) {
|
|
||||||
const element = payload[i]
|
|
||||||
if (positionContext.isTable) {
|
|
||||||
element.tdId = positionContext.tdId
|
|
||||||
element.trId = positionContext.trId
|
|
||||||
element.tableId = positionContext.tableId
|
|
||||||
}
|
|
||||||
elementList.splice(start + i, 0, element)
|
|
||||||
}
|
}
|
||||||
|
this.spliceElementList(elementList, start, 0, ...payload)
|
||||||
curIndex = startIndex + payload.length
|
curIndex = startIndex + payload.length
|
||||||
}
|
}
|
||||||
if (~curIndex) {
|
if (~curIndex) {
|
||||||
@@ -477,6 +483,41 @@ export class Draw {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public spliceElementList(elementList: IElement[], start: number, deleteCount: number, ...items: IElement[]) {
|
||||||
|
if (deleteCount > 0) {
|
||||||
|
// 当最后元素与开始元素列表信息不一致时:清除当前列表信息
|
||||||
|
const endIndex = start + deleteCount - 1
|
||||||
|
const endElement = elementList[endIndex]
|
||||||
|
const endElementListId = endElement?.listId
|
||||||
|
if (endElementListId && elementList[start - 1]?.listId !== endElementListId) {
|
||||||
|
let startIndex = endIndex
|
||||||
|
while (startIndex < elementList.length) {
|
||||||
|
const curElement = elementList[startIndex]
|
||||||
|
if (curElement.listId !== endElementListId || curElement.value === ZERO) break
|
||||||
|
delete curElement.listId
|
||||||
|
delete curElement.listType
|
||||||
|
delete curElement.listStyle
|
||||||
|
startIndex++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (items.length) {
|
||||||
|
// 格式化新增数据
|
||||||
|
const endIndex = start + deleteCount - 1
|
||||||
|
const endElement = elementList[endIndex]
|
||||||
|
const endNextElement = elementList[endIndex + 1]
|
||||||
|
const anchorElement = endElement?.value === ZERO && endNextElement && endNextElement.value !== ZERO
|
||||||
|
? endNextElement
|
||||||
|
: endElement
|
||||||
|
if (anchorElement) {
|
||||||
|
for (let i = 0; i < items.length; i++) {
|
||||||
|
this.formatElementContext(anchorElement, items[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elementList.splice(start, deleteCount, ...items)
|
||||||
|
}
|
||||||
|
|
||||||
public getCanvasEvent(): CanvasEvent {
|
public getCanvasEvent(): CanvasEvent {
|
||||||
return this.canvasEvent
|
return this.canvasEvent
|
||||||
}
|
}
|
||||||
@@ -517,6 +558,10 @@ export class Draw {
|
|||||||
return this.dateParticle
|
return this.dateParticle
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getListParticle(): ListParticle {
|
||||||
|
return this.listParticle
|
||||||
|
}
|
||||||
|
|
||||||
public getControl(): Control {
|
public getControl(): Control {
|
||||||
return this.control
|
return this.control
|
||||||
}
|
}
|
||||||
@@ -765,6 +810,8 @@ export class Draw {
|
|||||||
const defaultBasicRowMarginHeight = this.getDefaultBasicRowMarginHeight()
|
const defaultBasicRowMarginHeight = this.getDefaultBasicRowMarginHeight()
|
||||||
const canvas = document.createElement('canvas')
|
const canvas = document.createElement('canvas')
|
||||||
const ctx = canvas.getContext('2d') as CanvasRenderingContext2D
|
const ctx = canvas.getContext('2d') as CanvasRenderingContext2D
|
||||||
|
// 计算列表偏移宽度
|
||||||
|
const listStyleMap = this.listParticle.computeListStyle(ctx, elementList)
|
||||||
const rowList: IRow[] = []
|
const rowList: IRow[] = []
|
||||||
if (elementList.length) {
|
if (elementList.length) {
|
||||||
rowList.push({
|
rowList.push({
|
||||||
@@ -776,6 +823,9 @@ export class Draw {
|
|||||||
rowFlex: elementList?.[1]?.rowFlex
|
rowFlex: elementList?.[1]?.rowFlex
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
// 列表位置
|
||||||
|
let listId: string | undefined
|
||||||
|
let listIndex = 0
|
||||||
for (let i = 0; i < elementList.length; i++) {
|
for (let i = 0; i < elementList.length; i++) {
|
||||||
const curRow: IRow = rowList[rowList.length - 1]
|
const curRow: IRow = rowList[rowList.length - 1]
|
||||||
const element = elementList[i]
|
const element = elementList[i]
|
||||||
@@ -930,7 +980,7 @@ export class Draw {
|
|||||||
const cloneElement = deepClone(element)
|
const cloneElement = deepClone(element)
|
||||||
cloneElement.trList = cloneTrList
|
cloneElement.trList = cloneTrList
|
||||||
cloneElement.id = getUUID()
|
cloneElement.id = getUUID()
|
||||||
elementList.splice(i + 1, 0, cloneElement)
|
this.spliceElementList(elementList, i + 1, 0, cloneElement)
|
||||||
// 换页的是当前行则改变上下文
|
// 换页的是当前行则改变上下文
|
||||||
const positionContext = this.position.getPositionContext()
|
const positionContext = this.position.getPositionContext()
|
||||||
if (positionContext.isTable && positionContext.trIndex === deleteStart) {
|
if (positionContext.isTable && positionContext.trIndex === deleteStart) {
|
||||||
@@ -1007,7 +1057,17 @@ export class Draw {
|
|||||||
const preElement = elementList[i - 1]
|
const preElement = elementList[i - 1]
|
||||||
const nextElement = elementList[i + 1]
|
const nextElement = elementList[i + 1]
|
||||||
// 累计行宽 + 当前元素宽度 + 后面标点符号宽度
|
// 累计行宽 + 当前元素宽度 + 后面标点符号宽度
|
||||||
const curRowWidth = curRow.width + metrics.width + this.textParticle.measurePunctuationWidth(ctx, nextElement)
|
let curRowWidth = curRow.width + metrics.width + this.textParticle.measurePunctuationWidth(ctx, nextElement)
|
||||||
|
// 列表信息
|
||||||
|
if (element.listId) {
|
||||||
|
curRowWidth += listStyleMap.get(element.listId) || 0
|
||||||
|
if (element.listId !== listId) {
|
||||||
|
listIndex = 0
|
||||||
|
} else if (element.value === ZERO) {
|
||||||
|
listIndex++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
listId = element.listId
|
||||||
if (
|
if (
|
||||||
element.type === ElementType.TABLE
|
element.type === ElementType.TABLE
|
||||||
|| preElement?.type === ElementType.TABLE
|
|| preElement?.type === ElementType.TABLE
|
||||||
@@ -1017,9 +1077,14 @@ export class Draw {
|
|||||||
|| element.imgDisplay === ImageDisplay.INLINE
|
|| element.imgDisplay === ImageDisplay.INLINE
|
||||||
|| curRowWidth > innerWidth
|
|| curRowWidth > innerWidth
|
||||||
|| (i !== 0 && element.value === ZERO)
|
|| (i !== 0 && element.value === ZERO)
|
||||||
|
|| (preElement?.listId !== element.listId)
|
||||||
) {
|
) {
|
||||||
// 减小行元素前第一行空行行高
|
// 减小行元素前第一行空行行高
|
||||||
if (curRow.startIndex === 0 && curRow.elementList.length === 1 && INLINE_ELEMENT_TYPE.includes(element.type!)) {
|
if (
|
||||||
|
curRow.startIndex === 0 &&
|
||||||
|
curRow.elementList.length === 1 &&
|
||||||
|
(INLINE_ELEMENT_TYPE.includes(element.type!) || element.listId)
|
||||||
|
) {
|
||||||
curRow.height = defaultBasicRowMarginHeight
|
curRow.height = defaultBasicRowMarginHeight
|
||||||
}
|
}
|
||||||
// 两端对齐
|
// 两端对齐
|
||||||
@@ -1031,7 +1096,7 @@ export class Draw {
|
|||||||
}
|
}
|
||||||
curRow.width = innerWidth
|
curRow.width = innerWidth
|
||||||
}
|
}
|
||||||
rowList.push({
|
const row: IRow = {
|
||||||
width: metrics.width,
|
width: metrics.width,
|
||||||
height,
|
height,
|
||||||
startIndex: i,
|
startIndex: i,
|
||||||
@@ -1039,7 +1104,13 @@ export class Draw {
|
|||||||
ascent,
|
ascent,
|
||||||
rowFlex: elementList[i + 1]?.rowFlex,
|
rowFlex: elementList[i + 1]?.rowFlex,
|
||||||
isPageBreak: element.type === ElementType.PAGE_BREAK
|
isPageBreak: element.type === ElementType.PAGE_BREAK
|
||||||
})
|
}
|
||||||
|
if (element.listId) {
|
||||||
|
row.isList = true
|
||||||
|
row.offsetX = listStyleMap.get(element.listId!)
|
||||||
|
row.listIndex = listIndex
|
||||||
|
}
|
||||||
|
rowList.push(row)
|
||||||
} else {
|
} else {
|
||||||
curRow.width += metrics.width
|
curRow.width += metrics.width
|
||||||
if (curRow.height < height) {
|
if (curRow.height < height) {
|
||||||
@@ -1255,6 +1326,10 @@ export class Draw {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 绘制列表样式
|
||||||
|
if (curRow.isList) {
|
||||||
|
this.listParticle.drawListStyle(ctx, curRow, positionList[curRow.startIndex])
|
||||||
|
}
|
||||||
// 绘制富文本及文字
|
// 绘制富文本及文字
|
||||||
this._drawRichText(ctx)
|
this._drawRichText(ctx)
|
||||||
// 绘制选区
|
// 绘制选区
|
||||||
|
|||||||
@@ -32,6 +32,10 @@ export class Control {
|
|||||||
this.activeControl = null
|
this.activeControl = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getDraw(): Draw {
|
||||||
|
return this.draw
|
||||||
|
}
|
||||||
|
|
||||||
// 判断选区部分在控件边界外
|
// 判断选区部分在控件边界外
|
||||||
public isPartRangeInControlOutside(): boolean {
|
public isPartRangeInControlOutside(): boolean {
|
||||||
const { startIndex, endIndex } = this.getRange()
|
const { startIndex, endIndex } = this.getRange()
|
||||||
@@ -256,7 +260,7 @@ export class Control {
|
|||||||
if (!~leftIndex && !~rightIndex) return startIndex
|
if (!~leftIndex && !~rightIndex) return startIndex
|
||||||
leftIndex = ~leftIndex ? leftIndex : 0
|
leftIndex = ~leftIndex ? leftIndex : 0
|
||||||
// 删除元素
|
// 删除元素
|
||||||
elementList.splice(leftIndex + 1, rightIndex - leftIndex)
|
this.draw.spliceElementList(elementList, leftIndex + 1, rightIndex - leftIndex)
|
||||||
return leftIndex
|
return leftIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -273,7 +277,7 @@ export class Control {
|
|||||||
const curElement = elementList[index]
|
const curElement = elementList[index]
|
||||||
if (curElement.controlId !== startElement.controlId) break
|
if (curElement.controlId !== startElement.controlId) break
|
||||||
if (curElement.controlComponent === ControlComponent.PLACEHOLDER) {
|
if (curElement.controlComponent === ControlComponent.PLACEHOLDER) {
|
||||||
elementList.splice(index, 1)
|
this.draw.spliceElementList(elementList, index, 1)
|
||||||
} else {
|
} else {
|
||||||
index++
|
index++
|
||||||
}
|
}
|
||||||
@@ -289,7 +293,7 @@ export class Control {
|
|||||||
const placeholderStrList = splitText(control.placeholder)
|
const placeholderStrList = splitText(control.placeholder)
|
||||||
for (let p = 0; p < placeholderStrList.length; p++) {
|
for (let p = 0; p < placeholderStrList.length; p++) {
|
||||||
const value = placeholderStrList[p]
|
const value = placeholderStrList[p]
|
||||||
elementList.splice(startIndex + p + 1, 0, {
|
this.draw.spliceElementList(elementList, startIndex + p + 1, 0, {
|
||||||
value,
|
value,
|
||||||
controlId: startElement.controlId,
|
controlId: startElement.controlId,
|
||||||
type: ElementType.CONTROL,
|
type: ElementType.CONTROL,
|
||||||
|
|||||||
@@ -164,7 +164,8 @@ export class SelectControl implements IControlInstance {
|
|||||||
}
|
}
|
||||||
if (!~leftIndex || !~rightIndex) return -1
|
if (!~leftIndex || !~rightIndex) return -1
|
||||||
// 删除元素
|
// 删除元素
|
||||||
elementList.splice(leftIndex + 1, rightIndex - leftIndex)
|
const draw = this.control.getDraw()
|
||||||
|
draw.spliceElementList(elementList, leftIndex + 1, rightIndex - leftIndex)
|
||||||
// 增加占位符
|
// 增加占位符
|
||||||
this.control.addPlaceholder(preIndex)
|
this.control.addPlaceholder(preIndex)
|
||||||
this.element.control!.code = null
|
this.element.control!.code = null
|
||||||
@@ -186,8 +187,9 @@ export class SelectControl implements IControlInstance {
|
|||||||
const startElement = elementList[startIndex]
|
const startElement = elementList[startIndex]
|
||||||
const start = startIndex + 1
|
const start = startIndex + 1
|
||||||
const data = splitText(valueSet.value)
|
const data = splitText(valueSet.value)
|
||||||
|
const draw = this.control.getDraw()
|
||||||
for (let i = 0; i < data.length; i++) {
|
for (let i = 0; i < data.length; i++) {
|
||||||
elementList.splice(start + i, 0, {
|
draw.spliceElementList(elementList, start + i, 0, {
|
||||||
...startElement,
|
...startElement,
|
||||||
value: data[i],
|
value: data[i],
|
||||||
controlComponent: ControlComponent.VALUE
|
controlComponent: ControlComponent.VALUE
|
||||||
|
|||||||
@@ -62,9 +62,10 @@ export class TextControl implements IControlInstance {
|
|||||||
// 收缩边界到Value内
|
// 收缩边界到Value内
|
||||||
this.control.shrinkBoundary()
|
this.control.shrinkBoundary()
|
||||||
const { startIndex, endIndex } = range
|
const { startIndex, endIndex } = range
|
||||||
|
const draw = this.control.getDraw()
|
||||||
// 移除选区元素
|
// 移除选区元素
|
||||||
if (startIndex !== endIndex) {
|
if (startIndex !== endIndex) {
|
||||||
elementList.splice(startIndex + 1, endIndex - startIndex)
|
draw.spliceElementList(elementList, startIndex + 1, endIndex - startIndex)
|
||||||
} else {
|
} else {
|
||||||
// 移除空白占位符
|
// 移除空白占位符
|
||||||
this.control.removePlaceholder(startIndex)
|
this.control.removePlaceholder(startIndex)
|
||||||
@@ -73,7 +74,7 @@ export class TextControl implements IControlInstance {
|
|||||||
const startElement = elementList[startIndex]
|
const startElement = elementList[startIndex]
|
||||||
const start = range.startIndex + 1
|
const start = range.startIndex + 1
|
||||||
for (let i = 0; i < data.length; i++) {
|
for (let i = 0; i < data.length; i++) {
|
||||||
elementList.splice(start + i, 0, {
|
draw.spliceElementList(elementList, start + i, 0, {
|
||||||
...startElement,
|
...startElement,
|
||||||
...data[i],
|
...data[i],
|
||||||
controlComponent: ControlComponent.VALUE
|
controlComponent: ControlComponent.VALUE
|
||||||
@@ -90,11 +91,12 @@ export class TextControl implements IControlInstance {
|
|||||||
const { startIndex, endIndex } = range
|
const { startIndex, endIndex } = range
|
||||||
const startElement = elementList[startIndex]
|
const startElement = elementList[startIndex]
|
||||||
const endElement = elementList[endIndex]
|
const endElement = elementList[endIndex]
|
||||||
|
const draw = this.control.getDraw()
|
||||||
// backspace
|
// backspace
|
||||||
if (evt.key === KeyMap.Backspace) {
|
if (evt.key === KeyMap.Backspace) {
|
||||||
// 移除选区元素
|
// 移除选区元素
|
||||||
if (startIndex !== endIndex) {
|
if (startIndex !== endIndex) {
|
||||||
elementList.splice(startIndex + 1, endIndex - startIndex)
|
draw.spliceElementList(elementList, startIndex + 1, endIndex - startIndex)
|
||||||
const value = this.getValue()
|
const value = this.getValue()
|
||||||
if (!value.length) {
|
if (!value.length) {
|
||||||
this.control.addPlaceholder(startIndex)
|
this.control.addPlaceholder(startIndex)
|
||||||
@@ -110,7 +112,7 @@ export class TextControl implements IControlInstance {
|
|||||||
return this.control.removeControl(startIndex)
|
return this.control.removeControl(startIndex)
|
||||||
} else {
|
} else {
|
||||||
// 文本
|
// 文本
|
||||||
elementList.splice(startIndex, 1)
|
draw.spliceElementList(elementList, startIndex, 1)
|
||||||
const value = this.getValue()
|
const value = this.getValue()
|
||||||
if (!value.length) {
|
if (!value.length) {
|
||||||
this.control.addPlaceholder(startIndex - 1)
|
this.control.addPlaceholder(startIndex - 1)
|
||||||
@@ -121,7 +123,7 @@ export class TextControl implements IControlInstance {
|
|||||||
} else if (evt.key === KeyMap.Delete) {
|
} else if (evt.key === KeyMap.Delete) {
|
||||||
// 移除选区元素
|
// 移除选区元素
|
||||||
if (startIndex !== endIndex) {
|
if (startIndex !== endIndex) {
|
||||||
elementList.splice(startIndex + 1, endIndex - startIndex)
|
draw.spliceElementList(elementList, startIndex + 1, endIndex - startIndex)
|
||||||
const value = this.getValue()
|
const value = this.getValue()
|
||||||
if (!value.length) {
|
if (!value.length) {
|
||||||
this.control.addPlaceholder(startIndex)
|
this.control.addPlaceholder(startIndex)
|
||||||
@@ -138,7 +140,7 @@ export class TextControl implements IControlInstance {
|
|||||||
return this.control.removeControl(startIndex)
|
return this.control.removeControl(startIndex)
|
||||||
} else {
|
} else {
|
||||||
// 文本
|
// 文本
|
||||||
elementList.splice(startIndex + 1, 1)
|
draw.spliceElementList(elementList, startIndex + 1, 1)
|
||||||
const value = this.getValue()
|
const value = this.getValue()
|
||||||
if (!value.length) {
|
if (!value.length) {
|
||||||
this.control.addPlaceholder(startIndex)
|
this.control.addPlaceholder(startIndex)
|
||||||
@@ -156,8 +158,9 @@ export class TextControl implements IControlInstance {
|
|||||||
if (startIndex === endIndex) {
|
if (startIndex === endIndex) {
|
||||||
return startIndex
|
return startIndex
|
||||||
}
|
}
|
||||||
|
const draw = this.control.getDraw()
|
||||||
const elementList = this.control.getElementList()
|
const elementList = this.control.getElementList()
|
||||||
elementList.splice(startIndex + 1, endIndex - startIndex)
|
draw.spliceElementList(elementList, startIndex + 1, endIndex - startIndex)
|
||||||
const value = this.getValue()
|
const value = this.getValue()
|
||||||
if (!value.length) {
|
if (!value.length) {
|
||||||
this.control.addPlaceholder(startIndex)
|
this.control.addPlaceholder(startIndex)
|
||||||
|
|||||||
@@ -0,0 +1,97 @@
|
|||||||
|
import { ZERO } from '../../../dataset/constant/Common'
|
||||||
|
import { ulStyleMapping } from '../../../dataset/constant/List'
|
||||||
|
import { KeyMap } from '../../../dataset/enum/KeyMap'
|
||||||
|
import { ListStyle, ListType, UlStyle } from '../../../dataset/enum/List'
|
||||||
|
import { DeepRequired } from '../../../interface/Common'
|
||||||
|
import { IEditorOption } from '../../../interface/Editor'
|
||||||
|
import { IElement, IElementPosition } from '../../../interface/Element'
|
||||||
|
import { IRow } from '../../../interface/Row'
|
||||||
|
import { Draw } from '../Draw'
|
||||||
|
|
||||||
|
export class ListParticle {
|
||||||
|
|
||||||
|
private options: DeepRequired<IEditorOption>
|
||||||
|
|
||||||
|
// 非递增样式直接返回默认值
|
||||||
|
private readonly UN_COUNT_STYLE_WIDTH = 20
|
||||||
|
private readonly MEASURE_BASE_TEXT = '0'
|
||||||
|
private readonly LIST_GAP = 10
|
||||||
|
|
||||||
|
constructor(draw: Draw) {
|
||||||
|
this.options = draw.getOptions()
|
||||||
|
}
|
||||||
|
|
||||||
|
public computeListStyle(ctx: CanvasRenderingContext2D, elementList: IElement[]): Map<string, number> {
|
||||||
|
const listStyleMap = new Map<string, number>()
|
||||||
|
let start = 0
|
||||||
|
let curListId = elementList[start].listId
|
||||||
|
let curElementList: IElement[] = []
|
||||||
|
const elementLength = elementList.length
|
||||||
|
while (start < elementLength) {
|
||||||
|
const curElement = elementList[start]
|
||||||
|
if (curListId && curListId === curElement.listId) {
|
||||||
|
curElementList.push(curElement)
|
||||||
|
} else {
|
||||||
|
if (curElement.listId && curElement.listId !== curListId) {
|
||||||
|
// 列表结束
|
||||||
|
if (curElementList.length) {
|
||||||
|
const width = this.getListStyleWidth(ctx, curElementList)
|
||||||
|
listStyleMap.set(curListId!, width)
|
||||||
|
}
|
||||||
|
curListId = curElement.listId
|
||||||
|
curElementList = curListId ? [curElement] : []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
start++
|
||||||
|
}
|
||||||
|
if (curElementList.length) {
|
||||||
|
const width = this.getListStyleWidth(ctx, curElementList)
|
||||||
|
listStyleMap.set(curListId!, width)
|
||||||
|
}
|
||||||
|
return listStyleMap
|
||||||
|
}
|
||||||
|
|
||||||
|
public getListStyleWidth(ctx: CanvasRenderingContext2D, listElementList: IElement[]): number {
|
||||||
|
const startElement = listElementList[0]
|
||||||
|
// 非递增样式返回固定值
|
||||||
|
if (startElement.listStyle && startElement.listStyle !== ListStyle.DECIMAL) {
|
||||||
|
return this.UN_COUNT_STYLE_WIDTH
|
||||||
|
}
|
||||||
|
// 计算列表数量
|
||||||
|
const count = listElementList.reduce((pre, cur) => {
|
||||||
|
if (cur.value === ZERO) {
|
||||||
|
pre += 1
|
||||||
|
}
|
||||||
|
return pre
|
||||||
|
}, 0)
|
||||||
|
if (!count) return 0
|
||||||
|
// 以递增样式最大宽度为准
|
||||||
|
const text = `${this.MEASURE_BASE_TEXT.repeat(String(count).length)}${KeyMap.PERIOD}`
|
||||||
|
const textMetrics = ctx.measureText(text)
|
||||||
|
return Math.ceil(textMetrics.width + this.LIST_GAP)
|
||||||
|
}
|
||||||
|
|
||||||
|
public drawListStyle(ctx: CanvasRenderingContext2D, row: IRow, position: IElementPosition) {
|
||||||
|
const { elementList, offsetX, listIndex, ascent } = row
|
||||||
|
const startElement = elementList[0]
|
||||||
|
if (startElement.value !== ZERO) return
|
||||||
|
let text = ''
|
||||||
|
if (startElement.listType === ListType.UL) {
|
||||||
|
if (startElement.listStyle) {
|
||||||
|
text = ulStyleMapping[<UlStyle><unknown>startElement.listStyle]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
text = `${listIndex! + 1}${KeyMap.PERIOD}`
|
||||||
|
}
|
||||||
|
if (!text) return
|
||||||
|
const { coordinate: { leftTop: [startX, startY] } } = position
|
||||||
|
const x = startX - offsetX!
|
||||||
|
const y = startY + ascent
|
||||||
|
const { defaultFont, defaultSize, scale } = this.options
|
||||||
|
ctx.save()
|
||||||
|
ctx.font = `${defaultSize * scale}px ${defaultFont}`
|
||||||
|
ctx.fillText(text, x, y)
|
||||||
|
ctx.restore()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -50,7 +50,7 @@ export class DateParticle {
|
|||||||
const elementList = this.draw.getElementList()
|
const elementList = this.draw.getElementList()
|
||||||
const startElement = elementList[leftIndex + 1]
|
const startElement = elementList[leftIndex + 1]
|
||||||
// 删除旧时间
|
// 删除旧时间
|
||||||
elementList.splice(leftIndex + 1, rightIndex - leftIndex)
|
this.draw.spliceElementList(elementList, leftIndex + 1, rightIndex - leftIndex)
|
||||||
this.range.setRange(leftIndex, leftIndex)
|
this.range.setRange(leftIndex, leftIndex)
|
||||||
// 插入新时间
|
// 插入新时间
|
||||||
this.draw.insertElementList([{
|
this.draw.insertElementList([{
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ export function cut(host: CanvasEvent) {
|
|||||||
if (activeControl) {
|
if (activeControl) {
|
||||||
curIndex = control.cut()
|
curIndex = control.cut()
|
||||||
} else {
|
} else {
|
||||||
elementList.splice(start + 1, end - start)
|
draw.spliceElementList(elementList, start + 1, end - start)
|
||||||
curIndex = start
|
curIndex = start
|
||||||
}
|
}
|
||||||
rangeManager.setRange(curIndex, curIndex)
|
rangeManager.setRange(curIndex, curIndex)
|
||||||
|
|||||||
@@ -31,13 +31,7 @@ export function input(data: string, host: CanvasEvent) {
|
|||||||
const text = data.replaceAll(`\n`, ZERO)
|
const text = data.replaceAll(`\n`, ZERO)
|
||||||
const rangeManager = draw.getRange()
|
const rangeManager = draw.getRange()
|
||||||
const { startIndex, endIndex } = rangeManager.getRange()
|
const { startIndex, endIndex } = rangeManager.getRange()
|
||||||
// 表格需要上下文信息
|
// 格式化元素
|
||||||
const positionContext = position.getPositionContext()
|
|
||||||
let restArg = {}
|
|
||||||
if (positionContext.isTable) {
|
|
||||||
const { tdId, trId, tableId } = positionContext
|
|
||||||
restArg = { tdId, trId, tableId }
|
|
||||||
}
|
|
||||||
const elementList = draw.getElementList()
|
const elementList = draw.getElementList()
|
||||||
const endElement = elementList[endIndex]
|
const endElement = elementList[endIndex]
|
||||||
const endNextElement = elementList[endIndex + 1]
|
const endNextElement = elementList[endIndex + 1]
|
||||||
@@ -46,8 +40,7 @@ export function input(data: string, host: CanvasEvent) {
|
|||||||
: endElement
|
: endElement
|
||||||
const inputData: IElement[] = splitText(text).map(value => {
|
const inputData: IElement[] = splitText(text).map(value => {
|
||||||
const newElement: IElement = {
|
const newElement: IElement = {
|
||||||
value,
|
value
|
||||||
...restArg
|
|
||||||
}
|
}
|
||||||
const nextElement = elementList[endIndex + 1]
|
const nextElement = elementList[endIndex + 1]
|
||||||
if (
|
if (
|
||||||
@@ -77,12 +70,9 @@ export function input(data: string, host: CanvasEvent) {
|
|||||||
} else {
|
} else {
|
||||||
const start = startIndex + 1
|
const start = startIndex + 1
|
||||||
if (startIndex !== endIndex) {
|
if (startIndex !== endIndex) {
|
||||||
elementList.splice(start, endIndex - startIndex)
|
draw.spliceElementList(elementList, start, endIndex - startIndex)
|
||||||
}
|
|
||||||
// 禁止直接使用解构存在性能问题
|
|
||||||
for (let i = 0; i < inputData.length; i++) {
|
|
||||||
elementList.splice(start + i, 0, inputData[i])
|
|
||||||
}
|
}
|
||||||
|
draw.spliceElementList(elementList, start, 0, ...inputData)
|
||||||
curIndex = startIndex + inputData.length
|
curIndex = startIndex + inputData.length
|
||||||
}
|
}
|
||||||
if (~curIndex) {
|
if (~curIndex) {
|
||||||
|
|||||||
@@ -46,9 +46,9 @@ export function keydown(evt: KeyboardEvent, host: CanvasEvent) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (!isCollapsed) {
|
if (!isCollapsed) {
|
||||||
elementList.splice(startIndex + 1, endIndex - startIndex)
|
draw.spliceElementList(elementList, startIndex + 1, endIndex - startIndex)
|
||||||
} else {
|
} else {
|
||||||
elementList.splice(index, 1)
|
draw.spliceElementList(elementList, index, 1)
|
||||||
}
|
}
|
||||||
curIndex = isCollapsed ? index - 1 : startIndex
|
curIndex = isCollapsed ? index - 1 : startIndex
|
||||||
}
|
}
|
||||||
@@ -63,9 +63,9 @@ export function keydown(evt: KeyboardEvent, host: CanvasEvent) {
|
|||||||
curIndex = control.removeControl(endIndex + 1)
|
curIndex = control.removeControl(endIndex + 1)
|
||||||
} else {
|
} else {
|
||||||
if (!isCollapsed) {
|
if (!isCollapsed) {
|
||||||
elementList.splice(startIndex + 1, endIndex - startIndex)
|
draw.spliceElementList(elementList, startIndex + 1, endIndex - startIndex)
|
||||||
} else {
|
} else {
|
||||||
elementList.splice(index + 1, 1)
|
draw.spliceElementList(elementList, index + 1, 1)
|
||||||
}
|
}
|
||||||
curIndex = isCollapsed ? index : startIndex
|
curIndex = isCollapsed ? index : startIndex
|
||||||
}
|
}
|
||||||
@@ -73,25 +73,17 @@ export function keydown(evt: KeyboardEvent, host: CanvasEvent) {
|
|||||||
draw.render({ curIndex })
|
draw.render({ curIndex })
|
||||||
} else if (evt.key === KeyMap.Enter) {
|
} else if (evt.key === KeyMap.Enter) {
|
||||||
if (isReadonly || isPartRangeInControlOutside) return
|
if (isReadonly || isPartRangeInControlOutside) return
|
||||||
// 表格需要上下文信息
|
|
||||||
const positionContext = position.getPositionContext()
|
|
||||||
let restArg = {}
|
|
||||||
if (positionContext.isTable) {
|
|
||||||
const { tdId, trId, tableId } = positionContext
|
|
||||||
restArg = { tdId, trId, tableId }
|
|
||||||
}
|
|
||||||
const enterText: IElement = {
|
const enterText: IElement = {
|
||||||
value: ZERO,
|
value: ZERO
|
||||||
...restArg
|
|
||||||
}
|
}
|
||||||
let curIndex: number
|
let curIndex: number
|
||||||
if (activeControl && !control.isRangInPostfix()) {
|
if (activeControl && !control.isRangInPostfix()) {
|
||||||
curIndex = control.setValue([enterText])
|
curIndex = control.setValue([enterText])
|
||||||
} else {
|
} else {
|
||||||
if (isCollapsed) {
|
if (isCollapsed) {
|
||||||
elementList.splice(index + 1, 0, enterText)
|
draw.spliceElementList(elementList, index + 1, 0, enterText)
|
||||||
} else {
|
} else {
|
||||||
elementList.splice(startIndex + 1, endIndex - startIndex, enterText)
|
draw.spliceElementList(elementList, startIndex + 1, endIndex - startIndex, enterText)
|
||||||
}
|
}
|
||||||
curIndex = index + 1
|
curIndex = index + 1
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,17 +82,10 @@ export function mouseup(evt: MouseEvent, host: CanvasEvent) {
|
|||||||
// 格式化元素
|
// 格式化元素
|
||||||
const editorOptions = draw.getOptions()
|
const editorOptions = draw.getOptions()
|
||||||
const elementList = draw.getElementList()
|
const elementList = draw.getElementList()
|
||||||
const anchorElement = elementList[range.startIndex]
|
|
||||||
let restArg = {}
|
|
||||||
if (anchorElement.tableId) {
|
|
||||||
const { tdId, trId, tableId } = anchorElement
|
|
||||||
restArg = { tdId, trId, tableId }
|
|
||||||
}
|
|
||||||
const replaceElementList = dragElementList.map(el => {
|
const replaceElementList = dragElementList.map(el => {
|
||||||
if (!el.type || el.type === ElementType.TEXT || el.control?.type === ControlType.TEXT) {
|
if (!el.type || el.type === ElementType.TEXT || el.control?.type === ControlType.TEXT) {
|
||||||
const newElement: IElement = {
|
const newElement: IElement = {
|
||||||
value: el.value,
|
value: el.value
|
||||||
...restArg
|
|
||||||
}
|
}
|
||||||
EDITOR_ELEMENT_STYLE_ATTR.forEach(attr => {
|
EDITOR_ELEMENT_STYLE_ATTR.forEach(attr => {
|
||||||
const value = el[attr] as never
|
const value = el[attr] as never
|
||||||
@@ -123,7 +116,7 @@ export function mouseup(evt: MouseEvent, host: CanvasEvent) {
|
|||||||
rangeEnd = activeControl.setValue(replaceElementList)
|
rangeEnd = activeControl.setValue(replaceElementList)
|
||||||
rangeStart = rangeEnd - replaceLength
|
rangeStart = rangeEnd - replaceLength
|
||||||
} else {
|
} else {
|
||||||
elementList.splice(rangeStart + 1, 0, ...replaceElementList)
|
draw.spliceElementList(elementList, rangeStart + 1, 0, ...replaceElementList)
|
||||||
}
|
}
|
||||||
if (!~rangeEnd) {
|
if (!~rangeEnd) {
|
||||||
draw.render({
|
draw.render({
|
||||||
@@ -146,7 +139,7 @@ export function mouseup(evt: MouseEvent, host: CanvasEvent) {
|
|||||||
})
|
})
|
||||||
control.getActiveControl()?.cut()
|
control.getActiveControl()?.cut()
|
||||||
} else {
|
} else {
|
||||||
cacheElementList.splice(cacheRangeStartIndex + 1, cacheRangeEndIndex - cacheRangeStartIndex)
|
draw.spliceElementList(cacheElementList, cacheRangeStartIndex + 1, cacheRangeEndIndex - cacheRangeStartIndex)
|
||||||
}
|
}
|
||||||
// 重设上下文
|
// 重设上下文
|
||||||
const startElement = elementList[range.startIndex]
|
const startElement = elementList[range.startIndex]
|
||||||
|
|||||||
@@ -81,6 +81,10 @@ export class Position {
|
|||||||
} else if (curRow.rowFlex === RowFlex.RIGHT) {
|
} else if (curRow.rowFlex === RowFlex.RIGHT) {
|
||||||
x += innerWidth - curRow.width
|
x += innerWidth - curRow.width
|
||||||
}
|
}
|
||||||
|
// 列表向右移动-留出列表样式位置
|
||||||
|
if (curRow.isList) {
|
||||||
|
x += curRow.offsetX || 0
|
||||||
|
}
|
||||||
// 当前td所在位置
|
// 当前td所在位置
|
||||||
const tablePreX = x
|
const tablePreX = x
|
||||||
const tablePreY = y
|
const tablePreY = y
|
||||||
|
|||||||
@@ -82,10 +82,7 @@ export class RangeManager {
|
|||||||
// 向上查找
|
// 向上查找
|
||||||
let start = startIndex
|
let start = startIndex
|
||||||
while (start > 0) {
|
while (start > 0) {
|
||||||
if (
|
if (elementList[start].titleId !== elementList[start - 1]?.titleId) break
|
||||||
positionList[start].value === ZERO ||
|
|
||||||
(elementList[start].titleId !== elementList[start - 1]?.titleId)
|
|
||||||
) break
|
|
||||||
const { pageNo, rowNo } = positionList[start]
|
const { pageNo, rowNo } = positionList[start]
|
||||||
let rowArray = rangeRow.get(pageNo)
|
let rowArray = rangeRow.get(pageNo)
|
||||||
if (!rowArray) {
|
if (!rowArray) {
|
||||||
@@ -95,15 +92,13 @@ export class RangeManager {
|
|||||||
if (!rowArray.includes(rowNo)) {
|
if (!rowArray.includes(rowNo)) {
|
||||||
rowArray.unshift(rowNo)
|
rowArray.unshift(rowNo)
|
||||||
}
|
}
|
||||||
|
if (positionList[start]?.value === ZERO) break
|
||||||
start--
|
start--
|
||||||
}
|
}
|
||||||
// 向下查找
|
// 向下查找
|
||||||
let end = endIndex
|
let end = startIndex + 1
|
||||||
while (end < positionList.length) {
|
while (end < positionList.length) {
|
||||||
if (
|
if (elementList[end].titleId !== elementList[end + 1]?.titleId) break
|
||||||
positionList[end].value === ZERO ||
|
|
||||||
elementList[end].titleId !== elementList[end + 1]?.titleId
|
|
||||||
) break
|
|
||||||
const { pageNo, rowNo } = positionList[end]
|
const { pageNo, rowNo } = positionList[end]
|
||||||
let rowArray = rangeRow.get(pageNo)
|
let rowArray = rangeRow.get(pageNo)
|
||||||
if (!rowArray) {
|
if (!rowArray) {
|
||||||
@@ -113,11 +108,34 @@ export class RangeManager {
|
|||||||
if (!rowArray.includes(rowNo)) {
|
if (!rowArray.includes(rowNo)) {
|
||||||
rowArray.push(rowNo)
|
rowArray.push(rowNo)
|
||||||
}
|
}
|
||||||
|
if (positionList[end].value === ZERO) break
|
||||||
end++
|
end++
|
||||||
}
|
}
|
||||||
return rangeRow
|
return rangeRow
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取选区元素列表
|
||||||
|
public getRangeElementList(): IElement[] | null {
|
||||||
|
const { startIndex, endIndex } = this.range
|
||||||
|
if (!~startIndex && !~endIndex) return null
|
||||||
|
// 需要改变的元素列表
|
||||||
|
const rangeElementList: IElement[] = []
|
||||||
|
// 选区行信息
|
||||||
|
const rangeRow = this.getRangeParagraph()
|
||||||
|
if (!rangeRow) return null
|
||||||
|
const elementList = this.draw.getElementList()
|
||||||
|
const positionList = this.position.getPositionList()
|
||||||
|
for (let p = 0; p < positionList.length; p++) {
|
||||||
|
const position = positionList[p]
|
||||||
|
const rowArray = rangeRow.get(position.pageNo)
|
||||||
|
if (!rowArray) continue
|
||||||
|
if (rowArray.includes(position.rowNo)) {
|
||||||
|
rangeElementList.push(elementList[p])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rangeElementList
|
||||||
|
}
|
||||||
|
|
||||||
public getIsPointInRange(x: number, y: number): boolean {
|
public getIsPointInRange(x: number, y: number): boolean {
|
||||||
const { startIndex, endIndex } = this.range
|
const { startIndex, endIndex } = this.range
|
||||||
const positionList = this.position.getPositionList()
|
const positionList = this.position.getPositionList()
|
||||||
@@ -189,7 +207,7 @@ export class RangeManager {
|
|||||||
const elementList = this.draw.getElementList()
|
const elementList = this.draw.getElementList()
|
||||||
const endElement = elementList[index]
|
const endElement = elementList[index]
|
||||||
const endNextElement = elementList[index + 1]
|
const endNextElement = elementList[index + 1]
|
||||||
curElement = endElement.value === ZERO && endNextElement
|
curElement = endElement.value === ZERO && endNextElement && endNextElement.value !== ZERO
|
||||||
? endNextElement
|
? endNextElement
|
||||||
: endElement
|
: endElement
|
||||||
}
|
}
|
||||||
@@ -211,6 +229,8 @@ export class RangeManager {
|
|||||||
const rowMargin = curElement.rowMargin || this.options.defaultRowMargin
|
const rowMargin = curElement.rowMargin || this.options.defaultRowMargin
|
||||||
const dashArray = curElement.dashArray || []
|
const dashArray = curElement.dashArray || []
|
||||||
const level = curElement.level || null
|
const level = curElement.level || null
|
||||||
|
const listType = curElement.listType || null
|
||||||
|
const listStyle = curElement.listStyle || null
|
||||||
// 菜单
|
// 菜单
|
||||||
const painter = !!this.draw.getPainterStyle()
|
const painter = !!this.draw.getPainterStyle()
|
||||||
const undo = this.historyManager.isCanUndo()
|
const undo = this.historyManager.isCanUndo()
|
||||||
@@ -231,7 +251,9 @@ export class RangeManager {
|
|||||||
rowFlex,
|
rowFlex,
|
||||||
rowMargin,
|
rowMargin,
|
||||||
dashArray,
|
dashArray,
|
||||||
level
|
level,
|
||||||
|
listType,
|
||||||
|
listStyle
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,7 +281,9 @@ export class RangeManager {
|
|||||||
rowFlex: null,
|
rowFlex: null,
|
||||||
rowMargin,
|
rowMargin,
|
||||||
dashArray: [],
|
dashArray: [],
|
||||||
level: null
|
level: null,
|
||||||
|
listType: null,
|
||||||
|
listStyle: null
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,18 @@ export const EDITOR_ELEMENT_ZIP_ATTR: Array<keyof IElement> = [
|
|||||||
'checkbox',
|
'checkbox',
|
||||||
'dateFormat',
|
'dateFormat',
|
||||||
'block',
|
'block',
|
||||||
'level'
|
'level',
|
||||||
|
'listType',
|
||||||
|
'listStyle'
|
||||||
|
]
|
||||||
|
|
||||||
|
export const EDITOR_ELEMENT_CONTEXT_ATTR: Array<keyof IElement> = [
|
||||||
|
'tdId',
|
||||||
|
'trId',
|
||||||
|
'tableId',
|
||||||
|
'listId',
|
||||||
|
'listType',
|
||||||
|
'listStyle'
|
||||||
]
|
]
|
||||||
|
|
||||||
export const TEXTLIKE_ELEMENT_TYPE: ElementType[] = [
|
export const TEXTLIKE_ELEMENT_TYPE: ElementType[] = [
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import { UlStyle } from '../enum/List'
|
||||||
|
|
||||||
|
export const ulStyleMapping: Record<UlStyle, string> = {
|
||||||
|
[UlStyle.DISC]: '•',
|
||||||
|
[UlStyle.CIRCLE]: '◦',
|
||||||
|
[UlStyle.SQUARE]: '▫︎'
|
||||||
|
}
|
||||||
@@ -13,5 +13,6 @@ export enum ElementType {
|
|||||||
TAB = 'tab',
|
TAB = 'tab',
|
||||||
DATE = 'date',
|
DATE = 'date',
|
||||||
BLOCK = 'block',
|
BLOCK = 'block',
|
||||||
TITLE = 'title'
|
TITLE = 'title',
|
||||||
|
LIST = 'list'
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
export enum ListType {
|
||||||
|
UL = 'ul',
|
||||||
|
OL = 'ol'
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum UlStyle {
|
||||||
|
DISC = 'disc', // 实心圆点
|
||||||
|
CIRCLE = 'circle', // 空心圆点
|
||||||
|
SQUARE = 'square', // 实心方块
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum OlStyle {
|
||||||
|
DECIMAL = 'decimal' // 阿拉伯数字
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum ListStyle {
|
||||||
|
DISC = UlStyle.DISC,
|
||||||
|
CIRCLE = UlStyle.CIRCLE,
|
||||||
|
SQUARE = UlStyle.SQUARE,
|
||||||
|
DECIMAL = OlStyle.DECIMAL
|
||||||
|
}
|
||||||
+4
-1
@@ -41,6 +41,7 @@ import { MaxHeightRatio, NumberType } from './dataset/enum/Common'
|
|||||||
import { ITitleOption } from './interface/Title'
|
import { ITitleOption } from './interface/Title'
|
||||||
import { defaultTitleOption } from './dataset/constant/Title'
|
import { defaultTitleOption } from './dataset/constant/Title'
|
||||||
import { TitleLevel } from './dataset/enum/Title'
|
import { TitleLevel } from './dataset/enum/Title'
|
||||||
|
import { ListStyle, ListType } from './dataset/enum/List'
|
||||||
|
|
||||||
export default class Editor {
|
export default class Editor {
|
||||||
|
|
||||||
@@ -199,7 +200,9 @@ export {
|
|||||||
TableBorder,
|
TableBorder,
|
||||||
MaxHeightRatio,
|
MaxHeightRatio,
|
||||||
NumberType,
|
NumberType,
|
||||||
TitleLevel
|
TitleLevel,
|
||||||
|
ListType,
|
||||||
|
ListStyle
|
||||||
}
|
}
|
||||||
|
|
||||||
// 对外类型
|
// 对外类型
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { ControlComponent, ImageDisplay } from '../dataset/enum/Control'
|
import { ControlComponent, ImageDisplay } from '../dataset/enum/Control'
|
||||||
import { ElementType } from '../dataset/enum/Element'
|
import { ElementType } from '../dataset/enum/Element'
|
||||||
|
import { ListStyle, ListType } from '../dataset/enum/List'
|
||||||
import { RowFlex } from '../dataset/enum/Row'
|
import { RowFlex } from '../dataset/enum/Row'
|
||||||
import { TitleLevel } from '../dataset/enum/Title'
|
import { TitleLevel } from '../dataset/enum/Title'
|
||||||
import { TableBorder } from '../dataset/enum/table/Table'
|
import { TableBorder } from '../dataset/enum/table/Table'
|
||||||
@@ -37,6 +38,13 @@ export interface ITitleElement {
|
|||||||
titleId?: string;
|
titleId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IListElement {
|
||||||
|
valueList?: IElement[];
|
||||||
|
listType?: ListType;
|
||||||
|
listStyle?: ListStyle;
|
||||||
|
listId?: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ITableAttr {
|
export interface ITableAttr {
|
||||||
colgroup?: IColgroup[];
|
colgroup?: IColgroup[];
|
||||||
trList?: ITr[];
|
trList?: ITr[];
|
||||||
@@ -105,6 +113,7 @@ export type IElement = IElementBasic
|
|||||||
& IImageElement
|
& IImageElement
|
||||||
& IBlockElement
|
& IBlockElement
|
||||||
& ITitleElement
|
& ITitleElement
|
||||||
|
& IListElement
|
||||||
|
|
||||||
export interface IElementMetrics {
|
export interface IElementMetrics {
|
||||||
width: number;
|
width: number;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { EditorZone, ElementType, PageMode, TitleLevel } from '..'
|
import { EditorZone, ElementType, ListStyle, ListType, PageMode, TitleLevel } from '..'
|
||||||
import { RowFlex } from '../dataset/enum/Row'
|
import { RowFlex } from '../dataset/enum/Row'
|
||||||
import { IControl } from './Control'
|
import { IControl } from './Control'
|
||||||
import { IEditorResult } from './Editor'
|
import { IEditorResult } from './Editor'
|
||||||
@@ -20,6 +20,8 @@ export interface IRangeStyle {
|
|||||||
rowMargin: number;
|
rowMargin: number;
|
||||||
dashArray: number[];
|
dashArray: number[];
|
||||||
level: TitleLevel | null;
|
level: TitleLevel | null;
|
||||||
|
listType: ListType | null;
|
||||||
|
listStyle: ListStyle | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type IRangeStyleChange = (payload: IRangeStyle) => void
|
export type IRangeStyleChange = (payload: IRangeStyle) => void
|
||||||
|
|||||||
@@ -13,5 +13,8 @@ export interface IRow {
|
|||||||
rowFlex?: RowFlex;
|
rowFlex?: RowFlex;
|
||||||
startIndex: number;
|
startIndex: number;
|
||||||
isPageBreak?: boolean;
|
isPageBreak?: boolean;
|
||||||
|
isList?: boolean;
|
||||||
|
listIndex?: number;
|
||||||
|
offsetX?: number;
|
||||||
elementList: IRowElement[];
|
elementList: IRowElement[];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -137,6 +137,27 @@ export function formatElementList(elementList: IElement[], options: IFormatEleme
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
i--
|
i--
|
||||||
|
} else if (el.type === ElementType.LIST) {
|
||||||
|
// 移除父节点
|
||||||
|
elementList.splice(i, 1)
|
||||||
|
// 格式化元素
|
||||||
|
const valueList = el.valueList || []
|
||||||
|
formatElementList(valueList, {
|
||||||
|
...options
|
||||||
|
})
|
||||||
|
// 追加节点
|
||||||
|
if (valueList.length) {
|
||||||
|
const listId = getUUID()
|
||||||
|
for (let v = 0; v < valueList.length; v++) {
|
||||||
|
const value = valueList[v]
|
||||||
|
value.listId = listId
|
||||||
|
value.listType = el.listType
|
||||||
|
value.listStyle = el.listStyle
|
||||||
|
elementList.splice(i, 0, value)
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i--
|
||||||
} else if (el.type === ElementType.CONTROL) {
|
} else if (el.type === ElementType.CONTROL) {
|
||||||
const { prefix, postfix, value, placeholder, code, type, valueSets } = el.control!
|
const { prefix, postfix, value, placeholder, code, type, valueSets } = el.control!
|
||||||
const controlId = getUUID()
|
const controlId = getUUID()
|
||||||
@@ -422,6 +443,32 @@ export function zipElementList(payload: IElement[]): IElement[] {
|
|||||||
}
|
}
|
||||||
titleElement.valueList = zipElementList(valueList)
|
titleElement.valueList = zipElementList(valueList)
|
||||||
element = titleElement
|
element = titleElement
|
||||||
|
} else if (element.listId && element.listType) {
|
||||||
|
// 列表处理
|
||||||
|
const listId = element.listId
|
||||||
|
const listType = element.listType
|
||||||
|
const listStyle = element.listStyle
|
||||||
|
const listElement: IElement = {
|
||||||
|
type: ElementType.LIST,
|
||||||
|
value: '',
|
||||||
|
listId,
|
||||||
|
listType,
|
||||||
|
listStyle
|
||||||
|
}
|
||||||
|
const valueList: IElement[] = []
|
||||||
|
while (e < elementList.length) {
|
||||||
|
const listE = elementList[e]
|
||||||
|
if (listId !== listE.listId) {
|
||||||
|
e--
|
||||||
|
break
|
||||||
|
}
|
||||||
|
delete listE.listType
|
||||||
|
delete listE.listStyle
|
||||||
|
valueList.push(listE)
|
||||||
|
e++
|
||||||
|
}
|
||||||
|
listElement.valueList = zipElementList(valueList)
|
||||||
|
element = listElement
|
||||||
} else if (element.type === ElementType.CONTROL) {
|
} else if (element.type === ElementType.CONTROL) {
|
||||||
// 控件处理
|
// 控件处理
|
||||||
const controlId = element.controlId
|
const controlId = element.controlId
|
||||||
|
|||||||
+29
-1
@@ -1,7 +1,7 @@
|
|||||||
import { data, options } from './mock'
|
import { data, options } from './mock'
|
||||||
import './style.css'
|
import './style.css'
|
||||||
import prism from 'prismjs'
|
import prism from 'prismjs'
|
||||||
import Editor, { BlockType, Command, ControlType, EditorMode, ElementType, IBlock, IElement, KeyMap, PageMode, PaperDirection, RowFlex, TitleLevel } from './editor'
|
import Editor, { BlockType, Command, ControlType, EditorMode, ElementType, IBlock, IElement, KeyMap, ListStyle, ListType, PageMode, PaperDirection, RowFlex, TitleLevel } from './editor'
|
||||||
import { Dialog } from './components/dialog/Dialog'
|
import { Dialog } from './components/dialog/Dialog'
|
||||||
import { formatPrismToken } from './utils/prism'
|
import { formatPrismToken } from './utils/prism'
|
||||||
import { Signature } from './components/signature/Signature'
|
import { Signature } from './components/signature/Signature'
|
||||||
@@ -227,6 +227,19 @@ window.onload = function () {
|
|||||||
instance.command.executeRowMargin(Number(li.dataset.rowmargin!))
|
instance.command.executeRowMargin(Number(li.dataset.rowmargin!))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const listDom = document.querySelector<HTMLDivElement>('.menu-item__list')!
|
||||||
|
const listOptionDom = listDom.querySelector<HTMLDivElement>('.options')!
|
||||||
|
listDom.onclick = function () {
|
||||||
|
console.log('list')
|
||||||
|
listOptionDom.classList.toggle('visible')
|
||||||
|
}
|
||||||
|
listOptionDom.onclick = function (evt) {
|
||||||
|
const li = evt.target as HTMLLIElement
|
||||||
|
const listType = <ListType>li.dataset.listType || null
|
||||||
|
const listStyle = <ListStyle><unknown>li.dataset.listStyle
|
||||||
|
instance.command.executeList(listType, listStyle)
|
||||||
|
}
|
||||||
|
|
||||||
// 4. | 表格 | 图片 | 超链接 | 分割线 | 水印 | 代码块 | 分隔符 | 控件 | 复选框 | LaTeX | 日期选择器
|
// 4. | 表格 | 图片 | 超链接 | 分割线 | 水印 | 代码块 | 分隔符 | 控件 | 复选框 | LaTeX | 日期选择器
|
||||||
const tableDom = document.querySelector<HTMLDivElement>('.menu-item__table')!
|
const tableDom = document.querySelector<HTMLDivElement>('.menu-item__table')!
|
||||||
const tablePanelContainer = document.querySelector<HTMLDivElement>('.menu-item__table__collapse')!
|
const tablePanelContainer = document.querySelector<HTMLDivElement>('.menu-item__table__collapse')!
|
||||||
@@ -1080,6 +1093,21 @@ window.onload = function () {
|
|||||||
titleSelectDom.innerText = '正文'
|
titleSelectDom.innerText = '正文'
|
||||||
titleOptionDom.querySelector('li:first-child')!.classList.add('active')
|
titleOptionDom.querySelector('li:first-child')!.classList.add('active')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 列表
|
||||||
|
listOptionDom.querySelectorAll<HTMLLIElement>('li').forEach(li => li.classList.remove('active'))
|
||||||
|
if (payload.listType) {
|
||||||
|
const listType = payload.listType
|
||||||
|
const listStyle = payload.listType === ListType.OL ? ListStyle.DECIMAL : payload.listType
|
||||||
|
const curListDom = listOptionDom
|
||||||
|
.querySelector<HTMLLIElement>(`[data-list-type='${listType}'][data-list-style='${listStyle}']`)
|
||||||
|
if (curListDom) {
|
||||||
|
curListDom.classList.add('active')
|
||||||
|
listDom.classList.add('active')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
listDom.classList.remove('active')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
instance.listener.visiblePageNoListChange = function (payload) {
|
instance.listener.visiblePageNoListChange = function (payload) {
|
||||||
|
|||||||
+22
-3
@@ -1,6 +1,6 @@
|
|||||||
import { ControlType, ElementType, IEditorOption, IElement, TitleLevel } from './editor'
|
import { ControlType, ElementType, IEditorOption, IElement, ListType, TitleLevel } from './editor'
|
||||||
|
|
||||||
const text = `主诉:\n发热三天,咳嗽五天。\n现病史:\n患者于三天前无明显诱因,感冒后发现面部水肿,无皮疹,尿量减少,出现乏力,在外治疗无好转,现来我院就诊。\n既往史:\n有糖尿病10年,有高血压2年,有传染性疾病1年。报告其他既往疾病。\n流行病史:\n否认14天内接触过确诊患者、疑似患者、无症状感染者及其密切接触者;否认14天内去过以下场所:水产、肉类批发市场,农贸市场,集市,大型超市,夜市;否认14天内与以下场所工作人员密切接触:水产、肉类批发市场,农贸市场,集市,大型超市;否认14天内周围(如家庭、办公室)有2例以上聚集性发病;否认14天内接触过有发热或呼吸道症状的人员;否认14天内自身有发热或呼吸道症状;否认14天内接触过纳入隔离观察的人员及其他可能与新冠肺炎关联的情形;陪同家属无以上情况。\n体格检查:\nT:39.5℃,P:80bpm,R:20次/分,BP:120/80mmHg;\n辅助检查:\n2020年6月10日,普放:血细胞比容36.50%(偏低)40~50;单核细胞绝对值0.75*10/L(偏高)参考值:0.1~0.6;\n门诊诊断:\n1.高血压\n2.糖尿病\n3.病毒性感冒\n4.过敏性鼻炎\n5.过敏性鼻息肉\n处置治疗:\n1.超声引导下甲状腺细针穿刺术;\n2.乙型肝炎表面抗体测定;\n3.膜式病变细胞采集术、后颈皮下肤层;\n电子签名:【】\n其他记录:`
|
const text = `主诉:\n发热三天,咳嗽五天。\n现病史:\n患者于三天前无明显诱因,感冒后发现面部水肿,无皮疹,尿量减少,出现乏力,在外治疗无好转,现来我院就诊。\n既往史:\n有糖尿病10年,有高血压2年,有传染性疾病1年。报告其他既往疾病。\n流行病史:\n否认14天内接触过确诊患者、疑似患者、无症状感染者及其密切接触者;否认14天内去过以下场所:水产、肉类批发市场,农贸市场,集市,大型超市,夜市;否认14天内与以下场所工作人员密切接触:水产、肉类批发市场,农贸市场,集市,大型超市;否认14天内周围(如家庭、办公室)有2例以上聚集性发病;否认14天内接触过有发热或呼吸道症状的人员;否认14天内自身有发热或呼吸道症状;否认14天内接触过纳入隔离观察的人员及其他可能与新冠肺炎关联的情形;陪同家属无以上情况。\n体格检查:\nT:39.5℃,P:80bpm,R:20次/分,BP:120/80mmHg;\n辅助检查:\n2020年6月10日,普放:血细胞比容36.50%(偏低)40~50;单核细胞绝对值0.75*10/L(偏高)参考值:0.1~0.6;\n门诊诊断:处置治疗:电子签名:【】\n其他记录:`
|
||||||
|
|
||||||
// 模拟标题
|
// 模拟标题
|
||||||
const titleText = ['主诉:', '现病史:', '既往史:', '流行病史:', '体格检查:', '辅助检查:', '门诊诊断:', '处置治疗:', '电子签名:', '其他记录:']
|
const titleText = ['主诉:', '现病史:', '既往史:', '流行病史:', '体格检查:', '辅助检查:', '门诊诊断:', '处置治疗:', '电子签名:', '其他记录:']
|
||||||
@@ -135,8 +135,27 @@ elementList.splice(429, 0, {
|
|||||||
type: ElementType.SUPERSCRIPT
|
type: ElementType.SUPERSCRIPT
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 模拟列表
|
||||||
|
elementList.splice(450, 0, {
|
||||||
|
value: '',
|
||||||
|
type: ElementType.LIST,
|
||||||
|
listType: ListType.OL,
|
||||||
|
valueList: [{
|
||||||
|
value: '高血压\n糖尿病\n病毒性感冒\n过敏性鼻炎\n过敏性鼻息肉'
|
||||||
|
}]
|
||||||
|
})
|
||||||
|
|
||||||
|
elementList.splice(452, 0, {
|
||||||
|
value: '',
|
||||||
|
type: ElementType.LIST,
|
||||||
|
listType: ListType.OL,
|
||||||
|
valueList: [{
|
||||||
|
value: '超声引导下甲状腺细针穿刺术;\n乙型肝炎表面抗体测定;\n膜式病变细胞采集术、后颈皮下肤层;'
|
||||||
|
}]
|
||||||
|
})
|
||||||
|
|
||||||
// 模拟图片
|
// 模拟图片
|
||||||
elementList.splice(543, 0, {
|
elementList.splice(455, 0, {
|
||||||
value: `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFkAAAAgCAYAAAB5JtSmAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAQ0SURBVGhD7dhrUSNBFAVgvKACEVjAAhJQgAIUYAABGEAABvgfAdn6UnWou01PppOZhIXNj1P9vo9zH5PK1Waz2V5wWlxIPgMuJJ8Bi0h+fn7eXl9fb29ubrYPDw/dO/8DHh8fu/vB4kym4Orqaofb29vund8OSSbhemewSrugBMnG3vlvw9vb265yn56edmtz/t/f33+5C8MkixQSZSsl9UzLOHUmcwTYAN/Rpl5eXnY+pnIB0Xd3d7s5m3rvDsrkCGszNiQ7r/tr4v39fSc/uipOqRcqufTHBiO78GGdzG5xcLtIFmVde7L9NsvXRo9s84+Pj+79pUAwn5GcD1wIz5r+fYGeJdnjGiF9hwL7iWAcfX19/evtKVHJXrtN8Rf4A3TVczqhrut5i1mSZQgnIriSWtdzP2N+EvIhi3/GWqHWtWXuy2IYbheiKarJZIZknkxyrryc2Utrgal+9S8iScUXIx/3kcxfe/jotcuDezLFlIbARDrzHpytXdKnQr4xyc74Vu9YV5Ih2Q/tT7mDSEYw5ZU4wu3nJx64k/1z9umlUG0hah/JSbC6Jzi5exDJWoTHERoBxu8uf/pT1j3HDkUIJitjbRfRA/iwVzlgy1RCfSF5ili9xj7BUWKs9wJZ3MpditYu+lsc+/PRx53cVF9Pdg/syE9Hb6cS75PkmhUEUFofmTvLGEXKimHueJP9Y3swWQwGLUiA9xEbHKuvgs4pPe1+1myTAKlw81buJ8kigjAXKauXPLQPhEYgJSEYsgdTUR0BmTVgc6C359wcvKGnBrGO8dO5VlD1ZZ519nrBHvrwKVMCas9hgL0YUI2wV98fC4FqCWizzXyqF44A0ZKLHkilgvPs1zbiTuZIdZ414KvqGCKZYx4zple+MSrrJVncAyL02/TOqncJwVMglx5zI4QDZ5WPvBGEcNP+7TlEcqJIAQFGsIdQjmZt7MlYA5yiI3pOQTCQXUm2TuVmXgmewxDJQDgl6deJJoU5y7p9uwZagmu1mCvbNoOOBfkhOf6lRZjzPb8qRjBMMiUhM9GNMZQq5/oRXBP7Mlj/i12A7EMIaJGqDcl8I79+/N1xTvdINQ2TDAQSvI9Md479vdqCHKSFQKAfEmgBqCTDkjaSgOZXQkg2jy1ti0xApnBQJo/0obQRipeQXbN3CmxKGQch5xgki4Efghl/kFqzPD//2DnXIodIRpaoETaXxcmwGNO7N4I2Oyuc6b+xK/tL9IH3kY/E+r1JdST4yM+7VUiuJbuPZHBeHZcNvXtziMMV9mRuvUOX8Vg9IFjRx9dUYM3s2oJyNx9ahFfSWwyRHKHG3nmL2q/mojyFVAWnEdi2Hg7OBXwUCCKr1QEtoe0+/9jI3xqIiuF2QRD0zqcwpfQnge9TVSI4tWrNe79shj98F0xDC0N4bTUVF5LPgAvJJ8dm+wcP2iJuZNdC5QAAAABJRU5ErkJggg==`,
|
value: `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFkAAAAgCAYAAAB5JtSmAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAQ0SURBVGhD7dhrUSNBFAVgvKACEVjAAhJQgAIUYAABGEAABvgfAdn6UnWou01PppOZhIXNj1P9vo9zH5PK1Waz2V5wWlxIPgMuJJ8Bi0h+fn7eXl9fb29ubrYPDw/dO/8DHh8fu/vB4kym4Orqaofb29vund8OSSbhemewSrugBMnG3vlvw9vb265yn56edmtz/t/f33+5C8MkixQSZSsl9UzLOHUmcwTYAN/Rpl5eXnY+pnIB0Xd3d7s5m3rvDsrkCGszNiQ7r/tr4v39fSc/uipOqRcqufTHBiO78GGdzG5xcLtIFmVde7L9NsvXRo9s84+Pj+79pUAwn5GcD1wIz5r+fYGeJdnjGiF9hwL7iWAcfX19/evtKVHJXrtN8Rf4A3TVczqhrut5i1mSZQgnIriSWtdzP2N+EvIhi3/GWqHWtWXuy2IYbheiKarJZIZknkxyrryc2Utrgal+9S8iScUXIx/3kcxfe/jotcuDezLFlIbARDrzHpytXdKnQr4xyc74Vu9YV5Ih2Q/tT7mDSEYw5ZU4wu3nJx64k/1z9umlUG0hah/JSbC6Jzi5exDJWoTHERoBxu8uf/pT1j3HDkUIJitjbRfRA/iwVzlgy1RCfSF5ili9xj7BUWKs9wJZ3MpditYu+lsc+/PRx53cVF9Pdg/syE9Hb6cS75PkmhUEUFofmTvLGEXKimHueJP9Y3swWQwGLUiA9xEbHKuvgs4pPe1+1myTAKlw81buJ8kigjAXKauXPLQPhEYgJSEYsgdTUR0BmTVgc6C359wcvKGnBrGO8dO5VlD1ZZ519nrBHvrwKVMCas9hgL0YUI2wV98fC4FqCWizzXyqF44A0ZKLHkilgvPs1zbiTuZIdZ414KvqGCKZYx4zple+MSrrJVncAyL02/TOqncJwVMglx5zI4QDZ5WPvBGEcNP+7TlEcqJIAQFGsIdQjmZt7MlYA5yiI3pOQTCQXUm2TuVmXgmewxDJQDgl6deJJoU5y7p9uwZagmu1mCvbNoOOBfkhOf6lRZjzPb8qRjBMMiUhM9GNMZQq5/oRXBP7Mlj/i12A7EMIaJGqDcl8I79+/N1xTvdINQ2TDAQSvI9Md479vdqCHKSFQKAfEmgBqCTDkjaSgOZXQkg2jy1ti0xApnBQJo/0obQRipeQXbN3CmxKGQch5xgki4Efghl/kFqzPD//2DnXIodIRpaoETaXxcmwGNO7N4I2Oyuc6b+xK/tL9IH3kY/E+r1JdST4yM+7VUiuJbuPZHBeHZcNvXtziMMV9mRuvUOX8Vg9IFjRx9dUYM3s2oJyNx9ahFfSWwyRHKHG3nmL2q/mojyFVAWnEdi2Hg7OBXwUCCKr1QEtoe0+/9jI3xqIiuF2QRD0zqcwpfQnge9TVSI4tWrNe79shj98F0xDC0N4bTUVF5LPgAvJJ8dm+wcP2iJuZNdC5QAAAABJRU5ErkJggg==`,
|
||||||
width: 89,
|
width: 89,
|
||||||
height: 32,
|
height: 32,
|
||||||
|
|||||||
@@ -304,6 +304,26 @@ ul {
|
|||||||
background-image: url('./assets/images/row-margin.svg');
|
background-image: url('./assets/images/row-margin.svg');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.menu-item__list {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-item__list i {
|
||||||
|
background-image: url('./assets/images/list.svg');
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-item__list .options {
|
||||||
|
width: 110px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-item__list .options>ul>li * {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-item__list .options>ul>li li {
|
||||||
|
margin-left: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
.menu-item__image i {
|
.menu-item__image i {
|
||||||
background-image: url('./assets/images/image.svg');
|
background-image: url('./assets/images/image.svg');
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user