课程强制发布
This commit is contained in:
@@ -114,6 +114,7 @@ INSERT INTO `tb_sys_permission` (id, permission_id, name, code, description, mod
|
||||
|
||||
-- 1100-1199: 文章管理
|
||||
('1100', 'perm_admin_article_manage', '文章管理', 'admin:article:manage', '访问文章管理视图权限', 'module_news', '1', now()),
|
||||
('1101', 'perm_admin_article_force_publish', '文章强制发布', 'admin:article:force-publish', '强制发布文章权限(跳过敏感词校验)', 'module_news', '1', now()),
|
||||
|
||||
-- 1200-1299: Banner管理
|
||||
('1200', 'perm_admin_banner_manage', 'Banner管理', 'admin:banner:manage', '访问Banner管理视图权限', 'module_news', '1', now()),
|
||||
@@ -135,6 +136,7 @@ INSERT INTO `tb_sys_permission` (id, permission_id, name, code, description, mod
|
||||
|
||||
-- 2200-2299: 课程管理
|
||||
('2200', 'perm_admin_course_manage', '课程管理', 'admin:course:manage', '访问课程管理视图权限', 'module_study', '1', now()),
|
||||
('2201', 'perm_admin_course_force_publish', '课程强制发布', 'admin:course:force-publish', '强制发布课程权限(跳过敏感词校验)', 'module_study', '1', now()),
|
||||
|
||||
-- 2300-2399: 成就管理
|
||||
('2300', 'perm_admin_achievement_manage', '成就管理', 'admin:achievement:manage', '访问成就管理视图权限', 'module_study', '1', now()),
|
||||
@@ -200,6 +202,7 @@ INSERT INTO `tb_sys_role_permission` (id, role_id, permission_id, creator, creat
|
||||
-- 普通管理员权限 (1000-8999)
|
||||
('29', 'superadmin', 'perm_admin_resource_manage', '1', now()),
|
||||
('30', 'superadmin', 'perm_admin_article_manage', '1', now()),
|
||||
('46', 'superadmin', 'perm_admin_article_force_publish', '1', now()),
|
||||
('31', 'superadmin', 'perm_admin_banner_manage', '1', now()),
|
||||
('32', 'superadmin', 'perm_admin_tag_manage', '1', now()),
|
||||
('33', 'superadmin', 'perm_admin_column_manage', '1', now()),
|
||||
@@ -207,6 +210,7 @@ INSERT INTO `tb_sys_role_permission` (id, role_id, permission_id, creator, creat
|
||||
('35', 'superadmin', 'perm_admin_task_manage', '1', now()),
|
||||
('36', 'superadmin', 'perm_admin_study_records', '1', now()),
|
||||
('37', 'superadmin', 'perm_admin_course_manage', '1', now()),
|
||||
('47', 'superadmin', 'perm_admin_course_force_publish', '1', now()),
|
||||
('38', 'superadmin', 'perm_admin_achievement_manage', '1', now()),
|
||||
('39', 'superadmin', 'perm_admin_ai_config', '1', now()),
|
||||
('40', 'superadmin', 'perm_admin_knowledge_manage', '1', now()),
|
||||
@@ -249,6 +253,7 @@ INSERT INTO `tb_sys_role_permission` (id, role_id, permission_id, creator, creat
|
||||
-- 普通管理员权限 (1000-8999)
|
||||
('122', 'admin', 'perm_admin_resource_manage', '1', now()),
|
||||
('123', 'admin', 'perm_admin_article_manage', '1', now()),
|
||||
('140', 'admin', 'perm_admin_article_force_publish', '1', now()),
|
||||
('124', 'admin', 'perm_admin_banner_manage', '1', now()),
|
||||
('125', 'admin', 'perm_admin_tag_manage', '1', now()),
|
||||
('126', 'admin', 'perm_admin_column_manage', '1', now()),
|
||||
@@ -256,6 +261,7 @@ INSERT INTO `tb_sys_role_permission` (id, role_id, permission_id, creator, creat
|
||||
('128', 'admin', 'perm_admin_task_manage', '1', now()),
|
||||
('129', 'admin', 'perm_admin_study_records', '1', now()),
|
||||
('130', 'admin', 'perm_admin_course_manage', '1', now()),
|
||||
('141', 'admin', 'perm_admin_course_force_publish', '1', now()),
|
||||
('131', 'admin', 'perm_admin_achievement_manage', '1', now()),
|
||||
('132', 'admin', 'perm_admin_ai_config', '1', now()),
|
||||
('133', 'admin', 'perm_admin_knowledge_manage', '1', now()),
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
-- ============================================
|
||||
-- 强制发布权限更新脚本
|
||||
-- 用于更新现有数据库,添加文章和课程的强制发布权限
|
||||
-- 执行时间:2026-01-14
|
||||
-- ============================================
|
||||
|
||||
USE school_news;
|
||||
|
||||
-- 1. 插入新的权限数据
|
||||
INSERT INTO `tb_sys_permission` (id, permission_id, name, code, description, module_id, creator, create_time) VALUES
|
||||
('1101', 'perm_admin_article_force_publish', '文章强制发布', 'admin:article:force-publish', '强制发布文章权限(跳过敏感词校验)', 'module_news', '1', now()),
|
||||
('2201', 'perm_admin_course_force_publish', '课程强制发布', 'admin:course:force-publish', '强制发布课程权限(跳过敏感词校验)', 'module_study', '1', now())
|
||||
ON DUPLICATE KEY UPDATE
|
||||
name = VALUES(name),
|
||||
code = VALUES(code),
|
||||
description = VALUES(description),
|
||||
update_time = now();
|
||||
|
||||
-- 2. 为超级管理员角色添加强制发布权限
|
||||
INSERT INTO `tb_sys_role_permission` (id, role_id, permission_id, creator, create_time) VALUES
|
||||
('46', 'superadmin', 'perm_admin_article_force_publish', '1', now()),
|
||||
('47', 'superadmin', 'perm_admin_course_force_publish', '1', now())
|
||||
ON DUPLICATE KEY UPDATE update_time = now();
|
||||
|
||||
-- 3. 为管理员角色添加强制发布权限
|
||||
INSERT INTO `tb_sys_role_permission` (id, role_id, permission_id, creator, create_time) VALUES
|
||||
('140', 'admin', 'perm_admin_article_force_publish', '1', now()),
|
||||
('141', 'admin', 'perm_admin_course_force_publish', '1', now())
|
||||
ON DUPLICATE KEY UPDATE update_time = now();
|
||||
|
||||
-- 验证插入结果
|
||||
SELECT '=== 新增权限 ===' AS info;
|
||||
SELECT permission_id, name, code, description FROM tb_sys_permission
|
||||
WHERE permission_id IN ('perm_admin_article_force_publish', 'perm_admin_course_force_publish');
|
||||
|
||||
SELECT '=== 角色权限关联 ===' AS info;
|
||||
SELECT r.name AS role_name, p.name AS permission_name, p.code
|
||||
FROM tb_sys_role_permission rp
|
||||
JOIN tb_sys_role r ON r.role_id = rp.role_id
|
||||
JOIN tb_sys_permission p ON p.permission_id = rp.permission_id
|
||||
WHERE p.permission_id IN ('perm_admin_article_force_publish', 'perm_admin_course_force_publish');
|
||||
@@ -199,4 +199,13 @@ public interface CourseService {
|
||||
* @since 2025-11-14
|
||||
*/
|
||||
ResultDomain<Integer> getCourseCount(TbCourse filter);
|
||||
|
||||
/**
|
||||
* @description 强制发布课程(跳过敏感词校验)
|
||||
* @param courseID 课程ID
|
||||
* @return ResultDomain<TbCourse> 发布结果
|
||||
* @author kiro
|
||||
* @since 2026-01-14
|
||||
*/
|
||||
ResultDomain<TbCourse> forcePublishCourse(String courseID);
|
||||
}
|
||||
|
||||
@@ -166,4 +166,12 @@ public class CourseController {
|
||||
return courseService.incrementLearnCount(courseID);
|
||||
}
|
||||
|
||||
/**
|
||||
* 强制发布课程(跳过敏感词校验)
|
||||
*/
|
||||
@PostMapping("/{courseID}/force-publish")
|
||||
public ResultDomain<TbCourse> forcePublishCourse(@PathVariable("courseID") String courseID) {
|
||||
return courseService.forcePublishCourse(courseID);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -154,6 +154,72 @@ public class SCCourseServiceImpl implements SCCourseService {
|
||||
return resultDomain;
|
||||
}
|
||||
|
||||
// 验证课程基本信息
|
||||
if (courseItemVO.getName() == null || courseItemVO.getName().trim().isEmpty()) {
|
||||
resultDomain.fail("课程名称不能为空");
|
||||
return resultDomain;
|
||||
}
|
||||
|
||||
// 验证章节
|
||||
List<CourseItemVO> chapterVOs = courseItemVO.getChapters();
|
||||
if (chapterVOs == null || chapterVOs.isEmpty()) {
|
||||
resultDomain.fail("课程至少需要一个章节");
|
||||
return resultDomain;
|
||||
}
|
||||
|
||||
// 验证每个章节
|
||||
for (int i = 0; i < chapterVOs.size(); i++) {
|
||||
CourseItemVO chapterVO = chapterVOs.get(i);
|
||||
if (chapterVO.getName() == null || chapterVO.getName().trim().isEmpty()) {
|
||||
resultDomain.fail("第" + (i + 1) + "个章节名称不能为空");
|
||||
return resultDomain;
|
||||
}
|
||||
|
||||
// 验证章节节点
|
||||
List<CourseItemVO> nodeVOs = chapterVO.getChapters();
|
||||
if (nodeVOs == null || nodeVOs.isEmpty()) {
|
||||
resultDomain.fail("章节「" + chapterVO.getName() + "」至少需要一个学习节点");
|
||||
return resultDomain;
|
||||
}
|
||||
|
||||
// 验证每个节点
|
||||
for (int j = 0; j < nodeVOs.size(); j++) {
|
||||
CourseItemVO nodeVO = nodeVOs.get(j);
|
||||
if (nodeVO.getName() == null || nodeVO.getName().trim().isEmpty()) {
|
||||
resultDomain.fail("章节「" + chapterVO.getName() + "」的第" + (j + 1) + "个节点名称不能为空");
|
||||
return resultDomain;
|
||||
}
|
||||
|
||||
// 根据节点类型验证内容
|
||||
Integer nodeType = nodeVO.getNodeType();
|
||||
if (nodeType == null) {
|
||||
resultDomain.fail("章节「" + chapterVO.getName() + "」的节点「" + nodeVO.getName() + "」类型不能为空");
|
||||
return resultDomain;
|
||||
}
|
||||
|
||||
// 类型1:文章,需要resourceID
|
||||
// 类型2:文件/视频,需要resourceID或videoUrl
|
||||
// 类型3:文本,需要content
|
||||
if (nodeType == 1) {
|
||||
if (nodeVO.getResourceID() == null || nodeVO.getResourceID().trim().isEmpty()) {
|
||||
resultDomain.fail("章节「" + chapterVO.getName() + "」的节点「" + nodeVO.getName() + "」需要关联文章");
|
||||
return resultDomain;
|
||||
}
|
||||
} else if (nodeType == 2) {
|
||||
if ((nodeVO.getResourceID() == null || nodeVO.getResourceID().trim().isEmpty())
|
||||
&& (nodeVO.getVideoUrl() == null || nodeVO.getVideoUrl().trim().isEmpty())) {
|
||||
resultDomain.fail("章节「" + chapterVO.getName() + "」的节点「" + nodeVO.getName() + "」需要上传文件或视频");
|
||||
return resultDomain;
|
||||
}
|
||||
} else if (nodeType == 3) {
|
||||
if (nodeVO.getContent() == null || nodeVO.getContent().trim().isEmpty()) {
|
||||
resultDomain.fail("章节「" + chapterVO.getName() + "」的节点「" + nodeVO.getName() + "」内容不能为空");
|
||||
return resultDomain;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 转换为课程实体并保存
|
||||
TbCourse course = courseItemVO.toCourse();
|
||||
String courseID = IDUtils.generateID();
|
||||
@@ -763,4 +829,72 @@ public class SCCourseServiceImpl implements SCCourseService {
|
||||
}
|
||||
return resultDomain;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ResultDomain<TbCourse> forcePublishCourse(String courseID) {
|
||||
ResultDomain<TbCourse> resultDomain = new ResultDomain<>();
|
||||
try {
|
||||
// 参数验证
|
||||
if (courseID == null || courseID.isEmpty()) {
|
||||
resultDomain.fail("课程ID不能为空");
|
||||
return resultDomain;
|
||||
}
|
||||
|
||||
// 查询课程
|
||||
TbCourse course = courseMapper.selectByCourseId(courseID);
|
||||
if (course == null) {
|
||||
resultDomain.fail("课程不存在");
|
||||
return resultDomain;
|
||||
}
|
||||
|
||||
// 获取所有课程节点,强制设置为已审核
|
||||
List<TbCourseNode> nodeList = courseNodeMapper.selectByCourseId(courseID);
|
||||
if (nodeList != null && !nodeList.isEmpty()) {
|
||||
List<TbCourseNode> nodesToUpdate = new ArrayList<>();
|
||||
for (TbCourseNode node : nodeList) {
|
||||
if (!node.getIsAudited()) {
|
||||
node.setIsAudited(true);
|
||||
nodesToUpdate.add(node);
|
||||
|
||||
// 如果是文章类型节点,同时更新文章的审核状态
|
||||
if (node.getNodeType() == 1 && node.getResourceID() != null) {
|
||||
try {
|
||||
ResourceVO resource = new ResourceVO();
|
||||
resource.setResource(new TbResource());
|
||||
resource.getResource().setResourceID(node.getResourceID());
|
||||
resource.getResource().setIsAudited(true);
|
||||
resourceService.updateResource(resource);
|
||||
} catch (Exception e) {
|
||||
logger.warn("更新节点关联文章审核状态失败: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 批量更新节点审核状态
|
||||
if (!nodesToUpdate.isEmpty()) {
|
||||
courseNodeMapper.batchUpdateNodeAudited(nodesToUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
// 强制发布:跳过敏感词校验,直接设置为已发布
|
||||
course.setStatus(1);
|
||||
course.setUpdateTime(new Date());
|
||||
int result = courseMapper.updateCourse(course);
|
||||
|
||||
if (result > 0) {
|
||||
logger.info("强制发布课程成功: {}", courseID);
|
||||
// 重新查询返回完整数据
|
||||
TbCourse updated = courseMapper.selectByCourseId(courseID);
|
||||
resultDomain.success("强制发布课程成功", updated);
|
||||
} else {
|
||||
resultDomain.fail("强制发布课程失败");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("强制发布课程异常: {}", e.getMessage(), e);
|
||||
resultDomain.fail("强制发布课程失败: " + e.getMessage());
|
||||
}
|
||||
return resultDomain;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -241,8 +241,8 @@
|
||||
<!-- batchUpdateNodeAudited -->
|
||||
<update id="batchUpdateNodeAudited">
|
||||
<foreach collection="courseNodeList" item="item" separator=";">
|
||||
UPDATE tb_course_node
|
||||
SET is_audited = #{item.isAudited}
|
||||
UPDATE tb_course_node
|
||||
SET is_audited = #{item.isAudited}
|
||||
WHERE node_id = #{item.nodeID}
|
||||
</foreach>
|
||||
</update>
|
||||
|
||||
Reference in New Issue
Block a user