-- V1__init_schema.sql -- 初始表结构 -- postgres 扩展 CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; -- ===================================================== -- 用户相关表 -- ===================================================== -- 用户表 CREATE TABLE public.users ( id bigint NOT NULL, mobile character varying(11) NOT NULL, password_hash character varying(255) NOT NULL, access_token text, token_expires_at bigint, avatar_url character varying(500), global_wallet_address character varying(100), is_active boolean DEFAULT true NOT NULL, created_at bigint NOT NULL, updated_at bigint NOT NULL, deleted_at bigint ); CREATE SEQUENCE public.users_id_seq START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE CACHE 1; ALTER TABLE ONLY public.users ALTER COLUMN id SET DEFAULT nextval('public.users_id_seq'::regclass); ALTER TABLE ONLY public.users ADD CONSTRAINT users_pkey PRIMARY KEY (id); CREATE UNIQUE INDEX uk_users_mobile ON public.users USING btree (mobile); CREATE INDEX idx_users_deleted_at ON public.users USING btree (deleted_at); ALTER TABLE ONLY public.users ADD CONSTRAINT fk_users FOREIGN KEY (owner_uid) REFERENCES public.users(id) ON DELETE CASCADE; -- 明星信息表 CREATE TABLE public.stars ( star_id bigint NOT NULL, name character varying(100) NOT NULL, tag character varying(100), name_en character varying(100), pic_url character varying(500), description text, identity_id character varying(50) NOT NULL, is_active boolean DEFAULT true NOT NULL, created_at bigint NOT NULL, updated_at bigint NOT NULL ); CREATE SEQUENCE public.stars_star_id_seq START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE CACHE 1; ALTER TABLE ONLY public.stars ALTER COLUMN star_id SET DEFAULT nextval('public.stars_star_id_seq'::regclass); ALTER TABLE ONLY public.stars ADD CONSTRAINT stars_pkey PRIMARY KEY (star_id); CREATE UNIQUE INDEX uk_stars_identity_id ON public.stars USING btree (identity_id); -- 粉丝档案表 CREATE TABLE public.fan_profiles ( id bigint NOT NULL, user_id bigint NOT NULL, star_id bigint NOT NULL, nickname character varying(50) NOT NULL, level integer DEFAULT 1 NOT NULL, times integer DEFAULT 1 NOT NULL, social integer DEFAULT 0 NOT NULL, experience bigint DEFAULT 0 NOT NULL, coin_balance bigint DEFAULT 0 NOT NULL, crystal_balance bigint DEFAULT 0 NOT NULL, tags jsonb, starbook_limit integer DEFAULT 3 NOT NULL, slot_limit integer DEFAULT 3 NOT NULL, assets_count integer DEFAULT 0 NOT NULL, chain_address character varying(100), is_active boolean DEFAULT true NOT NULL, created_at bigint NOT NULL, updated_at bigint NOT NULL, avatar_url character varying(500) ); CREATE SEQUENCE public.fan_profiles_id_seq START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE CACHE 1; ALTER TABLE ONLY public.fan_profiles ALTER COLUMN id SET DEFAULT nextval('public.fan_profiles_id_seq'::regclass); ALTER TABLE ONLY public.fan_profiles ADD CONSTRAINT fan_profiles_pkey PRIMARY KEY (id); CREATE UNIQUE INDEX uk_fan_profiles_user_star ON public.fan_profiles USING btree (user_id, star_id); CREATE UNIQUE INDEX uk_fan_profiles_star_nickname ON public.fan_profiles USING btree (star_id, nickname); CREATE INDEX idx_fan_profiles_user_id ON public.fan_profiles USING btree (user_id); CREATE INDEX idx_fan_profiles_star_id ON public.fan_profiles USING btree (star_id); ALTER TABLE ONLY public.fan_profiles ADD CONSTRAINT fk_fan_profiles_user FOREIGN KEY (user_id) REFERENCES public.users(id); ALTER TABLE ONLY public.fan_profiles ADD CONSTRAINT fk_fan_profiles_star FOREIGN KEY (star_id) REFERENCES public.stars(star_id); -- ===================================================== -- 藏品相关表 -- ===================================================== -- 资产表(藏品) CREATE TABLE public.assets ( id bigint NOT NULL, owner_uid bigint NOT NULL, star_id bigint NOT NULL, name character varying(100) NOT NULL, cover_url character varying(500) NOT NULL, material_url character varying(500), description text, rarity integer, tags jsonb, visibility character varying(20) DEFAULT 'private'::character varying, status integer DEFAULT 0 NOT NULL, tx_hash character varying(100), block_number bigint, like_count integer DEFAULT 0 NOT NULL, is_original boolean DEFAULT false NOT NULL, created_at bigint NOT NULL, updated_at bigint NOT NULL, minted_at bigint, deleted_at bigint, is_active boolean DEFAULT true NOT NULL, info text ); CREATE SEQUENCE public.assets_id_seq START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE CACHE 1; ALTER TABLE ONLY public.assets ALTER COLUMN id SET DEFAULT nextval('public.assets_id_seq'::regclass); ALTER TABLE ONLY public.assets ADD CONSTRAINT assets_pkey PRIMARY KEY (id); CREATE INDEX idx_assets_created_at ON public.assets USING btree (created_at DESC); CREATE INDEX idx_assets_deleted_at ON public.assets USING btree (deleted_at); CREATE INDEX idx_assets_owner_star ON public.assets USING btree (owner_uid, star_id); CREATE INDEX idx_assets_star_active ON public.assets USING btree (star_id, is_active); CREATE INDEX idx_assets_status ON public.assets USING btree (status); CREATE INDEX idx_assets_tx_hash ON public.assets USING btree (tx_hash); ALTER TABLE ONLY public.assets ADD CONSTRAINT fk_assets_owner FOREIGN KEY (owner_uid) REFERENCES public.users(id) ON DELETE CASCADE; ALTER TABLE ONLY public.assets ADD CONSTRAINT fk_assets_star FOREIGN KEY (star_id) REFERENCES public.stars(star_id) ON DELETE CASCADE; -- 资产注册表(星册体系) CREATE TABLE public.asset_registry ( id bigint NOT NULL, asset_id bigint NOT NULL, asset_type character varying(20) NOT NULL, owner_uid bigint NOT NULL, star_id bigint NOT NULL, grade integer, collection_category character varying(50), activity_id bigint, activity_type character varying(50), status integer DEFAULT 0 NOT NULL, like_count integer DEFAULT 0 NOT NULL, display_status integer DEFAULT 0 NOT NULL, created_at bigint NOT NULL, updated_at bigint NOT NULL ); CREATE SEQUENCE public.asset_registry_id_seq START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE CACHE 1; ALTER TABLE ONLY public.asset_registry ALTER COLUMN id SET DEFAULT nextval('public.asset_registry_id_seq'::regclass); ALTER TABLE ONLY public.asset_registry ADD CONSTRAINT asset_registry_pkey PRIMARY KEY (id); CREATE INDEX idx_registry_owner_star ON public.asset_registry USING btree (owner_uid, star_id); ALTER TABLE ONLY public.asset_registry ADD CONSTRAINT fk_registry_asset FOREIGN KEY (asset_id) REFERENCES public.assets(id) ON DELETE CASCADE; ALTER TABLE ONLY public.asset_registry ADD CONSTRAINT fk_registry_owner FOREIGN KEY (owner_uid) REFERENCES public.users(id) ON DELETE CASCADE; ALTER TABLE ONLY public.asset_registry ADD CONSTRAINT fk_registry_star FOREIGN KEY (star_id) REFERENCES public.stars(star_id) ON DELETE CASCADE; -- 点赞记录表 CREATE TABLE public.asset_likes ( id bigint NOT NULL, asset_id bigint NOT NULL, user_id bigint NOT NULL, star_id bigint NOT NULL, created_at bigint NOT NULL ); CREATE SEQUENCE public.asset_likes_id_seq START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE CACHE 1; ALTER TABLE ONLY public.asset_likes ALTER COLUMN id SET DEFAULT nextval('public.asset_likes_id_seq'::regclass); ALTER TABLE ONLY public.asset_likes ADD CONSTRAINT asset_likes_pkey PRIMARY KEY (id); CREATE UNIQUE INDEX uk_asset_likes_user_asset ON public.asset_likes USING btree (user_id, asset_id); CREATE INDEX idx_asset_likes_asset ON public.asset_likes USING btree (asset_id); CREATE INDEX idx_asset_likes_user_star ON public.asset_likes USING btree (user_id, star_id); ALTER TABLE ONLY public.asset_likes ADD CONSTRAINT fk_asset_likes_asset FOREIGN KEY (asset_id) REFERENCES public.assets(id) ON DELETE CASCADE; ALTER TABLE ONLY public.asset_likes ADD CONSTRAINT fk_asset_likes_star FOREIGN KEY (star_id) REFERENCES public.stars(star_id) ON DELETE CASCADE; ALTER TABLE ONLY public.asset_likes ADD CONSTRAINT fk_asset_likes_user FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; -- 铸造订单表 CREATE TABLE public.mint_orders ( order_id character varying(100) NOT NULL, user_id bigint NOT NULL, asset_id bigint, star_id bigint NOT NULL, status character varying(20) DEFAULT 'PENDING'::character varying NOT NULL, cost_crystal bigint DEFAULT 0, error_message text, retry_count integer DEFAULT 0, material_url character varying(500), name character varying(100), description text, material_type character varying(50), event character varying(100), created_at bigint NOT NULL, updated_at bigint NOT NULL, minted_at bigint, info text ); ALTER TABLE ONLY public.mint_orders ADD CONSTRAINT mint_orders_pkey PRIMARY KEY (order_id); CREATE INDEX idx_mint_orders_asset ON public.mint_orders USING btree (asset_id); CREATE INDEX idx_mint_orders_created_at ON public.mint_orders USING btree (created_at DESC); CREATE INDEX idx_mint_orders_status ON public.mint_orders USING btree (status); CREATE INDEX idx_mint_orders_user_star ON public.mint_orders USING btree (user_id, star_id); ALTER TABLE ONLY public.mint_orders ADD CONSTRAINT fk_mint_orders_asset FOREIGN KEY (asset_id) REFERENCES public.assets(id) ON DELETE SET NULL; ALTER TABLE ONLY public.mint_orders ADD CONSTRAINT fk_mint_orders_star FOREIGN KEY (star_id) REFERENCES public.stars(star_id) ON DELETE CASCADE; ALTER TABLE ONLY public.mint_orders ADD CONSTRAINT fk_mint_orders_user FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; -- ===================================================== -- 展馆相关表 -- ===================================================== -- 展位表 CREATE TABLE public.booth_slots ( slot_id bigint NOT NULL, host_profile_id bigint NOT NULL, user_id bigint NOT NULL, star_id bigint NOT NULL, slot_index bigint NOT NULL, visibility character varying(20) DEFAULT 'public'::character varying, is_enabled boolean DEFAULT false, unlock_type character varying(20), unlock_value bigint, created_at bigint NOT NULL, updated_at bigint NOT NULL ); CREATE SEQUENCE public.booth_slots_slot_id_seq START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE CACHE 1; ALTER TABLE ONLY public.booth_slots ALTER COLUMN slot_id SET DEFAULT nextval('public.booth_slots_slot_id_seq'::regclass); ALTER TABLE ONLY public.booth_slots ADD CONSTRAINT booth_slots_pkey PRIMARY KEY (slot_id); CREATE UNIQUE INDEX idx_host_slot ON public.booth_slots USING btree (host_profile_id, slot_index); CREATE INDEX idx_star_enabled ON public.booth_slots USING btree (star_id); CREATE INDEX idx_user_star ON public.booth_slots USING btree (user_id, star_id); ALTER TABLE ONLY public.booth_slots ADD CONSTRAINT fk_booth_slots_profile FOREIGN KEY (host_profile_id) REFERENCES public.fan_profiles(id) ON DELETE CASCADE; -- 展品展示表 CREATE TABLE public.exhibitions ( id bigint NOT NULL, asset_id bigint NOT NULL, slot_id bigint NOT NULL, host_profile_id bigint NOT NULL, occupier_uid bigint NOT NULL, occupier_star_id bigint NOT NULL, start_time bigint NOT NULL, expire_at bigint NOT NULL, created_at bigint NOT NULL, updated_at bigint NOT NULL, deleted_at bigint ); CREATE SEQUENCE public.exhibitions_id_seq START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE CACHE 1; ALTER TABLE ONLY public.exhibitions ALTER COLUMN id SET DEFAULT nextval('public.exhibitions_id_seq'::regclass); ALTER TABLE ONLY public.exhibitions ADD CONSTRAINT exhibitions_pkey PRIMARY KEY (id); CREATE UNIQUE INDEX uk_asset ON public.exhibitions USING btree (asset_id); CREATE INDEX idx_expire ON public.exhibitions USING btree (expire_at); CREATE INDEX idx_host ON public.exhibitions USING btree (host_profile_id); CREATE INDEX idx_occupier ON public.exhibitions USING btree (occupier_uid, occupier_star_id); CREATE INDEX idx_slot ON public.exhibitions USING btree (slot_id); ALTER TABLE ONLY public.exhibitions ADD CONSTRAINT fk_exhibitions_asset FOREIGN KEY (asset_id) REFERENCES public.assets(id) ON DELETE CASCADE; ALTER TABLE ONLY public.exhibitions ADD CONSTRAINT fk_exhibitions_slot FOREIGN KEY (slot_id) REFERENCES public.booth_slots(slot_id) ON DELETE CASCADE; -- 展览收入记录表 CREATE TABLE public.exhibition_revenue_records ( id bigint NOT NULL, user_id bigint NOT NULL, star_id bigint NOT NULL, exhibition_id bigint NOT NULL, asset_id bigint NOT NULL, slot_id bigint NOT NULL, slot_owner_uid bigint NOT NULL, slot_type character varying(20) NOT NULL, crystal_amount bigint NOT NULL, cycle_start_time bigint NOT NULL, cycle_end_time bigint NOT NULL, status character varying(20) DEFAULT 'claimable'::character varying NOT NULL, claimed_at bigint, created_at bigint NOT NULL ); CREATE SEQUENCE public.exhibition_revenue_records_id_seq START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE CACHE 1; ALTER TABLE ONLY public.exhibition_revenue_records ALTER COLUMN id SET DEFAULT nextval('public.exhibition_revenue_records_id_seq'::regclass); ALTER TABLE ONLY public.exhibition_revenue_records ADD CONSTRAINT exhibition_revenue_records_pkey PRIMARY KEY (id); CREATE INDEX idx_user_revenue ON public.exhibition_revenue_records USING btree (user_id, star_id); -- ===================================================== -- 社交相关表 -- ===================================================== -- 好友请求表 CREATE TABLE public.friend_requests ( id bigint NOT NULL, from_user_id bigint NOT NULL, to_user_id bigint NOT NULL, star_id bigint NOT NULL, message character varying(200), status character varying(20) DEFAULT 'pending'::character varying NOT NULL, created_at bigint NOT NULL, updated_at bigint NOT NULL, expires_at bigint, processed_at bigint ); CREATE SEQUENCE public.friend_requests_id_seq START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE CACHE 1; ALTER TABLE ONLY public.friend_requests ALTER COLUMN id SET DEFAULT nextval('public.friend_requests_id_seq'::regclass); ALTER TABLE ONLY public.friend_requests ADD CONSTRAINT friend_requests_pkey PRIMARY KEY (id); CREATE INDEX idx_friend_requests_expires ON public.friend_requests USING btree (expires_at); CREATE INDEX idx_friend_requests_from_status ON public.friend_requests USING btree (from_user_id, status, created_at DESC); CREATE INDEX idx_friend_requests_star ON public.friend_requests USING btree (star_id); CREATE INDEX idx_friend_requests_to_status ON public.friend_requests USING btree (to_user_id, status, created_at DESC); CREATE INDEX idx_friend_requests_users_star ON public.friend_requests USING btree (from_user_id, to_user_id, star_id, created_at DESC); ALTER TABLE ONLY public.friend_requests ADD CONSTRAINT fk_friend_requests_from_user FOREIGN KEY (from_user_id) REFERENCES public.users(id) ON DELETE CASCADE; ALTER TABLE ONLY public.friend_requests ADD CONSTRAINT fk_friend_requests_to_user FOREIGN KEY (to_user_id) REFERENCES public.users(id) ON DELETE CASCADE; -- 好友关系表 CREATE TABLE public.friendships ( id bigint NOT NULL, user_id bigint NOT NULL, friend_id bigint NOT NULL, star_id bigint NOT NULL, status character varying(20) DEFAULT 'accepted'::character varying NOT NULL, remark character varying(50), intimacy integer DEFAULT 0 NOT NULL, created_at bigint NOT NULL, updated_at bigint NOT NULL ); CREATE SEQUENCE public.friendships_id_seq START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE CACHE 1; ALTER TABLE ONLY public.friendships ALTER COLUMN id SET DEFAULT nextval('public.friendships_id_seq'::regclass); ALTER TABLE ONLY public.friendships ADD CONSTRAINT friendships_pkey PRIMARY KEY (id); CREATE UNIQUE INDEX uk_friendships_user_friend_star ON public.friendships USING btree (user_id, friend_id, star_id); CREATE INDEX idx_friendships_friend_star ON public.friendships USING btree (friend_id); CREATE INDEX idx_friendships_list_query ON public.friendships USING btree (user_id, friend_id, star_id, status, remark, created_at); CREATE INDEX idx_friendships_user_star_created ON public.friendships USING btree (user_id, star_id, created_at DESC); CREATE INDEX idx_friendships_user_star_status ON public.friendships USING btree (user_id, star_id, status); ALTER TABLE ONLY public.friendships ADD CONSTRAINT fk_friendships_friend FOREIGN KEY (friend_id) REFERENCES public.users(id) ON DELETE CASCADE; ALTER TABLE ONLY public.friendships ADD CONSTRAINT fk_friendships_user FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; -- ===================================================== -- 任务相关表 -- ===================================================== -- 任务定义表 CREATE TABLE public.task_definitions ( id bigint NOT NULL, task_key character varying(50) NOT NULL, task_type character varying(20) NOT NULL, name character varying(100) NOT NULL, description text, crystal_reward bigint DEFAULT 0 NOT NULL, exp_reward bigint DEFAULT 0 NOT NULL, sort_order integer DEFAULT 0 NOT NULL, is_active boolean DEFAULT true NOT NULL, created_at bigint NOT NULL, updated_at bigint NOT NULL ); CREATE SEQUENCE public.task_definitions_id_seq START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE CACHE 1; ALTER TABLE ONLY public.task_definitions ALTER COLUMN id SET DEFAULT nextval('public.task_definitions_id_seq'::regclass); ALTER TABLE ONLY public.task_definitions ADD CONSTRAINT task_definitions_pkey PRIMARY KEY (id); CREATE UNIQUE INDEX idx_task_definitions_task_key ON public.task_definitions USING btree (task_key); -- 用户任务进度表 CREATE TABLE public.user_task_progress ( id bigint NOT NULL, user_id bigint NOT NULL, star_id bigint NOT NULL, task_key character varying(50) NOT NULL, status character varying(20) DEFAULT 'pending'::character varying NOT NULL, completed_at bigint, claimed_at bigint, created_at bigint NOT NULL, updated_at bigint NOT NULL ); CREATE SEQUENCE public.user_task_progress_id_seq START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE CACHE 1; ALTER TABLE ONLY public.user_task_progress ALTER COLUMN id SET DEFAULT nextval('public.user_task_progress_id_seq'::regclass); ALTER TABLE ONLY public.user_task_progress ADD CONSTRAINT user_task_progress_pkey PRIMARY KEY (id); CREATE UNIQUE INDEX uk_user_task ON public.user_task_progress USING btree (user_id, star_id, task_key); -- 用户引导状态表 CREATE TABLE public.user_onboarding_status ( id bigint NOT NULL, user_id bigint NOT NULL, star_id bigint NOT NULL, is_onboarding_completed boolean DEFAULT false NOT NULL, is_onboarding_claimed boolean DEFAULT false NOT NULL, has_friend_display_bonus boolean DEFAULT false NOT NULL, onboarding_completed_at bigint, onboarding_claimed_at bigint, created_at bigint NOT NULL, updated_at bigint NOT NULL ); CREATE SEQUENCE public.user_onboarding_status_id_seq START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE CACHE 1; ALTER TABLE ONLY public.user_onboarding_status ALTER COLUMN id SET DEFAULT nextval('public.user_onboarding_status_id_seq'::regclass); ALTER TABLE ONLY public.user_onboarding_status ADD CONSTRAINT user_onboarding_status_pkey PRIMARY KEY (id); CREATE UNIQUE INDEX uk_user_star_onboarding ON public.user_onboarding_status USING btree (user_id, star_id); -- ===================================================== -- 活动相关表 -- ===================================================== -- 活动表 CREATE TABLE public.activities ( id bigint NOT NULL, activity_type character varying(50) NOT NULL, title character varying(100) NOT NULL, description text, star_id bigint NOT NULL, start_time bigint NOT NULL, end_time bigint NOT NULL, target_progress bigint DEFAULT 1000 NOT NULL, current_progress bigint DEFAULT 0 NOT NULL, status character varying(20) DEFAULT 'pending'::character varying, stage_configs jsonb, created_at bigint NOT NULL, updated_at bigint NOT NULL, theme character varying(100), overall_end_time bigint DEFAULT 0 ); CREATE SEQUENCE public.activities_id_seq START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE CACHE 1; ALTER TABLE ONLY public.activities ALTER COLUMN id SET DEFAULT nextval('public.activities_id_seq'::regclass); ALTER TABLE ONLY public.activities ADD CONSTRAINT activities_pkey PRIMARY KEY (id); CREATE INDEX idx_activities_star_id ON public.activities USING btree (star_id); CREATE INDEX idx_activities_start_end ON public.activities USING btree (start_time, end_time); CREATE INDEX idx_activities_status ON public.activities USING btree (status); -- 活动道具表 CREATE TABLE public.activity_items ( id bigint NOT NULL, activity_id bigint NOT NULL, item_type character varying(50) NOT NULL, item_name character varying(50) NOT NULL, icon_url character varying(500), crystal_cost bigint NOT NULL, contribution_points bigint NOT NULL, sort_order integer DEFAULT 0 NOT NULL, is_active boolean DEFAULT true NOT NULL, created_at bigint NOT NULL, updated_at bigint NOT NULL ); CREATE SEQUENCE public.activity_items_id_seq START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE CACHE 1; ALTER TABLE ONLY public.activity_items ALTER COLUMN id SET DEFAULT nextval('public.activity_items_id_seq'::regclass); ALTER TABLE ONLY public.activity_items ADD CONSTRAINT activity_items_pkey PRIMARY KEY (id); CREATE INDEX idx_activity_items_activity ON public.activity_items USING btree (activity_id); CREATE INDEX idx_activity_items_type ON public.activity_items USING btree (item_type); ALTER TABLE ONLY public.activity_items ADD CONSTRAINT fk_activity_items_activity FOREIGN KEY (activity_id) REFERENCES public.activities(id) ON DELETE CASCADE; -- 活动贡献记录表 CREATE TABLE public.activity_contributions ( id bigint NOT NULL, activity_id bigint NOT NULL, user_id bigint NOT NULL, star_id bigint NOT NULL, item_id bigint NOT NULL, item_type character varying(50) NOT NULL, quantity integer DEFAULT 1 NOT NULL, crystal_spent bigint NOT NULL, contribution_points bigint NOT NULL, created_at bigint NOT NULL ); CREATE SEQUENCE public.activity_contributions_id_seq START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE CACHE 1; ALTER TABLE ONLY public.activity_contributions ALTER COLUMN id SET DEFAULT nextval('public.activity_contributions_id_seq'::regclass); ALTER TABLE ONLY public.activity_contributions ADD CONSTRAINT activity_contributions_pkey PRIMARY KEY (id); CREATE INDEX idx_activity_contributions_activity ON public.activity_contributions USING btree (activity_id); CREATE INDEX idx_activity_contributions_created ON public.activity_contributions USING btree (created_at DESC); CREATE INDEX idx_activity_contributions_user_star ON public.activity_contributions USING btree (user_id, star_id); ALTER TABLE ONLY public.activity_contributions ADD CONSTRAINT fk_activity_contributions_activity FOREIGN KEY (activity_id) REFERENCES public.activities(id) ON DELETE CASCADE; ALTER TABLE ONLY public.activity_contributions ADD CONSTRAINT fk_activity_contributions_item FOREIGN KEY (item_id) REFERENCES public.activity_items(id) ON DELETE CASCADE; ALTER TABLE ONLY public.activity_contributions ADD CONSTRAINT fk_activity_contributions_star FOREIGN KEY (star_id) REFERENCES public.stars(star_id) ON DELETE CASCADE; ALTER TABLE ONLY public.activity_contributions ADD CONSTRAINT fk_activity_contributions_user FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; -- 用户活动统计表 CREATE TABLE public.activity_user_stats ( id bigint NOT NULL, activity_id bigint NOT NULL, user_id bigint NOT NULL, star_id bigint NOT NULL, total_contribution bigint DEFAULT 0 NOT NULL, total_crystal_spent bigint DEFAULT 0 NOT NULL, total_items integer DEFAULT 0 NOT NULL, last_contribute_at bigint NOT NULL, created_at bigint NOT NULL, updated_at bigint NOT NULL ); CREATE SEQUENCE public.activity_user_stats_id_seq START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE CACHE 1; ALTER TABLE ONLY public.activity_user_stats ALTER COLUMN id SET DEFAULT nextval('public.activity_user_stats_id_seq'::regclass); ALTER TABLE ONLY public.activity_user_stats ADD CONSTRAINT activity_user_stats_pkey PRIMARY KEY (id); CREATE UNIQUE INDEX uk_activity_user_star ON public.activity_user_stats UNIQUE (activity_id, user_id, star_id); CREATE INDEX idx_activity_user_stats_activity ON public.activity_user_stats USING btree (activity_id); CREATE INDEX idx_activity_user_stats_contribution ON public.activity_user_stats USING btree (activity_id, total_contribution DESC); CREATE INDEX idx_activity_user_stats_user_star ON public.activity_user_stats USING btree (user_id, star_id); ALTER TABLE ONLY public.activity_user_stats ADD CONSTRAINT fk_activity_user_stats_activity FOREIGN KEY (activity_id) REFERENCES public.activities(id) ON DELETE CASCADE; ALTER TABLE ONLY public.activity_user_stats ADD CONSTRAINT fk_activity_user_stats_star FOREIGN KEY (star_id) REFERENCES public.stars(star_id) ON DELETE CASCADE; ALTER TABLE ONLY public.activity_user_stats ADD CONSTRAINT fk_activity_user_stats_user FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;