Ver Fonte

基础信息管理

haogh há 1 ano atrás
pai
commit
1b43677c2e
22 ficheiros alterados com 597 adições e 51 exclusões
  1. 18 0
      src/main/java/com/qmth/exam/reserve/bean/examsite/ExamSiteGuideReq.java
  2. 1 6
      src/main/java/com/qmth/exam/reserve/bean/examsite/ExamSiteSaveReq.java
  3. 24 0
      src/main/java/com/qmth/exam/reserve/bean/room/ExamRoomReq.java
  4. 29 0
      src/main/java/com/qmth/exam/reserve/bean/room/ExamRoomSaveReq.java
  5. 35 0
      src/main/java/com/qmth/exam/reserve/bean/room/ExamRoomVO.java
  6. 4 4
      src/main/java/com/qmth/exam/reserve/bean/teaching/TeachingReq.java
  7. 80 3
      src/main/java/com/qmth/exam/reserve/controller/admin/ExamRoomController.java
  8. 9 5
      src/main/java/com/qmth/exam/reserve/controller/admin/ExamSiteManageController.java
  9. 9 0
      src/main/java/com/qmth/exam/reserve/controller/admin/TeachingController.java
  10. 2 0
      src/main/java/com/qmth/exam/reserve/dao/CategoryDao.java
  11. 7 0
      src/main/java/com/qmth/exam/reserve/dao/ExamRoomDao.java
  12. 2 0
      src/main/java/com/qmth/exam/reserve/dao/ExamSiteDao.java
  13. 2 0
      src/main/java/com/qmth/exam/reserve/service/CategoryService.java
  14. 16 0
      src/main/java/com/qmth/exam/reserve/service/ExamRoomService.java
  15. 5 4
      src/main/java/com/qmth/exam/reserve/service/ExamSiteService.java
  16. 13 2
      src/main/java/com/qmth/exam/reserve/service/impl/CategoryServiceImpl.java
  17. 247 0
      src/main/java/com/qmth/exam/reserve/service/impl/ExamRoomServiceImpl.java
  18. 50 26
      src/main/java/com/qmth/exam/reserve/service/impl/ExamSiteServiceImpl.java
  19. 6 0
      src/main/resources/mapper/CategoryMapper.xml
  20. 31 1
      src/main/resources/mapper/ExamRoomMapper.xml
  21. 7 0
      src/main/resources/mapper/ExamSiteMapper.xml
  22. BIN
      src/main/resources/templates/examRoom.xlsx

+ 18 - 0
src/main/java/com/qmth/exam/reserve/bean/examsite/ExamSiteGuideReq.java

@@ -0,0 +1,18 @@
+package com.qmth.exam.reserve.bean.examsite;
+
+import com.qmth.exam.reserve.bean.IModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class ExamSiteGuideReq implements IModel {
+
+    @ApiModelProperty(value = "考点ID", required = true)
+    private Long id;
+
+    @ApiModelProperty(value = "考点指引", required = true)
+    private String guide;
+
+}

+ 1 - 6
src/main/java/com/qmth/exam/reserve/bean/examsite/ExamSiteSaveReq.java

