diff --git a/dashboard_for_sage/load_dashboard.py b/dashboard_for_sage/load_dashboard.py
index 69d0a6a..a584453 100644
--- a/dashboard_for_sage/load_dashboard.py
+++ b/dashboard_for_sage/load_dashboard.py
@@ -586,6 +586,99 @@ async def get_customer_daily_trend(request):
return result
+async def get_customer_users_today(request):
+ """获取当前客户组织今日各用户使用统计(含总计行)"""
+ env = request._run_ns
+ org_id = await _get_org_id(request)
+ today = env.curDateString()
+ async with get_sor_context(env, 'sage') as sor:
+ sql = """
+ SELECT
+ a.userid,
+ COALESCE(b.nick_name, b.username) as user_name,
+ COUNT(*) as call_cnt,
+ COALESCE(SUM(a.amount), 0) as total_amount
+ FROM llmusage a
+ LEFT JOIN users b ON a.userid = b.id
+ WHERE a.use_date = ${today}$
+ AND a.userorgid = ${org_id}$
+ GROUP BY a.userid, b.nick_name, b.username
+ ORDER BY call_cnt DESC
+ """
+ recs = await sor.sqlExe(sql, {'today': today, 'org_id': org_id})
+ result = []
+ total_calls = 0
+ total_amount = 0.0
+ for r in recs:
+ c = int(r.get('call_cnt', 0))
+ a = round(float(r.get('total_amount', 0)), 4)
+ total_calls += c
+ total_amount += a
+ result.append({
+ 'user_name': r.get('user_name', 'Unknown'),
+ 'call_cnt': c,
+ 'total_amount': a
+ })
+ # 追加总计行
+ result.append({
+ 'user_name': '【合计】',
+ 'call_cnt': total_calls,
+ 'total_amount': round(total_amount, 4)
+ })
+ return result
+
+
+async def get_customer_users_month(request):
+ """获取当前客户组织当月各用户使用统计(含总计行)"""
+ env = request._run_ns
+ org_id = await _get_org_id(request)
+ now = datetime.now()
+ month_start = now.strftime('%Y-%m-01')
+ if now.month == 12:
+ month_end = f'{now.year + 1}-01-01'
+ else:
+ month_end = f'{now.year}-{now.month + 1:02d}-01'
+ async with get_sor_context(env, 'sage') as sor:
+ sql = """
+ SELECT
+ a.userid,
+ COALESCE(b.nick_name, b.username) as user_name,
+ COUNT(*) as call_cnt,
+ COALESCE(SUM(a.amount), 0) as total_amount
+ FROM llmusage a
+ LEFT JOIN users b ON a.userid = b.id
+ WHERE a.use_date >= ${month_start}$
+ AND a.use_date < ${month_end}$
+ AND a.userorgid = ${org_id}$
+ GROUP BY a.userid, b.nick_name, b.username
+ ORDER BY call_cnt DESC
+ """
+ recs = await sor.sqlExe(sql, {
+ 'month_start': month_start,
+ 'month_end': month_end,
+ 'org_id': org_id
+ })
+ result = []
+ total_calls = 0
+ total_amount = 0.0
+ for r in recs:
+ c = int(r.get('call_cnt', 0))
+ a = round(float(r.get('total_amount', 0)), 4)
+ total_calls += c
+ total_amount += a
+ result.append({
+ 'user_name': r.get('user_name', 'Unknown'),
+ 'call_cnt': c,
+ 'total_amount': a
+ })
+ result.append({
+ 'user_name': '【合计】',
+ 'call_cnt': total_calls,
+ 'total_amount': round(total_amount, 4)
+ })
+ return result
+
+
def load_dashboard():
"""Register dashboard functions on ServerEnv"""
g = ServerEnv()
@@ -613,3 +706,5 @@ def load_dashboard():
g.get_customer_daily_summary = get_customer_daily_summary
g.get_customer_month_summary = get_customer_month_summary
g.get_customer_daily_trend = get_customer_daily_trend
+ g.get_customer_users_today = get_customer_users_today
+ g.get_customer_users_month = get_customer_users_month
diff --git a/scripts/load_path.py b/scripts/load_path.py
index 122ed38..4ee9713 100644
--- a/scripts/load_path.py
+++ b/scripts/load_path.py
@@ -79,6 +79,7 @@ paths = [
("/dashboard_for_sage/customer_daily_chart.ui", "logined"),
("/dashboard_for_sage/customer_monthly_chart.ui", "logined"),
("/dashboard_for_sage/customer_daily_trend.ui", "logined"),
+ ("/dashboard_for_sage/customer_users_table.ui", "logined"),
# API endpoints
("/dashboard_for_sage/api/top_models.dspy", "logined"),
@@ -87,6 +88,8 @@ paths = [
("/dashboard_for_sage/api/customer_daily_models.dspy", "logined"),
("/dashboard_for_sage/api/customer_monthly_models.dspy", "logined"),
("/dashboard_for_sage/api/customer_daily_trend.dspy", "logined"),
+ ("/dashboard_for_sage/api/customer_users_today.dspy", "logined"),
+ ("/dashboard_for_sage/api/customer_users_month.dspy", "logined"),
]
diff --git a/wwwroot/api/customer_users_month.dspy b/wwwroot/api/customer_users_month.dspy
new file mode 100644
index 0000000..45d91ba
--- /dev/null
+++ b/wwwroot/api/customer_users_month.dspy
@@ -0,0 +1,6 @@
+# coding=utf-8
+"""Customer per-user month usage API"""
+import json
+
+users = await get_customer_users_month(request)
+return json.dumps(users, ensure_ascii=False, default=str)
diff --git a/wwwroot/api/customer_users_today.dspy b/wwwroot/api/customer_users_today.dspy
new file mode 100644
index 0000000..1163e9f
--- /dev/null
+++ b/wwwroot/api/customer_users_today.dspy
@@ -0,0 +1,6 @@
+# coding=utf-8
+"""Customer per-user today usage API"""
+import json
+
+users = await get_customer_users_today(request)
+return json.dumps(users, ensure_ascii=False, default=str)
diff --git a/wwwroot/customer_usage.ui b/wwwroot/customer_usage.ui
index 05acf05..f6f5027 100644
--- a/wwwroot/customer_usage.ui
+++ b/wwwroot/customer_usage.ui
@@ -10,290 +10,20 @@
"options": {
"css": "filler"
},
- "subwidgets": [
- {
- "widgettype": "HBox",
- "options": {
- "width": "100%",
- "alignItems": "center",
- "marginBottom": "24px"
- },
- "subwidgets": [
- {
- "widgettype": "Title2",
- "options": {
- "fontWeight": "700",
- "otext": "客户专属监控",
- "i18n": true
- }
- },
- {
- "widgettype": "Filler"
- },
- {
- "widgettype": "Button",
- "options": {
- "label": "返回首页",
- "borderRadius": "6px",
- "padding": "6px 16px",
- "fontSize": "13px"
- },
- "binds": [
- {
- "wid": "self",
- "event": "click",
- "actiontype": "urlwidget",
- "target": "app.sage_main_content",
- "options": {
- "url": "{{entire_url('/dashboard_for_sage/index.ui')}}"
- },
- "mode": "replace"
- }
- ]
- }
- ]
- },
- {
- "widgettype": "ResponsableBox",
- "options": {
- "gap": "16px",
- "minWidth": "220px",
- "marginBottom": "24px"
- },
- "subwidgets": [
- {
- "widgettype": "VBox",
- "options": {
- "css": "stat-card",
- "padding": "20px",
- "borderRadius": "12px",
- "flex": "1",
- "minHeight": "110px"
- },
- "subwidgets": [
- {
- "widgettype": "HBox",
- "options": {
- "alignItems": "center",
- "marginBottom": "12px"
- },
- "subwidgets": [
- {
- "widgettype": "Svg",
- "options": {
- "svg": "",
- "width": "24px",
- "height": "24px"
- }
- },
- {
- "widgettype": "Filler"
- }
- ]
- },
- {
- "widgettype": "Text",
- "options": {
- "css": "stat-value",
- "text": "{{get_customer_daily_summary(request).cnt}}",
- "fontSize": "32px",
- "fontWeight": "700",
- "lineHeight": "1.1"
- }
- },
- {
- "widgettype": "Text",
- "options": {
- "css": "stat-label",
- "fontSize": "14px",
- "marginTop": "4px",
- "otext": "今日调用次数",
- "i18n": true
- }
- }
- ]
- },
- {
- "widgettype": "VBox",
- "options": {
- "css": "stat-card",
- "padding": "20px",
- "borderRadius": "12px",
- "flex": "1",
- "minHeight": "110px"
- },
- "subwidgets": [
- {
- "widgettype": "HBox",
- "options": {
- "alignItems": "center",
- "marginBottom": "12px"
- },
- "subwidgets": [
- {
- "widgettype": "Svg",
- "options": {
- "svg": "",
- "width": "24px",
- "height": "24px"
- }
- },
- {
- "widgettype": "Filler"
- }
- ]
- },
- {
- "widgettype": "Text",
- "options": {
- "css": "stat-value",
- "text": "¥{{get_customer_daily_summary(request).total_amount|round(2)}}",
- "fontSize": "32px",
- "fontWeight": "700",
- "lineHeight": "1.1"
- }
- },
- {
- "widgettype": "Text",
- "options": {
- "css": "stat-label",
- "fontSize": "14px",
- "marginTop": "4px",
- "otext": "今日消费金额",
- "i18n": true
- }
- }
- ]
- },
- {
- "widgettype": "VBox",
- "options": {
- "css": "stat-card",
- "padding": "20px",
- "borderRadius": "12px",
- "flex": "1",
- "minHeight": "110px"
- },
- "subwidgets": [
- {
- "widgettype": "HBox",
- "options": {
- "alignItems": "center",
- "marginBottom": "12px"
- },
- "subwidgets": [
- {
- "widgettype": "Svg",
- "options": {
- "svg": "",
- "width": "24px",
- "height": "24px"
- }
- },
- {
- "widgettype": "Filler"
- }
- ]
- },
- {
- "widgettype": "Text",
- "options": {
- "css": "stat-value",
- "text": "{{get_customer_month_summary(request).cnt}}",
- "fontSize": "32px",
- "fontWeight": "700",
- "lineHeight": "1.1"
- }
- },
- {
- "widgettype": "Text",
- "options": {
- "css": "stat-label",
- "fontSize": "14px",
- "marginTop": "4px",
- "otext": "本月调用次数",
- "i18n": true
- }
- }
- ]
- },
- {
- "widgettype": "VBox",
- "options": {
- "css": "stat-card",
- "padding": "20px",
- "borderRadius": "12px",
- "flex": "1",
- "minHeight": "110px"
- },
- "subwidgets": [
- {
- "widgettype": "HBox",
- "options": {
- "alignItems": "center",
- "marginBottom": "12px"
- },
- "subwidgets": [
- {
- "widgettype": "Svg",
- "options": {
- "svg": "",
- "width": "24px",
- "height": "24px"
- }
- },
- {
- "widgettype": "Filler"
- }
- ]
- },
- {
- "widgettype": "Text",
- "options": {
- "css": "stat-value",
- "text": "¥{{get_customer_month_summary(request).total_amount|round(2)}}",
- "fontSize": "32px",
- "fontWeight": "700",
- "lineHeight": "1.1"
- }
- },
- {
- "widgettype": "Text",
- "options": {
- "css": "stat-label",
- "fontSize": "14px",
- "marginTop": "4px",
- "otext": "本月消费金额",
- "i18n": true
- }
- }
- ]
- }
- ]
- },
- {
- "widgettype": "VBox",
- "options": {
- "css": "card",
- "width": "100%",
- "borderRadius": "12px",
- "padding": "20px",
- "marginBottom": "20px"
- },
"subwidgets": [
{
"widgettype": "HBox",
"options": {
"width": "100%",
"alignItems": "center",
- "marginBottom": "16px"
+ "marginBottom": "24px"
},
"subwidgets": [
{
- "widgettype": "Title4",
+ "widgettype": "Title2",
"options": {
- "fontWeight": "600",
- "otext": "本月每日调用趋势",
+ "fontWeight": "700",
+ "otext": "客户专属监控",
"i18n": true
}
},
@@ -303,20 +33,424 @@
{
"widgettype": "Button",
"options": {
- "label": "刷新",
- "border": "none",
+ "label": "返回首页",
"borderRadius": "6px",
- "padding": "4px 12px",
- "fontSize": "12px"
+ "padding": "6px 16px",
+ "fontSize": "13px"
},
"binds": [
{
"wid": "self",
"event": "click",
- "actiontype": "method",
- "target": "-@ChartLine",
- "method": "render_urldata",
- "params": {}
+ "actiontype": "urlwidget",
+ "target": "app.sage_main_content",
+ "options": {
+ "url": "{{entire_url('/dashboard_for_sage/index.ui')}}"
+ },
+ "mode": "replace"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "widgettype": "ResponsableBox",
+ "options": {
+ "gap": "16px",
+ "minWidth": "220px",
+ "marginBottom": "24px"
+ },
+ "subwidgets": [
+ {
+ "widgettype": "VBox",
+ "options": {
+ "css": "stat-card",
+ "padding": "20px",
+ "borderRadius": "12px",
+ "flex": "1",
+ "minHeight": "110px"
+ },
+ "subwidgets": [
+ {
+ "widgettype": "HBox",
+ "options": {
+ "alignItems": "center",
+ "marginBottom": "12px"
+ },
+ "subwidgets": [
+ {
+ "widgettype": "Svg",
+ "options": {
+ "svg": "",
+ "width": "24px",
+ "height": "24px"
+ }
+ },
+ {
+ "widgettype": "Filler"
+ }
+ ]
+ },
+ {
+ "widgettype": "Text",
+ "options": {
+ "css": "stat-value",
+ "text": "{{get_customer_daily_summary(request).cnt}}",
+ "fontSize": "32px",
+ "fontWeight": "700",
+ "lineHeight": "1.1"
+ }
+ },
+ {
+ "widgettype": "Text",
+ "options": {
+ "css": "stat-label",
+ "fontSize": "14px",
+ "marginTop": "4px",
+ "otext": "今日调用次数",
+ "i18n": true
+ }
+ }
+ ]
+ },
+ {
+ "widgettype": "VBox",
+ "options": {
+ "css": "stat-card",
+ "padding": "20px",
+ "borderRadius": "12px",
+ "flex": "1",
+ "minHeight": "110px"
+ },
+ "subwidgets": [
+ {
+ "widgettype": "HBox",
+ "options": {
+ "alignItems": "center",
+ "marginBottom": "12px"
+ },
+ "subwidgets": [
+ {
+ "widgettype": "Svg",
+ "options": {
+ "svg": "",
+ "width": "24px",
+ "height": "24px"
+ }
+ },
+ {
+ "widgettype": "Filler"
+ }
+ ]
+ },
+ {
+ "widgettype": "Text",
+ "options": {
+ "css": "stat-value",
+ "text": "¥{{get_customer_daily_summary(request).total_amount|round(2)}}",
+ "fontSize": "32px",
+ "fontWeight": "700",
+ "lineHeight": "1.1"
+ }
+ },
+ {
+ "widgettype": "Text",
+ "options": {
+ "css": "stat-label",
+ "fontSize": "14px",
+ "marginTop": "4px",
+ "otext": "今日消费金额",
+ "i18n": true
+ }
+ }
+ ]
+ },
+ {
+ "widgettype": "VBox",
+ "options": {
+ "css": "stat-card",
+ "padding": "20px",
+ "borderRadius": "12px",
+ "flex": "1",
+ "minHeight": "110px"
+ },
+ "subwidgets": [
+ {
+ "widgettype": "HBox",
+ "options": {
+ "alignItems": "center",
+ "marginBottom": "12px"
+ },
+ "subwidgets": [
+ {
+ "widgettype": "Svg",
+ "options": {
+ "svg": "",
+ "width": "24px",
+ "height": "24px"
+ }
+ },
+ {
+ "widgettype": "Filler"
+ }
+ ]
+ },
+ {
+ "widgettype": "Text",
+ "options": {
+ "css": "stat-value",
+ "text": "{{get_customer_month_summary(request).cnt}}",
+ "fontSize": "32px",
+ "fontWeight": "700",
+ "lineHeight": "1.1"
+ }
+ },
+ {
+ "widgettype": "Text",
+ "options": {
+ "css": "stat-label",
+ "fontSize": "14px",
+ "marginTop": "4px",
+ "otext": "本月调用次数",
+ "i18n": true
+ }
+ }
+ ]
+ },
+ {
+ "widgettype": "VBox",
+ "options": {
+ "css": "stat-card",
+ "padding": "20px",
+ "borderRadius": "12px",
+ "flex": "1",
+ "minHeight": "110px"
+ },
+ "subwidgets": [
+ {
+ "widgettype": "HBox",
+ "options": {
+ "alignItems": "center",
+ "marginBottom": "12px"
+ },
+ "subwidgets": [
+ {
+ "widgettype": "Svg",
+ "options": {
+ "svg": "",
+ "width": "24px",
+ "height": "24px"
+ }
+ },
+ {
+ "widgettype": "Filler"
+ }
+ ]
+ },
+ {
+ "widgettype": "Text",
+ "options": {
+ "css": "stat-value",
+ "text": "¥{{get_customer_month_summary(request).total_amount|round(2)}}",
+ "fontSize": "32px",
+ "fontWeight": "700",
+ "lineHeight": "1.1"
+ }
+ },
+ {
+ "widgettype": "Text",
+ "options": {
+ "css": "stat-label",
+ "fontSize": "14px",
+ "marginTop": "4px",
+ "otext": "本月消费金额",
+ "i18n": true
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "widgettype": "VBox",
+ "options": {
+ "css": "card",
+ "width": "100%",
+ "borderRadius": "12px",
+ "padding": "20px",
+ "marginBottom": "20px"
+ },
+ "subwidgets": [
+ {
+ "widgettype": "HBox",
+ "options": {
+ "width": "100%",
+ "alignItems": "center",
+ "marginBottom": "16px"
+ },
+ "subwidgets": [
+ {
+ "widgettype": "Title4",
+ "options": {
+ "fontWeight": "600",
+ "otext": "本月每日调用趋势",
+ "i18n": true
+ }
+ },
+ {
+ "widgettype": "Filler"
+ },
+ {
+ "widgettype": "Button",
+ "options": {
+ "label": "刷新",
+ "border": "none",
+ "borderRadius": "6px",
+ "padding": "4px 12px",
+ "fontSize": "12px"
+ },
+ "binds": [
+ {
+ "wid": "self",
+ "event": "click",
+ "actiontype": "method",
+ "target": "-@ChartLine",
+ "method": "render_urldata",
+ "params": {}
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "widgettype": "urlwidget",
+ "options": {
+ "url": "{{entire_url('customer_daily_trend.ui')}}"
+ }
+ }
+ ]
+ },
+ {
+ "widgettype": "HBox",
+ "options": {
+ "width": "100%",
+ "gap": "20px",
+ "marginBottom": "20px"
+ },
+ "subwidgets": [
+ {
+ "widgettype": "VBox",
+ "options": {
+ "css": "card",
+ "width": "50%",
+ "borderRadius": "12px",
+ "padding": "20px"
+ },
+ "subwidgets": [
+ {
+ "widgettype": "HBox",
+ "options": {
+ "width": "100%",
+ "alignItems": "center",
+ "marginBottom": "16px"
+ },
+ "subwidgets": [
+ {
+ "widgettype": "Title4",
+ "options": {
+ "fontWeight": "600",
+ "otext": "今日各模型调用",
+ "i18n": true
+ }
+ },
+ {
+ "widgettype": "Filler"
+ },
+ {
+ "widgettype": "Button",
+ "options": {
+ "label": "刷新",
+ "border": "none",
+ "borderRadius": "6px",
+ "padding": "4px 12px",
+ "fontSize": "12px"
+ },
+ "binds": [
+ {
+ "wid": "self",
+ "event": "click",
+ "actiontype": "method",
+ "target": "-@ChartBar",
+ "method": "render_urldata",
+ "params": {}
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "widgettype": "urlwidget",
+ "options": {
+ "url": "{{entire_url('customer_daily_chart.ui')}}"
+ }
+ }
+ ]
+ },
+ {
+ "widgettype": "VBox",
+ "options": {
+ "css": "card",
+ "width": "50%",
+ "borderRadius": "12px",
+ "padding": "20px"
+ },
+ "subwidgets": [
+ {
+ "widgettype": "HBox",
+ "options": {
+ "width": "100%",
+ "alignItems": "center",
+ "marginBottom": "16px"
+ },
+ "subwidgets": [
+ {
+ "widgettype": "Title4",
+ "options": {
+ "fontWeight": "600",
+ "otext": "本月各模型调用",
+ "i18n": true
+ }
+ },
+ {
+ "widgettype": "Filler"
+ },
+ {
+ "widgettype": "Button",
+ "options": {
+ "label": "刷新",
+ "border": "none",
+ "borderRadius": "6px",
+ "padding": "4px 12px",
+ "fontSize": "12px"
+ },
+ "binds": [
+ {
+ "wid": "self",
+ "event": "click",
+ "actiontype": "method",
+ "target": "-@ChartBar",
+ "method": "render_urldata",
+ "params": {}
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "widgettype": "urlwidget",
+ "options": {
+ "url": "{{entire_url('customer_monthly_chart.ui')}}"
+ }
}
]
}
@@ -325,138 +459,10 @@
{
"widgettype": "urlwidget",
"options": {
- "url": "{{entire_url('customer_daily_trend.ui')}}"
+ "url": "{{entire_url('customer_users_table.ui')}}"
}
}
]
- },
- {
- "widgettype": "HBox",
- "options": {
- "width": "100%",
- "gap": "20px",
- "marginBottom": "20px"
- },
- "subwidgets": [
- {
- "widgettype": "VBox",
- "options": {
- "css": "card",
- "width": "50%",
- "borderRadius": "12px",
- "padding": "20px"
- },
- "subwidgets": [
- {
- "widgettype": "HBox",
- "options": {
- "width": "100%",
- "alignItems": "center",
- "marginBottom": "16px"
- },
- "subwidgets": [
- {
- "widgettype": "Title4",
- "options": {
- "fontWeight": "600",
- "otext": "今日各模型调用",
- "i18n": true
- }
- },
- {
- "widgettype": "Filler"
- },
- {
- "widgettype": "Button",
- "options": {
- "label": "刷新",
- "border": "none",
- "borderRadius": "6px",
- "padding": "4px 12px",
- "fontSize": "12px"
- },
- "binds": [
- {
- "wid": "self",
- "event": "click",
- "actiontype": "method",
- "target": "-@ChartBar",
- "method": "render_urldata",
- "params": {}
- }
- ]
- }
- ]
- },
- {
- "widgettype": "urlwidget",
- "options": {
- "url": "{{entire_url('customer_daily_chart.ui')}}"
- }
- }
- ]
- },
- {
- "widgettype": "VBox",
- "options": {
- "css": "card",
- "width": "50%",
- "borderRadius": "12px",
- "padding": "20px"
- },
- "subwidgets": [
- {
- "widgettype": "HBox",
- "options": {
- "width": "100%",
- "alignItems": "center",
- "marginBottom": "16px"
- },
- "subwidgets": [
- {
- "widgettype": "Title4",
- "options": {
- "fontWeight": "600",
- "otext": "本月各模型调用",
- "i18n": true
- }
- },
- {
- "widgettype": "Filler"
- },
- {
- "widgettype": "Button",
- "options": {
- "label": "刷新",
- "border": "none",
- "borderRadius": "6px",
- "padding": "4px 12px",
- "fontSize": "12px"
- },
- "binds": [
- {
- "wid": "self",
- "event": "click",
- "actiontype": "method",
- "target": "-@ChartBar",
- "method": "render_urldata",
- "params": {}
- }
- ]
- }
- ]
- },
- {
- "widgettype": "urlwidget",
- "options": {
- "url": "{{entire_url('customer_monthly_chart.ui')}}"
- }
- }
- ]
- }
- ]
- }
- ]
}
]
-}
+}
\ No newline at end of file
diff --git a/wwwroot/customer_users_table.ui b/wwwroot/customer_users_table.ui
new file mode 100644
index 0000000..47bda65
--- /dev/null
+++ b/wwwroot/customer_users_table.ui
@@ -0,0 +1,120 @@
+{
+ "widgettype": "VBox",
+ "options": {
+ "css": "card",
+ "width": "100%",
+ "borderRadius": "12px",
+ "padding": "20px",
+ "marginBottom": "20px"
+ },
+ "subwidgets": [
+ {
+ "widgettype": "HBox",
+ "options": {
+ "width": "100%",
+ "alignItems": "center",
+ "marginBottom": "16px"
+ },
+ "subwidgets": [
+ {
+ "widgettype": "Title4",
+ "options": {
+ "fontWeight": "600",
+ "otext": "按用户统计",
+ "i18n": true
+ }
+ },
+ {
+ "widgettype": "Filler"
+ }
+ ]
+ },
+ {
+ "widgettype": "HBox",
+ "options": {
+ "width": "100%",
+ "gap": "20px"
+ },
+ "subwidgets": [
+ {
+ "widgettype": "VBox",
+ "options": {
+ "width": "50%"
+ },
+ "subwidgets": [
+ {
+ "widgettype": "Text",
+ "options": {
+ "otext": "今日",
+ "i18n": true,
+ "fontSize": "14px",
+ "fontWeight": "600",
+ "marginBottom": "8px"
+ }
+ },
+ {
+ "widgettype": "Tabular",
+ "options": {
+ "data_url": "{{entire_url('api/customer_users_today.dspy')}}",
+ "data_method": "GET",
+ "width": "100%",
+ "height": "auto",
+ "row_options": {
+ "browserfields": {
+ "exclouded": [],
+ "cwidth": {}
+ },
+ "fields": [
+ {"name": "user_name", "title": "用户", "type": "str", "uitype": "str", "label": "用户", "cwidth": 20},
+ {"name": "call_cnt", "title": "调用次数", "type": "int", "uitype": "int", "label": "调用次数", "cwidth": 12},
+ {"name": "total_amount", "title": "金额", "type": "float", "uitype": "float", "label": "金额", "cwidth": 12}
+ ]
+ },
+ "page_rows": 50
+ }
+ }
+ ]
+ },
+ {
+ "widgettype": "VBox",
+ "options": {
+ "width": "50%"
+ },
+ "subwidgets": [
+ {
+ "widgettype": "Text",
+ "options": {
+ "otext": "本月",
+ "i18n": true,
+ "fontSize": "14px",
+ "fontWeight": "600",
+ "marginBottom": "8px"
+ }
+ },
+ {
+ "widgettype": "Tabular",
+ "options": {
+ "data_url": "{{entire_url('api/customer_users_month.dspy')}}",
+ "data_method": "GET",
+ "width": "100%",
+ "height": "auto",
+ "row_options": {
+ "browserfields": {
+ "exclouded": [],
+ "cwidth": {}
+ },
+ "fields": [
+ {"name": "user_name", "title": "用户", "type": "str", "uitype": "str", "label": "用户", "cwidth": 20},
+ {"name": "call_cnt", "title": "调用次数", "type": "int", "uitype": "int", "label": "调用次数", "cwidth": 12},
+ {"name": "total_amount", "title": "金额", "type": "float", "uitype": "float", "label": "金额", "cwidth": 12}
+ ]
+ },
+ "page_rows": 50
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}