164 lines
5.9 KiB
Python
164 lines
5.9 KiB
Python
"""学生课程管理系统 - 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)
|