feat: 专区图标支持后台上传 OSS,查询接口下发 tupian_url
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -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': '删除成功'})
|
||||
|
||||
|
||||
|
||||
@@ -128,7 +128,8 @@ class ShangpinHuoquView(APIView):
|
||||
"id": zhuanqu.id,
|
||||
"mingzi": zhuanqu.mingzi,
|
||||
"leixing_id": zhuanqu.leixing_id,
|
||||
"paixu": zhuanqu.paixu
|
||||
"paixu": zhuanqu.paixu,
|
||||
"tupian_url": getattr(zhuanqu, 'tupian_url', None) or '',
|
||||
})
|
||||
|
||||
# 3. 查询商品列表(只查询可见专区下的商品,并排序)
|
||||
|
||||
Reference in New Issue
Block a user