import { useEffect, useState } from 'react'; import { Button, Descriptions, Drawer, Form, Input, Segmented, Space, Table, Tag, Typography } from 'antd'; import type { ColumnsType } from 'antd/es/table'; import { useSearchParams } from 'react-router-dom'; import { STORE_LOG_CATEGORY_OPTIONS, STORE_LOG_CATEGORY_LABELS, resolveStoreLogCategory, type StoreLogCategory, } from '../lib/store-log'; import { request } from '../lib/api'; import { AdminCellLine } from '../components/AdminCellLine'; import { fmtTime } from '../lib/constants'; import { useAdminList } from '../lib/useAdminList'; type Row = { id: string; source: 'analytics' | 'redeem_record' | 'store_payout'; storeId: string; storeAccountId: string | null; storeName: string | null; accountName: string | null; accountPhone: string | null; category: StoreLogCategory | null; eventName: string; clientApp: string | null; refType: string | null; refId: string | null; extraJson: Record | null; createdAt: string; }; const SOURCE_LABELS: Record = { analytics: '行为埋点', redeem_record: '核销记录', store_payout: '打款记录', }; function summarizeExtra(json: Record | null) { if (!json) return '—'; const text = JSON.stringify(json); return text.length > 80 ? `${text.slice(0, 80)}…` : text; } function parseCompositeId(id: string) { const idx = id.indexOf(':'); if (idx <= 0) return null; return { source: id.slice(0, idx), rawId: id.slice(idx + 1) }; } export default function StoreLogsPage() { const [searchParams, setSearchParams] = useSearchParams(); const [form] = Form.useForm(); const [category, setCategory] = useState(searchParams.get('category') ?? ''); const [filters, setFilters] = useState>(() => ({ storeId: searchParams.get('storeId') ?? '', storeAccountId: searchParams.get('storeAccountId') ?? '', phone: searchParams.get('phone') ?? '', storeName: searchParams.get('storeName') ?? '', eventName: searchParams.get('eventName') ?? '', })); const { data, loading, page, pageSize, setPage, setPageSize } = useAdminList( '/admin/logs/stores', () => { const qs = new URLSearchParams(); if (filters.storeId) qs.set('storeId', filters.storeId); if (filters.storeAccountId) qs.set('storeAccountId', filters.storeAccountId); if (filters.phone) qs.set('phone', filters.phone); if (filters.storeName) qs.set('storeName', filters.storeName); if (filters.eventName) qs.set('eventName', filters.eventName); if (category) qs.set('category', category); return qs; }, [filters, category], ); const [detail, setDetail] = useState | null>(null); const [drawerOpen, setDrawerOpen] = useState(false); useEffect(() => { form.setFieldsValue(filters); }, [form, filters]); const columns: ColumnsType = [ { title: '时间', dataIndex: 'createdAt', width: 160, render: fmtTime }, { title: '门店', width: 180, ellipsis: true, render: (_, r) => , }, { title: '账号', width: 150, ellipsis: true, render: (_, r) => ( ), }, { title: '分类', dataIndex: 'category', width: 100, render: (v: StoreLogCategory | null, r) => ( {STORE_LOG_CATEGORY_LABELS[v ?? ''] || resolveStoreLogCategory(r.eventName) || '其他'} ), }, { title: '事件', dataIndex: 'eventName', width: 160 }, { title: '来源', dataIndex: 'source', width: 100, render: (v: Row['source']) => SOURCE_LABELS[v] || v, }, { title: '关联', width: 120, render: (_, r) => (r.refType && r.refId ? `${r.refType}#${r.refId}` : '—'), }, { title: '摘要', ellipsis: true, render: (_, r) => summarizeExtra(r.extraJson), }, { title: '操作', width: 80, render: (_, row) => ( ), }, ]; return (
商户日志 门店登录、微信授权、核销、打款与营业状态等操作记录;历史核销/打款数据来自业务表归档。 ({ value: o.value, label: o.label }))} value={category} onChange={(v) => { setCategory(String(v)); setPage(1); const next = new URLSearchParams(searchParams); if (v) next.set('category', String(v)); else next.delete('category'); setSearchParams(next); }} />
{ setFilters(v); setPage(1); const next = new URLSearchParams(searchParams); for (const key of ['storeId', 'storeAccountId', 'phone', 'storeName', 'eventName'] as const) { if (v[key]) next.set(key, v[key]); else next.delete(key); } setSearchParams(next); }}>
{ setPage(p); setPageSize(ps); } }} /> setDrawerOpen(false)}> {detail && ( {String(detail.id)} {String(detail.storeName || detail.storeId || '—')} {String(detail.accountName || detail.storeAccountId || '系统/HQ')} {String(detail.accountPhone || '—')} {(STORE_LOG_CATEGORY_LABELS as Record)[String(detail.category ?? '')] || String(detail.category || '—')} {String(detail.eventName)} {SOURCE_LABELS[String(detail.source) as Row['source']] || String(detail.source || '—')} {String(detail.clientApp || '—')} {detail.refType ? `${String(detail.refType)}#${String(detail.refId)}` : '—'} {fmtTime(String(detail.createdAt))}
                {JSON.stringify(detail.extraJson ?? {}, null, 2)}
              
)}
); }