fix: 修复测试发现的 7 个问题 + 全 workspace clippy 清零
Some checks failed
CI / rust-check (push) Has been cancelled
CI / rust-test (push) Has been cancelled
CI / frontend-build (push) Has been cancelled
CI / security-audit (push) Has been cancelled

功能修复:
1. 患者创建空名称验证:后端添加 name.trim().is_empty() 检查
2. 仪表盘统计容错:单个查询失败返回零值而非 500
3. FHIR 路由修复:从 /fhir 移到 /api/v1/fhir 保持一致
4. 冻结模块后端中间件:新增 frozen_module_middleware 拦截冻结路径
5. 积分端点权限码:health.health-data.list → health.points.list
6. 角色权限迁移:护士补充 devices.list,运营补充 points.list/manage
7. 测试结果文档:R01-R05 角色测试 + T00/T10 结果归档

Clippy 全 workspace 清零(14→0 errors):
- erp-core: 修复 empty doc line、collapsible if、redundant closure 等 9 处
- erp-health: 修复 too_many_arguments、unused var、unnecessary parens 等 58 处
- erp-ai: 修复 dead_code、unused import 等 11 处
- erp-plugin: 修复 too_many_arguments、wildcard pattern 等 11 处
- erp-server-migration: 修复 enum_variant_names 5 处
- erp-auth/config/workflow/message: 各 1-3 处

工程改进:
- lint-staged 配置迁移到 .lintstagedrc.js(函数式避免文件列表传给 clippy)
- cargo fmt 统一格式化
This commit is contained in:
iven
2026-05-07 23:43:14 +08:00
parent 786f57c151
commit 6d5a711d2c
323 changed files with 15662 additions and 6603 deletions

View File

