fix: API返回纯数组格式,添加模型上下架功能

- get_organizations/get_upapps/uapi_options: 返回纯数组[{value,text}]
- 新增 get_catelogs/get_apis/get_ppids: 独立下拉数据API
- llm_api_map_manage.ui: 使用独立API替代data_field嵌套格式
- json/llm.json: 移除data_field,添加上架/下架toolbar
- llm_status_update.dspy: 模型上下架状态更新API
- 重新生成 llm/index.ui CRUD界面
This commit is contained in:
yumoqing 2026-05-30 01:43:09 +08:00
parent 283b7d498c
commit d84cc1d859
9 changed files with 125 additions and 26 deletions

View File

@ -39,17 +39,11 @@
},
"providerid": {
"uitype": "code",
"dataurl": "{{entire_url('../api/get_organizations.dspy')}}",
"data_field": "organizations",
"textField": "text",
"valueField": "id"
"dataurl": "{{entire_url('../api/get_organizations.dspy')}}"
},
"upappid": {
"uitype": "code",
"dataurl": "{{entire_url('../api/get_upapps.dspy')}}",
"data_field": "upapps",
"textField": "text",
"valueField": "id"
"dataurl": "{{entire_url('../api/get_upapps.dspy')}}"
}
}
},
@ -59,6 +53,16 @@
"name":"test",
"label":"体验",
"selected_row":true
},
{
"name":"publish",
"label":"上架",
"selected_row":true
},
{
"name":"unpublish",
"label":"下架",
"selected_row":true
}
]
},
@ -79,6 +83,42 @@
"id":"${id}"
}
}
},
{
"wid":"self",
"event":"publish",
"actiontype":"urlwidget",
"target":"PopupWindow",
"popup_options":{
"title":"上架确认",
"cwidth":20,
"cheight":8
},
"options":{
"url":"{{entire_url('../api/llm_status_update.dspy')}}",
"params":{
"id":"${id}",
"status":"published"
}
}
},
{
"wid":"self",
"event":"unpublish",
"actiontype":"urlwidget",
"target":"PopupWindow",
"popup_options":{
"title":"下架确认",
"cwidth":20,
"cheight":8
},
"options":{
"url":"{{entire_url('../api/llm_status_update.dspy')}}",
"params":{
"id":"${id}",
"status":"unpublished"
}
}
}
],
"editexclouded": [

14
wwwroot/api/get_apis.dspy Normal file
View File

@ -0,0 +1,14 @@
#!/usr/bin/env python3
import json
result = []
try:
dbname = get_module_dbname('llmage')
async with DBPools().sqlorContext(dbname) as sor:
rows = await sor.sqlExe("select name, path from uapi order by name", {})
result = [{'value': r['name'], 'text': f"{r['name']} ({r['path']})"} for r in (rows or [])]
except Exception as e:
pass
return json.dumps(result, ensure_ascii=False, default=str)

View File

@ -0,0 +1,14 @@
#!/usr/bin/env python3
import json
result = []
try:
dbname = get_module_dbname('llmage')
async with DBPools().sqlorContext(dbname) as sor:
rows = await sor.sqlExe("select id, name from llmcatelog order by name", {})
result = [{'value': r['id'], 'text': r['name']} for r in (rows or [])]
except Exception as e:
pass
return json.dumps(result, ensure_ascii=False, default=str)

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python3
import json
result = {'success': False, 'data': {'organizations': []}}
result = []
try:
async with get_sor_context(request._run_ns, 'rbac') as sor:
@ -12,9 +12,8 @@ try:
"select id, orgname from organization where id = ${id}$ or parentid = ${id}$ order by orgname",
{'id': user_orgid}
)
result['data']['organizations'] = [{'id': r['id'], 'text': r['orgname']} for r in (all_orgs or [])]
result['success'] = True
result = [{'value': r['id'], 'text': r['orgname']} for r in (all_orgs or [])]
except Exception as e:
result['error'] = str(e)
pass
return json.dumps(result, ensure_ascii=False, default=str)

View File

@ -0,0 +1,14 @@
#!/usr/bin/env python3
import json
result = []
try:
dbname = get_module_dbname('pricing')
async with DBPools().sqlorContext(dbname) as sor:
rows = await sor.sqlExe("select id, name from pricing_program order by name", {})
result = [{'value': r['id'], 'text': r['name']} for r in (rows or [])]
except Exception as e:
pass
return json.dumps(result, ensure_ascii=False, default=str)

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python3
import json
result = {'success': False, 'data': {'upapps': []}}
result = []
try:
async with get_sor_context(request._run_ns, 'uapi') as sor:
@ -10,9 +10,8 @@ try:
"select id, name from upapp where ownerid = ${ownerid}$ or ownerid is null order by name",
{'ownerid': user_orgid}
)
result['data']['upapps'] = [{'id': r['id'], 'text': r['name']} for r in (apps or [])]
result['success'] = True
result = [{'value': r['id'], 'text': r['name']} for r in (apps or [])]
except Exception as e:
result['error'] = str(e)
pass
return json.dumps(result, ensure_ascii=False, default=str)

View File

@ -0,0 +1,23 @@
#!/usr/bin/env python3
import json
result = {'success': False, 'message': ''}
try:
dbname = get_module_dbname('llmage')
record_id = params_kw.get('id')
status = params_kw.get('status')
if not record_id:
result['message'] = '缺少id'
elif status not in ('published', 'unpublished'):
result['message'] = '无效的状态值'
else:
async with DBPools().sqlorContext(dbname) as sor:
await sor.U('llm', {'id': record_id, 'status': status})
result['success'] = True
result['message'] = '上架成功' if status == 'published' else '下架成功'
except Exception as e:
result['message'] = str(e)
return json.dumps(result, ensure_ascii=False, default=str)

View File

@ -1,17 +1,16 @@
#!/usr/bin/env python3
import json
result = {'success': False, 'data': []}
result = []
try:
dbname = get_module_dbname('llmage')
async with DBPools().sqlorContext(dbname) as sor:
rows = await sor.sqlExe("select name, path from uapi order by name", {})
result['data'] = [{'id': r['name'], 'text': f"{r['name']} ({r['path']})"} for r in (rows or [])]
result['success'] = True
result = [{'value': r['name'], 'text': f"{r['name']} ({r['path']})"} for r in (rows or [])]
except Exception as e:
result['error'] = str(e)
pass
return json.dumps(result, ensure_ascii=False, default=str)

View File

@ -53,16 +53,14 @@
"name": "llmcatelogid",
"label": "选择分类",
"uitype": "code",
"dataurl": "{{entire_url('./api/llm_api_map_options.dspy')}}",
"data_field": "catelogs",
"dataurl": "{{entire_url('./api/get_catelogs.dspy')}}",
"placeholder": "请选择分类"
},
{
"name": "apiname",
"label": "API接口",
"uitype": "code",
"dataurl": "{{entire_url('./api/llm_api_map_options.dspy')}}",
"data_field": "apis",
"dataurl": "{{entire_url('./api/get_apis.dspy')}}",
"placeholder": "请选择API接口"
},
{
@ -81,8 +79,7 @@
"name": "ppid",
"label": "计费项目",
"uitype": "code",
"dataurl": "{{entire_url('./api/llm_api_map_options.dspy')}}",
"data_field": "ppids",
"dataurl": "{{entire_url('./api/get_ppids.dspy')}}",
"placeholder": "请选择计费项目"
}
],