改bug
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
18631081161 2026-03-25 21:54:49 +08:00
parent e56ee73b48
commit 70c466951b
6 changed files with 122 additions and 29 deletions

View File

@ -92,7 +92,7 @@ async function onWxLogin() {
const redirect = uni.getStorageSync('loginRedirect')
if (redirect) {
uni.removeStorageSync('loginRedirect')
uni.navigateTo({ url: redirect })
uni.redirectTo({ url: redirect })
} else {
uni.reLaunch({ url: '/pages/index/index' })
}

View File

@ -331,7 +331,10 @@
onNewMessage((msgList) => {
for (const msg of msgList) {
if (msg.from === this.targetImUserId || msg.from === this.imUserId) {
this.chatMessages.push(formatIMMessage(msg, this.imUserId))
const formatted = formatIMMessage(msg, this.imUserId)
// ID
if (this.orderId && formatted.orderId && String(formatted.orderId) !== String(this.orderId)) continue
this.chatMessages.push(formatted)
}
}
this.scrollToBottom()
@ -350,7 +353,11 @@
this.loadingHistory = true
try {
const res = await getMessageList(this.targetImUserId, this.nextReqMessageID)
const formatted = res.messageList.map(m => formatIMMessage(m, this.imUserId))
const allFormatted = res.messageList.map(m => formatIMMessage(m, this.imUserId))
// IDorderId
const formatted = this.orderId
? allFormatted.filter(m => !m.orderId || String(m.orderId) === String(this.orderId))
: allFormatted
this.chatMessages = [...formatted, ...this.chatMessages]
this.nextReqMessageID = res.nextReqMessageID
this.historyCompleted = res.isCompleted
@ -377,7 +384,7 @@
const text = this.inputText
this.inputText = ''
try {
const msg = await sendTextMessage(this.targetImUserId, text)
const msg = await sendTextMessage(this.targetImUserId, text, this.orderId)
this.chatMessages.push(formatIMMessage(msg, this.imUserId))
this.scrollToBottom()
} catch (e) {
@ -410,7 +417,7 @@
sourceType: ['album', 'camera'],
success: async (res) => {
try {
const msg = await sendImageMessage(this.targetImUserId, res.tempFilePaths[0])
const msg = await sendImageMessage(this.targetImUserId, res.tempFilePaths[0], this.orderId)
this.chatMessages.push(formatIMMessage(msg, this.imUserId))
this.scrollToBottom()
} catch (e) {
@ -477,7 +484,7 @@
difference: res.difference,
status: res.status,
description: `发起了${changeTypeLabel}改价申请`
})
}, this.orderId)
}
this.chatMessages.push({
id: `pc_${res.id}`,

View File

@ -52,13 +52,16 @@
:key="item.orderId"
@click="goChat(item)"
>
<image class="chat-avatar" :src="item.avatarUrl || '/static/logo.png'" mode="aspectFill"></image>
<image class="chat-avatar" :src="item.targetAvatar || '/static/logo.png'" mode="aspectFill"></image>
<view class="chat-info">
<view class="chat-top">
<text class="chat-name">{{ item.nickname || '用户' }}</text>
<text class="chat-time">{{ formatTime(item.lastMessageTime) }}</text>
<text class="chat-name">{{ item.targetNickname || '用户' }}</text>
<text class="chat-time">{{ formatTime(item.lastTime) }}</text>
</view>
<text class="chat-msg">{{ item.lastMessage || '' }}</text>
<text class="chat-msg">{{ getOrderLabel(item) }}</text>
</view>
<view class="chat-tag">
<text>{{ getStatusLabel(item.status) }}</text>
</view>
</view>
@ -71,8 +74,7 @@
</template>
<script>
import { getUnreadCount } from '../../utils/api'
import { getConversationList, getChatInstance } from '../../utils/im'
import { getUnreadCount, getChatOrderList } from '../../utils/api'
export default {
data() {
@ -110,11 +112,11 @@ export default {
}
},
/** 加载聊天记录列表(从腾讯 IM SDK 获取会话列表) */
/** 加载聊天记录列表 */
async loadChatList() {
try {
const list = await getConversationList()
this.chatList = list
const list = await getChatOrderList()
this.chatList = list || []
} catch (e) {
console.error('[消息页] 加载聊天列表失败:', e)
}
@ -145,12 +147,24 @@ export default {
/** 跳转聊天页 */
goChat(item) {
// IM orderId targetUserId
uni.navigateTo({
url: `/pages/message/chat?targetUserId=${item.targetUserId}`
url: `/pages/message/chat?orderId=${item.orderId}`
})
},
/** 获取订单摘要标签 */
getOrderLabel(item) {
const typeMap = { Pickup: '代取', Delivery: '代送', Help: '万能帮', Purchase: '代购', Food: '美食街' }
const typeName = typeMap[item.orderType] || item.orderType
return `${typeName} · ${item.itemName || '订单'} · ¥${item.commission}`
},
/** 获取状态标签 */
getStatusLabel(status) {
const map = { Pending: '待接单', InProgress: '进行中', WaitConfirm: '待确认', Completed: '已完成' }
return map[status] || status
},
/** 格式化时间显示 */
formatTime(dateStr) {
if (!dateStr) return ''
@ -320,7 +334,7 @@ export default {
}
.chat-msg {
font-size: 26rpx;
font-size: 24rpx;
color: #999999;
margin-top: 8rpx;
overflow: hidden;
@ -329,6 +343,19 @@ export default {
display: block;
}
.chat-tag {
flex-shrink: 0;
margin-left: 12rpx;
}
.chat-tag text {
font-size: 20rpx;
color: #FFB700;
background: #FFF8E6;
padding: 4rpx 12rpx;
border-radius: 6rpx;
}
.empty-chat {
text-align: center;
padding: 80rpx 0;

View File

@ -93,6 +93,11 @@ export function getOrderByChatUser(targetUserId) {
return request({ url: `/api/orders/by-chat-user/${targetUserId}` })
}
/** 获取聊天订单列表(消息页用) */
export function getChatOrderList() {
return request({ url: '/api/orders/chat-list' })
}
// ==================== 美食街 ====================
/** 获取门店列表 */

View File

@ -158,13 +158,15 @@ export async function getMessageList(targetUserId, nextReqMessageID) {
* 发送文本消息
* @param {string} targetUserId - 对方用户 ID
* @param {string} text - 文本内容
* @param {string|number} [orderId] - 关联订单ID
*/
export async function sendTextMessage(targetUserId, text) {
export async function sendTextMessage(targetUserId, text, orderId) {
const message = chat.createTextMessage({
to: targetUserId,
conversationType: TencentCloudChat.TYPES.CONV_C2C,
payload: { text }
})
if (orderId) message.cloudCustomData = JSON.stringify({ orderId: String(orderId) })
const res = await chat.sendMessage(message)
return res.data.message
}
@ -173,13 +175,15 @@ export async function sendTextMessage(targetUserId, text) {
* 发送图片消息
* @param {string} targetUserId - 对方用户 ID
* @param {string} filePath - 本地图片路径
* @param {string|number} [orderId] - 关联订单ID
*/
export async function sendImageMessage(targetUserId, filePath) {
export async function sendImageMessage(targetUserId, filePath, orderId) {
const message = chat.createImageMessage({
to: targetUserId,
conversationType: TencentCloudChat.TYPES.CONV_C2C,
payload: { file: { tempFilePaths: [filePath] } }
})
if (orderId) message.cloudCustomData = JSON.stringify({ orderId: String(orderId) })
const res = await chat.sendMessage(message)
return res.data.message
}
@ -188,8 +192,9 @@ export async function sendImageMessage(targetUserId, filePath) {
* 发送自定义消息改价申请等
* @param {string} targetUserId - 对方用户 ID
* @param {Object} customData - 自定义数据
* @param {string|number} [orderId] - 关联订单ID
*/
export async function sendCustomMessage(targetUserId, customData) {
export async function sendCustomMessage(targetUserId, customData, orderId) {
const message = chat.createCustomMessage({
to: targetUserId,
conversationType: TencentCloudChat.TYPES.CONV_C2C,
@ -199,6 +204,7 @@ export async function sendCustomMessage(targetUserId, customData) {
extension: customData.extension || ''
}
})
if (orderId) message.cloudCustomData = JSON.stringify({ orderId: String(orderId) })
const res = await chat.sendMessage(message)
return res.data.message
}
@ -213,6 +219,15 @@ export function formatIMMessage(msg, currentImUserId) {
const isSelf = msg.from === currentImUserId
const avatar = msg.avatar || '/static/logo.png'
// 提取消息关联的订单ID
let msgOrderId = null
if (msg.cloudCustomData) {
try {
const cd = JSON.parse(msg.cloudCustomData)
msgOrderId = cd.orderId || null
} catch (e) {}
}
// 文本消息
if (msg.type === TencentCloudChat.TYPES.MSG_TEXT) {
return {
@ -221,7 +236,8 @@ export function formatIMMessage(msg, currentImUserId) {
content: msg.payload.text,
isSelf,
avatar,
time: msg.time * 1000
time: msg.time * 1000,
orderId: msgOrderId
}
}
@ -234,7 +250,8 @@ export function formatIMMessage(msg, currentImUserId) {
content: imageInfo?.url || '',
isSelf,
avatar,
time: msg.time * 1000
time: msg.time * 1000,
orderId: msgOrderId
}
}
@ -253,19 +270,19 @@ export function formatIMMessage(msg, currentImUserId) {
newPrice: data.newPrice,
difference: data.difference,
status: data.status,
time: msg.time * 1000
time: msg.time * 1000,
orderId: msgOrderId
}
}
} catch (e) {
// 解析失败当普通文本处理
}
} catch (e) {}
return {
id: msg.ID,
type: 'text',
content: msg.payload.description || '[自定义消息]',
isSelf,
avatar,
time: msg.time * 1000
time: msg.time * 1000,
orderId: msgOrderId
}
}
@ -276,6 +293,7 @@ export function formatIMMessage(msg, currentImUserId) {
content: '[暂不支持的消息类型]',
isSelf,
avatar,
time: msg.time * 1000
time: msg.time * 1000,
orderId: msgOrderId
}
}

View File

@ -671,6 +671,42 @@ app.MapPost("/api/orders", async (CreateOrderRequest request, HttpContext httpCo
});
}).RequireAuthorization();
// 获取当前用户的聊天订单列表(已接单的订单,按时间排序)
app.MapGet("/api/orders/chat-list", async (HttpContext httpContext, AppDbContext db) =>
{
var userIdClaim = httpContext.User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier);
if (userIdClaim == null) return Results.Unauthorized();
var currentUserId = int.Parse(userIdClaim.Value);
var orders = await db.Orders
.Include(o => o.Owner)
.Include(o => o.Runner)
.Where(o => o.RunnerId != null &&
(o.OwnerId == currentUserId || o.RunnerId == currentUserId) &&
o.Status != OrderStatus.Cancelled)
.OrderByDescending(o => o.CompletedAt ?? o.AcceptedAt ?? o.CreatedAt)
.Select(o => new
{
OrderId = o.Id,
o.OrderNo,
OrderType = o.OrderType.ToString(),
o.ItemName,
Status = o.Status.ToString(),
o.Commission,
TargetUserId = o.OwnerId == currentUserId ? o.RunnerId : (int?)o.OwnerId,
TargetNickname = o.OwnerId == currentUserId
? (o.Runner != null ? o.Runner.Nickname : "用户")
: (o.Owner != null ? o.Owner.Nickname : "用户"),
TargetAvatar = o.OwnerId == currentUserId
? (o.Runner != null ? o.Runner.AvatarUrl : "")
: (o.Owner != null ? o.Owner.AvatarUrl : ""),
LastTime = o.CompletedAt ?? o.AcceptedAt ?? o.CreatedAt
})
.ToListAsync();
return Results.Ok(orders);
}).RequireAuthorization();
// 根据对方用户ID查找最近的关联订单用于聊天页显示订单卡片
app.MapGet("/api/orders/by-chat-user/{targetUserId}", async (int targetUserId, HttpContext httpContext, AppDbContext db) =>
{