refactor(mp): 迁移随访列表页 — 使用统一组件库 PageShell/ContentCard/StatusTag/LoadingCard/SearchSection

This commit is contained in:
iven
2026-05-16 00:56:51 +08:00
parent 40b88c566d
commit 8d41d5a167
2 changed files with 78 additions and 85 deletions

View File

@@ -1,13 +1,12 @@
@import '../../../styles/variables.scss'; @import '../../../styles/variables.scss';
@import '../../../styles/mixins.scss';
.followup-page { // PageShell 已接管min-height, background, padding
min-height: 100vh; // SearchSection 已接管:标签筛选栏
background: $bg; // ContentCard 已接管task-card 背景/圆角/阴影/触摸反馈
} // StatusTag 已接管:任务状态标签
.task-count { .task-count {
padding: 20px 28px; margin-bottom: 16px;
text { text {
font-size: var(--tk-font-h2); font-size: var(--tk-font-h2);
@@ -16,56 +15,37 @@
} }
.task-list { .task-list {
padding: 0 24px 120px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 16px; gap: var(--tk-gap-md);
} }
.task-card { .task-card__header {
background: $card; display: flex;
border-radius: $r-lg; justify-content: space-between;
padding: 28px; align-items: center;
box-shadow: $shadow-sm; margin-bottom: 12px;
}
&:active {
background: $bd-l; .task-card__type {
} font-size: var(--tk-font-body-lg);
font-weight: 600;
&__header { color: $tx;
display: flex; }
justify-content: space-between;
align-items: center; .task-card__patient {
margin-bottom: 12px; font-size: var(--tk-font-h1);
} color: $tx2;
display: block;
&__type { margin-bottom: 8px;
font-family: 'Georgia', 'Times New Roman', serif; }
font-size: var(--tk-font-body-lg);
font-weight: 600; .task-card__footer {
color: $tx; display: flex;
} justify-content: space-between;
}
&__status {
@include tag(transparent, $tx2); .task-card__date {
font-size: var(--tk-font-body); font-size: var(--tk-font-h2);
font-weight: 500; color: $tx3;
}
&__patient {
font-size: var(--tk-font-h1);
color: $tx2;
display: block;
margin-bottom: 8px;
}
&__footer {
display: flex;
justify-content: space-between;
}
&__date {
font-size: var(--tk-font-h2);
color: $tx3;
}
} }

View File

@@ -1,14 +1,16 @@
import { useState, useEffect, useCallback, useRef } from 'react'; import { useState, useEffect, useCallback, useRef } from 'react';
import { View, Text, ScrollView } from '@tarojs/components'; import { View, Text } from '@tarojs/components';
import Taro, { useRouter } from '@tarojs/taro'; import Taro, { useRouter } from '@tarojs/taro';
import { usePageData } from '@/hooks/usePageData'; import { usePageData } from '@/hooks/usePageData';
import { listFollowUpTasks, type FollowUpTask } from '@/services/doctor/followup'; import { listFollowUpTasks, type FollowUpTask } from '@/services/doctor/followup';
import Loading from '@/components/Loading'; import PageShell from '@/components/ui/PageShell';
import ContentCard from '@/components/ui/ContentCard';
import StatusTag from '@/components/ui/StatusTag';
import LoadingCard from '@/components/ui/LoadingCard';
import SearchSection from '@/components/patterns/SearchSection';
import ErrorState from '@/components/ErrorState'; import ErrorState from '@/components/ErrorState';
import EmptyState from '@/components/EmptyState'; import EmptyState from '@/components/EmptyState';
import { useElderClass } from '../../../hooks/useElderClass'; import { useElderClass } from '../../../hooks/useElderClass';
import { getStatusInlineStyle, getStatusLabel } from '@/utils/statusTag';
import SegmentTabs from '@/components/SegmentTabs';
import './index.scss'; import './index.scss';
const TABS = [ const TABS = [
@@ -19,6 +21,13 @@ const TABS = [
{ key: 'overdue', label: '已逾期' }, { key: 'overdue', label: '已逾期' },
]; ];
const STATUS_COLOR_MAP: Record<string, 'warning' | 'info' | 'success' | 'error'> = {
pending: 'warning',
in_progress: 'info',
completed: 'success',
overdue: 'error',
};
export default function FollowUpList() { export default function FollowUpList() {
const router = useRouter(); const router = useRouter();
const patientId = router.params.patientId || ''; const patientId = router.params.patientId || '';
@@ -52,7 +61,6 @@ export default function FollowUpList() {
const { trigger } = usePageData(loadTasks); const { trigger } = usePageData(loadTasks);
// tab/patientId 变化时重新加载(跳过首次 mount由 usePageData 的 useDidShow 处理)
useEffect(() => { useEffect(() => {
if (mountedRef.current) { if (mountedRef.current) {
trigger(); trigger();
@@ -74,43 +82,48 @@ export default function FollowUpList() {
return map[type] || type; return map[type] || type;
}; };
if (loading && tasks.length === 0) return <Loading />; if (loading && tasks.length === 0) return <LoadingCard count={3} />;
if (error) return <ErrorState onRetry={loadTasks} />; if (error) return <ErrorState onRetry={loadTasks} />;
return ( return (
<ScrollView scrollY className={`followup-page ${modeClass}`}> <PageShell safeBottom className={modeClass}>
<SegmentTabs tabs={TABS} activeKey={activeTab} onChange={(key) => setActiveTab(key)} variant="underline" /> <SearchSection
value=""
onChange={() => {}}
filters={TABS}
activeFilter={activeTab}
onFilterChange={(key) => setActiveTab(key)}
/>
<View className='task-count'> <View className="task-count">
<Text> {total} </Text> <Text> {total} </Text>
</View> </View>
{tasks.length === 0 ? ( {tasks.length === 0 ? (
<EmptyState text='暂无随访任务' /> <EmptyState text="暂无随访任务" />
) : ( ) : (
<View className='task-list'> <View className="task-list">
{tasks.map((task) => { {tasks.map((task) => (
return ( <ContentCard
<View key={task.id}
key={task.id} onPress={() => Taro.navigateTo({ url: `/pages/pkg-doctor-core/followup/detail/index?id=${task.id}` })}
className='task-card' >
onClick={() => Taro.navigateTo({ url: `/pages/pkg-doctor-core/followup/detail/index?id=${task.id}` })} <View className="task-card__header">
> <Text className="task-card__type">{getTypeLabel(task.follow_up_type)}</Text>
<View className='task-card__header'> <StatusTag
<Text className='task-card__type'>{getTypeLabel(task.follow_up_type)}</Text> status={task.status}
<View className='task-card__status' style={getStatusInlineStyle(task.status)}> colorMap={STATUS_COLOR_MAP}
<Text>{getStatusLabel(task.status)}</Text> size="sm"
</View> />
</View>
<Text className='task-card__patient'>{task.patient_name || '未知患者'}</Text>
<View className='task-card__footer'>
<Text className='task-card__date'>: {formatDate(task.planned_date)}</Text>
</View>
</View> </View>
); <Text className="task-card__patient">{task.patient_name || '未知患者'}</Text>
})} <View className="task-card__footer">
<Text className="task-card__date">: {formatDate(task.planned_date)}</Text>
</View>
</ContentCard>
))}
</View> </View>
)} )}
</ScrollView> </PageShell>
); );
} }