reallife_asset/wwwroot/api/submit_virtual_list_assets.dspy
yumoqing 925f58b025 feat: 添加私域虚拟人素材功能
- init.py: 新增6个虚拟人函数(create/list/upload/sync等),注册到ServerEnv
- api_mapping: 新增create_group→CreateAssetGroup映射
- 外部API: 5个rl_virtual_*.dspy端点(创建组合/列表/上传/素材列表/状态)
- 前端API: 4个submit/get dspy端点(UI表单提交和数据获取)
- UI页面: 3个页面(创建组合/上传素材/查看素材)
- index.ui: 左侧导航新增虚拟人素材分区(3个按钮)
- load_path.py: RBAC新增virtual页面和api/%路径
- docs: api_downapp.md新增虚拟人API文档(5个端点)
2026-06-02 15:25:14 +08:00

146 lines
4.6 KiB
Plaintext

vendor_group_id = params_kw.get('vendor_group_id', '')
if not vendor_group_id:
return json.dumps({
"widgettype": "Error",
"options": {"title": "错误", "message": "请选择素材组合"}
})
org_id = (await get_userorgid()) or '0'
result = await rl_list_virtual_assets_client(org_id, vendor_group_id)
if not result.get('success'):
return json.dumps({
"widgettype": "Error",
"options": {"title": "查询失败", "message": result.get('message', '未知错误')}
})
assets = result.get('assets', [])
if not assets:
return json.dumps({
"widgettype": "VBox",
"options": {"padding": "16px", "gap": "12px"},
"subwidgets": [
{
"widgettype": "Text",
"options": {"text": "该素材组合下暂无素材,请先上传虚拟人素材。"}
}
]
})
# Build asset cards
cards = []
for a in assets:
status = a.get('status', '')
name = a.get('name', '')
url = a.get('url', '')
atype = a.get('asset_type', '')
create_time = str(a.get('create_time', ''))[:16]
asset_id = a.get('id', '')
vendor_asset_id = a.get('vendor_asset_id', '')
s_lower = status.lower() if status else ''
if s_lower in ('active', 'available', 'ready'):
status_icon = "✅"
elif s_lower in ('processing', 'pending', 'submitted'):
status_icon = "⏳"
elif s_lower in ('failed', 'error'):
status_icon = "❌"
else:
status_icon = "📋"
card_subs = [
{
"widgettype": "HBox",
"options": {"gap": "8px", "alignItems": "center", "marginBottom": "4px"},
"subwidgets": [
{"widgettype": "Text", "options": {"text": name or "未命名", "fontWeight": "bold"}},
{"widgettype": "Text", "options": {"text": f"{status_icon} {status}", "cfontsize": 0.9}}
]
},
{
"widgettype": "Text",
"options": {"text": f"类型: {atype} 创建: {create_time}", "cfontsize": 0.9}
},
{
"widgettype": "Text",
"options": {"text": f"Asset URI: asset://{vendor_asset_id}", "cfontsize": 0.85}
}
]
# Media preview
if url:
if atype == 'Image':
card_subs.append({
"widgettype": "Image",
"options": {"url": url, "cwidth": 15, "cheight": 10, "objectFit": "cover", "borderRadius": "4px", "marginTop": "8px"}
})
elif atype == 'Video':
card_subs.append({
"widgettype": "VideoPlayer",
"options": {"url": url, "cwidth": 20, "cheight": 12, "marginTop": "8px"}
})
elif atype == 'Audio':
card_subs.append({
"widgettype": "AudioPlayer",
"options": {"url": url, "marginTop": "8px"}
})
# Buttons
check_url = request.path.rsplit('/', 1)[0] + '/submit_query_status.dspy'
btn_subs = [
{
"widgettype": "Button",
"options": {"label": "刷新状态"},
"binds": [{
"wid": "self", "event": "click",
"actiontype": "script", "target": "self",
"script": "(async function(){" \
"var url='" + check_url + "?_webbricks_=1&asset_id=" + asset_id + "';" \
"var r=await fetch(url);" \
"var j=await r.json();" \
"await bricks.show_resp_message_or_error({json:async function(){return j}});" \
"})()"
}]
}
]
if url:
btn_subs.append({
"widgettype": "Button",
"options": {"label": "下载"},
"binds": [{
"wid": "self", "event": "click",
"actiontype": "script", "target": "self",
"script": "window.open('" + url + "', '_blank')"
}]
})
card_subs.append({
"widgettype": "HBox",
"options": {"gap": "8px", "marginTop": "8px"},
"subwidgets": btn_subs
})
cards.append({
"widgettype": "VBox",
"options": {"css": "card", "padding": "12px", "borderRadius": "8px"},
"subwidgets": card_subs
})
result_widget = {
"widgettype": "VBox",
"options": {"padding": "16px", "gap": "12px"},
"subwidgets": [
{"widgettype": "Text", "options": {"text": f"共 {len(assets)} 个虚拟人素材", "fontWeight": "bold"}},
{
"widgettype": "ResponsableBox",
"options": {"gap": "12px", "minWidth": "300px"},
"subwidgets": cards
}
]
}
return json.dumps(result_widget, ensure_ascii=False)