Compare commits
2 Commits
71d8819361
...
01897a7ecc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
01897a7ecc | ||
|
|
18170609d9 |
@ -108,7 +108,7 @@ export function getCourses(params: CourseQueryParams): Promise<{
|
||||
page: number;
|
||||
pageSize: number;
|
||||
}> {
|
||||
return http.get('/courses', { params });
|
||||
return http.get('/admin/courses', { params });
|
||||
}
|
||||
|
||||
// 获取审核列表
|
||||
@ -118,82 +118,82 @@ export function getReviewList(params: CourseQueryParams): Promise<{
|
||||
page: number;
|
||||
pageSize: number;
|
||||
}> {
|
||||
return http.get('/courses/review', { params });
|
||||
return http.get('/admin/courses/review', { params });
|
||||
}
|
||||
|
||||
// 获取课程包详情
|
||||
export function getCourse(id: number): Promise<any> {
|
||||
return http.get(`/courses/${id}`);
|
||||
return http.get(`/admin/courses/${id}`);
|
||||
}
|
||||
|
||||
// 创建课程包
|
||||
export function createCourse(data: any): Promise<any> {
|
||||
return http.post('/courses', data);
|
||||
return http.post('/admin/courses', data);
|
||||
}
|
||||
|
||||
// 更新课程包
|
||||
export function updateCourse(id: number, data: any): Promise<any> {
|
||||
return http.put(`/courses/${id}`, data);
|
||||
return http.put(`/admin/courses/${id}`, data);
|
||||
}
|
||||
|
||||
// 删除课程包
|
||||
export function deleteCourse(id: number): Promise<any> {
|
||||
return http.delete(`/courses/${id}`);
|
||||
return http.delete(`/admin/courses/${id}`);
|
||||
}
|
||||
|
||||
// 验证课程完整性
|
||||
export function validateCourse(id: number): Promise<ValidationResult> {
|
||||
return http.get(`/courses/${id}/validate`);
|
||||
return http.get(`/admin/courses/${id}/validate`);
|
||||
}
|
||||
|
||||
// 提交审核
|
||||
export function submitCourse(id: number, copyrightConfirmed: boolean): Promise<any> {
|
||||
return http.post(`/courses/${id}/submit`, { copyrightConfirmed });
|
||||
return http.post(`/admin/courses/${id}/submit`, { copyrightConfirmed });
|
||||
}
|
||||
|
||||
// 撤销审核
|
||||
export function withdrawCourse(id: number): Promise<any> {
|
||||
return http.post(`/courses/${id}/withdraw`);
|
||||
return http.post(`/admin/courses/${id}/withdraw`);
|
||||
}
|
||||
|
||||
// 审核通过
|
||||
export function approveCourse(id: number, data: { checklist?: any; comment?: string }): Promise<any> {
|
||||
return http.post(`/courses/${id}/approve`, data);
|
||||
return http.post(`/admin/courses/${id}/approve`, data);
|
||||
}
|
||||
|
||||
// 审核驳回
|
||||
export function rejectCourse(id: number, data: { checklist?: any; comment: string }): Promise<any> {
|
||||
return http.post(`/courses/${id}/reject`, data);
|
||||
return http.post(`/admin/courses/${id}/reject`, data);
|
||||
}
|
||||
|
||||
// 直接发布(超级管理员)
|
||||
export function directPublishCourse(id: number, skipValidation?: boolean): Promise<any> {
|
||||
return http.post(`/courses/${id}/direct-publish`, { skipValidation });
|
||||
return http.post(`/admin/courses/${id}/direct-publish`, { skipValidation });
|
||||
}
|
||||
|
||||
// 发布课程包(兼容旧API)
|
||||
export function publishCourse(id: number): Promise<any> {
|
||||
return http.post(`/courses/${id}/publish`);
|
||||
return http.post(`/admin/courses/${id}/publish`);
|
||||
}
|
||||
|
||||
// 下架课程包
|
||||
export function unpublishCourse(id: number): Promise<any> {
|
||||
return http.post(`/courses/${id}/unpublish`);
|
||||
return http.post(`/admin/courses/${id}/unpublish`);
|
||||
}
|
||||
|
||||
// 重新发布
|
||||
export function republishCourse(id: number): Promise<any> {
|
||||
return http.post(`/courses/${id}/republish`);
|
||||
return http.post(`/admin/courses/${id}/republish`);
|
||||
}
|
||||
|
||||
// 获取课程包统计数据
|
||||
export function getCourseStats(id: number): Promise<any> {
|
||||
return http.get(`/courses/${id}/stats`);
|
||||
return http.get(`/admin/courses/${id}/stats`);
|
||||
}
|
||||
|
||||
// 获取版本历史
|
||||
export function getCourseVersions(id: number): Promise<any[]> {
|
||||
return http.get(`/courses/${id}/versions`);
|
||||
return http.get(`/admin/courses/${id}/versions`);
|
||||
}
|
||||
|
||||
// 课程状态映射
|
||||
|
||||
@ -447,21 +447,31 @@ router.beforeEach((to, from, next) => {
|
||||
const token = localStorage.getItem('token');
|
||||
const userRole = localStorage.getItem('role');
|
||||
|
||||
// 检测无效 token 或角色缺失,清除旧数据强制重新登录
|
||||
const validRoles = ['admin', 'school', 'teacher', 'parent'];
|
||||
const isValidToken = token && token.split('.').length === 3;
|
||||
const isValidRole = userRole && validRoles.includes(userRole);
|
||||
if ((token && !isValidToken) || (userRole && !isValidRole) || (isValidToken && !userRole)) {
|
||||
localStorage.clear();
|
||||
next('/login');
|
||||
return;
|
||||
}
|
||||
|
||||
// 设置页面标题
|
||||
if (to.meta.title) {
|
||||
document.title = `${to.meta.title} - 幼儿阅读教学服务平台`;
|
||||
}
|
||||
|
||||
// 需要认证但未登录
|
||||
if (to.meta.requiresAuth && !token) {
|
||||
if (to.meta.requiresAuth && !isValidToken) {
|
||||
message.warning('请先登录');
|
||||
next('/login');
|
||||
return;
|
||||
}
|
||||
|
||||
// 已登录用户访问登录页,跳转到对应首页
|
||||
if (to.path === '/login' && token) {
|
||||
const defaultRoute = userRole ? `/${userRole}/dashboard` : '/admin/dashboard';
|
||||
if (to.path === '/login' && isValidToken) {
|
||||
const defaultRoute = isValidRole ? `/${userRole}/dashboard` : '/admin/dashboard';
|
||||
next(defaultRoute);
|
||||
return;
|
||||
}
|
||||
@ -469,7 +479,7 @@ router.beforeEach((to, from, next) => {
|
||||
// 角色权限检查
|
||||
if (to.meta.role && userRole !== to.meta.role) {
|
||||
message.error('没有权限访问该页面');
|
||||
next(`/${userRole}/dashboard`);
|
||||
next(isValidRole ? `/${userRole}/dashboard` : '/login');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -45,14 +45,24 @@ public class AdminCourseController {
|
||||
return Result.success(courseService.getCourseById(id));
|
||||
}
|
||||
|
||||
@Operation(summary = "Get system course page")
|
||||
@Operation(summary = "Get system course page (all statuses)")
|
||||
@GetMapping
|
||||
public Result<PageResult<Course>> getCoursePage(
|
||||
@RequestParam(value = "page", required = false) Integer pageNum,
|
||||
@RequestParam(required = false) Integer pageSize,
|
||||
@RequestParam(required = false) String keyword,
|
||||
@RequestParam(required = false) String category) {
|
||||
Page<Course> page = courseService.getSystemCoursePage(pageNum, pageSize, keyword, category);
|
||||
@RequestParam(required = false) String category,
|
||||
@RequestParam(required = false) String status) {
|
||||
Page<Course> page = courseService.getSystemCoursePage(pageNum, pageSize, keyword, category, status);
|
||||
return Result.success(PageResult.of(page));
|
||||
}
|
||||
|
||||
@Operation(summary = "Get courses pending review")
|
||||
@GetMapping("/review")
|
||||
public Result<PageResult<Course>> getReviewCoursePage(
|
||||
@RequestParam(value = "page", required = false) Integer pageNum,
|
||||
@RequestParam(required = false) Integer pageSize) {
|
||||
Page<Course> page = courseService.getReviewCoursePage(pageNum, pageSize);
|
||||
return Result.success(PageResult.of(page));
|
||||
}
|
||||
|
||||
@ -63,6 +73,38 @@ public class AdminCourseController {
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@Operation(summary = "Submit course for review")
|
||||
@PostMapping("/{id}/submit")
|
||||
public Result<Void> submitCourse(@PathVariable Long id) {
|
||||
courseService.submitCourse(id);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@Operation(summary = "Withdraw course from review")
|
||||
@PostMapping("/{id}/withdraw")
|
||||
public Result<Void> withdrawCourse(@PathVariable Long id) {
|
||||
courseService.withdrawCourse(id);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@Operation(summary = "Approve course")
|
||||
@PostMapping("/{id}/approve")
|
||||
public Result<Void> approveCourse(
|
||||
@PathVariable Long id,
|
||||
@RequestParam(required = false) String comment) {
|
||||
courseService.approveCourse(id, comment);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@Operation(summary = "Reject course")
|
||||
@PostMapping("/{id}/reject")
|
||||
public Result<Void> rejectCourse(
|
||||
@PathVariable Long id,
|
||||
@RequestParam(required = false) String comment) {
|
||||
courseService.rejectCourse(id, comment);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@Operation(summary = "Publish course")
|
||||
@PostMapping("/{id}/publish")
|
||||
public Result<Void> publishCourse(@PathVariable Long id) {
|
||||
@ -70,6 +112,27 @@ public class AdminCourseController {
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@Operation(summary = "Direct publish course (skip review)")
|
||||
@PostMapping("/{id}/direct-publish")
|
||||
public Result<Void> directPublishCourse(@PathVariable Long id) {
|
||||
courseService.publishCourse(id);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@Operation(summary = "Unpublish (archive) course")
|
||||
@PostMapping("/{id}/unpublish")
|
||||
public Result<Void> unpublishCourse(@PathVariable Long id) {
|
||||
courseService.archiveCourse(id);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@Operation(summary = "Republish course")
|
||||
@PostMapping("/{id}/republish")
|
||||
public Result<Void> republishCourse(@PathVariable Long id) {
|
||||
courseService.publishCourse(id);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@Operation(summary = "Archive course")
|
||||
@PostMapping("/{id}/archive")
|
||||
public Result<Void> archiveCourse(@PathVariable Long id) {
|
||||
|
||||
@ -20,7 +20,7 @@ public interface CourseService {
|
||||
|
||||
Page<Course> getCoursePage(Long tenantId, Integer pageNum, Integer pageSize, String keyword, String category, String status);
|
||||
|
||||
Page<Course> getSystemCoursePage(Integer pageNum, Integer pageSize, String keyword, String category);
|
||||
Page<Course> getSystemCoursePage(Integer pageNum, Integer pageSize, String keyword, String category, String status);
|
||||
|
||||
void deleteCourse(Long id);
|
||||
|
||||
@ -30,4 +30,14 @@ public interface CourseService {
|
||||
|
||||
List<Course> getCoursesByTenantId(Long tenantId);
|
||||
|
||||
Page<Course> getReviewCoursePage(Integer pageNum, Integer pageSize);
|
||||
|
||||
void submitCourse(Long id);
|
||||
|
||||
void withdrawCourse(Long id);
|
||||
|
||||
void approveCourse(Long id, String comment);
|
||||
|
||||
void rejectCourse(Long id, String comment);
|
||||
|
||||
}
|
||||
|
||||
@ -250,13 +250,15 @@ public class CourseServiceImpl implements CourseService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<Course> getSystemCoursePage(Integer pageNum, Integer pageSize, String keyword, String category) {
|
||||
public Page<Course> getSystemCoursePage(Integer pageNum, Integer pageSize, String keyword, String category, String status) {
|
||||
Page<Course> page = PageUtils.of(pageNum, pageSize);
|
||||
LambdaQueryWrapper<Course> wrapper = new LambdaQueryWrapper<>();
|
||||
|
||||
wrapper.eq(Course::getIsSystem, 1)
|
||||
.eq(Course::getStatus, "published");
|
||||
wrapper.eq(Course::getIsSystem, 1);
|
||||
|
||||
if (StringUtils.hasText(status)) {
|
||||
wrapper.eq(Course::getStatus, status.toLowerCase());
|
||||
}
|
||||
if (StringUtils.hasText(keyword)) {
|
||||
wrapper.and(w -> w
|
||||
.like(Course::getName, keyword)
|
||||
@ -309,4 +311,56 @@ public class CourseServiceImpl implements CourseService {
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<Course> getReviewCoursePage(Integer pageNum, Integer pageSize) {
|
||||
Page<Course> page = PageUtils.of(pageNum, pageSize);
|
||||
LambdaQueryWrapper<Course> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(Course::getIsSystem, 1)
|
||||
.eq(Course::getStatus, "pending")
|
||||
.orderByDesc(Course::getSubmittedAt);
|
||||
return courseMapper.selectPage(page, wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void submitCourse(Long id) {
|
||||
Course course = getCourseById(id);
|
||||
course.setStatus("pending");
|
||||
course.setSubmittedAt(LocalDateTime.now());
|
||||
courseMapper.updateById(course);
|
||||
log.info("Course submitted for review: id={}", id);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void withdrawCourse(Long id) {
|
||||
Course course = getCourseById(id);
|
||||
course.setStatus("draft");
|
||||
courseMapper.updateById(course);
|
||||
log.info("Course withdrawn from review: id={}", id);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void approveCourse(Long id, String comment) {
|
||||
Course course = getCourseById(id);
|
||||
course.setStatus("published");
|
||||
course.setReviewComment(comment);
|
||||
course.setReviewedAt(LocalDateTime.now());
|
||||
course.setPublishedAt(LocalDateTime.now());
|
||||
courseMapper.updateById(course);
|
||||
log.info("Course approved: id={}", id);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void rejectCourse(Long id, String comment) {
|
||||
Course course = getCourseById(id);
|
||||
course.setStatus("rejected");
|
||||
course.setReviewComment(comment);
|
||||
course.setReviewedAt(LocalDateTime.now());
|
||||
courseMapper.updateById(course);
|
||||
log.info("Course rejected: id={}", id);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user