fix: 修复测试发现的 7 个问题 + 全 workspace clippy 清零
功能修复: 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:
@@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user