feat(store): dual business hours, avg price, and status lock
CI / verify (pull_request) Has been cancelled

Support 1-2 hour segments and optional avgPrice; show bank settlement on HQ store detail; enforce pickup min 2 bottles; Chinese order statuses; block shop reopen after permanent close.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-26 10:16:22 +08:00
parent 94d2a88581
commit 92cf51ba3d
25 changed files with 560 additions and 146 deletions
+7 -4
View File
@@ -14,11 +14,14 @@ const TABS = [
const STATUS_LABEL: Record<string, string> = {
PENDING_PAY: '待付款',
PENDING_SHIP: '已付款',
OUT_WAREHOUSE: '已付款',
SHIPPING: '已付款',
PENDING_RECEIVE: '已付款',
PENDING_SHIP: '待发货',
OUT_WAREHOUSE: '已出库',
SHIPPING: '配送中',
PENDING_RECEIVE: '待收货',
COMPLETED: '已完成',
CANCELLED: '已取消',
REFUNDING: '退款中',
REFUNDED: '已退款',
};
function isReshipOrder(order: Record<string, unknown>) {
+10 -2
View File
@@ -24,6 +24,9 @@ type StoreDetail = {
status: string;
openTime?: string | null;
closeTime?: string | null;
openTime2?: string | null;
closeTime2?: string | null;
avgPrice?: number | null;
category?: { name: string } | null;
media?: StoreMedia[];
};
@@ -41,8 +44,10 @@ const DEFAULT_INTRO =
'作为本地优质餐饮合作伙伴,门店融合地域饮食文化与高端社交场景,设有杜康文化体验区,让宾客在用餐之余领略中华酒祖的千年传承。主打精品地方菜与创意融合菜,氛围庄重而不失亲和力,是商务宴请、亲友小聚以及文化交流的理想场所。';
function formatHours(store: StoreDetail) {
if (store.openTime && store.closeTime) return `${store.openTime} - ${store.closeTime}`;
return '09:30 - 22:00';
const parts: string[] = [];
if (store.openTime && store.closeTime) parts.push(`${store.openTime}-${store.closeTime}`);
if (store.openTime2 && store.closeTime2) parts.push(`${store.openTime2}-${store.closeTime2}`);
return parts.length ? parts.join('') : '09:30-22:00';
}
function fullAddress(store: StoreDetail) {
@@ -135,6 +140,9 @@ export default function StoreDetailPage() {
<div>
<h2 className="store-detail-name">{store.name}</h2>
<p className="store-detail-hours">{formatHours(store)}</p>
{store.avgPrice != null && Number(store.avgPrice) > 0 ? (
<p className="store-detail-hours"> ¥{Number(store.avgPrice).toFixed(0)}</p>
) : null}
{store.category?.name && (
<span className="store-detail-category">{store.category.name}</span>
)}
+10 -4
View File
@@ -32,6 +32,9 @@ type StoreItem = {
status: string;
openTime?: string | null;
closeTime?: string | null;
openTime2?: string | null;
closeTime2?: string | null;
avgPrice?: number | null;
category?: { name: string } | null;
};
@@ -50,10 +53,10 @@ function storeCover(store: StoreItem, index: number) {
}
function formatHours(store: StoreItem) {
if (store.openTime && store.closeTime) {
return `营业时间: ${store.openTime}-${store.closeTime}`;
}
return '营业时间: 10:00-22:00';
const parts: string[] = [];
if (store.openTime && store.closeTime) parts.push(`${store.openTime}-${store.closeTime}`);
if (store.openTime2 && store.closeTime2) parts.push(`${store.openTime2}-${store.closeTime2}`);
return parts.length ? `营业时间: ${parts.join('')}` : '营业时间: 10:00-22:00';
}
export default function StoreListPage() {
@@ -238,6 +241,9 @@ export default function StoreListPage() {
<div className="store-card-meta">
<span className="status-open"></span>
<span className="store-card-hours">{formatHours(s)}</span>
{s.avgPrice != null && Number(s.avgPrice) > 0 ? (
<span className="store-card-hours">¥{Number(s.avgPrice).toFixed(0)}</span>
) : null}
</div>
</div>
<div className="store-card-bottom">