From 98e43b79578efaf5491a98821ba59f1486ce28fb Mon Sep 17 00:00:00 2001 From: suzmii Date: Mon, 31 Aug 2026 21:35:03 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=AD=97=E7=AC=A6=E4=B8=B2?= =?UTF-8?q?=E6=95=B0=E5=AD=97=E7=AD=9B=E9=80=89=E6=AF=94=E8=BE=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 让后台表格筛选同时解析实际值与期望值中的字符串数字 补充字符串化数字范围筛选回归测试 --- server-rs/crates/api-server/src/admin.rs | 30 +++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/server-rs/crates/api-server/src/admin.rs b/server-rs/crates/api-server/src/admin.rs index 613f5977b..bba718f84 100644 --- a/server-rs/crates/api-server/src/admin.rs +++ b/server-rs/crates/api-server/src/admin.rs @@ -3536,12 +3536,15 @@ fn admin_database_filter_operator_matches( // 数值优先、字符串兜底的比较,兼容后台单元格的字符串化值。 fn compare_admin_database_filter_values(actual: &Value, expected: &Value) -> Option { + let actual_number = actual + .as_f64() + .or_else(|| actual.as_str().and_then(|value| value.trim().parse().ok())); let expected_number = expected.as_f64().or_else(|| { expected .as_str() .and_then(|value| value.trim().parse().ok()) }); - if let (Some(actual_number), Some(expected_number)) = (actual.as_f64(), expected_number) { + if let (Some(actual_number), Some(expected_number)) = (actual_number, expected_number) { if actual_number.is_finite() && expected_number.is_finite() { return actual_number.partial_cmp(&expected_number); } @@ -5702,6 +5705,31 @@ mod tests { assert_eq!(user_ids, vec!["u10", "u12"]); } + #[test] + fn apply_admin_database_table_filters_compares_stringified_numeric_columns_numerically() { + let columns = vec!["user_id".to_string(), "points".to_string()]; + let mut rows = vec![ + build_admin_database_table_row(&json!(["u2", "2"]), &columns), + build_admin_database_table_row(&json!(["u10", "10"]), &columns), + build_admin_database_table_row(&json!(["u12", "12"]), &columns), + ]; + + apply_admin_database_table_filters( + &mut rows, + &AdminDatabaseTableRowsQuery { + filters: Some(json!([{"column": "points", "op": "gt", "value": "5"}]).to_string()), + ..Default::default() + }, + ) + .expect("stringified numeric range filters should compare numerically"); + + let user_ids = rows + .iter() + .filter_map(|row| row.cells.get("user_id").and_then(|value| value.as_str())) + .collect::>(); + assert_eq!(user_ids, vec!["u10", "u12"]); + } + #[test] fn apply_admin_database_table_filters_supports_list_and_negation_operators() { let columns: Vec = ["user_id", "name", "points", "deleted_at"]