背景:需求是打通企微客户名片与公司后台管理系统网校和crm的绑定和信息查看,由于公司主要技术栈为vue2且有部分项目自定义表单封装组件可以复用,所以新项目还是以vue2+ant design框架搭建
1.初始准备
-
后台管理系统增加企微侧边栏菜单,并把侧边栏页面链接和自定义配置的表单id关联作为一条数据。
-
登录企微后台创建应用、配置到聊天工具栏模块使用第一点的页面链接并拼接企业主体id和应用id。
网页授权及JS-SDK、企业微信授权登录等模块配置授权域名白名单并下载提供的txt文件后续交给运维放入前端服务器根目录进行域名安全校验。
最后要记得勾选“客户与上下游”里客户tab的API可调用接口的应用。
-
搭建项目准备,使用vue2+ant design+less搭建(sass版本冲突问题不友好非必要不推荐),使用了ant design的优点是可以大程度满足UI和产品的需求且符合旧项目组件的复用,但弊端是没有移动端的友好提示和中小屏下UI框架被做了处理,针对这些问题需要做适配的优化和组件的封装。
-
授权经调研后采用和微信公众号一样的方式,即跳转指定链接后获取code跟服务端接口换取当前用户信息。
2.初始化项目
-
使用vue2命令创建项目,并整理无关文件:
vue create sd-web-wecom-sidebar
-
配置项目env文件,用于区分多项目多环境。
-
新建代码仓库gitlab,并提交到远程代码仓库。
-
提供env文件名给运维配置到jenkins完成自动化部署。
3.项目开发
-
首先是公用交互组件和样式封装。
-
进入项目要能存储agentId和corpId,这点在链接地址栏上获取并存储vuex即可,至于写的位置,我是写在router文件的路由守卫。(写在App.vue不生效,写在main.js也可以)
-
登录判断,可以使用是否存了userInfo进行判断,未登录则跳转以下链接获取code并调用服务端接口换取userInfo,注意写好重定向地址逻辑。如果已登录则执行后续操作。
location.href = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${corpId}&redirect_uri=${location.href}&response_type=code&scope=snsapi_base&agentid=${agentId}#wechat_redirect`
-
调用后端接口,获取signature等信息。
-
由于兼容问题,需要同时调用两个企微初始化api,初始化后才可调用后续企微api:
wx.config({ beta: true, // 必须这么写,否则wx.invoke调用形式的jsapi会有问题 debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId: corpId, // 必填,企业微信的corpID timestamp: timestamp, // 必填,生成签名的时间戳 nonceStr: nonceStr, // 必填,生成签名的随机串 signature: signature, // 必填,签名,见 附录-JS-SDK使用权限签名算法 jsApiList // 必填,需要使用的JS接口列表,凡是要调用的接口都需要传进来 }) wx.ready(async function () { resolve() }) wx.error((res)=> { this.$alert('wx.config fail') console.log('wxConfig',res) reject(res) })
wx.agentConfig({ corpid: corpId, // 必填,企业微信的corpid,必须与当前登录的企业一致 agentid: agentId, // 必填,企业微信的应用id (e.g. 1000247) timestamp: timestamp, // 必填,生成签名的时间戳 nonceStr: nonceStr, // 必填,生成签名的随机串 signature: signature, // 必填,签名,见附录-JS-SDK使用权限签名算法 jsApiList, success: function (res) { resolve(res) }, fail: (res) =>{ this.$alert('wx.agentConfig fail') reject('agentConfig',res) if (res.errMsg.indexOf('function not exist') > -1) { this.$alert('版本过低请升级') } } })
-
当初始化完成后就可以使用以下获取当前对话的外部客户id了(initAgentConfig为封装的初始化检测):
export async function getCurExternalContact (retry) { await initAgentConfig() return new Promise((resolve, reject) => { wx.invoke('getCurExternalContact', { }, async function (res) { if (res.err_msg === 'getCurExternalContact:ok') { const userId = res.userId // 返回当前外部联系人userId // commit('SET_WX_USER_ID', userId) resolve(userId) } else { if (retry !== true) { store.commit('SET_INIT_AGENT_CONFIG', false) resolve(await getCurExternalContact(true)) } else { // 错误处理 reject(res.err_msg) } } }) }) }
-
至此,项目的基本搭建、授权和初始化已经完成。
-
后续继续封装优化项目,提供给其他小伙伴使用。
遇到的一点小问题:
-
需要实现初始化项目获取地址栏参数并存储一次企微信息,由于App.vue是未注册的组件,且项目一进入就跳转了crmUserInfo页面,所以App.vue并不能获取到企微信息。
-
思路转移到全局入口main.js,使用new URLSearchParams(window.location.search),配合get方法可以获取到,但对于router.params的**“/”**参数不太友好,应该只能引入router实例进行使用。最后是选择了router文件里路由守卫的方式实现。
-
ant design框架的日期时间选择框等均是英文,解决方式:
<!-- App.vue --> <template> <a-config-provider :locale="locale"> <div id="app"> <router-view /> </div> </a-config-provider> </template> <script> import zhCN from "ant-design-vue/lib/locale-provider/zh_CN"; export default { name: "app", data() { return { locale: zhCN, }; }, }; </script>
-
TinymceEditor富文本报错Uncaught SyntaxError: Unexpected token ‘<’,定位并删除配置代码解决。api废弃警告可配置deprecation_warnings: false解决。
-
其他企微授权问题,可以参照官方提示解决。不限于未配置白名单、配置参数错误、未走cache导致接口调用次数太多……
-
如何开启企微侧边栏调试模式?同时按Ctrl+Alt+Shift+D即可
-
企微侧边栏如何禁止页面缩放?可以尝试以下方法(注意客户端会有一段时间缓存,可以在设置-通用-存储空间-清理进行缓存验证):
<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
body { touch-action: manipulation; }
<script> // 禁用用户缩放 window.addEventListener('touchstart', (event) => { if (event.touches.length > 1) { event.preventDefault(); } }, { passive: false }); let lastTouchEnd = 0; window.addEventListener('touchend', (event) => { const now = new Date().getTime(); if (now - lastTouchEnd <= 300) { event.preventDefault(); } lastTouchEnd = now; }, { passive: false }); </script>
原文链接:xiaokar博客