123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634 |
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>数据查看</title>
- <!--引入 element-ui 的样式,-->
- <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
- <!-- 必须先引入vue, 后使用element-ui -->
- <script src="./js/vue.js"></script>
- <!-- 引入element 的组件库-->
- <script src="https://unpkg.com/element-ui/lib/index.js"></script>
- <script src="https://unpkg.com/vconsole/dist/vconsole.min.js"></script>
- <script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
- <script src="https://open.work.weixin.qq.com/wwopen/js/jwxwork-1.0.0.js"></script>
- <script>
- var vConsole = new window.VConsole();
- </script>
- </head>
- <style>
- body {
- margin: 0;
- padding: 0;
- }
- .box {
- width: 100vw;
- height: 100vh;
- box-sizing: border-box;
- background: #FAFAFA;
- }
- .page4 {
- width: 100vw;
- height: 100vh;
- box-sizing: border-box;
- }
- .top_tip {
- background: #afdefd;
- display: flex;
- justify-content: center;
- color: #FFF;
- font-size: 14px;
- padding: 6px 0;
- }
- .logo {
- width: 20px;
- height: 20px;
- margin-right: 10px;
- }
- .tag_list {
- display: flex;
- align-items: center;
- padding: 10px 20px;
- overflow-x: auto;
- }
- .content {
- padding: 20px;
- margin-bottom: 10px;
- background: #FFF;
- }
- .icon_logo {
- width: 20px;
- vertical-align: bottom;
- }
- .sop_content {
- background: #f1f9ff;
- padding: 10px 20px;
- border-radius: 10px;
- font-size: 14px;
- }
- .font {
- color: #1890ff;
- }
- .sop_list {
- padding: 10px 20px;
- }
- .sop_time {
- font-weight: 600;
- }
- .dot {
- width: 10px;
- height: 10px;
- color: #1890ff;
- }
- .sop_item {
- background: #FFF;
- padding: 20px;
- margin: 10px 0;
- font-size: 14px;
- }
- .sop_body {
- margin: 10px 0;
- }
- .sop_c {
- background: #FAFAFA;
- padding: 10px;
- }
- .sop_foot {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin: 10px 0;
- }
- .sop_btn {
- background: #1890ff;
- color: #FFFFFF;
- padding: 5px 20px;
- border-radius: 4px;
- font-size: 12px;
- }
- </style>
- <body>
- <div id="box" class="box">
- <!-- 数据查看 -->
- <div class="page4">
- <div class="top_tip">
- <img class="logo" src="./img/wefan.png"></img>
- 微分机器人提供技术支持
- </div>
- <el-tabs v-model="activeName" stretch @tab-click="handleClickTab">
- <el-tab-pane label="执行中" name="playing">
- <div class="tag_list">
- <el-tag style="margin-right: 10px;" :type="item.type" effect="plain" v-for="(item, index) in executeData" :key="index" @click="getSop(item)">{{item.sopName}}</el-tag>
- </div>
- <div class="content">
- <div class="sop_content">
- <img class="icon_logo" :src="sopItem.clientAvatar || './img/avatar.png'"></img>
- <span>「{{sopItem.clientName}}」在「{{timeFormat(sopItem.triggerTime, 'yyyy-MM-dd hh:mm:ss')}}」</span>
- <span class="font" v-if="sopItem.triggerType">添加好友后触发客户SOP任务,</span>
- <span class="font" v-else>打上标签后触发客户SOP任务,</span>
- <span>快去跟进吧</span>
- </div>
- </div>
- <div class="sop_list" v-for="(item, index) in sopPlans" :key="index">
- <div class="sop_time">
- <span class="dot">·</span>
- {{timeFormat(item.executeTime, 'yyyy-MM-dd')}}
- </div>
- <div class="sop_item">
- <div><span style="color: #1890ff;">{{timeFormat(item.executeTime, 'hh:mm:ss')}}</span>发送</div>
- <div class="sop_body" v-if="item.ctOthers.length > 0">
- <div v-for="(c, cIndex) in item.ctOthers" :key="cIndex">
- <div class="sop_c" v-if="c.matterType === 0">
- <span>{{ c.matterText }}</span>
- </div>
- <div class="sop_c" v-if="c.matterType === 1">
- <img style="width: 100px;" :src="c.imgUrl" />
- </div>
- <div class="sop_c" v-if="c.matterType === 5">
- <span>{{ c.linkTitle }}</span>
- </div>
- <div class="sop_c" v-if="c.matterType === 2">
- <span>自定义视频</span>
- </div>
- <div class="sop_c" v-if="c.matterType === 4">
- <span>{{ c.fileName }}</span>
- </div>
- <div class="sop_foot">
- <span style="color: #999;">{{item.isSend ? '已发送' : ''}}</span>
- <div class="sop_btn" @click="handleSend(item.id, c)">发送</div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </el-tab-pane>
- <el-tab-pane label="已完成" name="ending">
- <div class="tag_list">
- <el-tag style="margin-right: 10px;" :type="item.type" effect="plain" v-for="(item, index) in executeData" :key="index"
- @click="getSop(item)">{{item.sopName}}</el-tag>
- </div>
- <div class="content">
- <div class="sop_content">
- <img class="icon_logo" :src="sopItem.clientAvatar || './img/avatar.png'"></img>
- <span>「{{sopItem.clientName}}」在「{{timeFormat(sopItem.triggerTime, 'yyyy-MM-dd hh:mm:ss')}}」</span>
- <span class="font" v-if="sopItem.triggerType">添加好友后触发客户SOP任务,</span>
- <span class="font" v-else>打上标签后触发客户SOP任务,</span>
- <span>快去跟进吧</span>
- </div>
- </div>
- <div class="sop_list" v-for="(item, index) in sopPlans" :key="index">
- <div class="sop_time">
- <span class="dot">·</span>
- {{timeFormat(item.executeTime, 'yyyy-MM-dd')}}
- </div>
- <div class="sop_item">
- <div><span style="color: #1890ff;">{{timeFormat(item.executeTime, 'hh:mm:ss')}}</span>发送</div>
- <div class="sop_body" v-if="item.ctOthers.length > 0">
- <div v-for="(c, cIndex) in item.ctOthers" :key="cIndex">
- <div class="sop_c" v-if="c.matterType === 0">
- <span>{{ c.matterText }}</span>
- </div>
- <div class="sop_c" v-if="c.matterType === 1">
- <img style="width: 100px;" :src="c.imgUrl" />
- </div>
- <div class="sop_c" v-if="c.matterType === 5">
- <span>{{ c.linkTitle }}</span>
- </div>
- <div class="sop_c" v-if="c.matterType === 2">
- <span>自定义视频</span>
- </div>
- <div class="sop_c" v-if="c.matterType === 4">
- <span>{{ c.fileName }}</span>
- </div>
- <div class="sop_foot">
- <span style="color: #999;">{{item.isSend ? '已发送' : ''}}</span>
- <div class="sop_btn" @click="handleSend(item.id, c)">发送</div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </el-tab-pane>
- </el-tabs>
- </div>
- </div>
- </body>
- <script>
- new Vue({
- el: '#box',
- data() {
- return {
- httpUrl: '',
- bId: null,
- env: '',
- memberId: null,
- activeName: 'playing',
- executeData: [],
- sopItem: {},
- sopPlans: [],
- historyId: null,
- externalUserId: null,
- }
- },
- created() {
- this.bId = this.getQueryParam('bId')
- this.env = this.getQueryParam('env')
- if (!this.env || this.env === 'prod') {
- this.httpUrl = 'https://wlapi.wefanbot.com'
- } else {
- this.httpUrl = 'http://test.wefanbot.com:18993'
- }
- if (this.getQueryParam('memberId')) {
- // 已授权
- this.memberId = this.getQueryParam('memberId')
- this.getQyWxSign()
- } else {
- // 授权
- this.getAuth()
- }
- // this.memberId = "woU17nDAAAnoSca19vZVKiNEKdc9tyYQ"
- // this.externalUserId = "wmU17nDAAAGT2PF6G8PUHdSx2DY1ljpg"
- // this.executeSopList()
- },
- methods: {
- getAuth() {
- fetch(this.httpUrl + `/p/insuite/p/getRedirectUri?env=${this.env}&bId=${this.bId}`)
- .then(res => {
- return res.json()
- }).then(result => {
- let { data, code, msg } = result
- if (code === 1) {
- window.location.replace(data)
- } else {
- this.$message({
- message: msg,
- type: 'warning'
- })
- }
- })
- },
- getQyWxSign() {
- fetch(this.httpUrl + '/scrm/v1/wxcp-corp/p/getAgentConfig', {
- method: 'post',
- body: JSON.stringify({
- bId: this.bId,
- url: window.location.href,
- }),
- headers: {
- 'Content-Type': 'application/json'
- }
- }).then(res => {
- return res.json()
- }).then(result => {
- let { data, code, msg } = result
- if (code === 1) {
- let that = this
- wx.agentConfig({
- corpid: data.corpid,
- agentid: data.agentId,
- timestamp: data.timestamp, // 必填,生成签名的时间戳
- nonceStr: data.nonceStr, // 必填,生成签名的随机串
- signature: data.agentSignature, // 必填,签名,见附录1
- jsApiList: ['getCurExternalContact'], // 必填,需要使用的JS接口列表
- success: function (res) {
- // 回调
- // 此处直接在注入回调中调用了获取当前外部联系人userId的接口,注意此接口是从聊天框的工具栏进入才能获取
- wx.invoke('getCurExternalContact', {
- }, function (res) {
- if (res.err_msg == "getCurExternalContact:ok") {
- console.log('invoke成功:', res.userId);
- that.externalUserId = res.userId
- that.executeSopList()
- } else {
- //错误处理
- console.log('invoke失败:', res)
- }
- });
- },
- fail: function (res) {
- if (res.errMsg.indexOf('function not exist') > -1) {
- alert('版本过低请升级');
- }
- },
- complete: function (res) {
- // 回调
- console.log('complete1', res);
- }
- });
- } else {
- this.$message({
- message: msg,
- type: 'warning'
- })
- }
- })
- },
- handleClickTab(tab) {
- if (tab.name === 'playing') {
- this.executeSopList(0)
- } else {
- this.executeSopList(1)
- }
- },
- //获取执行中的sop计划
- executeSopList(status) {
- fetch(this.httpUrl + `/scrm/v1/wxcp-sop/p/executeSopList?externalUserId=${this.externalUserId}&memberId=${this.memberId}&bId=${this.bId}&status=${status || 0}`)
- .then(res => {
- return res.json()
- }).then(result => {
- let { data, code, msg } = result
- if (code === 1) {
- this.executeData = data
- if (data.length > 0) {
- this.executeData.forEach(i => {
- i.type = ''
- })
- this.getSop(data[0], status)
- }
- } else {
- this.$message({
- message: msg,
- type: 'warning'
- })
- }
- })
- },
- getSop (item, status) {
- this.sopItem = item
- this.executeData.forEach(i => {
- if (i.sopId !== item.sopId) {
- i.type = ''
- } else {
- i.type = 'success'
- }
- })
- this.getSopHistoryList(item, status)
- },
- // 获取sop内容
- getSopHistoryList(item, status) {
- fetch(this.httpUrl + `/scrm/v1/wxcp-sop/p/executeSopHistoryList?clientId=${item.clientId}&memberId=${this.memberId}&sopId=${item.sopId}&status=${status || 0}`)
- .then(res => {
- return res.json()
- }).then(result => {
- let { data, code, msg } = result
- if (code === 1) {
- this.sopPlans = data
- } else {
- this.$message({
- message: msg,
- type: 'warning'
- })
- }
- })
- },
- handleSend(historyId, c) {
- this.historyId = historyId
- if (c.matterType === 1 || c.matterType === 2 || c.matterType === 4) {
- fetch(this.httpUrl + `/scrm/v1/wxcp-sop/p/getMedia?planContentId=${c.id}`)
- .then(res => {
- return res.json()
- }).then(result => {
- let { data, code, msg } = result
- if (code === 1) {
- this.sendData(c, data.mediaId)
- } else {
- this.$message({
- message: msg,
- type: 'warning'
- })
- }
- })
- } else {
- this.sendData(c)
- }
- },
- sendData (c, mediaId) {
- fetch(this.httpUrl + '/scrm/v1/wxcp-corp/p/getAgentConfig', {
- method: 'post',
- body: JSON.stringify({
- bId: this.bId,
- url: window.location.href,
- }),
- headers: {
- 'Content-Type': 'application/json'
- }
- }).then(res => {
- return res.json()
- }).then(result => {
- let { data, code, msg } = result
- if (code === 1) {
- let that = this
- wx.agentConfig({
- corpid: data.corpid,
- agentid: data.agentId,
- timestamp: data.timestamp, // 必填,生成签名的时间戳
- nonceStr: data.nonceStr, // 必填,生成签名的随机串
- signature: data.agentSignature, // 必填,签名,见附录1
- jsApiList: ['sendChatMessage'], // 必填,需要使用的JS接口列表
- success: function (res) {
- // 回调
- if (c.matterType === 0) {
- wx.invoke('sendChatMessage', {
- msgtype: "text", //消息类型,必填
- enterChat: false, //为true时表示发送完成之后顺便进入会话,仅移动端3.1.10及以上版本支持该字段
- text: {
- content: c.matterText, //文本内容
- },
- }, function (res) {
- if (res.err_msg == 'sendChatMessage:ok') {
- that.updateSop()
- //发送成功
- that.$message({
- message: '发送成功',
- type: 'success'
- })
- }
- })
- } else if (c.matterType === 1) {
- wx.invoke('sendChatMessage', {
- msgtype: "image", //消息类型,必填
- enterChat: false, //为true时表示发送完成之后顺便进入会话,仅移动端3.1.10及以上版本支持该字段
- image:
- {
- mediaid: mediaId, //图片的素材id
- },
- }, function (res) {
- if (res.err_msg == 'sendChatMessage:ok') {
- that.updateSop()
- //发送成功
- that.$message({
- message: '发送成功',
- type: 'success'
- })
- }
- })
- } else if (c.matterType === 2) {
- wx.invoke('sendChatMessage', {
- msgtype: "video", //消息类型,必填
- enterChat: false, //为true时表示发送完成之后顺便进入会话,仅移动端3.1.10及以上版本支持该字段
- video:
- {
- mediaid: mediaId, //视频的素材id
- },
- }, function (res) {
- if (res.err_msg == 'sendChatMessage:ok') {
- that.updateSop()
- //发送成功
- that.$message({
- message: '发送成功',
- type: 'success'
- })
- }
- })
- } else if (c.matterType === 4) {
- wx.invoke('sendChatMessage', {
- msgtype: "file", //消息类型,必填
- enterChat: false, //为true时表示发送完成之后顺便进入会话,仅移动端3.1.10及以上版本支持该字段
- file:
- {
- mediaid: mediaId, //文件的素材id
- },
- }, function (res) {
- if (res.err_msg == 'sendChatMessage:ok') {
- that.updateSop()
- //发送成功
- that.$message({
- message: '发送成功',
- type: 'success'
- })
- }
- })
- } else if (c.matterType === 5) {
- wx.invoke('sendChatMessage', {
- msgtype: "news", //消息类型,必填
- enterChat: false, //为true时表示发送完成之后顺便进入会话,仅移动端3.1.10及以上版本支持该字段
- news:
- {
- link: c.linkUrl, //H5消息页面url 必填
- title: c.linkTitle, //H5消息标题
- desc: c.linkDescription, //H5消息摘要
- imgUrl: c.linkThumbUrl, //H5消息封面图片URL
- }
- }, function (res) {
- if (res.err_msg == 'sendChatMessage:ok') {
- that.updateSop()
- //发送成功
- that.$message({
- message: '发送成功',
- type: 'success'
- })
- }
- })
- }
- },
- fail: function (res) {
- if (res.errMsg.indexOf('function not exist') > -1) {
- alert('版本过低请升级');
- }
- },
- complete: function (res) {
- // 回调
- console.log('complete', res);
- }
- });
- } else {
- this.$message({
- message: msg,
- type: 'warning'
- })
- }
- })
- },
- // 发送成功后刷新数据
- updateSop() {
- fetch(this.httpUrl + `/scrm/v1/wxcp-sop/p/updateHistorySendStatus?historyId=${this.historyId}`)
- .then(res => {
- return res.json()
- }).then(result => {
- let { data, code, msg } = result
- if (code === 1) {
- this.getSopHistoryList(this.sopItem)
- } else {
- this.$message({
- message: msg,
- type: 'warning'
- })
- }
- }).finally(() => {
- this.historyId = null
- })
- },
- // 截取url中的数据
- getQueryParam(paramName) {
- // 获取当前URL的查询字符串部分
- const queryString = window.location.search;
- // 创建一个URLSearchParams对象
- const urlParams = new URLSearchParams(queryString);
- // 返回指定参数的值,如果不存在则返回null
- return urlParams.get(paramName);
- },
- timeFormat(time, format = 'yyyy-MM-dd hh:mm:ss') {
- if (time === undefined || time === '' || time === null) {
- return '/';
- }
- const date = new Date(time);
- const o = {
- 'M+': date.getMonth() + 1, // 月份
- 'd+': date.getDate(), // 日
- 'h+': date.getHours(), // 小时
- 'm+': date.getMinutes(), // 分钟
- 's+': date.getSeconds(), // 秒
- 'q+': Math.floor((date.getMonth() + 3) / 3), // 季度
- 'S': date.getMilliseconds() // 毫秒
- };
- // 处理年份
- if (/(y+)/.test(format)) {
- format = format.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length));
- }
- // 处理日期和时间部分
- for (let k in o) {
- if (new RegExp('(' + k + ')').test(format)) {
- let value = o[k];
- let padding = RegExp.$1.length === 1 ? '' : '00'; // 根据格式字符串中的长度决定是否补零
- format = format.replace(RegExp.$1, ('' + value).padStart(padding.length + value.toString().length - value.toString().length, '0'));
- }
- }
- // 如果格式只包含时间部分,移除日期部分可能的占位符
- if (!/(M+|d+)/.test(format)) {
- // 移除任何可能存在的日期占位符(如:'yyyy-MM-dd ')
- format = format.replace(/(\s*-\s*){2}/g, ''); // 移除两个'-'之间的任何内容
- format = format.replace(/^\s*yyyy-\s*/, ''); // 移除开头的'yyyy-'
- }
- // 如果格式只包含日期部分,移除时间部分可能的占位符
- if (!/(h+|m+|s+)/.test(format)) {
- // 移除任何可能存在的时间占位符(如:' hh:mm:ss')
- format = format.replace(/(\s*:\s*){2}/g, ''); // 移除两个':'之间的任何内容
- format = format.replace(/\s*hh:\s*$/, ''); // 移除结尾的' hh:'
- }
- return format;
- }
- }
- })
- </script>
- </html>
|