From d5f732434ca46bb0b323d18bd2334de1ae8af08f Mon Sep 17 00:00:00 2001 From: yumoqing Date: Wed, 1 Jul 2026 14:21:35 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20add=20copy=5Fapi=20tool=20to=20upapp=20?= =?UTF-8?q?=E2=80=94=20copy=20all=20uapi=20records=20to=20another=20upapp?= =?UTF-8?q?=20system?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- json/upapp.json | 62 ----------------------------------- wwwroot/api/copy_uapi.dspy | 66 ++++++++++++++++++++++++++++++++++++++ wwwroot/copy_uapi.ui | 33 +++++++++++++++++++ 3 files changed, 99 insertions(+), 62 deletions(-) create mode 100644 wwwroot/api/copy_uapi.dspy create mode 100644 wwwroot/copy_uapi.ui diff --git a/json/upapp.json b/json/upapp.json index 4eb7f9b..aa0942e 100644 --- a/json/upapp.json +++ b/json/upapp.json @@ -13,18 +13,6 @@ "label":"跳转到", "selected_data":true }, - { - "selected_row":true, - "name":"upappkey", - "icon":"{{entire_url('/imgs/upappkey.svg')}}", - "label":"APIKEY" - }, - { - "selected_row":true, - "name":"uapi", - "icon":"{{entire_url('/imgs/uapi.svg')}}", - "label":"API" - }, { "selected_row":true, "name":"copy_api", @@ -42,56 +30,6 @@ "url":"{{entire_url('/uapi/jump_in.dspy')}}" } }, - { - "wid":"self", - "event":"upappkey", - "actiontype":"urlwidget", - "target":"PopupWindow", - "popup_options":{ - "title":"APIKEY", - "icon":"{{entire_url('/appbase/get_icon.dspy')}}?id=upappkey", - "resizable":true, - "height":"70%", - "width":"70%" - }, - "params_mapping":{ - "mapping":{ - "id":"upappid", - "referer_widget":"referer_widget" - }, - "need_other":false - }, - "options":{ - "method":"POST", - "params":{}, - "url":"{{entire_url('../upappkey')}}" - } - }, - { - "wid":"self", - "event":"uapi", - "actiontype":"urlwidget", - "target":"PopupWindow", - "popup_options":{ - "title":"API", - "icon":"{{entire_url('/appbase/get_icon.dspy')}}?id=uapi", - "resizable":true, - "height":"70%", - "width":"70%" - }, - "params_mapping":{ - "mapping":{ - "id":"upappid", - "referer_widget":"referer_widget" - }, - "need_other":false - }, - "options":{ - "method":"POST", - "params":{}, - "url":"{{entire_url('../uapi')}}" - } - }, { "wid":"self", "event":"copy_api", diff --git a/wwwroot/api/copy_uapi.dspy b/wwwroot/api/copy_uapi.dspy new file mode 100644 index 0000000..511489f --- /dev/null +++ b/wwwroot/api/copy_uapi.dspy @@ -0,0 +1,66 @@ +ns = params_kw.copy() + +source_upappid = ns.get('source_upappid', '') +target_upappid = ns.get('target_upappid', '') + +if not source_upappid: + return json.dumps({'widgettype':'Error','options':{'text':'缺少源上位系统ID'}}, ensure_ascii=False) + +if not target_upappid: + return json.dumps({'widgettype':'Error','options':{'text':'请选择目标上位系统'}}, ensure_ascii=False) + +if source_upappid == target_upappid: + return json.dumps({'widgettype':'Error','options':{'text':'源和目标上位系统不能相同'}}, ensure_ascii=False) + +db = DBPools() +dbname = get_module_dbname('uapi') +async with db.sqlorContext(dbname) as sor: + # 查询源上位系统的所有API + sql = 'select * from uapi where upappid = ${upappid}$' + source_uapis = await sor.sqlExe(sql, {'upappid': source_upappid}) + + if not source_uapis: + return json.dumps({'widgettype':'Error','options':{'text':'源上位系统中没有API记录'}}, ensure_ascii=False) + + # 查询目标上位系统已有的API名称 + existing_sql = 'select name from uapi where upappid = ${upappid}$' + existing_recs = await sor.sqlExe(existing_sql, {'upappid': target_upappid}) + existing_names = {r['name'] for r in existing_recs} + + copied = 0 + skipped = 0 + for api in source_uapis: + if api['name'] in existing_names: + skipped += 1 + continue + + new_id = getID() + await sor.sqlExe( + '''insert into uapi (id,upappid,name,title,description,need_auth,stream,path,httpmethod,chunk_match,headers,params,data,response,ioid,callbackurl) + values (${id}$,${upappid}$,${name}$,${title}$,${description}$,${need_auth}$,${stream}$,${path}$,${httpmethod}$,${chunk_match}$,${headers}$,${params}$,${data}$,${response}$,${ioid}$,${callbackurl}$)''', + { + 'id': new_id, + 'upappid': target_upappid, + 'name': api.get('name', ''), + 'title': api.get('title', ''), + 'description': api.get('description', ''), + 'need_auth': api.get('need_auth', '0'), + 'stream': api.get('stream', ''), + 'path': api.get('path', ''), + 'httpmethod': api.get('httpmethod', 'GET'), + 'chunk_match': api.get('chunk_match', ''), + 'headers': api.get('headers', ''), + 'params': api.get('params', ''), + 'data': api.get('data', ''), + 'response': api.get('response', ''), + 'ioid': api.get('ioid', ''), + 'callbackurl': api.get('callbackurl', '') + } + ) + copied += 1 + + msg = f'成功复制 {copied} 条API记录' + if skipped > 0: + msg += f',跳过 {skipped} 条(API名称已存在)' + + return json.dumps({'widgettype':'Message','options':{'text':msg}}, ensure_ascii=False) diff --git a/wwwroot/copy_uapi.ui b/wwwroot/copy_uapi.ui new file mode 100644 index 0000000..b46023b --- /dev/null +++ b/wwwroot/copy_uapi.ui @@ -0,0 +1,33 @@ +{% set upapps = get_upapps_for_copy(request) %} +{ + "widgettype": "VBox", + "options": {"padding": "16px", "width": "100%"}, + "subwidgets": [ + { + "widgettype": "Text", + "options": {"text": "选择目标上位系统,将当前上位系统的所有API接口复制到目标系统"} + }, + { + "widgettype": "Form", + "options": { + "submit_url": "{{entire_url('./api/copy_uapi.dspy')}}", + "fields": [ + {"name": "source_upappid", "uitype": "hide", "value": "{{params_kw.get('upappid', '')}}"}, + {"name": "target_upappid", "uitype": "code", "label": "目标上位系统", "required": true, "codes": {{json.dumps(upapps, ensure_ascii=False)}}} + ] + }, + "binds": [ + { + "wid": "self", + "event": "submited", + "actiontype": "urlwidget", + "target": "app.sage_main_content", + "mode": "replace", + "options": { + "url": "{{entire_url('/uapi/upapp/')}}" + } + } + ] + } + ] +}