1. 使用说明

欢迎使用“AICC”的在线客服模块的移动端开发者工具套件(SDK)。我们分别为Android和iOS平台提供SDK,通过SDK,可以在您的APP中快速集成在线客服的各种功能。

2. 集成流程

下图展示在app中实现接入在线客服SDK的基本流程: image

3. 创建App接入渠道

3.1. App接入渠道创建页

登录后在左侧边栏中找到 企业配置→在线客服→渠道接入→App

image

3.2. 新增App接入渠道

点击右上角新增按钮,并根据提示新增即可

其中路由导航可以选择一个,如果没有或需要新增可以在内部侧边栏找到路由导航,然后根据文档新增

image

3.3. 新增路由导航

左侧内边栏中找到 路由导航

3.3.3. 添加机器人节点

在右侧找到机器人,往导航面板中拖动,然后按图示示例添加,也可以咨询我们销售或技术支持

image

3.3.4. 添加队列节点

在右侧找到队列,往导航面板中拖动,然后按图示示例添加,也可以咨询我们销售或技术支持

image

3.3.5. 路由导航配置完成

之后将节点链接起来保存即可,这是个简单的路由导航的配置示例,如需更复杂场景需要咨询我们销售或技术支持

image

3.4. 完成新增App接入渠道

新增App接入渠道并可配设置操作区域、扩展面板设置后,如下图

image

其中快捷入口(最多设置30个)设置功能,其中根据不同的事件有不同的配置,如下图

image

其中扩展面板(最多设置8个)设置功能,其中根据不同的事件有不同的配置,如下图

image

4. Android开发文档

4.1. 简介

欢迎使用“AICC”的在线客服移动端开发者工具套件(SDK)。本文针对安卓端使用做详细说明,通过 SDK,可以在您的 APP 中快速集成访客端在线聊天的功能,以具备文本、图片、视频等类型消息收发。 对接Demo已开源至GitHub: https://github.com/ti-net/clink-sdk

4.2. 环境要求

name

说明

Android SDK Build-tools

21.0.0 及以上

Android SDK

Android API 21 及以上

JAVA

JDK 1.7 及以上

Gradle

3.0 及以上版本

4.3. 集成SDK

4.3.1. 自动导入

在项目根目录的 build.gradle 文件中添加如下配置

	allprojects {
		repositories {
			...
			maven { url 'https://jitpack.io' }
		}
	}

在主 app 的 build.gradle 文件中添加如下依赖配置

    //implementation "com.ti-net.oskit:online:1.4.4" (不再更新)
	implementation 'com.github.ti-net-project:OnlineSDK-Android:2.4.3'

4.3.2. 手动导入

在主 app 的 build.gradle 文件中添加如下依赖配置

	api files('libs/online_2.4.3_kit_release.aar')

其他 说明:如您的应用内从未使用到以下依赖,且使用的是本地aar依赖客服SDK的方式,则需要在app的 build.gradle 文件中添加如下依赖配置

    //1.5.9.3版本之前仅需要添加以下依赖
    implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.0.0'
    implementation 'com.github.chrisbanes:PhotoView:2.3.0'
    //1.5.9.3+版本还需要添加以下依赖
    implementation 'com.jakewharton:disklrucache:2.0.2'
    implementation "org.jsoup:jsoup:1.12.1"

4.3.3. 混淆配置

-keep class com.tinet.** { *; }
-keep class org.tinet.** { *; }
-keep class com.org.** { *; }
-keep class com.lcw.** { *; }

4.3.4. 权限适配

AndroidManifest.xml 中添加如下所需要的权限

<!--SD卡读写权限,发送文件、保存文件。-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<!--录音权限,用于录音。-->
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<!--拍照权限,用于拍照(发送照片)-->
<uses-permission android:name="android.permission.CAMERA"/>

<!-- 安卓11+选择文件进行发送时查看所有文件必须权限  该权限属敏感权限,如有问题请咨询SDK技术支持 -->
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<uses-permission
    android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
    tools:ignore="ProtectedPermissions" />

4.4. 初始化

4.4.1. 功能描述

SDK 需要开发者在工程中调用下面方法来初始化 SDK。在 App 的整个生命周期中,开发者只需要将 SDK 初始化一次。

4.4.2. 参数说明

参数

类型

必填

说明

context

Context

上下文对象

tOSInitOption

TOSInitOption

初始化参数 option

TOSInitOption 参数说明

参数

类型

必填

说明

accessId

String

访问标识

accessSecret

String

访问秘钥

enterpriseId

String

企业号

apiUrl

String

