Files
hms/crates/erp-plugin/src/module.rs
iven a7a48167ca feat(plugin): P1-P4 审计修复 — 第三批 (配置变更通知 + 自定义视图)
3.1 配置变更通知:
- update_config 增加 EventBus 参数
- 更新成功后发布 plugin.config.updated 事件
- handler 传入 event_bus

3.2 自定义视图:
- plugin_user_views 表迁移 (id/tenant_id/user_id/plugin_id/entity/view_name/view_config/is_default)
- CRUD API: GET/POST /plugins/{id}/{entity}/views, DELETE /plugins/{id}/{entity}/views/{view_id}
- 默认视图互斥逻辑
2026-04-19 18:25:03 +08:00

176 lines
6.5 KiB
Rust

use async_trait::async_trait;
use axum::Router;
use axum::routing::{delete, get, post, put};
use erp_core::module::ErpModule;
pub struct PluginModule;
#[async_trait]
impl ErpModule for PluginModule {
fn name(&self) -> &str {
"plugin"
}
fn dependencies(&self) -> Vec<&str> {
vec!["auth", "config"]
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
}
impl PluginModule {
/// 插件管理路由(需要 JWT 认证)
pub fn protected_routes<S>() -> Router<S>
where
crate::state::PluginState: axum::extract::FromRef<S>,
S: Clone + Send + Sync + 'static,
{
let admin_routes = Router::new()
.route("/admin/plugins/upload", post(crate::handler::plugin_handler::upload_plugin::<S>))
.route("/admin/plugins", get(crate::handler::plugin_handler::list_plugins::<S>))
.route(
"/admin/plugins/{id}",
get(crate::handler::plugin_handler::get_plugin::<S>)
.delete(crate::handler::plugin_handler::purge_plugin::<S>),
)
.route(
"/admin/plugins/{id}/schema",
get(crate::handler::plugin_handler::get_plugin_schema::<S>),
)
.route(
"/admin/plugins/{id}/install",
post(crate::handler::plugin_handler::install_plugin::<S>),
)
.route(
"/admin/plugins/{id}/enable",
post(crate::handler::plugin_handler::enable_plugin::<S>),
)
.route(
"/admin/plugins/{id}/disable",
post(crate::handler::plugin_handler::disable_plugin::<S>),
)
.route(
"/admin/plugins/{id}/uninstall",
post(crate::handler::plugin_handler::uninstall_plugin::<S>),
)
.route(
"/admin/plugins/{id}/health",
get(crate::handler::plugin_handler::health_check_plugin::<S>),
)
.route(
"/admin/plugins/{id}/metrics",
get(crate::handler::plugin_handler::get_plugin_metrics::<S>),
)
.route(
"/admin/plugins/{id}/config",
put(crate::handler::plugin_handler::update_plugin_config::<S>),
)
.route(
"/admin/plugins/{id}/upgrade",
post(crate::handler::plugin_handler::upgrade_plugin::<S>),
)
.route(
"/admin/plugins/{id}/validate",
get(crate::handler::plugin_handler::validate_plugin::<S>),
);
// 插件数据 CRUD 路由
let data_routes = Router::new()
.route(
"/plugins/{plugin_id}/{entity}",
get(crate::handler::data_handler::list_plugin_data::<S>)
.post(crate::handler::data_handler::create_plugin_data::<S>),
)
.route(
"/plugins/{plugin_id}/{entity}/{id}",
get(crate::handler::data_handler::get_plugin_data::<S>)
.put(crate::handler::data_handler::update_plugin_data::<S>)
.patch(crate::handler::data_handler::patch_plugin_data::<S>)
.delete(crate::handler::data_handler::delete_plugin_data::<S>),
)
// 数据统计路由
.route(
"/plugins/{plugin_id}/{entity}/count",
get(crate::handler::data_handler::count_plugin_data::<S>),
)
.route(
"/plugins/{plugin_id}/{entity}/aggregate",
get(crate::handler::data_handler::aggregate_plugin_data::<S>),
)
.route(
"/plugins/{plugin_id}/{entity}/aggregate-multi",
post(crate::handler::data_handler::aggregate_multi_plugin_data::<S>),
)
// 批量操作路由
.route(
"/plugins/{plugin_id}/{entity}/batch",
post(crate::handler::data_handler::batch_plugin_data::<S>),
)
// 时间序列路由
.route(
"/plugins/{plugin_id}/{entity}/timeseries",
get(crate::handler::data_handler::get_plugin_timeseries::<S>),
)
// 跨插件引用:批量标签解析
.route(
"/plugins/{plugin_id}/{entity}/resolve-labels",
post(crate::handler::data_handler::resolve_ref_labels::<S>),
)
// 数据导入导出
.route(
"/plugins/{plugin_id}/{entity}/export",
get(crate::handler::data_handler::export_plugin_data::<S>),
)
.route(
"/plugins/{plugin_id}/{entity}/import",
post(crate::handler::data_handler::import_plugin_data::<S>),
)
// 对账扫描
.route(
"/plugins/{plugin_id}/reconcile",
post(crate::handler::data_handler::reconcile_refs::<S>),
)
// 用户自定义视图
.route(
"/plugins/{plugin_id}/{entity}/views",
get(crate::handler::data_handler::list_user_views::<S>)
.post(crate::handler::data_handler::create_user_view::<S>),
)
.route(
"/plugins/{plugin_id}/{entity}/views/{view_id}",
delete(crate::handler::data_handler::delete_user_view::<S>),
);
// 实体注册表路由
let registry_routes = Router::new()
.route(
"/plugin-registry/entities",
get(crate::handler::data_handler::list_public_entities::<S>),
);
// 市场路由
let market_routes = Router::new()
.route(
"/market/entries",
get(crate::handler::market_handler::list_market_entries::<S>),
)
.route(
"/market/entries/{id}",
get(crate::handler::market_handler::get_market_entry::<S>),
)
.route(
"/market/entries/{id}/install",
post(crate::handler::market_handler::install_from_market::<S>),
)
.route(
"/market/entries/{id}/reviews",
get(crate::handler::market_handler::list_market_reviews::<S>)
.post(crate::handler::market_handler::submit_market_review::<S>),
);
admin_routes.merge(data_routes).merge(registry_routes).merge(market_routes)
}
}