fix: 交付图与退款证据图入库/读出统一为完整 COS URL

This commit is contained in:
XingQue committed 2026-08-10 16:06:40 +08:00
1 parent c55b54995b
commit 6ba0824ea5
5 files changed
+89 -22

No files matched your search

+3 -2
View File
@@ -227,13 +227,14 @@ class AdGetDingdanXiangQing(APIView):
# 9. 查询打手提交的图片
try:
from utils.oss_utils import to_full_cos_url
# 查询该订单的所有打手提交图片
dashou_tupian_list = PlayerDeliveryImage.query.filter(
OrderID=dingdan_id
).values_list('ImageURL', flat=True)
# 转换为列表,过滤空值
dashou_images = [img for img in dashou_tupian_list if img]
# 转换为列表,过滤空值;相对路径补全为完整 URL
dashou_images = [to_full_cos_url(img) for img in dashou_tupian_list if img]
response_data['dashou_images'] = dashou_images
except Exception as e:
logger.warning(f"查询打手图片失败: {str(e)}")
+25 -11
View File
@@ -1357,12 +1357,14 @@ class DashouTijiaoView(APIView):
}, status=status.HTTP_403_FORBIDDEN)
# 5. 存储图片到Dashoutupian表(统一记在接单人/队长名下,组员可读)
# 小程序直传 COS 后常只带相对 Key;入库统一成完整 URL,后台/客服可不依赖拼接
from utils.oss_utils import to_full_cos_url
owner_uid = dingdan.PlayerID or yonghuid
for tupian_url in jiaofu_tupian_urls:
PlayerDeliveryImage.query.create(
OrderID=dingdan_id,
PlayerID=owner_uid,
ImageURL=tupian_url,
ImageURL=to_full_cos_url(tupian_url),
CreateTime=timezone.now()
)
@@ -1502,12 +1504,15 @@ class DashouDingdanXiangqingView(APIView):
}
try:
from orders.models import RefundEvidenceImage
dingdan_data['tuikuan_tupian'] = list(
RefundEvidenceImage.query.filter(OrderID=dingdan.OrderID)
from utils.oss_utils import to_full_cos_url
dingdan_data['tuikuan_tupian'] = [
to_full_cos_url(u)
for u in RefundEvidenceImage.query.filter(OrderID=dingdan.OrderID)
.exclude(ImageURL__isnull=True)
.exclude(ImageURL='')
.values_list('ImageURL', flat=True)
)
if u
]
except Exception:
dingdan_data['tuikuan_tupian'] = []
try:
@@ -1547,9 +1552,10 @@ class DashouDingdanXiangqingView(APIView):
).order_by('CreateTime')
jiaofu_tupian_urls = []
from utils.oss_utils import to_full_cos_url
for tupian_record in dashou_tupian_list:
if tupian_record.ImageURL:
jiaofu_tupian_urls.append(tupian_record.ImageURL)
jiaofu_tupian_urls.append(to_full_cos_url(tupian_record.ImageURL))
dingdan_data['dashou_jiaofu'] = jiaofu_tupian_urls
@@ -1787,28 +1793,36 @@ class DashouXiugaiView(APIView):
# ---------- 执行修改(使用事务保证原子性) ----------
try:
from utils.oss_utils import cos_url_variants, to_full_cos_url
with transaction.atomic():
# 1. 处理删除的图片:从 Dashoutupian 表中删除记录
# 1. 处理删除的图片:相对/绝对 URL 都能匹配
if deleted_images:
match_urls = set()
for u in deleted_images:
match_urls.update(cos_url_variants(u))
delete_count, _ = PlayerDeliveryImage.query.filter(
OrderID=dingdan_id,
ImageURL__in=deleted_images
ImageURL__in=list(match_urls),
).delete()
logger.info(f"订单 {dingdan_id} 删除图片 {delete_count} 张")
# 2. 处理新增的图片:插入新记录
# 2. 处理新增的图片:入库统一完整 URL
if new_images:
# 批量创建
new_records = []
for url in new_images:
full = to_full_cos_url(url)
if not full:
continue
new_records.append(PlayerDeliveryImage(
OrderID=dingdan_id,
PlayerID=owner_uid,
ImageURL=url,
ImageURL=full,
CreateTime=timezone.now()
))
PlayerDeliveryImage.objects.bulk_create(new_records)
logger.info(f"订单 {dingdan_id} 新增图片 {len(new_records)} 张")
if new_records:
PlayerDeliveryImage.objects.bulk_create(new_records)
logger.info(f"订单 {dingdan_id} 新增图片 {len(new_records)} 张")
# 3. 更新订单留言(如果发生变化)
# 注意:即使留言为空字符串,也允许更新,表示清空留言
+15 -5
View File
@@ -660,10 +660,11 @@ class ShangjiaDingdanXiangqingView(APIView):
order = shangjia_kuozhan.Order
# 4. 交付图片列表
from utils.oss_utils import to_full_cos_url
dashou_tupian_list = PlayerDeliveryImage.query.filter(
OrderID=dingdan_id
).order_by('CreateTime').values_list('ImageURL', flat=True)
dashou_jiaofu = list(dashou_tupian_list)
dashou_jiaofu = [to_full_cos_url(u) for u in dashou_tupian_list if u]
# 5. 打手详细信息(头像、昵称、用户ID)
dashou_yonghuid = order.PlayerID or ''
@@ -818,12 +819,15 @@ class ShangjiaDingdanXiangqingView(APIView):
}
try:
response_data['tuikuan_tupian'] = list(
RefundEvidenceImage.query.filter(OrderID=dingdan_id)
from utils.oss_utils import to_full_cos_url as _full_cos
response_data['tuikuan_tupian'] = [
_full_cos(u)
for u in RefundEvidenceImage.query.filter(OrderID=dingdan_id)
.exclude(ImageURL__isnull=True)
.exclude(ImageURL='')
.values_list('ImageURL', flat=True)
)
if u
]
except Exception:
response_data['tuikuan_tupian'] = []
@@ -1375,7 +1379,13 @@ class ShangjiaTuikuanShenqingView(APIView):
if not isinstance(tuikuan_tupian_urls, list):
tuikuan_tupian_urls = []
valid_urls = [str(u).strip() for u in tuikuan_tupian_urls if u and str(u).strip()]
from utils.oss_utils import to_full_cos_url
valid_urls = [
to_full_cos_url(u)
for u in tuikuan_tupian_urls
if u and str(u).strip()
]
valid_urls = [u for u in valid_urls if u]
# 4. 参数验证(文字 + 至少1张证据图)
if not dingdan_id or not tuikuan_liyou:
+8 -4
View File
@@ -1674,8 +1674,9 @@ class KefuGetOrderDetailView(APIView):
# 6. 打手图片
try:
from utils.oss_utils import to_full_cos_url
dashou_images = PlayerDeliveryImage.query.filter(OrderID=dingdan_id).values_list('ImageURL', flat=True)
response_data['dashou_images'] = [img for img in dashou_images if img]
response_data['dashou_images'] = [to_full_cos_url(img) for img in dashou_images if img]
except Exception as e:
logger.exception(f"[kefuhqddxq] 打手图片查询异常 dingdan_id={dingdan_id}")
response_data['dashou_images'] = []
@@ -1690,12 +1691,15 @@ class KefuGetOrderDetailView(APIView):
response_data.setdefault('reject_reason', '')
try:
from orders.models import RefundEvidenceImage
response_data['tuikuan_tupian'] = list(
RefundEvidenceImage.query.filter(OrderID=dingdan_id)
from utils.oss_utils import to_full_cos_url
response_data['tuikuan_tupian'] = [
to_full_cos_url(u)
for u in RefundEvidenceImage.query.filter(OrderID=dingdan_id)
.exclude(ImageURL__isnull=True)
.exclude(ImageURL='')
.values_list('ImageURL', flat=True)
)
if u
]
except Exception as e:
logger.exception(f"[kefuhqddxq] 退款图片查询异常 dingdan_id={dingdan_id}")
response_data['tuikuan_tupian'] = []
+38
View File
@@ -184,6 +184,44 @@ def _upload_to_aliyun_oss(file_obj, file_path):
return None
def _cos_public_domain() -> str:
"""COS 公网域名(无尾斜杠)。"""
return (getattr(settings, 'COS_DOMAIN', '') or '').rstrip('/')
def to_full_cos_url(url_or_key) -> str:
"""
相对 COS Key / 协议相对 URL → 完整 https URL。
已是 http(s) 则原样返回。用于交付图、退款证据图入库,避免后台当完整 URL 用时裂图。
"""
s = str(url_or_key or '').strip()
if not s:
return ''
if s.startswith('//'):
return f'https:{s}'
if s.startswith('http://') or s.startswith('https://'):
return s
domain = _cos_public_domain()
key = s.lstrip('/')
if not domain:
return key
return f'{domain}/{key}'
def cos_url_variants(url_or_key) -> list:
"""同一张图在库里可能存相对或绝对,删除匹配时两边都试。"""
s = str(url_or_key or '').strip()
if not s:
return []
full = to_full_cos_url(s)
key = _url_to_oss_key(s) or s.lstrip('/')
out = []
for x in (s, full, key, f'/{key}' if key else ''):
if x and x not in out:
out.append(x)
return out
def _url_to_oss_key(file_url):
"""从完整 URL 或相对路径提取 OSS 对象 Key"""
if not file_url: