From 040d3db89e3a70ef19814c0021ebdddddee8e312 Mon Sep 17 00:00:00 2001 From: lijinke666 Date: Fri, 28 Jun 2024 15:49:00 +0800 Subject: [PATCH 1/4] =?UTF-8?q?feat:=20=E7=BB=9F=E4=B8=80=E9=93=BE?= =?UTF-8?q?=E6=8E=A5=E8=B7=B3=E8=BD=AC=E5=AD=97=E6=AE=B5=E7=BB=98=E5=88=B6?= =?UTF-8?q?=E7=BB=9F=E4=B8=80,=20=E6=94=AF=E6=8C=81=E6=A0=87=E8=AE=B0?= =?UTF-8?q?=E5=88=97=E5=A4=B4=20close=20#2430?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../__snapshots__/theme-spec.ts.snap | 18 +++ ...spec.ts => header-cell-link-click-spec.ts} | 109 +++++++++++++----- ...spec.ts => header-cell-link-click-spec.ts} | 10 +- .../__tests__/unit/interaction/root-spec.ts | 4 +- packages/s2-core/src/cell/base-cell.ts | 16 ++- packages/s2-core/src/cell/row-cell.ts | 7 -- .../src/common/constant/interaction.ts | 2 +- .../click/header-cell-link-click.ts | 64 ++++++++++ .../base-interaction/click/index.ts | 2 +- .../base-interaction/click/row-text-click.ts | 52 --------- packages/s2-core/src/interaction/root.ts | 6 +- packages/s2-core/src/theme/index.ts | 3 + .../src/utils/interaction/link-field.ts | 22 ++-- packages/s2-react/playground/config.tsx | 54 +++++++-- s2-site/docs/api/general/S2Event.zh.md | 2 +- .../manual/advanced/interaction/basic.zh.md | 2 +- .../advanced/interaction/link-jump.zh.md | 78 ++++++++++--- s2-site/docs/manual/migration-v2.zh.md | 14 +++ .../advanced/demo/custom-link-jump.ts | 68 +++++++++++ .../advanced/demo/custom-tree-link-jump.ts | 5 +- .../interaction/advanced/demo/meta.json | 9 ++ .../advanced/demo/pivot-link-jump.ts | 7 +- 22 files changed, 404 insertions(+), 150 deletions(-) rename packages/s2-core/__tests__/spreadsheet/{row-link-spec.ts => header-cell-link-click-spec.ts} (61%) rename packages/s2-core/__tests__/unit/interaction/base-interaction/click/{row-text-click-spec.ts => header-cell-link-click-spec.ts} (72%) create mode 100644 packages/s2-core/src/interaction/base-interaction/click/header-cell-link-click.ts delete mode 100644 packages/s2-core/src/interaction/base-interaction/click/row-text-click.ts create mode 100644 s2-site/examples/interaction/advanced/demo/custom-link-jump.ts diff --git a/packages/s2-core/__tests__/spreadsheet/__snapshots__/theme-spec.ts.snap b/packages/s2-core/__tests__/spreadsheet/__snapshots__/theme-spec.ts.snap index 7c44b545ce..6572cf2782 100644 --- a/packages/s2-core/__tests__/spreadsheet/__snapshots__/theme-spec.ts.snap +++ b/packages/s2-core/__tests__/spreadsheet/__snapshots__/theme-spec.ts.snap @@ -12,6 +12,7 @@ Object { "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif", "fontSize": 12, "fontWeight": 700, + "linkTextFill": "#2C60D4", "opacity": 1, "textAlign": "center", "textBaseline": "middle", @@ -76,6 +77,7 @@ Object { "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif", "fontSize": 12, "fontWeight": "normal", + "linkTextFill": "#2C60D4", "opacity": 1, "textAlign": "right", "textBaseline": "middle", @@ -85,6 +87,7 @@ Object { "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif", "fontSize": 12, "fontWeight": "normal", + "linkTextFill": "#2C60D4", "opacity": 1, "textAlign": "center", "textBaseline": "middle", @@ -560,6 +563,7 @@ Object { "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif", "fontSize": 12, "fontWeight": 700, + "linkTextFill": "#4b91ff", "opacity": 1, "textAlign": "center", "textBaseline": "middle", @@ -624,6 +628,7 @@ Object { "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif", "fontSize": 12, "fontWeight": "normal", + "linkTextFill": "#4b91ff", "opacity": 1, "textAlign": "right", "textBaseline": "middle", @@ -633,6 +638,7 @@ Object { "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif", "fontSize": 12, "fontWeight": "normal", + "linkTextFill": "#4b91ff", "opacity": 1, "textAlign": "center", "textBaseline": "middle", @@ -1108,6 +1114,7 @@ Object { "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif", "fontSize": 12, "fontWeight": 700, + "linkTextFill": "#326EF4", "opacity": 1, "textAlign": "center", "textBaseline": "middle", @@ -1172,6 +1179,7 @@ Object { "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif", "fontSize": 12, "fontWeight": "normal", + "linkTextFill": "#326EF4", "opacity": 1, "textAlign": "right", "textBaseline": "middle", @@ -1181,6 +1189,7 @@ Object { "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif", "fontSize": 12, "fontWeight": "normal", + "linkTextFill": "#326EF4", "opacity": 1, "textAlign": "center", "textBaseline": "middle", @@ -1656,6 +1665,7 @@ Object { "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif", "fontSize": 12, "fontWeight": 700, + "linkTextFill": "#565C64", "opacity": 1, "textAlign": "center", "textBaseline": "middle", @@ -1720,6 +1730,7 @@ Object { "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif", "fontSize": 12, "fontWeight": "normal", + "linkTextFill": "#565C64", "opacity": 1, "textAlign": "right", "textBaseline": "middle", @@ -1729,6 +1740,7 @@ Object { "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif", "fontSize": 12, "fontWeight": "normal", + "linkTextFill": "#565C64", "opacity": 1, "textAlign": "center", "textBaseline": "middle", @@ -2204,6 +2216,7 @@ Object { "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif", "fontSize": 12, "fontWeight": 700, + "linkTextFill": "#326EF4", "opacity": 1, "textAlign": "center", "textBaseline": "middle", @@ -2268,6 +2281,7 @@ Object { "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif", "fontSize": 12, "fontWeight": "normal", + "linkTextFill": "#326EF4", "opacity": 1, "textAlign": "right", "textBaseline": "middle", @@ -2277,6 +2291,7 @@ Object { "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif", "fontSize": 12, "fontWeight": "normal", + "linkTextFill": "#326EF4", "opacity": 1, "textAlign": "center", "textBaseline": "middle", @@ -2752,6 +2767,7 @@ Object { "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif", "fontSize": 12, "fontWeight": 700, + "linkTextFill": "#326EF4", "opacity": 1, "textAlign": "center", "textBaseline": "middle", @@ -2816,6 +2832,7 @@ Object { "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif", "fontSize": 12, "fontWeight": "normal", + "linkTextFill": "#326EF4", "opacity": 1, "textAlign": "right", "textBaseline": "middle", @@ -2825,6 +2842,7 @@ Object { "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif", "fontSize": 12, "fontWeight": "normal", + "linkTextFill": "#326EF4", "opacity": 1, "textAlign": "center", "textBaseline": "middle", diff --git a/packages/s2-core/__tests__/spreadsheet/row-link-spec.ts b/packages/s2-core/__tests__/spreadsheet/header-cell-link-click-spec.ts similarity index 61% rename from packages/s2-core/__tests__/spreadsheet/row-link-spec.ts rename to packages/s2-core/__tests__/spreadsheet/header-cell-link-click-spec.ts index 1c133e8cff..5523dbf2cf 100644 --- a/packages/s2-core/__tests__/spreadsheet/row-link-spec.ts +++ b/packages/s2-core/__tests__/spreadsheet/header-cell-link-click-spec.ts @@ -1,4 +1,10 @@ -import { S2Event, type S2DataConfig, type S2Options } from '@/common'; +import { + EXTRA_FIELD, + S2Event, + type Node, + type S2DataConfig, + type S2Options, +} from '@/common'; import { PivotSheet } from '@/sheet-type'; import { noop } from 'lodash'; import { getContainer } from 'tests/util/helpers'; @@ -15,7 +21,7 @@ const s2Options: S2Options = { }, }, interaction: { - linkFields: ['province', 'city'], + linkFields: ['province', 'city', 'type'], }, }; @@ -63,31 +69,37 @@ const s2DataCfg: S2DataConfig = { ], }; -describe('Row Text Link Tests', () => { +describe('Header Cell Link Click Tests', () => { let container: HTMLDivElement; let s2: PivotSheet; const linkFieldJump = jest.fn(); + const emitCellClickEvent = (event: S2Event, node: Node) => { + s2.emit(event, { + stopPropagation: noop, + target: { + appendInfo: { + isLinkFieldText: true, + cellData: node, + }, + }, + } as any); + expect(node.belongsCell.getLinkFieldShape()).toBeDefined(); + }; + beforeEach(async () => { container = getContainer(); s2 = new PivotSheet(container, s2DataCfg, s2Options); await s2.render(); + s2.on(S2Event.GLOBAL_LINK_FIELD_JUMP, linkFieldJump); }); test('should get correctly row leaf node when click row 浙江', () => { const rowNode = s2.facet.getRowNodes()[0]; // 浙江 - s2.emit(S2Event.ROW_CELL_CLICK, { - stopPropagation: noop, - target: { - appendInfo: { - isLinkFieldText: true, - cellData: rowNode, - }, - }, - } as any); + emitCellClickEvent(S2Event.ROW_CELL_CLICK, rowNode); expect(linkFieldJump).toHaveBeenCalledWith({ field: 'province', @@ -98,6 +110,7 @@ describe('Row Text Link Tests', () => { price: 2, cost: 2, rowIndex: 0, + colIndex: -1, }, }); }); @@ -105,15 +118,7 @@ describe('Row Text Link Tests', () => { test('should get correctly row leaf node when click row 义乌1', () => { const rowNode = s2.facet.getRowNodes()[2]; // 义乌1 - s2.emit(S2Event.ROW_CELL_CLICK, { - stopPropagation: noop, - target: { - appendInfo: { - isLinkFieldText: true, - cellData: rowNode, - }, - }, - } as any); + emitCellClickEvent(S2Event.ROW_CELL_CLICK, rowNode); expect(linkFieldJump).toHaveBeenLastCalledWith({ field: 'city', @@ -125,6 +130,7 @@ describe('Row Text Link Tests', () => { price: 1, cost: 2, rowIndex: 1, + colIndex: -1, }, }); }); @@ -132,15 +138,7 @@ describe('Row Text Link Tests', () => { test('should get correctly row leaf node when click row 四川', () => { const rowNode = s2.facet.getRowNodes()[4]; // 四川 - s2.emit(S2Event.ROW_CELL_CLICK, { - stopPropagation: noop, - target: { - appendInfo: { - isLinkFieldText: true, - cellData: rowNode, - }, - }, - } as any); + emitCellClickEvent(S2Event.ROW_CELL_CLICK, rowNode); expect(linkFieldJump).toHaveBeenCalledWith({ field: 'province', @@ -151,6 +149,57 @@ describe('Row Text Link Tests', () => { price: 1, cost: 2, rowIndex: 3, + colIndex: -1, + }, + }); + }); + + test('should get correctly col leaf node when click col 笔', () => { + const colNode = s2.facet.getColNodes()[0]; // 笔 + + emitCellClickEvent(S2Event.COL_CELL_CLICK, colNode); + + expect(linkFieldJump).toHaveBeenCalledWith({ + field: 'type', + cellData: colNode, + record: { + province: '浙江', + type: '笔', + price: 2, + cost: 2, + rowIndex: 0, + colIndex: -1, + }, + }); + }); + + test('should get correctly extra field node when click col 价格', async () => { + s2.setOptions({ + interaction: { + linkFields: [EXTRA_FIELD], + }, + }); + s2.setDataCfg({ + fields: { + values: ['price'], + }, + }); + + await s2.render(); + const colNode = s2.facet.getColLeafNodes()[0]; + + emitCellClickEvent(S2Event.COL_CELL_CLICK, colNode); + + expect(linkFieldJump).toHaveBeenCalledWith({ + field: EXTRA_FIELD, + cellData: colNode, + record: { + province: '浙江', + type: '笔', + price: 2, + cost: 2, + rowIndex: 0, + colIndex: 0, }, }); }); diff --git a/packages/s2-core/__tests__/unit/interaction/base-interaction/click/row-text-click-spec.ts b/packages/s2-core/__tests__/unit/interaction/base-interaction/click/header-cell-link-click-spec.ts similarity index 72% rename from packages/s2-core/__tests__/unit/interaction/base-interaction/click/row-text-click-spec.ts rename to packages/s2-core/__tests__/unit/interaction/base-interaction/click/header-cell-link-click-spec.ts index 347ee77614..a7565cf3ea 100644 --- a/packages/s2-core/__tests__/unit/interaction/base-interaction/click/row-text-click-spec.ts +++ b/packages/s2-core/__tests__/unit/interaction/base-interaction/click/header-cell-link-click-spec.ts @@ -1,5 +1,5 @@ import type { RawData, S2DataConfig, S2Options } from '@/common/interface'; -import { RowTextClick } from '@/interaction/base-interaction/click'; +import { HeaderCellLinkClick } from '@/interaction/base-interaction/click'; import type { SpreadSheet } from '@/sheet-type'; import { createFakeSpreadSheet } from 'tests/util/helpers'; @@ -7,8 +7,8 @@ jest.mock('@/interaction/event-controller'); jest.mock('@/interaction/base-interaction/click/row-column-click'); jest.mock('@/interaction/range-selection'); -describe('Interaction Row Text Click Tests', () => { - let rowTextClick: RowTextClick; +describe('Interaction Header Link Click Tests', () => { + let headerCellLinkClick: HeaderCellLinkClick; let s2: SpreadSheet; const data: RawData[] = [ @@ -26,7 +26,7 @@ describe('Interaction Row Text Click Tests', () => { beforeEach(() => { s2 = createFakeSpreadSheet(); - rowTextClick = new RowTextClick(s2 as unknown as SpreadSheet); + headerCellLinkClick = new HeaderCellLinkClick(s2 as unknown as SpreadSheet); s2.options = { hierarchyType: 'grid', } as S2Options; @@ -37,6 +37,6 @@ describe('Interaction Row Text Click Tests', () => { }); test('should bind events', () => { - expect(rowTextClick.bindEvents).toBeDefined(); + expect(headerCellLinkClick.bindEvents).toBeDefined(); }); }); diff --git a/packages/s2-core/__tests__/unit/interaction/root-spec.ts b/packages/s2-core/__tests__/unit/interaction/root-spec.ts index 236c5c5906..47c42b6d9e 100644 --- a/packages/s2-core/__tests__/unit/interaction/root-spec.ts +++ b/packages/s2-core/__tests__/unit/interaction/root-spec.ts @@ -9,6 +9,7 @@ import { DataCellClick, DataCellMultiSelection, GuiIcon, + HeaderCellLinkClick, HoverEvent, InteractionName, InteractionStateName, @@ -20,7 +21,6 @@ import { RowCellBrushSelection, RowColumnClick, RowColumnResize, - RowTextClick, SelectedCellMove, SpreadSheet, type S2Options, @@ -588,7 +588,7 @@ describe('RootInteraction Tests', () => { ${InteractionName.CORNER_CELL_CLICK} | ${CornerCellClick} ${InteractionName.DATA_CELL_CLICK} | ${DataCellClick} ${InteractionName.ROW_COLUMN_CLICK} | ${RowColumnClick} - ${InteractionName.ROW_TEXT_CLICK} | ${RowTextClick} + ${InteractionName.HEADER_CELL_LINK_CLICK} | ${HeaderCellLinkClick} ${InteractionName.MERGED_CELLS_CLICK} | ${MergedCellClick} ${InteractionName.HOVER} | ${HoverEvent} ${InteractionName.DATA_CELL_BRUSH_SELECTION} | ${DataCellBrushSelection} diff --git a/packages/s2-core/src/cell/base-cell.ts b/packages/s2-core/src/cell/base-cell.ts index aa5cfc1ac7..86277e6a56 100644 --- a/packages/s2-core/src/cell/base-cell.ts +++ b/packages/s2-core/src/cell/base-cell.ts @@ -74,7 +74,7 @@ import { renderText, updateShapeAttr, } from '../utils/g-renders'; -import { checkIsLinkField } from '../utils/interaction/link-field'; +import { isLinkFieldNode } from '../utils/interaction/link-field'; import { isMobile } from '../utils/is-mobile'; import { getDisplayText, @@ -490,6 +490,7 @@ export abstract class BaseCell extends Group { } this.updateTextPosition(); + this.drawLinkField(this.meta); } protected drawLinkFieldShape( @@ -508,7 +509,7 @@ export abstract class BaseCell extends Group { const position = this.getTextPosition(); const actualTextWidth = this.getActualTextWidth(); - // 默认居左,其他align方式需要调整 + // 默认居左,其他 align 方式需要调整 let startX = position.x; if (textStyle.textAlign === 'center') { @@ -533,7 +534,7 @@ export abstract class BaseCell extends Group { this.textShape.style.fill = linkFillColor; this.textShape.style.cursor = 'pointer'; this.textShape.appendInfo = { - // 标记为行头(明细表行头其实就是 Data Cell)文本,方便做链接跳转直接识别 + // 标记为字段标记文本,方便做链接跳转直接识别 isLinkFieldText: true, cellData: this.meta, }; @@ -544,15 +545,18 @@ export abstract class BaseCell extends Group { return this.getTextStyle().linkTextFill!; } - protected drawLinkField(meta: Node | ViewMeta) { + protected drawLinkField(meta: T) { const { linkFields = [] } = this.spreadsheet.options.interaction!; const linkTextFill = this.getLinkFieldStyle(); - const isLinkField = checkIsLinkField(linkFields, meta); + const isLinkField = isLinkFieldNode( + linkFields, + meta as unknown as Node | ViewMeta, + ); this.drawLinkFieldShape(isLinkField, linkTextFill); } - // 根据当前state来更新cell的样式 + // 根据当前 state 来更新 cell 的样式 public updateByState(stateName: InteractionStateName, cell: S2CellType) { this.spreadsheet.interaction.setInteractedCells(cell); const stateStyles = get( diff --git a/packages/s2-core/src/cell/row-cell.ts b/packages/s2-core/src/cell/row-cell.ts index c545fc27af..026824986b 100644 --- a/packages/s2-core/src/cell/row-cell.ts +++ b/packages/s2-core/src/cell/row-cell.ts @@ -212,13 +212,6 @@ export class RowCell extends HeaderCell { return (!isLeaf && level === 0) || isTotals; } - public drawTextShape() { - super.drawTextShape(); - if (!this.isShallowRender()) { - this.drawLinkField(this.meta); - } - } - protected drawResizeAreaInLeaf() { if ( !this.meta.isLeaf || diff --git a/packages/s2-core/src/common/constant/interaction.ts b/packages/s2-core/src/common/constant/interaction.ts index 08a9be3d5e..77421de5bd 100644 --- a/packages/s2-core/src/common/constant/interaction.ts +++ b/packages/s2-core/src/common/constant/interaction.ts @@ -3,7 +3,7 @@ export enum InteractionName { DATA_CELL_CLICK = 'dataCellClick', MERGED_CELLS_CLICK = 'mergedCellsClick', ROW_COLUMN_CLICK = 'rowColumnClick', - ROW_TEXT_CLICK = 'rowTextClick', + HEADER_CELL_LINK_CLICK = 'headerCellLinkClick', HOVER = 'hover', DATA_CELL_BRUSH_SELECTION = 'dataCellBrushSelection', ROW_CELL_BRUSH_SELECTION = 'rowCellBrushSelection', diff --git a/packages/s2-core/src/interaction/base-interaction/click/header-cell-link-click.ts b/packages/s2-core/src/interaction/base-interaction/click/header-cell-link-click.ts new file mode 100644 index 0000000000..2971b75e0a --- /dev/null +++ b/packages/s2-core/src/interaction/base-interaction/click/header-cell-link-click.ts @@ -0,0 +1,64 @@ +import type { FederatedPointerEvent as CanvasEvent } from '@antv/g'; +import { InterceptType, S2Event } from '../../../common/constant'; +import type { Data, RawData } from '../../../common/interface'; +import { CellData } from '../../../data-set/cell-data'; +import type { Node } from '../../../facet/layout/node'; +import { BaseEvent, type BaseEventImplement } from '../../base-event'; + +export class HeaderCellLinkClick + extends BaseEvent + implements BaseEventImplement +{ + public bindEvents() { + this.bindRowCellClick(); + this.bindColCellClick(); + } + + private onHeaderCellClick(event: CanvasEvent) { + if (this.spreadsheet.interaction.hasIntercepts([InterceptType.CLICK])) { + return; + } + + if (!this.isLinkFieldText(event.target)) { + return; + } + + const { cellData } = this.getCellAppendInfo(event.target); + const field = cellData!.field; + const rowData = this.getCellData(cellData!); + + this.spreadsheet.emit(S2Event.GLOBAL_LINK_FIELD_JUMP, { + field, + cellData: cellData!, + record: rowData as Data, + }); + } + + private bindRowCellClick() { + this.spreadsheet.on(S2Event.ROW_CELL_CLICK, (event) => { + this.onHeaderCellClick(event); + }); + } + + private bindColCellClick() { + this.spreadsheet.on(S2Event.COL_CELL_CLICK, (event) => { + this.onHeaderCellClick(event); + }); + } + + private getCellData = (node: Node): RawData => { + const leafNode = node.getHeadLeafChild(); + + const data = this.spreadsheet.dataSet.getCellMultiData({ + query: leafNode?.query!, + })[0]; + + const originalData = CellData.getFieldValue(data) as RawData; + + return { + ...originalData, + rowIndex: node.rowIndex ?? leafNode?.rowIndex, + colIndex: node.colIndex ?? leafNode?.colIndex, + }; + }; +} diff --git a/packages/s2-core/src/interaction/base-interaction/click/index.ts b/packages/s2-core/src/interaction/base-interaction/click/index.ts index 0f09dc91a5..d0592ab9bd 100644 --- a/packages/s2-core/src/interaction/base-interaction/click/index.ts +++ b/packages/s2-core/src/interaction/base-interaction/click/index.ts @@ -1,5 +1,5 @@ export { CornerCellClick } from './corner-cell-click'; export { DataCellClick } from './data-cell-click'; +export { HeaderCellLinkClick } from './header-cell-link-click'; export { MergedCellClick } from './merged-cell-click'; export { RowColumnClick } from './row-column-click'; -export { RowTextClick } from './row-text-click'; diff --git a/packages/s2-core/src/interaction/base-interaction/click/row-text-click.ts b/packages/s2-core/src/interaction/base-interaction/click/row-text-click.ts deleted file mode 100644 index c2a5dace14..0000000000 --- a/packages/s2-core/src/interaction/base-interaction/click/row-text-click.ts +++ /dev/null @@ -1,52 +0,0 @@ -import type { FederatedPointerEvent as CanvasEvent } from '@antv/g'; -import { InterceptType, S2Event } from '../../../common/constant'; -import type { Data, RawData } from '../../../common/interface'; -import { CellData } from '../../../data-set/cell-data'; -import type { Node } from '../../../facet/layout/node'; -import { BaseEvent, type BaseEventImplement } from '../../base-event'; - -/** - * Row header click navigation interaction - */ -export class RowTextClick extends BaseEvent implements BaseEventImplement { - public bindEvents() { - this.bindRowCellClick(); - } - - private bindRowCellClick() { - this.spreadsheet.on(S2Event.ROW_CELL_CLICK, (event: CanvasEvent) => { - if (this.spreadsheet.interaction.hasIntercepts([InterceptType.CLICK])) { - return; - } - - if (!this.isLinkFieldText(event.target)) { - return; - } - - const { cellData } = this.getCellAppendInfo(event.target); - const field = cellData!.field; - const rowData = this.getRowData(cellData!); - - this.spreadsheet.emit(S2Event.GLOBAL_LINK_FIELD_JUMP, { - field, - cellData: cellData!, - record: rowData as Data, - }); - }); - } - - private getRowData = (cellData: Node): RawData => { - const leafNode = cellData.getHeadLeafChild(); - - const data = this.spreadsheet.dataSet.getCellMultiData({ - query: leafNode?.query!, - })[0]; - - const originalData = CellData.getFieldValue(data) as RawData; - - return { - ...originalData, - rowIndex: cellData.rowIndex ?? leafNode?.rowIndex, - }; - }; -} diff --git a/packages/s2-core/src/interaction/root.ts b/packages/s2-core/src/interaction/root.ts index 2de205b139..b15e9f1f5b 100644 --- a/packages/s2-core/src/interaction/root.ts +++ b/packages/s2-core/src/interaction/root.ts @@ -47,9 +47,9 @@ import { isMobile } from '../utils/is-mobile'; import type { BaseEvent } from './base-event'; import { DataCellClick, + HeaderCellLinkClick, MergedCellClick, RowColumnClick, - RowTextClick, } from './base-interaction/click'; import { CornerCellClick } from './base-interaction/click/corner-cell-click'; import { HoverEvent } from './base-interaction/hover'; @@ -415,8 +415,8 @@ export class RootInteraction { interaction: RowColumnClick, }, { - key: InteractionName.ROW_TEXT_CLICK, - interaction: RowTextClick, + key: InteractionName.HEADER_CELL_LINK_CLICK, + interaction: HeaderCellLinkClick, }, { key: InteractionName.MERGED_CELLS_CLICK, diff --git a/packages/s2-core/src/theme/index.ts b/packages/s2-core/src/theme/index.ts index 274e93ac5d..efa7dc3501 100644 --- a/packages/s2-core/src/theme/index.ts +++ b/packages/s2-core/src/theme/index.ts @@ -332,6 +332,7 @@ export const getTheme = ( fontSize: 12, fontWeight: 'normal', fill: basicColors[0], + linkTextFill: basicColors[6], opacity: 1, // 默认列头的数值字段和 dataCell 数值对齐 textAlign: 'right', @@ -342,6 +343,7 @@ export const getTheme = ( fontSize: 12, fontWeight: boldTextDefaultFontWeight, fill: basicColors[0], + linkTextFill: basicColors[6], opacity: 1, textAlign: 'center', textBaseline: 'middle', @@ -351,6 +353,7 @@ export const getTheme = ( fontSize: 12, fontWeight: 'normal', fill: basicColors[0], + linkTextFill: basicColors[6], opacity: 1, textAlign: 'center', textBaseline: 'middle', diff --git a/packages/s2-core/src/utils/interaction/link-field.ts b/packages/s2-core/src/utils/interaction/link-field.ts index 52281fb6a6..215533dbc1 100644 --- a/packages/s2-core/src/utils/interaction/link-field.ts +++ b/packages/s2-core/src/utils/interaction/link-field.ts @@ -1,15 +1,17 @@ +import { isFunction } from 'lodash'; import type { ViewMeta } from '../../common/interface/basic'; import type { Node } from '../../facet/layout/node'; -export const checkIsLinkField = ( +export const isLinkFieldNode = ( linkFields: string[] | ((meta: Node | ViewMeta) => boolean), meta: Node | ViewMeta, -): boolean => - typeof linkFields === 'function' - ? linkFields(meta) - : linkFields.some( - (field) => - field === meta.field || - field === meta.id || - field === meta.valueField, - ); +): boolean => { + if (isFunction(linkFields)) { + return linkFields(meta); + } + + return linkFields.some( + (field) => + field === meta.field || field === meta.id || field === meta.valueField, + ); +}; diff --git a/packages/s2-react/playground/config.tsx b/packages/s2-react/playground/config.tsx index 24ab755a64..2361f9b5c4 100644 --- a/packages/s2-react/playground/config.tsx +++ b/packages/s2-react/playground/config.tsx @@ -2,6 +2,7 @@ /* eslint-disable no-console */ import { EMPTY_PLACEHOLDER, + EXTRA_FIELD, customMerge, type CustomHeaderField, type CustomTreeNode, @@ -12,12 +13,7 @@ import { import { getBaseSheetComponentOptions } from '@antv/s2-shared'; import { PivotSheetMultiLineTextDataCfg } from '@antv/s2/__tests__/data/data-multi-line-text'; import type { SliderSingleProps } from 'antd'; -import { - data, - fields, - meta, - totalData, -} from '../__tests__/data/mock-dataset.json'; +import { data, meta, totalData } from '../__tests__/data/mock-dataset.json'; import type { SheetComponentOptions } from '../src/components'; export const tableSheetSingleColumns: CustomHeaderField[] = [ @@ -77,10 +73,47 @@ export const tableSheetDataCfg: S2DataConfig = { }; export const pivotSheetDataCfg: S2DataConfig = { - data, - totalData, - meta, - fields, + fields: { + rows: ['province', 'city'], + columns: ['type'], + values: ['price'], + valueInCols: true, + }, + data: [ + { + province: '浙江', + city: '义乌1', + type: '笔', + price: 1, + cost: 2, + }, + { + province: '浙江', + city: '义乌2', + type: '笔', + price: 1, + cost: 6, + }, + { + province: '浙江', + type: '笔', + price: 2, + cost: 2, + }, + { + province: '四川', + city: '成都', + type: '笔', + price: 1, + cost: 2, + }, + { + province: '四川', + type: '笔', + price: 1, + cost: 2, + }, + ], }; export const pivotSheetMultiLineTextDataCfg = PivotSheetMultiLineTextDataCfg; @@ -356,6 +389,7 @@ export const s2Options: SheetComponentOptions = { }, cornerText: '测试测试测试测试测试测试测试测试测试测试', interaction: { + linkFields: ['province', 'city', 'type', EXTRA_FIELD], copy: { enable: true, withFormat: true, diff --git a/s2-site/docs/api/general/S2Event.zh.md b/s2-site/docs/api/general/S2Event.zh.md index 419d46a9dd..bbfac830c1 100644 --- a/s2-site/docs/api/general/S2Event.zh.md +++ b/s2-site/docs/api/general/S2Event.zh.md @@ -144,7 +144,7 @@ s2.on(S2Event.ROW_CELL_CLICK, (event) => { | 选中 | `S2Event.GLOBAL_SELECTED` | 选中单元格时,如:刷选,多选,单选 | | 悬停 | `S2Event.GLOBAL_HOVER` | 鼠标悬停在单元格 | | 重置 | `S2Event.GLOBAL_RESET` | 点击空白处,按下 Esc 键 重置交互样式时 | -| 链接跳转 | `S2Event.GLOBAL_LINK_FIELD_JUMP` | 点击行列头被编辑为链接字段的文本时 | +| 链接跳转 | `S2Event.GLOBAL_LINK_FIELD_JUMP` | 点击(行头/列头/数值)为链接字段的文本时 | | icon 点击 | `S2Event.GLOBAL_ACTION_ICON_CLICK` | 单元格右侧的操作 icon 点击时,比如:排序图标 | | icon 悬停 | `S2Event.GLOBAL_ACTION_ICON_HOVER` | 单元格右侧的操作 icon 悬停时,比如:排序图标 | | 滚动 | `S2Event.GLOBAL_SCROLL` | 表格滚动 (含数值和行头单元格) | diff --git a/s2-site/docs/manual/advanced/interaction/basic.zh.md b/s2-site/docs/manual/advanced/interaction/basic.zh.md index 196e5bf551..87fda41c5d 100644 --- a/s2-site/docs/manual/advanced/interaction/basic.zh.md +++ b/s2-site/docs/manual/advanced/interaction/basic.zh.md @@ -33,7 +33,7 @@ tag: Updated | 悬停 | `S2Event.GLOBAL_HOVER` | 鼠标悬停时,对应单元格高亮展示,如果是数值单元格,则默认 [十字高亮](/docs/manual/advanced/interaction/basic#行列联动高亮),可设置 `hoverHighlight: false` 关闭 | | 复制 | `S2Event.GLOBAL_COPIED` | 复制选中的单元格数据 | | 隐藏列头 | `S2Event.COL_CELL_EXPANDED` `S2Event.COL_CELL_HIDDEN` | 隐藏/展开 列头 | -| 链接跳转 | `S2Event.GLOBAL_LINK_FIELD_JUMP` | 行头/列头 链接跳转 | +| 链接跳转 | `S2Event.GLOBAL_LINK_FIELD_JUMP` | 行头/列头/数值 链接跳转 | | 重置 | `S2Event.GLOBAL_RESET` | 再次点击,点击空白处,或按下 `Esc` 取消选中的单元格 | | 移动高亮单元格 | `S2Event.GLOBAL_SELECTED` | 点击数值单元格后,使用键盘方向键即可移动当前高亮单元格 | diff --git a/s2-site/docs/manual/advanced/interaction/link-jump.zh.md b/s2-site/docs/manual/advanced/interaction/link-jump.zh.md index bcdd7c0d0e..e7ae3501ab 100644 --- a/s2-site/docs/manual/advanced/interaction/link-jump.zh.md +++ b/s2-site/docs/manual/advanced/interaction/link-jump.zh.md @@ -1,6 +1,7 @@ --- title: 链接跳转 order: 3 +tag: Updated --- 将单元格文本标记为含有下划线的链接样式,实现链接跳转 🔗, 对于透视表和明细表,有细微的区别 @@ -29,21 +30,21 @@ const s2Options = { 使用 `S2Event.GLOBAL_LINK_FIELD_JUMP` 监听链接点击 -```ts +```ts | pure import { S2Event } from '@antv/s2' s2.on(S2Event.GLOBAL_LINK_FIELD_JUMP, (data) => { - const { key, record } = data; + const { field, cellData, record } = data; ... }); ``` ## 透视表 -支持将行头 `rows`, (数值 `values` @antv/s2@^1.44.0 新增) 标记为链接样式,`columns` 暂不支持 +支持将行头 `rows`, 列头 `columns`, 数值 `values` 标记为链接样式。 -```ts -import { S2Event } from '@antv/s2' +```ts | pure +import { S2Event, EXTRA_FIELD } from '@antv/s2' const s2DataConfig = { fields: { @@ -57,29 +58,49 @@ const s2Options = { width: 600, height: 600, interaction: { - linkFields: ['province', 'city', 'price'], + linkFields: ['province', 'city', 'type', 'price'], } }; const s2 = new PivotSheet(container, s2DataConfig, s2Options); s2.on(S2Event.GLOBAL_LINK_FIELD_JUMP, (data) => { - const { key, record } = data; - const value = record[key] + const { field, cellData, record } = data; + const value = record?.[field]; + // 拼装自己的跳转地址 - location.href = `https://path/to/${key}=${value}}`; + location.href = `https://path/to/${field}=${value}}`; }); await s2.render(); ``` - +在单指标的情况下,指标挂行头或列头,对额外多出一个虚拟行列头字段,对应 `EXTRA_FIELD`, 在这个例子中即 `数量` + +```ts +import { EXTRA_FIELD } from '@antv/s2' + +const s2Options = { + width: 600, + height: 600, + interaction: { + linkFields: [EXTRA_FIELD], + } +}; +``` + + ## 明细表 -支持将行头 `columns` 标记为链接样式 +支持将列头 `columns` 和对应的数值标记为链接样式。 -```ts +:::warning{title="注意"} +由于明细表单列头的特殊性,为和透视表保持一致,同时兼容多列头的场景,明细表的标记会对列头和数值**同时生效**. +如希望标记只对数值生效,可以参考下文 [自定义标记](#自定义标记) +::: + +```ts | pure import { S2Event } from '@antv/s2'; const s2DataConfig = { @@ -99,13 +120,38 @@ const s2Options = { const s2 = new TableSheet(container, s2DataConfig, s2Options); s2.on(S2Event.GLOBAL_LINK_FIELD_JUMP, (data) => { - const { key, record } = data; - const value = record[key] + const { field, cellData, record } = data; + const value = record?.[field]; + // 拼装自己的跳转地址 - location.href = `https://path/to/${key}=${value}}`; + location.href = `https://path/to/${field}=${value}`; }); await s2.render(); ``` - + + +## 自定义标记 + +除了配置行头/列头/数值字段外,支持根据单元格信息自定义标记,满足更多使用场景。 + +```ts +const s2Options = { + width: 600, + height: 600, + interaction: { + linkFields: (meta) => { + // 不标记列头 + if (meta?.belongsCell?.cellType === 'colCell') { + return false; + } + + // 根据指标值动态标记 + return meta?.fieldValue === '浙江' || meta?.fieldValue >= 10; + } + } +}; +``` + + diff --git a/s2-site/docs/manual/migration-v2.zh.md b/s2-site/docs/manual/migration-v2.zh.md index 6edf19957f..055477dbc9 100644 --- a/s2-site/docs/manual/migration-v2.zh.md +++ b/s2-site/docs/manual/migration-v2.zh.md @@ -732,6 +732,20 @@ const s2Options = { } ``` +#### 链接跳转逻辑变更 + +1. 现在链接跳转支持对 **列头** 标记,且明细表同时对 `列头` 和 `数值` 生效。 +2. 回调参数 `key` 调整为 `field`. + +```diff +s2.on(S2Event.GLOBAL_LINK_FIELD_JUMP, (data) => { +- const { key, cellData, record } = data; ++ const { field, cellData, record } = data; +}); +``` + +具体请查看 [链接跳转](/manual/advanced/interaction/link-jump) 相关文档。 + ### 组件层 @antv/s2-react #### 支持 React 18 和 Ant Design 5.0 diff --git a/s2-site/examples/interaction/advanced/demo/custom-link-jump.ts b/s2-site/examples/interaction/advanced/demo/custom-link-jump.ts new file mode 100644 index 0000000000..f24fc326b3 --- /dev/null +++ b/s2-site/examples/interaction/advanced/demo/custom-link-jump.ts @@ -0,0 +1,68 @@ +import { S2DataConfig, S2Event, S2Options, TableSheet } from '@antv/s2'; + +fetch('https://assets.antv.antgroup.com/s2/basic-table-mode.json') + .then((res) => res.json()) + .then(async (data) => { + const container = document.getElementById('container'); + const s2DataConfig: S2DataConfig = { + fields: { + columns: ['type', 'province', 'city', 'price', 'cost'], + }, + meta: [ + { + field: 'province', + name: '省份', + }, + { + field: 'city', + name: '城市', + }, + { + field: 'type', + name: '商品类别', + }, + { + field: 'price', + name: '价格', + }, + { + field: 'cost', + name: '成本', + }, + ], + data, + }; + + const s2Options: S2Options = { + width: 600, + height: 480, + interaction: { + linkFields: (meta) => { + // 不标记列头 + if (meta?.belongsCell?.cellType === 'colCell') { + return false; + } + + // 根据指标值动态标记 + return meta?.fieldValue === '浙江' || meta?.fieldValue >= 10; + }, + }, + }; + + const s2 = new TableSheet(container, s2DataConfig, s2Options); + + s2.on(S2Event.GLOBAL_LINK_FIELD_JUMP, (jumpData) => { + console.log('jumpData:', jumpData); + + const { field, record } = jumpData; + const value = record?.[field]; + const a = document.createElement('a'); + + a.target = '_blank'; + a.href = `https://s2.antv.antgroup.com/zh/docs/manual/introduction?${field}=${value}`; + a.click(); + a.remove(); + }); + + await s2.render(); + }); diff --git a/s2-site/examples/interaction/advanced/demo/custom-tree-link-jump.ts b/s2-site/examples/interaction/advanced/demo/custom-tree-link-jump.ts index 5b7da2294f..d2a84fb6ec 100644 --- a/s2-site/examples/interaction/advanced/demo/custom-tree-link-jump.ts +++ b/s2-site/examples/interaction/advanced/demo/custom-tree-link-jump.ts @@ -1,4 +1,4 @@ -import { S2Event, PivotSheet, S2DataConfig, S2Options } from '@antv/s2'; +import { PivotSheet, S2DataConfig, S2Event, S2Options } from '@antv/s2'; // 临时处理老数据格式 function process(children) { @@ -40,6 +40,7 @@ fetch( hierarchyType: 'tree', interaction: { linkFields: [ + 'type', 'custom-node-1', 'custom-node-2', 'custom-node-3', @@ -65,7 +66,7 @@ fetch( const a = document.createElement('a'); a.target = '_blank'; - a.href = `https://antv-s2.gitee.io/zh/docs/manual/introduction?${field}=${value}`; + a.href = `https://s2.antv.antgroup.com/zh/docs/manual/introduction?${field}=${value}`; a.click(); a.remove(); }); diff --git a/s2-site/examples/interaction/advanced/demo/meta.json b/s2-site/examples/interaction/advanced/demo/meta.json index 19351fd460..39dbecb203 100644 --- a/s2-site/examples/interaction/advanced/demo/meta.json +++ b/s2-site/examples/interaction/advanced/demo/meta.json @@ -28,6 +28,15 @@ }, "screenshot": "https://gw.alipayobjects.com/zos/antfincdn/aygNlbA0fu/link-table.gif" }, + { + "filename": "custom-link-jump.ts", + "title": { + "zh": "链接跳转 - 自定义", + "en": "Custom link jump" + }, + "screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Qt3wR4cIdn0AAAAAAAAAAAAADmJ7AQ/original", + "new": true + }, { "filename": "custom-tree-link-jump.ts", "title": { diff --git a/s2-site/examples/interaction/advanced/demo/pivot-link-jump.ts b/s2-site/examples/interaction/advanced/demo/pivot-link-jump.ts index 654fc29253..79fdd3065d 100644 --- a/s2-site/examples/interaction/advanced/demo/pivot-link-jump.ts +++ b/s2-site/examples/interaction/advanced/demo/pivot-link-jump.ts @@ -1,4 +1,4 @@ -import { S2Event, PivotSheet, S2Options } from '@antv/s2'; +import { EXTRA_FIELD, PivotSheet, S2Event, S2Options } from '@antv/s2'; fetch( 'https://gw.alipayobjects.com/os/bmw-prod/2a5dbbc8-d0a7-4d02-b7c9-34f6ca63cff6.json', @@ -11,7 +11,8 @@ fetch( width: 600, height: 480, interaction: { - linkFields: ['city', 'number'], + // EXTRA_FIELD 为数值挂行/列头时对应的虚拟字段 (数量) + linkFields: ['city', 'type', 'number', EXTRA_FIELD], }, }; @@ -25,7 +26,7 @@ fetch( const a = document.createElement('a'); a.target = '_blank'; - a.href = `https://antv-s2.gitee.io/zh/docs/manual/introduction?${field}=${value}`; + a.href = `https://s2.antv.antgroup.com/zh/docs/manual/introduction?${field}=${value}`; a.click(); a.remove(); }); From e4479cf4ac9fd73948cc868f40912fdcd1bbd1dd Mon Sep 17 00:00:00 2001 From: lijinke666 Date: Mon, 1 Jul 2024 11:10:07 +0800 Subject: [PATCH 2/4] =?UTF-8?q?test:=20=E6=9B=B4=E6=96=B0=E5=BF=AB?= =?UTF-8?q?=E7=85=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../__snapshots__/utils-spec.ts.snap | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/packages/s2-react-components/__tests__/unit/components/config/theme-panel/__snapshots__/utils-spec.ts.snap b/packages/s2-react-components/__tests__/unit/components/config/theme-panel/__snapshots__/utils-spec.ts.snap index a7e8ee25ad..80d1939618 100644 --- a/packages/s2-react-components/__tests__/unit/components/config/theme-panel/__snapshots__/utils-spec.ts.snap +++ b/packages/s2-react-components/__tests__/unit/components/config/theme-panel/__snapshots__/utils-spec.ts.snap @@ -12,6 +12,7 @@ Object { "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif", "fontSize": 12, "fontWeight": 700, + "linkTextFill": "#2B5ECF", "opacity": 1, "textAlign": "center", "textBaseline": "middle", @@ -76,6 +77,7 @@ Object { "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif", "fontSize": 12, "fontWeight": "normal", + "linkTextFill": "#2B5ECF", "opacity": 1, "textAlign": "right", "textBaseline": "middle", @@ -85,6 +87,7 @@ Object { "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif", "fontSize": 12, "fontWeight": "normal", + "linkTextFill": "#2B5ECF", "opacity": 1, "textAlign": "center", "textBaseline": "middle", @@ -560,6 +563,7 @@ Object { "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif", "fontSize": 12, "fontWeight": 700, + "linkTextFill": "#2B5ECF", "opacity": 1, "textAlign": "center", "textBaseline": "middle", @@ -624,6 +628,7 @@ Object { "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif", "fontSize": 12, "fontWeight": "normal", + "linkTextFill": "#2B5ECF", "opacity": 1, "textAlign": "right", "textBaseline": "middle", @@ -633,6 +638,7 @@ Object { "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif", "fontSize": 12, "fontWeight": "normal", + "linkTextFill": "#2B5ECF", "opacity": 1, "textAlign": "center", "textBaseline": "middle", @@ -1108,6 +1114,7 @@ Object { "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif", "fontSize": 12, "fontWeight": 700, + "linkTextFill": "#2B8257", "opacity": 1, "textAlign": "center", "textBaseline": "middle", @@ -1172,6 +1179,7 @@ Object { "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif", "fontSize": 12, "fontWeight": "normal", + "linkTextFill": "#2B8257", "opacity": 1, "textAlign": "right", "textBaseline": "middle", @@ -1181,6 +1189,7 @@ Object { "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif", "fontSize": 12, "fontWeight": "normal", + "linkTextFill": "#2B8257", "opacity": 1, "textAlign": "center", "textBaseline": "middle", @@ -1656,6 +1665,7 @@ Object { "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif", "fontSize": 12, "fontWeight": 700, + "linkTextFill": "#326EF4", "opacity": 1, "textAlign": "center", "textBaseline": "middle", @@ -1720,6 +1730,7 @@ Object { "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif", "fontSize": 12, "fontWeight": "normal", + "linkTextFill": "#326EF4", "opacity": 1, "textAlign": "right", "textBaseline": "middle", @@ -1729,6 +1740,7 @@ Object { "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif", "fontSize": 12, "fontWeight": "normal", + "linkTextFill": "#326EF4", "opacity": 1, "textAlign": "center", "textBaseline": "middle", @@ -2204,6 +2216,7 @@ Object { "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif", "fontSize": 12, "fontWeight": 700, + "linkTextFill": "#2B5ECF", "opacity": 1, "textAlign": "center", "textBaseline": "middle", @@ -2268,6 +2281,7 @@ Object { "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif", "fontSize": 12, "fontWeight": "normal", + "linkTextFill": "#2B5ECF", "opacity": 1, "textAlign": "right", "textBaseline": "middle", @@ -2277,6 +2291,7 @@ Object { "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif", "fontSize": 12, "fontWeight": "normal", + "linkTextFill": "#2B5ECF", "opacity": 1, "textAlign": "center", "textBaseline": "middle", @@ -2752,6 +2767,7 @@ Object { "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif", "fontSize": 12, "fontWeight": 700, + "linkTextFill": "#B6C0D7", "opacity": 1, "textAlign": "center", "textBaseline": "middle", @@ -2816,6 +2832,7 @@ Object { "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif", "fontSize": 12, "fontWeight": "normal", + "linkTextFill": "#B6C0D7", "opacity": 1, "textAlign": "right", "textBaseline": "middle", @@ -2825,6 +2842,7 @@ Object { "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif", "fontSize": 12, "fontWeight": "normal", + "linkTextFill": "#B6C0D7", "opacity": 1, "textAlign": "center", "textBaseline": "middle", @@ -3300,6 +3318,7 @@ Object { "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif", "fontSize": 12, "fontWeight": 700, + "linkTextFill": "#2B5ECF", "opacity": 1, "textAlign": "center", "textBaseline": "middle", @@ -3364,6 +3383,7 @@ Object { "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif", "fontSize": 12, "fontWeight": "normal", + "linkTextFill": "#2B5ECF", "opacity": 1, "textAlign": "right", "textBaseline": "middle", @@ -3373,6 +3393,7 @@ Object { "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif", "fontSize": 12, "fontWeight": "normal", + "linkTextFill": "#2B5ECF", "opacity": 1, "textAlign": "center", "textBaseline": "middle", From 806df968158fdae8a0394dd6d19300e00009507c Mon Sep 17 00:00:00 2001 From: lijinke666 Date: Mon, 1 Jul 2024 16:21:32 +0800 Subject: [PATCH 3/4] =?UTF-8?q?feat:=20=E5=8F=82=E6=95=B0=20cellData=20?= =?UTF-8?q?=E7=BB=9F=E4=B8=80=E4=B8=BA=20meta?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../header-cell-link-click-spec.ts | 12 ++--- .../click/data-cell-click-spec.ts | 4 +- .../click/row-column-click-spec.ts | 2 +- .../unit/utils/interaction/formatter-spec.ts | 6 +-- packages/s2-core/src/cell/base-cell.ts | 2 +- .../s2-core/src/common/interface/basic.ts | 5 +- .../s2-core/src/common/interface/emitter.ts | 3 +- .../base-interaction/click/data-cell-click.ts | 8 +-- .../click/header-cell-link-click.ts | 8 +-- .../src/utils/interaction/formatter.ts | 4 +- packages/s2-react/playground/config.tsx | 54 ++++--------------- .../docs/api/components/sheet-component.zh.md | 4 +- .../advanced/interaction/link-jump.zh.md | 10 ++-- s2-site/docs/manual/migration-v2.zh.md | 8 +-- 14 files changed, 50 insertions(+), 80 deletions(-) diff --git a/packages/s2-core/__tests__/spreadsheet/header-cell-link-click-spec.ts b/packages/s2-core/__tests__/spreadsheet/header-cell-link-click-spec.ts index 5523dbf2cf..9814418a5b 100644 --- a/packages/s2-core/__tests__/spreadsheet/header-cell-link-click-spec.ts +++ b/packages/s2-core/__tests__/spreadsheet/header-cell-link-click-spec.ts @@ -81,7 +81,7 @@ describe('Header Cell Link Click Tests', () => { target: { appendInfo: { isLinkFieldText: true, - cellData: node, + meta: node, }, }, } as any); @@ -103,7 +103,7 @@ describe('Header Cell Link Click Tests', () => { expect(linkFieldJump).toHaveBeenCalledWith({ field: 'province', - cellData: rowNode, + meta: rowNode, record: { province: '浙江', type: '笔', @@ -122,7 +122,7 @@ describe('Header Cell Link Click Tests', () => { expect(linkFieldJump).toHaveBeenLastCalledWith({ field: 'city', - cellData: rowNode, + meta: rowNode, record: { province: '浙江', city: '义乌1', @@ -142,7 +142,7 @@ describe('Header Cell Link Click Tests', () => { expect(linkFieldJump).toHaveBeenCalledWith({ field: 'province', - cellData: rowNode, + meta: rowNode, record: { province: '四川', type: '笔', @@ -161,7 +161,7 @@ describe('Header Cell Link Click Tests', () => { expect(linkFieldJump).toHaveBeenCalledWith({ field: 'type', - cellData: colNode, + meta: colNode, record: { province: '浙江', type: '笔', @@ -192,7 +192,7 @@ describe('Header Cell Link Click Tests', () => { expect(linkFieldJump).toHaveBeenCalledWith({ field: EXTRA_FIELD, - cellData: colNode, + meta: colNode, record: { province: '浙江', type: '笔', diff --git a/packages/s2-core/__tests__/unit/interaction/base-interaction/click/data-cell-click-spec.ts b/packages/s2-core/__tests__/unit/interaction/base-interaction/click/data-cell-click-spec.ts index c1efbf1faf..c3628c148c 100644 --- a/packages/s2-core/__tests__/unit/interaction/base-interaction/click/data-cell-click-spec.ts +++ b/packages/s2-core/__tests__/unit/interaction/base-interaction/click/data-cell-click-spec.ts @@ -131,7 +131,7 @@ describe('Interaction Data Cell Click Tests', () => { }, }, { - cellData: mockCellData, + meta: mockCellData, isLinkFieldText: true, }, ), @@ -139,7 +139,7 @@ describe('Interaction Data Cell Click Tests', () => { expect(linkFieldJump).toHaveBeenCalledWith({ field: mockCellData.valueField, - cellData: mockCellData, + meta: mockCellData, record: mockCellData.data, }); expect(s2.showTooltipWithInfo).not.toHaveBeenCalled(); diff --git a/packages/s2-core/__tests__/unit/interaction/base-interaction/click/row-column-click-spec.ts b/packages/s2-core/__tests__/unit/interaction/base-interaction/click/row-column-click-spec.ts index 044abca971..979e948ca6 100644 --- a/packages/s2-core/__tests__/unit/interaction/base-interaction/click/row-column-click-spec.ts +++ b/packages/s2-core/__tests__/unit/interaction/base-interaction/click/row-column-click-spec.ts @@ -209,7 +209,7 @@ describe('Interaction Row & Column Cell Click Tests', () => { target: new CustomRect( { style: { x: 1, y: 1, width: 1, height: 1 } }, { - cellData: mockCellData, + meta: mockCellData, isLinkFieldText: true, }, ), diff --git a/packages/s2-core/__tests__/unit/utils/interaction/formatter-spec.ts b/packages/s2-core/__tests__/unit/utils/interaction/formatter-spec.ts index 7ba6c8e29f..ce8d53d672 100644 --- a/packages/s2-core/__tests__/unit/utils/interaction/formatter-spec.ts +++ b/packages/s2-core/__tests__/unit/utils/interaction/formatter-spec.ts @@ -36,13 +36,13 @@ describe('#getBaseCellData()', () => { }); test('should get correctly cell data by append info', () => { - const cellData = 'test'; + const meta = 'test'; const cell = createMockCellInfo('test-a').mockCell; // @ts-ignore - cell.appendInfo = { cellData }; + cell.appendInfo = { meta }; event.target = cell; - expect(getData(event).viewMeta).toEqual(cellData); + expect(getData(event).viewMeta).toEqual(meta); }); }); diff --git a/packages/s2-core/src/cell/base-cell.ts b/packages/s2-core/src/cell/base-cell.ts index 86277e6a56..7510f50f44 100644 --- a/packages/s2-core/src/cell/base-cell.ts +++ b/packages/s2-core/src/cell/base-cell.ts @@ -536,7 +536,7 @@ export abstract class BaseCell extends Group { this.textShape.appendInfo = { // 标记为字段标记文本,方便做链接跳转直接识别 isLinkFieldText: true, - cellData: this.meta, + meta: this.meta, }; } diff --git a/packages/s2-core/src/common/interface/basic.ts b/packages/s2-core/src/common/interface/basic.ts index a92d3a52ab..8f738085d0 100644 --- a/packages/s2-core/src/common/interface/basic.ts +++ b/packages/s2-core/src/common/interface/basic.ts @@ -470,9 +470,10 @@ export interface OffsetConfig { }; } -export interface CellAppendInfo extends Partial { +export interface CellAppendInfo + extends Partial> { isLinkFieldText?: boolean; - cellData?: T; + meta?: T; } export type S2MountContainer = string | Element; diff --git a/packages/s2-core/src/common/interface/emitter.ts b/packages/s2-core/src/common/interface/emitter.ts index 7b4319c519..d6de4733d6 100644 --- a/packages/s2-core/src/common/interface/emitter.ts +++ b/packages/s2-core/src/common/interface/emitter.ts @@ -19,6 +19,7 @@ import type { S2CellType, S2Style, SortParams, + ViewMeta, } from '../../common/interface'; import type { RawData } from '../../common/interface/s2DataConfig'; import type { Node } from '../../facet/layout/node'; @@ -70,7 +71,7 @@ export interface EmitterType { /** ================ Cell ================ */ [S2Event.GLOBAL_LINK_FIELD_JUMP]: (data: { - cellData: Node; + meta: Node | ViewMeta; field: string; record: Data; }) => void; diff --git a/packages/s2-core/src/interaction/base-interaction/click/data-cell-click.ts b/packages/s2-core/src/interaction/base-interaction/click/data-cell-click.ts index afc117b292..b408f1ee10 100644 --- a/packages/s2-core/src/interaction/base-interaction/click/data-cell-click.ts +++ b/packages/s2-core/src/interaction/base-interaction/click/data-cell-click.ts @@ -126,13 +126,13 @@ export class DataCellClick extends BaseEvent implements BaseEventImplement { } private emitLinkFieldClickEvent(event: CanvasEvent) { - const { cellData } = this.getCellAppendInfo(event.target); - const { valueField: field, data: record } = cellData!; + const { meta } = this.getCellAppendInfo(event.target); + const { valueField: field, data: record } = meta!; this.spreadsheet.emit(S2Event.GLOBAL_LINK_FIELD_JUMP, { - cellData: cellData!, + meta: meta!, field, - record: Object.assign({ rowIndex: cellData?.rowIndex }, record), + record: Object.assign({ rowIndex: meta?.rowIndex }, record), }); } } diff --git a/packages/s2-core/src/interaction/base-interaction/click/header-cell-link-click.ts b/packages/s2-core/src/interaction/base-interaction/click/header-cell-link-click.ts index 2971b75e0a..4234e70a91 100644 --- a/packages/s2-core/src/interaction/base-interaction/click/header-cell-link-click.ts +++ b/packages/s2-core/src/interaction/base-interaction/click/header-cell-link-click.ts @@ -23,13 +23,13 @@ export class HeaderCellLinkClick return; } - const { cellData } = this.getCellAppendInfo(event.target); - const field = cellData!.field; - const rowData = this.getCellData(cellData!); + const { meta } = this.getCellAppendInfo(event.target); + const field = meta!.field; + const rowData = this.getCellData(meta!); this.spreadsheet.emit(S2Event.GLOBAL_LINK_FIELD_JUMP, { field, - cellData: cellData!, + meta: meta!, record: rowData as Data, }); } diff --git a/packages/s2-core/src/utils/interaction/formatter.ts b/packages/s2-core/src/utils/interaction/formatter.ts index 9bab62a166..97ea6c2c1c 100644 --- a/packages/s2-core/src/utils/interaction/formatter.ts +++ b/packages/s2-core/src/utils/interaction/formatter.ts @@ -6,9 +6,9 @@ import { getAppendInfo } from './common'; /* formate the base Event data */ export const getBaseCellData = (event: Event): TargetCellInfo => { const targetElement = event?.target as unknown as DisplayObject; - const currentCellData = getAppendInfo(targetElement)?.cellData; + const currentCellMeta = getAppendInfo(targetElement)?.meta; const target = targetElement?.parentNode as S2CellType; - const meta = (target?.getMeta?.() as Node) || currentCellData; + const meta = (target?.getMeta?.() as Node) || currentCellMeta; return { target, diff --git a/packages/s2-react/playground/config.tsx b/packages/s2-react/playground/config.tsx index 2361f9b5c4..21174dc28d 100644 --- a/packages/s2-react/playground/config.tsx +++ b/packages/s2-react/playground/config.tsx @@ -13,7 +13,12 @@ import { import { getBaseSheetComponentOptions } from '@antv/s2-shared'; import { PivotSheetMultiLineTextDataCfg } from '@antv/s2/__tests__/data/data-multi-line-text'; import type { SliderSingleProps } from 'antd'; -import { data, meta, totalData } from '../__tests__/data/mock-dataset.json'; +import { + data, + fields, + meta, + totalData, +} from '../__tests__/data/mock-dataset.json'; import type { SheetComponentOptions } from '../src/components'; export const tableSheetSingleColumns: CustomHeaderField[] = [ @@ -73,47 +78,10 @@ export const tableSheetDataCfg: S2DataConfig = { }; export const pivotSheetDataCfg: S2DataConfig = { - fields: { - rows: ['province', 'city'], - columns: ['type'], - values: ['price'], - valueInCols: true, - }, - data: [ - { - province: '浙江', - city: '义乌1', - type: '笔', - price: 1, - cost: 2, - }, - { - province: '浙江', - city: '义乌2', - type: '笔', - price: 1, - cost: 6, - }, - { - province: '浙江', - type: '笔', - price: 2, - cost: 2, - }, - { - province: '四川', - city: '成都', - type: '笔', - price: 1, - cost: 2, - }, - { - province: '四川', - type: '笔', - price: 1, - cost: 2, - }, - ], + data, + totalData, + meta, + fields, }; export const pivotSheetMultiLineTextDataCfg = PivotSheetMultiLineTextDataCfg; @@ -389,7 +357,7 @@ export const s2Options: SheetComponentOptions = { }, cornerText: '测试测试测试测试测试测试测试测试测试测试', interaction: { - linkFields: ['province', 'city', 'type', EXTRA_FIELD], + linkFields: ['province', 'city', 'type', 'number', EXTRA_FIELD], copy: { enable: true, withFormat: true, diff --git a/s2-site/docs/api/components/sheet-component.zh.md b/s2-site/docs/api/components/sheet-component.zh.md index 63924d285f..85b9dfc23f 100644 --- a/s2-site/docs/api/components/sheet-component.zh.md +++ b/s2-site/docs/api/components/sheet-component.zh.md @@ -99,7 +99,7 @@ tag: Updated | onMouseUp | 表格鼠标松开事件 | (event: CanvasEvent) => void | | | | onSelected | 单元格选中事件 | (cells: ( [Cell](/docs/api/basic-class/base-cell)[] ) => void | | | | onReset | 交互状态重置事件 | (event: KeyboardEvent) => void | | | -| onLinkFieldJump | 链接字段跳转事件 (cellData: @antv/s2 1.37.0 新增) | (data: { key: string; cellData: [Node](/docs/api/basic-class/node); record: [Data](/docs/api/general/S2DataConfig#data) }) => void | | | +| onLinkFieldJump | 链接字段跳转事件 | (data: { field: string; meta: [Node](/docs/api/basic-class/node) \| [ViewMeta](#viewmeta); record: [Data](/docs/api/general/S2DataConfig#data) }) => void | | | | onScroll | 单元格滚动事件 (含行头和数值单元格) | ({position: [CellScrollPosition](#cellscrollposition)} ) => void; | | | | onColCellBrushSelection | 批量选中刷选范围内的列头单元格,刷选过程中,显示刷选范围提示蒙层,刷选完成后,弹出 tooltip, 展示被刷选单元格信息 | (cells: [ColCell](/docs/api/basic-class/base-cell)[]) => void; | | | | onRowCellBrushSelection | 批量选中刷选范围内的行头单元格,刷选过程中,显示刷选范围提示蒙层,刷选完成后,弹出 tooltip, 展示被刷选单元格信息(仅支持透视表) | (cells: [RowCell](/docs/api/basic-class/base-cell)[]) => void; | | | @@ -225,7 +225,7 @@ type SheetComponentOptions = S2Options< | mouseUp | 表格鼠标松开事件 | (event: CanvasEvent) => void | | | | selected | 单元格选中事件 | ( cells: ([Cell](/docs/api/basic-class/base-cell)[] ) => void | | | | reset | 交互状态重置事件 | (event: KeyboardEvent) => void | | | -| linkFieldJump | 链接字段跳转事件 (cellData: @antv/s2 1.37.0 新增) | (data: { key: string; cellData: [Node](/docs/api/basic-class/node); record: [Data](/docs/api/general/S2DataConfig#data) }) => void | | | +| linkFieldJump | 链接字段跳转事件 | (data: { field: string; meta: [Node](/docs/api/basic-class/node) \| [ViewMeta](#viewmeta); record: [Data](/docs/api/general/S2DataConfig#data) }) => void | | | | scroll | 单元格滚动事件 (含行头和数值单元格) | ({position: [CellScrollPosition](#cellscrollposition)} ) => void; | | | | colCellBrushSelection | 批量选中刷选范围内的列头单元格,刷选过程中,显示刷选范围提示蒙层,刷选完成后,弹出 tooltip, 展示被刷选单元格信息 | (cells: ColCell[]) => void; | | | | rowCellBrushSelection | 批量选中刷选范围内的行头单元格,刷选过程中,显示刷选范围提示蒙层,刷选完成后,弹出 tooltip, 展示被刷选单元格信息(仅支持透视表) | (cells: RowCell[]) => void; | | | diff --git a/s2-site/docs/manual/advanced/interaction/link-jump.zh.md b/s2-site/docs/manual/advanced/interaction/link-jump.zh.md index e7ae3501ab..0eb4eb1713 100644 --- a/s2-site/docs/manual/advanced/interaction/link-jump.zh.md +++ b/s2-site/docs/manual/advanced/interaction/link-jump.zh.md @@ -34,8 +34,8 @@ const s2Options = { import { S2Event } from '@antv/s2' s2.on(S2Event.GLOBAL_LINK_FIELD_JUMP, (data) => { - const { field, cellData, record } = data; - ... + const { field, meta, record } = data; + // ... }); ``` @@ -44,7 +44,7 @@ s2.on(S2Event.GLOBAL_LINK_FIELD_JUMP, (data) => { 支持将行头 `rows`, 列头 `columns`, 数值 `values` 标记为链接样式。 ```ts | pure -import { S2Event, EXTRA_FIELD } from '@antv/s2' +import { S2Event } from '@antv/s2' const s2DataConfig = { fields: { @@ -65,7 +65,7 @@ const s2Options = { const s2 = new PivotSheet(container, s2DataConfig, s2Options); s2.on(S2Event.GLOBAL_LINK_FIELD_JUMP, (data) => { - const { field, cellData, record } = data; + const { field, meta, record } = data; const value = record?.[field]; // 拼装自己的跳转地址 @@ -120,7 +120,7 @@ const s2Options = { const s2 = new TableSheet(container, s2DataConfig, s2Options); s2.on(S2Event.GLOBAL_LINK_FIELD_JUMP, (data) => { - const { field, cellData, record } = data; + const { field, meta, record } = data; const value = record?.[field]; // 拼装自己的跳转地址 diff --git a/s2-site/docs/manual/migration-v2.zh.md b/s2-site/docs/manual/migration-v2.zh.md index 055477dbc9..ab0dfcadcf 100644 --- a/s2-site/docs/manual/migration-v2.zh.md +++ b/s2-site/docs/manual/migration-v2.zh.md @@ -732,15 +732,15 @@ const s2Options = { } ``` -#### 链接跳转逻辑变更 +#### 链接跳转逻辑和参数变更 -1. 现在链接跳转支持对 **列头** 标记,且明细表同时对 `列头` 和 `数值` 生效。 -2. 回调参数 `key` 调整为 `field`. +1. 现在链接跳转支持对 **列头** 标记,且明细表同时对 `列头` 和 `数值` 生效(可自定义规则)。 +2. 回调参数 `key` 调整为 `field`, `cellData` 调整为 `meta`. ```diff s2.on(S2Event.GLOBAL_LINK_FIELD_JUMP, (data) => { - const { key, cellData, record } = data; -+ const { field, cellData, record } = data; ++ const { field, meta, record } = data; }); ``` From 3197402cc8e045f0de611b52593fd2d2860e0c34 Mon Sep 17 00:00:00 2001 From: lijinke666 Date: Mon, 1 Jul 2024 16:29:39 +0800 Subject: [PATCH 4/4] =?UTF-8?q?chore:=20=E8=BF=98=E5=8E=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/s2-react/playground/config.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/s2-react/playground/config.tsx b/packages/s2-react/playground/config.tsx index 21174dc28d..e6ae3d4626 100644 --- a/packages/s2-react/playground/config.tsx +++ b/packages/s2-react/playground/config.tsx @@ -2,7 +2,6 @@ /* eslint-disable no-console */ import { EMPTY_PLACEHOLDER, - EXTRA_FIELD, customMerge, type CustomHeaderField, type CustomTreeNode, @@ -357,7 +356,7 @@ export const s2Options: SheetComponentOptions = { }, cornerText: '测试测试测试测试测试测试测试测试测试测试', interaction: { - linkFields: ['province', 'city', 'type', 'number', EXTRA_FIELD], + linkFields: [], copy: { enable: true, withFormat: true,