diff --git a/packages/components/calendar/__test__/__snapshots__/index.test.js.snap b/packages/components/calendar/__test__/__snapshots__/index.test.js.snap
index 5d458ac3a2..7e96062302 100644
--- a/packages/components/calendar/__test__/__snapshots__/index.test.js.snap
+++ b/packages/components/calendar/__test__/__snapshots__/index.test.js.snap
@@ -816,7 +816,7 @@ exports[`calendar :base 1`] = `
diff --git a/packages/components/date-time-picker/__test__/__snapshots__/index.test.js.snap b/packages/components/date-time-picker/__test__/__snapshots__/index.test.js.snap
index 1f620bf4fb..918cc34b9e 100644
--- a/packages/components/date-time-picker/__test__/__snapshots__/index.test.js.snap
+++ b/packages/components/date-time-picker/__test__/__snapshots__/index.test.js.snap
@@ -521,7 +521,7 @@ exports[`date-time-picker :base 1`] = `
diff --git a/packages/components/dialog/__test__/__snapshots__/index.test.js.snap b/packages/components/dialog/__test__/__snapshots__/index.test.js.snap
index 00ae9e2586..fbcc291f25 100644
--- a/packages/components/dialog/__test__/__snapshots__/index.test.js.snap
+++ b/packages/components/dialog/__test__/__snapshots__/index.test.js.snap
@@ -48,7 +48,7 @@ exports[`dialog :base 1`] = `
/>
diff --git a/packages/components/dropdown-menu/__test__/__snapshots__/index.test.js.snap b/packages/components/dropdown-menu/__test__/__snapshots__/index.test.js.snap
index 7983eb5617..51e3e1621d 100644
--- a/packages/components/dropdown-menu/__test__/__snapshots__/index.test.js.snap
+++ b/packages/components/dropdown-menu/__test__/__snapshots__/index.test.js.snap
@@ -675,7 +675,7 @@ exports[`dropdown-menu :base 1`] = `
class="t-dropdown-item__footer t-class-footer"
/>
diff --git a/packages/components/mixins/using-custom-navbar.ts b/packages/components/mixins/using-custom-navbar.ts
index eb25c9f964..d3d3968e6f 100644
--- a/packages/components/mixins/using-custom-navbar.ts
+++ b/packages/components/mixins/using-custom-navbar.ts
@@ -15,10 +15,12 @@ const useCustomNavbarBehavior = Behavior({
distanceTop: 0,
},
- lifetimes: {
- attached() {
- if (this.properties.usingCustomNavbar) {
+ observers: {
+ usingCustomNavbar(value) {
+ if (value) {
this.calculateCustomNavbarDistanceTop();
+ } else {
+ this.setData({ distanceTop: 0 });
}
},
},
diff --git a/packages/components/picker/__test__/__snapshots__/index.test.js.snap b/packages/components/picker/__test__/__snapshots__/index.test.js.snap
index 776f95b7f1..60a3fb50be 100644
--- a/packages/components/picker/__test__/__snapshots__/index.test.js.snap
+++ b/packages/components/picker/__test__/__snapshots__/index.test.js.snap
@@ -200,7 +200,7 @@ exports[`picker :base 1`] = `
diff --git a/packages/components/popup/popup.less b/packages/components/popup/popup.less
index 5f9f4281df..d8bd3c5579 100644
--- a/packages/components/popup/popup.less
+++ b/packages/components/popup/popup.less
@@ -33,6 +33,7 @@
padding: 20rpx;
line-height: 1;
color: @popup-close-btn-color;
+ font-size: 48rpx;
}
&--top {
diff --git a/packages/components/popup/popup.ts b/packages/components/popup/popup.ts
index a2f2f95fb9..73ebbfe66c 100644
--- a/packages/components/popup/popup.ts
+++ b/packages/components/popup/popup.ts
@@ -14,7 +14,7 @@ const name = `${prefix}-popup`;
@wxComponent()
export default class Popup extends SuperComponent {
- externalClasses = [`${prefix}-class`, `${prefix}-class-content`];
+ externalClasses = [`${prefix}-class`, `${prefix}-class-content`, `${prefix}-class-close`];
behaviors = [transition(), useCustomNavbar];
diff --git a/packages/components/popup/popup.wxml b/packages/components/popup/popup.wxml
index 673e377744..6fa11a0812 100644
--- a/packages/components/popup/popup.wxml
+++ b/packages/components/popup/popup.wxml
@@ -29,8 +29,8 @@
>
-
-
+
+
diff --git a/packages/components/table/README.en-US.md b/packages/components/table/README.en-US.md
index d7c5d1448f..5f591630e0 100644
--- a/packages/components/table/README.en-US.md
+++ b/packages/components/table/README.en-US.md
@@ -59,6 +59,8 @@ align | String | left | align type。options: left/right/center | N
cell | String / Function | - | use cell to render table cell。Typescript: `string \| ((params: BaseTableCellParams) => string)` `interface BaseTableCellParams { row: T; rowIndex: number; col: BaseTableCol; colIndex: number }`。[see more ts definition](https://github.com/Tencent/tdesign-miniprogram/blob/develop/packages/components/table/type.ts) | N
class-name | String / Object / Array / Function | - | cell classnames。Typescript: `TableColumnClassName \| TableColumnClassName[]` `type TableColumnClassName = ClassName \| ((context: CellData) => ClassName)` `interface CellData extends BaseTableCellParams { type: 'th' \| 'td' }`。[see more ts definition](https://github.com/Tencent/tdesign-miniprogram/blob/develop/packages/components/common/common.ts)。[see more ts definition](https://github.com/Tencent/tdesign-miniprogram/blob/develop/packages/components/table/type.ts) | N
col-key | String | - | unique key for column | N
+ellipsis | Boolean / Object / Function | false | ellipsis cell content。Typescript: `boolean \| PopupProps \| { props: PopupProps; content: string }`,[Popup API Documents](./popup?tab=api)。[see more ts definition](https://github.com/Tencent/tdesign-miniprogram/blob/develop/packages/components/table/type.ts) | N
+ellipsis-title | Boolean / Object / Function | undefinde | ellipsis title content。Typescript: `boolean \| PopupProps \| { props: PopupProps; content: string }` `interface BaseTableColParams { col: BaseTableCol; colIndex: number }`。[see more ts definition](https://github.com/Tencent/tdesign-miniprogram/blob/develop/packages/components/table/type.ts) | N
fixed | String | left | fixed current column to left or right。options: left/right | N
min-width | String / Number | - | add CSS property `min-width` to HTML Element ``,Browsers with [TablesNG](https://docs.google.com/document/d/16PFD1GtMI9Zgwu0jtPaKZJ75Q2wyZ9EZnVbBacOfiNA/preview) support `minWidth` | N
width | String / Number | - | column width | N
diff --git a/packages/components/table/README.md b/packages/components/table/README.md
index 5884ab5dbd..4e4aeeb980 100644
--- a/packages/components/table/README.md
+++ b/packages/components/table/README.md
@@ -45,7 +45,7 @@ toc: false
{{ stripe }}
-#### 带边框表格样式
+#### 带边框表格样式(内容超出省略与浮层预览)
{{ bordered }}
@@ -113,6 +113,8 @@ align | String | left | 列横向对齐方式。可选项:left/right/center |
cell | String / Function | - | 自定义单元格渲染。默认使用 `colKey` 的值作为自定义当前列的插槽名称。
如果 `cell` 值类型为 Function 表示以函数形式渲染单元格。优先级高于 `render`。泛型 T 指表格数据类型。TS 类型:`string \| ((params: BaseTableCellParams) => string)` `interface BaseTableCellParams { row: T; rowIndex: number; col: BaseTableCol; colIndex: number }`。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/blob/develop/packages/components/table/type.ts) | N
class-name | String / Object / Array / Function | - | 列类名,值类型是 Function 使用返回值作为列类名;值类型不为 Function 时,值用于整列类名(含表头)。泛型 T 指表格数据类型。TS 类型:`TableColumnClassName \| TableColumnClassName[]` `type TableColumnClassName = ClassName \| ((context: CellData) => ClassName)` `interface CellData extends BaseTableCellParams { type: 'th' \| 'td' }`。[通用类型定义](https://github.com/Tencent/tdesign-miniprogram/blob/develop/packages/components/common/common.ts)。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/blob/develop/packages/components/table/type.ts) | N
col-key | String | - | 渲染列所需字段,值为 `serial-number` 表示当前列为「序号」列 | N
+ellipsis | Boolean / Object / Function | false | 单元格和表头内容超出时,是否显示省略号。如果仅希望单元格超出省略,可设置 `ellipsisTitle = false`。
值为 `true`,则超出省略浮层默认显示单元格内容;
值类型为 `Function` 则自定义超出省略浮中层显示的内容。
值类型为 `Object`,则自动透传属性到 Popup 组件,可用于调整弹窗方向等特性。
同时透传 Popup 属性和自定义浮层内容,请使用 `{ props: { showOverlay: false }, content: () => 'something' }`。
请注意单元格超出省略的两个基本点:1. 内容元素是内联元素或样式(自定义单元格内容时需特别注意);2. 内容超出父元素。TS 类型:`boolean \| PopupProps \| { props: PopupProps; content: string }`,[Popup API Documents](./popup?tab=api)。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/blob/develop/packages/components/table/type.ts) | N
+ellipsis-title | Boolean / Object / Function | undefinde | 表头内容超出时,是否显示省略号。优先级高于 `ellipsis`。
值为 `true`,则超出省略的浮层默认显示表头全部内容;
值类型为 `Function` 用于自定义超出省略浮层显示的表头内容;
值类型为 `Object`,则自动透传属性到 Popup 组件,可用于调整弹窗方向等特性。
同时透传 Popup 属性和自定义浮层内容,请使用 `{ props: { showOverlay: false }, content: () => 'something' }`。TS 类型:`boolean \| PopupProps \| { props: PopupProps; content: string }` `interface BaseTableColParams { col: BaseTableCol; colIndex: number }`。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/blob/develop/packages/components/table/type.ts) | N
fixed | String | left | 固定列显示位置。可选项:left/right | N
min-width | String / Number | - | 透传 CSS 属性 `min-width` 到 `` 元素。⚠️ 仅少部分浏览器支持,如:使用 [TablesNG](https://docs.google.com/document/d/16PFD1GtMI9Zgwu0jtPaKZJ75Q2wyZ9EZnVbBacOfiNA/preview) 渲染的 Chrome 浏览器支持 `minWidth` | N
width | String / Number | - | 列宽,可以作为最小宽度使用。当列宽总和小于 `table` 元素时,浏览器根据宽度设置情况自动分配宽度;当列宽总和大于 `table` 元素,表现为定宽。可以同时调整 `table` 元素的宽度来达到自己想要的效果 | N
diff --git a/packages/components/table/__test__/__snapshots__/demo.test.js.snap b/packages/components/table/__test__/__snapshots__/demo.test.js.snap
index a48ba3cbe8..ad06c098a0 100644
--- a/packages/components/table/__test__/__snapshots__/demo.test.js.snap
+++ b/packages/components/table/__test__/__snapshots__/demo.test.js.snap
@@ -281,6 +281,99 @@ exports[`Table Table bordered demo works fine 1`] = `
`;
+exports[`Table Table ellipsis demo works fine 1`] = `
+
+
+
+`;
+
exports[`Table Table rowspan-colspan demo works fine 1`] = `
{
mapper.forEach((demoName) => {
diff --git a/packages/components/table/_example/base/index.wxss b/packages/components/table/_example/base/index.wxss
deleted file mode 100644
index bc0171b967..0000000000
--- a/packages/components/table/_example/base/index.wxss
+++ /dev/null
@@ -1 +0,0 @@
-/* base demo 无额外样式 */
diff --git a/packages/components/table/_example/bordered/index.wxss b/packages/components/table/_example/bordered/index.wxss
deleted file mode 100644
index 0a74168579..0000000000
--- a/packages/components/table/_example/bordered/index.wxss
+++ /dev/null
@@ -1 +0,0 @@
-/* bordered demo 无额外样式 */
diff --git a/packages/components/table/_example/ellipsis/index.js b/packages/components/table/_example/ellipsis/index.js
new file mode 100644
index 0000000000..885201d7df
--- /dev/null
+++ b/packages/components/table/_example/ellipsis/index.js
@@ -0,0 +1,89 @@
+import SkylineBehavior from '@behaviors/skyline.js';
+
+Component({
+ behaviors: [SkylineBehavior],
+ data: {
+ // 组合 ellipsis + ellipsisTitle 的不同形式与取值
+ // 约束:弹出层方向仅 bottom / center;弹出内容为单元格内容;弹出标题为该列表头
+ columns: [
+ // 1. ellipsis 为 Object:整体透传给 Popup(center 弹出 + 列表头作为标题);content 缺省时回退为单元格内容
+ {
+ colKey: 'applicant',
+ title: '申请人',
+ ellipsis: { placement: 'center', title: '申请人' },
+ },
+ // 2. ellipsis 为 Object + ellipsisTitle 为 true:表头内容也超出省略(优先级高于 ellipsis);bottom 弹出
+ {
+ colKey: 'status',
+ title: '审批状态与处理结果',
+ ellipsis: { placement: 'bottom', title: '审批状态' },
+ ellipsisTitle: true,
+ },
+ // 3. ellipsis 为 Object + ellipsisTitle 为 false:仅单元格超出省略,表头不省略
+ {
+ colKey: 'channel',
+ title: '签署方式',
+ ellipsis: { placement: 'bottom', title: '签署方式' },
+ ellipsisTitle: false,
+ },
+ // 4. ellipsis 与 ellipsisTitle 均为 Object:单元格浮层与表头浮层均带列表头标题;bottom 弹出
+ {
+ colKey: 'email',
+ title: '邮箱地址',
+ ellipsis: { placement: 'bottom', title: '邮箱地址' },
+ ellipsisTitle: { placement: 'bottom', title: '邮箱地址' },
+ },
+ ],
+ data: [],
+ },
+ lifetimes: {
+ attached() {
+ const data = [
+ {
+ id: 1,
+ applicant: '贾明(kyrieJia)',
+ status: '审批通过,流程已全部走完',
+ channel: '电子签署(在线完成)',
+ email: 'jiaming.kyrie@example.com',
+ },
+ {
+ id: 2,
+ applicant: '张三(threeZhang)',
+ status: '审批失败,请联系管理员处理',
+ channel: '纸质签署(线下邮寄)',
+ email: 'zhangsan.three@example.com',
+ },
+ {
+ id: 3,
+ applicant: '王芳(fangWang)',
+ status: '审批已过期,需重新发起',
+ channel: '电子签署(在线完成)',
+ email: 'wangfang.fw@example.com',
+ },
+ {
+ id: 4,
+ applicant: '李雷(leiLi)',
+ status: '审批中,等待上级确认',
+ channel: '纸质签署(线下邮寄)',
+ email: 'lilei.ll@example.com',
+ },
+ {
+ id: 5,
+ applicant: '韩梅梅(meiHan)',
+ status: '审批通过,流程已全部走完',
+ channel: '电子签署(在线完成)',
+ email: 'hanmeimei.mm@example.com',
+ },
+ ];
+ this.setData({ data });
+ },
+ },
+ methods: {
+ handleRowClick(e) {
+ console.log('[row-click]', e.detail);
+ },
+ handleCellClick(e) {
+ console.log('[cell-click]', e.detail);
+ },
+ },
+});
diff --git a/packages/components/table/_example/ellipsis/index.json b/packages/components/table/_example/ellipsis/index.json
new file mode 100644
index 0000000000..e3c621db08
--- /dev/null
+++ b/packages/components/table/_example/ellipsis/index.json
@@ -0,0 +1,6 @@
+{
+ "component": true,
+ "usingComponents": {
+ "t-table": "tdesign-miniprogram/table/table"
+ }
+}
diff --git a/packages/components/table/_example/ellipsis/index.wxml b/packages/components/table/_example/ellipsis/index.wxml
new file mode 100644
index 0000000000..dcd1ef5bdf
--- /dev/null
+++ b/packages/components/table/_example/ellipsis/index.wxml
@@ -0,0 +1,9 @@
+
diff --git a/packages/components/table/_example/rowspan-colspan/index.wxss b/packages/components/table/_example/rowspan-colspan/index.wxss
deleted file mode 100644
index 8fae2cf7c7..0000000000
--- a/packages/components/table/_example/rowspan-colspan/index.wxss
+++ /dev/null
@@ -1 +0,0 @@
-/* rowspan-colspan demo 无额外样式 */
diff --git a/packages/components/table/_example/scroll/index.wxss b/packages/components/table/_example/scroll/index.wxss
deleted file mode 100644
index 6c14f83f70..0000000000
--- a/packages/components/table/_example/scroll/index.wxss
+++ /dev/null
@@ -1 +0,0 @@
-/* scroll demo 无额外样式 */
diff --git a/packages/components/table/_example/stripe/index.wxss b/packages/components/table/_example/stripe/index.wxss
deleted file mode 100644
index dacf7e23a1..0000000000
--- a/packages/components/table/_example/stripe/index.wxss
+++ /dev/null
@@ -1 +0,0 @@
-/* stripe demo 无额外样式 */
diff --git a/packages/components/table/_example/table.json b/packages/components/table/_example/table.json
index 0dd71e440d..f85f125f51 100644
--- a/packages/components/table/_example/table.json
+++ b/packages/components/table/_example/table.json
@@ -6,6 +6,7 @@
"bordered": "./bordered",
"stripe": "./stripe",
"scroll": "./scroll",
+ "ellipsis": "./ellipsis",
"rowspan-colspan": "./rowspan-colspan"
}
}
diff --git a/packages/components/table/_example/table.wxml b/packages/components/table/_example/table.wxml
index 234f169c11..5ea3e8cd81 100644
--- a/packages/components/table/_example/table.wxml
+++ b/packages/components/table/_example/table.wxml
@@ -17,6 +17,9 @@
+
+
+
diff --git a/packages/components/table/table.json b/packages/components/table/table.json
index f20e16478f..0d40836af5 100644
--- a/packages/components/table/table.json
+++ b/packages/components/table/table.json
@@ -2,6 +2,7 @@
"component": true,
"styleIsolation": "apply-shared",
"usingComponents": {
- "t-loading": "../loading/loading"
+ "t-loading": "../loading/loading",
+ "t-popup": "../popup/popup"
}
}
diff --git a/packages/components/table/table.less b/packages/components/table/table.less
index aa60ecd112..51906a4b89 100644
--- a/packages/components/table/table.less
+++ b/packages/components/table/table.less
@@ -7,6 +7,8 @@
@table-header-bg-color: var(--td-table-header-bg-color, @bg-color-container);
@table-header-text-color: var(--td-table-header-text-color, @text-color-placeholder);
@table-body-text-color: var(--td-table-body-text-color, @text-color-primary);
+@table-popup-title-color: @text-color-primary;
+@table-popup-title-font: @font-title-medium;
@table-stripe-bg-color: var(--td-table-stripe-bg-color, @bg-color-secondarycontainer);
@table-td-padding: var(--td-table-td-padding, @spacer @spacer-1);
@table-th-padding: var(--td-table-th-padding, @spacer @spacer-1);
@@ -102,10 +104,80 @@
&__th-content,
&__td-content {
overflow: hidden;
+ }
+
+ // 开启 ellipsis / ellipsisTitle 后才出现超出省略
+ &__th-content--ellipsis,
+ &__td-content--ellipsis {
text-overflow: ellipsis;
white-space: nowrap;
}
+ &__popup {
+ &--center {
+ width: 480rpx;
+ height: 480rpx;
+ }
+
+ &--bottom,
+ &--top {
+ width: 100%;
+ height: 436rpx;
+ }
+
+ &--left,
+ &--right {
+ width: 65%;
+ height: 100%;
+ }
+
+ &-inner {
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+ box-sizing: border-box;
+ }
+
+ &-title {
+ flex-shrink: 0;
+ padding: @spacer-2;
+ overflow: hidden;
+ color: @table-popup-title-color;
+ font: @table-popup-title-font;
+ font-weight: 600;
+ text-align: center;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+
+ &:empty {
+ display: none;
+ }
+ }
+
+ &-close {
+ padding: @spacer-2;
+ }
+
+ &-content {
+ flex: 1;
+ overflow: auto;
+ word-break: break-all;
+ color: @table-body-text-color;
+ box-sizing: border-box;
+ padding: calc(48rpx + @spacer-2 * 2) @spacer-2 @spacer-2;
+
+ &--center {
+ padding-right: @spacer-3;
+ padding-bottom: @spacer-3;
+ padding-left: @spacer-3;
+ }
+ }
+
+ &-title:not(:empty) + .@{table-prefix}__popup-content {
+ padding-top: 0;
+ }
+ }
+
// 空数据
&__empty-row {
display: flex;
diff --git a/packages/components/table/table.ts b/packages/components/table/table.ts
index 1c2b28cb4a..8c86a093c2 100644
--- a/packages/components/table/table.ts
+++ b/packages/components/table/table.ts
@@ -10,8 +10,11 @@ import {
getCellKey,
getSkipSpansMap,
handleCellSpan,
+ hasEllipsisColumn,
isFirstColumnInSpan,
isLastRowInSpan,
+ isTextEllipsis,
+ resolveEllipsis,
} from './utils';
const { prefix } = config;
@@ -48,6 +51,12 @@ export default class Table extends SuperComponent {
scrollableToLeft: false,
scrollableToRight: false,
contentClasses: '',
+ // 超出省略(ellipsis / ellipsisTitle)
+ hasEllipsis: false,
+ titleClassNames: [] as string[],
+ titleEllipsisFlags: [] as boolean[],
+ popupProps: { placement: 'center' } as Record,
+ popupVisible: false,
};
observers = {
@@ -85,6 +94,9 @@ export default class Table extends SuperComponent {
} = this.properties;
const { classPrefix } = this.data;
+ // 开启后才渲染预览弹窗,并为单元格/表头附加超出省略测量用的类名
+ const hasEllipsis = hasEllipsisColumn((columns || []) as BaseTableCol[]);
+
// 解析 fixedRows
const fixedTopRows = (fixedRows && (fixedRows as number[])[0]) || 0;
const fixedBottomRows = (fixedRows && (fixedRows as number[])[1]) || 0;
@@ -207,6 +219,19 @@ export default class Table extends SuperComponent {
return classes.filter(Boolean).join(' ');
});
+ // 表头内容类名与省略标记:ellipsisTitle 优先级高于 ellipsis
+ const titleEllipsisList = (columns || []).map((col: BaseTableCol, colIndex: number) =>
+ resolveEllipsis(col.ellipsisTitle !== undefined ? col.ellipsisTitle : col.ellipsis, { col, colIndex }),
+ );
+ const titleClassNames = titleEllipsisList.map((item: any, colIndex: number) => {
+ const classes: string[] = [`${classPrefix}__th-content`];
+ if (item.enabled) {
+ classes.push(`${classPrefix}__th-content--ellipsis`, `${classPrefix}__th-content-${colIndex}`);
+ }
+ return classes.filter(Boolean).join(' ');
+ });
+ const titleEllipsisFlags = titleEllipsisList.map((item: any) => !!item.enabled);
+
// 计算合并单元格
const hasSpan = !!rowspanAndColspan && !!data?.length && !!columns?.length;
const skipSpansMap = getSkipSpansMap(data, columns, rowKey, rowspanAndColspan as Function);
@@ -245,11 +270,21 @@ export default class Table extends SuperComponent {
}
}
+ const cellEllipsis = resolveEllipsis(col.ellipsis, { row, col, rowIndex, colIndex });
+
// 合并场景用 grid 定位实现跨行跨列,非合并场景沿用列宽样式
const cellStyle = hasSpan
? `grid-column: ${colIndex + 1} / span ${colspan || 1}; grid-row: ${rowIndex + 1} / span ${rowspan || 1}`
: colStyles[colIndex];
+ const contentClasses: string[] = [`${classPrefix}__td-content`];
+ if (cellEllipsis.enabled) {
+ contentClasses.push(
+ `${classPrefix}__td-content--ellipsis`,
+ `${classPrefix}__td-content-${rowIndex}-${colIndex}`,
+ );
+ }
+
return {
colKey: col.colKey || String(colIndex),
colIndex,
@@ -257,6 +292,8 @@ export default class Table extends SuperComponent {
tdClass: tdClasses.filter(Boolean).join(' '),
cellStyle,
skipped: skipped || false,
+ contentClass: contentClasses.filter(Boolean).join(' '),
+ ellipsis: !!cellEllipsis.enabled,
};
});
@@ -338,6 +375,9 @@ export default class Table extends SuperComponent {
hasSpan,
tbodyStyles,
contentClasses,
+ hasEllipsis,
+ titleClassNames,
+ titleEllipsisFlags,
},
() => {
// 动态测量行高,修正固定行的 top/bottom 值
@@ -403,9 +443,77 @@ export default class Table extends SuperComponent {
}
},
+ /** 展示超出省略内容的预览弹窗(仅当内容实际溢出时才弹出) */
+ showEllipsisPopup(
+ this: any,
+ type: 'td' | 'th',
+ rowIndex: number,
+ colIndex: number,
+ content: string,
+ props: Record,
+ ) {
+ if (!content) return;
+
+ const { classPrefix } = this.data;
+ const suffix = type === 'th' ? `${colIndex}` : `${rowIndex}-${colIndex}`;
+
+ const query = this.createSelectorQuery();
+ query.select(`.${classPrefix}__${type}-content-${suffix}`).boundingClientRect();
+ query.select(`.${classPrefix}__${type}-text-${suffix}`).boundingClientRect();
+ query.exec((res: any) => {
+ const [contentRect, textRect] = res || [];
+ // 内容实际宽度大于可视宽度才视为溢出(对齐桌面端 scrollWidth > clientWidth)
+ if (!isTextEllipsis(contentRect, textRect)) return;
+
+ this.setData({
+ popupProps: {
+ placement: props.placement || 'center',
+ showOverlay: props.showOverlay !== false,
+ closeOnOverlayClick: props.closeOnOverlayClick !== false,
+ closeBtn: props.closeBtn !== false,
+ usingCustomNavbar: !!props.usingCustomNavbar,
+ title: props.title || '',
+ content,
+ },
+ popupVisible: true,
+ });
+ });
+ },
+
+ /** 点击表头:表头内容超出省略时,弹出浮层预览完整标题 */
+ onTitleClick(this: any, e: any) {
+ const { colIndex } = e.currentTarget.dataset;
+ const { columns } = this.properties;
+ const col = columns && columns[colIndex];
+ if (!col) return;
+
+ const resolved = resolveEllipsis(col.ellipsisTitle !== undefined ? col.ellipsisTitle : col.ellipsis, {
+ col,
+ colIndex,
+ });
+ if (!resolved.enabled) return;
+
+ this.showEllipsisPopup('th', 0, colIndex, resolved.content || col.title || '', resolved.props);
+ },
+
+ onPopupVisibleChange(this: any, e: any) {
+ const { visible } = e.detail || {};
+ if (!!visible !== this.data.popupVisible) {
+ this.setData({ popupVisible: !!visible });
+ }
+ },
+
onCellClick(this: any, e: any) {
const { rowIndex, colIndex } = e.currentTarget.dataset;
const { data, columns } = this.properties;
+ const cell = this.data.renderData?.[rowIndex]?.cells?.[colIndex];
+ const col = columns && columns[colIndex];
+ if (cell && col) {
+ const resolved = resolveEllipsis(col.ellipsis, { row: data[rowIndex], col, rowIndex, colIndex });
+ if (resolved.enabled) {
+ this.showEllipsisPopup('td', rowIndex, colIndex, resolved.content || cell.content, resolved.props);
+ }
+ }
if (data && data[rowIndex] && columns && columns[colIndex]) {
this.triggerEvent('cell-click', {
row: data[rowIndex],
diff --git a/packages/components/table/table.wxml b/packages/components/table/table.wxml
index 2fa0f239c9..8087681215 100644
--- a/packages/components/table/table.wxml
+++ b/packages/components/table/table.wxml
@@ -9,7 +9,12 @@
data-col-index="{{cell.colIndex}}"
bind:tap="onCellClick"
>
- {{cell.content}}
+
+
+ {{cell.content}}
+
+ {{cell.content}}
+
@@ -32,8 +37,15 @@
wx:key="colKey"
class="{{classPrefix}}__th {{thClassNames[colIndex]}}"
style="{{colStyles[colIndex]}}"
+ data-col-index="{{colIndex}}"
+ bind:tap="onTitleClick"
>
- {{col.title}}
+
+
+ {{col.title}}
+
+ {{col.title}}
+
@@ -93,4 +105,25 @@
{{footerSummary}}
+
+
+
+
+
diff --git a/packages/components/table/type.ts b/packages/components/table/type.ts
index e639e93115..c55faca4ed 100644
--- a/packages/components/table/type.ts
+++ b/packages/components/table/type.ts
@@ -5,6 +5,7 @@
* */
import { LoadingProps } from '../loading/index';
+import { PopupProps } from '../popup/index';
import type { ClassName } from '../common/common';
export interface TdBaseTableProps {
@@ -166,6 +167,16 @@ export interface BaseTableCol {
* @default ''
*/
colKey?: string;
+ /**
+ * 单元格和表头内容超出时,是否显示省略号。如果仅希望单元格超出省略,可设置 `ellipsisTitle = false`。
值为 `true`,则超出省略浮层默认显示单元格内容;
值类型为 `Function` 则自定义超出省略浮中层显示的内容。
值类型为 `Object`,则自动透传属性到 Popup 组件,可用于调整弹窗方向等特性。
同时透传 Popup 属性和自定义浮层内容,请使用 `{ props: { showOverlay: false }, content: () => 'something' }`。
请注意单元格超出省略的两个基本点:1. 内容元素是内联元素或样式(自定义单元格内容时需特别注意);2. 内容超出父元素
+ * @default false
+ */
+ ellipsis?: boolean | PopupProps | { props: PopupProps; content: string };
+ /**
+ * 表头内容超出时,是否显示省略号。优先级高于 `ellipsis`。
值为 `true`,则超出省略的浮层默认显示表头全部内容;
值类型为 `Function` 用于自定义超出省略浮层显示的表头内容;
值类型为 `Object`,则自动透传属性到 Popup 组件,可用于调整弹窗方向等特性。
同时透传 Popup 属性和自定义浮层内容,请使用 `{ props: { showOverlay: false }, content: () => 'something' }`
+ * @default undefinde
+ */
+ ellipsisTitle?: boolean | PopupProps | { props: PopupProps; content: string };
/**
* 固定列显示位置
* @default left
@@ -209,4 +220,9 @@ export interface CellData extends BaseTab
type: 'th' | 'td';
}
+export interface BaseTableColParams {
+ col: BaseTableCol;
+ colIndex: number;
+}
+
export type DataType = TableRowData;
diff --git a/packages/components/table/utils.ts b/packages/components/table/utils.ts
index c3cba4aae3..3048d125f6 100644
--- a/packages/components/table/utils.ts
+++ b/packages/components/table/utils.ts
@@ -117,3 +117,64 @@ export function isLastRowInSpan(rowIndex: number, rowspan?: number, totalDataLen
export function isFirstColumnInSpan(colIndex: number): boolean {
return colIndex === 0;
}
+
+// ------- 超出省略(ellipsis / ellipsisTitle) -------
+
+export interface EllipsisResult {
+ /** 是否开启超出省略 */
+ enabled: boolean;
+ /** 浮层展示内容,缺省时回退为单元格/表头完整内容 */
+ content?: string;
+ /** 透传给 Popup 组件的属性 */
+ props: Record;
+}
+
+/**
+ * 解析 `ellipsis` / `ellipsisTitle` 配置。
+ * 支持 `boolean` / `Object`(透传 Popup)/ `{ props, content }` / `Function`(按单元格动态返回)。
+ * `ellipsisTitle` 优先级高于 `ellipsis`,由调用方决定取值。
+ */
+export function resolveEllipsis(value: any, params: Record): EllipsisResult {
+ const disabled: EllipsisResult = { enabled: false, props: {} };
+ let result = value;
+
+ if (typeof value === 'function') {
+ try {
+ result = value(params);
+ } catch (err) {
+ // 函数可能依赖行数据(表头场景没有 row),异常时按未开启超出省略处理
+ return disabled;
+ }
+ }
+
+ if (result === false || result === null || result === undefined) return disabled;
+ if (typeof result === 'string') return { enabled: true, content: result, props: {} };
+ if (typeof result !== 'object') return { enabled: !!result, props: {} };
+
+ // `{ props, content }` 中 props 透传 Popup;其余形式整体作为 Popup 属性透传
+ const props: Record = result.props && typeof result.props === 'object' ? { ...result.props } : {};
+ if (!result.props) {
+ Object.keys(result).forEach((key) => {
+ if (key !== 'content') props[key] = result[key];
+ });
+ }
+
+ const content = typeof result.content === 'function' ? result.content() : result.content;
+ return { enabled: true, content: typeof content === 'string' ? content : undefined, props };
+}
+
+/** 是否存在列开启了超出省略 */
+export function hasEllipsisColumn(columns: BaseTableCol[]): boolean {
+ return (columns || []).some((col) => !!col.ellipsis || !!col.ellipsisTitle);
+}
+
+/**
+ * 判断单元格/表头内容是否溢出(对齐桌面端 `isTextEllipsis`:`scrollWidth > clientWidth`)。
+ * 小程序无法直接取节点 `scrollWidth`,故用内层文本节点的实际宽度(≈ scrollWidth)
+ * 与内容容器的可视宽度(≈ clientWidth)比较,内容宽度更大即为溢出。
+ * `tolerance` 用于消除 `boundingClientRect` 的亚像素误差。
+ */
+export function isTextEllipsis(contentRect?: { width: number }, textRect?: { width: number }, tolerance = 1): boolean {
+ if (!contentRect || !textRect) return false;
+ return textRect.width - contentRect.width > tolerance;
+}
diff --git a/packages/uniapp-components/table/README.en-US.md b/packages/uniapp-components/table/README.en-US.md
index efab84369f..73b53a5231 100644
--- a/packages/uniapp-components/table/README.en-US.md
+++ b/packages/uniapp-components/table/README.en-US.md
@@ -50,6 +50,8 @@ align | String | left | align type。options: left/right/center | N
cell | String / Function | - | use cell to render table cell。Typescript: `string \| ((params: BaseTableCellParams) => string)` `interface BaseTableCellParams { row: T; rowIndex: number; col: BaseTableCol; colIndex: number }`。[see more ts definition](https://github.com/tencent/tdesign-miniprogram/blob/develop/packages/uniapp-components/table/type.ts) | N
class-name | String / Object / Array / Function | - | cell classnames。Typescript: `TableColumnClassName \| TableColumnClassName[]` `type TableColumnClassName = ClassName \| ((context: CellData) => ClassName)` `interface CellData extends BaseTableCellParams { type: 'th' \| 'td' }`。[see more ts definition](https://github.com/tencent/tdesign-miniprogram/blob/develop/packages/uniapp-components/common/common.ts)。[see more ts definition](https://github.com/tencent/tdesign-miniprogram/blob/develop/packages/uniapp-components/table/type.ts) | N
col-key | String | - | unique key for column | N
+ellipsis | Boolean / Object / Function | false | ellipsis cell content。Typescript: `boolean \| PopupProps \| { props: PopupProps; content: string }`,[Popup API Documents](./popup?tab=api)。[see more ts definition](https://github.com/tencent/tdesign-miniprogram/blob/develop/packages/uniapp-components/table/type.ts) | N
+ellipsis-title | Boolean / Object / Function | undefinde | ellipsis title content。Typescript: `boolean \| PopupProps \| { props: PopupProps; content: string }` `interface BaseTableColParams { col: BaseTableCol; colIndex: number }`。[see more ts definition](https://github.com/tencent/tdesign-miniprogram/blob/develop/packages/uniapp-components/table/type.ts) | N
fixed | String | left | fixed current column to left or right。options: left/right | N
min-width | String / Number | - | add CSS property `min-width` to HTML Element ``,Browsers with [TablesNG](https://docs.google.com/document/d/16PFD1GtMI9Zgwu0jtPaKZJ75Q2wyZ9EZnVbBacOfiNA/preview) support `minWidth` | N
width | String / Number | - | column width | N
diff --git a/packages/uniapp-components/table/README.md b/packages/uniapp-components/table/README.md
index 53bb6deba3..43bf7988a6 100644
--- a/packages/uniapp-components/table/README.md
+++ b/packages/uniapp-components/table/README.md
@@ -95,6 +95,8 @@ align | String | left | 列横向对齐方式。可选项:left/right/center |
cell | String / Function | - | 自定义单元格渲染。默认使用 `colKey` 的值作为自定义当前列的插槽名称。
如果 `cell` 值类型为 Function 表示以函数形式渲染单元格。优先级高于 `render`。泛型 T 指表格数据类型。TS 类型:`string \| ((params: BaseTableCellParams) => string)` `interface BaseTableCellParams { row: T; rowIndex: number; col: BaseTableCol; colIndex: number }`。[详细类型定义](https://github.com/tencent/tdesign-miniprogram/blob/develop/packages/uniapp-components/table/type.ts) | N
class-name | String / Object / Array / Function | - | 列类名,值类型是 Function 使用返回值作为列类名;值类型不为 Function 时,值用于整列类名(含表头)。泛型 T 指表格数据类型。TS 类型:`TableColumnClassName \| TableColumnClassName[]` `type TableColumnClassName = ClassName \| ((context: CellData) => ClassName)` `interface CellData extends BaseTableCellParams { type: 'th' \| 'td' }`。[通用类型定义](https://github.com/tencent/tdesign-miniprogram/blob/develop/packages/uniapp-components/common/common.ts)。[详细类型定义](https://github.com/tencent/tdesign-miniprogram/blob/develop/packages/uniapp-components/table/type.ts) | N
col-key | String | - | 渲染列所需字段,值为 `serial-number` 表示当前列为「序号」列 | N
+ellipsis | Boolean / Object / Function | false | 单元格和表头内容超出时,是否显示省略号。如果仅希望单元格超出省略,可设置 `ellipsisTitle = false`。
值为 `true`,则超出省略浮层默认显示单元格内容;
值类型为 `Function` 则自定义超出省略浮中层显示的内容。
值类型为 `Object`,则自动透传属性到 Popup 组件,可用于调整弹窗方向等特性。
同时透传 Popup 属性和自定义浮层内容,请使用 `{ props: { showOverlay: false }, content: () => 'something' }`。
请注意单元格超出省略的两个基本点:1. 内容元素是内联元素或样式(自定义单元格内容时需特别注意);2. 内容超出父元素。TS 类型:`boolean \| PopupProps \| { props: PopupProps; content: string }`,[Popup API Documents](./popup?tab=api)。[详细类型定义](https://github.com/tencent/tdesign-miniprogram/blob/develop/packages/uniapp-components/table/type.ts) | N
+ellipsis-title | Boolean / Object / Function | undefinde | 表头内容超出时,是否显示省略号。优先级高于 `ellipsis`。
值为 `true`,则超出省略的浮层默认显示表头全部内容;
值类型为 `Function` 用于自定义超出省略浮层显示的表头内容;
值类型为 `Object`,则自动透传属性到 Popup 组件,可用于调整弹窗方向等特性。
同时透传 Popup 属性和自定义浮层内容,请使用 `{ props: { showOverlay: false }, content: () => 'something' }`。TS 类型:`boolean \| PopupProps \| { props: PopupProps; content: string }` `interface BaseTableColParams { col: BaseTableCol; colIndex: number }`。[详细类型定义](https://github.com/tencent/tdesign-miniprogram/blob/develop/packages/uniapp-components/table/type.ts) | N
fixed | String | left | 固定列显示位置。可选项:left/right | N
min-width | String / Number | - | 透传 CSS 属性 `min-width` 到 `` 元素。⚠️ 仅少部分浏览器支持,如:使用 [TablesNG](https://docs.google.com/document/d/16PFD1GtMI9Zgwu0jtPaKZJ75Q2wyZ9EZnVbBacOfiNA/preview) 渲染的 Chrome 浏览器支持 `minWidth` | N
width | String / Number | - | 列宽,可以作为最小宽度使用。当列宽总和小于 `table` 元素时,浏览器根据宽度设置情况自动分配宽度;当列宽总和大于 `table` 元素,表现为定宽。可以同时调整 `table` 元素的宽度来达到自己想要的效果 | N
diff --git a/packages/uniapp-components/table/type.ts b/packages/uniapp-components/table/type.ts
index 65a884ac26..5ba5934b51 100644
--- a/packages/uniapp-components/table/type.ts
+++ b/packages/uniapp-components/table/type.ts
@@ -5,6 +5,7 @@
* */
import type { TdLoadingProps as LoadingProps } from '../loading/type';
+import type { TdPopupProps as PopupProps } from '../popup/type';
import type { ClassName } from '../common/common';
export interface TdBaseTableProps {
@@ -119,6 +120,16 @@ export interface BaseTableCol {
* @default ''
*/
colKey?: string;
+ /**
+ * 单元格和表头内容超出时,是否显示省略号。如果仅希望单元格超出省略,可设置 `ellipsisTitle = false`。
值为 `true`,则超出省略浮层默认显示单元格内容;
值类型为 `Function` 则自定义超出省略浮中层显示的内容。
值类型为 `Object`,则自动透传属性到 Popup 组件,可用于调整弹窗方向等特性。
同时透传 Popup 属性和自定义浮层内容,请使用 `{ props: { showOverlay: false }, content: () => 'something' }`。
请注意单元格超出省略的两个基本点:1. 内容元素是内联元素或样式(自定义单元格内容时需特别注意);2. 内容超出父元素
+ * @default false
+ */
+ ellipsis?: boolean | PopupProps | { props: PopupProps; content: string };
+ /**
+ * 表头内容超出时,是否显示省略号。优先级高于 `ellipsis`。
值为 `true`,则超出省略的浮层默认显示表头全部内容;
值类型为 `Function` 用于自定义超出省略浮层显示的表头内容;
值类型为 `Object`,则自动透传属性到 Popup 组件,可用于调整弹窗方向等特性。
同时透传 Popup 属性和自定义浮层内容,请使用 `{ props: { showOverlay: false }, content: () => 'something' }`
+ * @default undefinde
+ */
+ ellipsisTitle?: boolean | PopupProps | { props: PopupProps; content: string };
/**
* 固定列显示位置
* @default left
@@ -170,11 +181,15 @@ export interface BaseTableCellParams {
}
export type TableColumnClassName =
- | ClassName
- | ((context: CellData) => ClassName);
+ ClassName | ((context: CellData) => ClassName);
export interface CellData extends BaseTableCellParams {
type: 'th' | 'td';
}
+export interface BaseTableColParams {
+ col: BaseTableCol;
+ colIndex: number;
+}
+
export type DataType = TableRowData;