Compare commits

...

7 Commits

Author SHA1 Message Date
李一帆 4def584a0a 清理没有清理干净的代码 2025-08-08 14:18:30 +08:00
李一帆 ed35bee4e7 Merge branch 'refs/heads/feature-concurrency' into cleanup 2025-08-08 14:16:07 +08:00
李一帆 f87abb6cdd 增加任务呼叫过程中出现异常后的处理 2025-08-08 14:15:43 +08:00
李一帆 2ed8f59279 Merge branch 'refs/heads/feature-concurrency' into cleanup
# Conflicts:
#	src/main/java/com/whdc/component/AutoCallTaskScheduled.java
2025-08-08 14:05:43 +08:00
李一帆 3624539d89 调整代码结构 2025-08-08 14:02:39 +08:00
李一帆 f4f5d8b822 清理废弃代码 2025-08-08 13:59:05 +08:00
李一帆 c809762302 并发处理呼叫任务 2025-08-08 13:51:52 +08:00
29 changed files with 297 additions and 1028 deletions

View File

@ -1,59 +0,0 @@
package com.whdc.component;
import com.whdc.service.AutoCallTaskService;
import com.whdc.utils.AutoCallHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
/**
* @author lyf
* @since 2025-06-20
*/
@Component
@Slf4j
@Profile("deprecated")
public class AutoCallScheduled {
@Autowired
private AutoCallTaskService autoCallTaskService;
@Autowired
private AutoCallHelper autoCallHelper;
@PostConstruct
public void getToken() throws Exception {
autoCallHelper.getToken();
}
@Scheduled(cron = "*/3 * * * * ?")
public void step1() {
if (autoCallTaskService.isScheduled()) {
autoCallTaskService.step1GenerateWarnCallMap();
}
}
@Scheduled(cron = "*/3 * * * * ?")
public void step2() {
if (autoCallTaskService.isScheduled()) {
autoCallTaskService.step2GenerateAutoCallByWcm();
}
}
@Scheduled(cron = "*/10 * * * * ?")
public void step3() {
if (autoCallTaskService.isScheduled()) {
autoCallTaskService.step3UploadCallTask();
}
}
@Scheduled(cron = "*/10 * * * * ?")
public void step4() {
if (autoCallTaskService.isScheduled()) {
autoCallTaskService.step4QueryTaskResult();
}
}
}

View File

@ -1,22 +1,26 @@
package com.whdc.component; package com.whdc.component;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.whdc.mapper.AutoCallConfigMapper; import com.whdc.mapper.AutoCallConfigMapper;
import com.whdc.mapper.AutoCallPersonMapper; import com.whdc.mapper.AutoCallPersonMapper;
import com.whdc.model.entity.AutoCallPerson; import com.whdc.model.autocall.AutoCallPerson;
import com.whdc.service.AutoCallTaskService2; import com.whdc.model.autocall.AutoCallTask;
import com.whdc.service.autocall.AutoCallTaskService2;
import com.whdc.utils.AutoCallHelper; import com.whdc.utils.AutoCallHelper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.annotation.Profile; import org.springframework.context.annotation.Profile;
import org.springframework.context.event.EventListener; import org.springframework.context.event.EventListener;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import javax.annotation.PreDestroy;
import java.util.List; import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
/** /**
* @author lyf * @author lyf
@ -35,10 +39,9 @@ public class AutoCallTaskScheduled {
private AutoCallConfigMapper configMapper; private AutoCallConfigMapper configMapper;
@Autowired @Autowired
private AutoCallHelper autoCallHelper; private AutoCallHelper autoCallHelper;
@Autowired
private TaskScheduler taskScheduler;
private AtomicBoolean initialized = new AtomicBoolean(false); private final AtomicBoolean initialized = new AtomicBoolean(false);
private final ExecutorService executorService = Executors.newCachedThreadPool();
@EventListener(ApplicationReadyEvent.class) @EventListener(ApplicationReadyEvent.class)
public void initialize() throws Exception { public void initialize() throws Exception {
@ -48,31 +51,84 @@ public class AutoCallTaskScheduled {
} }
@Scheduled(cron = "*/3 * * * * ?") @Scheduled(cron = "*/3 * * * * ?")
public void generateLoop() { public void generateTaskLoop() {
if (configMapper.isScheduled()) { if (configMapper.isScheduled()) {
autoCallTaskService.step1GenerateTask(); autoCallTaskService.step1GenerateTask();
} }
} }
private static final AtomicBoolean isSubmitting = new AtomicBoolean(false);
@Scheduled(cron = "*/3 * * * * ?") @Scheduled(cron = "*/3 * * * * ?")
public void callLoop() { public void submitTaskLoop() {
if (!isSubmitting.compareAndSet(false, true)) {
return;
}
try {
if (!initialized.get()) { if (!initialized.get()) {
return; return;
} }
if (!configMapper.isScheduled()) { if (!configMapper.isScheduled()) {
return; return;
} }
log.info("AutoCallTaskScheduled callLoop");
List<AutoCallPerson> personList = autoCallTaskService.step2GetOneUnUploadedPerson();
log.info("AutoCallTaskScheduled {}个外呼人, {}", personList.size(), personList.stream().map(AutoCallPerson::getUploadCustName).collect(Collectors.toList()));
try { try {
for (AutoCallPerson person : personList) { List<AutoCallTask> tasks = autoCallTaskService.getTaskMapper().selectList(
if (person.getUploadedTimes() < 2) { new QueryWrapper<AutoCallTask>().eq("status", AutoCallTask.STATUS_GENERATED_AKA_READY_TO_UPLOAD).ne("submit", 1)
autoCallTaskService.step3UploadAICCTask(person); );
} else { for (AutoCallTask task : tasks) {
autoCallTaskService.cancelPerson(person); executorService.submit(new AutoCallTaskThread(task.getId(), autoCallTaskService));
continue; log.info("提交任务 taskId={}", task.getId());
task.setSubmit(1);
autoCallTaskService.getTaskMapper().updateById(task);
} }
} catch (Exception e) {
log.error("提交任务时发生异常", e);
}
} finally {
isSubmitting.set(false);
}
}
@PreDestroy
public void destroy() {
log.info("正在关闭AutoCallTaskScheduled线程池...");
executorService.shutdown();
try {
if (!executorService.awaitTermination(60, java.util.concurrent.TimeUnit.SECONDS)) {
executorService.shutdownNow();
}
} catch (InterruptedException e) {
executorService.shutdownNow();
Thread.currentThread().interrupt();
}
log.info("AutoCallTaskScheduled线程池已关闭");
}
@AllArgsConstructor
@Slf4j
private static class AutoCallTaskThread implements Runnable {
private Integer taskId;
private AutoCallTaskService2 autoCallTaskService;
@Override
public void run() {
try {
List<AutoCallPerson> personList = autoCallTaskService.getPersonMapper().selectList(
new QueryWrapper<AutoCallPerson>().eq("task_id", taskId).orderByAsc("level")
);
if (personList == null || personList.isEmpty()) {
log.warn("任务没有责任人 taskId={}", taskId);
return;
}
for (AutoCallPerson person : personList) {
//任务可以并发了,但是人员没能前一通挂掉后再重呼
while (person.getUploadedTimes() < 2) {
if (AutoCallPerson.TAG_DONE.equals(person.getTag())) break;
//do upload
autoCallTaskService.step3UploadAICCTask(person);
//fetch status
int pendingDuration = 60 * 1000 * 2; int pendingDuration = 60 * 1000 * 2;
int loopGap = 1000; int loopGap = 1000;
boolean success = false; boolean success = false;
@ -81,23 +137,50 @@ public class AutoCallTaskScheduled {
Thread.sleep(loopGap); Thread.sleep(loopGap);
} catch (InterruptedException ignore) { } catch (InterruptedException ignore) {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
return; break;
} }
pendingDuration -= loopGap; pendingDuration -= loopGap;
success = autoCallTaskService.step4QueryAICCTaskResult(person); success = autoCallTaskService.step4QueryAICCTaskResult(person);
if (success) break; if (success) break;
} }
AutoCallPerson _person = autoCallTaskService.getPersonMapper().selectById(person.getId());
person = _person;
if (!success) { if (!success) {
person.setUploadedTimes(personMapper.selectById(person.getId()).getUploadedTimes());
if (person.getUploadedTimes() == 2) { if (person.getUploadedTimes() == 2) {
autoCallTaskService.markPersonDetailQueryTimeout(person); autoCallTaskService.markPersonDetailQueryTimeout(person);
} }
} }
//重呼等15秒
if (AutoCallPerson.TAG_DONE.equals(person.getTag())) break;
try {
Thread.sleep(15*1000);
} catch (InterruptedException ignore) {
Thread.currentThread().interrupt();
break;
}
}
if (!AutoCallPerson.TAG_DONE.equals(person.getTag())) {
autoCallTaskService.cancelPerson(person);
}
} }
} catch (Exception e) { } catch (Exception e) {
log.error("AutoCallTaskScheduled callLoop error", e); log.error("处理任务时发生异常 taskId={}", taskId, e);
AutoCallTask task = autoCallTaskService.getTaskMapper().selectById(taskId);
task.setStatus(AutoCallTask.STATUS_CANCELLED);
List<AutoCallPerson> personList = autoCallTaskService.getPersonMapper().selectList(
new QueryWrapper<AutoCallPerson>()
.eq("task_id", taskId)
.isNull("__remark")
.isNull("__tag")
);
for (AutoCallPerson person : personList) {
person.setStatus(AutoCallPerson.STATUS_CANCELLED);
person.setDetailRemark("请人工处置");
autoCallTaskService.getPersonMapper().updateById(person);
}
}
} }
} }

