智能外呼
parent
da00fc2b1a
commit
c20442eae6
|
|
@ -4,7 +4,6 @@ yarn-debug.log*
|
|||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
|
||||
/target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
|
||||
|
|
@ -44,3 +43,4 @@ yus-water/logs/
|
|||
**/target/**
|
||||
|
||||
/img
|
||||
runtime-lib/
|
||||
38
pom.xml
38
pom.xml
|
|
@ -223,23 +223,51 @@
|
|||
<version>4.6.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<version>4.12.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<!-- <plugin>-->
|
||||
<!-- <groupId>org.springframework.boot</groupId>-->
|
||||
<!-- <artifactId>spring-boot-maven-plugin</artifactId>-->
|
||||
<!-- <version>2.7.5</version>-->
|
||||
<!-- <executions>-->
|
||||
<!-- <execution>-->
|
||||
<!-- <id>repackage-executable-jar</id>-->
|
||||
<!-- <goals>-->
|
||||
<!-- <goal>repackage</goal>-->
|
||||
<!-- </goals>-->
|
||||
<!-- <configuration>-->
|
||||
<!-- <skip>true</skip>-->
|
||||
<!-- </configuration>-->
|
||||
<!-- </execution>-->
|
||||
<!-- </executions>-->
|
||||
<!-- </plugin>-->
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>2.7.5</version>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<version>3.5.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>copy-dependencies</id>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
<goal>copy-dependencies</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
<outputDirectory>${project.basedir}/runtime-lib</outputDirectory>
|
||||
<overWriteReleases>false</overWriteReleases>
|
||||
<overWriteSnapshots>false</overWriteSnapshots>
|
||||
<overWriteIfNewer>true</overWriteIfNewer>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
|
|
@ -8,8 +8,13 @@ import org.springframework.boot.SpringApplication;
|
|||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
|
||||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptEngineManager;
|
||||
import javax.script.ScriptException;
|
||||
|
||||
/**
|
||||
* @author 李赛
|
||||
* @date 2022-06-26 0:17
|
||||
|
|
@ -21,6 +26,7 @@ import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
|||
@EnableScheduling
|
||||
@SpringBootApplication
|
||||
@MapperScan("com.whdc.mapper")
|
||||
@EnableTransactionManagement
|
||||
public class FxkhTxlApiApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,59 @@
|
|||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
package com.whdc.component;
|
||||
|
||||
import com.whdc.mapper.AutoCallConfigMapper;
|
||||
import com.whdc.model.entity.AutoCallPerson;
|
||||
import com.whdc.service.AutoCallTaskService2;
|
||||
import com.whdc.utils.AutoCallHelper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.scheduling.TaskScheduler;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author lyf
|
||||
* @since 2025-06-20
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
@Profile("default")
|
||||
public class AutoCallTaskScheduled {
|
||||
|
||||
@Autowired
|
||||
private AutoCallTaskService2 autoCallTaskService;
|
||||
@Autowired
|
||||
private AutoCallConfigMapper configMapper;
|
||||
@Autowired
|
||||
private AutoCallHelper autoCallHelper;
|
||||
@Autowired
|
||||
private TaskScheduler taskScheduler;
|
||||
|
||||
private AtomicBoolean initialized = new AtomicBoolean(false);
|
||||
|
||||
@EventListener(ApplicationReadyEvent.class)
|
||||
public void initialize() throws Exception {
|
||||
autoCallHelper.getToken();
|
||||
initialized.set(true);
|
||||
log.info("AutoCallTaskScheduled初始化完成");
|
||||
}
|
||||
|
||||
@Scheduled(cron = "*/3 * * * * ?")
|
||||
public void generateLoop() {
|
||||
if (configMapper.isScheduled()) {
|
||||
autoCallTaskService.step1GenerateTask();
|
||||
}
|
||||
}
|
||||
|
||||
@Scheduled(cron = "*/3 * * * * ?")
|
||||
public void callLoop() {
|
||||
if (!initialized.get()) {
|
||||
return;
|
||||
}
|
||||
if (!configMapper.isScheduled()) {
|
||||
return;
|
||||
}
|
||||
log.info("AutoCallTaskScheduled callLoop");
|
||||
List<AutoCallPerson> personList = autoCallTaskService.step2GetOneUnUploadedPerson();
|
||||
log.info("AutoCallTaskScheduled {}个外呼人, {}", personList.size(), personList.stream().map(AutoCallPerson::getUploadCustName).collect(Collectors.toList()));
|
||||
try {
|
||||
for (AutoCallPerson person : personList) {
|
||||
autoCallTaskService.step3UploadAICCTask(person);
|
||||
|
||||
int pendingDuration = 60 * 1000 * 2;
|
||||
int loopGap = 1000;
|
||||
boolean success = false;
|
||||
while (pendingDuration > 0) {
|
||||
try {
|
||||
Thread.sleep(loopGap);
|
||||
} catch (InterruptedException ignore) {
|
||||
Thread.currentThread().interrupt();
|
||||
return;
|
||||
}
|
||||
pendingDuration -= loopGap;
|
||||
|
||||
success = autoCallTaskService.step4QueryAICCTaskResult(person);
|
||||
if (success) break;
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
autoCallTaskService.markPersonDetailQueryTimeout(person);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("AutoCallTaskScheduled callLoop error", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -19,6 +19,7 @@ import org.apache.commons.lang3.StringUtils;
|
|||
import org.apache.http.HttpStatus;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
|
|
@ -40,6 +41,7 @@ import static com.whdc.controller.QXWarnController.QX_TEMP_REDIS_KEY;
|
|||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
@Profile("default")
|
||||
public class MyPostConstruct {
|
||||
|
||||
@Autowired
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package com.whdc.config;
|
||||
|
||||
import okhttp3.OkHttpClient;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
|
|
@ -13,7 +15,11 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
|||
@EnableWebMvc
|
||||
@Configuration
|
||||
public class InterceptorConfig implements WebMvcConfigurer {
|
||||
|
||||
@Bean
|
||||
public OkHttpClient okHttpClient() {
|
||||
return new OkHttpClient.Builder()
|
||||
.build();
|
||||
}
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
|
||||
|
|
|
|||
|
|
@ -42,15 +42,15 @@ public class MybatisInterceptor implements Interceptor {
|
|||
continue;
|
||||
}
|
||||
|
||||
if (field.getType().equals(String.class)) {
|
||||
field.setAccessible(true);
|
||||
Object o = field.get(parameter);
|
||||
field.setAccessible(false);
|
||||
String newVal = o == null ? "" : String.valueOf(o).trim();
|
||||
field.setAccessible(true);
|
||||
field.set(parameter, newVal);
|
||||
field.setAccessible(false);
|
||||
}
|
||||
// if (field.getType().equals(String.class)) {
|
||||
// field.setAccessible(true);
|
||||
// Object o = field.get(parameter);
|
||||
// field.setAccessible(false);
|
||||
// String newVal = o == null ? "" : String.valueOf(o).trim();
|
||||
// field.setAccessible(true);
|
||||
// field.set(parameter, newVal);
|
||||
// field.setAccessible(false);
|
||||
// }
|
||||
|
||||
// 注入创建时间
|
||||
if ("createtime".equals(field.getName()) || ("createTime".equals(field.getName()))) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,91 @@
|
|||
package com.whdc.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.whdc.model.dto.AutoCallDto;
|
||||
import com.whdc.model.entity.AutoCallPerson;
|
||||
import com.whdc.model.entity.AutoCallTask;
|
||||
import com.whdc.model.entity.WarnCallMap;
|
||||
import com.whdc.service.AutoCallApiService;
|
||||
import com.whdc.service.AutoCallTaskService;
|
||||
import com.whdc.service.AutoCallTaskService2;
|
||||
import com.whdc.utils.ResultJson;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author lyf
|
||||
* @since 2025-06-17
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/autocall")
|
||||
public class AutoCallController {
|
||||
@Autowired
|
||||
private AutoCallApiService autoCallApiService;
|
||||
@Autowired
|
||||
private AutoCallTaskService autoCallTaskService;
|
||||
@Autowired
|
||||
private AutoCallTaskService2 autoCallTaskService2;
|
||||
|
||||
@GetMapping("/doCallTest")
|
||||
public ResultJson<String> doCallTest() throws ParseException {
|
||||
autoCallTaskService.generateFakeCall();
|
||||
return ResultJson.ok("resp");
|
||||
}
|
||||
|
||||
@GetMapping("/doGenerateTest2")
|
||||
public ResultJson<String> doGenerateTest2() throws ParseException {
|
||||
autoCallTaskService2.generateFakeCall();
|
||||
return ResultJson.ok("resp");
|
||||
}
|
||||
|
||||
@GetMapping("/doCallTest2")
|
||||
public ResultJson<List<AutoCallPerson>> doCallTest2() throws ParseException {
|
||||
List<AutoCallPerson> personList = autoCallTaskService2.doCallTest();
|
||||
return ResultJson.ok(personList);
|
||||
}
|
||||
|
||||
@GetMapping("/getToken")
|
||||
public ResultJson<String> getToken() {
|
||||
return ResultJson.ok(autoCallTaskService.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));
|
||||
}
|
||||
|
||||
@PostMapping("/page2")
|
||||
public ResultJson<Page<AutoCallTask>> page2(@RequestBody AutoCallDto dto) {
|
||||
return ResultJson.ok(autoCallApiService.page2(dto));
|
||||
}
|
||||
|
||||
@GetMapping("/listCallIsNotPut")
|
||||
public ResultJson<List<WarnCallMap>> listCallIsNotPut() {
|
||||
return ResultJson.ok(autoCallApiService.listCallIsNotPut());
|
||||
}
|
||||
|
||||
@GetMapping("/isEnable")
|
||||
public ResultJson<Boolean> isEnable() {
|
||||
return ResultJson.ok(autoCallTaskService.isEnable());
|
||||
}
|
||||
|
||||
@GetMapping("/setEnable")
|
||||
public ResultJson<Boolean> setEnable(@RequestParam("enable") Boolean enable) {
|
||||
autoCallTaskService.setEnable(enable);
|
||||
return ResultJson.ok(true);
|
||||
}
|
||||
|
||||
@GetMapping("/setCallIsPut")
|
||||
public ResultJson<Boolean> setCallIsPut(@RequestParam("taskId") Integer taskId) {
|
||||
autoCallTaskService.setCallIsPut(taskId);
|
||||
return ResultJson.ok(true);
|
||||
}
|
||||
}
|
||||
|
|
@ -7,7 +7,7 @@ import com.whdc.exception.MyException;
|
|||
import com.whdc.model.dto.ApiDto;
|
||||
import com.whdc.model.dto.GroupWarningDto;
|
||||
import com.whdc.model.dto.WarnDppleDto;
|
||||
import com.whdc.model.entity.AddressBookOld;
|
||||
import com.whdc.model.entity.WarningResponder;
|
||||
import com.whdc.model.entity.QXWarning;
|
||||
import com.whdc.model.entity.WarnMsgFB;
|
||||
import com.whdc.model.vo.*;
|
||||
|
|
@ -54,7 +54,7 @@ public class QXWarnController {
|
|||
@Autowired
|
||||
private IAddressBookService addressBookService;
|
||||
@Autowired
|
||||
private IAddressBookOldService addressBookOldService;
|
||||
private IWarningResponderService warningResponderService;
|
||||
@Autowired
|
||||
private IAdinfoService adinfoService;
|
||||
@Autowired
|
||||
|
|
@ -259,9 +259,9 @@ public class QXWarnController {
|
|||
// String adcd = adinfoService.getAdcdByAdnm2(cnnm2);//根据区县的名字找到对应的adcd
|
||||
// System.out.println(adcd);
|
||||
if (StringUtils.isNotBlank(cnnm2)) {
|
||||
List<AddressBookOld> dpples = addressBookOldService.getListByAdnm2(cnnm2);
|
||||
List<WarningResponder> dpples = warningResponderService.getListByAdnm2(cnnm2);
|
||||
System.out.println("dpple个数:" + dpples.size());
|
||||
for (AddressBookOld dpple : dpples) {
|
||||
for (WarningResponder dpple : dpples) {
|
||||
dpple.decryptPhone();
|
||||
WarnDppleVO warndpple = new WarnDppleVO();
|
||||
warndpple.setCtnm(dto.getCtnm());
|
||||
|
|
@ -269,6 +269,7 @@ public class QXWarnController {
|
|||
warndpple.setName(dpple.getName());
|
||||
warndpple.setPosition(dpple.getPosition());
|
||||
warndpple.setPhone(dpple.getPhone());
|
||||
warndpple.setLevel(dpple.getLevel());
|
||||
warnDpples.add(warndpple);
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
package com.whdc.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
||||
import com.whdc.model.entity.AddressBookOld;
|
||||
import com.whdc.model.entity.WarningResponder;
|
||||
import com.whdc.model.entity.QXWarning;
|
||||
import com.whdc.model.entity.WarnMsgFB;
|
||||
import com.whdc.model.vo.ExcelOldDataVo;
|
||||
import com.whdc.service.IAddressBookOldService;
|
||||
import com.whdc.service.IWarningResponderService;
|
||||
import com.whdc.service.IQXWarningService;
|
||||
import com.whdc.service.IWarnMsgFBService;
|
||||
import com.whdc.utils.ExcelCommon;
|
||||
|
|
@ -37,7 +37,7 @@ public class WarnMsgFBController {
|
|||
private IQXWarningService qxService;
|
||||
|
||||
@Autowired
|
||||
private IAddressBookOldService oldService;
|
||||
private IWarningResponderService oldService;
|
||||
//增
|
||||
@ApiOperation(value = "新增")
|
||||
@PostMapping(value = "/add")
|
||||
|
|
@ -76,8 +76,8 @@ public class WarnMsgFBController {
|
|||
List<QXWarning> qxWarns = ExcelCommon.importExcel(file,1, 0, 1, QXWarning.class);
|
||||
Map<String, List<QXWarning>> qxByID = qxWarns.stream().collect(Collectors.groupingBy(QXWarning::getEffectId, Collectors.toList()));
|
||||
|
||||
List<AddressBookOld> olds = oldService.list();
|
||||
Map<String, List<AddressBookOld>> txlByName = olds.stream().collect(Collectors.groupingBy(AddressBookOld::getName, Collectors.toList()));
|
||||
List<WarningResponder> olds = oldService.list();
|
||||
Map<String, List<WarningResponder>> txlByName = olds.stream().collect(Collectors.groupingBy(WarningResponder::getName, Collectors.toList()));
|
||||
|
||||
warnMsgs.forEach(o -> {
|
||||
List<QXWarning> qxWarnings = qxByID.get(o.getEffectId());
|
||||
|
|
@ -87,7 +87,7 @@ public class WarnMsgFBController {
|
|||
.setPublishTime(qxWarning.getPublishTime())
|
||||
.setWarnid(qxWarning.getWarnid());
|
||||
String name = o.getCalledPerson();
|
||||
List<AddressBookOld> txl = txlByName.get(name);
|
||||
List<WarningResponder> txl = txlByName.get(name);
|
||||
if (CollectionUtils.isNotEmpty(txl)){
|
||||
o.setCalledPhone(txl.get(0).getPhone());
|
||||
}else{
|
||||
|
|
|
|||
|
|
@ -4,11 +4,11 @@ import com.alibaba.fastjson.JSON;
|
|||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
|
||||
import com.whdc.exception.MyException;
|
||||
import com.whdc.model.dto.AddressBookOldDto;
|
||||
import com.whdc.model.entity.AddressBookOld;
|
||||
import com.whdc.model.dto.WarningResponderDto;
|
||||
import com.whdc.model.entity.WarningResponder;
|
||||
import com.whdc.model.vo.ExcelDataVo;
|
||||
import com.whdc.model.vo.ExcelOldDataVo;
|
||||
import com.whdc.service.IAddressBookOldService;
|
||||
import com.whdc.service.IWarningResponderService;
|
||||
import com.whdc.utils.ExcelCommon;
|
||||
import com.whdc.utils.ResultJson;
|
||||
import io.swagger.annotations.Api;
|
||||
|
|
@ -44,12 +44,12 @@ import static com.whdc.model.MyConstant.REDIS_KEY;
|
|||
@Slf4j
|
||||
@Api(tags = "web通讯录 - Controller")
|
||||
@RestController
|
||||
@RequestMapping("/addressbookOld")
|
||||
@RequestMapping({"/addressbookOld", "/warningResponder"})
|
||||
@Transactional
|
||||
public class AddressBookOldController {
|
||||
public class WarningResponderController {
|
||||
|
||||
@Autowired
|
||||
private IAddressBookOldService service;
|
||||
private IWarningResponderService service;
|
||||
|
||||
public static final String ADDRESS_BOOK_REDIS_KEY = REDIS_KEY + "addressbookOld";
|
||||
public static final String ADDRESS_BOOK_TEMP_REDIS_KEY = ADDRESS_BOOK_REDIS_KEY + "temp:";
|
||||
|
|
@ -62,23 +62,23 @@ public class AddressBookOldController {
|
|||
@ApiOperation(value = "查询所有联系人")
|
||||
@PostMapping(value = "find")
|
||||
@Cacheable(value = ADDRESS_BOOK_REDIS_KEY, key = "#root.method.name+':'+#dto.toString()")
|
||||
public ResultJson<List<AddressBookOld>> find(@RequestBody AddressBookOldDto dto) {
|
||||
public ResultJson<List<WarningResponder>> find(@RequestBody WarningResponderDto dto) {
|
||||
|
||||
LambdaQueryChainWrapper<AddressBookOld> query = service.lambdaQuery();
|
||||
LambdaQueryChainWrapper<WarningResponder> query = service.lambdaQuery();
|
||||
|
||||
String name = dto.getName();
|
||||
if (StringUtils.isNotBlank(name)){
|
||||
query.like(AddressBookOld::getName, name);
|
||||
query.like(WarningResponder::getName, name);
|
||||
}
|
||||
|
||||
String phone = dto.getPhone();
|
||||
if (StringUtils.isNotBlank(phone)){
|
||||
query.like(AddressBookOld::getPhone, phone);
|
||||
query.like(WarningResponder::getPhone, phone);
|
||||
}
|
||||
|
||||
List<AddressBookOld> data = query.list();
|
||||
List<WarningResponder> data = query.list();
|
||||
|
||||
data = data.stream().map(AddressBookOld::decryptPhone).collect(Collectors.toList());
|
||||
data = data.stream().map(WarningResponder::decryptPhone).collect(Collectors.toList());
|
||||
|
||||
return ResultJson.ok(data);
|
||||
|
||||
|
|
@ -89,13 +89,14 @@ public class AddressBookOldController {
|
|||
@GetMapping(value = "downloadExcel")
|
||||
public void downloadExcel( HttpServletResponse response) {
|
||||
|
||||
List<AddressBookOld> list = service.lambdaQuery()
|
||||
List<WarningResponder> list = service.lambdaQuery()
|
||||
.list();
|
||||
for (AddressBookOld o : list) {
|
||||
for (WarningResponder o : list) {
|
||||
o.decryptPhone();
|
||||
}
|
||||
list.stream().forEach(vo -> vo.setLevelLabel(dictMappingReverse(vo.getLevel())));
|
||||
ExcelCommon.exportExcel(list,
|
||||
null, "防汛抗旱通讯录", AddressBookOld.class, "湖北省防汛抗旱通信录模版" + LocalDateTime.now() + ".xlsx",
|
||||
null, "防汛抗旱通讯录", WarningResponder.class, "湖北省防汛抗旱通信录模版" + LocalDateTime.now() + ".xlsx",
|
||||
response);
|
||||
}
|
||||
|
||||
|
|
@ -103,7 +104,7 @@ public class AddressBookOldController {
|
|||
@PostMapping(value = "getExcelData")
|
||||
public ResultJson<ExcelOldDataVo> getExcelData(MultipartFile file) {
|
||||
|
||||
List<AddressBookOld> appends = ExcelCommon.importExcel(file, 0, 1, AddressBookOld.class);
|
||||
List<WarningResponder> appends = ExcelCommon.importExcel(file, 0, 1, WarningResponder.class);
|
||||
|
||||
ExcelOldDataVo excelDataVo = new ExcelOldDataVo();
|
||||
if (CollectionUtils.isNotEmpty(appends)){
|
||||
|
|
@ -129,7 +130,7 @@ public class AddressBookOldController {
|
|||
if (StringUtils.isBlank(s)){
|
||||
throw new MyException("文件已过期");
|
||||
}
|
||||
List<AddressBookOld> appends = JSON.parseArray(s, AddressBookOld.class);
|
||||
List<WarningResponder> appends = JSON.parseArray(s, WarningResponder.class);
|
||||
|
||||
if (CollectionUtils.isEmpty(appends)) {
|
||||
throw new MyException("文件数据为空");
|
||||
|
|
@ -148,7 +149,7 @@ public class AddressBookOldController {
|
|||
// 新增创建时间
|
||||
Date date = new Date();
|
||||
|
||||
appends = appends.stream().map(vo -> vo.setCreateTime(date).encryptPhone())
|
||||
appends = appends.stream().map(vo -> vo.setCreateTime(date).setLevel(dictMapping(vo.getLevelLabel())).encryptPhone())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (!service.saveBatch(appends)) {
|
||||
|
|
@ -158,4 +159,39 @@ public class AddressBookOldController {
|
|||
return ResultJson.ok("数据新增成功");
|
||||
}
|
||||
|
||||
private Integer dictMapping(String label) {
|
||||
if (label == null) {
|
||||
return null;
|
||||
}
|
||||
switch (label) {
|
||||
case "分管副市(县)长":
|
||||
return 1;
|
||||
case "常务副市(县)长":
|
||||
return 2;
|
||||
case "市(县)长":
|
||||
return 3;
|
||||
case "书记":
|
||||
return 4;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String dictMappingReverse(Integer level) {
|
||||
if (level == null) {
|
||||
return null;
|
||||
}
|
||||
switch (level) {
|
||||
case 1:
|
||||
return "分管副市(县)长";
|
||||
case 2:
|
||||
return "常务副市(县)长";
|
||||
case 3:
|
||||
return "市(县)长";
|
||||
case 4:
|
||||
return "书记";
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
package com.whdc.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.whdc.model.entity.AddressBookOld;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author xusan
|
||||
* @date 2024-05-11
|
||||
*/
|
||||
public interface AddressBookOldMapper extends BaseMapper<AddressBookOld> {
|
||||
|
||||
|
||||
List<AddressBookOld> getListByAdnm2(@Param("adnm")String adnm);
|
||||
// List<AddressBookOld> getListByAdnm(@Param("adnm") String adnm);
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
package com.whdc.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.whdc.model.entity.AutoCallConfig;
|
||||
|
||||
/**
|
||||
* @author lyf
|
||||
* @since 2025-06-19
|
||||
*/
|
||||
public interface AutoCallConfigMapper extends BaseMapper<AutoCallConfig> {
|
||||
default boolean isEnable() {
|
||||
AutoCallConfig config = selectOne(
|
||||
new QueryWrapper<AutoCallConfig>()
|
||||
.eq("key", "enable")
|
||||
.last("limit 1")
|
||||
);
|
||||
return config != null && "1".equals(config.getValue());
|
||||
}
|
||||
|
||||
default boolean isScheduled() {
|
||||
AutoCallConfig config = selectOne(
|
||||
new QueryWrapper<AutoCallConfig>()
|
||||
.eq("key", "schedule")
|
||||
.last("limit 1")
|
||||
);
|
||||
return config != null && "1".equals(config.getValue());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package com.whdc.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.whdc.model.entity.AutoCall;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author lyf
|
||||
* @since 2025-06-14
|
||||
*/
|
||||
public interface AutoCallMapper extends BaseMapper<AutoCall> {
|
||||
List<AutoCall> getListByLevelAndStatus(@Param("level") Integer level, @Param("status") String status, @Param("called") Boolean called, @Param("stm") Date stm, @Param("etm") Date etm);
|
||||
|
||||
default List<AutoCall> listByWcmIdAndCnnmOrderByLevelAsc(Integer wcmId, String cnnm) {
|
||||
return selectList(
|
||||
new QueryWrapper<AutoCall>()
|
||||
.eq("wcm_id", wcmId)
|
||||
.orderByAsc("level")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
package com.whdc.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.whdc.model.entity.AutoCallPerson;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author lyf
|
||||
* @since 2025-07-08
|
||||
*/
|
||||
public interface AutoCallPersonMapper extends BaseMapper<AutoCallPerson> {
|
||||
default List<AutoCallPerson> listUnUploaded() {
|
||||
return selectList(
|
||||
new QueryWrapper<AutoCallPerson>()
|
||||
.eq("status", AutoCallPerson.STATUS_DEFAULT)
|
||||
.orderByAsc("id")
|
||||
);
|
||||
}
|
||||
|
||||
default boolean isAnySuccess(Integer taskId) {
|
||||
return selectCount(
|
||||
new QueryWrapper<AutoCallPerson>()
|
||||
.eq("task_id", taskId)
|
||||
.eq("status", AutoCallPerson.STATUS_PUT)
|
||||
) > 0;
|
||||
}
|
||||
|
||||
default boolean isAllFail(Integer taskId) {
|
||||
long personCnt = selectCount(
|
||||
new QueryWrapper<AutoCallPerson>()
|
||||
.eq("task_id", taskId)
|
||||
);
|
||||
long failCnt = selectCount(
|
||||
new QueryWrapper<AutoCallPerson>()
|
||||
.eq("task_id", taskId)
|
||||
.in("status", AutoCallPerson.STATUS_CALLED, AutoCallPerson.STATUS_CANCELLED)
|
||||
);
|
||||
return personCnt == failCnt;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package com.whdc.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.whdc.model.entity.AutoCallTask;
|
||||
import com.whdc.model.entity.QXWarning;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author lyf
|
||||
* @since 2025-07-08
|
||||
*/
|
||||
public interface AutoCallTaskMapper extends BaseMapper<AutoCallTask> {
|
||||
List<QXWarning> listWarnsThatNotGeneratedTask();
|
||||
|
||||
default List<AutoCallTask> listShouldGenerate() {
|
||||
return selectList(
|
||||
new QueryWrapper<AutoCallTask>()
|
||||
.eq("status", AutoCallTask.STATUS_SHOULD_GENERATE)
|
||||
.orderByAsc("id")
|
||||
);
|
||||
}
|
||||
|
||||
@Select("update auto_call_task set status = #{status} where id = #{taskId}")
|
||||
void setStatus(Integer taskId, int status);
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ import java.util.List;
|
|||
public interface QXWarningMapper extends BaseMapper<QXWarning> {
|
||||
List<QXWarning> find(@Param("dto")QXWarning dto);
|
||||
List<QXWarningVO> findByMsgIsNull();
|
||||
List<QXWarningVO> findByAutoMsgIsNull();
|
||||
|
||||
IPage<QXWarning> page(@Param("page") IPage<QXWarning> page, @Param("dto") GroupWarningDto dto);
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,57 @@
|
|||
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")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package com.whdc.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.whdc.model.entity.WarningResponder;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author xusan
|
||||
* @date 2024-05-11
|
||||
*/
|
||||
public interface WarningResponderMapper extends BaseMapper<WarningResponder> {
|
||||
|
||||
|
||||
List<WarningResponder> getListByAdnm2(@Param("adnm") String adnm);
|
||||
|
||||
List<WarningResponder> listByCnnmAndLevelOrderByLevelAsc(@Param("cnnm") String cnnm, @Param("levels") List<Integer> levels);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package com.whdc.model.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* Description:
|
||||
* Created by XuSan on 2024/7/31.
|
||||
*
|
||||
* @author XuSan
|
||||
* @version 1.0
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class AutoCallDto {
|
||||
|
||||
private String stm;
|
||||
private String etm;
|
||||
|
||||
private Boolean callIsPut;
|
||||
|
||||
private FindPageDto page;
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@ import lombok.Data;
|
|||
* @date 2023年3月20日08:57:22
|
||||
*/
|
||||
@Data
|
||||
public class AddressBookOldDto{
|
||||
public class WarningResponderDto {
|
||||
|
||||
@ApiModelProperty(value = "名字")
|
||||
private String name;
|
||||
|
|
@ -9,6 +9,7 @@ import com.whdc.model.group.Insert;
|
|||
import com.whdc.model.group.Update;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
|
@ -110,4 +111,10 @@ public class AddressBook extends Model<AddressBook> implements Serializable {
|
|||
@ApiModelProperty(value = "openid")
|
||||
private String openid;
|
||||
|
||||
/**
|
||||
* 责任人级别
|
||||
*/
|
||||
@TableField(value = "level")
|
||||
@Schema(description = "1,2,3,4")
|
||||
private Integer level;
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
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 com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author lyf
|
||||
* @since 2025-06-14
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@ApiModel(description = "自动拨号")
|
||||
@TableName("FXKH_TXL.AUTOCALL")
|
||||
@ToString
|
||||
public class AutoCall {
|
||||
/*
|
||||
new的时候必填responderId,responderName,wcmId,createTm
|
||||
query后必填__开头的
|
||||
*/
|
||||
@TableId(value = "ID", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
@TableField(value = "responder_id")
|
||||
@JsonProperty("addressBookOldId")
|
||||
private Integer responderId;
|
||||
@JsonProperty("addressBookOldName")
|
||||
@TableField(value = "responder_name")
|
||||
private String responderName;
|
||||
@TableField(value = "status")
|
||||
private String status;//接通,空号,停机,关机,未接,拒接,占线,呼叫失败,null(空代表未呼叫)
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@TableField(value = "_create_tm")
|
||||
private Date createTm;
|
||||
@TableField(value = "wcm_id")
|
||||
private Integer wcmId;
|
||||
@TableField(value = "level")
|
||||
private Integer level;
|
||||
|
||||
@TableField(value = "__talk_times")
|
||||
private Integer talkTimes;//通话时长,单位秒
|
||||
@TableField(value = "__sip_term_cause")
|
||||
private String sipTermCause; //例如”对方挂机“
|
||||
@TableField(value = "__caller")
|
||||
private String caller;
|
||||
@TableField(value = "__number")
|
||||
private String number;
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@TableField(value = "__startring_at")
|
||||
private Date startringAt; //-3
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@TableField(value = "__connected_at")
|
||||
private Date connectedAt; //-3
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@TableField(value = "__started_at")
|
||||
private Date startedAt;
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@TableField(value = "__endring_at")
|
||||
private Date endringAt; //-3
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@TableField(value = "__disconnected_at")
|
||||
private Date disconnectedAt; //-3
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@TableField(value = "__stopped_at")
|
||||
private Date stopedAt;
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@TableField(value = "__last_modify")
|
||||
private Date lastModify;
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package com.whdc.model.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author lyf
|
||||
* @since 2025-06-19
|
||||
*/
|
||||
@Data
|
||||
@TableName("FXKH_TXL.AUTOCALL_CONFIG")
|
||||
public class AutoCallConfig {
|
||||
private String key;
|
||||
private String value;
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
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.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author lyf
|
||||
* @since 2025-07-08
|
||||
*/
|
||||
@Data
|
||||
public class AutoCallPerson {
|
||||
public static final int STATUS_DEFAULT = 0;
|
||||
public static final int STATUS_UPLOADED = 1;
|
||||
public static final int STATUS_CALLED = 2;
|
||||
public static final int STATUS_PUT = 3;
|
||||
public static final int STATUS_CANCELLED = 4;
|
||||
public static final int ERRCODE_ENCODE = 1;
|
||||
public static final int ERRCODE_UPLOAD_FAIL = 2;
|
||||
|
||||
@TableId(value = "ID", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
@TableField(value = "task_id")
|
||||
private Integer taskId;
|
||||
@TableField(value = "status")
|
||||
private Integer status; //0:未上传 default 0
|
||||
@TableField(value = "level")
|
||||
private Integer level;
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@TableField(value = "_create_tm")
|
||||
private Date createTm;
|
||||
@TableField(value = "error_code")
|
||||
private Integer errorCode; //default 0
|
||||
|
||||
@TableField(value = "__request_id")
|
||||
private String uploadRequestId; //任务名,同时作为参数的taskName,用custId
|
||||
@TableField(value = "__cust_id")
|
||||
private String uploadCustId; //联系人id,用warningResponderId加时间戳毫秒
|
||||
@TableField(value = "__cust_name")
|
||||
private String uploadCustName; //联系人
|
||||
@TableField(value = "__content")
|
||||
private String uploadContent; //联系人
|
||||
@TableField(value = "__number")
|
||||
private String uploadNumber;
|
||||
@TableField(value = "__upload_resp_msg")
|
||||
private String uploadRespMsg; //上传结果
|
||||
@TableField(value = "__remark")
|
||||
private String detailRemark;//接通,空号,停机,关机,未接,拒接,占线,呼叫失败,null(空代表未呼叫)
|
||||
@TableField(value = "__talk_times")
|
||||
private Integer detailTalkTimes;//通话时长,单位秒
|
||||
@TableField(value = "__sip_term_cause")
|
||||
private String detailSipTermCause; //例如”对方挂机“
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@TableField(value = "__startring_at")
|
||||
private Date detailStartringAt; //-3
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@TableField(value = "__connected_at")
|
||||
private Date detailConnectedAt; //-3
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@TableField(value = "__started_at")
|
||||
private Date detailStartedAt;
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@TableField(value = "__endring_at")
|
||||
private Date detailEndringAt; //-3
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@TableField(value = "__disconnected_at")
|
||||
private Date detailDisconnectedAt; //-3
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@TableField(value = "__stopped_at")
|
||||
private Date detailStopedAt;
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@TableField(value = "__last_modify")
|
||||
private Date detailLastModify;
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
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.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author lyf
|
||||
* @since 2025-07-08
|
||||
*/
|
||||
@Data
|
||||
public class AutoCallTask {
|
||||
public static final int STATUS_DEFAULT = 0; // 不生成
|
||||
public static final int STATUS_SHOULD_GENERATE = 1;
|
||||
public static final int STATUS_GENERATED = 2;
|
||||
public static final int STATUS_ANY_SUCCESS = 3;
|
||||
public static final int STATUS_ALL_FAIL = 4;
|
||||
public static final int STATUS_CANCELLED = 5;
|
||||
public static final int ERRCODE_NO_PERSON = 1;
|
||||
public static final int ERRCODE_DB_ERROR = 2;
|
||||
|
||||
@TableId(value = "ID", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
@TableField(value = "warn_id")
|
||||
private Integer warnId; //not null
|
||||
@TableField(value = "status")
|
||||
private Integer status; //0:不拨打 default 0
|
||||
@TableField(value = "error_code")
|
||||
private Integer errorCode; //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 = "WARN_CTNM")
|
||||
private String warnCtnm;
|
||||
@TableField(value = "warn_cnnm")
|
||||
private String warnCnnm;
|
||||
@TableField(value = "warn_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<AutoCallPerson> callList;
|
||||
}
|
||||
|
|
@ -160,4 +160,10 @@ public class ShAddressBook implements Serializable {
|
|||
@TableField(exist = false)
|
||||
List<ShCalls> list;
|
||||
|
||||
/**
|
||||
* 责任人级别
|
||||
*/
|
||||
@TableField(value = "level")
|
||||
@Schema(description = "1,2,3,4")
|
||||
private Integer level;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,73 @@
|
|||
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 {
|
||||
/*
|
||||
new的时候必填warnId,shouldGenerate,cnnm,requestId,custId,custName,warnName,warnTm,warnLevel,callContent,createTm
|
||||
生成autoCall后必填generated
|
||||
upload后必填uploadRespMsg,uploaded
|
||||
query后必填callIsPut,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;
|
||||
|
||||
}
|
||||
|
|
@ -33,10 +33,10 @@ import java.util.UUID;
|
|||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@ApiModel(description = "通讯录")
|
||||
@ApiModel(description = "预警责任人")
|
||||
@TableName("FXKH_TXL.ADDRESS_BOOK_OLD")
|
||||
@Slf4j
|
||||
public class AddressBookOld extends Model<AddressBookOld> implements Serializable {
|
||||
public class WarningResponder extends Model<WarningResponder> implements Serializable {
|
||||
|
||||
|
||||
@TableId(value = "ID",type = IdType.AUTO)
|
||||
|
|
@ -79,7 +79,7 @@ public class AddressBookOld extends Model<AddressBookOld> implements Serializabl
|
|||
@ApiModelProperty(value = "创建时间")
|
||||
private Date createTime;
|
||||
|
||||
public AddressBookOld encryptPhone(){
|
||||
public WarningResponder encryptPhone(){
|
||||
if (StringUtils.isBlank(this.salt)){
|
||||
this.salt = UUID.randomUUID().toString().replaceAll("-", "");
|
||||
}
|
||||
|
|
@ -94,7 +94,7 @@ public class AddressBookOld extends Model<AddressBookOld> implements Serializabl
|
|||
return this;
|
||||
}
|
||||
|
||||
public AddressBookOld decryptPhone(){
|
||||
public WarningResponder decryptPhone(){
|
||||
try {
|
||||
if (StringUtils.isNotBlank(this.phone) && StringUtils.isNotBlank(this.salt)){
|
||||
this.phone = SymmetricEncryption.decrypt(this.phone,this.salt);
|
||||
|
|
@ -105,4 +105,25 @@ public class AddressBookOld extends Model<AddressBookOld> implements Serializabl
|
|||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
WarningResponder a = new WarningResponder();
|
||||
a.setPhone("15623775829");
|
||||
a.encryptPhone();
|
||||
System.out.println(a.salt);
|
||||
System.out.println(a.phone);
|
||||
}
|
||||
|
||||
/**
|
||||
* 责任人级别
|
||||
*/
|
||||
@TableField(value = "LEVEL")
|
||||
private Integer level;
|
||||
|
||||
/**
|
||||
* 责任人级别
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
@Excel(name = "预警呼叫等级", width = 20)
|
||||
private String levelLabel;
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
package com.whdc.model.entity.autocall;
|
||||
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 联通查询任务状态接口返回对象
|
||||
*
|
||||
* @author lyf
|
||||
* @since 2025-06-17
|
||||
*/
|
||||
@lombok.Data
|
||||
@ToString
|
||||
public class AICCCallRespDetail {
|
||||
private Data data;
|
||||
|
||||
@lombok.Data
|
||||
@ToString
|
||||
public static class Data {
|
||||
List<Record> records;
|
||||
}
|
||||
|
||||
@lombok.Data
|
||||
@ToString
|
||||
public static class Record {
|
||||
private String caller; //外呼号码
|
||||
private Long dataTime;
|
||||
private String processId; //机器人id
|
||||
private String sessionDetailId; //联系人id,等同返回值的custId
|
||||
private Integer talkTimes;//通话时长,单位秒
|
||||
private String remark; //中文状态,接通,空号,停机,关机,未接,拒接,占线,呼叫失败,""代表未呼叫
|
||||
private String taskName; //任务名
|
||||
private Integer status; //0进行中 2结束 4暂停
|
||||
private Integer totalCount;
|
||||
private Integer sendCount;
|
||||
|
||||
private RawVarListMap rawVarListMap;
|
||||
}
|
||||
|
||||
@lombok.Data
|
||||
@ToString
|
||||
public static class RawVarListMap {
|
||||
private String taskName; //任务名,作为参数的taskName
|
||||
private String dialTaskMainSn; //任务编号,作为参数的requestId
|
||||
private String custId; //联系人id
|
||||
private String sipTermCause; //例如”对方挂机“
|
||||
private String sipTermStatus; //接通是200
|
||||
private String caller;
|
||||
@JSONField(name = "@NUMBER")
|
||||
private String number;
|
||||
private String startringAt;
|
||||
private String connectedAt;
|
||||
private String startedAt;
|
||||
private String endringAt;
|
||||
private String disconnectedAt;
|
||||
private String stopedAt;
|
||||
private String lastModify;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
package com.whdc.model.entity.autocall;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* uploadCallData接口的返回值
|
||||
*
|
||||
* @author lyf
|
||||
* @since 2025-06-20
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class AICCCallRespTask extends AICCCallRespWrapper {
|
||||
/*
|
||||
{
|
||||
"msg": "操作成功!",
|
||||
"result": {
|
||||
"msg": "任务名称重复" | "导入成功",
|
||||
"count": "0",
|
||||
"status": "-1"
|
||||
},
|
||||
"code": 0,
|
||||
"redirected": false,
|
||||
"success": true,
|
||||
"errorType": 0,
|
||||
"errorCode": "",
|
||||
"timestamp": 1750383985979
|
||||
}
|
||||
*/
|
||||
//code 0 success true
|
||||
public static final String MSG_SUCCESS = "导入成功";
|
||||
public static final String MSG_REPEAT = "任务名称重复";
|
||||
|
||||
private String msg;
|
||||
private String count;
|
||||
private String status;
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
package com.whdc.model.entity.autocall;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author lyf
|
||||
* @since 2025-06-20
|
||||
*/
|
||||
@Data
|
||||
public class AICCCallRespWrapper<T> {
|
||||
/*
|
||||
{
|
||||
"code": 406,
|
||||
"errorCode": "",
|
||||
"errorType": 0,
|
||||
"msg": "Token失效,请重新登录!",
|
||||
"redirected": true,
|
||||
"success": false,
|
||||
"timestamp": 1750384243314
|
||||
}
|
||||
*/
|
||||
//code 406 success false
|
||||
private String msg;
|
||||
private int code;
|
||||
private boolean redirected;
|
||||
private boolean success;
|
||||
private int errorType;
|
||||
private String errorCode;
|
||||
private long timestamp;
|
||||
|
||||
//token失效没有result
|
||||
private T result;
|
||||
|
||||
public boolean isTokenInvalid() {
|
||||
return code == 406 && !success;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package com.whdc.model.entity.autocall;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author lyf
|
||||
* @since 2025-06-20
|
||||
*/
|
||||
@Data
|
||||
public class AICCLogin {
|
||||
/*
|
||||
{"msg":"操作成功!","result":{"msg":"操作成功","tenantId":"963936517","status":"0","token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6IkhCU0wwMSIsInRlbmFudElkIjoiOTYzOTM2NTE3IiwiZXhwIjoxNzUwNjg4NjE4fQ.INUcA-keg7T3HrZXH87K2ZqOT2trxLF38kmA9Wu301w"},"code":0,"redirected":false,"success":true,"errorType":0,"errorCode":"","timestamp":1750386218853}
|
||||
*/
|
||||
//code 0 success true
|
||||
private String msg;
|
||||
private String tenantId;
|
||||
private String status;
|
||||
private String token;
|
||||
}
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
package com.whdc.model.entity.autocall;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author lyf
|
||||
* @since 2025-06-20
|
||||
*/
|
||||
@Data
|
||||
public class AICCUploadTask {
|
||||
/*
|
||||
JSONObject data = new JSONObject();
|
||||
data.put("taskName", taskName);
|
||||
data.put("processId", processId);
|
||||
data.put("callerGroup", callerGroup);
|
||||
data.put("requestId", requestId);
|
||||
data.put("calleeType", 2);
|
||||
data.put("repeatTimes", 2);
|
||||
data.put("autoCall", "0");
|
||||
data.put("spanSeconds", 60);
|
||||
data.put("processType", "3");
|
||||
data.put("mutiTimeRange", timeRange);
|
||||
JSONArray params = new JSONArray();
|
||||
JSONObject param = new JSONObject();
|
||||
param.put("@common_user_name", custName);
|
||||
param.put("@NUMBER", number);
|
||||
if (bakNumbers != null && bakNumbers.length > 0) {
|
||||
for (int i = 0; i < bakNumbers.length; i++) {
|
||||
if (i == 3) break;
|
||||
param.put("备用号码" + (i + 1), bakNumbers[i]);
|
||||
}
|
||||
}
|
||||
param.put("custId", custId);
|
||||
param.put("content", "我是省防办智能外呼系统," + content + "如需咨询请拨打02787221781");
|
||||
params.add(param);
|
||||
data.put("param", params);
|
||||
*/
|
||||
private String taskName;
|
||||
private String processId;
|
||||
private String callerGroup;
|
||||
private String requestId;
|
||||
private int calleeType = 1; //默认0 重乎1 顺乎2 默认为0
|
||||
private int repeatTimes = 1;//呼叫次数,CallType=0不传; CalleeType=1重乎必传; CalleeType=2顺乎并且autoCall为0必传
|
||||
private String autoCall = "0";//顺乎未接通是否重乎,开启=0; 关闭=1; CalleeType=2顺乎必传
|
||||
private int spanSeconds = 3;//重乎间隔时间(秒),CallType=0不传; CalleeType=1重乎必传; CalleeType=2顺乎并且autoCall为0必传
|
||||
private String processType = "3";
|
||||
private String mutiTimeRange;
|
||||
private List<Cust> param;
|
||||
// private String smsSend = "1"; //1不发短信,0发短信
|
||||
// private String smsSendType = "0"; //挂机短信0,未接通短信1,smsSend为0必传
|
||||
// private String templateId; //短信模板id,smsSend为0必传
|
||||
|
||||
@Data
|
||||
public static class Cust {
|
||||
@JSONField(name = "@common_user_name")
|
||||
private String custName;
|
||||
@JSONField(name = "@NUMBER")
|
||||
private String number;
|
||||
@JSONField(name = "备用号码1")
|
||||
private String backNumber1;
|
||||
@JSONField(name = "备用号码2")
|
||||
private String backNumber2;
|
||||
@JSONField(name = "备用号码3")
|
||||
private String backNumber3;
|
||||
private String custId;
|
||||
private String content;
|
||||
@JSONField(serialize = false, deserialize = false)
|
||||
private List<String> _numbers;
|
||||
|
||||
public static CustBuilder builder() {
|
||||
return new CustBuilder();
|
||||
}
|
||||
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public static class CustBuilder {
|
||||
private String custName;
|
||||
private String custId;
|
||||
private String content;
|
||||
@JSONField(serialize = false, deserialize = false)
|
||||
private List<String> _numbers;
|
||||
|
||||
public Cust build() {
|
||||
Cust cust = new Cust();
|
||||
cust.setCustName(custName);
|
||||
cust.setCustId(custId);
|
||||
cust.setContent(content);
|
||||
for (int i = 0; i < _numbers.size(); i++) {
|
||||
switch (i) {
|
||||
case 0:
|
||||
cust.setNumber(_numbers.get(i));
|
||||
break;
|
||||
case 1:
|
||||
cust.setBackNumber1(_numbers.get(i));
|
||||
break;
|
||||
case 2:
|
||||
cust.setBackNumber2(_numbers.get(i));
|
||||
break;
|
||||
case 3:
|
||||
cust.setBackNumber3(_numbers.get(i));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return cust;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void genMutiTimeRange() {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
this.mutiTimeRange = sdf.format(new Date()) + "_" + sdf.format(new Date(System.currentTimeMillis() + 1000 * 60 * 60));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
package com.whdc.model.vo;
|
||||
|
||||
import com.whdc.model.entity.AddressBookOld;
|
||||
import com.whdc.model.entity.WarningResponder;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
|
@ -21,7 +21,7 @@ import java.util.List;
|
|||
public class ExcelOldDataVo {
|
||||
|
||||
@ApiModelProperty(value = "数据")
|
||||
private List<AddressBookOld> list;
|
||||
private List<WarningResponder> list;
|
||||
|
||||
@ApiModelProperty(value = "键")
|
||||
private String key;
|
||||
|
|
|
|||
|
|
@ -25,4 +25,8 @@ public class WarnDppleVO {
|
|||
@ApiParam("手机号")
|
||||
@ApiModelProperty(value = "手机号")
|
||||
private String phone;
|
||||
|
||||
@ApiParam("责任级别")
|
||||
@ApiModelProperty(value = "责任级别")
|
||||
private Integer level;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,152 @@
|
|||
package com.whdc.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.whdc.mapper.*;
|
||||
import com.whdc.model.dto.AutoCallDto;
|
||||
import com.whdc.model.entity.AutoCall;
|
||||
import com.whdc.model.entity.AutoCallPerson;
|
||||
import com.whdc.model.entity.AutoCallTask;
|
||||
import com.whdc.model.entity.WarnCallMap;
|
||||
import com.whdc.utils.DateUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author lyf
|
||||
* @since 2025-06-14
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class AutoCallApiService {
|
||||
@Autowired
|
||||
private AutoCallMapper autoCallMapper;
|
||||
@Autowired
|
||||
private WarnCallMapMapper warnCallMapMapper;
|
||||
|
||||
public Page<AutoCallTask> page2(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<AutoCallTask> query = new QueryWrapper<AutoCallTask>()
|
||||
.orderByDesc("id")
|
||||
.between("warn_tm", stm, etm);
|
||||
if (dto.getCallIsPut() != null) {
|
||||
if (dto.getCallIsPut()) {
|
||||
query.eq("status",
|
||||
AutoCallTask.STATUS_ANY_SUCCESS
|
||||
);
|
||||
} else {
|
||||
query.eq("status",
|
||||
AutoCallTask.STATUS_ALL_FAIL
|
||||
);
|
||||
}
|
||||
} else {
|
||||
query.in("status",
|
||||
AutoCallTask.STATUS_SHOULD_GENERATE,
|
||||
AutoCallTask.STATUS_GENERATED,
|
||||
AutoCallTask.STATUS_ANY_SUCCESS,
|
||||
AutoCallTask.STATUS_ALL_FAIL,
|
||||
AutoCallTask.STATUS_CANCELLED
|
||||
);
|
||||
}
|
||||
Page pageParam = dto.getPage().getPage();
|
||||
Page<AutoCallTask> pageResult = taskMapper.selectPage(
|
||||
pageParam,
|
||||
query
|
||||
);
|
||||
|
||||
List<AutoCallTask> records = pageResult.getRecords();
|
||||
if (records.size() > 0) {
|
||||
for (AutoCallTask task : records) {
|
||||
Integer taskId = task.getId();
|
||||
List<AutoCallPerson> autoCallList = personMapper.selectList(
|
||||
new QueryWrapper<AutoCallPerson>()
|
||||
.eq("task_id", taskId)
|
||||
);
|
||||
task.setCallList(autoCallList);
|
||||
}
|
||||
}
|
||||
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
|
||||
private AutoCallTaskMapper taskMapper;
|
||||
@Autowired
|
||||
private AutoCallPersonMapper personMapper;
|
||||
@Autowired
|
||||
private QXWarningMapper warningMapper;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,494 @@
|
|||
package com.whdc.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.whdc.mapper.*;
|
||||
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;
|
||||
|
||||
/**
|
||||
* @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 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) {
|
||||
//处理行政区划和预警级别,橙色预警拨打1,2level的,红色预警只拨打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) {
|
||||
List<Integer> ret = new ArrayList<>();
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,449 @@
|
|||
package com.whdc.service;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.whdc.mapper.*;
|
||||
import com.whdc.model.entity.*;
|
||||
import com.whdc.model.entity.autocall.AICCCallRespDetail;
|
||||
import com.whdc.model.entity.autocall.AICCCallRespTask;
|
||||
import com.whdc.model.entity.autocall.AICCCallRespWrapper;
|
||||
import com.whdc.model.entity.autocall.AICCUploadTask;
|
||||
import com.whdc.utils.AICCHelper;
|
||||
import com.whdc.utils.SmsHelper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.support.DefaultTransactionDefinition;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author lyf
|
||||
* @since 2025-07-08
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class AutoCallTaskService2 {
|
||||
@Autowired
|
||||
private AutoCallTaskMapper taskMapper;
|
||||
@Autowired
|
||||
private AutoCallPersonMapper personMapper;
|
||||
@Autowired
|
||||
private AutoCallConfigMapper configMapper;
|
||||
@Autowired
|
||||
private PlatformTransactionManager transactionManager;
|
||||
@Autowired
|
||||
private WarningResponderMapper warningResponderMapper;
|
||||
@Autowired
|
||||
private QXWarningMapper qxWarningMapper;
|
||||
@Autowired
|
||||
private AICCHelper aiccHelper;
|
||||
@Autowired
|
||||
private SmsHelper smsHelper;
|
||||
|
||||
public void generateFakeCall() {
|
||||
QXWarning warn = qxWarningMapper.selectOne(
|
||||
new QueryWrapper<QXWarning>()
|
||||
.orderByDesc("WARNID")
|
||||
.last("limit 1")
|
||||
);
|
||||
warn.setCtnm("恩施州");
|
||||
warn.setCnnm("咸丰 ");
|
||||
|
||||
List<AutoCallTask> taskList = newTask(warn);
|
||||
AutoCallTask task = taskList.get(0);
|
||||
task.setStatus(0);
|
||||
task.setCreateTm(new Date());
|
||||
task.setWarnCnnm("咸丰 ");
|
||||
taskMapper.insert(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) {
|
||||
person.setDetailRemark("超时");
|
||||
person.setStatus(AutoCallPerson.STATUS_CANCELLED);
|
||||
person.setDetailSipTermCause("超时");
|
||||
personMapper.updateById(person);
|
||||
}
|
||||
|
||||
public void step1GenerateTask() {
|
||||
//切记要设置task的status
|
||||
List<QXWarning> warnList = taskMapper.listWarnsThatNotGeneratedTask();
|
||||
boolean enable = configMapper.isEnable();
|
||||
for (QXWarning warn : warnList) {
|
||||
try {
|
||||
List<AutoCallTask> taskList = newTask(warn);
|
||||
Date now = new Date();
|
||||
for (AutoCallTask task : taskList) {
|
||||
if (task.getWarnCnnm() == null) {
|
||||
task.setRemark("未找到县区");
|
||||
}
|
||||
task.setCreateTm(now);
|
||||
if (enable && task.getWarnCnnm() != null) {
|
||||
task.setStatus(AutoCallTask.STATUS_SHOULD_GENERATE);
|
||||
}
|
||||
taskMapper.insert(task);
|
||||
if (enable && task.getWarnCnnm() != null) {
|
||||
generatePerson(task);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("根据预警生成呼叫失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<AutoCallTask> newTask(QXWarning warn) {
|
||||
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<AutoCallTask> ret = new ArrayList<>();
|
||||
if (cnnmStr == null || cnnmStr.isEmpty()) {
|
||||
AutoCallTask task = newTask(null, warnId, publishTime, ctnm, warnSignalLevel, content);
|
||||
ret.add(task);
|
||||
return ret;
|
||||
}
|
||||
String[] cnnms = cnnmStr.split(",");
|
||||
for (String cnnm : cnnms) {
|
||||
if (cnnm.isEmpty()) continue;
|
||||
if (publishTime == null) continue;
|
||||
if ("test".equals(cnnm)) {
|
||||
cnnm = "咸丰 ";
|
||||
ctnm = "恩施州";
|
||||
}
|
||||
AutoCallTask task = newTask(cnnm, warnId, publishTime, ctnm, warnSignalLevel, content);
|
||||
ret.add(task);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private AutoCallTask newTask(String cnnm, Integer warnId, Date publishTime, String ctnm, String warnSignalLevel, String content) {
|
||||
AutoCallTask task = new AutoCallTask();
|
||||
task.setWarnId(warnId);
|
||||
task.setWarnCtnm(ctnm);
|
||||
task.setWarnCnnm(cnnm);
|
||||
task.setWarnContent(content);
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
task.setWarnTm(publishTime);
|
||||
task.setWarnName(String.format("%s%s%s%s预警", sdf.format(publishTime), ctnm, cnnm, warnSignalLevel));
|
||||
task.setWarnLevel(warnSignalLevel);
|
||||
return task;
|
||||
}
|
||||
|
||||
public void generatePerson(AutoCallTask task) {
|
||||
//切记要设置task的status
|
||||
List<AutoCallPerson> personList = newPerson(task);
|
||||
if (personList.size() == 0) {
|
||||
task.setRemark("未找到责任人");
|
||||
task.setStatus(AutoCallTask.STATUS_CANCELLED);
|
||||
task.setErrorCode(AutoCallTask.ERRCODE_NO_PERSON);
|
||||
taskMapper.updateById(task);
|
||||
return;
|
||||
}
|
||||
TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
|
||||
try {
|
||||
Date now = new Date();
|
||||
personList.forEach(a -> {
|
||||
a.setCreateTm(now);
|
||||
personMapper.insert(a);
|
||||
});
|
||||
task.setStatus(AutoCallTask.STATUS_GENERATED);
|
||||
taskMapper.updateById(task);
|
||||
transactionManager.commit(status);
|
||||
} catch (Exception e) {
|
||||
transactionManager.rollback(status);
|
||||
task.setRemark("数据库异常");
|
||||
task.setStatus(AutoCallTask.STATUS_CANCELLED);
|
||||
task.setErrorCode(AutoCallTask.ERRCODE_DB_ERROR);
|
||||
taskMapper.updateById(task);
|
||||
log.error("插入外呼责任人异常", e);
|
||||
log.error("{}", JSON.toJSONString(personList));
|
||||
}
|
||||
}
|
||||
|
||||
private List<Integer> mapWarnSignalLevel(String warnSignalLevel) {
|
||||
List<Integer> ret = new ArrayList<>();
|
||||
if ("红色".equals(warnSignalLevel)) {
|
||||
ret.add(3);
|
||||
} else {
|
||||
ret.add(1);
|
||||
ret.add(2);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static final String[] excludeNames = new String[]{"高新", "开发", "自治", "技术", "旅游", "管理", "工业", "产业", "示范"};
|
||||
|
||||
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<AutoCallPerson> newPerson(AutoCallTask task) {
|
||||
String cnnm = task.getWarnCnnm();
|
||||
long millis = task.getCreateTm().getTime();
|
||||
List<Integer> warnLevels = mapWarnSignalLevel(task.getWarnLevel());
|
||||
List<WarningResponder> wrList = warningResponderMapper.listByCnnmAndLevelOrderByLevelAsc(cnnm, warnLevels);
|
||||
if (wrList.isEmpty()) return Collections.emptyList();
|
||||
//处理县区包含高新区、开发区等情况
|
||||
doSomethingWith(cnnm, wrList);
|
||||
//按level从小到大排序
|
||||
wrList.sort(Comparator.comparingInt(WarningResponder::getLevel));
|
||||
|
||||
List<AutoCallPerson> personList = new ArrayList<>();
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
for (WarningResponder wr : wrList) {
|
||||
Integer wrLevel = wr.getLevel();
|
||||
wr.decryptPhone();
|
||||
AutoCallPerson person = new AutoCallPerson();
|
||||
String uniqueId = millis + "-" + wr.getId();
|
||||
person.setTaskId(task.getId());
|
||||
person.setUploadRequestId(uniqueId);
|
||||
person.setUploadCustId(uniqueId);
|
||||
person.setUploadCustName(wr.getName());
|
||||
person.setLevel(wrLevel);
|
||||
person.setUploadNumber(wr.getPhone());
|
||||
person.setUploadContent(
|
||||
"我是省防办智能外呼系统," +
|
||||
wr.getName() + "同志您好," +
|
||||
task.getWarnCtnm() +
|
||||
sdf.format(task.getWarnTm()) +
|
||||
"发布暴雨" +
|
||||
task.getWarnLevel() +
|
||||
"预警信号:" +
|
||||
task.getWarnContent() +
|
||||
"如需咨询请拨打02787221781,相关信息以短信发送给您。"
|
||||
);
|
||||
person.setCreateTm(task.getCreateTm());
|
||||
personList.add(person);
|
||||
}
|
||||
return personList;
|
||||
}
|
||||
|
||||
public List<AutoCallPerson> step2GetOneUnUploadedPerson() {
|
||||
List<AutoCallPerson> personList = personMapper.listUnUploaded();
|
||||
if (personList == null || personList.isEmpty()) return Collections.emptyList();
|
||||
|
||||
Map<Integer, List<AutoCallPerson>> personGroup = personList.stream().collect(Collectors.groupingBy(AutoCallPerson::getTaskId));
|
||||
|
||||
List<AutoCallPerson> ret = new ArrayList<>();
|
||||
personGroup.forEach((taskId, list) -> {
|
||||
//按level从小到大排序
|
||||
list.sort(Comparator.comparingInt(AutoCallPerson::getLevel));
|
||||
ret.add(list.get(0));
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static final AtomicBoolean isCalling = new AtomicBoolean(false);
|
||||
|
||||
public void step3UploadAICCTask(AutoCallPerson person) {
|
||||
//切记要设置person的status
|
||||
if (!isCalling.compareAndSet(false, true)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
List<String> numbers = Collections.singletonList(person.getUploadNumber());
|
||||
AICCUploadTask uploadTask = aiccHelper.newTask(
|
||||
person.getUploadRequestId(),
|
||||
person.getUploadCustId(),
|
||||
person.getUploadCustName(),
|
||||
person.getUploadContent(),
|
||||
numbers
|
||||
);
|
||||
AICCCallRespWrapper<AICCCallRespTask> AICCCallRespWrapper = null;
|
||||
try {
|
||||
AICCCallRespWrapper = aiccHelper.apiUploadCallData(uploadTask);
|
||||
} catch (GeneralSecurityException | UnsupportedEncodingException e) {
|
||||
person.setStatus(AutoCallPerson.STATUS_CANCELLED);
|
||||
person.setErrorCode(AutoCallPerson.ERRCODE_ENCODE);
|
||||
personMapper.updateById(person);
|
||||
log.error("外呼任务编码异常", e);
|
||||
}
|
||||
if (AICCCallRespWrapper == null) {
|
||||
person.setStatus(AutoCallPerson.STATUS_CANCELLED);
|
||||
person.setErrorCode(AutoCallPerson.ERRCODE_UPLOAD_FAIL);
|
||||
personMapper.updateById(person);
|
||||
} else {
|
||||
String msg = AICCCallRespWrapper.getResult().getMsg();
|
||||
person.setStatus(AutoCallPerson.STATUS_UPLOADED);
|
||||
person.setUploadRespMsg(msg);
|
||||
personMapper.updateById(person);
|
||||
smsHelper.send(numbers, person.getUploadContent());
|
||||
}
|
||||
} finally {
|
||||
isCalling.set(false);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean step4QueryAICCTaskResult(AutoCallPerson person) {
|
||||
//切记要设置person的status和task的status
|
||||
AICCCallRespWrapper<AICCCallRespDetail> detail = aiccHelper.apiGetTaskCallDetail(person.getUploadRequestId(), person.getUploadCustId());
|
||||
List<AICCCallRespDetail.Record> records = detail.getResult().getData().getRecords();
|
||||
if (records.isEmpty()) return false; //这个false是平台还未有拨打,应继续刷接口
|
||||
AICCCallRespDetail.Record record = records.get(0);
|
||||
String dialRemark = record.getRemark();
|
||||
boolean done = false;
|
||||
if ("接通".equals(dialRemark)) {
|
||||
person.setStatus(AutoCallPerson.STATUS_PUT);
|
||||
done = true;
|
||||
} else if (records.size() > 1) {
|
||||
person.setStatus(AutoCallPerson.STATUS_CALLED);
|
||||
done = true;
|
||||
}
|
||||
if (done) {
|
||||
person.setDetailRemark(dialRemark);
|
||||
person.setDetailTalkTimes(record.getTalkTimes());
|
||||
AICCCallRespDetail.RawVarListMap rawVarListMap = record.getRawVarListMap();
|
||||
person.setDetailSipTermCause(rawVarListMap.getSipTermCause());
|
||||
|
||||
{
|
||||
Date d;
|
||||
long l;
|
||||
if (rawVarListMap.getStartringAt() != null) {
|
||||
d = new Date();
|
||||
l = Long.parseLong(rawVarListMap.getStartringAt().substring(0, 13));
|
||||
d.setTime(l);
|
||||
person.setDetailStartringAt(d);
|
||||
}
|
||||
|
||||
if (rawVarListMap.getConnectedAt() != null) {
|
||||
d = new Date();
|
||||
l = Long.parseLong(rawVarListMap.getConnectedAt().substring(0, 13));
|
||||
d.setTime(l);
|
||||
person.setDetailConnectedAt(d);
|
||||
}
|
||||
|
||||
if (rawVarListMap.getStartedAt() != null) {
|
||||
d = new Date();
|
||||
l = Long.parseLong(rawVarListMap.getStartedAt());
|
||||
d.setTime(l);
|
||||
person.setDetailStartedAt(d);
|
||||
}
|
||||
|
||||
if (rawVarListMap.getEndringAt() != null) {
|
||||
d = new Date();
|
||||
l = Long.parseLong(rawVarListMap.getEndringAt().substring(0, 13));
|
||||
d.setTime(l);
|
||||
person.setDetailEndringAt(d);
|
||||
}
|
||||
|
||||
if (rawVarListMap.getDisconnectedAt() != null) {
|
||||
d = new Date();
|
||||
l = Long.parseLong(rawVarListMap.getDisconnectedAt().substring(0, 13));
|
||||
d.setTime(l);
|
||||
person.setDetailDisconnectedAt(d);
|
||||
}
|
||||
|
||||
if (rawVarListMap.getStopedAt() != null) {
|
||||
d = new Date();
|
||||
l = Long.parseLong(rawVarListMap.getStopedAt());
|
||||
d.setTime(l);
|
||||
person.setDetailStopedAt(d);
|
||||
}
|
||||
|
||||
if (rawVarListMap.getLastModify() != null) {
|
||||
d = new Date();
|
||||
l = Long.parseLong(rawVarListMap.getLastModify());
|
||||
d.setTime(l);
|
||||
person.setDetailLastModify(d);
|
||||
}
|
||||
}
|
||||
personMapper.updateById(person);
|
||||
boolean anySuccess = markTaskStatus(person.getTaskId());
|
||||
if (anySuccess) {
|
||||
markRemanentPersonStatus(person.getTaskId());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false; //这个false是平台还未完成重呼,应继续刷接口
|
||||
}
|
||||
|
||||
private void markRemanentPersonStatus(Integer taskId) {
|
||||
personMapper.update(new AutoCallPerson() {{
|
||||
setStatus(AutoCallPerson.STATUS_CANCELLED);
|
||||
setDetailRemark("已呼通其他联系人");
|
||||
}}, new QueryWrapper<AutoCallPerson>() {{
|
||||
eq("task_id", taskId);
|
||||
eq("status", AutoCallPerson.STATUS_DEFAULT);
|
||||
}});
|
||||
|
||||
}
|
||||
|
||||
private boolean markTaskStatus(Integer taskId) {
|
||||
boolean anySuccess = personMapper.isAnySuccess(taskId);
|
||||
if (anySuccess) {
|
||||
taskMapper.setStatus(taskId, AutoCallTask.STATUS_ANY_SUCCESS);
|
||||
return true;
|
||||
}
|
||||
boolean allFail = personMapper.isAllFail(taskId);
|
||||
if (allFail) {
|
||||
taskMapper.setStatus(taskId, AutoCallTask.STATUS_ALL_FAIL);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
package com.whdc.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.whdc.model.entity.AddressBookOld;
|
||||
import com.whdc.model.entity.WarningResponder;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
|
@ -12,6 +12,6 @@ import java.util.List;
|
|||
* @author xusan
|
||||
* @date 2024-05-11
|
||||
*/
|
||||
public interface IAddressBookOldService extends IService<AddressBookOld> {
|
||||
List<AddressBookOld> getListByAdnm2(String cnnm2);
|
||||
public interface IWarningResponderService extends IService<WarningResponder> {
|
||||
List<WarningResponder> getListByAdnm2(String cnnm2);
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
package com.whdc.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.whdc.mapper.AddressBookOldMapper;
|
||||
import com.whdc.model.dto.AddressBookOldDto;
|
||||
import com.whdc.model.entity.AddressBookOld;
|
||||
import com.whdc.service.IAddressBookOldService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author xusan
|
||||
* @date 2024-05-11
|
||||
*/
|
||||
@Service
|
||||
public class AddressBookOldServiceImpl extends ServiceImpl<AddressBookOldMapper, AddressBookOld> implements IAddressBookOldService {
|
||||
|
||||
@Override
|
||||
public List<AddressBookOld> getListByAdnm2(String adnm) {
|
||||
return baseMapper.getListByAdnm2(adnm);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
package com.whdc.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.whdc.mapper.WarningResponderMapper;
|
||||
import com.whdc.model.entity.WarningResponder;
|
||||
import com.whdc.service.IWarningResponderService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author xusan
|
||||
* @date 2024-05-11
|
||||
*/
|
||||
@Service
|
||||
public class WarningResponderServiceImpl extends ServiceImpl<WarningResponderMapper, WarningResponder> implements IWarningResponderService {
|
||||
|
||||
@Override
|
||||
public List<WarningResponder> getListByAdnm2(String adnm) {
|
||||
return baseMapper.getListByAdnm2(adnm);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,181 @@
|
|||
package com.whdc.utils;
|
||||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
|
||||
import javax.crypto.*;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.*;
|
||||
|
||||
|
||||
public class AESpkcs7paddingUtil {
|
||||
|
||||
/**
|
||||
* 密钥算法
|
||||
*/
|
||||
private static final String KEY_ALGORITHM = "AES";
|
||||
|
||||
/**
|
||||
* 加密/解密算法 / 工作模式 / 填充方式
|
||||
* Java 6支持PKCS5Padding填充方式
|
||||
* Bouncy Castle支持PKCS7Padding填充方式
|
||||
*/
|
||||
private static final String CIPHER_ALGORITHM = "AES/ECB/PKCS7Padding";
|
||||
|
||||
static {
|
||||
//如果是PKCS7Padding填充方式,则必须加上下面这行
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成密钥
|
||||
*
|
||||
* @return 密钥
|
||||
* @throws Exception
|
||||
*/
|
||||
public static String generateKey() throws Exception {
|
||||
//实例化密钥生成器
|
||||
KeyGenerator kg = KeyGenerator.getInstance(KEY_ALGORITHM);
|
||||
/**
|
||||
* 设置AES密钥长度
|
||||
* AES要求密钥长度为128位或192位或256位,java默认限制AES密钥长度最多128位
|
||||
* 如需192位或256位,则需要到oracle官网找到对应版本的jdk下载页,在"Additional Resources"中找到
|
||||
* "Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files",点击[DOWNLOAD]下载
|
||||
* 将下载后的local_policy.jar和US_export_policy.jar放到jdk安装目录下的jre/lib/security/目录下,替换该目录下的同名文件
|
||||
*/
|
||||
kg.init(128);
|
||||
//生成密钥
|
||||
SecretKey secretKey = kg.generateKey();
|
||||
//获得密钥的字符串形式
|
||||
return Base64.encodeBase64String(secretKey.getEncoded());
|
||||
}
|
||||
|
||||
/**
|
||||
* AES加密
|
||||
*
|
||||
* @param source 源字符串
|
||||
* @param key 密钥
|
||||
* @return 加密后的密文
|
||||
* @throws Exception
|
||||
*/
|
||||
public static String encrypt(String source, String key) throws GeneralSecurityException, UnsupportedEncodingException {
|
||||
|
||||
byte[] sourceBytes = source.getBytes("UTF-8");
|
||||
byte[] keyBytes = key.getBytes("UTF-8");
|
||||
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM, "BC");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(keyBytes, KEY_ALGORITHM));
|
||||
byte[] decrypted = cipher.doFinal(sourceBytes);
|
||||
return Base64.encodeBase64String(decrypted);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* AES解密
|
||||
*
|
||||
* @param encryptStr 加密后的密文
|
||||
* @param key 密钥
|
||||
* @return 源字符串
|
||||
* @throws Exception
|
||||
*/
|
||||
public static String decrypt(String encryptStr, String key) {
|
||||
try {
|
||||
byte[] sourceBytes = Base64.decodeBase64(encryptStr);
|
||||
final byte[] keyBytes = key.getBytes("UTF-8");
|
||||
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM, "BC");
|
||||
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(keyBytes, KEY_ALGORITHM));
|
||||
byte[] decoded = cipher.doFinal(sourceBytes);
|
||||
return new String(decoded, "UTF-8");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
String data = "{\"sysUserId\":\"HBSL01\",\"expire\":1000000}";
|
||||
String encrypt = encrypt(data, "yxt@2024-1234567");
|
||||
System.out.println(encrypt);
|
||||
String request = "{\"request\":\"" + encrypt + "\"}";
|
||||
String resp = HttpUtil.sendPost("https://aicc.cuopen.net:9801/aicc-api/ssb/callout/thirdParty/login", request);
|
||||
System.out.println(resp);
|
||||
|
||||
/*
|
||||
挂断是无人接听
|
||||
*/
|
||||
|
||||
// genTask();
|
||||
// genQueryTask();
|
||||
// String request = "{\n" +
|
||||
// " \"requestId\": \"hbsl1750130919921\",\n" +
|
||||
// " \"custId\": \"hbsl-zj\"\n" +
|
||||
// "}";
|
||||
// JSONObject header = new JSONObject();
|
||||
// header.put("X-Access-Token", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6Ik5TQkRKSzIwMjUiLCJ0ZW5hbnRJZCI6IjE5MTY1NDI5IiwiZXhwIjoxNzUwNDI5OTAzfQ.RvsTL5L8jPl6GqiQq344jBP5i-v6vuQt-kARsvUvuyY");
|
||||
// String resp = HttpUtil.sendPost("https://aicc.cuopen.net:9801/aicc-api/ssb/callout/thirdParty/task/getTaskCallDetail", request, header);
|
||||
// AICCCallRespDetail autoCallDetail = JSON.parseObject(resp, AICCCallRespDetail.class);
|
||||
// autoCallDetail.getResult().getData().getRecords().forEach(System.out::println);
|
||||
|
||||
|
||||
// AutoCallHelper helper = new AutoCallHelper();
|
||||
// helper.initToken();
|
||||
// String token = helper.getToken();
|
||||
// genTask();
|
||||
}
|
||||
|
||||
private static void genQueryTask() throws Exception {
|
||||
String requestId = "hbsl1750130186416";
|
||||
String custId = "detail2c9ab2f08709s438018722de2ebf001f";
|
||||
String data = "{\"requestId\":\"" + requestId + "\",\"custId\":\"" + custId + "\"}";
|
||||
System.out.println(data);
|
||||
String e = encrypt(data, "yxt@2024-1234567");
|
||||
System.out.println(e);
|
||||
}
|
||||
|
||||
private static void genTask() throws Exception {
|
||||
String taskName = "hbsl" + System.currentTimeMillis();
|
||||
String processId = "1934801506242949122";
|
||||
// String processId = "1934876091344777218";
|
||||
String requestId = taskName;
|
||||
String callerGroup = "02160980358";
|
||||
// String callerGroup = "01080945234";
|
||||
String content = "这里是湖北省防汛抗旱指挥部办公室,咸宁市2025年06月15日02时26分58秒发布暴雨橙色预警信号:过去6小时最大降水出现在青山镇(青山水库)为54.6毫米。预计今天夜间,崇阳南部将出现暴雨到大暴雨,累计降雨量将达100毫米以上,并伴有雷暴大风,山区山洪、地质灾害、城乡积涝、中小河流洪水风险高,请加强防范。";
|
||||
// String content = "咸宁市2025年06月15日02时26分58秒发布暴雨橙色预警信号";
|
||||
JSONObject data = new JSONObject();
|
||||
data.put("taskName", taskName);
|
||||
data.put("processId", processId);
|
||||
data.put("callerGroup", callerGroup);
|
||||
data.put("requestId", requestId);
|
||||
data.put("calleeType", 2);
|
||||
data.put("repeatTimes", 2);
|
||||
data.put("autoCall", "0");
|
||||
data.put("spanSeconds", 60);
|
||||
data.put("processType", "3");
|
||||
data.put("mutiTimeRange", "2025-06-17 10:00:00_2025-06-17 21:00:00");
|
||||
JSONArray params = new JSONArray();
|
||||
JSONObject param = new JSONObject();
|
||||
param.put("@common_user_name", "李");
|
||||
// param.put("@NUMBER", "15671545233");
|
||||
param.put("@NUMBER", "15671545233");
|
||||
param.put("备用号码1", "18162570850");
|
||||
// param.put("备用号码1", "13933930962");
|
||||
// param.put("备用号码2", "15697168180");
|
||||
param.put("custId", "abo70652-abo70653-abo70654");
|
||||
// param.put("address", "{}");
|
||||
param.put("content", content);
|
||||
params.add(param);
|
||||
data.put("param", params);
|
||||
System.out.println(data);
|
||||
|
||||
String e = encrypt(data.toJSONString(), "yxt@2024-1234567");
|
||||
|
||||
JSONObject request = new JSONObject();
|
||||
request.put("request", e);
|
||||
JSONObject header = new JSONObject();
|
||||
header.put("X-Access-Token", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6Ik5TQkRKSzIwMjUiLCJ0ZW5hbnRJZCI6IjE5MTY1NDI5IiwiZXhwIjoxNzUwNDI5OTAzfQ.RvsTL5L8jPl6GqiQq344jBP5i-v6vuQt-kARsvUvuyY");
|
||||
HttpUtil.sendPost("https://aicc.cuopen.net:9801/aicc-api/ssb/callout/thirdParty/task/uploadCallData", request.toJSONString(), header);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,243 @@
|
|||
package com.whdc.utils;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson.TypeReference;
|
||||
import com.whdc.model.entity.autocall.*;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* @author lyf
|
||||
* @since 2025-06-19
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class AICCHelper {
|
||||
@Setter
|
||||
@Value("${autocall.processId}")
|
||||
private String processId;
|
||||
@Setter
|
||||
@Value("${autocall.callerGroup}")
|
||||
private String callerGroup;
|
||||
@Setter
|
||||
@Value("${autocall.secret}")
|
||||
private String secret;
|
||||
@Setter
|
||||
@Value("${autocall.sysUserId}")
|
||||
private String sysUserId;
|
||||
@Autowired
|
||||
private HttpHelper httpHelper = new HttpHelper();
|
||||
|
||||
private static final AtomicBoolean isAcquiringToken = new AtomicBoolean(false);
|
||||
private static volatile CountDownLatch latch = new CountDownLatch(0);
|
||||
private static final AtomicReference<String> globalToken = new AtomicReference<>();
|
||||
|
||||
public String getToken() {
|
||||
if (globalToken.get() == null) {
|
||||
initToken();
|
||||
}
|
||||
return globalToken.get();
|
||||
}
|
||||
|
||||
public void initToken() throws RuntimeException {
|
||||
if (isAcquiringToken.compareAndSet(false, true)) {
|
||||
globalToken.set(null);
|
||||
try {
|
||||
String data = "{\"sysUserId\":\"" + sysUserId + "\",\"expire\":1000000}";
|
||||
String encrypt;
|
||||
try {
|
||||
encrypt = AESpkcs7paddingUtil.encrypt(data, secret);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
JSONObject request = new JSONObject();
|
||||
request.put("request", encrypt);
|
||||
Map<String, String> headers = new HashMap<>();
|
||||
headers.put("X-Access-Token", getToken());
|
||||
String resp = httpHelper.postJsonString("https://aicc.cuopen.net:9801/aicc-api/ssb/callout/thirdParty/login", request.toJSONString(), headers);
|
||||
|
||||
TypeReference<AICCCallRespWrapper<AICCLogin>> type = new TypeReference<AICCCallRespWrapper<AICCLogin>>() {
|
||||
};
|
||||
AICCCallRespWrapper<AICCLogin> AICCCallRespWrapper = JSON.parseObject(resp, type);
|
||||
if (AICCCallRespWrapper == null || !AICCCallRespWrapper.isSuccess() || AICCCallRespWrapper.getResult() == null) {
|
||||
log.warn("获取外呼系统token失败");
|
||||
return;
|
||||
}
|
||||
|
||||
AICCLogin result = AICCCallRespWrapper.getResult();
|
||||
String token = result.getToken();
|
||||
if (token != null && !token.isEmpty()) {
|
||||
globalToken.set(token);
|
||||
}
|
||||
} finally {
|
||||
isAcquiringToken.set(false);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
latch.await();
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AICCCallRespWrapper<AICCCallRespTask> apiUploadCallData(AICCUploadTask data) throws GeneralSecurityException, UnsupportedEncodingException {
|
||||
return apiUploadCallData(data, getToken());
|
||||
}
|
||||
|
||||
public AICCCallRespWrapper<AICCCallRespTask> apiUploadCallData(AICCUploadTask data, String token) throws GeneralSecurityException, UnsupportedEncodingException {
|
||||
String e;
|
||||
try {
|
||||
e = AESpkcs7paddingUtil.encrypt(JSON.toJSONString(data), secret);
|
||||
} catch (GeneralSecurityException | UnsupportedEncodingException ex) {
|
||||
throw ex;
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
JSONObject request = new JSONObject();
|
||||
request.put("request", e);
|
||||
Map<String, String> headers = new HashMap<>();
|
||||
headers.put("X-Access-Token", token);
|
||||
String resp = httpHelper.postJsonString("https://aicc.cuopen.net:9801/aicc-api/ssb/callout/thirdParty/task/uploadCallData", request.toJSONString(), headers);
|
||||
log.info("apiUploadCallData: {}", resp);
|
||||
TypeReference<AICCCallRespWrapper<AICCCallRespTask>> type = new TypeReference<AICCCallRespWrapper<AICCCallRespTask>>() {
|
||||
};
|
||||
AICCCallRespWrapper<AICCCallRespTask> AICCCallRespWrapper = JSON.parseObject(resp, type);
|
||||
if (AICCCallRespWrapper == null || !AICCCallRespWrapper.isSuccess()) {
|
||||
initToken();
|
||||
headers.put("X-Access-Token", getToken());
|
||||
resp = httpHelper.postJsonString("https://aicc.cuopen.net:9801/aicc-api/ssb/callout/thirdParty/task/uploadCallData", request.toJSONString(), headers);
|
||||
AICCCallRespWrapper = JSON.parseObject(resp, type);
|
||||
}
|
||||
|
||||
if (AICCCallRespWrapper == null || !AICCCallRespWrapper.isSuccess()) {
|
||||
return null;
|
||||
}
|
||||
return AICCCallRespWrapper;
|
||||
}
|
||||
|
||||
public AICCCallRespWrapper<AICCCallRespDetail> apiGetTaskCallDetail(String requestId, String custId) {
|
||||
JSONObject request = new JSONObject();
|
||||
request.put("requestId", requestId);
|
||||
request.put("custId", custId);
|
||||
Map<String, String> headers = new HashMap<>();
|
||||
headers.put("X-Access-Token", getToken());
|
||||
String resp = httpHelper.postJsonString("https://aicc.cuopen.net:9801/aicc-api/ssb/callout/thirdParty/task/getTaskCallDetail", request.toJSONString(),headers);
|
||||
|
||||
TypeReference<AICCCallRespWrapper<AICCCallRespDetail>> type = new TypeReference<AICCCallRespWrapper<AICCCallRespDetail>>() {
|
||||
};
|
||||
AICCCallRespWrapper<AICCCallRespDetail> AICCCallRespWrapper = JSON.parseObject(resp, type);
|
||||
if (AICCCallRespWrapper == null || !AICCCallRespWrapper.isSuccess()) {
|
||||
initToken();
|
||||
headers.put("X-Access-Token", getToken());
|
||||
resp = httpHelper.postJsonString("https://aicc.cuopen.net:9801/aicc-api/ssb/callout/thirdParty/task/getTaskCallDetail", request.toJSONString(), headers);
|
||||
AICCCallRespWrapper = JSON.parseObject(resp, type);
|
||||
}
|
||||
|
||||
if (AICCCallRespWrapper == null || !AICCCallRespWrapper.isSuccess()) {
|
||||
return null;
|
||||
}
|
||||
return AICCCallRespWrapper;
|
||||
}
|
||||
|
||||
public AICCUploadTask newTask(String requestId, String custId, String custName, String content, List<String> numbers) {
|
||||
AICCUploadTask task = new AICCUploadTask();
|
||||
task.setTaskName(requestId);
|
||||
task.setProcessId(processId);
|
||||
task.setCallerGroup(callerGroup);
|
||||
task.setRequestId(requestId);
|
||||
task.genMutiTimeRange();
|
||||
AICCUploadTask.Cust param = AICCUploadTask.Cust.builder()
|
||||
.setCustName(custName)
|
||||
.setCustId(custId)
|
||||
.setContent(content)
|
||||
.set_numbers(numbers)
|
||||
.build();
|
||||
task.setParam(Collections.singletonList(param));
|
||||
|
||||
return task;
|
||||
}
|
||||
|
||||
// private String sendPost(String url, JSONObject jsonData) {
|
||||
// String resp = sendPost(url, jsonData.toJSONString());
|
||||
// if (resp == null) {
|
||||
// resp = sendPost(url, jsonData.toJSONString());
|
||||
// }
|
||||
// return resp;
|
||||
// }
|
||||
//
|
||||
// private String sendPost(String url, JSONObject jsonData, String token) {
|
||||
// String resp = sendPost(url, jsonData.toJSONString(), token);
|
||||
// if (resp == null) {
|
||||
// resp = sendPost(url, jsonData.toJSONString(), token);
|
||||
// }
|
||||
// return resp;
|
||||
// }
|
||||
//
|
||||
// private String sendPost(String url, String jsonData) {
|
||||
// return sendPost(url, jsonData, getToken());
|
||||
// }
|
||||
//
|
||||
// private String sendPost(String url, String jsonData, String token) {
|
||||
// CloseableHttpResponse response = null;
|
||||
// CloseableHttpClient httpClient = null;
|
||||
// String responseContent = null;
|
||||
// try {
|
||||
// httpClient = HttpClients.createDefault();
|
||||
// HttpPost httpPost = new HttpPost(url);
|
||||
// httpPost.addHeader("Content-Type", "application/json");
|
||||
// httpPost.addHeader("X-Access-Token", token);
|
||||
//
|
||||
// if (StringUtils.isNotBlank(jsonData)) {
|
||||
// httpPost.setEntity(new StringEntity(jsonData, "UTF-8"));
|
||||
// }
|
||||
//
|
||||
// log.info("请求地址: " + url);
|
||||
// log.info("token: " + getToken());
|
||||
// log.info("请求参数: " + jsonData);
|
||||
//
|
||||
// response = httpClient.execute(httpPost);
|
||||
// HttpEntity entity = response.getEntity();
|
||||
// responseContent = EntityUtils.toString(entity, "UTF-8");
|
||||
// responseContent = jsonFormat(responseContent);
|
||||
// if (responseContent.length() < 200) {
|
||||
// log.info("响应参数: " + responseContent);
|
||||
// }
|
||||
// } catch (Exception e) {
|
||||
// log.error("发送请求异常", e);
|
||||
// return null;
|
||||
// } finally {
|
||||
// try {
|
||||
// if (null != response) {
|
||||
// response.close();
|
||||
// }
|
||||
// httpClient.close();
|
||||
// } catch (IOException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// }
|
||||
// return responseContent;
|
||||
// }
|
||||
|
||||
private static String jsonFormat(String str) {
|
||||
if (JSON.isValidObject(str)) {
|
||||
str = JSON.parseObject(str).toJSONString();
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,235 @@
|
|||
package com.whdc.utils;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson.TypeReference;
|
||||
import com.whdc.model.entity.autocall.*;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* @author lyf
|
||||
* @since 2025-06-19
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class AutoCallHelper {
|
||||
@Setter
|
||||
@Value("${autocall.processId}")
|
||||
private String processId;
|
||||
@Setter
|
||||
@Value("${autocall.callerGroup}")
|
||||
private String callerGroup;
|
||||
@Setter
|
||||
@Value("${autocall.secret}")
|
||||
private String secret;
|
||||
@Setter
|
||||
@Value("${autocall.sysUserId}")
|
||||
private String sysUserId;
|
||||
|
||||
private static final AtomicBoolean isAcquiringToken = new AtomicBoolean(false);
|
||||
private static volatile CountDownLatch latch = new CountDownLatch(0);
|
||||
private static final AtomicReference<String> globalToken = new AtomicReference<>();
|
||||
|
||||
public String getToken() {
|
||||
if (globalToken.get() == null) {
|
||||
initToken();
|
||||
}
|
||||
return globalToken.get();
|
||||
}
|
||||
|
||||
public void initToken() throws RuntimeException {
|
||||
if (isAcquiringToken.compareAndSet(false, true)) {
|
||||
globalToken.set(null);
|
||||
try {
|
||||
String data = "{\"sysUserId\":\"" + sysUserId + "\",\"expire\":1000000}";
|
||||
String encrypt;
|
||||
try {
|
||||
encrypt = AESpkcs7paddingUtil.encrypt(data, secret);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
JSONObject request = new JSONObject();
|
||||
request.put("request", encrypt);
|
||||
String resp = sendPost("https://aicc.cuopen.net:9801/aicc-api/ssb/callout/thirdParty/login", request);
|
||||
|
||||
TypeReference<AICCCallRespWrapper<AICCLogin>> type = new TypeReference<AICCCallRespWrapper<AICCLogin>>() {
|
||||
};
|
||||
AICCCallRespWrapper<AICCLogin> AICCCallRespWrapper = JSON.parseObject(resp, type);
|
||||
if (AICCCallRespWrapper == null || !AICCCallRespWrapper.isSuccess() || AICCCallRespWrapper.getResult() == null) {
|
||||
log.warn("获取外呼系统token失败");
|
||||
return;
|
||||
}
|
||||
|
||||
AICCLogin result = AICCCallRespWrapper.getResult();
|
||||
String token = result.getToken();
|
||||
if (token != null && !token.isEmpty()) {
|
||||
globalToken.set(token);
|
||||
}
|
||||
} finally {
|
||||
isAcquiringToken.set(false);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
latch.await();
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AICCCallRespWrapper<AICCCallRespTask> apiUploadCallData(AICCUploadTask data) {
|
||||
return apiUploadCallData(data, getToken());
|
||||
}
|
||||
|
||||
public AICCCallRespWrapper<AICCCallRespTask> apiUploadCallData(AICCUploadTask data, String token) {
|
||||
String e;
|
||||
try {
|
||||
e = AESpkcs7paddingUtil.encrypt(JSON.toJSONString(data), secret);
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
JSONObject request = new JSONObject();
|
||||
request.put("request", e);
|
||||
String resp = sendPost("https://aicc.cuopen.net:9801/aicc-api/ssb/callout/thirdParty/task/uploadCallData", request, token);
|
||||
|
||||
TypeReference<AICCCallRespWrapper<AICCCallRespTask>> type = new TypeReference<AICCCallRespWrapper<AICCCallRespTask>>() {
|
||||
};
|
||||
AICCCallRespWrapper<AICCCallRespTask> AICCCallRespWrapper = JSON.parseObject(resp, type);
|
||||
if (AICCCallRespWrapper == null || !AICCCallRespWrapper.isSuccess()) {
|
||||
initToken();
|
||||
resp = sendPost("https://aicc.cuopen.net:9801/aicc-api/ssb/callout/thirdParty/task/uploadCallData", request, token);
|
||||
AICCCallRespWrapper = JSON.parseObject(resp, type);
|
||||
}
|
||||
|
||||
if (AICCCallRespWrapper == null || !AICCCallRespWrapper.isSuccess()) {
|
||||
return null;
|
||||
}
|
||||
return AICCCallRespWrapper;
|
||||
}
|
||||
|
||||
public AICCCallRespWrapper<AICCCallRespDetail> apiGetTaskCallDetail(String requestId, String custId) {
|
||||
JSONObject request = new JSONObject();
|
||||
request.put("requestId", requestId);
|
||||
request.put("custId", custId);
|
||||
String resp = sendPost("https://aicc.cuopen.net:9801/aicc-api/ssb/callout/thirdParty/task/getTaskCallDetail", request);
|
||||
|
||||
TypeReference<AICCCallRespWrapper<AICCCallRespDetail>> type = new TypeReference<AICCCallRespWrapper<AICCCallRespDetail>>() {
|
||||
};
|
||||
AICCCallRespWrapper<AICCCallRespDetail> AICCCallRespWrapper = JSON.parseObject(resp, type);
|
||||
if (AICCCallRespWrapper == null || !AICCCallRespWrapper.isSuccess()) {
|
||||
initToken();
|
||||
resp = sendPost("https://aicc.cuopen.net:9801/aicc-api/ssb/callout/thirdParty/task/getTaskCallDetail", request);
|
||||
AICCCallRespWrapper = JSON.parseObject(resp, type);
|
||||
}
|
||||
|
||||
if (AICCCallRespWrapper == null || !AICCCallRespWrapper.isSuccess()) {
|
||||
return null;
|
||||
}
|
||||
return AICCCallRespWrapper;
|
||||
}
|
||||
|
||||
public AICCUploadTask newTask(String requestId, String custId, String custName, String content, List<String> numbers) {
|
||||
AICCUploadTask task = new AICCUploadTask();
|
||||
task.setTaskName(requestId);
|
||||
task.setProcessId(processId);
|
||||
task.setCallerGroup(callerGroup);
|
||||
task.setRequestId(requestId);
|
||||
task.genMutiTimeRange();
|
||||
AICCUploadTask.Cust param = AICCUploadTask.Cust.builder()
|
||||
.setCustName(custName)
|
||||
.setCustId(custId)
|
||||
.setContent(content)
|
||||
.set_numbers(numbers)
|
||||
.build();
|
||||
task.setParam(Collections.singletonList(param));
|
||||
|
||||
return task;
|
||||
}
|
||||
|
||||
private String sendPost(String url, JSONObject jsonData) {
|
||||
String resp = sendPost(url, jsonData.toJSONString());
|
||||
if (resp == null) {
|
||||
resp = sendPost(url, jsonData.toJSONString());
|
||||
}
|
||||
return resp;
|
||||
}
|
||||
|
||||
private String sendPost(String url, JSONObject jsonData, String token) {
|
||||
String resp = sendPost(url, jsonData.toJSONString(), token);
|
||||
if (resp == null) {
|
||||
resp = sendPost(url, jsonData.toJSONString(), token);
|
||||
}
|
||||
return resp;
|
||||
}
|
||||
|
||||
private String sendPost(String url, String jsonData) {
|
||||
return sendPost(url, jsonData, getToken());
|
||||
}
|
||||
|
||||
private String sendPost(String url, String jsonData, String token) {
|
||||
CloseableHttpResponse response = null;
|
||||
CloseableHttpClient httpClient = null;
|
||||
String responseContent = null;
|
||||
try {
|
||||
httpClient = HttpClients.createDefault();
|
||||
HttpPost httpPost = new HttpPost(url);
|
||||
httpPost.addHeader("Content-Type", "application/json");
|
||||
httpPost.addHeader("X-Access-Token", token);
|
||||
|
||||
if (StringUtils.isNotBlank(jsonData)) {
|
||||
httpPost.setEntity(new StringEntity(jsonData, "UTF-8"));
|
||||
}
|
||||
|
||||
log.info("请求地址: " + url);
|
||||
log.info("token: " + getToken());
|
||||
log.info("请求参数: " + jsonData);
|
||||
|
||||
response = httpClient.execute(httpPost);
|
||||
HttpEntity entity = response.getEntity();
|
||||
responseContent = EntityUtils.toString(entity, "UTF-8");
|
||||
responseContent = jsonFormat(responseContent);
|
||||
if (responseContent.length() < 200) {
|
||||
log.info("响应参数: " + responseContent);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("发送请求异常", e);
|
||||
return null;
|
||||
} finally {
|
||||
try {
|
||||
if (null != response) {
|
||||
response.close();
|
||||
}
|
||||
httpClient.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return responseContent;
|
||||
}
|
||||
|
||||
private static String jsonFormat(String str) {
|
||||
if (JSON.isValidObject(str)) {
|
||||
str = JSON.parseObject(str).toJSONString();
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
|
@ -4,10 +4,7 @@ import java.text.ParseException;
|
|||
import java.text.SimpleDateFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.Objects;
|
||||
import java.util.SimpleTimeZone;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author 李赛
|
||||
|
|
@ -118,6 +115,23 @@ public class DateUtils {
|
|||
return simpleDateFormat.parse(dateStr);
|
||||
}
|
||||
|
||||
public static Date standardize(Date date, boolean stm) {
|
||||
Calendar c = Calendar.getInstance();
|
||||
c.setTime(date);
|
||||
if (stm) {
|
||||
c.set(Calendar.HOUR_OF_DAY, 0);
|
||||
c.set(Calendar.MINUTE, 0);
|
||||
c.set(Calendar.SECOND, 0);
|
||||
c.set(Calendar.MILLISECOND, 0);
|
||||
} else {
|
||||
c.set(Calendar.HOUR_OF_DAY, 23);
|
||||
c.set(Calendar.MINUTE, 59);
|
||||
c.set(Calendar.SECOND, 59);
|
||||
c.set(Calendar.MILLISECOND, 999);
|
||||
}
|
||||
return c.getTime();
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) throws ParseException {
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,216 @@
|
|||
package com.whdc.utils;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import okhttp3.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author lyf
|
||||
* @since 2025-06-25
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class HttpHelper {
|
||||
@Autowired
|
||||
private OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
|
||||
|
||||
public @NotNull String get(@NotNull String url, @Nullable Map<String, String> params, @Nullable Map<String, String> headers) {
|
||||
if (url.isEmpty()) {
|
||||
return "url为空";
|
||||
}
|
||||
|
||||
Request.Builder requestBuilder = new Request.Builder()
|
||||
.url(url)
|
||||
.get();
|
||||
|
||||
//header
|
||||
if (headers != null) {
|
||||
for (Map.Entry<String, String> entry : headers.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
String value = entry.getValue();
|
||||
if (key != null && value != null) {
|
||||
requestBuilder.header(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
//doGet
|
||||
Request request = requestBuilder.build();
|
||||
|
||||
return doGet(request);
|
||||
}
|
||||
|
||||
private @NotNull String doGet(Request request) {
|
||||
try (Response response = okHttpClient.newCall(request).execute()) {
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
return response.body().string();
|
||||
} else {
|
||||
return "请求失败:" + response;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
return "网络异常:" + e.getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
public @NotNull String postJsonString(@NotNull String url, @Nullable String json, @Nullable Map<String, String> headers) {
|
||||
return postJsonString(url, json, headers, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
public @NotNull String postJsonString(@NotNull String url, @Nullable String json, @Nullable Map<String, String> headers, @NotNull Charset charset) {
|
||||
if (url.isEmpty()) {
|
||||
return "url为空";
|
||||
}
|
||||
if (json == null) {
|
||||
json = "{}";
|
||||
}
|
||||
|
||||
//mediatype
|
||||
MediaType mediaType = MediaType.get("application/json");
|
||||
//payload
|
||||
RequestBody requestBody = RequestBody.create(json, mediaType);
|
||||
//builder
|
||||
Request.Builder requestBuilder = new Request.Builder()
|
||||
.url(url)
|
||||
.header("Content-Type", mediaType + ";charset=" + charset.name())
|
||||
.post(requestBody);
|
||||
//header
|
||||
if (headers != null) {
|
||||
for (Map.Entry<String, String> entry : headers.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
String value = entry.getValue();
|
||||
if (key != null && value != null) {
|
||||
requestBuilder.header(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
Request request = requestBuilder.build();
|
||||
//post
|
||||
return doPost(request);
|
||||
}
|
||||
|
||||
public @NotNull String postFormData(@NotNull String url, @Nullable Map<String, Object> params, @Nullable Map<String, String> headers) {
|
||||
return postFormData(url, params, headers, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
public @NotNull String postFormData(@NotNull String url, @Nullable Map<String, Object> params, @Nullable Map<String, String> headers, @NotNull Charset charset) {
|
||||
if (url.isEmpty()) {
|
||||
return "url为空";
|
||||
}
|
||||
|
||||
//mediatype
|
||||
MediaType mediaType = MultipartBody.FORM;
|
||||
//payload
|
||||
MultipartBody.Builder bodyBuilder = new MultipartBody.Builder()
|
||||
.setType(MultipartBody.FORM);
|
||||
if (params != null) {
|
||||
for (Map.Entry<String, Object> entry : params.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
if (key == null || value == null) {
|
||||
continue;
|
||||
}
|
||||
if (value instanceof String) {
|
||||
bodyBuilder.addFormDataPart(key, (String) value);
|
||||
} else if (value instanceof File) {
|
||||
File file = (File) value;
|
||||
RequestBody fileBody = RequestBody.create(file, MediaType.get("application/octet-stream"));
|
||||
bodyBuilder.addFormDataPart(key, file.getName(), fileBody);
|
||||
} else {
|
||||
return "不支持的参数类型";
|
||||
}
|
||||
}
|
||||
}
|
||||
RequestBody requestBody = bodyBuilder.build();
|
||||
//builder
|
||||
Request.Builder requestBuilder = new Request.Builder()
|
||||
.url(url)
|
||||
.header("Content-Type", mediaType + ";charset=" + charset.name())
|
||||
.post(requestBody);
|
||||
//header
|
||||
if (headers != null) {
|
||||
for (Map.Entry<String, String> entry : headers.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
String value = entry.getValue();
|
||||
if (key != null && value != null) {
|
||||
requestBuilder.header(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
//post
|
||||
Request request = requestBuilder.build();
|
||||
|
||||
return doPost(request);
|
||||
}
|
||||
|
||||
public @NotNull String postFormUrlEncoded(@NotNull String url, @Nullable Map<String, Object> params, @Nullable Map<String, String> headers) {
|
||||
return postFormUrlEncoded(url, params, headers, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
public @NotNull String postFormUrlEncoded(@NotNull String url, @Nullable Map<String, Object> params, @Nullable Map<String, String> headers, @NotNull Charset charset) {
|
||||
if (url.isEmpty()) {
|
||||
return "url为空";
|
||||
}
|
||||
|
||||
//mediatype
|
||||
MediaType mediaType = MediaType.get("application/x-www-form-urlencoded");
|
||||
//payload
|
||||
FormBody.Builder bodyBuilder = new FormBody.Builder(charset);
|
||||
if (params != null) {
|
||||
for (Map.Entry<String, Object> entry : params.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
if (key != null && value != null) {
|
||||
try {
|
||||
// Manually encode using GBK
|
||||
String encodedValue = URLEncoder.encode(value.toString(), "GBK");
|
||||
bodyBuilder.addEncoded(key, encodedValue);
|
||||
} catch (Exception e) {
|
||||
return "参数encode错误";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
RequestBody formBody = bodyBuilder.build();
|
||||
//builder
|
||||
Request.Builder requestBuilder = new Request.Builder()
|
||||
.url(url)
|
||||
.header("Content-Type", mediaType + ";charset=" + charset.name())
|
||||
.post(formBody);
|
||||
//header
|
||||
if (headers != null) {
|
||||
for (Map.Entry<String, String> entry : headers.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
String value = entry.getValue();
|
||||
if (key != null && value != null) {
|
||||
requestBuilder.header(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
//post
|
||||
Request request = requestBuilder.build();
|
||||
|
||||
return doPost(request);
|
||||
}
|
||||
|
||||
private @NotNull String doPost(Request request) {
|
||||
try (Response response = okHttpClient.newCall(request).execute()) {
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
return response.body().string();
|
||||
} else {
|
||||
return "请求失败:" + response;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
return "网络异常:" + e.getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -393,6 +393,7 @@ public class HttpUtil {
|
|||
}
|
||||
|
||||
log.info("请求地址: " + url);
|
||||
log.info("请求header: " + header);
|
||||
log.info("请求参数: " + jsonData);
|
||||
|
||||
|
||||
|
|
@ -402,7 +403,9 @@ public class HttpUtil {
|
|||
|
||||
responseContent = jsonFormat(responseContent);
|
||||
|
||||
if (responseContent.length() < 200) {
|
||||
log.info("响应参数: " + responseContent);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("发送请求异常", e);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,174 @@
|
|||
package com.whdc.utils;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author lyf
|
||||
* @since 2025-06-25
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class SmsHelper {
|
||||
@Value("${sms.url}")
|
||||
private String url;
|
||||
@Value("${sms.userName}")
|
||||
private String userName;
|
||||
@Value("${sms.serviceCode}")
|
||||
private String serviceCode;
|
||||
@Value("${sms.userPassword}")
|
||||
private String userPassword;
|
||||
@Autowired
|
||||
private HttpHelper httpHelper;
|
||||
|
||||
public String send(List<String> phones, String content) {
|
||||
return send(phones, content, "201");
|
||||
}
|
||||
|
||||
private String send(List<String> phones, String content, String msgType) {
|
||||
if (phones == null || phones.size() == 0) {
|
||||
return "未选择手机号";
|
||||
}
|
||||
if (content == null || content.length() == 0) {
|
||||
return "短信内容为空";
|
||||
}
|
||||
|
||||
String[] msgIds = new String[phones.size()];
|
||||
for (int i = 0; i < phones.size(); i++) {
|
||||
msgIds[i] = UUID.randomUUID().toString().replace("-", "");
|
||||
}
|
||||
String strPhones = String.join(",", phones);
|
||||
String strMsgIds = String.join(",", msgIds);
|
||||
String timestamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
|
||||
String sign = md5(userPassword + timestamp).toUpperCase();
|
||||
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("serviceCode", serviceCode);
|
||||
params.put("userName", userName);
|
||||
params.put("userPassword", userPassword);
|
||||
params.put("phones", strPhones);
|
||||
params.put("msgContent", encodeGBK(content));
|
||||
params.put("timestamp", timestamp);
|
||||
params.put("sign", sign);
|
||||
params.put("mhtMsgIds", strMsgIds);
|
||||
params.put("sendTime", "");
|
||||
params.put("priority", "5");
|
||||
params.put("orgCode", "42");
|
||||
params.put("msgType", msgType);
|
||||
params.put("reportFlag", "0");
|
||||
|
||||
String strResult = httpHelper.postFormUrlEncoded(url, params, null, Charset.forName("GBK"));
|
||||
if (strResult == null) {
|
||||
return "发送失败";
|
||||
}
|
||||
|
||||
// Map result = new ObjectMapper().readValue(strResult, Map.class);
|
||||
JSONObject result = JSON.parseObject(strResult);
|
||||
if (result == null) {
|
||||
return "发送结果解析失败";
|
||||
}
|
||||
int errorCode = (Integer) result.get("result");
|
||||
if (errorCode != 0) {
|
||||
return SmtpErrorCode.getErrorString(errorCode);
|
||||
}
|
||||
|
||||
return "发送成功";
|
||||
}
|
||||
|
||||
private String md5(String str) {
|
||||
MessageDigest m;
|
||||
try {
|
||||
m = MessageDigest.getInstance("MD5");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
m.update(str.getBytes());
|
||||
byte[] s = m.digest();
|
||||
return parseByte2HexStr(s);
|
||||
}
|
||||
|
||||
private static String encodeGBK(String content) {
|
||||
try {
|
||||
return URLDecoder.decode(content, "GBK");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
//将二进制数组转换成16进制字符串
|
||||
private String parseByte2HexStr(byte[] buf) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (byte b : buf) {
|
||||
String hex = Integer.toHexString(b & 0xFF);
|
||||
if (hex.length() == 1) {
|
||||
hex = '0' + hex;
|
||||
}
|
||||
sb.append(hex);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static class SmtpErrorCode {
|
||||
private static Map<Integer, String> map;
|
||||
|
||||
static {
|
||||
map = new HashMap<>();
|
||||
|
||||
map.put(100, "非法登录,如登录名、口令出错、登录名与口令不符,md5 值不匹配等。");
|
||||
map.put(101, "连接过多,指单个商户要求同时建立的连接数过多。");
|
||||
map.put(102, "登陆类型错。");
|
||||
map.put(103, "协议版本号错");
|
||||
map.put(104, "ip 不合法,请联系管理员绑定 ip 后才可正常使用");
|
||||
map.put(105, "Smtp 的 tcp 协议只支持后付费类型");
|
||||
|
||||
map.put(201, "非法手机号码。");
|
||||
map.put(202, "reportFlag 值不合法,值必须为 0 或 1");
|
||||
map.put(203, "信息长度错");
|
||||
map.put(204, "短信内容中有非法字符");
|
||||
map.put(205, "短信内容太长");
|
||||
map.put(206, "不存在的优先级");
|
||||
map.put(207, "SUBMIT 命令中的 serviceCode 不合法或者过期");
|
||||
map.put(208, "手机号和商户消息 id 个数不匹配");
|
||||
map.put(209, "orgCode 字段超过规定长度");
|
||||
map.put(210, "msgType 字段超过规定长度");
|
||||
map.put(211, "http 提交短信时的 url 不正确");
|
||||
map.put(212, "被代理的商户与代理商户之间的关系不合法");
|
||||
map.put(213, "暂未开通此商户通道,或者商户通道名称配置错误");
|
||||
map.put(214, "请求参数有误,比如传递了不在接口文档中定义的参数");
|
||||
map.put(215, "被代理的商户 id 不存在");
|
||||
map.put(216, "商户平台的消息 id 的长度超过最大长度");
|
||||
map.put(217, "sendTime 参数时间戳格式不正确");
|
||||
map.put(218, "商户服务代码与用户名密码不匹配");
|
||||
map.put(219, "接口只支持 HTTP POST 方式提交,而您的请求为 HTTP GET 方式");
|
||||
map.put(220, "批量提交一次最多只支持 50 个");
|
||||
map.put(221, "手机号不能为空");
|
||||
map.put(222, "短信内容含有乱码");
|
||||
|
||||
map.put(500, "系统内部失败");
|
||||
|
||||
map.put(900, "余额不足");
|
||||
map.put(901, "发送速度太快");
|
||||
}
|
||||
|
||||
public static String getErrorString(int errorcode) {
|
||||
if (!map.containsKey(errorcode)) {
|
||||
return "errorcode:" + errorcode + "未定义";
|
||||
}
|
||||
|
||||
return map.get(errorcode);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -6,6 +6,10 @@ server:
|
|||
session:
|
||||
# 配置会话超时
|
||||
timeout: 120s
|
||||
encoding:
|
||||
charset: UTF-8
|
||||
enabled: true
|
||||
force: true
|
||||
spring:
|
||||
#数据库配置
|
||||
datasource:
|
||||
|
|
@ -86,3 +90,16 @@ wx:
|
|||
|
||||
#getGroupWarning: http://223.75.53.141:8000/shzh/met/zyqxfw/api/warning/getGroupWarning
|
||||
getGroupWarning: http://127.0.0.1:20000/shzh/met/zyqxfw/api/warning/getGroupWarning
|
||||
|
||||
autocall:
|
||||
sysUserId: HBSL01 # 平台网页https://aicc.cuopen.net:9801/login 密码Gswl@2025
|
||||
processId: 1935233125932101634
|
||||
# processId: 1934801506242949122
|
||||
# callerGroup: 02160980358
|
||||
callerGroup: 02759325005
|
||||
secret: yxt@2024-1234567
|
||||
sms:
|
||||
url: http://120.55.193.51:8098/smtp/http/submit
|
||||
userName: hbfx15
|
||||
serviceCode: hbfx15
|
||||
userPassword: hbfx15
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
log4j.rootLogger=ERROR
|
||||
log4j.logger.org.apache.http=ERROR
|
||||
|
|
@ -34,7 +34,7 @@
|
|||
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
|
||||
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||
<level>debug</level>
|
||||
<level>info</level>
|
||||
</filter>
|
||||
<encoder>
|
||||
<Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
|
||||
|
|
@ -199,15 +199,16 @@
|
|||
<logger name="o.a.http.impl.execchain.MainClientExec" level="error" additivity="false"/>
|
||||
<logger name=".i.c.DefaultHttpClientConnectionOperator" level="error" additivity="false"/>
|
||||
<logger name=".a.http.impl.execchain.MainClientExec" level="error" additivity="false"/>
|
||||
<logger name="org.apache.http" level="error" additivity="false"/>
|
||||
<!--
|
||||
ERROR [ModelSpecification.spec] At least one type of specification is required
|
||||
https://github.com/jhipster/generator-jhipster/pull/15004/files
|
||||
-->
|
||||
<logger name="Validator" level="INFO"/>
|
||||
|
||||
<root level="debug">
|
||||
<root level="INFO">
|
||||
<appender-ref ref="CONSOLE"/>
|
||||
<appender-ref ref="DEBUG_FILE"/>
|
||||
<!-- <appender-ref ref="DEBUG_FILE"/>-->
|
||||
<appender-ref ref="INFO_FILE"/>
|
||||
<appender-ref ref="WARN_FILE"/>
|
||||
<appender-ref ref="ERROR_FILE"/>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
<?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" >
|
||||
<mapper namespace="com.whdc.mapper.AutoCallMapper">
|
||||
<select id="getListByLevelAndStatus" resultType="com.whdc.model.entity.AutoCall">
|
||||
select * from AUTOCALL A
|
||||
where 1=1
|
||||
<if test="level != null">
|
||||
and A.LEVEL = #{adnm}
|
||||
</if>
|
||||
<if test="status != null and called == null">
|
||||
and A.STATUS = #{status}
|
||||
</if>
|
||||
<if test="called != null and called == true">
|
||||
and A.STATUS is not null
|
||||
</if>
|
||||
<if test="called != null and called == false">
|
||||
and A.STATUS is null
|
||||
</if>
|
||||
<if test="stm != null and etm != null">
|
||||
AND A._create_tm BETWEEN #{stm} AND #{etm}
|
||||
</if>
|
||||
</select>
|
||||
</mapper>
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
<?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" >
|
||||
<mapper namespace="com.whdc.mapper.AutoCallTaskMapper">
|
||||
<select id="listWarnsThatNotGeneratedTask" resultType="com.whdc.model.entity.QXWarning">
|
||||
SELECT
|
||||
Q.*
|
||||
FROM
|
||||
FXKH_TXL.QXWARNING Q
|
||||
WHERE
|
||||
NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM FXKH_TXL.AUTOCALL_TASK TASK
|
||||
WHERE TASK.WARN_ID = Q.WARNID
|
||||
)
|
||||
AND Q.PUBLISH_TIME > (
|
||||
SELECT MAX(TASK_LATEST.warn_tm)
|
||||
FROM FXKH_TXL.AUTOCALL_TASK TASK_LATEST
|
||||
)
|
||||
ORDER BY Q.WARNID ASC;
|
||||
</select>
|
||||
<select id="getList" resultType="com.whdc.model.entity.AutoCallTask">
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
FXKH_TXL.AUTOCALL_TASK TASK
|
||||
WHERE
|
||||
TASK.AUTOCALL_ID IS NULL
|
||||
AND TASK.SHOULD_GENERATE = 1
|
||||
AND TASK.GENERATED = 0
|
||||
</select>
|
||||
</mapper>
|
||||
|
|
@ -29,6 +29,17 @@
|
|||
WF.ID IS NULL
|
||||
ORDER BY Q.WARNID DESC
|
||||
</select>
|
||||
<select id="findByAutoMsgIsNull" resultType="com.whdc.model.vo.QXWarningVO">
|
||||
SELECT
|
||||
Q.*, 0 STATUS
|
||||
FROM
|
||||
FXKH_TXL.QXWARNING Q
|
||||
LEFT JOIN FXKH_TXL.AUTOCALL WF ON WF.WARN_ID = Q.WARNID
|
||||
WHERE
|
||||
WF.ID IS NULL
|
||||
AND Q.PUBLISH_TIME >= '2025-06-19 09:00:00'
|
||||
ORDER BY Q.WARNID DESC
|
||||
</select>
|
||||
<select id="page" resultType="com.whdc.model.vo.QXWarningVO">
|
||||
SELECT
|
||||
Q.*,IF( WF.ID IS NOT NULL,1,0) STATUS
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
<?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" >
|
||||
<mapper namespace="com.whdc.mapper.WarnCallMapMapper">
|
||||
<select id="listWarnsThatNotGeneratedWcm" resultType="com.whdc.model.entity.QXWarning">
|
||||
SELECT
|
||||
Q.*
|
||||
FROM
|
||||
FXKH_TXL.QXWARNING Q
|
||||
WHERE
|
||||
NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM FXKH_TXL.WARN_CALL_MAP WCM
|
||||
WHERE WCM.WARN_ID = Q.WARNID
|
||||
)
|
||||
AND Q.PUBLISH_TIME > (
|
||||
SELECT MAX(WCM_LATEST.warn_tm)
|
||||
FROM FXKH_TXL.WARN_CALL_MAP WCM_LATEST
|
||||
)
|
||||
ORDER BY Q.WARNID ASC;
|
||||
</select>
|
||||
<select id="getWCMList" resultType="com.whdc.model.entity.AutoCall">
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
FXKH_TXL.WARN_CALL_MAP WCM
|
||||
WHERE
|
||||
WCM.AUTOCALL_ID IS NULL
|
||||
AND WCM.SHOULD_GENERATE = 1
|
||||
AND WCM.GENERATED = 0
|
||||
</select>
|
||||
</mapper>
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<?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">
|
||||
<mapper namespace="com.whdc.mapper.AddressBookOldMapper">
|
||||
<mapper namespace="com.whdc.mapper.WarningResponderMapper">
|
||||
|
||||
<!-- AND AB.ADCD ${dto.v} #{dto.adcd}-->
|
||||
<select id="page" resultType="com.whdc.model.vo.AddressBookVo">
|
||||
|
|
@ -89,7 +89,7 @@
|
|||
LEFT JOIN ADINFO A ON AB.ADCD = A.ADCD
|
||||
WHERE AB.OPENID = #{id}
|
||||
</select>
|
||||
<select id="getListByAdnm2" resultType="com.whdc.model.entity.AddressBookOld">
|
||||
<select id="getListByAdnm2" resultType="com.whdc.model.entity.WarningResponder">
|
||||
select * from ADDRESS_BOOK_OLD A
|
||||
where 1=1 and
|
||||
<if test="adnm != null and adnm != '' ">
|
||||
|
|
@ -97,5 +97,18 @@
|
|||
</if>
|
||||
</select>
|
||||
|
||||
<select id="listByCnnmAndLevelOrderByLevelAsc" resultType="com.whdc.model.entity.WarningResponder">
|
||||
select * from ADDRESS_BOOK_OLD A
|
||||
where 1=1
|
||||
<if test="cnnm != null and cnnm != '' ">
|
||||
<!-- and A.CNNM like CONCAT('%',#{cnnm},'%')-->
|
||||
and A.CNNM = #{cnnm}
|
||||
</if>
|
||||
and level in
|
||||
<foreach collection="levels" item="item" index="index" open="(" separator="," close=")">
|
||||
#{item}
|
||||
</foreach>
|
||||
order by level asc
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
Loading…
Reference in New Issue