use std::any::Any; use std::sync::Arc; use uuid::Uuid; use crate::error::AppResult; use crate::events::EventBus; /// 模块注册接口 /// 所有业务模块(Auth, Workflow, Message, Config, 行业模块)都实现此 trait #[async_trait::async_trait] pub trait ErpModule: Send + Sync { /// 模块名称(唯一标识) fn name(&self) -> &str; /// 模块版本 fn version(&self) -> &str { env!("CARGO_PKG_VERSION") } /// 依赖的其他模块名称 fn dependencies(&self) -> Vec<&str> { vec![] } /// 注册事件处理器 fn register_event_handlers(&self, _bus: &EventBus) {} /// 租户创建时的初始化钩子 async fn on_tenant_created(&self, _tenant_id: Uuid) -> AppResult<()> { Ok(()) } /// 租户删除时的清理钩子 async fn on_tenant_deleted(&self, _tenant_id: Uuid) -> AppResult<()> { Ok(()) } /// Downcast support: return `self` as `&dyn Any` for concrete type access. /// /// This allows the server crate to retrieve module-specific methods /// (e.g. `AuthModule::public_routes()`) that are not part of the trait. fn as_any(&self) -> &dyn Any; } /// 模块注册器 — 用 Arc 包装使其可 Clone(用于 Axum State) #[derive(Clone, Default)] pub struct ModuleRegistry { modules: Arc>>, } impl ModuleRegistry { pub fn new() -> Self { Self { modules: Arc::new(vec![]), } } pub fn register(mut self, module: impl ErpModule + 'static) -> Self { tracing::info!(module = module.name(), version = module.version(), "Module registered"); let mut modules = (*self.modules).clone(); modules.push(Arc::new(module)); self.modules = Arc::new(modules); self } pub fn register_handlers(&self, bus: &EventBus) { for module in self.modules.iter() { module.register_event_handlers(bus); } } pub fn modules(&self) -> &[Arc] { &self.modules } }