diff --git a/apps/miniprogram/src/pages/doctor/alerts/index.tsx b/apps/miniprogram/src/pages/doctor/alerts/index.tsx
index 947b420..91f280c 100644
--- a/apps/miniprogram/src/pages/doctor/alerts/index.tsx
+++ b/apps/miniprogram/src/pages/doctor/alerts/index.tsx
@@ -1,4 +1,4 @@
-import { useState, useEffect } from 'react';
+import { useState, useEffect, useMemo } from 'react';
import { View, Text, ScrollView } from '@tarojs/components';
import Taro from '@tarojs/taro';
import * as doctorApi from '@/services/doctor';
@@ -34,6 +34,8 @@ export default function AlertList() {
const [total, setTotal] = useState(0);
const [page, setPage] = useState(1);
+ const totalPages = useMemo(() => totalPages, [total]);
+
useEffect(() => {
loadAlerts();
}, [page, activeTab]);
@@ -137,11 +139,11 @@ export default function AlertList() {
上一页
- {page} / {Math.ceil(total / 20)}
+ {page} / {totalPages}
= Math.ceil(total / 20) ? 'disabled' : ''}`}
- onClick={() => page < Math.ceil(total / 20) && setPage(page + 1)}
+ className={`alert-pagination__btn ${page >= totalPages ? 'disabled' : ''}`}
+ onClick={() => page < totalPages && setPage(page + 1)}
>
下一页
diff --git a/apps/miniprogram/src/pages/doctor/consultation/index.tsx b/apps/miniprogram/src/pages/doctor/consultation/index.tsx
index e43b90d..98dc22b 100644
--- a/apps/miniprogram/src/pages/doctor/consultation/index.tsx
+++ b/apps/miniprogram/src/pages/doctor/consultation/index.tsx
@@ -1,4 +1,4 @@
-import { useState, useEffect } from 'react';
+import { useState, useEffect, useMemo } from 'react';
import { View, Text, ScrollView } from '@tarojs/components';
import Taro from '@tarojs/taro';
import * as doctorApi from '@/services/doctor';
@@ -22,6 +22,8 @@ export default function ConsultationList() {
const [total, setTotal] = useState(0);
const [page, setPage] = useState(1);
+ const totalPages = useMemo(() => totalPages, [total]);
+
useEffect(() => {
loadSessions();
}, [page, activeTab]);
@@ -112,10 +114,10 @@ export default function ConsultationList() {
className={`pagination__btn ${page <= 1 ? 'disabled' : ''}`}
onClick={() => page > 1 && setPage(page - 1)}
>上一页
- {page} / {Math.ceil(total / 20)}
+ {page} / {totalPages}
= Math.ceil(total / 20) ? 'disabled' : ''}`}
- onClick={() => page < Math.ceil(total / 20) && setPage(page + 1)}
+ className={`pagination__btn ${page >= totalPages ? 'disabled' : ''}`}
+ onClick={() => page < totalPages && setPage(page + 1)}
>下一页
)}
diff --git a/apps/miniprogram/src/pages/doctor/index.tsx b/apps/miniprogram/src/pages/doctor/index.tsx
index 5911e72..6420dea 100644
--- a/apps/miniprogram/src/pages/doctor/index.tsx
+++ b/apps/miniprogram/src/pages/doctor/index.tsx
@@ -1,4 +1,4 @@
-import { useState, useEffect } from 'react';
+import { useState, useEffect, useMemo } from 'react';
import { View, Text, Input, ScrollView } from '@tarojs/components';
import Taro from '@tarojs/taro';
import { useAuthStore } from '@/stores/auth';
@@ -11,33 +11,66 @@ interface CardConfig {
label: string;
initial: string;
route: string;
+ roles?: string[];
}
-const CARDS: CardConfig[] = [
+const ALL_CARDS: CardConfig[] = [
{ key: 'total_patients', label: '我的患者', initial: '患', route: '/pages/doctor/patients/index' },
{ key: 'unread_messages', label: '未读消息', initial: '消', route: '/pages/doctor/consultation/index' },
- { key: 'pending_follow_ups', label: '待处理随访', initial: '随', route: '/pages/doctor/followup/index' },
- { key: 'today_consultations', label: '今日咨询', initial: '诊', route: '/pages/doctor/consultation/index' },
+ { key: 'pending_follow_ups', label: '待处理随访', initial: '随', route: '/pages/doctor/followup/index', roles: ['doctor', 'nurse', 'health_manager'] },
+ { key: 'today_consultations', label: '今日咨询', initial: '诊', route: '/pages/doctor/consultation/index', roles: ['doctor', 'health_manager'] },
];
-const HEALTH_CARDS: CardConfig[] = [
- { key: 'pending_lab_review', label: '待审化验', initial: '化', route: '/pages/doctor/report/index' },
+const ALL_HEALTH_CARDS: CardConfig[] = [
+ { key: 'pending_lab_review', label: '待审化验', initial: '化', route: '/pages/doctor/report/index', roles: ['doctor'] },
{ key: 'today_appointments', label: '今日预约', initial: '约', route: '/pages/doctor/patients/index' },
];
-const QUICK_ACTIONS = [
- { label: '化验审核', initial: '审', route: '/pages/doctor/report/index' },
- { label: '患者查询', initial: '查', route: '/pages/doctor/patients/index' },
- { label: '随访记录', initial: '随', route: '/pages/doctor/followup/index' },
- { label: '告警中心', initial: '警', route: '/pages/doctor/alerts/index' },
+interface QuickAction {
+ label: string;
+ initial: string;
+ route: string;
+ roles: string[];
+}
+
+const ALL_QUICK_ACTIONS: QuickAction[] = [
+ { label: '化验审核', initial: '审', route: '/pages/doctor/report/index', roles: ['doctor'] },
+ { label: '患者查询', initial: '查', route: '/pages/doctor/patients/index', roles: ['doctor', 'nurse', 'health_manager'] },
+ { label: '随访记录', initial: '随', route: '/pages/doctor/followup/index', roles: ['doctor', 'nurse', 'health_manager'] },
+ { label: '告警中心', initial: '警', route: '/pages/doctor/alerts/index', roles: ['doctor', 'nurse', 'health_manager'] },
+ { label: '透析管理', initial: '透', route: '/pages/doctor/dialysis/index', roles: ['doctor'] },
+ { label: '处方管理', initial: '方', route: '/pages/doctor/prescription/index', roles: ['doctor'] },
+ { label: '行动收件箱', initial: '行', route: '/pages/doctor/action-inbox/index', roles: ['doctor', 'nurse', 'health_manager'] },
];
+const ROLE_LABELS: Record = {
+ doctor: '医生',
+ nurse: '护士',
+ health_manager: '健康管理师',
+ admin: '管理员',
+ operator: '运营',
+};
+
export default function DoctorHome() {
- const { user, logout } = useAuthStore();
+ const { user, logout, roles } = useAuthStore();
const [dashboard, setDashboard] = useState(null);
const [alertCount, setAlertCount] = useState(0);
const [loading, setLoading] = useState(true);
+ const hasRole = (allowed: string[] | undefined) => {
+ if (!allowed) return true;
+ return roles.some((r) => r === 'admin' || allowed.includes(r));
+ };
+
+ const cards = useMemo(() => ALL_CARDS.filter((c) => hasRole(c.roles)), [roles]);
+ const healthCards = useMemo(() => ALL_HEALTH_CARDS.filter((c) => hasRole(c.roles)), [roles]);
+ const quickActions = useMemo(() => ALL_QUICK_ACTIONS.filter((a) => hasRole(a.roles)), [roles]);
+
+ const roleLabel = useMemo(() => {
+ const primary = roles.find((r) => r !== 'admin');
+ return primary ? (ROLE_LABELS[primary] || primary) : '医护';
+ }, [roles]);
+
useEffect(() => {
loadDashboard();
}, []);
@@ -76,7 +109,7 @@ export default function DoctorHome() {
医护工作台
- {user?.display_name || user?.username || '医生'},您好
+ {user?.display_name || user?.username || roleLabel},您好
{new Date().toLocaleDateString('zh-CN', { month: 'long', day: 'numeric', weekday: 'long' })}
@@ -102,7 +135,7 @@ export default function DoctorHome() {
工作概览
- {CARDS.map((card) => (
+ {cards.map((card) => (
-
+ {healthCards.length > 0 && (
健康审核
- {HEALTH_CARDS.map((card) => (
+ {healthCards.map((card) => (
))}
-
+ )}
快捷操作
- {QUICK_ACTIONS.map((action) => (
+ {quickActions.map((action) => (
Math.ceil(total / 20), [total]);
+
if (loading && patients.length === 0) return ;
return (
@@ -162,10 +164,10 @@ export default function PatientList() {
>
上一页
- {page} / {Math.ceil(total / 20)}
+ {page} / {totalPages}
= Math.ceil(total / 20) ? 'disabled' : ''}`}
- onClick={() => page < Math.ceil(total / 20) && setPage(page + 1)}
+ className={`pagination__btn ${page >= totalPages ? 'disabled' : ''}`}
+ onClick={() => page < totalPages && setPage(page + 1)}
>
下一页
diff --git a/apps/miniprogram/src/stores/auth.ts b/apps/miniprogram/src/stores/auth.ts
index aa3a8cf..2d1dbe0 100644
--- a/apps/miniprogram/src/stores/auth.ts
+++ b/apps/miniprogram/src/stores/auth.ts
@@ -24,6 +24,10 @@ interface AuthState {
logout: () => void;
restore: () => void;
isMedicalStaff: () => boolean;
+ isDoctor: () => boolean;
+ isNurse: () => boolean;
+ isHealthManager: () => boolean;
+ hasRole: (code: string) => boolean;
hasPatientProfile: () => boolean;
}
@@ -36,7 +40,27 @@ export const useAuthStore = create((set, get) => ({
isMedicalStaff: () => {
const { roles } = get();
- return roles.some((r) => r === 'doctor' || r === 'nurse' || r === 'admin');
+ return roles.some((r) => r === 'doctor' || r === 'nurse' || r === 'admin' || r === 'health_manager');
+ },
+
+ isDoctor: () => {
+ const { roles } = get();
+ return roles.some((r) => r === 'doctor' || r === 'admin');
+ },
+
+ isNurse: () => {
+ const { roles } = get();
+ return roles.some((r) => r === 'nurse' || r === 'admin');
+ },
+
+ isHealthManager: () => {
+ const { roles } = get();
+ return roles.some((r) => r === 'health_manager' || r === 'admin');
+ },
+
+ hasRole: (code: string) => {
+ const { roles } = get();
+ return roles.some((r) => r === code || r === 'admin');
},
hasPatientProfile: () => {