diff --git a/docs/en/guide/command-execute.md b/docs/en/guide/command-execute.md
index 79e0e24..c2463e6 100644
--- a/docs/en/guide/command-execute.md
+++ b/docs/en/guide/command-execute.md
@@ -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
diff --git a/docs/en/guide/i18n.md b/docs/en/guide/i18n.md
index 17f4c2d..bd5bbbc 100644
--- a/docs/en/guide/i18n.md
+++ b/docs/en/guide/i18n.md
@@ -63,6 +63,8 @@ interface ILang {
borderAll: string
borderEmpty: string
borderExternal: string
+ borderTd: string
+ borderTdBottom: string
}
}
datePicker: {
diff --git a/docs/en/guide/schema.md b/docs/en/guide/schema.md
index 29e1bc6..4420254 100644
--- a/docs/en/guide/schema.md
+++ b/docs/en/guide/schema.md
@@ -54,6 +54,7 @@ interface IElement {
rowspan: number;
verticalAlign?: VerticalAlign;
backgroundColor?: string;
+ borderType?: TdBorder;
value: IElement[];
}[];
}[];
diff --git a/docs/guide/command-execute.md b/docs/guide/command-execute.md
index 4ca07f5..533c341 100644
--- a/docs/guide/command-execute.md
+++ b/docs/guide/command-execute.md
@@ -419,6 +419,16 @@ instance.command.executeTableTdVerticalAlign(payload: VerticalAlign)
instance.command.executeTableBorderType(payload: TableBorder)
```
+## executeTableTdBorderType
+
+功能:表格单元格边框类型
+
+用法:
+
+```javascript
+instance.command.executeTableTdBorderType(payload: TdBorder)
+```
+
## executeTableTdBackgroundColor
功能:表格单元格背景色
diff --git a/docs/guide/i18n.md b/docs/guide/i18n.md
index 0857ead..76654b4 100644
--- a/docs/guide/i18n.md
+++ b/docs/guide/i18n.md
@@ -63,6 +63,8 @@ interface ILang {
borderAll: string
borderEmpty: string
borderExternal: string
+ borderTd: string
+ borderTdBottom: string
}
}
datePicker: {
diff --git a/docs/guide/schema.md b/docs/guide/schema.md
index 5de455a..59a41b0 100644
--- a/docs/guide/schema.md
+++ b/docs/guide/schema.md
@@ -54,6 +54,7 @@ interface IElement {
rowspan: number;
verticalAlign?: VerticalAlign;
backgroundColor?: string;
+ borderType?: TdBorder;
value: IElement[];
}[];
}[];
diff --git a/src/editor/assets/css/contextmenu/contextmenu.css b/src/editor/assets/css/contextmenu/contextmenu.css
index dc6a7af..c6ae576 100644
--- a/src/editor/assets/css/contextmenu/contextmenu.css
+++ b/src/editor/assets/css/contextmenu/contextmenu.css
@@ -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);
}
\ No newline at end of file
diff --git a/src/editor/assets/images/table-border-td-bottom.svg b/src/editor/assets/images/table-border-td-bottom.svg
new file mode 100644
index 0000000..952b9e2
--- /dev/null
+++ b/src/editor/assets/images/table-border-td-bottom.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/editor/assets/images/table-border-td.svg b/src/editor/assets/images/table-border-td.svg
new file mode 100644
index 0000000..219d5f6
--- /dev/null
+++ b/src/editor/assets/images/table-border-td.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/editor/core/command/Command.ts b/src/editor/core/command/Command.ts
index 2f81632..32c1d13 100644
--- a/src/editor/core/command/Command.ts
+++ b/src/editor/core/command/Command.ts
@@ -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)
diff --git a/src/editor/core/command/CommandAdapt.ts b/src/editor/core/command/CommandAdapt.ts
index f39b643..b6db916 100644
--- a/src/editor/core/command/CommandAdapt.ts
+++ b/src/editor/core/command/CommandAdapt.ts
@@ -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
diff --git a/src/editor/core/contextmenu/menus/tableMenus.ts b/src/editor/core/contextmenu/menus/tableMenus.ts
index ca51bc6..6e33697 100644
--- a/src/editor/core/contextmenu/menus/tableMenus.ts
+++ b/src/editor/core/contextmenu/menus/tableMenus.ts
@@ -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)
+ }
+ }
+ ]
}
]
},
diff --git a/src/editor/core/draw/particle/table/TableParticle.ts b/src/editor/core/draw/particle/table/TableParticle.ts
index 017ff03..f1ae929 100644
--- a/src/editor/core/draw/particle/table/TableParticle.ts
+++ b/src/editor/core/draw/particle/table/TableParticle.ts
@@ -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()
diff --git a/src/editor/core/i18n/lang/en.json b/src/editor/core/i18n/lang/en.json
index e8e22c4..00f96a9 100644
--- a/src/editor/core/i18n/lang/en.json
+++ b/src/editor/core/i18n/lang/en.json
@@ -43,7 +43,9 @@
"border": "Table border",
"borderAll": "All",
"borderEmpty": "Empty",
- "borderExternal": "External"
+ "borderExternal": "External",
+ "borderTd": "Table cell border",
+ "borderTdBottom": "Bottom"
}
},
"datePicker": {
diff --git a/src/editor/core/i18n/lang/zh-CN.json b/src/editor/core/i18n/lang/zh-CN.json
index de44f3f..49e22ac 100644
--- a/src/editor/core/i18n/lang/zh-CN.json
+++ b/src/editor/core/i18n/lang/zh-CN.json
@@ -43,7 +43,9 @@
"border": "表格边框",
"borderAll": "所有框线",
"borderEmpty": "无框线",
- "borderExternal": "外侧框线"
+ "borderExternal": "外侧框线",
+ "borderTd": "单元格边框",
+ "borderTdBottom": "下边框"
}
},
"datePicker": {
diff --git a/src/editor/dataset/constant/Element.ts b/src/editor/dataset/constant/Element.ts
index 947f14a..891a085 100644
--- a/src/editor/dataset/constant/Element.ts
+++ b/src/editor/dataset/constant/Element.ts
@@ -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 = [
'bold',
@@ -61,6 +62,12 @@ export const EDITOR_ELEMENT_ZIP_ATTR: Array = [
'groupIds'
]
+export const TABLE_TD_ZIP_ATTR: Array = [
+ 'verticalAlign',
+ 'backgroundColor',
+ 'borderType'
+]
+
export const TABLE_CONTEXT_ATTR: Array = [
'tdId',
'trId',
diff --git a/src/editor/dataset/enum/table/Table.ts b/src/editor/dataset/enum/table/Table.ts
index 927075c..6482dc3 100644
--- a/src/editor/dataset/enum/table/Table.ts
+++ b/src/editor/dataset/enum/table/Table.ts
@@ -3,3 +3,7 @@ export enum TableBorder {
EMPTY = 'empty',
EXTERNAL = 'external'
}
+
+export enum TdBorder {
+ BOTTOM = 'bottom'
+}
diff --git a/src/editor/index.ts b/src/editor/index.ts
index bb90342..0e89946 100644
--- a/src/editor/index.ts
+++ b/src/editor/index.ts
@@ -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,
diff --git a/src/editor/interface/table/Td.ts b/src/editor/interface/table/Td.ts
index c35e41b..12ddb5b 100644
--- a/src/editor/interface/table/Td.ts
+++ b/src/editor/interface/table/Td.ts
@@ -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 // 真实最小高度(包含跨列)
diff --git a/src/editor/utils/element.ts b/src/editor/utils/element.ts
index f3738b5..78682cb 100644
--- a/src/editor/utils/element.ts
+++ b/src/editor/utils/element.ts
@@ -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
}
}