平台 apiUrl(ex:https://octopus-api-1.vlink.cn/api/sdk/v1)

onlineUrl

String

在线业务 onlineUrl(ex:https://chat-app-bj.clink.cn)

debug

boolean

是否开启 debug 模式

advanceParams

Map<String, Object>

自定义可配参数,可为空

4.4.3. 代码示例

说明:只需要在继承 Application 类的 onCreate 初始化一次

        TOSInitOption tOSInitOption = new TOSInitOption();
        tOSInitOption.setAccessId(accessId);
        tOSInitOption.setAccessSecret(accessSecret);
        tOSInitOption.setEnterpriseId(enterpriseId);
        tOSInitOption.setApiUrl(define.getApiUrl());
        tOSInitOption.setOnlineUrl(define.getOnlineUrl());
        tOSInitOption.setDebug(BuildConfig.DEBUG);

        TOSClientKit.initSDK(this, tOSInitOption, new TImageLoader() {
            @Override
            public void loadImage(ImageView imageView, Object uri) {
                // 加载图片,加载图片的略图,合理利用缓存
            }

            @Override
            public void loadImage(ImageView imageView, Object uri, int placeholderImg, int errorImg) {
                // 加载图片,指定加载中的图片资源和加载图片异常资源,加载图片的略图,合理利用缓存
            }

            @Override
            public void loadImage(ImageView imageView, Object uri, int originalWidth, int originalHeight, TImageLoaderListener listener) {
                // 加载图片,指定图片加载的大小,用于需要查看大图或详图

            }

            @Override
            public void loadImage(Context context, Object uri, int originalWidth, int originalHeight, TImageLoaderListener listener) {
                // 加载图片,指定图片加载的大小,用于需要查看大图或详图,且加载控件非ImageView
            }
        });

4.5. 连接

4.5.1. 功能描述

连接在线客服,同一用户多次调用 connect 不会触发多次连接

4.5.2. 参数说明

参数

类型

必填

说明

tOSConnectOption

TOSConnectOption

初始化参数 option

TOSConnectOption 参数说明

参数

类型

必填

说明

visitorId

String

用户 App 的 userID(为空的情况下,系统默认为 UUID 去除-号,不可包含中文或特殊符号,建议使用用户系统 ID 方便 APP 拓展功能)

nickname

String

昵称

headUrl

String

头像地址

mobile

String

手机号

advanceParams

Map<String, Object>

自定义拓展信息

customerFields

Map<String, Object>

客户资料自定义字段(v2.0.2+支持此配置项)

4.5.3. 代码示例

说明:只需要在继承 Application 类的 onCreate 初始化一次

        //自定义可配参数
        Map<String, Object> extraInfo = new HashMap<>();
        extraInfo.put("enableMqtt", false);//连接时不开启mqtt服务

        //客户资料自定义字段
        Map<String, Object> customerFields = new HashMap<>();
        customerFields.put("autoUpdate", 1); //开启自动更新客户资料
        customerFields.put("客户名称", "XXX"); //客户名称自定义
        customerFields.put("电话", "XXX");
        customerFields.put("性别", "XXX");
        customerFields.put("地址", "XXX");
        customerFields.put("邮箱", "XXX");

        TOSConnectOption tOSConnectOption = new TOSConnectOption();
        tOSConnectOption.setVisitorId(id);
        tOSConnectOption.setNickname(nickname);
        tOSConnectOption.setHeadUrl(headerUrl);
        tOSConnectOption.setMobile(phone);
        tOSConnectOption.setAdvanceParams(extraInfo);
        tOSConnectOption.setCustomerFields(customerFields);

        TOSClientKit.connect(tOSConnectOption, new OnlineConnectResultCallback() {
            @Override
            public void onSuccess() {
            //连接成功回调
            }

            @Override
            public void onError(int errorCode, String errorDesc) {
            //连接失败回调
            }
        });

4.6. 断开连接

4.6.1. 功能描述

断开连接在线客服,当用户退出登录时调用

4.6.2. 参数说明

参数

类型

必填

说明

isReceivePush

Boolean

是否需要推送

listener

OnlineDisconnectListener

断开连接监听

4.6.3. 代码示例

        TOSClientKit.disConnect(false, null);

4.7. 会话页面

说明:TOSClientKit 已经实现了一个默认的会话视图页面,直接使用此类,即可快速启动和使用聊天页面。 注:只有 TOSClientKit 调用 connect 成功时,才可进入客服会话聊天页面

4.7.1. 集成会话页面

集成会话页面 fragment(即 SessionFragment),建议实现自己的 Fragment 继承 SessionFragment,可实现高度自定义。 如下代码:

SessionFragment sessionFragment = new SessionFragment();
sessionFragment.setArguments(getIntent().getExtras());
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.container, sessionFragment);
transaction.commitAllowingStateLoss();

4.8. 高级功能

4.8.1. 消息

消息监听
TOSClientKit.addOnlineMessageListener(new OnlineMessageListener() {
            @Override
            public void onMessage(OnlineMessage message) {
                // 收到的消息信息
            }
        });
消息事件监听
TOSClientKit.addOnlineEventListener(new OnlineEventListener() {
            @Override
            public void chatOpen(OnlineMessage message) {
            //会话开始
            }

            @Override
            public void chatClose(OnlineMessage message) {
            //会话结束
            }

            @Override
            public void chatBridge(OnlineMessage message) {
            //接通座席
            }

            @Override
            public void chatQueue(OnlineMessage message) {
            //进入排队
            }

            @Override
            public void chatLocation(OnlineMessage message) {
            //排队位置播报
            }

            @Override
            public void chatLeaveMessage(OnlineMessage message) {
            //留言
            }

            @Override
            public void chatInvestigation(OnlineMessage message) {
            //满意度
            }

            @Override
            public void robotBridge(OnlineMessage message) {
            //接通机器人
            }

            @Override
            public void withdraw(String messageId) {
            //座席撤回消息
            }

            @Override
            public void chatSwitch(OnlineMessage message) {
            //分支节点
            }

            @Override
            public void chatLeadingWords(OnlineMessage message) {
            //引导语消息
            }

            @Override
            public void chatInquiry(OnlineMessage message) {
            //询前表单消息
            }

            @Override
            public void chatResponse(OnlineMessage message) {
            //消息发送响应
            }
        });
最后一条消息信息

代码示例

     TOSClientKit.getLastMessageInfo(visitorId, new OnLastMessageResult() {
            @Override
            public void onLastMessage(int unreadCount, String lastMessage) {

            }
        });

返回参数说明

参数

类型

说明

unreadCount

String

未读数

lastMessage

String

最后一条消息

4.8.2. 会话

获取会话当前在线状态

代码示例

    /**
     * 获取当前在线状态
     *
     * @return 0:不在线(会话结束)  1:机器人   2:人工座席
     */
     TOSClientKit.getCurrentOnlineStatus()
会话状态监听
TOSClientKit.setOnlineStatusListener(new OnlineMessageManager.OnlineStatusListener() {
            @Override
            public void onStatusChanged(int status) {
                //当前状态
            }
        });
获取当前会话信息

代码示例

    /**
     * 获取当前会话信息
     *
     * @return SessionInfo
     */
     TOSClientKit.getCurrentSessionInfo()

返回参数SessionInfo说明

参数

类型

说明

mainUniqueId

String

会话 ID

startTime

String

会话开始时间

status

int

会话状态(新打开 1;路由中 2;排队中 3;接通座席 4;留言中 5;满意度 6;关闭 7;接通机器人 8;座席主动发起会话 9;)

enterpriseId

String

企业 id

visitorId

String

访客 id

4.8.3. 功能拓展

消息点击

请继承 SessionFragment 来实现

@Override
protected SessionClickListener getListener() {
   return new SessionClickListenerImpl(this){

            @Override
            public void onClick(View itemView, OnlineMessage message) {
                super.onClick(itemView,message);
                //消息点击事件
            }

            @Override
            public void onLinkClick(String url) {
                //super.onLinkClick(url);
                //屏蔽super,可实现自定义超链接点击事件
            }

            /**
            *
            * @param content          点击文本内容
            * @param messageEventType 文本类型
            */
            @Override
            public void onLinkClick(String content, String messageEventType) {
                //可根据messageEventType实现自有业务逻辑
            }

            @Override
            public void videoPlay(String url) {
                super.videoPlay(url);
                //自定义视频播放,如果需要自己实现视频播放,则需要屏蔽super.videoPlay(url);父类的实现方式
            }

            @Override
            public void downloadFile(String url, String name) {
                super.downloadFile(url, name);
               //下载文件回调,屏蔽super可自定义而下载功能
            }

            /**
             *
             * @param permissions
             * @param requestCode
             *   申请语音权限(requestCode = 1661)
             *   申请相机权限(requestCode = 1662)
             *   申请相机、语音权限 -- 拍摄(requestCode = 1663)
             *   申请文件权限 -- 文件(requestCode = 1664)
             *
             */
            @Override
            public void onStartRequestPermissionsCallback(@NonNull String[] permissions, int requestCode) {
                super.onStartRequestPermissionsCallback(permissions, requestCode);
                // : 2022/9/19 权限申请回调
                TLogUtils.i("onStartRequestPermissionsCallback:" + requestCode);
            }

            /**
             * 订单相关按钮点击事件(只回调button类型为link的事件)
             * @param buttonBean 按钮信息
             * @param orderBean  订单信息
             */
            @Override
            public void onOrderButtonClick(OnlineOrderButtonBean buttonBean, OnlineOrderBean orderBean) {
                super.onOrderButtonClick(buttonBean, orderBean);
                TToastUtils.showShortToast(requireContext(), "链接按钮:" + buttonBean.getText());
            }

            /**
             * 点击订单商品
             * @param productBean 商品信息
             * @param orderBean   订单信息
             */
            @Override
            public void onOrderProductClick(OnlineOrderProductBean productBean, OnlineOrderBean orderBean) {
                super.onOrderProductClick(productBean, orderBean);
                TToastUtils.showShortToast(requireContext(), "点击商品:" + productBean.getTitle());
            }

        };
    }
底部面板

请继承 SessionFragment 来实现 拓展面板重写需要实现UI的修改和事件的响应两步。

重写底部面板功能
    @Override
    public void funcList(List<Function> funcs) {
        if (null == funcs) {
            funcs = new ArrayList<>();
        }
        funcs.clear();

        //系统自带,根据UI自行定义即可
        Function f = new Function(Function.TYPE_SYSTEM,Function.SEND_IMAGE);
        f.setLogo(ContextCompat.getDrawable(requireContext(),R.mipmap.session_chat_over));
        f.setTitle("图片");
        funcs.add(f);
        funcs.add(new Function(Function.TYPE_SYSTEM, Function.SEND_VIDEO));
        funcs.add(new Function(Function.TYPE_SYSTEM, Function.SEND_FILE));
        funcs.add(new Function(Function.TO_ONLINE, ContextCompat.getDrawable(getActivity(), R.mipmap.session_to_online), "转人工"));
        funcs.add(new Function(Function.CHAT_OVER, ContextCompat.getDrawable(getActivity(), R.mipmap.session_chat_over), "结束会话"));


        //自定义卡片
        funcs.add(new Function(10002,
            requireContext().getResources().getDrawable(R.mipmap.session_chat_over),
            "商品卡片"));


        super.funcList(funcs);
    }
实现事件监听
    @Override
    protected FuncListener getFuncListener() {
        return new FuncListenerImpl(this) {
            @Override
            public void onFuncClick(Function func) {
                switch (func.getTypeId()){
                    case 10002:
                        ArrayList<CardInfo> cardInfos = new ArrayList<CardInfo>();
                        cardInfos.add(cardInfo("华为P40麒麟990 5G SoC芯片 5000万超感知徕卡三摄 30倍数字变焦"));
                        cardInfos.add(cardInfo("华为P30"));
                        cardInfos.add(cardInfo("华为P40"));
                        cardInfos.add(cardInfo("华为P50"));
                        new CardListDialog(cardInfos, cardInfo -> getPresent().sendCard(cardInfo)).show(getChildFragmentManager());
                        break;
                    default:
                        super.onFuncClick(func);
                        break;
                }

            }
        };
    }
快捷入口
ArrayList message = new ArrayList<>();
message.add(new LabeInfo("转人工", "转人工"));
message.add(new LabeInfo("订单号", "1234567890"));
message.add(new LabeInfo("服务地区", "北京市"));
message.add(new LabeInfo("服务", "满意"));
message.add(new LabeInfo("师傅", "金师傅"));
message.add(new LabeInfo("产品类型", "电子产品"));
message.add(new LabeInfo("师傅电话", "12345678900"));
message.add(new LabeInfo("订单状态", "已完成"));


//获取默认留言状态更新快捷入口实例
LabeInfo chatLeaveMessageStatus = LabeInfo.getChatLeaveMessageStatus(ticketPluginUrl);
Map<String, Object> dynamicConfigParameters = chatLeaveMessageStatus.getDynamicConfigParameters();
// :  客服留言数量提示开关(默认:true)
dynamicConfigParameters.put(LabeInfo.TOS_COMMENT_COUNT_ENABLE, swCommentCountEnable.isChecked());
// :  仅查询和展示访客创建的工单(默认:false)
dynamicConfigParameters.put(LabeInfo.TOS_VISITOR_CREATED_TICKET, cbVisitorCreatedTicket.isChecked());
// :  没有客服留言时不展示该快捷入口(默认:false)
dynamicConfigParameters.put(LabeInfo.TOS_NO_COMMENT_COUNT_HIDE_QUICK_ENTRY, cbNoCommentCountHideQuickEntry.isChecked());
// :  应用阶段(0:关闭,1:机器人,2:人工,10:机器人和人工,默认:10)
dynamicConfigParameters.put(LabeInfo.TOS_APPLICATION_STAGE, Integer.valueOf(etApplicationStage.getText().toString()));
chatLeaveMessageStatus.setDynamicConfigParameters(dynamicConfigParameters);

//添加留言状态更新快捷入口实例到快捷入口数组中(v2.0.1+支持此配置项)
message.add(chatLeaveMessageStatus);


//更新快捷入口可实时更新至会话窗体
TOSClientKit.updateSessionWindowQuickEntrys(message);

//清空快捷入口数据
TOSClientKit.clearSessionWindowQuickEntrys();

//快捷入口的点击回调
//请继承SessionFragment来实现
@Override
protected LabelListener getLabelListener() {
    return new LabelListenerImpl(this) {
        @Override
        public void onLabelClick(LabeInfo info) {
            super.onLabelClick(info);
            Toast.makeText(requireContext(), info.toString(), Toast.LENGTH_SHORT).show();
            // 快捷入口调用按钮转人工方法示例
            if(info.getName().equals("转人工")){
                getPresent().transferToHuman("转人工");
            }
        }
    };
}
商品卡片功能
商品卡片数据传递

商品卡片数据可以通过 argument 传递到会话窗体,参数名:tinetCard,可直接引用 SessionFragment.ARGS_CARD,参数实体为 CardInfo。

//定义CardInfo,卡片实体
CardInfo message = new CardInfo();
message.setSubTitle("HUAWEI Mate 60 Pro 海思 麒麟 9000s 5000万超感知徕卡三摄 100倍数字变焦");
message.setDescription("这是商品描述,遥遥领先遥遥领先遥遥领先遥遥领先遥遥领先遥遥领先");
message.setImg(
            "https://pro-fd.zol-img.com.cn/t_s300x300c5/g7/M00/04/0A/ChMkK2Ttx0iIfxQ1AADOoMpjc8MAAURKgH08wUAAM64551.jpg");
message.setPrice("¥ 6499.99");
message.setTime(TimeUtils.getDate(System.currentTimeMillis()));
message.setStatus("已到货");

HashMap<String, String> extraInfo = new HashMap<>();
extraInfo.put("订单号", "1234567890");//如需在商品卡片左上角显示订单号,则需配置此项,名称统一为”订单号“
extraInfo.put("服务地区", "北京市");
extraInfo.put("服务", "满意");
extraInfo.put("师傅", "金师傅");
extraInfo.put("产品类型", "电子产品");
extraInfo.put("师傅电话", "12345678900");
extraInfo.put("订单状态", "已完成");
message.setExtraInfo(extraInfo);

//传递至会话窗体
intent.putExtra(ChatFragment.ARGS_CARD,message);
发送商品卡片

在继承SessionFragment的fragment中实现方法:

    getPresent().sendCard(CardInfo)
按钮发送转人工(自带标识,可用于区分按钮转人工的数据)

在继承SessionFragment的fragment中实现方法:

    getPresent().transferToHuman("转人工");

4.9. 自定义UI配置

自定义UI配置有两种方式可以实现,第一是对各种消息修改其对应的style,第二是统一替换资源文件。

4.9.1. 修改消息的样式

消息昵称
<style name="tinetNicknameStyle">
        <item name="android:singleLine">true</item>
        <item name="android:textColor">@color/ti_nickname_text_color</item>
        <item name="android:textSize">@dimen/ti_chat_username_text_size</item>
        <item name="android:ellipsize">end</item>
        <item name="android:paddingBottom">@dimen/ti_nickname_content_span</item>
        <item name="android:layout_width">wrap_content</item>
        <item name="android:layout_height">wrap_content</item>
</style>
消息时间
<style name="tinetTimeStyle">
        <item name="android:textColor">@color/ti_msg_time_color</item>
        <item name="android:textSize">@dimen/ti_time_size</item>
</style>
文本消息
<!--默认字体样式-->
<style name="tinetTextStyle">
        <item name="android:linksClickable">true</item>
        <item name="android:paddingStart">@dimen/ti_content_paddingLeft</item>
        <item name="android:paddingEnd">@dimen/ti_content_paddingRight</item>
        <item name="android:paddingTop">@dimen/ti_content_paddingTop</item>
        <item name="android:paddingBottom">@dimen/ti_content_paddingBottom</item>
        <item name="android:textColor">@color/ti_send_msg_text_color</item>
        <item name="android:textSize">@dimen/ti_receive_bubble_text_size</item>
</style>
<!--发送文本的样式-->
<style name="tinetTextStyle.tinetTextSendStyle">
        <item name="android:gravity">left|center_vertical</item>
        <item name="android:background">@drawable/ti_send_bubble_bg</item>
</style>
<!--接收文本的样式-->
<style name="tinetTextStyle.tinetTextReceiveStyle">
        <item name="android:gravity">left|center_vertical</item>
        <item name="android:background">@drawable/ti_receive_bubble_bg</item>
</style>
图片消息

图片消息样式分为两部分:图片外部容器,图片内容.

图片外部容器
<!--默认图片容器样式-->
<style name="tinetImageContainerStyle"></style>

<!--默认图片容器样式 - 发送 -->
<style name="tinetImageContainerStyle.tinetImageContainerSendStyle">
        <item name="android:background">@drawable/ti_send_bubble_bg</item>
</style>

<!--默认图片容器样式 - 接收 -->
<style name="tinetImageContainerStyle.tinetImageContainerReceiveStyle">
        <item name="android:background">@drawable/ti_receive_bubble_bg</item>
</style>
图片内容
<!--默认图片样式-->
<style name="tinetImageStyle">
        <item name="android:adjustViewBounds">true</item>
        <item name="android:maxWidth">250dp</item>
        <item name="android:maxHeight">250dp</item>
        <item name="android:minWidth">160dp</item>
        <item name="android:padding">@dimen/ti_image_content_padding</item>
        <item name="android:minHeight">160dp</item>
        <item name="android:scaleType">fitXY</item>
</style>

<!--发送图片的样式-->
<style name="tinetImageStyle.tinetImageSendStyle">
        <item name="shapeAppearance">@style/tinetImageSendStyle</item>
</style>

<!--接收图片的样式-->
<style name="tinetImageStyle.tinetImageReceiveStyle">
        <item name="shapeAppearance">@style/tinetImageReceiverStyle</item>
</style>
语音消息

语音消息样式分为三部分:语音外部容器,语音时长,以及语音动画

语音外部容器
<!--语音消息容器样式-->
    <style name="tinetAudioContainerStyle">
        <item name="android:paddingStart">@dimen/ti_content_paddingLeft</item>
        <item name="android:paddingEnd">@dimen/ti_content_paddingRight</item>
        <item name="android:paddingTop">@dimen/ti_content_paddingTop</item>
        <item name="android:paddingBottom">@dimen/ti_content_paddingBottom</item>
        <item name="android:minHeight">42dp</item>
        <item name="android:minWidth">@dimen/ti_voice_min_width</item>
    </style>

    <!--语音消息容器样式 - 发送-->
    <style name="tinetAudioContainerStyle.tinetAudioContainerSendStyle">
        <item name="android:background">@drawable/ti_send_bubble_bg</item>
        <item name="android:gravity">right|center_vertical</item>
    </style>

    <!--语音消息容器样式 - 接收-->
    <style name="tinetAudioContainerStyle.tinetAudioContainerReceiverStyle">
        <item name="android:background">@drawable/ti_receive_bubble_bg</item>
        <item name="android:gravity">left|center_vertical</item>
    </style>
语音时长
    <!--语音消息内容样式-->
    <style name="tinetAudioContentStyle">
        <item name="android:textColor">@color/ti_send_msg_text_color</item>
        <item name="android:textSize">@dimen/ti_receive_bubble_text_size</item>
    </style>

    <!--语音消息内容样式 - 发送-->
    <style name="tinetAudioContentStyle.tinetAudioContentSendStyle"></style>
    <!--语音消息内容样式 - 接收-->
    <style name="tinetAudioContentStyle.tinetAudioContentReceiveStyle">
        <item name="android:layout_marginLeft">5dp</item>
    </style>
语音动画
    <!--语音消息图标样式-->
    <style name="tinetAudioIconStyle"/>

    <!--语音消息图标样式 - 发送-->
    <style name="tinetAudioIconStyle.tinetAudioIconSendStyle">
        <item name="android:layout_marginLeft">5dp</item>
        <item name="android:background">@drawable/ti_audio_animation_right_list</item>
    </style>
    <!--语音消息图标样式 - 接收-->
    <style name="tinetAudioIconStyle.tinetAudioIconReceiveStyle">
        <item name="android:background">@drawable/ti_audio_animation_left_list</item>
    </style>
视频消息

视频消息分为三部分:视频外部容器、视频封面、视频按钮

视频外部容器
    <!--默认视频容器样式-->
    <style name="tinetVideoContainerStyle"></style>
    <!--默认视频容器样式 - 发送 -->
    <style name="tinetVideoContainerStyle.tinetVideoContainerSendStyle">
        <item name="android:background">@drawable/ti_send_bubble_bg</item>
    </style>
    <!--默认视频容器样式 - 接收 -->
    <style name="tinetVideoContainerStyle.tinetVideoContainerReceiveStyle">
        <item name="android:background">@drawable/ti_receive_bubble_bg</item>
    </style>
视频封面
    <!--默认视频样式-->
    <style name="tinetVideoStyle">
        <item name="android:adjustViewBounds">true</item>
        <item name="android:maxWidth">250dp</item>
        <item name="android:maxHeight">250dp</item>
        <item name="android:minWidth">160dp</item>
        <item name="android:padding">@dimen/ti_image_content_padding</item>
        <item name="android:minHeight">160dp</item>
        <item name="android:scaleType">fitXY</item>
    </style>

    <style name="tinetVideoStyle.tinetVideoSendStyle">
        <item name="shapeAppearance">@style/tinetImageSendStyle</item>
    </style>

    <style name="tinetVideoStyle.tinetVideoReceiveStyle">
        <item name="shapeAppearance">@style/tinetImageReceiverStyle</item>
    </style>
视频按钮
    <!--默认视频样式 - 播放按钮 -->
    <style name="tinetVideoIconStyle">
        <item name="android:src">@drawable/tinetVideoPlay</item>
    </style>

    <style name="tinetVideoIconStyle.tinetVideoIconSendStyle"></style>
    <style name="tinetVideoIconStyle.tinetVideoIconReceiveStyle"></style>
文件消息

文件消息分为:文件外部容器,文件名,文件中间分隔线,文件下载文字。

文件外部容器
    <!--默认文件样式 - 容器样式 -->
    <style name="tinetFileContainerStyle">
        <item name="android:background">@drawable/ti_shape_file_message_bg</item>
    </style>
文件名
    <!--默认文件样式 - 文件名样式 -->
    <style name="tinetFileNameStyle">
        <item name="android:ellipsize">end</item>
        <item name="android:lineSpacingExtra">1dp</item>
        <item name="android:maxLines">2</item>
        <item name="android:paddingLeft">4dp</item>
        <item name="android:textColor">@android:color/black</item>
        <item name="android:textSize">@dimen/ti_receive_bubble_text_size</item>
    </style>
文件中间分隔线
    <!--默认文件样式 - 分隔线样式 -->
    <style name="tinetFileDividerStyle">
        <item name="android:background">#0F000000</item>
    </style>
文件下载文字
    <!--默认文件样式 - 下载文字样式-->
    <style name="tinetFileDownloadStyle">
        <item name="android:gravity">center</item>
        <item name="android:text">@string/ti_file_down</item>
        <item name="android:textColor">#4385FF</item>
        <item name="android:textSize">@dimen/ti_receive_bubble_text_size</item>
    </style>
富文本-文本消息
    <!--富文本 - 文本消息-->
    <style name="tinetHtmlTextStyle">
        <item name="android:lineSpacingExtra">2dp</item>
        <item name="android:textColor">@color/ti_receive_msg_text_color</item>
        <item name="android:textSize">@dimen/ti_receive_bubble_text_size</item>
    </style>
通知消息

通知消息是由TextView实现的,支持TextView所有的样式。

    <!--通知消息样式-->
    <style name="tinetNotifyStyle">
        <item name="android:layout_gravity">center</item>
        <item name="android:background">@drawable/ti_shape_notification_bg</item>
        <item name="android:gravity">center</item>
        <item name="android:lineSpacingExtra">1dp</item>
        <item name="android:paddingHorizontal" tools:ignore="NewApi">@dimen/ti_notification_paddingHorizontal</item>
        <item name="android:paddingVertical" tools:ignore="NewApi">@dimen/ti_notification_paddingVertical</item>
        <item name="android:layout_marginHorizontal" tools:ignore="NewApi">@dimen/ti_notification_marginHorizontal</item>
        <item name="android:layout_marginVertical" tools:ignore="NewApi">0dp</item>
        <item name="android:textColor">@color/ti_tips_text_color</item>
        <item name="android:textSize">@dimen/ti_notification_size</item>
    </style>
引导语
    <!--引导语-->
    <style name="tinetLeadingWordsStyle">
        <item name="android:background">@drawable/ti_shape_notification_bg</item>
        <item name="android:layout_gravity">center</item>
        <item name="android:gravity">center</item>
        <item name="android:lineSpacingExtra">1dp</item>
        <item name="android:paddingHorizontal" tools:ignore="NewApi">@dimen/ti_notification_paddingHorizontal</item>
        <item name="android:paddingVertical" tools:ignore="NewApi">@dimen/ti_notification_paddingVertical</item>
        <item name="android:layout_marginHorizontal" tools:ignore="NewApi">@dimen/ti_notification_marginHorizontal</item>
        <item name="android:layout_marginVertical" tools:ignore="NewApi">0dp</item>
        <item name="android:textColor">@color/ti_tips_text_color</item>
        <item name="android:textSize">@dimen/ti_notification_size</item>
    </style>
机器人快捷回复消息
    <!--接收消息的样式-->
    <style name="tinetReceiveMessageStyle">
        <item name="android:paddingStart">@dimen/ti_content_paddingLeft</item>
        <item name="android:paddingEnd">@dimen/ti_content_paddingRight</item>
        <item name="android:paddingTop">@dimen/ti_content_paddingTop</item>
        <item name="android:paddingBottom">@dimen/ti_content_paddingBottom</item>
        <item name="android:background">@drawable/ti_receive_bubble_bg</item>
    </style>

    <!--默认容器-->
    <style name="tinetReceiveMessageStyle.tinetContainerStyle">
    </style>

    <!--机器人快捷回复消息-->
    <style name="tinetReceiveMessageStyle.tinetContainerStyle.tinetRobotReplyStyle">
        <item name="android:gravity">left|center_vertical</item>
        <item name="android:maxWidth">@dimen/ti_message_max_width</item>
        <item name="android:textColor">@color/ti_receive_msg_text_color</item>
        <item name="android:textSize">@dimen/ti_receive_bubble_text_size</item>
    </style>
分类消息
    <!--分类消息 - 标题样式-->
    <style name="tinetRobotClassicTitleStyle">
        <item name="android:layout_marginBottom">14dp</item>
        <item name="android:lineSpacingExtra">2dp</item>
        <item name="android:textColor">@color/ti_black</item>
        <item name="android:textSize">14sp</item>
    </style>

    <!--分类消息 - 猜你所想样式-->
    <style name="tinetRobotClassicGuessStyle">
        <item name="android:textColor">@color/ti_guess_text_color</item>
        <item name="android:textSize">16sp</item>
        <item name="android:textStyle">bold</item>
    </style>

    <!--分类消息 - tab样式-->
    <style name="tinetRobotClassicTabStyle">
        <item name="android:layout_marginTop">12dp</item>
        <item name="android:background">@color/transparent</item>
        <item name="tabGravity">fill</item>
        <item name="tabIndicatorColor">@color/ti_blue</item>
        <item name="tabIndicatorFullWidth">false</item>
        <item name="tabIndicatorGravity">bottom</item>
        <item name="tabIndicatorHeight">2dp</item>
        <item name="tabMode">scrollable</item>
        <item name="tabSelectedTextColor">@color/ti_blue</item>
        <item name="tabTextAppearance">@style/tabLayoutTextStyle</item>
        <item name="tabTextColor">@color/ti_black</item>
        <item name="android:layout_width">match_parent</item>
        <item name="android:layout_height">40dp</item>
    </style>

    <!--分类消息 - 分隔线样式-->
    <style name="tinetRobotClassicDividerStyle">
        <item name="android:background">#0A000000</item>
    </style>

    <!--问题 - 问题项样式-->
    <style name="tinetRobotQuestionStyle">
        <item name="android:layout_marginLeft">8dp</item>
        <item name="android:lineSpacingExtra">1dp</item>
        <item name="android:textColor">@color/ti_dark</item>
        <item name="android:textSize">@dimen/ti_group_question_item_text_size</item>
    </style>

    <!--会话分隔线样式-->
    <style name="tinetSessionDividerStyle">
        <item name="android:layout_width">match_parent</item>
        <item name="android:layout_height">1dp</item>
        <item name="android:background">#EAEBEF</item>
    </style>

    <!--会话分隔线底部样式-->
    <style name="tinetSessionBottomDividerStyle">
        <item name="android:layout_width">match_parent</item>
        <item name="android:layout_height">1dp</item>
        <item name="android:background">#EAEBEF</item>
    </style>

    <!--换一换-->
    <style name="tinetQuestionChangeStyle">
        <item name="android:layout_width">wrap_content</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:drawableLeft">@drawable/ti_ic_refresh_change</item>
        <item name="android:drawablePadding">4dp</item>
        <item name="android:paddingRight">10dp</item>
        <item name="android:text">@string/ti_change</item>
        <item name="android:textColor">#4385FF</item>
        <item name="android:paddingVertical" tools:ignore="NewApi">5dp</item>
        <item name="android:textSize">12sp</item>
    </style>

4.9.2. 全局资源替换

分组

属性名

对象类型

描述

聊天列表背景色

ti_session_background_color

color

聊天背景颜色

昵称

ti_chat_username_text_size

dimen

昵称文字大小

昵称

ti_nickname_text_color

color

昵称文字颜色

气泡

ti_send_bubble_bg

drawable

发送气泡

气泡

ti_receive_bubble_bg

drawable

接收气泡

图片视频圆角

ti_voice_min_width

dimen

统一只设置气泡角度(用于图片、视频)

视频

tinetVideoPlay

drawable

视频消息的播放按钮

消息间距

ti_msg_time_span

dimen

消息与时间之间的间距

消息间距

ti_msg_msg_span

dimen

消息与消息之间的间距

发送端文字颜色和大小

ti_send_bubble_text_size

dimen

发送端文字大小

发送端文字颜色和大小

ti_send_msg_text_color

color

发送端文字颜色

接收端文字颜色和大小

ti_receive_bubble_text_size

dimen

接收端文字大小

接收端文字颜色和大小

ti_receive_msg_text_color

color

接收端文字颜色

分类问题

ti_question_span

dimen

问题之间的距离

消息最大宽度

ti_message_max_span

dimen

消息居另一边的间距 该值应该是头像大小+左右间距 ti_msg_horizontal_span ti_chat_avatar_message_spacing ti_chat_avatar_size

消息内容间距

ti_content_paddingLeft

dimen

消息内容左内间距

消息内容间距

ti_content_paddingRight

dimen

消息内容右内间距

消息内容间距

ti_content_paddingTop

dimen

消息内容上内间距

消息内容间距

ti_content_paddingBottom

dimen

消息内容下内间距

4.9.3. 消息头像

<!--访客和坐席头像-->
<declare-styleable name="UserHeaderView">
    <!--是否为左边的头像,否则为右边的头像-->
    <attr name="tinetHeaderIsLeft" format="boolean" />
    <!--头像大小-->
    <attr name="tinetHeaderSize" format="dimension|reference" />
    <!--头像与屏幕之间的距离-->
    <attr name="tinetHeaderMarginScreenHorizontal" format="dimension|reference"/>
    <!--头像与消息之间的距离-->
    <attr name="tinetHeaderMarginMessage" format="dimension|reference" />
    <!--头像圆角大小-->
    <attr name="tinetHeaderRadius" format="dimension|reference" />
    <!--圆角头像-->
    <attr name="tinetHeaderIsCircle" format="boolean"></attr>
</declare-styleable>

4.9.4. 聊天输入面板

包括文字输入框、发送按钮、语音按钮、表情按钮、更多按钮、按住说话。

整体定义
<!--用户输入框,如果不允许表情,同时也不允许更多的话,则发送按钮常驻-->
    <declare-styleable name="SessionInputView">
        <!--是否允许发送语音-->
        <attr name="tinetSessionInputVoiceEnable" format="boolean"/>
        <!--是否允许更多-->
        <attr name="tinetSessionInputMoreEnable" format="boolean"/>
        <!--是否允许发送表情-->
        <attr name="tinetSessionInputEmoEnable" format="boolean"/>
        <!--整体背景色-->
        <attr name="android:background"/>

        <!--键盘输入框(表情按钮与键盘按钮切换的图标)-->
        <attr name="tinetKeyboardSrc" format="reference"/>

        <attr name="android:paddingLeft"/>
        <attr name="android:paddingTop"/>
        <attr name="android:paddingBottom"/>
        <attr name="android:paddingRight"/>

        <!--聊天语音输入框的样式-->
        <attr name="tinetAudioStyle" format="reference"/>
        <!--表情按钮的样式-->
        <attr name="tinetEmoStyle" format="reference"/>
        <!--更多按钮的样式-->
        <attr name="tinetMoreStyle" format="reference"/>
        <!--输入框的样式-->
        <attr name="tinetInputStyle" format="reference"/>
        <!--发送按钮的样式-->
        <attr name="tinetSendButtonStyle" format="reference"/>
        <!--按住说话的样式-->
        <attr name="tinetVoiceStyle" format="reference"/>
    </declare-styleable>
文字输入框
 <attr name="android:background"/>
        <attr name="android:gravity"/>
        <!--[默认:@string/ti_input_box_hint_text]-->
        <attr name="android:hint"/>
        <attr name="android:lineHeight"/>
        <attr name="android:maxLines"/>
        <attr name="android:lines"/>
        <attr name="android:paddingLeft"/>
        <attr name="android:paddingTop"/>
        <attr name="android:layout_marginLeft"/>
        <attr name="android:layout_marginRight"/>
        <attr name="android:layout_marginTop"/>
        <attr name="android:layout_marginBottom"/>
        <attr name="android:paddingBottom"/>
        <attr name="android:paddingRight"/>
        <attr name="android:textColor"/>
        <attr name="android:textColorHint"/>
        <attr name="android:layout_height"/>
        <attr name="android:textSize"/>
        <attr name="android:imeOptions"/>
        <attr name="android:inputType"/>
发送按钮
<attr name="android:layout_width"/>
        <attr name="android:layout_height"/>
        <attr name="android:background"/>
        <attr name="android:gravity"/>
        <attr name="android:text"/>
        <attr name="android:textColor"/>
        <attr name="android:textSize"/>
        <attr name="android:paddingLeft"/>
        <attr name="android:paddingTop"/>
        <attr name="android:paddingBottom"/>
        <attr name="android:paddingRight"/>
        <attr name="android:layout_marginLeft"/>
        <attr name="android:layout_marginRight"/>
        <attr name="android:layout_marginTop"/>
        <attr name="android:layout_marginBottom"/>
语音按钮,表情按钮,更多按钮
 <attr name="android:layout_width"/>
        <attr name="android:layout_height"/>
        <attr name="android:paddingLeft"/>
        <attr name="android:paddingTop"/>
        <attr name="android:paddingBottom"/>
        <attr name="android:paddingRight"/>
        <attr name="android:src"/>
        <attr name="android:layout_marginLeft"/>
        <attr name="android:layout_marginRight"/>
        <attr name="android:layout_marginTop"/>
        <attr name="android:layout_marginBottom"/>
        <attr name="android:scaleType"/>
按住说话
<attr name="android:layout_width"/>
        <attr name="android:layout_height"/>
        <attr name="android:background"/>
        <attr name="android:gravity"/>
        <attr name="android:text"/>
        <attr name="android:textColor"/>
        <attr name="android:textSize"/>

        <!--按下去的文字-->
        <attr name="tinetPressText" format="string"/>

        <attr name="android:paddingLeft"/>
        <attr name="android:paddingTop"/>
        <attr name="android:paddingBottom"/>
        <attr name="android:paddingRight"/>
        <attr name="android:layout_marginLeft"/>
        <attr name="android:layout_marginRight"/>
        <attr name="android:layout_marginTop"/>
        <attr name="android:layout_marginBottom"/>

4.9.5. 语音弹框交互

定义布局
<!--录音布局-->
<item name="tinet_voice_popup_layout" type="layout">@layout/frg_session_audio_popup</item>

示例:frg_session_audio_popup.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:background="@android:color/transparent"
  android:orientation="vertical">


  <RelativeLayout
    android:layout_width="160dp"
    android:layout_height="160dp"
    android:layout_gravity="center"
    android:id="@+id/view"
    android:background="@drawable/ti_voice_record_view_bg"
    android:gravity="center">




    <ImageView
      android:id="@+id/iv"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_centerHorizontal="true"
      android:layout_marginLeft="41dp"
      android:layout_marginTop="20dp"
      android:layout_marginRight="41dp"
      android:src="@mipmap/popupv"
      android:layout_marginBottom="11dp" />


    <TextView
      android:id="@+id/tv"
      android:layout_width="match_parent"
      android:layout_height="40dp"
      android:layout_alignParentBottom="true"
      android:layout_gravity="center"
      android:layout_marginLeft="14dp"
      android:layout_marginTop="11dp"
      android:layout_marginRight="14dp"
      android:layout_marginBottom="11dp"
      android:gravity="center"
      android:textColor="@color/ti_input_area_voice_press_hint_text_color"
      android:textSize="14sp" />
  </RelativeLayout>


</FrameLayout>
注册监听事件,实现UI布局实现
AudioPopupManager.registerAudioListener(new AudioListener() {
    private ImageView iv;
    private TextView tv;
    private View v;

    @Override
    public void initView(View view) {
        iv = view.findViewById(R.id.iv);
        tv = view.findViewById(R.id.tv);
        v= view.findViewById(R.id.view);
    }


    @Override
    public void startRecording() {
        tv.setText("可以松开手指");
        v.setBackgroundColor(ContextCompat.getColor(MainActivity.this,R.color.ti_guess_text_color));
    }


    @Override
    public void timeoutTip() {
        tv.setText("超时");
    }


    @Override
    public void cancelRecording() {
        tv.setText("松开手指,取消发送");
        v.setBackgroundColor(ContextCompat.getColor(MainActivity.this,R.color.ti_line_up_text_color));
    }


    @Override
    public void shortRecording() {
        Toast.makeText(MainActivity.this,"录制时间太短了",Toast.LENGTH_SHORT).show();;
    }


    @Override
    public void onAudioChanged(int db) {
        tv.setText("录音中,音量:"+db);
    }
});

4.9.6. 发送状态

消息发送中动画和发送失败的UI都可以实现高级自定义

发送中

如果有动画,控件如果是ProgressBar则不需要处理,如果是其他,则需要实现AnimListener,实现动画

<item name="tinet_message_sending_layout" type="layout">@layout/message_sending</item>//注:动画控件命名:tinetSending

示例:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="wrap_content"
  android:background="@color/ti_red"
  android:layout_height="wrap_content"
  xmlns:tools="http://schemas.android.com/tools">

  <ProgressBar
    android:id="@id/tinetSending"
    style="?android:attr/progressBarStyleSmall"
    android:layout_width="20dp"
    android:layout_height="20dp"
    android:layout_gravity="center"
    android:layout_margin="5dp"
    android:visibility="gone"
    tools:visibility="visible" />


</FrameLayout>
发送失败

根控件的控件ID为:@id/tinetSendFailureContent

<item name="tinet_message_send_failure_layout" type="layout">@layout/message_send_failure</item>

示例:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:id="@id/tinetSendFailureContent"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_gravity="center"
  android:layout_marginEnd="2dp"
  android:maxWidth="100dp"
  android:visibility="gone"
  tools:visibility="visible">


  <TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:text="发送失败了"/>


  <ImageView
    android:layout_width="20dp"
    android:layout_height="20dp"
    android:layout_margin="5dp"
    android:layout_gravity="center"
    android:src="@drawable/ti_ic_error_hint" />
</LinearLayout>

4.9.7. 下拉刷新

SDK默认采用了 androidx.swiperefreshlayout.widget.SwipeRefreshLayout组件作为刷新会话列表控件,同时如果没有历史消息,还是可以继续下拉刷新。 SDK的刷新组件可以完全自定义实现。

定义布局文件名

tinet_session_refresh为定义的布局对象ID

    <item name="tinet_session_refresh" type="layout">@layout/refresh</item>
布局文件

例:refresh.xml

    <?xml version="1.0" encoding="utf-8"?>
        <!-- 该控件为自定义的刷新控件,此处以SmartRefreshLayout为例 -->
        <com.scwang.smartrefresh.layout.SmartRefreshLayout
          xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:app="http://schemas.android.com/apk/res-auto"
          android:layout_width="match_parent"
          android:id="@+id/smartRefresh"
          android:layout_height="0dp"
          android:layout_weight="1">
          <!-- 此处尽量不要修改 start -->
          <FrameLayout
            android:id="@id/tinetMessageContainer"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@drawable/ti_session_bg">
            <androidx.recyclerview.widget.RecyclerView
              android:id="@id/tinetMessageRecyclerView"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:fastScrollEnabled="false"
              android:orientation="vertical"
              android:layerType="software"
              android:transcriptMode="normal"
              app:layoutManager="com.tinet.oskit.adapter.layout.ReverseLinearLayoutManager" />
          </FrameLayout>
          <!-- 此处尽量不要修改 end -->
        </com.scwang.smartrefresh.layout.SmartRefreshLayout>
实现刷新方法

在继承SessionFragment的fragment中实现方法:

查看历史消息

实现onMessageRefresh();方法。

    smartRefresh = view.findViewById(R.id.smartRefresh);
    if(null != smartRefresh) {
        smartRefresh.setOnRefreshListener(new OnRefreshListener() {
        @Override
        public void onRefresh(@NonNull RefreshLayout refreshLayout) {
          //查看历史消息
          onMessageRefresh();
        }
   });
    }
结束刷新

void finishMessageRefresh(Long lastMessageTime,boolean hasMore,boolean isRefresh) //lastMessageTime最后一条消息的时间。hasMore是否还有更多消息,isRefresh是否为第一次刷新。

    @Override
    protected void finishMessageRefresh() {
       if(smartRefresh != null) {
           smartRefresh.finishRefresh();
       }
    }

4.9.8. 文本高亮可点击配置

说明:只需要在继承 Application 类的 onCreate 初始化一次

        // : 2022/10/13 以下为配置文本消息含超链接高亮显示规则
        List<TTextPatternRule> tTextPatternRules = new ArrayList<>();
        tTextPatternRules.add(
                new TTextPatternRule(Pattern.compile("这里填正则表达式", Pattern.CASE_INSENSITIVE),  //正则Pattern变量,是否忽略大小写可自行修改compile第二个参数
                        Color.parseColor("#1366dc"),  //高亮显示颜色int值,可自行修改为所需颜色
                        "phoneNumber"));  //类型说明,用于onLinkClick方法内回调messageEventType,区分匹配类型


       TOSClientKitConfig tosClientKitConfig = new TOSClientKitConfig.Builder()
                .setTextHighLightRuleList(tTextPatternRules)//配置文本消息含超链接高亮显示规则数组
                .build();

       TOSClientKit.setTosClientKitConfig(tosClientKitConfig);

4.9.9. 满意度评价弹窗配置

说明:旧版满意度评价为聊天页面消息内容中直接展示,新版则从聊天页面底部弹出dialog弹窗(v1.9.3+提供此配置项)

        TOSClientKitConfig tosClientKitConfig = new TOSClientKitConfig.Builder()
                .isOpenNewEvaluating(true) //开启新版满意度评价弹窗
                .build();

       TOSClientKit.setTosClientKitConfig(tosClientKitConfig);

4.9.10. 主动弹满意度评价弹窗

说明:此功能只建立在上一条开启了新版满意度评价弹窗功能才生效

首次离开页面主动弹满意度评价弹窗

说明:当开启会话后,实现首次离开页面时主动弹出满意度评价弹窗

    /**
     * 加载会话fragment所在的activity实现以下方法,拦截返回按钮事件
     */
    @Override
    public void onBackPressed() {
        // : 2024/7/17 调用会话fragment的handleFirstOutInvestigation方法
        chatFragment.handleFirstOutInvestigation();
    }
每次离开页面主动弹满意度评价弹窗

说明:当开启会话后,实现每次离开页面时都主动弹出满意度评价弹窗

    /**
     * 加载会话fragment所在的activity实现以下方法,拦截返回按钮事件
     */
    @Override
    public void onBackPressed() {
        // : 2024/7/17 调用会话fragment的showSatisfactionEvaluationPop方法
        chatFragment.showSatisfactionEvaluationPop();
    }

4.9.11. 开启点赞点踩功能

v2.0.1+提供此配置项

        TOSClientKitConfig tosClientKitConfig = new TOSClientKitConfig.Builder()
                .isOpenHelpfulFeature(true) //是否开启点赞点踩功能
                .isShowUnHelpfulContent(true) //是否展示点踩内容输入框
                .isRequiredUnHelpfulContent(true) //是否必填点踩内容
                .setUnHelpfulContentHint("这个是个暗文提示") //设置点踩输入框提示安暗文
                .setUnHelpfulTagList(Arrays.asList("答非所问", "没有想要的答案", "这是长标签测试哦")) //设置点踩标签
                .build();

        TOSClientKit.setTOSClientKitConfig(tosClientKitConfig);

4.10. 其他

4.10.1. 获取版本号

代码示例

    /**
     * 获取SDK版本号
     *
     * @return 版本号字符串
     */
     TOSClientKit.getSDKVersion()

4.11. 更新说明

SDK 2.4.2 版本更新说明[2025-0116]
Added
- 下载文件api回调下载进度
Changed
- 机器人查看大图需要显示原图
- 点击订单抽屉商品,订单抽屉弹窗不消失

SDK 2.4.1 版本更新说明[2025-0113]
Added
- 订单卡片增加订单标签字段、支持不传商品图片
- 订单抽屉支持分类tab

SDK 2.4.0 版本更新说明[2024-1230]
Added
- 新增支持机器人专题模式热点问题
- 新增表单留言支持路由导航中留言节点设置的返回
- Android7.0及以下设备加载H5工单插件页面增加友好提示
Changed
- 解决Android7.0及以下设备首次进入会话不显示头像,语音时长问题
- 解决Android7.0及以下设备满意度评价成功提示显示不全问题

SDK 2.3.1 版本更新说明[2024-12-17]
Added
- 新增订单抽屉发送订单功能
- 新增快捷入口更多面板支持后端配置
- 新增工单留言页面返回节点功能
Changed
- 吸底商品卡片发送extradata更改为数组类型
- 优化网络异常重发消息提示效果
- 兼容Android6.0机型语音发送问题

SDK 2.0.2 版本更新说明[2024-11-06]
Added
- 连接参数新增自动更新客户资料自定义字段
Changed
- 快捷入口显示顺序及更新逻辑优化

SDK 2.0.1 版本更新说明[2024-10-17]
Added
- 新增工单留言快捷入口功能
- 视频播放增加缓存功能
- 新增工单留言提交成功提示页面
- 新增文件消息UI支持自定义样式
- 待发送的商品卡片新增描述语展示
- 待发送的商品卡片新增描述语展示
- 下载图片视频保存到相册功能
- 视频图片下载增加正在下载中的交互
Changed
- 待发送商品卡片交互优化
- 增加发起满意度评价错误提示
- 进入会话页面头像闪动优化
- 优化播放视频时app压后台暂停播放
- 兼容app层targetSDK <33 时动态申请权限功能
- 修复语音取消功能异常
- 历史会话消息不展示点赞点踩

4.12. 常见问题

调用初始化方法的时机?

放置在继承application类的onCreate方法内即可,初始化方法内只含变量保存,不存在耗时操作。

初始化为何没有成功失败的回调?

初始化方法内只含基本上下文参数及SDK所需基本参数的赋值操作,不含任何复杂逻辑,故默认都为成功,不含失败。如若必传参数未传,则后续方法调用会提示对应错误

调用连接方法的时机?

如访客id与应用用户id无关联,可随机生成访客Id,则可在进入应用主页面后直接进行连接操作;
如访客id需要依赖应用用户id,则可在登录成功后,进行连接操作;
如想在使用客服模块时,再进行初始化与连接操作,则可在进入客服聊天页面之前进行连接操作,连接操作成功后,再跳转至客服聊天页面;

调用断开连接方法的时机?

可不关注断开连接方法,如需调用,可在app应用退出登录时调用

支持重复调用连接吗?

SDK内部支持重复调用连接,针对重复调用,SDK也正常执行后面流程,返回连接状态。

网络异常情况下,连接断开,需要进行手动重新连接吗?

SDK内部已封装了重连逻辑,无需app层实现重连逻辑。

进入页面为何显示对话已结束,无法发送文字?

这是后台的功能配置问题,需要有机器人或者在线的客服,才能发送消息。

如何解决客服分组问题?

如需多组客服,可根据需要在后台创建多个队列,使用不同accessId初始化不同的队列。

聊天界面那些UI样式可以自定义?

聊天页面大部分UI样式均可使用资源替换自定义*
如应用内统一样式,则可通过查看【4.10.1. xml修改示例】来进行修改,修改字体大小与尺寸可通过定义dimen来修改,修改颜色值可通过colors文件来修改,也可直接以同名资源文件名来直接替换,以达到更多修改目的;
如应用内,有多个客服聊天场景,且需要不同UI样式,则可通过查看【4.10.2. 代码修改示例】来进行UI自定义的修改,此修改只可满足大部分基础UI样式的修改;

集成SDK后为何图片不展示?

由于SDK内部不提供直接加载图片功能,需要app层在initSDK方法内实现图片加载,此设计是由于每个app可能用到不同的图片加载库,为不引起依赖库冲突,方便使用,则SDK直接回调了图片加载的对应参数,供app层使用
glide加载具体示例如下:

TOSClientKit.initSDK(this, tOSInitOption, new TImageLoader() {
            @Override
            public void loadImage(ImageView imageView, Object uri) {
                Glide.with(imageView.getContext())
                        .load(uri)
                        .error(R.drawable.ti_ic_load_default_image)
                        .placeholder(R.drawable.ti_ic_load_default_image)
                        .into(imageView);
            }

            @Override
            public void loadImage(ImageView imageView, Object uri, int placeholderImg, int errorImg) {
                Glide.with(imageView.getContext())
                        .load(uri)
                        .override(CustomTarget.SIZE_ORIGINAL, CustomTarget.SIZE_ORIGINAL)
                        .error(errorImg)
                        .placeholder(placeholderImg)
                        .into(imageView);
            }

            @Override
            public void loadImage(ImageView imageView, Object uri, int originalWidth, int originalHeight, TImageLoaderListener listener) {
                Glide.with(imageView.getContext())
                        .load(uri)
                        .override(originalWidth, originalHeight)
                        .listener(new ImageRequestListener(listener))
                        .error(R.drawable.ti_ic_load_default_image)
                        .placeholder(R.drawable.ti_ic_load_default_image).into(imageView);

            }

            @Override
            public void loadImage(Context context, Object uri, int originalWidth, int originalHeight, TImageLoaderListener listener) {
                Glide.with(context)
                        .load(uri)
                        .override(originalWidth, originalHeight)
                        .into(new CustomTarget<Drawable>() {
                            @Override
                            public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
                                if (null != listener) {
                                    listener.onResourceReady(resource);
                                }
                            }

                            @Override
                            public void onLoadCleared(@Nullable Drawable placeholder) {
                                if (null != listener) {
                                    listener.onLoadFailed();
                                }
                            }
                        });
            }
        });


    class ImageRequestListener implements RequestListener<Drawable> {

        private TImageLoaderListener listener;

        public ImageRequestListener(TImageLoaderListener listener) {
            this.listener = listener;
        }

        @Override
        public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
            if (null != listener) {
                listener.onLoadFailed();
            }

            return false;
        }

        @Override
        public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
            if (null != listener) {
                listener.onResourceReady(resource);
            }
            return false;
        }
    }

