style(frontend): 全项目表格统一百分比布局并居中
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
import { Table as AntTable } from 'antd'
|
||||
import type { TableProps } from 'antd'
|
||||
|
||||
import { normalizePercentColumns } from '@/utils/percent-table-layout'
|
||||
|
||||
/**
|
||||
* 全项目统一表格:列宽转百分比、表头与内容居中。
|
||||
*
|
||||
* 业务表格仍按原列宽数值表达相对比例,由这里统一归一化为 100%。
|
||||
* rowSelection / expandable 会额外占用 AntD 内置列,因此预留少量百分比。
|
||||
*/
|
||||
export default function PercentTable<RecordType extends object = Record<string, unknown>>(
|
||||
props: TableProps<RecordType>,
|
||||
) {
|
||||
const { columns, scroll, tableLayout: _tableLayout, ...rest } = props
|
||||
const reservedPercent =
|
||||
(props.rowSelection ? 4 : 0) +
|
||||
(props.expandable && typeof props.expandable === 'object' ? 4 : 0)
|
||||
const normalizedColumns = columns
|
||||
? normalizePercentColumns(columns, { reservedPercent })
|
||||
: columns
|
||||
const scrollConfig = typeof scroll === 'object' && scroll ? scroll : {}
|
||||
|
||||
return (
|
||||
<AntTable<RecordType>
|
||||
{...rest}
|
||||
columns={normalizedColumns}
|
||||
tableLayout="fixed"
|
||||
scroll={{ ...scrollConfig, x: '100%' }}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { ReloadOutlined, SearchOutlined } from '@ant-design/icons'
|
||||
import { Alert, Button, Card, Empty, Form, Input, Select, Space, Table, Typography } from 'antd'
|
||||
import { Alert, Button, Card, Empty, Form, Input, Select, Space, Typography } from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import type { TableColumnsType } from 'antd'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { useMemo } from 'react'
|
||||
@@ -203,7 +204,7 @@ export default function AdminAuditLogsPage() {
|
||||
) : null}
|
||||
|
||||
<Card>
|
||||
<Table<AdminAuditLogItem>
|
||||
<PercentTable<AdminAuditLogItem>
|
||||
rowKey="logId"
|
||||
loading={query.isLoading || query.isFetching}
|
||||
columns={columns}
|
||||
|
||||
@@ -10,10 +10,10 @@ import {
|
||||
Skeleton,
|
||||
Space,
|
||||
Statistic,
|
||||
Table,
|
||||
Tag,
|
||||
Typography,
|
||||
} from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import type { TableColumnsType } from 'antd'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { useMemo, useState } from 'react'
|
||||
@@ -226,7 +226,7 @@ export default function AdminDashboardPage() {
|
||||
/>
|
||||
) : null}
|
||||
|
||||
<Table<AdminLoginLogItem>
|
||||
<PercentTable<AdminLoginLogItem>
|
||||
rowKey="logId"
|
||||
loading={loginQuery.isLoading || loginQuery.isFetching}
|
||||
columns={columns}
|
||||
|
||||
@@ -16,10 +16,10 @@ import {
|
||||
Popconfirm,
|
||||
Select,
|
||||
Space,
|
||||
Table,
|
||||
Tag,
|
||||
Typography,
|
||||
} from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import type { TableColumnsType } from 'antd'
|
||||
import { useEffect, useMemo, useRef, useState } from 'react'
|
||||
|
||||
@@ -377,7 +377,7 @@ export default function AdminDouyinMashidaCertificatePage() {
|
||||
|
||||
<div className="kuaishou-industry-split">
|
||||
<Card title="本地券码" className="kuaishou-industry-voucher-card">
|
||||
<Table
|
||||
<PercentTable
|
||||
rowKey="id"
|
||||
size="middle"
|
||||
tableLayout="fixed"
|
||||
|
||||
@@ -10,10 +10,10 @@ import {
|
||||
Select,
|
||||
Space,
|
||||
Statistic,
|
||||
Table,
|
||||
Tag,
|
||||
Typography,
|
||||
} from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import type { TableColumnsType } from 'antd'
|
||||
import { useState } from 'react'
|
||||
|
||||
@@ -224,7 +224,7 @@ export default function AdminFinancePage() {
|
||||
</Button>
|
||||
}
|
||||
>
|
||||
<Table<AdminFinanceDailyItem>
|
||||
<PercentTable<AdminFinanceDailyItem>
|
||||
rowKey="date"
|
||||
loading={summaryQuery.isLoading}
|
||||
dataSource={daily}
|
||||
@@ -252,7 +252,7 @@ export default function AdminFinancePage() {
|
||||
</Space>
|
||||
}
|
||||
>
|
||||
<Table<AdminFinanceChannelDailyItem>
|
||||
<PercentTable<AdminFinanceChannelDailyItem>
|
||||
rowKey={(row) => `${row.date}-${row.channel}-${row.category}`}
|
||||
loading={summaryQuery.isLoading}
|
||||
dataSource={channelDaily}
|
||||
@@ -304,7 +304,7 @@ export default function AdminFinancePage() {
|
||||
</Space>
|
||||
}
|
||||
>
|
||||
<Table<AdminFinanceTransaction>
|
||||
<PercentTable<AdminFinanceTransaction>
|
||||
rowKey={(row) => `${row.category}-${row.sourceId}-${row.occurredAt}`}
|
||||
loading={transactionsQuery.isLoading}
|
||||
dataSource={transactionData?.items || []}
|
||||
|
||||
@@ -18,11 +18,11 @@ import {
|
||||
Popconfirm,
|
||||
Select,
|
||||
Space,
|
||||
Table,
|
||||
Tabs,
|
||||
Tag,
|
||||
Typography,
|
||||
} from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import type { TableColumnsType, TabsProps } from 'antd'
|
||||
import { useEffect, useMemo, useRef, useState } from 'react'
|
||||
|
||||
@@ -963,7 +963,7 @@ export default function AdminKuaishouIndustryPage() {
|
||||
|
||||
function renderVoucherTable(scrollX?: number) {
|
||||
return (
|
||||
<Table
|
||||
<PercentTable
|
||||
rowKey="id"
|
||||
size="middle"
|
||||
tableLayout="fixed"
|
||||
@@ -1297,7 +1297,7 @@ export default function AdminKuaishouIndustryPage() {
|
||||
查询售后
|
||||
</Button>
|
||||
</Space>
|
||||
<Table
|
||||
<PercentTable
|
||||
rowKey={(row) => String(row.refundId || row.oid || JSON.stringify(row))}
|
||||
columns={refundColumns}
|
||||
dataSource={refundRows}
|
||||
|
||||
@@ -20,10 +20,10 @@ import {
|
||||
Modal,
|
||||
Space,
|
||||
Statistic,
|
||||
Table,
|
||||
Tag,
|
||||
Typography,
|
||||
} from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import type { TableColumnsType } from 'antd'
|
||||
import { useState } from 'react'
|
||||
|
||||
@@ -245,7 +245,7 @@ export default function AdminManualFulfillmentPage() {
|
||||
</Space>
|
||||
|
||||
<Card bordered={false}>
|
||||
<Table
|
||||
<PercentTable
|
||||
rowKey="orderItemId"
|
||||
size="small"
|
||||
columns={columns}
|
||||
|
||||
@@ -16,10 +16,10 @@ import {
|
||||
Modal,
|
||||
Skeleton,
|
||||
Space,
|
||||
Table,
|
||||
Tag,
|
||||
Typography,
|
||||
} from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import type { TableColumnsType } from 'antd'
|
||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
|
||||
import { useEffect, useState } from 'react'
|
||||
@@ -318,7 +318,7 @@ export default function AdminOrderDetailPage() {
|
||||
</Card>
|
||||
|
||||
<Card title="商品明细">
|
||||
<Table<AdminOrderDetail['items'][number]>
|
||||
<PercentTable<AdminOrderDetail['items'][number]>
|
||||
rowKey="orderItemId"
|
||||
pagination={false}
|
||||
dataSource={detail.items}
|
||||
@@ -354,7 +354,7 @@ export default function AdminOrderDetailPage() {
|
||||
</Card>
|
||||
|
||||
<Card title="任务">
|
||||
<Table<AdminTaskListItem>
|
||||
<PercentTable<AdminTaskListItem>
|
||||
rowKey="taskId"
|
||||
pagination={false}
|
||||
dataSource={detail.tasks}
|
||||
|
||||
@@ -16,11 +16,11 @@ import {
|
||||
Segmented,
|
||||
Select,
|
||||
Space,
|
||||
Table,
|
||||
Tag,
|
||||
Tooltip,
|
||||
Typography,
|
||||
} from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import type { TableColumnsType } from 'antd'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { useEffect, useMemo } from 'react'
|
||||
@@ -503,7 +503,7 @@ export default function AdminOrdersPage() {
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<Table<AdminOrderListItem>
|
||||
<PercentTable<AdminOrderListItem>
|
||||
rowKey="orderId"
|
||||
loading={query.isLoading || query.isFetching}
|
||||
columns={columns}
|
||||
|
||||
@@ -11,11 +11,11 @@ import {
|
||||
Select,
|
||||
Space,
|
||||
Statistic,
|
||||
Table,
|
||||
Tabs,
|
||||
Tag,
|
||||
Typography,
|
||||
} from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import type { TableColumnsType } from 'antd'
|
||||
import { useState } from 'react'
|
||||
|
||||
@@ -386,7 +386,7 @@ export default function AdminSalesProfitPage() {
|
||||
key: 'daily',
|
||||
label: '日报',
|
||||
children: (
|
||||
<Table
|
||||
<PercentTable
|
||||
rowKey="statDate"
|
||||
size="small"
|
||||
columns={dailyColumns}
|
||||
@@ -401,7 +401,7 @@ export default function AdminSalesProfitPage() {
|
||||
key: 'product',
|
||||
label: '商品',
|
||||
children: (
|
||||
<Table
|
||||
<PercentTable
|
||||
rowKey={(row) => `${row.canonicalProductId || 'unmapped'}`}
|
||||
size="small"
|
||||
columns={productColumns}
|
||||
@@ -416,7 +416,7 @@ export default function AdminSalesProfitPage() {
|
||||
key: 'fulfillment-mode',
|
||||
label: '履约方式',
|
||||
children: (
|
||||
<Table
|
||||
<PercentTable
|
||||
rowKey="fulfillmentMode"
|
||||
size="small"
|
||||
columns={fulfillmentModeColumns}
|
||||
@@ -431,7 +431,7 @@ export default function AdminSalesProfitPage() {
|
||||
key: 'facts',
|
||||
label: '事实明细',
|
||||
children: (
|
||||
<Table
|
||||
<PercentTable
|
||||
rowKey="id"
|
||||
size="small"
|
||||
columns={factColumns}
|
||||
|
||||
@@ -28,12 +28,12 @@ import {
|
||||
Skeleton,
|
||||
Space,
|
||||
Spin,
|
||||
Table,
|
||||
Tabs,
|
||||
Tag,
|
||||
Tooltip,
|
||||
Typography,
|
||||
} from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import type { TableColumnsType } from 'antd'
|
||||
import { useMutation, useQuery } from '@tanstack/react-query'
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
@@ -898,7 +898,7 @@ export default function AdminTaskDetailPage() {
|
||||
key: 'events',
|
||||
label: `事件流水 (${resolvedDetail.events.length})`,
|
||||
children: (
|
||||
<Table<TaskEvent>
|
||||
<PercentTable<TaskEvent>
|
||||
rowKey="eventId"
|
||||
pagination={false}
|
||||
columns={eventColumns}
|
||||
@@ -1757,7 +1757,7 @@ function KuaishouIndustryVoucherPanel({ voucher }: { voucher: KuaishouIndustryVo
|
||||
) : null}
|
||||
|
||||
{consumeDetails.length > 0 ? (
|
||||
<Table<Record<string, unknown>>
|
||||
<PercentTable<Record<string, unknown>>
|
||||
className="platform-section-gap"
|
||||
rowKey={(_, index) => String(index ?? 0)}
|
||||
pagination={false}
|
||||
@@ -1905,7 +1905,7 @@ function KuaishouCloudPanel({
|
||||
|
||||
{flow.rebind.history.length > 0 ? (
|
||||
<Card title="换绑记录">
|
||||
<Table
|
||||
<PercentTable
|
||||
rowKey={(row) => `${row.attempt}-${row.requestedAt || ''}`}
|
||||
pagination={false}
|
||||
dataSource={flow.rebind.history}
|
||||
@@ -1969,7 +1969,7 @@ function RedeemResolutionPanel({
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
|
||||
<Table
|
||||
<PercentTable
|
||||
className="platform-section-gap"
|
||||
rowKey={(row) => `${row.attempt}-${row.codeMasked}`}
|
||||
pagination={false}
|
||||
|
||||
@@ -19,11 +19,11 @@ import {
|
||||
Select,
|
||||
Space,
|
||||
Spin,
|
||||
Table,
|
||||
Tag,
|
||||
Tooltip,
|
||||
Typography,
|
||||
} from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import type { TableColumnsType } from 'antd'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
@@ -576,7 +576,7 @@ export default function AdminTasksPage() {
|
||||
) : null}
|
||||
|
||||
<Card>
|
||||
<Table<AdminTaskListItem>
|
||||
<PercentTable<AdminTaskListItem>
|
||||
rowKey="taskId"
|
||||
loading={query.isLoading || query.isFetching}
|
||||
columns={columns}
|
||||
|
||||
@@ -12,10 +12,10 @@ import {
|
||||
Select,
|
||||
Space,
|
||||
Switch,
|
||||
Table,
|
||||
Tag,
|
||||
Typography,
|
||||
} from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import type { MenuProps, TableColumnsType } from 'antd'
|
||||
import { useQuery, useQueryClient } from '@tanstack/react-query'
|
||||
import { useMemo, useState } from 'react'
|
||||
@@ -675,7 +675,7 @@ export default function AdminUsersPage() {
|
||||
</Typography.Text>
|
||||
}
|
||||
>
|
||||
<Table<AdminUserListItem>
|
||||
<PercentTable<AdminUserListItem>
|
||||
rowKey="userId"
|
||||
loading={query.isLoading || query.isFetching}
|
||||
columns={columns}
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
* 不写渠道映射,也不维护游戏分类。
|
||||
*/
|
||||
import { ReloadOutlined, SyncOutlined } from '@ant-design/icons'
|
||||
import { Alert, App, Button, Card, Space, Switch, Table, Tag, Typography } from 'antd'
|
||||
import { Alert, App, Button, Card, Space, Switch, Tag, Typography } from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import { useQuery, useQueryClient } from '@tanstack/react-query'
|
||||
import { useState } from 'react'
|
||||
|
||||
@@ -134,7 +135,7 @@ export function AffiliateSkuPanel() {
|
||||
style={{ marginBottom: 12 }}
|
||||
message="自动发货只按上游货源 SKU 配采购成本:订单项直接按 aff:<skuCode> 归一,不走渠道映射;这里不维护游戏分类和商品上下架,那些只属于接单平台。"
|
||||
/>
|
||||
<Table
|
||||
<PercentTable
|
||||
tableLayout="fixed"
|
||||
rowKey="id"
|
||||
size="small"
|
||||
|
||||
@@ -15,10 +15,10 @@ import {
|
||||
Select,
|
||||
Space,
|
||||
Switch,
|
||||
Table,
|
||||
Tag,
|
||||
Typography,
|
||||
} from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import type { TableColumnsType } from 'antd'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { useState } from 'react'
|
||||
@@ -427,7 +427,7 @@ export function ChannelMappingPanel() {
|
||||
</Button>
|
||||
<Button onClick={() => setExpandedMappingProductIds([])}>收起全部</Button>
|
||||
</Space>
|
||||
<Table<ChannelProductMappingGroup>
|
||||
<PercentTable<ChannelProductMappingGroup>
|
||||
tableLayout="fixed"
|
||||
rowKey={(row) => String(row.canonicalProductId)}
|
||||
size="small"
|
||||
@@ -445,7 +445,7 @@ export function ChannelMappingPanel() {
|
||||
<Typography.Text type="secondary">
|
||||
该标准商品下共有 {group.mappings.length} 条渠道映射
|
||||
</Typography.Text>
|
||||
<Table<ChannelProductMapping>
|
||||
<PercentTable<ChannelProductMapping>
|
||||
tableLayout="fixed"
|
||||
rowKey="id"
|
||||
size="small"
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
* 异常表不再存履约载体,履约方式从 order_items.fulfillment_mode join 得到;
|
||||
* 前端按履约方式筛选时传 fulfillmentMode 参数。
|
||||
*/
|
||||
import { App, Button, Card, Select, Space, Table, Tag, Typography } from 'antd'
|
||||
import { App, Button, Card, Select, Space, Tag, Typography } from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import type { TableColumnsType } from 'antd'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { useState } from 'react'
|
||||
@@ -160,7 +161,7 @@ export function CostExceptionPanel() {
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Table
|
||||
<PercentTable
|
||||
tableLayout="fixed"
|
||||
rowKey="id"
|
||||
size="small"
|
||||
|
||||
@@ -6,20 +6,8 @@
|
||||
* 通用成本模型(平台费 / 支付费 / 售后损失 / 其他)对所有履约方式生效。
|
||||
*/
|
||||
import { PlusOutlined, SearchOutlined } from '@ant-design/icons'
|
||||
import {
|
||||
Alert,
|
||||
App,
|
||||
Button,
|
||||
Card,
|
||||
Form,
|
||||
Input,
|
||||
Modal,
|
||||
Select,
|
||||
Space,
|
||||
Table,
|
||||
Tag,
|
||||
Typography,
|
||||
} from 'antd'
|
||||
import { Alert, App, Button, Card, Form, Input, Modal, Select, Space, Tag, Typography } from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import type { TableColumnsType } from 'antd'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { useState } from 'react'
|
||||
@@ -244,7 +232,7 @@ export function CostItemPanel() {
|
||||
style={{ width: 260 }}
|
||||
/>
|
||||
</Space>
|
||||
<Table
|
||||
<PercentTable
|
||||
tableLayout="fixed"
|
||||
rowKey="id"
|
||||
size="small"
|
||||
|
||||
@@ -3,18 +3,8 @@
|
||||
*
|
||||
* 履约方式直接读 order_items.fulfillment_mode,页面只做展示,不允许改判。
|
||||
*/
|
||||
import {
|
||||
App,
|
||||
Alert,
|
||||
Button,
|
||||
Card,
|
||||
Descriptions,
|
||||
Empty,
|
||||
InputNumber,
|
||||
Space,
|
||||
Table,
|
||||
Typography,
|
||||
} from 'antd'
|
||||
import { App, Alert, Button, Card, Descriptions, Empty, InputNumber, Space, Typography } from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import { useState } from 'react'
|
||||
|
||||
import { createAdminCostSnapshot, previewAdminCost } from '@/services/admin'
|
||||
@@ -150,7 +140,7 @@ export function CostPreviewPanel() {
|
||||
/>
|
||||
) : null}
|
||||
|
||||
<Table
|
||||
<PercentTable
|
||||
tableLayout="fixed"
|
||||
rowKey={(row) => `${row.costItemId}-${row.costVersionId}`}
|
||||
size="small"
|
||||
|
||||
@@ -17,10 +17,10 @@ import {
|
||||
Modal,
|
||||
Select,
|
||||
Space,
|
||||
Table,
|
||||
Tag,
|
||||
Typography,
|
||||
} from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import type { TableColumnsType } from 'antd'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { useState } from 'react'
|
||||
@@ -402,7 +402,7 @@ export function CostVersionPanel() {
|
||||
style={{ width: 140 }}
|
||||
/>
|
||||
</Space>
|
||||
<Table
|
||||
<PercentTable
|
||||
tableLayout="fixed"
|
||||
rowKey="id"
|
||||
size="small"
|
||||
|
||||
@@ -33,10 +33,10 @@ import {
|
||||
Select,
|
||||
Space,
|
||||
Statistic,
|
||||
Table,
|
||||
Tag,
|
||||
Typography,
|
||||
} from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import type { TableColumnsType } from 'antd'
|
||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
|
||||
import { useState } from 'react'
|
||||
@@ -382,7 +382,7 @@ export function ManualSkuConfigPanel() {
|
||||
</Button>
|
||||
</Space>
|
||||
|
||||
<Table
|
||||
<PercentTable
|
||||
rowKey="id"
|
||||
size="small"
|
||||
columns={columns}
|
||||
|
||||
@@ -23,11 +23,11 @@ import {
|
||||
Select,
|
||||
Space,
|
||||
Switch,
|
||||
Table,
|
||||
Tabs,
|
||||
Tag,
|
||||
Typography,
|
||||
} from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import type { TableColumnsType } from 'antd'
|
||||
import { useQuery, useQueryClient } from '@tanstack/react-query'
|
||||
import { useState } from 'react'
|
||||
@@ -559,7 +559,7 @@ export function ProductCatalogPanel() {
|
||||
style={{ width: 280 }}
|
||||
/>
|
||||
</Space>
|
||||
<Table
|
||||
<PercentTable
|
||||
tableLayout="fixed"
|
||||
rowKey="id"
|
||||
size="small"
|
||||
|
||||
@@ -24,11 +24,11 @@ import {
|
||||
Select,
|
||||
Space,
|
||||
Statistic,
|
||||
Table,
|
||||
Tabs,
|
||||
Tag,
|
||||
Typography,
|
||||
} from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import type { TableColumnsType } from 'antd'
|
||||
import dayjs from 'dayjs'
|
||||
import type { Dayjs } from 'dayjs'
|
||||
@@ -1048,7 +1048,7 @@ export default function FundManagementView({ role }: { role: ManagementRole }) {
|
||||
) : null
|
||||
}
|
||||
>
|
||||
<Table<AdminFundAccount>
|
||||
<PercentTable<AdminFundAccount>
|
||||
rowKey="id"
|
||||
size="small"
|
||||
columns={buildAccountColumns('agent')}
|
||||
@@ -1074,7 +1074,7 @@ export default function FundManagementView({ role }: { role: ManagementRole }) {
|
||||
) : null
|
||||
}
|
||||
>
|
||||
<Table<AdminFundAccount>
|
||||
<PercentTable<AdminFundAccount>
|
||||
rowKey="id"
|
||||
size="small"
|
||||
columns={buildAccountColumns('supervisor')}
|
||||
@@ -1139,7 +1139,7 @@ export default function FundManagementView({ role }: { role: ManagementRole }) {
|
||||
}}
|
||||
/>
|
||||
</Space>
|
||||
<Table<AdminFundExpense>
|
||||
<PercentTable<AdminFundExpense>
|
||||
rowKey="id"
|
||||
size="small"
|
||||
columns={expenseColumns}
|
||||
@@ -1188,7 +1188,7 @@ export default function FundManagementView({ role }: { role: ManagementRole }) {
|
||||
)}
|
||||
/>
|
||||
</Space>
|
||||
<Table<AdminFundReconciliation>
|
||||
<PercentTable<AdminFundReconciliation>
|
||||
rowKey="id"
|
||||
size="small"
|
||||
columns={reconciliationColumns}
|
||||
@@ -1227,7 +1227,7 @@ export default function FundManagementView({ role }: { role: ManagementRole }) {
|
||||
</Space>
|
||||
}
|
||||
>
|
||||
<Table<AdminFundAccount>
|
||||
<PercentTable<AdminFundAccount>
|
||||
rowKey="id"
|
||||
size="small"
|
||||
columns={buildAccountColumns('supervisor')}
|
||||
@@ -1262,7 +1262,7 @@ export default function FundManagementView({ role }: { role: ManagementRole }) {
|
||||
</Space>
|
||||
}
|
||||
>
|
||||
<Table<AdminFundAccount>
|
||||
<PercentTable<AdminFundAccount>
|
||||
rowKey="id"
|
||||
size="small"
|
||||
columns={buildAccountColumns('agent')}
|
||||
@@ -1793,7 +1793,7 @@ export default function FundManagementView({ role }: { role: ManagementRole }) {
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
<Card title="资金流水" style={{ marginTop: 16 }}>
|
||||
<Table<AdminFundEntry>
|
||||
<PercentTable<AdminFundEntry>
|
||||
rowKey="id"
|
||||
size="small"
|
||||
columns={detailEntryColumns}
|
||||
|
||||
@@ -18,11 +18,11 @@ import {
|
||||
Select,
|
||||
Space,
|
||||
Statistic,
|
||||
Table,
|
||||
Tabs,
|
||||
Tag,
|
||||
Typography,
|
||||
} from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import type { TableColumnsType } from 'antd'
|
||||
import dayjs from 'dayjs'
|
||||
import { useState } from 'react'
|
||||
@@ -497,7 +497,7 @@ export default function FundSupportView() {
|
||||
key: 'credit-entries',
|
||||
label: '积分流水',
|
||||
children: (
|
||||
<Table<PlatformCreditEntry>
|
||||
<PercentTable<PlatformCreditEntry>
|
||||
rowKey="id"
|
||||
size="small"
|
||||
columns={creditEntryColumns}
|
||||
@@ -514,7 +514,7 @@ export default function FundSupportView() {
|
||||
key: 'entries',
|
||||
label: '备用金流水',
|
||||
children: (
|
||||
<Table<AdminFundEntry>
|
||||
<PercentTable<AdminFundEntry>
|
||||
rowKey="id"
|
||||
size="small"
|
||||
columns={entryColumns}
|
||||
@@ -529,7 +529,7 @@ export default function FundSupportView() {
|
||||
key: 'expenses',
|
||||
label: '我的支出',
|
||||
children: (
|
||||
<Table<AdminFundExpense>
|
||||
<PercentTable<AdminFundExpense>
|
||||
rowKey="id"
|
||||
size="small"
|
||||
columns={expenseColumns}
|
||||
|
||||
@@ -24,10 +24,10 @@ import {
|
||||
Select,
|
||||
Space,
|
||||
Statistic,
|
||||
Table,
|
||||
Tag,
|
||||
Typography,
|
||||
} from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import type { TableColumnsType } from 'antd'
|
||||
import { useState } from 'react'
|
||||
|
||||
@@ -399,7 +399,7 @@ export function PlatformCreditPanel() {
|
||||
<Typography.Title level={5} style={{ margin: '8px 0 12px' }}>
|
||||
客服积分余额
|
||||
</Typography.Title>
|
||||
<Table<PlatformCreditAccount>
|
||||
<PercentTable<PlatformCreditAccount>
|
||||
rowKey="id"
|
||||
size="small"
|
||||
columns={accountColumns}
|
||||
@@ -413,7 +413,7 @@ export function PlatformCreditPanel() {
|
||||
<Typography.Title level={5} style={{ margin: '24px 0 12px' }}>
|
||||
积分流水
|
||||
</Typography.Title>
|
||||
<Table
|
||||
<PercentTable
|
||||
rowKey="id"
|
||||
size="small"
|
||||
columns={entryColumns}
|
||||
|
||||
@@ -11,10 +11,10 @@ import {
|
||||
Modal,
|
||||
Select,
|
||||
Space,
|
||||
Table,
|
||||
Tag,
|
||||
Typography,
|
||||
} from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import { forwardRef, useImperativeHandle, useState } from 'react'
|
||||
|
||||
import ImageUpload from '@/components/files/ImageUpload'
|
||||
@@ -195,7 +195,7 @@ const AfterSalesPanel = forwardRef<AfterSalesPanelHandle>(function AfterSalesPan
|
||||
}
|
||||
bordered={false}
|
||||
>
|
||||
<Table<WorkerAfterSalesCase>
|
||||
<PercentTable<WorkerAfterSalesCase>
|
||||
rowKey="caseId"
|
||||
loading={afterSalesCasesQuery.isLoading}
|
||||
dataSource={afterSalesCasesQuery.data?.data.items || []}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ReloadOutlined } from '@ant-design/icons'
|
||||
import { useQuery, useQueryClient } from '@tanstack/react-query'
|
||||
import { App, Button, Card, Form, Input, Modal, Space, Table, Tag, Typography } from 'antd'
|
||||
import { App, Button, Card, Form, Input, Modal, Space, Tag, Typography } from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import type { TableColumnsType } from 'antd'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useSearchParams } from 'react-router'
|
||||
@@ -147,7 +148,7 @@ export default function CancelRequestsPanel() {
|
||||
}
|
||||
bordered={false}
|
||||
>
|
||||
<Table<WorkerCancelRequest>
|
||||
<PercentTable<WorkerCancelRequest>
|
||||
rowKey="requestId"
|
||||
size="small"
|
||||
loading={requestsQuery.isLoading}
|
||||
|
||||
@@ -11,11 +11,11 @@ import {
|
||||
Modal,
|
||||
Select,
|
||||
Space,
|
||||
Table,
|
||||
Tag,
|
||||
Typography,
|
||||
Upload,
|
||||
} from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import type { TableColumnsType } from 'antd'
|
||||
import { useMemo, useState } from 'react'
|
||||
|
||||
@@ -312,7 +312,7 @@ export default function CategoriesPanel() {
|
||||
</Form>
|
||||
</Card>
|
||||
<Card title="分类列表(树形层级)" bordered={false}>
|
||||
<Table<WorkCategory>
|
||||
<PercentTable<WorkCategory>
|
||||
rowKey="categoryId"
|
||||
loading={categoriesQuery.isLoading}
|
||||
dataSource={treeData}
|
||||
|
||||
@@ -18,11 +18,11 @@ import {
|
||||
Space,
|
||||
Statistic,
|
||||
Switch,
|
||||
Table,
|
||||
Tag,
|
||||
Tooltip,
|
||||
Typography,
|
||||
} from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import type { TableColumnsType } from 'antd'
|
||||
import { useState } from 'react'
|
||||
|
||||
@@ -839,7 +839,7 @@ export default function ConsignmentInventoryPanel() {
|
||||
}
|
||||
/>
|
||||
) : null}
|
||||
<Table
|
||||
<PercentTable
|
||||
rowKey="id"
|
||||
columns={columns}
|
||||
dataSource={items}
|
||||
|
||||
@@ -20,12 +20,12 @@ import {
|
||||
Row,
|
||||
Select,
|
||||
Space,
|
||||
Table,
|
||||
Tag,
|
||||
Tooltip,
|
||||
Typography,
|
||||
App,
|
||||
} from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import type { TableColumnsType } from 'antd'
|
||||
import { useState } from 'react'
|
||||
|
||||
@@ -457,7 +457,7 @@ export default function ConsignmentSubmissionsPanel() {
|
||||
}
|
||||
/>
|
||||
) : null}
|
||||
<Table
|
||||
<PercentTable
|
||||
rowKey="id"
|
||||
columns={submissionColumns}
|
||||
dataSource={submissions}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ReloadOutlined } from '@ant-design/icons'
|
||||
import { useQuery, useQueryClient } from '@tanstack/react-query'
|
||||
import { App, Button, Card, Form, Input, Modal, Space, Table, Tag, Typography } from 'antd'
|
||||
import { App, Button, Card, Form, Input, Modal, Space, Tag, Typography } from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import type { TableColumnsType } from 'antd'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useSearchParams } from 'react-router'
|
||||
@@ -123,7 +124,7 @@ export default function FeedbacksPanel() {
|
||||
}
|
||||
bordered={false}
|
||||
>
|
||||
<Table<WorkerOrderFeedback>
|
||||
<PercentTable<WorkerOrderFeedback>
|
||||
rowKey="feedbackId"
|
||||
size="small"
|
||||
loading={feedbacksQuery.isLoading}
|
||||
|
||||
@@ -13,10 +13,10 @@ import {
|
||||
Select,
|
||||
Space,
|
||||
Switch,
|
||||
Table,
|
||||
Tag,
|
||||
Typography,
|
||||
} from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import type { TableColumnsType } from 'antd'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useSearchParams } from 'react-router'
|
||||
@@ -585,7 +585,7 @@ export default function FinancePanel() {
|
||||
totalCount={financeRequestsQuery.data?.data.summary?.totalCount}
|
||||
totalAmount={financeRequestsQuery.data?.data.summary?.totalAmount}
|
||||
/>
|
||||
<Table<WorkerFinanceRequest>
|
||||
<PercentTable<WorkerFinanceRequest>
|
||||
rowKey="requestId"
|
||||
loading={financeRequestsQuery.isLoading}
|
||||
dataSource={financeRequestsQuery.data?.data.items || []}
|
||||
|
||||
@@ -11,10 +11,10 @@ import {
|
||||
InputNumber,
|
||||
Space,
|
||||
Switch,
|
||||
Table,
|
||||
Tag,
|
||||
Upload,
|
||||
} from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
|
||||
import {
|
||||
@@ -182,7 +182,7 @@ export default function HallConfigPanel() {
|
||||
一级分类限额将限制该游戏及旗下所有子分类的总单量;二级分类可单独设置细化限额。
|
||||
</span>
|
||||
</div>
|
||||
<Table<WorkCategory>
|
||||
<PercentTable<WorkCategory>
|
||||
rowKey="categoryId"
|
||||
size="small"
|
||||
pagination={false}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { Card, Segmented, Space, Table, Tag, Typography } from 'antd'
|
||||
import { Card, Segmented, Space, Tag, Typography } from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import type { TableColumnsType } from 'antd'
|
||||
import { useState } from 'react'
|
||||
|
||||
@@ -134,7 +135,7 @@ export default function LeaderboardPanel() {
|
||||
: ''}
|
||||
</Typography.Text>
|
||||
</Space>
|
||||
<Table<AdminWorkerLeaderboardEntry>
|
||||
<PercentTable<AdminWorkerLeaderboardEntry>
|
||||
rowKey="workerId"
|
||||
columns={columns}
|
||||
dataSource={items}
|
||||
|
||||
@@ -9,10 +9,10 @@ import {
|
||||
Modal,
|
||||
Space,
|
||||
Switch,
|
||||
Table,
|
||||
Tag,
|
||||
Typography,
|
||||
} from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import type { TableColumnsType } from 'antd'
|
||||
import { useState } from 'react'
|
||||
|
||||
@@ -225,7 +225,7 @@ export default function LevelsPanel() {
|
||||
</Form>
|
||||
</Card>
|
||||
<Card title="等级列表" bordered={false}>
|
||||
<Table<WorkerLevel>
|
||||
<PercentTable<WorkerLevel>
|
||||
rowKey="levelId"
|
||||
loading={levelsQuery.isLoading}
|
||||
dataSource={levelsQuery.data?.data.items || []}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useQuery, useQueryClient } from '@tanstack/react-query'
|
||||
import { App, Alert, Button, Card, Space, Switch, Table, Typography } from 'antd'
|
||||
import { App, Alert, Button, Card, Space, Switch, Typography } from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import type { TableColumnsType } from 'antd'
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
@@ -143,7 +144,7 @@ export default function NotificationsPanel() {
|
||||
message="配置仅影响保存后产生的通知"
|
||||
description="关闭后台待办后,声音播报会同步关闭;已创建的待办不会被隐藏或删除。"
|
||||
/>
|
||||
<Table
|
||||
<PercentTable
|
||||
rowKey="key"
|
||||
columns={columns}
|
||||
dataSource={notificationEventRows}
|
||||
|
||||
@@ -18,11 +18,11 @@ import {
|
||||
Select,
|
||||
Space,
|
||||
Switch,
|
||||
Table,
|
||||
Tabs,
|
||||
Tag,
|
||||
Typography,
|
||||
} from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import type { TableColumnsType } from 'antd'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useNavigate } from 'react-router'
|
||||
@@ -359,7 +359,7 @@ export default function ProductMatchPanel() {
|
||||
发现新商品后,点击「绑定到模板」在接单模板页配置匹配
|
||||
</Typography.Text>
|
||||
</Space>
|
||||
<Table<KuaishouMatchSource>
|
||||
<PercentTable<KuaishouMatchSource>
|
||||
rowKey={(row) =>
|
||||
`${row.sellerId}-${row.relItemId}-${row.itemTitle}-${row.relSkuId}-${row.skuNick}`
|
||||
}
|
||||
@@ -660,7 +660,7 @@ export default function ProductMatchPanel() {
|
||||
</Button>
|
||||
</Popconfirm>
|
||||
</div>
|
||||
<Table<WorkProductMatchLog>
|
||||
<PercentTable<WorkProductMatchLog>
|
||||
rowKey="logId"
|
||||
loading={logsQuery.isLoading}
|
||||
columns={logColumns}
|
||||
|
||||
@@ -23,11 +23,11 @@ import {
|
||||
Select,
|
||||
Space,
|
||||
Switch,
|
||||
Table,
|
||||
Tabs,
|
||||
Tag,
|
||||
Typography,
|
||||
} from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import type { TableColumnsType } from 'antd'
|
||||
import { useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { useNavigate, useSearchParams } from 'react-router'
|
||||
@@ -1350,7 +1350,7 @@ export default function ProductRulesPanel() {
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
<Table<WorkProductRule>
|
||||
<PercentTable<WorkProductRule>
|
||||
rowKey="ruleId"
|
||||
size="small"
|
||||
loading={rulesQuery.isLoading || mappingsQuery.isLoading}
|
||||
|
||||
@@ -11,9 +11,9 @@ import {
|
||||
Select,
|
||||
Space,
|
||||
Switch,
|
||||
Table,
|
||||
Tag,
|
||||
} from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import type { ColumnsType } from 'antd/es/table'
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
@@ -381,7 +381,7 @@ export default function RiskControlPanel() {
|
||||
</Button>
|
||||
}
|
||||
>
|
||||
<Table
|
||||
<PercentTable
|
||||
rowKey="key"
|
||||
size="small"
|
||||
columns={trackerColumns}
|
||||
@@ -427,7 +427,7 @@ export default function RiskControlPanel() {
|
||||
</Button>
|
||||
</Space>
|
||||
|
||||
<Table
|
||||
<PercentTable
|
||||
rowKey="id"
|
||||
size="small"
|
||||
columns={eventColumns}
|
||||
|
||||
@@ -32,11 +32,11 @@ import {
|
||||
Select,
|
||||
Space,
|
||||
Switch,
|
||||
Table,
|
||||
Tabs,
|
||||
Tag,
|
||||
Typography,
|
||||
} from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import type { TableColumnsType } from 'antd'
|
||||
import { useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { useNavigate, useSearchParams } from 'react-router'
|
||||
@@ -2076,7 +2076,7 @@ export default function WorkOrdersPanel() {
|
||||
}
|
||||
bordered={false}
|
||||
>
|
||||
<Table<WorkOrder>
|
||||
<PercentTable<WorkOrder>
|
||||
rowKey="workOrderId"
|
||||
loading={ordersQuery.isLoading}
|
||||
dataSource={ordersQuery.data?.data.items || []}
|
||||
@@ -3139,7 +3139,7 @@ export default function WorkOrdersPanel() {
|
||||
</div>
|
||||
</Space>
|
||||
) : null}
|
||||
<Table<WorkOrderShare>
|
||||
<PercentTable<WorkOrderShare>
|
||||
rowKey="shareId"
|
||||
size="small"
|
||||
dataSource={sharingShares}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useState } from 'react'
|
||||
import { Card, Descriptions, Drawer, Select, Space, Table, Tabs, Tag, Typography } from 'antd'
|
||||
import { Card, Descriptions, Drawer, Select, Space, Tabs, Tag, Typography } from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import type { TableColumnsType } from 'antd'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
|
||||
@@ -303,7 +304,7 @@ function UnfreezesSection({ workerId }: { workerId: number }) {
|
||||
},
|
||||
]
|
||||
return (
|
||||
<Table<WorkerDepositUnfreeze>
|
||||
<PercentTable<WorkerDepositUnfreeze>
|
||||
rowKey="id"
|
||||
size="small"
|
||||
columns={columns}
|
||||
@@ -398,7 +399,7 @@ function LedgersSection({ workerId }: { workerId: number }) {
|
||||
setPage(1)
|
||||
}}
|
||||
/>
|
||||
<Table<WorkerWalletLedger>
|
||||
<PercentTable<WorkerWalletLedger>
|
||||
rowKey="ledgerId"
|
||||
size="small"
|
||||
columns={columns}
|
||||
@@ -463,7 +464,7 @@ function OrdersSection({ workerId }: { workerId: number }) {
|
||||
},
|
||||
]
|
||||
return (
|
||||
<Table<WorkOrder>
|
||||
<PercentTable<WorkOrder>
|
||||
rowKey="workOrderId"
|
||||
size="small"
|
||||
columns={columns}
|
||||
|
||||
@@ -13,11 +13,11 @@ import {
|
||||
Select,
|
||||
Space,
|
||||
Switch,
|
||||
Table,
|
||||
Tag,
|
||||
Tooltip,
|
||||
Typography,
|
||||
} from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import type { TableColumnsType } from 'antd'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { useSearchParams } from 'react-router'
|
||||
@@ -952,7 +952,7 @@ export default function WorkersPanel() {
|
||||
: '寄卖白名单已关闭:全部打手均可发布寄卖。下方开关仅在重新开启白名单后生效。'
|
||||
}
|
||||
/>
|
||||
<Table<WorkerUser>
|
||||
<PercentTable<WorkerUser>
|
||||
rowKey="workerId"
|
||||
loading={workersQuery.isLoading}
|
||||
dataSource={workersQuery.data?.data.items || []}
|
||||
|
||||
@@ -18,7 +18,6 @@ import {
|
||||
Space,
|
||||
Spin,
|
||||
Switch,
|
||||
Table,
|
||||
Tag,
|
||||
Typography,
|
||||
} from 'antd'
|
||||
|
||||
@@ -19,11 +19,11 @@ import {
|
||||
Space,
|
||||
Spin,
|
||||
Switch,
|
||||
Table,
|
||||
Tabs,
|
||||
Tag,
|
||||
Typography,
|
||||
} from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import type { TableColumnsType } from 'antd'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useSearchParams } from 'react-router'
|
||||
@@ -1106,7 +1106,7 @@ function KuaishouIndustryPanel({
|
||||
{shops.length === 0 ? (
|
||||
<Empty description="暂无店铺授权" />
|
||||
) : (
|
||||
<Table<AdminKuaishouIndustryShopConfig>
|
||||
<PercentTable<AdminKuaishouIndustryShopConfig>
|
||||
rowKey={(row, index) => buildIndustryShopRowKey(row, index || 0)}
|
||||
columns={shopColumns}
|
||||
dataSource={shops}
|
||||
@@ -1694,7 +1694,7 @@ function AffiliateDashPlatformPanel() {
|
||||
<Typography.Text code>apps/backend/.../affiliate-dash/sku-mapping.ts</Typography.Text>
|
||||
,与平台商品目录对齐。
|
||||
</Typography.Paragraph>
|
||||
<Table<SkuMappingRow>
|
||||
<PercentTable<SkuMappingRow>
|
||||
rowKey={(row) => row.productNo}
|
||||
size="small"
|
||||
pagination={{ pageSize: 10, showSizeChanger: false }}
|
||||
@@ -1760,7 +1760,7 @@ function AffiliateDashPlatformPanel() {
|
||||
</Typography.Text>
|
||||
) : null}
|
||||
</Space>
|
||||
<Table<AdminAffiliateDashProductItem>
|
||||
<PercentTable<AdminAffiliateDashProductItem>
|
||||
rowKey="sku"
|
||||
size="small"
|
||||
loading={productsLoading}
|
||||
|
||||
@@ -39,11 +39,11 @@ import {
|
||||
Spin,
|
||||
Statistic,
|
||||
Switch,
|
||||
Table,
|
||||
Tag,
|
||||
Tooltip,
|
||||
Typography,
|
||||
} from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import type { TableColumnsType } from 'antd'
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
@@ -986,7 +986,7 @@ export function PddPlatformPanel() {
|
||||
</Button>
|
||||
}
|
||||
>
|
||||
<Table
|
||||
<PercentTable
|
||||
rowKey="shopId"
|
||||
columns={columns}
|
||||
dataSource={config.stores}
|
||||
|
||||
@@ -16,11 +16,11 @@ import {
|
||||
Modal,
|
||||
Segmented,
|
||||
Space,
|
||||
Table,
|
||||
Tabs,
|
||||
Typography,
|
||||
type InputRef,
|
||||
} from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { Navigate, useNavigate } from 'react-router'
|
||||
|
||||
@@ -665,7 +665,7 @@ export default function WorkerLoginPage() {
|
||||
message="验证账号密码后,可删除旧设备。PC 和手机分别最多同时在线 3 台。"
|
||||
style={{ marginBottom: 16 }}
|
||||
/>
|
||||
<Table
|
||||
<PercentTable
|
||||
size="small"
|
||||
rowKey="sessionId"
|
||||
loading={deviceManagerLoading}
|
||||
|
||||
@@ -6,7 +6,8 @@ import {
|
||||
ThunderboltOutlined,
|
||||
WarningOutlined,
|
||||
} from '@ant-design/icons'
|
||||
import { Alert, Button, Card, Empty, Input, Space, Table, Tabs, Typography } from 'antd'
|
||||
import { Alert, Button, Card, Empty, Input, Space, Tabs, Typography } from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import type { TableColumnsType } from 'antd'
|
||||
|
||||
import type { Pagination, WorkerOrderOverviewItem, WorkOrder } from '@/types/worker-platform'
|
||||
@@ -255,7 +256,7 @@ export function WorkerOrderDesktopList({
|
||||
/>
|
||||
) : null}
|
||||
|
||||
<Table<WorkOrder>
|
||||
<PercentTable<WorkOrder>
|
||||
rowKey="workOrderId"
|
||||
size="middle"
|
||||
loading={loading}
|
||||
|
||||
@@ -8,9 +8,9 @@ import {
|
||||
Input,
|
||||
Modal,
|
||||
Space,
|
||||
Table,
|
||||
Typography,
|
||||
} from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
import type { FormInstance } from 'antd'
|
||||
|
||||
import type { WorkerFinanceConfig, WorkerSessionDevice, WorkerUser } from '@/types/worker-platform'
|
||||
@@ -93,7 +93,7 @@ export function WorkerProfileAccountModals({
|
||||
type="info"
|
||||
message={`PC 和手机分别最多同时在线 ${maxDevices} 台(当前 PC ${deviceCounts.pc} 台、手机 ${deviceCounts.mobile} 台),删除对应旧设备后才能登录。`}
|
||||
/>
|
||||
<Table<WorkerSessionDevice>
|
||||
<PercentTable<WorkerSessionDevice>
|
||||
size="small"
|
||||
loading={devicesLoading}
|
||||
rowKey="sessionId"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { ReloadOutlined } from '@ant-design/icons'
|
||||
import { Button, Card, Empty, Pagination, Select, Space, Spin, Table, Tag } from 'antd'
|
||||
import { Button, Card, Empty, Pagination, Select, Space, Spin, Tag } from 'antd'
|
||||
import PercentTable from '@/components/common/PercentTable'
|
||||
|
||||
import type {
|
||||
WorkerFinanceRequest,
|
||||
@@ -293,7 +294,7 @@ export function WorkerProfileDesktopLedgerRecords({
|
||||
</Space>
|
||||
}
|
||||
>
|
||||
<Table<WorkerWalletLedger>
|
||||
<PercentTable<WorkerWalletLedger>
|
||||
rowKey="ledgerId"
|
||||
size="small"
|
||||
loading={loading}
|
||||
@@ -353,7 +354,7 @@ export function WorkerProfileDesktopRequestRecords({
|
||||
</Space>
|
||||
}
|
||||
>
|
||||
<Table<WorkerFinanceRequest>
|
||||
<PercentTable<WorkerFinanceRequest>
|
||||
rowKey="requestId"
|
||||
size="small"
|
||||
loading={loading}
|
||||
|
||||
@@ -11,3 +11,4 @@
|
||||
@import './admin.css';
|
||||
@import './client.css';
|
||||
@import './worker.css';
|
||||
@import './table.css';
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
/* 全项目表格统一规范:宽度百分比自适应,表头与内容全部居中。 */
|
||||
.ant-table-wrapper .ant-table {
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
.ant-table-wrapper .ant-table-thead > tr > th,
|
||||
.ant-table-wrapper .ant-table-tbody > tr > td {
|
||||
text-align: center !important;
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
import type { TableColumnsType } from 'antd'
|
||||
|
||||
type Column<RecordType extends object> = TableColumnsType<RecordType>[number]
|
||||
|
||||
type WidthContext<RecordType extends object> = {
|
||||
leafPercent: WeakMap<Column<RecordType>, number>
|
||||
}
|
||||
|
||||
/**
|
||||
* 把业务列宽(px 数值)按相对权重归一化为百分比。
|
||||
* rowSelection / expandable 等内置列由调用方传入需要预留的百分比。
|
||||
*/
|
||||
export function normalizePercentColumns<RecordType extends object>(
|
||||
columns: TableColumnsType<RecordType>,
|
||||
options: { reservedPercent?: number } = {},
|
||||
): TableColumnsType<RecordType> {
|
||||
const leaves: Column<RecordType>[] = []
|
||||
collectLeaves(columns, leaves)
|
||||
|
||||
const explicitWeights = leaves
|
||||
.map((column) => numericWidth(column.width))
|
||||
.filter((width): width is number => width !== null)
|
||||
const fallbackWeight =
|
||||
explicitWeights.length > 0
|
||||
? explicitWeights.reduce((sum, width) => sum + width, 0) / explicitWeights.length
|
||||
: 100
|
||||
const totalWeight = leaves.reduce(
|
||||
(sum, column) => sum + (numericWidth(column.width) ?? fallbackWeight),
|
||||
0,
|
||||
)
|
||||
const budgetPercent = Math.max(60, 100 - Math.max(0, options.reservedPercent ?? 0))
|
||||
|
||||
const leafPercent = new WeakMap<Column<RecordType>, number>()
|
||||
for (const column of leaves) {
|
||||
const weight = numericWidth(column.width) ?? fallbackWeight
|
||||
leafPercent.set(column, (weight / totalWeight) * budgetPercent)
|
||||
}
|
||||
|
||||
return applyPercentWidths(columns, { leafPercent })
|
||||
}
|
||||
|
||||
function applyPercentWidths<RecordType extends object>(
|
||||
columns: TableColumnsType<RecordType>,
|
||||
context: WidthContext<RecordType>,
|
||||
): TableColumnsType<RecordType> {
|
||||
return columns.map((column) => {
|
||||
const children = 'children' in column ? column.children : undefined
|
||||
if (Array.isArray(children) && children.length > 0) {
|
||||
const normalizedChildren = applyPercentWidths(children, context)
|
||||
const width = normalizedChildren.reduce((sum, child) => sum + percentOf(child.width), 0)
|
||||
return {
|
||||
...column,
|
||||
width: `${width.toFixed(4)}%`,
|
||||
align: 'center',
|
||||
children: normalizedChildren,
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...column,
|
||||
width: `${(context.leafPercent.get(column) ?? 0).toFixed(4)}%`,
|
||||
align: 'center',
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function collectLeaves<RecordType extends object>(
|
||||
columns: TableColumnsType<RecordType>,
|
||||
leaves: Column<RecordType>[],
|
||||
) {
|
||||
for (const column of columns) {
|
||||
const children = 'children' in column ? column.children : undefined
|
||||
if (Array.isArray(children) && children.length > 0) {
|
||||
collectLeaves(children, leaves)
|
||||
} else {
|
||||
leaves.push(column)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function numericWidth(width: Column<object>['width']) {
|
||||
if (typeof width === 'number' && Number.isFinite(width) && width > 0) return width
|
||||
if (typeof width === 'string') {
|
||||
const parsed = Number.parseFloat(width)
|
||||
if (Number.isFinite(parsed) && parsed > 0) return parsed
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
function percentOf(width: Column<object>['width']) {
|
||||
if (typeof width !== 'string' || !width.endsWith('%')) return 0
|
||||
const parsed = Number.parseFloat(width)
|
||||
return Number.isFinite(parsed) ? parsed : 0
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import test from 'node:test'
|
||||
|
||||
import type { TableColumnsType } from 'antd'
|
||||
|
||||
import { normalizePercentColumns } from '../src/utils/percent-table-layout.ts'
|
||||
|
||||
test('百分比表格:按原列宽权重归一化到 100%', () => {
|
||||
const columns: TableColumnsType<Record<string, unknown>> = [
|
||||
{ title: 'A', dataIndex: 'a', width: 100 },
|
||||
{ title: 'B', dataIndex: 'b', width: 300 },
|
||||
]
|
||||
const result = normalizePercentColumns(columns)
|
||||
assert.deepEqual(
|
||||
result.map((column) => column.width),
|
||||
['25.0000%', '75.0000%'],
|
||||
)
|
||||
assert.ok(result.every((column) => column.align === 'center'))
|
||||
})
|
||||
|
||||
test('百分比表格:没有列宽时平均分配', () => {
|
||||
const columns: TableColumnsType<Record<string, unknown>> = [
|
||||
{ title: 'A', dataIndex: 'a' },
|
||||
{ title: 'B', dataIndex: 'b' },
|
||||
]
|
||||
assert.deepEqual(
|
||||
normalizePercentColumns(columns).map((column) => column.width),
|
||||
['50.0000%', '50.0000%'],
|
||||
)
|
||||
})
|
||||
|
||||
test('百分比表格:选择列预留 4%', () => {
|
||||
const columns: TableColumnsType<Record<string, unknown>> = [
|
||||
{ title: 'A', dataIndex: 'a', width: 100 },
|
||||
{ title: 'B', dataIndex: 'b', width: 100 },
|
||||
]
|
||||
const result = normalizePercentColumns(columns, { reservedPercent: 4 })
|
||||
assert.deepEqual(
|
||||
result.map((column) => column.width),
|
||||
['48.0000%', '48.0000%'],
|
||||
)
|
||||
})
|
||||
|
||||
test('百分比表格:分组列宽等于子列之和', () => {
|
||||
const columns: TableColumnsType<Record<string, unknown>> = [
|
||||
{
|
||||
title: '分组',
|
||||
children: [
|
||||
{ title: 'A', dataIndex: 'a', width: 100 },
|
||||
{ title: 'B', dataIndex: 'b', width: 100 },
|
||||
],
|
||||
},
|
||||
]
|
||||
const result = normalizePercentColumns(columns)
|
||||
assert.equal(result[0]?.width, '100.0000%')
|
||||
})
|
||||
|
||||
test('全项目表格必须统一使用 PercentTable', () => {
|
||||
const offenders: string[] = []
|
||||
for (const file of listTsxFiles(path.join(process.cwd(), 'src'))) {
|
||||
const source = fs.readFileSync(file, 'utf8')
|
||||
if (/<Table\b/.test(source)) {
|
||||
offenders.push(path.relative(process.cwd(), file))
|
||||
}
|
||||
}
|
||||
assert.deepEqual(offenders, [], `仍有表格直接使用 AntD Table:${offenders.join(', ')}`)
|
||||
})
|
||||
|
||||
function listTsxFiles(dir: string): string[] {
|
||||
return fs.readdirSync(dir, { withFileTypes: true }).flatMap((entry) => {
|
||||
const fullPath = path.join(dir, entry.name)
|
||||
if (entry.isDirectory()) return listTsxFiles(fullPath)
|
||||
return entry.isFile() && entry.name.endsWith('.tsx') ? [fullPath] : []
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user