feat: add table td border type

pr675
Hufe921 3 years ago
parent 7260b6439b
commit d8876b1095

@ -419,6 +419,16 @@ Usage:
instance.command.executeTableBorderType(payload: TableBorder)
```
## executeTableTdBorderType
Feature: Table td border type
Usage:
```javascript
instance.command.executeTableTdBorderType(payload: TableBorder)
```
## executeTableTdBackgroundColor
Feature: Table cell background color

@ -63,6 +63,8 @@ interface ILang {
borderAll: string
borderEmpty: string
borderExternal: string
borderTd: string
borderTdBottom: string
}
}
datePicker: {

@ -54,6 +54,7 @@ interface IElement {
rowspan: number;
verticalAlign?: VerticalAlign;
backgroundColor?: string;
borderType?: TdBorder;
value: IElement[];
}[];
}[];

@ -419,6 +419,16 @@ instance.command.executeTableTdVerticalAlign(payload: VerticalAlign)
instance.command.executeTableBorderType(payload: TableBorder)
```
## executeTableTdBorderType
功能:表格单元格边框类型
用法:
```javascript
instance.command.executeTableTdBorderType(payload: TdBorder)
```
## executeTableTdBackgroundColor
功能:表格单元格背景色

@ -63,6 +63,8 @@ interface ILang {
borderAll: string
borderEmpty: string
borderExternal: string
borderTd: string
borderTdBottom: string
}
}
datePicker: {

@ -54,6 +54,7 @@ interface IElement {
rowspan: number;
verticalAlign?: VerticalAlign;
backgroundColor?: string;
borderType?: TdBorder;
value: IElement[];
}[];
}[];

@ -157,4 +157,12 @@
.ce-contextmenu-border-external {
background-image: url(../../../assets/images/table-border-external.svg);
}
.ce-contextmenu-border-td {
background-image: url(../../../assets/images/table-border-td.svg);
}
.ce-contextmenu-border-td-bottom {
background-image: url(../../../assets/images/table-border-td-bottom.svg);
}

@ -0,0 +1 @@
<svg width="16" height="16" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M2.5 3a.5.5 0 01.5-.5h11a.5.5 0 01.5.5v11a.5.5 0 01-.5.5H3a.5.5 0 01-.5-.5V3z" stroke="#AAACB0"/><path stroke="#3D4757" d="M2.5 8.5 h12"/></svg>

After

Width:  |  Height:  |  Size: 228 B

@ -0,0 +1 @@
<svg width="16" height="16" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M2.5 3a.5.5 0 01.5-.5h11a.5.5 0 01.5.5v11a.5.5 0 01-.5.5H3a.5.5 0 01-.5-.5V3z" stroke="#AAACB0"/><path stroke="#3D4757" d="M8.5 2.5 v6 h-6"/></svg>

After

Width:  |  Height:  |  Size: 231 B

