From 37e999bef93e513d0c5adc2e5672c44cdebce8bb Mon Sep 17 00:00:00 2001 From: tikkhun Date: Fri, 21 Nov 2025 15:21:42 +0800 Subject: [PATCH] =?UTF-8?q?refactor(=E8=AE=A2=E5=8D=95):=20=E9=87=8D?= =?UTF-8?q?=E6=9E=84=E8=AE=A2=E5=8D=95=E8=AF=A6=E6=83=85=E6=8A=BD=E5=B1=89?= =?UTF-8?q?=E7=BB=84=E4=BB=B6=E5=B9=B6=E7=A7=BB=E5=8A=A8=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将订单详情抽屉组件从 Order/List 移动到 Subscription/Orders 目录 提取 RelatedOrders 组件为独立文件 重构订单详情逻辑,保持功能不变但提高可维护性 --- src/pages/Order/List/OrderDetailDrawer.tsx | 381 ------------------ src/pages/Order/List/RelatedOrders.tsx | 55 --- src/pages/Order/List/index.tsx | 37 +- .../Subscription/Orders/OrderDetailDrawer.tsx | 51 +++ .../Subscription/Orders/RelatedOrders.tsx | 9 + 5 files changed, 70 insertions(+), 463 deletions(-) delete mode 100644 src/pages/Order/List/OrderDetailDrawer.tsx delete mode 100644 src/pages/Order/List/RelatedOrders.tsx diff --git a/src/pages/Order/List/OrderDetailDrawer.tsx b/src/pages/Order/List/OrderDetailDrawer.tsx deleted file mode 100644 index b58a880..0000000 --- a/src/pages/Order/List/OrderDetailDrawer.tsx +++ /dev/null @@ -1,381 +0,0 @@ -import React, { useEffect, useMemo, useRef, useState } from 'react'; -import { - App, - Button, - Card, - Divider, - Drawer, - Empty, - Popconfirm, - Space, - Tag, -} from 'antd'; -import { ActionType } from '@ant-design/pro-components'; -import { CopyOutlined, DownOutlined, FileDoneOutlined } from '@ant-design/icons'; - -// 服务器 API 引用(保持与原 index.tsx 一致) -import { - ordercontrollerChangestatus, - ordercontrollerGetorderdetail, - ordercontrollerSyncorderbyid, -} from '@/servers/api/order'; -import { logisticscontrollerDelshipment } from '@/servers/api/logistics'; - -// 工具与子组件 -import { formatShipmentState, formatSource } from '@/utils/format'; -import RelatedOrders from './RelatedOrders'; - -// 中文注释:为保持原文件结构简单,此处从 index.tsx 引入的子组件仍由原文件导出或保持原状 -// 若后续需要彻底解耦,可将 OrderNote / Shipping / SalesChange 也独立到文件 -// 当前按你的要求仅抽离详情 Drawer - -type OrderRecord = API.Order; - -interface OrderDetailDrawerProps { - tableRef: React.MutableRefObject; // 中文注释:列表刷新引用 - orderId: number; // 中文注释:订单主键 ID - record: OrderRecord; // 中文注释:订单行记录 - open: boolean; // 中文注释:是否打开抽屉 - onClose: () => void; // 中文注释:关闭抽屉回调 - setActiveLine: (id: number) => void; // 中文注释:高亮当前行 - OrderNoteComponent: React.ComponentType; // 中文注释:备注组件(从外部注入) - SalesChangeComponent: React.ComponentType; // 中文注释:换货组件(从外部注入) -} - -const OrderDetailDrawer: React.FC = ({ - tableRef, - orderId, - record, - open, - onClose, - setActiveLine, - OrderNoteComponent, - SalesChangeComponent, -}) => { - const { message } = App.useApp(); - const ref = useRef(); - const [detail, setDetail] = useState(null); - - // 中文注释:加载详情数据(与 index.tsx 中完全保持一致) - const initRequest = async () => { - const { data, success }: API.OrderDetailRes = - await ordercontrollerGetorderdetail({ orderId }); - if (!success || !data) return null; - // 中文注释:销售项合并 SKU,展示数量汇总 - data.sales = data.sales?.reduce( - (acc: API.OrderSale[], cur: API.OrderSale) => { - const idx = acc.findIndex((v: any) => v.productId === cur.productId); - if (idx === -1) acc.push(cur); - else acc[idx].quantity += cur.quantity; - return acc; - }, - [], - ); - return data; - }; - - useEffect(() => { - (async () => { - if (open && orderId) { - try { - const data = await initRequest(); - setDetail(data); - } catch (e) { - setDetail(null); - } - } else { - setDetail(null); - } - })(); - }, [open, orderId]); - - return ( - , - ...(['after_sale_pending', 'pending_reshipment'].includes( - record.orderStatus, - ) - ? [] - : [ - , - , - ]), - ...([ - 'processing', - 'pending_reshipment', - 'completed', - 'pending_refund', - ].includes(record.orderStatus) - ? [ - , - { - try { - const { success, message: errMsg } = - await ordercontrollerChangestatus( - { id: record.id }, - { status: 'after_sale_pending' }, - ); - if (!success) throw new Error(errMsg); - tableRef.current?.reload(); - } catch (error: any) { - message.error(error.message); - } - }} - > - - , - ] - : []), - ...(record.orderStatus === 'after_sale_pending' - ? [ - , - { - try { - const { success, message: errMsg } = - await ordercontrollerChangestatus( - { id: record.id }, - { status: 'cancelled' }, - ); - if (!success) throw new Error(errMsg); - tableRef.current?.reload(); - } catch (error: any) { - message.error(error.message); - } - }} - > - - , - , - { - try { - const { success, message: errMsg } = - await ordercontrollerChangestatus( - { id: record.id }, - { status: 'refund_requested' }, - ); - if (!success) throw new Error(errMsg); - tableRef.current?.reload(); - } catch (error: any) { - message.error(error.message); - } - }} - > - - , - , - { - try { - const { success, message: errMsg } = - await ordercontrollerChangestatus( - { id: record.id }, - { status: 'completed' }, - ); - if (!success) throw new Error(errMsg); - tableRef.current?.reload(); - } catch (error: any) { - message.error(error.message); - } - }} - > - - , - ] - : []), - ]} - > - {(() => { setActiveLine(record.id as number); return null; })()} - {/** 中文注释:优先使用详情数据,其次使用列表行数据 */} - {(() => { - const drec: any = detail || record; - {/* 中文注释:基本信息展示(保持原有格式) */} - return (<> -
- - {drec?.orderStatus} - {formatSource(drec.source_type, drec.utm_source)} - -
- - {/* 中文注释:原始订单行项目 */} -
-
原始订单
- {Array.isArray((drec as any)?.items) && drec.items.length > 0 ? ( -
    - {drec.items.map((item: any) => ( -
  • - {item.name}:{item.quantity} -
  • - ))} -
- ) : ( - - )} -
- - {/* 中文注释:关联(订阅/订单),使用已存在的 RelatedOrders 组件 */} -
-
关联
- -
- - {/* 中文注释:订单内容(销售项) */} -
-
订单内容
- {Array.isArray((drec as any)?.sales) && drec.sales.length > 0 ? ( -
    - {drec.sales.map((item: any) => ( -
  • - {item.name}:{item.quantity} -
  • - ))} -
- ) : ( - - )} -
- - {/* 中文注释:备注 */} -
-
备注
- {Array.isArray((drec as any)?.notes) && drec.notes.length > 0 ? ( -
- {drec.notes.map((note: any) => ( -
-
- {note.username} - {note.createdAt} -
-
{note.content}
-
- ))} -
- ) : ( - - )} -
- - {/* 中文注释:物流信息 */} -
-
物流信息
- {Array.isArray((drec as any)?.shipment) && drec.shipment.length > 0 ? ( -
- {(drec as any).shipment.map((v: any) => ( - - {v.tracking_provider} - {v.primary_tracking_number} - { - try { - await navigator.clipboard.writeText(v.tracking_url); - message.success('复制成功!'); - } catch (err) { - message.error('复制失败!'); - } - }} - /> - - } - actions={ - v.state === 'waiting-for-scheduling' || v.state === 'waiting-for-transit' - ? [ - { - try { - const { success, message: errMsg } = await logisticscontrollerDelshipment({ id: v.id }); - if (!success) throw new Error(errMsg); - tableRef.current?.reload(); - } catch (error: any) { - message.error(error.message); - } - }} - > - 取消运单 - , - ] - : [] - } - > -
订单号: {Array.isArray(v?.orderIds) ? v.orderIds.join(',') : '-'}
- {Array.isArray(v?.items) && - v.items.map((item: any) => ( -
- {item.name}: {item.quantity} -
- ))} -
- ))} -
- ) : ( - - )} -
- - {/* 中文注释:换货(外部传入组件) */} -
- -
- ); - })()} -
- ); -}; - -export default OrderDetailDrawer; \ No newline at end of file diff --git a/src/pages/Order/List/RelatedOrders.tsx b/src/pages/Order/List/RelatedOrders.tsx deleted file mode 100644 index ed94eb7..0000000 --- a/src/pages/Order/List/RelatedOrders.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import React from 'react'; -import { Empty, Tag } from 'antd'; -import dayjs from 'dayjs'; -import relativeTime from 'dayjs/plugin/relativeTime'; - -dayjs.extend(relativeTime); - -/** - * RelatedOrders 表格组件 - * 用于展示订单详情中的关联数据(订阅/订单),按统一表格样式渲染 - * 中文注释:本组件将订阅与订单统一归一化为五列展示,便于快速浏览 - */ -const RelatedOrders: React.FC<{ data?: any[] }> = ({ data = [] }) => { - const rows = (Array.isArray(data) ? data : []).map((it: any) => { - const isSubscription = !!it?.externalSubscriptionId || !!it?.billing_period || !!it?.line_items; - const number = isSubscription ? `#${it?.externalSubscriptionId || it?.id}` : `#${it?.externalOrderId || it?.id}`; - const relationship = isSubscription ? 'Subscription' : 'Order'; - const dateRaw = it?.start_date || it?.date_created || it?.createdAt || it?.updatedAt; - const dateText = dateRaw ? dayjs(dateRaw).fromNow() : '-'; - const status = (isSubscription ? it?.status : it?.orderStatus) || '-'; - const statusLower = String(status).toLowerCase(); - const color = statusLower === 'active' ? 'green' : statusLower === 'cancelled' ? 'red' : 'default'; - const totalNum = Number(it?.total || 0); - const totalText = isSubscription ? `$${totalNum.toFixed(2)} / ${it?.billing_period || 'period'}` : `$${totalNum.toFixed(2)}`; - return { key: `${isSubscription ? 'sub' : 'order'}-${it?.id}`, number, relationship, dateText, status, color, totalText }; - }); - - if (rows.length === 0) return ; - - return ( -
- {/* 表头(英文文案,符合国际化默认英文的要求) */} -
-
订单编号
-
关系
-
日期
-
状态
-
金额
-
-
- {rows.map((r) => ( -
- -
{r.relationship}
-
{r.dateText}
-
{r.status}
-
{r.totalText}
-
- ))} -
-
- ); -}; - -export default RelatedOrders; diff --git a/src/pages/Order/List/index.tsx b/src/pages/Order/List/index.tsx index 76a7862..d4d9be5 100644 --- a/src/pages/Order/List/index.tsx +++ b/src/pages/Order/List/index.tsx @@ -81,6 +81,7 @@ import { } from 'antd'; import Item from 'antd/es/list/Item'; <<<<<<< HEAD +<<<<<<< HEAD import RelatedOrders from '../../Subscription/Orders/RelatedOrders'; ======= import RelatedOrders from './RelatedOrders'; @@ -89,6 +90,9 @@ import RelatedOrders from './RelatedOrders'; ======= import OrderDetailDrawer from './OrderDetailDrawer'; >>>>>>> 1f4128f (refactor(订单): 抽离订单详情抽屉为独立组件并复用) +======= +import RelatedOrders from '../../Subscription/Orders/RelatedOrders'; +>>>>>>> d98e843 (refactor(订单): 重构订单详情抽屉组件并移动相关文件) import React, { useMemo, useRef, useState } from 'react'; import { printPDF } from '@/utils/util'; @@ -97,9 +101,6 @@ const ListPage: React.FC = () => { const [activeKey, setActiveKey] = useState('all'); const [count, setCount] = useState([]); const [activeLine, setActiveLine] = useState(-1); - const [detailOpen, setDetailOpen] = useState(false); - const [detailRecord, setDetailRecord] = useState(null); - const [detailOrderId, setDetailOrderId] = useState(null); const tabs: TabsProps['items'] = useMemo(() => { const total = count.reduce((acc, cur) => acc + Number(cur.count), 0); const tabs = [ @@ -323,31 +324,13 @@ const ListPage: React.FC = () => { ) : ( <> )} - - {detailRecord && detailOrderId !== null && ( - setDetailOpen(false)} - tableRef={actionRef} - orderId={detailOrderId as number} - record={detailRecord as any} - setActiveLine={setActiveLine} - OrderNoteComponent={OrderNote} - SalesChangeComponent={SalesChange} - /> - )} + record={record} + tableRef={actionRef} + orderId={record.id as number} + setActiveLine={setActiveLine} + /> >>>>>> d98e843 (refactor(订单): 重构订单详情抽屉组件并移动相关文件) import { ordercontrollerChangestatus, ordercontrollerGetorderdetail, @@ -27,13 +31,18 @@ import { formatShipmentState, formatSource } from '@/utils/format'; import RelatedOrders from './RelatedOrders'; import { ORDER_STATUS_ENUM } from '@/constants'; +<<<<<<< HEAD // 中文注释:为保持原文件结构简单,此处从 index.tsx 引入的子组件仍由原文件导出或保持原状 +======= +// 中文注释:为保持原文件结构简单,此处从 index.tsx 引入的子组件仍由原文件导出或保持原状 +>>>>>>> d98e843 (refactor(订单): 重构订单详情抽屉组件并移动相关文件) // 若后续需要彻底解耦,可将 OrderNote / Shipping / SalesChange 也独立到文件 // 当前按你的要求仅抽离详情 Drawer type OrderRecord = API.Order; interface OrderDetailDrawerProps { +<<<<<<< HEAD tableRef: React.MutableRefObject; // 中文注释:列表刷新引用 orderId: number; // 中文注释:订单主键 ID record: OrderRecord; // 中文注释:订单行记录 @@ -42,6 +51,16 @@ interface OrderDetailDrawerProps { setActiveLine: (id: number) => void; // 中文注释:高亮当前行 OrderNoteComponent: React.ComponentType; // 中文注释:备注组件(从外部注入) SalesChangeComponent: React.ComponentType; // 中文注释:换货组件(从外部注入) +======= + tableRef: React.MutableRefObject; // 中文注释:列表刷新引用 + orderId: number; // 中文注释:订单主键 ID + record: OrderRecord; // 中文注释:订单行记录 + open: boolean; // 中文注释:是否打开抽屉 + onClose: () => void; // 中文注释:关闭抽屉回调 + setActiveLine: (id: number) => void; // 中文注释:高亮当前行 + OrderNoteComponent: React.ComponentType; // 中文注释:备注组件(从外部注入) + SalesChangeComponent: React.ComponentType; // 中文注释:换货组件(从外部注入) +>>>>>>> d98e843 (refactor(订单): 重构订单详情抽屉组件并移动相关文件) } const OrderDetailDrawer: React.FC = ({ @@ -57,7 +76,11 @@ const OrderDetailDrawer: React.FC = ({ const { message } = App.useApp(); const ref = useRef(); +<<<<<<< HEAD // 中文注释:加载详情数据(与 index.tsx 中完全保持一致) +======= + // 中文注释:加载详情数据(与 index.tsx 中完全保持一致) +>>>>>>> d98e843 (refactor(订单): 重构订单详情抽屉组件并移动相关文件) const initRequest = async () => { const { data, success }: API.OrderDetailRes = await ordercontrollerGetorderdetail({ orderId }); if (!success || !data) return { data: {} } as any; @@ -84,7 +107,11 @@ const OrderDetailDrawer: React.FC = ({ size="large" onClose={onClose} footer={[ +<<<<<<< HEAD // 中文注释:备注组件(外部传入以避免循环依赖) +======= + // 中文注释:备注组件(外部传入以避免循环依赖) +>>>>>>> d98e843 (refactor(订单): 重构订单详情抽屉组件并移动相关文件) , ...(['after_sale_pending', 'pending_reshipment'].includes( record.orderStatus, @@ -241,6 +268,7 @@ const OrderDetailDrawer: React.FC = ({ (
+<<<<<<< HEAD
company:{r?.shipping?.company || r?.billing?.company || '-'}
first_name:{r?.shipping?.first_name || r?.billing?.first_name || '-'}
last_name:{r?.shipping?.last_name || r?.billing?.last_name || '-'}
@@ -250,12 +278,27 @@ const OrderDetailDrawer: React.FC = ({
postcode:{r?.shipping?.postcode || r?.billing?.postcode || '-'}
phone:{r?.shipping?.phone || r?.billing?.phone || '-'}
address_1:{r?.shipping?.address_1 || r?.billing?.address_1 || '-'}
+======= +
company:{r?.shipping?.company || r?.billing?.company || '-'}
+
first_name:{r?.shipping?.first_name || r?.billing?.first_name || '-'}
+
last_name:{r?.shipping?.last_name || r?.billing?.last_name || '-'}
+
country:{r?.shipping?.country || r?.billing?.country || '-'}
+
state:{r?.shipping?.state || r?.billing?.state || '-'}
+
city:{r?.shipping?.city || r?.billing?.city || '-'}
+
postcode:{r?.shipping?.postcode || r?.billing?.postcode || '-'}
+
phone:{r?.shipping?.phone || r?.billing?.phone || '-'}
+
address_1:{r?.shipping?.address_1 || r?.billing?.address_1 || '-'}
+>>>>>>> d98e843 (refactor(订单): 重构订单详情抽屉组件并移动相关文件)
)} /> (
    {(r?.items || []).map((item: any) => ( +<<<<<<< HEAD
  • {item.name}:{item.quantity}
  • +======= +
  • {item.name}:{item.quantity}
  • +>>>>>>> d98e843 (refactor(订单): 重构订单详情抽屉组件并移动相关文件) ))}
)} /> @@ -265,7 +308,11 @@ const OrderDetailDrawer: React.FC = ({ (
    {(r?.sales || []).map((item: any) => ( +<<<<<<< HEAD
  • {item.name}:{item.quantity}
  • +======= +
  • {item.name}:{item.quantity}
  • +>>>>>>> d98e843 (refactor(订单): 重构订单详情抽屉组件并移动相关文件) ))}
)} /> @@ -310,7 +357,11 @@ const OrderDetailDrawer: React.FC = ({ ] : [] } > +<<<<<<< HEAD
订单号: {Array.isArray(v?.orderIds) ? v.orderIds.join(',') : '-'}
+======= +
订单号: {Array.isArray(v?.orderIds) ? v.orderIds.join(',') : '-'}
+>>>>>>> d98e843 (refactor(订单): 重构订单详情抽屉组件并移动相关文件) {Array.isArray(v?.items) && v.items.map((item: any) => (
{item.name}: {item.quantity}
))} diff --git a/src/pages/Subscription/Orders/RelatedOrders.tsx b/src/pages/Subscription/Orders/RelatedOrders.tsx index 57470ab..028af20 100644 --- a/src/pages/Subscription/Orders/RelatedOrders.tsx +++ b/src/pages/Subscription/Orders/RelatedOrders.tsx @@ -7,8 +7,13 @@ dayjs.extend(relativeTime); /** * RelatedOrders 表格组件 +<<<<<<< HEAD * 用于展示订单详情中的关联数据(订阅/订单),按统一表格样式渲染 * 中文注释:本组件将订阅与订单统一归一化为五列展示,便于快速浏览 +======= + * 用于展示订单详情中的关联数据(订阅/订单),按统一表格样式渲染 + * 中文注释:本组件将订阅与订单统一归一化为五列展示,便于快速浏览 +>>>>>>> d98e843 (refactor(订单): 重构订单详情抽屉组件并移动相关文件) */ const RelatedOrders: React.FC<{ data?: any[] }> = ({ data = [] }) => { const rows = (Array.isArray(data) ? data : []).map((it: any) => { @@ -29,7 +34,11 @@ const RelatedOrders: React.FC<{ data?: any[] }> = ({ data = [] }) => { return (
+<<<<<<< HEAD {/* 表头(英文文案,符合国际化默认英文的要求) */} +======= + {/* 表头(英文文案,符合国际化默认英文的要求) */} +>>>>>>> d98e843 (refactor(订单): 重构订单详情抽屉组件并移动相关文件)
订单编号
关系