from pathlib import Path import json root=Path('D:/web/dj/huobao-source/frontend/app') p=root/'views/drama/episode.vue';s=p.read_text(encoding='utf-8') component=lambda kind,item:f'' s=s.replace('\n []) function referencesSaving(type, id) { return referenceBusyIds.value.includes(`${type}:${id}`) } function updateAssetReferences(type, id, references) { const patch = { reference_images: references, referenceImages: references } const items = type === 'character' ? chars.value : type === 'scene' ? scenes.value : propItems.value const item = items.find(value => value.id === id) if (item) Object.assign(item, patch) if (assetDetail.value.type === type && assetDetail.value.item?.id === id) Object.assign(assetDetail.value.item, patch) } ''',1) for kind,suffix,item in [('character','Char','c'),('scene','Scene','s'),('prop','Prop','p')]: needle=f'async function gen{suffix}Img(id) {{' s=s.replace(needle,needle+f"\n if (referencesSaving('{kind}', id)) {{ toast.info(t('assetReferences.wait')); return }}",1) for expr in [item+'.id','assetDetail.item.id']: s=s.replace(f':disabled="isPending{suffix}Image({expr})"',f':disabled="isPending{suffix}Image({expr}) || referencesSaving(\'{kind}\', {expr})"') for name in ('batchCharImages','batchSceneImages','batchPropImages'): needle=f'function {name}() {{';s=s.replace(needle,needle+"\n if (referenceBusyIds.value.length) { toast.info(t('assetReferences.wait')); return }",1) p.write_text(s,encoding='utf-8') translations={ 'zh':dict(title='生图参考图',add='添加参考图',saving='保存中',preview='预览参考图 {n}',remove='移除参考图 {n}',used='生成/重绘时自动使用,按顺序作为参考图。',empty='上传人物、造型或风格参考,生成/重绘时使用。',formats='JPG / PNG / WebP · 单张 ≤ 20MB · 最多 6 张',limit='每个资产最多 6 张参考图',invalid='请选择有效的 JPG、PNG 或 WebP 图片,单张不超过 20MB',saved='参考图已保存,生成/重绘时会自动使用',removed='已移除参考图',wait='参考图保存中,请稍后生成'), 'en':dict(title='Image references',add='Add references',saving='Saving',preview='Preview reference {n}',remove='Remove reference {n}',used='Used in this order when generating or redrawing.',empty='Add identity, outfit or style references for generation.',formats='JPG / PNG / WebP · Up to 20 MB each · 6 images max',limit='Up to 6 references per asset',invalid='Choose valid JPG, PNG or WebP files, up to 20 MB each',saved='References saved for generation and redraws',removed='Reference removed',wait='References are saving. Please wait before generating.'), 'ja':dict(title='生成用の参照画像',add='参照画像を追加',saving='保存中',preview='参照画像 {n} を表示',remove='参照画像 {n} を削除',used='生成・再生成時に、この順序で参照します。',empty='人物・衣装・画風の参照画像を追加できます。',formats='JPG / PNG / WebP · 1枚20MBまで · 最大6枚',limit='素材ごとに参照画像は最大6枚です',invalid='20MB以下のJPG・PNG・WebP画像を選択してください',saved='参照画像を保存しました',removed='参照画像を削除しました',wait='参照画像を保存中です。お待ちください。'), 'ko':dict(title='생성 참고 이미지',add='참고 이미지 추가',saving='저장 중',preview='참고 이미지 {n} 미리보기',remove='참고 이미지 {n} 제거',used='생성 또는 다시 그리기 시 이 순서로 사용합니다.',empty='인물, 의상 또는 스타일 참고 이미지를 추가하세요.',formats='JPG / PNG / WebP · 장당 20MB 이하 · 최대 6장',limit='에셋당 참고 이미지는 최대 6장입니다',invalid='장당 20MB 이하의 JPG, PNG 또는 WebP 이미지를 선택하세요',saved='생성에 사용할 참고 이미지를 저장했습니다',removed='참고 이미지를 제거했습니다',wait='참고 이미지를 저장 중입니다. 잠시 기다려 주세요.') } for lang,values in translations.items(): p=root/'locales'/(lang+'.json');s=p.read_text(encoding='utf-8');assert '"assetReferences"' not in s block=json.dumps(values,ensure_ascii=False,indent=2).replace('\n','\n ') s=s.replace('{','{\n "assetReferences": '+block+',',1);json.loads(s);p.write_text(s,encoding='utf-8') print('Reference components and translations added')