DROP SCHEMA IF EXISTS recommendation CASCADE; CREATE SCHEMA IF NOT EXISTS recommendation; DROP TABLE IF EXISTS recommendation.rc_recommendation_task CASCADE; CREATE TABLE IF NOT EXISTS recommendation.rc_recommendation_task ( task_id VARCHAR(64) PRIMARY KEY, user_id VARCHAR(64) NOT NULL, scene_code VARCHAR(32) NOT NULL, trigger_source VARCHAR(32) NOT NULL DEFAULT 'SCHEDULE', strategy_version VARCHAR(32), profile_snapshot_json JSONB NOT NULL DEFAULT '{}'::JSONB, status VARCHAR(16) NOT NULL DEFAULT 'CREATED', tenant_id VARCHAR(64) NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT chk_rc_recommendation_task_status CHECK (status IN ('CREATED', 'RUNNING', 'DONE', 'FAILED')), CONSTRAINT chk_rc_recommendation_task_profile_json CHECK (jsonb_typeof(profile_snapshot_json) = 'object'), CONSTRAINT fk_rc_recommendation_task_user FOREIGN KEY (user_id) REFERENCES upms.tb_sys_user(user_id) ); COMMENT ON TABLE recommendation.rc_recommendation_task IS '推荐任务表'; COMMENT ON COLUMN recommendation.rc_recommendation_task.task_id IS '推荐任务ID'; COMMENT ON COLUMN recommendation.rc_recommendation_task.user_id IS '推荐目标用户ID'; COMMENT ON COLUMN recommendation.rc_recommendation_task.scene_code IS '推荐场景编码(HOME/WRONGBOOK/REVIEW等)'; COMMENT ON COLUMN recommendation.rc_recommendation_task.trigger_source IS '触发来源(SCHEDULE/EVENT/MANUAL)'; COMMENT ON COLUMN recommendation.rc_recommendation_task.strategy_version IS '推荐策略版本'; COMMENT ON COLUMN recommendation.rc_recommendation_task.profile_snapshot_json IS '画像快照JSON'; COMMENT ON COLUMN recommendation.rc_recommendation_task.status IS '任务状态'; COMMENT ON COLUMN recommendation.rc_recommendation_task.tenant_id IS '租户ID'; COMMENT ON COLUMN recommendation.rc_recommendation_task.created_at IS '创建时间'; COMMENT ON COLUMN recommendation.rc_recommendation_task.updated_at IS '更新时间'; DROP TABLE IF EXISTS recommendation.rc_recommendation_item CASCADE; CREATE TABLE IF NOT EXISTS recommendation.rc_recommendation_item ( item_id VARCHAR(64) PRIMARY KEY, task_id VARCHAR(64) NOT NULL, content_type VARCHAR(32) NOT NULL, content_object_id VARCHAR(64) NOT NULL, content_object_type VARCHAR(64) NOT NULL, rank_no INTEGER NOT NULL, score NUMERIC(10,6), reason_codes VARCHAR(255), metadata_json JSONB NOT NULL DEFAULT '{}'::JSONB, tenant_id VARCHAR(64) NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT chk_rc_recommendation_item_content_type CHECK (content_type IN ('COURSE', 'QUESTION', 'PAPER', 'WRONG_QUESTION', 'REVIEW_PLAN', 'MIXED')), CONSTRAINT chk_rc_recommendation_item_metadata_json CHECK (jsonb_typeof(metadata_json) = 'object'), CONSTRAINT uq_rc_recommendation_item_task_rank UNIQUE (task_id, rank_no), CONSTRAINT fk_rc_recommendation_item_task FOREIGN KEY (task_id) REFERENCES recommendation.rc_recommendation_task(task_id) ON DELETE CASCADE ); COMMENT ON TABLE recommendation.rc_recommendation_item IS '推荐结果明细表'; COMMENT ON COLUMN recommendation.rc_recommendation_item.item_id IS '推荐项ID'; COMMENT ON COLUMN recommendation.rc_recommendation_item.task_id IS '推荐任务ID'; COMMENT ON COLUMN recommendation.rc_recommendation_item.content_type IS '内容类型'; COMMENT ON COLUMN recommendation.rc_recommendation_item.content_object_id IS '内容对象ID'; COMMENT ON COLUMN recommendation.rc_recommendation_item.content_object_type IS '内容对象类型'; COMMENT ON COLUMN recommendation.rc_recommendation_item.rank_no IS '推荐位次'; COMMENT ON COLUMN recommendation.rc_recommendation_item.score IS '推荐分'; COMMENT ON COLUMN recommendation.rc_recommendation_item.reason_codes IS '推荐原因编码集合'; COMMENT ON COLUMN recommendation.rc_recommendation_item.metadata_json IS '扩展元数据JSON'; COMMENT ON COLUMN recommendation.rc_recommendation_item.tenant_id IS '租户ID'; COMMENT ON COLUMN recommendation.rc_recommendation_item.created_at IS '创建时间'; DROP TABLE IF EXISTS recommendation.rc_recommendation_feedback CASCADE; CREATE TABLE IF NOT EXISTS recommendation.rc_recommendation_feedback ( feedback_id VARCHAR(64) PRIMARY KEY, item_id VARCHAR(64) NOT NULL, user_id VARCHAR(64) NOT NULL, event_type VARCHAR(16) NOT NULL, event_value NUMERIC(10,4), event_detail_json JSONB NOT NULL DEFAULT '{}'::JSONB, event_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, tenant_id VARCHAR(64) NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT chk_rc_recommendation_feedback_event_type CHECK (event_type IN ('EXPOSE', 'CLICK', 'START', 'COMPLETE', 'DISLIKE', 'SKIP')), CONSTRAINT chk_rc_recommendation_feedback_detail_json CHECK (jsonb_typeof(event_detail_json) = 'object'), CONSTRAINT fk_rc_recommendation_feedback_item FOREIGN KEY (item_id) REFERENCES recommendation.rc_recommendation_item(item_id) ON DELETE CASCADE, CONSTRAINT fk_rc_recommendation_feedback_user FOREIGN KEY (user_id) REFERENCES upms.tb_sys_user(user_id) ); COMMENT ON TABLE recommendation.rc_recommendation_feedback IS '推荐反馈事件表'; COMMENT ON COLUMN recommendation.rc_recommendation_feedback.feedback_id IS '反馈事件ID'; COMMENT ON COLUMN recommendation.rc_recommendation_feedback.item_id IS '推荐项ID'; COMMENT ON COLUMN recommendation.rc_recommendation_feedback.user_id IS '用户ID'; COMMENT ON COLUMN recommendation.rc_recommendation_feedback.event_type IS '事件类型'; COMMENT ON COLUMN recommendation.rc_recommendation_feedback.event_value IS '事件值(可选)'; COMMENT ON COLUMN recommendation.rc_recommendation_feedback.event_detail_json IS '事件详情JSON'; COMMENT ON COLUMN recommendation.rc_recommendation_feedback.event_time IS '事件发生时间'; COMMENT ON COLUMN recommendation.rc_recommendation_feedback.tenant_id IS '租户ID'; COMMENT ON COLUMN recommendation.rc_recommendation_feedback.created_at IS '创建时间'; DROP TABLE IF EXISTS recommendation.rc_recommendation_effect_daily CASCADE; CREATE TABLE IF NOT EXISTS recommendation.rc_recommendation_effect_daily ( stat_date DATE NOT NULL, scene_code VARCHAR(32) NOT NULL, strategy_version VARCHAR(32) NOT NULL, tenant_id VARCHAR(64) NOT NULL, expose_count BIGINT NOT NULL DEFAULT 0, click_count BIGINT NOT NULL DEFAULT 0, complete_count BIGINT NOT NULL DEFAULT 0, dislike_count BIGINT NOT NULL DEFAULT 0, ctr NUMERIC(10,6) NOT NULL DEFAULT 0, complete_rate NUMERIC(10,6) NOT NULL DEFAULT 0, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (stat_date, scene_code, strategy_version, tenant_id) ); COMMENT ON TABLE recommendation.rc_recommendation_effect_daily IS '推荐效果日统计表'; COMMENT ON COLUMN recommendation.rc_recommendation_effect_daily.stat_date IS '统计日期'; COMMENT ON COLUMN recommendation.rc_recommendation_effect_daily.scene_code IS '推荐场景编码'; COMMENT ON COLUMN recommendation.rc_recommendation_effect_daily.strategy_version IS '策略版本'; COMMENT ON COLUMN recommendation.rc_recommendation_effect_daily.tenant_id IS '租户ID'; COMMENT ON COLUMN recommendation.rc_recommendation_effect_daily.expose_count IS '曝光次数'; COMMENT ON COLUMN recommendation.rc_recommendation_effect_daily.click_count IS '点击次数'; COMMENT ON COLUMN recommendation.rc_recommendation_effect_daily.complete_count IS '完成次数'; COMMENT ON COLUMN recommendation.rc_recommendation_effect_daily.dislike_count IS '不喜欢次数'; COMMENT ON COLUMN recommendation.rc_recommendation_effect_daily.ctr IS '点击率'; COMMENT ON COLUMN recommendation.rc_recommendation_effect_daily.complete_rate IS '完成率'; COMMENT ON COLUMN recommendation.rc_recommendation_effect_daily.created_at IS '创建时间'; COMMENT ON COLUMN recommendation.rc_recommendation_effect_daily.updated_at IS '更新时间'; CREATE INDEX IF NOT EXISTS idx_rc_recommendation_task_user_scene ON recommendation.rc_recommendation_task(user_id, scene_code, created_at DESC); CREATE INDEX IF NOT EXISTS idx_rc_recommendation_task_tenant_status ON recommendation.rc_recommendation_task(tenant_id, status, created_at DESC); CREATE INDEX IF NOT EXISTS idx_rc_recommendation_item_task ON recommendation.rc_recommendation_item(task_id, rank_no); CREATE INDEX IF NOT EXISTS idx_rc_recommendation_item_content ON recommendation.rc_recommendation_item(content_object_type, content_object_id); CREATE INDEX IF NOT EXISTS idx_rc_recommendation_feedback_item_event ON recommendation.rc_recommendation_feedback(item_id, event_type, event_time DESC); CREATE INDEX IF NOT EXISTS idx_rc_recommendation_feedback_user_event ON recommendation.rc_recommendation_feedback(user_id, event_type, event_time DESC); CREATE INDEX IF NOT EXISTS idx_rc_recommendation_effect_daily_tenant_date ON recommendation.rc_recommendation_effect_daily(tenant_id, stat_date DESC); DROP TABLE IF EXISTS recommendation.rc_student_profile_feature CASCADE; DROP TABLE IF EXISTS recommendation.rc_student_profile_snapshot CASCADE; CREATE TABLE IF NOT EXISTS recommendation.rc_student_profile_snapshot ( profile_id VARCHAR(64) PRIMARY KEY, user_id VARCHAR(64) NOT NULL, profile_version VARCHAR(32) NOT NULL, profile_date DATE NOT NULL, feature_source_version VARCHAR(64), profile_json JSONB NOT NULL DEFAULT '{}'::JSONB, confidence_score NUMERIC(6,4), profile_status VARCHAR(16) NOT NULL DEFAULT 'ACTIVE', tenant_id VARCHAR(64) NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT uq_rc_student_profile_snapshot_user_version UNIQUE (user_id, profile_version), CONSTRAINT chk_rc_student_profile_snapshot_json CHECK (jsonb_typeof(profile_json) = 'object'), CONSTRAINT chk_rc_student_profile_snapshot_status CHECK (profile_status IN ('ACTIVE', 'ARCHIVED')), CONSTRAINT fk_rc_student_profile_snapshot_user FOREIGN KEY (user_id) REFERENCES upms.tb_sys_user(user_id) ); COMMENT ON TABLE recommendation.rc_student_profile_snapshot IS '学员画像快照表'; COMMENT ON COLUMN recommendation.rc_student_profile_snapshot.profile_id IS '画像ID'; COMMENT ON COLUMN recommendation.rc_student_profile_snapshot.user_id IS '学员ID'; COMMENT ON COLUMN recommendation.rc_student_profile_snapshot.profile_version IS '画像版本'; COMMENT ON COLUMN recommendation.rc_student_profile_snapshot.profile_date IS '画像日期'; COMMENT ON COLUMN recommendation.rc_student_profile_snapshot.feature_source_version IS '特征来源版本'; COMMENT ON COLUMN recommendation.rc_student_profile_snapshot.profile_json IS '画像JSON'; COMMENT ON COLUMN recommendation.rc_student_profile_snapshot.confidence_score IS '画像置信度'; COMMENT ON COLUMN recommendation.rc_student_profile_snapshot.profile_status IS '画像状态'; COMMENT ON COLUMN recommendation.rc_student_profile_snapshot.tenant_id IS '租户ID'; COMMENT ON COLUMN recommendation.rc_student_profile_snapshot.created_at IS '创建时间'; COMMENT ON COLUMN recommendation.rc_student_profile_snapshot.updated_at IS '更新时间'; CREATE TABLE IF NOT EXISTS recommendation.rc_student_profile_feature ( feature_id VARCHAR(64) PRIMARY KEY, profile_id VARCHAR(64) NOT NULL, feature_group VARCHAR(32) NOT NULL, feature_key VARCHAR(64) NOT NULL, feature_value_num NUMERIC(18,6), feature_value_text VARCHAR(512), feature_value_json JSONB, value_type VARCHAR(16) NOT NULL DEFAULT 'NUM', source_domain VARCHAR(32) NOT NULL, source_ref_id VARCHAR(64), sample_time TIMESTAMP, tenant_id VARCHAR(64) NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT chk_rc_student_profile_feature_value_type CHECK (value_type IN ('NUM', 'TEXT', 'JSON', 'BOOL')), CONSTRAINT chk_rc_student_profile_feature_source_domain CHECK (source_domain IN ('COURSE', 'HOMEWORK', 'GRADING', 'REVIEW', 'RECOMMENDATION', 'ACHIEVEMENT', 'SYSTEM')), CONSTRAINT chk_rc_student_profile_feature_json CHECK (feature_value_json IS NULL OR jsonb_typeof(feature_value_json) IN ('object', 'array', 'string', 'number', 'boolean')), CONSTRAINT fk_rc_student_profile_feature_profile FOREIGN KEY (profile_id) REFERENCES recommendation.rc_student_profile_snapshot(profile_id) ON DELETE CASCADE ); COMMENT ON TABLE recommendation.rc_student_profile_feature IS '学员画像特征明细表'; COMMENT ON COLUMN recommendation.rc_student_profile_feature.feature_id IS '特征ID'; COMMENT ON COLUMN recommendation.rc_student_profile_feature.profile_id IS '画像ID'; COMMENT ON COLUMN recommendation.rc_student_profile_feature.feature_group IS '特征组'; COMMENT ON COLUMN recommendation.rc_student_profile_feature.feature_key IS '特征键'; COMMENT ON COLUMN recommendation.rc_student_profile_feature.feature_value_num IS '数值特征值'; COMMENT ON COLUMN recommendation.rc_student_profile_feature.feature_value_text IS '文本特征值'; COMMENT ON COLUMN recommendation.rc_student_profile_feature.feature_value_json IS 'JSON特征值'; COMMENT ON COLUMN recommendation.rc_student_profile_feature.value_type IS '值类型'; COMMENT ON COLUMN recommendation.rc_student_profile_feature.source_domain IS '来源域'; COMMENT ON COLUMN recommendation.rc_student_profile_feature.source_ref_id IS '来源对象ID'; COMMENT ON COLUMN recommendation.rc_student_profile_feature.sample_time IS '采样时间'; COMMENT ON COLUMN recommendation.rc_student_profile_feature.tenant_id IS '租户ID'; COMMENT ON COLUMN recommendation.rc_student_profile_feature.created_at IS '创建时间'; DROP TABLE IF EXISTS recommendation.rc_learning_loop_event CASCADE; DROP TABLE IF EXISTS recommendation.rc_learning_loop_case CASCADE; CREATE TABLE IF NOT EXISTS recommendation.rc_learning_loop_case ( loop_case_id VARCHAR(64) PRIMARY KEY, user_id VARCHAR(64) NOT NULL, wrong_question_id VARCHAR(64) NOT NULL, review_plan_id VARCHAR(64), profile_id VARCHAR(64), recommendation_task_id VARCHAR(64), recommendation_item_id VARCHAR(64), feedback_id VARCHAR(64), user_achievement_id VARCHAR(64), loop_status VARCHAR(16) NOT NULL DEFAULT 'OPEN', effect_score NUMERIC(10,4), opened_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, closed_at TIMESTAMP, tenant_id VARCHAR(64) NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT chk_rc_learning_loop_case_status CHECK (loop_status IN ('OPEN', 'IN_PROGRESS', 'CLOSED', 'FAILED')), CONSTRAINT chk_rc_learning_loop_case_closed_at CHECK (closed_at IS NULL OR closed_at >= opened_at), CONSTRAINT fk_rc_learning_loop_case_user FOREIGN KEY (user_id) REFERENCES upms.tb_sys_user(user_id), CONSTRAINT fk_rc_learning_loop_case_wrong_question FOREIGN KEY (wrong_question_id) REFERENCES question.gd_wrong_question(wrong_question_id), CONSTRAINT fk_rc_learning_loop_case_review_plan FOREIGN KEY (review_plan_id) REFERENCES question.gd_review_plan(review_plan_id), CONSTRAINT fk_rc_learning_loop_case_profile FOREIGN KEY (profile_id) REFERENCES recommendation.rc_student_profile_snapshot(profile_id), CONSTRAINT fk_rc_learning_loop_case_recommendation_task FOREIGN KEY (recommendation_task_id) REFERENCES recommendation.rc_recommendation_task(task_id), CONSTRAINT fk_rc_learning_loop_case_recommendation_item FOREIGN KEY (recommendation_item_id) REFERENCES recommendation.rc_recommendation_item(item_id), CONSTRAINT fk_rc_learning_loop_case_feedback FOREIGN KEY (feedback_id) REFERENCES recommendation.rc_recommendation_feedback(feedback_id), CONSTRAINT fk_rc_learning_loop_case_user_achievement FOREIGN KEY (user_achievement_id) REFERENCES achievement.ac_user_achievement(user_achievement_id) ); COMMENT ON TABLE recommendation.rc_learning_loop_case IS '学习闭环主表(错题-复习-推荐-成就)'; COMMENT ON COLUMN recommendation.rc_learning_loop_case.loop_case_id IS '闭环案例ID'; COMMENT ON COLUMN recommendation.rc_learning_loop_case.user_id IS '用户ID'; COMMENT ON COLUMN recommendation.rc_learning_loop_case.wrong_question_id IS '错题ID'; COMMENT ON COLUMN recommendation.rc_learning_loop_case.review_plan_id IS '复习计划ID'; COMMENT ON COLUMN recommendation.rc_learning_loop_case.profile_id IS '画像ID'; COMMENT ON COLUMN recommendation.rc_learning_loop_case.recommendation_task_id IS '推荐任务ID'; COMMENT ON COLUMN recommendation.rc_learning_loop_case.recommendation_item_id IS '推荐项ID'; COMMENT ON COLUMN recommendation.rc_learning_loop_case.feedback_id IS '反馈事件ID'; COMMENT ON COLUMN recommendation.rc_learning_loop_case.user_achievement_id IS '成就记录ID'; COMMENT ON COLUMN recommendation.rc_learning_loop_case.loop_status IS '闭环状态'; COMMENT ON COLUMN recommendation.rc_learning_loop_case.effect_score IS '闭环效果分'; COMMENT ON COLUMN recommendation.rc_learning_loop_case.opened_at IS '闭环开启时间'; COMMENT ON COLUMN recommendation.rc_learning_loop_case.closed_at IS '闭环关闭时间'; COMMENT ON COLUMN recommendation.rc_learning_loop_case.tenant_id IS '租户ID'; COMMENT ON COLUMN recommendation.rc_learning_loop_case.created_at IS '创建时间'; COMMENT ON COLUMN recommendation.rc_learning_loop_case.updated_at IS '更新时间'; CREATE TABLE IF NOT EXISTS recommendation.rc_learning_loop_event ( loop_event_id VARCHAR(64) PRIMARY KEY, loop_case_id VARCHAR(64) NOT NULL, stage_code VARCHAR(32) NOT NULL, stage_status VARCHAR(16) NOT NULL DEFAULT 'DONE', event_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, event_score NUMERIC(10,4), event_detail_json JSONB NOT NULL DEFAULT '{}'::JSONB, tenant_id VARCHAR(64) NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT chk_rc_learning_loop_event_stage_code CHECK (stage_code IN ('WRONG_CAPTURED', 'REVIEW_PLANNED', 'PROFILE_UPDATED', 'RECOMMENDED', 'EXPOSED', 'ENGAGED', 'REVIEW_COMPLETED', 'ACHIEVED')), CONSTRAINT chk_rc_learning_loop_event_stage_status CHECK (stage_status IN ('PENDING', 'DONE', 'FAILED', 'SKIPPED')), CONSTRAINT chk_rc_learning_loop_event_detail_json CHECK (jsonb_typeof(event_detail_json) = 'object'), CONSTRAINT fk_rc_learning_loop_event_case FOREIGN KEY (loop_case_id) REFERENCES recommendation.rc_learning_loop_case(loop_case_id) ON DELETE CASCADE ); COMMENT ON TABLE recommendation.rc_learning_loop_event IS '学习闭环阶段事件表'; COMMENT ON COLUMN recommendation.rc_learning_loop_event.loop_event_id IS '闭环事件ID'; COMMENT ON COLUMN recommendation.rc_learning_loop_event.loop_case_id IS '闭环案例ID'; COMMENT ON COLUMN recommendation.rc_learning_loop_event.stage_code IS '阶段编码'; COMMENT ON COLUMN recommendation.rc_learning_loop_event.stage_status IS '阶段状态'; COMMENT ON COLUMN recommendation.rc_learning_loop_event.event_time IS '事件时间'; COMMENT ON COLUMN recommendation.rc_learning_loop_event.event_score IS '阶段得分'; COMMENT ON COLUMN recommendation.rc_learning_loop_event.event_detail_json IS '事件详情JSON'; COMMENT ON COLUMN recommendation.rc_learning_loop_event.tenant_id IS '租户ID'; COMMENT ON COLUMN recommendation.rc_learning_loop_event.created_at IS '创建时间'; DROP TABLE IF EXISTS recommendation.rc_learning_loop_effect_daily CASCADE; CREATE TABLE IF NOT EXISTS recommendation.rc_learning_loop_effect_daily ( stat_date DATE NOT NULL, tenant_id VARCHAR(64) NOT NULL, opened_case_count BIGINT NOT NULL DEFAULT 0, closed_case_count BIGINT NOT NULL DEFAULT 0, achieved_case_count BIGINT NOT NULL DEFAULT 0, avg_effect_score NUMERIC(10,4) NOT NULL DEFAULT 0, avg_close_hours NUMERIC(10,4) NOT NULL DEFAULT 0, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (stat_date, tenant_id) ); COMMENT ON TABLE recommendation.rc_learning_loop_effect_daily IS '学习闭环效果日统计表'; COMMENT ON COLUMN recommendation.rc_learning_loop_effect_daily.stat_date IS '统计日期'; COMMENT ON COLUMN recommendation.rc_learning_loop_effect_daily.tenant_id IS '租户ID'; COMMENT ON COLUMN recommendation.rc_learning_loop_effect_daily.opened_case_count IS '开启案例数'; COMMENT ON COLUMN recommendation.rc_learning_loop_effect_daily.closed_case_count IS '关闭案例数'; COMMENT ON COLUMN recommendation.rc_learning_loop_effect_daily.achieved_case_count IS '达成成就案例数'; COMMENT ON COLUMN recommendation.rc_learning_loop_effect_daily.avg_effect_score IS '平均效果分'; COMMENT ON COLUMN recommendation.rc_learning_loop_effect_daily.avg_close_hours IS '平均闭环时长(小时)'; COMMENT ON COLUMN recommendation.rc_learning_loop_effect_daily.created_at IS '创建时间'; COMMENT ON COLUMN recommendation.rc_learning_loop_effect_daily.updated_at IS '更新时间'; CREATE INDEX IF NOT EXISTS idx_rc_student_profile_snapshot_user_date ON recommendation.rc_student_profile_snapshot(user_id, profile_date DESC); CREATE INDEX IF NOT EXISTS idx_rc_student_profile_snapshot_tenant_version ON recommendation.rc_student_profile_snapshot(tenant_id, profile_version, created_at DESC); CREATE INDEX IF NOT EXISTS idx_rc_student_profile_feature_profile_group ON recommendation.rc_student_profile_feature(profile_id, feature_group, feature_key); CREATE INDEX IF NOT EXISTS idx_rc_student_profile_feature_source ON recommendation.rc_student_profile_feature(source_domain, source_ref_id); CREATE INDEX IF NOT EXISTS idx_rc_learning_loop_case_user_status ON recommendation.rc_learning_loop_case(user_id, loop_status, opened_at DESC); CREATE INDEX IF NOT EXISTS idx_rc_learning_loop_case_wrong_question ON recommendation.rc_learning_loop_case(wrong_question_id, opened_at DESC); CREATE INDEX IF NOT EXISTS idx_rc_learning_loop_case_tenant_status ON recommendation.rc_learning_loop_case(tenant_id, loop_status, opened_at DESC); CREATE INDEX IF NOT EXISTS idx_rc_learning_loop_event_case_stage_time ON recommendation.rc_learning_loop_event(loop_case_id, stage_code, event_time DESC); CREATE INDEX IF NOT EXISTS idx_rc_learning_loop_event_tenant_time ON recommendation.rc_learning_loop_event(tenant_id, event_time DESC); CREATE INDEX IF NOT EXISTS idx_rc_learning_loop_effect_daily_tenant_date ON recommendation.rc_learning_loop_effect_daily(tenant_id, stat_date DESC); DROP TABLE IF EXISTS recommendation.rc_loop_metric_map CASCADE; DROP TABLE IF EXISTS recommendation.rc_loop_stage_achievement_map CASCADE; CREATE TABLE IF NOT EXISTS recommendation.rc_loop_stage_achievement_map ( stage_map_id VARCHAR(64) PRIMARY KEY, stage_code VARCHAR(32) NOT NULL, event_code VARCHAR(64) NOT NULL, template_id VARCHAR(64), metric_id VARCHAR(64), award_source VARCHAR(32) NOT NULL DEFAULT 'RULE_ENGINE', priority INTEGER NOT NULL DEFAULT 100, enabled BOOLEAN NOT NULL DEFAULT TRUE, ext_json JSONB NOT NULL DEFAULT '{}'::JSONB, tenant_id VARCHAR(64) NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT uq_rc_loop_stage_achievement_map UNIQUE (tenant_id, stage_code, event_code, priority), CONSTRAINT chk_rc_loop_stage_achievement_map_stage_code CHECK (stage_code IN ('WRONG_CAPTURED', 'REVIEW_PLANNED', 'PROFILE_UPDATED', 'RECOMMENDED', 'EXPOSED', 'ENGAGED', 'REVIEW_COMPLETED', 'ACHIEVED')), CONSTRAINT chk_rc_loop_stage_achievement_map_award_source CHECK (award_source IN ('RULE_ENGINE', 'MANUAL', 'SYSTEM')), CONSTRAINT chk_rc_loop_stage_achievement_map_ext_json CHECK (jsonb_typeof(ext_json) = 'object'), CONSTRAINT fk_rc_loop_stage_achievement_map_event FOREIGN KEY (event_code) REFERENCES achievement.ac_achievement_event_dict(event_code), CONSTRAINT fk_rc_loop_stage_achievement_map_template FOREIGN KEY (template_id) REFERENCES achievement.ac_achievement_rule_template(template_id), CONSTRAINT fk_rc_loop_stage_achievement_map_metric FOREIGN KEY (metric_id) REFERENCES achievement.ac_achievement_metric_def(metric_id) ); COMMENT ON TABLE recommendation.rc_loop_stage_achievement_map IS '闭环阶段到成就事件映射表(通用配置)'; COMMENT ON COLUMN recommendation.rc_loop_stage_achievement_map.stage_map_id IS '阶段映射ID'; COMMENT ON COLUMN recommendation.rc_loop_stage_achievement_map.stage_code IS '闭环阶段编码'; COMMENT ON COLUMN recommendation.rc_loop_stage_achievement_map.event_code IS '成就事件编码'; COMMENT ON COLUMN recommendation.rc_loop_stage_achievement_map.template_id IS '成就规则模板ID'; COMMENT ON COLUMN recommendation.rc_loop_stage_achievement_map.metric_id IS '成就指标ID'; COMMENT ON COLUMN recommendation.rc_loop_stage_achievement_map.award_source IS '发放来源'; COMMENT ON COLUMN recommendation.rc_loop_stage_achievement_map.priority IS '优先级'; COMMENT ON COLUMN recommendation.rc_loop_stage_achievement_map.enabled IS '是否启用'; COMMENT ON COLUMN recommendation.rc_loop_stage_achievement_map.ext_json IS '扩展配置JSON'; COMMENT ON COLUMN recommendation.rc_loop_stage_achievement_map.tenant_id IS '租户ID'; COMMENT ON COLUMN recommendation.rc_loop_stage_achievement_map.created_at IS '创建时间'; COMMENT ON COLUMN recommendation.rc_loop_stage_achievement_map.updated_at IS '更新时间'; CREATE TABLE IF NOT EXISTS recommendation.rc_loop_metric_map ( metric_map_id VARCHAR(64) PRIMARY KEY, stage_code VARCHAR(32) NOT NULL, metric_id VARCHAR(64) NOT NULL, source_field VARCHAR(64) NOT NULL, agg_method VARCHAR(16) NOT NULL DEFAULT 'LATEST', weight NUMERIC(6,4) NOT NULL DEFAULT 1.0000, enabled BOOLEAN NOT NULL DEFAULT TRUE, ext_json JSONB NOT NULL DEFAULT '{}'::JSONB, tenant_id VARCHAR(64) NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT uq_rc_loop_metric_map UNIQUE (tenant_id, stage_code, metric_id, source_field), CONSTRAINT chk_rc_loop_metric_map_stage_code CHECK (stage_code IN ('WRONG_CAPTURED', 'REVIEW_PLANNED', 'PROFILE_UPDATED', 'RECOMMENDED', 'EXPOSED', 'ENGAGED', 'REVIEW_COMPLETED', 'ACHIEVED')), CONSTRAINT chk_rc_loop_metric_map_agg_method CHECK (agg_method IN ('LATEST', 'SUM', 'AVG', 'MAX', 'MIN', 'COUNT')), CONSTRAINT chk_rc_loop_metric_map_weight CHECK (weight > 0 AND weight <= 1), CONSTRAINT chk_rc_loop_metric_map_ext_json CHECK (jsonb_typeof(ext_json) = 'object'), CONSTRAINT fk_rc_loop_metric_map_metric FOREIGN KEY (metric_id) REFERENCES achievement.ac_achievement_metric_def(metric_id) ); COMMENT ON TABLE recommendation.rc_loop_metric_map IS '闭环指标映射表(通用配置)'; COMMENT ON COLUMN recommendation.rc_loop_metric_map.metric_map_id IS '指标映射ID'; COMMENT ON COLUMN recommendation.rc_loop_metric_map.stage_code IS '闭环阶段编码'; COMMENT ON COLUMN recommendation.rc_loop_metric_map.metric_id IS '成就指标ID'; COMMENT ON COLUMN recommendation.rc_loop_metric_map.source_field IS '来源字段名'; COMMENT ON COLUMN recommendation.rc_loop_metric_map.agg_method IS '聚合方法'; COMMENT ON COLUMN recommendation.rc_loop_metric_map.weight IS '权重'; COMMENT ON COLUMN recommendation.rc_loop_metric_map.enabled IS '是否启用'; COMMENT ON COLUMN recommendation.rc_loop_metric_map.ext_json IS '扩展配置JSON'; COMMENT ON COLUMN recommendation.rc_loop_metric_map.tenant_id IS '租户ID'; COMMENT ON COLUMN recommendation.rc_loop_metric_map.created_at IS '创建时间'; COMMENT ON COLUMN recommendation.rc_loop_metric_map.updated_at IS '更新时间'; CREATE INDEX IF NOT EXISTS idx_rc_loop_stage_achievement_map_tenant_stage ON recommendation.rc_loop_stage_achievement_map(tenant_id, stage_code, enabled, priority); CREATE INDEX IF NOT EXISTS idx_rc_loop_stage_achievement_map_event ON recommendation.rc_loop_stage_achievement_map(event_code, tenant_id, enabled); CREATE INDEX IF NOT EXISTS idx_rc_loop_metric_map_tenant_stage ON recommendation.rc_loop_metric_map(tenant_id, stage_code, enabled);