fix_bug_login_and_user
This commit is contained in:
		
							parent
							
								
									4f06468ec9
								
							
						
					
					
						commit
						5f46d87528
					
				@ -1,4 +1,4 @@
 | 
			
		||||
from flask import Flask, render_template, session, g, Markup
 | 
			
		||||
from flask import Flask, render_template, session, g, Markup, redirect, url_for
 | 
			
		||||
from flask_login import LoginManager
 | 
			
		||||
from app.models.user import db, User
 | 
			
		||||
from app.controllers.user import user_bp
 | 
			
		||||
@ -118,7 +118,7 @@ def create_app(config=None):
 | 
			
		||||
    @app.route('/')
 | 
			
		||||
    def index():
 | 
			
		||||
        if not current_user.is_authenticated:
 | 
			
		||||
            return render_template('login.html')
 | 
			
		||||
            return redirect(url_for('user.login'))
 | 
			
		||||
        return render_template('index.html')  # 无需传递current_user,Flask-Login自动提供
 | 
			
		||||
 | 
			
		||||
    @app.errorhandler(404)
 | 
			
		||||
 | 
			
		||||
@ -2,6 +2,7 @@ from flask import Blueprint, render_template, request, redirect, url_for, flash,
 | 
			
		||||
from app.models.book import Book, Category
 | 
			
		||||
from app.models.user import db
 | 
			
		||||
from app.utils.auth import login_required, admin_required
 | 
			
		||||
from flask_login import current_user, login_required
 | 
			
		||||
import os
 | 
			
		||||
from werkzeug.utils import secure_filename
 | 
			
		||||
import datetime
 | 
			
		||||
@ -14,6 +15,7 @@ book_bp = Blueprint('book', __name__)
 | 
			
		||||
@login_required
 | 
			
		||||
@admin_required
 | 
			
		||||
def admin_book_list():
 | 
			
		||||
    print(f"DEBUG: admin_book_list 函数被调用,用户={current_user.username},认证状态={current_user.is_authenticated}")
 | 
			
		||||
    page = request.args.get('page', 1, type=int)
 | 
			
		||||
    per_page = request.args.get('per_page', 10, type=int)
 | 
			
		||||
    # 只显示状态为1的图书(未下架的图书)
 | 
			
		||||
@ -128,7 +130,6 @@ def book_detail(book_id):
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# 添加图书页面
 | 
			
		||||
# 添加图书页面
 | 
			
		||||
@book_bp.route('/add', methods=['GET', 'POST'])
 | 
			
		||||
@login_required
 | 
			
		||||
@ -193,7 +194,7 @@ def add_book():
 | 
			
		||||
                        ext = '.jpg'  # 默认扩展名
 | 
			
		||||
 | 
			
		||||
                    filename = f"{uuid.uuid4()}{ext}"
 | 
			
		||||
                    upload_folder = os.path.join(current_app.static_folder, 'uploads', 'covers')
 | 
			
		||||
                    upload_folder = os.path.join(current_app.static_folder,  'covers')
 | 
			
		||||
 | 
			
		||||
                    # 确保上传目录存在
 | 
			
		||||
                    if not os.path.exists(upload_folder):
 | 
			
		||||
@ -201,7 +202,7 @@ def add_book():
 | 
			
		||||
 | 
			
		||||
                    file_path = os.path.join(upload_folder, filename)
 | 
			
		||||
                    cover_file.save(file_path)
 | 
			
		||||
                    cover_url = f'/static/uploads/covers/{filename}'
 | 
			
		||||
                    cover_url = f'/static/covers/{filename}'
 | 
			
		||||
                except Exception as e:
 | 
			
		||||
                    current_app.logger.error(f"封面上传失败: {str(e)}")
 | 
			
		||||
                    flash(f"封面上传失败: {str(e)}", 'warning')
 | 
			
		||||
@ -322,7 +323,7 @@ def edit_book(book_id):
 | 
			
		||||
            cover_file = request.files['cover']
 | 
			
		||||
            if cover_file and cover_file.filename != '':
 | 
			
		||||
                filename = secure_filename(f"{uuid.uuid4()}_{cover_file.filename}")
 | 
			
		||||
                upload_folder = os.path.join(current_app.static_folder, 'uploads/covers')
 | 
			
		||||
                upload_folder = os.path.join(current_app.static_folder, 'covers')
 | 
			
		||||
 | 
			
		||||
                # 确保上传目录存在
 | 
			
		||||
                if not os.path.exists(upload_folder):
 | 
			
		||||
@ -606,3 +607,18 @@ def export_books():
 | 
			
		||||
 | 
			
		||||
    # 提供下载链接
 | 
			
		||||
    return redirect(url_for('static', filename=f'temp/{filename}'))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@book_bp.route('/test-permissions')
 | 
			
		||||
