Files
drl_2/xuexiao/app.py
user9994793890 3468394c6c feat: 实现单价分离、班级转课、消课筛选和手动录入功能
Coze-Commit-Type: user
Coze-User-ID: 3722323274763196
Coze-Conversation-ID: 5260473
2026-05-29 10:40:41 +08:00

164 lines
5.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""学生课程管理系统 - Flask主应用入口"""
import os
from flask import Flask
from config import Config, write_engine
from models import db
def create_app():
"""应用工厂函数"""
app = Flask(__name__)
app.config.from_object(Config)
app.config['TEMPLATES_AUTO_RELOAD'] = True
# 初始化数据库
db.init_app(app)
# 仅当存在有效的 write_engine非 None时才复用
if write_engine is not None:
if app in db._app_engines:
old_engine = db._app_engines[app].get(None)
if old_engine is not None and old_engine is not write_engine:
old_engine.dispose()
db._app_engines[app][None] = write_engine
# 注入模板上下文变量
@app.context_processor
def inject_globals():
from flask import session
from datetime import date
from models import User, ConsumptionRecord, Student
from sqlalchemy import func
user_id = session.get('user_id')
user = db.session.get(User, user_id) if user_id else None
panel_progress = 0
if user:
month_start = date.today().replace(day=1)
month_h = db.session.query(
func.coalesce(func.sum(ConsumptionRecord.hours_consumed), 0)
).filter(ConsumptionRecord.consume_date >= month_start).scalar() or 0
students = Student.query.filter_by(status=1).count() or 1
target = max(students * 4, 20)
panel_progress = min(100, int(float(month_h) / target * 100))
return {'current_user': user, 'panel_progress': panel_progress}
# 注册路由直接注册到app不使用蓝图
with app.app_context():
from routes import register_all_routes
register_all_routes(app)
# 建表 + 自动迁移Doris / MySQL / SQLite
from db_bootstrap import bootstrap_database
bootstrap_database()
_init_default_data()
_sync_account_original_prices()
return app
def _sync_account_original_prices():
"""未录原价时:课程表单价 → 最新月度快照单价"""
from models import db, StudentAccount, Course, MonthlySnapshot
from sqlalchemy import func
try:
accounts = StudentAccount.query.filter(
db.or_(
StudentAccount.original_price_per_lesson.is_(None),
StudentAccount.original_price_per_lesson == 0,
)
).all()
n = 0
for acc in accounts:
if acc.original_price_per_lesson and float(acc.original_price_per_lesson or 0) > 0:
continue
crs = db.session.get(Course, acc.course_id)
if crs and float(crs.price_per_hour or 0) > 0:
acc.original_price_per_lesson = crs.price_per_hour
n += 1
continue
row = (
db.session.query(MonthlySnapshot.unit_price)
.filter(
MonthlySnapshot.account_id == acc.id,
MonthlySnapshot.unit_price > 0,
)
.order_by(
MonthlySnapshot.year.desc(),
MonthlySnapshot.month.desc(),
)
.first()
)
if row and float(row[0] or 0) > 0:
acc.original_price_per_lesson = row[0]
n += 1
if n:
db.session.commit()
except Exception:
db.session.rollback()
def _init_default_data():
"""初始化默认数据: 确保admin用户和管理员角色存在"""
from models import User, Role
from utils import PERMISSIONS
# §八 默认角色层级
default_roles = [
('超级管理员', 'all', '全部权限'),
('校区管理员', ','.join(PERMISSIONS.keys()), '本校区全部业务'),
(
'财务',
'recharge_view,recharge_add,recharge_export,recharge_activity_view,'
'recharge_activity_add,recharge_activity_edit,refund_view,refund_add,'
'refund_export,statistics_view,statistics_export,log_view',
'充值退费与报表',
),
(
'授课老师',
'student_view,course_view,class_view,class_add,attendance_view,'
'attendance_add,consumption_view,consumption_add,schedule_view',
'消课考勤与班级',
),
]
for name, perms, remark in default_roles:
if not Role.query.filter_by(name=name).first():
db.session.add(Role(name=name, permissions=perms, remark=remark))
db.session.commit()
# 校区管理员:补齐后续新增的权限项(如课时核对表)
campus = Role.query.filter_by(name='校区管理员').first()
if campus and campus.permissions != 'all':
all_keys = sorted(PERMISSIONS.keys())
campus.permissions = ','.join(all_keys)
db.session.commit()
admin_role = Role.query.filter_by(name='超级管理员').first()
if not admin_role:
admin_role = Role(name='超级管理员', permissions='all', remark='系统默认管理员角色')
db.session.add(admin_role)
db.session.commit()
admin_role = Role.query.filter_by(name='超级管理员').first()
# 确保admin用户存在且密码正确
admin = User.query.filter_by(username='admin').first()
default_password = 'admin123'
if not admin:
admin = User(
username='admin', real_name='系统管理员',
role_id=admin_role.id, status=1, remark='默认管理员'
)
admin.set_password(default_password)
db.session.add(admin)
db.session.commit()
elif not admin.check_password(default_password):
admin.set_password(default_password)
db.session.commit()
app = create_app()
if __name__ == '__main__':
port = int(os.environ.get('DEPLOY_RUN_PORT', 5000))
app.run(host='0.0.0.0', port=port, debug=True, use_reloader=True)