refactor(mp): 迁移商城+AI报告+预约列表+文章详情页 — 统一组件库

商城订单/积分兑换/积分明细、AI 报告列表、预约列表、
文章详情共 6 个页面迁移:
- 最外层容器 → PageShell
- SCSS 删除 min-height/background 通用样式
This commit is contained in:
iven
2026-05-16 01:33:42 +08:00
parent 37327a4da4
commit 466b6567d1
12 changed files with 36 additions and 50 deletions

View File

@@ -1,12 +1,7 @@
@import '../../../styles/variables.scss'; @import '../../../styles/variables.scss';
@import '../../../styles/mixins.scss'; @import '../../../styles/mixins.scss';
.ai-report-page { // PageShell 已接管min-height, background, padding
min-height: 100vh;
background: $bg;
padding: 24px;
padding-bottom: 40px;
}
.page-title { .page-title {
@include section-title; @include section-title;

View File

@@ -6,6 +6,7 @@ import { listAiAnalysis, type AiAnalysisItem } from '@/services/ai-analysis';
import Loading from '@/components/Loading'; import Loading from '@/components/Loading';
import EmptyState from '@/components/EmptyState'; import EmptyState from '@/components/EmptyState';
import { useElderClass } from '../../../hooks/useElderClass'; import { useElderClass } from '../../../hooks/useElderClass';
import PageShell from '@/components/ui/PageShell';
import './index.scss'; import './index.scss';
const TYPE_LABELS: Record<string, string> = { const TYPE_LABELS: Record<string, string> = {
@@ -61,14 +62,14 @@ export default function AiReportList() {
if (list.length === 0) { if (list.length === 0) {
return ( return (
<View className={`ai-report-page ${modeClass}`}> <PageShell className={modeClass}>
<EmptyState text='暂无 AI 分析报告' /> <EmptyState text='暂无 AI 分析报告' />
</View> </PageShell>
); );
} }
return ( return (
<View className={`ai-report-page ${modeClass}`}> <PageShell className={modeClass}>
<View className='page-title'>AI </View> <View className='page-title'>AI </View>
<ScrollView scrollY className='report-scroll' onScrollToLower={loadMore}> <ScrollView scrollY className='report-scroll' onScrollToLower={loadMore}>
{list.map((item) => { {list.map((item) => {
@@ -93,6 +94,6 @@ export default function AiReportList() {
{loading && <Loading />} {loading && <Loading />}
{!hasMore && list.length > 0 && <Text className='no-more'></Text>} {!hasMore && list.length > 0 && <Text className='no-more'></Text>}
</ScrollView> </ScrollView>
</View> </PageShell>
); );
} }

View File

@@ -1,9 +1,8 @@
@import '../../styles/variables.scss'; @import '../../styles/variables.scss';
@import '../../styles/mixins.scss'; @import '../../styles/mixins.scss';
// PageShell 已接管min-height, background, padding
.appointment-page { .appointment-page {
min-height: 100vh;
background: $bg;
padding-bottom: 160px; padding-bottom: 160px;
} }

View File

@@ -7,6 +7,7 @@ import type { Appointment } from '../../services/appointment';
import EmptyState from '../../components/EmptyState'; import EmptyState from '../../components/EmptyState';
import Loading from '../../components/Loading'; import Loading from '../../components/Loading';
import { useElderClass } from '../../hooks/useElderClass'; import { useElderClass } from '../../hooks/useElderClass';
import PageShell from '@/components/ui/PageShell';
import './index.scss'; import './index.scss';
const STATUS_MAP: Record<string, { label: string; className: string }> = { const STATUS_MAP: Record<string, { label: string; className: string }> = {
@@ -80,7 +81,7 @@ export default function AppointmentList() {
}; };
return ( return (
<View className={`appointment-page ${modeClass}`}> <PageShell className={modeClass}>
{/* 页面标题 */} {/* 页面标题 */}
<View className='page-header'> <View className='page-header'>
<Text className='page-title'></Text> <Text className='page-title'></Text>
@@ -146,6 +147,6 @@ export default function AppointmentList() {
<View className='fab-btn' onClick={goCreate}> <View className='fab-btn' onClick={goCreate}>
<Text className='fab-text'></Text> <Text className='fab-text'></Text>
</View> </View>
</View> </PageShell>
); );
} }

View File

@@ -1,11 +1,7 @@
@import '../../../styles/variables.scss'; @import '../../../styles/variables.scss';
@import '../../../styles/mixins.scss'; @import '../../../styles/mixins.scss';
.article-detail-page { // PageShell 已接管min-height, background, padding
min-height: 100vh;
background: $bg;
padding-bottom: 40px;
}
.article-header { .article-header {
background: $card; background: $card;

View File

@@ -7,6 +7,7 @@ import { trackEvent } from '@/services/analytics';
import { sanitizeHtml } from '@/utils/sanitize-html'; import { sanitizeHtml } from '@/utils/sanitize-html';
import { useElderClass } from '../../../hooks/useElderClass'; import { useElderClass } from '../../../hooks/useElderClass';
import { useAuthStore } from '../../../stores/auth'; import { useAuthStore } from '../../../stores/auth';
import PageShell from '@/components/ui/PageShell';
import './index.scss'; import './index.scss';
export default function ArticleDetail() { export default function ArticleDetail() {
@@ -44,26 +45,26 @@ export default function ArticleDetail() {
if (loading) { if (loading) {
return ( return (
<View className={`article-detail-page ${modeClass}`}> <PageShell className={modeClass}>
<View className='loading-state'> <View className='loading-state'>
<Text className='loading-text'>...</Text> <Text className='loading-text'>...</Text>
</View> </View>
</View> </PageShell>
); );
} }
if (!article) { if (!article) {
return ( return (
<View className={`article-detail-page ${modeClass}`}> <PageShell className={modeClass}>
<View className='empty-state'> <View className='empty-state'>
<Text className='empty-text'></Text> <Text className='empty-text'></Text>
</View> </View>
</View> </PageShell>
); );
} }
return ( return (
<View className={`article-detail-page ${modeClass}`}> <PageShell className={modeClass}>
{/* 文章头部 */} {/* 文章头部 */}
<View className='article-header'> <View className='article-header'>
<Text className='article-title'>{article.title}</Text> <Text className='article-title'>{article.title}</Text>
@@ -93,6 +94,6 @@ export default function ArticleDetail() {
nodes={sanitizeHtml(article.content || '')} nodes={sanitizeHtml(article.content || '')}
/> />
</View> </View>
</View> </PageShell>
); );
} }

View File

@@ -1,11 +1,7 @@
@import '../../../styles/variables.scss'; @import '../../../styles/variables.scss';
@import '../../../styles/mixins.scss'; @import '../../../styles/mixins.scss';
.detail-page { // PageShell 已接管min-height, background, padding
min-height: 100vh;
background: $bg;
padding-bottom: 40px;
}
/* ===== 余额卡片 ===== */ /* ===== 余额卡片 ===== */
.balance-card { .balance-card {

View File

@@ -8,6 +8,7 @@ import { usePointsStore } from '../../../stores/points';
import EmptyState from '../../../components/EmptyState'; import EmptyState from '../../../components/EmptyState';
import Loading from '../../../components/Loading'; import Loading from '../../../components/Loading';
import { useElderClass } from '../../../hooks/useElderClass'; import { useElderClass } from '../../../hooks/useElderClass';
import PageShell from '@/components/ui/PageShell';
import './index.scss'; import './index.scss';
const TYPE_TABS = [ const TYPE_TABS = [
@@ -109,7 +110,7 @@ export default function PointsDetail() {
const balance = account?.balance ?? 0; const balance = account?.balance ?? 0;
return ( return (
<View className={`detail-page ${modeClass}`}> <PageShell className={modeClass}>
{/* 余额卡片 */} {/* 余额卡片 */}
<View className='balance-card'> <View className='balance-card'>
<Text className='balance-label'></Text> <Text className='balance-label'></Text>
@@ -177,6 +178,6 @@ export default function PointsDetail() {
)} )}
</View> </View>
)} )}
</View> </PageShell>
); );
} }

View File

@@ -1,9 +1,8 @@
@import '../../../styles/variables.scss'; @import '../../../styles/variables.scss';
@import '../../../styles/mixins.scss'; @import '../../../styles/mixins.scss';
// PageShell 已接管min-height, background, padding
.exchange-page { .exchange-page {
min-height: 100vh;
background: $bg;
padding-bottom: 140px; padding-bottom: 140px;
} }

View File

@@ -11,6 +11,7 @@ import { usePointsStore } from '../../../stores/points';
import Loading from '../../../components/Loading'; import Loading from '../../../components/Loading';
import { useElderClass } from '../../../hooks/useElderClass'; import { useElderClass } from '../../../hooks/useElderClass';
import { useSafeTimeout } from '@/hooks/useSafeTimeout'; import { useSafeTimeout } from '@/hooks/useSafeTimeout';
import PageShell from '@/components/ui/PageShell';
import './index.scss'; import './index.scss';
const TYPE_INITIAL: Record<string, string> = { const TYPE_INITIAL: Record<string, string> = {
@@ -128,9 +129,9 @@ export default function ExchangeConfirm() {
if (loading) { if (loading) {
return ( return (
<View className={`exchange-page ${modeClass}`}> <PageShell className={modeClass}>
<Loading /> <Loading />
</View> </PageShell>
); );
} }
@@ -140,7 +141,7 @@ export default function ExchangeConfirm() {
const iconCls = TYPE_CLASS[productType] || 'product-icon-wrap--service'; const iconCls = TYPE_CLASS[productType] || 'product-icon-wrap--service';
return ( return (
<View className={`exchange-page ${modeClass}`}> <PageShell className={modeClass}>
{/* 商品预览卡片 */} {/* 商品预览卡片 */}
<View className='product-card'> <View className='product-card'>
<View className={`product-icon-wrap ${iconCls}`}> <View className={`product-icon-wrap ${iconCls}`}>
@@ -216,6 +217,6 @@ export default function ExchangeConfirm() {
</Text> </Text>
</View> </View>
</View> </View>
</View> </PageShell>
); );
} }

View File

@@ -1,11 +1,8 @@
@import '../../../styles/variables.scss'; @import '../../../styles/variables.scss';
@import '../../../styles/mixins.scss'; @import '../../../styles/mixins.scss';
.orders-page { // PageShell 已接管min-height, background, safe-bottom
min-height: 100vh; // ContentCard 已接管order-card 背景/圆角/阴影
background: $bg;
padding-bottom: 40px;
}
/* ===== 订单列表 ===== */ /* ===== 订单列表 ===== */
.order-list { .order-list {
@@ -13,11 +10,8 @@
} }
.order-card { .order-card {
background: $card;
border-radius: $r;
margin-bottom: 16px; margin-bottom: 16px;
overflow: hidden; overflow: hidden;
box-shadow: $shadow-sm;
} }
.order-header { .order-header {

View File

@@ -8,6 +8,8 @@ import EmptyState from '../../../components/EmptyState';
import ErrorState from '../../../components/ErrorState'; import ErrorState from '../../../components/ErrorState';
import Loading from '../../../components/Loading'; import Loading from '../../../components/Loading';
import SegmentTabs from '../../../components/SegmentTabs'; import SegmentTabs from '../../../components/SegmentTabs';
import PageShell from '@/components/ui/PageShell';
import ContentCard from '@/components/ui/ContentCard';
import { useElderClass } from '../../../hooks/useElderClass'; import { useElderClass } from '../../../hooks/useElderClass';
import './index.scss'; import './index.scss';
@@ -111,7 +113,7 @@ export default function MallOrders() {
}; };
return ( return (
<View className={`orders-page ${modeClass}`}> <PageShell padding="none" className={modeClass}>
{/* 状态筛选标签 */} {/* 状态筛选标签 */}
<SegmentTabs tabs={STATUS_TABS} activeKey={activeTab} onChange={handleTabChange} variant="underline" /> <SegmentTabs tabs={STATUS_TABS} activeKey={activeTab} onChange={handleTabChange} variant="underline" />
@@ -131,7 +133,7 @@ export default function MallOrders() {
{orders.map((order) => { {orders.map((order) => {
const statusCfg = getStatusConfig(order.status); const statusCfg = getStatusConfig(order.status);
return ( return (
<View className='order-card' key={order.id}> <ContentCard className='order-card' key={order.id}>
<View className='order-header'> <View className='order-header'>
<Text className='order-product'> {order.product_id.slice(0, 8)}</Text> <Text className='order-product'> {order.product_id.slice(0, 8)}</Text>
<View <View
@@ -162,7 +164,7 @@ export default function MallOrders() {
</View> </View>
)} )}
</View> </View>
</View> </ContentCard>
); );
})} })}
{loading && <Loading />} {loading && <Loading />}
@@ -171,6 +173,6 @@ export default function MallOrders() {
)} )}
</View> </View>
)} )}
</View> </PageShell>
); );
} }