|
|
@ -8,6 +8,13 @@ from flask_mysqldb import MySQL
|
|
|
|
import MySQLdb.cursors
|
|
|
|
import MySQLdb.cursors
|
|
|
|
from werkzeug.utils import secure_filename
|
|
|
|
from werkzeug.utils import secure_filename
|
|
|
|
from flask_login import LoginManager, UserMixin, login_user, login_required, current_user
|
|
|
|
from flask_login import LoginManager, UserMixin, login_user, login_required, current_user
|
|
|
|
|
|
|
|
from wtforms import Form, StringField
|
|
|
|
|
|
|
|
from wtforms.validators import Length, EqualTo, ValidationError
|
|
|
|
|
|
|
|
import pymysql
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
conn = pymysql.connect(host="localhost", port=3306,
|
|
|
|
|
|
|
|
user="root", password="lin556688",
|
|
|
|
|
|
|
|
database="mydatabase", charset="utf8mb4")
|
|
|
|
|
|
|
|
|
|
|
|
# 初始化 Flask 应用
|
|
|
|
# 初始化 Flask 应用
|
|
|
|
app = Flask(__name__)
|
|
|
|
app = Flask(__name__)
|
|
|
@ -81,9 +88,8 @@ def load_user(user_id):
|
|
|
|
return None
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
@app.route('/')
|
|
|
|
@app.route('/')
|
|
|
|
def index():
|
|
|
|
def home():
|
|
|
|
current_app.logger.info("Index route accessed")
|
|
|
|
return render_template('login.html')
|
|
|
|
return "Welcome to the Home Page!"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@app.route('/view_logs')
|
|
|
|
@app.route('/view_logs')
|
|
|
|
@login_required
|
|
|
|
@login_required
|
|
|
@ -149,6 +155,61 @@ def login():
|
|
|
|
|
|
|
|
|
|
|
|
return render_template('login.html')
|
|
|
|
return render_template('login.html')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 处理数据库语句
|
|
|
|
|
|
|
|
def con_my_sql(sql_code):
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
conn.ping(reconnect=True)
|
|
|
|
|
|
|
|
cursor= conn.cursor(pymysql.cursors.DictCursor)
|
|
|
|
|
|
|
|
cursor.execute(sql_code)
|
|
|
|
|
|
|
|
conn.commit()
|
|
|
|
|
|
|
|
conn.close()
|
|
|
|
|
|
|
|
return cursor
|
|
|
|
|
|
|
|
except pymysql.MySQLError as err_massage:
|
|
|
|
|
|
|
|
conn.rollback()
|
|
|
|
|
|
|
|
conn.close()
|
|
|
|
|
|
|
|
return type(err_massage), err_massage
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class RegisterForm(Form):
|
|
|
|
|
|
|
|
captcha = StringField(validators=[Length(min=4,max=4,message='校验码格式错误')])
|
|
|
|
|
|
|
|
username = StringField(validators=[Length(min=3,max=10,message='用户名长度必须在3到10个字符之间')])
|
|
|
|
|
|
|
|
password = StringField(validators=[Length(min=6,max=20,message='密码长度必须在6到20个字符之间')])
|
|
|
|
|
|
|
|
password_confirm = StringField(validators=[EqualTo('password',message='两次输入的密码不一致')])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def validate_captcha(self, filed):
|
|
|
|
|
|
|
|
if filed.data not in ['1111', '2222', '3333']:
|
|
|
|
|
|
|
|
raise ValidationError('校验码错误')
|
|
|
|
|
|
|
|
@app.route('/register', methods=['GET', 'POST'])
|
|
|
|
|
|
|
|
def register():
|
|
|
|
|
|
|
|
if request.method == 'GET':
|
|
|
|
|
|
|
|
return render_template('register.html')
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
form = RegisterForm(request.form)
|
|
|
|
|
|
|
|
if form.validate():
|
|
|
|
|
|
|
|
username = form.username.data
|
|
|
|
|
|
|
|
password = form.password.data
|
|
|
|
|
|
|
|
captcha = form.captcha.data
|
|
|
|
|
|
|
|
# 静态注册码进行角色注册
|
|
|
|
|
|
|
|
if captcha == "1111":
|
|
|
|
|
|
|
|
role = "侦查者"
|
|
|
|
|
|
|
|
if captcha == "2222":
|
|
|
|
|
|
|
|
role = "指挥者"
|
|
|
|
|
|
|
|
if captcha == "3333":
|
|
|
|
|
|
|
|
role = "攻击者"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
code = "select * from users where username = '%s'" % username
|
|
|
|
|
|
|
|
cursor_ans = con_my_sql(code)
|
|
|
|
|
|
|
|
cursor_select = cursor_ans.fetchall()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if len(cursor_select) > 0:
|
|
|
|
|
|
|
|
return '用户已经存在 <a href="/">返回登录</a>'
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
code = "INSERT INTO users(username, password, role) VALUES('%s', '%s', '%s')" % (username, password, role)
|
|
|
|
|
|
|
|
print(con_my_sql(code))
|
|
|
|
|
|
|
|
return '注册成功 <a href="/">返回登录</a>'
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
print(form.errors)
|
|
|
|
|
|
|
|
return redirect(url_for('register'))
|
|
|
|
|
|
|
|
|
|
|
|
# 侦查者页面
|
|
|
|
# 侦查者页面
|
|
|
|
@app.route('/scout')
|
|
|
|
@app.route('/scout')
|
|
|
|
@login_required
|
|
|
|
@login_required
|
|
|
@ -156,8 +217,75 @@ def scout():
|
|
|
|
logger.info("Accessing scout page")
|
|
|
|
logger.info("Accessing scout page")
|
|
|
|
if current_user.role != '侦查者':
|
|
|
|
if current_user.role != '侦查者':
|
|
|
|
logger.warning("Unauthorized access to scout page")
|
|
|
|
logger.warning("Unauthorized access to scout page")
|
|
|
|
|
|
|
|
return '用户无此页面访问权限 <a href="/">返回登录<a/>'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 获取侦察者的通知
|
|
|
|
|
|
|
|
cursor = mysql.connection.cursor()
|
|
|
|
|
|
|
|
cursor.execute("SELECT * FROM notifications WHERE user_id = %s ORDER BY created_at DESC", (current_user.id,))
|
|
|
|
|
|
|
|
notifications = cursor.fetchall()
|
|
|
|
|
|
|
|
cursor.close()
|
|
|
|
|
|
|
|
logger.info(f"Notifications fetched: {notifications}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return render_template('scout.html', notifications=notifications)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 处理消息
|
|
|
|
|
|
|
|
@app.route('/handle_message/<int:message_id>/<action>', methods=['POST'])
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
|
|
|
|
def handle_message(message_id, action):
|
|
|
|
|
|
|
|
logger.info(f"Handling message action: {action} for ID: {message_id}")
|
|
|
|
|
|
|
|
if current_user.role != '指挥者':
|
|
|
|
|
|
|
|
logger.warning("Unauthorized access to handle message")
|
|
|
|
return redirect(url_for('login'))
|
|
|
|
return redirect(url_for('login'))
|
|
|
|
return render_template('scout.html')
|
|
|
|
|
|
|
|
|
|
|
|
cursor = mysql.connection.cursor()
|
|
|
|
|
|
|
|
if action == 'accept':
|
|
|
|
|
|
|
|
cursor.execute("UPDATE messages SET status = 'accepted' WHERE id = %s", (message_id,))
|
|
|
|
|
|
|
|
flash('消息已接受')
|
|
|
|
|
|
|
|
elif action == 'reject':
|
|
|
|
|
|
|
|
cursor.execute("UPDATE messages SET status = 'rejected' WHERE id = %s", (message_id,))
|
|
|
|
|
|
|
|
flash('消息已打回')
|
|
|
|
|
|
|
|
mysql.connection.commit()
|
|
|
|
|
|
|
|
cursor.close()
|
|
|
|
|
|
|
|
logger.info(f"Message status updated: {action}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 获取消息内容
|
|
|
|
|
|
|
|
cursor = mysql.connection.cursor()
|
|
|
|
|
|
|
|
cursor.execute("SELECT message FROM messages WHERE id = %s", (message_id,))
|
|
|
|
|
|
|
|
message_data = cursor.fetchone()
|
|
|
|
|
|
|
|
cursor.close()
|
|
|
|
|
|
|
|
logger.info(f"Message data fetched: {message_data}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 将结果反馈给侦察者
|
|
|
|
|
|
|
|
cursor = mysql.connection.cursor()
|
|
|
|
|
|
|
|
cursor.execute("SELECT id FROM users WHERE role = '侦查者'")
|
|
|
|
|
|
|
|
scouts = cursor.fetchall()
|
|
|
|
|
|
|
|
cursor.close()
|
|
|
|
|
|
|
|
logger.info(f"Scouts found: {scouts}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for scout in scouts:
|
|
|
|
|
|
|
|
cursor = mysql.connection.cursor()
|
|
|
|
|
|
|
|
cursor.execute("INSERT INTO notifications (user_id, message_id, action, message) VALUES (%s, %s, %s, %s)",
|
|
|
|
|
|
|
|
(scout['id'], message_id, action, message_data['message']))
|
|
|
|
|
|
|
|
mysql.connection.commit()
|
|
|
|
|
|
|
|
cursor.close()
|
|
|
|
|
|
|
|
logger.info(f"Notification inserted for scout: {scout['id']}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return redirect(url_for('commander'))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 清除通知
|
|
|
|
|
|
|
|
@app.route('/clear_notifications', methods=['POST'])
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
|
|
|
|
def clear_notifications():
|
|
|
|
|
|
|
|
user_id = request.json.get('user_id')
|
|
|
|
|
|
|
|
if not user_id:
|
|
|
|
|
|
|
|
return jsonify({'success': False, 'message': 'User ID is required'}), 400
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cursor = mysql.connection.cursor()
|
|
|
|
|
|
|
|
cursor.execute("DELETE FROM notifications WHERE user_id = %s", (user_id,))
|
|
|
|
|
|
|
|
mysql.connection.commit()
|
|
|
|
|
|
|
|
cursor.close()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return jsonify({'success': True, 'message': 'Notifications cleared successfully'})
|
|
|
|
|
|
|
|
|
|
|
|
# 指挥者页面
|
|
|
|
# 指挥者页面
|
|
|
|
@app.route('/commander')
|
|
|
|
@app.route('/commander')
|
|
|
@ -166,7 +294,7 @@ def commander():
|
|
|
|
logger.info("Accessing commander page")
|
|
|
|
logger.info("Accessing commander page")
|
|
|
|
if current_user.role != '指挥者':
|
|
|
|
if current_user.role != '指挥者':
|
|
|
|
logger.warning("Unauthorized access to commander page")
|
|
|
|
logger.warning("Unauthorized access to commander page")
|
|
|
|
return redirect(url_for('login'))
|
|
|
|
return '用户无此页面访问权限 <a href="/">返回登录<a/>'
|
|
|
|
|
|
|
|
|
|
|
|
# 获取特定目录下的所有文件和攻击坐标状态
|
|
|
|
# 获取特定目录下的所有文件和攻击坐标状态
|
|
|
|
directory = 'E:/_Ufo/0000jiegou/TheBattleCar/uploads'
|
|
|
|
directory = 'E:/_Ufo/0000jiegou/TheBattleCar/uploads'
|
|
|
@ -185,7 +313,13 @@ def commander():
|
|
|
|
attacks = cursor.fetchall()
|
|
|
|
attacks = cursor.fetchall()
|
|
|
|
cursor.close()
|
|
|
|
cursor.close()
|
|
|
|
|
|
|
|
|
|
|
|
return render_template('commander.html', media_items=media_items, attacks=attacks)
|
|
|
|
# 获取侦察者发送的消息
|
|
|
|
|
|
|
|
cursor = mysql.connection.cursor()
|
|
|
|
|
|
|
|
cursor.execute("SELECT id, message, photo_url, created_at, status FROM messages ORDER BY created_at DESC")
|
|
|
|
|
|
|
|
messages = cursor.fetchall()
|
|
|
|
|
|
|
|
cursor.close()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return render_template('commander.html', media_items=media_items, attacks=attacks, messages=messages)
|
|
|
|
|
|
|
|
|
|
|
|
# 指挥者发送攻击坐标
|
|
|
|
# 指挥者发送攻击坐标
|
|
|
|
@app.route('/send_attack', methods=['POST'])
|
|
|
|
@app.route('/send_attack', methods=['POST'])
|
|
|
@ -211,6 +345,47 @@ def send_attack():
|
|
|
|
flash('攻击坐标已发送')
|
|
|
|
flash('攻击坐标已发送')
|
|
|
|
return redirect(url_for('commander'))
|
|
|
|
return redirect(url_for('commander'))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 清除照片
|
|
|
|
|
|
|
|
@app.route('/clear_photos', methods=['POST'])
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
|
|
|
|
def clear_photos():
|
|
|
|
|
|
|
|
logger.info("Handling clear photos request")
|
|
|
|
|
|
|
|
if current_user.role != '指挥者':
|
|
|
|
|
|
|
|
logger.warning("Unauthorized access to clear photos")
|
|
|
|
|
|
|
|
return redirect(url_for('login'))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
directory = app.config['UPLOAD_FOLDER']
|
|
|
|
|
|
|
|
for filename in os.listdir(directory):
|
|
|
|
|
|
|
|
file_path = os.path.join(directory, filename)
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
if os.path.isfile(file_path):
|
|
|
|
|
|
|
|
os.unlink(file_path)
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
|
|
logger.error(f"Error deleting file: {str(e)}")
|
|
|
|
|
|
|
|
flash(f"Error deleting file: {str(e)}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
logger.info("Photos cleared successfully")
|
|
|
|
|
|
|
|
flash('照片已清空')
|
|
|
|
|
|
|
|
return redirect(url_for('commander'))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 清除侦察者发送的消息
|
|
|
|
|
|
|
|
@app.route('/clear_messages', methods=['POST'])
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
|
|
|
|
def clear_messages():
|
|
|
|
|
|
|
|
logger.info("Handling clear messages request")
|
|
|
|
|
|
|
|
if current_user.role != '指挥者':
|
|
|
|
|
|
|
|
logger.warning("Unauthorized access to clear messages")
|
|
|
|
|
|
|
|
return redirect(url_for('login'))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cursor = mysql.connection.cursor()
|
|
|
|
|
|
|
|
cursor.execute("DELETE FROM messages")
|
|
|
|
|
|
|
|
mysql.connection.commit()
|
|
|
|
|
|
|
|
cursor.close()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
logger.info("Messages cleared successfully")
|
|
|
|
|
|
|
|
flash('消息已清空')
|
|
|
|
|
|
|
|
return redirect(url_for('commander'))
|
|
|
|
|
|
|
|
|
|
|
|
# 攻击者页面
|
|
|
|
# 攻击者页面
|
|
|
|
@app.route('/attacker')
|
|
|
|
@app.route('/attacker')
|
|
|
|
@login_required
|
|
|
|
@login_required
|
|
|
@ -218,7 +393,7 @@ def attacker():
|
|
|
|
logger.info("Accessing attacker page")
|
|
|
|
logger.info("Accessing attacker page")
|
|
|
|
if current_user.role != '攻击者':
|
|
|
|
if current_user.role != '攻击者':
|
|
|
|
logger.warning("Unauthorized access to attacker page")
|
|
|
|
logger.warning("Unauthorized access to attacker page")
|
|
|
|
return redirect(url_for('login'))
|
|
|
|
return '用户无此页面访问权限 <a href="/">返回登录<a/>'
|
|
|
|
|
|
|
|
|
|
|
|
# 获取攻击坐标列表
|
|
|
|
# 获取攻击坐标列表
|
|
|
|
cursor = mysql.connection.cursor()
|
|
|
|
cursor = mysql.connection.cursor()
|
|
|
@ -281,7 +456,7 @@ def send_message():
|
|
|
|
|
|
|
|
|
|
|
|
# 插入数据到 MySQL
|
|
|
|
# 插入数据到 MySQL
|
|
|
|
cursor = mysql.connection.cursor()
|
|
|
|
cursor = mysql.connection.cursor()
|
|
|
|
cursor.execute("INSERT INTO messages (message, photo_url) VALUES (%s, %s)", (message, photo_url))
|
|
|
|
cursor.execute("INSERT INTO messages (message, photo_url, status) VALUES (%s, %s, %s)", (message, photo_url, 'pending'))
|
|
|
|
mysql.connection.commit()
|
|
|
|
mysql.connection.commit()
|
|
|
|
cursor.close()
|
|
|
|
cursor.close()
|
|
|
|
logger.info(f"Message sent: {message}, Photo URL: {photo_url}")
|
|
|
|
logger.info(f"Message sent: {message}, Photo URL: {photo_url}")
|
|
|
@ -296,7 +471,7 @@ def send_message():
|
|
|
|
def get_messages():
|
|
|
|
def get_messages():
|
|
|
|
logger.info("Handling get messages request")
|
|
|
|
logger.info("Handling get messages request")
|
|
|
|
cursor = mysql.connection.cursor()
|
|
|
|
cursor = mysql.connection.cursor()
|
|
|
|
cursor.execute("SELECT id, message, photo_url, created_at FROM messages")
|
|
|
|
cursor.execute("SELECT id, message, photo_url, created_at, status FROM messages")
|
|
|
|
result = cursor.fetchall()
|
|
|
|
result = cursor.fetchall()
|
|
|
|
cursor.close()
|
|
|
|
cursor.close()
|
|
|
|
|
|
|
|
|
|
|
@ -306,7 +481,8 @@ def get_messages():
|
|
|
|
'id': row['id'],
|
|
|
|
'id': row['id'],
|
|
|
|
'message': row['message'],
|
|
|
|
'message': row['message'],
|
|
|
|
'photo_url': row['photo_url'],
|
|
|
|
'photo_url': row['photo_url'],
|
|
|
|
'created_at': row['created_at']
|
|
|
|
'created_at': row['created_at'],
|
|
|
|
|
|
|
|
'status': row['status']
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
return jsonify(messages)
|
|
|
|
return jsonify(messages)
|
|
|
|