fix(miniprogram): 多角色找茬模式发现并修复 16 个问题
Some checks failed
CI / frontend-build (push) Has been cancelled
CI / rust-check (push) Has been cancelled
CI / rust-test (push) Has been cancelled
CI / security-audit (push) Has been cancelled

P0 Bug:
- 健康 AI 建议幽灵路径 pkg-appointment → appointment/create
- 血糖 indicator_type 始终 blood_sugar,不区分空腹/餐后
- 商城订单页 switchTab 跳转非 TabBar 页面

P1 设计系统:
- Profile/Index 页 emoji 图标替换为衬线首字
- Profile 硬编码颜色替换为 SCSS 变量 class
- alerts/action-inbox 两个页面全面接入设计系统
- ai-report/detail 删除重复 mixin 定义
- ErrorBoundary 添加重试按钮移除 emoji
- 新增 $r-xs: 8px 圆角变量

P1 导航/交互:
- Profile 补充 4 个缺失菜单(透析/知情同意/用药/活动)
- Settings 隐私政策改为跳转实际页面
- 全局启用 enablePullDownRefresh
- 首页/健康页添加下拉刷新
- 咨询/消息列表添加分页加载更多
- 医生端患者列表改为上拉加载
- 首页/健康页间距统一为 24px
This commit is contained in:
iven
2026-05-08 16:07:06 +08:00
parent 22b8ac7ac6
commit 3dac6a9eda
17 changed files with 231 additions and 134 deletions

View File

@@ -1,6 +1,6 @@
import { useState } from 'react';
import { useState, useRef } from 'react';
import { View, Text } from '@tarojs/components';
import Taro, { useDidShow } from '@tarojs/taro';
import Taro, { useDidShow, useReachBottom } from '@tarojs/taro';
import { listConsultations, ConsultationSession } from '../../services/consultation';
import { notificationService } from '../../services/notification';
import Loading from '../../components/Loading';
@@ -21,34 +21,62 @@ export default function Messages() {
const [sessions, setSessions] = useState<ConsultationSession[]>([]);
const [notifications, setNotifications] = useState<NotificationItem[]>([]);
const [loading, setLoading] = useState(false);
const [page, setPage] = useState(1);
const [total, setTotal] = useState(0);
const loadingRef = useRef(false);
useDidShow(() => {
loadData(activeTab);
loadData(activeTab, 1, true);
});
const loadData = async (tab: MsgTab) => {
const loadData = async (tab: MsgTab, pageNum: number = 1, isRefresh = false) => {
if (loadingRef.current) return;
loadingRef.current = true;
setLoading(true);
try {
if (tab === 'consultation') {
const res = await listConsultations({ page: 1, page_size: 20 });
setSessions(res.data || []);
const res = await listConsultations({ page: pageNum, page_size: 20 });
const list = res.data || [];
if (isRefresh) {
setSessions(list);
} else {
setSessions((prev) => [...prev, ...list]);
}
setTotal(res.total || 0);
} else {
const res = await notificationService.list<{ data: unknown[] }>({ page: 1, page_size: 20 });
setNotifications((res as { data?: unknown[] })?.data || []);
const res = await notificationService.list<{ data: unknown[]; total?: number }>({ page: pageNum, page_size: 20 });
const list = (res as { data?: unknown[] })?.data || [];
if (isRefresh) {
setNotifications(list as NotificationItem[]);
} else {
setNotifications((prev) => [...prev, ...(list as NotificationItem[])]);
}
setTotal((res as { total?: number })?.total || 0);
}
setPage(pageNum);
} catch {
if (tab === 'consultation') setSessions([]);
else setNotifications([]);
if (isRefresh) {
if (tab === 'consultation') setSessions([]);
else setNotifications([]);
}
} finally {
setLoading(false);
loadingRef.current = false;
}
};
const handleTabChange = (tab: MsgTab) => {
setActiveTab(tab);
loadData(tab);
loadData(tab, 1, true);
};
useReachBottom(() => {
const currentList = activeTab === 'consultation' ? sessions : notifications;
if (!loading && currentList.length < total) {
loadData(activeTab, page + 1);
}
});
const formatTime = (dateStr: string | null) => {
if (!dateStr) return '';
const d = new Date(dateStr);