ae7c63c08d
CI / verify (pull_request) Has been cancelled
Share PullToRefresh for partner/shop H5; enable Taro pull-down on mini-user lists. Co-authored-by: Cursor <cursoragent@cursor.com>
134 lines
5.1 KiB
TypeScript
134 lines
5.1 KiB
TypeScript
import { useCallback, useEffect, useState } from 'react';
|
|
import { Link, useNavigate } from 'react-router-dom';
|
|
import PullToRefresh from '@dukang/shared-ui/PullToRefresh';
|
|
import { request } from '../lib/api';
|
|
|
|
function formatMoney(n: number) {
|
|
return n.toLocaleString('zh-CN', { minimumFractionDigits: 0, maximumFractionDigits: 2 });
|
|
}
|
|
|
|
export default function HomePage() {
|
|
const navigate = useNavigate();
|
|
const [dash, setDash] = useState<Record<string, unknown> | null>(null);
|
|
const [open, setOpen] = useState(true);
|
|
|
|
const loadDashboard = useCallback(() => {
|
|
return request<Record<string, unknown>>('SHOP_H5', '/shop/dashboard')
|
|
.then((d) => {
|
|
setDash(d);
|
|
setOpen(String((d.store as Record<string, unknown>)?.status) === 'OPEN');
|
|
})
|
|
.catch(() => {});
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
void loadDashboard();
|
|
}, [loadDashboard]);
|
|
|
|
useEffect(() => {
|
|
function onResume() {
|
|
void loadDashboard();
|
|
}
|
|
function onVisibility() {
|
|
if (document.visibilityState === 'visible') onResume();
|
|
}
|
|
document.addEventListener('visibilitychange', onVisibility);
|
|
window.addEventListener('pageshow', onResume);
|
|
window.addEventListener('focus', onResume);
|
|
return () => {
|
|
document.removeEventListener('visibilitychange', onVisibility);
|
|
window.removeEventListener('pageshow', onResume);
|
|
window.removeEventListener('focus', onResume);
|
|
};
|
|
}, [loadDashboard]);
|
|
|
|
const store = dash?.store as Record<string, unknown> | undefined;
|
|
const recent = (dash?.recentRecords as Array<Record<string, unknown>>) || [];
|
|
const openTime = String(store?.openTime || '10:00');
|
|
const closeTime = String(store?.closeTime || '22:00');
|
|
|
|
return (
|
|
<PullToRefresh onRefresh={loadDashboard} className="shop-home-page">
|
|
<header className="shop-home-header">
|
|
<h1 className="app-page-title">门店管理中心</h1>
|
|
</header>
|
|
|
|
<div className="shop-home-content">
|
|
<section className="shop-home-hero">
|
|
<div className="shop-home-hero-store">
|
|
<span className="material-symbols-outlined shop-fill-icon">store</span>
|
|
<h2>{String(store?.name || '门店')}</h2>
|
|
</div>
|
|
<div className="shop-home-stats">
|
|
<div className="shop-home-stat">
|
|
<p className="shop-home-stat-label">今日核销笔数</p>
|
|
<p className="shop-home-stat-value">{Number(dash?.todayCount || 0)}</p>
|
|
</div>
|
|
<div className="shop-home-stat">
|
|
<p className="shop-home-stat-label">今日到账金额</p>
|
|
<p className="shop-home-stat-value">
|
|
<span style={{ fontSize: 18 }}>¥</span>
|
|
{formatMoney(Number(dash?.todayAmount || 0))}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section className="shop-home-scan">
|
|
<Link
|
|
to="/redeem/phone"
|
|
className="shop-home-scan-btn"
|
|
>
|
|
<span className="material-symbols-outlined">smartphone</span>
|
|
</Link>
|
|
<p className="shop-home-scan-label">手机号核销</p>
|
|
</section>
|
|
|
|
<section className="shop-home-status">
|
|
<div className="shop-home-status-left">
|
|
<div className={`shop-home-status-icon${open ? '' : ' closed'}`}>
|
|
<span className="material-symbols-outlined shop-fill-icon">schedule</span>
|
|
</div>
|
|
<div>
|
|
<p className="shop-home-status-title">营业状态</p>
|
|
<p className="shop-home-status-sub">{open ? '当前正在营业中' : '当前已停止营业'}</p>
|
|
<p className="shop-home-status-sub">营业时间: {openTime} - {closeTime}</p>
|
|
</div>
|
|
</div>
|
|
<label className="shop-home-switch" onClick={() => navigate('/status')}>
|
|
<input type="checkbox" checked={open} readOnly tabIndex={-1} />
|
|
<span className="shop-home-switch-track" />
|
|
</label>
|
|
</section>
|
|
|
|
<section>
|
|
<div className="shop-home-records-head">
|
|
<h3 className="shop-home-records-title">核销记录</h3>
|
|
<Link to="/records" className="shop-home-records-link">
|
|
查看全部
|
|
<span className="material-symbols-outlined" style={{ fontSize: 16 }}>chevron_right</span>
|
|
</Link>
|
|
</div>
|
|
<div className="shop-home-record-list">
|
|
{recent.length === 0 && (
|
|
<p className="shop-home-status-sub" style={{ textAlign: 'center', padding: '16px 0' }}>暂无核销记录</p>
|
|
)}
|
|
{recent.map((r) => (
|
|
<div key={String(r.id)} className="shop-home-record-item">
|
|
<div>
|
|
<p className="shop-home-record-time">核销时间</p>
|
|
<p className="shop-home-record-value">
|
|
{new Date(String(r.createdAt)).toLocaleString('zh-CN')}
|
|
</p>
|
|
</div>
|
|
<p className="shop-home-record-amount">¥{formatMoney(Number(r.amount))}</p>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</section>
|
|
</div>
|
|
|
|
</PullToRefresh>
|
|
);
|
|
}
|