@@ -9,7 +9,7 @@ import lombok.Setter;
 @Setter
 public class ExamSiteSaveReq implements IModel {
 
-    @ApiModelProperty(value = "考点ID",required = false)
+    @ApiModelProperty(value = "考点ID")
     private Long id;
 
     @ApiModelProperty(value = "考点代码",required = true)
@@ -24,9 +24,4 @@ public class ExamSiteSaveReq implements IModel {
     @ApiModelProperty(value = "考点所属教学点ID",required = true)
     private Long categoryId;
 
-    @ApiModelProperty(value = "考点容量",required = false)
-    private Integer capacity;
-
-    @ApiModelProperty(value = "考点状态",required = true)
-    private Boolean enable;
 }

+ 24 - 0
src/main/java/com/qmth/exam/reserve/bean/room/ExamRoomReq.java

@@ -0,0 +1,24 @@
+package com.qmth.exam.reserve.bean.room;
+
+import com.qmth.exam.reserve.bean.IModel;
+import com.qmth.exam.reserve.bean.PagerReq;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class ExamRoomReq extends PagerReq {
+
+    @ApiModelProperty("教学点ID")
+    private Long teachingId;
+
+    @ApiModelProperty("考点ID")
+    private Long examSiteId;
+
+    @ApiModelProperty("考场名称")
+    private String name;
+
+    @ApiModelProperty("考场状态")
+    private Boolean enable;
+}

+ 29 - 0
src/main/java/com/qmth/exam/reserve/bean/room/ExamRoomSaveReq.java

@@ -0,0 +1,29 @@
+package com.qmth.exam.reserve.bean.room;
+
+import com.qmth.exam.reserve.bean.IModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class ExamRoomSaveReq implements IModel {
+
+    @ApiModelProperty(value = "考场ID")
+    private Long id;
+
+    @ApiModelProperty(value = "考场代码", required = true)
+    private String code;
+
+    @ApiModelProperty(value = "考场名称", required = true)
+    private String name;
+
+    @ApiModelProperty(value = "考场地址", required = true)
+    private String address;
+
+    @ApiModelProperty(value = "考场容量", required = true)
+    private Integer capacity;
+
+    @ApiModelProperty(value = "所属考点", required = true)
+    private Long examSiteId;
+}

+ 35 - 0
src/main/java/com/qmth/exam/reserve/bean/room/ExamRoomVO.java

@@ -0,0 +1,35 @@
+package com.qmth.exam.reserve.bean.room;
+
+import com.qmth.exam.reserve.bean.IModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class ExamRoomVO implements IModel {
+
+    @ApiModelProperty("考场ID")
+    private Long id;
+
+    @ApiModelProperty("考场代码")
+    private String code;
+
+    @ApiModelProperty("考场名称")
+    private String name;
+
+    @ApiModelProperty("考场地址")
+    private String address;
+
+    @ApiModelProperty("考场(机房)容量")
+    private Integer capacity;
+
+    @ApiModelProperty("所属考点")
+    private String examSiteName;
+
+    @ApiModelProperty("所属教学点")
+    private String teachingName;
+
+    @ApiModelProperty("考场状态")
+    private Boolean enable;
+}

+ 4 - 4
src/main/java/com/qmth/exam/reserve/bean/teaching/TeachingReq.java

@@ -13,15 +13,15 @@ public class TeachingReq extends PagerReq implements IModel {
 
     private static final long serialVersionUID = 2203050783813389251L;
 
-    @ApiModelProperty(value = "教学点名称", required = false)
+    @ApiModelProperty(value = "教学点名称")
     private String name;
 
-    @ApiModelProperty(value = "教学点代码", required = false)
+    @ApiModelProperty(value = "教学点代码")
     private String code;
 
-    @ApiModelProperty(value = "状态(true|false)",required = false)
+    @ApiModelProperty(value = "状态(true|false)")
     private Boolean enable;
 
-    @ApiModelProperty(value = "教学点所在层级(默认为2)",required = false)
+    @ApiModelProperty(value = "教学点所在层级(默认为2)")
     private Integer level;
 }

+ 80 - 3
src/main/java/com/qmth/exam/reserve/controller/admin/ExamRoomController.java

@@ -1,15 +1,92 @@
 package com.qmth.exam.reserve.controller.admin;
 
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.qmth.boot.api.annotation.Aac;
 import com.qmth.boot.api.constant.ApiConstant;
+import com.qmth.boot.core.collection.PageResult;
+import com.qmth.boot.core.exception.StatusException;
+import com.qmth.exam.reserve.bean.examsite.ExamSiteReq;
+import com.qmth.exam.reserve.bean.examsite.ExamSiteSaveReq;
+import com.qmth.exam.reserve.bean.examsite.ExamSiteVO;
+import com.qmth.exam.reserve.bean.login.LoginUser;
+import com.qmth.exam.reserve.bean.room.ExamRoomReq;
+import com.qmth.exam.reserve.bean.room.ExamRoomSaveReq;
+import com.qmth.exam.reserve.bean.room.ExamRoomVO;
 import com.qmth.exam.reserve.controller.BaseController;
+import com.qmth.exam.reserve.entity.ExamRoomEntity;
+import com.qmth.exam.reserve.enums.Role;
+import com.qmth.exam.reserve.service.ExamRoomService;
+import com.qmth.exam.reserve.util.ResourceUtil;
 import io.swagger.annotations.Api;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 @RestController
-@Api(tags = "【管理端端】考场管理相关接口")
+@Api(tags = "【管理端】考场管理相关接口")
 @RequestMapping(ApiConstant.DEFAULT_URI_PREFIX + "/admin/room")
 @Aac(strict = false, auth = true)
 public class ExamRoomController extends BaseController {
+
+    @Autowired
+    private ExamRoomService examRoomService;
+
+    @ApiOperation(value = "考场管理分页")
+    @PostMapping(value = "/page")
+    public PageResult<ExamRoomVO> page(@RequestBody ExamRoomReq req) {
+        LoginUser user = curLoginUser();
+        if (user.getRole().equals(Role.TEACHING)) {
+            req.setTeachingId(user.getCategoryId());
+        }
+        return examRoomService.pageExamRoom(req);
+    }
+
+    @ApiOperation(value = "考场单个查询")
+    @PostMapping(value = "/find")
+    public ExamRoomEntity find(@RequestParam Long id) {
+        return examRoomService.getById(id);
+    }
+
+    @ApiOperation(value = "考场新增/编辑")
+    @PostMapping(value = "/save")
+    public void save(@RequestBody ExamRoomSaveReq req) {
+        LoginUser user = curLoginUser();
+        examRoomService.saveExamRoom(user, req);
+    }
+
+    @ApiOperation(value = "考场启用/禁用")
+    @PostMapping(value = "/enable")
+    public void enable(@ApiParam("考场ID") @RequestParam Long id, @ApiParam("启用/禁用") @RequestParam Boolean enable) {
+        examRoomService.enable(id, enable);
+    }
+
+    @ApiOperation(value = "考场模版下载")
+    @PostMapping(value = "/import/template")
+    public void download() {
+        exportFile("考场模板.xlsx", ResourceUtil.getStream("templates/examRoom.xlsx"));
+    }
+
+    @ApiOperation(value = "考场导入")
+    @PostMapping(value = "/import")
+    public Map<String, Object> importExamRoom(@RequestParam MultipartFile file) {
+        LoginUser user = this.curLoginUser();
+        List<Map<String, Object>> failRecords;
+        try {
+            failRecords = examRoomService.importExamRoom(user, file.getInputStream());
+        } catch (IOException e) {
+            throw new StatusException("文件读取出错", e);
+        }
+        Map<String, Object> map = new HashMap<>();
+        map.put("hasError", CollectionUtils.isNotEmpty(failRecords));
+        map.put("failRecords", failRecords);
+        return map;
+    }
+
 }

+ 9 - 5
src/main/java/com/qmth/exam/reserve/controller/admin/ExamSiteManageController.java

@@ -5,6 +5,7 @@ import com.qmth.boot.api.annotation.Aac;
 import com.qmth.boot.api.constant.ApiConstant;
 import com.qmth.boot.core.collection.PageResult;
 import com.qmth.boot.core.exception.StatusException;
+import com.qmth.exam.reserve.bean.examsite.ExamSiteGuideReq;
 import com.qmth.exam.reserve.bean.examsite.ExamSiteReq;
 import com.qmth.exam.reserve.bean.examsite.ExamSiteSaveReq;
 import com.qmth.exam.reserve.bean.examsite.ExamSiteVO;
@@ -39,7 +40,7 @@ public class ExamSiteManageController extends BaseController {
     @PostMapping(value = "/page")
     public PageResult<ExamSiteVO> page(@RequestBody ExamSiteReq req) {
         LoginUser user = curLoginUser();
-        if(user.getRole().equals(Role.TEACHING)) {
+        if (user.getRole().equals(Role.TEACHING)) {
             req.setTeachingId(user.getCategoryId());
         }
         return examSiteService.page(req);
@@ -47,7 +48,6 @@ public class ExamSiteManageController extends BaseController {
 
     @ApiOperation(value = "考点管理查询")
     @PostMapping(value = "/find")
-    @Aac(strict = false, auth = false)
     public ExamSiteEntity find(@ApiParam("考点ID") @RequestParam Long id) {
         return examSiteService.getById(id);
     }
@@ -65,14 +65,18 @@ public class ExamSiteManageController extends BaseController {
         examSiteService.enable(id, enable);
     }
 
-    @ApiOperation(value = "考点指引")
+    @ApiOperation(value = "查询考点指引")
     @PostMapping(value = "/guide")
-    @Aac(strict = false, auth = false)
     public String guide(@ApiParam("考点ID") @RequestParam Long id) {
         ExamSiteEntity examSite = examSiteService.getById(id);
         return examSite.getGuide();
     }
 
+    @ApiOperation(value = "保存考点指引")
+    @PostMapping(value = "/guide/save")
+    public void saveGuide(@ApiParam("考点指引") @RequestBody ExamSiteGuideReq req) {
+        examSiteService.saveGuide(req);
+    }
 
     @ApiOperation(value = "考点模版下载")
     @PostMapping(value = "/import/template")
@@ -89,7 +93,7 @@ public class ExamSiteManageController extends BaseController {
         }
         List<Map<String, Object>> failRecords;
         try {
-            failRecords = examSiteService.importExamSite(user,file.getInputStream());
+            failRecords = examSiteService.importExamSite(user, file.getInputStream());
         } catch (IOException e) {
             throw new StatusException("文件读取出错", e);
         }

+ 9 - 0
src/main/java/com/qmth/exam/reserve/controller/admin/TeachingController.java

@@ -5,6 +5,8 @@ import com.qmth.boot.core.exception.StatusException;
 import com.qmth.exam.reserve.bean.login.LoginUser;
 import com.qmth.exam.reserve.bean.stdapply.CategoryVO;
 import com.qmth.exam.reserve.bean.teaching.TeachingSaveReq;
+import com.qmth.exam.reserve.entity.CategoryEntity;
+import com.qmth.exam.reserve.entity.ExamSiteEntity;
 import com.qmth.exam.reserve.enums.Role;
 import com.qmth.exam.reserve.util.ResourceUtil;
 import io.swagger.annotations.ApiModelProperty;
@@ -53,6 +55,13 @@ public class TeachingController extends BaseController {
         return categoryService.listCity(user);
     }
 
+    @ApiOperation(value = "教学点查询")
+    @PostMapping(value = "/find")
+    public CategoryEntity find(@ApiParam("教学点ID") @RequestParam Long id) {
+        return categoryService.getById(id);
+    }
+
+
     @ApiOperation(value = "教学点新增/编辑")
     @PostMapping(value = "/save")
     public void save(@RequestBody TeachingSaveReq req) {

+ 2 - 0
src/main/java/com/qmth/exam/reserve/dao/CategoryDao.java

@@ -12,4 +12,6 @@ import org.springframework.web.bind.annotation.RequestParam;
 public interface CategoryDao extends BaseMapper<CategoryEntity> {
 
     IPage<TeachingVO> page(Page<TeachingVO> page, @Param("req") TeachingReq req);
+
+    void updateTeachingCapacity(@Param("teachingId") Long teachingId);
 }

+ 7 - 0
src/main/java/com/qmth/exam/reserve/dao/ExamRoomDao.java

@@ -1,8 +1,15 @@
 package com.qmth.exam.reserve.dao;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.qmth.boot.core.collection.PageResult;
+import com.qmth.exam.reserve.bean.examsite.ExamSiteVO;
+import com.qmth.exam.reserve.bean.room.ExamRoomReq;
+import com.qmth.exam.reserve.bean.room.ExamRoomVO;
 import com.qmth.exam.reserve.entity.ExamRoomEntity;
 
 public interface ExamRoomDao extends BaseMapper<ExamRoomEntity> {
 
+    IPage<ExamRoomVO> pageExamRoom(Page<ExamRoomVO> page, ExamRoomReq req);
 }

+ 2 - 0
src/main/java/com/qmth/exam/reserve/dao/ExamSiteDao.java

@@ -16,4 +16,6 @@ public interface ExamSiteDao extends BaseMapper<ExamSiteEntity> {
     ExamSiteCacheBean findInfoById(@Param("examSiteId") Long examSiteId);
 
     IPage<ExamSiteVO> page(Page<ExamSiteVO> page, @Param("req") ExamSiteReq req);
+
+    void updateExamSiteCapacity(@Param("examSiteId") Long examSiteId);
 }

+ 2 - 0
src/main/java/com/qmth/exam/reserve/service/CategoryService.java

@@ -29,4 +29,6 @@ public interface CategoryService extends IService<CategoryEntity> {
     List<CategoryVO> listCity(LoginUser user);
 
     List<Map<String, Object>> importTeaching(LoginUser user, InputStream inputStream);
+
+    void updateTeachingCapacity(Long teachingId);
 }

+ 16 - 0
src/main/java/com/qmth/exam/reserve/service/ExamRoomService.java

@@ -1,8 +1,24 @@
 package com.qmth.exam.reserve.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.qmth.boot.core.collection.PageResult;
+import com.qmth.exam.reserve.bean.login.LoginUser;
+import com.qmth.exam.reserve.bean.room.ExamRoomReq;
+import com.qmth.exam.reserve.bean.room.ExamRoomSaveReq;
+import com.qmth.exam.reserve.bean.room.ExamRoomVO;
 import com.qmth.exam.reserve.entity.ExamRoomEntity;
 
+import java.io.InputStream;
+import java.util.List;
+import java.util.Map;
+
 public interface ExamRoomService extends IService<ExamRoomEntity> {
 
+    PageResult<ExamRoomVO> pageExamRoom(ExamRoomReq req);
+
+    void saveExamRoom(LoginUser user, ExamRoomSaveReq req);
+
+    void enable(Long id, Boolean enable);
+
+    List<Map<String, Object>> importExamRoom(LoginUser user, InputStream inputStream);
 }

+ 5 - 4
src/main/java/com/qmth/exam/reserve/service/ExamSiteService.java

@@ -2,10 +2,7 @@ package com.qmth.exam.reserve.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.qmth.boot.core.collection.PageResult;
-import com.qmth.exam.reserve.bean.examsite.ExamSiteInfo;
-import com.qmth.exam.reserve.bean.examsite.ExamSiteReq;
-import com.qmth.exam.reserve.bean.examsite.ExamSiteSaveReq;
-import com.qmth.exam.reserve.bean.examsite.ExamSiteVO;
+import com.qmth.exam.reserve.bean.examsite.*;
 import com.qmth.exam.reserve.bean.login.LoginUser;
 import com.qmth.exam.reserve.bean.stdapply.CategoryVO;
 import com.qmth.exam.reserve.entity.ExamSiteEntity;
@@ -29,4 +26,8 @@ public interface ExamSiteService extends IService<ExamSiteEntity> {
     void enable(Long id, Boolean enable);
 
     List<Map<String, Object>> importExamSite(LoginUser user, InputStream inputStream);
+
+    void updateExamSiteCapacity(Long examSiteId);
+
+    void saveGuide(ExamSiteGuideReq req);
 }

+ 13 - 2
src/main/java/com/qmth/exam/reserve/service/impl/CategoryServiceImpl.java

@@ -211,7 +211,13 @@ public class CategoryServiceImpl extends ServiceImpl<CategoryDao, CategoryEntity
         category.setLevel(CategoryLevel.TEACHING.getValue());
         category.setOrgId(user.getOrgId());
         category.setParentId(getById(req.getCityId()).getId());
-        saveOrUpdate(category);
+        if(req.getId() == null) {
+            save(category);
+        } else {
+            updateById(category);
+            //清空教学点缓存
+            categoryCacheService.clearCategoryByIdCache(category.getId());
+        }
     }
 
     @Override
@@ -235,7 +241,7 @@ public class CategoryServiceImpl extends ServiceImpl<CategoryDao, CategoryEntity
             LambdaQueryWrapper<CategoryEntity> wrapper = new LambdaQueryWrapper<>();
             wrapper.eq(CategoryEntity::getCode, req.getCode());
             List<CategoryEntity> list = baseMapper.selectList(wrapper);
-            if (list.size() > 0) {
+            if (!list.isEmpty()) {
                 throw new StatusException("教学点代码已经存在");
             }
         }
@@ -331,6 +337,11 @@ public class CategoryServiceImpl extends ServiceImpl<CategoryDao, CategoryEntity
         return failRecords;
     }
 
+    @Override
+    public void updateTeachingCapacity(Long teachingId) {
+        baseMapper.updateTeachingCapacity(teachingId);
+    }
+
     private void saveTeaching(CategoryEntity category) {
         LambdaQueryWrapper<CategoryEntity> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(CategoryEntity::getCode, category.getCode());

+ 247 - 0
src/main/java/com/qmth/exam/reserve/service/impl/ExamRoomServiceImpl.java

@@ -1,17 +1,264 @@
 package com.qmth.exam.reserve.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.qmth.boot.core.collection.PageResult;
+import com.qmth.boot.core.exception.StatusException;
+import com.qmth.boot.tools.excel.ExcelReader;
+import com.qmth.boot.tools.excel.enums.ExcelType;
+import com.qmth.boot.tools.excel.model.DataMap;
+import com.qmth.exam.reserve.bean.login.LoginUser;
+import com.qmth.exam.reserve.bean.room.ExamRoomReq;
+import com.qmth.exam.reserve.bean.room.ExamRoomSaveReq;
+import com.qmth.exam.reserve.bean.room.ExamRoomVO;
+import com.qmth.exam.reserve.cache.impl.ApplyTaskCacheService;
 import com.qmth.exam.reserve.dao.ExamRoomDao;
 import com.qmth.exam.reserve.entity.ExamRoomEntity;
+import com.qmth.exam.reserve.entity.ExamSiteEntity;
+import com.qmth.exam.reserve.service.CategoryService;
 import com.qmth.exam.reserve.service.ExamRoomService;
+import com.qmth.exam.reserve.service.ExamSiteService;
+import com.qmth.exam.reserve.util.PageUtil;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.transaction.interceptor.TransactionAspectSupport;
+
+import java.io.InputStream;
+import java.util.*;
 
 @Service
 public class ExamRoomServiceImpl extends ServiceImpl<ExamRoomDao, ExamRoomEntity> implements ExamRoomService {
 
     private static final Logger log = LoggerFactory.getLogger(ExamRoomServiceImpl.class);
+    private static final String[] EXCEL_HEADER = new String[]{"考场号", "考场名称", "考场地址", "考场容量", "所属考点代码", "所属考点名称"};
+
+    @Autowired
+    private ExamSiteService examSiteService;
+
+    @Autowired
+    private CategoryService categoryService;
+
+    @Autowired
+    private ApplyTaskCacheService cacheService;
+
+
+    @Override
+    public PageResult<ExamRoomVO> pageExamRoom(ExamRoomReq req) {
+        IPage<ExamRoomVO> iPage = baseMapper.pageExamRoom(new Page<>(req.getPageNumber(), req.getPageSize()),
+                req);
+        return PageUtil.of(iPage);
+    }
+
+    @Transactional
+    @Override
+    public void saveExamRoom(LoginUser user, ExamRoomSaveReq req) {
+        checkExamRoom(req);
+        ExamRoomEntity examRoomEntity = new ExamRoomEntity();
+        BeanUtils.copyProperties(req, examRoomEntity);
+        if (req.getId() == null) {
+            examRoomEntity.setEnable(Boolean.TRUE);
+            save(examRoomEntity);
+        } else {
+            updateById(examRoomEntity);
+        }
+        //更新考点容量和教学点容量
+        updateExamSiteAndTeachingCapacity(req.getExamSiteId());
+    }
+
+    @Transactional
+    @Override
+    public void enable(Long id, Boolean enable) {
+        ExamRoomEntity examRoom = getById(id);
+        LambdaUpdateWrapper<ExamRoomEntity> wrapper = new LambdaUpdateWrapper<>();
+        wrapper.set(ExamRoomEntity::getEnable, enable);
+        wrapper.eq(ExamRoomEntity::getId, id);
+        update(null, wrapper);
+
+        updateExamSiteAndTeachingCapacity(examRoom.getExamSiteId());
+    }
+
+    @Override
+    public List<Map<String, Object>> importExamRoom(LoginUser user, InputStream inputStream) {
+        List<DataMap> lineList = null;
+        ExcelReader reader = ExcelReader.create(ExcelType.XLSX, inputStream, 0);
+        try {
+            lineList = reader.getDataMapList();
+        } catch (Exception e) {
+            throw new StatusException("Excel 解析失败");
+        }
+        if (com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isEmpty(lineList)) {
+            throw new StatusException("Excel无内容");
+        }
+        List<Map<String, Object>> failRecords = new ArrayList<>();
+        List<ExamRoomEntity> examRoomList = new ArrayList<>();
+        Long teachingId = user.getCategoryId();
+        for (int i = 0; i < lineList.size(); i++) {
+            DataMap line = lineList.get(i);
+            ExamRoomEntity room = new ExamRoomEntity();
+            StringBuilder msg = new StringBuilder();
+            String code = trimAndNullIfBlank(line.get(EXCEL_HEADER[0]));
+            if (StringUtils.isBlank(code)) {
+                msg.append(" 考场号不能为空");
+            } else {
+                room.setCode(code);
+            }
+            String name = trimAndNullIfBlank(line.get(EXCEL_HEADER[1]));
+            if (StringUtils.isBlank(name)) {
+                msg.append(" 考场名称不能为空");
+            } else {
+                room.setName(name);
+            }
+            String address = trimAndNullIfBlank(line.get(EXCEL_HEADER[2]));
+            if (StringUtils.isBlank(address)) {
+                msg.append(" 考场地址不能为空");
+            } else {
+                room.setAddress(address);
+            }
+            String capacity = trimAndNullIfBlank(line.get(EXCEL_HEADER[3]));
+            if (StringUtils.isBlank(capacity) || !capacity.matches("\\d+") || Integer.parseInt(capacity) <= 0) {
+                msg.append(" 考场容量必须为大于0的整数");
+            } else {
+                room.setCapacity(Integer.parseInt(capacity));
+            }
+            String examSiteCode = trimAndNullIfBlank(line.get(EXCEL_HEADER[4]));
+            if (StringUtils.isBlank(examSiteCode)) {
+                msg.append(" 所属考点代码不能为空");
+            }
+            String examSiteName = trimAndNullIfBlank(line.get(EXCEL_HEADER[5]));
+            if (StringUtils.isBlank(examSiteName)) {
+                msg.append(" 所属考点名称不能为空");
+            }
+            List<ExamSiteEntity> examSiteList = listExamSite(examSiteCode, examSiteName, teachingId);
+            if (examSiteList.isEmpty()) {
+                msg.append(" 找不到所属考点");
+            }
+            if (examSiteList.size() > 1) {
+                msg.append(" 找到的所属考点大于1个");
+            }
+            if (examSiteList.size() == 1) {
+                ExamRoomEntity examRoom = getExamRoom(examSiteList.get(0).getId(), code);
+                if (examRoom != null) {
+                    msg.append(" 当前考点下已经存在考场代码为:").append(code).append("的考场");
+                } else {
+                    room.setExamSiteId(examSiteList.get(0).getId());
+                    room.setEnable(Boolean.TRUE);
+                }
+            }
+
+            if (msg.length() > 0) {
+                failRecords.add(newError(i + 1, msg.toString()));
+            } else {
+                examRoomList.add(room);
+            }
+        }
+
+        if (!failRecords.isEmpty())
+            return failRecords;
+
+        for (int i = 0; i < examRoomList.size(); i++) {
+            ExamRoomEntity examRoomEntity = examRoomList.get(i);
+            try {
+                saveRoom(examRoomEntity);
+            } catch (Exception e) {
+                failRecords.add(newError(i + 1, " 系统异常"));
+                log.error("导入异常", e);
+            }
+        }
+
+        if (CollectionUtils.isNotEmpty(failRecords)) {
+            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+            return failRecords;
+        }
+
+        return failRecords;
+    }
+
+    private void saveRoom(ExamRoomEntity room) {
+        ExamRoomEntity examRoom = getExamRoom(room.getExamSiteId(), room.getCode());
+        if (examRoom != null) {
+            examRoom.setCapacity(room.getCapacity());
+            LambdaUpdateWrapper<ExamRoomEntity> wrapper = new LambdaUpdateWrapper<>();
+            wrapper.set(ExamRoomEntity::getName, room.getName());
+            wrapper.set(ExamRoomEntity::getAddress, room.getAddress());
+            wrapper.set(ExamRoomEntity::getCapacity, room.getCapacity());
+            wrapper.set(ExamRoomEntity::getEnable, Boolean.TRUE);
+            wrapper.eq(ExamRoomEntity::getId, room.getId());
+            update(null, wrapper);
+        } else {
+            save(room);
+        }
+        updateExamSiteAndTeachingCapacity(room.getExamSiteId());
+    }
+
+    private List<ExamSiteEntity> listExamSite(String examSiteCode, String examSiteName, Long categoryId) {
+        ExamSiteEntity examSiteEntity = null;
+        LambdaQueryWrapper<ExamSiteEntity> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(ExamSiteEntity::getCode, examSiteCode);
+        wrapper.eq(ExamSiteEntity::getName, examSiteName);
+        wrapper.eq(categoryId != null, ExamSiteEntity::getCategoryId, categoryId);
+        return examSiteService.list(wrapper);
+    }
+
+    private void updateExamSiteAndTeachingCapacity(Long examSiteId) {
+        examSiteService.updateExamSiteCapacity(examSiteId);
+        ExamSiteEntity examSite = examSiteService.getById(examSiteId);
+        categoryService.updateTeachingCapacity(examSite.getCategoryId());
+        //清空考点容量缓存
+        cacheService.clearApplyTotalCountCache(examSiteId);
+    }
+
+    private void checkExamRoom(ExamRoomSaveReq req) {
+        if (StringUtils.isEmpty(req.getCode())) {
+            throw new StatusException("考场代码不能为空");
+        }
+        if (StringUtils.isEmpty(req.getName())) {
+            throw new StatusException("考场名称不能为空");
+        }
+        if (StringUtils.isEmpty(req.getAddress())) {
+            throw new StatusException("考场地址不能为空");
+        }
+        if (req.getCapacity() == null || req.getCapacity() <= 0) {
+            throw new StatusException("考场容量必须大于0");
+        }
+        if (req.getExamSiteId() == null) {
+            throw new StatusException("请选择考点");
+        }
+        if (req.getId() == null) {
+            ExamRoomEntity examRoomEntity = getExamRoom(req.getExamSiteId(), req.getCode());
+            if (examRoomEntity != null) {
+                ExamSiteEntity site = examSiteService.getById(req.getExamSiteId());
+                throw new StatusException("考点:" + site.getName() + "下已存在代码为:" + req.getCode() + "的考场");
+            }
+        }
+    }
+
+    private ExamRoomEntity getExamRoom(Long examSiteId, String roomCode) {
+        LambdaQueryWrapper<ExamRoomEntity> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(ExamRoomEntity::getExamSiteId, examSiteId);
+        wrapper.eq(ExamRoomEntity::getCode, roomCode);
+        return baseMapper.selectOne(wrapper);
+    }
 
+    private String trimAndNullIfBlank(String s) {
+        if (StringUtils.isBlank(s)) {
+            return null;
+        }
+        return s.trim();
+    }
 
+    private Map<String, Object> newError(int lineNum, String msg) {
+        Map<String, Object> map = new HashMap<>();
+        map.put("lineNum", lineNum);
+        map.put("msg", msg);
+        return map;
+    }
 }

+ 50 - 26
src/main/java/com/qmth/exam/reserve/service/impl/ExamSiteServiceImpl.java

@@ -2,6 +2,7 @@ package com.qmth.exam.reserve.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -10,12 +11,10 @@ import com.qmth.boot.core.exception.StatusException;
 import com.qmth.boot.tools.excel.ExcelReader;
 import com.qmth.boot.tools.excel.enums.ExcelType;
 import com.qmth.boot.tools.excel.model.DataMap;
-import com.qmth.exam.reserve.bean.examsite.ExamSiteInfo;
-import com.qmth.exam.reserve.bean.examsite.ExamSiteReq;
-import com.qmth.exam.reserve.bean.examsite.ExamSiteSaveReq;
-import com.qmth.exam.reserve.bean.examsite.ExamSiteVO;
+import com.qmth.exam.reserve.bean.examsite.*;
 import com.qmth.exam.reserve.bean.login.LoginUser;
 import com.qmth.exam.reserve.bean.stdapply.CategoryVO;
+import com.qmth.exam.reserve.cache.impl.ExamSiteCacheService;
 import com.qmth.exam.reserve.dao.ExamSiteDao;
 import com.qmth.exam.reserve.entity.CategoryEntity;
 import com.qmth.exam.reserve.entity.ExamSiteEntity;
@@ -27,6 +26,7 @@ import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.transaction.interceptor.TransactionAspectSupport;
 
 import java.io.InputStream;
@@ -40,6 +40,9 @@ public class ExamSiteServiceImpl extends ServiceImpl<ExamSiteDao, ExamSiteEntity
     @Autowired
     private CategoryService categoryService;
 
+    @Autowired
+    private ExamSiteCacheService examSiteCacheService;
+
     @Override
     public List<CategoryVO> listExamSite(Long teachingId) {
         QueryWrapper<ExamSiteEntity> wrapper = new QueryWrapper<>();
@@ -101,18 +104,16 @@ public class ExamSiteServiceImpl extends ServiceImpl<ExamSiteDao, ExamSiteEntity
         checkExamSite(req);
         ExamSiteEntity site = new ExamSiteEntity();
         BeanUtils.copyProperties(req, site);
-        if(req.getId() == null) {
-            LambdaQueryWrapper<ExamSiteEntity> wrapper = new LambdaQueryWrapper<>();
-            wrapper.eq(ExamSiteEntity::getCategoryId, req.getCategoryId());
-            wrapper.eq(ExamSiteEntity::getCode, req.getCode());
-            ExamSiteEntity existSite = baseMapper.selectOne(wrapper);
-            if (existSite != null) {
-                throw new StatusException("code:" + req.getCode() + "已经存在");
-            }
+        if (req.getId() == null) {
+            site.setEnable(Boolean.TRUE);
             save(site);
         } else {
             updateById(site);
+            //清空考点缓存
+            examSiteCacheService.clearExamSiteByIdCache(site.getId());
         }
+
+
     }
 
     @Override
@@ -122,6 +123,7 @@ public class ExamSiteServiceImpl extends ServiceImpl<ExamSiteDao, ExamSiteEntity
         baseMapper.updateById(examSite);
     }
 
+    @Transactional
     @Override
     public List<Map<String, Object>> importExamSite(LoginUser user, InputStream inputStream) {
         List<DataMap> lineList = null;
@@ -134,7 +136,7 @@ public class ExamSiteServiceImpl extends ServiceImpl<ExamSiteDao, ExamSiteEntity
         if (com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isEmpty(lineList)) {
             throw new StatusException("Excel无内容");
         }
-        List<Map<String, Object>> failRecords = new ArrayList<Map<String, Object>>();
+        List<Map<String, Object>> failRecords = new ArrayList<>();
         List<ExamSiteEntity> examSiteList = new ArrayList<>();
         for (int i = 0; i < lineList.size(); i++) {
             DataMap line = lineList.get(i);
@@ -161,9 +163,9 @@ public class ExamSiteServiceImpl extends ServiceImpl<ExamSiteDao, ExamSiteEntity
                 wrapper.eq(CategoryEntity::getEnable, Boolean.TRUE);
                 wrapper.eq(CategoryEntity::getOrgId, user.getOrgId());
                 List<CategoryEntity> list = categoryService.list(wrapper);
-                if(list.isEmpty()) {
+                if (list.isEmpty()) {
                     msg.append(" 所属教学点不存在");
-                } else if(list.size() > 1) {
+                } else if (list.size() > 1) {
                     msg.append(" 所属教学点,查询到多条相同名称的数据");
                 } else {
                     site.setCategoryId(list.get(0).getId());
@@ -204,36 +206,58 @@ public class ExamSiteServiceImpl extends ServiceImpl<ExamSiteDao, ExamSiteEntity
         return failRecords;
     }
 
+    @Override
+    public void updateExamSiteCapacity(Long examSiteId) {
+        baseMapper.updateExamSiteCapacity(examSiteId);
+    }
+
+    @Override
+    public void saveGuide(ExamSiteGuideReq req) {
+        ExamSiteEntity examSite = getById(req.getId());
+        LambdaUpdateWrapper<ExamSiteEntity> updateWrapper = new LambdaUpdateWrapper<>();
+        updateWrapper.set(ExamSiteEntity::getGuide, req.getGuide());
+        updateWrapper.eq(ExamSiteEntity::getId, req.getId());
+        update(null , updateWrapper);
+    }
+
     private void saveExamSite(ExamSiteEntity examSite) {
         LambdaQueryWrapper<ExamSiteEntity> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(ExamSiteEntity::getCode, examSite.getCode());
         wrapper.eq(ExamSiteEntity::getCategoryId, examSite.getCategoryId());
         ExamSiteEntity existSite = baseMapper.selectOne(wrapper);
         if (existSite != null) {
-            existSite.setEnable(Boolean.TRUE);
-            existSite.setName(examSite.getName());
-            existSite.setAddress(examSite.getAddress());
-            baseMapper.updateById(existSite);
+            LambdaUpdateWrapper<ExamSiteEntity> updateWrapper = new LambdaUpdateWrapper<>();
+            updateWrapper.set(ExamSiteEntity::getName, examSite.getName());
+            updateWrapper.set(ExamSiteEntity::getAddress, examSite.getAddress());
+            updateWrapper.eq(ExamSiteEntity::getId, examSite.getId());
+            update(null, updateWrapper);
         } else {
-            baseMapper.insert(examSite);
+            examSite.setEnable(Boolean.TRUE);
+            save(examSite);
         }
     }
 
     private void checkExamSite(ExamSiteSaveReq req) {
-        if(StringUtils.isEmpty(req.getCode())) {
+        if (StringUtils.isEmpty(req.getCode())) {
             throw new StatusException("考点代码不能为空");
         }
-        if(StringUtils.isEmpty(req.getName())) {
+        if (StringUtils.isEmpty(req.getName())) {
             throw new StatusException("考点名称不能为空");
         }
-        if(StringUtils.isEmpty(req.getAddress())) {
+        if (StringUtils.isEmpty(req.getAddress())) {
             throw new StatusException("考点地址不能为空");
         }
-        if(req.getCategoryId() == null) {
+        if (req.getCategoryId() == null) {
             throw new StatusException("请选择考点所属教学点");
         }
-        if(req.getEnable() == null) {
-            throw new StatusException("请选择考点状态");
+        if (req.getId() == null) {
+            LambdaQueryWrapper<ExamSiteEntity> wrapper = new LambdaQueryWrapper<>();
+            wrapper.eq(ExamSiteEntity::getCategoryId, req.getCategoryId());
+            wrapper.eq(ExamSiteEntity::getCode, req.getCode());
+            ExamSiteEntity existSite = baseMapper.selectOne(wrapper);
+            if (existSite != null) {
+                throw new StatusException("考点代码:" + req.getCode() + "已经存在");
+            }
         }
     }
 

+ 6 - 0
src/main/resources/mapper/CategoryMapper.xml

@@ -28,4 +28,10 @@
         </if>
         order by c.code
     </select>
+    
+    <update id="updateTeachingCapacity">
+        UPDATE t_category SET capacity =( SELECT sum( capacity ) FROM t_exam_site WHERE category_id = #{teachingId} AND ENABLE = 1 )
+        WHERE
+            id = #{teachingId}
+    </update>
 </mapper>

+ 31 - 1
src/main/resources/mapper/ExamRoomMapper.xml

@@ -1,5 +1,35 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.qmth.exam.reserve.dao.ExamRoomDao">
-
+    <select id="pageExamRoom" resultType="com.qmth.exam.reserve.bean.room.ExamRoomVO">
+        SELECT
+            r.ID,
+            r.CODE,
+            r.NAME,
+            r.address,
+            r.capacity,
+            s.NAME examSiteName,
+            g.NAME teachingName,
+            r.ENABLE
+        FROM
+            t_exam_room r,
+            t_exam_site s,
+            t_category g
+        WHERE
+            r.exam_site_id = s.id
+          AND s.category_id = g.id
+        <if test="req.teachingId != null">
+            AND s.category_id=#{req.teachingId}
+        </if>
+        <if test="req.examSiteId != null">
+            AND s.id=#{req.examSiteId}
+        </if>
+        <if test="req.enable != null">
+            AND r.enable=#{req.enable}
+        </if>
+        <if test="req.name != null and req.name != ''">
+            AND r.name like concat('%',#{req.name}, '%')
+        </if>
+        order by r.code
+    </select>
 </mapper>

+ 7 - 0
src/main/resources/mapper/ExamSiteMapper.xml

@@ -44,5 +44,12 @@
             and s.enable=#{req.enable}
         </if>
     </select>
+    
+    <update id="updateExamSiteCapacity">
+        UPDATE t_exam_site
+        SET capacity = ( SELECT sum( capacity ) FROM t_exam_room WHERE exam_site_id = #{examSiteId} AND ENABLE = 1 )
+        WHERE
+            id =  #{examSiteId};
+    </update>
 
 </mapper>

BIN
src/main/resources/templates/examRoom.xlsx