Files
K12Study/init/pg/course/10_create_course_tables.sql
2026-04-16 11:30:30 +08:00

513 lines
29 KiB
SQL
Raw Permalink 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.

DROP SCHEMA IF EXISTS course CASCADE;
CREATE SCHEMA IF NOT EXISTS course;
DROP TABLE IF EXISTS course.cl_course CASCADE;
CREATE TABLE IF NOT EXISTS course.cl_course (
course_id VARCHAR(64) PRIMARY KEY,
title VARCHAR(256) NOT NULL,
subject_code VARCHAR(32) NOT NULL,
grade_code VARCHAR(32) NOT NULL,
difficulty_level VARCHAR(16),
status VARCHAR(32) NOT NULL DEFAULT 'DRAFT',
adcode VARCHAR(12) NOT NULL,
tenant_id VARCHAR(64) NOT NULL,
tenant_path VARCHAR(255) NOT NULL,
dept_id VARCHAR(64),
dept_path VARCHAR(255),
created_by VARCHAR(64),
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
COMMENT ON TABLE course.cl_course IS '课程主表';
COMMENT ON COLUMN course.cl_course.course_id IS '课程ID';
COMMENT ON COLUMN course.cl_course.title IS '课程标题';
COMMENT ON COLUMN course.cl_course.subject_code IS '学科编码';
COMMENT ON COLUMN course.cl_course.grade_code IS '年级编码';
COMMENT ON COLUMN course.cl_course.difficulty_level IS '难度等级';
COMMENT ON COLUMN course.cl_course.status IS '状态DRAFT/PUBLISHED/ARCHIVED';
COMMENT ON COLUMN course.cl_course.adcode IS '行政区划编码';
COMMENT ON COLUMN course.cl_course.tenant_id IS '租户ID';
COMMENT ON COLUMN course.cl_course.tenant_path IS '租户路径';
COMMENT ON COLUMN course.cl_course.dept_id IS '部门ID';
COMMENT ON COLUMN course.cl_course.dept_path IS '部门路径';
COMMENT ON COLUMN course.cl_course.created_by IS '创建人ID';
COMMENT ON COLUMN course.cl_course.created_at IS '创建时间';
DROP TABLE IF EXISTS course.cl_course_chapter CASCADE;
CREATE TABLE IF NOT EXISTS course.cl_course_chapter (
chapter_id VARCHAR(64) PRIMARY KEY,
course_id VARCHAR(64) NOT NULL,
chapter_no INTEGER NOT NULL,
chapter_title VARCHAR(256) NOT NULL,
adcode VARCHAR(12) NOT NULL,
tenant_id VARCHAR(64) NOT NULL,
tenant_path VARCHAR(255) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT fk_cl_course_chapter_course
FOREIGN KEY (course_id) REFERENCES course.cl_course(course_id)
);
COMMENT ON TABLE course.cl_course_chapter IS '课程章节表';
COMMENT ON COLUMN course.cl_course_chapter.chapter_id IS '章节ID';
COMMENT ON COLUMN course.cl_course_chapter.course_id IS '课程ID';
COMMENT ON COLUMN course.cl_course_chapter.chapter_no IS '章节序号';
COMMENT ON COLUMN course.cl_course_chapter.chapter_title IS '章节标题';
COMMENT ON COLUMN course.cl_course_chapter.adcode IS '行政区划编码';
COMMENT ON COLUMN course.cl_course_chapter.tenant_id IS '租户ID';
COMMENT ON COLUMN course.cl_course_chapter.tenant_path IS '租户路径';
COMMENT ON COLUMN course.cl_course_chapter.created_at IS '创建时间';
DROP TABLE IF EXISTS course.cl_course_node CASCADE;
CREATE TABLE IF NOT EXISTS course.cl_course_node (
node_id VARCHAR(64) PRIMARY KEY,
chapter_id VARCHAR(64) NOT NULL,
node_no INTEGER NOT NULL,
node_title VARCHAR(256) NOT NULL,
node_type VARCHAR(32) NOT NULL DEFAULT 'LESSON',
class_type VARCHAR(32),
duration_sec INTEGER,
adcode VARCHAR(12) NOT NULL,
tenant_id VARCHAR(64) NOT NULL,
tenant_path VARCHAR(255) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT chk_cl_course_node_type
CHECK (node_type IN ('LESSON', 'IN_CLASS_ACTIVITY', 'AFTER_CLASS_TASK', 'MATERIAL', 'OTHER')),
CONSTRAINT fk_cl_course_node_chapter
FOREIGN KEY (chapter_id) REFERENCES course.cl_course_chapter(chapter_id)
);
COMMENT ON TABLE course.cl_course_node IS '课程学习节点表';
COMMENT ON COLUMN course.cl_course_node.node_id IS '学习节点ID';
COMMENT ON COLUMN course.cl_course_node.chapter_id IS '章节ID';
COMMENT ON COLUMN course.cl_course_node.node_no IS '节点序号';
COMMENT ON COLUMN course.cl_course_node.node_title IS '节点标题';
COMMENT ON COLUMN course.cl_course_node.node_type IS '节点类型LESSON/IN_CLASS_ACTIVITY/AFTER_CLASS_TASK/MATERIAL/OTHER';
COMMENT ON COLUMN course.cl_course_node.class_type IS '课堂类型(如讲授/讨论/测验)';
COMMENT ON COLUMN course.cl_course_node.duration_sec IS '时长(秒)';
COMMENT ON COLUMN course.cl_course_node.adcode IS '行政区划编码';
COMMENT ON COLUMN course.cl_course_node.tenant_id IS '租户ID';
COMMENT ON COLUMN course.cl_course_node.tenant_path IS '租户路径';
COMMENT ON COLUMN course.cl_course_node.created_at IS '创建时间';
DROP TABLE IF EXISTS course.cl_knowledge_point CASCADE;
CREATE TABLE IF NOT EXISTS course.cl_knowledge_point (
kp_id VARCHAR(64) PRIMARY KEY,
kp_code VARCHAR(64) NOT NULL,
kp_name VARCHAR(256) NOT NULL,
kp_alias VARCHAR(256),
kp_type VARCHAR(32) NOT NULL DEFAULT 'ATOMIC',
parent_kp_id VARCHAR(64),
kp_path VARCHAR(512),
kp_desc TEXT,
subject_code VARCHAR(32) NOT NULL,
grade_code VARCHAR(32) NOT NULL,
difficulty_level VARCHAR(16),
importance_level NUMERIC(6,4) NOT NULL DEFAULT 1.0000,
graph_entity_id VARCHAR(64),
source_db VARCHAR(64) NOT NULL DEFAULT 'postgresql',
source_table VARCHAR(128) NOT NULL DEFAULT 'course.cl_knowledge_point',
source_pk VARCHAR(128),
metadata_json JSONB NOT NULL DEFAULT '{}'::JSONB,
status VARCHAR(32) NOT NULL DEFAULT 'ACTIVE',
adcode VARCHAR(12) NOT NULL,
tenant_id VARCHAR(64) NOT NULL,
tenant_path VARCHAR(255) NOT NULL,
dept_id VARCHAR(64),
dept_path VARCHAR(255),
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT uq_cl_knowledge_point_tenant_code
UNIQUE (tenant_id, kp_code),
CONSTRAINT uq_cl_knowledge_point_tenant_graph_entity
UNIQUE (tenant_id, graph_entity_id),
CONSTRAINT chk_cl_knowledge_point_type
CHECK (kp_type IN ('DOMAIN', 'TOPIC', 'ATOMIC')),
CONSTRAINT chk_cl_knowledge_point_importance
CHECK (importance_level > 0 AND importance_level <= 1),
CONSTRAINT chk_cl_knowledge_point_metadata_json
CHECK (jsonb_typeof(metadata_json) = 'object'),
CONSTRAINT fk_cl_knowledge_point_parent
FOREIGN KEY (parent_kp_id) REFERENCES course.cl_knowledge_point(kp_id) ON DELETE SET NULL
);
COMMENT ON TABLE course.cl_knowledge_point IS '知识点表';
COMMENT ON COLUMN course.cl_knowledge_point.kp_id IS '知识点ID';
COMMENT ON COLUMN course.cl_knowledge_point.kp_code IS '知识点编码';
COMMENT ON COLUMN course.cl_knowledge_point.kp_name IS '知识点名称';
COMMENT ON COLUMN course.cl_knowledge_point.kp_alias IS '知识点别名';
COMMENT ON COLUMN course.cl_knowledge_point.kp_type IS '知识点类型DOMAIN/TOPIC/ATOMIC';
COMMENT ON COLUMN course.cl_knowledge_point.parent_kp_id IS '父知识点ID';
COMMENT ON COLUMN course.cl_knowledge_point.kp_path IS '知识点树路径';
COMMENT ON COLUMN course.cl_knowledge_point.kp_desc IS '知识点描述';
COMMENT ON COLUMN course.cl_knowledge_point.subject_code IS '学科编码';
COMMENT ON COLUMN course.cl_knowledge_point.grade_code IS '年级编码';
COMMENT ON COLUMN course.cl_knowledge_point.difficulty_level IS '难度等级';
COMMENT ON COLUMN course.cl_knowledge_point.importance_level IS '重要性权重0,1]';
COMMENT ON COLUMN course.cl_knowledge_point.graph_entity_id IS '图谱实体IDNebula/Neo4j 映射)';
COMMENT ON COLUMN course.cl_knowledge_point.source_db IS '来源数据库';
COMMENT ON COLUMN course.cl_knowledge_point.source_table IS '来源表';
COMMENT ON COLUMN course.cl_knowledge_point.source_pk IS '来源主键';
COMMENT ON COLUMN course.cl_knowledge_point.metadata_json IS '扩展元数据JSON';
COMMENT ON COLUMN course.cl_knowledge_point.status IS '状态ACTIVE/DISABLED';
COMMENT ON COLUMN course.cl_knowledge_point.adcode IS '行政区划编码';
COMMENT ON COLUMN course.cl_knowledge_point.tenant_id IS '租户ID';
COMMENT ON COLUMN course.cl_knowledge_point.tenant_path IS '租户路径';
COMMENT ON COLUMN course.cl_knowledge_point.dept_id IS '部门ID';
COMMENT ON COLUMN course.cl_knowledge_point.dept_path IS '部门路径';
COMMENT ON COLUMN course.cl_knowledge_point.created_at IS '创建时间';
COMMENT ON COLUMN course.cl_knowledge_point.updated_at IS '更新时间';
DROP TABLE IF EXISTS course.cl_chapter_kp_rel CASCADE;
CREATE TABLE IF NOT EXISTS course.cl_chapter_kp_rel (
chapter_id VARCHAR(64) NOT NULL,
kp_id VARCHAR(64) NOT NULL,
relation_type VARCHAR(32) NOT NULL DEFAULT 'TEACHES',
weight NUMERIC(6,4) NOT NULL DEFAULT 1.0000,
is_core BOOLEAN NOT NULL DEFAULT FALSE,
tenant_id VARCHAR(64) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (chapter_id, kp_id),
CONSTRAINT chk_cl_chapter_kp_rel_type
CHECK (relation_type IN ('TEACHES', 'REVIEWS', 'EXTENDS')),
CONSTRAINT chk_cl_chapter_kp_rel_weight
CHECK (weight > 0 AND weight <= 1),
CONSTRAINT fk_cl_chapter_kp_rel_chapter
FOREIGN KEY (chapter_id) REFERENCES course.cl_course_chapter(chapter_id),
CONSTRAINT fk_cl_chapter_kp_rel_kp
FOREIGN KEY (kp_id) REFERENCES course.cl_knowledge_point(kp_id)
);
COMMENT ON TABLE course.cl_chapter_kp_rel IS '章节-知识点关联表';
COMMENT ON COLUMN course.cl_chapter_kp_rel.chapter_id IS '章节ID';
COMMENT ON COLUMN course.cl_chapter_kp_rel.kp_id IS '知识点ID';
COMMENT ON COLUMN course.cl_chapter_kp_rel.relation_type IS '关系类型TEACHES/REVIEWS/EXTENDS';
COMMENT ON COLUMN course.cl_chapter_kp_rel.weight IS '关联权重0,1]';
COMMENT ON COLUMN course.cl_chapter_kp_rel.is_core IS '是否核心知识点';
COMMENT ON COLUMN course.cl_chapter_kp_rel.tenant_id IS '租户ID';
COMMENT ON COLUMN course.cl_chapter_kp_rel.created_at IS '创建时间';
COMMENT ON COLUMN course.cl_chapter_kp_rel.updated_at IS '更新时间';
DROP TABLE IF EXISTS course.cl_student_kp_mastery CASCADE;
CREATE TABLE IF NOT EXISTS course.cl_student_kp_mastery (
mastery_id VARCHAR(64) PRIMARY KEY,
student_id VARCHAR(64) NOT NULL,
kp_id VARCHAR(64) NOT NULL,
mastery_score NUMERIC(6,4) NOT NULL DEFAULT 0,
mastery_level VARCHAR(16) NOT NULL DEFAULT 'UNKNOWN',
mastery_status VARCHAR(16) NOT NULL DEFAULT 'LEARNING',
evidence_json JSONB NOT NULL DEFAULT '{}'::JSONB,
last_source_type VARCHAR(32),
last_source_id VARCHAR(64),
last_assessed_at TIMESTAMP,
adcode VARCHAR(12) NOT NULL,
tenant_id VARCHAR(64) NOT NULL,
tenant_path VARCHAR(255) NOT NULL,
dept_id VARCHAR(64),
dept_path VARCHAR(255),
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT uq_cl_student_kp_mastery_student_kp
UNIQUE (student_id, kp_id),
CONSTRAINT chk_cl_student_kp_mastery_score
CHECK (mastery_score >= 0 AND mastery_score <= 1),
CONSTRAINT chk_cl_student_kp_mastery_level
CHECK (mastery_level IN ('UNKNOWN', 'LOW', 'MEDIUM', 'HIGH', 'MASTERED')),
CONSTRAINT chk_cl_student_kp_mastery_status
CHECK (mastery_status IN ('LEARNING', 'STABLE', 'FORGOTTEN')),
CONSTRAINT chk_cl_student_kp_mastery_evidence_json
CHECK (jsonb_typeof(evidence_json) = 'object'),
CONSTRAINT fk_cl_student_kp_mastery_student
FOREIGN KEY (student_id) REFERENCES upms.tb_sys_user(user_id),
CONSTRAINT fk_cl_student_kp_mastery_kp
FOREIGN KEY (kp_id) REFERENCES course.cl_knowledge_point(kp_id)
);
COMMENT ON TABLE course.cl_student_kp_mastery IS '学生知识点掌握度表';
COMMENT ON COLUMN course.cl_student_kp_mastery.mastery_id IS '掌握度记录ID';
COMMENT ON COLUMN course.cl_student_kp_mastery.student_id IS '学生ID';
COMMENT ON COLUMN course.cl_student_kp_mastery.kp_id IS '知识点ID';
COMMENT ON COLUMN course.cl_student_kp_mastery.mastery_score IS '掌握度分值0-1';
COMMENT ON COLUMN course.cl_student_kp_mastery.mastery_level IS '掌握等级';
COMMENT ON COLUMN course.cl_student_kp_mastery.mastery_status IS '掌握状态LEARNING/STABLE/FORGOTTEN';
COMMENT ON COLUMN course.cl_student_kp_mastery.evidence_json IS '证据数据JSON错题、批改、学习行为等';
COMMENT ON COLUMN course.cl_student_kp_mastery.last_source_type IS '最近更新来源类型';
COMMENT ON COLUMN course.cl_student_kp_mastery.last_source_id IS '最近更新来源ID';
COMMENT ON COLUMN course.cl_student_kp_mastery.last_assessed_at IS '最近评估时间';
COMMENT ON COLUMN course.cl_student_kp_mastery.adcode IS '行政区划编码';
COMMENT ON COLUMN course.cl_student_kp_mastery.tenant_id IS '租户ID';
COMMENT ON COLUMN course.cl_student_kp_mastery.tenant_path IS '租户路径';
COMMENT ON COLUMN course.cl_student_kp_mastery.dept_id IS '部门ID';
COMMENT ON COLUMN course.cl_student_kp_mastery.dept_path IS '部门路径';
COMMENT ON COLUMN course.cl_student_kp_mastery.created_at IS '创建时间';
COMMENT ON COLUMN course.cl_student_kp_mastery.updated_at IS '更新时间';
DROP TABLE IF EXISTS course.cl_kp_material_rel CASCADE;
CREATE TABLE IF NOT EXISTS course.cl_kp_material_rel (
rel_id VARCHAR(64) PRIMARY KEY,
kp_id VARCHAR(64) NOT NULL,
material_type VARCHAR(32) NOT NULL,
material_ref_id VARCHAR(64) NOT NULL,
material_uri VARCHAR(512),
weight NUMERIC(6,4) NOT NULL DEFAULT 1.0000,
source_table VARCHAR(128),
source_pk VARCHAR(128),
tenant_id VARCHAR(64) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT chk_cl_kp_material_rel_type
CHECK (material_type IN ('VECTOR_DOCUMENT', 'VECTOR_CHUNK', 'COURSE_RESOURCE', 'EXTERNAL_URI')),
CONSTRAINT chk_cl_kp_material_rel_weight
CHECK (weight > 0 AND weight <= 1),
CONSTRAINT fk_cl_kp_material_rel_kp
FOREIGN KEY (kp_id) REFERENCES course.cl_knowledge_point(kp_id)
);
COMMENT ON TABLE course.cl_kp_material_rel IS '知识点-学习资料关联表';
COMMENT ON COLUMN course.cl_kp_material_rel.rel_id IS '关联ID';
COMMENT ON COLUMN course.cl_kp_material_rel.kp_id IS '知识点ID';
COMMENT ON COLUMN course.cl_kp_material_rel.material_type IS '资料类型VECTOR_DOCUMENT/VECTOR_CHUNK/COURSE_RESOURCE/EXTERNAL_URI';
COMMENT ON COLUMN course.cl_kp_material_rel.material_ref_id IS '资料对象ID';
COMMENT ON COLUMN course.cl_kp_material_rel.material_uri IS '资料URI';
COMMENT ON COLUMN course.cl_kp_material_rel.weight IS '关联权重0,1]';
COMMENT ON COLUMN course.cl_kp_material_rel.source_table IS '来源表';
COMMENT ON COLUMN course.cl_kp_material_rel.source_pk IS '来源主键';
COMMENT ON COLUMN course.cl_kp_material_rel.tenant_id IS '租户ID';
COMMENT ON COLUMN course.cl_kp_material_rel.created_at IS '创建时间';
COMMENT ON COLUMN course.cl_kp_material_rel.updated_at IS '更新时间';
DROP TABLE IF EXISTS course.cl_course_knowledge_rel CASCADE;
CREATE TABLE IF NOT EXISTS course.cl_course_knowledge_rel (
course_id VARCHAR(64) NOT NULL,
kp_id VARCHAR(64) NOT NULL,
weight NUMERIC(6,4) NOT NULL DEFAULT 1.0000,
tenant_id VARCHAR(64) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (course_id, kp_id),
CONSTRAINT chk_cl_course_knowledge_rel_weight
CHECK (weight > 0 AND weight <= 1),
CONSTRAINT fk_cl_course_knowledge_rel_course
FOREIGN KEY (course_id) REFERENCES course.cl_course(course_id),
CONSTRAINT fk_cl_course_knowledge_rel_kp
FOREIGN KEY (kp_id) REFERENCES course.cl_knowledge_point(kp_id)
);
COMMENT ON TABLE course.cl_course_knowledge_rel IS '课程-知识点关联表';
COMMENT ON COLUMN course.cl_course_knowledge_rel.course_id IS '课程ID';
COMMENT ON COLUMN course.cl_course_knowledge_rel.kp_id IS '知识点ID';
COMMENT ON COLUMN course.cl_course_knowledge_rel.weight IS '关联权重0,1]';
COMMENT ON COLUMN course.cl_course_knowledge_rel.tenant_id IS '租户ID';
COMMENT ON COLUMN course.cl_course_knowledge_rel.created_at IS '创建时间';
DROP TABLE IF EXISTS course.cl_course_tag CASCADE;
CREATE TABLE IF NOT EXISTS course.cl_course_tag (
tag_id VARCHAR(64) PRIMARY KEY,
tag_name VARCHAR(128) NOT NULL,
tag_type VARCHAR(32) NOT NULL,
tenant_id VARCHAR(64) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
COMMENT ON TABLE course.cl_course_tag IS '课程标签表';
COMMENT ON COLUMN course.cl_course_tag.tag_id IS '标签ID';
COMMENT ON COLUMN course.cl_course_tag.tag_name IS '标签名称';
COMMENT ON COLUMN course.cl_course_tag.tag_type IS '标签类型';
COMMENT ON COLUMN course.cl_course_tag.tenant_id IS '租户ID';
COMMENT ON COLUMN course.cl_course_tag.created_at IS '创建时间';
DROP TABLE IF EXISTS course.cl_course_tag_rel CASCADE;
CREATE TABLE IF NOT EXISTS course.cl_course_tag_rel (
course_id VARCHAR(64) NOT NULL,
tag_id VARCHAR(64) NOT NULL,
tenant_id VARCHAR(64) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (course_id, tag_id),
CONSTRAINT fk_cl_course_tag_rel_course
FOREIGN KEY (course_id) REFERENCES course.cl_course(course_id),
CONSTRAINT fk_cl_course_tag_rel_tag
FOREIGN KEY (tag_id) REFERENCES course.cl_course_tag(tag_id)
);
COMMENT ON TABLE course.cl_course_tag_rel IS '课程-标签关联表';
COMMENT ON COLUMN course.cl_course_tag_rel.course_id IS '课程ID';
COMMENT ON COLUMN course.cl_course_tag_rel.tag_id IS '标签ID';
COMMENT ON COLUMN course.cl_course_tag_rel.tenant_id IS '租户ID';
COMMENT ON COLUMN course.cl_course_tag_rel.created_at IS '创建时间';
DROP TABLE IF EXISTS course.cl_node_resource CASCADE;
CREATE TABLE IF NOT EXISTS course.cl_node_resource (
resource_id VARCHAR(64) PRIMARY KEY,
node_id VARCHAR(64) NOT NULL,
resource_type VARCHAR(32) NOT NULL,
file_id VARCHAR(64),
resource_url VARCHAR(512),
resource_title VARCHAR(256),
tenant_id VARCHAR(64) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT chk_cl_node_resource_type
CHECK (resource_type IN ('PDF', 'VIDEO', 'DOC', 'IMAGE', 'LINK', 'OTHER')),
CONSTRAINT chk_cl_node_resource_ref
CHECK (file_id IS NOT NULL OR resource_url IS NOT NULL),
CONSTRAINT fk_cl_node_resource_node
FOREIGN KEY (node_id) REFERENCES course.cl_course_node(node_id),
CONSTRAINT fk_cl_node_resource_file
FOREIGN KEY (file_id) REFERENCES upms.tb_sys_file(file_id)
);
COMMENT ON TABLE course.cl_node_resource IS '学习节点资源表';
COMMENT ON COLUMN course.cl_node_resource.resource_id IS '资源ID';
COMMENT ON COLUMN course.cl_node_resource.node_id IS '学习节点ID';
COMMENT ON COLUMN course.cl_node_resource.resource_type IS '资源类型PDF/VIDEO/DOC/IMAGE/LINK/OTHER';
COMMENT ON COLUMN course.cl_node_resource.file_id IS '资源文件ID';
COMMENT ON COLUMN course.cl_node_resource.resource_url IS '资源地址';
COMMENT ON COLUMN course.cl_node_resource.resource_title IS '资源标题';
COMMENT ON COLUMN course.cl_node_resource.tenant_id IS '租户ID';
COMMENT ON COLUMN course.cl_node_resource.created_at IS '创建时间';
DROP TABLE IF EXISTS course.cl_node_kp_rel CASCADE;
CREATE TABLE IF NOT EXISTS course.cl_node_kp_rel (
node_id VARCHAR(64) NOT NULL,
kp_id VARCHAR(64) NOT NULL,
relation_type VARCHAR(32) NOT NULL DEFAULT 'TEACHES',
weight NUMERIC(6,4) NOT NULL DEFAULT 1.0000,
tenant_id VARCHAR(64) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (node_id, kp_id),
CONSTRAINT chk_cl_node_kp_rel_type
CHECK (relation_type IN ('TEACHES', 'PRACTICES', 'REVIEWS')),
CONSTRAINT chk_cl_node_kp_rel_weight
CHECK (weight > 0 AND weight <= 1),
CONSTRAINT fk_cl_node_kp_rel_node
FOREIGN KEY (node_id) REFERENCES course.cl_course_node(node_id),
CONSTRAINT fk_cl_node_kp_rel_kp
FOREIGN KEY (kp_id) REFERENCES course.cl_knowledge_point(kp_id)
);
COMMENT ON TABLE course.cl_node_kp_rel IS '学习节点-知识点关联表';
COMMENT ON COLUMN course.cl_node_kp_rel.node_id IS '学习节点ID';
COMMENT ON COLUMN course.cl_node_kp_rel.kp_id IS '知识点ID';
COMMENT ON COLUMN course.cl_node_kp_rel.relation_type IS '关系类型TEACHES/PRACTICES/REVIEWS';
COMMENT ON COLUMN course.cl_node_kp_rel.weight IS '关联权重0,1]';
COMMENT ON COLUMN course.cl_node_kp_rel.tenant_id IS '租户ID';
COMMENT ON COLUMN course.cl_node_kp_rel.created_at IS '创建时间';
DROP TABLE IF EXISTS course.cl_node_homework_rel CASCADE;
CREATE TABLE IF NOT EXISTS course.cl_node_homework_rel (
node_id VARCHAR(64) NOT NULL,
assignment_id VARCHAR(64) NOT NULL,
relation_type VARCHAR(32) NOT NULL DEFAULT 'AFTER_CLASS',
tenant_id VARCHAR(64) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (node_id, assignment_id),
CONSTRAINT chk_cl_node_homework_rel_type
CHECK (relation_type IN ('IN_CLASS', 'AFTER_CLASS')),
CONSTRAINT fk_cl_node_homework_rel_node
FOREIGN KEY (node_id) REFERENCES course.cl_course_node(node_id)
);
COMMENT ON TABLE course.cl_node_homework_rel IS '学习节点-作业关联表';
COMMENT ON COLUMN course.cl_node_homework_rel.node_id IS '学习节点ID';
COMMENT ON COLUMN course.cl_node_homework_rel.assignment_id IS '作业IDquestion.hw_assignment.assignment_id';
COMMENT ON COLUMN course.cl_node_homework_rel.relation_type IS '关系类型IN_CLASS/AFTER_CLASS';
COMMENT ON COLUMN course.cl_node_homework_rel.tenant_id IS '租户ID';
COMMENT ON COLUMN course.cl_node_homework_rel.created_at IS '创建时间';
DROP TABLE IF EXISTS course.cl_learning_session CASCADE;
CREATE TABLE IF NOT EXISTS course.cl_learning_session (
session_id VARCHAR(64) PRIMARY KEY,
user_id VARCHAR(64) NOT NULL,
course_id VARCHAR(64) NOT NULL,
status VARCHAR(32) NOT NULL DEFAULT 'STARTED',
started_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
ended_at TIMESTAMP,
adcode VARCHAR(12) NOT NULL,
tenant_id VARCHAR(64) NOT NULL,
tenant_path VARCHAR(255) NOT NULL,
dept_id VARCHAR(64),
dept_path VARCHAR(255),
CONSTRAINT fk_cl_learning_session_user
FOREIGN KEY (user_id) REFERENCES upms.tb_sys_user(user_id),
CONSTRAINT fk_cl_learning_session_course
FOREIGN KEY (course_id) REFERENCES course.cl_course(course_id)
);
COMMENT ON TABLE course.cl_learning_session IS '学习会话表';
COMMENT ON COLUMN course.cl_learning_session.session_id IS '会话ID';
COMMENT ON COLUMN course.cl_learning_session.user_id IS '学员ID';
COMMENT ON COLUMN course.cl_learning_session.course_id IS '课程ID';
COMMENT ON COLUMN course.cl_learning_session.status IS '会话状态STARTED/PAUSED/COMPLETED';
COMMENT ON COLUMN course.cl_learning_session.started_at IS '开始时间';
COMMENT ON COLUMN course.cl_learning_session.ended_at IS '结束时间';
COMMENT ON COLUMN course.cl_learning_session.adcode IS '行政区划编码';
COMMENT ON COLUMN course.cl_learning_session.tenant_id IS '租户ID';
COMMENT ON COLUMN course.cl_learning_session.tenant_path IS '租户路径';
COMMENT ON COLUMN course.cl_learning_session.dept_id IS '部门ID';
COMMENT ON COLUMN course.cl_learning_session.dept_path IS '部门路径';
DROP TABLE IF EXISTS course.cl_learning_progress CASCADE;
CREATE TABLE IF NOT EXISTS course.cl_learning_progress (
progress_id VARCHAR(64) PRIMARY KEY,
session_id VARCHAR(64) NOT NULL,
node_id VARCHAR(64) NOT NULL,
progress_pct NUMERIC(5,2) NOT NULL DEFAULT 0,
last_position_sec INTEGER NOT NULL DEFAULT 0,
mastery_level VARCHAR(16),
tenant_id VARCHAR(64) NOT NULL,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT fk_cl_learning_progress_session
FOREIGN KEY (session_id) REFERENCES course.cl_learning_session(session_id),
CONSTRAINT fk_cl_learning_progress_node
FOREIGN KEY (node_id) REFERENCES course.cl_course_node(node_id)
);
COMMENT ON TABLE course.cl_learning_progress IS '学习进度表';
COMMENT ON COLUMN course.cl_learning_progress.progress_id IS '进度ID';
COMMENT ON COLUMN course.cl_learning_progress.session_id IS '学习会话ID';
COMMENT ON COLUMN course.cl_learning_progress.node_id IS '学习节点ID';
COMMENT ON COLUMN course.cl_learning_progress.progress_pct IS '进度百分比';
COMMENT ON COLUMN course.cl_learning_progress.last_position_sec IS '最后学习位置(秒)';
COMMENT ON COLUMN course.cl_learning_progress.mastery_level IS '掌握等级';
COMMENT ON COLUMN course.cl_learning_progress.tenant_id IS '租户ID';
COMMENT ON COLUMN course.cl_learning_progress.updated_at IS '更新时间';
DROP TABLE IF EXISTS course.cl_learning_event CASCADE;
CREATE TABLE IF NOT EXISTS course.cl_learning_event (
event_id VARCHAR(64) PRIMARY KEY,
session_id VARCHAR(64) NOT NULL,
event_type VARCHAR(32) NOT NULL,
event_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
payload_json JSONB,
tenant_id VARCHAR(64) NOT NULL,
CONSTRAINT fk_cl_learning_event_session
FOREIGN KEY (session_id) REFERENCES course.cl_learning_session(session_id)
);
COMMENT ON TABLE course.cl_learning_event IS '学习行为事件表';
COMMENT ON COLUMN course.cl_learning_event.event_id IS '事件ID';
COMMENT ON COLUMN course.cl_learning_event.session_id IS '会话ID';
COMMENT ON COLUMN course.cl_learning_event.event_type IS '事件类型start/pause/seek/finish';
COMMENT ON COLUMN course.cl_learning_event.event_time IS '事件时间';
COMMENT ON COLUMN course.cl_learning_event.payload_json IS '事件扩展信息';
COMMENT ON COLUMN course.cl_learning_event.tenant_id IS '租户ID';
CREATE INDEX IF NOT EXISTS idx_cl_course_tenant_subject_grade
ON course.cl_course(tenant_id, subject_code, grade_code);
CREATE INDEX IF NOT EXISTS idx_cl_course_chapter_course_no
ON course.cl_course_chapter(course_id, chapter_no);
CREATE INDEX IF NOT EXISTS idx_cl_course_node_chapter_no
ON course.cl_course_node(chapter_id, node_no);
CREATE INDEX IF NOT EXISTS idx_cl_knowledge_point_subject_grade
ON course.cl_knowledge_point(tenant_id, subject_code, grade_code);
CREATE INDEX IF NOT EXISTS idx_cl_knowledge_point_parent
ON course.cl_knowledge_point(tenant_id, parent_kp_id);
CREATE INDEX IF NOT EXISTS idx_cl_knowledge_point_graph_entity
ON course.cl_knowledge_point(tenant_id, graph_entity_id);
CREATE INDEX IF NOT EXISTS idx_cl_chapter_kp_rel_chapter
ON course.cl_chapter_kp_rel(tenant_id, chapter_id, relation_type);
CREATE INDEX IF NOT EXISTS idx_cl_chapter_kp_rel_kp
ON course.cl_chapter_kp_rel(tenant_id, kp_id, relation_type);
CREATE INDEX IF NOT EXISTS idx_cl_student_kp_mastery_student
ON course.cl_student_kp_mastery(tenant_id, student_id, mastery_score DESC);
CREATE INDEX IF NOT EXISTS idx_cl_student_kp_mastery_kp
ON course.cl_student_kp_mastery(tenant_id, kp_id, mastery_score DESC);
CREATE INDEX IF NOT EXISTS idx_cl_kp_material_rel_kp
ON course.cl_kp_material_rel(tenant_id, kp_id, material_type);
CREATE INDEX IF NOT EXISTS idx_cl_node_resource_node
ON course.cl_node_resource(node_id, resource_type);
CREATE INDEX IF NOT EXISTS idx_cl_node_kp_rel_node
ON course.cl_node_kp_rel(tenant_id, node_id, relation_type);
CREATE INDEX IF NOT EXISTS idx_cl_node_kp_rel_kp
ON course.cl_node_kp_rel(tenant_id, kp_id, relation_type);
CREATE INDEX IF NOT EXISTS idx_cl_node_homework_rel_node
ON course.cl_node_homework_rel(tenant_id, node_id, relation_type);
CREATE INDEX IF NOT EXISTS idx_cl_learning_session_user_course
ON course.cl_learning_session(tenant_id, user_id, course_id);
CREATE INDEX IF NOT EXISTS idx_cl_learning_progress_session_node
ON course.cl_learning_progress(session_id, node_id);
CREATE INDEX IF NOT EXISTS idx_cl_learning_event_session_time
ON course.cl_learning_event(session_id, event_time DESC);