feat(店铺管理): 优化订单列表和媒体管理功能

- 在订单列表中将ID列改为订单号列并优化布局
- 在媒体管理页面添加批量转换为WebP功能
- 修复媒体管理页面操作列按钮样式问题
- 清理API接口中多余的where和order参数
- 删除未使用的Woo/Media页面
This commit is contained in:
tikkhun 2025-12-15 17:46:43 +08:00
parent 2e9c7fafce
commit dc616f5e8d
7 changed files with 116 additions and 261 deletions

View File

@ -73,7 +73,7 @@ export default defineConfig({
component: './Site/List', component: './Site/List',
}, },
{ {
name: '店铺页面', name: '店铺管理',
path: '/site/shop', path: '/site/shop',
component: './Site/Shop/Layout', component: './Site/Shop/Layout',
routes: [ routes: [

View File

@ -1721,8 +1721,11 @@ const Shipping: React.FC<{
]} ]}
/> />
<ProFormDependency name={[['details', 'packaging_type']]}> <ProFormDependency name={[['details', 'packaging_type']]}>
{({ details: { packaging_type } }) => { {({ details }) => {
if (packaging_type === 'package') { // 根据包装类型决定渲染内容
const selectedPackagingType = details?.packaging_type;
// 判断是否为纸箱
if (selectedPackagingType === 'package') {
return ( return (
<ProFormList <ProFormList
min={1} min={1}
@ -1863,7 +1866,8 @@ const Shipping: React.FC<{
</ProFormList> </ProFormList>
); );
} }
if (packaging_type === 'courier-pak') { // 判断是否为文件袋
if (selectedPackagingType === 'courier-pak') {
return ( return (
<ProFormList <ProFormList
label="文件袋" label="文件袋"

View File

@ -110,6 +110,7 @@ const MediaPage: React.FC = () => {
title: '操作', title: '操作',
valueType: 'option', valueType: 'option',
width: 160, width: 160,
fixed: 'right',
render: (_, record) => ( render: (_, record) => (
<Space> <Space>
<Button <Button
@ -119,14 +120,18 @@ const MediaPage: React.FC = () => {
onClick={() => { onClick={() => {
setEditing(record); setEditing(record);
}} }}
/> >
</Button>
<Popconfirm <Popconfirm
title="确定删除吗?" title="确定删除吗?"
onConfirm={() => handleDelete(record.id)} onConfirm={() => handleDelete(record.id)}
okText="确定" okText="确定"
cancelText="取消" cancelText="取消"
> >
<Button type="link" danger title="删除" icon={<DeleteOutlined />} /> <Button type="link" danger title="删除" icon={<DeleteOutlined />}>
</Button>
</Popconfirm> </Popconfirm>
</Space> </Space>
), ),
@ -187,7 +192,7 @@ const MediaPage: React.FC = () => {
toolBarRender={() => [ toolBarRender={() => [
<ModalForm <ModalForm
title="上传媒体" title="上传媒体"
trigger={<Button type="primary" title="上传媒体" icon={<PlusOutlined />} />} trigger={<Button type="primary" title="上传媒体" icon={<PlusOutlined />}></Button>}
width={500} width={500}
onFinish={async (values) => { onFinish={async (values) => {
if (!siteId) return false; if (!siteId) return false;
@ -252,7 +257,9 @@ const MediaPage: React.FC = () => {
message.error(res.message || '导出失败'); message.error(res.message || '导出失败');
} }
}} }}
/>, >
</Button>,
<Popconfirm <Popconfirm
title="确定批量删除选中项吗?" title="确定批量删除选中项吗?"
okText="确定" okText="确定"
@ -280,9 +287,45 @@ const MediaPage: React.FC = () => {
danger danger
icon={<DeleteOutlined />} icon={<DeleteOutlined />}
disabled={!selectedRowKeys.length} disabled={!selectedRowKeys.length}
/> >
</Button>
</Popconfirm> </Popconfirm>
,
<Button
title="批量转换为WebP"
disabled={!selectedRowKeys.length}
onClick={async () => {
// 条件判断 如果站点編號不存在則直接返回
if (!siteId) return;
try {
// 发起后端批量转换请求
const response = await request(`/site-api/${siteId}/media/convert-webp`, {
method: 'POST',
data: { ids: selectedRowKeys },
});
// 条件判断 根据接口返回结果进行提示
if (response.success) {
const convertedCount = response?.data?.converted?.length || 0;
const failedCount = response?.data?.failed?.length || 0;
if (failedCount > 0) {
message.warning(`部分转换失败 已转换 ${convertedCount} 失败 ${failedCount}`);
} else {
message.success(`转换成功 已转换 ${convertedCount}`);
}
// 刷新列表数据
actionRef.current?.reload();
} else {
message.error(response.message || '转换失败');
}
} catch (error: any) {
message.error(error.message || '转换失败');
}
}}
>
WebP
</Button>
]} ]}
/> />

View File

@ -78,14 +78,10 @@ const OrdersPage: React.FC = () => {
const columns: ProColumns<API.Order>[] = [ const columns: ProColumns<API.Order>[] = [
{ {
title: 'ID', title: '订单号',
dataIndex: 'id', dataIndex: 'id',
hideInSearch: true, hideInSearch: true,
}, },
{
title: '订单号',
dataIndex: 'number',
},
{ {
title: '状态', title: '状态',
dataIndex: 'status', dataIndex: 'status',
@ -151,7 +147,7 @@ const OrdersPage: React.FC = () => {
render: (_, record) => { render: (_, record) => {
return ( return (
<> <>
<EditOrder <EditOrder
key={record.id} key={record.id}
record={record} record={record}
tableRef={actionRef} tableRef={actionRef}
@ -208,6 +204,7 @@ const OrdersPage: React.FC = () => {
<PageContainer ghost header={{ title: null, breadcrumb: undefined }}> <PageContainer ghost header={{ title: null, breadcrumb: undefined }}>
<Tabs items={tabs} activeKey={activeKey} onChange={setActiveKey} /> <Tabs items={tabs} activeKey={activeKey} onChange={setActiveKey} />
<ProTable <ProTable
columns={columns}
params={{ status: activeKey }} params={{ status: activeKey }}
headerTitle="查询表格" headerTitle="查询表格"
scroll={{ x: 'max-content' }} scroll={{ x: 'max-content' }}
@ -227,10 +224,10 @@ const OrdersPage: React.FC = () => {
toolBarRender={() => [ toolBarRender={() => [
<CreateOrder tableRef={actionRef} siteId={siteId} />, <CreateOrder tableRef={actionRef} siteId={siteId} />,
<BatchEditOrders <BatchEditOrders
tableRef={actionRef} tableRef={actionRef}
selectedRowKeys={selectedRowKeys} selectedRowKeys={selectedRowKeys}
setSelectedRowKeys={setSelectedRowKeys} setSelectedRowKeys={setSelectedRowKeys}
siteId={siteId} siteId={siteId}
/>, />,
<Button <Button
title="批量删除" title="批量删除"
@ -405,7 +402,7 @@ const OrdersPage: React.FC = () => {
success: false success: false
}; };
}} }}
columns={columns}
/> />
</PageContainer> </PageContainer>
); );

View File

@ -1,167 +0,0 @@
import { sitecontrollerAll } from '@/servers/api/site';
import { PageContainer, ProColumns, ProTable } from '@ant-design/pro-components';
import { request } from '@umijs/max';
import { App, Image, Select } from 'antd';
import React, { useEffect, useState } from 'react';
const MediaPage: React.FC = () => {
const { message } = App.useApp();
const [sites, setSites] = useState<any[]>([]);
const [selectedSiteId, setSelectedSiteId] = useState<number | undefined>();
const [mediaList, setMediaList] = useState<any[]>([]);
const [loading, setLoading] = useState(false);
const [pagination, setPagination] = useState({
current: 1,
pageSize: 20,
total: 0,
});
// Fetch sites
useEffect(() => {
const fetchSites = async () => {
try {
const res = await sitecontrollerAll();
if (res.success && res.data) {
setSites(res.data);
if (res.data.length > 0) {
setSelectedSiteId(res.data[0].id);
}
}
} catch (error) {
message.error('获取站点列表失败');
}
};
fetchSites();
}, []);
// Fetch media
const fetchMedia = async (siteId: number, page: number, pageSize: number) => {
setLoading(true);
try {
const res = await request('/media/list', {
params: { siteId, page, pageSize },
});
if (res.success) {
setMediaList(res.data.items || []);
setPagination({
current: page,
pageSize: pageSize,
total: res.data.total || 0,
});
} else {
message.error(res.message || '获取媒体库失败');
}
} catch (error) {
message.error('获取媒体库失败');
} finally {
setLoading(false);
}
};
useEffect(() => {
if (selectedSiteId) {
fetchMedia(selectedSiteId, 1, pagination.pageSize);
}
}, [selectedSiteId]);
const handlePageChange = (page: number, pageSize: number) => {
if (selectedSiteId) {
fetchMedia(selectedSiteId, page, pageSize);
}
};
const formatSize = (bytes: number) => {
if (!bytes) return '-';
if (bytes === 0) return '0 B';
const k = 1024;
const sizes = ['B', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
};
const columns: ProColumns<any>[] = [
{
title: '展示',
dataIndex: 'source_url',
hideInSearch: true,
render: (_, record) => (
<Image
src={record.media_details?.sizes?.thumbnail?.source_url || record.source_url}
style={{ width: 60, height: 60, objectFit: 'contain', background: '#f0f0f0' }}
fallback="https://via.placeholder.com/60?text=No+Img"
/>
),
},
{
title: '名称',
dataIndex: ['title', 'rendered'],
copyable: true,
ellipsis: true,
width: 200,
},
{
title: '宽高',
dataIndex: 'media_details',
hideInSearch: true,
render: (_, record) => {
const width = record.media_details?.width;
const height = record.media_details?.height;
return width && height ? `${width} x ${height}` : '-';
},
},
{
title: '地址',
dataIndex: 'source_url',
copyable: true,
ellipsis: true,
hideInSearch: true,
},
{
title: '文件大小',
dataIndex: 'media_details',
hideInSearch: true,
render: (_, record) => formatSize(record.media_details?.filesize),
},
{
title: '素材类型',
dataIndex: 'mime_type',
width: 120,
},
];
return (
<PageContainer
header={{
title: '媒体库',
extra: [
<Select
key="site-select"
style={{ width: 200 }}
placeholder="选择站点"
value={selectedSiteId}
onChange={setSelectedSiteId}
options={sites.map(site => ({ label: site.name, value: site.id }))}
/>
]
}}
>
<ProTable
rowKey="id"
columns={columns}
dataSource={mediaList}
loading={loading}
search={false}
pagination={{
current: pagination.current,
pageSize: pagination.pageSize,
total: pagination.total,
onChange: handlePageChange,
showSizeChanger: true,
}}
options={false}
/>
</PageContainer>
);
};
export default MediaPage;

View File

@ -15,10 +15,6 @@ export async function siteapicontrollerGetcustomers(
method: 'GET', method: 'GET',
params: { params: {
...queryParams, ...queryParams,
where: undefined,
...queryParams['where'],
order: undefined,
...queryParams['order'],
}, },
...(options || {}), ...(options || {}),
}, },
@ -74,10 +70,6 @@ export async function siteapicontrollerExportcustomers(
method: 'GET', method: 'GET',
params: { params: {
...queryParams, ...queryParams,
where: undefined,
...queryParams['where'],
order: undefined,
...queryParams['order'],
}, },
...(options || {}), ...(options || {}),
}); });
@ -113,10 +105,6 @@ export async function siteapicontrollerGetmedia(
method: 'GET', method: 'GET',
params: { params: {
...queryParams, ...queryParams,
where: undefined,
...queryParams['where'],
order: undefined,
...queryParams['order'],
}, },
...(options || {}), ...(options || {}),
}); });
@ -141,6 +129,28 @@ export async function siteapicontrollerBatchmedia(
}); });
} }
/** 此处后端没有提供注释 POST /site-api/${param0}/media/convert-webp */
export async function siteapicontrollerConvertmediatowebp(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.siteapicontrollerConvertmediatowebpParams,
body: Record<string, any>,
options?: { [key: string]: any },
) {
const { siteId: param0, ...queryParams } = params;
return request<Record<string, any>>(
`/site-api/${param0}/media/convert-webp`,
{
method: 'POST',
headers: {
'Content-Type': 'text/plain',
},
params: { ...queryParams },
data: body,
...(options || {}),
},
);
}
/** 此处后端没有提供注释 GET /site-api/${param0}/media/export */ /** 此处后端没有提供注释 GET /site-api/${param0}/media/export */
export async function siteapicontrollerExportmedia( export async function siteapicontrollerExportmedia(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象) // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
@ -152,10 +162,6 @@ export async function siteapicontrollerExportmedia(
method: 'GET', method: 'GET',
params: { params: {
...queryParams, ...queryParams,
where: undefined,
...queryParams['where'],
order: undefined,
...queryParams['order'],
}, },
...(options || {}), ...(options || {}),
}); });
@ -172,10 +178,6 @@ export async function siteapicontrollerGetorders(
method: 'GET', method: 'GET',
params: { params: {
...queryParams, ...queryParams,
where: undefined,
...queryParams['where'],
order: undefined,
...queryParams['order'],
}, },
...(options || {}), ...(options || {}),
}); });
@ -230,10 +232,6 @@ export async function siteapicontrollerExportorders(
method: 'GET', method: 'GET',
params: { params: {
...queryParams, ...queryParams,
where: undefined,
...queryParams['where'],
order: undefined,
...queryParams['order'],
}, },
...(options || {}), ...(options || {}),
}); });
@ -271,10 +269,6 @@ export async function siteapicontrollerGetproducts(
method: 'GET', method: 'GET',
params: { params: {
...queryParams, ...queryParams,
where: undefined,
...queryParams['where'],
order: undefined,
...queryParams['order'],
}, },
...(options || {}), ...(options || {}),
}, },
@ -330,10 +324,6 @@ export async function siteapicontrollerExportproducts(
method: 'GET', method: 'GET',
params: { params: {
...queryParams, ...queryParams,
where: undefined,
...queryParams['where'],
order: undefined,
...queryParams['order'],
}, },
...(options || {}), ...(options || {}),
}); });
@ -350,10 +340,6 @@ export async function siteapicontrollerExportproductsspecial(
method: 'GET', method: 'GET',
params: { params: {
...queryParams, ...queryParams,
where: undefined,
...queryParams['where'],
order: undefined,
...queryParams['order'],
}, },
...(options || {}), ...(options || {}),
}); });
@ -413,10 +399,6 @@ export async function siteapicontrollerGetsubscriptions(
method: 'GET', method: 'GET',
params: { params: {
...queryParams, ...queryParams,
where: undefined,
...queryParams['where'],
order: undefined,
...queryParams['order'],
}, },
...(options || {}), ...(options || {}),
}, },
@ -434,10 +416,6 @@ export async function siteapicontrollerExportsubscriptions(
method: 'GET', method: 'GET',
params: { params: {
...queryParams, ...queryParams,
where: undefined,
...queryParams['where'],
order: undefined,
...queryParams['order'],
}, },
...(options || {}), ...(options || {}),
}); });
@ -512,10 +490,6 @@ export async function siteapicontrollerGetcustomerorders(
method: 'GET', method: 'GET',
params: { params: {
...queryParams, ...queryParams,
where: undefined,
...queryParams['where'],
order: undefined,
...queryParams['order'],
}, },
...(options || {}), ...(options || {}),
}, },

