im-kf

4.13.0-beta.14 • Public • Published

客服独立IM工作台

启动

1、git clone

2、yarn

3、yarn build 编译独立工作台,生成lib文件

4、yarn serve 运行工作台的example

im-test文件夹下面,直接引用src,不依赖lib

端口8883

访问后端接口 需要配置nginx 以及 hosts

nginx建议内容

server { listen 80; server_name crm.guazi-cloud.com;

   location / {
       proxy_pass http://127.0.0.1:8883;
   }

}

hosts建议使用whistle配置: crm-test.guazi-cloud.com/ 127.0.0.1:8883

项目文件结构

src

核心功能实现

---- src
      ---- assets   一些icon资源文件
      ---- common   公共组件
           ---- tab 实现了纵向的tab组件(使用方法类似于elementui的tab)
      ---- style    公共样式(修改了一些elementui的组件样式)
      ---- net-work 网络请求
           ---- 一些涉及到会话的数据请求

      ---- core     核心实现

           ---- bone.vue                   实现整体UI框架(拖拽整体边界等逻辑)
           ---- chat-status                会话状态(正在输入中等等)
           ---- chats-box                  会话列表
           ---- input-area                 输入区域,包括输入框上面的快捷功能
           ---- message                    消息展示区域
           ---- toolbar                    消息展示区域上方的工具条
           ---- image                      消息图片区域,支持缩放,旋转和下载等功能
           ---- record-list                消息历史记录区域,滚动加载所有的历史消息,后续扩展支持渲染卡片等消息
           ---- utils                      一些工具方法


      ---- plugins

           ----- message-render            消息渲染包
                 ---- common               渲染公共
                      ---- bot-reply.vue   机器人推荐回答
                      ---- layout.vue      消息体外部容器
                      ---- message-status.vue   消息状态成功失败
                 ---- components           各类消息组件
                      ---- card            一些卡片
                      ---- image.vue       图片消息
                      ...
                 ---- formatter.js         消息的formatter(注册)
                 ---- index.js             入口

           ----- link-card                 直达链接卡片包
                 ---- link-card-list
                 ---- net-work             直达链接卡片的network

im-test

项目使用示例实现

lib

项目打包后的资源

build

编译配置

全局API

Matrix

提供插件的注册

Matrix.use

参数: Object

注册插件的方法,会调用对象里面的install方法

Matrix.formatter

参数:Object

注册老通道会话的消息组件的formatter,会extend到消息formatter的默认值上面

示例:

    export default {
        // 处理消息类型为 c2kf 的消息, 追加 sender
        c2kf(m) {
            m.sender = 2
            return m
        },
        // 处理消息类型为 kf2c 的消息, 追加 sender
        kf2c: (m) => {
            m.sender = 1
            return m
        },
        // 处理消息内容为 text 的所有消息, 解析文本
        text: (m) => {
            m.renderType = 'text'
            m.contentShort = m.content
            // m.content = this.textParsing(m.content)
            return m
        },
        // 处理消息内容为 image 的所有消息
        image: (m) => {
            m.renderType = 'image'
            m.contentShort = '图片'
            return m
        },
        // 系统消息
        system_msg_for_kf: (m) => {
            m.sender = 3
            m.renderType = 'sysmsg'
            m.contentShort = '系统消息'
            return m
        },
        // 富文本
        rich_text(m) {
            m.renderType = 'richText'
            m.contentShort = '富文本'
            return m
        },
        card(m) {
            m.renderType = 'text'
            m.contentShort = '卡片'
            return m
        },
        // 猜你想问
        'card-4'(m) {
            m.renderType = 'guessCard'
            m.contentShort = '猜你想问'
            return m
        },
        'card-6'(m) {
            m.renderType = 'helpCard'
            m.contetShort = '帮你选车'
            return m
        },
        'card-7'(m) {
            m.renderType = 'linkCard'
            m.contetShort = '直达卡片'
            return m
        },
        'card-8'(m) {
            m.renderType = 'loginCard'
            m.contentShort = '登录卡片'
            return m
        },
        'card-9'(m) {
            m.renderType = 'workListCard'
            m.contentShort = '工单列表卡片'
            return m
        },
        'card-14'(m) {
            m.renderType = 'chatRecordCard'
            m.contentShort = '聊天记录卡片'
            return m
        },
        'card-23'(m) {
            m.renderType = 'harassmentPreventionCard'
            m.contetShort = '防骚扰卡片'
            return m
        },
    }

