master
小萌新 3 months ago
parent 896ba81d60
commit f2a53a6e33
  1. 1
      src/main/java/com/teaching/backend/model/dto/chapter/ChapterDTO.java
  2. 100
      src/main/java/com/teaching/backend/model/dto/chapter/ChapterExcelDTO.java
  3. 2
      src/main/java/com/teaching/backend/model/entity/chapter/TemporaryChapter.java
  4. 4
      src/main/java/com/teaching/backend/service/chapter/IChapterService.java
  5. 13
      src/main/java/com/teaching/backend/service/impl/chapter/ChapterServiceImpl.java
  6. 24
      src/main/java/com/teaching/backend/utils/Chapter/ExcelParser.java
  7. 145
      src/main/java/com/teaching/backend/utils/Chapter/SheetHandler.java
  8. 34
      src/main/java/com/teaching/backend/utils/Chapter/SheetPreScanner.java

@ -67,7 +67,6 @@ public class ChapterDTO implements Serializable {
@ApiModelProperty(value = "要求")
private String requirement;
@ApiModelProperty(value = "线上学时")
private String onlineClassHours;

@ -0,0 +1,100 @@
package com.teaching.backend.model.dto.chapter;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* ClassName: ChapterExcelDto
* Package: com.teaching.backend.model.dto.chapter
* Description:
*
* @Author 姜钧瀚
* @Create 2024/8/10 13:44
* @Version 1.0
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ChapterExcelDTO implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "创建人")
private String createBy;
@ApiModelProperty(value = "创建日期")
@JsonFormat(pattern = "yyyy/M/d HH:mm:ss")
private LocalDateTime createTime;
@ApiModelProperty(value = "更新人")
private String updateBy;
@ApiModelProperty(value = "更新日期")
@JsonFormat(pattern = "yyyy/M/d HH-mm-ss")
private LocalDateTime updateTime;
@ApiModelProperty(value = "所属部门")
private String sysOrgCode;
@ApiModelProperty(value = "序号")
private Double orderNum;
@ApiModelProperty(value = "章节名称")
private String name;
@ApiModelProperty(value = "简介")
private String content;
@ApiModelProperty(value = "父章节")
private Long pid;
@ApiModelProperty(value = "课程id")
private String courseId;
@ApiModelProperty(value = "课程目标")
private String courseObjectivesId;
@ApiModelProperty(value = "总学时")
private double totalClassHours;
@ApiModelProperty(value = "要求")
private String requirement;
@TableField(exist = false)
@ApiModelProperty(value = "是否是节")
private boolean isSection;
@TableField(exist = false)
@ApiModelProperty(value = "章内序号")
private Integer internalOrder;
@ApiModelProperty(value = "线上学时")
private String onlineClassHours;
@ApiModelProperty(value = "周次")
private String zc;
@ApiModelProperty(value = "内部序号显示")
private String numshow;
@ApiModelProperty(value = "excel上级序号")
@TableField(exist = false)
private Long ParentExcelId;
@ApiModelProperty(value = "excel序号")
@TableField(exist = false)
private Long ExcelId;
public void setIsSection(boolean b) {
this.isSection=b;
}
}

