feat(project): init

This commit is contained in:
2026-02-02 14:27:56 +08:00
commit ed3219deb4
46 changed files with 7235 additions and 0 deletions

1
migrations/0001_core.sql Normal file
View File

@@ -0,0 +1 @@
CREATE EXTENSION IF NOT EXISTS pgcrypto;

90
migrations/0002_cms.sql Normal file
View File

@@ -0,0 +1,90 @@
CREATE TYPE cms_tag_kind AS ENUM ('tag', 'category');
CREATE TYPE cms_article_status AS ENUM ('draft', 'published');
CREATE TABLE cms_columns (
tenant_id uuid NOT NULL,
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
name text NOT NULL,
slug text NOT NULL,
description text,
parent_id uuid,
sort_order int NOT NULL DEFAULT 0,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
UNIQUE (tenant_id, slug)
);
CREATE INDEX cms_columns_tenant_parent_idx ON cms_columns (tenant_id, parent_id);
CREATE TABLE cms_tags (
tenant_id uuid NOT NULL,
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
kind cms_tag_kind NOT NULL,
name text NOT NULL,
slug text NOT NULL,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
UNIQUE (tenant_id, kind, slug)
);
CREATE INDEX cms_tags_tenant_kind_idx ON cms_tags (tenant_id, kind);
CREATE TABLE cms_media (
tenant_id uuid NOT NULL,
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
url text NOT NULL,
mime_type text,
size_bytes bigint,
width int,
height int,
created_at timestamptz NOT NULL DEFAULT now(),
created_by uuid
);
CREATE INDEX cms_media_tenant_created_at_idx ON cms_media (tenant_id, created_at DESC);
CREATE TABLE cms_articles (
tenant_id uuid NOT NULL,
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
column_id uuid,
title text NOT NULL,
slug text NOT NULL,
summary text,
content text NOT NULL DEFAULT '',
status cms_article_status NOT NULL DEFAULT 'draft',
current_version int NOT NULL DEFAULT 0,
published_at timestamptz,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
created_by uuid,
updated_by uuid,
UNIQUE (tenant_id, slug)
);
CREATE INDEX cms_articles_tenant_status_updated_idx ON cms_articles (tenant_id, status, updated_at DESC);
CREATE INDEX cms_articles_tenant_column_idx ON cms_articles (tenant_id, column_id);
CREATE TABLE cms_article_tags (
tenant_id uuid NOT NULL,
article_id uuid NOT NULL REFERENCES cms_articles(id) ON DELETE CASCADE,
tag_id uuid NOT NULL REFERENCES cms_tags(id) ON DELETE CASCADE,
PRIMARY KEY (tenant_id, article_id, tag_id)
);
CREATE INDEX cms_article_tags_tenant_tag_idx ON cms_article_tags (tenant_id, tag_id);
CREATE TABLE cms_article_versions (
tenant_id uuid NOT NULL,
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
article_id uuid NOT NULL REFERENCES cms_articles(id) ON DELETE CASCADE,
version int NOT NULL,
title text NOT NULL,
summary text,
content text NOT NULL,
status cms_article_status NOT NULL,
created_at timestamptz NOT NULL DEFAULT now(),
created_by uuid,
UNIQUE (tenant_id, article_id, version)
);
CREATE INDEX cms_article_versions_tenant_article_idx ON cms_article_versions (tenant_id, article_id, version DESC);