集成后点击大图预览照片后为何崩溃?

由于SDK内部图片预览使用了其他预览插件,需检查是否添加SDK之外以下依赖:
    //1.5.9.3版本之前仅需要添加以下依赖
    implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.0.0'
    implementation 'com.github.chrisbanes:PhotoView:2.3.0'
    //1.5.9.3+版本还需要添加以下依赖
    implementation 'com.jakewharton:disklrucache:2.0.2'
    implementation "org.jsoup:jsoup:1.12.1"
    implementation 'com.github.gzu-liyujiang.AndroidPicker:Common:4.1.5'
    implementation 'com.github.gzu-liyujiang.AndroidPicker:FilePicker:4.1.5'

留言页面为何点击留言没有任何反应?

留言页面留言消息是通过连接服务来发送留言消息,需要检查是否在会话聊天页面onDestroy方法内调用了断开连接disConnect方法。注意不要在会话聊天页面activity内手动调用disConnect断开连接方法。

4.13. 附加说明

4.13.1. 会话详情

字段名

字段类型

字段描述

备注

mainUniqueId

String

会话 ID

startTime

long

会话开始时间

status

int

当前会话状态

暂未使用

enterpriseId

String

企业 id

visitorId

String

访客 id

4.13.2. 在线状态

字段名

