diff --git a/admin-core/src/main/java/com/ibeetl/admin/core/service/CoreBaseAnnotationParser.java b/admin-core/src/main/java/com/ibeetl/admin/core/service/CoreBaseAnnotationParser.java index 091560cf..05ffb36f 100644 --- a/admin-core/src/main/java/com/ibeetl/admin/core/service/CoreBaseAnnotationParser.java +++ b/admin-core/src/main/java/com/ibeetl/admin/core/service/CoreBaseAnnotationParser.java @@ -18,6 +18,7 @@ import org.springframework.beans.factory.annotation.Autowired; import java.lang.reflect.Field; import java.lang.reflect.Method; +import java.util.Arrays; import java.util.List; /** @@ -76,7 +77,7 @@ public class CoreBaseAnnotationParser { TailBean ext = (TailBean) bean; Class c = ext.getClass(); do { - Field[] fields = c.getDeclaredFields(); + List fields = Arrays.asList(c.getDeclaredFields()); for (Field field : fields) { if (field.isAnnotationPresent(Dict.class)) { field.setAccessible(true); @@ -89,7 +90,16 @@ public class CoreBaseAnnotationParser { CoreDict dbDict = dict.type().contains(".") ? dictUtil.findCoreDictByTable(dict.type(), fieldValue.toString()) : dictUtil.findCoreDict(dict.type(), fieldValue.toString()); display = dbDict != null ? dbDict.getName() : null; } - ext.set(field.getName() + dict.suffix(), display); + + // 是否声明属性,则直接复制给声明的遍历 + String fullFieldName = field.getName() + dict.suffix(); + boolean isHaveProperties = fields.stream().anyMatch(item -> item.getName().equals(fullFieldName)); + if (isHaveProperties) { + ReflectUtil.setFieldValue(ext, fullFieldName, display); + } + else { + ext.set(fullFieldName, display); + } } catch (Exception e) { e.printStackTrace(); } finally { @@ -122,8 +132,15 @@ public class CoreBaseAnnotationParser { ReadJSON readJSON = field.getAnnotation(ReadJSON.class); try { Object o = field.get(ext); + // 是否声明属性,则直接复制给声明的遍历 + String fullFieldName = field.getName() + readJSON.suffix(); + boolean isHaveProperties = fields.stream().anyMatch(item -> item.getName().equals(fullFieldName)); if(null != o) { - ext.set(field.getName() + readJSON.suffix(), JSONUtil.parse(o)); + if (isHaveProperties) { + ReflectUtil.setFieldValue(ext, fullFieldName, JSONUtil.parse(o)); + }else { + ext.set(fullFieldName, JSONUtil.parse(o)); + } } } catch (Exception e) { e.printStackTrace(); @@ -148,7 +165,17 @@ public class CoreBaseAnnotationParser { if (ObjectUtil.isNotEmpty(enumValue)) { display = String.valueOf(enumValue); } - ext.set(field.getName() + dict.suffix(), display); + + // 是否声明属性,则直接复制给声明的遍历 + String fullFieldName = field.getName() + dict.suffix(); + boolean isHaveProperties = fields.stream().anyMatch(item -> item.getName().equals(fullFieldName)); + if(null != o) { + if (isHaveProperties) { + ReflectUtil.setFieldValue(ext, fullFieldName, display); + }else { + ext.set(fullFieldName, display); + } + } } } catch (IllegalArgumentException | IllegalAccessException e) { log.error("@DictEnum 注解解析异常: {}", e.getMessage()); diff --git a/web/src/main/java/cn/jlw/util/excel/DeviceExcelSelectorServiceImpl.java b/web/src/main/java/cn/jlw/util/excel/DeviceExcelSelectorServiceImpl.java new file mode 100644 index 00000000..f1e5060d --- /dev/null +++ b/web/src/main/java/cn/jlw/util/excel/DeviceExcelSelectorServiceImpl.java @@ -0,0 +1,30 @@ +package cn.jlw.util.excel; + +import cn.hutool.core.collection.CollUtil; +import cn.jlw.util.SpringContextUtil; +import com.ibeetl.admin.core.entity.CoreDict; +import com.ibeetl.admin.core.service.CoreDictService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Slf4j +@Service +public class DeviceExcelSelectorServiceImpl implements ExcelSelectorService { + + @Override + public String[] getSelectorData() { + return null; + } + + @Override + public String[] getSelectorData(String dictKeyValue) { + CoreDictService coreDictService = (CoreDictService) SpringContextUtil.getBean(CoreDictService.class); + List list = coreDictService.findAllByTable(dictKeyValue); + if (CollUtil.isEmpty(list)) { + return null; + } + return list.stream().map(CoreDict::getName).toArray(String[]::new); + } +} diff --git a/web/src/main/java/cn/jlw/util/excel/EasyExcelTypeEnum.java b/web/src/main/java/cn/jlw/util/excel/EasyExcelTypeEnum.java new file mode 100644 index 00000000..05f02974 --- /dev/null +++ b/web/src/main/java/cn/jlw/util/excel/EasyExcelTypeEnum.java @@ -0,0 +1,29 @@ +package cn.jlw.util.excel; + +import cn.hutool.core.util.EnumUtil; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + *

+ * excel的文件格式 + *

+ * + * @author mlx + * @date 2022/11/26 + * @modified + */ +@Getter +@AllArgsConstructor +public enum EasyExcelTypeEnum { + + CSV(".csv"), + XLS(".xls"), + XLSX(".xlsx"); + + private String fileExtName; + + public static EasyExcelTypeEnum parseType(String fileExtName) { + return EnumUtil.likeValueOf(EasyExcelTypeEnum.class, fileExtName); + } +} diff --git a/web/src/main/java/cn/jlw/util/excel/ExcelCellDataListener.java b/web/src/main/java/cn/jlw/util/excel/ExcelCellDataListener.java new file mode 100644 index 00000000..4e124f9c --- /dev/null +++ b/web/src/main/java/cn/jlw/util/excel/ExcelCellDataListener.java @@ -0,0 +1,79 @@ +package cn.jlw.util.excel; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.ReflectUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.exception.ExcelDataConvertException; +import com.alibaba.excel.read.listener.ReadListener; +import com.alibaba.excel.read.metadata.holder.ReadRowHolder; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +@Data +@Slf4j +public class ExcelCellDataListener implements ReadListener { + + /** + * 数据集合 + */ + private List data = CollUtil.newArrayList(); + + private Map failMap = MapUtil.newHashMap(16); + + @Override + public void invoke(T bean, AnalysisContext context) { + boolean emptyRow = true; + List fieldList = Arrays.asList(ReflectUtil.getFields(bean.getClass())); + for (Field field : fieldList) { + field.setAccessible(true); + try { + Object fieldValue = field.get(bean); + if (fieldValue instanceof String) { + if (StrUtil.isNotBlank((String) fieldValue)) { + emptyRow = false; + break; + } + } + if (ObjectUtil.isNotNull(fieldValue)) { + emptyRow = false; + break; + } + } catch (IllegalAccessException e) { + log.error(e.getMessage(), e); + } + } + if (!emptyRow) { + // 不处理空数据行 + data.add(bean); + ReadRowHolder readRowHolder = context.readRowHolder(); + log.info("rowIndex: {}, rowType: {}", readRowHolder.getRowIndex(), readRowHolder.getRowType()); + } + } + + @Override + public void onException(Exception exception, AnalysisContext context) { + log.error(exception.getMessage(), exception); + if (exception instanceof ExcelDataConvertException) { + ExcelDataConvertException e = (ExcelDataConvertException) exception; + ExcelFailRecord excelFailRecord = new ExcelFailRecord(); + excelFailRecord.setRow(e.getRowIndex()); + excelFailRecord.setColumn(e.getColumnIndex()); + excelFailRecord.setFailMessage(e.getCause().getMessage()); + + failMap.put(e.getRowIndex(), excelFailRecord); + } + } + + @Override + public void doAfterAllAnalysed(AnalysisContext analysisContext) { + log.info("Excel Deal Finish"); + } +} diff --git a/web/src/main/java/cn/jlw/util/excel/ExcelFailRecord.java b/web/src/main/java/cn/jlw/util/excel/ExcelFailRecord.java new file mode 100644 index 00000000..d3487d07 --- /dev/null +++ b/web/src/main/java/cn/jlw/util/excel/ExcelFailRecord.java @@ -0,0 +1,21 @@ +package cn.jlw.util.excel; + +import lombok.Data; + +/** + *

+ * excel导入的错误信息记录 + *

+ * + * @author mlx + * @date 2022/11/26 + * @modified + */ +@Data +public class ExcelFailRecord { + + private Integer row; + private Integer column; + private String failMessage; + +} diff --git a/web/src/main/java/cn/jlw/util/excel/ExcelSelector.java b/web/src/main/java/cn/jlw/util/excel/ExcelSelector.java new file mode 100644 index 00000000..237e99b7 --- /dev/null +++ b/web/src/main/java/cn/jlw/util/excel/ExcelSelector.java @@ -0,0 +1,19 @@ +package cn.jlw.util.excel; + +public @interface ExcelSelector { + + /** + * 固定数据 + */ + String[] fixedSelector() default {}; + + /** + * 字典key + */ + String dictKeyValue() default ""; + + /** + * 服务类 + */ + Class[] serviceClass() default {}; +} diff --git a/web/src/main/java/cn/jlw/util/excel/ExcelSelectorDataWriteHandler.java b/web/src/main/java/cn/jlw/util/excel/ExcelSelectorDataWriteHandler.java new file mode 100644 index 00000000..9ed8b53b --- /dev/null +++ b/web/src/main/java/cn/jlw/util/excel/ExcelSelectorDataWriteHandler.java @@ -0,0 +1,41 @@ +package cn.jlw.util.excel; + +import cn.hutool.core.collection.CollUtil; +import com.alibaba.excel.write.handler.SheetWriteHandler; +import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; +import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; +import lombok.Data; +import org.apache.poi.ss.usermodel.DataValidation; +import org.apache.poi.ss.usermodel.DataValidationConstraint; +import org.apache.poi.ss.usermodel.DataValidationHelper; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.util.CellRangeAddressList; + +import java.util.Map; + +@Data +public class ExcelSelectorDataWriteHandler implements SheetWriteHandler { + + private final Map selectedMap; + + @Override + public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { + Sheet sheet = writeSheetHolder.getSheet(); + DataValidationHelper helper = sheet.getDataValidationHelper(); + if (CollUtil.isEmpty(selectedMap)) { + return; + } + selectedMap.forEach((k, v) -> { + // 下拉 首行 末行 首列 末列 + CellRangeAddressList list = new CellRangeAddressList(v.getStartRow(), v.getEndRow(), k, k); + // 下拉值 + DataValidationConstraint constraint = helper.createExplicitListConstraint(v.getSelectorData()); + DataValidation validation = helper.createValidation(constraint, list); + validation.setErrorStyle(DataValidation.ErrorStyle.STOP); + validation.setShowErrorBox(true); + validation.setSuppressDropDownArrow(true); + validation.createErrorBox("提示", "请输入下拉选项中的内容"); + sheet.addValidationData(validation); + }); + } +} diff --git a/web/src/main/java/cn/jlw/util/excel/ExcelSelectorResolve.java b/web/src/main/java/cn/jlw/util/excel/ExcelSelectorResolve.java new file mode 100644 index 00000000..2b4eb98f --- /dev/null +++ b/web/src/main/java/cn/jlw/util/excel/ExcelSelectorResolve.java @@ -0,0 +1,63 @@ +package cn.jlw.util.excel; + +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.StrUtil; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +/** + * Excel选择器解析 + * @author lx + */ +@Data +@Slf4j +public class ExcelSelectorResolve { + + /** + * 下拉选起始行 + */ + private int startRow = 0; + + /** + * 下拉选结束行 + */ + private int endRow = 500; + + /** + * 下拉数据集 + */ + private String[] selectorData; + + /** + * 解决Excel注解的下拉选数据获取 + * + * @param excelSelector Excel下拉选 + * @return java.lang.String[] + * @author mlx + */ + public String[] resolveExcelSelector(ExcelSelector excelSelector) { + if (excelSelector == null) { + return null; + } + + String[] fixedSelector = excelSelector.fixedSelector(); + if (ArrayUtil.isNotEmpty(fixedSelector)) { + return fixedSelector; + } + String[] selectorData = null; + Class[] serviceClass = excelSelector.serviceClass(); + if (ArrayUtil.isNotEmpty(serviceClass)) { + try { + ExcelSelectorService excelSelectorService = serviceClass[0].newInstance(); + if (StrUtil.isBlank(excelSelector.dictKeyValue())) { + selectorData = excelSelectorService.getSelectorData(); + } else { + selectorData = excelSelectorService.getSelectorData(excelSelector.dictKeyValue()); + } + } catch (InstantiationException | IllegalAccessException e) { + log.error(e.getMessage(), e); + } + } + return selectorData; + } +} diff --git a/web/src/main/java/cn/jlw/util/excel/ExcelSelectorService.java b/web/src/main/java/cn/jlw/util/excel/ExcelSelectorService.java new file mode 100644 index 00000000..665e0b69 --- /dev/null +++ b/web/src/main/java/cn/jlw/util/excel/ExcelSelectorService.java @@ -0,0 +1,21 @@ +package cn.jlw.util.excel; + +public interface ExcelSelectorService { + + /** + * 获取下拉数据 + * + * @return java.lang.String[] + * @author mlx + */ + String[] getSelectorData(); + + /** + * 根据字典key获取下拉数据 + * + * @param dictKeyValue 字典key + * @return java.lang.String[] + * @author mlx + */ + String[] getSelectorData(String dictKeyValue); +} diff --git a/web/src/main/java/cn/jlw/util/excel/ExcelUtil.java b/web/src/main/java/cn/jlw/util/excel/ExcelUtil.java new file mode 100644 index 00000000..56a396d4 --- /dev/null +++ b/web/src/main/java/cn/jlw/util/excel/ExcelUtil.java @@ -0,0 +1,282 @@ +package cn.jlw.util.excel; + +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelReader; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.read.listener.ReadListener; +import com.alibaba.excel.read.metadata.ReadSheet; +import com.alibaba.excel.support.ExcelTypeEnum; +import com.alibaba.excel.write.metadata.style.WriteCellStyle; +import com.alibaba.excel.write.style.HorizontalCellStyleStrategy; +import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy; +import com.ibeetl.admin.core.util.FreezeAndFilter; +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.ss.usermodel.HorizontalAlignment; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.reflect.Field; +import java.net.URLEncoder; +import java.util.List; +import java.util.Map; + +@Slf4j +public class ExcelUtil { + + /** + * 默认的sheet名称 + */ + private static final String DEFAULT_SHEET_NAME = "Sheet1"; + + /** + * 写Excel数据 + * + * @param response response + * @param fileName 文件名称 + * @param data 数据 + * @param clazz 类class + * @author mlx + */ + public static void writeExcel(HttpServletResponse response, String fileName, List data, Class clazz) { + writeExcel(response, fileName, DEFAULT_SHEET_NAME, data, clazz); + } + + /** + * 写Excel数据 + * + * @param response response + * @param fileName 文件名称 + * @param sheetName sheet名称 + * @param data 数据 + * @param clazz 类class + * @author mlx + */ + public static void writeExcel(HttpServletResponse response, String fileName, String sheetName, List data, Class clazz) { + OutputStream outputStream = null; + Map selectedMap = getSelectedMap(clazz); + ExcelSelectorDataWriteHandler writeHandler = new ExcelSelectorDataWriteHandler(selectedMap); + try { + outputStream = getOutputStream(response, fileName, ExcelTypeEnum.XLSX); + EasyExcel.write(outputStream, clazz).excelType(ExcelTypeEnum.XLSX).sheet(sheetName) + .registerWriteHandler(writeHandler) + .registerWriteHandler(new FreezeAndFilter()) + .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 基于 column 长度,自动适配。最大 255 宽度 + .doWrite(data); + } catch (Exception e) { + log.error(e.getMessage(), e); + } finally { + if (outputStream != null) { + try { + outputStream.close(); + } catch (IOException e) { + log.error(e.getMessage(), e); + } + } + } + } + + /** + * 读取不包含头信息的Excel + * + * @param file 文件 + * @param clazz 类class + * @author mlx + */ + public static List readExcelNotContainHeader(MultipartFile file, Class clazz) throws IOException { + return readExcel(1, file, clazz); + } + + /** + * 读取包含头信息的Excel + * + * @param file 文件 + * @param clazz 类class + * @author mlx + */ + public static List readExcelContainHeader(MultipartFile file, Class clazz) throws IOException { + return readExcel(0, file, clazz); + } + + /** + * 读取Excel + * + * @param rowNum 行数 + * @param file 文件 + * @param clazz 类class + * @author mlx + */ + public static List readExcel(int rowNum, MultipartFile file, Class clazz) throws IOException { + String fileName = file.getOriginalFilename(); + InputStream inputStream = file.getInputStream(); + return readExcel(rowNum, fileName, inputStream, clazz); + } + + /** + * 读取不包含头信息的Excel + * + * @param fileName 文件名称 + * @param inputStream 流 + * @param clazz 类 + * @author mlx + */ + public static List readExcelNotContainHeader(String fileName, InputStream inputStream, Class clazz) { + return readExcel(1, fileName, inputStream, clazz); + } + + /** + * 读取包含头信息的Excel + * + * @param fileName 文件名称 + * @param inputStream 流 + * @param clazz 类 + * @param listener 监听 + * @author mlx + */ + public static List readExcelContainHeader(String fileName, InputStream inputStream, Class clazz, ExcelCellDataListener listener) { + return readExcel(0, fileName, inputStream, clazz); + } + + /** + * 读取Excel + * + * @param rowNum 行数 + * @param fileName 文件名称 + * @param inputStream 流 + * @param clazz 类 + * @author mlx + */ + public static List readExcel(int rowNum, String fileName, InputStream inputStream, Class clazz) { + ExcelCellDataListener dataListener = new ExcelCellDataListener<>(); + try { + ExcelReader excelReader = getExcelReader(rowNum, fileName, inputStream, clazz, dataListener); + if (excelReader == null) { + return null; + } + List sheetList = excelReader.excelExecutor().sheetList(); + for (ReadSheet sheet : sheetList) { + excelReader.read(sheet); + } + excelReader.finish(); + } finally { + try { + inputStream.close(); + } catch (IOException e) { + log.error(e.getMessage(), e); + } + } + return dataListener.getData(); + } + + /** + * 获取OutputStream + * + * @param response response + * @param fileName 文件名称 + * @return java.io.OutputStream + * @author mlx + */ + private static OutputStream getOutputStream(HttpServletResponse response, String fileName, ExcelTypeEnum typeEnum) throws Exception { + fileName = URLEncoder.encode(fileName, "UTF-8"); + response.setStatus(200); + response.setCharacterEncoding("UTF-8"); + if (ExcelTypeEnum.CSV.equals(typeEnum)) { + response.setContentType("application/csv"); + } else { + response.setContentType("application/vnd.ms-excel"); + } + response.setHeader("Content-Disposition", "attachment;filename=" + fileName + typeEnum.getValue()); + return response.getOutputStream(); + } + + /** + * 获取ExcelReader + * + * @param rowNum 行数 + * @param fileName 文件名称 + * @param inputStream 流 + * @param clazz 类class + * @param listener 监听 + * @return com.alibaba.excel.ExcelReader + * @author mlx + */ + private static ExcelReader getExcelReader(int rowNum, String fileName, InputStream inputStream, Class clazz, ReadListener listener) { + if (StrUtil.isBlank(fileName)) { + return null; + } + String fileExtName = getFileExtName(fileName); + EasyExcelTypeEnum typeEnum = EasyExcelTypeEnum.parseType(fileExtName); + if (typeEnum == null) { + log.info("表格类型错误"); + } + + return EasyExcel.read(inputStream, clazz, listener).headRowNumber(rowNum).build(); + } + + /** + * 获取文件后缀名称 .xxx + * + * @param fileName 文件名称 + * @return java.lang.String + * @author mlx + */ + private static String getFileExtName(String fileName) { + if (StrUtil.isBlank(fileName)) { + return null; + } + int lastIndex = fileName.lastIndexOf(StrUtil.DOT); + if (lastIndex != -1) { + return fileName.substring(lastIndex); + } + return null; + } + + /** + * 获取样式 + * + * @return com.alibaba.excel.write.style.HorizontalCellStyleStrategy + * @author mlx + */ + private static HorizontalCellStyleStrategy getStyleStrategy() { + // 表头样式 + WriteCellStyle headStyle = new WriteCellStyle(); + // 设置表头居中对齐 + headStyle.setHorizontalAlignment(HorizontalAlignment.CENTER); + // 内容样式 + WriteCellStyle contentStyle = new WriteCellStyle(); + // 设置内容靠左对齐 + contentStyle.setHorizontalAlignment(HorizontalAlignment.LEFT); + return new HorizontalCellStyleStrategy(headStyle, contentStyle); + } + + /** + * 获取下拉的map + * + * @param clazz 类class + * @return java.util.Map + * @author mlx + */ + private static Map getSelectedMap(Class clazz) { + Map selectedMap = MapUtil.newHashMap(); + Field[] fields = clazz.getDeclaredFields(); + for (Field field : fields) { + if (!field.isAnnotationPresent(ExcelSelector.class) || !field.isAnnotationPresent(ExcelProperty.class)) { + continue; + } + ExcelSelector excelSelector = field.getAnnotation(ExcelSelector.class); + ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class); + ExcelSelectorResolve resolve = new ExcelSelectorResolve(); + String[] data = resolve.resolveExcelSelector(excelSelector); + if (ArrayUtil.isNotEmpty(data)) { + resolve.setSelectorData(data); + selectedMap.put(excelProperty.index(), resolve); + } + } + return selectedMap; + } +} diff --git a/web/src/main/java/com/ibeetl/jlw/entity/TeacherOpenCourse.java b/web/src/main/java/com/ibeetl/jlw/entity/TeacherOpenCourse.java index 0c3eff05..607f4ffd 100644 --- a/web/src/main/java/com/ibeetl/jlw/entity/TeacherOpenCourse.java +++ b/web/src/main/java/com/ibeetl/jlw/entity/TeacherOpenCourse.java @@ -50,6 +50,10 @@ public class TeacherOpenCourse extends BaseEntity{ private Integer teacherOpenCourseStatus ; + @UpdateIgnore + @InsertIgnore + private String teacherOpenCourseStatusText; + @FetchSql("select t.teacher_id, ta.teacher_name, ta.teacher_sn, teacher_open_course_merge_teacher_auth_code from teacher_open_course_merge_teacher t " + "left join teacher ta on ta.teacher_id = t.teacher_id " + "where t.teacher_open_course_id = #teacherOpenCourseId# and t.teacher_open_course_merge_teacher_status = 1 " + @@ -88,6 +92,14 @@ public class TeacherOpenCourse extends BaseEntity{ @InsertIgnore private float courseHours; + public String getTeacherOpenCourseStatusText() { + return teacherOpenCourseStatusText; + } + + public void setTeacherOpenCourseStatusText(String teacherOpenCourseStatusText) { + this.teacherOpenCourseStatusText = teacherOpenCourseStatusText; + } + @Setter @Getter @Accessors(chain = true) diff --git a/web/src/main/java/com/ibeetl/jlw/entity/TeacherOpenCourseMergeResourcesQuestion.java b/web/src/main/java/com/ibeetl/jlw/entity/TeacherOpenCourseMergeResourcesQuestion.java index b29cc771..779bd59d 100644 --- a/web/src/main/java/com/ibeetl/jlw/entity/TeacherOpenCourseMergeResourcesQuestion.java +++ b/web/src/main/java/com/ibeetl/jlw/entity/TeacherOpenCourseMergeResourcesQuestion.java @@ -1,5 +1,7 @@ package com.ibeetl.jlw.entity; +import cn.jlw.util.excel.ExcelSelector; +import com.alibaba.excel.annotation.ExcelProperty; import com.ibeetl.admin.core.annotation.Dict; import com.ibeetl.admin.core.entity.BaseEntity; import com.ibeetl.admin.core.util.ValidateConfig; @@ -23,51 +25,68 @@ public class TeacherOpenCourseMergeResourcesQuestion extends BaseEntity{ //开课ID @Dict(type="teacher_open_course.teacher_open_course_title.teacher_open_course_status=1") + @ExcelSelector(dictKeyValue = "teacher_open_course.teacher_open_course_title.teacher_open_course_status=1") + @ExcelProperty("关联开课") private Long teacherOpenCourseId ; //课程章节ID @Dict(type="teacher_open_course_merge_course_info.course_info_name.course_info_status=1") + @ExcelSelector(dictKeyValue = "teacher_open_course_merge_course_info.course_info_name.course_info_status=1") + @ExcelProperty("课程章节") private Long teacherOpenCourseMergeCourseInfoId ; //题型(1单选 2多选 3判断 4填空 5分析) - + @ExcelSelector(fixedSelector = {"1单选", "2多选", "3判断" }) + @ExcelProperty("题型") private Integer questionType ; //分值 + @ExcelProperty("分值") private BigDecimal questionScore ; //题干 + @ExcelProperty("题干") private String questionStem ; //选项A + @ExcelProperty("选项A") private String questionOptionA ; //选项B + @ExcelProperty("选项B") private String questionOptionB ; //选项C + @ExcelProperty("选项C") + private String questionOptionC ; //选项D + @ExcelProperty("选项D") + private String questionOptionD ; //选项E + @ExcelProperty("选项E") + private String questionOptionE ; //答案(单选是一个 多选是多个 判断是对错) + @ExcelProperty("答案 单选是一个 多选是多个 判断是对错") private String questionAnswer ; //解析 + @ExcelProperty("解析") private String questionAnalysis ; diff --git a/web/src/main/java/com/ibeetl/jlw/web/BaseController.java b/web/src/main/java/com/ibeetl/jlw/web/BaseController.java index f702917d..2097b25f 100644 --- a/web/src/main/java/com/ibeetl/jlw/web/BaseController.java +++ b/web/src/main/java/com/ibeetl/jlw/web/BaseController.java @@ -4,6 +4,9 @@ import org.springframework.beans.factory.annotation.Autowired; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.validation.constraints.NotBlank; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; /** *

@@ -22,5 +25,13 @@ public class BaseController { @Autowired protected HttpServletRequest request; + protected void setExcelResponse(@NotBlank String filename) throws UnsupportedEncodingException { + response.setCharacterEncoding("utf-8"); + // 设置 header 和 contentType。写在最后的原因是,避免报错时,响应 contentType 已经被修改了 + response.addHeader("Content-Disposition", "attachment;filename*=utf-8''" + URLEncoder.encode(filename, "UTF-8")); +// response.setContentType("application/vnd.ms-excel;charset=UTF-8"); xls + // xlsx + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + } } diff --git a/web/src/main/java/com/ibeetl/jlw/web/TeacherOpenCourseMergeResourcesQuestionController.java b/web/src/main/java/com/ibeetl/jlw/web/TeacherOpenCourseMergeResourcesQuestionController.java index c8e57a18..8740324f 100644 --- a/web/src/main/java/com/ibeetl/jlw/web/TeacherOpenCourseMergeResourcesQuestionController.java +++ b/web/src/main/java/com/ibeetl/jlw/web/TeacherOpenCourseMergeResourcesQuestionController.java @@ -1,11 +1,14 @@ package com.ibeetl.jlw.web; import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.date.DateUtil; import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.StrUtil; import cn.jlw.Interceptor.GetFile; import cn.jlw.Interceptor.RFile; import cn.jlw.Interceptor.SCoreUser; import cn.jlw.util.ToolUtils; +import cn.jlw.util.excel.ExcelUtil; import cn.jlw.validate.ValidateConfig; import com.ibeetl.admin.core.annotation.Function; import com.ibeetl.admin.core.entity.CoreUser; @@ -16,6 +19,7 @@ import com.ibeetl.jlw.entity.FileEntity; import com.ibeetl.jlw.entity.TeacherOpenCourseMergeResourcesQuestion; import com.ibeetl.jlw.service.TeacherOpenCourseMergeResourcesQuestionService; import com.ibeetl.jlw.web.query.TeacherOpenCourseMergeResourcesQuestionQuery; +import lombok.SneakyThrows; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -42,9 +46,13 @@ import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Map; +import static cn.jlw.util.CacheUserUtil.getStudent; +import static com.ibeetl.admin.core.util.user.CacheUserUtil.getUser; + /** * 开课题目拉取 开课-题库管理-离线 接口 * 切记不要对非线程安全的静态变量进行写操作 @@ -52,7 +60,7 @@ import java.util.Map; @RestController @Validated -public class TeacherOpenCourseMergeResourcesQuestionController{ +public class TeacherOpenCourseMergeResourcesQuestionController extends BaseController { private final Log log = LogFactory.getLog(this.getClass()); private static final String MODEL = "/jlw/teacherOpenCourseMergeResourcesQuestion"; @@ -464,4 +472,20 @@ public class TeacherOpenCourseMergeResourcesQuestionController{ return JsonResult.success(teacherOpenCourseMergeResourcesQuestionService.getGroupQuestionTypeCount(teacherOpenCourseId)); } + /** + * 导出批量模板 + * @return + */ + @SneakyThrows + @GetMapping(API + "/exportBatchTemplate.do") + public void exportBatchTemplate() { + + Assert.notNull(getUser(), "请登录后再操作"); + Assert.isNull(getStudent(), "学生无法访问该接口"); + + String filename = StrUtil.format("批量题目导入模板 {}", DateUtil.formatDate(DateUtil.date())); + // 输出 Excel + ExcelUtil.writeExcel(response, filename, Collections.emptyList(), TeacherOpenCourseMergeResourcesQuestion.class); + + } }