diff --git a/apps/web/public/inventory.wasm b/apps/web/public/inventory.wasm new file mode 100644 index 0000000..ec18f60 Binary files /dev/null and b/apps/web/public/inventory.wasm differ diff --git a/apps/web/src/App.tsx b/apps/web/src/App.tsx index 2e4d953..b888716 100644 --- a/apps/web/src/App.tsx +++ b/apps/web/src/App.tsx @@ -4,6 +4,7 @@ import { ConfigProvider, theme as antdTheme, Spin } from 'antd'; import zhCN from 'antd/locale/zh_CN'; import MainLayout from './layouts/MainLayout'; import Login from './pages/Login'; +import { ErrorBoundary } from './components/ErrorBoundary'; import { useAuthStore } from './stores/auth'; import { useAppStore } from './stores/app'; @@ -133,6 +134,7 @@ export default function App() { element={ + }> } /> @@ -151,6 +153,7 @@ export default function App() { } /> + } diff --git a/crates/erp-plugin/src/data_service.rs b/crates/erp-plugin/src/data_service.rs index e5455bc..c12e236 100644 --- a/crates/erp-plugin/src/data_service.rs +++ b/crates/erp-plugin/src/data_service.rs @@ -527,6 +527,7 @@ impl PluginDataService { db: &sea_orm::DatabaseConnection, filter: Option, search: Option, + scope: Option, ) -> AppResult { let info = resolve_entity_info(plugin_id, entity_name, tenant_id, db).await?; @@ -543,7 +544,7 @@ impl PluginDataService { } }; - let (sql, values) = DynamicTableManager::build_filtered_count_sql( + let (mut sql, mut values) = DynamicTableManager::build_filtered_count_sql( &info.table_name, tenant_id, filter, @@ -551,6 +552,13 @@ impl PluginDataService { ) .map_err(|e| AppError::Validation(e))?; + // 合并数据权限条件 + let scope_condition = build_scope_sql(&scope, &info.generated_fields); + if !scope_condition.0.is_empty() { + sql = merge_scope_condition(sql, &scope_condition); + values.extend(scope_condition.1); + } + #[derive(FromQueryResult)] struct CountResult { count: i64, @@ -578,10 +586,11 @@ impl PluginDataService { db: &sea_orm::DatabaseConnection, group_by_field: &str, filter: Option, + scope: Option, ) -> AppResult> { let info = resolve_entity_info(plugin_id, entity_name, tenant_id, db).await?; - let (sql, values) = DynamicTableManager::build_aggregate_sql( + let (mut sql, mut values) = DynamicTableManager::build_aggregate_sql( &info.table_name, tenant_id, group_by_field, @@ -589,6 +598,13 @@ impl PluginDataService { ) .map_err(|e| AppError::Validation(e))?; + // 合并数据权限条件 + let scope_condition = build_scope_sql(&scope, &info.generated_fields); + if !scope_condition.0.is_empty() { + sql = merge_scope_condition(sql, &scope_condition); + values.extend(scope_condition.1); + } + #[derive(FromQueryResult)] struct AggRow { key: Option, @@ -621,7 +637,7 @@ impl PluginDataService { filter: Option, ) -> AppResult> { // TODO: 未来版本添加 Redis 缓存层 - Self::aggregate(plugin_id, entity_name, tenant_id, db, group_by_field, filter).await + Self::aggregate(plugin_id, entity_name, tenant_id, db, group_by_field, filter, None).await } /// 时间序列聚合 — 按时间字段截断为 day/week/month 统计计数 @@ -634,10 +650,11 @@ impl PluginDataService { time_grain: &str, start: Option, end: Option, + scope: Option, ) -> AppResult> { let info = resolve_entity_info(plugin_id, entity_name, tenant_id, db).await?; - let (sql, values) = DynamicTableManager::build_timeseries_sql( + let (mut sql, mut values) = DynamicTableManager::build_timeseries_sql( &info.table_name, tenant_id, time_field, @@ -647,6 +664,13 @@ impl PluginDataService { ) .map_err(|e| AppError::Validation(e))?; + // 合并数据权限条件 + let scope_condition = build_scope_sql(&scope, &info.generated_fields); + if !scope_condition.0.is_empty() { + sql = merge_scope_condition(sql, &scope_condition); + values.extend(scope_condition.1); + } + #[derive(FromQueryResult)] struct TsRow { period: Option, diff --git a/crates/erp-plugin/src/handler/data_handler.rs b/crates/erp-plugin/src/handler/data_handler.rs index e6d0104..ce16f7c 100644 --- a/crates/erp-plugin/src/handler/data_handler.rs +++ b/crates/erp-plugin/src/handler/data_handler.rs @@ -390,6 +390,11 @@ where 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?; + // 解析 filter JSON let filter: Option = params .filter @@ -403,6 +408,7 @@ where &state.db, filter, params.search, + scope, ) .await?; @@ -434,6 +440,11 @@ where 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?; + // 解析 filter JSON let filter: Option = params .filter @@ -447,6 +458,7 @@ where &state.db, ¶ms.group_by, filter, + scope, ) .await?; @@ -483,6 +495,11 @@ where 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 result = PluginDataService::timeseries( plugin_id, &entity, @@ -492,6 +509,7 @@ where ¶ms.time_grain, params.start, params.end, + scope, ) .await?;