Files
dj/integration-work/add_asset_reference_ui.py

44 lines
5.3 KiB
Python

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'<AssetReferenceImages kind="{kind}" :asset="{item}" @updated="updateAssetReferences" @preview="openImageViewer" />'
s=s.replace('<CharacterVoice :character="c"',component('character','c')+'\n <CharacterVoice :character="c"',1)
for kind,item in [('scene','s'),('prop','p')]:
needle=':disabled="isPending'+('Scene' if kind=='scene' else 'Prop')+'Image('+item+'.id)" @click.stop="gen'
pos=s.index(needle);end=s.index(' </div>\n </div>',pos)+len(' </div>')
s=s[:end]+'\n '+component(kind,item)+s[end:]
s=s.replace('<CharacterVoice v-if="assetDetail.type', '<AssetReferenceImages :key="assetDetail.type + assetDetail.item.id" :kind="assetDetail.type" :asset="assetDetail.item" @updated="updateAssetReferences" @preview="openImageViewer" />\n <CharacterVoice v-if="assetDetail.type',1)
needle="const assetDetail = ref({ open: false, type: '', item: null })"
assert s.count(needle)==1
s=s.replace(needle,needle+'''
const referenceBusyIds = useState('asset-reference-busy', () => [])
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')