diff --git a/orders/views/dashou.py b/orders/views/dashou.py index 55ebe1a..119d11d 100644 --- a/orders/views/dashou.py +++ b/orders/views/dashou.py @@ -1360,12 +1360,15 @@ class DashouTijiaoView(APIView): # 小程序直传 COS 后常只带相对 Key;入库统一成完整 URL,后台/客服可不依赖拼接 from utils.oss_utils import to_full_cos_url owner_uid = dingdan.PlayerID or yonghuid + now = timezone.now() for tupian_url in jiaofu_tupian_urls: + full = to_full_cos_url(tupian_url) PlayerDeliveryImage.query.create( OrderID=dingdan_id, PlayerID=owner_uid, - ImageURL=to_full_cos_url(tupian_url), - CreateTime=timezone.now() + ImageURL=full, + CreateTime=now, + UpdateTime=now, ) # 6. 更新订单主表 @@ -1794,6 +1797,7 @@ class DashouXiugaiView(APIView): # ---------- 执行修改(使用事务保证原子性) ---------- try: from utils.oss_utils import cos_url_variants, to_full_cos_url + now = timezone.now() with transaction.atomic(): # 1. 处理删除的图片:相对/绝对 URL 都能匹配 if deleted_images: @@ -1806,36 +1810,39 @@ class DashouXiugaiView(APIView): ).delete() logger.info(f"订单 {dingdan_id} 删除图片 {delete_count} 张") - # 2. 处理新增的图片:入库统一完整 URL + # 2. 新增图片:必须走 query.create(与首次提交一致) + # 禁止 bulk_create:会跳过 auto_now,UpdateTime 可能为 NULL, + # 且历史曾导致「小程序本地能看、库里没有/后台裂图」。 + saved_urls = [] if new_images: - # 批量创建 - new_records = [] for url in new_images: full = to_full_cos_url(url) if not full: continue - new_records.append(PlayerDeliveryImage( + PlayerDeliveryImage.query.create( OrderID=dingdan_id, PlayerID=owner_uid, ImageURL=full, - CreateTime=timezone.now() - )) - if new_records: - PlayerDeliveryImage.objects.bulk_create(new_records) - logger.info(f"订单 {dingdan_id} 新增图片 {len(new_records)} 张") + CreateTime=now, + UpdateTime=now, + ) + saved_urls.append(full) + logger.info(f"订单 {dingdan_id} 新增交付图 {len(saved_urls)} 张: {saved_urls}") # 3. 更新订单留言(如果发生变化) # 注意:即使留言为空字符串,也允许更新,表示清空留言 if 'liuyan' in data: # 判断是否传了liuyan字段(可能为空字符串) dingdan.PlayerRemark = liuyan - dingdan.UpdateTime = timezone.now() + dingdan.UpdateTime = now dingdan.save(update_fields=['PlayerRemark', 'UpdateTime']) # 全部成功,返回成功响应 return Response({ 'code': 0, 'msg': '修改成功', - 'data': None + 'data': { + 'saved_image_urls': saved_urls if new_images else [], + } }, status=status.HTTP_200_OK) except Exception as e: diff --git a/orders/views/merchant.py b/orders/views/merchant.py index b69e62c..e8f005b 100644 --- a/orders/views/merchant.py +++ b/orders/views/merchant.py @@ -1462,15 +1462,24 @@ class ShangjiaTuikuanShenqingView(APIView): logger.info(f"订单 {dingdan_id} 已有退款记录,已更新退款理由") # 8b. 退款证据图:覆盖写入(重新申请时替换旧图) + # 必须 query.create + 完整 URL;勿用 bulk_create(UpdateTime/auto_now 不生效) + from utils.oss_utils import to_full_cos_url as _refund_full RefundEvidenceImage.query.filter(OrderID=dingdan_id).delete() - RefundEvidenceImage.objects.bulk_create([ - RefundEvidenceImage( + now_ev = timezone.now() + saved_refund = [] + for url in valid_urls: + full = _refund_full(url) + if not full: + continue + RefundEvidenceImage.query.create( OrderID=dingdan_id, UserID=current_user.UserUID, - ImageURL=url, + ImageURL=full, + CreateTime=now_ev, + UpdateTime=now_ev, ) - for url in valid_urls - ]) + saved_refund.append(full) + logger.info(f"订单 {dingdan_id} 退款证据图入库 {len(saved_refund)} 张") # 9. 更新订单状态为4(退款中) dingdan.Status = 4 @@ -1508,7 +1517,7 @@ class ShangjiaTuikuanShenqingView(APIView): 'dingdan_id': dingdan_id, 'new_zhuangtai': 4, 'tuikuan_liyou': tuikuan_liyou, - 'tuikuan_tupian': valid_urls, + 'tuikuan_tupian': saved_refund, 'jine': float(dingdan.Amount) if dingdan.Amount else 0.0, 'dashou_id': dingdan.PlayerID }