114 lines
3.6 KiB
Rust
Raw Normal View History

//! 组织树 API
//!
//! 返回组织->项目->设备完整树状结构。
//! 根据用户角色进行数据隔离:总管理员看全部,企业管理员只看本组织。
use axum::extract::State;
use axum::Json;
use serde_json::{json, Value};
use super::organizations::{CabinetRow, OrganizationRow, ProjectRow, TreeNode};
use crate::error::AppError;
use crate::middleware::auth::{self, CurrentUser};
use crate::commands::AppState;
/// GET /api/organization-tree — 返回组织->项目->设备完整树
///
/// 需要 `device:view` 权限。
/// 数据隔离:总管理员看所有组织,企业管理员只看本组织下的数据。
pub async fn organization_tree(
user: CurrentUser,
State(state): State<AppState>,
) -> Result<Json<Value>, AppError> {
auth::check_permission(&user, "device:view")?;
let db = &state.mysql;
// 根据角色过滤组织:总管理员看所有,企业管理员只看本组织
let orgs: Vec<OrganizationRow> = if user.role_level >= 2 {
sqlx::query_as(
r#"SELECT id, name FROM organizations ORDER BY id"#,
)
.fetch_all(db)
.await?
} else if let Some(org_id) = user.organization_id {
sqlx::query_as(
r#"SELECT id, name FROM organizations WHERE id = ? ORDER BY id"#,
)
.bind(org_id)
.fetch_all(db)
.await?
} else {
// 无组织关联的用户看不到任何数据
return Ok(Json(json!([])));
};
let projects: Vec<ProjectRow> = sqlx::query_as(
r#"SELECT id, organization_id, name FROM projects ORDER BY id"#,
)
.fetch_all(db)
.await?;
let cabinets: Vec<CabinetRow> = sqlx::query_as(
r#"SELECT id, project_id, abstract_id, imei, iccid, name, address, status
FROM cabinets ORDER BY id"#,
)
.fetch_all(db)
.await?;
// 构建树
let tree: Vec<TreeNode> = orgs
.into_iter()
.map(|org| {
let org_projects: Vec<ProjectRow> = projects
.iter()
.filter(|p| p.organization_id == Some(org.id))
.cloned()
.collect();
let children: Vec<TreeNode> = org_projects
.into_iter()
.map(|proj| {
let proj_cabinets: Vec<CabinetRow> = cabinets
.iter()
.filter(|c| c.project_id == Some(proj.id))
.cloned()
.collect();
let cab_nodes: Vec<TreeNode> = proj_cabinets
.into_iter()
.map(|c| TreeNode {
id: c.id,
name: c.name.unwrap_or_else(|| c.abstract_id.clone()),
children: None,
abstract_id: Some(c.abstract_id),
imei: Some(c.imei),
status: Some(c.status),
})
.collect();
TreeNode {
id: proj.id,
name: proj.name,
children: Some(cab_nodes),
abstract_id: None,
imei: None,
status: None,
}
})
.collect();
TreeNode {
id: org.id,
name: org.name,
children: Some(children),
abstract_id: None,
imei: None,
status: None,
}
})
.collect();
Ok(Json(json!(tree)))
}