pipeline-llm/wwwroot/api/llm_wallet_todo_popup.dspy

120 lines
5.8 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_wallet_todo_popup.dspy — 钱包余额不足待办详情弹窗2026-09-11 用户定夺)
# 平台待办 source='llm_wallet' 的「查看内容并处理」入口。
# 入参: id=llm_wallet_<account_id> 或 account_id=<账号id>
# 展示账号钱包状态 + 充值表单(金额/备注)→ POST llm_account_recharge.dspy
# 充值到账余额回升 → 待办由状态派生自动消失provider 不再返回)。
import json as _json
uid = await get_user()
if not uid:
return {"widgettype": "Message", "options": {"title": "未登录", "message": "请先登录后查看待办"}}
pk = params_kw or {}
acc_id = str(pk.get('account_id') or '').strip()
if not acc_id:
raw = str(pk.get('id') or '').strip()
if raw.startswith('llm_wallet_'):
acc_id = raw[len('llm_wallet_'):]
else:
acc_id = raw
if not acc_id:
return {"widgettype": "Message", "options": {"title": "打开失败", "message": "缺少账号 id"}}
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, a.org_id, "
"v.name AS vendor_name, COALESCE(NULLIF(a.org_id,''), v.org_id, '0') AS owner_org "
"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", {})
trecs = await sor.sqlExe(
"SELECT params_value FROM params WHERE params_name='llm_wallet_balance_threshold' LIMIT 1", {})
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')可看全部;否则只看本属主机构的账号
if user_org != '0' and owner_org not in ('', user_org):
return {"widgettype": "Message", "options": {"title": "无权访问", "message": "该账号属于其他机构"}}
balance = float(row['balance'] or 0)
threshold = 5.0
try:
if trecs and str(trecs[0]['params_value'] or '').strip():
threshold = float(str(trecs[0]['params_value']).strip())
except Exception:
pass
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 元 **门禁阈值**%.2f 元 **累计充值**%.4f 元'
% (balance, threshold, float(row['total_recharge'] or 0)),
'**账号状态**' + str(row['status'] or ''), '']
if balance < threshold:
head_md += ['> ⚠️ 余额低于门禁阈值——该账号已从模型调用轮询集剔除,'
'调用其下模型将顺延到其他账号;全部账号不足时调用报可行动错误。',
'> 充值到账后待办自动消失、账号自动恢复轮询。', '']
else:
head_md += ['> ✅ 余额已恢复到阈值以上,账号在轮询集中正常可用,本待办即将自动关闭。', '']
recharge_url = entire_url('/pipeline-llm/api/llm_account_recharge.dspy')
def _read_input_js(wid):
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();")
_tail = ("var pw=bricks.getWidgetById('llm_wallet_todo_pw',bricks.app);"
"if(pw&&pw.destroy){pw.destroy();}"
"if(window.refreshTodo){window.refreshTodo();}"
"if(d&&d.success){var mo=new bricks.Message({title:'充值成功',message:d.message||'钱包已充值'});mo.open();}"
"else{var mf=new bricks.Message({title:'充值失败',message:(d&&(d.message||d.error))||'充值失败'});mf.open();}")
do_js = (_read_input_js('llm_wallet_amt')
+ "var amt=parseFloat(cv);"
+ "if(isNaN(amt)||amt<=0){new bricks.Message({title:'请填写金额',message:'充值金额必须是大于 0 的数字'}).open();return;}"
+ _read_input_js('llm_wallet_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=await r.json();" + _tail)
sub = [
{"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_wallet_amt",
"options": {"name": "llm_wallet_amt", "placeholder": "如 100.00", "width": "160px"}},
{"widgettype": "UiText", "id": "llm_wallet_note",
"options": {"name": "llm_wallet_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}]}]}]
return {
"widgettype": "PopupWindow",
"id": "llm_wallet_todo_pw",
"options": {"title": "钱包充值 — " + acc_name, "width": "52%", "height": "46%",
"auto_open": True, "resizable": True},
"subwidgets": [{
"widgettype": "VScrollPanel",
"options": {"css": "filler", "width": "100%", "height": "100%", "padding": "14px"},
"subwidgets": sub}]
}