use sea_orm::entity::Set; use sea_orm::entity::prelude::*; use uuid::Uuid; /// 会籍三段式:`joined_at` 记录最近一次入组,`left_at` 记录退出,`banned_at` 记录封禁。 /// 同一 (organization_id, user_id) 只有一行,重新加入时复用该行并清空 `left_at`, /// 这样审计与"这个人在这个组织的全部历史"始终落在同一处。 #[sea_orm::model] #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)] #[sea_orm(table_name = "space_members")] pub struct Model { #[sea_orm(primary_key, auto_increment = false)] pub id: Uuid, #[sea_orm(unique_key = "org_user")] pub organization_id: Uuid, #[sea_orm(indexed, unique_key = "org_user")] pub user_id: i64, pub role: super::SpaceMemberRole, #[sea_orm(default_expr = "Expr::current_timestamp()")] pub joined_at: DateTimeUtc, pub left_at: Option, pub banned_at: Option, #[sea_orm(column_type = "String(StringLen::N(512))")] pub ban_reason: Option, pub invited_by: Option, pub join_method: super::SpaceJoinMethod, #[sea_orm(indexed)] pub invite_id: Option, /// 成员展示别名与头像(旧 `space_members.alias_*`)。 #[sea_orm(column_type = "String(StringLen::N(64))")] pub alias_name: Option, #[sea_orm(column_type = "String(StringLen::N(512))")] pub alias_avatar_url: Option, /// 通知偏好与免打扰设置(旧 `space_members` 同名列表)。 #[sea_orm(default_value = "all")] pub message_notifications: super::MessageNotifications, #[sea_orm(default_value = false)] pub muted: bool, pub mute_until: Option, #[sea_orm(default_value = false)] pub mobile_push: bool, #[sea_orm(default_value = false)] pub suppress_everyone: bool, #[sea_orm(default_value = false)] pub suppress_roles: bool, #[sea_orm(default_value = false)] pub hide_muted_channels: bool, /// 封禁附加信息(旧 `space_bans` 的 expires_at 与四个 allow_* 位)。 pub ban_expires_at: Option, #[sea_orm(default_value = false)] pub ban_allow_agent_join: bool, #[sea_orm(default_value = false)] pub ban_allow_speak: bool, #[sea_orm(default_value = false)] pub ban_allow_push_repo: bool, #[sea_orm(default_value = false)] pub ban_allow_comment_any: bool, pub last_active_at: Option, #[sea_orm(default_value = 1)] pub version: i32, #[sea_orm(belongs_to, from = "organization_id", to = "id", on_delete = "Cascade")] pub organization: BelongsTo, #[sea_orm(belongs_to, from = "user_id", to = "id")] pub user: BelongsTo, } #[async_trait::async_trait] impl ActiveModelBehavior for ActiveModel { async fn before_save(mut self, _db: &C, insert: bool) -> Result where C: ConnectionTrait, { if insert && self.id.is_not_set() { self.id = Set(Uuid::now_v7()); } Ok(self) } }