@@ -4,9 +4,9 @@ use sea_orm::DatabaseConnection;
use uuid::Uuid;
use wasmtime::StoreLimits;
use crate::erp::plugin::host_api;
use crate::dynamic_table::DynamicTableManager;
use crate::engine::PluginEngine;
use crate::erp::plugin::host_api;
/// 待刷新的写操作
#[derive(Debug)]
@@ -144,15 +144,15 @@ impl host_api::Host for HostState {
) -> Result<Vec<u8>, String> {
// 预填充模式(向后兼容)
if self.db.is_none() {
return self.query_results
return self
.query_results
.get(&entity)
.cloned()
.ok_or_else(|| format!("实体 '{}' 的查询结果未预填充", entity));
}
let db = self.db.clone().ok_or("数据库连接不可用")?;
let event_bus = self.event_bus.clone()
.ok_or("事件总线不可用")?;
let event_bus = self.event_bus.clone().ok_or("事件总线不可用")?;
// 先 flush pending writes确保读后写一致性
let ops = std::mem::take(&mut self.pending_ops);
@@ -217,30 +217,28 @@ impl host_api::Host for HostState {
// 执行查询
let rt = tokio::runtime::Handle::current();
let rows = rt.block_on(async {
use sea_orm::{FromQueryResult, Statement};
#[derive(Debug, FromQueryResult)]
struct QueryRow {
data: serde_json::Value,
}
let rows = rt
.block_on(async {
use sea_orm::{FromQueryResult, Statement};
#[derive(Debug, FromQueryResult)]
struct QueryRow {
data: serde_json::Value,
}
let results = QueryRow::find_by_statement(Statement::from_sql_and_values(
sea_orm::DatabaseBackend::Postgres,
sql,
values,
))
.all(&db)
.await
.map_err(|e| format!("查询执行失败: {}", e))?;
let results = QueryRow::find_by_statement(Statement::from_sql_and_values(
sea_orm::DatabaseBackend::Postgres,
sql,
values,
))
.all(&db)
.await
.map_err(|e| format!("查询执行失败: {}", e))?;
let items: Vec<serde_json::Value> = results
.into_iter()
.map(|r| r.data)
.collect();
let items: Vec<serde_json::Value> = results.into_iter().map(|r| r.data).collect();
Ok::<Vec<serde_json::Value>, String>(items)
})
.map_err(|e: String| e)?;
Ok::<Vec<serde_json::Value>, String>(items)
})
.map_err(|e: String| e)?;
serde_json::to_vec(&rows).map_err(|e| e.to_string())
}
@@ -306,13 +304,13 @@ impl host_api::Host for HostState {
}
fn numbering_generate(&mut self, rule_key: String) -> Result<String, String> {
let rule = self.numbering_rules
let rule = self
.numbering_rules
.get(&rule_key)
.ok_or_else(|| format!("编号规则 '{}' 未声明", rule_key))?
.clone();
let db = self.db.clone()
.ok_or("编号生成需要数据库连接")?;
let db = self.db.clone().ok_or("编号生成需要数据库连接")?;
let _tenant_id = self.tenant_id;
let plugin_id = self.plugin_id.clone();
@@ -320,7 +318,7 @@ impl host_api::Host for HostState {
let rt = tokio::runtime::Handle::current();
rt.block_on(async {
use sea_orm::{Statement, FromQueryResult, ConnectionTrait};
use sea_orm::{ConnectionTrait, FromQueryResult, Statement};
let now = chrono::Utc::now();
let year = now.format("%Y").to_string();
@@ -354,7 +352,9 @@ impl host_api::Host for HostState {
db.execute(Statement::from_string(
sea_orm::DatabaseBackend::Postgres,
create_sql,
)).await.map_err(|e| format!("创建序列表失败: {}", e))?;
))
.await
.map_err(|e| format!("创建序列表失败: {}", e))?;
// 使用 advisory lock 保证并发安全
// lock_id 基于规则名哈希
@@ -369,11 +369,15 @@ impl host_api::Host for HostState {
db.execute(Statement::from_string(
sea_orm::DatabaseBackend::Postgres,
lock_sql,
)).await.map_err(|e| format!("获取锁失败: {}", e))?;
))
.await
.map_err(|e| format!("获取锁失败: {}", e))?;
// 读取当前值
#[derive(Debug, FromQueryResult)]
struct SeqRow { current_val: i64 }
struct SeqRow {
current_val: i64,
}
let read_sql = format!(
"SELECT current_val FROM {} WHERE rule_key = $1 AND period_key = $2",
@@ -383,7 +387,10 @@ impl host_api::Host for HostState {
sea_orm::DatabaseBackend::Postgres,
read_sql,
[rule_key.clone().into(), period_key.clone().into()],
)).one(&db).await.map_err(|e| format!("读取序列失败: {}", e))?;
))
.one(&db)
.await
.map_err(|e| format!("读取序列失败: {}", e))?;
let next_val = current.map(|r| r.current_val + 1).unwrap_or(1);
@@ -396,12 +403,19 @@ impl host_api::Host for HostState {
db.execute(Statement::from_sql_and_values(
sea_orm::DatabaseBackend::Postgres,
upsert_sql,
[rule_key.clone().into(), period_key.clone().into(), next_val.into()],
)).await.map_err(|e| format!("更新序列失败: {}", e))?;
[
rule_key.clone().into(),
period_key.clone().into(),
next_val.into(),
],
))
.await
.map_err(|e| format!("更新序列失败: {}", e))?;
let seq_str = format!("{:0>width$}", next_val, width = rule.seq_length as usize);
let number = rule.format
let number = rule
.format
.replace("{PREFIX}", &rule.prefix)
.replace("{YEAR}", &year)
.replace("{MONTH}", &month)
@@ -414,11 +428,11 @@ impl host_api::Host for HostState {
}
fn setting_get(&mut self, key: String) -> Result<Vec<u8>, String> {
let config = self.plugin_config.as_object()
let config = self
.plugin_config
.as_object()
.ok_or("插件配置不是有效对象")?;
let value = config.get(&key)
.cloned()
.unwrap_or(serde_json::Value::Null);
let value = config.get(&key).cloned().unwrap_or(serde_json::Value::Null);
serde_json::to_vec(&value).map_err(|e| e.to_string())
}
}