客服电话 → 13203801799(CUSTOMER_SERVICE_PHONE,协议文案走常量自动同步)
权益页去掉分享按钮,菜单分享保留 支付成功改 reLaunch 清栈;订单列表返回首页 减数量低于起购时 toast「同城/跨城/现场提货至少购买 N 瓶」 核销成功可评星并 POST /redeem/ratings;HQ 新增「门店评价」页 /store-ratings 成功页「回到首页」改用 .redeem-cancel-btn,不再撑破布局 历史记录改为核销流水:GET /redeem/records;生产库已有 2 笔(用户 13073729990)可验证。权益明细字段映射也一并修了 我的页头像提高点击层级,避免被卡片遮挡
This commit is contained in:
@@ -6,6 +6,7 @@ import DashboardPage from './pages/DashboardPage';
|
||||
import UsersPage from './pages/UsersPage';
|
||||
import OrdersPage from './pages/OrdersPage';
|
||||
import StoresPage from './pages/StoresPage';
|
||||
import StoreRatingsPage from './pages/StoreRatingsPage';
|
||||
import StoreAccountsPage from './pages/StoreAccountsPage';
|
||||
import BenefitCouponsPage from './pages/BenefitCouponsPage';
|
||||
import BenefitLedgersPage from './pages/BenefitLedgersPage';
|
||||
@@ -78,6 +79,7 @@ export default function App() {
|
||||
<Route path="/products" element={<ProductsPage />} />
|
||||
<Route path="/product-detail-templates" element={<ProductDetailTemplatesPage />} />
|
||||
<Route path="/stores" element={<StoresPage />} />
|
||||
<Route path="/store-ratings" element={<StoreRatingsPage />} />
|
||||
<Route path="/store-categories" element={<StoreCategoriesPage />} />
|
||||
<Route path="/store-accounts" element={<StoreAccountsPage />} />
|
||||
<Route path="/store-media" element={<StoreMediaPage />} />
|
||||
|
||||
@@ -51,6 +51,7 @@ const MENU_ITEMS: MenuProps['items'] = [
|
||||
label: '门店',
|
||||
children: [
|
||||
{ key: '/stores', label: '门店列表' },
|
||||
{ key: '/store-ratings', label: '门店评价' },
|
||||
{ key: '/store-categories', label: '门店分类' },
|
||||
{ key: '/store-accounts', label: '门店账户' },
|
||||
{ key: '/store-media', label: '门店资源' },
|
||||
@@ -145,6 +146,7 @@ function menuAllowed(key: string, permissionKeys: string[]): boolean {
|
||||
'/knowledge-bases': 'knowledge_bases',
|
||||
'stores-group': 'stores',
|
||||
'/stores': 'stores',
|
||||
'/store-ratings': 'stores',
|
||||
'/store-categories': 'stores',
|
||||
'/store-accounts': 'stores',
|
||||
'/store-media': 'stores',
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
import { useState } from 'react';
|
||||
import { useState } from 'react';
|
||||
import { Button, Form, Input, Table, Typography } from 'antd';
|
||||
import type { ColumnsType } from 'antd/es/table';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import { fmtTime } from '../lib/constants';
|
||||
import { useAdminList } from '../lib/useAdminList';
|
||||
|
||||
type Row = {
|
||||
id: string;
|
||||
serviceScore: number;
|
||||
envScore: number;
|
||||
createdAt: string;
|
||||
redeemNo: string;
|
||||
redeemAmount: number;
|
||||
store?: { id: string; name: string; cityName?: string };
|
||||
user?: { userNo: string; phone: string | null; nickname: string | null };
|
||||
};
|
||||
|
||||
export default function StoreRatingsPage() {
|
||||
const [searchParams] = useSearchParams();
|
||||
const initialStoreId = searchParams.get('storeId') || '';
|
||||
const [form] = Form.useForm();
|
||||
const [filters, setFilters] = useState<Record<string, string>>({
|
||||
...(initialStoreId ? { storeId: initialStoreId } : {}),
|
||||
});
|
||||
|
||||
const { data, loading, page, pageSize, setPage, setPageSize } = useAdminList<Row>(
|
||||
'/admin/store-ratings',
|
||||
() => {
|
||||
const qs = new URLSearchParams();
|
||||
if (filters.storeId) qs.set('storeId', filters.storeId);
|
||||
if (filters.redeemNo) qs.set('redeemNo', filters.redeemNo);
|
||||
return qs;
|
||||
},
|
||||
[filters],
|
||||
);
|
||||
|
||||
const columns: ColumnsType<Row> = [
|
||||
{ title: '核销号', dataIndex: 'redeemNo', width: 180 },
|
||||
{
|
||||
title: '门店',
|
||||
dataIndex: ['store', 'name'],
|
||||
render: (v, row) => (row.store?.cityName ? `${v}(${row.store.cityName})` : v),
|
||||
},
|
||||
{
|
||||
title: '用户',
|
||||
width: 140,
|
||||
render: (_, row) => row.user?.phone || row.user?.userNo || '-',
|
||||
},
|
||||
{ title: '核销额', dataIndex: 'redeemAmount', width: 90, render: (v) => `¥${v}` },
|
||||
{ title: '服务分', dataIndex: 'serviceScore', width: 80 },
|
||||
{ title: '环境分', dataIndex: 'envScore', width: 80 },
|
||||
{ title: '评价时间', dataIndex: 'createdAt', width: 170, render: fmtTime },
|
||||
];
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Typography.Title level={4} style={{ marginTop: 0 }}>
|
||||
门店评价
|
||||
</Typography.Title>
|
||||
<Form
|
||||
form={form}
|
||||
layout="inline"
|
||||
style={{ marginBottom: 16 }}
|
||||
initialValues={filters}
|
||||
onFinish={(v) => {
|
||||
setFilters({
|
||||
storeId: v.storeId || '',
|
||||
redeemNo: v.redeemNo || '',
|
||||
});
|
||||
setPage(1);
|
||||
}}
|
||||
>
|
||||
<Form.Item name="storeId" label="门店ID">
|
||||
<Input allowClear placeholder="storeId" />
|
||||
</Form.Item>
|
||||
<Form.Item name="redeemNo" label="核销号">
|
||||
<Input allowClear />
|
||||
</Form.Item>
|
||||
<Form.Item>
|
||||
<Button type="primary" htmlType="submit">
|
||||
查询
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
<Table
|
||||
rowKey="id"
|
||||
loading={loading}
|
||||
columns={columns}
|
||||
dataSource={data?.items ?? []}
|
||||
pagination={{
|
||||
current: page,
|
||||
pageSize,
|
||||
total: data?.total ?? 0,
|
||||
showSizeChanger: true,
|
||||
onChange: (p, ps) => {
|
||||
setPage(p);
|
||||
setPageSize(ps);
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -770,9 +770,12 @@ export default function StoresPage() {
|
||||
{ title: '店长', dataIndex: ['account', 'name'], width: 90, render: (v) => v || '—' },
|
||||
{ title: '创建', dataIndex: 'createdAt', width: 160, render: fmtTime },
|
||||
{
|
||||
title: '操作', width: 80,
|
||||
title: '操作', width: 140,
|
||||
render: (_, row) => (
|
||||
<Button type="link" size="small" onClick={() => void openStoreDetail(row)}>详情</Button>
|
||||
<Space size={0}>
|
||||
<Button type="link" size="small" onClick={() => void openStoreDetail(row)}>详情</Button>
|
||||
<Button type="link" size="small" onClick={() => navigate(`/store-ratings?storeId=${row.id}`)}>评价</Button>
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user