refactor(mp): 迁移剩余 8 特殊页面到统一组件库
- 首页/健康/我的/商城/消息 TabBar 页面使用 PageShell 替代手写容器 - 登录/法律条款/关怀模式设置页使用 PageShell 替代手写容器 - 各页面卡片统一使用 ContentCard 组件 - 清理页面 SCSS 中的 min-height/background/padding 样板代码 - 66 个小程序页面全部完成统一组件迁移
This commit is contained in:
@@ -2,9 +2,6 @@
|
||||
@import '../../styles/mixins.scss';
|
||||
|
||||
.health-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding: 20px 24px 100px;
|
||||
padding-bottom: calc(100px + env(safe-area-inset-bottom));
|
||||
}
|
||||
|
||||
@@ -23,10 +20,6 @@
|
||||
/* ─── 录入区 ─── */
|
||||
.input-section {
|
||||
margin-bottom: 20px;
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
padding: 20px;
|
||||
box-shadow: $shadow-md;
|
||||
}
|
||||
|
||||
.input-group {
|
||||
@@ -130,11 +123,7 @@
|
||||
}
|
||||
|
||||
.trend-empty {
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
padding: 24px;
|
||||
text-align: center;
|
||||
box-shadow: $shadow-sm;
|
||||
}
|
||||
|
||||
.trend-empty-text {
|
||||
@@ -143,10 +132,7 @@
|
||||
}
|
||||
|
||||
.trend-chart {
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
padding: 16px;
|
||||
box-shadow: $shadow-sm;
|
||||
}
|
||||
|
||||
.trend-bars {
|
||||
@@ -217,10 +203,6 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
padding: 16px;
|
||||
box-shadow: $shadow-sm;
|
||||
|
||||
&:active {
|
||||
opacity: 0.85;
|
||||
@@ -266,11 +248,6 @@
|
||||
|
||||
/* ─── 健康资讯入口 ─── */
|
||||
.article-entry {
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
padding: 16px;
|
||||
box-shadow: $shadow-sm;
|
||||
|
||||
&:active {
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@ import Loading from '../../components/Loading';
|
||||
import ErrorState from '../../components/ErrorState';
|
||||
import GuestGuard from '../../components/GuestGuard';
|
||||
import SegmentTabs from '../../components/SegmentTabs';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import ContentCard from '@/components/ui/ContentCard';
|
||||
import { useHealthData, VITAL_TABS, type VitalType } from './useHealthData';
|
||||
import './index.scss';
|
||||
|
||||
@@ -48,12 +50,12 @@ export default function Health() {
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<View className={`health-page ${modeClass}`}>
|
||||
<PageShell padding="md" safeBottom={false} scroll={false} className={`health-page ${modeClass}`}>
|
||||
<View className='health-header'>
|
||||
<Text className='health-title'>健康数据</Text>
|
||||
</View>
|
||||
<ErrorState onRetry={fetchData} />
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -162,7 +164,7 @@ export default function Health() {
|
||||
const dayLabels = ['日', '一', '二', '三', '四', '五', '六'];
|
||||
|
||||
return (
|
||||
<View className={`health-page ${modeClass}`}>
|
||||
<PageShell padding="md" safeBottom={false} scroll={false} className={`health-page ${modeClass}`}>
|
||||
<View className='health-header'>
|
||||
<Text className='health-title'>健康数据</Text>
|
||||
</View>
|
||||
@@ -199,7 +201,7 @@ export default function Health() {
|
||||
|
||||
<SegmentTabs tabs={VITAL_TABS} activeKey={activeTab} onChange={handleTabChange} variant="pill" />
|
||||
|
||||
<View className='input-section'>
|
||||
<ContentCard variant="elevated">
|
||||
{activeTab === 'blood_pressure' && (
|
||||
<View className='input-group'>
|
||||
<Text className='input-label'>收缩压(高压)</Text>
|
||||
@@ -281,18 +283,18 @@ export default function Health() {
|
||||
<View className='save-btn' onClick={handleSave}>
|
||||
<Text className='save-btn-text'>{saving ? '保存中...' : '保存'}</Text>
|
||||
</View>
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
<View className='trend-section'>
|
||||
<Text className='section-title'>近 7 天趋势</Text>
|
||||
{trendLoading ? (
|
||||
<Loading />
|
||||
) : trendData.length === 0 ? (
|
||||
<View className='trend-empty'>
|
||||
<ContentCard padding="md">
|
||||
<Text className='trend-empty-text'>暂无趋势数据</Text>
|
||||
</View>
|
||||
</ContentCard>
|
||||
) : (
|
||||
<View className='trend-chart'>
|
||||
<ContentCard padding="md">
|
||||
<View className='trend-bars'>
|
||||
{getThresholdValue(activeTab, thresholds) && (() => {
|
||||
const tv = getThresholdValue(activeTab, thresholds)!;
|
||||
@@ -319,16 +321,15 @@ export default function Health() {
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
</View>
|
||||
</ContentCard>
|
||||
)}
|
||||
</View>
|
||||
|
||||
<View
|
||||
className='article-entry'
|
||||
onClick={() => Taro.navigateTo({ url: '/pages/article/index' })}
|
||||
<ContentCard
|
||||
onPress={() => Taro.navigateTo({ url: '/pages/article/index' })}
|
||||
>
|
||||
<Text className='article-entry-text'>最新健康资讯 ›</Text>
|
||||
</View>
|
||||
</View>
|
||||
</ContentCard>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,9 +6,6 @@
|
||||
═══════════════════════════════════════ */
|
||||
|
||||
.home-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding: 20px 24px 100px;
|
||||
padding-bottom: calc(100px + env(safe-area-inset-bottom));
|
||||
}
|
||||
|
||||
@@ -69,10 +66,6 @@
|
||||
|
||||
/* ─── 今日体征进度 ─── */
|
||||
.checkin-card {
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
box-shadow: $shadow-md;
|
||||
padding: 20px;
|
||||
margin-bottom: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -140,11 +133,6 @@
|
||||
}
|
||||
|
||||
.vital-card {
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
padding: 14px 16px;
|
||||
box-shadow: $shadow-sm;
|
||||
|
||||
&:active {
|
||||
opacity: 0.7;
|
||||
}
|
||||
@@ -314,8 +302,6 @@
|
||||
═══════════════════════════════════════ */
|
||||
|
||||
.guest-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding-bottom: calc(120px + env(safe-area-inset-bottom));
|
||||
}
|
||||
|
||||
@@ -393,10 +379,7 @@
|
||||
}
|
||||
|
||||
.guest-article-card {
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
overflow: hidden;
|
||||
box-shadow: $shadow-sm;
|
||||
display: flex;
|
||||
|
||||
&:active {
|
||||
@@ -449,10 +432,6 @@
|
||||
/* ─── 底部登录引导 ─── */
|
||||
.guest-login-prompt {
|
||||
margin: 24px 24px 0;
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
padding: 20px;
|
||||
box-shadow: $shadow-md;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
|
||||
@@ -10,6 +10,8 @@ import { api } from '@/services/request';
|
||||
import type { Article } from '@/services/article';
|
||||
import ProgressRing from '../../components/ProgressRing';
|
||||
import Loading from '../../components/Loading';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import ContentCard from '@/components/ui/ContentCard';
|
||||
import { useHomeData, type ReminderItem } from './useHomeData';
|
||||
import './index.scss';
|
||||
|
||||
@@ -83,7 +85,7 @@ function GuestHome({ modeClass }: { modeClass: string }) {
|
||||
const slides = banners.length > 0 ? banners : FALLBACK_SLIDES;
|
||||
|
||||
return (
|
||||
<View className={`guest-page ${modeClass}`}>
|
||||
<PageShell padding="none" safeBottom={false} scroll={false} className={`guest-page ${modeClass}`}>
|
||||
<Swiper
|
||||
className='guest-swiper'
|
||||
indicatorDots
|
||||
@@ -116,10 +118,11 @@ function GuestHome({ modeClass }: { modeClass: string }) {
|
||||
{articles.length > 0 ? (
|
||||
<View className='guest-articles'>
|
||||
{articles.map((article) => (
|
||||
<View
|
||||
className='guest-article-card'
|
||||
<ContentCard
|
||||
key={article.id}
|
||||
onClick={() => Taro.navigateTo({ url: `/pages/article/detail/index?id=${article.id}` })}
|
||||
onPress={() => Taro.navigateTo({ url: `/pages/article/detail/index?id=${article.id}` })}
|
||||
activeFeedback="opacity"
|
||||
padding="none"
|
||||
>
|
||||
{article.cover_image && (
|
||||
<Image className='guest-article-cover' src={article.cover_image} mode='aspectFill' />
|
||||
@@ -130,34 +133,40 @@ function GuestHome({ modeClass }: { modeClass: string }) {
|
||||
{article.summary || '点击查看详情'}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</ContentCard>
|
||||
))}
|
||||
</View>
|
||||
) : (
|
||||
<View className='guest-articles'>
|
||||
<View className='guest-article-card'>
|
||||
<Text className='guest-article-title'>健康数据管理</Text>
|
||||
<Text className='guest-article-summary'>记录并追踪您的体征数据</Text>
|
||||
</View>
|
||||
<View className='guest-article-card'>
|
||||
<Text className='guest-article-title'>智能预约排班</Text>
|
||||
<Text className='guest-article-summary'>在线预约透析和治疗</Text>
|
||||
</View>
|
||||
<View className='guest-article-card'>
|
||||
<Text className='guest-article-title'>AI 健康分析</Text>
|
||||
<Text className='guest-article-summary'>个性化健康趋势解读</Text>
|
||||
</View>
|
||||
<ContentCard padding="none">
|
||||
<View className='guest-article-body'>
|
||||
<Text className='guest-article-title'>健康数据管理</Text>
|
||||
<Text className='guest-article-summary'>记录并追踪您的体征数据</Text>
|
||||
</View>
|
||||
</ContentCard>
|
||||
<ContentCard padding="none">
|
||||
<View className='guest-article-body'>
|
||||
<Text className='guest-article-title'>智能预约排班</Text>
|
||||
<Text className='guest-article-summary'>在线预约透析和治疗</Text>
|
||||
</View>
|
||||
</ContentCard>
|
||||
<ContentCard padding="none">
|
||||
<View className='guest-article-body'>
|
||||
<Text className='guest-article-title'>AI 健康分析</Text>
|
||||
<Text className='guest-article-summary'>个性化健康趋势解读</Text>
|
||||
</View>
|
||||
</ContentCard>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
|
||||
<View className='guest-login-prompt'>
|
||||
<ContentCard variant="elevated">
|
||||
<Text className='guest-login-text'>登录后即可使用完整健康管理服务</Text>
|
||||
<View className='guest-login-btn' onClick={navigateToLogin}>
|
||||
<Text className='guest-login-btn-text'>立即登录</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</ContentCard>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -177,7 +186,7 @@ function HomeDashboard({ modeClass }: { modeClass: string }) {
|
||||
};
|
||||
|
||||
return (
|
||||
<View className={`home-page ${modeClass}`}>
|
||||
<PageShell padding="md" safeBottom={false} scroll={false} className={`home-page ${modeClass}`}>
|
||||
<View className='greeting-section'>
|
||||
<View className='greeting-left'>
|
||||
<Text className='greeting-text'>{greeting},{displayName}</Text>
|
||||
@@ -191,7 +200,7 @@ function HomeDashboard({ modeClass }: { modeClass: string }) {
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View className='checkin-card' onClick={() => Taro.switchTab({ url: '/pages/health/index' })}>
|
||||
<ContentCard variant="elevated" onPress={() => Taro.switchTab({ url: '/pages/health/index' })}>
|
||||
<View className='checkin-left'>
|
||||
<ProgressRing percent={progressPercent} />
|
||||
</View>
|
||||
@@ -207,7 +216,7 @@ function HomeDashboard({ modeClass }: { modeClass: string }) {
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
<View className='vitals-section'>
|
||||
<Text className='section-title'>今日体征</Text>
|
||||
@@ -218,10 +227,10 @@ function HomeDashboard({ modeClass }: { modeClass: string }) {
|
||||
{healthItems.map((item) => {
|
||||
const tag = getStatusTag(item.status);
|
||||
return (
|
||||
<View
|
||||
className='vital-card'
|
||||
<ContentCard
|
||||
key={item.label}
|
||||
onClick={() => Taro.navigateTo({ url: `/pages/pkg-health/trend/index?indicator=${item.indicator}` })}
|
||||
onPress={() => Taro.navigateTo({ url: `/pages/pkg-health/trend/index?indicator=${item.indicator}` })}
|
||||
activeFeedback="opacity"
|
||||
>
|
||||
<Text className='vital-label'>{item.label}</Text>
|
||||
<View className='vital-value-row'>
|
||||
@@ -232,7 +241,7 @@ function HomeDashboard({ modeClass }: { modeClass: string }) {
|
||||
{tag && <Text className={`vital-tag ${tag.cls}`}>{tag.label}</Text>}
|
||||
{!item.status && <Text className='vital-tag tag-empty'>未记录</Text>}
|
||||
</View>
|
||||
</View>
|
||||
</ContentCard>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
@@ -270,7 +279,7 @@ function HomeDashboard({ modeClass }: { modeClass: string }) {
|
||||
<Text className='action-btn-text'>预约挂号</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
@import '../../styles/variables.scss';
|
||||
|
||||
.legal-page {
|
||||
min-height: 100vh;
|
||||
background: $card;
|
||||
padding: 32px 24px;
|
||||
padding-bottom: 60px;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { View, Text, RichText } from '@tarojs/components';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import './index.scss';
|
||||
|
||||
const PRIVACY_CONTENT = `
|
||||
@@ -48,11 +49,11 @@ const PRIVACY_CONTENT = `
|
||||
|
||||
export default function PrivacyPolicy() {
|
||||
return (
|
||||
<View className='legal-page'>
|
||||
<PageShell className='legal-page' scroll={false}>
|
||||
<RichText className='legal-content' nodes={PRIVACY_CONTENT} />
|
||||
<View className='legal-footer'>
|
||||
<Text className='legal-footer-text'>如有疑问,请联系客服</Text>
|
||||
</View>
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { View, Text, RichText } from '@tarojs/components';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import './index.scss';
|
||||
|
||||
const AGREEMENT_CONTENT = `
|
||||
@@ -34,11 +35,11 @@ const AGREEMENT_CONTENT = `
|
||||
|
||||
export default function UserAgreement() {
|
||||
return (
|
||||
<View className='legal-page'>
|
||||
<PageShell className='legal-page' scroll={false}>
|
||||
<RichText className='legal-content' nodes={AGREEMENT_CONTENT} />
|
||||
<View className='legal-footer'>
|
||||
<Text className='legal-footer-text'>如有疑问,请联系客服</Text>
|
||||
</View>
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
@import '../../styles/variables.scss';
|
||||
@import '../../styles/mixins.scss';
|
||||
|
||||
.login-scroll {
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.login-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
// PageShell 接管 min-height, background, scroll
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { useState } from 'react';
|
||||
import { View, Text, Button, ScrollView } from '@tarojs/components';
|
||||
import { View, Text, Button } from '@tarojs/components';
|
||||
import Taro from '@tarojs/taro';
|
||||
import { useAuthStore } from '../../stores/auth';
|
||||
import { useElderClass } from '../../hooks/useElderClass';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import './index.scss';
|
||||
|
||||
const IS_DEV = process.env.NODE_ENV !== 'production';
|
||||
@@ -95,8 +96,7 @@ export default function Login() {
|
||||
};
|
||||
|
||||
return (
|
||||
<ScrollView scrollY className={`login-scroll ${loginClass}`}>
|
||||
<View className='login-page'>
|
||||
<PageShell padding="none" scroll className={`login-page ${loginClass}`}>
|
||||
{/* 品牌区 */}
|
||||
<View className='login-brand'>
|
||||
<View className='login-logo'>
|
||||
@@ -155,7 +155,6 @@ export default function Login() {
|
||||
暂不登录,先看看
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</ScrollView>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
@import '../../styles/mixins.scss';
|
||||
|
||||
.mall-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding-bottom: calc(120px + env(safe-area-inset-bottom));
|
||||
}
|
||||
|
||||
@@ -121,10 +119,7 @@
|
||||
}
|
||||
|
||||
.product-card {
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
overflow: hidden;
|
||||
box-shadow: $shadow-sm;
|
||||
|
||||
&:active {
|
||||
opacity: 0.7;
|
||||
|
||||
@@ -10,6 +10,8 @@ import Loading from '../../components/Loading';
|
||||
import ErrorState from '../../components/ErrorState';
|
||||
import EmptyState from '../../components/EmptyState';
|
||||
import { useElderClass } from '../../hooks/useElderClass';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import ContentCard from '@/components/ui/ContentCard';
|
||||
import './index.scss';
|
||||
|
||||
const PRODUCT_TYPE_TABS = [
|
||||
@@ -137,7 +139,7 @@ export default function Mall() {
|
||||
|
||||
if (noProfile) {
|
||||
return (
|
||||
<View className={`mall-page ${modeClass}`}>
|
||||
<PageShell padding="md" safeBottom={false} scroll={false} className={`mall-page ${modeClass}`}>
|
||||
<EmptyState
|
||||
icon='档'
|
||||
text='请先完善个人档案'
|
||||
@@ -145,12 +147,12 @@ export default function Mall() {
|
||||
actionText='去建档'
|
||||
onAction={() => Taro.navigateTo({ url: '/pages/pkg-profile/family-add/index' })}
|
||||
/>
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<View className={`mall-page ${modeClass}`}>
|
||||
<PageShell padding="none" safeBottom={false} scroll={false} className={`mall-page ${modeClass}`}>
|
||||
{/* 积分余额卡片 */}
|
||||
<View className='mall-header'>
|
||||
<View className='points-card'>
|
||||
@@ -197,7 +199,7 @@ export default function Mall() {
|
||||
) : (
|
||||
<View className='product-grid'>
|
||||
{products.map((item) => (
|
||||
<View className='product-card' key={item.id} onClick={() => handleProductClick(item)}>
|
||||
<ContentCard key={item.id} onPress={() => handleProductClick(item)} activeFeedback="opacity" padding="none">
|
||||
<View className={`product-image ${TYPE_BG[item.product_type] || ''}`}>
|
||||
<Text className='product-image-char'>
|
||||
{item.product_type === 'physical' ? '物' : item.product_type === 'service' ? '券' : '权'}
|
||||
@@ -217,7 +219,7 @@ export default function Mall() {
|
||||
) : null}
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</ContentCard>
|
||||
))}
|
||||
{loading && <Loading />}
|
||||
{!loading && products.length >= total && total > 0 && (
|
||||
@@ -225,6 +227,6 @@ export default function Mall() {
|
||||
)}
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
@import '../../styles/mixins.scss';
|
||||
|
||||
.messages-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
// PageShell 接管 min-height, background
|
||||
padding: 20px 24px 100px;
|
||||
padding-bottom: calc(100px + env(safe-area-inset-bottom));
|
||||
}
|
||||
@@ -91,14 +90,7 @@
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
align-items: center;
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
padding: 16px;
|
||||
box-shadow: $shadow-sm;
|
||||
|
||||
&:active {
|
||||
opacity: 0.85;
|
||||
}
|
||||
// ContentCard 接管 background, border-radius, padding, box-shadow, active feedback
|
||||
}
|
||||
|
||||
.consult-card-muted {
|
||||
@@ -188,10 +180,7 @@
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
align-items: flex-start;
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
padding: 16px;
|
||||
box-shadow: $shadow-sm;
|
||||
// ContentCard 接管 background, border-radius, padding, box-shadow
|
||||
}
|
||||
|
||||
.notify-card-muted {
|
||||
|
||||
@@ -10,6 +10,8 @@ import GuestGuard from '../../components/GuestGuard';
|
||||
import { useAuthStore } from '../../stores/auth';
|
||||
import { useElderClass } from '../../hooks/useElderClass';
|
||||
import { usePageData } from '@/hooks/usePageData';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import ContentCard from '@/components/ui/ContentCard';
|
||||
import './index.scss';
|
||||
|
||||
type MsgTab = 'consultation' | 'notification';
|
||||
@@ -116,7 +118,7 @@ export default function Messages() {
|
||||
const unreadConsultCount = sessions.filter((s) => s.unread_count_patient > 0).length;
|
||||
|
||||
return (
|
||||
<View className={`messages-page ${modeClass}`}>
|
||||
<PageShell safeBottom={false} scroll={false} className={`messages-page ${modeClass}`}>
|
||||
{/* 页头 */}
|
||||
<View className='messages-header'>
|
||||
<Text className='messages-title'>消息</Text>
|
||||
@@ -160,10 +162,11 @@ export default function Messages() {
|
||||
const doctorName = session.last_message?.slice(0, 1) || '医';
|
||||
const hasUnread = session.unread_count_patient > 0;
|
||||
return (
|
||||
<View
|
||||
<ContentCard
|
||||
key={session.id}
|
||||
onPress={() => Taro.navigateTo({ url: `/pages/pkg-consultation/detail/index?id=${session.id}` })}
|
||||
padding="sm"
|
||||
className={`consult-card ${hasUnread ? '' : 'consult-card-muted'}`}
|
||||
onClick={() => Taro.navigateTo({ url: `/pages/pkg-consultation/detail/index?id=${session.id}` })}
|
||||
>
|
||||
<View className={`consult-avatar ${hasUnread ? 'consult-avatar-active' : ''}`}>
|
||||
<Text className='consult-avatar-char'>{doctorName}</Text>
|
||||
@@ -188,7 +191,7 @@ export default function Messages() {
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</ContentCard>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
@@ -207,7 +210,7 @@ export default function Messages() {
|
||||
const cfg = NOTIFY_ICONS[n.type] || NOTIFY_ICONS.report;
|
||||
const isUnread = !n.read;
|
||||
return (
|
||||
<View key={n.id} className={`notify-card ${isUnread ? '' : 'notify-card-muted'}`}>
|
||||
<ContentCard key={n.id} padding="sm" activeFeedback="none" className={`notify-card ${isUnread ? '' : 'notify-card-muted'}`}>
|
||||
<View className={`notify-icon ${cfg.cls}`}>
|
||||
<Text className={`notify-icon-char ${cfg.cls}`}>{cfg.icon}</Text>
|
||||
</View>
|
||||
@@ -219,7 +222,7 @@ export default function Messages() {
|
||||
<Text className='notify-desc'>{n.desc}</Text>
|
||||
</View>
|
||||
{isUnread && <View className='notify-dot' />}
|
||||
</View>
|
||||
</ContentCard>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
@@ -228,6 +231,6 @@ export default function Messages() {
|
||||
</>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,17 +2,11 @@
|
||||
@import '../../../styles/mixins.scss';
|
||||
|
||||
.elder-mode-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding: 24px;
|
||||
// PageShell 接管 min-height, background, padding
|
||||
}
|
||||
|
||||
.elder-mode-card {
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
padding: 24px;
|
||||
box-shadow: $shadow-md;
|
||||
margin-bottom: 20px;
|
||||
// ContentCard 接管 background, border-radius, padding, box-shadow, margin-bottom
|
||||
}
|
||||
|
||||
.elder-mode-header {
|
||||
@@ -108,10 +102,7 @@
|
||||
}
|
||||
|
||||
.elder-mode-preview-card {
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
padding: 20px;
|
||||
box-shadow: $shadow-sm;
|
||||
// ContentCard 接管 background, border-radius, padding, box-shadow
|
||||
}
|
||||
|
||||
.elder-mode-preview-sample {
|
||||
|
||||
@@ -2,6 +2,8 @@ import { View, Text } from '@tarojs/components';
|
||||
import Taro from '@tarojs/taro';
|
||||
import { useUIStore } from '../../../stores/ui';
|
||||
import { useElderClass } from '../../../hooks/useElderClass';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import ContentCard from '@/components/ui/ContentCard';
|
||||
import './index.scss';
|
||||
|
||||
export default function ElderMode() {
|
||||
@@ -21,8 +23,8 @@ export default function ElderMode() {
|
||||
};
|
||||
|
||||
return (
|
||||
<View className={`elder-mode-page ${modeClass}`}>
|
||||
<View className='elder-mode-card'>
|
||||
<PageShell className={`elder-mode-page ${modeClass}`}>
|
||||
<ContentCard variant="elevated" className='elder-mode-card'>
|
||||
<View className='elder-mode-header'>
|
||||
<Text className='elder-mode-icon'>老</Text>
|
||||
<View className='elder-mode-info'>
|
||||
@@ -42,19 +44,19 @@ export default function ElderMode() {
|
||||
<View className='elder-mode-switch-thumb' />
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
<View className='elder-mode-preview'>
|
||||
<Text className='elder-mode-preview-title'>效果预览</Text>
|
||||
<View className='elder-mode-preview-card'>
|
||||
<ContentCard padding="lg" className='elder-mode-preview-card'>
|
||||
<Text className={`elder-mode-preview-sample ${isElder ? 'elder-mode-preview-sample--large' : ''}`}>
|
||||
{isElder ? '长辈模式字体示例' : '标准模式字体示例'}
|
||||
</Text>
|
||||
<Text className='elder-mode-preview-note'>
|
||||
{isElder ? '字号放大 1.3 倍,间距放大 1.2 倍' : '正常字号和间距'}
|
||||
</Text>
|
||||
</View>
|
||||
</ContentCard>
|
||||
</View>
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,21 +2,14 @@
|
||||
@import '../../styles/mixins.scss';
|
||||
|
||||
.profile-page {
|
||||
min-height: 100vh;
|
||||
background: $bg;
|
||||
padding: 20px 24px 100px;
|
||||
padding-bottom: calc(100px + env(safe-area-inset-bottom));
|
||||
}
|
||||
|
||||
/* ─── 用户信息卡片 ─── */
|
||||
.profile-user-card {
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
box-shadow: $shadow-md;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
@@ -70,11 +63,7 @@
|
||||
|
||||
.stat-card {
|
||||
flex: 1;
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
padding: 16px;
|
||||
text-align: center;
|
||||
box-shadow: $shadow-sm;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
@@ -118,10 +107,7 @@
|
||||
}
|
||||
|
||||
.menu-group-card {
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
overflow: hidden;
|
||||
box-shadow: $shadow-sm;
|
||||
}
|
||||
|
||||
.menu-item {
|
||||
|
||||
@@ -7,6 +7,8 @@ import { useUIStore } from '../../stores/ui';
|
||||
import { navigateToLogin } from '../../utils/navigate';
|
||||
import { usePageData } from '@/hooks/usePageData';
|
||||
import Loading from '../../components/Loading';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import ContentCard from '@/components/ui/ContentCard';
|
||||
import './index.scss';
|
||||
|
||||
interface MenuItem {
|
||||
@@ -123,10 +125,10 @@ export default function Profile() {
|
||||
const displayInitial = (user?.display_name || user?.username || '用').charAt(0);
|
||||
|
||||
return (
|
||||
<View className={`profile-page ${modeClass}`}>
|
||||
<PageShell padding="md" safeBottom={false} scroll={false} className={`profile-page ${modeClass}`}>
|
||||
{/* 用户信息卡片 */}
|
||||
{isGuest ? (
|
||||
<View className='profile-user-card' onClick={navigateToLogin}>
|
||||
<ContentCard variant="elevated" onPress={navigateToLogin}>
|
||||
<View className='profile-avatar profile-avatar--guest'>
|
||||
<Text className='profile-avatar-char'>?</Text>
|
||||
</View>
|
||||
@@ -135,10 +137,10 @@ export default function Profile() {
|
||||
<Text className='profile-phone'>点击登录,开启健康管理之旅</Text>
|
||||
</View>
|
||||
<Text className='profile-arrow'>›</Text>
|
||||
</View>
|
||||
</ContentCard>
|
||||
) : (
|
||||
<>
|
||||
<View className='profile-user-card'>
|
||||
<ContentCard variant="elevated">
|
||||
<View className='profile-avatar'>
|
||||
<Text className='profile-avatar-char'>{displayInitial}</Text>
|
||||
</View>
|
||||
@@ -149,21 +151,21 @@ export default function Profile() {
|
||||
</Text>
|
||||
</View>
|
||||
<Text className='profile-arrow'>›</Text>
|
||||
</View>
|
||||
</ContentCard>
|
||||
|
||||
{/* 积分 + 打卡 */}
|
||||
{pointsLoading ? (
|
||||
<Loading />
|
||||
) : (
|
||||
<View className='profile-stats-row'>
|
||||
<View className='stat-card'>
|
||||
<ContentCard padding="sm">
|
||||
<Text className='stat-value stat-pri'>{(pointsAccount?.balance ?? 0).toLocaleString()}</Text>
|
||||
<Text className='stat-label'>健康积分</Text>
|
||||
</View>
|
||||
<View className='stat-card'>
|
||||
</ContentCard>
|
||||
<ContentCard padding="sm">
|
||||
<Text className='stat-value stat-acc'>{checkinInfo?.consecutive_days ?? 0}<Text className='stat-unit'>天</Text></Text>
|
||||
<Text className='stat-label'>连续打卡</Text>
|
||||
</View>
|
||||
</ContentCard>
|
||||
</View>
|
||||
)}
|
||||
</>
|
||||
@@ -173,7 +175,7 @@ export default function Profile() {
|
||||
{groups.map((group) => (
|
||||
<View className='menu-group' key={group.title}>
|
||||
<Text className='menu-group-title'>{group.title}</Text>
|
||||
<View className='menu-group-card'>
|
||||
<ContentCard padding="none">
|
||||
{group.items.map((item, idx) => (
|
||||
<View
|
||||
className='menu-item'
|
||||
@@ -188,7 +190,7 @@ export default function Profile() {
|
||||
<Text className='menu-arrow'>›</Text>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
</ContentCard>
|
||||
</View>
|
||||
))}
|
||||
|
||||
@@ -202,6 +204,6 @@ export default function Profile() {
|
||||
<Text className='logout-text'>退出登录</Text>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user