package com.repair.controller;


import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jcraft.jsch.*;
import com.repair.annotation.PassToken;
import com.repair.api.RepairRecordControllerAPI;
import com.repair.common.utils.*;
import com.repair.config.WxOpenidConfig;
import com.repair.model.enumModel.*;
import com.repair.model.pojo.*;
import com.repair.model.request.*;
import com.repair.model.result.*;
import com.repair.model.vo.*;
import com.repair.services.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.InputStream;
import java.math.BigDecimal;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import static com.repair.common.utils.StrUtils.getUUIDBits;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author ceshi
 * @since 2023-07-24
 */
@RestController
public class RepairRecordController implements RepairRecordControllerAPI {

    @Autowired
    private WeiXiaoUtil weiXiaoUtil;
    @Autowired
    private WxOpenidConfig wxOpenidConfig;
    @Autowired
    private RepairUserService repairUserService;
    @Autowired
    private RepairAdminService repairAdminService;
    @Autowired
    private RepairRecordService repairRecordService;
    @Autowired
    private RepairSchoolService repairSchoolService;
    @Autowired
    private RepairConsumeService repairConsumeService;
    @Autowired
    private RepairEvaluateService repairEvaluateService;
    @Autowired
    private RepairReceivingService repairReceivingService;
    @Autowired
    private RepairPayRecordService repairPayRecordService;
    @Autowired
    private RepairTrackRecordService repairTrackRecordService;
    @Autowired
    private RepairArticleTypeService repairArticleTypeService;
    @Autowired
    private RepairConsumablesService repairConsumablesService;
    @Autowired
    private RepairLeaveMessageService repairLeaveMessageService;
    @Autowired
    private RepairShiftSettingsService repairShiftSettingsService;
    @Autowired
    private RepairTransferRecordService repairTransferRecordService;
    @Autowired
    private RepairOfflineRecordService repairOfflineRecordService;
    @Autowired
    private RepairDispatchRecordService repairDispatchRecordService;
    @Autowired
    private RepairSystemMessagesService repairSystemMessagesService;
    @Autowired
    private RepairCollaborateRecordService repairCollaborateRecordService;

    /**
     * 报修单微信支付接口
     *
     * @param wpr           微信支付参数
     * @param bindingResult 是否为空判断
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public CommonResult pay(WxPayRequest wpr, BindingResult bindingResult) throws Exception {
        System.out.println(TimeExchange.getTime() + "进入微信支付====");
        System.out.println(TimeExchange.getTime() + "微信支付参数====：" + JSON.toJSON(wpr));
        if (bindingResult.hasErrors()) {
            String st = paramUtils.getParamError(bindingResult);
            return CommonResult.fail(st);
        }

        RepairRecord rr = repairRecordService.getRepairById(wpr.getRecordId());
        if (rr == null) {
            return CommonResult.fail("维修单已失效，支付失败");
        }

        if (wpr.getTotalPrice().compareTo(rr.getPrice()) != 0) {
            return CommonResult.fail("支付金额与订单金额不一致");
        }

        //查看该订单是否支付过
        RepairPayRecord oldRpr = repairPayRecordService.getRepairPayByRecordId(wpr.getRecordId());
        if (oldRpr != null && oldRpr.getIsSuccess().equals(ePayStatu.Paysuccess.getValue())) {
            return CommonResult.fail("该订单已支付，请勿重复操作");
        }

        try {
            System.out.println(TimeExchange.getTime() + "微信支付判断全部通过");
            //返回0表示等于0，返回1表示大于0，返回-1表示小于0
            if (wpr.getTotalPrice().compareTo(BigDecimal.ZERO) < 0 || wpr.getTotalPrice().compareTo(BigDecimal.ZERO) == 0) {
                if (oldRpr == null) {
                    RepairPayRecord rpr = new RepairPayRecord();
                    rpr.setRecordId(wpr.getRecordId());
                    rpr.setUserId(rr.getUserId());
                    rpr.setPayNo(getUUIDBits(15));
                    rpr.setPayPrice(BigDecimal.ZERO);
                    rpr.setIsSuccess(ePayStatu.Paysuccess.getValue());
                    rpr.setRemark("支付金额为0，不用走微信支付");
                    int insertRpr = repairPayRecordService.insertRepairPayRecord(rpr);
                    if (insertRpr <= 0) {
                        throw new Exception("支付失败！");
                    }
                } else {
                    oldRpr.setRemark(oldRpr.getRemark() + "后续支付：支付金额为0，不用走微信支付");
                    oldRpr.setPayPrice(BigDecimal.ZERO);
                    oldRpr.setIsSuccess(ePayStatu.Paysuccess.getValue());
                    int updateRpr = repairPayRecordService.updateRepairPayRecord(oldRpr);
                    if (updateRpr <= 0) {
                        throw new Exception("支付失败！");
                    }
                }

                rr.setMaintenanceState(eRecordStatu.Maintenance.getValue());

                int updateRecord = repairRecordService.updateRepairRecord(rr);
                if (updateRecord <= 0) {
                    throw new Exception("支付失败！");
                }
            }
        } catch (Exception e) {
            throw new Exception("支付失败！");
        }

        RepairUser ru = repairUserService.queryUserByOpenid(wpr.getOpenid());
        if (ru == null) {
            return CommonResult.fail("用户信息不合法，支付失败");
        }

        if (!ru.getId().equals(rr.getUserId())) {
            return CommonResult.fail("无法为其他订单支付");
        }

        //微信支付以分为单位
        int totalfee = (wpr.getTotalPrice().multiply(new BigDecimal(100))).intValue();
        Map<String, String> params = new HashMap<String, String>();
        params.put("attach", "报修系统");//附加数据，在查询API和支付通知中原样返回，可作为自定义参数使用。
        params.put("appid", wxOpenidConfig.getXappid());//微信分配的小程序ID
        params.put("mch_id", wxOpenidConfig.getShappid());//微信支付分配的商户号
        String nonceStr = WxUtil.getWxNonceStr();
        params.put("nonce_str", nonceStr);//随机字符串，长度要求在32位以内。推荐随机数生成算法
        params.put("body", "南交-报修系统");//商品简单描述，该字段请按照规范传递，具体请见参数规定
        params.put("out_trade_no", rr.getRecordNo());//商户系统内部订单号，要求32个字符内，只能是数字、大小写字母_-|*@ ，且在同一个商户号下唯一。详见商户订单号
        params.put("total_fee", String.valueOf(totalfee));//支付金额
        params.put("spbill_create_ip", wxOpenidConfig.getIpconfig());//支持IPV4和IPV6两种格式的IP地址。调用微信支付API的机器IP：服务器IP地址
        params.put("notify_url", wxOpenidConfig.getReturnUrl());//"https://chtech.ncjti.edu.cn/testingServer/repairTest/repair/api/repairRecord/returnPay");//"https://chtech.ncjti.edu.cn/campusMaintenance/repair-api/repair/api/repairRecord/returnPay");//异步接收微信支付结果通知的回调地址，通知url必须为外网可访问的url，不能携带参数。
        params.put("trade_type", "JSAPI");//取值如下：JSAPI，NATIVE，APP等，说明详见参数规定
        params.put("openid", wpr.getOpenid());//trade_type=JSAPI时（即公众号支付），此参数必传，此参数为微信用户在商户对应appid下的唯一标识
        String Sign = WxUtil.getSign(params, wxOpenidConfig.getShsecret());//参数 + 商户密钥
        params.put("sign", Sign);
        String retXml = WxUtil.getRequestXml(params);
        System.out.println(TimeExchange.getTime() + "微信支付提交的参数：" + retXml);

        String msg = HttpUtils.post("https://api.mch.weixin.qq.com/pay/unifiedorder", retXml);

        System.out.println(TimeExchange.getTime() + "微信返回的信息：" + msg);

        // 支付失败
        if (msg.indexOf("FAIL") > -1) {
            return CommonResult.fail("支付异常");
        }

        JaxbUtil requestBinder = new JaxbUtil(TongYiReturn.class, JaxbUtil.CollectionWrapper.class);
        TongYiReturn to = requestBinder.fromXml(msg);

        // 支付成功
        if (to.getReturn_code().equals("SUCCESS") && to.getResult_code().equals("SUCCESS")) {
            EndPay pay = new EndPay();
            pay.setAppId(wxOpenidConfig.getXappid());
            pay.setSignType("MD5");
            pay.setTimeStamp(System.currentTimeMillis() / 1000 + "");
            pay.setPrepay_id(to.getPrepay_id());
            pay.setNonceStr(nonceStr);
            Map<String, String> requestMap = new HashMap<String, String>();
            requestMap.put("appId", pay.getAppId());
            requestMap.put("timeStamp", pay.getTimeStamp());
            requestMap.put("nonceStr", pay.getNonceStr());
            requestMap.put("package", "prepay_id=" + pay.getPrepay_id());
            requestMap.put("signType", "MD5");
            pay.setPaySign(WxUtil.getSign(requestMap, wxOpenidConfig.getShsecret()));

            return CommonResult.ok(pay);
        }

        return CommonResult.ok();
    }

    /**
     * 支付成功后回调,推送消息给商家
     *
     * @param request  请求参数
     * @param response 响应参数
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    @PassToken
    public void returnPay(HttpServletRequest request, HttpServletResponse response) throws Exception {
        System.out.println(TimeExchange.getTime() + "进入支付回调====");
        try {
            BufferedReader reader = null;// BufferedReader 字符输入流
            reader = request.getReader();
            String line = "";
            String xmlString = null;
            StringBuilder inputString = new StringBuilder();
            while ((line = reader.readLine()) != null) {
                inputString.append(line);
            }
            xmlString = inputString.toString();
            request.getReader().close();
            JaxbUtil requestBinder = new JaxbUtil(PayResult.class, PayResult.class);
            PayResult result = requestBinder.fromXml(xmlString);// Xml到Java，用fromXML()方法
            System.out.println(TimeExchange.getTime() + "支付回调返回的参数：" + result);
            String recordNo = result.getOut_trade_no();
            System.out.println(TimeExchange.getTime() + "支付成功回调，维修单号：" + recordNo);
            RepairRecord rr = repairRecordService.queryRepairByRecordno(recordNo);
            // 支付成功
            if (result.getResult_code().equals("SUCCESS") && rr != null) {
                System.out.println(TimeExchange.getTime() + "支付成功回调，维修单号：" + recordNo);
                RepairPayRecord rpr = repairPayRecordService.getRepairPayByRecordId(rr.getId());
                if (rpr == null) {
                    // 保存支付信息
                    rpr = new RepairPayRecord();
                    rpr.setRecordId(rr.getId());
                    rpr.setUserId(rr.getUserId());
                    rpr.setPayNo(result.getNonce_str());
                    System.out.println("回调的金额：" + result.getTotal_fee());
                    rpr.setPayPrice(new BigDecimal(result.getTotal_fee()).divide(new BigDecimal("100")).setScale(2));
                    rpr.setIsSuccess(ePayStatu.Paysuccess.getValue());
                    rpr.setRemark("微信支付支付成功");
                    int insertRpr = repairPayRecordService.insertRepairPayRecord(rpr);
                    if (insertRpr <= 0) {
                        String returnMsg = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[MESSAGE]]></return_msg></xml>";
                        response.getWriter().write(returnMsg);// 发送消息返回给微信
                        throw new Exception("支付回调失败！");
                    }
                } else if (rpr.getIsSuccess() != ePayStatu.Paysuccess.getValue()) {
                    rpr.setPayNo(result.getNonce_str());
                    System.out.println("回调的金额：" + result.getTotal_fee());
                    rpr.setPayPrice(new BigDecimal(result.getTotal_fee()).divide(new BigDecimal("100")).setScale(2, BigDecimal.ROUND_HALF_UP));
                    rpr.setIsSuccess(ePayStatu.Paysuccess.getValue());
                    rpr.setRemark(rpr.getRemark() + "微信支付支付成功");
                    int updateRpr = repairPayRecordService.updateRepairPayRecord(rpr);
                    if (updateRpr <= 0) {
                        String returnMsg = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[MESSAGE]]></return_msg></xml>";
                        response.getWriter().write(returnMsg);// 发送消息返回给微信
                        throw new Exception("支付回调失败！");
                    }
                }

                rr.setMaintenanceState(eRecordStatu.Maintenance.getValue());

                int updateRecord = repairRecordService.updateRepairRecord(rr);
                if (updateRecord <= 0) {
                    String returnMsg = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[MESSAGE]]></return_msg></xml>";
                    response.getWriter().write(returnMsg);// 发送消息返回给微信
                    throw new Exception("支付回调失败！");
                }

                //添加跟踪记录
                RepairTrackRecord rtr = new RepairTrackRecord();
                rtr.setRecordId(rr.getId());
                rtr.setMaintenanceState(eRecordStatu.Maintenance.getValue());
                rtr.setContent("订单支付：" + rpr.getPayPrice().toString());
                rtr.setUserId(rr.getUserId());
                rtr.setUserZzstr("用户");
                int insertRtr = repairTrackRecordService.insertRepairTrackRecord(rtr);
                if (insertRtr <= 0) {
                    throw new Exception("支付回调失败！");
                }

                String returnMsg = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
                response.getWriter().write(returnMsg);// 发送成功消息返回给微信
            } else {
                System.out.println(TimeExchange.getTime() + "支付失败回调，维修单号：" + recordNo);
                String returnMsg = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[MESSAGE]]></return_msg></xml>";
                response.getWriter().write(returnMsg);// 发送消息返回给微信
                throw new Exception("支付回调失败！");
            }
        } catch (Exception e) {
            String returnMsg = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[MESSAGE]]></return_msg></xml>";
            response.getWriter().write(returnMsg);// 发送消息返回给微信
            System.out.println(TimeExchange.getTime() + "支付回调失败错误信息：" + e.getMessage());
            throw new Exception("支付回调失败！");
        }
    }

    /**
     * 提交报修订单
     *
     * @param rrr           报修订单数据
     * @param bindingResult 是否为空判断
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public CommonResult InsertRepairRecord(repairRecordRequest rrr, BindingResult bindingResult) throws Exception {

        System.out.println("提交订单" + JSON.toJSON(rrr));
        if (bindingResult.hasErrors()) {
            String st = paramUtils.getParamError(bindingResult);
            return CommonResult.fail(st);
        }

        //2023-10-07 A-jax 添加判断区域和校区ID是否一致
        if ((rrr.getAreaId().contains("墨轩湖校区") && rrr.getSchoolId().intValue() == eSchool.HJH.getValue()) || (rrr.getAreaId().contains("黄家湖校区") && rrr.getSchoolId().intValue() == eSchool.MXH.getValue())) {
            System.out.println("报修区域和校区不一致");
            return CommonResult.fail("报修区域和校区不一致");
        }

        //region
        /**
         * 2023-10-23 A-jax 添加重复报修判断
         */
        //报修时间 >= (当前时间 - 4) 的 并且状态不是 取消和关单的报修数据
        String dateStr = TimeExchange.TimeDesH(new Date(), 4);
        int count = repairRecordService.queryRepairRepeat(rrr.getUserId(), rrr.getBuildId(), rrr.getArticleId(), dateStr);
        if (count > 0) {
            return CommonResult.fail("短时间内请勿重复报修！");
        }
        //endregion

        RepairUser userInfo = repairUserService.getRepairById(rrr.getUserId());
        if (userInfo == null) {
            return CommonResult.fail("用户信息已失效，报修失败！");
        }


        //循环班次数据
        Integer isDuty = 0;
        try {
            Date nowDate = new Date();
            //Date nowDate = TimeExchange.StringToDate("2023-10-09 21:25:19","yyyy-MM-dd HH:mm:ss");
            String dateNow = new SimpleDateFormat("yyyy-MM-dd").format(nowDate);
            String dateHour = new SimpleDateFormat("HH:mm").format(nowDate);

            RepairRecord rr = new RepairRecord();
            rr.setAreaId(rrr.getAreaId());
            rr.setArticleId(rrr.getArticleId());
            rr.setSchoolId(rrr.getSchoolId());
            rr.setRecordNo(getUUIDBits(15));
            rr.setAddress(rrr.getAddress());
            rr.setDescription(rrr.getDescription());
            rr.setImage(StringUtils.join(rrr.getImages(), ','));
            rr.setVoice(rrr.getVoice());
            rr.setVoiceLength(rrr.getVoiceLength());
            rr.setUserId(rrr.getUserId());
            rr.setUserName(rrr.getUserName());
            rr.setUserPhone(rrr.getUserPhone());
            String college = userInfo.getCollege() == null || userInfo.getCollege().length() == 0 ? "" : "/" + userInfo.getCollege();
            String grade = userInfo.getGrade() == null || userInfo.getGrade().length() == 0 ? "" : "/" + userInfo.getGrade();
            String profession = userInfo.getProfession() == null || userInfo.getProfession().length() == 0 ? "" : "/" + userInfo.getProfession();
            rr.setUserClass(eIdentityType.stringOf(userInfo.getIdentityType()) + college + grade + profession);//2023-10-23 A-jax 添加年级记录操作
            rr.setReportTime(new Date());
            rr.setMaintenanceState(eRecordStatu.Dispatch.getValue());
            rr.setBuildId(rrr.getBuildId());
            rr.setIsCollaborate(0);
            rr.setVersion(0);

            //派单操作
            //根据类型和校区找到对应的维修师傅
            //获取到了多位师傅的话 单子随机派给满足条件的一位师傅
            //照接单数从小到大排 最小的优先接单（前提是满足条件）
            //值班或下班或周末有派给指定的维修师傅的单子就是值班单 并且不考核
            //其他无人接的单子，第二天（工作日）的时候自动派
            //派单表中需要记录接单时间  接单表中需要记录维修完成时间
            //楼栋条件 员工必填楼栋 满足楼栋条件才能派
            List<AutoDispatchUserVo> users = repairUserService.autoDispatchUser(rrr.getSchoolId(), dateNow, rrr.getArticleId(), rrr.getBuildId());

            String shiftStr = StringUtils.join(users.stream().map(AutoDispatchUserVo::getShiftId).collect(Collectors.toList()), ",");
            List<String> shifts = Arrays.asList(shiftStr.split(",")).stream().distinct().collect(Collectors.toList());
            RepairDispatchRecord rdr = null;
            //只获取不是值班 或下班后的排班数据
            List<RepairShiftSettings> shiftDatas = repairShiftSettingsService.getRepairsShiftIdByHour(shifts, dateHour);
            if (shiftDatas.size() <= 0) {
                System.out.println("提交订单1");
                isDuty = 1;
            }
            for (AutoDispatchUserVo user : users) {
                List<RepairShiftSettings> datas = shiftDatas.stream().filter(e -> ("," + user.getShiftId() + ",").contains(("," + e.getId() + ","))).collect(Collectors.toList());
                if (datas.size() <= 0) {
                    continue;
                }
                System.out.println("提交订单2");
                int acceptanceAssessTime = user.getAcceptanceTime();
                try {
                    System.out.println("提交订单3");
                    //2023-10-08 看是否是值班时间接单
                    if (datas.size() > 0) {
                        Optional<RepairShiftSettings> shiftData = datas.stream().filter(e -> nowDate.before(TimeExchange.StringToDate(dateNow + " " + e.getEndTime() + ":00", "yyyy-MM-dd HH:mm:ss"))).sorted(Comparator.comparing(RepairShiftSettings::getStartTime)).findFirst();
                        if (shiftData != null && shiftData.isPresent()) {
                            if (shiftData.get().getIsDuty().intValue() == 1) {
                                isDuty = 1;
                            }
                        }
                    }
                    System.out.println("提交订单4");
                    //下班之后或者值班接的单不考核 将报修工单中的is_duty改为1
                    Date workTime = TimeExchange.StringToDate(dateNow + " " + datas.get(0).getEndTime() + ":00", "yyyy-MM-dd HH:mm:ss");
                    if (workTime.before(nowDate)) {
                        System.out.println("提交订单5");
                        isDuty = 1;
                    }

                    if (isDuty == 0) {
                        System.out.println("提交订单6");
                        //在工作时间才去派单
                        List<timeVo> tvs = DelayedUtils.timeVos(datas);

                        //工作的时间是否够修完 临下班接的单不做延长
                        for (int i = 0; i < tvs.size(); i++) {
                            Date startWorkTime = TimeExchange.StringToDate(dateNow + " " + tvs.get(i).getStart() + ":00", "yyyy-MM-dd HH:mm:ss");
                            Date endWorkTime = TimeExchange.StringToDate(dateNow + " " + tvs.get(i).getEnd() + ":00", "yyyy-MM-dd HH:mm:ss");

                            //小于工作时间段的开始时间
                            if (nowDate.before(startWorkTime) || nowDate.equals(startWorkTime) && i == 0) {
                                //早上开始上班之前的单子
                                int minute = TimeExchange.getOffsetMinutes(nowDate, startWorkTime);
                                int workMinte = TimeExchange.getOffsetMinutes(nowDate, endWorkTime);
                                acceptanceAssessTime = acceptanceAssessTime + minute;
                                acceptanceAssessTime = DelayedUtils.addMinuteStart(tvs, endWorkTime, acceptanceAssessTime, nowDate, dateNow, workMinte, i, 1);
                                break;
                            } else if ((startWorkTime.before(nowDate) || startWorkTime.equals(nowDate)) && (nowDate.before(endWorkTime) || nowDate.equals(endWorkTime))) {
                                //工作时间段内的单子
                                int workMinte = TimeExchange.getOffsetMinutes(nowDate, endWorkTime);
                                acceptanceAssessTime = DelayedUtils.addMinuteStart(tvs, endWorkTime, acceptanceAssessTime, nowDate, dateNow, workMinte, i, 1);
                                break;

                            } else {
                                //非工作时间段的单子
                                Date nextStartWorkTime = TimeExchange.StringToDate(dateNow + " " + tvs.get(i + 1).getStart() + ":00", "yyyy-MM-dd HH:mm:ss");
                                if ((endWorkTime.before(nowDate) || endWorkTime.equals(nowDate)) && (nowDate.before(nextStartWorkTime) || nowDate.equals(nextStartWorkTime))) {
                                    Date nextEndWorkTime = TimeExchange.StringToDate(dateNow + " " + tvs.get(i + 1).getEnd() + ":00", "yyyy-MM-dd HH:mm:ss");
                                    int minute = TimeExchange.getOffsetMinutes(nowDate, nextStartWorkTime);
                                    int workMinte = TimeExchange.getOffsetMinutes(nowDate, nextEndWorkTime);
                                    acceptanceAssessTime = acceptanceAssessTime + minute;
                                    acceptanceAssessTime = DelayedUtils.addMinuteStart(tvs, nextEndWorkTime, acceptanceAssessTime, nowDate, dateNow, workMinte, i, 2);
                                    break;
                                }
                            }
                        }
                    }

                    rdr = new RepairDispatchRecord();
                    //创建派单记录
                    rdr.setAssignedTime(new Date());
                    rdr.setAcceptanceAssessTime(acceptanceAssessTime);
                    rdr.setOrderType(0);
                    rdr.setIsLoseEfficacy(0);
                    rdr.setUsersId(user.getId());
                    break;

                } catch (Exception e) {
                    System.out.println("提交订单异常" + e.getMessage());
                    throw new Exception("报修单提交失败！");
                }
            }

            rr.setIsDuty(isDuty);
            int result = repairRecordService.insertRepairRecord(rr);

            if (result <= 0) {
                throw new Exception("报修单提交失败！");
            }

            //两种情况：
            //1、工单已提交（没找到被派单师傅）
            //工单已生成，将尽快为您派单。
            //2、工单待接单（找到了被派单）
            //工单已交给系统，系统将催促师傅师尽快接单。
            if (rdr != null) {
                rdr.setRecordId(result);

                int dispatch = repairDispatchRecordService.insertRepairDispatchRecord(rdr);
                if (dispatch <= 0) {
                    throw new Exception("报修单提交失败！");
                }
                List<RepairSystemMessages> rsms = new ArrayList<>();
                RepairSystemMessages rsm = new RepairSystemMessages();
                rsm.setIsRead(0);
                rsm.setRecordId(result);
                rsm.setRecipientId(rdr.getUsersId());
                rsm.setContent("用户提交工单，请尽快处理！");
                rsms.add(rsm);
                RepairSystemMessages rsm1 = new RepairSystemMessages();
                rsm1.setIsRead(0);
                rsm1.setRecordId(result);
                rsm1.setRecipientId(rrr.getUserId());
                rsm1.setContent("工单已交给系统，系统将催促师傅师尽快接单！");
                rsms.add(rsm1);
                boolean insertRsm = repairSystemMessagesService.inserBatchSystemMessage(rsms);
                if (!insertRsm) {
                    throw new Exception("报修单提交失败！");
                }
            } else {
                RepairSystemMessages rsm = new RepairSystemMessages();
                rsm.setIsRead(0);
                rsm.setRecordId(result);
                rsm.setRecipientId(rrr.getUserId());
                rsm.setContent("工单已生成，将尽快为您派单！");
                int insertRsm = repairSystemMessagesService.insertRepairSystemMessages(rsm);
                if (insertRsm <= 0) {
                    throw new Exception("报修单提交失败！");
                }
            }

            //添加跟踪记录
            RepairTrackRecord rtr = new RepairTrackRecord();
            rtr.setRecordId(result);
            rtr.setMaintenanceState(eRecordStatu.Dispatch.getValue());
            rtr.setContent("提交订单");
            rtr.setUserId(rr.getUserId());
            rtr.setUserZzstr("用户");
            rtr.setImage(StringUtils.join(rrr.getImages(), ','));
            rtr.setVoice(rrr.getVoice());
            rtr.setVoiceLength(rrr.getVoiceLength());
            int insertRtr = repairTrackRecordService.insertRepairTrackRecord(rtr);
            if (insertRtr <= 0) {
                throw new Exception("报修单提交失败！");
            }

        } catch (Exception e) {
            System.out.println("提交订单异常2" + e.getMessage());
            throw new Exception("报修单提交失败！");
        }