View File

@ -1,20 +1,15 @@
package com.whdc.controller; package com.whdc.controller.autocall;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.whdc.mapper.WarningResponderMapper; import com.whdc.mapper.AutoCallConfigMapper;
import com.whdc.model.dto.AutoCallDto; import com.whdc.model.dto.AutoCallDto;
import com.whdc.model.dto.CallPutDto;
import com.whdc.model.dto.FindPageDto; import com.whdc.model.dto.FindPageDto;
import com.whdc.model.entity.AutoCallPerson; import com.whdc.model.autocall.AutoCallPerson;
import com.whdc.model.entity.AutoCallTask; import com.whdc.model.autocall.AutoCallTask;
import com.whdc.model.entity.WarnCallMap; import com.whdc.service.autocall.AutoCallApiService;
import com.whdc.model.entity.WarningResponder; import com.whdc.service.autocall.AutoCallTaskService2;
import com.whdc.service.AutoCallApiService; import com.whdc.utils.AICCHelper;
import com.whdc.service.AutoCallTaskService;
import com.whdc.service.AutoCallTaskService2;
import com.whdc.utils.ResultJson; import com.whdc.utils.ResultJson;
import com.whdc.utils.SmsHelper;
import org.apache.poi.util.IOUtils; import org.apache.poi.util.IOUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@ -25,8 +20,6 @@ import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.text.ParseException; import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
/** /**
@ -39,15 +32,11 @@ public class AutoCallController {
@Autowired @Autowired
private AutoCallApiService autoCallApiService; private AutoCallApiService autoCallApiService;
@Autowired @Autowired
private AutoCallTaskService autoCallTaskService;
@Autowired
private AutoCallTaskService2 autoCallTaskService2; private AutoCallTaskService2 autoCallTaskService2;
@Autowired
@GetMapping("/doCallTest") private AICCHelper aiccHelper;
public ResultJson<String> doCallTest() throws ParseException { @Autowired
autoCallTaskService.generateFakeCall(); private AutoCallConfigMapper configMapper;
return ResultJson.ok("resp");
}
@GetMapping("/doGenerateTest2") @GetMapping("/doGenerateTest2")
public ResultJson<String> doGenerateTest2() throws ParseException { public ResultJson<String> doGenerateTest2() throws ParseException {
@ -55,29 +44,14 @@ public class AutoCallController {
return ResultJson.ok("resp"); return ResultJson.ok("resp");
} }
@GetMapping("/doCallTest2")
public ResultJson<List<AutoCallPerson>> doCallTest2() throws ParseException {
List<AutoCallPerson> personList = autoCallTaskService2.doCallTest();
return ResultJson.ok(personList);
}
@GetMapping("/getToken") @GetMapping("/getToken")
public ResultJson<String> getToken() { public ResultJson<String> getToken() {
return ResultJson.ok(autoCallTaskService.getToken()); return ResultJson.ok(aiccHelper.getToken());
}
@GetMapping("/queryTaskResult")
public ResultJson<String> queryTaskResult(@RequestParam("requestId") String requestId, @RequestParam("custId") String custId) {
return ResultJson.ok(autoCallTaskService.queryTaskResult(requestId, custId));
}
@PostMapping("/page")
public ResultJson<Page<WarnCallMap>> newList(@RequestBody AutoCallDto dto) {
return ResultJson.ok(autoCallApiService.page(dto));
} }
/** /**
* *
*
* @return * @return
*/ */
@GetMapping("/listCallIsNotPass") @GetMapping("/listCallIsNotPass")
@ -87,6 +61,7 @@ public class AutoCallController {
/** /**
* *
*
* @return * @return
*/ */
@GetMapping("/listCallIsNotPassPage") @GetMapping("/listCallIsNotPassPage")
@ -99,19 +74,15 @@ public class AutoCallController {
return ResultJson.ok(autoCallApiService.page2(dto)); return ResultJson.ok(autoCallApiService.page2(dto));
} }
@GetMapping("/listCallIsNotPut")
public ResultJson<List<WarnCallMap>> listCallIsNotPut() {
return ResultJson.ok(autoCallApiService.listCallIsNotPut());
}
@GetMapping("/isEnable") @GetMapping("/isEnable")
public ResultJson<Boolean> isEnable() { public ResultJson<Boolean> isEnable() {
return ResultJson.ok(autoCallTaskService.isEnable()); return ResultJson.ok(configMapper.isEnable());
} }
@GetMapping("/setEnable") @GetMapping("/setEnable")
public ResultJson<Boolean> setEnable(@RequestParam("enable") Boolean enable) { public ResultJson<Boolean> setEnable(@RequestParam("enable") Boolean enable) {
autoCallTaskService.setEnable(enable); configMapper.setEnable(enable);
return ResultJson.ok(true); return ResultJson.ok(true);
} }
@ -120,30 +91,6 @@ public class AutoCallController {
return ResultJson.ok(autoCallTaskService2.manualClose(taskId, personId)); return ResultJson.ok(autoCallTaskService2.manualClose(taskId, personId));
} }
/**
* ID
* @param taskId
* @return
*/
@Deprecated
@GetMapping("/setCallIsPut")
public ResultJson<Boolean> setCallIsPut(@RequestParam("taskId") Integer taskId) {
autoCallTaskService.setCallIsPut(taskId);
return ResultJson.ok(true);
}
/**
*
* @param dto
* @return
*/
@Deprecated
@PostMapping("/setCallIsPutList")
public ResultJson<Boolean> setCallIsPutList(@RequestBody CallPutDto dto) {
autoCallTaskService.setCallIsPutList(dto);
return ResultJson.ok(true);
}
@PostMapping("/exportPdf") @PostMapping("/exportPdf")
public void exportPDF(@RequestBody AutoCallDto dto, public void exportPDF(@RequestBody AutoCallDto dto,
HttpServletResponse response, HttpServletResponse response,

View File

@ -2,7 +2,7 @@ package com.whdc.mapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.whdc.model.entity.AutoCallConfig; import com.whdc.model.autocall.AutoCallConfig;
/** /**
* @author lyf * @author lyf
@ -18,6 +18,17 @@ public interface AutoCallConfigMapper extends BaseMapper<AutoCallConfig> {
return config != null && "1".equals(config.getValue()); return config != null && "1".equals(config.getValue());
} }
default void setEnable(Boolean enable) {
AutoCallConfig config = new AutoCallConfig();
config.setKey("enable");
config.setValue(enable ? "1" : "0");
update(
config,
new QueryWrapper<AutoCallConfig>()
.eq("key", "enable")
);
}
default boolean isScheduled() { default boolean isScheduled() {
AutoCallConfig config = selectOne( AutoCallConfig config = selectOne(
new QueryWrapper<AutoCallConfig>() new QueryWrapper<AutoCallConfig>()

View File

@ -2,7 +2,7 @@ package com.whdc.mapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.whdc.model.entity.AutoCall; import com.whdc.model.autocall.AutoCall;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
import java.util.Date; import java.util.Date;

View File

@ -2,7 +2,7 @@ package com.whdc.mapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.whdc.model.entity.AutoCallPerson; import com.whdc.model.autocall.AutoCallPerson;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
import java.util.List; import java.util.List;

View File

@ -2,7 +2,7 @@ package com.whdc.mapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.whdc.model.entity.AutoCallTask; import com.whdc.model.autocall.AutoCallTask;
import com.whdc.model.entity.QXWarning; import com.whdc.model.entity.QXWarning;
import org.apache.ibatis.annotations.Select; import org.apache.ibatis.annotations.Select;

View File

@ -1,57 +0,0 @@
package com.whdc.mapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.whdc.model.entity.QXWarning;
import com.whdc.model.entity.WarnCallMap;
import java.util.List;
/**
* @author lyf
* @since 2025-06-19
*/
public interface WarnCallMapMapper extends BaseMapper<WarnCallMap> {
List<QXWarning> listWarnsThatNotGeneratedWcm();
default List<WarnCallMap> listUnGeneratedWcm() {
return selectList(
new QueryWrapper<WarnCallMap>()
.eq("should_generate", 1)
.eq("generated", 0)
.eq("err_step", 0)
.orderByAsc("id")
);
}
default List<WarnCallMap> listUnUploadedWcm() {
return selectList(
new QueryWrapper<WarnCallMap>()
.eq("generated", 1)
.eq("uploaded", 0)
.eq("err_step", 0)
.orderByAsc("id")
);
}
default List<WarnCallMap> listUnCalledWcm() {
return selectList(
new QueryWrapper<WarnCallMap>()
.eq("uploaded", 1)
.eq("called", 0)
.eq("err_step", 0)
.orderByAsc("id")
);
}
default List<WarnCallMap> listCallIsNotPutWcm() {
return selectList(
new QueryWrapper<WarnCallMap>()
.eq("uploaded", 1)
.eq("called", 1)
.eq("call_is_put", 0)
.eq("err_step", 0)
.orderByDesc("id")
);
}
}

View File

@ -1,4 +1,4 @@
package com.whdc.model.entity; package com.whdc.model.autocall;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField;

View File

@ -1,4 +1,4 @@
package com.whdc.model.entity; package com.whdc.model.autocall;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data; import lombok.Data;

View File

@ -1,4 +1,4 @@
package com.whdc.model.entity; package com.whdc.model.autocall;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField;
@ -24,6 +24,7 @@ public class AutoCallPerson {
public static final int STATUS_MANUAL_CLOSE = 6; public static final int STATUS_MANUAL_CLOSE = 6;
public static final int ERRCODE_ENCODE = 1; public static final int ERRCODE_ENCODE = 1;
public static final int ERRCODE_UPLOAD_FAIL = 2; public static final int ERRCODE_UPLOAD_FAIL = 2;
public static final String TAG_DONE = "已知晓";
@TableId(value = "ID", type = IdType.AUTO) @TableId(value = "ID", type = IdType.AUTO)
private Integer id; private Integer id;

View File

@ -1,4 +1,4 @@
package com.whdc.model.entity; package com.whdc.model.autocall;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField;
@ -19,7 +19,7 @@ import java.util.List;
public class AutoCallTask { public class AutoCallTask {
public static final int STATUS_DEFAULT = 0; // 不生成 public static final int STATUS_DEFAULT = 0; // 不生成
public static final int STATUS_SHOULD_GENERATE = 1; public static final int STATUS_SHOULD_GENERATE = 1;
public static final int STATUS_GENERATED = 2; public static final int STATUS_GENERATED_AKA_READY_TO_UPLOAD = 2;
public static final int STATUS_ANY_SUCCESS = 3; public static final int STATUS_ANY_SUCCESS = 3;
public static final int STATUS_ALL_FAIL = 4; public static final int STATUS_ALL_FAIL = 4;
public static final int STATUS_CANCELLED = 5; public static final int STATUS_CANCELLED = 5;
@ -50,6 +50,8 @@ public class AutoCallTask {
private String warnContent; private String warnContent;
@TableField(value = "__tag") @TableField(value = "__tag")
private String tag; //话术识别:未识别,已知晓 private String tag; //话术识别:未识别,已知晓
@TableField(value = "submit")
private Integer submit; //是否已提交线程池default 0
@TableField(value = "_create_tm") @TableField(value = "_create_tm")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")

View File

@ -1,4 +1,4 @@
package com.whdc.model.entity.autocall; package com.whdc.model.autocall.aicc;
import com.alibaba.fastjson.annotation.JSONField; import com.alibaba.fastjson.annotation.JSONField;

View File

@ -1,4 +1,4 @@
package com.whdc.model.entity.autocall; package com.whdc.model.autocall.aicc;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;

View File

@ -1,4 +1,4 @@
package com.whdc.model.entity.autocall; package com.whdc.model.autocall.aicc;
import lombok.Data; import lombok.Data;

View File

@ -1,4 +1,4 @@
package com.whdc.model.entity.autocall; package com.whdc.model.autocall.aicc;
import lombok.Data; import lombok.Data;

View File

@ -1,4 +1,4 @@
package com.whdc.model.entity.autocall; package com.whdc.model.autocall.aicc;
import com.alibaba.fastjson.annotation.JSONField; import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data; import lombok.Data;

View File

@ -1,73 +0,0 @@
package com.whdc.model.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.util.Date;
import java.util.List;
/**
* @author lyf
* @since 2025-06-19
*/
@Data
@TableName("FXKH_TXL.WARN_CALL_MAP")
public class WarnCallMap {
/*
newwarnId,shouldGenerate,cnnm,requestId,custId,custName,warnName,warnTm,warnLevel,callContent,createTm
autoCallgenerated
uploaduploadRespMsg,uploaded
querycallIsPut,called
*/
@TableId(value = "ID", type = IdType.AUTO)
private Integer id;
@TableField(value = "warn_id")
private Integer warnId; //not null
@TableField(value = "should_generate")
private Integer shouldGenerate; //0:不生成1:生成, not null
@TableField(value = "generated")
private Integer generated; //0:未生成1:已生成, default 0
@TableField(value = "uploaded")
private Integer uploaded; //0:未上传1:已上传, default 0
@TableField(value = "cnnm")
private String cnnm;
@TableField(value = "upload_resp_msg")
private String uploadRespMsg;
@TableField(value = "request_id")
private String requestId; //任务名作为参数的taskName
@TableField(value = "cust_id")
private String custId; //联系人id
@TableField(value = "cust_name")
private String custName; //联系人
@TableField(value = "call_is_put")
private Integer callIsPut; //0:未接通1:已接通, default 0
@TableField(value = "called")
private Integer called; //0:未拨打1:已拨打, default 0
@TableField(value = "err_step")
private Integer errStep; //0:初始化1:step1出错, 以此类推,default 0
@TableField(value = "warn_name")
private String warnName;
@TableField(value = "warn_tm")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
private Date warnTm;
@TableField(value = "warn_level")
private String warnLevel;
@TableField(value = "call_content")
private String warnContent;
@TableField(value = "_create_tm")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
private Date createTm;
@TableField(value = "_remark")
private String remark;
@TableField(exist = false)
private List<AutoCall> callList;
}

View File

@ -1,522 +0,0 @@
package com.whdc.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.whdc.mapper.*;
import com.whdc.model.dto.CallPutDto;
import com.whdc.model.entity.*;
import com.whdc.model.entity.autocall.AICCCallRespDetail;
import com.whdc.model.entity.autocall.AICCCallRespWrapper;
import com.whdc.model.entity.autocall.AICCUploadTask;
import com.whdc.model.entity.autocall.AICCCallRespTask;
import com.whdc.utils.AutoCallHelper;
import com.whdc.utils.SmsHelper;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
import static com.whdc.model.entity.AutoCallTask.STATUS_MANUAL_CLOSE;
/**
* @author lyf
* @since 2025-06-14
*/
@Service
@Slf4j
public class AutoCallTaskService {
private static final String[] excludeNames = new String[]{"高新", "开发", "自治", "技术", "旅游", "管理", "工业", "产业", "示范"};
private static final AtomicBoolean isCalling = new AtomicBoolean(false);
@Autowired
private AutoCallTaskMapper autoCallTaskMapper;
@Autowired
private WarningResponderMapper warningResponderMapper;
@Autowired
private QXWarningMapper qxWarningMapper;
@Autowired
private AutoCallMapper autoCallMapper;
@Autowired
private AutoCallConfigMapper configMapper;
@Autowired
private WarnCallMapMapper warnCallMapMapper;
@Autowired
private AutoCallHelper autoCallHelper;
@Autowired
private SmsHelper smsHelper;
@Value("${autocall.processId}")
private String processId;
@Value("${autocall.callerGroup}")
private String callerGroup;
@Value("${autocall.secret}")
private String secret;
@Value("${autocall.sysUserId}")
private String sysUserId;
@Transactional
public void generateFakeCall() throws ParseException {
QXWarning warn = qxWarningMapper.selectOne(
new QueryWrapper<QXWarning>()
.orderByDesc("WARNID")
.last("limit 1")
);
warn.setCtnm("恩施州");
warn.setCnnm("咸丰,");
List<WarnCallMap> wcmList = newWcmByWarn(warn);
WarnCallMap wcm = wcmList.get(0);
wcm.setCreateTm(new Date());
warnCallMapMapper.insert(wcm);
}
public void step1GenerateWarnCallMap() {
List<QXWarning> warnList = warnCallMapMapper.listWarnsThatNotGeneratedWcm();
for (QXWarning warn : warnList) {
try {
List<WarnCallMap> wcmList = newWcmByWarn(warn);
for (WarnCallMap wcm : wcmList) {
if (wcm.getCnnm() == null) {
wcm.setErrStep(1);
wcm.setRemark("未找到县区");
}
wcm.setCreateTm(new Date());
warnCallMapMapper.insert(wcm);
}
} catch (Exception e) {
log.error("根据预警生成呼叫失败", e);
}
}
}
public String getToken() {
return autoCallHelper.getToken();
}
private @NotNull List<WarnCallMap> newWcmByWarn(QXWarning warn) throws ParseException {
String cnnmStr = warn.getCnnm();
Integer warnId = warn.getWarnid();
String warnSignalLevel = warn.getWarnSignalLevel();
String content = warn.getContent();
String ctnm = warn.getCtnm();
Date publishTime = warn.getPublishTime();
List<WarnCallMap> wcmList = new ArrayList<>();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日HH时mm分");
// content = "我是省防办智能外呼系统," + content + "如需咨询请拨打02787221781";
content = "我是省防办智能外呼系统," +warn.getCtnm()+sdf.format(warn.getPublishTime()) +"发布暴雨"+warn.getWarnSignalLevel()+"预警信号:"+ content + "如需咨询请拨打02787221781相关信息以短信发送给您。";
if (cnnmStr == null || cnnmStr.trim().isEmpty()) {
WarnCallMap wcm = newWcm(null, warnId, publishTime, ctnm, warnSignalLevel, content);
wcmList.add(wcm);
return wcmList;
}
String[] cnnms = cnnmStr.trim().split(",");
for (String cnnm : cnnms) {
if (cnnm.isEmpty()) continue;
if (publishTime == null) continue;
WarnCallMap wcm = newWcm(cnnm, warnId, publishTime, ctnm, warnSignalLevel, content);
wcmList.add(wcm);
}
return wcmList;
}
private @NotNull WarnCallMap newWcm(String cnnm, Integer warnId, Date publishTime, String ctnm, String warnSignalLevel, String content) throws ParseException {
WarnCallMap wcm = new WarnCallMap();
wcm.setWarnId(warnId);
wcm.setCnnm(cnnm);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
wcm.setWarnTm(publishTime);
wcm.setWarnName(String.format("%s%s%s%s预警", sdf.format(publishTime), ctnm, cnnm, warnSignalLevel));
wcm.setWarnLevel(warnSignalLevel);
wcm.setWarnContent(content);
wcm.setRequestId("hbsl" + new Date().getTime() + cnnm);
if (isEnable()) {
wcm.setShouldGenerate(1);
} else {
wcm.setShouldGenerate(0);
}
return wcm;
}
//为什么wcm和autocall的生成要分开wcm是根据qxwarning生成的自动呼叫可能会暂停避免之后开启会根据早时的qxwarning生成wcm进而呼叫
public void step2GenerateAutoCallByWcm() {
List<WarnCallMap> wcmList = warnCallMapMapper.listUnGeneratedWcm();
for (WarnCallMap wcm : wcmList) {
List<AutoCall> autoCallList = newAutoCall(wcm);
if (autoCallList.size() == 0) {
wcm.setErrStep(2);
wcm.setRemark("未找到责任人");
warnCallMapMapper.updateById(wcm);
return;
}
StringBuilder sb = new StringBuilder();
//将responderId合并为custId
for (AutoCall autoCall : autoCallList) {
sb.append(autoCall.getResponderId()).append("-");
}
sb.deleteCharAt(sb.length() - 1);
String custId = System.currentTimeMillis() + "-" + sb;
//将responderName合并为custName
sb = new StringBuilder();
for (AutoCall autoCall : autoCallList) {
sb.append(autoCall.getResponderName()).append(",");
}
sb.deleteCharAt(sb.length() - 1);
String custName = sb.toString();
wcm.setCustId(custId);
wcm.setCustName(custName);
wcm.setGenerated(1);
Date now = new Date();
autoCallList.forEach(a -> {
a.setCreateTm(now);
autoCallMapper.insert(a);
});
warnCallMapMapper.updateById(wcm);
}
}
private @NotNull List<AutoCall> newAutoCall(WarnCallMap wcm) {
Integer wcmId = wcm.getId();
String cnnm = wcm.getCnnm();
List<AutoCall> existList = autoCallMapper.listByWcmIdAndCnnmOrderByLevelAsc(wcmId, cnnm);
if (existList != null && existList.size() > 0) {
return Collections.emptyList();
}
return newAutoCall(wcmId, cnnm, wcm.getWarnLevel());
}
private @NotNull List<AutoCall> newAutoCall(Integer wcmId, String cnnm, String warnLevelStr) {
//处理行政区划和预警级别橙色预警拨打12level的红色预警只拨打3level的
List<Integer> warnLevel = mapWarnSignalLevel(warnLevelStr);
List<WarningResponder> wrList = listWarningResponderByCnnmAndLevelOrderByLevelAsc(cnnm, warnLevel);
if (wrList.isEmpty()) return Collections.emptyList();
//处理县区包含高新区、开发区等情况
doSomethingWith(cnnm, wrList);
//按level从小到大排序
wrList.sort(Comparator.comparingInt(WarningResponder::getLevel));
List<AutoCall> autoCallList = new ArrayList<>();
for (WarningResponder wr : wrList) {
Integer wrLevel = wr.getLevel();
wr.decryptPhone();
AutoCall autoCall = new AutoCall();
autoCall.setResponderId(wr.getId())
.setResponderName(wr.getName())
.setWcmId(wcmId)
.setLevel(wrLevel)
.setNumber(wr.getPhone());
autoCallList.add(autoCall);
}
return autoCallList;
}
public void step3UploadCallTask() {
if (!isCalling.compareAndSet(false, true)) {
return;
}
try {
//已提交,提交返回内容为“导入成功”,未拨打
List<WarnCallMap> wcmList = warnCallMapMapper.listUnUploadedWcm();
if (wcmList == null || wcmList.isEmpty()) return;
for (WarnCallMap wcm : wcmList) {
Integer wcmId = wcm.getId();
List<AutoCall> autoCallList = autoCallMapper.listByWcmIdAndCnnmOrderByLevelAsc(wcmId, wcm.getCnnm());
if (autoCallList == null || autoCallList.isEmpty()) {
wcm.setErrStep(3);
wcm.setRemark("未找到呼叫列表");
warnCallMapMapper.updateById(wcm);
continue;
}
List<String> numbers = autoCallList.stream()
.map(AutoCall::getNumber)
.collect(Collectors.toList());
AICCUploadTask task = autoCallHelper.newTask(
wcm.getRequestId(),
wcm.getCustId(),
wcm.getCustName(),
wcm.getWarnContent(),
numbers
);
AICCCallRespWrapper<AICCCallRespTask> AICCCallRespWrapper = autoCallHelper.apiUploadCallData(task);
String msg = AICCCallRespWrapper.getResult().getMsg();
wcm.setUploaded(1);
wcm.setUploadRespMsg(msg);
warnCallMapMapper.updateById(wcm);
smsHelper.send(numbers, wcm.getWarnContent());
}
} finally {
isCalling.set(false);
}
}
public void step4QueryTaskResult() {
List<WarnCallMap> wcmList = warnCallMapMapper.listUnCalledWcm();
if (wcmList.isEmpty()) return;
for (WarnCallMap wcm : wcmList) {
Integer wcmId = wcm.getId();
String requestId = wcm.getRequestId();
String custId = wcm.getCustId();
List<AutoCall> autoCallList = autoCallMapper.listByWcmIdAndCnnmOrderByLevelAsc(wcmId, wcm.getCnnm());
if (autoCallList == null || autoCallList.isEmpty()) {
wcm.setErrStep(4);
wcm.setRemark("未找到呼叫列表");
warnCallMapMapper.updateById(wcm);
continue;
}
AICCCallRespWrapper<AICCCallRespDetail> AICCCallRespWrapper = autoCallHelper.apiGetTaskCallDetail(requestId, custId);
if (AICCCallRespWrapper == null || !AICCCallRespWrapper.isSuccess()) {
wcm.setErrStep(4);
wcm.setRemark("请求外呼平台失败");
warnCallMapMapper.updateById(wcm);
continue;
}
//任务不存在
if (AICCCallRespWrapper.getResult() == null
|| AICCCallRespWrapper.getResult().getData() == null
|| AICCCallRespWrapper.getResult().getData().getRecords() == null
|| AICCCallRespWrapper.getResult().getData().getRecords().isEmpty()) {
wcm.setErrStep(4);
wcm.setRemark("外呼平台查询不到任务");
warnCallMapMapper.updateById(wcm);
continue;
}
List<AICCCallRespDetail.Record> records = AICCCallRespWrapper.getResult().getData().getRecords();
boolean anyCalled = true;
boolean anyCallIsPut = false;
for (AICCCallRespDetail.Record record : records) {
if (record.getRemark() == null || record.getRemark().isEmpty()) {
anyCalled = false;
continue;
}
if ("接通".equals(record.getRemark())) anyCallIsPut = true;
AICCCallRespDetail.RawVarListMap rawVarListMap = record.getRawVarListMap();
String number = rawVarListMap.getNumber();
AutoCall call = null;
for (AutoCall a : autoCallList) {
if (a.getNumber().equals(number)) {
call = a;
break;
}
}
copyDataFromDetailToAutoCall(record, call, rawVarListMap);
}
if (!records.isEmpty() && anyCalled) {
wcm.setCalled(1);
warnCallMapMapper.updateById(wcm);
}
for (AutoCall a : autoCallList) {
if (a.getStatus() == null && anyCallIsPut) {
a.setStatus("已呼通其他责任人");
}
autoCallMapper.updateById(a);
}
if (anyCallIsPut) {
wcm.setCallIsPut(1);
warnCallMapMapper.updateById(wcm);
}
}
}
public AICCCallRespWrapper<AICCCallRespDetail> queryTaskResult(String requestId, String custId) {
return autoCallHelper.apiGetTaskCallDetail(requestId, custId);
}
private void copyDataFromDetailToAutoCall(AICCCallRespDetail.Record record, AutoCall call, AICCCallRespDetail.RawVarListMap rawVarListMap) {
if (call != null) {
call.setStatus(record.getRemark());
call.setTalkTimes(record.getTalkTimes());
call.setSipTermCause(rawVarListMap.getSipTermCause());
call.setCaller(rawVarListMap.getCaller());
Date d;
long l;
if (rawVarListMap.getStartringAt() != null) {
d = new Date();
l = Long.parseLong(rawVarListMap.getStartringAt().substring(0, 13));
d.setTime(l);
call.setStartringAt(d);
}
if (rawVarListMap.getConnectedAt() != null) {
d = new Date();
l = Long.parseLong(rawVarListMap.getConnectedAt().substring(0, 13));
d.setTime(l);
call.setConnectedAt(d);
}
if (rawVarListMap.getStartedAt() != null) {
d = new Date();
l = Long.parseLong(rawVarListMap.getStartedAt());
d.setTime(l);
call.setStartedAt(d);
}
if (rawVarListMap.getEndringAt() != null) {
d = new Date();
l = Long.parseLong(rawVarListMap.getEndringAt().substring(0, 13));
d.setTime(l);
call.setEndringAt(d);
}
if (rawVarListMap.getDisconnectedAt() != null) {
d = new Date();
l = Long.parseLong(rawVarListMap.getDisconnectedAt().substring(0, 13));
d.setTime(l);
call.setDisconnectedAt(d);
}
if (rawVarListMap.getStopedAt() != null) {
d = new Date();
l = Long.parseLong(rawVarListMap.getStopedAt());
d.setTime(l);
call.setStopedAt(d);
}
if (rawVarListMap.getLastModify() != null) {
d = new Date();
l = Long.parseLong(rawVarListMap.getLastModify());
d.setTime(l);
call.setLastModify(d);
}
}
}
private List<Integer> mapWarnSignalLevel(String warnSignalLevel) {
/**
* 1 2 3 4
*/
List<Integer> ret = new ArrayList<>();
ret.add(1);
ret.add(2);
ret.add(3);
ret.add(4);
// if ("红色".equals(warnSignalLevel)) {
// ret.add(3);
// } else {
// ret.add(1);
// ret.add(2);
// }
return ret;
}
/*
*/
public void setEnable(Boolean enable) {
AutoCallConfig config = new AutoCallConfig();
config.setKey("enable");
config.setValue(enable ? "1" : "0");
configMapper.update(
config,
new QueryWrapper<AutoCallConfig>()
.eq("key", "enable")
);
}
/*
*/
public boolean isEnable() {
AutoCallConfig config = configMapper.selectOne(
new QueryWrapper<AutoCallConfig>()
.eq("key", "enable")
.last("limit 1")
);
return config != null && "1".equals(config.getValue());
}
public void setCallIsPut(Integer wcmId) {
WarnCallMap wcm = warnCallMapMapper.selectById(wcmId);
wcm.setCalled(1);
wcm.setCallIsPut(1);
warnCallMapMapper.updateById(wcm);
}
/*
*/
public boolean isScheduled() {
AutoCallConfig config = configMapper.selectOne(
new QueryWrapper<AutoCallConfig>()
.eq("key", "schedule")
.last("limit 1")
);
return config != null && "1".equals(config.getValue());
}
private static void doSomethingWith(String cnmm, List<WarningResponder> wrList) {
//预警包含高新等字符,可跳出
boolean skip = false;
for (String excludeName : excludeNames) {
if (cnmm.contains(excludeName)) {
skip = true;
break;
}
}
if (skip) {
return;
}
//预警不包含高新等字符,检查人员,保留不包含高新等字符的人员
Iterator<WarningResponder> iter = wrList.iterator();
while (iter.hasNext()) {
WarningResponder autoCall = iter.next();
boolean anyMatch = false;
for (String excludeName : excludeNames) {
if (autoCall.getCnnm().contains(excludeName)) {
anyMatch = true;
break;
}
}
if (anyMatch) {
iter.remove();
}
}
}
private List<WarningResponder> listWarningResponderByCnnmAndLevelOrderByLevelAsc(String cnnm, List<Integer> levels) {
return warningResponderMapper.listByCnnmAndLevelOrderByLevelAsc(cnnm, levels);
}
@Transactional
public void setCallIsPutList(CallPutDto dto) {
LambdaQueryWrapper<AutoCallTask> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.in(AutoCallTask::getId,dto.getTaskIds());
List<AutoCallTask> autoCallTasks = autoCallTaskMapper.selectList(queryWrapper);
for (AutoCallTask autoCallTask : autoCallTasks) {
//告警任务取消
autoCallTask.setStatus(STATUS_MANUAL_CLOSE);
autoCallTask.setRemark("人工处置");
autoCallTaskMapper.updateById(autoCallTask);
}
}
}

View File

@ -1,4 +1,4 @@
package com.whdc.service; package com.whdc.service.autocall;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@ -25,10 +25,9 @@ import com.itextpdf.layout.properties.TextAlignment;
import com.itextpdf.layout.properties.UnitValue; import com.itextpdf.layout.properties.UnitValue;
import com.whdc.mapper.*; import com.whdc.mapper.*;
import com.whdc.model.dto.AutoCallDto; import com.whdc.model.dto.AutoCallDto;
import com.whdc.model.entity.AutoCall; import com.whdc.model.autocall.AutoCall;
import com.whdc.model.entity.AutoCallPerson; import com.whdc.model.autocall.AutoCallPerson;
import com.whdc.model.entity.AutoCallTask; import com.whdc.model.autocall.AutoCallTask;
import com.whdc.model.entity.WarnCallMap;
import com.whdc.utils.DateUtils; import com.whdc.utils.DateUtils;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -54,8 +53,6 @@ import java.util.List;
public class AutoCallApiService { public class AutoCallApiService {
@Autowired @Autowired
private AutoCallMapper autoCallMapper; private AutoCallMapper autoCallMapper;
@Autowired
private WarnCallMapMapper warnCallMapMapper;
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@ -89,7 +86,7 @@ public class AutoCallApiService {
} else { } else {
query.in("status", query.in("status",
AutoCallTask.STATUS_SHOULD_GENERATE, AutoCallTask.STATUS_SHOULD_GENERATE,
AutoCallTask.STATUS_GENERATED, AutoCallTask.STATUS_GENERATED_AKA_READY_TO_UPLOAD,
AutoCallTask.STATUS_ANY_SUCCESS, AutoCallTask.STATUS_ANY_SUCCESS,
AutoCallTask.STATUS_ALL_FAIL, AutoCallTask.STATUS_ALL_FAIL,
AutoCallTask.STATUS_CANCELLED, AutoCallTask.STATUS_CANCELLED,
@ -130,62 +127,6 @@ public class AutoCallApiService {
return pageResult; return pageResult;
} }
public Page<WarnCallMap> page(AutoCallDto dto) {
Date stm = null;
Date etm = null;
try {
if (dto.getStm() != null && dto.getEtm() != null) {
stm = DateUtils.formatD(dto.getStm(), DateUtils.DATE_PATTERN1);
etm = DateUtils.formatD(dto.getEtm(), DateUtils.DATE_PATTERN1);
}
} catch (ParseException e) {
throw new RuntimeException(e);
}
if (stm != null) stm = DateUtils.standardize(stm, true);
if (etm != null) etm = DateUtils.standardize(etm, false);
QueryWrapper<WarnCallMap> query = new QueryWrapper<WarnCallMap>()
.eq("should_generate", 1)
.orderByDesc("id")
.between("warn_tm", stm, etm);
if (dto.getCallIsPut() != null) {
if (dto.getCallIsPut()) {
query.eq("call_is_put", 1);
} else {
query.eq("call_is_put", 0);
}
}
Page pageParam = dto.getPage().getPage();
Page<WarnCallMap> pageResult = warnCallMapMapper.selectPage(
pageParam,
query
);
List<WarnCallMap> records = pageResult.getRecords();
if (records.size() > 0) {
for (WarnCallMap record : records) {
Integer wcmId = record.getId();
List<AutoCall> autoCallList = autoCallMapper.selectList(
new QueryWrapper<AutoCall>()
.eq("wcm_id", wcmId)
);
record.setCallList(autoCallList);
}
}
return pageResult;
}
public List<WarnCallMap> listCallIsNotPut() {
List<WarnCallMap> wcmList = warnCallMapMapper.listCallIsNotPutWcm();
for (WarnCallMap record : wcmList) {
Integer wcmId = record.getId();
List<AutoCall> autoCallList = autoCallMapper.selectList(
new QueryWrapper<AutoCall>()
.eq("wcm_id", wcmId)
);
record.setCallList(autoCallList);
}
return wcmList;
}
@Autowired @Autowired
private AutoCallTaskMapper taskMapper; private AutoCallTaskMapper taskMapper;
@Autowired @Autowired
@ -224,7 +165,7 @@ public class AutoCallApiService {
} else { } else {
query.in("status", query.in("status",
AutoCallTask.STATUS_SHOULD_GENERATE, AutoCallTask.STATUS_SHOULD_GENERATE,
AutoCallTask.STATUS_GENERATED, AutoCallTask.STATUS_GENERATED_AKA_READY_TO_UPLOAD,
AutoCallTask.STATUS_ANY_SUCCESS, AutoCallTask.STATUS_ANY_SUCCESS,
AutoCallTask.STATUS_ALL_FAIL, AutoCallTask.STATUS_ALL_FAIL,
AutoCallTask.STATUS_CANCELLED, AutoCallTask.STATUS_CANCELLED,
@ -541,7 +482,7 @@ private void addTableHeader(Table table) {
AutoCallTask.STATUS_ALL_FAIL, AutoCallTask.STATUS_ALL_FAIL,
// AutoCallTask.STATUS_SHOULD_GENERATE, // AutoCallTask.STATUS_SHOULD_GENERATE,
// AutoCallTask.STATUS_CANCELLED, // AutoCallTask.STATUS_CANCELLED,
AutoCallTask.STATUS_GENERATED, AutoCallTask.STATUS_GENERATED_AKA_READY_TO_UPLOAD,
AutoCallTask.STATUS_ANY_SUCCESS AutoCallTask.STATUS_ANY_SUCCESS
); );
//__tag is null or __tag != "已知晓" //__tag is null or __tag != "已知晓"
@ -562,9 +503,9 @@ private void addTableHeader(Table table) {
.orderByDesc("id"); .orderByDesc("id");
query.in("status", query.in("status",
AutoCallTask.STATUS_ALL_FAIL, AutoCallTask.STATUS_ALL_FAIL,
AutoCallTask.STATUS_SHOULD_GENERATE, // AutoCallTask.STATUS_SHOULD_GENERATE,
AutoCallTask.STATUS_CANCELLED, AutoCallTask.STATUS_CANCELLED,
AutoCallTask.STATUS_GENERATED AutoCallTask.STATUS_GENERATED_AKA_READY_TO_UPLOAD
); );
Page pageParam = dto.getPage().getPage(); Page pageParam = dto.getPage().getPage();
Page<AutoCallTask> page = taskMapper.selectPage(pageParam, query); Page<AutoCallTask> page = taskMapper.selectPage(pageParam, query);

View File

@ -1,16 +1,16 @@
package com.whdc.service; package com.whdc.service.autocall;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.whdc.mapper.*; import com.whdc.mapper.*;
import com.whdc.model.entity.AutoCallPerson; import com.whdc.model.autocall.AutoCallPerson;
import com.whdc.model.entity.AutoCallTask; import com.whdc.model.autocall.AutoCallTask;
import com.whdc.model.entity.QXWarning; import com.whdc.model.entity.QXWarning;
import com.whdc.model.entity.WarningResponder; import com.whdc.model.entity.WarningResponder;
import com.whdc.model.entity.autocall.AICCCallRespDetail; import com.whdc.model.autocall.aicc.AICCCallRespDetail;
import com.whdc.model.entity.autocall.AICCCallRespTask; import com.whdc.model.autocall.aicc.AICCCallRespTask;
import com.whdc.model.entity.autocall.AICCCallRespWrapper; import com.whdc.model.autocall.aicc.AICCCallRespWrapper;
import com.whdc.model.entity.autocall.AICCUploadTask; import com.whdc.model.autocall.aicc.AICCUploadTask;
import com.whdc.utils.AICCHelper; import com.whdc.utils.AICCHelper;
import com.whdc.utils.SmsHelper; import com.whdc.utils.SmsHelper;
import lombok.Getter; import lombok.Getter;
@ -40,6 +40,7 @@ public class AutoCallTaskService2 {
@Getter @Getter
private AutoCallTaskMapper taskMapper; private AutoCallTaskMapper taskMapper;
@Autowired @Autowired
@Getter
private AutoCallPersonMapper personMapper; private AutoCallPersonMapper personMapper;
@Autowired @Autowired
private AutoCallConfigMapper configMapper; private AutoCallConfigMapper configMapper;
@ -85,48 +86,20 @@ public class AutoCallTaskService2 {
taskMapper.insert(task); taskMapper.insert(task);
generatePerson(task); generatePerson(task);
warn = qxWarningMapper.selectOne( // warn = qxWarningMapper.selectOne(
new QueryWrapper<QXWarning>() // new QueryWrapper<QXWarning>()
.orderByDesc("WARNID") // .orderByDesc("WARNID")
.last("limit 1") // .last("limit 1")
); // );
warn.setCtnm("荆州市"); // warn.setCtnm("荆州市");
warn.setCnnm("竹溪 "); // warn.setCnnm("竹溪 ");
taskList = newTask(warn); // taskList = newTask(warn);
task = taskList.get(0); // task = taskList.get(0);
task.setStatus(0); // task.setStatus(0);
task.setCreateTm(new Date()); // task.setCreateTm(new Date());
task.setWarnCnnm("竹溪 "); // task.setWarnCnnm("竹溪 ");
taskMapper.insert(task); // taskMapper.insert(task);
generatePerson(task); // generatePerson(task);
}
public List<AutoCallPerson> doCallTest() {
List<AutoCallPerson> personList = step2GetOneUnUploadedPerson();
for (AutoCallPerson person : personList) {
step3UploadAICCTask(person);
int pendingDuration = 60 * 1000 * 2;
int loopGap = 1000;
while (true) {
try {
Thread.sleep(loopGap);
} catch (InterruptedException ignore) {
}
pendingDuration -= loopGap;
if (pendingDuration <= 0) break;
boolean f = step4QueryAICCTaskResult(person);
if (f) {
break;
}
}
if (pendingDuration <= 0) {
markPersonDetailQueryTimeout(person);
}
}
return personList;
} }
public void markPersonDetailQueryTimeout(AutoCallPerson person) { public void markPersonDetailQueryTimeout(AutoCallPerson person) {
@ -154,12 +127,11 @@ public class AutoCallTaskService2 {
task.setRemark("未找到县区"); task.setRemark("未找到县区");
} }
task.setCreateTm(now); task.setCreateTm(now);
if (enable && task.getWarnCnnm() != null) {
task.setStatus(AutoCallTask.STATUS_SHOULD_GENERATE);
}
taskMapper.insert(task); taskMapper.insert(task);
if (enable && task.getWarnCnnm() != null) { if (enable && task.getWarnCnnm() != null) {
generatePerson(task); if (generatePerson(task)) {
task.setStatus(AutoCallTask.STATUS_SHOULD_GENERATE);
}
} }
} }
} catch (Exception e) { } catch (Exception e) {
@ -209,7 +181,7 @@ public class AutoCallTaskService2 {
return task; return task;
} }
public void generatePerson(AutoCallTask task) { public boolean generatePerson(AutoCallTask task) {
//切记要设置task的status //切记要设置task的status
List<AutoCallPerson> personList = newPerson(task); List<AutoCallPerson> personList = newPerson(task);
if (personList.size() == 0) { if (personList.size() == 0) {
@ -217,7 +189,7 @@ public class AutoCallTaskService2 {
task.setStatus(AutoCallTask.STATUS_CANCELLED); task.setStatus(AutoCallTask.STATUS_CANCELLED);
task.setErrorCode(AutoCallTask.ERRCODE_NO_PERSON); task.setErrorCode(AutoCallTask.ERRCODE_NO_PERSON);
taskMapper.updateById(task); taskMapper.updateById(task);
return; return false;
} }
TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition()); TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
try { try {
@ -226,7 +198,7 @@ public class AutoCallTaskService2 {
a.setCreateTm(now); a.setCreateTm(now);
personMapper.insert(a); personMapper.insert(a);
}); });
task.setStatus(AutoCallTask.STATUS_GENERATED); task.setStatus(AutoCallTask.STATUS_GENERATED_AKA_READY_TO_UPLOAD);
taskMapper.updateById(task); taskMapper.updateById(task);
transactionManager.commit(status); transactionManager.commit(status);
} catch (Exception e) { } catch (Exception e) {
@ -237,7 +209,9 @@ public class AutoCallTaskService2 {
taskMapper.updateById(task); taskMapper.updateById(task);
log.error("插入外呼责任人异常", e); log.error("插入外呼责任人异常", e);
log.error("{}", JSON.toJSONString(personList)); log.error("{}", JSON.toJSONString(personList));
return false;
} }
return true;
} }
private List<Integer> mapWarnSignalLevel(String warnSignalLevel) { private List<Integer> mapWarnSignalLevel(String warnSignalLevel) {
@ -342,6 +316,7 @@ public class AutoCallTaskService2 {
return personList; return personList;
} }
@Deprecated
public List<AutoCallPerson> step2GetOneUnUploadedPerson() { public List<AutoCallPerson> step2GetOneUnUploadedPerson() {
List<AutoCallPerson> personList = personMapper.listUnUploaded(); List<AutoCallPerson> personList = personMapper.listUnUploaded();
if (personList == null || personList.isEmpty()) return Collections.emptyList(); if (personList == null || personList.isEmpty()) return Collections.emptyList();
@ -358,14 +333,14 @@ public class AutoCallTaskService2 {
return ret; return ret;
} }
private static final AtomicBoolean isCalling = new AtomicBoolean(false); // private static final AtomicBoolean isCalling = new AtomicBoolean(false);
public void step3UploadAICCTask(AutoCallPerson person) { public void step3UploadAICCTask(AutoCallPerson person) {
//切记要设置person的status //切记要设置person的status
if (!isCalling.compareAndSet(false, true)) { // if (!isCalling.compareAndSet(false, true)) {
return; // return;
} // }
try { // try {
if (person.getUploadedTimes() == 2) { if (person.getUploadedTimes() == 2) {
cancelPerson(person); cancelPerson(person);
try { try {
@ -413,9 +388,10 @@ public class AutoCallTaskService2 {
personMapper.updateById(person); personMapper.updateById(person);
smsHelper.send(numbers, person.getSmsContent()); smsHelper.send(numbers, person.getSmsContent());
} }
} finally { // }
isCalling.set(false); // finally {
} // isCalling.set(false);
// }
} }
public boolean step4QueryAICCTaskResult(AutoCallPerson person) { public boolean step4QueryAICCTaskResult(AutoCallPerson person) {

View File

@ -3,7 +3,7 @@ package com.whdc.utils;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference; import com.alibaba.fastjson.TypeReference;
import com.whdc.model.entity.autocall.*; import com.whdc.model.autocall.aicc.*;
import lombok.Setter; import lombok.Setter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -117,7 +117,7 @@ public class AICCHelper {
TypeReference<AICCCallRespWrapper<AICCCallRespTask>> type = new TypeReference<AICCCallRespWrapper<AICCCallRespTask>>() { TypeReference<AICCCallRespWrapper<AICCCallRespTask>> type = new TypeReference<AICCCallRespWrapper<AICCCallRespTask>>() {
}; };
AICCCallRespWrapper<AICCCallRespTask> AICCCallRespWrapper = null; AICCCallRespWrapper<AICCCallRespTask> AICCCallRespWrapper = null;
if (!resp.contains("请求失败") || !resp.contains("网络异常")) { if (!resp.contains("请求失败") && !resp.contains("网络异常")) {
try { try {
AICCCallRespWrapper = JSON.parseObject(resp, type); AICCCallRespWrapper = JSON.parseObject(resp, type);
} catch (Exception ex) { } catch (Exception ex) {
@ -132,7 +132,7 @@ public class AICCHelper {
initToken(); initToken();
headers.put("X-Access-Token", getToken()); headers.put("X-Access-Token", getToken());
resp = httpHelper.postJsonString("https://aicc.cuopen.net:9801/aicc-api/ssb/callout/thirdParty/task/uploadCallData", request.toJSONString(), headers); resp = httpHelper.postJsonString("https://aicc.cuopen.net:9801/aicc-api/ssb/callout/thirdParty/task/uploadCallData", request.toJSONString(), headers);
if (!resp.contains("请求失败") || !resp.contains("网络异常")) { if (!resp.contains("请求失败") && !resp.contains("网络异常")) {
try { try {
AICCCallRespWrapper = JSON.parseObject(resp, type); AICCCallRespWrapper = JSON.parseObject(resp, type);
} catch (Exception ex) { } catch (Exception ex) {

View File

@ -3,7 +3,7 @@ package com.whdc.utils;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference; import com.alibaba.fastjson.TypeReference;
import com.whdc.model.entity.autocall.*; import com.whdc.model.autocall.aicc.*;
import lombok.Setter; import lombok.Setter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;

View File

@ -24,42 +24,42 @@ public class HttpHelper {
@Autowired @Autowired
private OkHttpClient okHttpClient = new OkHttpClient.Builder().build(); private OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
public @NotNull String get(@NotNull String url, @Nullable Map<String, String> params, @Nullable Map<String, String> headers) { // public @NotNull String get(@NotNull String url, @Nullable Map<String, String> params, @Nullable Map<String, String> headers) {
if (url.isEmpty()) { // if (url.isEmpty()) {
return "url为空"; // return "url为空";
} // }
//
Request.Builder requestBuilder = new Request.Builder() // Request.Builder requestBuilder = new Request.Builder()
.url(url) // .url(url)
.get(); // .get();
//
//header // //header
if (headers != null) { // if (headers != null) {
for (Map.Entry<String, String> entry : headers.entrySet()) { // for (Map.Entry<String, String> entry : headers.entrySet()) {
String key = entry.getKey(); // String key = entry.getKey();
String value = entry.getValue(); // String value = entry.getValue();
if (key != null && value != null) { // if (key != null && value != null) {
requestBuilder.header(key, value); // requestBuilder.header(key, value);
} // }
} // }
} // }
//doGet // //doGet
Request request = requestBuilder.build(); // Request request = requestBuilder.build();
//
return doGet(request); // return doGet(request);
} // }
//
private @NotNull String doGet(Request request) { // private @NotNull String doGet(Request request) {
try (Response response = okHttpClient.newCall(request).execute()) { // try (Response response = okHttpClient.newCall(request).execute()) {
if (response.isSuccessful() && response.body() != null) { // if (response.isSuccessful() && response.body() != null) {
return response.body().string(); // return response.body().string();
} else { // } else {
return "请求失败:" + response; // return "请求失败:" + response;
} // }
} catch (IOException e) { // } catch (IOException e) {
return "网络异常:" + e.getMessage(); // return "网络异常:" + e.getMessage();
} // }
} // }
public @NotNull String postJsonString(@NotNull String url, @Nullable String json, @Nullable Map<String, String> headers) { public @NotNull String postJsonString(@NotNull String url, @Nullable String json, @Nullable Map<String, String> headers) {
return postJsonString(url, json, headers, StandardCharsets.UTF_8); return postJsonString(url, json, headers, StandardCharsets.UTF_8);
@ -94,7 +94,13 @@ public class HttpHelper {
} }
Request request = requestBuilder.build(); Request request = requestBuilder.build();
//post //post
return doPost(request); String resp = doPost(request);
if (resp.contains("请求失败") || resp.contains("网络异常")) {
log.warn("请求失败request{}", request);
log.warn("请求失败request header{}", headers);
log.warn("请求失败request payload{}", json);
}
return resp;
} }
public @NotNull String postFormData(@NotNull String url, @Nullable Map<String, Object> params, @Nullable Map<String, String> headers) { public @NotNull String postFormData(@NotNull String url, @Nullable Map<String, Object> params, @Nullable Map<String, String> headers) {
@ -148,7 +154,13 @@ public class HttpHelper {
//post //post
Request request = requestBuilder.build(); Request request = requestBuilder.build();
return doPost(request); String resp = doPost(request);
if (resp.contains("请求失败") || resp.contains("网络异常")) {
log.warn("请求失败request{}", request);
log.warn("请求失败request header{}", headers);
log.warn("请求失败request payload{}", params);
}
return resp;
} }
public @NotNull String postFormUrlEncoded(@NotNull String url, @Nullable Map<String, Object> params, @Nullable Map<String, String> headers) { public @NotNull String postFormUrlEncoded(@NotNull String url, @Nullable Map<String, Object> params, @Nullable Map<String, String> headers) {
@ -198,7 +210,13 @@ public class HttpHelper {
//post //post
Request request = requestBuilder.build(); Request request = requestBuilder.build();
return doPost(request); String resp = doPost(request);
if (resp.contains("请求失败") || resp.contains("网络异常")) {
log.warn("请求失败request{}", request);
log.warn("请求失败request header{}", headers);
log.warn("请求失败request payload{}", params);
}
return resp;
} }
private @NotNull String doPost(Request request) { private @NotNull String doPost(Request request) {
@ -206,6 +224,7 @@ public class HttpHelper {
if (response.isSuccessful() && response.body() != null) { if (response.isSuccessful() && response.body() != null) {
return response.body().string(); return response.body().string();
} else { } else {
log.warn("请求失败response{}", response);
return "请求失败:" + response; return "请求失败:" + response;
} }
} catch (IOException e) { } catch (IOException e) {

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.whdc.mapper.AutoCallMapper"> <mapper namespace="com.whdc.mapper.AutoCallMapper">
<select id="getListByLevelAndStatus" resultType="com.whdc.model.entity.AutoCall"> <select id="getListByLevelAndStatus" resultType="com.whdc.model.autocall.AutoCall">
select * from AUTOCALL A select * from AUTOCALL A
where 1=1 where 1=1
<if test="level != null"> <if test="level != null">

View File

@ -4,7 +4,7 @@
<select id="selectListByTaskId" resultType="com.whdc.model.entity.AutoCallPerson"> <select id="selectListByTaskId" resultType="com.whdc.model.autocall.AutoCallPerson">
select T1.*,T2.POSITION as position from FXKH_TXL.AUTO_CALL_PERSON T1 select T1.*,T2.POSITION as position from FXKH_TXL.AUTO_CALL_PERSON T1
LEFT JOIN FXKH_TXL.SH_ADDRESS_BOOK T2 ON T1.__NUMBER = T2.PHONE LEFT JOIN FXKH_TXL.SH_ADDRESS_BOOK T2 ON T1.__NUMBER = T2.PHONE
where T1.TASK_ID = #{taskId} where T1.TASK_ID = #{taskId}

View File

@ -18,7 +18,7 @@
) )
ORDER BY Q.WARNID ASC; ORDER BY Q.WARNID ASC;
</select> </select>
<select id="getList" resultType="com.whdc.model.entity.AutoCallTask"> <select id="getList" resultType="com.whdc.model.autocall.AutoCallTask">
SELECT SELECT
* *
FROM FROM

View File

@ -18,7 +18,7 @@
) )
ORDER BY Q.WARNID ASC; ORDER BY Q.WARNID ASC;
</select> </select>
<select id="getWCMList" resultType="com.whdc.model.entity.AutoCall"> <select id="getWCMList" resultType="com.whdc.model.autocall.AutoCall">
SELECT SELECT
* *
FROM FROM

View File

@ -3,12 +3,12 @@ package com.whdc.utils;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.whdc.model.entity.AutoCallPerson; import com.whdc.model.autocall.AutoCallPerson;
import com.whdc.model.entity.AutoCallTask; import com.whdc.model.autocall.AutoCallTask;
import com.whdc.model.entity.autocall.AICCCallRespDetail; import com.whdc.model.autocall.aicc.AICCCallRespDetail;
import com.whdc.model.entity.autocall.AICCCallRespTask; import com.whdc.model.autocall.aicc.AICCCallRespTask;
import com.whdc.model.entity.autocall.AICCCallRespWrapper; import com.whdc.model.autocall.aicc.AICCCallRespWrapper;
import com.whdc.model.entity.autocall.AICCUploadTask; import com.whdc.model.autocall.aicc.AICCUploadTask;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;