diff --git a/server/skillhub-app/src/main/resources/db/migration/V3__phase3_review_social_tables.sql b/server/skillhub-app/src/main/resources/db/migration/V3__phase3_review_social_tables.sql new file mode 100644 index 00000000..d15b06e8 --- /dev/null +++ b/server/skillhub-app/src/main/resources/db/migration/V3__phase3_review_social_tables.sql @@ -0,0 +1,79 @@ +-- V3__phase3_review_social_tables.sql +-- Phase 3: 审核工作流、提升、评分/收藏、幂等性 + +-- 审核任务表 +CREATE TABLE review_task ( + id BIGSERIAL PRIMARY KEY, + skill_version_id BIGINT NOT NULL REFERENCES skill_version(id), + namespace_id BIGINT NOT NULL REFERENCES namespace(id), + status VARCHAR(32) NOT NULL DEFAULT 'PENDING', + version INT NOT NULL DEFAULT 1, + submitted_by BIGINT NOT NULL REFERENCES user_account(id), + reviewed_by BIGINT REFERENCES user_account(id), + review_comment TEXT, + submitted_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + reviewed_at TIMESTAMP +); + +CREATE INDEX idx_review_task_namespace_status ON review_task(namespace_id, status); +CREATE INDEX idx_review_task_submitted_by_status ON review_task(submitted_by, status); +CREATE UNIQUE INDEX idx_review_task_version_pending ON review_task(skill_version_id) WHERE status = 'PENDING'; + +-- 提升申请表 +CREATE TABLE promotion_request ( + id BIGSERIAL PRIMARY KEY, + source_skill_id BIGINT NOT NULL REFERENCES skill(id), + source_version_id BIGINT NOT NULL REFERENCES skill_version(id), + target_namespace_id BIGINT NOT NULL REFERENCES namespace(id), + target_skill_id BIGINT REFERENCES skill(id), + status VARCHAR(32) NOT NULL DEFAULT 'PENDING', + version INT NOT NULL DEFAULT 1, + submitted_by BIGINT NOT NULL REFERENCES user_account(id), + reviewed_by BIGINT REFERENCES user_account(id), + review_comment TEXT, + submitted_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + reviewed_at TIMESTAMP +); + +CREATE INDEX idx_promotion_request_source_skill ON promotion_request(source_skill_id); +CREATE INDEX idx_promotion_request_status ON promotion_request(status); +CREATE UNIQUE INDEX idx_promotion_request_version_pending ON promotion_request(source_version_id) WHERE status = 'PENDING'; + +-- 技能收藏表 +CREATE TABLE skill_star ( + id BIGSERIAL PRIMARY KEY, + skill_id BIGINT NOT NULL REFERENCES skill(id), + user_id BIGINT NOT NULL REFERENCES user_account(id), + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + UNIQUE(skill_id, user_id) +); + +CREATE INDEX idx_skill_star_user_id ON skill_star(user_id); +CREATE INDEX idx_skill_star_skill_id ON skill_star(skill_id); + +-- 技能评分表 +CREATE TABLE skill_rating ( + id BIGSERIAL PRIMARY KEY, + skill_id BIGINT NOT NULL REFERENCES skill(id), + user_id BIGINT NOT NULL REFERENCES user_account(id), + score SMALLINT NOT NULL CHECK (score >= 1 AND score <= 5), + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + UNIQUE(skill_id, user_id) +); + +CREATE INDEX idx_skill_rating_skill_id ON skill_rating(skill_id); + +-- 幂等性记录表 +CREATE TABLE idempotency_record ( + request_id VARCHAR(64) PRIMARY KEY, + resource_type VARCHAR(64) NOT NULL, + resource_id BIGINT, + status VARCHAR(32) NOT NULL, + response_status_code INT, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + expires_at TIMESTAMP NOT NULL +); + +CREATE INDEX idx_idempotency_record_expires_at ON idempotency_record(expires_at); +CREATE INDEX idx_idempotency_record_status_created ON idempotency_record(status, created_at);