字段类型

字段描述

备注

STATUS_OUTLINE

int

不在线(会话结束)

STATUS_ROBOT

int

机器人在线

STATUS_ONLINE

int

人工座席

4.13.3. 消息类型

消息类型

objectName

描述

文本消息

TextMessage

文本消息(包含表情)

图片消息

ImageMessage

图片消息

语音消息

VoiceMessage

语音消息

视频消息

VideoMessage

视频消息

文件消息

FileMessage

文件消息

消息细分类型

参数名

参数值

说明

TEXT

1

文本消息

IMAGE

2

图片消息

FILE

3

文件消息

VIDEO

4

视频消息

ROBOT_HTML

5

机器人富文本消息

ROBOT_CHOOSE

6

机器人选项消息

VOICE

7

语音消息

KNOW_LEDGE

8

知识库文件消息

CARD

10

卡片消息

ROBOT_GROUP

14

机器人组合消息

ROBOT_ABOUT_QUESTION

15

机器人相关问题

ROBOT_GUESS_QUESTION

16

机器人猜你想问

ROBOT_COMMON_QUESTION

17

机器人常见问题

ROBOT_APPROX_QUESTION

18

机器人近似问题

ROBOT_COMMENT_QUESTION

19

机器人推荐问题

ROBOT_COMMON_QUESTION_CLASSIC

20

机器人常见问题(分类)

4.13.4. 消息发送状态

参数名

参数值

说明

NORMAL

1

正常

SENSITIVE_WORD

2

包含敏感词

REVOKE

3

已被撤回

4.13.5. 事件

参数名

参数值

说明

CHAT_MESSAGE

chatMessage

聊天消息

CHAT_BRIDGE

chatBridge

接通座席

CHAT_CLOSE

chatClose

关闭座席

CHAT_LEAVE_MESSAGE

chatLeaveMessage

留言消息

ROBOT_BRIDGE

robotBridge

接通机器人

CHAT_OPEN

chatOpen

会话开始

CHAT_QUEUE

chatQueue

进入排队

CHAT_LOCATION

chatLocation

排队位置播报

CHAT_INVESTIGATION

chatInvestigation

满意度

WITHDRAW

withdraw

座席撤回消息

CHAT_SWITCH

chatSwitch

分支节点

CHAT_LEADING_WORDS

chatLeadingWords

引导语

CHAT_INQUIRY

chatInquiry

询前表单

CHAT_OFFLINE

chatOffline

访客离线

CHAT_ONLINE

chatOnline

访客上线

CHAT_LEAVE_QUEUE

chatLeaveQueue

访客退出排队

CHAT_SWITCH_NEXT

chatSwitchNext

访客选择节点

CHAT_SUBMIT_INVESTIGATION

chatSubmitInvestigation

访客提交满意度

CHAT_SUBMIT_INQUIRY

chatSubmitInquiry

访客提交询前表单

4.13.6. 消息发送人类型

消息发送人类型封装在类 OnlineMessageSenderType 类中。

参数名

参数值

说明

ONLINE

1

座席

VISITOR

2

访客

SYSTEM

3

系统

ROBOT

4

机器人

NOTIFY

5

系统通知

4.13.7. 消息状态

系统支持的消息状态封装在 TMessageStatus 类中。

参数名

参数值

说明

MSG_STATUS_SEND_FAIL

-1

消息发送失败状态

MSG_STATUS_SENDING

0

消息发送中状态

MSG_STATUS_SEND_SUCCESS

1

消息已发送状态

4.13.8. 商品卡片消息

参数名

参数类型

说明

title

String

卡片消息标题

subTitle

String

卡片消息副标题

description

String

卡片消息的描述,例如商品的简单描述

price

String

商品卡片的价格

time

String

卡片消息的时间,例如订单的生成时间

img

String

卡片消息的图片地址,例如商品的图片地址

url

String

卡片消息详情,例如商品的详情页

subUrl

String

卡片消息详情副地址

buttonText

String

按钮文本内容

status

String

商品状态

extraInfo

HashMap<String, String>

额外信息

extraData

String

额外信息

5. iOS开发文档

5.1. 简介

欢迎使用“AICC”的在线客服移动端开发者工具套件(SDK)。本文针对iOS端使用做详细说明,通过SDK,可以在您的APP中快速集成访客端在线聊天的功能,以具备文本,图片、视频等类型消息收发及消息通知能力。 对接Demo已开源至GitHub: https://github.com/ti-net/clink-sdk

5.2. 环境要求

适配iOS 9.0以上

开发工具:Xcode 16+

5.3. 集成SDK

5.3.1. SDK文件说明

解压下载【iOS_SDK】,下载完为一个压缩包,包含TOSClientLib.framework、TOSClientKit.framework、TOSClient.bundle和相关说明文档。

文件名

说明

TOSClinetKit.framework

SDK UI Kit

TOSClient.bundle

图片资源文件 表情资源文件

TOSCilentLib.framework

SDK Lib

5.3.2. 自动导入

  1. cd 至项目根目录。

  2. 执行 vim podfile

  3. Podfile 文件中,添加以下内容

pod 'TOSClientKit'
  1. 执行 pod install。如果出现找不到相关版本的问题,可先执行 pod repo update ,再执行 pod install

5.3.3. 手动导入

把下载的TOSClinetKit.framework 、TOSClientLib.framework、TOSClient.bundle文件夹中的文件拖入你的工程里。 iOS_SDK 的实现,依赖了一些系统的框架,在开发应用时需要在工程里加入这些框架 ( TOSClientLib不包含UI界面,可根据接口自行开发功能 ) 。开发者首先点击工程右边的工程名,然后在工程名右边依次选择 TARGETS → BuiLd Phases → Link Binary With Libraries,展开 LinkBinary With Libraries 后点击展开后下面的 + 来添加下面的依赖项:

- TOSClientLib.framework(Embed & Sign)
- TOSClientKit.framework(Embed & Sign)
- TOSClient.bundle
- 另外需要增加libc++.tbd来支持c++环境

5.3.4. 配置权限

相机、麦克风、相册等权限

 Privacy - Camera Usage Description
 Privacy - Microphone Usage Description
 Privacy - Photo Library Additions Usage Description
 Privacy - Photo Library Usage Description

5.3.5. 注意事项

  • 在APP的 Info.plist 文件中增加 CFBundleDisplayName,value值为APP名称

  • 在会话页面中关闭键盘管理的第三方控件,如:IQKeyboardManager

  • 如有需要,可在跳转会话页面前设置会话页面的titleName属性,修改顶部标题

5.4. 初始化

5.4.1. 功能描述