Matrix.nativeFormatter

因im-kf兼容新通道native-sdk,且新老通道的 native-sdkim-sdk的 MSG_TYPE(新通道MSG_TYPE 参考文档) 定义有所区别,所以新通道的自定义formatter需要额外方法定义

参数:Object

注册新通道会话的消息组件的formatter,会extend到消息formatter的默认值上面

示例:

// 参考 native-sdk文档上的各类参数:http://im-doc-sdk.guazi-cloud.com/guide/
import { NativeSdk } from 'im-kf'

let { DOMAIN_TYPE, CONTENT_TYPE, CTRL_TYPE, helpers, config } = NativeSdk

const C2GMsgformatter = (m) => {
    let { ANONYMOUS, EXTERNAL } = DOMAIN_TYPE
    if ([ANONYMOUS, EXTERNAL].includes(m.fromDomain)) {
        m.sender = 2
    } else {
        m.sender = 1
    }
    let {
        TEXT,
        IMAGE,
        VIDEO,
        HTML_CARD,
        TEMPLATE_STYLE_CARD,
        CUSTOM,
        CARD,
        RICH_TEXT,
    } = CONTENT_TYPE
    switch (m.subType) {
        case TEXT: {
            m.renderType = 'text'
            break
        }
        case IMAGE: {
            m.renderType = 'image'
            m.contentShort = '图片'
            try {
                let imgObj = JSON.parse(m.content)
                m.contentUrl = imgObj.url
            } catch (e) {
                m.contentUrl = 'https://image.guazistatic.com/gz01180417/19/53/8f570ee1e498c0c7149077e0e42b262f.png' // 默认失败的图片
            }
            break
        }
        case VIDEO: {
            m.renderType = 'video'
            m.contentShort = '视频'
            break
        }
        case HTML_CARD: {
            let contentParsed = helpers.parseCard(m.content, NativeSdk, config)
            m.renderType = 'htmlCard'
            m.contentParsed = contentParsed
            m.contentShort = contentParsed.cardName
            break
        }
        case RICH_TEXT: {
            m.renderType = 'richText' // 模板卡片
            m.contentShort = '富文本消息'
            break
        }
        case TEMPLATE_STYLE_CARD: {
            m.renderType = 'templateStyleCard' // 模板卡片
            m.contentShort = '模板卡片'
            break
        }
        case CARD: {
            m.renderType = 'card' // 卡片消息
            m.contentShort = '卡片消息'
            break
        }
        case CUSTOM: {
            m.renderType = 'custom' // 自定义消息
            m.contentShort = '自定义卡片'
            break
        }
        default: {
            m.renderType = 'hidden'
        }
    }
    return m
}
const CtrlFormatter = (m) => {
    m.sender = 3
    if (m.subType === CTRL_TYPE.SERVICE_GROUP_CONTENT) {
        m.renderType = 'sysmsg'
        m.contentShort = '系统消息'
    } else {
        m.renderType = 'hidden'

    }
    return m
}
export default {
    C2GSEND: m => C2GMsgformatter(m),
    C2GPUSH: m => C2GMsgformatter(m),
    CTRLPUSH_V1: m => CtrlFormatter(m),
    RECEIPT(m) {
        m.renderType = 'hidden'
        return m
    },
    RECALL: (m) => {
        // if (m.from === Bridge.im.config.uid) {
        //     m.content = '你撤回了一条消息'
        // } else {
        //     m.content = '对方撤回了一条消息'
        // }
        m.renderType = 'recall'
        m.sender = 3
        return m
    },
}

Matrix.renderComponent

参数:Object(Vue的Component,需要Component提供name属性)

注册具体用来渲染消息的组件

Matrix.WebImMixin

提供一些便利的方法,可以使用mixin注入

Slot

toolbox

注册到输入框上面的工具箱里面,需要采用im-tab-pane的方式注册

示例

chat-info

会话详细内容,会被注册到会话框右边的空间里面

示例

WebIm

开发中使用到的API挂载的实例

会以$webIm的方式注册到Vue.prototype上面

