- 新增 actionInbox 服务层(待办事项列表/线程查询) - consultation 服务扩展(会话详情/发送消息) - 多页面代码优化(profile/messages/health/article) - 新增 navigate 工具函数
191 lines
7.1 KiB
TypeScript
191 lines
7.1 KiB
TypeScript
import { View, Text } from '@tarojs/components';
|
||
import Taro, { useDidShow } from '@tarojs/taro';
|
||
import { useAuthStore } from '../../stores/auth';
|
||
import { usePointsStore } from '../../stores/points';
|
||
import { useUIStore } from '../../stores/ui';
|
||
import { navigateToLogin } from '../../utils/navigate';
|
||
import './index.scss';
|
||
|
||
interface MenuItem {
|
||
label: string;
|
||
icon: string;
|
||
bg: string;
|
||
color: string;
|
||
path: string;
|
||
isSwitchTab?: boolean;
|
||
}
|
||
|
||
interface MenuGroup {
|
||
title: string;
|
||
items: MenuItem[];
|
||
}
|
||
|
||
const LOGGED_IN_GROUPS: MenuGroup[] = [
|
||
{
|
||
title: '健康管理',
|
||
items: [
|
||
{ label: '健康记录', icon: '健', bg: 'pri-l', color: 'pri', path: '/pages/pkg-profile/health-records/index' },
|
||
{ label: '我的报告', icon: '报', bg: 'acc-l', color: 'acc', path: '/pages/pkg-profile/reports/index' },
|
||
{ label: 'AI 分析', icon: '智', bg: 'pri-l', color: 'pri', path: '/pages/ai-report/list/index' },
|
||
{ label: '诊断记录', icon: '诊', bg: 'acc-l', color: 'acc', path: '/pages/pkg-profile/diagnoses/index' },
|
||
{ label: '用药记录', icon: '药', bg: 'pri-l', color: 'pri', path: '/pages/pkg-profile/medication/index' },
|
||
],
|
||
},
|
||
{
|
||
title: '就诊服务',
|
||
items: [
|
||
{ label: '我的预约', icon: '约', bg: 'pri-l', color: 'pri', path: '/pages/appointment/index' },
|
||
{ label: '我的随访', icon: '随', bg: 'acc-l', color: 'acc', path: '/pages/pkg-profile/followups/index' },
|
||
{ label: '在线咨询', icon: '问', bg: 'pri-l', color: 'pri', path: '/pages/consultation/index' },
|
||
],
|
||
},
|
||
{
|
||
title: '透析管理',
|
||
items: [
|
||
{ label: '透析记录', icon: '透', bg: 'pri-l', color: 'pri', path: '/pages/pkg-profile/dialysis-records/index' },
|
||
{ label: '透析处方', icon: '方', bg: 'acc-l', color: 'acc', path: '/pages/pkg-profile/dialysis-prescriptions/index' },
|
||
{ label: '知情同意', icon: '知', bg: 'pri-l', color: 'pri', path: '/pages/pkg-profile/consents/index' },
|
||
],
|
||
},
|
||
{
|
||
title: '生活服务',
|
||
items: [
|
||
{ label: '积分商城', icon: '礼', bg: 'pri-l', color: 'pri', path: '/pages/mall/index', isSwitchTab: true },
|
||
{ label: '线下活动', icon: '活', bg: 'acc-l', color: 'acc', path: '/pages/events/index' },
|
||
],
|
||
},
|
||
{
|
||
title: '账号',
|
||
items: [
|
||
{ label: '就诊人管理', icon: '家', bg: 'pri-l', color: 'pri', path: '/pages/pkg-profile/family/index' },
|
||
{ label: '长辈模式', icon: '老', bg: 'acc-l', color: 'acc', path: '/pages/pkg-profile/elder-mode/index' },
|
||
{ label: '设备同步', icon: '设', bg: 'surface-alt', color: 'tx3', path: '/pages/device-sync/index' },
|
||
{ label: '设置', icon: '齿', bg: 'surface-alt', color: 'tx3', path: '/pages/pkg-profile/settings/index' },
|
||
],
|
||
},
|
||
];
|
||
|
||
const GUEST_GROUPS: MenuGroup[] = [
|
||
{
|
||
title: '设置',
|
||
items: [
|
||
{ label: '长辈模式', icon: '老', bg: 'acc-l', color: 'acc', path: '/pages/pkg-profile/elder-mode/index' },
|
||
{ label: '设置', icon: '齿', bg: 'surface-alt', color: 'tx3', path: '/pages/pkg-profile/settings/index' },
|
||
],
|
||
},
|
||
];
|
||
|
||
export default function Profile() {
|
||
const { user, logout } = useAuthStore();
|
||
const { account: pointsAccount, checkinStatus: checkinInfo, refresh: refreshPoints } = usePointsStore();
|
||
const mode = useUIStore((s) => s.mode);
|
||
const modeClass = mode === 'elder' ? 'elder-mode' : '';
|
||
const isGuest = !user;
|
||
const groups = isGuest ? GUEST_GROUPS : LOGGED_IN_GROUPS;
|
||
|
||
useDidShow(() => {
|
||
if (!isGuest) refreshPoints();
|
||
});
|
||
|
||
const handleMenuClick = (item: MenuItem) => {
|
||
if (item.isSwitchTab) {
|
||
Taro.switchTab({ url: item.path });
|
||
} else {
|
||
Taro.navigateTo({ url: item.path });
|
||
}
|
||
};
|
||
|
||
const handleLogout = () => {
|
||
Taro.showModal({
|
||
title: '退出登录',
|
||
content: '确定要退出登录吗?',
|
||
}).then((res) => {
|
||
if (res.confirm) {
|
||
logout();
|
||
}
|
||
});
|
||
};
|
||
|
||
const displayName = user?.display_name || user?.username || (user?.phone ? `${user.phone.slice(-4)}` : '') || '用户';
|
||
const displayInitial = (user?.display_name || user?.username || '用').charAt(0);
|
||
|
||
return (
|
||
<View className={`profile-page ${modeClass}`}>
|
||
{/* 用户信息卡片 */}
|
||
{isGuest ? (
|
||
<View className='profile-user-card' onClick={navigateToLogin}>
|
||
<View className='profile-avatar profile-avatar--guest'>
|
||
<Text className='profile-avatar-char'>?</Text>
|
||
</View>
|
||
<View className='profile-user-info'>
|
||
<Text className='profile-name'>未登录</Text>
|
||
<Text className='profile-phone'>点击登录,开启健康管理之旅</Text>
|
||
</View>
|
||
<Text className='profile-arrow'>›</Text>
|
||
</View>
|
||
) : (
|
||
<>
|
||
<View className='profile-user-card'>
|
||
<View className='profile-avatar'>
|
||
<Text className='profile-avatar-char'>{displayInitial}</Text>
|
||
</View>
|
||
<View className='profile-user-info'>
|
||
<Text className='profile-name'>{displayName}</Text>
|
||
<Text className='profile-phone'>
|
||
{user?.phone ? `${user.phone.slice(0, 3)}****${user.phone.slice(-4)}` : ''}
|
||
</Text>
|
||
</View>
|
||
<Text className='profile-arrow'>›</Text>
|
||
</View>
|
||
|
||
{/* 积分 + 打卡 */}
|
||
<View className='profile-stats-row'>
|
||
<View className='stat-card'>
|
||
<Text className='stat-value stat-pri'>{(pointsAccount?.balance ?? 0).toLocaleString()}</Text>
|
||
<Text className='stat-label'>健康积分</Text>
|
||
</View>
|
||
<View className='stat-card'>
|
||
<Text className='stat-value stat-acc'>{checkinInfo?.consecutive_days ?? 0}<Text className='stat-unit'>天</Text></Text>
|
||
<Text className='stat-label'>连续打卡</Text>
|
||
</View>
|
||
</View>
|
||
</>
|
||
)}
|
||
|
||
{/* 分组菜单 */}
|
||
{groups.map((group) => (
|
||
<View className='menu-group' key={group.title}>
|
||
<Text className='menu-group-title'>{group.title}</Text>
|
||
<View className='menu-group-card'>
|
||
{group.items.map((item, idx) => (
|
||
<View
|
||
className='menu-item'
|
||
key={item.label}
|
||
onClick={() => handleMenuClick(item)}
|
||
>
|
||
<View className={`menu-icon menu-icon--${item.bg}`}>
|
||
<Text className={`menu-icon-text menu-icon-text--${item.color}`}>{item.icon}</Text>
|
||
</View>
|
||
<Text className='menu-label'>{item.label}</Text>
|
||
{idx < group.items.length - 1 && <View className='menu-divider' />}
|
||
<Text className='menu-arrow'>›</Text>
|
||
</View>
|
||
))}
|
||
</View>
|
||
</View>
|
||
))}
|
||
|
||
{/* 退出登录 / 登录 */}
|
||
{isGuest ? (
|
||
<View className='profile-logout' onClick={navigateToLogin}>
|
||
<Text className='logout-text logout-text--pri'>登录账号</Text>
|
||
</View>
|
||
) : (
|
||
<View className='profile-logout' onClick={handleLogout}>
|
||
<Text className='logout-text'>退出登录</Text>
|
||
</View>
|
||
)}
|
||
</View>
|
||
);
|
||
}
|