hejianhao
2026-08-18 3ec85d8a7b95570733f284d8dfc9531090830556
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
import RegionCascader from '@/components/RegionCascader';
import { PlusOutlined } from '@ant-design/icons';
import { history, useAccess } from '@umijs/max';
import { Button, Descriptions, Form, Input, Modal, Pagination, Space, Table, message } from 'antd';
import React, { useEffect, useState } from 'react';
import { createAgent, deleteAgent, getAgentDetail, getAgentPage, updateAgent } from './service';
 
type RegionValue = { regionCode?: string[]; regionName?: string };
type AgentItem = { id: number; agentName: string; contactInfo?: string; address?: string; regionNames?: string[]; createdAt?: string };
 
const AgentPage: React.FC = () => {
  const access = useAccess();
  const [searchForm] = Form.useForm<{ regionPath?: string[]; agentName?: string }>();
  const [form] = Form.useForm();
  const [list, setList] = useState<AgentItem[]>([]);
  const [pagination, setPagination] = useState({ page: 1, pageSize: 10, total: 0 });
  const [loading, setLoading] = useState(false);
  const [open, setOpen] = useState(false);
  const [detail, setDetail] = useState<any>();
  const [editingId, setEditingId] = useState<number>();
  const canView = access['member:agent:view'];
 
  const load = async (page = 1, pageSize = pagination.pageSize) => {
    const search = searchForm.getFieldsValue();
    setLoading(true);
    try {
      const response = await getAgentPage({
        page,
        pageSize,
        agentName: search.agentName?.trim() || undefined,
        regionCode: search.regionPath?.[search.regionPath.length - 1],
      });
      setList(response.data?.list || []);
      setPagination({
        page: Number(response.data?.page || page),
        pageSize: Number(response.data?.pageSize || pageSize),
        total: Number(response.data?.total || 0),
      });
    } finally {
      setLoading(false);
    }
  };
 
  useEffect(() => {
    if (!canView) history.replace('/Welcome');
    else void load();
  }, [canView]);
 
  const openForm = async (id?: number) => {
    setEditingId(id);
    setDetail(undefined);
    setOpen(true);
    form.resetFields();
    if (!id) {
      form.setFieldsValue({ regions: [{}] });
      return;
    }
    const response = await getAgentDetail(id);
    form.setFieldsValue({
      ...response.data,
      regions: (response.data?.regions || []).map((region: any) => ({
        ...region,
        regionCode: region.regionPath,
      })),
    });
  };
 
  const openDetail = async (id: number) => {
    const response = await getAgentDetail(id);
    setEditingId(undefined);
    setDetail(response.data);
    setOpen(true);
  };
 
  const submit = async () => {
    const values = await form.validateFields();
    const regions = (values.regions || []).map((region: RegionValue) => ({
      regionCode: region.regionCode?.[region.regionCode.length - 1],
    }));
    try {
      if (editingId) await updateAgent(editingId, { ...values, regions });
      else await createAgent({ ...values, regions });
      message.success(editingId ? '保存成功' : '新增成功');
      setOpen(false);
      await load(editingId ? pagination.page : 1);
    } catch (error) {
      message.error((error as Error)?.message || '保存失败');
    }
  };
 
  const columns = [
    { title: '序号', width: 70, render: (_: any, __: any, index: number) => (pagination.page - 1) * pagination.pageSize + index + 1 },
    { title: '代理负责人', dataIndex: 'agentName' },
    { title: '负责省份', render: (_: any, record: AgentItem) => (record.regionNames || []).join('、') || '-' },
    { title: '联系信息', dataIndex: 'contactInfo', render: (value: string) => value || '-' },
    { title: '详细地址', dataIndex: 'address', render: (value: string) => value || '-' },
    { title: '创建时间', dataIndex: 'createdAt', width: 180 },
    {
      title: '操作',
      width: 180,
      render: (_: any, record: AgentItem, index: number) => <Space size={0}>
        {access['member:agent:detail'] && <Button type="link" onClick={() => openDetail(record.id)}>详情</Button>}
        {access['member:agent:edit'] && <Button type="link" onClick={() => openForm(record.id)}>编辑</Button>}
        {access['member:agent:delete'] && !(pagination.page === 1 && index === 0) && <Button type="link" danger onClick={() => Modal.confirm({
          title: '确定删除该省代理吗?',
          onOk: async () => { await deleteAgent(record.id); message.success('删除成功'); await load(); },
        })}>删除</Button>}
      </Space>,
    },
  ];
 
  return <div style={{ padding: 24 }}>
    <h2>省代理管理</h2>
    <Form form={searchForm} layout="inline" onFinish={() => load(1)}>
      <Form.Item name="regionPath" label="负责省份"><RegionCascader allowClear changeOnSelect placeholder="全部" /></Form.Item>
      <Form.Item name="agentName" label="代理负责人"><Input allowClear placeholder="请输入" /></Form.Item>
      <Button onClick={() => { searchForm.resetFields(); void load(1); }}>重置</Button>
      <Button type="primary" htmlType="submit" style={{ marginLeft: 8 }}>查询</Button>
    </Form>
    <div style={{ margin: '16px 0' }}>{access['member:agent:add'] && <Button type="primary" icon={<PlusOutlined />} onClick={() => openForm()}>新增</Button>}</div>
    <Table rowKey="id" columns={columns as any} dataSource={list} loading={loading} pagination={false} />
    <Pagination style={{ marginTop: 16, textAlign: 'right' }} current={pagination.page} pageSize={pagination.pageSize} total={pagination.total} showSizeChanger onChange={load} />
    <Modal open={open} title={detail ? '省代理详情' : editingId ? '编辑省代理' : '新增省代理'} width={760} onCancel={() => setOpen(false)} footer={detail ? null : <><Button onClick={() => setOpen(false)}>取消</Button><Button type="primary" onClick={submit}>确定</Button></>}>
      {detail ? <Descriptions bordered column={2} items={[
        ['代理负责人', detail.agentName], ['负责省份', (detail.regionNames || []).join('、')],
        ['开户银行', detail.bankName], ['银行账号', detail.accountNumber], ['账户名称', detail.accountHolder],
        ['开户支行', detail.branchName], ['联系信息', detail.contactInfo], ['详细地址', detail.address],
      ].map(([label, children]) => ({ label, children: children || '-' }))} /> :
        <Form form={form} labelCol={{ span: 5 }}>
          <Form.Item name="agentName" label="代理负责人" rules={[{ required: true, message: '请输入代理负责人' }]}><Input maxLength={50} /></Form.Item>
          <Form.List name="regions" rules={[{ validator: async (_, value) => { if (!value?.length) throw new Error('请选择负责省份'); } }]}>
            {(fields, { add, remove }, { errors }) => <Form.Item label="负责省份" required>
              {fields.map(({ key, name, ...rest }) => <Space key={key} align="baseline">
                <Form.Item {...rest} name={[name, 'regionCode']} rules={[{ required: true, message: '请选择负责省份' }]}><RegionCascader changeOnSelect /></Form.Item>
                {fields.length > 1 && <Button onClick={() => remove(name)}>删除</Button>}
              </Space>)}
              <Button type="dashed" onClick={() => add({})}>添加负责省份</Button>
              <Form.ErrorList errors={errors} />
            </Form.Item>}
          </Form.List>
          <Form.Item name="bankName" label="开户银行"><Input maxLength={100} /></Form.Item>
          <Form.Item name="accountNumber" label="银行账号"><Input maxLength={30} /></Form.Item>
          <Form.Item name="accountHolder" label="账户名称"><Input maxLength={50} /></Form.Item>
          <Form.Item name="branchName" label="开户支行"><Input maxLength={100} /></Form.Item>
          <Form.Item name="contactInfo" label="联系信息"><Input maxLength={200} /></Form.Item>
          <Form.Item name="address" label="详细地址"><Input.TextArea rows={3} maxLength={255} /></Form.Item>
        </Form>}
    </Modal>
  </div>;
};
 
export default AgentPage;