feat: 专区图标支持后台上传 OSS,查询接口下发 tupian_url

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
XingQue
2026-07-28 02:12:09 +08:00
parent 1c67f98866
commit 2ff5df09bc
2 changed files with 63 additions and 7 deletions

View File

@@ -587,6 +587,24 @@ class ModifyProductTypeZoneView(APIView):
else:
return Response({'code': 400, 'msg': '无效的action'})
def _upload_zhuanqu_icon(self, image_file):
"""专区图标上传到 OSS相对路径前缀 shangpin/zhuanqu/(按俱乐部存库,路径共用前缀)。"""
try:
valid, msg = validate_image(image_file)
if not valid:
return None, msg
except ImportError:
pass
ext = image_file.name.split('.')[-1].lower() if image_file.name and '.' in image_file.name else 'png'
if ext not in ('jpg', 'jpeg', 'png', 'gif', 'webp'):
ext = 'png'
new_filename = f"{int(time.time())}_{uuid.uuid4().hex[:12]}.{ext}"
oss_path = f"shangpin/zhuanqu/{new_filename}"
url = upload_to_oss(image_file, oss_path)
if not url:
return None, '图片上传失败'
return oss_path, None
def add_zhuanqu(self, request):
mingzi = request.data.get('mingzi', '').strip()
leixing_id = request.data.get('leixing_id')
@@ -609,6 +627,16 @@ class ModifyProductTypeZoneView(APIView):
except (TypeError, ValueError):
return Response({'code': 400, 'msg': '审核状态无效必须为1或2'})
# 图标:优先上传文件;否则可选手填相对路径(兼容旧用法)
tupian_url = (request.data.get('tupian_url') or '').strip()
image_file = request.FILES.get('file')
uploaded_path = None
if image_file:
uploaded_path, err = self._upload_zhuanqu_icon(image_file)
if err:
return Response({'code': 500 if err == '图片上传失败' else 400, 'msg': err})
tupian_url = uploaded_path
try:
with transaction.atomic():
from jituan.services.club_write import resolve_club_id_for_write
@@ -619,11 +647,17 @@ class ModifyProductTypeZoneView(APIView):
shenhezhuangtai=shenhezhuangtai,
paixu=0,
club_id=club_id,
tupian_url=(request.data.get('tupian_url') or '').strip(),
tupian_url=tupian_url,
)
return Response({'code': 0, 'msg': '添加成功', 'data': {'id': zhuanqu.id, 'club_id': club_id}})
return Response({
'code': 0,
'msg': '添加成功',
'data': {'id': zhuanqu.id, 'club_id': club_id, 'tupian_url': tupian_url},
})
except Exception as e:
logger.error(f"添加专区失败: {e}", exc_info=True)
if uploaded_path:
delete_from_oss(uploaded_path)
return Response({'code': 500, 'msg': '数据库错误'})
def update_zhuanqu(self, request):
@@ -671,10 +705,18 @@ class ModifyProductTypeZoneView(APIView):
except (TypeError, ValueError):
return Response({'code': 400, 'msg': '审核状态无效必须为1或2'})
if 'tupian_url' in request.data:
old_image_path = getattr(zhuanqu, 'tupian_url', None) or ''
image_file = request.FILES.get('file')
uploaded_path = None
if image_file:
uploaded_path, err = self._upload_zhuanqu_icon(image_file)
if err:
return Response({'code': 500 if err == '图片上传失败' else 400, 'msg': err})
if uploaded_path != old_image_path:
changes['tupian_url'] = uploaded_path
elif 'tupian_url' in request.data:
new_url = (request.data.get('tupian_url') or '').strip()
old_url = getattr(zhuanqu, 'tupian_url', None) or ''
if new_url != old_url:
if new_url != old_image_path:
changes['tupian_url'] = new_url
if not changes:
@@ -685,9 +727,18 @@ class ModifyProductTypeZoneView(APIView):
for field, value in changes.items():
setattr(zhuanqu, field, value)
zhuanqu.save()
return Response({'code': 0, 'msg': '修改成功'})
# 换图或清空后删旧 OSS新上传路径与旧不同时
if 'tupian_url' in changes and old_image_path and old_image_path != changes['tupian_url']:
delete_from_oss(old_image_path)
return Response({
'code': 0,
'msg': '修改成功',
'data': {'id': zhuanqu.id, 'tupian_url': getattr(zhuanqu, 'tupian_url', '') or ''},
})
except Exception as e:
logger.error(f"更新专区失败: {e}", exc_info=True)
if uploaded_path:
delete_from_oss(uploaded_path)
return Response({'code': 500, 'msg': '修改失败'})
def delete_zhuanqu(self, request):
@@ -710,6 +761,7 @@ class ModifyProductTypeZoneView(APIView):
if zone_club != write_club:
return Response({'code': 403, 'msg': '专区不属于当前俱乐部'})
old_image_path = getattr(zhuanqu, 'tupian_url', None) or ''
with transaction.atomic():
if delete_products:
Shangpin.query.filter(zhuanqu_id=zone_id).delete()
@@ -717,6 +769,9 @@ class ModifyProductTypeZoneView(APIView):
Shangpin.query.filter(zhuanqu_id=zone_id).update(zhuanqu_id=None)
zhuanqu.delete()
if old_image_path:
delete_from_oss(old_image_path)
return Response({'code': 0, 'msg': '删除成功'})