fix: 交付图与退款证据图入库/读出统一为完整 COS URL
This commit is contained in:
1 parent
c55b54995b
commit
6ba0824ea5
5 files changed
+89
-22
No files matched your search
@@ -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
@@ -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. 更新订单留言(如果发生变化)
|
||||
# 注意:即使留言为空字符串,也允许更新,表示清空留言
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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'] = []
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in new issue
Block a user