from flask import Blueprint, request, jsonify, send_file, current_app from flask_login import login_required, current_user from werkzeug.utils import secure_filename import sys import os # 添加父目录到路径 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from models import db, Article, Resource, TeamMember from datetime import datetime bp = Blueprint('cms', __name__) def allowed_file(filename, allowed_extensions): """检查文件扩展名是否允许""" return '.' in filename and filename.rsplit('.', 1)[1].lower() in allowed_extensions # 文章管理 @bp.route('/articles', methods=['GET']) def get_articles(): """获取文章列表""" category = request.args.get('category', 'news') published_only = request.args.get('published_only', 'true').lower() == 'true' query = Article.query.filter_by(category=category) if published_only: query = query.filter_by(published=True) # 如果未登录,过滤受保护内容 if not current_user.is_authenticated: query = query.filter_by(is_protected=False) articles = query.order_by(Article.created_at.desc()).all() return jsonify({ 'articles': [article.to_dict() for article in articles] }), 200 @bp.route('/articles/', methods=['GET']) def get_article(article_id): """获取单篇文章""" article = Article.query.get_or_404(article_id) # 检查是否需要登录 if article.is_protected and not current_user.is_authenticated: return jsonify({'error': 'Authentication required'}), 401 if not article.published: if not current_user.is_authenticated or not current_user.is_admin: return jsonify({'error': 'Article not found'}), 404 return jsonify({'article': article.to_dict()}), 200 @bp.route('/articles', methods=['POST']) @login_required def create_article(): """创建文章(需要管理员权限)""" if not current_user.is_admin: return jsonify({'error': 'Admin access required'}), 403 data = request.get_json() article = Article( title=data.get('title'), content=data.get('content'), summary=data.get('summary'), category=data.get('category', 'news'), is_protected=data.get('is_protected', False), author_id=current_user.id, published=data.get('published', True) ) db.session.add(article) db.session.commit() return jsonify({ 'message': 'Article created successfully', 'article': article.to_dict() }), 201 @bp.route('/articles/', methods=['PUT']) @login_required def update_article(article_id): """更新文章(需要管理员权限)""" if not current_user.is_admin: return jsonify({'error': 'Admin access required'}), 403 article = Article.query.get_or_404(article_id) data = request.get_json() article.title = data.get('title', article.title) article.content = data.get('content', article.content) article.summary = data.get('summary', article.summary) article.category = data.get('category', article.category) article.is_protected = data.get('is_protected', article.is_protected) article.published = data.get('published', article.published) article.updated_at = datetime.utcnow() db.session.commit() return jsonify({ 'message': 'Article updated successfully', 'article': article.to_dict() }), 200 @bp.route('/articles/', methods=['DELETE']) @login_required def delete_article(article_id): """删除文章(需要管理员权限)""" if not current_user.is_admin: return jsonify({'error': 'Admin access required'}), 403 article = Article.query.get_or_404(article_id) db.session.delete(article) db.session.commit() return jsonify({'message': 'Article deleted successfully'}), 200 # 资源管理 @bp.route('/resources', methods=['GET']) def get_resources(): """获取资源列表""" category = request.args.get('category') query = Resource.query if category: query = query.filter_by(category=category) # 如果未登录,过滤受保护资源 if not current_user.is_authenticated: query = query.filter_by(is_protected=False) resources = query.order_by(Resource.created_at.desc()).all() return jsonify({ 'resources': [resource.to_dict() for resource in resources] }), 200 @bp.route('/resources', methods=['POST']) @login_required def upload_resource(): """上传资源文件(需要管理员权限)""" if not current_user.is_admin: return jsonify({'error': 'Admin access required'}), 403 if 'file' not in request.files: return jsonify({'error': 'No file provided'}), 400 file = request.files['file'] if file.filename == '': return jsonify({'error': 'No file selected'}), 400 if file and allowed_file(file.filename, {'pdf', 'zip', 'rar', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx'}): filename = secure_filename(file.filename) uploads_dir = current_app.config['UPLOAD_FOLDER'] os.makedirs(uploads_dir, exist_ok=True) filepath = os.path.join(uploads_dir, filename) file.save(filepath) resource = Resource( name=request.form.get('name', filename), description=request.form.get('description', ''), file_path=f'/uploads/{filename}', file_size=os.path.getsize(filepath), file_type=filename.rsplit('.', 1)[1].lower(), category=request.form.get('category', 'document'), is_protected=request.form.get('is_protected', 'false').lower() == 'true' ) db.session.add(resource) db.session.commit() return jsonify({ 'message': 'Resource uploaded successfully', 'resource': resource.to_dict() }), 201 return jsonify({'error': 'Invalid file type'}), 400 # 团队成员管理 @bp.route('/team', methods=['GET']) def get_team(): """获取团队成员列表""" role = request.args.get('role') query = TeamMember.query if role: query = query.filter_by(role=role) members = query.order_by(TeamMember.order, TeamMember.created_at).all() return jsonify({ 'members': [member.to_dict() for member in members] }), 200 @bp.route('/team', methods=['POST']) @login_required def create_team_member(): """创建团队成员(需要管理员权限)""" if not current_user.is_admin: return jsonify({'error': 'Admin access required'}), 403 data = request.get_json() member = TeamMember( name=data.get('name'), title=data.get('title'), title_en=data.get('title_en'), bio=data.get('bio'), bio_en=data.get('bio_en'), role=data.get('role', 'student'), email=data.get('email'), website=data.get('website'), order=data.get('order', 0) ) db.session.add(member) db.session.commit() return jsonify({ 'message': 'Team member created successfully', 'member': member.to_dict() }), 201