import { useCallback, useEffect, useMemo, useState } from 'react'; import { Link, useNavigate, useSearchParams } from 'react-router-dom'; import PullToRefresh from '@dukang/shared-ui/PullToRefresh'; import { isLoggedIn, request } from '../lib/api'; import { toastSuccess } from '../lib/toast'; import { usePartnerSession } from '../contexts/PartnerSessionContext'; import { canCreatePartnerStore, canManagePartnerStore } from '../lib/partnerAccess'; import { canPartnerOpenStore, storeAuditLabel, storeListBadge, type StoreStatusValue, } from '../lib/storeStatus'; import { usePartnerPageView } from '../lib/usePageView'; type StatusFilter = 'ALL' | StoreStatusValue | 'PENDING_AUDIT' | 'REJECTED'; const FILTERS: { key: StatusFilter; label: string }[] = [ { key: 'ALL', label: '全部' }, { key: 'OPEN', label: '营业中' }, { key: 'PAUSED', label: '临时闭店' }, { key: 'PENDING_AUDIT', label: '待审核' }, { key: 'REJECTED', label: '已驳回' }, { key: 'CLOSED', label: '永久闭店' }, ]; export default function StoreListPage() { usePartnerPageView('partner_store_list_view'); const navigate = useNavigate(); const [searchParams] = useSearchParams(); const { account } = usePartnerSession(); const canMutate = canManagePartnerStore(account); const canCreate = canCreatePartnerStore(account); const [stores, setStores] = useState>>([]); const [q, setQ] = useState(''); const initialFilter = (searchParams.get('audit') === 'pending' ? 'PENDING_AUDIT' : 'ALL') as StatusFilter; const [filter, setFilter] = useState(initialFilter); const [updatingId, setUpdatingId] = useState(null); const [error, setError] = useState(''); const [closeTarget, setCloseTarget] = useState(null); const loadStores = useCallback(() => { return request>>('PARTNER_H5', '/partner/stores').then(setStores); }, []); useEffect(() => { if (!isLoggedIn()) { navigate('/login'); return; } void loadStores(); }, [navigate, loadStores]); useEffect(() => { document.title = canMutate ? '门店管理' : '我的门店'; }, [canMutate]); const filtered = useMemo( () => stores.filter((s) => { const matchQ = !q || String(s.name).includes(q) || String(s.address).includes(q); const audit = String(s.auditStatus || 'APPROVED').toUpperCase(); const status = String(s.status).toUpperCase(); let matchStatus = true; if (filter === 'PENDING_AUDIT') matchStatus = audit === 'PENDING'; else if (filter === 'REJECTED') matchStatus = audit === 'REJECTED'; else if (filter !== 'ALL') matchStatus = status === filter; return matchQ && matchStatus; }), [stores, q, filter], ); async function updateStatus(storeId: string, next: StoreStatusValue, auditStatus?: string) { if (next === 'OPEN' && !canPartnerOpenStore(auditStatus)) { setError( auditStatus === 'REJECTED' ? '门店审核未通过,请查看驳回原因并修改后重新提交' : '门店尚在总部审核中,通过后方可开门', ); return; } if (next === 'CLOSED') { setCloseTarget(storeId); return; } setUpdatingId(storeId); setError(''); try { await request('PARTNER_H5', `/partner/stores/${storeId}/status`, { method: 'PUT', body: JSON.stringify({ status: next }), }); await loadStores(); if (next === 'OPEN') toastSuccess('已营业'); if (next === 'PAUSED') toastSuccess('已临时闭店'); } catch { /* request 已 toast */ } finally { setUpdatingId(null); } } async function confirmCloseStore() { if (!closeTarget) return; const storeId = closeTarget; setCloseTarget(null); setUpdatingId(storeId); setError(''); try { await request('PARTNER_H5', `/partner/stores/${storeId}/status`, { method: 'PUT', body: JSON.stringify({ status: 'CLOSED' }), }); await loadStores(); toastSuccess('已永久闭店'); } catch { /* request 已 toast */ } finally { setUpdatingId(null); } } return ( {error && (

{error}

)}
search setQ(e.target.value)} />
{canCreate && ( )} {filtered.length === 0 &&
暂无门店
} {filtered.map((s) => { const storeId = String(s.id); const currentStatus = String(s.status).toUpperCase() as StoreStatusValue; const auditStatus = String(s.auditStatus || 'APPROVED').toUpperCase(); const dim = currentStatus === 'CLOSED'; const storeName = String(s.name || '未命名门店'); const busy = updatingId === storeId; const badge = storeListBadge(s); const switchOn = currentStatus === 'OPEN'; const switchDisabled = busy || currentStatus === 'CLOSED' || auditStatus === 'PENDING' || auditStatus === 'REJECTED'; return (

门店名称

{storeName}

{String(s.address || s.district || '')}

{auditStatus === 'REJECTED' && s.rejectReason ? (

{storeAuditLabel(auditStatus)}:{String(s.rejectReason)}

) : null}
{badge.label}
{canMutate ? (
{currentStatus !== 'CLOSED' ? ( <> ) : null} edit
) : null}
); })} {closeTarget && (
setCloseTarget(null)} >
e.stopPropagation()} >

确认永久闭店?

永久闭店后不可再开门营业,确认关闭该门店?

)}
); }