// +---------------------------------------------------------------------- declare (strict_types = 1); namespace addon\wxchat\worker\handle; use addon\wxchat\model\WxchatMessage; use addon\wxchat\model\WxchatUnreadCount; use addon\wxchat\worker\enum\MsgFrame; use addon\wxchat\worker\enum\MsgType; use addon\wxchat\worker\MsgReply; use GatewayWorker\Lib\Gateway; /** * 状态消息处理:正在输入 / 送达 / 已读 / 撤回 * typing 仅实时转发不落库;read 清零未读;revoked 标记撤回 */ class StatusHandle { public static function handle($client_id, $header, $payload) { $uid = Gateway::getUidByClientId($client_id); if (empty($uid)) { MsgReply::sendError($client_id, '未认证,请先登录'); return; } switch ($header->type) { case MsgType::TYPING->value: // 实时转发给对方,不落库 $to = (int)($payload->receiver ?? 0); if ($to && Gateway::isUidOnline($to)) { MsgReply::sendToUid($to, MsgFrame::STATUS->value, MsgType::TYPING->value, 'typing', [ 'from' => $uid, ]); } break; case MsgType::READ->value: // 标记某会话已读:清零自己对该会话的未读 $peer = (int)($payload->receiver ?? 0); if ($peer) { WxchatUnreadCount::reset($uid, 0, $peer); } break; case MsgType::REVOKED->value: // 撤回消息 $msgId = (int)($payload->msg_id ?? 0); $msg = WxchatMessage::find($msgId); if ($msg && $msg->sender_id == $uid) { $msg->is_recalled = 1; $msg->recalled_at = date('Y-m-d H:i:s'); $msg->save(); // 通知对方撤回 $to = (int)($payload->receiver ?? 0); if ($to && Gateway::isUidOnline($to)) { MsgReply::sendToUid($to, MsgFrame::STATUS->value, MsgType::REVOKED->value, 'revoked', [ 'msg_id' => $msgId, 'from' => $uid, ]); } } break; case MsgType::DELIVERED->value: // 送达回执,无需处理 break; default: MsgReply::sendError($client_id, '不支持的状态消息类型'); } } }