@@ -300,7 +300,7 @@ body:has(.big-screen-page),
|
||||
.big-screen-list-head,
|
||||
.big-screen-row {
|
||||
display: grid;
|
||||
grid-template-columns: 180px 1fr 160px 200px;
|
||||
grid-template-columns: 208px 1fr 160px 200px;
|
||||
align-items: center;
|
||||
column-gap: 16px;
|
||||
}
|
||||
@@ -434,6 +434,13 @@ body:has(.big-screen-page),
|
||||
font-weight: 700;
|
||||
font-variant-numeric: tabular-nums;
|
||||
white-space: nowrap;
|
||||
letter-spacing: 0.5px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.big-screen-amount--6d {
|
||||
font-size: 0.86em;
|
||||
letter-spacing: 0;
|
||||
}
|
||||
|
||||
.big-screen-items {
|
||||
@@ -540,13 +547,14 @@ body:has(.big-screen-page),
|
||||
.big-screen-fx-card {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
min-width: 420px;
|
||||
max-width: 72vw;
|
||||
min-width: min(420px, 92vw);
|
||||
max-width: min(920px, 92vw);
|
||||
padding: 28px 40px 32px;
|
||||
border-radius: 12px;
|
||||
text-align: center;
|
||||
background: rgba(8, 22, 48, 0.82);
|
||||
backdrop-filter: blur(8px);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.big-screen-fx-card--t1 {
|
||||
@@ -562,7 +570,7 @@ body:has(.big-screen-page),
|
||||
}
|
||||
|
||||
.big-screen-fx-card--t3 {
|
||||
min-width: 520px;
|
||||
min-width: min(560px, 94vw);
|
||||
padding: 36px 48px 40px;
|
||||
border: 3px solid #ffd666;
|
||||
box-shadow:
|
||||
@@ -623,12 +631,19 @@ body:has(.big-screen-page),
|
||||
}
|
||||
|
||||
.big-screen-fx-amount {
|
||||
font-size: 64px;
|
||||
font-size: clamp(44px, 8.5vw, 64px);
|
||||
font-weight: 800;
|
||||
font-variant-numeric: tabular-nums;
|
||||
letter-spacing: 2px;
|
||||
line-height: 1.1;
|
||||
color: #e6f7ff;
|
||||
max-width: 100%;
|
||||
margin-inline: auto;
|
||||
}
|
||||
|
||||
.big-screen-fx-amount--6d {
|
||||
font-size: clamp(36px, 7vw, 52px) !important;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.big-screen-fx-card--t1 .big-screen-fx-amount {
|
||||
@@ -643,7 +658,7 @@ body:has(.big-screen-page),
|
||||
}
|
||||
|
||||
.big-screen-fx-card--t3 .big-screen-fx-amount {
|
||||
font-size: 84px;
|
||||
font-size: clamp(52px, 10vw, 84px);
|
||||
color: #ffd666;
|
||||
text-shadow:
|
||||
0 0 12px #ffd666,
|
||||
@@ -651,6 +666,11 @@ body:has(.big-screen-page),
|
||||
animation: big-screen-amount-flash 0.9s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.big-screen-fx-card--t3 .big-screen-fx-amount--6d {
|
||||
font-size: clamp(44px, 8.5vw, 68px) !important;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
@keyframes big-screen-amount-pop {
|
||||
0% {
|
||||
transform: scale(0.7);
|
||||
@@ -695,14 +715,23 @@ body:has(.big-screen-page),
|
||||
}
|
||||
.big-screen-list-head,
|
||||
.big-screen-row {
|
||||
grid-template-columns: 140px 1fr 120px 160px;
|
||||
grid-template-columns: 172px 1fr 120px 160px;
|
||||
font-size: 16px;
|
||||
}
|
||||
.big-screen-amount--6d {
|
||||
font-size: 0.82em;
|
||||
}
|
||||
.big-screen-fx-amount {
|
||||
font-size: 44px;
|
||||
font-size: clamp(36px, 8vw, 44px);
|
||||
}
|
||||
.big-screen-fx-card--t3 .big-screen-fx-amount {
|
||||
font-size: 56px;
|
||||
font-size: clamp(40px, 9vw, 56px);
|
||||
}
|
||||
.big-screen-fx-amount--6d {
|
||||
font-size: clamp(32px, 6.5vw, 40px) !important;
|
||||
}
|
||||
.big-screen-fx-card--t3 .big-screen-fx-amount--6d {
|
||||
font-size: clamp(34px, 7vw, 48px) !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -217,6 +217,12 @@ export default function ProxyOrderModal({ open, onClose, onSuccess }: ProxyOrder
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ payMethod: 'NATIVE' }),
|
||||
});
|
||||
if (pay.mode === 'mock') {
|
||||
message.success(`支付成功:${order.orderNo}`);
|
||||
resetForm();
|
||||
onSuccess({ id: order.id, orderNo: order.orderNo });
|
||||
return;
|
||||
}
|
||||
setCodeUrl(pay.codeUrl ?? null);
|
||||
startPoll(order.id);
|
||||
} catch (e) {
|
||||
|
||||
@@ -1,71 +1,5 @@
|
||||
export const PACKAGE_AUDIT_CHANGED_EVENT = 'admin:package-audit-changed';
|
||||
export const AUDIT_NOTICE_CHANGED_EVENT = 'dukang:audit-notice-changed';
|
||||
export const BIG_SCREEN_DEMO_CHANNEL = 'dukang-big-screen';
|
||||
export const BIG_SCREEN_DEMO_STORAGE_KEY = 'dukang:big-screen-demo';
|
||||
|
||||
export type BigScreenDemoOrder = {
|
||||
payAmount: number;
|
||||
items: string;
|
||||
userPhoneMasked: string;
|
||||
};
|
||||
|
||||
export type BigScreenDemoPayload = {
|
||||
type: 'demo';
|
||||
id: string;
|
||||
at: number;
|
||||
orders: BigScreenDemoOrder[];
|
||||
};
|
||||
|
||||
export function buildBigScreenDemoPayload(): BigScreenDemoPayload {
|
||||
return {
|
||||
type: 'demo',
|
||||
id: `demo-${Date.now()}`,
|
||||
at: Date.now(),
|
||||
orders: [
|
||||
{ payAmount: 1288, items: '杜康君酿 · 浓香型 × 6瓶', userPhoneMasked: '138****8888' },
|
||||
{ payAmount: 688, items: '杜康君酿 · 浓香型 × 2瓶', userPhoneMasked: '139****6666' },
|
||||
{ payAmount: 188, items: '杜康君酿 · 浓香型 × 1瓶', userPhoneMasked: '137****1888' },
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
export function triggerBigScreenDemo() {
|
||||
const payload = buildBigScreenDemoPayload();
|
||||
try {
|
||||
localStorage.setItem(BIG_SCREEN_DEMO_STORAGE_KEY, JSON.stringify(payload));
|
||||
} catch {
|
||||
/* ignore quota */
|
||||
}
|
||||
try {
|
||||
const ch = new BroadcastChannel(BIG_SCREEN_DEMO_CHANNEL);
|
||||
ch.postMessage(payload);
|
||||
ch.close();
|
||||
} catch {
|
||||
/* BroadcastChannel 不可用时靠 localStorage 冷启动 */
|
||||
}
|
||||
return payload;
|
||||
}
|
||||
|
||||
export function readPendingBigScreenDemo(maxAgeMs = 8000): BigScreenDemoPayload | null {
|
||||
try {
|
||||
const raw = localStorage.getItem(BIG_SCREEN_DEMO_STORAGE_KEY);
|
||||
if (!raw) return null;
|
||||
const parsed = JSON.parse(raw) as BigScreenDemoPayload;
|
||||
if (parsed?.type !== 'demo' || !parsed.id || !Array.isArray(parsed.orders)) return null;
|
||||
if (Date.now() - Number(parsed.at || 0) > maxAgeMs) return null;
|
||||
return parsed;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export function clearPendingBigScreenDemo() {
|
||||
try {
|
||||
localStorage.removeItem(BIG_SCREEN_DEMO_STORAGE_KEY);
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
|
||||
export function notifyPackageAuditChanged() {
|
||||
window.dispatchEvent(new Event(PACKAGE_AUDIT_CHANGED_EVENT));
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
import { useCallback, useEffect, useMemo, useRef, useState, type CSSProperties } from 'react';
|
||||
import { request } from '../lib/api';
|
||||
import {
|
||||
BIG_SCREEN_DEMO_CHANNEL,
|
||||
clearPendingBigScreenDemo,
|
||||
readPendingBigScreenDemo,
|
||||
type BigScreenDemoPayload,
|
||||
} from '../lib/admin-events';
|
||||
|
||||
export type BigScreenOrder = {
|
||||
id: string;
|
||||
orderNo: string;
|
||||
payAmount: number;
|
||||
items: string;
|
||||
/** 展示用时间(付款成功时间) */
|
||||
createdAt: string;
|
||||
paidAt?: string;
|
||||
userPhoneMasked: string | null;
|
||||
};
|
||||
|
||||
@@ -23,6 +19,101 @@ const ROW_MS = 2500;
|
||||
const WEEKDAYS = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
|
||||
const TIER_DURATION: Record<AmountTier, number> = { 1: 3000, 2: 4500, 3: 6000 };
|
||||
|
||||
const SEED_IDS = new Set(
|
||||
['seed-1', 'seed-2', 'seed-3', 'seed-4', 'seed-5', 'seed-6', 'seed-7', 'seed-8'],
|
||||
);
|
||||
|
||||
function seedPaidAt(h: number, m: number, s: number): string {
|
||||
const d = new Date();
|
||||
d.setHours(h, m, s, 0);
|
||||
return d.toISOString();
|
||||
}
|
||||
|
||||
/** 发布会滚动列表垫底演示数据(不参与成交动效) */
|
||||
const BIG_SCREEN_SEED_ORDERS: BigScreenOrder[] = [
|
||||
{
|
||||
id: 'seed-1',
|
||||
orderNo: 'DK-DEMO-001',
|
||||
payAmount: 1288,
|
||||
items: '杜康君酿 · 浓香型 × 6瓶',
|
||||
createdAt: seedPaidAt(14, 28, 36),
|
||||
paidAt: seedPaidAt(14, 28, 36),
|
||||
userPhoneMasked: '138****8888',
|
||||
},
|
||||
{
|
||||
id: 'seed-2',
|
||||
orderNo: 'DK-DEMO-002',
|
||||
payAmount: 688,
|
||||
items: '杜康君酿 · 浓香型 × 2瓶',
|
||||
createdAt: seedPaidAt(14, 22, 18),
|
||||
paidAt: seedPaidAt(14, 22, 18),
|
||||
userPhoneMasked: '139****6666',
|
||||
},
|
||||
{
|
||||
id: 'seed-3',
|
||||
orderNo: 'DK-DEMO-003',
|
||||
payAmount: 1588,
|
||||
items: '杜康典藏 · 礼盒装 × 2套',
|
||||
createdAt: seedPaidAt(14, 15, 42),
|
||||
paidAt: seedPaidAt(14, 15, 42),
|
||||
userPhoneMasked: '136****9527',
|
||||
},
|
||||
{
|
||||
id: 'seed-4',
|
||||
orderNo: 'DK-DEMO-004',
|
||||
payAmount: 520,
|
||||
items: '杜康特曲 · 500ml × 4瓶',
|
||||
createdAt: seedPaidAt(14, 8, 55),
|
||||
paidAt: seedPaidAt(14, 8, 55),
|
||||
userPhoneMasked: '135****3210',
|
||||
},
|
||||
{
|
||||
id: 'seed-5',
|
||||
orderNo: 'DK-DEMO-005',
|
||||
payAmount: 268,
|
||||
items: '杜康君酿 · 浓香型 × 1瓶',
|
||||
createdAt: seedPaidAt(13, 56, 7),
|
||||
paidAt: seedPaidAt(13, 56, 7),
|
||||
userPhoneMasked: '137****1888',
|
||||
},
|
||||
{
|
||||
id: 'seed-6',
|
||||
orderNo: 'DK-DEMO-006',
|
||||
payAmount: 999,
|
||||
items: '杜康窖藏 · 珍藏版 × 3瓶',
|
||||
createdAt: seedPaidAt(13, 48, 33),
|
||||
paidAt: seedPaidAt(13, 48, 33),
|
||||
userPhoneMasked: '133****7788',
|
||||
},
|
||||
{
|
||||
id: 'seed-7',
|
||||
orderNo: 'DK-DEMO-007',
|
||||
payAmount: 188,
|
||||
items: '杜康小酒 · 品鉴装 × 2瓶',
|
||||
createdAt: seedPaidAt(13, 35, 21),
|
||||
paidAt: seedPaidAt(13, 35, 21),
|
||||
userPhoneMasked: '158****0099',
|
||||
},
|
||||
{
|
||||
id: 'seed-8',
|
||||
orderNo: 'DK-DEMO-008',
|
||||
payAmount: 1200,
|
||||
items: '杜康君酿 · 浓香型 × 5瓶',
|
||||
createdAt: seedPaidAt(13, 22, 49),
|
||||
paidAt: seedPaidAt(13, 22, 49),
|
||||
userPhoneMasked: '186****5566',
|
||||
},
|
||||
];
|
||||
|
||||
function mergeDisplayItems(live: BigScreenOrder[]): BigScreenOrder[] {
|
||||
if (!live.length) return [...BIG_SCREEN_SEED_ORDERS];
|
||||
return [...live, ...BIG_SCREEN_SEED_ORDERS];
|
||||
}
|
||||
|
||||
function isSeedOrder(order: BigScreenOrder): boolean {
|
||||
return SEED_IDS.has(order.id);
|
||||
}
|
||||
|
||||
function pad(n: number) {
|
||||
return String(n).padStart(2, '0');
|
||||
}
|
||||
@@ -35,7 +126,7 @@ function formatDateLine(d: Date) {
|
||||
return `${d.getFullYear()} / ${pad(d.getMonth() + 1)} / ${pad(d.getDate())} ${WEEKDAYS[d.getDay()]}`;
|
||||
}
|
||||
|
||||
function formatHm(iso: string): string {
|
||||
function formatOrderTime(iso: string): string {
|
||||
try {
|
||||
return formatClock(new Date(iso));
|
||||
} catch {
|
||||
@@ -50,6 +141,11 @@ function formatAmount(n: number): string {
|
||||
});
|
||||
}
|
||||
|
||||
function amountCssClass(payAmount: number, base: string): string {
|
||||
const wide = Math.floor(Math.abs(Number(payAmount || 0))) >= 100_000;
|
||||
return wide ? `${base} ${base}--6d` : base;
|
||||
}
|
||||
|
||||
export function amountTier(payAmount: number): AmountTier {
|
||||
if (payAmount >= 1000) return 3;
|
||||
if (payAmount >= 500) return 2;
|
||||
@@ -83,9 +179,11 @@ function OrderRow({
|
||||
className={`big-screen-row big-screen-row--t${tier}${latest ? ' is-latest' : ''}`}
|
||||
>
|
||||
{latest ? <span className="big-screen-row-mark" /> : null}
|
||||
<span className="big-screen-amount">¥ {formatAmount(order.payAmount)}</span>
|
||||
<span className={amountCssClass(order.payAmount, 'big-screen-amount')}>
|
||||
¥ {formatAmount(order.payAmount)}
|
||||
</span>
|
||||
<span className="big-screen-items">{order.items || '—'}</span>
|
||||
<span className="big-screen-time">{formatHm(order.createdAt)}</span>
|
||||
<span className="big-screen-time">{formatOrderTime(order.paidAt ?? order.createdAt)}</span>
|
||||
<span className="big-screen-phone">{order.userPhoneMasked || '—'}</span>
|
||||
</div>
|
||||
);
|
||||
@@ -253,11 +351,13 @@ function CelebrateFx({ order, onDone }: { order: BigScreenOrder; onDone: () => v
|
||||
{tier >= 2 ? <div className="big-screen-fx-sweep big-screen-fx-sweep--alt" /> : null}
|
||||
<div className={`big-screen-fx-card big-screen-fx-card--t${tier}`}>
|
||||
<div className="big-screen-fx-kicker">{tier === 3 ? '高额成交' : tier === 2 ? '大额成交' : '新成交'}</div>
|
||||
<div className="big-screen-fx-amount">¥ {formatAmount(displayAmount)}</div>
|
||||
<div className={amountCssClass(displayAmount || order.payAmount, 'big-screen-fx-amount')}>
|
||||
¥ {formatAmount(displayAmount)}
|
||||
</div>
|
||||
<div className="big-screen-fx-items">{order.items || '—'}</div>
|
||||
<div className="big-screen-fx-meta">
|
||||
<span>{order.userPhoneMasked || '—'}</span>
|
||||
<span>{formatHm(order.createdAt)}</span>
|
||||
<span>{formatOrderTime(order.paidAt ?? order.createdAt)}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -270,12 +370,16 @@ export default function BigScreenPage() {
|
||||
const [paused, setPaused] = useState(false);
|
||||
const [celebrate, setCelebrate] = useState<BigScreenOrder | null>(null);
|
||||
const seenIdsRef = useRef<Set<string> | null>(null);
|
||||
const celebratedIdsRef = useRef<Set<string>>(new Set());
|
||||
const queueRef = useRef<BigScreenOrder[]>([]);
|
||||
const celebratingRef = useRef(false);
|
||||
const viewportRef = useRef<HTMLDivElement | null>(null);
|
||||
const demoSeenRef = useRef<Set<string>>(new Set());
|
||||
const [viewportH, setViewportH] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
for (const o of BIG_SCREEN_SEED_ORDERS) celebratedIdsRef.current.add(o.id);
|
||||
}, []);
|
||||
|
||||
const playNext = useCallback(() => {
|
||||
const next = queueRef.current.shift() ?? null;
|
||||
celebratingRef.current = !!next;
|
||||
@@ -285,11 +389,13 @@ export default function BigScreenPage() {
|
||||
|
||||
const enqueueNew = useCallback(
|
||||
(fresh: BigScreenOrder[]) => {
|
||||
if (!fresh.length) return;
|
||||
const ranked = [...fresh].sort((a, b) => {
|
||||
const toCelebrate = fresh.filter((o) => !celebratedIdsRef.current.has(o.id));
|
||||
if (!toCelebrate.length) return;
|
||||
for (const o of toCelebrate) celebratedIdsRef.current.add(o.id);
|
||||
const ranked = [...toCelebrate].sort((a, b) => {
|
||||
const td = amountTier(b.payAmount) - amountTier(a.payAmount);
|
||||
if (td !== 0) return td;
|
||||
return +new Date(b.createdAt) - +new Date(a.createdAt);
|
||||
return +new Date(b.paidAt ?? b.createdAt) - +new Date(a.paidAt ?? a.createdAt);
|
||||
});
|
||||
queueRef.current.push(...ranked);
|
||||
if (!celebratingRef.current) playNext();
|
||||
@@ -297,38 +403,16 @@ export default function BigScreenPage() {
|
||||
[playNext],
|
||||
);
|
||||
|
||||
const playDemo = useCallback(
|
||||
(payload: BigScreenDemoPayload) => {
|
||||
if (!payload?.orders?.length || demoSeenRef.current.has(payload.id)) return;
|
||||
demoSeenRef.current.add(payload.id);
|
||||
const now = new Date().toISOString();
|
||||
const fake: BigScreenOrder[] = payload.orders.map((o, i) => ({
|
||||
id: `${payload.id}-${i}`,
|
||||
orderNo: `${payload.id}-${i}`,
|
||||
payAmount: o.payAmount,
|
||||
items: o.items,
|
||||
createdAt: now,
|
||||
userPhoneMasked: o.userPhoneMasked,
|
||||
}));
|
||||
setItems((prev) => [...fake, ...prev.filter((row) => !row.id.startsWith('demo-'))]);
|
||||
enqueueNew(fake);
|
||||
clearPendingBigScreenDemo();
|
||||
},
|
||||
[enqueueNew],
|
||||
);
|
||||
|
||||
const fetchData = useCallback(() => {
|
||||
return request<{ items: BigScreenOrder[] }>('/admin/orders/big-screen?limit=2000')
|
||||
.then((d) => {
|
||||
const list = d.items ?? [];
|
||||
setItems((prev) => {
|
||||
const demos = prev.filter((o) => o.id.startsWith('demo-'));
|
||||
return demos.length ? [...demos, ...list] : list;
|
||||
});
|
||||
setItems(mergeDisplayItems(list));
|
||||
setLoadError('');
|
||||
const seen = seenIdsRef.current;
|
||||
if (!seen) {
|
||||
seenIdsRef.current = new Set(list.map((o) => o.id));
|
||||
for (const o of list) celebratedIdsRef.current.add(o.id);
|
||||
return;
|
||||
}
|
||||
const fresh = list.filter((o) => !seen.has(o.id));
|
||||
@@ -337,6 +421,7 @@ export default function BigScreenPage() {
|
||||
})
|
||||
.catch((e) => {
|
||||
setLoadError(e instanceof Error ? e.message : '加载失败');
|
||||
setItems(mergeDisplayItems([]));
|
||||
});
|
||||
}, [enqueueNew]);
|
||||
|
||||
@@ -346,24 +431,6 @@ export default function BigScreenPage() {
|
||||
return () => clearInterval(id);
|
||||
}, [fetchData]);
|
||||
|
||||
useEffect(() => {
|
||||
const pending = readPendingBigScreenDemo();
|
||||
if (pending) playDemo(pending);
|
||||
|
||||
let ch: BroadcastChannel | null = null;
|
||||
try {
|
||||
ch = new BroadcastChannel(BIG_SCREEN_DEMO_CHANNEL);
|
||||
ch.onmessage = (ev: MessageEvent<BigScreenDemoPayload>) => {
|
||||
if (ev.data?.type === 'demo' && ev.data.orders?.length) playDemo(ev.data);
|
||||
};
|
||||
} catch {
|
||||
ch = null;
|
||||
}
|
||||
return () => {
|
||||
ch?.close();
|
||||
};
|
||||
}, [playDemo]);
|
||||
|
||||
useEffect(() => {
|
||||
const html = document.documentElement;
|
||||
const prevHtml = html.style.overflow;
|
||||
@@ -399,7 +466,8 @@ export default function BigScreenPage() {
|
||||
const trackItems = useMemo(() => unitItems.concat(unitItems), [unitItems]);
|
||||
const marqueeMs = Math.max(unitItems.length, 1) * ROW_MS;
|
||||
const rolling = items.length > 0 && unitItems.length > 0;
|
||||
const latestId = items[0]?.id;
|
||||
const latestLive = items.find((o) => !isSeedOrder(o));
|
||||
const latestId = latestLive?.id;
|
||||
|
||||
return (
|
||||
<div className="big-screen-page">
|
||||
@@ -431,7 +499,7 @@ export default function BigScreenPage() {
|
||||
<div className="big-screen-list-head">
|
||||
<span>下单金额</span>
|
||||
<span>下单商品</span>
|
||||
<span>下单时间</span>
|
||||
<span>付款时间</span>
|
||||
<span>下单人</span>
|
||||
</div>
|
||||
<div className="big-screen-list-body" ref={viewportRef}>
|
||||
|
||||
@@ -21,7 +21,6 @@ import {
|
||||
} from 'antd';
|
||||
import type { ColumnsType } from 'antd/es/table';
|
||||
import { request, type AdminOrderItem, type AdminOrderRow, type HqProfile, type Paginated } from '../lib/api';
|
||||
import { triggerBigScreenDemo } from '../lib/admin-events';
|
||||
import {
|
||||
ADMIN_OPTIONS_PAGE_SIZE,
|
||||
DELIVERY_PROVIDER_LABELS,
|
||||
@@ -192,7 +191,6 @@ export default function OrdersPage() {
|
||||
const [trackOpen, setTrackOpen] = useState(false);
|
||||
const canDeleteOrders = (profile?.permissionKeys ?? []).includes('orders_delete');
|
||||
const canProxyOrder = (profile?.permissionKeys ?? []).includes('orders');
|
||||
const isSuperAdmin = profile?.adminRole === 'SUPER_ADMIN';
|
||||
|
||||
const selectedOrders = useMemo(
|
||||
() => (data?.items ?? []).filter((row) => selectedRowKeys.includes(row.id)),
|
||||
@@ -545,17 +543,6 @@ export default function OrdersPage() {
|
||||
<Typography.Title level={4} style={{ margin: 0 }}>订单监控</Typography.Title>
|
||||
<Space>
|
||||
<Button onClick={() => window.open('/orders/big-screen', 'dukang-big-screen')}>大屏</Button>
|
||||
{isSuperAdmin ? (
|
||||
<Button
|
||||
onClick={() => {
|
||||
window.open('/orders/big-screen', 'dukang-big-screen');
|
||||
triggerBigScreenDemo();
|
||||
message.success('已发送测试成交动效(三级 / 二级 / 一级)');
|
||||
}}
|
||||
>
|
||||
测试
|
||||
</Button>
|
||||
) : null}
|
||||
{canProxyOrder ? (
|
||||
<Button type="primary" onClick={() => setProxyOpen(true)}>
|
||||
代下单
|
||||
|
||||
Reference in New Issue
Block a user