diff --git a/reading-platform-frontend/src/api/auth.ts b/reading-platform-frontend/src/api/auth.ts index 9f2c983..9fb37c6 100644 --- a/reading-platform-frontend/src/api/auth.ts +++ b/reading-platform-frontend/src/api/auth.ts @@ -11,7 +11,7 @@ export interface LoginResponse { user: { id: number; name: string; - role: 'admin' | 'school' | 'teacher'; + role: 'admin' | 'school' | 'teacher' | 'parent'; tenantId?: number; tenantName?: string; email?: string; @@ -22,7 +22,7 @@ export interface LoginResponse { export interface UserProfile { id: number; name: string; - role: 'admin' | 'school' | 'teacher'; + role: 'admin' | 'school' | 'teacher' | 'parent'; tenantId?: number; tenantName?: string; email?: string; diff --git a/reading-platform-frontend/src/api/notification.ts b/reading-platform-frontend/src/api/notification.ts new file mode 100644 index 0000000..f1d0f7c --- /dev/null +++ b/reading-platform-frontend/src/api/notification.ts @@ -0,0 +1,52 @@ +import { http } from './index'; + +export interface NotificationItem { + id: number; + title: string; + content: string; + notificationType: string; + isRead: boolean; + readAt?: string; + createdAt: string; +} + +export interface NotificationsResponse { + items: NotificationItem[]; + total: number; + unreadCount: number; + page: number; + pageSize: number; +} + +export interface NotificationQueryParams { + page?: number; + pageSize?: number; + isRead?: boolean; + notificationType?: string; +} + +/** 根据角色获取通知列表(teacher | school | parent) */ +export function getNotifications( + role: 'teacher' | 'school' | 'parent', + params?: NotificationQueryParams +): Promise { + return http.get(`/${role}/notifications`, { params }); +} + +/** 根据角色获取未读数量 */ +export function getUnreadCount(role: 'teacher' | 'school' | 'parent'): Promise { + return http.get(`/${role}/notifications/unread-count`); +} + +/** 标记单条已读 */ +export function markNotificationAsRead( + role: 'teacher' | 'school' | 'parent', + id: number +): Promise { + return http.put(`/${role}/notifications/${id}/read`); +} + +/** 全部标记已读 */ +export function markAllNotificationsAsRead(role: 'teacher' | 'school' | 'parent'): Promise { + return http.put(`/${role}/notifications/read-all`); +} diff --git a/reading-platform-frontend/src/components/NotificationBell.vue b/reading-platform-frontend/src/components/NotificationBell.vue index 36ec186..d178464 100644 --- a/reading-platform-frontend/src/components/NotificationBell.vue +++ b/reading-platform-frontend/src/components/NotificationBell.vue @@ -65,7 +65,12 @@ import { SoundOutlined, } from '@ant-design/icons-vue'; import { useUserStore } from '@/stores/user'; -import { getNotifications, markNotificationAsRead, markAllNotificationsAsRead } from '@/api/parent'; +import { + getNotifications, + getUnreadCount, + markNotificationAsRead, + markAllNotificationsAsRead, +} from '@/api/notification'; import type { Component } from 'vue'; import dayjs from 'dayjs'; import relativeTime from 'dayjs/plugin/relativeTime'; @@ -108,17 +113,16 @@ const handleBellClick = () => { }; const loadNotifications = async () => { + const role = userStore.user?.role as 'teacher' | 'school' | 'parent' | undefined; + if (role !== 'teacher' && role !== 'school' && role !== 'parent') { + return; + } loading.value = true; try { - const role = userStore.user?.role; - // 根据角色调用不同的API - if (role === 'parent') { - const data = await getNotifications({ pageSize: 5 }); - notifications.value = data.items; - total.value = data.total; - unreadCount.value = data.unreadCount; - } - // 其他角色的通知可以在这里扩展 + const data = await getNotifications(role, { pageSize: 5 }); + notifications.value = data.items; + total.value = data.total; + unreadCount.value = data.unreadCount; } catch (error: any) { console.error('Failed to load notifications:', error); } finally { @@ -127,12 +131,10 @@ const loadNotifications = async () => { }; const handleNotificationClick = async (notification: any) => { - if (!notification.isRead) { + const role = userStore.user?.role as 'teacher' | 'school' | 'parent' | undefined; + if (!notification.isRead && (role === 'teacher' || role === 'school' || role === 'parent')) { try { - const role = userStore.user?.role; - if (role === 'parent') { - await markNotificationAsRead(notification.id); - } + await markNotificationAsRead(role, notification.id); notification.isRead = true; unreadCount.value = Math.max(0, unreadCount.value - 1); } catch (error) { @@ -143,11 +145,10 @@ const handleNotificationClick = async (notification: any) => { }; const markAllRead = async () => { + const role = userStore.user?.role as 'teacher' | 'school' | 'parent' | undefined; + if (role !== 'teacher' && role !== 'school' && role !== 'parent') return; try { - const role = userStore.user?.role; - if (role === 'parent') { - await markAllNotificationsAsRead(); - } + await markAllNotificationsAsRead(role); notifications.value.forEach((n) => (n.isRead = true)); unreadCount.value = 0; message.success('已全部标记为已读'); @@ -162,7 +163,10 @@ const viewAll = () => { }; onMounted(() => { - // 可以定期检查未读数量 + const role = userStore.user?.role as 'teacher' | 'school' | 'parent' | undefined; + if (role === 'teacher' || role === 'school' || role === 'parent') { + getUnreadCount(role).then((n) => (unreadCount.value = n)).catch(() => {}); + } }); diff --git a/reading-platform-frontend/src/router/index.ts b/reading-platform-frontend/src/router/index.ts index a5abb4d..2d9c9b2 100644 --- a/reading-platform-frontend/src/router/index.ts +++ b/reading-platform-frontend/src/router/index.ts @@ -112,6 +112,12 @@ const routes: RouteRecordRaw[] = [ component: () => import('@/views/admin/SettingsView.vue'), meta: { title: '系统设置' }, }, + { + path: 'profile', + name: 'AdminProfile', + component: () => import('@/views/profile/ProfileView.vue'), + meta: { title: '个人信息' }, + }, ], }, { @@ -256,6 +262,12 @@ const routes: RouteRecordRaw[] = [ component: () => import('@/views/school/settings/SettingsView.vue'), meta: { title: '系统设置' }, }, + { + path: 'profile', + name: 'SchoolProfile', + component: () => import('@/views/profile/ProfileView.vue'), + meta: { title: '个人信息' }, + }, ], }, { @@ -376,6 +388,12 @@ const routes: RouteRecordRaw[] = [ component: () => import('@/views/teacher/growth/GrowthRecordView.vue'), meta: { title: '成长档案' }, }, + { + path: 'profile', + name: 'TeacherProfile', + component: () => import('@/views/profile/ProfileView.vue'), + meta: { title: '个人信息' }, + }, ], }, { @@ -423,6 +441,12 @@ const routes: RouteRecordRaw[] = [ component: () => import('@/views/parent/growth/GrowthRecordView.vue'), meta: { title: '成长档案' }, }, + { + path: 'profile', + name: 'ParentProfile', + component: () => import('@/views/profile/ProfileView.vue'), + meta: { title: '个人信息' }, + }, ], }, { diff --git a/reading-platform-frontend/src/views/admin/LayoutView.vue b/reading-platform-frontend/src/views/admin/LayoutView.vue index c801f79..cf63f7f 100644 --- a/reading-platform-frontend/src/views/admin/LayoutView.vue +++ b/reading-platform-frontend/src/views/admin/LayoutView.vue @@ -149,9 +149,7 @@
- - - +