filesend/backend/app/routes/team_leader.py

241 lines
7.6 KiB
Python

from flask import Blueprint, request, jsonify
from flask_jwt_extended import jwt_required, get_jwt_identity
from ..models import User, File, Download, TeamMember, CategoryPermission, db
from datetime import datetime
from .admin import team_leader_required
team_leader_bp = Blueprint('team_leader', __name__, url_prefix='/api/team-leader')
@team_leader_bp.route('/members', methods=['GET'])
@team_leader_required
def get_team_members():
"""团队长获取自己的团队成员列表"""
current_user_id = get_jwt_identity()
# 获取团队成员
team_members = TeamMember.query.filter_by(leader_id=current_user_id).all()
result = []
for member in team_members:
member_data = member.member.to_dict()
# 获取成员的文件统计信息
file_count = File.query.filter_by(uploaded_by=member.member_id).count()
download_count = Download.query.filter_by(user_id=member.member_id).count()
member_data['file_count'] = file_count
member_data['download_count'] = download_count
member_data['joined_at'] = member.created_at.isoformat()
result.append(member_data)
return jsonify({
'team_members': result,
'total_members': len(result)
}), 200
@team_leader_bp.route('/members/<int:member_id>/files', methods=['GET'])
@team_leader_required
def get_member_files(member_id):
"""团队长查看团队成员的文件"""
current_user_id = get_jwt_identity()
# 验证该成员是否属于当前团队长
team_member = TeamMember.query.filter_by(
leader_id=current_user_id,
member_id=member_id
).first()
if not team_member:
return jsonify({'message': '该用户不是您的团队成员'}), 403
page = request.args.get('page', 1, type=int)
per_page = request.args.get('per_page', 10, type=int)
category_id = request.args.get('category_id', type=int)
query = File.query.filter_by(uploaded_by=member_id)
if category_id:
query = query.filter_by(category_id=category_id)
pagination = query.paginate(page=page, per_page=per_page, error_out=False)
files = pagination.items
return jsonify({
'files': [file.to_dict() for file in files],
'total_files': pagination.total,
'pages': pagination.pages,
'current_page': pagination.page,
'has_next': pagination.has_next,
'has_prev': pagination.has_prev
}), 200
@team_leader_bp.route('/members/<int:member_id>/downloads', methods=['GET'])
@team_leader_required
def get_member_downloads(member_id):
"""团队长查看团队成员的下载记录"""
current_user_id = get_jwt_identity()
# 验证该成员是否属于当前团队长
team_member = TeamMember.query.filter_by(
leader_id=current_user_id,
member_id=member_id
).first()
if not team_member:
return jsonify({'message': '该用户不是您的团队成员'}), 403
page = request.args.get('page', 1, type=int)
per_page = request.args.get('per_page', 10, type=int)
pagination = Download.query.filter_by(user_id=member_id).order_by(
Download.download_time.desc()
).paginate(page=page, per_page=per_page, error_out=False)
downloads = pagination.items
result = []
for download in downloads:
download_data = download.to_dict()
download_data['file_name'] = download.file.filename
download_data['file_size'] = download.file.file_size
result.append(download_data)
return jsonify({
'downloads': result,
'total_downloads': pagination.total,
'pages': pagination.pages,
'current_page': pagination.page,
'has_next': pagination.has_next,
'has_prev': pagination.has_prev
}), 200
@team_leader_bp.route('/members/<int:member_id>/quota', methods=['PUT'])
@team_leader_required
def update_member_quota(member_id):
"""团队长修改团队成员的每日配额"""
current_user_id = get_jwt_identity()
# 验证该成员是否属于当前团队长
team_member = TeamMember.query.filter_by(
leader_id=current_user_id,
member_id=member_id
).first()
if not team_member:
return jsonify({'message': '该用户不是您的团队成员'}), 403
data = request.get_json()
daily_quota = data.get('daily_quota')
if daily_quota is None:
return jsonify({'message': '每日配额不能为空'}), 400
if daily_quota < 0:
return jsonify({'message': '每日配额不能为负数'}), 400
member = User.query.get(member_id)
member.daily_quota = daily_quota
db.session.commit()
return jsonify({
'message': f'用户 {member.username} 的每日配额已更新为 {daily_quota}',
'user': member.to_dict()
}), 200
@team_leader_bp.route('/members/<int:member_id>/status', methods=['PUT'])
@team_leader_required
def update_member_status(member_id):
"""团队长启用/禁用团队成员账号"""
current_user_id = get_jwt_identity()
# 验证该成员是否属于当前团队长
team_member = TeamMember.query.filter_by(
leader_id=current_user_id,
member_id=member_id
).first()
if not team_member:
return jsonify({'message': '该用户不是您的团队成员'}), 403
data = request.get_json()
is_active = data.get('is_active')
if is_active is None:
return jsonify({'message': '状态不能为空'}), 400
member = User.query.get(member_id)
member.is_active = is_active
db.session.commit()
status_text = '启用' if is_active else '禁用'
return jsonify({
'message': f'用户 {member.username} 的账号已{status_text}',
'user': member.to_dict()
}), 200
@team_leader_bp.route('/team-stats', methods=['GET'])
@team_leader_required
def get_team_stats():
"""团队长获取团队统计信息"""
current_user_id = get_jwt_identity()
# 获取团队成员
team_members = TeamMember.query.filter_by(leader_id=current_user_id).all()
member_ids = [member.member_id for member in team_members]
if not member_ids:
return jsonify({
'total_members': 0,
'total_files': 0,
'total_downloads': 0,
'active_members': 0
}), 200
# 统计信息
total_files = File.query.filter(File.uploaded_by.in_(member_ids)).count()
total_downloads = Download.query.filter(Download.user_id.in_(member_ids)).count()
active_members = User.query.filter(
User.id.in_(member_ids),
User.is_active == True
).count()
return jsonify({
'total_members': len(team_members),
'total_files': total_files,
'total_downloads': total_downloads,
'active_members': active_members
}), 200
@team_leader_bp.route('/available-categories', methods=['GET'])
@team_leader_required
def get_available_categories():
"""团队长获取可分配给团队成员的分类"""
current_user_id = get_jwt_identity()
# 获取团队长有权限的分类
permissions = CategoryPermission.query.filter_by(user_id=current_user_id).all()
category_ids = [perm.category_id for perm in permissions]
if not category_ids:
return jsonify({'categories': []}), 200
# 返回分类信息
from ..models import Category
categories = Category.query.filter(Category.id.in_(category_ids)).all()
return jsonify({
'categories': [{
'id': cat.id,
'name': cat.name,
'description': cat.description,
'path': cat.path
} for cat in categories]
}), 200