From ef49c7b6d3747ff0003924779c950e0d61bca82c Mon Sep 17 00:00:00 2001 From: QDKF Date: Mon, 15 Sep 2025 19:34:25 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AF=B9=E6=8E=A5=E6=88=91=E7=9A=84?= =?UTF-8?q?=E4=BC=9A=E8=AF=9D=EF=BC=8C=E6=9F=A5=E8=AF=A2=E4=BC=9A=E8=AF=9D?= =?UTF-8?q?=E6=B6=88=E6=81=AF=EF=BC=8C=E6=9F=A5=E8=AF=A2=E7=BE=A4=E8=81=8A?= =?UTF-8?q?=E6=88=90=E5=91=98=E5=88=97=E8=A1=A8=EF=BC=8C=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E8=AF=BE=E7=A8=8B=E8=AF=84=E8=AE=BA=E6=8E=A5=E5=8F=A3;?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BC=9A=E8=AF=9D=E6=B6=88=E6=81=AF=E7=A9=BA?= =?UTF-8?q?=E7=8A=B6=E6=80=81=E6=A0=B7=E5=BC=8F=EF=BC=8C=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E8=AF=81=E4=B9=A6=E4=B8=AD=E5=BF=83=E5=86=85=E5=AE=B9=E6=A0=B7?= =?UTF-8?q?=E5=BC=8F=EF=BC=8C=E4=BF=AE=E5=A4=8D=E7=8F=AD=E7=BA=A7=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E7=BB=84=E4=BB=B6=E5=88=A0=E9=99=A4=E5=AD=A6=E5=91=98?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/index.ts | 12 + src/api/modules/chat.ts | 177 ++++++ src/api/modules/teachCourse.ts | 2 +- .../ExamComponents/QuestionBankModal.vue | 6 +- src/components/teacher/ClassManagement.vue | 275 ++++----- src/views/teacher/ExamPages/AddExam.vue | 4 +- .../teacher/certificate/CertificateNew.vue | 180 +++++- src/views/teacher/message/MessageCenter.vue | 56 +- .../message/components/CommentLikes.vue | 375 ++++++++--- .../components/NotificationMessages.vue | 581 ++++++++++++------ src/views/teacher/student/ClassManagement.vue | 13 +- 11 files changed, 1216 insertions(+), 465 deletions(-) create mode 100644 src/api/modules/chat.ts diff --git a/src/api/index.ts b/src/api/index.ts index e5eae4d..c176296 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -12,6 +12,7 @@ export { default as OrderApi } from './modules/order' export { default as UploadApi } from './modules/upload' export { default as StatisticsApi } from './modules/statistics' export { default as ExamApi } from './modules/exam' +export { ChatApi } from './modules/chat' // API 基础配置 export const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:3000/jeecgboot' @@ -221,6 +222,17 @@ export const API_ENDPOINTS = { PROGRESS: '/learning-progress', MY_COURSES: '/my-courses', }, + + // 聊天相关 + CHAT: { + MY_CHATS: '/aiol/aiolChat/my_chats', + MESSAGES: '/aiol/aiolChat/:chatId/messages', + MEMBERS: '/aiol/aiolChat/:chatId/members', + SEND: '/aiol/aiolChat/send', + MARK_READ: '/aiol/aiolChat/mark-read', + UNREAD_COUNT: '/aiol/aiolChat/unread-count', + FOLLOW: '/aiol/aiolUserFollow/follow', + }, // 资源相关 RESOURCES: { diff --git a/src/api/modules/chat.ts b/src/api/modules/chat.ts new file mode 100644 index 0000000..90a254a --- /dev/null +++ b/src/api/modules/chat.ts @@ -0,0 +1,177 @@ +// 聊天相关API接口 +import { ApiRequest } from '../request' +import type { ApiResponse } from '../types' + +// 聊天会话接口类型定义 +export interface ChatSession { + id: string + name: string + type: number // 0=私聊,1=群聊 + avatar?: string + lastMessage?: string + lastMessageTime?: string + unreadCount?: number + isOnline?: boolean + createTime?: string + updateTime?: string + // 根据实际API响应添加的字段 + refId?: string // 关联ID + createBy?: string + updateBy?: string + izAllMuted?: boolean + showLabel?: string + memberCount?: number // 群成员数量 + status?: number // 会话状态 + description?: string // 会话描述 +} + +// 聊天消息接口类型定义 +export interface ChatMessage { + id: string + chatId: string + senderId: string + senderName: string + senderAvatar?: string + content: string + messageType: 'text' | 'image' | 'file' | 'system' + timestamp: string + isRead: boolean + replyTo?: string + // 根据接口文档优化的字段 + status?: number // 消息状态 + fileUrl?: string // 文件URL + fileSize?: number // 文件大小 + fileType?: string // 文件类型 +} + +// 群聊成员接口类型定义 +export interface ChatMember { + id: string + chatId: string + userId: string + userName: string + userAvatar?: string + role: 'admin' | 'member' + joinTime: string + isOnline?: boolean + // 根据接口文档优化的字段 + status?: number // 成员状态 + lastActiveTime?: string // 最后活跃时间 +} + +// 我的会话列表响应类型 +export interface MyChatsResponse { + success: boolean + message: string + code: number + result: ChatSession[] + timestamp: number +} + +// 会话消息列表响应类型 +export interface ChatMessagesResponse { + success: boolean + message: string + code: number + result: ChatMessage[] + timestamp: number +} + +// 群聊成员列表响应类型 +export interface ChatMembersResponse { + success: boolean + message: string + code: number + result: ChatMember[] + timestamp: number +} + +// 分页查询参数 +export interface ChatQueryParams { + page?: number + size?: number + keyword?: string + type?: 'private' | 'group' + status?: number +} + +/** + * 聊天相关API + */ +export const ChatApi = { + /** + * 获取我的会话列表 + * GET /aiol/aiolChat/my_chats + * 支持分页和筛选参数 + */ + getMyChats: (params?: ChatQueryParams): Promise> => { + return ApiRequest.get('/aiol/aiolChat/my_chats', { params }) + }, + + /** + * 查询会话消息 + * GET /aiol/aiolChat/{chatId}/messages + * 支持分页加载历史消息 + */ + getChatMessages: (chatId: string, params?: ChatQueryParams): Promise> => { + console.log('🔍 调用getChatMessages接口,chatId:', chatId, 'params:', params) + return ApiRequest.get(`/aiol/aiolChat/${chatId}/messages`, { params }) + }, + + /** + * 查询群聊成员列表 + * GET /aiol/aiolChat/{chatId}/members + */ + getChatMembers: (chatId: string): Promise> => { + return ApiRequest.get(`/aiol/aiolChat/${chatId}/members`) + }, + + /** + * 关注/取关教师 + * POST /aiol/aiolUserFollow/follow + */ + followTeacher: (followedId: string): Promise> => { + return ApiRequest.post('/aiol/aiolUserFollow/follow', { + followedId + }) + }, + + /** + * 发送消息 + * POST /aiol/aiolChat/send + * 根据接口文档添加发送消息功能 + */ + sendMessage: (data: { + chatId: string + content: string + messageType: 'text' | 'image' | 'file' + replyTo?: string + fileUrl?: string + fileSize?: number + fileType?: string + }): Promise> => { + return ApiRequest.post('/aiol/aiolChat/send', data) + }, + + + /** + * 标记消息为已读 + * PUT /aiol/aiolChat/mark-read + * 根据接口文档添加标记已读功能 + */ + markAsRead: (chatId: string, messageIds?: string[]): Promise> => { + return ApiRequest.put('/aiol/aiolChat/mark-read', { + chatId, + messageIds + }) + }, + + /** + * 获取未读消息数量 + * GET /aiol/aiolChat/unread-count + * 根据接口文档添加未读消息统计 + */ + getUnreadCount: (): Promise> => { + return ApiRequest.get('/aiol/aiolChat/unread-count') + } +} diff --git a/src/api/modules/teachCourse.ts b/src/api/modules/teachCourse.ts index bd83a67..cbe3d66 100644 --- a/src/api/modules/teachCourse.ts +++ b/src/api/modules/teachCourse.ts @@ -489,7 +489,7 @@ export class ClassApi { * 删除班级内学生 */ static async removeStudent(classId: string, studentId: string): Promise> { - return ApiRequest.delete(`/aiol/aiolClass/${classId}/remove_student/${studentId}`); + return ApiRequest.delete(`/aiol/aiolClass/${classId}/remove_student/${studentId}`, undefined); } /** diff --git a/src/components/admin/ExamComponents/QuestionBankModal.vue b/src/components/admin/ExamComponents/QuestionBankModal.vue index dd0feb3..e42fba1 100644 --- a/src/components/admin/ExamComponents/QuestionBankModal.vue +++ b/src/components/admin/ExamComponents/QuestionBankModal.vue @@ -94,7 +94,7 @@
管理班级 - + @@ -44,10 +43,10 @@ import { CaretForward, EllipsisVertical } from '@vicons/ionicons5' import { onMounted, ref } from "vue" import { ClassApi } from '@/api/modules/teachCourse' -const classList = ref>([]) +const classList = ref>([]) // 当前激活的班级ID -const activeClassId = ref(1) +const activeClassId = ref('1') // 引用ClassManagement组件 const classManagementRef = ref | null>(null) @@ -77,7 +76,7 @@ const getClassItemOptions = () => [ ] // 点击班级项的处理函数 -const handleClassClick = (classId: number) => { +const handleClassClick = (classId: string) => { console.log(`🖱️ 用户点击班级: ${classId}, 当前激活班级: ${activeClassId.value}`) if (activeClassId.value !== classId) { activeClassId.value = classId @@ -98,7 +97,7 @@ const handleClassMenuSelect = (value: string) => { } // 处理班级项菜单选择 -const handleClassItemMenuSelect = (value: string, classId: number) => { +const handleClassItemMenuSelect = (value: string, classId: string) => { if (!classManagementRef.value) return const selectedClass = classList.value.find(item => item.id === classId)