属性

$im

im实例,IM通信的核心

$root

工作台vue组件实例

方法

sendMessage

参数:message | Object 消息体内容,内容具体查看IM-SDK

描述:发送消息

sendFile

参数:message | Object 消息体内容,内容具体查看IM-SDK

描述:发送文件类型的消息

logout

描述:登出IM

login

描述:登录IM

setFree

描述:设置IM状态为空闲

setBusy

描述:设置IM状态为忙碌

appendChatIcon

参数:

描述:会话上面添加ICON

removeChatIcon

参数:

描述:会话上面清楚ICON

事件

会话事件

ready

im实例注册完成,并且挂载各种方法成功

chat-change

选中会话改变(包括因为点击选中带来的改变,或者因为同步会话状态带来的改变)

chat-end

会话主动结束

消息事件

new-message

新消息事件

paste-input

输入区域的粘贴事件

insert-text

参数:content | string

描述:向输入框插入文本

TODO

1:index.vue 里面的 onMessage 方法

2:chats-box 里面关于会话逻辑的部分要从index.vue分离出来

版本升级

v4.0.0-beta:24

兼容新通道Native-sdk

  • 新增变化
  • 新版本依赖了vuex 所以初始化配置新增了 store参数,示例如下:
// main.js
import Vue from 'vue';
import Vuex from 'vuex';
import WebIm from 'im-kf';
import plugin from './libs/plugin';
import 'im-kf/lib/im-kf.css';


WebIm.use(plugin);
Vue.use(Vuex);

const store = new Vuex.Store({
    modules: {
        ...
    },
});

Vue.use(WebIm, {
    isDev: isDev,
    config: {
        // imBarStatus: 'min'
    },
    store, // 新增参数store 将vuex生成的store进行赋值
});

  • this.$webIm增加监听坐席当前会话状态事件:change-im-status。示例如下:
    methods: {
        setWebImLinkStatus(status) {
            
        }
    },
    created() {
        this.$webIm.on('change-im-status', this.setWebImLinkStatus);
    },

change-im-status事件回调函数的行参status:

状态 说明
free 空闲
busy 忙碌
  • IM-KF实例新增 nativeFormatter 函数 用来绑定新通道的自定义formatter数据,使用方式:
  • 1 新建native-formatter.js文件,输入如下类似自定义内容:
// webIm 参考 native-sdk文档上的各类参数:http://im-doc-sdk.guazi-cloud.com/guide/
const FromDomainType = {
    STAFF: 0, // 内部员工
    GROUP: 1, // 群 暂时不用
    WORKSPACE: 2, // 工作台
    OFFACC: 3, // 公众号 暂时不用
    SERVICE: 4, // 客服
    ANONYMOUS: 5, // C端匿名用户
    ROBOT: 6, // 机器人
    EXTERNAL: 7, // C端登录用户
    SYSTEM: 8, // 系统
    UNKNOWN: 9, // 未知
    SALER: 10, // 销售
    APPRAISER: 11, // 捡瓜子。评估师
    NEWCAR_SALER: 12, // 新车太阳花销售
    MERCHANT: 13, // 开放平台车商
}

