ThreadJobService.java 11.5 KB
package com.ruoyi.service;


import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.http.HttpUtil;
import com.ruoyi.common.cache.NowSchedulingCache;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.exception.file.FileUploadException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.driver.domain.Driver;
import com.ruoyi.driver.mapper.DriverMapper;
import com.ruoyi.driver.mapper.DriverSchedulingMapper;
import com.ruoyi.eexception.domain.EquipmentException;
import com.ruoyi.eexception.mapper.EquipmentExceptionMapper;
import com.ruoyi.in.domain.SignIn;
import com.ruoyi.job.DriverJob;
import com.ruoyi.pojo.entity.DriverScheduling;
import com.ruoyi.pojo.response.ResponseSchedulingDto;
import com.ruoyi.utils.ConstDateUtil;
import com.ruoyi.utils.ToolUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.web.client.RestTemplate;
import sun.misc.BASE64Decoder;

import javax.annotation.Resource;
import java.io.*;
import java.util.*;
import java.util.stream.Collectors;

import static com.ruoyi.common.ConstDriverProperties.BC_TYPE_IN;
import static com.ruoyi.common.ConstDriverProperties.BC_TYPE_OUT;
import static com.ruoyi.common.ConstEquipmentProperties.*;
import static com.ruoyi.common.ConstSignInConstSignInProperties.SIGN_NO_EX_NUM;


/**
 * 多线程任务
 *
 * @author 20412
 */
@EnableAsync
@Component
@Slf4j
public class ThreadJobService {

    @Autowired
    private DriverMapper driverMapper;

    @Autowired
    private DriverSchedulingMapper schedulingMapper;

    @Resource
    private NowSchedulingCache nowSchedulingCache;


    @Autowired
    private PlatformTransactionManager transactionManager;

    @Autowired
    private EquipmentExceptionMapper exceptionMapper;

    @Value("${api.headImage}")
    private String headImagePre;

    @Autowired
    private RestTemplate restTemplate;


