241 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			241 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
from flask import Flask, render_template, session, g, Markup, redirect, url_for
 | 
						|
from flask_login import LoginManager
 | 
						|
from app.models.database import db
 | 
						|
from app.models.user import User
 | 
						|
from app.controllers.user import user_bp
 | 
						|
from app.controllers.book import book_bp
 | 
						|
from app.controllers.borrow import borrow_bp
 | 
						|
from app.controllers.inventory import inventory_bp
 | 
						|
from flask_login import LoginManager, current_user
 | 
						|
from app.controllers.statistics import statistics_bp
 | 
						|
from app.controllers.announcement import announcement_bp
 | 
						|
from app.models.notification import Notification
 | 
						|
from app.controllers.log import log_bp
 | 
						|
import os
 | 
						|
from datetime import datetime
 | 
						|
login_manager = LoginManager()
 | 
						|
 | 
						|
 | 
						|
def create_app(config=None):
 | 
						|
    app = Flask(__name__)
 | 
						|
 | 
						|
    # 加载默认配置
 | 
						|
    app.config.from_object('config')
 | 
						|
 | 
						|
    # 如果提供了配置对象,则加载它
 | 
						|
    if config:
 | 
						|
        if isinstance(config, dict):
 | 
						|
            app.config.update(config)
 | 
						|
        else:
 | 
						|
            app.config.from_object(config)
 | 
						|
 | 
						|
    # 从环境变量指定的文件加载配置(如果有)
 | 
						|
    app.config.from_envvar('APP_CONFIG_FILE', silent=True)
 | 
						|
 | 
						|
    # 初始化数据库
 | 
						|
    db.init_app(app)
 | 
						|
 | 
						|
    # 初始化 Flask-Login
 | 
						|
    login_manager.init_app(app)
 | 
						|
    login_manager.login_view = 'user.login'
 | 
						|
 | 
						|
    @login_manager.user_loader
 | 
						|
    def load_user(user_id):
 | 
						|
        return User.query.get(int(user_id))
 | 
						|
 | 
						|
    # 注册蓝图
 | 
						|
    app.register_blueprint(user_bp, url_prefix='/user')
 | 
						|
    app.register_blueprint(book_bp, url_prefix='/book')
 | 
						|
    app.register_blueprint(borrow_bp, url_prefix='/borrow')
 | 
						|
    app.register_blueprint(statistics_bp)
 | 
						|
    app.register_blueprint(inventory_bp)
 | 
						|
    app.register_blueprint(log_bp)
 | 
						|
    app.register_blueprint(announcement_bp, url_prefix='/announcement')
 | 
						|
 | 
						|
    # 创建数据库表
 | 
						|
    with app.app_context():
 | 
						|
        # 先导入基础模型
 | 
						|
        from app.models.user import User, Role
 | 
						|
        from app.models.book import Book, Category
 | 
						|
 | 
						|
        # 创建表
 | 
						|
        db.create_all()
 | 
						|
 | 
						|
        # 再导入依赖模型 - 但不在这里定义关系
 | 
						|
        from app.models.borrow import BorrowRecord
 | 
						|
        from app.models.inventory import InventoryLog
 | 
						|
        from app.models.log import Log
 | 
						|
 | 
						|
        # 移除这些重复的关系定义
 | 
						|
        # Book.borrow_records = db.relationship('BorrowRecord', backref='book', lazy='dynamic')
 | 
						|
        # Book.inventory_logs = db.relationship('InventoryLog', backref='book', lazy='dynamic')
 | 
						|
        # Category.books = db.relationship('Book', backref='category', lazy='dynamic')
 | 
						|
 | 
						|
        # 创建默认角色
 | 
						|
        from app.models.user import Role
 | 
						|
        if not Role.query.filter_by(id=1).first():
 | 
						|
            admin_role = Role(id=1, role_name='管理员', description='系统管理员')
 | 
						|
            db.session.add(admin_role)
 | 
						|
 | 
						|
        if not Role.query.filter_by(id=2).first():
 | 
						|
            user_role = Role(id=2, role_name='普通用户', description='普通用户')
 | 
						|
            db.session.add(user_role)
 | 
						|
 | 
						|
        # 创建管理员账号
 | 
						|
        if not User.query.filter_by(username='admin').first():
 | 
						|
            admin = User(
 | 
						|
                username='admin',
 | 
						|
                password='admin123',
 | 
						|
                email='admin@example.com',
 | 
						|
                role_id=1,
 | 
						|
                nickname='系统管理员'
 | 
						|
            )
 | 
						|
            db.session.add(admin)
 | 
						|
 | 
						|
        # 创建基础分类
 | 
						|
        from app.models.book import Category
 | 
						|
        if not Category.query.first():
 | 
						|
            categories = [
 | 
						|
                Category(name='文学', sort=1),
 | 
						|
                Category(name='计算机', sort=2),
 | 
						|
                Category(name='历史', sort=3),
 | 
						|
                Category(name='科学', sort=4),
 | 
						|
                Category(name='艺术', sort=5),
 | 
						|
                Category(name='经济', sort=6),
 | 
						|
                Category(name='哲学', sort=7),
 | 
						|
                Category(name='教育', sort=8)
 | 
						|
            ]
 | 
						|
            db.session.add_all(categories)
 | 
						|
 | 
						|
        db.session.commit()
 | 
						|
 | 
						|
    # 其余代码保持不变...
 | 
						|
    @app.before_request
 | 
						|
    def load_logged_in_user():
 | 
						|
        user_id = session.get('user_id')
 | 
						|
 | 
						|
        if user_id is None:
 | 
						|
            g.user = None
 | 
						|
        else:
 | 
						|
            g.user = User.query.get(user_id)
 | 
						|
 | 
						|
    @app.route('/')
 | 
						|
    def index():
 | 
						|
        from app.models.book import Book
 | 
						|
        from app.models.user import User
 | 
						|
        from app.models.borrow import BorrowRecord
 | 
						|
        from app.models.announcement import Announcement
 | 
						|
        from app.models.notification import Notification
 | 
						|
        from sqlalchemy import func, desc
 | 
						|
        from flask_login import current_user
 | 
						|
 | 
						|
        # 获取统计数据
 | 
						|
        stats = {
 | 
						|
            'total_books': Book.query.count(),
 | 
						|
            'total_users': User.query.count(),
 | 
						|
            'active_borrows': BorrowRecord.query.filter(BorrowRecord.return_date.is_(None)).count(),
 | 
						|
            'user_borrows': 0
 | 
						|
        }
 | 
						|
 | 
						|
        # 如果用户已登录,获取其待还图书数量
 | 
						|
        if current_user.is_authenticated:
 | 
						|
            stats['user_borrows'] = BorrowRecord.query.filter(
 | 
						|
                BorrowRecord.user_id == current_user.id,
 | 
						|
                BorrowRecord.return_date.is_(None)
 | 
						|
            ).count()
 | 
						|
 | 
						|
        # 获取最新图书
 | 
						|
        latest_books = Book.query.filter_by(status=1).order_by(Book.created_at.desc()).limit(4).all()
 | 
						|
 | 
						|
        # 获取热门图书(根据借阅次数)
 | 
						|
        try:
 | 
						|
            # 这里假设你的数据库中有表记录借阅次数
 | 
						|
            popular_books_query = db.session.query(
 | 
						|
                Book, func.count(BorrowRecord.id).label('borrow_count')
 | 
						|
            ).join(
 | 
						|
                BorrowRecord, Book.id == BorrowRecord.book_id, isouter=True
 | 
						|
            ).filter(
 | 
						|
                Book.status == 1
 | 
						|
            ).group_by(
 | 
						|
                Book.id
 | 
						|
            ).order_by(
 | 
						|
                desc('borrow_count')
 | 
						|
            ).limit(5)
 | 
						|
 | 
						|
            # 提取图书对象并添加借阅计数
 | 
						|
            popular_books = []
 | 
						|
            for book, count in popular_books_query:
 | 
						|
                book.borrow_count = count
 | 
						|
                popular_books.append(book)
 | 
						|
        except Exception as e:
 | 
						|
            # 如果查询有问题,使用最新的书作为备选
 | 
						|
            popular_books = latest_books.copy() if latest_books else []
 | 
						|
            print(f"获取热门图书失败: {str(e)}")
 | 
						|
 | 
						|
        # 获取最新公告
 | 
						|
        announcements = Announcement.query.filter_by(status=1).order_by(
 | 
						|
            Announcement.is_top.desc(),
 | 
						|
            Announcement.created_at.desc()
 | 
						|
        ).limit(3).all()
 | 
						|
 | 
						|
        now = datetime.now()
 | 
						|
 | 
						|
        # 获取用户的未读通知
 | 
						|
        user_notifications = []
 | 
						|
        if current_user.is_authenticated:
 | 
						|
            user_notifications = Notification.query.filter_by(
 | 
						|
                user_id=current_user.id,
 | 
						|
                status=0
 | 
						|
            ).order_by(
 | 
						|
                Notification.created_at.desc()
 | 
						|
            ).limit(5).all()
 | 
						|
 | 
						|
        return render_template('index.html',
 | 
						|
                               stats=stats,
 | 
						|
                               latest_books=latest_books,
 | 
						|
                               popular_books=popular_books,
 | 
						|
                               announcements=announcements,
 | 
						|
                               user_notifications=user_notifications,
 | 
						|
                               now=now
 | 
						|
                               )
 | 
						|
 | 
						|
    @app.errorhandler(404)
 | 
						|
    def page_not_found(e):
 | 
						|
        return render_template('404.html'), 404
 | 
						|
 | 
						|
    @app.template_filter('nl2br')
 | 
						|
    def nl2br_filter(s):
 | 
						|
        if s:
 | 
						|
            return Markup(s.replace('\n', '<br>'))
 | 
						|
        return s
 | 
						|
 | 
						|
    @app.context_processor
 | 
						|
    def utility_processor():
 | 
						|
        def get_unread_notifications_count(user_id):
 | 
						|
            if user_id:
 | 
						|
                return Notification.get_unread_count(user_id)
 | 
						|
            return 0
 | 
						|
 | 
						|
        def get_recent_notifications(user_id, limit=5):
 | 
						|
            if user_id:
 | 
						|
                # 按时间倒序获取最近的几条通知
 | 
						|
                notifications = Notification.query.filter_by(user_id=user_id) \
 | 
						|
                    .order_by(Notification.created_at.desc()) \
 | 
						|
                    .limit(limit) \
 | 
						|
                    .all()
 | 
						|
                return notifications
 | 
						|
            return []
 | 
						|
 | 
						|
        return dict(
 | 
						|
            get_unread_notifications_count=get_unread_notifications_count,
 | 
						|
            get_recent_notifications=get_recent_notifications
 | 
						|
        )
 | 
						|
 | 
						|
    return app
 | 
						|
 | 
						|
    @app.context_processor
 | 
						|
    def inject_now():
 | 
						|
        return {'now': datetime.datetime.now()}
 | 
						|
 | 
						|
 |