Files
012-kaopeilian/backend/migrations/add_certificate_system.sql
yuliang_guo 64f5d567fa
Some checks failed
continuous-integration/drone/push Build is failing
feat: 实现 KPL 系统功能改进计划
1. 课程学习进度追踪
   - 新增 UserCourseProgress 和 UserMaterialProgress 模型
   - 新增 /api/v1/progress/* 进度追踪 API
   - 更新 admin.py 使用真实课程完成率数据

2. 路由权限检查完善
   - 新增前端 permissionChecker.ts 权限检查工具
   - 更新 router/guard.ts 实现团队和课程权限验证
   - 新增后端 permission_service.py

3. AI 陪练音频转文本
   - 新增 speech_recognition.py 语音识别服务
   - 新增 /api/v1/speech/* API
   - 更新 ai-practice-coze.vue 支持语音输入

4. 双人对练报告生成
   - 更新 practice_room_service.py 添加报告生成功能
   - 新增 /rooms/{room_code}/report API
   - 更新 duo-practice-report.vue 调用真实 API

5. 学习提醒推送
   - 新增 notification_service.py 通知服务
   - 新增 scheduler_service.py 定时任务服务
   - 支持钉钉、企微、站内消息推送

6. 智能学习推荐
   - 新增 recommendation_service.py 推荐服务
   - 新增 /api/v1/recommendations/* API
   - 支持错题、能力、进度、热门多维度推荐

7. 安全问题修复
   - DEBUG 默认值改为 False
   - 添加 SECRET_KEY 安全警告
   - 新增 check_security_settings() 检查函数

8. 证书 PDF 生成
   - 更新 certificate_service.py 添加 PDF 生成
   - 添加 weasyprint、Pillow、qrcode 依赖
   - 更新下载 API 支持 PDF 和 PNG 格式
2026-01-30 14:22:35 +08:00

167 lines
7.2 KiB
SQL
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.
-- ================================================================
-- 证书系统数据库迁移脚本
-- 创建日期: 2026-01-29
-- 功能: 添加证书模板表和用户证书表
-- ================================================================
-- 事务开始
START TRANSACTION;
-- ================================================================
-- 1. 创建证书模板表
-- ================================================================
CREATE TABLE IF NOT EXISTS certificate_templates (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL COMMENT '模板名称',
type ENUM('course', 'exam', 'achievement') NOT NULL COMMENT '证书类型: course=课程结业, exam=考试合格, achievement=成就证书',
background_url VARCHAR(500) COMMENT '证书背景图URL',
template_html TEXT COMMENT 'HTML模板内容',
template_style TEXT COMMENT 'CSS样式',
is_active BOOLEAN DEFAULT TRUE COMMENT '是否启用',
sort_order INT DEFAULT 0 COMMENT '排序顺序',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_type (type),
INDEX idx_is_active (is_active)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='证书模板表';
-- ================================================================
-- 2. 创建用户证书表
-- ================================================================
CREATE TABLE IF NOT EXISTS user_certificates (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT NOT NULL COMMENT '用户ID',
template_id INT NOT NULL COMMENT '模板ID',
certificate_no VARCHAR(50) UNIQUE NOT NULL COMMENT '证书编号 KPL-年份-序号',
title VARCHAR(200) NOT NULL COMMENT '证书标题',
description TEXT COMMENT '证书描述/成就说明',
issued_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '颁发时间',
valid_until DATETIME COMMENT '有效期至NULL表示永久',
-- 关联信息
course_id INT COMMENT '关联课程ID',
exam_id INT COMMENT '关联考试ID',
badge_id INT COMMENT '关联奖章ID',
-- 成绩信息
score DECIMAL(5,2) COMMENT '考试分数',
completion_rate DECIMAL(5,2) COMMENT '完成率',
-- 生成的文件
pdf_url VARCHAR(500) COMMENT 'PDF文件URL',
image_url VARCHAR(500) COMMENT '分享图片URL',
-- 元数据
meta_data JSON COMMENT '扩展元数据',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
FOREIGN KEY (template_id) REFERENCES certificate_templates(id),
INDEX idx_user_id (user_id),
INDEX idx_certificate_no (certificate_no),
INDEX idx_course_id (course_id),
INDEX idx_exam_id (exam_id),
INDEX idx_issued_at (issued_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户证书表';
-- ================================================================
-- 3. 插入默认证书模板
-- ================================================================
INSERT INTO certificate_templates (name, type, template_html, template_style, is_active, sort_order) VALUES
-- 课程结业证书模板
('课程结业证书', 'course',
'<div class="certificate">
<div class="header">
<div class="logo">考培练系统</div>
<h1>结业证书</h1>
</div>
<div class="body">
<p class="recipient">兹证明 <strong>{{user_name}}</strong></p>
<p class="content">已完成课程《{{course_name}}》的全部学习内容</p>
<p class="completion">完成率:{{completion_rate}}%</p>
<p class="date">颁发日期:{{issue_date}}</p>
</div>
<div class="footer">
<div class="cert-no">证书编号:{{certificate_no}}</div>
<div class="qrcode">{{qrcode}}</div>
</div>
</div>',
'.certificate { width: 800px; height: 600px; padding: 40px; background: linear-gradient(135deg, #f5f7fa 0%, #e4e9f2 100%); font-family: "Microsoft YaHei", sans-serif; }
.header { text-align: center; margin-bottom: 30px; }
.header .logo { font-size: 24px; color: #667eea; font-weight: bold; }
.header h1 { font-size: 36px; color: #333; margin: 20px 0; }
.body { text-align: center; padding: 30px 60px; }
.body .recipient { font-size: 20px; margin-bottom: 20px; }
.body .content { font-size: 18px; color: #555; margin-bottom: 15px; }
.body .completion { font-size: 16px; color: #667eea; }
.body .date { font-size: 14px; color: #888; margin-top: 30px; }
.footer { display: flex; justify-content: space-between; align-items: center; margin-top: 40px; }
.cert-no { font-size: 12px; color: #999; }
.qrcode { width: 80px; height: 80px; }',
TRUE, 1),
-- 考试合格证书模板
('考试合格证书', 'exam',
'<div class="certificate exam-cert">
<div class="header">
<div class="logo">考培练系统</div>
<h1>考试合格证书</h1>
</div>
<div class="body">
<p class="recipient">兹证明 <strong>{{user_name}}</strong></p>
<p class="content">在《{{exam_name}}》考试中成绩合格</p>
<div class="score-badge">
<span class="score">{{score}}</span>
<span class="unit">分</span>
</div>
<p class="date">考试日期:{{exam_date}}</p>
</div>
<div class="footer">
<div class="cert-no">证书编号:{{certificate_no}}</div>
<div class="qrcode">{{qrcode}}</div>
</div>
</div>',
'.certificate.exam-cert { width: 800px; height: 600px; padding: 40px; background: linear-gradient(135deg, #e8f5e9 0%, #c8e6c9 100%); font-family: "Microsoft YaHei", sans-serif; }
.exam-cert .header h1 { color: #2e7d32; }
.score-badge { display: inline-block; padding: 20px 40px; background: #fff; border-radius: 50%; box-shadow: 0 4px 20px rgba(0,0,0,0.1); margin: 20px 0; }
.score-badge .score { font-size: 48px; font-weight: bold; color: #2e7d32; }
.score-badge .unit { font-size: 18px; color: #666; }',
TRUE, 2),
-- 成就证书模板
('成就证书', 'achievement',
'<div class="certificate achievement-cert">
<div class="header">
<div class="logo">考培练系统</div>
<h1>成就证书</h1>
</div>
<div class="body">
<p class="recipient">兹证明 <strong>{{user_name}}</strong></p>
<div class="achievement-icon">{{badge_icon}}</div>
<p class="achievement-name">{{badge_name}}</p>
<p class="achievement-desc">{{badge_description}}</p>
<p class="date">获得日期:{{achieve_date}}</p>
</div>
<div class="footer">
<div class="cert-no">证书编号:{{certificate_no}}</div>
<div class="qrcode">{{qrcode}}</div>
</div>
</div>',
'.certificate.achievement-cert { width: 800px; height: 600px; padding: 40px; background: linear-gradient(135deg, #fff3e0 0%, #ffe0b2 100%); font-family: "Microsoft YaHei", sans-serif; }
.achievement-cert .header h1 { color: #e65100; }
.achievement-icon { font-size: 64px; margin: 20px 0; }
.achievement-name { font-size: 24px; font-weight: bold; color: #e65100; margin: 10px 0; }
.achievement-desc { font-size: 16px; color: #666; }',
TRUE, 3);
-- 提交事务
COMMIT;
-- ================================================================
-- 验证脚本
-- ================================================================
-- SELECT * FROM certificate_templates;
-- SELECT COUNT(*) AS template_count FROM certificate_templates;