fix: failed_accounting.ui显示优化 + dspy跨库JOIN返回_text字段 - failed_accounting.ui: userid→username, userorgid→orgname, llmid→llm.name - 移除cost/use_date列, InlineForm紧凑布局 - failed_accounting_list.dspy: 跨库JOIN users/organization/llm获取名称 - handled保持原始值, 由UI的code控件显示

This commit is contained in:
Hermes Agent 2026-06-18 14:15:28 +08:00
parent 6f977450c9
commit 4abd553302
2 changed files with 132 additions and 72 deletions

View File

@ -1,72 +1,101 @@
result = {'success': False, 'rows': [], 'total': 0, 'page': 1, 'page_size': 50} result = {'success': False, 'rows': [], 'total': 0, 'page': 1, 'page_size': 50}
try: try:
dbname = get_module_dbname('llmage') llmage_db = get_module_dbname('llmage')
sage_db = get_module_dbname('sage')
db = DBPools()
filters = {} filters = {}
if params_kw.get('userorgid'): if params_kw.get('userorgid'):
filters['userorgid'] = params_kw.get('userorgid') filters['userorgid'] = params_kw.get('userorgid')
if params_kw.get('llmid'): if params_kw.get('llmid'):
filters['llmid'] = params_kw.get('llmid') filters['llmid'] = params_kw.get('llmid')
if params_kw.get('handled') is not None and params_kw.get('handled') != '': if params_kw.get('handled') is not None and params_kw.get('handled') != '':
filters['handled'] = params_kw.get('handled') filters['handled'] = params_kw.get('handled')
if params_kw.get('start_date'): if params_kw.get('start_date'):
filters['start_date'] = params_kw.get('start_date') filters['start_date'] = params_kw.get('start_date')
if params_kw.get('end_date'): if params_kw.get('end_date'):
filters['end_date'] = params_kw.get('end_date') filters['end_date'] = params_kw.get('end_date')
if params_kw.get('filter_userid'):
filters['filter_userid'] = params_kw.get('filter_userid')
if params_kw.get('filter_llmid'):
filters['filter_llmid'] = params_kw.get('filter_llmid')
page = int(params_kw.get('page', 1)) page = int(params_kw.get('page', 1))
page_size = int(params_kw.get('page_size', 50)) page_size = int(params_kw.get('page_size', 50))
async with DBPools().sqlorContext(dbname) as sor: async with db.sqlorContext(llmage_db) as sor:
conditions = [] conditions = []
ns = {} ns = {}
if 'handled' not in filters: if filters.get('userorgid'):
conditions.append("handled='0'") conditions.append("f.userorgid=${userorgid}$")
ns['userorgid'] = filters['userorgid']
if filters.get('llmid'):
conditions.append("f.llmid=${llmid}$")
ns['llmid'] = filters['llmid']
if filters.get('handled') is not None:
conditions.append("f.handled=${handled}$")
ns['handled'] = filters['handled']
if filters.get('start_date'):
conditions.append("f.use_date>=${start_date}$")
ns['start_date'] = filters['start_date']
if filters.get('end_date'):
conditions.append("f.use_date<=${end_date}$")
ns['end_date'] = filters['end_date']
if filters.get('filter_userid'):
conditions.append("f.userid LIKE ${filter_userid}$")
ns['filter_userid'] = '%' + filters['filter_userid'] + '%'
if filters.get('filter_llmid'):
conditions.append("(f.llmid LIKE ${filter_llmid}$ OR f.llmid_text LIKE ${filter_llmid}$)")
ns['filter_llmid'] = '%' + filters['filter_llmid'] + '%'
if filters.get('userorgid'): where = ""
conditions.append("userorgid=${userorgid}$") if conditions:
ns['userorgid'] = filters['userorgid'] where = "WHERE " + " AND ".join(conditions)
if filters.get('llmid'):
conditions.append("llmid=${llmid}$")
ns['llmid'] = filters['llmid']
if filters.get('handled') is not None:
conditions.append("handled=${handled}$")
ns['handled'] = filters['handled']
if filters.get('start_date'):
conditions.append("use_date>=${start_date}$")
ns['start_date'] = filters['start_date']
if filters.get('end_date'):
conditions.append("use_date<=${end_date}$")
ns['end_date'] = filters['end_date']
where = "" # 跨库JOIN获取名称
if conditions: sql = f"""
where = "where " + " and ".join(conditions) SELECT f.*,
u.username as userid_text,
o.orgname as userorgid_text,
l.name as llmid_text
FROM llmusage_accounting_failed f
LEFT JOIN {sage_db}.users u ON f.userid = u.userid
LEFT JOIN {sage_db}.organization o ON f.userorgid = o.id
LEFT JOIN {llmage_db}.llm l ON f.llmid = l.id
{where}
ORDER BY f.failed_time DESC
"""
count_sql = f"select count(*) as cnt from llmusage_accounting_failed {where}" count_sql = f"""
count_recs = await sor.sqlExe(count_sql, ns) SELECT count(*) as cnt
total = count_recs[0].cnt if count_recs else 0 FROM llmusage_accounting_failed f
LEFT JOIN {sage_db}.users u ON f.userid = u.userid
LEFT JOIN {sage_db}.organization o ON f.userorgid = o.id
LEFT JOIN {llmage_db}.llm l ON f.llmid = l.id
{where}
"""
count_recs = await sor.sqlExe(count_sql, ns)
total = count_recs[0].cnt if count_recs else 0
offset = (page - 1) * page_size offset = (page - 1) * page_size
query_sql = f"""select * from llmusage_accounting_failed {where} query_sql = sql + f" LIMIT {page_size} OFFSET {offset}"
order by failed_time desc limit {page_size} offset {offset}""" recs = await sor.sqlExe(query_sql, ns)
recs = await sor.sqlExe(query_sql, ns)
rows = [] rows = []
for r in (recs or []): for r in (recs or []):
d = dict(r) d = dict(r)
d['handled'] = '已处理' if d.get('handled') == '1' else '未处理' rows.append(d)
rows.append(d)
result['rows'] = rows result['rows'] = rows
result['total'] = total result['total'] = total
result['page'] = page result['page'] = page
result['page_size'] = page_size result['page_size'] = page_size
result['success'] = True result['success'] = True
except Exception as e: except Exception as e:
result['error'] = str(e) result['error'] = str(e)
debug(f'failed_accounting_list error: {format_exc()}')
return json.dumps(result, ensure_ascii=False, default=str) return json.dumps(result, ensure_ascii=False, default=str)

