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/', 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/', 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/', 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//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//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//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//files/', 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 )