        return CommonResult.ok("报修单提交成功");
    }

    /**
     * 根据数据ID更新报修数据
     *
     * @param rr            报修数据
     * @param bindingResult 是否为空判断
     * @return
     */
    @Override
    public CommonResult updateRepairRecordById(RepairRecord rr, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            String st = paramUtils.getParamError(bindingResult);
            return CommonResult.fail(st);
        }

        int result = repairRecordService.updateRepairRecord(rr);

        return result > 0 ? CommonResult.ok("修改成功") : CommonResult.fail("修改失败");
    }

    /**
     * 报修单分页数据查询
     *
     * @param currentPage 当前页数
     * @param pageCount   一页数据条数
     * @param name        查询名称
     * @return
     */
    @Override
    public CommonResult queryPageRepairRecords(int currentPage, int pageCount, String name) {
        PageUtils<RepairRecord> result = repairRecordService.queryPageRepairRecords(currentPage, pageCount, name);

        return CommonResult.ok(result);
    }

    /**
     * 根据数据ID删除报修数据
     *
     * @param id 数据ID
     * @return
     */
    @Override
    public CommonResult deleteRepairRecordById(int id) {
        RepairRecord data = repairRecordService.getRepairById(id);
        if (data == null) {
            return CommonResult.fail("当前数据不存在，删除失败！");
        }

        int result = repairRecordService.deleteRepairRecordById(id);

        return result > 0 ? CommonResult.ok("删除成功") : CommonResult.fail("删除失败");
    }

    /**
     * 文件上传
     *
     * @param file 上传的文件
     * @return
     * @throws Exception
     */
    @Override
    public CommonResult uploadFile(MultipartFile file) throws Exception {

        UploadFileVo result = new UploadFileVo();

        String name = StrUtils.getRandomName(file.getOriginalFilename());

        String user = "root"; //SFTP服务器用户名
        String password = "Best@123!@#"; // SFTP服务器密码
        String host = "172.16.20.92";  //  SFTP服务器地址
        int port = 22; // SFTP 服务器端口
        String remoteDirPath = "/usr/local/nginx/image"; // 远程目录路径
        //从MultipartFile对象中获取流
        InputStream inputStream = null;
        inputStream = file.getInputStream();
        //String downpath="/book/《Python爬虫开发与项目实战》.pdf";
        //String spath="C:/Users/F1339769/Desktop";
        JSch jsch = new JSch();
        Session session = null;
        ChannelSftp channelSftp = null;
        try {
            session = jsch.getSession(user, host, port);
            session.setPassword(password);
            session.setConfig("StrictHostKeyChecking", "no");
            session.connect(30000);
            System.out.println("连接成功");
            channelSftp = (ChannelSftp) session.openChannel("sftp");
            channelSftp.connect();
            // 创建远程目录
            String[] dirArr = remoteDirPath.split("/");
            String path = "";
            for (int i = 0; i < dirArr.length; i++) {
                path = path + "/" + dirArr[i];
                try {
                    channelSftp.cd(path);
                } catch (SftpException e) {
                    channelSftp.mkdir(path);
                    channelSftp.cd(path);
                }
            }
            //  文件上传到远程服务器上
            channelSftp.put(inputStream, name);
            //  从远程服务器上下载文件
            //channelSftp.get(downpath, spath);
        } catch (JSchException e) {
            e.printStackTrace();
        } finally {
            if (channelSftp != null) {
                channelSftp.disconnect();
            }
            if (session != null) {
                session.disconnect();
            }
            result.setResultUrl("https://chtech.ncjti.edu.cn/campusMaintenance/image/" + name);
        }
        return CommonResult.ok(result);
    }

    /**
     * 撤销报修数据
     *
     * @param id 数据ID
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public CommonResult revokeRepairRecordById(int id) throws Exception {
        RepairRecord data = repairRecordService.getRepairById(id);
        if (data == null) {
            return CommonResult.fail("当前数据不存在，撤销失败！");
        }

        if (data.getMaintenanceState() != eRecordStatu.Dispatch.getValue() && data.getMaintenanceState() != eRecordStatu.ToConfirmed.getValue()) {
            return CommonResult.fail("待接单或待确认才能进行撤销操作！");
        }

        try {
            List<Integer> userIds = new ArrayList<>();
            //获取该维修单的派单记录数据
            List<RepairDispatchRecord> rdrs = repairDispatchRecordService.queryDispatchByRecordId(data.getId());
            if (rdrs.size() > 0) {
                userIds = rdrs.stream().map(RepairDispatchRecord::getUsersId).collect(Collectors.toList());
                //将该维修单的派单记录和接单记录都置为无效
                RepairDispatchRecord rdr = new RepairDispatchRecord();
                int updateD = repairDispatchRecordService.updateDispatch(data.getId(), rdr.setIsLoseEfficacy(eDispatchResult.Expired.getValue()));
                if (updateD <= 0) {
                    throw new Exception("撤销失败！");
                }
                if (rdrs.get(0).getReceivingTime() != null) {
                    RepairReceiving rr = new RepairReceiving();
                    int updateR = repairReceivingService.updateReceiving(data.getId(), rr.setIsLoseEfficacy(eDispatchResult.Expired.getValue()));
                    if (updateR <= 0) {
                        throw new Exception("撤销失败！");
                    }
                }
            }

            if (userIds.size() > 0) {
                List<RepairSystemMessages> rsms = new ArrayList<>();
                for (int i = 0; i < userIds.size(); i++) {
                    RepairSystemMessages rsm = new RepairSystemMessages();
                    rsm.setIsRead(0);
                    rsm.setRecordId(data.getId());
                    rsm.setRecipientId(userIds.get(i));
                    rsm.setContent("工单已被用户取消！");
                    rsms.add(rsm);
                }
                boolean insertRsm = repairSystemMessagesService.inserBatchSystemMessage(rsms);
                if (!insertRsm) {
                    throw new Exception("撤销失败！");
                }
            }

            data.setMaintenanceState(eRecordStatu.Canceled.getValue());
            int result = repairRecordService.updateRepairRecord(data);
            if (result <= 0) {
                throw new Exception("撤销失败！");
            }

            //添加跟踪记录
            RepairTrackRecord rtr = new RepairTrackRecord();
            rtr.setRecordId(id);
            rtr.setMaintenanceState(eRecordStatu.Canceled.getValue());
            rtr.setContent("用户撤销");
            rtr.setUserId(data.getUserId());
            rtr.setUserZzstr("用户");
            int insertRtr = repairTrackRecordService.insertRepairTrackRecord(rtr);
            if (insertRtr <= 0) {
                throw new Exception("报修单提交失败！");
            }
        } catch (Exception e) {
            throw new Exception("撤销失败！");
        }

        return CommonResult.ok("撤销成功");
    }

    /**
     * 获取用户自己的报修分页数据
     * 还要处理一下订单超时状态
     *
     * @param currentPage 当前页数
     * @param pageCount   一页数据条数
     * @param userId      用户ID
     * @param state       状态
     *                    未完成：1
     *                    待确认：2
     *                    已完成：3
     * @return
     */
    @Override
    public CommonResult getRepairRecordsByUserId(int currentPage, int pageCount, int userId, int state) {
        PageUtils<MyRepairRecordVo> result = repairRecordService.queryMyRepairRecordList(currentPage, pageCount, state, userId);

        List<Integer> recordIds = result.getList().stream().map(MyRepairRecordVo::getId).collect(Collectors.toList());

        List<RepairConsumables> rcs = repairConsumablesService.getRepairsByRecordIds(recordIds);

        List<RepairEvaluate> evaluates = repairEvaluateService.getRepairByRecordIds(recordIds);

        for (MyRepairRecordVo r : result.getList()) {
            long count = evaluates.stream().filter(e -> e.getRecordId().equals(r.getId())).count();
            r.setState(eRecordStatu.stringOf(r.getStateId()));
            r.setImages(Arrays.asList(r.getImage().split(",")));
            List<RepairConsumables> datas = rcs.stream().filter(e -> e.getRecordId().equals(r.getId())).collect(Collectors.toList());
            r.setConsumables(datas);
            r.setEvaluate((count <= 0 && r.getStateId() == eRecordStatu.Finished.getValue()) ? 1 : 0);
        }
        return CommonResult.ok(result);
    }

    /**
     * 获取用户报修头部的维修数量
     *
     * @param userId 用户ID
     * @return
     */
    @Override
    public CommonResult getRepairRecordCountByUserId(int userId) {
        RepairRecordCountVo result = repairRecordService.getRepairRecordCount(userId);
        return CommonResult.ok(result);
    }

    /**
     * 个人工单
     * 获取维修师傅头部报修工单数量
     *
     * @param userId 用户ID
     * @return
     */
    @Override
    public CommonResult getTechnicianCountByUserId(int userId) {
        RepairUser user = repairUserService.getRepairById(userId);
        if (user == null) {
            return CommonResult.fail("用户信息失效，查询失败");
        }

        String dateNow = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        MaintenanceTechnicianVo result = repairRecordService.queryRepairTechnicianCount(userId, dateNow, user.getSchoolId());
        return CommonResult.ok(result);
    }

    /**
     * 个人工单
     * 获取维修师傅头部报修工单分页数据
     *
     * @param currentPage 当前页数
     * @param pageCount   一页数据条数
     * @param userId      用户ID
     * @param state       状态
     *                    待接单：1
     *                    维修中：2
     *                    已超时：3
     *                    待审核：4
     * @return
     */
    @Override
    public CommonResult getTechniciansByUserId(int currentPage, int pageCount, int userId, int state) {
        RepairUser user = repairUserService.getRepairById(userId);
        if (user == null) {
            return CommonResult.fail("用户信息失效，查询失败");
        }

        PageUtils<RepairTechnicianVo> result = null;
        String dateNow = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        switch (state) {
            case 1://待接单
                result = repairRecordService.queryPendingOrderList(currentPage, pageCount, userId, dateNow, user.getSchoolId());
                break;
            case 2://维修中
                result = repairRecordService.queryRepairOrderList(currentPage, pageCount, userId, dateNow, user.getSchoolId());
                break;
            case 3://已超时
                result = repairRecordService.queryTimeoutOrderList(currentPage, pageCount, userId, dateNow, user.getSchoolId());
                for (RepairTechnicianVo re : result.getList()) {
                    re.setState(eRecordStatu.stringOf(re.getMaintenanceState()));
                }
                break;
            case 4://待审核
                result = repairRecordService.queryExamineOrderList(currentPage, pageCount, userId, user.getSchoolId());
                break;
            default:
                break;
        }

        //2023-10-09 A-jax 添加获取耗材记录详情方法
        if (result.getList().size() > 0) {
            List<Integer> recordIds = result.getList().stream().map(RepairTechnicianVo::getId).collect(Collectors.toList());
            List<RepairConsumables> consumables = repairConsumablesService.getRepairsByRecordIds(recordIds);
            for (RepairTechnicianVo data : result.getList()) {
                List<RepairConsumables> datas = consumables.stream().filter(e -> e.getRecordId().equals(data.getId())).collect(Collectors.toList());
                data.setGoodsList(datas);
            }
        }

        return CommonResult.ok(result);
    }

    /**
     * 报修工单催单操作
     *
     * @param recordId 报修记录ID
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public CommonResult repairRecordReminder(int recordId) throws Exception {
        // 根据报修ID查找是否有派单数据 并且是有效的
        RepairRecord record = repairRecordService.getRepairById(recordId);
        if (record == null) {
            return CommonResult.fail("报修工单数据无效，催单失败");
        }

        if (record.getMaintenanceState() >= eRecordStatu.Finished.getValue()) {
            return CommonResult.fail("当前报修工单状态不支持催单操作");
        }

        List<String> cardnumber = new ArrayList<>();
        List<Integer> userIds = new ArrayList<>();

        // 有的话就发给被派单的维修师傅
        // 否则就发给郭师傅
        List<RepairCardNumberVo> cardNumbers = repairDispatchRecordService.queryRepairCardNumber(recordId);
        if (cardNumbers.size() <= 0) {
            //获取郭师傅的卡号把消息发给郭师傅
            List<Integer> uz = new ArrayList<>();
            uz.add(eUserZZ.Monitor.getValue());
            List<RepairUser> users = repairUserService.getRepairByUserZZ(uz, record.getSchoolId());
            cardnumber = users.stream().map(RepairUser::getCardNumber).collect(Collectors.toList());
            userIds = users.stream().map(RepairUser::getId).collect(Collectors.toList());
        } else {
            cardnumber = cardNumbers.stream().map(RepairCardNumberVo::getCardNumber).collect(Collectors.toList());
            userIds = cardNumbers.stream().map(RepairCardNumberVo::getUserId).collect(Collectors.toList());
        }

        if (cardnumber.size() <= 0) {
            return CommonResult.fail("当前工单无接收人，催单失败");
        }

        List<RepairSystemMessages> rsms = new ArrayList<>();
        for (int i = 0; i < userIds.size(); i++) {
            RepairSystemMessages rsm = new RepairSystemMessages();
            rsm.setIsRead(0);
            rsm.setRecordId(recordId);
            rsm.setRecipientId(userIds.get(i));
            rsm.setContent("您有工单用户催促，请尽快处理！");
            rsms.add(rsm);
        }

        try {
            boolean insertS = repairSystemMessagesService.inserBatchSystemMessage(rsms);
            if (!insertS) {
                throw new Exception("催单失败！");
            }

            String content = MessageFormat.format("【报修系统】维修师傅，你好，工单{0}用户催单，请及时处理，谢谢！", record.getRecordNo());
            CommonResult result = weiXiaoUtil.sendNotice(cardnumber, "报修工单催单", "催单", content, null);
            if (!result.getCode().equals("200")) {
                throw new Exception("催单失败！");
            }
        } catch (Exception e) {
            throw new Exception("催单失败！");
        }

        return CommonResult.ok("催单成功");
    }


    /**
     * 工单管理头部状态数量
     *
     * @param schoolId  校区ID
     * @param userhead  请求头
     * @param keyWord   关键字
     * @param startTime 起始时间
     * @param endTime   结束时间
     * @return
     */
    @Override
    public CommonResult queryManageCount(Integer schoolId, @RequestHeader("user_head") String userhead, String keyWord, String startTime, String endTime, String maintenanceName) {
        //String userID = AesUtils.decrypt(userhead);
        //RepairAdmin operateData = repairAdminService.getRepairById(userID);
        //if (operateData == null) {
        //    return CommonResult.fail("操作人信息不合法，无法获取工单数据！");
        //}
        //if (operateData.getIsSuper().equals(eIsSuper.Super.getValue())) {
        //    schoolId = null;
        //}

        if (startTime != null && endTime != null) {
            try {
                startTime = TimeExchange.getStartOfDayStr(TimeExchange.StringToDate(startTime, "yyyy-MM-dd"));
                endTime = TimeExchange.getEndOfDayStr(TimeExchange.StringToDate(endTime, "yyyy-MM-dd"));
            } catch (Exception e) {
            }
        }

        RepairManageCountVo result = repairRecordService.queryManageCount(schoolId, keyWord, startTime, endTime, maintenanceName);
        return CommonResult.ok(result);
    }

    /**
     * 工单管理报修分页数据
     *
     * @param currentPage 当前页数
     * @param pageCount   一页数据条数
     * @param userhead    请求头
     * @param state       状态
     *                    全部    0
     *                    待接单  1
     *                    维修中  2
     *                    待处理  3
     *                    待审核  4
     *                    已完成  5
     *                    已取消  6
     *                    已关单  7
     *                    已超时  8
     *                    转线下  9
     * @param keyWord     关键字
     * @param startTime   起始时间
     * @param endTime     结束时间
     * @param schoolId    校区ID
     * @return
     */
    @Override
    public CommonResult queryManagePage(int currentPage, int pageCount, @RequestHeader("user_head") String userhead, int state, String keyWord, String startTime, String endTime, Integer schoolId, String maintenanceName) {

        if (startTime != null && endTime != null) {
            try {
                startTime = TimeExchange.getStartOfDayStr(TimeExchange.StringToDate(startTime, "yyyy-MM-dd"));
                endTime = TimeExchange.getEndOfDayStr(TimeExchange.StringToDate(endTime, "yyyy-MM-dd"));
            } catch (Exception e) {
            }
        }

        // String userID = AesUtils.decrypt(userhead);
        // RepairAdmin operateData = repairAdminService.getRepairById(userID);
        // if (operateData == null) {
        //     return CommonResult.fail("操作人信息不合法，无法获取工单数据！");
        // }
        // if (operateData.getIsSuper().equals(eIsSuper.Super.getValue())) {
        //     schoolId = null;
        // }

        PageUtils<RepairRecordPageVo> result = null;
        /**
         * 出现延时按钮
         * 待接单 已完成 已取消 已关单 不需要出现延时按钮
         * 0 2 3 4 8 需要
         */
        String stateStr = null;
        switch (state) {
            case 0:
                result = repairRecordService.queryNotTimeout(currentPage, pageCount, stateStr, keyWord, startTime, endTime, schoolId, maintenanceName);
                for (RepairRecordPageVo r : result.getList()) {
                    if (r.getMaintenanceState() == 1) {
                        r.setState("待接单");
                        r.setClose(1);
                        if (r.getMaintenancerName() != null) {
                            r.setDelayed(1);
                        }
                    } else if (r.getMaintenanceState() == 2) {
                        r.setState("维修中");
                        r.setDelayed(1);
                    } else if (r.getMaintenanceState() == 3) {
                        r.setState("待处理");
                        r.setDelayed(1);
                    } else if (r.getMaintenanceState() == 4) {
                        r.setState("待确认");
                        r.setDelayed(1);
                    } else if (r.getMaintenanceState() == 5 || r.getMaintenanceState() == 6) {
                        r.setState(r.getMaintenanceState() == 5 ? "转单待审核" : "协作待审核");
                        r.setDelayed(1);
                    } else if (r.getMaintenanceState() == 7) {
                        r.setState("已完成");
                    } else if (r.getMaintenanceState() == 8) {
                        r.setState("已取消");
                    } else if (r.getMaintenanceState() == 9) {
                        r.setState("已关单");
                    }
                }
                break;
            case 1:
                stateStr = "=1)";
                result = repairRecordService.queryNotTimeout(currentPage, pageCount, stateStr, keyWord, startTime, endTime, schoolId, maintenanceName);
                for (RepairRecordPageVo r : result.getList()) {
                    //待接单才能关单
                    r.setState("待接单");
                    r.setClose(1);
                    if (r.getMaintenancerName() != null) {
                        r.setDelayed(1);
                    }
                }
                break;
            case 2:
                stateStr = "=2)";
                result = repairRecordService.queryNotTimeout(currentPage, pageCount, stateStr, keyWord, startTime, endTime, schoolId, maintenanceName);
                for (RepairRecordPageVo r : result.getList()) {
                    r.setState("维修中");
                    r.setDelayed(1);
                }
                break;
            case 3:
                stateStr = "=3)";
                result = repairRecordService.queryNotTimeout(currentPage, pageCount, stateStr, keyWord, startTime, endTime, schoolId, maintenanceName);
                for (RepairRecordPageVo r : result.getList()) {
                    r.setState("待处理");
                    r.setDelayed(1);
                }
                break;
            case 4:
                stateStr = "=5 or rr.maintenance_state = 6 or rr.maintenance_state = 11)";
                result = repairRecordService.queryNotTimeout(currentPage, pageCount, stateStr, keyWord, startTime, endTime, schoolId, maintenanceName);
                for (RepairRecordPageVo r : result.getList()) {
                    r.setState(r.getMaintenanceState() == 5 ? "转单待审核" : (r.getMaintenanceState() == 6 ? "协作待审核" : "转线下待审核"));
                    r.setDelayed(1);
                }
                break;
            case 5:
                stateStr = "=7)";
                result = repairRecordService.queryNotTimeout(currentPage, pageCount, stateStr, keyWord, startTime, endTime, schoolId, maintenanceName);
                for (RepairRecordPageVo r : result.getList()) {
                    r.setState("已完成");
                }
                break;
            case 6:
                stateStr = "=8)";
                result = repairRecordService.queryNotTimeout(currentPage, pageCount, stateStr, keyWord, startTime, endTime, schoolId, maintenanceName);
                for (RepairRecordPageVo r : result.getList()) {
                    r.setState("已取消");
                }
                break;
            case 7:
                stateStr = "=9)";
                result = repairRecordService.queryNotTimeout(currentPage, pageCount, stateStr, keyWord, startTime, endTime, schoolId, maintenanceName);
                for (RepairRecordPageVo r : result.getList()) {
                    r.setState("已关单");
                }
                break;
            case 8:
                PageUtils<RepairRecordTimeoutPageVo> timeoutResult = repairRecordService.queryTimeout(currentPage, pageCount, keyWord, startTime, endTime, schoolId, maintenanceName);
                List<RepairRecordPageVo> pages = new ArrayList<>();
                for (RepairRecordTimeoutPageVo r : timeoutResult.getList()) {
                    RepairRecordPageVo page = new RepairRecordPageVo();
                    page.setId(r.getId());
                    page.setRecordNo(r.getRecordNo());
                    page.setAreaName(r.getAreaName());
                    page.setUserId(r.getUserId());
                    page.setUserName(r.getUserName());
                    page.setUserPhone(r.getUserPhone());
                    page.setArticleName(r.getArticleName());
                    page.setDescription(r.getDescription());
                    page.setSchoolId(r.getSchoolId());
                    page.setMaintenanceState(r.getMaintenanceState());
                    List<String> timeoutStr = new ArrayList<>();
                    if (r.getTimeoutStr() != null) {
                        timeoutStr.add(r.getTimeoutStr());
                    }
                    if (r.getMaintenanceTimeout() != null) {
                        timeoutStr.add(r.getMaintenanceTimeout());
                    }
                    page.setState(StringUtils.join(timeoutStr, ','));
                    page.setReportTime(r.getReportTime());
                    page.setMaintenancerName(r.getMaintenancerName());
                    pages.add(page);
                }
                result = new PageUtils<RepairRecordPageVo>(pages, timeoutResult.getTotalCount(), timeoutResult.getPageSize(), timeoutResult.getCurrPage());
                break;
            case 9:
                stateStr = "=10)";
                result = repairRecordService.queryNotTimeout(currentPage, pageCount, stateStr, keyWord, startTime, endTime, schoolId, maintenanceName);
                for (RepairRecordPageVo r : result.getList()) {
                    r.setState("转线下");
                }
                break;
            default:
                break;
        }

        if (result.getList().size() > 0) {
            List<Integer> recordIds = result.getList().stream().map(RepairRecordPageVo::getId).collect(Collectors.toList());
            /**
             * 全部 待接单 待处理
             * 出现派单按钮
             * 没有派单记录的数据出现派单按钮
             */
            if (state == 0 || state == 1 || state == 3) {

                List<RepairDispatchRecord> disps = repairDispatchRecordService.queryRepairDispatch(recordIds);
                for (RepairRecordPageVo r : result.getList()) {
                    if (r.getMaintenanceState() == eRecordStatu.Dispatch.getValue()) {
                        long count = disps.stream().filter(e -> e.getRecordId().equals(r.getId())).count();
                        r.setDispatch(count > 0 ? 0 : 1);
                    }
                }
            }

            /**
             * 全部 待审核
             * 出现协作审核按钮
             * 出现转单审核按钮
             */
            if (state == 0 || state == 4) {
                List<CollaborateRecordVo> collaborates = repairCollaborateRecordService.queryRepairCollaborate(recordIds);
                for (RepairRecordPageVo r : result.getList()) {
                    if (r.getMaintenanceState() == eRecordStatu.Collaborate.getValue()) {
                        long collaborate = collaborates.stream().filter(e -> e.getRecordId() == r.getId() && e.getState().equals("协作")).count();
                        r.setCollaborate(collaborate > 0 ? 1 : 0);
                    } else if (r.getMaintenanceState() == eRecordStatu.Transfer.getValue()) {
                        long transfer = collaborates.stream().filter(e -> e.getRecordId() == r.getId() && e.getState().equals("转单")).count();
                        r.setTransfer(transfer > 0 ? 1 : 0);
                    } else if (r.getMaintenanceState() == eRecordStatu.OfflineReview.getValue()) {
                        long offline = collaborates.stream().filter(e -> e.getRecordId() == r.getId() && e.getState().equals("转线下")).count();
                        r.setOffline(offline > 0 ? 1 : 0);
                    }
                }
            }

            /**
             * 全部 待处理
             * 有耗材记录就显示改价按钮
             * 出现改价按钮
             */
            if (state == 0 || state == 3) {
                List<RepairConsumables> consumables = repairConsumablesService.getRepairsByRecordIds(recordIds);
                for (RepairRecordPageVo r : result.getList()) {
                    if (r.getMaintenanceState() == eRecordStatu.ToLogistics.getValue()
                            || r.getMaintenanceState() == eRecordStatu.Transfer.getValue()
                            || r.getMaintenanceState() == eRecordStatu.Collaborate.getValue()) {
                        long consumable = consumables.stream().filter(e -> e.getRecordId() == r.getId()).count();
                        r.setChangePrice(consumable > 0 ? 1 : 0);
                    }
                }
            }

            /**
             * 出现回复按钮
             * 有留言 且用户回复消息数大于后勤人员回复的
             */
            List<RepairLeaveMessage> messages = repairLeaveMessageService.getRepairsByRecordIds(recordIds);
            for (RepairRecordPageVo r : result.getList()) {
                List<RepairLeaveMessage> alls = messages.stream().filter(e -> e.getRecordId() == r.getId()).collect(Collectors.toList());
                List<RepairLeaveMessage> owns = alls.stream().filter(e -> e.getRecordId() == r.getId() && e.getSenderId().equals(r.getUserId())).collect(Collectors.toList());
                r.setReply(owns.size() > alls.size() / 2 ? 1 : 0);
            }

        }
        return CommonResult.ok(result);
    }

    /**
     * 待处理池报修分页数据
     *
     * @param currentPage 当前页数
     * @param pageCount   一页数据条数
     * @param schoolId    校区ID
     * @return
     */
    @Override
    public CommonResult queryPendingOrder(int currentPage, int pageCount, int schoolId) {
        PageUtils<pendingOrderVo> result = repairRecordService.queryPendingOrder(currentPage, pageCount, schoolId);
        return CommonResult.ok(result);
    }

    /**
     * 待处理池接单操作
     *
     * @param recordId 维修单ID
     * @param userId   操作人ID
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public CommonResult receiveOrders(int recordId, int userId) throws Exception {
        System.out.println("待处理池接单，报修单ID：" + recordId + "，用户ID：" + userId);

        try {
            Date nowDate = new Date();
            String dateHour = new SimpleDateFormat("HH:mm").format(new Date());

            //判断是否存在派单数据
            int dispatchCount = repairDispatchRecordService.queryDispatchCount(recordId);
            if (dispatchCount > 0) {
                return CommonResult.fail("该工单存在待处理人，抢单失败！");
            }

            //获取订单
            RepairRecord recordData = repairRecordService.getRepairById(recordId);
            if (recordData == null) {
                return CommonResult.fail("订单不存在，抢单失败！");
            }

            if (!recordData.getMaintenanceState().equals(eRecordStatu.Dispatch.getValue())) {
                return CommonResult.fail("订单状态错误，抢单失败！");
            }

            //获取维修师傅的用户信息 并获取当天的排班数据
            String dateNow = TimeExchange.DateToString(nowDate, "yyyy-MM-dd");
            UserDataVo result = repairUserService.queryUserData(userId, dateNow);

            if (result == null) {
                return CommonResult.fail("非法身份，抢单失败！");
            }

            if (result.getStartDate() == null || result.getShiftId() == null) {
                return CommonResult.fail("当天未排班，无法接单！");
            }

//            long count = Arrays.asList(result.getArticleId().split(",")).stream().filter(e -> e.equals(recordData.getArticleId().toString())).count();
//            if (count <= 0) {
//                return CommonResult.fail("无法维修该种类物品！");
//            }

            List<String> shifts = Arrays.asList(result.getShiftId().split(","));
            List<RepairShiftSettings> shiftDatas = repairShiftSettingsService.getRepairsByShiftIds(shifts, dateHour);
            if (shiftDatas.size() <= 0) {
                return CommonResult.fail("当天未排班，无法接单！");
            }

            //师傅自己抢单的时候不去限制抢单师傅的楼栋 以及报修种类

            Integer isDuty = recordData.getIsDuty();
            int acceptanceAssessTime = result.getAcceptanceAssessTime();
            int maintenanceAssessTime = result.getMaintenanceAssessTime();
            try {
                //2023-10-08 看是否是值班时间接单
                if (shiftDatas.size() > 0) {
                    Optional<RepairShiftSettings> shiftData = shiftDatas.stream().filter(e -> nowDate.before(TimeExchange.StringToDate(dateNow + " " + e.getEndTime() + ":00", "yyyy-MM-dd HH:mm:ss"))).sorted(Comparator.comparing(RepairShiftSettings::getStartTime)).findFirst();
                    if (shiftData != null && shiftData.isPresent()) {
                        if (shiftData.get().getIsDuty().intValue() == 1) {
                            isDuty = 1;
                        }
                    }
                }

                //下班之后或者值班接的单不考核 将报修工单中的is_duty改为1
                Date workTime = TimeExchange.StringToDate(dateNow + " " + shiftDatas.get(0).getEndTime() + ":00", "yyyy-MM-dd HH:mm:ss");
                if (workTime.before(nowDate)) {
                    isDuty = 1;
                }

                if (isDuty == 0) {
                    List<timeVo> tvs = DelayedUtils.timeVos(shiftDatas);

                    //工作的时间是否够修完 临下班接的单不做延长
                    for (int i = 0; i < tvs.size(); i++) {
                        Date startWorkTime = TimeExchange.StringToDate(dateNow + " " + tvs.get(i).getStart() + ":00", "yyyy-MM-dd HH:mm:ss");
                        Date endWorkTime = TimeExchange.StringToDate(dateNow + " " + tvs.get(i).getEnd() + ":00", "yyyy-MM-dd HH:mm:ss");

                        //小于工作时间段的开始时间
                        if (nowDate.before(startWorkTime) || nowDate.equals(startWorkTime) && i == 0) {
                            //早上开始上班之前的单子
                            int minute = TimeExchange.getOffsetMinutes(nowDate, startWorkTime);
                            int workMinte = TimeExchange.getOffsetMinutes(nowDate, endWorkTime);
                            acceptanceAssessTime = acceptanceAssessTime + minute;
                            acceptanceAssessTime = DelayedUtils.addMinuteStart(tvs, endWorkTime, acceptanceAssessTime, nowDate, dateNow, workMinte, i, 1);
                            maintenanceAssessTime = maintenanceAssessTime + minute;
                            maintenanceAssessTime = DelayedUtils.addMinuteStart(tvs, endWorkTime, maintenanceAssessTime, nowDate, dateNow, workMinte, i, 1);
                            break;
                        } else if ((startWorkTime.before(nowDate) || startWorkTime.equals(nowDate)) && (nowDate.before(endWorkTime) || nowDate.equals(endWorkTime))) {
                            //工作时间段内的单子
                            int workMinte = TimeExchange.getOffsetMinutes(nowDate, endWorkTime);
                            acceptanceAssessTime = DelayedUtils.addMinuteStart(tvs, endWorkTime, acceptanceAssessTime, nowDate, dateNow, workMinte, i, 1);
                            maintenanceAssessTime = DelayedUtils.addMinuteStart(tvs, endWorkTime, maintenanceAssessTime, nowDate, dateNow, workMinte, i, 1);
                            break;

                        } else {
                            //非工作时间段的单子
                            Date nextStartWorkTime = TimeExchange.StringToDate(dateNow + " " + tvs.get(i + 1).getStart() + ":00", "yyyy-MM-dd HH:mm:ss");
                            if ((endWorkTime.before(nowDate) || endWorkTime.equals(nowDate)) && (nowDate.before(nextStartWorkTime) || nowDate.equals(nextStartWorkTime))) {
                                Date nextEndWorkTime = TimeExchange.StringToDate(dateNow + " " + tvs.get(i + 1).getEnd() + ":00", "yyyy-MM-dd HH:mm:ss");
                                int minute = TimeExchange.getOffsetMinutes(nowDate, nextStartWorkTime);
                                int workMinte = TimeExchange.getOffsetMinutes(nowDate, nextEndWorkTime);
                                acceptanceAssessTime = acceptanceAssessTime + minute;
                                acceptanceAssessTime = DelayedUtils.addMinuteStart(tvs, nextEndWorkTime, acceptanceAssessTime, nowDate, dateNow, workMinte, i, 2);
                                maintenanceAssessTime = maintenanceAssessTime + minute;
                                maintenanceAssessTime = DelayedUtils.addMinuteStart(tvs, nextEndWorkTime, maintenanceAssessTime, nowDate, dateNow, workMinte, i, 2);
                                break;
                            }
                        }
                    }
                }
            } catch (Exception e) {
                System.out.println("待处理池接单延时，异常原因" + e.getMessage());
                throw new Exception("延时异常，抢单失败！");
            }

            //将工单状态更新为维修中
            recordData.setMaintenanceState(eRecordStatu.Maintenance.getValue());
            recordData.setMaintenancerId(String.valueOf(userId));
            recordData.setMaintenancerName(result.getUserName());
            recordData.setMaintenancerPhone(result.getUserPhone());
            recordData.setIsDuty(isDuty);
            int updateRecord = repairRecordService.updateRepairRecord(recordData);
            if (updateRecord <= 0) {
                System.out.println("待处理池接单更新报修单失败");
                throw new Exception("抢单失败！");
            }

            //创建派单记录
            RepairDispatchRecord rdr = new RepairDispatchRecord();
            rdr.setRecordId(recordId);
            rdr.setUsersId(userId);
            rdr.setAssignedTime(nowDate);
            rdr.setAcceptanceAssessTime(acceptanceAssessTime);
            rdr.setReceivingTime(nowDate);
            rdr.setOrderType(0);
            rdr.setIsLoseEfficacy(0);
            int dispatch = repairDispatchRecordService.insertRepairDispatchRecord(rdr);
            if (dispatch <= 0) {
                System.out.println("待处理池接单更新被派单表失败");
                throw new Exception("抢单失败！");
            }

            //创建接单记录
            RepairReceiving rr = new RepairReceiving();
            rr.setRecordId(recordId);
            rr.setDispatchId(rdr.getId());
            rr.setUserId(userId);
            rr.setReceivingTime(nowDate);
            rr.setMaintenanceAssessTime(maintenanceAssessTime);
            rr.setIsLoseEfficacy(0);
            int receive = repairReceivingService.insertRepairReceiving(rr);
            if (receive <= 0) {
                System.out.println("待处理池接单更新接单表失败");
                throw new Exception("抢单失败！");
            }

            //给用户发消息
            RepairSystemMessages rsm = new RepairSystemMessages();
            rsm.setIsRead(0);
            rsm.setRecordId(recordId);
            rsm.setRecipientId(recordData.getUserId());
            rsm.setContent("工单已被" + recordData.getMaintenancerName() + "接单，电话" + recordData.getMaintenancerPhone() + "，师傅会尽快上门维修。");
            int insertRsm = repairSystemMessagesService.insertRepairSystemMessages(rsm);
            if (insertRsm <= 0) {
                System.out.println("待处理池接单更新系统信息表失败");
                throw new Exception("抢单失败！");
            }

            //添加跟踪记录
            RepairTrackRecord rtr = new RepairTrackRecord();
            rtr.setRecordId(recordId);
            rtr.setMaintenanceState(eRecordStatu.Maintenance.getValue());
            rtr.setContent("已接单");
            rtr.setUserId(userId);
            rtr.setUserZzstr("维修师傅");
            int insertRtr = repairTrackRecordService.insertRepairTrackRecord(rtr);
            if (insertRtr <= 0) {
                System.out.println("待处理池接单更新进度表失败");
                throw new Exception("抢单失败！");
            }

        } catch (Exception e) {
            System.out.println("待处理池接单失败1，异常信息：" + e.getMessage());
            throw new Exception("抢单失败！");
        }

        return CommonResult.ok("工单已被您接单，请和用户确认上门维修时间");
    }

    /**
     * 维修师傅接单
     *
     * @param recordId 维修单记录ID
     * @param userId   操作用户ID
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public CommonResult receiveOwnOrders(int recordId, int userId) throws Exception {
        try {
            Date nowDate = new Date();
            String dateHour = new SimpleDateFormat("HH:mm").format(new Date());

            //获取订单
            RepairRecord recordData = repairRecordService.getRepairById(recordId);
            if (recordData == null) {
                return CommonResult.fail("订单不存在，接单失败！");
            }

            //协作单才能多个人接单 其他情况下只能一个人接单
            if (!recordData.getMaintenanceState().equals(eRecordStatu.Dispatch.getValue()) && recordData.getIsCollaborate() != 1) {
                return CommonResult.fail("订单状态错误，接单失败！");
            }

            //获取操作人的派单数据
            List<RepairDispatchRecord> rdrs = repairDispatchRecordService.queryDispatchByRecordId(recordId);
            RepairDispatchRecord dispatch = null;
            if (rdrs != null && rdrs.size() > 0) {
                Optional<RepairDispatchRecord> data = rdrs.stream().filter(e -> e.getUsersId().equals(userId)).findFirst();
                if (data != null && data.isPresent()) {
                    dispatch = data.get();
                } else {
                    return CommonResult.fail("该工单存在待处理人，接单失败");
                }
            }

            String dateNow = TimeExchange.DateToString(nowDate, "yyyy-MM-dd");
            UserDataVo result = repairUserService.queryUserData(userId, dateNow);

            if (result == null) {
                return CommonResult.fail("非法身份，接单失败！");
            }

            if (result.getStartDate() == null || result.getShiftId() == null) {
                return CommonResult.fail("当天未排班，无法接单！");
            }

            if (result.getArticleId() == null) {
                return CommonResult.fail("无法维修该种类物品！");
            }
            long count = Arrays.asList(result.getArticleId().split(",")).stream().filter(e -> e.equals(recordData.getArticleId().toString())).count();
            if (count <= 0) {
                return CommonResult.fail("无法维修该种类物品！");
            }

            List<String> shifts = Arrays.asList(result.getShiftId().split(","));
            List<RepairShiftSettings> shiftDatas = repairShiftSettingsService.getRepairsByShiftIds(shifts, dateHour);
            if (shiftDatas.size() <= 0) {
                return CommonResult.fail("当天未排班，无法接单！");
            }

            Integer isDuty = recordData.getIsDuty();
            //2023-10-08 看是否是值班时间接单
            if (shiftDatas.size() > 0) {
                Optional<RepairShiftSettings> shiftData = shiftDatas.stream().filter(e -> nowDate.before(TimeExchange.StringToDate(dateNow + " " + e.getEndTime() + ":00", "yyyy-MM-dd HH:mm:ss"))).sorted(Comparator.comparing(RepairShiftSettings::getStartTime)).findFirst();
                if (shiftData != null && shiftData.isPresent()) {
                    if (shiftData.get().getIsDuty().intValue() == 1) {
                        isDuty = 1;
                        recordData.setIsDuty(isDuty);
                    }
                }
            }

            int maintenanceAssessTime = result.getMaintenanceAssessTime();
            if (recordData.getIsDuty() != 1) {
                //派单的时候是值班单就按值班单算
                //如果不是值班时间派的 那这个单子就不是值班单
                //例如，A师傅上午09:00-12:00工作，下午13:00-16:00值班
                //有个单子10:00派给A师傅，下午14:00接单的时候这个单子依旧要进行考核；
                //即：最终是否是值班单以派单时机为准
                //最终如果是值班单就不用考虑维修考核时间延时的问题
                Date workTime = TimeExchange.StringToDate(dateNow + " " + shiftDatas.get(0).getEndTime() + ":00", "yyyy-MM-dd HH:mm:ss");
                if (workTime.before(nowDate)) {
                    maintenanceAssessTime = maintenanceAssessTime;
                }

                if (nowDate.before(workTime)) {
                    List<timeVo> tvs = DelayedUtils.timeVos(shiftDatas);

                    //工作的时间是否够修完 临下班接的单不做延长
                    for (int i = 0; i < tvs.size(); i++) {
                        Date startWorkTime = TimeExchange.StringToDate(dateNow + " " + tvs.get(i).getStart() + ":00", "yyyy-MM-dd HH:mm:ss");
                        Date endWorkTime = TimeExchange.StringToDate(dateNow + " " + tvs.get(i).getEnd() + ":00", "yyyy-MM-dd HH:mm:ss");

                        //小于工作时间段的开始时间
                        if (nowDate.before(startWorkTime) || nowDate.equals(startWorkTime) && i == 0) {
                            //早上开始上班之前的单子
                            int minute = TimeExchange.getOffsetMinutes(nowDate, startWorkTime);
                            int workMinte = TimeExchange.getOffsetMinutes(nowDate, endWorkTime);
                            maintenanceAssessTime = maintenanceAssessTime + minute;
                            maintenanceAssessTime = DelayedUtils.addMinuteStart(tvs, endWorkTime, maintenanceAssessTime, nowDate, dateNow, workMinte, i, 1);
                            break;
                        } else if ((startWorkTime.before(nowDate) || startWorkTime.equals(nowDate)) && (nowDate.before(endWorkTime) || nowDate.equals(endWorkTime))) {
                            //工作时间段内的单子
                            int workMinte = TimeExchange.getOffsetMinutes(nowDate, endWorkTime);
                            maintenanceAssessTime = DelayedUtils.addMinuteStart(tvs, endWorkTime, maintenanceAssessTime, nowDate, dateNow, workMinte, i, 1);
                            break;

                        } else {
                            //非工作时间段的单子
                            Date nextStartWorkTime = TimeExchange.StringToDate(dateNow + " " + tvs.get(i + 1).getStart() + ":00", "yyyy-MM-dd HH:mm:ss");
                            if ((endWorkTime.before(nowDate) || endWorkTime.equals(nowDate)) && (nowDate.before(nextStartWorkTime) || nowDate.equals(nextStartWorkTime))) {
                                Date nextEndWorkTime = TimeExchange.StringToDate(dateNow + " " + tvs.get(i + 1).getEnd() + ":00", "yyyy-MM-dd HH:mm:ss");
                                int minute = TimeExchange.getOffsetMinutes(nowDate, nextStartWorkTime);
                                int workMinte = TimeExchange.getOffsetMinutes(nowDate, nextEndWorkTime);
                                maintenanceAssessTime = maintenanceAssessTime + minute;
                                maintenanceAssessTime = DelayedUtils.addMinuteStart(tvs, nextEndWorkTime, maintenanceAssessTime, nowDate, dateNow, workMinte, i, 2);
                                break;
                            }
                        }
                    }
                }
            }

            //2023-09-30 如果是多人单 则需要都接单之后才能将单子转为维修状态 进行下一步操作
            if (rdrs.size() > 0) {
                long data = rdrs.stream().filter(e -> !e.getUsersId().equals(userId) && e.getReceivingTime() == null).count();
                if (data <= 0) {
                    //将工单状态更新为维修中
                    recordData.setMaintenanceState(eRecordStatu.Maintenance.getValue());
                    String mi = recordData.getMaintenancerId() == null ? String.valueOf(userId) : recordData.getMaintenancerId() + "," + String.valueOf(userId);
                    recordData.setMaintenancerId(mi);
                    recordData.setMaintenancerName(result.getUserName());
                    recordData.setMaintenancerPhone(result.getUserPhone());
                    recordData.setIsDuty(isDuty);

                    int updateRecord = repairRecordService.updateRepairRecord(recordData);
                    if (updateRecord <= 0) {
                        throw new Exception("接单失败！");
                    }
                }
            }

            int disId = 0;
            if (dispatch == null) {
                //更新派单记录
                dispatch = new RepairDispatchRecord();
                dispatch.setAssignedTime(new Date());
                dispatch.setAcceptanceAssessTime(result.getAcceptanceAssessTime());
                dispatch.setOrderType(0);
                dispatch.setIsLoseEfficacy(0);
                dispatch.setUsersId(userId);
                dispatch.setReceivingTime(nowDate);
                int insertDispatch = repairDispatchRecordService.insertRepairDispatchRecord(dispatch);
                if (insertDispatch <= 0) {
                    throw new Exception("接单失败！");
                }
                disId = insertDispatch;
            } else {
                //更新派单记录
                dispatch.setReceivingTime(nowDate);
                int updateDispatch = repairDispatchRecordService.updateRepairDispatchRecord(dispatch);
                if (updateDispatch <= 0) {
                    throw new Exception("接单失败！");
                }
                disId = dispatch.getId();
            }


            //创建接单记录
            RepairReceiving rr = new RepairReceiving();
            rr.setRecordId(recordId);
            rr.setDispatchId(disId);
            rr.setUserId(userId);
            rr.setReceivingTime(new Date());
            rr.setMaintenanceAssessTime(maintenanceAssessTime);
            rr.setIsLoseEfficacy(0);
            int receive = repairReceivingService.insertRepairReceiving(rr);
            if (receive <= 0) {
                throw new Exception("接单失败！");
            }

            RepairSystemMessages rsm = new RepairSystemMessages();
            rsm.setIsRead(0);
            rsm.setRecordId(recordId);
            rsm.setRecipientId(userId);
            rsm.setContent("工单已被" + result.getUserName() + "接单，电话" + result.getUserPhone() + "，师傅会尽快上门维修。");
            int insertRsm = repairSystemMessagesService.insertRepairSystemMessages(rsm);
            if (insertRsm <= 0) {
                throw new Exception("报修单提交失败！");
            }

            //添加跟踪记录
            RepairTrackRecord rtr = new RepairTrackRecord();
            rtr.setRecordId(recordId);
            rtr.setMaintenanceState(eRecordStatu.Maintenance.getValue());
            rtr.setContent("已接单");
            rtr.setUserId(userId);
            rtr.setUserZzstr("维修师傅");
            int insertRtr = repairTrackRecordService.insertRepairTrackRecord(rtr);
            if (insertRtr <= 0) {
                throw new Exception("接单失败");
            }
        } catch (Exception e) {
            throw new Exception("接单失败！");
        }

        return CommonResult.ok("工单已被您接单，请和用户确认上门维修时间");
    }

    /**
     * 派单
     * 派单没有转线下
     *
     * @param rsor          派单数据
     * @param bindingResult 是否为空判断
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public CommonResult receiveSendOrders(ReceiveSendOrdersRequest rsor, @RequestHeader("user_head") String userhead, BindingResult bindingResult) throws Exception {
        if (bindingResult.hasErrors()) {
            String st = paramUtils.getParamError(bindingResult);
            return CommonResult.fail(st);
        }

        RepairRecord rr = repairRecordService.getById(rsor.getRecordId());
        if (rr == null) {
            return CommonResult.fail("维修单数据失效，派单失败");
        }

        //派单没有转线下
        if (rr.getMaintenanceState() != eRecordStatu.Dispatch.getValue()) {
            return CommonResult.fail("维修单状态异常，派单失败");
        }

        //查询该订单是否存在被派单数据
        List<RepairDispatchRecord> repairDis = repairDispatchRecordService.queryDispatchByRecordId(rsor.getRecordId());
        if (repairDis != null && repairDis.size() > 0) {
            return CommonResult.fail("该订单存在待接单师傅，请勿再次派单");
        }

        Integer isDuty = rr.getIsDuty();
        Date nowDate = new Date();
        String dateHour = new SimpleDateFormat("HH:mm").format(new Date());
        String dateNow = new SimpleDateFormat("yyyy-MM-dd").format(new Date());

        try {
            List<String> shifts = Arrays.asList(rsor.getShiftId().split(",")).stream().distinct().collect(Collectors.toList());
            RepairDispatchRecord rdr = null;
            //只获取不是值班 或下班后的排班数据
            List<RepairShiftSettings> shiftDatas = repairShiftSettingsService.getRepairsShiftIdByHour(shifts, dateHour);
            List<RepairShiftSettings> datas = shiftDatas.stream().filter(e -> ("," + rsor.getShiftId() + ",").contains(("," + e.getId() + ","))).collect(Collectors.toList());
            if (datas.size() > 0) {
                int acceptanceAssessTime = rsor.getAcceptanceTime();
                try {

                    //2023-10-08 看是否是值班时间接单
                    if (shiftDatas.size() > 0) {
                        Optional<RepairShiftSettings> shiftData = datas.stream().filter(e -> nowDate.before(TimeExchange.StringToDate(dateNow + " " + e.getEndTime() + ":00", "yyyy-MM-dd HH:mm:ss"))).sorted(Comparator.comparing(RepairShiftSettings::getStartTime)).findFirst();
                        if (shiftData != null && shiftData.isPresent()) {
                            if (shiftData.get().getIsDuty().intValue() == 1) {
                                isDuty = 1;
                            }
                        }
                    }

                    //下班之后或者值班接的单不考核 将报修工单中的is_duty改为1
                    Date workTime = TimeExchange.StringToDate(dateNow + " " + datas.get(0).getEndTime() + ":00", "yyyy-MM-dd HH:mm:ss");
                    if (workTime.before(nowDate)) {
                        isDuty = 1;
                    }

                    if (isDuty == 0) {
                        //在工作时间才去派单
                        List<timeVo> tvs = DelayedUtils.timeVos(datas);

                        //工作的时间是否够修完 临下班接的单不做延长
                        for (int i = 0; i < tvs.size(); i++) {
                            Date startWorkTime = TimeExchange.StringToDate(dateNow + " " + tvs.get(i).getStart() + ":00", "yyyy-MM-dd HH:mm:ss");
                            Date endWorkTime = TimeExchange.StringToDate(dateNow + " " + tvs.get(i).getEnd() + ":00", "yyyy-MM-dd HH:mm:ss");

                            //小于工作时间段的开始时间
                            if (nowDate.before(startWorkTime) || nowDate.equals(startWorkTime) && i == 0) {
                                //早上开始上班之前的单子
                                int minute = TimeExchange.getOffsetMinutes(nowDate, startWorkTime);
                                int workMinte = TimeExchange.getOffsetMinutes(nowDate, endWorkTime);
                                acceptanceAssessTime = acceptanceAssessTime + minute;
                                acceptanceAssessTime = DelayedUtils.addMinuteStart(tvs, endWorkTime, acceptanceAssessTime, nowDate, dateNow, workMinte, i, 1);
                                break;
                            } else if ((startWorkTime.before(nowDate) || startWorkTime.equals(nowDate)) && (nowDate.before(endWorkTime) || nowDate.equals(endWorkTime))) {
                                //工作时间段内的单子
                                int workMinte = TimeExchange.getOffsetMinutes(nowDate, endWorkTime);
                                acceptanceAssessTime = DelayedUtils.addMinuteStart(tvs, endWorkTime, acceptanceAssessTime, nowDate, dateNow, workMinte, i, 1);
                                break;

                            } else {
                                //非工作时间段的单子
                                Date nextStartWorkTime = TimeExchange.StringToDate(dateNow + " " + tvs.get(i + 1).getStart() + ":00", "yyyy-MM-dd HH:mm:ss");
                                if ((endWorkTime.before(nowDate) || endWorkTime.equals(nowDate)) && (nowDate.before(nextStartWorkTime) || nowDate.equals(nextStartWorkTime))) {
                                    Date nextEndWorkTime = TimeExchange.StringToDate(dateNow + " " + tvs.get(i + 1).getEnd() + ":00", "yyyy-MM-dd HH:mm:ss");
                                    int minute = TimeExchange.getOffsetMinutes(nowDate, nextStartWorkTime);
                                    int workMinte = TimeExchange.getOffsetMinutes(nowDate, nextEndWorkTime);
                                    acceptanceAssessTime = acceptanceAssessTime + minute;
                                    acceptanceAssessTime = DelayedUtils.addMinuteStart(tvs, nextEndWorkTime, acceptanceAssessTime, nowDate, dateNow, workMinte, i, 2);
                                    break;
                                }
                            }
                        }
                    }

                    rdr = new RepairDispatchRecord();
                    //创建派单记录
                    rdr.setAssignedTime(new Date());
                    rdr.setAcceptanceAssessTime(acceptanceAssessTime);
                    rdr.setOrderType(eDispatchType.Send.getValue());
                    rdr.setIsLoseEfficacy(eDispatchResult.NotExpired.getValue());

                } catch (Exception e) {
                    throw new Exception("派单失败！");
                }
            } else {
                isDuty = 1;
                rdr = new RepairDispatchRecord();
                //创建派单记录
                rdr.setAssignedTime(new Date());
                rdr.setAcceptanceAssessTime(rsor.getAcceptanceTime());
                rdr.setOrderType(eDispatchType.Send.getValue());
                rdr.setIsLoseEfficacy(eDispatchResult.NotExpired.getValue());
            }

            rr.setIsDuty(isDuty);
            int result = repairRecordService.updateRepairRecord(rr);

            if (result <= 0) {
                throw new Exception("派单失败！");
            }

            if (rdr != null) {
                rdr.setRecordId(rr.getId());
                rdr.setUsersId(rsor.getId());
                int dispatch = repairDispatchRecordService.insertRepairDispatchRecord(rdr);
                if (dispatch <= 0) {
                    throw new Exception("派单失败！");
                }
            }

            String userID = AesUtils.decrypt(userhead);
            RepairAdmin operateData = repairAdminService.getRepairById(userID);
            if (operateData == null) {
                return CommonResult.fail("操作人信息不合法，无法进行回复！");
            }

            //操作人
            Integer senderId = 0;//超级管理员用ID为0
            if (!operateData.getIsSuper().equals(eIsSuper.Super.getValue())) {
                RepairUser user = repairUserService.getRepairByCardNumber(operateData.getCardNumber());
                if (user == null) {
                    return CommonResult.fail("管理端账号未与移动端账号绑定，无法进行审核！");
                }
                senderId = user.getId();
            }

            RepairSystemMessages rsm = new RepairSystemMessages();
            rsm.setIsRead(0);
            rsm.setRecordId(rsor.getRecordId());
            rsm.setRecipientId(rsor.getId());
            rsm.setContent("管理员为您派发工单，请尽快处理！");
            int insertRsm = repairSystemMessagesService.insertRepairSystemMessages(rsm);
            if (insertRsm <= 0) {
                throw new Exception("派单失败！");
            }

            //添加跟踪记录  派单不加跟踪记录
            RepairTrackRecord rtr = new RepairTrackRecord();
            rtr.setRecordId(rsor.getRecordId());
            rtr.setMaintenanceState(eRecordStatu.Dispatch.getValue());
            rtr.setContent("已派单");
            rtr.setUserId(senderId);
            rtr.setUserZzstr("管理员");
            int insertRtr = repairTrackRecordService.insertRepairTrackRecord(rtr);
            if (insertRtr <= 0) {
                throw new Exception("派单失败");
            }
        } catch (Exception e) {
            throw new Exception("派单失败");
        }
        return CommonResult.ok("派单成功");
    }

    /**
     * 协作员工集合下拉框
     *
     * @param recordId 报修记录ID
     * @return
     * @throws Exception
     */
    @Override
    public CommonResult dropDown(Integer recordId) {

        RepairRecord rr = repairRecordService.getRepairById(recordId);

        if (rr == null) {
            return CommonResult.fail("维修单无效，获取维修师傅数据失败");
        }

        Integer buildId = rr.getBuildId();
        Integer articleId = rr.getArticleId();
        Integer schoolId = rr.getSchoolId();

        //获取转单申请数据 拿到申请人数据，下来数据中不包含申请人
        RepairTransferRecord tdata = repairTransferRecordService.getRepairByRecordId(recordId);
        if (tdata == null) {
            return CommonResult.fail("转单申请无效，获取维修师傅数据失败");
        }

        List<AutoDispatchUserVo> autoDispatchUserVos = repairUserService.dropDown(buildId, articleId, schoolId, tdata.getUserId());

        ////将可以接单的师傅显示到协作下拉框中（员工状态 正常接单：1）
        // LambdaQueryWrapper<RepairUser> wrapper = new LambdaQueryWrapper<>();
        // wrapper.eq(RepairUser::getState, eUserStatu.Received.getValue())
        //         .like(RepairUser::getArticle_id,articleId);
        //
        // List<RepairUser> repairUsers = repairUserService.list(wrapper);

        return CommonResult.ok(autoDispatchUserVos);
    }

    /**
     * 转单审核
     *
     * @param tr            审核数据
     * @param bindingResult 是否为空判断
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public CommonResult transfer(transferRequest tr, @RequestHeader("user_head") String userhead, BindingResult bindingResult) throws Exception {
        if (bindingResult.hasErrors()) {
            String st = paramUtils.getParamError(bindingResult);
            return CommonResult.fail(st);
        }

        if (eApprovalStatu.Agree.getValue() == tr.getApproverStatu() && tr.getUserId() == null) {
            return CommonResult.fail("被派单师傅不能为空");
        }

        if (tr.getApproverStatu() == eApprovalStatu.Refuse.getValue() && tr.getRefuseRemark() == null) {
            return CommonResult.fail("驳回时，留言不能为空");
        }

        //获取转单审核数据
        RepairTransferRecord transferRecord = repairTransferRecordService.getById(tr.getId());
        if (transferRecord == null) {
            return CommonResult.fail("转单审核数据为空，审核失败");
        }

        if (transferRecord.getUserId().equals(tr.getUserId())) {
            return CommonResult.fail("无法将申请人作为被转单人员");
        }

        RepairRecord rr = repairRecordService.getRepairById(transferRecord.getRecordId());
        if (rr == null) {
            return CommonResult.fail("维修单数据不存在，审核失败");
        }

        if (rr.getMaintenanceState() != eRecordStatu.Transfer.getValue()) {
            return CommonResult.fail("维修单状态异常，审核失败");
        }

        String userID = AesUtils.decrypt(userhead);
        RepairAdmin operateData = repairAdminService.getRepairById(userID);
        if (operateData == null) {
            return CommonResult.fail("操作人信息不合法，无法进行审核！");
        }

        //发送人
        Integer senderId = 0;//超级管理员用ID为0
        if (!operateData.getIsSuper().equals(eIsSuper.Super.getValue())) {
            RepairUser user = repairUserService.getRepairByCardNumber(operateData.getCardNumber());
            if (user == null) {
                return CommonResult.fail("管理端账号未与移动端账号绑定，无法进行审核！");
            }
            senderId = user.getId();
        }

        try {
            //转单表中的审批操作人和审批状态
            transferRecord.setApproverId(senderId);
            transferRecord.setApprovalStatu(tr.getApproverStatu());
            int insertTransfer = repairTransferRecordService.updateRepairTransferRecord(transferRecord);
            if (insertTransfer <= 0) {
                throw new Exception("转单审核失败！");
            }

            if (eApprovalStatu.Agree.getValue() == tr.getApproverStatu()) {
                //被派单用户
                RepairUser repairUser = repairUserService.getById(tr.getUserId());
                if (repairUser == null) {
                    return CommonResult.fail("被派单师傅数据异常，审核失败");
                }

                //将原有的派单记录数据置为失效
                RepairDispatchRecord oldDispatchRecord = new RepairDispatchRecord();
                oldDispatchRecord.setIsLoseEfficacy(eDispatchResult.Expired.getValue());
                int updateDis = repairDispatchRecordService.updateDispatch(rr.getId(), oldDispatchRecord);

                //同意
                //添加派单记录
                RepairDispatchRecord repairDispatchRecord = new RepairDispatchRecord();
                repairDispatchRecord.setRecordId(rr.getId());
                repairDispatchRecord.setUsersId(tr.getUserId());
                repairDispatchRecord.setAssignedTime(new Date());
                repairDispatchRecord.setAcceptanceAssessTime(repairUser.getAcceptanceAssessTime());
                repairDispatchRecord.setOrderType(eDispatchType.Transfer.getValue());
                repairDispatchRecord.setIsLoseEfficacy(eDispatchResult.NotExpired.getValue());
                int insertDispatch = repairDispatchRecordService.insertRepairDispatchRecord(repairDispatchRecord);
                if (insertDispatch <= 0) {
                    throw new Exception("转单审核失败！");
                }

            }

            //同意的时候将维修表的状态改成派单中
            //拒绝的时候将维修表的状态改成转单前的
            rr.setMaintenanceState(eRecordStatu.Dispatch.getValue());
            int updateRecord = repairRecordService.updateRepairRecord(rr);
            if (updateRecord <= 0) {
                throw new Exception("转单审核失败！");
            }

            RepairSystemMessages rsm = new RepairSystemMessages();
            rsm.setIsRead(0);
            rsm.setRecordId(transferRecord.getRecordId());
            rsm.setRecipientId(transferRecord.getApproverId());
            rsm.setContent(eApprovalStatu.Agree.getValue() == tr.getApproverStatu() ? "您的审核工单已通过！" : "您的审核工单被驳回" + (tr.getRefuseRemark() == null ? "" : "：" + tr.getRefuseRemark()));
            int insertRsm = repairSystemMessagesService.insertRepairSystemMessages(rsm);
            if (insertRsm <= 0) {
                throw new Exception("转单审核失败！");
            }

            //添加跟踪记录
            RepairTrackRecord repairTrackRecord = new RepairTrackRecord();
            repairTrackRecord.setRecordId(rr.getId());
            repairTrackRecord.setContent("转单审核" + (tr.getRefuseRemark() == null ? "" : "-" + tr.getRefuseRemark()));
            repairTrackRecord.setMaintenanceState(rr.getMaintenanceState());
            repairTrackRecord.setUserId(senderId);
            repairTrackRecord.setUserZzstr("管理员");
            int insertTrack = repairTrackRecordService.insertRepairTrackRecord(repairTrackRecord);
            if (insertTrack <= 0) {
                throw new Exception("转单审核失败！");
            }

        } catch (Exception e) {
            throw new Exception("转单审核失败！");
        }

        return CommonResult.ok("转单审核成功");
    }

    /**
     * 转线下审核
     *
     * @param tr            审核数据
     * @param bindingResult 是否为空判断
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public CommonResult offline(transferRequest tr, @RequestHeader("user_head") String userhead, BindingResult bindingResult) throws Exception {
        if (bindingResult.hasErrors()) {
            String st = paramUtils.getParamError(bindingResult);
            return CommonResult.fail(st);
        }

        if (eApprovalStatu.Agree.getValue() == tr.getApproverStatu() && tr.getUserId() == null) {
            return CommonResult.fail("被转线下师傅不能为空");
        }

        if (tr.getApproverStatu() == eApprovalStatu.Refuse.getValue() && tr.getRefuseRemark() == null) {
            return CommonResult.fail("驳回时，留言不能为空");
        }

        //获取转单审核数据
        RepairOfflineRecord offlineRecord = repairOfflineRecordService.getById(tr.getId());
        if (offlineRecord == null) {
            return CommonResult.fail("转线下审核数据为空，审核失败");
        }

        if (offlineRecord.getUserId().equals(tr.getUserId())) {
            return CommonResult.fail("无法将申请人作为被转线下人员");
        }

        RepairRecord rr = repairRecordService.getRepairById(offlineRecord.getRecordId());
        if (rr == null) {
            return CommonResult.fail("维修单数据不存在，审核失败");
        }

        if (rr.getMaintenanceState() != eRecordStatu.OfflineReview.getValue()) {
            return CommonResult.fail("维修单状态异常，审核失败");
        }

        String userID = AesUtils.decrypt(userhead);
        RepairAdmin operateData = repairAdminService.getRepairById(userID);
        if (operateData == null) {
            return CommonResult.fail("操作人信息不合法，无法进行审核！");
        }

        //发送人
        Integer senderId = 0;//超级管理员用ID为0
        if (!operateData.getIsSuper().equals(eIsSuper.Super.getValue())) {
            RepairUser user = repairUserService.getRepairByCardNumber(operateData.getCardNumber());
            if (user == null) {
                return CommonResult.fail("管理端账号未与移动端账号绑定，无法进行审核！");
            }
            senderId = user.getId();
        }

        try {
            //转单表中的审批操作人和审批状态
            offlineRecord.setApproverId(senderId);
            offlineRecord.setApprovalStatu(tr.getApproverStatu());
            int insertOffline = repairOfflineRecordService.updateRepairOfflineRecord(offlineRecord);
            if (insertOffline <= 0) {
                throw new Exception("转线下审核失败！");
            }

            if (eApprovalStatu.Agree.getValue() == tr.getApproverStatu()) {
                //转线下用户
                RepairUser repairUser = repairUserService.getById(tr.getUserId());
                if (repairUser == null) {
                    return CommonResult.fail("被转线下师傅数据异常，审核失败");
                }

                //将原有的派单记录数据置为失效
                RepairDispatchRecord oldDispatchRecord = new RepairDispatchRecord();
                oldDispatchRecord.setIsLoseEfficacy(eDispatchResult.Expired.getValue());
                int updateDis = repairDispatchRecordService.updateDispatch(rr.getId(), oldDispatchRecord);

                //同意
                rr.setMaintenanceState(eRecordStatu.Offline.getValue());
                //将维修师傅也加进去
                rr.setMaintenancerName(repairUser.getUserName());
                rr.setMaintenancerPhone(repairUser.getUserPhone());
            } else {
                //转线下前的维修单记录状态
                rr.setMaintenanceState(offlineRecord.getOldRecord());
            }

            int updateRecord = repairRecordService.updateRepairRecord(rr);
            if (updateRecord <= 0) {
                throw new Exception("转线下审核失败！");
            }

            RepairSystemMessages rsm = new RepairSystemMessages();
            rsm.setIsRead(0);
            rsm.setRecordId(offlineRecord.getRecordId());
            rsm.setRecipientId(offlineRecord.getApproverId());
            rsm.setContent(eApprovalStatu.Agree.getValue() == tr.getApproverStatu() ? "您的审核工单已通过！" : "您的审核工单被驳回" + (tr.getRefuseRemark() == null ? "" : "：" + tr.getRefuseRemark()));
            int insertRsm = repairSystemMessagesService.insertRepairSystemMessages(rsm);
            if (insertRsm <= 0) {
                throw new Exception("转单审核失败！");
            }

            //添加跟踪记录
            RepairTrackRecord repairTrackRecord = new RepairTrackRecord();
            repairTrackRecord.setRecordId(rr.getId());
            repairTrackRecord.setContent("转线下审核" + (tr.getRefuseRemark() == null ? "" : "-" + tr.getRefuseRemark()));
            repairTrackRecord.setMaintenanceState(rr.getMaintenanceState());
            repairTrackRecord.setUserId(senderId);
            repairTrackRecord.setUserZzstr("管理员");
            int insertTrack = repairTrackRecordService.insertRepairTrackRecord(repairTrackRecord);
            if (insertTrack <= 0) {
                throw new Exception("转线下审核失败！");
            }

        } catch (Exception e) {
            throw new Exception("转线下审核失败！");
        }

        return CommonResult.ok("转线下审核成功");
    }

    /**
     * 获取协作审核数据
     *
     * @param recordId 报修记录ID
     * @return
     */
    @Override
    public CommonResult cooperationDetail(int recordId) {
        RepairRecord rr = repairRecordService.getRepairById(recordId);
        if (rr == null) {
            return CommonResult.fail("维修单数据不存在，获取协作审核失败");
        }

        if (rr.getMaintenanceState() != eRecordStatu.Collaborate.getValue()) {
            return CommonResult.fail("维修单状态异常，获取协作审核失败");
        }
        CollaborateDetailVo result = repairCollaborateRecordService.queryCollaborateDetail(recordId);
        if (result == null) {
            return CommonResult.fail("协作审核数据不存在，无法进行协作审核操作");
        }
        String[] cns = result.getCollaboratorName().split(",");
        List<CollaborateDataVo> cdvs = new ArrayList<>();
        for (int i = 0; i < cns.length; i++) {
            String[] cn = cns[i].split("-");
            CollaborateDataVo cdv = new CollaborateDataVo();
            cdv.setId(Integer.valueOf(cn[0]));
            cdv.setName(cn[1]);
            cdvs.add(cdv);
        }
        result.setCollaboratorDatas(cdvs);
        return CommonResult.ok(result);
    }

    /**
     * 获取转单审核数据
     *
     * @param recordId 报修记录ID
     * @return
     */
    @Override
    public CommonResult transferDetail(int recordId) {
        RepairRecord rr = repairRecordService.getRepairById(recordId);
        if (rr == null) {
            return CommonResult.fail("维修单数据不存在，获取转单审核失败");
        }

        if (rr.getMaintenanceState() != eRecordStatu.Transfer.getValue()) {
            return CommonResult.fail("维修单状态异常，获取转单审核失败");
        }

        TransferDetailVo result = repairTransferRecordService.queryTransferDetail(recordId);
        if (result == null) {
            return CommonResult.fail("转单审核数据不存在，无法进行转单审核操作");
        }

        return CommonResult.ok(result);
    }

    /**
     * 获取转线下审核数据
     *
     * @param recordId 报修记录ID
     * @return
     */
    @Override
    public CommonResult offlineDetail(int recordId) {
        RepairRecord rr = repairRecordService.getRepairById(recordId);
        if (rr == null) {
            return CommonResult.fail("维修单数据不存在，获取转线下审核失败");
        }

        if (rr.getMaintenanceState().intValue() != eRecordStatu.OfflineReview.getValue()) {
            return CommonResult.fail("维修单状态异常，获取转线下审核失败");
        }

        OfflineDetailVo result = repairOfflineRecordService.queryOfflineDetail(recordId);
        if (result == null) {
            return CommonResult.fail("转线下审核数据不存在，无法进行转线下审核操作");
        }

        return CommonResult.ok(result);
    }

    /**
     * 协作审核
     *
     * @param cor           协作审核数据
     * @param bindingResult 是否为空判断
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public CommonResult cooperationOrders(cooperationOrdersRequest cor, @RequestHeader("user_head") String userhead, BindingResult bindingResult) throws Exception {
        if (bindingResult.hasErrors()) {
            String st = paramUtils.getParamError(bindingResult);
            return CommonResult.fail(st);
        }

        //获取协作审核数据
        RepairCollaborateRecord collaborateRecord = repairCollaborateRecordService.getById(cor.getId());
        if (collaborateRecord == null) {
            return CommonResult.fail("协作审核数据为空，审核失败");
        }

        if (cor.getCollaborator().contains(collaborateRecord.getUserId())) {
            return CommonResult.fail("请勿将申请人选为协作人");
        }

        RepairRecord rr = repairRecordService.getRepairById(collaborateRecord.getRecordId());
        if (rr == null) {
            return CommonResult.fail("维修单数据不存在，审核失败");
        }

        if (rr.getMaintenanceState() != eRecordStatu.Collaborate.getValue()) {
            return CommonResult.fail("维修单状态异常，审核失败");
        }

        //批量获取人用户信息
        List<RepairUser> repairUsers = repairUserService.getRepairs(cor.getCollaborator());

        String userID = AesUtils.decrypt(userhead);
        RepairAdmin operateData = repairAdminService.getRepairById(userID);
        if (operateData == null) {
            return CommonResult.fail("操作人信息不合法，无法进行回复！");
        }

        //发送人
        Integer senderId = 0;//超级管理员用ID为0
        if (!operateData.getIsSuper().equals(eIsSuper.Super.getValue())) {
            RepairUser user = repairUserService.getRepairByCardNumber(operateData.getCardNumber());
            if (user == null) {
                return CommonResult.fail("管理端账号未与移动端账号绑定，无法进行审核！");
            }
            senderId = user.getId();
        }

        try {
            //转单表中的审批操作人和审批状态
            collaborateRecord.setApproverId(senderId);
            collaborateRecord.setApprovalStatu(cor.getApproverStatu());
            int updateCollaborate = repairCollaborateRecordService.updateRepairCollaborateRecord(collaborateRecord);
            if (updateCollaborate <= 0) {
                throw new Exception("协作审核失败！");
            }
            //同意 批量添加派单数据
            if (eApprovalStatu.Agree.getValue() == cor.getApproverStatu()) {
                List<RepairDispatchRecord> rdrs = new ArrayList<>();
                //获取维修数据
                for (RepairUser ru : repairUsers) {
                    RepairDispatchRecord rdr = new RepairDispatchRecord();
                    rdr.setRecordId(rr.getId());
                    rdr.setUsersId(ru.getId());
                    rdr.setAssignedTime(new Date());
                    rdr.setAcceptanceAssessTime(ru.getAcceptanceAssessTime());
                    rdr.setOrderType(eDispatchType.Cooperation.getValue());
                    rdr.setIsLoseEfficacy(eDispatchResult.NotExpired.getValue());
                    rdrs.add(rdr);
                }

                if (rdrs.size() > 0) {
                    boolean insertDispatch = repairDispatchRecordService.insertDispatchBatch(rdrs);
                    if (!insertDispatch) {
                        throw new Exception("协作审核失败！");
                    }
                }
            }

            //同意的时候将维修表的状态改成派单中
            //拒绝的时候将维修表的状态改成转单前的状态
            if (rr.getMaintenancerId() != null) {
                //说明有人接单了 那就把状态改为维修中
                rr.setMaintenanceState(eRecordStatu.Maintenance.getValue());
            } else {
                rr.setMaintenanceState(eRecordStatu.Dispatch.getValue());
            }

            int updateRecord = repairRecordService.updateRepairRecord(rr);
            if (updateRecord <= 0) {
                throw new Exception("协作审核失败！");
            }

            RepairSystemMessages rsm = new RepairSystemMessages();
            rsm.setIsRead(0);
            rsm.setRecordId(collaborateRecord.getRecordId());
            rsm.setRecipientId(collaborateRecord.getApproverId());
            rsm.setContent(eApprovalStatu.Agree.getValue() == cor.getApproverStatu() ? "您的审核工单已通过！" : "您的审核工单被驳回");
            int insertRsm = repairSystemMessagesService.insertRepairSystemMessages(rsm);
            if (insertRsm <= 0) {
                throw new Exception("协作审核失败！");
            }

            //添加跟踪记录
            RepairTrackRecord rtr = new RepairTrackRecord();
            rtr.setRecordId(collaborateRecord.getRecordId());
            rtr.setMaintenanceState(rr.getMaintenanceState());
            rtr.setContent("协作审批");
            rtr.setUserId(senderId);
            rtr.setUserZzstr("管理员");
            int insertRtr = repairTrackRecordService.insertRepairTrackRecord(rtr);
            if (insertRtr <= 0) {
                throw new Exception("协作审核失败！");
            }
        } catch (Exception e) {
            throw new Exception("协作审核失败！");
        }

        return CommonResult.ok("协作审核成功");
    }

    /**
     * 详情展示
     *
     * @param recordId 维修记录ID
     * @return
     * @throws Exception
     */
    @Override
    public CommonResult details(int recordId) throws Exception {
        //工单信息数据
        DetailsVo rr = repairRecordService.queryDetailData(recordId);
        if (rr == null) {
            return CommonResult.fail("工单信息失效，获取详情数据失败");
        }

        List<TrackDetailsVo> tracks = repairTrackRecordService.queryDetailData(recordId);
        List<RepairConsumables> rcs = repairConsumablesService.getRepairsByRecordId(recordId);
        if (tracks.size() > 0) {
            rr.setTracks(tracks);
        }
        if (rcs.size() > 0) {
            rr.setConsumables(rcs);
        }

        return CommonResult.ok(rr);
    }


    /**
     * 改价耗材记录显示
     *
     * @param recordId 维修记录ID
     * @return
     * @throws Exception
     */
    @Override
    public CommonResult alterPriceShow(int recordId) {
        if (ObjectUtils.isEmpty(recordId)) {
            return CommonResult.fail("显示失败");
        }
        LambdaQueryWrapper<RepairConsumables> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(RepairConsumables::getRecordId, recordId);

        List<RepairConsumables> repairConsumablesList = repairConsumablesService.list(wrapper);

        if (ObjectUtils.isEmpty(repairConsumablesList) || repairConsumablesList.size() <= 0) {
            return CommonResult.fail("显示失败");
        }

        List<AlterPriceShowVo> vos = new ArrayList<>();

        repairConsumablesList.forEach(rc -> {
            Integer articleId = rc.getArticleId();
            RepairArticleType articleType = repairArticleTypeService.getById(articleId);
            AlterPriceShowVo alterPriceShowVo = new AlterPriceShowVo();
            if (ObjectUtils.isNotEmpty(articleType)) {
                alterPriceShowVo.setArticleName(articleType.getName());
            }
            alterPriceShowVo.setRepairConsumables(rc);
            vos.add(alterPriceShowVo);
        });

        return CommonResult.ok(vos);
    }

    /**
     * 改价物品种类下拉框
     *
     * @param schoolId 校区ID
     * @return
     * @throws Exception
     */
    @Override
    public CommonResult alterPriceGoodsType(int schoolId) throws Exception {
        if (ObjectUtils.isEmpty(schoolId)) {
            return CommonResult.fail("显示失败");
        }

        LambdaQueryWrapper<RepairArticleType> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(RepairArticleType::getId, RepairArticleType::getName)
                .eq(RepairArticleType::getSchoolId, schoolId)
                .eq(RepairArticleType::getParentId, 0);

        List<RepairArticleType> list = repairArticleTypeService.list(wrapper);
        return CommonResult.ok(list);

    }

    /**
     * 改价耗材名称下拉
     *
     * @param schoolId  校区ID
     * @param articleId 报修物品ID
     * @return
     * @throws Exception
     */
    @Override
    public CommonResult alterPriceGoodsName(int schoolId, int articleId) {
        if (ObjectUtils.isEmpty(schoolId) || ObjectUtils.isEmpty(articleId)) {
            return CommonResult.fail("显示失败");
        }


        LambdaQueryWrapper<RepairArticleType> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(RepairArticleType::getId)
                .eq(RepairArticleType::getParentId, articleId);
        List<RepairArticleType> list = repairArticleTypeService.list(wrapper);
        if (ObjectUtils.isEmpty(list) || list.size() <= 0) {
            return CommonResult.fail("显示失败");
        }

        ArrayList<String> strings = new ArrayList<>();
        strings.add(articleId + "");

        list.forEach(repairArticleType -> {
            String id = repairArticleType.getId() + "";
            strings.add(id);
        });

        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < strings.size(); i++) {
            sb.append("FIND_IN_SET(" + strings.get(i) + ",article_id)");
            if (i + 1 != strings.size()) {
                sb.append(" or ");
            }
        }

        String sss = sb.toString();

        List<RepairArticleConsumeVo> consumeResult = repairConsumeService.queryArticleConsumesName(sss, schoolId);


        return CommonResult.ok(consumeResult);
    }

    /**
     * 改价操作
     *
     * @param apr           改价耗材数据
     * @param bindingResult 是否为空判断
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public CommonResult alterPrice(AlterPriceRequest apr, @RequestHeader("user_head") String userhead, BindingResult bindingResult) throws Exception {
        System.out.println("改价操作" + JSON.toJSON(apr));

        if (bindingResult.hasErrors()) {
            String st = paramUtils.getParamError(bindingResult);
            return CommonResult.fail(st);
        }
        try {


            Integer recordId = apr.getRecordId();

            List<Integer> ids = apr.getIds();

            List<RepairConsumables> repairConsumables = apr.getRepairConsumablesList();
            //当前报修记录
            LambdaQueryWrapper<RepairConsumables> wrapper = new LambdaQueryWrapper<>();
            wrapper.select(RepairConsumables::getId)
                    .eq(RepairConsumables::getRecordId, recordId);
            List<RepairConsumables> list = repairConsumablesService.list(wrapper);
            if (ObjectUtils.isEmpty(list) || list.size() <= 0) {
                return CommonResult.fail("改价失败");
            }

            ArrayList<Integer> integers = new ArrayList<>();
            list.forEach(rc -> {
                Integer id = rc.getId();
                integers.add(id);
            });

            String userID = AesUtils.decrypt(userhead);
            RepairAdmin operateData = repairAdminService.getRepairById(userID);
            if (operateData == null) {
                return CommonResult.fail("操作人信息不合法，无法进行改价！");
            }

            //        当为空时，维修是不要耗材的
            if (ObjectUtils.isEmpty(repairConsumables)) {
                boolean remove = repairConsumablesService.removeByIds(integers);
                if (!remove) {
                    throw new Exception("改价失败");
                }
            } else {
                //            将参数有主键的则修改，没有的则添加
                for (RepairConsumables repairConsumable : repairConsumables) {
                    Integer id = repairConsumable.getId();
                    if (ObjectUtils.isEmpty(id)) {
                        repairConsumable.setChangeUser(operateData.getUsername());
                        boolean save = repairConsumablesService.save(repairConsumable);
                        if (!save) {
                            throw new Exception("改价失败");
                        }
                    } else {
                        repairConsumable.setChangeUser(operateData.getUsername());
                        boolean update = repairConsumablesService.updateById(repairConsumable);
                        if (!update) {
                            throw new Exception("改价失败");
                        }
                    }
                }
                for (Integer integer : integers) {
                    if (!(ids.contains(integer))) {
                        boolean b = repairConsumablesService.removeById(integer);
                        if (!b) {
                            throw new Exception("改价失败");
                        }
                    }
                }
            }
            //        修改维修表总价
            RepairRecord repairRecord = repairRecordService.getById(recordId);
            if (ObjectUtils.isEmpty(repairRecord)) {
                return CommonResult.fail("改价失败");
            }

            //发送人
            Integer senderId = 0;//超级管理员用ID为0
            if (!operateData.getIsSuper().equals(eIsSuper.Super.getValue())) {
                RepairUser user = repairUserService.getRepairByCardNumber(operateData.getCardNumber());
                if (user == null) {
                    return CommonResult.fail("管理端账号未与移动端账号绑定，无法进行改价！");
                }
                senderId = user.getId();
            }

            repairRecord.setMaintenanceState(eRecordStatu.ToConfirmed.getValue());
            repairRecord.setPrice(apr.getTotalPrice());
            boolean update = repairRecordService.updateById(repairRecord);

            //追踪记录表
            RepairTrackRecord repairTrackRecord = new RepairTrackRecord();
            repairTrackRecord.setRecordId(recordId);
            repairTrackRecord.setMaintenanceState(eRecordStatu.ToConfirmed.getValue());
            repairTrackRecord.setContent("改价");
            repairTrackRecord.setUserId(senderId);
            repairTrackRecord.setUserZzstr("管理员");
            boolean save = repairTrackRecordService.save(repairTrackRecord);

            if (!(update && save)) {
                throw new Exception("改价失败");
            }

        } catch (Exception e) {
            throw new Exception("改价失败");
        }
        return CommonResult.ok("改价成功");
    }

    /**
     * 延时操作
     *
     * @param dr            延时数据
     * @param bindingResult 是否为空判断
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public CommonResult delayed(DelayedRequest dr, BindingResult bindingResult) throws Exception {
        if (bindingResult.hasErrors()) {
            String st = paramUtils.getParamError(bindingResult);
            return CommonResult.fail(st);
        }

        try {

            //接单考核时间大于0 去修改派单记录表的数据
            if (dr.getReceiving() > 0) {
                List<RepairDispatchRecord> list = repairDispatchRecordService.queryDispatchByRecordId(dr.getRecordId());
                if (list.size() > 0) {
                    for (RepairDispatchRecord data : list) {
                        data.setAcceptanceAssessTime(data.getAcceptanceAssessTime() + dr.getReceiving());
                    }

                    boolean updateBatch = repairDispatchRecordService.updateDispatchBatch(list);
                    if (!updateBatch) {
                        throw new Exception("延时失败");
                    }
                }
            }

            //接单记录
            if (dr.getMaintain() > 0) {
                List<RepairReceiving> list = repairReceivingService.queryReceivingByRecordId(dr.getRecordId());
                if (list.size() > 0) {

                    for (RepairReceiving data : list) {
                        data.setMaintenanceAssessTime(data.getMaintenanceAssessTime() + dr.getMaintain());
                    }

                    boolean updateBatch = repairReceivingService.updateReceivingBatch(list);
                    if (!updateBatch) {
                        throw new Exception("延时失败");
                    }
                }

            }

            // //追踪记录表
            // RepairTrackRecord repairTrackRecord = new RepairTrackRecord();
            // repairTrackRecord.setRecordId(dr.getRecordId());
            // repairTrackRecord.setContent("延时");
            // boolean save = repairTrackRecordService.save(repairTrackRecord);
            //
            // if (!save) {
            //     throw new Exception("延时失败");
            // }
        } catch (Exception e) {
            throw new Exception("延时失败");
        }

        return CommonResult.ok("延时成功");
    }

    /**
     * 回复
     * 在订单是待确认状态下 用户能发送信息给后勤 此时订单状态改为待处理
     * 后勤回复信息给用户   此时订单状态为待确认
     * 如果是管理端回复的则记录
     *
     * @param rr            回复数据
     * @param bindingResult 是否为空判断
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public CommonResult revert(@RequestBody RevertRequest rr, @RequestHeader("user_head") String userhead, BindingResult bindingResult) throws Exception {
        if (bindingResult.hasErrors()) {
            String st = paramUtils.getParamError(bindingResult);
            return CommonResult.fail(st);
        }

        try {
            String userID = AesUtils.decrypt(userhead);
            RepairAdmin operateData = repairAdminService.getRepairById(userID);
            if (operateData == null) {
                return CommonResult.fail("操作人信息不合法，无法进行回复！");
            }

            //发送人
            Integer senderId = 0;//超级管理员用ID为0
            if (!operateData.getIsSuper().equals(eIsSuper.Super.getValue())) {
                RepairUser user = repairUserService.getRepairByCardNumber(operateData.getCardNumber());
                if (user == null) {
                    return CommonResult.fail("管理端账号未与移动端账号绑定，无法进行回复！");
                }
                senderId = user.getId();
            }

            RepairRecord data = repairRecordService.getRepairById(rr.getRecordId());
            if (data == null) {
                return CommonResult.fail("报修单已失效，无法进行回复");
            }

            if (data.getMaintenanceState() != eRecordStatu.ToLogistics.getValue()) {
                return CommonResult.fail("待处理维修单才能进行回复操作");
            }

            //接收人
            Integer recipientId = data.getUserId();

            //将工单数据状态改为待确认
            data.setMaintenanceState(eRecordStatu.ToConfirmed.getValue());
            int result = repairRecordService.updateRepairRecord(data);
            if (result <= 0) {
                throw new Exception("回复失败！");
            }

            //内容
            String content = rr.getContent();

            RepairLeaveMessage repairLeaveMessage = new RepairLeaveMessage();
            repairLeaveMessage.setRecordId(data.getId());
            repairLeaveMessage.setRecipientId(recipientId);
            repairLeaveMessage.setSenderId(senderId);
            repairLeaveMessage.setContent(content);

            boolean mSave = repairLeaveMessageService.save(repairLeaveMessage);

            if (!mSave) {
                throw new Exception("回复失败！");
            }

            //        追踪记录表
            RepairTrackRecord repairTrackRecord = new RepairTrackRecord();
            repairTrackRecord.setMaintenanceState(eRecordStatu.ToConfirmed.getValue());
            repairTrackRecord.setRecordId(data.getId());
            repairTrackRecord.setContent("回复：" + rr.getContent());
            repairTrackRecord.setUserId(senderId);
            repairTrackRecord.setUserZzstr("管理员");

            boolean save = repairTrackRecordService.save(repairTrackRecord);

            if (!save) {
                throw new Exception("回复失败！");
            }

        } catch (Exception e) {
            throw new Exception("回复失败！");
        }

        return CommonResult.ok("回复成功");
    }

    /**
     * 工单管理数据报表导出
     *
     * @param response  响应流
     * @param keyWord   关键字
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @param schoolId  校区ID
     * @param state     状态
     * @param userhead  请求头
     * @throws Exception
     */
    @Override
    public void reportExport(HttpServletResponse response, String keyWord, String startTime, String endTime, Integer schoolId, Integer state, String userhead) {

        if (startTime != null && endTime != null) {
            try {
                startTime = TimeExchange.getStartOfDayStr(TimeExchange.StringToDate(startTime, "yyyy-MM-dd"));
                endTime = TimeExchange.getEndOfDayStr(TimeExchange.StringToDate(endTime, "yyyy-MM-dd"));
            } catch (Exception e) {
            }
        }

        // 状态为0是查全部，为1查派单中。为2查维修中，3查转后勤，4是查转单待审核，协作待审核，5是查已完成，6是查已取消，7是查已关单，8是查维修中值班单

        // String userID = AesUtils.decrypt(userhead);
        // RepairAdmin operateData = repairAdminService.getRepairById(userID);
        // if (operateData == null) {
        //       return CommonResult.fail("操作人信息不合法，无法获取工单数据！");
        //     return;
        // }
        // if (operateData.getIsSuper().equals(eIsSuper.Super.getValue())) {
        //     schoolId = null;
        // }


        List<ReportExportVo> result = null;


        String stateStr = null;
        switch (state) {
            case 0:
                result = repairRecordService.queryNotTimeoutReportExport(stateStr, keyWord, startTime, endTime, schoolId);
                for (ReportExportVo r : result) {
                    if (r.getMaintenanceState() == 1) {
                        r.setState("待接单");
                    } else if (r.getMaintenanceState() == 2) {
                        r.setState("维修中");
                    } else if (r.getMaintenanceState() == 3) {
                        r.setState("待处理");
                    } else if (r.getMaintenanceState() == 5 || r.getMaintenanceState() == 6) {
                        r.setState("待审核");
                    } else if (r.getMaintenanceState() == 7) {
                        r.setState("已完成");
                    } else if (r.getMaintenanceState() == 8) {
                        r.setState("已取消");
                    } else if (r.getMaintenanceState() == 9) {
                        r.setState("已关单");
                    }
                }
                break;
            case 1:
                stateStr = "=1)";
                result = repairRecordService.queryNotTimeoutReportExport(stateStr, keyWord, startTime, endTime, schoolId);
                for (ReportExportVo r : result) {
                    //待接单才能关单
                    r.setState("待接单");
                }
                break;
            case 2:
                stateStr = "=2)";
                result = repairRecordService.queryNotTimeoutReportExport(stateStr, keyWord, startTime, endTime, schoolId);
                for (ReportExportVo r : result) {
                    r.setState("维修中");

                }
                break;
            case 3:
                stateStr = "=3)";
                result = repairRecordService.queryNotTimeoutReportExport(stateStr, keyWord, startTime, endTime, schoolId);
                for (ReportExportVo r : result) {
                    r.setState("待处理");

                }
                break;
            case 4:
                stateStr = "=5 or rr.maintenance_state = 6 or rr.maintenance_state = 11)";
                result = repairRecordService.queryNotTimeoutReportExport(stateStr, keyWord, startTime, endTime, schoolId);
                for (ReportExportVo r : result) {
                    r.setState("待审核");

                }
                break;
            case 5:
                stateStr = "=7)";
                result = repairRecordService.queryNotTimeoutReportExport(stateStr, keyWord, startTime, endTime, schoolId);
                for (ReportExportVo r : result) {
                    r.setState("已完成");
                }
                break;
            case 6:
                stateStr = "=8)";
                result = repairRecordService.queryNotTimeoutReportExport(stateStr, keyWord, startTime, endTime, schoolId);
                for (ReportExportVo r : result) {
                    r.setState("已取消");

                }
                break;
            case 7:
                stateStr = "=9)";
                result = repairRecordService.queryNotTimeoutReportExport(stateStr, keyWord, startTime, endTime, schoolId);
                for (ReportExportVo r : result) {
                    r.setState("已关单");
                }
                break;
            case 8:
                result = repairRecordService.queryTimeoutReportExport(keyWord, startTime, endTime, schoolId);
                for (ReportExportVo r : result) {
                    r.setState("已超时");
                }
                break;
            case 9:
                stateStr = "=10)";
                result = repairRecordService.queryNotTimeoutReportExport(stateStr, keyWord, startTime, endTime, schoolId);
                for (ReportExportVo r : result) {
                    r.setState("转线下");
                }
                break;
            default:
                break;
        }

        //导出

        Workbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet("报修记录表");
        Row headerRow = sheet.createRow(0);
        headerRow.createCell(0).setCellValue("工单编号");
        headerRow.createCell(1).setCellValue("报修区域");
        headerRow.createCell(2).setCellValue("姓名");
        headerRow.createCell(3).setCellValue("电话");
        headerRow.createCell(4).setCellValue("报修物品");
        headerRow.createCell(5).setCellValue("故障描述");
        headerRow.createCell(6).setCellValue("状态");
        headerRow.createCell(7).setCellValue("报修时间");
        headerRow.createCell(8).setCellValue("维修师傅");

        for (int i = 0; i < result.size(); i++) {
            ReportExportVo reportExportVo = result.get(i);
            Row dataRow1 = sheet.createRow(i + 1);
            dataRow1.createCell(0).setCellValue(reportExportVo.getRecordNo());
            dataRow1.createCell(1).setCellValue(reportExportVo.getAreaName());
            dataRow1.createCell(2).setCellValue(reportExportVo.getUserName());
            dataRow1.createCell(3).setCellValue(reportExportVo.getUserPhone());
            dataRow1.createCell(4).setCellValue(reportExportVo.getArticleName());
            dataRow1.createCell(5).setCellValue(reportExportVo.getDescription());
            dataRow1.createCell(6).setCellValue(reportExportVo.getState());
            dataRow1.createCell(7).setCellValue(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(reportExportVo.getReportTime()));
            dataRow1.createCell(8).setCellValue(reportExportVo.getMaintenancerName());

        }

        // 将工作簿写入文件
        ExcelUtils.excelDownload(workbook, "工单管理表.xlsx", response);

        // try (OutputStream outputStream = new FileOutputStream("报修记录表.xlsx")) {
        //     EasyExcel.write(outputStream, ReportExportVo.class).sheet("报修记录表").doWrite(result);
        // }catch (Exception e){
        //     e.printStackTrace();
        // }
    }

    /**
     * 维修师傅首页头部工单数量
     *
     * @param userId 用户ID
     * @return
     */
    @Override
    public CommonResult queryMasterHomeCount(int userId) {
        RepairUser user = repairUserService.getRepairById(userId);
        if (user == null) {
            return CommonResult.fail("用户信息失效，查询失败");
        }

        MasterHomepageVo result = repairRecordService.queryMasterHomeCount(userId, user.getSchoolId());
        return CommonResult.ok(result);
    }

    /**
     * 后勤首页头部工单数量
     *
     * @param schoolId 校区ID
     * @return
     */
    @Override
    public CommonResult queryLogisticHomeCount(int schoolId) {
        MasterHomepageVo result = repairRecordService.queryLogisticHomeCount(schoolId);
        return CommonResult.ok(result);
    }

    /**
     * 报修校区统计
     *
     * @param state 状态
     *              全部：0
     *              本年：1
     *              本月：2
     *              本周：3
     *              今天：4
     * @return
     * @throws Exception
     */
    @Override
    public CommonResult repairCampus(int state) {
        List<RepairCampusVo> result = new ArrayList<>();
        RepairCampusVo HJH = new RepairCampusVo();
        HJH.setId(eSchool.HJH.getValue());
        HJH.setSchoolName(eSchool.stringOf(eSchool.HJH.getValue()));
        result.add(HJH);
        RepairCampusVo MXH = new RepairCampusVo();
        MXH.setId(eSchool.MXH.getValue());
        MXH.setSchoolName(eSchool.stringOf(eSchool.MXH.getValue()));
        result.add(MXH);

        List<RepairCampusRecordVo> campusVoList = new ArrayList<>();
        //全部
        if (state == 0) {
            campusVoList = repairRecordService.repairCampusTotal();


        } else {
            String startTime = DateUtils.startTime(state);
            String endTime = DateUtils.endTime();

            if (ObjectUtils.isEmpty(startTime)) {
                return CommonResult.fail("参数有误");
            }
            campusVoList = repairRecordService.repairCampus(startTime, endTime);

        }


        for (RepairCampusVo r : result) {
            if (campusVoList == null) {
                r.setOrdersCompensation(0);
                r.setOrdersGratis(0);
                r.setTotalPrice(BigDecimal.ZERO);
            }

            //获取当前循环校区的数据
            List<RepairCampusRecordVo> ownDatas = campusVoList.stream().filter(e -> e.getSchoolId().equals(r.getId())).collect(Collectors.toList());
            r.setOrdersTotal(ownDatas == null ? 0 : ownDatas.size());
            //等于1表示大于0 有偿数据
            if (ownDatas == null) {
                r.setOrdersCompensation(0);
                r.setOrdersGratis(0);
                r.setTotalPrice(BigDecimal.ZERO);
            } else {
                List<RepairCampusRecordVo> paidDatas = ownDatas.stream().filter(e -> e.getPrice() != null && e.getPrice().compareTo(BigDecimal.ZERO) == 1).collect(Collectors.toList());
                r.setOrdersCompensation(paidDatas == null ? 0 : paidDatas.size());
                r.setOrdersGratis(ownDatas.size() - paidDatas.size());
                //要合并维修中多个师傅接单的情况 多个师傅接一个单子 只计算一个单子的钱

                BigDecimal totalNoTwo = paidDatas.stream().filter(e -> e.getMaintenanceState() != 2).map(RepairCampusRecordVo::getPrice).reduce(BigDecimal.ZERO, BigDecimal::add);

                List<Integer> withTwo = paidDatas.stream().filter(e -> e.getMaintenanceState() == 2).map(RepairCampusRecordVo::getId).distinct().collect(Collectors.toList());

                for (Integer w : withTwo) {
                    Optional<RepairCampusRecordVo> one = paidDatas.stream().filter(e -> e.getId().equals(w)).findFirst();
                    if (one != null && one.isPresent()) {
                        totalNoTwo = totalNoTwo.add(one.get().getPrice());
                    }
                }
                r.setTotalPrice(totalNoTwo);
            }

        }

        return CommonResult.ok(result);
    }

    /**
     * 报修区域
     *
     * @param state 状态
     *              全部：0
     *              本年：1
     *              本月：2
     *              本周：3
     *              今天：4
     * @return
     * @throws Exception
     */
    @Override
    public CommonResult repairArea(int state, int currentPage, int pageCount) throws Exception {
        //    全部
        if (state == 0) {
            IPage<RepairAreaVo> repairAreaTotal = repairRecordService.repairAreaTotal(currentPage, pageCount);
            return CommonResult.ok(repairAreaTotal);
        }

        String startTime = DateUtils.startTime(state);
        String endTime = DateUtils.endTime();

        if (ObjectUtils.isEmpty(startTime)) {
            return CommonResult.fail("参数有误");
        }

        IPage<RepairAreaVo> repairAreaTotal = repairRecordService.repairArea(startTime, endTime, currentPage, pageCount);

        return CommonResult.ok(repairAreaTotal);
    }

    /**
     * 报修区域导出
     *
     * @param response 响应流
     * @param state    状态
     *                 全部：0
     *                 本年：1
     *                 本月：2
     *                 本周：3
     *                 今天：4
     * @throws Exception
     */
    @Override
    public void repairAreaExport(HttpServletResponse response, int state) {
        String startTime = DateUtils.startTime(state);
        String endTime = DateUtils.endTime();
        List<RepairAreaVo> vos = repairRecordService.repairAreaExport(startTime, endTime);

        //导出
        Workbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet("报修区域统计");
        Row headerRow = sheet.createRow(0);
        headerRow.createCell(0).setCellValue("序号");
        headerRow.createCell(1).setCellValue("学校名称");
        headerRow.createCell(2).setCellValue("报修区域");
        headerRow.createCell(3).setCellValue("工单总数");
        headerRow.createCell(4).setCellValue("有偿");
        headerRow.createCell(5).setCellValue("无偿");
        headerRow.createCell(6).setCellValue("耗材总费用");


        for (int i = 0; i < vos.size(); i++) {
            RepairAreaVo vo = vos.get(i);
            Row dataRow1 = sheet.createRow(i + 1);
            dataRow1.createCell(0).setCellValue(vo.getId());
            dataRow1.createCell(1).setCellValue(vo.getSchoolName());
            String areaName = vo.getAreaName();
            areaName = areaName.substring(5);
            dataRow1.createCell(2).setCellValue(areaName);
            dataRow1.createCell(3).setCellValue(vo.getOrdersTotal());
            dataRow1.createCell(4).setCellValue(vo.getOrdersCompensation());
            dataRow1.createCell(5).setCellValue(vo.getOrdersGratis());
            BigDecimal totalPrice = vo.getTotalPrice();
            if (ObjectUtils.isEmpty(totalPrice)) {
                totalPrice = new BigDecimal(0);
            }
            dataRow1.createCell(6).setCellValue(totalPrice.toString());

        }

        // 将工作簿写入文件
        ExcelUtils.excelDownload(workbook, "报修区域.xlsx", response);

    }

    /**
     * 报修物品统计
     *
     * @param state       状态
     *                    全部：0
     *                    本年：1
     *                    本月：2
     *                    本周：3
     *                    今天：4
     * @param currentPage 当前页
     * @param pageCount   一页数据条数
     * @return
     */
    @Override
    public CommonResult maintenanceGoods(int state, int currentPage, int pageCount) {
        //    全部
        if (state == 0) {
            IPage<MaintenanceGoodsVo> maintenanceGoodsVoList = repairRecordService.maintenanceGoodsTotal(currentPage, pageCount);
            return CommonResult.ok(maintenanceGoodsVoList);
        }

        String startTime = DateUtils.startTime(state);
        String endTime = DateUtils.endTime();

        if (ObjectUtils.isEmpty(startTime)) {
            return CommonResult.fail("参数有误");
        }

        IPage<MaintenanceGoodsVo> maintenanceGoodsVoList = repairRecordService.maintenanceGoods(startTime, endTime, currentPage, pageCount);
        return CommonResult.ok(maintenanceGoodsVoList);
    }

    /**
     * 报修物品导出
     *
     * @param response 响应流
     * @param state    状态
     *                 全部：0
     *                 本年：1
     *                 本月：2
     *                 本周：3
     *                 今天：4
     * @throws Exception
     */
    @Override
    public void maintenanceGoodsExport(HttpServletResponse response, int state) {
        String startTime = DateUtils.startTime(state);
        String endTime = DateUtils.endTime();

        List<MaintenanceGoodsVo> vos = repairRecordService.maintenanceGoodsExport(startTime, endTime);

        //        导出
        Workbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet("维修物品统计");
        Row headerRow = sheet.createRow(0);
        headerRow.createCell(0).setCellValue("序号");
        headerRow.createCell(1).setCellValue("名称");
        headerRow.createCell(2).setCellValue("校区");
        headerRow.createCell(3).setCellValue("工单总数");
        headerRow.createCell(4).setCellValue("有偿");
        headerRow.createCell(5).setCellValue("无偿");
        headerRow.createCell(6).setCellValue("耗材总费用");

        for (int i = 0; i < vos.size(); i++) {
            MaintenanceGoodsVo vo = vos.get(i);
            Row dataRow1 = sheet.createRow(i + 1);
            dataRow1.createCell(0).setCellValue(vo.getId());
            dataRow1.createCell(1).setCellValue(vo.getArticleName());
            dataRow1.createCell(2).setCellValue(vo.getSchoolName());
            dataRow1.createCell(3).setCellValue(vo.getOrdersTotal());
            dataRow1.createCell(4).setCellValue(vo.getOrdersCompensation());
            dataRow1.createCell(5).setCellValue(vo.getOrdersGratis());

            BigDecimal totalPrice = vo.getTotalPrice();
            if (ObjectUtils.isEmpty(totalPrice)) {
                totalPrice = new BigDecimal(0);
            }
            dataRow1.createCell(6).setCellValue(totalPrice.toString());

        }
        // 将工作簿写入文件
        ExcelUtils.excelDownload(workbook, "维修物品.xlsx", response);

    }

    /**
     * 维修师傅效率统计
     *
     * @param state       状态
     *                    全部：0
     *                    本年：1
     *                    本月：2
     *                    本周：3
     *                    今天：4
     * @param currentPage 当前页数
     * @param pageCount   一页数据条数
     * @param schoolId    校区ID
     * @param keyWord     关键字搜索
     * @return
     */
    @Override
    public CommonResult maintenanceWorker(int state, int currentPage, int pageCount, Integer schoolId, String keyWord) {

        String startTime = DateUtils.startTime(state);
        String endTime = DateUtils.endTime();

        //重写
        PageUtils<RepairUser> userPages = repairUserService.queryUserPage(currentPage, pageCount, schoolId, keyWord);

        if (userPages.getList() == null || userPages.getList().size() <= 0) {
            return CommonResult.ok(userPages);
        }

        LambdaQueryWrapper<RepairReceiving> wrapperReceiving = new LambdaQueryWrapper<>();
        wrapperReceiving.between(ObjectUtils.isNotEmpty(startTime), RepairReceiving::getReceivingTime, startTime, endTime);
        wrapperReceiving.isNotNull(RepairReceiving::getFinishTime);
        wrapperReceiving.groupBy(RepairReceiving::getUserId);
        IPage<RepairReceiving> repairReceivingListPage = repairReceivingService.page(new Page<RepairReceiving>(currentPage, pageCount), wrapperReceiving);

        IPage<MaintenanceWorkerVo> page = new Page();

        List<RepairReceiving> records = repairReceivingListPage.getRecords();

        ArrayList<Integer> usersList = new ArrayList<>();
        for (RepairUser user : userPages.getList()) {
            Integer userId = user.getId();
            usersList.add(userId);
        }

        LambdaQueryWrapper<RepairReceiving> wrapperReceiving2 = new LambdaQueryWrapper<>();
        wrapperReceiving2.between(ObjectUtils.isNotEmpty(startTime), RepairReceiving::getReceivingTime, startTime, endTime);
        wrapperReceiving2.isNotNull(RepairReceiving::getFinishTime)
                .in(RepairReceiving::getUserId, usersList);

        List<RepairReceiving> repairReceivingList = repairReceivingService.list(wrapperReceiving2);

        ArrayList<Integer> userList = new ArrayList<>();

        ArrayList<Integer> recordList = new ArrayList<>();

        // 接单总次数
        HashMap<Integer, List<Integer>> receivingCountMap = new HashMap<>();

        // 维修超时次数
        Map<Integer, Integer> maintainTimeOutMap = new HashMap<>();

        // 维修总时长
        Map<Integer, Long> maintainMap = new HashMap<>();


        for (RepairReceiving repairReceiving : repairReceivingList) {
            Date finishTime = repairReceiving.getFinishTime();

            if (ObjectUtils.isEmpty(finishTime)) {
                break;
            }

            Integer userId = repairReceiving.getUserId();
            userList.add(userId);

            Integer recordId = repairReceiving.getRecordId();
            recordList.add(recordId);

            if (receivingCountMap.containsKey(userId)) {
                // 总次数
                List<Integer> list = receivingCountMap.get(userId);
                list.add(recordId);
                receivingCountMap.put(userId, list);
            } else {
                ArrayList<Integer> list = new ArrayList<>();
                list.add(recordId);
                receivingCountMap.put(userId, list);
            }


            // 接单时间
            long receivingTime = repairReceiving.getReceivingTime().getTime();
            // 考核时间(分)
            Integer maintenanceAssessTime = repairReceiving.getMaintenanceAssessTime() * 1000 * 60;

            long time = receivingTime + maintenanceAssessTime;

            // 完成时间
            long finishTimeTime = finishTime.getTime();

            // 实际完成时间大于接单时间加考核时间为超时
            if (finishTimeTime > time) {
                if (maintainTimeOutMap.containsKey(userId)) {
                    // 次数
                    Integer count = maintainTimeOutMap.get(userId);
                    count = count + 1;
                    maintainTimeOutMap.put(userId, count);
                } else {
                    maintainTimeOutMap.put(userId, 1);
                }
            }

            // 维修时长=完成时间-接单时间(分)
            long maintainTime = finishTimeTime - receivingTime;
            maintainTime = maintainTime / 1000 / 60;

            if (maintainMap.containsKey(userId)) {
                // 维修时长
                Long maintainTotalTime = maintainMap.get(userId);
                maintainTotalTime = maintainTotalTime + maintainTime;
                maintainMap.put(userId, maintainTotalTime);
            } else {
                maintainMap.put(userId, maintainTime);
            }
        }

        // 接单总次数
        HashMap<Integer, List<Integer>> sendCountMap = new HashMap<>();
        // 接单超时次数
        Map<Integer, Integer> sendTimeOutMap = new HashMap<>();
        // 接单总时长
        Map<Integer, Long> sendMap = new HashMap<>();

        LambdaQueryWrapper<RepairDispatchRecord> rdrsWrapper = new LambdaQueryWrapper<>();
        rdrsWrapper.in(RepairDispatchRecord::getRecordId, recordList)
                .isNotNull(RepairDispatchRecord::getReceivingTime);


        List<RepairDispatchRecord> repairDispatchRecords = repairDispatchRecordService.list(rdrsWrapper);
        for (RepairDispatchRecord repairDispatchRecord : repairDispatchRecords) {
            // 派单时间
            long sendTime = repairDispatchRecord.getAssignedTime().getTime();
            // 接单考核时间
            Integer acceptanceAssessTime = repairDispatchRecord.getAcceptanceAssessTime() * 1000 * 60;

            long time = sendTime + acceptanceAssessTime;

            // 接单时间
            long receivingTime = repairDispatchRecord.getReceivingTime().getTime();
            // 接单人
            Integer usersId = repairDispatchRecord.getUsersId();
            Integer recordId = repairDispatchRecord.getRecordId();

            if (sendCountMap.containsKey(usersId)) {
                List<Integer> integers = sendCountMap.get(usersId);
                integers.add(recordId);
                sendCountMap.put(usersId, integers);
            } else {
                ArrayList<Integer> integers = new ArrayList<>();
                integers.add(recordId);
                sendCountMap.put(usersId, integers);
            }


            // 实际完成时间大于接单时间加考核时间为超时
            if (receivingTime > time) {
                if (sendTimeOutMap.containsKey(usersId)) {
                    // 次数
                    Integer count = sendTimeOutMap.get(usersId);
                    count = count + 1;
                    sendTimeOutMap.put(usersId, count);
                } else {
                    sendTimeOutMap.put(usersId, 1);
                }
            }

            // 接单时长=接单时间-派单时间(分)
            Long orderReceivingTime = receivingTime - sendTime;
            orderReceivingTime = orderReceivingTime / 1000 / 60;

            if (sendMap.containsKey(usersId)) {
                // 接单总时长
                Long sendTotalTime = sendMap.get(usersId);
                sendTotalTime = sendTotalTime + orderReceivingTime;
                sendMap.put(usersId, sendTotalTime);
            } else {
                sendMap.put(usersId, orderReceivingTime);
            }
        }

        Wrapper<RepairSchool> schoolWrapper = new LambdaQueryWrapper<>();
        List<RepairSchool> schoolList = repairSchoolService.list(schoolWrapper);

        ArrayList<MaintenanceWorkerVo> vos = new ArrayList<>();

        userPages.getList().forEach(repairUser -> {
            MaintenanceWorkerVo maintenanceWorkerVo = new MaintenanceWorkerVo();

            // 名字
            maintenanceWorkerVo.setName(repairUser.getUserName());

            // 学校
            Integer school = repairUser.getSchoolId();
            for (RepairSchool repairSchool : schoolList) {
                Integer id = repairSchool.getId();
                if (id.equals(school)) {
                    maintenanceWorkerVo.setSchoolName(repairSchool.getName());
                }
            }

            Integer id = repairUser.getId();
            // 工单集合
            List<Integer> recordsList = receivingCountMap.get(id);
            int size = recordsList != null ? recordsList.size() : 0;
            BigDecimal b = new BigDecimal(size);

            // 工单总数
            maintenanceWorkerVo.setWorkOrderTotal(size);

            // 超时率
            if (maintainTimeOutMap.containsKey(id)) {
                Integer integer = maintainTimeOutMap.get(id);
                BigDecimal a = new BigDecimal(integer);
                BigDecimal c = b;

                // 接单总次数
                List<Integer> integers = sendCountMap.get(id);
                BigDecimal bigDecimal1 = new BigDecimal(integers.size());
                c = c.add(bigDecimal1);
                // 接单
                if (sendTimeOutMap.containsKey(id)) {
                    Integer integer1 = sendTimeOutMap.get(id);
                    BigDecimal bigDecimal = new BigDecimal(integer1);
                    a = a.add(bigDecimal);

                }

                BigDecimal bigDecimal = a.divide(c, 2, BigDecimal.ROUND_HALF_UP);
                BigDecimal multiply = bigDecimal.multiply(new BigDecimal(100));
                maintenanceWorkerVo.setTimeOut(multiply + "%");
            }

            // 平均维修时间
            Long aLong = maintainMap.get(id) == null ? 0L : maintainMap.get(id);
            BigDecimal bigDecimal = new BigDecimal(aLong);
            BigDecimal maintain = b.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : bigDecimal.divide(b, 2, BigDecimal.ROUND_HALF_UP);
            maintenanceWorkerVo.setMaintain(maintain);

            // 平均响应时长
            if (sendMap.containsKey(id)) {
                Long aLong1 = sendMap.get(id);
                BigDecimal bigDecimal1 = new BigDecimal(aLong1);
                List<Integer> integers = sendCountMap.get(id);
                if (integers.size() <= 0) {
                    maintenanceWorkerVo.setAnswer(null);
                } else {
                    BigDecimal bigDecimal2 = new BigDecimal(integers.size());
                    BigDecimal send = bigDecimal1.divide(bigDecimal2, 2, BigDecimal.ROUND_HALF_UP);
                    maintenanceWorkerVo.setAnswer(send);
                }
            }
            // 总费用
            LambdaQueryWrapper<RepairRecord> recordWrapper = new LambdaQueryWrapper<>();
            recordWrapper.in(RepairRecord::getId, recordsList);

            List<RepairRecord> list = recordsList != null && recordsList.size() > 0 ? repairRecordService.list(recordWrapper) : new ArrayList<>();

            BigDecimal totalPrice = new BigDecimal(0);
            for (RepairRecord repairRecord : list) {
                BigDecimal price = repairRecord.getPrice();
                if (ObjectUtils.isNotEmpty(price)) {
                    totalPrice = totalPrice.add(price);
                }
            }
            maintenanceWorkerVo.setTotalPrice(totalPrice);

            // 好评率
            LambdaQueryWrapper<RepairEvaluate> evaluateWrapper = new LambdaQueryWrapper<>();
            evaluateWrapper.in(RepairEvaluate::getRecordId, recordsList);
            // 根据工单id来查询对应的评价
            List<RepairEvaluate> repairEvaluates = recordsList != null && recordsList.size() > 0 ? repairEvaluateService.list(evaluateWrapper) : new ArrayList<>();

            if (ObjectUtils.isEmpty(repairEvaluates) && repairEvaluates.size() <= 0) {
                maintenanceWorkerVo.setDegreePraise(0);
            } else {
                int count = 0;
                for (RepairEvaluate repairEvaluate : repairEvaluates) {
                    Integer star = repairEvaluate.getStar();
                    if (star > 3) {
                        count++;
                    }
                }
                maintenanceWorkerVo.setDegreePraise(count);
            }

            vos.add(maintenanceWorkerVo);

        });
        page.setRecords(vos);
        page.setCurrent(userPages.getCurrPage());
        page.setSize(userPages.getPageSize());
        page.setPages(userPages.getTotalPage());
        page.setTotal(userPages.getTotalCount());
        return CommonResult.ok(page);
    }

    /**
     * 维修师傅效率导出
     *
     * @param response 响应流
     * @param state    状态
     *                 全部：0
     *                 本年：1
     *                 本月：2
     *                 本周：3
     *                 今天：4
     */
    @Override
    public void maintenanceWorkerExport(HttpServletResponse response, int state, Integer schoolId, String keyWord) {
        String startTime = DateUtils.startTime(state);
        String endTime = DateUtils.endTime();

        ArrayList<MaintenanceWorkerVo> vos = new ArrayList<>();

        //        导出
        Workbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet("维修师傅效率统计");
        Row headerRow = sheet.createRow(0);
        headerRow.createCell(0).setCellValue("序号");
        headerRow.createCell(1).setCellValue("校区");
        headerRow.createCell(2).setCellValue("姓名");
        headerRow.createCell(3).setCellValue("工单总数");
        headerRow.createCell(4).setCellValue("好评数");
        headerRow.createCell(5).setCellValue("超时率");
        headerRow.createCell(6).setCellValue("平均响应时长(分)");
        headerRow.createCell(7).setCellValue("平均维修时长(分)");
        headerRow.createCell(8).setCellValue("耗材总费用(元)");


        LambdaQueryWrapper<RepairReceiving> wrapperReceiving = new LambdaQueryWrapper<>();
        wrapperReceiving.between(ObjectUtils.isNotEmpty(startTime), RepairReceiving::getReceivingTime, startTime, endTime);
        wrapperReceiving.isNotNull(RepairReceiving::getFinishTime);
        List<RepairReceiving> repairReceivingList = repairReceivingService.list(wrapperReceiving);

        PageUtils<RepairUser> userPages = repairUserService.queryUserPage(1, 100, schoolId, keyWord);

        if (ObjectUtils.isNotEmpty(userPages) && userPages.getList().size() > 0) {

            ArrayList<Integer> userList = new ArrayList<>();

            ArrayList<Integer> recordList = new ArrayList<>();

            // 接单总次数
            HashMap<Integer, List<Integer>> receivingCountMap = new HashMap<>();

            // 维修超时次数
            Map<Integer, Integer> maintainTimeOutMap = new HashMap<>();

            // 维修总时长
            Map<Integer, Long> maintainMap = new HashMap<>();


            for (RepairReceiving repairReceiving : repairReceivingList) {
                Date finishTime = repairReceiving.getFinishTime();

                if (ObjectUtils.isEmpty(finishTime)) {
                    break;
                }

                Integer userId = repairReceiving.getUserId();
                userList.add(userId);

                Integer recordId = repairReceiving.getRecordId();
                recordList.add(recordId);

                if (receivingCountMap.containsKey(userId)) {
                    // 总次数
                    List<Integer> list = receivingCountMap.get(userId);
                    list.add(recordId);
                    receivingCountMap.put(userId, list);
                } else {
                    ArrayList<Integer> list = new ArrayList<>();
                    list.add(recordId);
                    receivingCountMap.put(userId, list);
                }


                // 接单时间
                long receivingTime = repairReceiving.getReceivingTime().getTime();
                // 考核时间(分)
                Integer maintenanceAssessTime = repairReceiving.getMaintenanceAssessTime() * 1000 * 60;

                long time = receivingTime + maintenanceAssessTime;

                // 完成时间
                long finishTimeTime = finishTime.getTime();

                // 实际完成时间大于接单时间加考核时间为超时
                if (finishTimeTime > time) {
                    if (maintainTimeOutMap.containsKey(userId)) {
                        // 次数
                        Integer count = maintainTimeOutMap.get(userId);
                        count = count + 1;
                        maintainTimeOutMap.put(userId, count);
                    } else {
                        maintainTimeOutMap.put(userId, 1);
                    }
                }

                // 维修时长=完成时间-接单时间(分)
                long maintainTime = finishTimeTime - receivingTime;
                maintainTime = maintainTime / 1000 / 60;

                if (maintainMap.containsKey(userId)) {
                    // 维修时长
                    Long maintainTotalTime = maintainMap.get(userId);
                    maintainTotalTime = maintainTotalTime + maintainTime;
                    maintainMap.put(userId, maintainTotalTime);
                } else {
                    maintainMap.put(userId, maintainTime);
                }

            }

            // 接单总次数
            HashMap<Integer, List<Integer>> sendCountMap = new HashMap<>();
            // 接单超时次数
            Map<Integer, Integer> sendTimeOutMap = new HashMap<>();
            // 接单总时长
            Map<Integer, Long> sendMap = new HashMap<>();

            LambdaQueryWrapper<RepairDispatchRecord> rdrsWrapper = new LambdaQueryWrapper<>();
            rdrsWrapper.in(RepairDispatchRecord::getRecordId, recordList)
                    .isNotNull(RepairDispatchRecord::getReceivingTime);


            List<RepairDispatchRecord> repairDispatchRecords = repairDispatchRecordService.list(rdrsWrapper);
            for (RepairDispatchRecord repairDispatchRecord : repairDispatchRecords) {
                // 派单时间
                long sendTime = repairDispatchRecord.getAssignedTime().getTime();
                // 接单考核时间
                Integer acceptanceAssessTime = repairDispatchRecord.getAcceptanceAssessTime() * 1000 * 60;

                long time = sendTime + acceptanceAssessTime;

                // 接单时间
                long receivingTime = repairDispatchRecord.getReceivingTime().getTime();
                // 接单人
                Integer usersId = repairDispatchRecord.getUsersId();
                Integer recordId = repairDispatchRecord.getRecordId();

                if (sendCountMap.containsKey(usersId)) {
                    List<Integer> integers = sendCountMap.get(usersId);
                    integers.add(recordId);
                    sendCountMap.put(usersId, integers);
                } else {
                    ArrayList<Integer> integers = new ArrayList<>();
                    sendCountMap.put(usersId, integers);
                }

                // 实际完成时间大于接单时间加考核时间为超时
                if (receivingTime > time) {
                    if (sendTimeOutMap.containsKey(usersId)) {
                        // 次数
                        Integer count = sendTimeOutMap.get(usersId);
                        count = count + 1;
                        sendTimeOutMap.put(usersId, count);
                    } else {
                        sendTimeOutMap.put(usersId, 1);
                    }
                }

                // 接单时长=接单时间-派单时间(分)
                Long orderReceivingTime = receivingTime - sendTime;
                orderReceivingTime = orderReceivingTime / 1000 / 60;

                if (sendMap.containsKey(usersId)) {
                    // 接单总时长
                    Long sendTotalTime = sendMap.get(usersId);
                    sendTotalTime = sendTotalTime + orderReceivingTime;
                    sendMap.put(usersId, sendTotalTime);
                } else {
                    sendMap.put(usersId, orderReceivingTime);
                }


            }


            Wrapper<RepairSchool> schoolWrapper = new LambdaQueryWrapper<>();
            List<RepairSchool> schoolList = repairSchoolService.list(schoolWrapper);


            userPages.getList().forEach(repairUser -> {
                MaintenanceWorkerVo maintenanceWorkerVo = new MaintenanceWorkerVo();

                // 名字
                maintenanceWorkerVo.setName(repairUser.getUserName());

                // 学校
                Integer school = repairUser.getSchoolId();
                for (RepairSchool repairSchool : schoolList) {
                    Integer id = repairSchool.getId();
                    if (id.equals(school)) {
                        maintenanceWorkerVo.setSchoolName(repairSchool.getName());
                    }
                }

                Integer id = repairUser.getId();
                // 工单集合
                List<Integer> recordsList = receivingCountMap.get(id);
                int size = recordsList != null ? recordsList.size() : 0;
                BigDecimal b = new BigDecimal(size);

                // 工单总数
                maintenanceWorkerVo.setWorkOrderTotal(size);

                // 超时率
                if (maintainTimeOutMap.containsKey(id)) {
                    Integer integer = maintainTimeOutMap.get(id);
                    BigDecimal a = new BigDecimal(integer);
                    BigDecimal c = b;
                    // 接单
                    if (sendTimeOutMap.containsKey(id)) {
                        Integer integer1 = sendTimeOutMap.get(id);
                        BigDecimal bigDecimal = new BigDecimal(integer1);
                        a = a.add(bigDecimal);
                        List<Integer> integers = sendCountMap.get(id);
                        c = c.add(new BigDecimal(integers.size()));
                    }

                    BigDecimal bigDecimal = a.divide(c, 2, BigDecimal.ROUND_HALF_UP);
                    BigDecimal multiply = bigDecimal.multiply(new BigDecimal(100));
                    maintenanceWorkerVo.setTimeOut(multiply + "%");
                }

                // 平均维修时间
                Long aLong = maintainMap.get(id) == null ? 0L : maintainMap.get(id);
                BigDecimal bigDecimal = new BigDecimal(aLong);
                BigDecimal maintain = b.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : bigDecimal.divide(b, 2, BigDecimal.ROUND_HALF_UP);
                maintenanceWorkerVo.setMaintain(maintain);

                // 平均响应时长
                if (sendMap.containsKey(id)) {
                    Long aLong1 = sendMap.get(id);
                    BigDecimal bigDecimal1 = new BigDecimal(aLong1);
                    List<Integer> integers = sendCountMap.get(id);
                    if (integers.size() <= 0) {
                        maintenanceWorkerVo.setAnswer(null);
                    } else {
                        BigDecimal bigDecimal2 = new BigDecimal(integers.size());
                        BigDecimal send = bigDecimal1.divide(bigDecimal2, 2, BigDecimal.ROUND_HALF_UP);
                        maintenanceWorkerVo.setAnswer(send);
                    }
                }

                // 总费用
                LambdaQueryWrapper<RepairRecord> recordWrapper = new LambdaQueryWrapper<>();
                recordWrapper.in(RepairRecord::getId, recordsList);

                List<RepairRecord> list = recordsList != null && recordsList.size() > 0 ? repairRecordService.list(recordWrapper) : new ArrayList<>();
                BigDecimal totalPrice = new BigDecimal(0);
                for (RepairRecord repairRecord : list) {
                    BigDecimal price = repairRecord.getPrice();
                    if (ObjectUtils.isNotEmpty(price)) {
                        totalPrice = totalPrice.add(price);
                    }
                }
                maintenanceWorkerVo.setTotalPrice(totalPrice);

                // 好评率
                LambdaQueryWrapper<RepairEvaluate> evaluateWrapper = new LambdaQueryWrapper<>();
                evaluateWrapper.in(RepairEvaluate::getRecordId, recordsList);
                // 根据工单id来查询对应的评价
                List<RepairEvaluate> repairEvaluates = recordsList != null && recordsList.size() > 0 ? repairEvaluateService.list(evaluateWrapper) : new ArrayList<>();

                if (ObjectUtils.isEmpty(repairEvaluates) && repairEvaluates.size() <= 0) {
                    maintenanceWorkerVo.setDegreePraise(0);
                } else {
                    int count = 0;
                    for (RepairEvaluate repairEvaluate : repairEvaluates) {
                        Integer star = repairEvaluate.getStar();
                        if (star > 3) {
                            count++;
                        }
                    }
                    maintenanceWorkerVo.setDegreePraise(count);
                }


                vos.add(maintenanceWorkerVo);
            });

            for (int i = 0; i < vos.size(); i++) {
                MaintenanceWorkerVo vo = vos.get(i);
                Row dataRow1 = sheet.createRow(i + 1);
                dataRow1.createCell(0).setCellValue(i + 1);
                dataRow1.createCell(1).setCellValue(vo.getSchoolName());
                dataRow1.createCell(2).setCellValue(vo.getName());
                dataRow1.createCell(3).setCellValue(vo.getWorkOrderTotal());
                dataRow1.createCell(4).setCellValue(vo.getDegreePraise());
                dataRow1.createCell(5).setCellValue(vo.getTimeOut());
                BigDecimal answer = vo.getAnswer();
                if (ObjectUtils.isEmpty(answer)) {
                    answer = new BigDecimal(0);
                }
                dataRow1.createCell(6).setCellValue(answer.toString());
                BigDecimal maintain = vo.getMaintain();
                if (ObjectUtils.isEmpty(maintain)) {
                    maintain = new BigDecimal(0);
                }

                dataRow1.createCell(7).setCellValue(maintain.toString());

                BigDecimal totalPrice = vo.getTotalPrice();
                if (ObjectUtils.isEmpty(totalPrice)) {
                    totalPrice = new BigDecimal(0);
                }
                dataRow1.createCell(8).setCellValue(totalPrice.toString());

            }
        }
        // 将工作簿写入文件
        ExcelUtils.excelDownload(workbook, "维修师傅.xlsx", response);


    }

    /**
     * 报修分析统计
     *
     * @param state 状态
     *              全部：0
     *              本年：1
     *              本月：2
     *              本周：3
     *              今天：4
     * @return
     */
    @Override
    public CommonResult repairAnalysis(int state) {
        String startTime = DateUtils.startTime(state);
        String endTime = DateUtils.endTime();

        RepairAnalysisVo vo = repairRecordService.repairAnalysis(startTime, endTime);

        Integer timeOutCount = repairRecordService.queryTimeOut(startTime, endTime);

        vo.setTimeOutCount(timeOutCount);

        return CommonResult.ok(vo);
    }

    /**
     * 报修趋势分析
     *
     * @param state 状态
     *              全部：0
     *              本年：1
     *              本月：2
     *              本周：3
     *              今天：4
     * @return
     */
    @Override
    public CommonResult repairTrend(int state) {

        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        //当前时间
        LocalDateTime now = LocalDateTime.now();


        // 本次时间
        String startTime = DateUtils.trendStartTime(state);
        LocalDateTime sTime = LocalDateTime.parse(startTime, dateTimeFormatter);

        int monthValue = sTime.getMonthValue();

        // 对比时间
        String doubleStartTime = DateUtils.trendComparisonStartTime(state);
        LocalDateTime dsTime = LocalDateTime.parse(doubleStartTime, dateTimeFormatter);

        ArrayList<RepairTrendVo> vos = new ArrayList<>();
        // 本年和去年
        if (state == 1) {

            for (int i = 1; i <= 12; i++) {
                RepairTrendVo repairTrendVo = new RepairTrendVo();
                // 获取当前月份
                int monthValue1 = now.getMonthValue();

                if (i <= monthValue1) {
                    LocalDateTime dateTime = sTime.plusMonths(i - 1);
                    LocalDateTime endTime = sTime.plusMonths(i);
                    LambdaQueryWrapper<RepairRecord> wrapper = new LambdaQueryWrapper<>();
                    wrapper.between(RepairRecord::getReportTime, dateTime, endTime);
                    int count = repairRecordService.count(wrapper);
                    repairTrendVo.setTrendCount(count);
                    repairTrendVo.setTrendName(dateTime.getMonthValue() + "月");
                }

                LocalDateTime dDateTime = dsTime.plusMonths(i - 1);
                LocalDateTime doubleEndTime = dsTime.plusMonths(i);
                LambdaQueryWrapper<RepairRecord> dWrapper = new LambdaQueryWrapper<>();
                dWrapper.between(RepairRecord::getReportTime, dDateTime, doubleEndTime);
                int dCount = repairRecordService.count(dWrapper);
                repairTrendVo.setTrendComparisonCount(dCount);

                repairTrendVo.setTrendComparisonName(dDateTime.getMonthValue() + "月");
                vos.add(repairTrendVo);
            }

        } else if (state == 2) {
            for (int i = 1; i <= 31; i++) {
                RepairTrendVo repairTrendVo = new RepairTrendVo();

                int dayOfMonth = now.getDayOfMonth();

                LocalDateTime dateTime = sTime.plusDays(i - 1);
                LocalDateTime endTime = sTime.plusDays(i);

                LocalDateTime dDateTime = dsTime.plusDays(i - 1);
                LocalDateTime doubleEndTime = dsTime.plusDays(i);

                int value = dateTime.getMonthValue();
                int value2 = dDateTime.getMonthValue();

                // 当前时间月份相同就可以添加
                if (value == monthValue && i <= dayOfMonth) {
                    LambdaQueryWrapper<RepairRecord> wrapper = new LambdaQueryWrapper<>();
                    wrapper.between(RepairRecord::getReportTime, dateTime, endTime);
                    int count = repairRecordService.count(wrapper);
                    repairTrendVo.setTrendCount(count);
                    repairTrendVo.setTrendName(value + "月" + dateTime.getDayOfMonth() + "号");
                }
                // 对比的月份不相同就可以添加
                if (value2 != monthValue) {
                    LambdaQueryWrapper<RepairRecord> dWrapper = new LambdaQueryWrapper<>();
                    dWrapper.between(RepairRecord::getReportTime, dDateTime, doubleEndTime);
                    int dCount = repairRecordService.count(dWrapper);
                    repairTrendVo.setTrendComparisonCount(dCount);
                    repairTrendVo.setTrendComparisonName(value2 + "月" + dDateTime.getDayOfMonth() + "号");
                }

                vos.add(repairTrendVo);
            }

        } else if (state == 3) {
            for (int i = 1; i <= 7; i++) {
                // 获取当前星期
                int value = now.getDayOfWeek().getValue();

                RepairTrendVo repairTrendVo = new RepairTrendVo();

                if (i <= value) {
                    LocalDateTime dateTime = sTime.plusDays(i - 1);
                    LocalDateTime endTime = sTime.plusDays(i);
                    LambdaQueryWrapper<RepairRecord> wrapper = new LambdaQueryWrapper<>();
                    wrapper.between(RepairRecord::getReportTime, dateTime, endTime);
                    int count = repairRecordService.count(wrapper);
                    repairTrendVo.setTrendCount(count);
                    repairTrendVo.setTrendName(DateUtils.weekName(dateTime.getDayOfWeek().getValue()));
                }

                LocalDateTime dDateTime = dsTime.plusDays(i - 1);
                LocalDateTime doubleEndTime = dsTime.plusDays(i);
                LambdaQueryWrapper<RepairRecord> dWrapper = new LambdaQueryWrapper<>();
                dWrapper.between(RepairRecord::getReportTime, dDateTime, doubleEndTime);
                int dCount = repairRecordService.count(dWrapper);
                repairTrendVo.setTrendComparisonCount(dCount);

                repairTrendVo.setTrendComparisonName(DateUtils.weekName(dDateTime.getDayOfWeek().getValue()));
                vos.add(repairTrendVo);
            }
        } else if (state == 4) {
            for (int i = 1; i <= 24; i++) {
                RepairTrendVo repairTrendVo = new RepairTrendVo();

                // 获取当前小时
                int hour = now.getHour();

                if (i <= hour) {
                    LocalDateTime dateTime = sTime.plusHours(i - 1);
                    LocalDateTime endTime = sTime.plusHours(i);
                    LambdaQueryWrapper<RepairRecord> wrapper = new LambdaQueryWrapper<>();
                    wrapper.between(RepairRecord::getReportTime, dateTime, endTime);
                    int count = repairRecordService.count(wrapper);
                    repairTrendVo.setTrendCount(count);
                    repairTrendVo.setTrendName(dateTime.getHour() + "点");
                }

                LocalDateTime dDateTime = dsTime.plusHours(i - 1);
                LocalDateTime doubleEndTime = dsTime.plusHours(i);
                LambdaQueryWrapper<RepairRecord> dWrapper = new LambdaQueryWrapper<>();
                dWrapper.between(RepairRecord::getReportTime, dDateTime, doubleEndTime);
                int dCount = repairRecordService.count(dWrapper);
                repairTrendVo.setTrendComparisonCount(dCount);

                repairTrendVo.setTrendComparisonName(dDateTime.getHour() + "点");
                vos.add(repairTrendVo);
            }
        }

        return CommonResult.ok(vos);
    }

    /**
     * 总数据汇总分析
     *
     * @return
     */
    @Override
    public CommonResult repairSummarizing() {

        List<RepairSummarizingVo> vos = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            String startTime = DateUtils.startTime(i);
            String endTime = DateUtils.endTime();
            RepairSummarizingVo vo = repairRecordService.repairSummarizing(startTime, endTime);
            if (i == 0) {
                vo.setDateName("全部");
            } else if (i == 1) {
                vo.setDateName("本年");
            } else if (i == 2) {
                vo.setDateName("本月");
            } else if (i == 3) {
                vo.setDateName("本周");
            } else {
                vo.setDateName("今天");
            }
            vos.add(vo);
        }


        return CommonResult.ok(vos);
    }

    /**
     * 总数据分析
     *
     * @return
     */
    @Override
    public CommonResult repairTotalData() {
        RepairTotalDataVo vo = repairRecordService.repairTotalData();
        return CommonResult.ok(vo);
    }

    /**
     * 打印
     *
     * @param recordId
     * @return
     */
    @Override
    public CommonResult queryPrintData(int recordId, String userhead) {
        PrintVo vo = repairRecordService.queryPrintData(recordId);
        if (vo == null) {
            vo = new PrintVo();
        }

        String userID = AesUtils.decrypt(userhead);
        RepairAdmin operateData = repairAdminService.getRepairById(userID);
        if (operateData == null) {
            return CommonResult.fail("操作人信息不合法，无法进行打印操作！");
        }

        vo.setPrintTime(new Date());
        vo.setOperator(operateData.getUsername());

        return CommonResult.ok(vo);
    }

    /**
     * 待确认-留言
     *
     * @param mrr           留言数据
     * @param bindingResult 是否为空判断
     * @return
     * @throws Exception
     */
    @Override
    public CommonResult mobileReply(MobileRevertRequest mrr, BindingResult bindingResult) throws Exception {
        if (bindingResult.hasErrors()) {
            String st = paramUtils.getParamError(bindingResult);
            return CommonResult.fail(st);
        }

        try {
            RepairRecord data = repairRecordService.getRepairById(mrr.getRecordId());
            if (data == null) {
                return CommonResult.fail("报修单已失效，无法进行回复");
            }

            if (data.getMaintenanceState() != eRecordStatu.ToLogistics.getValue()) {
                return CommonResult.fail("待处理维修单才能进行回复操作");
            }

            //接收人
            Integer recipientId = data.getUserId();

            //将工单数据状态改为待确认
            data.setMaintenanceState(eRecordStatu.ToConfirmed.getValue());
            int result = repairRecordService.updateRepairRecord(data);
            if (result <= 0) {
                throw new Exception("回复失败！");
            }


            RepairLeaveMessage repairLeaveMessage = new RepairLeaveMessage();
            repairLeaveMessage.setRecordId(data.getId());
            repairLeaveMessage.setRecipientId(recipientId);
            repairLeaveMessage.setSenderId(mrr.getUserId());
            repairLeaveMessage.setContent(mrr.getContent());

            boolean mSave = repairLeaveMessageService.save(repairLeaveMessage);

            if (!mSave) {
                throw new Exception("回复失败！");
            }

            //        追踪记录表
            RepairTrackRecord repairTrackRecord = new RepairTrackRecord();
            repairTrackRecord.setMaintenanceState(eRecordStatu.ToConfirmed.getValue());
            repairTrackRecord.setRecordId(data.getId());
            repairTrackRecord.setContent("回复:" + mrr.getContent());
            repairTrackRecord.setUserId(mrr.getUserId());
            repairTrackRecord.setUserZzstr("管理员");
            boolean save = repairTrackRecordService.save(repairTrackRecord);

            if (!save) {
                throw new Exception("回复失败！");
            }

            RepairSystemMessages rsm = new RepairSystemMessages();
            rsm.setIsRead(0);
            rsm.setRecordId(mrr.getRecordId());
            rsm.setRecipientId(recipientId);
            rsm.setContent("用户已回复，请尽快处理！");
            int insertRsm = repairSystemMessagesService.insertRepairSystemMessages(rsm);
            if (insertRsm <= 0) {
                throw new Exception("回复失败！");
            }

        } catch (Exception e) {
            throw new Exception("回复失败！");
        }

        return CommonResult.ok("回复成功");
    }

    /**
     * 关单操作
     *
     * @param recordId 维修记录ID
     * @param userId   用户ID
     * @param reason   关单原因
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public CommonResult closeOrders(int recordId, String userId, String reason, String remark, Integer voiceLength) throws Exception {

        //获取订单
        RepairRecord recordData = repairRecordService.getRepairById(recordId);
        if (recordData == null) {
            return CommonResult.fail("订单不存在，关单失败！");
        }

        //待接单才能关单
        if (recordData.getMaintenanceState() != eRecordStatu.Dispatch.getValue()) {
            return CommonResult.fail("待接单状态的工单才能关闭");
        }

        try {
            //将工单状态更新为维修中
            recordData.setCustomsOfficerId(userId);
            recordData.setRemark(reason);
            recordData.setMaintenanceState(eRecordStatu.Closed.getValue());
            int updateRecord = repairRecordService.updateRepairRecord(recordData);
            if (updateRecord <= 0) {
                return CommonResult.fail("关单失败！");
            }

            RepairSystemMessages rsm = new RepairSystemMessages();
            rsm.setIsRead(0);
            rsm.setRecordId(recordId);
            rsm.setRecipientId(recordData.getUserId());
            rsm.setContent("工单已被师傅关闭，关单原因为：" + reason + "！");
            int insertRsm = repairSystemMessagesService.insertRepairSystemMessages(rsm);
            if (insertRsm <= 0) {
                throw new Exception("关单失败！");
            }

            //添加跟踪记录
            RepairTrackRecord rtr = new RepairTrackRecord();
            rtr.setRecordId(recordId);
            rtr.setMaintenanceState(eRecordStatu.Closed.getValue());
            rtr.setContent("已关单-" + reason);
            rtr.setUserId(Integer.valueOf(userId));
            rtr.setUserZzstr("维修师傅");
            if (voiceLength != null) {
                rtr.setVoice(remark);
                rtr.setVoiceLength(voiceLength);
            } else {
                rtr.setContent(rtr.getContent() + " 补充说明：" + remark);
            }
            int insertRtr = repairTrackRecordService.insertRepairTrackRecord(rtr);
            if (insertRtr <= 0) {
                throw new Exception("关单失败");
            }

            //查询用户的微校卡号
            RepairUser user = repairUserService.getRepairById(recordData.getUserId());
            if (user == null) {
                throw new Exception("关单失败");
            }
            List<String> cardNumber = new ArrayList<>();
            cardNumber.add(user.getCardNumber());
            String content = MessageFormat.format("【报修系统】报修用户，你好，工单{0}因{1}原因已被关单，谢谢！", recordData.getRecordNo(), reason);
            CommonResult result = weiXiaoUtil.sendNotice(cardNumber, "报修工单关单", "关单", content, null);
            if (!result.getCode().equals("200")) {
                throw new Exception("关单失败！");
            }
        } catch (Exception e) {
            throw new Exception("关单失败！");
        }

        return CommonResult.ok("关单成功");
    }

    /**
     * 管理端关单操作
     *
     * @param recordId 维修记录ID
     * @param userhead 请求头
     * @param reason   关单原因
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public CommonResult closePCOrder(int recordId, String userhead, String reason, String remark) throws Exception {

        //获取订单
        RepairRecord recordData = repairRecordService.getRepairById(recordId);
        if (recordData == null) {
            return CommonResult.fail("订单不存在，关单失败！");
        }

        //待接单才能关单
        if (recordData.getMaintenanceState() != eRecordStatu.Dispatch.getValue()) {
            return CommonResult.fail("待接单状态的工单才能关闭");
        }

        String userID = AesUtils.decrypt(userhead);
        RepairAdmin operateData = repairAdminService.getRepairById(userID);
        if (operateData == null) {
            return CommonResult.fail("操作人信息不合法，无法进行关单！");
        }

        //发送人
        Integer userId = 0;//超级管理员用ID为0
        if (!operateData.getIsSuper().equals(eIsSuper.Super.getValue())) {
            RepairUser user = repairUserService.getRepairByCardNumber(operateData.getCardNumber());
            if (user == null) {
                return CommonResult.fail("管理端账号未与移动端账号绑定，无法进行关单！");
            }
            userId = user.getId();
        }

        try {
            //将工单状态更新为维修中
            recordData.setCustomsOfficerId(userId.toString());
            recordData.setRemark(reason);
            recordData.setMaintenanceState(eRecordStatu.Closed.getValue());
            int updateRecord = repairRecordService.updateRepairRecord(recordData);
            if (updateRecord <= 0) {
                return CommonResult.fail("关单失败！");
            }

            RepairSystemMessages rsm = new RepairSystemMessages();
            rsm.setIsRead(0);
            rsm.setRecordId(recordId);
            rsm.setRecipientId(recordData.getUserId());
            rsm.setContent("工单已被师傅关闭，关单原因为：" + reason + "！");
            int insertRsm = repairSystemMessagesService.insertRepairSystemMessages(rsm);
            if (insertRsm <= 0) {
                throw new Exception("关单失败！");
            }

            //添加跟踪记录
            RepairTrackRecord rtr = new RepairTrackRecord();
            rtr.setRecordId(recordId);
            rtr.setMaintenanceState(eRecordStatu.Closed.getValue());
            rtr.setContent("已关单-" + reason + "  补充说明：" + remark);
            rtr.setUserId(Integer.valueOf(userId));
            rtr.setUserZzstr("维修师傅");

            int insertRtr = repairTrackRecordService.insertRepairTrackRecord(rtr);
            if (insertRtr <= 0) {
                throw new Exception("关单失败");
            }

            RepairUser user = repairUserService.getRepairById(recordData.getUserId());
            if (user == null) {
                throw new Exception("关单失败");
            }
            List<String> cardNumber = new ArrayList<>();
            cardNumber.add(user.getCardNumber());
            String content = MessageFormat.format("【报修系统】报修用户，你好，工单{0}因{1}原因已被关单，谢谢！", recordData.getRecordNo(), reason);
            CommonResult result = weiXiaoUtil.sendNotice(cardNumber, "报修工单关单", "关单", content, null);
            if (!result.getCode().equals("200")) {
                throw new Exception("关单失败！");
            }
        } catch (Exception e) {
            throw new Exception("关单失败！");
        }

        return CommonResult.ok("关单成功");
    }

    /**
     * 维修完成
     *
     * @param data          报修数据
     * @param userhead      请求头
     * @param bindingResult 是否为空判断
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public CommonResult finishOrder(finishOrderRequest data, @RequestHeader("user_head") String userhead, BindingResult bindingResult) throws Exception {
        System.out.println("维修完成提交订单" + JSON.toJSON(data));
        try {
            if (bindingResult.hasErrors()) {
                String st = paramUtils.getParamError(bindingResult);
                return CommonResult.fail(st);
            }
            List<RepairConsumables> rcDatas = new ArrayList<>();
            //需要记录后续添加的耗材数据 但是不把钱记录到订单总金额中
            if (data.getConsumes().size() > 0) {
                for (insertConsumablesRequest rc : data.getConsumes()) {
                    if (rc.getConsumeId() == null) {
                        return CommonResult.fail("耗材ID不能为空");
                    }
                    if (rc.getConsumeName() == null) {
                        return CommonResult.fail("耗材名称不能为空");
                    }
                    if (rc.getNumber() == null || rc.getNumber() <= 0) {
                        return CommonResult.fail("耗材数量不能为空");
                    }
                    if (rc.getPrice() == null) {
                        return CommonResult.fail("耗材单价不能为空");
                    }
                    RepairConsumables rcData = new RepairConsumables();
                    rcData.setArticleId(rc.getArticleId());
                    rcData.setRecordId(data.getRecordId());
                    rcData.setConsumeId(rc.getConsumeId());
                    rcData.setConsumeName(rc.getConsumeName());
                    rcData.setNumber(rc.getNumber());
                    rcData.setPrice(rc.getPrice());
                    rcData.setTotalPrice(new BigDecimal(0));
                    rcDatas.add(rcData);
                }
            }

            //获取订单
            RepairRecord recordData = repairRecordService.getRepairById(data.getRecordId());
            if (recordData == null) {
                return CommonResult.fail("工单不存在，提交失败！");
            }

            //待接单才能关单
            if (recordData.getMaintenanceState() == eRecordStatu.Finished.getValue()) {
                return CommonResult.fail("该工单已被提交，请勿重复操作");
            }

            if (recordData.getMaintenanceState() != eRecordStatu.Maintenance.getValue()) {
                return CommonResult.fail("维修中的工单才能进行提交");
            }

            if (rcDatas.size() > 0) {
                boolean result = repairConsumablesService.insertConsumableBatch(rcDatas);

                if (!result) {
                    throw new Exception("提交失败！");
                }
            }

            //2023-09-30 一个人点了完成就帮其他人都完成
            //将工单状态更新为已完成
            recordData.setFinishVoice(data.getVoice());
            recordData.setFinishVoiceLength(data.getVoiceLength());
            recordData.setContent(data.getContnet());
            recordData.setMaintenancer(data.getImages().size() > 0 ? StringUtils.join(data.getImages(), ',') : null);
            recordData.setMaintenanceState(eRecordStatu.Finished.getValue());
            int updateRecord = repairRecordService.updateRepairRecord(recordData);
            if (updateRecord <= 0) {
                throw new Exception("提交失败！");
            }

            //更新接单记录数据的维修完成时间
            RepairReceiving rr = new RepairReceiving();
            rr.setFinishTime(new Date());
            int updateReceiving = repairReceivingService.updateRepairByRecordId(data.getRecordId(), rr);
            if (updateReceiving <= 0) {
                throw new Exception("提交失败！");
            }

            RepairSystemMessages rsm = new RepairSystemMessages();
            rsm.setIsRead(0);
            rsm.setRecordId(data.getRecordId());
            rsm.setRecipientId(recordData.getUserId());
            rsm.setContent("服务已经完成，期待再次为您服务，请为我们的服务点评~");
            int insertRsm = repairSystemMessagesService.insertRepairSystemMessages(rsm);
            if (insertRsm <= 0) {
                throw new Exception("提交失败！");
            }

            String userID = AesUtils.decrypt(userhead);
            RepairAdmin operateData = repairAdminService.getRepairById(userID);
            if (operateData == null) {
                return CommonResult.fail("操作人信息不合法，无法进行回复！");
            }

            //发送人
            Integer senderId = 0;//超级管理员用ID为0
            if (!operateData.getIsSuper().equals(eIsSuper.Super.getValue())) {
                RepairUser user = repairUserService.getRepairByCardNumber(operateData.getCardNumber());
                if (user == null) {
                    return CommonResult.fail("管理端账号未与移动端账号绑定，无法进行审核！");
                }
                senderId = user.getId();
            }

            //添加跟踪记录
            RepairTrackRecord rtr = new RepairTrackRecord();
            rtr.setRecordId(data.getRecordId());
            rtr.setMaintenanceState(eRecordStatu.Finished.getValue());
            rtr.setContent("已完成");
            rtr.setUserId(senderId);
            rtr.setUserZzstr("维修师傅");
            rtr.setImage(StringUtils.join(data.getImages(), ','));
            rtr.setVoice(data.getVoice());
            rtr.setVoiceLength(data.getVoiceLength());
            int insertRtr = repairTrackRecordService.insertRepairTrackRecord(rtr);
            if (insertRtr <= 0) {
                throw new Exception("提交失败");
            }
        } catch (Exception e) {
            System.out.println("维修完成提交失败：" + e.getMessage());
            throw new Exception("提交失败！");
        }

        return CommonResult.ok("提交成功！");
    }

    /**
     * 转单审核申请
     *
     * @param data          转单审核申请数据
     * @param bindingResult 是否为空判断
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public CommonResult transferApply(transferApplyRequest data, BindingResult bindingResult) throws Exception {
        try {
            if (bindingResult.hasErrors()) {
                String st = paramUtils.getParamError(bindingResult);
                return CommonResult.fail(st);
            }

            //已关单 已取消 已完成的单子不能提交转单申请
            //获取订单 判断当前订单是否是待接单状态
            RepairRecord recordData = repairRecordService.getRepairById(data.getRecordId());
            if (recordData == null) {
                return CommonResult.fail("订单不存在，申请失败");
            }

            if (recordData.getMaintenanceState() == eRecordStatu.Transfer.getValue()) {
                return CommonResult.fail("该订单已发起转单审核，请勿重复操作");
            }

            if (recordData.getMaintenanceState() != eRecordStatu.Dispatch.getValue()) {
                return CommonResult.fail("待接单的订单才能进行转单申请");
            }

            RepairTransferRecord rtr = new RepairTransferRecord();
            rtr.setRecordId(data.getRecordId());
            rtr.setVoice(data.getVoice());
            rtr.setVoiceLength(data.getVoiceLength());
            rtr.setRemark(data.getRemark());
            rtr.setUserId(data.getUserId());
            rtr.setApprovalStatu(2);

            int result = repairTransferRecordService.insertRepairTransferRecord(rtr);
            if (result <= 0) {
                throw new Exception("申请失败！");
            }

            recordData.setMaintenanceState(eRecordStatu.Transfer.getValue());
            int updateRecord = repairRecordService.updateRepairRecord(recordData);
            if (updateRecord <= 0) {
                throw new Exception("申请失败！");
            }

            //给郭班长和后勤发消息
            List<Integer> userZZ = new ArrayList<>();
            userZZ.add(2);
            userZZ.add(3);
            List<RepairUser> users = repairUserService.getRepairByUserZZ(userZZ, recordData.getSchoolId());
            List<RepairSystemMessages> rsms = new ArrayList<>();
            for (RepairUser user : users) {
                RepairSystemMessages rsm = new RepairSystemMessages();
                rsm.setIsRead(0);
                rsm.setRecordId(data.getRecordId());
                rsm.setRecipientId(user.getId());
                rsm.setContent("您有一个审核工单，请尽快处理!");
                rsms.add(rsm);
            }

            boolean insertRsm = repairSystemMessagesService.inserBatchSystemMessage(rsms);
            if (!insertRsm) {
                throw new Exception("转单审核发起失败！");
            }

            //添加跟踪记录
            RepairTrackRecord rtrR = new RepairTrackRecord();
            rtrR.setRecordId(data.getRecordId());
            rtrR.setMaintenanceState(eRecordStatu.Transfer.getValue());
            rtrR.setContent("转单审核申请");
            rtrR.setUserId(data.getUserId());
            rtrR.setUserZzstr("维修师傅");
            rtrR.setVoice(data.getVoice());
            rtrR.setVoiceLength(data.getVoiceLength());
            int insertRtr = repairTrackRecordService.insertRepairTrackRecord(rtrR);
            if (insertRtr <= 0) {
                throw new Exception("转单审核发起失败！");
            }


        } catch (Exception e) {
            throw new Exception("转单审核发起失败！");
        }

        return CommonResult.ok("转单审核发起成功");
    }


    /**
     * 转线下审核申请
     *
     * @param data          转单审核申请数据
     * @param bindingResult 是否为空判断
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public CommonResult offlineApply(offlineApplyRequest data, BindingResult bindingResult) throws Exception {
        try {
            if (bindingResult.hasErrors()) {
                String st = paramUtils.getParamError(bindingResult);
                return CommonResult.fail(st);
            }

            //已关单 已取消 已完成的单子不能提交转单申请
            //获取订单 判断当前订单是否是待接单状态
            RepairRecord recordData = repairRecordService.getRepairById(data.getRecordId());
            if (recordData == null) {
                return CommonResult.fail("订单不存在，申请失败");
            }

            if (recordData.getMaintenanceState().intValue() == eRecordStatu.OfflineReview.getValue()) {
                return CommonResult.fail("该订单已发起转线下审核，请勿重复操作");
            }

            RepairOfflineRecord ror = new RepairOfflineRecord();
            ror.setRecordId(data.getRecordId());
            ror.setVoice(data.getVoice());
            ror.setVoiceLength(data.getVoiceLength());
            ror.setRemark(data.getRemark());
            ror.setUserId(data.getUserId());
            ror.setApprovalStatu(2);
            ror.setOldRecord(recordData.getMaintenanceState());

            int result = repairOfflineRecordService.insertRepairOfflineRecord(ror);
            if (result <= 0) {
                throw new Exception("申请失败！");
            }

            recordData.setMaintenanceState(eRecordStatu.OfflineReview.getValue());
            int updateRecord = repairRecordService.updateRepairRecord(recordData);
            if (updateRecord <= 0) {
                throw new Exception("申请失败！");
            }

            //给郭班长和后勤发消息
            List<Integer> userZZ = new ArrayList<>();
            userZZ.add(2);
            userZZ.add(3);
            List<RepairUser> users = repairUserService.getRepairByUserZZ(userZZ, recordData.getSchoolId());
            List<RepairSystemMessages> rsms = new ArrayList<>();
            for (RepairUser user : users) {
                RepairSystemMessages rsm = new RepairSystemMessages();
                rsm.setIsRead(0);
                rsm.setRecordId(data.getRecordId());
                rsm.setRecipientId(user.getId());
                rsm.setContent("您有一个审核工单，请尽快处理!");
                rsms.add(rsm);
            }

            boolean insertRsm = repairSystemMessagesService.inserBatchSystemMessage(rsms);
            if (!insertRsm) {
                throw new Exception("转线下审核发起失败！");
            }

            //添加跟踪记录
            RepairTrackRecord rtrR = new RepairTrackRecord();
            rtrR.setRecordId(data.getRecordId());
            rtrR.setMaintenanceState(eRecordStatu.OfflineReview.getValue());
            rtrR.setContent("转线下审核申请");
            rtrR.setUserId(data.getUserId());
            rtrR.setUserZzstr("维修师傅");
            rtrR.setVoice(data.getVoice());
            rtrR.setVoiceLength(data.getVoiceLength());
            int insertRtr = repairTrackRecordService.insertRepairTrackRecord(rtrR);
            if (insertRtr <= 0) {
                throw new Exception("转线下审核发起失败！");
            }

        } catch (Exception e) {
            throw new Exception("转线下审核发起失败！");
        }

        return CommonResult.ok("转线下审核发起成功");
    }


    /**
     * 协作审核申请
     *
     * @param data          协作审核申请数据
     * @param bindingResult 是否为空判断
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public CommonResult collaborateApply(collaborateApplyRequest data, BindingResult bindingResult) throws Exception {
        try {
            if (bindingResult.hasErrors()) {
                String st = paramUtils.getParamError(bindingResult);
                return CommonResult.fail(st);
            }

            //已关单 已取消 已完成的单子不能提交转单申请
            //获取订单 判断当前订单是否是待接单状态
            RepairRecord recordData = repairRecordService.getRepairById(data.getRecordId());
            if (recordData == null) {
                return CommonResult.fail("订单不存在，申请失败");
            }

            /**
             * 2023-09-27 发起协作审核并审核后不允许再次发起审核
             * 获取协作审核数据
             */
            RepairCollaborateRecord collaborateRecord = repairCollaborateRecordService.getRepairNeByRecordId(data.getRecordId());
            if (collaborateRecord != null) {
                return CommonResult.fail("该订单已发起协作审核，请勿重复操作");
            }

            if (recordData.getMaintenanceState() == eRecordStatu.Collaborate.getValue()) {
                return CommonResult.fail("该订单已发起协作审核，请勿重复操作");
            }

            if (recordData.getMaintenanceState() != eRecordStatu.Dispatch.getValue()) {
                return CommonResult.fail("待接单的订单才能进行协作申请");
            }

            //协作人中不能包含申请人
            long count = data.getCollaborator().stream().filter(e -> e.equals(data.getUserId())).count();
            if (count > 0) {
                return CommonResult.fail("协作人中不能包含当前申请人");
            }

            RepairCollaborateRecord rcr = new RepairCollaborateRecord();
            rcr.setRecordId(data.getRecordId());
            rcr.setVoice(data.getVoice());
            rcr.setVoiceLength(data.getVoiceLength());
            rcr.setRemark(data.getRemark());
            rcr.setUserId(data.getUserId());
            rcr.setApprovalStatu(2);
            rcr.setCollaborator(StringUtils.join(data.getCollaborator(), ','));

            int result = repairCollaborateRecordService.insertRepairCollaborateRecord(rcr);
            if (result <= 0) {
                throw new Exception("申请失败！");
            }

            recordData.setMaintenanceState(eRecordStatu.Collaborate.getValue());
            int updateRecord = repairRecordService.updateRepairRecord(recordData);
            if (updateRecord <= 0) {
                throw new Exception("申请失败！");
            }

            //给郭班长和后勤发消息
            List<Integer> userZZ = new ArrayList<>();
            userZZ.add(2);
            userZZ.add(3);
            List<RepairUser> users = repairUserService.getRepairByUserZZ(userZZ, recordData.getSchoolId());
            List<RepairSystemMessages> rsms = new ArrayList<>();
            for (RepairUser user : users) {
                RepairSystemMessages rsm = new RepairSystemMessages();
                rsm.setIsRead(0);
                rsm.setRecordId(data.getRecordId());
                rsm.setRecipientId(user.getId());
                rsm.setContent("您有一个审核工单，请尽快处理!");
                rsms.add(rsm);
            }

            boolean insertRsm = repairSystemMessagesService.inserBatchSystemMessage(rsms);
            if (!insertRsm) {
                throw new Exception("转单审核发起失败！");
            }

            //添加跟踪记录
            RepairTrackRecord rtr = new RepairTrackRecord();
            rtr.setRecordId(data.getRecordId());
            rtr.setMaintenanceState(eRecordStatu.Collaborate.getValue());
            rtr.setContent("协作审核申请");
            rtr.setUserId(data.getUserId());
            rtr.setUserZzstr("维修师傅");
            rtr.setVoice(data.getVoice());
            rtr.setVoiceLength(data.getVoiceLength());
            int insertRtr = repairTrackRecordService.insertRepairTrackRecord(rtr);
            if (insertRtr <= 0) {
                throw new Exception("协作审核发起失败");
            }
        } catch (Exception e) {
            throw new Exception("协作审核发起失败！");
        }

        return CommonResult.ok("协作审核发起成功");
    }

    /**
     * 获取工单管理头部报修数量
     *
     * @param schoolId 校区ID
     * @return
     */
    @Override
    public CommonResult queryTeamWorkCount(int schoolId) {
        String dateNow = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        TeamWorkCountVo result = repairRecordService.queryTeamWorkCount(schoolId, dateNow);
        return CommonResult.ok(result);
    }

    /**
     * 获取工单管理头部报修数据
     *
     * @param currentPage 当前页数
     * @param pageCount   一页数据条数
     * @param state       状态
     *                    待接单 1
     *                    维修中 2
     *                    已超时 3
     *                    待审核 4
     *                    已完成 5
     *                    待处理 6
     *                    已关单 7
     * @param schoolId    校区ID
     * @return
     */
    @Override
    public CommonResult queryTeamWorkPage(int currentPage, int pageCount, int state, int schoolId) {
        PageUtils<RepairTechnicianVo> result = null;
        String dateNow = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        switch (state) {
            case 1:
                result = repairRecordService.queryTeamWorkPending(currentPage, pageCount, schoolId, dateNow);
                break;
            case 2:
                result = repairRecordService.queryTeamWorkMaintenance(currentPage, pageCount, schoolId, dateNow);
                break;
            case 3:
                result = repairRecordService.queryTeamWorkTimeout(currentPage, pageCount, schoolId, dateNow);
                break;
            case 4:
                result = repairRecordService.queryTeamWorkExamine(currentPage, pageCount, schoolId);
                break;
            case 5:
                result = repairRecordService.queryTeamWorkFinished(currentPage, pageCount, schoolId);
                break;
            case 6:
                result = repairRecordService.queryTeamWorkLogistics(currentPage, pageCount, schoolId);
                break;
            case 7:
                result = repairRecordService.queryTeamWorkClosed(currentPage, pageCount, schoolId);
                break;
            case 8:
                result = repairRecordService.queryTeamWorkOffline(currentPage, pageCount, schoolId);
                break;
            default:
                break;
        }

        //2023-10-09 A-jax 添加获取耗材记录详情方法
        if (result.getList().size() > 0) {
            List<Integer> recordIds = result.getList().stream().map(RepairTechnicianVo::getId).collect(Collectors.toList());
            List<RepairConsumables> consumables = repairConsumablesService.getRepairsByRecordIds(recordIds);
            for (RepairTechnicianVo data : result.getList()) {
                List<RepairConsumables> datas = consumables.stream().filter(e -> e.getRecordId().equals(data.getId())).collect(Collectors.toList());
                data.setGoodsList(datas);
            }
        }

        return CommonResult.ok(result);
    }

//    /**
//     * 获取打印数据
//     */
//    @Override
//    public CommonResult queryTeamWorkPage(int currentPage, int pageCount, int state, int schoolId) {
//        return CommonResult.ok("");
//    }
}

