用户消息系统:消息列表、订单群聊、联系对方入口

- 新增消息列表页和聊天详情页,支持 SSE 实时推送
- 订单详情页新增"联系对方"按钮,一键进入订单群聊
- 导航栏新增"消息"入口
- 修复 mobileHost 路径匹配 bug,避免 /m 前缀误匹配
- 优化 dev.sh:提取 mysql 辅助函数、修复空 PID 处理、条件检查依赖

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
yml
2026-05-27 09:46:34 +08:00
co-authored by Claude Opus 4.7
parent 8cbd06dca4
commit 6fb5de204c
7 changed files with 792 additions and 14 deletions
+34 -1
View File
@@ -1,8 +1,10 @@
<script setup lang="ts">
import { ElMessage } from 'element-plus'
import { ChatDotRound } from '@element-plus/icons-vue'
import { computed, onMounted, ref } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { fetchOrderChat } from '@/api/chats'
import { createDispute } from '@/api/disputes'
import { uploadFile } from '@/api/files'
import {
@@ -61,6 +63,7 @@ const rejectReason = ref('')
const disputeType = ref('cannot_login')
const disputeDescription = ref('')
const disputeEvidenceText = ref('')
const openingChat = ref(false)
const isOwner = computed(() => order.value?.owner_id === session.userId)
const isRenter = computed(() => order.value?.renter_id === session.userId)
@@ -300,6 +303,19 @@ async function handleEvidenceUpload(event: Event) {
}
}
async function openOrderChat() {
if (!order.value || openingChat.value) return
openingChat.value = true
try {
const chat = await fetchOrderChat(order.value.id)
await router.push(`/messages/${chat.id}`)
} catch {
ElMessage.error('订单群聊暂不可用')
} finally {
openingChat.value = false
}
}
function readError(error: unknown, fallback: string) {
if (typeof error === 'object' && error && 'response' in error) {
const response = (error as { response?: { data?: { message?: string } } }).response
@@ -463,7 +479,13 @@ function linesToList(value: string) {
<div v-if="order" class="page-header">
<p class="eyebrow">{{ order.order_no }}</p>
<h1>订单详情</h1>
<p>{{ order.title }} · {{ order.server_region }} / {{ order.login_platform }}</p>
<div class="header-actions">
<p>{{ order.title }} · {{ order.server_region }} / {{ order.login_platform }}</p>
<el-button type="primary" :loading="openingChat" @click="openOrderChat">
<el-icon style="margin-right: 4px;"><ChatDotRound /></el-icon>
联系对方
</el-button>
</div>
</div>
<div v-if="order" class="detail-grid">
@@ -644,6 +666,17 @@ function linesToList(value: string) {
</template>
<style scoped>
.header-actions {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
}
.header-actions p {
margin: 0;
}
.checkout-resource-panel {
display: grid;
gap: 10px;