def test_permissions():
 | 
			
		||||
    """测试当前用户权限"""
 | 
			
		||||
    if not current_user.is_authenticated:
 | 
			
		||||
        return "未登录"
 | 
			
		||||
 | 
			
		||||
    return f"""
 | 
			
		||||
    <h1>用户权限信息</h1>
 | 
			
		||||
    <p>用户名: {current_user.username}</p>
 | 
			
		||||
    <p>角色ID: {current_user.role_id}</p>
 | 
			
		||||
    <p>是否管理员: {'是' if current_user.role_id == 1 else '否'}</p>
 | 
			
		||||
    <p><a href="/book/admin/list">尝试访问管理页面</a></p>
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,5 @@
 | 
			
		||||
from flask import Blueprint, request, redirect, url_for, flash, g
 | 
			
		||||
from flask import Blueprint, request, redirect, url_for, flash, g, jsonify
 | 
			
		||||
from flask_login import current_user, login_required
 | 
			
		||||
from app.models.book import Book
 | 
			
		||||
from app.models.borrow import BorrowRecord
 | 
			
		||||
from app.models.inventory import InventoryLog
 | 
			
		||||
@ -80,3 +81,80 @@ def borrow_book():
 | 
			
		||||
        flash(f'借阅失败: {str(e)}', 'danger')
 | 
			
		||||
 | 
			
		||||
    return redirect(url_for('book.book_detail', book_id=book_id))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@borrow_bp.route('/add/<int:book_id>', methods=['POST'])
 | 
			
		||||
@login_required
 | 
			
		||||
def add_borrow(book_id):
 | 
			
		||||
    # 验证图书存在
 | 
			
		||||
    book = Book.query.get_or_404(book_id)
 | 
			
		||||
 | 
			
		||||
    # 默认借阅天数
 | 
			
		||||
    borrow_days = 14
 | 
			
		||||
 | 
			
		||||
    # 检查库存
 | 
			
		||||
    if book.stock <= 0:
 | 
			
		||||
        return jsonify({
 | 
			
		||||
            'success': False,
 | 
			
		||||
            'message': f'《{book.title}》当前无库存,无法借阅'
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
    # 检查是否已借阅
 | 
			
		||||
    existing_borrow = BorrowRecord.query.filter_by(
 | 
			
		||||
        user_id=current_user.id,  # 使用current_user
 | 
			
		||||
        book_id=book_id,
 | 
			
		||||
        status=1  # 1表示借阅中
 | 
			
		||||
    ).first()
 | 
			
		||||
 | 
			
		||||
    if existing_borrow:
 | 
			
		||||
        return jsonify({
 | 
			
		||||
            'success': False,
 | 
			
		||||
            'message': f'您已借阅《{book.title}》,请勿重复借阅'
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
    try:
 | 
			
		||||
        # 创建借阅记录
 | 
			
		||||
        now = datetime.datetime.now()
 | 
			
		||||
        due_date = now + datetime.timedelta(days=borrow_days)
 | 
			
		||||
 | 
			
		||||
        borrow_record = BorrowRecord(
 | 
			
		||||
            user_id=current_user.id,  # 使用current_user
 | 
			
		||||
            book_id=book_id,
 | 
			
		||||
            borrow_date=now,
 | 
			
		||||
            due_date=due_date,
 | 
			
		||||
            status=1,  # 1表示借阅中
 | 
			
		||||
            created_at=now,
 | 
			
		||||
            updated_at=now
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        # 更新图书库存
 | 
			
		||||
        book.stock -= 1
 | 
			
		||||
        book.updated_at = now
 | 
			
		||||
 | 
			
		||||
        db.session.add(borrow_record)
 | 
			
		||||
        db.session.commit()
 | 
			
		||||
 | 
			
		||||
        # 添加库存变更日志
 | 
			
		||||
        inventory_log = InventoryLog(
 | 
			
		||||
            book_id=book_id,
 | 
			
		||||
            change_type='借出',
 | 
			
		||||
            change_amount=-1,
 | 
			
		||||
            after_stock=book.stock,
 | 
			
		||||
            operator_id=current_user.id,  # 使用current_user
 | 
			
		||||
            remark='用户借书',
 | 
			
		||||
            changed_at=now
 | 
			
		||||
        )
 | 
			
		||||
        db.session.add(inventory_log)
 | 
			
		||||
        db.session.commit()
 | 
			
		||||
 | 
			
		||||
        return jsonify({
 | 
			
		||||
            'success': True,
 | 
			
		||||
            'message': f'成功借阅《{book.title}》,请在 {due_date.strftime("%Y-%m-%d")} 前归还'
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
    except Exception as e:
 | 
			
		||||
        db.session.rollback()
 | 
			
		||||
        return jsonify({
 | 
			
		||||
            'success': False,
 | 
			
		||||
            'message': f'借阅失败: {str(e)}'
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
@ -53,9 +53,19 @@ verification_codes = VerificationStore()
 | 
			
		||||
def admin_required(f):
 | 
			
		||||
    @wraps(f)
 | 
			
		||||
    def decorated_function(*args, **kwargs):
 | 
			
		||||
        if not current_user.is_authenticated or current_user.role_id != 1:
 | 
			
		||||
            flash('您没有管理员权限', 'error')
 | 
			
		||||
        print(
 | 
			
		||||
            f"DEBUG: admin_required检查,用户认证={current_user.is_authenticated},角色ID={current_user.role_id if current_user.is_authenticated else 'None'}")
 | 
			
		||||
 | 
			
		||||
        if not current_user.is_authenticated:
 | 
			
		||||
            print("DEBUG: 用户未登录,重定向到登录页面")
 | 
			
		||||
            return redirect(url_for('user.login', next=request.url))
 | 
			
		||||
 | 
			
		||||
        if current_user.role_id != 1:
 | 
			
		||||
            print(f"DEBUG: 用户{current_user.username}不是管理员,角色ID={current_user.role_id}")
 | 
			
		||||
            flash('您没有管理员权限访问此页面', 'error')
 | 
			
		||||
            return redirect(url_for('index'))
 | 
			
		||||
 | 
			
		||||
        print(f"DEBUG: 用户{current_user.username}是管理员,允许访问")
 | 
			
		||||
        return f(*args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    return decorated_function
 | 
			
		||||
@ -63,8 +73,21 @@ def admin_required(f):
 | 
			
		||||
 | 
			
		||||
@user_bp.route('/login', methods=['GET', 'POST'])
 | 
			
		||||
def login():
 | 
			
		||||
    # 如果用户已经登录,直接重定向到首页
 | 
			
		||||
    print(f"DEBUG: 登录函数被调用,认证状态={current_user.is_authenticated}")
 | 
			
		||||
    print(f"DEBUG: 请求方法={request.method},next参数={request.args.get('next')}")
 | 
			
		||||
 | 
			
		||||
    # 获取next参数
 | 
			
		||||
    next_page = request.args.get('next')
 | 
			
		||||
 | 
			
		||||
    # 如果用户已经登录,处理重定向
 | 
			
		||||
    if current_user.is_authenticated:
 | 
			
		||||
        if next_page:
 | 
			
		||||
            from urllib.parse import urlparse
 | 
			
		||||
            parsed = urlparse(next_page)
 | 
			
		||||
            path = parsed.path
 | 
			
		||||
            print(f"DEBUG: 提取的路径={path}")
 | 
			
		||||
            # 删除特殊处理,直接重定向到path
 | 
			
		||||
            return redirect(path)
 | 
			
		||||
        return redirect(url_for('index'))
 | 
			
		||||
 | 
			
		||||
    if request.method == 'POST':
 | 
			
		||||
@ -363,6 +386,8 @@ def get_role_user_count(role_id):
 | 
			
		||||
    count = User.query.filter_by(role_id=role_id).count()
 | 
			
		||||
    return jsonify({'count': count})
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@user_bp.route('/user/role/<int:role_id>/count', methods=['GET'])
 | 
			
		||||
@login_required
 | 
			
		||||
@admin_required
 | 
			
		||||
 | 
			
		||||
@ -27,6 +27,7 @@ class User(db.Model, UserMixin):
 | 
			
		||||
        self.nickname = nickname
 | 
			
		||||
        self.role_id = role_id
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def is_active(self):
 | 
			
		||||
        return self.status == 1
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
		 Before Width: | Height: | Size: 761 KiB After Width: | Height: | Size: 761 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								app/static/covers/69a1f7af-2b9c-4354-9af9-f3bb909acad4_.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								app/static/covers/69a1f7af-2b9c-4354-9af9-f3bb909acad4_.jpg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 761 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								app/static/covers/jieyou.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								app/static/covers/jieyou.jpg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 37 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								app/static/covers/santi.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								app/static/covers/santi.jpg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 404 KiB  | 
@ -8,8 +8,6 @@
 | 
			
		||||
 | 
			
		||||
{% block content %}
 | 
			
		||||
<div class="book-list-container">
 | 
			
		||||
    <!-- 添加泡泡动画元素 -->
 | 
			
		||||
    <!-- 这些泡泡会通过 JS 动态创建 -->
 | 
			
		||||
 | 
			
		||||
    <div class="page-header">
 | 
			
		||||
        <h1>图书管理</h1>
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user