-- ============================================================= -- 038: Announcement targeting system (ported from rwadurian) -- 公告定向推送系统: 全体用户 / 按标签 / 指定用户 -- ============================================================= -- 1. 公告主表 CREATE TABLE IF NOT EXISTS announcements ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), title VARCHAR(200) NOT NULL, content TEXT NOT NULL, type VARCHAR(20) NOT NULL DEFAULT 'SYSTEM' CHECK (type IN ('SYSTEM','ACTIVITY','REWARD','UPGRADE','ANNOUNCEMENT')), priority VARCHAR(10) NOT NULL DEFAULT 'NORMAL' CHECK (priority IN ('LOW','NORMAL','HIGH','URGENT')), target_type VARCHAR(10) NOT NULL DEFAULT 'ALL' CHECK (target_type IN ('ALL','BY_TAG','SPECIFIC')), target_config JSONB, image_url VARCHAR(500), link_url VARCHAR(500), is_enabled BOOLEAN NOT NULL DEFAULT true, published_at TIMESTAMPTZ, expires_at TIMESTAMPTZ, created_by UUID, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE INDEX idx_announcements_type ON announcements(type); CREATE INDEX idx_announcements_target ON announcements(target_type); CREATE INDEX idx_announcements_enabled ON announcements(is_enabled, published_at); -- 2. 公告标签定向表 CREATE TABLE IF NOT EXISTS announcement_tag_targets ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), announcement_id UUID NOT NULL REFERENCES announcements(id) ON DELETE CASCADE, tag VARCHAR(100) NOT NULL ); CREATE INDEX idx_ann_tag_targets_ann ON announcement_tag_targets(announcement_id); CREATE INDEX idx_ann_tag_targets_tag ON announcement_tag_targets(tag); -- 3. 公告用户定向表 CREATE TABLE IF NOT EXISTS announcement_user_targets ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), announcement_id UUID NOT NULL REFERENCES announcements(id) ON DELETE CASCADE, user_id UUID NOT NULL ); CREATE INDEX idx_ann_user_targets_ann ON announcement_user_targets(announcement_id); CREATE INDEX idx_ann_user_targets_user ON announcement_user_targets(user_id); -- 4. 公告已读记录表 CREATE TABLE IF NOT EXISTS announcement_reads ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), announcement_id UUID NOT NULL REFERENCES announcements(id) ON DELETE CASCADE, user_id UUID NOT NULL, read_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), UNIQUE (announcement_id, user_id) ); CREATE INDEX idx_ann_reads_user ON announcement_reads(user_id); CREATE INDEX idx_ann_reads_ann ON announcement_reads(announcement_id); -- 5. 用户标签表 CREATE TABLE IF NOT EXISTS user_tags ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL, tag VARCHAR(100) NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), UNIQUE (user_id, tag) ); CREATE INDEX idx_user_tags_user ON user_tags(user_id); CREATE INDEX idx_user_tags_tag ON user_tags(tag);