222 lines
7.1 KiB
TypeScript
222 lines
7.1 KiB
TypeScript
import { ActionType, DrawerForm, PageContainer, ProColumns, ProFormText, ProTable } from '@ant-design/pro-components';
|
||
import { request, useParams } from '@umijs/max';
|
||
import { App, Avatar, Button, Popconfirm, Space, Tag } from 'antd';
|
||
import React, { useRef, useState } from 'react';
|
||
import { DeleteFilled, EditOutlined, PlusOutlined, UserOutlined } from '@ant-design/icons';
|
||
|
||
const CustomerPage: React.FC = () => {
|
||
const { message } = App.useApp();
|
||
const { siteId } = useParams<{ siteId: string }>();
|
||
const [editing, setEditing] = useState<any>(null);
|
||
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
|
||
const actionRef = useRef<ActionType>();
|
||
|
||
const handleDelete = async (id: number) => {
|
||
if (!siteId) return;
|
||
try {
|
||
const res = await request(`/site-api/${siteId}/customers/${id}`, { method: 'DELETE' });
|
||
if (res.success) {
|
||
message.success('删除成功');
|
||
actionRef.current?.reload();
|
||
} else {
|
||
message.error(res.message || '删除失败');
|
||
}
|
||
} catch (e) {
|
||
message.error('删除失败');
|
||
}
|
||
};
|
||
|
||
const columns: ProColumns<any>[] = [
|
||
{
|
||
title: '头像',
|
||
dataIndex: 'avatar_url',
|
||
hideInSearch: true,
|
||
width: 80,
|
||
render: (_, record) => {
|
||
// 从raw数据中获取头像URL,因为DTO中没有这个字段
|
||
const avatarUrl = record.raw?.avatar_url || record.avatar_url;
|
||
return <Avatar src={avatarUrl} icon={<UserOutlined />} size="large" />;
|
||
},
|
||
},
|
||
{
|
||
title: '姓名',
|
||
dataIndex: 'username',
|
||
render: (_, record) => {
|
||
// DTO中有first_name和last_name字段,username可能从raw数据中获取
|
||
const username = record.username || record.raw?.username || 'N/A';
|
||
return (
|
||
<div>
|
||
<div>{username}</div>
|
||
<div style={{ fontSize: 12, color: '#888' }}>
|
||
{record.first_name} {record.last_name}
|
||
</div>
|
||
</div>
|
||
);
|
||
},
|
||
},
|
||
{
|
||
title: '邮箱',
|
||
dataIndex: 'email',
|
||
copyable: true,
|
||
},
|
||
{
|
||
title: '角色',
|
||
dataIndex: 'role',
|
||
render: (_, record) => {
|
||
// 角色信息可能从raw数据中获取,因为DTO中没有这个字段
|
||
const role = record.role || record.raw?.role || 'N/A';
|
||
return <Tag color="blue">{role}</Tag>;
|
||
},
|
||
},
|
||
{
|
||
title: '账单地址',
|
||
dataIndex: 'billing',
|
||
hideInSearch: true,
|
||
render: (_, record) => {
|
||
const { billing } = record;
|
||
if (!billing) return '-';
|
||
return (
|
||
<div style={{ fontSize: 12 }}>
|
||
<div>{billing.address_1} {billing.address_2}</div>
|
||
<div>{billing.city}, {billing.state}, {billing.postcode}</div>
|
||
<div>{billing.country}</div>
|
||
<div>{billing.phone}</div>
|
||
</div>
|
||
);
|
||
},
|
||
},
|
||
{
|
||
title: '注册时间',
|
||
dataIndex: 'date_created',
|
||
valueType: 'dateTime',
|
||
hideInSearch: true,
|
||
},
|
||
{
|
||
title: '操作',
|
||
valueType: 'option',
|
||
width: 120,
|
||
render: (_, record) => (
|
||
<Space>
|
||
<Button type="link" title="编辑" icon={<EditOutlined />} onClick={() => setEditing(record)} />
|
||
<Popconfirm title="确定删除?" onConfirm={() => handleDelete(record.id)}>
|
||
<Button type="link" danger title="删除" icon={<DeleteFilled />} />
|
||
</Popconfirm>
|
||
</Space>
|
||
),
|
||
},
|
||
];
|
||
|
||
return (
|
||
<PageContainer
|
||
ghost
|
||
header={{
|
||
title: null,
|
||
breadcrumb: undefined
|
||
}}
|
||
>
|
||
<ProTable
|
||
rowKey="id"
|
||
columns={columns}
|
||
search={false}
|
||
options={false}
|
||
actionRef={actionRef}
|
||
rowSelection={{
|
||
selectedRowKeys,
|
||
onChange: setSelectedRowKeys,
|
||
}}
|
||
request={async (params) => {
|
||
if (!siteId) return { data: [], total: 0, success: true };
|
||
const response = await request(`/site-api/${siteId}/customers`, {
|
||
params: { page: params.current, per_page: params.pageSize },
|
||
});
|
||
|
||
if (!response.success) {
|
||
message.error(response.message || '获取客户列表失败');
|
||
return {
|
||
data: [],
|
||
total: 0,
|
||
success: false,
|
||
};
|
||
}
|
||
|
||
const data = response.data;
|
||
return {
|
||
total: data?.total || 0,
|
||
data: data?.items || [],
|
||
success: true,
|
||
};
|
||
}}
|
||
toolBarRender={() => [
|
||
<DrawerForm
|
||
title="新增客户"
|
||
trigger={<Button type="primary" title="新增" icon={<PlusOutlined />} />}
|
||
onFinish={async (values) => {
|
||
if (!siteId) return false;
|
||
const res = await request(`/site-api/${siteId}/customers`, { method: 'POST', data: values });
|
||
if (res.success) {
|
||
message.success('新增成功');
|
||
actionRef.current?.reload();
|
||
return true;
|
||
}
|
||
message.error(res.message || '新增失败');
|
||
return false;
|
||
}}
|
||
>
|
||
<ProFormText name="email" label="邮箱" rules={[{ required: true }]} />
|
||
<ProFormText name="first_name" label="名" />
|
||
<ProFormText name="last_name" label="姓" />
|
||
<ProFormText name="username" label="用户名" />
|
||
</DrawerForm>,
|
||
<Button
|
||
title="批量编辑"
|
||
icon={<EditOutlined />}
|
||
onClick={() => message.info('批量编辑暂未实现')}
|
||
/>,
|
||
<Button
|
||
title="批量删除"
|
||
danger
|
||
icon={<DeleteFilled />}
|
||
onClick={async () => {
|
||
if (!siteId) return;
|
||
let ok = 0, fail = 0;
|
||
for (const id of selectedRowKeys) {
|
||
const res = await request(`/site-api/${siteId}/customers/${id}`, { method: 'DELETE' });
|
||
if (res.success) ok++; else fail++;
|
||
}
|
||
message.success(`删除成功 ${ok} 条, 失败 ${fail} 条`);
|
||
actionRef.current?.reload();
|
||
setSelectedRowKeys([]);
|
||
}}
|
||
/>
|
||
]}
|
||
/>
|
||
|
||
<DrawerForm
|
||
title="编辑客户"
|
||
open={!!editing}
|
||
onOpenChange={(visible) => !visible && setEditing(null)}
|
||
initialValues={editing || {}}
|
||
onFinish={async (values) => {
|
||
if (!siteId || !editing) return false;
|
||
const res = await request(`/site-api/${siteId}/customers/${editing.id}`, { method: 'PUT', data: values });
|
||
if (res.success) {
|
||
message.success('更新成功');
|
||
actionRef.current?.reload();
|
||
setEditing(null);
|
||
return true;
|
||
}
|
||
message.error(res.message || '更新失败');
|
||
return false;
|
||
}}
|
||
>
|
||
<ProFormText name="email" label="邮箱" rules={[{ required: true }]} />
|
||
<ProFormText name="first_name" label="名" />
|
||
<ProFormText name="last_name" label="姓" />
|
||
<ProFormText name="username" label="用户名" />
|
||
</DrawerForm>
|
||
</PageContainer>
|
||
);
|
||
};
|
||
|
||
export default CustomerPage;
|