-- Bidirectional friends as two directed rows, one pending request per pair, reports. CREATE TABLE IF NOT EXISTS friend_relations ( id BIGINT NOT NULL AUTO_INCREMENT COMMENT '行 id,表内自增', user_id BIGINT NOT NULL COMMENT '关系所属用户', friend_id BIGINT NOT NULL COMMENT '对方 user_id', status TINYINT NOT NULL DEFAULT 1 COMMENT '1=好友 0=非好友(仅用于单向拉黑占位)', remark VARCHAR(64) NOT NULL DEFAULT '' COMMENT '备注,仅自己可见', is_blocked TINYINT NOT NULL DEFAULT 0 COMMENT '是否拉黑对方', is_pinned TINYINT NOT NULL DEFAULT 0 COMMENT '会话消息置顶', source TINYINT NOT NULL DEFAULT 0 COMMENT '添加来源:0=未知 1=二维码 2=邮箱 3=spark_id', created_at DATETIME(3) NOT NULL COMMENT '成为好友或建边时间', updated_at DATETIME(3) NOT NULL COMMENT '最近更新时间', PRIMARY KEY (id), UNIQUE KEY uk_user_friend (user_id, friend_id), KEY idx_user_status (user_id, status) ) COMMENT='单向好友边。A 与 B 互为好友时存两行,各自维护备注、拉黑、置顶'; CREATE TABLE IF NOT EXISTS friend_requests ( id BIGINT PRIMARY KEY COMMENT 'Snowflake 申请 id', from_user BIGINT NOT NULL COMMENT '申请人 user_id', to_user BIGINT NOT NULL COMMENT '被申请人 user_id', source TINYINT NOT NULL COMMENT '来源:1=二维码 2=邮箱 3=spark_id', reason VARCHAR(128) NOT NULL DEFAULT '' COMMENT '申请理由', remark VARCHAR(64) NOT NULL DEFAULT '' COMMENT '申请人对对方的备注,同意后写入自己的好友边', status TINYINT NOT NULL DEFAULT 1 COMMENT '1=待处理 2=已同意 3=已拒绝', created_at DATETIME(3) NOT NULL COMMENT '首次申请时间', updated_at DATETIME(3) NOT NULL COMMENT '最近一次申请或处理时间', UNIQUE KEY uk_from_to (from_user, to_user), KEY idx_to_status (to_user, status, updated_at) ) COMMENT='好友申请。同一对 from→to 只保留一行,重复发起覆盖理由与备注'; CREATE TABLE IF NOT EXISTS friend_reports ( id BIGINT PRIMARY KEY COMMENT 'Snowflake 投诉 id', user_id BIGINT NOT NULL COMMENT '投诉人 user_id', target_id BIGINT NOT NULL COMMENT '被投诉人 user_id', reason TINYINT NOT NULL COMMENT '投诉类型:1=垃圾 2=骚扰 3=不实身份 4=其他', detail VARCHAR(512) NOT NULL DEFAULT '' COMMENT '投诉说明', created_at DATETIME(3) NOT NULL COMMENT '投诉时间', KEY idx_user_created (user_id, created_at), KEY idx_target (target_id) ) COMMENT='好友投诉。仅记录,不自动拉黑';