refactor(mp): 统一空状态为 EmptyState 组件 + 清理旧 Tab CSS

- 4 个页面的内联空状态替换为共享 EmptyState 组件
  (messages / action-inbox / pkg-health/alerts / mall)
- 清理 10 个页面的旧 Tab CSS(迁移到 SegmentTabs 后不再需要)
- 清理 elder-mode 中已删除的 mall-empty-state 引用
This commit is contained in:
iven
2026-05-15 23:11:34 +08:00
parent c06e986090
commit 3fb5a77ac0
17 changed files with 16 additions and 446 deletions

View File

@@ -20,51 +20,6 @@
color: $tx; color: $tx;
} }
/* ─── 类型 Tab ─── */
.vital-tabs {
display: flex;
padding: 0 0 16px;
gap: 8px;
}
.vital-tab {
flex: 1;
height: 48px;
border-radius: $r-sm;
background: $surface-alt;
@include flex-center;
position: relative;
&:active {
opacity: 0.85;
}
&.vital-tab-active {
background: $pri;
box-shadow: 0 2px 8px rgba(196, 98, 58, 0.25);
.vital-tab-text {
color: $white;
}
}
}
.vital-tab-text {
font-size: var(--tk-font-cap);
font-weight: 600;
color: $tx2;
}
.vital-tab-dot {
position: absolute;
top: 8px;
right: 8px;
width: 6px;
height: 6px;
border-radius: 50%;
background: $wrn;
}
/* ─── 录入区 ─── */ /* ─── 录入区 ─── */
.input-section { .input-section {
margin-bottom: 20px; margin-bottom: 20px;

View File

@@ -207,58 +207,3 @@
} }
} }
/* ─── 空状态 ─── */
.mall-empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 100px 40px;
}
.empty-icon {
width: 120px;
height: 120px;
border-radius: 50%;
background: $pri-l;
@include flex-center;
margin-bottom: 32px;
}
.empty-char {
font-family: 'Georgia', 'Times New Roman', serif;
font-size: var(--tk-font-hero);
font-weight: bold;
color: $pri;
line-height: 1;
}
.empty-title {
font-size: var(--tk-font-body-lg);
font-weight: 600;
color: $tx;
margin-bottom: 12px;
}
.empty-hint {
font-size: var(--tk-font-h1);
color: var(--tk-text-secondary);
text-align: center;
margin-bottom: 24px;
}
.empty-action {
background: $pri;
border-radius: $r;
padding: 16px 48px;
&:active {
opacity: 0.85;
}
}
.empty-action-text {
font-size: var(--tk-font-body-lg);
color: $white;
font-weight: 600;
}

View File

