From d10052104a8a1a5f88d1bb7617a898225a63273f Mon Sep 17 00:00:00 2001 From: tikkhun Date: Thu, 18 Dec 2025 15:23:31 +0800 Subject: [PATCH] =?UTF-8?q?feat(shop):=20=E6=96=B0=E5=A2=9E=E8=AF=84?= =?UTF-8?q?=E8=AE=BA=E7=AE=A1=E7=90=86=E5=8A=9F=E8=83=BD=E5=B9=B6=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E5=BA=97=E9=93=BA=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit refactor(api): 重构API请求参数处理逻辑 style(product): 调整产品表单字段顺序 fix(orders): 修正订单列表分页参数 perf(logistics): 优化批量删除操作性能 docs(typings): 更新API类型定义 chore: 移除无用代码和注释 --- .umirc.ts | 5 - src/app.tsx | 2 +- src/pages/Product/Permutation/index.tsx | 40 +- src/pages/Site/List/index.tsx | 377 +++--------------- src/pages/Site/Shop/Customers/index.tsx | 80 ++-- src/pages/Site/Shop/EditSiteForm.tsx | 158 ++++++++ src/pages/Site/Shop/Layout.tsx | 135 ++++--- src/pages/Site/Shop/Logistics/index.tsx | 33 +- src/pages/Site/Shop/Orders/index.tsx | 26 +- src/pages/Site/Shop/Products/index.tsx | 165 +++++++- src/pages/Site/Shop/Reviews/ReviewForm.tsx | 29 ++ src/pages/Site/Shop/Reviews/index.tsx | 101 +++++ src/pages/Site/Shop/Subscriptions/index.tsx | 60 +-- .../Site/Shop/components/Order/Forms.tsx | 3 +- .../Site/Shop/components/Product/Forms.tsx | 11 +- src/servers/api/index.ts | 2 + src/servers/api/review.ts | 80 ++++ src/servers/api/siteApi.ts | 126 ++++++ src/servers/api/typings.d.ts | 318 +++++++++++++-- 19 files changed, 1179 insertions(+), 572 deletions(-) create mode 100644 src/pages/Site/Shop/EditSiteForm.tsx create mode 100644 src/pages/Site/Shop/Reviews/ReviewForm.tsx create mode 100644 src/pages/Site/Shop/Reviews/index.tsx create mode 100644 src/servers/api/review.ts diff --git a/.umirc.ts b/.umirc.ts index a04289d..aa54802 100644 --- a/.umirc.ts +++ b/.umirc.ts @@ -310,11 +310,6 @@ export default defineConfig({ changeOrigin: true, pathRewrite: { '^/api': '' }, }, - '/site-api': { - target: UMI_APP_API_URL, - changeOrigin: true, - pathRewrite: { '^/site-api': '/site-api' }, - }, }, npmClient: 'pnpm', }); diff --git a/src/app.tsx b/src/app.tsx index fc9f857..6144a5f 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -72,7 +72,7 @@ export const layout = (): ProLayoutProps => { }; export const request: RequestConfig = { - baseURL: UMI_APP_API_URL, + baseURL: '/api', // baseURL: UMI_APP_API_URL, requestInterceptors: [ (url: string, options: any) => { const token = localStorage.getItem('token'); diff --git a/src/pages/Product/Permutation/index.tsx b/src/pages/Product/Permutation/index.tsx index 06f40ca..033ccc9 100644 --- a/src/pages/Product/Permutation/index.tsx +++ b/src/pages/Product/Permutation/index.tsx @@ -296,45 +296,7 @@ const PermutationPage: React.FC = () => { }} scroll={{ x: 'max-content' }} search={false} - toolBarRender={() => [ - - ]} + toolBarRender={false} /> )} diff --git a/src/pages/Site/List/index.tsx b/src/pages/Site/List/index.tsx index 36ab559..76211c6 100644 --- a/src/pages/Site/List/index.tsx +++ b/src/pages/Site/List/index.tsx @@ -1,17 +1,21 @@ import { ActionType, - DrawerForm, ProColumns, - ProFormDependency, - ProFormInstance, - ProFormSelect, - ProFormSwitch, - ProFormText, ProTable, } from '@ant-design/pro-components'; +import { + sitecontrollerCreate, + sitecontrollerDisable, + sitecontrollerList, + sitecontrollerUpdate, +} from '@/servers/api/site'; +import { wpproductcontrollerSyncproducts } from '@/servers/api/wpProduct'; +import { ordercontrollerSyncorder } from '@/servers/api/order'; +import { subscriptioncontrollerSync } from '@/servers/api/subscription'; import { request } from '@umijs/max'; import { Button, message, notification, Popconfirm, Space, Tag } from 'antd'; -import React, { useEffect, useRef, useState } from 'react'; +import React, { useRef, useState } from 'react'; +import EditSiteForm from '../Shop/EditSiteForm'; // 引入重构后的表单组件 // 区域数据项类型 interface AreaItem { @@ -26,11 +30,12 @@ interface StockPointItem { } // 站点数据项类型(前端不包含密钥字段,后端列表不返回密钥) -interface SiteItem { +export interface SiteItem { id: number; name: string; description?: string; apiUrl?: string; + websiteUrl?: string; // 网站地址 type?: 'woocommerce' | 'shopyy'; skuPrefix?: string; isDisabled: number; @@ -38,24 +43,8 @@ interface SiteItem { stockPoints?: StockPointItem[]; } -// 创建/更新表单的值类型,包含可选的密钥字段 -interface SiteFormValues { - name: string; - description?: string; - apiUrl?: string; - type?: 'woocommerce' | 'shopyy'; - isDisabled?: boolean; - consumerKey?: string; // WooCommerce REST API 的 consumer key - consumerSecret?: string; // WooCommerce REST API 的 consumer secret - token?: string; // Shopyy token - skuPrefix?: string; - areas?: string[]; - stockPointIds?: number[]; -} - const SiteList: React.FC = () => { const actionRef = useRef(); - const formRef = useRef(); const [open, setOpen] = useState(false); const [editing, setEditing] = useState(null); const [selectedRowKeys, setSelectedRowKeys] = useState([]); @@ -73,24 +62,27 @@ const SiteList: React.FC = () => { try { for (const id of ids) { // 同步产品 - const prodRes = await request(`/wp_product/sync/${id}`, { method: 'POST' }); - if (prodRes) { - stats.products.success += prodRes.successCount || 0; - stats.products.fail += prodRes.failureCount || 0; + const prodRes = await wpproductcontrollerSyncproducts({ siteId: id }); + if (prodRes.success) { + stats.products.success += 1; + } else { + stats.products.fail += 1; } // 同步订单 - const orderRes = await request(`/order/syncOrder/${id}`, { method: 'POST' }); - if (orderRes) { - stats.orders.success += orderRes.successCount || 0; - stats.orders.fail += orderRes.failureCount || 0; + const orderRes = await ordercontrollerSyncorder({ siteId: id }); + if (orderRes.success) { + stats.orders.success += 1; + } else { + stats.orders.fail += 1; } // 同步订阅 - const subRes = await request(`/subscription/sync/${id}`, { method: 'POST' }); - if (subRes) { - stats.subscriptions.success += subRes.successCount || 0; - stats.subscriptions.fail += subRes.failureCount || 0; + const subRes = await subscriptioncontrollerSync({ siteId: id }); + if (subRes.success) { + stats.subscriptions.success += 1; + } else { + stats.subscriptions.fail += 1; } } hide(); @@ -115,39 +107,6 @@ const SiteList: React.FC = () => { } }; - useEffect(() => { - if (!open) return; - if (editing) { - formRef.current?.setFieldsValue({ - name: editing.name, - description: editing.description, - apiUrl: editing.apiUrl, - type: editing.type, - skuPrefix: editing.skuPrefix, - isDisabled: !!editing.isDisabled, - consumerKey: undefined, - consumerSecret: undefined, - token: undefined, - areas: editing.areas?.map((area) => area.code) ?? [], - stockPointIds: editing.stockPoints?.map((sp) => sp.id) ?? [], - }); - } else { - formRef.current?.setFieldsValue({ - name: undefined, - description: undefined, - apiUrl: undefined, - type: 'woocommerce', - skuPrefix: undefined, - isDisabled: false, - consumerKey: undefined, - consumerSecret: undefined, - token: undefined, - areas: [], - stockPointIds: [], - }); - } - }, [open, editing]); - // 表格列定义 const columns: ProColumns[] = [ { @@ -160,6 +119,13 @@ const SiteList: React.FC = () => { { title: '名称', dataIndex: 'name', width: 220 }, { title: '描述', dataIndex: 'description', width: 220, hideInSearch: true }, { title: 'API 地址', dataIndex: 'apiUrl', width: 280, hideInSearch: true }, + { + title: '网站地址', + dataIndex: 'websiteUrl', + width: 280, + hideInSearch: true, + render: (text) => {text} + }, { title: 'SKU 前缀', dataIndex: 'skuPrefix', @@ -176,24 +142,6 @@ const SiteList: React.FC = () => { { label: 'Shopyy', value: 'shopyy' }, ], }, - // { - // title: '区域', - // dataIndex: 'areas', - // width: 200, - // hideInSearch: true, - // render: (_, row) => { - // if (!row.areas || row.areas.length === 0) { - // return 全球; - // } - // return ( - // - // {row.areas.map((area) => ( - // {area.name} - // ))} - // - // ); - // }, - // }, { title: '关联仓库', dataIndex: 'stockPoints', @@ -254,10 +202,7 @@ const SiteList: React.FC = () => { } onConfirm={async () => { try { - await request(`/site/disable/${row.id}`, { - method: 'PUT', - data: { disabled: !row.isDisabled }, - }); + await sitecontrollerDisable({ id: String(row.id) }, { disabled: !row.isDisabled }); message.success('更新成功'); actionRef.current?.reload(); } catch (e: any) { @@ -277,21 +222,17 @@ const SiteList: React.FC = () => { // 表格数据请求 const tableRequest = async (params: Record) => { try { - const { current = 1, pageSize = 10, name, type } = params; - const resp = await request('/site/list', { - method: 'GET', - params: { - current, - pageSize, - keyword: name || undefined, - type: type || undefined, - }, + const { current, pageSize, name, type } = params; + const resp = await sitecontrollerList({ + current, + pageSize, + keyword: name || undefined, + type: type || undefined, }); - const { success, data, message: errMsg } = resp as any; - if (!success) throw new Error(errMsg || '获取失败'); + // 假设 resp 直接就是后端返回的结构,包含 items 和 total return { - data: (data?.items ?? []) as SiteItem[], - total: data?.total ?? 0, + data: (resp?.data?.items ?? []) as SiteItem[], + total: resp?.data?.total ?? 0, success: true, }; } catch (e: any) { @@ -300,80 +241,20 @@ const SiteList: React.FC = () => { } }; - // 提交创建/更新逻辑;编辑时未填写密钥则不提交(保持原值) - const handleSubmit = async (values: SiteFormValues) => { + const handleFinish = async (values: any) => { try { - const isShopyy = values.type === 'shopyy'; - const apiUrl = isShopyy ? 'https://openapi.oemapps.com' : values.apiUrl; - if (editing) { - const payload: Record = { - // 仅提交存在的字段,避免覆盖为 null/空 - ...(values.name ? { name: values.name } : {}), - ...(values.description ? { description: values.description } : {}), - ...(apiUrl ? { apiUrl: apiUrl } : {}), - ...(values.type ? { type: values.type } : {}), - ...(typeof values.isDisabled === 'boolean' - ? { isDisabled: values.isDisabled } - : {}), - ...(values.skuPrefix ? { skuPrefix: values.skuPrefix } : {}), - areas: values.areas ?? [], - stockPointIds: values.stockPointIds ?? [], - }; - - if (isShopyy) { - if (values.token && values.token.trim()) { - payload.token = values.token.trim(); - } - } else { - // 仅当输入了新密钥时才提交,未输入则保持原本值 - if (values.consumerKey && values.consumerKey.trim()) { - payload.consumerKey = values.consumerKey.trim(); - } - if (values.consumerSecret && values.consumerSecret.trim()) { - payload.consumerSecret = values.consumerSecret.trim(); - } - } - - await request(`/site/update/${editing.id}`, { - method: 'PUT', - data: payload, - }); + await sitecontrollerUpdate({ id: String(editing.id) }, values); + message.success('更新成功'); } else { - if (isShopyy) { - if (!values.token) { - throw new Error('Token is required for Shopyy'); - } - } else { - // 新增站点时要求填写 consumerKey 和 consumerSecret - if (!values.consumerKey || !values.consumerSecret) { - throw new Error('Consumer Key and Secret are required for WooCommerce'); - } - } - - await request('/site/create', { - method: 'POST', - data: { - name: values.name, - description: values.description, - apiUrl: apiUrl, - type: values.type || 'woocommerce', - consumerKey: isShopyy ? undefined : values.consumerKey, - consumerSecret: isShopyy ? undefined : values.consumerSecret, - token: isShopyy ? values.token : undefined, - skuPrefix: values.skuPrefix, - areas: values.areas ?? [], - stockPointIds: values.stockPointIds ?? [], - }, - }); + await sitecontrollerCreate(values); + message.success('创建成功'); } - message.success('提交成功'); setOpen(false); - setEditing(null); actionRef.current?.reload(); return true; - } catch (e: any) { - message.error(e?.message || '提交失败'); + } catch (error: any) { + message.error(error.message || '操作失败'); return false; } }; @@ -381,7 +262,7 @@ const SiteList: React.FC = () => { return ( <> - scroll={{ x: 'max-content' }} + scroll={{ x: 'max-content' }} actionRef={actionRef} rowKey="id" columns={columns} @@ -392,161 +273,35 @@ const SiteList: React.FC = () => { }} toolBarRender={() => [ , - // 同步包括 orders subscriptions 等等 , ]} /> - - title={editing ? '编辑站点' : '新增站点'} + - {/* 站点名称,必填 */} - - - - - {/* 仓库选择 */} - { - try { - const resp = await request('/stock/stock-point/all', { - method: 'GET', - }); - if (resp.success) { - return resp.data.map((item: any) => ({ - label: item.name, - value: item.id, - })); - } - return []; - } catch (e) { - return []; - } - }} - /> - - {/* 区域选择 - 暂时隐藏 */} - {/* { - try { - const resp = await request('/area', { - method: 'GET', - params: { pageSize: 1000 }, - }); - if (resp.success) { - return resp.data.list.map((area: AreaItem) => ({ - label: area.name, - value: area.code, - })); - } - return []; - } catch (e) { - return []; - } - }} - /> */} - - {/* 平台类型选择 */} - - - - {({ type }) => { - const isShopyy = type === 'shopyy'; - return isShopyy ? ( - <> - - - - ) : ( - <> - - {/* WooCommerce REST consumer key */} - - {/* WooCommerce REST consumer secret */} - - - ); - }} - - - {editing && } - - - + onOpenChange={(visible) => { + setOpen(visible); + if (!visible) { + setEditing(null); + } + }} + initialValues={editing} + isEdit={!!editing} + onFinish={handleFinish} + /> ); }; diff --git a/src/pages/Site/Shop/Customers/index.tsx b/src/pages/Site/Shop/Customers/index.tsx index 7d6e414..e95618a 100644 --- a/src/pages/Site/Shop/Customers/index.tsx +++ b/src/pages/Site/Shop/Customers/index.tsx @@ -144,18 +144,6 @@ const CustomerPage: React.FC = () => { return {role}; }, }, - { - title: '订单数', - dataIndex: 'orders', - sorter: true, - hideInSearch: true, - }, - { - title: '总花费', - dataIndex: 'total_spend', - sorter: true, - hideInSearch: true, - }, { title: '账单地址', dataIndex: 'billing', @@ -173,23 +161,6 @@ const CustomerPage: React.FC = () => { ); }, }, - { - title: '收货地址', - dataIndex: 'shipping', - hideInSearch: true, - render: (_, record) => { - const { shipping } = record; - if (!shipping) return '-'; - return ( -
-
{shipping.address_1} {shipping.address_2}
-
{shipping.city}, {shipping.state}, {shipping.postcode}
-
{shipping.country}
-
{shipping.phone}
-
- ); - }, - }, { title: '注册时间', dataIndex: 'date_created', @@ -268,21 +239,9 @@ const CustomerPage: React.FC = () => { } const data = response.data; - let items = (data?.items || []) as any[]; - if (sort && typeof sort === 'object') { - const [field, dir] = Object.entries(sort)[0] || []; - if (field === 'orders' || field === 'total_spend') { - const isDesc = dir === 'descend'; - items = items.slice().sort((a, b) => { - const av = Number(a?.[field] ?? 0); - const bv = Number(b?.[field] ?? 0); - return isDesc ? bv - av : av - bv; - }); - } - } return { total: data?.total || 0, - data: items, + data: data?.items || [], success: true, }; }} @@ -411,19 +370,42 @@ const CustomerPage: React.FC = () => { search={false} pagination={{ pageSize: 20 }} columns={[ - { title: '订单ID', dataIndex: 'id' }, - { title: '订单号', dataIndex: 'number' }, - { title: '状态', dataIndex: 'status' }, - { title: '币种', dataIndex: 'currency' }, - { title: '金额', dataIndex: 'total' }, - { title: '创建时间', dataIndex: 'date_created', valueType: 'dateTime' }, + { title: '订单号', dataIndex: 'number', copyable: true }, + { + title: '客户邮箱', + dataIndex: 'email', + copyable: true, + render: () => { + return ordersCustomer?.email; + }, + }, + { title: '支付时间', dataIndex: 'date_paid', valueType: 'dateTime', hideInSearch: true }, + { title: '订单金额', dataIndex: 'total', hideInSearch: true }, + { title: '状态', dataIndex: 'status', hideInSearch: true }, + { title: '来源', dataIndex: 'created_via', hideInSearch: true }, + { + title: '订单内容', + dataIndex: 'line_items', + hideInSearch: true, + render: (_, record) => { + return ( +
+ {record.line_items?.map((item: any) => ( +
+ {item.name} x {item.quantity} +
+ ))} +
+ ); + }, + }, ]} request={async (params) => { if (!siteId || !ordersCustomer?.id) return { data: [], total: 0, success: true }; const res = await request(`/site-api/${siteId}/customers/${ordersCustomer.id}/orders`, { params: { page: params.current, - page_size: params.pageSize, + per_page: params.pageSize, }, }); if (!res?.success) { diff --git a/src/pages/Site/Shop/EditSiteForm.tsx b/src/pages/Site/Shop/EditSiteForm.tsx new file mode 100644 index 0000000..de5ca03 --- /dev/null +++ b/src/pages/Site/Shop/EditSiteForm.tsx @@ -0,0 +1,158 @@ + +import { + DrawerForm, + ProFormDependency, + ProFormSelect, + ProFormSwitch, + ProFormText, + ProFormTextArea, +} from '@ant-design/pro-components'; +import { Form } from 'antd'; +import React, { useEffect } from 'react'; +import { areacontrollerGetarealist } from '@/servers/api/area'; +import { stockcontrollerGetallstockpoints } from '@/servers/api/stock'; + +// 定义组件的 props 类型 +interface EditSiteFormProps { + open: boolean; // 控制抽屉表单的显示和隐藏 + onOpenChange: (visible: boolean) => void; // 当抽屉表单显示状态改变时调用 + onFinish: (values: any) => Promise; // 表单提交成功时的回调 + initialValues?: any; // 表单的初始值 + isEdit: boolean; // 标记当前是编辑模式还是新建模式 +} + +const EditSiteForm: React.FC = ({ + open, + onOpenChange, + onFinish, + initialValues, + isEdit, +}) => { + const [form] = Form.useForm(); + + // 当 initialValues 或 open 状态变化时, 更新表单的值 + useEffect(() => { + // 如果抽屉是打开的 + if (open) { + // 如果是编辑模式并且有初始值 + if (isEdit && initialValues) { + // 编辑模式下, 设置表单值为初始值 + form.setFieldsValue({ + ...initialValues, + isDisabled: initialValues.isDisabled === 1, // 将后端的 1/0 转换成 true/false + }); + } else { + // 新建模式或抽屉关闭时, 重置表单 + form.resetFields(); + } + } + }, [initialValues, isEdit, open, form]); + + return ( + { + // 直接将表单值传递给 onFinish 回调 + // 后端需要布尔值, 而 ProFormSwitch 已经提供了布尔值 + return onFinish(values); + }} + layout="vertical" + > + + + + + + {/* 根据选择的平台动态显示不同的认证字段 */} + + {({ type }) => { + // 如果平台是 woocommerce + if (type === 'woocommerce') { + return ( + <> + + + + ); + } + // 如果平台是 shopyy + if (type === 'shopyy') { + return ( + + ); + } + return null; + }} + + + { + // 从后端接口获取区域数据 + const res = await areacontrollerGetarealist({ pageSize: 1000 }); + // areacontrollerGetarealist 直接返回数组, 所以不需要 .data.list + return res.map((area: any) => ({ label: area.name, value: area.code })); + }} + /> + { + // 从后端接口获取仓库数据 + const res = await stockcontrollerGetallstockpoints(); + // 使用可选链和空值合并运算符来安全地处理可能未定义的数据 + return res?.data?.map((sp: any) => ({ label: sp.name, value: sp.id })) ?? []; + }} + /> + + + ); +}; + +export default EditSiteForm; diff --git a/src/pages/Site/Shop/Layout.tsx b/src/pages/Site/Shop/Layout.tsx index 79ef6f7..018d853 100644 --- a/src/pages/Site/Shop/Layout.tsx +++ b/src/pages/Site/Shop/Layout.tsx @@ -1,52 +1,51 @@ +import { EditOutlined } from '@ant-design/icons'; +import { request } from '@umijs/max'; import { sitecontrollerAll } from '@/servers/api/site'; import { PageContainer, } from '@ant-design/pro-components'; import { Outlet, history, useLocation, useParams } from '@umijs/max'; -import { App, Button, Card, Col, Menu, Row, Select, Spin } from 'antd'; +import { Button, Card, Col, Menu, Row, Select, Spin, message } from 'antd'; import React, { useEffect, useState } from 'react'; +import EditSiteForm from './EditSiteForm'; +import type { SiteItem } from '../List/index'; const ShopLayout: React.FC = () => { - const [sites, setSites] = useState<{ label: string; value: number }[]>([]); + const [sites, setSites] = useState([]); const [loading, setLoading] = useState(true); const { siteId } = useParams<{ siteId: string }>(); const location = useLocation(); - const { message } = App.useApp(); + + const [editModalOpen, setEditModalOpen] = useState(false); + const [editingSite, setEditingSite] = useState(null); + + const fetchSites = async () => { + try { + setLoading(true); + const { data = [] } = await sitecontrollerAll(); + setSites(data); + + if (!siteId && data.length > 0) { + history.replace(`/site/shop/${data[0].id}/products`); + } + } catch (error) { + console.error('Failed to fetch sites', error); + } finally { + setLoading(false); + } + }; useEffect(() => { - const fetchSites = async () => { - try { - const { data = [] } = await sitecontrollerAll(); - const siteOptions = data.map((item: any) => ({ - label: item.name, - value: item.id, - })); - setSites(siteOptions); - - // 如果 URL 中没有 siteId,且有站点数据,默认跳转到第一个站点的 products 页面 - if (!siteId && siteOptions.length > 0) { - history.replace(`/site/shop/${siteOptions[0].value}/products`); - } - } catch (error) { - console.error('Failed to fetch sites', error); - } finally { - setLoading(false); - } - }; fetchSites(); }, []); const handleSiteChange = (value: number) => { - // 切换站点时,保持当前的功能模块(products/orders/etc),只改变 siteId const currentPath = location.pathname; const parts = currentPath.split('/'); - // 假设路径结构是 /site/shop/:siteId/module... - // parts: ['', 'site', 'shop', '123', 'products'] if (parts.length >= 5) { parts[3] = String(value); history.push(parts.join('/')); } else { - // Fallback history.push(`/site/shop/${value}/products`); } }; @@ -56,18 +55,14 @@ const ShopLayout: React.FC = () => { history.push(`/site/shop/${siteId}/${e.key}`); }; - // 获取当前选中的菜单项 const getSelectedKey = () => { const parts = location.pathname.split('/'); - // /site/shop/:siteId/:module if (parts.length >= 5) { - return parts[4]; // products, orders, subscriptions, logistics + return parts[4]; } return 'products'; }; - // 已移除店铺同步逻辑,页面加载即从站点实时拉取数据 - if (loading) { return ( { ); } + const handleFinish = async (values: any) => { + if (!editingSite) { + message.error('未找到要编辑的站点'); + return false; + } + try { + await request(`/site/${editingSite.id}`, { + method: 'PUT', + data: values, + }); + message.success('更新成功'); + setEditModalOpen(false); + fetchSites(); // 重新获取站点列表以更新数据 + return true; + } catch (error: any) { + message.error(error.message || '操作失败'); + return false; + } + }; + return ( - + { style={{ height: '100%', overflow: 'hidden' }} >
-
选择店铺:
- ({ label: site.name, value: site.id }))} + value={siteId ? Number(siteId) : undefined} + onChange={handleSiteChange} + showSearch + optionFilterProp="label" + /> +
{ { key: 'products', label: '产品管理' }, { key: 'orders', label: '订单管理' }, { key: 'subscriptions', label: '订阅管理' }, - { key: 'logistics', label: '物流管理' }, { key: 'media', label: '媒体管理' }, { key: 'customers', label: '客户管理' }, + { key: 'reviews', label: '评论管理' }, ]} />
- {/* 这里的 Outlet 会渲染子路由组件,如 Products, Orders 等 */} {siteId ? :
请选择店铺
}
- {/* 店铺同步弹窗已移除 */} + { + setEditModalOpen(visible); + if (!visible) { + setEditingSite(null); + } + }} + initialValues={editingSite} + isEdit={!!editingSite} + onFinish={handleFinish} + />
); }; diff --git a/src/pages/Site/Shop/Logistics/index.tsx b/src/pages/Site/Shop/Logistics/index.tsx index 70789c4..228fa9f 100644 --- a/src/pages/Site/Shop/Logistics/index.tsx +++ b/src/pages/Site/Shop/Logistics/index.tsx @@ -209,41 +209,28 @@ const LogisticsPage: React.FC = () => { - { - // 条件判断 如果当前未选择任何行则直接返回 - if (!selectedRows || selectedRows.length === 0) return; + - + 批量删除 + ); }} diff --git a/src/pages/Site/Shop/Orders/index.tsx b/src/pages/Site/Shop/Orders/index.tsx index 3f94fe6..1ee3b26 100644 --- a/src/pages/Site/Shop/Orders/index.tsx +++ b/src/pages/Site/Shop/Orders/index.tsx @@ -113,6 +113,30 @@ const OrdersPage: React.FC = () => { dataIndex: 'customer_name', hideInSearch: true, }, + { + title: '商品', + dataIndex: 'line_items', + hideInSearch: true, + width: 200, + ellipsis: true, + render: (_, record) => { + // 检查 record.line_items 是否是数组并且有内容 + if (Array.isArray(record.line_items) && record.line_items.length > 0) { + // 遍历 line_items 数组, 显示每个商品的名称和数量 + return ( +
+ {record.line_items.map((item: any) => ( +
+ {`${item.name} x ${item.quantity}`} +
+ ))} +
+ ); + } + // 如果 line_items 不存在或不是数组, 则显示占位符 + return '-'; + }, + }, { title: '支付方式', dataIndex: 'payment_method', @@ -372,7 +396,7 @@ const OrdersPage: React.FC = () => { const res = await request(`/site-api/${siteId}/orders`, { params: { page: 1, - page_size: 1, + per_page: 1, where: { ...baseWhere, status: rawStatus }, }, }); diff --git a/src/pages/Site/Shop/Products/index.tsx b/src/pages/Site/Shop/Products/index.tsx index 0914125..a4e1b9e 100644 --- a/src/pages/Site/Shop/Products/index.tsx +++ b/src/pages/Site/Shop/Products/index.tsx @@ -8,7 +8,7 @@ import { ProTable, } from '@ant-design/pro-components'; import { App, Button, Divider, Popconfirm, Tag } from 'antd'; -import { DeleteFilled } from '@ant-design/icons'; +import { DeleteFilled, LinkOutlined } from '@ant-design/icons'; import React, { useEffect, useRef, useState } from 'react'; import { BatchEditProducts, @@ -21,13 +21,13 @@ import { CreateProduct, } from '../components/Product/Forms'; import { TagConfig } from '../components/Product/utils'; - const ProductsPage: React.FC = () => { const { message } = App.useApp(); const actionRef = useRef(); const [selectedRowKeys, setSelectedRowKeys] = useState([]); const [selectedRows, setSelectedRows] = useState([]); // Use any or unified DTO type const { siteId } = useParams<{ siteId: string }>(); + const [siteInfo, setSiteInfo] = useState(); const [config, setConfig] = useState({ brands: [], fruits: [], @@ -43,6 +43,20 @@ const ProductsPage: React.FC = () => { actionRef.current?.reload(); }, [siteId]); + useEffect(() => { + const loadSiteInfo = async () => { + try { + const res = await request(`/site/get/${siteId}`); + if (res?.success && res?.data) { + setSiteInfo(res.data); + } + } catch (e) {} + }; + if (siteId) { + loadSiteInfo(); + } + }, [siteId]); + useEffect(() => { const fetchAllConfigs = async () => { try { @@ -86,8 +100,9 @@ const ProductsPage: React.FC = () => { fetchAllConfigs(); }, []); - const columns: ProColumns[] = [ + const columns: ProColumns[] = [ { + // ID title: 'ID', dataIndex: 'id', hideInSearch: true, @@ -98,36 +113,43 @@ const ProductsPage: React.FC = () => { } }, { + // sku title: 'sku', dataIndex: 'sku', fixed: 'left', }, { + // 名称 title: '名称', dataIndex: 'name', }, { + // 产品状态 title: '产品状态', dataIndex: 'status', valueType: 'select', valueEnum: PRODUCT_STATUS_ENUM, }, { + // 产品类型 title: '产品类型', dataIndex: 'type', }, { + // 库存状态 title: '库存状态', dataIndex: 'stock_status', valueType: 'select', valueEnum: PRODUCT_STOCK_STATUS_ENUM, }, { + // 库存 title: '库存', dataIndex: 'stock_quantity', hideInSearch: true, }, { + // 图片 title: '图片', dataIndex: 'images', hideInSearch: true, @@ -139,16 +161,101 @@ const ProductsPage: React.FC = () => { }, }, { + // 常规价格 title: '常规价格', dataIndex: 'regular_price', hideInSearch: true, }, { + // 销售价格 title: '销售价格', dataIndex: 'sale_price', hideInSearch: true, }, { + // 标签 + title: '标签', + dataIndex: 'tags', + hideInSearch: true, + width: 250, + render: (_, record) => { + // 检查 record.tags 是否存在并且是一个数组 + if (record.tags && Array.isArray(record.tags)) { + // 遍历 tags 数组并为每个 tag 对象渲染一个 Tag 组件 + return ( +
+ {record.tags.map((tag: any) => ( + // 使用 tag.name 作为 key, 因为 tag.id 可能是对象, 会导致 React key 错误 + {tag.name} + ))} +
+ ); + } + // 如果 record.tags 不是一个有效的数组,则不渲染任何内容 + return null; + }, + }, + { + // 分类 + title: '分类', + dataIndex: 'categories', + hideInSearch: true, + width: 250, + render: (_, record) => { + // 检查 record.categories 是否存在并且是一个数组 + if (record.categories && Array.isArray(record.categories)) { + // 遍历 categories 数组并为每个 category 对象渲染一个 Tag 组件 + return ( +
+ {record.categories.map((cat: any) => ( + // 使用 cat.name 作为 key + {cat.name} + ))} +
+ ); + } + // 如果 record.categories 不是一个有效的数组,则不渲染任何内容 + return null; + }, + }, + { + // 属性 + title: '属性', + dataIndex: 'attributes', + hideInSearch: true, + width: 250, + render: (_, record) => { + // 检查 record.attributes 是否存在并且是一个数组 + if (record.attributes && Array.isArray(record.attributes)) { + return ( +
+ {(record.attributes as any[]).map((attr: any) => ( +
+ {attr.name}: {Array.isArray(attr.options) ? attr.options.join(', ') : ''} +
+ ))} +
+ ); + } + return null; + }, + }, + { + // 创建时间 + title: '创建时间', + dataIndex: 'date_created', + valueType: 'dateTime', + hideInSearch: true, + }, + { + // 修改时间 + title: '修改时间', + dataIndex: 'date_modified', + valueType: 'dateTime', + hideInSearch: true, + }, + { + // 操作 title: '操作', dataIndex: 'option', valueType: 'option', @@ -158,6 +265,19 @@ const ProductsPage: React.FC = () => {
+ +
+ ); +}; + +export default ReviewForm; diff --git a/src/pages/Site/Shop/Reviews/index.tsx b/src/pages/Site/Shop/Reviews/index.tsx new file mode 100644 index 0000000..e6aa23d --- /dev/null +++ b/src/pages/Site/Shop/Reviews/index.tsx @@ -0,0 +1,101 @@ +import React, { useRef, useState } from 'react'; +import { ActionType, ProTable, ProColumns, ProCard } from '@ant-design/pro-components'; +import { Button, Popconfirm, message, Space } from 'antd'; +import { siteapicontrollerGetreviews, siteapicontrollerDeletereview } from '@/servers/api/siteApi'; +import ReviewForm from './ReviewForm'; +import { useParams } from '@umijs/max'; + +const ReviewsPage: React.FC = () => { + const params = useParams(); + const siteId = Number(params.siteId); + const actionRef = useRef(); + const [open, setOpen] = useState(false); + const [editing, setEditing] = useState(null); + + const columns: ProColumns[] = [ + { title: 'ID', dataIndex: 'id', key: 'id', width: 50 }, + { title: '产品ID', dataIndex: 'product_id', key: 'product_id', width: 80 }, + { title: '作者', dataIndex: 'author', key: 'author' }, + { title: '评分', dataIndex: 'rating', key: 'rating', width: 80 }, + { title: '状态', dataIndex: 'status', key: 'status', width: 100 }, + { + title: '创建时间', + dataIndex: 'date_created', + key: 'date_created', + valueType: 'dateTime', + width: 150, + }, + { + title: '操作', + key: 'action', + width: 150, + render: (_, record) => ( + + + { + if (record.id) { + try { + const response = await siteapicontrollerDeletereview({ siteId, id: String(record.id) }); + if (response.success) { + message.success('删除成功'); + actionRef.current?.reload(); + } else { + message.error('删除失败'); + } + } catch (error) { + message.error('删除失败'); + } + } + }}> + + + + ), + }, + ]; + + return ( + + + columns={columns} + actionRef={actionRef} + request={async (params) => { + const response = await siteapicontrollerGetreviews({ ...params, siteId, page: params.current, per_page: params.pageSize }); + return { + data: response.data.items, + success: true, + total: response.data.total, + }; + }} + rowKey="id" + search={{ + labelWidth: 'auto', + }} + headerTitle="评论列表" + toolBarRender={() => [ + , + ]} + /> + setOpen(false)} + onSuccess={() => { + setOpen(false); + actionRef.current?.reload(); + }} + /> + + ); +}; + +export default ReviewsPage; diff --git a/src/pages/Site/Shop/Subscriptions/index.tsx b/src/pages/Site/Shop/Subscriptions/index.tsx index 7073fda..4899e08 100644 --- a/src/pages/Site/Shop/Subscriptions/index.tsx +++ b/src/pages/Site/Shop/Subscriptions/index.tsx @@ -56,7 +56,6 @@ const SubscriptionsPage: React.FC = () => { title: '订阅ID', dataIndex: 'id', hideInSearch: true, - width: 120, }, { title: '状态', @@ -70,25 +69,21 @@ const SubscriptionsPage: React.FC = () => { ) : ( '-' ), - width: 120, }, { title: '客户ID', dataIndex: 'customer_id', hideInSearch: true, - width: 120, }, { title: '计费周期', dataIndex: 'billing_period', hideInSearch: true, - width: 120, }, { title: '计费间隔', dataIndex: 'billing_interval', hideInSearch: true, - width: 120, }, { title: '开始时间', @@ -102,10 +97,23 @@ const SubscriptionsPage: React.FC = () => { hideInSearch: true, width: 160, }, + { + // 创建时间 + title: '创建时间', + dataIndex: 'date_created', + valueType: 'dateTime', + hideInSearch: true, + }, + { + // 修改时间 + title: '修改时间', + dataIndex: 'date_modified', + valueType: 'dateTime', + hideInSearch: true, + }, { title: '操作', valueType: 'option', - width: 120, render: (_, row) => ( } diff --git a/src/pages/Site/Shop/components/Product/Forms.tsx b/src/pages/Site/Shop/components/Product/Forms.tsx index 35e0f23..8aff04f 100644 --- a/src/pages/Site/Shop/components/Product/Forms.tsx +++ b/src/pages/Site/Shop/components/Product/Forms.tsx @@ -355,16 +355,17 @@ export const UpdateForm: React.FC<{ placeholder="请输入SKU" rules={[{ required: true, message: '请输入SKU' }]} /> - + + {initialValues.type === 'simple' ? ( <> ('/review/create', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }); +} + +/** 此处后端没有提供注释 DELETE /review/delete/${param0} */ +export async function reviewcontrollerDelete( + // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) + params: API.reviewcontrollerDeleteParams, + options?: { [key: string]: any }, +) { + const { id: param0, ...queryParams } = params; + return request(`/review/delete/${param0}`, { + method: 'DELETE', + params: { ...queryParams }, + ...(options || {}), + }); +} + +/** 此处后端没有提供注释 GET /review/get/${param0} */ +export async function reviewcontrollerGet( + // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) + params: API.reviewcontrollerGetParams, + options?: { [key: string]: any }, +) { + const { id: param0, ...queryParams } = params; + return request(`/review/get/${param0}`, { + method: 'GET', + params: { ...queryParams }, + ...(options || {}), + }); +} + +/** 此处后端没有提供注释 GET /review/list */ +export async function reviewcontrollerList( + // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) + params: API.reviewcontrollerListParams, + options?: { [key: string]: any }, +) { + return request('/review/list', { + method: 'GET', + params: { + ...params, + }, + ...(options || {}), + }); +} + +/** 此处后端没有提供注释 PUT /review/update/${param0} */ +export async function reviewcontrollerUpdate( + // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) + params: API.reviewcontrollerUpdateParams, + body: API.UpdateReviewDTO, + options?: { [key: string]: any }, +) { + const { id: param0, ...queryParams } = params; + return request(`/review/update/${param0}`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + }, + params: { ...queryParams }, + data: body, + ...(options || {}), + }); +} diff --git a/src/servers/api/siteApi.ts b/src/servers/api/siteApi.ts index 39b8d5f..898c33f 100644 --- a/src/servers/api/siteApi.ts +++ b/src/servers/api/siteApi.ts @@ -15,6 +15,10 @@ export async function siteapicontrollerGetcustomers( method: 'GET', params: { ...queryParams, + where: undefined, + ...queryParams['where'], + order: undefined, + ...queryParams['order'], }, ...(options || {}), }, @@ -70,6 +74,10 @@ export async function siteapicontrollerExportcustomers( method: 'GET', params: { ...queryParams, + where: undefined, + ...queryParams['where'], + order: undefined, + ...queryParams['order'], }, ...(options || {}), }); @@ -105,6 +113,10 @@ export async function siteapicontrollerGetmedia( method: 'GET', params: { ...queryParams, + where: undefined, + ...queryParams['where'], + order: undefined, + ...queryParams['order'], }, ...(options || {}), }); @@ -162,6 +174,10 @@ export async function siteapicontrollerExportmedia( method: 'GET', params: { ...queryParams, + where: undefined, + ...queryParams['where'], + order: undefined, + ...queryParams['order'], }, ...(options || {}), }); @@ -178,6 +194,10 @@ export async function siteapicontrollerGetorders( method: 'GET', params: { ...queryParams, + where: undefined, + ...queryParams['where'], + order: undefined, + ...queryParams['order'], }, ...(options || {}), }); @@ -232,6 +252,10 @@ export async function siteapicontrollerExportorders( method: 'GET', params: { ...queryParams, + where: undefined, + ...queryParams['where'], + order: undefined, + ...queryParams['order'], }, ...(options || {}), }); @@ -269,6 +293,10 @@ export async function siteapicontrollerGetproducts( method: 'GET', params: { ...queryParams, + where: undefined, + ...queryParams['where'], + order: undefined, + ...queryParams['order'], }, ...(options || {}), }, @@ -324,6 +352,10 @@ export async function siteapicontrollerExportproducts( method: 'GET', params: { ...queryParams, + where: undefined, + ...queryParams['where'], + order: undefined, + ...queryParams['order'], }, ...(options || {}), }); @@ -340,6 +372,10 @@ export async function siteapicontrollerExportproductsspecial( method: 'GET', params: { ...queryParams, + where: undefined, + ...queryParams['where'], + order: undefined, + ...queryParams['order'], }, ...(options || {}), }); @@ -386,6 +422,48 @@ export async function siteapicontrollerImportproductsspecial( ); } +/** 此处后端没有提供注释 GET /site-api/${param0}/reviews */ +export async function siteapicontrollerGetreviews( + // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) + params: API.siteapicontrollerGetreviewsParams, + options?: { [key: string]: any }, +) { + const { siteId: param0, ...queryParams } = params; + return request( + `/site-api/${param0}/reviews`, + { + method: 'GET', + params: { + ...queryParams, + where: undefined, + ...queryParams['where'], + order: undefined, + ...queryParams['order'], + }, + ...(options || {}), + }, + ); +} + +/** 此处后端没有提供注释 POST /site-api/${param0}/reviews */ +export async function siteapicontrollerCreatereview( + // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) + params: API.siteapicontrollerCreatereviewParams, + body: API.CreateReviewDTO, + options?: { [key: string]: any }, +) { + const { siteId: param0, ...queryParams } = params; + return request(`/site-api/${param0}/reviews`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + params: { ...queryParams }, + data: body, + ...(options || {}), + }); +} + /** 此处后端没有提供注释 GET /site-api/${param0}/subscriptions */ export async function siteapicontrollerGetsubscriptions( // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) @@ -399,6 +477,10 @@ export async function siteapicontrollerGetsubscriptions( method: 'GET', params: { ...queryParams, + where: undefined, + ...queryParams['where'], + order: undefined, + ...queryParams['order'], }, ...(options || {}), }, @@ -416,6 +498,10 @@ export async function siteapicontrollerExportsubscriptions( method: 'GET', params: { ...queryParams, + where: undefined, + ...queryParams['where'], + order: undefined, + ...queryParams['order'], }, ...(options || {}), }); @@ -490,6 +576,10 @@ export async function siteapicontrollerGetcustomerorders( method: 'GET', params: { ...queryParams, + where: undefined, + ...queryParams['where'], + order: undefined, + ...queryParams['order'], }, ...(options || {}), }, @@ -671,6 +761,42 @@ export async function siteapicontrollerDeleteproduct( ); } +/** 此处后端没有提供注释 PUT /site-api/${param1}/reviews/${param0} */ +export async function siteapicontrollerUpdatereview( + // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) + params: API.siteapicontrollerUpdatereviewParams, + body: API.UpdateReviewDTO, + options?: { [key: string]: any }, +) { + const { id: param0, siteId: param1, ...queryParams } = params; + return request( + `/site-api/${param1}/reviews/${param0}`, + { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + }, + params: { ...queryParams }, + data: body, + ...(options || {}), + }, + ); +} + +/** 此处后端没有提供注释 DELETE /site-api/${param1}/reviews/${param0} */ +export async function siteapicontrollerDeletereview( + // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) + params: API.siteapicontrollerDeletereviewParams, + options?: { [key: string]: any }, +) { + const { id: param0, siteId: param1, ...queryParams } = params; + return request>(`/site-api/${param1}/reviews/${param0}`, { + method: 'DELETE', + params: { ...queryParams }, + ...(options || {}), + }); +} + /** 此处后端没有提供注释 PUT /site-api/${param2}/products/${param1}/variations/${param0} */ export async function siteapicontrollerUpdatevariation( // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) diff --git a/src/servers/api/typings.d.ts b/src/servers/api/typings.d.ts index bd94d7e..66294c8 100644 --- a/src/servers/api/typings.d.ts +++ b/src/servers/api/typings.d.ts @@ -184,6 +184,25 @@ declare namespace API { items?: PurchaseOrderItem[]; }; + type CreateReviewDTO = { + /** 站点ID */ + siteId?: number; + /** 产品ID */ + productId?: number; + /** 客户ID */ + customerId?: number; + /** 评论者姓名 */ + author?: string; + /** 评论者电子邮件 */ + email?: string; + /** 评论内容 */ + content?: string; + /** 评分 (1-5) */ + rating?: number; + /** 状态 */ + status?: 'pending' | 'approved' | 'rejected'; + }; + type CreateSiteDTO = { /** 区域 */ areas?: any; @@ -1211,6 +1230,19 @@ declare namespace API { stockPointId?: number; }; + type QueryReviewDTO = { + /** 当前页码 */ + current?: number; + /** 每页数量 */ + pageSize?: number; + /** 站点ID */ + siteId?: number; + /** 产品ID */ + productId?: number; + /** 状态 */ + status?: string; + }; + type QueryServiceDTO = { /** 页码 */ current?: number; @@ -1316,6 +1348,31 @@ declare namespace API { data?: RateDTO[]; }; + type reviewcontrollerDeleteParams = { + id: number; + }; + + type reviewcontrollerGetParams = { + id: number; + }; + + type reviewcontrollerListParams = { + /** 当前页码 */ + current?: number; + /** 每页数量 */ + pageSize?: number; + /** 站点ID */ + siteId?: number; + /** 产品ID */ + productId?: number; + /** 状态 */ + status?: string; + }; + + type reviewcontrollerUpdateParams = { + id: number; + }; + type Service = { id?: string; carrier_name?: string; @@ -1442,6 +1499,10 @@ declare namespace API { siteId: number; }; + type siteapicontrollerCreatereviewParams = { + siteId: number; + }; + type siteapicontrollerDeletecustomerParams = { id: string; siteId: number; @@ -1462,6 +1523,11 @@ declare namespace API { siteId: number; }; + type siteapicontrollerDeletereviewParams = { + id: number; + siteId: number; + }; + type siteapicontrollerExportcustomersParams = { /** 页码 */ page?: number; @@ -1476,9 +1542,9 @@ declare namespace API { /** 客户ID,用于筛选订单 */ customer_id?: number; /** 过滤条件对象 */ - where?: any; + where?: Record; /** 排序对象,例如 { "sku": "desc" } */ - order?: any; + order?: Record; /** 排序字段(兼容旧入参) */ orderby?: string; /** 排序方式(兼容旧入参) */ @@ -1502,9 +1568,9 @@ declare namespace API { /** 客户ID,用于筛选订单 */ customer_id?: number; /** 过滤条件对象 */ - where?: any; + where?: Record; /** 排序对象,例如 { "sku": "desc" } */ - order?: any; + order?: Record; /** 排序字段(兼容旧入参) */ orderby?: string; /** 排序方式(兼容旧入参) */ @@ -1528,9 +1594,9 @@ declare namespace API { /** 客户ID,用于筛选订单 */ customer_id?: number; /** 过滤条件对象 */ - where?: any; + where?: Record; /** 排序对象,例如 { "sku": "desc" } */ - order?: any; + order?: Record; /** 排序字段(兼容旧入参) */ orderby?: string; /** 排序方式(兼容旧入参) */ @@ -1554,9 +1620,9 @@ declare namespace API { /** 客户ID,用于筛选订单 */ customer_id?: number; /** 过滤条件对象 */ - where?: any; + where?: Record; /** 排序对象,例如 { "sku": "desc" } */ - order?: any; + order?: Record; /** 排序字段(兼容旧入参) */ orderby?: string; /** 排序方式(兼容旧入参) */ @@ -1580,9 +1646,9 @@ declare namespace API { /** 客户ID,用于筛选订单 */ customer_id?: number; /** 过滤条件对象 */ - where?: any; + where?: Record; /** 排序对象,例如 { "sku": "desc" } */ - order?: any; + order?: Record; /** 排序字段(兼容旧入参) */ orderby?: string; /** 排序方式(兼容旧入参) */ @@ -1606,9 +1672,9 @@ declare namespace API { /** 客户ID,用于筛选订单 */ customer_id?: number; /** 过滤条件对象 */ - where?: any; + where?: Record; /** 排序对象,例如 { "sku": "desc" } */ - order?: any; + order?: Record; /** 排序字段(兼容旧入参) */ orderby?: string; /** 排序方式(兼容旧入参) */ @@ -1632,9 +1698,9 @@ declare namespace API { /** 客户ID,用于筛选订单 */ customer_id?: number; /** 过滤条件对象 */ - where?: any; + where?: Record; /** 排序对象,例如 { "sku": "desc" } */ - order?: any; + order?: Record; /** 排序字段(兼容旧入参) */ orderby?: string; /** 排序方式(兼容旧入参) */ @@ -1664,9 +1730,9 @@ declare namespace API { /** 客户ID,用于筛选订单 */ customer_id?: number; /** 过滤条件对象 */ - where?: any; + where?: Record; /** 排序对象,例如 { "sku": "desc" } */ - order?: any; + order?: Record; /** 排序字段(兼容旧入参) */ orderby?: string; /** 排序方式(兼容旧入参) */ @@ -1690,9 +1756,9 @@ declare namespace API { /** 客户ID,用于筛选订单 */ customer_id?: number; /** 过滤条件对象 */ - where?: any; + where?: Record; /** 排序对象,例如 { "sku": "desc" } */ - order?: any; + order?: Record; /** 排序字段(兼容旧入参) */ orderby?: string; /** 排序方式(兼容旧入参) */ @@ -1726,9 +1792,9 @@ declare namespace API { /** 客户ID,用于筛选订单 */ customer_id?: number; /** 过滤条件对象 */ - where?: any; + where?: Record; /** 排序对象,例如 { "sku": "desc" } */ - order?: any; + order?: Record; /** 排序字段(兼容旧入参) */ orderby?: string; /** 排序方式(兼容旧入参) */ @@ -1757,9 +1823,35 @@ declare namespace API { /** 客户ID,用于筛选订单 */ customer_id?: number; /** 过滤条件对象 */ - where?: any; + where?: Record; /** 排序对象,例如 { "sku": "desc" } */ - order?: any; + order?: Record; + /** 排序字段(兼容旧入参) */ + orderby?: string; + /** 排序方式(兼容旧入参) */ + orderDir?: string; + /** 选中ID列表,逗号分隔 */ + ids?: string; + siteId: number; + }; + + type siteapicontrollerGetreviewsParams = { + /** 页码 */ + page?: number; + /** 每页数量 */ + per_page?: number; + /** 每页数量别名 */ + page_size?: number; + /** 搜索关键词 */ + search?: string; + /** 状态 */ + status?: string; + /** 客户ID,用于筛选订单 */ + customer_id?: number; + /** 过滤条件对象 */ + where?: Record; + /** 排序对象,例如 { "sku": "desc" } */ + order?: Record; /** 排序字段(兼容旧入参) */ orderby?: string; /** 排序方式(兼容旧入参) */ @@ -1783,9 +1875,9 @@ declare namespace API { /** 客户ID,用于筛选订单 */ customer_id?: number; /** 过滤条件对象 */ - where?: any; + where?: Record; /** 排序对象,例如 { "sku": "desc" } */ - order?: any; + order?: Record; /** 排序字段(兼容旧入参) */ orderby?: string; /** 排序方式(兼容旧入参) */ @@ -1831,6 +1923,11 @@ declare namespace API { siteId: number; }; + type siteapicontrollerUpdatereviewParams = { + id: number; + siteId: number; + }; + type siteapicontrollerUpdatevariationParams = { variationId: string; productId: string; @@ -2193,6 +2290,40 @@ declare namespace API { minute?: string; }; + type UnifiedAddressDTO = { + /** 名 */ + first_name?: string; + /** 姓 */ + last_name?: string; + /** 全名 */ + fullname?: string; + /** 公司 */ + company?: string; + /** 地址1 */ + address_1?: string; + /** 地址2 */ + address_2?: string; + /** 城市 */ + city?: string; + /** 省/州 */ + state?: string; + /** 邮政编码 */ + postcode?: string; + /** 国家 */ + country?: string; + /** 邮箱 */ + email?: string; + /** 电话 */ + phone?: string; + }; + + type UnifiedCategoryDTO = { + /** 分类ID */ + id?: Record; + /** 分类名称 */ + name?: string; + }; + type UnifiedCustomerDTO = { /** 客户ID */ id?: Record; @@ -2219,11 +2350,11 @@ declare namespace API { /** 电话 */ phone?: string; /** 账单地址 */ - billing?: any; + billing?: UnifiedAddressDTO; /** 收货地址 */ - shipping?: any; + shipping?: UnifiedAddressDTO; /** 原始数据 */ - raw?: any; + raw?: Record; }; type UnifiedCustomerPaginationDTO = { @@ -2301,14 +2432,14 @@ declare namespace API { customer_name?: string; /** 客户邮箱 */ email?: string; - /** 订单项 */ - line_items?: any; + /** 订单项(具体的商品) */ + line_items?: UnifiedOrderLineItemDTO[]; /** 销售项(兼容前端) */ - sales?: any; + sales?: UnifiedOrderLineItemDTO[]; /** 账单地址 */ - billing?: any; + billing?: UnifiedAddressDTO; /** 收货地址 */ - shipping?: any; + shipping?: UnifiedAddressDTO; /** 账单地址全称 */ billing_full_address?: string; /** 收货地址全称 */ @@ -2320,7 +2451,24 @@ declare namespace API { /** 更新时间 */ date_modified?: string; /** 原始数据 */ - raw?: any; + raw?: Record; + }; + + type UnifiedOrderLineItemDTO = { + /** 订单项ID */ + id?: Record; + /** 产品名称 */ + name?: string; + /** 产品ID */ + product_id?: Record; + /** 变体ID */ + variation_id?: Record; + /** 数量 */ + quantity?: number; + /** 总计 */ + total?: string; + /** SKU */ + sku?: string; }; type UnifiedOrderPaginationDTO = { @@ -2338,6 +2486,21 @@ declare namespace API { totalPages?: number; }; + type UnifiedProductAttributeDTO = { + /** 属性ID */ + id?: Record; + /** 属性名称 */ + name?: string; + /** 属性位置 */ + position?: number; + /** 对变体是否可见 */ + visible?: boolean; + /** 是否为变体属性 */ + variation?: boolean; + /** 属性选项 */ + options?: string[]; + }; + type UnifiedProductDTO = { /** 产品ID */ id?: Record; @@ -2362,17 +2525,21 @@ declare namespace API { /** 产品图片 */ images?: UnifiedImageDTO[]; /** 产品标签 */ - tags?: any; + tags?: UnifiedTagDTO[]; + /** 产品分类 */ + categories?: UnifiedCategoryDTO[]; /** 产品属性 */ - attributes?: any; + attributes?: UnifiedProductAttributeDTO[]; /** 产品变体 */ - variations?: any; + variations?: UnifiedProductVariationDTO[]; /** 创建时间 */ date_created?: string; /** 更新时间 */ date_modified?: string; + /** 产品链接 */ + frontendUrl?: string; /** 原始数据(保留备用) */ - raw?: any; + raw?: Record; }; type UnifiedProductPaginationDTO = { @@ -2390,6 +2557,59 @@ declare namespace API { totalPages?: number; }; + type UnifiedProductVariationDTO = { + /** 变体ID */ + id?: Record; + /** 变体SKU */ + sku?: string; + /** 常规价格 */ + regular_price?: string; + /** 销售价格 */ + sale_price?: string; + /** 当前价格 */ + price?: string; + /** 库存状态 */ + stock_status?: string; + /** 库存数量 */ + stock_quantity?: number; + /** 变体图片 */ + image?: UnifiedImageDTO; + }; + + type UnifiedReviewDTO = { + /** 评论ID */ + id?: Record; + /** 产品ID */ + product_id?: Record; + /** 评论者 */ + author?: string; + /** 评论者邮箱 */ + email?: string; + /** 评论内容 */ + content?: string; + /** 评分 */ + rating?: number; + /** 状态 */ + status?: string; + /** 创建时间 */ + date_created?: string; + }; + + type UnifiedReviewPaginationDTO = { + /** 列表数据 */ + items?: UnifiedReviewDTO[]; + /** 总数 */ + total?: number; + /** 当前页 */ + page?: number; + /** 每页数量 */ + per_page?: number; + /** 每页数量别名 */ + page_size?: number; + /** 总页数 */ + totalPages?: number; + }; + type UnifiedSearchParamsDTO = { /** 页码 */ page?: number; @@ -2404,9 +2624,9 @@ declare namespace API { /** 客户ID,用于筛选订单 */ customer_id?: number; /** 过滤条件对象 */ - where?: any; + where?: Record; /** 排序对象,例如 { "sku": "desc" } */ - order?: any; + order?: Record; /** 排序字段(兼容旧入参) */ orderby?: string; /** 排序方式(兼容旧入参) */ @@ -2435,9 +2655,9 @@ declare namespace API { /** 下次支付时间 */ next_payment_date?: string; /** 订单项 */ - line_items?: any; + line_items?: UnifiedOrderLineItemDTO[]; /** 原始数据 */ - raw?: any; + raw?: Record; }; type UnifiedSubscriptionPaginationDTO = { @@ -2455,6 +2675,13 @@ declare namespace API { totalPages?: number; }; + type UnifiedTagDTO = { + /** 标签ID */ + id?: Record; + /** 标签名称 */ + name?: string; + }; + type UpdateAreaDTO = { /** 编码 */ code?: string; @@ -2499,6 +2726,15 @@ declare namespace API { items?: PurchaseOrderItem[]; }; + type UpdateReviewDTO = { + /** 评论内容 */ + content?: string; + /** 评分 (1-5) */ + rating?: number; + /** 状态 */ + status?: 'pending' | 'approved' | 'rejected'; + }; + type UpdateSiteDTO = { /** 区域 */ areas?: any;