from functools import wraps from flask import session, request, jsonify, redirect, url_for import socket import os import yaml import subprocess import platform from utils.logger_config import logger # 配置上传文件夹 UPLOAD_FOLDER = 'uploads' ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif', 'bmp', 'webp'} # 登录验证装饰器 def login_required(f): @wraps(f) def decorated_function(*args, **kwargs): if 'logged_in' not in session: # 如果是 API 请求,返回 401 if request.path.startswith('/api/'): return jsonify({'success': False, 'message': '未登录'}), 401 # 如果是页面请求,跳转到登录页 # 假设 auth blueprint 注册为 'auth',登录路由名为 'login' return redirect(url_for('auth.login')) return f(*args, **kwargs) return decorated_function def allowed_file(filename): """检查文件扩展名是否允许""" return '.' in filename and \ filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS def get_server_ip(): """获取服务器的本地IP地址""" try: # 连接到一个远程地址(不会实际发送数据) s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.connect(("8.8.8.8", 80)) ip = s.getsockname()[0] s.close() return ip except Exception: # 如果获取失败,尝试其他方法 try: hostname = socket.gethostname() ip = socket.gethostbyname(hostname) return ip except Exception: return "127.0.0.1" # 回退到localhost def load_led_config(): """读取LED配置文件""" try: config_path = 'led_config.yaml' if os.path.exists(config_path): with open(config_path, 'r', encoding='utf-8') as f: config = yaml.safe_load(f) return config.get('segments', []) return [] except Exception as e: logger.error(f"读取LED配置文件失败: {e}") return [] def ping_ip(ip): """ Ping IP地址,返回是否通畅 """ if not ip: return False system_type = platform.system().lower() if system_type == 'windows': # -n 1: 发送1个包 # -w 1000: 超时1000ms command = ['ping', '-n', '1', '-w', '1000', ip] else: # -c 1: 发送1个包 # -W 1: 超时1s command = ['ping', '-c', '1', '-W', '1', ip] try: # 这里的 stdout/stderr=subprocess.DEVNULL 防止输出干扰日志 return subprocess.call(command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) == 0 except Exception as e: logger.error(f"Ping IP {ip} 异常: {e}") return False