feat(admin): delete store staff; city store count links to filtered list
CI / verify (pull_request) Has been cancelled

HQ can remove store sub-accounts from primary account detail; cities table store count jumps to /stores?cityId=.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-28 15:43:09 +08:00
parent 0cb2b2cebb
commit 118d57d710
7 changed files with 141 additions and 7 deletions
+50 -4
View File
@@ -1,5 +1,5 @@
import { useMemo, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { useEffect, useMemo, useState } from 'react';
import { useNavigate, useSearchParams } from 'react-router-dom';
import {
Alert,
Button,
@@ -322,10 +322,14 @@ type CategoryNode = {
export default function StoresPage() {
const navigate = useNavigate();
const [searchParams] = useSearchParams();
const initialCityId = searchParams.get('cityId') ?? '';
const [form] = Form.useForm();
const [editForm] = Form.useForm();
const [createForm] = Form.useForm<StoreCreateForm>();
const [filters, setFilters] = useState<Record<string, string>>({});
const [filters, setFilters] = useState<Record<string, string>>(() =>
initialCityId ? { cityId: initialCityId } : {},
);
const { data, loading, page, pageSize, setPage, setPageSize, reload } = useAdminList<StoreRow>(
'/admin/stores',
() => {
@@ -334,10 +338,12 @@ export default function StoresPage() {
if (filters.status) qs.set('status', filters.status);
if (filters.auditStatus) qs.set('auditStatus', filters.auditStatus);
if (filters.phone) qs.set('phone', filters.phone);
if (filters.cityId) qs.set('cityId', filters.cityId);
return qs;
},
[filters],
);
const [filterCities, setFilterCities] = useState<CityOption[]>([]);
const [detail, setDetail] = useState<Record<string, unknown> | null>(null);
const [drawerOpen, setDrawerOpen] = useState(false);
const [rejectOpen, setRejectOpen] = useState(false);
@@ -356,6 +362,25 @@ export default function StoresPage() {
const [saving, setSaving] = useState(false);
const [phoneMismatch, setPhoneMismatch] = useState<string | null>(null);
useEffect(() => {
void request<Paginated<CityOption>>(`/admin/cities?pageSize=${ADMIN_OPTIONS_PAGE_SIZE}`)
.then((res) => setFilterCities(res.items))
.catch(() => {});
}, []);
useEffect(() => {
const cityId = searchParams.get('cityId') ?? '';
setFilters((prev) => {
if ((prev.cityId ?? '') === cityId) return prev;
const next = { ...prev };
if (cityId) next.cityId = cityId;
else delete next.cityId;
return next;
});
form.setFieldsValue({ cityId: cityId || undefined });
if (cityId) setPage(1);
}, [searchParams, form, setPage]);
const selectedPartnerId = Form.useWatch('partnerAccountId', createForm);
const selectedRegionCodes = Form.useWatch('regionCodes', createForm);
const selectedCityId = Form.useWatch('cityId', createForm);
@@ -726,6 +751,16 @@ export default function StoresPage() {
<Form form={form} layout="inline" style={{ marginBottom: 16 }} onFinish={(v) => { setFilters(v); setPage(1); }}>
<Form.Item name="name" label="名称"><Input allowClear /></Form.Item>
<Form.Item name="phone" label="电话"><Input allowClear /></Form.Item>
<Form.Item name="cityId" label="城市">
<Select
allowClear
showSearch
optionFilterProp="label"
style={{ width: 140 }}
placeholder="全部"
options={filterCities.map((c) => ({ value: c.id, label: c.name }))}
/>
</Form.Item>
<Form.Item name="status" label="营业状态">
<Select allowClear style={{ width: 100 }} placeholder="全部" options={Object.entries(STORE_STATUS_LABELS).map(([value, label]) => ({ value, label }))} />
</Form.Item>
@@ -738,7 +773,18 @@ export default function StoresPage() {
/>
</Form.Item>
<Form.Item><Button type="primary" htmlType="submit"></Button></Form.Item>
<Form.Item><Button onClick={() => { form.resetFields(); setFilters({}); setPage(1); }}></Button></Form.Item>
<Form.Item>
<Button
onClick={() => {
form.resetFields();
setFilters({});
setPage(1);
if (searchParams.has('cityId')) navigate('/stores', { replace: true });
}}
>
</Button>
</Form.Item>
</Form>
<Table rowKey="id" className="admin-table-nowrap" loading={loading} columns={columns} dataSource={data?.items ?? []} scroll={{ x: 1200 }}
pagination={{ current: page, pageSize, total: data?.total ?? 0, showSizeChanger: true, onChange: (p, ps) => { setPage(p); setPageSize(ps); } }} />