课程与附件关联

This commit is contained in:
wsw 2023-07-29 09:28:28 +08:00
parent cd475f080e
commit b9623983c7
10 changed files with 318 additions and 22 deletions

View File

@ -0,0 +1,150 @@
/*
* Copyright (C) 2023 杭州白书科技有限公司
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package xyz.playedu.api.controller.backend;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import xyz.playedu.api.constant.BPermissionConstant;
import xyz.playedu.api.constant.BackendConstant;
import xyz.playedu.api.domain.CourseAttachment;
import xyz.playedu.api.exception.NotFoundException;
import xyz.playedu.api.middleware.BackendPermissionMiddleware;
import xyz.playedu.api.request.backend.CourseAttachmentMultiRequest;
import xyz.playedu.api.request.backend.CourseAttachmentRequest;
import xyz.playedu.api.request.backend.CourseAttachmentSortRequest;
import xyz.playedu.api.service.CourseAttachmentService;
import xyz.playedu.api.types.JsonResponse;
import java.util.*;
@RestController
@Slf4j
@RequestMapping("/backend/v1/course/{courseId}/attachment")
public class CourseAttachmentController {
@Autowired private CourseAttachmentService attachmentService;
@BackendPermissionMiddleware(slug = BPermissionConstant.COURSE)
@PostMapping("/create")
public JsonResponse store(
@PathVariable(name = "courseId") Integer courseId,
@RequestBody @Validated CourseAttachmentRequest req)
throws NotFoundException {
// 附件类型校验
String type = req.getType();
if (!BackendConstant.RESOURCE_TYPE_ATTACHMENT.contains(type)) {
return JsonResponse.error("附件类型不支持");
}
// 课时重复添加校验
List<Integer> existsRids = attachmentService.getRidsByCourseId(courseId);
if (existsRids != null) {
if (existsRids.contains(req.getRid())) {
return JsonResponse.error("附件已存在");
}
}
CourseAttachment courseAttachment =
attachmentService.create(
courseId,
req.getSort(),
req.getTitle(),
type,
req.getRid());
return JsonResponse.success();
}
@BackendPermissionMiddleware(slug = BPermissionConstant.COURSE)
@PostMapping("/create-batch")
@Transactional
public JsonResponse storeMulti(
@PathVariable(name = "courseId") Integer courseId,
@RequestBody @Validated CourseAttachmentMultiRequest req) {
if (req.getAttachments().size() == 0) {
return JsonResponse.error("参数为空");
}
List<Integer> existsRids = attachmentService.getRidsByCourseId(courseId);
List<CourseAttachment> attachments = new ArrayList<>();
Date now = new Date();
for (CourseAttachmentMultiRequest.AttachmentItem item : req.getAttachments()) {
if (existsRids.contains(item.getRid())) {
return JsonResponse.error("附件《" + item.getTitle() + "》已存在");
}
attachments.add(
new CourseAttachment() {
{
setCourseId(courseId);
setSort(item.getSort());
setType(item.getType());
setRid(item.getRid());
setTitle(item.getTitle());
setCreatedAt(now);
}
});
}
attachmentService.saveBatch(attachments);
return JsonResponse.success();
}
@BackendPermissionMiddleware(slug = BPermissionConstant.COURSE)
@GetMapping("/{id}")
public JsonResponse edit(
@PathVariable(name = "courseId") Integer courseId,
@PathVariable(name = "id") Integer id)
throws NotFoundException {
CourseAttachment courseAttachment = attachmentService.findOrFail(id, courseId);
return JsonResponse.data(courseAttachment);
}
@BackendPermissionMiddleware(slug = BPermissionConstant.COURSE)
@PutMapping("/{id}")
public JsonResponse update(
@PathVariable(name = "courseId") Integer courseId,
@PathVariable(name = "id") Integer id,
@RequestBody @Validated CourseAttachmentRequest req)
throws NotFoundException {
CourseAttachment courseAttachment = attachmentService.findOrFail(id, courseId);
attachmentService.update(courseAttachment, req.getSort(), req.getTitle());
return JsonResponse.success();
}
@BackendPermissionMiddleware(slug = BPermissionConstant.COURSE)
@DeleteMapping("/{id}")
public JsonResponse destroy(
@PathVariable(name = "courseId") Integer courseId,
@PathVariable(name = "id") Integer id)
throws NotFoundException {
CourseAttachment courseAttachment = attachmentService.findOrFail(id, courseId);
attachmentService.removeById(courseAttachment.getId());
return JsonResponse.success();
}
@PutMapping("/update/sort")
public JsonResponse updateSort(
@PathVariable(name = "courseId") Integer courseId,
@RequestBody @Validated CourseAttachmentSortRequest req) {
attachmentService.updateSort(req.getIds(), courseId);
return JsonResponse.success();
}
}

View File

@ -26,7 +26,6 @@ import org.springframework.web.bind.annotation.*;
import xyz.playedu.api.BCtx;
import xyz.playedu.api.constant.BPermissionConstant;
import xyz.playedu.api.constant.BackendConstant;
import xyz.playedu.api.domain.*;
import xyz.playedu.api.event.CourseDestroyEvent;
import xyz.playedu.api.exception.NotFoundException;
@ -54,6 +53,10 @@ public class CourseController {
@Autowired private CourseHourService hourService;
@Autowired private CourseAttachmentService attachmentService;
@Autowired private ResourceService resourceService;
@Autowired private DepartmentService departmentService;
@Autowired private ApplicationContext ctx;
@ -192,6 +195,28 @@ public class CourseController {
courseService.updateClassHour(course.getId(), classHourCount);
}
// 课程附件
if (req.getAttachments().size() > 0) {
List<CourseAttachment> insertAttachments = new ArrayList<>();
final Integer[] sort = {0};
for (CourseRequest.AttachmentItem attachmentItem : req.getAttachments()) {
insertAttachments.add(
new CourseAttachment() {
{
setCourseId(course.getId());
setSort(sort[0]++);
setTitle(attachmentItem.getName());
setType(attachmentItem.getType());
setRid(attachmentItem.getRid());
setCreatedAt(now);
}
});
}
if (insertAttachments.size() > 0) {
attachmentService.saveBatch(insertAttachments);
}
}
return JsonResponse.success();
}
@ -203,28 +228,20 @@ public class CourseController {
List<Integer> categoryIds = courseService.getCategoryIdsByCourseId(course.getId());
List<CourseChapter> chapters = chapterService.getChaptersByCourseId(course.getId());
List<CourseHour> hours = hourService.getHoursByCourseId(course.getId());
List<CourseAttachment> attachments = attachmentService.getAttachmentsByCourseId(course.getId());
Map<Integer,String> resourceMap = resourceService.chunks(attachments.stream().map(CourseAttachment::getRid).toList())
.stream().collect(Collectors.toMap(Resource::getId, Resource::getUrl));
attachments.forEach(courseAttachment -> {
courseAttachment.setUrl(resourceMap.get(courseAttachment.getRid()));
});
HashMap<String, Object> data = new HashMap<>();
data.put("course", course);
data.put("dep_ids", depIds); // 已关联的部门
data.put("category_ids", categoryIds); // 已关联的分类
data.put("chapters", chapters);
data.put(
"hours",
hours.stream()
.filter(
courseHour ->
BackendConstant.RESOURCE_TYPE_VIDEO.equals(
courseHour.getType()))
.collect(Collectors.groupingBy(CourseHour::getChapterId)));
data.put(
"attachments",
hours.stream()
.filter(
courseHour ->
BackendConstant.RESOURCE_TYPE_ATTACHMENT.contains(
courseHour.getType()))
.collect(Collectors.groupingBy(CourseHour::getChapterId)));
data.put("hours", hours.stream().collect(Collectors.groupingBy(CourseHour::getChapterId)));
data.put("attachments", attachments);
return JsonResponse.data(data);
}

View File

@ -52,6 +52,9 @@ public class CourseAttachment implements Serializable {
/** 资源id */
private Integer rid;
/** 资源url */
private String url;
/** */
@JsonIgnore private Date createdAt;
@ -86,6 +89,9 @@ public class CourseAttachment implements Serializable {
&& (this.getRid() == null
? other.getRid() == null
: this.getRid().equals(other.getRid()))
&& (this.getUrl() == null
? other.getUrl() == null
: this.getUrl().equals(other.getUrl()))
&& (this.getCreatedAt() == null
? other.getCreatedAt() == null
: this.getCreatedAt().equals(other.getCreatedAt()));
@ -101,6 +107,7 @@ public class CourseAttachment implements Serializable {
result = prime * result + ((getTitle() == null) ? 0 : getTitle().hashCode());
result = prime * result + ((getType() == null) ? 0 : getType().hashCode());
result = prime * result + ((getRid() == null) ? 0 : getRid().hashCode());
result = prime * result + ((getUrl() == null) ? 0 : getUrl().hashCode());
result = prime * result + ((getCreatedAt() == null) ? 0 : getCreatedAt().hashCode());
return result;
}
@ -117,6 +124,7 @@ public class CourseAttachment implements Serializable {
sb.append(", title=").append(title);
sb.append(", type=").append(type);
sb.append(", rid=").append(rid);
sb.append(", url=").append(url);
sb.append(", createdAt=").append(createdAt);
sb.append(", serialVersionUID=").append(serialVersionUID);
sb.append("]");

View File

@ -20,6 +20,7 @@ import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import xyz.playedu.api.event.CourseDestroyEvent;
import xyz.playedu.api.service.CourseAttachmentService;
import xyz.playedu.api.service.CourseDepartmentService;
import xyz.playedu.api.service.UserCourseHourRecordService;
import xyz.playedu.api.service.UserCourseRecordService;
@ -41,6 +42,8 @@ public class CourseDestroyListener {
@Autowired private UserCourseHourRecordService userCourseHourRecordService;
@Autowired private CourseAttachmentService courseAttachmentService;
@EventListener
public void departmentRelateRemove(CourseDestroyEvent event) {
courseDepartmentService.removeByCourseId(event.getCourseId());
@ -51,6 +54,11 @@ public class CourseDestroyListener {
courseCategoryService.removeByCourseId(event.getCourseId());
}
@EventListener
public void attachmentRelateRemove(CourseDestroyEvent event) {
courseAttachmentService.remove(event.getCourseId());
}
@EventListener
public void removeUserRecords(CourseDestroyEvent event) {
userCourseRecordService.removeByCourseId(event.getCourseId());

View File

@ -0,0 +1,35 @@
/*
* Copyright (C) 2023 杭州白书科技有限公司
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package xyz.playedu.api.request.backend;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.util.List;
@Data
public class CourseAttachmentMultiRequest {
@Data
public static class AttachmentItem {
private String title;
private Integer sort;
private String type;
private Integer rid;
}
@NotNull(message = "attachments参数不存在")
private List<AttachmentItem> attachments;
}

View File

@ -0,0 +1,36 @@
/*
* Copyright (C) 2023 杭州白书科技有限公司
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package xyz.playedu.api.request.backend;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Data
public class CourseAttachmentRequest {
@NotBlank(message = "请输入附件名称")
private String title;
@NotNull(message = "sort参数不存在")
private Integer sort;
@NotBlank(message = "请选择附件类型")
private String type;
@NotNull(message = "rid参数不存在")
private Integer rid;
}

View File

@ -0,0 +1,25 @@
/*
* Copyright (C) 2023 杭州白书科技有限公司
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package xyz.playedu.api.request.backend;
import lombok.Data;
import java.util.List;
@Data
public class CourseAttachmentSortRequest {
private List<Integer> ids;
}

View File

@ -72,6 +72,13 @@ public class CourseRequest {
private List<HourItem> hours;
}
@Data
public static class AttachmentItem {
private String name;
private String type;
private Integer rid;
}
// 格式
// [
// {
@ -100,4 +107,14 @@ public class CourseRequest {
// ]
@NotNull(message = "hours参数不存在")
private List<HourItem> hours;
// 格式
// [
// {
// 'name' => '附件名',
// 'type' => '附件类型',
// 'rid' => '资源id',
// }...
// ]
private List<AttachmentItem> attachments;
}

View File

@ -27,7 +27,7 @@ public interface CourseAttachmentService extends IService<CourseAttachment> {
void update(CourseAttachment courseAttachment, Integer sort, String title);
List<CourseAttachment> getAttachmentByCourseId(Integer courseId);
List<CourseAttachment> getAttachmentsByCourseId(Integer courseId);
CourseAttachment create(
Integer courseId,
@ -42,7 +42,7 @@ public interface CourseAttachmentService extends IService<CourseAttachment> {
void updateSort(List<Integer> ids, Integer cid);
List<Integer> getRidsByCourseId(Integer courseId, String type);
List<Integer> getRidsByCourseId(Integer courseId);
List<CourseAttachment> chunk(List<Integer> attachmentIds);
}

View File

@ -53,7 +53,7 @@ public class CourseAttachmentServiceImpl extends ServiceImpl<CourseAttachmentMap
}
@Override
public List<CourseAttachment> getAttachmentByCourseId(Integer courseId) {
public List<CourseAttachment> getAttachmentsByCourseId(Integer courseId) {
return list(query().getWrapper().eq("course_id", courseId).orderByAsc("sort"));
}
@ -108,8 +108,8 @@ public class CourseAttachmentServiceImpl extends ServiceImpl<CourseAttachmentMap
}
@Override
public List<Integer> getRidsByCourseId(Integer courseId, String type) {
return list(query().getWrapper().eq("course_id", courseId).eq("type", type)).stream()
public List<Integer> getRidsByCourseId(Integer courseId) {
return list(query().getWrapper().eq("course_id", courseId)).stream()
.map(CourseAttachment::getRid)
.toList();
}