import { useState } from 'react'; import { Button, Checkbox, Descriptions, Drawer, Form, Input, Modal, Popconfirm, Select, Space, Table, Tag, Typography, message, } from 'antd'; import type { ColumnsType } from 'antd/es/table'; import { request, type Paginated } from '../lib/api'; import { ACCOUNT_STATUS_LABELS, ADMIN_OPTIONS_PAGE_SIZE, STORE_STATUS_LABELS, fmtTime } from '../lib/constants'; import { useAdminList } from '../lib/useAdminList'; type StoreBrief = { id: string; name: string; status: string; cityName?: string }; type Row = { id: string; phone: string; name: string; status: string; createdAt: string; isTest?: boolean; storeCount?: number; staffCount?: number; bankAccountName?: string | null; bankAccountNo?: string | null; bankBranch?: string | null; store?: StoreBrief | null; stores?: StoreBrief[]; staff?: Array<{ id: string; name: string; phone: string; status: string; storeIds?: string[] }>; }; type StoreOption = { id: string; name: string }; export default function StoreAccountsPage() { const [form] = Form.useForm(); const [createForm] = Form.useForm(); const [filters, setFilters] = useState>({}); const { data, loading, page, pageSize, setPage, setPageSize, reload } = useAdminList( '/admin/store-accounts', () => { const qs = new URLSearchParams(); if (filters.phone) qs.set('phone', String(filters.phone)); if (filters.status) qs.set('status', String(filters.status)); if (filters.excludeTest) qs.set('excludeTest', 'true'); return qs; }, [filters], ); const [detail, setDetail] = useState(null); const [drawerOpen, setDrawerOpen] = useState(false); const [createOpen, setCreateOpen] = useState(false); const [stores, setStores] = useState([]); const [deletingStaffId, setDeletingStaffId] = useState(null); async function loadStores() { const res = await request>(`/admin/stores?pageSize=${ADMIN_OPTIONS_PAGE_SIZE}`); setStores(res.items); } async function refreshDetail(accountId: string) { const d = await request(`/admin/store-accounts/${accountId}`); setDetail(d); void reload(); } async function deleteStaff(staffId: string) { if (!detail) return; setDeletingStaffId(staffId); try { await request(`/admin/store-accounts/${detail.id}/staff/${staffId}`, { method: 'DELETE' }); message.success('子账号已删除'); await refreshDetail(detail.id); } catch (e) { message.error(e instanceof Error ? e.message : '删除失败'); } finally { setDeletingStaffId(null); } } const columns: ColumnsType = [ { title: '姓名', dataIndex: 'name', width: 120, render: (v, row) => ( {v} {row.isTest ? 测试 : null} ), }, { title: '手机', dataIndex: 'phone', width: 120 }, { title: '绑定门店', width: 180, render: (_, row) => row.stores?.length ? row.stores.map((s) => s.name).join('、') : row.store?.name ?? '—', }, { title: '门店数', dataIndex: 'storeCount', width: 70, render: (n, row) => n ?? row.stores?.length ?? 0, }, { title: '子账号', dataIndex: 'staffCount', width: 70, render: (n) => n ?? 0, }, { title: '收款户名', dataIndex: 'bankAccountName', width: 120, render: (v) => v || '—', }, { title: '账号状态', dataIndex: 'status', width: 90, render: (s) => {ACCOUNT_STATUS_LABELS[s] || s}, }, { title: '创建', dataIndex: 'createdAt', width: 160, render: fmtTime }, { title: '操作', width: 80, render: (_, row) => ( ), }, ]; return (
门店账户 主账号可绑定多家门店;收款信息挂在主账号;「新建账户」用于补录无主账号门店
{ setFilters(v); setPage(1); }} > ({ value, label }))} onChange={async (status) => { await request(`/admin/store-accounts/${detail.id}`, { method: 'PUT', body: JSON.stringify({ status }), }); message.success('已更新'); void reload(); }} /> ) } > {detail && ( <> {detail.name} {detail.phone} {detail.bankAccountName || '—'} {detail.bankAccountNo || '—'} {detail.bankBranch || '—'} {(detail.stores ?? []).map((s) => ( {s.name} {s.status ? `(${STORE_STATUS_LABELS[s.status] || s.status})` : ''} ))} {!detail.stores?.length ? '—' : null} {detail.staff?.length ? ( <> 子账号 {ACCOUNT_STATUS_LABELS[s] || s}, }, { title: '操作', width: 80, render: (_, staff) => ( void deleteStaff(staff.id)} > ), }, ]} /> ) : ( 暂无子账号 )} )} setCreateOpen(false)} onOk={async () => { const v = await createForm.validateFields(); await request('/admin/store-accounts', { method: 'POST', body: JSON.stringify(v) }); message.success('已创建'); setCreateOpen(false); createForm.resetFields(); void reload(); }} > ); }