feat: multi-module iteration

This commit is contained in:
2026-08-04 21:38:49 +08:00
parent 9d96c73246
commit 71f508e02b
1366 changed files with 202004 additions and 0 deletions
@@ -0,0 +1,96 @@
import { useEffect, useState } from 'react';
import { View, Text, Button } from '@tarojs/components';
import { useDidShow } from '@tarojs/taro';
import HqHeader from '../../components/HqHeader';
import HqTabBar from '../../components/HqTabBar';
import { request, type Paginated, toast } from '../../lib/api';
import { useHqSession } from '../../lib/session';
import { fmtMoney, fmtTime } from '../../lib/constants';
type RedeemRow = {
id: string;
redeemNo: string;
amount: number | string;
createdAt: string;
store?: { name: string; cityName?: string };
user?: { nickname?: string; phone?: string };
payout?: unknown;
};
// 门店核销到账比例(V2 手册:门店核销结算 60%)
const STORE_PAYOUT_RATE = 0.6;
export default function SettlementPage() {
useHqSession();
const [rows, setRows] = useState<RedeemRow[]>([]);
const [loading, setLoading] = useState(true);
function load() {
setLoading(true);
request<Paginated<RedeemRow>>('/admin/redeem-records?pageSize=50')
.then((d) => setRows(d.items))
.catch(() => setRows([]))
.finally(() => setLoading(false));
}
useEffect(load, []);
useDidShow(load);
const totalRedeem = rows.reduce((s, r) => s + Number(r.amount || 0), 0);
const totalPayout = totalRedeem * STORE_PAYOUT_RATE;
const pendingCount = rows.filter((r) => !r.payout).length;
return (
<View className="hq-page hq-page--tab">
<HqHeader title="结算中心" />
<View className="hq-stat-grid">
<View className="hq-stat">
<Text className="hq-stat__label"></Text>
<Text className="hq-stat__value">¥{fmtMoney(totalRedeem)}</Text>
<Text className="hq-stat__sub"> {rows.length} </Text>
</View>
<View className="hq-stat">
<Text className="hq-stat__label">(60%)</Text>
<Text className="hq-stat__value">¥{fmtMoney(totalPayout)}</Text>
<Text className="hq-stat__sub"> {pendingCount} </Text>
</View>
</View>
<View style="margin:12px 16px">
<Button
className="hq-btn hq-btn--primary hq-btn--block"
onClick={() => toast('preV1 阶段批量打款为演示,暂不实际出款')}
>
</Button>
</View>
<Text className="hq-section-title"></Text>
{loading && <View className="hq-empty"></View>}
{!loading && rows.length === 0 && <View className="hq-empty"></View>}
{rows.map((r) => (
<View key={r.id} className="hq-card" style="margin-top:8px;margin-bottom:0">
<View className="hq-row">
<Text style="font-size:14px;font-weight:600">{r.store?.name || '门店'}</Text>
<Text className={`hq-badge ${r.payout ? 'hq-badge--ok' : 'hq-badge--warn'}`}>
{r.payout ? '已结算' : '待结算'}
</Text>
</View>
<Text className="hq-muted" style="display:block;margin-top:4px;font-size:12px">
{r.store?.cityName || ''} · {r.redeemNo}
</Text>
<View className="hq-row" style="margin-top:8px">
<Text className="hq-muted" style="font-size:12px">{fmtTime(r.createdAt)}</Text>
<Text style="font-size:15px;font-weight:700;color:var(--hq-red)">
¥{fmtMoney(r.amount)} · ¥{fmtMoney(Number(r.amount || 0) * STORE_PAYOUT_RATE)}
</Text>
</View>
</View>
))}
<HqTabBar selected={2} />
</View>
);
}