欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【机房报修管理系统】 后端篇(二十) Controller层开发——工单管理相关接口

程序员文章站 2022-06-18 17:15:46
...

一、前情提要


    各位朋友新年快乐,今天是年初八,由于春节的关系,【机房报修管理系统】停更了一段时间,但是并不是弃坑了,我会再以后尽量1~2天一更,把前端篇和后端篇的坑填上。
    上一次我们做完了管理员的Controller层的开发,这一次我们进行工单管理的开发;由于在上一篇文章《【机房报修管理系统】 后端篇(十九) Controller层开发——管理员相关接口》对一些简单的增删改查的接口有详细的说明,所以接下来的Controller开发中,对于一些比较简单的接口就不再赘述,请各位同学自行查看上面提到的文章。



二、接口功能设想


    在工单管理接口中,除了最基本的增删改查的功能外,还需要有一个受理工单完成工单功能,用于管理员在后台能够对工单进行改变工单状态。在保存工单,即报修人在报修的时候,可以提供上传图片功能。

    受理工单时,工单状态从未受理转为受理中,工单需要填上受理的管理员编号,并且发送邮件给报修人留下的邮箱,和报修人说明工单正在维修中。

    完成工单时,首先将工单在数据库表Order(未受理或受理中工单)转存到CompleteOrder(已完成工单),并且删除Order表中的相应数据,相应的机房可用电脑数+1。


三、接口设计以及实现


注意:以下的接口不再进行详细说明,需要的同学请查看我的GitHub

  • getAllOrdersInfo(获得所有维修工单信息)
  • getOrdersInfoById(通过维修工单ID获得工单信息)
  • updateOrders(修改维修工单)
  • deleteOrders(删除维修工单)

前期准备

pom.xml中导入相应的第三方工具

		<dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-io</artifactId>
            <version>1.3.2</version>
        </dependency>
        <dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils</artifactId>
            <version>1.9.3</version>
        </dependency>

设定存储图片的虚拟目录以及文件上传配置
application.properties中编写以下配置

# 文件上传配置
spring.servlet.multipart.max-file-size=100Mb
spring.servlet.multipart.max-request-size=1000Mb
#维修工单图片虚拟目录
order.img.dir=/opt/Image
#所有的访问都经过静态资源路径
spring.mvc.static-path-pattern=/**
#配置静态资源路径
spring.resources.static-locations= \
  classpath:/META-INF/resources/,\
  classpath:/resources/,\
  classpath:/static/,\
  classpath:/public/,\
  file:${order.img.dir}

1.创建一个工单管理相关的类OrderController

com.repairsystem.web.controller下常见工单管理类OrderController

@RestController
@Api(value = "维修工单相关接口", tags = {"维修工单业务相关接口"})
@RequestMapping("/orders")
public class OrderController {

    @Autowired
    private OrdersService ordersService;
    
    @Autowired
    private ClassService classService;

    @Autowired
    private CompleteOrderService completeOrderService;

    @Autowired
    private EmailService emailService;
}

2.创建工单的VO类OrderVO

com.repairsystem.entity.vo下创建VO类OrderVO
下面的@JsonFormat注解是用于在以JSON格式输出的时候规定输出的格式

package com.repairsystem.entity.vo;

import com.fasterxml.jackson.annotation.JsonFormat;

import java.util.Date;

/**
 * @author CheungChingYin
 * @date 2018/11/2
 * @time 21:40
 */
public class OrderVO {

    private Integer orderId;
    private String problem;
    private Integer computerNumber;
    private String className;
    private String buildingName;
    private Integer status;
    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
    private Date submitTime;
    private String imagesPath;
    private Integer adminId;
    private String adminName;
    private String userName;
    private String userPhone;
    private String userEmail;

    public Integer getOrderId() {
        return orderId;
    }

    public void setOrderId(Integer orderId) {
        this.orderId = orderId;
    }

    public String getProblem() {
        return problem;
    }

    public void setProblem(String problem) {
        this.problem = problem;
    }

    public Integer getComputerNumber() {
        return computerNumber;
    }

