fix(web): use page scrolling for all tables
This commit is contained in:
@@ -10,7 +10,7 @@ import { PlusOutlined, ReloadOutlined } from '@ant-design/icons';
|
||||
import type { ColumnsType } from 'antd/es/table';
|
||||
import { remove, creatorUpdate, creatorGet, creatorAction } from '@/services/api';
|
||||
import { accountReadiness, conflictMessage, dateTime } from '@/utils/helpers';
|
||||
import { fixedLeft, fixedRight, tablePagination, useOverflowGrid } from '@/utils/table';
|
||||
import { fixedLeft, fixedRight, tablePagination } from '@/utils/table';
|
||||
import AccountLoginModal from '@/components/accounts/AccountLoginModal';
|
||||
import AccountCreateModal from '@/components/accounts/AccountCreateModal';
|
||||
|
||||
@@ -70,7 +70,6 @@ export default function AccountManagementList() {
|
||||
const [actionBusy, setActionBusy] = useState('');
|
||||
const [loginTarget, setLoginTarget] = useState<Row | null>(null);
|
||||
const { message: messageApi } = App.useApp();
|
||||
const { vertical } = useOverflowGrid(rows.length);
|
||||
|
||||
const load = useCallback(async () => {
|
||||
setPending(true);
|
||||
@@ -336,7 +335,7 @@ export default function AccountManagementList() {
|
||||
loading={pending}
|
||||
sticky
|
||||
pagination={tablePagination()}
|
||||
scroll={{ x: 'max-content', y: vertical ? 'calc(100vh - 300px)' : undefined }}
|
||||
scroll={{ x: 'max-content' }}
|
||||
locale={{ emptyText: '暂无账号或待登录环境。' }}
|
||||
/>
|
||||
<Modal
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
// 监控账号列表:表格呈现账号画像、作品数据与同步状态。
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { history } from '@umijs/max';
|
||||
import { Alert, App, Avatar, Button, Card, Flex, Form, Modal, Popconfirm, Select, Space, Table, Tag, Tooltip, Typography } from 'antd';
|
||||
import { Alert, App, Avatar, Button, Card, Flex, Form, Grid, Modal, Popconfirm, Select, Space, Table, Tag, Tooltip, Typography } from 'antd';
|
||||
import type { ColumnsType } from 'antd/es/table';
|
||||
import { CloudUploadOutlined, ReloadOutlined } from '@ant-design/icons';
|
||||
import { getList, remove, creatorAction, creatorUpdate } from '@/services/api';
|
||||
import { conflictMessage, dateTime } from '@/utils/helpers';
|
||||
import { fixedLeft, fixedRight, tablePagination, tableScroll, useOverflowGrid } from '@/utils/table';
|
||||
import { fixedLeft, fixedRight, tablePagination } from '@/utils/table';
|
||||
|
||||
interface CompetitorRow {
|
||||
id: string;
|
||||
@@ -45,7 +45,7 @@ export default function MonitoringAccountList() {
|
||||
const [tagBusy, setTagBusy] = useState(false);
|
||||
const [actionBusy, setActionBusy] = useState('');
|
||||
const { message: messageApi } = App.useApp();
|
||||
const { vertical, horizontal } = useOverflowGrid(rows.length);
|
||||
const horizontal = !Grid.useBreakpoint().xl;
|
||||
|
||||
const load = useCallback(async () => {
|
||||
setPending(true);
|
||||
@@ -230,7 +230,7 @@ export default function MonitoringAccountList() {
|
||||
sticky
|
||||
pagination={tablePagination()}
|
||||
locale={{ emptyText: '暂无监控账号。' }}
|
||||
scroll={tableScroll(horizontal ? 1100 : undefined, vertical ? 'calc(100vh - 300px)' : undefined)}
|
||||
scroll={{ x: horizontal ? 1100 : undefined }}
|
||||
/>
|
||||
<Modal
|
||||
open={Boolean(tagTarget)}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
// 账号导入:语义对齐 web.archived AccountImportPage(分享链接解析任务列表 + 新建导入任务 Modal)。
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { Alert, App, Avatar, Button, Card, Flex, Form, Input, Modal, Select, Space, Table, Tag, Tooltip, Typography } from 'antd';
|
||||
import { Alert, App, Avatar, Button, Card, Flex, Form, Grid, Input, Modal, Select, Space, Table, Tag, Tooltip, Typography } from 'antd';
|
||||
import { PlusOutlined, ReloadOutlined } from '@ant-design/icons';
|
||||
import type { ColumnsType } from 'antd/es/table';
|
||||
import { create, getList, creatorAction } from '@/services/api';
|
||||
import { conflictMessage, dateTime, extractShareURL, platformForShareURL, platformLabel, shareJobStatus } from '@/utils/helpers';
|
||||
import { fixedLeft, fixedRight, tablePagination, tableScroll, useOverflowGrid } from '@/utils/table';
|
||||
import { fixedLeft, fixedRight, tablePagination } from '@/utils/table';
|
||||
|
||||
interface Job {
|
||||
id: string;
|
||||
@@ -34,7 +34,7 @@ export default function Page() {
|
||||
const [busy, setBusy] = useState(false);
|
||||
const [retryID, setRetryID] = useState<string | null>(null);
|
||||
const { message: messageApi } = App.useApp();
|
||||
const { vertical, horizontal } = useOverflowGrid(jobs.length);
|
||||
const horizontal = !Grid.useBreakpoint().xl;
|
||||
|
||||
const loadShareJobs = useCallback(async () => {
|
||||
setPending(true);
|
||||
@@ -188,7 +188,7 @@ export default function Page() {
|
||||
{error ? (
|
||||
<Alert type="error" showIcon style={{ marginBottom: 16 }} title={error.message} action={<Button size="small" onClick={loadShareJobs}>重试</Button>} />
|
||||
) : null}
|
||||
<Table rowKey="id" columns={columns} dataSource={jobs} loading={pending} sticky pagination={tablePagination()} scroll={tableScroll(horizontal ? 1000 : undefined, vertical ? 'calc(100vh - 300px)' : undefined)} locale={{ emptyText: '暂无分享链接解析任务。' }} />
|
||||
<Table rowKey="id" columns={columns} dataSource={jobs} loading={pending} sticky pagination={tablePagination()} scroll={{ x: horizontal ? 1000 : undefined }} locale={{ emptyText: '暂无分享链接解析任务。' }} />
|
||||
<Modal open={createOpen} title="创建账号导入任务" onCancel={closeCreate} onOk={createJob} confirmLoading={busy} okText={busy ? '加入中…' : '加入解析队列'} width={560}>
|
||||
<Form form={form} layout="vertical">
|
||||
<Form.Item name="shareText" label="分享内容或链接" required extra="可直接粘贴平台分享文案,系统会自动提取其中的链接并识别作者。">
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
// 网关管理:语义对齐 web.archived GatewaysPage.jsx(注册/编辑 Modal、令牌显隐复制、删除)。
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { Alert, App, Button, Card, Flex, Form, Input, Modal, Popconfirm, Space, Table, Tag, Tooltip, Typography } from 'antd';
|
||||
import { Alert, App, Button, Card, Flex, Form, Grid, Input, Modal, Popconfirm, Space, Table, Tag, Tooltip, Typography } from 'antd';
|
||||
import { CopyOutlined, EyeInvisibleOutlined, EyeOutlined, PlusOutlined } from '@ant-design/icons';
|
||||
import type { ColumnsType } from 'antd/es/table';
|
||||
import { create, getList, remove, update } from '@/services/api';
|
||||
import { conflictMessage, dateTime } from '@/utils/helpers';
|
||||
import { fixedLeft, fixedRight, tablePagination, tableScroll, useOverflowGrid } from '@/utils/table';
|
||||
import { fixedLeft, fixedRight, tablePagination } from '@/utils/table';
|
||||
|
||||
const namePattern = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
|
||||
const tokenPattern = /^[A-Za-z0-9][A-Za-z0-9._-]{15,127}$/;
|
||||
@@ -95,7 +95,7 @@ export default function Page() {
|
||||
const [busy, setBusy] = useState('');
|
||||
const [created, setCreated] = useState<any>(null);
|
||||
const { message: messageApi } = App.useApp();
|
||||
const { vertical, horizontal } = useOverflowGrid(gateways.length);
|
||||
const horizontal = !Grid.useBreakpoint().xl;
|
||||
const healthReloadTimer = useRef<ReturnType<typeof setTimeout>>(undefined);
|
||||
|
||||
const load = useCallback(async () => {
|
||||
@@ -234,7 +234,7 @@ export default function Page() {
|
||||
{error ? (
|
||||
<Alert type="error" showIcon style={{ marginBottom: 16 }} title={error.message} action={<Button size="small" onClick={load}>重试</Button>} />
|
||||
) : null}
|
||||
<Table rowKey="name" columns={columns} dataSource={gateways} loading={pending} sticky pagination={tablePagination()} scroll={tableScroll(horizontal ? 960 : undefined, vertical ? 'calc(100vh - 300px)' : undefined)} locale={{ emptyText: '暂无网关;注册后环境即可调度到该网关。' }} />
|
||||
<Table rowKey="name" columns={columns} dataSource={gateways} loading={pending} sticky pagination={tablePagination()} scroll={{ x: horizontal ? 960 : undefined }} locale={{ emptyText: '暂无网关;注册后环境即可调度到该网关。' }} />
|
||||
<GatewayFormModal
|
||||
open={createOpen}
|
||||
initial={null}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
// 网络出口:语义对齐 web.archived NetworkExitsPage.jsx(列表 + 创建/编辑 Modal + 检测/启停/删除动作 + 出口详情页)。
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { history } from '@umijs/max';
|
||||
import { Alert, App, Button, Card, Flex, Form, Input, InputNumber, Modal, Popconfirm, Select, Space, Table, Tag, Typography } from 'antd';
|
||||
import { Alert, App, Button, Card, Flex, Form, Grid, Input, InputNumber, Modal, Popconfirm, Select, Space, Table, Tag, Typography } from 'antd';
|
||||
import { PlusOutlined } from '@ant-design/icons';
|
||||
import type { ColumnsType } from 'antd/es/table';
|
||||
import { create, getOne, getList, networkExitAction, remove, update } from '@/services/api';
|
||||
import { conflictMessage, dateTime } from '@/utils/helpers';
|
||||
import { fixedLeft, fixedRight, tablePagination, tableScroll, useOverflowGrid } from '@/utils/table';
|
||||
import { fixedLeft, fixedRight, tablePagination } from '@/utils/table';
|
||||
|
||||
const healthText: Record<string, string> = {
|
||||
unchecked: '未检测',
|
||||
@@ -113,7 +113,7 @@ export default function Page() {
|
||||
const [editing, setEditing] = useState<any | null>(null);
|
||||
const [busy, setBusy] = useState('');
|
||||
const { message: messageApi } = App.useApp();
|
||||
const { vertical, horizontal } = useOverflowGrid(exits.length);
|
||||
const horizontal = !Grid.useBreakpoint().xl;
|
||||
|
||||
const load = useCallback(async () => {
|
||||
setPending(true);
|
||||
@@ -306,7 +306,7 @@ export default function Page() {
|
||||
loading={pending}
|
||||
sticky
|
||||
pagination={tablePagination()}
|
||||
scroll={tableScroll(horizontal ? 1100 : undefined, vertical ? 'calc(100vh - 300px)' : undefined)}
|
||||
scroll={{ x: horizontal ? 1100 : undefined }}
|
||||
locale={{ emptyText: '暂无网络出口。创建并检测健康后,才能绑定运行环境。' }}
|
||||
/>
|
||||
<ExitFormModal
|
||||
|
||||
+2
-24
@@ -1,31 +1,9 @@
|
||||
// 列表页表格的统一形态:固定表头(表内滚动)+ 固定首列/操作列 + 横向滚动 + 分页。
|
||||
// 仅用 antd/rc-table 原生能力,不自定义滚动组件:
|
||||
// - scroll.y(表内滚动,固定表头)+ sticky(页面余量滚动时表头吸顶兜底);
|
||||
// antd 源码在 fixHeader 时固定 overflowY: 'scroll'(滚动条常驻,官方未提供按需开关),
|
||||
// 因此仅在「数据行超过一屏」时才开启 scroll.y,用 overflowGrid 判断:
|
||||
// 纵向 ≤ md(阈值 768,Grid.useBreakpoint 官方响应式 hook)→ 小屏数据必超一屏 → scroll.y + 首列固定;
|
||||
// 横向 ≥ xl(阈值 1280,布局含侧栏后仍够宽)→ 无挤压,不加 scroll.x/fixed 列/scroll.y;
|
||||
// 其余中等宽度 → scroll.x + fixed 首列/操作列,不设 scroll.y(无固定表头时滚动条自然按需出现)。
|
||||
// - scroll.x + 固定首列(fixed: 'left')与操作列(fixed: 'right')防挤压折叠。
|
||||
// - pageSize 20 + hideOnSinglePage:数据多时翻页,单页时隐藏分页条保持原视觉。
|
||||
import { Grid } from 'antd';
|
||||
// 列表表格使用页面纵向滚动与 sticky 表头吸顶,不设置表内纵向滚动。
|
||||
// 保留横向滚动、固定首列/操作列与分页(每页 20 条,单页隐藏分页条)。
|
||||
import type { ColumnsType, ColumnType } from 'antd/es/table';
|
||||
|
||||
export const TABLE_PAGE_SIZE = 20;
|
||||
|
||||
// antd Table 内容超出视口高度时,浏览器才需要纵向滚动;
|
||||
// 这里用「数据行数 × 行高」与视口比较,决定是否需要表内滚动(固定表头)。
|
||||
export function useOverflowGrid(rowCount: number) {
|
||||
const screens = Grid.useBreakpoint();
|
||||
const vertical = rowCount * 48 + 120 >= window.innerHeight - 300 || !screens.md;
|
||||
const horizontal = !screens.xl;
|
||||
return { vertical, horizontal };
|
||||
}
|
||||
|
||||
export function tableScroll(x: number | undefined, y: string | undefined) {
|
||||
return { x, y };
|
||||
}
|
||||
|
||||
export function tablePagination() {
|
||||
return { pageSize: TABLE_PAGE_SIZE, hideOnSinglePage: true };
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ const ts = require('typescript');
|
||||
const requireWeb = createRequire(resolve(__dirname, '../package.json'));
|
||||
const file = resolve(__dirname, '../src/components/accounts/AccountManagementList.tsx');
|
||||
|
||||
function setup({ accounts = [{ id: 'account-1', name: '真实昵称', business_status: 'normal', tags: ['主账号'] }], environments = [{ alias: 'env-1', gateway: 'gw-a' }], loadError, actionError, grid = { vertical: true, horizontal: true } } = {}) {
|
||||
function setup({ accounts = [{ id: 'account-1', name: '真实昵称', business_status: 'normal', tags: ['主账号'] }], environments = [{ alias: 'env-1', gateway: 'gw-a' }], loadError, actionError } = {}) {
|
||||
const states = [], calls = [], messages = [], paths = [];
|
||||
let cursor = 0, started = false;
|
||||
const marker = displayName => Object.assign(() => null, { displayName });
|
||||
@@ -34,7 +34,7 @@ function setup({ accounts = [{ id: 'account-1', name: '真实昵称', business_s
|
||||
async remove(resource, id) { calls.push({ resource, id }); if (options.actionError) throw options.actionError; },
|
||||
};
|
||||
if (id === '@/utils/helpers') return { accountReadiness: () => ({ ready: true, label: '可运行' }), dateTime: value => value, conflictMessage: (error, fallback) => error.message || fallback };
|
||||
if (id === '@/utils/table') return { fixedLeft: column => ({ ...column, fixed: 'left' }), fixedRight: column => ({ ...column, fixed: 'right' }), tablePagination: () => ({}), tableScroll: (x, y) => ({ x, y }), useOverflowGrid: () => grid };
|
||||
if (id === '@/utils/table') return { fixedLeft: column => ({ ...column, fixed: 'left' }), fixedRight: column => ({ ...column, fixed: 'right' }), tablePagination: () => ({ pageSize: 20, hideOnSinglePage: true }) };
|
||||
if (id.startsWith('@/components/accounts/')) return { default: marker(id.split('/').at(-1)) };
|
||||
return requireWeb(id);
|
||||
};
|
||||
@@ -67,24 +67,25 @@ test('待登录环境与已登录账号共用唯一列表、计数及分页', as
|
||||
assert.notEqual(rows[0].id, rows[1].id);
|
||||
});
|
||||
|
||||
for (const horizontal of [false, true]) {
|
||||
for (const vertical of [false, true]) {
|
||||
test(`账号与操作列不挤压,其他列横向滚动(横向溢出 ${horizontal},纵向溢出 ${vertical})`, async () => {
|
||||
const s = await ready({ grid: { horizontal, vertical } });
|
||||
const { columns, scroll, dataSource } = s.find('Table').props;
|
||||
assert.equal(columns[0].title, '账号');
|
||||
assert.equal(columns[0].fixed, 'left');
|
||||
assert.equal(columns[0].width, 240);
|
||||
assert.equal(columns.at(-1).title, '操作');
|
||||
assert.equal(columns.at(-1).fixed, 'right');
|
||||
assert.equal(columns.at(-1).width, 300);
|
||||
assert.ok(columns.slice(1, -1).every(column => !column.fixed));
|
||||
assert.equal(scroll.x, 'max-content', '宽屏也应按内容宽度滚动,而不是挤压两侧列');
|
||||
assert.equal(scroll.y, vertical ? 'calc(100vh - 300px)' : undefined);
|
||||
const row = dataSource.find(row => !row.pending_environment);
|
||||
assert.notEqual(s.find('Space', s.cell('操作', row)).props.wrap, true, '操作按钮不得换行折叠');
|
||||
});
|
||||
}
|
||||
for (const rowCount of [1, 20, 100]) {
|
||||
test(`账号与操作列不挤压,${rowCount} 条数据使用页面纵向滚动`, async () => {
|
||||
const s = await ready({ accounts: Array.from({ length: rowCount }, (_, i) => ({ id: `account-${i}`, name: `账号 ${i}` })), environments: [] });
|
||||
const { columns, scroll, dataSource, sticky, pagination } = s.find('Table').props;
|
||||
assert.equal(dataSource.length, rowCount);
|
||||
assert.equal(sticky, true);
|
||||
assert.deepEqual(pagination, { pageSize: 20, hideOnSinglePage: true });
|
||||
assert.equal(columns[0].title, '账号');
|
||||
assert.equal(columns[0].fixed, 'left');
|
||||
assert.equal(columns[0].width, 240);
|
||||
assert.equal(columns.at(-1).title, '操作');
|
||||
assert.equal(columns.at(-1).fixed, 'right');
|
||||
assert.equal(columns.at(-1).width, 300);
|
||||
assert.ok(columns.slice(1, -1).every(column => !column.fixed));
|
||||
assert.equal(scroll.x, 'max-content', '宽屏也应按内容宽度滚动,而不是挤压两侧列');
|
||||
assert.equal(Object.hasOwn(scroll, 'y'), false, '不应启用表格内部纵向滚动');
|
||||
const row = dataSource.find(row => !row.pending_environment);
|
||||
assert.notEqual(s.find('Space', s.cell('操作', row)).props.wrap, true, '操作按钮不得换行折叠');
|
||||
});
|
||||
}
|
||||
|
||||
test('按共用环境数据库ID倒序排列,新建环境与账号在前,登录绑定不改变位置', async () => {
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
const assert = require('node:assert/strict');
|
||||
const { readFileSync } = require('node:fs');
|
||||
const { test } = require('node:test');
|
||||
const vm = require('node:vm');
|
||||
const ts = require('typescript');
|
||||
|
||||
// 表格统一形态:固定表头(scroll.y)+ sticky 兜底 + 横向滚动 + 操作列固定右侧 + 分页。
|
||||
// 页面纵向滚动 + sticky 表头吸顶 + 横向滚动 + 固定列 + 分页。
|
||||
const files = [
|
||||
'src/components/accounts/MonitoringAccountList.tsx',
|
||||
'src/components/accounts/AccountManagementList.tsx',
|
||||
'src/pages/accounts/import.tsx',
|
||||
'src/pages/network-exits/index.tsx',
|
||||
'src/pages/gateways/index.tsx',
|
||||
['src/components/accounts/MonitoringAccountList.tsx', 1100],
|
||||
['src/components/accounts/AccountManagementList.tsx', 'max-content'],
|
||||
['src/pages/accounts/import.tsx', 1000],
|
||||
['src/pages/network-exits/index.tsx', 1100],
|
||||
['src/pages/gateways/index.tsx', 960],
|
||||
];
|
||||
|
||||
for (const file of files) {
|
||||
for (const [file, width] of files) {
|
||||
const source = ts.createSourceFile(
|
||||
file,
|
||||
readFileSync(`${__dirname}/../${file}`, 'utf8'),
|
||||
@@ -21,13 +22,74 @@ for (const file of files) {
|
||||
ts.ScriptKind.TSX,
|
||||
);
|
||||
const code = source.getFullText();
|
||||
const tables = [];
|
||||
function visit(node) {
|
||||
if ((ts.isJsxOpeningElement(node) || ts.isJsxSelfClosingElement(node)) && node.tagName.getText(source) === 'Table') tables.push(node);
|
||||
ts.forEachChild(node, visit);
|
||||
}
|
||||
visit(source);
|
||||
|
||||
test(`${file} 表格使用统一固定表头与分页形态`, () => {
|
||||
assert.match(code, /sticky/, '应开启表头吸顶兜底');
|
||||
assert.match(code, /pagination=\{tablePagination\(\)\}/, '应恢复分页(每页 20,单页隐藏)');
|
||||
assert.doesNotMatch(code, /pagination=\{false\}/, '不应再保留 pagination={false}');
|
||||
assert.match(code, /\.\.\.fixedLeft</, '首列应固定在左侧');
|
||||
assert.match(code, /\.\.\.fixedRight</, '操作列应固定在右侧');
|
||||
assert.match(code, /useOverflowGrid\(/, '应按数据量按需开启表内滚动/横向滚动');
|
||||
test(`${file} 保留表头吸顶、分页和固定列`, () => {
|
||||
assert.equal(tables.length, 1);
|
||||
const props = tables[0].attributes.properties;
|
||||
assert.ok(props.some(prop => prop.name?.getText(source) === 'sticky'));
|
||||
assert.match(code, /pagination=\{tablePagination\(\)\}/);
|
||||
assert.doesNotMatch(code, /pagination=\{false\}/);
|
||||
assert.match(code, /\.\.\.fixedLeft</);
|
||||
assert.match(code, /\.\.\.fixedRight</);
|
||||
});
|
||||
|
||||
test(`${file} 数据多或小屏时仍使用页面纵向滚动,横向滚动不变`, () => {
|
||||
const scroll = tables[0].attributes.properties.find(prop => prop.name?.getText(source) === 'scroll');
|
||||
assert.ok(scroll?.initializer && ts.isJsxExpression(scroll.initializer));
|
||||
const expression = scroll.initializer.expression.getText(source);
|
||||
for (const horizontal of [false, true]) {
|
||||
for (const height of [480, 1080]) {
|
||||
for (const rowCount of [0, 1, 20, 100]) {
|
||||
const result = vm.runInNewContext(`(${expression})`, {
|
||||
horizontal,
|
||||
vertical: rowCount * 48 + 120 >= height - 300 || horizontal,
|
||||
tableScroll: (x, y) => ({ x, y }),
|
||||
});
|
||||
assert.equal(Object.hasOwn(result, 'y'), false, `不应配置 scroll.y(行数 ${rowCount},高度 ${height})`);
|
||||
assert.equal(result.x, width === 'max-content' ? width : horizontal ? width : undefined);
|
||||
}
|
||||
}
|
||||
}
|
||||
assert.doesNotMatch(code, /window\.innerHeight|useOverflowGrid|tableScroll/, '不再保留按高度和行数启用表内滚动的旧路径');
|
||||
if (width !== 'max-content') assert.match(code, /!Grid\.useBreakpoint\(\)\.xl/, '横向断点保持 xl');
|
||||
});
|
||||
}
|
||||
|
||||
const tableFile = `${__dirname}/../src/utils/table.ts`;
|
||||
const tableCode = ts.transpileModule(readFileSync(tableFile, 'utf8'), {
|
||||
fileName: tableFile,
|
||||
compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2022 },
|
||||
}).outputText;
|
||||
const tableModule = { exports: {} };
|
||||
vm.runInNewContext(tableCode, { exports: tableModule.exports }, { filename: tableFile });
|
||||
const helpers = tableModule.exports;
|
||||
|
||||
test('分页仍为每页 20 条,单页隐藏分页条', () => {
|
||||
assert.equal(helpers.TABLE_PAGE_SIZE, 20);
|
||||
const pagination = helpers.tablePagination();
|
||||
assert.equal(pagination.pageSize, 20);
|
||||
assert.equal(pagination.hideOnSinglePage, true);
|
||||
});
|
||||
|
||||
test('固定列保留原配置且不修改输入', () => {
|
||||
const column = { title: '账号', width: 240 };
|
||||
for (const [helper, side] of [[helpers.fixedLeft, 'left'], [helpers.fixedRight, 'right']]) {
|
||||
const fixed = helper(column);
|
||||
assert.equal(fixed.fixed, side);
|
||||
assert.equal(fixed.title, column.title);
|
||||
assert.equal(fixed.width, column.width);
|
||||
assert.notEqual(fixed, column);
|
||||
assert.equal(Object.hasOwn(column, 'fixed'), false);
|
||||
}
|
||||
});
|
||||
|
||||
test('移除纵向滚动判断与无必要的滚动包装函数', () => {
|
||||
assert.equal(helpers.useOverflowGrid, undefined);
|
||||
assert.equal(helpers.tableScroll, undefined);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user