From 80794c954746434e83ec95c2369d6a5cd1b0c1cd Mon Sep 17 00:00:00 2001 From: iven Date: Sat, 16 May 2026 00:50:27 +0800 Subject: [PATCH] =?UTF-8?q?refactor(mp):=20=E8=AF=95=E7=82=B9=E8=BF=81?= =?UTF-8?q?=E7=A7=BB=E6=82=A3=E8=80=85=E5=88=97=E8=A1=A8=E9=A1=B5=20?= =?UTF-8?q?=E2=80=94=20=E4=BD=BF=E7=94=A8=E7=BB=9F=E4=B8=80=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 替换手写 UI 为: - PageShell 替代手动 min-height/bg/padding - SearchSection 替代手写搜索栏 + 标签筛选 - ContentCard 替代手写卡片样式(背景/圆角/阴影/触摸反馈) - StatusTag 替代 @include tag() mixin - LoadingCard 替代初始加载的 Loading 组件 SCSS 从 151 行精简到 65 行,保留页面特有业务样式。 数据加载逻辑(无限滚动 + usePageData)保持不变。 --- .../pages/pkg-doctor-core/patients/index.scss | 136 ++++-------------- .../pages/pkg-doctor-core/patients/index.tsx | 118 ++++++--------- 2 files changed, 69 insertions(+), 185 deletions(-) diff --git a/apps/miniprogram/src/pages/pkg-doctor-core/patients/index.scss b/apps/miniprogram/src/pages/pkg-doctor-core/patients/index.scss index bdd150c..a2dc5a9 100644 --- a/apps/miniprogram/src/pages/pkg-doctor-core/patients/index.scss +++ b/apps/miniprogram/src/pages/pkg-doctor-core/patients/index.scss @@ -1,47 +1,9 @@ @import '../../../styles/variables.scss'; -@import '../../../styles/mixins.scss'; -.patient-list-page { - min-height: 100vh; - background: $bg; - padding: 24px; - padding-bottom: 120px; -} - -.search-bar { - margin-bottom: 20px; - - .search-input { - background: $card; - border-radius: $r; - padding: 20px 24px; - font-size: var(--tk-font-body-lg); - width: 100%; - box-sizing: border-box; - box-shadow: $shadow-sm; - } -} - -.tag-filter { - white-space: nowrap; - margin-bottom: 20px; - width: 100%; -} - -.tag-chip { - display: inline-block; - padding: 10px 24px; - border-radius: $r-pill; - background: $bd-l; - font-size: var(--tk-font-h2); - color: $tx2; - margin-right: 16px; - - &.active { - background: $pri; - color: $card; - } -} +// PageShell 已接管:min-height, background, padding +// SearchSection 已接管:search-bar +// ContentCard 已接管:patient-card 背景/圆角/阴影/触摸反馈 +// StatusTag 已接管:patient-card__status 标签样式 .patient-count { margin-bottom: 16px; @@ -55,90 +17,44 @@ .patient-cards { display: flex; flex-direction: column; + gap: var(--tk-gap-md); +} + +.patient-card__header { + display: flex; + align-items: center; gap: 16px; } -.patient-card { - background: $card; - border-radius: $r-lg; - padding: 28px; - box-shadow: $shadow-sm; +.patient-card__name { + font-size: var(--tk-font-num); + font-weight: 600; + color: $tx; +} - &:active { - background: $bd-l; - } +.patient-card__meta { + font-size: var(--tk-font-h2); + color: $tx2; + flex: 1; +} - &__header { - display: flex; - align-items: center; - margin-bottom: 12px; - } - - &__name { - font-size: var(--tk-font-num); - font-weight: 600; - color: $tx; - margin-right: 16px; - } - - &__meta { - font-size: var(--tk-font-h2); - color: $tx2; - } - - &__tags { - display: flex; - flex-wrap: wrap; - gap: 8px; - margin-bottom: 8px; - } - - &__status { - @include tag($bg, $tx2); - - &--active { - @include tag($acc-l, $acc); - } - - &--inactive { - @include tag($bd-l, $tx3); - } - } +.patient-card__tags { + display: flex; + flex-wrap: wrap; + gap: 8px; + margin-top: 12px; } .patient-tag { padding: 4px 14px; border-radius: $r; - background: $pri-l; + background: rgba($pri, 0.1); &__text { font-size: var(--tk-font-body); } } -.pagination { - display: flex; - justify-content: center; - align-items: center; - gap: 24px; - margin-top: 32px; - - &__btn { - font-size: var(--tk-font-h1); - color: $pri; - padding: 12px 24px; - - &.disabled { - color: $tx3; - } - } - - &__info { - font-size: var(--tk-font-h2); - color: $tx2; - } -} - .load-more-hint-wrap { text-align: center; padding: 20px; diff --git a/apps/miniprogram/src/pages/pkg-doctor-core/patients/index.tsx b/apps/miniprogram/src/pages/pkg-doctor-core/patients/index.tsx index 846482b..e09e462 100644 --- a/apps/miniprogram/src/pages/pkg-doctor-core/patients/index.tsx +++ b/apps/miniprogram/src/pages/pkg-doctor-core/patients/index.tsx @@ -1,10 +1,15 @@ import { useState, useEffect, useCallback, useRef } from 'react'; -import { View, Text, Input, ScrollView } from '@tarojs/components'; +import { View, Text } from '@tarojs/components'; import Taro, { useReachBottom } from '@tarojs/taro'; import { usePageData } from '@/hooks/usePageData'; import { listPatients, listPatientTags, type PatientItem, type PatientTag } from '@/services/doctor/patient'; -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 EmptyState from '@/components/EmptyState'; +import Loading from '@/components/Loading'; import { useElderClass } from '../../../hooks/useElderClass'; import './index.scss'; @@ -19,9 +24,7 @@ export default function PatientList() { const [page, setPage] = useState(1); const mountedRef = useRef(false); - useEffect(() => { - loadTags(); - }, []); + useEffect(() => { loadTags(); }, []); const loadTags = async () => { try { @@ -40,11 +43,7 @@ export default function PatientList() { tag_id: activeTag || undefined, }); const list = res.data || []; - if (isRefresh) { - setPatients(list); - } else { - setPatients((prev) => [...prev, ...list]); - } + setPatients(prev => isRefresh ? list : [...prev, ...list]); setTotal(res.total || 0); setPage(pageNum); } catch { @@ -59,24 +58,15 @@ export default function PatientList() { { enablePullDown: true }, ); - // tag 变化时重新加载(跳过首次 mount,由 usePageData 的 useDidShow 处理) useEffect(() => { - if (mountedRef.current) { - loadPatients(1, true); - } + if (mountedRef.current) { loadPatients(1, true); } mountedRef.current = true; }, [activeTag, loadPatients]); useReachBottom(() => { - if (!loading && patients.length < total) { - loadPatients(page + 1); - } + if (!loading && patients.length < total) { loadPatients(page + 1); } }); - const handleSearch = () => { - loadPatients(1, true); - }; - const handleTagFilter = (tagId: string) => { setActiveTag(tagId === activeTag ? '' : tagId); }; @@ -98,91 +88,69 @@ export default function PatientList() { return `${age}岁`; }; - if (loading && patients.length === 0) return ; + const filters = [ + { key: '', label: '全部' }, + ...tags.map(t => ({ key: t.id, label: t.name })), + ]; + + if (loading && patients.length === 0) return ; return ( - - - setSearch(e.detail.value)} - confirmType='search' - onConfirm={handleSearch} - /> - + + loadPatients(1, true)} + placeholder="搜索患者姓名/手机号" + filters={filters} + activeFilter={activeTag} + onFilterChange={handleTagFilter} + /> - {tags.length > 0 && ( - - handleTagFilter('')} - > - 全部 - - {tags.map((tag) => ( - handleTagFilter(tag.id)} - > - {tag.name} - - ))} - - )} - - + 共 {total} 位患者 {patients.length === 0 ? ( - + ) : ( - + {patients.map((p) => ( - Taro.navigateTo({ url: `/pages/pkg-doctor-core/patients/detail/index?id=${p.id}` })} + onPress={() => Taro.navigateTo({ url: `/pages/pkg-doctor-core/patients/detail/index?id=${p.id}` })} > - - {p.name} - + + {p.name} + {getGenderLabel(p.gender)} {calcAge(p.birth_date)} + {p.status && } {p.tags && p.tags.length > 0 && ( - + {p.tags.map((t) => ( - {t.name} + {t.name} ))} )} - {p.status && ( - - {p.status === 'active' ? '活跃' : p.status === 'inactive' ? '非活跃' : p.status} - - )} - + ))} )} {!loading && patients.length >= total && total > 0 && ( - - 没有更多了 + + 没有更多了 )} {loading && patients.length > 0 && } - + ); }