    public void setComputerNumber(Integer computerNumber) {
        this.computerNumber = computerNumber;
    }

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }

    public String getBuildingName() {
        return buildingName;
    }

    public void setBuildingName(String buildingName) {
        this.buildingName = buildingName;
    }

    public Integer getStatus() {
        return status;
    }

    public void setStatus(Integer status) {
        this.status = status;
    }

    public Date getSubmitTime() {
        return submitTime;
    }

    public void setSubmitTime(Date submitTime) {
        this.submitTime = submitTime;
    }

    public String getImagesPath() {
        return imagesPath;
    }

    public void setImagesPath(String imagesPath) {
        this.imagesPath = imagesPath;
    }

    public String getAdminName() {
        return adminName;
    }

    public void setAdminName(String adminName) {
        this.adminName = adminName;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getUserPhone() {
        return userPhone;
    }

    public void setUserPhone(String userPhone) {
        this.userPhone = userPhone;
    }

    public String getUserEmail() {
        return userEmail;
    }

    public void setUserEmail(String userEmail) {
        this.userEmail = userEmail;
    }

    public Integer getAdminId() {
        return adminId;
    }

    public void setAdminId(Integer adminId) {
        this.adminId = adminId;
    }

    @Override
    public String toString() {
        return "OrderVO{" +
                "orderId=" + orderId +
                ", problem='" + problem + '\'' +
                ", computerNumber=" + computerNumber +
                ", className='" + className + '\'' +
                ", buildingName='" + buildingName + '\'' +
                ", status=" + status +
                ", submitTime=" + submitTime +
                ", imagesPath='" + imagesPath + '\'' +
                ", adminId=" + adminId +
                ", adminName='" + adminName + '\'' +
                ", userName='" + userName + '\'' +
                ", userPhone='" + userPhone + '\'' +
                ", userEmail='" + userEmail + '\'' +
                '}';
    }
}

