|
@@ -29,7 +29,8 @@ from .filter import ContainerDetailFilter,ContainerListFilter,ContainerOperation
|
|
from warehouse.models import ListModel as warehouse
|
|
from warehouse.models import ListModel as warehouse
|
|
from staff.models import ListModel as staff
|
|
from staff.models import ListModel as staff
|
|
from rest_framework.permissions import AllowAny
|
|
from rest_framework.permissions import AllowAny
|
|
-
|
|
|
|
|
|
+import threading
|
|
|
|
+from django.db import close_old_connections
|
|
logger = logging.getLogger(__name__)
|
|
logger = logging.getLogger(__name__)
|
|
class ContainerListViewSet(viewsets.ModelViewSet):
|
|
class ContainerListViewSet(viewsets.ModelViewSet):
|
|
"""
|
|
"""
|
|
@@ -275,7 +276,8 @@ class ContainerWCSViewSet(viewsets.ModelViewSet):
|
|
+ f"{int(location_list_cnumber.col):02d}" + '-'
|
|
+ f"{int(location_list_cnumber.col):02d}" + '-'
|
|
+ f"{int(location_list_cnumber.layer):02d}"
|
|
+ f"{int(location_list_cnumber.layer):02d}"
|
|
)
|
|
)
|
|
- self.generate_task(container, current_location, allocation_target_location) # 生成任务
|
|
|
|
|
|
+ batch_id = LocationAllocation.get_batch(container_code)
|
|
|
|
+ self.generate_task(container, current_location, allocation_target_location,batch_id,location_list_cnumber.c_number) # 生成任务
|
|
current_task = ContainerWCSModel.objects.get(
|
|
current_task = ContainerWCSModel.objects.get(
|
|
container=container,
|
|
container=container,
|
|
tasktype='inbound'
|
|
tasktype='inbound'
|
|
@@ -302,9 +304,20 @@ class ContainerWCSViewSet(viewsets.ModelViewSet):
|
|
)
|
|
)
|
|
|
|
|
|
@transaction.atomic
|
|
@transaction.atomic
|
|
- def generate_task(self, container, current_location, target_location):
|
|
|
|
|
|
+ def generate_task(self, container, current_location, target_location,batch_id,location_c_number):
|
|
|
|
+ batch = BoundBatchModel.objects.filter(bound_number=batch_id).first()
|
|
|
|
+ batch_detail = BoundDetailModel.objects.filter(bound_batch=batch).first()
|
|
|
|
+ if not batch:
|
|
|
|
+ logger.error(f"批次号 {batch_id} 不存在")
|
|
|
|
+ return False
|
|
data_tosave = {
|
|
data_tosave = {
|
|
'container': container,
|
|
'container': container,
|
|
|
|
+ 'batch': batch,
|
|
|
|
+ 'batch_out': None,
|
|
|
|
+ 'bound_list': batch_detail.bound_list,
|
|
|
|
+ 'sequence': 1,
|
|
|
|
+ 'order_number' :location_c_number,
|
|
|
|
+ 'priority': 1,
|
|
'current_location': current_location,
|
|
'current_location': current_location,
|
|
'month': timezone.now().strftime('%Y%m'),
|
|
'month': timezone.now().strftime('%Y%m'),
|
|
'target_location': target_location,
|
|
'target_location': target_location,
|
|
@@ -335,6 +348,9 @@ class ContainerWCSViewSet(viewsets.ModelViewSet):
|
|
data = self.request.data
|
|
data = self.request.data
|
|
container = data.get('container_number')
|
|
container = data.get('container_number')
|
|
current_location = data.get('current_location')
|
|
current_location = data.get('current_location')
|
|
|
|
+ taskNumber = data.get('taskNumber')
|
|
|
|
+
|
|
|
|
+
|
|
logger.info(f"请求托盘:{container},请求位置:{current_location}")
|
|
logger.info(f"请求托盘:{container},请求位置:{current_location}")
|
|
if current_location =="203":
|
|
if current_location =="203":
|
|
current_location ="in1"
|
|
current_location ="in1"
|
|
@@ -462,7 +478,8 @@ class ContainerWCSViewSet(viewsets.ModelViewSet):
|
|
+ f"{int(location_list_cnumber.col):02d}" + '-'
|
|
+ f"{int(location_list_cnumber.col):02d}" + '-'
|
|
+ f"{int(location_list_cnumber.layer):02d}"
|
|
+ f"{int(location_list_cnumber.layer):02d}"
|
|
)
|
|
)
|
|
- self.generate_task(container, current_location, allocation_target_location) # 生成任务
|
|
|
|
|
|
+ batch_id = allocator.get_batch(container_code)
|
|
|
|
+ self.generate_task(container, current_location, allocation_target_location,batch_id,location_list_cnumber.c_number) # 生成任务
|
|
current_task = ContainerWCSModel.objects.get(
|
|
current_task = ContainerWCSModel.objects.get(
|
|
container=container,
|
|
container=container,
|
|
tasktype='inbound'
|
|
tasktype='inbound'
|
|
@@ -793,6 +810,219 @@ class ContainerOperateViewSet(viewsets.ModelViewSet):
|
|
headers = self.get_success_headers(serializer.data)
|
|
headers = self.get_success_headers(serializer.data)
|
|
return Response(serializer.data, status=200, headers=headers)
|
|
return Response(serializer.data, status=200, headers=headers)
|
|
|
|
|
|
|
|
+
|
|
|
|
+class OutboundService:
|
|
|
|
+ @staticmethod
|
|
|
|
+ def generate_task_id():
|
|
|
|
+ """生成唯一任务ID(格式: outbound-年月-顺序号)"""
|
|
|
|
+ month = timezone.now().strftime("%Y%m")
|
|
|
|
+ last_task = ContainerWCSModel.objects.filter(
|
|
|
|
+ tasktype='outbound',
|
|
|
|
+ month=int(month)
|
|
|
|
+ ).order_by('-sequence').first()
|
|
|
|
+ sequence = last_task.sequence + 1 if last_task else 1
|
|
|
|
+ return f"outbound-{month}-{sequence:04d}"
|
|
|
|
+
|
|
|
|
+ # @staticmethod
|
|
|
|
+ # def send_task_to_wcs(task):
|
|
|
|
+ # """发送任务到WCS"""
|
|
|
|
+ # send_data = {
|
|
|
|
+ # "taskid": task.taskid,
|
|
|
|
+ # "container": task.container,
|
|
|
|
+ # "current_location": task.current_location,
|
|
|
|
+ # "target_location": task.target_location,
|
|
|
|
+ # "tasktype": task.tasktype,
|
|
|
|
+ # "month": task.month,
|
|
|
|
+ # "message": task.message,
|
|
|
|
+ # "status": task.status,
|
|
|
|
+ # "taskNumber": task.tasknumber
|
|
|
|
+ # }
|
|
|
|
+ # try:
|
|
|
|
+ # requests.post("http://127.0.0.1:8008/container/batch/", json=send_data, timeout=10)
|
|
|
|
+ # response = requests.post("http://192.168.18.67:1616//wcs/WebApi/getOutTask", json=send_data, timeout=10)
|
|
|
|
+ # if response.status_code == 200:
|
|
|
|
+ # task.status = 200
|
|
|
|
+ # task.save()/wcs/WebApi/getOutTask
|
|
|
|
+ # logger.info(f"任务 {task.taskid} 已发送")
|
|
|
|
+ # return True
|
|
|
|
+ # else:
|
|
|
|
+ # logger.error(f"WCS返回错误: {response.text}")
|
|
|
|
+ # task.status = 400
|
|
|
|
+ # task.save()
|
|
|
|
+ # return False
|
|
|
|
+ # except Exception as e:
|
|
|
|
+ # logger.error(f"发送失败: {str(e)}")
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ # return False
|
|
|
|
+
|
|
|
|
+ @staticmethod
|
|
|
|
+ def send_task_to_wcs(task):
|
|
|
|
+ """异步发送任务到WCS(非阻塞版本)"""
|
|
|
|
+ # 提取任务关键数据用于线程(避免直接传递ORM对象)
|
|
|
|
+ task_data = {
|
|
|
|
+ 'task_id': task.pk, # 使用主键而不是对象
|
|
|
|
+ 'send_data': {
|
|
|
|
+ "code":'200',
|
|
|
|
+ "message": task.message,
|
|
|
|
+ "data":{
|
|
|
|
+ "taskid": task.taskid,
|
|
|
|
+ "container": task.container,
|
|
|
|
+ "current_location": task.current_location,
|
|
|
|
+ "target_location": task.target_location,
|
|
|
|
+ "tasktype": task.tasktype,
|
|
|
|
+ "month": task.month,
|
|
|
|
+ "message": task.message,
|
|
|
|
+ "status": task.status,
|
|
|
|
+ "taskNumber": task.tasknumber,
|
|
|
|
+ "order_number":task.order_number,
|
|
|
|
+ "sequence":task.sequence
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ # 创建并启动线程
|
|
|
|
+ thread = threading.Thread(
|
|
|
|
+ target=OutboundService._async_send_handler,
|
|
|
|
+ kwargs=task_data,
|
|
|
|
+ daemon=True # 守护线程(主程序退出时自动终止)
|
|
|
|
+ )
|
|
|
|
+ thread.start()
|
|
|
|
+ return True # 立即返回表示已开始处理
|
|
|
|
+
|
|
|
|
+ @staticmethod
|
|
|
|
+ def _async_send_handler(task_id, send_data):
|
|
|
|
+ """异步处理的实际工作函数"""
|
|
|
|
+ try:
|
|
|
|
+ # 每个线程需要独立的数据库连接
|
|
|
|
+ close_old_connections()
|
|
|
|
+
|
|
|
|
+ # 重新获取任务对象(确保使用最新数据)
|
|
|
|
+ task = ContainerWCSModel.objects.get(pk=task_id)
|
|
|
|
+
|
|
|
|
+ # 发送第一个请求(不处理结果)
|
|
|
|
+ requests.post(
|
|
|
|
+ "http://127.0.0.1:8008/container/batch/",
|
|
|
|
+ json=send_data,
|
|
|
|
+ timeout=10
|
|
|
|
+ )
|
|
|
|
+
|
|
|
|
+ # 发送关键请求
|
|
|
|
+ response = requests.post(
|
|
|
|
+ "http://192.168.18.67:1616/wcs/WebApi/getOutTask",
|
|
|
|
+ json=send_data,
|
|
|
|
+ timeout=10
|
|
|
|
+ )
|
|
|
|
+
|
|
|
|
+ # 处理响应
|
|
|
|
+ if response.status_code == 200:
|
|
|
|
+ task.status = 200
|
|
|
|
+ task.save()
|
|
|
|
+ logger.info(f"任务 {task.taskid} 已发送")
|
|
|
|
+ else:
|
|
|
|
+ logger.error(f"WCS返回错误: {response.text}")
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ except Exception as e:
|
|
|
|
+ logger.error(f"发送失败: {str(e)}")
|
|
|
|
+
|
|
|
|
+ finally:
|
|
|
|
+ close_old_connections() # 清理数据库连接
|
|
|
|
+
|
|
|
|
+ @staticmethod
|
|
|
|
+ def create_initial_tasks(container_list,bound_list_id):
|
|
|
|
+ """生成初始任务队列"""
|
|
|
|
+ with transaction.atomic():
|
|
|
|
+ current_WCS = ContainerWCSModel.objects.filter(tasktype='outbound',bound_list_id = bound_list_id).first()
|
|
|
|
+ if current_WCS:
|
|
|
|
+ logger.error(f"当前{bound_list_id}已有出库任务")
|
|
|
|
+
|
|
|
|
+ return False
|
|
|
|
+ tasks = []
|
|
|
|
+ start_sequence = ContainerWCSModel.objects.filter(tasktype='outbound').count() + 1
|
|
|
|
+ tasknumber = ContainerWCSModel.objects.filter().count()
|
|
|
|
+ tasknumber_index = 1
|
|
|
|
+ for index, container in enumerate(container_list, start=start_sequence):
|
|
|
|
+ container_obj = ContainerListModel.objects.filter(id =container['container_number']).first()
|
|
|
|
+ if container_obj.current_location != container_obj.target_location:
|
|
|
|
+ logger.error(f"托盘 {container_obj.container_code} 未到达目的地,不生成任务")
|
|
|
|
+ return False
|
|
|
|
+ OutBoundDetail_obj = OutBoundDetailModel.objects.filter(bound_list=bound_list_id,bound_batch_number_id=container['batch_id']).first()
|
|
|
|
+ if not OutBoundDetail_obj:
|
|
|
|
+ logger.error(f"批次 {container['batch_id']} 不存在")
|
|
|
|
+ return False
|
|
|
|
+ month = int(timezone.now().strftime("%Y%m"))
|
|
|
|
+ task = ContainerWCSModel(
|
|
|
|
+ taskid=OutboundService.generate_task_id(),
|
|
|
|
+ batch = OutBoundDetail_obj.bound_batch_number,
|
|
|
|
+ batch_out = OutBoundDetail_obj.bound_batch,
|
|
|
|
+ bound_list = OutBoundDetail_obj.bound_list,
|
|
|
|
+ sequence=index,
|
|
|
|
+ order_number = container['location_c_number'],
|
|
|
|
+ priority=100,
|
|
|
|
+ tasknumber = month*10000+tasknumber_index+tasknumber,
|
|
|
|
+ container=container_obj.container_code,
|
|
|
|
+ current_location=container_obj.current_location,
|
|
|
|
+ target_location="103",
|
|
|
|
+ tasktype="outbound",
|
|
|
|
+ month=int(timezone.now().strftime("%Y%m")),
|
|
|
|
+ message="等待出库",
|
|
|
|
+ status=100,
|
|
|
|
+ )
|
|
|
|
+ tasknumber_index += 1
|
|
|
|
+ tasks.append(task)
|
|
|
|
+ ContainerWCSModel.objects.bulk_create(tasks)
|
|
|
|
+ logger.info(f"已创建 {len(tasks)} 个初始任务")
|
|
|
|
+
|
|
|
|
+ @staticmethod
|
|
|
|
+ def insert_new_tasks(new_tasks):
|
|
|
|
+ """动态插入新任务并重新排序"""
|
|
|
|
+ with transaction.atomic():
|
|
|
|
+ pending_tasks = list(ContainerWCSModel.objects.select_for_update().filter(status=100))
|
|
|
|
+
|
|
|
|
+ # 插入新任务
|
|
|
|
+ for new_task_data in new_tasks:
|
|
|
|
+ new_task = ContainerWCSModel(
|
|
|
|
+ taskid=OutboundService.generate_task_id(),
|
|
|
|
+ priority=new_task_data.get('priority', 100),
|
|
|
|
+ container=new_task_data['container'],
|
|
|
|
+ current_location=new_task_data['current_location'],
|
|
|
|
+ target_location=new_task_data.get('target_location', 'OUT01'),
|
|
|
|
+ tasktype="outbound",
|
|
|
|
+ month=int(timezone.now().strftime("%Y%m")),
|
|
|
|
+ message="等待出库",
|
|
|
|
+ status=100,
|
|
|
|
+ )
|
|
|
|
+ # 找到插入位置
|
|
|
|
+ insert_pos = 0
|
|
|
|
+ for i, task in enumerate(pending_tasks):
|
|
|
|
+ if new_task.priority < task.priority:
|
|
|
|
+ insert_pos = i
|
|
|
|
+ break
|
|
|
|
+ else:
|
|
|
|
+ insert_pos = len(pending_tasks)
|
|
|
|
+ pending_tasks.insert(insert_pos, new_task)
|
|
|
|
+
|
|
|
|
+ # 重新分配顺序号
|
|
|
|
+ for i, task in enumerate(pending_tasks, start=1):
|
|
|
|
+ task.sequence = i
|
|
|
|
+ if task.pk is None:
|
|
|
|
+ task.save()
|
|
|
|
+ else:
|
|
|
|
+ task.save(update_fields=['sequence'])
|
|
|
|
+
|
|
|
|
+ logger.info(f"已插入 {len(new_tasks)} 个新任务")
|
|
|
|
+
|
|
|
|
+ @staticmethod
|
|
|
|
+ def process_next_task():
|
|
|
|
+ """处理下一个任务"""
|
|
|
|
+ next_task = ContainerWCSModel.objects.filter(status=100).order_by('sequence').first()
|
|
|
|
+ if not next_task:
|
|
|
|
+ logger.info("没有待处理任务")
|
|
|
|
+ return
|
|
|
|
+ OutboundService.send_task_to_wcs(next_task)
|
|
|
|
+
|
|
|
|
+
|
|
class OutTaskViewSet(viewsets.ModelViewSet):
|
|
class OutTaskViewSet(viewsets.ModelViewSet):
|
|
|
|
|
|
"""
|
|
"""
|
|
@@ -807,27 +1037,35 @@ class OutTaskViewSet(viewsets.ModelViewSet):
|
|
try:
|
|
try:
|
|
data = self.request.data
|
|
data = self.request.data
|
|
logger.info(f"收到 WMS 推送数据: {data}")
|
|
logger.info(f"收到 WMS 推送数据: {data}")
|
|
- send_data= {
|
|
|
|
- "container": "12345",
|
|
|
|
- "current_location": "in1",
|
|
|
|
- "month": 202503,
|
|
|
|
- "current_location": "W01-01-01-01",
|
|
|
|
- "target_location": "W01-01-01-01",
|
|
|
|
- "tasktype": "inbound",
|
|
|
|
- "taskid": "inbound-202503-0001",
|
|
|
|
- "message": "生成入库任务",
|
|
|
|
- "status": 103
|
|
|
|
- }
|
|
|
|
- post_json_to_url("http://127.0.0.1:8008/container/batch/", send_data)
|
|
|
|
|
|
+
|
|
|
|
+ # 假设从请求中获取 bound_list_id
|
|
|
|
+ bound_list_id = data.get('bound_list_id')
|
|
|
|
+ batch_count = self.get_batch_count_by_boundlist(bound_list_id)
|
|
|
|
+
|
|
|
|
+ logger.info(f"出库批次数量: {batch_count}")
|
|
|
|
+ # 获取需要出库的托盘列表
|
|
|
|
+ generate_result = self.generate_location_by_demand(batch_count)
|
|
|
|
+ if generate_result['code'] != '200':
|
|
|
|
+ return Response(generate_result, status=500)
|
|
|
|
+ container_list = generate_result['data']
|
|
|
|
+
|
|
|
|
+ logger.info(f"生成出库任务: {container_list}")
|
|
|
|
+ # 2. 生成初始任务
|
|
|
|
+ OutboundService.create_initial_tasks(container_list,bound_list_id)
|
|
|
|
+
|
|
|
|
+ # 3. 立即发送第一个任务
|
|
|
|
+ OutboundService.process_next_task()
|
|
|
|
+
|
|
return Response({"code": "200", "msg": "Success"}, status=200)
|
|
return Response({"code": "200", "msg": "Success"}, status=200)
|
|
except Exception as e:
|
|
except Exception as e:
|
|
|
|
+ logger.error(f"任务生成失败: {str(e)}")
|
|
return Response({"code": "500", "msg": str(e)}, status=500)
|
|
return Response({"code": "500", "msg": str(e)}, status=500)
|
|
|
|
|
|
def get_batch_count_by_boundlist(self,bound_list_id):
|
|
def get_batch_count_by_boundlist(self,bound_list_id):
|
|
try:
|
|
try:
|
|
bound_list_obj_all = OutBoundDetailModel.objects.filter(bound_list=bound_list_id).all()
|
|
bound_list_obj_all = OutBoundDetailModel.objects.filter(bound_list=bound_list_id).all()
|
|
if bound_list_obj_all:
|
|
if bound_list_obj_all:
|
|
- logger.info(f"查询批次数量成功: {bound_list_obj_all.count()}")
|
|
|
|
|
|
+
|
|
batch_count_dict = {}
|
|
batch_count_dict = {}
|
|
# 统计批次数量(创建哈希表,去重)
|
|
# 统计批次数量(创建哈希表,去重)
|
|
for batch in bound_list_obj_all:
|
|
for batch in bound_list_obj_all:
|
|
@@ -843,12 +1081,11 @@ class OutTaskViewSet(viewsets.ModelViewSet):
|
|
logger.error(f"查询批次数量失败: {str(e)}")
|
|
logger.error(f"查询批次数量失败: {str(e)}")
|
|
return {}
|
|
return {}
|
|
|
|
|
|
-
|
|
|
|
def get_location_by_status_and_batch(self,status,bound_id):
|
|
def get_location_by_status_and_batch(self,status,bound_id):
|
|
try:
|
|
try:
|
|
container_obj = ContainerDetailModel.objects.filter(batch=bound_id,status=status).all()
|
|
container_obj = ContainerDetailModel.objects.filter(batch=bound_id,status=status).all()
|
|
if container_obj:
|
|
if container_obj:
|
|
- logger.info(f"查询{status}状态的批次数量成功: {container_obj.count()}")
|
|
|
|
|
|
+
|
|
container_dict = {}
|
|
container_dict = {}
|
|
# 统计托盘数量(创建哈希表,去重)
|
|
# 统计托盘数量(创建哈希表,去重)
|
|
for obj in container_obj:
|
|
for obj in container_obj:
|
|
@@ -863,7 +1100,8 @@ class OutTaskViewSet(viewsets.ModelViewSet):
|
|
except Exception as e:
|
|
except Exception as e:
|
|
logger.error(f"查询{status}状态的批次数量失败: {str(e)}")
|
|
logger.error(f"查询{status}状态的批次数量失败: {str(e)}")
|
|
return {}
|
|
return {}
|
|
- def get_order_by_batch(self,container_list):
|
|
|
|
|
|
+
|
|
|
|
+ def get_order_by_batch(self,container_list,bound_id):
|
|
try:
|
|
try:
|
|
container_dict = {}
|
|
container_dict = {}
|
|
for container in container_list:
|
|
for container in container_list:
|
|
@@ -875,7 +1113,8 @@ class OutTaskViewSet(viewsets.ModelViewSet):
|
|
"container_number":container,
|
|
"container_number":container,
|
|
"location_c_number":location_c_number,
|
|
"location_c_number":location_c_number,
|
|
"location_id ":location_container.location.id,
|
|
"location_id ":location_container.location.id,
|
|
- "location_type":location_container.location.location_type
|
|
|
|
|
|
+ "location_type":location_container.location.location_type,
|
|
|
|
+ "batch_id":bound_id,
|
|
}
|
|
}
|
|
|
|
|
|
if len(container_dict.keys()) == len(container_list):
|
|
if len(container_dict.keys()) == len(container_list):
|
|
@@ -901,7 +1140,7 @@ class OutTaskViewSet(viewsets.ModelViewSet):
|
|
if not container_list:
|
|
if not container_list:
|
|
return {"code": "500", "msg": f"批次 {demand_id} 不存在"}
|
|
return {"code": "500", "msg": f"批次 {demand_id} 不存在"}
|
|
container_id_list = container_list.keys()
|
|
container_id_list = container_list.keys()
|
|
- container_order = self.get_order_by_batch(container_id_list)
|
|
|
|
|
|
+ container_order = self.get_order_by_batch(container_id_list,demand_id)
|
|
if not container_order:
|
|
if not container_order:
|
|
return {"code": "500", "msg": f"托盘 {container_id_list} 不存在"}
|
|
return {"code": "500", "msg": f"托盘 {container_id_list} 不存在"}
|
|
order = sorted(
|
|
order = sorted(
|
|
@@ -940,37 +1179,3 @@ class BatchViewSet(viewsets.ModelViewSet):
|
|
logger.info(f"收到 WMS 推送数据: {data}")
|
|
logger.info(f"收到 WMS 推送数据: {data}")
|
|
return Response({"code": "200", "msg": "Success"}, status=200)
|
|
return Response({"code": "200", "msg": "Success"}, status=200)
|
|
|
|
|
|
-def post_json_to_url(url, data):
|
|
|
|
- """
|
|
|
|
- 发送 JSON 数据到指定 URL
|
|
|
|
- :param url: 目标地址 (e.g., "https://api.example.com/endpoint")
|
|
|
|
- :param data: 要发送的字典数据 (e.g., {"key": "value"})
|
|
|
|
- :return: 响应内容 (字典) 或错误信息
|
|
|
|
- """
|
|
|
|
- headers = {
|
|
|
|
- 'Content-Type': 'application/json',
|
|
|
|
- # 可选:添加认证头 (如 Token)
|
|
|
|
- # 'Authorization': f'Bearer {settings.API_TOKEN}'
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- try:
|
|
|
|
- # 发送 POST 请求
|
|
|
|
- response = requests.post(
|
|
|
|
- url,
|
|
|
|
- data=json.dumps(data), # 序列化为 JSON 字符串
|
|
|
|
- headers=headers,
|
|
|
|
- timeout=10 # 超时时间(秒)
|
|
|
|
- )
|
|
|
|
-
|
|
|
|
- # 检查 HTTP 状态码
|
|
|
|
- response.raise_for_status()
|
|
|
|
-
|
|
|
|
- # 解析 JSON 响应
|
|
|
|
- return response.json()
|
|
|
|
-
|
|
|
|
- except requests.exceptions.RequestException as e:
|
|
|
|
- # 处理网络错误、超时等
|
|
|
|
- return {"error": str(e)}
|
|
|
|
- except json.JSONDecodeError:
|
|
|
|
- # 处理响应非 JSON 格式的情况
|
|
|
|
- return {"error": "Invalid JSON response"}
|
|
|