@ -69,7 +69,7 @@ public class TemporaryChapter implements Serializable {
private String courseObjectivesId;
@ApiModelProperty(value = "总学时")
private String totalClassHours;
private double totalClassHours;
@ApiModelProperty(value = "要求")
private String requirement;

@ -4,12 +4,12 @@ package com.teaching.backend.service.chapter;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.teaching.backend.model.dto.chapter.ChapterDTO;
import com.teaching.backend.model.dto.chapter.ChapterExcelDTO;
import com.teaching.backend.model.entity.chapter.Chapter;
import com.teaching.backend.model.vo.chapter.ChapterVo;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.LinkedList;
import java.util.List;
@ -54,7 +54,7 @@ public interface IChapterService extends IService<Chapter> {
void moveDataFromTemporaryToFinal();
Long saveToTemporaryTable(ChapterDTO chapterDTO);
Long saveToTemporaryTable(ChapterExcelDTO chapterDTO);
void downExcel(HttpServletResponse response) throws IOException;

@ -14,12 +14,12 @@ import com.teaching.backend.mapper.chapter.ChapterMapper;
import com.teaching.backend.mapper.chapter.TemporaryChapterMapper;
import com.teaching.backend.model.dto.chapter.ChapterDTO;
import com.teaching.backend.model.dto.chapter.ChapterExcelDTO;
import com.teaching.backend.model.entity.chapter.Chapter;
import com.teaching.backend.model.entity.chapter.TemporaryChapter;
import com.teaching.backend.model.entity.knowtmp.Knowtmp;
import com.teaching.backend.model.vo.chapter.ChapterVo;
import com.teaching.backend.service.Know.KnowService;
import com.teaching.backend.service.chapter.IChapterService;
import com.teaching.backend.utils.Chapter.ExcelUtils;
import org.springframework.beans.BeanUtils;
@ -29,7 +29,6 @@ import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
@ -517,7 +516,7 @@ public class ChapterServiceImpl extends ServiceImpl<ChapterMapper, Chapter> impl
@Transactional(rollbackFor = Exception.class)
@Override
public Long saveToTemporaryTable(ChapterDTO chapterDTO) {
public Long saveToTemporaryTable(ChapterExcelDTO chapterDTO) {
TemporaryChapter temporaryChapter = new TemporaryChapter();
try {
BeanUtils.copyProperties(chapterDTO, temporaryChapter);
@ -526,10 +525,13 @@ public class ChapterServiceImpl extends ServiceImpl<ChapterMapper, Chapter> impl
}
Long pid = temporaryChapter.getPid();
//pid=0的时候
if (pid == null || pid == 0) {
temporaryChapter.setPid(0L);
setChapterOrder(temporaryChapter, 0L);
} else {
}
//pid!=0的时候
else {
TemporaryChapter parentChapter = temporaryChapterMapper.selectById(pid);
if (parentChapter != null) {
temporaryChapter.setPid(parentChapter.getId());
@ -538,8 +540,9 @@ public class ChapterServiceImpl extends ServiceImpl<ChapterMapper, Chapter> impl
throw new BusinessException(ErrorCode.PARAMS_ERROR, "未找到父章节,ID 为: " + pid);
}
}
// 执行
temporaryChapterMapper.insert(temporaryChapter);
return temporaryChapter.getId();
}

@ -13,10 +13,13 @@ package com.teaching.backend.utils.Chapter;
import com.teaching.backend.mapper.chapter.TemporaryChapterMapper;
import com.teaching.backend.service.chapter.IChapterService;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.eventusermodel.XSSFSheetXMLHandler;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.apache.poi.xssf.model.StylesTable;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.xml.sax.InputSource;
@ -40,20 +43,35 @@ public class ExcelParser {
public List<String> parse(InputStream inputStream, String courseId) throws Exception {
OPCPackage pkg = OPCPackage.open(inputStream);
List<String> validationErrors = new ArrayList<>();
int totalRows = 0;
try {
XSSFReader reader = new XSSFReader(pkg);
SharedStringsTable sst = reader.getSharedStringsTable();
StylesTable styles = reader.getStylesTable();
XMLReader parser = XMLReaderFactory.createXMLReader();
SheetHandler sheetHandler = new SheetHandler(temporaryChapterMapper, chapterService, courseId);
parser.setContentHandler(new XSSFSheetXMLHandler(styles, sst, sheetHandler, false));
XSSFReader.SheetIterator sheets = (XSSFReader.SheetIterator) reader.getSheetsData();
SheetPreScanner preScanner = new SheetPreScanner();
while (sheets.hasNext()) {
InputStream sheetstream = sheets.next();
InputSource sheetSource = new InputSource(sheetstream);
try {
parser.setContentHandler(new XSSFSheetXMLHandler(styles, sst, preScanner, false));
parser.parse(sheetSource);
} finally {
sheetstream.close();
}
}
totalRows = preScanner.getRowCount();
sheets = (XSSFReader.SheetIterator) reader.getSheetsData();
SheetHandler sheetHandler = null;
while (sheets.hasNext()) {
InputStream sheetstream = sheets.next();
InputSource sheetSource = new InputSource(sheetstream);
try {
sheetHandler = new SheetHandler(temporaryChapterMapper, chapterService, courseId, totalRows);
parser.setContentHandler(new XSSFSheetXMLHandler(styles, sst, sheetHandler, false));
parser.parse(sheetSource);
} finally {
sheetstream.close();

@ -3,10 +3,17 @@ package com.teaching.backend.utils.Chapter;
import com.teaching.backend.common.ErrorCode;
import com.teaching.backend.exception.BusinessException;
import com.teaching.backend.mapper.chapter.TemporaryChapterMapper;
import com.teaching.backend.model.dto.chapter.ChapterDTO;
import com.teaching.backend.model.dto.chapter.ChapterExcelDTO;
import com.teaching.backend.service.chapter.IChapterService;
import jdk.nashorn.internal.ir.IfNode;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xssf.eventusermodel.XSSFSheetXMLHandler;
import org.apache.poi.xssf.usermodel.XSSFComment;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
@ -23,127 +30,139 @@ import java.util.*;
public class SheetHandler implements XSSFSheetXMLHandler.SheetContentsHandler {
private final TemporaryChapterMapper temporaryChapterMapper;
private Long currentChapterPid;
private final TemporaryChapterMapper temporaryChapterMapper;
private Double chapterHour;
private final IChapterService chapterService;
private final String courseId;
private ChapterDTO chapterDTO;
private ChapterExcelDTO chapterDTO;
private Map<Long, Long> excelIdToDatabaseIdMap = new HashMap<>();
private List<String> validationErrors = new ArrayList<>();
private boolean hasErrors = false;
private List<ChapterDTO> collectedChapters = new ArrayList<>();
private int totalRows;
public SheetHandler(TemporaryChapterMapper temporaryChapterMapper, IChapterService chapterService, String courseId) {
public SheetHandler(TemporaryChapterMapper temporaryChapterMapper, IChapterService chapterService, String courseId,int totalRows) {
this.temporaryChapterMapper = temporaryChapterMapper;
this.chapterService = chapterService;
this.courseId = courseId;
this.totalRows=totalRows;
}
@Override
public void startRow(int rowIndex) {
if (rowIndex == 0) {
chapterDTO = null;
if (rowIndex < totalRows - 1) {
if (rowIndex == 0 || rowIndex == 1) {
chapterDTO = null;
} else {
chapterDTO = new ChapterExcelDTO();
chapterDTO.setCourseId(courseId);
}
} else {
chapterDTO = new ChapterDTO();
chapterDTO.setCourseId(courseId);
chapterDTO = null;
}
}
@Override
public void endRow(int rowIndex) {
if (rowIndex != 0 && chapterDTO != null) {
List<String> errors = validateChapter(chapterDTO);
if (!errors.isEmpty()) {
validationErrors.addAll(errors);
hasErrors = true;
return;
}
collectedChapters.add(chapterDTO);
}
}
@Transactional(rollbackFor = Exception.class)
@Transactional(rollbackFor = Exception.class)
public List<String> finalizeProcess() {
if (hasErrors) {
return validationErrors;
}
for (ChapterDTO chapter : collectedChapters) {
if (chapter.getParentExcelId() == null || chapter.getParentExcelId() == 0) {
saveToTemporaryTable(chapter);
}
}
for (ChapterDTO chapter : collectedChapters) {
if (chapter.getParentExcelId() != null && chapter.getParentExcelId() != 0) {
saveToTemporaryTable(chapter);
}
}
chapterService.moveDataFromTemporaryToFinal();
return Collections.emptyList();
}
private void saveToTemporaryTable(ChapterDTO chapterDTO) {
private void saveToTemporaryTable(ChapterExcelDTO chapterDTO) {
Long pid = chapterDTO.getParentExcelId();
if (pid != null && pid != 0) {
Long parentId = excelIdToDatabaseIdMap.get(pid);
if (parentId != null) {
chapterDTO.setPid(parentId);
} else {
temporaryChapterMapper.deleteAll();
throw new BusinessException(ErrorCode.PARAMS_ERROR, "未找到父章节,Excel ID 为: " + pid);
}
}
Long savedChapterId = chapterService.saveToTemporaryTable(chapterDTO);
excelIdToDatabaseIdMap.put(chapterDTO.getExcelId(), savedChapterId);
}
}
private List<String> validateChapter(ChapterExcelDTO chapterDTO) {
List<String> errors = new ArrayList<>();
return errors;
}
@Override
public void endRow(int rowIndex) {
if (rowIndex != 0 && chapterDTO != null) {
List<String> errors = validateChapter(chapterDTO);
if (!errors.isEmpty()) {
validationErrors.addAll(errors);
hasErrors = true;
return;
}
private List<String> validateChapter(ChapterDTO chapterDTO) {
List<String> errors = new ArrayList<>();
if (chapterDTO.getName() == null || chapterDTO.getName().isEmpty()) {
errors.add("编号:"+chapterDTO.getExcelId()+"的章节名字不能为空");
if (chapterDTO.isSection()) {
if (currentChapterPid != null) {
chapterDTO.setTotalClassHours(chapterHour);
chapterDTO.setPid(currentChapterPid);
saveToTemporaryTable(chapterDTO);
} else {
throw new BusinessException(ErrorCode.PARAMS_ERROR, "未找到父章节,Excel ID 为: " + chapterDTO.getExcelId());
}
}
}
if (chapterDTO.getExcelId() == null || chapterDTO.getExcelId() <= 0) {
errors.add("编号不能小于0");
}
if (chapterDTO.getParentExcelId() == null || chapterDTO.getParentExcelId() < 0) {
errors.add("编号:"+chapterDTO.getExcelId()+"的上级编号不能小于0");
}
if (chapterDTO.getParentExcelId().equals(chapterDTO.getExcelId())) {
errors.add("编号:"+chapterDTO.getExcelId()+"的 上级编号不能等于其自身");
}
return errors;
}
@Override
public void cell(String cellReference, String formattedValue, XSSFComment comment) {
if (chapterDTO != null && formattedValue != null) {
if (chapterDTO != null) {
String letter = cellReference.substring(0, 1);
switch (letter) {
case "A":
chapterDTO.setExcelId(Long.valueOf(formattedValue));
break;
case "B":
chapterDTO.setName(formattedValue);
break;
case "C":
chapterDTO.setParentExcelId(Long.valueOf(formattedValue));
if (!chapterDTO.isSection()) {
chapterDTO.setTotalClassHours(Double.parseDouble(formattedValue));
saveToTemporaryTable(chapterDTO);
currentChapterPid = excelIdToDatabaseIdMap.get(chapterDTO.getExcelId());
}
break;
case "D":
chapterDTO.setOrderNum(Double.valueOf(formattedValue));
break;
case "E":
if (!formattedValue.isEmpty()) {
chapterDTO.setName(formattedValue);
chapterDTO.setIsSection(true);
}
break;
case "F":
if (chapterDTO.isSection()) {
chapterDTO.setTotalClassHours(Double.parseDouble(formattedValue));
chapterHour = chapterDTO.getTotalClassHours();
}
break;
}
}
}
}

@ -0,0 +1,34 @@
package com.teaching.backend.utils.Chapter;
import org.apache.poi.xssf.eventusermodel.XSSFSheetXMLHandler;
import org.apache.poi.xssf.usermodel.XSSFComment;
/**
* ClassName: Sheet
* Package: com.teaching.backend.utils.Chapter
* Description:
*
* @Author 姜钧瀚
* @Create 2024/8/11 18:04
* @Version 1.0
*/
public class SheetPreScanner implements XSSFSheetXMLHandler.SheetContentsHandler {
private int rowCount = 0;
@Override
public void startRow(int rowNum) {
rowCount++;
}
@Override
public void endRow(int rowNum) {
}
@Override
public void cell(String cellReference, String formattedValue, XSSFComment comment) {
}
public int getRowCount() {
return rowCount;
}
}
Loading…
Cancel
Save