diff --git a/apps/miniprogram/src/app.config.ts b/apps/miniprogram/src/app.config.ts
index 1357e69..2e158f6 100644
--- a/apps/miniprogram/src/app.config.ts
+++ b/apps/miniprogram/src/app.config.ts
@@ -1,6 +1,7 @@
export default defineAppConfig({
pages: [
'pages/index/index',
+ 'pages/login/index',
'pages/health/index',
'pages/health/input/index',
'pages/health/trend/index',
@@ -20,7 +21,6 @@ export default defineAppConfig({
'pages/profile/followups/index',
'pages/profile/medication/index',
'pages/profile/settings/index',
- 'pages/login/index',
],
tabBar: {
color: '#94A3B8',
diff --git a/apps/miniprogram/src/components/EmptyState/index.scss b/apps/miniprogram/src/components/EmptyState/index.scss
new file mode 100644
index 0000000..9741d02
--- /dev/null
+++ b/apps/miniprogram/src/components/EmptyState/index.scss
@@ -0,0 +1,37 @@
+@import '../../styles/variables.scss';
+
+.empty-state {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding: 120px 40px;
+}
+
+.empty-state-icon {
+ font-size: 80px;
+ margin-bottom: 24px;
+}
+
+.empty-state-text {
+ font-size: 30px;
+ color: $tx2;
+ margin-bottom: 8px;
+}
+
+.empty-state-hint {
+ font-size: 24px;
+ color: $tx3;
+ margin-bottom: 32px;
+}
+
+.empty-state-action {
+ background: $pri;
+ border-radius: 40px;
+ padding: 16px 48px;
+}
+
+.empty-state-action-text {
+ font-size: 28px;
+ color: #fff;
+}
diff --git a/apps/miniprogram/src/components/EmptyState/index.tsx b/apps/miniprogram/src/components/EmptyState/index.tsx
new file mode 100644
index 0000000..4bdee10
--- /dev/null
+++ b/apps/miniprogram/src/components/EmptyState/index.tsx
@@ -0,0 +1,32 @@
+import React from 'react';
+import { View, Text } from '@tarojs/components';
+import './index.scss';
+
+interface EmptyStateProps {
+ icon?: string;
+ text: string;
+ hint?: string;
+ actionText?: string;
+ onAction?: () => void;
+}
+
+export default function EmptyState({
+ icon = '📭',
+ text,
+ hint,
+ actionText,
+ onAction,
+}: EmptyStateProps) {
+ return (
+
+ {icon}
+ {text}
+ {hint && {hint}}
+ {actionText && onAction && (
+
+ {actionText}
+
+ )}
+
+ );
+}
diff --git a/apps/miniprogram/src/components/ErrorState/index.scss b/apps/miniprogram/src/components/ErrorState/index.scss
new file mode 100644
index 0000000..4d6a4af
--- /dev/null
+++ b/apps/miniprogram/src/components/ErrorState/index.scss
@@ -0,0 +1,32 @@
+@import '../../styles/variables.scss';
+
+.error-state {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding: 120px 40px;
+}
+
+.error-state-icon {
+ font-size: 80px;
+ margin-bottom: 24px;
+}
+
+.error-state-text {
+ font-size: 28px;
+ color: $tx2;
+ margin-bottom: 32px;
+ text-align: center;
+}
+
+.error-state-retry {
+ background: $pri;
+ border-radius: 40px;
+ padding: 16px 48px;
+}
+
+.error-state-retry-text {
+ font-size: 28px;
+ color: #fff;
+}
diff --git a/apps/miniprogram/src/components/ErrorState/index.tsx b/apps/miniprogram/src/components/ErrorState/index.tsx
new file mode 100644
index 0000000..1c7ef15
--- /dev/null
+++ b/apps/miniprogram/src/components/ErrorState/index.tsx
@@ -0,0 +1,25 @@
+import React from 'react';
+import { View, Text } from '@tarojs/components';
+import './index.scss';
+
+interface ErrorStateProps {
+ text?: string;
+ onRetry?: () => void;
+}
+
+export default function ErrorState({
+ text = '加载失败,请稍后重试',
+ onRetry,
+}: ErrorStateProps) {
+ return (
+
+ ⚠️
+ {text}
+ {onRetry && (
+
+ 重新加载
+
+ )}
+
+ );
+}
diff --git a/apps/miniprogram/src/components/Loading/index.scss b/apps/miniprogram/src/components/Loading/index.scss
new file mode 100644
index 0000000..98b450c
--- /dev/null
+++ b/apps/miniprogram/src/components/Loading/index.scss
@@ -0,0 +1,30 @@
+@import '../../styles/variables.scss';
+
+.loading-state {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding: 80px 40px;
+}
+
+.loading-spinner {
+ width: 48px;
+ height: 48px;
+ border: 4px solid $bd;
+ border-top-color: $pri;
+ border-radius: 50%;
+ animation: spin 0.8s linear infinite;
+ margin-bottom: 20px;
+}
+
+@keyframes spin {
+ to {
+ transform: rotate(360deg);
+ }
+}
+
+.loading-state-text {
+ font-size: 26px;
+ color: $tx3;
+}
diff --git a/apps/miniprogram/src/components/Loading/index.tsx b/apps/miniprogram/src/components/Loading/index.tsx
new file mode 100644
index 0000000..8ccfe5a
--- /dev/null
+++ b/apps/miniprogram/src/components/Loading/index.tsx
@@ -0,0 +1,16 @@
+import React from 'react';
+import { View, Text } from '@tarojs/components';
+import './index.scss';
+
+interface LoadingProps {
+ text?: string;
+}
+
+export default function Loading({ text = '加载中...' }: LoadingProps) {
+ return (
+
+
+ {text}
+
+ );
+}
diff --git a/apps/miniprogram/src/pages/appointment/index.tsx b/apps/miniprogram/src/pages/appointment/index.tsx
index efdc390..605ef91 100644
--- a/apps/miniprogram/src/pages/appointment/index.tsx
+++ b/apps/miniprogram/src/pages/appointment/index.tsx
@@ -3,6 +3,8 @@ import { View, Text } from '@tarojs/components';
import Taro, { useDidShow, useReachBottom, usePullDownRefresh } from '@tarojs/taro';
import { listAppointments, cancelAppointment } from '../../services/appointment';
import type { Appointment } from '../../services/appointment';
+import EmptyState from '../../components/EmptyState';
+import Loading from '../../components/Loading';
import './index.scss';
const STATUS_MAP: Record = {
@@ -82,11 +84,7 @@ export default function AppointmentList() {
{/* 预约列表 */}
{appointments.length === 0 && !loading ? (
-
- 📋
- 暂无预约记录
- 点击下方按钮新建预约
-
+
) : (
{appointments.map((item) => {
@@ -120,14 +118,10 @@ export default function AppointmentList() {
);
})}
{loading && (
-
- 加载中...
-
+
)}
{!loading && appointments.length >= total && total > 0 && (
-
- 没有更多了
-
+
)}
)}
diff --git a/apps/miniprogram/src/pages/article/index.tsx b/apps/miniprogram/src/pages/article/index.tsx
index 033a23d..c01020e 100644
--- a/apps/miniprogram/src/pages/article/index.tsx
+++ b/apps/miniprogram/src/pages/article/index.tsx
@@ -2,6 +2,8 @@ import React, { useState, useCallback } from 'react';
import { View, Text } from '@tarojs/components';
import Taro, { useDidShow, usePullDownRefresh, useReachBottom } from '@tarojs/taro';
import { listArticles, Article } from '../../services/article';
+import EmptyState from '../../components/EmptyState';
+import Loading from '../../components/Loading';
import './index.scss';
export default function ArticleList() {
@@ -80,15 +82,11 @@ export default function ArticleList() {
{articles.length === 0 && !loading && (
-
- 暂无资讯文章
-
+
)}
{loading && (
-
- 加载中...
-
+
)}
);
diff --git a/apps/miniprogram/src/pages/followup/index.tsx b/apps/miniprogram/src/pages/followup/index.tsx
index 9168a2e..4f4fc66 100644
--- a/apps/miniprogram/src/pages/followup/index.tsx
+++ b/apps/miniprogram/src/pages/followup/index.tsx
@@ -2,6 +2,8 @@ import React, { useState, useCallback } from 'react';
import { View, Text } from '@tarojs/components';
import Taro, { useDidShow } from '@tarojs/taro';
import { listTasks, FollowUpTask } from '../../services/followup';
+import EmptyState from '../../components/EmptyState';
+import Loading from '../../components/Loading';
import './index.scss';
const TABS = [
@@ -89,18 +91,14 @@ export default function FollowUpList() {
{tasks.length === 0 && !loading && (
-
- 暂无{(() => {
- const tab = TABS.find((t) => t.key === activeTab);
- return tab ? tab.label : '';
- })()}任务
-
+ {
+ const tab = TABS.find((t) => t.key === activeTab);
+ return tab ? tab.label : '';
+ })()}任务`} />
)}
{loading && (
-
- 加载中...
-
+
)}
);
diff --git a/apps/miniprogram/src/pages/index/index.tsx b/apps/miniprogram/src/pages/index/index.tsx
index 0aca94b..c7dc16c 100644
--- a/apps/miniprogram/src/pages/index/index.tsx
+++ b/apps/miniprogram/src/pages/index/index.tsx
@@ -1,6 +1,7 @@
import { View, Text } from '@tarojs/components';
import Taro, { useDidShow } from '@tarojs/taro';
import { useAuthStore } from '../../stores/auth';
+import EmptyState from '../../components/EmptyState';
import './index.scss';
export default function Index() {
@@ -76,9 +77,7 @@ export default function Index() {
{/* 即将到来 */}
即将到来
-
- 暂无即将到来的预约
-
+
);
diff --git a/apps/miniprogram/src/pages/profile/family/index.tsx b/apps/miniprogram/src/pages/profile/family/index.tsx
index d763400..671245e 100644
--- a/apps/miniprogram/src/pages/profile/family/index.tsx
+++ b/apps/miniprogram/src/pages/profile/family/index.tsx
@@ -3,6 +3,7 @@ import { View, Text } from '@tarojs/components';
import Taro, { useDidShow } from '@tarojs/taro';
import { listPatients, Patient } from '../../../services/patient';
import { useAuthStore } from '../../../stores/auth';
+import EmptyState from '../../../components/EmptyState';
import './index.scss';
export default function FamilyList() {
@@ -72,9 +73,7 @@ export default function FamilyList() {
{patients.length === 0 && !loading && (
-
- 暂无就诊人
-
+
)}
diff --git a/apps/miniprogram/src/pages/profile/reports/index.tsx b/apps/miniprogram/src/pages/profile/reports/index.tsx
index 25b3f92..0f7705f 100644
--- a/apps/miniprogram/src/pages/profile/reports/index.tsx
+++ b/apps/miniprogram/src/pages/profile/reports/index.tsx
@@ -2,6 +2,8 @@ import React, { useState, useCallback } from 'react';
import { View, Text } from '@tarojs/components';
import Taro, { useDidShow, usePullDownRefresh, useReachBottom } from '@tarojs/taro';
import { listReports, LabReport } from '../../../services/report';
+import EmptyState from '../../../components/EmptyState';
+import Loading from '../../../components/Loading';
import './index.scss';
const PAGE_SIZE = 20;
@@ -79,15 +81,11 @@ export default function MyReports() {
{reports.length === 0 && !loading && (
-
- 暂无报告记录
-
+
)}
{loading && (
-
- 加载中...
-
+
)}
);
diff --git a/apps/miniprogram/src/pages/report/index.tsx b/apps/miniprogram/src/pages/report/index.tsx
index 73a0d60..339eb6d 100644
--- a/apps/miniprogram/src/pages/report/index.tsx
+++ b/apps/miniprogram/src/pages/report/index.tsx
@@ -2,6 +2,8 @@ import React, { useState, useCallback } from 'react';
import { View, Text } from '@tarojs/components';
import Taro, { useDidShow, usePullDownRefresh, useReachBottom } from '@tarojs/taro';
import { listReports, LabReport } from '../../services/report';
+import EmptyState from '../../components/EmptyState';
+import Loading from '../../components/Loading';
import './index.scss';
const PAGE_SIZE = 20;
@@ -82,15 +84,11 @@ export default function ReportList() {
{reports.length === 0 && !loading && (
-
- 暂无报告记录
-
+
)}
{loading && (
-
- 加载中...
-
+
)}
);