客服SDK提供了一套完整的聊天界面,帮助开发者快速集成,并提供自定义接口,以实现定制需求。只需以下几行代码便可快速启动SDK应用。

  • 请在链接客服服务成功后再调起会话页面

5.4.2. 参数说明

参数

类型

必填

说明

accessId

NSString

访问标识(后台创建账号时获取,移动端唯一标识,对应座席端渠道ID)

accessSecret

NSString

访问秘钥(后台创建账号时获取,在座席端管理平台创建渠道时生成)

enterpriseId

NSString

企业号(后台创建账号时获取,企业ID)

apiUrl

NSString

平台apiUrl(接口环境平台 ex:https://octopus-api-1.vlink.cn/api/sdk/v1)

onlineUrl

NSString

在线业务onlineUrl(ex:https://chat-app-bj.clink.cn)

debug

BOOL

是否开启debug模式

advanceParams

NSDictionary

自定义可配参数,可为空

5.4.3. 代码示例

首先在AppDelegate中初始化SDK的Option
TOSInitOption * initOption = [[TOSInitOption alloc] initWithOption:YES
                             apiUrl:@"平台apiUrl"
                          onlineUrl:@"平台onlineUrl"
                           accessId:@"移动端唯一标识,对应座席端渠道ID"
                       accessSecret:@"在座席端管理平台创建渠道时生成"
                       enterpriseId:@"企业ID"
                      advanceParams:@{}];
[[TOSClientKit sharedTOSKit] initSDK:initOption];

5.5. 连接

5.5.1. 功能描述

连接在线客服,同一用户多次调用connect不会触发多次连接

5.5.2. 参数说明

参数

类型

必填

说明

visitorId

NSString

用户App的userID(为空的情况下,系统默认为UUID去除-号,不可包含中文或特殊符号,建议使用用户系统ID方便APP拓展功能)

nickname

NSString

昵称

headUrl

NSString

头像地址

mobile

NSString

手机号

advanceParams

NSDictionary

自定义拓展信息

customerFields

NSDictionary

客户资料自定义字段(2.0.5版本新增)

5.5.3. 代码示例

TOSConnectOption * connectOption = [[TOSConnectOption alloc] initWithOption:@"用户App的userID"
																	 nickname:@"昵称"
																	 headUrl:@"头像地址"
																	 mobile:@"手机号"
																	 advanceParams:@{}];

/// 自动更新客户资料(autoUpdate值为1才会触发更新)
connectOption.customerFields = @{
    @"autoUpdate" : @(1),
    @"电话" : @"010-12345678",
    @"性别" : @(1),
};

[[TOSClientKit sharedTOSKit] connect:connectOption success:^{

    } error:^(TIMConnectErrorCode errCode, NSString * _Nonnull errorDes) {

    } tokenIncorrect:^{

}];

5.6. 断开连接

5.6.1. 功能描述

断开连接在线客服,当用户退出登录时调用

5.6.2. 参数说明

参数

类型

必填

说明

isReceivePush

BOOL

是否需要推送

5.6.3. 代码示例

TOSDisConnectOption *disOption = [[TOSDisConnectOption alloc] initWithOption:YES];
[[TIMClient sharedTIMClient] disconnect:disOption success:^{

} error:^(TIMConnectErrorCode errCode, NSString * _Nonnull errorDes) {

}];

5.7. 会话相关

5.7.1. 获取会话信息

TOSSessionInfoModel 参数说明

参数

类型

必填

说明

enterpriseId

NSString

企业号

mainUniqueId

NSString

会话ID

startTime

NSNumber

时间戳

status

NSNumber

会话状态(新打开 1;路由中 2;排队中 3;接通座席 4;留言中 5;满意度 6;关闭 7;接通机器人 8;座席主动发起会话 9;)

visitorId

NSString

当前用户ID

TOSSessionInfoModel *model = [[TOSClientKit sharedTOSKit] getCurrentSessionInfo];

5.7.2. 集成会话页面

如果想要配置相关功能,需要继承TOSCustomerChatVC类

NS_ASSUME_NONNULL_BEGIN
@interface ChatInfoViewController : TOSCustomerChatVC

@end

5.7.3. 监听当前会话状态

/// TOSClientKit类
/**
 TIMKit消息接收的监听器

 @warning 如果您使用TIMKit,可以设置并实现此Delegate监听消息接收;
 */
-(void)setTIMKitMessageRecvDelegate:(id<TIMReceiveMessageDelegate>)delegate;

/// 示例:
[[TOSClientKit sharedTOSKit] setTIMKitMessageRecvDelegate:self];


/// TIMReceiveMessageDelegate
/**
 当前会话状态变更
 typedef NS_ENUM(NSUInteger, TinetChatStatusType) {
    TinetChatStatusTypeOutline,   // 客服或机器人未接入(默认状态)
    TinetChatStatusTypeRobot,     // 机器人在线
    TinetChatStatusTypeOnline,    // 客服在线
    TinetChatStatusTypeCloseChat, // 结束会话
}
 @param statusType  0: 不在线或结束会话 1: 机器人 2: 人工座席
 */
- (void)getCurrentOnlineStatus:(TinetChatStatusType)statusType;

5.7.4. 文本消息点击回调

  • 此方法需要在TOSCustomerChatVC类的子类中实现

typedef NS_ENUM(NSUInteger, TinetClickTextMessageEventType) {
    TinetClickEventTypeUrl,					      // 链接
    TinetClickEventTypeOrderNumber,				  // 订单号
    TinetClickEventTypePhone,		  	  	     // 手机号
    TinetClickCommodityCard,					 // 商品卡片
    TinetClickMiniProgramCard,					  // 小程序
	TinetClickLogisticsCard,					  // 物流卡片
    TinetClickOrderCard,                          //订单数据
};

/// 文本类型消息中关于链接、商品卡片、订单号和手机号的相关点击回调
/// @param eventType 事件类型
/// @param userInfo  详细信息
- (void)tinet_textMessageClickAction:(TinetClickTextMessageEventType)eventType userInfo:(NSDictionary *)userInfo;


/// 订单卡片点击回调需要做数据判断
- (void)tinet_textMessageClickAction:(TinetClickTextMessageEventType)eventType userInfo:(NSDictionary *)userInfo {
    [super tinet_textMessageClickAction:eventType userInfo:userInfo];

    if (eventType == TinetClickOrderCard) {
        NSLog(@"商品卡片点击后传递过来的数据");
        if ([userInfo objectForKey:@"content"]) {
            NSDictionary * content = userInfo[@"content"];
            /// 表示是订单抽屉的点击方法
            if ([content objectForKey:@"productModel"]) {

            }
            else {
                /// 说明是聊天页面的订单卡片的点击方法

            }
        }
    }
}

5.7.5. 会话状态监听

  • 此方法需要在TOSClientKitCustomerChatVC类的子类中实现

typedef NS_ENUM(NSUInteger, TinetChatStatusType) {
    TinetChatStatusTypeOutline,   // 客服或机器人未接入(默认状态)
    TinetChatStatusTypeRobot,     // 机器人在线
    TinetChatStatusTypeOnline,    // 客服在线
    TinetChatStatusTypeCloseChat,	// 结束会话
};

/// @param status  会话状态
/// 当前会话状态监听
- (void)chatStatusChanged:(TinetChatStatusType)status;

5.7.6. 获取未读数和最后一条消息

  /**
   未读消息获取
  */
	[[TOSClientKit sharedTOSKit] getUnreadMessage:^(NSString * _Nonnull lastMessage, NSInteger unreadCount) {
        NSLog(@"未读数:%@, 最后一条消息:%@", unreadCount, lastMessage);
    } withError:^(NSString * _Nonnull errorStr) {
        /// 错误提示
    }];

  // 未读数的更新  接收通知
  [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(unreadMessage:) name:KTOSClientLibLastMessageReceivedNotification object:nil];

5.7.7. 关闭会话

  /**
   关闭会话
  */
	TOSSessionInfoModel * infoModel = [TOSClientKit.sharedTOSKit getCurrentSessionInfo];
    [TOSClientKit.sharedTOSKit closeSessionMainUniqueId:infoModel.mainUniqueId
                                          withVisitorId:infoModel.visitorId succuess:^{
        NSLog(@"关闭会话成功");
    } error:^(TIMConnectErrorCode errCode, NSString * _Nonnull errorDes) {
        NSLog(@"错误信息:%@", errorDes);
    }];

关闭上一个会话

  /**
   关闭上一个会话
  */
    TOSSessionInfoModel * infoModel = [TOSClientKit.sharedTOSKit getCurrentSessionInfo];
	[[TOSClientKit sharedTOSKit] closeLastSession:infoModel.visitorId
                                         succuess:^{
        NSLog(@"关闭会话成功");
    } error:^(TIMConnectErrorCode errCode, NSString * _Nonnull errorDes) {
        NSLog(@"错误信息:%@", errorDes);
    }];

5.7.8. 发送文本消息

/// 发送文本消息,需要在TOSCustomerChatVC类内调用此方法
- (void)sendText:(NSString *)text;

5.7.9. 满意度评价

/// 弹出满意度评价。需要在TOSCustomerChatVC类内调用此方法,每位用户不论是否评价,只会弹出一次
- (void)investigationAlert;

5.8. 自定义UI配置

5.8.1. 配置UI类说明

/**
 * 快捷入口-工单留言的eventName
 */
static NSString * const TOS_EVENT_NAME_TICKET_MESSAGE_STATUS = @"kTOSTicketMessageStatus";

/**
 * 工单插件地址
 */
static NSString * const TOS_TICKET_PLUGIN_URL = @"ticketPluginUrl";

/**
 * 工单插件返回地址
 */
static NSString * const TOS_TICKET_PLUGIN_URL_RESULT = @"ticketPluginUrlResult";

/**
 * 客服留言数量提示开关(默认:true)
 */
static NSString * const TOS_COMMENT_COUNT_ENABLE = @"commentCountEnable";

/**
 * 仅查询和展示访客创建的工单(默认:false)
 */
static NSString * const TOS_VISITOR_CREATED_TICKET = @"visitorCreatedTicket";

/**
 * 没有客服留言时不展示该快捷入口(默认:false)
 */
static NSString * const TOS_NO_COMMENT_COUNT_HIDE_QUICK_ENTRY = @"noCommentCountHideQuickEntry";

/**
 * 留言未读数数量
 */
static NSString * const TOS_STAFF_COMMENT_TOTAL_COUNT = @"staffCommentTotalCount";

/**
 * 应用阶段(
 * TOSAppLicationStageType_OFF:关闭,
 * TOSAppLicationStageType_Robot:机器人,
 * TOSAppLicationStageType_Robot:人工,
 * TOSAppLicationStageType_Human:机器人和人工)
 */
static NSString * const TOS_APPLICATION_STAGE = @"applicationStage";

// 关闭
static NSString * const TOSAppLicationStageType_OFF = @"TOSAppLicationStageType_OFF";

// 机器人
static NSString * const TOSAppLicationStageType_Robot = @"TOSAppLicationStageType_Robot";

// 人工
static NSString * const TOSAppLicationStageType_Human = @"TOSAppLicationStageType_Human";

// 机器人和人工 默认
static NSString * const TOSAppLicationStageType_Both = @"TOSAppLicationStageType_Both";


/**
 气泡的圆角类型枚举
 */
typedef NS_ENUM(NSInteger, BubbleCornerType) {
    /// 全切圆角
    BubbleCornerTypeAll             =   0,
    /// 左边上面是圆角
    BubbleCornerTypeLeftTop         =   1,
    /// 左边下面是圆角
    BubbleCornerTypeLeftBottom      =   2,
    /// 左边两个都是圆角
    BubbleCornerTypeLeft            =   3,
    /// 右边上面是圆角
    BubbleCornerTypeRightTop        =   4,
    /// 右边下面是圆角
    BubbleCornerTypeRightBottom     =   5,
    /// 右边两个都是圆角
    BubbleCornerTypeRight           =   6,
    /// 上面两个都是圆角
    BubbleCornerTypeTop             =   7,
    /// 下面两个都是圆角
    BubbleCornerTypeBottom          =   8,
    /// 左上方不是圆角
    BubbleCornerTypeNoLeftTop       =   9,
    /// 右上方不是圆角
    BubbleCornerTypeNoRightTop      =   10,
    /// 左下方不是圆角
    BubbleCornerTypeNoLeftBottom    =   11,
    /// 右下方不是圆角
    BubbleCornerTypeNoRightBottom   =   12,
    /// 不切圆角
    BubbleCornerTypeNormal          =   13,
};

/**
 在点击退出页面按钮时,满意度的弹出模式
 */
typedef NS_ENUM(NSInteger, SatisfactionShowModel) {
    /// 只在首次弹出
    SatisfactionShowModelFirstTimePopup          =   0,
    /// 每次都弹出
    SatisfactionShowModelEveryTimePopup          =   1
};

/// 快捷输入model的事件枚举类型
typedef NS_ENUM(NSInteger, TOSQuickEntryEventType) {
    /// 不做任何操作
    TOSQuickEntryEventTypeNormal            =   0,
    /// 链接外跳
    TOSQuickEntryEventTypeLink              =   1,
    /// 满意度评价
    TOSQuickEntryEventTypeSatisfaction      =   2,
    /// 结束会话
    TOSQuickEntryEventTypeCloseChat         =   3,
    /// 消息发送
    TOSQuickEntryEventTypeSendText          =   4,
    /// 订单卡片
    TOSQuickEntryEventTypeOrderCard         =   5,
    /// 工单插件
    TOSQuickEntryEventTypeTicketPlugin      =   6,
    /// 转人工事件
    TOSQuickEntryEventTypeArtificial        =   7,
    /// 自定义事件
    TOSQuickEntryEventTypeCustom            =   8,

};

/// 正则model
@interface TOSRegularModel : NSObject

/// 正则表达式
@property (nonatomic, copy, nullable) NSString                * regular;

/// 高亮颜色
@property (nonatomic, strong, nullable) UIColor                * highlightColor;


@end

  /// 快捷入口model
@interface TOSQuickEntryModel : TIMLibBaseModel

/// 快捷入口名称
@property (nonatomic, copy) NSString                *name;

/// 快捷入口值
@property (nonatomic, copy) NSString                *value;

/// 快捷入口的事件类型
@property (nonatomic, assign) TOSQuickEntryEventType                type;

/// 快捷事件名称(该属性在v2.4.0版本后弃用)
@property (nonatomic, copy, nonnull) NSString       *eventName;

/// 快捷入口事件动态配置参数集合
@property (nonatomic, strong) NSMutableDictionary          *dynamicConfigParameters;

/// 快捷入口拉起页面的数据参数集合
@property (nonatomic, strong) NSMutableDictionary                * params;

//+ (TOSQuickEntryModel *)getChatLeaveMessageStatusWithTicketPluginUrl:(NSString *)ticketPluginUrl;

@end

+ (TOSKitCustomInfo *)shareCustomInfo;

/// 快速入口Item的圆角弧度
@property (nonatomic, assign) CGFloat               quickEntryItem_cornerRadius;

/// 发送方气泡的颜色
@property (nonatomic, strong) UIColor               *senderBubble_backGround;
/// 发送方气泡的圆角弧度
@property (nonatomic, assign) CGFloat               senderBubble_cornerRadius;

/// 头像的圆角弧度
@property (nonatomic, assign) CGFloat               portrait_cornerRadius;

/// 聊天背景颜色
@property (nonatomic, strong) UIColor               *chat_backGround;

/// 快速入口Item的背景颜色
@property (nonatomic, strong) UIColor               *quickEntryItem_backgroundColor;

/// 接收方气泡的颜色
@property (nonatomic, strong) UIColor               *receiveBubble_backGround;
/// 接收方气泡的圆角弧度
@property (nonatomic, assign) CGFloat               receiveBubble_cornerRadius;

/// 快速入口底部的背景颜色
@property (nonatomic, strong) UIColor               *quickEntryBottom_backgroundColor;

/// 接收方字体颜色
@property (nonatomic, strong) UIColor               *receiveText_Color;

/// 发送方字体颜色
@property (nonatomic, strong) UIColor               *senderText_Color;

/// 聊天底部输入中的语音按钮控制
@property (nonatomic, assign) BOOL                  ChatBox_voiceButton_enable;

/// 聊天底部输入中文本输入框的暗文设置
@property (nonatomic, strong) NSString              *ChatBox_textview_placeholder;

/// 聊天底部背景颜色
@property (nonatomic, strong) UIColor               *ChatBox_backGroundColor;

/// 聊天底部中线条颜色
@property (nonatomic, strong) UIColor               *ChatBox_lineColor;

/// 聊天中显示的时间字体颜色
@property (nonatomic, strong) UIColor               *Chat_time_textColor;

/// 启用或关闭客服或机器人昵称的显示
@property (nonatomic, assign) BOOL                  Chat_tosRobotName_show;

/// 启用或关闭访客昵称的显示
@property (nonatomic, assign) BOOL                  Chat_visitorName_show;

/// 启用或关闭客服昵称(机器人昵称)UI区域的显示
@property (nonatomic, assign) BOOL                  Chat_tosRobotName_enable;

/// 启用或关闭访客昵称UI区域的显示
@property (nonatomic, assign) BOOL                  Chat_visitorName_enable;

/// 启用或关闭客服和机器人头像UI区域的显示
@property (nonatomic, assign) BOOL                  Chat_tosRobot_portrait_enable;

/// 启用或关闭访客头像UI区域的显示
@property (nonatomic, assign) BOOL                  Chat_visitor_portrait_enable;

/// 相册展示导航栏中的文字颜色
@property (nonatomic, strong) UIColor               *imagePicker_barItemTextColor;

/// 相册展示导航栏中的背景颜色
@property (nonatomic, strong) UIColor               *imagePicker_naviBgColor;

/// 吐司提示气泡背景颜色
@property (nonatomic, strong) UIColor               *Toast_backGroundColor;

/// 吐司提示中文字颜色
@property (nonatomic, strong) UIColor               *Toast_textColor;

/// 语音按钮中文字颜色
@property (nonatomic, strong) UIColor               *VoiceButton_textColor;

/// 语音按钮中文字高亮颜色
@property (nonatomic, strong) UIColor               *VoiceButton_highlight_textColor;

/// 商品卡片-待发送  发送按钮背景颜色
@property (nonatomic, strong) UIColor               *CommodityCard_sendBtn_backgroundColor;

/// 商品卡片-待发送  发送按钮文字颜色
@property (nonatomic, strong) UIColor               *CommodityCard_sendBtn_textColor;

/// 商品卡片-待发送  标题文字颜色
@property (nonatomic, strong) UIColor               *CommodityCard_title_textColor;

/// 商品卡片-待发送  描述文字颜色
@property (nonatomic, strong) UIColor *CommodityCard_descriptions_textColor;

/// 商品卡片-待发送  商品价格文字颜色
@property (nonatomic, strong) UIColor               *CommodityCard_price_textColor;

/// 商品卡片-详情  订单号: xxx 文字颜色
@property (nonatomic, strong) UIColor               *CommodityCardDetails_orderId_sender_textColor;
@property (nonatomic, strong) UIColor               *CommodityCardDetails_orderId_receive_textColor;

/// 商品卡片-详情  时间文字颜色
@property (nonatomic, strong) UIColor               *CommodityCardDetails_time_sender_textColor;
@property (nonatomic, strong) UIColor               *CommodityCardDetails_time_receive_textColor;

/// 商品卡片-详情  标题文字颜色
@property (nonatomic, strong) UIColor               *CommodityCardDetails_title_sender_textColor;
@property (nonatomic, strong) UIColor               *CommodityCardDetails_title_receive_textColor;

/// 商品卡片-详情  商品描述文字颜色
@property (nonatomic, strong) UIColor               *CommodityCardDetails_description_sender_textColor;
@property (nonatomic, strong) UIColor               *CommodityCardDetails_description_receive_textColor;

/// 商品卡片-详情  商品价格文字颜色
@property (nonatomic, strong) UIColor               *CommodityCardDetails_price_sender_textColor;
@property (nonatomic, strong) UIColor               *CommodityCardDetails_price_receive_textColor;

/// 商品卡片-详情  到货状态:xxx 文字颜色
@property (nonatomic, strong) UIColor               *CommodityCardDetails_transportStatus_sender_textColor;
@property (nonatomic, strong) UIColor               *CommodityCardDetails_transportStatus_receive_textColor;

/// 设置聊天页面的标题名字
@property(nonatomic, copy) NSString                 *titleName;

/// 接入号名称
@property(nonatomic, copy) NSString                 *appName;

/// 快捷入口的数据
@property (nonatomic, strong) NSArray            <TOSQuickEntryModel *> *quickEntryAllItems;

/// 商品卡片配置数据
@property (nonatomic, strong, nullable) TOSClientKitCommodityCardOption *commodityCardOption;


/// 气泡的最大宽度
@property (nonatomic, assign) CGFloat                bubbleMaxWidth;

/// 头像的大小,图像是正方形只需要设置宽度就可以了  default:40
@property (nonatomic, assign) CGFloat                headWidth;

/// 头像距屏幕边缘的距离 default:10
@property (nonatomic, assign) CGFloat                headMargin;
/// 头像距离气泡的距离 default:8.0
@property (nonatomic, assign) CGFloat                headToBubble;

/// 每条消息的间距 default:10.0
@property (nonatomic, assign) CGFloat                cellMargin;

/// 气泡的内间距 default:10.0
@property (nonatomic, assign) CGFloat                bubblePadding;

/// 聊天底部输入中的表情按钮控制 default:YES
@property (nonatomic, assign) BOOL                   chatBox_emotionButton_enable;

/// 聊天底部输入中的更多按钮控制 default:YES
@property (nonatomic, assign) BOOL                   chatBox_moreButton_enable;

/// 聊天底部的整体高度 default:56.0
@property (nonatomic, assign) CGFloat                chatBox_Height;

/// 聊天底部文本框距上下方的间距 default: 8.0
@property (nonatomic, assign) CGFloat                chatBox_textView_topAndBottomMargin;

/// 聊天底部文本框的初始高度,只读属性,想要改变该值需要配合另外两个属性 (⚠️该值的计算公式是:chatBox_Height - chatBox_textView_topAndBottomMargin*2 得出)
@property (nonatomic, assign, readonly) CGFloat      chatBox_textView_height;

/// 聊天底部最左侧的item距左侧间距 default: 10.0
@property (nonatomic, assign) CGFloat                chatBox_itemLeftPadding;

/// 聊天底部最右侧的item距右侧间距 default: 10.0
@property (nonatomic, assign) CGFloat                chatBox_itemRightPadding;

/// 聊天底部每个item之间的间距 default: 10.0
@property (nonatomic, assign) CGFloat                chatBox_itemSpacing;

/// 聊天底部的每个item距离底部的间距(去除安全区域)defalut: 14
@property (nonatomic, assign) CGFloat                chatBox_itemBottomSpacing;

/// 聊天底部的输入框字体 default: [UIFont fontWithName:@"PingFangSC-Regular" size:16.0]
@property (nonatomic, strong) UIFont                 *chatBox_textView_font;

/// 聊天底部的输入框内边距 default: UIEdgeInsetsMake(10, 10, 10, 10)
@property (nonatomic, assign) UIEdgeInsets           chatBox_textView_textContainerInset;

/// 聊天底部的输入框字体颜色 default:262626
@property (nonatomic, strong) UIColor                *chatBox_textView_textColor;

/// 聊天底部的输入框背景颜色 default:whiteColor
@property (nonatomic, strong) UIColor                *chatBox_textView_backgroundColor;

/// 聊天底部文本框的圆角值 default:8.0
@property (nonatomic, assign) CGFloat                chatBox_textView_cornerRadius;

/// 聊天底部文本框的边框颜色 default: clearColor
@property (nonatomic, strong) UIColor                *chatBox_textView_borderColor;

/// 聊天底部文本框的边框宽度 default: 0.5
@property (nonatomic, assign) CGFloat                chatBox_textView_borderWidth;

/// 聊天底部文本框的最多显示行数 default:5
@property (nonatomic, assign) NSInteger              chatBox_textView_maxRows;

/// 默认提示文字距离输入框左边的距离 default: 10.0
@property (nonatomic, assign) CGFloat                chatBox_textView_placeholderMargin;

/// 聊天底部文本框的暗文的字体颜色 default: grayColor
@property (nonatomic, strong) UIColor                *chatBox_textview_placeholderTextColor;

/// 录制语音的初始文本 default: 按住 说话
@property (nonatomic, copy) NSString                 *chatBox_talkText;

/// 录制语音的按中文本 default: 松开 结束
@property (nonatomic, copy) NSString                 *chatBox_talkHighlightedText;

/// 录制语音的按钮字体 default: [UIFont boldSystemFontOfSize:16.0f]
@property (nonatomic, strong) UIFont                 *chatBox_talkFont;

/// 录制语音的按钮边框 defalut: 0.5
@property (nonatomic, assign) CGFloat                chatBox_talk_borderWidth;

/// 录制语音的按钮边框颜色 defalut:E8E8E8
@property (nonatomic, strong) UIColor                *chatBox_talk_borderColor;
/// 输入框右侧的发送按钮开关 default: NO (发送按钮设置为YES时,chatBox_emotionButton_enable和chatBox_moreButton_enable 值需要为NO,且chatBox_sendButton_enable为YES,才会显示发送按钮)
@property (nonatomic, assign) BOOL                   chatBox_sendButton_enable;

/// 录制语音的按钮背景颜色 defalut: clearColor
@property (nonatomic, strong) UIColor                *chatBox_talk_backgroundColor;

/// 录制语音的按钮按住背景颜色 defalut: B2B2B2
@property (nonatomic, strong) UIColor                *chatBox_talk_backgroundHighlightedColor;

/// 录制语音的按钮按住字体颜色 defalut: 434343
@property (nonatomic, strong) UIColor                *chatBox_talk_fontHighlightedColor;

/// 输入框右侧的发送按钮大小 defatult: 60 : chatBox_textView_height
@property (nonatomic, assign) CGSize                 chatBox_sendButtonSize;

/// 输入框右侧的发送按钮 只需要设置按钮的内容,样式需要设置其他属性(chatBox_sendButtonSize/chatBox_sendButton_cornerRadius/chatBox_sendButton_borderColor/chatBox_sendButton_HighlightedColor)
@property (nonatomic, strong) UIButton               *chatBox_sendButton;

/// 输入框右侧的发送按钮的圆角 default: 10.0
@property (nonatomic, assign) CGFloat                chatBox_sendButton_cornerRadius;

/// 输入框右侧的发送按钮边框默认颜色,即输入框没有值时发送按钮的边框颜色 default: UIColor.grayColor
@property (nonatomic, strong) UIColor                *chatBox_sendButton_borderColor;

/// 输入框右侧的发送按钮高亮的颜色,即输入框有值时发送按钮的边框颜色 default: UIColor.blackColor
@property (nonatomic, strong) UIColor                *chatBox_sendButton_HighlightedColor;

/// 输入框右侧的发送按钮边框宽度 default: 1
@property (nonatomic, assign) CGFloat                chatBox_sendButton_borderWidth;

/// 重新发送按钮的大小 default: 20:20
@property (nonatomic, assign) CGSize                 resendButtonSize;

/// 重新发送按钮,设置后会显示这个按钮,不需要设置大小,大小由 resendButtonSize 控制。default: 红色感叹号的图片样式
@property (nonatomic, strong) UIButton               *resendButton;

/// 重新发送按钮距离气泡的间距 default: 4.0
@property (nonatomic, assign) CGFloat                resendToBubblePadding;

/**
 自定义cell的注册事件
 要在页面加载前进行赋值,key:事件名,value:对应的cell。
 示例
 @{
    @"TypeEventQueue" :  [CustomTableViewCell class]
 }
 然后在页面实现- (UITableViewCell *)customTableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath withModel:(nonnull TIMMessageModel *)model;方法
 自定义的cell需要继承于 TOSChatCustomBaseTableViewCell
 */
@property (nonatomic, strong) NSMutableDictionary   *customCellRegister;

/// 发送侧语音按钮的语音图标距离气泡右侧的X值 default: 22.0
@property (nonatomic, assign) CGFloat               chat_send_voiceImageToBubbleRightX;

/// 发送侧语音按钮的语音时长距离气泡左侧的X值 default: 10.0
@property (nonatomic, assign) CGFloat               chat_send_voiceLabelToBubbleLeftX;

/// 发送侧语音按钮的语音图标距离气泡顶部的Y值 default: 10.0
@property (nonatomic, assign) CGFloat               chat_send_voiceImageToBubbleTop;

/// 发送侧语音按钮的语音时长距离气泡顶部的Y值 default: 10.0
@property (nonatomic, assign) CGFloat               chat_send_voiceLabelToBubbleTop;

/// 语音消息的最低宽度 default: 60
@property (nonatomic, assign) CGFloat               chat_voiceMinWidth;

/// 语音录制view,需要设置位置及大小
@property (nonatomic, strong) UIView                *chatBox_voiceRecordView;

/// 语音取消录制view,需要设置位置及大小
@property (nonatomic, strong) UIView                *chatBox_voiceCancelRecordView;

/// 语音录制时间过短的提示view,需要设置位置及大小
@property (nonatomic, strong) UIView                *chatBox_voiceRecordSoShortView;

/// 语音录制时间过短的提示view显示时间 default: 2.0
@property (nonatomic, assign) CGFloat               chatBox_voiceRecordSoShortTime;

/// 表情面板的删除按钮的默认图片
@property (nonatomic, strong) UIImage               *chatBox_emotion_deleteButton_image;

/// 表情面板的删除按钮的高亮图片
@property (nonatomic, strong) UIImage               *chatBox_emotion_deleteButton_highlightedImage;

/// 表情面板的删除按钮背景色 default:whiteColor
@property (nonatomic, strong) UIColor               *chatBox_emotion_deleteButtonBackGroundColor;

/// 表情面板的删除按钮大小 default: CGSizeMake(49, 38)
@property (nonatomic, assign) CGSize                chatBox_emotion_deleteButtonSize;

/// 删除按钮位置的 (x,y) 的偏移,默认为 CGPointZero
@property (nonatomic, assign) CGPoint               chatBox_emotion_deleteButtonOffset;

/// 表情面板的删除按钮的圆角 default: 4.0
@property (nonatomic, assign) CGFloat               chatBox_emotion_deleteButton_cornerRadius;

/// 表情面板的删除按钮的calayer
@property (nonatomic, strong) CALayer               *chatBox_emotion_deleteCALayer;

/// 表情面板的发送按钮文案 default: 发送
@property (nonatomic, copy) NSString                *chatBox_emotion_sendButton_text;

/// 表情面板的发送按钮文案 default: 发送
@property (nonatomic, copy) NSString                *chatBox_emotion_sendButton_textHighlighted;

/// 表情面板的发送按钮大小 default: CGSizeMake(49, 38)
@property (nonatomic, assign) CGSize                chatBox_emotion_sendButtonSize;

/// 表情面板的发送按钮背景色 default: 4385FF
@property (nonatomic, strong) UIColor               *chatBox_emotion_sendButtonBackGroundColor;

/// 发送按钮布局时的外边距,相对于控件右下角。仅right/bottom有效,默认为{0, 0, 16, 16}
@property(nonatomic, assign) UIEdgeInsets           chatBox_emotion_sendButtonMargins;

/// 表情面板的发送按钮的圆角 default: 4.0
@property (nonatomic, assign) CGFloat               chatBox_emotion_sendButton_cornerRadius;

/// 表情面板的发送按钮字体 default: [UIFont fontWithName:@"PingFangSC-Regular" size:14.f]
@property (nonatomic, strong) UIFont                *chatBox_emotion_sendButtonFont;

/// 表情面板的发送按钮默认的文字颜色,即输入框有值时发送按钮的文字颜色 default: UIColor.whiteColor
@property (nonatomic, strong) UIColor               *chatBox_emotion_sendButton_textColor;

/// 表情面板的发送按钮高亮的文字颜色,即输入框有值时发送按钮的文字颜色 default: UIColor.whiteColor
@property (nonatomic, strong) UIColor               *chatBox_emotion_sendButton_textHighlightedColor;

/// 表情面板的发送按钮的calayer
@property (nonatomic, strong) CALayer               *chatBox_emotion_sendCALayer;

/// 分页控件距离底部的间距,default: 22.0
@property(nonatomic, assign) CGFloat                chatBox_emotion_pageControlMarginBottom;

/// 输入区域上方的线条高度 default: 1
@property (nonatomic, assign) CGFloat               chatBox_topLineHeight;

/// 是否在删除和发送按钮下方显示表情 default: NO
@property (nonatomic, assign) BOOL                  chatBox_emotion_functionItemDisplayed;

/// 输入区域item的宽度 default: 28
@property (nonatomic, assign) CGFloat               chatBox_Item_Width;

/// 最后一条消息距离输入区域的间距 default: 0
@property (nonatomic, assign) CGFloat               lastMessage_spacing;

/// 昵称和气泡之间的间距 default: 0
@property (nonatomic, assign) CGFloat               nickNameToBubbleSpacing;

/// 气泡的圆角类型以【发送方】为标准,【接收方】自动对称。 defalut: 全切圆角 BubbleCornerTypeAll (BubbleCornerTypeNormal 时 senderBubble_cornerRadius/receiveBubble_cornerRadius无效)
@property (nonatomic, assign) BubbleCornerType      chatBubble_CornerType;

/// 系统消息的背景颜色 default: FFFFFF, 0.65
@property (nonatomic, strong) UIColor               *chatMessage_system_backgroundColor;

/// 系统消息的字体 default: [UIFont systemFontOfSize:11.0]
@property (nonatomic, strong) UIFont                *chatMessage_system_textFont;

/// 系统消息的字体颜色 default: 595959
@property (nonatomic, strong) UIColor               *chatMessage_system_textColor;

/// 系统消息的对齐方式 default: NSTextAlignmentCenter
@property (nonatomic, assign) NSTextAlignment       chatMessage_system_textAlignment;

/// 系统消息的内容背景圆角 default: 4.0
@property (nonatomic, assign) CGFloat               chatMessage_system_cornerRadius;

/// 系统消息的Label是否居中显示 default: YES (若设置为NO,就根据chatMessage_system_edgeInsets的值进行布局)
@property (nonatomic, assign) BOOL                  chatMessage_system_center;

/// 系统消息的文本控件距离屏幕上下左右间距 default: UIEdgeInsetsMake(5, 20, 5, 20)
@property (nonatomic, assign) UIEdgeInsets          chatMessage_system_edgeInsets;

/// 系统消息的文本控件上下左右内间距 default: UIEdgeInsetsMake(0, 0, 0, 0)
@property (nonatomic, assign) UIEdgeInsets          chatMessage_system_labelTextEdgeInsets;

/// 表情面板的背景颜色 default: F3F6F9
@property (nonatomic, strong) UIColor               *chatBox_emotion_backgroundColor;

/// 表情面板顶部的分割线颜色 default: E8E8E8
@property (nonatomic, strong) UIColor               *chatBox_emotion_topLineColor;

/// 表情面板顶部的分割线高度 default: 1
@property (nonatomic, assign) CGFloat               chatBox_emotion_topLineHeight;

/// 更多面板的背景颜色 default: 237, 237, 246, 1
@property (nonatomic, strong) UIColor               *chatBox_more_backgroundColor;

/// 更多面板的item图片圆角配置 default: 12.0f (最大设置28,超过28会造成图片畸形,超过28的数值按28取值)
@property (nonatomic, assign) CGFloat               chatBox_more_itemCornerRadius;

/// 更多面板的item的背景颜色 default: whiteColor
@property (nonatomic, strong) UIColor               *chatBox_more_itemBackgroundColor;

/// 更多面板的item的图片UIEdgeInsets  default: UIEdgeInsetsMake(12, 12, 12, 12)
@property (nonatomic, assign) UIEdgeInsets          chatBox_more_itemImageEdgeInsets;

/// 更多面板的item的文字颜色 default: 595959
@property (nonatomic, strong) UIColor               *chatBox_more_itemTextColor;

/// 更多面板的顶部分割线颜色 default: E8E8E8
@property (nonatomic, strong) UIColor               *chatBox_more_topLineColor;

/// 更多面板的顶部分割线高度 default: 1.0
@property (nonatomic, assign) CGFloat               chatBox_more_topLineHeight;

/// 访客昵称字体 default: [UIFont systemFontOfSize:12.0]
@property (nonatomic, strong) UIFont                *chatMessage_visitorName_font;

/// 访客昵称字体颜色 default: 595959
@property (nonatomic, strong) UIColor               *chatMessage_visitorName_textColor;

/// 机器人/座席字体 default: [UIFont systemFontOfSize:12.0]
@property (nonatomic, strong) UIFont                *chatMessage_tosRobotName_font;

/// 机器人/座席字体颜色 default: 595959
@property (nonatomic, strong) UIColor               *chatMessage_tosRobotName_textColor;

/// 访客气泡文本字体 default: [UIFont fontWithName:@"PingFangSC-Regular" size:16.0]
@property (nonatomic, strong) UIFont                *chatMessage_visitorText_font;

/// 机器人/座席字体 default: [UIFont fontWithName:@"PingFangSC-Regular" size:16.0]
@property (nonatomic, strong) UIFont                *chatMessage_tosRobotText_font;

/// 输入区域文本框的光标颜色 default: blueColor
@property (nonatomic, strong) UIColor               *chatBox_textView_tintColor;

/// 机器人组合消息标题字体 default: [UIFont fontWithName:@"PingFangSC-Regular" size:16.0]
@property (nonatomic, strong) UIFont                *chatMessage_tosRobotCombination_titleFont;

/// 机器人组合消息副标题字体颜色 default: FAAD14
@property (nonatomic, strong) UIColor               *chatMessage_tosRobotCombination_titleColor;

/// 机器人组合消息副标题字体 default: [UIFont fontWithName:@"PingFangSC-Regular" size:16.0]
@property (nonatomic, strong) UIFont                *chatMessage_tosRobotCombination_subTitleFont;

/// 机器人组合消息的字体 default: [UIFont fontWithName:@"PingFangSC-Regular" size:14.f]
@property (nonatomic, strong) UIFont                *chatMessage_tosRobotCombination_hotSubIssueTitleFont;

/// 机器人组合消息分类选项卡的字体 default: [UIFont fontWithName:@"PingFangSC-Regular" size:14.0f]
@property (nonatomic, strong) UIFont                *chatMessage_tosRobotCombination_segmentFont;

/// 机器人组合消息分类选项卡未选择的字体颜色 default: 141223
@property (nonatomic, strong) UIColor               *chatMessage_tosRobotCombination_segmentUnselectedTextColor;

/// 机器人组合消息分类选项卡的字体颜色 default: 4385FF
@property (nonatomic, strong) UIColor               *chatMessage_tosRobotCombination_segmentTextColor;

/// 机器人组合消息分类选项卡的下划线颜色 default: 000000, 0.04f
@property (nonatomic, strong) UIColor               *chatMessage_tosRobotCombination_segmentLineColor;

/// 机器人组合消息的字体颜色 default: 262626
@property (nonatomic, strong) UIColor               *chatMessage_tosRobotCombination_hotSubIssueTitleColor;

/// 机器人组合消息的间距 default: 10.0f
@property (nonatomic, assign) CGFloat               chatMessage_tosRobotCombination_hotSubIssusSpacing;

/// 机器人组合消息的换一换按钮是否展示的数量限制 default: 5 (超过5条会显示换一换按钮)
@property (nonatomic, assign) NSInteger             chatMessage_tosRobotCombination_showRefreshNumber;

/// 机器人组合消息的换一换按钮的图片 default: robotCell_hotIssueRefresh
@property (nonatomic, strong) UIImage               *chatMessage_tosRobotCombination_showRefreshImage;

/// 机器人组合消息的换一换按钮的文字内容 default: 换一换
@property (nonatomic, copy) NSString                *chatMessage_tosRobotCombination_showRefreshTitle;

/// 机器人组合消息的换一换按钮的文字颜色 default: 4385FF
@property (nonatomic, strong) UIColor               *chatMessage_tosRobotCombination_showRefreshTitleColor;

/// 机器人组合消息的换一换按钮的文字字体 default: [UIFont fontWithName:@"PingFangSC-Regular" size:12.f]
@property (nonatomic, strong) UIFont                *chatMessage_tosRobotCombination_showRefreshTitleFont;

/// 会话状态为机器人时是否隐藏语音按钮 default: NO
@property (nonatomic, assign) BOOL                   robotHiddenVoice;

/// 满意度评价的弹出样式 : 固定底部弹出
@property (nonatomic, assign, readonly) BOOL         satisfactionViewPopupMode;

/// 在点击退出页面按钮时,满意度的弹出模式
@property (nonatomic, assign) SatisfactionShowModel  satisfactionViewShowModel;

/// 列表消息中的满意度评价按钮颜色-未选中 default: 0x4385FF
@property (nonatomic, strong) UIColor                *satisfaction_evaluate_normal;

/// 列表消息中的满意度评价按钮颜色-选中 default: 0xF0F0F0
@property (nonatomic, strong) UIColor                *satisfaction_evaluate_selected;

/// 列表消息中的满意度评价按钮标题颜色-未选中 default: 0xFFFFFF
@property (nonatomic, strong) UIColor                *satisfaction_evaluate_titleColor_normal;

/// 列表消息中的满意度评价按钮标题颜色-选中 default: 0xBFBFBF
@property (nonatomic, strong) UIColor                *satisfaction_evaluate_titleColor_selected;


/// 满意度弹窗的评价提交按钮颜色-未选中 default: 0x4385FF
@property (nonatomic, strong) UIColor                *satisfaction_evaluate_submit;

/// 满意度弹窗的评价提交按钮标题颜色-未选中 default: 0xFFFFFF
@property (nonatomic, strong) UIColor                *satisfaction_evaluate_submit_titleColor;

/**
 * 电话正则
 * urlRegualr的highlightColor默认为:4385FF
 * telRegular的regular默认为:
 * @"(0\\d{2,3}-?\\d{7,8})|(\\(0\\d{2,3}\\)\\d{7,8})|1[34578]\\d{9}|400-?\\d{3}-?\\d{4}|\\+?\\d{2}1[34578]\\d{9}"
 */
@property (nonatomic, strong, nullable) TOSRegularModel     *telRegular;

/// 订单号正则默认为null
@property (nonatomic, strong, nullable) TOSRegularModel     *orderNumberRegular;

/**
 * 链接正则
 * urlRegualr的highlightColor默认为:4385FF
 * urlRegular的regular默认为:
 * @"(((http[s]{0,1}|ftp)://[a-zA-Z0-9\\.\\-]+\\.([a-zA-Z]{2,4})(:\\d+)?(/[a-zA-Z0-9\\.\\-~!@#$%^&*+?:_/=<>]*)?)|(www.[a-zA-Z0-9\\.\\-]+\\.([a-zA-Z]{2,4})(:\\d+)?(/[a-zA-Z0-9\\.\\-~!@#$%^&*+?:_/=<>]*)?)|(((http[s]{0,1}|ftp)://|)((?:(?:25[0-5]|2[0-4]\\d|((1\\d{2})|([1-9]?\\d)))\\.){3}(?:25[0-5]|2[0-4]\\d|((1\\d{2})|([1-9]?\\d))))(:\\d+)?(/[a-zA-Z0-9\\.\\-~!@#$%^&*+?:_/=<>]*)?))"
 */
@property (nonatomic, strong, nullable) TOSRegularModel     *urlRegular;

/// 只使用本地上传头像(v2.0.5+开始废弃)
@property (nonatomic, assign) BOOL                   enableLocalAvatar NS_UNAVAILABLE;

/// 访客默认头像
@property (nonatomic, strong) UIImage                *visitorDefaultAvatar;

/// 机器人默认头像
@property (nonatomic, strong) UIImage                *robotDefaultAvatar;

/// 客服默认头像
@property (nonatomic, strong) UIImage                *customerServiceDefaultAvatar;

/// 系统默认头像
@property (nonatomic, strong) UIImage                *systemDefaultAvatar;

/// 是否开启点赞点踩功能    YES:开启   NO:关闭  默认为NO
@property (nonatomic, assign) BOOL isOpenHelpfulFeature;

/// 是否展示点踩内容输入框
@property (nonatomic, assign) BOOL isShowUnHelpfulContent;

/// 是否必填点踩内容
@property (nonatomic, assign) BOOL isRequiredUnHelpfulContent;

/// 设置点踩输入框提示安暗文
@property (nonatomic, copy)   NSString               *setUnHelpfulContentHint;

/// 设置点踩标签
@property (nonatomic, strong) NSArray    <NSString *>*setUnHelpfulTagList;

/// 订单的配置model
@property (nonatomic, strong) TOSKitOrderDrawerHelper                * orderDrawer;

示例代码:
[TOSKitCustomInfo shareCustomInfo].senderBubble_backGround = [UIColor redColor];

5.8.2. 订单配置

@interface TOSKitOrderDrawerHelper : NSObject

/// 抽屉页面圆角 默认:20.0f
@property (nonatomic, assign) CGFloat                drawerCorner;

/// 店铺图片的圆角 默认:10.0f
@property (nonatomic, assign) CGFloat                logoCorner;

/// 订单列表的背景颜色 默认:#F5F5F5
@property (nonatomic, strong) UIColor                * listBackGroundColor;

/// 单个订单的背景颜色 默认:#FFFFFF
@property (nonatomic, strong) UIColor                * backGroundColor;

/// 单个订单的父视图圆角 默认:8.0f
@property (nonatomic, assign) CGFloat                orderCorner;

/// 商品图标的圆角值 默认:6.0f
@property (nonatomic, assign) CGFloat                productIconCorner;

@end

5.8.3. 商品卡片

商品卡片数据传递

在会话加载时携带商品卡片信息,需要进行商品卡片的数据配置

 // TOSClientKitCommodityCardOption 详情见 商品卡片参数说明
  TOSClientKitCommodityCardOption *option = [[TOSClientKitCommodityCardOption alloc] init];
  option.subTitle = @"HUAWEI Mate 60 Pro 海思 麒麟 9000s 5000万超感知徕卡三摄 100倍数字变焦";
  option.descriptions = @"这是商品描述,遥遥领先遥遥领先遥遥领先遥遥领先遥遥领先遥遥领先";
  option.price = @"100.99";
  option.time = @"2022/05/24 18:32";
  option.img = @"https://pro-fd.zol-img.com.cn/t_s300x300c5/g7/M00/04/0A/ChMkK2Ttx0iIfxQ1AADOoMpjc8MAAURKgH08wUAAM64551.jpg";
  option.status = @"已到货";
  option.url = @"https://hellojoy.jd.com/";
  option.title = @"华为P40";
  option.subUrl = @"https://p4psearch.1688.com/";
  option.buttonText = @"buttonText";
  option.extraData = @[@{@"name": @"订单状态", @"value": @"1234324"}];
  option.extraInfo =
  @[@{@"name": @"订单号", @"value": @"1234567890"},
  @{@"name": @"产品类型", @"value": @"电子产品"},
  @{@"name": @"师傅"   , @"value": @"金师傅"},
  @{@"name": @"服务地区", @"value": @"北京市"},
  @{@"name": @"服务"   , @"value": @"满意"},
  @{@"name": @"师傅电话", @"value": @"12345678900"},
  @{@"name": @"订单状态", @"value": @"已完成"}];

 [TOSKitCustomInfo shareCustomInfo].commodityCardOption = option;
发送商品卡片
/// 发送商品卡片消息
- (void)sendCard:(TOSClientKitCommodityCardOption *)userInfo;

/// 下面是传参示例
TOSClientKitCommodityCardOption *option = [[TOSClientKitCommodityCardOption alloc] init];
option.subTitle = @"HUAWEI Mate 60 Pro 海思 麒麟 9000s 5000万超感知徕卡三摄 100倍数字变焦";
option.descriptions = @"这是商品描述,遥遥领先遥遥领先遥遥领先遥遥领先遥遥领先遥遥领先";
option.price = @"100.99";
option.time = @"2022/05/24 18:32";
option.img = @"https://pro-fd.zol-img.com.cn/t_s300x300c5/g7/M00/04/0A/ChMkK2Ttx0iIfxQ1AADOoMpjc8MAAURKgH08wUAAM64551.jpg";
option.status = @"已到货";
option.url = @"https://hellojoy.jd.com/";
option.title = @"华为P40";
option.subUrl = @"https://p4psearch.1688.com/";
option.buttonText = @"buttonText";
option.extraData = @[@{@"name": @"订单状态", @"value": @"1234324"}];
option.extraInfo =
  @[@{@"name": @"订单号", @"value": @"1234567890"}, //如需在商品卡片左上角显示订单号,则需配置此项,名称统一为”订单号“
  @{@"name": @"产品类型", @"value": @"电子产品"},
  @{@"name": @"师傅"   , @"value": @"金师傅"},
  @{@"name": @"服务地区", @"value": @"北京市"},
  @{@"name": @"服务"   , @"value": @"满意"},
  @{@"name": @"师傅电话", @"value": @"12345678900"},
  @{@"name": @"订单状态", @"value": @"已完成"}];

[self sendCard:option];

5.8.4. 快捷入口配置

NSMutableArray <TOSQuickEntryModel *>*quickEntryAllItems = [NSMutableArray array];

TOSQuickEntryModel *model = [[TOSQuickEntryModel alloc] init];
model.name = @"快捷入口的展示名称";
model.value = @"快捷入口值";
model.eventName = @"快捷事件名称";
model.dynamicConfigParameters = [NSMutableDictionary dictionary];//快捷入口事件动态配置参数集合
[quickEntryAllItems addObject:model];

// 快接入口留言模块示例
TOSQuickEntryModel *entryModel = [TOSQuickEntryModel getChatLeaveMessageStatusWithTicketPluginUrl:@"TicketPluginUrl"];
// 客服留言数量提示开关(默认:true)
entryModel.dynamicConfigParameters[TOS_COMMENT_COUNT_ENABLE] = [NSNumber numberWithBool:true];
// 仅查询和展示访客创建的工单(默认:false)
entryModel.dynamicConfigParameters[TOS_VISITOR_CREATED_TICKET] = [NSNumber numberWithBool:false];
// 没有客服留言时不展示该快捷入口(默认:false)
entryModel.dynamicConfigParameters[TOS_NO_COMMENT_COUNT_HIDE_QUICK_ENTRY] = [NSNumber numberWithBool:false];
/**
	* 应用阶段(
	* TOSAppLicationStageType_OFF:关闭,
	* TOSAppLicationStageType_Robot:机器人,
	* TOSAppLicationStageType_Robot:人工,
	* TOSAppLicationStageType_Human:机器人和人工,默认:10)
*/
entryModel.dynamicConfigParameters[TOS_APPLICATION_STAGE] = TOSAppLicationStageType_Both;
[quickEntryAllItems addObject:entryModel];

// quickEntryAllItems需要在页面跳转前设置
[TOSKitCustomInfo shareCustomInfo].quickEntryAllItems = quickEntryAllItems;

/// 快捷入口的点击回调(需要在TOSCustomerChatVC的子类实现这个方法)
- (void)quickEntryItemDidTouchModel:(TOSQuickEntryModel *)model;

/// 快捷入口-自定义转人工按钮
/// 发送转人工事件
/// @param messageStr 自定义文本消息
- (void)sendTransferToHumanMessage:(NSString *)messageStr;

/// 快接入口数据更新方法(需要在TOSCustomerChatVC的子类调用这个方法)
- (void)updateSessionWindowQuickEntrys:(NSArray <TOSQuickEntryModel *>*)quickEntryAllItems;

// 示例:
/// 快捷入口的点击回调(需要在TOSCustomerChatVC的子类实现这个方法)
- (void)quickEntryItemDidTouchModel:(TOSQuickEntryModel *)model {
  if ([model.eventName isEqualToString:@"快捷事件名称"]) {
    [self sendTransferToHumanMessage:model.value];
	}
}

// 示例:
/// 当前会话状态监听
- (void)chatStatusChanged:(TinetChatStatusType)status {
    [super chatStatusChanged:status];
    switch (status) {
            case TinetChatStatusTypeOutline: {  // 不在线或结束会话
                NSLog(@"触发了不在线或结束会话回调");
                [self updateSessionWindowQuickEntrys:@[]];
            }
                break;
            case TinetChatStatusTypeRobot: {    // 机器人在线
                NSLog(@"触发了机器人在线回调");
                TOSQuickEntryModel *model = [[TOSQuickEntryModel alloc] init];
                model.name = @"转人工";
                model.value = @"转人工";
                model.eventName = @"TransferToHuman";
                model.dynamicConfigParameters = [NSMutableDictionary dictionary];//快捷入口事件动态配置参数集合
                [self updateSessionWindowQuickEntrys:@[model]];
            }
                break;
            case TinetChatStatusTypeOnline: {   // 客服在线
                NSLog(@"触发了客服在线回调");
                TOSQuickEntryModel *model = [[TOSQuickEntryModel alloc] init];
                model.name = @"满意度评价";
                model.value = @"满意度评价";
                model.eventName = @"SatisfactionEvaluation";
                model.dynamicConfigParameters = [NSMutableDictionary dictionary];//快捷入口事件动态配置参数集合
                [self updateSessionWindowQuickEntrys:@[model]];
            }
                break;
            default:
                break;
        }
}

5.8.5. 结束会话配置

/// 在TOSCustomerChatVC 页面重写该方法可自定义会话结束后的UI
/// 结束会话UI事件
- (void)closeViewEvent;

5.8.6. 重写消息样式

/// cell要实现这个方法,要在实现该方法前,配置 [TOSKitCustomInfo shareCustomInfo].customCellRegister
- (TOSChatCustomBaseTableViewCell *)customTableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath withModel:(TIMMessageModel *)model;

5.8.7. 刷新组件

/// 顶部刷新控件, 重写这个组件的回调方法要调用 loadMoreMessage 方法,(block回调需要注意循环引用问题)
@property (nonatomic, strong) TIMRefreshHeader                * customRefreshHeader;

/// refresh组件回调需要调用的方法
- (void)loadMoreMessage;

5.8.8. 列表滑动高度

/// 当前列表的滑动高度,子类重写该方法可以获取当前列表的滑动高度
/// - Parameters:
///   - contentOffset: 当前列表的滑动范围
///   - messageHeight: 消息列表的高度
- (void)tableViewContentOffset:(CGPoint)contentOffset withMessageHeight:(CGFloat)messageHeight;

5.8.9. 扩展面板配置

TOSKitExtendBoardItemModel类说明

+ (TOSKitChatBoxExtendBoard *)shareChatBoxExtendBoard;
/// 扩展项
@property (nonatomic, strong) NSArray <TOSKitExtendBoardItemModel *>*allItems;

/// 示例代码
TOSKitExtendBoardItemModel *model1 = [[TOSKitExtendBoardItemModel alloc] init];
model1.type = TOSChatBoxExtendBoardTypePhotos;	//除自定义类型外,其他类型不填即为默认UI

TOSKitExtendBoardItemModel *model2 = [[TOSKitExtendBoardItemModel alloc] init];
model2.type = TOSChatBoxExtendBoardTypeTakePicture;

TOSKitExtendBoardItemModel *model3 = [[TOSKitExtendBoardItemModel alloc] init];
model3.type = TOSChatBoxExtendBoardTypeCustom;//类型
model3.title = @"按钮3"; //标题
model3.image = @"image";//图片名称,图片大小:32*32/64*64/96*96
model3.index = 3;       //下标
[TOSKitChatBoxExtendBoard shareChatBoxExtendBoard].allItems = @[model1,model2,model3];

/// 扩展面板,自定义按钮事件 (需要在子类实现这个方法)
- (void)didClinkCustomExtendBoardItemAction:(TOSKitExtendBoardItemModel *)item;

TOSKitExtendBoardItemModel参数说明

参数名

参数值

说明

title

NSString

标题

image

NSString

图片名

index

NSInteger

扩展项的唯一标示符

type

TOSChatBoxExtendBoardType

枚举类型,除自定义类型外,其他类型不填即为默认UI

dynamicConfigParameters

NSMutableDictionary

自定义参数

TOSChatBoxExtendBoardType参数说明

参数名

参数值

说明

TOSChatBoxExtendBoardTypePhotos

0

相册

TOSChatBoxExtendBoardTypeTakePicture

1

相机

TOSChatBoxExtendBoardTypeCustomFile

2

文件

TOSChatBoxExtendBoardTypeArtificial

3

转人工

TOSChatBoxExtendBoardTypeCloseChat

4

结束会话

TOSChatBoxExtendBoardTypeCustom

5

自定义

TOSChatBoxExtendBoardTypeCustomFileApp

6

手机系统的文件App

TOSChatBoxExtendBoardTypeOrder

7

订单卡片

TOSChatBoxExtendBoardTypeLink

8

链接

TOSChatBoxExtendBoardTypeSatisfaction

9

满意度评价

5.9. 其他

5.9.1. 获取版本号

// 获取版本号
[TOSClientKit getSDKVersion];

5.10. 更新说明

SDK 2.4.3 版本更新说明[2025-01-14]
Changed
- 优化订单抽屉功能
- 优化链接跳转的url编码功能
- 优化表情键盘UI

SDK 2.4.2 版本更新说明[2025-01-09]
Changed
- 抽屉列表的商品点击数据透传优化,包含订单信息和点击的商品信息
- 发送订单消息bottomButtonConfig为nil会造成客户侧的扩展拦截掉,优化了逻辑

SDK 2.4.1 版本更新说明[2025-01-07]
Changed
- 抽屉列表的商品点击数据透传
- 快捷入口的点击逻辑优化
- 订单发送bottomButtonConfig无值时默认传nil
- 订单的表头信息通过数据权重优先展示订单状态信息

SDK 2.4.0 版本更新说明[2024-12-30]
Changed
- 表单留言支持路由导航中留言节点设置的返回
- 知识库关联问交互和展示问题修改
- 支持机器人专题模式热点问题
- 修复快捷入口工单留言无法根据后台接口展示隐藏问题
- 优化isCloseSession字段的状态修改逻辑

SDK 2.3.3 版本更新说明[2024-12-27]
Changed
- 解决订单不展示问题
- 快捷入口和更多面板的订单事件匹配

SDK 2.3.2 版本更新说明[2024-12-19]
Added
- 新增订单抽屉页面
- 新增订单消息的收发
Changed
- 商品卡片,extraData字段类型优化
- 完善点赞点踩增加滚动至底部功能
- 完善在线工单留言点击返回到会话功能
- 快捷入口和更多面板支持后端配置
- 完善解决转人工出来慢问题
- 解决a标签不展示问题

SDK 2.1.0 版本更新说明[2024-11-21]
Changed
- 优化点踩备注复用问题
- 优化待发送卡片的金额过长的显示问题
- 优化快捷入口的UI展示问题
- 优化转人工排队时回调会话状态问题
- 优化默认头像加载逻辑

SDK 2.0.5 版本更新说明[2024-11-05]
Added
- 支持服务进度快捷入口
- 支持自动创建更新客户资料功能
Changed
- 优化进入会话页面头像闪动问题
- 优化底部商品卡片展示逻辑
- 优化第三方库YYKit中的命名
- 修复智能图谱中推荐回复的消息未换行的问题
- 修改获取满意度弹窗的回调逻辑
- 修复用户点击快捷入口满意度评价时头像问题
- 优化关闭卡片的变更UI放在主线程处理
- 优化会话结束事件逻辑
- 修复首次点击相册选中视频发送问题

SDK 2.0.2 版本更新说明[2024-09-12]
Added
- 点赞点踩功能
- 文件发送功能
- 满意度自动弹出功能
Changed
- 优化点赞点踩偶现跳动问题
- 修改排队的显示样式

5.11. 常见问题

  1. 进入页面为何显示对话已结束,无法发送文字?

    这是后台的功能配置问题,需要有机器人或者在线的客服,才能发送消息。
  2. 如何解决客服分组问题?

    如需切换客服组,可先结束正在进行中的会话,然后根据后台配置修改TOSConnectOption类的advanceParams附加字段,在其中传入对应键值对后重新进入会话页面。
    [[TOSClientKit sharedTOSKit] closeSession:^{
        [[TOSClientKit sharedTOSKit] setAdvanceParams:@{@"qno": @"0510"}];
        ChatInfoViewController *chatVC = [[ChatInfoViewController alloc] init];
        chatVC.titleName = @"客服";
        chatVC.appName = @"客服SDK";
        self.hidesBottomBarWhenPushed  = YES;
        [self.navigationController pushViewController:chatVC animated:YES];
    } error:^(TIMConnectErrorCode errCode, NSString * _Nonnull errorDes) {
    }];
  3. 关于UserId不能传入特殊字符的问题

    // 传入可能会出现的特殊字符
    NSString *charaters = @"?!@#$^&%*+,:;='\"`<>()[]{}/\\| 《》";
    NSCharacterSet *set = [[NSCharacterSet characterSetWithCharactersInString:charaters] invertedSet];
    NSString *userId = [@"需要编码的字符串" stringByAddingPercentEncodingWithAllowedCharacters:set];
  4. 商品卡片、物流卡片如何隐藏不需要的控件?

    需要在对应的字段传入对应类型的空值,如:@""、@[]、@{}
  5. 关于cocoapods内搜不到SDK的最新版本问题

    需要在终端执行pod update

5.12. 附加说明

会话状态监听

参数名

参数值

说明

TinetChatStatusTypeOutline

0

客服或机器人未接入(默认状态)

TinetChatStatusTypeRobot

1

机器人在线

TinetChatStatusTypeOnline

2

客服在线

TinetChatStatusTypeCloseChat

3

结束会话

TOSClientKitCommodityCardOption 商品卡片参数说明

参数名

参数类型

说明

subTitle

NSString

卡片消息副标题

descriptions

NSString

卡片消息的描述,例如商品的简单描述

price

NSString

商品卡片的价格

time

NSString

卡片消息的时间,例如订单的生成时间

img

NSString

卡片消息的图片地址,例如商品的图片地址

status

NSString

商品状态

extraInfo

NSDictionary

额外信息

title

NSString

标题

subUrl

NSString

卡片副标题点击跳转链接,商品卡片的点击事件获取到的链接

url

NSString

卡片点击跳转链接(废弃)

buttonText

NSString

发送按钮文本内容(废弃)

extraData

NSString

附加字段 Tips:2.3.1版本修改了字段类型(从NSString改成了id类型)),示例:@[@{@"name": @"订单状态", @"value": @"1234324"},]

6. uniapp开发文档

6.1. 简介

欢迎使用“AICC”的在线客服移动端开发者工具插件(plugin)。本文针对uniapp端使用做详细说明,通过引入本插件,可以在您的APP中快速集成访客端在线聊天的功能,以具备文本、图片、视频等类型消息收发。

6.2. 环境准备

建议使用最新的 HBuilderX 编辑器 。

iOS 9.0 或以上版本且支持音视频的 iOS 设备,暂不支持模拟器。

Android 版本不低于 5.0 且支持音视频的 Android 设备,暂不支持模拟器。建议使用 Android 5.0 (SDK API Level 21)及以上版本。

6.3. 下载插件

6.3.1. 云端依赖插件

购买 uni-app 原生插件 登录 uni 原生插件市场,并访问 AICC-TOSClientKit 插件,在插件详情页中购买(免费插件也可以在插件市场0元购)。购买后才能够云端打包使用插件。购买插件时请选择正确的 appid,以及绑定正确包名。

使用自定义基座打包 uni 原生插件 (请使用真机运行自定义基座) 使用 uni 原生插件必须先提交云端打包才能生效,购买插件后在应用的 manifest.json 页面的 App原生插件配置 项下单击选择云端插件,选择(AICC在线客服插件)。

6.3.2. 下载离线插件包

下载 uni-app 原生插件 登录 uni 原生插件市场,并访问 AICC-TOSClientKit 插件,在插件详情页中点击下载,将插件压缩包下载至本地。

将原生插件配置到uni-app项目的“nativeplugins”下,还需要在manifest.json文件的“App原生插件配置”项下点击“选择本地插件”,在列表中选择需要打包生效的插件。

6.4. 引入并使用插件

6.4.1. 在 vue 页面中引入原生插件

使用 uni.requireNativePlugin 的 API 在 vue 页面中引入原生插件,参数为插件的 ID。如下:

uni.requireNativePlugin("AICC-TOSClientKit");

6.4.2. 使用插件

初始化
参数说明

参数

类型

必填

说明

accessId

String

访问标识

accessSecret

String

访问秘钥

enterpriseId

String

企业号

apiUrl

String

平台apiUrl

onlineUrl

String

平台onlineUrl

debug

boolean

是否开启debug模式

advanceParams

Map<String, Object>

自定义可配参数,可为空

代码示例如下:

				tOSClientKit.initPlugin({
						'accessId': '',//会话接入id
						'accessSecret': '',//会话接入Secret
						'enterpriseId': ,//企业id
						'apiUrl': '',//aip地址
						'onlineUrl': '',//在线地址
						'debug': true,//是否开启debug模式
						'advanceParams':{}//高级配置参数
					},
					(ret) => {
						if (ret.code == 0) {
							// 成功
						} else {
							//失败
						}
					})
进入在线客服会话页面
参数说明

参数

类型

必填

说明

visitorId

String

用户App的userID(为空的情况下,系统默认为UUID去除-号,不可包含中文或特殊符号,建议使用用户系统ID方便APP拓展功能)

nickname

String

昵称

headUrl

String

头像地址

mobile

String

手机号

advanceParams

Map<String, Object>

自定义可配参数

代码示例如下:

				tOSClientKit.enterSession({
						'nickname': 'uniapp体验用户名',//用户昵称
						'headUrl': 'https://img2.baidu.com/it/u=1229468480,2938819374&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500',//用户头像
						'mobile': '135xxxx9206'//手机号
					},
					(ret) => {
						if (ret.code == 0) {
							// 成功
						} else {
							//失败
						}
					})