feat: 添加手动发货和刷新订单状态功能

- 订单管理新增"手动发货"和"刷新状态"按钮
- 手动发货使用现有WebSocket连接发送消息(与自动发货逻辑一致)
- 支持从闲鱼平台获取真实订单状态
- CookieManager新增live_instances存储XianyuLive实例
- 订单详情获取支持force_refresh强制刷新参数

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
GuDong
2026-01-25 05:47:21 +08:00
parent 801a3135cf
commit 53e81a7452
5 changed files with 471 additions and 68 deletions
+69 -22
View File
@@ -5127,15 +5127,16 @@ class XianyuLive:
logger.error(f"{self.cookie_id}】免拼发货模块调用失败: {self._safe_str(e)}")
return {"error": f"免拼发货模块调用失败: {self._safe_str(e)}", "order_id": order_id}
async def fetch_order_detail_info(self, order_id: str, item_id: str = None, buyer_id: str = None, debug_headless: bool = None, sid: str = None):
async def fetch_order_detail_info(self, order_id: str, item_id: str = None, buyer_id: str = None, debug_headless: bool = None, sid: str = None, force_refresh: bool = False):
"""获取订单详情信息(使用独立的锁机制,不受延迟锁影响)
Args:
order_id: 订单ID
item_id: 商品ID
buyer_id: 买家ID
debug_headless: 是否使用有头模式调试
sid: 会话ID 56226853668@goofish用于简化消息匹配订单
force_refresh: 是否强制刷新跳过缓存直接从闲鱼获取
"""
# 使用独立的订单详情锁,不与自动发货锁冲突
order_detail_lock = self._order_detail_locks[order_id]
@@ -5163,7 +5164,7 @@ class XianyuLive:
logger.info(f"{self.cookie_id}】🖥️ 启用有头模式进行调试")
# 异步获取订单详情(使用当前账号的cookie)
result = await fetch_order_detail_simple(order_id, cookie_string, headless=headless_mode)
result = await fetch_order_detail_simple(order_id, cookie_string, headless=headless_mode, force_refresh=force_refresh)
if result:
logger.info(f"{self.cookie_id}】订单详情获取成功: {order_id}")
@@ -5176,6 +5177,10 @@ class XianyuLive:
spec_value_2 = result.get('spec_value_2', '')
quantity = result.get('quantity', '')
amount = result.get('amount', '')
# 获取订单状态(从闲鱼页面解析)
order_status = result.get('order_status', '')
if order_status:
logger.info(f"{self.cookie_id}】📊 订单状态: {order_status}")
if spec_name and spec_value:
logger.info(f"{self.cookie_id}】📋 规格名称: {spec_name}")
@@ -5209,7 +5214,8 @@ class XianyuLive:
spec_value_2=spec_value_2,
quantity=quantity,
amount=amount,
cookie_id=self.cookie_id
cookie_id=self.cookie_id,
order_status=order_status if order_status else None # 传递从闲鱼获取的订单状态
)
# 使用订单状态处理器设置状态
@@ -7620,6 +7626,7 @@ class XianyuLive:
logger.warning(f"{self.cookie_id}】强制关闭时出现异常(已忽略): {e}")
async def send_msg_once(self, toid, item_id, text):
"""单次发送消息(创建新的WebSocket连接)"""
headers = {
"Cookie": self.cookies_str,
"Host": "wss-goofish.dingtalk.com",
@@ -7631,27 +7638,46 @@ class XianyuLive:
"Accept-Encoding": "gzip, deflate, br, zstd",
"Accept-Language": "zh-CN,zh;q=0.9",
}
logger.info(f"{self.cookie_id}】开始单次发送消息: toid={toid}, item_id={item_id}")
# 兼容不同版本的websockets库
try:
async with websockets.connect(
self.base_url,
extra_headers=headers
extra_headers=headers,
close_timeout=5 # 添加关闭超时
) as websocket:
await self._handle_websocket_connection(websocket, toid, item_id, text)
result = await self._handle_websocket_connection(websocket, toid, item_id, text)
if result:
logger.info(f"{self.cookie_id}】单次发送消息成功")
else:
raise Exception("消息发送失败")
except TypeError as e:
# 安全地检查异常信息
error_msg = self._safe_str(e)
if "extra_headers" in error_msg:
logger.warning("websockets库不支持extra_headers参数,使用兼容模式")
# 使用兼容模式,通过subprotocols传递部分头信息
# 使用兼容模式
async with websockets.connect(
self.base_url,
additional_headers=headers
additional_headers=headers,
close_timeout=5
) as websocket:
await self._handle_websocket_connection(websocket, toid, item_id, text)
result = await self._handle_websocket_connection(websocket, toid, item_id, text)
if result:
logger.info(f"{self.cookie_id}】单次发送消息成功(兼容模式)")
else:
raise Exception("消息发送失败")
else:
raise
except websockets.exceptions.ConnectionClosedError as e:
logger.warning(f"{self.cookie_id}】WebSocket连接关闭: {self._safe_str(e)}")
# 连接关闭但消息可能已发送,不抛出异常
except Exception as e:
logger.error(f"{self.cookie_id}】单次发送消息异常: {self._safe_str(e)}")
raise
async def _create_websocket_connection(self, headers):
"""创建WebSocket连接,兼容不同版本的websockets库,支持代理配置"""
@@ -7773,19 +7799,40 @@ class XianyuLive:
async def _handle_websocket_connection(self, websocket, toid, item_id, text):
"""处理WebSocket连接的具体逻辑"""
await self.init(websocket)
await self.create_chat(websocket, toid, item_id)
async for message in websocket:
try:
logger.info(f"{self.cookie_id}】message: {message}")
message = json.loads(message)
cid = message["body"]["singleChatConversation"]["cid"]
cid = cid.split('@')[0]
await self.send_msg(websocket, cid, toid, text)
logger.info(f'{self.cookie_id}】send message')
return
except Exception as e:
pass
try:
await self.init(websocket)
await self.create_chat(websocket, toid, item_id)
# 添加超时处理,最多等待30秒
timeout = 30
start_time = time.time()
async for message in websocket:
try:
# 检查是否超时
if time.time() - start_time > timeout:
logger.warning(f"{self.cookie_id}】WebSocket消息等待超时")
break
logger.info(f"{self.cookie_id}】message: {message}")
message = json.loads(message)
cid = message["body"]["singleChatConversation"]["cid"]
cid = cid.split('@')[0]
await self.send_msg(websocket, cid, toid, text)
logger.info(f'{self.cookie_id}】send message success')
return True
except KeyError:
# 消息格式不符合预期,继续等待
continue
except Exception as e:
logger.warning(f"{self.cookie_id}】处理消息异常: {self._safe_str(e)}")
continue
logger.warning(f"{self.cookie_id}】WebSocket连接关闭,未能发送消息")
return False
except Exception as e:
logger.error(f"{self.cookie_id}】WebSocket连接处理异常: {self._safe_str(e)}")
return False
def is_chat_message(self, message):
"""判断是否为用户聊天消息"""
+12 -3
View File
@@ -18,6 +18,7 @@ class CookieManager:
self.cookie_status: Dict[str, bool] = {} # 账号启用状态
self.auto_confirm_settings: Dict[str, bool] = {} # 自动确认发货设置
self._task_locks: Dict[str, asyncio.Lock] = {} # 每个cookie_id的任务锁,防止重复创建
self.live_instances: Dict[str, Any] = {} # 存储 XianyuLive 实例,供外部调用
self._load_from_db()
def _load_from_db(self):
@@ -69,17 +70,19 @@ class CookieManager:
logger.info(f"{cookie_id}】开始创建XianyuLive实例...")
logger.info(f"{cookie_id}】Cookie值长度: {len(cookie_value)}")
live = XianyuLive(cookie_value, cookie_id=cookie_id, user_id=user_id)
# 保存实例供外部调用
self.live_instances[cookie_id] = live
logger.info(f"{cookie_id}】XianyuLive实例创建成功,开始调用main()...")
# 强制刷新日志,确保日志被写入
try:
import sys
sys.stdout.flush()
except:
pass
await live.main()
# main() 正常退出(不应该发生,因为main()内部有无限循环)
logger.warning(f"{cookie_id}】XianyuLive.main() 正常退出(这通常不应该发生)")
except asyncio.CancelledError:
@@ -101,6 +104,8 @@ class CookieManager:
except:
pass
finally:
# 清理实例引用
self.live_instances.pop(cookie_id, None)
logger.info(f"{cookie_id}】_run_xianyu方法执行结束")
# 确保日志被刷新
try:
@@ -330,6 +335,10 @@ class CookieManager:
return {cid: value for cid, value in self.cookies.items()
if self.cookie_status.get(cid, True)}
def get_xianyu_instance(self, cookie_id: str):
"""获取指定Cookie的XianyuLive实例(如果正在运行)"""
return self.live_instances.get(cookie_id)
def _start_cookie_task(self, cookie_id: str):
"""启动指定Cookie的任务"""
if cookie_id in self.tasks:
+164
View File
@@ -6710,6 +6710,170 @@ def get_user_orders(current_user: Dict[str, Any] = Depends(get_current_user)):
raise HTTPException(status_code=500, detail=f"查询订单失败: {str(e)}")
@app.post('/api/orders/{order_id}/deliver')
async def manual_deliver_order(order_id: str, current_user: Dict[str, Any] = Depends(get_current_user)):
"""手动发货 - 根据订单信息匹配发货规则并发送卡券"""
try:
from db_manager import db_manager
import cookie_manager
user_id = current_user['user_id']
log_with_user('info', f"手动发货请求: 订单 {order_id}", current_user)
# 获取订单信息
order = db_manager.get_order_by_id(order_id)
if not order:
return {"success": False, "delivered": False, "message": "订单不存在"}
# 验证订单属于当前用户
cookie_id = order.get('cookie_id')
if not cookie_id:
return {"success": False, "delivered": False, "message": "订单缺少账号信息"}
cookie_info = db_manager.get_cookie_details(cookie_id)
if not cookie_info or cookie_info.get('user_id') != user_id:
return {"success": False, "delivered": False, "message": "无权操作此订单"}
# 获取 XianyuLive 实例
xianyu_instance = cookie_manager.manager.get_xianyu_instance(cookie_id) if cookie_manager.manager else None
if not xianyu_instance:
return {"success": False, "delivered": False, "message": f"账号 {cookie_id} 未运行,请先启动账号"}
# 获取订单详情
item_id = order.get('item_id')
buyer_id = order.get('buyer_id')
if not item_id:
return {"success": False, "delivered": False, "message": "订单缺少商品信息"}
if not buyer_id:
return {"success": False, "delivered": False, "message": "订单缺少买家信息,无法发送消息"}
# 获取商品标题
item_info = db_manager.get_item_info(cookie_id, item_id)
item_title = item_info.get('item_title', '') if item_info else ''
# 调用自动发货逻辑获取发货内容
delivery_content = await xianyu_instance._auto_delivery(
item_id=item_id,
item_title=item_title,
order_id=order_id,
send_user_id=buyer_id
)
if delivery_content:
# 发送发货内容给买家
try:
if delivery_content.startswith("__IMAGE_SEND__"):
# 图片类型暂不支持手动发货
log_with_user('warning', f"手动发货: 订单 {order_id} 为图片类型,暂不支持手动发送", current_user)
return {"success": False, "delivered": False, "message": "图片类型卡券暂不支持手动发货"}
else:
# 使用现有的WebSocket连接发送消息(与自动发货逻辑一致)
ws = getattr(xianyu_instance, 'ws', None)
if ws:
# 获取订单的sid(会话ID
sid = order.get('sid', '')
if sid:
# 提取cid部分(去掉@goofish后缀)
cid = sid.replace('@goofish', '')
log_with_user('info', f"手动发货: 使用现有WebSocket连接发送, cid={cid}, buyer_id={buyer_id}", current_user)
await xianyu_instance.send_msg(ws, cid, buyer_id, delivery_content)
else:
# 如果没有sid,尝试用buyer_id作为cid
log_with_user('warning', f"手动发货: 订单无sid,尝试使用buyer_id作为cid", current_user)
await xianyu_instance.send_msg(ws, buyer_id, buyer_id, delivery_content)
else:
# 没有现有连接,回退到send_msg_once
log_with_user('warning', f"手动发货: 无现有WebSocket连接,使用send_msg_once", current_user)
await xianyu_instance.send_msg_once(buyer_id, item_id, delivery_content)
log_with_user('info', f"手动发货消息已发送: 订单 {order_id}, 买家 {buyer_id}", current_user)
# 更新订单状态为已发货
db_manager.insert_or_update_order(order_id=order_id, order_status='shipped')
log_with_user('info', f"手动发货成功: 订单 {order_id}", current_user)
return {"success": True, "delivered": True, "message": "发货成功,消息已发送给买家"}
except Exception as send_error:
log_with_user('error', f"手动发货发送消息失败: 订单 {order_id} - {str(send_error)}", current_user)
return {"success": False, "delivered": False, "message": f"获取发货内容成功但发送消息失败: {str(send_error)}"}
else:
log_with_user('warning', f"手动发货失败: 订单 {order_id} - 未匹配到发货规则", current_user)
return {"success": False, "delivered": False, "message": "未匹配到发货规则,请检查卡券和发货规则配置"}
except Exception as e:
log_with_user('error', f"手动发货异常: 订单 {order_id} - {str(e)}", current_user)
import traceback
logger.error(f"手动发货异常堆栈: {traceback.format_exc()}")
return {"success": False, "delivered": False, "message": f"发货失败: {str(e)}"}
@app.post('/api/orders/{order_id}/refresh')
async def refresh_order_status(order_id: str, current_user: Dict[str, Any] = Depends(get_current_user)):
"""刷新订单状态 - 从闲鱼平台获取最新订单状态"""
try:
from db_manager import db_manager
import cookie_manager
user_id = current_user['user_id']
log_with_user('info', f"刷新订单状态请求: 订单 {order_id}", current_user)
# 获取订单信息
order = db_manager.get_order_by_id(order_id)
if not order:
return {"success": False, "updated": False, "message": "订单不存在"}
old_status = order.get('order_status', '')
# 验证订单属于当前用户
cookie_id = order.get('cookie_id')
if not cookie_id:
return {"success": False, "updated": False, "message": "订单缺少账号信息"}
cookie_info = db_manager.get_cookie_details(cookie_id)
if not cookie_info or cookie_info.get('user_id') != user_id:
return {"success": False, "updated": False, "message": "无权操作此订单"}
# 获取 XianyuLive 实例
xianyu_instance = cookie_manager.manager.get_xianyu_instance(cookie_id) if cookie_manager.manager else None
if not xianyu_instance:
return {"success": False, "updated": False, "message": f"账号 {cookie_id} 未运行,请先启动账号"}
# 获取订单详情(强制从闲鱼平台获取最新信息,跳过缓存)
item_id = order.get('item_id')
buyer_id = order.get('buyer_id')
sid = order.get('sid')
result = await xianyu_instance.fetch_order_detail_info(
order_id=order_id,
item_id=item_id,
buyer_id=buyer_id,
sid=sid,
force_refresh=True # 强制刷新,跳过缓存
)
if result:
# 获取更新后的订单信息
updated_order = db_manager.get_order_by_id(order_id)
new_status = updated_order.get('order_status', '') if updated_order else ''
status_changed = old_status != new_status
log_with_user('info', f"刷新订单状态成功: 订单 {order_id}, 状态: {old_status} -> {new_status}", current_user)
return {
"success": True,
"updated": status_changed,
"new_status": new_status,
"message": f"状态已更新: {new_status}" if status_changed else "订单状态无变化"
}
else:
log_with_user('warning', f"刷新订单状态失败: 订单 {order_id}", current_user)
return {"success": False, "updated": False, "message": "获取订单详情失败,请稍后重试"}
except Exception as e:
log_with_user('error', f"刷新订单状态异常: 订单 {order_id} - {str(e)}", current_user)
import traceback
logger.error(f"刷新订单状态异常堆栈: {traceback.format_exc()}")
return {"success": False, "updated": False, "message": f"刷新失败: {str(e)}"}
# ==================== 自动更新接口 ====================
from auto_updater import get_updater, UpdateStatus, init_updater
+78
View File
@@ -9884,6 +9884,9 @@ function createOrderRow(order) {
const statusClass = getOrderStatusClass(order.order_status);
const statusText = getOrderStatusText(order.order_status);
// 判断是否可以手动发货(允许多次发货,除了交易关闭的订单)
const canDeliver = !['closed', 'refunded'].includes(order.order_status);
return `
<tr>
<td>
@@ -9924,6 +9927,12 @@ function createOrderRow(order) {
</td>
<td>
<div class="btn-group btn-group-sm" role="group">
<button class="btn btn-outline-success btn-sm" onclick="manualDeliverOrder('${order.order_id}')" title="手动发货" ${canDeliver ? '' : 'disabled'}>
<i class="bi bi-truck"></i>
</button>
<button class="btn btn-outline-info btn-sm" onclick="refreshOrderStatus('${order.order_id}')" title="刷新状态">
<i class="bi bi-arrow-repeat"></i>
</button>
<button class="btn btn-outline-primary btn-sm" onclick="showOrderDetail('${order.order_id}')" title="查看详情">
<i class="bi bi-eye"></i>
</button>
@@ -10335,6 +10344,75 @@ async function batchDeleteOrders() {
}
}
// 手动发货订单
async function manualDeliverOrder(orderId) {
try {
const confirmed = confirm(`确定要手动发货此订单吗?\n\n订单ID: ${orderId}\n\n系统将根据发货规则自动匹配发货内容并发送给买家。`);
if (!confirmed) {
return;
}
showToast('正在执行发货...', 'info');
const response = await fetch(`${apiBase}/api/orders/${orderId}/deliver`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${authToken}`,
'Content-Type': 'application/json'
}
});
const result = await response.json();
if (response.ok) {
if (result.delivered) {
showToast(`发货成功!\n${result.message}`, 'success');
} else {
showToast(`发货失败: ${result.message}`, 'warning');
}
// 刷新订单列表
await refreshOrdersData();
} else {
showToast(`发货失败: ${result.detail || '未知错误'}`, 'danger');
}
} catch (error) {
console.error('手动发货失败:', error);
showToast('手动发货失败: ' + error.message, 'danger');
}
}
// 刷新订单状态
async function refreshOrderStatus(orderId) {
try {
showToast('正在刷新订单状态...', 'info');
const response = await fetch(`${apiBase}/api/orders/${orderId}/refresh`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${authToken}`,
'Content-Type': 'application/json'
}
});
const result = await response.json();
if (response.ok) {
if (result.updated) {
showToast(`订单状态已更新: ${result.new_status}`, 'success');
} else {
showToast(result.message || '订单状态无变化', 'info');
}
// 刷新订单列表
await refreshOrdersData();
} else {
showToast(`刷新失败: ${result.detail || '未知错误'}`, 'danger');
}
} catch (error) {
console.error('刷新订单状态失败:', error);
showToast('刷新订单状态失败: ' + error.message, 'danger');
}
}
// 切换全选订单
function toggleSelectAllOrders(checkbox) {
const orderCheckboxes = document.querySelectorAll('.order-checkbox');
+148 -43
View File
@@ -328,6 +328,10 @@ class OrderDetailFetcher:
# 获取并解析SKU信息
sku_info = await self._get_sku_content()
# 获取订单状态
order_status = await self._get_order_status()
logger.info(f"订单 {order_id} 状态: {order_status}")
# 获取页面标题
try:
title = await self.page.title()
@@ -346,6 +350,7 @@ class OrderDetailFetcher:
'spec_value_2': sku_info.get('spec_value_2', '') if sku_info else '', # 规格2值
'quantity': sku_info.get('quantity', '') if sku_info else '', # 数量
'amount': sku_info.get('amount', '') if sku_info else '', # 金额
'order_status': order_status, # 订单状态
'timestamp': time.time(),
'from_cache': False # 标记数据来源
}
@@ -442,6 +447,100 @@ class OrderDetailFetcher:
logger.error(f"解析SKU内容异常: {e}")
return {}
async def _get_order_status(self) -> str:
"""
从订单详情页面获取订单状态
Returns:
订单状态字符串,可能的值:
- 'success': 交易成功
- 'closed': 交易关闭
- 'pending_payment': 待付款
- 'pending_delivery': 待发货
- 'shipped': 已发货/待收货
- 'refunding': 退款中
- 'unknown': 未知状态
"""
try:
if not await self._check_browser_status():
logger.error("浏览器状态异常,无法获取订单状态")
return 'unknown'
# 尝试多种选择器获取订单状态
status_selectors = [
'.orderStatusText--F6eoVcHD', # 常见的订单状态选择器
'.order-status',
'.status-text',
'[class*="orderStatus"]',
'[class*="StatusText"]',
]
status_text = ''
for selector in status_selectors:
try:
element = await self.page.query_selector(selector)
if element:
text = await element.text_content()
if text:
status_text = text.strip()
logger.info(f"通过选择器 {selector} 获取到订单状态: {status_text}")
break
except Exception as e:
logger.debug(f"选择器 {selector} 获取失败: {e}")
continue
# 如果选择器都失败,尝试从页面文本中提取
if not status_text:
try:
page_content = await self.page.content()
# 检查常见的状态文本
status_patterns = [
('交易成功', 'success'),
('交易关闭', 'closed'),
('已关闭', 'closed'),
('待付款', 'pending_payment'),
('待发货', 'pending_delivery'),
('已发货', 'shipped'),
('待收货', 'shipped'),
('退款中', 'refunding'),
('退款成功', 'refunded'),
]
for pattern, status in status_patterns:
if pattern in page_content:
logger.info(f"从页面内容中检测到订单状态: {pattern} -> {status}")
return status
except Exception as e:
logger.warning(f"从页面内容获取状态失败: {e}")
# 解析状态文本
if status_text:
status_mapping = {
'交易成功': 'success',
'交易关闭': 'closed',
'已关闭': 'closed',
'待付款': 'pending_payment',
'待发货': 'pending_delivery',
'已发货': 'shipped',
'待收货': 'shipped',
'退款中': 'refunding',
'退款成功': 'refunded',
}
for text, status in status_mapping.items():
if text in status_text:
logger.info(f"订单状态解析: {status_text} -> {status}")
return status
logger.warning(f"未知的订单状态文本: {status_text}")
return 'unknown'
logger.warning("无法获取订单状态")
return 'unknown'
except Exception as e:
logger.error(f"获取订单状态异常: {e}")
return 'unknown'
async def _get_sku_content(self) -> Optional[Dict[str, str]]:
"""获取并解析SKU内容,包括规格、数量和金额,支持双规格"""
try:
@@ -690,7 +789,7 @@ class OrderDetailFetcher:
# 便捷函数
async def fetch_order_detail_simple(order_id: str, cookie_string: str = None, headless: bool = True) -> Optional[Dict[str, Any]]:
async def fetch_order_detail_simple(order_id: str, cookie_string: str = None, headless: bool = True, force_refresh: bool = False) -> Optional[Dict[str, Any]]:
"""
简单的订单详情获取函数(优化版:先检查数据库,再初始化浏览器)
@@ -698,6 +797,7 @@ async def fetch_order_detail_simple(order_id: str, cookie_string: str = None, he
order_id: 订单ID
cookie_string: Cookie字符串,如果不提供则使用默认值
headless: 是否无头模式
force_refresh: 是否强制刷新(跳过缓存直接从闲鱼获取)
Returns:
订单详情字典,包含以下字段:
@@ -709,60 +809,65 @@ async def fetch_order_detail_simple(order_id: str, cookie_string: str = None, he
- spec_value: 规格值
- quantity: 数量
- amount: 金额
- order_status: 订单状态
- timestamp: 获取时间戳
失败时返回None
"""
# 先检查数据库中是否有有效数据
try:
from db_manager import db_manager
existing_order = db_manager.get_order_by_id(order_id)
# 如果不是强制刷新,先检查数据库中是否有有效数据
if not force_refresh:
try:
from db_manager import db_manager
existing_order = db_manager.get_order_by_id(order_id)
if existing_order:
# 检查金额字段是否有效
amount = existing_order.get('amount', '')
amount_valid = False
if existing_order:
# 检查金额字段是否有效
amount = existing_order.get('amount', '')
amount_valid = False
if amount:
amount_clean = str(amount).replace('¥', '').replace('', '').replace('$', '').strip()
try:
amount_value = float(amount_clean)
amount_valid = amount_value > 0
except (ValueError, TypeError):
amount_valid = False
if amount:
amount_clean = str(amount).replace('¥', '').replace('', '').replace('$', '').strip()
try:
amount_value = float(amount_clean)
amount_valid = amount_value > 0
except (ValueError, TypeError):
amount_valid = False
if amount_valid:
logger.info(f"📋 订单 {order_id} 已存在于数据库中且金额有效({amount}),直接返回缓存数据")
print(f"✅ 订单 {order_id} 使用缓存数据,跳过浏览器获取")
if amount_valid:
logger.info(f"📋 订单 {order_id} 已存在于数据库中且金额有效({amount}),直接返回缓存数据")
print(f"✅ 订单 {order_id} 使用缓存数据,跳过浏览器获取")
# 构建返回格式
result = {
'order_id': existing_order['order_id'],
'url': f"https://www.goofish.com/order-detail?orderId={order_id}&role=seller",
'title': f"订单详情 - {order_id}",
'sku_info': {
# 构建返回格式
result = {
'order_id': existing_order['order_id'],
'url': f"https://www.goofish.com/order-detail?orderId={order_id}&role=seller",
'title': f"订单详情 - {order_id}",
'sku_info': {
'spec_name': existing_order.get('spec_name', ''),
'spec_value': existing_order.get('spec_value', ''),
'spec_name_2': existing_order.get('spec_name_2', ''),
'spec_value_2': existing_order.get('spec_value_2', ''),
'quantity': existing_order.get('quantity', ''),
'amount': existing_order.get('amount', '')
},
'spec_name': existing_order.get('spec_name', ''),
'spec_value': existing_order.get('spec_value', ''),
'spec_name_2': existing_order.get('spec_name_2', ''),
'spec_value_2': existing_order.get('spec_value_2', ''),
'quantity': existing_order.get('quantity', ''),
'amount': existing_order.get('amount', '')
},
'spec_name': existing_order.get('spec_name', ''),
'spec_value': existing_order.get('spec_value', ''),
'spec_name_2': existing_order.get('spec_name_2', ''),
'spec_value_2': existing_order.get('spec_value_2', ''),
'quantity': existing_order.get('quantity', ''),
'amount': existing_order.get('amount', ''),
'order_status': existing_order.get('order_status', 'unknown'), # 添加订单状态
'timestamp': time.time(),
'from_cache': True
}
return result
else:
logger.info(f"📋 订单 {order_id} 存在于数据库中但金额无效({amount}),需要重新获取")
print(f"⚠️ 订单 {order_id} 金额无效,重新获取详情...")
except Exception as e:
logger.warning(f"检查数据库缓存失败: {e}")
'amount': existing_order.get('amount', ''),
'order_status': existing_order.get('order_status', 'unknown'), # 添加订单状态
'timestamp': time.time(),
'from_cache': True
}
return result
else:
logger.info(f"📋 订单 {order_id} 存在于数据库中但金额无效({amount}),需要重新获取")
print(f"⚠️ 订单 {order_id} 金额无效,重新获取详情...")
except Exception as e:
logger.warning(f"检查数据库缓存失败: {e}")
else:
logger.info(f"🔄 订单 {order_id} 强制刷新,跳过缓存检查")
print(f"🔄 订单 {order_id} 强制刷新模式...")
# 数据库中没有有效数据,使用浏览器获取
logger.info(f"🌐 订单 {order_id} 需要浏览器获取,开始初始化浏览器...")