feat: 复制API功能-工具栏按钮+弹窗选源/目标+后台复制

This commit is contained in:
yumoqing 2026-07-01 15:02:33 +08:00
parent 27f3ee9c78
commit d57b8dbc73
5 changed files with 115 additions and 0 deletions

View File

@ -58,6 +58,10 @@
"name":"unpublish", "name":"unpublish",
"label":"下架", "label":"下架",
"selected_row":true "selected_row":true
},
{
"name":"copy_api",
"label":"复制API"
} }
] ]
}, },
@ -114,6 +118,21 @@
"action":"unpublished" "action":"unpublished"
} }
} }
},
{
"wid":"self",
"event":"copy_api",
"actiontype":"urlwidget",
"target":"PopupWindow",
"popup_options":{
"title":"复制API配置",
"cwidth":24,
"cheight":14,
"dismiss_events":["cancel","submited"]
},
"options":{
"url":"{{entire_url('../api/copy_api_form.ui')}}"
}
} }
], ],
"editexclouded": [ "editexclouded": [

View File

@ -127,6 +127,9 @@ PATHS_LOGINED = [
f"/{MOD}/api/llmusage_update.dspy", f"/{MOD}/api/llmusage_update.dspy",
f"/{MOD}/api/retry_accounting.dspy", f"/{MOD}/api/retry_accounting.dspy",
f"/{MOD}/api/uapi_options.dspy", f"/{MOD}/api/uapi_options.dspy",
f"/{MOD}/api/copy_api_form.ui",
f"/{MOD}/api/copy_api.dspy",
f"/{MOD}/api/get_search_llm_for_copy.dspy",
# CRUD 子目录 — llm/ # CRUD 子目录 — llm/
f"/{MOD}/llm/index.ui", f"/{MOD}/llm/index.ui",

47
wwwroot/api/copy_api.dspy Normal file
View File

@ -0,0 +1,47 @@
# 复制API配置从源llm复制所有llm_api_map记录到目标llm
result = {'widgettype':'Message','options':{'title':'Error','message':'','timeout':3}}
try:
from_llmid = params_kw.get('from_llmid')
to_llmid = params_kw.get('to_llmid')
if not from_llmid or not to_llmid:
raise Exception('请选择源模型和目标模型')
if from_llmid == to_llmid:
raise Exception('源模型和目标模型不能相同')
dbname = get_module_dbname('llmage')
async with DBPools().sqlorContext(dbname) as sor:
# 删除目标已有的映射
await sor.sqlExe("DELETE FROM llm_api_map WHERE llmid=${id}$", {'id': to_llmid})
# 复制源的所有映射到目标
src_sql = "SELECT * FROM llm_api_map WHERE llmid=${id}$"
src_recs = await sor.sqlExe(src_sql, {'id': from_llmid})
count = 0
for r in src_recs or []:
await sor.C('llm_api_map', {
'id': getID(),
'llmid': to_llmid,
'llmcatelogid': r.llmcatelogid,
'apiname': r.apiname,
'query_apiname': r.query_apiname or '',
'query_period': r.query_period or 30,
'ppid': r.ppid or '',
'isdefaultcatelog': r.isdefaultcatelog or '0',
})
count += 1
result = {'widgettype':'Message','options':{
'title':'复制完成','message':f'已复制{count}条API配置','timeout':3,'type':'success'
}}
except Exception as e:
debug(f'copy_api error: {format_exc()}')
result = {'widgettype':'Message','options':{
'title':'复制失败','message':str(e),'timeout':5,'type':'error'
}}
return result

View File

@ -0,0 +1,34 @@
{
"widgettype": "Form",
"options": {
"submit_url": "{{entire_url('../api/copy_api.dspy')}}",
"fields": [
{
"name": "from_llmid",
"label": "源模型",
"uitype": "code",
"required": true,
"dataurl": "{{entire_url('../api/get_search_llm_for_copy.dspy')}}",
"valueField": "from_llmid",
"textField": "from_llmid_text"
},
{
"name": "to_llmid",
"label": "目标模型",
"uitype": "code",
"required": true,
"dataurl": "{{entire_url('../api/get_search_llm_for_copy.dspy')}}",
"valueField": "to_llmid",
"textField": "to_llmid_text"
}
]
},
"binds": [
{
"wid": "self",
"event": "submited",
"actiontype": "close",
"target": "PopupWindow"
}
]
}

View File

@ -0,0 +1,12 @@
# 返回可选llm列表供复制API时选择源和目标
result = [{'value':'','text':'请选择'}]
try:
dbname = get_module_dbname('llmage')
async with DBPools().sqlorContext(dbname) as sor:
sql = "SELECT id as value, name as text FROM llm WHERE status='published' ORDER BY name"
recs = await sor.sqlExe(sql, {})
if recs:
result.extend([{'value':r.value,'text':r.text} for r in recs])
except Exception as e:
debug(f'get_search_llm_for_copy error: {e}')
return result