const C2GMsgformatter = (m) => {
    let { ANONYMOUS, EXTERNAL } = FromDomainType
    if ([ANONYMOUS, EXTERNAL].includes(m.fromDomain)) {
        m.sender = 2
    } else {
        m.sender = 1
    }
    let {
        TEXT,
        IMAGE,
        VIDEO,
        HTML_CARD,
        TEMPLATE_STYLE_CARD,
        CUSTOM,
        CARD,
        RICH_TEXT,
    } = WebIM.CONTENT_TYPE
    switch (m.subType) {
        case TEXT: {
            m.renderType = 'text'
            break
        }
        case IMAGE: {
            m.renderType = 'image'
            m.contentShort = '图片'
            try {
                let imgObj = JSON.parse(m.content)
                m.contentUrl = imgObj.url
            } catch (e) {
                m.contentUrl = 'https://image.guazistatic.com/gz01180417/19/53/8f570ee1e498c0c7149077e0e42b262f.png' // 默认失败的图片
            }
            break
        }
        case VIDEO: {
            m.renderType = 'video'
            m.contentShort = '视频'
            break
        }
        case HTML_CARD: {
            let contentParsed = WebIM.helpers.parseCard(m.content, WebIM, WebIM.config)
            m.renderType = 'htmlCard'
            m.contentParsed = contentParsed
            m.contentShort = contentParsed.cardName
            break
        }
        case RICH_TEXT: {
            m.renderType = 'richText' // 模板卡片
            m.contentShort = '富文本消息'
            break
        }
        case TEMPLATE_STYLE_CARD: {
            m.renderType = 'templateStyleCard' // 模板卡片
            m.contentShort = '模板卡片'
            break
        }
        case CARD: {
            m.renderType = 'card' // 卡片消息
            m.contentShort = '卡片消息'
            break
        }
        case CUSTOM: {
            m.renderType = 'custom' // 自定义消息
            m.contentShort = '自定义卡片'
            break
        }
        default: {
            m.renderType = 'hidden'
        }
    }
    return m
}
const CtrlFormatter = (m) => {
    m.sender = 3
    if (m.subType === WebIM.CTRL_TYPE.SERVICE_GROUP_CONTENT) {
        m.renderType = 'sysmsg'
        m.contentShort = '系统消息'
    } else {
        m.renderType = 'hidden'

    }
    return m
}
// WebIm是 
export default {
    C2GSEND: m => C2GMsgformatter(m),
    C2GPUSH: m => C2GMsgformatter(m),
    CTRLPUSH_V1: m => CtrlFormatter(m),
    RECEIPT(m) {
        m.renderType = 'hidden'
        return m
    },
    RECALL: (m) => {
        // if (m.from === Bridge.im.config.uid) {
        //     m.content = '你撤回了一条消息'
        // } else {
        //     m.content = '对方撤回了一条消息'
        // }
        m.renderType = 'recall'
        m.sender = 3
        return m
    },
}
  • 2 在plugin中增加如下内容:
import TestRender from './test-render.vue'
import nativeFormat from './native-formatter' // 新通道formatter
import format from './formatter' // 老通道formatter

export default {
    install(im) {
        im.formatter(format)
        // 新增内容
        im.nativeFormatter(nativeFormat)
        
        im.renderComponent(TestRender)
    },
}
  • 废弃
  • 废弃 v3.0.2-Beta.6 版本中的linkStatusHasChanged事件

v3.0.2-Beta.6

im-kf组件增加props事件 linkStatusHasChanged表示IM连接状态已经改变

  • 修改package.json里 im-kf版本为
    git+http://git.guazi-corp.com/blusher/im-kf.git#v3.0.2-Beta.6
    
  • 运行 yarn install更新yarn.lock文件
  • 为im-kf组件增加linkStatusHasChanged事件:
    <im-kf :uid="userInfo.userId + '' " 
            :uname="userInfo.userName + '' " 
            :debug="true" 
            :mainWidth="mainWidth"
            :mainHeight="mainHeight"
            :rightSideWidth="rightSideWidth"
            :leftSideWidth="leftSideWidth"
            :inputHeight="inputHeight"
            :left="150"
            :canResize="canResize"
            @linkStatusHasChanged="linkStatusHasChanged"
            custom-class="im-index">
        <div slot="chat-info" >
            //此部分用于扩展自己的业务部分
        </div>
    </im-kf>
    
    
    methods: {
        changeChat(chat) {
            //eslint-disable-next-line
            console.log(chat)
        },
        // im弹框连接状态更换通知事件
        linkStatusHasChanged(status) {
            console.log(status)
        },
    },
    
    • linkStatusHasChanged形参status枚举值:
状态 说明
online 上线
offline 下线
free 空闲
busy 忙碌
  • 2.4.1-beta.8

    快捷输入功能:解决埋点901577070811(旧埋点id为10250126)数据无法发送的bug

    • 修改package.json里 im-kf版本为
    git+http://git.guazi-corp.com/blusher/im-kf.git#v2.4.1-beta.8
    
    • 运行 yarn install更新yarn.lock文件

Readme

Keywords

none

Package Sidebar

Install

npm i im-kf

Weekly Downloads

1

Version

4.13.0-beta.14

License

MIT

Unpacked Size

35 MB

Total Files

46

Last publish

Collaborators

  • warmwarmheart