在action中配置@Result(params={"root","{d,message}"})

本文介绍如何在Struts2框架中通过JSON正确返回多个参数的方法,包括配置注解和解决序列化问题的技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题的产生:我需要通过json给前台传回多个参数,一开始注解中是这样写的:params={“root”,”d,message”},在前端只能取到message的值,后来加上大括号就行了:params={“root”,”{d,message}”},需要注意的是,d这个部门对象中的属性不要有其他对象或者集合,有的话在返回json过程中会出错,这时可以给其他对象或者集合的getter方法上面加@JSON(serialize=false),告诉框架不要序列化这些属性即可。

@Controller
@Scope("prototype")
@Namespace("/department")
@ParentPackage("json-default")//使用json必须要设置这个,它继承了struts-default
public class DepartmentAction extends ActionSupport{
private Department d;//部门对象
private String message;//返回页面的消息
@Action(value="update",results={                        
//重点在下面这句···············································                
            @Result(name="json",type="json",params={"root","{d,message}"})
    })
    public String update(){

            return "json";
    }


//需要使用json方式返回d和message,那么一定要封装,d和message是全局变量

    public Department getD() {
        return d;
    }

    public void setD(Department d) {
        this.d = d;
    }
    public String getMessage() {
        return message;
    }


    public void setMessage(String message) {
        this.message = message;
    }
}
import sys import os import time import logging import traceback import threading import platform import psutil import datetime from pathlib import Path from logging.handlers import RotatingFileHandler from core.config import CoreConfig system_config = CoreConfig() # 创建配置实例 # ========== 安全工具函数 ========== def safe_path(path_str: str) -> Path: """安全处理路径字符串,确保跨平台兼容性""" try: path = Path(path_str) if not path.is_absolute(): # 如果路径是相对的,基于项目根目录解析 base_dir = Path(__file__).parent.parent.resolve() return (base_dir / path).resolve() return path.resolve() except Exception as e: logging.error(f"路径解析错误: {path_str} - {str(e)}") return Path.cwd().resolve() class SafeConsoleHandler(logging.StreamHandler): """Windows安全的控制台日志处理器""" def emit(self, record): try: msg = self.format(record) # 安全处理Unicode字符 safe_msg = msg.encode('utf-8', errors='replace').decode('utf-8') stream = self.stream stream.write(safe_msg + self.terminator) self.flush() except Exception: self.handleError(record) # ========== 配置系统初始化 ========== # 添加核心模块路径 sys.path.insert(0, str(Path(__file__).parent.parent)) # 导入核心配置 from core.config import CoreConfig as SystemConfig # 全局配置实例 system_config = SystemConfig() # ========== 安全日志系统 ========== def setup_logger() -> logging.Logger: """配置并返回安全的日志系统""" logger = logging.getLogger('WebServer') # 清除所有现有处理器 for handler in logger.handlers[:]: logger.removeHandler(handler) # 安全获取配置项 debug_mode = system_config.get('DEBUG', False) log_level = logging.DEBUG if debug_mode else logging.INFO log_file = system_config.get('logging.file', 'logs/web_server.log') max_log_size = system_config.get('logging.max_size', 10) # MB backup_count = system_config.get('logging.backup_count', 5) # 设置日志级别 logger.setLevel(log_level) # 创建安全的控制台处理器 console_handler = SafeConsoleHandler() console_handler.setLevel(log_level) # 创建安全的文件处理器 try: # 确保日志目录存在 log_path = safe_path(log_file) log_path.parent.mkdir(parents=True, exist_ok=True) file_handler = RotatingFileHandler( filename=str(log_path), maxBytes=max_log_size * 1024 * 1024, backupCount=backup_count, encoding='utf-8' ) file_handler.setLevel(logging.DEBUG) except Exception as e: logging.error(f"无法创建文件日志处理器: {str(e)}") file_handler = logging.NullHandler() # 创建安全的格式化器 formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(process)d - %(thread)d - %(message)s', datefmt='%Y-%m-%d %H:%M:%S' ) # 应用格式化器 console_handler.setFormatter(formatter) file_handler.setFormatter(formatter) # 添加处理器 logger.addHandler(console_handler) logger.addHandler(file_handler) # 设置根日志器 root_logger = logging.getLogger() root_logger.setLevel(log_level) for handler in root_logger.handlers[:]: root_logger.removeHandler(handler) root_logger.addHandler(console_handler) root_logger.addHandler(file_handler) # 配置第三方库日志器 third_party_loggers = ['werkzeug', 'engineio', 'socketio', 'urllib3'] for log_name in third_party_loggers: lib_logger = logging.getLogger(log_name) lib_logger.setLevel(logging.WARNING) lib_logger.propagate = False lib_logger.addHandler(file_handler) # 安全记录日志系统初始化完成 logger.info("日志系统初始化完成") logger.info("日志级别: %s", 'DEBUG' if debug_mode else 'INFO') logger.info("日志文件: %s", log_file) return logger # 初始化日志系统 logger = setup_logger() # ========== Flask应用初始化 ========== from flask import Flask, render_template, request, jsonify, send_from_directory, current_app # 安全获取模板和静态文件路径 template_dir = safe_path(system_config.get('template_dir', Path(__file__).parent / 'templates')) static_dir = safe_path(system_config.get('static_dir', Path(__file__).parent / 'static')) app = Flask( __name__, template_folder=str(template_dir), static_folder=str(static_dir), static_url_path='/static' ) # 设置Flask调试模式 app.debug = system_config.get('DEBUG', False) app.secret_key = system_config.get('SECRET_KEY', 'default_secret_key') # ========== 环境管理器 ========== class EnvironmentManager: """跨平台兼容的环境管理器""" def __init__(self): self.state = { 'temperature': 22.5, 'humidity': 45.0, 'light_level': 75, 'objects': [], 'last_updated': datetime.datetime.now().isoformat() } self.healthy = True self.lock = threading.Lock() self.running = False self.update_thread = None self.observers = [] logger.info("环境管理器初始化成功") def start(self): """启动环境状态更新线程""" if self.running: return self.running = True self.update_thread = threading.Thread(target=self._update_loop, daemon=True) self.update_thread.start() logger.info("环境管理器已启动") def stop(self): """停止环境管理器""" self.running = False if self.update_thread and self.update_thread.is_alive(): self.update_thread.join(timeout=5) logger.info("环境管理器已停止") def register_observer(self, callback): """注册状态变更观察者""" self.observers.append(callback) logger.debug("注册环境状态观察者: %s", callback.__name__) def _notify_observers(self): """通知所有观察者状态变更""" for observer in self.observers: try: observer(self.state) except Exception as e: logger.error("通知环境观察者失败: %s", str(e)) def _update_loop(self): """环境状态更新循环""" while self.running: try: with self.lock: # 模拟环境变化 self.state['temperature'] = round(20 + 5 * (time.time() % 10) / 10, 1) self.state['humidity'] = round(40 + 10 * (time.time() % 10) / 10, 1) self.state['light_level'] = round(70 + 10 * (time.time() % 10) / 10, 1) self.state['last_updated'] = datetime.datetime.now().isoformat() # 通知观察者 self._notify_observers() except Exception as e: logger.error("环境更新失败: %s", str(e)) time.sleep(1.0) def get_state(self): """获取当前环境状态""" with self.lock: return self.state.copy() def execute_action(self, action, params): """执行环境动作""" logger.info("执行环境动作: %s 参数: %s", action, params) try: if action == "adjust_temperature": return self._adjust_temperature(params) elif action == "adjust_light": return self._adjust_light(params) elif action == "add_object": return self._add_object(params) elif action == "remove_object": return self._remove_object(params) else: logger.warning("未知环境动作: %s", action) return False except Exception as e: logger.error("执行环境动作失败: %s", str(e)) return False def _adjust_temperature(self, params): """调整温度""" value = params.get('value') if value is None: logger.warning("缺少温度值参数") return False try: value = float(value) except ValueError: logger.warning("无效的温度值: %s", value) return False if 10 <= value <= 40: with self.lock: self.state['temperature'] = value return True logger.warning("温度值超出范围 (10-40): %s", value) return False def _adjust_light(self, params): """调整光照强度""" level = params.get('level') if level is None: logger.warning("缺少光照强度参数") return False try: level = float(level) except ValueError: logger.warning("无效的光照强度: %s", level) return False if 0 <= level <= 100: with self.lock: self.state['light_level'] = level return True logger.warning("光照强度超出范围 (0-100): %s", level) return False def _add_object(self, params): """添加环境对象""" obj_name = params.get('name') if not obj_name: logger.warning("缺少对象名称") return False obj_type = params.get('type', 'object') position = params.get('position', 'unknown') # 检查是否已存在 with self.lock: for obj in self.state['objects']: if obj['name'] == obj_name: logger.warning("对象已存在: %s", obj_name) return False # 添加新对象 self.state['objects'].append({ 'name': obj_name, 'type': obj_type, 'position': position, 'added_at': datetime.datetime.now().isoformat() }) return True def _remove_object(self, params): """移除环境对象""" obj_name = params.get('name') if not obj_name: logger.warning("缺少对象名称") return False # 查找并移除对象 with self.lock: for i, obj in enumerate(self.state['objects']): if obj['name'] == obj_name: del self.state['objects'][i] return True logger.warning("未找到对象: %s", obj_name) return False def is_healthy(self): """检查环境健康状态""" # 简单检查:确保所有值在合理范围内 with self.lock: temp = self.state['temperature'] light = self.state['light_level'] if temp < 10 or temp > 40: logger.warning("温度超出健康范围: %s℃", temp) return False if light < 0 or light > 100: logger.warning("光照强度超出健康范围: %s%%", light) return False return self.healthy and self.running # ========== 系统初始化器 ========== class SystemInitializer: """健壮的系统初始化器""" def __init__(self): self.start_time = time.time() self.components = { 'ai_core': None, 'hardware_manager': None, 'life_scheduler': None, 'ai_agent': None, 'environment_manager': None } # 安全获取基础目录 try: self.base_dir = safe_path(system_config.get('BASE_DIR', Path(__file__).parent.parent)) logger.info("系统初始化器创建, 基础目录: %s", self.base_dir) except Exception as e: self.base_dir = Path.cwd().resolve() logger.error("获取基础目录失败, 使用当前目录: %s | 错误: %s", self.base_dir, str(e)) def initialize_system_paths(self): """安全初始化系统路径""" try: # 确保项目根目录在 sys.path 中 root_dir = self.base_dir.parent if self.base_dir.name == "web_ui" else self.base_dir if str(root_dir) not in sys.path: sys.path.insert(0, str(root_dir)) logger.info("项目根目录: %s", root_dir) # 添加子目录 sub_dirs = ['agent', 'core', 'utils', 'config', 'cognitive_arch', 'environment'] for sub_dir in sub_dirs: full_path = root_dir / sub_dir if full_path.exists() and full_path.is_dir(): if str(full_path) not in sys.path: sys.path.insert(0, str(full_path)) logger.info("添加路径: %s", full_path) else: logger.warning("目录不存在: %s - 已跳过", full_path) # 调试输出当前 sys.path logger.debug("当前 sys.path: %s", sys.path) except Exception as e: logger.error("系统路径初始化失败: %s", str(e)) def initialize_environment_manager(self): """初始化环境管理器""" try: self.components['environment_manager'] = EnvironmentManager() self.components['environment_manager'].start() logger.info("环境管理器初始化成功") return self.components['environment_manager'] except Exception as e: logger.error("环境管理器初始化失败: %s", str(e)) logger.error(traceback.format_exc()) logger.warning("环境交互功能将不可用") return None def initialize_ai_core(self): """初始化AI核心""" logger.info("AI核心初始化") # 简化实现 self.components['ai_core'] = type('AICore', (), { 'status': 'running', 'get_state': lambda: { "status": "running", "model": system_config.get('DEFAULT_MODEL', 'gpt-3.5-turbo'), "last_update": datetime.datetime.now().isoformat() } })() return self.components['ai_core'] def initialize_hardware_manager(self): """初始化硬件管理器""" logger.info("硬件管理器初始化") # 简化实现 self.components['hardware_manager'] = type('HardwareManager', (), { 'get_status': lambda: { "cpu_usage": psutil.cpu_percent(), "memory_usage": psutil.virtual_memory().percent, "gpu_usage": 0, "disk_usage": psutil.disk_usage('/').percent, "timestamp": datetime.datetime.now().isoformat() } })() return self.components['hardware_manager'] def initialize_life_scheduler(self): """初始化生活调度器""" logger.info("生活调度器初始化") # 简化实现 self.components['life_scheduler'] = type('LifeScheduler', (), { 'get_status': lambda: { "current_activity": "thinking", "next_activity": "learning", "energy": 85, "last_update": datetime.datetime.now().isoformat() } })() return self.components['life_scheduler'] def initialize_ai_agent(self): """初始化AI智能体""" logger.info("开始初始化AI智能体") try: # 动态导入智能体模块 try: from agent.autonomous_agent import AutonomousAgent logger.info("成功导入 AutonomousAgent 类") except ImportError as e: logger.error("导入 AutonomousAgent 失败: %s", str(e)) logger.error(traceback.format_exc()) raise # 创建智能体实例 self.components['ai_agent'] = AutonomousAgent() logger.info("智能体实例创建成功") # 连接环境管理器 if self.components.get('environment_manager'): self._connect_agent_to_environment() # 启动智能体 self._start_agent_background_tasks() logger.info("AI智能体初始化完成") return True except ImportError: logger.warning("无法导入AutonomousAgent,使用模拟智能体") self._create_mock_agent() return False except Exception as e: logger.error("AI智能体初始化失败: %s", str(e)) logger.error(traceback.format_exc()) self._create_mock_agent() return False def _connect_agent_to_environment(self): """连接智能体到环境管理器""" agent = self.components['ai_agent'] env_manager = self.components['environment_manager'] try: if hasattr(agent, 'set_environment'): agent.set_environment(env_manager) logger.info("已将环境管理器连接到智能体") return True else: logger.warning("智能体没有 set_environment 方法,无法连接环境管理器") return False except Exception as e: logger.error("连接环境管理器失败: %s", str(e)) return False def _start_agent_background_tasks(self): """启动智能体后台任务""" agent = self.components['ai_agent'] try: if hasattr(agent, 'start'): agent.start() logger.info("智能体后台任务已启动") return True else: logger.warning("智能体没有 start 方法,无法启动后台任务") return False except Exception as e: logger.error("启动智能体后台任务失败: %s", str(e)) return False def _create_mock_agent(self): """创建模拟智能体""" logger.warning("使用模拟智能体作为回退方案") self.components['ai_agent'] = type('MockAgent', (), { 'process_input': lambda self, input, user_id: f"智能体初始化失败,使用模拟模式: 收到消息 '{input}'" })() def start_evolution_monitor(self): """启动进化监视器""" logger.info("进化监视器启动") # 简化实现 def monitor(): while True: logger.debug("进化监视器运行中...") time.sleep(60) threading.Thread(target=monitor, daemon=True).start() def initialize_all(self): """初始化所有系统组件""" logger.info("=" * 50) logger.info("开始初始化AI系统") logger.info("=" * 50) self.initialize_system_paths() self.initialize_ai_core() self.initialize_hardware_manager() self.initialize_life_scheduler() self.initialize_ai_agent() self.initialize_environment_manager() self.start_evolution_monitor() logger.info("所有系统组件初始化完成") return self.components # ========== WebSocket处理 ========== def setup_websocket_handlers(socketio, env_manager): if not socketio or not env_manager: return @socketio.on('connect') def handle_connect(): logger.info('客户端已连接') socketio.emit('system_status', {'status': 'ready'}) # 注册环境状态观察者 env_manager.register_observer(lambda state: socketio.emit('environment_update', state)) @socketio.on('disconnect') def handle_disconnect(): logger.info('客户端已断开连接') @socketio.on('user_message') def handle_user_message(data): user_id = data.get('user_id', 'guest') message = data.get('message', '') logger.info("收到来自 %s 的消息: %s", user_id, message) # 使用线程池处理消息 def process_message(): try: components = current_app.config['SYSTEM_COMPONENTS'] if components['ai_agent']: return components['ai_agent'].process_input(message, user_id) else: return f"已收到您的消息: {message}" except Exception as e: logger.error("消息处理失败: %s", str(e)) return "处理消息时出错" future = ThreadPoolExecutor().submit(process_message) try: response = future.result(timeout=10) socketio.emit('agent_response', { 'user_id': user_id, 'response': response }) except TimeoutError: socketio.emit('agent_response', { 'user_id': user_id, 'response': "处理超时,请重试" }) # ========== 路由注册 ========== def register_routes(app): @app.route('/') def home(): """根路由显示欢迎页面""" current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") return render_template('index.html', current_time=current_time, host=request.host, version="1.0") # 环境路由 @app.route('/environment') def environment_view(): return render_template('environment_view.html') @app.route('/api/environment/state', methods=['GET']) def get_environment_state(): env_manager = app.config['SYSTEM_COMPONENTS'].get('environment_manager') if not env_manager: return jsonify({"success": False, "error": "环境管理器未初始化"}), 503 try: state = env_manager.get_state() return jsonify(state) except Exception as e: app.logger.error("获取环境状态失败: %s", traceback.format_exc()) return jsonify({"success": False, "error": str(e)}), 500 @app.route('/api/environment/action', methods=['POST']) def execute_environment_action(): env_manager = app.config['SYSTEM_COMPONENTS'].get('environment_manager') if not env_manager: return jsonify({"success": False, "error": "环境管理器未初始化"}), 503 try: data = request.json action = data.get('action') params = data.get('params', {}) if not action: return jsonify({"success": False, "error": "缺少动作参数"}), 400 success = env_manager.execute_action(action, params) return jsonify({"success": success, "action": action}) except Exception as e: app.logger.error("执行环境动作失败: %s", traceback.format_exc()) return jsonify({"success": False, "error": str(e)}), 500 # 静态文件路由 @app.route('/static/<path:filename>') def static_files(filename): return send_from_directory(app.static_folder, filename) # 健康检查路由 @app.route('/health') def health_check(): components = app.config['SYSTEM_COMPONENTS'] status = { "ai_core": components['ai_core'] is not None, "hardware_manager": components['hardware_manager'] is not None, "life_scheduler": components['life_scheduler'] is not None, "ai_agent": components['ai_agent'] is not None, "environment_manager": components['environment_manager'] and components['environment_manager'].is_healthy(), "timestamp": datetime.datetime.now().isoformat() } return jsonify(status) # 系统状态路由 @app.route('/status') def status(): components = app.config['SYSTEM_COMPONENTS'] system_info = { "uptime": time.time() - app.config['START_TIME'], "ai_core_status": components['ai_core'].get_state() if components['ai_core'] else "uninitialized", "hardware_status": components['hardware_manager'].get_status() if components[ 'hardware_manager'] else "uninitialized", "life_scheduler_status": components['life_scheduler'].get_status() if components[ 'life_scheduler'] else "uninitialized", "environment_status": components['environment_manager'].get_state() if components[ 'environment_manager'] else "uninitialized", "platform": platform.platform(), "python_version": sys.version, "memory_usage": psutil.virtual_memory().percent, "cpu_usage": psutil.cpu_percent(), "thread_count": threading.active_count(), "process_id": os.getpid(), "timestamp": datetime.datetime.now().isoformat() } return jsonify(system_info) # 智能体健康检查路由 @app.route('/agent/health') def agent_health(): agent = app.config['SYSTEM_COMPONENTS'].get('ai_agent') if not agent: return jsonify({"status": "not_initialized"}), 503 try: if hasattr(agent, 'get_status'): status = agent.get_status() return jsonify(status) else: return jsonify({"status": "running", "message": "Mock agent active"}) except Exception as e: return jsonify({"error": str(e)}), 500 # ========== 错误处理 ========== def register_error_handlers(app): @app.errorhandler(404) def page_not_found(e): return render_template('404.html'), 404 @app.errorhandler(500) def internal_server_error(e): return render_template('500.html'), 500 @app.errorhandler(Exception) def handle_general_exception(e): logger.error("未处理异常: %s", str(e)) logger.error(traceback.format_exc()) return render_template('error.html', error=str(e)), 500 # ========== Web应用工厂 ========== def create_app(): # 创建Flask应用 try: template_dir = safe_path(system_config.get('template_dir', Path(__file__).parent / 'templates')) static_dir = safe_path(system_config.get('static_dir', Path(__file__).parent / 'static')) except Exception as e: logger.error("路径配置错误: %s", str(e)) template_dir = Path(__file__).parent / 'templates' static_dir = Path(__file__).parent / 'static' app = Flask( __name__, template_folder=str(template_dir), static_folder=str(static_dir), static_url_path='/static' ) app.secret_key = system_config.get('SECRET_KEY', 'default_secret_key') # 初始化系统组件 try: system_initializer = SystemInitializer() components = system_initializer.initialize_all() app.config['SYSTEM_COMPONENTS'] = components app.config['START_TIME'] = system_initializer.start_time except Exception as e: logger.error("系统初始化失败: %s", str(e)) app.config['SYSTEM_COMPONENTS'] = {} app.config['START_TIME'] = time.time() # 配置SocketIO socketio = None try: from flask_socketio import SocketIO socketio = SocketIO( app, async_mode=system_config.get('ASYNC_MODE', 'threading'), logger=logger.getEffectiveLevel() <= logging.DEBUG, engineio_logger=logger.getEffectiveLevel() <= logging.DEBUG ) env_manager = app.config['SYSTEM_COMPONENTS'].get('environment_manager') if env_manager: setup_websocket_handlers(socketio, env_manager) app.config['SOCKETIO'] = socketio except ImportError: logger.error("未安装flask-socketio,WebSocket功能不可用") except Exception as e: logger.error("SocketIO初始化失败: %s", str(e)) # 注册路由和错误处理 register_routes(app) register_error_handlers(app) return app, socketio # ========== 主程序入口 ========== if __name__ == '__main__': try: app, socketio = create_app() # 服务器配置 host = system_config.get('server.host', '0.0.0.0') port = system_config.get('server.port', 5000) env = os.environ.get('ENV', 'development') # 启动服务器 if env == 'production': # 生产环境使用Waitress服务器 from waitress import serve logger.info("生产服务器启动: http://%s:%s", host, port) serve(app, host=host, port=port, threads=8) else: # 开发环境使用内置服务器 logger.info("开发服务器启动: http://%s:%s", host, port) if socketio: socketio.run( app, host=host, port=port, debug=system_config.get('DEBUG', False), use_reloader=False ) else: app.run( host=host, port=port, debug=system_config.get('DEBUG', False), use_reloader=False ) except Exception as e: logger.critical("服务器启动失败: %s", str(e)) logger.critical(traceback.format_exc())
最新发布
08-13
烦 优化好的完整版发我 我不会改# E:\AI_System\web_ui\server.py import sys import os import time import logging import json import traceback import threading import platform import psutil import datetime from pathlib import Path from functools import wraps from concurrent.futures import ThreadPoolExecutor import logging.handlers # 在导入其他模块前添加核心配置路径 sys.path.insert(0, str(Path(__file__).parent.parent / 'core')) from core.config import CoreConfig as SystemConfig # 全局配置实例 system_config = SystemConfig() # 初始化日志系统 # E:\AI_System\web_ui\server.py # E:\AI_System\web_ui\server.py import logging from logging.handlers import RotatingFileHandler from flask import Flask from core import system_config, env_manager def setup_logger() -> logging.Logger: """配置并返回日志系统""" logger = logging.getLogger('WebServer') # 清除所有现有处理器,避免重复日志 for handler in logger.handlers[:]: logger.removeHandler(handler) # 安全获取配置项 debug_mode = system_config.get('DEBUG', False) log_level = logging.DEBUG if debug_mode else logging.INFO log_file = system_config.get('logging.file', 'web_server.log') max_log_size = system_config.get('logging.max_size', 10) # MB backup_count = system_config.get('logging.backup_count', 5) # 设置日志级别 logger.setLevel(log_level) # 创建控制台处理器 console_handler = logging.StreamHandler() console_handler.setLevel(log_level) # 创建文件处理器(带日志轮转) file_handler = RotatingFileHandler( filename=log_file, maxBytes=max_log_size * 1024 * 1024, # MB to bytes backupCount=backup_count, encoding='utf-8' ) file_handler.setLevel(logging.DEBUG) # 文件记录所有调试信息 # 创建格式化器 formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(process)d - %(thread)d - %(message)s', datefmt='%Y-%m-%d %H:%M:%S' ) # 应用格式化器 console_handler.setFormatter(formatter) file_handler.setFormatter(formatter) # 添加处理器 logger.addHandler(console_handler) logger.addHandler(file_handler) # 设置根日志器 root_logger = logging.getLogger() root_logger.setLevel(log_level) root_logger.addHandler(console_handler) root_logger.addHandler(file_handler) # 配置第三方库日志器 third_party_loggers = ['werkzeug', 'engineio', 'socketio', 'urllib3'] for log_name in third_party_loggers: lib_logger = logging.getLogger(log_name) lib_logger.setLevel(logging.WARNING) # 只记录警告及以上 lib_logger.propagate = False # 不传播给根日志器 lib_logger.addHandler(file_handler) # 只记录到文件 # 记录日志系统初始化完成 logger.info("✅ 日志系统初始化完成") logger.info(f"📝 日志级别: {'DEBUG' if debug_mode else 'INFO'}") logger.info(f"📁 日志文件: {log_file}") return logger # 初始化Flask应用 app = Flask(__name__) app.debug = system_config.get('DEBUG', False) # 初始化日志系统 logger = setup_logger() # 环境管理器使用示例 def create_environment(): """创建新环境示例""" try: env_name = "production" env_config = { "python_version": "3.9", "packages": ["flask", "numpy", "pandas"], "system_dependencies": ["libssl-dev", "zlib1g-dev"] } env_path = env_manager.create_environment(env_name, env_config) logger.info(f"✅ 创建环境 '{env_name}' 成功 | 路径: {env_path}") # 激活环境 env_manager.activate_environment(env_name) logger.info(f"🔌 已激活环境 '{env_name}'") except Exception as e: logger.error(f"❌ 环境创建失败: {str(e)}") # 发送错误通知 send_error_notification(f"环境创建失败: {str(e)}") # 启动时创建环境 if __name__ == "__main__": create_environment() app.run(host=system_config.get('server.host', '0.0.0.0'), port=system_config.get('server.port', 5000)) def setup_logger(): """配置日志系统""" logger = logging.getLogger('WebServer') # 安全获取 DEBUG 配置 debug_mode = system_config.get('DEBUG', False) # 设置日志级别 logger.setLevel(logging.DEBUG if debug_mode else logging.INFO) # 创建控制台处理器 console_handler = logging.StreamHandler() console_handler.setLevel(logging.DEBUG if debug_mode else logging.INFO) # 创建文件处理器 log_file = system_config.get('logging.file', 'web_server.log') file_handler = logging.FileHandler(log_file, encoding='utf-8') file_handler.setLevel(logging.DEBUG) # 创建格式化器 formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S' ) console_handler.setFormatter(formatter) file_handler.setFormatter(formatter) # 添加处理器 logger.addHandler(console_handler) logger.addHandler(file_handler) # 设置全局日志级别 logging.basicConfig( level=logging.DEBUG if debug_mode else logging.INFO, handlers=[console_handler, file_handler] ) return logger # 在文件开头导入系统配置 from core import system_config # 使用配置设置 Flask 调试模式 app = Flask(__name__) app.debug = system_config.get('DEBUG', False) # ... 其他代码 ... # 设置其他日志器 for log_name in ['werkzeug', 'engineio', 'socketio']: lib_logger = logging.getLogger(log_name) lib_logger.setLevel(logging.WARNING) lib_logger.propagate = False lib_logger.addHandler(file_handler) lib_logger.addHandler(console_handler) return logger # 全局日志实例 logger = setup_logger() # ========== 环境管理器重构 ========== class EnvironmentManager: """重构后的环境管理器""" def __init__(self): self.state = { 'temperature': 22.5, 'humidity': 45.0, 'light_level': 75, 'objects': [], 'last_updated': datetime.datetime.now().isoformat() } self.healthy = True self.lock = threading.Lock() self.running = False self.update_thread = None self.observers = [] # 状态变更观察者 def start(self): """启动环境状态更新线程""" if self.running: return self.running = True self.update_thread = threading.Thread(target=self._update_loop, daemon=True) self.update_thread.start() logger.info("✅ 环境管理器已启动") def stop(self): """停止环境管理器""" self.running = False if self.update_thread: self.update_thread.join(timeout=5) logger.info("🛑 环境管理器已停止") def register_observer(self, callback): """注册状态变更观察者""" self.observers.append(callback) logger.debug(f"注册环境状态观察者: {callback.__name__}") def _notify_observers(self): """通知所有观察者状态变更""" for observer in self.observers: try: observer(self.state) except Exception as e: logger.error(f"通知环境观察者失败: {str(e)}") def _update_loop(self): """环境状态更新循环""" while self.running: try: with self.lock: # 模拟环境变化 self.state['temperature'] = round(20 + 5 * (time.time() % 10) / 10, 1) self.state['humidity'] = round(40 + 10 * (time.time() % 10) / 10, 1) self.state['light_level'] = round(70 + 10 * (time.time() % 10) / 10, 1) self.state['last_updated'] = datetime.datetime.now().isoformat() # 通知观察者 self._notify_observers() except Exception as e: logger.error(f"环境更新失败: {str(e)}") time.sleep(1.0) def get_state(self): """获取当前环境状态""" with self.lock: return self.state.copy() def execute_action(self, action, params): """执行环境动作""" logger.info(f"执行环境动作: {action} 参数: {params}") try: if action == "adjust_temperature": return self._adjust_temperature(params) elif action == "adjust_light": return self._adjust_light(params) elif action == "add_object": return self._add_object(params) elif action == "remove_object": return self._remove_object(params) else: logger.warning(f"未知环境动作: {action}") return False except Exception as e: logger.error(f"执行环境动作失败: {str(e)}") return False def _adjust_temperature(self, params): """调整温度""" value = params.get('value') if value is None: logger.warning("缺少温度值参数") return False try: value = float(value) except ValueError: logger.warning(f"无效的温度值: {value}") return False if 10 <= value <= 40: with self.lock: self.state['temperature'] = value return True logger.warning(f"温度值超出范围 (10-40): {value}") return False def _adjust_light(self, params): """调整光照强度""" level = params.get('level') if level is None: logger.warning("缺少光照强度参数") return False try: level = float(level) except ValueError: logger.warning(f"无效的光照强度: {level}") return False if 0 <= level <= 100: with self.lock: self.state['light_level'] = level return True logger.warning(f"光照强度超出范围 (0-100): {level}") return False def _add_object(self, params): """添加环境对象""" obj_name = params.get('name') if not obj_name: logger.warning("缺少对象名称") return False obj_type = params.get('type', 'object') position = params.get('position', 'unknown') # 检查是否已存在 with self.lock: for obj in self.state['objects']: if obj['name'] == obj_name: logger.warning(f"对象已存在: {obj_name}") return False # 添加新对象 self.state['objects'].append({ 'name': obj_name, 'type': obj_type, 'position': position, 'added_at': datetime.datetime.now().isoformat() }) return True def _remove_object(self, params): """移除环境对象""" obj_name = params.get('name') if not obj_name: logger.warning("缺少对象名称") return False # 查找并移除对象 with self.lock: for i, obj in enumerate(self.state['objects']): if obj['name'] == obj_name: del self.state['objects'][i] return True logger.warning(f"未找到对象: {obj_name}") return False def is_healthy(self): """检查环境健康状态""" # 简单检查:确保所有值在合理范围内 with self.lock: temp = self.state['temperature'] light = self.state['light_level'] if temp < 10 or temp > 40: logger.warning(f"温度超出健康范围: {temp}℃") return False if light < 0 or light > 100: logger.warning(f"光照强度超出健康范围: {light}%") return False return self.healthy and self.running # ========== 系统初始化器重构 ========== class SystemInitializer: """重构后的系统初始化器""" def __init__(self): self.start_time = time.time() self.components = { 'ai_core': None, 'hardware_manager': None, 'life_scheduler': None, 'ai_agent': None, 'environment_manager': None } logger.info(f"系统初始化器创建, 基础目录: {system_config.BASE_DIR}") def initialize_system_paths(self): """初始化系统路径""" # 添加项目根目录到 sys.path if str(system_config.BASE_DIR) not in sys.path: sys.path.insert(0, str(system_config.BASE_DIR)) logger.info(f"项目根目录: {system_config.BASE_DIR}") # 添加子目录 sub_dirs = ['agent', 'core', 'utils', 'config', 'cognitive_arch', 'environment'] for sub_dir in sub_dirs: full_path = system_config.BASE_DIR / sub_dir if full_path.exists() and full_path.is_dir(): if str(full_path) not in sys.path: sys.path.insert(0, str(full_path)) logger.info(f"添加路径: {full_path}") else: logger.warning(f"目录不存在: {full_path} - 已跳过") def initialize_environment_manager(self): """初始化环境管理器""" try: self.components['environment_manager'] = EnvironmentManager() self.components['environment_manager'].start() logger.info("✅ 环境管理器初始化成功") return self.components['environment_manager'] except Exception as e: logger.error(f"❌ 环境管理器初始化失败: {str(e)}") logger.error(traceback.format_exc()) logger.warning("⚠️ 环境交互功能将不可用") return None def initialize_ai_core(self): """初始化AI核心""" logger.info("✅ AI核心初始化") # 简化实现 self.components['ai_core'] = type('AICore', (), { 'status': 'running', 'get_state': lambda: { "status": "running", "model": system_config.DEFAULT_MODEL, "last_update": datetime.datetime.now().isoformat() } })() return self.components['ai_core'] def initialize_hardware_manager(self): """初始化硬件管理器""" logger.info("✅ 硬件管理器初始化") # 简化实现 self.components['hardware_manager'] = type('HardwareManager', (), { 'get_status': lambda: { "cpu_usage": psutil.cpu_percent(), "memory_usage": psutil.virtual_memory().percent, "gpu_usage": 0, "disk_usage": psutil.disk_usage('/').percent, "timestamp": datetime.datetime.now().isoformat() } })() return self.components['hardware_manager'] def initialize_life_scheduler(self): """初始化生活调度器""" logger.info("✅ 生活调度器初始化") # 简化实现 self.components['life_scheduler'] = type('LifeScheduler', (), { 'get_status': lambda: { "current_activity": "thinking", "next_activity": "learning", "energy": 85, "last_update": datetime.datetime.now().isoformat() } })() return self.components['life_scheduler'] def initialize_ai_agent(self): """初始化AI智能体""" logger.info("🚀 开始初始化AI智能体") try: # 动态导入智能体模块 from agent.autonomous_agent import AutonomousAgent # 创建智能体实例 self.components['ai_agent'] = AutonomousAgent() # 将环境管理器传递给智能体(如果存在) if self.components['environment_manager']: # 检查智能体是否有设置环境的方法 if hasattr(self.components['ai_agent'], 'set_environment'): self.components['ai_agent'].set_environment( self.components['environment_manager'] ) logger.info("✅ 已将环境管理器连接到智能体") else: logger.warning("智能体没有set_environment方法,无法连接环境管理器") # 启动智能体后台任务 if hasattr(self.components['ai_agent'], 'start'): self.components['ai_agent'].start() logger.info("🚦 智能体后台任务已启动") else: logger.warning("智能体没有start方法,无法启动后台任务") logger.info("✅ AI智能体初始化完成") return True except Exception as e: logger.error(f"❌ AI智能体初始化失败: {str(e)}") logger.error(traceback.format_exc()) # 创建回退的模拟智能体 logger.warning("⚠️ 使用模拟智能体作为回退方案") self.components['ai_agent'] = type('MockAgent', (), { 'process_input': lambda self, input, user_id: f"智能体初始化失败,使用模拟模式: 收到消息 '{input}'" })() return False def start_evolution_monitor(self): """启动进化监视器""" logger.info("✅ 进化监视器启动") # 简化实现 def monitor(): while True: logger.debug("进化监视器运行中...") time.sleep(60) threading.Thread(target=monitor, daemon=True).start() def initialize_all(self): """初始化所有系统组件""" logger.info("=" * 50) logger.info("🚀 开始初始化AI系统") logger.info("=" * 50) self.initialize_system_paths() self.initialize_ai_core() self.initialize_hardware_manager() self.initialize_life_scheduler() self.initialize_ai_agent() self.initialize_environment_manager() self.start_evolution_monitor() logger.info("✅ 所有系统组件初始化完成") return self.components # ========== Web应用工厂重构 ========== def create_app(): # 创建Flask应用 app = Flask( __name__, template_folder=str(system_config.TEMPLATE_DIR), static_folder=str(system_config.STATIC_DIR), static_url_path='/static' ) app.secret_key = system_config.SECRET_KEY # 初始化限流器 limiter = Limiter( key_func=get_remote_address, app=app, default_limits=["200 per day", "50 per hour"], storage_uri="memory://" ) app.config['LIMITER'] = limiter # 初始化系统组件 system_initializer = SystemInitializer() components = system_initializer.initialize_all() app.config['SYSTEM_COMPONENTS'] = components app.config['START_TIME'] = system_initializer.start_time # 配置SocketIO socketio = SocketIO( app, async_mode=system_config.ASYNC_MODE, logger=logger.getEffectiveLevel() <= logging.DEBUG, engineio_logger=logger.getEffectiveLevel() <= logging.DEBUG ) setup_websocket_handlers(socketio, components['environment_manager']) app.config['SOCKETIO'] = socketio # 注册路由和错误处理 register_routes(app) register_error_handlers(app) # 创建基础模板文件 create_base_templates() return app, socketio # ========== WebSocket处理 ========== def setup_websocket_handlers(socketio, env_manager): @socketio.on('connect') def handle_connect(): logger.info('客户端已连接') socketio.emit('system_status', {'status': 'ready'}) # 注册环境状态观察者 if env_manager: env_manager.register_observer(lambda state: socketio.emit('environment_update', state)) @socketio.on('disconnect') def handle_disconnect(): logger.info('客户端已断开连接') @socketio.on('user_message') def handle_user_message(data): user_id = data.get('user_id', 'guest') message = data.get('message', '') logger.info(f"收到来自 {user_id} 的消息: {message}") # 使用线程池处理消息 def process_message(): try: components = current_app.config['SYSTEM_COMPONENTS'] if components['ai_agent']: return components['ai_agent'].process_input(message, user_id) else: return f"已收到您的消息: {message}" except Exception as e: logger.error(f"消息处理失败: {str(e)}") return "处理消息时出错" future = ThreadPoolExecutor().submit(process_message) try: response = future.result(timeout=10) socketio.emit('agent_response', { 'user_id': user_id, 'response': response }) except TimeoutError: socketio.emit('agent_response', { 'user_id': user_id, 'response': "处理超时,请重试" }) # ========== 路由注册 ========== def register_routes(app): @app.route('/') def home(): """根路由显示欢迎页面""" current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") return render_template('index.html', current_time=current_time, host=request.host, version="1.0") # 环境路由 @app.route('/environment') def environment_view(): return render_template('environment_view.html') @app.route('/api/environment/state', methods=['GET']) @app.config['LIMITER'].limit("10 per minute") def get_environment_state(): env_manager = app.config['SYSTEM_COMPONENTS'].get('environment_manager') if not env_manager: return jsonify({"success": False, "error": "环境管理器未初始化"}), 503 try: state = env_manager.get_state() return jsonify(state) except Exception as e: app.logger.error(f"获取环境状态失败: {traceback.format_exc()}") return jsonify({"success": False, "error": str(e)}), 500 @app.route('/api/environment/action', methods=['POST']) @app.config['LIMITER'].limit("5 per minute") def execute_environment_action(): env_manager = app.config['SYSTEM_COMPONENTS'].get('environment_manager') if not env_manager: return jsonify({"success": False, "error": "环境管理器未初始化"}), 503 try: data = request.json action = data.get('action') params = data.get('params', {}) if not action: return jsonify({"success": False, "error": "缺少动作参数"}), 400 success = env_manager.execute_action(action, params) return jsonify({"success": success, "action": action}) except Exception as e: app.logger.error(f"执行环境动作失败: {traceback.format_exc()}") return jsonify({"success": False, "error": str(e)}), 500 # 静态文件路由 @app.route('/static/<path:filename>') def static_files(filename): return send_from_directory(app.static_folder, filename) # 健康检查路由 @app.route('/health') def health_check(): components = app.config['SYSTEM_COMPONENTS'] status = { "ai_core": components['ai_core'] is not None, "hardware_manager": components['hardware_manager'] is not None, "life_scheduler": components['life_scheduler'] is not None, "ai_agent": components['ai_agent'] is not None, "environment_manager": components['environment_manager'] and components['environment_manager'].is_healthy(), "timestamp": datetime.datetime.now().isoformat() } return jsonify(status) # 系统状态路由 @app.route('/status') @app.config['LIMITER'].exempt def status(): components = app.config['SYSTEM_COMPONENTS'] system_info = { "uptime": time.time() - app.config['START_TIME'], "ai_core_status": components['ai_core'].get_state() if components['ai_core'] else "uninitialized", "hardware_status": components['hardware_manager'].get_status() if components[ 'hardware_manager'] else "uninitialized", "life_scheduler_status": components['life_scheduler'].get_status() if components[ 'life_scheduler'] else "uninitialized", "environment_status": components['environment_manager'].get_state() if components[ 'environment_manager'] else "uninitialized", "platform": platform.platform(), "python_version": sys.version, "memory_usage": psutil.virtual_memory().percent, "cpu_usage": psutil.cpu_percent(), "thread_count": threading.active_count(), "process_id": os.getpid(), "timestamp": datetime.datetime.now().isoformat() } return jsonify(system_info) # 其他路由保持不变... # ========== 主程序入口 ========== if __name__ == '__main__': app, socketio = create_app() # 启动服务器 if os.environ.get('ENV') == 'production': # 生产环境使用Waitress服务器 from waitress import serve logger.info(f"🚀 生产服务器启动: http://{system_config.HOST}:{system_config.PORT}") serve(app, host=system_config.HOST, port=system_config.PORT, threads=8) else: # 开发环境使用内置服务器 logger.info(f"🚀 开发服务器启动: http://{system_config.HOST}:{system_config.PORT}") socketio.run( app, host=system_config.HOST, port=system_config.PORT, debug=system_config.DEBUG, use_reloader=False )
08-13
我已经发了你三遍serber.py了 为什么你还是看不见??????# E:\AI_System\web_ui\server.py (完整修复版) import sys import os import time import logging import json import traceback import threading import platform import psutil import datetime import subprocess from pathlib import Path from functools import wraps from concurrent.futures import ThreadPoolExecutor import logging.handlers # ========== 关键修复1: 最先执行eventlet猴子补丁 ========== try: import eventlet eventlet.monkey_patch() # 必须在所有导入之前执行 print("✅ Eventlet monkey patch applied at startup") except ImportError: print("⚠️ Eventlet not installed, using threading mode") pass # 修复1:更新依赖包列表 REQUIRED_PACKAGES = [ 'flask', 'flask_socketio', 'flask_limiter', 'psutil', 'eventlet', 'waitress' ] def check_dependencies(): """增强依赖检查功能""" missing = [] for package in REQUIRED_PACKAGES: try: __import__(package) except ImportError: missing.append(package) if missing: print(f"❌ 缺少必要的依赖包: {', '.join(missing)}") print("请运行以下命令安装依赖:") print(f"pip install {' '.join(missing)}") sys.exit(1) if __name__ == '__main__': check_dependencies() # 在启动前检查依赖 # 现在导入其他模块 from flask import Flask, jsonify, request, render_template from flask_socketio import SocketIO, emit from flask_limiter import Limiter from flask_limiter.util import get_remote_address # ========== 配置系统 ========== class SystemConfig: def __init__(self): self.BASE_DIR = Path(__file__).resolve().parent.parent self.HOST = '0.0.0.0' self.PORT = 5000 self.LOG_LEVEL = 'DEBUG' self.SECRET_KEY = os.getenv('SECRET_KEY', 'your_secret_key_here') self.DEBUG = True self.USE_GPU = False self.DEFAULT_MODEL = 'gpt-3.5-turbo' self.MAX_WORKERS = 4 # 目录配置 self.LOG_DIR = self.BASE_DIR / 'logs' self.LOG_DIR.mkdir(parents=True, exist_ok=True) self.CONFIG_DIR = self.BASE_DIR / 'config' self.CONFIG_DIR.mkdir(parents=True, exist_ok=True) self.AGENT_PATH = self.BASE_DIR / 'agent' self.MODEL_CACHE_DIR = self.BASE_DIR / 'model_cache' self.MODEL_CACHE_DIR.mkdir(parents=True, exist_ok=True) self.TEMPLATE_DIR = self.BASE_DIR / 'web_ui' / 'templates' def __str__(self): return f"SystemConfig(HOST={self.HOST}, PORT={self.PORT})" config = SystemConfig() # ========== 全局协调器 ========== coordinator = None executor = ThreadPoolExecutor(max_workers=config.MAX_WORKERS) def register_coordinator(coord): global coordinator coordinator = coord if coordinator and hasattr(coordinator, 'connect_to_ui'): coordinator.connect_to_ui(update_ui) def update_ui(event): if 'socketio' in globals(): socketio.emit('system_event', event) # ========== 线程安全装饰器 ========== def synchronized(lock): def decorator(func): @wraps(func) def wrapper(*args, **kwargs): with lock: return func(*args, **kwargs) return wrapper return decorator # ========== 日志系统 ========== def setup_logger(): """优化日志配置""" logger = logging.getLogger('WebServer') logger.setLevel(getattr(logging, config.LOG_LEVEL.upper(), logging.DEBUG)) # 清除所有现有处理器 for handler in logger.handlers[:]: logger.removeHandler(handler) # 日志格式 log_formatter = logging.Formatter( '%(asctime)s [%(levelname)s] %(name)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S' ) # 文件日志处理器 (每天轮换,保留30天) file_handler = logging.handlers.TimedRotatingFileHandler( config.LOG_DIR / 'web_server.log', when='midnight', backupCount=30, encoding='utf-8' ) file_handler.setFormatter(log_formatter) logger.addHandler(file_handler) # 控制台日志处理器 console_handler = logging.StreamHandler() console_handler.setFormatter(log_formatter) logger.addHandler(console_handler) # 设置Flask和SocketIO日志 flask_logger = logging.getLogger('werkzeug') flask_logger.setLevel(logging.WARNING) socketio_logger = logging.getLogger('engineio') socketio_logger.setLevel(logging.WARNING) return logger logger = setup_logger() # ========== 环境管理器 ========== class EnvironmentManager: """独立的环境管理器类""" def __init__(self, config): self.config = config self.state = { 'temperature': 22.5, 'humidity': 45.0, 'light_level': 75, 'objects': [], 'last_updated': datetime.datetime.now().isoformat() } self.healthy = True self.lock = threading.Lock() @synchronized(threading.Lock()) def start(self): logger.info("环境管理器已启动") @synchronized(threading.Lock()) def get_state(self): # 更新模拟数据 self.state['temperature'] = round(20 + 5 * (time.time() % 10) / 10, 1) self.state['humidity'] = round(40 + 10 * (time.time() % 10) / 10, 1) self.state['light_level'] = round(70 + 10 * (time.time() % 10) / 10, 1) self.state['last_updated'] = datetime.datetime.now().isoformat() return self.state @synchronized(threading.Lock()) def execute_action(self, action, params): logger.info(f"执行环境动作: {action} 参数: {params}") if action == "adjust_temperature": self.state['temperature'] = params.get('value', 22.0) return True elif action == "adjust_light": self.state['light_level'] = params.get('level', 70) return True return False def is_healthy(self): return self.healthy # ========== 系统初始化 ========== class SystemInitializer: def __init__(self): self.base_dir = Path(__file__).resolve().parent.parent self.ai_core = None self.hardware_manager = None self.life_scheduler = None self.ai_agent = None self.start_time = time.time() self.environment_manager = None self.life_lock = threading.Lock() def initialize_system_paths(self): sys.path.insert(0, str(self.base_dir)) logger.info(f"项目根目录: {self.base_dir}") sub_dirs = ['agent', 'core', 'utils', 'config', 'cognitive_arch', 'environment'] for sub_dir in sub_dirs: full_path = self.base_dir / sub_dir if full_path.exists(): sys.path.insert(0, str(full_path)) logger.info(f"添加路径: {full_path}") else: logger.warning(f"目录不存在: {full_path} - 已跳过") def initialize_environment_manager(self): try: env_config = {'update_interval': 1.0, 'spatial': {'grid_size': 1.0}} self.environment_manager = EnvironmentManager(env_config) self.environment_manager.start() logger.info("✅ 环境管理器初始化成功") return self.environment_manager except Exception as e: logger.error(f"❌ 环境管理器初始化失败: {str(e)}") logger.warning("⚠️ 环境交互功能将不可用") return None def initialize_ai_core(self): logger.info("✅ 模拟AI核心初始化") self.ai_core = type('AICore', (), { 'status': 'running', 'get_state': lambda: {"status": "running", "model": "gpt-3.5-turbo"} })() def initialize_hardware_manager(self): logger.info("✅ 模拟硬件管理器初始化") self.hardware_manager = type('HardwareManager', (), { 'get_status': lambda: { "cpu_usage": psutil.cpu_percent(), "memory_usage": psutil.virtual_memory().percent, "gpu_usage": 0 } })() @synchronized(lock=threading.Lock()) def initialize_life_scheduler(self): logger.info("✅ 模拟生活调度器初始化") self.life_scheduler = type('LifeScheduler', (), { 'get_status': lambda: { "current_activity": "thinking", "next_activity": "learning", "energy": 85 } })() @synchronized(lock=threading.Lock()) def initialize_ai_agent(self): logger.info("✅ 模拟AI智能体初始化") self.ai_agent = type('AIAgent', (), { 'process_input': lambda self, input, user_id: f"你好{user_id},我收到了你的消息: '{input}'" })() def start_evolution_monitor(self): logger.info("✅ 模拟进化监视器启动") def initialize_all(self): logger.info("=" * 50) logger.info("🚀 开始初始化AI系统") logger.info("=" * 50) self.initialize_system_paths() self.initialize_ai_core() self.initialize_hardware_manager() self.initialize_life_scheduler() self.initialize_ai_agent() self.initialize_environment_manager() self.start_evolution_monitor() logger.info("✅ 所有系统组件初始化完成") return { "ai_core": self.ai_core, "hardware_manager": self.hardware_manager, "life_scheduler": self.life_scheduler, "ai_agent": self.ai_agent, "environment_manager": self.environment_manager } # ========== 环境交互路由 ========== def register_environment_routes(app): @app.route('/environment') def environment_view(): return render_template('environment_view.html') @app.route('/api/environment/state', methods=['GET']) @app.config['LIMITER'].limit("10 per minute") def get_environment_state(): env_manager = app.config['SYSTEM_COMPONENTS'].get('environment_manager') if not env_manager: return jsonify({"success": False, "error": "环境管理器未初始化"}), 503 try: state = env_manager.get_state() return jsonify(state) except Exception as e: app.logger.error(f"获取环境状态失败: {traceback.format_exc()}") return jsonify({"success": False, "error": str(e)}), 500 @app.route('/api/environment/action', methods=['POST']) @app.config['LIMITER'].limit("5 per minute") def execute_environment_action(): env_manager = app.config['SYSTEM_COMPONENTS'].get('environment_manager') if not env_manager: return jsonify({"success": False, "error": "环境管理器未初始化"}), 503 try: data = request.json action = data.get('action') params = data.get('params', {}) if not action: return jsonify({"success": False, "error": "缺少动作参数"}), 400 success = env_manager.execute_action(action, params) return jsonify({"success": success, "action": action}) except Exception as e: app.logger.error(f"执行环境动作失败: {traceback.format_exc()}") return jsonify({"success": False, "error": str(e)}), 500 # ========== 路由注册 ========== def register_routes(app): register_environment_routes(app) # 健康检查路由 @app.route('/health') def health_check(): return jsonify({"status": "healthy", "timestamp": datetime.datetime.now().isoformat()}) # 系统状态路由 @app.route('/status') @app.config['LIMITER'].exempt def status(): components = app.config['SYSTEM_COMPONENTS'] system_info = { "uptime": time.time() - app.config['START_TIME'], "ai_core_status": components['ai_core'].status if components['ai_core'] else "uninitialized", "hardware_status": components['hardware_manager'].get_status() if components[ 'hardware_manager'] else "uninitialized", "life_scheduler_status": components['life_scheduler'].get_status() if components[ 'life_scheduler'] else "uninitialized", "environment_status": components['environment_manager'].is_healthy() if components[ 'environment_manager'] else "uninitialized", "platform": platform.platform(), "python_version": sys.version, "memory_usage": psutil.virtual_memory().percent, "cpu_usage": psutil.cpu_percent(), "thread_count": threading.active_count(), "process_id": os.getpid() } return jsonify(system_info) # 核心系统路由 @app.route('/api/core/state') @app.config['LIMITER'].limit("10 per minute") def get_core_state(): ai_core = app.config['SYSTEM_COMPONENTS'].get('ai_core') if not ai_core: return jsonify({"error": "AI核心未初始化"}), 503 return jsonify(ai_core.get_state()) # 生活系统路由 @app.route('/life/dashboard') def life_dashboard(): return render_template('life_dashboard.html') @app.route('/api/life/status') @app.config['LIMITER'].limit("10 per minute") def get_life_status(): life_scheduler = app.config['SYSTEM_COMPONENTS'].get('life_scheduler') if not life_scheduler: return jsonify({"error": "生活调度器未初始化"}), 503 status = life_scheduler.get_status() return jsonify(status) # 聊天路由 @app.route('/chat', methods=['POST']) @app.config['LIMITER'].limit("30 per minute") def chat(): components = app.config['SYSTEM_COMPONENTS'] if not components['ai_agent']: return jsonify({"error": "Agent未初始化"}), 503 try: data = request.get_json() user_input = data.get('message', '') user_id = data.get('user_id', 'default') if not user_input: return jsonify({"error": "消息内容不能为空"}), 400 app.logger.info(f"聊天请求: 用户={user_id}, 内容长度={len(user_input)}") # 使用线程池异步处理 future = executor.submit(components['ai_agent'].process_input, user_input, user_id) response = future.result(timeout=10) # 10秒超时 return jsonify({"response": response}) except TimeoutError: return jsonify({"error": "处理超时"}), 504 except Exception as e: app.logger.error(f"聊天处理失败: {traceback.format_exc()}") return jsonify({"error": "聊天处理失败", "details": str(e)}), 500 # 404处理 @app.route('/<path:path>') def catch_all(path): return jsonify({"error": "路由不存在", "path": path}), 404 def register_error_handlers(app): @app.errorhandler(404) def not_found_error(error): return jsonify({"error": "资源未找到", "message": str(error)}), 404 @app.errorhandler(500) def internal_error(error): app.logger.error(f"服务器内部错误: {str(error)}") return jsonify({"error": "服务器内部错误", "message": "请查看日志获取详细信息"}), 500 # ========== WebSocket处理 ========== def setup_websocket_handlers(socketio): @socketio.on('connect') def handle_connect(): logger.info('客户端已连接') socketio.emit('system_status', {'status': 'ready'}) @socketio.on('disconnect') def handle_disconnect(): logger.info('客户端已断开连接') @socketio.on('user_message') def handle_user_message(data): user_id = data.get('user_id', 'guest') message = data.get('message', '') logger.info(f"收到来自 {user_id} 的消息: {message}") # 使用线程池处理消息 def process_message(): try: global coordinator if coordinator: return coordinator.process_message(message) else: return f"已收到您的消息: {message}" except Exception as e: logger.error(f"消息处理失败: {str(e)}") return "处理消息时出错" future = executor.submit(process_message) try: response = future.result(timeout=10) socketio.emit('agent_response', { 'user_id': user_id, 'response': response }) except TimeoutError: socketio.emit('agent_response', { 'user_id': user_id, 'response': "处理超时,请重试" }) # ========== 生产环境启动器 ========== def run_production_server(app): try: from waitress import serve logger.info(f"🚀 生产服务器启动: http://{config.HOST}:{config.PORT}") logger.warning("⚠️ 当前运行在生产模式 (Waitress WSGI服务器)") serve(app, host=config.HOST, port=config.PORT, threads=8) except ImportError: logger.error("❌ 缺少生产环境依赖: waitress") logger.info("请运行: pip install waitress") sys.exit(1) # ========== Flask应用工厂 (关键修复) ========== def create_app(): app = Flask( __name__, template_folder=str(config.TEMPLATE_DIR), static_folder='static', static_url_path='/static' ) app.secret_key = config.SECRET_KEY # 初始化限流器 (修复点: 先创建LIMITER并添加到配置) limiter = Limiter( get_remote_address, app=app, default_limits=["200 per day", "50 per hour"], storage_uri="memory://" ) app.config['LIMITER'] = limiter # 关键修复:配置LIMITER system_initializer = SystemInitializer() components = system_initializer.initialize_all() app.config['SYSTEM_COMPONENTS'] = components app.config['START_TIME'] = system_initializer.start_time app.config['BASE_DIR'] = system_initializer.base_dir # 配置SocketIO async_mode = 'threading' try: import eventlet async_mode = 'eventlet' logger.info("✅ 使用eventlet异步模式") except ImportError: logger.warning("⚠️ eventlet未安装,使用threading模式,性能可能受影响") socketio = SocketIO( app, cors_allowed_origins="*", async_mode=async_mode, logger=True, engineio_logger=True ) app.config['SOCKETIO'] = socketio # 注册路由和错误处理 register_routes(app) register_error_handlers(app) return app, socketio # ========== 主程序入口 ========== if __name__ == '__main__': try: app, socketio = create_app() setup_websocket_handlers(socketio) if config.DEBUG: logger.info(f"开发服务器运行在 http://{config.HOST}:{config.PORT}") socketio.run( app, host=config.HOST, port=config.PORT, debug=True, use_reloader=False, log_output=True ) else: run_production_server(app) except KeyboardInterrupt: logger.info("服务器关闭") executor.shutdown(wait=False) except Exception as e: logger.critical(f"服务器启动失败: {str(e)}") logger.error(traceback.format_exc()) executor.shutdown(wait=False) sys.exit(1)
08-12
# E:\AI_System\core\config.py import os import json import logging from pathlib import Path from typing import Dict, Any, Optional, Union import hashlib import sys class CoreConfig: """核心配置管理器 - Windows兼容版""" def __init__(self, config_path: Union[str, Path] = None, env_prefix: str = "", default_config: Dict = None): # 确定基础目录 - 修复AttributeError self.BASE_DIR = self._determine_base_dir() # 初始化参数 self.config_path = Path(config_path) if config_path else None self.env_prefix = env_prefix self.default_config = default_config or {} self._config = { 'BASE_DIR': str(self.BASE_DIR), # 确保BASE_DIR在配置中 'LOG_DIR': str(self.BASE_DIR / "logs"), 'CONFIG_DIR': str(self.BASE_DIR / "config"), 'CACHE_DIR': str(self.BASE_DIR / "cache"), 'DATA_DIR': str(self.BASE_DIR / "data"), 'MODEL_DIR': str(self.BASE_DIR / "models"), } self._last_hash = None # 设置安全的日志器 - 避免Unicode错误 self.logger = self._create_safe_logger() # 初始化配置 self._initialize() def _determine_base_dir(self) -> Path: """确定基础目录""" # 1. 尝试从环境变量获取 base_dir_env = os.getenv(f"{self.env_prefix}BASE_DIR") if base_dir_env: return Path(base_dir_env).resolve() # 2. 尝试基于当前文件位置计算 try: return Path(__file__).parent.parent.resolve() except NameError: # 在交互式环境中运行时 return Path.cwd().resolve() # 3. 默认使用当前工作目录 return Path.cwd().resolve() def _create_safe_logger(self) -> logging.Logger: """创建安全的日志器(Windows兼容)""" logger = logging.getLogger('CoreConfig') logger.setLevel(logging.INFO) # 创建安全的控制台处理器 class SafeConsoleHandler(logging.StreamHandler): def emit(self, record): try: msg = self.format(record) # 替换或移除Windows不支持的Unicode字符 safe_msg = msg.encode('utf-8', errors='replace').decode('utf-8') stream = self.stream stream.write(safe_msg + self.terminator) self.flush() except Exception: self.handleError(record) console_handler = SafeConsoleHandler() console_handler.setFormatter(logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S' )) logger.addHandler(console_handler) return logger def _initialize(self): """初始化配置""" self.logger.info("初始化配置管理器 | 环境前缀: %s | 基础目录: %s", self.env_prefix, self.BASE_DIR) # 加载环境变量 self._load_environment() # 加载配置文件 if self.config_path and self.config_path.exists(): self._load_config_file() elif self.config_path: self.logger.warning("配置文件不存在: %s", self.config_path) # 合并默认配置 self._merge_defaults() # 创建必要目录 self._create_directories() self.logger.info("配置加载完成 | 条目数: %d", len(self._config)) def _load_environment(self): """加载环境变量""" self.logger.info("加载环境变量...") # 加载系统环境变量 for key, value in os.environ.items(): if key.startswith(self.env_prefix): config_key = key[len(self.env_prefix):].lower() self._config[config_key] = value def _load_config_file(self): """加载配置文件""" file_type = self.config_path.suffix.lower() self.logger.info("加载配置文件: %s (类型: %s)", self.config_path, file_type[1:]) try: if file_type == '.json': with open(self.config_path, 'r', encoding='utf-8') as f: config_data = json.load(f) elif file_type in ('.yaml', '.yml'): import yaml with open(self.config_path, 'r', encoding='utf-8') as f: config_data = yaml.safe_load(f) elif file_type == '.ini': import configparser parser = configparser.ConfigParser() parser.read(self.config_path, encoding='utf-8') config_data = {} for section in parser.sections(): config_data[section] = dict(parser.items(section)) else: raise ValueError(f"不支持的配置文件类型: {file_type}") # 合并配置 self._deep_merge(self._config, config_data) self._last_hash = self._calculate_hash() except Exception as e: self.logger.error("加载配置文件失败: %s", str(e)) def _merge_defaults(self): """合并默认配置""" self.logger.info("合并默认配置...") self._deep_merge(self._config, self.default_config) def _deep_merge(self, target: Dict, source: Dict): """深度合并字典""" for key, value in source.items(): if (key in target and isinstance(target[key], dict) and isinstance(value, dict)): self._deep_merge(target[key], value) else: target[key] = value def _calculate_hash(self) -> str: """计算配置哈希值""" return hashlib.md5(json.dumps(self._config, sort_keys=True).encode()).hexdigest() def _create_directories(self): """创建配置中指定的目录""" dir_keys = ['log_dir', 'cache_dir', 'model_dir', 'data_dir'] for key in dir_keys: path = self.get_path(key) if not path.exists(): path.mkdir(parents=True, exist_ok=True) self.logger.info("创建目录: %s", path) def get(self, key: str, default: Any = None) -> Any: """安全获取配置值""" keys = key.split('.') current = self._config for k in keys: if isinstance(current, dict) and k in current: current = current[k] else: return default return current def get_path(self, key: str, default: Optional[Union[str, Path]] = None) -> Path: """获取路径配置项""" path_str = self.get(key, default) if path_str is None: return self.BASE_DIR / "default" # 安全回退 path = Path(path_str) if not path.is_absolute(): return self.BASE_DIR / path return path def __getattr__(self, name: str) -> Any: """支持点操作符访问配置项""" if name in self._config: return self._config[name] # 支持嵌套属性访问 parts = name.split('.') current = self._config for part in parts: if part in current: current = current[part] else: raise AttributeError(f"'{type(self).__name__}' object has no attribute '{name}'") return current # E:\AI_System\web_ui\server.py import sys import os import time import logging import json import traceback import threading import platform import psutil import datetime from pathlib import Path from functools import wraps from concurrent.futures import ThreadPoolExecutor from logging.handlers import RotatingFileHandler # ========== 安全工具函数 ========== def safe_path(path_str: str) -> Path: """安全处理路径字符串,确保跨平台兼容性""" try: path = Path(path_str) if not path.is_absolute(): # 如果路径是相对的,基于项目根目录解析 base_dir = Path(__file__).parent.parent.resolve() return (base_dir / path).resolve() return path.resolve() except Exception as e: logging.error(f"路径解析错误: {path_str} - {str(e)}") return Path.cwd().resolve() class SafeConsoleHandler(logging.StreamHandler): """Windows安全的控制台日志处理器""" def emit(self, record): try: msg = self.format(record) # 安全处理Unicode字符 safe_msg = msg.encode('utf-8', errors='replace').decode('utf-8') stream = self.stream stream.write(safe_msg + self.terminator) self.flush() except Exception: self.handleError(record) # ========== 配置系统初始化 ========== # 添加核心模块路径 sys.path.insert(0, str(Path(__file__).parent.parent)) # 导入核心配置 from core.config import CoreConfig as SystemConfig # 全局配置实例 system_config = SystemConfig() # ========== 安全日志系统 ========== def setup_logger() -> logging.Logger: """配置并返回安全的日志系统""" logger = logging.getLogger('WebServer') # 清除所有现有处理器 for handler in logger.handlers[:]: logger.removeHandler(handler) # 安全获取配置项 debug_mode = system_config.get('DEBUG', False) log_level = logging.DEBUG if debug_mode else logging.INFO log_file = system_config.get('logging.file', 'logs/web_server.log') max_log_size = system_config.get('logging.max_size', 10) # MB backup_count = system_config.get('logging.backup_count', 5) # 设置日志级别 logger.setLevel(log_level) # 创建安全的控制台处理器 console_handler = SafeConsoleHandler() console_handler.setLevel(log_level) # 创建安全的文件处理器 try: # 确保日志目录存在 log_path = safe_path(log_file) log_path.parent.mkdir(parents=True, exist_ok=True) file_handler = RotatingFileHandler( filename=str(log_path), maxBytes=max_log_size * 1024 * 1024, backupCount=backup_count, encoding='utf-8' ) file_handler.setLevel(logging.DEBUG) except Exception as e: logging.error(f"无法创建文件日志处理器: {str(e)}") file_handler = logging.NullHandler() # 创建安全的格式化器 formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(process)d - %(thread)d - %(message)s', datefmt='%Y-%m-%d %H:%M:%S' ) # 应用格式化器 console_handler.setFormatter(formatter) file_handler.setFormatter(formatter) # 添加处理器 logger.addHandler(console_handler) logger.addHandler(file_handler) # 设置根日志器 root_logger = logging.getLogger() root_logger.setLevel(log_level) for handler in root_logger.handlers[:]: root_logger.removeHandler(handler) root_logger.addHandler(console_handler) root_logger.addHandler(file_handler) # 配置第三方库日志器 third_party_loggers = ['werkzeug', 'engineio', 'socketio', 'urllib3'] for log_name in third_party_loggers: lib_logger = logging.getLogger(log_name) lib_logger.setLevel(logging.WARNING) lib_logger.propagate = False lib_logger.addHandler(file_handler) # 安全记录日志系统初始化完成 logger.info("日志系统初始化完成") logger.info("日志级别: %s", 'DEBUG' if debug_mode else 'INFO') logger.info("日志文件: %s", log_file) return logger # 初始化日志系统 logger = setup_logger() # ========== Flask应用初始化 ========== from flask import Flask, render_template, request, jsonify, send_from_directory, current_app # 安全获取模板和静态文件路径 template_dir = safe_path(system_config.get('template_dir', Path(__file__).parent / 'templates')) static_dir = safe_path(system_config.get('static_dir', Path(__file__).parent / 'static')) app = Flask( __name__, template_folder=str(template_dir), static_folder=str(static_dir), static_url_path='/static' ) # 设置Flask调试模式 app.debug = system_config.get('DEBUG', False) app.secret_key = system_config.get('SECRET_KEY', 'default_secret_key') # ========== 环境管理器 ========== class EnvironmentManager: """跨平台兼容的环境管理器""" def __init__(self): self.state = { 'temperature': 22.5, 'humidity': 45.0, 'light_level': 75, 'objects': [], 'last_updated': datetime.datetime.now().isoformat() } self.healthy = True self.lock = threading.Lock() self.running = False self.update_thread = None self.observers = [] logger.info("环境管理器初始化成功") def start(self): """启动环境状态更新线程""" if self.running: return self.running = True self.update_thread = threading.Thread(target=self._update_loop, daemon=True) self.update_thread.start() logger.info("环境管理器已启动") def stop(self): """停止环境管理器""" self.running = False if self.update_thread and self.update_thread.is_alive(): self.update_thread.join(timeout=5) logger.info("环境管理器已停止") def register_observer(self, callback): """注册状态变更观察者""" self.observers.append(callback) logger.debug("注册环境状态观察者: %s", callback.__name__) def _notify_observers(self): """通知所有观察者状态变更""" for observer in self.observers: try: observer(self.state) except Exception as e: logger.error("通知环境观察者失败: %s", str(e)) def _update_loop(self): """环境状态更新循环""" while self.running: try: with self.lock: # 模拟环境变化 self.state['temperature'] = round(20 + 5 * (time.time() % 10) / 10, 1) self.state['humidity'] = round(40 + 10 * (time.time() % 10) / 10, 1) self.state['light_level'] = round(70 + 10 * (time.time() % 10) / 10, 1) self.state['last_updated'] = datetime.datetime.now().isoformat() # 通知观察者 self._notify_observers() except Exception as e: logger.error("环境更新失败: %s", str(e)) time.sleep(1.0) def get_state(self): """获取当前环境状态""" with self.lock: return self.state.copy() def execute_action(self, action, params): """执行环境动作""" logger.info("执行环境动作: %s 参数: %s", action, params) try: if action == "adjust_temperature": return self._adjust_temperature(params) elif action == "adjust_light": return self._adjust_light(params) elif action == "add_object": return self._add_object(params) elif action == "remove_object": return self._remove_object(params) else: logger.warning("未知环境动作: %s", action) return False except Exception as e: logger.error("执行环境动作失败: %s", str(e)) return False def _adjust_temperature(self, params): """调整温度""" value = params.get('value') if value is None: logger.warning("缺少温度值参数") return False try: value = float(value) except ValueError: logger.warning("无效的温度值: %s", value) return False if 10 <= value <= 40: with self.lock: self.state['temperature'] = value return True logger.warning("温度值超出范围 (10-40): %s", value) return False def _adjust_light(self, params): """调整光照强度""" level = params.get('level') if level is None: logger.warning("缺少光照强度参数") return False try: level = float(level) except ValueError: logger.warning("无效的光照强度: %s", level) return False if 0 <= level <= 100: with self.lock: self.state['light_level'] = level return True logger.warning("光照强度超出范围 (0-100): %s", level) return False def _add_object(self, params): """添加环境对象""" obj_name = params.get('name') if not obj_name: logger.warning("缺少对象名称") return False obj_type = params.get('type', 'object') position = params.get('position', 'unknown') # 检查是否已存在 with self.lock: for obj in self.state['objects']: if obj['name'] == obj_name: logger.warning("对象已存在: %s", obj_name) return False # 添加新对象 self.state['objects'].append({ 'name': obj_name, 'type': obj_type, 'position': position, 'added_at': datetime.datetime.now().isoformat() }) return True def _remove_object(self, params): """移除环境对象""" obj_name = params.get('name') if not obj_name: logger.warning("缺少对象名称") return False # 查找并移除对象 with self.lock: for i, obj in enumerate(self.state['objects']): if obj['name'] == obj_name: del self.state['objects'][i] return True logger.warning("未找到对象: %s", obj_name) return False def is_healthy(self): """检查环境健康状态""" # 简单检查:确保所有值在合理范围内 with self.lock: temp = self.state['temperature'] light = self.state['light_level'] if temp < 10 or temp > 40: logger.warning("温度超出健康范围: %s℃", temp) return False if light < 0 or light > 100: logger.warning("光照强度超出健康范围: %s%%", light) return False return self.healthy and self.running # ========== 系统初始化器 ========== class SystemInitializer: """健壮的系统初始化器""" def __init__(self): self.start_time = time.time() self.components = { 'ai_core': None, 'hardware_manager': None, 'life_scheduler': None, 'ai_agent': None, 'environment_manager': None } # 安全获取基础目录 try: self.base_dir = safe_path(system_config.get('BASE_DIR', Path(__file__).parent.parent)) logger.info("系统初始化器创建, 基础目录: %s", self.base_dir) except Exception as e: self.base_dir = Path.cwd().resolve() logger.error("获取基础目录失败, 使用当前目录: %s | 错误: %s", self.base_dir, str(e)) def initialize_system_paths(self): """安全初始化系统路径""" try: # 添加项目根目录到 sys.path if str(self.base_dir) not in sys.path: sys.path.insert(0, str(self.base_dir)) logger.info("项目根目录: %s", self.base_dir) # 添加子目录 sub_dirs = ['agent', 'core', 'utils', 'config', 'cognitive_arch', 'environment'] for sub_dir in sub_dirs: full_path = self.base_dir / sub_dir if full_path.exists() and full_path.is_dir(): if str(full_path) not in sys.path: sys.path.insert(0, str(full_path)) logger.info("添加路径: %s", full_path) else: logger.warning("目录不存在: %s - 已跳过", full_path) except Exception as e: logger.error("系统路径初始化失败: %s", str(e)) def initialize_environment_manager(self): """初始化环境管理器""" try: self.components['environment_manager'] = EnvironmentManager() self.components['environment_manager'].start() logger.info("环境管理器初始化成功") return self.components['environment_manager'] except Exception as e: logger.error("环境管理器初始化失败: %s", str(e)) logger.error(traceback.format_exc()) logger.warning("环境交互功能将不可用") return None def initialize_ai_core(self): """初始化AI核心""" logger.info("AI核心初始化") # 简化实现 self.components['ai_core'] = type('AICore', (), { 'status': 'running', 'get_state': lambda: { "status": "running", "model": system_config.get('DEFAULT_MODEL', 'gpt-3.5-turbo'), "last_update": datetime.datetime.now().isoformat() } })() return self.components['ai_core'] def initialize_hardware_manager(self): """初始化硬件管理器""" logger.info("硬件管理器初始化") # 简化实现 self.components['hardware_manager'] = type('HardwareManager', (), { 'get_status': lambda: { "cpu_usage": psutil.cpu_percent(), "memory_usage": psutil.virtual_memory().percent, "gpu_usage": 0, "disk_usage": psutil.disk_usage('/').percent, "timestamp": datetime.datetime.now().isoformat() } })() return self.components['hardware_manager'] def initialize_life_scheduler(self): """初始化生活调度器""" logger.info("生活调度器初始化") # 简化实现 self.components['life_scheduler'] = type('LifeScheduler', (), { 'get_status': lambda: { "current_activity": "thinking", "next_activity": "learning", "energy": 85, "last_update": datetime.datetime.now().isoformat() } })() return self.components['life_scheduler'] def initialize_ai_agent(self): """初始化AI智能体""" logger.info("开始初始化AI智能体") try: # 动态导入智能体模块 from agent.autonomous_agent import AutonomousAgent # 创建智能体实例 self.components['ai_agent'] = AutonomousAgent() # 将环境管理器传递给智能体(如果存在) if self.components['environment_manager']: # 检查智能体是否有设置环境的方法 if hasattr(self.components['ai_agent'], 'set_environment'): self.components['ai_agent'].set_environment( self.components['environment_manager'] ) logger.info("已将环境管理器连接到智能体") else: logger.warning("智能体没有set_environment方法,无法连接环境管理器") # 启动智能体后台任务 if hasattr(self.components['ai_agent'], 'start'): self.components['ai_agent'].start() logger.info("智能体后台任务已启动") else: logger.warning("智能体没有start方法,无法启动后台任务") logger.info("AI智能体初始化完成") return True except ImportError: logger.warning("无法导入AutonomousAgent,使用模拟智能体") self._create_mock_agent() return False except Exception as e: logger.error("AI智能体初始化失败: %s", str(e)) logger.error(traceback.format_exc()) self._create_mock_agent() return False def _create_mock_agent(self): """创建模拟智能体""" logger.warning("使用模拟智能体作为回退方案") self.components['ai_agent'] = type('MockAgent', (), { 'process_input': lambda self, input, user_id: f"智能体初始化失败,使用模拟模式: 收到消息 '{input}'" })() def start_evolution_monitor(self): """启动进化监视器""" logger.info("进化监视器启动") # 简化实现 def monitor(): while True: logger.debug("进化监视器运行中...") time.sleep(60) threading.Thread(target=monitor, daemon=True).start() def initialize_all(self): """初始化所有系统组件""" logger.info("=" * 50) logger.info("开始初始化AI系统") logger.info("=" * 50) self.initialize_system_paths() self.initialize_ai_core() self.initialize_hardware_manager() self.initialize_life_scheduler() self.initialize_ai_agent() self.initialize_environment_manager() self.start_evolution_monitor() logger.info("所有系统组件初始化完成") return self.components # ========== WebSocket处理 ========== def setup_websocket_handlers(socketio, env_manager): if not socketio or not env_manager: return @socketio.on('connect') def handle_connect(): logger.info('客户端已连接') socketio.emit('system_status', {'status': 'ready'}) # 注册环境状态观察者 env_manager.register_observer(lambda state: socketio.emit('environment_update', state)) @socketio.on('disconnect') def handle_disconnect(): logger.info('客户端已断开连接') @socketio.on('user_message') def handle_user_message(data): user_id = data.get('user_id', 'guest') message = data.get('message', '') logger.info("收到来自 %s 的消息: %s", user_id, message) # 使用线程池处理消息 def process_message(): try: components = current_app.config['SYSTEM_COMPONENTS'] if components['ai_agent']: return components['ai_agent'].process_input(message, user_id) else: return f"已收到您的消息: {message}" except Exception as e: logger.error("消息处理失败: %s", str(e)) return "处理消息时出错" future = ThreadPoolExecutor().submit(process_message) try: response = future.result(timeout=10) socketio.emit('agent_response', { 'user_id': user_id, 'response': response }) except TimeoutError: socketio.emit('agent_response', { 'user_id': user_id, 'response': "处理超时,请重试" }) # ========== 路由注册 ========== def register_routes(app): @app.route('/') def home(): """根路由显示欢迎页面""" current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") return render_template('index.html', current_time=current_time, host=request.host, version="1.0") # 环境路由 @app.route('/environment') def environment_view(): return render_template('environment_view.html') @app.route('/api/environment/state', methods=['GET']) def get_environment_state(): env_manager = app.config['SYSTEM_COMPONENTS'].get('environment_manager') if not env_manager: return jsonify({"success": False, "error": "环境管理器未初始化"}), 503 try: state = env_manager.get_state() return jsonify(state) except Exception as e: app.logger.error("获取环境状态失败: %s", traceback.format_exc()) return jsonify({"success": False, "error": str(e)}), 500 @app.route('/api/environment/action', methods=['POST']) def execute_environment_action(): env_manager = app.config['SYSTEM_COMPONENTS'].get('environment_manager') if not env_manager: return jsonify({"success": False, "error": "环境管理器未初始化"}), 503 try: data = request.json action = data.get('action') params = data.get('params', {}) if not action: return jsonify({"success": False, "error": "缺少动作参数"}), 400 success = env_manager.execute_action(action, params) return jsonify({"success": success, "action": action}) except Exception as e: app.logger.error("执行环境动作失败: %s", traceback.format_exc()) return jsonify({"success": False, "error": str(e)}), 500 # 静态文件路由 @app.route('/static/<path:filename>') def static_files(filename): return send_from_directory(app.static_folder, filename) # 健康检查路由 @app.route('/health') def health_check(): components = app.config['SYSTEM_COMPONENTS'] status = { "ai_core": components['ai_core'] is not None, "hardware_manager": components['hardware_manager'] is not None, "life_scheduler": components['life_scheduler'] is not None, "ai_agent": components['ai_agent'] is not None, "environment_manager": components['environment_manager'] and components['environment_manager'].is_healthy(), "timestamp": datetime.datetime.now().isoformat() } return jsonify(status) # 系统状态路由 @app.route('/status') def status(): components = app.config['SYSTEM_COMPONENTS'] system_info = { "uptime": time.time() - app.config['START_TIME'], "ai_core_status": components['ai_core'].get_state() if components['ai_core'] else "uninitialized", "hardware_status": components['hardware_manager'].get_status() if components[ 'hardware_manager'] else "uninitialized", "life_scheduler_status": components['life_scheduler'].get_status() if components[ 'life_scheduler'] else "uninitialized", "environment_status": components['environment_manager'].get_state() if components[ 'environment_manager'] else "uninitialized", "platform": platform.platform(), "python_version": sys.version, "memory_usage": psutil.virtual_memory().percent, "cpu_usage": psutil.cpu_percent(), "thread_count": threading.active_count(), "process_id": os.getpid(), "timestamp": datetime.datetime.now().isoformat() } return jsonify(system_info) # ========== 错误处理 ========== def register_error_handlers(app): @app.errorhandler(404) def page_not_found(e): return render_template('404.html'), 404 @app.errorhandler(500) def internal_server_error(e): return render_template('500.html'), 500 @app.errorhandler(Exception) def handle_general_exception(e): logger.error("未处理异常: %s", str(e)) logger.error(traceback.format_exc()) return render_template('error.html', error=str(e)), 500 # ========== Web应用工厂 ========== def create_app(): # 创建Flask应用 try: template_dir = safe_path(system_config.get('template_dir', Path(__file__).parent / 'templates')) static_dir = safe_path(system_config.get('static_dir', Path(__file__).parent / 'static')) except Exception as e: logger.error("路径配置错误: %s", str(e)) template_dir = Path(__file__).parent / 'templates' static_dir = Path(__file__).parent / 'static' app = Flask( __name__, template_folder=str(template_dir), static_folder=str(static_dir), static_url_path='/static' ) app.secret_key = system_config.get('SECRET_KEY', 'default_secret_key') # 初始化系统组件 try: system_initializer = SystemInitializer() components = system_initializer.initialize_all() app.config['SYSTEM_COMPONENTS'] = components app.config['START_TIME'] = system_initializer.start_time except Exception as e: logger.error("系统初始化失败: %s", str(e)) app.config['SYSTEM_COMPONENTS'] = {} app.config['START_TIME'] = time.time() # 配置SocketIO socketio = None try: from flask_socketio import SocketIO socketio = SocketIO( app, async_mode=system_config.get('ASYNC_MODE', 'threading'), logger=logger.getEffectiveLevel() <= logging.DEBUG, engineio_logger=logger.getEffectiveLevel() <= logging.DEBUG ) env_manager = app.config['SYSTEM_COMPONENTS'].get('environment_manager') if env_manager: setup_websocket_handlers(socketio, env_manager) app.config['SOCKETIO'] = socketio except ImportError: logger.error("未安装flask-socketio,WebSocket功能不可用") except Exception as e: logger.error("SocketIO初始化失败: %s", str(e)) # 注册路由和错误处理 register_routes(app) register_error_handlers(app) return app, socketio # ========== 主程序入口 ========== if __name__ == '__main__': try: app, socketio = create_app() # 服务器配置 host = system_config.get('server.host', '0.0.0.0') port = system_config.get('server.port', 5000) env = os.environ.get('ENV', 'development') # 启动服务器 if env == 'production': # 生产环境使用Waitress服务器 from waitress import serve logger.info("生产服务器启动: http://%s:%s", host, port) serve(app, host=host, port=port, threads=8) else: # 开发环境使用内置服务器 logger.info("开发服务器启动: http://%s:%s", host, port) if socketio: socketio.run( app, host=host, port=port, debug=system_config.get('DEBUG', False), use_reloader=False ) else: app.run( host=host, port=port, debug=system_config.get('DEBUG', False), use_reloader=False ) except Exception as e: logger.critical("服务器启动失败: %s", str(e)) logger.critical(traceback.format_exc()) Microsoft Windows [版本 10.0.22631.2861] (c) Microsoft Corporation。保留所有权利。 C:\Users\Administrator>cd /d E:\AI_System\web_ui E:\AI_System\web_ui>python server.py Traceback (most recent call last): File "E:\AI_System\web_ui\server.py", line 53, in <module> from core.config import CoreConfig as SystemConfig File "E:\AI_System\core\__init__.py", line 12, in <module> system_config = CoreConfig( File "E:\AI_System\core\config.py", line 19, in __init__ self.BASE_DIR = self._determine_base_dir() File "E:\AI_System\core\config.py", line 44, in _determine_base_dir base_dir_env = os.getenv(f"{self.env_prefix}BASE_DIR") File "E:\AI_System\core\config.py", line 199, in __getattr__ if name in self._config: File "E:\AI_System\core\config.py", line 199, in __getattr__ if name in self._config: File "E:\AI_System\core\config.py", line 199, in __getattr__ if name in self._config: [Previous line repeated 982 more times] RecursionError: maximum recursion depth exceeded E:\AI_System\web_ui>
08-13
<template> <div class="vote-container"> <!-- 消息提示 --> <div v-if="showAlert" :class="['alert', alertType]"> {{ alertMessage }} </div> <!-- 投票人信息 --> <div class="voter-info" v-if="voterName && voterIdCard"> <p>投票人:{{ voterName }}</p> <p>身份证:{{ formattedIdCard }}</p> </div> <!-- 投票统计信息 --> <div class="stats"> <div class="stat"> <h3>经理投票</h3> <div class="progress"> <div class="progress-bar" :style="{ width: (votes.A / 5) * 100 + '%' }"></div> </div> <p>{{ votes.A }} / 5</p> </div> <div class="stat"> <h3>厂长投票</h3> <div class="progress"> <div class="progress-bar" :style="{ width: (votes.B / 5) * 100 + '%' }"></div> </div> <p>{{ votes.B }} / 5</p> </div> <div class="stat"> <h3>副厂长投票</h3> <div class="progress"> <div class="progress-bar" :style="{ width: (votes.C / 15) * 100 + '%' }"></div> </div> <p>{{ votes.C }} / 15</p> </div> <div class="stat"> <h3>总票数</h3> <div class="progress"> <div class="progress-bar" :style="{ width: (totalVotes / 25) * 100 + '%' }"></div> </div> <p>{{ totalVotes }} / 25</p> </div> </div> <!-- 被投票人列表 --> <div class="voters-grid"> <div v-for="voter in voters" :key="voter.id" class="voter-card"> <h4>{{ voter.name }}</h4> <p class="voter-id">ID: {{ voter.id }}</p> <div class="vote-options"> <button @click="castVote(voter, 'A')" :disabled="!canVote(voter, 'A')" :class="{ 'selected': voter.vote === 'A', 'disabled': !canVote(voter, 'A') }" > 经理 </button> <button @click="castVote(voter, 'B')" :disabled="!canVote(voter, 'B')" :class="{ 'selected': voter.vote === 'B', 'disabled': !canVote(voter, 'B') }" > 厂长 </button> <button @click="castVote(voter, 'C')" :disabled="!canVote(voter, 'C')" :class="{ 'selected': voter.vote === 'C', 'disabled': !canVote(voter, 'C') }" > 副厂长 </button> </div> </div> </div> <!-- 操作按钮 --> <div class="action-buttons"> <button @click="submitVotes" :disabled="!hasSelectedCandidates || isSubmitting">提交投票</button> <button @click="resetVotes" :disabled="isSubmitting">重置投票</button> </div> </div> </template> <script setup> import { ref, reactive, computed } from 'vue'; import { useRoute, useRouter} from 'vue-router'; import { onMounted } from 'vue'; const route = useRoute(); const router = useRouter() const voters = ref([]); //候选人 // 使用props接收参数 const props = defineProps({ queryParams: { type: Object, default: () => ({}) } }) // 使用计算属性 const activeSurvey = ref({ surveyId: route.params.surveyId,//调查令 qydcl: route.params.qydcl, dclx: route.query.dclx, tffs: route.query.tffs, bt: route.query.bt }); onMounted(async() => { // 确保路由完全解析完成 await router.isReady() // console.log('当前路由对象:', route) // console.log('路径参数:', route.params) // 获取params参数 // console.log('查询参数:', route.query) // 获取query参数 }); // 添加消息提示状态 const alertMessage = ref(''); const showAlert = ref(false); const alertType = ref(''); // 'success' 或 'error' // 安全序列化函数 function safeStringify(obj) { const seen = new WeakSet(); return JSON.stringify(obj, (key, value) => { if (typeof value === "object" && value !== null) { if (seen.has(value)) { // 检测到循环引用,返回占位符或跳过 return "[Circular Reference Removed]"; } seen.add(value); } return value; }); } // onMounted生命周期钩子 onMounted(async () => { // 从sessionStorage获取投票人信息并立即清除 const voterInfo = sessionStorage.getItem('voterInfo'); if (voterInfo) { const { name, idCard } = JSON.parse(voterInfo); voterName.value = name; voterIdCard.value = idCard; sessionStorage.removeItem('voterInfo'); } // 获取投票详情 const route = useRoute(); // 加载候选人数据 voters.value = await fetchCandidates(); }); // 添加用于存储投票人信息的变量 const voterName = ref(''); const voterIdCard = ref(''); // 格式化身份证显示(安全脱敏) const formattedIdCard = computed(() => { if (!voterIdCard.value) return ''; // 显示前6位和后4位,中间用*代替 return voterIdCard.value.substring(0, 6) + '******' + voterIdCard.value.substring(voterIdCard.value.length - 4); }); onMounted(() => { // 从sessionStorage获取数据并立即清除 const voterInfo = sessionStorage.getItem('voterInfo'); if (voterInfo) { const { name, idCard } = JSON.parse(voterInfo); voterName.value = name; voterIdCard.value = idCard; // 关键:立即清除存储防止数据残留 sessionStorage.removeItem('voterInfo'); } }); //获取候选人明细 const fetchCandidates = async () => { try { const response = await fetch('/api/wechat/getInvestigate', { method: 'POST', body: JSON.stringify({ id: '9', dcl: '123' }) }); // console.log('API响应:', response); const result = await response.json(); if (!result || !result.root) throw new Error('无效API响应'); // 提取候选人数据 const candidateArray = []; let idCounter = 1; // 自增计数器,名称序号 result.root.forEach(rootItem => { if (!rootItem.childEntList) return; rootItem.childEntList.forEach(candidate => { if (!candidate.dcbt || !candidate.dcxbt) return; candidateArray.push({ originalid: candidate.dcbt, name: candidate.dcxbt, vote: null, id:idCounter++, tmlx: candidate.tmlx, // 投票类型 mainId: candidate.mainId // 主ID }); }); }); return candidateArray; } catch (error) { console.error('获取候选人失败:', error); return []; // 返回空数组保持安全 } }; // 新增计算属性 - 获取已选择的候选人 const selectedCandidates = computed(() => { return voters.value .filter(v => v.vote) // 只过滤已投票的 .map(v => ({ id: v.originalid, // 候选人原始ID voteType: v.vote, // 投票类型(A/B/C) voteValue: v.vote === 'A' ? 17 : // 转换类型值 v.vote === 'B' ? 18 : 19, name: v.name, // 候选人姓名 tmlx: v.tmlx // 原始类型 })); }); // 检查是否有选择的候选人 const hasSelectedCandidates = computed(() => { return selectedCandidates.value.length > 0; }); // 投票统计 const votes = reactive({ A: 0, B: 0, C: 0 }); // 计算总票数 const totalVotes = computed(() => { return votes.A + votes.B + votes.C; }); // 投票方法 const canVote = (voter, type) => { // 情况1:用户取消当前选择的类型(总是允许) if (voter.vote === type) return true; // 情况2:用户从其他类型转换到当前类型 if (voter.vote && voter.vote !== type) { if (type === 'A' && votes.A >= 5) return false; if (type === 'B' && votes.B >= 5) return false; if (type === 'C' && votes.C >= 15) return false; } // 情况3:用户首次投票 if (!voter.vote) { if (type === 'A' && votes.A >= 5) return false; if (type === 'B' && votes.B >= 5) return false; if (type === 'C' && votes.C >= 15) return false; if (totalVotes.value >= 25) return false; } return true; }; // 投票方法 const castVote = (voter, type) => { // 如果已投票且点击相同类型,取消投票 if (voter.vote === type) { voter.vote = null; votes[type]--; return; } // 如果之前有投票,先取消 if (voter.vote !== null) { votes[voter.vote]--; } // 投新票 voter.vote = type; votes[type]++; }; //投票人信息 // 添加投票人信息数据模型 const voterInfo = reactive({ name: '', idNumber: '' }); // // 添加基本信息验证 // const isValid = computed(() => { // return voterInfo.name.trim() !== '' && // voterInfo.idNumber.trim() !== '' && // /^\d{17}[\dXx]$/.test(voterInfo.idNumber); // }); // 提交投票 // 防止重复提交 const isSubmitting = ref(false); // 提交投票到API const submitVotes = async () => { // console.log("dclx", activeSurvey.value.dclx); // 添加防御性检查 if (!hasSelectedCandidates.value) { showMessage('请先选择候选人', 'error'); return; } // 防止重复提交 if (isSubmitting.value) return; isSubmitting.value = true; try { const mainData = [ { fieldName: "bt", fieldValue: activeSurvey.value.bt }, { fieldName: "tprxm", fieldValue: voterName.value }, { fieldName: "tprsfz", fieldValue: voterIdCard.value }, { fieldName: "mb", fieldValue: candidate.mainId }, { fieldName: "dclx", fieldValue: activeSurvey.value.dclx }, { fieldName: "tffs", fieldValue: activeSurvey.value.tffs } ]; const workflowRequestTableRecords = selectedCandidates.value.map(candidate => ({ workflowRequestTableFields: [ { fieldName: "dcbt", fieldValue: candidate.originalid }, { fieldName: "tmlx", fieldValue: candidate.tmlx }, { fieldName: "dcxx", fieldValue: candidate.vote === 'A' ? 17 : candidate.vote === 'B' ? 18 : 19 } ] })); console.log('提交数据:', { mainData, workflowRequestTableRecords }); const requestBody = { requestName: activeSurvey.value.bt, // 投票标题 workflowId: 118, // 固定工作流ID mainData, workflowRequestTableRecords }; // 发送POST请求 const response = await fetch('/api/wechat/addInvestigateWorkflow1', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: safeStringify(requestBody)// 使用安全序列化,避免重复引用 }); const result = await response.json(); // 根据 api_status 判断 if (result.api_status === true) { // 成功处理 const successMsg = result.msg || '投票提交成功!'; showMessage('投票提交成功!', 'success'); // 存储已投票标识 localStorage.setItem('voted_' + voterIdCard.value, 'true'); } else { // 处理错误情况 if (result.msg === '你已提交或不满足提交条件') { showMessage(result.msg, 'error'); // 特殊处理:用户已投票,存储标识防止重复提交 localStorage.setItem('voted_' + voterIdCard.value, 'true'); } else { // 其他错误情况 const errorMsg = result.msg ? `提交失败: ${result.msg}` : '未知错误,请稍后重试'; showMessage(errorMsg, 'error'); } } } catch (error) { console.error('网络请求失败:', error); showMessage('网络错误,请检查连接后重试', 'error'); } finally { isSubmitting.value = false; } }; // 重置投票 const resetVotes = () => { if (confirm('确定要重置所有投票吗?')) { voters.value.forEach(voter => { voter.vote = null; }); votes.A = 0; votes.B = 0; votes.C = 0; voterInfo.name = ''; voterInfo.idNumber = ''; } }; //后台响应信息showMessage const showMessage = (message, type = 'error') => { // 更新消息提示状态 alertMessage.value = message; showAlert.value = true; alertType.value = type; // 错误提示停留3秒,成功提示停留2秒 const timeout = type === 'error' ? 3000 : 2000; setTimeout(() => { showAlert.value = false; }, timeout); }; </script> <style scoped> /* 移动端垂直布局 */ @media (max-width: 480px) { .input-group { flex-direction: column; } } /* 平板/桌面端水平布局 */ @media (min-width: 768px) { .input-group { flex-direction: row; } } /* 消息提示样式 */ .alert { padding: 15px; margin-bottom: 20px; border-radius: 4px; text-align: center; position: fixed; top: 20px; left: 50%; transform: translateX(-50%); z-index: 1000; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); min-width: 300px; opacity: 0.95; } .alert.error { background-color: #ffebee; color: #b71c1c; border: 1px solid #ffcdd2; } .alert.success { background-color: #e8f5e9; color: #1b5e20; border: 1px solid #c8e6c9; } .vote-container { max-width: 1200px; margin: 0 auto; padding: 20px; } .stats { display: flex; justify-content: space-between; margin-bottom: 30px; background: #f5f7fa; padding: 20px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); } .stat { flex: 1; text-align: center; padding: 0 15px; } .progress { height: 20px; background: #e0e0e0; border-radius: 10px; margin: 10px 0; overflow: hidden; } .progress-bar { height: 100%; background: #3498db; transition: width 0.3s; } .voters-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 20px; } .voter-card { background: white; border-radius: 8px; padding: 15px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); transition: transform 0.2s; } .voter-card:hover { transform: translateY(-5px); } .voter-id { color: #777; font-size: 0.9rem; margin-bottom: 15px; } .vote-options { display: flex; justify-content: space-between; } .vote-options button { flex: 1; margin: 0 5px; padding: 8px 0; border: none; border-radius: 4px; cursor: pointer; transition: all 0.2s; } .vote-options button:not(.selected):hover { opacity: 0.9; transform: scale(1.05); } .vote-options button:first-child { background: #ff6b6b; color: white; } .vote-options button:nth-child(2) { background: #4ecdc4; color: white; } .vote-options button:last-child { background: #ffd166; color: white; } .selected { border: 2px solid #2c3e50 !important; font-weight: bold; box-shadow: 0 0 2 rgba(61, 60, 60, 0.5); } .disabled { opacity: 0.5 !important; cursor: not-allowed !important; } .action-buttons { margin-top: 30px; display: flex; justify-content: center; gap: 20px; } .action-buttons button { padding: 12px 30px; border: none; border-radius: 6px; cursor: pointer; font-size: 1rem; font-weight: 600; transition: all 0.2s; } .action-buttons button:first-child { background: #3498db; color: white; } .action-buttons button:first-child:disabled { background: #bdc3c7; cursor: not-allowed; } .action-buttons button:last-child { background: #e74c3c; color: white; } .action-buttons button:hover:not(:disabled) { transform: translateY(-2px); box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); } </style>报错:网络请求失败: ReferenceError: candidate is not defined at submitVotes (Vote.vue:341:1)
06-12
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值