fix(cron): 用中文说明替代解析器原始报错

- 后端 CronPreviewError 增加 user_message,预览与任务保存共用;解析器英文原文只写日志
- 针对「0/2」这类单数字步长给出具体改法(*/2 或 1-10/2)
- 前端预览面板用警告图标 + 中文提示展示,网络异常回退通用文案,Cron 输入同步 aria-invalid
This commit is contained in:
2026-11-02 22:35:39 +08:00
parent b2ff255e32
commit b7ded69a7d
5 changed files with 51 additions and 10 deletions
+4 -1
View File
@@ -110,7 +110,10 @@ pub async fn preview_cron(
chrono::Utc::now(),
request.count,
)
.map_err(|error| ApiError::validation("expression", error.to_string()))?;
.map_err(|error| {
tracing::debug!(error = %error, "cron preview failed");
ApiError::validation("expression", error.user_message())
})?;
Ok(Json(preview))
}
+21
View File
@@ -21,6 +21,27 @@ pub enum CronPreviewError {
InvalidTimezone(String),
}
impl CronPreviewError {
/// 面向界面的中文说明。解析器原始错误(英文、带组件路径)只写日志,
/// 不再直接抛给前端。
pub fn user_message(&self) -> String {
match self {
Self::InvalidExpression(detail) => {
if detail.contains("Invalid step syntax") {
"Cron 表达式步长写法不正确:不要用「0/2」这种单数字步长,通配步长写「*/2」,范围步长写「1-10/2」"
.to_owned()
} else {
"Cron 表达式无效,请检查字段取值与步长写法(通配步长用 */n,范围步长用 a-b/n)"
.to_owned()
}
}
Self::TooManyRuns => format!("一次最多预览 {MAX_PREVIEW_RUNS} 次运行"),
Self::NoFutureOccurrence => "Cron 表达式没有可计算的未来执行时间".to_owned(),
Self::InvalidTimezone(_) => "时区必须是有效的 IANA 时区名称".to_owned(),
}
}
}
#[derive(Debug, Deserialize, ToSchema)]
#[serde(deny_unknown_fields)]
pub struct CronPreviewRequest {
+6 -5
View File
@@ -166,14 +166,15 @@ fn validate_common(
})?;
let cron = Cron::from_str(cron_expression).map_err(|error| {
crate::error::ApiError::validation("cron", format!("Cron 表达式无效: {error}"))
tracing::debug!(error = %error, "invalid cron expression");
let message =
crate::cron::CronPreviewError::InvalidExpression(error.to_string()).user_message();
crate::error::ApiError::validation("cron", message)
})?;
cron.find_next_occurrence(&Utc::now(), false)
.map_err(|error| {
crate::error::ApiError::validation(
"cron",
format!("Cron 表达式没有可计算的未来执行时间: {error}"),
)
tracing::debug!(error = %error, "cron has no future occurrence");
crate::error::ApiError::validation("cron", "Cron 表达式没有可计算的未来执行时间")
})?;
Ok(())