"""返回 dashboard 动态 UI 描述(含实时数据)""" from datetime import date, datetime, timedelta db = DBPools() today = date.today().isoformat() now = datetime.now() five_min_ago = (now - timedelta(minutes=5)).strftime('%Y-%m-%d %H:%M:%S') # 今日用量 async with db.sqlorContext('sage') as sor: usage = await sor.sqlExe( "SELECT COUNT(*) as cnt, COALESCE(SUM(amount), 0) as total_amount FROM llmusage WHERE use_date = ${today}$", {'today': today} ) cnt = int(usage[0]['cnt']) if usage else 0 total_amount = float(usage[0]['total_amount']) if usage else 0.0 # 总用户数 async with db.sqlorContext('sage') as sor: users = await sor.sqlExe("SELECT COUNT(*) as total_users FROM users", {}) total_users = int(users[0]['total_users']) if users else 0 # 并发用户 async with db.sqlorContext('sage') as sor: conc = await sor.sqlExe( "SELECT COUNT(DISTINCT userid) as concurrent_users FROM llmusage WHERE use_date = ${today}$ AND use_time >= ${five_min_ago}$", {'today': today, 'five_min_ago': five_min_ago} ) concurrent_users = int(conc[0]['concurrent_users']) if conc else 0 # ChartBar data_url — 用相对路径,bricks 会基于当前上下文解析 chart_data_url = 'api/get_top_models.dspy' return { "widgettype": "VBox", "options": {"width": "100%"}, "subwidgets": [ { "widgettype": "ResponsableBox", "options": {"gap": "16px", "minWidth": "250px"}, "subwidgets": [ { "widgettype": "VBox", "id": "card_today_cnt", "options": {"bgcolor": "#FFFFFF", "padding": "24px", "borderRadius": "8px", "flex": "1", "minHeight": "120px", "boxShadow": "0 2px 8px rgba(0,0,0,0.1)"}, "subwidgets": [ {"widgettype": "Text", "options": {"text": "今日调用笔数", "fontSize": "14px", "color": "#888", "marginBottom": "8px"}}, {"widgettype": "Text", "id": "today_cnt_value", "options": {"text": str(cnt), "fontSize": "32px", "fontWeight": "bold", "color": "#1890ff"}} ] }, { "widgettype": "VBox", "id": "card_today_amount", "options": {"bgcolor": "#FFFFFF", "padding": "24px", "borderRadius": "8px", "flex": "1", "minHeight": "120px", "boxShadow": "0 2px 8px rgba(0,0,0,0.1)"}, "subwidgets": [ {"widgettype": "Text", "options": {"text": "今日交易金额", "fontSize": "14px", "color": "#888", "marginBottom": "8px"}}, {"widgettype": "Text", "id": "today_amount_value", "options": {"text": f"\u00a5{total_amount:.2f}", "fontSize": "32px", "fontWeight": "bold", "color": "#52c41a"}} ] }, { "widgettype": "VBox", "id": "card_total_users", "options": {"bgcolor": "#FFFFFF", "padding": "24px", "borderRadius": "8px", "flex": "1", "minHeight": "120px", "boxShadow": "0 2px 8px rgba(0,0,0,0.1)"}, "subwidgets": [ {"widgettype": "Text", "options": {"text": "用户总数", "fontSize": "14px", "color": "#888", "marginBottom": "8px"}}, {"widgettype": "Text", "id": "total_users_value", "options": {"text": str(total_users), "fontSize": "32px", "fontWeight": "bold", "color": "#722ed1"}} ] }, { "widgettype": "VBox", "id": "card_concurrent_users", "options": {"bgcolor": "#FFFFFF", "padding": "24px", "borderRadius": "8px", "flex": "1", "minHeight": "120px", "boxShadow": "0 2px 8px rgba(0,0,0,0.1)"}, "subwidgets": [ {"widgettype": "Text", "options": {"text": "当前并发用户", "fontSize": "14px", "color": "#888", "marginBottom": "8px"}}, {"widgettype": "Text", "id": "concurrent_users_value", "options": {"text": str(concurrent_users), "fontSize": "32px", "fontWeight": "bold", "color": "#fa8c16"}} ] } ] }, { "widgettype": "VBox", "id": "chart_section", "options": {"bgcolor": "#FFFFFF", "padding": "24px", "borderRadius": "8px", "marginTop": "20px", "minHeight": "350px", "boxShadow": "0 2px 8px rgba(0,0,0,0.1)"}, "subwidgets": [ {"widgettype": "Text", "options": {"text": "Top 3 模型(今日)", "fontSize": "18px", "fontWeight": "bold", "color": "#333", "marginBottom": "16px"}}, { "widgettype": "ChartBar", "id": "top_models_chart", "options": { "height": "300px", "width": "100%", "data_url": chart_data_url, "nameField": "model_name", "valueFields": ["cnt", "total_amount"] } } ] } ] }