Explorar el Código

外呼新增接口列表

peicj hace 2 días
padre
commit
8ea2d55136

+ 527 - 0
ruoyi-admin/src/main/java/com/ruoyi/aicall/controller/ApiController.java

@@ -13,6 +13,7 @@ import com.ruoyi.aicall.service.ICcCallTaskService;
 import com.ruoyi.aicall.service.ICcLlmAgentAccountService;
 import com.ruoyi.aicall.service.ICcTtsAliyunService;
 import com.ruoyi.aicall.utils.ClientIpCheck;
+import com.ruoyi.aicall.utils.DESUtil;
 import com.ruoyi.cc.domain.*;
 import com.ruoyi.cc.service.*;
 import com.ruoyi.cc.utils.DateValidatorUtils;
@@ -25,15 +26,20 @@ import com.ruoyi.common.utils.ShiroUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.bean.BeanUtils;
 import com.ruoyi.common.utils.uuid.UuidGenerator;
+import com.ruoyi.framework.shiro.service.SysPasswordService;
+import com.ruoyi.framework.shiro.util.AuthorizationUtils;
+import com.ruoyi.system.service.ISysUserService;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.RandomUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Controller;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
 import java.util.*;
+import java.util.stream.Collectors;
 
 @Controller
 @Slf4j
