接入商品评论数据

This commit is contained in:
2026-03-20 17:30:30 +08:00
parent 620ae742df
commit 13811ae87d
14 changed files with 535 additions and 1753 deletions

View File

@@ -1,44 +1,12 @@
<!-- 商家端 - 聊天页面 -->
<template>
<view class="chat-page">
<<<<<<< HEAD
<view class="chat-header">
=======
<!-- 聊天头部 -->
<view class="chat-header" :style="{ paddingTop: navPaddingTop }">
>>>>>>> local-backup-root-cyj
<view class="header-back" @click="goBack">
<text class="back-icon"></text>
</view>
<view class="header-info">
<<<<<<< HEAD
<text class="chat-title">{{ chatTitle }}</text>
<text class="chat-status">在线</text>
</view>
<view class="header-actions"></view>
</view>
<scroll-view scroll-y class="chat-content" :scroll-into-view="scrollToView" scroll-with-animation>
<view class="chat-messages">
<view v-for="msg in chatMessages" :key="msg.id" :class="['message-item', msg.is_from_user ? 'me' : 'received']" :id="'msg-' + msg.id">
<view v-if="!msg.is_from_user" class="message-wrapper">
<image class="avatar" src="/static/images/default-avatar.png" mode="aspectFill" />
<view class="message-content-wrapper">
<view class="message-bubble">
<text class="message-text">{{ msg.content }}</text>
<text class="message-time">{{ formatTime(msg.created_at) }}</text>
</view>
</view>
</view>
<view v-else class="message-wrapper me">
<view class="message-content-wrapper">
<view class="message-bubble me">
<text class="message-text">{{ msg.content }}</text>
<text class="message-time">{{ formatTime(msg.created_at) }}</text>
</view>
</view>
<image class="avatar me" src="/static/images/default-shop.png" mode="aspectFill" />
=======
<view class="header-info-text-wrapper">
<text class="chat-title">{{ chatTitle }}</text>
<text class="chat-status">在线</text>
@@ -103,20 +71,11 @@
:src="shopAvatar"
mode="aspectFill"
/>
>>>>>>> local-backup-root-cyj
</view>
</view>
</view>
</scroll-view>
<<<<<<< HEAD
<view class="chat-input">
<input v-model="inputText" class="input-field" placeholder="请输入消息..." confirm-type="send" @confirm="sendMessage" />
<view class="send-btn" @click="sendMessage">
<text class="send-icon">➤</text>
</view>
</view>
=======
<!-- 聊天输入区 -->
<view class="chat-input">
<view class="input-tools">
@@ -156,23 +115,16 @@
</text>
</view>
</scroll-view>
>>>>>>> local-backup-root-cyj
</view>
</template>
<script lang="uts">
import supa from '@/components/supadb/aksupainstance.uts'
<<<<<<< HEAD
type ChatMessageType = {
id: string
=======
import type { AkSupaRealtimeChannel } from '@/components/supadb/aksupa.uts'
type ChatMessageType = {
id: string
viewId: string
>>>>>>> local-backup-root-cyj
session_id: string
sender_id: string
receiver_id: string
@@ -181,10 +133,7 @@
is_read: boolean
is_from_user: boolean
created_at: string
<<<<<<< HEAD
=======
time: string
>>>>>>> local-backup-root-cyj
}
export default {
@@ -196,9 +145,6 @@
inputText: '',
chatMessages: [] as ChatMessageType[],
scrollToView: '',
<<<<<<< HEAD
merchantId: ''
=======
merchantId: '',
userAvatar: '/static/images/default-avatar.png',
shopAvatar: '/static/images/default-shop.png',
@@ -212,19 +158,15 @@
computed: {
emojiList(): string[] {
return ['😊', '😂', '🤣', '😍', '😘', '🥰', '😭', '😡', '👍', '👏', '🙏', '🎉', '❤️', '🔥', '⭐']
>>>>>>> local-backup-root-cyj
}
},
onLoad(options: any) {
<<<<<<< HEAD
=======
const sysInfo = uni.getSystemInfoSync()
const statusBarH = sysInfo.statusBarHeight
this.navPaddingTop = (statusBarH + 10) + 'px'
console.log('chat page onLoad options:', options)
>>>>>>> local-backup-root-cyj
if (options.session_id) {
this.sessionId = options.session_id
}
@@ -238,9 +180,6 @@
},
onShow() {
<<<<<<< HEAD
this.loadChatMessages()
=======
console.log('chat page onShow, chatUserId:', this.chatUserId, 'merchantId:', this.merchantId)
if (this.merchantId) {
this.loadChatMessages()
@@ -257,61 +196,12 @@
if (this.realtimeChannel != null) {
supa.removeChannel(this.realtimeChannel!)
}
>>>>>>> local-backup-root-cyj
},
methods: {
async initMerchantId() {
try {
const session = supa.getSession()
<<<<<<< HEAD
this.merchantId = session?.user?.getString('id') || uni.getStorageSync('user_id') || ''
} catch (e) {}
},
async loadChatMessages() {
try {
let query
if (this.sessionId) {
query = supa
.from('ml_chat_messages')
.select('*')
.eq('session_id', this.sessionId)
.order('created_at', { ascending: true })
} else if (this.chatUserId && this.merchantId) {
query = supa
.from('ml_chat_messages')
.select('*')
.or(`and(sender_id.eq.${this.chatUserId},receiver_id.eq.${this.merchantId}),and(sender_id.eq.${this.merchantId},receiver_id.eq.${this.chatUserId})`)
.order('created_at', { ascending: true })
}
if (query) {
const response = await query.execute()
if (response.data && (response.data as any[]).length > 0) {
const rawData = response.data as any[]
const messages: ChatMessageType[] = []
for (let i = 0; i < rawData.length; i++) {
const item = rawData[i] as UTSJSONObject
const senderId = item.getString('sender_id')
messages.push({
id: item.getString('id') || '',
session_id: item.getString('session_id') || '',
sender_id: senderId || '',
receiver_id: item.getString('receiver_id') || '',
content: item.getString('content') || '',
msg_type: item.getString('msg_type') || 'text',
is_read: item.getBoolean('is_read') || false,
is_from_user: senderId === this.merchantId,
created_at: item.getString('created_at') || ''
} as ChatMessageType)
}
this.chatMessages = messages
this.scrollToView = messages.length > 0 ? 'msg-' + messages[messages.length - 1].id : ''
this.markAsRead()
}
=======
if (session != null && session.user != null) {
this.merchantId = session.user.getString('id') || ''
}
@@ -405,15 +295,12 @@
} else {
console.log('没有找到聊天记录')
this.chatMessages = []
>>>>>>> local-backup-root-cyj
}
} catch (e) {
console.error('加载聊天记录失败:', e)
}
},
<<<<<<< HEAD
=======
setupRealtimeSubscription(): void {
console.log('开始建立聊天实时订阅...')
@@ -492,25 +379,12 @@
}, 100)
},
>>>>>>> local-backup-root-cyj
async markAsRead() {
try {
await supa
.from('ml_chat_messages')
.update({ is_read: true })
.eq('receiver_id', this.merchantId)
<<<<<<< HEAD
.eq('is_read', false)
.execute()
} catch (e) {}
},
async sendMessage() {
if (!this.inputText.trim()) return
const content = this.inputText.trim()
this.inputText = ''
=======
.eq('sender_id', this.chatUserId)
.eq('is_read', false)
.execute()
@@ -525,7 +399,6 @@
this.inputText = ''
this.showEmoji = false
>>>>>>> local-backup-root-cyj
try {
const newMessage = {
@@ -543,26 +416,6 @@
.insert([newMessage])
.execute()
<<<<<<< HEAD
if (!response.error) {
this.loadChatMessages()
}
} catch (e) {
console.error('发送消息失败:', e)
}
},
goBack() {
uni.navigateBack()
},
formatTime(timeStr: string): string {
if (!timeStr) return ''
const date = new Date(timeStr)
const hours = date.getHours().toString().padStart(2, '0')
const minutes = date.getMinutes().toString().padStart(2, '0')
return `${hours}:${minutes}`
=======
if (response.error != null) {
console.error('发送消息失败:', response.error)
uni.showToast({ title: '发送失败', icon: 'none' })
@@ -621,40 +474,12 @@
goBack() {
uni.navigateBack()
>>>>>>> local-backup-root-cyj
}
}
}
</script>
<style>
<<<<<<< HEAD
.chat-page { display: flex; flex-direction: column; height: 100vh; background-color: #f5f5f5; }
.chat-header { display: flex; align-items: center; padding: 20rpx 30rpx; background-color: #fff; border-bottom: 1rpx solid #eee; }
.header-back { padding: 10rpx 20rpx 10rpx 0; }
.back-icon { font-size: 48rpx; color: #333; font-weight: bold; }
.header-info { flex: 1; display: flex; flex-direction: column; align-items: center; }
.chat-title { font-size: 32rpx; color: #333; font-weight: 500; }
.chat-status { font-size: 22rpx; color: #4CAF50; }
.header-actions { padding: 10rpx; }
.chat-content { flex: 1; padding: 20rpx; }
.chat-messages { display: flex; flex-direction: column; }
.message-item { margin-bottom: 30rpx; }
.message-wrapper { display: flex; align-items: flex-start; }
.message-wrapper.me { flex-direction: row-reverse; }
.avatar { width: 80rpx; height: 80rpx; border-radius: 8rpx; margin: 0 20rpx; }
.message-content-wrapper { max-width: 70%; }
.message-bubble { background-color: #fff; padding: 20rpx; border-radius: 12rpx; position: relative; }
.message-bubble.me { background-color: #007AFF; }
.me .message-text { color: #fff; }
.me .message-time { color: rgba(255,255,255,0.7); }
.message-text { font-size: 28rpx; color: #333; line-height: 1.4; }
.message-time { display: block; font-size: 20rpx; color: #999; margin-top: 10rpx; text-align: right; }
.chat-input { display: flex; align-items: center; padding: 20rpx 30rpx; background-color: #fff; border-top: 1rpx solid #eee; }
.input-field { flex: 1; height: 72rpx; background-color: #f5f5f5; border-radius: 36rpx; padding: 0 30rpx; font-size: 28rpx; }
.send-btn { margin-left: 20rpx; width: 72rpx; height: 72rpx; background-color: #007AFF; border-radius: 50%; display: flex; align-items: center; justify-content: center; }
.send-icon { font-size: 32rpx; color: #fff; }
=======
.chat-page { width: 100%; flex: 1; background-color: #f5f5f5; display: flex; flex-direction: column; overflow: hidden; }
.chat-header { background-color: white; padding-left: 15px; padding-right: 15px; padding-bottom: 10px; display: flex; flex-direction: row; align-items: center; justify-content: space-between; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: #eee; flex-shrink: 0; }
@@ -700,5 +525,4 @@
.image-bubble { padding: 0 !important; background-color: transparent !important; }
.image-bubble .message-time { margin-top: 5px; text-align: right; }
.message-image { width: 150px; border-radius: 8px; }
>>>>>>> local-backup-root-cyj
</style>