|
|
@@ -0,0 +1,174 @@
|
|
|
+<script setup>
|
|
|
+import {onMounted, ref} from 'vue'
|
|
|
+import {ElMessage, ElMessageBox} from 'element-plus'
|
|
|
+import {Clock, MessageSquare, User} from 'lucide-vue-next'
|
|
|
+import request from '@/utils/request.js'
|
|
|
+
|
|
|
+const messages = ref([])
|
|
|
+const total = ref(0)
|
|
|
+const loading = ref(false)
|
|
|
+const currentPage = ref(1)
|
|
|
+const pageSize = ref(10)
|
|
|
+
|
|
|
+const getList = async () => {
|
|
|
+ loading.value = true
|
|
|
+ try {
|
|
|
+ const res = await request.get('/chat/getRobotMessage', {
|
|
|
+ params: {
|
|
|
+ page: currentPage.value,
|
|
|
+ size: pageSize.value
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ if (res.code !== 200) {
|
|
|
+ ElMessage.error(res.msg)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ messages.value = res.data.records
|
|
|
+ total.value = res.data.total
|
|
|
+ } catch (error) {
|
|
|
+ ElMessage.error('获取留言列表失败')
|
|
|
+ } finally {
|
|
|
+ loading.value = false
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const handlePageChange = (page) => {
|
|
|
+ currentPage.value = page
|
|
|
+ getList()
|
|
|
+}
|
|
|
+
|
|
|
+const formatTime = (time) => {
|
|
|
+ return new Date(time).toLocaleString('zh-CN', {
|
|
|
+ year: 'numeric',
|
|
|
+ month: '2-digit',
|
|
|
+ day: '2-digit',
|
|
|
+ hour: '2-digit',
|
|
|
+ minute: '2-digit'
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ getList()
|
|
|
+})
|
|
|
+
|
|
|
+const readMessage = async (messageId) => {
|
|
|
+ try {
|
|
|
+ await ElMessageBox.confirm(
|
|
|
+ '确认要将该留言标记为已读吗?',
|
|
|
+ '提示',
|
|
|
+ {
|
|
|
+ confirmButtonText: '确定',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ type: 'warning'
|
|
|
+ }
|
|
|
+ )
|
|
|
+
|
|
|
+ const res = await request.get('/chat/readMessage', {
|
|
|
+ params: { messageId }
|
|
|
+ })
|
|
|
+
|
|
|
+ if (res.code !== 200) {
|
|
|
+ ElMessage.error(res.msg)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ ElMessage.success('标记为已读')
|
|
|
+ getList()
|
|
|
+ } catch (error) {
|
|
|
+ if (error !== 'cancel') {
|
|
|
+ ElMessage.error('标记为已读失败')
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<template>
|
|
|
+ <div class="min-h-[calc(100vh-90px)] bg-gray-50 p-6">
|
|
|
+ <div class="max-w-full mx-auto">
|
|
|
+ <div class="mb-6">
|
|
|
+ <div class="flex items-center gap-3 mb-2">
|
|
|
+ <MessageSquare class="w-8 h-8 text-blue-600" />
|
|
|
+ <h1 class="text-3xl font-bold text-gray-800">客户留言</h1>
|
|
|
+ </div>
|
|
|
+ <p class="text-gray-500">共 {{ total }} 条留言</p>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <el-card v-loading="loading" shadow="never" class="mb-6">
|
|
|
+ <div v-if="messages.length === 0 && !loading" class="text-center py-12">
|
|
|
+ <MessageSquare class="w-16 h-16 text-gray-300 mx-auto mb-4" />
|
|
|
+ <p class="text-gray-400 text-lg">暂无留言</p>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div v-else class="space-y-4">
|
|
|
+ <div
|
|
|
+ v-for="message in messages"
|
|
|
+ :key="message.id"
|
|
|
+ class="border border-gray-200 rounded-lg p-4 hover:shadow-md transition-shadow bg-white"
|
|
|
+ >
|
|
|
+ <!-- 顶部信息 -->
|
|
|
+ <div class="flex items-center justify-between mb-3">
|
|
|
+ <div class="flex items-center gap-2">
|
|
|
+ <User class="w-5 h-5 text-blue-600" />
|
|
|
+ <span class="text-sm font-medium text-gray-700">
|
|
|
+ 客户ID: {{ message.fromId }}
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="flex items-center gap-2">
|
|
|
+ <!-- 状态:未读时显示按钮,已读显示标签 -->
|
|
|
+ <el-button
|
|
|
+ v-if="message.status !== 'read'"
|
|
|
+ type="primary"
|
|
|
+ size="small"
|
|
|
+ @click="readMessage(message.id)"
|
|
|
+ >
|
|
|
+ 标记已读
|
|
|
+ </el-button>
|
|
|
+ <el-tag
|
|
|
+ v-else
|
|
|
+ size="small"
|
|
|
+ type="success"
|
|
|
+ >
|
|
|
+ 已读
|
|
|
+ </el-tag>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 内容 -->
|
|
|
+ <div class="mb-3 pl-2 border-l-3 border-blue-500">
|
|
|
+ <p class="text-gray-800 text-base leading-relaxed">
|
|
|
+ {{ message.content }}
|
|
|
+ </p>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 时间 & ID -->
|
|
|
+ <div class="flex items-center gap-2 text-gray-400 text-sm">
|
|
|
+ <Clock class="w-4 h-4" />
|
|
|
+ <span>{{ formatTime(message.createdAt) }}</span>
|
|
|
+ <span class="ml-auto text-xs text-gray-400">ID: {{ message.id }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-card>
|
|
|
+
|
|
|
+ <div class="flex justify-center">
|
|
|
+ <el-pagination
|
|
|
+ v-model:current-page="currentPage"
|
|
|
+ :page-size="pageSize"
|
|
|
+ :total="total"
|
|
|
+ layout="prev, pager, next, total"
|
|
|
+ background
|
|
|
+ @current-change="handlePageChange"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.el-card {
|
|
|
+ border-radius: 12px;
|
|
|
+}
|
|
|
+</style>
|