158 lines
4.4 KiB
Rust
158 lines
4.4 KiB
Rust
//! 设备日志 API — 分页列表查询
|
|
|
|
use axum::extract::{Query, State};
|
|
use axum::Json;
|
|
use chrono::NaiveDateTime;
|
|
use serde::{Deserialize, Serialize};
|
|
use serde_json::{json, Value};
|
|
|
|
use crate::error::AppError;
|
|
use crate::middleware::auth::{self, CurrentUser};
|
|
|
|
/// 设备日志查询参数
|
|
#[derive(Debug, Deserialize)]
|
|
pub struct DeviceLogQuery {
|
|
pub cabinet_id: Option<i64>,
|
|
pub log_type: Option<i8>,
|
|
pub start_time: Option<String>,
|
|
pub end_time: Option<String>,
|
|
#[serde(default = "default_page")]
|
|
pub page: i64,
|
|
#[serde(default = "default_page_size")]
|
|
pub page_size: i64,
|
|
}
|
|
|
|
/// 设备日志列表项
|
|
#[derive(Debug, Serialize)]
|
|
pub struct DeviceLogItem {
|
|
pub id: i64,
|
|
pub cabinet_id: i64,
|
|
pub cabinet_name: Option<String>,
|
|
pub log_type: i8,
|
|
pub log_type_text: String,
|
|
pub content: Option<String>,
|
|
pub created_at: Option<String>,
|
|
}
|
|
|
|
fn default_page() -> i64 { 1 }
|
|
fn default_page_size() -> i64 { 20 }
|
|
|
|
/// 日志类型码转中文
|
|
fn log_type_text(log_type: i8) -> &'static str {
|
|
match log_type {
|
|
1 => "状态上报",
|
|
2 => "故障",
|
|
3 => "告警",
|
|
4 => "停电",
|
|
_ => "未知",
|
|
}
|
|
}
|
|
|
|
/// 数据库行映射
|
|
#[derive(Debug, sqlx::FromRow)]
|
|
struct DeviceLogRow {
|
|
id: i64,
|
|
cabinet_id: i64,
|
|
cabinet_name: Option<String>,
|
|
log_type: i8,
|
|
content: Option<String>,
|
|
created_at: Option<NaiveDateTime>,
|
|
}
|
|
|
|
/// GET /api/device-logs — 设备日志分页列表
|
|
pub async fn list_device_logs(
|
|
user: CurrentUser,
|
|
State(state): State<super::AppState>,
|
|
Query(params): Query<DeviceLogQuery>,
|
|
) -> Result<Json<Value>, AppError> {
|
|
auth::check_permission(&user, "device_log:view")?;
|
|
let offset = (params.page - 1) * params.page_size;
|
|
|
|
// 构建 WHERE 条件
|
|
let mut conditions = Vec::new();
|
|
let mut bind_values: Vec<String> = Vec::new();
|
|
|
|
if let Some(cabinet_id) = params.cabinet_id {
|
|
conditions.push("dl.cabinet_id = ?");
|
|
bind_values.push(cabinet_id.to_string());
|
|
}
|
|
if let Some(log_type) = params.log_type {
|
|
conditions.push("dl.log_type = ?");
|
|
bind_values.push(log_type.to_string());
|
|
}
|
|
if let Some(ref start_time) = params.start_time {
|
|
conditions.push("dl.created_at >= ?");
|
|
bind_values.push(start_time.clone());
|
|
}
|
|
if let Some(ref end_time) = params.end_time {
|
|
conditions.push("dl.created_at <= ?");
|
|
bind_values.push(end_time.clone());
|
|
}
|
|
|
|
// 追加组织数据隔离
|
|
let (org_cond, org_binds) = auth::org_condition(&user, "dl");
|
|
if !org_cond.is_empty() {
|
|
conditions.push(org_cond.trim_start_matches(" AND "));
|
|
bind_values.extend(org_binds);
|
|
}
|
|
|
|
let where_clause = if conditions.is_empty() {
|
|
String::new()
|
|
} else {
|
|
format!("WHERE {}", conditions.join(" AND "))
|
|
};
|
|
|
|
// 查询总数
|
|
let count_sql = format!(
|
|
"SELECT COUNT(*) FROM device_logs dl {}",
|
|
where_clause
|
|
);
|
|
let mut count_query = sqlx::query_scalar::<_, i64>(&count_sql);
|
|
for val in &bind_values {
|
|
count_query = count_query.bind(val);
|
|
}
|
|
let total = count_query.fetch_one(&state.mysql).await?;
|
|
|
|
// 查询列表
|
|
let list_sql = format!(
|
|
"SELECT dl.id, dl.cabinet_id, c.name AS cabinet_name, \
|
|
dl.log_type, dl.content, dl.created_at \
|
|
FROM device_logs dl \
|
|
LEFT JOIN cabinets c ON dl.cabinet_id = c.id \
|
|
{} ORDER BY dl.created_at DESC LIMIT ? OFFSET ?",
|
|
where_clause
|
|
);
|
|
|
|
let mut list_query = sqlx::query_as::<_, DeviceLogRow>(&list_sql);
|
|
for val in &bind_values {
|
|
list_query = list_query.bind(val);
|
|
}
|
|
list_query = list_query.bind(params.page_size).bind(offset);
|
|
|
|
let rows = list_query.fetch_all(&state.mysql).await?;
|
|
|
|
let list: Vec<DeviceLogItem> = rows
|
|
.into_iter()
|
|
.map(|r| DeviceLogItem {
|
|
id: r.id,
|
|
cabinet_id: r.cabinet_id,
|
|
cabinet_name: r.cabinet_name,
|
|
log_type: r.log_type,
|
|
log_type_text: log_type_text(r.log_type).to_string(),
|
|
content: r.content,
|
|
created_at: r.created_at.map(|t| t.to_string()),
|
|
})
|
|
.collect();
|
|
|
|
Ok(Json(json!({
|
|
"code": 0,
|
|
"data": {
|
|
"list": list,
|
|
"total": total,
|
|
"page": params.page,
|
|
"page_size": params.page_size,
|
|
},
|
|
"message": "ok"
|
|
})))
|
|
}
|