1. 使用说明
欢迎使用“AICC”的在线客服模块的移动端开发者工具套件(SDK)。我们分别为Android和iOS平台提供SDK,通过SDK,可以在您的APP中快速集成在线客服的各种功能。
2. 集成流程
下图展示在app中实现接入在线客服SDK的基本流程:
3. 创建App接入渠道
3.3. 新增路由导航
左侧内边栏中找到 路由导航
3.4. 完成新增App接入渠道
新增App接入渠道并可配设置操作区域、扩展面板设置后,如下图
其中快捷入口(最多设置30个)设置功能,其中根据不同的事件有不同的配置,如下图
其中扩展面板(最多设置8个)设置功能,其中根据不同的事件有不同的配置,如下图
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);
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.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.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. 自动导入
-
cd
至项目根目录。 -
执行
vim podfile
。 -
在
Podfile
文件中,添加以下内容
pod 'TOSClientKit'
-
执行
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. 注意事项
|
5.4. 初始化
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. 文本消息点击回调
|
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. 会话状态监听
|
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. 常见问题
-
进入页面为何显示对话已结束,无法发送文字?
这是后台的功能配置问题,需要有机器人或者在线的客服,才能发送消息。
-
如何解决客服分组问题?
如需切换客服组,可先结束正在进行中的会话,然后根据后台配置修改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) { }];
-
关于UserId不能传入特殊字符的问题
// 传入可能会出现的特殊字符 NSString *charaters = @"?!@#$^&%*+,:;='\"`<>()[]{}/\\| 《》"; NSCharacterSet *set = [[NSCharacterSet characterSetWithCharactersInString:charaters] invertedSet]; NSString *userId = [@"需要编码的字符串" stringByAddingPercentEncodingWithAllowedCharacters:set];
-
商品卡片、物流卡片如何隐藏不需要的控件?
需要在对应的字段传入对应类型的空值,如:@""、@[]、@{}
-
关于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 {
//失败
}
})