Files
drl_2/xuexiao/routes/dashboard.py
user9994793890 ee860ce0ae Initial commit
2026-05-29 10:28:07 +08:00

115 lines
3.9 KiB
Python

"""仪表盘路由"""
from datetime import date, datetime
from flask import render_template
from sqlalchemy import func
from sqlalchemy.orm import joinedload
from models import (
db, Student, Course, Teacher, Class_, StudentAccount,
MonthlySnapshot, ConsumptionRecord,
)
from utils import login_required
from keshi_display import get_latest_period, snapshot_lessons_display
from keshi_stats import period_overview, monthly_trend_from_snapshots
import business_rules as rules
def register_routes(app):
@app.route('/', endpoint='dashboard')
@app.route('/dashboard', endpoint='dashboard')
@login_required
def dashboard():
today = date.today()
py, pm = get_latest_period()
period_label = f'{py}-{pm:02d}' if py and pm else ''
total_students = Student.query.filter_by(status=1).count()
total_courses = Course.query.filter_by(status=1).count()
total_teachers = Teacher.query.filter_by(status=1).count()
total_classes = Class_.query.filter_by(status=1).count()
month_recharge = 0.0
month_consumption = 0.0
if py and pm:
ov = period_overview(py, pm)
month_recharge = ov['recharge']
month_consumption = ov['consumed_hours']
today_consumption = ConsumptionRecord.query.filter(
ConsumptionRecord.consume_date == today,
).count()
recent_recharges = []
threshold = rules.LOW_HOURS_WARNING_THRESHOLD
low_hours_accounts = []
if py and pm:
snaps = (
MonthlySnapshot.query.options(
joinedload(MonthlySnapshot.account).joinedload(StudentAccount.student),
joinedload(MonthlySnapshot.account).joinedload(StudentAccount.course),
)
.filter(MonthlySnapshot.year == py, MonthlySnapshot.month == pm)
.all()
)
candidates = []
for s in snaps:
acc = s.account
if not acc or not acc.student:
continue
disp = snapshot_lessons_display(s, acc)
total_h = disp.get('end_total_lessons')
if total_h is None:
continue
th = float(total_h)
if 0 < th <= threshold:
candidates.append((acc, th, disp))
candidates.sort(key=lambda x: x[1])
low_hours_accounts = candidates[:8]
recent_consumptions = ConsumptionRecord.query.order_by(
ConsumptionRecord.consume_date.desc(),
).limit(8).all()
trend = monthly_trend_from_snapshots()
monthly_chart = []
max_amount = 1.0
for item in trend[-6:]:
amt = float(item['recharge'])
max_amount = max(max_amount, amt)
monthly_chart.append({
'label': item['label'],
'amount': amt,
'is_current': item['month'] == period_label,
})
if not monthly_chart:
max_amount = 1.0
hour = datetime.now().hour
if hour < 12:
greeting = '早上好'
elif hour < 18:
greeting = '下午好'
else:
greeting = '晚上好'
return render_template(
'dashboard.html',
greeting=greeting,
monthly_chart=monthly_chart,
chart_max=max_amount,
recent_consumptions=recent_consumptions,
total_students=total_students,
total_courses=total_courses,
total_teachers=total_teachers,
total_classes=total_classes,
month_recharge=float(month_recharge),
month_consumption=float(month_consumption),
today_consumption=today_consumption,
recent_recharges=recent_recharges,
low_hours_accounts=low_hours_accounts,
period_label=period_label,
)