@ -43,6 +43,7 @@ export class Command {
public executeCancelMergeTableCell: CommandAdapt['cancelMergeTableCell']
public executeTableTdVerticalAlign: CommandAdapt['tableTdVerticalAlign']
public executeTableBorderType: CommandAdapt['tableBorderType']
public executeTableTdBorderType: CommandAdapt['tableTdBorderType']
public executeTableTdBackgroundColor: CommandAdapt['tableTdBackgroundColor']
public executeTableSelectAll: CommandAdapt['tableSelectAll']
public executeImage: CommandAdapt['image']
@ -143,6 +144,7 @@ export class Command {
this.executeCancelMergeTableCell = adapt.cancelMergeTableCell.bind(adapt)
this.executeTableTdVerticalAlign = adapt.tableTdVerticalAlign.bind(adapt)
this.executeTableBorderType = adapt.tableBorderType.bind(adapt)
this.executeTableTdBorderType = adapt.tableTdBorderType.bind(adapt)
this.executeTableTdBackgroundColor =
adapt.tableTdBackgroundColor.bind(adapt)
this.executeTableSelectAll = adapt.tableSelectAll.bind(adapt)

@ -13,7 +13,7 @@ import { ElementType } from '../../dataset/enum/Element'
import { ElementStyleKey } from '../../dataset/enum/ElementStyle'
import { ListStyle, ListType } from '../../dataset/enum/List'
import { RowFlex } from '../../dataset/enum/Row'
import { TableBorder } from '../../dataset/enum/table/Table'
import { TableBorder, TdBorder } from '../../dataset/enum/table/Table'
import { TitleLevel } from '../../dataset/enum/Title'
import { VerticalAlign } from '../../dataset/enum/VerticalAlign'
import { ICatalog } from '../../interface/Catalog'
@ -1227,6 +1227,27 @@ export class CommandAdapt {
})
}
public tableTdBorderType(payload: TdBorder) {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
const rowCol = this.draw.getTableParticle().getRangeRowCol()
if (!rowCol) return
const tdList = rowCol.flat()
// 存在则设置边框类型,否则取消设置
const isSetBorderType = tdList.some(td => td.borderType !== payload)
tdList.forEach(td => {
if (isSetBorderType) {
td.borderType = payload
} else {
delete td.borderType
}
})
const { endIndex } = this.range.getRange()
this.draw.render({
curIndex: endIndex
})
}
public tableTdBackgroundColor(payload: string) {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return

@ -1,5 +1,5 @@
import { VerticalAlign } from '../../../dataset/enum/VerticalAlign'
import { TableBorder } from '../../../dataset/enum/table/Table'
import { TableBorder, TdBorder } from '../../../dataset/enum/table/Table'
import { IRegisterContextMenu } from '../../../interface/contextmenu/ContextMenu'
import { Command } from '../../command/Command'
@ -37,6 +37,21 @@ export const tableMenus: IRegisterContextMenu[] = [
callback: (command: Command) => {
command.executeTableBorderType(TableBorder.EXTERNAL)
}
},
{
i18nPath: 'contextmenu.table.borderTd',
icon: 'border-td',
when: () => true,
childMenus: [
{
i18nPath: 'contextmenu.table.borderTdBottom',
icon: 'border-td-bottom',
when: () => true,
callback: (command: Command) => {
command.executeTableTdBorderType(TdBorder.BOTTOM)
}
}
]
}
]
},