    /**
     * 异步上传图片
     *
     * @param url
     * @param base64
     * @throws FileUploadException
     * @throws IOException
     */
    @Async
    public void asyncStartUploadBase64Image(String url, String base64) {
        FileOutputStream outputStream = null;
        base64 = base64.replaceAll(" ", "");
        BASE64Decoder decoder = new BASE64Decoder();
        try {
            byte[] photoBase64 = decoder.decodeBuffer(base64);
            for (int i = 0; i < photoBase64.length; ++i) {
                //调整异常数据
                if (photoBase64[i] < 0) {
                    photoBase64[i] += 256;
                }
            }
            outputStream = new FileOutputStream(url);
            outputStream.write(photoBase64);
            outputStream.flush();
            log.info("异步文件上传完毕");
        } catch (Exception e) {
            log.error("文件上传异常:{}", e.getMessage());
        } finally {
            try {
                if (!Objects.isNull(outputStream)) {
                    outputStream.close();
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * 签到人员与签到设备绑定
     *
     * @param deviceId
     * @param jobCodes
     */
    @Async
    public void asyncInsertSignInContactEquipment(String deviceId, List<String> jobCodes) {
        Integer result = driverMapper.insertDriverFace(deviceId, jobCodes);
        log.info("注册设备与员工关联完毕:{}", result);
    }

    @Async
    public void asyncInsertExceptionRecord(SignIn signIn){
        if (!SIGN_NO_EX_NUM.equals(signIn.getExType())){
            EquipmentException exception = new EquipmentException();
            exception.setExType(signIn.getExType());
            exception.setDeviceId(signIn.getDeviceId());
            exception.setJobCode(signIn.getJobCode());
            exception.setStatus(EQUIPMENT_PROCESS_FLOW_COMMIT);
            exception.setImage(signIn.getImage());
            exception.setTitle("打卡异常");
            exception.setRemark(signIn.getRemark());
            exception.setCreateTime(signIn.getCreateTime());
            exceptionMapper.insertEquipmentException(exception);
        }
    }

    @Async
    public void asyncUploadDriverWithUpdateImageUrl(List<Driver> drivers, String token) {
        // 插入数据
        for (Driver driver : drivers) {
            // 开启事务
            TransactionStatus transaction = transactionManager.getTransaction(new DefaultTransactionDefinition());
            try {
                // 插入数据
                insertDriverInfo(token, driver);
                // 提交事务
                transactionManager.commit(transaction);
            } catch (Exception e) {
                // 回滚事务
                transactionManager.rollback(transaction);
                log.error("保存数据是出现了异常:{}", e.getMessage());
            }
        }


    }

    private void insertDriverInfo(String token, Driver driver) {
        String headImageUrl = driver.getImage();
        // 生成文件路径
        String fileName = driver.getJobCode() + ".png";
        String filePath = RuoYiConfig.getUploadPath() + headImagePre + "/" + fileName;
        try {
            fileName = FileUploadUtils.getPathFileName(RuoYiConfig.getUploadPath() + headImagePre, fileName);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        driver.setImage(fileName);
        // 插入数据  如果员工已经存在在不在下载图片
        String imageUrl = DriverJob.getDownloadImageUrl(token, headImageUrl);
        // 获取图片请求地址
        if (StringUtils.isEmpty(imageUrl)) {
            log.error("工号:{},图片缺失,放弃保存员工信息,等待员工图片手动上传。", driver.getJobCode());
            return;
        }
        int result = driverMapper.insertDriver(driver);
        log.debug("插入完毕");
        if (result == 0) {
            return;
        }
        log.info("图片开始上传");
        // 获取图片数据
        InputStream is = getImageInputStreamByUrl(imageUrl);
        // 上传图片
        try {
            uploadImage(is, filePath);
        } catch (IOException e) {
            log.error("工号:{}的人脸图像,上传失败:{}", driver.getJobCode(), e.getMessage());
            is = getImageInputStreamByUrl(imageUrl);
            try {
                uploadImage(is, filePath);
            } catch (IOException ex) {
                log.error("工号:{}的人脸图像,再次上传失败:{}", driver.getJobCode(), e.getMessage());
                throw new RuntimeException(ex);
            }
        }
        log.info("图片上传完毕");
    }

    private InputStream getImageInputStreamByUrl(String imageUrl) {
        return HttpUtil.createGet(imageUrl).execute().bodyStream();
    }

    public static void uploadImage(InputStream is, String filePath) throws IOException {
        if (Objects.isNull(is)) {
            throw new IOException("图片数据不存在");
        }
        File file = new File(filePath + File.separator);
        log.info("文件路径:{}", file.getPath());
        if (!file.exists()) {
            if (!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }
        }
        // 保存图片到本地文件
        FileOutputStream fos = null;
        try {

            fos = new FileOutputStream(file);
            byte[] cbuf = new byte[1024];
            int len;
            while ((len = is.read(cbuf)) != -1) {
                fos.write(cbuf, 0, len);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                if (is != null) {
                    is.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (fos != null) {
                    fos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 检查文件类型
     *
     * @param b
     * @return
     */
    public static String checkImageBase64Format(byte[] b) {
        String type = "";
        if (0x424D == ((b[0] & 0xff) << 8 | (b[1] & 0xff))) {
            type = ".bmp";
        } else if (0x8950 == ((b[0] & 0xff) << 8 | (b[1] & 0xff))) {
            type = ".png";
        } else {
            type = ".jpg";
        }
//        else if (0xFFD8 == ((b[0] & 0xff) << 8 | (b[1] & 0xff))) {
//            type = "jpg";
//        }
        return type;
    }


    /**
     * 保存当天的调度信息
     *
     * @param originSchedulingMap
     */
    @Async
    @Transactional(rollbackFor = {Exception.class})
    public void asyncComputedScheduling(Map<String, List<ResponseSchedulingDto>> originSchedulingMap) {
        //查询当天是否保存过考情表  如果存在则保存
        List<DriverScheduling> dto = schedulingMapper.queryToDay(ConstDateUtil.formatDate("yyyy-MM-dd"), null,null,null);
        // 存入缓存
        if (!CollectionUtil.isEmpty(dto) || originSchedulingMap.size() == 0) {
            String date = ConstDateUtil.formatDate(new Date());
            if (CollectionUtil.isEmpty(nowSchedulingCache.getCacheScheduling(date))){
                Map<String, List<DriverScheduling>> resultMap =new HashMap<>(800);
                handleResultMap(resultMap,dto);
                nowSchedulingCache.setCacheScheduling(date,resultMap);
            }
            return;
        }


        List<DriverScheduling> bcList = new ArrayList<>(1000);
        for (String key : originSchedulingMap.keySet()) {
            List<ResponseSchedulingDto> schedulingList = originSchedulingMap.get(key);
            List<DriverScheduling> nowScheduling = schedulingList.stream()
                    .filter(item -> BC_TYPE_IN.equals(item.getBcType()) || BC_TYPE_OUT.equals(item.getBcType()))
                    .map(item -> {
                        DriverScheduling scheduling = new DriverScheduling();
                        BeanUtils.copyProperties(item, scheduling);
                        return scheduling;
                    }).collect(Collectors.toList());
            if (nowScheduling.size() > 4){
                System.out.println("问题工号:" + key);
            }
            if (nowScheduling.size() % 2 == 1){
                System.out.println("问题工号:" + key);
            }
            bcList.addAll(nowScheduling);
        }
        schedulingMapper.insertRoster(bcList);
    }

    private void handleResultMap(Map<String, List<DriverScheduling>> resultMap, List<DriverScheduling> schedulingList) {
        for (DriverScheduling scheduling : schedulingList) {
            List<DriverScheduling> list = resultMap.get(scheduling.getJobCode());
            if (CollectionUtil.isEmpty(list)){
                resultMap.put(scheduling.getJobCode(),new ArrayList<>(Arrays.asList(scheduling)));
            }else {
                list.add(scheduling);
            }
        }
    }

}