效果未实现,我手动修改数据库已有条目信息,前端未能够实时监听。 前端代码:// pages/order-detail/order-detail.js
Page({
data: {
activeIndex: 0, // 当前选中的状态索引
statusList: ['新订单', '备货中', '待配送', '配送中', '已完成', '已取消'], // 订单状态列表
showActionSheet: false, // 是否显示操作面板
currentOrderId: null, // 当前操作的订单ID
cancelOrderCount: 0, // 取消订单次数
lastCancelDate: null, // 最后一次取消订单的日期
searchText: '', // 搜索关键字
orders: [], // 所有订单数据
filteredOrders: [], // 筛选后的订单数据
isLoading: false, // 是否正在加载数据
page: 1, // 当前页码
pageSize: 10, // 每页大小
hasMore: true ,// 是否还有更多数据
socketOpen: false, // WebSocket 是否已打开
socketTask: null, // WebSocket 实例
},
// onLoad() {
// this.loadOrders(); // 加载订单数据
// this.loadCancelInfo(); // 加载取消订单信息
// },
onReachBottom() {
if (this.data.hasMore && !this.data.isLoading) {
this.setData({ page: this.data.page + 1 }, () => {
this.loadOrders();
});
}
},
loadCancelInfo() {
const cancelInfo = wx.getStorageSync('cancelOrderInfo') || {};
this.setData({
cancelOrderCount: cancelInfo.count || 0,
lastCancelDate: cancelInfo.date || null
});
},
onLoad() {
this.loadOrders(); // 加载订单数据
this.initWebSocket(); // 初始化 WebSocket
},
onUnload() {
this.closeWebSocket(); // 页面卸载时关闭 WebSocket
},
// 初始化 WebSocket
// pages/order-detail/order-detail.js
initWebSocket() {
const that = this;
const socketTask = wx.connectSocket({
url: 'ws://127.0.0.1:8001/ws/orders/',
header: {
'Authorization': 'Bearer ' + wx.getStorageSync('token')
}
});
socketTask.onOpen(() => {
console.log('WebSocket 已连接');
that.setData({ socketOpen: true });
});
socketTask.onMessage((res) => {
console.log('收到新订单:', res.data);
const newOrder = JSON.parse(res.data);
// 更新本地订单数据
that.setData({
orders: [newOrder, ...that.data.orders],
filteredOrders: [newOrder, ...that.data.filteredOrders]
});
// 提示用户有新订单
wx.showToast({
title: '有新订单',
icon: 'success'
});
});
socketTask.onError((err) => {
console.error('WebSocket 连接错误:', err);
that.setData({ socketOpen: false });
});
socketTask.onClose(() => {
console.log('WebSocket 已关闭');
that.setData({ socketOpen: false });
});
this.setData({ socketTask });
},
// 关闭 WebSocket
closeWebSocket() {
const { socketTask } = this.data;
if (socketTask) {
socketTask.close();
}
},
async loadOrders() {
if (this.data.isLoading || !this.data.hasMore) return;
this.setData({ isLoading: true });
try {
const { statusList, activeIndex, searchText, page, pageSize } = this.data;
const currentStatus = statusList[activeIndex];
const user = wx.getStorageSync('userInfo');
const shopId = user.id; // 确保已存储shopId
const res = await new Promise((resolve, reject) => {
wx.request({
url: 'http://127.0.0.1:8000/api/gouw/merchant/orders/',
method: 'GET',
header: {
'Authorization': 'Bearer ' + wx.getStorageSync('token'),
'Content-Type': 'application/json'
},
data: {
shop_id: shopId,
status: currentStatus,
search: searchText,
page: page,
page_size: pageSize
},
success: (res) => {
if (res.statusCode === 200) {
resolve(res.data);
} else {
reject(new Error(`HTTP ${res.statusCode}: ${res.data?.message || '请求失败'}`));
}
},
fail: (err) => {
reject(new Error('网络请求失败'));
}
});
});
console.log('API响应数据:', JSON.stringify(res, null, 2));
if (res.code === 200) {
const newOrders = res.data.orders.map(order => ({
id: order.orderId,
orderId: order.orderNo,
customerName: order.customerName,
customerPhone: order.customerPhone,
status: order.status,
statusCode: order.statusCode,
createTime: order.createTime,
totalAmount: order.totalAmount,
products: order.products,
deliveryFee: order.deliveryFee
}));
this.setData({
orders: page === 1 ? newOrders : [...this.data.orders, ...newOrders],
filteredOrders: page === 1 ? newOrders : [...this.data.orders, ...newOrders],
hasMore: page < res.data.pagination.totalPages,
isLoading: false
});
} else {
throw new Error(res.message || '加载订单失败');
}
} catch (err) {
console.error('加载订单错误:', err.message, err);
wx.showToast({
title: err.message || '加载订单失败',
icon: 'none',
duration: 2000
});
this.setData({ isLoading: false });
}
},
// 加载订单数据
// async loadOrders() {
// try {
// const user = wx.getStorageSync('userInfo');
// const shopId = user.id;
// const res = await new Promise((resolve, reject) => {
// wx.request({
// url: 'http://127.0.0.1:8000/api/gouw/merchant/orders/',
// method: 'GET',
// header: {
// 'Authorization': 'Bearer ' + wx.getStorageSync('token'),
// 'Content-Type': 'application/json'
// },
// data: {
// shop_id: shopId,
// status: '新订单',
// page: 1,
// page_size: 10
// },
// success: (res) => {
// if (res.statusCode === 200) {
// resolve(res.data);
// } else {
// reject(new Error(`HTTP ${res.statusCode}: ${res.data?.message || '请求失败'}`));
// }
// },
// fail: (err) => {
// reject(new Error('网络请求失败'));
// }
// });
// });
// if (res.code === 200) {
// const orders = res.data.orders.map(order => ({
// id: order.orderId,
// orderId: order.orderNo,
// customerName: order.customerName,
// customerPhone: order.customerPhone,
// status: order.status,
// statusCode: order.statusCode,
// createTime: order.createTime,
// totalAmount: order.totalAmount,
// products: order.products,
// deliveryFee: order.deliveryFee
// }));
// this.setData({
// orders,
// filteredOrders: orders
// });
// }
// } catch (err) {
// console.error('加载订单错误:', err.message);
// }
// },
// 切换订单状态
switchStatus(e) {
const index = e.currentTarget.dataset.index;
this.setData({
activeIndex: index,
searchText: '',
page: 1,
hasMore: true
}, () => {
this.loadOrders();
});
},
filterOrders() {
const { activeIndex, statusList, orders, searchText } = this.data;
const currentStatus = statusList[activeIndex];
let filtered = orders.filter(order => {
if (currentStatus !== '全部' && order.status !== currentStatus) {
return false;
}
if (searchText && !order.orderId.includes(searchText) &&
!order.customerName.includes(searchText) &&
!order.customerPhone.includes(searchText)) {
return false;
}
return true;
});
filtered.sort((a, b) => new Date(b.createTime) - new Date(a.createTime));
this.setData({ filteredOrders: filtered });
},
handleSearchInput(e) {
this.setData({
searchText: e.detail.value
});
},
handleSearch() {
this.setData({
page: 1,
hasMore: true
}, () => {
this.loadOrders();
});
},
showActionSheet(e) {
const orderId = e.currentTarget.dataset.orderid;
this.setData({
showActionSheet: true,
currentOrderId: orderId
});
},
hideActionSheet() {
this.setData({
showActionSheet: false,
currentOrderId: null
});
},
handleCancelOrder(e) {
const orderId = e.currentTarget.dataset.orderid;
const today = new Date().toDateString();
if (this.data.lastCancelDate === today && this.data.cancelOrderCount >= 3) {
wx.showModal({
title: '提示',
content: '当天取消接单次数已经用完,如需继续,请点击申诉',
showCancel: false
});
this.hideActionSheet();
return;
}
let newCount = this.data.cancelOrderCount;
let newDate = this.data.lastCancelDate;
if (newDate !== today) {
newCount = 0;
newDate = today;
}
newCount++;
this.setData({
cancelOrderCount: newCount,
lastCancelDate: newDate
});
wx.setStorageSync('cancelOrderInfo', {
count: newCount,
date: newDate
});
this.updateOrderStatus(orderId, '已取消');
wx.showToast({
title: '订单已取消',
icon: 'success'
});
this.hideActionSheet();
},
handleAppeal(e) {
const orderId = e.currentTarget.dataset.orderid;
this.hideActionSheet();
wx.navigateTo({
url: `/pages/appeal/appeal?orderId=${orderId}`,
success: () => {
console.log('跳转到申诉页面');
},
fail: (err) => {
console.error('跳转失败:', err);
wx.showToast({
title: '跳转失败,请重试',
icon: 'none'
});
}
});
},
handleAcceptOrder(e) {
const orderId = e.currentTarget.dataset.orderid;
this.updateOrderStatus(orderId, '备货中');
wx.showToast({
title: '接单成功',
icon: 'success'
});
},
handleReadyForDelivery(e) {
const orderId = e.currentTarget.dataset.orderid;
this.updateOrderStatus(orderId, '待配送');
wx.showToast({
title: '备货完成',
icon: 'success'
});
},
handleStartDelivery(e) {
const orderId = e.currentTarget.dataset.orderid;
this.updateOrderStatus(orderId, '配送中');
wx.showToast({
title: '开始配送',
icon: 'success'
});
},
handleCompleteDelivery(e) {
const orderId = e.currentTarget.dataset.orderid;
this.updateOrderStatus(orderId, '已完成');
wx.showToast({
title: '配送完成',
icon: 'success'
});
},
// 更新订单状态
async updateOrderStatus(orderId, newStatus) {
const token = wx.getStorageSync('token');
if (!token) {
wx.showToast({
title: '未登录,请重新登录',
icon: 'none'
});
return;
}
wx.showLoading({ title: '处理中...', mask: true });
try {
const res = await new Promise((resolve, reject) => {
wx.request({
url: 'http://127.0.0.1:8000/api/gouw/update-order-status/',
method: 'POST',
header: {
'Authorization': 'Bearer ' + token,
'Content-Type': 'application/json'
},
data: {
order_no: orderId,
status: newStatus
},
success: (res) => {
if (res.statusCode === 200 && res.data.code === 200) {
resolve(res.data);
} else {
reject(new Error(res.data?.message || '更新失败'));
}
},
fail: (err) => {
reject(new Error('网络请求失败'));
}
});
});
wx.hideLoading();
wx.showToast({
title: '操作成功',
icon: 'success'
});
// 从本地数据中移除已处理的订单
// 核心修改:更新本地订单状态并重新过滤
const updatedOrders = this.data.orders.map(order => {
if (order.orderId === orderId) {
return { ...order, status: newStatus };
}
return order;
});
this.setData({
// 从完整订单列表移除
orders: this.data.orders.filter(order => order.orderId !== orderId),
// 从当前视图列表直接移除
filteredOrders: this.data.filteredOrders.filter(order => order.orderId !== orderId)
});
wx.hideLoading();
wx.showToast({ title: '操作成功', icon: 'success' });
// this.loadOrders();
// 如果需要重新加载数据,可以调用 this.loadOrders();
} catch (err) {
console.error('更新订单状态失败:', err.message);
wx.hideLoading();
wx.showToast({
title: err.message || '操作失败,请重试',
icon: 'none'
});
}
},
// 辅助方法:匹配搜索条件
matchSearchCriteria(order) {
const searchText = this.data.searchText.toLowerCase();
return !searchText ||
order.orderId.toLowerCase().includes(searchText) ||
order.customerName.toLowerCase().includes(searchText) ||
order.customerPhone.includes(searchText);
},
sj_mb(e) {
wx.navigateTo({
url: "/pages/gr_xx/gr_xx",
success: () => {
console.log('成功跳转到商家信息页面');
},
fail: (err) => {
console.error('跳转失败:', err);
wx.showToast({
title: '跳转失败,请重试',
icon: 'none'
});
}
});
},
dp_zt(e) {
wx.navigateTo({
url: "/pages/dp_zt/dp_zt",
success: () => {
console.log('成功跳转到商家信息页面');
},
fail: (err) => {
console.error('跳转失败:', err);
wx.showToast({
title: '跳转失败,请重试',
icon: 'none'
});
}
});
},
tk_dd(e) {
wx.navigateTo({
url: "/pages/tk_dd/tk_dd",
success: () => {
console.log('成功跳转到退款订单页面');
},
fail: (err) => {
console.error('跳转失败:', err);
wx.showToast({
title: '跳转失败,请重试',
icon: 'none'
});
}
});
}
});
后端代码:# DjangoProject1/asgi.py
import os
from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter, URLRouter
from .routing import application # 直接导入主路由配置
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'DjangoProject1.settings')
application = application # DjangoProject1/routing.py
from django.urls import re_path
from channels.routing import ProtocolTypeRouter, URLRouter
from gouw.routing import websocket_urlpatterns as gouw_routes # 直接导入子路由
application = ProtocolTypeRouter({
"websocket": URLRouter([
re_path(r'^ws/', URLRouter(gouw_routes)), # 确保路径匹配
])
}) # gouw/consumers.py
import json
from channels.generic.websocket import AsyncWebsocketConsumer
from asgiref.sync import async_to_sync
from channels.layers import get_channel_layer
class OrderConsumer(AsyncWebsocketConsumer):
async def connect(self):
# 接受 WebSocket 连接
await self.accept()
# 将用户加入组
await self.channel_layer.group_add("orders", self.channel_name)
async def disconnect(self, close_code):
# 用户断开连接时从组中移除
await self.channel_layer.group_discard("orders", self.channel_name)
async def receive(self, text_data):
# 接收来自客户端的消息
text_data_json = json.loads(text_data)
message = text_data_json['message']
await self.channel_layer.group_send(
"orders",
{
'type': 'order_message',
'message': message
}
)
async def order_message(self, event):
# 处理来自组的消息并发送给客户端
message = event['message']
await self.send(text_data=json.dumps({
'message': message
}))
# 广播新订单
def broadcast_new_order(order_data):
channel_layer = get_channel_layer()
async_to_sync(channel_layer.group_send)(
"orders",
{
'type': 'order_message',
'message': order_data
}
) # gouw/routing.py
from django.urls import path
from .consumers import OrderConsumer
websocket_urlpatterns = [
path('orders/', OrderConsumer.as_asgi()), # 保持简单路由列表
]
# gouw/signals.py
from django.db.models.signals import post_save, post_delete
from django.dispatch import receiver
from .models import Order
from .consumers import broadcast_new_order
@receiver(post_save, sender=Order)
def order_saved(sender, instance, created, **kwargs):
"""
当订单保存时触发此信号。
如果是新创建的订单,则广播消息。
"""
if created:
print(f"New order created: {instance}")
broadcast_new_order({
"id": instance.id,
"orderNo": instance.orderNo,
"status": instance.status,
"createTime": str(instance.createTime),
"totalAmount": instance.totalAmount,
"customerName": instance.customerName,
"customerPhone": instance.customerPhone
})
@receiver(post_delete, sender=Order)
def order_deleted(sender, instance, **kwargs):
"""
当订单删除时触发此信号。
可以选择广播删除消息。
"""
print(f"Order deleted: {instance}")