ApiController.java 92 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139
  1. package com.ruoyi.aicall.controller;
  2. import com.alibaba.fastjson.JSONArray;
  3. import com.alibaba.fastjson.JSONObject;
  4. import com.ruoyi.aicall.domain.*;
  5. import com.ruoyi.aicall.model.*;
  6. import com.ruoyi.aicall.service.*;
  7. import com.ruoyi.aicall.utils.ClientIpCheck;
  8. import com.ruoyi.aicall.utils.DESUtil;
  9. import com.ruoyi.cc.domain.*;
  10. import com.ruoyi.cc.service.*;
  11. import com.ruoyi.cc.utils.DateValidatorUtils;
  12. import com.ruoyi.common.core.controller.BaseController;
  13. import com.ruoyi.common.core.domain.AjaxResult;
  14. import com.ruoyi.common.core.domain.entity.SysUser;
  15. import com.ruoyi.common.core.page.TableDataInfo;
  16. import com.ruoyi.common.utils.CommonUtils;
  17. import com.ruoyi.common.utils.DateUtils;
  18. import com.ruoyi.common.utils.ShiroUtils;
  19. import com.ruoyi.common.utils.StringUtils;
  20. import com.ruoyi.common.utils.bean.BeanUtils;
  21. import com.ruoyi.common.utils.uuid.UuidGenerator;
  22. import com.ruoyi.framework.shiro.service.SysPasswordService;
  23. import com.ruoyi.framework.shiro.util.AuthorizationUtils;
  24. import com.ruoyi.system.domain.SysConfig;
  25. import com.ruoyi.system.service.ISysConfigService;
  26. import com.ruoyi.system.service.ISysUserService;
  27. import lombok.extern.slf4j.Slf4j;
  28. import org.apache.commons.lang3.RandomUtils;
  29. import org.springframework.beans.factory.annotation.Autowired;
  30. import org.springframework.stereotype.Controller;
  31. import org.springframework.transaction.annotation.Transactional;
  32. import org.springframework.util.CollectionUtils;
  33. import org.springframework.web.bind.annotation.*;
  34. import javax.servlet.http.HttpServletRequest;
  35. import java.io.UnsupportedEncodingException;
  36. import java.net.URLDecoder;
  37. import java.net.URLEncoder;
  38. import java.util.*;
  39. import java.util.stream.Collectors;
  40. @Controller
  41. @Slf4j
  42. @RequestMapping("/aicall/api")
  43. public class ApiController extends BaseController {
  44. @Autowired
  45. private ICcCallTaskService callTaskService;
  46. @Autowired
  47. private ICcCallPhoneService ccCallPhoneService;
  48. @Autowired
  49. private ICcInboundCdrService inboundCdrService;
  50. @Autowired
  51. private ICcOutboundCdrService outboundCdrService;
  52. @Autowired
  53. private ICcParamsService paramsService;
  54. @Autowired
  55. private ICcGatewaysService ccGatewaysService;
  56. @Autowired
  57. private ICcLlmAgentAccountService ccLlmAgentAccountService;
  58. @Autowired
  59. private ICcBizGroupService ccBizGroupService;
  60. @Autowired
  61. private ICcCallTaskService ccCallTaskService;
  62. @Autowired
  63. private ICcTtsAliyunService ccTtsAliyunService;
  64. @Autowired
  65. private ICcExtNumService ccExtNumService;
  66. @Autowired
  67. private ICcParamsService ccParamsService;
  68. @Autowired
  69. private ISysUserService userService;
  70. @Autowired
  71. private SysPasswordService passwordService;
  72. @Autowired
  73. private ICcCustCallRecordService ccCustCallRecordService;
  74. @Autowired
  75. private ICcCustInfoService ccCustInfoService;
  76. @Autowired
  77. private ISysDivisionDataService sysDivisionDataService;
  78. @Autowired
  79. private ICcOutboundCdrService ccOutboundCdrService;
  80. @Autowired
  81. private ISysConfigService sysConfigService;
  82. @Autowired
  83. private ICcAsrLanguagesService asrLanguagesService;
  84. /**
  85. * 获取外呼网关列表接口
  86. * @param req
  87. * @return
  88. */
  89. @GetMapping("/gateway/list")
  90. @ResponseBody
  91. public AjaxResult getGatewayList(HttpServletRequest req, @RequestParam(value = "purposes", required = false) String purposes){
  92. // 校验客户端ip是否在白名单内
  93. if (!ClientIpCheck.checkIp(req)) {
  94. return AjaxResult.error(AjaxResult.Type.NO_AUTH, "未授权,请联系系统管理员添加ip白名单!", "");
  95. }
  96. // 获取外呼网关列表
  97. Map<String, Object> params = new HashMap<>();
  98. if (StringUtils.isBlank(purposes)) {
  99. params.put("purposes", Arrays.asList(1,2,3));
  100. } else {
  101. params.put("purposes", Arrays.asList(purposes.split(",")));
  102. }
  103. List<CcGateways> list = ccGatewaysService.selectCcGatewaysList(new CcGateways().setParams(params));
  104. List<ApiGatewaysModel> result = new ArrayList<>();
  105. for (CcGateways data: list) {
  106. ApiGatewaysModel model = new ApiGatewaysModel();
  107. BeanUtils.copyProperties(data, model);
  108. result.add(model);
  109. }
  110. return AjaxResult.success(result);
  111. }
  112. /**
  113. * 获取大模型列表接口
  114. * @param req
  115. * @return
  116. */
  117. @GetMapping("/llmacount/list")
  118. @ResponseBody
  119. public AjaxResult getLlmAcountList(HttpServletRequest req){
  120. // 校验客户端ip是否在白名单内
  121. if (!ClientIpCheck.checkIp(req)) {
  122. return AjaxResult.error(AjaxResult.Type.NO_AUTH, "未授权,请联系系统管理员添加ip白名单!", "");
  123. }
  124. // 获取大模型列表
  125. List<CcLlmAgentAccount> list = ccLlmAgentAccountService.selectCcLlmAgentAccountList(new CcLlmAgentAccount());
  126. return AjaxResult.success(list);
  127. }
  128. /**
  129. * 获取音色列表
  130. * @return
  131. */
  132. @GetMapping("/voicecode/list")
  133. @ResponseBody
  134. public AjaxResult getVoiceCodeList(HttpServletRequest req)
  135. {
  136. // 校验客户端ip是否在白名单内
  137. if (!ClientIpCheck.checkIp(req)) {
  138. return AjaxResult.error(AjaxResult.Type.NO_AUTH, "未授权,请联系系统管理员添加ip白名单!", "");
  139. }
  140. // 获取音色列表
  141. List<CcTtsAliyun> list = ccTtsAliyunService.selectCcTtsAliyunList(new CcTtsAliyun());
  142. JSONArray result = new JSONArray();
  143. for (CcTtsAliyun ttsAliyun: list) {
  144. JSONObject obj = new JSONObject();
  145. obj.put("voiceName", ttsAliyun.getVoiceName());
  146. obj.put("voiceCode", ttsAliyun.getVoiceCode());
  147. obj.put("voiceSource", ttsAliyun.getVoiceSource());
  148. obj.put("ttsModels", ttsAliyun.getTtsModels());
  149. result.add(obj);
  150. }
  151. return AjaxResult.success(result);
  152. }
  153. /**
  154. * 获取技能组列表
  155. * @param req
  156. * @return
  157. */
  158. @GetMapping("/busigroup/list")
  159. @ResponseBody
  160. public AjaxResult getBusigroupList(HttpServletRequest req){
  161. // // 校验客户端ip是否在白名单内
  162. // if (!ClientIpCheck.checkIp(req)) {
  163. // return AjaxResult.error(AjaxResult.Type.NO_AUTH, "未授权,请联系系统管理员添加ip白名单!", "");
  164. // }
  165. // 获取技能组列表
  166. List<CcBizGroup> list = ccBizGroupService.selectCcBizGroupList(new CcBizGroup());
  167. return AjaxResult.success(list);
  168. }
  169. /**
  170. * 通话记录查询接口(支持按时间、坐席、号码、呼入/呼出类型筛选)
  171. * @param req
  172. * @param queryParams
  173. * @return
  174. */
  175. @PostMapping("/calltask/list")
  176. @ResponseBody
  177. public TableDataInfo getCallTaskList(HttpServletRequest req, @RequestBody ApiCallTaskQueryParams queryParams)
  178. {
  179. TableDataInfo tableDataInfo;
  180. // 校验请求方ip是否合法
  181. if (!ClientIpCheck.checkIp(req)) {
  182. tableDataInfo = new TableDataInfo();
  183. tableDataInfo.setTotal(0);
  184. tableDataInfo.setCode(AjaxResult.Type.NO_AUTH.value());
  185. tableDataInfo.setMsg("未授权,请联系系统管理员添加ip白名单!");
  186. return tableDataInfo;
  187. }
  188. // 处理分页
  189. if (null == queryParams.getPageNum()) {
  190. queryParams.setPageNum(1);
  191. }
  192. if (null == queryParams.getPageSize()) {
  193. queryParams.setPageSize(20);
  194. }
  195. // 校验参数
  196. if (StringUtils.isNotEmpty(queryParams.getCreateTimeStart())
  197. && !DateValidatorUtils.isYmdHms(queryParams.getCreateTimeStart())) {
  198. tableDataInfo = new TableDataInfo();
  199. tableDataInfo.setTotal(0);
  200. tableDataInfo.setCode(AjaxResult.Type.INVALID_PARAM.value());
  201. tableDataInfo.setMsg("createTimeStart格式不正确,请使用'yyyy-MM-dd HH:mm:ss'格式!");
  202. return tableDataInfo;
  203. }
  204. if (StringUtils.isNotEmpty(queryParams.getCreateTimeEnd())
  205. && !DateValidatorUtils.isYmdHms(queryParams.getCreateTimeEnd())) {
  206. tableDataInfo = new TableDataInfo();
  207. tableDataInfo.setTotal(0);
  208. tableDataInfo.setCode(AjaxResult.Type.ERROR.value());
  209. tableDataInfo.setMsg("createTimeEnd格式不正确,请使用'yyyy-MM-dd HH:mm:ss'格式!");
  210. return tableDataInfo;
  211. }
  212. Map<String, Object> params = new HashMap<>();
  213. params.put("createTimeStart", queryParams.getCreateTimeStart());
  214. params.put("createTimeEnd", queryParams.getCreateTimeEnd());
  215. // 分页请求数据
  216. startPage(queryParams.getPageNum(), queryParams.getPageSize());
  217. CcCallTask ccCallTask = new CcCallTask();
  218. ccCallTask.setBatchId(queryParams.getBatchId());
  219. ccCallTask.setBatchName(queryParams.getBatchName());
  220. ccCallTask.setParams(params);
  221. List<CcCallTask> list = ccCallTaskService.selectCcCallTaskList(ccCallTask);
  222. tableDataInfo = getDataTable(list);
  223. List<CcCallTask> records = (List<CcCallTask>) tableDataInfo.getRows();
  224. for (CcCallTask data: records){
  225. CallTaskStatModel statModel = ccCallPhoneService.statByBatchId(data.getBatchId());
  226. data.setPhoneCount(statModel.getPhoneCount());
  227. data.setCallCount(statModel.getCallCount());
  228. data.setNoCallCount(statModel.getPhoneCount() - statModel.getCallCount());
  229. data.setConnectCount(statModel.getConnectCount());
  230. data.setNoConnectCount(statModel.getCallCount() - statModel.getConnectCount());
  231. if (data.getCallCount() > 0) {
  232. data.setRealConnectRate(data.getConnectCount()*1.0/data.getCallCount());
  233. } else {
  234. data.setRealConnectRate(0.0);
  235. }
  236. }
  237. tableDataInfo.setRows(records);
  238. return tableDataInfo;
  239. }
  240. /**
  241. * 根据uuid查询
  242. * @param req
  243. * @param uuid
  244. * @param callType
  245. * @return
  246. */
  247. @GetMapping("/record/uuid")
  248. @ResponseBody
  249. public AjaxResult getRecordByUuid(HttpServletRequest req, @RequestParam String uuid, @RequestParam String callType)
  250. {
  251. // 校验客户端ip是否在白名单内
  252. if (!ClientIpCheck.checkIp(req)) {
  253. return AjaxResult.error(AjaxResult.Type.NO_AUTH, "未授权,请联系系统管理员添加ip白名单!", "");
  254. }
  255. if (StringUtils.isBlank(callType)) {
  256. return AjaxResult.error(AjaxResult.Type.INVALID_PARAM, "callType不能为空!", "");
  257. }
  258. // 01:呼入, 02:AI外呼, 03:人工外呼
  259. ApiCallRecordQueryParams queryParams = new ApiCallRecordQueryParams().setUuid(uuid).setCallType(callType);
  260. TableDataInfo tableDataInfo = new TableDataInfo();
  261. if ("01".equals(callType)) {
  262. tableDataInfo = getInboundRecords(queryParams);
  263. } else if ("02".equals(callType)) {
  264. tableDataInfo = getAiCallRecords(queryParams);
  265. } else if ("03".equals(callType)) {
  266. tableDataInfo = getOutboundRecords(queryParams);
  267. }
  268. if (null != tableDataInfo.getRows() && tableDataInfo.getRows().size() > 0) {
  269. return AjaxResult.success(tableDataInfo.getRows().get(0));
  270. } else {
  271. return AjaxResult.success();
  272. }
  273. }
  274. /**
  275. * 通话记录查询接口(支持按时间、坐席、号码、呼入/呼出类型筛选)
  276. * @param req
  277. * @param queryParams
  278. * @return
  279. */
  280. @PostMapping("/records/list")
  281. @ResponseBody
  282. public TableDataInfo getRecordsList(HttpServletRequest req, @RequestBody ApiCallRecordQueryParams queryParams)
  283. {
  284. TableDataInfo tableDataInfo;
  285. // 校验请求方ip是否合法
  286. if (!ClientIpCheck.checkIp(req)) {
  287. tableDataInfo = new TableDataInfo();
  288. tableDataInfo.setTotal(0);
  289. tableDataInfo.setCode(AjaxResult.Type.NO_AUTH.value());
  290. tableDataInfo.setMsg("未授权,请联系系统管理员添加ip白名单!");
  291. return tableDataInfo;
  292. }
  293. // 分页参数处理
  294. if (null == queryParams.getPageNum()
  295. && null == queryParams.getPageSize()) {
  296. queryParams.setPageNum(1);
  297. queryParams.setPageSize(200000);
  298. }
  299. if (null == queryParams.getPageNum()) {
  300. queryParams.setPageNum(1);
  301. }
  302. if (null == queryParams.getPageSize()) {
  303. queryParams.setPageSize(20);
  304. }
  305. // 类型(01:呼入, 02:AI外呼, 03:人工外呼)
  306. String callType = queryParams.getCallType();
  307. if (StringUtils.isBlank(callType)) {
  308. tableDataInfo = new TableDataInfo();
  309. tableDataInfo.setTotal(0);
  310. tableDataInfo.setCode(AjaxResult.Type.INVALID_PARAM.value());
  311. tableDataInfo.setMsg("callType不能为空!");
  312. return tableDataInfo;
  313. }
  314. // 校验参数
  315. if (StringUtils.isNotEmpty(queryParams.getCalloutTimeStart())
  316. && !DateValidatorUtils.isYmdHms(queryParams.getCalloutTimeStart())) {
  317. tableDataInfo = new TableDataInfo();
  318. tableDataInfo.setTotal(0);
  319. tableDataInfo.setCode(AjaxResult.Type.INVALID_PARAM.value());
  320. tableDataInfo.setMsg("calloutTimeStart格式不正确,请使用'yyyy-MM-dd HH:mm:ss'格式!");
  321. return tableDataInfo;
  322. }
  323. if (StringUtils.isNotEmpty(queryParams.getCalloutTimeEnd())
  324. && !DateValidatorUtils.isYmdHms(queryParams.getCalloutTimeEnd())) {
  325. tableDataInfo = new TableDataInfo();
  326. tableDataInfo.setTotal(0);
  327. tableDataInfo.setCode(AjaxResult.Type.INVALID_PARAM.value());
  328. tableDataInfo.setMsg("calloutTimeStart格式不正确,请使用'yyyy-MM-dd HH:mm:ss'格式!");
  329. return tableDataInfo;
  330. }
  331. // 01:呼入, 02:AI外呼, 03:人工外呼
  332. if ("01".equals(callType)) {
  333. return getInboundRecords(queryParams);
  334. } else if ("02".equals(callType)) {
  335. return getAiCallRecords(queryParams);
  336. } else if ("03".equals(callType)) {
  337. return getOutboundRecords(queryParams);
  338. } else {
  339. tableDataInfo = new TableDataInfo();
  340. tableDataInfo.setTotal(0);
  341. tableDataInfo.setCode(AjaxResult.Type.INVALID_PARAM.value());
  342. tableDataInfo.setMsg("callType参数不合法,呼入请输入01,AI外呼请输入02,手工外呼请输入03!");
  343. return tableDataInfo;
  344. }
  345. }
  346. /**
  347. * 创建外呼任务接口(含任务名称、优先级、并发数、TTS/音频模板等参数)接口
  348. * @param req
  349. * @param apiCallTaskModel
  350. * @return
  351. */
  352. @PostMapping("/ai/createTask")
  353. @ResponseBody
  354. public AjaxResult createCallTask(HttpServletRequest req, @RequestBody ApiCallTaskModel apiCallTaskModel) {
  355. // 校验ip白名单
  356. if (!ClientIpCheck.checkIp(req)) {
  357. return AjaxResult.error(AjaxResult.Type.NO_AUTH, "未授权,请联系系统管理员添加ip白名单!", "");
  358. }
  359. CcCallTask ccCallTask = new CcCallTask();
  360. // 校验参数
  361. // 任务名称不能为空
  362. if (StringUtils.isBlank(apiCallTaskModel.getBatchName())) {
  363. return AjaxResult.error(AjaxResult.Type.INVALID_PARAM, "batchName不能为空!", "");
  364. }
  365. // threadNum不能为空
  366. if (null == apiCallTaskModel.getThreadNum()) {
  367. return AjaxResult.error(AjaxResult.Type.INVALID_PARAM, "threadNum不能为空!", "");
  368. }
  369. // 校验groupId是否存在
  370. if (!checkGroupId(apiCallTaskModel.getGroupId())) {
  371. return AjaxResult.error(AjaxResult.Type.INVALID_PARAM, "groupId参数不合法,请输入正确的groupId!", "");
  372. }
  373. // 校验taskType是否合法
  374. if (null == apiCallTaskModel.getTaskType()) {
  375. return AjaxResult.error(AjaxResult.Type.INVALID_PARAM, "taskType不能为空!", "");
  376. } else {
  377. if (apiCallTaskModel.getTaskType() != 1
  378. && apiCallTaskModel.getTaskType() != 2) {
  379. return AjaxResult.error(AjaxResult.Type.INVALID_PARAM, "taskType参数不合法,AI外呼请输入1,通知提醒请输入2!", "");
  380. }
  381. }
  382. // 校验gatewayId是否合法
  383. if (!checkGatewayId(apiCallTaskModel.getGatewayId())) {
  384. return AjaxResult.error(AjaxResult.Type.INVALID_PARAM, "gatewayId参数不合法,请输入正确的gatewayId!", "");
  385. }
  386. // AI外呼需要校验llmAccountId是否合法
  387. if (apiCallTaskModel.getTaskType() == 2) {
  388. if (!checkLlmAccountId(apiCallTaskModel.getLlmAccountId())) {
  389. return AjaxResult.error(AjaxResult.Type.INVALID_PARAM, "llmAccountId参数不合法,请输入正确的llmAccountId!", "");
  390. }
  391. }
  392. // playTimes 如果为空,默认值给1
  393. if (apiCallTaskModel.getTaskType() == 3) {
  394. if (null == apiCallTaskModel.getPlayTimes()) {
  395. apiCallTaskModel.setPlayTimes(1);
  396. }
  397. }
  398. // 校验voiceCode、voiceSource是否合法
  399. if (!checkVoiceCode(apiCallTaskModel.getVoiceCode(), apiCallTaskModel.getVoiceSource())) {
  400. return AjaxResult.error(AjaxResult.Type.INVALID_PARAM, "voiceCode或voiceSource参数不合法,请输入正确的voiceCode和voiceSource!", "");
  401. }
  402. // 创建任务
  403. BeanUtils.copyProperties(apiCallTaskModel, ccCallTask, "batchId");
  404. if ("acd".equals(ccCallTask.getAiTransferType())) {
  405. ccCallTask.setAiTransferData(ccCallTask.getAiTransferGroupId());
  406. } else if ("extension".equals(ccCallTask.getAiTransferType())) {
  407. ccCallTask.setAiTransferData(ccCallTask.getAiTransferExtNumber());
  408. } else if ("gateway".equals(ccCallTask.getAiTransferType())) {
  409. JSONObject aiTransferData = new JSONObject();
  410. aiTransferData.put("gatewayId", ccCallTask.getAiTransferGatewayId());
  411. aiTransferData.put("destNumber", ccCallTask.getAiTransferGatewayDestNumber());
  412. ccCallTask.setAiTransferData(JSONObject.toJSONString(aiTransferData));
  413. }
  414. if (null != ccCallTask.getConntectRate() && ccCallTask.getConntectRate() > 0) {
  415. ccCallTask.setRate(ccCallTask.getConntectRate()/100.0);
  416. }
  417. ccCallTask.setCreatetime(System.currentTimeMillis());
  418. if (StringUtils.isBlank(ccCallTask.getAsrLanguageCode())) {
  419. ccCallTask.setAsrLanguageCode("zh-CN");
  420. }
  421. if (StringUtils.isBlank(ccCallTask.getTtsLanguageCode())) {
  422. ccCallTask.setTtsLanguageCode("zh-CN");
  423. }
  424. if (StringUtils.isBlank(ccCallTask.getAsrModels())) {
  425. ccCallTask.setAsrProvider("ali");
  426. ccCallTask.setAsrModels("fun-asr-flash-8k-realtime");
  427. }
  428. if (StringUtils.isBlank(ccCallTask.getTtsModels())) {
  429. ccCallTask.setTtsModels("");
  430. }
  431. ccCallTaskService.insertCcCallTask(ccCallTask);
  432. apiCallTaskModel.setBatchId(ccCallTask.getBatchId());
  433. return AjaxResult.success("success", apiCallTaskModel);
  434. }
  435. /**
  436. * 启动任务接口
  437. * @param req
  438. * @param batchId
  439. * @return
  440. */
  441. @GetMapping("/ai/startTask")
  442. @ResponseBody
  443. public AjaxResult startTask(HttpServletRequest req, @RequestParam("batchId") Long batchId) {
  444. // 校验ip白名单
  445. if (!ClientIpCheck.checkIp(req)) {
  446. return AjaxResult.error(AjaxResult.Type.NO_AUTH, "未授权,请联系系统管理员添加ip白名单", "");
  447. }
  448. // 启动任务
  449. CcCallTask ccCallTask = ccCallTaskService.selectCcCallTaskByBatchId(batchId);
  450. if (null == ccCallTask) {
  451. return AjaxResult.error(AjaxResult.Type.INVALID_PARAM, "参数batchId不合法,请输入正确的batchId", "");
  452. }
  453. ccCallTask.setIfcall(1);
  454. ccCallTask.setExecuting(0L);
  455. ccCallTask.setStopTime(0L);
  456. ccCallTaskService.updateCcCallTask(ccCallTask);
  457. return AjaxResult.success();
  458. }
  459. /**
  460. * 停止任务接口
  461. * @param req
  462. * @param batchId
  463. * @return
  464. */
  465. @GetMapping( "/ai/stopTask")
  466. @ResponseBody
  467. public AjaxResult stopTask(HttpServletRequest req, @RequestParam("batchId") Long batchId)
  468. {
  469. // 校验ip白名单
  470. if (!ClientIpCheck.checkIp(req)) {
  471. return AjaxResult.error(AjaxResult.Type.NO_AUTH, "未授权,请联系系统管理员添加ip白名单", "");
  472. }
  473. // 停止任务
  474. CcCallTask ccCallTask = ccCallTaskService.selectCcCallTaskByBatchId(batchId);
  475. if (null == ccCallTask) {
  476. return AjaxResult.error(AjaxResult.Type.INVALID_PARAM, "参数batchId不合法,请输入正确的batchId", "");
  477. }
  478. ccCallTask.setIfcall(0);
  479. ccCallTask.setExecuting(0L);
  480. ccCallTask.setStopTime(System.currentTimeMillis());
  481. ccCallTaskService.updateCcCallTask(ccCallTask);
  482. return AjaxResult.success();
  483. }
  484. /**
  485. * 追加名单(不自动启动任务)
  486. * @param req
  487. * @param aiCallListModel
  488. * @return
  489. */
  490. @PostMapping("/ai/addCallList")
  491. @ResponseBody
  492. public AjaxResult addAiCallList(HttpServletRequest req, @RequestBody AiCallListModel aiCallListModel) {
  493. if (!ClientIpCheck.checkIp(req)) {
  494. return AjaxResult.error(AjaxResult.Type.NO_AUTH, "未授权,请联系系统管理员添加ip白名单", "");
  495. }
  496. Long batchId = aiCallListModel.getBatchId();
  497. if (null == batchId) {
  498. return AjaxResult.error(AjaxResult.Type.INVALID_PARAM, "参数batchId不能为空", "");
  499. }
  500. if (CollectionUtils.isEmpty(aiCallListModel.getPhoneList())) {
  501. return AjaxResult.error(AjaxResult.Type.INVALID_PARAM, "参数phoneList不能为空", "");
  502. }
  503. // 获取任务
  504. CcCallTask ccCallTask = callTaskService.selectCcCallTaskByBatchId(batchId);
  505. if (null == ccCallTask) {
  506. return AjaxResult.error(AjaxResult.Type.INVALID_PARAM, "参数batchId不合法,请输入正确的batchId", "");
  507. }
  508. if (ccCallTask.getTaskType() != 1) {
  509. return AjaxResult.error(AjaxResult.Type.INVALID_PARAM, "参数batchId不合法,请输入AI外呼任务(taskType为1)的batchId", "");
  510. }
  511. // 追加名单
  512. Integer successCount = 0;
  513. List<CcCallPhone> callPhoneList = new ArrayList<>();
  514. for (String phoneNum: aiCallListModel.getPhoneList()) {
  515. if (StringUtils.isBlank(phoneNum)) {
  516. continue;
  517. }
  518. JSONObject bizJson = new JSONObject();
  519. CcCallPhone callPhone = buildCcCallPhone(ccCallTask, phoneNum, bizJson);
  520. callPhoneList.add(callPhone);
  521. successCount ++;
  522. if (callPhoneList.size() >= 200) {
  523. ccCallPhoneService.batchInsertCcCallPhone(callPhoneList);
  524. callPhoneList = new ArrayList<>();
  525. }
  526. }
  527. if (callPhoneList.size() > 0) {
  528. ccCallPhoneService.batchInsertCcCallPhone(callPhoneList);
  529. }
  530. log.info("成功追加" + successCount + "个名单");
  531. return AjaxResult.success("成功追加" + successCount + "个名单");
  532. }
  533. /**
  534. * 追加外呼名单(不自动启动任务)
  535. * @param req
  536. * @param commonCallListModel
  537. * @return
  538. */
  539. @PostMapping("/common/addCallList")
  540. @ResponseBody
  541. public AjaxResult addCommonCallList(HttpServletRequest req, @RequestBody CommonCallListModel commonCallListModel) {
  542. if (!ClientIpCheck.checkIp(req)) {
  543. return AjaxResult.error(AjaxResult.Type.NO_AUTH, "未授权,请联系系统管理员添加ip白名单", "");
  544. }
  545. Long batchId = commonCallListModel.getBatchId();
  546. if (null == batchId) {
  547. return AjaxResult.error(AjaxResult.Type.INVALID_PARAM, "参数batchId不能为空", "");
  548. }
  549. if (CollectionUtils.isEmpty(commonCallListModel.getPhoneList())) {
  550. return AjaxResult.error(AjaxResult.Type.INVALID_PARAM, "参数phoneList不能为空", "");
  551. }
  552. // 获取任务
  553. CcCallTask ccCallTask = callTaskService.selectCcCallTaskByBatchId(batchId);
  554. if (null == ccCallTask) {
  555. return AjaxResult.error(AjaxResult.Type.INVALID_PARAM, "参数batchId不合法,请输入正确的batchId", "");
  556. }
  557. // 通知类的通知内容必填
  558. if (ccCallTask.getTaskType() == 2) {
  559. for (CommonPhoneModel commonPhoneModel : commonCallListModel.getPhoneList()) {
  560. if (StringUtils.isBlank(commonPhoneModel.getNoticeContent())) {
  561. return AjaxResult.error(AjaxResult.Type.INVALID_PARAM, "号码" + commonPhoneModel.getPhoneNum() + "的noticeContent不能为空!", "");
  562. }
  563. }
  564. }
  565. // 追加名单
  566. Integer successCount = 0;
  567. List<CcCallPhone> callPhoneList = new ArrayList<>();
  568. for (CommonPhoneModel commonPhoneModel : commonCallListModel.getPhoneList()) {
  569. String phoneNum = commonPhoneModel.getPhoneNum();
  570. if (StringUtils.isBlank(phoneNum)) {
  571. continue;
  572. }
  573. CcCallPhone callPhone = buildCcCallPhone(ccCallTask, phoneNum, commonPhoneModel.getBizJson());
  574. callPhone.setTtsText(commonPhoneModel.getNoticeContent());
  575. callPhoneList.add(callPhone);
  576. successCount ++;
  577. if (callPhoneList.size() >= 200) {
  578. ccCallPhoneService.batchInsertCcCallPhone(callPhoneList);
  579. callPhoneList = new ArrayList<>();
  580. }
  581. }
  582. if (callPhoneList.size() > 0) {
  583. ccCallPhoneService.batchInsertCcCallPhone(callPhoneList);
  584. }
  585. log.info("成功追加" + successCount + "个名单");
  586. return AjaxResult.success("成功追加" + successCount + "个名单",callPhoneList);
  587. }
  588. /**
  589. * yangqiang定制的追加通知的名单
  590. * @param req
  591. * @param noticeCallModel
  592. * @return
  593. */
  594. @PostMapping("/notice/call")
  595. @ResponseBody
  596. public AjaxResult callNotice(HttpServletRequest req, @RequestBody NoticeCallModel noticeCallModel) {
  597. if (!ClientIpCheck.checkIp(req)) {
  598. return AjaxResult.error(AjaxResult.Type.NO_AUTH, "未授权,请联系系统管理员添加ip白名单", "");
  599. }
  600. // 获取任务
  601. String batchName = paramsService.getParamValueByCode("testNoticeCallTaskName", "test");
  602. String phoneNum = paramsService.getParamValueByCode("testNoticeCallPhoneNum", "13908113506");
  603. CcCallTask ccCallTask = callTaskService.selectCcCallTaskByBatchName(batchName, 2);
  604. // 追加名单
  605. JSONObject bizJson = new JSONObject();
  606. CcCallPhone callPhone = buildCcCallPhone(ccCallTask, phoneNum, bizJson);
  607. callPhone.setTtsText(noticeCallModel.getNoticeContent());
  608. ccCallPhoneService.insertCcCallPhone(callPhone);
  609. // 启动任务
  610. ccCallTask.setIfcall(1);
  611. ccCallTask.setExecuting(0L);
  612. ccCallTask.setStopTime(0L);
  613. callTaskService.updateCcCallTask(ccCallTask);
  614. return AjaxResult.success();
  615. }
  616. private CcCallPhone buildCcCallPhone(CcCallTask ccCallTask, String phoneNum, JSONObject bizJson) {
  617. CcCallPhone callPhone = new CcCallPhone();
  618. callPhone.setId(UuidGenerator.GetOneUuid());
  619. callPhone.setGroupId("1");
  620. callPhone.setBatchId(ccCallTask.getBatchId());
  621. callPhone.setCreatetime(new Date().getTime());
  622. callPhone.setCallstatus(0);
  623. callPhone.setCalloutTime(0L);
  624. callPhone.setCallcount(0);
  625. callPhone.setCallEndTime(0L);
  626. callPhone.setTimeLen(0L);
  627. callPhone.setValidTimeLen(0L);
  628. callPhone.setUuid("");
  629. callPhone.setConnectedTime(0L);
  630. callPhone.setHangupCause("");
  631. callPhone.setAnsweredTime(0L);
  632. callPhone.setDialogue("");
  633. callPhone.setWavfile("");
  634. callPhone.setRecordServerUrl("");
  635. callPhone.setDialogueCount(0L);
  636. callPhone.setAcdOpnum("");
  637. callPhone.setAcdQueueTime(0L);
  638. callPhone.setAcdWaitTime(0);
  639. callPhone.setTelephone(phoneNum);
  640. if (phoneNum.length() > 4) {
  641. bizJson.put("tailNum", phoneNum.substring(phoneNum.length()-4));
  642. } else {
  643. bizJson.put("tailNum", phoneNum);
  644. }
  645. bizJson.put("phoneNum", phoneNum);
  646. callPhone.setCustName(bizJson.getString("custName"));
  647. if (null == callPhone.getCustName()) {
  648. callPhone.setCustName("");
  649. }
  650. callPhone.setBizJson(JSONObject.toJSONString(bizJson));
  651. if (ccCallTask.getTaskType() == 1) {
  652. callPhone.setIntent("");
  653. } else {
  654. callPhone.setIntent("-");
  655. }
  656. return callPhone;
  657. }
  658. private void insertCallPhoneBatch(List<CcCallPhone> batchList, List<CcCallPhone> successList) {
  659. if (batchList.isEmpty()) {
  660. return;
  661. }
  662. try {
  663. ccCallPhoneService.batchInsertCcCallPhone(batchList);
  664. successList.addAll(batchList);
  665. } catch (Exception e) {
  666. log.error("批次插入名单失败,本批{}条,继续处理下一批", batchList.size(), e);
  667. } finally {
  668. batchList.clear();
  669. }
  670. }
  671. private TableDataInfo getOutboundRecords(ApiCallRecordQueryParams queryParams) {
  672. Map<String, Object> params = new HashMap<>();
  673. params.put("inboundTimeStart", queryParams.getCalloutTimeStart());
  674. params.put("inboundTimeEnd", queryParams.getCalloutTimeEnd());
  675. if (null != queryParams.getTimeLenStart()) {
  676. params.put("timeLenSecondStart", queryParams.getTimeLenStart().toString());
  677. }
  678. if (null != queryParams.getTimeLenEnd()) {
  679. params.put("timeLenSecondEnd", queryParams.getTimeLenEnd().toString());
  680. }
  681. startPage(queryParams.getPageNum(), queryParams.getPageSize());
  682. CcOutboundCdr outboundCdr = new CcOutboundCdr();
  683. outboundCdr.setUuid(queryParams.getUuid());
  684. outboundCdr.setCaller(queryParams.getTelephone());
  685. outboundCdr.setOpnum(queryParams.getExtnum());
  686. outboundCdr.setParams(params);
  687. List<CcOutboundCdr> list = outboundCdrService.selectCcOutboundCdrList(outboundCdr);
  688. TableDataInfo tableData = getDataTable(list);
  689. List<CcOutboundCdr> records = (List<CcOutboundCdr>) tableData.getRows();
  690. List<ApiCallRecordQueryResult> apiRecords = new ArrayList<>();
  691. for (CcOutboundCdr data: records) {
  692. ApiCallRecordQueryResult apiData = new ApiCallRecordQueryResult();
  693. if (data.getRecordFilename().startsWith("/")) {
  694. data.setRecordFilename(data.getRecordFilename().substring(1));
  695. }
  696. data.setWavFileUrl("/recordings/files?filename=" + data.getRecordFilename());
  697. apiData.setUuid(data.getUuid());
  698. apiData.setTelephone(CommonUtils.maskPhoneNumber(data.getCallee()));
  699. apiData.setCalloutTime(DateUtils.format(new Date(data.getStartTime()), "yyyy-MM-dd HH:mm:ss"));
  700. if (data.getAnsweredTime() > 0) {
  701. apiData.setAnsweredTime(DateUtils.format(new Date(data.getAnsweredTime()), "yyyy-MM-dd HH:mm:ss"));
  702. } else {
  703. apiData.setAnsweredTime("");
  704. }
  705. if (data.getEndTime() > 0) {
  706. apiData.setCallEndTime(DateUtils.format(new Date(data.getEndTime()), "yyyy-MM-dd HH:mm:ss"));
  707. } else {
  708. apiData.setCallEndTime("");
  709. }
  710. apiData.setHangupCause(data.getHangupCause());
  711. if (data.getTimeLen() > 0) {
  712. apiData.setWavFileUrl(data.getWavFileUrl());
  713. } else {
  714. apiData.setWavFileUrl("");
  715. }
  716. apiData.setDialogue(new JSONArray());
  717. apiData.setTimeLen(Long.valueOf(data.getTimeLen()/1000).intValue());
  718. apiRecords.add(apiData);
  719. }
  720. tableData.setRows(records);
  721. TableDataInfo tableDataInfo = new TableDataInfo();
  722. tableDataInfo.setCode(tableData.getCode());
  723. tableDataInfo.setRows(apiRecords);
  724. tableDataInfo.setTotal(tableData.getTotal());
  725. tableDataInfo.setMsg(tableData.getMsg());
  726. return tableDataInfo;
  727. }
  728. private TableDataInfo getInboundRecords(ApiCallRecordQueryParams queryParams) {
  729. Map<String, Object> params = new HashMap<>();
  730. params.put("inboundTimeStart", queryParams.getCalloutTimeStart());
  731. params.put("inboundTimeEnd", queryParams.getCalloutTimeEnd());
  732. if (null != queryParams.getTimeLenStart()) {
  733. params.put("timeLenSecondStart", queryParams.getTimeLenStart().toString());
  734. }
  735. if (null != queryParams.getTimeLenEnd()) {
  736. params.put("timeLenSecondEnd", queryParams.getTimeLenEnd().toString());
  737. }
  738. startPage(queryParams.getPageNum(), queryParams.getPageSize());
  739. CcInboundCdr inboundCdr = new CcInboundCdr();
  740. inboundCdr.setUuid(queryParams.getUuid());
  741. inboundCdr.setCaller(queryParams.getTelephone());
  742. inboundCdr.setOpnum(queryParams.getExtnum());
  743. inboundCdr.setParams(params);
  744. List<CcInboundCdr> list = inboundCdrService.selectCcInboundCdrList(inboundCdr);
  745. TableDataInfo tableData = getDataTable(list);
  746. List<CcInboundCdr> records = (List<CcInboundCdr>) tableData.getRows();
  747. List<ApiCallRecordQueryResult> apiRecords = new ArrayList<>();
  748. for (CcInboundCdr data: records) {
  749. ApiCallRecordQueryResult apiData = new ApiCallRecordQueryResult();
  750. if (data.getWavFile().startsWith("/")) {
  751. data.setWavFile(data.getWavFile().substring(1));
  752. }
  753. data.setWavFileUrl("/recordings/files?filename=" + data.getWavFile());
  754. apiData.setUuid(data.getUuid());
  755. apiData.setTelephone(CommonUtils.maskPhoneNumber(data.getCaller()));
  756. apiData.setCalloutTime(DateUtils.format(new Date(data.getInboundTime()), "yyyy-MM-dd HH:mm:ss"));
  757. if (data.getAnsweredTime() > 0) {
  758. apiData.setAnsweredTime(DateUtils.format(new Date(data.getAnsweredTime()), "yyyy-MM-dd HH:mm:ss"));
  759. } else {
  760. apiData.setAnsweredTime("");
  761. }
  762. if (data.getHangupTime() > 0) {
  763. apiData.setCallEndTime(DateUtils.format(new Date(data.getHangupTime()), "yyyy-MM-dd HH:mm:ss"));
  764. } else {
  765. apiData.setCallEndTime("");
  766. }
  767. apiData.setHangupCause("");
  768. if (data.getTimeLen() > 0) {
  769. apiData.setWavFileUrl(data.getWavFileUrl());
  770. } else {
  771. apiData.setWavFileUrl("");
  772. }
  773. if (StringUtils.isNotEmpty(data.getChatContent())) {
  774. JSONArray dialogue = new JSONArray();
  775. JSONArray.parseArray(data.getChatContent()).forEach(obj -> {
  776. JSONObject json = (JSONObject) obj;
  777. if ("assistant".equals(json.getString("role"))
  778. || "user".equals(json.getString("role"))) {
  779. JSONObject content = new JSONObject();
  780. content.put("role", json.getString("role"));
  781. content.put("content", json.getString("content"));
  782. dialogue.add(content);
  783. }
  784. });
  785. apiData.setDialogue(dialogue);
  786. } else {
  787. apiData.setDialogue(new JSONArray());
  788. }
  789. apiData.setTimeLen(Long.valueOf(data.getTimeLen()/1000).intValue());
  790. apiData.setManualAnsweredTime(data.getManualAnsweredTime());
  791. apiData.setManualAnsweredTimeLen(data.getManualAnsweredTimeLen());
  792. apiRecords.add(apiData);
  793. }
  794. tableData.setRows(records);
  795. TableDataInfo tableDataInfo = new TableDataInfo();
  796. tableDataInfo.setCode(tableData.getCode());
  797. tableDataInfo.setRows(apiRecords);
  798. tableDataInfo.setTotal(tableData.getTotal());
  799. tableDataInfo.setMsg(tableData.getMsg());
  800. return tableDataInfo;
  801. }
  802. private TableDataInfo getAiCallRecords(ApiCallRecordQueryParams queryParams) {
  803. Map<String, Object> params = new HashMap<>();
  804. params.put("calloutTimeStart", queryParams.getCalloutTimeStart());
  805. params.put("calloutTimeEnd", queryParams.getCalloutTimeEnd());
  806. if (null != queryParams.getTimeLenStart()) {
  807. params.put("timeLenSecondStart", queryParams.getTimeLenStart().toString());
  808. }
  809. if (null != queryParams.getTimeLenEnd()) {
  810. params.put("timeLenSecondEnd", queryParams.getTimeLenEnd().toString());
  811. }
  812. startPage(queryParams.getPageNum(), queryParams.getPageSize());
  813. CcCallPhone ccCallPhone = new CcCallPhone();
  814. if (null != queryParams.getBatchId() && queryParams.getBatchId() > 0) {
  815. ccCallPhone.setBatchId(queryParams.getBatchId());
  816. }
  817. ccCallPhone.setUuid(queryParams.getUuid());
  818. ccCallPhone.setTelephone(queryParams.getTelephone());
  819. ccCallPhone.setAcdOpnum(queryParams.getExtnum());
  820. ccCallPhone.setCallstatus(queryParams.getCallstatus());
  821. ccCallPhone.setCallerNumber(queryParams.getCallerNumber());
  822. ccCallPhone.setParams(params);
  823. List<CcCallPhone> list = ccCallPhoneService.selectCcCallPhoneList(ccCallPhone);
  824. TableDataInfo tableData = getDataTable(list);
  825. List<CcCallPhone> records = (List<CcCallPhone>) tableData.getRows();
  826. List<ApiCallRecordQueryResult> apiRecords = new ArrayList<>();
  827. for (CcCallPhone data: records) {
  828. ApiCallRecordQueryResult apiData = new ApiCallRecordQueryResult();
  829. if (data.getWavfile().startsWith("/")) {
  830. data.setWavfile(data.getWavfile().substring(1));
  831. }
  832. data.setWavfile("/recordings/files?filename=" + data.getWavfile());
  833. apiData.setUuid(data.getUuid());
  834. apiData.setTelephone(CommonUtils.maskPhoneNumber(data.getTelephone()));
  835. apiData.setCalloutTime(DateUtils.format(new Date(data.getCalloutTime()), "yyyy-MM-dd HH:mm:ss"));
  836. if (data.getAnsweredTime() > 0) {
  837. apiData.setAnsweredTime(DateUtils.format(new Date(data.getAnsweredTime()), "yyyy-MM-dd HH:mm:ss"));
  838. } else {
  839. apiData.setAnsweredTime("");
  840. }
  841. if (data.getCallEndTime() > 0) {
  842. apiData.setCallEndTime(DateUtils.format(new Date(data.getCallEndTime()), "yyyy-MM-dd HH:mm:ss"));
  843. } else {
  844. apiData.setCallEndTime("");
  845. }
  846. apiData.setHangupCause(data.getHangupCause());
  847. if (data.getTimeLen() > 0) {
  848. apiData.setWavFileUrl(data.getWavfile());
  849. } else {
  850. apiData.setWavFileUrl("");
  851. }
  852. if (StringUtils.isNotEmpty(data.getDialogue())) {
  853. JSONArray dialogue = new JSONArray();
  854. JSONArray.parseArray(data.getDialogue()).forEach(obj -> {
  855. JSONObject json = (JSONObject) obj;
  856. if ("assistant".equals(json.getString("role"))
  857. || "user".equals(json.getString("role"))) {
  858. JSONObject content = new JSONObject();
  859. content.put("role", json.getString("role"));
  860. content.put("content", json.getString("content"));
  861. dialogue.add(content);
  862. }
  863. });
  864. apiData.setDialogue(dialogue);
  865. } else {
  866. apiData.setDialogue(new JSONArray());
  867. }
  868. apiData.setTimeLen(Long.valueOf(data.getTimeLen()/1000).intValue());
  869. apiData.setSessionId(data.getId());
  870. apiData.setCallstatus(data.getCallstatus());
  871. apiData.setCallerNumber(CommonUtils.maskPhoneNumber(data.getCallerNumber()));
  872. apiData.setManualAnsweredTime(data.getManualAnsweredTime());
  873. apiData.setManualAnsweredTimeLen(data.getManualAnsweredTimeLen());
  874. apiRecords.add(apiData);
  875. }
  876. tableData.setRows(records);
  877. TableDataInfo tableDataInfo = new TableDataInfo();
  878. tableDataInfo.setCode(tableData.getCode());
  879. tableDataInfo.setRows(apiRecords);
  880. tableDataInfo.setTotal(tableData.getTotal());
  881. tableDataInfo.setMsg(tableData.getMsg());
  882. return tableDataInfo;
  883. }
  884. private boolean checkGroupId(String groupId) {
  885. // 可以为空
  886. if (StringUtils.isBlank(groupId)) {
  887. return true;
  888. }
  889. // 如果传值了,必须是存在的值
  890. CcBizGroup ccBizGroup = ccBizGroupService.selectCcBizGroupByGroupId(groupId);
  891. if (null == ccBizGroup) {
  892. return false;
  893. }
  894. return true;
  895. }
  896. private boolean checkGatewayId(Long gatewayId) {
  897. // 不可以为空
  898. if (null == gatewayId) {
  899. return false;
  900. }
  901. // 必须是存在的网关,且用途是外呼或者不限制
  902. CcGateways ccGateways = ccGatewaysService.selectCcGatewaysById(gatewayId);
  903. if (null == ccGateways) {
  904. return false;
  905. }
  906. // 网关用途 0 dropped; 1 phonebar; 2 outbound tasks; 3. Unlimited
  907. if (ccGateways.getPurpose() != 2
  908. && ccGateways.getPurpose() != 3) {
  909. return false;
  910. }
  911. return true;
  912. }
  913. private boolean checkLlmAccountId(Integer llmAccountId) {
  914. // 不能为空
  915. if (null == llmAccountId) {
  916. return false;
  917. }
  918. // 必须存在
  919. CcLlmAgentAccount ccLlmAgentAccount = ccLlmAgentAccountService.selectCcLlmAgentAccountById(llmAccountId);
  920. if (null == ccLlmAgentAccount) {
  921. return false;
  922. }
  923. return true;
  924. }
  925. private boolean checkVoiceCode(String voiceCode, String voiceSource) {
  926. // 不能为空
  927. if (StringUtils.isBlank(voiceCode) || StringUtils.isBlank(voiceSource)) {
  928. return false;
  929. }
  930. // voiceSource仅支持aliyun_tts、aliyun_tts_flow、doubao_vcl_tts、xf_tts 和 tx_tts1
  931. if (!"aliyun_tts".equals(voiceSource)
  932. && !"aliyun_tts_flow".equals(voiceSource)
  933. && !"doubao_vcl_tts".equals(voiceSource)
  934. && !"xf_tts".equals(voiceSource)
  935. && !"tx_tts1".equals(voiceSource)
  936. && !"vt_tts".equals(voiceSource)) {
  937. return false;
  938. }
  939. // voiceCode必须是存在的
  940. CcTtsAliyun ccTtsAliyun = ccTtsAliyunService.selectCcTtsAliyunByVoiceCode(voiceCode);
  941. if (null == ccTtsAliyun) {
  942. return false;
  943. }
  944. return true;
  945. }
  946. /**
  947. * 行稳数智追加名单【不自动启动任务,需要在任务管理页面手动启动任务】
  948. * @param req
  949. * @param localCallModel
  950. * @return
  951. */
  952. @PostMapping("/local/addCall")
  953. @ResponseBody
  954. public AjaxResult addLocalCall(HttpServletRequest req, @RequestBody LocalCallModel localCallModel) {
  955. // if (!ClientIpCheck.checkIp(req)) {
  956. // return AjaxResult.error(AjaxResult.Type.NO_AUTH, "未授权,请联系系统管理员添加ip白名单", "");
  957. // }
  958. // 获取任务
  959. String batchName = localCallModel.getBatchName();
  960. if (StringUtils.isEmpty(batchName)) {
  961. batchName = paramsService.getParamValueByCode("testNoticeCallTaskName", "test");
  962. }
  963. CcCallTask ccCallTask = callTaskService.selectCcCallTaskByBatchName(batchName, 1);
  964. log.info("接收到名单localCallModel:{}", JSONObject.toJSONString(localCallModel));
  965. log.info("batchName:{}", batchName);
  966. log.info("ccCallTask:{}", JSONObject.toJSONString(ccCallTask));
  967. // 追加名单
  968. String phoneNum = localCallModel.getPhone();
  969. JSONObject bizJson = new JSONObject();
  970. bizJson.put("caller", localCallModel.getCaller());
  971. bizJson.put("welcomeMessage", localCallModel.getWelcomeMessage());
  972. bizJson.put("questionChainId", localCallModel.getQuestionChainId());
  973. CcCallPhone callPhone = buildCcCallPhone(ccCallTask, phoneNum, bizJson);
  974. ccCallPhoneService.insertCcCallPhone(callPhone);
  975. // 暂时关闭自动启动逻辑(后续改成自动启停逻辑)
  976. // // 如果停止超过5分钟,则自动启动
  977. // if (ccCallTask.getIfcall() == 0
  978. // && (System.currentTimeMillis() - ccCallTask.getStopTime()) >= 5*60*1000L) {
  979. // ccCallTask.setIfcall(1);
  980. // ccCallTask.setExecuting(0L);
  981. // ccCallTask.setStopTime(0L);
  982. // callTaskService.updateCcCallTask(ccCallTask);
  983. // }
  984. JSONObject res = new JSONObject();
  985. res.put("sessionId", callPhone.getId().toString());
  986. log.info("名单处理完成:{}", JSONObject.toJSONString(callPhone));
  987. return AjaxResult.success(res);
  988. }
  989. /**
  990. * 自动绑定并获取分机信息
  991. * @param req
  992. * @param loginUser
  993. * @return
  994. */
  995. @GetMapping("/phoneBar/extnum/bind")
  996. @ResponseBody
  997. public AjaxResult getExtNumByUserName(HttpServletRequest req, @RequestParam String loginUser) {
  998. // 获取分机号
  999. CcExtNum ccExtNum = ccExtNumService.selectCcExtNumByUserCode(loginUser);
  1000. if (null != ccExtNum) {
  1001. return AjaxResult.success("success", ccExtNum);
  1002. }
  1003. // 如果没有获取到分机,则自动绑定分机
  1004. List<CcExtNum> ccExtNumList = ccExtNumService.selectUnBindCcExtNumList();
  1005. if (CollectionUtils.isEmpty(ccExtNumList)) {
  1006. log.error("没有可用分机,无法分配分机-:{}", loginUser);
  1007. return AjaxResult.error("没有可用分机,无法分配分机");
  1008. }
  1009. ccExtNum = ccExtNumList.get(RandomUtils.nextInt(0, ccExtNumList.size()));
  1010. ccExtNum.setUserCode(loginUser);
  1011. ccExtNumService.updateCcExtNum(ccExtNum);
  1012. return AjaxResult.success("success", ccExtNum);
  1013. }
  1014. /**
  1015. * 获取电话工具条的网关列表
  1016. * @param req
  1017. * @param extNum
  1018. * @return
  1019. */
  1020. @GetMapping("/phoneBar/params")
  1021. @ResponseBody
  1022. public AjaxResult getPhoneBaseParams(HttpServletRequest req, @RequestParam String extNum) {
  1023. // 获取分机号
  1024. CcExtNum ccExtNum = ccExtNumService.selectCcExtNumByExtNum(Long.valueOf(extNum));
  1025. String extnum = ccExtNum.getExtNum().toString();
  1026. String opnum = ccExtNum.getUserCode();
  1027. String groupId = "1";
  1028. String skillLevel = "9";
  1029. String projectId = "1";
  1030. String loginToken = ccExtNumService.createToken(extnum, opnum, groupId, skillLevel, projectId);
  1031. // 网关用途 0 dropped; 1 phonebar; 2 outbound tasks; 3. Unlimited
  1032. Map<String, Object> params = new HashMap<>();
  1033. params.put("purposes", Arrays.asList(1,3));
  1034. List<CcGateways> gatewaysList = ccGatewaysService.selectCcGatewaysList(new CcGateways().setParams(params));
  1035. List<JSONObject> gatewayList = new ArrayList<>();
  1036. for (CcGateways ccGateways: gatewaysList) {
  1037. JSONObject configGateway = new JSONObject();
  1038. configGateway.put("uuid", ccGateways.getId().toString());
  1039. configGateway.put("updateTime", ccGateways.getUpdateTime());
  1040. configGateway.put("gatewayAddr", ccGateways.getGwAddr());
  1041. configGateway.put("callerNumber", ccGateways.getCaller());
  1042. configGateway.put("calleePrefix", ccGateways.getCalleePrefix());
  1043. configGateway.put("callProfile", ccGateways.getProfileName());
  1044. configGateway.put("priority", ccGateways.getPriority());
  1045. configGateway.put("concurrency", ccGateways.getMaxConcurrency());
  1046. configGateway.put("register", ccGateways.getRegister());
  1047. configGateway.put("authUsername", ccGateways.getAuthUsername());
  1048. configGateway.put("audioCodec", ccGateways.getCodec());
  1049. gatewayList.add(configGateway);
  1050. }
  1051. JSONObject callConfig = new JSONObject();
  1052. String scriptServer = ccParamsService.getParamValueByCode("call-center-server-ip-addr", "");
  1053. String scriptPort = ccParamsService.getParamValueByCode("call-center-websocket-port", "");
  1054. callConfig.put("scriptServer", scriptServer);
  1055. callConfig.put("scriptPort", scriptPort);
  1056. callConfig.put("loginToken", loginToken);
  1057. callConfig.put("gatewayList", gatewayList);
  1058. return AjaxResult.success(callConfig);
  1059. }
  1060. @PostMapping("/test/localChat")
  1061. @ResponseBody
  1062. public JSONObject localChat(HttpServletRequest request, @RequestBody JSONObject reqParams) {
  1063. // {"code":200, "data":{"choices":[{"content":"xxxxxxx", "wavFilePath":"/home/Records/251224101457010001/20260113161253001914.wav"}]}}
  1064. log.info("请求参数:{}", reqParams);
  1065. Integer rounds = 0;
  1066. for (int i = 0; i < reqParams.getJSONArray("messages").size(); i++) {
  1067. if ("assistant".equals(reqParams.getJSONArray("messages").getJSONObject(i).getString("role"))) {
  1068. rounds ++;
  1069. }
  1070. }
  1071. String[] rspDatas = new String[]{
  1072. // "您好,请问您是测试1本人是吗?| /home/Records/23/round-1.wav; ",
  1073. "这里是中信银行委托方,这个电话号码是测试1在中信银行办理业务时登记的号码,您是测试1吗? | /home/Records/23/round-2-1.wav;/home/Records/23/round-2-2.wav;/home/Records/23/round-2-3.wav",
  1074. "这里是中信银行委托方,这边主要是通知您一下,您在中信银行卡尾号6388的信用卡已错过到期环款日,当期账单账面欠款总额9097元全国统一核账时间在今天下午5点需要您在此之前处理进来,可以吧?| /home/Records/23/round-3-1.wav;/home/Records/23/round-3-2.wav;",
  1075. "您的账单现在已经过环款日了,能和我们说一下您是为什么还没处理欠款吗? | /home/Records/23/round-4.wav",
  1076. "好的,请您在今天下午5点之前至少处理您的最低还款额0元时间和资金都没问题,对吗?|/home/Records/23/round-5.wav",
  1077. "银行稍后安排工作人员查账,建议您尽快处理欠款,不打扰您了,再见。hangupCall|/home/Records/23/round-6.wav"
  1078. };
  1079. JSONObject result = new JSONObject();
  1080. result.put("code", 200);
  1081. JSONObject data = new JSONObject();
  1082. JSONArray choices = new JSONArray();
  1083. JSONObject delta = new JSONObject();
  1084. String[] rspData = rspDatas[rounds].split("\\|");
  1085. delta.put("content", rspData[0].trim());
  1086. delta.put("wavFilePath", rspData[1].trim());
  1087. JSONObject choices0 = new JSONObject();
  1088. choices0.put("delta", delta);
  1089. choices.add(choices0);
  1090. data.put("choices", choices);
  1091. result.put("data", data);
  1092. return result;
  1093. }
  1094. //=======================================================新增接口============================================================
  1095. /**
  1096. * 删除外呼任务
  1097. */
  1098. @PostMapping( "/removeTask")
  1099. @ResponseBody
  1100. @Transactional
  1101. public AjaxResult removeTask(@RequestBody Map<String, Long[]> paramMap)
  1102. {
  1103. Long[] batchIds= paramMap.get("batchIds");
  1104. if(batchIds==null){
  1105. return AjaxResult.error(AjaxResult.Type.INVALID_PARAM, "batchIds不能为空!", "");
  1106. }
  1107. for (Long batchId : batchIds) {
  1108. // 备份拨打记录数据
  1109. ccCallPhoneService.bakCallPhoneByBatchId(batchId);
  1110. // 删除拨打记录数据
  1111. ccCallPhoneService.delCallPhoneByBatchId(batchId);
  1112. // 备份任务数据
  1113. ccCallTaskService.bakCallTaskByBatchId(batchId);
  1114. }
  1115. // 删除任务数据
  1116. String batchIdsStr = Arrays.stream(batchIds)
  1117. .map(String::valueOf)
  1118. .collect(Collectors.joining(","));
  1119. return toAjax(ccCallTaskService.deleteCcCallTaskByBatchIds(batchIdsStr));
  1120. }
  1121. /**
  1122. * 获取电话工具条的网关列表
  1123. */
  1124. @PostMapping("/myPhoneBar/params")
  1125. @ResponseBody
  1126. public AjaxResult getMyPhoneBaseParams(@RequestBody Map<String,String> param) {
  1127. String extNum = param.get("extNum");
  1128. String myGateway = param.get("myGateway");
  1129. if(extNum == null){
  1130. return AjaxResult.error("分机号参数缺失");
  1131. }
  1132. // 获取分机号
  1133. CcExtNum ccExtNum = ccExtNumService.selectCcExtNumByExtNum(Long.valueOf(extNum));
  1134. String extnum = ccExtNum.getExtNum().toString();
  1135. String opnum = ccExtNum.getUserCode();
  1136. String password = ccExtNum.getExtPass();
  1137. String groupId = "1";
  1138. String skillLevel = "9";
  1139. String projectId = "1";
  1140. //1.创建token
  1141. String loginToken = ccExtNumService.createToken(extnum, opnum, groupId, skillLevel, projectId);
  1142. //2.获取加密密码
  1143. String encryptStr = DESUtil.encrypt(password + "," + DateUtils.format(DateUtils.addDays(new Date(), 1), "yyyyMMddHHmm"));
  1144. encryptStr = String.format("var _phoneEncryptPassword='%s';", encryptStr);
  1145. CcGateways ccGatewaysVo = new CcGateways();
  1146. //判断指定网关还是全部网关
  1147. if(StringUtils.isNotBlank(myGateway)){
  1148. List<Long> gatewayIds = Arrays.stream(myGateway.split(","))
  1149. .map(Long::parseLong)
  1150. .collect(Collectors.toList());
  1151. ccGatewaysVo.setGatewayIds(gatewayIds);
  1152. }else{
  1153. String wgName = param.get("wgName");
  1154. if(StringUtils.isNotBlank(wgName)){
  1155. ccGatewaysVo.setGwName(wgName);
  1156. }else{
  1157. // 网关用途 0 已废弃; 1 电话条; 2 外呼任务; 3 无限制
  1158. Map<String, Object> params = new HashMap<>();
  1159. params.put("purposes", Arrays.asList(1,3));
  1160. ccGatewaysVo.setParams(params);
  1161. }
  1162. }
  1163. //3.获取工具条网关列表
  1164. List<CcGateways> gatewaysList = ccGatewaysService.selectCcGatewaysList(ccGatewaysVo);
  1165. List<JSONObject> gatewayList = new ArrayList<>();
  1166. for (CcGateways ccGateways: gatewaysList) {
  1167. JSONObject configGateway = new JSONObject();
  1168. configGateway.put("uuid", ccGateways.getId().toString());
  1169. configGateway.put("updateTime", ccGateways.getUpdateTime());
  1170. configGateway.put("gatewayAddr", ccGateways.getGwAddr());
  1171. configGateway.put("callerNumber", ccGateways.getCaller());
  1172. configGateway.put("calleePrefix", ccGateways.getCalleePrefix());
  1173. configGateway.put("callProfile", ccGateways.getProfileName());
  1174. configGateway.put("priority", ccGateways.getPriority());
  1175. configGateway.put("concurrency", ccGateways.getMaxConcurrency());
  1176. configGateway.put("register", ccGateways.getRegister());
  1177. configGateway.put("authUsername", ccGateways.getAuthUsername());
  1178. configGateway.put("audioCodec", ccGateways.getCodec());
  1179. gatewayList.add(configGateway);
  1180. }
  1181. JSONObject callConfig = new JSONObject();
  1182. String scriptServer = ccParamsService.getParamValueByCode("call-center-server-ip-addr", "");
  1183. String scriptPort = ccParamsService.getParamValueByCode("call-center-websocket-port", "");
  1184. callConfig.put("scriptServer", scriptServer);
  1185. callConfig.put("scriptPort", scriptPort);
  1186. callConfig.put("loginToken", loginToken);
  1187. callConfig.put("encryptPsw", encryptStr);
  1188. callConfig.put("gatewayList", gatewayList);
  1189. //登录账号
  1190. callConfig.put("opNum", opnum);
  1191. //登录用户名称
  1192. SysUser sysUser = userService.selectUserByLoginName(opnum);
  1193. if(sysUser != null){
  1194. callConfig.put("userName", sysUser.getUserName());
  1195. }
  1196. return AjaxResult.success(callConfig);
  1197. }
  1198. /**
  1199. * 查询未绑定的分机管理列表
  1200. */
  1201. @GetMapping("/extnum/selectUnBindCcExtNumList")
  1202. @ResponseBody
  1203. public AjaxResult selectUnBindCcExtNumList()
  1204. {
  1205. return AjaxResult.success(ccExtNumService.selectUnBindCcExtNumList());
  1206. }
  1207. /**
  1208. * 查询公司未绑定的分机管理列表
  1209. */
  1210. @PostMapping("/extnum/selectCompanyUnBindCcExtNumList")
  1211. @ResponseBody
  1212. public AjaxResult selectCompanyUnBindCcExtNumList(@RequestBody CcExtNum ccExtNum)
  1213. {
  1214. return AjaxResult.success(ccExtNumService.selectCcExtNumList(ccExtNum));
  1215. }
  1216. /**
  1217. * 查询未绑定的分机管理列表分页
  1218. */
  1219. @PostMapping("/extnum/selectUnBindCcExtNumListPage")
  1220. @ResponseBody
  1221. public TableDataInfo selectUnBindCcExtNumListPage(@RequestBody CcExtNum ccExtNum)
  1222. {
  1223. Integer pageNum = ccExtNum.getPageNum() != null ? ccExtNum.getPageNum().intValue() : 1;
  1224. Integer pageSize = ccExtNum.getPageSize() != null ? ccExtNum.getPageSize().intValue() : 10;
  1225. startPage(pageNum, pageSize);
  1226. List<CcExtNum> list = ccExtNumService.selectUnBindCcExtNumListPage(ccExtNum);
  1227. return getDataTable(list);
  1228. }
  1229. /**
  1230. * 通用查询分机列表分页
  1231. */
  1232. @PostMapping("/extnumPage")
  1233. @ResponseBody
  1234. public TableDataInfo extnumPage(@RequestBody CcExtNum ccExtNum)
  1235. {
  1236. Integer pageNum = ccExtNum.getPageNum() != null ? ccExtNum.getPageNum().intValue() : 1;
  1237. Integer pageSize = ccExtNum.getPageSize() != null ? ccExtNum.getPageSize().intValue() : 10;
  1238. startPage(pageNum, pageSize);
  1239. List<CcExtNum> list = ccExtNumService.selectCcExtNumList(ccExtNum);
  1240. if(!CollectionUtils.isEmpty(list)){
  1241. list.forEach(extNum -> {
  1242. if(StringUtils.isNotBlank(extNum.getUserCode()) && (extNum.getUserCode().startsWith("Runtian_cp_") || extNum.getUserCode().startsWith("_cp_"))){
  1243. extNum.setUserCode("");
  1244. }
  1245. });
  1246. }
  1247. return getDataTable(list);
  1248. }
  1249. /**
  1250. * 新增企业绑定未使用的分机(实际只是公司占位,需销售来绑定)
  1251. */
  1252. @PostMapping("/companyBindExtNum")
  1253. @ResponseBody
  1254. @Transactional
  1255. public AjaxResult companyBindExtNum(@RequestBody Map<String,String> param)
  1256. {
  1257. String companyName = param.get("companyName");
  1258. String sipExtNumIds = param.get("sipExtNumIds");
  1259. if(StringUtils.isBlank(companyName) || StringUtils.isBlank(sipExtNumIds)){
  1260. return AjaxResult.error("参数companyName或sipExtNumIds缺失");
  1261. }
  1262. //公司绑定分机
  1263. List<Long> extNumList = Arrays.stream(sipExtNumIds.split(","))
  1264. .map(String::trim)
  1265. .filter(StringUtils::isNotBlank)
  1266. .map(Long::parseLong)
  1267. .collect(Collectors.toList());
  1268. CcExtNum extNum = new CcExtNum();
  1269. extNum.setUserCode(companyName);
  1270. extNum.setSipExtNumList(extNumList);
  1271. return toAjax(ccExtNumService.updateCompanyBindExtNum(extNum));
  1272. }
  1273. /**
  1274. * 公司批量解绑分机,根据分机号
  1275. */
  1276. @PostMapping("/companyBatchUnbindSipExt")
  1277. @ResponseBody
  1278. public AjaxResult companyBatchUnbindSipExt(@RequestBody Set<Long> extNums)
  1279. {
  1280. if(extNums == null || extNums.isEmpty()){
  1281. return AjaxResult.error("参数为空");
  1282. }
  1283. return toAjax(ccExtNumService.companyBatchUnbindSipExt(extNums));
  1284. }
  1285. /**
  1286. * 新增用户且绑定未使用的分机返回用户
  1287. */
  1288. @PostMapping("/user/addUserOrBindExtNumReturnUser")
  1289. @ResponseBody
  1290. @Transactional
  1291. public AjaxResult addUserOrBindExtNumReturnUser(@RequestBody SysUser user)
  1292. {
  1293. if(StringUtils.isBlank(user.getPassword())){
  1294. throw new RuntimeException("密码不能为空");
  1295. }
  1296. // 校验分机号是否为空
  1297. if (null == user.getExtNum()) {
  1298. throw new RuntimeException("新增用户失败,分机号不能为空");
  1299. }
  1300. // 校验分机号是否存在
  1301. CcExtNum extNum = ccExtNumService.selectCcExtNumByExtNum(user.getExtNum());
  1302. if (null == extNum) {
  1303. throw new RuntimeException("新增用户失败,分机号" + user.getExtNum() + "不存在");
  1304. }
  1305. user.setSalt(ShiroUtils.randomSalt());
  1306. user.setPassword(passwordService.encryptPassword(user.getLoginName(), user.getPassword(), user.getSalt()));
  1307. user.setPwdUpdateDate(DateUtils.getNowDate());
  1308. user.setCreateBy("ylrz");
  1309. int i;
  1310. SysUser sysUser = userService.selectUserByLoginName(user.getLoginName());
  1311. if (sysUser != null)
  1312. {
  1313. //优化一下,如果账号存在就更新账号
  1314. user.setUserId(sysUser.getUserId());
  1315. i = userService.updateUser(user);
  1316. }else{
  1317. i = userService.insertUser(user);
  1318. }
  1319. if(i>0){
  1320. //绑定分机
  1321. extNum.setUserCode(user.getLoginName());
  1322. int num = ccExtNumService.updateCcExtNum(extNum);
  1323. if(num>0){
  1324. user.setExtPass(extNum.getExtPass());
  1325. return AjaxResult.success(user);
  1326. } else {
  1327. throw new RuntimeException("用户信息处理成功,但分机号绑定失败");
  1328. }
  1329. }
  1330. throw new RuntimeException("新增用户和绑分机操作失败");
  1331. }
  1332. /**
  1333. * 修改用户且绑分机
  1334. */
  1335. @PostMapping("/user/editUserOrUnBindExtNum")
  1336. @ResponseBody
  1337. @Transactional
  1338. public AjaxResult editUserOrUnBindExtNum(@RequestBody SysUser user)
  1339. {
  1340. if (!userService.checkLoginNameUnique(user))
  1341. {
  1342. throw new RuntimeException("修改用户'" + user.getLoginName() + "'失败,登录账号已存在");
  1343. }
  1344. else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user))
  1345. {
  1346. throw new RuntimeException("修改用户'" + user.getLoginName() + "'失败,手机号码已存在");
  1347. }
  1348. user.setUpdateBy("ylrz");
  1349. AuthorizationUtils.clearAllCachedAuthorizationInfo();
  1350. int i = userService.updateUser(user);
  1351. if(i>0){
  1352. int cleanNum;
  1353. if(StringUtils.isNotBlank(user.getUserSource()) && (user.getUserSource().equals("0") || user.getUserSource().equals("2"))){
  1354. cleanNum = ccExtNumService.updateUserCodeByLoginName(user.getCompanyName(),user.getLoginName());
  1355. }else{
  1356. //先清除原分机绑定
  1357. cleanNum = ccExtNumService.cleanCcExtNumByUserCode(user.getLoginName());
  1358. }
  1359. if(cleanNum>0){
  1360. //修改绑定分机
  1361. CcExtNum extNum = new CcExtNum();
  1362. extNum.setExtNum(user.getExtNum());
  1363. extNum.setUserCode(user.getLoginName());
  1364. int updateNum = ccExtNumService.updateCcExtNumByUserCode(extNum);
  1365. if(updateNum>0){
  1366. CcExtNum num = ccExtNumService.selectCcExtNumByExtNum(user.getExtNum());
  1367. if(null != num){
  1368. user.setExtPass(num.getExtPass());
  1369. return AjaxResult.success(user);
  1370. }
  1371. }
  1372. }
  1373. }
  1374. throw new RuntimeException("修改用户失败");
  1375. }
  1376. /**
  1377. * 删除用户且解绑分机
  1378. */
  1379. @PostMapping("/deleteUserOrunBindExtNum")
  1380. @ResponseBody
  1381. @Transactional
  1382. public AjaxResult deleteUserOrunBindExtNum(@RequestBody SysUser user)
  1383. {
  1384. //先解绑分机
  1385. CcExtNum extNum = new CcExtNum();
  1386. extNum.setExtNum(user.getExtNum());
  1387. extNum.setUserCode(user.getUserCode());
  1388. int updateNum = ccExtNumService.updateCcExtNumByUserCode(extNum);
  1389. if(updateNum>0){
  1390. //删除用户
  1391. int i = userService.deleteUserById(user.getUserId());
  1392. if(i>0){
  1393. return AjaxResult.success();
  1394. }
  1395. }
  1396. throw new RuntimeException("删除用户且解绑分机失败");
  1397. }
  1398. /**
  1399. * 获取手动外呼客户沟通信息
  1400. * @param phoneNum 手机号
  1401. * @param callType 类型 1呼入 2外呼
  1402. * @param uuid 通话uuid
  1403. */
  1404. @GetMapping("/getCustCommunicationInfo")
  1405. @ResponseBody
  1406. public AjaxResult getCustCommunicationInfo(@RequestParam("phoneNum") String phoneNum, @RequestParam("callType") Integer callType, @RequestParam("uuid") String uuid)
  1407. {
  1408. Map<String,Object> mmap = new HashMap<>();
  1409. CcCustInfo ccCustInfo = ccCustInfoService.selectCcCustInfoByPhoneNum(phoneNum);
  1410. if (null == ccCustInfo) {
  1411. ccCustInfo = new CcCustInfo();
  1412. ccCustInfo.setCallRecordList(new ArrayList<>());
  1413. } else {
  1414. ccCustInfo.setCallRecordList(ccCustCallRecordService.selectCcCustCallRecordList(new CcCustCallRecord().setCustId(ccCustInfo.getId())));
  1415. }
  1416. ccCustInfo.setPhoneNum(phoneNum);
  1417. mmap.put("ccCustInfo", ccCustInfo);
  1418. mmap.put("callType", callType);
  1419. mmap.put("uuid", uuid);
  1420. // 省下拉框
  1421. List<SysDivisionData> sysDivisionData = sysDivisionDataService.selectSysDivisionDataList(null);
  1422. List<SysDivisionData> provinces = sysDivisionData.stream()
  1423. .filter(d -> d.getDeep() == 0)
  1424. .collect(Collectors.toList());
  1425. mmap.put("provinces", provinces);
  1426. // 市下拉框
  1427. List<SysDivisionData> citys = sysDivisionData.stream()
  1428. .filter(d -> d.getDeep() == 1)
  1429. .collect(Collectors.toList());
  1430. mmap.put("citys", citys);
  1431. // 区县下拉框
  1432. List<SysDivisionData> countys = sysDivisionData.stream()
  1433. .filter(d -> d.getDeep() == 2)
  1434. .collect(Collectors.toList());
  1435. mmap.put("countys", countys);
  1436. return AjaxResult.success(mmap);
  1437. }
  1438. /**
  1439. * 新增保存手动外呼沟通记录
  1440. */
  1441. @PostMapping("/add/custcallrecord")
  1442. @ResponseBody
  1443. public AjaxResult addAustcallrecord(@RequestBody CcCustInfo ccCustInfo)
  1444. {
  1445. ccCustInfoService.updateCcCustInfo(ccCustInfo);
  1446. CcCustInfo custInfoBak = ccCustInfoService.selectCcCustInfoByPhoneNum(ccCustInfo.getPhoneNum());
  1447. CcCustCallRecord callRecord = JSONObject.parseObject(ccCustInfo.getCallRecord(), CcCustCallRecord.class);
  1448. callRecord.setCustId(custInfoBak.getId());
  1449. //这里改成查询
  1450. callRecord.setUserId(ccCustInfo.getOpNum());
  1451. callRecord.setUserRealName(ccCustInfo.getUserName());
  1452. callRecord.setCreateTime(new Date());
  1453. CcCustCallRecord hisCallRecord = ccCustCallRecordService.selectCcCustCallRecordByUuid(callRecord.getUuid());
  1454. if (null == hisCallRecord) {
  1455. return toAjax(ccCustCallRecordService.insertCcCustCallRecord(callRecord));
  1456. } else {
  1457. callRecord.setId(hisCallRecord.getId());
  1458. return toAjax(ccCustCallRecordService.updateCcCustCallRecord(callRecord));
  1459. }
  1460. }
  1461. /**
  1462. * 查询手动外呼记录列表
  1463. */
  1464. @PostMapping("/outboundcdrList")
  1465. @ResponseBody
  1466. public TableDataInfo outboundcdrList(@RequestBody CcOutboundCdr ccOutboundCdr)
  1467. {
  1468. startPage();
  1469. List<CcOutboundCdr> list = ccOutboundCdrService.selectCcOutboundCdrList(ccOutboundCdr);
  1470. for (CcOutboundCdr data: list) {
  1471. data.setWavFileUrl("/recordings/files?filename=" + data.getRecordFilename());
  1472. try {
  1473. if(StringUtils.isNotEmpty(data.getCallee())){
  1474. data.setCallee(DESUtil.encrypt(URLEncoder.encode(data.getCallee(), "UTF-8")));
  1475. }else{
  1476. data.setCallee("");
  1477. }
  1478. if(StringUtils.isNotEmpty(data.getCaller())){
  1479. data.setCaller(DESUtil.encrypt(URLEncoder.encode(data.getCaller(), "UTF-8")));
  1480. }else{
  1481. data.setCaller("");
  1482. }
  1483. } catch (Throwable e) {
  1484. throw new RuntimeException(e);
  1485. }
  1486. }
  1487. return getDataTable(list);
  1488. }
  1489. /**
  1490. * 通话记录查询接口(返回完整的数据表格式)
  1491. */
  1492. @PostMapping("/call/phone/records")
  1493. @ResponseBody
  1494. public TableDataInfo getcallPhoneRecords(HttpServletRequest req, @RequestBody ApiCallRecordQueryParams queryParams)
  1495. {
  1496. TableDataInfo tableDataInfo;
  1497. // 校验请求方ip是否合法
  1498. if (!ClientIpCheck.checkIp(req)) {
  1499. tableDataInfo = new TableDataInfo();
  1500. tableDataInfo.setTotal(0);
  1501. tableDataInfo.setCode(AjaxResult.Type.NO_AUTH.value());
  1502. tableDataInfo.setMsg("未授权,请联系系统管理员添加ip白名单!");
  1503. return tableDataInfo;
  1504. }
  1505. // 分页参数处理
  1506. if (null == queryParams.getPageNum()
  1507. && null == queryParams.getPageSize()) {
  1508. queryParams.setPageNum(1);
  1509. queryParams.setPageSize(200000);
  1510. }
  1511. if (null == queryParams.getPageNum()) {
  1512. queryParams.setPageNum(1);
  1513. }
  1514. if (null == queryParams.getPageSize()) {
  1515. queryParams.setPageSize(20);
  1516. }
  1517. // 类型(01:呼入, 02:AI外呼, 03:人工外呼)
  1518. String callType = queryParams.getCallType();
  1519. if (StringUtils.isBlank(callType)) {
  1520. tableDataInfo = new TableDataInfo();
  1521. tableDataInfo.setTotal(0);
  1522. tableDataInfo.setCode(AjaxResult.Type.INVALID_PARAM.value());
  1523. tableDataInfo.setMsg("callType不能为空!");
  1524. return tableDataInfo;
  1525. }
  1526. // 校验参数
  1527. if (StringUtils.isNotEmpty(queryParams.getCalloutTimeStart())
  1528. && !DateValidatorUtils.isYmdHms(queryParams.getCalloutTimeStart())) {
  1529. tableDataInfo = new TableDataInfo();
  1530. tableDataInfo.setTotal(0);
  1531. tableDataInfo.setCode(AjaxResult.Type.INVALID_PARAM.value());
  1532. tableDataInfo.setMsg("calloutTimeStart格式不正确,请使用'yyyy-MM-dd HH:mm:ss'格式!");
  1533. return tableDataInfo;
  1534. }
  1535. if (StringUtils.isNotEmpty(queryParams.getCalloutTimeEnd())
  1536. && !DateValidatorUtils.isYmdHms(queryParams.getCalloutTimeEnd())) {
  1537. tableDataInfo = new TableDataInfo();
  1538. tableDataInfo.setTotal(0);
  1539. tableDataInfo.setCode(AjaxResult.Type.INVALID_PARAM.value());
  1540. tableDataInfo.setMsg("calloutTimeStart格式不正确,请使用'yyyy-MM-dd HH:mm:ss'格式!");
  1541. return tableDataInfo;
  1542. }
  1543. // 01:呼入, 02:AI外呼, 03:人工外呼
  1544. if ("01".equals(callType)) {
  1545. return getInboundRecords(queryParams);
  1546. } else if ("02".equals(callType)) {
  1547. return getAiCallRecordsTable(queryParams);
  1548. } else if ("03".equals(callType)) {
  1549. return getOutboundRecordsTable(queryParams);
  1550. } else {
  1551. tableDataInfo = new TableDataInfo();
  1552. tableDataInfo.setTotal(0);
  1553. tableDataInfo.setCode(AjaxResult.Type.INVALID_PARAM.value());
  1554. tableDataInfo.setMsg("callType参数不合法,呼入请输入01,AI外呼请输入02,手工外呼请输入03!");
  1555. return tableDataInfo;
  1556. }
  1557. }
  1558. //ai外呼记录查询
  1559. private TableDataInfo getAiCallRecordsTable(ApiCallRecordQueryParams queryParams) {
  1560. Map<String, Object> params = new HashMap<>();
  1561. if (null != queryParams.getTimeLenStart()) {
  1562. params.put("timeLenStart", queryParams.getTimeLenStart());
  1563. }
  1564. if (null != queryParams.getTimeLenEnd()) {
  1565. params.put("timeLenEnd", queryParams.getTimeLenEnd());
  1566. }
  1567. if (null != queryParams.getCalloutTimeStart()) {
  1568. params.put("calloutTimeStart", queryParams.getCalloutTimeStart());
  1569. }
  1570. if (null != queryParams.getCalloutTimeEnd()) {
  1571. params.put("calloutTimeEnd", queryParams.getCalloutTimeEnd());
  1572. }
  1573. if (null != queryParams.getAnsweredTimeStart()) {
  1574. params.put("answeredTimeStart", queryParams.getAnsweredTimeStart());
  1575. }
  1576. if (null != queryParams.getAnsweredTimeEnd()) {
  1577. params.put("answeredTimeEnd", queryParams.getAnsweredTimeEnd());
  1578. }
  1579. if (null != queryParams.getCallEndTimeStart()) {
  1580. params.put("callEndTimeStart", queryParams.getCallEndTimeStart());
  1581. }
  1582. if (null != queryParams.getCallEndTimeEnd()) {
  1583. params.put("callEndTimeEnd", queryParams.getCallEndTimeEnd());
  1584. }
  1585. CcCallPhone ccCallPhone = new CcCallPhone();
  1586. if (null != queryParams.getBatchId() && queryParams.getBatchId() > 0) {
  1587. ccCallPhone.setBatchId(queryParams.getBatchId());
  1588. }
  1589. ccCallPhone.setUuid(queryParams.getUuid());
  1590. ccCallPhone.setTelephone(queryParams.getTelephone());
  1591. ccCallPhone.setAcdOpnum(queryParams.getExtnum());
  1592. ccCallPhone.setCallstatus(queryParams.getCallstatus());
  1593. ccCallPhone.setCallerNumber(queryParams.getCallerNumber());
  1594. ccCallPhone.setParams(params);
  1595. startPage(queryParams.getPageNum(), queryParams.getPageSize());
  1596. List<CcCallPhone> list = ccCallPhoneService.selectCcCallPhoneYlrzList(ccCallPhone);
  1597. list.forEach(callPhoneRecord -> {
  1598. if(StringUtils.isNotBlank(callPhoneRecord.getWavfile())){
  1599. if (callPhoneRecord.getWavfile().startsWith("/")) {
  1600. callPhoneRecord.setWavfile("/recordings/files?filename=" + callPhoneRecord.getWavfile().substring(1));
  1601. }else{
  1602. callPhoneRecord.setWavfile("/recordings/files?filename=" + callPhoneRecord.getWavfile());
  1603. }
  1604. }
  1605. callPhoneRecord.setTelephone(CommonUtils.maskPhoneNumber(callPhoneRecord.getTelephone()));
  1606. callPhoneRecord.setCallerNumber(CommonUtils.maskPhoneNumber(callPhoneRecord.getCallerNumber()));
  1607. callPhoneRecord.setCallstatusName( CcCallPhone.getCallStatusName(callPhoneRecord.getCallstatus()));
  1608. callPhoneRecord.setCalloutTimeStr(DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", new Date(callPhoneRecord.getCalloutTime())));
  1609. callPhoneRecord.setAnsweredTimeStr(DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", new Date(callPhoneRecord.getAnsweredTime())));
  1610. callPhoneRecord.setCallEndTimeStr(DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", new Date(callPhoneRecord.getCallEndTime())));
  1611. callPhoneRecord.setTimeLenSec(DateUtils.formatTimeLength(callPhoneRecord.getTimeLen()/1000));
  1612. });
  1613. return getDataTable(list);
  1614. }
  1615. //人工外呼记录查询
  1616. private TableDataInfo getOutboundRecordsTable(ApiCallRecordQueryParams queryParams) {
  1617. Map<String, Object> params = new HashMap<>();
  1618. if (null != queryParams.getTimeLenStart()) {
  1619. params.put("timeLenStart", queryParams.getTimeLenStart());
  1620. }
  1621. if (null != queryParams.getTimeLenEnd()) {
  1622. params.put("timeLenEnd", queryParams.getTimeLenEnd());
  1623. }
  1624. if (null != queryParams.getCalloutTimeStart()) {
  1625. params.put("calloutTimeStart", queryParams.getCalloutTimeStart());
  1626. }
  1627. if (null != queryParams.getCalloutTimeEnd()) {
  1628. params.put("calloutTimeEnd", queryParams.getCalloutTimeEnd());
  1629. }
  1630. if (null != queryParams.getAnsweredTimeStart()) {
  1631. params.put("answeredTimeStart", queryParams.getAnsweredTimeStart());
  1632. }
  1633. if (null != queryParams.getAnsweredTimeEnd()) {
  1634. params.put("answeredTimeEnd", queryParams.getAnsweredTimeEnd());
  1635. }
  1636. if (null != queryParams.getEndTimeStart()) {
  1637. params.put("endTimeStart", queryParams.getEndTimeStart());
  1638. }
  1639. if (null != queryParams.getEndTimeEnd()) {
  1640. params.put("endTimeEnd", queryParams.getEndTimeEnd());
  1641. }
  1642. CcCallPhone ccCallPhone = new CcCallPhone();
  1643. if (null != queryParams.getBatchId() && queryParams.getBatchId() > 0) {
  1644. ccCallPhone.setBatchId(queryParams.getBatchId());
  1645. }
  1646. CcOutboundCdr outboundCdr = new CcOutboundCdr();
  1647. outboundCdr.setUuid(queryParams.getUuid());
  1648. outboundCdr.setCaller(queryParams.getTelephone());
  1649. outboundCdr.setOpnum(queryParams.getExtnum());
  1650. outboundCdr.setParams(params);
  1651. startPage(queryParams.getPageNum(), queryParams.getPageSize());
  1652. List<CcOutboundCdr> list = outboundCdrService.selectCcOutboundCdrYlrzList(outboundCdr);
  1653. list.forEach(callPhoneRecord -> {
  1654. if(StringUtils.isNotBlank(callPhoneRecord.getRecordFilename())){
  1655. if (callPhoneRecord.getRecordFilename().startsWith("/")) {
  1656. callPhoneRecord.setRecordFilename("/recordings/files?filename=" + callPhoneRecord.getRecordFilename().substring(1));
  1657. }else{
  1658. callPhoneRecord.setWavFileUrl("/recordings/files?filename=" + callPhoneRecord.getRecordFilename());
  1659. }
  1660. callPhoneRecord.setStartTimeStr(DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", new Date(callPhoneRecord.getStartTime())));
  1661. callPhoneRecord.setAnsweredTimeStr(DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", new Date(callPhoneRecord.getAnsweredTime())));
  1662. callPhoneRecord.setEndTimeStr(DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", new Date(callPhoneRecord.getEndTime())));
  1663. callPhoneRecord.setTimeLenSec(DateUtils.formatTimeLength(callPhoneRecord.getTimeLen()/1000));
  1664. callPhoneRecord.setTimeLenValidStr(DateUtils.formatTimeLength(callPhoneRecord.getTimeLenValid()/1000));
  1665. }
  1666. callPhoneRecord.setCallee(CommonUtils.maskPhoneNumber(callPhoneRecord.getCallee()));
  1667. });
  1668. return getDataTable(list);
  1669. }
  1670. /**
  1671. * 获取外呼网关列表接口
  1672. * purposes 1手动外呼电话条,2AI外呼,3不限制
  1673. * @param queryParams 网关参数
  1674. * @param req
  1675. */
  1676. @PostMapping("/gateway/myList")
  1677. @ResponseBody
  1678. public TableDataInfo getGatewayMyList(@RequestBody CcGateways queryParams, HttpServletRequest req){
  1679. // 校验请求方ip是否合法
  1680. if (!ClientIpCheck.checkIp(req)) {
  1681. TableDataInfo tableDataInfo;
  1682. tableDataInfo = new TableDataInfo();
  1683. tableDataInfo.setTotal(0);
  1684. tableDataInfo.setCode(AjaxResult.Type.NO_AUTH.value());
  1685. tableDataInfo.setMsg("未授权,请联系系统管理员添加ip白名单!");
  1686. return tableDataInfo;
  1687. }
  1688. startPage(queryParams.getPageNum(), queryParams.getPageSize());
  1689. return getDataTable(ccGatewaysService.selectCcGatewaysList(queryParams));
  1690. }
  1691. /**
  1692. * 根据通话id集合查询uuid不为空的自动外呼数据
  1693. */
  1694. @PostMapping( "/getCcCallPhoneByIds")
  1695. @ResponseBody
  1696. public AjaxResult getCcCallPhoneByIds(@RequestBody List<String> callPhoneIds)
  1697. {
  1698. if(callPhoneIds==null){
  1699. return AjaxResult.error(AjaxResult.Type.INVALID_PARAM, "callPhoneIds不能为空!", "");
  1700. }
  1701. List<CcCallPhone> list = ccCallPhoneService.selectCcCallPhoneListByIds(callPhoneIds);
  1702. if(!CollectionUtils.isEmpty(list)){
  1703. list.forEach(callPhoneRecord -> {
  1704. callPhoneRecord.setBizJson("");
  1705. try{
  1706. if(StringUtils.isNotEmpty(callPhoneRecord.getTelephone())){
  1707. callPhoneRecord.setTelephone(DESUtil.encrypt(URLEncoder.encode(callPhoneRecord.getTelephone(), "UTF-8")));
  1708. }else{
  1709. callPhoneRecord.setTelephone("");
  1710. }
  1711. }catch (Exception e){
  1712. callPhoneRecord.setTelephone("");
  1713. }
  1714. try{
  1715. if(StringUtils.isNotEmpty(callPhoneRecord.getCallerNumber())){
  1716. callPhoneRecord.setCallerNumber(DESUtil.encrypt(URLEncoder.encode(callPhoneRecord.getCallerNumber(), "UTF-8")));
  1717. }else{
  1718. callPhoneRecord.setCallerNumber("");
  1719. }
  1720. }catch (Exception e){
  1721. callPhoneRecord.setCallerNumber("");
  1722. }
  1723. });
  1724. }
  1725. return AjaxResult.success(list);
  1726. }
  1727. /**
  1728. * 根据UUID查询自动外呼对话详情
  1729. */
  1730. @PostMapping( "/getCcCallPhoneByUuid")
  1731. @ResponseBody
  1732. public AjaxResult getCcCallPhoneByUuid(@RequestBody CcCallPhone callPhone)
  1733. {
  1734. if(callPhone==null || StringUtils.isBlank(callPhone.getUuid())){
  1735. return AjaxResult.error(AjaxResult.Type.INVALID_PARAM, "callPhone或uuid不能为空!", "");
  1736. }
  1737. return AjaxResult.success(ccCallPhoneService.selectCcCallPhoneDialogueByUuid(callPhone.getUuid()));
  1738. }
  1739. /**
  1740. * 修改任务
  1741. * @param ccCallTask
  1742. * @return
  1743. */
  1744. @PostMapping("/editTask")
  1745. @ResponseBody
  1746. public AjaxResult editTask(@RequestBody CcCallTask ccCallTask)
  1747. {
  1748. if ("acd".equals(ccCallTask.getAiTransferType())) {
  1749. ccCallTask.setAiTransferData(ccCallTask.getAiTransferGroupId());
  1750. } else if ("extension".equals(ccCallTask.getAiTransferType())) {
  1751. ccCallTask.setAiTransferData(ccCallTask.getAiTransferExtNumber());
  1752. } else if ("gateway".equals(ccCallTask.getAiTransferType())) {
  1753. JSONObject aiTransferData = new JSONObject();
  1754. aiTransferData.put("gatewayId", ccCallTask.getAiTransferGatewayId());
  1755. aiTransferData.put("destNumber", ccCallTask.getAiTransferGatewayDestNumber());
  1756. ccCallTask.setAiTransferData(JSONObject.toJSONString(aiTransferData));
  1757. }
  1758. return toAjax(ccCallTaskService.updateCcCallTask(ccCallTask));
  1759. }
  1760. /**
  1761. * 获取音色分页列表
  1762. */
  1763. @PostMapping("/voicecodePage")
  1764. @ResponseBody
  1765. public TableDataInfo voicecodePage(@RequestBody CcTtsAliyun queryParams)
  1766. {
  1767. if(queryParams==null){
  1768. queryParams = new CcTtsAliyun();
  1769. }
  1770. if(queryParams.getPageNum()==null){
  1771. queryParams.setPageNum(1);
  1772. }
  1773. if(queryParams.getPageSize()== null){
  1774. queryParams.setPageSize(10);
  1775. }
  1776. startPage(queryParams.getPageNum(), queryParams.getPageSize());
  1777. // 获取音色列表
  1778. List<CcTtsAliyun> list = ccTtsAliyunService.selectCcTtsAliyunList(queryParams);
  1779. return getDataTable(list);
  1780. }
  1781. /**
  1782. * 追加外呼名单(不自动启动任务,数据加密传输)
  1783. * @param encryptedData
  1784. */
  1785. @PostMapping(value ="/import/autoCallData")
  1786. @ResponseBody
  1787. public AjaxResult addCommonCallList(@RequestBody String encryptedData) {
  1788. // 解密数据
  1789. String decryptedJson;
  1790. try {
  1791. //base64特殊处理
  1792. encryptedData = URLDecoder.decode(encryptedData, "UTF-8").replaceAll("=+$", "");
  1793. decryptedJson = DESUtil.decrypt(encryptedData);
  1794. } catch (Throwable e) {
  1795. return AjaxResult.error(AjaxResult.Type.INVALID_PARAM, "参数encryptedData解密失败", "");
  1796. }
  1797. // 2. 反序列化为 Java 对象
  1798. CommonCallListModel commonCallListModel = JSONObject.parseObject(decryptedJson, CommonCallListModel.class);
  1799. Long batchId = commonCallListModel.getBatchId();
  1800. if (null == batchId) {
  1801. return AjaxResult.error(AjaxResult.Type.INVALID_PARAM, "参数batchId不能为空", "");
  1802. }
  1803. if (CollectionUtils.isEmpty(commonCallListModel.getPhoneList())) {
  1804. return AjaxResult.error(AjaxResult.Type.INVALID_PARAM, "参数phoneList不能为空", "");
  1805. }
  1806. // 获取任务
  1807. CcCallTask ccCallTask = callTaskService.selectCcCallTaskByBatchId(batchId);
  1808. if (null == ccCallTask) {
  1809. return AjaxResult.error(AjaxResult.Type.INVALID_PARAM, "参数batchId不合法,请输入正确的batchId", "");
  1810. }
  1811. // 通知类的通知内容必填
  1812. if (ccCallTask.getTaskType() == 2) {
  1813. for (CommonPhoneModel commonPhoneModel : commonCallListModel.getPhoneList()) {
  1814. if (StringUtils.isBlank(commonPhoneModel.getNoticeContent())) {
  1815. return AjaxResult.error(AjaxResult.Type.INVALID_PARAM, "号码" + commonPhoneModel.getPhoneNum() + "的noticeContent不能为空!", "");
  1816. }
  1817. }
  1818. }
  1819. // 追加名单:逐批入库,每批成功后再汇总,批次互不影响
  1820. List<CcCallPhone> batchList = new ArrayList<>(200);
  1821. List<CcCallPhone> allCallPhoneList = new ArrayList<>();
  1822. for (CommonPhoneModel commonPhoneModel : commonCallListModel.getPhoneList()) {
  1823. String phoneNum = commonPhoneModel.getPhoneNum();
  1824. if (StringUtils.isBlank(phoneNum)) {
  1825. continue;
  1826. }
  1827. CcCallPhone callPhone = buildCcCallPhone(ccCallTask, phoneNum, commonPhoneModel.getBizJson());
  1828. callPhone.setTtsText(commonPhoneModel.getNoticeContent());
  1829. batchList.add(callPhone);
  1830. if (batchList.size() >= 200) {
  1831. insertCallPhoneBatch(batchList, allCallPhoneList);
  1832. }
  1833. }
  1834. insertCallPhoneBatch(batchList, allCallPhoneList);
  1835. int successCount = allCallPhoneList.size();
  1836. log.info("成功追加" + successCount + "个名单");
  1837. if(!CollectionUtils.isEmpty(allCallPhoneList)){
  1838. allCallPhoneList.forEach(callPhoneRecord -> {
  1839. callPhoneRecord.setBizJson("");
  1840. try{
  1841. if(StringUtils.isNotEmpty(callPhoneRecord.getTelephone())){
  1842. callPhoneRecord.setTelephone(DESUtil.encrypt(URLEncoder.encode(callPhoneRecord.getTelephone(), "UTF-8")));
  1843. }else{
  1844. callPhoneRecord.setTelephone("");
  1845. }
  1846. }catch (Throwable e){
  1847. callPhoneRecord.setTelephone("");
  1848. }
  1849. try{
  1850. if(StringUtils.isNotEmpty(callPhoneRecord.getCallerNumber())){
  1851. callPhoneRecord.setCallerNumber(DESUtil.encrypt(URLEncoder.encode(callPhoneRecord.getCallerNumber(), "UTF-8")));
  1852. }else{
  1853. callPhoneRecord.setCallerNumber("");
  1854. }
  1855. }catch (Throwable e){
  1856. callPhoneRecord.setCallerNumber("");
  1857. }
  1858. });
  1859. }
  1860. return AjaxResult.success("成功追加" + successCount + "个名单", allCallPhoneList);
  1861. }
  1862. /**
  1863. * 手动同步手动外呼记录
  1864. * @param ids
  1865. */
  1866. @PostMapping(value ="/outboundcdr/manualPullTest")
  1867. @ResponseBody
  1868. public AjaxResult outboundcdrManualPullTest(@RequestBody List<String> ids) {
  1869. List<CcOutboundCdr> list = outboundCdrService.selectCcOutboundCdrByIds(ids);
  1870. if(!CollectionUtils.isEmpty(list)){
  1871. for (CcOutboundCdr outboundCdr : list){
  1872. if(StringUtils.isNotEmpty(outboundCdr.getCaller())){
  1873. try {
  1874. outboundCdr.setCaller(DESUtil.encrypt(URLEncoder.encode(outboundCdr.getCaller(), "UTF-8")));
  1875. } catch (Throwable e) {
  1876. outboundCdr.setCaller("");
  1877. }
  1878. }
  1879. if(StringUtils.isNotEmpty(outboundCdr.getCallee())){
  1880. try {
  1881. outboundCdr.setCallee(DESUtil.encrypt(URLEncoder.encode(outboundCdr.getCallee(), "UTF-8")));
  1882. } catch (Throwable e) {
  1883. outboundCdr.setCallee("");
  1884. }
  1885. }
  1886. }
  1887. }
  1888. return AjaxResult.success("成功获取" + list.size() + "条数据",list);
  1889. }
  1890. /**
  1891. * 查询全部ttsprovider列表
  1892. */
  1893. @GetMapping("/tts/voiceSource/all")
  1894. @ResponseBody
  1895. public AjaxResult allTtsProvider()
  1896. {
  1897. SysConfig sysConfig = new SysConfig();
  1898. sysConfig.setConfigKey("config_tts_provider");
  1899. List<SysConfig> list = sysConfigService.selectConfigList(sysConfig);
  1900. Map<String, String> providerMap = new HashMap<>();
  1901. for (SysConfig data: list) {
  1902. providerMap.put(data.getConfigValue(), data.getConfigName());
  1903. }
  1904. return AjaxResult.success(providerMap);
  1905. }
  1906. /**
  1907. * 查询全部asrprovider列表
  1908. */
  1909. @GetMapping("/asr/provider/all")
  1910. @ResponseBody
  1911. public AjaxResult allAsrProvider()
  1912. {
  1913. SysConfig sysConfig = new SysConfig();
  1914. sysConfig.setConfigKey("config_asr_provider");
  1915. List<SysConfig> list = sysConfigService.selectConfigList(sysConfig);
  1916. Map<String, String> providerMap = new HashMap<>();
  1917. for (SysConfig data: list) {
  1918. providerMap.put(data.getConfigValue(), data.getConfigName());
  1919. }
  1920. return AjaxResult.success(providerMap);
  1921. }
  1922. /**
  1923. * 根据asr厂商获取语言
  1924. */
  1925. @GetMapping("/asr/language")
  1926. @ResponseBody
  1927. public AjaxResult getAsrLanguages(@RequestParam String asrProvider)
  1928. {
  1929. List<JSONObject> languageList = new ArrayList<>();
  1930. Map<String, String> languageCodeMap = new HashMap<>();
  1931. List<CcAsrLanguages> asrLanguagesList = asrLanguagesService.selectCcAsrLanguagesList(new CcAsrLanguages().setAsrProvider(asrProvider));
  1932. for (CcAsrLanguages asrLanguages: asrLanguagesList) {
  1933. if (StringUtils.isNotEmpty(asrLanguages.getLanguageCode())
  1934. && StringUtils.isEmpty(languageCodeMap.get(asrLanguages.getLanguageCode()))) {
  1935. languageCodeMap.put(asrLanguages.getLanguageCode(), asrLanguages.getLanguageName());
  1936. }
  1937. }
  1938. if (CollectionUtils.isEmpty(languageCodeMap)) {
  1939. languageCodeMap.put("zh-CN", "中文");
  1940. }
  1941. for (String key: languageCodeMap.keySet()) {
  1942. JSONObject obj = new JSONObject();
  1943. obj.put("key", key);
  1944. obj.put("value", languageCodeMap.get(key));
  1945. languageList.add(obj);
  1946. }
  1947. return AjaxResult.success(languageList);
  1948. }
  1949. /**
  1950. * 根据asr厂商和语言获取asr模型列表
  1951. */
  1952. @GetMapping("/asr/models")
  1953. @ResponseBody
  1954. public AjaxResult getAsrModels(@RequestParam String asrProvider, @RequestParam String asrLanguageCode)
  1955. {
  1956. List<JSONObject> modelsList = new ArrayList<>();
  1957. Map<String, String> asrModelsMap = new HashMap<>();
  1958. List<CcAsrLanguages> asrLanguagesList = asrLanguagesService.selectCcAsrLanguagesList(new CcAsrLanguages().setAsrProvider(asrProvider).setLanguageCode(asrLanguageCode));
  1959. for (CcAsrLanguages asrLanguages: asrLanguagesList) {
  1960. if (StringUtils.isNotEmpty(asrLanguages.getModels())
  1961. && StringUtils.isEmpty(asrModelsMap.get(asrLanguages.getModels()))) {
  1962. asrModelsMap.put(asrLanguages.getModels(), asrLanguages.getModels());
  1963. }
  1964. }
  1965. if (CollectionUtils.isEmpty(asrModelsMap)) {
  1966. asrModelsMap.put("", "");
  1967. }
  1968. for (String key: asrModelsMap.keySet()) {
  1969. JSONObject obj = new JSONObject();
  1970. obj.put("key", key);
  1971. obj.put("value", asrModelsMap.get(key));
  1972. modelsList.add(obj);
  1973. }
  1974. return AjaxResult.success(modelsList);
  1975. }
  1976. /**
  1977. * 根据tts厂商和语言获取asr模型列表
  1978. */
  1979. @GetMapping("/tts/models")
  1980. @ResponseBody
  1981. public AjaxResult getTtsModels(@RequestParam String voiceSource, @RequestParam String ttsLanguageCode)
  1982. {
  1983. List<JSONObject> modelsList = new ArrayList<>();
  1984. Map<String, String> ttsModelMap = new HashMap<>();
  1985. List<CcTtsAliyun> ccTtsAliyunList = ccTtsAliyunService.selectCcTtsAliyunList(new CcTtsAliyun().setVoiceSource(voiceSource).setLanguageCode(ttsLanguageCode));
  1986. for (CcTtsAliyun ccTtsAliyun: ccTtsAliyunList) {
  1987. if (StringUtils.isNotEmpty(ccTtsAliyun.getTtsModels())
  1988. && StringUtils.isEmpty(ttsModelMap.get(ccTtsAliyun.getTtsModels()))) {
  1989. ttsModelMap.put(ccTtsAliyun.getTtsModels(), ccTtsAliyun.getTtsModels());
  1990. }
  1991. }
  1992. if (CollectionUtils.isEmpty(ttsModelMap)) {
  1993. ttsModelMap.put("", "");
  1994. }
  1995. for (String key: ttsModelMap.keySet()) {
  1996. JSONObject obj = new JSONObject();
  1997. obj.put("key", key);
  1998. obj.put("value", ttsModelMap.get(key));
  1999. modelsList.add(obj);
  2000. }
  2001. return AjaxResult.success(modelsList);
  2002. }
  2003. /**
  2004. * 根据tts厂商获取支持语言
  2005. */
  2006. @GetMapping("/tts/language")
  2007. @ResponseBody
  2008. public AjaxResult getTtsLanguages(@RequestParam String voiceSource)
  2009. {
  2010. List<JSONObject> languageList = new ArrayList<>();
  2011. Map<String, String> languageCodeMap = new HashMap<>();
  2012. List<CcTtsAliyun> ccTtsAliyunList = ccTtsAliyunService.selectCcTtsAliyunList(new CcTtsAliyun().setVoiceSource(voiceSource));
  2013. for (CcTtsAliyun ccTtsAliyun: ccTtsAliyunList) {
  2014. if (StringUtils.isNotEmpty(ccTtsAliyun.getLanguageCode())
  2015. && StringUtils.isEmpty(languageCodeMap.get(ccTtsAliyun.getLanguageCode()))) {
  2016. languageCodeMap.put(ccTtsAliyun.getLanguageCode(), ccTtsAliyun.getLanguageName());
  2017. }
  2018. }
  2019. if (CollectionUtils.isEmpty(languageCodeMap)) {
  2020. languageCodeMap.put("zh-CN", "中文");
  2021. }
  2022. for (String key: languageCodeMap.keySet()) {
  2023. JSONObject obj = new JSONObject();
  2024. obj.put("key", key);
  2025. obj.put("value", languageCodeMap.get(key));
  2026. languageList.add(obj);
  2027. }
  2028. return AjaxResult.success(languageList);
  2029. }
  2030. }