CRM业务

作者: 陆遥远 | 来源:发表于2018-03-27 09:08 被阅读0次
    1. 坐席和坐席组长自己登陆也可以打
      (1) 坐席组长登陆 -----> 进入坐席---->我的客户 (如果有客户数据可以直接点击呼叫进行拨打,没有可以进行新增)
      (2) (1) ----> 点击查看 ------> 页面上有两处电话图标可以进行点击拨打。
    1. 前端请求接口: http://192.168.134.133:3000/api/agentindesk/agentCTI
      请求方式:post
      后端controllers
      路径:controllers/agentindesk.js

      方法: Agentindesk.prototype.postAgentCTI = function(req, res, next) {
      _this.common.redisClient.hget(guest.realm + ':C:AGENT:' + guest.agentNo + ':H', "destNum", function(err, results) {
      var cti = require('../lib/dialer')(guest);
      cti.callCustomer(req, res, next);
      cti.callBack(req, res, next);
      var cti = require('../sapi/cti')(guest);
      cti.agent(req, res, next);
      }
      }

       lib/dialer.js 相关的模块    
       Dialer.prototype.callCustomer = function(req, res, next) {
           涉及到的表:customers
           以及对应的models的findById().
       }
       
       发起呼叫接口 - 双呼
       Dialer.prototype.callBack = function(req, res, next) {
            common.redisClient.hgetall(req.params.realm + ':C:H', function(rde, rdres) {
              涉及的表:client
              以及对应的models的list
              common.redisClient.hget(req.params.realm + ':APILIMIT:' + common.moment().format('YYYYMMDD') + ':H', "call", function(totalcall_err, totalcall_res) { 
              }
              //检查主叫是否为坐席
               common.redisClient.exists(req.params.realm + ':C:AGENT:' + req.body.caller + ':H', function(isagent_err, isagent_res) {
               }
              
               //对各种通话权限的判断
               common.redisClient.rpush(req.params.realm + ':DIALER:L', JSON.stringify(json));
               common.redisClient.hincrby(req.params.realm + ':APILIMIT:' + common.moment().format('YYYYMMDD') + ':H', 'call', 1);
               common.redisClient.expire(req.params.realm + ':APILIMIT:' + common.moment().format('YYYYMMDD') + ':H', xes);
              
            }
       }
      

    //*******************************************************************************************************************
    相关的 /sapi/cti.js
    CTI.prototype.agent = function (req, res, next) {
    common.redisClient.hget(req.params.realm+":C:H","timezone",function(err,tz){
    _this.agentAction(req,tz,function(err,ares){

         });
     });
    

    }
    CTI.prototype.agentAction = function(req,tz,callback){
    }

    拨号盘相关的表:project_customers_contacts.json, project_customers.json
    入参:
    { action: 'dial',
    customer_id: '5a7929c61611889d053fcc0b',
    hideContact: true,
    phoneField: '电话号码',
    calleeShowNum: '02100000000',
    agentGroupNo: '83901',
    userField: '{"project_id":"58afa2554e6b565b30997032", "campaign_id":"58b51f27ffe0be7e1db2a31f", "customer_id":"5a7929c61611889d053fcc0b"}'
    }

    相关的redis:

    1. key: :C:AGENT:
      数据结构H: state
      deviceType
      destNum
      sipPass
      webPass
      loginPass
      customCallerId
      agentId
      requireSignin
      displayName
      clickDialOnly
      depId
    2. key C:H (订单相关的)
      数据结构:
      1) timezone
      3) language
      5) interTimeout
      7) exterTimeout
      9) name
      11) token
      13) customCDR
      15) cdrEvents
      17) callEvents
      19) agentEvents
      21) monitorInbound
      23) monitorOutbound
      25) monitorInternal
      27) monitorFormat
      29) monitorParttern
      31) asr
      33) asrCallback
      35) callerIdPolicy
      37) client_id
      39) email_server_id
      41) sms_profile_id
      43) restrictCallerId
      45) parentRealm
     3. keys ':APILIMIT:'
        数据结构:
    
     4. keys ':DIALER:L'
        数据结构:
        {
            "type": "call",
            "caller": "10001",
            "callee": "15321306404",
            "callerShowNum": "15321306404",
            "calleeShowNum": "02100000000",
            "account": "10001",
            "userField": "{\"project_id\":\"5a3cdfedbe680a7c75ae0849\", \"campaign_id\":\"5a5dc4250be91c8c67f1d493\", \"customer_id\":\"5a6ac86a7474053b4f329dc8\"}",
            "callback": "",
            "hideContact": true,
            "agentGroupNo": "1001",
            "sessionId": "_180153bd7fb1e0b3a271cb97bba4054c140e"
        }
    
    1. 请求地址: 192.168.134.133:3000/api/agents/roles?filter=%7B%7D&page=0&pageSize=0
      请求方式:get
      描述:坐席-----> 管理界面---(坐席组长下的坐席)

      后端controllers
      pass: controllers/agents.js

      接口功能描述:如果是client,可以看到其下所有座席;如果是座席组长,可以看到座席组长下所有座席。
      方法: Agents.prototype.list = function(req, res, next, obj) {}
      调用了models.js 里面的list方法。
      入参:{ controller: 'agents' }

    1. 请求地址:http://192.168.134.133:3000/api/profiles/ranking
      请求方式:get
      描述:坐席---> 联系客户-----(下面第一个下拉列表的选项)

      后端controllers
      pass: controllers/profiles/profiles.js
      方法: Profiles.prototype.getCampaigns = function(callback) {}
      涉及的表: agents, agent_groups, campaigns
      参数:无

    1. 请求地址:http://192.168.134.133:3000/api/profiles/agents/507f1f77bcf86cd799439108
      请求方式:get
      描述: 坐席----> 管理界面-----(坐席以及坐席组长的profiles)
      方法:Profiles.prototype.searchInformation = function(req, res, next) {}
      涉及的表:agents,accounts
    1. 请求地址: http://192.168.134.133:3000/api/profiles/agents/507f1f77bcf86cd799439108
      请求方式: put
      描述: 坐席------> 管理界面--------> 坐席简介-------> 确认更改
      方法:Profiles.prototype.updateInformation = function(req, res, next) {}
      涉及的表: agents , accounts
      入参:
    1. 请求地址: http://192.168.134.133:3000/api/agentindesk/58b51f27ffe0be7e1db2a31f/private?filter=%7B%22campaigns.campaign_id%22:%7B%22logic%22:%22%3D%22,%22value%22:%2258b51f27ffe0be7e1db2a31f%22%7D,%22currentStat.callresult_id%22:%7B%22logic%22:%22%3D%22,%22value%22:%22%22%7D%7D&page=0&pageSize=15&sort=%7B%22campaigns.updatedAt%22:1%7D
      请求方式:get
      描述: 坐席------> 联系客户------>表格内客户的数据
      方法: Agentindesk.prototype.listPrivate = function(req, res, next){}
      涉及到的表: campaigns, project_customers_***************,customers
      入参: filter: '{"campaigns.campaign_id":
      {"logic":"=","value":"58b51f27ffe0be7e1db2a31f"},
      "currentStat.callresult_id":{"logic":"=","value":""}}',
      page: '0',
      pageSize: '15',
      sort: '{"campaigns.updatedAt":1}'

    2. 请求地址: http://192.168.134.133:3000/api/agentindesk/customerSchema?campaign_id=58b51f27ffe0be7e1db2a31f
      请求方式:get
      描述:坐席------> 联系客户------>表格的 theader (获取客户表字段属性)
      方法: Agentindesk.prototype.listCustomerSchema = function (req, res, next) {}
      涉及到的表:campaigns,project_customers_***************,customers.
      入参:campaign_id

     请求地址: http://192.168.134.133:3000/api/agentindesk/callResults?filter=%7B%7D&page=0&pageSize=0&sort=%7B%22value%22:1%7D
     请求方式:get
     描述:坐席-----> 联系客户-------> 呼叫结果---(呼叫结果选项的下拉列表)
     请求方式:get
     方法:Agentindesk.prototype.listCallResults = function(req, res, next){
     操作的表: callresults
     入参:  { 
                controller: 'agentindesk',
               id: 'callResults'
             }
    
    1. 请求地址:http://192.168.134.133:3000/api/agentindesk/customers
      请求方式:post
      描述:坐席---------> 联系客户------(新增客户)
      方法:Agentindesk.prototype.createCustomer = function (req, res, next) {}
      **注释:检查该计划是否允许添加客户
      操作的表:campaigns, project_customers_***********,customers
      入参: { '姓名': '',
      '电话号码': '111111111',
      '电子邮件': '',
      '性别': '',
      '年龄': '',
      '城市': '',
      '区域': '',
      '备注': '',
      campaign_id: '58b51f27ffe0be7e1db2a31f'
      }

    2. 请求地址:http://192.168.134.133:3000/api/agentindesk/58b51f27ffe0be7e1db2a31f/random?campaign_id=58b51f27ffe0be7e1db2a31f&pageSize=15&project_id=58afa2554e6b565b30997032
      请求方式:get
      描述: 坐席---------> 联系客户------抢 (接口)
      方法: Agentindesk.prototype.listRandom = function(req, res, next){}
      后端方法的描述:随机列出指定任务的公海数据
      操作的表: campaigns, project_customers_****************,customers
      入参:{ controller: 'agentindesk',
      id: '58b51f27ffe0be7e1db2a31f',
      resource: 'random'
      }

    12  请求地址: http://192.168.134.133:3000/api/agentindesk/58b51f27ffe0be7e1db2a31f/random?campaign_id=58b51f27ffe0be7e1db2a31f&pageSize=15&project_id=58afa2554e6b565b30997032
        请求方式:get
        描述:坐席-------> 联系客户-------换一批 (接口)
        方法: Agentindesk.prototype.listRandom = function(req, res, next){}
        后端方法的描述:随机列出指定任务的公海数据
        操作的表: campaigns, project_customers_****************,customers 
        入参:{  controller: 'agentindesk',
                         id: '58b51f27ffe0be7e1db2a31f',
                   resource: 'random'
              }
    
     13. 请求地址: http://192.168.134.133:3000/api/agentindesk/58b51f27ffe0be7e1db2a31f/private?filter=%7B%22campaigns.campaign_id%22:%7B%22logic%22:%22%3D%22,%22value%22:%2258b51f27ffe0be7e1db2a31f%22%7D,%22campaigns.appointment%22:%7B%22from%22:%222018-02-08+00:00:00%22,%22to%22:%222018-02-08+23:59:59%22%7D,%22currentStat.callresult_id%22:%7B%22logic%22:%22%3D%22,%22value%22:%22%22%7D%7D&page=0&pageSize=15&sort=%7B%22campaigns.appointment%22:1%7D
         请求方式:get
         描述:坐席-----> 联系客户-------> (左边列表最后一个选项)我的预约
         方法: Agentindesk.prototype.listPrivate = function(req, res, next){}
         操作的表: campaigns, project_customers_***************,
         入参: {  
                   page: 0, 
                   pageSize: 15, 
                   data: [],
                   total: 0, 
                   totalPages: 0
               }
         
         
              
           
        
        
        
    14. 拨打电话相关最重要的三个接口:
     (1)    http://192.168.134.133:3000/api/agentindesk/renewPolling
     (2)  http://192.168.134.133:3000/api/agentindesk/agentCTI
      (3)   http://192.168.134.133:3000/api/agentindesk/checkQuota?campaign_id=58b51f27ffe0be7e1db2a31f
    
    
    1.  前端功能描述:坐席-------->联系客户---->呼叫
        (1)前端
        路径:  app/components/agentdesk/.
        前端页面:   agentdesk.html 
        主要HTML代码:
            <a ng-click="popCustomer('dial', drow);" href="#" class="btn default btn-xs green" ng-show="curNavLi != 'public' && curNavLi != 'campaignPublic'"><i class="fa fa-phone"></i> 呼叫 </a> 
        主要调用的js: agentdesk.js 
        
        调用js的方法:
              $scope.popCustomer = function (type, info) {}
         参数结构:type = "dial";
                   info = {  
                            _id                        
                            accounts
                            callStat
                            callresults
                            campaigns
                            comments
                            created
                            created_by_id
                            created_by_username
                            dialListStat
                            dialerStat
                            isInPDList
                            sale_funnels
                            tag
                            updated
                            区域
                            城市
                            备注
                            姓名
                            年龄
                            性别
                            电子邮件
                            电话号码
                         }
        
       
        内部判断逻辑:1.1 对拨打条件进行判定.
                          客户已质检,不能拨打电话,判断条件qced = "yes"
                          客户已成功提交,不能拨打电话,判断条件:sales_funnel_value > 0   
                          客户已失败提交,不能拨打电话,判定条件:sales_funnel_value < 0                       
                   
                      1.2 检查配额
        前端的请求接口:
        clusterccHttp.post('agentindesk/agentCTI', params).success(function (results, status, headers, config) {}
        返回参数对各种失败信息做判定:
        1.1 正在拨号,请稍后...
        1.2 拨号失败
        1.3 拨号申请中,请稍后...
        1.4 拨号失败
        
        (2) 后端
        请求方式:post
           后端controllers
           路径:controllers/agentindesk.js 
          
           方法: Agentindesk.prototype.postAgentCTI = function(req, res, next) {
                            _this.common.redisClient.hget(guest.realm + ':C:AGENT:' + guest.agentNo + ':H', "destNum", function(err, results) {
                                 var cti = require('../lib/dialer')(guest);
                                 cti.callCustomer(req, res, next);
                                 cti.callBack(req, res, next);
                                 var cti = require('../sapi/cti')(guest);
                                 cti.agent(req, res, next);
                            }
                          }
              
                lib/dialer.js 相关的模块    
                Dialer.prototype.callCustomer = function(req, res, next) {
                    涉及到的表:customers
                    以及对应的models的findById().
                }
                
                发起呼叫接口 - 双呼
                Dialer.prototype.callBack = function(req, res, next) {
                     common.redisClient.hgetall(req.params.realm + ':C:H', function(rde, rdres) {
                       涉及的表:client
                       以及对应的models的list
                       common.redisClient.hget(req.params.realm + ':APILIMIT:' + common.moment().format('YYYYMMDD') + ':H', "call", function(totalcall_err, totalcall_res) { 
                       }
                       //检查主叫是否为坐席
                        common.redisClient.exists(req.params.realm + ':C:AGENT:' + req.body.caller + ':H', function(isagent_err, isagent_res) {
                        }
                       
                        //对各种通话权限的判断
                        common.redisClient.rpush(req.params.realm + ':DIALER:L', JSON.stringify(json));
                        common.redisClient.hincrby(req.params.realm + ':APILIMIT:' + common.moment().format('YYYYMMDD') + ':H', 'call', 1);
                        common.redisClient.expire(req.params.realm + ':APILIMIT:' + common.moment().format('YYYYMMDD') + ':H', xes);
                       
                     }
                }
            
          //******************************************************************************************************************* 
          相关的 /sapi/cti.js 
          CTI.prototype.agent = function (req, res, next) {
             common.redisClient.hget(req.params.realm+":C:H","timezone",function(err,tz){
                 _this.agentAction(req,tz,function(err,ares){
                     
                 });
             });
          }
          CTI.prototype.agentAction = function(req,tz,callback){
          }
          
          拨号盘相关的表:project_customers_contacts.json, project_customers.json
          入参:
           { action: 'dial',
            customer_id: '5a7929c61611889d053fcc0b',
            hideContact: true,
            phoneField: '电话号码',
            calleeShowNum: '02100000000',
            agentGroupNo: '83901',
            userField: '{"project_id":"58afa2554e6b565b30997032", "campaign_id":"58b51f27ffe0be7e1db2a31f", "customer_id":"5a7929c61611889d053fcc0b"}' 
            }
    
           相关的redis:      
           1. key: *:C:AGENT:*
            数据结构H:   state      
                          deviceType 
                          destNum  
                          sipPass
                          webPass
                          loginPass
                          customCallerId
                          agentId
                          requireSignin
                          displayName
                          clickDialOnly
                          depId
            2. key  *C:H*  (订单相关的)
             数据结构:
                        1) timezone
                        3) language
                        5) interTimeout
                        7) exterTimeout
                        9) name
                        11) token
                        13) customCDR
                        15) cdrEvents
                        17) callEvents
                        19) agentEvents
                        21) monitorInbound
                        23) monitorOutbound
                        25) monitorInternal
                        27) monitorFormat
                        29) monitorParttern
                        31) asr
                        33) asrCallback
                        35) callerIdPolicy
                        37) client_id
                        39) email_server_id
                        41) sms_profile_id
                        43) restrictCallerId
                        45) parentRealm     
    
    
             3. keys ':APILIMIT:'
                数据结构:
    
             4. keys ':DIALER:L'
                数据结构:
                {
                    "type": "call",
                    "caller": "10001",
                    "callee": "15321306404",
                    "callerShowNum": "15321306404",
                    "calleeShowNum": "02100000000",
                    "account": "10001",
                    "userField": "{\"project_id\":\"5a3cdfedbe680a7c75ae0849\", \"campaign_id\":\"5a5dc4250be91c8c67f1d493\", \"customer_id\":\"5a6ac86a7474053b4f329dc8\"}",
                    "callback": "",
                    "hideContact": true,
                    "agentGroupNo": "1001",
                    "sessionId": "_180153bd7fb1e0b3a271cb97bba4054c140e"
                }
                
                
        
    
        
    2.  功能描述:坐席-------->管理界面--->个人信息
        (1) 前端
        路径:  app/components/profiles/profiles.js
        前端页面:   profiles.html 
        前端js方法:    
        clusterccHttp.get("profiles/" + type + "/" + $window.localStorage._id){}
        传参: (1) type = agents
               (2) $window.localStorage._id 507f1f77bcf86cd799439108
        (2) 后端
        请求方式:get
        描述: 坐席----> 管理界面-----(坐席以及坐席组长的profiles)
        方法:Profiles.prototype.searchInformation = function(req, res, next) {}
        涉及的表:agents,accounts
    
    
        
    3.  功能描述:坐席-------->管理界面--->坐席数据
        (1) 前端
            路径:  app/components/profiles/profiles.js
            前端页面:   profiles.html
            2,3 HTML代码片段
              <div class="profile-usermenu">
                    <ul class="nav">
                        <li   ng-class="{active: PageLocation=='Dashboard'}" ng-click="PageLocation='Dashboard'" ng-show="isAgent == 'yes'">
                            <a href="#">
                                <i class="icon-home"></i>
                                {{'Agent Data' | translate}}
                                <span ng-if="PageLocation=='Dashboard'" class="btn-default" style="background:transparent" ng-click="fetchRanking()">
                                    <i class="fa fa-refresh"></i>
                                </span>
                            </a>
                        </li>
                        <li ng-class="{active: PageLocation=='Agent'}" ng-click="PageLocation='Agent'" ng-show="isAgent == 'yes'">
                            <a href="#" >
                            <i class="icon-settings"></i>
                            {{'Personal Information' | translate}}</a>
                        </li>
                        <li ng-class="{active: PageLocation=='Account'}" ng-click="PageLocation='Account'" ng-hide="true" ng-if="(!isAgent || isAgent == 'no')">
                            <a href="#">
                            <i class="icon-settings"></i>
                            {{'Personal Information' | translate}}</a>
                        </li>
                    </ul>
                </div>
            调用方法:fetchRanking = function(){}
            调用后端接口的代码: clusterccHttp.get('profiles/ranking').success(function(data, status, headers, config) {}
            请求方式:get
              
        (2)后端
             路径: controllers/profiles/profiles.js
             方法: Profiles.prototype.getCampaigns = function(callback) {}
             涉及的表: agents,  agent_groups, campaigns
             参数:无
        
    3.1  排行榜内的数据,和3 使用的接口相同
            campaigns:
            58b51f27ffe0be7e1db2a31f:"Demo Campaign 1"
            58b51f27ffe0be7e1db2a320:"Demo Campaign 2"
            
            
            
    客户弹屏: 
    function popCustomerFun($rootScope, $scope, $translate, clusterccHttp, $window, $injector, $compile, info) {    
    }
    
    data  数据结构:
        
                {
                "姓名":"sym",
                "电话号码":"13856421235",
                "电子邮件":"1171@qq.com",
                "性别":"男",
                "年龄":"25",
                "城市":"北京",
                "区域":"",
                "备注":"",
                "campaigns":[
                    {
                        "agentNo":"1007",
                        "agentName":"HoegerMarlon",
                        "agent_id":"507f1f77bcf86cd799439108",
                        "campaign_id":"58b51f27ffe0be7e1db2a31f",
                        "sessionId":"",
                        "sales_funnel_value":0,
                        "qced":"no"
                    }
                ],
                "dialerStat":{
                    "totalDialedNum":0
                },
                "callStat":{
                    "called":0,
                    "answered":0
                },
                "dialListStat":{
                    "isInPDList":false,
                    "priority":0,
                    "scheduleAt":""
                },
                "isInPDList":false,
                "comments":[
    
                ],
                "tag":[
    
                ],
                "created_by_username":"1007",
                "created_by_id":"507f1f77bcf86cd799439108",
                "created":"2018-02-11T07:01:03.000Z",
                "updated":"2018-02-11T07:01:03.000Z",
                "_id":"5a7fea2f17ca740000e08c1e"
                }       
    

    {
    "_id" : ObjectId("5a8166f7253706f3c3c95d29"),
    "project_customer_id" : ObjectId("5a8166f7253706f3c3c95d28"),
    "project_id" : ObjectId("58afa2554e6b565b30997032"),
    "campaign_id" : ObjectId("58b51f27ffe0be7e1db2a31f"),
    "schedule_time" : "",
    "agentgroupno" : "",
    "agentno" : "1007",
    "mobile" : "566554645566",
    "city_id" : "",
    "area_id" : "",
    "level_id" : "",
    "survey_answer_id" : "",
    "successed_type" : 0,
    "data_from" : 0,
    "bigdata_batch_no" : "",
    "tag" : [],
    "bale_time" : "",
    "is_diallist" : 0,
    "project_customer_contact_id" : "",
    "last_sales_funnel_value" : -99,
    "last_callresult_id" : "",
    "last_agent_id" : "",
    "last_agentno" : "",
    "last_memo" : "",
    "last_contact_create_time" : "",
    "last_contact_update_time" : "",
    "last_is_qc" : 0,
    "last_qc_status" : "",
    "last_qc_update_time" : "",
    "last_qc_operator_id" : "",
    "last_qc_memo" : "",
    "operator_id" : ObjectId("507f1f77bcf86cd799439108"),
    "operate_type" : 1,
    "is_uploadAudio" : 0,
    "uploadAudioTimes" : 0,
    "create_time" : ISODate("2018-02-12T10:05:43.000Z"),
    "update_time" : ISODate("2018-02-12T10:05:43.000Z")
    }

    分页

    需要改的地方:
    (1) 
        data.campaigns.forEach(function (c) {
            if (c.campaign_id == campaign_id && c.survey_answer_id) {
                survey_answer_id = c.survey_answer_id;
            }
        }); 
            
    (2) 
             if (data.comments.length == 0) {
                $(myobj + '#newCommentTabBtn').trigger('click');
            } else if (info.callInfo) {
                var lastCommentData = data.comments[data.comments.length - 1];
                var cursessionId = (typeof(info.callInfo.parentCdrId) != 'undefined' && info.callInfo.parentCdrId != '') ? info.callInfo.parentCdrId : info.callInfo.sessionId;
                if (lastCommentData.sessionId == cursessionId) {
                    autoAdd = 'yes';
                    $(myobj + '#lastCommentTabBtn').trigger('click');
                } else {
                    $(myobj + '#newCommentTabBtn').trigger('click');
                }
            } else {
                $(myobj + '#lastCommentTabBtn').trigger('click');
            }
    (3)   //项目是否需要质检
            if ($scope.campaignObjs[campaign_id] && $scope.campaignObjs[campaign_id].hasOwnProperty("needQC") && $scope.campaignObjs[campaign_id].needQC == true) {
                //坐席提交成功客户后,质检前不允许新增联络记录
                if (action == 'add' && data.comments.length > 0 && data.comments[data.comments.length - 1].sales_funnel_value > 0 && data.comments[data.comments.length - 1].qced == 'no') {
                    clustercc.bootBoxAlert('此客户为成功客户,因未质检,目前不允许新增联络记录.');
                    return;
                }
            }
    (4)  var valideResult = $scope.validOperate('view', data);    //暂时认为不需要更改
            
        
        
     (5)    //客户资料字段获取
            var fieldsAry = $scope.customerFieldAttrJson[campaign_id].fieldsDeafult;
            if (campaign_id != 'pubcustomers') {
                fieldsAry = $scope.campaigns[$scope.campaignsAry.indexOf(campaign_id)].fields;
            }
            
            
     (6)
    

    filter:"{"_id":{"logic":"=","value":"-1"},"dialListStat.isInPDList":{"logic":"between","value":[null,null,false]}}"
    page:"0"
    pageSize:"20"
    sort:"{"dialerStat.lastDialAt":-1}"

    呼叫结果改为二级结构:

    1. 坐席组长--联系客户:二级搜索以及界面: 1.5 天
      联系客户--详情页: 呼叫结果二级联动搜索以及界面: 1.5 天
    1. 呼叫结果列表:
      呼叫结果管理界面: 1天
      大搜索框功能实现: 0.5 天
      小搜索框功能实现: 1天
      编辑呼叫结果:
      编辑呼叫结果界面:1 天
      实现后端功能: 1天

    2. 客户数据页面:
      (1) 客户数据:实现列表展示界面。 1
      (2) 实现客户数据列表的展示。 1
      (3) 实现客户数据大搜索(联动的查询) 1
      (4) 实现客户数据小搜索查询. 1
      (5) 实现特殊备注联络备注下载。 2 (需要熟悉代码)

    3. 成功提交客户:
      (1) 成功提交:实现列表展示界面。 1
      (2) 实现成功提交客户数据列表的展示。 1
      (3) 实现成功提交客户数据大搜索(联动的查询) 1
      (4) 实现成功提交客户数据小搜索查询. 1
      (5) 实现成功提交特殊备注联络备注下载。 1

    相关文章

      网友评论

        本文标题:CRM业务

        本文链接:https://www.haomeiwen.com/subject/xgkjcftx.html