如何开发CRM客户管理App

CRM即“客户关系管理”,其载体是一种存储客户联系信息以及追踪客户活动的软件。在移动互联时代,CRM客户管理app更具实际价值,可以帮助企业摆脱PC的束缚、以更加灵活的方式开展业务,同时妥善地存储、更新全部客户信息,吸引新客户、保留老客户以及将已有客户转为忠实客户,实现业务增长。

一、思维导图

二、功能介绍

1. 客户管理:录入客户信息、客户跟进、客户销售记录、直接拨打客户电话、条件筛选查询、公共客户;

2. 申请、收、发货管理;

3. 文档库、知识库;

4. 工作日志、日程管理;

5. 产品管理、库存管理;

6. 门店管理、员工管理;

7. 统计分析:客户统计分析、门店统计分析、员工统计分析、销售统计分析;

8. 通讯录、消息提醒;

9. 即时通讯、视频会议。

三、应用模块

四、项目目录

五、开发过程

1. 首页导航

系统首页使用tabLayout,可以将相关参数配置在JSON文件中,再在config.xml中将content的值设置成该JSON文件的路径。如果底部导航没有特殊需求这里强烈建议大家使用tabLayout为app进行布局,官方已经将各类手机屏幕及不同的分辨率进行了适配,免去了很多适配方面的问题。

{    "name": "root",    "hideNavigationBar": true,    "navigationBar": {      "background": "#035dff",      "color": "#fff",      "shadow": "#035dff",      "hideBackButton": true    },    "tabBar": {      "scrollEnabled": false,      "background": "#fff",      "shadow": "#f1f1f1",      "color": "#8a8a8a",      "selectedColor": "#000000",      "index":0,      "preload": 0,      "frames": [{        "name": "home",        "url": "pages/main/home.stml",        "title": "主页"      }, {        "name": "notice",        "url": "pages/notice/notice-index.stml",        "title": "消息通知"      }, {        "name": "tellbook",        "url": "pages/main/tellbook.stml",        "title": "通讯录"      }, {        "name": "my",        "url": "pages/seeting/my.stml",        "title": "个人中心"      }],      "list": [{        "text": "主页",        "iconPath": "image/navbar/home-o.png",        "selectedIconPath": "image/navbar/home.png",        "scale":3      }, {        "text": "提醒",        "iconPath": "image/navbar/notice-o.png",        "selectedIconPath": "image/navbar/notice.png",        "scale":3      }, {        "text": "通讯录",        "iconPath": "image/navbar/book-o.png",        "selectedIconPath": "image/navbar/book.png",        "scale":3      }, {        "text": "设置",        "iconPath": "image/navbar/set-o.png",        "selectedIconPath": "image/navbar/set.png",        "scale":3      }]    }  }

2. 动态权限