@@ -64,6 +70,18 @@ public class ApiController extends BaseController {
     private ICcExtNumService ccExtNumService;
     @Autowired
     private ICcParamsService ccParamsService;
+    @Autowired
+    private ISysUserService userService;
+    @Autowired
+    private SysPasswordService passwordService;
+    @Autowired
+    private ICcCustCallRecordService ccCustCallRecordService;
+    @Autowired
+    private ICcCustInfoService ccCustInfoService;
+    @Autowired
+    private ISysDivisionDataService sysDivisionDataService;
+    @Autowired
+    private ICcOutboundCdrService ccOutboundCdrService;
 
     /**
      * 获取外呼网关列表接口
@@ -1101,4 +1119,513 @@ public class ApiController extends BaseController {
         result.put("data", data);
         return result;
     }
+
+    //=======================================================新增接口============================================================
+    /**
+     * 删除外呼任务
+     */
+    @PostMapping( "/removeTask")
+    @ResponseBody
+    @Transactional
+    public AjaxResult removeTask(@RequestBody Map<String, Long[]> paramMap)
+    {
+        Long[] batchIds= paramMap.get("batchIds");
+        if(batchIds==null){
+            return AjaxResult.error(AjaxResult.Type.INVALID_PARAM, "batchIds不能为空!", "");
+        }
+        for (Long batchId : batchIds) {
+            // 备份拨打记录数据
+            ccCallPhoneService.bakCallPhoneByBatchId(batchId);
+            // 删除拨打记录数据
+            ccCallPhoneService.delCallPhoneByBatchId(batchId);
+            // 备份任务数据
+            ccCallTaskService.bakCallTaskByBatchId(batchId);
+        }
+
+        // 删除任务数据
+        String batchIdsStr = Arrays.stream(batchIds)
+                .map(String::valueOf)
+                .collect(Collectors.joining(","));
+        return toAjax(ccCallTaskService.deleteCcCallTaskByBatchIds(batchIdsStr));
+    }
+    /**
+     * 获取电话工具条的网关列表
+     */
+    @PostMapping("/myPhoneBar/params")
+    @ResponseBody
+    public AjaxResult getMyPhoneBaseParams(@RequestBody Map<String,String> param) {
+
+        String extNum = param.get("extNum");
+        String myGateway = param.get("myGateway");
+        if(extNum == null){
+            return AjaxResult.error("分机号参数缺失");
+        }
+        // 获取分机号
+        CcExtNum ccExtNum = ccExtNumService.selectCcExtNumByExtNum(Long.valueOf(extNum));
+
+        String extnum = ccExtNum.getExtNum().toString();
+        String opnum = ccExtNum.getUserCode();
+        String password = ccExtNum.getExtPass();
+        String groupId = "1";
+        String skillLevel = "9";
+        String projectId = "1";
+        //1.创建token
+        String loginToken = ccExtNumService.createToken(extnum, opnum, groupId, skillLevel, projectId);
+        //2.获取加密密码
+        String encryptStr = DESUtil.encrypt(password + "," + DateUtils.format(DateUtils.addDays(new Date(), 1), "yyyyMMddHHmm"));
+        encryptStr = String.format("var _phoneEncryptPassword='%s';", encryptStr);
+
+        CcGateways ccGatewaysVo = new CcGateways();
+        //判断指定网关还是全部网关
+        if(StringUtils.isNotBlank(myGateway)){
+            List<Long> gatewayIds = Arrays.stream(myGateway.split(","))
+                    .map(Long::parseLong)
+                    .collect(Collectors.toList());
+            ccGatewaysVo.setGatewayIds(gatewayIds);
+        }else{
+            // 网关用途 0 已废弃; 1 电话条; 2 外呼任务; 3 无限制
+            Map<String, Object> params = new HashMap<>();
+            params.put("purposes", Arrays.asList(1,3));
+            ccGatewaysVo.setParams(params);
+        }
+        //3.获取工具条网关列表
+        List<CcGateways> gatewaysList = ccGatewaysService.selectCcGatewaysList(ccGatewaysVo);
+        List<JSONObject> gatewayList = new ArrayList<>();
+        for (CcGateways ccGateways: gatewaysList) {
+            JSONObject configGateway = new JSONObject();
+            configGateway.put("uuid", ccGateways.getId().toString());
+            configGateway.put("updateTime", ccGateways.getUpdateTime());
+            configGateway.put("gatewayAddr", ccGateways.getGwAddr());
+            configGateway.put("callerNumber", ccGateways.getCaller());
+            configGateway.put("calleePrefix", ccGateways.getCalleePrefix());
+            configGateway.put("callProfile", ccGateways.getProfileName());
+            configGateway.put("priority", ccGateways.getPriority());
+            configGateway.put("concurrency", ccGateways.getMaxConcurrency());
+            configGateway.put("register", ccGateways.getRegister());
+            configGateway.put("authUsername", ccGateways.getAuthUsername());
+            configGateway.put("audioCodec", ccGateways.getCodec());
+            gatewayList.add(configGateway);
+        }
+        JSONObject callConfig = new JSONObject();
+
+        String scriptServer = ccParamsService.getParamValueByCode("call-center-server-ip-addr", "");
+        String scriptPort = ccParamsService.getParamValueByCode("call-center-websocket-port", "");
+
+        callConfig.put("scriptServer", scriptServer);
+        callConfig.put("scriptPort", scriptPort);
+        callConfig.put("loginToken", loginToken);
+        callConfig.put("encryptPsw", encryptStr);
+        callConfig.put("gatewayList", gatewayList);
+        //登录账号
+        callConfig.put("opNum", opnum);
+        //登录用户名称
+        SysUser sysUser = userService.selectUserByLoginName(opnum);
+        if(sysUser != null){
+            callConfig.put("userName", sysUser.getUserName());
+        }
+
+        return AjaxResult.success(callConfig);
+
+    }
+    /**
+     * 查询未绑定的分机管理列表
+     */
+    @GetMapping("/extnum/selectUnBindCcExtNumList")
+    @ResponseBody
+    public AjaxResult selectUnBindCcExtNumList()
+    {
+        return AjaxResult.success(ccExtNumService.selectUnBindCcExtNumList());
+    }
+    /**
+     * 新增用户且绑定未使用的分机返回用户
+     */
+    @PostMapping("/user/addUserOrBindExtNumReturnUser")
+    @ResponseBody
+    @Transactional
+    public AjaxResult addUserOrBindExtNumReturnUser(@RequestBody SysUser user)
+    {
+        if (!userService.checkLoginNameUnique(user))
+        {
+            throw new RuntimeException("新增用户'" + user.getLoginName() + "'失败,登录账号已存在");
+        }
+        else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user))
+        {
+            throw new RuntimeException("新增用户'" + user.getLoginName() + "'失败,手机号码已存在");
+        }
+        user.setSalt(ShiroUtils.randomSalt());
+        user.setPassword(passwordService.encryptPassword(user.getLoginName(), user.getPassword(), user.getSalt()));
+        user.setPwdUpdateDate(DateUtils.getNowDate());
+        user.setCreateBy("ylrz");
+        int i = userService.insertUser(user);
+        if(i>0){
+            //绑定分机
+            if (StringUtils.isNotEmpty(user.getLoginName())) {
+                CcExtNum extNum = ccExtNumService.selectCcExtNumByExtNum(user.getExtNum());
+                if (null != extNum) {
+                    extNum.setUserCode(user.getLoginName());
+                    int num = ccExtNumService.updateCcExtNum(extNum);
+                    if(num>0){
+                        return AjaxResult.success(user);
+                    }
+                }
+            }
+        }
+        throw new RuntimeException("新增用户失败");
+    }
+    /**
+     * 修改用户且绑分机
+     */
+    @PostMapping("/user/editUserOrUnBindExtNum")
+    @ResponseBody
+    @Transactional
+    public AjaxResult editUserOrUnBindExtNum(@RequestBody SysUser user)
+    {
+        if (!userService.checkLoginNameUnique(user))
+        {
+            throw new RuntimeException("修改用户'" + user.getLoginName() + "'失败,登录账号已存在");
+        }
+        else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user))
+        {
+            throw new RuntimeException("修改用户'" + user.getLoginName() + "'失败,手机号码已存在");
+        }
+        user.setUpdateBy("ylrz");
+        AuthorizationUtils.clearAllCachedAuthorizationInfo();
+        int i = userService.updateUser(user);
+        if(i>0){
+            //修改绑定分机
+            CcExtNum extNum = new CcExtNum();
+            extNum.setExtNum(user.getExtNum());
+            extNum.setUserCode(user.getLoginName());
+            //先清除原分机绑定
+            int cleanNum = ccExtNumService.cleanCcExtNumByUserCode(user.getLoginName());
+            if(cleanNum>0){
+                int updateNum = ccExtNumService.updateCcExtNumByUserCode(extNum);
+                if(updateNum>0){
+                    return AjaxResult.success(user);
+                }
+            }
+        }
+        throw new RuntimeException("修改用户失败");
+    }
+
+
+    /**
+     * 获取手动外呼客户沟通信息
+     * @param phoneNum 手机号
+     * @param callType 类型  1呼入 2外呼
+     * @param uuid  通话uuid
+     */
+    @GetMapping("/getCustCommunicationInfo")
+    @ResponseBody
+    public AjaxResult getCustCommunicationInfo(@RequestParam("phoneNum") String phoneNum, @RequestParam("callType") Integer callType, @RequestParam("uuid") String uuid)
+    {
+        Map<String,Object> mmap = new HashMap<>();
+        CcCustInfo ccCustInfo = ccCustInfoService.selectCcCustInfoByPhoneNum(phoneNum);
+        if (null == ccCustInfo) {
+            ccCustInfo = new CcCustInfo();
+            ccCustInfo.setCallRecordList(new ArrayList<>());
+        } else {
+            ccCustInfo.setCallRecordList(ccCustCallRecordService.selectCcCustCallRecordList(new CcCustCallRecord().setCustId(ccCustInfo.getId())));
+        }
+        ccCustInfo.setPhoneNum(phoneNum);
+        mmap.put("ccCustInfo", ccCustInfo);
+        mmap.put("callType", callType);
+        mmap.put("uuid", uuid);
+        // 省下拉框
+        List<SysDivisionData> sysDivisionData = sysDivisionDataService.selectSysDivisionDataList(null);
+        List<SysDivisionData> provinces = sysDivisionData.stream()
+                .filter(d -> d.getDeep() == 0)
+                .collect(Collectors.toList());
+        mmap.put("provinces", provinces);
+        // 市下拉框
+        List<SysDivisionData> citys = sysDivisionData.stream()
+                .filter(d -> d.getDeep() == 1)
+                .collect(Collectors.toList());
+        mmap.put("citys", citys);
+        // 区县下拉框
+        List<SysDivisionData> countys = sysDivisionData.stream()
+                .filter(d -> d.getDeep() == 2)
+                .collect(Collectors.toList());
+        mmap.put("countys", countys);
+        return AjaxResult.success(mmap);
+    }
+
+    /**
+     * 新增保存手动外呼沟通记录
+     */
+    @PostMapping("/add/custcallrecord")
+    @ResponseBody
+    public AjaxResult addAustcallrecord(@RequestBody CcCustInfo ccCustInfo)
+    {
+        ccCustInfoService.updateCcCustInfo(ccCustInfo);
+        CcCustInfo custInfoBak = ccCustInfoService.selectCcCustInfoByPhoneNum(ccCustInfo.getPhoneNum());
+        CcCustCallRecord callRecord = JSONObject.parseObject(ccCustInfo.getCallRecord(), CcCustCallRecord.class);
+        callRecord.setCustId(custInfoBak.getId());
+        //这里改成查询
+
+        callRecord.setUserId(ccCustInfo.getOpNum());
+        callRecord.setUserRealName(ccCustInfo.getUserName());
+        callRecord.setCreateTime(new Date());
+        CcCustCallRecord hisCallRecord = ccCustCallRecordService.selectCcCustCallRecordByUuid(callRecord.getUuid());
+        if (null == hisCallRecord) {
+            return toAjax(ccCustCallRecordService.insertCcCustCallRecord(callRecord));
+        } else {
+            callRecord.setId(hisCallRecord.getId());
+            return toAjax(ccCustCallRecordService.updateCcCustCallRecord(callRecord));
+        }
+    }
+    /**
+     * 查询手动外呼记录列表
+     */
+    @PostMapping("/outboundcdrList")
+    @ResponseBody
+    public TableDataInfo outboundcdrList(@RequestBody CcOutboundCdr ccOutboundCdr)
+    {
+        startPage();
+        List<CcOutboundCdr> list = ccOutboundCdrService.selectCcOutboundCdrList(ccOutboundCdr);
+        for (CcOutboundCdr data: list) {
+            data.setWavFileUrl("/recordings/files?filename=" + data.getRecordFilename());
+        }
+        return getDataTable(list);
+    }
+
+    /**
+     * 通话记录查询接口(返回完整的数据表格式)
+     */
+    @PostMapping("/call/phone/records")
+    @ResponseBody
+    public TableDataInfo getcallPhoneRecords(HttpServletRequest req, @RequestBody ApiCallRecordQueryParams queryParams)
+    {
+        TableDataInfo tableDataInfo;
+        // 校验请求方ip是否合法
+        if (!ClientIpCheck.checkIp(req)) {
+            tableDataInfo = new TableDataInfo();
+            tableDataInfo.setTotal(0);
+            tableDataInfo.setCode(AjaxResult.Type.NO_AUTH.value());
+            tableDataInfo.setMsg("未授权,请联系系统管理员添加ip白名单!");
+            return tableDataInfo;
+        }
+        // 分页参数处理
+        if (null == queryParams.getPageNum()
+                && null == queryParams.getPageSize()) {
+            queryParams.setPageNum(1);
+            queryParams.setPageSize(200000);
+        }
+        if (null == queryParams.getPageNum()) {
+            queryParams.setPageNum(1);
+        }
+        if (null == queryParams.getPageSize()) {
+            queryParams.setPageSize(20);
+        }
+        // 类型(01:呼入, 02:AI外呼, 03:人工外呼)
+        String callType = queryParams.getCallType();
+        if (StringUtils.isBlank(callType)) {
+            tableDataInfo = new TableDataInfo();
+            tableDataInfo.setTotal(0);
+            tableDataInfo.setCode(AjaxResult.Type.INVALID_PARAM.value());
+            tableDataInfo.setMsg("callType不能为空!");
+            return tableDataInfo;
+        }
+        // 校验参数
+        if (StringUtils.isNotEmpty(queryParams.getCalloutTimeStart())
+                && !DateValidatorUtils.isYmdHms(queryParams.getCalloutTimeStart())) {
+            tableDataInfo = new TableDataInfo();
+            tableDataInfo.setTotal(0);
+            tableDataInfo.setCode(AjaxResult.Type.INVALID_PARAM.value());
+            tableDataInfo.setMsg("calloutTimeStart格式不正确,请使用'yyyy-MM-dd HH:mm:ss'格式!");
+            return tableDataInfo;
+        }
+        if (StringUtils.isNotEmpty(queryParams.getCalloutTimeEnd())
+                && !DateValidatorUtils.isYmdHms(queryParams.getCalloutTimeEnd())) {
+            tableDataInfo = new TableDataInfo();
+            tableDataInfo.setTotal(0);
+            tableDataInfo.setCode(AjaxResult.Type.INVALID_PARAM.value());
+            tableDataInfo.setMsg("calloutTimeStart格式不正确,请使用'yyyy-MM-dd HH:mm:ss'格式!");
+            return tableDataInfo;
+        }
+
+        // 01:呼入, 02:AI外呼, 03:人工外呼
+        if ("01".equals(callType)) {
+            return getInboundRecords(queryParams);
+        } else if ("02".equals(callType)) {
+            return getAiCallRecordsTable(queryParams);
+        } else if ("03".equals(callType)) {
+            return getOutboundRecordsTable(queryParams);
+        } else {
+            tableDataInfo = new TableDataInfo();
+            tableDataInfo.setTotal(0);
+            tableDataInfo.setCode(AjaxResult.Type.INVALID_PARAM.value());
+            tableDataInfo.setMsg("callType参数不合法,呼入请输入01,AI外呼请输入02,手工外呼请输入03!");
+            return tableDataInfo;
+        }
+    }
+    //ai外呼记录查询
+    private TableDataInfo getAiCallRecordsTable(ApiCallRecordQueryParams queryParams) {
+        Map<String, Object> params = new HashMap<>();
+        if (null != queryParams.getTimeLenStart()) {
+            params.put("timeLenStart", queryParams.getTimeLenStart());
+        }
+        if (null != queryParams.getTimeLenEnd()) {
+            params.put("timeLenEnd", queryParams.getTimeLenEnd());
+        }
+        if (null != queryParams.getCalloutTimeStart()) {
+            params.put("calloutTimeStart", queryParams.getCalloutTimeStart());
+        }
+        if (null != queryParams.getCalloutTimeEnd()) {
+            params.put("calloutTimeEnd", queryParams.getCalloutTimeEnd());
+        }
+        if (null != queryParams.getAnsweredTimeStart()) {
+            params.put("answeredTimeStart", queryParams.getAnsweredTimeStart());
+        }
+        if (null != queryParams.getAnsweredTimeEnd()) {
+            params.put("answeredTimeEnd", queryParams.getAnsweredTimeEnd());
+        }
+        if (null != queryParams.getCallEndTimeStart()) {
+            params.put("callEndTimeStart", queryParams.getCallEndTimeStart());
+        }
+        if (null != queryParams.getCallEndTimeEnd()) {
+            params.put("callEndTimeEnd", queryParams.getCallEndTimeEnd());
+        }
+        CcCallPhone ccCallPhone = new CcCallPhone();
+        if (null != queryParams.getBatchId() && queryParams.getBatchId() > 0) {
+            ccCallPhone.setBatchId(queryParams.getBatchId());
+        }
+        ccCallPhone.setUuid(queryParams.getUuid());
+        ccCallPhone.setTelephone(queryParams.getTelephone());
+        ccCallPhone.setAcdOpnum(queryParams.getExtnum());
+        ccCallPhone.setCallstatus(queryParams.getCallstatus());
+        ccCallPhone.setCallerNumber(queryParams.getCallerNumber());
+        ccCallPhone.setParams(params);
+        startPage(queryParams.getPageNum(), queryParams.getPageSize());
+        List<CcCallPhone> list = ccCallPhoneService.selectCcCallPhoneYlrzList(ccCallPhone);
+        list.forEach(callPhoneRecord -> {
+            if(StringUtils.isNotBlank(callPhoneRecord.getWavfile())){
+                if (callPhoneRecord.getWavfile().startsWith("/")) {
+                    callPhoneRecord.setWavfile("/recordings/files?filename=" + callPhoneRecord.getWavfile().substring(1));
+                }else{
+                    callPhoneRecord.setWavfile("/recordings/files?filename=" + callPhoneRecord.getWavfile());
+                }
+            }
+            callPhoneRecord.setCallstatusName( CcCallPhone.getCallStatusName(callPhoneRecord.getCallstatus()));
+            callPhoneRecord.setCalloutTimeStr(DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", new Date(callPhoneRecord.getCalloutTime())));
+            callPhoneRecord.setAnsweredTimeStr(DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", new Date(callPhoneRecord.getAnsweredTime())));
+            callPhoneRecord.setCallEndTimeStr(DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", new Date(callPhoneRecord.getCallEndTime())));
+            callPhoneRecord.setTimeLenSec(DateUtils.formatTimeLength(callPhoneRecord.getTimeLen()/1000));
+        });
+        return getDataTable(list);
+    }
+    //人工外呼记录查询
+    private TableDataInfo getOutboundRecordsTable(ApiCallRecordQueryParams queryParams) {
+        Map<String, Object> params = new HashMap<>();
+        if (null != queryParams.getTimeLenStart()) {
+            params.put("timeLenStart", queryParams.getTimeLenStart());
+        }
+        if (null != queryParams.getTimeLenEnd()) {
+            params.put("timeLenEnd", queryParams.getTimeLenEnd());
+        }
+        if (null != queryParams.getCalloutTimeStart()) {
+            params.put("calloutTimeStart", queryParams.getCalloutTimeStart());
+        }
+        if (null != queryParams.getCalloutTimeEnd()) {
+            params.put("calloutTimeEnd", queryParams.getCalloutTimeEnd());
+        }
+        if (null != queryParams.getAnsweredTimeStart()) {
+            params.put("answeredTimeStart", queryParams.getAnsweredTimeStart());
+        }
+        if (null != queryParams.getAnsweredTimeEnd()) {
+            params.put("answeredTimeEnd", queryParams.getAnsweredTimeEnd());
+        }
+        if (null != queryParams.getEndTimeStart()) {
+            params.put("endTimeStart", queryParams.getEndTimeStart());
+        }
+        if (null != queryParams.getEndTimeEnd()) {
+            params.put("endTimeEnd", queryParams.getEndTimeEnd());
+        }
+        CcCallPhone ccCallPhone = new CcCallPhone();
+        if (null != queryParams.getBatchId() && queryParams.getBatchId() > 0) {
+            ccCallPhone.setBatchId(queryParams.getBatchId());
+        }
+
+        CcOutboundCdr outboundCdr = new CcOutboundCdr();
+        outboundCdr.setUuid(queryParams.getUuid());
+        outboundCdr.setCaller(queryParams.getTelephone());
+        outboundCdr.setOpnum(queryParams.getExtnum());
+        outboundCdr.setParams(params);
+        startPage(queryParams.getPageNum(), queryParams.getPageSize());
+        List<CcOutboundCdr> list = outboundCdrService.selectCcOutboundCdrYlrzList(outboundCdr);
+        list.forEach(callPhoneRecord -> {
+            if(StringUtils.isNotBlank(callPhoneRecord.getRecordFilename())){
+                if (callPhoneRecord.getRecordFilename().startsWith("/")) {
+                    callPhoneRecord.setRecordFilename("/recordings/files?filename=" + callPhoneRecord.getRecordFilename().substring(1));
+                }else{
+                    callPhoneRecord.setWavFileUrl("/recordings/files?filename=" + callPhoneRecord.getRecordFilename());
+                }
+                callPhoneRecord.setStartTimeStr(DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", new Date(callPhoneRecord.getStartTime())));
+                callPhoneRecord.setAnsweredTimeStr(DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", new Date(callPhoneRecord.getAnsweredTime())));
+                callPhoneRecord.setEndTimeStr(DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", new Date(callPhoneRecord.getEndTime())));
+                callPhoneRecord.setTimeLenSec(DateUtils.formatTimeLength(callPhoneRecord.getTimeLen()/1000));
+                callPhoneRecord.setTimeLenValidStr(DateUtils.formatTimeLength(callPhoneRecord.getTimeLenValid()/1000));
+            }
+
+        });
+        return getDataTable(list);
+    }
+
+    /**
+     * 获取外呼网关列表接口
+     * purposes 1手动外呼电话条,2AI外呼,3不限制
+     * @param queryParams 网关参数
+     * @param req
+     */
+    @PostMapping("/gateway/myList")
+    @ResponseBody
+    public TableDataInfo getGatewayMyList(@RequestBody CcGateways queryParams, HttpServletRequest req){
+        // 校验请求方ip是否合法
+        if (!ClientIpCheck.checkIp(req)) {
+            TableDataInfo tableDataInfo;
+            tableDataInfo = new TableDataInfo();
+            tableDataInfo.setTotal(0);
+            tableDataInfo.setCode(AjaxResult.Type.NO_AUTH.value());
+            tableDataInfo.setMsg("未授权,请联系系统管理员添加ip白名单!");
+            return tableDataInfo;
+        }
+        startPage(queryParams.getPageNum(), queryParams.getPageSize());
+        return getDataTable(ccGatewaysService.selectCcGatewaysList(queryParams));
+    }
+    /**
+     * 根据通话id集合查询uuid不为空的自动外呼数据
+     */
+    @PostMapping( "/getCcCallPhoneByIds")
+    @ResponseBody
+    public AjaxResult getCcCallPhoneByIds(@RequestBody List<String> callPhoneIds)
+    {
+        if(callPhoneIds==null){
+            return AjaxResult.error(AjaxResult.Type.INVALID_PARAM, "callPhoneIds不能为空!", "");
+        }
+        return AjaxResult.success(ccCallPhoneService.selectCcCallPhoneListByIds(callPhoneIds));
+    }
+
+    /**
+     * 修改任务
+     * @param ccCallTask
+     * @return
+     */
+    @PostMapping("/editTask")
+    @ResponseBody
+    public AjaxResult editTask(@RequestBody CcCallTask ccCallTask)
+    {
+
+        if ("acd".equals(ccCallTask.getAiTransferType())) {
+            ccCallTask.setAiTransferData(ccCallTask.getAiTransferGroupId());
+        } else if ("extension".equals(ccCallTask.getAiTransferType())) {
+            ccCallTask.setAiTransferData(ccCallTask.getAiTransferExtNumber());
+        } else if ("gateway".equals(ccCallTask.getAiTransferType())) {
+            JSONObject aiTransferData = new JSONObject();
+            aiTransferData.put("gatewayId", ccCallTask.getAiTransferGatewayId());
+            aiTransferData.put("destNumber", ccCallTask.getAiTransferGatewayDestNumber());
+            ccCallTask.setAiTransferData(JSONObject.toJSONString(aiTransferData));
+        }
+        return toAjax(ccCallTaskService.updateCcCallTask(ccCallTask));
+    }
+
 }

+ 55 - 1
ruoyi-admin/src/main/java/com/ruoyi/aicall/domain/CcCallPhone.java

@@ -171,5 +171,59 @@ public class CcCallPhone implements Serializable {
     /** The duration of the manual agent service time. */
     private String manualAnsweredTimeLen;
 
-
+    private String callstatusName;
+    private String calloutTimeStr;
+    private String answeredTimeStr;
+    private String callEndTimeStr;
+    private String timeLenSec;
+
+    /**
+     * 根据呼叫状态码获取状态名称
+     * @param status 状态码
+     * @return 状态名称
+     */
+    public static String getCallStatusName(Integer status) {
+        if (status == null) {
+            return "未知";
+        }
+        switch (status) {
+            case 0:
+                return "未拨打";
+            case 1:
+                return "已进入呼叫队列";
+            case 2:
+                return "正在拨号";
+            case 3:
+            case 30:
+                return "未接通";
+            case 4:
+                return "已接通";
+            case 5:
+                return "通话中断";
+            case 6:
+                return "成功转人工或 AI";
+            case 7:
+                return "线路故障";
+            case 31:
+                return "客户正在通话中";
+            case 32:
+                return "关机";
+            case 33:
+                return "空号";
+            case 34:
+                return "无人接听";
+            case 35:
+                return "停机";
+            case 36:
+                return "网络忙";
+            case 37:
+                return "语音助手";
+            case 38:
+                return "暂时无法接通";
+            case 39:
+                return "呼叫限制";
+            default:
+                return "未知状态";
+        }
+    }
 }

+ 4 - 0
ruoyi-admin/src/main/java/com/ruoyi/aicall/mapper/CcCallPhoneMapper.java

@@ -89,4 +89,8 @@ public interface CcCallPhoneMapper
     void bakCallPhoneByBatchId(Long batchId);
 
     void delCallPhoneByBatchId(Long batchId);
+
+    List<CcCallPhone> selectCcCallPhoneYlrzList(CcCallPhone ccCallPhone);
+
+    List<CcCallPhone> selectCcCallPhoneListByIds(List<String> callPhoneIds);
 }

+ 10 - 0
ruoyi-admin/src/main/java/com/ruoyi/aicall/model/ApiCallRecordQueryParams.java

@@ -47,4 +47,14 @@ public class ApiCallRecordQueryParams implements Serializable {
     /** 主叫号码 */
     private String callerNumber;
 
+
+    /** 接听时间起止 */
+    private String answeredTimeStart;
+    private String answeredTimeEnd;
+    /** 自动外呼挂机时间起止 */
+    private String callEndTimeStart;
+    private String callEndTimeEnd;
+    /** 手动外呼挂机时间起止 */
+    private String endTimeStart;
+    private String endTimeEnd;
 }

+ 4 - 0
ruoyi-admin/src/main/java/com/ruoyi/aicall/service/ICcCallPhoneService.java

@@ -87,4 +87,8 @@ public interface ICcCallPhoneService
     void bakCallPhoneByBatchId(Long batchId);
 
     void delCallPhoneByBatchId(Long batchId);
+
+    List<CcCallPhone> selectCcCallPhoneYlrzList(CcCallPhone ccCallPhone);
+
+    List<CcCallPhone> selectCcCallPhoneListByIds(List<String> callPhoneIds);
 }

+ 53 - 0
ruoyi-admin/src/main/java/com/ruoyi/aicall/service/impl/CcCallPhoneServiceImpl.java

@@ -1,5 +1,6 @@
 package com.ruoyi.aicall.service.impl;
 
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -224,4 +225,56 @@ public class CcCallPhoneServiceImpl implements ICcCallPhoneService
     public void delCallPhoneByBatchId(Long batchId) {
         ccCallPhoneMapper.delCallPhoneByBatchId(batchId);
     }
+    /**
+     * 查询外呼号码列表
+     *
+     * @param ccCallPhone 外呼号码
+     * @return 外呼号码
+     */
+    @Override
+    public List<CcCallPhone> selectCcCallPhoneYlrzList(CcCallPhone ccCallPhone)
+    {
+        Map<String, Object> params = ccCallPhone.getParams();
+        if (null == params) {
+            params = new HashMap<>();
+        }
+        if (null != params.get("timeLenStart")
+                && !"".equals(params.get("timeLenStart"))) {
+            params.put("timeLenStart", Double.valueOf((String)params.get("timeLenStart")) * 60 * 1000L);
+        }
+        if (null != params.get("timeLenEnd")
+                && !"".equals(params.get("timeLenEnd"))) {
+            params.put("timeLenEnd", Double.valueOf((String)params.get("timeLenEnd")) * 60 * 1000L);
+        }
+        if (null != params.get("calloutTimeStart")
+                && !"".equals(params.get("calloutTimeStart"))) {
+            params.put("calloutTimeStart", DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", (String)params.get("calloutTimeStart")).getTime());
+        }
+        if (null != params.get("calloutTimeEnd")
+                && !"".equals(params.get("calloutTimeEnd"))) {
+            params.put("calloutTimeEnd", DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", (String)params.get("calloutTimeEnd")).getTime());
+        }
+        if (null != params.get("answeredTimeStart")
+                && !"".equals(params.get("answeredTimeStart"))) {
+            params.put("answeredTimeStart", DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", (String)params.get("answeredTimeStart")).getTime());
+        }
+        if (null != params.get("answeredTimeEnd")
+                && !"".equals(params.get("answeredTimeEnd"))) {
+            params.put("answeredTimeEnd", DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", (String)params.get("answeredTimeEnd")).getTime());
+        }
+        if (null != params.get("callEndTimeStart")
+                && !"".equals(params.get("callEndTimeStart"))) {
+            params.put("callEndTimeStart", DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", (String)params.get("callEndTimeStart")).getTime());
+        }
+        if (null != params.get("callEndTimeEnd")
+                && !"".equals(params.get("callEndTimeEnd"))) {
+            params.put("callEndTimeEnd", DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", (String)params.get("callEndTimeEnd")).getTime());
+        }
+        ccCallPhone.setParams(params);
+        return ccCallPhoneMapper.selectCcCallPhoneYlrzList(ccCallPhone);
+    }
+    @Override
+    public List<CcCallPhone> selectCcCallPhoneListByIds(List<String> callPhoneIds) {
+        return ccCallPhoneMapper.selectCcCallPhoneListByIds(callPhoneIds);
+    }
 }

+ 4 - 1
ruoyi-admin/src/main/java/com/ruoyi/cc/domain/CcCustInfo.java

@@ -80,5 +80,8 @@ public class CcCustInfo implements Serializable {
 
     // 详情带的参数
     private List<CcCustCallRecord> callRecordList;
-
+    //登陆账号
+    private String opNum;
+    //用户名称
+    private String userName;
 }

+ 5 - 0
ruoyi-admin/src/main/java/com/ruoyi/cc/domain/CcGateways.java

@@ -11,6 +11,7 @@ import com.ruoyi.common.core.domain.BaseEntity;
 import java.io.Serializable;
 import java.util.Date;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -79,5 +80,9 @@ public class CcGateways implements Serializable {
     @JsonInclude(JsonInclude.Include.NON_EMPTY)
     private Map<String, Object> params = new HashMap<>();
 
+    private Integer pageSize;
 
+    private Integer pageNum;
+
+    private List<Long> gatewayIds;
 }

+ 5 - 0
ruoyi-admin/src/main/java/com/ruoyi/cc/domain/CcOutboundCdr.java

@@ -71,4 +71,9 @@ public class CcOutboundCdr implements Serializable {
     @JsonInclude(JsonInclude.Include.NON_EMPTY)
     private Map<String, Object> params;
 
+    private String startTimeStr;
+    private String answeredTimeStr;
+    private String endTimeStr;
+    private String timeLenSec;
+    private String timeLenValidStr;
 }

+ 4 - 0
ruoyi-admin/src/main/java/com/ruoyi/cc/mapper/CcExtNumMapper.java

@@ -64,4 +64,8 @@ public interface CcExtNumMapper
      * @return
      */
     List<CcExtNum> selectUnBindCcExtNumList();
+
+    int cleanCcExtNumByUserCode(String loginName);
+
+    int updateCcExtNumByUserCode(CcExtNum extNum);
 }

+ 4 - 0
ruoyi-admin/src/main/java/com/ruoyi/cc/service/ICcExtNumService.java

@@ -89,4 +89,8 @@ public interface ICcExtNumService
      * @return
      */
     List<CcExtNum> selectUnBindCcExtNumList();
+
+    int cleanCcExtNumByUserCode(String loginName);
+
+    int updateCcExtNumByUserCode(CcExtNum extNum);
 }

+ 2 - 0
ruoyi-admin/src/main/java/com/ruoyi/cc/service/ICcOutboundCdrService.java

@@ -58,4 +58,6 @@ public interface ICcOutboundCdrService
      * @return 结果
      */
     public int deleteCcOutboundCdrById(String id);
+
+    List<CcOutboundCdr> selectCcOutboundCdrYlrzList(CcOutboundCdr outboundCdr);
 }

+ 8 - 0
ruoyi-admin/src/main/java/com/ruoyi/cc/service/impl/CcExtNumServiceImpl.java

@@ -162,4 +162,12 @@ public class CcExtNumServiceImpl implements ICcExtNumService
     public List<CcExtNum> selectUnBindCcExtNumList() {
         return ccExtNumMapper.selectUnBindCcExtNumList();
     }
+    @Override
+    public int cleanCcExtNumByUserCode(String loginName) {
+        return ccExtNumMapper.cleanCcExtNumByUserCode(loginName);
+    }
+    @Override
+    public int updateCcExtNumByUserCode(CcExtNum extNum) {
+        return ccExtNumMapper.updateCcExtNumByUserCode(extNum);
+    }
 }

+ 48 - 0
ruoyi-admin/src/main/java/com/ruoyi/cc/service/impl/CcOutboundCdrServiceImpl.java

@@ -142,4 +142,52 @@ public class CcOutboundCdrServiceImpl implements ICcOutboundCdrService
     {
         return ccOutboundCdrMapper.deleteCcOutboundCdrById(id);
     }
+    /**
+     * 查询外呼记录列表
+     *
+     * @param ccOutboundCdr 外呼记录
+     * @return 外呼记录
+     */
+    @Override
+    public List<CcOutboundCdr> selectCcOutboundCdrYlrzList(CcOutboundCdr ccOutboundCdr)
+    {
+        Map<String, Object> params = ccOutboundCdr.getParams();
+        if (null == params) {
+            params = new HashMap<>();
+        }
+        if (null != params.get("timeLenStart")
+                && !"".equals(params.get("timeLenStart"))) {
+            params.put("timeLenStart", Double.valueOf((String)params.get("timeLenStart")) * 60 * 1000L);
+        }
+        if (null != params.get("timeLenEnd")
+                && !"".equals(params.get("timeLenEnd"))) {
+            params.put("timeLenEnd", Double.valueOf((String)params.get("timeLenEnd")) * 60 * 1000L);
+        }
+        if (null != params.get("calloutTimeStart")
+                && !"".equals(params.get("calloutTimeStart"))) {
+            params.put("calloutTimeStart", DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", (String)params.get("calloutTimeStart")).getTime());
+        }
+        if (null != params.get("calloutTimeEnd")
+                && !"".equals(params.get("calloutTimeEnd"))) {
+            params.put("calloutTimeEnd", DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", (String)params.get("calloutTimeEnd")).getTime());
+        }
+        if (null != params.get("answeredTimeStart")
+                && !"".equals(params.get("answeredTimeStart"))) {
+            params.put("answeredTimeStart", DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", (String)params.get("answeredTimeStart")).getTime());
+        }
+        if (null != params.get("answeredTimeEnd")
+                && !"".equals(params.get("answeredTimeEnd"))) {
+            params.put("answeredTimeEnd", DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", (String)params.get("answeredTimeEnd")).getTime());
+        }
+        if (null != params.get("endTimeStart")
+                && !"".equals(params.get("endTimeStart"))) {
+            params.put("endTimeStart", DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", (String)params.get("endTimeStart")).getTime());
+        }
+        if (null != params.get("endTimeEnd")
+                && !"".equals(params.get("endTimeEnd"))) {
+            params.put("endTimeEnd", DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", (String)params.get("endTimeEnd")).getTime());
+        }
+        ccOutboundCdr.setParams(params);
+        return ccOutboundCdrMapper.selectCcOutboundCdrList(ccOutboundCdr);
+    }
 }

+ 63 - 0
ruoyi-admin/src/main/resources/mapper/aicall/CcCallPhoneMapper.xml

@@ -282,4 +282,67 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     <delete id="delCallPhoneByBatchId" parameterType="Long">
         delete from cc_call_phone where batch_id = #{batchId}
     </delete>
+
+
+    <select id="selectCcCallPhoneYlrzList" parameterType="CcCallPhone" resultMap="CcCallPhoneResult">
+        select ccp.*, cct.batch_name as batchName from cc_call_phone ccp left join cc_call_task cct on cct.batch_id = ccp.batch_id
+        <where>
+            <if test="uuid != null and uuid != '' "> and ccp.uuid = #{uuid}</if>
+            <if test="batchId != null "> and ccp.batch_id = #{batchId}</if>
+            <if test="telephone != null  and telephone != ''"> and ccp.telephone = #{telephone}</if>
+            <if test="custName != null  and custName != ''"> and ccp.cust_name = #{custName}</if>
+            <if test="callstatus != null "> and ccp.callstatus = #{callstatus}</if>
+            <if test="params.calloutTimeStart != null and params.calloutTimeStart != ''"><!-- 开始时间检索 -->
+                AND ccp.callout_time &gt;= #{params.calloutTimeStart}
+            </if>
+            <if test="params.calloutTimeEnd != null and params.calloutTimeEnd != ''"><!-- 结束时间检索 -->
+                AND ccp.callout_time &lt;= #{params.calloutTimeEnd}
+            </if>
+            <if test="params.callEndTimeStart != null and params.callEndTimeStart != ''"><!-- 开始时间检索 -->
+                AND ccp.call_end_time &gt;= #{params.callEndTimeStart}
+            </if>
+            <if test="params.callEndTimeEnd != null and params.callEndTimeEnd != ''"><!-- 结束时间检索 -->
+                AND ccp.call_end_time &lt;= #{params.callEndTimeEnd}
+            </if>
+            <if test="params.timeLenStart != null and params.timeLenStart != ''"><!-- 开始时间检索 -->
+                AND ccp.time_len &gt;= #{params.timeLenStart}
+            </if>
+            <if test="params.timeLenEnd != null and params.timeLenEnd != ''"><!-- 结束时间检索 -->
+                AND ccp.time_len &lt;= #{params.timeLenEnd}
+            </if>
+            <if test="params.connectedTimeStart != null and params.connectedTimeStart != ''"><!-- 开始时间检索 -->
+                AND ccp.connected_time &gt;= #{params.connectedTimeStart}
+            </if>
+            <if test="params.connectedTimeEnd != null and params.connectedTimeEnd != ''"><!-- 结束时间检索 -->
+                AND ccp.connected_time &lt;= #{connectedTimeEnd}
+            </if>
+            <if test="params.answeredTimeStart != null and params.answeredTimeStart != ''"><!-- 开始时间检索 -->
+                AND ccp.answered_time &gt;= #{params.answeredTimeStart}
+            </if>
+            <if test="params.answeredTimeEnd != null and params.answeredTimeEnd != ''"><!-- 结束时间检索 -->
+                AND ccp.answered_time &lt;= #{params.answeredTimeEnd}
+            </if>
+            <if test="batchId != null and batchId != ''">
+                AND ccp.batch_id = #{batchId}
+            </if>
+            <if test="intent != null and intent != ''">
+                AND ccp.intent = #{intent}
+            </if>
+            <if test="billingStatus != null ">
+                and ccp.billing_status = #{billingStatus}
+            </if>
+            <if test="callerNumber != null and callerNumber != '' ">
+                and ccp.caller_number = #{callerNumber}
+            </if>
+            AND ccp.callstatus >= 3 AND ccp.call_end_time > 0
+        </where>
+        order by ccp.call_end_time desc
+    </select>
+    <select id="selectCcCallPhoneListByIds" parameterType="java.util.List" resultMap="CcCallPhoneResult">
+        <include refid="selectCcCallPhoneVo"/>
+        where uuid is not null and id in
+        <foreach item="id" collection="list" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </select>
 </mapper>

+ 6 - 1
ruoyi-admin/src/main/resources/mapper/cc/CcExtNumMapper.xml

@@ -68,5 +68,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <include refid="selectCcExtNumVo"/>
         where user_code = ''
     </select>
-
+    <update id="cleanCcExtNumByUserCode" parameterType="String">
+        update cc_ext_num set user_code = '' where user_code = #{userCode}
+    </update>
+    <update id="updateCcExtNumByUserCode" parameterType="CcExtNum">
+        update cc_ext_num set user_code = #{userCode} where ext_num = #{extNum}
+    </update>
 </mapper>