import { ordercontrollerSyncorders } from '@/servers/api/order'; import { sitecontrollerCreate, sitecontrollerDisable, sitecontrollerList, sitecontrollerUpdate, } from '@/servers/api/site'; import { subscriptioncontrollerSync } from '@/servers/api/subscription'; import { stockcontrollerGetallstockpoints } from '@/servers/api/stock'; import { ActionType, ProColumns, ProTable, DrawerForm, ProFormSelect, ProFormSwitch } from '@ant-design/pro-components'; import { Button, message, notification, Popconfirm, Space, Tag, Form } from 'antd'; import React, { useRef, useState, useEffect } from 'react'; import EditSiteForm from '../Shop/EditSiteForm'; // 引入重构后的表单组件 import * as countries from 'i18n-iso-countries'; import zhCN from 'i18n-iso-countries/langs/zh'; // 区域数据项类型 interface AreaItem { code: string; name: string; } // 仓库数据项类型 interface StockPointItem { id: number; name: string; } // 站点数据项类型(前端不包含密钥字段,后端列表不返回密钥) export interface SiteItem { id: number; name: string; description?: string; apiUrl?: string; websiteUrl?: string; // 网站地址 type?: 'woocommerce' | 'shopyy'; skuPrefix?: string; isDisabled: number; areas?: AreaItem[]; stockPoints?: StockPointItem[]; } const SiteList: React.FC = () => { const actionRef = useRef(); const [open, setOpen] = useState(false); const [editing, setEditing] = useState(null); const [selectedRowKeys, setSelectedRowKeys] = useState([]); const [batchEditOpen, setBatchEditOpen] = useState(false); const [batchEditForm] = Form.useForm(); countries.registerLocale(zhCN); const handleSync = async (ids: number[]) => { if (!ids.length) return; const hide = message.loading('正在同步...', 0); const stats = { orders: { success: 0, fail: 0 }, subscriptions: { success: 0, fail: 0 }, }; try { for (const id of ids) { // 同步订单 const orderRes = await ordercontrollerSyncorders({ siteId: id }); if (orderRes.success) { stats.orders.success += 1; } else { stats.orders.fail += 1; } // 同步订阅 const subRes = await subscriptioncontrollerSync({ siteId: id }); if (subRes.success) { stats.subscriptions.success += 1; } else { stats.subscriptions.fail += 1; } } hide(); notification.success({ message: '同步完成', description: (

订单: 成功 {stats.orders.success}, 失败 {stats.orders.fail}