在首页的apiready中根据提示授权需要获取的权限,app每次启动的时候就会判断是否已授权,如果未授权就提示进行授权。

            apiready(){                let limits=[];        //获取权限        var resultList = api.hasPermission({          list: ['storage', 'location', 'camera', 'photos', 'phone']        });        if (resultList[0].granted) {          // 已授权,可以继续下一步操作        } else {          limits.push(resultList[0].name);        }        if (resultList[1].granted) {          // 已授权,可以继续下一步操作        } else {          limits.push(resultList[1].name);        }        if (resultList[2].granted) {          // 已授权,可以继续下一步操作        } else {          limits.push(resultList[2].name);        }        if (resultList[3].granted) {          // 已授权,可以继续下一步操作        } else {          limits.push(resultList[3].name);        }        if (resultList[4].granted) {          // 已授权,可以继续下一步操作        } else {          limits.push(resultList[4].name);        }        if(limits.length>0){          api.requestPermission({            list: limits,          }, (res) => {              });        }            }

3. 消息事件

通过sendEvent把事件广播出去,然后在其他页面通过addEventListener监听事件,通过事件名和附带的参数进行其他操作。

举例:登录成功之后,需要在个人中心加载个人信息,在首页加载相关个人的数据;添加某项数据之后,需要进行刷新列表等等。

methods: {      login(){        if (!this.data.username) {          this.showToast("姓名不能为空");          return;        }        if (!this.data.password) {          this.showToast("密码不能为空");          return;        }         var data={          secret:'',          user:this.data.username,          psw:this.data.password        };        api.showProgress();        POST('Index/queryuserinfo',data,{}).then(ret =>{          // console.log(JSON.stringify(ret));          if(ret.flag=='Success'){            api.setPrefs({key:'username',value:ret.data.username});            //api.setPrefs({key:'password',value:ret.data.password});            api.setPrefs({key:'userid',value:ret.data.id});            api.setPrefs({key:'roleid',value:ret.data.roleid});            api.setPrefs({key:'rolename',value:ret.data.rolename});            api.setPrefs({key:'organid',value:ret.data.organid});            api.setPrefs({key:'organname',value:ret.data.organname});            api.setPrefs({key:'organtype',value:ret.data.organtype});            api.setPrefs({key:'phone',value:ret.data.phone});                api.setPrefs({key:'name',value:ret.data.name});               api.sendEvent({              name: 'loginsuccess',            });            api.closeWin();          }          else{            api.toast({              msg:'登录失败!请稍后再试。'            })          }          api.hideProgress();        }).catch(err =>{          api.toast({            msg:JSON.stringify(err)          })        })      }    }

4. 接口调用

封装了req.js进行接口调用,采用了ES6语法中的Promise是异步编程的一种解决方案(比传统的回调函数更加合理、强大),用同步操作将异步流程表达出来,避免层层嵌套回调。Promise 对象提供统一接口,使得控制异步操作更加容易。有兴趣的同学可以多研究一下Promise。

const config = {    schema: 'http',    host: '192.168.1.5',    path: 'api.php/Home',    secret:'776eca99-******-11e9-9897-*******'} function req(options) {    const baseUrl = `${config.schema}://${config.host}/${config.path}/`;    options.url = baseUrl + options.url;    return new Promise((resolve, reject) => {        api.ajax(options,  (ret, err) => {            // console.log('[' + options.method + '] ' + options.url + ' [' + api.winName + '/' + api.frameName + ']n' + JSON.stringify({            //     ...options, ret, err            // }))            if (ret) {                resolve(ret);                api.hideProgress();            } else {                reject(err);                 api.hideProgress();            }        });    })}/** * GET请求快捷方法 * @constructor * @param url {string} 地址 * @param options {Object} 附加参数 */function GET(url, options = {}) {    return req({        ...options, url, method: 'GET'    });} /** * POST 请求快捷方法 * @param url * @param data * @param options {Object} 附加参数 * @returns {Promise<Object>} * @constructor */function POST(url, data, options = {}) {    data.secret = config.secret;    return req({        ...options, url, method: 'POST', data: {            values: data        }    });} export {    req, GET, POST, config}

在页面中调用的时候首先需要引入js文件。

//引入 import {POST, GET} from '../../script/req.js' //使用      methods: {    loadDaily(){        var data={          secret:'',          userid: api.getPrefs({sync: true,key: 'userid'})        };        api.showProgress();        POST('Index/queryleastremind',data,{}).then(ret =>{          // console.log(JSON.stringify(ret));          if(ret.flag=='Success'){            this.data.dailyList = ret.data;            this.data.isDaily = false;          }          else{            this.data.isDaily = true;          }          api.hideProgress();        }).catch(err =>{          this.data.isDaily = true;          api.toast({            msg:JSON.stringify(err)          })        })      }        }

5. 双击退出程序

在首页、登录页或其他需要双击退出程序的页面,在apiready中添加。

          apiready(){          //监听返回  双击退出程序      api.setPrefs({        key: 'time_last',        value: '0'      });      api.addEventListener({        name : 'keyback'        }, (ret, err) => {        var time_last = api.getPrefs({sync: true,key: 'time_last'});        var time_now = Date.parse(new Date());        if (time_now - time_last > 2000) {          api.setPrefs({key:'time_last',value:time_now});          api.toast({            msg : '再按一次退出APP',            duration : 2000,            location : 'bottom'          });        } else {          api.closeWidget({            silent : true          });        }      });          }

6. 清空缓存

官方自带的API clearCache,可清空全部缓存,也可选择清除多少天前的缓存。

7. 消息推送

采用极光推送,需要集成ajpush模块。

具体使用方法可详细阅读官方模块文档。

推送功能初始化需要在app每次启动的时候进行集成,将初始化极光推送的方法集成在util工具类中,在首页进行初始化。

fnReadyAJpush(){        var jpush = api.require('ajpush');        api.addEventListener({name:'pause'}, function(ret,err) {            onPause();//监听应用进入后台,通知jpush暂停事件        })         api.addEventListener({name:'resume'}, function(ret,err) {            onResume();//监听应用恢复到前台,通知jpush恢复事件        })         //设置初始化        jpush.init(function(ret, err){            if(ret && ret.status){                var ali=$api.getStorage('userid');                var tag=$api.getStorage('roleid');                //绑定别名                if($api.getStorage('userid')){                    jpush.bindAliasAndTags({                        alias:ali,                        tags:[tag]                    }, function(ret, err){                        if(ret.statusCode==0){                            api.toast({ msg: '推送初始化成功'});                        }                        else{                            api.toast({ msg: '绑定别名失败'});                        }                    });                }                //监听消息                jpush.setListener(function(ret) {                    var content = ret.content;                    alert(content);                });                }            else{                    api.toast({ msg: '推送服务初始化失败'});                }        });    }

初始化使用,每次启动app的时候需要,重新登陆之后可能存在切换账 的情况,也需要重新登陆。

8. 定位功能

因为系统中的定位只需要确定当前位置即可,所有定位功能使用的是aMapLBS模块,此模块没有打开地图的功能,只需要在用到的页面直接调用获取定位即可。

使用前需要在config.xml中进行配置,具体参数需要去高德开放平台去申请。

            //获取当前位置信息和经纬度               setLocation(){        var aMapLBS = api.require('aMapLBS');        aMap.updateLocationPrivacy({          privacyAgree:'didAgree',          privacyShow:'didShow',          containStatus:'didContain'        });        aMapLBS.configManager({          accuracy: 'hundredMeters',          filter: 1        }, (ret, err) => {          if (ret.status) {            aMapLBS.singleLocation({              timeout: 2            }, (ret, err) => {              if (ret.status) {                  this.data.lon = ret.lon;                this.data.lat = ret.lat;              }            });            aMapLBS.singleAddress({              timeout: 2            }, (ret, err) => {              if (ret.status) {                this.data.address = ret.formattedAddress;              }            });          }          else{            api.toast({              msg:'定位初始化失败,请开启手机定位。'            })            return false;          }        });      }

9. 视频、语音通话

采用tencentTRTC开发音视频通话功能。需要先去腾讯云平台创建应用申请key,在通过官方提供的方法生成userSig。

生成userSig代码:

//获取腾讯视频RTC usersig    public function getQQrtcusersig(){      checkscret('secret');//验证授权码      checkdataPost('userid');//用户ID       $sdkappid=C('sdkappid');      $key=C('usersig_key');       $userid=$_POST['userid'];      require 'vendor/autoload.php';      $api = new TencentTLSSigAPIv2($sdkappid, $key);      $sig = $api->genSig($userid);      if($sig){        returnApiSuccess('查询成功',$sig);      }      else{        returnApiError( '查询失败,请稍后再试');        exit();      }    }

用户视频画面需要根据当前视频用户数,进行计算调整。

<template>    <view class="page">    <view class="video-bk"></view>        <view class="footer">      <view class="footer-item" @click="setLoud">        <image class="footer-item-ico" src='../../image/loud-on.png' mode="widthFix" 

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2022年8月1日
下一篇 2022年8月1日

相关推荐