- 新建 useElderClass hook,替代每页 3 行样板代码 - 新建 CSS 自定义属性 Design Token 系统(tokens.scss) 正常/关怀两套值:字号、间距、触控、布局参数 - 15 个页面批量接入关怀模式 class: TabBar: 商城页 主流程: 预约列表/详情/创建、咨询详情 子包: 体征录入/趋势/日常监测/告警、用药/档案/随访/报告/家庭/设置 - 新建 elder-toast 工具(关怀模式 3s + 触觉反馈) - 页面覆盖率:4/59 → 22/59 (37%) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
109 lines
3.4 KiB
TypeScript
109 lines
3.4 KiB
TypeScript
import React, { useState, useCallback } from 'react';
|
|
import { View, Text } from '@tarojs/components';
|
|
import Taro, { useDidShow, usePullDownRefresh, useReachBottom } from '@tarojs/taro';
|
|
import { listReports, LabReport } from '../../../services/report';
|
|
import EmptyState from '../../../components/EmptyState';
|
|
import Loading from '../../../components/Loading';
|
|
import { useElderClass } from '../../../hooks/useElderClass';
|
|
import './index.scss';
|
|
|
|
export default function MyReports() {
|
|
const modeClass = useElderClass();
|
|
const [reports, setReports] = useState<LabReport[]>([]);
|
|
const [page, setPage] = useState(1);
|
|
const [total, setTotal] = useState(0);
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
const fetchData = useCallback(async (p: number, append = false) => {
|
|
const patientId = Taro.getStorageSync('current_patient_id') || '';
|
|
if (!patientId) {
|
|
setReports([]);
|
|
return;
|
|
}
|
|
setLoading(true);
|
|
try {
|
|
const res = await listReports(patientId, p);
|
|
const list = res.data || [];
|
|
setReports(append ? (prev) => [...prev, ...list] : list);
|
|
setTotal(res.total);
|
|
setPage(p);
|
|
} catch {
|
|
Taro.showToast({ title: '加载失败', icon: 'none' });
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
}, []);
|
|
|
|
useDidShow(() => {
|
|
fetchData(1);
|
|
});
|
|
|
|
usePullDownRefresh(() => {
|
|
fetchData(1).finally(() => {
|
|
Taro.stopPullDownRefresh();
|
|
});
|
|
});
|
|
|
|
useReachBottom(() => {
|
|
if (!loading && reports.length < total) {
|
|
fetchData(page + 1, true);
|
|
}
|
|
});
|
|
|
|
const goToDetail = (id: string) => {
|
|
Taro.navigateTo({ url: `/pages/report/detail/index?id=${id}` });
|
|
};
|
|
|
|
const formatStatus = (report: LabReport) => {
|
|
const indicators = report.indicators;
|
|
if (!indicators || typeof indicators !== 'object') return 'unknown';
|
|
const vals = Object.values(indicators) as Array<{ status?: string }>;
|
|
const hasAbnormal = vals.some((v) => v.status === 'high' || v.status === 'low');
|
|
return hasAbnormal ? 'abnormal' : 'normal';
|
|
};
|
|
|
|
const typeInitial = (type: string) => {
|
|
return type ? type.charAt(0) : '报';
|
|
};
|
|
|
|
return (
|
|
<View className={`my-reports-page ${modeClass}`}>
|
|
<Text className='page-title'>检查报告</Text>
|
|
|
|
<View className='report-list'>
|
|
{reports.map((r) => {
|
|
const status = formatStatus(r);
|
|
return (
|
|
<View
|
|
className='report-card'
|
|
key={r.id}
|
|
onClick={() => goToDetail(r.id)}
|
|
>
|
|
<View className='report-card-top'>
|
|
<View className='report-type-row'>
|
|
<View className='report-avatar'>
|
|
<Text className='report-avatar-text'>{typeInitial(r.report_type)}</Text>
|
|
</View>
|
|
<Text className='report-type'>{r.report_type}</Text>
|
|
</View>
|
|
<Text className={`report-status ${status}`}>
|
|
{status === 'normal' ? '正常' : status === 'abnormal' ? '异常' : '未知'}
|
|
</Text>
|
|
</View>
|
|
<Text className='report-date'>{r.report_date}</Text>
|
|
</View>
|
|
);
|
|
})}
|
|
</View>
|
|
|
|
{reports.length === 0 && !loading && (
|
|
<EmptyState text={Taro.getStorageSync('current_patient_id') ? '暂无报告记录' : '请先在就诊人管理中选择就诊人'} />
|
|
)}
|
|
|
|
{loading && (
|
|
<Loading />
|
|
)}
|
|
</View>
|
|
);
|
|
}
|