reallife_asset/wwwroot/api/submit_virtual_upload.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

89 lines
3.7 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import os
vendor_group_id = params_kw.get('vendor_group_id', '')
source_url = params_kw.get('source_url', '')
asset_type = params_kw.get('asset_type', '')
name = params_kw.get('name', '')
if not vendor_group_id or not source_url:
return json.dumps({
"widgettype": "Error",
"options": {"title": "错误", "message": "请选择素材组合并上传素材文件", "anchor": "cc"}
})
# Validate media file type from path extension
ext = os.path.splitext(source_url.split('?')[0])[1].lower() if source_url else ''
media_map = {
'.jpg': 'Image', '.jpeg': 'Image', '.png': 'Image', '.gif': 'Image', '.bmp': 'Image', '.webp': 'Image', '.svg': 'Image', '.tiff': 'Image', '.heic': 'Image',
'.mp4': 'Video', '.avi': 'Video', '.mov': 'Video', '.wmv': 'Video', '.flv': 'Video', '.mkv': 'Video', '.webm': 'Video',
'.mp3': 'Audio', '.wav': 'Audio', '.aac': 'Audio', '.flac': 'Audio', '.ogg': 'Audio', '.wma': 'Audio', '.m4a': 'Audio',
}
detected_type = media_map.get(ext, '')
if ext and not detected_type:
return json.dumps({
"widgettype": "Error",
"options": {"title": "错误", "message": f"不支持的文件类型: {ext},请上传图片、音频或视频文件", "anchor": "cc"}
})
if not asset_type and detected_type:
asset_type = detected_type
if not asset_type:
asset_type = 'Image'
# Convert base64 / local path to public URL
if source_url.startswith('data:') or (not source_url.startswith('http') and len(source_url) < 8000):
source_url = await b64media2url(request, source_url)
if not source_url:
return json.dumps({
"widgettype": "Error",
"options": {"title": "错误", "message": "素材文件转换失败", "anchor": "cc"}
})
org_id = (await get_userorgid()) or '0'
user_id = (await get_user()) or ''
result = await rl_upload_virtual_asset(org_id, vendor_group_id, source_url, asset_type, name, user_id)
if result.get('success'):
asset_id = result.get('id', '')
vendor_asset_id = result.get('vendor_asset_id', '')
status_text = result.get('status', 'Processing')
msg = f"虚拟人素材已提交,当前状态:{status_text}\n素材ID{asset_id}\n供应商资产ID{vendor_asset_id}"
base_path = request.path.rsplit('/', 1)[0]
check_url = base_path + '/submit_query_status.dspy'
return json.dumps({
"widgettype": "Message",
"id": "virtual_upload_result_popup",
"options": {"title": "上传成功", "message": "", "anchor": "cc"},
"subwidgets": [
{
"widgettype": "VBox",
"options": {"padding": "8px", "gap": "12px"},
"subwidgets": [
{"widgettype": "Text", "options": {"text": msg}},
{
"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}});"
"})()"
}]
}
]
}
]
})
else:
return json.dumps({
"widgettype": "Error",
"options": {"title": "上传失败", "message": result.get('message', '未知错误'), "anchor": "cc"}
})