解决手机端解码报错的问题

This commit is contained in:
赵毅 2025-09-24 17:55:52 +08:00
parent 088891bdbb
commit 9b6a3c9bce
5 changed files with 109 additions and 73 deletions

33
package-lock.json generated
View File

@ -9,6 +9,7 @@
"version": "1.0.1",
"dependencies": {
"abort-controller": "^3.0.0",
"buffer": "^6.0.3",
"mqtt": "^3.0.0",
"vue": "^3.5.21"
}
@ -220,6 +221,30 @@
"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": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
@ -245,9 +270,9 @@
}
},
"node_modules/buffer": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
"integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
"funding": [
{
"type": "github",
@ -265,7 +290,7 @@
"license": "MIT",
"dependencies": {
"base64-js": "^1.3.1",
"ieee754": "^1.1.13"
"ieee754": "^1.2.1"
}
},
"node_modules/buffer-from": {

View File

@ -18,6 +18,7 @@
},
"dependencies": {
"abort-controller": "^3.0.0",
"buffer": "^6.0.3",
"mqtt": "^3.0.0",
"vue": "^3.5.21"
}

View File

@ -1,4 +1,4 @@
<template>
packages/customerService/index/index<template>
<view class="chat-container">
<!-- 聊天头部 -->
<view :style="{ paddingTop: top + 'px', height: localHeight + 'px' }" class="chat-header">
@ -15,8 +15,8 @@
<view v-if="connectingStatus" class="connecting-status">{{ connectingStatus }}</view>
<!-- 聊天消息区域 -->
<scroll-view :scroll-into-view="scrollToView" class="chat-messages" scroll-y="true"
@scrolltoupper="loadMoreHistory" @scrolltolower="loadMoreHistory" lower-threshold="100" upper-threshold="100">
<scroll-view :scroll-into-view="scrollToView" class="chat-messages" scroll-y="true" @scrolltoupper="loadMoreHistory"
@scrolltolower="loadMoreHistory" lower-threshold="100" upper-threshold="100">
<!-- 加载历史消息提示 -->
<view v-if="isLoadingHistory" class="message-time">加载历史消息...</view>
@ -32,7 +32,7 @@
'loading': message.isLoading
}" class="message-item">
<image :src="message.isSelf ? userAvatar : (chatTarget.employee_image)" class="message-avatar"
mode="aspectFill"></image>
mode="aspectFill"></image>
<view class="message-content">
{{ message.content }}
</view>
@ -44,9 +44,9 @@
<view class="chat-input-area">
<view class="input-container">
<textarea v-model="inputMessage" :adjust-position="true" class="message-input" placeholder="请输入消息..."
@confirm="sendMessage" @input="handleInput" auto-height hold-keyboard="true"
enable-keyboard-accessory-view="true" cursor-spacing="10" maxlength="500"
@focus="onInputFocus" @blur="onInputBlur"></textarea>
@confirm="sendMessage" @input="handleInput" auto-height hold-keyboard="true"
enable-keyboard-accessory-view="true" cursor-spacing="10" maxlength="500" @focus="onInputFocus"
@blur="onInputBlur"></textarea>
<button :disabled="!canSend || !client || !isConnected" class="send-btn" @tap="sendMessage">
发送
</button>
@ -61,7 +61,7 @@ import { apiArr } from '@/api/customerService'
import mqttTool from '@/utils/mqtt'
export default {
data(){
data() {
return {
localHeight: '',
top: '',
@ -105,14 +105,14 @@ export default {
scrollToBottomFlag: false
}
},
onLoad(options){
onLoad(options) {
const meun = menuButtonInfo()
this.top = meun.top
this.localHeight = meun.height
//
if (options.item) {
this.chatTarget = JSON.parse(options.item)
this.chatTarget.title = `客服${ this.chatTarget.employee_name }`
this.chatTarget.title = `客服${this.chatTarget.employee_name}`
}
// MQTT
this.initChat()
@ -120,10 +120,10 @@ export default {
//
this.userAvatar = picUrl + uni.getStorageSync('headPhoto')
},
onShow(){
onShow() {
},
methods: {
async connect(){
async connect() {
this.client = null
const options = {
clientId: this.selfClientId
@ -154,9 +154,10 @@ export default {
await this.subscribe()
this.client.on('message', (topic, message) => {
let de = new TextDecoder('utf-8')
let msg = de.decode(message)
let jsMsg = JSON.parse(msg)
const msgStr = Buffer.from(message).toString('utf8'); // UTF-8
const msg = JSON.parse(msgStr); //
let jsMsg = msg // 使
console.log('收到消息', topic, msg)
if (jsMsg.send_client === this.selfClientId || jsMsg.receive_client === this.selfClientId) {
console.log('接收或发送人是我')
@ -174,7 +175,7 @@ export default {
}
})
},
async subscribe(){
async subscribe() {
if (this.isConnected && this.client) {
this.client.subscribe('contact/message/receive_msg', { qos: 0 }, (err) => {
if (!err) {
@ -191,7 +192,7 @@ export default {
}
},
//
async initChat(){
async initChat() {
try {
//
this.connectingStatus = '正在连接客服...'
@ -212,7 +213,7 @@ export default {
},
// MQTT
async getMqttConfig(){
async getMqttConfig() {
try {
// clientIdAPI
return new Promise((resolve, reject) => {
@ -244,7 +245,7 @@ export default {
},
// MQTT
onDisconnect(packet){
onDisconnect(packet) {
console.log('MQTT连接断开', packet)
this.isConnected = false
this.client = null
@ -263,7 +264,7 @@ export default {
},
//
async loadHistoryMessages(){
async loadHistoryMessages() {
if (!this.hasMoreHistory || this.isLoadingHistory) {
return
}
@ -319,14 +320,14 @@ export default {
},
//
loadMoreHistory(){
loadMoreHistory() {
if (!this.isLoadingHistory && this.hasMoreHistory) {
this.loadHistoryMessages()
}
},
//
sendMessage(){
sendMessage() {
const content = this.inputMessage.trim()
console.log('发送消息', content)
if (!content || !this.client || !this.isConnected) return
@ -344,17 +345,17 @@ export default {
}
console.log('发送消息', msgData)
this.client.publish(
'contact/message/send_msg', // 使
JSON.stringify(msgData),
{ Qos: 0 },
(err) => {
if (err) {
console.error('发送消息失败', err)
//
} else {
console.log('发送消息成功')
}
'contact/message/send_msg', // 使
JSON.stringify(msgData),
{ Qos: 0 },
(err) => {
if (err) {
console.error('发送消息失败', err)
//
} else {
console.log('发送消息成功')
}
}
)
//
@ -362,7 +363,7 @@ export default {
},
//
handleInput(){
handleInput() {
this.canSend = this.inputMessage.trim().length > 0
},
@ -382,7 +383,7 @@ export default {
},
// 线
needShowTime(index){
needShowTime(index) {
if (index === 0) return true
const currentMsg = this.messages[index]
@ -393,28 +394,28 @@ export default {
},
//
formatTime(time){
formatTime(time) {
const date = new Date(time)
const hours = date.getHours().toString().padStart(2, '0')
const minutes = date.getMinutes().toString().padStart(2, '0')
return `${ hours }:${ minutes }`
return `${hours}:${minutes}`
},
//
scrollToBottom(){
scrollToBottom() {
setTimeout(() => {
this.scrollToView = 'msg-' + (this.messages.length - 1)
}, 100)
},
//
goBack(){
goBack() {
uni.navigateBack()
},
// -
startKeepalive(){
startKeepalive() {
//
this.stopKeepalive()
@ -426,20 +427,20 @@ export default {
}
this.client.publish(
'contact/message/keep_time',
JSON.stringify(keepaliveData),
{},
(err) => {
if (err) {
console.error('发送心跳包失败', err)
//
if (!this.isConnected) {
return
}
console.log('心跳包发送失败,尝试检查连接状态')
//
'contact/message/keep_time',
JSON.stringify(keepaliveData),
{},
(err) => {
if (err) {
console.error('发送心跳包失败', err)
//
if (!this.isConnected) {
return
}
console.log('心跳包发送失败,尝试检查连接状态')
//
}
}
)
} else {
console.warn('MQTT未连接停止心跳包')
@ -449,7 +450,7 @@ export default {
},
//
stopKeepalive(){
stopKeepalive() {
if (this.keepaliveTimer) {
clearInterval(this.keepaliveTimer)
this.keepaliveTimer = null
@ -457,7 +458,7 @@ export default {
},
//
goToChangeService(){
goToChangeService() {
uni.navigateTo({
url: '/packages/customerService/changeService/index?currentMchId=' + this.chatTarget.mchId
})
@ -465,7 +466,7 @@ export default {
},
//
onUnload(){
onUnload() {
// MQTT
if (this.client) {
this.client.disconnect()

View File

@ -83,6 +83,7 @@ page {
justify-content: space-between;
align-items: center;
box-shadow: 3rpx -3rpx 15rpx 0rpx rgba(255,27,27,0.05);
padding-bottom: 30rpx;
}
.left {

View File

@ -164,6 +164,14 @@ buffer@^5.5.0:
base64-js "^1.3.1"
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:
version "1.1.0"
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"
xtend "^4.0.0"
ieee754@^1.1.13:
ieee754@^1.1.13, ieee754@^1.2.1:
version "1.2.1"
resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz"
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==