手动发货太慢?RPA批量处理TikTok订单,效率提升2500%🚀
每天被TikTok订单发货淹没?打包、打印、发货到崩溃?别慌!作为影刀RPA的资深布道者,今天我要分享一个硬核技术方案,用RPA+AI智能批量处理TikTok订单发货,让你彻底告别手动发货的噩梦!
一、背景痛点:订单发货的"物流噩梦"
在TikTok电商运营中,订单发货是客户体验的关键环节,但手动处理简直就是一场效率灾难:
手动发货的十大痛点:
-
重复操作爆炸:每天处理几百个订单,重复打印、打包、发货到怀疑人生
-
信息核对繁琐:手动核对订单信息、地址、商品规格,眼都要看花
-
物流单号混乱:不同平台、不同物流商的单号管理混乱不堪
-
打包效率低下:手动测量商品、选择包装、打印面单,效率极低
-
错误发货频发:人工操作容易发错货、发漏货,造成客户投诉
-
多平台协调难:需要在TikTok、ERP、WMS、物流系统间来回切换
-
库存更新滞后:发货后库存无法实时更新,导致超卖
-
数据统计缺失:手动发货难以统计发货时效和物流表现
-
规模扩展困难:订单量增加时,人工打包根本无法应对
-
客户体验差:发货慢、错误多,客户满意度直线下降
数据冲击:按每个订单手动处理平均耗时8分钟计算,每天处理100个订单就要800分钟!这时间本可以用来优化产品策略或分析客户行为。
灵魂拷问 :当竞争对手用自动化系统秒级处理发货时,你还要苦哈哈地一个个手动打包吗?今天,我们就用影刀RPA彻底颠覆传统订单发货方式!
二、解决方案:智能订单发货工作流设计
我们的核心思路是构建一个AI赋能的自动化发货系统,实现从订单获取到物流跟踪的全链路自动化。
整体架构:
订单自动获取 → 智能订单分组 → 物流方案优化 → 面单批量打印 → 智能打包推荐 → 发货状态更新 → 库存自动扣减 → 客户通知发送 → 物流实时跟踪
技术亮点:
-
智能订单分组:基于收货地址、商品类型自动优化发货批次
-
物流方案优化:根据重量、时效、成本智能选择最优物流
-
面单批量生成:自动生成并批量打印所有发货面单
-
打包智能推荐:基于商品尺寸自动推荐最佳包装方案
-
多系统数据同步:自动同步发货状态到所有相关系统
-
实时异常检测:自动发现异常订单,及时人工干预
这个方案不仅开箱即用,还能通过机器学习不断优化发货效率!
三、代码实现:手把手搭建订单发货机器人
下面我用影刀RPA的设计思路和详细代码,带你一步步构建这个智能发货系统。
环境准备
-
工具:影刀RPA社区版 + 硬件自动化组件
-
硬件:打印机、扫码枪、电子秤(可选)
-
系统:TikTok Seller Center、ERP、WMS
-
物流:快递鸟、菜鸟、顺丰等物流API
核心代码实现
# TikTok订单批量发货处理系统
from shadowbot import Browser, Excel, Database, Hardware, System, Email
import pandas as pd
from datetime import datetime, timedelta
import requests
import json
import time
from collections import defaultdict
import warnings
warnings.filterwarnings('ignore')
class TiktokOrderFulfillment:
def __init__(self):
self.pending_orders = []
self.processed_orders = {}
self.shipping_methods = {}
self.inventory_data = {}
def main_flow(self):
"""主流程:从订单获取到发货完成"""
try:
print("🚀 启动TikTok订单批量发货处理系统...")
# 步骤1:加载基础配置
self.load_base_config()
# 步骤2:获取待处理订单
self.fetch_pending_orders()
# 步骤3:订单智能预处理
self.preprocess_orders()
# 步骤4:批量发货处理
self.batch_process_orders()
# 步骤5:生成发货报告
self.generate_fulfillment_report()
# 步骤6:客户通知发送
self.send_customer_notifications()
print(f"🎉 订单发货完成!成功处理 {len(self.processed_orders)} 个订单")
except Exception as e:
print(f"❌ 系统执行失败: {e}")
self.error_handling(e)
def load_base_config(self):
"""加载基础配置"""
print("📥 加载基础配置...")
# 加载物流配置
self.load_shipping_config()
# 加载库存数据
self.load_inventory_data()
# 加载包装材料数据
self.load_packaging_data()
# 加载自动化硬件配置
self.load_hardware_config()
def load_shipping_config(self):
"""加载物流配置"""
print(" 🚚 加载物流配置...")
try:
# 从数据库加载物流商配置
shipping_df = Database.query("""
SELECT carrier_code, carrier_name, api_config, cost_rules,
delivery_time, weight_limits, enabled
FROM shipping_carriers
WHERE enabled = 1
""")
for _, row in shipping_df.iterrows():
self.shipping_methods[row['carrier_code']] = {
'name': row['carrier_name'],
'api_config': json.loads(row['api_config']),
'cost_rules': json.loads(row['cost_rules']),
'delivery_time': row['delivery_time'],
'weight_limits': json.loads(row['weight_limits'])
}
print(f" ✅ 成功加载 {len(self.shipping_methods)} 个物流商")
except Exception as e:
print(f" ⚠️ 物流配置加载失败: {e}")
self.load_default_shipping_config()
def load_default_shipping_config(self):
"""加载默认物流配置"""
self.shipping_methods = {
'SF': {
'name': '顺丰速运',
'api_config': {'url': 'https://sf-api.com', 'key': 'your_key'},
'cost_rules': {'base': 12, 'per_kg': 2},
'delivery_time': '1-2天',
'weight_limits': {'min': 0.1, 'max': 20}
},
'YT': {
'name': '圆通速递',
'api_config': {'url': 'https://yto-api.com', 'key': 'your_key'},
'cost_rules': {'base': 8, 'per_kg': 1},
'delivery_time': '2-3天',
'weight_limits': {'min': 0.1, 'max': 30}
},
'ZD': {
'name': '中通快递',
'api_config': {'url': 'https://zto-api.com', 'key': 'your_key'},
'cost_rules': {'base': 7, 'per_kg': 0.8},
'delivery_time': '2-4天',
'weight_limits': {'min': 0.1, 'max': 25}
}
}
def load_inventory_data(self):
"""加载库存数据"""
print(" 📦 加载库存数据...")
try:
inventory_df = Database.query("""
SELECT product_sku, warehouse_location, current_stock,
reserved_stock, product_weight, product_dimensions
FROM product_inventory
""")
self.inventory_data = inventory_df.set_index('product_sku').to_dict('index')
except Exception as e:
print(f" ⚠️ 库存数据加载失败: {e}")
self.inventory_data = {}
def load_packaging_data(self):
"""加载包装材料数据"""
print(" 📦 加载包装材料数据...")
self.packaging_materials = {
'envelope': {
'name': '快递信封',
'cost': 0.5,
'weight': 0.05,
'dimensions': {'length': 30, 'width': 20, 'height': 1},
'max_weight': 0.5
},
'small_box': {
'name': '小号纸箱',
'cost': 1.5,
'weight': 0.2,
'dimensions': {'length': 25, 'width': 18, 'height': 10},
'max_weight': 3
},
'medium_box': {
'name': '中号纸箱',
'cost': 2.5,
'weight': 0.4,
'dimensions': {'length': 35, 'width': 25, 'height': 15},
'max_weight': 10
},
'large_box': {
'name': '大号纸箱',
'cost': 4.0,
'weight': 0.6,
'dimensions': {'length': 45, 'width': 35, 'height': 25},
'max_weight': 20
}
}
def load_hardware_config(self):
"""加载自动化硬件配置"""
print(" 🔌 加载硬件配置...")
self.hardware_config = {
'printer': {
'type': 'thermal',
'connection': 'USB',
'paper_width': 100
},
'scanner': {
'type': 'barcode',
'connection': 'USB'
},
'scale': {
'type': 'electronic',
'connection': 'USB',
'max_weight': 30
}
}
def fetch_pending_orders(self):
"""获取待处理订单"""
print("📨 获取待处理订单...")
try:
# 初始化浏览器
browser = self.init_browser()
# 登录TikTok商家后台
self.login_seller_center(browser)
# 导航到订单管理页面
self.navigate_to_orders_page(browser)
# 获取待发货订单列表
self.extract_pending_orders(browser)
# 关闭浏览器
browser.quit()
print(f"✅ 成功获取 {len(self.pending_orders)} 个待发货订单")
except Exception as e:
print(f"❌ 订单获取失败: {e}")
# 使用备选方案从数据库获取
self.fetch_orders_from_database()
def init_browser(self):
"""初始化浏览器环境"""
browser = Browser.open_browser("chrome")
Browser.set_window_size(browser, 1400, 900)
Browser.set_timeout(browser, 30)
Browser.set_headers(browser, {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Accept-Language': 'en-US,en;q=0.9'
})
return browser
def login_seller_center(self, browser):
"""登录商家后台"""
print(" 🔐 登录TikTok商家后台...")
try:
Browser.navigate_to(browser, "https://seller.tiktok.com")
System.wait(5)
if not self.check_seller_login(browser):
self.perform_seller_login(browser)
print(" ✅ 商家后台登录成功")
except Exception as e:
raise Exception(f"商家后台登录失败: {e}")
def check_seller_login(self, browser):
"""检查登录状态"""
try:
dashboard_element = Browser.find_element(browser, "xpath",
"//div[contains(text(), 'Dashboard')]")
return dashboard_element is not None
except:
return False
def perform_seller_login(self, browser):
"""执行登录"""
# 这里需要配置实际的登录信息
username = "your_seller_username"
password = "your_seller_password"
try:
# 点击登录按钮
login_btn = Browser.find_element(browser, "xpath",
"//button[contains(text(), 'Log in')]")
Browser.click(login_btn)
System.wait(3)
# 输入用户名
username_input = Browser.find_element(browser, "xpath",
"//input[@type='email']")
Browser.input_text(username_input, username)
# 点击继续
continue_btn = Browser.find_element(browser, "xpath",
"//button[contains(text(), 'Continue')]")
Browser.click(continue_btn)
System.wait(3)
# 输入密码
password_input = Browser.find_element(browser, "xpath",
"//input[@type='password']")
Browser.input_text(password_input, password)
# 点击登录
submit_btn = Browser.find_element(browser, "xpath",
"//button[@type='submit']")
Browser.click(submit_btn)
# 等待登录完成
System.wait(10)
if not self.check_seller_login(browser):
raise Exception("登录验证失败")
except Exception as e:
raise Exception(f"登录过程失败: {e}")
def navigate_to_orders_page(self, browser):
"""导航到订单管理页面"""
try:
# 点击订单管理菜单
orders_menu = Browser.find_element(browser, "xpath",
"//span[contains(text(), 'Orders')]")
Browser.click(orders_menu)
System.wait(3)
# 点击待发货订单筛选
pending_filter = Browser.find_element(browser, "xpath",
"//span[contains(text(), 'To Ship')]")
Browser.click(pending_filter)
System.wait(3)
except Exception as e:
raise Exception(f"导航到订单页面失败: {e}")
def extract_pending_orders(self, browser):
"""提取待发货订单"""
try:
# 查找订单表格
orders_table = Browser.find_element(browser, "xpath",
"//table[contains(@class, 'orders-table')]")
# 提取订单行
order_rows = Browser.find_elements(browser, "xpath",
"//tr[contains(@class, 'order-row')]")
for row in order_rows:
order_data = self.extract_single_order(row)
if order_data:
self.pending_orders.append(order_data)
except Exception as e:
raise Exception(f"提取订单列表失败: {e}")
def extract_single_order(self, row_element):
"""提取单个订单数据"""
try:
# 提取订单基本信息
cells = Browser.find_elements(row_element, "xpath", "./td")
if len(cells) < 8:
return None
order_data = {
'order_id': Browser.get_text(cells[0]),
'order_date': Browser.get_text(cells[1]),
'customer_name': Browser.get_text(cells[2]),
'customer_address': Browser.get_text(cells[3]),
'product_sku': Browser.get_text(cells[4]),
'quantity': int(Browser.get_text(cells[5])),
'total_amount': float(Browser.get_text(cells[6]).replace('$', '')),
'order_status': Browser.get_text(cells[7]),
'shipping_method': None,
'tracking_number': None,
'package_weight': 0,
'shipping_cost': 0,
'package_size': None
}
# 点击查看详情获取完整信息
detail_btn = Browser.find_element(row_element, "xpath",
".//button[contains(text(), 'Details')]")
Browser.click(detail_btn)
System.wait(2)
# 提取订单详细内容
self.extract_order_details(order_data)
return order_data
except Exception as e:
print(f"提取单个订单失败: {e}")
return None
def extract_order_details(self, order_data):
"""提取订单详细信息"""
try:
# 提取客户联系电话
phone_element = Browser.find_element(browser, "xpath",
"//div[contains(text(), 'Phone')]")
if phone_element:
order_data['customer_phone'] = Browser.get_text(phone_element).replace('Phone:', '').strip()
# 提取商品规格
spec_element = Browser.find_element(browser, "xpath",
"//div[contains(@class, 'product-spec')]")
if spec_element:
order_data['product_spec'] = Browser.get_text(spec_element)
# 提取特殊要求
note_element = Browser.find_element(browser, "xpath",
"//div[contains(@class, 'customer-note')]")
if note_element:
order_data['customer_note'] = Browser.get_text(note_element)
except Exception as e:
print(f"提取订单详情失败: {e}")
def fetch_orders_from_database(self):
"""从数据库获取订单(备选方案)"""
try:
orders_df = Database.query("""
SELECT order_id, order_date, customer_name, customer_address,
product_sku, quantity, total_amount, order_status,
customer_phone, product_spec, customer_note
FROM tiktok_orders
WHERE order_status = 'pending_shipment'
AND order_date >= DATE_SUB(NOW(), INTERVAL 7 DAY)
ORDER BY order_date ASC
""")
for _, row in orders_df.iterrows():
self.pending_orders.append({
'order_id': row['order_id'],
'order_date': row['order_date'],
'customer_name': row['customer_name'],
'customer_address': row['customer_address'],
'product_sku': row['product_sku'],
'quantity': row['quantity'],
'total_amount': row['total_amount'],
'order_status': row['order_status'],
'customer_phone': row['customer_phone'],
'product_spec': row['product_spec'],
'customer_note': row['customer_note'],
'shipping_method': None,
'tracking_number': None,
'package_weight': 0,
'shipping_cost': 0,
'package_size': None
})
print(f"✅ 从数据库获取 {len(self.pending_orders)} 个待发货订单")
except Exception as e:
print(f"❌ 数据库获取订单失败: {e}")
def preprocess_orders(self):
"""订单智能预处理"""
print("🔧 订单智能预处理...")
for order in self.pending_orders:
try:
# 库存检查
self.check_inventory_availability(order)
# 计算包裹重量和尺寸
self.calculate_package_details(order)
# 选择最优物流方案
self.select_optimal_shipping(order)
# 推荐包装材料
self.recommend_packaging(order)
# 计算预估运费
self.calculate_shipping_cost(order)
print(f" ✅ 订单 {order['order_id']} 预处理完成")
except Exception as e:
print(f" ❌ 订单 {order['order_id']} 预处理失败: {e}")
order['processable'] = False
order['error'] = str(e)
def check_inventory_availability(self, order):
"""检查库存可用性"""
sku = order['product_sku']
quantity = order['quantity']
if sku in self.inventory_data:
inventory = self.inventory_data[sku]
if inventory['current_stock'] - inventory['reserved_stock'] >= quantity:
order['inventory_available'] = True
order['warehouse_location'] = inventory['warehouse_location']
else:
order['inventory_available'] = False
raise Exception(f"库存不足: 需要{quantity},可用{inventory['current_stock'] - inventory['reserved_stock']}")
else:
order['inventory_available'] = False
raise Exception(f"商品SKU不存在: {sku}")
def calculate_package_details(self, order):
"""计算包裹重量和尺寸"""
sku = order['product_sku']
quantity = order['quantity']
if sku in self.inventory_data:
product_data = self.inventory_data[sku]
# 计算总重量
if 'product_weight' in product_data:
order['package_weight'] = product_data['product_weight'] * quantity
else:
# 默认重量估算
order['package_weight'] = 0.5 * quantity
# 估算包裹尺寸
if 'product_dimensions' in product_data:
dims = product_data['product_dimensions']
# 简化的尺寸计算(实际应该更复杂)
order['package_size'] = {
'length': dims['length'],
'width': dims['width'],
'height': dims['height'] * quantity
}
else:
# 默认尺寸
order['package_size'] = {'length': 20, 'width': 15, 'height': 10 * quantity}
else:
# 使用默认值
order['package_weight'] = 0.5 * quantity
order['package_size'] = {'length': 20, 'width': 15, 'height': 10 * quantity}
def select_optimal_shipping(self, order):
"""选择最优物流方案"""
weight = order['package_weight']
address = order['customer_address']
suitable_carriers = []
for carrier_code, carrier_info in self.shipping_methods.items():
limits = carrier_info['weight_limits']
# 检查重量限制
if limits['min'] <= weight <= limits['max']:
# 计算运费
cost = self.calculate_shipping_cost_for_carrier(carrier_info, weight, address)
suitable_carriers.append({
'carrier_code': carrier_code,
'carrier_name': carrier_info['name'],
'cost': cost,
'delivery_time': carrier_info['delivery_time'],
'score': self.calculate_shipping_score(carrier_info, cost, weight, address)
})
if suitable_carriers:
# 选择评分最高的物流商
best_carrier = max(suitable_carriers, key=lambda x: x['score'])
order['shipping_method'] = best_carrier['carrier_code']
order['shipping_carrier_name'] = best_carrier['carrier_name']
order['estimated_delivery'] = best_carrier['delivery_time']
else:
raise Exception("没有合适的物流商")
def calculate_shipping_cost_for_carrier(self, carrier_info, weight, address):
"""计算特定物流商的运费"""
cost_rules = carrier_info['cost_rules']
# 基础运费 + 续重运费
base_cost = cost_rules['base']
additional_cost = max(0, weight - 1) * cost_rules.get('per_kg', 0)
return base_cost + additional_cost
def calculate_shipping_score(self, carrier_info, cost, weight, address):
"""计算物流商综合评分"""
score = 0
# 成本得分(40%)
max_reasonable_cost = 20 # 假设最高合理运费
cost_score = max(0, 1 - (cost / max_reasonable_cost))
score += cost_score * 0.4
# 时效得分(30%)
delivery_time = carrier_info['delivery_time']
if '1' in delivery_time:
time_score = 1.0
elif '2' in delivery_time:
time_score = 0.8
elif '3' in delivery_time:
time_score = 0.6
else:
time_score = 0.4
score += time_score * 0.3
# 可靠性得分(20%)
# 这里可以接入历史物流数据
reliability_score = 0.8
score += reliability_score * 0.2
# 覆盖范围得分(10%)
coverage_score = 1.0 # 假设全覆盖
score += coverage_score * 0.1
return score
def recommend_packaging(self, order):
"""推荐包装材料"""
weight = order['package_weight']
size = order['package_size']
volume = size['length'] * size['width'] * size['height']
for material_type, material_info in self.packaging_materials.items():
max_vol = (material_info['dimensions']['length'] *
material_info['dimensions']['width'] *
material_info['dimensions']['height'])
if (weight <= material_info['max_weight'] and
volume <= max_vol * 0.8): # 留20%余量
order['recommended_package'] = material_type
order['package_cost'] = material_info['cost']
order['package_weight_total'] = weight + material_info['weight']
return
# 如果没有合适的包装,使用大号纸箱
order['recommended_package'] = 'large_box'
order['package_cost'] = self.packaging_materials['large_box']['cost']
order['package_weight_total'] = weight + self.packaging_materials['large_box']['weight']
def calculate_shipping_cost(self, order):
"""计算总运费"""
weight = order['package_weight_total']
carrier_code = order['shipping_method']
if carrier_code in self.shipping_methods:
carrier_info = self.shipping_methods[carrier_code]
order['shipping_cost'] = self.calculate_shipping_cost_for_carrier(
carrier_info, weight, order['customer_address']
)
else:
order['shipping_cost'] = 10 # 默认运费
def batch_process_orders(self):
"""批量处理订单"""
print("🔄 批量处理订单发货...")
processable_orders = [order for order in self.pending_orders
if order.get('inventory_available', False)]
successful_count = 0
failed_count = 0
for order in processable_orders:
try:
result = self.process_single_order(order)
if result['success']:
successful_count += 1
else:
failed_count += 1
# 记录处理结果
self.processed_orders[order['order_id']] = result
# 短暂延迟,避免操作过快
System.wait(1)
except Exception as e:
print(f" ❌ 订单 {order['order_id']} 处理失败: {e}")
failed_count += 1
self.processed_orders[order['order_id']] = {
'success': False,
'error': str(e),
'process_time': datetime.now()
}
print(f"✅ 成功处理 {successful_count} 个订单,失败 {failed_count} 个")
def process_single_order(self, order):
"""处理单个订单发货"""
print(f" 📦 处理订单发货: {order['order_id']}")
try:
# 生成物流单号
tracking_number = self.generate_tracking_number(order)
order['tracking_number'] = tracking_number
# 打印发货面单
self.print_shipping_label(order)
# 更新库存
self.update_inventory(order)
# 在TikTok后台标记发货
self.mark_as_shipped_in_tiktok(order)
# 同步到ERP系统
self.sync_to_erp_system(order)
return {
'success': True,
'tracking_number': tracking_number,
'shipping_method': order['shipping_carrier_name'],
'shipping_cost': order['shipping_cost'],
'process_time': datetime.now()
}
except Exception as e:
print(f" ❌ 订单 {order['order_id']} 发货失败: {e}")
return {
'success': False,
'error': str(e),
'process_time': datetime.now()
}
def generate_tracking_number(self, order):
"""生成物流单号"""
carrier_code = order['shipping_method']
# 这里应该调用物流商API获取真实单号
# 暂时使用模拟数据
prefix_map = {
'SF': 'SF',
'YT': 'YT',
'ZD': 'ZD'
}
prefix = prefix_map.get(carrier_code, 'TT')
timestamp = int(time.time())
random_num = random.randint(100000, 999999)
return f"{prefix}{timestamp}{random_num}"
def print_shipping_label(self, order):
"""打印发货面单"""
try:
# 生成面单HTML
label_html = self.generate_shipping_label_html(order)
# 调用打印机打印
Hardware.print_html(label_html, self.hardware_config['printer'])
print(f" 打印面单: {order['tracking_number']}")
except Exception as e:
raise Exception(f"打印面单失败: {e}")
def generate_shipping_label_html(self, order):
"""生成发货面单HTML"""
return f"""
<html>
<head>
<style>
body {{ font-family: Arial, sans-serif; margin: 0; padding: 10px; }}
.label {{ border: 1px solid #000; padding: 15px; width: 100mm; }}
.header {{ text-align: center; font-size: 16px; font-weight: bold; margin-bottom: 10px; }}
.section {{ margin-bottom: 8px; }}
.section-title {{ font-weight: bold; font-size: 12px; }}
.barcode {{ text-align: center; margin: 10px 0; }}
</style>
</head>
<body>
<div class="label">
<div class="header">发货面单</div>
<div class="section">
<div class="section-title">订单信息</div>
订单号: {order['order_id']}<br>
下单时间: {order['order_date']}
</div>
<div class="section">
<div class="section-title">收货信息</div>
{order['customer_name']}<br>
{order['customer_address']}<br>
{order.get('customer_phone', '')}
</div>
<div class="section">
<div class="section-title">商品信息</div>
{order['product_sku']} x {order['quantity']}<br>
{order.get('product_spec', '')}
</div>
<div class="section">
<div class="section-title">物流信息</div>
物流公司: {order['shipping_carrier_name']}<br>
运单号: {order['tracking_number']}<br>
预估时效: {order['estimated_delivery']}
</div>
<div class="barcode">
[条形码: {order['tracking_number']}]
</div>
<div class="section" style="text-align: center; font-size: 10px;">
打印时间: {datetime.now().strftime('%Y-%m-%d %H:%M')}
</div>
</div>
</body>
</html>
"""
def update_inventory(self, order):
"""更新库存"""
try:
sku = order['product_sku']
quantity = order['quantity']
# 更新数据库库存
Database.execute("""
UPDATE product_inventory
SET current_stock = current_stock - ?,
reserved_stock = reserved_stock - ?,
last_updated = NOW()
WHERE product_sku = ?
""", (quantity, quantity, sku))
print(f" 库存更新: {sku} -{quantity}")
except Exception as e:
raise Exception(f"库存更新失败: {e}")
def mark_as_shipped_in_tiktok(self, order):
"""在TikTok后台标记发货"""
try:
browser = self.init_browser()
# 登录商家后台
self.login_seller_center(browser)
# 导航到订单详情页
self.navigate_to_order_detail(browser, order['order_id'])
# 点击发货按钮
ship_btn = Browser.find_element(browser, "xpath",
"//button[contains(text(), 'Ship')]")
Browser.click(ship_btn)
System.wait(3)
# 输入物流信息
tracking_input = Browser.find_element(browser, "xpath",
"//input[@placeholder='Tracking number']")
Browser.input_text(tracking_input, order['tracking_number'])
carrier_dropdown = Browser.find_element(browser, "xpath",
"//select[@name='carrier']")
Browser.select_option(carrier_dropdown, order['shipping_method'])
# 确认发货
confirm_btn = Browser.find_element(browser, "xpath",
"//button[contains(text(), 'Confirm')]")
Browser.click(confirm_btn)
System.wait(5)
# 验证发货成功
if not self.verify_shipment_success(browser):
raise Exception("发货状态更新失败")
browser.quit()
print(f" TikTok后台标记发货成功")
except Exception as e:
raise Exception(f"TikTok后台标记发货失败: {e}")
def navigate_to_order_detail(self, browser, order_id):
"""导航到订单详情页"""
try:
# 搜索订单
search_input = Browser.find_element(browser, "xpath",
"//input[@placeholder='Search orders']")
Browser.input_text(search_input, order_id)
search_btn = Browser.find_element(browser, "xpath",