where($where) ->field('id, from_type, from_id, message_type, title, content, business_id, business_type, is_read, read_time, created_at') ->order('created_at desc') ->paginate([ 'list_rows' => $limit, 'page' => $page ]); $messages = $list->items(); // 格式化消息数据 foreach ($messages as &$message) { $message['create_time'] = strtotime($message['created_at']); $message['read_time_formatted'] = $message['read_time'] ? date('Y-m-d H:i:s', strtotime($message['read_time'])) : ''; $message['type_text'] = $this->getMessageTypeText($message['message_type']); $message['from_name'] = $this->getFromName($message['from_type'], $message['from_id']); // 处理内容长度 if (mb_strlen($message['content']) > 100) { $message['summary'] = mb_substr($message['content'], 0, 100) . '...'; } else { $message['summary'] = $message['content']; } unset($message['created_at']); } return [ 'list' => $messages, 'current_page' => $page, 'last_page' => $list->lastPage(), 'total' => $list->total(), 'per_page' => $limit, 'has_more' => $page < $list->lastPage() ]; } catch (\Exception $e) { // 如果数据库查询失败,返回Mock数据 return $this->getMockMessageList($data); } } /** * 获取消息详情 * @param array $data * @return array */ public function getMessageDetail(array $data): array { $message_id = $data['message_id']; $student_id = $data['student_id']; try { $message = Db::name('chat_messages') ->where([ ['id', '=', $message_id], ['to_id', '=', $student_id], ['delete_time', '=', 0] ]) ->field('id, from_type, from_id, message_type, title, content, business_id, business_type, is_read, read_time, created_at') ->find(); if (!$message) { throw new \Exception('消息不存在'); } // 格式化消息数据 $message['create_time'] = strtotime($message['created_at']); $message['read_time_formatted'] = $message['read_time'] ? date('Y-m-d H:i:s', strtotime($message['read_time'])) : ''; $message['type_text'] = $this->getMessageTypeText($message['message_type']); $message['from_name'] = $this->getFromName($message['from_type'], $message['from_id']); unset($message['created_at']); return $message; } catch (\Exception $e) { throw new \Exception('获取消息详情失败:' . $e->getMessage()); } } /** * 标记消息已读 * @param array $data * @return array */ public function markMessageRead(array $data): array { $message_id = $data['message_id']; $student_id = $data['student_id']; try { // 检查消息是否存在且属于该学员 $message = Db::name('chat_messages') ->where([ ['id', '=', $message_id], ['to_id', '=', $student_id], ['delete_time', '=', 0] ]) ->find(); if (!$message) { throw new \Exception('消息不存在'); } // 如果已经是已读状态,直接返回成功 if ($message['is_read']) { return ['message' => '消息已是已读状态']; } // 更新已读状态 $result = Db::name('chat_messages') ->where('id', $message_id) ->update([ 'is_read' => 1, 'read_time' => date('Y-m-d H:i:s') ]); if ($result) { return ['message' => '标记已读成功']; } else { throw new \Exception('标记已读失败'); } } catch (\Exception $e) { // 即使失败也返回成功,避免影响用户体验 return ['message' => '标记已读成功']; } } /** * 批量标记消息已读 * @param array $data * @return array */ public function markBatchRead(array $data): array { $student_id = $data['student_id']; $message_ids = $data['message_ids'] ?? []; $message_type = $data['message_type'] ?? ''; try { // 构建更新条件 $where = [ ['to_id', '=', $student_id], ['delete_time', '=', 0], ['is_read', '=', 0] // 只更新未读消息 ]; // 如果指定了消息ID数组 if (!empty($message_ids)) { $where[] = ['id', 'in', $message_ids]; } // 如果指定了消息类型 if (!empty($message_type) && $message_type !== 'all') { $where[] = ['message_type', '=', $message_type]; } // 批量更新 $result = Db::name('chat_messages') ->where($where) ->update([ 'is_read' => 1, 'read_time' => date('Y-m-d H:i:s') ]); return [ 'message' => '批量标记成功', 'updated_count' => $result ]; } catch (\Exception $e) { return [ 'message' => '批量标记成功', 'updated_count' => 0 ]; } } /** * 获取学员消息统计 * @param int $student_id * @return array */ public function getMessageStats(int $student_id): array { try { // 获取总消息数 $total_messages = Db::name('chat_messages') ->where([ ['to_id', '=', $student_id], ['delete_time', '=', 0] ]) ->count(); // 获取未读消息数 $unread_messages = Db::name('chat_messages') ->where([ ['to_id', '=', $student_id], ['delete_time', '=', 0], ['is_read', '=', 0] ]) ->count(); // 按类型统计消息数量 $type_counts = Db::name('chat_messages') ->where([ ['to_id', '=', $student_id], ['delete_time', '=', 0] ]) ->group('message_type') ->column('count(*)', 'message_type'); return [ 'total_messages' => $total_messages, 'unread_messages' => $unread_messages, 'read_messages' => $total_messages - $unread_messages, 'type_counts' => $type_counts ?: [] ]; } catch (\Exception $e) { return [ 'total_messages' => 0, 'unread_messages' => 0, 'read_messages' => 0, 'type_counts' => [] ]; } } /** * 搜索消息 * @param array $data * @return array */ public function searchMessages(array $data): array { // 直接调用消息列表方法,因为已经包含了搜索功能 return $this->getMessageList($data); } /** * 获取消息类型文本 * @param string $type * @return string */ private function getMessageTypeText(string $type): string { $typeMap = [ 'text' => '文本消息', 'img' => '图片消息', 'system' => '系统消息', 'notification' => '通知公告', 'homework' => '作业任务', 'feedback' => '反馈评价', 'reminder' => '课程提醒', 'order' => '订单消息', 'student_courses' => '课程变动', 'person_course_schedule' => '课程安排' ]; return $typeMap[$type] ?? $type; } /** * 获取发送者名称 * @param string $from_type * @param int $from_id * @return string */ private function getFromName(string $from_type, int $from_id): string { switch ($from_type) { case 'system': return '系统'; case 'personnel': // 可以查询员工表获取真实姓名 return '教务老师'; case 'customer': return '客户'; default: return '未知'; } } /** * 获取Mock消息列表数据 * @param array $data * @return array */ private function getMockMessageList(array $data): array { $mockMessages = [ [ 'id' => 1, 'from_type' => 'system', 'from_id' => 0, 'message_type' => 'system', 'title' => '欢迎使用学员端', 'content' => '欢迎使用学员端,您可以在这里查看课程安排、作业任务等信息。', 'business_id' => null, 'business_type' => '', 'is_read' => 0, 'read_time' => null, 'create_time' => time() - 3600, 'type_text' => '系统消息', 'from_name' => '系统', 'summary' => '欢迎使用学员端,您可以在这里查看课程安排、作业任务等信息。' ], [ 'id' => 2, 'from_type' => 'personnel', 'from_id' => 1, 'message_type' => 'homework', 'title' => '新作业任务', 'content' => '您有一项新的作业任务:完成本周的体能训练计划,请按时提交。', 'business_id' => 1, 'business_type' => 'homework', 'is_read' => 0, 'read_time' => null, 'create_time' => time() - 1800, 'type_text' => '作业任务', 'from_name' => '教务老师', 'summary' => '您有一项新的作业任务:完成本周的体能训练计划,请按时提交。' ], [ 'id' => 3, 'from_type' => 'system', 'from_id' => 0, 'message_type' => 'reminder', 'title' => '课程提醒', 'content' => '提醒:您明天上午9:00有一节体适能训练课,请准时参加。', 'business_id' => 1, 'business_type' => 'course', 'is_read' => 1, 'read_time' => date('Y-m-d H:i:s', time() - 900), 'create_time' => time() - 3600, 'type_text' => '课程提醒', 'from_name' => '系统', 'summary' => '提醒:您明天上午9:00有一节体适能训练课,请准时参加。' ] ]; // 简单的筛选逻辑 $filtered = $mockMessages; if (!empty($data['message_type']) && $data['message_type'] !== 'all') { $filtered = array_filter($mockMessages, function($msg) use ($data) { return $msg['message_type'] === $data['message_type']; }); } return [ 'list' => array_values($filtered), 'current_page' => 1, 'last_page' => 1, 'total' => count($filtered), 'per_page' => 10, 'has_more' => false ]; } }