Files
012-kaopeilian/CHANGELOG-2026-01-29.md
yuliang_guo 3ddb1bda2d
Some checks failed
continuous-integration/drone/push Build is failing
docs: 更新 CHANGELOG 添加下午的修复内容
2026-01-29 17:38:43 +08:00

262 lines
9.0 KiB
Markdown
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.
# KPL 考培练系统 功能迭代更新日志
**日期**: 2026-01-29
**版本**: v1.5.0
---
## 一、奖章条件优化
### 修复内容
- 修复 `badge_service.py` 中统计查询的 SQL 语法问题
- 将非标准 `func.if_` 替换为 SQLAlchemy 标准 `case` 语句
- 优化考试统计逻辑:通过数、满分数、优秀数分开查询
- 添加 `func.coalesce` 处理空值
### 新增功能
- `check_badges_by_category()` - 按类别检查奖章
- `check_exam_badges()` - 考试后触发
- `check_practice_badges()` - 练习后触发
- `check_streak_badges()` - 签到后触发
- `check_level_badges()` - 等级变化后触发
### 文件变更
- `backend/app/services/badge_service.py`
---
## 二、移动端适配
### 适配页面
| 页面 | 文件 | 适配要点 |
|------|------|----------|
| 登录页 | `views/login/index.vue` | 表单全宽、背景动画隐藏、钉钉安全区域 |
| 课程中心 | `views/trainee/course-center.vue` | 单列卡片、分类横向滚动、操作按钮网格化 |
| 课程详情 | `views/trainee/course-detail.vue` | 侧边栏折叠、视频自适应、工具栏响应式 |
| 考试页面 | `views/exam/practice.vue` | 选项垂直排列、按钮放大、弹窗全屏 |
| 成长路径 | `views/trainee/growth-path.vue` | 雷达图缩放、卡片堆叠、统计区折叠 |
| 排行榜 | `views/trainee/leaderboard.vue` | 列表简化、签到按钮全宽 |
### 技术方案
- 使用 `@media (max-width: 768px)``@media (max-width: 480px)` 断点
- 钉钉环境使用 `env(safe-area-inset-*)` 适配安全区域
---
## 三、证书系统
### 数据库设计
```sql
-- 证书模板表
CREATE TABLE certificate_templates (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
type ENUM('course', 'exam', 'achievement') NOT NULL,
background_url VARCHAR(500),
template_html TEXT,
template_style TEXT,
is_active BOOLEAN DEFAULT TRUE,
...
);
-- 用户证书表
CREATE TABLE user_certificates (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT NOT NULL,
template_id INT NOT NULL,
certificate_no VARCHAR(50) UNIQUE NOT NULL,
title VARCHAR(200) NOT NULL,
...
);
```
### 后端实现
- **模型**: `CertificateTemplate`, `UserCertificate`, `CertificateType`
- **服务**: `CertificateService`
- `issue_course_certificate()` - 颁发课程证书
- `issue_exam_certificate()` - 颁发考试证书
- `issue_achievement_certificate()` - 颁发成就证书
- `generate_certificate_image()` - 生成分享图片
- `get_certificate_by_no()` - 验证证书
### API 端点
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/certificates/me` | 我的证书列表 |
| GET | `/certificates/{id}` | 证书详情 |
| GET | `/certificates/{id}/image` | 获取分享图片 |
| GET | `/certificates/{id}/download` | 下载证书 |
| GET | `/certificates/verify/{no}` | 验证证书(无需登录) |
| POST | `/certificates/issue/course` | 颁发课程证书 |
| POST | `/certificates/issue/exam` | 颁发考试证书 |
### 前端实现
- **API**: `frontend/src/api/certificate.ts`
- **页面**: `frontend/src/views/trainee/my-certificates.vue`
- **功能**: 证书列表、分类筛选、预览、分享、下载
### 文件变更
- `backend/migrations/add_certificate_system.sql` (新增)
- `backend/app/models/certificate.py` (新增)
- `backend/app/services/certificate_service.py` (新增)
- `backend/app/api/v1/endpoints/certificate.py` (新增)
- `backend/app/models/__init__.py` (修改)
- `backend/app/api/v1/__init__.py` (修改)
- `frontend/src/api/certificate.ts` (新增)
- `frontend/src/views/trainee/my-certificates.vue` (新增)
- `frontend/src/router/index.ts` (修改)
---
## 四、数据大屏
### 数据指标
| 类别 | 指标 |
|------|------|
| 概览 | 总学员数、今日活跃、周活跃、月活跃、总学习时长、签到率 |
| 考试 | 总次数、通过率、平均分、满分人数 |
| 部门 | 成员数、通过率、平均学习时长、平均等级 |
| 趋势 | 近7天活跃用户、学习时长、考试次数 |
| 分布 | 1-10级用户数量分布 |
| 动态 | 最新学习活动实时滚动 |
### 后端实现
- **服务**: `DashboardService`
- `get_enterprise_overview()` - 企业级概览
- `get_department_comparison()` - 部门对比
- `get_learning_trend()` - 学习趋势
- `get_level_distribution()` - 等级分布
- `get_realtime_activities()` - 实时动态
- `get_team_dashboard()` - 团队级数据
- `get_course_ranking()` - 课程热度排行
### API 端点
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/dashboard/enterprise/overview` | 企业概览 |
| GET | `/dashboard/enterprise/departments` | 部门对比 |
| GET | `/dashboard/enterprise/trend` | 学习趋势 |
| GET | `/dashboard/enterprise/level-distribution` | 等级分布 |
| GET | `/dashboard/enterprise/activities` | 实时动态 |
| GET | `/dashboard/enterprise/course-ranking` | 课程排行 |
| GET | `/dashboard/team` | 团队数据 |
| GET | `/dashboard/all` | 完整数据(一次性) |
### 前端实现
- **API**: `frontend/src/api/dashboard.ts`
- **页面**: `frontend/src/views/admin/data-dashboard.vue`
- **图表**: ECharts (横向柱状图、折线图、仪表盘、饼图)
- **功能**: 全屏模式、5分钟自动刷新、响应式布局
### 文件变更
- `backend/app/services/dashboard_service.py` (新增)
- `backend/app/api/v1/endpoints/dashboard.py` (新增)
- `backend/app/api/v1/__init__.py` (修改)
- `frontend/src/api/dashboard.ts` (新增)
- `frontend/src/views/admin/data-dashboard.vue` (新增)
- `frontend/src/router/index.ts` (修改)
---
## 部署说明
### 数据库迁移
需执行以下 SQL 脚本:
```bash
# 证书系统迁移
mysql -u root -p kaopeilian < backend/migrations/add_certificate_system.sql
```
### 依赖安装
后端新增依赖(用于证书图片生成):
```bash
pip install Pillow qrcode
```
### 路由变更
新增前端路由:
- `/trainee/my-certificates` - 我的证书
- `/manager/data-dashboard` - 数据大屏
---
## 五、错误提示优化(下午更新)
### 课程名重复错误优化
**问题**:创建课程时名称重复返回 409 错误,前端提示不明确
**修复内容**
1. **后端** `course_service.py`:课程名重复时返回 `existing_id``existing_name`
2. **前端** `edit-course.vue`:检测 409 错误后弹出确认框
- "查看已有课程" → 跳转到已存在的课程
- "修改名称" → 留在当前页面
### 通用错误处理增强
- `errorHandler.ts` 新增 409 冲突错误处理
- 新增工具函数:`isConflictError()`, `getConflictDetail()`, `getConflictMessage()`
### 其他页面错误提示优化
- `position-management.vue`:岗位创建/编辑错误提取详细信息
- `user-management.vue`:用户编辑错误提取详细信息
### 文件变更
- `backend/app/services/course_service.py` (修改)
- `frontend/src/utils/errorHandler.ts` (修改)
- `frontend/src/views/manager/edit-course.vue` (修改)
- `frontend/src/views/admin/position-management.vue` (修改)
- `frontend/src/views/admin/user-management.vue` (修改)
---
## 六、部署问题修复(下午更新)
### 后端导入路径修复
1. `certificate.py` 模型:`from app.core.database import Base``from app.models.base import Base`
2. `certificate.py` API`from app.core.database import get_db``from app.core.deps import get_db`
3. `dashboard.py` API同上
4. 合并 `get_current_user` 导入到 `app.core.deps`
### 依赖安装
```bash
docker exec kpl-backend-dev pip install Pillow qrcode
```
### 前端构建同步问题
- 问题:构建输出到 `/root/aiedu/frontend/dist/`,但容器挂载的是 `/root/aiedu/dist-test/`
- 解决:构建后需手动同步 `cp -r /root/aiedu/frontend/dist/* /root/aiedu/dist-test/`
---
## 七、钉钉免密登录问题修复(下午更新)
### 问题现象
- 钉钉环境打开应用后显示"没有访问此页面的权限"
- 后端日志显示登录实际成功
### 问题原因
登录成功后读取 URL 中的 `redirect` 参数跳转,但该参数指向用户无权限的页面(如 /admin/*
### 修复内容
`login/index.vue`:登录成功后检查 redirect 目标是否有权限
```javascript
// 检查 redirect 目标是否有权限访问
if ((redirect.startsWith('/admin') && userRole !== 'admin') ||
(redirect.startsWith('/manager') && !['admin', 'manager'].includes(userRole))) {
redirect = defaultRoute // 改为跳转到默认页面
}
```
### 调试工具
- 钉钉环境自动启用 vConsole`main.ts` 中根据 UA 判断)
- 依赖:`npm install vconsole`
---
## 待办事项
- [ ] 证书 PDF 生成(需安装 weasyprint
- [ ] 课程完成进度追踪user_course_progress 表)
- [ ] 数据大屏数据缓存优化
- [ ] 钉钉环境下底部导航适配
- [ ] 移除 vConsole 调试代码(问题确认解决后)