/** * package model * 作用:定义全系统通用的数据结构(PO 与 DTO)。 * 规范:所有字段均采用 snake_case (下划线命名) 以保持 DB 和 JSON 的高度一致性。 */ package model import "time" // ========================================== // 数据库实体 (PO - Persistent Object) // ========================================== /** * ChatMessage * 对应数据库表:chat_messages * 作用:持久化存储聊天记录,包括文本、多媒体和信令状态。 */ type ChatMessage struct { // 消息唯一标识 ID ID uint `gorm:"primaryKey;comment:消息唯一标识ID" json:"id"` // 房间ID,用于标识聊天室或会话 RoomID string `gorm:"type:varchar(100);index;comment:房间ID" json:"room_id"` // 发送者用户ID SenderUserID string `gorm:"type:varchar(100);index;comment:发送者用户ID" json:"sender_user_id"` // 接收者用户ID ReceiverUserID string `gorm:"type:varchar(100);index;comment:接收者用户ID" json:"receiver_user_id"` // 消息类型 (0:文本, 1:图片, 2:音频, 3:视频, 4:处方, 5:病例, 6:视频通话, 7:语音通话, 8:文件) MessageType int `gorm:"type:int;comment:消息类型" json:"message_type"` // 消息内容或信令数据 Content string `gorm:"type:text;comment:消息内容" json:"content"` // 存储富文本元数据(如URL预览信息的JSON字符串: {"title":"...","image":"..."}) Extra string `gorm:"type:text;comment:扩展字段,存储JSON格式的元数据" json:"extra"` // 通话时长(秒),仅在通话类型的消息中有效 Duration int `gorm:"type:int;comment:通话时长(秒)" json:"duration"` // 关联的通话ID (用于串联信令) CallID string `gorm:"type:varchar(100);index;comment:关联的通话ID" json:"call_id"` // 通话状态 (invite, accepted, ended, rejected, offer, answer, candidate, hangup, etc.) CallStatus string `gorm:"type:varchar(50);comment:通话状态" json:"call_status"` // 创建时间,自动生成 CreatedAt time.Time `gorm:"autoCreateTime;comment:创建时间" json:"created_at"` } // TableName 指定表名和注释 func (ChatMessage) TableName() string { return "chat_messages" } // ========================================== // 交互数据传输对象 (DTO - Data Transfer Object) // ========================================== /** * WsPayload * 作用:WebSocket 传输的最外层通用载荷。 * 逻辑:根据 RequestType 字段决定如何解析 Data。 */ type WsPayload struct { // 请求类型: "bind", "heartbeat", "send_message", "receive_message" RequestType string `json:"request_type"` // 具体数据载荷,结构取决于 RequestType Data interface{} `json:"data"` } /** * SendMessageReq * 作用:客户端发送消息或信令的请求参数结构。 */ type SendMessageReq struct { // [新增] 发送端的 WebSocket ClientID,用于在多端同步时排除自己 SenderClientID string `json:"sender_client_id,omitempty"` // 指定目标客户端ID (选填,用于点对点精确控制) TargetClientID string `json:"target_client_id,omitempty"` // 指定目标用户ID (选填,用于发送给用户的所有设备) ReceiverUserID string `json:"receiver_user_id,omitempty"` // 房间ID RoomID string `json:"room_id"` // 消息类型 MessageType int `json:"message_type"` // 内容 Content string `json:"content"` // 时长 Duration int `json:"duration"` // 辅助字段: 辅助元数据 Extra string `json:"extra,omitempty"` // WebRTC 信令专用字段: 通话唯一ID CallID string `json:"call_id,omitempty"` // WebRTC 信令专用字段: 信令状态 (invite, offer, answer, candidate, hangup) CallStatus string `json:"call_status,omitempty"` } /** * UrlMeta * 作用:URL 预览元数据结构 (存储在 Extra 字段中) */ type UrlMeta struct { // 标题 Title string `json:"title"` // 描述 Description string `json:"description"` // 图片链接 Image string `json:"image"` // 原始URL Url string `json:"url"` } /** * BindReq * 作用:用户绑定请求参数。 */ type BindReq struct { // 用户ID UserID string `json:"user_id"` // WebSocket握手后获得的临时ID ClientID string `json:"client_id"` } /** * ICEServerConfig * 作用:返回给前端的 TURN/STUN 配置信息。 */ type ICEServerConfig struct { // TURN服务器地址列表 Urls []string `json:"urls"` // 鉴权用户名 Username string `json:"username,omitempty"` // 鉴权密码 Credential string `json:"credential,omitempty"` } /** * User * 对应数据库表:users * 作用:用户基本信息表 */ type User struct { // 用户唯一ID ID string `gorm:"primaryKey;type:varchar(100);comment:用户唯一ID" json:"id"` // 邮箱 Email string `gorm:"type:varchar(255);uniqueIndex;comment:邮箱" json:"email"` // 手机号 Phone string `gorm:"type:varchar(20);uniqueIndex;comment:手机号" json:"phone"` // 密码(加密后) Password string `gorm:"type:varchar(255);comment:密码(加密后)" json:"-"` // 用户名称 Name string `gorm:"type:varchar(100);comment:用户名称" json:"name"` // 用户头像URL或字符 Avatar string `gorm:"type:varchar(500);comment:用户头像" json:"avatar"` // 用户描述或签名 Desc string `gorm:"type:varchar(500);comment:用户描述或签名" json:"desc"` // 地区 Region string `gorm:"type:varchar(100);comment:地区" json:"region"` // 创建时间 CreatedAt time.Time `gorm:"autoCreateTime;comment:创建时间" json:"created_at"` // 更新时间 UpdatedAt time.Time `gorm:"autoUpdateTime;comment:更新时间" json:"updated_at"` } // TableName 指定表名和注释 func (User) TableName() string { return "users" } /** * UserContact * 对应数据库表:user_contacts * 作用:用户联系人表,存储好友关系、分组、备注等信息 */ type UserContact struct { // 主键ID ID uint `gorm:"primaryKey;comment:主键ID" json:"id"` // 用户ID - 当前用户 UserID string `gorm:"type:varchar(100);index;comment:用户ID" json:"user_id"` // 联系人ID - 好友的用户ID ContactID string `gorm:"type:varchar(100);index;comment:联系人ID" json:"contact_id"` // 备注名称 - 用户自定义的好友备注 RemarkName string `gorm:"type:varchar(100);comment:备注名称" json:"remark_name"` // 分组ID - 好友所属分组 GroupID uint `gorm:"type:int;index;comment:分组ID" json:"group_id"` // 是否置顶 IsTop bool `gorm:"type:tinyint(1);default:0;comment:是否置顶" json:"is_top"` // 是否免打扰 IsMuted bool `gorm:"type:tinyint(1);default:0;comment:是否免打扰" json:"is_muted"` // 是否特别关心(高优先级提醒,类似 QQ 特别关心) IsSpecialCare bool `gorm:"type:tinyint(1);default:0;comment:是否特别关心" json:"is_special_care"` // 是否拉黑(加入黑名单,不再接收消息/出现在默认列表中) IsBlocked bool `gorm:"type:tinyint(1);default:0;comment:是否拉黑" json:"is_blocked"` // 最后聊天时间 LastChatTime *time.Time `gorm:"type:datetime;comment:最后聊天时间" json:"last_chat_time"` // 最后一条消息 LastMessage string `gorm:"type:text;comment:最后一条消息" json:"last_message"` // 未读消息数 UnreadCount int `gorm:"type:int;default:0;comment:未读消息数" json:"unread_count"` // 创建时间 CreatedAt time.Time `gorm:"autoCreateTime;comment:创建时间" json:"created_at"` // 更新时间 UpdatedAt time.Time `gorm:"autoUpdateTime;comment:更新时间" json:"updated_at"` } // TableName 指定表名和注释 func (UserContact) TableName() string { return "user_contacts" } /** * ContactGroup * 对应数据库表:contact_groups * 作用:联系人分组表 */ type ContactGroup struct { // 主键ID ID uint `gorm:"primaryKey;comment:主键ID" json:"id"` // 用户ID - 分组所属用户 UserID string `gorm:"type:varchar(100);index;comment:用户ID" json:"user_id"` // 分组名称 GroupName string `gorm:"type:varchar(100);comment:分组名称" json:"group_name"` // 排序顺序 SortOrder int `gorm:"type:int;default:0;comment:排序顺序" json:"sort_order"` // 创建时间 CreatedAt time.Time `gorm:"autoCreateTime;comment:创建时间" json:"created_at"` } // TableName 指定表名和注释 func (ContactGroup) TableName() string { return "contact_groups" } /** * ChatRoom * 对应数据库表:chat_rooms * 作用:聊天房间表,支持点对点和群聊 */ type ChatRoom struct { // 房间ID - 主键 RoomID string `gorm:"primaryKey;type:varchar(100);comment:房间ID" json:"room_id"` // 房间类型 - "p2p" 点对点 / "group" 群聊 RoomType string `gorm:"type:varchar(20);index;comment:房间类型" json:"room_type"` // 房间名称 - 群聊时显示 RoomName string `gorm:"type:varchar(200);comment:房间名称" json:"room_name"` // 房间头像 - 群聊时显示 RoomAvatar string `gorm:"type:varchar(500);comment:房间头像" json:"room_avatar"` // 成员列表 - JSON数组 Members string `gorm:"type:text;comment:成员列表JSON" json:"members"` // 创建者ID CreatorID string `gorm:"type:varchar(100);index;comment:创建者ID" json:"creator_id"` // 最后消息时间 LastMessageTime *time.Time `gorm:"type:datetime;index;comment:最后消息时间" json:"last_message_time"` // 最后消息内容 LastMessage string `gorm:"type:text;comment:最后消息内容" json:"last_message"` // 创建时间 CreatedAt time.Time `gorm:"autoCreateTime;comment:创建时间" json:"created_at"` // 更新时间 UpdatedAt time.Time `gorm:"autoUpdateTime;comment:更新时间" json:"updated_at"` } // TableName 指定表名和注释 func (ChatRoom) TableName() string { return "chat_rooms" } /** * FriendRequest * 对应数据库表:friend_requests * 作用:好友申请表 */ type FriendRequest struct { // 主键ID ID uint `gorm:"primaryKey;comment:主键ID" json:"id"` // 发送者用户ID FromUserID string `gorm:"type:varchar(100);index;comment:发送者用户ID" json:"from_user_id"` // 接收者用户ID ToUserID string `gorm:"type:varchar(100);index;comment:接收者用户ID" json:"to_user_id"` // 申请消息 Message string `gorm:"type:text;comment:申请消息" json:"message"` // 状态 - "pending", "accepted", "rejected" Status string `gorm:"type:varchar(20);default:'pending';index;comment:状态" json:"status"` // 创建时间 CreatedAt time.Time `gorm:"autoCreateTime;comment:创建时间" json:"created_at"` // 更新时间 UpdatedAt time.Time `gorm:"autoUpdateTime;comment:更新时间" json:"updated_at"` } // TableName 指定表名和注释 func (FriendRequest) TableName() string { return "friend_requests" } /** * VerificationCode * 对应数据库表:verification_codes * 作用:验证码表 */ type VerificationCode struct { // 主键ID ID uint `gorm:"primaryKey;comment:主键ID" json:"id"` // 邮箱或手机号 Target string `gorm:"type:varchar(255);index;comment:邮箱或手机号" json:"target"` // 验证码 Code string `gorm:"type:varchar(10);comment:验证码" json:"-"` // 类型 - "email" 或 "sms" Type string `gorm:"type:varchar(20);comment:类型" json:"type"` // 过期时间 ExpiresAt time.Time `gorm:"type:datetime;index;comment:过期时间" json:"expires_at"` // 创建时间 CreatedAt time.Time `gorm:"autoCreateTime;comment:创建时间" json:"created_at"` } // TableName 指定表名和注释 func (VerificationCode) TableName() string { return "verification_codes" } /** * Attachment * 对应数据库表:attachments * 作用:附件表,记录上传的文件信息 */ type Attachment struct { // 主键ID ID uint `gorm:"primaryKey;comment:主键ID" json:"id"` // 上传者ID UploaderID string `gorm:"type:varchar(100);index;comment:上传者ID" json:"uploader_id"` // 文件名 FileName string `gorm:"type:varchar(255);comment:文件名" json:"file_name"` // 文件类型 - "image" 或 "video" FileType string `gorm:"type:varchar(20);index;comment:文件类型" json:"file_type"` // 文件大小(字节) FileSize int64 `gorm:"type:bigint;comment:文件大小(字节)" json:"file_size"` // 文件路径 FilePath string `gorm:"type:varchar(500);comment:文件路径" json:"file_path"` // 文件URL FileURL string `gorm:"type:varchar(500);comment:文件URL" json:"file_url"` // MIME类型 MimeType string `gorm:"type:varchar(100);comment:MIME类型" json:"mime_type"` // 宽度(图片/视频) Width int `gorm:"type:int;comment:宽度" json:"width"` // 高度(图片/视频) Height int `gorm:"type:int;comment:高度" json:"height"` // 时长(视频,秒) Duration int `gorm:"type:int;comment:时长(秒)" json:"duration"` // 创建时间 CreatedAt time.Time `gorm:"autoCreateTime;comment:创建时间" json:"created_at"` } // TableName 指定表名和注释 func (Attachment) TableName() string { return "attachments" } /** * ApiRequestLog * 对应数据库表:api_request_logs * 作用:接口请求日志表,记录所有API请求信息 */ type ApiRequestLog struct { // 主键ID ID uint `gorm:"primaryKey;comment:主键ID" json:"id"` // 请求路由 Route string `gorm:"type:varchar(255);index;comment:请求路由" json:"route"` // 请求IP IP string `gorm:"type:varchar(50);index;comment:请求IP" json:"ip"` // IP归属地 IPLocation string `gorm:"type:varchar(255);comment:IP归属地" json:"ip_location"` // 请求用户ID(未登录为0) UserID string `gorm:"type:varchar(100);index;comment:请求用户ID" json:"user_id"` // 请求方式 Method string `gorm:"type:varchar(10);comment:请求方式" json:"method"` // 请求参数(JSON) RequestParams string `gorm:"type:text;comment:请求参数" json:"request_params"` // 返回参数(JSON) ResponseParams string `gorm:"type:text;comment:返回参数" json:"response_params"` // 返回code ResponseCode int `gorm:"type:int;index;comment:返回code" json:"response_code"` // 返回http状态 HTTPStatus int `gorm:"type:int;comment:返回http状态" json:"http_status"` // 请求时间 RequestTime time.Time `gorm:"type:datetime;index;comment:请求时间" json:"request_time"` } // TableName 指定表名和注释 func (ApiRequestLog) TableName() string { return "api_request_logs" } /** * ChatConversation * 对应数据库表:chat_conversations * 作用:用户级别的最近会话列表,支持置顶、免打扰和未读计数等功能 */ type ChatConversation struct { // 主键ID ID uint `gorm:"primaryKey;comment:主键ID" json:"id"` // 所属用户ID(当前登录用户) UserID string `gorm:"type:varchar(100);index;comment:用户ID" json:"user_id"` // 目标ID:好友ID或群ID TargetID string `gorm:"type:varchar(100);index;comment:目标ID(好友或群)" json:"target_id"` // 房间ID:与 chat_messages / chat_rooms 中的 room_id 一致 RoomID string `gorm:"type:varchar(100);index;comment:房间ID" json:"room_id"` // 会话类型:1-私聊 2-群聊 Type int `gorm:"type:int;comment:会话类型(1=私聊,2=群聊)" json:"type"` // 是否置顶 IsTop bool `gorm:"type:tinyint(1);default:0;comment:是否置顶" json:"is_top"` // 是否免打扰 IsMuted bool `gorm:"type:tinyint(1);default:0;comment:是否免打扰" json:"is_muted"` // 是否特别关心(用于在前端高亮显示) IsSpecialCare bool `gorm:"type:tinyint(1);default:0;comment:是否特别关心" json:"is_special_care"` // 未读消息数 UnreadCount int `gorm:"type:int;default:0;comment:未读消息数" json:"unread_count"` // 最后一条消息内容(用于列表摘要) LastMessage string `gorm:"type:varchar(500);comment:最后一条消息内容" json:"last_message"` // 最后消息时间 LastTime time.Time `gorm:"type:datetime;index;comment:最后消息时间" json:"last_time"` // 创建时间 CreatedAt time.Time `gorm:"autoCreateTime;comment:创建时间" json:"created_at"` // 更新时间 UpdatedAt time.Time `gorm:"autoUpdateTime;comment:更新时间" json:"updated_at"` } // TableName 指定表名和注释 func (ChatConversation) TableName() string { return "chat_conversations" } /** * LoginLog * 对应数据库表:login_logs * 作用:登录日志表,记录所有登录尝试 */ type LoginLog struct { // 主键ID ID uint `gorm:"primaryKey;comment:主键ID" json:"id"` // 登录账号 Account string `gorm:"type:varchar(255);index;comment:登录账号" json:"account"` // 登录ID(失败记录0) UserID string `gorm:"type:varchar(100);index;comment:登录ID" json:"user_id"` // 归属地(IP归属地) Location string `gorm:"type:varchar(255);comment:归属地" json:"location"` // 地址(IP地址) IP string `gorm:"type:varchar(50);index;comment:IP地址" json:"ip"` // 成功/失败状态(true=成功,false=失败) Success bool `gorm:"type:tinyint(1);index;comment:成功状态" json:"success"` // 登录时间 LoginTime time.Time `gorm:"type:datetime;index;comment:登录时间" json:"login_time"` } // TableName 指定表名和注释 func (LoginLog) TableName() string { return "login_logs" } /** * ClusterMessage * 作用:内部通信,Redis Pub/Sub 集群消息转发结构。 */ type ClusterMessage struct { // 发出该消息的源节点ID SenderNodeID string `json:"sender_node_id"` // 目标用户ID TargetUserID string `json:"target_user_id"` // 原始消息体 (WsPayload) Payload interface{} `json:"payload"` } // ========================================== // 认证相关 DTO // ========================================== /** * LoginReq * 作用:登录请求参数 */ type LoginReq struct { // 账号(邮箱或手机号) Account string `json:"account" binding:"required"` // 密码 Password string `json:"password" binding:"required"` // 记住我 Remember bool `json:"remember,omitempty"` } /** * RegisterReq * 作用:注册请求参数 */ type RegisterReq struct { // 邮箱 Email string `json:"email" binding:"required,email"` // 手机号 Phone string `json:"phone" binding:"required"` // 密码 Password string `json:"password" binding:"required,min=8"` // 确认密码 ConfirmPassword string `json:"confirm_password" binding:"required"` // 验证码(可选) Code string `json:"code,omitempty"` // 同意用户协议 AgreeTerms bool `json:"agree_terms" binding:"required"` } /** * LoginResponse * 作用:登录响应 */ type LoginResponse struct { // Token Token string `json:"token"` // 用户信息 User User `json:"user"` } /** * RegisterResponse * 作用:注册响应 */ type RegisterResponse struct { // Token Token string `json:"token"` // 用户信息 User User `json:"user"` } /** * SendCodeReq * 作用:发送验证码请求 */ type SendCodeReq struct { // 邮箱或手机号 Target string `json:"target" binding:"required"` // 类型 - "email" 或 "sms" Type string `json:"type" binding:"required,oneof=email sms"` } // ========================================== // 常量定义 // ========================================== const ( // Redis Key 前缀: 用户所在节点映射 (Hash结构或String结构) KeyUserNodeMap = "ws:user:node:" // Redis Channel: 集群广播频道 ChanClusterBroadcast = "ws:cluster:broadcast" // 文件大小限制(字节) MaxImageSize = 10 * 1024 * 1024 // 10MB MaxVideoSize = 500 * 1024 * 1024 // 500MB )