From 3607701c26aa1178327f9a365b6d6327a451aa63 Mon Sep 17 00:00:00 2001 From: 12451 <12451@example.com> Date: Thu, 2 Jul 2026 21:42:52 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=A0=91=E8=8A=82=E7=82=B9=E6=98=BE?= =?UTF-8?q?=E7=A4=BA=E8=AE=BE=E5=A4=87=E6=95=B0=E9=87=8F=EF=BC=8C=E5=A6=82?= =?UTF-8?q?=20=E6=97=A0=E9=94=A1=E8=89=BE=E5=8A=A8=20(15)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api-server/src/routes/cabinet_tree.rs | 48 ++++++++++++++----- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/software/api-server/src/routes/cabinet_tree.rs b/software/api-server/src/routes/cabinet_tree.rs index 06690aa..34debb5 100644 --- a/software/api-server/src/routes/cabinet_tree.rs +++ b/software/api-server/src/routes/cabinet_tree.rs @@ -14,7 +14,7 @@ use crate::error::AppError; use crate::middleware::auth::{self, CurrentUser}; use crate::commands::AppState; -/// 组织树接口 — 返回多级组织->项目树 +/// 组织树接口 — 返回多级组织->项目树(含设备数量) pub async fn organization_tree( user: CurrentUser, State(state): State, @@ -23,7 +23,7 @@ pub async fn organization_tree( let db = &state.mysql; - // 获取所有组织(带parent_id) + // 获取所有组织 let orgs: Vec = sqlx::query_as( "SELECT id, name, parent_id FROM organizations ORDER BY id" ) @@ -37,10 +37,19 @@ pub async fn organization_tree( .fetch_all(db) .await?; + // 获取每个项目的设备数量 + let project_counts: Vec<(i64, i64)> = sqlx::query_as( + "SELECT project_id, COUNT(*) as cnt FROM cabinets GROUP BY project_id" + ) + .fetch_all(db) + .await?; + let project_count_map: std::collections::HashMap = project_counts.into_iter().collect(); + // 递归构建树 fn build_tree( orgs: &[OrganizationRow], projects: &[ProjectRow], + project_count_map: &std::collections::HashMap, parent_id: Option, ) -> Vec { orgs @@ -48,19 +57,22 @@ pub async fn organization_tree( .filter(|o| o.parent_id == parent_id) .map(|org| { // 递归获取子组织 - let children = build_tree(orgs, projects, Some(org.id)); + let children = build_tree(orgs, projects, project_count_map, Some(org.id)); // 获取该组织下的项目 let org_projects: Vec = projects .iter() .filter(|p| p.organization_id == Some(org.id)) - .map(|p| TreeNode { - id: p.id, - name: p.name.clone(), - children: None, - abstract_id: None, - imei: None, - status: None, + .map(|p| { + let count = project_count_map.get(&p.id).copied().unwrap_or(0); + TreeNode { + id: p.id, + name: format!("{} ({})", p.name, count), + children: None, + abstract_id: None, + imei: None, + status: None, + } }) .collect(); @@ -68,9 +80,21 @@ pub async fn organization_tree( let mut all_children = children; all_children.extend(org_projects); + // 计算本组织下的总设备数量 + let total_count: i64 = all_children.iter() + .map(|c| { + // 从项目名称中提取数量 + if let Some(start) = c.name.rfind('(') { + if let Some(end) = c.name.rfind(')') { + c.name[start+1..end].parse().unwrap_or(0) + } else { 0 } + } else { 0 } + }) + .sum(); + TreeNode { id: org.id, - name: org.name.clone(), + name: format!("{} ({})", org.name, total_count), children: if all_children.is_empty() { None } else { Some(all_children) }, abstract_id: None, imei: None, @@ -80,7 +104,7 @@ pub async fn organization_tree( .collect() } - let tree = build_tree(&orgs, &projects, None); + let tree = build_tree(&orgs, &projects, &project_count_map, None); Ok(Json(json!(tree))) }