@ -1,4 +1,5 @@
import { ElementType, IElement, TableBorder } from '../../../..'
import { TdBorder } from '../../../../dataset/enum/table/Table'
import { IEditorOption } from '../../../../interface/Editor'
import { ITd } from '../../../../interface/table/Td'
import { ITr } from '../../../../interface/table/Tr'
@ -122,40 +123,55 @@ export class TableParticle {
startY: number
) {
const { colgroup, trList, borderType } = element
if (!colgroup || !trList || borderType === TableBorder.EMPTY) return
if (!colgroup || !trList) return
const { scale } = this.options
const tableWidth = element.width! * scale
const tableHeight = element.height! * scale
// 无边框
const isEmptyBorderType = borderType === TableBorder.EMPTY
// 仅外边框
const isExternalBorderType = borderType === TableBorder.EXTERNAL
ctx.save()
// 渲染边框
this._drawOuterBorder({
ctx,
startX,
startY,
width: tableWidth,
height: tableHeight,
isDrawFullBorder: isExternalBorderType
})
if (!isExternalBorderType) {
// 渲染表格
for (let t = 0; t < trList.length; t++) {
const tr = trList[t]
for (let d = 0; d < tr.tdList.length; d++) {
const td = tr.tdList[d]
const width = td.width! * scale
const height = td.height! * scale
const x = Math.round(td.x! * scale + startX + width)
const y = Math.round(td.y! * scale + startY)
ctx.translate(0.5, 0.5)
// 绘制线条
ctx.beginPath()
if (!isEmptyBorderType) {
this._drawOuterBorder({
ctx,
startX,
startY,
width: tableWidth,
height: tableHeight,
isDrawFullBorder: isExternalBorderType
})
}
// 渲染单元格
for (let t = 0; t < trList.length; t++) {
const tr = trList[t]
for (let d = 0; d < tr.tdList.length; d++) {
const td = tr.tdList[d]
// 没有设置单元格边框 && 没有设置表格边框则忽略
if (!td.borderType && (isEmptyBorderType || isExternalBorderType)) {
continue
}
const width = td.width! * scale
const height = td.height! * scale
const x = Math.round(td.x! * scale + startX + width)
const y = Math.round(td.y! * scale + startY)
ctx.translate(0.5, 0.5)
// 绘制线条
ctx.beginPath()
if (td.borderType === TdBorder.BOTTOM) {
ctx.moveTo(x, y + height)
ctx.lineTo(x - width, y + height)
ctx.stroke()
}
if (!isEmptyBorderType && !isExternalBorderType) {
ctx.moveTo(x, y + height)
ctx.moveTo(x, y)
ctx.lineTo(x, y + height)
ctx.lineTo(x - width, y + height)
ctx.stroke()
ctx.translate(-0.5, -0.5)
}
ctx.translate(-0.5, -0.5)
}
}
ctx.restore()

@ -43,7 +43,9 @@
"border": "Table border",
"borderAll": "All",
"borderEmpty": "Empty",
"borderExternal": "External"
"borderExternal": "External",
"borderTd": "Table cell border",
"borderTdBottom": "Bottom"
}
},
"datePicker": {

@ -43,7 +43,9 @@
"border": "表格边框",
"borderAll": "所有框线",
"borderEmpty": "无框线",
"borderExternal": "外侧框线"
"borderExternal": "外侧框线",
"borderTd": "单元格边框",
"borderTdBottom": "下边框"
}
},
"datePicker": {

@ -1,5 +1,6 @@
import { ElementType } from '../enum/Element'
import { IElement } from '../../interface/Element'
import { ITd } from '../../interface/table/Td'
export const EDITOR_ELEMENT_STYLE_ATTR: Array<keyof IElement> = [
'bold',
@ -61,6 +62,12 @@ export const EDITOR_ELEMENT_ZIP_ATTR: Array<keyof IElement> = [
'groupIds'
]
export const TABLE_TD_ZIP_ATTR: Array<keyof ITd> = [
'verticalAlign',
'backgroundColor',
'borderType'
]
export const TABLE_CONTEXT_ATTR: Array<keyof IElement> = [
'tdId',
'trId',

@ -3,3 +3,7 @@ export enum TableBorder {
EMPTY = 'empty',
EXTERNAL = 'external'
}
export enum TdBorder {
BOTTOM = 'bottom'
}

@ -44,7 +44,7 @@ import { defaultCursorOption } from './dataset/constant/Cursor'
import { IPageNumber } from './interface/PageNumber'
import { defaultPageNumberOption } from './dataset/constant/PageNumber'
import { VerticalAlign } from './dataset/enum/VerticalAlign'
import { TableBorder } from './dataset/enum/table/Table'
import { TableBorder, TdBorder } from './dataset/enum/table/Table'
import { IFooter } from './interface/Footer'
import { defaultFooterOption } from './dataset/constant/Footer'
import { MaxHeightRatio, NumberType } from './dataset/enum/Common'
@ -259,6 +259,7 @@ export {
BlockType,
PaperDirection,
TableBorder,
TdBorder,
MaxHeightRatio,
NumberType,
TitleLevel,

@ -1,4 +1,5 @@
import { VerticalAlign } from '../../dataset/enum/VerticalAlign'
import { TdBorder } from '../../dataset/enum/table/Table'
import { IElement, IElementPosition } from '../Element'
import { IRow } from '../Row'
@ -20,6 +21,7 @@ export interface ITd {
positionList?: IElementPosition[]
verticalAlign?: VerticalAlign
backgroundColor?: string
borderType?: TdBorder
mainHeight?: number // 内容 + 内边距高度
realHeight?: number // 真实高度(包含跨列)
realMinHeight?: number // 真实最小高度(包含跨列)

@ -14,6 +14,7 @@ import {
EDITOR_ELEMENT_ZIP_ATTR,
INLINE_NODE_NAME,
TABLE_CONTEXT_ATTR,
TABLE_TD_ZIP_ATTR,
TEXTLIKE_ELEMENT_TYPE
} from '../dataset/constant/Element'
import {
@ -483,12 +484,13 @@ export function zipElementList(payload: IElement[]): IElement[] {
rowspan: td.rowspan,
value: zipElementList(td.value)
}
if (td.verticalAlign) {
zipTd.verticalAlign = td.verticalAlign
}
if (td.backgroundColor) {
zipTd.backgroundColor = td.backgroundColor
}
// 压缩单元格属性
TABLE_TD_ZIP_ATTR.forEach(attr => {
const value = td[attr] as never
if (value !== undefined) {
zipTd[attr] = value
}
})
tr.tdList[d] = zipTd
}
}

Loading…
Cancel
Save