Files
quyun-v2/specs/DB.sql

340 lines
16 KiB
PL/PgSQL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- QuyUn v2 数据库 DDLPostgreSQL
-- 说明:本文件用于规格参考,需与 backend/database/migrations 保持一致。
BEGIN;
-- Users
CREATE TABLE IF NOT EXISTS users(
id bigserial PRIMARY KEY, -- 主键ID自增
username varchar(255) NOT NULL UNIQUE, -- 用户名:唯一,用于登录
password varchar(255) NOT NULL, -- 密码:加密存储
roles text[] DEFAULT '{user}', -- 角色:用户角色列表,如 {user, super_admin}
status varchar(50) DEFAULT 'active', -- 状态active/inactive/banned
metas jsonb DEFAULT '{}', -- 元数据:额外扩展信息
balance bigint DEFAULT 0, -- 全局可用余额:分/最小货币单位
balance_frozen bigint DEFAULT 0, -- 全局冻结余额:分/最小货币单位
verified_at timestamp with time zone, -- 实名认证时间
nickname varchar(255) DEFAULT '', -- 昵称:用户显示名称
avatar varchar(512) DEFAULT '', -- 头像URL地址
gender varchar(32) DEFAULT 'secret', -- 性别male/female/secret
bio varchar(512) DEFAULT '', -- 简介:用户个人简介
birthday date, -- 生日YYYY-MM-DD
location jsonb DEFAULT '{}', -- 位置:省市区信息 {province: "...", city: "..."}
points bigint DEFAULT 0, -- 积分:用户积分
phone varchar(32) DEFAULT '', -- 手机号:用于登录/验证
is_real_name_verified boolean DEFAULT FALSE, -- 是否实名认证true/false
created_at timestamp with time zone DEFAULT NOW(), -- 创建时间:默认 now()
updated_at timestamp with time zone DEFAULT NOW(), -- 更新时间:默认 now()
deleted_at timestamp with time zone -- 删除时间:软删除
);
-- Tenants
CREATE TABLE IF NOT EXISTS tenants(
id bigserial PRIMARY KEY, -- 主键ID自增
user_id bigint NOT NULL, -- 创建者ID关联 users.id
code varchar(64) NOT NULL UNIQUE, -- 租户代码:唯一标识,用于 URL 等
uuid uuid NOT NULL, -- UUID全局唯一标识
name varchar(128) NOT NULL, -- 租户名称
status varchar(64) NOT NULL, -- 状态pending_verify/verified/banned
config jsonb DEFAULT '{}', -- 配置:租户配置信息
expired_at timestamp with time zone, -- 过期时间:租户有效期
created_at timestamp with time zone DEFAULT NOW(), -- 创建时间:默认 now()
updated_at timestamp with time zone DEFAULT NOW() -- 更新时间:默认 now()
);
CREATE INDEX IF NOT EXISTS idx_tenants_user_id ON tenants(user_id);
-- TenantUsers
CREATE TABLE IF NOT EXISTS tenant_users(
id bigserial PRIMARY KEY, -- 主键ID自增
tenant_id bigint NOT NULL, -- 租户ID关联 tenants.id
user_id bigint NOT NULL, -- 用户ID关联 users.id
role text[] DEFAULT '{member}', -- 角色member/tenant_admin
status varchar(50) DEFAULT 'verified', -- 状态pending_verify/verified/banned
created_at timestamp with time zone DEFAULT NOW(), -- 创建时间:默认 now()
updated_at timestamp with time zone DEFAULT NOW(), -- 更新时间:默认 now()
UNIQUE (tenant_id, user_id)
);
-- Contents
CREATE TABLE IF NOT EXISTS contents(
id bigserial PRIMARY KEY, -- 主键ID自增用于内容引用
tenant_id bigint NOT NULL, -- 租户ID多租户隔离关键字段
user_id bigint NOT NULL, -- 用户ID内容创建者/发布者
title varchar(255) NOT NULL, -- 标题:用于列表展示与搜索
description text NOT NULL, -- 描述:用于详情页展示
status varchar(32) DEFAULT 'draft', -- 状态draft/reviewing/published/unpublished/blocked
visibility varchar(32) DEFAULT 'tenant_only', -- 可见性public/tenant_only/private
preview_seconds int DEFAULT 60, -- 试看秒数:默认 60
preview_downloadable boolean DEFAULT FALSE, -- 试看是否允许下载
published_at timestamp with time zone, -- 发布时间
summary varchar(256) DEFAULT '', -- 简介:用于列表/卡片展示
tags jsonb DEFAULT '[]', -- 标签JSON 数组
body text DEFAULT '', -- 内容主体:文章内容/详细介绍
genre varchar(64) DEFAULT '', -- 类型/流派
views int DEFAULT 0, -- 浏览量
likes int DEFAULT 0, -- 点赞数
key varchar(32) DEFAULT '', -- 音乐调性/主音
is_pinned boolean DEFAULT FALSE, -- 是否置顶
created_at timestamp with time zone DEFAULT NOW(), -- 创建时间
updated_at timestamp with time zone DEFAULT NOW(), -- 更新时间
deleted_at timestamp with time zone -- 软删除时间
);
CREATE INDEX IF NOT EXISTS idx_contents_tenant_id ON contents(tenant_id);
-- MediaAssets
CREATE TABLE IF NOT EXISTS media_assets(
id bigserial PRIMARY KEY, -- 主键ID自增
tenant_id bigint NOT NULL, -- 租户ID多租户隔离关键字段
user_id bigint NOT NULL, -- 用户ID资源上传者
type varchar(32) DEFAULT 'video', -- 资源类型video/audio/image
status varchar(32) DEFAULT 'uploaded', -- 处理状态uploaded/processing/ready/failed/deleted
provider varchar(64) NOT NULL, -- 存储提供方s3/minio/oss/local
bucket varchar(128) NOT NULL, -- 存储桶
object_key varchar(512) NOT NULL, -- 对象键
meta jsonb DEFAULT '{}', -- 元数据JSON
variant varchar(32) DEFAULT 'main', -- 产物类型main/preview
source_asset_id bigint DEFAULT 0, -- 派生来源资源ID
hash varchar(64) DEFAULT '', -- 文件 MD5 哈希
created_at timestamp with time zone DEFAULT NOW(), -- 创建时间
updated_at timestamp with time zone DEFAULT NOW(), -- 更新时间
deleted_at timestamp with time zone -- 软删除时间
);
CREATE INDEX IF NOT EXISTS idx_media_assets_hash ON media_assets (hash);
-- ContentAssets
CREATE TABLE IF NOT EXISTS content_assets(
id bigserial PRIMARY KEY, -- 主键ID自增
tenant_id bigint NOT NULL, -- 租户ID
user_id bigint NOT NULL, -- 用户ID
content_id bigint NOT NULL, -- 内容ID
asset_id bigint NOT NULL, -- 资源ID
role varchar(32) DEFAULT 'main', -- 资源角色main/cover/preview
sort int DEFAULT 0, -- 排序
created_at timestamp with time zone DEFAULT NOW(), -- 创建时间
updated_at timestamp with time zone DEFAULT NOW() -- 更新时间
);
-- ContentPrices
CREATE TABLE IF NOT EXISTS content_prices(
id bigserial PRIMARY KEY, -- 主键ID自增
tenant_id bigint NOT NULL, -- 租户ID
user_id bigint NOT NULL, -- 用户ID
content_id bigint NOT NULL, -- 内容ID
currency varchar(16) DEFAULT 'CNY', -- 币种
price_amount bigint NOT NULL, -- 基础价格:分
discount_type varchar(16) DEFAULT 'none', -- 折扣类型none/percent/amount
discount_value bigint DEFAULT 0, -- 折扣值
discount_start_at timestamp with time zone, -- 折扣开始时间
discount_end_at timestamp with time zone, -- 折扣结束时间
created_at timestamp with time zone DEFAULT NOW(), -- 创建时间
updated_at timestamp with time zone DEFAULT NOW(), -- 更新时间
UNIQUE (tenant_id, content_id)
);
-- ContentAccess
CREATE TABLE IF NOT EXISTS content_access(
id bigserial PRIMARY KEY, -- 主键ID自增
tenant_id bigint NOT NULL, -- 租户ID
user_id bigint NOT NULL, -- 用户ID
content_id bigint NOT NULL, -- 内容ID
order_id bigint DEFAULT 0, -- 订单ID
status varchar(16) DEFAULT 'active', -- 权益状态
revoked_at timestamp with time zone, -- 撤销时间
created_at timestamp with time zone DEFAULT NOW(), -- 创建时间
updated_at timestamp with time zone DEFAULT NOW(), -- 更新时间
UNIQUE (tenant_id, user_id, content_id)
);
-- Orders
CREATE TABLE IF NOT EXISTS orders(
id bigserial PRIMARY KEY, -- 主键ID自增
tenant_id bigint NOT NULL, -- 租户ID
user_id bigint NOT NULL, -- 用户ID
type varchar(32) DEFAULT 'content_purchase', -- 订单类型
status varchar(32) DEFAULT 'created', -- 订单状态
currency varchar(16) DEFAULT 'CNY', -- 币种
amount_original bigint NOT NULL, -- 原价金额
amount_discount bigint NOT NULL, -- 优惠金额
amount_paid bigint NOT NULL, -- 实付金额
snapshot jsonb DEFAULT '{}', -- 订单快照
idempotency_key varchar(128) NOT NULL, -- 幂等键
paid_at timestamp with time zone, -- 支付时间
refunded_at timestamp with time zone, -- 退款时间
refund_forced boolean DEFAULT FALSE, -- 是否强制退款
refund_operator_user_id bigint DEFAULT 0, -- 退款操作人
refund_reason varchar(255) DEFAULT '', -- 退款原因
created_at timestamp with time zone DEFAULT NOW(), -- 创建时间
updated_at timestamp with time zone DEFAULT NOW(), -- 更新时间
coupon_id bigint DEFAULT 0 -- 关联优惠券ID (0表示未使用)
);
-- OrderItems
CREATE TABLE IF NOT EXISTS order_items(
id bigserial PRIMARY KEY, -- 主键ID自增
tenant_id bigint NOT NULL, -- 租户ID
user_id bigint NOT NULL, -- 用户ID
order_id bigint NOT NULL, -- 订单ID
content_id bigint NOT NULL, -- 内容ID
content_user_id bigint NOT NULL, -- 内容作者用户ID
amount_paid bigint NOT NULL, -- 该行实付金额
snapshot jsonb DEFAULT '{}', -- 内容快照
created_at timestamp with time zone DEFAULT NOW(), -- 创建时间
updated_at timestamp with time zone DEFAULT NOW() -- 更新时间
);
-- TenantLedgers
CREATE TABLE IF NOT EXISTS tenant_ledgers(
id bigserial PRIMARY KEY, -- 主键ID自增
tenant_id bigint NOT NULL, -- 租户ID
user_id bigint NOT NULL, -- 用户ID
order_id bigint DEFAULT 0, -- 关联订单ID
type varchar(32) NOT NULL, -- 流水类型
amount bigint NOT NULL, -- 流水金额
balance_before bigint NOT NULL, -- 变更前可用余额
balance_after bigint NOT NULL, -- 变更后可用余额
frozen_before bigint NOT NULL, -- 变更前冻结余额
frozen_after bigint NOT NULL, -- 变更后冻结余额
idempotency_key varchar(128) NOT NULL, -- 幂等键
remark varchar(255) NOT NULL, -- 备注
operator_user_id bigint DEFAULT 0, -- 操作者用户ID
biz_ref_type varchar(32) DEFAULT '', -- 业务引用类型
biz_ref_id bigint DEFAULT 0, -- 业务引用ID
created_at timestamp with time zone DEFAULT NOW(), -- 创建时间
updated_at timestamp with time zone DEFAULT NOW() -- 更新时间
);
-- TenantInvites
CREATE TABLE IF NOT EXISTS tenant_invites(
id bigserial PRIMARY KEY, -- 主键ID自增
tenant_id bigint NOT NULL, -- 租户ID
user_id bigint NOT NULL, -- 创建人用户ID
code varchar(64) NOT NULL, -- 邀请码
status varchar(32) DEFAULT 'active', -- 邀请状态
max_uses int NOT NULL, -- 最大可使用次数
used_count int DEFAULT 0, -- 已使用次数
expires_at timestamp with time zone, -- 过期时间
disabled_at timestamp with time zone, -- 禁用时间
disabled_operator_user_id bigint DEFAULT 0, -- 禁用操作人用户ID
remark varchar(255) DEFAULT '', -- 备注
created_at timestamp with time zone DEFAULT NOW(), -- 创建时间
updated_at timestamp with time zone DEFAULT NOW() -- 更新时间
);
-- TenantJoinRequests
CREATE TABLE IF NOT EXISTS tenant_join_requests(
id bigserial PRIMARY KEY, -- 主键ID自增
tenant_id bigint NOT NULL, -- 租户ID
user_id bigint NOT NULL, -- 申请人用户ID
status varchar(32) DEFAULT 'pending', -- 申请状态
reason varchar(255) NOT NULL, -- 申请原因
decided_at timestamp with time zone, -- 处理时间
decided_operator_user_id bigint DEFAULT 0, -- 处理人用户ID
decided_reason varchar(255) DEFAULT '', -- 处理说明
created_at timestamp with time zone DEFAULT NOW(), -- 创建时间
updated_at timestamp with time zone DEFAULT NOW() -- 更新时间
);
-- Comments
CREATE TABLE IF NOT EXISTS comments(
id bigserial PRIMARY KEY, -- 主键ID自增
tenant_id bigint NOT NULL, -- 租户ID
user_id bigint NOT NULL, -- 用户ID
content_id bigint NOT NULL, -- 内容ID
reply_to bigint DEFAULT 0, -- 回复评论ID0表示一级评论
content text NOT NULL, -- 评论内容
likes int DEFAULT 0, -- 点赞数
created_at timestamp with time zone DEFAULT NOW(), -- 创建时间
updated_at timestamp with time zone DEFAULT NOW(), -- 更新时间
deleted_at timestamp with time zone -- 软删除时间
);
CREATE INDEX IF NOT EXISTS idx_comments_content_id ON comments(content_id);
CREATE INDEX IF NOT EXISTS idx_comments_user_id ON comments(user_id);
-- User Content Actions (Like, Favorite)
CREATE TABLE IF NOT EXISTS user_content_actions(
id bigserial PRIMARY KEY, -- 主键ID自增
user_id bigint NOT NULL, -- 用户ID
content_id bigint NOT NULL, -- 内容ID
type varchar(32) NOT NULL, -- 类型like, favorite
created_at timestamp with time zone DEFAULT NOW(), -- 创建时间
UNIQUE (user_id, content_id, type)
);
-- User Comment Actions (Like)
CREATE TABLE IF NOT EXISTS user_comment_actions(
id bigserial PRIMARY KEY, -- 主键ID自增
user_id bigint NOT NULL, -- 用户ID
comment_id bigint NOT NULL, -- 评论ID
type varchar(32) NOT NULL, -- 类型like
created_at timestamp with time zone DEFAULT NOW(), -- 创建时间
UNIQUE (user_id, comment_id, type)
);
-- Payout Accounts
CREATE TABLE IF NOT EXISTS payout_accounts(
id bigserial PRIMARY KEY, -- 主键ID自增
tenant_id bigint NOT NULL, -- 租户ID
user_id bigint NOT NULL, -- 用户ID
type varchar(32) NOT NULL, -- 类型bank, alipay
name varchar(128) NOT NULL, -- 账户名称/开户行
account varchar(128) NOT NULL, -- 账号
realname varchar(128) NOT NULL, -- 真实姓名
created_at timestamp with time zone DEFAULT NOW(), -- 创建时间
updated_at timestamp with time zone DEFAULT NOW() -- 更新时间
);
CREATE INDEX IF NOT EXISTS idx_payout_accounts_tenant_id ON payout_accounts(tenant_id);
-- Notifications
CREATE TABLE IF NOT EXISTS notifications(
id bigserial PRIMARY KEY, -- 主键ID自增
user_id bigint NOT NULL, -- 接收用户ID
tenant_id bigint DEFAULT 0, -- 来源租户ID
type varchar(32) NOT NULL, -- 类型system, order, audit, interaction
title varchar(255) NOT NULL, -- 标题
content text NOT NULL, -- 内容
is_read boolean DEFAULT FALSE, -- 是否已读
created_at timestamp with time zone DEFAULT NOW() -- 创建时间
);
CREATE INDEX IF NOT EXISTS idx_notifications_user_id ON notifications(user_id);
-- Coupons
CREATE TABLE IF NOT EXISTS coupons(
id bigserial PRIMARY KEY, -- 主键ID
tenant_id bigint NOT NULL DEFAULT 0, -- 租户ID
title varchar(255) NOT NULL, -- 优惠券标题
description text, -- 优惠券描述
type varchar(32) NOT NULL, -- 优惠券类型: fix_amount/discount
value bigint NOT NULL, -- 优惠券面值
min_order_amount bigint NOT NULL DEFAULT 0, -- 最低订单金额门槛
max_discount bigint, -- 最高抵扣金额
total_quantity integer NOT NULL DEFAULT 0, -- 发行总量
used_quantity integer NOT NULL DEFAULT 0, -- 已使用数量
start_at timestamptz, -- 开始生效时间
end_at timestamptz, -- 过期失效时间
created_at timestamptz NOT NULL DEFAULT NOW(),
updated_at timestamptz NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_coupons_tenant_id ON coupons(tenant_id);
CREATE TABLE IF NOT EXISTS user_coupons(
id bigserial PRIMARY KEY,
user_id bigint NOT NULL, -- 用户ID
coupon_id bigint NOT NULL, -- 优惠券ID
order_id bigint, -- 使用该优惠券的订单ID
status varchar(32) NOT NULL DEFAULT 'unused', -- 状态: unused/used/expired
used_at timestamptz, -- 使用时间
created_at timestamptz NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_user_coupons_user_id ON user_coupons(user_id);
CREATE INDEX IF NOT EXISTS idx_user_coupons_coupon_id ON user_coupons(coupon_id);
COMMIT;