import { ActionType, DrawerForm, ProColumns, ProFormDependency, ProFormInstance, ProFormSelect, ProFormSwitch, ProFormText, ProTable, } from '@ant-design/pro-components'; import { request } from '@umijs/max'; import { Button, message, Popconfirm, Space, Tag } from 'antd'; import React, { useEffect, useRef, useState } from 'react'; // 区域数据项类型 interface AreaItem { code: string; name: string; } // 站点数据项类型(前端不包含密钥字段,后端列表不返回密钥) interface SiteItem { id: number; name: string; apiUrl?: string; type?: 'woocommerce' | 'shopyy'; skuPrefix?: string; isDisabled: number; areas?: AreaItem[]; } // 创建/更新表单的值类型,包含可选的密钥字段 interface SiteFormValues { name: 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[]; } const SiteList: React.FC = () => { const actionRef = useRef(); const formRef = useRef(); const [open, setOpen] = useState(false); const [editing, setEditing] = useState(null); useEffect(() => { if (!open) return; if (editing) { formRef.current?.setFieldsValue({ name: editing.name, 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) ?? [], }); } else { formRef.current?.setFieldsValue({ name: undefined, apiUrl: undefined, type: 'woocommerce', skuPrefix: undefined, isDisabled: false, consumerKey: undefined, consumerSecret: undefined, token: undefined, }); } }, [open, editing]); // 表格列定义 const columns: ProColumns[] = [ { title: 'ID', dataIndex: 'id', width: 80, sorter: true, hideInSearch: true, }, { title: '名称', dataIndex: 'name', width: 220 }, { title: 'API 地址', dataIndex: 'apiUrl', width: 280, hideInSearch: true }, { title: 'SKU 前缀', dataIndex: 'skuPrefix', width: 160, hideInSearch: true, }, { title: '平台', dataIndex: 'type', width: 140, valueType: 'select', request: async () => [ { label: 'WooCommerce', value: 'woocommerce' }, { 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: 'isDisabled', width: 120, hideInSearch: true, render: (_, row) => ( {row.isDisabled ? '已禁用' : '启用中'} ), }, { title: '操作', dataIndex: 'actions', width: 240, hideInSearch: true, render: (_, row) => ( { try { await request(`/site/disable/${row.id}`, { method: 'PUT', data: { disabled: !row.isDisabled }, }); message.success('更新成功'); actionRef.current?.reload(); } catch (e: any) { message.error(e?.message || '更新失败'); } }} > ), }, ]; // 表格数据请求 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 { success, data, message: errMsg } = resp as any; if (!success) throw new Error(errMsg || '获取失败'); return { data: (data?.items ?? []) as SiteItem[], total: data?.total ?? 0, success: true, }; } catch (e: any) { message.error(e?.message || '获取失败'); return { data: [], total: 0, success: false }; } }; // 提交创建/更新逻辑;编辑时未填写密钥则不提交(保持原值) const handleSubmit = async (values: SiteFormValues) => { 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 } : {}), ...(apiUrl ? { apiUrl: apiUrl } : {}), ...(values.type ? { type: values.type } : {}), ...(typeof values.isDisabled === 'boolean' ? { isDisabled: values.isDisabled } : {}), ...(values.skuPrefix ? { skuPrefix: values.skuPrefix } : {}), areas: values.areas ?? [], }; 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, }); } 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, 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 ?? [], }, }); } message.success('提交成功'); setOpen(false); setEditing(null); actionRef.current?.reload(); return true; } catch (e: any) { message.error(e?.message || '提交失败'); return false; } }; return ( <> actionRef={actionRef} rowKey="id" columns={columns} request={tableRequest} toolBarRender={() => [ , // 同步包括 orders subscriptions 等等 ]} /> title={editing ? '编辑站点' : '新增站点'} open={open} onOpenChange={setOpen} formRef={formRef} onFinish={handleSubmit} > {/* 站点名称,必填 */} {/* 区域选择 */} { 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 && } ); }; export default SiteList;