215 lines
4.9 KiB
JavaScript
215 lines
4.9 KiB
JavaScript
// pages/support/support.js
|
|
const app = getApp()
|
|
const api = require('../../utils/api')
|
|
const util = require('../../utils/util')
|
|
const imageUrl = require('../../utils/imageUrl')
|
|
|
|
Page({
|
|
data: {
|
|
statusBarHeight: 44,
|
|
navHeight: 96,
|
|
myAvatar: '/images/default-avatar.svg',
|
|
messages: [],
|
|
inputText: '',
|
|
inputFocus: false,
|
|
isTyping: false,
|
|
ticketId: '',
|
|
scrollIntoView: '',
|
|
scrollTop: 0,
|
|
pollingTimer: null
|
|
},
|
|
|
|
onLoad() {
|
|
const { statusBarHeight, navHeight, userInfo } = app.globalData
|
|
const myAvatar = imageUrl.getAvatarUrl(userInfo?.avatar)
|
|
|
|
this.setData({
|
|
statusBarHeight,
|
|
navHeight,
|
|
myAvatar
|
|
})
|
|
|
|
this.initSupport()
|
|
},
|
|
|
|
onAvatarError() {
|
|
this.setData({
|
|
myAvatar: '/images/default-avatar.svg'
|
|
})
|
|
},
|
|
|
|
onUnload() {
|
|
this.stopPolling()
|
|
},
|
|
|
|
onHide() {
|
|
this.stopPolling()
|
|
},
|
|
|
|
onShow() {
|
|
if (this.data.ticketId) {
|
|
this.startPolling()
|
|
}
|
|
},
|
|
|
|
/**
|
|
* 初始化客服会话
|
|
*/
|
|
async initSupport() {
|
|
wx.showLoading({ title: '加载中...' })
|
|
try {
|
|
const guestId = wx.getStorageSync('guestId') || util.generateId()
|
|
if (!wx.getStorageSync('guestId')) {
|
|
wx.setStorageSync('guestId', guestId)
|
|
}
|
|
|
|
// 获取已有咨询列表
|
|
const res = await api.customerService.getList(guestId)
|
|
const data = res.data || {}
|
|
const tickets = data.tickets || []
|
|
|
|
if (tickets.length > 0) {
|
|
// 使用最近的一个工单
|
|
const latestTicket = tickets[0]
|
|
this.setData({ ticketId: latestTicket.id })
|
|
await this.loadMessages(latestTicket.id)
|
|
} else {
|
|
// 如果没有工单,可以在首次发送消息时创建
|
|
console.log('[support] No existing tickets found.')
|
|
}
|
|
} catch (err) {
|
|
console.error('[support] initSupport error:', err)
|
|
} finally {
|
|
wx.hideLoading()
|
|
this.startPolling()
|
|
}
|
|
},
|
|
|
|
/**
|
|
* 加载消息历史
|
|
*/
|
|
async loadMessages(ticketId) {
|
|
try {
|
|
const res = await api.customerService.getDetail(ticketId)
|
|
if (res.success && res.data) {
|
|
const messages = res.data.messages.map(msg => ({
|
|
id: msg.id,
|
|
isMe: msg.senderType === 'user',
|
|
text: msg.content,
|
|
time: util.formatTime(new Date(msg.createdAt), 'HH:mm'),
|
|
senderName: msg.senderName
|
|
}))
|
|
|
|
// 如果有新消息才更新,避免闪烁
|
|
if (JSON.stringify(messages) !== JSON.stringify(this.data.messages)) {
|
|
this.setData({ messages }, () => {
|
|
this.scrollToBottom()
|
|
})
|
|
}
|
|
}
|
|
} catch (err) {
|
|
console.error('[support] loadMessages error:', err)
|
|
}
|
|
},
|
|
|
|
/**
|
|
* 发送消息
|
|
*/
|
|
async onSend() {
|
|
const content = this.data.inputText.trim()
|
|
if (!content || this.isSending) return
|
|
|
|
this.isSending = true
|
|
const tempId = util.generateId()
|
|
const now = new Date()
|
|
|
|
// 先在本地显示
|
|
const userMsg = {
|
|
id: tempId,
|
|
isMe: true,
|
|
text: content,
|
|
time: util.formatTime(now, 'HH:mm')
|
|
}
|
|
|
|
this.setData({
|
|
messages: [...this.data.messages, userMsg],
|
|
inputText: '',
|
|
inputFocus: true
|
|
}, () => {
|
|
this.scrollToBottom()
|
|
})
|
|
|
|
try {
|
|
if (this.data.ticketId) {
|
|
// 回复已有工单
|
|
await api.customerService.reply({
|
|
ticketId: this.data.ticketId,
|
|
content: content,
|
|
userName: app.globalData.userInfo?.nickname || '访客'
|
|
})
|
|
} else {
|
|
// 创建新工单
|
|
const guestId = wx.getStorageSync('guestId')
|
|
const res = await api.customerService.create({
|
|
category: 'other',
|
|
content: content,
|
|
userName: app.globalData.userInfo?.nickname || '访客',
|
|
guestId: guestId
|
|
})
|
|
if (res.success && res.data) {
|
|
this.setData({ ticketId: res.data.ticketId })
|
|
}
|
|
}
|
|
// 发送后立即拉取一次
|
|
if (this.data.ticketId) {
|
|
await this.loadMessages(this.data.ticketId)
|
|
}
|
|
} catch (err) {
|
|
console.error('[support] send message error:', err)
|
|
wx.showToast({ title: '发送失败', icon: 'none' })
|
|
} finally {
|
|
this.isSending = false
|
|
}
|
|
},
|
|
|
|
onInput(e) {
|
|
this.setData({ inputText: e.detail.value })
|
|
},
|
|
|
|
/**
|
|
* 开始轮询
|
|
*/
|
|
startPolling() {
|
|
this.stopPolling()
|
|
this.data.pollingTimer = setInterval(() => {
|
|
if (this.data.ticketId) {
|
|
this.loadMessages(this.data.ticketId)
|
|
}
|
|
}, 4000) // 每4秒轮询一次
|
|
},
|
|
|
|
/**
|
|
* 停止轮询
|
|
*/
|
|
stopPolling() {
|
|
if (this.data.pollingTimer) {
|
|
clearInterval(this.data.pollingTimer)
|
|
this.data.pollingTimer = null
|
|
}
|
|
},
|
|
|
|
onBack() {
|
|
wx.navigateBack()
|
|
},
|
|
|
|
onTapChatArea() {
|
|
this.setData({ inputFocus: false })
|
|
},
|
|
|
|
scrollToBottom() {
|
|
this.setData({
|
|
scrollIntoView: 'chat-bottom-anchor'
|
|
})
|
|
}
|
|
})
|