View File

@ -3,22 +3,15 @@
"options": { "options": {
"width": "100%", "width": "100%",
"height": "100%", "height": "100%",
"padding": "16px", "padding": "8px",
"spacing": 12 "gap": "8px"
}, },
"subwidgets": [ "subwidgets": [
{
"widgettype": "Title2",
"options": {
"text": "记账失败记录",
"halign": "left"
}
},
{ {
"widgettype": "HBox", "widgettype": "HBox",
"options": { "options": {
"width": "100%", "width": "100%",
"spacing": 8, "gap": "8px",
"alignItems": "flex-end" "alignItems": "flex-end"
}, },
"subwidgets": [ "subwidgets": [
@ -28,7 +21,6 @@
"options": { "options": {
"css": "card", "css": "card",
"padding": "8px", "padding": "8px",
"show_label": true,
"submit_label": "查询", "submit_label": "查询",
"submit_css": "primary", "submit_css": "primary",
"fields": [ "fields": [
@ -115,19 +107,58 @@
{"value": "0", "text": "未处理"}, {"value": "0", "text": "未处理"},
{"value": "1", "text": "已处理"} {"value": "1", "text": "已处理"}
] ]
},
"userid": {
"uitype": "code",
"valueField": "userid",
"textField": "userid_text",
"params": {
"dbname": "sage",
"table": "users",
"tblvalue": "userid",
"tbltext": "username",
"valueField": "userid",
"textField": "userid_text"
},
"dataurl": "{{entire_url('/appbase/get_code.dspy')}}"
},
"userorgid": {
"uitype": "code",
"valueField": "userorgid",
"textField": "userorgid_text",
"params": {
"dbname": "sage",
"table": "organization",
"tblvalue": "id",
"tbltext": "orgname",
"valueField": "userorgid",
"textField": "userorgid_text"
},
"dataurl": "{{entire_url('/appbase/get_code.dspy')}}"
},
"llmid": {
"uitype": "code",
"valueField": "llmid",
"textField": "llmid_text",
"params": {
"dbname": "llmage",
"table": "llm",
"tblvalue": "id",
"tbltext": "name",
"valueField": "llmid",
"textField": "llmid_text"
},
"dataurl": "{{entire_url('/appbase/get_code.dspy')}}"
} }
} }
}, },
"fields": [ "fields": [
{"name": "id", "title": "ID", "type": "str", "length": 32, "uitype": "str", "label": "ID"},
{"name": "llmusageid", "title": "使用记录ID", "type": "str", "length": 32, "cwidth": 12, "uitype": "str", "label": "使用记录ID"}, {"name": "llmusageid", "title": "使用记录ID", "type": "str", "length": 32, "cwidth": 12, "uitype": "str", "label": "使用记录ID"},
{"name": "llmid", "title": "模型ID", "type": "str", "length": 32, "cwidth": 12, "uitype": "str", "label": "模型ID"}, {"name": "llmid", "title": "模型", "type": "str", "length": 32, "cwidth": 12, "uitype": "str", "label": "模型"},
{"name": "userid", "title": "用户ID", "type": "str", "length": 32, "cwidth": 10, "uitype": "str", "label": "用户ID"}, {"name": "userid", "title": "用户", "type": "str", "length": 32, "cwidth": 10, "uitype": "str", "label": "用户"},
{"name": "userorgid", "title": "机构ID", "type": "str", "length": 32, "cwidth": 10, "uitype": "str", "label": "机构ID"}, {"name": "userorgid", "title": "机构", "type": "str", "length": 32, "cwidth": 10, "uitype": "str", "label": "机构"},
{"name": "use_date", "title": "使用日期", "type": "date", "cwidth": 10, "uitype": "date", "label": "使用日期"},
{"name": "use_time", "title": "使用时间", "type": "timestamp", "cwidth": 14, "uitype": "str", "label": "使用时间"}, {"name": "use_time", "title": "使用时间", "type": "timestamp", "cwidth": 14, "uitype": "str", "label": "使用时间"},
{"name": "amount", "title": "金额", "type": "double", "length": 18, "dec": 5, "cwidth": 8, "uitype": "float", "label": "金额"}, {"name": "amount", "title": "金额", "type": "double", "length": 18, "dec": 5, "cwidth": 8, "uitype": "float", "label": "金额"},
{"name": "cost", "title": "成本", "type": "double", "length": 18, "dec": 5, "cwidth": 8, "uitype": "float", "label": "成本"},
{"name": "failed_reason", "title": "失败原因", "type": "text", "cwidth": 20, "uitype": "text", "label": "失败原因"}, {"name": "failed_reason", "title": "失败原因", "type": "text", "cwidth": 20, "uitype": "text", "label": "失败原因"},
{"name": "failed_time", "title": "失败时间", "type": "timestamp", "cwidth": 14, "uitype": "str", "label": "失败时间"}, {"name": "failed_time", "title": "失败时间", "type": "timestamp", "cwidth": 14, "uitype": "str", "label": "失败时间"},
{"name": "retry_count", "title": "重试", "type": "int", "cwidth": 4, "uitype": "int", "label": "重试"}, {"name": "retry_count", "title": "重试", "type": "int", "cwidth": 4, "uitype": "int", "label": "重试"},