You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

81 lines
3.2 KiB

<template>
<view class="page-staff-chat">
<view class="nav-bar">
<text class="nav-back" @tap="goBack"></text>
<text class="nav-title">💬 客人对话</text>
<text></text>
</view>
<scroll-view class="chat-list" scroll-y :scroll-into-view="scrollToId">
<ChatBubble v-for="m in messages" :key="m.id" :msg="m" viewer="staff" />
<view id="chat-bottom"></view>
</scroll-view>
<view class="chat-input-bar">
<input class="chat-input" v-model="inputText" placeholder="回复客人..." @confirm="sendMsg" />
<button class="chat-send" @tap="sendMsg">发送</button>
</view>
</view>
</template>
<script>
import { ref, onMounted, onUnmounted } from 'vue'
import { useStaffStore } from '@/stores/staff'
import { get, post } from '@/utils/request'
import { API } from '@/utils/constants'
import { startPoll, stopPoll } from '@/utils/poller'
import ChatBubble from '@/components/ChatBubble.vue'
export default {
components: { ChatBubble },
setup() {
const staff = useStaffStore()
const cardNo = ref(uni.getStorageSync('chatCardNo') || '')
const messages = ref([])
const inputText = ref('')
const scrollToId = ref('')
let lastId = 0
async function loadMessages() {
try {
const res = await get(API.MESSAGE_LIST, { card_no: cardNo.value, since: lastId })
if (Array.isArray(res) && res.length > 0) {
const newMsgs = res.filter(m => m.senderType === 'customer')
if (newMsgs.length > 0) staff.incrementUnread(newMsgs.length)
messages.value = [...messages.value, ...res]
lastId = res[res.length - 1].id
scrollToId.value = 'chat-bottom'
}
} catch (e) {}
}
async function sendMsg() {
const content = inputText.value.trim()
if (!content) return
inputText.value = ''
try {
await post(API.MESSAGE_SEND, { cardNo: cardNo.value, senderType: 'staff', content, staffId: staff.staffId })
await loadMessages()
} catch (e) {}
}
function goBack() { staff.clearUnread(); uni.navigateBack() }
onMounted(() => { staff.clearUnread(); loadMessages(); startPoll('staffChat', loadMessages, 5000) })
onUnmounted(() => stopPoll('staffChat'))
return { cardNo, messages, inputText, scrollToId, sendMsg, goBack }
}
}
</script>
<style scoped>
.page-staff-chat{min-height:100vh;display:flex;flex-direction:column;background:var(--bg);width:100%}
.nav-bar{height:100rpx;position:sticky;top:0;z-index:100;background:var(--bg);display:flex;align-items:center;justify-content:space-between;padding:0 28rpx;border-bottom:1px solid var(--border);flex-shrink:0}
.nav-back{font-size:36rpx;color:var(--text-dim)}
.nav-title{font-size:32rpx;font-weight:800;color:var(--gold)}
.chat-list{flex:1;padding:16rpx 0}
.chat-input-bar{display:flex;align-items:center;padding:16rpx 24rpx;padding-bottom:calc(16rpx + var(--safe-b));background:var(--bg-card);border-top:1px solid var(--border);gap:16rpx}
.chat-input{flex:1;height:76rpx;background:var(--bg);border-radius:16rpx;padding:0 28rpx;font-size:28rpx;color:var(--text)}
.chat-send{width:104rpx;height:72rpx;border-radius:16rpx;background:var(--blue);color:#fff;border:none;font-size:26rpx;font-weight:700}
</style>