refactor(mp): 迁移剩余 8 特殊页面到统一组件库

- 首页/健康/我的/商城/消息 TabBar 页面使用 PageShell 替代手写容器
- 登录/法律条款/关怀模式设置页使用 PageShell 替代手写容器
- 各页面卡片统一使用 ContentCard 组件
- 清理页面 SCSS 中的 min-height/background/padding 样板代码
- 66 个小程序页面全部完成统一组件迁移
This commit is contained in:
iven
2026-05-16 01:55:28 +08:00
parent c6bffd4019
commit 184bd0ea03
17 changed files with 109 additions and 179 deletions

View File

@@ -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;
}

View File

@@ -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>
);
}

View File

@@ -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;

View File

@@ -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>
);
}

View File

@@ -1,9 +1,7 @@
@import '../../styles/variables.scss';
.legal-page {
min-height: 100vh;
background: $card;
padding: 32px 24px;
padding-bottom: 60px;
}

View File

@@ -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>
);
}

View File

@@ -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>
);
}

View File

@@ -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;

View File

@@ -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>
);
}

View File

@@ -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;

View File

@@ -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>
);
}

View File

@@ -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 {

View File

@@ -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>
);
}

View File

@@ -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 {

View File

@@ -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>
);
}

View File

@@ -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 {

View File

@@ -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>
);
}