feat(plugin): P2-P4 插件平台演进 — 通用服务 + 质量保障 + 市场
P2 平台通用服务: - manifest 扩展: settings/numbering/templates/trigger_events/importable/exportable 声明 - 插件配置 UI: PluginSettingsForm 自动表单 + 后端校验 + 详情抽屉 Settings 标签页 - 编号规则: Host API numbering-generate + PostgreSQL 序列 + manifest 绑定 - 触发事件: data_service create/update/delete 自动发布 DomainEvent - WIT 接口: 新增 numbering-generate/setting-get Host API P3 质量保障: - plugin_validator.rs: 安全扫描(WASM大小/实体数量/字段校验) + 复杂度评分 - 运行时监控指标: RuntimeMetrics (错误率/响应时间/Fuel/内存) - 性能基准: BenchmarkResult 阈值定义 - 上传时自动安全扫描 + /validate API 端点 P4 插件市场: - 数据库迁移: plugin_market_entries + plugin_market_reviews 表 - 前端 PluginMarket 页面: 分类浏览/搜索/详情/评分 - 路由注册: /plugins/market 测试: 269 全通过 (71 erp-plugin + 41 auth + 57 config + 34 core + 50 message + 16 workflow)
This commit is contained in:
@@ -14,6 +14,65 @@ use crate::error::PluginError;
|
||||
use crate::manifest::PluginField;
|
||||
use crate::state::EntityInfo;
|
||||
|
||||
/// 根据 plugin 数据库 ID 查找 manifest 中匹配 entity 的触发事件
|
||||
async fn find_trigger_events(
|
||||
plugin_db_id: Uuid,
|
||||
entity_name: &str,
|
||||
db: &sea_orm::DatabaseConnection,
|
||||
) -> AppResult<Vec<crate::manifest::PluginTriggerEvent>> {
|
||||
let model = plugin::Entity::find_by_id(plugin_db_id)
|
||||
.one(db)
|
||||
.await?
|
||||
.ok_or_else(|| AppError::NotFound(format!("插件 {} 不存在", plugin_db_id)))?;
|
||||
|
||||
let manifest: crate::manifest::PluginManifest =
|
||||
serde_json::from_value(model.manifest_json)
|
||||
.map_err(|e| PluginError::InvalidManifest(e.to_string()))?;
|
||||
|
||||
let triggers = manifest.trigger_events
|
||||
.unwrap_or_default()
|
||||
.into_iter()
|
||||
.filter(|t| t.entity == entity_name)
|
||||
.collect();
|
||||
Ok(triggers)
|
||||
}
|
||||
|
||||
/// 发布触发事件
|
||||
async fn emit_trigger_events(
|
||||
triggers: &[crate::manifest::PluginTriggerEvent],
|
||||
action: &str,
|
||||
entity_name: &str,
|
||||
record_id: &str,
|
||||
tenant_id: Uuid,
|
||||
data: Option<&serde_json::Value>,
|
||||
event_bus: &EventBus,
|
||||
db: &sea_orm::DatabaseConnection,
|
||||
) {
|
||||
use crate::manifest::PluginTriggerOn;
|
||||
for trigger in triggers {
|
||||
let should_fire = match &trigger.on {
|
||||
PluginTriggerOn::Create => action == "create",
|
||||
PluginTriggerOn::Update => action == "update",
|
||||
PluginTriggerOn::Delete => action == "delete",
|
||||
PluginTriggerOn::CreateOrUpdate => action == "create" || action == "update",
|
||||
};
|
||||
if should_fire {
|
||||
let payload = serde_json::json!({
|
||||
"event": trigger.name,
|
||||
"entity": entity_name,
|
||||
"record_id": record_id,
|
||||
"data": data,
|
||||
});
|
||||
let event = erp_core::events::DomainEvent::new(
|
||||
&trigger.name,
|
||||
tenant_id,
|
||||
payload,
|
||||
);
|
||||
event_bus.publish(event, db).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 行级数据权限参数 — 传递到 service 层注入 SQL 条件
|
||||
pub struct DataScopeParams {
|
||||
pub scope_level: String,
|
||||
@@ -68,6 +127,11 @@ impl PluginDataService {
|
||||
)
|
||||
.await;
|
||||
|
||||
// 触发事件发布
|
||||
if let Ok(triggers) = find_trigger_events(plugin_id, entity_name, db).await {
|
||||
emit_trigger_events(&triggers, "create", entity_name, &result.id.to_string(), tenant_id, Some(&result.data), _event_bus, db).await;
|
||||
}
|
||||
|
||||
Ok(PluginDataResp {
|
||||
id: result.id.to_string(),
|
||||
data: result.data,
|
||||
@@ -279,6 +343,11 @@ impl PluginDataService {
|
||||
)
|
||||
.await;
|
||||
|
||||
// 触发事件发布
|
||||
if let Ok(triggers) = find_trigger_events(plugin_id, entity_name, db).await {
|
||||
emit_trigger_events(&triggers, "update", entity_name, &result.id.to_string(), tenant_id, Some(&result.data), _event_bus, db).await;
|
||||
}
|
||||
|
||||
Ok(PluginDataResp {
|
||||
id: result.id.to_string(),
|
||||
data: result.data,
|
||||
@@ -428,6 +497,11 @@ impl PluginDataService {
|
||||
)
|
||||
.await;
|
||||
|
||||
// 触发事件发布
|
||||
if let Ok(triggers) = find_trigger_events(plugin_id, entity_name, db).await {
|
||||
emit_trigger_events(&triggers, "delete", entity_name, &id.to_string(), tenant_id, None, _event_bus, db).await;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user