3.实现上传图片功能:uploadImage

  • URI:/orders/uploadImage

  • 请求方式:POST

  • 参数:file(属于多文件类MultipartFile

  • 返回信息:状态码200,图片路径信息(上传图片成功时)

  • 返回信息:状态码500,存储图片时出现的异常(上传图片失败时)

  • 返回信息:Null(没有图片上传时)

  • 接口实现方法:
    1.检查上传的file是否为空,为空则返回null
    2.调用图片上传工具
    3.如果返回的map有success则视为上传成功,返回图片的上传地址。
    4.如果返回的map为空或者出success外的其他key值,则返回上传图片出现的异常。

  • 上传图片工具类OrderUploadUtils的实现方法
    1.检查传入的file是否为空,如果为空则返回map提示为空。
    2.以yyyy-MM-dd的格式获取当前日期。
    3.存储的文件夹地址以固定的前缀地址/当前日期/,检查有没有此文件夹存在,如果不存在则创建相应的文件夹。
    4.检查文件的格式是否属于gif,jpg,jpeg,png,如果不属于则返回错误信息说明文件格式不对。
    5.文件以文件名当前时间+UUID.jpg的格式储存,如果储存失败则返回失败信息,储存成功则返回图片存储路径。

虚拟目录的地址(按照上面配置的虚拟目录地址进行填写)
com.repairsystem.utils.ConstantUtils编写以下常量

 class Path {

        //虚拟目录地址
        public static final String DIRPATH = "/opt/Image";
    }

com.repairsystem.utils创建图片上传工具OrderUploadUtils

package com.repairsystem.utils;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * @author CheungChingYin
 * @date 2018/11/13
 * @time 10:40
 */
@Component
public class OrderUploadUtils {


    private static String dir = ConstantUtils.Path.DIRPATH;

    public static Map<String, String> upLoadOrderImage(MultipartFile file) {
        Map<String, String> resultMap = new HashMap<String, String>();
        if (file.isEmpty()) {
            resultMap.put("failure", "传入的文件为空");
            return resultMap;
        }
        SimpleDateFormat simpleDateFormatDate = new SimpleDateFormat("yyyy-MM-dd");
        String currentDate = simpleDateFormatDate.format(new Date());

        String fileName = file.getOriginalFilename();
        String realPath = dir + "/" + currentDate + "/";
        File fileDir = new File(realPath);
        if (!fileDir.exists()) {
            fileDir.mkdirs();
        }

        String extName = FilenameUtils.getExtension(fileName);
        String allowImgFormat = "gif,jpg,jpeg,png";

        if (!allowImgFormat.contains(extName.toLowerCase())) {
            resultMap.put("failure", "传入的文件不是图像");
            return resultMap;
        }

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd&HH-mm-ss");
        String currentTime = simpleDateFormat.format(new Date());
        fileName = currentTime + UUID.randomUUID() + ".jpg";
        InputStream inputStream = null;
        FileOutputStream fileOutputStream = null;
        try {
            inputStream = file.getInputStream();
            fileOutputStream = new FileOutputStream(realPath + fileName);
            IOUtils.copy(inputStream, fileOutputStream);
        } catch (IOException e) {
            resultMap.put("failure", "图片储存失败");
            e.printStackTrace();
            return resultMap;
        } finally {
            IOUtils.closeQuietly(inputStream);
            IOUtils.closeQuietly(fileOutputStream);
        }
        resultMap.put("success", "/" + currentDate + "/" + fileName);
        return resultMap;
    }
}

com.repairsystem.web.controller.OrderController编写接口逻辑

 @ApiOperation(value = "上传工单图片")
    @PostMapping(value = "/uploadImage")
    public JsonResult uploadImage(@ApiParam(value = "图片上传") MultipartFile file){
        if (!file.isEmpty()) {
            String dbPath = null;
            Map<String,String> map = OrderUploadUtils.upLoadOrderImage(file);
            if (map.get("success") != null){
                dbPath = map.get("success");
                return JsonResult.ok(dbPath);
            }else{
                return JsonResult.errorMsg(map.get("failure"));
            }
        } else {
            return null;
        }
    }

4.保存维修工单:saveOrders

  • URI:/orders/saveOrders
  • 请求方式POST
  • 请求参数:problem(工单问题,数据类型为String
  • 请求参数:computerNumber(电脑编号,数据类型为Integer
  • 请求参数:classId(实训室ID,数据类型为Integer
  • 请求参数:buildingId(实训楼ID,数据类型为Integer
  • 请求参数:userName(报修人名字,数据类型为String
  • 请求参数:userPhone(报修人手机号,数据类型为String
  • 请求参数:userEmail(报修人邮箱,数据类型为String
  • 请求参数:imagePath(图片路径,数据类型为String
  • 返回信息:状态码200(成功时)
  • 返回信息:状态码500(失败时)
  • 实现方法:
    1.创建一个order对象,将获得的信息存入对象中。
    2.对象order的属性状态设置为0(未受理)
    3.对象order的提交时间setSubmitTime设置为当前时间
    4.将信息存入数据库中
    5.调用reduceComputerEnable方法将对应实训室的可用电脑减少1台。
 @ApiOperation(value = "保存维修工单")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "problem", value = "维修工单问题", required = true, dataType = "String", paramType = "form"),
            @ApiImplicitParam(name = "computerNumber", value = "维修电脑编号", required = true, dataType = "String", paramType = "form"),
            @ApiImplicitParam(name = "classId", value = "所属实训室编号", required = true, dataType = "String", paramType = "form"),
            @ApiImplicitParam(name = "buildingId", value = "所属实训楼编号", required = true, dataType = "String", paramType = "form"),
            @ApiImplicitParam(name = "userName", value = "报修人名称", required = true, dataType = "String", paramType = "form"),
            @ApiImplicitParam(name = "userPhone", value = "报修人电话", required = true, dataType = "String", paramType = "form"),
            @ApiImplicitParam(name = "userEmail", value = "报修人邮箱", required = true, dataType = "String", paramType = "form"),
            @ApiImplicitParam(name = "imagePath", value = "图片地址", required = true, dataType = "String", paramType = "form"),
    })
    @PostMapping(value = "/saveOrders")
    public JsonResult saveOrders(String problem, Integer computerNumber, Integer classId, Integer buildingId, String userName, String userPhone, String userEmail, String imagePath) {
        if (StringUtils.isBlank(classId.toString())) {
            JsonResult.errorMsg("传入的实训室ID(classId)不能为空");
        }
        Orders orders = new Orders();

        orders.setImagesPath(imagePath);
        orders.setProblem(problem);
        orders.setComputerNumber(computerNumber);
        orders.setClassId(classId);
        orders.setBuildingId(buildingId);
        orders.setStatus(0);//刚提交维修工单状态是未维修状态0
        orders.setUserName(userName);
        orders.setUserPhone(userPhone);
        orders.setUserEmail(userEmail);
        orders.setSubmitTime(new Date());

        ordersService.saveOrder(orders);
        classService.reduceComputerEnable(orders.getClassId());
        return JsonResult.ok();
    }

5.接受维修工单receiveOrder

  • URI:/orders/receiveOrder
  • 请求方法:GET
  • 请求参数:orderId(维修工单ID,数据类型为Integer
  • 请求参数:adminId(接受维修工单管理员ID,数据类型为Integer
  • 返回信息:状态码200(成功时)
  • 返回信息:状态码500,返回邮件发送失败信息(邮件发送失败时)
  • 实现方法:
    1.通过工单ID获得工单对象。
    2.通过工单ID更新工单的接收管理员ID并且工单状态为1(受理中)。
    3.调用邮件服务发送邮件
 @ApiOperation(value = "接受维修工单")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "orderId", value = "维修工单ID", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "adminId",value = "接受维修工单管理员ID",required = true,dataType = "String", paramType = "query"),
    })
    @GetMapping("/receiveOrder")
    public JsonResult receiveOrder(Integer orderId, Integer adminId){
        Orders orderInfo = ordersService.searchOrderById(orderId);
        Orders order = new Orders();
        order.setOrderId(orderId);
        order.setAdminId(adminId);
        order.setStatus(1);
        ordersService.updateOrder(order);
        String emailResult = emailService.acceptOrderMail(orderInfo.getUserName(),orderInfo.getUserEmail());
        if(!"OK".equals(emailResult)){
            JsonResult.errorMsg("邮件发送失败");
        }
        return JsonResult.ok();
    }

6.完成维修工单orderComplete

  • URI:/orders/orderComplete
  • 请求方法:POST
  • 请求参数:orderId(维修工单ID,数据类型为Integer
  • 请求参数:remark(维修备注,数据类型为String
  • 返回信息:状态码200(成功时)
  • 返回信息:状态码500,返回邮件发送失败信息(邮件发送失败时)
  • 实现方法:
    1.通过工单ID获得工单对象信息。
    2.将工单信息转存到completeOrder对象中,并且存入completeOrder数据表(工单完成表)中。
    3.删除在`orders``数据表中的相应数据。
    4.在相应的实训室可用电脑+1(维修完成)。
    5.发送邮件到报修人的邮箱中,提示维修已完成。
 @ApiOperation(value = "完成维修工单")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "orderId", value = "维修工单ID", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "remark",value = "维修备注",dataType = "Long",paramType = "query")
    })

    @PostMapping("/orderComplete")
    public JsonResult orderComplete(Integer orderId, String remark){
        if (StringUtils.isBlank(orderId.toString())){
            return JsonResult.errorMsg("传入的维修工单ID(orderId)不能为空");
        }
        Orders order = ordersService.searchOrderById(orderId);
        CompleteOrder completeOrder = Entity2VO.entity2VO(order, CompleteOrder.class);
        if(StringUtils.isNoneBlank(remark)){
            completeOrder.setRemark(remark);
        }
        completeOrder.setImagePath(order.getImagesPath());
        completeOrder.setCompleteTime(new Date());
        completeOrder.setAdminName(null);
        completeOrder.setClassName(null);
        completeOrder.setBuildingName(null);

        try {
            completeOrderService.saveCompleteOrder(completeOrder);
        } catch (Exception e) {
            return JsonResult.errorException(e.getMessage());
        }
        ordersService.deleteOrder(orderId);
        classService.increaseComputerEnable(order.getClassId());
        String emailResult = emailService.completeOrderMail(order.getUserName(),order.getUserEmail());
        if(!"OK".equals(emailResult)){
            JsonResult.errorMsg("邮件发送失败");
        }
        return JsonResult.ok();

    }

     到这里,Controller层开发——工单管理相关接口已经开发完成了。如果您对次篇文章有疑问,可以在文章下方留言,谢谢您的阅读。如对【机房报修管理系统】系列文章有兴趣,可以关注或收藏我的文章,您的支持是我最大的动力,我会尽快推出下一期内容,敬请期待。