Files
SI_TEALab_2025_LabWebsite/dofile/backend/routes/meetings.py
T
pengxiao a3eb5c7b2d init: TEALab 2025 实验室网站项目
从百度网盘 /apps/bypy/dofile/ 下载的完整项目结构,包含:
- dofile/: Flask 后端(端口 5000)+ 静态前端(端口 6002)
- officefile/: 项目相关文档
- .gitignore: Python venv / 日志 / 缓存

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-14 01:07:19 +08:00

257 lines
8.0 KiB
Python

from flask import Blueprint, request, jsonify, send_from_directory, current_app
from flask_login import login_required, current_user
from werkzeug.utils import secure_filename
import sys
import os
from datetime import datetime, date, time
# 添加父目录到路径
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from models import db, Meeting, MeetingRegistration, MeetingFile, User
bp = Blueprint('meetings', __name__)
def allowed_file(filename, allowed_extensions):
"""检查文件扩展名是否允许"""
return '.' in filename and filename.rsplit('.', 1)[1].lower() in allowed_extensions
@bp.route('/meetings', methods=['GET'])
@login_required
def get_meetings():
"""获取组会列表(实验室成员可查看所有)"""
status = request.args.get('status')
meeting_type = request.args.get('type')
query = Meeting.query
if status:
query = query.filter_by(status=status)
if meeting_type:
query = query.filter_by(meeting_type=meeting_type)
meetings = query.order_by(Meeting.date.desc(), Meeting.time.desc()).all()
return jsonify({
'meetings': [meeting.to_dict() for meeting in meetings]
}), 200
@bp.route('/meetings/<int:meeting_id>', methods=['GET'])
@login_required
def get_meeting(meeting_id):
"""获取单个组会详情"""
meeting = Meeting.query.get_or_404(meeting_id)
# 获取参会人员列表
registrations = MeetingRegistration.query.filter_by(meeting_id=meeting_id).all()
attendees = [reg.to_dict() for reg in registrations]
# 获取文件列表
files = MeetingFile.query.filter_by(meeting_id=meeting_id).all()
file_list = [f.to_dict() for f in files]
result = meeting.to_dict()
result['attendees'] = attendees
result['files'] = file_list
return jsonify({'meeting': result}), 200
@bp.route('/meetings', methods=['POST'])
@login_required
def create_meeting():
"""创建组会(需要登录)"""
data = request.get_json()
# 解析日期和时间
meeting_date = datetime.strptime(data['date'], '%Y-%m-%d').date() if data.get('date') else None
meeting_time = datetime.strptime(data['time'], '%H:%M').time() if data.get('time') else None
meeting = Meeting(
title=data.get('title'),
description=data.get('description'),
date=meeting_date,
time=meeting_time,
location=data.get('location'),
organizer_id=current_user.id,
status=data.get('status', 'planned'),
meeting_type=data.get('meeting_type', 'weekly')
)
db.session.add(meeting)
db.session.commit()
return jsonify({
'message': 'Meeting created successfully',
'meeting': meeting.to_dict()
}), 201
@bp.route('/meetings/<int:meeting_id>', methods=['PUT'])
@login_required
def update_meeting(meeting_id):
"""更新组会(只有创建者可以编辑)"""
meeting = Meeting.query.get_or_404(meeting_id)
# 检查权限:只有创建者可以编辑
if meeting.organizer_id != current_user.id:
return jsonify({'error': 'Only the organizer can edit this meeting'}), 403
data = request.get_json()
if 'title' in data:
meeting.title = data['title']
if 'description' in data:
meeting.description = data['description']
if 'date' in data:
meeting.date = datetime.strptime(data['date'], '%Y-%m-%d').date()
if 'time' in data:
meeting.time = datetime.strptime(data['time'], '%H:%M').time()
if 'location' in data:
meeting.location = data['location']
if 'status' in data:
meeting.status = data['status']
if 'meeting_type' in data:
meeting.meeting_type = data['meeting_type']
if 'meeting_notes' in data:
meeting.meeting_notes = data['meeting_notes']
meeting.updated_at = datetime.utcnow()
db.session.commit()
return jsonify({
'message': 'Meeting updated successfully',
'meeting': meeting.to_dict()
}), 200
@bp.route('/meetings/<int:meeting_id>', methods=['DELETE'])
@login_required
def delete_meeting(meeting_id):
"""删除组会(只有创建者可以删除)"""
meeting = Meeting.query.get_or_404(meeting_id)
# 检查权限
if meeting.organizer_id != current_user.id:
return jsonify({'error': 'Only the organizer can delete this meeting'}), 403
db.session.delete(meeting)
db.session.commit()
return jsonify({'message': 'Meeting deleted successfully'}), 200
@bp.route('/meetings/<int:meeting_id>/register', methods=['POST'])
@login_required
def register_meeting(meeting_id):
"""报名参加组会"""
meeting = Meeting.query.get_or_404(meeting_id)
# 检查是否已报名
existing = MeetingRegistration.query.filter_by(
meeting_id=meeting_id,
user_id=current_user.id
).first()
if existing:
return jsonify({'error': 'Already registered'}), 400
registration = MeetingRegistration(
meeting_id=meeting_id,
user_id=current_user.id,
status='registered'
)
db.session.add(registration)
db.session.commit()
return jsonify({
'message': 'Registered successfully',
'registration': registration.to_dict()
}), 201
@bp.route('/meetings/<int:meeting_id>/checkin', methods=['POST'])
@login_required
def checkin_meeting(meeting_id):
"""签到组会"""
registration = MeetingRegistration.query.filter_by(
meeting_id=meeting_id,
user_id=current_user.id
).first_or_404()
registration.status = 'checked_in'
db.session.commit()
return jsonify({
'message': 'Checked in successfully',
'registration': registration.to_dict()
}), 200
@bp.route('/meetings/<int:meeting_id>/files', methods=['POST'])
@login_required
def upload_meeting_file(meeting_id):
"""上传组会文件(只有创建者可以上传)"""
meeting = Meeting.query.get_or_404(meeting_id)
# 检查权限
if meeting.organizer_id != current_user.id:
return jsonify({'error': 'Only the organizer can upload files'}), 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', 'doc', 'docx', 'ppt', 'pptx', 'xls', 'xlsx', 'zip', 'rar'}):
filename = secure_filename(file.filename)
uploads_dir = current_app.config['UPLOAD_FOLDER']
meeting_dir = os.path.join(uploads_dir, 'meetings', str(meeting_id))
os.makedirs(meeting_dir, exist_ok=True)
filepath = os.path.join(meeting_dir, filename)
file.save(filepath)
meeting_file = MeetingFile(
meeting_id=meeting_id,
name=request.form.get('name', filename),
file_path=f'/uploads/meetings/{meeting_id}/{filename}',
file_size=os.path.getsize(filepath),
file_type=filename.rsplit('.', 1)[1].lower(),
uploader_id=current_user.id
)
db.session.add(meeting_file)
db.session.commit()
return jsonify({
'message': 'File uploaded successfully',
'file': meeting_file.to_dict()
}), 201
return jsonify({'error': 'Invalid file type'}), 400
@bp.route('/meetings/<int:meeting_id>/files/<int:file_id>', methods=['GET'])
@login_required
def download_meeting_file(meeting_id, file_id):
"""下载组会文件"""
meeting_file = MeetingFile.query.filter_by(
meeting_id=meeting_id,
id=file_id
).first_or_404()
uploads_dir = current_app.config['UPLOAD_FOLDER']
file_path = os.path.join(uploads_dir, 'meetings', str(meeting_id), os.path.basename(meeting_file.file_path))
return send_from_directory(
os.path.dirname(file_path),
os.path.basename(file_path),
as_attachment=True
)