Commit 0742ef17dc417b553065cef15e109f0d5f392178
1 parent
862b98e7
reactor(infra):增加代码生成的单测(import 情况)
Showing
121 changed files
with
9261 additions
and
0 deletions
Too many changes.
To preserve performance only 100 of 121 files are displayed.
yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one_importEnable/assert.json
0 → 100644
| 1 | +[ { | |
| 2 | + "contentPath" : "java/InfraStudentPageReqVO", | |
| 3 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentPageReqVO.java" | |
| 4 | +}, { | |
| 5 | + "contentPath" : "java/InfraStudentRespVO", | |
| 6 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentRespVO.java" | |
| 7 | +}, { | |
| 8 | + "contentPath" : "java/InfraStudentSaveReqVO", | |
| 9 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentSaveReqVO.java" | |
| 10 | +}, { | |
| 11 | + "contentPath" : "java/InfraStudentImportExcelVO", | |
| 12 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentImportExcelVO.java" | |
| 13 | +}, { | |
| 14 | + "contentPath" : "java/InfraStudentImportRespVO", | |
| 15 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentImportRespVO.java" | |
| 16 | +}, { | |
| 17 | + "contentPath" : "java/InfraStudentController", | |
| 18 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/InfraStudentController.java" | |
| 19 | +}, { | |
| 20 | + "contentPath" : "java/InfraStudentDO", | |
| 21 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentDO.java" | |
| 22 | +}, { | |
| 23 | + "contentPath" : "java/InfraStudentMapper", | |
| 24 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentMapper.java" | |
| 25 | +}, { | |
| 26 | + "contentPath" : "xml/InfraStudentMapper", | |
| 27 | + "filePath" : "yudao-module-infra/src/main/resources/mapper/demo/InfraStudentMapper.xml" | |
| 28 | +}, { | |
| 29 | + "contentPath" : "java/InfraStudentServiceImpl", | |
| 30 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImpl.java" | |
| 31 | +}, { | |
| 32 | + "contentPath" : "java/InfraStudentService", | |
| 33 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentService.java" | |
| 34 | +}, { | |
| 35 | + "contentPath" : "java/InfraStudentServiceImplTest", | |
| 36 | + "filePath" : "yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImplTest.java" | |
| 37 | +}, { | |
| 38 | + "contentPath" : "java/ErrorCodeConstants_手动操作", | |
| 39 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants_手动操作.java" | |
| 40 | +}, { | |
| 41 | + "contentPath" : "sql/sql", | |
| 42 | + "filePath" : "sql/sql.sql" | |
| 43 | +}, { | |
| 44 | + "contentPath" : "sql/h2", | |
| 45 | + "filePath" : "sql/h2.sql" | |
| 46 | +}, { | |
| 47 | + "contentPath" : "vue/index", | |
| 48 | + "filePath" : "yudao-ui-admin-vben/src/views/infra/demo/index.vue" | |
| 49 | +}, { | |
| 50 | + "contentPath" : "vue/form", | |
| 51 | + "filePath" : "yudao-ui-admin-vben/src/views/infra/demo/modules/form.vue" | |
| 52 | +}, { | |
| 53 | + "contentPath" : "vue/import-form", | |
| 54 | + "filePath" : "yudao-ui-admin-vben/src/views/infra/demo/modules/import-form.vue" | |
| 55 | +}, { | |
| 56 | + "contentPath" : "ts/index", | |
| 57 | + "filePath" : "yudao-ui-admin-vben/src/api/infra/demo/index.ts" | |
| 58 | +} ] | |
| 0 | 59 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one_importEnable/java/ErrorCodeConstants_手动操作
0 → 100644
yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one_importEnable/java/InfraStudentController
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.controller.admin.demo; | |
| 2 | + | |
| 3 | +import org.springframework.web.bind.annotation.*; | |
| 4 | +import org.springframework.web.multipart.MultipartFile; | |
| 5 | +import jakarta.annotation.Resource; | |
| 6 | +import org.springframework.validation.annotation.Validated; | |
| 7 | +import org.springframework.security.access.prepost.PreAuthorize; | |
| 8 | +import io.swagger.v3.oas.annotations.tags.Tag; | |
| 9 | +import io.swagger.v3.oas.annotations.Parameter; | |
| 10 | +import io.swagger.v3.oas.annotations.Operation; | |
| 11 | + | |
| 12 | +import jakarta.validation.constraints.*; | |
| 13 | +import jakarta.validation.*; | |
| 14 | +import jakarta.servlet.http.*; | |
| 15 | +import java.util.*; | |
| 16 | +import java.io.IOException; | |
| 17 | + | |
| 18 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | |
| 19 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 20 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | |
| 21 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | |
| 22 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | |
| 23 | + | |
| 24 | +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; | |
| 25 | + | |
| 26 | +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; | |
| 27 | +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*; | |
| 28 | + | |
| 29 | +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; | |
| 30 | +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; | |
| 31 | +import cn.iocoder.yudao.module.infra.service.demo.InfraStudentService; | |
| 32 | + | |
| 33 | +@Tag(name = "管理后台 - 学生") | |
| 34 | +@RestController | |
| 35 | +@RequestMapping("/infra/student") | |
| 36 | +@Validated | |
| 37 | +public class InfraStudentController { | |
| 38 | + | |
| 39 | + @Resource | |
| 40 | + private InfraStudentService studentService; | |
| 41 | + | |
| 42 | + @PostMapping("/create") | |
| 43 | + @Operation(summary = "创建学生") | |
| 44 | + @PreAuthorize("@ss.hasPermission('infra:student:create')") | |
| 45 | + public CommonResult<Long> createStudent(@Valid @RequestBody InfraStudentSaveReqVO createReqVO) { | |
| 46 | + return success(studentService.createStudent(createReqVO)); | |
| 47 | + } | |
| 48 | + | |
| 49 | + @PutMapping("/update") | |
| 50 | + @Operation(summary = "更新学生") | |
| 51 | + @PreAuthorize("@ss.hasPermission('infra:student:update')") | |
| 52 | + public CommonResult<Boolean> updateStudent(@Valid @RequestBody InfraStudentSaveReqVO updateReqVO) { | |
| 53 | + studentService.updateStudent(updateReqVO); | |
| 54 | + return success(true); | |
| 55 | + } | |
| 56 | + | |
| 57 | + @DeleteMapping("/delete") | |
| 58 | + @Operation(summary = "删除学生") | |
| 59 | + @Parameter(name = "id", description = "编号", required = true) | |
| 60 | + @PreAuthorize("@ss.hasPermission('infra:student:delete')") | |
| 61 | + public CommonResult<Boolean> deleteStudent(@RequestParam("id") Long id) { | |
| 62 | + studentService.deleteStudent(id); | |
| 63 | + return success(true); | |
| 64 | + } | |
| 65 | + | |
| 66 | + @DeleteMapping("/delete-list") | |
| 67 | + @Parameter(name = "ids", description = "编号", required = true) | |
| 68 | + @Operation(summary = "批量删除学生") | |
| 69 | + @PreAuthorize("@ss.hasPermission('infra:student:delete')") | |
| 70 | + public CommonResult<Boolean> deleteStudentList(@RequestParam("ids") List<Long> ids) { | |
| 71 | + studentService.deleteStudentListByIds(ids); | |
| 72 | + return success(true); | |
| 73 | + } | |
| 74 | + | |
| 75 | + @GetMapping("/get") | |
| 76 | + @Operation(summary = "获得学生") | |
| 77 | + @Parameter(name = "id", description = "编号", required = true, example = "1024") | |
| 78 | + @PreAuthorize("@ss.hasPermission('infra:student:query')") | |
| 79 | + public CommonResult<InfraStudentRespVO> getStudent(@RequestParam("id") Long id) { | |
| 80 | + InfraStudentDO student = studentService.getStudent(id); | |
| 81 | + return success(BeanUtils.toBean(student, InfraStudentRespVO.class)); | |
| 82 | + } | |
| 83 | + | |
| 84 | + @GetMapping("/page") | |
| 85 | + @Operation(summary = "获得学生分页") | |
| 86 | + @PreAuthorize("@ss.hasPermission('infra:student:query')") | |
| 87 | + public CommonResult<PageResult<InfraStudentRespVO>> getStudentPage(@Valid InfraStudentPageReqVO pageReqVO) { | |
| 88 | + PageResult<InfraStudentDO> pageResult = studentService.getStudentPage(pageReqVO); | |
| 89 | + return success(BeanUtils.toBean(pageResult, InfraStudentRespVO.class)); | |
| 90 | + } | |
| 91 | + | |
| 92 | + @GetMapping("/export-excel") | |
| 93 | + @Operation(summary = "导出学生 Excel") | |
| 94 | + @PreAuthorize("@ss.hasPermission('infra:student:export')") | |
| 95 | + @ApiAccessLog(operateType = EXPORT) | |
| 96 | + public void exportStudentExcel(@Valid InfraStudentPageReqVO pageReqVO, | |
| 97 | + HttpServletResponse response) throws IOException { | |
| 98 | + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); | |
| 99 | + List<InfraStudentDO> list = studentService.getStudentPage(pageReqVO).getList(); | |
| 100 | + // 导出 Excel | |
| 101 | + ExcelUtils.write(response, "学生.xls", "数据", InfraStudentRespVO.class, | |
| 102 | + BeanUtils.toBean(list, InfraStudentRespVO.class)); | |
| 103 | + } | |
| 104 | + | |
| 105 | + @GetMapping("/get-import-template") | |
| 106 | + @Operation(summary = "获得导入学生模板") | |
| 107 | + @PreAuthorize("@ss.hasPermission('infra:student:import')") | |
| 108 | + public void importTemplate(HttpServletResponse response) throws IOException { | |
| 109 | + ExcelUtils.write(response, "学生导入模板.xls", "数据", | |
| 110 | + InfraStudentImportExcelVO.class, Collections.emptyList()); | |
| 111 | + } | |
| 112 | + | |
| 113 | + @PostMapping("/import") | |
| 114 | + @Operation(summary = "导入学生") | |
| 115 | + @Parameter(name = "file", description = "Excel 文件", required = true) | |
| 116 | + @PreAuthorize("@ss.hasPermission('infra:student:import')") | |
| 117 | + public CommonResult<InfraStudentImportRespVO> importExcel(@RequestParam("file") MultipartFile file) throws Exception { | |
| 118 | + List<InfraStudentImportExcelVO> list = ExcelUtils.read(file, InfraStudentImportExcelVO.class); | |
| 119 | + return success(studentService.importStudentList(list)); | |
| 120 | + } | |
| 121 | + | |
| 122 | +} | |
| 0 | 123 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one_importEnable/java/InfraStudentDO
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.dal.dataobject.demo; | |
| 2 | + | |
| 3 | +import lombok.*; | |
| 4 | +import java.util.*; | |
| 5 | +import java.time.LocalDateTime; | |
| 6 | +import java.time.LocalDateTime; | |
| 7 | +import com.baomidou.mybatisplus.annotation.*; | |
| 8 | +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | |
| 9 | + | |
| 10 | +/** | |
| 11 | + * 学生 DO | |
| 12 | + * | |
| 13 | + * @author 芋道源码 | |
| 14 | + */ | |
| 15 | +@TableName("infra_student") | |
| 16 | +@KeySequence("infra_student_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 | |
| 17 | +@Data | |
| 18 | +@EqualsAndHashCode(callSuper = true) | |
| 19 | +@ToString(callSuper = true) | |
| 20 | +@Builder | |
| 21 | +@NoArgsConstructor | |
| 22 | +@AllArgsConstructor | |
| 23 | +public class InfraStudentDO extends BaseDO { | |
| 24 | + | |
| 25 | + /** | |
| 26 | + * 编号 | |
| 27 | + */ | |
| 28 | + @TableId | |
| 29 | + private Long id; | |
| 30 | + /** | |
| 31 | + * 名字 | |
| 32 | + */ | |
| 33 | + private String name; | |
| 34 | + /** | |
| 35 | + * 简介 | |
| 36 | + */ | |
| 37 | + private String description; | |
| 38 | + /** | |
| 39 | + * 出生日期 | |
| 40 | + */ | |
| 41 | + private LocalDateTime birthday; | |
| 42 | + /** | |
| 43 | + * 性别 | |
| 44 | + * | |
| 45 | + * 枚举 {@link TODO system_user_sex 对应的类} | |
| 46 | + */ | |
| 47 | + private Integer sex; | |
| 48 | + /** | |
| 49 | + * 是否有效 | |
| 50 | + * | |
| 51 | + * 枚举 {@link TODO infra_boolean_string 对应的类} | |
| 52 | + */ | |
| 53 | + private Boolean enabled; | |
| 54 | + /** | |
| 55 | + * 头像 | |
| 56 | + */ | |
| 57 | + private String avatar; | |
| 58 | + /** | |
| 59 | + * 附件 | |
| 60 | + */ | |
| 61 | + private String video; | |
| 62 | + /** | |
| 63 | + * 备注 | |
| 64 | + */ | |
| 65 | + private String memo; | |
| 66 | + | |
| 67 | + | |
| 68 | +} | |
| 0 | 69 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one_importEnable/java/InfraStudentImportExcelVO
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; | |
| 2 | + | |
| 3 | +import cn.idev.excel.annotation.ExcelProperty; | |
| 4 | +import lombok.AllArgsConstructor; | |
| 5 | +import lombok.Builder; | |
| 6 | +import lombok.Data; | |
| 7 | +import lombok.NoArgsConstructor; | |
| 8 | +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; | |
| 9 | +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * 学生 Excel 导入 VO | |
| 13 | + */ | |
| 14 | +@Data | |
| 15 | +@Builder | |
| 16 | +@AllArgsConstructor | |
| 17 | +@NoArgsConstructor | |
| 18 | +public class InfraStudentImportExcelVO { | |
| 19 | + | |
| 20 | + @ExcelProperty("名字") | |
| 21 | + private String name; | |
| 22 | + | |
| 23 | + @ExcelProperty("简介") | |
| 24 | + private String description; | |
| 25 | + | |
| 26 | + @ExcelProperty("出生日期") | |
| 27 | + private LocalDateTime birthday; | |
| 28 | + | |
| 29 | + @ExcelProperty(value = "性别", converter = DictConvert.class) | |
| 30 | + @DictFormat("system_user_sex") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 | |
| 31 | + private Integer sex; | |
| 32 | + | |
| 33 | + @ExcelProperty(value = "是否有效", converter = DictConvert.class) | |
| 34 | + @DictFormat("infra_boolean_string") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 | |
| 35 | + private Boolean enabled; | |
| 36 | + | |
| 37 | + @ExcelProperty("头像") | |
| 38 | + private String avatar; | |
| 39 | + | |
| 40 | + @ExcelProperty("附件") | |
| 41 | + private String video; | |
| 42 | + | |
| 43 | + @ExcelProperty("备注") | |
| 44 | + private String memo; | |
| 45 | + | |
| 46 | +} | |
| 0 | 47 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one_importEnable/java/InfraStudentImportRespVO
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; | |
| 2 | + | |
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 4 | +import lombok.Builder; | |
| 5 | +import lombok.Data; | |
| 6 | + | |
| 7 | +import java.util.Map; | |
| 8 | + | |
| 9 | +@Schema(description = "管理后台 - 学生导入 Response VO") | |
| 10 | +@Data | |
| 11 | +@Builder | |
| 12 | +public class InfraStudentImportRespVO { | |
| 13 | + | |
| 14 | + @Schema(description = "创建成功的数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") | |
| 15 | + private Integer successCount; | |
| 16 | + | |
| 17 | + @Schema(description = "导入失败的数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | |
| 18 | + private Integer failureCount; | |
| 19 | + | |
| 20 | + @Schema(description = "导入失败的数据集合,key 为行号,value 为失败原因", requiredMode = Schema.RequiredMode.REQUIRED) | |
| 21 | + private Map<Integer, String> failureRows; | |
| 22 | + | |
| 23 | +} | |
| 0 | 24 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one_importEnable/java/InfraStudentMapper
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.dal.mysql.demo; | |
| 2 | + | |
| 3 | +import java.util.*; | |
| 4 | + | |
| 5 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 6 | +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | |
| 7 | +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | |
| 8 | +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; | |
| 9 | +import org.apache.ibatis.annotations.Mapper; | |
| 10 | +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; | |
| 11 | + | |
| 12 | +/** | |
| 13 | + * 学生 Mapper | |
| 14 | + * | |
| 15 | + * @author 芋道源码 | |
| 16 | + */ | |
| 17 | +@Mapper | |
| 18 | +public interface InfraStudentMapper extends BaseMapperX<InfraStudentDO> { | |
| 19 | + | |
| 20 | + default PageResult<InfraStudentDO> selectPage(InfraStudentPageReqVO reqVO) { | |
| 21 | + return selectPage(reqVO, new LambdaQueryWrapperX<InfraStudentDO>() | |
| 22 | + .likeIfPresent(InfraStudentDO::getName, reqVO.getName()) | |
| 23 | + .eqIfPresent(InfraStudentDO::getBirthday, reqVO.getBirthday()) | |
| 24 | + .eqIfPresent(InfraStudentDO::getSex, reqVO.getSex()) | |
| 25 | + .eqIfPresent(InfraStudentDO::getEnabled, reqVO.getEnabled()) | |
| 26 | + .betweenIfPresent(InfraStudentDO::getCreateTime, reqVO.getCreateTime()) | |
| 27 | + .orderByDesc(InfraStudentDO::getId)); | |
| 28 | + } | |
| 29 | + | |
| 30 | +} | |
| 0 | 31 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one_importEnable/java/InfraStudentPageReqVO
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; | |
| 2 | + | |
| 3 | +import lombok.*; | |
| 4 | +import java.util.*; | |
| 5 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 6 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | |
| 7 | +import org.springframework.format.annotation.DateTimeFormat; | |
| 8 | +import java.time.LocalDateTime; | |
| 9 | + | |
| 10 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | |
| 11 | + | |
| 12 | +@Schema(description = "管理后台 - 学生分页 Request VO") | |
| 13 | +@Data | |
| 14 | +public class InfraStudentPageReqVO extends PageParam { | |
| 15 | + | |
| 16 | + @Schema(description = "名字", example = "芋头") | |
| 17 | + private String name; | |
| 18 | + | |
| 19 | + @Schema(description = "出生日期") | |
| 20 | + private LocalDateTime birthday; | |
| 21 | + | |
| 22 | + @Schema(description = "性别", example = "1") | |
| 23 | + private Integer sex; | |
| 24 | + | |
| 25 | + @Schema(description = "是否有效", example = "true") | |
| 26 | + private Boolean enabled; | |
| 27 | + | |
| 28 | + @Schema(description = "创建时间") | |
| 29 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 30 | + private LocalDateTime[] createTime; | |
| 31 | + | |
| 32 | +} | |
| 0 | 33 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one_importEnable/java/InfraStudentRespVO
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; | |
| 2 | + | |
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 4 | +import lombok.*; | |
| 5 | +import java.util.*; | |
| 6 | +import org.springframework.format.annotation.DateTimeFormat; | |
| 7 | +import java.time.LocalDateTime; | |
| 8 | +import cn.idev.excel.annotation.*; | |
| 9 | +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; | |
| 10 | +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; | |
| 11 | + | |
| 12 | +@Schema(description = "管理后台 - 学生 Response VO") | |
| 13 | +@Data | |
| 14 | +@ExcelIgnoreUnannotated | |
| 15 | +public class InfraStudentRespVO { | |
| 16 | + | |
| 17 | + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | |
| 18 | + @ExcelProperty("编号") | |
| 19 | + private Long id; | |
| 20 | + | |
| 21 | + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头") | |
| 22 | + @ExcelProperty("名字") | |
| 23 | + private String name; | |
| 24 | + | |
| 25 | + @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍") | |
| 26 | + @ExcelProperty("简介") | |
| 27 | + private String description; | |
| 28 | + | |
| 29 | + @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED) | |
| 30 | + @ExcelProperty("出生日期") | |
| 31 | + private LocalDateTime birthday; | |
| 32 | + | |
| 33 | + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | |
| 34 | + @ExcelProperty(value = "性别", converter = DictConvert.class) | |
| 35 | + @DictFormat("system_user_sex") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 | |
| 36 | + private Integer sex; | |
| 37 | + | |
| 38 | + @Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") | |
| 39 | + @ExcelProperty(value = "是否有效", converter = DictConvert.class) | |
| 40 | + @DictFormat("infra_boolean_string") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 | |
| 41 | + private Boolean enabled; | |
| 42 | + | |
| 43 | + @Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") | |
| 44 | + @ExcelProperty("头像") | |
| 45 | + private String avatar; | |
| 46 | + | |
| 47 | + @Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4") | |
| 48 | + @ExcelProperty("附件") | |
| 49 | + private String video; | |
| 50 | + | |
| 51 | + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注") | |
| 52 | + @ExcelProperty("备注") | |
| 53 | + private String memo; | |
| 54 | + | |
| 55 | + @Schema(description = "创建时间") | |
| 56 | + @ExcelProperty("创建时间") | |
| 57 | + private LocalDateTime createTime; | |
| 58 | + | |
| 59 | +} | |
| 0 | 60 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one_importEnable/java/InfraStudentSaveReqVO
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; | |
| 2 | + | |
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 4 | +import lombok.*; | |
| 5 | +import java.util.*; | |
| 6 | +import jakarta.validation.constraints.*; | |
| 7 | +import org.springframework.format.annotation.DateTimeFormat; | |
| 8 | +import java.time.LocalDateTime; | |
| 9 | + | |
| 10 | +@Schema(description = "管理后台 - 学生新增/修改 Request VO") | |
| 11 | +@Data | |
| 12 | +public class InfraStudentSaveReqVO { | |
| 13 | + | |
| 14 | + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | |
| 15 | + private Long id; | |
| 16 | + | |
| 17 | + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头") | |
| 18 | + @NotEmpty(message = "名字不能为空") | |
| 19 | + private String name; | |
| 20 | + | |
| 21 | + @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍") | |
| 22 | + @NotEmpty(message = "简介不能为空") | |
| 23 | + private String description; | |
| 24 | + | |
| 25 | + @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED) | |
| 26 | + @NotNull(message = "出生日期不能为空") | |
| 27 | + private LocalDateTime birthday; | |
| 28 | + | |
| 29 | + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | |
| 30 | + @NotNull(message = "性别不能为空") | |
| 31 | + private Integer sex; | |
| 32 | + | |
| 33 | + @Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") | |
| 34 | + @NotNull(message = "是否有效不能为空") | |
| 35 | + private Boolean enabled; | |
| 36 | + | |
| 37 | + @Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") | |
| 38 | + @NotEmpty(message = "头像不能为空") | |
| 39 | + private String avatar; | |
| 40 | + | |
| 41 | + @Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4") | |
| 42 | + @NotEmpty(message = "附件不能为空") | |
| 43 | + private String video; | |
| 44 | + | |
| 45 | + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注") | |
| 46 | + @NotEmpty(message = "备注不能为空") | |
| 47 | + private String memo; | |
| 48 | + | |
| 49 | +} | |
| 0 | 50 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one_importEnable/java/InfraStudentService
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.service.demo; | |
| 2 | + | |
| 3 | +import java.util.*; | |
| 4 | +import jakarta.validation.*; | |
| 5 | +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; | |
| 6 | +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; | |
| 7 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 8 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | |
| 9 | + | |
| 10 | +/** | |
| 11 | + * 学生 Service 接口 | |
| 12 | + * | |
| 13 | + * @author 芋道源码 | |
| 14 | + */ | |
| 15 | +public interface InfraStudentService { | |
| 16 | + | |
| 17 | + /** | |
| 18 | + * 创建学生 | |
| 19 | + * | |
| 20 | + * @param createReqVO 创建信息 | |
| 21 | + * @return 编号 | |
| 22 | + */ | |
| 23 | + Long createStudent(@Valid InfraStudentSaveReqVO createReqVO); | |
| 24 | + | |
| 25 | + /** | |
| 26 | + * 导入学生 | |
| 27 | + * | |
| 28 | + * @param importList 导入信息 | |
| 29 | + * @return 导入结果 | |
| 30 | + */ | |
| 31 | + InfraStudentImportRespVO importStudentList(List<InfraStudentImportExcelVO> importList); | |
| 32 | + | |
| 33 | + /** | |
| 34 | + * 更新学生 | |
| 35 | + * | |
| 36 | + * @param updateReqVO 更新信息 | |
| 37 | + */ | |
| 38 | + void updateStudent(@Valid InfraStudentSaveReqVO updateReqVO); | |
| 39 | + | |
| 40 | + /** | |
| 41 | + * 删除学生 | |
| 42 | + * | |
| 43 | + * @param id 编号 | |
| 44 | + */ | |
| 45 | + void deleteStudent(Long id); | |
| 46 | + | |
| 47 | + /** | |
| 48 | + * 批量删除学生 | |
| 49 | + * | |
| 50 | + * @param ids 编号 | |
| 51 | + */ | |
| 52 | + void deleteStudentListByIds(List<Long> ids); | |
| 53 | + | |
| 54 | + /** | |
| 55 | + * 获得学生 | |
| 56 | + * | |
| 57 | + * @param id 编号 | |
| 58 | + * @return 学生 | |
| 59 | + */ | |
| 60 | + InfraStudentDO getStudent(Long id); | |
| 61 | + | |
| 62 | + /** | |
| 63 | + * 获得学生分页 | |
| 64 | + * | |
| 65 | + * @param pageReqVO 分页查询 | |
| 66 | + * @return 学生分页 | |
| 67 | + */ | |
| 68 | + PageResult<InfraStudentDO> getStudentPage(InfraStudentPageReqVO pageReqVO); | |
| 69 | + | |
| 70 | +} | |
| 0 | 71 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one_importEnable/java/InfraStudentServiceImpl
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.service.demo; | |
| 2 | + | |
| 3 | +import cn.hutool.core.collection.CollUtil; | |
| 4 | +import org.springframework.stereotype.Service; | |
| 5 | +import jakarta.annotation.Resource; | |
| 6 | +import org.springframework.validation.annotation.Validated; | |
| 7 | +import org.springframework.transaction.annotation.Transactional; | |
| 8 | + | |
| 9 | +import java.util.*; | |
| 10 | +import java.util.concurrent.atomic.AtomicInteger; | |
| 11 | +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; | |
| 12 | +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; | |
| 13 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 14 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | |
| 15 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | |
| 16 | + | |
| 17 | +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper; | |
| 18 | + | |
| 19 | +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | |
| 20 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | |
| 21 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.diffList; | |
| 22 | +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; | |
| 23 | + | |
| 24 | +/** | |
| 25 | + * 学生 Service 实现类 | |
| 26 | + * | |
| 27 | + * @author 芋道源码 | |
| 28 | + */ | |
| 29 | +@Service | |
| 30 | +@Validated | |
| 31 | +public class InfraStudentServiceImpl implements InfraStudentService { | |
| 32 | + | |
| 33 | + @Resource | |
| 34 | + private InfraStudentMapper studentMapper; | |
| 35 | + | |
| 36 | + @Override | |
| 37 | + public Long createStudent(InfraStudentSaveReqVO createReqVO) { | |
| 38 | + // 插入 | |
| 39 | + InfraStudentDO student = BeanUtils.toBean(createReqVO, InfraStudentDO.class); | |
| 40 | + studentMapper.insert(student); | |
| 41 | + | |
| 42 | + // 返回 | |
| 43 | + return student.getId(); | |
| 44 | + } | |
| 45 | + | |
| 46 | + @Override | |
| 47 | + @Transactional(rollbackFor = Exception.class) // 添加事务,异常则回滚所有导入 | |
| 48 | + public InfraStudentImportRespVO importStudentList(List<InfraStudentImportExcelVO> importList) { | |
| 49 | + if (CollUtil.isEmpty(importList)) { | |
| 50 | + return InfraStudentImportRespVO.builder() | |
| 51 | + .successCount(0).failureCount(0).failureRows(new LinkedHashMap<>()).build(); | |
| 52 | + } | |
| 53 | + // 遍历,逐个创建 | |
| 54 | + InfraStudentImportRespVO respVO = InfraStudentImportRespVO.builder() | |
| 55 | + .successCount(0).failureCount(0).failureRows(new LinkedHashMap<>()).build(); | |
| 56 | + AtomicInteger index = new AtomicInteger(1); | |
| 57 | + importList.forEach(importItem -> { | |
| 58 | + int currentIndex = index.getAndIncrement(); | |
| 59 | + try { | |
| 60 | + createStudent(BeanUtils.toBean(importItem, InfraStudentSaveReqVO.class)); | |
| 61 | + respVO.setSuccessCount(respVO.getSuccessCount() + 1); | |
| 62 | + } catch (Exception ex) { | |
| 63 | + respVO.getFailureRows().put(currentIndex, ex.getMessage()); | |
| 64 | + } | |
| 65 | + }); | |
| 66 | + respVO.setFailureCount(respVO.getFailureRows().size()); | |
| 67 | + return respVO; | |
| 68 | + } | |
| 69 | + | |
| 70 | + @Override | |
| 71 | + public void updateStudent(InfraStudentSaveReqVO updateReqVO) { | |
| 72 | + // 校验存在 | |
| 73 | + validateStudentExists(updateReqVO.getId()); | |
| 74 | + // 更新 | |
| 75 | + InfraStudentDO updateObj = BeanUtils.toBean(updateReqVO, InfraStudentDO.class); | |
| 76 | + studentMapper.updateById(updateObj); | |
| 77 | + } | |
| 78 | + | |
| 79 | + @Override | |
| 80 | + public void deleteStudent(Long id) { | |
| 81 | + // 校验存在 | |
| 82 | + validateStudentExists(id); | |
| 83 | + // 删除 | |
| 84 | + studentMapper.deleteById(id); | |
| 85 | + } | |
| 86 | + | |
| 87 | + @Override | |
| 88 | + public void deleteStudentListByIds(List<Long> ids) { | |
| 89 | + // 删除 | |
| 90 | + studentMapper.deleteByIds(ids); | |
| 91 | + } | |
| 92 | + | |
| 93 | + | |
| 94 | + private void validateStudentExists(Long id) { | |
| 95 | + if (studentMapper.selectById(id) == null) { | |
| 96 | + throw exception(STUDENT_NOT_EXISTS); | |
| 97 | + } | |
| 98 | + } | |
| 99 | + | |
| 100 | + @Override | |
| 101 | + public InfraStudentDO getStudent(Long id) { | |
| 102 | + return studentMapper.selectById(id); | |
| 103 | + } | |
| 104 | + | |
| 105 | + @Override | |
| 106 | + public PageResult<InfraStudentDO> getStudentPage(InfraStudentPageReqVO pageReqVO) { | |
| 107 | + return studentMapper.selectPage(pageReqVO); | |
| 108 | + } | |
| 109 | + | |
| 110 | +} | |
| 0 | 111 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one_importEnable/java/InfraStudentServiceImplTest
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.service.demo; | |
| 2 | + | |
| 3 | +import org.junit.jupiter.api.Disabled; | |
| 4 | +import org.junit.jupiter.api.Test; | |
| 5 | + | |
| 6 | +import jakarta.annotation.Resource; | |
| 7 | + | |
| 8 | +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; | |
| 9 | + | |
| 10 | +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; | |
| 11 | +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; | |
| 12 | +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper; | |
| 13 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 14 | + | |
| 15 | +import jakarta.annotation.Resource; | |
| 16 | +import org.springframework.context.annotation.Import; | |
| 17 | +import java.util.*; | |
| 18 | +import java.time.LocalDateTime; | |
| 19 | + | |
| 20 | +import static cn.hutool.core.util.RandomUtil.*; | |
| 21 | +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; | |
| 22 | +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*; | |
| 23 | +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; | |
| 24 | +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*; | |
| 25 | +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*; | |
| 26 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*; | |
| 27 | +import static org.junit.jupiter.api.Assertions.*; | |
| 28 | +import static org.mockito.Mockito.*; | |
| 29 | + | |
| 30 | +/** | |
| 31 | + * {@link InfraStudentServiceImpl} 的单元测试类 | |
| 32 | + * | |
| 33 | + * @author 芋道源码 | |
| 34 | + */ | |
| 35 | +@Import(InfraStudentServiceImpl.class) | |
| 36 | +public class InfraStudentServiceImplTest extends BaseDbUnitTest { | |
| 37 | + | |
| 38 | + @Resource | |
| 39 | + private InfraStudentServiceImpl studentService; | |
| 40 | + | |
| 41 | + @Resource | |
| 42 | + private InfraStudentMapper studentMapper; | |
| 43 | + | |
| 44 | + @Test | |
| 45 | + public void testCreateStudent_success() { | |
| 46 | + // 准备参数 | |
| 47 | + InfraStudentSaveReqVO createReqVO = randomPojo(InfraStudentSaveReqVO.class).setId(null); | |
| 48 | + | |
| 49 | + // 调用 | |
| 50 | + Long studentId = studentService.createStudent(createReqVO); | |
| 51 | + // 断言 | |
| 52 | + assertNotNull(studentId); | |
| 53 | + // 校验记录的属性是否正确 | |
| 54 | + InfraStudentDO student = studentMapper.selectById(studentId); | |
| 55 | + assertPojoEquals(createReqVO, student, "id"); | |
| 56 | + } | |
| 57 | + | |
| 58 | + @Test | |
| 59 | + public void testUpdateStudent_success() { | |
| 60 | + // mock 数据 | |
| 61 | + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class); | |
| 62 | + studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据 | |
| 63 | + // 准备参数 | |
| 64 | + InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class, o -> { | |
| 65 | + o.setId(dbStudent.getId()); // 设置更新的 ID | |
| 66 | + }); | |
| 67 | + | |
| 68 | + // 调用 | |
| 69 | + studentService.updateStudent(updateReqVO); | |
| 70 | + // 校验是否更新正确 | |
| 71 | + InfraStudentDO student = studentMapper.selectById(updateReqVO.getId()); // 获取最新的 | |
| 72 | + assertPojoEquals(updateReqVO, student); | |
| 73 | + } | |
| 74 | + | |
| 75 | + @Test | |
| 76 | + public void testUpdateStudent_notExists() { | |
| 77 | + // 准备参数 | |
| 78 | + InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class); | |
| 79 | + | |
| 80 | + // 调用, 并断言异常 | |
| 81 | + assertServiceException(() -> studentService.updateStudent(updateReqVO), STUDENT_NOT_EXISTS); | |
| 82 | + } | |
| 83 | + | |
| 84 | + @Test | |
| 85 | + public void testDeleteStudent_success() { | |
| 86 | + // mock 数据 | |
| 87 | + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class); | |
| 88 | + studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据 | |
| 89 | + // 准备参数 | |
| 90 | + Long id = dbStudent.getId(); | |
| 91 | + | |
| 92 | + // 调用 | |
| 93 | + studentService.deleteStudent(id); | |
| 94 | + // 校验数据不存在了 | |
| 95 | + assertNull(studentMapper.selectById(id)); | |
| 96 | + } | |
| 97 | + | |
| 98 | + @Test | |
| 99 | + public void testDeleteStudent_notExists() { | |
| 100 | + // 准备参数 | |
| 101 | + Long id = randomLongId(); | |
| 102 | + | |
| 103 | + // 调用, 并断言异常 | |
| 104 | + assertServiceException(() -> studentService.deleteStudent(id), STUDENT_NOT_EXISTS); | |
| 105 | + } | |
| 106 | + | |
| 107 | + @Test | |
| 108 | + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 | |
| 109 | + public void testGetStudentPage() { | |
| 110 | + // mock 数据 | |
| 111 | + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class, o -> { // 等会查询到 | |
| 112 | + o.setName(null); | |
| 113 | + o.setBirthday(null); | |
| 114 | + o.setSex(null); | |
| 115 | + o.setEnabled(null); | |
| 116 | + o.setCreateTime(null); | |
| 117 | + }); | |
| 118 | + studentMapper.insert(dbStudent); | |
| 119 | + // 测试 name 不匹配 | |
| 120 | + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setName(null))); | |
| 121 | + // 测试 birthday 不匹配 | |
| 122 | + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setBirthday(null))); | |
| 123 | + // 测试 sex 不匹配 | |
| 124 | + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setSex(null))); | |
| 125 | + // 测试 enabled 不匹配 | |
| 126 | + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setEnabled(null))); | |
| 127 | + // 测试 createTime 不匹配 | |
| 128 | + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setCreateTime(null))); | |
| 129 | + // 准备参数 | |
| 130 | + InfraStudentPageReqVO reqVO = new InfraStudentPageReqVO(); | |
| 131 | + reqVO.setName(null); | |
| 132 | + reqVO.setBirthday(null); | |
| 133 | + reqVO.setSex(null); | |
| 134 | + reqVO.setEnabled(null); | |
| 135 | + reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); | |
| 136 | + | |
| 137 | + // 调用 | |
| 138 | + PageResult<InfraStudentDO> pageResult = studentService.getStudentPage(reqVO); | |
| 139 | + // 断言 | |
| 140 | + assertEquals(1, pageResult.getTotal()); | |
| 141 | + assertEquals(1, pageResult.getList().size()); | |
| 142 | + assertPojoEquals(dbStudent, pageResult.getList().get(0)); | |
| 143 | + } | |
| 144 | + | |
| 145 | +} | |
| 0 | 146 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one_importEnable/sql/h2
0 → 100644
| 1 | +-- 将该建表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/create_tables.sql 文件里 | |
| 2 | +CREATE TABLE IF NOT EXISTS "infra_student" ( | |
| 3 | + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, | |
| 4 | + "name" varchar NOT NULL, | |
| 5 | + "description" varchar NOT NULL, | |
| 6 | + "birthday" varchar NOT NULL, | |
| 7 | + "sex" int NOT NULL, | |
| 8 | + "enabled" bit NOT NULL, | |
| 9 | + "avatar" varchar NOT NULL, | |
| 10 | + "video" varchar NOT NULL, | |
| 11 | + "memo" varchar NOT NULL, | |
| 12 | + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| 13 | + PRIMARY KEY ("id") | |
| 14 | +) COMMENT '学生表'; | |
| 15 | + | |
| 16 | +-- 将该删表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/clean.sql 文件里 | |
| 17 | +DELETE FROM "infra_student"; | |
| 0 | 18 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one_importEnable/sql/sql
0 → 100644
| 1 | +-- 菜单 SQL | |
| 2 | +INSERT INTO system_menu( | |
| 3 | + name, permission, type, sort, parent_id, | |
| 4 | + path, icon, component, status, component_name | |
| 5 | +) | |
| 6 | +VALUES ( | |
| 7 | + '学生管理', '', 2, 0, 888, | |
| 8 | + 'student', '', 'infra/demo/index', 0, 'InfraStudent' | |
| 9 | +); | |
| 10 | + | |
| 11 | +-- 按钮父菜单ID | |
| 12 | +SELECT @parentId := LAST_INSERT_ID(); | |
| 13 | + | |
| 14 | +-- 按钮 SQL | |
| 15 | +INSERT INTO system_menu( | |
| 16 | + name, permission, type, sort, parent_id, | |
| 17 | + path, icon, component, status | |
| 18 | +) | |
| 19 | +VALUES ( | |
| 20 | + '学生查询', 'infra:student:query', 3, 1, @parentId, | |
| 21 | + '', '', '', 0 | |
| 22 | +); | |
| 23 | +INSERT INTO system_menu( | |
| 24 | + name, permission, type, sort, parent_id, | |
| 25 | + path, icon, component, status | |
| 26 | +) | |
| 27 | +VALUES ( | |
| 28 | + '学生创建', 'infra:student:create', 3, 2, @parentId, | |
| 29 | + '', '', '', 0 | |
| 30 | +); | |
| 31 | +INSERT INTO system_menu( | |
| 32 | + name, permission, type, sort, parent_id, | |
| 33 | + path, icon, component, status | |
| 34 | +) | |
| 35 | +VALUES ( | |
| 36 | + '学生更新', 'infra:student:update', 3, 3, @parentId, | |
| 37 | + '', '', '', 0 | |
| 38 | +); | |
| 39 | +INSERT INTO system_menu( | |
| 40 | + name, permission, type, sort, parent_id, | |
| 41 | + path, icon, component, status | |
| 42 | +) | |
| 43 | +VALUES ( | |
| 44 | + '学生删除', 'infra:student:delete', 3, 4, @parentId, | |
| 45 | + '', '', '', 0 | |
| 46 | +); | |
| 47 | +INSERT INTO system_menu( | |
| 48 | + name, permission, type, sort, parent_id, | |
| 49 | + path, icon, component, status | |
| 50 | +) | |
| 51 | +VALUES ( | |
| 52 | + '学生导出', 'infra:student:export', 3, 5, @parentId, | |
| 53 | + '', '', '', 0 | |
| 54 | +); | |
| 55 | +INSERT INTO system_menu( | |
| 56 | + name, permission, type, sort, parent_id, | |
| 57 | + path, icon, component, status | |
| 58 | +) | |
| 59 | +VALUES ( | |
| 60 | + '学生导入', 'infra:student:import', 3, 6, @parentId, | |
| 61 | + '', '', '', 0 | |
| 62 | +); | |
| 0 | 63 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one_importEnable/ts/index
0 → 100644
| 1 | +import type { PageParam, PageResult } from '@vben/request'; | |
| 2 | +import type { Dayjs } from 'dayjs'; | |
| 3 | + | |
| 4 | +import { requestClient } from '#/api/request'; | |
| 5 | + | |
| 6 | +export namespace StudentApi { | |
| 7 | + /** 学生信息 */ | |
| 8 | + export interface Student { | |
| 9 | + id: number; // 编号 | |
| 10 | + name?: string; // 名字 | |
| 11 | + description?: string; // 简介 | |
| 12 | + birthday?: string | Dayjs; // 出生日期 | |
| 13 | + sex?: number; // 性别 | |
| 14 | + enabled?: boolean; // 是否有效 | |
| 15 | + avatar?: string; // 头像 | |
| 16 | + video?: string; // 附件 | |
| 17 | + memo?: string; // 备注 | |
| 18 | + } | |
| 19 | +} | |
| 20 | + | |
| 21 | +/** 查询学生分页 */ | |
| 22 | +export function getStudentPage(params: PageParam) { | |
| 23 | + return requestClient.get<PageResult<StudentApi.Student>>('/infra/student/page', { params }); | |
| 24 | +} | |
| 25 | + | |
| 26 | +/** 查询学生详情 */ | |
| 27 | +export function getStudent(id: number) { | |
| 28 | + return requestClient.get<StudentApi.Student>(`/infra/student/get?id=${id}`); | |
| 29 | +} | |
| 30 | + | |
| 31 | +/** 新增学生 */ | |
| 32 | +export function createStudent(data: StudentApi.Student) { | |
| 33 | + return requestClient.post('/infra/student/create', data); | |
| 34 | +} | |
| 35 | + | |
| 36 | +/** 修改学生 */ | |
| 37 | +export function updateStudent(data: StudentApi.Student) { | |
| 38 | + return requestClient.put('/infra/student/update', data); | |
| 39 | +} | |
| 40 | + | |
| 41 | +/** 删除学生 */ | |
| 42 | +export function deleteStudent(id: number) { | |
| 43 | + return requestClient.delete(`/infra/student/delete?id=${id}`); | |
| 44 | +} | |
| 45 | + | |
| 46 | +/** 批量删除学生 */ | |
| 47 | +export function deleteStudentList(ids: number[]) { | |
| 48 | + return requestClient.delete(`/infra/student/delete-list?ids=${ids.join(',')}`) | |
| 49 | +} | |
| 50 | + | |
| 51 | +/** 导出学生 */ | |
| 52 | +export function exportStudent(params: any) { | |
| 53 | + return requestClient.download('/infra/student/export-excel', { params }); | |
| 54 | +} | |
| 55 | + | |
| 56 | +/** 下载学生导入模板 */ | |
| 57 | +export function importStudentTemplate() { | |
| 58 | + return requestClient.download('/infra/student/get-import-template'); | |
| 59 | +} | |
| 60 | + | |
| 61 | +/** 导入学生 */ | |
| 62 | +export function importStudent(data: FormData) { | |
| 63 | + return requestClient.post('/infra/student/import', data); | |
| 64 | +} | |
| 0 | 65 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one_importEnable/vue/form
0 → 100644
| 1 | +<script lang="ts" setup> | |
| 2 | +import type { Rule } from 'ant-design-vue/es/form'; | |
| 3 | +import type { StudentApi } from '#/api/infra/demo'; | |
| 4 | + | |
| 5 | +import { computed, ref } from 'vue'; | |
| 6 | + | |
| 7 | +import { useVbenModal } from '@vben/common-ui'; | |
| 8 | +import { DICT_TYPE } from '@vben/constants'; | |
| 9 | +import { getDictOptions } from '@vben/hooks'; | |
| 10 | +import { Tinymce as RichTextarea } from '#/components/tinymce'; | |
| 11 | +import { ImageUpload, FileUpload } from "#/components/upload"; | |
| 12 | +import { message, Tabs, Form, Input, Textarea, Select, RadioGroup, Radio, CheckboxGroup, Checkbox, DatePicker, TreeSelect } from 'ant-design-vue'; | |
| 13 | + | |
| 14 | +import { $t } from '#/locales'; | |
| 15 | +import { getStudent, createStudent, updateStudent } from '#/api/infra/demo'; | |
| 16 | + | |
| 17 | +const emit = defineEmits(['success']); | |
| 18 | + | |
| 19 | +const formRef = ref(); | |
| 20 | +const formData = ref<Partial<StudentApi.Student>>({ | |
| 21 | + id: undefined, | |
| 22 | + name: undefined, | |
| 23 | + description: undefined, | |
| 24 | + birthday: undefined, | |
| 25 | + sex: undefined, | |
| 26 | + enabled: undefined, | |
| 27 | + avatar: undefined, | |
| 28 | + video: undefined, | |
| 29 | + memo: undefined, | |
| 30 | +}); | |
| 31 | +const rules: Record<string, Rule[]> = { | |
| 32 | + name: [{ required: true, message: '名字不能为空', trigger: 'blur' }], | |
| 33 | + description: [{ required: true, message: '简介不能为空', trigger: 'blur' }], | |
| 34 | + birthday: [{ required: true, message: '出生日期不能为空', trigger: 'blur' }], | |
| 35 | + sex: [{ required: true, message: '性别不能为空', trigger: 'change' }], | |
| 36 | + enabled: [{ required: true, message: '是否有效不能为空', trigger: 'blur' }], | |
| 37 | + avatar: [{ required: true, message: '头像不能为空', trigger: 'blur' }], | |
| 38 | + video: [{ required: true, message: '附件不能为空', trigger: 'blur' }], | |
| 39 | + memo: [{ required: true, message: '备注不能为空', trigger: 'blur' }], | |
| 40 | +}; | |
| 41 | +const getTitle = computed(() => { | |
| 42 | + return formData.value?.id | |
| 43 | + ? $t('ui.actionTitle.edit', ['学生']) | |
| 44 | + : $t('ui.actionTitle.create', ['学生']); | |
| 45 | +}); | |
| 46 | + | |
| 47 | + | |
| 48 | +/** 重置表单 */ | |
| 49 | +function resetForm() { | |
| 50 | + formData.value = { | |
| 51 | + id: undefined, | |
| 52 | + name: undefined, | |
| 53 | + description: undefined, | |
| 54 | + birthday: undefined, | |
| 55 | + sex: undefined, | |
| 56 | + enabled: undefined, | |
| 57 | + avatar: undefined, | |
| 58 | + video: undefined, | |
| 59 | + memo: undefined, | |
| 60 | + }; | |
| 61 | + formRef.value?.resetFields(); | |
| 62 | +} | |
| 63 | + | |
| 64 | + | |
| 65 | +const [Modal, modalApi] = useVbenModal({ | |
| 66 | + async onConfirm() { | |
| 67 | + await formRef.value?.validate(); | |
| 68 | + modalApi.lock(); | |
| 69 | + // 提交表单 | |
| 70 | + const data = formData.value as StudentApi.Student; | |
| 71 | + try { | |
| 72 | + await (formData.value?.id ? updateStudent(data) : createStudent(data)); | |
| 73 | + // 关闭并提示 | |
| 74 | + await modalApi.close(); | |
| 75 | + emit('success'); | |
| 76 | + message.success({ | |
| 77 | + content: $t('ui.actionMessage.operationSuccess'), | |
| 78 | + }); | |
| 79 | + } finally { | |
| 80 | + modalApi.unlock(); | |
| 81 | + } | |
| 82 | + }, | |
| 83 | + async onOpenChange(isOpen: boolean) { | |
| 84 | + if (!isOpen) { | |
| 85 | + resetForm() | |
| 86 | + return; | |
| 87 | + } | |
| 88 | + // 加载数据 | |
| 89 | + let data = modalApi.getData<StudentApi.Student>(); | |
| 90 | + if (!data) { | |
| 91 | + return; | |
| 92 | + } | |
| 93 | + if (data.id) { | |
| 94 | + modalApi.lock(); | |
| 95 | + try { | |
| 96 | + data = await getStudent(data.id); | |
| 97 | + } finally { | |
| 98 | + modalApi.unlock(); | |
| 99 | + } | |
| 100 | + } | |
| 101 | + formData.value = data; | |
| 102 | + }, | |
| 103 | +}); | |
| 104 | +</script> | |
| 105 | + | |
| 106 | +<template> | |
| 107 | + <Modal :title="getTitle"> | |
| 108 | + <Form | |
| 109 | + ref="formRef" | |
| 110 | + :model="formData" | |
| 111 | + :rules="rules" | |
| 112 | + :label-col="{ span: 5 }" | |
| 113 | + :wrapper-col="{ span: 18 }" | |
| 114 | + > | |
| 115 | + <Form.Item label="名字" name="name"> | |
| 116 | + <Input v-model:value="formData.name" placeholder="请输入名字" /> | |
| 117 | + </Form.Item> | |
| 118 | + <Form.Item label="简介" name="description"> | |
| 119 | + <Textarea v-model:value="formData.description" placeholder="请输入简介" /> | |
| 120 | + </Form.Item> | |
| 121 | + <Form.Item label="出生日期" name="birthday"> | |
| 122 | + <DatePicker | |
| 123 | + v-model:value="formData.birthday" | |
| 124 | + valueFormat="x" | |
| 125 | + placeholder="选择出生日期" | |
| 126 | + /> | |
| 127 | + </Form.Item> | |
| 128 | + <Form.Item label="性别" name="sex"> | |
| 129 | + <Select v-model:value="formData.sex" placeholder="请选择性别"> | |
| 130 | + <Select.Option | |
| 131 | + v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')" | |
| 132 | + :key="dict.value" | |
| 133 | + :value="dict.value" | |
| 134 | + > | |
| 135 | + {{ dict.label }} | |
| 136 | + </Select.Option> | |
| 137 | + </Select> | |
| 138 | + </Form.Item> | |
| 139 | + <Form.Item label="是否有效" name="enabled"> | |
| 140 | + <RadioGroup v-model:value="formData.enabled"> | |
| 141 | + <Radio | |
| 142 | + v-for="dict in getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean')" | |
| 143 | + :key="dict.value" | |
| 144 | + :value="dict.value" | |
| 145 | + > | |
| 146 | + {{ dict.label }} | |
| 147 | + </Radio> | |
| 148 | + </RadioGroup> | |
| 149 | + </Form.Item> | |
| 150 | + <Form.Item label="头像" name="avatar"> | |
| 151 | + <ImageUpload v-model:value="formData.avatar" /> | |
| 152 | + </Form.Item> | |
| 153 | + <Form.Item label="附件" name="video"> | |
| 154 | + <FileUpload v-model:value="formData.video" /> | |
| 155 | + </Form.Item> | |
| 156 | + <Form.Item label="备注" name="memo"> | |
| 157 | + <RichTextarea v-model="formData.memo" height="500px" /> | |
| 158 | + </Form.Item> | |
| 159 | + </Form> | |
| 160 | + </Modal> | |
| 161 | +</template> | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one_importEnable/vue/import-form
0 → 100644
| 1 | +<script lang="ts" setup> | |
| 2 | +import type { FileType } from 'ant-design-vue/es/upload/interface'; | |
| 3 | + | |
| 4 | +import { ref } from 'vue'; | |
| 5 | + | |
| 6 | +import { useVbenModal } from '@vben/common-ui'; | |
| 7 | +import { downloadFileFromBlobPart } from '@vben/utils'; | |
| 8 | + | |
| 9 | +import { Button, message, Upload } from 'ant-design-vue'; | |
| 10 | + | |
| 11 | +import { importStudent, importStudentTemplate } from '#/api/infra/demo'; | |
| 12 | + | |
| 13 | +defineOptions({ name: 'StudentImport' }); | |
| 14 | + | |
| 15 | +const emit = defineEmits(['success']); | |
| 16 | +const fileRef = ref<File | null>(null); | |
| 17 | + | |
| 18 | +const [Modal, modalApi] = useVbenModal({ | |
| 19 | + async onConfirm() { | |
| 20 | + if (!fileRef.value) { | |
| 21 | + message.error('请上传文件'); | |
| 22 | + return; | |
| 23 | + } | |
| 24 | + modalApi.lock(); | |
| 25 | + try { | |
| 26 | + const formData = new FormData(); | |
| 27 | + formData.append('file', fileRef.value); | |
| 28 | + const response: any = await importStudent(formData); | |
| 29 | + const data = response?.data ?? response ?? {}; | |
| 30 | + let text = '导入成功数量:' + (data.successCount || 0) + ';导入失败数量:' + (data.failureCount || 0) + ';'; | |
| 31 | + if (data.failureRows) { | |
| 32 | + Object.keys(data.failureRows).forEach((rowNo) => { | |
| 33 | + text += '< 第' + rowNo + '行: ' + data.failureRows[rowNo] + ' >'; | |
| 34 | + }); | |
| 35 | + } | |
| 36 | + message.info(text); | |
| 37 | + await modalApi.close(); | |
| 38 | + emit('success'); | |
| 39 | + } finally { | |
| 40 | + modalApi.unlock(); | |
| 41 | + } | |
| 42 | + }, | |
| 43 | +}); | |
| 44 | + | |
| 45 | +/** 上传前:拦截 antd Upload 的自动上传,文件存到 ref */ | |
| 46 | +function beforeUpload(file: FileType) { | |
| 47 | + fileRef.value = file as unknown as File; | |
| 48 | + return false; | |
| 49 | +} | |
| 50 | + | |
| 51 | +/** 下载导入模板 */ | |
| 52 | +async function handleDownload() { | |
| 53 | + const data = await importStudentTemplate(); | |
| 54 | + downloadFileFromBlobPart({ fileName: '学生导入模板.xls', source: data }); | |
| 55 | +} | |
| 56 | +</script> | |
| 57 | + | |
| 58 | +<template> | |
| 59 | + <Modal title="导入学生" class="w-1/3"> | |
| 60 | + <div class="mx-4"> | |
| 61 | + <Upload :max-count="1" accept=".xls,.xlsx" :before-upload="beforeUpload"> | |
| 62 | + <Button type="primary"> 选择 Excel 文件 </Button> | |
| 63 | + </Upload> | |
| 64 | + </div> | |
| 65 | + <template #prepend-footer> | |
| 66 | + <div class="flex flex-auto items-center"> | |
| 67 | + <Button @click="handleDownload"> 下载导入模板 </Button> | |
| 68 | + </div> | |
| 69 | + </template> | |
| 70 | + </Modal> | |
| 71 | +</template> | |
| 0 | 72 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one_importEnable/vue/index
0 → 100644
| 1 | +<script lang="ts" setup> | |
| 2 | +import type { StudentApi } from '#/api/infra/demo'; | |
| 3 | + | |
| 4 | +import { ref, h, reactive, onMounted, nextTick } from 'vue'; | |
| 5 | + | |
| 6 | +import { Page, useVbenModal } from '@vben/common-ui'; | |
| 7 | +import { DICT_TYPE } from '@vben/constants'; | |
| 8 | +import { getDictOptions } from '@vben/hooks'; | |
| 9 | +import { useTableToolbar, VbenVxeTableToolbar } from '@vben/plugins/vxe-table'; | |
| 10 | +import { cloneDeep, downloadFileFromBlobPart, formatDateTime, isEmpty } from '@vben/utils'; | |
| 11 | +import { Button, Card, message, Tabs, Pagination, Form, RangePicker, DatePicker, Select, Input } from 'ant-design-vue'; | |
| 12 | +import StudentForm from './modules/form.vue'; | |
| 13 | +import { Download, Plus, RefreshCw, Search, Trash2 } from '@vben/icons'; | |
| 14 | +import { DictTag } from '#/components/dict-tag'; | |
| 15 | +import { VxeColumn, VxeTable } from '#/adapter/vxe-table'; | |
| 16 | +import { getRangePickerDefaultProps } from '#/utils/rangePickerProps'; | |
| 17 | + | |
| 18 | + | |
| 19 | +import { $t } from '#/locales'; | |
| 20 | +import { getStudentPage, deleteStudent, deleteStudentList, exportStudent } from '#/api/infra/demo'; | |
| 21 | +import StudentImport from './modules/import-form.vue'; | |
| 22 | + | |
| 23 | + | |
| 24 | +const loading = ref(true) // 列表的加载中 | |
| 25 | +const list = ref<StudentApi.Student[]>([]) // 列表的数据 | |
| 26 | + | |
| 27 | +const total = ref(0) // 列表的总页数 | |
| 28 | +const queryParams = reactive({ | |
| 29 | + pageNo: 1, | |
| 30 | + pageSize: 10, | |
| 31 | + name: undefined, | |
| 32 | + birthday: undefined, | |
| 33 | + birthday: undefined, | |
| 34 | + sex: undefined, | |
| 35 | + enabled: undefined, | |
| 36 | + createTime: undefined, | |
| 37 | +}) | |
| 38 | +const queryFormRef = ref() // 搜索的表单 | |
| 39 | +const exportLoading = ref(false) // 导出的加载中 | |
| 40 | + | |
| 41 | +/** 查询列表 */ | |
| 42 | +async function getList() { | |
| 43 | + loading.value = true | |
| 44 | + try { | |
| 45 | + const params = cloneDeep(queryParams) as any; | |
| 46 | + if (params.birthday && Array.isArray(params.birthday)) { | |
| 47 | + params.birthday = (params.birthday as string[]).join(','); | |
| 48 | + } | |
| 49 | + if (params.createTime && Array.isArray(params.createTime)) { | |
| 50 | + params.createTime = (params.createTime as string[]).join(','); | |
| 51 | + } | |
| 52 | + const data = await getStudentPage(params) | |
| 53 | + list.value = data.list | |
| 54 | + total.value = data.total | |
| 55 | + } finally { | |
| 56 | + loading.value = false | |
| 57 | + } | |
| 58 | +} | |
| 59 | + | |
| 60 | +/** 搜索按钮操作 */ | |
| 61 | +function handleQuery() { | |
| 62 | + queryParams.pageNo = 1 | |
| 63 | + getList() | |
| 64 | +} | |
| 65 | + | |
| 66 | +/** 重置按钮操作 */ | |
| 67 | +function resetQuery() { | |
| 68 | + queryFormRef.value.resetFields() | |
| 69 | + handleQuery() | |
| 70 | +} | |
| 71 | + | |
| 72 | +const [FormModal, formModalApi] = useVbenModal({ | |
| 73 | + connectedComponent: StudentForm, | |
| 74 | + destroyOnClose: true, | |
| 75 | +}); | |
| 76 | +const [ImportFormModal, importFormModalApi] = useVbenModal({ | |
| 77 | + connectedComponent: StudentImport, | |
| 78 | + destroyOnClose: true, | |
| 79 | +}); | |
| 80 | + | |
| 81 | +/** 导入学生 */ | |
| 82 | +function handleImport() { | |
| 83 | + importFormModalApi.open(); | |
| 84 | +} | |
| 85 | + | |
| 86 | +/** 创建学生 */ | |
| 87 | +function handleCreate() { | |
| 88 | + formModalApi.setData(null).open(); | |
| 89 | +} | |
| 90 | + | |
| 91 | +/** 编辑学生 */ | |
| 92 | +function handleEdit(row: StudentApi.Student) { | |
| 93 | + formModalApi.setData(row).open(); | |
| 94 | +} | |
| 95 | + | |
| 96 | + | |
| 97 | +/** 删除学生 */ | |
| 98 | +async function handleDelete(row: StudentApi.Student) { | |
| 99 | + const hideLoading = message.loading({ | |
| 100 | + content: $t('ui.actionMessage.deleting', [row.id]), | |
| 101 | + duration: 0, | |
| 102 | + }); | |
| 103 | + try { | |
| 104 | + await deleteStudent(row.id!); | |
| 105 | + message.success($t('ui.actionMessage.deleteSuccess', [row.id])); | |
| 106 | + await getList(); | |
| 107 | + } finally { | |
| 108 | + hideLoading(); | |
| 109 | + } | |
| 110 | +} | |
| 111 | + | |
| 112 | +/** 批量删除学生 */ | |
| 113 | +async function handleDeleteBatch() { | |
| 114 | + const hideLoading = message.loading({ | |
| 115 | + content: $t('ui.actionMessage.deleting'), | |
| 116 | + duration: 0, | |
| 117 | + }); | |
| 118 | + try { | |
| 119 | + await deleteStudentList(checkedIds.value); | |
| 120 | + checkedIds.value = []; | |
| 121 | + message.success($t('ui.actionMessage.deleteSuccess')); | |
| 122 | + await getList(); | |
| 123 | + } finally { | |
| 124 | + hideLoading(); | |
| 125 | + } | |
| 126 | +} | |
| 127 | + | |
| 128 | +const checkedIds = ref<number[]>([]) | |
| 129 | +function handleRowCheckboxChange({ | |
| 130 | + records, | |
| 131 | +}: { | |
| 132 | + records: StudentApi.Student[]; | |
| 133 | +}) { | |
| 134 | + checkedIds.value = records.map((item) => item.id!); | |
| 135 | +} | |
| 136 | + | |
| 137 | +/** 导出表格 */ | |
| 138 | +async function handleExport() { | |
| 139 | +try { | |
| 140 | + exportLoading.value = true; | |
| 141 | + const data = await exportStudent(queryParams); | |
| 142 | + downloadFileFromBlobPart({ fileName: '学生.xls', source: data }); | |
| 143 | +}finally { | |
| 144 | + exportLoading.value = false; | |
| 145 | +} | |
| 146 | +} | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | +/** 初始化 */ | |
| 151 | +const { hiddenSearchBar, tableToolbarRef, tableRef } = useTableToolbar(); | |
| 152 | +onMounted(() => { | |
| 153 | + getList(); | |
| 154 | +}); | |
| 155 | +</script> | |
| 156 | + | |
| 157 | +<template> | |
| 158 | + <Page auto-content-height> | |
| 159 | + <FormModal @success="getList" /> | |
| 160 | + <ImportFormModal @success="getList" /> | |
| 161 | + | |
| 162 | + <Card v-if="!hiddenSearchBar" class="mb-4"> | |
| 163 | + <!-- 搜索工作栏 --> | |
| 164 | + <Form | |
| 165 | + :model="queryParams" | |
| 166 | + ref="queryFormRef" | |
| 167 | + layout="inline" | |
| 168 | + > | |
| 169 | + <Form.Item label="名字" name="name"> | |
| 170 | + <Input | |
| 171 | + v-model:value="queryParams.name" | |
| 172 | + placeholder="请输入名字" | |
| 173 | + allowClear | |
| 174 | + @pressEnter="handleQuery" | |
| 175 | + class="w-full" | |
| 176 | + /> | |
| 177 | + </Form.Item> | |
| 178 | + <Form.Item label="出生日期" name="birthday"> | |
| 179 | + <DatePicker | |
| 180 | + v-model:value="queryParams.birthday" | |
| 181 | + valueFormat="YYYY-MM-DD" | |
| 182 | + placeholder="选择出生日期" | |
| 183 | + allowClear | |
| 184 | + class="w-full" | |
| 185 | + /> | |
| 186 | + </Form.Item> | |
| 187 | + <Form.Item label="性别" name="sex"> | |
| 188 | + <Select | |
| 189 | + v-model:value="queryParams.sex" | |
| 190 | + placeholder="请选择性别" | |
| 191 | + allowClear | |
| 192 | + class="w-full" | |
| 193 | + > | |
| 194 | + <Select.Option | |
| 195 | + v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')" | |
| 196 | + :key="dict.value" | |
| 197 | + :value="dict.value" | |
| 198 | + > | |
| 199 | + {{ dict.label }} | |
| 200 | + </Select.Option> | |
| 201 | + </Select> | |
| 202 | + </Form.Item> | |
| 203 | + <Form.Item label="是否有效" name="enabled"> | |
| 204 | + <Select | |
| 205 | + v-model:value="queryParams.enabled" | |
| 206 | + placeholder="请选择是否有效" | |
| 207 | + allowClear | |
| 208 | + class="w-full" | |
| 209 | + > | |
| 210 | + <Select.Option | |
| 211 | + v-for="dict in getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean')" | |
| 212 | + :key="dict.value" | |
| 213 | + :value="dict.value" | |
| 214 | + > | |
| 215 | + {{ dict.label }} | |
| 216 | + </Select.Option> | |
| 217 | + </Select> | |
| 218 | + </Form.Item> | |
| 219 | + <Form.Item label="创建时间" name="createTime"> | |
| 220 | + <RangePicker | |
| 221 | + v-model:value="queryParams.createTime" | |
| 222 | + v-bind="getRangePickerDefaultProps()" | |
| 223 | + class="w-full" | |
| 224 | + /> | |
| 225 | + </Form.Item> | |
| 226 | + <Form.Item> | |
| 227 | + <Button class="ml-2" @click="resetQuery"> 重置 </Button> | |
| 228 | + <Button class="ml-2" @click="handleQuery" type="primary"> | |
| 229 | + 搜索 | |
| 230 | + </Button> | |
| 231 | + </Form.Item> | |
| 232 | + </Form> | |
| 233 | + </Card> | |
| 234 | + | |
| 235 | + <!-- 列表 --> | |
| 236 | + <Card title="学生"> | |
| 237 | + <template #extra> | |
| 238 | + <VbenVxeTableToolbar | |
| 239 | + ref="tableToolbarRef" | |
| 240 | + v-model:hidden-search="hiddenSearchBar" | |
| 241 | + > | |
| 242 | + <Button | |
| 243 | + class="ml-2" | |
| 244 | + :icon="h(Plus)" | |
| 245 | + type="primary" | |
| 246 | + @click="handleCreate" | |
| 247 | + v-access:code="['infra:student:create']" | |
| 248 | + > | |
| 249 | + {{ $t('ui.actionTitle.create', ['学生']) }} | |
| 250 | + </Button> | |
| 251 | + <Button | |
| 252 | + class="ml-2" | |
| 253 | + type="primary" | |
| 254 | + @click="handleImport" | |
| 255 | + v-access:code="['infra:student:import']" | |
| 256 | + > | |
| 257 | + 导入 | |
| 258 | + </Button> | |
| 259 | + <Button | |
| 260 | + :icon="h(Download)" | |
| 261 | + type="primary" | |
| 262 | + class="ml-2" | |
| 263 | + :loading="exportLoading" | |
| 264 | + @click="handleExport" | |
| 265 | + v-access:code="['infra:student:export']" | |
| 266 | + > | |
| 267 | + {{ $t('ui.actionTitle.export') }} | |
| 268 | + </Button> | |
| 269 | + <Button | |
| 270 | + :icon="h(Trash2)" | |
| 271 | + type="primary" | |
| 272 | + danger | |
| 273 | + class="ml-2" | |
| 274 | + :disabled="isEmpty(checkedIds)" | |
| 275 | + @click="handleDeleteBatch" | |
| 276 | + v-access:code="['infra:student:delete']" | |
| 277 | + > | |
| 278 | + 批量删除 | |
| 279 | + </Button> | |
| 280 | + </VbenVxeTableToolbar> | |
| 281 | + </template> | |
| 282 | + <VxeTable | |
| 283 | + ref="tableRef" | |
| 284 | + :data="list" | |
| 285 | + show-overflow | |
| 286 | + :loading="loading" | |
| 287 | + @checkboxAll="handleRowCheckboxChange" | |
| 288 | + @checkboxChange="handleRowCheckboxChange" | |
| 289 | + > | |
| 290 | + <VxeColumn type="checkbox" width="40" /> | |
| 291 | + <VxeColumn field="id" title="编号" align="center" /> | |
| 292 | + <VxeColumn field="name" title="名字" align="center" /> | |
| 293 | + <VxeColumn field="description" title="简介" align="center" /> | |
| 294 | + <VxeColumn field="birthday" title="出生日期" align="center"> | |
| 295 | + <template #default="{row}"> | |
| 296 | + {{formatDateTime(row.birthday)}} | |
| 297 | + </template> | |
| 298 | + </VxeColumn> | |
| 299 | + <VxeColumn field="sex" title="性别" align="center"> | |
| 300 | + <template #default="{row}"> | |
| 301 | + <dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="row.sex" /> | |
| 302 | + </template> | |
| 303 | + </VxeColumn> | |
| 304 | + <VxeColumn field="enabled" title="是否有效" align="center"> | |
| 305 | + <template #default="{row}"> | |
| 306 | + <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="row.enabled" /> | |
| 307 | + </template> | |
| 308 | + </VxeColumn> | |
| 309 | + <VxeColumn field="avatar" title="头像" align="center" /> | |
| 310 | + <VxeColumn field="video" title="附件" align="center" /> | |
| 311 | + <VxeColumn field="memo" title="备注" align="center" /> | |
| 312 | + <VxeColumn field="createTime" title="创建时间" align="center"> | |
| 313 | + <template #default="{row}"> | |
| 314 | + {{formatDateTime(row.createTime)}} | |
| 315 | + </template> | |
| 316 | + </VxeColumn> | |
| 317 | + <VxeColumn field="operation" title="操作" align="center"> | |
| 318 | + <template #default="{row}"> | |
| 319 | + <Button | |
| 320 | + size="small" | |
| 321 | + type="link" | |
| 322 | + @click="handleEdit(row)" | |
| 323 | + v-access:code="['infra:student:update']" | |
| 324 | + > | |
| 325 | + {{ $t('ui.actionTitle.edit') }} | |
| 326 | + </Button> | |
| 327 | + <Button | |
| 328 | + size="small" | |
| 329 | + type="link" | |
| 330 | + danger | |
| 331 | + class="ml-2" | |
| 332 | + @click="handleDelete(row)" | |
| 333 | + v-access:code="['infra:student:delete']" | |
| 334 | + > | |
| 335 | + {{ $t('ui.actionTitle.delete') }} | |
| 336 | + </Button> | |
| 337 | + </template> | |
| 338 | + </VxeColumn> | |
| 339 | + </VxeTable> | |
| 340 | + <!-- 分页 --> | |
| 341 | + <div class="mt-2 flex justify-end"> | |
| 342 | + <Pagination | |
| 343 | + :total="total" | |
| 344 | + v-model:current="queryParams.pageNo" | |
| 345 | + v-model:page-size="queryParams.pageSize" | |
| 346 | + show-size-changer | |
| 347 | + @change="getList" | |
| 348 | + /> | |
| 349 | + </div> | |
| 350 | + </Card> | |
| 351 | + </Page> | |
| 352 | +</template> | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one_importEnable/xml/InfraStudentMapper
0 → 100644
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | |
| 2 | +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | |
| 3 | +<mapper namespace="cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper"> | |
| 4 | + | |
| 5 | + <!-- | |
| 6 | + 一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。 | |
| 7 | + 无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。 | |
| 8 | + 代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。 | |
| 9 | + 文档可见:https://www.iocoder.cn/MyBatis/x-plugins/ | |
| 10 | + --> | |
| 11 | + | |
| 12 | +</mapper> | |
| 0 | 13 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one_importEnable/assert.json
0 → 100644
| 1 | +[ { | |
| 2 | + "contentPath" : "java/InfraStudentPageReqVO", | |
| 3 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentPageReqVO.java" | |
| 4 | +}, { | |
| 5 | + "contentPath" : "java/InfraStudentRespVO", | |
| 6 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentRespVO.java" | |
| 7 | +}, { | |
| 8 | + "contentPath" : "java/InfraStudentSaveReqVO", | |
| 9 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentSaveReqVO.java" | |
| 10 | +}, { | |
| 11 | + "contentPath" : "java/InfraStudentImportExcelVO", | |
| 12 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentImportExcelVO.java" | |
| 13 | +}, { | |
| 14 | + "contentPath" : "java/InfraStudentImportRespVO", | |
| 15 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentImportRespVO.java" | |
| 16 | +}, { | |
| 17 | + "contentPath" : "java/InfraStudentController", | |
| 18 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/InfraStudentController.java" | |
| 19 | +}, { | |
| 20 | + "contentPath" : "java/InfraStudentDO", | |
| 21 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentDO.java" | |
| 22 | +}, { | |
| 23 | + "contentPath" : "java/InfraStudentMapper", | |
| 24 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentMapper.java" | |
| 25 | +}, { | |
| 26 | + "contentPath" : "xml/InfraStudentMapper", | |
| 27 | + "filePath" : "yudao-module-infra/src/main/resources/mapper/demo/InfraStudentMapper.xml" | |
| 28 | +}, { | |
| 29 | + "contentPath" : "java/InfraStudentServiceImpl", | |
| 30 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImpl.java" | |
| 31 | +}, { | |
| 32 | + "contentPath" : "java/InfraStudentService", | |
| 33 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentService.java" | |
| 34 | +}, { | |
| 35 | + "contentPath" : "java/InfraStudentServiceImplTest", | |
| 36 | + "filePath" : "yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImplTest.java" | |
| 37 | +}, { | |
| 38 | + "contentPath" : "java/ErrorCodeConstants_手动操作", | |
| 39 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants_手动操作.java" | |
| 40 | +}, { | |
| 41 | + "contentPath" : "sql/sql", | |
| 42 | + "filePath" : "sql/sql.sql" | |
| 43 | +}, { | |
| 44 | + "contentPath" : "sql/h2", | |
| 45 | + "filePath" : "sql/h2.sql" | |
| 46 | +}, { | |
| 47 | + "contentPath" : "ts/data", | |
| 48 | + "filePath" : "yudao-ui-admin-vben/src/views/infra/demo/data.ts" | |
| 49 | +}, { | |
| 50 | + "contentPath" : "vue/index", | |
| 51 | + "filePath" : "yudao-ui-admin-vben/src/views/infra/demo/index.vue" | |
| 52 | +}, { | |
| 53 | + "contentPath" : "vue/form", | |
| 54 | + "filePath" : "yudao-ui-admin-vben/src/views/infra/demo/modules/form.vue" | |
| 55 | +}, { | |
| 56 | + "contentPath" : "vue/import-form", | |
| 57 | + "filePath" : "yudao-ui-admin-vben/src/views/infra/demo/modules/import-form.vue" | |
| 58 | +}, { | |
| 59 | + "contentPath" : "ts/index", | |
| 60 | + "filePath" : "yudao-ui-admin-vben/src/api/infra/demo/index.ts" | |
| 61 | +} ] | |
| 0 | 62 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one_importEnable/java/ErrorCodeConstants_手动操作
0 → 100644
yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one_importEnable/java/InfraStudentController
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.controller.admin.demo; | |
| 2 | + | |
| 3 | +import org.springframework.web.bind.annotation.*; | |
| 4 | +import org.springframework.web.multipart.MultipartFile; | |
| 5 | +import jakarta.annotation.Resource; | |
| 6 | +import org.springframework.validation.annotation.Validated; | |
| 7 | +import org.springframework.security.access.prepost.PreAuthorize; | |
| 8 | +import io.swagger.v3.oas.annotations.tags.Tag; | |
| 9 | +import io.swagger.v3.oas.annotations.Parameter; | |
| 10 | +import io.swagger.v3.oas.annotations.Operation; | |
| 11 | + | |
| 12 | +import jakarta.validation.constraints.*; | |
| 13 | +import jakarta.validation.*; | |
| 14 | +import jakarta.servlet.http.*; | |
| 15 | +import java.util.*; | |
| 16 | +import java.io.IOException; | |
| 17 | + | |
| 18 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | |
| 19 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 20 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | |
| 21 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | |
| 22 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | |
| 23 | + | |
| 24 | +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; | |
| 25 | + | |
| 26 | +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; | |
| 27 | +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*; | |
| 28 | + | |
| 29 | +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; | |
| 30 | +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; | |
| 31 | +import cn.iocoder.yudao.module.infra.service.demo.InfraStudentService; | |
| 32 | + | |
| 33 | +@Tag(name = "管理后台 - 学生") | |
| 34 | +@RestController | |
| 35 | +@RequestMapping("/infra/student") | |
| 36 | +@Validated | |
| 37 | +public class InfraStudentController { | |
| 38 | + | |
| 39 | + @Resource | |
| 40 | + private InfraStudentService studentService; | |
| 41 | + | |
| 42 | + @PostMapping("/create") | |
| 43 | + @Operation(summary = "创建学生") | |
| 44 | + @PreAuthorize("@ss.hasPermission('infra:student:create')") | |
| 45 | + public CommonResult<Long> createStudent(@Valid @RequestBody InfraStudentSaveReqVO createReqVO) { | |
| 46 | + return success(studentService.createStudent(createReqVO)); | |
| 47 | + } | |
| 48 | + | |
| 49 | + @PutMapping("/update") | |
| 50 | + @Operation(summary = "更新学生") | |
| 51 | + @PreAuthorize("@ss.hasPermission('infra:student:update')") | |
| 52 | + public CommonResult<Boolean> updateStudent(@Valid @RequestBody InfraStudentSaveReqVO updateReqVO) { | |
| 53 | + studentService.updateStudent(updateReqVO); | |
| 54 | + return success(true); | |
| 55 | + } | |
| 56 | + | |
| 57 | + @DeleteMapping("/delete") | |
| 58 | + @Operation(summary = "删除学生") | |
| 59 | + @Parameter(name = "id", description = "编号", required = true) | |
| 60 | + @PreAuthorize("@ss.hasPermission('infra:student:delete')") | |
| 61 | + public CommonResult<Boolean> deleteStudent(@RequestParam("id") Long id) { | |
| 62 | + studentService.deleteStudent(id); | |
| 63 | + return success(true); | |
| 64 | + } | |
| 65 | + | |
| 66 | + @DeleteMapping("/delete-list") | |
| 67 | + @Parameter(name = "ids", description = "编号", required = true) | |
| 68 | + @Operation(summary = "批量删除学生") | |
| 69 | + @PreAuthorize("@ss.hasPermission('infra:student:delete')") | |
| 70 | + public CommonResult<Boolean> deleteStudentList(@RequestParam("ids") List<Long> ids) { | |
| 71 | + studentService.deleteStudentListByIds(ids); | |
| 72 | + return success(true); | |
| 73 | + } | |
| 74 | + | |
| 75 | + @GetMapping("/get") | |
| 76 | + @Operation(summary = "获得学生") | |
| 77 | + @Parameter(name = "id", description = "编号", required = true, example = "1024") | |
| 78 | + @PreAuthorize("@ss.hasPermission('infra:student:query')") | |
| 79 | + public CommonResult<InfraStudentRespVO> getStudent(@RequestParam("id") Long id) { | |
| 80 | + InfraStudentDO student = studentService.getStudent(id); | |
| 81 | + return success(BeanUtils.toBean(student, InfraStudentRespVO.class)); | |
| 82 | + } | |
| 83 | + | |
| 84 | + @GetMapping("/page") | |
| 85 | + @Operation(summary = "获得学生分页") | |
| 86 | + @PreAuthorize("@ss.hasPermission('infra:student:query')") | |
| 87 | + public CommonResult<PageResult<InfraStudentRespVO>> getStudentPage(@Valid InfraStudentPageReqVO pageReqVO) { | |
| 88 | + PageResult<InfraStudentDO> pageResult = studentService.getStudentPage(pageReqVO); | |
| 89 | + return success(BeanUtils.toBean(pageResult, InfraStudentRespVO.class)); | |
| 90 | + } | |
| 91 | + | |
| 92 | + @GetMapping("/export-excel") | |
| 93 | + @Operation(summary = "导出学生 Excel") | |
| 94 | + @PreAuthorize("@ss.hasPermission('infra:student:export')") | |
| 95 | + @ApiAccessLog(operateType = EXPORT) | |
| 96 | + public void exportStudentExcel(@Valid InfraStudentPageReqVO pageReqVO, | |
| 97 | + HttpServletResponse response) throws IOException { | |
| 98 | + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); | |
| 99 | + List<InfraStudentDO> list = studentService.getStudentPage(pageReqVO).getList(); | |
| 100 | + // 导出 Excel | |
| 101 | + ExcelUtils.write(response, "学生.xls", "数据", InfraStudentRespVO.class, | |
| 102 | + BeanUtils.toBean(list, InfraStudentRespVO.class)); | |
| 103 | + } | |
| 104 | + | |
| 105 | + @GetMapping("/get-import-template") | |
| 106 | + @Operation(summary = "获得导入学生模板") | |
| 107 | + @PreAuthorize("@ss.hasPermission('infra:student:import')") | |
| 108 | + public void importTemplate(HttpServletResponse response) throws IOException { | |
| 109 | + ExcelUtils.write(response, "学生导入模板.xls", "数据", | |
| 110 | + InfraStudentImportExcelVO.class, Collections.emptyList()); | |
| 111 | + } | |
| 112 | + | |
| 113 | + @PostMapping("/import") | |
| 114 | + @Operation(summary = "导入学生") | |
| 115 | + @Parameter(name = "file", description = "Excel 文件", required = true) | |
| 116 | + @PreAuthorize("@ss.hasPermission('infra:student:import')") | |
| 117 | + public CommonResult<InfraStudentImportRespVO> importExcel(@RequestParam("file") MultipartFile file) throws Exception { | |
| 118 | + List<InfraStudentImportExcelVO> list = ExcelUtils.read(file, InfraStudentImportExcelVO.class); | |
| 119 | + return success(studentService.importStudentList(list)); | |
| 120 | + } | |
| 121 | + | |
| 122 | +} | |
| 0 | 123 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one_importEnable/java/InfraStudentDO
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.dal.dataobject.demo; | |
| 2 | + | |
| 3 | +import lombok.*; | |
| 4 | +import java.util.*; | |
| 5 | +import java.time.LocalDateTime; | |
| 6 | +import java.time.LocalDateTime; | |
| 7 | +import com.baomidou.mybatisplus.annotation.*; | |
| 8 | +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | |
| 9 | + | |
| 10 | +/** | |
| 11 | + * 学生 DO | |
| 12 | + * | |
| 13 | + * @author 芋道源码 | |
| 14 | + */ | |
| 15 | +@TableName("infra_student") | |
| 16 | +@KeySequence("infra_student_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 | |
| 17 | +@Data | |
| 18 | +@EqualsAndHashCode(callSuper = true) | |
| 19 | +@ToString(callSuper = true) | |
| 20 | +@Builder | |
| 21 | +@NoArgsConstructor | |
| 22 | +@AllArgsConstructor | |
| 23 | +public class InfraStudentDO extends BaseDO { | |
| 24 | + | |
| 25 | + /** | |
| 26 | + * 编号 | |
| 27 | + */ | |
| 28 | + @TableId | |
| 29 | + private Long id; | |
| 30 | + /** | |
| 31 | + * 名字 | |
| 32 | + */ | |
| 33 | + private String name; | |
| 34 | + /** | |
| 35 | + * 简介 | |
| 36 | + */ | |
| 37 | + private String description; | |
| 38 | + /** | |
| 39 | + * 出生日期 | |
| 40 | + */ | |
| 41 | + private LocalDateTime birthday; | |
| 42 | + /** | |
| 43 | + * 性别 | |
| 44 | + * | |
| 45 | + * 枚举 {@link TODO system_user_sex 对应的类} | |
| 46 | + */ | |
| 47 | + private Integer sex; | |
| 48 | + /** | |
| 49 | + * 是否有效 | |
| 50 | + * | |
| 51 | + * 枚举 {@link TODO infra_boolean_string 对应的类} | |
| 52 | + */ | |
| 53 | + private Boolean enabled; | |
| 54 | + /** | |
| 55 | + * 头像 | |
| 56 | + */ | |
| 57 | + private String avatar; | |
| 58 | + /** | |
| 59 | + * 附件 | |
| 60 | + */ | |
| 61 | + private String video; | |
| 62 | + /** | |
| 63 | + * 备注 | |
| 64 | + */ | |
| 65 | + private String memo; | |
| 66 | + | |
| 67 | + | |
| 68 | +} | |
| 0 | 69 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one_importEnable/java/InfraStudentImportExcelVO
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; | |
| 2 | + | |
| 3 | +import cn.idev.excel.annotation.ExcelProperty; | |
| 4 | +import lombok.AllArgsConstructor; | |
| 5 | +import lombok.Builder; | |
| 6 | +import lombok.Data; | |
| 7 | +import lombok.NoArgsConstructor; | |
| 8 | +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; | |
| 9 | +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * 学生 Excel 导入 VO | |
| 13 | + */ | |
| 14 | +@Data | |
| 15 | +@Builder | |
| 16 | +@AllArgsConstructor | |
| 17 | +@NoArgsConstructor | |
| 18 | +public class InfraStudentImportExcelVO { | |
| 19 | + | |
| 20 | + @ExcelProperty("名字") | |
| 21 | + private String name; | |
| 22 | + | |
| 23 | + @ExcelProperty("简介") | |
| 24 | + private String description; | |
| 25 | + | |
| 26 | + @ExcelProperty("出生日期") | |
| 27 | + private LocalDateTime birthday; | |
| 28 | + | |
| 29 | + @ExcelProperty(value = "性别", converter = DictConvert.class) | |
| 30 | + @DictFormat("system_user_sex") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 | |
| 31 | + private Integer sex; | |
| 32 | + | |
| 33 | + @ExcelProperty(value = "是否有效", converter = DictConvert.class) | |
| 34 | + @DictFormat("infra_boolean_string") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 | |
| 35 | + private Boolean enabled; | |
| 36 | + | |
| 37 | + @ExcelProperty("头像") | |
| 38 | + private String avatar; | |
| 39 | + | |
| 40 | + @ExcelProperty("附件") | |
| 41 | + private String video; | |
| 42 | + | |
| 43 | + @ExcelProperty("备注") | |
| 44 | + private String memo; | |
| 45 | + | |
| 46 | +} | |
| 0 | 47 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one_importEnable/java/InfraStudentImportRespVO
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; | |
| 2 | + | |
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 4 | +import lombok.Builder; | |
| 5 | +import lombok.Data; | |
| 6 | + | |
| 7 | +import java.util.Map; | |
| 8 | + | |
| 9 | +@Schema(description = "管理后台 - 学生导入 Response VO") | |
| 10 | +@Data | |
| 11 | +@Builder | |
| 12 | +public class InfraStudentImportRespVO { | |
| 13 | + | |
| 14 | + @Schema(description = "创建成功的数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") | |
| 15 | + private Integer successCount; | |
| 16 | + | |
| 17 | + @Schema(description = "导入失败的数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | |
| 18 | + private Integer failureCount; | |
| 19 | + | |
| 20 | + @Schema(description = "导入失败的数据集合,key 为行号,value 为失败原因", requiredMode = Schema.RequiredMode.REQUIRED) | |
| 21 | + private Map<Integer, String> failureRows; | |
| 22 | + | |
| 23 | +} | |
| 0 | 24 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one_importEnable/java/InfraStudentMapper
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.dal.mysql.demo; | |
| 2 | + | |
| 3 | +import java.util.*; | |
| 4 | + | |
| 5 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 6 | +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | |
| 7 | +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | |
| 8 | +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; | |
| 9 | +import org.apache.ibatis.annotations.Mapper; | |
| 10 | +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; | |
| 11 | + | |
| 12 | +/** | |
| 13 | + * 学生 Mapper | |
| 14 | + * | |
| 15 | + * @author 芋道源码 | |
| 16 | + */ | |
| 17 | +@Mapper | |
| 18 | +public interface InfraStudentMapper extends BaseMapperX<InfraStudentDO> { | |
| 19 | + | |
| 20 | + default PageResult<InfraStudentDO> selectPage(InfraStudentPageReqVO reqVO) { | |
| 21 | + return selectPage(reqVO, new LambdaQueryWrapperX<InfraStudentDO>() | |
| 22 | + .likeIfPresent(InfraStudentDO::getName, reqVO.getName()) | |
| 23 | + .eqIfPresent(InfraStudentDO::getBirthday, reqVO.getBirthday()) | |
| 24 | + .eqIfPresent(InfraStudentDO::getSex, reqVO.getSex()) | |
| 25 | + .eqIfPresent(InfraStudentDO::getEnabled, reqVO.getEnabled()) | |
| 26 | + .betweenIfPresent(InfraStudentDO::getCreateTime, reqVO.getCreateTime()) | |
| 27 | + .orderByDesc(InfraStudentDO::getId)); | |
| 28 | + } | |
| 29 | + | |
| 30 | +} | |
| 0 | 31 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one_importEnable/java/InfraStudentPageReqVO
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; | |
| 2 | + | |
| 3 | +import lombok.*; | |
| 4 | +import java.util.*; | |
| 5 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 6 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | |
| 7 | +import org.springframework.format.annotation.DateTimeFormat; | |
| 8 | +import java.time.LocalDateTime; | |
| 9 | + | |
| 10 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | |
| 11 | + | |
| 12 | +@Schema(description = "管理后台 - 学生分页 Request VO") | |
| 13 | +@Data | |
| 14 | +public class InfraStudentPageReqVO extends PageParam { | |
| 15 | + | |
| 16 | + @Schema(description = "名字", example = "芋头") | |
| 17 | + private String name; | |
| 18 | + | |
| 19 | + @Schema(description = "出生日期") | |
| 20 | + private LocalDateTime birthday; | |
| 21 | + | |
| 22 | + @Schema(description = "性别", example = "1") | |
| 23 | + private Integer sex; | |
| 24 | + | |
| 25 | + @Schema(description = "是否有效", example = "true") | |
| 26 | + private Boolean enabled; | |
| 27 | + | |
| 28 | + @Schema(description = "创建时间") | |
| 29 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 30 | + private LocalDateTime[] createTime; | |
| 31 | + | |
| 32 | +} | |
| 0 | 33 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one_importEnable/java/InfraStudentRespVO
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; | |
| 2 | + | |
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 4 | +import lombok.*; | |
| 5 | +import java.util.*; | |
| 6 | +import org.springframework.format.annotation.DateTimeFormat; | |
| 7 | +import java.time.LocalDateTime; | |
| 8 | +import cn.idev.excel.annotation.*; | |
| 9 | +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; | |
| 10 | +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; | |
| 11 | + | |
| 12 | +@Schema(description = "管理后台 - 学生 Response VO") | |
| 13 | +@Data | |
| 14 | +@ExcelIgnoreUnannotated | |
| 15 | +public class InfraStudentRespVO { | |
| 16 | + | |
| 17 | + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | |
| 18 | + @ExcelProperty("编号") | |
| 19 | + private Long id; | |
| 20 | + | |
| 21 | + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头") | |
| 22 | + @ExcelProperty("名字") | |
| 23 | + private String name; | |
| 24 | + | |
| 25 | + @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍") | |
| 26 | + @ExcelProperty("简介") | |
| 27 | + private String description; | |
| 28 | + | |
| 29 | + @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED) | |
| 30 | + @ExcelProperty("出生日期") | |
| 31 | + private LocalDateTime birthday; | |
| 32 | + | |
| 33 | + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | |
| 34 | + @ExcelProperty(value = "性别", converter = DictConvert.class) | |
| 35 | + @DictFormat("system_user_sex") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 | |
| 36 | + private Integer sex; | |
| 37 | + | |
| 38 | + @Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") | |
| 39 | + @ExcelProperty(value = "是否有效", converter = DictConvert.class) | |
| 40 | + @DictFormat("infra_boolean_string") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 | |
| 41 | + private Boolean enabled; | |
| 42 | + | |
| 43 | + @Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") | |
| 44 | + @ExcelProperty("头像") | |
| 45 | + private String avatar; | |
| 46 | + | |
| 47 | + @Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4") | |
| 48 | + @ExcelProperty("附件") | |
| 49 | + private String video; | |
| 50 | + | |
| 51 | + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注") | |
| 52 | + @ExcelProperty("备注") | |
| 53 | + private String memo; | |
| 54 | + | |
| 55 | + @Schema(description = "创建时间") | |
| 56 | + @ExcelProperty("创建时间") | |
| 57 | + private LocalDateTime createTime; | |
| 58 | + | |
| 59 | +} | |
| 0 | 60 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one_importEnable/java/InfraStudentSaveReqVO
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; | |
| 2 | + | |
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 4 | +import lombok.*; | |
| 5 | +import java.util.*; | |
| 6 | +import jakarta.validation.constraints.*; | |
| 7 | +import org.springframework.format.annotation.DateTimeFormat; | |
| 8 | +import java.time.LocalDateTime; | |
| 9 | + | |
| 10 | +@Schema(description = "管理后台 - 学生新增/修改 Request VO") | |
| 11 | +@Data | |
| 12 | +public class InfraStudentSaveReqVO { | |
| 13 | + | |
| 14 | + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | |
| 15 | + private Long id; | |
| 16 | + | |
| 17 | + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头") | |
| 18 | + @NotEmpty(message = "名字不能为空") | |
| 19 | + private String name; | |
| 20 | + | |
| 21 | + @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍") | |
| 22 | + @NotEmpty(message = "简介不能为空") | |
| 23 | + private String description; | |
| 24 | + | |
| 25 | + @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED) | |
| 26 | + @NotNull(message = "出生日期不能为空") | |
| 27 | + private LocalDateTime birthday; | |
| 28 | + | |
| 29 | + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | |
| 30 | + @NotNull(message = "性别不能为空") | |
| 31 | + private Integer sex; | |
| 32 | + | |
| 33 | + @Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") | |
| 34 | + @NotNull(message = "是否有效不能为空") | |
| 35 | + private Boolean enabled; | |
| 36 | + | |
| 37 | + @Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") | |
| 38 | + @NotEmpty(message = "头像不能为空") | |
| 39 | + private String avatar; | |
| 40 | + | |
| 41 | + @Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4") | |
| 42 | + @NotEmpty(message = "附件不能为空") | |
| 43 | + private String video; | |
| 44 | + | |
| 45 | + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注") | |
| 46 | + @NotEmpty(message = "备注不能为空") | |
| 47 | + private String memo; | |
| 48 | + | |
| 49 | +} | |
| 0 | 50 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one_importEnable/java/InfraStudentService
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.service.demo; | |
| 2 | + | |
| 3 | +import java.util.*; | |
| 4 | +import jakarta.validation.*; | |
| 5 | +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; | |
| 6 | +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; | |
| 7 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 8 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | |
| 9 | + | |
| 10 | +/** | |
| 11 | + * 学生 Service 接口 | |
| 12 | + * | |
| 13 | + * @author 芋道源码 | |
| 14 | + */ | |
| 15 | +public interface InfraStudentService { | |
| 16 | + | |
| 17 | + /** | |
| 18 | + * 创建学生 | |
| 19 | + * | |
| 20 | + * @param createReqVO 创建信息 | |
| 21 | + * @return 编号 | |
| 22 | + */ | |
| 23 | + Long createStudent(@Valid InfraStudentSaveReqVO createReqVO); | |
| 24 | + | |
| 25 | + /** | |
| 26 | + * 导入学生 | |
| 27 | + * | |
| 28 | + * @param importList 导入信息 | |
| 29 | + * @return 导入结果 | |
| 30 | + */ | |
| 31 | + InfraStudentImportRespVO importStudentList(List<InfraStudentImportExcelVO> importList); | |
| 32 | + | |
| 33 | + /** | |
| 34 | + * 更新学生 | |
| 35 | + * | |
| 36 | + * @param updateReqVO 更新信息 | |
| 37 | + */ | |
| 38 | + void updateStudent(@Valid InfraStudentSaveReqVO updateReqVO); | |
| 39 | + | |
| 40 | + /** | |
| 41 | + * 删除学生 | |
| 42 | + * | |
| 43 | + * @param id 编号 | |
| 44 | + */ | |
| 45 | + void deleteStudent(Long id); | |
| 46 | + | |
| 47 | + /** | |
| 48 | + * 批量删除学生 | |
| 49 | + * | |
| 50 | + * @param ids 编号 | |
| 51 | + */ | |
| 52 | + void deleteStudentListByIds(List<Long> ids); | |
| 53 | + | |
| 54 | + /** | |
| 55 | + * 获得学生 | |
| 56 | + * | |
| 57 | + * @param id 编号 | |
| 58 | + * @return 学生 | |
| 59 | + */ | |
| 60 | + InfraStudentDO getStudent(Long id); | |
| 61 | + | |
| 62 | + /** | |
| 63 | + * 获得学生分页 | |
| 64 | + * | |
| 65 | + * @param pageReqVO 分页查询 | |
| 66 | + * @return 学生分页 | |
| 67 | + */ | |
| 68 | + PageResult<InfraStudentDO> getStudentPage(InfraStudentPageReqVO pageReqVO); | |
| 69 | + | |
| 70 | +} | |
| 0 | 71 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one_importEnable/java/InfraStudentServiceImpl
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.service.demo; | |
| 2 | + | |
| 3 | +import cn.hutool.core.collection.CollUtil; | |
| 4 | +import org.springframework.stereotype.Service; | |
| 5 | +import jakarta.annotation.Resource; | |
| 6 | +import org.springframework.validation.annotation.Validated; | |
| 7 | +import org.springframework.transaction.annotation.Transactional; | |
| 8 | + | |
| 9 | +import java.util.*; | |
| 10 | +import java.util.concurrent.atomic.AtomicInteger; | |
| 11 | +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; | |
| 12 | +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; | |
| 13 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 14 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | |
| 15 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | |
| 16 | + | |
| 17 | +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper; | |
| 18 | + | |
| 19 | +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | |
| 20 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | |
| 21 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.diffList; | |
| 22 | +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; | |
| 23 | + | |
| 24 | +/** | |
| 25 | + * 学生 Service 实现类 | |
| 26 | + * | |
| 27 | + * @author 芋道源码 | |
| 28 | + */ | |
| 29 | +@Service | |
| 30 | +@Validated | |
| 31 | +public class InfraStudentServiceImpl implements InfraStudentService { | |
| 32 | + | |
| 33 | + @Resource | |
| 34 | + private InfraStudentMapper studentMapper; | |
| 35 | + | |
| 36 | + @Override | |
| 37 | + public Long createStudent(InfraStudentSaveReqVO createReqVO) { | |
| 38 | + // 插入 | |
| 39 | + InfraStudentDO student = BeanUtils.toBean(createReqVO, InfraStudentDO.class); | |
| 40 | + studentMapper.insert(student); | |
| 41 | + | |
| 42 | + // 返回 | |
| 43 | + return student.getId(); | |
| 44 | + } | |
| 45 | + | |
| 46 | + @Override | |
| 47 | + @Transactional(rollbackFor = Exception.class) // 添加事务,异常则回滚所有导入 | |
| 48 | + public InfraStudentImportRespVO importStudentList(List<InfraStudentImportExcelVO> importList) { | |
| 49 | + if (CollUtil.isEmpty(importList)) { | |
| 50 | + return InfraStudentImportRespVO.builder() | |
| 51 | + .successCount(0).failureCount(0).failureRows(new LinkedHashMap<>()).build(); | |
| 52 | + } | |
| 53 | + // 遍历,逐个创建 | |
| 54 | + InfraStudentImportRespVO respVO = InfraStudentImportRespVO.builder() | |
| 55 | + .successCount(0).failureCount(0).failureRows(new LinkedHashMap<>()).build(); | |
| 56 | + AtomicInteger index = new AtomicInteger(1); | |
| 57 | + importList.forEach(importItem -> { | |
| 58 | + int currentIndex = index.getAndIncrement(); | |
| 59 | + try { | |
| 60 | + createStudent(BeanUtils.toBean(importItem, InfraStudentSaveReqVO.class)); | |
| 61 | + respVO.setSuccessCount(respVO.getSuccessCount() + 1); | |
| 62 | + } catch (Exception ex) { | |
| 63 | + respVO.getFailureRows().put(currentIndex, ex.getMessage()); | |
| 64 | + } | |
| 65 | + }); | |
| 66 | + respVO.setFailureCount(respVO.getFailureRows().size()); | |
| 67 | + return respVO; | |
| 68 | + } | |
| 69 | + | |
| 70 | + @Override | |
| 71 | + public void updateStudent(InfraStudentSaveReqVO updateReqVO) { | |
| 72 | + // 校验存在 | |
| 73 | + validateStudentExists(updateReqVO.getId()); | |
| 74 | + // 更新 | |
| 75 | + InfraStudentDO updateObj = BeanUtils.toBean(updateReqVO, InfraStudentDO.class); | |
| 76 | + studentMapper.updateById(updateObj); | |
| 77 | + } | |
| 78 | + | |
| 79 | + @Override | |
| 80 | + public void deleteStudent(Long id) { | |
| 81 | + // 校验存在 | |
| 82 | + validateStudentExists(id); | |
| 83 | + // 删除 | |
| 84 | + studentMapper.deleteById(id); | |
| 85 | + } | |
| 86 | + | |
| 87 | + @Override | |
| 88 | + public void deleteStudentListByIds(List<Long> ids) { | |
| 89 | + // 删除 | |
| 90 | + studentMapper.deleteByIds(ids); | |
| 91 | + } | |
| 92 | + | |
| 93 | + | |
| 94 | + private void validateStudentExists(Long id) { | |
| 95 | + if (studentMapper.selectById(id) == null) { | |
| 96 | + throw exception(STUDENT_NOT_EXISTS); | |
| 97 | + } | |
| 98 | + } | |
| 99 | + | |
| 100 | + @Override | |
| 101 | + public InfraStudentDO getStudent(Long id) { | |
| 102 | + return studentMapper.selectById(id); | |
| 103 | + } | |
| 104 | + | |
| 105 | + @Override | |
| 106 | + public PageResult<InfraStudentDO> getStudentPage(InfraStudentPageReqVO pageReqVO) { | |
| 107 | + return studentMapper.selectPage(pageReqVO); | |
| 108 | + } | |
| 109 | + | |
| 110 | +} | |
| 0 | 111 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one_importEnable/java/InfraStudentServiceImplTest
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.service.demo; | |
| 2 | + | |
| 3 | +import org.junit.jupiter.api.Disabled; | |
| 4 | +import org.junit.jupiter.api.Test; | |
| 5 | + | |
| 6 | +import jakarta.annotation.Resource; | |
| 7 | + | |
| 8 | +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; | |
| 9 | + | |
| 10 | +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; | |
| 11 | +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; | |
| 12 | +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper; | |
| 13 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 14 | + | |
| 15 | +import jakarta.annotation.Resource; | |
| 16 | +import org.springframework.context.annotation.Import; | |
| 17 | +import java.util.*; | |
| 18 | +import java.time.LocalDateTime; | |
| 19 | + | |
| 20 | +import static cn.hutool.core.util.RandomUtil.*; | |
| 21 | +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; | |
| 22 | +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*; | |
| 23 | +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; | |
| 24 | +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*; | |
| 25 | +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*; | |
| 26 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*; | |
| 27 | +import static org.junit.jupiter.api.Assertions.*; | |
| 28 | +import static org.mockito.Mockito.*; | |
| 29 | + | |
| 30 | +/** | |
| 31 | + * {@link InfraStudentServiceImpl} 的单元测试类 | |
| 32 | + * | |
| 33 | + * @author 芋道源码 | |
| 34 | + */ | |
| 35 | +@Import(InfraStudentServiceImpl.class) | |
| 36 | +public class InfraStudentServiceImplTest extends BaseDbUnitTest { | |
| 37 | + | |
| 38 | + @Resource | |
| 39 | + private InfraStudentServiceImpl studentService; | |
| 40 | + | |
| 41 | + @Resource | |
| 42 | + private InfraStudentMapper studentMapper; | |
| 43 | + | |
| 44 | + @Test | |
| 45 | + public void testCreateStudent_success() { | |
| 46 | + // 准备参数 | |
| 47 | + InfraStudentSaveReqVO createReqVO = randomPojo(InfraStudentSaveReqVO.class).setId(null); | |
| 48 | + | |
| 49 | + // 调用 | |
| 50 | + Long studentId = studentService.createStudent(createReqVO); | |
| 51 | + // 断言 | |
| 52 | + assertNotNull(studentId); | |
| 53 | + // 校验记录的属性是否正确 | |
| 54 | + InfraStudentDO student = studentMapper.selectById(studentId); | |
| 55 | + assertPojoEquals(createReqVO, student, "id"); | |
| 56 | + } | |
| 57 | + | |
| 58 | + @Test | |
| 59 | + public void testUpdateStudent_success() { | |
| 60 | + // mock 数据 | |
| 61 | + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class); | |
| 62 | + studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据 | |
| 63 | + // 准备参数 | |
| 64 | + InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class, o -> { | |
| 65 | + o.setId(dbStudent.getId()); // 设置更新的 ID | |
| 66 | + }); | |
| 67 | + | |
| 68 | + // 调用 | |
| 69 | + studentService.updateStudent(updateReqVO); | |
| 70 | + // 校验是否更新正确 | |
| 71 | + InfraStudentDO student = studentMapper.selectById(updateReqVO.getId()); // 获取最新的 | |
| 72 | + assertPojoEquals(updateReqVO, student); | |
| 73 | + } | |
| 74 | + | |
| 75 | + @Test | |
| 76 | + public void testUpdateStudent_notExists() { | |
| 77 | + // 准备参数 | |
| 78 | + InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class); | |
| 79 | + | |
| 80 | + // 调用, 并断言异常 | |
| 81 | + assertServiceException(() -> studentService.updateStudent(updateReqVO), STUDENT_NOT_EXISTS); | |
| 82 | + } | |
| 83 | + | |
| 84 | + @Test | |
| 85 | + public void testDeleteStudent_success() { | |
| 86 | + // mock 数据 | |
| 87 | + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class); | |
| 88 | + studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据 | |
| 89 | + // 准备参数 | |
| 90 | + Long id = dbStudent.getId(); | |
| 91 | + | |
| 92 | + // 调用 | |
| 93 | + studentService.deleteStudent(id); | |
| 94 | + // 校验数据不存在了 | |
| 95 | + assertNull(studentMapper.selectById(id)); | |
| 96 | + } | |
| 97 | + | |
| 98 | + @Test | |
| 99 | + public void testDeleteStudent_notExists() { | |
| 100 | + // 准备参数 | |
| 101 | + Long id = randomLongId(); | |
| 102 | + | |
| 103 | + // 调用, 并断言异常 | |
| 104 | + assertServiceException(() -> studentService.deleteStudent(id), STUDENT_NOT_EXISTS); | |
| 105 | + } | |
| 106 | + | |
| 107 | + @Test | |
| 108 | + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 | |
| 109 | + public void testGetStudentPage() { | |
| 110 | + // mock 数据 | |
| 111 | + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class, o -> { // 等会查询到 | |
| 112 | + o.setName(null); | |
| 113 | + o.setBirthday(null); | |
| 114 | + o.setSex(null); | |
| 115 | + o.setEnabled(null); | |
| 116 | + o.setCreateTime(null); | |
| 117 | + }); | |
| 118 | + studentMapper.insert(dbStudent); | |
| 119 | + // 测试 name 不匹配 | |
| 120 | + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setName(null))); | |
| 121 | + // 测试 birthday 不匹配 | |
| 122 | + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setBirthday(null))); | |
| 123 | + // 测试 sex 不匹配 | |
| 124 | + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setSex(null))); | |
| 125 | + // 测试 enabled 不匹配 | |
| 126 | + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setEnabled(null))); | |
| 127 | + // 测试 createTime 不匹配 | |
| 128 | + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setCreateTime(null))); | |
| 129 | + // 准备参数 | |
| 130 | + InfraStudentPageReqVO reqVO = new InfraStudentPageReqVO(); | |
| 131 | + reqVO.setName(null); | |
| 132 | + reqVO.setBirthday(null); | |
| 133 | + reqVO.setSex(null); | |
| 134 | + reqVO.setEnabled(null); | |
| 135 | + reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); | |
| 136 | + | |
| 137 | + // 调用 | |
| 138 | + PageResult<InfraStudentDO> pageResult = studentService.getStudentPage(reqVO); | |
| 139 | + // 断言 | |
| 140 | + assertEquals(1, pageResult.getTotal()); | |
| 141 | + assertEquals(1, pageResult.getList().size()); | |
| 142 | + assertPojoEquals(dbStudent, pageResult.getList().get(0)); | |
| 143 | + } | |
| 144 | + | |
| 145 | +} | |
| 0 | 146 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one_importEnable/sql/h2
0 → 100644
| 1 | +-- 将该建表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/create_tables.sql 文件里 | |
| 2 | +CREATE TABLE IF NOT EXISTS "infra_student" ( | |
| 3 | + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, | |
| 4 | + "name" varchar NOT NULL, | |
| 5 | + "description" varchar NOT NULL, | |
| 6 | + "birthday" varchar NOT NULL, | |
| 7 | + "sex" int NOT NULL, | |
| 8 | + "enabled" bit NOT NULL, | |
| 9 | + "avatar" varchar NOT NULL, | |
| 10 | + "video" varchar NOT NULL, | |
| 11 | + "memo" varchar NOT NULL, | |
| 12 | + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| 13 | + PRIMARY KEY ("id") | |
| 14 | +) COMMENT '学生表'; | |
| 15 | + | |
| 16 | +-- 将该删表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/clean.sql 文件里 | |
| 17 | +DELETE FROM "infra_student"; | |
| 0 | 18 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one_importEnable/sql/sql
0 → 100644
| 1 | +-- 菜单 SQL | |
| 2 | +INSERT INTO system_menu( | |
| 3 | + name, permission, type, sort, parent_id, | |
| 4 | + path, icon, component, status, component_name | |
| 5 | +) | |
| 6 | +VALUES ( | |
| 7 | + '学生管理', '', 2, 0, 888, | |
| 8 | + 'student', '', 'infra/demo/index', 0, 'InfraStudent' | |
| 9 | +); | |
| 10 | + | |
| 11 | +-- 按钮父菜单ID | |
| 12 | +SELECT @parentId := LAST_INSERT_ID(); | |
| 13 | + | |
| 14 | +-- 按钮 SQL | |
| 15 | +INSERT INTO system_menu( | |
| 16 | + name, permission, type, sort, parent_id, | |
| 17 | + path, icon, component, status | |
| 18 | +) | |
| 19 | +VALUES ( | |
| 20 | + '学生查询', 'infra:student:query', 3, 1, @parentId, | |
| 21 | + '', '', '', 0 | |
| 22 | +); | |
| 23 | +INSERT INTO system_menu( | |
| 24 | + name, permission, type, sort, parent_id, | |
| 25 | + path, icon, component, status | |
| 26 | +) | |
| 27 | +VALUES ( | |
| 28 | + '学生创建', 'infra:student:create', 3, 2, @parentId, | |
| 29 | + '', '', '', 0 | |
| 30 | +); | |
| 31 | +INSERT INTO system_menu( | |
| 32 | + name, permission, type, sort, parent_id, | |
| 33 | + path, icon, component, status | |
| 34 | +) | |
| 35 | +VALUES ( | |
| 36 | + '学生更新', 'infra:student:update', 3, 3, @parentId, | |
| 37 | + '', '', '', 0 | |
| 38 | +); | |
| 39 | +INSERT INTO system_menu( | |
| 40 | + name, permission, type, sort, parent_id, | |
| 41 | + path, icon, component, status | |
| 42 | +) | |
| 43 | +VALUES ( | |
| 44 | + '学生删除', 'infra:student:delete', 3, 4, @parentId, | |
| 45 | + '', '', '', 0 | |
| 46 | +); | |
| 47 | +INSERT INTO system_menu( | |
| 48 | + name, permission, type, sort, parent_id, | |
| 49 | + path, icon, component, status | |
| 50 | +) | |
| 51 | +VALUES ( | |
| 52 | + '学生导出', 'infra:student:export', 3, 5, @parentId, | |
| 53 | + '', '', '', 0 | |
| 54 | +); | |
| 55 | +INSERT INTO system_menu( | |
| 56 | + name, permission, type, sort, parent_id, | |
| 57 | + path, icon, component, status | |
| 58 | +) | |
| 59 | +VALUES ( | |
| 60 | + '学生导入', 'infra:student:import', 3, 6, @parentId, | |
| 61 | + '', '', '', 0 | |
| 62 | +); | |
| 0 | 63 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one_importEnable/ts/data
0 → 100644
| 1 | +import type { VbenFormSchema } from '#/adapter/form'; | |
| 2 | +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; | |
| 3 | +import type { InfraStudentApi } from '#/api/infra/demo'; | |
| 4 | + | |
| 5 | +import { DICT_TYPE } from '@vben/constants'; | |
| 6 | +import { getDictOptions } from '@vben/hooks'; | |
| 7 | + | |
| 8 | +import { getRangePickerDefaultProps } from '#/utils'; | |
| 9 | + | |
| 10 | +/** 新增/修改的表单 */ | |
| 11 | +export function useFormSchema(): VbenFormSchema[] { | |
| 12 | + return [ | |
| 13 | + { | |
| 14 | + fieldName: 'id', | |
| 15 | + component: 'Input', | |
| 16 | + dependencies: { | |
| 17 | + triggerFields: [''], | |
| 18 | + show: () => false, | |
| 19 | + }, | |
| 20 | + }, | |
| 21 | + { | |
| 22 | + fieldName: 'name', | |
| 23 | + label: '名字', | |
| 24 | + rules: 'required', | |
| 25 | + component: 'Input', | |
| 26 | + componentProps: { | |
| 27 | + placeholder: '请输入名字', | |
| 28 | + }, | |
| 29 | + }, | |
| 30 | + { | |
| 31 | + fieldName: 'description', | |
| 32 | + label: '简介', | |
| 33 | + rules: 'required', | |
| 34 | + component: 'Textarea', | |
| 35 | + componentProps: { | |
| 36 | + placeholder: '请输入简介', | |
| 37 | + }, | |
| 38 | + }, | |
| 39 | + { | |
| 40 | + fieldName: 'birthday', | |
| 41 | + label: '出生日期', | |
| 42 | + rules: 'required', | |
| 43 | + component: 'DatePicker', | |
| 44 | + componentProps: { | |
| 45 | + showTime: true, | |
| 46 | + format: 'YYYY-MM-DD HH:mm:ss', | |
| 47 | + valueFormat: 'x', | |
| 48 | + }, | |
| 49 | + }, | |
| 50 | + { | |
| 51 | + fieldName: 'sex', | |
| 52 | + label: '性别', | |
| 53 | + rules: 'required', | |
| 54 | + component: 'Select', | |
| 55 | + componentProps: { | |
| 56 | + options: getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number'), | |
| 57 | + placeholder: '请选择性别', | |
| 58 | + }, | |
| 59 | + }, | |
| 60 | + { | |
| 61 | + fieldName: 'enabled', | |
| 62 | + label: '是否有效', | |
| 63 | + rules: 'required', | |
| 64 | + component: 'RadioGroup', | |
| 65 | + componentProps: { | |
| 66 | + options: getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean'), | |
| 67 | + buttonStyle: 'solid', | |
| 68 | + optionType: 'button', | |
| 69 | + }, | |
| 70 | + }, | |
| 71 | + { | |
| 72 | + fieldName: 'avatar', | |
| 73 | + label: '头像', | |
| 74 | + rules: 'required', | |
| 75 | + component: 'ImageUpload', | |
| 76 | + }, | |
| 77 | + { | |
| 78 | + fieldName: 'video', | |
| 79 | + label: '附件', | |
| 80 | + rules: 'required', | |
| 81 | + component: 'FileUpload', | |
| 82 | + }, | |
| 83 | + { | |
| 84 | + fieldName: 'memo', | |
| 85 | + label: '备注', | |
| 86 | + rules: 'required', | |
| 87 | + component: 'RichTextarea', | |
| 88 | + }, | |
| 89 | + ]; | |
| 90 | +} | |
| 91 | + | |
| 92 | +/** 导入的表单 */ | |
| 93 | +export function useImportFormSchema(): VbenFormSchema[] { | |
| 94 | + return [ | |
| 95 | + { | |
| 96 | + fieldName: 'file', | |
| 97 | + label: '学生数据', | |
| 98 | + component: 'Upload', | |
| 99 | + rules: 'required', | |
| 100 | + help: '仅允许导入 xls、xlsx 格式文件', | |
| 101 | + }, | |
| 102 | + ]; | |
| 103 | +} | |
| 104 | + | |
| 105 | +/** 列表的搜索表单 */ | |
| 106 | +export function useGridFormSchema(): VbenFormSchema[] { | |
| 107 | + return [ | |
| 108 | + { | |
| 109 | + fieldName: 'name', | |
| 110 | + label: '名字', | |
| 111 | + component: 'Input', | |
| 112 | + componentProps: { | |
| 113 | + allowClear: true, | |
| 114 | + placeholder: '请输入名字', | |
| 115 | + }, | |
| 116 | + }, | |
| 117 | + { | |
| 118 | + fieldName: 'birthday', | |
| 119 | + label: '出生日期', | |
| 120 | + component: 'RangePicker', | |
| 121 | + componentProps: { | |
| 122 | + ...getRangePickerDefaultProps(), | |
| 123 | + allowClear: true, | |
| 124 | + }, | |
| 125 | + }, | |
| 126 | + { | |
| 127 | + fieldName: 'sex', | |
| 128 | + label: '性别', | |
| 129 | + component: 'Select', | |
| 130 | + componentProps: { | |
| 131 | + allowClear: true, | |
| 132 | + options: getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number'), | |
| 133 | + placeholder: '请选择性别', | |
| 134 | + }, | |
| 135 | + }, | |
| 136 | + { | |
| 137 | + fieldName: 'enabled', | |
| 138 | + label: '是否有效', | |
| 139 | + component: 'Select', | |
| 140 | + componentProps: { | |
| 141 | + allowClear: true, | |
| 142 | + options: getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean'), | |
| 143 | + placeholder: '请选择是否有效', | |
| 144 | + }, | |
| 145 | + }, | |
| 146 | + { | |
| 147 | + fieldName: 'createTime', | |
| 148 | + label: '创建时间', | |
| 149 | + component: 'RangePicker', | |
| 150 | + componentProps: { | |
| 151 | + ...getRangePickerDefaultProps(), | |
| 152 | + allowClear: true, | |
| 153 | + }, | |
| 154 | + }, | |
| 155 | + ]; | |
| 156 | +} | |
| 157 | + | |
| 158 | +/** 列表的字段 */ | |
| 159 | +export function useGridColumns(): VxeTableGridOptions<InfraStudentApi.Student>['columns'] { | |
| 160 | + return [ | |
| 161 | + { type: 'checkbox', width: 40 }, | |
| 162 | + { | |
| 163 | + field: 'id', | |
| 164 | + title: '编号', | |
| 165 | + minWidth: 120, | |
| 166 | + cellRender: { | |
| 167 | + name: 'CellDict', | |
| 168 | + props: { type: DICT_TYPE.$dictType.toUpperCase() }, | |
| 169 | + }, | |
| 170 | + }, | |
| 171 | + { | |
| 172 | + field: 'name', | |
| 173 | + title: '名字', | |
| 174 | + minWidth: 120, | |
| 175 | + cellRender: { | |
| 176 | + name: 'CellDict', | |
| 177 | + props: { type: DICT_TYPE.$dictType.toUpperCase() }, | |
| 178 | + }, | |
| 179 | + }, | |
| 180 | + { | |
| 181 | + field: 'description', | |
| 182 | + title: '简介', | |
| 183 | + minWidth: 120, | |
| 184 | + cellRender: { | |
| 185 | + name: 'CellDict', | |
| 186 | + props: { type: DICT_TYPE.$dictType.toUpperCase() }, | |
| 187 | + }, | |
| 188 | + }, | |
| 189 | + { | |
| 190 | + field: 'birthday', | |
| 191 | + title: '出生日期', | |
| 192 | + minWidth: 120, | |
| 193 | + formatter: 'formatDateTime', | |
| 194 | + }, | |
| 195 | + { | |
| 196 | + field: 'sex', | |
| 197 | + title: '性别', | |
| 198 | + minWidth: 120, | |
| 199 | + cellRender: { | |
| 200 | + name: 'CellDict', | |
| 201 | + props: { type: DICT_TYPE.SYSTEM_USER_SEX }, | |
| 202 | + }, | |
| 203 | + }, | |
| 204 | + { | |
| 205 | + field: 'enabled', | |
| 206 | + title: '是否有效', | |
| 207 | + minWidth: 120, | |
| 208 | + cellRender: { | |
| 209 | + name: 'CellDict', | |
| 210 | + props: { type: DICT_TYPE.INFRA_BOOLEAN_STRING }, | |
| 211 | + }, | |
| 212 | + }, | |
| 213 | + { | |
| 214 | + field: 'avatar', | |
| 215 | + title: '头像', | |
| 216 | + minWidth: 120, | |
| 217 | + cellRender: { | |
| 218 | + name: 'CellDict', | |
| 219 | + props: { type: DICT_TYPE.$dictType.toUpperCase() }, | |
| 220 | + }, | |
| 221 | + }, | |
| 222 | + { | |
| 223 | + field: 'video', | |
| 224 | + title: '附件', | |
| 225 | + minWidth: 120, | |
| 226 | + cellRender: { | |
| 227 | + name: 'CellDict', | |
| 228 | + props: { type: DICT_TYPE.$dictType.toUpperCase() }, | |
| 229 | + }, | |
| 230 | + }, | |
| 231 | + { | |
| 232 | + field: 'memo', | |
| 233 | + title: '备注', | |
| 234 | + minWidth: 120, | |
| 235 | + cellRender: { | |
| 236 | + name: 'CellDict', | |
| 237 | + props: { type: DICT_TYPE.$dictType.toUpperCase() }, | |
| 238 | + }, | |
| 239 | + }, | |
| 240 | + { | |
| 241 | + field: 'createTime', | |
| 242 | + title: '创建时间', | |
| 243 | + minWidth: 120, | |
| 244 | + formatter: 'formatDateTime', | |
| 245 | + }, | |
| 246 | + { | |
| 247 | + title: '操作', | |
| 248 | + width: 200, | |
| 249 | + fixed: 'right', | |
| 250 | + slots: { default: 'actions' }, | |
| 251 | + }, | |
| 252 | + ]; | |
| 253 | +} | |
| 254 | + | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one_importEnable/ts/index
0 → 100644
| 1 | +import type { PageParam, PageResult } from '@vben/request'; | |
| 2 | +import type { Dayjs } from 'dayjs'; | |
| 3 | + | |
| 4 | +import { requestClient } from '#/api/request'; | |
| 5 | + | |
| 6 | +export namespace InfraStudentApi { | |
| 7 | + /** 学生信息 */ | |
| 8 | + export interface Student { | |
| 9 | + id: number; // 编号 | |
| 10 | + name?: string; // 名字 | |
| 11 | + description?: string; // 简介 | |
| 12 | + birthday?: string | Dayjs; // 出生日期 | |
| 13 | + sex?: number; // 性别 | |
| 14 | + enabled?: boolean; // 是否有效 | |
| 15 | + avatar?: string; // 头像 | |
| 16 | + video?: string; // 附件 | |
| 17 | + memo?: string; // 备注 | |
| 18 | + } | |
| 19 | +} | |
| 20 | + | |
| 21 | +/** 查询学生分页 */ | |
| 22 | +export function getStudentPage(params: PageParam) { | |
| 23 | + return requestClient.get<PageResult<InfraStudentApi.Student>>( | |
| 24 | + '/infra/student/page', | |
| 25 | + { params }, | |
| 26 | + ); | |
| 27 | +} | |
| 28 | + | |
| 29 | +/** 查询学生详情 */ | |
| 30 | +export function getStudent(id: number) { | |
| 31 | + return requestClient.get<InfraStudentApi.Student>( | |
| 32 | + `/infra/student/get?id=${id}`, | |
| 33 | + ); | |
| 34 | +} | |
| 35 | + | |
| 36 | +/** 新增学生 */ | |
| 37 | +export function createStudent(data: InfraStudentApi.Student) { | |
| 38 | + return requestClient.post('/infra/student/create', data); | |
| 39 | +} | |
| 40 | + | |
| 41 | +/** 修改学生 */ | |
| 42 | +export function updateStudent(data: InfraStudentApi.Student) { | |
| 43 | + return requestClient.put('/infra/student/update', data); | |
| 44 | +} | |
| 45 | + | |
| 46 | +/** 删除学生 */ | |
| 47 | +export function deleteStudent(id: number) { | |
| 48 | + return requestClient.delete(`/infra/student/delete?id=${id}`); | |
| 49 | +} | |
| 50 | + | |
| 51 | +/** 批量删除学生 */ | |
| 52 | +export function deleteStudentList(ids: number[]) { | |
| 53 | + return requestClient.delete( | |
| 54 | + `/infra/student/delete-list?ids=${ids.join(',')}`, | |
| 55 | + ); | |
| 56 | +} | |
| 57 | + | |
| 58 | +/** 导出学生 */ | |
| 59 | +export function exportStudent(params: any) { | |
| 60 | + return requestClient.download('/infra/student/export-excel', { params }); | |
| 61 | +} | |
| 62 | + | |
| 63 | +/** 下载学生导入模板 */ | |
| 64 | +export function importStudentTemplate() { | |
| 65 | + return requestClient.download('/infra/student/get-import-template'); | |
| 66 | +} | |
| 67 | + | |
| 68 | +/** 导入学生 */ | |
| 69 | +export function importStudent(file: File) { | |
| 70 | + return requestClient.upload('/infra/student/import', { file }); | |
| 71 | +} | |
| 0 | 72 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one_importEnable/vue/form
0 → 100644
| 1 | +<script lang="ts" setup> | |
| 2 | +import type { InfraStudentApi } from '#/api/infra/demo'; | |
| 3 | + | |
| 4 | +import { computed, ref } from 'vue'; | |
| 5 | + | |
| 6 | +import { useVbenModal } from '@vben/common-ui'; | |
| 7 | + | |
| 8 | +import { message } from 'ant-design-vue'; | |
| 9 | + | |
| 10 | +import { useVbenForm } from '#/adapter/form'; | |
| 11 | +import { createStudent, getStudent, updateStudent } from '#/api/infra/demo'; | |
| 12 | +import { $t } from '#/locales'; | |
| 13 | + | |
| 14 | +import { useFormSchema } from '../data'; | |
| 15 | + | |
| 16 | +const emit = defineEmits(['success']); | |
| 17 | +const formData = ref<InfraStudentApi.Student>(); | |
| 18 | +const getTitle = computed(() => { | |
| 19 | + return formData.value?.id | |
| 20 | + ? $t('ui.actionTitle.edit', ['学生']) | |
| 21 | + : $t('ui.actionTitle.create', ['学生']); | |
| 22 | +}); | |
| 23 | + | |
| 24 | +const [Form, formApi] = useVbenForm({ | |
| 25 | + commonConfig: { | |
| 26 | + componentProps: { | |
| 27 | + class: 'w-full', | |
| 28 | + }, | |
| 29 | + formItemClass: 'col-span-2', | |
| 30 | + labelWidth: 80, | |
| 31 | + }, | |
| 32 | + layout: 'horizontal', | |
| 33 | + schema: useFormSchema(), | |
| 34 | + showDefaultActions: false, | |
| 35 | +}); | |
| 36 | + | |
| 37 | +const [Modal, modalApi] = useVbenModal({ | |
| 38 | + async onConfirm() { | |
| 39 | + const { valid } = await formApi.validate(); | |
| 40 | + if (!valid) { | |
| 41 | + return; | |
| 42 | + } | |
| 43 | + modalApi.lock(); | |
| 44 | + // 提交表单 | |
| 45 | + const data = (await formApi.getValues()) as InfraStudentApi.Student; | |
| 46 | + try { | |
| 47 | + await (formData.value?.id ? updateStudent(data) : createStudent(data)); | |
| 48 | + // 关闭并提示 | |
| 49 | + await modalApi.close(); | |
| 50 | + emit('success'); | |
| 51 | + message.success($t('ui.actionMessage.operationSuccess')); | |
| 52 | + } finally { | |
| 53 | + modalApi.unlock(); | |
| 54 | + } | |
| 55 | + }, | |
| 56 | + async onOpenChange(isOpen: boolean) { | |
| 57 | + if (!isOpen) { | |
| 58 | + formData.value = undefined; | |
| 59 | + return; | |
| 60 | + } | |
| 61 | + // 加载数据 | |
| 62 | + const data = modalApi.getData<InfraStudentApi.Student>(); | |
| 63 | + if (!data || !data.id) { | |
| 64 | + return; | |
| 65 | + } | |
| 66 | + modalApi.lock(); | |
| 67 | + try { | |
| 68 | + formData.value = await getStudent(data.id); | |
| 69 | + // 设置到 values | |
| 70 | + await formApi.setValues(formData.value); | |
| 71 | + } finally { | |
| 72 | + modalApi.unlock(); | |
| 73 | + } | |
| 74 | + }, | |
| 75 | +}); | |
| 76 | +</script> | |
| 77 | + | |
| 78 | +<template> | |
| 79 | + <Modal :title="getTitle"> | |
| 80 | + <Form class="mx-4" /> | |
| 81 | + </Modal> | |
| 82 | +</template> | |
| 0 | 83 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one_importEnable/vue/import-form
0 → 100644
| 1 | +<script lang="ts" setup> | |
| 2 | +import type { FileType } from 'ant-design-vue/es/upload/interface'; | |
| 3 | + | |
| 4 | +import { useVbenModal } from '@vben/common-ui'; | |
| 5 | +import { downloadFileFromBlobPart } from '@vben/utils'; | |
| 6 | + | |
| 7 | +import { Button, message, Upload } from 'ant-design-vue'; | |
| 8 | + | |
| 9 | +import { useVbenForm } from '#/adapter/form'; | |
| 10 | +import { importStudent, importStudentTemplate } from '#/api/infra/demo'; | |
| 11 | +import { $t } from '#/locales'; | |
| 12 | + | |
| 13 | +import { useImportFormSchema } from '../data'; | |
| 14 | + | |
| 15 | +const emit = defineEmits(['success']); | |
| 16 | + | |
| 17 | +const [Form, formApi] = useVbenForm({ | |
| 18 | + commonConfig: { | |
| 19 | + formItemClass: 'col-span-2', | |
| 20 | + labelWidth: 120, | |
| 21 | + }, | |
| 22 | + layout: 'horizontal', | |
| 23 | + schema: useImportFormSchema(), | |
| 24 | + showDefaultActions: false, | |
| 25 | +}); | |
| 26 | + | |
| 27 | +const [Modal, modalApi] = useVbenModal({ | |
| 28 | + async onConfirm() { | |
| 29 | + const { valid } = await formApi.validate(); | |
| 30 | + if (!valid) { | |
| 31 | + return; | |
| 32 | + } | |
| 33 | + modalApi.lock(); | |
| 34 | + // 提交表单 | |
| 35 | + const data = await formApi.getValues(); | |
| 36 | + try { | |
| 37 | + await importStudent(data.file); | |
| 38 | + // 关闭并提示 | |
| 39 | + await modalApi.close(); | |
| 40 | + emit('success'); | |
| 41 | + message.success($t('ui.actionMessage.operationSuccess')); | |
| 42 | + } finally { | |
| 43 | + modalApi.unlock(); | |
| 44 | + } | |
| 45 | + }, | |
| 46 | +}); | |
| 47 | + | |
| 48 | +/** 上传前 */ | |
| 49 | +function beforeUpload(file: FileType) { | |
| 50 | + formApi.setFieldValue('file', file); | |
| 51 | + return false; | |
| 52 | +} | |
| 53 | + | |
| 54 | +/** 下载模板 */ | |
| 55 | +async function handleDownload() { | |
| 56 | + const data = await importStudentTemplate(); | |
| 57 | + downloadFileFromBlobPart({ fileName: '学生导入模板.xls', source: data }); | |
| 58 | +} | |
| 59 | +</script> | |
| 60 | + | |
| 61 | +<template> | |
| 62 | + <Modal title="导入学生" class="w-1/3"> | |
| 63 | + <Form class="mx-4"> | |
| 64 | + <template #file> | |
| 65 | + <div class="w-full"> | |
| 66 | + <Upload | |
| 67 | + :max-count="1" | |
| 68 | + accept=".xls,.xlsx" | |
| 69 | + :before-upload="beforeUpload" | |
| 70 | + > | |
| 71 | + <Button type="primary"> 选择 Excel 文件 </Button> | |
| 72 | + </Upload> | |
| 73 | + </div> | |
| 74 | + </template> | |
| 75 | + </Form> | |
| 76 | + <template #prepend-footer> | |
| 77 | + <div class="flex flex-auto items-center"> | |
| 78 | + <Button @click="handleDownload"> 下载导入模板 </Button> | |
| 79 | + </div> | |
| 80 | + </template> | |
| 81 | + </Modal> | |
| 82 | +</template> | |
| 0 | 83 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one_importEnable/vue/index
0 → 100644
| 1 | +<script lang="ts" setup> | |
| 2 | +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; | |
| 3 | +import type { InfraStudentApi } from '#/api/infra/demo'; | |
| 4 | + | |
| 5 | +import { ref } from 'vue'; | |
| 6 | + | |
| 7 | +import { confirm, Page, useVbenModal } from '@vben/common-ui'; | |
| 8 | +import { downloadFileFromBlobPart, isEmpty } from '@vben/utils'; | |
| 9 | + | |
| 10 | +import { message } from 'ant-design-vue'; | |
| 11 | + | |
| 12 | +import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; | |
| 13 | +import { | |
| 14 | + deleteStudent, | |
| 15 | + deleteStudentList, | |
| 16 | + exportStudent, | |
| 17 | + getStudentPage, | |
| 18 | +} from '#/api/infra/demo'; | |
| 19 | +import StudentImport from './modules/import-form.vue'; | |
| 20 | +import { $t } from '#/locales'; | |
| 21 | + | |
| 22 | +import { useGridColumns, useGridFormSchema } from './data'; | |
| 23 | +import Form from './modules/form.vue'; | |
| 24 | + | |
| 25 | +const [FormModal, formModalApi] = useVbenModal({ | |
| 26 | + connectedComponent: Form, | |
| 27 | + destroyOnClose: true, | |
| 28 | +}); | |
| 29 | +const [ImportFormModal, importFormModalApi] = useVbenModal({ | |
| 30 | + connectedComponent: StudentImport, | |
| 31 | + destroyOnClose: true, | |
| 32 | +}); | |
| 33 | + | |
| 34 | +/** 导入学生 */ | |
| 35 | +function handleImport() { | |
| 36 | + importFormModalApi.open(); | |
| 37 | +} | |
| 38 | + | |
| 39 | +/** 刷新表格 */ | |
| 40 | +function handleRefresh() { | |
| 41 | + gridApi.query(); | |
| 42 | +} | |
| 43 | + | |
| 44 | +/** 创建学生 */ | |
| 45 | +function handleCreate() { | |
| 46 | + formModalApi.setData(null).open(); | |
| 47 | +} | |
| 48 | + | |
| 49 | +/** 编辑学生 */ | |
| 50 | +function handleEdit(row: InfraStudentApi.Student) { | |
| 51 | + formModalApi.setData(row).open(); | |
| 52 | +} | |
| 53 | + | |
| 54 | +/** 删除学生 */ | |
| 55 | +async function handleDelete(row: InfraStudentApi.Student) { | |
| 56 | + const hideLoading = message.loading({ | |
| 57 | + content: $t('ui.actionMessage.deleting', [row.id]), | |
| 58 | + duration: 0, | |
| 59 | + }); | |
| 60 | + try { | |
| 61 | + await deleteStudent(row.id!); | |
| 62 | + message.success($t('ui.actionMessage.deleteSuccess', [row.id])); | |
| 63 | + handleRefresh(); | |
| 64 | + } finally { | |
| 65 | + hideLoading(); | |
| 66 | + } | |
| 67 | +} | |
| 68 | + | |
| 69 | +/** 批量删除学生 */ | |
| 70 | +async function handleDeleteBatch() { | |
| 71 | + await confirm($t('ui.actionMessage.deleteBatchConfirm')); | |
| 72 | + const hideLoading = message.loading({ | |
| 73 | + content: $t('ui.actionMessage.deletingBatch'), | |
| 74 | + duration: 0, | |
| 75 | + }); | |
| 76 | + try { | |
| 77 | + await deleteStudentList(checkedIds.value); | |
| 78 | + checkedIds.value = []; | |
| 79 | + message.success($t('ui.actionMessage.deleteSuccess')); | |
| 80 | + handleRefresh(); | |
| 81 | + } finally { | |
| 82 | + hideLoading(); | |
| 83 | + } | |
| 84 | +} | |
| 85 | + | |
| 86 | +const checkedIds = ref<number[]>([]); | |
| 87 | +function handleRowCheckboxChange({ | |
| 88 | + records, | |
| 89 | +}: { | |
| 90 | + records: InfraStudentApi.Student[]; | |
| 91 | +}) { | |
| 92 | + checkedIds.value = records.map((item) => item.id!); | |
| 93 | +} | |
| 94 | + | |
| 95 | +/** 导出表格 */ | |
| 96 | +async function handleExport() { | |
| 97 | + const data = await exportStudent(await gridApi.formApi.getValues()); | |
| 98 | + downloadFileFromBlobPart({ fileName: '学生.xls', source: data }); | |
| 99 | +} | |
| 100 | + | |
| 101 | + | |
| 102 | +const [Grid, gridApi] = useVbenVxeGrid({ | |
| 103 | + formOptions: { | |
| 104 | + schema: useGridFormSchema(), | |
| 105 | + }, | |
| 106 | + gridOptions: { | |
| 107 | + columns: useGridColumns(), | |
| 108 | + height: 'auto', | |
| 109 | + keepSource: true, | |
| 110 | + proxyConfig: { | |
| 111 | + ajax: { | |
| 112 | + query: async ({ page }, formValues) => { | |
| 113 | + return await getStudentPage({ | |
| 114 | + pageNo: page.currentPage, | |
| 115 | + pageSize: page.pageSize, | |
| 116 | + ...formValues, | |
| 117 | + }); | |
| 118 | + }, | |
| 119 | + }, | |
| 120 | + }, | |
| 121 | + rowConfig: { | |
| 122 | + keyField: 'id', | |
| 123 | + isHover: true, | |
| 124 | + }, | |
| 125 | + toolbarConfig: { | |
| 126 | + refresh: true, | |
| 127 | + search: true, | |
| 128 | + }, | |
| 129 | + } as VxeTableGridOptions<InfraStudentApi.Student>, | |
| 130 | + gridEvents: { | |
| 131 | + checkboxAll: handleRowCheckboxChange, | |
| 132 | + checkboxChange: handleRowCheckboxChange, | |
| 133 | + }, | |
| 134 | +}); | |
| 135 | +</script> | |
| 136 | + | |
| 137 | +<template> | |
| 138 | + <Page auto-content-height> | |
| 139 | + <FormModal @success="handleRefresh" /> | |
| 140 | + <ImportFormModal @success="handleRefresh" /> | |
| 141 | + <Grid table-title="学生列表"> | |
| 142 | + <template #toolbar-tools> | |
| 143 | + <TableAction | |
| 144 | + :actions="[ | |
| 145 | + { | |
| 146 | + label: $t('ui.actionTitle.create', ['学生']), | |
| 147 | + type: 'primary', | |
| 148 | + icon: ACTION_ICON.ADD, | |
| 149 | + auth: ['infra:student:create'], | |
| 150 | + onClick: handleCreate, | |
| 151 | + }, | |
| 152 | + { | |
| 153 | + label: '导入', | |
| 154 | + type: 'primary', | |
| 155 | + auth: ['infra:student:import'], | |
| 156 | + onClick: handleImport, | |
| 157 | + }, | |
| 158 | + { | |
| 159 | + label: $t('ui.actionTitle.export'), | |
| 160 | + type: 'primary', | |
| 161 | + icon: ACTION_ICON.DOWNLOAD, | |
| 162 | + auth: ['infra:student:export'], | |
| 163 | + onClick: handleExport, | |
| 164 | + }, | |
| 165 | + { | |
| 166 | + label: $t('ui.actionTitle.deleteBatch'), | |
| 167 | + type: 'primary', | |
| 168 | + danger: true, | |
| 169 | + icon: ACTION_ICON.DELETE, | |
| 170 | + auth: ['infra:student:delete'], | |
| 171 | + disabled: isEmpty(checkedIds), | |
| 172 | + onClick: handleDeleteBatch, | |
| 173 | + }, | |
| 174 | + ]" | |
| 175 | + /> | |
| 176 | + </template> | |
| 177 | + <template #actions="{ row }"> | |
| 178 | + <TableAction | |
| 179 | + :actions="[ | |
| 180 | + { | |
| 181 | + label: $t('common.edit'), | |
| 182 | + type: 'link', | |
| 183 | + icon: ACTION_ICON.EDIT, | |
| 184 | + auth: ['infra:student:update'], | |
| 185 | + onClick: handleEdit.bind(null, row), | |
| 186 | + }, | |
| 187 | + { | |
| 188 | + label: $t('common.delete'), | |
| 189 | + type: 'link', | |
| 190 | + danger: true, | |
| 191 | + icon: ACTION_ICON.DELETE, | |
| 192 | + auth: ['infra:student:delete'], | |
| 193 | + popConfirm: { | |
| 194 | + title: $t('ui.actionMessage.deleteConfirm', [row.id]), | |
| 195 | + confirm: handleDelete.bind(null, row), | |
| 196 | + }, | |
| 197 | + }, | |
| 198 | + ]" | |
| 199 | + /> | |
| 200 | + </template> | |
| 201 | + </Grid> | |
| 202 | + </Page> | |
| 203 | +</template> | |
| 0 | 204 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one_importEnable/xml/InfraStudentMapper
0 → 100644
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | |
| 2 | +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | |
| 3 | +<mapper namespace="cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper"> | |
| 4 | + | |
| 5 | + <!-- | |
| 6 | + 一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。 | |
| 7 | + 无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。 | |
| 8 | + 代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。 | |
| 9 | + 文档可见:https://www.iocoder.cn/MyBatis/x-plugins/ | |
| 10 | + --> | |
| 11 | + | |
| 12 | +</mapper> | |
| 0 | 13 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one_importEnable/assert.json
0 → 100644
| 1 | +[ { | |
| 2 | + "contentPath" : "java/InfraStudentPageReqVO", | |
| 3 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentPageReqVO.java" | |
| 4 | +}, { | |
| 5 | + "contentPath" : "java/InfraStudentRespVO", | |
| 6 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentRespVO.java" | |
| 7 | +}, { | |
| 8 | + "contentPath" : "java/InfraStudentSaveReqVO", | |
| 9 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentSaveReqVO.java" | |
| 10 | +}, { | |
| 11 | + "contentPath" : "java/InfraStudentImportExcelVO", | |
| 12 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentImportExcelVO.java" | |
| 13 | +}, { | |
| 14 | + "contentPath" : "java/InfraStudentImportRespVO", | |
| 15 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentImportRespVO.java" | |
| 16 | +}, { | |
| 17 | + "contentPath" : "java/InfraStudentController", | |
| 18 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/InfraStudentController.java" | |
| 19 | +}, { | |
| 20 | + "contentPath" : "java/InfraStudentDO", | |
| 21 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentDO.java" | |
| 22 | +}, { | |
| 23 | + "contentPath" : "java/InfraStudentMapper", | |
| 24 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentMapper.java" | |
| 25 | +}, { | |
| 26 | + "contentPath" : "xml/InfraStudentMapper", | |
| 27 | + "filePath" : "yudao-module-infra/src/main/resources/mapper/demo/InfraStudentMapper.xml" | |
| 28 | +}, { | |
| 29 | + "contentPath" : "java/InfraStudentServiceImpl", | |
| 30 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImpl.java" | |
| 31 | +}, { | |
| 32 | + "contentPath" : "java/InfraStudentService", | |
| 33 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentService.java" | |
| 34 | +}, { | |
| 35 | + "contentPath" : "java/InfraStudentServiceImplTest", | |
| 36 | + "filePath" : "yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImplTest.java" | |
| 37 | +}, { | |
| 38 | + "contentPath" : "java/ErrorCodeConstants_手动操作", | |
| 39 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants_手动操作.java" | |
| 40 | +}, { | |
| 41 | + "contentPath" : "sql/sql", | |
| 42 | + "filePath" : "sql/sql.sql" | |
| 43 | +}, { | |
| 44 | + "contentPath" : "sql/h2", | |
| 45 | + "filePath" : "sql/h2.sql" | |
| 46 | +}, { | |
| 47 | + "contentPath" : "vue/index", | |
| 48 | + "filePath" : "yudao-ui-admin-vben/src/views/infra/demo/index.vue" | |
| 49 | +}, { | |
| 50 | + "contentPath" : "vue/form", | |
| 51 | + "filePath" : "yudao-ui-admin-vben/src/views/infra/demo/modules/form.vue" | |
| 52 | +}, { | |
| 53 | + "contentPath" : "vue/import-form", | |
| 54 | + "filePath" : "yudao-ui-admin-vben/src/views/infra/demo/modules/import-form.vue" | |
| 55 | +}, { | |
| 56 | + "contentPath" : "ts/index", | |
| 57 | + "filePath" : "yudao-ui-admin-vben/src/api/infra/demo/index.ts" | |
| 58 | +} ] | |
| 0 | 59 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one_importEnable/java/ErrorCodeConstants_手动操作
0 → 100644
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one_importEnable/java/InfraStudentController
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.controller.admin.demo; | |
| 2 | + | |
| 3 | +import org.springframework.web.bind.annotation.*; | |
| 4 | +import org.springframework.web.multipart.MultipartFile; | |
| 5 | +import jakarta.annotation.Resource; | |
| 6 | +import org.springframework.validation.annotation.Validated; | |
| 7 | +import org.springframework.security.access.prepost.PreAuthorize; | |
| 8 | +import io.swagger.v3.oas.annotations.tags.Tag; | |
| 9 | +import io.swagger.v3.oas.annotations.Parameter; | |
| 10 | +import io.swagger.v3.oas.annotations.Operation; | |
| 11 | + | |
| 12 | +import jakarta.validation.constraints.*; | |
| 13 | +import jakarta.validation.*; | |
| 14 | +import jakarta.servlet.http.*; | |
| 15 | +import java.util.*; | |
| 16 | +import java.io.IOException; | |
| 17 | + | |
| 18 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | |
| 19 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 20 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | |
| 21 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | |
| 22 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | |
| 23 | + | |
| 24 | +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; | |
| 25 | + | |
| 26 | +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; | |
| 27 | +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*; | |
| 28 | + | |
| 29 | +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; | |
| 30 | +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; | |
| 31 | +import cn.iocoder.yudao.module.infra.service.demo.InfraStudentService; | |
| 32 | + | |
| 33 | +@Tag(name = "管理后台 - 学生") | |
| 34 | +@RestController | |
| 35 | +@RequestMapping("/infra/student") | |
| 36 | +@Validated | |
| 37 | +public class InfraStudentController { | |
| 38 | + | |
| 39 | + @Resource | |
| 40 | + private InfraStudentService studentService; | |
| 41 | + | |
| 42 | + @PostMapping("/create") | |
| 43 | + @Operation(summary = "创建学生") | |
| 44 | + @PreAuthorize("@ss.hasPermission('infra:student:create')") | |
| 45 | + public CommonResult<Long> createStudent(@Valid @RequestBody InfraStudentSaveReqVO createReqVO) { | |
| 46 | + return success(studentService.createStudent(createReqVO)); | |
| 47 | + } | |
| 48 | + | |
| 49 | + @PutMapping("/update") | |
| 50 | + @Operation(summary = "更新学生") | |
| 51 | + @PreAuthorize("@ss.hasPermission('infra:student:update')") | |
| 52 | + public CommonResult<Boolean> updateStudent(@Valid @RequestBody InfraStudentSaveReqVO updateReqVO) { | |
| 53 | + studentService.updateStudent(updateReqVO); | |
| 54 | + return success(true); | |
| 55 | + } | |
| 56 | + | |
| 57 | + @DeleteMapping("/delete") | |
| 58 | + @Operation(summary = "删除学生") | |
| 59 | + @Parameter(name = "id", description = "编号", required = true) | |
| 60 | + @PreAuthorize("@ss.hasPermission('infra:student:delete')") | |
| 61 | + public CommonResult<Boolean> deleteStudent(@RequestParam("id") Long id) { | |
| 62 | + studentService.deleteStudent(id); | |
| 63 | + return success(true); | |
| 64 | + } | |
| 65 | + | |
| 66 | + @DeleteMapping("/delete-list") | |
| 67 | + @Parameter(name = "ids", description = "编号", required = true) | |
| 68 | + @Operation(summary = "批量删除学生") | |
| 69 | + @PreAuthorize("@ss.hasPermission('infra:student:delete')") | |
| 70 | + public CommonResult<Boolean> deleteStudentList(@RequestParam("ids") List<Long> ids) { | |
| 71 | + studentService.deleteStudentListByIds(ids); | |
| 72 | + return success(true); | |
| 73 | + } | |
| 74 | + | |
| 75 | + @GetMapping("/get") | |
| 76 | + @Operation(summary = "获得学生") | |
| 77 | + @Parameter(name = "id", description = "编号", required = true, example = "1024") | |
| 78 | + @PreAuthorize("@ss.hasPermission('infra:student:query')") | |
| 79 | + public CommonResult<InfraStudentRespVO> getStudent(@RequestParam("id") Long id) { | |
| 80 | + InfraStudentDO student = studentService.getStudent(id); | |
| 81 | + return success(BeanUtils.toBean(student, InfraStudentRespVO.class)); | |
| 82 | + } | |
| 83 | + | |
| 84 | + @GetMapping("/page") | |
| 85 | + @Operation(summary = "获得学生分页") | |
| 86 | + @PreAuthorize("@ss.hasPermission('infra:student:query')") | |
| 87 | + public CommonResult<PageResult<InfraStudentRespVO>> getStudentPage(@Valid InfraStudentPageReqVO pageReqVO) { | |
| 88 | + PageResult<InfraStudentDO> pageResult = studentService.getStudentPage(pageReqVO); | |
| 89 | + return success(BeanUtils.toBean(pageResult, InfraStudentRespVO.class)); | |
| 90 | + } | |
| 91 | + | |
| 92 | + @GetMapping("/export-excel") | |
| 93 | + @Operation(summary = "导出学生 Excel") | |
| 94 | + @PreAuthorize("@ss.hasPermission('infra:student:export')") | |
| 95 | + @ApiAccessLog(operateType = EXPORT) | |
| 96 | + public void exportStudentExcel(@Valid InfraStudentPageReqVO pageReqVO, | |
| 97 | + HttpServletResponse response) throws IOException { | |
| 98 | + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); | |
| 99 | + List<InfraStudentDO> list = studentService.getStudentPage(pageReqVO).getList(); | |
| 100 | + // 导出 Excel | |
| 101 | + ExcelUtils.write(response, "学生.xls", "数据", InfraStudentRespVO.class, | |
| 102 | + BeanUtils.toBean(list, InfraStudentRespVO.class)); | |
| 103 | + } | |
| 104 | + | |
| 105 | + @GetMapping("/get-import-template") | |
| 106 | + @Operation(summary = "获得导入学生模板") | |
| 107 | + @PreAuthorize("@ss.hasPermission('infra:student:import')") | |
| 108 | + public void importTemplate(HttpServletResponse response) throws IOException { | |
| 109 | + ExcelUtils.write(response, "学生导入模板.xls", "数据", | |
| 110 | + InfraStudentImportExcelVO.class, Collections.emptyList()); | |
| 111 | + } | |
| 112 | + | |
| 113 | + @PostMapping("/import") | |
| 114 | + @Operation(summary = "导入学生") | |
| 115 | + @Parameter(name = "file", description = "Excel 文件", required = true) | |
| 116 | + @PreAuthorize("@ss.hasPermission('infra:student:import')") | |
| 117 | + public CommonResult<InfraStudentImportRespVO> importExcel(@RequestParam("file") MultipartFile file) throws Exception { | |
| 118 | + List<InfraStudentImportExcelVO> list = ExcelUtils.read(file, InfraStudentImportExcelVO.class); | |
| 119 | + return success(studentService.importStudentList(list)); | |
| 120 | + } | |
| 121 | + | |
| 122 | +} | |
| 0 | 123 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one_importEnable/java/InfraStudentDO
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.dal.dataobject.demo; | |
| 2 | + | |
| 3 | +import lombok.*; | |
| 4 | +import java.util.*; | |
| 5 | +import java.time.LocalDateTime; | |
| 6 | +import java.time.LocalDateTime; | |
| 7 | +import com.baomidou.mybatisplus.annotation.*; | |
| 8 | +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | |
| 9 | + | |
| 10 | +/** | |
| 11 | + * 学生 DO | |
| 12 | + * | |
| 13 | + * @author 芋道源码 | |
| 14 | + */ | |
| 15 | +@TableName("infra_student") | |
| 16 | +@KeySequence("infra_student_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 | |
| 17 | +@Data | |
| 18 | +@EqualsAndHashCode(callSuper = true) | |
| 19 | +@ToString(callSuper = true) | |
| 20 | +@Builder | |
| 21 | +@NoArgsConstructor | |
| 22 | +@AllArgsConstructor | |
| 23 | +public class InfraStudentDO extends BaseDO { | |
| 24 | + | |
| 25 | + /** | |
| 26 | + * 编号 | |
| 27 | + */ | |
| 28 | + @TableId | |
| 29 | + private Long id; | |
| 30 | + /** | |
| 31 | + * 名字 | |
| 32 | + */ | |
| 33 | + private String name; | |
| 34 | + /** | |
| 35 | + * 简介 | |
| 36 | + */ | |
| 37 | + private String description; | |
| 38 | + /** | |
| 39 | + * 出生日期 | |
| 40 | + */ | |
| 41 | + private LocalDateTime birthday; | |
| 42 | + /** | |
| 43 | + * 性别 | |
| 44 | + * | |
| 45 | + * 枚举 {@link TODO system_user_sex 对应的类} | |
| 46 | + */ | |
| 47 | + private Integer sex; | |
| 48 | + /** | |
| 49 | + * 是否有效 | |
| 50 | + * | |
| 51 | + * 枚举 {@link TODO infra_boolean_string 对应的类} | |
| 52 | + */ | |
| 53 | + private Boolean enabled; | |
| 54 | + /** | |
| 55 | + * 头像 | |
| 56 | + */ | |
| 57 | + private String avatar; | |
| 58 | + /** | |
| 59 | + * 附件 | |
| 60 | + */ | |
| 61 | + private String video; | |
| 62 | + /** | |
| 63 | + * 备注 | |
| 64 | + */ | |
| 65 | + private String memo; | |
| 66 | + | |
| 67 | + | |
| 68 | +} | |
| 0 | 69 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one_importEnable/java/InfraStudentImportExcelVO
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; | |
| 2 | + | |
| 3 | +import cn.idev.excel.annotation.ExcelProperty; | |
| 4 | +import lombok.AllArgsConstructor; | |
| 5 | +import lombok.Builder; | |
| 6 | +import lombok.Data; | |
| 7 | +import lombok.NoArgsConstructor; | |
| 8 | +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; | |
| 9 | +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * 学生 Excel 导入 VO | |
| 13 | + */ | |
| 14 | +@Data | |
| 15 | +@Builder | |
| 16 | +@AllArgsConstructor | |
| 17 | +@NoArgsConstructor | |
| 18 | +public class InfraStudentImportExcelVO { | |
| 19 | + | |
| 20 | + @ExcelProperty("名字") | |
| 21 | + private String name; | |
| 22 | + | |
| 23 | + @ExcelProperty("简介") | |
| 24 | + private String description; | |
| 25 | + | |
| 26 | + @ExcelProperty("出生日期") | |
| 27 | + private LocalDateTime birthday; | |
| 28 | + | |
| 29 | + @ExcelProperty(value = "性别", converter = DictConvert.class) | |
| 30 | + @DictFormat("system_user_sex") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 | |
| 31 | + private Integer sex; | |
| 32 | + | |
| 33 | + @ExcelProperty(value = "是否有效", converter = DictConvert.class) | |
| 34 | + @DictFormat("infra_boolean_string") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 | |
| 35 | + private Boolean enabled; | |
| 36 | + | |
| 37 | + @ExcelProperty("头像") | |
| 38 | + private String avatar; | |
| 39 | + | |
| 40 | + @ExcelProperty("附件") | |
| 41 | + private String video; | |
| 42 | + | |
| 43 | + @ExcelProperty("备注") | |
| 44 | + private String memo; | |
| 45 | + | |
| 46 | +} | |
| 0 | 47 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one_importEnable/java/InfraStudentImportRespVO
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; | |
| 2 | + | |
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 4 | +import lombok.Builder; | |
| 5 | +import lombok.Data; | |
| 6 | + | |
| 7 | +import java.util.Map; | |
| 8 | + | |
| 9 | +@Schema(description = "管理后台 - 学生导入 Response VO") | |
| 10 | +@Data | |
| 11 | +@Builder | |
| 12 | +public class InfraStudentImportRespVO { | |
| 13 | + | |
| 14 | + @Schema(description = "创建成功的数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") | |
| 15 | + private Integer successCount; | |
| 16 | + | |
| 17 | + @Schema(description = "导入失败的数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | |
| 18 | + private Integer failureCount; | |
| 19 | + | |
| 20 | + @Schema(description = "导入失败的数据集合,key 为行号,value 为失败原因", requiredMode = Schema.RequiredMode.REQUIRED) | |
| 21 | + private Map<Integer, String> failureRows; | |
| 22 | + | |
| 23 | +} | |
| 0 | 24 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one_importEnable/java/InfraStudentMapper
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.dal.mysql.demo; | |
| 2 | + | |
| 3 | +import java.util.*; | |
| 4 | + | |
| 5 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 6 | +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | |
| 7 | +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | |
| 8 | +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; | |
| 9 | +import org.apache.ibatis.annotations.Mapper; | |
| 10 | +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; | |
| 11 | + | |
| 12 | +/** | |
| 13 | + * 学生 Mapper | |
| 14 | + * | |
| 15 | + * @author 芋道源码 | |
| 16 | + */ | |
| 17 | +@Mapper | |
| 18 | +public interface InfraStudentMapper extends BaseMapperX<InfraStudentDO> { | |
| 19 | + | |
| 20 | + default PageResult<InfraStudentDO> selectPage(InfraStudentPageReqVO reqVO) { | |
| 21 | + return selectPage(reqVO, new LambdaQueryWrapperX<InfraStudentDO>() | |
| 22 | + .likeIfPresent(InfraStudentDO::getName, reqVO.getName()) | |
| 23 | + .eqIfPresent(InfraStudentDO::getBirthday, reqVO.getBirthday()) | |
| 24 | + .eqIfPresent(InfraStudentDO::getSex, reqVO.getSex()) | |
| 25 | + .eqIfPresent(InfraStudentDO::getEnabled, reqVO.getEnabled()) | |
| 26 | + .betweenIfPresent(InfraStudentDO::getCreateTime, reqVO.getCreateTime()) | |
| 27 | + .orderByDesc(InfraStudentDO::getId)); | |
| 28 | + } | |
| 29 | + | |
| 30 | +} | |
| 0 | 31 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one_importEnable/java/InfraStudentPageReqVO
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; | |
| 2 | + | |
| 3 | +import lombok.*; | |
| 4 | +import java.util.*; | |
| 5 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 6 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | |
| 7 | +import org.springframework.format.annotation.DateTimeFormat; | |
| 8 | +import java.time.LocalDateTime; | |
| 9 | + | |
| 10 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | |
| 11 | + | |
| 12 | +@Schema(description = "管理后台 - 学生分页 Request VO") | |
| 13 | +@Data | |
| 14 | +public class InfraStudentPageReqVO extends PageParam { | |
| 15 | + | |
| 16 | + @Schema(description = "名字", example = "芋头") | |
| 17 | + private String name; | |
| 18 | + | |
| 19 | + @Schema(description = "出生日期") | |
| 20 | + private LocalDateTime birthday; | |
| 21 | + | |
| 22 | + @Schema(description = "性别", example = "1") | |
| 23 | + private Integer sex; | |
| 24 | + | |
| 25 | + @Schema(description = "是否有效", example = "true") | |
| 26 | + private Boolean enabled; | |
| 27 | + | |
| 28 | + @Schema(description = "创建时间") | |
| 29 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 30 | + private LocalDateTime[] createTime; | |
| 31 | + | |
| 32 | +} | |
| 0 | 33 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one_importEnable/java/InfraStudentRespVO
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; | |
| 2 | + | |
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 4 | +import lombok.*; | |
| 5 | +import java.util.*; | |
| 6 | +import org.springframework.format.annotation.DateTimeFormat; | |
| 7 | +import java.time.LocalDateTime; | |
| 8 | +import cn.idev.excel.annotation.*; | |
| 9 | +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; | |
| 10 | +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; | |
| 11 | + | |
| 12 | +@Schema(description = "管理后台 - 学生 Response VO") | |
| 13 | +@Data | |
| 14 | +@ExcelIgnoreUnannotated | |
| 15 | +public class InfraStudentRespVO { | |
| 16 | + | |
| 17 | + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | |
| 18 | + @ExcelProperty("编号") | |
| 19 | + private Long id; | |
| 20 | + | |
| 21 | + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头") | |
| 22 | + @ExcelProperty("名字") | |
| 23 | + private String name; | |
| 24 | + | |
| 25 | + @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍") | |
| 26 | + @ExcelProperty("简介") | |
| 27 | + private String description; | |
| 28 | + | |
| 29 | + @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED) | |
| 30 | + @ExcelProperty("出生日期") | |
| 31 | + private LocalDateTime birthday; | |
| 32 | + | |
| 33 | + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | |
| 34 | + @ExcelProperty(value = "性别", converter = DictConvert.class) | |
| 35 | + @DictFormat("system_user_sex") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 | |
| 36 | + private Integer sex; | |
| 37 | + | |
| 38 | + @Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") | |
| 39 | + @ExcelProperty(value = "是否有效", converter = DictConvert.class) | |
| 40 | + @DictFormat("infra_boolean_string") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 | |
| 41 | + private Boolean enabled; | |
| 42 | + | |
| 43 | + @Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") | |
| 44 | + @ExcelProperty("头像") | |
| 45 | + private String avatar; | |
| 46 | + | |
| 47 | + @Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4") | |
| 48 | + @ExcelProperty("附件") | |
| 49 | + private String video; | |
| 50 | + | |
| 51 | + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注") | |
| 52 | + @ExcelProperty("备注") | |
| 53 | + private String memo; | |
| 54 | + | |
| 55 | + @Schema(description = "创建时间") | |
| 56 | + @ExcelProperty("创建时间") | |
| 57 | + private LocalDateTime createTime; | |
| 58 | + | |
| 59 | +} | |
| 0 | 60 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one_importEnable/java/InfraStudentSaveReqVO
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; | |
| 2 | + | |
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 4 | +import lombok.*; | |
| 5 | +import java.util.*; | |
| 6 | +import jakarta.validation.constraints.*; | |
| 7 | +import org.springframework.format.annotation.DateTimeFormat; | |
| 8 | +import java.time.LocalDateTime; | |
| 9 | + | |
| 10 | +@Schema(description = "管理后台 - 学生新增/修改 Request VO") | |
| 11 | +@Data | |
| 12 | +public class InfraStudentSaveReqVO { | |
| 13 | + | |
| 14 | + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | |
| 15 | + private Long id; | |
| 16 | + | |
| 17 | + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头") | |
| 18 | + @NotEmpty(message = "名字不能为空") | |
| 19 | + private String name; | |
| 20 | + | |
| 21 | + @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍") | |
| 22 | + @NotEmpty(message = "简介不能为空") | |
| 23 | + private String description; | |
| 24 | + | |
| 25 | + @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED) | |
| 26 | + @NotNull(message = "出生日期不能为空") | |
| 27 | + private LocalDateTime birthday; | |
| 28 | + | |
| 29 | + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | |
| 30 | + @NotNull(message = "性别不能为空") | |
| 31 | + private Integer sex; | |
| 32 | + | |
| 33 | + @Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") | |
| 34 | + @NotNull(message = "是否有效不能为空") | |
| 35 | + private Boolean enabled; | |
| 36 | + | |
| 37 | + @Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") | |
| 38 | + @NotEmpty(message = "头像不能为空") | |
| 39 | + private String avatar; | |
| 40 | + | |
| 41 | + @Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4") | |
| 42 | + @NotEmpty(message = "附件不能为空") | |
| 43 | + private String video; | |
| 44 | + | |
| 45 | + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注") | |
| 46 | + @NotEmpty(message = "备注不能为空") | |
| 47 | + private String memo; | |
| 48 | + | |
| 49 | +} | |
| 0 | 50 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one_importEnable/java/InfraStudentService
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.service.demo; | |
| 2 | + | |
| 3 | +import java.util.*; | |
| 4 | +import jakarta.validation.*; | |
| 5 | +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; | |
| 6 | +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; | |
| 7 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 8 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | |
| 9 | + | |
| 10 | +/** | |
| 11 | + * 学生 Service 接口 | |
| 12 | + * | |
| 13 | + * @author 芋道源码 | |
| 14 | + */ | |
| 15 | +public interface InfraStudentService { | |
| 16 | + | |
| 17 | + /** | |
| 18 | + * 创建学生 | |
| 19 | + * | |
| 20 | + * @param createReqVO 创建信息 | |
| 21 | + * @return 编号 | |
| 22 | + */ | |
| 23 | + Long createStudent(@Valid InfraStudentSaveReqVO createReqVO); | |
| 24 | + | |
| 25 | + /** | |
| 26 | + * 导入学生 | |
| 27 | + * | |
| 28 | + * @param importList 导入信息 | |
| 29 | + * @return 导入结果 | |
| 30 | + */ | |
| 31 | + InfraStudentImportRespVO importStudentList(List<InfraStudentImportExcelVO> importList); | |
| 32 | + | |
| 33 | + /** | |
| 34 | + * 更新学生 | |
| 35 | + * | |
| 36 | + * @param updateReqVO 更新信息 | |
| 37 | + */ | |
| 38 | + void updateStudent(@Valid InfraStudentSaveReqVO updateReqVO); | |
| 39 | + | |
| 40 | + /** | |
| 41 | + * 删除学生 | |
| 42 | + * | |
| 43 | + * @param id 编号 | |
| 44 | + */ | |
| 45 | + void deleteStudent(Long id); | |
| 46 | + | |
| 47 | + /** | |
| 48 | + * 批量删除学生 | |
| 49 | + * | |
| 50 | + * @param ids 编号 | |
| 51 | + */ | |
| 52 | + void deleteStudentListByIds(List<Long> ids); | |
| 53 | + | |
| 54 | + /** | |
| 55 | + * 获得学生 | |
| 56 | + * | |
| 57 | + * @param id 编号 | |
| 58 | + * @return 学生 | |
| 59 | + */ | |
| 60 | + InfraStudentDO getStudent(Long id); | |
| 61 | + | |
| 62 | + /** | |
| 63 | + * 获得学生分页 | |
| 64 | + * | |
| 65 | + * @param pageReqVO 分页查询 | |
| 66 | + * @return 学生分页 | |
| 67 | + */ | |
| 68 | + PageResult<InfraStudentDO> getStudentPage(InfraStudentPageReqVO pageReqVO); | |
| 69 | + | |
| 70 | +} | |
| 0 | 71 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one_importEnable/java/InfraStudentServiceImpl
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.service.demo; | |
| 2 | + | |
| 3 | +import cn.hutool.core.collection.CollUtil; | |
| 4 | +import org.springframework.stereotype.Service; | |
| 5 | +import jakarta.annotation.Resource; | |
| 6 | +import org.springframework.validation.annotation.Validated; | |
| 7 | +import org.springframework.transaction.annotation.Transactional; | |
| 8 | + | |
| 9 | +import java.util.*; | |
| 10 | +import java.util.concurrent.atomic.AtomicInteger; | |
| 11 | +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; | |
| 12 | +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; | |
| 13 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 14 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | |
| 15 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | |
| 16 | + | |
| 17 | +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper; | |
| 18 | + | |
| 19 | +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | |
| 20 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | |
| 21 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.diffList; | |
| 22 | +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; | |
| 23 | + | |
| 24 | +/** | |
| 25 | + * 学生 Service 实现类 | |
| 26 | + * | |
| 27 | + * @author 芋道源码 | |
| 28 | + */ | |
| 29 | +@Service | |
| 30 | +@Validated | |
| 31 | +public class InfraStudentServiceImpl implements InfraStudentService { | |
| 32 | + | |
| 33 | + @Resource | |
| 34 | + private InfraStudentMapper studentMapper; | |
| 35 | + | |
| 36 | + @Override | |
| 37 | + public Long createStudent(InfraStudentSaveReqVO createReqVO) { | |
| 38 | + // 插入 | |
| 39 | + InfraStudentDO student = BeanUtils.toBean(createReqVO, InfraStudentDO.class); | |
| 40 | + studentMapper.insert(student); | |
| 41 | + | |
| 42 | + // 返回 | |
| 43 | + return student.getId(); | |
| 44 | + } | |
| 45 | + | |
| 46 | + @Override | |
| 47 | + @Transactional(rollbackFor = Exception.class) // 添加事务,异常则回滚所有导入 | |
| 48 | + public InfraStudentImportRespVO importStudentList(List<InfraStudentImportExcelVO> importList) { | |
| 49 | + if (CollUtil.isEmpty(importList)) { | |
| 50 | + return InfraStudentImportRespVO.builder() | |
| 51 | + .successCount(0).failureCount(0).failureRows(new LinkedHashMap<>()).build(); | |
| 52 | + } | |
| 53 | + // 遍历,逐个创建 | |
| 54 | + InfraStudentImportRespVO respVO = InfraStudentImportRespVO.builder() | |
| 55 | + .successCount(0).failureCount(0).failureRows(new LinkedHashMap<>()).build(); | |
| 56 | + AtomicInteger index = new AtomicInteger(1); | |
| 57 | + importList.forEach(importItem -> { | |
| 58 | + int currentIndex = index.getAndIncrement(); | |
| 59 | + try { | |
| 60 | + createStudent(BeanUtils.toBean(importItem, InfraStudentSaveReqVO.class)); | |
| 61 | + respVO.setSuccessCount(respVO.getSuccessCount() + 1); | |
| 62 | + } catch (Exception ex) { | |
| 63 | + respVO.getFailureRows().put(currentIndex, ex.getMessage()); | |
| 64 | + } | |
| 65 | + }); | |
| 66 | + respVO.setFailureCount(respVO.getFailureRows().size()); | |
| 67 | + return respVO; | |
| 68 | + } | |
| 69 | + | |
| 70 | + @Override | |
| 71 | + public void updateStudent(InfraStudentSaveReqVO updateReqVO) { | |
| 72 | + // 校验存在 | |
| 73 | + validateStudentExists(updateReqVO.getId()); | |
| 74 | + // 更新 | |
| 75 | + InfraStudentDO updateObj = BeanUtils.toBean(updateReqVO, InfraStudentDO.class); | |
| 76 | + studentMapper.updateById(updateObj); | |
| 77 | + } | |
| 78 | + | |
| 79 | + @Override | |
| 80 | + public void deleteStudent(Long id) { | |
| 81 | + // 校验存在 | |
| 82 | + validateStudentExists(id); | |
| 83 | + // 删除 | |
| 84 | + studentMapper.deleteById(id); | |
| 85 | + } | |
| 86 | + | |
| 87 | + @Override | |
| 88 | + public void deleteStudentListByIds(List<Long> ids) { | |
| 89 | + // 删除 | |
| 90 | + studentMapper.deleteByIds(ids); | |
| 91 | + } | |
| 92 | + | |
| 93 | + | |
| 94 | + private void validateStudentExists(Long id) { | |
| 95 | + if (studentMapper.selectById(id) == null) { | |
| 96 | + throw exception(STUDENT_NOT_EXISTS); | |
| 97 | + } | |
| 98 | + } | |
| 99 | + | |
| 100 | + @Override | |
| 101 | + public InfraStudentDO getStudent(Long id) { | |
| 102 | + return studentMapper.selectById(id); | |
| 103 | + } | |
| 104 | + | |
| 105 | + @Override | |
| 106 | + public PageResult<InfraStudentDO> getStudentPage(InfraStudentPageReqVO pageReqVO) { | |
| 107 | + return studentMapper.selectPage(pageReqVO); | |
| 108 | + } | |
| 109 | + | |
| 110 | +} | |
| 0 | 111 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one_importEnable/java/InfraStudentServiceImplTest
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.service.demo; | |
| 2 | + | |
| 3 | +import org.junit.jupiter.api.Disabled; | |
| 4 | +import org.junit.jupiter.api.Test; | |
| 5 | + | |
| 6 | +import jakarta.annotation.Resource; | |
| 7 | + | |
| 8 | +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; | |
| 9 | + | |
| 10 | +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; | |
| 11 | +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; | |
| 12 | +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper; | |
| 13 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 14 | + | |
| 15 | +import jakarta.annotation.Resource; | |
| 16 | +import org.springframework.context.annotation.Import; | |
| 17 | +import java.util.*; | |
| 18 | +import java.time.LocalDateTime; | |
| 19 | + | |
| 20 | +import static cn.hutool.core.util.RandomUtil.*; | |
| 21 | +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; | |
| 22 | +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*; | |
| 23 | +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; | |
| 24 | +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*; | |
| 25 | +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*; | |
| 26 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*; | |
| 27 | +import static org.junit.jupiter.api.Assertions.*; | |
| 28 | +import static org.mockito.Mockito.*; | |
| 29 | + | |
| 30 | +/** | |
| 31 | + * {@link InfraStudentServiceImpl} 的单元测试类 | |
| 32 | + * | |
| 33 | + * @author 芋道源码 | |
| 34 | + */ | |
| 35 | +@Import(InfraStudentServiceImpl.class) | |
| 36 | +public class InfraStudentServiceImplTest extends BaseDbUnitTest { | |
| 37 | + | |
| 38 | + @Resource | |
| 39 | + private InfraStudentServiceImpl studentService; | |
| 40 | + | |
| 41 | + @Resource | |
| 42 | + private InfraStudentMapper studentMapper; | |
| 43 | + | |
| 44 | + @Test | |
| 45 | + public void testCreateStudent_success() { | |
| 46 | + // 准备参数 | |
| 47 | + InfraStudentSaveReqVO createReqVO = randomPojo(InfraStudentSaveReqVO.class).setId(null); | |
| 48 | + | |
| 49 | + // 调用 | |
| 50 | + Long studentId = studentService.createStudent(createReqVO); | |
| 51 | + // 断言 | |
| 52 | + assertNotNull(studentId); | |
| 53 | + // 校验记录的属性是否正确 | |
| 54 | + InfraStudentDO student = studentMapper.selectById(studentId); | |
| 55 | + assertPojoEquals(createReqVO, student, "id"); | |
| 56 | + } | |
| 57 | + | |
| 58 | + @Test | |
| 59 | + public void testUpdateStudent_success() { | |
| 60 | + // mock 数据 | |
| 61 | + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class); | |
| 62 | + studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据 | |
| 63 | + // 准备参数 | |
| 64 | + InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class, o -> { | |
| 65 | + o.setId(dbStudent.getId()); // 设置更新的 ID | |
| 66 | + }); | |
| 67 | + | |
| 68 | + // 调用 | |
| 69 | + studentService.updateStudent(updateReqVO); | |
| 70 | + // 校验是否更新正确 | |
| 71 | + InfraStudentDO student = studentMapper.selectById(updateReqVO.getId()); // 获取最新的 | |
| 72 | + assertPojoEquals(updateReqVO, student); | |
| 73 | + } | |
| 74 | + | |
| 75 | + @Test | |
| 76 | + public void testUpdateStudent_notExists() { | |
| 77 | + // 准备参数 | |
| 78 | + InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class); | |
| 79 | + | |
| 80 | + // 调用, 并断言异常 | |
| 81 | + assertServiceException(() -> studentService.updateStudent(updateReqVO), STUDENT_NOT_EXISTS); | |
| 82 | + } | |
| 83 | + | |
| 84 | + @Test | |
| 85 | + public void testDeleteStudent_success() { | |
| 86 | + // mock 数据 | |
| 87 | + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class); | |
| 88 | + studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据 | |
| 89 | + // 准备参数 | |
| 90 | + Long id = dbStudent.getId(); | |
| 91 | + | |
| 92 | + // 调用 | |
| 93 | + studentService.deleteStudent(id); | |
| 94 | + // 校验数据不存在了 | |
| 95 | + assertNull(studentMapper.selectById(id)); | |
| 96 | + } | |
| 97 | + | |
| 98 | + @Test | |
| 99 | + public void testDeleteStudent_notExists() { | |
| 100 | + // 准备参数 | |
| 101 | + Long id = randomLongId(); | |
| 102 | + | |
| 103 | + // 调用, 并断言异常 | |
| 104 | + assertServiceException(() -> studentService.deleteStudent(id), STUDENT_NOT_EXISTS); | |
| 105 | + } | |
| 106 | + | |
| 107 | + @Test | |
| 108 | + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 | |
| 109 | + public void testGetStudentPage() { | |
| 110 | + // mock 数据 | |
| 111 | + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class, o -> { // 等会查询到 | |
| 112 | + o.setName(null); | |
| 113 | + o.setBirthday(null); | |
| 114 | + o.setSex(null); | |
| 115 | + o.setEnabled(null); | |
| 116 | + o.setCreateTime(null); | |
| 117 | + }); | |
| 118 | + studentMapper.insert(dbStudent); | |
| 119 | + // 测试 name 不匹配 | |
| 120 | + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setName(null))); | |
| 121 | + // 测试 birthday 不匹配 | |
| 122 | + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setBirthday(null))); | |
| 123 | + // 测试 sex 不匹配 | |
| 124 | + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setSex(null))); | |
| 125 | + // 测试 enabled 不匹配 | |
| 126 | + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setEnabled(null))); | |
| 127 | + // 测试 createTime 不匹配 | |
| 128 | + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setCreateTime(null))); | |
| 129 | + // 准备参数 | |
| 130 | + InfraStudentPageReqVO reqVO = new InfraStudentPageReqVO(); | |
| 131 | + reqVO.setName(null); | |
| 132 | + reqVO.setBirthday(null); | |
| 133 | + reqVO.setSex(null); | |
| 134 | + reqVO.setEnabled(null); | |
| 135 | + reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); | |
| 136 | + | |
| 137 | + // 调用 | |
| 138 | + PageResult<InfraStudentDO> pageResult = studentService.getStudentPage(reqVO); | |
| 139 | + // 断言 | |
| 140 | + assertEquals(1, pageResult.getTotal()); | |
| 141 | + assertEquals(1, pageResult.getList().size()); | |
| 142 | + assertPojoEquals(dbStudent, pageResult.getList().get(0)); | |
| 143 | + } | |
| 144 | + | |
| 145 | +} | |
| 0 | 146 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one_importEnable/sql/h2
0 → 100644
| 1 | +-- 将该建表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/create_tables.sql 文件里 | |
| 2 | +CREATE TABLE IF NOT EXISTS "infra_student" ( | |
| 3 | + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, | |
| 4 | + "name" varchar NOT NULL, | |
| 5 | + "description" varchar NOT NULL, | |
| 6 | + "birthday" varchar NOT NULL, | |
| 7 | + "sex" int NOT NULL, | |
| 8 | + "enabled" bit NOT NULL, | |
| 9 | + "avatar" varchar NOT NULL, | |
| 10 | + "video" varchar NOT NULL, | |
| 11 | + "memo" varchar NOT NULL, | |
| 12 | + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| 13 | + PRIMARY KEY ("id") | |
| 14 | +) COMMENT '学生表'; | |
| 15 | + | |
| 16 | +-- 将该删表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/clean.sql 文件里 | |
| 17 | +DELETE FROM "infra_student"; | |
| 0 | 18 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one_importEnable/sql/sql
0 → 100644
| 1 | +-- 菜单 SQL | |
| 2 | +INSERT INTO system_menu( | |
| 3 | + name, permission, type, sort, parent_id, | |
| 4 | + path, icon, component, status, component_name | |
| 5 | +) | |
| 6 | +VALUES ( | |
| 7 | + '学生管理', '', 2, 0, 888, | |
| 8 | + 'student', '', 'infra/demo/index', 0, 'InfraStudent' | |
| 9 | +); | |
| 10 | + | |
| 11 | +-- 按钮父菜单ID | |
| 12 | +SELECT @parentId := LAST_INSERT_ID(); | |
| 13 | + | |
| 14 | +-- 按钮 SQL | |
| 15 | +INSERT INTO system_menu( | |
| 16 | + name, permission, type, sort, parent_id, | |
| 17 | + path, icon, component, status | |
| 18 | +) | |
| 19 | +VALUES ( | |
| 20 | + '学生查询', 'infra:student:query', 3, 1, @parentId, | |
| 21 | + '', '', '', 0 | |
| 22 | +); | |
| 23 | +INSERT INTO system_menu( | |
| 24 | + name, permission, type, sort, parent_id, | |
| 25 | + path, icon, component, status | |
| 26 | +) | |
| 27 | +VALUES ( | |
| 28 | + '学生创建', 'infra:student:create', 3, 2, @parentId, | |
| 29 | + '', '', '', 0 | |
| 30 | +); | |
| 31 | +INSERT INTO system_menu( | |
| 32 | + name, permission, type, sort, parent_id, | |
| 33 | + path, icon, component, status | |
| 34 | +) | |
| 35 | +VALUES ( | |
| 36 | + '学生更新', 'infra:student:update', 3, 3, @parentId, | |
| 37 | + '', '', '', 0 | |
| 38 | +); | |
| 39 | +INSERT INTO system_menu( | |
| 40 | + name, permission, type, sort, parent_id, | |
| 41 | + path, icon, component, status | |
| 42 | +) | |
| 43 | +VALUES ( | |
| 44 | + '学生删除', 'infra:student:delete', 3, 4, @parentId, | |
| 45 | + '', '', '', 0 | |
| 46 | +); | |
| 47 | +INSERT INTO system_menu( | |
| 48 | + name, permission, type, sort, parent_id, | |
| 49 | + path, icon, component, status | |
| 50 | +) | |
| 51 | +VALUES ( | |
| 52 | + '学生导出', 'infra:student:export', 3, 5, @parentId, | |
| 53 | + '', '', '', 0 | |
| 54 | +); | |
| 55 | +INSERT INTO system_menu( | |
| 56 | + name, permission, type, sort, parent_id, | |
| 57 | + path, icon, component, status | |
| 58 | +) | |
| 59 | +VALUES ( | |
| 60 | + '学生导入', 'infra:student:import', 3, 6, @parentId, | |
| 61 | + '', '', '', 0 | |
| 62 | +); | |
| 0 | 63 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one_importEnable/ts/index
0 → 100644
| 1 | +import type { PageParam, PageResult } from '@vben/request'; | |
| 2 | +import type { Dayjs } from 'dayjs'; | |
| 3 | + | |
| 4 | +import { requestClient } from '#/api/request'; | |
| 5 | + | |
| 6 | +export namespace StudentApi { | |
| 7 | + /** 学生信息 */ | |
| 8 | + export interface Student { | |
| 9 | + id: number; // 编号 | |
| 10 | + name?: string; // 名字 | |
| 11 | + description?: string; // 简介 | |
| 12 | + birthday?: string | Dayjs; // 出生日期 | |
| 13 | + sex?: number; // 性别 | |
| 14 | + enabled?: boolean; // 是否有效 | |
| 15 | + avatar?: string; // 头像 | |
| 16 | + video?: string; // 附件 | |
| 17 | + memo?: string; // 备注 | |
| 18 | + } | |
| 19 | +} | |
| 20 | + | |
| 21 | +/** 查询学生分页 */ | |
| 22 | +export function getStudentPage(params: PageParam) { | |
| 23 | + return requestClient.get<PageResult<StudentApi.Student>>('/infra/student/page', { params }); | |
| 24 | +} | |
| 25 | + | |
| 26 | +/** 查询学生详情 */ | |
| 27 | +export function getStudent(id: number) { | |
| 28 | + return requestClient.get<StudentApi.Student>(`/infra/student/get?id=${id}`); | |
| 29 | +} | |
| 30 | + | |
| 31 | +/** 新增学生 */ | |
| 32 | +export function createStudent(data: StudentApi.Student) { | |
| 33 | + return requestClient.post('/infra/student/create', data); | |
| 34 | +} | |
| 35 | + | |
| 36 | +/** 修改学生 */ | |
| 37 | +export function updateStudent(data: StudentApi.Student) { | |
| 38 | + return requestClient.put('/infra/student/update', data); | |
| 39 | +} | |
| 40 | + | |
| 41 | +/** 删除学生 */ | |
| 42 | +export function deleteStudent(id: number) { | |
| 43 | + return requestClient.delete(`/infra/student/delete?id=${id}`); | |
| 44 | +} | |
| 45 | + | |
| 46 | +/** 批量删除学生 */ | |
| 47 | +export function deleteStudentList(ids: number[]) { | |
| 48 | + return requestClient.delete(`/infra/student/delete-list?ids=${ids.join(',')}`) | |
| 49 | +} | |
| 50 | + | |
| 51 | +/** 导出学生 */ | |
| 52 | +export function exportStudent(params: any) { | |
| 53 | + return requestClient.download('/infra/student/export-excel', { params }); | |
| 54 | +} | |
| 55 | + | |
| 56 | +/** 下载学生导入模板 */ | |
| 57 | +export function importStudentTemplate() { | |
| 58 | + return requestClient.download('/infra/student/get-import-template'); | |
| 59 | +} | |
| 60 | + | |
| 61 | +/** 导入学生 */ | |
| 62 | +export function importStudent(data: FormData) { | |
| 63 | + return requestClient.post('/infra/student/import', data); | |
| 64 | +} | |
| 0 | 65 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one_importEnable/vue/form
0 → 100644
| 1 | +<script lang="ts" setup> | |
| 2 | +import type { StudentApi } from '#/api/infra/student'; | |
| 3 | +import type { FormRules } from 'element-plus'; | |
| 4 | + | |
| 5 | +import { useVbenModal } from '@vben/common-ui'; | |
| 6 | +import { DICT_TYPE } from '@vben/constants'; | |
| 7 | +import { getDictOptions } from '@vben/hooks'; | |
| 8 | +import { Tinymce as RichTextarea } from '#/components/tinymce'; | |
| 9 | +import { ImageUpload, FileUpload } from "#/components/upload"; | |
| 10 | +import { ElMessage, ElTabs, ElTabPane, ElForm, ElFormItem, ElInput, ElSelect, ElOption, ElRadioGroup, ElRadio, ElCheckboxGroup, ElCheckbox, ElDatePicker, ElTreeSelect } from 'element-plus'; | |
| 11 | + | |
| 12 | +import { computed, ref, reactive } from 'vue'; | |
| 13 | +import { $t } from '#/locales'; | |
| 14 | +import { getStudent, createStudent, updateStudent } from '#/api/infra/student'; | |
| 15 | + | |
| 16 | +const emit = defineEmits(['success']); | |
| 17 | + | |
| 18 | +const formRef = ref(); | |
| 19 | +const formData = ref<Partial<StudentApi.Student>>({ | |
| 20 | + id: undefined, | |
| 21 | + name: undefined, | |
| 22 | + description: undefined, | |
| 23 | + birthday: undefined, | |
| 24 | + sex: undefined, | |
| 25 | + enabled: undefined, | |
| 26 | + avatar: undefined, | |
| 27 | + video: undefined, | |
| 28 | + memo: undefined, | |
| 29 | +}); | |
| 30 | +const rules = reactive<FormRules>({ | |
| 31 | + name: [{ required: true, message: '名字不能为空', trigger: 'blur' }], | |
| 32 | + description: [{ required: true, message: '简介不能为空', trigger: 'blur' }], | |
| 33 | + birthday: [{ required: true, message: '出生日期不能为空', trigger: 'blur' }], | |
| 34 | + sex: [{ required: true, message: '性别不能为空', trigger: 'change' }], | |
| 35 | + enabled: [{ required: true, message: '是否有效不能为空', trigger: 'blur' }], | |
| 36 | + avatar: [{ required: true, message: '头像不能为空', trigger: 'blur' }], | |
| 37 | + video: [{ required: true, message: '附件不能为空', trigger: 'blur' }], | |
| 38 | + memo: [{ required: true, message: '备注不能为空', trigger: 'blur' }], | |
| 39 | +}); | |
| 40 | +const getTitle = computed(() => { | |
| 41 | + return formData.value?.id | |
| 42 | + ? $t('ui.actionTitle.edit', ['学生']) | |
| 43 | + : $t('ui.actionTitle.create', ['学生']); | |
| 44 | +}); | |
| 45 | + | |
| 46 | + | |
| 47 | +/** 重置表单 */ | |
| 48 | +const resetForm = () => { | |
| 49 | + formData.value = { | |
| 50 | + id: undefined, | |
| 51 | + name: undefined, | |
| 52 | + description: undefined, | |
| 53 | + birthday: undefined, | |
| 54 | + sex: undefined, | |
| 55 | + enabled: undefined, | |
| 56 | + avatar: undefined, | |
| 57 | + video: undefined, | |
| 58 | + memo: undefined, | |
| 59 | + }; | |
| 60 | + formRef.value?.resetFields(); | |
| 61 | +} | |
| 62 | + | |
| 63 | + | |
| 64 | +const [Modal, modalApi] = useVbenModal({ | |
| 65 | + async onConfirm() { | |
| 66 | + await formRef.value?.validate(); | |
| 67 | + modalApi.lock(); | |
| 68 | + // 提交表单 | |
| 69 | + const data = formData.value as StudentApi.Student; | |
| 70 | + try { | |
| 71 | + await (formData.value?.id ? updateStudent(data) : createStudent(data)); | |
| 72 | + // 关闭并提示 | |
| 73 | + await modalApi.close(); | |
| 74 | + emit('success'); | |
| 75 | + ElMessage.success($t('ui.actionMessage.operationSuccess')); | |
| 76 | + } finally { | |
| 77 | + modalApi.unlock(); | |
| 78 | + } | |
| 79 | + }, | |
| 80 | + async onOpenChange(isOpen: boolean) { | |
| 81 | + if (!isOpen) { | |
| 82 | + resetForm() | |
| 83 | + return; | |
| 84 | + } | |
| 85 | + // 加载数据 | |
| 86 | + let data = modalApi.getData<StudentApi.Student>(); | |
| 87 | + if (!data) { | |
| 88 | + return; | |
| 89 | + } | |
| 90 | + if (data.id) { | |
| 91 | + modalApi.lock(); | |
| 92 | + try { | |
| 93 | + data = await getStudent(data.id); | |
| 94 | + } finally { | |
| 95 | + modalApi.unlock(); | |
| 96 | + } | |
| 97 | + } | |
| 98 | + formData.value = data; | |
| 99 | + }, | |
| 100 | +}); | |
| 101 | +</script> | |
| 102 | + | |
| 103 | +<template> | |
| 104 | + <Modal :title="getTitle"> | |
| 105 | + <el-form | |
| 106 | + ref="formRef" | |
| 107 | + :model="formData" | |
| 108 | + :rules="rules" | |
| 109 | + label-width="120px" | |
| 110 | + label-position="right" | |
| 111 | + > | |
| 112 | + <el-form-item label="名字" prop="name"> | |
| 113 | + <el-input v-model="formData.name" placeholder="请输入名字" /> | |
| 114 | + </el-form-item> | |
| 115 | + <el-form-item label="简介" prop="description"> | |
| 116 | + <el-input v-model="formData.description" type="textarea" placeholder="请输入简介" /> | |
| 117 | + </el-form-item> | |
| 118 | + <el-form-item label="出生日期" prop="birthday"> | |
| 119 | + <el-date-picker | |
| 120 | + v-model="formData.birthday" | |
| 121 | + value-format="x" | |
| 122 | + placeholder="选择出生日期" | |
| 123 | + /> | |
| 124 | + </el-form-item> | |
| 125 | + <el-form-item label="性别" prop="sex"> | |
| 126 | + <el-select v-model="formData.sex" placeholder="请选择性别"> | |
| 127 | + <el-option | |
| 128 | + v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')" | |
| 129 | + :key="dict.value" | |
| 130 | + :value="dict.value" | |
| 131 | + :label="dict.label" | |
| 132 | + /> | |
| 133 | + </el-select> | |
| 134 | + </el-form-item> | |
| 135 | + <el-form-item label="是否有效" prop="enabled"> | |
| 136 | + <el-radio-group v-model="formData.enabled"> | |
| 137 | + <el-radio | |
| 138 | + v-for="dict in getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean')" | |
| 139 | + :key="dict.value" | |
| 140 | + :label="dict.value" | |
| 141 | + > | |
| 142 | + {{ dict.label }} | |
| 143 | + </el-radio> | |
| 144 | + </el-radio-group> | |
| 145 | + </el-form-item> | |
| 146 | + <el-form-item label="头像" prop="avatar"> | |
| 147 | + <ImageUpload v-model="formData.avatar" /> | |
| 148 | + </el-form-item> | |
| 149 | + <el-form-item label="附件" prop="video"> | |
| 150 | + <FileUpload v-model="formData.video" /> | |
| 151 | + </el-form-item> | |
| 152 | + <el-form-item label="备注" prop="memo"> | |
| 153 | + <RichTextarea v-model="formData.memo" height="500px" /> | |
| 154 | + </el-form-item> | |
| 155 | + </el-form> | |
| 156 | + </Modal> | |
| 157 | +</template> | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one_importEnable/vue/import-form
0 → 100644
| 1 | +<script lang="ts" setup> | |
| 2 | +import { ref } from 'vue'; | |
| 3 | + | |
| 4 | +import { useVbenModal } from '@vben/common-ui'; | |
| 5 | +import { downloadFileFromBlobPart } from '@vben/utils'; | |
| 6 | + | |
| 7 | +import { ElButton, ElMessage, ElUpload } from 'element-plus'; | |
| 8 | + | |
| 9 | +import { importStudent, importStudentTemplate } from '#/api/infra/demo'; | |
| 10 | + | |
| 11 | +defineOptions({ name: 'StudentImport' }); | |
| 12 | + | |
| 13 | +const emit = defineEmits(['success']); | |
| 14 | +const fileRef = ref<File | null>(null); | |
| 15 | + | |
| 16 | +const [Modal, modalApi] = useVbenModal({ | |
| 17 | + async onConfirm() { | |
| 18 | + if (!fileRef.value) { | |
| 19 | + ElMessage.error('请上传文件'); | |
| 20 | + return; | |
| 21 | + } | |
| 22 | + modalApi.lock(); | |
| 23 | + try { | |
| 24 | + const formData = new FormData(); | |
| 25 | + formData.append('file', fileRef.value); | |
| 26 | + const response: any = await importStudent(formData); | |
| 27 | + const data = response?.data ?? response ?? {}; | |
| 28 | + let text = '导入成功数量:' + (data.successCount || 0) + ';导入失败数量:' + (data.failureCount || 0) + ';'; | |
| 29 | + if (data.failureRows) { | |
| 30 | + Object.keys(data.failureRows).forEach((rowNo) => { | |
| 31 | + text += '< 第' + rowNo + '行: ' + data.failureRows[rowNo] + ' >'; | |
| 32 | + }); | |
| 33 | + } | |
| 34 | + ElMessage.info(text); | |
| 35 | + await modalApi.close(); | |
| 36 | + emit('success'); | |
| 37 | + } finally { | |
| 38 | + modalApi.unlock(); | |
| 39 | + } | |
| 40 | + }, | |
| 41 | +}); | |
| 42 | + | |
| 43 | +/** 文件改变 */ | |
| 44 | +function handleChange(file: any) { | |
| 45 | + if (file.raw) { | |
| 46 | + fileRef.value = file.raw; | |
| 47 | + } | |
| 48 | +} | |
| 49 | + | |
| 50 | +/** 下载导入模板 */ | |
| 51 | +async function handleDownload() { | |
| 52 | + const data = await importStudentTemplate(); | |
| 53 | + downloadFileFromBlobPart({ fileName: '学生导入模板.xls', source: data }); | |
| 54 | +} | |
| 55 | +</script> | |
| 56 | + | |
| 57 | +<template> | |
| 58 | + <Modal title="导入学生" class="w-1/3"> | |
| 59 | + <div class="mx-4"> | |
| 60 | + <ElUpload | |
| 61 | + :limit="1" | |
| 62 | + accept=".xls,.xlsx" | |
| 63 | + :on-change="handleChange" | |
| 64 | + :auto-upload="false" | |
| 65 | + > | |
| 66 | + <ElButton type="primary"> 选择 Excel 文件 </ElButton> | |
| 67 | + </ElUpload> | |
| 68 | + </div> | |
| 69 | + <template #prepend-footer> | |
| 70 | + <div class="flex flex-auto items-center"> | |
| 71 | + <ElButton @click="handleDownload"> 下载导入模板 </ElButton> | |
| 72 | + </div> | |
| 73 | + </template> | |
| 74 | + </Modal> | |
| 75 | +</template> | |
| 0 | 76 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one_importEnable/vue/index
0 → 100644
| 1 | +<script lang="ts" setup> | |
| 2 | +import type { StudentApi } from '#/api/infra/student'; | |
| 3 | + | |
| 4 | +import { ref, h, reactive, onMounted, nextTick } from 'vue'; | |
| 5 | + | |
| 6 | +import { Page, useVbenModal } from '@vben/common-ui'; | |
| 7 | +import { DICT_TYPE } from '@vben/constants'; | |
| 8 | +import { getDictOptions } from '@vben/hooks'; | |
| 9 | +import { useTableToolbar, VbenVxeTableToolbar } from '@vben/plugins/vxe-table'; | |
| 10 | +import { cloneDeep, downloadFileFromBlobPart, formatDateTime } from '@vben/utils'; | |
| 11 | +import { ElButton, ElMessage, ElLoading, ElTabs, ElTabPane, ElPagination, ElForm, ElFormItem, ElDatePicker, ElSelect, ElOption, ElInput } from 'element-plus'; | |
| 12 | +import StudentForm from './modules/form.vue'; | |
| 13 | +import { Download, Plus, RefreshCw, Search, Trash2 } from '@vben/icons'; | |
| 14 | +import { ContentWrap } from '#/components/content-wrap'; | |
| 15 | +import { VxeColumn, VxeTable } from '#/adapter/vxe-table'; | |
| 16 | + | |
| 17 | + | |
| 18 | +import { $t } from '#/locales'; | |
| 19 | +import { isEmpty } from '@vben/utils'; | |
| 20 | +import { getStudentPage, deleteStudent, deleteStudentList, exportStudent } from '#/api/infra/student'; | |
| 21 | +import StudentImport from './modules/import-form.vue'; | |
| 22 | + | |
| 23 | + | |
| 24 | +const loading = ref(true) // 列表的加载中 | |
| 25 | +const list = ref<StudentApi.Student[]>([]) // 列表的数据 | |
| 26 | + | |
| 27 | +const total = ref(0) // 列表的总页数 | |
| 28 | +const queryParams = reactive({ | |
| 29 | + pageNo: 1, | |
| 30 | + pageSize: 10, | |
| 31 | + name: undefined, | |
| 32 | + birthday: undefined, | |
| 33 | + birthday: undefined, | |
| 34 | + sex: undefined, | |
| 35 | + enabled: undefined, | |
| 36 | + createTime: undefined, | |
| 37 | +}) | |
| 38 | +const queryFormRef = ref() // 搜索的表单 | |
| 39 | +const exportLoading = ref(false) // 导出的加载中 | |
| 40 | + | |
| 41 | +/** 查询列表 */ | |
| 42 | +const getList = async () => { | |
| 43 | + loading.value = true | |
| 44 | + try { | |
| 45 | + const params = cloneDeep(queryParams) as any; | |
| 46 | + if (params.birthday && Array.isArray(params.birthday)) { | |
| 47 | + params.birthday = (params.birthday as string[]).join(','); | |
| 48 | + } | |
| 49 | + if (params.createTime && Array.isArray(params.createTime)) { | |
| 50 | + params.createTime = (params.createTime as string[]).join(','); | |
| 51 | + } | |
| 52 | + const data = await getStudentPage(params) | |
| 53 | + list.value = data.list | |
| 54 | + total.value = data.total | |
| 55 | + } finally { | |
| 56 | + loading.value = false | |
| 57 | + } | |
| 58 | +} | |
| 59 | + | |
| 60 | +/** 搜索按钮操作 */ | |
| 61 | +function handleQuery() { | |
| 62 | + queryParams.pageNo = 1 | |
| 63 | + getList() | |
| 64 | +} | |
| 65 | + | |
| 66 | +/** 重置按钮操作 */ | |
| 67 | +function resetQuery() { | |
| 68 | + queryFormRef.value.resetFields() | |
| 69 | + handleQuery() | |
| 70 | +} | |
| 71 | + | |
| 72 | +const [FormModal, formModalApi] = useVbenModal({ | |
| 73 | + connectedComponent: StudentForm, | |
| 74 | + destroyOnClose: true, | |
| 75 | +}); | |
| 76 | +const [ImportFormModal, importFormModalApi] = useVbenModal({ | |
| 77 | + connectedComponent: StudentImport, | |
| 78 | + destroyOnClose: true, | |
| 79 | +}); | |
| 80 | + | |
| 81 | +/** 导入学生 */ | |
| 82 | +function handleImport() { | |
| 83 | + importFormModalApi.open(); | |
| 84 | +} | |
| 85 | + | |
| 86 | +/** 创建学生 */ | |
| 87 | +function handleCreate() { | |
| 88 | + formModalApi.setData(null).open(); | |
| 89 | +} | |
| 90 | + | |
| 91 | +/** 编辑学生 */ | |
| 92 | +function handleEdit(row: StudentApi.Student) { | |
| 93 | + formModalApi.setData(row).open(); | |
| 94 | +} | |
| 95 | + | |
| 96 | + | |
| 97 | +/** 删除学生 */ | |
| 98 | +async function handleDelete(row: StudentApi.Student) { | |
| 99 | + const loadingInstance = ElLoading.service({ | |
| 100 | + text: $t('ui.actionMessage.deleting', [row.id]), | |
| 101 | + }); | |
| 102 | + try { | |
| 103 | + await deleteStudent(row.id as number); | |
| 104 | + ElMessage.success($t('ui.actionMessage.deleteSuccess', [row.id])); | |
| 105 | + await getList(); | |
| 106 | + } finally { | |
| 107 | + loadingInstance.close(); | |
| 108 | + } | |
| 109 | +} | |
| 110 | + | |
| 111 | +/** 批量删除学生 */ | |
| 112 | +async function handleDeleteBatch() { | |
| 113 | + const loadingInstance = ElLoading.service({ | |
| 114 | + text: $t('ui.actionMessage.deleting'), | |
| 115 | + }); | |
| 116 | + try { | |
| 117 | + await deleteStudentList(checkedIds.value); | |
| 118 | + checkedIds.value = []; | |
| 119 | + ElMessage.success($t('ui.actionMessage.deleteSuccess')); | |
| 120 | + await getList(); | |
| 121 | + } finally { | |
| 122 | + loadingInstance.close(); | |
| 123 | + } | |
| 124 | +} | |
| 125 | + | |
| 126 | +const checkedIds = ref<number[]>([]) | |
| 127 | +function handleRowCheckboxChange({ | |
| 128 | + records, | |
| 129 | +}: { | |
| 130 | + records: StudentApi.Student[]; | |
| 131 | +}) { | |
| 132 | + checkedIds.value = records.map((item) => item.id!); | |
| 133 | +} | |
| 134 | + | |
| 135 | +/** 导出表格 */ | |
| 136 | +async function handleExport() { | |
| 137 | +try { | |
| 138 | + exportLoading.value = true; | |
| 139 | + const data = await exportStudent(queryParams); | |
| 140 | + downloadFileFromBlobPart({ fileName: '学生.xls', source: data }); | |
| 141 | +}finally { | |
| 142 | + exportLoading.value = false; | |
| 143 | +} | |
| 144 | +} | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | +/** 初始化 */ | |
| 149 | +const { hiddenSearchBar, tableToolbarRef, tableRef } = useTableToolbar(); | |
| 150 | +onMounted(() => { | |
| 151 | + getList(); | |
| 152 | +}); | |
| 153 | +</script> | |
| 154 | + | |
| 155 | +<template> | |
| 156 | + <Page auto-content-height> | |
| 157 | + <FormModal @success="getList" /> | |
| 158 | + <ImportFormModal @success="getList" /> | |
| 159 | + | |
| 160 | + <ContentWrap v-if="!hiddenSearchBar"> | |
| 161 | + <!-- 搜索工作栏 --> | |
| 162 | + <el-form | |
| 163 | + :model="queryParams" | |
| 164 | + ref="queryFormRef" | |
| 165 | + inline | |
| 166 | + > | |
| 167 | + <el-form-item label="名字"> | |
| 168 | + <el-input | |
| 169 | + v-model="queryParams.name" | |
| 170 | + placeholder="请输入名字" | |
| 171 | + clearable | |
| 172 | + @keyup.enter="handleQuery" | |
| 173 | + class="!w-[240px]" | |
| 174 | + /> | |
| 175 | + </el-form-item> | |
| 176 | + <el-form-item label="出生日期"> | |
| 177 | + <el-date-picker | |
| 178 | + v-model="queryParams.birthday" | |
| 179 | + value-format="YYYY-MM-DD" | |
| 180 | + placeholder="选择出生日期" | |
| 181 | + clearable | |
| 182 | + class="!w-[240px]" | |
| 183 | + /> | |
| 184 | + </el-form-item> | |
| 185 | + <el-form-item label="性别"> | |
| 186 | + <el-select | |
| 187 | + v-model="queryParams.sex" | |
| 188 | + placeholder="请选择性别" | |
| 189 | + clearable | |
| 190 | + class="!w-[240px]" | |
| 191 | + > | |
| 192 | + <el-option | |
| 193 | + v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')" | |
| 194 | + :key="dict.value" | |
| 195 | + :value="dict.value" | |
| 196 | + :label="dict.label" | |
| 197 | + /> | |
| 198 | + </el-select> | |
| 199 | + </el-form-item> | |
| 200 | + <el-form-item label="是否有效"> | |
| 201 | + <el-select | |
| 202 | + v-model="queryParams.enabled" | |
| 203 | + placeholder="请选择是否有效" | |
| 204 | + clearable | |
| 205 | + class="!w-[240px]" | |
| 206 | + > | |
| 207 | + <el-option | |
| 208 | + v-for="dict in getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean')" | |
| 209 | + :key="dict.value" | |
| 210 | + :value="dict.value" | |
| 211 | + :label="dict.label" | |
| 212 | + /> | |
| 213 | + </el-select> | |
| 214 | + </el-form-item> | |
| 215 | + <el-form-item label="创建时间"> | |
| 216 | + <el-date-picker | |
| 217 | + v-model="queryParams.createTime" | |
| 218 | + type="daterange" | |
| 219 | + value-format="YYYY-MM-DD" | |
| 220 | + range-separator="至" | |
| 221 | + start-placeholder="开始日期" | |
| 222 | + end-placeholder="结束日期" | |
| 223 | + class="!w-[240px]" | |
| 224 | + /> | |
| 225 | + </el-form-item> | |
| 226 | + <el-form-item> | |
| 227 | + <el-button class="ml-2" @click="resetQuery"> 重置 </el-button> | |
| 228 | + <el-button class="ml-2" @click="handleQuery" type="primary"> | |
| 229 | + 搜索 | |
| 230 | + </el-button> | |
| 231 | + </el-form-item> | |
| 232 | + </el-form> | |
| 233 | + </ContentWrap> | |
| 234 | + | |
| 235 | + <!-- 列表 --> | |
| 236 | + <ContentWrap title="学生"> | |
| 237 | + <template #extra> | |
| 238 | + <TableToolbar | |
| 239 | + ref="tableToolbarRef" | |
| 240 | + v-model:hidden-search="hiddenSearchBar" | |
| 241 | + > | |
| 242 | + <el-button | |
| 243 | + class="ml-2" | |
| 244 | + :icon="h(Plus)" | |
| 245 | + type="primary" | |
| 246 | + @click="handleCreate" | |
| 247 | + v-access:code="['infra:student:create']" | |
| 248 | + > | |
| 249 | + {{ $t('ui.actionTitle.create', ['学生']) }} | |
| 250 | + </el-button> | |
| 251 | + <el-button | |
| 252 | + class="ml-2" | |
| 253 | + type="primary" | |
| 254 | + @click="handleImport" | |
| 255 | + v-access:code="['infra:student:import']" | |
| 256 | + > | |
| 257 | + 导入 | |
| 258 | + </el-button> | |
| 259 | + <el-button | |
| 260 | + :icon="h(Download)" | |
| 261 | + type="primary" | |
| 262 | + class="ml-2" | |
| 263 | + :loading="exportLoading" | |
| 264 | + @click="handleExport" | |
| 265 | + v-access:code="['infra:student:export']" | |
| 266 | + > | |
| 267 | + {{ $t('ui.actionTitle.export') }} | |
| 268 | + </el-button> | |
| 269 | + <el-button | |
| 270 | + :icon="h(Trash2)" | |
| 271 | + type="danger" | |
| 272 | + class="ml-2" | |
| 273 | + :disabled="isEmpty(checkedIds)" | |
| 274 | + @click="handleDeleteBatch" | |
| 275 | + v-access:code="['infra:student:delete']" | |
| 276 | + > | |
| 277 | + 批量删除 | |
| 278 | + </el-button> | |
| 279 | + </TableToolbar> | |
| 280 | + </template> | |
| 281 | + <vxe-table | |
| 282 | + ref="tableRef" | |
| 283 | + :data="list" | |
| 284 | + show-overflow | |
| 285 | + :loading="loading" | |
| 286 | + @checkboxAll="handleRowCheckboxChange" | |
| 287 | + @checkboxChange="handleRowCheckboxChange" | |
| 288 | + > | |
| 289 | + <vxe-column type="checkbox" width="40"></vxe-column> | |
| 290 | + <vxe-column field="id" title="编号" align="center" /> | |
| 291 | + <vxe-column field="name" title="名字" align="center" /> | |
| 292 | + <vxe-column field="description" title="简介" align="center" /> | |
| 293 | + <vxe-column field="birthday" title="出生日期" align="center"> | |
| 294 | + <template #default="{row}"> | |
| 295 | + {{formatDateTime(row.birthday)}} | |
| 296 | + </template> | |
| 297 | + </vxe-column> | |
| 298 | + <vxe-column field="sex" title="性别" align="center"> | |
| 299 | + <template #default="{row}"> | |
| 300 | + <dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="row.sex" /> | |
| 301 | + </template> | |
| 302 | + </vxe-column> | |
| 303 | + <vxe-column field="enabled" title="是否有效" align="center"> | |
| 304 | + <template #default="{row}"> | |
| 305 | + <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="row.enabled" /> | |
| 306 | + </template> | |
| 307 | + </vxe-column> | |
| 308 | + <vxe-column field="avatar" title="头像" align="center" /> | |
| 309 | + <vxe-column field="video" title="附件" align="center" /> | |
| 310 | + <vxe-column field="memo" title="备注" align="center" /> | |
| 311 | + <vxe-column field="createTime" title="创建时间" align="center"> | |
| 312 | + <template #default="{row}"> | |
| 313 | + {{formatDateTime(row.createTime)}} | |
| 314 | + </template> | |
| 315 | + </vxe-column> | |
| 316 | + <vxe-column field="operation" title="操作" align="center"> | |
| 317 | + <template #default="{row}"> | |
| 318 | + <el-button | |
| 319 | + size="small" | |
| 320 | + type="primary" | |
| 321 | + link | |
| 322 | + @click="handleEdit(row as any)" | |
| 323 | + v-access:code="['infra:student:update']" | |
| 324 | + > | |
| 325 | + {{ $t('ui.actionTitle.edit') }} | |
| 326 | + </el-button> | |
| 327 | + <el-button | |
| 328 | + size="small" | |
| 329 | + type="danger" | |
| 330 | + link | |
| 331 | + class="ml-2" | |
| 332 | + @click="handleDelete(row as any)" | |
| 333 | + v-access:code="['infra:student:delete']" | |
| 334 | + > | |
| 335 | + {{ $t('ui.actionTitle.delete') }} | |
| 336 | + </el-button> | |
| 337 | + </template> | |
| 338 | + </vxe-column> | |
| 339 | + </vxe-table> | |
| 340 | + <!-- 分页 --> | |
| 341 | + <div class="mt-2 flex justify-end"> | |
| 342 | + <el-pagination | |
| 343 | + :total="total" | |
| 344 | + v-model:current-page="queryParams.pageNo" | |
| 345 | + v-model:page-size="queryParams.pageSize" | |
| 346 | + :page-sizes="[10, 20, 50, 100]" | |
| 347 | + layout="total, sizes, prev, pager, next, jumper" | |
| 348 | + @size-change="getList" | |
| 349 | + @current-change="getList" | |
| 350 | + /> | |
| 351 | + </div> | |
| 352 | + </ContentWrap> | |
| 353 | + </Page> | |
| 354 | +</template> | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one_importEnable/xml/InfraStudentMapper
0 → 100644
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | |
| 2 | +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | |
| 3 | +<mapper namespace="cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper"> | |
| 4 | + | |
| 5 | + <!-- | |
| 6 | + 一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。 | |
| 7 | + 无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。 | |
| 8 | + 代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。 | |
| 9 | + 文档可见:https://www.iocoder.cn/MyBatis/x-plugins/ | |
| 10 | + --> | |
| 11 | + | |
| 12 | +</mapper> | |
| 0 | 13 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one_importEnable/assert.json
0 → 100644
| 1 | +[ { | |
| 2 | + "contentPath" : "java/InfraStudentPageReqVO", | |
| 3 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentPageReqVO.java" | |
| 4 | +}, { | |
| 5 | + "contentPath" : "java/InfraStudentRespVO", | |
| 6 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentRespVO.java" | |
| 7 | +}, { | |
| 8 | + "contentPath" : "java/InfraStudentSaveReqVO", | |
| 9 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentSaveReqVO.java" | |
| 10 | +}, { | |
| 11 | + "contentPath" : "java/InfraStudentImportExcelVO", | |
| 12 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentImportExcelVO.java" | |
| 13 | +}, { | |
| 14 | + "contentPath" : "java/InfraStudentImportRespVO", | |
| 15 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentImportRespVO.java" | |
| 16 | +}, { | |
| 17 | + "contentPath" : "java/InfraStudentController", | |
| 18 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/InfraStudentController.java" | |
| 19 | +}, { | |
| 20 | + "contentPath" : "java/InfraStudentDO", | |
| 21 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentDO.java" | |
| 22 | +}, { | |
| 23 | + "contentPath" : "java/InfraStudentMapper", | |
| 24 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentMapper.java" | |
| 25 | +}, { | |
| 26 | + "contentPath" : "xml/InfraStudentMapper", | |
| 27 | + "filePath" : "yudao-module-infra/src/main/resources/mapper/demo/InfraStudentMapper.xml" | |
| 28 | +}, { | |
| 29 | + "contentPath" : "java/InfraStudentServiceImpl", | |
| 30 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImpl.java" | |
| 31 | +}, { | |
| 32 | + "contentPath" : "java/InfraStudentService", | |
| 33 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentService.java" | |
| 34 | +}, { | |
| 35 | + "contentPath" : "java/InfraStudentServiceImplTest", | |
| 36 | + "filePath" : "yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImplTest.java" | |
| 37 | +}, { | |
| 38 | + "contentPath" : "java/ErrorCodeConstants_手动操作", | |
| 39 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants_手动操作.java" | |
| 40 | +}, { | |
| 41 | + "contentPath" : "sql/sql", | |
| 42 | + "filePath" : "sql/sql.sql" | |
| 43 | +}, { | |
| 44 | + "contentPath" : "sql/h2", | |
| 45 | + "filePath" : "sql/h2.sql" | |
| 46 | +}, { | |
| 47 | + "contentPath" : "ts/data", | |
| 48 | + "filePath" : "yudao-ui-admin-vben/src/views/infra/demo/data.ts" | |
| 49 | +}, { | |
| 50 | + "contentPath" : "vue/index", | |
| 51 | + "filePath" : "yudao-ui-admin-vben/src/views/infra/demo/index.vue" | |
| 52 | +}, { | |
| 53 | + "contentPath" : "vue/form", | |
| 54 | + "filePath" : "yudao-ui-admin-vben/src/views/infra/demo/modules/form.vue" | |
| 55 | +}, { | |
| 56 | + "contentPath" : "vue/import-form", | |
| 57 | + "filePath" : "yudao-ui-admin-vben/src/views/infra/demo/modules/import-form.vue" | |
| 58 | +}, { | |
| 59 | + "contentPath" : "ts/index", | |
| 60 | + "filePath" : "yudao-ui-admin-vben/src/api/infra/demo/index.ts" | |
| 61 | +} ] | |
| 0 | 62 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one_importEnable/java/ErrorCodeConstants_手动操作
0 → 100644
yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one_importEnable/java/InfraStudentController
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.controller.admin.demo; | |
| 2 | + | |
| 3 | +import org.springframework.web.bind.annotation.*; | |
| 4 | +import org.springframework.web.multipart.MultipartFile; | |
| 5 | +import jakarta.annotation.Resource; | |
| 6 | +import org.springframework.validation.annotation.Validated; | |
| 7 | +import org.springframework.security.access.prepost.PreAuthorize; | |
| 8 | +import io.swagger.v3.oas.annotations.tags.Tag; | |
| 9 | +import io.swagger.v3.oas.annotations.Parameter; | |
| 10 | +import io.swagger.v3.oas.annotations.Operation; | |
| 11 | + | |
| 12 | +import jakarta.validation.constraints.*; | |
| 13 | +import jakarta.validation.*; | |
| 14 | +import jakarta.servlet.http.*; | |
| 15 | +import java.util.*; | |
| 16 | +import java.io.IOException; | |
| 17 | + | |
| 18 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | |
| 19 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 20 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | |
| 21 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | |
| 22 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | |
| 23 | + | |
| 24 | +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; | |
| 25 | + | |
| 26 | +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; | |
| 27 | +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*; | |
| 28 | + | |
| 29 | +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; | |
| 30 | +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; | |
| 31 | +import cn.iocoder.yudao.module.infra.service.demo.InfraStudentService; | |
| 32 | + | |
| 33 | +@Tag(name = "管理后台 - 学生") | |
| 34 | +@RestController | |
| 35 | +@RequestMapping("/infra/student") | |
| 36 | +@Validated | |
| 37 | +public class InfraStudentController { | |
| 38 | + | |
| 39 | + @Resource | |
| 40 | + private InfraStudentService studentService; | |
| 41 | + | |
| 42 | + @PostMapping("/create") | |
| 43 | + @Operation(summary = "创建学生") | |
| 44 | + @PreAuthorize("@ss.hasPermission('infra:student:create')") | |
| 45 | + public CommonResult<Long> createStudent(@Valid @RequestBody InfraStudentSaveReqVO createReqVO) { | |
| 46 | + return success(studentService.createStudent(createReqVO)); | |
| 47 | + } | |
| 48 | + | |
| 49 | + @PutMapping("/update") | |
| 50 | + @Operation(summary = "更新学生") | |
| 51 | + @PreAuthorize("@ss.hasPermission('infra:student:update')") | |
| 52 | + public CommonResult<Boolean> updateStudent(@Valid @RequestBody InfraStudentSaveReqVO updateReqVO) { | |
| 53 | + studentService.updateStudent(updateReqVO); | |
| 54 | + return success(true); | |
| 55 | + } | |
| 56 | + | |
| 57 | + @DeleteMapping("/delete") | |
| 58 | + @Operation(summary = "删除学生") | |
| 59 | + @Parameter(name = "id", description = "编号", required = true) | |
| 60 | + @PreAuthorize("@ss.hasPermission('infra:student:delete')") | |
| 61 | + public CommonResult<Boolean> deleteStudent(@RequestParam("id") Long id) { | |
| 62 | + studentService.deleteStudent(id); | |
| 63 | + return success(true); | |
| 64 | + } | |
| 65 | + | |
| 66 | + @DeleteMapping("/delete-list") | |
| 67 | + @Parameter(name = "ids", description = "编号", required = true) | |
| 68 | + @Operation(summary = "批量删除学生") | |
| 69 | + @PreAuthorize("@ss.hasPermission('infra:student:delete')") | |
| 70 | + public CommonResult<Boolean> deleteStudentList(@RequestParam("ids") List<Long> ids) { | |
| 71 | + studentService.deleteStudentListByIds(ids); | |
| 72 | + return success(true); | |
| 73 | + } | |
| 74 | + | |
| 75 | + @GetMapping("/get") | |
| 76 | + @Operation(summary = "获得学生") | |
| 77 | + @Parameter(name = "id", description = "编号", required = true, example = "1024") | |
| 78 | + @PreAuthorize("@ss.hasPermission('infra:student:query')") | |
| 79 | + public CommonResult<InfraStudentRespVO> getStudent(@RequestParam("id") Long id) { | |
| 80 | + InfraStudentDO student = studentService.getStudent(id); | |
| 81 | + return success(BeanUtils.toBean(student, InfraStudentRespVO.class)); | |
| 82 | + } | |
| 83 | + | |
| 84 | + @GetMapping("/page") | |
| 85 | + @Operation(summary = "获得学生分页") | |
| 86 | + @PreAuthorize("@ss.hasPermission('infra:student:query')") | |
| 87 | + public CommonResult<PageResult<InfraStudentRespVO>> getStudentPage(@Valid InfraStudentPageReqVO pageReqVO) { | |
| 88 | + PageResult<InfraStudentDO> pageResult = studentService.getStudentPage(pageReqVO); | |
| 89 | + return success(BeanUtils.toBean(pageResult, InfraStudentRespVO.class)); | |
| 90 | + } | |
| 91 | + | |
| 92 | + @GetMapping("/export-excel") | |
| 93 | + @Operation(summary = "导出学生 Excel") | |
| 94 | + @PreAuthorize("@ss.hasPermission('infra:student:export')") | |
| 95 | + @ApiAccessLog(operateType = EXPORT) | |
| 96 | + public void exportStudentExcel(@Valid InfraStudentPageReqVO pageReqVO, | |
| 97 | + HttpServletResponse response) throws IOException { | |
| 98 | + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); | |
| 99 | + List<InfraStudentDO> list = studentService.getStudentPage(pageReqVO).getList(); | |
| 100 | + // 导出 Excel | |
| 101 | + ExcelUtils.write(response, "学生.xls", "数据", InfraStudentRespVO.class, | |
| 102 | + BeanUtils.toBean(list, InfraStudentRespVO.class)); | |
| 103 | + } | |
| 104 | + | |
| 105 | + @GetMapping("/get-import-template") | |
| 106 | + @Operation(summary = "获得导入学生模板") | |
| 107 | + @PreAuthorize("@ss.hasPermission('infra:student:import')") | |
| 108 | + public void importTemplate(HttpServletResponse response) throws IOException { | |
| 109 | + ExcelUtils.write(response, "学生导入模板.xls", "数据", | |
| 110 | + InfraStudentImportExcelVO.class, Collections.emptyList()); | |
| 111 | + } | |
| 112 | + | |
| 113 | + @PostMapping("/import") | |
| 114 | + @Operation(summary = "导入学生") | |
| 115 | + @Parameter(name = "file", description = "Excel 文件", required = true) | |
| 116 | + @PreAuthorize("@ss.hasPermission('infra:student:import')") | |
| 117 | + public CommonResult<InfraStudentImportRespVO> importExcel(@RequestParam("file") MultipartFile file) throws Exception { | |
| 118 | + List<InfraStudentImportExcelVO> list = ExcelUtils.read(file, InfraStudentImportExcelVO.class); | |
| 119 | + return success(studentService.importStudentList(list)); | |
| 120 | + } | |
| 121 | + | |
| 122 | +} | |
| 0 | 123 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one_importEnable/java/InfraStudentDO
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.dal.dataobject.demo; | |
| 2 | + | |
| 3 | +import lombok.*; | |
| 4 | +import java.util.*; | |
| 5 | +import java.time.LocalDateTime; | |
| 6 | +import java.time.LocalDateTime; | |
| 7 | +import com.baomidou.mybatisplus.annotation.*; | |
| 8 | +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | |
| 9 | + | |
| 10 | +/** | |
| 11 | + * 学生 DO | |
| 12 | + * | |
| 13 | + * @author 芋道源码 | |
| 14 | + */ | |
| 15 | +@TableName("infra_student") | |
| 16 | +@KeySequence("infra_student_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 | |
| 17 | +@Data | |
| 18 | +@EqualsAndHashCode(callSuper = true) | |
| 19 | +@ToString(callSuper = true) | |
| 20 | +@Builder | |
| 21 | +@NoArgsConstructor | |
| 22 | +@AllArgsConstructor | |
| 23 | +public class InfraStudentDO extends BaseDO { | |
| 24 | + | |
| 25 | + /** | |
| 26 | + * 编号 | |
| 27 | + */ | |
| 28 | + @TableId | |
| 29 | + private Long id; | |
| 30 | + /** | |
| 31 | + * 名字 | |
| 32 | + */ | |
| 33 | + private String name; | |
| 34 | + /** | |
| 35 | + * 简介 | |
| 36 | + */ | |
| 37 | + private String description; | |
| 38 | + /** | |
| 39 | + * 出生日期 | |
| 40 | + */ | |
| 41 | + private LocalDateTime birthday; | |
| 42 | + /** | |
| 43 | + * 性别 | |
| 44 | + * | |
| 45 | + * 枚举 {@link TODO system_user_sex 对应的类} | |
| 46 | + */ | |
| 47 | + private Integer sex; | |
| 48 | + /** | |
| 49 | + * 是否有效 | |
| 50 | + * | |
| 51 | + * 枚举 {@link TODO infra_boolean_string 对应的类} | |
| 52 | + */ | |
| 53 | + private Boolean enabled; | |
| 54 | + /** | |
| 55 | + * 头像 | |
| 56 | + */ | |
| 57 | + private String avatar; | |
| 58 | + /** | |
| 59 | + * 附件 | |
| 60 | + */ | |
| 61 | + private String video; | |
| 62 | + /** | |
| 63 | + * 备注 | |
| 64 | + */ | |
| 65 | + private String memo; | |
| 66 | + | |
| 67 | + | |
| 68 | +} | |
| 0 | 69 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one_importEnable/java/InfraStudentImportExcelVO
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; | |
| 2 | + | |
| 3 | +import cn.idev.excel.annotation.ExcelProperty; | |
| 4 | +import lombok.AllArgsConstructor; | |
| 5 | +import lombok.Builder; | |
| 6 | +import lombok.Data; | |
| 7 | +import lombok.NoArgsConstructor; | |
| 8 | +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; | |
| 9 | +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * 学生 Excel 导入 VO | |
| 13 | + */ | |
| 14 | +@Data | |
| 15 | +@Builder | |
| 16 | +@AllArgsConstructor | |
| 17 | +@NoArgsConstructor | |
| 18 | +public class InfraStudentImportExcelVO { | |
| 19 | + | |
| 20 | + @ExcelProperty("名字") | |
| 21 | + private String name; | |
| 22 | + | |
| 23 | + @ExcelProperty("简介") | |
| 24 | + private String description; | |
| 25 | + | |
| 26 | + @ExcelProperty("出生日期") | |
| 27 | + private LocalDateTime birthday; | |
| 28 | + | |
| 29 | + @ExcelProperty(value = "性别", converter = DictConvert.class) | |
| 30 | + @DictFormat("system_user_sex") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 | |
| 31 | + private Integer sex; | |
| 32 | + | |
| 33 | + @ExcelProperty(value = "是否有效", converter = DictConvert.class) | |
| 34 | + @DictFormat("infra_boolean_string") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 | |
| 35 | + private Boolean enabled; | |
| 36 | + | |
| 37 | + @ExcelProperty("头像") | |
| 38 | + private String avatar; | |
| 39 | + | |
| 40 | + @ExcelProperty("附件") | |
| 41 | + private String video; | |
| 42 | + | |
| 43 | + @ExcelProperty("备注") | |
| 44 | + private String memo; | |
| 45 | + | |
| 46 | +} | |
| 0 | 47 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one_importEnable/java/InfraStudentImportRespVO
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; | |
| 2 | + | |
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 4 | +import lombok.Builder; | |
| 5 | +import lombok.Data; | |
| 6 | + | |
| 7 | +import java.util.Map; | |
| 8 | + | |
| 9 | +@Schema(description = "管理后台 - 学生导入 Response VO") | |
| 10 | +@Data | |
| 11 | +@Builder | |
| 12 | +public class InfraStudentImportRespVO { | |
| 13 | + | |
| 14 | + @Schema(description = "创建成功的数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") | |
| 15 | + private Integer successCount; | |
| 16 | + | |
| 17 | + @Schema(description = "导入失败的数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | |
| 18 | + private Integer failureCount; | |
| 19 | + | |
| 20 | + @Schema(description = "导入失败的数据集合,key 为行号,value 为失败原因", requiredMode = Schema.RequiredMode.REQUIRED) | |
| 21 | + private Map<Integer, String> failureRows; | |
| 22 | + | |
| 23 | +} | |
| 0 | 24 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one_importEnable/java/InfraStudentMapper
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.dal.mysql.demo; | |
| 2 | + | |
| 3 | +import java.util.*; | |
| 4 | + | |
| 5 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 6 | +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | |
| 7 | +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | |
| 8 | +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; | |
| 9 | +import org.apache.ibatis.annotations.Mapper; | |
| 10 | +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; | |
| 11 | + | |
| 12 | +/** | |
| 13 | + * 学生 Mapper | |
| 14 | + * | |
| 15 | + * @author 芋道源码 | |
| 16 | + */ | |
| 17 | +@Mapper | |
| 18 | +public interface InfraStudentMapper extends BaseMapperX<InfraStudentDO> { | |
| 19 | + | |
| 20 | + default PageResult<InfraStudentDO> selectPage(InfraStudentPageReqVO reqVO) { | |
| 21 | + return selectPage(reqVO, new LambdaQueryWrapperX<InfraStudentDO>() | |
| 22 | + .likeIfPresent(InfraStudentDO::getName, reqVO.getName()) | |
| 23 | + .eqIfPresent(InfraStudentDO::getBirthday, reqVO.getBirthday()) | |
| 24 | + .eqIfPresent(InfraStudentDO::getSex, reqVO.getSex()) | |
| 25 | + .eqIfPresent(InfraStudentDO::getEnabled, reqVO.getEnabled()) | |
| 26 | + .betweenIfPresent(InfraStudentDO::getCreateTime, reqVO.getCreateTime()) | |
| 27 | + .orderByDesc(InfraStudentDO::getId)); | |
| 28 | + } | |
| 29 | + | |
| 30 | +} | |
| 0 | 31 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one_importEnable/java/InfraStudentPageReqVO
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; | |
| 2 | + | |
| 3 | +import lombok.*; | |
| 4 | +import java.util.*; | |
| 5 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 6 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | |
| 7 | +import org.springframework.format.annotation.DateTimeFormat; | |
| 8 | +import java.time.LocalDateTime; | |
| 9 | + | |
| 10 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | |
| 11 | + | |
| 12 | +@Schema(description = "管理后台 - 学生分页 Request VO") | |
| 13 | +@Data | |
| 14 | +public class InfraStudentPageReqVO extends PageParam { | |
| 15 | + | |
| 16 | + @Schema(description = "名字", example = "芋头") | |
| 17 | + private String name; | |
| 18 | + | |
| 19 | + @Schema(description = "出生日期") | |
| 20 | + private LocalDateTime birthday; | |
| 21 | + | |
| 22 | + @Schema(description = "性别", example = "1") | |
| 23 | + private Integer sex; | |
| 24 | + | |
| 25 | + @Schema(description = "是否有效", example = "true") | |
| 26 | + private Boolean enabled; | |
| 27 | + | |
| 28 | + @Schema(description = "创建时间") | |
| 29 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 30 | + private LocalDateTime[] createTime; | |
| 31 | + | |
| 32 | +} | |
| 0 | 33 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one_importEnable/java/InfraStudentRespVO
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; | |
| 2 | + | |
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 4 | +import lombok.*; | |
| 5 | +import java.util.*; | |
| 6 | +import org.springframework.format.annotation.DateTimeFormat; | |
| 7 | +import java.time.LocalDateTime; | |
| 8 | +import cn.idev.excel.annotation.*; | |
| 9 | +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; | |
| 10 | +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; | |
| 11 | + | |
| 12 | +@Schema(description = "管理后台 - 学生 Response VO") | |
| 13 | +@Data | |
| 14 | +@ExcelIgnoreUnannotated | |
| 15 | +public class InfraStudentRespVO { | |
| 16 | + | |
| 17 | + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | |
| 18 | + @ExcelProperty("编号") | |
| 19 | + private Long id; | |
| 20 | + | |
| 21 | + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头") | |
| 22 | + @ExcelProperty("名字") | |
| 23 | + private String name; | |
| 24 | + | |
| 25 | + @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍") | |
| 26 | + @ExcelProperty("简介") | |
| 27 | + private String description; | |
| 28 | + | |
| 29 | + @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED) | |
| 30 | + @ExcelProperty("出生日期") | |
| 31 | + private LocalDateTime birthday; | |
| 32 | + | |
| 33 | + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | |
| 34 | + @ExcelProperty(value = "性别", converter = DictConvert.class) | |
| 35 | + @DictFormat("system_user_sex") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 | |
| 36 | + private Integer sex; | |
| 37 | + | |
| 38 | + @Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") | |
| 39 | + @ExcelProperty(value = "是否有效", converter = DictConvert.class) | |
| 40 | + @DictFormat("infra_boolean_string") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 | |
| 41 | + private Boolean enabled; | |
| 42 | + | |
| 43 | + @Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") | |
| 44 | + @ExcelProperty("头像") | |
| 45 | + private String avatar; | |
| 46 | + | |
| 47 | + @Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4") | |
| 48 | + @ExcelProperty("附件") | |
| 49 | + private String video; | |
| 50 | + | |
| 51 | + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注") | |
| 52 | + @ExcelProperty("备注") | |
| 53 | + private String memo; | |
| 54 | + | |
| 55 | + @Schema(description = "创建时间") | |
| 56 | + @ExcelProperty("创建时间") | |
| 57 | + private LocalDateTime createTime; | |
| 58 | + | |
| 59 | +} | |
| 0 | 60 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one_importEnable/java/InfraStudentSaveReqVO
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; | |
| 2 | + | |
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 4 | +import lombok.*; | |
| 5 | +import java.util.*; | |
| 6 | +import jakarta.validation.constraints.*; | |
| 7 | +import org.springframework.format.annotation.DateTimeFormat; | |
| 8 | +import java.time.LocalDateTime; | |
| 9 | + | |
| 10 | +@Schema(description = "管理后台 - 学生新增/修改 Request VO") | |
| 11 | +@Data | |
| 12 | +public class InfraStudentSaveReqVO { | |
| 13 | + | |
| 14 | + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | |
| 15 | + private Long id; | |
| 16 | + | |
| 17 | + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头") | |
| 18 | + @NotEmpty(message = "名字不能为空") | |
| 19 | + private String name; | |
| 20 | + | |
| 21 | + @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍") | |
| 22 | + @NotEmpty(message = "简介不能为空") | |
| 23 | + private String description; | |
| 24 | + | |
| 25 | + @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED) | |
| 26 | + @NotNull(message = "出生日期不能为空") | |
| 27 | + private LocalDateTime birthday; | |
| 28 | + | |
| 29 | + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | |
| 30 | + @NotNull(message = "性别不能为空") | |
| 31 | + private Integer sex; | |
| 32 | + | |
| 33 | + @Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") | |
| 34 | + @NotNull(message = "是否有效不能为空") | |
| 35 | + private Boolean enabled; | |
| 36 | + | |
| 37 | + @Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") | |
| 38 | + @NotEmpty(message = "头像不能为空") | |
| 39 | + private String avatar; | |
| 40 | + | |
| 41 | + @Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4") | |
| 42 | + @NotEmpty(message = "附件不能为空") | |
| 43 | + private String video; | |
| 44 | + | |
| 45 | + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注") | |
| 46 | + @NotEmpty(message = "备注不能为空") | |
| 47 | + private String memo; | |
| 48 | + | |
| 49 | +} | |
| 0 | 50 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one_importEnable/java/InfraStudentService
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.service.demo; | |
| 2 | + | |
| 3 | +import java.util.*; | |
| 4 | +import jakarta.validation.*; | |
| 5 | +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; | |
| 6 | +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; | |
| 7 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 8 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | |
| 9 | + | |
| 10 | +/** | |
| 11 | + * 学生 Service 接口 | |
| 12 | + * | |
| 13 | + * @author 芋道源码 | |
| 14 | + */ | |
| 15 | +public interface InfraStudentService { | |
| 16 | + | |
| 17 | + /** | |
| 18 | + * 创建学生 | |
| 19 | + * | |
| 20 | + * @param createReqVO 创建信息 | |
| 21 | + * @return 编号 | |
| 22 | + */ | |
| 23 | + Long createStudent(@Valid InfraStudentSaveReqVO createReqVO); | |
| 24 | + | |
| 25 | + /** | |
| 26 | + * 导入学生 | |
| 27 | + * | |
| 28 | + * @param importList 导入信息 | |
| 29 | + * @return 导入结果 | |
| 30 | + */ | |
| 31 | + InfraStudentImportRespVO importStudentList(List<InfraStudentImportExcelVO> importList); | |
| 32 | + | |
| 33 | + /** | |
| 34 | + * 更新学生 | |
| 35 | + * | |
| 36 | + * @param updateReqVO 更新信息 | |
| 37 | + */ | |
| 38 | + void updateStudent(@Valid InfraStudentSaveReqVO updateReqVO); | |
| 39 | + | |
| 40 | + /** | |
| 41 | + * 删除学生 | |
| 42 | + * | |
| 43 | + * @param id 编号 | |
| 44 | + */ | |
| 45 | + void deleteStudent(Long id); | |
| 46 | + | |
| 47 | + /** | |
| 48 | + * 批量删除学生 | |
| 49 | + * | |
| 50 | + * @param ids 编号 | |
| 51 | + */ | |
| 52 | + void deleteStudentListByIds(List<Long> ids); | |
| 53 | + | |
| 54 | + /** | |
| 55 | + * 获得学生 | |
| 56 | + * | |
| 57 | + * @param id 编号 | |
| 58 | + * @return 学生 | |
| 59 | + */ | |
| 60 | + InfraStudentDO getStudent(Long id); | |
| 61 | + | |
| 62 | + /** | |
| 63 | + * 获得学生分页 | |
| 64 | + * | |
| 65 | + * @param pageReqVO 分页查询 | |
| 66 | + * @return 学生分页 | |
| 67 | + */ | |
| 68 | + PageResult<InfraStudentDO> getStudentPage(InfraStudentPageReqVO pageReqVO); | |
| 69 | + | |
| 70 | +} | |
| 0 | 71 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one_importEnable/java/InfraStudentServiceImpl
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.service.demo; | |
| 2 | + | |
| 3 | +import cn.hutool.core.collection.CollUtil; | |
| 4 | +import org.springframework.stereotype.Service; | |
| 5 | +import jakarta.annotation.Resource; | |
| 6 | +import org.springframework.validation.annotation.Validated; | |
| 7 | +import org.springframework.transaction.annotation.Transactional; | |
| 8 | + | |
| 9 | +import java.util.*; | |
| 10 | +import java.util.concurrent.atomic.AtomicInteger; | |
| 11 | +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; | |
| 12 | +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; | |
| 13 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 14 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | |
| 15 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | |
| 16 | + | |
| 17 | +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper; | |
| 18 | + | |
| 19 | +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | |
| 20 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | |
| 21 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.diffList; | |
| 22 | +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; | |
| 23 | + | |
| 24 | +/** | |
| 25 | + * 学生 Service 实现类 | |
| 26 | + * | |
| 27 | + * @author 芋道源码 | |
| 28 | + */ | |
| 29 | +@Service | |
| 30 | +@Validated | |
| 31 | +public class InfraStudentServiceImpl implements InfraStudentService { | |
| 32 | + | |
| 33 | + @Resource | |
| 34 | + private InfraStudentMapper studentMapper; | |
| 35 | + | |
| 36 | + @Override | |
| 37 | + public Long createStudent(InfraStudentSaveReqVO createReqVO) { | |
| 38 | + // 插入 | |
| 39 | + InfraStudentDO student = BeanUtils.toBean(createReqVO, InfraStudentDO.class); | |
| 40 | + studentMapper.insert(student); | |
| 41 | + | |
| 42 | + // 返回 | |
| 43 | + return student.getId(); | |
| 44 | + } | |
| 45 | + | |
| 46 | + @Override | |
| 47 | + @Transactional(rollbackFor = Exception.class) // 添加事务,异常则回滚所有导入 | |
| 48 | + public InfraStudentImportRespVO importStudentList(List<InfraStudentImportExcelVO> importList) { | |
| 49 | + if (CollUtil.isEmpty(importList)) { | |
| 50 | + return InfraStudentImportRespVO.builder() | |
| 51 | + .successCount(0).failureCount(0).failureRows(new LinkedHashMap<>()).build(); | |
| 52 | + } | |
| 53 | + // 遍历,逐个创建 | |
| 54 | + InfraStudentImportRespVO respVO = InfraStudentImportRespVO.builder() | |
| 55 | + .successCount(0).failureCount(0).failureRows(new LinkedHashMap<>()).build(); | |
| 56 | + AtomicInteger index = new AtomicInteger(1); | |
| 57 | + importList.forEach(importItem -> { | |
| 58 | + int currentIndex = index.getAndIncrement(); | |
| 59 | + try { | |
| 60 | + createStudent(BeanUtils.toBean(importItem, InfraStudentSaveReqVO.class)); | |
| 61 | + respVO.setSuccessCount(respVO.getSuccessCount() + 1); | |
| 62 | + } catch (Exception ex) { | |
| 63 | + respVO.getFailureRows().put(currentIndex, ex.getMessage()); | |
| 64 | + } | |
| 65 | + }); | |
| 66 | + respVO.setFailureCount(respVO.getFailureRows().size()); | |
| 67 | + return respVO; | |
| 68 | + } | |
| 69 | + | |
| 70 | + @Override | |
| 71 | + public void updateStudent(InfraStudentSaveReqVO updateReqVO) { | |
| 72 | + // 校验存在 | |
| 73 | + validateStudentExists(updateReqVO.getId()); | |
| 74 | + // 更新 | |
| 75 | + InfraStudentDO updateObj = BeanUtils.toBean(updateReqVO, InfraStudentDO.class); | |
| 76 | + studentMapper.updateById(updateObj); | |
| 77 | + } | |
| 78 | + | |
| 79 | + @Override | |
| 80 | + public void deleteStudent(Long id) { | |
| 81 | + // 校验存在 | |
| 82 | + validateStudentExists(id); | |
| 83 | + // 删除 | |
| 84 | + studentMapper.deleteById(id); | |
| 85 | + } | |
| 86 | + | |
| 87 | + @Override | |
| 88 | + public void deleteStudentListByIds(List<Long> ids) { | |
| 89 | + // 删除 | |
| 90 | + studentMapper.deleteByIds(ids); | |
| 91 | + } | |
| 92 | + | |
| 93 | + | |
| 94 | + private void validateStudentExists(Long id) { | |
| 95 | + if (studentMapper.selectById(id) == null) { | |
| 96 | + throw exception(STUDENT_NOT_EXISTS); | |
| 97 | + } | |
| 98 | + } | |
| 99 | + | |
| 100 | + @Override | |
| 101 | + public InfraStudentDO getStudent(Long id) { | |
| 102 | + return studentMapper.selectById(id); | |
| 103 | + } | |
| 104 | + | |
| 105 | + @Override | |
| 106 | + public PageResult<InfraStudentDO> getStudentPage(InfraStudentPageReqVO pageReqVO) { | |
| 107 | + return studentMapper.selectPage(pageReqVO); | |
| 108 | + } | |
| 109 | + | |
| 110 | +} | |
| 0 | 111 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one_importEnable/java/InfraStudentServiceImplTest
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.service.demo; | |
| 2 | + | |
| 3 | +import org.junit.jupiter.api.Disabled; | |
| 4 | +import org.junit.jupiter.api.Test; | |
| 5 | + | |
| 6 | +import jakarta.annotation.Resource; | |
| 7 | + | |
| 8 | +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; | |
| 9 | + | |
| 10 | +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; | |
| 11 | +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; | |
| 12 | +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper; | |
| 13 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 14 | + | |
| 15 | +import jakarta.annotation.Resource; | |
| 16 | +import org.springframework.context.annotation.Import; | |
| 17 | +import java.util.*; | |
| 18 | +import java.time.LocalDateTime; | |
| 19 | + | |
| 20 | +import static cn.hutool.core.util.RandomUtil.*; | |
| 21 | +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; | |
| 22 | +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*; | |
| 23 | +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; | |
| 24 | +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*; | |
| 25 | +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*; | |
| 26 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*; | |
| 27 | +import static org.junit.jupiter.api.Assertions.*; | |
| 28 | +import static org.mockito.Mockito.*; | |
| 29 | + | |
| 30 | +/** | |
| 31 | + * {@link InfraStudentServiceImpl} 的单元测试类 | |
| 32 | + * | |
| 33 | + * @author 芋道源码 | |
| 34 | + */ | |
| 35 | +@Import(InfraStudentServiceImpl.class) | |
| 36 | +public class InfraStudentServiceImplTest extends BaseDbUnitTest { | |
| 37 | + | |
| 38 | + @Resource | |
| 39 | + private InfraStudentServiceImpl studentService; | |
| 40 | + | |
| 41 | + @Resource | |
| 42 | + private InfraStudentMapper studentMapper; | |
| 43 | + | |
| 44 | + @Test | |
| 45 | + public void testCreateStudent_success() { | |
| 46 | + // 准备参数 | |
| 47 | + InfraStudentSaveReqVO createReqVO = randomPojo(InfraStudentSaveReqVO.class).setId(null); | |
| 48 | + | |
| 49 | + // 调用 | |
| 50 | + Long studentId = studentService.createStudent(createReqVO); | |
| 51 | + // 断言 | |
| 52 | + assertNotNull(studentId); | |
| 53 | + // 校验记录的属性是否正确 | |
| 54 | + InfraStudentDO student = studentMapper.selectById(studentId); | |
| 55 | + assertPojoEquals(createReqVO, student, "id"); | |
| 56 | + } | |
| 57 | + | |
| 58 | + @Test | |
| 59 | + public void testUpdateStudent_success() { | |
| 60 | + // mock 数据 | |
| 61 | + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class); | |
| 62 | + studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据 | |
| 63 | + // 准备参数 | |
| 64 | + InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class, o -> { | |
| 65 | + o.setId(dbStudent.getId()); // 设置更新的 ID | |
| 66 | + }); | |
| 67 | + | |
| 68 | + // 调用 | |
| 69 | + studentService.updateStudent(updateReqVO); | |
| 70 | + // 校验是否更新正确 | |
| 71 | + InfraStudentDO student = studentMapper.selectById(updateReqVO.getId()); // 获取最新的 | |
| 72 | + assertPojoEquals(updateReqVO, student); | |
| 73 | + } | |
| 74 | + | |
| 75 | + @Test | |
| 76 | + public void testUpdateStudent_notExists() { | |
| 77 | + // 准备参数 | |
| 78 | + InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class); | |
| 79 | + | |
| 80 | + // 调用, 并断言异常 | |
| 81 | + assertServiceException(() -> studentService.updateStudent(updateReqVO), STUDENT_NOT_EXISTS); | |
| 82 | + } | |
| 83 | + | |
| 84 | + @Test | |
| 85 | + public void testDeleteStudent_success() { | |
| 86 | + // mock 数据 | |
| 87 | + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class); | |
| 88 | + studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据 | |
| 89 | + // 准备参数 | |
| 90 | + Long id = dbStudent.getId(); | |
| 91 | + | |
| 92 | + // 调用 | |
| 93 | + studentService.deleteStudent(id); | |
| 94 | + // 校验数据不存在了 | |
| 95 | + assertNull(studentMapper.selectById(id)); | |
| 96 | + } | |
| 97 | + | |
| 98 | + @Test | |
| 99 | + public void testDeleteStudent_notExists() { | |
| 100 | + // 准备参数 | |
| 101 | + Long id = randomLongId(); | |
| 102 | + | |
| 103 | + // 调用, 并断言异常 | |
| 104 | + assertServiceException(() -> studentService.deleteStudent(id), STUDENT_NOT_EXISTS); | |
| 105 | + } | |
| 106 | + | |
| 107 | + @Test | |
| 108 | + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 | |
| 109 | + public void testGetStudentPage() { | |
| 110 | + // mock 数据 | |
| 111 | + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class, o -> { // 等会查询到 | |
| 112 | + o.setName(null); | |
| 113 | + o.setBirthday(null); | |
| 114 | + o.setSex(null); | |
| 115 | + o.setEnabled(null); | |
| 116 | + o.setCreateTime(null); | |
| 117 | + }); | |
| 118 | + studentMapper.insert(dbStudent); | |
| 119 | + // 测试 name 不匹配 | |
| 120 | + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setName(null))); | |
| 121 | + // 测试 birthday 不匹配 | |
| 122 | + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setBirthday(null))); | |
| 123 | + // 测试 sex 不匹配 | |
| 124 | + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setSex(null))); | |
| 125 | + // 测试 enabled 不匹配 | |
| 126 | + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setEnabled(null))); | |
| 127 | + // 测试 createTime 不匹配 | |
| 128 | + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setCreateTime(null))); | |
| 129 | + // 准备参数 | |
| 130 | + InfraStudentPageReqVO reqVO = new InfraStudentPageReqVO(); | |
| 131 | + reqVO.setName(null); | |
| 132 | + reqVO.setBirthday(null); | |
| 133 | + reqVO.setSex(null); | |
| 134 | + reqVO.setEnabled(null); | |
| 135 | + reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); | |
| 136 | + | |
| 137 | + // 调用 | |
| 138 | + PageResult<InfraStudentDO> pageResult = studentService.getStudentPage(reqVO); | |
| 139 | + // 断言 | |
| 140 | + assertEquals(1, pageResult.getTotal()); | |
| 141 | + assertEquals(1, pageResult.getList().size()); | |
| 142 | + assertPojoEquals(dbStudent, pageResult.getList().get(0)); | |
| 143 | + } | |
| 144 | + | |
| 145 | +} | |
| 0 | 146 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one_importEnable/sql/h2
0 → 100644
| 1 | +-- 将该建表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/create_tables.sql 文件里 | |
| 2 | +CREATE TABLE IF NOT EXISTS "infra_student" ( | |
| 3 | + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, | |
| 4 | + "name" varchar NOT NULL, | |
| 5 | + "description" varchar NOT NULL, | |
| 6 | + "birthday" varchar NOT NULL, | |
| 7 | + "sex" int NOT NULL, | |
| 8 | + "enabled" bit NOT NULL, | |
| 9 | + "avatar" varchar NOT NULL, | |
| 10 | + "video" varchar NOT NULL, | |
| 11 | + "memo" varchar NOT NULL, | |
| 12 | + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| 13 | + PRIMARY KEY ("id") | |
| 14 | +) COMMENT '学生表'; | |
| 15 | + | |
| 16 | +-- 将该删表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/clean.sql 文件里 | |
| 17 | +DELETE FROM "infra_student"; | |
| 0 | 18 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one_importEnable/sql/sql
0 → 100644
| 1 | +-- 菜单 SQL | |
| 2 | +INSERT INTO system_menu( | |
| 3 | + name, permission, type, sort, parent_id, | |
| 4 | + path, icon, component, status, component_name | |
| 5 | +) | |
| 6 | +VALUES ( | |
| 7 | + '学生管理', '', 2, 0, 888, | |
| 8 | + 'student', '', 'infra/demo/index', 0, 'InfraStudent' | |
| 9 | +); | |
| 10 | + | |
| 11 | +-- 按钮父菜单ID | |
| 12 | +SELECT @parentId := LAST_INSERT_ID(); | |
| 13 | + | |
| 14 | +-- 按钮 SQL | |
| 15 | +INSERT INTO system_menu( | |
| 16 | + name, permission, type, sort, parent_id, | |
| 17 | + path, icon, component, status | |
| 18 | +) | |
| 19 | +VALUES ( | |
| 20 | + '学生查询', 'infra:student:query', 3, 1, @parentId, | |
| 21 | + '', '', '', 0 | |
| 22 | +); | |
| 23 | +INSERT INTO system_menu( | |
| 24 | + name, permission, type, sort, parent_id, | |
| 25 | + path, icon, component, status | |
| 26 | +) | |
| 27 | +VALUES ( | |
| 28 | + '学生创建', 'infra:student:create', 3, 2, @parentId, | |
| 29 | + '', '', '', 0 | |
| 30 | +); | |
| 31 | +INSERT INTO system_menu( | |
| 32 | + name, permission, type, sort, parent_id, | |
| 33 | + path, icon, component, status | |
| 34 | +) | |
| 35 | +VALUES ( | |
| 36 | + '学生更新', 'infra:student:update', 3, 3, @parentId, | |
| 37 | + '', '', '', 0 | |
| 38 | +); | |
| 39 | +INSERT INTO system_menu( | |
| 40 | + name, permission, type, sort, parent_id, | |
| 41 | + path, icon, component, status | |
| 42 | +) | |
| 43 | +VALUES ( | |
| 44 | + '学生删除', 'infra:student:delete', 3, 4, @parentId, | |
| 45 | + '', '', '', 0 | |
| 46 | +); | |
| 47 | +INSERT INTO system_menu( | |
| 48 | + name, permission, type, sort, parent_id, | |
| 49 | + path, icon, component, status | |
| 50 | +) | |
| 51 | +VALUES ( | |
| 52 | + '学生导出', 'infra:student:export', 3, 5, @parentId, | |
| 53 | + '', '', '', 0 | |
| 54 | +); | |
| 55 | +INSERT INTO system_menu( | |
| 56 | + name, permission, type, sort, parent_id, | |
| 57 | + path, icon, component, status | |
| 58 | +) | |
| 59 | +VALUES ( | |
| 60 | + '学生导入', 'infra:student:import', 3, 6, @parentId, | |
| 61 | + '', '', '', 0 | |
| 62 | +); | |
| 0 | 63 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one_importEnable/ts/data
0 → 100644
| 1 | +import type { VbenFormSchema } from '#/adapter/form'; | |
| 2 | +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; | |
| 3 | +import type { InfraStudentApi } from '#/api/infra/demo'; | |
| 4 | + | |
| 5 | +import { DICT_TYPE } from '@vben/constants'; | |
| 6 | +import { getDictOptions } from '@vben/hooks'; | |
| 7 | + | |
| 8 | +import { getRangePickerDefaultProps } from '#/utils'; | |
| 9 | + | |
| 10 | +/** 新增/修改的表单 */ | |
| 11 | +export function useFormSchema(): VbenFormSchema[] { | |
| 12 | + return [ | |
| 13 | + { | |
| 14 | + fieldName: 'id', | |
| 15 | + component: 'Input', | |
| 16 | + dependencies: { | |
| 17 | + triggerFields: [''], | |
| 18 | + show: () => false, | |
| 19 | + }, | |
| 20 | + }, | |
| 21 | + { | |
| 22 | + fieldName: 'name', | |
| 23 | + label: '名字', | |
| 24 | + rules: 'required', | |
| 25 | + component: 'Input', | |
| 26 | + componentProps: { | |
| 27 | + placeholder: '请输入名字', | |
| 28 | + }, | |
| 29 | + }, | |
| 30 | + { | |
| 31 | + fieldName: 'description', | |
| 32 | + label: '简介', | |
| 33 | + rules: 'required', | |
| 34 | + component: 'Textarea', | |
| 35 | + componentProps: { | |
| 36 | + placeholder: '请输入简介', | |
| 37 | + }, | |
| 38 | + }, | |
| 39 | + { | |
| 40 | + fieldName: 'birthday', | |
| 41 | + label: '出生日期', | |
| 42 | + rules: 'required', | |
| 43 | + component: 'DatePicker', | |
| 44 | + componentProps: { | |
| 45 | + showTime: true, | |
| 46 | + format: 'YYYY-MM-DD HH:mm:ss', | |
| 47 | + valueFormat: 'x', | |
| 48 | + class: '!w-full', | |
| 49 | + }, | |
| 50 | + }, | |
| 51 | + { | |
| 52 | + fieldName: 'sex', | |
| 53 | + label: '性别', | |
| 54 | + rules: 'required', | |
| 55 | + component: 'Select', | |
| 56 | + componentProps: { | |
| 57 | + options: getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number'), | |
| 58 | + placeholder: '请选择性别', | |
| 59 | + }, | |
| 60 | + }, | |
| 61 | + { | |
| 62 | + fieldName: 'enabled', | |
| 63 | + label: '是否有效', | |
| 64 | + rules: 'required', | |
| 65 | + component: 'RadioGroup', | |
| 66 | + componentProps: { | |
| 67 | + options: getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean'), | |
| 68 | + buttonStyle: 'solid', | |
| 69 | + optionType: 'button', | |
| 70 | + }, | |
| 71 | + }, | |
| 72 | + { | |
| 73 | + fieldName: 'avatar', | |
| 74 | + label: '头像', | |
| 75 | + rules: 'required', | |
| 76 | + component: 'ImageUpload', | |
| 77 | + }, | |
| 78 | + { | |
| 79 | + fieldName: 'video', | |
| 80 | + label: '附件', | |
| 81 | + rules: 'required', | |
| 82 | + component: 'FileUpload', | |
| 83 | + }, | |
| 84 | + { | |
| 85 | + fieldName: 'memo', | |
| 86 | + label: '备注', | |
| 87 | + rules: 'required', | |
| 88 | + component: 'RichTextarea', | |
| 89 | + }, | |
| 90 | + ]; | |
| 91 | +} | |
| 92 | + | |
| 93 | +/** 导入的表单 */ | |
| 94 | +export function useImportFormSchema(): VbenFormSchema[] { | |
| 95 | + return [ | |
| 96 | + { | |
| 97 | + fieldName: 'file', | |
| 98 | + label: '学生数据', | |
| 99 | + component: 'Upload', | |
| 100 | + rules: 'required', | |
| 101 | + help: '仅允许导入 xls、xlsx 格式文件', | |
| 102 | + }, | |
| 103 | + ]; | |
| 104 | +} | |
| 105 | + | |
| 106 | +/** 列表的搜索表单 */ | |
| 107 | +export function useGridFormSchema(): VbenFormSchema[] { | |
| 108 | + return [ | |
| 109 | + { | |
| 110 | + fieldName: 'name', | |
| 111 | + label: '名字', | |
| 112 | + component: 'Input', | |
| 113 | + componentProps: { | |
| 114 | + clearable: true, | |
| 115 | + placeholder: '请输入名字', | |
| 116 | + }, | |
| 117 | + }, | |
| 118 | + { | |
| 119 | + fieldName: 'birthday', | |
| 120 | + label: '出生日期', | |
| 121 | + component: 'RangePicker', | |
| 122 | + componentProps: { | |
| 123 | + ...getRangePickerDefaultProps(), | |
| 124 | + clearable: true, | |
| 125 | + }, | |
| 126 | + }, | |
| 127 | + { | |
| 128 | + fieldName: 'sex', | |
| 129 | + label: '性别', | |
| 130 | + component: 'Select', | |
| 131 | + componentProps: { | |
| 132 | + clearable: true, | |
| 133 | + options: getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number'), | |
| 134 | + placeholder: '请选择性别', | |
| 135 | + }, | |
| 136 | + }, | |
| 137 | + { | |
| 138 | + fieldName: 'enabled', | |
| 139 | + label: '是否有效', | |
| 140 | + component: 'Select', | |
| 141 | + componentProps: { | |
| 142 | + clearable: true, | |
| 143 | + options: getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean'), | |
| 144 | + placeholder: '请选择是否有效', | |
| 145 | + }, | |
| 146 | + }, | |
| 147 | + { | |
| 148 | + fieldName: 'createTime', | |
| 149 | + label: '创建时间', | |
| 150 | + component: 'RangePicker', | |
| 151 | + componentProps: { | |
| 152 | + ...getRangePickerDefaultProps(), | |
| 153 | + clearable: true, | |
| 154 | + }, | |
| 155 | + }, | |
| 156 | + ]; | |
| 157 | +} | |
| 158 | + | |
| 159 | +/** 列表的字段 */ | |
| 160 | +export function useGridColumns(): VxeTableGridOptions<InfraStudentApi.Student>['columns'] { | |
| 161 | + return [ | |
| 162 | + { type: 'checkbox', width: 40 }, | |
| 163 | + { | |
| 164 | + field: 'id', | |
| 165 | + title: '编号', | |
| 166 | + minWidth: 120, | |
| 167 | + cellRender: { | |
| 168 | + name: 'CellDict', | |
| 169 | + props: { type: DICT_TYPE.$dictType.toUpperCase() }, | |
| 170 | + }, | |
| 171 | + }, | |
| 172 | + { | |
| 173 | + field: 'name', | |
| 174 | + title: '名字', | |
| 175 | + minWidth: 120, | |
| 176 | + cellRender: { | |
| 177 | + name: 'CellDict', | |
| 178 | + props: { type: DICT_TYPE.$dictType.toUpperCase() }, | |
| 179 | + }, | |
| 180 | + }, | |
| 181 | + { | |
| 182 | + field: 'description', | |
| 183 | + title: '简介', | |
| 184 | + minWidth: 120, | |
| 185 | + cellRender: { | |
| 186 | + name: 'CellDict', | |
| 187 | + props: { type: DICT_TYPE.$dictType.toUpperCase() }, | |
| 188 | + }, | |
| 189 | + }, | |
| 190 | + { | |
| 191 | + field: 'birthday', | |
| 192 | + title: '出生日期', | |
| 193 | + minWidth: 120, | |
| 194 | + formatter: 'formatDateTime', | |
| 195 | + }, | |
| 196 | + { | |
| 197 | + field: 'sex', | |
| 198 | + title: '性别', | |
| 199 | + minWidth: 120, | |
| 200 | + cellRender: { | |
| 201 | + name: 'CellDict', | |
| 202 | + props: { type: DICT_TYPE.SYSTEM_USER_SEX }, | |
| 203 | + }, | |
| 204 | + }, | |
| 205 | + { | |
| 206 | + field: 'enabled', | |
| 207 | + title: '是否有效', | |
| 208 | + minWidth: 120, | |
| 209 | + cellRender: { | |
| 210 | + name: 'CellDict', | |
| 211 | + props: { type: DICT_TYPE.INFRA_BOOLEAN_STRING }, | |
| 212 | + }, | |
| 213 | + }, | |
| 214 | + { | |
| 215 | + field: 'avatar', | |
| 216 | + title: '头像', | |
| 217 | + minWidth: 120, | |
| 218 | + cellRender: { | |
| 219 | + name: 'CellDict', | |
| 220 | + props: { type: DICT_TYPE.$dictType.toUpperCase() }, | |
| 221 | + }, | |
| 222 | + }, | |
| 223 | + { | |
| 224 | + field: 'video', | |
| 225 | + title: '附件', | |
| 226 | + minWidth: 120, | |
| 227 | + cellRender: { | |
| 228 | + name: 'CellDict', | |
| 229 | + props: { type: DICT_TYPE.$dictType.toUpperCase() }, | |
| 230 | + }, | |
| 231 | + }, | |
| 232 | + { | |
| 233 | + field: 'memo', | |
| 234 | + title: '备注', | |
| 235 | + minWidth: 120, | |
| 236 | + cellRender: { | |
| 237 | + name: 'CellDict', | |
| 238 | + props: { type: DICT_TYPE.$dictType.toUpperCase() }, | |
| 239 | + }, | |
| 240 | + }, | |
| 241 | + { | |
| 242 | + field: 'createTime', | |
| 243 | + title: '创建时间', | |
| 244 | + minWidth: 120, | |
| 245 | + formatter: 'formatDateTime', | |
| 246 | + }, | |
| 247 | + { | |
| 248 | + title: '操作', | |
| 249 | + width: 200, | |
| 250 | + fixed: 'right', | |
| 251 | + slots: { default: 'actions' }, | |
| 252 | + }, | |
| 253 | + ]; | |
| 254 | +} | |
| 255 | + | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one_importEnable/ts/index
0 → 100644
| 1 | +import type { PageParam, PageResult } from '@vben/request'; | |
| 2 | +import type { Dayjs } from 'dayjs'; | |
| 3 | + | |
| 4 | +import { requestClient } from '#/api/request'; | |
| 5 | + | |
| 6 | +export namespace InfraStudentApi { | |
| 7 | + /** 学生信息 */ | |
| 8 | + export interface Student { | |
| 9 | + id: number; // 编号 | |
| 10 | + name?: string; // 名字 | |
| 11 | + description?: string; // 简介 | |
| 12 | + birthday?: string | Dayjs; // 出生日期 | |
| 13 | + sex?: number; // 性别 | |
| 14 | + enabled?: boolean; // 是否有效 | |
| 15 | + avatar?: string; // 头像 | |
| 16 | + video?: string; // 附件 | |
| 17 | + memo?: string; // 备注 | |
| 18 | + } | |
| 19 | +} | |
| 20 | + | |
| 21 | +/** 查询学生分页 */ | |
| 22 | +export function getStudentPage(params: PageParam) { | |
| 23 | + return requestClient.get<PageResult<InfraStudentApi.Student>>( | |
| 24 | + '/infra/student/page', | |
| 25 | + { params }, | |
| 26 | + ); | |
| 27 | +} | |
| 28 | + | |
| 29 | +/** 查询学生详情 */ | |
| 30 | +export function getStudent(id: number) { | |
| 31 | + return requestClient.get<InfraStudentApi.Student>( | |
| 32 | + `/infra/student/get?id=${id}`, | |
| 33 | + ); | |
| 34 | +} | |
| 35 | + | |
| 36 | +/** 新增学生 */ | |
| 37 | +export function createStudent(data: InfraStudentApi.Student) { | |
| 38 | + return requestClient.post('/infra/student/create', data); | |
| 39 | +} | |
| 40 | + | |
| 41 | +/** 修改学生 */ | |
| 42 | +export function updateStudent(data: InfraStudentApi.Student) { | |
| 43 | + return requestClient.put('/infra/student/update', data); | |
| 44 | +} | |
| 45 | + | |
| 46 | +/** 删除学生 */ | |
| 47 | +export function deleteStudent(id: number) { | |
| 48 | + return requestClient.delete(`/infra/student/delete?id=${id}`); | |
| 49 | +} | |
| 50 | + | |
| 51 | +/** 批量删除学生 */ | |
| 52 | +export function deleteStudentList(ids: number[]) { | |
| 53 | + return requestClient.delete( | |
| 54 | + `/infra/student/delete-list?ids=${ids.join(',')}`, | |
| 55 | + ); | |
| 56 | +} | |
| 57 | + | |
| 58 | +/** 导出学生 */ | |
| 59 | +export function exportStudent(params: any) { | |
| 60 | + return requestClient.download('/infra/student/export-excel', { params }); | |
| 61 | +} | |
| 62 | + | |
| 63 | +/** 下载学生导入模板 */ | |
| 64 | +export function importStudentTemplate() { | |
| 65 | + return requestClient.download('/infra/student/get-import-template'); | |
| 66 | +} | |
| 67 | + | |
| 68 | +/** 导入学生 */ | |
| 69 | +export function importStudent(file: File) { | |
| 70 | + return requestClient.upload('/infra/student/import', { file }); | |
| 71 | +} | |
| 0 | 72 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one_importEnable/vue/form
0 → 100644
| 1 | +<script lang="ts" setup> | |
| 2 | +import type { InfraStudentApi } from '#/api/infra/demo'; | |
| 3 | + | |
| 4 | +import { computed, ref } from 'vue'; | |
| 5 | + | |
| 6 | +import { useVbenModal } from '@vben/common-ui'; | |
| 7 | + | |
| 8 | +import { ElMessage } from 'element-plus'; | |
| 9 | + | |
| 10 | +import { useVbenForm } from '#/adapter/form'; | |
| 11 | +import { createStudent, getStudent, updateStudent } from '#/api/infra/demo'; | |
| 12 | +import { $t } from '#/locales'; | |
| 13 | + | |
| 14 | +import { useFormSchema } from '../data'; | |
| 15 | + | |
| 16 | +const emit = defineEmits(['success']); | |
| 17 | +const formData = ref<InfraStudentApi.Student>(); | |
| 18 | +const getTitle = computed(() => { | |
| 19 | + return formData.value?.id | |
| 20 | + ? $t('ui.actionTitle.edit', ['学生']) | |
| 21 | + : $t('ui.actionTitle.create', ['学生']); | |
| 22 | +}); | |
| 23 | + | |
| 24 | +const [Form, formApi] = useVbenForm({ | |
| 25 | + commonConfig: { | |
| 26 | + componentProps: { | |
| 27 | + class: 'w-full', | |
| 28 | + }, | |
| 29 | + formItemClass: 'col-span-2', | |
| 30 | + labelWidth: 80, | |
| 31 | + }, | |
| 32 | + layout: 'horizontal', | |
| 33 | + schema: useFormSchema(), | |
| 34 | + showDefaultActions: false, | |
| 35 | +}); | |
| 36 | + | |
| 37 | +const [Modal, modalApi] = useVbenModal({ | |
| 38 | + async onConfirm() { | |
| 39 | + const { valid } = await formApi.validate(); | |
| 40 | + if (!valid) { | |
| 41 | + return; | |
| 42 | + } | |
| 43 | + modalApi.lock(); | |
| 44 | + // 提交表单 | |
| 45 | + const data = (await formApi.getValues()) as InfraStudentApi.Student; | |
| 46 | + try { | |
| 47 | + await (formData.value?.id ? updateStudent(data) : createStudent(data)); | |
| 48 | + // 关闭并提示 | |
| 49 | + await modalApi.close(); | |
| 50 | + emit('success'); | |
| 51 | + ElMessage.success($t('ui.actionMessage.operationSuccess')); | |
| 52 | + } finally { | |
| 53 | + modalApi.unlock(); | |
| 54 | + } | |
| 55 | + }, | |
| 56 | + async onOpenChange(isOpen: boolean) { | |
| 57 | + if (!isOpen) { | |
| 58 | + formData.value = undefined; | |
| 59 | + return; | |
| 60 | + } | |
| 61 | + // 加载数据 | |
| 62 | + const data = modalApi.getData<InfraStudentApi.Student>(); | |
| 63 | + if (!data || !data.id) { | |
| 64 | + return; | |
| 65 | + } | |
| 66 | + modalApi.lock(); | |
| 67 | + try { | |
| 68 | + formData.value = await getStudent(data.id); | |
| 69 | + // 设置到 values | |
| 70 | + await formApi.setValues(formData.value); | |
| 71 | + } finally { | |
| 72 | + modalApi.unlock(); | |
| 73 | + } | |
| 74 | + }, | |
| 75 | +}); | |
| 76 | +</script> | |
| 77 | + | |
| 78 | +<template> | |
| 79 | + <Modal :title="getTitle"> | |
| 80 | + <Form class="mx-4" /> | |
| 81 | + </Modal> | |
| 82 | +</template> | |
| 0 | 83 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one_importEnable/vue/import-form
0 → 100644
| 1 | +<script lang="ts" setup> | |
| 2 | +import { useVbenModal } from '@vben/common-ui'; | |
| 3 | +import { downloadFileFromBlobPart } from '@vben/utils'; | |
| 4 | + | |
| 5 | +import { ElButton, ElMessage, ElUpload } from 'element-plus'; | |
| 6 | + | |
| 7 | +import { useVbenForm } from '#/adapter/form'; | |
| 8 | +import { importStudent, importStudentTemplate } from '#/api/infra/demo'; | |
| 9 | +import { $t } from '#/locales'; | |
| 10 | + | |
| 11 | +import { useImportFormSchema } from '../data'; | |
| 12 | + | |
| 13 | +const emit = defineEmits(['success']); | |
| 14 | + | |
| 15 | +const [Form, formApi] = useVbenForm({ | |
| 16 | + commonConfig: { | |
| 17 | + formItemClass: 'col-span-2', | |
| 18 | + labelWidth: 120, | |
| 19 | + }, | |
| 20 | + layout: 'horizontal', | |
| 21 | + schema: useImportFormSchema(), | |
| 22 | + showDefaultActions: false, | |
| 23 | +}); | |
| 24 | + | |
| 25 | +const [Modal, modalApi] = useVbenModal({ | |
| 26 | + async onConfirm() { | |
| 27 | + const { valid } = await formApi.validate(); | |
| 28 | + if (!valid) { | |
| 29 | + return; | |
| 30 | + } | |
| 31 | + modalApi.lock(); | |
| 32 | + // 提交表单 | |
| 33 | + const data = await formApi.getValues(); | |
| 34 | + try { | |
| 35 | + await importStudent(data.file); | |
| 36 | + // 关闭并提示 | |
| 37 | + await modalApi.close(); | |
| 38 | + emit('success'); | |
| 39 | + ElMessage.success($t('ui.actionMessage.operationSuccess')); | |
| 40 | + } finally { | |
| 41 | + modalApi.unlock(); | |
| 42 | + } | |
| 43 | + }, | |
| 44 | +}); | |
| 45 | + | |
| 46 | +/** 文件改变时 */ | |
| 47 | +function handleChange(file: any) { | |
| 48 | + if (file.raw) { | |
| 49 | + formApi.setFieldValue('file', file.raw); | |
| 50 | + } | |
| 51 | +} | |
| 52 | + | |
| 53 | +/** 下载模板 */ | |
| 54 | +async function handleDownload() { | |
| 55 | + const data = await importStudentTemplate(); | |
| 56 | + downloadFileFromBlobPart({ fileName: '学生导入模板.xls', source: data }); | |
| 57 | +} | |
| 58 | +</script> | |
| 59 | + | |
| 60 | +<template> | |
| 61 | + <Modal title="导入学生" class="w-1/3"> | |
| 62 | + <Form class="mx-4"> | |
| 63 | + <template #file> | |
| 64 | + <div class="w-full"> | |
| 65 | + <ElUpload | |
| 66 | + :limit="1" | |
| 67 | + accept=".xls,.xlsx" | |
| 68 | + :on-change="handleChange" | |
| 69 | + :auto-upload="false" | |
| 70 | + > | |
| 71 | + <ElButton type="primary"> 选择 Excel 文件 </ElButton> | |
| 72 | + </ElUpload> | |
| 73 | + </div> | |
| 74 | + </template> | |
| 75 | + </Form> | |
| 76 | + <template #prepend-footer> | |
| 77 | + <div class="flex flex-auto items-center"> | |
| 78 | + <ElButton @click="handleDownload"> 下载导入模板 </ElButton> | |
| 79 | + </div> | |
| 80 | + </template> | |
| 81 | + </Modal> | |
| 82 | +</template> | |
| 0 | 83 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one_importEnable/vue/index
0 → 100644
| 1 | +<script lang="ts" setup> | |
| 2 | +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; | |
| 3 | +import type { InfraStudentApi } from '#/api/infra/demo'; | |
| 4 | + | |
| 5 | +import { ref } from 'vue'; | |
| 6 | + | |
| 7 | +import { confirm, Page, useVbenModal } from '@vben/common-ui'; | |
| 8 | +import { downloadFileFromBlobPart, isEmpty } from '@vben/utils'; | |
| 9 | + | |
| 10 | +import { ElLoading, ElMessage } from 'element-plus'; | |
| 11 | + | |
| 12 | +import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; | |
| 13 | +import { | |
| 14 | + deleteStudent, | |
| 15 | + deleteStudentList, | |
| 16 | + exportStudent, | |
| 17 | + getStudentPage, | |
| 18 | +} from '#/api/infra/demo'; | |
| 19 | +import StudentImport from './modules/import-form.vue'; | |
| 20 | +import { $t } from '#/locales'; | |
| 21 | + | |
| 22 | +import { useGridColumns, useGridFormSchema } from './data'; | |
| 23 | +import Form from './modules/form.vue'; | |
| 24 | + | |
| 25 | +const [FormModal, formModalApi] = useVbenModal({ | |
| 26 | + connectedComponent: Form, | |
| 27 | + destroyOnClose: true, | |
| 28 | +}); | |
| 29 | +const [ImportFormModal, importFormModalApi] = useVbenModal({ | |
| 30 | + connectedComponent: StudentImport, | |
| 31 | + destroyOnClose: true, | |
| 32 | +}); | |
| 33 | + | |
| 34 | +/** 导入学生 */ | |
| 35 | +function handleImport() { | |
| 36 | + importFormModalApi.open(); | |
| 37 | +} | |
| 38 | + | |
| 39 | +/** 刷新表格 */ | |
| 40 | +function handleRefresh() { | |
| 41 | + gridApi.query(); | |
| 42 | +} | |
| 43 | + | |
| 44 | +/** 创建学生 */ | |
| 45 | +function handleCreate() { | |
| 46 | + formModalApi.setData(null).open(); | |
| 47 | +} | |
| 48 | + | |
| 49 | +/** 编辑学生 */ | |
| 50 | +function handleEdit(row: InfraStudentApi.Student) { | |
| 51 | + formModalApi.setData(row).open(); | |
| 52 | +} | |
| 53 | + | |
| 54 | +/** 删除学生 */ | |
| 55 | +async function handleDelete(row: InfraStudentApi.Student) { | |
| 56 | + const loadingInstance = ElLoading.service({ | |
| 57 | + text: $t('ui.actionMessage.deleting', [row.id]), | |
| 58 | + }); | |
| 59 | + try { | |
| 60 | + await deleteStudent(row.id!); | |
| 61 | + ElMessage.success($t('ui.actionMessage.deleteSuccess', [row.id])); | |
| 62 | + handleRefresh(); | |
| 63 | + } finally { | |
| 64 | + loadingInstance.close(); | |
| 65 | + } | |
| 66 | +} | |
| 67 | + | |
| 68 | +/** 批量删除学生 */ | |
| 69 | +async function handleDeleteBatch() { | |
| 70 | + await confirm($t('ui.actionMessage.deleteBatchConfirm')); | |
| 71 | + const loadingInstance = ElLoading.service({ | |
| 72 | + text: $t('ui.actionMessage.deletingBatch'), | |
| 73 | + }); | |
| 74 | + try { | |
| 75 | + await deleteStudentList(checkedIds.value); | |
| 76 | + checkedIds.value = []; | |
| 77 | + ElMessage.success($t('ui.actionMessage.deleteSuccess')); | |
| 78 | + handleRefresh(); | |
| 79 | + } finally { | |
| 80 | + loadingInstance.close(); | |
| 81 | + } | |
| 82 | +} | |
| 83 | + | |
| 84 | +const checkedIds = ref<number[]>([]); | |
| 85 | +function handleRowCheckboxChange({ | |
| 86 | + records, | |
| 87 | +}: { | |
| 88 | + records: InfraStudentApi.Student[]; | |
| 89 | +}) { | |
| 90 | + checkedIds.value = records.map((item) => item.id!); | |
| 91 | +} | |
| 92 | + | |
| 93 | +/** 导出表格 */ | |
| 94 | +async function handleExport() { | |
| 95 | + const data = await exportStudent(await gridApi.formApi.getValues()); | |
| 96 | + downloadFileFromBlobPart({ fileName: '学生.xls', source: data }); | |
| 97 | +} | |
| 98 | + | |
| 99 | + | |
| 100 | +const [Grid, gridApi] = useVbenVxeGrid({ | |
| 101 | + formOptions: { | |
| 102 | + schema: useGridFormSchema(), | |
| 103 | + }, | |
| 104 | + gridOptions: { | |
| 105 | + columns: useGridColumns(), | |
| 106 | + height: 'auto', | |
| 107 | + keepSource: true, | |
| 108 | + proxyConfig: { | |
| 109 | + ajax: { | |
| 110 | + query: async ({ page }, formValues) => { | |
| 111 | + return await getStudentPage({ | |
| 112 | + pageNo: page.currentPage, | |
| 113 | + pageSize: page.pageSize, | |
| 114 | + ...formValues, | |
| 115 | + }); | |
| 116 | + }, | |
| 117 | + }, | |
| 118 | + }, | |
| 119 | + rowConfig: { | |
| 120 | + keyField: 'id', | |
| 121 | + isHover: true, | |
| 122 | + }, | |
| 123 | + toolbarConfig: { | |
| 124 | + refresh: true, | |
| 125 | + search: true, | |
| 126 | + }, | |
| 127 | + } as VxeTableGridOptions<InfraStudentApi.Student>, | |
| 128 | + gridEvents: { | |
| 129 | + checkboxAll: handleRowCheckboxChange, | |
| 130 | + checkboxChange: handleRowCheckboxChange, | |
| 131 | + }, | |
| 132 | +}); | |
| 133 | +</script> | |
| 134 | + | |
| 135 | +<template> | |
| 136 | + <Page auto-content-height> | |
| 137 | + <FormModal @success="handleRefresh" /> | |
| 138 | + <ImportFormModal @success="handleRefresh" /> | |
| 139 | + <Grid table-title="学生列表"> | |
| 140 | + <template #toolbar-tools> | |
| 141 | + <TableAction | |
| 142 | + :actions="[ | |
| 143 | + { | |
| 144 | + label: $t('ui.actionTitle.create', ['学生']), | |
| 145 | + type: 'primary', | |
| 146 | + icon: ACTION_ICON.ADD, | |
| 147 | + auth: ['infra:student:create'], | |
| 148 | + onClick: handleCreate, | |
| 149 | + }, | |
| 150 | + { | |
| 151 | + label: '导入', | |
| 152 | + type: 'primary', | |
| 153 | + auth: ['infra:student:import'], | |
| 154 | + onClick: handleImport, | |
| 155 | + }, | |
| 156 | + { | |
| 157 | + label: $t('ui.actionTitle.export'), | |
| 158 | + type: 'primary', | |
| 159 | + icon: ACTION_ICON.DOWNLOAD, | |
| 160 | + auth: ['infra:student:export'], | |
| 161 | + onClick: handleExport, | |
| 162 | + }, | |
| 163 | + { | |
| 164 | + label: $t('ui.actionTitle.deleteBatch'), | |
| 165 | + type: 'danger', | |
| 166 | + icon: ACTION_ICON.DELETE, | |
| 167 | + auth: ['infra:student:delete'], | |
| 168 | + disabled: isEmpty(checkedIds), | |
| 169 | + onClick: handleDeleteBatch, | |
| 170 | + }, | |
| 171 | + ]" | |
| 172 | + /> | |
| 173 | + </template> | |
| 174 | + <template #actions="{ row }"> | |
| 175 | + <TableAction | |
| 176 | + :actions="[ | |
| 177 | + { | |
| 178 | + label: $t('common.edit'), | |
| 179 | + type: 'primary', | |
| 180 | + link: true, | |
| 181 | + icon: ACTION_ICON.EDIT, | |
| 182 | + auth: ['infra:student:update'], | |
| 183 | + onClick: handleEdit.bind(null, row), | |
| 184 | + }, | |
| 185 | + { | |
| 186 | + label: $t('common.delete'), | |
| 187 | + type: 'danger', | |
| 188 | + link: true, | |
| 189 | + icon: ACTION_ICON.DELETE, | |
| 190 | + auth: ['infra:student:delete'], | |
| 191 | + popConfirm: { | |
| 192 | + title: $t('ui.actionMessage.deleteConfirm', [row.id]), | |
| 193 | + confirm: handleDelete.bind(null, row), | |
| 194 | + }, | |
| 195 | + }, | |
| 196 | + ]" | |
| 197 | + /> | |
| 198 | + </template> | |
| 199 | + </Grid> | |
| 200 | + </Page> | |
| 201 | +</template> | |
| 0 | 202 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one_importEnable/xml/InfraStudentMapper
0 → 100644
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | |
| 2 | +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | |
| 3 | +<mapper namespace="cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper"> | |
| 4 | + | |
| 5 | + <!-- | |
| 6 | + 一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。 | |
| 7 | + 无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。 | |
| 8 | + 代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。 | |
| 9 | + 文档可见:https://www.iocoder.cn/MyBatis/x-plugins/ | |
| 10 | + --> | |
| 11 | + | |
| 12 | +</mapper> | |
| 0 | 13 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vue2_one_importEnable/assert.json
0 → 100644
| 1 | +[ { | |
| 2 | + "contentPath" : "java/InfraStudentPageReqVO", | |
| 3 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentPageReqVO.java" | |
| 4 | +}, { | |
| 5 | + "contentPath" : "java/InfraStudentRespVO", | |
| 6 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentRespVO.java" | |
| 7 | +}, { | |
| 8 | + "contentPath" : "java/InfraStudentSaveReqVO", | |
| 9 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentSaveReqVO.java" | |
| 10 | +}, { | |
| 11 | + "contentPath" : "java/InfraStudentImportExcelVO", | |
| 12 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentImportExcelVO.java" | |
| 13 | +}, { | |
| 14 | + "contentPath" : "java/InfraStudentImportRespVO", | |
| 15 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentImportRespVO.java" | |
| 16 | +}, { | |
| 17 | + "contentPath" : "java/InfraStudentController", | |
| 18 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/InfraStudentController.java" | |
| 19 | +}, { | |
| 20 | + "contentPath" : "java/InfraStudentDO", | |
| 21 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentDO.java" | |
| 22 | +}, { | |
| 23 | + "contentPath" : "java/InfraStudentMapper", | |
| 24 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentMapper.java" | |
| 25 | +}, { | |
| 26 | + "contentPath" : "xml/InfraStudentMapper", | |
| 27 | + "filePath" : "yudao-module-infra/src/main/resources/mapper/demo/InfraStudentMapper.xml" | |
| 28 | +}, { | |
| 29 | + "contentPath" : "java/InfraStudentServiceImpl", | |
| 30 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImpl.java" | |
| 31 | +}, { | |
| 32 | + "contentPath" : "java/InfraStudentService", | |
| 33 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentService.java" | |
| 34 | +}, { | |
| 35 | + "contentPath" : "java/InfraStudentServiceImplTest", | |
| 36 | + "filePath" : "yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImplTest.java" | |
| 37 | +}, { | |
| 38 | + "contentPath" : "java/ErrorCodeConstants_手动操作", | |
| 39 | + "filePath" : "yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants_手动操作.java" | |
| 40 | +}, { | |
| 41 | + "contentPath" : "sql/sql", | |
| 42 | + "filePath" : "sql/sql.sql" | |
| 43 | +}, { | |
| 44 | + "contentPath" : "sql/h2", | |
| 45 | + "filePath" : "sql/h2.sql" | |
| 46 | +}, { | |
| 47 | + "contentPath" : "vue/index", | |
| 48 | + "filePath" : "yudao-ui-admin-vue2/src/views/infra/demo/index.vue" | |
| 49 | +}, { | |
| 50 | + "contentPath" : "js/index", | |
| 51 | + "filePath" : "yudao-ui-admin-vue2/src/api/infra/demo/index.js" | |
| 52 | +}, { | |
| 53 | + "contentPath" : "vue/StudentForm", | |
| 54 | + "filePath" : "yudao-ui-admin-vue2/src/views/infra/demo/StudentForm.vue" | |
| 55 | +} ] | |
| 0 | 56 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vue2_one_importEnable/java/ErrorCodeConstants_手动操作
0 → 100644
yudao-module-infra/src/test/resources/codegen/vue2_one_importEnable/java/InfraStudentController
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.controller.admin.demo; | |
| 2 | + | |
| 3 | +import org.springframework.web.bind.annotation.*; | |
| 4 | +import org.springframework.web.multipart.MultipartFile; | |
| 5 | +import jakarta.annotation.Resource; | |
| 6 | +import org.springframework.validation.annotation.Validated; | |
| 7 | +import org.springframework.security.access.prepost.PreAuthorize; | |
| 8 | +import io.swagger.v3.oas.annotations.tags.Tag; | |
| 9 | +import io.swagger.v3.oas.annotations.Parameter; | |
| 10 | +import io.swagger.v3.oas.annotations.Operation; | |
| 11 | + | |
| 12 | +import jakarta.validation.constraints.*; | |
| 13 | +import jakarta.validation.*; | |
| 14 | +import jakarta.servlet.http.*; | |
| 15 | +import java.util.*; | |
| 16 | +import java.io.IOException; | |
| 17 | + | |
| 18 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | |
| 19 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 20 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | |
| 21 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | |
| 22 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | |
| 23 | + | |
| 24 | +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; | |
| 25 | + | |
| 26 | +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; | |
| 27 | +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*; | |
| 28 | + | |
| 29 | +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; | |
| 30 | +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; | |
| 31 | +import cn.iocoder.yudao.module.infra.service.demo.InfraStudentService; | |
| 32 | + | |
| 33 | +@Tag(name = "管理后台 - 学生") | |
| 34 | +@RestController | |
| 35 | +@RequestMapping("/infra/student") | |
| 36 | +@Validated | |
| 37 | +public class InfraStudentController { | |
| 38 | + | |
| 39 | + @Resource | |
| 40 | + private InfraStudentService studentService; | |
| 41 | + | |
| 42 | + @PostMapping("/create") | |
| 43 | + @Operation(summary = "创建学生") | |
| 44 | + @PreAuthorize("@ss.hasPermission('infra:student:create')") | |
| 45 | + public CommonResult<Long> createStudent(@Valid @RequestBody InfraStudentSaveReqVO createReqVO) { | |
| 46 | + return success(studentService.createStudent(createReqVO)); | |
| 47 | + } | |
| 48 | + | |
| 49 | + @PutMapping("/update") | |
| 50 | + @Operation(summary = "更新学生") | |
| 51 | + @PreAuthorize("@ss.hasPermission('infra:student:update')") | |
| 52 | + public CommonResult<Boolean> updateStudent(@Valid @RequestBody InfraStudentSaveReqVO updateReqVO) { | |
| 53 | + studentService.updateStudent(updateReqVO); | |
| 54 | + return success(true); | |
| 55 | + } | |
| 56 | + | |
| 57 | + @DeleteMapping("/delete") | |
| 58 | + @Operation(summary = "删除学生") | |
| 59 | + @Parameter(name = "id", description = "编号", required = true) | |
| 60 | + @PreAuthorize("@ss.hasPermission('infra:student:delete')") | |
| 61 | + public CommonResult<Boolean> deleteStudent(@RequestParam("id") Long id) { | |
| 62 | + studentService.deleteStudent(id); | |
| 63 | + return success(true); | |
| 64 | + } | |
| 65 | + | |
| 66 | + @DeleteMapping("/delete-list") | |
| 67 | + @Parameter(name = "ids", description = "编号", required = true) | |
| 68 | + @Operation(summary = "批量删除学生") | |
| 69 | + @PreAuthorize("@ss.hasPermission('infra:student:delete')") | |
| 70 | + public CommonResult<Boolean> deleteStudentList(@RequestParam("ids") List<Long> ids) { | |
| 71 | + studentService.deleteStudentListByIds(ids); | |
| 72 | + return success(true); | |
| 73 | + } | |
| 74 | + | |
| 75 | + @GetMapping("/get") | |
| 76 | + @Operation(summary = "获得学生") | |
| 77 | + @Parameter(name = "id", description = "编号", required = true, example = "1024") | |
| 78 | + @PreAuthorize("@ss.hasPermission('infra:student:query')") | |
| 79 | + public CommonResult<InfraStudentRespVO> getStudent(@RequestParam("id") Long id) { | |
| 80 | + InfraStudentDO student = studentService.getStudent(id); | |
| 81 | + return success(BeanUtils.toBean(student, InfraStudentRespVO.class)); | |
| 82 | + } | |
| 83 | + | |
| 84 | + @GetMapping("/page") | |
| 85 | + @Operation(summary = "获得学生分页") | |
| 86 | + @PreAuthorize("@ss.hasPermission('infra:student:query')") | |
| 87 | + public CommonResult<PageResult<InfraStudentRespVO>> getStudentPage(@Valid InfraStudentPageReqVO pageReqVO) { | |
| 88 | + PageResult<InfraStudentDO> pageResult = studentService.getStudentPage(pageReqVO); | |
| 89 | + return success(BeanUtils.toBean(pageResult, InfraStudentRespVO.class)); | |
| 90 | + } | |
| 91 | + | |
| 92 | + @GetMapping("/export-excel") | |
| 93 | + @Operation(summary = "导出学生 Excel") | |
| 94 | + @PreAuthorize("@ss.hasPermission('infra:student:export')") | |
| 95 | + @ApiAccessLog(operateType = EXPORT) | |
| 96 | + public void exportStudentExcel(@Valid InfraStudentPageReqVO pageReqVO, | |
| 97 | + HttpServletResponse response) throws IOException { | |
| 98 | + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); | |
| 99 | + List<InfraStudentDO> list = studentService.getStudentPage(pageReqVO).getList(); | |
| 100 | + // 导出 Excel | |
| 101 | + ExcelUtils.write(response, "学生.xls", "数据", InfraStudentRespVO.class, | |
| 102 | + BeanUtils.toBean(list, InfraStudentRespVO.class)); | |
| 103 | + } | |
| 104 | + | |
| 105 | + @GetMapping("/get-import-template") | |
| 106 | + @Operation(summary = "获得导入学生模板") | |
| 107 | + @PreAuthorize("@ss.hasPermission('infra:student:import')") | |
| 108 | + public void importTemplate(HttpServletResponse response) throws IOException { | |
| 109 | + ExcelUtils.write(response, "学生导入模板.xls", "数据", | |
| 110 | + InfraStudentImportExcelVO.class, Collections.emptyList()); | |
| 111 | + } | |
| 112 | + | |
| 113 | + @PostMapping("/import") | |
| 114 | + @Operation(summary = "导入学生") | |
| 115 | + @Parameter(name = "file", description = "Excel 文件", required = true) | |
| 116 | + @PreAuthorize("@ss.hasPermission('infra:student:import')") | |
| 117 | + public CommonResult<InfraStudentImportRespVO> importExcel(@RequestParam("file") MultipartFile file) throws Exception { | |
| 118 | + List<InfraStudentImportExcelVO> list = ExcelUtils.read(file, InfraStudentImportExcelVO.class); | |
| 119 | + return success(studentService.importStudentList(list)); | |
| 120 | + } | |
| 121 | + | |
| 122 | +} | |
| 0 | 123 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vue2_one_importEnable/java/InfraStudentDO
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.dal.dataobject.demo; | |
| 2 | + | |
| 3 | +import lombok.*; | |
| 4 | +import java.util.*; | |
| 5 | +import java.time.LocalDateTime; | |
| 6 | +import java.time.LocalDateTime; | |
| 7 | +import com.baomidou.mybatisplus.annotation.*; | |
| 8 | +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | |
| 9 | + | |
| 10 | +/** | |
| 11 | + * 学生 DO | |
| 12 | + * | |
| 13 | + * @author 芋道源码 | |
| 14 | + */ | |
| 15 | +@TableName("infra_student") | |
| 16 | +@KeySequence("infra_student_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 | |
| 17 | +@Data | |
| 18 | +@EqualsAndHashCode(callSuper = true) | |
| 19 | +@ToString(callSuper = true) | |
| 20 | +@Builder | |
| 21 | +@NoArgsConstructor | |
| 22 | +@AllArgsConstructor | |
| 23 | +public class InfraStudentDO extends BaseDO { | |
| 24 | + | |
| 25 | + /** | |
| 26 | + * 编号 | |
| 27 | + */ | |
| 28 | + @TableId | |
| 29 | + private Long id; | |
| 30 | + /** | |
| 31 | + * 名字 | |
| 32 | + */ | |
| 33 | + private String name; | |
| 34 | + /** | |
| 35 | + * 简介 | |
| 36 | + */ | |
| 37 | + private String description; | |
| 38 | + /** | |
| 39 | + * 出生日期 | |
| 40 | + */ | |
| 41 | + private LocalDateTime birthday; | |
| 42 | + /** | |
| 43 | + * 性别 | |
| 44 | + * | |
| 45 | + * 枚举 {@link TODO system_user_sex 对应的类} | |
| 46 | + */ | |
| 47 | + private Integer sex; | |
| 48 | + /** | |
| 49 | + * 是否有效 | |
| 50 | + * | |
| 51 | + * 枚举 {@link TODO infra_boolean_string 对应的类} | |
| 52 | + */ | |
| 53 | + private Boolean enabled; | |
| 54 | + /** | |
| 55 | + * 头像 | |
| 56 | + */ | |
| 57 | + private String avatar; | |
| 58 | + /** | |
| 59 | + * 附件 | |
| 60 | + */ | |
| 61 | + private String video; | |
| 62 | + /** | |
| 63 | + * 备注 | |
| 64 | + */ | |
| 65 | + private String memo; | |
| 66 | + | |
| 67 | + | |
| 68 | +} | |
| 0 | 69 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vue2_one_importEnable/java/InfraStudentImportExcelVO
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; | |
| 2 | + | |
| 3 | +import cn.idev.excel.annotation.ExcelProperty; | |
| 4 | +import lombok.AllArgsConstructor; | |
| 5 | +import lombok.Builder; | |
| 6 | +import lombok.Data; | |
| 7 | +import lombok.NoArgsConstructor; | |
| 8 | +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; | |
| 9 | +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * 学生 Excel 导入 VO | |
| 13 | + */ | |
| 14 | +@Data | |
| 15 | +@Builder | |
| 16 | +@AllArgsConstructor | |
| 17 | +@NoArgsConstructor | |
| 18 | +public class InfraStudentImportExcelVO { | |
| 19 | + | |
| 20 | + @ExcelProperty("名字") | |
| 21 | + private String name; | |
| 22 | + | |
| 23 | + @ExcelProperty("简介") | |
| 24 | + private String description; | |
| 25 | + | |
| 26 | + @ExcelProperty("出生日期") | |
| 27 | + private LocalDateTime birthday; | |
| 28 | + | |
| 29 | + @ExcelProperty(value = "性别", converter = DictConvert.class) | |
| 30 | + @DictFormat("system_user_sex") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 | |
| 31 | + private Integer sex; | |
| 32 | + | |
| 33 | + @ExcelProperty(value = "是否有效", converter = DictConvert.class) | |
| 34 | + @DictFormat("infra_boolean_string") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 | |
| 35 | + private Boolean enabled; | |
| 36 | + | |
| 37 | + @ExcelProperty("头像") | |
| 38 | + private String avatar; | |
| 39 | + | |
| 40 | + @ExcelProperty("附件") | |
| 41 | + private String video; | |
| 42 | + | |
| 43 | + @ExcelProperty("备注") | |
| 44 | + private String memo; | |
| 45 | + | |
| 46 | +} | |
| 0 | 47 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vue2_one_importEnable/java/InfraStudentImportRespVO
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; | |
| 2 | + | |
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 4 | +import lombok.Builder; | |
| 5 | +import lombok.Data; | |
| 6 | + | |
| 7 | +import java.util.Map; | |
| 8 | + | |
| 9 | +@Schema(description = "管理后台 - 学生导入 Response VO") | |
| 10 | +@Data | |
| 11 | +@Builder | |
| 12 | +public class InfraStudentImportRespVO { | |
| 13 | + | |
| 14 | + @Schema(description = "创建成功的数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") | |
| 15 | + private Integer successCount; | |
| 16 | + | |
| 17 | + @Schema(description = "导入失败的数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | |
| 18 | + private Integer failureCount; | |
| 19 | + | |
| 20 | + @Schema(description = "导入失败的数据集合,key 为行号,value 为失败原因", requiredMode = Schema.RequiredMode.REQUIRED) | |
| 21 | + private Map<Integer, String> failureRows; | |
| 22 | + | |
| 23 | +} | |
| 0 | 24 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vue2_one_importEnable/java/InfraStudentMapper
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.dal.mysql.demo; | |
| 2 | + | |
| 3 | +import java.util.*; | |
| 4 | + | |
| 5 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 6 | +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | |
| 7 | +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | |
| 8 | +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; | |
| 9 | +import org.apache.ibatis.annotations.Mapper; | |
| 10 | +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; | |
| 11 | + | |
| 12 | +/** | |
| 13 | + * 学生 Mapper | |
| 14 | + * | |
| 15 | + * @author 芋道源码 | |
| 16 | + */ | |
| 17 | +@Mapper | |
| 18 | +public interface InfraStudentMapper extends BaseMapperX<InfraStudentDO> { | |
| 19 | + | |
| 20 | + default PageResult<InfraStudentDO> selectPage(InfraStudentPageReqVO reqVO) { | |
| 21 | + return selectPage(reqVO, new LambdaQueryWrapperX<InfraStudentDO>() | |
| 22 | + .likeIfPresent(InfraStudentDO::getName, reqVO.getName()) | |
| 23 | + .eqIfPresent(InfraStudentDO::getBirthday, reqVO.getBirthday()) | |
| 24 | + .eqIfPresent(InfraStudentDO::getSex, reqVO.getSex()) | |
| 25 | + .eqIfPresent(InfraStudentDO::getEnabled, reqVO.getEnabled()) | |
| 26 | + .betweenIfPresent(InfraStudentDO::getCreateTime, reqVO.getCreateTime()) | |
| 27 | + .orderByDesc(InfraStudentDO::getId)); | |
| 28 | + } | |
| 29 | + | |
| 30 | +} | |
| 0 | 31 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vue2_one_importEnable/java/InfraStudentPageReqVO
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; | |
| 2 | + | |
| 3 | +import lombok.*; | |
| 4 | +import java.util.*; | |
| 5 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 6 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | |
| 7 | +import org.springframework.format.annotation.DateTimeFormat; | |
| 8 | +import java.time.LocalDateTime; | |
| 9 | + | |
| 10 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | |
| 11 | + | |
| 12 | +@Schema(description = "管理后台 - 学生分页 Request VO") | |
| 13 | +@Data | |
| 14 | +public class InfraStudentPageReqVO extends PageParam { | |
| 15 | + | |
| 16 | + @Schema(description = "名字", example = "芋头") | |
| 17 | + private String name; | |
| 18 | + | |
| 19 | + @Schema(description = "出生日期") | |
| 20 | + private LocalDateTime birthday; | |
| 21 | + | |
| 22 | + @Schema(description = "性别", example = "1") | |
| 23 | + private Integer sex; | |
| 24 | + | |
| 25 | + @Schema(description = "是否有效", example = "true") | |
| 26 | + private Boolean enabled; | |
| 27 | + | |
| 28 | + @Schema(description = "创建时间") | |
| 29 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 30 | + private LocalDateTime[] createTime; | |
| 31 | + | |
| 32 | +} | |
| 0 | 33 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vue2_one_importEnable/java/InfraStudentRespVO
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; | |
| 2 | + | |
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 4 | +import lombok.*; | |
| 5 | +import java.util.*; | |
| 6 | +import org.springframework.format.annotation.DateTimeFormat; | |
| 7 | +import java.time.LocalDateTime; | |
| 8 | +import cn.idev.excel.annotation.*; | |
| 9 | +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; | |
| 10 | +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; | |
| 11 | + | |
| 12 | +@Schema(description = "管理后台 - 学生 Response VO") | |
| 13 | +@Data | |
| 14 | +@ExcelIgnoreUnannotated | |
| 15 | +public class InfraStudentRespVO { | |
| 16 | + | |
| 17 | + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | |
| 18 | + @ExcelProperty("编号") | |
| 19 | + private Long id; | |
| 20 | + | |
| 21 | + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头") | |
| 22 | + @ExcelProperty("名字") | |
| 23 | + private String name; | |
| 24 | + | |
| 25 | + @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍") | |
| 26 | + @ExcelProperty("简介") | |
| 27 | + private String description; | |
| 28 | + | |
| 29 | + @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED) | |
| 30 | + @ExcelProperty("出生日期") | |
| 31 | + private LocalDateTime birthday; | |
| 32 | + | |
| 33 | + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | |
| 34 | + @ExcelProperty(value = "性别", converter = DictConvert.class) | |
| 35 | + @DictFormat("system_user_sex") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 | |
| 36 | + private Integer sex; | |
| 37 | + | |
| 38 | + @Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") | |
| 39 | + @ExcelProperty(value = "是否有效", converter = DictConvert.class) | |
| 40 | + @DictFormat("infra_boolean_string") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 | |
| 41 | + private Boolean enabled; | |
| 42 | + | |
| 43 | + @Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") | |
| 44 | + @ExcelProperty("头像") | |
| 45 | + private String avatar; | |
| 46 | + | |
| 47 | + @Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4") | |
| 48 | + @ExcelProperty("附件") | |
| 49 | + private String video; | |
| 50 | + | |
| 51 | + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注") | |
| 52 | + @ExcelProperty("备注") | |
| 53 | + private String memo; | |
| 54 | + | |
| 55 | + @Schema(description = "创建时间") | |
| 56 | + @ExcelProperty("创建时间") | |
| 57 | + private LocalDateTime createTime; | |
| 58 | + | |
| 59 | +} | |
| 0 | 60 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vue2_one_importEnable/java/InfraStudentSaveReqVO
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; | |
| 2 | + | |
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 4 | +import lombok.*; | |
| 5 | +import java.util.*; | |
| 6 | +import jakarta.validation.constraints.*; | |
| 7 | +import org.springframework.format.annotation.DateTimeFormat; | |
| 8 | +import java.time.LocalDateTime; | |
| 9 | + | |
| 10 | +@Schema(description = "管理后台 - 学生新增/修改 Request VO") | |
| 11 | +@Data | |
| 12 | +public class InfraStudentSaveReqVO { | |
| 13 | + | |
| 14 | + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | |
| 15 | + private Long id; | |
| 16 | + | |
| 17 | + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头") | |
| 18 | + @NotEmpty(message = "名字不能为空") | |
| 19 | + private String name; | |
| 20 | + | |
| 21 | + @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍") | |
| 22 | + @NotEmpty(message = "简介不能为空") | |
| 23 | + private String description; | |
| 24 | + | |
| 25 | + @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED) | |
| 26 | + @NotNull(message = "出生日期不能为空") | |
| 27 | + private LocalDateTime birthday; | |
| 28 | + | |
| 29 | + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | |
| 30 | + @NotNull(message = "性别不能为空") | |
| 31 | + private Integer sex; | |
| 32 | + | |
| 33 | + @Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") | |
| 34 | + @NotNull(message = "是否有效不能为空") | |
| 35 | + private Boolean enabled; | |
| 36 | + | |
| 37 | + @Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") | |
| 38 | + @NotEmpty(message = "头像不能为空") | |
| 39 | + private String avatar; | |
| 40 | + | |
| 41 | + @Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4") | |
| 42 | + @NotEmpty(message = "附件不能为空") | |
| 43 | + private String video; | |
| 44 | + | |
| 45 | + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注") | |
| 46 | + @NotEmpty(message = "备注不能为空") | |
| 47 | + private String memo; | |
| 48 | + | |
| 49 | +} | |
| 0 | 50 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vue2_one_importEnable/java/InfraStudentService
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.service.demo; | |
| 2 | + | |
| 3 | +import java.util.*; | |
| 4 | +import jakarta.validation.*; | |
| 5 | +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; | |
| 6 | +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; | |
| 7 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 8 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | |
| 9 | + | |
| 10 | +/** | |
| 11 | + * 学生 Service 接口 | |
| 12 | + * | |
| 13 | + * @author 芋道源码 | |
| 14 | + */ | |
| 15 | +public interface InfraStudentService { | |
| 16 | + | |
| 17 | + /** | |
| 18 | + * 创建学生 | |
| 19 | + * | |
| 20 | + * @param createReqVO 创建信息 | |
| 21 | + * @return 编号 | |
| 22 | + */ | |
| 23 | + Long createStudent(@Valid InfraStudentSaveReqVO createReqVO); | |
| 24 | + | |
| 25 | + /** | |
| 26 | + * 导入学生 | |
| 27 | + * | |
| 28 | + * @param importList 导入信息 | |
| 29 | + * @return 导入结果 | |
| 30 | + */ | |
| 31 | + InfraStudentImportRespVO importStudentList(List<InfraStudentImportExcelVO> importList); | |
| 32 | + | |
| 33 | + /** | |
| 34 | + * 更新学生 | |
| 35 | + * | |
| 36 | + * @param updateReqVO 更新信息 | |
| 37 | + */ | |
| 38 | + void updateStudent(@Valid InfraStudentSaveReqVO updateReqVO); | |
| 39 | + | |
| 40 | + /** | |
| 41 | + * 删除学生 | |
| 42 | + * | |
| 43 | + * @param id 编号 | |
| 44 | + */ | |
| 45 | + void deleteStudent(Long id); | |
| 46 | + | |
| 47 | + /** | |
| 48 | + * 批量删除学生 | |
| 49 | + * | |
| 50 | + * @param ids 编号 | |
| 51 | + */ | |
| 52 | + void deleteStudentListByIds(List<Long> ids); | |
| 53 | + | |
| 54 | + /** | |
| 55 | + * 获得学生 | |
| 56 | + * | |
| 57 | + * @param id 编号 | |
| 58 | + * @return 学生 | |
| 59 | + */ | |
| 60 | + InfraStudentDO getStudent(Long id); | |
| 61 | + | |
| 62 | + /** | |
| 63 | + * 获得学生分页 | |
| 64 | + * | |
| 65 | + * @param pageReqVO 分页查询 | |
| 66 | + * @return 学生分页 | |
| 67 | + */ | |
| 68 | + PageResult<InfraStudentDO> getStudentPage(InfraStudentPageReqVO pageReqVO); | |
| 69 | + | |
| 70 | +} | |
| 0 | 71 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vue2_one_importEnable/java/InfraStudentServiceImpl
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.service.demo; | |
| 2 | + | |
| 3 | +import cn.hutool.core.collection.CollUtil; | |
| 4 | +import org.springframework.stereotype.Service; | |
| 5 | +import jakarta.annotation.Resource; | |
| 6 | +import org.springframework.validation.annotation.Validated; | |
| 7 | +import org.springframework.transaction.annotation.Transactional; | |
| 8 | + | |
| 9 | +import java.util.*; | |
| 10 | +import java.util.concurrent.atomic.AtomicInteger; | |
| 11 | +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; | |
| 12 | +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; | |
| 13 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 14 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | |
| 15 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | |
| 16 | + | |
| 17 | +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper; | |
| 18 | + | |
| 19 | +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | |
| 20 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | |
| 21 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.diffList; | |
| 22 | +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; | |
| 23 | + | |
| 24 | +/** | |
| 25 | + * 学生 Service 实现类 | |
| 26 | + * | |
| 27 | + * @author 芋道源码 | |
| 28 | + */ | |
| 29 | +@Service | |
| 30 | +@Validated | |
| 31 | +public class InfraStudentServiceImpl implements InfraStudentService { | |
| 32 | + | |
| 33 | + @Resource | |
| 34 | + private InfraStudentMapper studentMapper; | |
| 35 | + | |
| 36 | + @Override | |
| 37 | + public Long createStudent(InfraStudentSaveReqVO createReqVO) { | |
| 38 | + // 插入 | |
| 39 | + InfraStudentDO student = BeanUtils.toBean(createReqVO, InfraStudentDO.class); | |
| 40 | + studentMapper.insert(student); | |
| 41 | + | |
| 42 | + // 返回 | |
| 43 | + return student.getId(); | |
| 44 | + } | |
| 45 | + | |
| 46 | + @Override | |
| 47 | + @Transactional(rollbackFor = Exception.class) // 添加事务,异常则回滚所有导入 | |
| 48 | + public InfraStudentImportRespVO importStudentList(List<InfraStudentImportExcelVO> importList) { | |
| 49 | + if (CollUtil.isEmpty(importList)) { | |
| 50 | + return InfraStudentImportRespVO.builder() | |
| 51 | + .successCount(0).failureCount(0).failureRows(new LinkedHashMap<>()).build(); | |
| 52 | + } | |
| 53 | + // 遍历,逐个创建 | |
| 54 | + InfraStudentImportRespVO respVO = InfraStudentImportRespVO.builder() | |
| 55 | + .successCount(0).failureCount(0).failureRows(new LinkedHashMap<>()).build(); | |
| 56 | + AtomicInteger index = new AtomicInteger(1); | |
| 57 | + importList.forEach(importItem -> { | |
| 58 | + int currentIndex = index.getAndIncrement(); | |
| 59 | + try { | |
| 60 | + createStudent(BeanUtils.toBean(importItem, InfraStudentSaveReqVO.class)); | |
| 61 | + respVO.setSuccessCount(respVO.getSuccessCount() + 1); | |
| 62 | + } catch (Exception ex) { | |
| 63 | + respVO.getFailureRows().put(currentIndex, ex.getMessage()); | |
| 64 | + } | |
| 65 | + }); | |
| 66 | + respVO.setFailureCount(respVO.getFailureRows().size()); | |
| 67 | + return respVO; | |
| 68 | + } | |
| 69 | + | |
| 70 | + @Override | |
| 71 | + public void updateStudent(InfraStudentSaveReqVO updateReqVO) { | |
| 72 | + // 校验存在 | |
| 73 | + validateStudentExists(updateReqVO.getId()); | |
| 74 | + // 更新 | |
| 75 | + InfraStudentDO updateObj = BeanUtils.toBean(updateReqVO, InfraStudentDO.class); | |
| 76 | + studentMapper.updateById(updateObj); | |
| 77 | + } | |
| 78 | + | |
| 79 | + @Override | |
| 80 | + public void deleteStudent(Long id) { | |
| 81 | + // 校验存在 | |
| 82 | + validateStudentExists(id); | |
| 83 | + // 删除 | |
| 84 | + studentMapper.deleteById(id); | |
| 85 | + } | |
| 86 | + | |
| 87 | + @Override | |
| 88 | + public void deleteStudentListByIds(List<Long> ids) { | |
| 89 | + // 删除 | |
| 90 | + studentMapper.deleteByIds(ids); | |
| 91 | + } | |
| 92 | + | |
| 93 | + | |
| 94 | + private void validateStudentExists(Long id) { | |
| 95 | + if (studentMapper.selectById(id) == null) { | |
| 96 | + throw exception(STUDENT_NOT_EXISTS); | |
| 97 | + } | |
| 98 | + } | |
| 99 | + | |
| 100 | + @Override | |
| 101 | + public InfraStudentDO getStudent(Long id) { | |
| 102 | + return studentMapper.selectById(id); | |
| 103 | + } | |
| 104 | + | |
| 105 | + @Override | |
| 106 | + public PageResult<InfraStudentDO> getStudentPage(InfraStudentPageReqVO pageReqVO) { | |
| 107 | + return studentMapper.selectPage(pageReqVO); | |
| 108 | + } | |
| 109 | + | |
| 110 | +} | |
| 0 | 111 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vue2_one_importEnable/java/InfraStudentServiceImplTest
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.service.demo; | |
| 2 | + | |
| 3 | +import org.junit.jupiter.api.Disabled; | |
| 4 | +import org.junit.jupiter.api.Test; | |
| 5 | + | |
| 6 | +import jakarta.annotation.Resource; | |
| 7 | + | |
| 8 | +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; | |
| 9 | + | |
| 10 | +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; | |
| 11 | +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; | |
| 12 | +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper; | |
| 13 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 14 | + | |
| 15 | +import jakarta.annotation.Resource; | |
| 16 | +import org.springframework.context.annotation.Import; | |
| 17 | +import java.util.*; | |
| 18 | +import java.time.LocalDateTime; | |
| 19 | + | |
| 20 | +import static cn.hutool.core.util.RandomUtil.*; | |
| 21 | +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; | |
| 22 | +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*; | |
| 23 | +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; | |
| 24 | +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*; | |
| 25 | +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*; | |
| 26 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*; | |
| 27 | +import static org.junit.jupiter.api.Assertions.*; | |
| 28 | +import static org.mockito.Mockito.*; | |
| 29 | + | |
| 30 | +/** | |
| 31 | + * {@link InfraStudentServiceImpl} 的单元测试类 | |
| 32 | + * | |
| 33 | + * @author 芋道源码 | |
| 34 | + */ | |
| 35 | +@Import(InfraStudentServiceImpl.class) | |
| 36 | +public class InfraStudentServiceImplTest extends BaseDbUnitTest { | |
| 37 | + | |
| 38 | + @Resource | |
| 39 | + private InfraStudentServiceImpl studentService; | |
| 40 | + | |
| 41 | + @Resource | |
| 42 | + private InfraStudentMapper studentMapper; | |
| 43 | + | |
| 44 | + @Test | |
| 45 | + public void testCreateStudent_success() { | |
| 46 | + // 准备参数 | |
| 47 | + InfraStudentSaveReqVO createReqVO = randomPojo(InfraStudentSaveReqVO.class).setId(null); | |
| 48 | + | |
| 49 | + // 调用 | |
| 50 | + Long studentId = studentService.createStudent(createReqVO); | |
| 51 | + // 断言 | |
| 52 | + assertNotNull(studentId); | |
| 53 | + // 校验记录的属性是否正确 | |
| 54 | + InfraStudentDO student = studentMapper.selectById(studentId); | |
| 55 | + assertPojoEquals(createReqVO, student, "id"); | |
| 56 | + } | |
| 57 | + | |
| 58 | + @Test | |
| 59 | + public void testUpdateStudent_success() { | |
| 60 | + // mock 数据 | |
| 61 | + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class); | |
| 62 | + studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据 | |
| 63 | + // 准备参数 | |
| 64 | + InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class, o -> { | |
| 65 | + o.setId(dbStudent.getId()); // 设置更新的 ID | |
| 66 | + }); | |
| 67 | + | |
| 68 | + // 调用 | |
| 69 | + studentService.updateStudent(updateReqVO); | |
| 70 | + // 校验是否更新正确 | |
| 71 | + InfraStudentDO student = studentMapper.selectById(updateReqVO.getId()); // 获取最新的 | |
| 72 | + assertPojoEquals(updateReqVO, student); | |
| 73 | + } | |
| 74 | + | |
| 75 | + @Test | |
| 76 | + public void testUpdateStudent_notExists() { | |
| 77 | + // 准备参数 | |
| 78 | + InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class); | |
| 79 | + | |
| 80 | + // 调用, 并断言异常 | |
| 81 | + assertServiceException(() -> studentService.updateStudent(updateReqVO), STUDENT_NOT_EXISTS); | |
| 82 | + } | |
| 83 | + | |
| 84 | + @Test | |
| 85 | + public void testDeleteStudent_success() { | |
| 86 | + // mock 数据 | |
| 87 | + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class); | |
| 88 | + studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据 | |
| 89 | + // 准备参数 | |
| 90 | + Long id = dbStudent.getId(); | |
| 91 | + | |
| 92 | + // 调用 | |
| 93 | + studentService.deleteStudent(id); | |
| 94 | + // 校验数据不存在了 | |
| 95 | + assertNull(studentMapper.selectById(id)); | |
| 96 | + } | |
| 97 | + | |
| 98 | + @Test | |
| 99 | + public void testDeleteStudent_notExists() { | |
| 100 | + // 准备参数 | |
| 101 | + Long id = randomLongId(); | |
| 102 | + | |
| 103 | + // 调用, 并断言异常 | |
| 104 | + assertServiceException(() -> studentService.deleteStudent(id), STUDENT_NOT_EXISTS); | |
| 105 | + } | |
| 106 | + | |
| 107 | + @Test | |
| 108 | + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 | |
| 109 | + public void testGetStudentPage() { | |
| 110 | + // mock 数据 | |
| 111 | + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class, o -> { // 等会查询到 | |
| 112 | + o.setName(null); | |
| 113 | + o.setBirthday(null); | |
| 114 | + o.setSex(null); | |
| 115 | + o.setEnabled(null); | |
| 116 | + o.setCreateTime(null); | |
| 117 | + }); | |
| 118 | + studentMapper.insert(dbStudent); | |
| 119 | + // 测试 name 不匹配 | |
| 120 | + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setName(null))); | |
| 121 | + // 测试 birthday 不匹配 | |
| 122 | + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setBirthday(null))); | |
| 123 | + // 测试 sex 不匹配 | |
| 124 | + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setSex(null))); | |
| 125 | + // 测试 enabled 不匹配 | |
| 126 | + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setEnabled(null))); | |
| 127 | + // 测试 createTime 不匹配 | |
| 128 | + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setCreateTime(null))); | |
| 129 | + // 准备参数 | |
| 130 | + InfraStudentPageReqVO reqVO = new InfraStudentPageReqVO(); | |
| 131 | + reqVO.setName(null); | |
| 132 | + reqVO.setBirthday(null); | |
| 133 | + reqVO.setSex(null); | |
| 134 | + reqVO.setEnabled(null); | |
| 135 | + reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); | |
| 136 | + | |
| 137 | + // 调用 | |
| 138 | + PageResult<InfraStudentDO> pageResult = studentService.getStudentPage(reqVO); | |
| 139 | + // 断言 | |
| 140 | + assertEquals(1, pageResult.getTotal()); | |
| 141 | + assertEquals(1, pageResult.getList().size()); | |
| 142 | + assertPojoEquals(dbStudent, pageResult.getList().get(0)); | |
| 143 | + } | |
| 144 | + | |
| 145 | +} | |
| 0 | 146 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vue2_one_importEnable/js/index
0 → 100644
| 1 | +import request from '@/utils/request' | |
| 2 | + | |
| 3 | +// 创建学生 | |
| 4 | +export function createStudent(data) { | |
| 5 | + return request({ | |
| 6 | + url: '/infra/student/create', | |
| 7 | + method: 'post', | |
| 8 | + data: data | |
| 9 | + }) | |
| 10 | +} | |
| 11 | + | |
| 12 | +// 更新学生 | |
| 13 | +export function updateStudent(data) { | |
| 14 | + return request({ | |
| 15 | + url: '/infra/student/update', | |
| 16 | + method: 'put', | |
| 17 | + data: data | |
| 18 | + }) | |
| 19 | +} | |
| 20 | + | |
| 21 | +// 删除学生 | |
| 22 | +export function deleteStudent(id) { | |
| 23 | + return request({ | |
| 24 | + url: '/infra/student/delete?id=' + id, | |
| 25 | + method: 'delete' | |
| 26 | + }) | |
| 27 | +} | |
| 28 | + | |
| 29 | +/** 批量删除学生 */ | |
| 30 | +export function deleteStudentList(ids) { | |
| 31 | + return request({ | |
| 32 | + url: `/infra/student/delete-list?ids=${ids.join(',')}`, | |
| 33 | + method: 'delete' | |
| 34 | + }) | |
| 35 | +} | |
| 36 | + | |
| 37 | +// 获得学生 | |
| 38 | +export function getStudent(id) { | |
| 39 | + return request({ | |
| 40 | + url: '/infra/student/get?id=' + id, | |
| 41 | + method: 'get' | |
| 42 | + }) | |
| 43 | +} | |
| 44 | + | |
| 45 | +// 获得学生分页 | |
| 46 | +export function getStudentPage(params) { | |
| 47 | + return request({ | |
| 48 | + url: '/infra/student/page', | |
| 49 | + method: 'get', | |
| 50 | + params | |
| 51 | + }) | |
| 52 | +} | |
| 53 | +// 导出学生 Excel | |
| 54 | +export function exportStudentExcel(params) { | |
| 55 | + return request({ | |
| 56 | + url: '/infra/student/export-excel', | |
| 57 | + method: 'get', | |
| 58 | + params, | |
| 59 | + responseType: 'blob' | |
| 60 | + }) | |
| 61 | +} | |
| 62 | + | |
| 63 | +// 下载学生导入模板 | |
| 64 | +export function importStudentTemplate() { | |
| 65 | + return request({ | |
| 66 | + url: '/infra/student/get-import-template', | |
| 67 | + method: 'get', | |
| 68 | + responseType: 'blob' | |
| 69 | + }) | |
| 70 | +} | |
| 71 | + | |
| 72 | +// 导入学生 | |
| 73 | +export function importStudent(data) { | |
| 74 | + return request({ | |
| 75 | + url: '/infra/student/import', | |
| 76 | + method: 'post', | |
| 77 | + data | |
| 78 | + }) | |
| 79 | +} | |
| 0 | 80 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vue2_one_importEnable/sql/h2
0 → 100644
| 1 | +-- 将该建表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/create_tables.sql 文件里 | |
| 2 | +CREATE TABLE IF NOT EXISTS "infra_student" ( | |
| 3 | + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, | |
| 4 | + "name" varchar NOT NULL, | |
| 5 | + "description" varchar NOT NULL, | |
| 6 | + "birthday" varchar NOT NULL, | |
| 7 | + "sex" int NOT NULL, | |
| 8 | + "enabled" bit NOT NULL, | |
| 9 | + "avatar" varchar NOT NULL, | |
| 10 | + "video" varchar NOT NULL, | |
| 11 | + "memo" varchar NOT NULL, | |
| 12 | + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| 13 | + PRIMARY KEY ("id") | |
| 14 | +) COMMENT '学生表'; | |
| 15 | + | |
| 16 | +-- 将该删表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/clean.sql 文件里 | |
| 17 | +DELETE FROM "infra_student"; | |
| 0 | 18 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vue2_one_importEnable/sql/sql
0 → 100644
| 1 | +-- 菜单 SQL | |
| 2 | +INSERT INTO system_menu( | |
| 3 | + name, permission, type, sort, parent_id, | |
| 4 | + path, icon, component, status, component_name | |
| 5 | +) | |
| 6 | +VALUES ( | |
| 7 | + '学生管理', '', 2, 0, 888, | |
| 8 | + 'student', '', 'infra/demo/index', 0, 'InfraStudent' | |
| 9 | +); | |
| 10 | + | |
| 11 | +-- 按钮父菜单ID | |
| 12 | +SELECT @parentId := LAST_INSERT_ID(); | |
| 13 | + | |
| 14 | +-- 按钮 SQL | |
| 15 | +INSERT INTO system_menu( | |
| 16 | + name, permission, type, sort, parent_id, | |
| 17 | + path, icon, component, status | |
| 18 | +) | |
| 19 | +VALUES ( | |
| 20 | + '学生查询', 'infra:student:query', 3, 1, @parentId, | |
| 21 | + '', '', '', 0 | |
| 22 | +); | |
| 23 | +INSERT INTO system_menu( | |
| 24 | + name, permission, type, sort, parent_id, | |
| 25 | + path, icon, component, status | |
| 26 | +) | |
| 27 | +VALUES ( | |
| 28 | + '学生创建', 'infra:student:create', 3, 2, @parentId, | |
| 29 | + '', '', '', 0 | |
| 30 | +); | |
| 31 | +INSERT INTO system_menu( | |
| 32 | + name, permission, type, sort, parent_id, | |
| 33 | + path, icon, component, status | |
| 34 | +) | |
| 35 | +VALUES ( | |
| 36 | + '学生更新', 'infra:student:update', 3, 3, @parentId, | |
| 37 | + '', '', '', 0 | |
| 38 | +); | |
| 39 | +INSERT INTO system_menu( | |
| 40 | + name, permission, type, sort, parent_id, | |
| 41 | + path, icon, component, status | |
| 42 | +) | |
| 43 | +VALUES ( | |
| 44 | + '学生删除', 'infra:student:delete', 3, 4, @parentId, | |
| 45 | + '', '', '', 0 | |
| 46 | +); | |
| 47 | +INSERT INTO system_menu( | |
| 48 | + name, permission, type, sort, parent_id, | |
| 49 | + path, icon, component, status | |
| 50 | +) | |
| 51 | +VALUES ( | |
| 52 | + '学生导出', 'infra:student:export', 3, 5, @parentId, | |
| 53 | + '', '', '', 0 | |
| 54 | +); | |
| 55 | +INSERT INTO system_menu( | |
| 56 | + name, permission, type, sort, parent_id, | |
| 57 | + path, icon, component, status | |
| 58 | +) | |
| 59 | +VALUES ( | |
| 60 | + '学生导入', 'infra:student:import', 3, 6, @parentId, | |
| 61 | + '', '', '', 0 | |
| 62 | +); | |
| 0 | 63 | \ No newline at end of file | ... | ... |
yudao-module-infra/src/test/resources/codegen/vue2_one_importEnable/vue/StudentForm
0 → 100644
| 1 | +<template> | |
| 2 | + <div class="app-container"> | |
| 3 | + <!-- 对话框(添加 / 修改) --> | |
| 4 | + <el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="45%" v-dialogDrag append-to-body> | |
| 5 | + <el-form ref="formRef" :model="formData" :rules="formRules" v-loading="formLoading" label-width="100px"> | |
| 6 | + <el-form-item label="名字" prop="name"> | |
| 7 | + <el-input v-model="formData.name" placeholder="请输入名字" /> | |
| 8 | + </el-form-item> | |
| 9 | + <el-form-item label="简介" prop="description"> | |
| 10 | + <el-input v-model="formData.description" type="textarea" placeholder="请输入内容" /> | |
| 11 | + </el-form-item> | |
| 12 | + <el-form-item label="出生日期" prop="birthday"> | |
| 13 | + <el-date-picker clearable v-model="formData.birthday" type="date" value-format="timestamp" placeholder="选择出生日期" /> | |
| 14 | + </el-form-item> | |
| 15 | + <el-form-item label="性别" prop="sex"> | |
| 16 | + <el-select v-model="formData.sex" placeholder="请选择性别"> | |
| 17 | + <el-option v-for="dict in this.getDictDatas(DICT_TYPE.SYSTEM_USER_SEX)" | |
| 18 | + :key="dict.value" :label="dict.label" :value="parseInt(dict.value)" /> | |
| 19 | + </el-select> | |
| 20 | + </el-form-item> | |
| 21 | + <el-form-item label="是否有效" prop="enabled"> | |
| 22 | + <el-radio-group v-model="formData.enabled"> | |
| 23 | + <el-radio v-for="dict in this.getDictDatas(DICT_TYPE.INFRA_BOOLEAN_STRING)" | |
| 24 | + :key="dict.value" :label="dict.value">{{dict.label}}</el-radio> | |
| 25 | + </el-radio-group> | |
| 26 | + </el-form-item> | |
| 27 | + <el-form-item label="头像"> | |
| 28 | + <ImageUpload v-model="formData.avatar"/> | |
| 29 | + </el-form-item> | |
| 30 | + <el-form-item label="附件"> | |
| 31 | + <FileUpload v-model="formData.video"/> | |
| 32 | + </el-form-item> | |
| 33 | + <el-form-item label="备注"> | |
| 34 | + <Editor v-model="formData.memo" :min-height="192"/> | |
| 35 | + </el-form-item> | |
| 36 | + </el-form> | |
| 37 | + <div slot="footer" class="dialog-footer"> | |
| 38 | + <el-button type="primary" @click="submitForm" :disabled="formLoading">确 定</el-button> | |
| 39 | + <el-button @click="dialogVisible = false">取 消</el-button> | |
| 40 | + </div> | |
| 41 | + </el-dialog> | |
| 42 | + </div> | |
| 43 | +</template> | |
| 44 | + | |
| 45 | +<script> | |
| 46 | + import * as StudentApi from '@/api/infra/demo'; | |
| 47 | + import ImageUpload from '@/components/ImageUpload'; | |
| 48 | + import FileUpload from '@/components/FileUpload'; | |
| 49 | + import Editor from '@/components/Editor'; | |
| 50 | + export default { | |
| 51 | + name: "StudentForm", | |
| 52 | + components: { | |
| 53 | + ImageUpload, | |
| 54 | + FileUpload, | |
| 55 | + Editor, | |
| 56 | + }, | |
| 57 | + data() { | |
| 58 | + return { | |
| 59 | + // 弹出层标题 | |
| 60 | + dialogTitle: "", | |
| 61 | + // 是否显示弹出层 | |
| 62 | + dialogVisible: false, | |
| 63 | + // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 | |
| 64 | + formLoading: false, | |
| 65 | + // 表单参数 | |
| 66 | + formData: { | |
| 67 | + id: undefined, | |
| 68 | + name: undefined, | |
| 69 | + description: undefined, | |
| 70 | + birthday: undefined, | |
| 71 | + sex: undefined, | |
| 72 | + enabled: undefined, | |
| 73 | + avatar: undefined, | |
| 74 | + video: undefined, | |
| 75 | + memo: undefined, | |
| 76 | + }, | |
| 77 | + // 表单校验 | |
| 78 | + formRules: { | |
| 79 | + name: [{ required: true, message: '名字不能为空', trigger: 'blur' }], | |
| 80 | + description: [{ required: true, message: '简介不能为空', trigger: 'blur' }], | |
| 81 | + birthday: [{ required: true, message: '出生日期不能为空', trigger: 'blur' }], | |
| 82 | + sex: [{ required: true, message: '性别不能为空', trigger: 'change' }], | |
| 83 | + enabled: [{ required: true, message: '是否有效不能为空', trigger: 'blur' }], | |
| 84 | + avatar: [{ required: true, message: '头像不能为空', trigger: 'blur' }], | |
| 85 | + video: [{ required: true, message: '附件不能为空', trigger: 'blur' }], | |
| 86 | + memo: [{ required: true, message: '备注不能为空', trigger: 'blur' }], | |
| 87 | + }, | |
| 88 | + }; | |
| 89 | + }, | |
| 90 | + methods: { | |
| 91 | + /** 打开弹窗 */ | |
| 92 | + async open(id) { | |
| 93 | + this.dialogVisible = true; | |
| 94 | + this.reset(); | |
| 95 | + // 修改时,设置数据 | |
| 96 | + if (id) { | |
| 97 | + this.formLoading = true; | |
| 98 | + try { | |
| 99 | + const res = await StudentApi.getStudent(id); | |
| 100 | + this.formData = res.data; | |
| 101 | + this.title = "修改学生"; | |
| 102 | + } finally { | |
| 103 | + this.formLoading = false; | |
| 104 | + } | |
| 105 | + } | |
| 106 | + this.title = "新增学生"; | |
| 107 | + }, | |
| 108 | + /** 提交按钮 */ | |
| 109 | + async submitForm() { | |
| 110 | + // 校验主表 | |
| 111 | + await this.$refs["formRef"].validate(); | |
| 112 | + this.formLoading = true; | |
| 113 | + try { | |
| 114 | + const data = this.formData; | |
| 115 | + // 修改的提交 | |
| 116 | + if (data.id) { | |
| 117 | + await StudentApi.updateStudent(data); | |
| 118 | + this.$modal.msgSuccess("修改成功"); | |
| 119 | + this.dialogVisible = false; | |
| 120 | + this.$emit('success'); | |
| 121 | + return; | |
| 122 | + } | |
| 123 | + // 添加的提交 | |
| 124 | + await StudentApi.createStudent(data); | |
| 125 | + this.$modal.msgSuccess("新增成功"); | |
| 126 | + this.dialogVisible = false; | |
| 127 | + this.$emit('success'); | |
| 128 | + } finally { | |
| 129 | + this.formLoading = false; | |
| 130 | + } | |
| 131 | + }, | |
| 132 | + /** 表单重置 */ | |
| 133 | + reset() { | |
| 134 | + this.formData = { | |
| 135 | + id: undefined, | |
| 136 | + name: undefined, | |
| 137 | + description: undefined, | |
| 138 | + birthday: undefined, | |
| 139 | + sex: undefined, | |
| 140 | + enabled: undefined, | |
| 141 | + avatar: undefined, | |
| 142 | + video: undefined, | |
| 143 | + memo: undefined, | |
| 144 | + }; | |
| 145 | + this.resetForm("formRef"); | |
| 146 | + } | |
| 147 | + } | |
| 148 | + }; | |
| 149 | +</script> | ... | ... |
yudao-module-infra/src/test/resources/codegen/vue2_one_importEnable/vue/index
0 → 100644
| 1 | +<template> | |
| 2 | + <div class="app-container"> | |
| 3 | + <!-- 搜索工作栏 --> | |
| 4 | + <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px"> | |
| 5 | + <el-form-item label="名字" prop="name"> | |
| 6 | + <el-input v-model="queryParams.name" placeholder="请输入名字" clearable @keyup.enter.native="handleQuery"/> | |
| 7 | + </el-form-item> | |
| 8 | + <el-form-item label="出生日期" prop="birthday"> | |
| 9 | + <el-date-picker clearable v-model="queryParams.birthday" type="date" value-format="yyyy-MM-dd" placeholder="选择出生日期" /> | |
| 10 | + </el-form-item> | |
| 11 | + <el-form-item label="性别" prop="sex"> | |
| 12 | + <el-select v-model="queryParams.sex" placeholder="请选择性别" clearable size="small"> | |
| 13 | + <el-option v-for="dict in this.getDictDatas(DICT_TYPE.SYSTEM_USER_SEX)" | |
| 14 | + :key="dict.value" :label="dict.label" :value="dict.value"/> | |
| 15 | + </el-select> | |
| 16 | + </el-form-item> | |
| 17 | + <el-form-item label="是否有效" prop="enabled"> | |
| 18 | + <el-select v-model="queryParams.enabled" placeholder="请选择是否有效" clearable size="small"> | |
| 19 | + <el-option v-for="dict in this.getDictDatas(DICT_TYPE.INFRA_BOOLEAN_STRING)" | |
| 20 | + :key="dict.value" :label="dict.label" :value="dict.value"/> | |
| 21 | + </el-select> | |
| 22 | + </el-form-item> | |
| 23 | + <el-form-item label="创建时间" prop="createTime"> | |
| 24 | + <el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange" | |
| 25 | + range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" /> | |
| 26 | + </el-form-item> | |
| 27 | + <el-form-item> | |
| 28 | + <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button> | |
| 29 | + <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button> | |
| 30 | + </el-form-item> | |
| 31 | + </el-form> | |
| 32 | + | |
| 33 | + <!-- 操作工具栏 --> | |
| 34 | + <el-row :gutter="10" class="mb8"> | |
| 35 | + <el-col :span="1.5"> | |
| 36 | + <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="openForm(undefined)" | |
| 37 | + v-hasPermi="['infra:student:create']">新增</el-button> | |
| 38 | + </el-col> | |
| 39 | + <el-col :span="1.5"> | |
| 40 | + <el-button type="info" plain icon="el-icon-upload2" size="mini" @click="handleImport" | |
| 41 | + :loading="importLoading" v-hasPermi="['infra:student:import']">导入</el-button> | |
| 42 | + </el-col> | |
| 43 | + <el-col :span="1.5"> | |
| 44 | + <el-button type="info" plain icon="el-icon-document" size="mini" @click="handleImportTemplate" | |
| 45 | + v-hasPermi="['infra:student:import']">导入模板</el-button> | |
| 46 | + </el-col> | |
| 47 | + <el-col :span="1.5"> | |
| 48 | + <el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport" :loading="exportLoading" | |
| 49 | + v-hasPermi="['infra:student:export']">导出</el-button> | |
| 50 | + </el-col> | |
| 51 | + <el-col :span="1.5"> | |
| 52 | + <el-button | |
| 53 | + type="danger" | |
| 54 | + plain | |
| 55 | + icon="el-icon-delete" | |
| 56 | + size="mini" | |
| 57 | + :disabled="isEmpty(checkedIds)" | |
| 58 | + @click="handleDeleteBatch" | |
| 59 | + v-hasPermi="['infra:student:delete']" | |
| 60 | + > | |
| 61 | + 批量删除 | |
| 62 | + </el-button> | |
| 63 | + </el-col> | |
| 64 | + <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> | |
| 65 | + </el-row> | |
| 66 | + <input ref="importFileRef" type="file" style="display: none" accept=".xls,.xlsx" @change="handleImportFileChange" /> | |
| 67 | + | |
| 68 | + <el-table | |
| 69 | + v-loading="loading" | |
| 70 | + :data="list" | |
| 71 | + :stripe="true" | |
| 72 | + :show-overflow-tooltip="true" | |
| 73 | + @selection-change="handleRowCheckboxChange" | |
| 74 | + > | |
| 75 | + <el-table-column type="selection" width="55" /> | |
| 76 | + <el-table-column label="编号" align="center" prop="id"> | |
| 77 | + <template v-slot="scope"> | |
| 78 | + <dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="scope.row.id" /> | |
| 79 | + </template> | |
| 80 | + </el-table-column> | |
| 81 | + <el-table-column label="名字" align="center" prop="name"> | |
| 82 | + <template v-slot="scope"> | |
| 83 | + <dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="scope.row.name" /> | |
| 84 | + </template> | |
| 85 | + </el-table-column> | |
| 86 | + <el-table-column label="简介" align="center" prop="description"> | |
| 87 | + <template v-slot="scope"> | |
| 88 | + <dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="scope.row.description" /> | |
| 89 | + </template> | |
| 90 | + </el-table-column> | |
| 91 | + <el-table-column label="出生日期" align="center" prop="birthday" width="180"> | |
| 92 | + <template v-slot="scope"> | |
| 93 | + <span>{{ parseTime(scope.row.birthday) }}</span> | |
| 94 | + </template> | |
| 95 | + </el-table-column> | |
| 96 | + <el-table-column label="性别" align="center" prop="sex"> | |
| 97 | + <template v-slot="scope"> | |
| 98 | + <dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="scope.row.sex" /> | |
| 99 | + </template> | |
| 100 | + </el-table-column> | |
| 101 | + <el-table-column label="是否有效" align="center" prop="enabled"> | |
| 102 | + <template v-slot="scope"> | |
| 103 | + <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.enabled" /> | |
| 104 | + </template> | |
| 105 | + </el-table-column> | |
| 106 | + <el-table-column label="头像" align="center" prop="avatar"> | |
| 107 | + <template v-slot="scope"> | |
| 108 | + <dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="scope.row.avatar" /> | |
| 109 | + </template> | |
| 110 | + </el-table-column> | |
| 111 | + <el-table-column label="附件" align="center" prop="video"> | |
| 112 | + <template v-slot="scope"> | |
| 113 | + <dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="scope.row.video" /> | |
| 114 | + </template> | |
| 115 | + </el-table-column> | |
| 116 | + <el-table-column label="备注" align="center" prop="memo"> | |
| 117 | + <template v-slot="scope"> | |
| 118 | + <dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="scope.row.memo" /> | |
| 119 | + </template> | |
| 120 | + </el-table-column> | |
| 121 | + <el-table-column label="创建时间" align="center" prop="createTime" width="180"> | |
| 122 | + <template v-slot="scope"> | |
| 123 | + <span>{{ parseTime(scope.row.createTime) }}</span> | |
| 124 | + </template> | |
| 125 | + </el-table-column> | |
| 126 | + <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> | |
| 127 | + <template v-slot="scope"> | |
| 128 | + <el-button size="mini" type="text" icon="el-icon-edit" @click="openForm(scope.row.id)" | |
| 129 | + v-hasPermi="['infra:student:update']">修改</el-button> | |
| 130 | + <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" | |
| 131 | + v-hasPermi="['infra:student:delete']">删除</el-button> | |
| 132 | + </template> | |
| 133 | + </el-table-column> | |
| 134 | + </el-table> | |
| 135 | + <!-- 分页组件 --> | |
| 136 | + <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" | |
| 137 | + @pagination="getList"/> | |
| 138 | + <!-- 对话框(添加 / 修改) --> | |
| 139 | + <StudentForm ref="formRef" @success="getList" /> | |
| 140 | + </div> | |
| 141 | +</template> | |
| 142 | + | |
| 143 | +<script> | |
| 144 | +import * as StudentApi from '@/api/infra/demo'; | |
| 145 | +import StudentForm from './StudentForm.vue'; | |
| 146 | +export default { | |
| 147 | + name: "Student", | |
| 148 | + components: { | |
| 149 | + StudentForm | |
| 150 | + }, | |
| 151 | + data() { | |
| 152 | + return { | |
| 153 | + // 遮罩层 | |
| 154 | + loading: true, | |
| 155 | + // 导出遮罩层 | |
| 156 | + exportLoading: false, | |
| 157 | + // 导入遮罩层 | |
| 158 | + importLoading: false, | |
| 159 | + // 显示搜索条件 | |
| 160 | + showSearch: true, | |
| 161 | + // 总条数 | |
| 162 | + total: 0, | |
| 163 | + // 学生列表 | |
| 164 | + list: [], | |
| 165 | + // 是否展开,默认全部展开 | |
| 166 | + isExpandAll: true, | |
| 167 | + // 重新渲染表格状态 | |
| 168 | + refreshTable: true, | |
| 169 | + // 选中行 | |
| 170 | + currentRow: {}, | |
| 171 | + checkedIds: [], | |
| 172 | + // 查询参数 | |
| 173 | + queryParams: { | |
| 174 | + pageNo: 1, | |
| 175 | + pageSize: 10, | |
| 176 | + name: null, | |
| 177 | + birthday: null, | |
| 178 | + sex: null, | |
| 179 | + enabled: null, | |
| 180 | + createTime: [], | |
| 181 | + }, | |
| 182 | + }; | |
| 183 | + }, | |
| 184 | + created() { | |
| 185 | + this.getList(); | |
| 186 | + }, | |
| 187 | + methods: { | |
| 188 | + /** 查询列表 */ | |
| 189 | + async getList() { | |
| 190 | + try { | |
| 191 | + this.loading = true; | |
| 192 | + const res = await StudentApi.getStudentPage(this.queryParams); | |
| 193 | + this.list = res.data.list; | |
| 194 | + this.total = res.data.total; | |
| 195 | + } finally { | |
| 196 | + this.loading = false; | |
| 197 | + } | |
| 198 | + }, | |
| 199 | + /** 搜索按钮操作 */ | |
| 200 | + handleQuery() { | |
| 201 | + this.queryParams.pageNo = 1; | |
| 202 | + this.getList(); | |
| 203 | + }, | |
| 204 | + /** 重置按钮操作 */ | |
| 205 | + resetQuery() { | |
| 206 | + this.resetForm("queryForm"); | |
| 207 | + this.handleQuery(); | |
| 208 | + }, | |
| 209 | + /** 添加/修改操作 */ | |
| 210 | + openForm(id) { | |
| 211 | + this.$refs["formRef"].open(id); | |
| 212 | + }, | |
| 213 | + /** 导入按钮操作 */ | |
| 214 | + handleImport() { | |
| 215 | + this.$refs.importFileRef && this.$refs.importFileRef.click(); | |
| 216 | + }, | |
| 217 | + /** 导入模板下载 */ | |
| 218 | + async handleImportTemplate() { | |
| 219 | + const data = await StudentApi.importStudentTemplate(); | |
| 220 | + this.$download.excel(data, '学生导入模板.xls'); | |
| 221 | + }, | |
| 222 | + /** 导入文件变更 */ | |
| 223 | + async handleImportFileChange(event) { | |
| 224 | + const target = event.target; | |
| 225 | + const file = target.files && target.files[0]; | |
| 226 | + if (!file) { | |
| 227 | + return; | |
| 228 | + } | |
| 229 | + this.importLoading = true; | |
| 230 | + try { | |
| 231 | + const formData = new FormData(); | |
| 232 | + formData.append('file', file); | |
| 233 | + const res = await StudentApi.importStudent(formData); | |
| 234 | + const data = res.data || res; | |
| 235 | + let text = '导入成功数量:' + (data.successCount || 0) + ';导入失败数量:' + (data.failureCount || 0) + ';'; | |
| 236 | + if (data.failureRows) { | |
| 237 | + Object.keys(data.failureRows).forEach((rowNo) => { | |
| 238 | + text += '< 第' + rowNo + '行: ' + data.failureRows[rowNo] + ' >'; | |
| 239 | + }); | |
| 240 | + } | |
| 241 | + await this.$alert(text, '学生导入结果', { dangerouslyUseHTMLString: true }); | |
| 242 | + await this.getList(); | |
| 243 | + } catch { | |
| 244 | + } finally { | |
| 245 | + target.value = ''; | |
| 246 | + this.importLoading = false; | |
| 247 | + } | |
| 248 | + }, | |
| 249 | + /** 删除按钮操作 */ | |
| 250 | + async handleDelete(row) { | |
| 251 | + const id = row.id; | |
| 252 | + await this.$modal.confirm('是否确认删除学生编号为"' + id + '"的数据项?') | |
| 253 | + try { | |
| 254 | + await StudentApi.deleteStudent(id); | |
| 255 | + await this.getList(); | |
| 256 | + this.$modal.msgSuccess("删除成功"); | |
| 257 | + } catch {} | |
| 258 | + }, | |
| 259 | + /** 批量删除学生 */ | |
| 260 | + async handleDeleteBatch() { | |
| 261 | + await this.$modal.confirm('是否确认删除?') | |
| 262 | + try { | |
| 263 | + await StudentApi.deleteStudentList(this.checkedIds); | |
| 264 | + this.checkedIds = []; | |
| 265 | + await this.getList(); | |
| 266 | + this.$modal.msgSuccess("删除成功"); | |
| 267 | + } catch {} | |
| 268 | + }, | |
| 269 | + handleRowCheckboxChange(records) { | |
| 270 | + this.checkedIds = records.map((item) => item.id); | |
| 271 | + }, | |
| 272 | + /** 导出按钮操作 */ | |
| 273 | + async handleExport() { | |
| 274 | + await this.$modal.confirm('是否确认导出所有学生数据项?'); | |
| 275 | + try { | |
| 276 | + this.exportLoading = true; | |
| 277 | + const data = await StudentApi.exportStudentExcel(this.queryParams); | |
| 278 | + this.$download.excel(data, '学生.xls'); | |
| 279 | + } catch { | |
| 280 | + } finally { | |
| 281 | + this.exportLoading = false; | |
| 282 | + } | |
| 283 | + }, | |
| 284 | + } | |
| 285 | +}; | |
| 286 | +</script> | ... | ... |