This commit is contained in:
oneao committed 2026-10-16 17:30:17 +08:00
1 parent e7c84a82a2
commit 025d3232c4
65 files changed
+9838 -9111

No files matched your search

+38 -86
View File
@@ -203,16 +203,7 @@ const App = {
title: '金额',
width: 120,
align: 'right',
// 展示:千分位 + ¥ 前缀。**小数位不写在这里**,统一由 editor.precision 给
format: { thousands: true, prefix: '¥' },
editor: {
type: 'number',
// 精度:两位小数。超出即 error(红底 + 左侧竖条 + 悬停浮层「最多 2 位小数」),
// 且**不改数据** —— E2E 用它验「输多了只标红、值原样保留」
precision: 2,
// 金额必须 > 0:让「校验态全表可见」在 E2E 里有可断言的 error 数据
validate: (v: unknown) => Number(v) > 0 || '金额必须大于 0',
},
editor: { type: 'input', inputType: 'number' },
},
{
dataIndex: 'status',
@@ -224,8 +215,7 @@ const App = {
{ label: '启用', value: 1 },
{ label: '停用', value: 0 },
],
// 按行禁用:enabled=0 的那一行状态不许改 —— 用来锁「动态灰底」这条视觉
// (e2e 断言第 2 行灰、第 1 行不灰,且都**不需要先进入编辑行**)
// 按行禁用:enabled=0 的那一行状态不许改(fms 的 editor.disabled 语义)
disabled: (row: { enabled?: number }) => row.enabled === 0,
},
},
@@ -233,11 +223,7 @@ const App = {
{
dataIndex: 'remark',
title: '备注',
editor: {
type: 'text',
// 备注非空:提供 warning 级校验(金额是 error,这里是 warning,两级都有样例)
validateWarning: (v: unknown) => String(v ?? '').length > 0 || '建议填写备注',
},
editor: { type: 'input' },
},
{ dataIndex: 'op', title: '操作', width: 140, resizable: false, actions: [
{ label: '编辑', onClick: () => {} },
@@ -256,8 +242,8 @@ const App = {
// 路径只能在这种「行数多到会虚拟化」的表上复现(见 e2e/table.spec.ts 的键盘跳格用例)
const bigTableColumns = [
{ dataIndex: 'id', title: 'ID', width: 80 },
{ dataIndex: 'name', title: '名称', width: 200, editor: { type: 'text' } },
{ dataIndex: 'value', title: '数值', width: 140, align: 'right', editor: { type: 'number' } },
{ dataIndex: 'name', title: '名称', width: 200, editor: { type: 'input' } },
{ dataIndex: 'value', title: '数值', width: 140, align: 'right', editor: { type: 'input', inputType: 'number' } },
]
const bigTableData = Array.from({ length: 5000 }, (_, i) => ({
id: i + 1,
@@ -266,11 +252,10 @@ const App = {
}))
/**
* 纯展示表(列上**都没有** `editor`)—— 「不可改灰底」门控的宿主。
* 纯展示表(列上**都没有** `editor`)。
*
* 灰底的语义是「这一格现在改不了」,只有**旁边存在可改的格子**时才是信息。
* 这类表若逐格铺灰,整张表看上去就是「禁用状态」(文档里 6/7 张 demo 正是纯展示表)。
* 判据在 G3Table 的 editableColumnsExist / shouldMarkReadonly,见那边注释。
* ⚠️ fms-vue 的 fms-table 没有「不可改灰底」这套视觉(那是旧版 G3Table 的自有能力),
* 所以本表与其它表的差别只剩「没有编辑器」。
*/
const plainColumns = [
{ dataIndex: 'code', title: '编号', width: 120 },
@@ -282,29 +267,23 @@ const App = {
{ code: 'A-002', name: '纯展示行 2', remark: '这一列也不可编辑' },
])
/* ---- Table:固定列 + 校验态(几何回归用例的宿主)---- */
/* ---- Table:固定列 + 受控当前行 ---- */
/**
* 为什么单独造一份数据:
* 「校验未通过的格子刚好在固定列上」这个组合出过一次**只有真浏览器才量得出**的
* 位移 —— 校验态样式给 td 的 `position: relative` 覆盖了库的固定列定位,
* 内联的 `left: 200px` 于是从「sticky 吸附偏移」变成普通相对位移,
* 整格被推开「前面所有左固定列宽度之和」。happy-dom 没有布局引擎,锁不住这类问题。
* 固定列的宿主:列宽总和顶出视口,制造必须横向滚动的场景。
*
* 两个刻意之处:
* · 第 2 行名称为空 → 固定列上必然出现一个 error 格;
* · 列宽总和(1680px)超过视口宽度 → 必须横向滚动,固定列才有「固定」可言。
* 配置只有列上的 `fixed`,但有三条硬约束:
* · `fixed: 'left'` 的列排在最前面、`'right'` 的排在最后面;
* · 固定列必须写 `width`(左固定列的吸附位移由「它左侧固定列宽度累加」算出);
* · 总列宽要超过容器宽,否则固定与不固定看不出区别。
*/
const fixedTableColumns = [
{ dataIndex: 'code', title: '编号(左固定)', width: 200, fixed: 'left' },
{
dataIndex: 'name',
title: '名称(校验列)',
title: '名称',
width: 200,
fixed: 'left',
editor: {
type: 'text',
validate: (v: unknown) => String(v ?? '').length > 0 || '名称不能为空',
},
editor: { type: 'input' },
},
// 填充列:把总宽顶出视口,否则固定列与普通列长得一模一样
...Array.from({ length: 6 }, (_, i) => ({
@@ -318,7 +297,6 @@ const App = {
Object.fromEntries(Array.from({ length: 6 }, (_, k) => [`extra${k}`, `填充值 ${k + 1}-${row}`]))
const fixedTableData = [
{ id: 1, code: 'A-001', name: '正常行', remark: '已归档', ...fixedRowFillers(1) },
// 空名称 → 这一格必然处于 error 态
{ id: 2, code: 'A-002', name: '', remark: '待复核', ...fixedRowFillers(2) },
]
/**
@@ -331,32 +309,16 @@ const App = {
const fixedActiveKey = ref<string | null>(null)
/**
* 日期编辑器(`editor.type = 'date'`)的宿主。
* 日期列(**只读展示**)。
*
* 刻意**单独一张小表**,而不是往 table-wrap 里加列:那张表的列序被 Tab 跳格用例
* 逐格锁着(amount → status → enabled → remark 的顺位),插一列就要连带改一串断言。
*
* 两列刻意配不同格式,覆盖 `format` 的两种用法:
* · 开航日 —— 默认 `YYYY-MM-DD`(面板选到「日」为止),并配必填校验;
* · 截单日 —— `'YYYY-MM-DD HH:mm'`,面板会多出时间列、选完要点「确定」才提交。
* ⚠️ fms-vue 的 fms-table 没有 date 编辑器,所以本组件也没有 —— `editor.type`
* 只有 input / select / checkbox。这里保留两列纯粹是让「含日期字符串的列」
* 在真实密度下正常渲染,不再挂编辑器。
*/
const dateTableColumns = ref<G3TableColumn<TableRow>[]>([
{ dataIndex: 'bookingNo', title: '订舱号', width: 120 },
{
dataIndex: 'etd',
title: '开航日',
width: 150,
editor: {
type: 'date',
validate: (v: unknown) => String(v ?? '').length > 0 || '请选择开航日',
},
},
{
dataIndex: 'docClose',
title: '截单日',
width: 180,
editor: { type: 'date', format: 'YYYY-MM-DD HH:mm' },
},
{ dataIndex: 'etd', title: '开航日', width: 150 },
{ dataIndex: 'docClose', title: '截单日', width: 180 },
])
const dateTableData = ref<TableRow[]>([
{ id: 1, bookingNo: 'BK001', etd: '2026-03-15', docClose: '2026-03-12 18:00' },
@@ -366,18 +328,19 @@ const App = {
])
/**
* 键盘行为的宿主:三列分别覆盖「单行 text」「单行 number」「多行 textarea」。
* 键盘行为的宿主:三列都是**单行**编辑器。
*
* 单行与多行的 Enter 语义**不同**(确认下移 vs 换行),所以必须有一列 textarea
* 才能把这条区分锁住 —— table-wrap 里没有多行编辑器。
* 表格编辑器没有 `textarea`(见 `src/table/types.ts` 里 `TableEditor.type` 的说明:
* 行高放不下多行正文),所以这里不存在「多行 Enter 换行」那种分支 ——
* Enter 一律是「确认 + 下移」,上下键一律归表格导航。
*/
const keysTableColumns = ref<G3TableColumn<TableRow>[]>([
{ dataIndex: 'code', title: '编号', width: 130, editor: { type: 'text' } },
{ dataIndex: 'qty', title: '数量', width: 110, align: 'right', editor: { type: 'number' } },
{ dataIndex: 'note', title: '备注(多行)', width: 260, editor: { type: 'textarea' } },
{ dataIndex: 'code', title: '编号', width: 130, editor: { type: 'input' } },
{ dataIndex: 'qty', title: '数量', width: 110, align: 'right', editor: { type: 'input', inputType: 'number' } },
{ dataIndex: 'note', title: '备注', width: 260, editor: { type: 'input' } },
])
const keysTableData = ref<TableRow[]>([
{ id: 1, code: 'K-001', qty: 12, note: '第一行' },
{ id: 1, code: 'K-001', qty: 12, note: '备注一' },
{ id: 2, code: 'K-002', qty: 34, note: '' },
{ id: 3, code: 'K-003', qty: 56, note: '' },
])
@@ -704,9 +667,7 @@ const App = {
/>
</div>
<!-- 大数据量(5000 行):纵向虚拟滚动应当开启;容器限高以产生滚动。
顺带开斑马纹:纵向虚拟时库改取 nth-child(odd)(DOM 首行≈偶数数据行),
冻结列的条纹叠色必须跟着同一套 nth-child 走(见 _overrides.scss 的 stripe 段)。 -->
<!-- 大数据量(5000 行):纵向虚拟滚动应当开启;容器限高以产生滚动。 -->
<div data-testid="table-big-wrap" style="height: 360px; margin-top: 16px">
<G3Table
data-testid="table-big"
@@ -714,7 +675,6 @@ const App = {
:data-source="bigTableData"
:seq="false"
:row-height="30"
stripe
/>
</div>
@@ -728,24 +688,23 @@ const App = {
/>
</div>
<!-- 固定列 + 校验态 + 受控当前行:几何与「点格进编辑要高亮」的回归宿主 -->
<!-- 固定列 + 受控当前行 -->
<div data-testid="table-fixed-wrap" style="height: 240px; margin-top: 16px">
<G3Table
data-testid="table-fixed"
:columns="fixedTableColumns"
:data-source="fixedTableData"
:active-row-key="fixedActiveKey"
fixed-col-shadow
@row-click="(_, row) => (fixedActiveKey = String(row.id))"
/>
</div>
<!-- 纯展示表(列上都没有 editor):不该铺「不可改」灰底 -->
<!-- 纯展示表(列上都没有 editor) -->
<div data-testid="table-plain-wrap" style="height: 200px; margin-top: 16px">
<G3Table data-testid="table-plain" :columns="plainColumns" :data-source="plainData" />
</div>
<!-- 关闭编辑(editable: false),但列上声明了 editor:同样不该铺灰底 -->
<!-- 关闭编辑(editable: false),但列上声明了 editor -->
<div data-testid="table-noedit-wrap" style="height: 200px; margin-top: 16px">
<G3Table
data-testid="table-noedit"
@@ -755,14 +714,8 @@ const App = {
/>
</div>
<!-- 斑马纹(stripe):固定列(序号列)也要跟着上条纹。
用纯展示列(没有 editor)当宿主,避免「不可改灰底」盖住条纹干扰断言。 -->
<div data-testid="table-stripe-wrap" style="height: 200px; margin-top: 16px">
<G3Table data-testid="table-stripe" :columns="plainColumns" :data-source="plainData" stripe />
</div>
<!-- 日期编辑器(editor.type = 'date'):点格即弹日历,值始终是字符串。
刻意单独一张表:table-wrap 的列序被 Tab 跳格用例逐格锁着,往它里面加列会连带改一堆断言。 -->
<!-- 日期列(只读展示):fms 没有 date 编辑器,见 dateTableColumns 的说明。 -->
<div data-testid="table-date-wrap" style="height: 220px; margin-top: 16px">
<G3Table
data-testid="table-date"
@@ -772,15 +725,14 @@ const App = {
/>
</div>
<!-- 键盘行为的宿主:Enter 下移 / 多行换行 / 方向键归输入框。
同样单独一张表(理由同上),行高给足让 textarea 有地方显示多行。 -->
<!-- 键盘行为的宿主:Enter 下移 / 左右键到边界切格 / 上下键切行。
同样单独一张表(理由同上)。三列都是单行编辑器 —— 表格没有 textarea。 -->
<div data-testid="table-keys-wrap" style="height: 260px; margin-top: 16px">
<G3Table
data-testid="table-keys"
:columns="keysTableColumns"
:data-source="keysTableData"
:seq="false"
:row-height="64"
/>
</div>
</section>
@@ -788,4 +740,4 @@ const App = {
`,
}
createApp(App).mount('#app')
createApp(App).mount('#app')