Compare commits
8 Commits
8d41d5a167
...
c6bffd4019
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c6bffd4019 | ||
|
|
466b6567d1 | ||
|
|
37327a4da4 | ||
|
|
4dd5a1b4d9 | ||
|
|
900c9babc3 | ||
|
|
61f1061092 | ||
|
|
85701ddeb2 | ||
|
|
5e230ba1b5 |
@@ -1,21 +1,6 @@
|
||||
@import '../../../styles/variables.scss';
|
||||
@import '../../../styles/mixins.scss';
|
||||
|
||||
.detail-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding: 24px;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
|
||||
.detail-card {
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
padding: 28px;
|
||||
margin-bottom: 20px;
|
||||
box-shadow: $shadow-sm;
|
||||
}
|
||||
|
||||
.detail-type {
|
||||
@include section-title;
|
||||
margin-bottom: 12px;
|
||||
@@ -31,12 +16,7 @@
|
||||
color: $tx3;
|
||||
}
|
||||
|
||||
.content-card {
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
padding: 28px;
|
||||
box-shadow: $shadow-sm;
|
||||
|
||||
.content-card-wrap {
|
||||
// RichText 内部样式
|
||||
h1, h2, h3 {
|
||||
font-weight: bold;
|
||||
|
||||
@@ -4,6 +4,8 @@ import Taro, { useRouter } from '@tarojs/taro';
|
||||
import { usePageData } from '@/hooks/usePageData';
|
||||
import { getAiAnalysisDetail, type AiAnalysisItem } from '@/services/ai-analysis';
|
||||
import Loading from '@/components/Loading';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import ContentCard from '@/components/ui/ContentCard';
|
||||
import { sanitizeHtml } from '@/utils/sanitize-html';
|
||||
import { useElderClass } from '../../../hooks/useElderClass';
|
||||
import './index.scss';
|
||||
@@ -54,9 +56,9 @@ export default function AiReportDetail() {
|
||||
|
||||
if (!analysis) {
|
||||
return (
|
||||
<View className={`detail-page ${modeClass}`}>
|
||||
<PageShell className={modeClass}>
|
||||
<Text className='empty-text'>报告不存在</Text>
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -68,8 +70,8 @@ export default function AiReportDetail() {
|
||||
const isAutoAnalysis = (analysis.result_metadata as Record<string, unknown>)?.auto_analysis === true;
|
||||
|
||||
return (
|
||||
<View className={`detail-page ${modeClass}`}>
|
||||
<View className='detail-card'>
|
||||
<PageShell className={modeClass}>
|
||||
<ContentCard>
|
||||
<Text className='detail-type'>{TYPE_LABELS[analysis.analysis_type] || analysis.analysis_type}</Text>
|
||||
<View className='detail-meta'>
|
||||
<Text className='meta-item'>模型: {analysis.model_used}</Text>
|
||||
@@ -80,7 +82,7 @@ export default function AiReportDetail() {
|
||||
<Text className='auto-badge-text'>系统自动分析</Text>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
{isTrendAnalysis && (
|
||||
<View className='trend-tip-card'>
|
||||
@@ -90,9 +92,9 @@ export default function AiReportDetail() {
|
||||
</View>
|
||||
)}
|
||||
|
||||
<View className='content-card'>
|
||||
<ContentCard className='content-card-wrap'>
|
||||
<RichText className='report-content' nodes={htmlContent} />
|
||||
</View>
|
||||
</View>
|
||||
</ContentCard>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
@import '../../../styles/variables.scss';
|
||||
@import '../../../styles/mixins.scss';
|
||||
|
||||
.ai-report-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding: 24px;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
// PageShell 已接管:min-height, background, padding
|
||||
|
||||
.page-title {
|
||||
@include section-title;
|
||||
|
||||
@@ -6,6 +6,7 @@ import { listAiAnalysis, type AiAnalysisItem } from '@/services/ai-analysis';
|
||||
import Loading from '@/components/Loading';
|
||||
import EmptyState from '@/components/EmptyState';
|
||||
import { useElderClass } from '../../../hooks/useElderClass';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import './index.scss';
|
||||
|
||||
const TYPE_LABELS: Record<string, string> = {
|
||||
@@ -61,14 +62,14 @@ export default function AiReportList() {
|
||||
|
||||
if (list.length === 0) {
|
||||
return (
|
||||
<View className={`ai-report-page ${modeClass}`}>
|
||||
<PageShell className={modeClass}>
|
||||
<EmptyState text='暂无 AI 分析报告' />
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<View className={`ai-report-page ${modeClass}`}>
|
||||
<PageShell className={modeClass}>
|
||||
<View className='page-title'>AI 分析报告</View>
|
||||
<ScrollView scrollY className='report-scroll' onScrollToLower={loadMore}>
|
||||
{list.map((item) => {
|
||||
@@ -93,6 +94,6 @@ export default function AiReportList() {
|
||||
{loading && <Loading />}
|
||||
{!hasMore && list.length > 0 && <Text className='no-more'>没有更多了</Text>}
|
||||
</ScrollView>
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
@import '../../../styles/variables.scss';
|
||||
@import '../../../styles/mixins.scss';
|
||||
|
||||
.create-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
// PageShell 已接管:min-height, background
|
||||
|
||||
.create-page-shell {
|
||||
padding-bottom: 160px;
|
||||
}
|
||||
|
||||
@@ -132,11 +132,7 @@
|
||||
|
||||
/* 确认卡片 (step 3 医生信息) */
|
||||
.confirm-card {
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
padding: 24px 28px;
|
||||
margin-bottom: 24px;
|
||||
box-shadow: $shadow-sm;
|
||||
}
|
||||
|
||||
.confirm-row {
|
||||
|
||||
@@ -7,6 +7,8 @@ import { TEMPLATE_IDS } from '@/services/wechat-templates';
|
||||
import { trackEvent } from '@/services/analytics';
|
||||
import StepIndicator from '../../../components/StepIndicator';
|
||||
import WeekCalendar from '../../../components/WeekCalendar';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import ContentCard from '@/components/ui/ContentCard';
|
||||
import { useElderClass } from '../../../hooks/useElderClass';
|
||||
import { useSafeTimeout } from '@/hooks/useSafeTimeout';
|
||||
import './index.scss';
|
||||
@@ -153,7 +155,7 @@ export default function AppointmentCreate() {
|
||||
};
|
||||
|
||||
return (
|
||||
<View className={`create-page ${modeClass}`}>
|
||||
<PageShell padding="none" safeBottom={false} scroll={false} className={modeClass}>
|
||||
<StepIndicator
|
||||
steps={[{ label: '选科室' }, { label: '选医生' }, { label: '选时段' }]}
|
||||
current={currentStep}
|
||||
@@ -222,7 +224,7 @@ export default function AppointmentCreate() {
|
||||
<View className='step-content'>
|
||||
<Text className='step-title'>选择就诊时间</Text>
|
||||
|
||||
<View className='confirm-card'>
|
||||
<ContentCard className='confirm-card'>
|
||||
<View className='confirm-row'>
|
||||
<View className='confirm-icon-wrap'>
|
||||
<Text className='confirm-icon-serif'>医</Text>
|
||||
@@ -235,7 +237,7 @@ export default function AppointmentCreate() {
|
||||
<Text className='confirm-dept-text'>{department}</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
<WeekCalendar
|
||||
scheduledDates={scheduledDates}
|
||||
@@ -295,6 +297,6 @@ export default function AppointmentCreate() {
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,55 +1,13 @@
|
||||
@import '../../../styles/variables.scss';
|
||||
@import '../../../styles/mixins.scss';
|
||||
|
||||
.detail-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding-bottom: 160px;
|
||||
}
|
||||
|
||||
/* 顶部导航 */
|
||||
.detail-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 32px;
|
||||
padding-top: 48px;
|
||||
background: $card;
|
||||
box-shadow: $shadow-sm;
|
||||
}
|
||||
|
||||
.back-btn {
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
.back-text {
|
||||
font-size: var(--tk-font-body-lg);
|
||||
color: $pri;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
font-family: 'Georgia', 'Times New Roman', serif;
|
||||
font-size: var(--tk-font-num-lg);
|
||||
font-weight: bold;
|
||||
color: $tx;
|
||||
}
|
||||
|
||||
.header-placeholder {
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
/* 状态卡片 */
|
||||
.status-card {
|
||||
background: $card;
|
||||
border-radius: $r-lg;
|
||||
padding: 40px 32px;
|
||||
margin: 20px 24px 24px;
|
||||
box-shadow: $shadow-md;
|
||||
.status-card-wrap {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin: 20px 24px 24px;
|
||||
}
|
||||
|
||||
.status-tag {
|
||||
@@ -97,12 +55,8 @@
|
||||
}
|
||||
|
||||
/* 详情信息 */
|
||||
.info-section {
|
||||
.info-section-wrap {
|
||||
margin: 0 24px 24px;
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
padding: 28px;
|
||||
box-shadow: $shadow-sm;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
@@ -171,11 +125,9 @@
|
||||
}
|
||||
|
||||
/* 温馨提示 */
|
||||
.tips-card {
|
||||
.tips-card-wrap {
|
||||
margin: 0 24px 24px;
|
||||
background: $wrn-l;
|
||||
border-radius: $r;
|
||||
padding: 24px 28px;
|
||||
}
|
||||
|
||||
.tips-title {
|
||||
|
||||
@@ -5,6 +5,9 @@ import { getAppointment, cancelAppointment } from '../../../services/appointment
|
||||
import type { Appointment } from '../../../services/appointment';
|
||||
import Loading from '../../../components/Loading';
|
||||
import ErrorState from '../../../components/ErrorState';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import ContentCard from '@/components/ui/ContentCard';
|
||||
import PageHeader from '@/components/patterns/PageHeader';
|
||||
import { useElderClass } from '../../../hooks/useElderClass';
|
||||
import { useSafeTimeout } from '@/hooks/useSafeTimeout';
|
||||
import './index.scss';
|
||||
@@ -65,53 +68,39 @@ export default function AppointmentDetail() {
|
||||
}
|
||||
};
|
||||
|
||||
const goBack = () => Taro.navigateBack();
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<View className={`detail-page ${modeClass}`}>
|
||||
<View className='detail-header'>
|
||||
<View className='back-btn' onClick={goBack}><Text className='back-text'>返回</Text></View>
|
||||
<Text className='header-title'>预约详情</Text>
|
||||
<View className='header-placeholder' />
|
||||
</View>
|
||||
<PageShell padding='none' scroll={false} className={modeClass}>
|
||||
<PageHeader title='预约详情' />
|
||||
<Loading />
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
if (error || !appointment) {
|
||||
return (
|
||||
<View className={`detail-page ${modeClass}`}>
|
||||
<View className='detail-header'>
|
||||
<View className='back-btn' onClick={goBack}><Text className='back-text'>返回</Text></View>
|
||||
<Text className='header-title'>预约详情</Text>
|
||||
<View className='header-placeholder' />
|
||||
</View>
|
||||
<PageShell padding='none' scroll={false} className={modeClass}>
|
||||
<PageHeader title='预约详情' />
|
||||
<ErrorState text='未找到预约信息' />
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<View className={`detail-page ${modeClass}`}>
|
||||
<View className='detail-header'>
|
||||
<View className='back-btn' onClick={goBack}><Text className='back-text'>返回</Text></View>
|
||||
<Text className='header-title'>预约详情</Text>
|
||||
<View className='header-placeholder' />
|
||||
</View>
|
||||
<PageShell padding='none' scroll={false} className={modeClass}>
|
||||
<PageHeader title='预约详情' />
|
||||
|
||||
{/* 状态卡片 */}
|
||||
<View className='status-card'>
|
||||
<ContentCard variant='elevated' className='status-card-wrap'>
|
||||
<View className={`status-tag ${status.className}`}>
|
||||
<Text className='status-tag-text'>{status.label}</Text>
|
||||
</View>
|
||||
<Text className='status-doctor'>{appointment.doctor_name}</Text>
|
||||
<Text className='status-dept'>{appointment.department || ''}</Text>
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
{/* 预约信息 */}
|
||||
<View className='info-section'>
|
||||
<ContentCard className='info-section-wrap'>
|
||||
<Text className='section-title'>预约信息</Text>
|
||||
|
||||
<View className='info-item'>
|
||||
@@ -145,14 +134,14 @@ export default function AppointmentDetail() {
|
||||
</View>
|
||||
<Text className='info-value info-id'>{appointment.id}</Text>
|
||||
</View>
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
{/* 温馨提示 */}
|
||||
{(appointment.status === 'pending' || appointment.status === 'confirmed') && (
|
||||
<View className='tips-card'>
|
||||
<ContentCard className='tips-card-wrap'>
|
||||
<Text className='tips-title'>温馨提示</Text>
|
||||
<Text className='tips-text'>请按预约时间提前15分钟到达,携带有效身份证件和医保卡。</Text>
|
||||
</View>
|
||||
</ContentCard>
|
||||
)}
|
||||
|
||||
{/* 取消按钮 */}
|
||||
@@ -166,6 +155,6 @@ export default function AppointmentDetail() {
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
@import '../../styles/variables.scss';
|
||||
@import '../../styles/mixins.scss';
|
||||
|
||||
// PageShell 已接管:min-height, background, padding
|
||||
.appointment-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding-bottom: 160px;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import type { Appointment } from '../../services/appointment';
|
||||
import EmptyState from '../../components/EmptyState';
|
||||
import Loading from '../../components/Loading';
|
||||
import { useElderClass } from '../../hooks/useElderClass';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import './index.scss';
|
||||
|
||||
const STATUS_MAP: Record<string, { label: string; className: string }> = {
|
||||
@@ -80,7 +81,7 @@ export default function AppointmentList() {
|
||||
};
|
||||
|
||||
return (
|
||||
<View className={`appointment-page ${modeClass}`}>
|
||||
<PageShell className={modeClass}>
|
||||
{/* 页面标题 */}
|
||||
<View className='page-header'>
|
||||
<Text className='page-title'>预约挂号</Text>
|
||||
@@ -146,6 +147,6 @@ export default function AppointmentList() {
|
||||
<View className='fab-btn' onClick={goCreate}>
|
||||
<Text className='fab-text'>新建预约</Text>
|
||||
</View>
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
@import '../../../styles/variables.scss';
|
||||
@import '../../../styles/mixins.scss';
|
||||
|
||||
.article-detail-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
// PageShell 已接管:min-height, background, padding
|
||||
|
||||
.article-header {
|
||||
background: $card;
|
||||
|
||||
@@ -7,6 +7,7 @@ import { trackEvent } from '@/services/analytics';
|
||||
import { sanitizeHtml } from '@/utils/sanitize-html';
|
||||
import { useElderClass } from '../../../hooks/useElderClass';
|
||||
import { useAuthStore } from '../../../stores/auth';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import './index.scss';
|
||||
|
||||
export default function ArticleDetail() {
|
||||
@@ -44,26 +45,26 @@ export default function ArticleDetail() {
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<View className={`article-detail-page ${modeClass}`}>
|
||||
<PageShell className={modeClass}>
|
||||
<View className='loading-state'>
|
||||
<Text className='loading-text'>加载中...</Text>
|
||||
</View>
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
if (!article) {
|
||||
return (
|
||||
<View className={`article-detail-page ${modeClass}`}>
|
||||
<PageShell className={modeClass}>
|
||||
<View className='empty-state'>
|
||||
<Text className='empty-text'>文章不存在</Text>
|
||||
</View>
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<View className={`article-detail-page ${modeClass}`}>
|
||||
<PageShell className={modeClass}>
|
||||
{/* 文章头部 */}
|
||||
<View className='article-header'>
|
||||
<Text className='article-title'>{article.title}</Text>
|
||||
@@ -93,6 +94,6 @@ export default function ArticleDetail() {
|
||||
nodes={sanitizeHtml(article.content || '')}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,13 +1,6 @@
|
||||
@import '../../../../styles/variables.scss';
|
||||
@import '../../../../styles/mixins.scss';
|
||||
|
||||
.alert-detail-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding: 24px;
|
||||
padding-bottom: 160px;
|
||||
}
|
||||
|
||||
.alert-detail-header {
|
||||
margin-bottom: 24px;
|
||||
|
||||
@@ -77,12 +70,6 @@
|
||||
}
|
||||
|
||||
.alert-detail-card {
|
||||
background: $card;
|
||||
border-radius: $r-lg;
|
||||
padding: 24px;
|
||||
margin-bottom: 16px;
|
||||
box-shadow: $shadow-sm;
|
||||
|
||||
&__label {
|
||||
font-size: var(--tk-font-h2);
|
||||
color: $tx2;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useState, useCallback } from 'react';
|
||||
import { View, Text, ScrollView, Button } from '@tarojs/components';
|
||||
import { View, Text, Button } from '@tarojs/components';
|
||||
import Taro from '@tarojs/taro';
|
||||
import { usePageData } from '@/hooks/usePageData';
|
||||
import {
|
||||
@@ -7,6 +7,8 @@ import {
|
||||
type Alert,
|
||||
} from '@/services/doctor/alerts';
|
||||
import Loading from '@/components/Loading';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import ContentCard from '@/components/ui/ContentCard';
|
||||
import { useElderClass } from '../../../../hooks/useElderClass';
|
||||
import './index.scss';
|
||||
|
||||
@@ -91,9 +93,9 @@ export default function AlertDetail() {
|
||||
if (loading) return <Loading />;
|
||||
if (!alert) {
|
||||
return (
|
||||
<View className={`alert-detail-page ${modeClass}`}>
|
||||
<PageShell className={modeClass}>
|
||||
<Text>告警不存在</Text>
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -103,7 +105,7 @@ export default function AlertDetail() {
|
||||
const isAcknowledged = alert.status === 'acknowledged';
|
||||
|
||||
return (
|
||||
<ScrollView scrollY className={`alert-detail-page ${modeClass}`}>
|
||||
<PageShell className={modeClass}>
|
||||
{/* 顶部状态 */}
|
||||
<View className='alert-detail-header'>
|
||||
<View className='alert-detail-header__tags'>
|
||||
@@ -120,55 +122,55 @@ export default function AlertDetail() {
|
||||
</View>
|
||||
|
||||
{/* 告警信息 */}
|
||||
<View className='alert-detail-card'>
|
||||
<ContentCard>
|
||||
<Text className='alert-detail-card__label'>告警标题</Text>
|
||||
<Text className='alert-detail-card__value'>{alert.title}</Text>
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
<View className='alert-detail-card'>
|
||||
<ContentCard>
|
||||
<Text className='alert-detail-card__label'>患者 ID</Text>
|
||||
<Text className='alert-detail-card__value alert-detail-card__value--id'>
|
||||
{alert.patient_id ? `${alert.patient_id.slice(0, 8)}...` : '-'}
|
||||
</Text>
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
<View className='alert-detail-card'>
|
||||
<ContentCard>
|
||||
<Text className='alert-detail-card__label'>严重程度</Text>
|
||||
<Text className='alert-detail-card__value'>{severity.label}</Text>
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
{alert.detail && (
|
||||
<View className='alert-detail-card'>
|
||||
<ContentCard>
|
||||
<Text className='alert-detail-card__label'>告警详情</Text>
|
||||
<Text className='alert-detail-card__value alert-detail-card__value--detail'>
|
||||
{JSON.stringify(alert.detail, null, 2)}
|
||||
</Text>
|
||||
</View>
|
||||
</ContentCard>
|
||||
)}
|
||||
|
||||
{alert.acknowledged_by && (
|
||||
<View className='alert-detail-card'>
|
||||
<ContentCard>
|
||||
<Text className='alert-detail-card__label'>处理人</Text>
|
||||
<Text className='alert-detail-card__value'>{alert.acknowledged_by}</Text>
|
||||
</View>
|
||||
</ContentCard>
|
||||
)}
|
||||
|
||||
{alert.acknowledged_at && (
|
||||
<View className='alert-detail-card'>
|
||||
<ContentCard>
|
||||
<Text className='alert-detail-card__label'>确认时间</Text>
|
||||
<Text className='alert-detail-card__value'>
|
||||
{new Date(alert.acknowledged_at).toLocaleString('zh-CN')}
|
||||
</Text>
|
||||
</View>
|
||||
</ContentCard>
|
||||
)}
|
||||
|
||||
{alert.resolved_at && (
|
||||
<View className='alert-detail-card'>
|
||||
<ContentCard>
|
||||
<Text className='alert-detail-card__label'>恢复时间</Text>
|
||||
<Text className='alert-detail-card__value'>
|
||||
{new Date(alert.resolved_at).toLocaleString('zh-CN')}
|
||||
</Text>
|
||||
</View>
|
||||
</ContentCard>
|
||||
)}
|
||||
|
||||
{/* 操作按钮 */}
|
||||
@@ -203,6 +205,6 @@ export default function AlertDetail() {
|
||||
)}
|
||||
</View>
|
||||
)}
|
||||
</ScrollView>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,19 +1,12 @@
|
||||
@import '../../../../styles/variables.scss';
|
||||
@import '../../../../styles/mixins.scss';
|
||||
|
||||
.create-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding: 24px;
|
||||
padding-bottom: 200px;
|
||||
}
|
||||
// PageShell 已接管:min-height, background, padding
|
||||
// ContentCard 已接管:background, border-radius, padding, box-shadow
|
||||
|
||||
/* ─── 表单分组间距(ContentCard 外层补充) ─── */
|
||||
.section {
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
padding: 24px;
|
||||
margin-bottom: 16px;
|
||||
box-shadow: $shadow-sm;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { View, Text, Input, Textarea, Picker, ScrollView } from '@tarojs/components';
|
||||
import { View, Text, Input, Textarea, Picker } from '@tarojs/components';
|
||||
import Taro, { useRouter } from '@tarojs/taro';
|
||||
import {
|
||||
getDialysisRecord, updateDialysisRecord, createDialysisRecord,
|
||||
} from '@/services/doctor/dialysis';
|
||||
import Loading from '@/components/Loading';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import ContentCard from '@/components/ui/ContentCard';
|
||||
import { useElderClass } from '../../../../hooks/useElderClass';
|
||||
import { useSafeTimeout } from '@/hooks/useSafeTimeout';
|
||||
import './index.scss';
|
||||
@@ -173,8 +175,8 @@ export default function DialysisCreate() {
|
||||
);
|
||||
|
||||
return (
|
||||
<ScrollView scrollY className={`create-page ${modeClass}`}>
|
||||
<View className='section'>
|
||||
<PageShell safeBottom={false} className={modeClass}>
|
||||
<ContentCard className='section'>
|
||||
<Text className='section-title'>基本信息</Text>
|
||||
<View className='form-row'>
|
||||
<Text className='form-label'>透析日期</Text>
|
||||
@@ -208,16 +210,16 @@ export default function DialysisCreate() {
|
||||
</View>
|
||||
<InputField label='透析时长' field='dialysis_duration' placeholder='分钟' type='number' />
|
||||
<InputField label='血流速' field='blood_flow_rate' placeholder='ml/min' type='number' />
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
<View className='section'>
|
||||
<ContentCard className='section'>
|
||||
<Text className='section-title'>体重</Text>
|
||||
<InputField label='干体重' field='dry_weight' placeholder='kg' />
|
||||
<InputField label='透前体重' field='pre_weight' placeholder='kg' />
|
||||
<InputField label='透后体重' field='post_weight' placeholder='kg' />
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
<View className='section'>
|
||||
<ContentCard className='section'>
|
||||
<Text className='section-title'>血压与心率</Text>
|
||||
<InputField label='透前收缩压' field='pre_bp_systolic' placeholder='mmHg' type='number' />
|
||||
<InputField label='透前舒张压' field='pre_bp_diastolic' placeholder='mmHg' type='number' />
|
||||
@@ -225,9 +227,9 @@ export default function DialysisCreate() {
|
||||
<InputField label='透后舒张压' field='post_bp_diastolic' placeholder='mmHg' type='number' />
|
||||
<InputField label='透前心率' field='pre_heart_rate' placeholder='bpm' type='number' />
|
||||
<InputField label='透后心率' field='post_heart_rate' placeholder='bpm' type='number' />
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
<View className='section'>
|
||||
<ContentCard className='section'>
|
||||
<Text className='section-title'>超滤与备注</Text>
|
||||
<InputField label='超滤量' field='ultrafiltration_volume' placeholder='ml' type='number' />
|
||||
<View className='form-row form-row--textarea'>
|
||||
@@ -240,11 +242,11 @@ export default function DialysisCreate() {
|
||||
maxlength={500}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
<View className={`submit-btn ${submitting ? 'submit-btn--disabled' : ''}`} onClick={handleSubmit}>
|
||||
<Text className='submit-btn__text'>{submitting ? '提交中...' : isEdit ? '更新记录' : '创建记录'}</Text>
|
||||
</View>
|
||||
</ScrollView>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,21 +1,6 @@
|
||||
@import '../../../../styles/variables.scss';
|
||||
@import '../../../../styles/mixins.scss';
|
||||
|
||||
.dialysis-detail {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding: 24px;
|
||||
padding-bottom: 200px;
|
||||
}
|
||||
|
||||
.section {
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
padding: 24px;
|
||||
margin-bottom: 16px;
|
||||
box-shadow: $shadow-sm;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: var(--tk-font-body-lg);
|
||||
font-weight: bold;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useState, useCallback } from 'react';
|
||||
import { View, Text, ScrollView } from '@tarojs/components';
|
||||
import { View, Text } from '@tarojs/components';
|
||||
import Taro, { useRouter } from '@tarojs/taro';
|
||||
import { usePageData } from '@/hooks/usePageData';
|
||||
import {
|
||||
@@ -8,6 +8,8 @@ import {
|
||||
type DialysisRecord,
|
||||
} from '@/services/doctor/dialysis';
|
||||
import Loading from '@/components/Loading';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import ContentCard from '@/components/ui/ContentCard';
|
||||
import { useElderClass } from '../../../../hooks/useElderClass';
|
||||
import { useSafeTimeout } from '@/hooks/useSafeTimeout';
|
||||
import './index.scss';
|
||||
@@ -93,15 +95,15 @@ export default function DialysisDetail() {
|
||||
};
|
||||
|
||||
if (loading) return <Loading />;
|
||||
if (!record) return <View className={`error-text ${modeClass}`}><Text>记录加载失败</Text></View>;
|
||||
if (!record) return <PageShell className={modeClass}><View className='error-text'><Text>记录加载失败</Text></View></PageShell>;
|
||||
|
||||
const canComplete = record.status === 'draft';
|
||||
const canReview = record.status === 'completed';
|
||||
|
||||
return (
|
||||
<ScrollView scrollY className={`dialysis-detail ${modeClass}`}>
|
||||
<PageShell className={modeClass}>
|
||||
{/* 状态头部 */}
|
||||
<View className='section'>
|
||||
<ContentCard>
|
||||
<View className='record-header'>
|
||||
<Text className='record-header__title'>{record.dialysis_date}</Text>
|
||||
<Text className={`record-header__status record-header__status--${record.status}`}>
|
||||
@@ -112,10 +114,10 @@ export default function DialysisDetail() {
|
||||
{(record.dialysis_type === 'HD' ? '血液透析' : record.dialysis_type === 'HDF' ? '血液透析滤过' : record.dialysis_type === 'HF' ? '血液滤过' : record.dialysis_type)}
|
||||
</Text>
|
||||
{record.reviewed_at && <Text className='review-info'>审核于 {record.reviewed_at}</Text>}
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
{/* 基本信息 */}
|
||||
<View className='section'>
|
||||
<ContentCard>
|
||||
<Text className='section-title'>基本信息</Text>
|
||||
<Row label='透析日期' value={record.dialysis_date} />
|
||||
<Row label='开始时间' value={record.start_time} />
|
||||
@@ -123,10 +125,10 @@ export default function DialysisDetail() {
|
||||
<Row label='透析时长' value={record.dialysis_duration} unit=' 分钟' />
|
||||
<Row label='血流速' value={record.blood_flow_rate} unit=' ml/min' />
|
||||
<Row label='超滤量' value={record.ultrafiltration_volume} unit=' ml' />
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
{/* 体重与血压 */}
|
||||
<View className='section'>
|
||||
<ContentCard>
|
||||
<Text className='section-title'>体重与血压</Text>
|
||||
<Row label='干体重' value={record.dry_weight} unit=' kg' />
|
||||
<Row label='透前体重' value={record.pre_weight} unit=' kg' />
|
||||
@@ -139,17 +141,17 @@ export default function DialysisDetail() {
|
||||
)}
|
||||
<Row label='透前心率' value={record.pre_heart_rate} unit=' bpm' />
|
||||
<Row label='透后心率' value={record.post_heart_rate} unit=' bpm' />
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
{/* 症状与并发症 */}
|
||||
{(record.symptoms || record.complication_notes) && (
|
||||
<View className='section'>
|
||||
<ContentCard>
|
||||
<Text className='section-title'>症状与并发症</Text>
|
||||
{record.symptoms && (
|
||||
<Row label='症状' value={JSON.stringify(record.symptoms)} />
|
||||
)}
|
||||
<Row label='并发症备注' value={record.complication_notes} />
|
||||
</View>
|
||||
</ContentCard>
|
||||
)}
|
||||
|
||||
{/* 操作按钮 */}
|
||||
@@ -175,6 +177,6 @@ export default function DialysisDetail() {
|
||||
<Text className='action-btn__text'>删除</Text>
|
||||
</View>
|
||||
</View>
|
||||
</ScrollView>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,19 +1,12 @@
|
||||
@import '../../../../styles/variables.scss';
|
||||
@import '../../../../styles/mixins.scss';
|
||||
|
||||
.create-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding: 24px;
|
||||
padding-bottom: 200px;
|
||||
}
|
||||
// PageShell 已接管:min-height, background, padding
|
||||
// ContentCard 已接管:background, border-radius, padding, box-shadow
|
||||
|
||||
/* ─── 表单分组间距(ContentCard 外层补充) ─── */
|
||||
.section {
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
padding: 24px;
|
||||
margin-bottom: 16px;
|
||||
box-shadow: $shadow-sm;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { useState } from 'react';
|
||||
import { View, Text, Input, Textarea, Picker, ScrollView } from '@tarojs/components';
|
||||
import { View, Text, Input, Textarea, Picker } from '@tarojs/components';
|
||||
import Taro, { useRouter } from '@tarojs/taro';
|
||||
import { createDialysisPrescription } from '@/services/doctor/dialysis';
|
||||
import Loading from '@/components/Loading';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import ContentCard from '@/components/ui/ContentCard';
|
||||
import { useElderClass } from '../../../../hooks/useElderClass';
|
||||
import { useSafeTimeout } from '@/hooks/useSafeTimeout';
|
||||
import './index.scss';
|
||||
@@ -118,31 +120,31 @@ export default function PrescriptionCreate() {
|
||||
);
|
||||
|
||||
return (
|
||||
<ScrollView scrollY className={`create-page ${modeClass}`}>
|
||||
<PageShell safeBottom={false} className={modeClass}>
|
||||
{/* 透析器 */}
|
||||
<View className='section'>
|
||||
<ContentCard className='section'>
|
||||
<Text className='section-title'>透析器</Text>
|
||||
<InputField label='透析器型号' field='dialyzer_model' placeholder='请输入型号' type='text' />
|
||||
<InputField label='膜面积' field='membrane_area' placeholder='m²' />
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
{/* 透析液 */}
|
||||
<View className='section'>
|
||||
<ContentCard className='section'>
|
||||
<Text className='section-title'>透析液配比</Text>
|
||||
<InputField label='钾浓度' field='dialysate_potassium' placeholder='mmol/L' />
|
||||
<InputField label='钙浓度' field='dialysate_calcium' placeholder='mmol/L' />
|
||||
<InputField label='碳酸氢盐' field='dialysate_bicarbonate' placeholder='mmol/L' />
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
{/* 抗凝 */}
|
||||
<View className='section'>
|
||||
<ContentCard className='section'>
|
||||
<Text className='section-title'>抗凝方案</Text>
|
||||
<InputField label='抗凝类型' field='anticoagulation_type' placeholder='请输入' type='text' />
|
||||
<InputField label='抗凝剂量' field='anticoagulation_dose' placeholder='请输入' type='text' />
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
{/* 参数 */}
|
||||
<View className='section'>
|
||||
<ContentCard className='section'>
|
||||
<Text className='section-title'>参数设置</Text>
|
||||
<InputField label='目标超滤量' field='target_ultrafiltration_ml' placeholder='ml' type='number' />
|
||||
<InputField label='目标干体重' field='target_dry_weight' placeholder='kg' />
|
||||
@@ -150,17 +152,17 @@ export default function PrescriptionCreate() {
|
||||
<InputField label='透析液流量' field='dialysate_flow_rate' placeholder='ml/min' type='number' />
|
||||
<InputField label='每周频次' field='frequency_per_week' placeholder='次/周' type='number' />
|
||||
<InputField label='每次时长' field='duration_minutes' placeholder='分钟' type='number' />
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
{/* 血管通路 */}
|
||||
<View className='section'>
|
||||
<ContentCard className='section'>
|
||||
<Text className='section-title'>血管通路</Text>
|
||||
<InputField label='通路类型' field='vascular_access_type' placeholder='请输入' type='text' />
|
||||
<InputField label='通路位置' field='vascular_access_location' placeholder='请输入' type='text' />
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
{/* 生效日期 */}
|
||||
<View className='section'>
|
||||
<ContentCard className='section'>
|
||||
<Text className='section-title'>生效日期</Text>
|
||||
<View className='form-row'>
|
||||
<Text className='form-label'>生效日期</Text>
|
||||
@@ -178,10 +180,10 @@ export default function PrescriptionCreate() {
|
||||
</Text>
|
||||
</Picker>
|
||||
</View>
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
{/* 备注 */}
|
||||
<View className='section'>
|
||||
<ContentCard className='section'>
|
||||
<Text className='section-title'>备注</Text>
|
||||
<Textarea
|
||||
className='form-textarea'
|
||||
@@ -190,11 +192,11 @@ export default function PrescriptionCreate() {
|
||||
onInput={(e) => updateField('notes', e.detail.value)}
|
||||
maxlength={500}
|
||||
/>
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
<View className={`submit-btn ${submitting ? 'submit-btn--disabled' : ''}`} onClick={handleSubmit}>
|
||||
<Text className='submit-btn__text'>{submitting ? '提交中...' : '创建处方'}</Text>
|
||||
</View>
|
||||
</ScrollView>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,21 +1,6 @@
|
||||
@import '../../../../styles/variables.scss';
|
||||
@import '../../../../styles/mixins.scss';
|
||||
|
||||
.prescription-detail {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding: 24px;
|
||||
padding-bottom: 200px;
|
||||
}
|
||||
|
||||
.section {
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
padding: 24px;
|
||||
margin-bottom: 16px;
|
||||
box-shadow: $shadow-sm;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: var(--tk-font-body-lg);
|
||||
font-weight: bold;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useState, useCallback } from 'react';
|
||||
import { View, Text, ScrollView } from '@tarojs/components';
|
||||
import { View, Text } from '@tarojs/components';
|
||||
import Taro, { useRouter } from '@tarojs/taro';
|
||||
import { usePageData } from '@/hooks/usePageData';
|
||||
import {
|
||||
@@ -7,6 +7,8 @@ import {
|
||||
type DialysisPrescription,
|
||||
} from '@/services/doctor/dialysis';
|
||||
import Loading from '@/components/Loading';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import ContentCard from '@/components/ui/ContentCard';
|
||||
import { useElderClass } from '../../../../hooks/useElderClass';
|
||||
import { useSafeTimeout } from '@/hooks/useSafeTimeout';
|
||||
import './index.scss';
|
||||
@@ -83,12 +85,12 @@ export default function PrescriptionDetail() {
|
||||
};
|
||||
|
||||
if (loading) return <Loading />;
|
||||
if (!rx) return <View className={`error-text ${modeClass}`}><Text>处方加载失败</Text></View>;
|
||||
if (!rx) return <PageShell className={modeClass}><View className='error-text'><Text>处方加载失败</Text></View></PageShell>;
|
||||
|
||||
return (
|
||||
<ScrollView scrollY className={`prescription-detail ${modeClass}`}>
|
||||
<PageShell className={modeClass}>
|
||||
{/* 状态头部 */}
|
||||
<View className='section'>
|
||||
<ContentCard>
|
||||
<View className='rx-header'>
|
||||
<Text className='rx-header__title'>{rx.dialyzer_model || '透析处方'}</Text>
|
||||
<Text className={`rx-header__status rx-header__status--${rx.status}`}>
|
||||
@@ -98,10 +100,10 @@ export default function PrescriptionDetail() {
|
||||
{(rx.effective_from || rx.effective_to) && (
|
||||
<Text className='rx-sub'>{rx.effective_from || '...'} ~ {rx.effective_to || '...'}</Text>
|
||||
)}
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
{/* 基本参数 */}
|
||||
<View className='section'>
|
||||
<ContentCard>
|
||||
<Text className='section-title'>基本参数</Text>
|
||||
<Row label='透析器型号' value={rx.dialyzer_model} />
|
||||
<Row label='膜面积' value={rx.membrane_area != null ? `${rx.membrane_area}` : null} unit=' m²' />
|
||||
@@ -109,47 +111,47 @@ export default function PrescriptionDetail() {
|
||||
<Row label='透析液流量' value={rx.dialysate_flow_rate} unit=' ml/min' />
|
||||
<Row label='频率' value={rx.frequency_per_week != null ? `${rx.frequency_per_week} 次/周` : null} />
|
||||
<Row label='每次时长' value={rx.duration_minutes} unit=' 分钟' />
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
{/* 透析液配比 */}
|
||||
<View className='section'>
|
||||
<ContentCard>
|
||||
<Text className='section-title'>透析液配比</Text>
|
||||
<Row label='钾浓度' value={rx.dialysate_potassium} unit=' mmol/L' />
|
||||
<Row label='钙浓度' value={rx.dialysate_calcium} unit=' mmol/L' />
|
||||
<Row label='碳酸氢盐' value={rx.dialysate_bicarbonate} unit=' mmol/L' />
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
{/* 抗凝方案 */}
|
||||
<View className='section'>
|
||||
<ContentCard>
|
||||
<Text className='section-title'>抗凝方案</Text>
|
||||
<Row label='抗凝类型' value={rx.anticoagulation_type} />
|
||||
<Row label='抗凝剂量' value={rx.anticoagulation_dose} />
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
{/* 血管通路 */}
|
||||
{(rx.vascular_access_type || rx.vascular_access_location) && (
|
||||
<View className='section'>
|
||||
<ContentCard>
|
||||
<Text className='section-title'>血管通路</Text>
|
||||
<Row label='通路类型' value={rx.vascular_access_type} />
|
||||
<Row label='通路位置' value={rx.vascular_access_location} />
|
||||
</View>
|
||||
</ContentCard>
|
||||
)}
|
||||
|
||||
{/* 超滤目标 */}
|
||||
{(rx.target_ultrafiltration_ml != null || rx.target_dry_weight != null) && (
|
||||
<View className='section'>
|
||||
<ContentCard>
|
||||
<Text className='section-title'>超滤目标</Text>
|
||||
<Row label='目标超滤量' value={rx.target_ultrafiltration_ml} unit=' ml' />
|
||||
<Row label='目标干体重' value={rx.target_dry_weight} unit=' kg' />
|
||||
</View>
|
||||
</ContentCard>
|
||||
)}
|
||||
|
||||
{/* 备注 */}
|
||||
{rx.notes && (
|
||||
<View className='section'>
|
||||
<ContentCard>
|
||||
<Text className='section-title'>备注</Text>
|
||||
<Text className='notes-text'>{rx.notes}</Text>
|
||||
</View>
|
||||
</ContentCard>
|
||||
)}
|
||||
|
||||
{/* 操作按钮 */}
|
||||
@@ -163,6 +165,6 @@ export default function PrescriptionDetail() {
|
||||
<Text className='action-btn__text'>删除</Text>
|
||||
</View>
|
||||
</View>
|
||||
</ScrollView>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,21 +1,6 @@
|
||||
@import '../../../../styles/variables.scss';
|
||||
@import '../../../../styles/mixins.scss';
|
||||
|
||||
.report-detail {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding: 24px;
|
||||
padding-bottom: 120px;
|
||||
}
|
||||
|
||||
.section {
|
||||
background: $card;
|
||||
border-radius: $r-lg;
|
||||
padding: 28px;
|
||||
margin-bottom: 20px;
|
||||
box-shadow: $shadow-sm;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
@include section-title;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { useState, useCallback } from 'react';
|
||||
import { View, Text, Textarea, ScrollView } from '@tarojs/components';
|
||||
import { View, Text, Textarea } from '@tarojs/components';
|
||||
import Taro, { useRouter } from '@tarojs/taro';
|
||||
import { usePageData } from '@/hooks/usePageData';
|
||||
import { getLabReport, reviewLabReport, type LabReportDetail } from '@/services/doctor/labReport';
|
||||
import Loading from '@/components/Loading';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import ContentCard from '@/components/ui/ContentCard';
|
||||
import { useElderClass } from '../../../../hooks/useElderClass';
|
||||
import './index.scss';
|
||||
|
||||
@@ -53,12 +55,12 @@ export default function ReportDetail() {
|
||||
const formatDate = (d: string) => new Date(d).toLocaleDateString('zh-CN');
|
||||
|
||||
if (loading) return <Loading />;
|
||||
if (!report) return <View className={`error-text ${modeClass}`}><Text>报告加载失败</Text></View>;
|
||||
if (!report) return <PageShell className={modeClass}><View className='error-text'><Text>报告加载失败</Text></View></PageShell>;
|
||||
|
||||
return (
|
||||
<ScrollView scrollY className={`report-detail ${modeClass}`}>
|
||||
<PageShell className={modeClass}>
|
||||
{/* 基本信息 */}
|
||||
<View className='section'>
|
||||
<ContentCard>
|
||||
<View className='report-header'>
|
||||
<Text className='report-header__type'>{report.report_type}</Text>
|
||||
<Text className={`report-header__status report-header__status--${report.status}`}>
|
||||
@@ -69,11 +71,11 @@ export default function ReportDetail() {
|
||||
{report.reviewed_at && (
|
||||
<Text className='review-info'>审核于: {formatDate(report.reviewed_at)}</Text>
|
||||
)}
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
{/* 指标列表 */}
|
||||
{report.items && report.items.length > 0 && (
|
||||
<View className='section'>
|
||||
<ContentCard>
|
||||
<Text className='section-title'>检验指标</Text>
|
||||
<View className='indicator-table'>
|
||||
<View className='indicator-row indicator-row--header'>
|
||||
@@ -102,11 +104,11 @@ export default function ReportDetail() {
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
</ContentCard>
|
||||
)}
|
||||
|
||||
{/* 医生注释 */}
|
||||
<View className='section'>
|
||||
<ContentCard>
|
||||
<Text className='section-title'>医生注释</Text>
|
||||
{report.status === 'reviewed' && report.doctor_notes ? (
|
||||
<View className='notes-display'>
|
||||
@@ -129,7 +131,7 @@ export default function ReportDetail() {
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</ScrollView>
|
||||
</ContentCard>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
@import '../../../styles/variables.scss';
|
||||
@import '../../../styles/mixins.scss';
|
||||
@import '../../styles/variables.scss';
|
||||
@import '../../styles/mixins.scss';
|
||||
|
||||
.action-inbox-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
}
|
||||
// PageShell 已接管:min-height, background
|
||||
// ContentCard 已接管:inbox-card 背景/圆角/阴影/触摸反馈
|
||||
|
||||
.inbox-list {
|
||||
height: calc(100vh - 50px);
|
||||
@@ -12,11 +10,7 @@
|
||||
}
|
||||
|
||||
.inbox-card {
|
||||
background: $card;
|
||||
border-radius: $r-sm;
|
||||
padding: 14px 16px;
|
||||
margin-bottom: 10px;
|
||||
box-shadow: $shadow-sm;
|
||||
|
||||
.inbox-card-header {
|
||||
display: flex;
|
||||
|
||||
@@ -13,6 +13,8 @@ import Loading from '@/components/Loading';
|
||||
import ErrorState from '@/components/ErrorState';
|
||||
import EmptyState from '@/components/EmptyState';
|
||||
import SegmentTabs from '@/components/SegmentTabs';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import ContentCard from '@/components/ui/ContentCard';
|
||||
import { useElderClass } from '../../../hooks/useElderClass';
|
||||
import './index.scss';
|
||||
|
||||
@@ -119,7 +121,7 @@ export default function ActionInboxPage() {
|
||||
};
|
||||
|
||||
return (
|
||||
<View className={`action-inbox-page ${modeClass}`}>
|
||||
<PageShell padding="none" className={modeClass}>
|
||||
<SegmentTabs tabs={STATUS_TABS} activeKey={activeTab} onChange={handleTabChange} variant="underline" />
|
||||
|
||||
{error ? (
|
||||
@@ -129,10 +131,11 @@ export default function ActionInboxPage() {
|
||||
) : (
|
||||
<ScrollView scrollY className="inbox-list">
|
||||
{items.map((item) => (
|
||||
<View
|
||||
<ContentCard
|
||||
key={item.id}
|
||||
className="inbox-card"
|
||||
onClick={() => handleItemClick(item)}
|
||||
activeFeedback="opacity"
|
||||
onPress={() => handleItemClick(item)}
|
||||
>
|
||||
<View className="inbox-card-header">
|
||||
<Text
|
||||
@@ -146,7 +149,7 @@ export default function ActionInboxPage() {
|
||||
{item.patient_name} ·{' '}
|
||||
{new Date(item.created_at).toLocaleDateString('zh-CN')}
|
||||
</Text>
|
||||
</View>
|
||||
</ContentCard>
|
||||
))}
|
||||
{loading && <Loading />}
|
||||
{!loading && items.length >= total && total > 0 && (
|
||||
@@ -208,6 +211,6 @@ export default function ActionInboxPage() {
|
||||
)}
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,21 +1,6 @@
|
||||
@import '../../../../styles/variables.scss';
|
||||
@import '../../../../styles/mixins.scss';
|
||||
|
||||
.followup-detail {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding: 24px;
|
||||
padding-bottom: 120px;
|
||||
}
|
||||
|
||||
.section {
|
||||
background: $card;
|
||||
border-radius: $r-lg;
|
||||
padding: 28px;
|
||||
margin-bottom: 20px;
|
||||
box-shadow: $shadow-sm;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
@include section-title;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useState, useCallback } from 'react';
|
||||
import { View, Text, Textarea, ScrollView, Picker } from '@tarojs/components';
|
||||
import { View, Text, Textarea, Picker } from '@tarojs/components';
|
||||
import Taro, { useRouter } from '@tarojs/taro';
|
||||
import { usePageData } from '@/hooks/usePageData';
|
||||
import {
|
||||
@@ -8,6 +8,8 @@ import {
|
||||
type FollowUpTask, type FollowUpRecord,
|
||||
} from '@/services/doctor/followup';
|
||||
import Loading from '@/components/Loading';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import ContentCard from '@/components/ui/ContentCard';
|
||||
import { useElderClass } from '../../../../hooks/useElderClass';
|
||||
import './index.scss';
|
||||
|
||||
@@ -93,13 +95,13 @@ export default function FollowUpDetail() {
|
||||
const formatDate = (d: string) => new Date(d).toLocaleDateString('zh-CN');
|
||||
|
||||
if (loading) return <Loading />;
|
||||
if (!task) return <View className={`error-text ${modeClass}`}><Text>任务加载失败</Text></View>;
|
||||
if (!task) return <PageShell className={modeClass}><View className='error-text'><Text>任务加载失败</Text></View></PageShell>;
|
||||
|
||||
const canSubmit = task.status === 'in_progress' || task.status === 'pending' || task.status === 'overdue';
|
||||
|
||||
return (
|
||||
<ScrollView scrollY className={`followup-detail ${modeClass}`}>
|
||||
<View className='section'>
|
||||
<PageShell className={modeClass}>
|
||||
<ContentCard>
|
||||
<View className='task-header'>
|
||||
<Text className='task-header__title'>随访详情</Text>
|
||||
<Text className={`task-header__status task-header__status--${task.status}`}>
|
||||
@@ -126,11 +128,11 @@ export default function FollowUpDetail() {
|
||||
<Text className='task-template__text'>{task.content_template}</Text>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
{/* 历史记录 */}
|
||||
{records.length > 0 && (
|
||||
<View className='section'>
|
||||
<ContentCard>
|
||||
<Text className='section-title'>历史记录</Text>
|
||||
{records.map((r) => (
|
||||
<View key={r.id} className='record-item'>
|
||||
@@ -140,12 +142,12 @@ export default function FollowUpDetail() {
|
||||
{r.medical_advice && <Text className='record-item__text'>医嘱: {r.medical_advice}</Text>}
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
</ContentCard>
|
||||
)}
|
||||
|
||||
{/* 填写表单 */}
|
||||
{canSubmit && (
|
||||
<View className='section'>
|
||||
<ContentCard>
|
||||
<Text className='section-title'>记录随访</Text>
|
||||
{(task.status === 'pending' || task.status === 'overdue') && (
|
||||
<View className='start-btn' onClick={handleStartTask}>
|
||||
@@ -193,8 +195,8 @@ export default function FollowUpDetail() {
|
||||
<View className={`submit-btn ${submitting ? 'submit-btn--disabled' : ''}`} onClick={handleSubmit}>
|
||||
<Text className='submit-btn__text'>{submitting ? '提交中...' : '提交记录'}</Text>
|
||||
</View>
|
||||
</View>
|
||||
</ContentCard>
|
||||
)}
|
||||
</ScrollView>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
@import '../../styles/variables.scss';
|
||||
@import '../../styles/mixins.scss';
|
||||
|
||||
// PageShell 已接管:min-height, background, padding
|
||||
|
||||
.doctor-home {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding: 32px;
|
||||
padding-bottom: calc(160px + env(safe-area-inset-bottom));
|
||||
|
||||
&__header {
|
||||
margin-bottom: 40px;
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { useState, useMemo, useCallback } from 'react';
|
||||
import { View, Text, Input, ScrollView } from '@tarojs/components';
|
||||
import { View, Text, Input } from '@tarojs/components';
|
||||
import Taro from '@tarojs/taro';
|
||||
import { useAuthStore } from '@/stores/auth';
|
||||
import { useElderClass } from '../../hooks/useElderClass';
|
||||
import { usePageData } from '@/hooks/usePageData';
|
||||
import { getDashboard, type DoctorDashboard } from '@/services/doctor/dashboard';
|
||||
import Loading from '@/components/Loading';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import './index.scss';
|
||||
|
||||
interface CardConfig {
|
||||
@@ -107,7 +108,7 @@ export default function DoctorHome() {
|
||||
if (loading) return <Loading />;
|
||||
|
||||
return (
|
||||
<ScrollView scrollY className={`doctor-home ${modeClass}`}>
|
||||
<PageShell safeBottom={false} className={`doctor-home ${modeClass}`}>
|
||||
<View className='doctor-home__header'>
|
||||
<Text className='doctor-home__title'>医护工作台</Text>
|
||||
<Text className='doctor-home__greeting'>
|
||||
@@ -192,6 +193,6 @@ export default function DoctorHome() {
|
||||
<View className='doctor-home__footer'>
|
||||
<Text className='doctor-home__logout' onClick={handleLogout}>退出登录</Text>
|
||||
</View>
|
||||
</ScrollView>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,21 +1,6 @@
|
||||
@import '../../../../styles/variables.scss';
|
||||
@import '../../../../styles/mixins.scss';
|
||||
|
||||
.patient-detail {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding: 24px;
|
||||
padding-bottom: 120px;
|
||||
}
|
||||
|
||||
.section {
|
||||
background: $card;
|
||||
border-radius: $r-lg;
|
||||
padding: 28px;
|
||||
margin-bottom: 20px;
|
||||
box-shadow: $shadow-sm;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
@include section-title;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { useState, useCallback } from 'react';
|
||||
import { View, Text, ScrollView } from '@tarojs/components';
|
||||
import { View, Text } from '@tarojs/components';
|
||||
import Taro, { useRouter } from '@tarojs/taro';
|
||||
import { usePageData } from '@/hooks/usePageData';
|
||||
import { getPatient, getHealthSummary, type PatientDetail, type HealthSummary } from '@/services/doctor/patient';
|
||||
import Loading from '@/components/Loading';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import ContentCard from '@/components/ui/ContentCard';
|
||||
import { useElderClass } from '../../../../hooks/useElderClass';
|
||||
import './index.scss';
|
||||
|
||||
@@ -42,12 +44,12 @@ export default function PatientDetail() {
|
||||
};
|
||||
|
||||
if (loading) return <Loading />;
|
||||
if (!patient) return <View className={`error-text ${modeClass}`}><Text>患者信息加载失败</Text></View>;
|
||||
if (!patient) return <PageShell className={modeClass}><View className='error-text'><Text>患者信息加载失败</Text></View></PageShell>;
|
||||
|
||||
return (
|
||||
<ScrollView scrollY className={`patient-detail ${modeClass}`}>
|
||||
<PageShell className={modeClass}>
|
||||
{/* 基本信息 */}
|
||||
<View className='section'>
|
||||
<ContentCard>
|
||||
<View className='section-header'>
|
||||
<Text className='section-title'>基本信息</Text>
|
||||
</View>
|
||||
@@ -57,11 +59,11 @@ export default function PatientDetail() {
|
||||
<View className='info-item'><Text className='info-label'>年龄</Text><Text className='info-value'>{calcAge(patient.birth_date)}岁</Text></View>
|
||||
{patient.blood_type && <View className='info-item'><Text className='info-label'>血型</Text><Text className='info-value'>{patient.blood_type}</Text></View>}
|
||||
</View>
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
{/* 医疗信息 */}
|
||||
{(patient.allergy_history || patient.medical_history_summary) && (
|
||||
<View className='section'>
|
||||
<ContentCard>
|
||||
<Text className='section-title'>医疗信息</Text>
|
||||
{patient.allergy_history && (
|
||||
<View className='warning-card'>
|
||||
@@ -75,12 +77,12 @@ export default function PatientDetail() {
|
||||
<Text className='info-block-text'>{patient.medical_history_summary}</Text>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</ContentCard>
|
||||
)}
|
||||
|
||||
{/* 健康摘要 */}
|
||||
{summary && (
|
||||
<View className='section'>
|
||||
<ContentCard>
|
||||
<Text className='section-title'>健康概览</Text>
|
||||
{summary.latest_vital_signs && (
|
||||
<View className='vitals-grid'>
|
||||
@@ -116,12 +118,12 @@ export default function PatientDetail() {
|
||||
<Text className='stat-value stat-value--warn'>{summary.pending_follow_ups} 项</Text>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</ContentCard>
|
||||
)}
|
||||
|
||||
{/* 近期化验 */}
|
||||
{summary?.latest_lab_report && (
|
||||
<View className='section'>
|
||||
<ContentCard>
|
||||
<Text className='section-title'>近期化验</Text>
|
||||
<View
|
||||
className='lab-item'
|
||||
@@ -135,11 +137,11 @@ export default function PatientDetail() {
|
||||
<Text className='lab-item__abnormal'>{summary.latest_lab_report.abnormal_count} 项异常</Text>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
</ContentCard>
|
||||
)}
|
||||
|
||||
{/* 快捷操作 */}
|
||||
<View className='section'>
|
||||
<ContentCard>
|
||||
<Text className='section-title'>操作</Text>
|
||||
<View className='action-buttons'>
|
||||
<View className='action-btn' onClick={() => Taro.navigateTo({ url: `/pages/pkg-doctor-clinical/report/index?patientId=${patientId}` })}>
|
||||
@@ -149,7 +151,7 @@ export default function PatientDetail() {
|
||||
<Text>随访记录</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</ScrollView>
|
||||
</ContentCard>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
@import '../../../styles/variables.scss';
|
||||
@import '../../../styles/mixins.scss';
|
||||
|
||||
.alerts-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
}
|
||||
// PageShell 已接管:min-height, background, safe-bottom
|
||||
// ContentCard 已接管:alert-card 背景/圆角/阴影
|
||||
|
||||
.alerts-tabs {
|
||||
display: flex;
|
||||
@@ -39,11 +36,7 @@
|
||||
}
|
||||
|
||||
.alert-card {
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
padding: 24px;
|
||||
margin-bottom: 16px;
|
||||
box-shadow: $shadow-sm;
|
||||
}
|
||||
|
||||
.alert-header {
|
||||
|
||||
@@ -8,6 +8,8 @@ import Loading from '@/components/Loading';
|
||||
import ErrorState from '@/components/ErrorState';
|
||||
import EmptyState from '@/components/EmptyState';
|
||||
import SegmentTabs from '@/components/SegmentTabs';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import ContentCard from '@/components/ui/ContentCard';
|
||||
import { useElderClass } from '../../../hooks/useElderClass';
|
||||
import './index.scss';
|
||||
|
||||
@@ -79,23 +81,23 @@ export default function PatientAlerts() {
|
||||
|
||||
if (!currentPatient) {
|
||||
return (
|
||||
<View className={`alerts-page ${modeClass}`}>
|
||||
<PageShell padding="none" className={modeClass}>
|
||||
<ErrorState text='请先完善个人档案' onRetry={() => Taro.navigateTo({ url: '/pages/pkg-profile/family-add/index' })} />
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<View className={`alerts-page ${modeClass}`}>
|
||||
<PageShell padding="none" className={modeClass}>
|
||||
<SegmentTabs tabs={STATUS_TABS} activeKey={status} onChange={handleTabChange} variant="pill" />
|
||||
<ErrorState onRetry={() => fetchAlerts(1, status, true)} />
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<View className={`alerts-page ${modeClass}`}>
|
||||
<PageShell padding="none" className={modeClass}>
|
||||
<SegmentTabs tabs={STATUS_TABS} activeKey={status} onChange={handleTabChange} variant="pill" />
|
||||
|
||||
{alerts.length === 0 && !loading ? (
|
||||
@@ -105,7 +107,7 @@ export default function PatientAlerts() {
|
||||
{alerts.map((item) => {
|
||||
const sev = SEVERITY_MAP[item.severity] || SEVERITY_MAP.warning;
|
||||
return (
|
||||
<View className='alert-card' key={item.id}>
|
||||
<ContentCard className='alert-card' key={item.id}>
|
||||
<View className='alert-header'>
|
||||
<View className={`alert-badge ${sev.className}`}>
|
||||
<Text className='alert-badge-text'>{sev.label}</Text>
|
||||
@@ -115,7 +117,7 @@ export default function PatientAlerts() {
|
||||
</Text>
|
||||
</View>
|
||||
<Text className='alert-title'>{item.title}</Text>
|
||||
</View>
|
||||
</ContentCard>
|
||||
);
|
||||
})}
|
||||
{loading && <Loading />}
|
||||
@@ -124,6 +126,6 @@ export default function PatientAlerts() {
|
||||
)}
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
@import '../../../styles/variables.scss';
|
||||
@import '../../../styles/mixins.scss';
|
||||
|
||||
.dm-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding: 0 0 60px;
|
||||
}
|
||||
// PageShell 已接管:min-height, background
|
||||
// ContentCard 已接管:dm-card/dm-group 背景/圆角/阴影
|
||||
|
||||
/* ── hero ── */
|
||||
.dm-hero {
|
||||
@@ -44,10 +41,6 @@
|
||||
|
||||
/* ── card (standalone, used for date picker) ── */
|
||||
.dm-card {
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
box-shadow: $shadow-md;
|
||||
padding: 28px;
|
||||
margin: 0 24px 20px;
|
||||
}
|
||||
|
||||
@@ -98,9 +91,6 @@
|
||||
|
||||
/* ── collapsible group ── */
|
||||
.dm-group {
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
box-shadow: $shadow-md;
|
||||
margin: 0 24px 20px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ import { clearRequestCache } from '@/services/request';
|
||||
import { trackEvent } from '@/services/analytics';
|
||||
import { useSafeTimeout } from '@/hooks/useSafeTimeout';
|
||||
import { useElderClass } from '@/hooks/useElderClass';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import ContentCard from '@/components/ui/ContentCard';
|
||||
import {
|
||||
BP_RANGE, WEIGHT_RANGE, SUGAR_RANGE, VOLUME_RANGE,
|
||||
checkAbnormal, formatDate, FIELD_LABELS,
|
||||
@@ -218,7 +220,7 @@ export default function DailyMonitoring() {
|
||||
const bloodSugarAbnormal = checkAbnormal(bloodSugar, 'bloodSugar');
|
||||
|
||||
return (
|
||||
<View className={`dm-page ${modeClass}`}>
|
||||
<PageShell padding="none" safeBottom className={modeClass}>
|
||||
{/* 页面标题 */}
|
||||
<View className='dm-hero'>
|
||||
<View className='dm-hero-icon'>
|
||||
@@ -229,7 +231,7 @@ export default function DailyMonitoring() {
|
||||
</View>
|
||||
|
||||
{/* 日期选择 (standalone card) */}
|
||||
<View className='dm-card'>
|
||||
<ContentCard className='dm-card'>
|
||||
<View className='dm-card-header'>
|
||||
<Text className='dm-card-title'>记录日期</Text>
|
||||
{isToday && (
|
||||
@@ -247,10 +249,10 @@ export default function DailyMonitoring() {
|
||||
<Text className='dm-date-arrow'>V</Text>
|
||||
</View>
|
||||
</Picker>
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
{/* ── Group 1: 晨间体征 (default open) ── */}
|
||||
<View className={`dm-group${collapsed.morning ? ' dm-group-collapsed' : ''}`}>
|
||||
<ContentCard className={`dm-group${collapsed.morning ? ' dm-group-collapsed' : ''}`}>
|
||||
<View className='dm-group-header' onClick={() => toggleSection('morning')}>
|
||||
<Text className='dm-group-title'>晨间体征</Text>
|
||||
<Text className={`dm-group-arrow${collapsed.morning ? '' : ' dm-group-arrow-open'}`}>▸</Text>
|
||||
@@ -295,10 +297,10 @@ export default function DailyMonitoring() {
|
||||
</View>
|
||||
<Text className='dm-field-unit'>mmHg</Text>
|
||||
</View>
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
{/* ── Group 2: 晚间体征 (default open) ── */}
|
||||
<View className={`dm-group${collapsed.evening ? ' dm-group-collapsed' : ''}`}>
|
||||
<ContentCard className={`dm-group${collapsed.evening ? ' dm-group-collapsed' : ''}`}>
|
||||
<View className='dm-group-header' onClick={() => toggleSection('evening')}>
|
||||
<Text className='dm-group-title'>晚间体征</Text>
|
||||
<Text className={`dm-group-arrow${collapsed.evening ? '' : ' dm-group-arrow-open'}`}>▸</Text>
|
||||
@@ -343,10 +345,10 @@ export default function DailyMonitoring() {
|
||||
</View>
|
||||
<Text className='dm-field-unit'>mmHg</Text>
|
||||
</View>
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
{/* ── Group 3: 其他指标 (default collapsed) ── */}
|
||||
<View className={`dm-group${collapsed.other ? ' dm-group-collapsed' : ''}`}>
|
||||
<ContentCard className={`dm-group${collapsed.other ? ' dm-group-collapsed' : ''}`}>
|
||||
<View className='dm-group-header' onClick={() => toggleSection('other')}>
|
||||
<Text className='dm-group-title'>其他指标</Text>
|
||||
<Text className={`dm-group-arrow${collapsed.other ? '' : ' dm-group-arrow-open'}`}>▸</Text>
|
||||
@@ -428,7 +430,7 @@ export default function DailyMonitoring() {
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
{/* 提交 */}
|
||||
<View
|
||||
@@ -442,6 +444,6 @@ export default function DailyMonitoring() {
|
||||
<View className='dm-reset' onClick={resetForm}>
|
||||
<Text className='dm-reset-text'>清空表单</Text>
|
||||
</View>
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
@import '../../../styles/variables.scss';
|
||||
@import '../../../styles/mixins.scss';
|
||||
|
||||
.device-sync-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
}
|
||||
// PageShell 已接管:min-height, background, safe-bottom
|
||||
// ContentCard 已接管:sync-status-card/sync-result-card 背景/圆角/阴影
|
||||
|
||||
.sync-header {
|
||||
background: $pri;
|
||||
@@ -130,11 +127,7 @@
|
||||
.sync-status-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: $card;
|
||||
border-radius: $r-sm;
|
||||
padding: 24px;
|
||||
margin-bottom: 16px;
|
||||
box-shadow: $shadow-sm;
|
||||
}
|
||||
|
||||
.sync-status-dot {
|
||||
@@ -225,9 +218,6 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
padding: 48px 24px;
|
||||
margin-bottom: 24px;
|
||||
box-shadow: $shadow-sm;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@ import { uploadReadings } from '@/services/device-sync';
|
||||
import { useAuthStore } from '@/stores/auth';
|
||||
import type { BLEDevice, NormalizedReading } from '@/services/ble/types';
|
||||
import { useElderClass } from '@/hooks/useElderClass';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import ContentCard from '@/components/ui/ContentCard';
|
||||
import './index.scss';
|
||||
|
||||
/** liveReadings 最大保留条数,防止内存无限增长 */
|
||||
@@ -232,10 +234,10 @@ export default function DeviceSync() {
|
||||
|
||||
const renderConnected = () => (
|
||||
<View className="sync-section">
|
||||
<View className="sync-status-card">
|
||||
<ContentCard className="sync-status-card">
|
||||
<Text className="sync-status-dot sync-status-dot--connected" />
|
||||
<Text className="sync-status-text">已连接: {selectedDevice?.name}</Text>
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
{liveReadings.length > 0 && (
|
||||
<View className="sync-readings-panel">
|
||||
@@ -276,11 +278,11 @@ export default function DeviceSync() {
|
||||
|
||||
const renderDone = () => (
|
||||
<View className="sync-section">
|
||||
<View className="sync-result-card">
|
||||
<ContentCard className="sync-result-card">
|
||||
<Text className="sync-result-icon">V</Text>
|
||||
<Text className="sync-result-title">同步完成</Text>
|
||||
<Text className="sync-result-count">成功上传 {syncCount} 条数据</Text>
|
||||
</View>
|
||||
</ContentCard>
|
||||
<View className="sync-action" onClick={() => {
|
||||
handleDisconnect();
|
||||
if (returnTo === 'input') {
|
||||
@@ -293,7 +295,7 @@ export default function DeviceSync() {
|
||||
);
|
||||
|
||||
return (
|
||||
<View className={`device-sync-page ${modeClass}`}>
|
||||
<PageShell padding="none" className={modeClass}>
|
||||
<View className="sync-header">
|
||||
<Text className="sync-header-title">设备同步</Text>
|
||||
</View>
|
||||
@@ -317,6 +319,6 @@ export default function DeviceSync() {
|
||||
{(pageState === 'idle' || pageState === 'error') && renderIdle()}
|
||||
{pageState === 'connected' && renderConnected()}
|
||||
{pageState === 'done' && renderDone()}
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
@import '../../../styles/variables.scss';
|
||||
@import '../../../styles/mixins.scss';
|
||||
|
||||
.input-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding: 0 0 60px;
|
||||
}
|
||||
// PageShell 已接管:min-height, background
|
||||
// ContentCard 已接管:input-card 背景/圆角/阴影
|
||||
|
||||
/* ── hero ── */
|
||||
.input-hero {
|
||||
@@ -47,10 +44,6 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
box-shadow: $shadow-sm;
|
||||
padding: 24px 28px;
|
||||
margin: 0 24px 20px;
|
||||
border: 1px dashed $pri;
|
||||
|
||||
@@ -72,10 +65,6 @@
|
||||
|
||||
/* ── card ── */
|
||||
.input-card {
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
box-shadow: $shadow-md;
|
||||
padding: 28px;
|
||||
margin: 0 24px 20px;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@ import { useSafeTimeout } from '@/hooks/useSafeTimeout';
|
||||
import { trackEvent } from '@/services/analytics';
|
||||
import { useElderClass } from '../../../hooks/useElderClass';
|
||||
import Loading from '../../../components/Loading';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import ContentCard from '@/components/ui/ContentCard';
|
||||
import './index.scss';
|
||||
|
||||
const INDICATORS = [
|
||||
@@ -176,7 +178,7 @@ export default function HealthInput() {
|
||||
const indicatorInitial = INDICATORS[indicatorIdx].label.charAt(0);
|
||||
|
||||
return (
|
||||
<View className={`input-page ${modeClass}`}>
|
||||
<PageShell padding="none" safeBottom className={modeClass}>
|
||||
{loadingThresholds && <Loading />}
|
||||
|
||||
{!loadingThresholds && (
|
||||
@@ -197,7 +199,7 @@ export default function HealthInput() {
|
||||
</View>
|
||||
|
||||
{/* 指标类型选择 */}
|
||||
<View className='input-card'>
|
||||
<ContentCard className='input-card'>
|
||||
<View className='input-card-header'>
|
||||
<View className='input-card-indicator'>
|
||||
<Text className='input-card-indicator-char'>{indicatorInitial}</Text>
|
||||
@@ -215,11 +217,11 @@ export default function HealthInput() {
|
||||
<Text className='input-picker-arrow'>V</Text>
|
||||
</View>
|
||||
</Picker>
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
{/* 数值输入 */}
|
||||
{BP_INDICATORS.includes(INDICATORS[indicatorIdx].value) ? (
|
||||
<View className='input-card'>
|
||||
<ContentCard className='input-card'>
|
||||
<Text className='input-section-title'>血压数值</Text>
|
||||
<View className='input-bp-group'>
|
||||
<View className='input-bp-field'>
|
||||
@@ -249,9 +251,9 @@ export default function HealthInput() {
|
||||
</View>
|
||||
</View>
|
||||
<Text className='input-field-unit'>mmHg</Text>
|
||||
</View>
|
||||
</ContentCard>
|
||||
) : (
|
||||
<View className='input-card'>
|
||||
<ContentCard className='input-card'>
|
||||
<Text className='input-section-title'>检测数值</Text>
|
||||
<Input
|
||||
type='digit'
|
||||
@@ -263,11 +265,11 @@ export default function HealthInput() {
|
||||
<Text className='input-field-unit'>
|
||||
{INDICATORS[indicatorIdx].label.match(/\((.+)\)/)?.[1] || ''}
|
||||
</Text>
|
||||
</View>
|
||||
</ContentCard>
|
||||
)}
|
||||
|
||||
{/* 备注 */}
|
||||
<View className='input-card'>
|
||||
<ContentCard className='input-card'>
|
||||
<Text className='input-section-title'>备注</Text>
|
||||
<Input
|
||||
className='input-field-box input-field-full'
|
||||
@@ -275,7 +277,7 @@ export default function HealthInput() {
|
||||
value={note}
|
||||
onInput={(e) => setNote(e.detail.value)}
|
||||
/>
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
{/* 提交 */}
|
||||
<View
|
||||
@@ -286,6 +288,6 @@ export default function HealthInput() {
|
||||
</View>
|
||||
</>
|
||||
)}
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
@import '../../../styles/variables.scss';
|
||||
@import '../../../styles/mixins.scss';
|
||||
|
||||
.trend-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
// PageShell 已接管:min-height, background
|
||||
// ContentCard 已接管:trend-chart-card 背景/圆角/阴影
|
||||
|
||||
.trend-page-shell {
|
||||
padding-bottom: 60px;
|
||||
}
|
||||
|
||||
@@ -48,10 +49,6 @@
|
||||
/* ── chart card ── */
|
||||
.trend-chart-card {
|
||||
margin: 0 24px 20px;
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
box-shadow: $shadow-md;
|
||||
padding: 24px;
|
||||
min-height: 300px;
|
||||
overflow: hidden;
|
||||
}
|
||||
@@ -59,9 +56,6 @@
|
||||
/* ── reference card ── */
|
||||
.trend-ref-card {
|
||||
margin: 0 24px 20px;
|
||||
background: $acc-l;
|
||||
border-radius: $r;
|
||||
padding: 20px 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
|
||||
@@ -8,6 +8,8 @@ import Loading from '@/components/Loading';
|
||||
import ErrorState from '@/components/ErrorState';
|
||||
import EmptyState from '@/components/EmptyState';
|
||||
import SegmentTabs from '@/components/SegmentTabs';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import ContentCard from '@/components/ui/ContentCard';
|
||||
import { useElderClass } from '../../../hooks/useElderClass';
|
||||
import './index.scss';
|
||||
|
||||
@@ -67,7 +69,7 @@ export default function Trend() {
|
||||
};
|
||||
|
||||
return (
|
||||
<View className={`trend-page ${modeClass}`}>
|
||||
<PageShell padding="none" className={modeClass}>
|
||||
{/* 页面标题 */}
|
||||
<View className='trend-hero'>
|
||||
<View className='trend-hero-icon'>
|
||||
@@ -81,36 +83,36 @@ export default function Trend() {
|
||||
|
||||
{/* ECharts 折线图 */}
|
||||
{loading ? (
|
||||
<View className='trend-chart-card'>
|
||||
<ContentCard className='trend-chart-card'>
|
||||
<Loading />
|
||||
</View>
|
||||
</ContentCard>
|
||||
) : error ? (
|
||||
<View className='trend-chart-card'>
|
||||
<ContentCard className='trend-chart-card'>
|
||||
<ErrorState onRetry={fetchTrend} />
|
||||
</View>
|
||||
</ContentCard>
|
||||
) : points.length === 0 ? (
|
||||
<View className='trend-chart-card'>
|
||||
<ContentCard className='trend-chart-card'>
|
||||
<EmptyState text='暂无趋势数据' />
|
||||
</View>
|
||||
</ContentCard>
|
||||
) : (
|
||||
<View className='trend-chart-card'>
|
||||
<ContentCard className='trend-chart-card'>
|
||||
<TrendChart
|
||||
data={points}
|
||||
referenceMin={meta.refMin}
|
||||
referenceMax={meta.refMax}
|
||||
unit={meta.unit}
|
||||
/>
|
||||
</View>
|
||||
</ContentCard>
|
||||
)}
|
||||
|
||||
{/* 参考区间 */}
|
||||
{!loading && points.length > 0 && meta.refMin !== undefined && meta.refMax !== undefined && (
|
||||
<View className='trend-ref-card'>
|
||||
<ContentCard variant="outlined" className='trend-ref-card'>
|
||||
<Text className='trend-ref-label'>参考区间</Text>
|
||||
<Text className='trend-ref-value'>
|
||||
{meta.refMin} ~ {meta.refMax} {meta.unit}
|
||||
</Text>
|
||||
</View>
|
||||
</ContentCard>
|
||||
)}
|
||||
|
||||
{/* 数据列表 */}
|
||||
@@ -135,6 +137,6 @@ export default function Trend() {
|
||||
})}
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
@import '../../../styles/variables.scss';
|
||||
@import '../../../styles/mixins.scss';
|
||||
|
||||
.detail-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
// PageShell 已接管:min-height, background, padding
|
||||
|
||||
/* ===== 余额卡片 ===== */
|
||||
.balance-card {
|
||||
|
||||
@@ -8,6 +8,7 @@ import { usePointsStore } from '../../../stores/points';
|
||||
import EmptyState from '../../../components/EmptyState';
|
||||
import Loading from '../../../components/Loading';
|
||||
import { useElderClass } from '../../../hooks/useElderClass';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import './index.scss';
|
||||
|
||||
const TYPE_TABS = [
|
||||
@@ -109,7 +110,7 @@ export default function PointsDetail() {
|
||||
const balance = account?.balance ?? 0;
|
||||
|
||||
return (
|
||||
<View className={`detail-page ${modeClass}`}>
|
||||
<PageShell className={modeClass}>
|
||||
{/* 余额卡片 */}
|
||||
<View className='balance-card'>
|
||||
<Text className='balance-label'>当前积分</Text>
|
||||
@@ -177,6 +178,6 @@ export default function PointsDetail() {
|
||||
)}
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
@import '../../../styles/variables.scss';
|
||||
@import '../../../styles/mixins.scss';
|
||||
|
||||
// PageShell 已接管:min-height, background, padding
|
||||
.exchange-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding-bottom: 140px;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import { usePointsStore } from '../../../stores/points';
|
||||
import Loading from '../../../components/Loading';
|
||||
import { useElderClass } from '../../../hooks/useElderClass';
|
||||
import { useSafeTimeout } from '@/hooks/useSafeTimeout';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import './index.scss';
|
||||
|
||||
const TYPE_INITIAL: Record<string, string> = {
|
||||
@@ -128,9 +129,9 @@ export default function ExchangeConfirm() {
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<View className={`exchange-page ${modeClass}`}>
|
||||
<PageShell className={modeClass}>
|
||||
<Loading />
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -140,7 +141,7 @@ export default function ExchangeConfirm() {
|
||||
const iconCls = TYPE_CLASS[productType] || 'product-icon-wrap--service';
|
||||
|
||||
return (
|
||||
<View className={`exchange-page ${modeClass}`}>
|
||||
<PageShell className={modeClass}>
|
||||
{/* 商品预览卡片 */}
|
||||
<View className='product-card'>
|
||||
<View className={`product-icon-wrap ${iconCls}`}>
|
||||
@@ -216,6 +217,6 @@ export default function ExchangeConfirm() {
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
@import '../../../styles/variables.scss';
|
||||
@import '../../../styles/mixins.scss';
|
||||
|
||||
.orders-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
// PageShell 已接管:min-height, background, safe-bottom
|
||||
// ContentCard 已接管:order-card 背景/圆角/阴影
|
||||
|
||||
/* ===== 订单列表 ===== */
|
||||
.order-list {
|
||||
@@ -13,11 +10,8 @@
|
||||
}
|
||||
|
||||
.order-card {
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
margin-bottom: 16px;
|
||||
overflow: hidden;
|
||||
box-shadow: $shadow-sm;
|
||||
}
|
||||
|
||||
.order-header {
|
||||
|
||||
@@ -8,6 +8,8 @@ import EmptyState from '../../../components/EmptyState';
|
||||
import ErrorState from '../../../components/ErrorState';
|
||||
import Loading from '../../../components/Loading';
|
||||
import SegmentTabs from '../../../components/SegmentTabs';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import ContentCard from '@/components/ui/ContentCard';
|
||||
import { useElderClass } from '../../../hooks/useElderClass';
|
||||
import './index.scss';
|
||||
|
||||
@@ -111,7 +113,7 @@ export default function MallOrders() {
|
||||
};
|
||||
|
||||
return (
|
||||
<View className={`orders-page ${modeClass}`}>
|
||||
<PageShell padding="none" className={modeClass}>
|
||||
{/* 状态筛选标签 */}
|
||||
<SegmentTabs tabs={STATUS_TABS} activeKey={activeTab} onChange={handleTabChange} variant="underline" />
|
||||
|
||||
@@ -131,7 +133,7 @@ export default function MallOrders() {
|
||||
{orders.map((order) => {
|
||||
const statusCfg = getStatusConfig(order.status);
|
||||
return (
|
||||
<View className='order-card' key={order.id}>
|
||||
<ContentCard className='order-card' key={order.id}>
|
||||
<View className='order-header'>
|
||||
<Text className='order-product'>商品 {order.product_id.slice(0, 8)}</Text>
|
||||
<View
|
||||
@@ -162,7 +164,7 @@ export default function MallOrders() {
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
</ContentCard>
|
||||
);
|
||||
})}
|
||||
{loading && <Loading />}
|
||||
@@ -171,6 +173,6 @@ export default function MallOrders() {
|
||||
)}
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
@import '../../../styles/variables.scss';
|
||||
@import '../../../styles/mixins.scss';
|
||||
|
||||
.consents-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding: 32px 24px;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
// PageShell 已接管:min-height, background, padding
|
||||
|
||||
.page-title {
|
||||
@include section-title;
|
||||
|
||||
@@ -8,6 +8,7 @@ import type { Consent } from '@/services/consent';
|
||||
import EmptyState from '@/components/EmptyState';
|
||||
import Loading from '@/components/Loading';
|
||||
import { useElderClass } from '../../../hooks/useElderClass';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import './index.scss';
|
||||
|
||||
const CONSENT_TYPE_MAP: Record<string, string> = {
|
||||
@@ -82,7 +83,7 @@ export default function ConsentList() {
|
||||
};
|
||||
|
||||
return (
|
||||
<View className={`consents-page ${modeClass}`}>
|
||||
<PageShell className={modeClass}>
|
||||
<Text className='page-title'>知情同意</Text>
|
||||
|
||||
<View className='consent-list'>
|
||||
@@ -123,6 +124,6 @@ export default function ConsentList() {
|
||||
)}
|
||||
|
||||
{loading && <Loading />}
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
@import '../../../styles/variables.scss';
|
||||
@import '../../../styles/mixins.scss';
|
||||
|
||||
.diagnoses-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding: 32px 24px;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
// PageShell 已接管:min-height, background, padding
|
||||
|
||||
.page-title {
|
||||
font-family: 'Georgia', 'Times New Roman', serif;
|
||||
|
||||
@@ -7,6 +7,7 @@ import { listDiagnoses, Diagnosis } from '../../../services/health-record';
|
||||
import EmptyState from '../../../components/EmptyState';
|
||||
import Loading from '../../../components/Loading';
|
||||
import { useElderClass } from '../../../hooks/useElderClass';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import './index.scss';
|
||||
|
||||
const TYPE_MAP: Record<string, { label: string; cls: string }> = {
|
||||
@@ -60,7 +61,7 @@ export default function Diagnoses() {
|
||||
});
|
||||
|
||||
return (
|
||||
<View className={`diagnoses-page ${modeClass}`}>
|
||||
<PageShell className={modeClass}>
|
||||
<Text className='page-title'>诊断记录</Text>
|
||||
|
||||
<View className='diagnosis-list'>
|
||||
@@ -95,6 +96,6 @@ export default function Diagnoses() {
|
||||
)}
|
||||
|
||||
{loading && <Loading />}
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,28 +1,11 @@
|
||||
@import '../../../../styles/variables.scss';
|
||||
@import '../../../../styles/mixins.scss';
|
||||
|
||||
.detail-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding: 24px;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
|
||||
.detail-card {
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
padding: 28px;
|
||||
margin-bottom: 20px;
|
||||
box-shadow: $shadow-sm;
|
||||
}
|
||||
|
||||
.header-card {
|
||||
.header-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.header-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.detail-title {
|
||||
|
||||
@@ -5,6 +5,8 @@ import { usePageData } from '@/hooks/usePageData';
|
||||
import { getDialysisPrescription } from '@/services/dialysis';
|
||||
import type { DialysisPrescription } from '@/services/dialysis';
|
||||
import Loading from '@/components/Loading';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import ContentCard from '@/components/ui/ContentCard';
|
||||
import { useElderClass } from '../../../../hooks/useElderClass';
|
||||
import './index.scss';
|
||||
|
||||
@@ -36,8 +38,8 @@ export default function DialysisPrescriptionDetail() {
|
||||
|
||||
usePageData(fetchDetail, { throttleMs: 60000 });
|
||||
|
||||
if (loading) return <View className={`detail-page ${modeClass}`}><Loading /></View>;
|
||||
if (!rx) return <View className={`detail-page ${modeClass}`}><View className='empty-state'><Text className='empty-text'>处方不存在</Text></View></View>;
|
||||
if (loading) return <PageShell className={modeClass}><Loading /></PageShell>;
|
||||
if (!rx) return <PageShell className={modeClass}><View className='empty-state'><Text className='empty-text'>处方不存在</Text></View></PageShell>;
|
||||
|
||||
const si = STATUS_MAP[rx.status] || { label: rx.status, cls: '' };
|
||||
|
||||
@@ -52,9 +54,9 @@ export default function DialysisPrescriptionDetail() {
|
||||
};
|
||||
|
||||
return (
|
||||
<View className={`detail-page ${modeClass}`}>
|
||||
<PageShell className={modeClass}>
|
||||
{/* 状态头部 */}
|
||||
<View className='detail-card header-card'>
|
||||
<ContentCard>
|
||||
<View className='header-row'>
|
||||
<Text className='detail-title'>{rx.dialyzer_model || '透析处方'}</Text>
|
||||
<Text className={`status-tag ${si.cls}`}>{si.label}</Text>
|
||||
@@ -62,10 +64,10 @@ export default function DialysisPrescriptionDetail() {
|
||||
{(rx.effective_from || rx.effective_to) && (
|
||||
<Text className='header-sub'>{rx.effective_from || '...'} ~ {rx.effective_to || '...'}</Text>
|
||||
)}
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
{/* 基本参数 */}
|
||||
<View className='detail-card'>
|
||||
<ContentCard>
|
||||
<Text className='section-title'>基本参数</Text>
|
||||
<Row label='透析器型号' value={rx.dialyzer_model} />
|
||||
<Row label='膜面积' value={rx.membrane_area != null ? `${rx.membrane_area} m²` : null} />
|
||||
@@ -73,48 +75,48 @@ export default function DialysisPrescriptionDetail() {
|
||||
<Row label='透析液流量' value={rx.dialysate_flow_rate != null ? `${rx.dialysate_flow_rate} ml/min` : null} />
|
||||
<Row label='频率' value={rx.frequency_per_week != null ? `${rx.frequency_per_week} 次/周` : null} />
|
||||
<Row label='每次时长' value={rx.duration_minutes != null ? `${rx.duration_minutes} 分钟` : null} />
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
{/* 透析液配比 */}
|
||||
<View className='detail-card'>
|
||||
<ContentCard>
|
||||
<Text className='section-title'>透析液配比</Text>
|
||||
<Row label='钾浓度' value={rx.dialysate_potassium != null ? `${rx.dialysate_potassium} mmol/L` : null} />
|
||||
<Row label='钙浓度' value={rx.dialysate_calcium != null ? `${rx.dialysate_calcium} mmol/L` : null} />
|
||||
<Row label='碳酸氢盐浓度' value={rx.dialysate_bicarbonate != null ? `${rx.dialysate_bicarbonate} mmol/L` : null} />
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
{/* 抗凝方案 */}
|
||||
<View className='detail-card'>
|
||||
<ContentCard>
|
||||
<Text className='section-title'>抗凝方案</Text>
|
||||
<Row label='抗凝类型' value={rx.anticoagulation_type} />
|
||||
<Row label='抗凝剂量' value={rx.anticoagulation_dose} />
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
{/* 血管通路 */}
|
||||
{(rx.vascular_access_type || rx.vascular_access_location) && (
|
||||
<View className='detail-card'>
|
||||
<ContentCard>
|
||||
<Text className='section-title'>血管通路</Text>
|
||||
<Row label='通路类型' value={rx.vascular_access_type} />
|
||||
<Row label='通路位置' value={rx.vascular_access_location} />
|
||||
</View>
|
||||
</ContentCard>
|
||||
)}
|
||||
|
||||
{/* 超滤与干体重 */}
|
||||
{(rx.target_ultrafiltration_ml != null || rx.target_dry_weight != null) && (
|
||||
<View className='detail-card'>
|
||||
<ContentCard>
|
||||
<Text className='section-title'>超滤目标</Text>
|
||||
<Row label='目标超滤量' value={rx.target_ultrafiltration_ml != null ? `${rx.target_ultrafiltration_ml} ml` : null} />
|
||||
<Row label='目标干体重' value={rx.target_dry_weight != null ? `${rx.target_dry_weight} kg` : null} />
|
||||
</View>
|
||||
</ContentCard>
|
||||
)}
|
||||
|
||||
{/* 备注 */}
|
||||
{rx.notes && (
|
||||
<View className='detail-card'>
|
||||
<ContentCard>
|
||||
<Text className='section-title'>备注</Text>
|
||||
<Text className='notes-text'>{rx.notes}</Text>
|
||||
</View>
|
||||
</ContentCard>
|
||||
)}
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
@import '../../../styles/variables.scss';
|
||||
@import '../../../styles/mixins.scss';
|
||||
|
||||
.dialysis-prescriptions-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding: 32px 24px;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
// PageShell 已接管:min-height, background, padding
|
||||
|
||||
.page-title {
|
||||
@include section-title;
|
||||
|
||||
@@ -8,6 +8,7 @@ import type { DialysisPrescription } from '@/services/dialysis';
|
||||
import EmptyState from '@/components/EmptyState';
|
||||
import Loading from '@/components/Loading';
|
||||
import { useElderClass } from '../../../hooks/useElderClass';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import './index.scss';
|
||||
|
||||
const STATUS_MAP: Record<string, { label: string; cls: string }> = {
|
||||
@@ -57,7 +58,7 @@ export default function DialysisPrescriptionList() {
|
||||
const statusInfo = (s: string) => STATUS_MAP[s] || { label: s, cls: '' };
|
||||
|
||||
return (
|
||||
<View className={`dialysis-prescriptions-page ${modeClass}`}>
|
||||
<PageShell className={modeClass}>
|
||||
<Text className='page-title'>透析处方</Text>
|
||||
|
||||
<View className='prescription-list'>
|
||||
@@ -96,6 +97,6 @@ export default function DialysisPrescriptionList() {
|
||||
)}
|
||||
|
||||
{loading && <Loading />}
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,28 +1,11 @@
|
||||
@import '../../../../styles/variables.scss';
|
||||
@import '../../../../styles/mixins.scss';
|
||||
|
||||
.detail-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding: 24px;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
|
||||
.detail-card {
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
padding: 28px;
|
||||
margin-bottom: 20px;
|
||||
box-shadow: $shadow-sm;
|
||||
}
|
||||
|
||||
.header-card {
|
||||
.header-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.header-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.detail-title {
|
||||
|
||||
@@ -5,6 +5,8 @@ import { usePageData } from '@/hooks/usePageData';
|
||||
import { getDialysisRecord } from '@/services/dialysis';
|
||||
import type { DialysisRecord } from '@/services/dialysis';
|
||||
import Loading from '@/components/Loading';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import ContentCard from '@/components/ui/ContentCard';
|
||||
import { useElderClass } from '../../../../hooks/useElderClass';
|
||||
import './index.scss';
|
||||
|
||||
@@ -42,25 +44,25 @@ export default function DialysisRecordDetail() {
|
||||
|
||||
usePageData(fetchDetail, { throttleMs: 60000 });
|
||||
|
||||
if (loading) return <View className={`detail-page ${modeClass}`}><Loading /></View>;
|
||||
if (!record) return <View className={`detail-page ${modeClass}`}><View className='empty-state'><Text className='empty-text'>记录不存在</Text></View></View>;
|
||||
if (loading) return <PageShell className={modeClass}><Loading /></PageShell>;
|
||||
if (!record) return <PageShell className={modeClass}><View className='empty-state'><Text className='empty-text'>记录不存在</Text></View></PageShell>;
|
||||
|
||||
const si = STATUS_MAP[record.status] || { label: record.status, cls: '' };
|
||||
|
||||
return (
|
||||
<View className={`detail-page ${modeClass}`}>
|
||||
<PageShell className={modeClass}>
|
||||
{/* 状态头部 */}
|
||||
<View className='detail-card header-card'>
|
||||
<ContentCard>
|
||||
<View className='header-row'>
|
||||
<Text className='detail-title'>{record.dialysis_date}</Text>
|
||||
<Text className={`status-tag ${si.cls}`}>{si.label}</Text>
|
||||
</View>
|
||||
<Text className='header-sub'>{TYPE_MAP[record.dialysis_type] || record.dialysis_type}</Text>
|
||||
{record.reviewed_at && <Text className='review-info'>审核时间 {record.reviewed_at}</Text>}
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
{/* 基本信息 */}
|
||||
<View className='detail-card'>
|
||||
<ContentCard>
|
||||
<Text className='section-title'>基本信息</Text>
|
||||
{record.start_time && (
|
||||
<View className='detail-row'><Text className='detail-label'>开始时间</Text><Text className='detail-value'>{record.start_time}</Text></View>
|
||||
@@ -77,10 +79,10 @@ export default function DialysisRecordDetail() {
|
||||
{record.ultrafiltration_volume != null && (
|
||||
<View className='detail-row'><Text className='detail-label'>超滤量</Text><Text className='detail-value'>{record.ultrafiltration_volume} ml</Text></View>
|
||||
)}
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
{/* 体重与血压 */}
|
||||
<View className='detail-card'>
|
||||
<ContentCard>
|
||||
<Text className='section-title'>体重与血压</Text>
|
||||
{record.dry_weight != null && (
|
||||
<View className='detail-row'><Text className='detail-label'>干体重</Text><Text className='detail-value'>{record.dry_weight} kg</Text></View>
|
||||
@@ -103,11 +105,11 @@ export default function DialysisRecordDetail() {
|
||||
{record.post_heart_rate != null && (
|
||||
<View className='detail-row'><Text className='detail-label'>透后心率</Text><Text className='detail-value'>{record.post_heart_rate} bpm</Text></View>
|
||||
)}
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
{/* 症状与并发症 */}
|
||||
{(record.symptoms || record.complication_notes) && (
|
||||
<View className='detail-card'>
|
||||
<ContentCard>
|
||||
<Text className='section-title'>症状与并发症</Text>
|
||||
{record.symptoms && Object.keys(record.symptoms).length > 0 && (
|
||||
<View className='detail-row'><Text className='detail-label'>症状</Text><Text className='detail-value'>{JSON.stringify(record.symptoms)}</Text></View>
|
||||
@@ -115,8 +117,8 @@ export default function DialysisRecordDetail() {
|
||||
{record.complication_notes && (
|
||||
<View className='detail-row'><Text className='detail-label'>并发症备注</Text><Text className='detail-value'>{record.complication_notes}</Text></View>
|
||||
)}
|
||||
</View>
|
||||
</ContentCard>
|
||||
)}
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
@import '../../../styles/variables.scss';
|
||||
@import '../../../styles/mixins.scss';
|
||||
|
||||
.dialysis-records-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding: 32px 24px;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
// PageShell 已接管:min-height, background, padding
|
||||
|
||||
.page-title {
|
||||
@include section-title;
|
||||
|
||||
@@ -8,6 +8,7 @@ import type { DialysisRecord } from '@/services/dialysis';
|
||||
import EmptyState from '@/components/EmptyState';
|
||||
import Loading from '@/components/Loading';
|
||||
import { useElderClass } from '../../../hooks/useElderClass';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import './index.scss';
|
||||
|
||||
const TYPE_MAP: Record<string, { label: string; cls: string }> = {
|
||||
@@ -64,7 +65,7 @@ export default function DialysisRecordList() {
|
||||
const statusInfo = (s: string) => STATUS_MAP[s] || { label: s, cls: '' };
|
||||
|
||||
return (
|
||||
<View className={`dialysis-records-page ${modeClass}`}>
|
||||
<PageShell className={modeClass}>
|
||||
<Text className='page-title'>透析记录</Text>
|
||||
|
||||
<View className='record-list'>
|
||||
@@ -101,6 +102,6 @@ export default function DialysisRecordList() {
|
||||
)}
|
||||
|
||||
{loading && <Loading />}
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
@import '../../../styles/variables.scss';
|
||||
@import '../../../styles/mixins.scss';
|
||||
|
||||
// PageShell 已接管:min-height, background, padding
|
||||
.events-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding-bottom: 120px;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import Loading from '@/components/Loading';
|
||||
import EmptyState from '@/components/EmptyState';
|
||||
import { useElderClass } from '@/hooks/useElderClass';
|
||||
import { usePageData } from '@/hooks/usePageData';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import './index.scss';
|
||||
|
||||
const STATUS_MAP: Record<string, { label: string; className: string }> = {
|
||||
@@ -60,7 +61,7 @@ export default function EventsPage() {
|
||||
if (loading) return <Loading />;
|
||||
|
||||
return (
|
||||
<ScrollView scrollY className={`events-page ${modeClass}`}>
|
||||
<PageShell className={modeClass}>
|
||||
<View className='events-header'>
|
||||
<Text className='events-header__title'>线下活动</Text>
|
||||
<Text className='events-header__subtitle'>参加活动赢取积分</Text>
|
||||
@@ -111,6 +112,6 @@ export default function EventsPage() {
|
||||
})}
|
||||
</View>
|
||||
)}
|
||||
</ScrollView>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
@import '../../../styles/variables.scss';
|
||||
@import '../../../styles/mixins.scss';
|
||||
|
||||
// PageShell 已接管:min-height, background, padding
|
||||
.family-add-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding: 32px 24px;
|
||||
padding-bottom: 160px;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import Taro, { useRouter } from '@tarojs/taro';
|
||||
import { createPatient, updatePatient, Patient } from '../../../services/patient';
|
||||
import { useElderClass } from '../../../hooks/useElderClass';
|
||||
import { useSafeTimeout } from '@/hooks/useSafeTimeout';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import './index.scss';
|
||||
|
||||
const RELATION_OPTIONS = ['本人', '配偶', '父母', '子女', '其他'];
|
||||
@@ -66,7 +67,7 @@ export default function FamilyAdd() {
|
||||
};
|
||||
|
||||
return (
|
||||
<View className={`family-add-page ${modeClass}`}>
|
||||
<PageShell className={modeClass}>
|
||||
<Text className='page-title'>{editId ? '编辑就诊人' : '添加就诊人'}</Text>
|
||||
|
||||
<View className='form-card'>
|
||||
@@ -134,6 +135,6 @@ export default function FamilyAdd() {
|
||||
>
|
||||
<Text className='submit-text'>{submitting ? '提交中...' : editId ? '保存修改' : '确认添加'}</Text>
|
||||
</View>
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
@import '../../../styles/variables.scss';
|
||||
@import '../../../styles/mixins.scss';
|
||||
|
||||
// PageShell 已接管:min-height, background, padding
|
||||
.family-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding: 32px 24px;
|
||||
padding-bottom: 160px;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import { listPatients, Patient } from '../../../services/patient';
|
||||
import { useAuthStore } from '../../../stores/auth';
|
||||
import EmptyState from '../../../components/EmptyState';
|
||||
import { useElderClass } from '../../../hooks/useElderClass';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import './index.scss';
|
||||
|
||||
export default function FamilyList() {
|
||||
@@ -60,7 +61,7 @@ export default function FamilyList() {
|
||||
};
|
||||
|
||||
return (
|
||||
<View className={`family-page ${modeClass}`}>
|
||||
<PageShell className={modeClass}>
|
||||
<Text className='family-page-title'>就诊人管理</Text>
|
||||
|
||||
<View className='family-list'>
|
||||
@@ -103,6 +104,6 @@ export default function FamilyList() {
|
||||
<View className='family-add-btn' onClick={goToAdd}>
|
||||
<Text className='family-add-text'>添加就诊人</Text>
|
||||
</View>
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,21 +1,6 @@
|
||||
@import '../../../../styles/variables.scss';
|
||||
@import '../../../../styles/mixins.scss';
|
||||
|
||||
.detail-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding: 24px;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
|
||||
.detail-card {
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
padding: 28px;
|
||||
margin-bottom: 20px;
|
||||
box-shadow: $shadow-sm;
|
||||
}
|
||||
|
||||
.detail-title {
|
||||
@include section-title;
|
||||
font-size: var(--tk-font-num-lg);
|
||||
@@ -79,13 +64,6 @@
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.submit-card {
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
padding: 28px;
|
||||
box-shadow: $shadow-sm;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
@include section-title;
|
||||
margin-bottom: 16px;
|
||||
|
||||
@@ -8,6 +8,8 @@ import { TEMPLATE_IDS } from '@/services/wechat-templates';
|
||||
import { trackEvent } from '@/services/analytics';
|
||||
import Loading from '@/components/Loading';
|
||||
import ErrorState from '@/components/ErrorState';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import ContentCard from '@/components/ui/ContentCard';
|
||||
import { useElderClass } from '@/hooks/useElderClass';
|
||||
import './index.scss';
|
||||
|
||||
@@ -89,25 +91,25 @@ export default function FollowUpDetail() {
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<View className={`detail-page ${modeClass}`}>
|
||||
<PageShell className={modeClass}>
|
||||
<Loading />
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
if (error || !task) {
|
||||
return (
|
||||
<View className={`detail-page ${modeClass}`}>
|
||||
<PageShell className={modeClass}>
|
||||
<ErrorState text='任务不存在' />
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
const isCompleted = task.status === 'completed';
|
||||
|
||||
return (
|
||||
<View className={`detail-page ${modeClass}`}>
|
||||
<View className='detail-card'>
|
||||
<PageShell className={modeClass}>
|
||||
<ContentCard>
|
||||
<Text className='detail-title'>{task.follow_up_type}</Text>
|
||||
<View className='detail-row'>
|
||||
<Text className='detail-label'>状态</Text>
|
||||
@@ -132,10 +134,10 @@ export default function FollowUpDetail() {
|
||||
<Text className='detail-desc-text'>{task.content_template}</Text>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
{!isCompleted && (
|
||||
<View className='submit-card'>
|
||||
<ContentCard>
|
||||
<Text className='section-title'>填写随访记录</Text>
|
||||
<Textarea
|
||||
className='submit-textarea'
|
||||
@@ -152,8 +154,8 @@ export default function FollowUpDetail() {
|
||||
{submitting ? '提交中...' : '提交'}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</ContentCard>
|
||||
)}
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
@import '../../../styles/variables.scss';
|
||||
@import '../../../styles/mixins.scss';
|
||||
|
||||
.my-followups-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
}
|
||||
// PageShell 已接管:min-height, background, padding
|
||||
|
||||
.tab-bar {
|
||||
display: flex;
|
||||
|
||||
@@ -7,6 +7,7 @@ import EmptyState from '../../../components/EmptyState';
|
||||
import ErrorState from '../../../components/ErrorState';
|
||||
import Loading from '../../../components/Loading';
|
||||
import { useElderClass } from '../../../hooks/useElderClass';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import './index.scss';
|
||||
|
||||
const TABS = [
|
||||
@@ -60,7 +61,7 @@ export default function MyFollowUps() {
|
||||
};
|
||||
|
||||
return (
|
||||
<View className={`my-followups-page ${modeClass}`}>
|
||||
<PageShell className={modeClass}>
|
||||
<View className='tab-bar'>
|
||||
{TABS.map((tab) => (
|
||||
<View
|
||||
@@ -109,6 +110,6 @@ export default function MyFollowUps() {
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
@import '../../../styles/variables.scss';
|
||||
@import '../../../styles/mixins.scss';
|
||||
|
||||
.health-records-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding: 32px 24px;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
// PageShell 已接管:min-height, background, padding
|
||||
|
||||
.page-title {
|
||||
font-family: 'Georgia', 'Times New Roman', serif;
|
||||
|
||||
@@ -7,6 +7,7 @@ import { listHealthRecords, HealthRecord } from '../../../services/health-record
|
||||
import EmptyState from '../../../components/EmptyState';
|
||||
import Loading from '../../../components/Loading';
|
||||
import { useElderClass } from '../../../hooks/useElderClass';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import './index.scss';
|
||||
|
||||
const TYPE_MAP: Record<string, string> = {
|
||||
@@ -54,7 +55,7 @@ export default function HealthRecords() {
|
||||
});
|
||||
|
||||
return (
|
||||
<View className={`health-records-page ${modeClass}`}>
|
||||
<PageShell className={modeClass}>
|
||||
<Text className='page-title'>健康记录</Text>
|
||||
|
||||
<View className='record-list'>
|
||||
@@ -84,6 +85,6 @@ export default function HealthRecords() {
|
||||
)}
|
||||
|
||||
{loading && <Loading />}
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
@import '../../../styles/variables.scss';
|
||||
@import '../../../styles/mixins.scss';
|
||||
|
||||
// PageShell 已接管:min-height, background, padding
|
||||
.medication-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding: 32px 24px;
|
||||
padding-bottom: 160px;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
type MedicationReminder,
|
||||
} from '../../../services/medication-reminder';
|
||||
import { useElderClass } from '../../../hooks/useElderClass';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import './index.scss';
|
||||
|
||||
export default function MedicationReminder() {
|
||||
@@ -100,17 +101,17 @@ export default function MedicationReminder() {
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<View className={`medication-page ${modeClass}`}>
|
||||
<PageShell className={modeClass}>
|
||||
<Text className='page-title'>用药提醒</Text>
|
||||
<View className='medication-loading'>
|
||||
<Text className='medication-loading-text'>加载中...</Text>
|
||||
</View>
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<View className={`medication-page ${modeClass}`}>
|
||||
<PageShell className={modeClass}>
|
||||
<Text className='page-title'>用药提醒</Text>
|
||||
|
||||
<View className='reminder-list'>
|
||||
@@ -199,6 +200,6 @@ export default function MedicationReminder() {
|
||||
<Text className='add-text'>添加提醒</Text>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,21 +1,6 @@
|
||||
@import '../../../../styles/variables.scss';
|
||||
@import '../../../../styles/mixins.scss';
|
||||
|
||||
.detail-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding: 24px;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
|
||||
.detail-card {
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
padding: 28px;
|
||||
margin-bottom: 20px;
|
||||
box-shadow: $shadow-sm;
|
||||
}
|
||||
|
||||
.detail-title {
|
||||
font-family: 'Georgia', 'Times New Roman', serif;
|
||||
font-size: var(--tk-font-num-lg);
|
||||
@@ -51,13 +36,6 @@
|
||||
margin-left: 24px;
|
||||
}
|
||||
|
||||
.indicators-card {
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
padding: 28px;
|
||||
box-shadow: $shadow-sm;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-family: 'Georgia', 'Times New Roman', serif;
|
||||
font-size: var(--tk-font-num);
|
||||
|
||||
@@ -4,6 +4,8 @@ import Taro, { useRouter } from '@tarojs/taro';
|
||||
import { usePageData } from '@/hooks/usePageData';
|
||||
import { getReportDetail, LabReport } from '@/services/report';
|
||||
import Loading from '@/components/Loading';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import ContentCard from '@/components/ui/ContentCard';
|
||||
import { useElderClass } from '@/hooks/useElderClass';
|
||||
import { useAuthStore } from '@/stores/auth';
|
||||
import './index.scss';
|
||||
@@ -62,26 +64,26 @@ export default function ReportDetail() {
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<View className={`detail-page ${modeClass}`}>
|
||||
<PageShell className={modeClass}>
|
||||
<Loading />
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
if (!report) {
|
||||
return (
|
||||
<View className={`detail-page ${modeClass}`}>
|
||||
<PageShell className={modeClass}>
|
||||
<View className='empty-state'>
|
||||
<Text className='empty-text'>报告不存在</Text>
|
||||
</View>
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<View className={`detail-page ${modeClass}`}>
|
||||
<PageShell className={modeClass}>
|
||||
{/* 基本信息 */}
|
||||
<View className='detail-card'>
|
||||
<ContentCard>
|
||||
<Text className='detail-title'>{report.report_type}</Text>
|
||||
<View className='detail-row'>
|
||||
<Text className='detail-label'>报告日期</Text>
|
||||
@@ -93,10 +95,10 @@ export default function ReportDetail() {
|
||||
<Text className='detail-value'>{report.doctor_interpretation}</Text>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
{/* 指标列表 */}
|
||||
<View className='indicators-card'>
|
||||
<ContentCard>
|
||||
<Text className='section-title'>检查指标</Text>
|
||||
{indicators.map((item) => {
|
||||
const statusInfo = getStatusInfo(item.status);
|
||||
@@ -122,7 +124,7 @@ export default function ReportDetail() {
|
||||
</View>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
</View>
|
||||
</ContentCard>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
@import '../../../styles/variables.scss';
|
||||
@import '../../../styles/mixins.scss';
|
||||
|
||||
.my-reports-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding: 32px 24px;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
// PageShell 已接管:min-height, background, padding
|
||||
|
||||
.page-title {
|
||||
@include section-title;
|
||||
|
||||
@@ -7,6 +7,7 @@ import { listReports, LabReport } from '../../../services/report';
|
||||
import EmptyState from '../../../components/EmptyState';
|
||||
import Loading from '../../../components/Loading';
|
||||
import { useElderClass } from '../../../hooks/useElderClass';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import './index.scss';
|
||||
|
||||
export default function MyReports() {
|
||||
@@ -64,7 +65,7 @@ export default function MyReports() {
|
||||
};
|
||||
|
||||
return (
|
||||
<View className={`my-reports-page ${modeClass}`}>
|
||||
<PageShell className={modeClass}>
|
||||
<Text className='page-title'>检查报告</Text>
|
||||
|
||||
<View className='report-list'>
|
||||
@@ -100,6 +101,6 @@ export default function MyReports() {
|
||||
{loading && (
|
||||
<Loading />
|
||||
)}
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
@import '../../../styles/variables.scss';
|
||||
@import '../../../styles/mixins.scss';
|
||||
|
||||
.settings-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding: 32px 24px;
|
||||
}
|
||||
// PageShell 已接管:min-height, background, padding
|
||||
|
||||
.page-title {
|
||||
@include section-title;
|
||||
|
||||
@@ -4,6 +4,7 @@ import Taro from '@tarojs/taro';
|
||||
import { useAuthStore } from '../../../stores/auth';
|
||||
import { invalidateHeadersCache, clearRequestCache } from '@/services/request';
|
||||
import { useElderClass } from '../../../hooks/useElderClass';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import './index.scss';
|
||||
|
||||
export default function Settings() {
|
||||
@@ -65,7 +66,7 @@ export default function Settings() {
|
||||
};
|
||||
|
||||
return (
|
||||
<View className={`settings-page ${modeClass}`}>
|
||||
<PageShell className={modeClass}>
|
||||
<Text className='page-title'>设置</Text>
|
||||
|
||||
<View className='settings-group'>
|
||||
@@ -97,6 +98,6 @@ export default function Settings() {
|
||||
<Text className='settings-label logout-label'>退出登录</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user