from flask import Flask, redirect, url_for from flask_login import LoginManager, current_user # 添加 current_user 导入 from config.config import config from app.models import db, User, Student # 添加 Student 导入 import os import json # 添加 json 导入 from datetime import datetime, timedelta # 添加 datetime 和 timedelta 导入 def create_app(config_name=None): if config_name is None: config_name = os.environ.get('FLASK_ENV', 'default') app = Flask(__name__) app.config.from_object(config[config_name]) # 初始化扩展 db.init_app(app) # 初始化Flask-Login login_manager = LoginManager() login_manager.init_app(app) login_manager.login_view = 'auth.login' login_manager.login_message = '请先登录后访问此页面。' login_manager.login_message_category = 'info' @app.template_filter('fromjson') def from_json(value): try: return json.loads(value) except: return {} @app.template_filter('strptime') def strptime_filter(value, format_string): try: return datetime.strptime(value, format_string) except: return None @app.template_filter('calculate_duration') def calculate_duration(start_time, end_time, date_str): try: if not start_time or not end_time: return None start_datetime = datetime.strptime(f"{date_str} {start_time}", '%Y-%m-%d %H:%M:%S') end_datetime = datetime.strptime(f"{date_str} {end_time}", '%Y-%m-%d %H:%M:%S') # 如果结束时间小于开始时间,说明跨天了 if end_datetime < start_datetime: end_datetime += timedelta(days=1) duration = (end_datetime - start_datetime).total_seconds() / 3600 return round(duration, 1) except: return None @app.context_processor def utility_processor(): def get_current_student(): # 添加安全检查 if not current_user.is_authenticated: return None if current_user.is_admin(): return None return Student.query.filter_by(student_number=current_user.student_number).first() return dict(get_current_student=get_current_student) # 注册Python内置函数到Jinja2环境 app.jinja_env.globals.update( max=max, min=min, abs=abs, round=round, len=len, int=int, float=float, str=str, sum=sum, enumerate=enumerate, zip=zip ) @login_manager.user_loader def load_user(user_id): return User.query.get(int(user_id)) # 注册蓝图 from app.routes.auth import auth_bp from app.routes.student import student_bp from app.routes.admin import admin_bp app.register_blueprint(auth_bp, url_prefix='/auth') app.register_blueprint(student_bp, url_prefix='/student') app.register_blueprint(admin_bp, url_prefix='/admin') # 注册模板全局函数 from app.utils import get_pending_leaves_count app.jinja_env.globals.update( get_pending_leaves_count=get_pending_leaves_count, # 移除这行,因为我们已经通过 context_processor 注册了 # get_current_student=get_current_student ) # 主页路由 @app.route('/') def index(): if current_user.is_authenticated: if current_user.is_admin(): return redirect(url_for('admin.dashboard')) else: return redirect(url_for('student.dashboard')) return redirect(url_for('auth.login')) # 创建数据库表 with app.app_context(): db.create_all() return app