diff --git a/backend/apps/generation/views.py b/backend/apps/generation/views.py index 72737bc..61ec22e 100644 --- a/backend/apps/generation/views.py +++ b/backend/apps/generation/views.py @@ -2750,18 +2750,35 @@ def asset_groups_view(request): team = request.user.team if request.method == 'GET': - groups = ( + groups = list( AssetGroup.objects .filter(team=team) .annotate(asset_count=Count('assets')) .order_by('-created_at') ) + + # 从火山同步素材组名字(一次 API 调用) + remote_ids = [g.remote_group_id for g in groups if g.remote_group_id] + if remote_ids: + try: + from utils.assets_client import list_asset_groups + remote_items, _ = list_asset_groups(page=1, page_size=100) + remote_name_map = {item['Id']: item.get('Name', '') for item in remote_items if 'Id' in item} + for g in groups: + if g.remote_group_id and g.remote_group_id in remote_name_map: + remote_name = remote_name_map[g.remote_group_id] + if remote_name and remote_name != g.name: + g.name = remote_name + g.save(update_fields=['name']) + except Exception: + pass # 同步失败不影响列表展示 + results = [] for g in groups: results.append({ 'id': g.id, 'name': g.name, - 'thumbnail_url': g.thumbnail_url, + 'thumbnail_url': g.thumbnail_url if g.asset_count > 0 else '', 'asset_count': g.asset_count, 'remote_group_id': g.remote_group_id, 'created_at': g.created_at.isoformat(), @@ -2784,12 +2801,12 @@ def asset_groups_view(request): w, h = img.size if w < 300 or h < 300: return Response( - {'error': f'图片尺寸太小({w}x{h}),宽高均需 ≥ 300px'}, + {'error': f'图片太小了,请上传更大的图片(当前 {w}x{h},最小要求 300x300)'}, status=status.HTTP_400_BAD_REQUEST, ) if w > 6000 or h > 6000: return Response( - {'error': f'图片尺寸太大({w}x{h}),宽高均需 ≤ 6000px'}, + {'error': f'图片太大了,请压缩后重试(当前 {w}x{h},最大支持 6000x6000)'}, status=status.HTTP_400_BAD_REQUEST, ) file.seek(0) # Reset after PIL read @@ -2868,6 +2885,18 @@ def asset_group_detail_view(request, group_id): return Response({'error': '素材组不存在'}, status=status.HTTP_404_NOT_FOUND) if request.method == 'GET': + # 同步火山端的素材组名字 + if group.remote_group_id: + try: + from utils.assets_client import get_asset_group + remote = get_asset_group(group.remote_group_id) + remote_name = remote.get('Name', '') + if remote_name and remote_name != group.name: + group.name = remote_name + group.save(update_fields=['name']) + except Exception: + pass # 查不到就用本地名字 + assets_qs = Asset.objects.filter(group=group).order_by('-created_at') asset_list = [] for a in assets_qs: @@ -2947,12 +2976,12 @@ def asset_group_add_asset_view(request, group_id): w, h = img.size if w < 300 or h < 300: return Response( - {'error': f'图片尺寸太小({w}x{h}),宽高均需 ≥ 300px'}, + {'error': f'图片太小了,请上传更大的图片(当前 {w}x{h},最小要求 300x300)'}, status=status.HTTP_400_BAD_REQUEST, ) if w > 6000 or h > 6000: return Response( - {'error': f'图片尺寸太大({w}x{h}),宽高均需 ≤ 6000px'}, + {'error': f'图片太大了,请压缩后重试(当前 {w}x{h},最大支持 6000x6000)'}, status=status.HTTP_400_BAD_REQUEST, ) file.seek(0) @@ -3053,6 +3082,7 @@ def asset_search_view(request): groups = ( AssetGroup.objects .filter(team=team, name__icontains=q) + .annotate(asset_count=Count('assets')) .order_by('-created_at')[:20] ) results = [] @@ -3060,7 +3090,8 @@ def asset_search_view(request): results.append({ 'id': g.id, 'name': g.name, - 'thumbnail_url': g.thumbnail_url, + 'thumbnail_url': g.thumbnail_url if g.asset_count > 0 else '', + 'asset_count': g.asset_count, 'remote_group_id': g.remote_group_id, }) return Response({'results': results}) diff --git a/backend/utils/assets_client.py b/backend/utils/assets_client.py index ca306da..a5f54e8 100644 --- a/backend/utils/assets_client.py +++ b/backend/utils/assets_client.py @@ -167,6 +167,12 @@ def get_asset(asset_id: str) -> dict: return _do_request('GetAsset', body) +def get_asset_group(group_id: str) -> dict: + """Get single asset group details.""" + body = {'Id': group_id, 'ProjectName': PROJECT_NAME} + return _do_request('GetAssetGroup', body) + + def update_asset_group(group_id: str, name: str = None, description: str = None): """Update an asset group's name and/or description.""" body = {'Id': group_id, 'ProjectName': PROJECT_NAME} diff --git a/web/src/components/AssetLibraryModal.tsx b/web/src/components/AssetLibraryModal.tsx index ce9c28e..e8780f1 100644 --- a/web/src/components/AssetLibraryModal.tsx +++ b/web/src/components/AssetLibraryModal.tsx @@ -211,7 +211,11 @@ export function AssetLibraryModal({ open, onClose }: Props) {
{groups.map((group) => (
handleGroupClick(group)}> - {group.name} + {group.asset_count === 0 ? ( +
暂无图片
+ ) : ( + {group.name} + )}
{editingName && editingName.id === group.id ? (
e.stopPropagation()}> @@ -406,6 +410,7 @@ export function AssetLibraryModal({ open, onClose }: Props) { )}
⚠️ 素材上传后无法删除,请确认后再上传
+
⚠️ 图片尺寸要求:宽高均需在 300~6000 像素之间
0 && !textAfterAt.includes(' ')) { + // Text after @, search assets (Chinese + English) if (searchTimerRef.current) clearTimeout(searchTimerRef.current); searchTimerRef.current = setTimeout(() => { assetsApi.search(textAfterAt).then((res) => { @@ -641,7 +641,11 @@ export function PromptInput() { }} >
- + {group.thumbnail_url ? ( + + ) : ( + 无图 + )}
{group.name} 人像 diff --git a/web/src/pages/ProfilePage.module.css b/web/src/pages/ProfilePage.module.css index 7cbaf16..441f727 100644 --- a/web/src/pages/ProfilePage.module.css +++ b/web/src/pages/ProfilePage.module.css @@ -3,6 +3,8 @@ margin: 0 auto; padding: 24px 20px 60px; min-height: 100vh; + height: 100vh; + overflow-y: auto; } /* Header */