@@ -8,6 +8,7 @@ import { useAuthStore } from '../../stores/auth';
import { usePointsStore } from '../../stores/points'; import { usePointsStore } from '../../stores/points';
import Loading from '../../components/Loading'; import Loading from '../../components/Loading';
import ErrorState from '../../components/ErrorState'; import ErrorState from '../../components/ErrorState';
import EmptyState from '../../components/EmptyState';
import { useElderClass } from '../../hooks/useElderClass'; import { useElderClass } from '../../hooks/useElderClass';
import './index.scss'; import './index.scss';
@@ -137,16 +138,13 @@ export default function Mall() {
if (noProfile) { if (noProfile) {
return ( return (
<View className={`mall-page ${modeClass}`}> <View className={`mall-page ${modeClass}`}>
<View className='mall-empty-state'> <EmptyState
<View className='empty-icon'> icon='档'
<Text className='empty-char'></Text> text='请先完善个人档案'
</View> hint='建档后即可使用积分商城、签到等功能'
<Text className='empty-title'></Text> actionText='去建档'
<Text className='empty-hint'>使</Text> onAction={() => Taro.navigateTo({ url: '/pages/pkg-profile/family-add/index' })}
<View className='empty-action' onClick={() => Taro.navigateTo({ url: '/pages/pkg-profile/family-add/index' })}> />
<Text className='empty-action-text'></Text>
</View>
</View>
</View> </View>
); );
} }
@@ -195,13 +193,7 @@ export default function Mall() {
{error ? ( {error ? (
<ErrorState onRetry={() => loadAll()} /> <ErrorState onRetry={() => loadAll()} />
) : products.length === 0 && !loading ? ( ) : products.length === 0 && !loading ? (
<View className='mall-empty-state'> <EmptyState icon='礼' text='暂无商品' hint='更多好物即将上架' />
<View className='empty-icon'>
<Text className='empty-char'></Text>
</View>
<Text className='empty-title'></Text>
<Text className='empty-hint'></Text>
</View>
) : ( ) : (
<View className='product-grid'> <View className='product-grid'>
{products.map((item) => ( {products.map((item) => (

View File

@@ -86,19 +86,6 @@
gap: 8px; gap: 8px;
} }
.msg-empty {
background: $card;
border-radius: $r;
padding: 48px 24px;
text-align: center;
box-shadow: $shadow-sm;
}
.msg-empty-text {
font-size: var(--tk-font-cap);
color: $tx2;
}
/* ─── 咨询卡片 ─── */ /* ─── 咨询卡片 ─── */
.consult-card { .consult-card {
display: flex; display: flex;

View File

@@ -5,6 +5,7 @@ import { listConsultations, ConsultationSession } from '../../services/consultat
import { notificationService } from '../../services/notification'; import { notificationService } from '../../services/notification';
import Loading from '../../components/Loading'; import Loading from '../../components/Loading';
import ErrorState from '../../components/ErrorState'; import ErrorState from '../../components/ErrorState';
import EmptyState from '../../components/EmptyState';
import GuestGuard from '../../components/GuestGuard'; import GuestGuard from '../../components/GuestGuard';
import { useAuthStore } from '../../stores/auth'; import { useAuthStore } from '../../stores/auth';
import { useElderClass } from '../../hooks/useElderClass'; import { useElderClass } from '../../hooks/useElderClass';
@@ -152,9 +153,7 @@ export default function Messages() {
loading ? ( loading ? (
<Loading /> <Loading />
) : sessions.length === 0 ? ( ) : sessions.length === 0 ? (
<View className='msg-empty'> <EmptyState text='暂无咨询消息' />
<Text className='msg-empty-text'></Text>
</View>
) : ( ) : (
<View className='msg-list'> <View className='msg-list'>
{sessions.map((session) => { {sessions.map((session) => {
@@ -201,9 +200,7 @@ export default function Messages() {
loading ? ( loading ? (
<Loading /> <Loading />
) : notifications.length === 0 ? ( ) : notifications.length === 0 ? (
<View className='msg-empty'> <EmptyState text='暂无新通知' />
<Text className='msg-empty-text'></Text>
</View>
) : ( ) : (
<View className='msg-list'> <View className='msg-list'>
{notifications.map((n) => { {notifications.map((n) => {

View File

@@ -26,26 +26,6 @@
color: $tx2; color: $tx2;
} }
.alert-tabs {
display: flex;
gap: 12px;
margin-bottom: 24px;
}
.alert-tab {
padding: 10px 24px;
border-radius: $r-pill;
background: $bd-l;
font-size: var(--tk-font-h2);
color: $tx2;
transition: all 0.2s;
&--active {
background: $pri;
color: $card;
}
}
.alert-cards { .alert-cards {
display: flex; display: flex;
flex-direction: column; flex-direction: column;

View File

@@ -20,43 +20,6 @@
color: $tx; color: $tx;
} }
.tabs {
display: flex;
padding: 0 24px;
background: $card;
border-bottom: 1px solid $bd-l;
}
.tab {
flex: 1;
text-align: center;
padding: 20px 0;
position: relative;
&--active {
.tab-text {
color: $pri;
font-weight: bold;
}
&::after {
content: '';
position: absolute;
bottom: 0;
left: 25%;
right: 25%;
height: 4px;
background: $pri;
border-radius: $r-xs;
}
}
}
.tab-text {
font-size: var(--tk-font-h1);
color: $tx2;
}
.record-list { .record-list {
padding: 16px 24px; padding: 16px 24px;
} }

View File

@@ -20,43 +20,6 @@
color: $tx; color: $tx;
} }
.tabs {
display: flex;
padding: 0 24px;
background: $card;
border-bottom: 1px solid $bd-l;
}
.tab {
flex: 1;
text-align: center;
padding: 20px 0;
position: relative;
&--active {
.tab-text {
color: $pri;
font-weight: bold;
}
&::after {
content: '';
position: absolute;
bottom: 0;
left: 25%;
right: 25%;
height: 4px;
background: $pri;
border-radius: $r-xs;
}
}
}
.tab-text {
font-size: var(--tk-font-h1);
color: $tx2;
}
.prescription-list { .prescription-list {
padding: 16px 24px; padding: 16px 24px;
} }

View File

@@ -6,44 +6,6 @@
background: $bg; background: $bg;
} }
.inbox-tabs {
display: flex;
background: $card;
padding: 0 16px;
border-bottom: 1px solid $bd;
.inbox-tab {
flex: 1;
text-align: center;
padding: 12px 0;
min-height: 48px;
&.active {
.inbox-tab-text {
color: $pri;
font-weight: 600;
position: relative;
&::after {
content: '';
position: absolute;
bottom: -12px;
left: 30%;
right: 30%;
height: 3px;
background: $pri;
border-radius: $r-xs;
}
}
}
}
.inbox-tab-text {
font-size: var(--tk-font-cap);
color: $tx2;
}
}
.inbox-list { .inbox-list {
height: calc(100vh - 50px); height: calc(100vh - 50px);
padding: 12px; padding: 12px;
@@ -103,16 +65,6 @@
} }
} }
.inbox-empty {
text-align: center;
padding: 80px 0;
.inbox-empty-text {
font-size: var(--tk-font-cap);
color: $tx3;
}
}
.half-screen-dialog { .half-screen-dialog {
position: fixed; position: fixed;
bottom: 0; bottom: 0;

View File

@@ -11,6 +11,7 @@ import {
} from '@/services/action-inbox'; } from '@/services/action-inbox';
import Loading from '@/components/Loading'; import Loading from '@/components/Loading';
import ErrorState from '@/components/ErrorState'; import ErrorState from '@/components/ErrorState';
import EmptyState from '@/components/EmptyState';
import SegmentTabs from '@/components/SegmentTabs'; import SegmentTabs from '@/components/SegmentTabs';
import { useElderClass } from '../../../hooks/useElderClass'; import { useElderClass } from '../../../hooks/useElderClass';
import './index.scss'; import './index.scss';
@@ -124,9 +125,7 @@ export default function ActionInboxPage() {
{error ? ( {error ? (
<ErrorState onRetry={() => fetchItems(1, activeTab, true)} /> <ErrorState onRetry={() => fetchItems(1, activeTab, true)} />
) : items.length === 0 && !loading ? ( ) : items.length === 0 && !loading ? (
<View className="inbox-empty"> <EmptyState text='暂无待办事项' />
<Text className="inbox-empty-text"></Text>
</View>
) : ( ) : (
<ScrollView scrollY className="inbox-list"> <ScrollView scrollY className="inbox-list">
{items.map((item) => ( {items.map((item) => (

View File

@@ -6,38 +6,6 @@
background: $bg; background: $bg;
} }
.tabs {
display: flex;
background: $card;
padding: 0 16px;
border-bottom: 1px solid $bd;
}
.tab {
flex: 1;
text-align: center;
padding: 24px 0;
font-size: var(--tk-font-body-lg);
color: $tx2;
position: relative;
&--active {
color: $pri;
font-weight: 600;
&::after {
content: '';
position: absolute;
bottom: 0;
left: 30%;
right: 30%;
height: 4px;
background: $pri;
border-radius: $r-xs;
}
}
}
.session-list { .session-list {
padding: 20px 24px; padding: 20px 24px;
display: flex; display: flex;

View File

@@ -6,40 +6,6 @@
background: $bg; background: $bg;
} }
.tabs {
display: flex;
background: $card;
padding: 0 12px;
border-bottom: 1px solid $bd;
overflow-x: auto;
white-space: nowrap;
}
.tab {
display: inline-block;
padding: 24px 16px;
font-size: var(--tk-font-h1);
color: $tx2;
position: relative;
flex-shrink: 0;
&--active {
color: $pri;
font-weight: 600;
&::after {
content: '';
position: absolute;
bottom: 0;
left: 20%;
right: 20%;
height: 4px;
background: $pri;
border-radius: $r-xs;
}
}
}
.task-count { .task-count {
padding: 20px 28px; padding: 20px 28px;

View File

@@ -105,34 +105,3 @@
color: $tx; color: $tx;
line-height: 1.5; line-height: 1.5;
} }
.alerts-empty {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 120px 0;
}
.alerts-empty-text {
font-size: var(--tk-font-num);
color: var(--tk-text-secondary);
margin-bottom: 16px;
}
.alerts-empty-hint {
font-size: var(--tk-font-h1);
color: var(--tk-text-secondary);
}
.alerts-empty-action {
margin-top: 24px;
padding: 16px 48px;
background: $pri;
border-radius: $r-pill;
}
.alerts-empty-action-text {
color: $card;
font-size: var(--tk-font-body-lg);
}

View File

@@ -6,6 +6,7 @@ import { listPatientAlerts, type Alert } from '@/services/alert';
import { useAuthStore } from '@/stores/auth'; import { useAuthStore } from '@/stores/auth';
import Loading from '@/components/Loading'; import Loading from '@/components/Loading';
import ErrorState from '@/components/ErrorState'; import ErrorState from '@/components/ErrorState';
import EmptyState from '@/components/EmptyState';
import SegmentTabs from '@/components/SegmentTabs'; import SegmentTabs from '@/components/SegmentTabs';
import { useElderClass } from '../../../hooks/useElderClass'; import { useElderClass } from '../../../hooks/useElderClass';
import './index.scss'; import './index.scss';
@@ -98,7 +99,7 @@ export default function PatientAlerts() {
<SegmentTabs tabs={STATUS_TABS} activeKey={status} onChange={handleTabChange} variant="pill" /> <SegmentTabs tabs={STATUS_TABS} activeKey={status} onChange={handleTabChange} variant="pill" />
{alerts.length === 0 && !loading ? ( {alerts.length === 0 && !loading ? (
<ErrorState text='暂无告警记录' hint='您的各项指标正常' /> <EmptyState text='暂无告警记录' hint='您的各项指标正常' />
) : ( ) : (
<View className='alerts-list'> <View className='alerts-list'>
{alerts.map((item) => { {alerts.map((item) => {

View File

@@ -45,29 +45,6 @@
padding: 0 32px 28px; padding: 0 32px 28px;
} }
.trange-tab {
padding: 12px 32px;
border-radius: $r-pill;
background: $card;
box-shadow: $shadow-sm;
transition: all 0.2s;
}
.trange-tab-active {
background: $pri;
box-shadow: $shadow-md;
}
.trange-tab-text {
font-size: var(--tk-font-h2);
color: $tx2;
font-weight: 500;
}
.trange-tab-text-active {
color: $white;
}
/* ── chart card ── */ /* ── chart card ── */
.trend-chart-card { .trend-chart-card {
margin: 0 24px 20px; margin: 0 24px 20px;

View File

@@ -7,45 +7,6 @@
padding-bottom: 40px; padding-bottom: 40px;
} }
/* ===== 状态筛选标签 ===== */
.status-tabs {
display: flex;
gap: 0;
padding: 20px 24px 0;
background: $card;
margin-bottom: 16px;
border-radius: 0 0 $r-lg $r-lg;
}
.status-tab {
flex: 1;
@include flex-center;
padding: 16px 0;
position: relative;
&.active::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 40px;
height: 4px;
background: $pri;
border-radius: $r-xs;
}
}
.status-tab-text {
font-size: var(--tk-font-body-lg);
color: $tx3;
.status-tab.active & {
color: $pri;
font-weight: bold;
}
}
/* ===== 订单列表 ===== */ /* ===== 订单列表 ===== */
.order-list { .order-list {
padding: 0 24px; padding: 0 24px;

View File

@@ -124,9 +124,4 @@
.guest-login-btn { .guest-login-btn {
height: 64px; height: 64px;
} }
// ─── 积分商城空状态 ───
.mall-empty-state {
padding: 100px 40px;
}
} }