feat: 间隔时间加分可以按照多少天、月、分钟后加分

fix: 修复若干问题
下雨了好害怕我靠
This commit is contained in:
NanGua-QWQ
2026-03-29 18:17:54 +08:00
parent a930e4843c
commit e4d9ee0c85
14 changed files with 507 additions and 83 deletions
+64 -16
View File
@@ -1,4 +1,4 @@
use chrono::{DateTime, Utc};
use chrono::{DateTime, Months, Utc};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use tauri::{AppHandle, Emitter};
@@ -15,6 +15,20 @@ pub struct AutoScoreAction {
pub value: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
enum IntervalUnit {
Minute,
Day,
Month,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
struct IntervalTriggerValue {
amount: i64,
unit: IntervalUnit,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AutoScoreRule {
pub id: i32,
@@ -171,23 +185,17 @@ impl AutoScoreService {
for trigger in &rule.triggers {
if trigger.event == "interval_time_passed" {
let minutes = trigger
.value
let interval = parse_interval_trigger_value(trigger.value.as_ref());
let base_time = rule
.last_executed
.as_ref()
.and_then(|v| v.parse::<i64>().ok())
.unwrap_or(30);
let interval_ms = minutes * 60 * 1000;
.and_then(|value| DateTime::parse_from_rfc3339(value).ok())
.map(|value| value.with_timezone(&Utc))
.unwrap_or(now);
if let Some(last_executed_str) = &rule.last_executed {
if let Ok(last_executed) = DateTime::parse_from_rfc3339(last_executed_str) {
let last_executed_utc: DateTime<Utc> = last_executed.with_timezone(&Utc);
let next_execute_time =
last_executed_utc + chrono::Duration::milliseconds(interval_ms);
let delay_ms = (next_execute_time - now).num_milliseconds();
return Some(delay_ms.max(0));
}
}
return Some(interval_ms);
let next_execute_time = add_interval_to_time(base_time, &interval)?;
let delay_ms = (next_execute_time - now).num_milliseconds();
return Some(delay_ms.max(0));
}
}
None
@@ -197,3 +205,43 @@ impl AutoScoreService {
let _ = app_handle.emit("auto-score:rulesChanged", &self.rules);
}
}
fn parse_interval_trigger_value(value: Option<&String>) -> IntervalTriggerValue {
if let Some(raw_value) = value {
if let Ok(minutes) = raw_value.parse::<i64>() {
if minutes > 0 {
return IntervalTriggerValue {
amount: minutes,
unit: IntervalUnit::Minute,
};
}
}
if let Ok(parsed_value) = serde_json::from_str::<IntervalTriggerValue>(raw_value) {
if parsed_value.amount > 0 {
return parsed_value;
}
}
}
IntervalTriggerValue {
amount: 30,
unit: IntervalUnit::Minute,
}
}
fn add_interval_to_time(
base_time: DateTime<Utc>,
interval: &IntervalTriggerValue,
) -> Option<DateTime<Utc>> {
match interval.unit {
IntervalUnit::Minute => {
base_time.checked_add_signed(chrono::Duration::minutes(interval.amount))
}
IntervalUnit::Day => base_time.checked_add_signed(chrono::Duration::days(interval.amount)),
IntervalUnit::Month => {
let months = u32::try_from(interval.amount).ok()?;
base_time.checked_add_months(Months::new(months))
}
}
}