pipeline-llm/wwwroot/api/llm_account_recharge_popup.dspy

100 lines
5.6 KiB
Plaintext
Raw 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.

# llm_account_recharge_popup.dspy — 供应商账号列表「充值登记」弹窗内容
# 入口: json/llm_account_by_vendor.json 工具栏 recharge 按钮(selected_row) → binds
# urlwidget → PopupWindow(外壳由 popup_options 生成,此处只返回内容 widget,
# 返回 PopupWindow 会套娃——同 llm_call_trace_io.dspy 约定)。
# 入参: 列表页 toolbar selected_row 自动注入整行数据(id=账号主键)。
# 提交: POST llm_account_recharge.dspy → gateway.recharge_account:
# balance += 充值金额、total_recharge 累加、写充值流水;余额回升后
# 「钱包充值」待办由状态派生自动消失。
uid = await get_user()
if not uid:
return {"widgettype": "Message", "options": {"title": "提示", "message": "请先登录", "timeout": 3}}
acc_id = str((params_kw or {}).get('id') or '').strip()
if not acc_id:
return {"widgettype": "Message", "options": {"title": "打开失败", "message": "请先在列表中选中一个账号行"}}
user_org = str(await get_userorgid() or '0')
dbname = get_module_dbname('pipeline-llm')
async with DBPools().sqlorContext(dbname) as sor:
recs = await sor.sqlExe(
"SELECT a.id, a.name, a.balance, a.total_recharge, a.status, "
"COALESCE(NULLIF(a.org_id,''), v.org_id, '0') AS owner_org, v.name AS vendor_name "
"FROM llm_account a LEFT JOIN llm_vendor v ON v.id=a.vendor_id "
"WHERE a.id=${i}$ LIMIT 1", {"i": acc_id})
await sor.sqlExe("COMMIT", {})
if not recs:
return {"widgettype": "Message", "options": {"title": "打开失败", "message": "账号不存在或已删除"}}
row = recs[0]
owner_org = str(row['owner_org'] or '0')
# 机构隔离:平台业主('0')可看全部;否则只看本属主机构的账号(同 llm_wallet_todo_popup)
if user_org != '0' and owner_org not in ('', user_org):
return {"widgettype": "Message", "options": {"title": "无权访问", "message": "该账号属于其他机构"}}
balance = float(row['balance'] or 0)
acc_name = str(row['name'] or acc_id)
vendor_name = str(row['vendor_name'] or '')
head_md = ['## 充值登记', '',
'**账号**:' + (('【%s】' % vendor_name) if vendor_name else '') + acc_name,
'**当前余额**:%.4f 元 | **累计充值**:%.4f 元 | **状态**:%s'
% (balance, float(row['total_recharge'] or 0), str(row['status'] or '')),
'',
'> 确认后账号余额 = 当前余额 + 充值金额,并写入充值流水;'
'余额回升到门禁阈值以上后该账号自动恢复模型调用轮询。']
recharge_url = entire_url('/pipeline-llm/api/llm_account_recharge.dspy')
def _read_input_js(wid):
# 弹窗内控件 getWidgetById 起点必须 bricks.app(DOM 挂 body 下,app.root 查不到)
return ("var cw=bricks.getWidgetById(" + json.dumps(wid) + ",bricks.app);var cv='';"
"if(cw){cv=(typeof cw.resultValue==='function')?cw.resultValue():"
"((cw.dom_element&&cw.dom_element.value)||'');}"
"cv=(cv===null||cv===undefined)?'':String(cv).trim();")
# 成功:关弹窗(从内容控件沿 parent 链找 PopupWindow 外壳) + 刷新账号列表 + 提示;
# 失败:弹窗保持打开,允许改金额重试。
_close_and_refresh_js = (
"var box=bricks.getWidgetById('llm_acc_recharge_box',bricks.app);"
"var pw=box;while(pw&&!(pw instanceof bricks.PopupWindow)&&!(pw instanceof bricks.Popup)){pw=pw.parent;}"
"if(pw){if(pw.destroy){pw.destroy();}else if(pw.dismiss){pw.dismiss();}}"
"var t=bricks.getWidgetById('llm_account_tbl',bricks.app);"
"if(t&&t.render){t.old_params=null;t.render({});}")
do_js = (_read_input_js('llm_acc_amt')
+ "var amt=parseFloat(cv);"
+ "if(isNaN(amt)||amt<=0){new bricks.Message({title:'请填写金额',message:'充值金额必须是大于 0 的数字'}).open();return;}"
+ _read_input_js('llm_acc_note')
+ "var r=await fetch(" + json.dumps(recharge_url) + ",{method:'POST',"
"headers:{'Content-Type':'application/json'},"
"body:JSON.stringify({account_id:" + json.dumps(acc_id) + ",amount:amt,note:cv})});"
"var d=null;try{d=await r.json();}catch(e){}"
+ "if(d&&d.success){" + _close_and_refresh_js
+ "new bricks.Message({title:'充值成功',message:d.message||'账号余额已更新'}).open();}"
+ "else{new bricks.Message({title:'充值失败',message:(d&&(d.message||d.error))||('请求失败 HTTP '+r.status)}).open();}")
return {
"widgettype": "VBox",
"id": "llm_acc_recharge_box",
"options": {"width": "100%", "height": "100%", "padding": "16px", "gap": "12px"},
"subwidgets": [
{"widgettype": "MdWidget", "options": {"mdtext": '\n'.join(head_md), "width": "100%"}},
{"widgettype": "HBox",
"options": {"width": "100%", "gap": "8px", "alignItems": "center"},
"subwidgets": [
{"widgettype": "Text", "options": {"text": "充值金额(元):", "cfontsize": 0.9, "color": "#334155"}},
{"widgettype": "UiText", "id": "llm_acc_amt",
"options": {"name": "llm_acc_amt", "placeholder": "如 100.00", "width": "160px"}},
{"widgettype": "UiText", "id": "llm_acc_note",
"options": {"name": "llm_acc_note", "placeholder": "备注(可选,如银行流水号)",
"flex": "1 1 auto"}},
{"widgettype": "Button",
"options": {"label": "💰 确认充值", "css": "primary small"},
"binds": [{"wid": "self", "event": "click", "actiontype": "script",
"target": "self", "script": do_js}]}]}]
}