解决手机端解码报错的问题
This commit is contained in:
parent
088891bdbb
commit
9b6a3c9bce
33
package-lock.json
generated
33
package-lock.json
generated
@ -9,6 +9,7 @@
|
|||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"abort-controller": "^3.0.0",
|
"abort-controller": "^3.0.0",
|
||||||
|
"buffer": "^6.0.3",
|
||||||
"mqtt": "^3.0.0",
|
"mqtt": "^3.0.0",
|
||||||
"vue": "^3.5.21"
|
"vue": "^3.5.21"
|
||||||
}
|
}
|
||||||
@ -220,6 +221,30 @@
|
|||||||
"readable-stream": "^3.4.0"
|
"readable-stream": "^3.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/bl/node_modules/buffer": {
|
||||||
|
"version": "5.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
|
||||||
|
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "consulting",
|
||||||
|
"url": "https://feross.org/support"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"base64-js": "^1.3.1",
|
||||||
|
"ieee754": "^1.1.13"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/bl/node_modules/readable-stream": {
|
"node_modules/bl/node_modules/readable-stream": {
|
||||||
"version": "3.6.2",
|
"version": "3.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
|
||||||
@ -245,9 +270,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/buffer": {
|
"node_modules/buffer": {
|
||||||
"version": "5.7.1",
|
"version": "6.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
|
"resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
|
||||||
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
|
"integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "github",
|
"type": "github",
|
||||||
@ -265,7 +290,7 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"base64-js": "^1.3.1",
|
"base64-js": "^1.3.1",
|
||||||
"ieee754": "^1.1.13"
|
"ieee754": "^1.2.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/buffer-from": {
|
"node_modules/buffer-from": {
|
||||||
|
|||||||
@ -18,6 +18,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"abort-controller": "^3.0.0",
|
"abort-controller": "^3.0.0",
|
||||||
|
"buffer": "^6.0.3",
|
||||||
"mqtt": "^3.0.0",
|
"mqtt": "^3.0.0",
|
||||||
"vue": "^3.5.21"
|
"vue": "^3.5.21"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
<template>
|
packages/customerService/index/index<template>
|
||||||
<view class="chat-container">
|
<view class="chat-container">
|
||||||
<!-- 聊天头部 -->
|
<!-- 聊天头部 -->
|
||||||
<view :style="{ paddingTop: top + 'px', height: localHeight + 'px' }" class="chat-header">
|
<view :style="{ paddingTop: top + 'px', height: localHeight + 'px' }" class="chat-header">
|
||||||
@ -15,8 +15,8 @@
|
|||||||
<view v-if="connectingStatus" class="connecting-status">{{ connectingStatus }}</view>
|
<view v-if="connectingStatus" class="connecting-status">{{ connectingStatus }}</view>
|
||||||
|
|
||||||
<!-- 聊天消息区域 -->
|
<!-- 聊天消息区域 -->
|
||||||
<scroll-view :scroll-into-view="scrollToView" class="chat-messages" scroll-y="true"
|
<scroll-view :scroll-into-view="scrollToView" class="chat-messages" scroll-y="true" @scrolltoupper="loadMoreHistory"
|
||||||
@scrolltoupper="loadMoreHistory" @scrolltolower="loadMoreHistory" lower-threshold="100" upper-threshold="100">
|
@scrolltolower="loadMoreHistory" lower-threshold="100" upper-threshold="100">
|
||||||
<!-- 加载历史消息提示 -->
|
<!-- 加载历史消息提示 -->
|
||||||
<view v-if="isLoadingHistory" class="message-time">加载历史消息...</view>
|
<view v-if="isLoadingHistory" class="message-time">加载历史消息...</view>
|
||||||
|
|
||||||
@ -45,8 +45,8 @@
|
|||||||
<view class="input-container">
|
<view class="input-container">
|
||||||
<textarea v-model="inputMessage" :adjust-position="true" class="message-input" placeholder="请输入消息..."
|
<textarea v-model="inputMessage" :adjust-position="true" class="message-input" placeholder="请输入消息..."
|
||||||
@confirm="sendMessage" @input="handleInput" auto-height hold-keyboard="true"
|
@confirm="sendMessage" @input="handleInput" auto-height hold-keyboard="true"
|
||||||
enable-keyboard-accessory-view="true" cursor-spacing="10" maxlength="500"
|
enable-keyboard-accessory-view="true" cursor-spacing="10" maxlength="500" @focus="onInputFocus"
|
||||||
@focus="onInputFocus" @blur="onInputBlur"></textarea>
|
@blur="onInputBlur"></textarea>
|
||||||
<button :disabled="!canSend || !client || !isConnected" class="send-btn" @tap="sendMessage">
|
<button :disabled="!canSend || !client || !isConnected" class="send-btn" @tap="sendMessage">
|
||||||
发送
|
发送
|
||||||
</button>
|
</button>
|
||||||
@ -61,7 +61,7 @@ import { apiArr } from '@/api/customerService'
|
|||||||
import mqttTool from '@/utils/mqtt'
|
import mqttTool from '@/utils/mqtt'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data(){
|
data() {
|
||||||
return {
|
return {
|
||||||
localHeight: '',
|
localHeight: '',
|
||||||
top: '',
|
top: '',
|
||||||
@ -105,14 +105,14 @@ export default {
|
|||||||
scrollToBottomFlag: false
|
scrollToBottomFlag: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onLoad(options){
|
onLoad(options) {
|
||||||
const meun = menuButtonInfo()
|
const meun = menuButtonInfo()
|
||||||
this.top = meun.top
|
this.top = meun.top
|
||||||
this.localHeight = meun.height
|
this.localHeight = meun.height
|
||||||
// 获取聊天对象信息
|
// 获取聊天对象信息
|
||||||
if (options.item) {
|
if (options.item) {
|
||||||
this.chatTarget = JSON.parse(options.item)
|
this.chatTarget = JSON.parse(options.item)
|
||||||
this.chatTarget.title = `客服${ this.chatTarget.employee_name }`
|
this.chatTarget.title = `客服${this.chatTarget.employee_name}`
|
||||||
}
|
}
|
||||||
// 初始化MQTT连接
|
// 初始化MQTT连接
|
||||||
this.initChat()
|
this.initChat()
|
||||||
@ -120,10 +120,10 @@ export default {
|
|||||||
// 初始化用户头像
|
// 初始化用户头像
|
||||||
this.userAvatar = picUrl + uni.getStorageSync('headPhoto')
|
this.userAvatar = picUrl + uni.getStorageSync('headPhoto')
|
||||||
},
|
},
|
||||||
onShow(){
|
onShow() {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async connect(){
|
async connect() {
|
||||||
this.client = null
|
this.client = null
|
||||||
const options = {
|
const options = {
|
||||||
clientId: this.selfClientId
|
clientId: this.selfClientId
|
||||||
@ -154,9 +154,10 @@ export default {
|
|||||||
|
|
||||||
await this.subscribe()
|
await this.subscribe()
|
||||||
this.client.on('message', (topic, message) => {
|
this.client.on('message', (topic, message) => {
|
||||||
let de = new TextDecoder('utf-8')
|
const msgStr = Buffer.from(message).toString('utf8'); // 二进制转UTF-8字符串
|
||||||
let msg = de.decode(message)
|
const msg = JSON.parse(msgStr); // 后续解析逻辑不变
|
||||||
let jsMsg = JSON.parse(msg)
|
|
||||||
|
let jsMsg = msg // 直接使用已解析的对象,无需再次解析
|
||||||
console.log('收到消息', topic, msg)
|
console.log('收到消息', topic, msg)
|
||||||
if (jsMsg.send_client === this.selfClientId || jsMsg.receive_client === this.selfClientId) {
|
if (jsMsg.send_client === this.selfClientId || jsMsg.receive_client === this.selfClientId) {
|
||||||
console.log('接收或发送人是我')
|
console.log('接收或发送人是我')
|
||||||
@ -174,7 +175,7 @@ export default {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
async subscribe(){
|
async subscribe() {
|
||||||
if (this.isConnected && this.client) {
|
if (this.isConnected && this.client) {
|
||||||
this.client.subscribe('contact/message/receive_msg', { qos: 0 }, (err) => {
|
this.client.subscribe('contact/message/receive_msg', { qos: 0 }, (err) => {
|
||||||
if (!err) {
|
if (!err) {
|
||||||
@ -191,7 +192,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 初始化聊天
|
// 初始化聊天
|
||||||
async initChat(){
|
async initChat() {
|
||||||
try {
|
try {
|
||||||
// 显示连接状态
|
// 显示连接状态
|
||||||
this.connectingStatus = '正在连接客服...'
|
this.connectingStatus = '正在连接客服...'
|
||||||
@ -212,7 +213,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// 获取MQTT连接配置
|
// 获取MQTT连接配置
|
||||||
async getMqttConfig(){
|
async getMqttConfig() {
|
||||||
try {
|
try {
|
||||||
// 如果没有已创建的实例或clientId,则通过API获取
|
// 如果没有已创建的实例或clientId,则通过API获取
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
@ -244,7 +245,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// MQTT断开连接回调
|
// MQTT断开连接回调
|
||||||
onDisconnect(packet){
|
onDisconnect(packet) {
|
||||||
console.log('MQTT连接断开', packet)
|
console.log('MQTT连接断开', packet)
|
||||||
this.isConnected = false
|
this.isConnected = false
|
||||||
this.client = null
|
this.client = null
|
||||||
@ -263,7 +264,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// 加载历史消息
|
// 加载历史消息
|
||||||
async loadHistoryMessages(){
|
async loadHistoryMessages() {
|
||||||
if (!this.hasMoreHistory || this.isLoadingHistory) {
|
if (!this.hasMoreHistory || this.isLoadingHistory) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -319,14 +320,14 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// 加载更多历史消息
|
// 加载更多历史消息
|
||||||
loadMoreHistory(){
|
loadMoreHistory() {
|
||||||
if (!this.isLoadingHistory && this.hasMoreHistory) {
|
if (!this.isLoadingHistory && this.hasMoreHistory) {
|
||||||
this.loadHistoryMessages()
|
this.loadHistoryMessages()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// 发送消息
|
// 发送消息
|
||||||
sendMessage(){
|
sendMessage() {
|
||||||
const content = this.inputMessage.trim()
|
const content = this.inputMessage.trim()
|
||||||
console.log('发送消息', content)
|
console.log('发送消息', content)
|
||||||
if (!content || !this.client || !this.isConnected) return
|
if (!content || !this.client || !this.isConnected) return
|
||||||
@ -362,7 +363,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// 处理输入事件
|
// 处理输入事件
|
||||||
handleInput(){
|
handleInput() {
|
||||||
this.canSend = this.inputMessage.trim().length > 0
|
this.canSend = this.inputMessage.trim().length > 0
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -382,7 +383,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// 是否需要显示时间分割线
|
// 是否需要显示时间分割线
|
||||||
needShowTime(index){
|
needShowTime(index) {
|
||||||
if (index === 0) return true
|
if (index === 0) return true
|
||||||
|
|
||||||
const currentMsg = this.messages[index]
|
const currentMsg = this.messages[index]
|
||||||
@ -393,28 +394,28 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// 格式化时间
|
// 格式化时间
|
||||||
formatTime(time){
|
formatTime(time) {
|
||||||
const date = new Date(time)
|
const date = new Date(time)
|
||||||
const hours = date.getHours().toString().padStart(2, '0')
|
const hours = date.getHours().toString().padStart(2, '0')
|
||||||
const minutes = date.getMinutes().toString().padStart(2, '0')
|
const minutes = date.getMinutes().toString().padStart(2, '0')
|
||||||
|
|
||||||
return `${ hours }:${ minutes }`
|
return `${hours}:${minutes}`
|
||||||
},
|
},
|
||||||
|
|
||||||
// 滚动到底部
|
// 滚动到底部
|
||||||
scrollToBottom(){
|
scrollToBottom() {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.scrollToView = 'msg-' + (this.messages.length - 1)
|
this.scrollToView = 'msg-' + (this.messages.length - 1)
|
||||||
}, 100)
|
}, 100)
|
||||||
},
|
},
|
||||||
|
|
||||||
// 返回上一页
|
// 返回上一页
|
||||||
goBack(){
|
goBack() {
|
||||||
uni.navigateBack()
|
uni.navigateBack()
|
||||||
},
|
},
|
||||||
|
|
||||||
// 启动心跳包 - 增强版:添加错误处理和状态检查
|
// 启动心跳包 - 增强版:添加错误处理和状态检查
|
||||||
startKeepalive(){
|
startKeepalive() {
|
||||||
// 停止之前的定时器
|
// 停止之前的定时器
|
||||||
this.stopKeepalive()
|
this.stopKeepalive()
|
||||||
|
|
||||||
@ -449,7 +450,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// 停止心跳包
|
// 停止心跳包
|
||||||
stopKeepalive(){
|
stopKeepalive() {
|
||||||
if (this.keepaliveTimer) {
|
if (this.keepaliveTimer) {
|
||||||
clearInterval(this.keepaliveTimer)
|
clearInterval(this.keepaliveTimer)
|
||||||
this.keepaliveTimer = null
|
this.keepaliveTimer = null
|
||||||
@ -457,7 +458,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// 跳转到切换客服页面
|
// 跳转到切换客服页面
|
||||||
goToChangeService(){
|
goToChangeService() {
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: '/packages/customerService/changeService/index?currentMchId=' + this.chatTarget.mchId
|
url: '/packages/customerService/changeService/index?currentMchId=' + this.chatTarget.mchId
|
||||||
})
|
})
|
||||||
@ -465,7 +466,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// 页面卸载时停止心跳包
|
// 页面卸载时停止心跳包
|
||||||
onUnload(){
|
onUnload() {
|
||||||
// 断开MQTT连接
|
// 断开MQTT连接
|
||||||
if (this.client) {
|
if (this.client) {
|
||||||
this.client.disconnect()
|
this.client.disconnect()
|
||||||
|
|||||||
@ -83,6 +83,7 @@ page {
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
box-shadow: 3rpx -3rpx 15rpx 0rpx rgba(255,27,27,0.05);
|
box-shadow: 3rpx -3rpx 15rpx 0rpx rgba(255,27,27,0.05);
|
||||||
|
padding-bottom: 30rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.left {
|
.left {
|
||||||
|
|||||||
10
yarn.lock
10
yarn.lock
@ -164,6 +164,14 @@ buffer@^5.5.0:
|
|||||||
base64-js "^1.3.1"
|
base64-js "^1.3.1"
|
||||||
ieee754 "^1.1.13"
|
ieee754 "^1.1.13"
|
||||||
|
|
||||||
|
buffer@^6.0.3:
|
||||||
|
version "6.0.3"
|
||||||
|
resolved "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz"
|
||||||
|
integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==
|
||||||
|
dependencies:
|
||||||
|
base64-js "^1.3.1"
|
||||||
|
ieee754 "^1.2.1"
|
||||||
|
|
||||||
callback-stream@^1.0.2:
|
callback-stream@^1.0.2:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.npmjs.org/callback-stream/-/callback-stream-1.1.0.tgz"
|
resolved "https://registry.npmjs.org/callback-stream/-/callback-stream-1.1.0.tgz"
|
||||||
@ -384,7 +392,7 @@ help-me@^1.0.1:
|
|||||||
through2 "^2.0.1"
|
through2 "^2.0.1"
|
||||||
xtend "^4.0.0"
|
xtend "^4.0.0"
|
||||||
|
|
||||||
ieee754@^1.1.13:
|
ieee754@^1.1.13, ieee754@^1.2.1:
|
||||||
version "1.2.1"
|
version "1.2.1"
|
||||||
resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz"
|
resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz"
|
||||||
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
|
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user