init
This commit is contained in:
119
docs/TrainingProgressLogic.md
Normal file
119
docs/TrainingProgressLogic.md
Normal file
@@ -0,0 +1,119 @@
|
||||
# 培训计划学员进度计算逻辑说明
|
||||
|
||||
本文档说明了在生成“在线教育培训月度统计表”时,学员完成培训进度的计算逻辑及相关数据库表关联关系。
|
||||
|
||||
## 1. 总体进度计算逻辑
|
||||
|
||||
学员的培训进度取决于 `hot_training_participant` 表中的状态。
|
||||
|
||||
### 1.1 已完成学员
|
||||
如果学员在 `hot_training_participant` 表中的 `is_completed` 字段为 `1`(或 `complete_time` 不为空),则该学员的进度直接记为 **100%**。
|
||||
这意味着学员已经完成了所有的课程学习以及综合检测(如果有)。
|
||||
|
||||
### 1.2 未完成学员
|
||||
如果学员尚未完成(`is_completed = 0`),则进度计算公式如下:
|
||||
|
||||
$$
|
||||
\text{总进度} = \frac{\sum \text{各课程进度} + \text{综合检测进度}}{\text{课程数量} + 1}
|
||||
$$
|
||||
|
||||
* **课程数量**:当前培训计划包含的课程总数(来自 `hot_training_course_config`)。
|
||||
* **综合检测进度**:对于未完成学员,综合检测部分默认记为 **0%**。
|
||||
* **各课程进度**:见下文详细计算。
|
||||
|
||||
---
|
||||
|
||||
## 2. 单门课程进度计算逻辑
|
||||
|
||||
对于培训计划中的每一门课程,其进度计算取决于该课程是否包含**随堂练习**(题目)。
|
||||
|
||||
### 2.1 判断课程是否有随堂练习
|
||||
1. 通过 `hot_training_course_config` 表找到对应的 `course_id`。
|
||||
2. 查询 `hot_course_resource` 表,条件为 `course_id` 且 `resource_type = 3`(题目)。
|
||||
3. 如果存在记录,则认为该课程包含随堂练习;否则认为不包含。
|
||||
|
||||
### 2.2 课程进度计算公式
|
||||
|
||||
#### 情况 A:无随堂练习
|
||||
$$
|
||||
\text{课程进度} = \text{视频播放进度}
|
||||
$$
|
||||
* **视频播放进度**:取 `hot_training_course_record` 表中该用户该课程的 `progress_rate`(百分比值,最大100)。
|
||||
|
||||
#### 情况 B:有随堂练习
|
||||
$$
|
||||
\text{课程进度} = (\text{视频播放进度} \times 90\%) + (\text{随堂练习得分} \times 10\%)
|
||||
$$
|
||||
* **视频播放进度**:同上。
|
||||
* **随堂练习得分**:
|
||||
* 检查 `hot_training_course_record` 表中的 `check_status` 字段。
|
||||
* 如果 `check_status = 1`(已完成),则得分为 **100**。
|
||||
* 否则,得分为 **0**。
|
||||
|
||||
---
|
||||
|
||||
## 3. 课程时长计算逻辑(分钟)
|
||||
|
||||
“教育培训内容”区域除展示课程名称外,同时展示每门课程的视频总时长(分钟)。
|
||||
|
||||
### 3.1 计算步骤
|
||||
|
||||
1. 通过 `hot_training_course_config` 获取当前培训计划的课程列表(按 `sort_no` 排序),得到每门课的 `course_id`。
|
||||
2. 查询 `hot_course_resource` 表中该 `course_id` 下的视频资源:
|
||||
- 条件:`course_id = ? AND resource_type = 1`(视频)
|
||||
- 得到视频资源 ID 列表:`resource_id`(对应 `hot_media_resource.id`)
|
||||
3. 查询 `hot_media_resource` 表,按资源 ID 集合汇总视频时长:
|
||||
- 汇总字段:`SUM(duration_seconds)`
|
||||
4. 将秒数转换为分钟并向上取整:
|
||||
- `duration_min = ceil(duration_seconds / 60)`
|
||||
|
||||
### 3.2 展示规则
|
||||
|
||||
- 若课程无视频资源或汇总时长为空,则时长列显示空白。
|
||||
- 否则显示 `X分钟`。
|
||||
|
||||
---
|
||||
|
||||
## 4. 学习记录表 - 学习时长计算逻辑
|
||||
|
||||
在“学习记录表”中,会显示“学习分钟数/计划分钟数”。
|
||||
|
||||
### 4.1 计划分钟数
|
||||
逻辑同第3节“课程时长计算逻辑”,为该培训计划下所有课程视频时长的总和(分钟,向上取整)。
|
||||
|
||||
### 4.2 学习分钟数
|
||||
取 `hot_training_course_record` 表中的 `learn_duration_min` 字段。
|
||||
**注意**:尽管字段名为 `min`,但在实际业务中存储的是**秒**。
|
||||
因此计算逻辑为:
|
||||
1. 获取该用户在该培训计划下所有课程的学习记录。
|
||||
2. 若同一课程有多条记录,取 `learn_duration_min` 最大值。
|
||||
3. **对于每一门课程,将其学习时长与该课程的计划视频时长进行比较,取较小值(即学习时长不大于课程时长)。**
|
||||
4. 累加所有课程的**处理后时长**(秒)。
|
||||
5. 将总秒数除以 60 并向上取整,得到最终的学习分钟数。
|
||||
|
||||
---
|
||||
|
||||
## 5. 数据库表关联关系
|
||||
|
||||
以下是涉及的关键数据库表及其关联方式:
|
||||
|
||||
1. **hot_training (培训计划主表)**
|
||||
* `id`: 培训计划ID
|
||||
|
||||
2. **hot_training_participant (培训参与人员表)**
|
||||
* `training_id`: 关联 `hot_training.id`
|
||||
* `user_id`: 学员ID
|
||||
* `is_completed`: 是否完成培训 (1=是, 0=否)
|
||||
* `complete_time`: 完成时间
|
||||
|
||||
3. **hot_training_course_config (培训课程配置表)**
|
||||
* `training_id`: 关联 `hot_training.id`
|
||||
* `course_id`: 关联 `hot_course.id` (实际课程ID)
|
||||
* `id`: 培训课程配置ID (用于关联学习记录)
|
||||
|
||||
4. **hot_course_resource (课程资源关联表)**
|
||||
* `course_id`: 关联 `hot_course.id`
|
||||
* `resource_type`: 资源类型 (1=视频 2=音频 3=题目)
|
||||
* 用于判断课程是否有随堂练习。
|
||||
|
||||
5. **hot_training_course_record (培训课程学习记录表)**
|
||||
99
docs/dev_specs.md
Normal file
99
docs/dev_specs.md
Normal file
@@ -0,0 +1,99 @@
|
||||
# 车辆档案打印功能开发规范
|
||||
|
||||
## 1. 核心技术栈
|
||||
* **模板引擎**: Velocity (`.html.vm`)
|
||||
* **PDF生成**: Gotenberg (HTML转PDF)
|
||||
* **水印处理**: PDFBox (`PdfWatermarkUtil`)
|
||||
* **存储**: OSS (图片URL处理)
|
||||
|
||||
## 2. 通用样式与布局规范 (Template)
|
||||
所有打印模板位于 `src/main/resources/templates/vehicle/` 目录下。
|
||||
|
||||
### 2.1 页面布局
|
||||
* **纸张设置**: A4 纵向 (Vertical)。
|
||||
* **容器宽度**: `.page-content` 宽度建议设置为 **99%** 或留出微小边距,防止浏览器预览或打印时**右侧边框**被截断。
|
||||
* **表格样式**:
|
||||
* 必须使用标准 HTML `<table>`。
|
||||
* 边框合并: `border-collapse: collapse;`。
|
||||
* 边框线条: 统一使用细线 (`1px solid #000` 或 `#333`),避免出现粗细不一的视觉效果。
|
||||
* **禁止**使用 `<div>` 模拟表格边框,防止分页截断错位。
|
||||
|
||||
### 2.2 图片展示 (核心优化)
|
||||
* **容器**: 图片必须放置在表格单元格 (`<td>`) 内部。
|
||||
* **布局方式**: 使用 Flex 布局 (`display: flex; flex-wrap: wrap;`)。
|
||||
* **动态宽度逻辑** (Velocity):
|
||||
* **单张图片**: 宽度设为 **98%** (占满整行),居中显示。
|
||||
* **多张图片**: 宽度设为 **48%** (一行两张),保留 1% 间距。
|
||||
* **样式代码参考**:
|
||||
```html
|
||||
<div style="display: flex; flex-wrap: wrap; justify-content: flex-start;">
|
||||
#if($images.size() == 1)
|
||||
#set($widthStyle = "width: 98%;")
|
||||
#else
|
||||
#set($widthStyle = "width: 48%;")
|
||||
#end
|
||||
#foreach($img in $images)
|
||||
<div style="$!widthStyle height: 350px; margin: 1%; display: flex; align-items: center; justify-content: center; border: 1px solid #eee;">
|
||||
<img src="$!img" style="max-width: 100%; max-height: 100%; object-fit: contain;" />
|
||||
</div>
|
||||
#end
|
||||
</div>
|
||||
```
|
||||
|
||||
### 2.3 水印设置
|
||||
* **位置调整**: 为防止 A4 纵向打印时最后一行水印被截断,Y 轴偏移量需增加。
|
||||
* **代码位置**: `PdfWatermarkUtil.java`
|
||||
* **参数**: `y + 100` (原为 `y + 50`)。
|
||||
|
||||
---
|
||||
|
||||
## 3. 后端接口开发规范 (Java)
|
||||
|
||||
### 3.1 接口定义
|
||||
* **Controller**: `VehicleFileController`
|
||||
* **Service**: `IVehicleFilePrintService`
|
||||
* **请求方式**: `POST` (支持批量打印)
|
||||
* **参数**: `List<Long> vehicleIds`
|
||||
* **响应**: `void` (写入 `HttpServletResponse` 流,Content-Type: `application/pdf`)
|
||||
|
||||
### 3.2 数据查询逻辑
|
||||
所有打印业务需遵循“**取最新一条记录**”的原则:
|
||||
1. **查询条件**: `vehicle_id`
|
||||
2. **排序**: 按业务时间或完成时间 **倒序** (`orderByDesc`)
|
||||
3. **限制**: 取第一条 (`LIMIT 1`)
|
||||
4. **容错**:
|
||||
* 如果记录不存在 (`null`),跳过该车辆 (`continue`)。
|
||||
* **数据补全**: 如果业务表中缺失关键信息(如 `plateNumber`),**必须**回查 `hot_vehicle` 基础表进行补全。
|
||||
|
||||
### 3.3 图片URL处理
|
||||
* 数据库中图片通常以逗号分隔字符串存储 (`img1.jpg,img2.jpg`)。
|
||||
* **必须**使用 `splitUrls` 方法分割为 `List<String>`。
|
||||
* **必须**通过 `ossService.selectUrlByIds` 处理(如需签名或转换)。
|
||||
|
||||
---
|
||||
|
||||
## 4. 具体业务模块规范
|
||||
|
||||
### 4.1 车辆年审报告 (Inspection Report)
|
||||
* **接口地址**: `/vehicle/file/inspectionReport`
|
||||
* **数据源表**: `hot_vehicle_annual_review`
|
||||
* **关键字段**: `review_date` (年审日期), `image_urls` (附件)
|
||||
* **模板文件**: `inspectionReport.html.vm`
|
||||
* **特殊要求**:
|
||||
* 评定等级需转义 (1=一级, 2=二级)。
|
||||
* 所有附件图片需放入表格行中。
|
||||
|
||||
### 4.2 车辆二级维护记录 (Maintenance Record)
|
||||
* **接口地址**: `/vehicle/file/maintenanceRecord`
|
||||
* **数据源表**: `hot_vehicle_maintenance`
|
||||
* **关键字段**:
|
||||
* `finish_time` (完成时间 - 排序依据)
|
||||
* `entry_inspect_image_urls` (进厂检验单)
|
||||
* `process_inspect_image_urls` (过程检验单)
|
||||
* `final_inspect_image_urls` (竣工检验单)
|
||||
* `factory_cert_image_urls` (出厂合格证)
|
||||
* **模板文件**: `maintenanceRecord.html.vm`
|
||||
* **特殊要求**:
|
||||
* **纯表格布局**: 整个页面(包括标题、信息、四类图片)全部在 `<table>` 内部。
|
||||
* **标题样式**: 表格内的分类标题(如“竣工检验单”)**不需要**背景色,字体加粗居中。
|
||||
* **图片布局**: 严格执行“单张全宽、多张半宽”的动态布局规则。
|
||||
Reference in New Issue
Block a user