package cn.cslg.pas.service; import cn.cslg.pas.common.JsonPage; import cn.cslg.pas.common.model.dto.QueryQrtzTaskLogsDTO; import cn.cslg.pas.common.model.dto.TaskAddNewDTO; import cn.cslg.pas.common.model.dto.QueryTaskDTO; import cn.cslg.pas.common.model.vo.*; import cn.cslg.pas.common.utils.*; import cn.cslg.pas.common.utils.SecurityUtils.LoginUtils; import cn.cslg.pas.domain.*; import cn.cslg.pas.domain.asso.AssoProductPatent; import cn.cslg.pas.domain.asso.TaskCondition; import cn.cslg.pas.mapper.TaskMapper; import cn.cslg.pas.common.model.dto.UploadFileDTO; import cn.cslg.pas.service.asso.AssoProductPatentService; import cn.cslg.pas.service.asso.TaskConditionService; import cn.cslg.pas.service.impl.ProductServiceImpl; import cn.cslg.pas.service.upLoadPatent.*; import cn.hutool.core.io.FileUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson2.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.quartz.SchedulerException; import org.springframework.beans.BeanUtils; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.*; import java.util.stream.Collectors; /** *

* 任务表 服务类 *

* * @author 王岩 * @since 2022-02-27 */ @Slf4j @Service @RequiredArgsConstructor(onConstructor_ = {@Lazy}) public class TaskService extends ServiceImpl implements ITaskService { private final FileUtils fileUtils; private final LoginUtils loginUtils; private final RequestService requestService; private final OutInterfaceService outInterfaceService; private final PantentQueueService pantentQueueService; private final ExcutePatentDataExcel excutePatentDataExcel; private final ExcutePatentDataEpo excutePatentDataEpo; private final ExcutePatentDataStar excutePatentDataStar; private final TaskConditionService taskConditionService; private final ProjectService projectService; private final ReportService reportService; private final ProductServiceImpl productService; private final JobService jobService; private final TaskMapper taskMapper; public String getFileUrl(Integer id) { Task task = this.getById(id); return fileUtils.getSystemPath() + task.getUrl(); } public Integer add(UploadFileDTO fileDTO, Integer projectId, Integer productId, Integer total, Integer type, Integer fieldNum, String oldName) { //创建任务表实体类,准备装载数据 ↓ Task task = new Task(); //任务开始时间 task.setStartTime(DateUtils.getDateTime()); //任务状态(0.队列中 1.进行中 2.成功 3.失败) task.setStatus(0); if (projectId != null) { //专题库id task.setProjectId(projectId); } if (productId != null) { //产品id task.setProductId(productId); } //文件名称 task.setFileName(fileDTO.getFileName()); //文件路径 task.setUrl(fileDTO.getPath()); //文件的专利总数量 task.setTotal(total); //文件大小 task.setFileSize(fileDTO.getFileSize()); //任务类型 (1.上传 2导出) task.setType(type); //导入导出字段数量 task.setFieldNum(fieldNum); //创建人id task.setCreateBy(loginUtils.getId()); //文件原始名称 task.setOldName(oldName); //数据入任务表 task.insert(); return task.getId(); } /** * 新增导入专利任务 * * @param fileDTO Excel文件 * @param json 前台参数 * @return 返回任务id */ public Integer addTask2(UploadFileDTO fileDTO, Integer total, String json) { //将前台参数json格式转换为实体类(从中取出专题库id存入任务表) ProjectImportPatentVO projectImportPatentVO = JsonUtils.jsonToPojo(json, ProjectImportPatentVO.class); //创建任务表实体类,准备装载数据 ↓ Task task = new Task(); //任务开始时间 //task.setStartTime(DateUtils.getDateTime()); //任务状态(0.队列中 1.进行中 2.成功 3.失败) task.setStatus(0); if (projectImportPatentVO.getProjectId() != null && projectImportPatentVO.getReportId() == null) { //若是和专题库关联 task.setProjectId(projectImportPatentVO.getProjectId()); } else if (projectImportPatentVO.getProjectId() == null && projectImportPatentVO.getReportId() != null) { //若是和报告关联 task.setReportId(projectImportPatentVO.getReportId()); } else if (projectImportPatentVO.getProductId() != null) { //若是和产品关联 task.setProductId(projectImportPatentVO.getProductId()); } //文件名称 task.setFileName(fileDTO.getFileName()); //文件路径 task.setUrl(fileDTO.getPath()); //文件的专利总数量 task.setTotal(total); //文件大小 task.setFileSize(fileDTO.getFileSize()); //任务类型 (1.上传 2导出) task.setType(1); //导入导出字段数量 task.setFieldNum(0); //创建人id task.setCreateBy(loginUtils.getId()); //文件原始名称 task.setOldName(fileDTO.getName()); //成功条数 task.setSuccessNum(0); //失败条数 task.setDefaultNum(0); //前台参数json格式 task.setPramJson(json); //任务类型1(0普通任务 1定时任务) task.setTaskType(0); task.setAsCompare(projectImportPatentVO.getAsCompare()); //数据入任务表 task.insert(); return task.getId(); } /** * 新增网站导入专利任务 * * @param taskAddNewDTO 前台参数 * @return 返回任务id */ public Integer addTask3(TaskAddNewDTO taskAddNewDTO, Integer total, TaskCondition taskCondition) { //创建任务表实体类,准备装载数据 ↓ Task task = new Task(); //任务开始时间 //task.setStartTime(DateUtils.getDateTime()); //任务状态(0.队列中 1.进行中 2.成功 3.失败) task.setStatus(0); //判断当前导入专利任务是与专题库关联还是与报告关联 if (taskAddNewDTO.getProjectId() != null && taskAddNewDTO.getReportId() == null) { //专题库id task.setProjectId(taskAddNewDTO.getProjectId()); } else if (taskAddNewDTO.getProjectId() == null && taskAddNewDTO.getReportId() != null) { //报告id task.setReportId(taskAddNewDTO.getReportId()); } else if (taskAddNewDTO.getProductId() != null) { //产品id task.setProductId(taskAddNewDTO.getProductId()); } //专利总数量 task.setTotal(total); //任务类型 (1Excel导入 2导出 3欧专局导入 4专利之星导入 5专利号导入) task.setType(taskAddNewDTO.getTaskType2()); //导入导出字段数量 task.setFieldNum(0); //创建人id task.setCreateBy(loginUtils.getId()); //成功条数 task.setSuccessNum(0); //失败条数 task.setDefaultNum(0); //所属任务条件id task.setTaskConditionId(taskCondition.getId()); //与专题库关联信息(自定义字段、文件夹) ProjectImportPatentVO projectImportPatentVO = new ProjectImportPatentVO(); BeanUtils.copyProperties(taskAddNewDTO, projectImportPatentVO); String pramJson = JSONObject.toJSONString(projectImportPatentVO); task.setPramJson(pramJson); //任务类型1(0普通任务 1定时任务) task.setTaskType(taskAddNewDTO.getTaskType()); //是否直接作为对比数据 task.setAsCompare(taskAddNewDTO.getAsCompare()); //数据入任务表 log.info("任务表新增数据"); task.insert(); return task.getId(); } public Task edit(Integer id, Integer status) { Task task = this.getById(id); task.setStatus(status); task.setEndTime(DateUtils.getDateTime()); task.updateById(); return task; } public String delete(Integer id) { Task temp = this.getById(id); this.removeById(id); if (StringUtils.isNotEmpty(temp.getUrl())) { FileUtil.del(fileUtils.getSystemPath(temp.getUrl())); } return Response.success(true); } public void deleteReportTasks(Integer reportId) { this.remove(new LambdaQueryWrapper().eq(Task::getReportId, reportId)); } public void deleteTask(Integer taskId) { log.info("开始处理【删除任务】的业务,参数为:id={}", taskId); //检查任务是否存在,若不存在则提示用户"删除失败,当前任务已不存在,请尝试刷新页面" Task task = this.getById(taskId); if (task == null) { ThrowException.throwXiaoShiException("删除失败,当前任务已不存在,请尝试刷新页面"); } //检查任务状态 //若是已完成或已暂停,则直接删除 if (task.getStatus().equals(2) || task.getStatus().equals(4)) { this.removeById(task); //若是网站导入任务,则还要删除任务条件表对应数据 if (task.getType().equals(3) || task.getType().equals(4)) { taskConditionService.removeById(task.getTaskConditionId()); } } //若是等待中,则先要将生产者队列中的该任务剔除,再删除 //若是进行中,则不允许删除,并提示用户"当前任务正在进行中,无法删除" } public IPage getPageList(TaskVO params) throws IOException { String createName = params.getCreateName(); //如果此次查询是要根据创建人名称查询则👇 if (createName != null && !createName.equals("")) { //远程调用权限系统的根据创建人名称模糊查询创建人ids的接口 String res = outInterfaceService.getPersonIdByNamePCS(createName); List createPersonIds = JSONArray.parseArray(res, Integer.class); //当未查询到时给创建人ids集合赋值唯一元素id=-1,即查空页返回 if (createPersonIds == null || createPersonIds.size() == 0) { createPersonIds = new ArrayList<>(Collections.singletonList(-1)); } params.setCreatePersonIds(createPersonIds); } IPage pageList = baseMapper.getPageList(new Page<>(params.getCurrent(), params.getSize()), params); this.setDataList(pageList.getRecords()); return pageList; } public PageVO queryTasks(QueryTaskDTO queryTaskDTO) throws IOException { log.info("开始处理【查询任务】的业务,参数为:{}", queryTaskDTO); //装载创建人id queryTaskDTO.setCreateId(loginUtils.getId()); //根据创建人名称模糊查询 if (queryTaskDTO.getCreateName() != null && !queryTaskDTO.getCreateName().equals("")) { String res = outInterfaceService.getPersonIdByNamePCS(queryTaskDTO.getCreateName()); List personIds = JSON.parseArray(res, Integer.class); if (personIds.size() == 0) { //若根据该名称查询不到任何人员,则将人员ids集合添加一个元素-1(防止sql报错) personIds.add(-1); } queryTaskDTO.setPersonIds(personIds); } //若有排序,则根据创建时间排 if (queryTaskDTO.getOrderBy() != null) { queryTaskDTO.setOrderBy("create_time"); } //若要分页 if (queryTaskDTO.getCurrent() != null && queryTaskDTO.getSize() != null) { PageHelper.startPage(queryTaskDTO.getCurrent(), queryTaskDTO.getSize()); } List tasks = taskMapper.queryTasks(queryTaskDTO); PageInfo pageInfo = new PageInfo<>(tasks); //装载创建人名称、装载任务名称 if (tasks.size() > 0) { //装载创建人名称 List createPersonIds = tasks.stream().map(QueryTaskVO::getCreateBy).collect(Collectors.toList()); String res = outInterfaceService.getPersonnelByIdsFromPCS(createPersonIds); com.alibaba.fastjson.JSONObject jsonObject = com.alibaba.fastjson.JSONObject.parseObject(res); List personnels = com.alibaba.fastjson.JSONObject.parseArray(jsonObject.getString("data"), Personnel.class); for (QueryTaskVO task : tasks) { for (Personnel personnel : personnels) { if (personnel.getId().equals(task.getCreateBy())) { task.setCreateName(personnel.getPersonnelName()); break; } } } //装载任务名称(专利号/检索式 导入到 某某 专题库/报告中/产品) if (queryTaskDTO.getProjectId() != null) { //若当前查询是查询所有导入专题库的任务,则装载专题库名称 List projectIds = tasks.stream().map(QueryTaskVO::getProjectId).collect(Collectors.toList()); List projects = projectService.list(new LambdaQueryWrapper().in(Project::getId, projectIds)); tasks.forEach(task -> { projects.forEach(project -> { if (task.getProjectId().equals(project.getId())) { task.setProjectName(project.getName()); } }); }); } else if (queryTaskDTO.getReportId() != null) { //若当前查询是查询所有导入报告的任务,则装载报告名称 List reportIds = tasks.stream().map(QueryTaskVO::getReportId).collect(Collectors.toList()); String res2 = outInterfaceService.getReportsFromRMS(reportIds); JSONObject jsonObject2 = JSONObject.parseObject(res2); List reports = JSON.parseArray(jsonObject2.getString("data"), Report.class); tasks.forEach(task -> { reports.forEach(report -> { if (task.getReportId().equals(report.getId())) { task.setReportName(report.getName()); } }); }); } else if (queryTaskDTO.getProductId() != null) { //若当前查询是查询所有导入产品的任务,则装载报告名称 List productIds = tasks.stream().map(QueryTaskVO::getProductId).collect(Collectors.toList()); List products = productService.list(new LambdaQueryWrapper().in(Product::getId, productIds)); tasks.forEach(task -> { products.forEach(product -> { if (task.getProductId().equals(product.getId())) { task.setProductName(product.getProductName()); } }); }); } for (QueryTaskVO task : tasks) { String taskName = ""; //任务名称 String type = ""; //导入方式(Excel/专利号/检索式) String to = ""; //导入到哪里(专题库/报告) String toName = ""; //专题库或报告名称 if (task.getType().equals(5)) { type = "专利号"; } else if (task.getType().equals(3) || task.getType().equals(4)) { type = "检索式"; } else if (task.getType().equals(1)) { type = "Excel"; } if (task.getProjectName() != null) { to = "专题库"; toName = task.getProjectName(); } else if (task.getReportName() != null) { to = "报告"; toName = task.getReportName(); } else if (task.getProductName() != null) { to = "产品"; toName = task.getProductName(); } if (task.getType().equals(2)) { //导出任务 taskName = to + "【" + toName + "】导出 - " + task.getCreateName(); } else { //导入任务 taskName = type + "导入到" + to + "【" + toName + "】 - " + task.getCreateName(); } task.setTaskName(taskName); } } //手动创建分页信息返回对象 PageVO pageVO = new PageVO() .setCurrent(pageInfo.getPageNum()) .setSize(pageInfo.getPageSize()) .setTotal((int) pageInfo.getTotal()) .setRecords(tasks); return pageVO; } public Page queryQrtzTaskLogs(QueryQrtzTaskLogsDTO queryQrtzTaskLogsDTO) { log.info("开始处理【查询定时任务执行日志】的业务,参数为:taskId={}", queryQrtzTaskLogsDTO.getTaskId()); //检查任务是否存在,若不存在则提示用户"该定时任务已不存在,请尝试刷新页面" Task task = this.getById(queryQrtzTaskLogsDTO.getTaskId()); if (task == null) { ThrowException.throwXiaoShiException("该定时任务已不存在,请尝试刷新页面"); } //检查任务是否为定时任务,若不是则提示用户"该任务不为定时任务,暂无更新日志" TaskCondition taskCondition = taskConditionService.getById(task.getTaskConditionId()); if (!taskCondition.getTaskType().equals(1)) { ThrowException.throwXiaoShiException("该任务不为定时任务,暂无更新日志"); } Page pageList = this.page(new Page<>(queryQrtzTaskLogsDTO.getCurrent(), queryQrtzTaskLogsDTO.getSize()), new LambdaQueryWrapper().eq(Task::getTaskConditionId, task.getTaskConditionId()).orderByDesc(Task::getCreateTime)); return pageList; } public void cancelTask(Integer taskId) throws SchedulerException, InterruptedException { log.info("开始处理【取消任务】的业务,参数为:taskId={}", taskId); //检查任务是否存在,若不存在则提示用户"取消任务失败,当前任务已不存在,请尝试刷新页面" Task task = this.getById(taskId); if (task == null) { ThrowException.throwXiaoShiException("取消任务失败,当前任务已不存在,请尝试刷新页面"); return; } //检查任务状态是否为已完成(普通任务),若是则提示用户"取消任务失败,已完成的任务无法取消" if (task.getStatus().equals(2) && task.getTaskType().equals(0)) { ThrowException.throwXiaoShiException("取消任务失败,已完成的任务无法取消"); } //若是定时任务(即本次请求目的是取消该定时任务),删除job中的该定时任务条件 if (task.getTaskType().equals(1)) { //删除job中的该定时任务条件 jobService.deleteJob(task.getTaskConditionId()); } //若该任务处于进行中 if (task.getStatus().equals(1)) { //将生产者生产专利中的公共任务状态改为暂停 if (task.getType() == 1) { excutePatentDataExcel.setTaskStatus(taskId, 4); } else if (task.getType() == 3) { excutePatentDataEpo.setTaskStatus(taskId, 4); } else if (task.getType() == 4) { excutePatentDataStar.setTaskStatus(taskId, 4); } if (task.getType().equals(3) || task.getType().equals(4)) { Thread.sleep(500); //将专利各部分装载线程队列中该任务的专利清空 pantentQueueService.setQueueRemoveTasks(taskId); } Thread.sleep(1000); //将消费者的专利队列中所有该任务的专利剔除 pantentQueueService.consumerQueueRemoveTasks(taskId); } //若该任务处于等待中 if (task.getStatus().equals(0)) { //将生产者任务队列中该任务剔除 pantentQueueService.taskQueueListRemoveTask(Arrays.asList(task.getId())); } //最后修改任务状态为5已取消 Task updateTask = new Task(); updateTask.setId(task.getId()); updateTask.setStatus(5); updateTask.setEndTime(DateUtils.getDateTime()); log.info("os_task表修改任务状态为取消"); this.updateById(updateTask); } public List getQueueList(Integer type, Integer projectId, Integer productId) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(Task::getCreateBy, loginUtils.getId()); queryWrapper.eq(Task::getType, type); queryWrapper.in(Task::getStatus, new ArrayList() {{ add(0); add(1); }}); if (projectId != null) { queryWrapper.eq(Task::getProjectId, projectId); } if (productId != null) { queryWrapper.eq(Task::getProductId, productId); } queryWrapper.orderByAsc(Task::getStartTime); return this.list(queryWrapper); } public Integer add2(Integer projectId, Long fieldNum, Integer total) { Task task = new Task(); task.setStatus(0); task.setProjectId(projectId); task.setType(2); task.setTotal(total); task.setFieldNum(fieldNum.intValue()); task.setCreateBy(loginUtils.getId()); task.setStartTime(DateUtils.getDateTime()); task.insert(); return task.getId(); } public void updateStatus(Integer id, Integer status, Integer endTime) { Task task = this.getById(id); task.setStatus(status); if (endTime != null) { task.setEndTime(endTime); } task.updateById(); } public void updateTime(Integer id, Integer status, Integer endTime, String url, String fileName) { Task task = this.getById(id); task.setStatus(status); task.setEndTime(endTime); task.setFileName(fileName); task.setUrl(url); task.updateById(); } private void setDataList(List taskList) throws IOException { //获得创建人的id集合 List createIds = taskList.stream().map(Task::getCreateBy).collect(Collectors.toList()); //获取专题库负责人对应信息 String jsonObject1 = requestService.getPersonnelFromPCS(createIds); JSONArray jsonArray = JSON.parseArray(jsonObject1); List personnelList = jsonArray.toJavaList(ProjectVO.Personnel.class); for (Task task : taskList) { for (ProjectVO.Personnel personnel : personnelList) { //装载创建人名 if (task.getCreateBy() != null) { if (task.getCreateBy().equals(personnel.getId())) { task.setCreateName(personnel.getPersonnelName()); } } } } } /** * 暂停任务 * * @param taskId 任务id * @return 返回任务状态4,已暂停 */ @Override public Integer pauseTask(Integer taskId) throws InterruptedException { log.info("开始处理【暂停任务】的业务,参数为:taskId={}", taskId); //检查任务是否存在,若不存在则提示用户 "暂停失败,当前任务已不存在,请尝试刷新页面" log.info("检查尝试暂停的任务是否存在"); Task task = this.getById(taskId); if (task == null) { ThrowException.throwXiaoShiException("暂停失败,当前任务已不存在,请尝试刷新页面"); return null; } //检查任务是否处于进行中状态,若不是则提示用户 "暂停失败,当前任务不处于进行中状态,请尝试刷新页面" if (!task.getStatus().equals(1)) { ThrowException.throwXiaoShiException("暂停失败,当前任务不在进行中,请尝试刷新页面"); } //任务表将任务状态修改为4暂停 Task updateTask = new Task(); updateTask.setId(taskId); updateTask.setStatus(4); log.info("任务表修改数据,暂停任务,任务id={}", taskId); boolean updateResult = this.updateById(updateTask); if (!updateResult) { ThrowException.throwXiaoShiException("暂停失败,服务器忙请稍后再试"); } //将检索生产专利时的公共任务状态改为暂停(若还在检索生产,则会结束) if (task.getType() == 1) { //Excel导入 excutePatentDataExcel.setTaskStatus(taskId, 4); } else if (task.getType() == 3) { //欧专局 excutePatentDataEpo.setTaskStatus(taskId, 4); } else if (task.getType() == 4) { //专利之星 excutePatentDataStar.setTaskStatus(taskId, 4); } //若是网站导入任务,则还要将专利各部分装载线程队列中该任务元素清空 if (task.getType().equals(3) || task.getType().equals(4)) { //等上半秒(上述代码虽然使得生产暂停,但是生产暂停前正在存入生产队列的过程中,等2秒使得这些放入消费者队列后再清空消费者) pantentQueueService.setQueueRemoveTasks(taskId); } //等上一秒(上述代码虽然使得生产暂停,但是生产暂停前已生产的专利正在存入消费者队列的过程中,等2秒使得这些放入消费者队列后再清空消费者) Thread.sleep(1500); //将消费者的专利队列中所有该任务的专利剔除 pantentQueueService.consumerQueueRemoveTasks(taskId); log.info("暂停任务成功"); return updateTask.getStatus(); } /** * 继续任务 * * @param taskId 任务id */ @Override public Integer continueTask(Integer taskId) { log.info("开始处理【继续任务】的业务,参数为:taskId={}", taskId); //检查任务是否存在,若不存在则提示用户 "继续任务失败,当前任务已不存在,请尝试刷新页面" log.info("检查尝试继续的任务是否存在"); Task task = this.getById(taskId); if (task == null) { ThrowException.throwXiaoShiException("继续任务失败,当前任务已不存在,请尝试刷新页面"); return null; } //检查任务是否处于暂停状态,若不是则提示用户 "继续任务失败,当前任务未暂停,请尝试刷新页面" if (!task.getStatus().equals(4)) { ThrowException.throwXiaoShiException("继续任务失败,当前任务未暂停,请尝试刷新页面"); } //继续任务(将任务状态改为0即等待中) Task updateTask = new Task(); updateTask.setId(taskId); updateTask.setStatus(0); log.info("任务表修改数据,继续任务,任务id={}", taskId); boolean updateResult = this.updateById(updateTask); if (!updateResult) { ThrowException.throwXiaoShiException("继续任务失败,服务器忙请稍后再试"); } //将当前任务添加进生产者任务队列进行排队,并唤醒生产者线程 pantentQueueService.taskQueueListAddTask(new ArrayList<>(Arrays.asList(taskId))); //将生产者生产专利类中的公共任务状态从暂停改为0 if (task.getType().equals(1) && excutePatentDataExcel.getpTaskId().equals(task.getId())) { excutePatentDataExcel.setTaskStatus(taskId, 0); } else if (task.getType().equals(3) && excutePatentDataEpo.getpTaskId().equals(task.getId())) { excutePatentDataEpo.setTaskStatus(taskId, 0); } else if (task.getType().equals(4) && excutePatentDataStar.getpTaskId().equals(task.getId())) { excutePatentDataStar.setTaskStatus(taskId, 0); } pantentQueueService.awakeTasktch(); log.info("继续任务成功"); return updateTask.getStatus(); } }