diff --git a/contact-center/app/src/main/java/com/chatopera/cc/util/exception/CSKefuRestException.java b/contact-center/app/src/main/java/com/chatopera/cc/util/exception/CSKefuRestException.java new file mode 100644 index 00000000..74070664 --- /dev/null +++ b/contact-center/app/src/main/java/com/chatopera/cc/util/exception/CSKefuRestException.java @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2018 Chatopera Inc, + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.chatopera.cc.util.exception; + +public class CSKefuRestException extends Exception { + public CSKefuRestException(String msg){ + super(msg); + } +} diff --git a/contact-center/app/src/main/java/com/chatopera/cc/util/json/GsonTools.java b/contact-center/app/src/main/java/com/chatopera/cc/util/json/GsonTools.java new file mode 100644 index 00000000..d7a62e36 --- /dev/null +++ b/contact-center/app/src/main/java/com/chatopera/cc/util/json/GsonTools.java @@ -0,0 +1,94 @@ +package com.chatopera.cc.util.json; +/* + * Copyright (C) 2018 Chatopera Inc, + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +import java.util.Map; + +public class GsonTools { + + public static enum ConflictStrategy { + + THROW_EXCEPTION, PREFER_FIRST_OBJ, PREFER_SECOND_OBJ, PREFER_NON_NULL; + } + + public static class JsonObjectExtensionConflictException extends Exception { + + public JsonObjectExtensionConflictException(String message) { + super(message); + } + + } + + public static void extendJsonObject(JsonObject destinationObject, ConflictStrategy conflictResolutionStrategy, JsonObject... objs) + throws JsonObjectExtensionConflictException { + for (JsonObject obj : objs) { + extendJsonObject(destinationObject, obj, conflictResolutionStrategy); + } + } + + private static void extendJsonObject(JsonObject leftObj, JsonObject rightObj, ConflictStrategy conflictStrategy) + throws JsonObjectExtensionConflictException { + for (Map.Entry rightEntry : rightObj.entrySet()) { + String rightKey = rightEntry.getKey(); + JsonElement rightVal = rightEntry.getValue(); + if (leftObj.has(rightKey)) { + //conflict + JsonElement leftVal = leftObj.get(rightKey); + if (leftVal.isJsonArray() && rightVal.isJsonArray()) { + JsonArray leftArr = leftVal.getAsJsonArray(); + JsonArray rightArr = rightVal.getAsJsonArray(); + //concat the arrays -- there cannot be a conflict in an array, it's just a collection of stuff + for (int i = 0; i < rightArr.size(); i++) { + leftArr.add(rightArr.get(i)); + } + } else if (leftVal.isJsonObject() && rightVal.isJsonObject()) { + //recursive merging + extendJsonObject(leftVal.getAsJsonObject(), rightVal.getAsJsonObject(), conflictStrategy); + } else {//not both arrays or objects, normal merge with conflict resolution + handleMergeConflict(rightKey, leftObj, leftVal, rightVal, conflictStrategy); + } + } else {//no conflict, add to the object + leftObj.add(rightKey, rightVal); + } + } + } + + private static void handleMergeConflict(String key, JsonObject leftObj, JsonElement leftVal, JsonElement rightVal, ConflictStrategy conflictStrategy) + throws JsonObjectExtensionConflictException { + { + switch (conflictStrategy) { + case PREFER_FIRST_OBJ: + break;//do nothing, the right val gets thrown out + case PREFER_SECOND_OBJ: + leftObj.add(key, rightVal);//right side auto-wins, replace left val with its val + break; + case PREFER_NON_NULL: + //check if right side is not null, and left side is null, in which case we use the right val + if (leftVal.isJsonNull() && !rightVal.isJsonNull()) { + leftObj.add(key, rightVal); + }//else do nothing since either the left value is non-null or the right value is null + break; + case THROW_EXCEPTION: + throw new JsonObjectExtensionConflictException("Key " + key + " exists in both objects and the conflict resolution strategy is " + conflictStrategy); + default: + throw new UnsupportedOperationException("The conflict strategy " + conflictStrategy + " is unknown and cannot be processed"); + } + } + } +} \ No newline at end of file diff --git a/contact-center/app/src/main/java/com/chatopera/cc/webim/service/es/ContactNotesRepository.java b/contact-center/app/src/main/java/com/chatopera/cc/webim/service/es/ContactNotesRepository.java index d01c86fe..19cb4804 100644 --- a/contact-center/app/src/main/java/com/chatopera/cc/webim/service/es/ContactNotesRepository.java +++ b/contact-center/app/src/main/java/com/chatopera/cc/webim/service/es/ContactNotesRepository.java @@ -17,8 +17,10 @@ package com.chatopera.cc.webim.service.es; import com.chatopera.cc.webim.web.model.ContactNotes; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; public interface ContactNotesRepository extends ElasticsearchRepository { - + public Page findByContactidAndOrgiOrderByCreatetimeDesc(String contactid, String q, Pageable page); } diff --git a/contact-center/app/src/main/java/com/chatopera/cc/webim/web/handler/api/rest/ApiContactNotesController.java b/contact-center/app/src/main/java/com/chatopera/cc/webim/web/handler/api/rest/ApiContactNotesController.java index 1f833aa0..4761b153 100644 --- a/contact-center/app/src/main/java/com/chatopera/cc/webim/web/handler/api/rest/ApiContactNotesController.java +++ b/contact-center/app/src/main/java/com/chatopera/cc/webim/web/handler/api/rest/ApiContactNotesController.java @@ -15,22 +15,305 @@ */ package com.chatopera.cc.webim.web.handler.api.rest; +import com.chatopera.cc.core.UKDataContext; +import com.chatopera.cc.util.Constants; +import com.chatopera.cc.util.Menu; +import com.chatopera.cc.util.exception.CSKefuRestException; +import com.chatopera.cc.util.json.GsonTools; import com.chatopera.cc.webim.service.es.ContactNotesRepository; +import com.chatopera.cc.webim.service.es.ContactsRepository; +import com.chatopera.cc.webim.service.repository.OrganRepository; +import com.chatopera.cc.webim.service.repository.UserRepository; import com.chatopera.cc.webim.web.handler.Handler; +import com.chatopera.cc.webim.web.handler.api.request.RestUtils; +import com.chatopera.cc.webim.web.model.ContactNotes; +import com.chatopera.cc.webim.web.model.Contacts; +import com.chatopera.cc.webim.web.model.Organ; +import com.chatopera.cc.webim.web.model.User; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; +import javax.servlet.http.HttpServletRequest; +import java.util.Date; + /** * 联系人笔记 */ @RestController -@RequestMapping("/api/contactnotes") +@RequestMapping("/api/contacts/notes") @Api(value = "联系人笔记", description = "管理联系人笔记") public class ApiContactNotesController extends Handler { + private final static Logger logger = LoggerFactory.getLogger(ApiContactNotesController.class); @Autowired private ContactNotesRepository contactNotesRes; + + @Autowired + private ContactsRepository contactsRes; + + + @Autowired + private UserRepository userRes; + + + @Autowired + private OrganRepository organRes; + + + /** + * 获取创建人 + * + * @param creater + * @return + */ + private JsonObject creater(final String creater) { + JsonObject data = new JsonObject(); + // 增加创建人 + User u = userRes.findById(creater); + if (u != null) { + data.addProperty("creater", u.getId()); + data.addProperty("creatername", u.getUname()); + // 获取创建者部门 + if (u.getOrgan() != null) { + Organ o = organRes.findOne(u.getOrgan()); + if (o != null) { + data.addProperty("createrorgan", o.getName()); + data.addProperty("createrorganid", o.getId()); + } + } + } else { + logger.warn("[contact notes] detail [{}] 无法得到创建者。", creater); + } + return data; + } + + /** + * 获取笔记详情 + * + * @param j + * @return + */ + private JsonObject detail(final JsonObject j) throws GsonTools.JsonObjectExtensionConflictException { + logger.info("[contact note] detail {}] {}", j.toString()); + JsonObject resp = new JsonObject(); + // TODO 增加权限检查 + if (j.has("id") && StringUtils.isNotBlank(j.get("id").getAsString())) { + ContactNotes cn = contactNotesRes.findOne(j.get("id").getAsString()); + if (cn != null) { + JsonObject data = new JsonObject(); + data.addProperty("contactid", cn.getContactid()); + data.addProperty("category", cn.getCategory()); + data.addProperty("createtime", Constants.DISPLAY_DATE_FORMATTER.format(cn.getCreatetime())); + data.addProperty("updatetime", Constants.DISPLAY_DATE_FORMATTER.format(cn.getUpdatetime())); + data.addProperty("content", cn.getContent()); + data.addProperty("agentuser", cn.getAgentuser()); + data.addProperty("onlineuser", cn.getOnlineuser()); + GsonTools.extendJsonObject(data, GsonTools.ConflictStrategy.PREFER_FIRST_OBJ, creater(cn.getCreater())); + resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_SUCC); + resp.add(RestUtils.RESP_KEY_DATA, data); + } else { + resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_2); + resp.addProperty(RestUtils.RESP_KEY_ERROR, "不存在该联系人笔记。"); + } + } + return resp; + } + + /** + * 创建联系人笔记 + * + * @param payload + * @return + */ + private JsonObject create(final JsonObject payload) { + logger.info("[contact note] create {}", payload.toString()); + JsonObject resp = new JsonObject(); + // validate parameters + String invalid = validateCreatePayload(payload); + if (invalid != null) { + resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_2); + resp.addProperty(RestUtils.RESP_KEY_ERROR, invalid); + return resp; + } + + ContactNotes cn = new ContactNotes(); + cn.setCategory(payload.get("category").getAsString()); + cn.setContent(payload.get("content").getAsString()); + cn.setCreater(payload.get("creater").getAsString()); + cn.setOrgi(payload.get("orgi").getAsString()); + cn.setContactid(payload.get("contactid").getAsString()); + cn.setDatastatus(false); + + Date dt = new Date(); + cn.setCreatetime(dt); + cn.setUpdatetime(dt); + + if (payload.has("agentuser")) { + cn.setAgentuser(payload.get("agentuser").getAsString()); + } + + if (payload.has("onlineuser")) { + cn.setOnlineuser(payload.get("onlineuser").getAsString()); + } + + contactNotesRes.save(cn); + resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_SUCC); + JsonObject data = new JsonObject(); + data.addProperty("id", cn.getId()); + data.addProperty("updatetime", Constants.DISPLAY_DATE_FORMATTER.format(dt)); + resp.add("data", data); + return resp; + } + + /** + * 验证创建数据 + * + * @param payload + * @return + */ + private String validateCreatePayload(JsonObject payload) { + if (!payload.has("category")) { + return "参数传递不合法,没有[category]。"; + } + + if ((!payload.has("content")) || StringUtils.isBlank(payload.get("content").getAsString())) { + return "参数传递不合法,没有[content]。"; + } + + if ((!payload.has("contactid")) || StringUtils.isBlank(payload.get("contactid").getAsString())) { + return "参数传递不合法,没有[contactid]。"; + } else { + Contacts c = contactsRes.findOne(payload.get("contactid").getAsString()); + if (c == null) + return "参数不合法,不存在该联系人。"; + } + + return null; + } + + /** + * Build query string + * + * @param j + * @return + */ + private String querybuilder(final JsonObject j) { + StringBuffer sb = new StringBuffer(); + if (j.has("orgi")) { + sb.append("orgi:"); + sb.append(j.get("orgi").getAsString()); + sb.append(" "); + } + + return sb.toString(); + } + + /** + * 根据联系人ID获取联系人笔记列表 + * + * @param j + * @param request + * @return + */ + private JsonObject fetch(final JsonObject j, final HttpServletRequest request) throws GsonTools.JsonObjectExtensionConflictException { + logger.info("[contact note] fetch [{}]", j.toString()); + JsonObject resp = new JsonObject(); + if ((!j.has("contactid")) || StringUtils.isBlank(j.get("contactid").getAsString())) { + resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_2); + resp.addProperty(RestUtils.RESP_KEY_ERROR, "参数传递不合法,没有[contactid]。"); + return resp; + } + final String cid = j.get("contactid").getAsString(); + Contacts c = contactsRes.findOne(cid); + + if (c == null) { + resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_4); + resp.addProperty(RestUtils.RESP_KEY_ERROR, "不存在该联系人。"); + return resp; + } + + String q = querybuilder(j); + + Page cns = contactNotesRes.findByContactidAndOrgiOrderByCreatetimeDesc(cid, + q, new PageRequest(super.getP(request), super.getPs(request))); + + resp.addProperty("size", cns.getSize()); + resp.addProperty("number", cns.getNumber()); + resp.addProperty("totalPage", cns.getTotalPages()); + resp.addProperty("totalElements", cns.getTotalElements()); + + // 转化 page 为 json + JsonArray data = new JsonArray(); + for (ContactNotes cn : cns) { + if (cn != null) { + JsonObject x = new JsonObject(); + x.addProperty("contactid", cn.getContactid()); + x.addProperty("category", cn.getCategory()); + x.addProperty("createtime", Constants.DISPLAY_DATE_FORMATTER.format(cn.getCreatetime())); + x.addProperty("updatetime", Constants.DISPLAY_DATE_FORMATTER.format(cn.getUpdatetime())); + x.addProperty("content", cn.getContent()); + x.addProperty("agentuser", cn.getAgentuser()); + x.addProperty("onlineuser", cn.getOnlineuser()); + GsonTools.extendJsonObject(x, GsonTools.ConflictStrategy.PREFER_FIRST_OBJ, creater(cn.getCreater())); + data.add(x); + } + } + + resp.add("data", data); + return resp; + } + + + @RequestMapping(method = RequestMethod.POST) + @Menu(type = "apps", subtype = "contactnotes", access = true) + @ApiOperation("联系人笔记") + public ResponseEntity operations(HttpServletRequest request, @RequestBody final String body) throws CSKefuRestException, GsonTools.JsonObjectExtensionConflictException { + final JsonObject j = (new JsonParser()).parse(body).getAsJsonObject(); + logger.info("[contact note] operations payload {}", j.toString()); + JsonObject json = new JsonObject(); + HttpHeaders headers = RestUtils.header(); + j.addProperty("creater", super.getUser(request).getId()); + j.addProperty("orgi", UKDataContext.SYSTEM_ORGI); + + if (!j.has("ops")) { + json.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_1); + json.addProperty(RestUtils.RESP_KEY_ERROR, "不合法的请求参数。"); + } else { + switch (StringUtils.lowerCase(j.get("ops").getAsString())) { + case "create": + json = create(j); + break; + case "detail": + json = detail(j); + break; + case "fetch": + json = fetch(j, request); + break; + default: + json.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_3); + json.addProperty(RestUtils.RESP_KEY_ERROR, "不支持的操作。"); + break; + } + } + return new ResponseEntity(json.toString(), headers, HttpStatus.OK); + } + + } diff --git a/contact-center/app/src/main/resources/templates/apps/im/mobile.html b/contact-center/app/src/main/resources/templates/apps/im/mobile.html index 50dfe5c8..b4e1b1ae 100644 --- a/contact-center/app/src/main/resources/templates/apps/im/mobile.html +++ b/contact-center/app/src/main/resources/templates/apps/im/mobile.html @@ -280,7 +280,8 @@ // 参数连接 // 参数连接 var hostname = location.hostname ; - var socket = io.connect('${schema!'http'}://'+hostname+':${port}/im/user?userid=${userid!''}<#if aiid??>&aiid=${aiid}&orgi=${orgi!''}&session=${sessionid!''}&appid=${appid!''}&osname=${(osname!'')?url}&browser=${(browser!'')?url}<#if skill??>&skill=${skill}<#if agent??>&agent=${agent}'); + var protocol = window.location.protocol.replace(/:/g,''); + var socket = io.connect(protocol + '://'+hostname+':${port}/im/user?userid=${userid!''}<#if aiid??>&aiid=${aiid}&orgi=${orgi!''}&session=${sessionid!''}&appid=${appid!''}&osname=${(osname!'')?url}&browser=${(browser!'')?url}<#if skill??>&skill=${skill}<#if agent??>&agent=${agent}'); socket.on('connect',function(){ //service.sendRequestMessage(); //output(''+ new Date().format("yyyy-MM-dd hh:mm:ss") + ' 开始沟通' +'' , 'message callOutConnect-message'); diff --git a/contact-center/config/postman/Chatopera_cc_v1.postman_collection.json b/contact-center/config/postman/Chatopera_cc_v1.postman_collection.json new file mode 100644 index 00000000..84631c88 --- /dev/null +++ b/contact-center/config/postman/Chatopera_cc_v1.postman_collection.json @@ -0,0 +1,552 @@ +{ + "info": { + "_postman_id": "845f31e9-eedd-4168-b2d7-f56e7ff40f58", + "name": "Chatopera_cc_v1", + "description": "Chatopera Contact Center API", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "item": [ + { + "name": "http://{{IP}}:{{PORT}}/tokens", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "http://{{IP}}:{{PORT}}/tokens?username=admin&password=admin1234", + "protocol": "http", + "host": [ + "{{IP}}" + ], + "port": "{{PORT}}", + "path": [ + "tokens" + ], + "query": [ + { + "key": "username", + "value": "admin" + }, + { + "key": "password", + "value": "admin1234" + } + ] + } + }, + "response": [] + }, + { + "name": "http://{{IP}}:{{PORT}}/api/user", + "request": { + "method": "GET", + "header": [ + { + "key": "authorization", + "value": "{{AUTH}}" + } + ], + "body": {}, + "url": { + "raw": "http://{{IP}}:{{PORT}}/api/user", + "protocol": "http", + "host": [ + "{{IP}}" + ], + "port": "{{PORT}}", + "path": [ + "api", + "user" + ] + } + }, + "response": [] + }, + { + "name": "启动呼叫计划", + "request": { + "method": "POST", + "header": [ + { + "key": "authorization", + "value": "4ef6064932a04f7c87d431f1189392d6" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\"ops\": \"execute\", \"dialplanId\": \"402882516556801d016556db24e908de\"}" + }, + "url": { + "raw": "http://{{IP}}:{{PORT}}/api/callout/dialplan", + "protocol": "http", + "host": [ + "{{IP}}" + ], + "port": "{{PORT}}", + "path": [ + "api", + "callout", + "dialplan" + ] + } + }, + "response": [] + }, + { + "name": "暂停呼叫计划", + "request": { + "method": "POST", + "header": [ + { + "key": "authorization", + "value": "75dc28487bb84fb59edbb7231fd6bfda" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\"ops\": \"pause\", \"dialplanId\": \"402882516546e777016546eeb00c0452\"}" + }, + "url": { + "raw": "http://{{IP}}:{{PORT}}/api/callout/dialplan", + "protocol": "http", + "host": [ + "{{IP}}" + ], + "port": "{{PORT}}", + "path": [ + "api", + "callout", + "dialplan" + ] + } + }, + "response": [] + }, + { + "name": "删除呼叫计划", + "request": { + "method": "POST", + "header": [ + { + "key": "authorization", + "value": "098e0f79525d472a9beb4197f02ff8cb" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\"ops\": \"delete\", \"dialplanId\": \"402882516556801d016556db24e908de\"}" + }, + "url": { + "raw": "http://{{IP}}:{{PORT}}/api/callout/dialplan", + "protocol": "http", + "host": [ + "{{IP}}" + ], + "port": "{{PORT}}", + "path": [ + "api", + "callout", + "dialplan" + ] + } + }, + "response": [] + }, + { + "name": "通话记录查询", + "request": { + "method": "POST", + "header": [ + { + "key": "authorization", + "value": "05f13a549bb04a2a9849563e38a60695" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\"ops\": \"query\", \"fromdate\": \"2018-08-21\", \"enddate\": \"2018-08-20\"}" + }, + "url": { + "raw": "http://{{IP}}:{{PORT}}/api/callout/records?p=1&ps=20", + "protocol": "http", + "host": [ + "{{IP}}" + ], + "port": "{{PORT}}", + "path": [ + "api", + "callout", + "records" + ], + "query": [ + { + "key": "p", + "value": "1" + }, + { + "key": "ps", + "value": "20" + } + ] + } + }, + "response": [] + }, + { + "name": "获取语音渠道坐席监控数据", + "request": { + "method": "POST", + "header": [ + { + "key": "authorization", + "value": "55d8348d753b432c9b9e42c39d35ccc8" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\"ops\": \"status\", \"channel\": \"bxzq\"}" + }, + "url": { + "raw": "http://{{IP}}:{{PORT}}/api/callout/monitor", + "protocol": "http", + "host": [ + "{{IP}}" + ], + "port": "{{PORT}}", + "path": [ + "api", + "callout", + "monitor" + ] + } + }, + "response": [] + }, + { + "name": "获取文件URL", + "request": { + "method": "POST", + "header": [ + { + "key": "authorization", + "value": "6db1ae1e5f5740df98b7d54d38fdb89c" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\"ops\": \"wav\", \"file\": \"2018-08-22/63187a63-f2c8-4463-85a6-db5d49851945.wav\"}" + }, + "url": { + "raw": "http://{{IP}}:{{PORT}}/api/callout/records", + "protocol": "http", + "host": [ + "{{IP}}" + ], + "port": "{{PORT}}", + "path": [ + "api", + "callout", + "records" + ] + } + }, + "response": [] + }, + { + "name": "外呼日报查询", + "request": { + "method": "POST", + "header": [ + { + "key": "authorization", + "value": "ad163116e63b4764ba0a741cf882ed23" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\"ops\": \"agg\", \"datestr\": \"2018-08-22\", \"channel\": \"bxzq\", \"direction\": \"out\"}" + }, + "url": { + "raw": "http://{{IP}}:{{PORT}}/api/callout/records", + "protocol": "http", + "host": [ + "{{IP}}" + ], + "port": "{{PORT}}", + "path": [ + "api", + "callout", + "records" + ] + } + }, + "response": [] + }, + { + "name": "坐席报表查询", + "request": { + "method": "POST", + "header": [ + { + "key": "authorization", + "value": "ca8c28e459fd477b9ccc9f210a3a81ea" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"ops\": \"audit\",\n \"fromdate\": \"2018-08-22\",\n \"channel\": \"bxzq\",\n \"enddate\": \"2018-08-24\"\n}" + }, + "url": { + "raw": "http://{{IP}}:{{PORT}}/api/callout/records", + "protocol": "http", + "host": [ + "{{IP}}" + ], + "port": "{{PORT}}", + "path": [ + "api", + "callout", + "records" + ] + } + }, + "response": [] + }, + { + "name": "坐席监控", + "request": { + "method": "POST", + "header": [ + { + "key": "authorization", + "value": "570d6bd5f37441af977ab7eceeb6951a" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"ops\": \"status\",\n \"channel\": \"bxzq\"\n}" + }, + "url": { + "raw": "http://{{IP}}:{{PORT}}/api/callout/monitor", + "protocol": "http", + "host": [ + "{{IP}}" + ], + "port": "{{PORT}}", + "path": [ + "api", + "callout", + "monitor" + ] + } + }, + "response": [] + }, + { + "name": "坐席监听", + "request": { + "method": "POST", + "header": [ + { + "key": "authorization", + "value": "ea9639dd357941f4986b8d19d2a91496" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"ops\": \"dropin\",\n \"channel\": \"bxzq\",\n \"callid\": \"2523f480-9e16-4a7a-9c3d-318ea7624109\"\n}" + }, + "url": { + "raw": "http://{{IP}}:{{PORT}}/api/callout/monitor", + "protocol": "http", + "host": [ + "{{IP}}" + ], + "port": "{{PORT}}", + "path": [ + "api", + "callout", + "monitor" + ] + } + }, + "response": [] + }, + { + "name": "\b联系人笔记:创建", + "request": { + "method": "POST", + "header": [ + { + "key": "authorization", + "value": "1e597e76a338439ebc2411a4a69d7d9f" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\"ops\": \"create\", \"category\": \"外呼\", \"content\": \"xx\", \"contactid\": \"25d61fe78db54bec95c9d0f405d0b20b\"}" + }, + "url": { + "raw": "http://{{IP}}:{{PORT}}/api/contacts/notes", + "protocol": "http", + "host": [ + "{{IP}}" + ], + "port": "{{PORT}}", + "path": [ + "api", + "contacts", + "notes" + ] + } + }, + "response": [] + }, + { + "name": "\b联系人笔记:详情", + "request": { + "method": "POST", + "header": [ + { + "key": "authorization", + "value": "d6e1a25c36194b2ba501a01f6ab4aaae" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\"ops\": \"detail\", \"id\": \"xxx\"}" + }, + "url": { + "raw": "http://{{IP}}:{{PORT}}/api/contacts/notes", + "protocol": "http", + "host": [ + "{{IP}}" + ], + "port": "{{PORT}}", + "path": [ + "api", + "contacts", + "notes" + ] + } + }, + "response": [] + }, + { + "name": "\b联系人笔记:获取联系人所有笔记", + "request": { + "method": "POST", + "header": [ + { + "key": "authorization", + "value": "06d09745a0964d258d86c07cc4f7f838" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\"ops\": \"fetch\", \"contactid\": \"xxx\"}" + }, + "url": { + "raw": "http://{{IP}}:{{PORT}}/api/contacts/notes", + "protocol": "http", + "host": [ + "{{IP}}" + ], + "port": "{{PORT}}", + "path": [ + "api", + "contacts", + "notes" + ] + } + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "id": "ee82d425-91be-4e85-b3da-7fbfd5d0da19", + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "id": "26cdde89-40b3-4b7f-85ad-09652137888c", + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ] +} \ No newline at end of file