1、修改后台数据概览页面
2、增加对应是时间范围修改
This commit is contained in:
@@ -247,7 +247,10 @@ async def list_credit_records(
|
||||
page: int = Query(1, ge=1),
|
||||
page_size: int = Query(20, ge=1, le=100),
|
||||
user_id: str | None = Query(None),
|
||||
user_name: str | None = Query(None),
|
||||
type: str | None = Query(None),
|
||||
start_date: str = Query(None),
|
||||
end_date: str = Query(None),
|
||||
admin: User = Depends(get_admin_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
@@ -261,9 +264,25 @@ async def list_credit_records(
|
||||
if user_id:
|
||||
query = query.where(CreditRecord.user_id == user_id)
|
||||
count_query = count_query.where(CreditRecord.user_id == user_id)
|
||||
if user_name:
|
||||
query = query.where(User.username.like(f'%{user_name}%'))
|
||||
count_query = count_query.join(User, CreditRecord.user_id == User.id).where(User.username.like(f'%{user_name}%'))
|
||||
if type:
|
||||
query = query.where(CreditRecord.type == type)
|
||||
count_query = count_query.where(CreditRecord.type == type)
|
||||
|
||||
try:
|
||||
if start_date:
|
||||
date_start = datetime.strptime(start_date, "%Y-%m-%d")
|
||||
query = query.where(CreditRecord.created_at >= date_start)
|
||||
count_query = count_query.where(CreditRecord.created_at >= date_start)
|
||||
if end_date:
|
||||
date_end = datetime.strptime(end_date, "%Y-%m-%d")
|
||||
date_end = date_end.replace(hour=23, minute=59, second=59, microsecond=999999)
|
||||
query = query.where(CreditRecord.created_at <= date_end)
|
||||
count_query = count_query.where(CreditRecord.created_at <= date_end)
|
||||
except:
|
||||
pass
|
||||
|
||||
total = (await db.execute(count_query)).scalar() or 0
|
||||
result = await db.execute(query.offset((page - 1) * page_size).limit(page_size))
|
||||
@@ -1124,40 +1143,95 @@ async def list_operation_logs(
|
||||
async def get_stats(
|
||||
admin: User = Depends(get_admin_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
start_date: str = Query(None),
|
||||
end_date: str = Query(None),
|
||||
):
|
||||
total_users = (await db.execute(
|
||||
select(func.count(User.id)).where(User.user_type == "frontend")
|
||||
)).scalar() or 0
|
||||
total_projects = (await db.execute(select(func.count(Project.id)).where(Project.deleted_at.is_(None)))).scalar() or 0
|
||||
total_generations = (
|
||||
await db.execute(select(func.count(GenerationRecord.id)).where(GenerationRecord.deleted_at.is_(None)))
|
||||
).scalar() or 0
|
||||
total_revenue = (
|
||||
await db.execute(
|
||||
select(func.coalesce(func.sum(PaymentOrder.amount), 0)).where(
|
||||
PaymentOrder.status == "paid"
|
||||
)
|
||||
)
|
||||
).scalar() or 0
|
||||
|
||||
today_start = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
|
||||
try:
|
||||
if start_date:
|
||||
date_start = datetime.strptime(start_date, "%Y-%m-%d")
|
||||
else:
|
||||
date_start = today_start
|
||||
if end_date:
|
||||
date_end = datetime.strptime(end_date, "%Y-%m-%d")
|
||||
date_end = date_end.replace(hour=23, minute=59, second=59, microsecond=999999)
|
||||
else:
|
||||
date_end = datetime.now()
|
||||
except:
|
||||
date_start = today_start
|
||||
date_end = datetime.now()
|
||||
|
||||
today_start = datetime.now().replace(
|
||||
hour=0, minute=0, second=0, microsecond=0
|
||||
)
|
||||
credits_today = (
|
||||
await db.execute(
|
||||
select(func.coalesce(func.sum(func.abs(CreditRecord.amount)), 0)).where(
|
||||
CreditRecord.type == "consume",
|
||||
CreditRecord.created_at >= today_start,
|
||||
)
|
||||
total_projects = (await db.execute(
|
||||
select(func.count(Project.id)).where(
|
||||
Project.deleted_at.is_(None),
|
||||
Project.created_at >= date_start,
|
||||
Project.created_at <= date_end,
|
||||
)
|
||||
).scalar() or 0
|
||||
)).scalar() or 0
|
||||
|
||||
total_generations = (await db.execute(
|
||||
select(func.count(GenerationAITask.id)).where(
|
||||
GenerationAITask.created_at >= date_start,
|
||||
GenerationAITask.created_at <= date_end,
|
||||
)
|
||||
)).scalar() or 0
|
||||
|
||||
total_records = (await db.execute(
|
||||
select(func.count(GenerationRecord.id)).where(
|
||||
GenerationRecord.deleted_at.is_(None),
|
||||
GenerationRecord.created_at >= date_start,
|
||||
GenerationRecord.created_at <= date_end,
|
||||
)
|
||||
)).scalar() or 0
|
||||
|
||||
total_revenue = (await db.execute(
|
||||
select(func.coalesce(func.sum(PaymentOrder.amount), 0)).where(
|
||||
PaymentOrder.status == "paid",
|
||||
PaymentOrder.created_at >= date_start,
|
||||
PaymentOrder.created_at <= date_end,
|
||||
)
|
||||
)).scalar() or 0
|
||||
|
||||
credits_consumed = (await db.execute(
|
||||
select(func.coalesce(func.sum(func.abs(CreditRecord.amount)), 0)).where(
|
||||
CreditRecord.type == "consume",
|
||||
CreditRecord.created_at >= date_start,
|
||||
CreditRecord.created_at <= date_end,
|
||||
)
|
||||
)).scalar() or 0
|
||||
|
||||
alipay_revenue = (await db.execute(
|
||||
select(func.coalesce(func.sum(PaymentOrder.amount), 0)).where(
|
||||
PaymentOrder.status == "paid",
|
||||
PaymentOrder.payment_method == "alipay",
|
||||
PaymentOrder.created_at >= date_start,
|
||||
PaymentOrder.created_at <= date_end,
|
||||
)
|
||||
)).scalar() or 0
|
||||
|
||||
wechat_revenue = (await db.execute(
|
||||
select(func.coalesce(func.sum(PaymentOrder.amount), 0)).where(
|
||||
PaymentOrder.status == "paid",
|
||||
PaymentOrder.payment_method == "wechat",
|
||||
PaymentOrder.created_at >= date_start,
|
||||
PaymentOrder.created_at <= date_end,
|
||||
)
|
||||
)).scalar() or 0
|
||||
|
||||
return AdminStatsOut(
|
||||
total_users=total_users,
|
||||
total_projects=total_projects,
|
||||
total_generations=total_generations,
|
||||
total_records=total_records,
|
||||
total_revenue=float(total_revenue),
|
||||
credits_consumed_today=float(credits_today),
|
||||
credits_consumed_today=float(credits_consumed),
|
||||
today_alipay_revenue=float(alipay_revenue),
|
||||
today_wechat_revenue=float(wechat_revenue),
|
||||
)
|
||||
|
||||
|
||||
|
||||
+70
-28
@@ -322,13 +322,54 @@ async def _seed_data():
|
||||
# Seed menu configs
|
||||
from app.models.menu_config import MenuConfig
|
||||
|
||||
default_menus = [
|
||||
("/projects", "我的项目", "HomeOutlined", 0, "frontend"),
|
||||
("/conversation", "AI创作", "StarOutlined", 1, "frontend"),
|
||||
("/records", "项目记录", "PlayCircleOutlined", 2, "frontend"),
|
||||
("/generated", "素材云", "StarOutlined", 3, "frontend"),
|
||||
frontend_groups = [
|
||||
("AI项目行业生成", "HomeOutlined", 0),
|
||||
("AI对话生成", "HomeOutlined", 1),
|
||||
("AI视频创作", "HomeOutlined", 2),
|
||||
("资产管理", "HomeOutlined", 3),
|
||||
("媒体关联", "HomeOutlined", 4),
|
||||
]
|
||||
for path, label, icon, order, target in default_menus:
|
||||
frontend_group_ids: dict[str, str] = {}
|
||||
for label, icon, order in frontend_groups:
|
||||
existing = await db.execute(
|
||||
select(MenuConfig).where(
|
||||
MenuConfig.label == label,
|
||||
MenuConfig.menu_type == "group",
|
||||
MenuConfig.menu_target == "frontend",
|
||||
).limit(1)
|
||||
)
|
||||
group = existing.scalar_one_or_none()
|
||||
if group:
|
||||
frontend_group_ids[label] = group.id
|
||||
else:
|
||||
gid = generate_id()
|
||||
frontend_group_ids[label] = gid
|
||||
db.add(
|
||||
MenuConfig(
|
||||
id=gid,
|
||||
path="",
|
||||
label=label,
|
||||
icon=icon,
|
||||
sort_order=order,
|
||||
is_active=True,
|
||||
parent_id=None,
|
||||
menu_type="group",
|
||||
menu_target="frontend",
|
||||
is_default=True,
|
||||
)
|
||||
)
|
||||
|
||||
frontend_pages = [
|
||||
("/projects", "我的项目", "HomeOutlined", 0, "AI项目行业生成", True),
|
||||
("/conversation", "AI创作", "StarOutlined", 0, "AI对话生成", True),
|
||||
("/initial", "爆款开头复刻", "CodeOutlined", 0, "AI视频创作", False),
|
||||
("/removelens", "拆镜复刻", "CameraOutlined", 1, "AI视频创作", False),
|
||||
("/records", "项目记录", "PlayCircleOutlined", 0, "资产管理", True),
|
||||
("/generated", "素材云", "CloudOutlined", 1, "资产管理", True),
|
||||
("/authorization", "授权管理", "UserOutlined", 0, "媒体关联", False),
|
||||
("/consume", "消耗列表", "FileTextOutlined", 1, "媒体关联", False),
|
||||
]
|
||||
for path, label, icon, order, group_label, is_default in frontend_pages:
|
||||
existing = await db.execute(
|
||||
select(MenuConfig).where(MenuConfig.path == path).limit(1)
|
||||
)
|
||||
@@ -341,30 +382,33 @@ async def _seed_data():
|
||||
icon=icon,
|
||||
sort_order=order,
|
||||
is_active=True,
|
||||
parent_id=frontend_group_ids.get(group_label),
|
||||
menu_type="page",
|
||||
menu_target=target,
|
||||
is_default=True,
|
||||
menu_target="frontend",
|
||||
is_default=is_default,
|
||||
)
|
||||
)
|
||||
|
||||
# Seed admin group menus first, then page menus with parent_id
|
||||
admin_groups = [
|
||||
("模型设置", "RobotOutlined", 98),
|
||||
("模型配置", "RobotOutlined", 6),
|
||||
("系统设置", "SettingOutlined", 99),
|
||||
]
|
||||
group_ids = {}
|
||||
admin_group_ids: dict[str, str] = {}
|
||||
for label, icon, order in admin_groups:
|
||||
existing = await db.execute(
|
||||
select(MenuConfig).where(
|
||||
MenuConfig.label == label,
|
||||
MenuConfig.menu_type == "group",
|
||||
MenuConfig.menu_target == "admin",
|
||||
)
|
||||
.limit(1)
|
||||
).limit(1)
|
||||
)
|
||||
group = existing.scalar_one_or_none()
|
||||
if not group:
|
||||
if group:
|
||||
admin_group_ids[label] = group.id
|
||||
else:
|
||||
gid = generate_id()
|
||||
admin_group_ids[label] = gid
|
||||
db.add(
|
||||
MenuConfig(
|
||||
id=gid,
|
||||
@@ -377,35 +421,33 @@ async def _seed_data():
|
||||
menu_target="admin",
|
||||
)
|
||||
)
|
||||
group_ids[label] = gid
|
||||
else:
|
||||
group_ids[label] = group.id
|
||||
|
||||
# (path, label, icon, sort_order, parent_group_label or None)
|
||||
admin_menus = [
|
||||
admin_pages = [
|
||||
("/", "数据概览", "DashboardOutlined", 0, None),
|
||||
("/users", "用户管理", "UserOutlined", 1, None),
|
||||
("/credit-records", "交易流水", "WalletOutlined", 2, None),
|
||||
("/generation-records", "生成记录", "VideoCameraOutlined", 3, None),
|
||||
("/generation-ai", "创作记录", "BulbOutlined", 3, None),
|
||||
("/generation-records", "项目记录", "VideoCameraOutlined", 3, None),
|
||||
("/recharge-packages", "充值套餐", "GiftOutlined", 4, None),
|
||||
("/notifications", "消息推送", "BellOutlined", 5, None),
|
||||
("/video-engines", "视频引擎", "PlayCircleOutlined", 0, "模型配置"),
|
||||
("/models", "模型配置", "RobotOutlined", 1, "模型配置"),
|
||||
("/image-engines", "图片模型", "PictureOutlined", 2, "模型配置"),
|
||||
("/credit-ratios", "积分比例", "CalculatorOutlined", 3, "模型配置"),
|
||||
("/payment-stats", "支付统计", "LineChartOutlined", 6, None),
|
||||
("/video-engines", "视频引擎", "PlayCircleOutlined", 0, "模型设置"),
|
||||
("/models", "模型配置", "RobotOutlined", 1, "模型设置"),
|
||||
("/image-engines", "图片模型", "PictureOutlined", 2, "模型设置"),
|
||||
("/credit-ratios", "积分比例", "CalculatorOutlined", 3, "模型设置"),
|
||||
("/payment", "支付配置", "DollarOutlined", 1, "系统设置"),
|
||||
("/industries", "行业配置", "AppstoreOutlined", 2, "系统设置"),
|
||||
("/menu-configs", "菜单配置", "SettingOutlined", 3, "系统设置"),
|
||||
("/settings", "系统设置", "SettingOutlined", 4, "系统设置"),
|
||||
("/operation-logs", "操作日志", "HistoryOutlined", 5, "系统设置"),
|
||||
("/operation-logs", "操作日志", "DatabaseOutlined", 5, "系统设置"),
|
||||
("/oauthapp-list", "授权应用", "MenuOutlined", 28, "系统设置"),
|
||||
]
|
||||
for path, label, icon, order, parent_group in admin_menus:
|
||||
for path, label, icon, order, parent_group in admin_pages:
|
||||
existing = await db.execute(
|
||||
select(MenuConfig).where(
|
||||
MenuConfig.path == path,
|
||||
MenuConfig.menu_target == "admin",
|
||||
)
|
||||
.limit(1)
|
||||
).limit(1)
|
||||
)
|
||||
if not existing.scalar_one_or_none():
|
||||
db.add(
|
||||
@@ -418,7 +460,7 @@ async def _seed_data():
|
||||
is_active=True,
|
||||
menu_type="page",
|
||||
menu_target="admin",
|
||||
parent_id=group_ids.get(parent_group),
|
||||
parent_id=admin_group_ids.get(parent_group),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -93,5 +93,8 @@ class AdminStatsOut(BaseModel):
|
||||
total_users: int
|
||||
total_projects: int
|
||||
total_generations: int
|
||||
total_records: int
|
||||
total_revenue: float
|
||||
credits_consumed_today: float
|
||||
today_alipay_revenue: float
|
||||
today_wechat_revenue: float
|
||||
|
||||
Reference in New Issue
Block a user