登录页面
This commit is contained in:
@@ -1,13 +1,34 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { View, Text, Button } from '@tarojs/components';
|
||||
import { View, Text, Image } from '@tarojs/components';
|
||||
import Taro, { useDidShow } from '@tarojs/taro';
|
||||
import PageShell from '../../components/PageShell';
|
||||
import TabMainHeader from '../../components/TabMainHeader';
|
||||
import UserTabBar, { shouldRenderPageTabBar, syncTabBarSelected } from '../../components/UserTabBar';
|
||||
import { goLogin } from '../../lib/auth-nav';
|
||||
import { isLoggedIn, logout, request, toast, type UserProfile } from '../../lib/api';
|
||||
|
||||
const ORDER_SHORTCUTS = [
|
||||
{ tab: 'pending_pay', icon: '付', label: '待付款' },
|
||||
{ tab: 'paid', icon: '包', label: '已付款' },
|
||||
{ tab: 'completed', icon: '成', label: '已完成' },
|
||||
] as const;
|
||||
|
||||
const SERVICES = [
|
||||
{ icon: '址', label: '地址管理', url: '/pages/addresses/index' },
|
||||
{ icon: '店', label: '可用门店', tab: '/pages/stores/index' },
|
||||
{ icon: '服', label: '联系客服', url: '/pages/customer-service/index' },
|
||||
{ icon: '关', label: '关于我们', action: 'about' as const },
|
||||
] as const;
|
||||
|
||||
function formatMoney(amount: number) {
|
||||
return amount.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
|
||||
}
|
||||
|
||||
export default function MinePage() {
|
||||
const [profile, setProfile] = useState<UserProfile | null>(null);
|
||||
const loggedIn = isLoggedIn();
|
||||
const [profile, setProfile] = useState<UserProfile | null>(null);
|
||||
const [benefitBalance, setBenefitBalance] = useState(0);
|
||||
const [orderCounts, setOrderCounts] = useState<Record<string, number>>({});
|
||||
|
||||
useDidShow(() => {
|
||||
syncTabBarSelected(3);
|
||||
@@ -15,43 +36,187 @@ export default function MinePage() {
|
||||
|
||||
useEffect(() => {
|
||||
if (!loggedIn) return;
|
||||
request<UserProfile>('/auth/me')
|
||||
.then(setProfile)
|
||||
.catch((e) => toast(e instanceof Error ? e.message : '加载失败'));
|
||||
Promise.all([
|
||||
request<UserProfile>('/auth/me'),
|
||||
request<Array<Record<string, unknown>>>('/benefit/coupons').catch(() => []),
|
||||
...ORDER_SHORTCUTS.map((s) =>
|
||||
request<{ total: number }>(`/trade/orders?tab=${s.tab}&pageSize=1`).catch(() => ({ total: 0 })),
|
||||
),
|
||||
])
|
||||
.then(([me, coupons, ...totals]) => {
|
||||
setProfile(me);
|
||||
const balance = (coupons as Array<Record<string, unknown>>).reduce((sum, c) => {
|
||||
if (String(c.status) === 'ACTIVE') return sum + Number(c.balance || 0);
|
||||
return sum;
|
||||
}, 0);
|
||||
setBenefitBalance(balance);
|
||||
const counts: Record<string, number> = {};
|
||||
ORDER_SHORTCUTS.forEach((s, i) => {
|
||||
counts[s.tab] = (totals[i] as { total: number })?.total ?? 0;
|
||||
});
|
||||
setOrderCounts(counts);
|
||||
})
|
||||
.catch(() => {});
|
||||
}, [loggedIn]);
|
||||
|
||||
function handleService(item: (typeof SERVICES)[number]) {
|
||||
if ('url' in item && item.url) {
|
||||
Taro.navigateTo({ url: item.url });
|
||||
return;
|
||||
}
|
||||
if ('tab' in item && item.tab) {
|
||||
Taro.switchTab({ url: item.tab });
|
||||
return;
|
||||
}
|
||||
if ('action' in item && item.action === 'about') {
|
||||
toast('杜康好客 · 传承千年酒文化');
|
||||
}
|
||||
}
|
||||
|
||||
if (!loggedIn) {
|
||||
return (
|
||||
<PageShell variant="tab" className="mine-page">
|
||||
<TabMainHeader title="我的" />
|
||||
<View className="mine-header">
|
||||
<View className="mine-header-texture" />
|
||||
<View className="mine-profile">
|
||||
<View className="mine-avatar">
|
||||
<Text>客</Text>
|
||||
</View>
|
||||
<View>
|
||||
<Text className="mine-profile-name">未登录</Text>
|
||||
<Text className="mine-member-tag">好客会员</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
<View className="mine-login-gate u-card">
|
||||
<View className="u-empty">登录后管理订单与个人信息</View>
|
||||
<View
|
||||
className="u-btn u-btn--block"
|
||||
onClick={() => goLogin('/pages/mine/index')}
|
||||
>
|
||||
<Text>去登录</Text>
|
||||
</View>
|
||||
</View>
|
||||
{shouldRenderPageTabBar() ? <UserTabBar selected={3} /> : null}
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
const nickname = profile?.nickname || '用户';
|
||||
const avatarUrl = profile?.avatarUrl;
|
||||
|
||||
return (
|
||||
<View className="u-page u-page--tab">
|
||||
<PageShell variant="tab" className="mine-page">
|
||||
<TabMainHeader title="我的" />
|
||||
<View className="u-card">
|
||||
{loggedIn ? (
|
||||
<View>
|
||||
<Text className="u-title" style={{ marginBottom: 4 }}>
|
||||
{profile?.nickname || '用户'}
|
||||
</Text>
|
||||
<Text className="u-muted" style={{ display: 'block', marginBottom: 16 }}>
|
||||
{profile?.phone || '未绑定手机'}
|
||||
</Text>
|
||||
<Text className="u-muted" style={{ display: 'block', marginBottom: 16 }}>
|
||||
订单 / 地址 / 核销码等页面后续从 h5-user 迁移
|
||||
</Text>
|
||||
<Button className="u-btn u-btn--block" onClick={() => logout()}>
|
||||
退出登录
|
||||
</Button>
|
||||
<View className="mine-header">
|
||||
<View className="mine-header-texture" />
|
||||
<View className="mine-profile">
|
||||
<View className="mine-avatar">
|
||||
{avatarUrl ? (
|
||||
<Image className="mine-avatar-img" src={avatarUrl} mode="aspectFill" />
|
||||
) : (
|
||||
<Text>{nickname.slice(0, 1)}</Text>
|
||||
)}
|
||||
</View>
|
||||
) : (
|
||||
<View>
|
||||
<View className="u-empty">登录后管理订单与个人信息</View>
|
||||
<Button
|
||||
className="u-btn u-btn--block"
|
||||
onClick={() => Taro.navigateTo({ url: '/pages/login/index' })}
|
||||
>
|
||||
去登录
|
||||
</Button>
|
||||
<Text className="mine-profile-name">{nickname}</Text>
|
||||
<Text className="mine-member-tag">{profile?.phone || '好客会员'}</Text>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View className="mine-main">
|
||||
<View className="mine-card">
|
||||
<View className="mine-card-head">
|
||||
<Text className="mine-card-title">我的资产</Text>
|
||||
<Text
|
||||
className="mine-card-link"
|
||||
onClick={() => Taro.switchTab({ url: '/pages/benefit/index' })}
|
||||
>
|
||||
查看明细 ›
|
||||
</Text>
|
||||
</View>
|
||||
<View className="mine-asset-panel">
|
||||
<View>
|
||||
<Text className="mine-asset-label">好客权益余额</Text>
|
||||
<View className="mine-asset-amount">
|
||||
<Text className="mine-asset-currency">¥</Text>
|
||||
<Text className="mine-asset-value">{formatMoney(benefitBalance)}</Text>
|
||||
</View>
|
||||
</View>
|
||||
<Text
|
||||
className="mine-asset-cta"
|
||||
onClick={() => Taro.navigateTo({ url: '/pages/redeem/index' })}
|
||||
>
|
||||
去使用
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View className="mine-card">
|
||||
<View className="mine-card-head">
|
||||
<Text className="mine-card-title">我的订单</Text>
|
||||
<Text
|
||||
className="mine-card-link"
|
||||
onClick={() => Taro.navigateTo({ url: '/pages/orders/index' })}
|
||||
>
|
||||
全部订单 ›
|
||||
</Text>
|
||||
</View>
|
||||
<View className="mine-order-grid">
|
||||
{ORDER_SHORTCUTS.map((item) => {
|
||||
const count = orderCounts[item.tab] ?? 0;
|
||||
return (
|
||||
<View
|
||||
key={item.tab}
|
||||
className="mine-order-item"
|
||||
onClick={() =>
|
||||
Taro.navigateTo({ url: `/pages/orders/index?tab=${item.tab}` })
|
||||
}
|
||||
>
|
||||
<View className="mine-order-icon">
|
||||
<Text>{item.icon}</Text>
|
||||
</View>
|
||||
{count > 0 ? (
|
||||
<Text className="mine-order-badge">{count > 99 ? '99+' : count}</Text>
|
||||
) : null}
|
||||
<Text className="mine-order-label">{item.label}</Text>
|
||||
</View>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View className="mine-card">
|
||||
<View className="mine-card-head">
|
||||
<Text className="mine-card-title">常用服务</Text>
|
||||
</View>
|
||||
<View className="mine-service-grid">
|
||||
{SERVICES.map((item) => (
|
||||
<View
|
||||
key={item.label}
|
||||
className="mine-service-item"
|
||||
onClick={() => handleService(item)}
|
||||
>
|
||||
<View className="mine-service-icon">
|
||||
<Text>{item.icon}</Text>
|
||||
</View>
|
||||
<Text className="mine-service-label">{item.label}</Text>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View className="mine-footer">
|
||||
<Text className="mine-version">杜康好客 mini-user v0.1.0</Text>
|
||||
<Text className="mine-logout" onClick={() => logout()}>
|
||||
退出登录
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{shouldRenderPageTabBar() ? <UserTabBar selected={3} /> : null}
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user