232 lines
9.8 KiB
Go
232 lines
9.8 KiB
Go
/**
|
||
* package models
|
||
* 作用:定义项目中所有的数据结构,包括 HTTP 请求/响应载荷、数据库模型、Redis 消息格式以及常量定义。
|
||
*/
|
||
package models
|
||
|
||
import "time"
|
||
|
||
/**
|
||
* SendMessagePayload
|
||
* 结构体:客户端发送消息的请求载荷。
|
||
* 用途:用于解析 WebSocket 或 HTTP POST 请求体中的 JSON 数据。
|
||
*/
|
||
// 统一消息结构(发送方使用)
|
||
type SendMessagePayload struct {
|
||
RequestType string `json:"request_type"` // 消息类型
|
||
TargetClientID string `json:"target_client_id"` // 目标客户端ID
|
||
SenderUserID string `json:"sender_user_id"` // 发送者用户ID
|
||
ReceiverUserID string `json:"receiver_user_id"` // 接收者用户ID
|
||
MessageType int `json:"message_type"` // 消息类型(0-13)
|
||
MessageContent string `json:"message_content"` // 消息内容
|
||
RoomId string `json:"room_id"` // 房间ID
|
||
Duration int `json:"duration"` // 时长(音频、视频、音视频通话)
|
||
Token string `json:"token,omitempty"` // 认证Token
|
||
UserType string `json:"user_type,omitempty"` // 用户类型: user/doctor
|
||
CleanOldConnections bool `json:"clean_old_connections"` // 是否清理旧连接(bind时使用)
|
||
// 通话专用字段
|
||
CallID string `json:"call_id,omitempty"` // 通话唯一ID
|
||
CallStatus string `json:"call_status,omitempty"` // 通话状态:invite/accepted/rejected/ended/candidate
|
||
}
|
||
|
||
/**
|
||
* SendToUserPayload
|
||
* 结构体:仅通过用户ID发送消息的简化载荷。
|
||
*/
|
||
// 通过用户ID发送消息的结构
|
||
type SendToUserPayload struct {
|
||
RoomId string `json:"room_id"` // 发送者用户ID
|
||
Duration int `json:"duration"` // 时长(音频、视频、音视频通话)
|
||
SenderUserID string `json:"sender_user_id"` // 发送者用户ID
|
||
ReceiverUserID string `json:"receiver_user_id"` // 接收者用户ID
|
||
MessageType int `json:"message_type"` // 消息类型(0-13)
|
||
MessageContent string `json:"message_content"` // 消息内容
|
||
// 通话专用字段
|
||
CallID string `json:"call_id,omitempty"` // 通话唯一ID
|
||
CallStatus string `json:"call_status,omitempty"` // 通话状态:invite/accepted/rejected/ended/candidate/offer/answer
|
||
}
|
||
|
||
/**
|
||
* XkChatMessage
|
||
* 结构体:数据库模型,对应 xk_chat_messages 表(假设)。
|
||
* 用途:持久化存储聊天记录。
|
||
*/
|
||
// 聊天消息记录模型
|
||
type XkChatMessage struct {
|
||
ID uint `gorm:"primaryKey" json:"id"`
|
||
RoomId string `gorm:"type:varchar(100);index" json:"room_id"` // 房间ID
|
||
SenderUserID string `gorm:"type:varchar(100);index" json:"sender_user_id"` // 发送者用户ID
|
||
ReceiverUserID string `gorm:"type:varchar(100);index" json:"receiver_user_id"` // 接收者用户ID
|
||
MessageType int `gorm:"type:int" json:"message_type"` // 消息类型(0-9)
|
||
MessageContent string `gorm:"type:text" json:"message_content"` // 消息内容
|
||
Duration int `json:"duration"` // 时长(音频、视频、音视频通话)
|
||
CallID string `gorm:"type:varchar(100);index" json:"call_id"` // 通话唯一ID
|
||
CallStatus string `gorm:"type:varchar(50)" json:"call_status"` // 通话状态
|
||
CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"` // 创建时间
|
||
}
|
||
|
||
/**
|
||
* ClientReceivedMessage
|
||
* 结构体:客户端最终接收到的消息格式。
|
||
* 用途:服务端推送到客户端的 JSON 结构。
|
||
*/
|
||
// 客户端接收消息结构(最终格式)
|
||
type ClientReceivedMessage struct {
|
||
ID int `json:"id"` // 房间号
|
||
RoomID string `json:"room_id"` // 房间号
|
||
SenderID string `json:"sender_id"` // 发送者连接ID
|
||
ReceiverID string `json:"receiver_id"` // 接收者连接ID
|
||
SenderUserID string `json:"sender_user_id"` // 发送者用户ID
|
||
ReceiverUserID string `json:"receiver_user_id"` // 接收者用户ID
|
||
MessageType int `json:"message_type"` // 消息类型(0-13)
|
||
MessageContent string `json:"message_content"` // 消息内容
|
||
CreatedAt string `json:"created_at"` // 创建时间
|
||
Duration int `json:"duration"` // 时长(音频、视频、音视频通话)
|
||
|
||
// 通话专用字段
|
||
CallID string `json:"call_id,omitempty"` // 通话唯一ID
|
||
CallStatus string `json:"call_status,omitempty"` // 通话状态:invite/accepted/rejected/ended/candidate/offer/answer
|
||
}
|
||
|
||
/**
|
||
* RedisMessage
|
||
* 结构体:Redis Pub/Sub 消息结构。
|
||
* 用途:用于跨节点消息转发。
|
||
*/
|
||
// Redis 消息结构
|
||
type RedisMessage struct {
|
||
SenderNodeID string `json:"sender_node_id"` // 发送节点ID
|
||
ClientID string `json:"client_id"` // 目标客户端ID
|
||
Message string `json:"message"` // 消息内容
|
||
}
|
||
|
||
// 用户绑定请求结构
|
||
type BindRequest struct {
|
||
UserID string `json:"user_id"` // 用户ID
|
||
ClientID string `json:"client_id"` // 客户端ID
|
||
Token string `json:"token"` // 认证Token
|
||
}
|
||
|
||
/**
|
||
* AuthResponse
|
||
* 结构体:认证响应结构
|
||
* 用途:返回给客户端的认证状态
|
||
*/
|
||
type AuthResponse struct {
|
||
AuthStatus string `json:"auth_status"` // 认证状态: success/failed/token_expired
|
||
Message string `json:"message"` // 消息说明
|
||
ClientID string `json:"clientId,omitempty"` // 客户端ID
|
||
}
|
||
|
||
/**
|
||
* ClientInfo
|
||
* 结构体:客户端连接信息(包含认证信息)
|
||
* 用途:存储已连接客户端的认证状态和token
|
||
*/
|
||
type ClientInfo struct {
|
||
ClientID string `json:"client_id"` // 客户端ID
|
||
UserID string `json:"user_id"` // 用户ID
|
||
UserType string `json:"user_type"` // 用户类型: user/doctor
|
||
Token string `json:"token"` // 认证Token
|
||
IsAuth bool `json:"is_auth"` // 是否已认证
|
||
AuthTime time.Time `json:"auth_time"` // 认证时间
|
||
LastCheckTime time.Time `json:"last_check_time"` // 上次检查时间
|
||
}
|
||
|
||
/**
|
||
* CallSignal
|
||
* 结构体:WebRTC 信令数据载荷。
|
||
*/
|
||
// 通话信令结构
|
||
type CallSignal struct {
|
||
CallStatus string `json:"call_status"` // 动作: invite/accept/reject/end/candidate/offer/answer
|
||
CallType int `json:"call_type"` // 通话类型:6=视频,7=语音
|
||
CallID string `json:"call_id"` // 通话唯一ID
|
||
CallerID string `json:"caller_id"` // 主叫用户ID
|
||
CalleeID string `json:"callee_id"` // 被叫用户ID
|
||
Data string `json:"data"` // 数据(SDP/ICE候选)
|
||
}
|
||
|
||
// WebRTC信令数据结构
|
||
type WebRTCSignalData struct {
|
||
Type string `json:"type"` // offer/answer/candidate
|
||
SDP string `json:"sdp,omitempty"` // SDP数据
|
||
Candidate interface{} `json:"candidate,omitempty"` // ICE候选数据
|
||
SDPMid string `json:"sdpMid,omitempty"` // SDP媒体标识
|
||
SDPMLineIndex int `json:"sdpMLineIndex,omitempty"` // SDP行索引
|
||
}
|
||
|
||
// 通话状态常量
|
||
const (
|
||
CallStatusInvite = "invite" // 发起邀请
|
||
CallStatusAccepted = "accepted" // 接受通话
|
||
CallStatusRejected = "rejected" // 拒绝通话
|
||
CallStatusEnded = "ended" // 结束通话
|
||
CallStatusOffer = "offer" // WebRTC Offer
|
||
CallStatusAnswer = "answer" // WebRTC Answer
|
||
CallStatusCandidate = "candidate" // ICE候选
|
||
CallStatusHangup = "hangup" // 挂断
|
||
CallStatusDisconnected = "disconnected" // 断开连接
|
||
CallStatusTerminated = "terminated" // 终止
|
||
CallStatusNoAnswer = "no-answer" // 无人接听
|
||
CallStatusBusy = "busy" // 忙线
|
||
CallStatusFailed = "failed" // 失败
|
||
CallStatusConnecting = "connecting" // 连接中
|
||
)
|
||
|
||
// 消息类型常量
|
||
const (
|
||
MessageTypeText = 0 // 文本消息
|
||
MessageTypeImage = 1 // 图片消息
|
||
MessageTypeAudio = 2 // 音频消息
|
||
MessageTypeVideo = 3 // 视频消息
|
||
MessageTypePrescription = 4 // 处方消息
|
||
MessageTypeMedicalRecord = 5 // 病例消息
|
||
MessageTypeVideoCall = 6 // 视频通话
|
||
MessageTypeAudioCall = 7 // 语音通话
|
||
MessageTypeFile = 8 // 文件消息
|
||
MessageTypeSystem = 9 // 系统消息
|
||
MessageTypeRegister = 10 // 挂号信息
|
||
MessageTypePatientExperience = 11 // 患者就诊经历卡片
|
||
MessageTypeProductCard = 12 // 商品卡片
|
||
MessageTypeEndConsultation = 13 // 结束问诊卡片
|
||
)
|
||
|
||
// Redis键常量
|
||
const (
|
||
ClientUserKey = "client_user_mapping" // clientid -> userid映射
|
||
UserClientKey = "user_client_mapping" // userid -> clientid列表
|
||
TokenKeyPrefix = "xiaokang_database_xk_user_" // Mobile token存储前缀 (Redis DB 1) - 包含Laravel全局前缀
|
||
AdminTokenKeyPrefix = "xiaokang_database_xk_login_" // Admin token存储前缀 (Redis DB 0) - 包含Laravel全局前缀
|
||
)
|
||
|
||
// 用户类型常量
|
||
const (
|
||
UserTypeDoctor = "doctor" // 后台用户类型(PC管理端)
|
||
UserTypeUser = "user" // 小程序用户类型
|
||
)
|
||
|
||
// 响应结构
|
||
type APIResponse struct {
|
||
Status string `json:"status"`
|
||
Message string `json:"message"`
|
||
Data interface{} `json:"data,omitempty"`
|
||
Error string `json:"error,omitempty"`
|
||
}
|
||
|
||
// 健康检查响应
|
||
type HealthResponse struct {
|
||
Status string `json:"status"`
|
||
Node string `json:"node"`
|
||
Port string `json:"port"`
|
||
Time string `json:"time"`
|
||
}
|
||
|
||
// 绑定响应
|
||
type BindResponse struct {
|
||
Status string `json:"status"`
|
||
Message string `json:"message"`
|
||
UserID string `json:"user_id"`
|
||
ClientID string `json:"client_id"`
|
||
}
|