feat(plugin): P2-4 数据导入导出 — 后端 export/import API + 前端 UI + TS 修复
- data_service: export 方法查询匹配行(上限10000),import 方法逐行校验+插入 - data_handler: export_plugin_data / import_plugin_data 处理函数 - module: 注册 GET /export + POST /import 路由 - pluginData.ts: exportPluginData / importPluginData API 函数 - PluginCRUDPage: 根据 entity importable/exportable 标志显示导出/导入按钮 - PluginMarket: 修复 TS 错误 (unused imports, type narrowing) - PluginSettingsForm: 修复 TS 错误 (Rule type, Divider orientation)
This commit is contained in:
@@ -9,7 +9,8 @@ use erp_core::types::{ApiResponse, PaginatedResponse, TenantContext};
|
||||
|
||||
use crate::data_dto::{
|
||||
AggregateItem, AggregateMultiReq, AggregateMultiRow, AggregateQueryParams, BatchActionReq,
|
||||
CountQueryParams, CreatePluginDataReq, PatchPluginDataReq, PluginDataListParams,
|
||||
CountQueryParams, CreatePluginDataReq, ExportParams, ImportReq, ImportResult,
|
||||
PatchPluginDataReq, PluginDataListParams,
|
||||
PluginDataResp, PublicEntityResp, ResolveLabelsReq, ResolveLabelsResp,
|
||||
TimeseriesItem, TimeseriesParams, UpdatePluginDataReq,
|
||||
};
|
||||
@@ -780,3 +781,95 @@ where
|
||||
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
// ─── 数据导入导出 ──────────────────────────────────────────────────────
|
||||
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/api/v1/plugins/{plugin_id}/{entity}/export",
|
||||
params(ExportParams),
|
||||
responses(
|
||||
(status = 200, description = "导出成功"),
|
||||
),
|
||||
security(("bearer_auth" = [])),
|
||||
tag = "插件数据"
|
||||
)]
|
||||
/// GET /api/v1/plugins/{plugin_id}/{entity}/export — 导出数据
|
||||
pub async fn export_plugin_data<S>(
|
||||
State(state): State<PluginState>,
|
||||
Extension(ctx): Extension<TenantContext>,
|
||||
Path((plugin_id, entity)): Path<(Uuid, String)>,
|
||||
Query(params): Query<ExportParams>,
|
||||
) -> Result<Json<ApiResponse<Vec<serde_json::Value>>>, AppError>
|
||||
where
|
||||
PluginState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
let manifest_id = resolve_manifest_id(plugin_id, ctx.tenant_id, &state.db).await?;
|
||||
let fine_perm = compute_permission_code(&manifest_id, &entity, "list");
|
||||
require_permission(&ctx, &fine_perm)?;
|
||||
|
||||
let scope = resolve_data_scope(
|
||||
&ctx, &manifest_id, &entity, &fine_perm, &state.db,
|
||||
).await?;
|
||||
|
||||
let filter: Option<serde_json::Value> = params
|
||||
.filter
|
||||
.as_ref()
|
||||
.and_then(|f| serde_json::from_str(f).ok());
|
||||
|
||||
let rows = PluginDataService::export(
|
||||
plugin_id,
|
||||
&entity,
|
||||
ctx.tenant_id,
|
||||
&state.db,
|
||||
filter,
|
||||
params.search,
|
||||
params.sort_by,
|
||||
params.sort_order,
|
||||
&state.entity_cache,
|
||||
scope,
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(Json(ApiResponse::ok(rows)))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/api/v1/plugins/{plugin_id}/{entity}/import",
|
||||
request_body = ImportReq,
|
||||
responses(
|
||||
(status = 200, description = "导入完成", body = ApiResponse<ImportResult>),
|
||||
),
|
||||
security(("bearer_auth" = [])),
|
||||
tag = "插件数据"
|
||||
)]
|
||||
/// POST /api/v1/plugins/{plugin_id}/{entity}/import — 导入数据
|
||||
pub async fn import_plugin_data<S>(
|
||||
State(state): State<PluginState>,
|
||||
Extension(ctx): Extension<TenantContext>,
|
||||
Path((plugin_id, entity)): Path<(Uuid, String)>,
|
||||
Json(req): Json<ImportReq>,
|
||||
) -> Result<Json<ApiResponse<ImportResult>>, AppError>
|
||||
where
|
||||
PluginState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
let manifest_id = resolve_manifest_id(plugin_id, ctx.tenant_id, &state.db).await?;
|
||||
let fine_perm = compute_permission_code(&manifest_id, &entity, "create");
|
||||
require_permission(&ctx, &fine_perm)?;
|
||||
|
||||
let result = PluginDataService::import(
|
||||
plugin_id,
|
||||
&entity,
|
||||
ctx.tenant_id,
|
||||
ctx.user_id,
|
||||
req.rows,
|
||||
&state.db,
|
||||
&state.event_bus,
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user