import { customercontrollerAddtag, customercontrollerDeltag, customercontrollerGetcustomerlist, customercontrollerGettags, customercontrollerSetrate, customercontrollerSynccustomers, } from '@/servers/api/customer'; import { sitecontrollerAll } from '@/servers/api/site'; import { ActionType, ModalForm, PageContainer, ProColumns, ProFormDateTimeRangePicker, ProFormSelect, ProFormText, ProTable, } from '@ant-design/pro-components'; import { App, Avatar, Button, Form, Rate, Space, Tag, Tooltip } from 'antd'; import { useEffect, useRef, useState } from 'react'; import HistoryOrders from './HistoryOrders'; // 地址格式化函数 const formatAddress = (address: any) => { if (!address) return '-'; if (typeof address === 'string') { try { address = JSON.parse(address); } catch (e) { return address; } } const { first_name, last_name, company, address_1, address_2, city, state, postcode, country, phone: addressPhone, email: addressEmail, } = address; const parts = []; // 姓名 const fullName = [first_name, last_name].filter(Boolean).join(' '); if (fullName) parts.push(fullName); // 公司 if (company) parts.push(company); // 地址行 if (address_1) parts.push(address_1); if (address_2) parts.push(address_2); // 城市、州、邮编 const locationParts = [city, state, postcode].filter(Boolean).join(', '); if (locationParts) parts.push(locationParts); // 国家 if (country) parts.push(country); // 联系方式 if (addressPhone) parts.push(`电话: ${addressPhone}`); if (addressEmail) parts.push(`邮箱: ${addressEmail}`); return parts.join(', '); }; // 地址卡片组件 const AddressCell: React.FC<{ address: any; title: string }> = ({ address, title, }) => { const formattedAddress = formatAddress(address); if (formattedAddress === '-') { return -; } return ( {title}:
{formattedAddress} } placement="topLeft" >
{formattedAddress}
); }; const CustomerList: React.FC = () => { const actionRef = useRef(); const { message } = App.useApp(); const [syncModalVisible, setSyncModalVisible] = useState(false); const columns: ProColumns[] = [ { title: 'ID', dataIndex: 'id', }, { title: '原始 ID', dataIndex: 'origin_id', sorter: true, }, { title: '站点', dataIndex: 'site_id', valueType: 'select', request: async () => { try { const { data, success } = await sitecontrollerAll(); if (success && data) { return data.map((site: any) => ({ label: site.name, value: site.id, })); } return []; } catch (error) { console.error('获取站点列表失败:', error); return []; } }, }, { title: '头像', dataIndex: 'avatar', hideInSearch: true, width: 60, render: (_, record) => ( {!record.avatar && record.fullname?.charAt(0)?.toUpperCase()} ), }, { title: '姓名', dataIndex: 'fullname', sorter: true, render: (_, record) => { return ( record.fullname || `${record.first_name || ''} ${record.last_name || ''}`.trim() || record.username || '-' ); }, }, { title: '用户名', dataIndex: 'username', copyable: true, sorter: true, }, { title: '邮箱', dataIndex: 'email', copyable: true, sorter: true, }, { title: '电话', dataIndex: 'phone', copyable: true, }, { title: '账单地址', dataIndex: 'billing', hideInSearch: true, width: 200, render: (billing) => , }, { title: '物流地址', dataIndex: 'shipping', hideInSearch: true, width: 200, render: (shipping) => , }, { title: '评分', dataIndex: 'rate', hideInSearch: true, sorter: true, render: (_, record) => { return ( { try { const { success, message: msg } = await customercontrollerSetrate({ id: record.id, rate: val, }); if (success) { message.success(msg); actionRef.current?.reload(); } } catch (e: any) { message.error(e?.message || '设置评分失败'); } }} value={record.rate || 0} allowHalf /> ); }, }, { title: '标签', dataIndex: 'tags', hideInSearch: true, render: (_, record) => { const tags = record?.tags || []; return ( {tags.map((tag: string) => { return ( { const { success, message: msg } = await customercontrollerDeltag({ email: record.email, tag, }); if (!success) { message.error(msg); return false; } actionRef.current?.reload(); return true; }} style={{ marginBottom: 4 }} > {tag} ); })} ); }, }, { title: '创建时间', dataIndex: 'site_created_at', valueType: 'dateTime', hideInSearch: true, sorter: true, width: 140, }, { title: '更新时间', dataIndex: 'site_created_at', valueType: 'dateTime', hideInSearch: true, sorter: true, width: 140, }, { title: '操作', dataIndex: 'option', valueType: 'option', fixed: 'right', width: 120, render: (_, record) => { return ( {/* 订单 */} ); }, }, ]; return ( { console.log('custoemr request',params, sorter,filter) const { current, pageSize, ...restParams } = params; const orderBy:any = {} Object.entries(sorter).forEach(([key, value]) => { orderBy[key] = value === 'ascend' ? 'asc' : 'desc'; }) // 构建查询参数 const queryParams: any = { page: current || 1, per_page: pageSize || 20, where: { ...filter, ...restParams }, orderBy }; const result = await customercontrollerGetcustomerlist({params: queryParams}); console.log(queryParams, result); return { total: result?.data?.total || 0, data: result?.data?.items || [], success: true, }; }} search={{ labelWidth: 'auto', span: 6, }} pagination={{ pageSize: 20, showSizeChanger: true, showQuickJumper: true, }} toolBarRender={() => [ , // 这里可以添加导出、导入等功能按钮 ]} /> setSyncModalVisible(false)} tableRef={actionRef} /> ); }; const AddTag: React.FC<{ email: string; tags?: string[]; tableRef: React.MutableRefObject; }> = ({ email, tags, tableRef }) => { const { message } = App.useApp(); const [tagList, setTagList] = useState([]); return ( 修改标签 } width={800} modalProps={{ destroyOnHidden: true, }} submitter={false} > { const { data, success } = await customercontrollerGettags(); if (!success) return []; setTagList(tags || []); return data .filter((tag: string) => { return !(tags || []).includes(tag); }) .map((tag: string) => ({ label: tag, value: tag })); }} fieldProps={{ value: tagList, // 当前值 onChange: async (newValue) => { const added = newValue.filter((x) => !(tags || []).includes(x)); const removed = (tags || []).filter((x) => !newValue.includes(x)); if (added.length) { const { success, message: msg } = await customercontrollerAddtag({ email, tag: added[0], }); if (!success) { message.error(msg); return; } } if (removed.length) { const { success, message: msg } = await customercontrollerDeltag({ email, tag: removed[0], }); if (!success) { message.error(msg); return; } } tableRef?.current?.reload(); setTagList(newValue); }, }} > ); }; const SyncCustomersModal: React.FC<{ visible: boolean; onClose: () => void; tableRef: React.MutableRefObject; }> = ({ visible, onClose, tableRef }) => { const { message } = App.useApp(); const [sites, setSites] = useState([]); const [loading, setLoading] = useState(false); const [form] = Form.useForm(); // 添加表单实例 // 获取站点列表 useEffect(() => { if (visible) { setLoading(true); sitecontrollerAll() .then((res: any) => { setSites(res?.data || []); }) .catch((error: any) => { message.error('获取站点列表失败: ' + (error.message || '未知错误')); }) .finally(() => { setLoading(false); }); } }, [visible]); // 定义同步参数类型 type SyncParams = { siteId: number; search?: string; role?: string; dateRange?: [string, string]; orderBy?: string; }; const handleSync = async (values: SyncParams) => { try { setLoading(true); // 构建过滤参数 const params: any = {}; // 添加搜索关键词 if (values.search) { params.search = values.search; } // 添加角色过滤 if (values.role) { params.where = { ...params.where, role: values.role, }; } // 添加日期范围过滤(使用 after 和 before 参数) if (values.dateRange && values.dateRange[0] && values.dateRange[1]) { params.where = { ...params.where, after: values.dateRange[0], before: values.dateRange[1], }; } // 添加排序 if (values.orderBy) { params.orderBy = values.orderBy; } const { success, message: msg, data, } = await customercontrollerSynccustomers({ siteId: values.siteId, params: Object.keys(params).length > 0 ? params : undefined, }); if (success) { // 显示详细的同步结果 const result = data || {}; const { total = 0, synced = 0, created = 0, updated = 0, errors = [], } = result; let resultMessage = `同步完成!共处理 ${total} 个客户:`; if (created > 0) resultMessage += ` 新建 ${created} 个`; if (updated > 0) resultMessage += ` 更新 ${updated} 个`; if (synced > 0) resultMessage += ` 同步成功 ${synced} 个`; if (errors.length > 0) resultMessage += ` 失败 ${errors.length} 个`; if (errors.length > 0) { // 如果有错误,显示警告消息 message.warning({ content: (
{resultMessage}
失败详情: {errors .slice(0, 3) .map((err: any) => err.email || err.error) .join(', ')} {errors.length > 3 && ` 等 ${errors.length - 3} 个错误...`}
), duration: 8, key: 'sync-result', }); } else { // 完全成功 message.success({ content: resultMessage, duration: 4, key: 'sync-result', }); } onClose(); // 刷新表格数据 tableRef.current?.reload(); return true; } else { message.error(msg || '同步失败'); return false; } } catch (error: any) { message.error('同步失败: ' + (error.message || '未知错误')); return false; } finally { setLoading(false); } }; return ( !open && onClose()} modalProps={{ destroyOnClose: true, confirmLoading: loading, }} onFinish={handleSync} form={form} > ({ label: site.name, value: site.id, }))} rules={[{ required: true, message: '请选择站点' }]} fieldProps={{ loading: loading, }} /> { return { dateRange: value, }; }} fieldProps={{ showTime: false, style: { width: '100%' }, }} /> ); }; export { AddTag }; export default CustomerList;