订阅: 成功 {stats.subscriptions.success}, 失败{' '} {stats.subscriptions.fail}

), duration: null, // 不自动关闭 }); setSelectedRowKeys([]); actionRef.current?.reload(); } catch (error: any) { hide(); message.error(error.message || '同步失败'); } }; // 获取所有国家/地区的选项 const getCountryOptions = () => { // 获取所有国家的 ISO 代码 const countryCodes = countries.getAlpha2Codes(); // 将国家代码转换为选项数组 return Object.keys(countryCodes).map((code) => ({ label: countries.getName(code, 'zh') || code, // 使用中文名称, 如果没有则使用代码 value: code, })); }; // 处理批量编辑提交 const handleBatchEditFinish = async (values: any) => { if (!selectedRowKeys.length) return; const hide = message.loading('正在批量更新...', 0); try { // 遍历所有选中的站点 ID for (const id of selectedRowKeys) { // 构建更新数据对象,只包含用户填写了值的字段 const updateData: any = {}; // 如果用户选择了区域,则更新区域 if (values.areas && values.areas.length > 0) { updateData.areas = values.areas; } // 如果用户选择了仓库,则更新仓库 if (values.stockPointIds && values.stockPointIds.length > 0) { updateData.stockPointIds = values.stockPointIds; } // 如果用户设置了禁用状态,则更新状态 if (values.isDisabled !== undefined) { updateData.isDisabled = values.isDisabled; } // 如果有需要更新的字段,则调用更新接口 if (Object.keys(updateData).length > 0) { await sitecontrollerUpdate({ id: String(id) }, updateData); } } hide(); message.success('批量更新成功'); setBatchEditOpen(false); setSelectedRowKeys([]); batchEditForm.resetFields(); actionRef.current?.reload(); } catch (error: any) { hide(); message.error(error.message || '批量更新失败'); } }; // 当批量编辑弹窗打开时,重置表单 useEffect(() => { if (batchEditOpen) { batchEditForm.resetFields(); } }, [batchEditOpen, batchEditForm]); // 表格列定义 const columns: ProColumns[] = [ { title: 'ID', dataIndex: 'id', width: 80, sorter: true, hideInSearch: true, }, { 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', hideInSearch: true, }, { title: '平台', dataIndex: 'type', valueType: 'select', request: async () => [ { label: 'WooCommerce', value: 'woocommerce' }, { label: 'Shopyy', value: 'shopyy' }, ], }, { // 地区列配置 title: "地区", dataIndex: "areas", hideInSearch: true, render: (_, row) => { // 如果没有关联地区,显示"全局"标签 if (!row.areas || row.areas.length === 0) { return 全局; } // 遍历显示所有关联的地区名称 return ( {row.areas.map((area) => ( {area.name} ))} ); }, }, { title: '关联仓库', dataIndex: 'stockPoints', hideInSearch: true, render: (_, row) => { if (!row.stockPoints || row.stockPoints.length === 0) { return ; } return ( {row.stockPoints.map((sp) => ( {sp.name} ))} ); }, }, { title: '状态', dataIndex: 'isDisabled', width: 120, hideInSearch: true, render: (_, row) => ( {row.isDisabled ? '已禁用' : '启用中'} ), }, { title: '操作', dataIndex: 'actions', width: 240, fixed: 'right', hideInSearch: true, render: (_, row) => ( { try { await sitecontrollerDisable( { id: String(row.id) }, { disabled: !row.isDisabled }, ); message.success('更新成功'); actionRef.current?.reload(); } catch (e: any) { message.error(e?.message || '更新失败'); } }} > ), }, ]; // 表格数据请求 const tableRequest = async (params: Record) => { try { const { current, pageSize, name, type } = params; const resp = await sitecontrollerList({ current, pageSize, keyword: name || undefined, type: type || undefined, }); // 假设 resp 直接就是后端返回的结构,包含 items 和 total return { data: (resp?.data?.items ?? []) as SiteItem[], total: resp?.data?.total ?? 0, success: true, }; } catch (e: any) { message.error(e?.message || '获取失败'); return { data: [], total: 0, success: false }; } }; const handleFinish = async (values: any) => { try { if (editing) { await sitecontrollerUpdate({ id: String(editing.id) }, values); message.success('更新成功'); } else { await sitecontrollerCreate(values); message.success('创建成功'); } setOpen(false); actionRef.current?.reload(); return true; } catch (error: any) { message.error(error.message || '操作失败'); return false; } }; return ( <> scroll={{ x: 'max-content' }} actionRef={actionRef} rowKey="id" columns={columns} request={tableRequest} rowSelection={{ selectedRowKeys, onChange: setSelectedRowKeys, }} pagination={{ defaultPageSize: 20, showSizeChanger: true, showQuickJumper: true, }} toolBarRender={() => [ , , , ]} /> { setOpen(visible); if (!visible) { setEditing(null); } }} initialValues={editing} isEdit={!!editing} onFinish={handleFinish} /> {/* 批量编辑弹窗 */} (option?.label ?? '').toLowerCase().includes(input.toLowerCase()) } options={getCountryOptions()} /> { // 从后端接口获取仓库数据 const res = await stockcontrollerGetallstockpoints(); // 使用可选链和空值合并运算符来安全地处理可能未定义的数据 return ( res?.data?.map((sp: any) => ({ label: sp.name, value: sp.id })) ?? [] ); }} /> ); }; export default SiteList;