View File

@ -1421,6 +1421,10 @@ declare namespace API {
siteId: number; siteId: number;
}; };
type siteapicontrollerConvertmediatowebpParams = {
siteId: number;
};
type siteapicontrollerCreatecustomerParams = { type siteapicontrollerCreatecustomerParams = {
siteId: number; siteId: number;
}; };
@ -1472,9 +1476,9 @@ declare namespace API {
/** 客户ID,用于筛选订单 */ /** 客户ID,用于筛选订单 */
customer_id?: number; customer_id?: number;
/** 过滤条件对象 */ /** 过滤条件对象 */
where?: Record<string, any>; where?: any;
/** 排序对象,例如 { "sku": "desc" } */ /** 排序对象,例如 { "sku": "desc" } */
order?: Record<string, any>; order?: any;
/** 排序字段(兼容旧入参) */ /** 排序字段(兼容旧入参) */
orderby?: string; orderby?: string;
/** 排序方式(兼容旧入参) */ /** 排序方式(兼容旧入参) */
@ -1498,9 +1502,9 @@ declare namespace API {
/** 客户ID,用于筛选订单 */ /** 客户ID,用于筛选订单 */
customer_id?: number; customer_id?: number;
/** 过滤条件对象 */ /** 过滤条件对象 */
where?: Record<string, any>; where?: any;
/** 排序对象,例如 { "sku": "desc" } */ /** 排序对象,例如 { "sku": "desc" } */
order?: Record<string, any>; order?: any;
/** 排序字段(兼容旧入参) */ /** 排序字段(兼容旧入参) */
orderby?: string; orderby?: string;
/** 排序方式(兼容旧入参) */ /** 排序方式(兼容旧入参) */
@ -1524,9 +1528,9 @@ declare namespace API {
/** 客户ID,用于筛选订单 */ /** 客户ID,用于筛选订单 */
customer_id?: number; customer_id?: number;
/** 过滤条件对象 */ /** 过滤条件对象 */
where?: Record<string, any>; where?: any;
/** 排序对象,例如 { "sku": "desc" } */ /** 排序对象,例如 { "sku": "desc" } */
order?: Record<string, any>; order?: any;
/** 排序字段(兼容旧入参) */ /** 排序字段(兼容旧入参) */
orderby?: string; orderby?: string;
/** 排序方式(兼容旧入参) */ /** 排序方式(兼容旧入参) */
@ -1550,9 +1554,9 @@ declare namespace API {
/** 客户ID,用于筛选订单 */ /** 客户ID,用于筛选订单 */
customer_id?: number; customer_id?: number;
/** 过滤条件对象 */ /** 过滤条件对象 */
where?: Record<string, any>; where?: any;
/** 排序对象,例如 { "sku": "desc" } */ /** 排序对象,例如 { "sku": "desc" } */
order?: Record<string, any>; order?: any;
/** 排序字段(兼容旧入参) */ /** 排序字段(兼容旧入参) */
orderby?: string; orderby?: string;
/** 排序方式(兼容旧入参) */ /** 排序方式(兼容旧入参) */
@ -1576,9 +1580,9 @@ declare namespace API {
/** 客户ID,用于筛选订单 */ /** 客户ID,用于筛选订单 */
customer_id?: number; customer_id?: number;
/** 过滤条件对象 */ /** 过滤条件对象 */
where?: Record<string, any>; where?: any;
/** 排序对象,例如 { "sku": "desc" } */ /** 排序对象,例如 { "sku": "desc" } */
order?: Record<string, any>; order?: any;
/** 排序字段(兼容旧入参) */ /** 排序字段(兼容旧入参) */
orderby?: string; orderby?: string;
/** 排序方式(兼容旧入参) */ /** 排序方式(兼容旧入参) */
@ -1602,9 +1606,9 @@ declare namespace API {
/** 客户ID,用于筛选订单 */ /** 客户ID,用于筛选订单 */
customer_id?: number; customer_id?: number;
/** 过滤条件对象 */ /** 过滤条件对象 */
where?: Record<string, any>; where?: any;
/** 排序对象,例如 { "sku": "desc" } */ /** 排序对象,例如 { "sku": "desc" } */
order?: Record<string, any>; order?: any;
/** 排序字段(兼容旧入参) */ /** 排序字段(兼容旧入参) */
orderby?: string; orderby?: string;
/** 排序方式(兼容旧入参) */ /** 排序方式(兼容旧入参) */
@ -1628,9 +1632,9 @@ declare namespace API {
/** 客户ID,用于筛选订单 */ /** 客户ID,用于筛选订单 */
customer_id?: number; customer_id?: number;
/** 过滤条件对象 */ /** 过滤条件对象 */
where?: Record<string, any>; where?: any;
/** 排序对象,例如 { "sku": "desc" } */ /** 排序对象,例如 { "sku": "desc" } */
order?: Record<string, any>; order?: any;
/** 排序字段(兼容旧入参) */ /** 排序字段(兼容旧入参) */
orderby?: string; orderby?: string;
/** 排序方式(兼容旧入参) */ /** 排序方式(兼容旧入参) */
@ -1660,9 +1664,9 @@ declare namespace API {
/** 客户ID,用于筛选订单 */ /** 客户ID,用于筛选订单 */
customer_id?: number; customer_id?: number;
/** 过滤条件对象 */ /** 过滤条件对象 */
where?: Record<string, any>; where?: any;
/** 排序对象,例如 { "sku": "desc" } */ /** 排序对象,例如 { "sku": "desc" } */
order?: Record<string, any>; order?: any;
/** 排序字段(兼容旧入参) */ /** 排序字段(兼容旧入参) */
orderby?: string; orderby?: string;
/** 排序方式(兼容旧入参) */ /** 排序方式(兼容旧入参) */
@ -1686,9 +1690,9 @@ declare namespace API {
/** 客户ID,用于筛选订单 */ /** 客户ID,用于筛选订单 */
customer_id?: number; customer_id?: number;
/** 过滤条件对象 */ /** 过滤条件对象 */
where?: Record<string, any>; where?: any;
/** 排序对象,例如 { "sku": "desc" } */ /** 排序对象,例如 { "sku": "desc" } */
order?: Record<string, any>; order?: any;
/** 排序字段(兼容旧入参) */ /** 排序字段(兼容旧入参) */
orderby?: string; orderby?: string;
/** 排序方式(兼容旧入参) */ /** 排序方式(兼容旧入参) */
@ -1722,9 +1726,9 @@ declare namespace API {
/** 客户ID,用于筛选订单 */ /** 客户ID,用于筛选订单 */
customer_id?: number; customer_id?: number;
/** 过滤条件对象 */ /** 过滤条件对象 */
where?: Record<string, any>; where?: any;
/** 排序对象,例如 { "sku": "desc" } */ /** 排序对象,例如 { "sku": "desc" } */
order?: Record<string, any>; order?: any;
/** 排序字段(兼容旧入参) */ /** 排序字段(兼容旧入参) */
orderby?: string; orderby?: string;
/** 排序方式(兼容旧入参) */ /** 排序方式(兼容旧入参) */
@ -1753,9 +1757,9 @@ declare namespace API {
/** 客户ID,用于筛选订单 */ /** 客户ID,用于筛选订单 */
customer_id?: number; customer_id?: number;
/** 过滤条件对象 */ /** 过滤条件对象 */
where?: Record<string, any>; where?: any;
/** 排序对象,例如 { "sku": "desc" } */ /** 排序对象,例如 { "sku": "desc" } */
order?: Record<string, any>; order?: any;
/** 排序字段(兼容旧入参) */ /** 排序字段(兼容旧入参) */
orderby?: string; orderby?: string;
/** 排序方式(兼容旧入参) */ /** 排序方式(兼容旧入参) */
@ -1779,9 +1783,9 @@ declare namespace API {
/** 客户ID,用于筛选订单 */ /** 客户ID,用于筛选订单 */
customer_id?: number; customer_id?: number;
/** 过滤条件对象 */ /** 过滤条件对象 */
where?: Record<string, any>; where?: any;
/** 排序对象,例如 { "sku": "desc" } */ /** 排序对象,例如 { "sku": "desc" } */
order?: Record<string, any>; order?: any;
/** 排序字段(兼容旧入参) */ /** 排序字段(兼容旧入参) */
orderby?: string; orderby?: string;
/** 排序方式(兼容旧入参) */ /** 排序方式(兼容旧入参) */
@ -2400,9 +2404,9 @@ declare namespace API {
/** 客户ID,用于筛选订单 */ /** 客户ID,用于筛选订单 */
customer_id?: number; customer_id?: number;
/** 过滤条件对象 */ /** 过滤条件对象 */
where?: Record<string, any>; where?: any;
/** 排序对象,例如 { "sku": "desc" } */ /** 排序对象,例如 { "sku": "desc" } */
order?: Record<string, any>; order?: any;
/** 排序字段(兼容旧入参) */ /** 排序字段(兼容旧入参) */
orderby?: string; orderby?: string;
/** 排序方式(兼容旧入参) */ /** 排序方式(兼容旧入参) */