refactor: 代码优化和资源表修复

- 修复 CourseStatus 枚举
- 优化 CourseServiceImpl 和 TeacherStatsServiceImpl
- 修复资源表迁移脚本
- 更新开发日志

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
En 2026-03-16 15:35:57 +08:00
parent 4a713c41d3
commit 05d075eefc
10 changed files with 14 additions and 49 deletions

View File

@ -432,7 +432,7 @@ reading-platform-frontend/test-results/
│ ├── 家长学生关联 (parent_student) → 家长 (parent) │ ├── 家长学生关联 (parent_student) → 家长 (parent)
│ ├── 任务完成 (task_completion) │ ├── 任务完成 (task_completion)
│ └── 成长记录 (growth_record) │ └── 成长记录 (growth_record)
└── 资源库 (resource_librarie) └── 资源库 (resource_library)
└── 资源项 (resource_item) └── 资源项 (resource_item)
``` ```

View File

@ -11,67 +11,32 @@ declare module 'vue' {
AAvatar: typeof import('ant-design-vue/es')['Avatar'] AAvatar: typeof import('ant-design-vue/es')['Avatar']
ABadge: typeof import('ant-design-vue/es')['Badge'] ABadge: typeof import('ant-design-vue/es')['Badge']
AButton: typeof import('ant-design-vue/es')['Button'] AButton: typeof import('ant-design-vue/es')['Button']
AButtonGroup: typeof import('ant-design-vue/es')['ButtonGroup']
ACard: typeof import('ant-design-vue/es')['Card'] ACard: typeof import('ant-design-vue/es')['Card']
ACheckbox: typeof import('ant-design-vue/es')['Checkbox'] ACheckbox: typeof import('ant-design-vue/es')['Checkbox']
ACheckboxGroup: typeof import('ant-design-vue/es')['CheckboxGroup']
ACol: typeof import('ant-design-vue/es')['Col'] ACol: typeof import('ant-design-vue/es')['Col']
ADatePicker: typeof import('ant-design-vue/es')['DatePicker']
ADescriptions: typeof import('ant-design-vue/es')['Descriptions']
ADescriptionsItem: typeof import('ant-design-vue/es')['DescriptionsItem']
ADivider: typeof import('ant-design-vue/es')['Divider']
ADrawer: typeof import('ant-design-vue/es')['Drawer']
ADropdown: typeof import('ant-design-vue/es')['Dropdown'] ADropdown: typeof import('ant-design-vue/es')['Dropdown']
AEmpty: typeof import('ant-design-vue/es')['Empty'] AEmpty: typeof import('ant-design-vue/es')['Empty']
AForm: typeof import('ant-design-vue/es')['Form'] AForm: typeof import('ant-design-vue/es')['Form']
AFormItem: typeof import('ant-design-vue/es')['FormItem'] AFormItem: typeof import('ant-design-vue/es')['FormItem']
AImage: typeof import('ant-design-vue/es')['Image']
AImagePreviewGroup: typeof import('ant-design-vue/es')['ImagePreviewGroup']
AInput: typeof import('ant-design-vue/es')['Input'] AInput: typeof import('ant-design-vue/es')['Input']
AInputNumber: typeof import('ant-design-vue/es')['InputNumber']
AInputPassword: typeof import('ant-design-vue/es')['InputPassword'] AInputPassword: typeof import('ant-design-vue/es')['InputPassword']
AInputSearch: typeof import('ant-design-vue/es')['InputSearch'] AInputSearch: typeof import('ant-design-vue/es')['InputSearch']
ALayout: typeof import('ant-design-vue/es')['Layout'] ALayout: typeof import('ant-design-vue/es')['Layout']
ALayoutContent: typeof import('ant-design-vue/es')['LayoutContent'] ALayoutContent: typeof import('ant-design-vue/es')['LayoutContent']
ALayoutHeader: typeof import('ant-design-vue/es')['LayoutHeader'] ALayoutHeader: typeof import('ant-design-vue/es')['LayoutHeader']
ALayoutSider: typeof import('ant-design-vue/es')['LayoutSider'] ALayoutSider: typeof import('ant-design-vue/es')['LayoutSider']
AList: typeof import('ant-design-vue/es')['List']
AListItem: typeof import('ant-design-vue/es')['ListItem']
AListItemMeta: typeof import('ant-design-vue/es')['ListItemMeta']
AMenu: typeof import('ant-design-vue/es')['Menu'] AMenu: typeof import('ant-design-vue/es')['Menu']
AMenuDivider: typeof import('ant-design-vue/es')['MenuDivider'] AMenuDivider: typeof import('ant-design-vue/es')['MenuDivider']
AMenuItem: typeof import('ant-design-vue/es')['MenuItem'] AMenuItem: typeof import('ant-design-vue/es')['MenuItem']
AModal: typeof import('ant-design-vue/es')['Modal'] AModal: typeof import('ant-design-vue/es')['Modal']
APageHeader: typeof import('ant-design-vue/es')['PageHeader']
APagination: typeof import('ant-design-vue/es')['Pagination']
APopconfirm: typeof import('ant-design-vue/es')['Popconfirm'] APopconfirm: typeof import('ant-design-vue/es')['Popconfirm']
AProgress: typeof import('ant-design-vue/es')['Progress']
ARadio: typeof import('ant-design-vue/es')['Radio']
ARadioGroup: typeof import('ant-design-vue/es')['RadioGroup']
ARangePicker: typeof import('ant-design-vue/es')['RangePicker']
ARate: typeof import('ant-design-vue/es')['Rate']
ARow: typeof import('ant-design-vue/es')['Row'] ARow: typeof import('ant-design-vue/es')['Row']
ASelect: typeof import('ant-design-vue/es')['Select'] ASelect: typeof import('ant-design-vue/es')['Select']
ASelectOptGroup: typeof import('ant-design-vue/es')['SelectOptGroup']
ASelectOption: typeof import('ant-design-vue/es')['SelectOption'] ASelectOption: typeof import('ant-design-vue/es')['SelectOption']
ASkeleton: typeof import('ant-design-vue/es')['Skeleton']
ASpace: typeof import('ant-design-vue/es')['Space'] ASpace: typeof import('ant-design-vue/es')['Space']
ASpin: typeof import('ant-design-vue/es')['Spin']
AStatistic: typeof import('ant-design-vue/es')['Statistic']
AStep: typeof import('ant-design-vue/es')['Step']
ASteps: typeof import('ant-design-vue/es')['Steps']
ASubMenu: typeof import('ant-design-vue/es')['SubMenu']
ASwitch: typeof import('ant-design-vue/es')['Switch']
ATable: typeof import('ant-design-vue/es')['Table'] ATable: typeof import('ant-design-vue/es')['Table']
ATabPane: typeof import('ant-design-vue/es')['TabPane']
ATabs: typeof import('ant-design-vue/es')['Tabs']
ATag: typeof import('ant-design-vue/es')['Tag'] ATag: typeof import('ant-design-vue/es')['Tag']
ATextarea: typeof import('ant-design-vue/es')['Textarea']
ATimeRangePicker: typeof import('ant-design-vue/es')['TimeRangePicker']
ATooltip: typeof import('ant-design-vue/es')['Tooltip'] ATooltip: typeof import('ant-design-vue/es')['Tooltip']
ATypographyText: typeof import('ant-design-vue/es')['TypographyText']
AUpload: typeof import('ant-design-vue/es')['Upload']
AUploadDragger: typeof import('ant-design-vue/es')['UploadDragger']
FilePreviewModal: typeof import('./components/FilePreviewModal.vue')['default'] FilePreviewModal: typeof import('./components/FilePreviewModal.vue')['default']
FileUploader: typeof import('./components/course/FileUploader.vue')['default'] FileUploader: typeof import('./components/course/FileUploader.vue')['default']
LessonConfigPanel: typeof import('./components/course/LessonConfigPanel.vue')['default'] LessonConfigPanel: typeof import('./components/course/LessonConfigPanel.vue')['default']

View File

@ -145,7 +145,7 @@ School, teacher, and parent accounts need to be created through the admin interf
| Lesson | lessons, lesson_feedbacks, student_records | | Lesson | lessons, lesson_feedbacks, student_records |
| Task | tasks, task_targets, task_completions, task_templates | | Task | tasks, task_targets, task_completions, task_templates |
| Growth | growth_records | | Growth | growth_records |
| Resource | resource_libraries, resource_items | | Resource | resource_library, resource_items |
| Schedule | schedule_plans, schedule_templates | | Schedule | schedule_plans, schedule_templates |
| System | system_settings, notifications, operation_logs, tags | | System | system_settings, notifications, operation_logs, tags |

View File

@ -9,7 +9,7 @@ import lombok.Getter;
public enum CourseStatus { public enum CourseStatus {
DRAFT("draft", "Draft"), DRAFT("draft", "Draft"),
PUBLISHED("published", "Published"), PUBLISHED("published", "PUBLISHED"),
ARCHIVED("archived", "Archived"); ARCHIVED("archived", "Archived");
private final String code; private final String code;

View File

@ -11,7 +11,7 @@ import lombok.EqualsAndHashCode;
@Schema(description = "资源库实体") @Schema(description = "资源库实体")
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@TableName("resource_librarie") @TableName("resource_library")
public class ResourceLibrary extends BaseEntity { public class ResourceLibrary extends BaseEntity {
@Schema(description = "租户 ID") @Schema(description = "租户 ID")

View File

@ -394,7 +394,7 @@ public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course>
@Transactional @Transactional
public void publishCourse(Long id) { public void publishCourse(Long id) {
Course course = getCourseById(id); Course course = getCourseById(id);
course.setStatus("published"); course.setStatus("PUBLISHED");
course.setPublishedAt(LocalDateTime.now()); course.setPublishedAt(LocalDateTime.now());
courseMapper.updateById(course); courseMapper.updateById(course);
log.info("课程发布成功id={}", id); log.info("课程发布成功id={}", id);
@ -433,7 +433,7 @@ public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course>
.or() .or()
.eq(Course::getIsSystem, 1) .eq(Course::getIsSystem, 1)
) )
.eq(Course::getStatus, "published") .eq(Course::getStatus, "PUBLISHED")
.orderByAsc(Course::getName) .orderByAsc(Course::getName)
); );
} }

View File

@ -78,7 +78,7 @@ public class TeacherStatsServiceImpl implements TeacherStatsService {
List<Course> recommendedCourses = courseMapper.selectList( List<Course> recommendedCourses = courseMapper.selectList(
new LambdaQueryWrapper<Course>() new LambdaQueryWrapper<Course>()
.eq(Course::getTenantId, tenantId) .eq(Course::getTenantId, tenantId)
.eq(Course::getStatus, "published") .eq(Course::getStatus, "PUBLISHED")
.orderByDesc(Course::getUsageCount) .orderByDesc(Course::getUsageCount)
.last("LIMIT 5") .last("LIMIT 5")
); );
@ -132,7 +132,7 @@ public class TeacherStatsServiceImpl implements TeacherStatsService {
return courseMapper.selectList( return courseMapper.selectList(
new LambdaQueryWrapper<Course>() new LambdaQueryWrapper<Course>()
.eq(Course::getTenantId, tenantId) .eq(Course::getTenantId, tenantId)
.eq(Course::getStatus, "published") .eq(Course::getStatus, "PUBLISHED")
.orderByDesc(Course::getUsageCount) .orderByDesc(Course::getUsageCount)
.last("LIMIT 10") .last("LIMIT 10")
); );

View File

@ -197,7 +197,7 @@ INSERT IGNORE INTO `student_record` (`id`, `lesson_id`, `student_id`, `attendanc
-- 11. 资源库和资源项数据 -- 11. 资源库和资源项数据
-- ----------------------------------------------------- -- -----------------------------------------------------
INSERT IGNORE INTO `resource_librarie` (`id`, `name`, `library_type`, `description`, `cover_image`, `status`, `sort_order`, `created_by`) VALUES INSERT IGNORE INTO `resource_library` (`id`, `name`, `library_type`, `description`, `cover_image`, `status`, `sort_order`, `created_by`) VALUES
(1, '绘本资源库', 'PICTURE_BOOK', '精选优质绘本资源', '/libraries/picture-book/cover.jpg', 'ACTIVE', 1, 1), (1, '绘本资源库', 'PICTURE_BOOK', '精选优质绘本资源', '/libraries/picture-book/cover.jpg', 'ACTIVE', 1, 1),
(2, '教学素材库', 'MATERIAL', '教学辅助素材资源', '/libraries/material/cover.jpg', 'ACTIVE', 2, 1), (2, '教学素材库', 'MATERIAL', '教学辅助素材资源', '/libraries/material/cover.jpg', 'ACTIVE', 2, 1),
(3, '活动模板库', 'TEMPLATE', '各类活动模板', '/libraries/template/cover.jpg', 'ACTIVE', 3, 1); (3, '活动模板库', 'TEMPLATE', '各类活动模板', '/libraries/template/cover.jpg', 'ACTIVE', 3, 1);

View File

@ -6,9 +6,9 @@
-- ===================================================== -- =====================================================
-- ----------------------------------------------------- -- -----------------------------------------------------
-- 表30: 资源库表 (resource_librarie) -- 表30: 资源库表 (resource_library)
-- ----------------------------------------------------- -- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `resource_librarie` ( CREATE TABLE IF NOT EXISTS `resource_library` (
`id` BIGINT NOT NULL COMMENT '主键ID', `id` BIGINT NOT NULL COMMENT '主键ID',
`tenant_id` VARCHAR(50) COMMENT '租户ID', `tenant_id` VARCHAR(50) COMMENT '租户ID',
`name` VARCHAR(200) NOT NULL COMMENT '资源库名称', `name` VARCHAR(200) NOT NULL COMMENT '资源库名称',

View File

@ -5,9 +5,9 @@
-- ===================================================== -- =====================================================
-- ----------------------------------------------------- -- -----------------------------------------------------
-- 1. 修改 resource_librarie 表,添加数字资源管理字段 -- 1. 修改 resource_library 表,添加数字资源管理字段
-- ----------------------------------------------------- -- -----------------------------------------------------
ALTER TABLE `resource_librarie` ALTER TABLE `resource_library`
ADD COLUMN `library_type` VARCHAR(50) COMMENT '资源库类型 (PICTURE_BOOK/MATERIAL/TEMPLATE)', ADD COLUMN `library_type` VARCHAR(50) COMMENT '资源库类型 (PICTURE_BOOK/MATERIAL/TEMPLATE)',
ADD COLUMN `cover_image` VARCHAR(500) COMMENT '封面图片 URL', ADD COLUMN `cover_image` VARCHAR(500) COMMENT '封面图片 URL',
ADD COLUMN `status` VARCHAR(20) DEFAULT 'ACTIVE' COMMENT '状态', ADD COLUMN `status` VARCHAR(20) DEFAULT 'ACTIVE' COMMENT '状态',
@ -15,7 +15,7 @@ ADD COLUMN `sort_order` INT DEFAULT 0 COMMENT '排序号',
ADD COLUMN `created_by` BIGINT COMMENT '创建人 ID'; ADD COLUMN `created_by` BIGINT COMMENT '创建人 ID';
-- 将现有的 type 字段数据复制到 library_type -- 将现有的 type 字段数据复制到 library_type
UPDATE `resource_librarie` SET `library_type` = `type` WHERE `type` IS NOT NULL; UPDATE `resource_library` SET `library_type` = `type` WHERE `type` IS NOT NULL;
-- ----------------------------------------------------- -- -----------------------------------------------------
-- 2. 修改 resource_item 表,添加数字资源管理字段 -- 2. 修改 resource_item 表,添加数字资源管理字段