From d57b8dbc73f3ee1797586e84fafe83793e112859 Mon Sep 17 00:00:00 2001 From: yumoqing Date: Wed, 1 Jul 2026 15:02:33 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A4=8D=E5=88=B6API=E5=8A=9F=E8=83=BD?= =?UTF-8?q?-=E5=B7=A5=E5=85=B7=E6=A0=8F=E6=8C=89=E9=92=AE+=E5=BC=B9?= =?UTF-8?q?=E7=AA=97=E9=80=89=E6=BA=90/=E7=9B=AE=E6=A0=87+=E5=90=8E?= =?UTF-8?q?=E5=8F=B0=E5=A4=8D=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- json/llm.json | 19 ++++++++++ scripts/load_path.py | 3 ++ wwwroot/api/copy_api.dspy | 47 ++++++++++++++++++++++++ wwwroot/api/copy_api_form.ui | 34 +++++++++++++++++ wwwroot/api/get_search_llm_for_copy.dspy | 12 ++++++ 5 files changed, 115 insertions(+) create mode 100644 wwwroot/api/copy_api.dspy create mode 100644 wwwroot/api/copy_api_form.ui create mode 100644 wwwroot/api/get_search_llm_for_copy.dspy diff --git a/json/llm.json b/json/llm.json index 0b82d74..794bae8 100644 --- a/json/llm.json +++ b/json/llm.json @@ -58,6 +58,10 @@ "name":"unpublish", "label":"下架", "selected_row":true + }, + { + "name":"copy_api", + "label":"复制API" } ] }, @@ -114,6 +118,21 @@ "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": [ diff --git a/scripts/load_path.py b/scripts/load_path.py index 01a739a..9754ced 100644 --- a/scripts/load_path.py +++ b/scripts/load_path.py @@ -127,6 +127,9 @@ PATHS_LOGINED = [ f"/{MOD}/api/llmusage_update.dspy", f"/{MOD}/api/retry_accounting.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/ f"/{MOD}/llm/index.ui", diff --git a/wwwroot/api/copy_api.dspy b/wwwroot/api/copy_api.dspy new file mode 100644 index 0000000..c02df6f --- /dev/null +++ b/wwwroot/api/copy_api.dspy @@ -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 diff --git a/wwwroot/api/copy_api_form.ui b/wwwroot/api/copy_api_form.ui new file mode 100644 index 0000000..6a460d7 --- /dev/null +++ b/wwwroot/api/copy_api_form.ui @@ -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" + } + ] +} diff --git a/wwwroot/api/get_search_llm_for_copy.dspy b/wwwroot/api/get_search_llm_for_copy.dspy new file mode 100644 index 0000000..0c463e7 --- /dev/null +++ b/wwwroot/api/get_search_llm_for_copy.dspy @@ -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