fix: align lineloss default periods with page semantics

Default month/week deterministic lineloss requests to the source page's built-in time ranges while preserving explicit-period parsing and existing routing contracts.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
木炎
2026-04-12 21:35:28 +08:00
parent 45b60e37f7
commit a8a470481d
3 changed files with 379 additions and 18 deletions

View File

@@ -1,4 +1,4 @@
use chrono::{Datelike, Duration, NaiveDate};
use chrono::{Datelike, Duration, Local, NaiveDate};
use serde_json::json;
use super::contracts::{
@@ -37,7 +37,11 @@ fn resolve_month_period(input: &str) -> Result<ResolvedPeriod, String> {
});
}
Err(missing_period_prompt())
if contains_explicit_month_period_hint(input) {
return Err(missing_period_prompt());
}
Ok(default_month_period())
}
fn resolve_week_period(input: &str) -> Result<ResolvedPeriod, String> {
@@ -45,26 +49,83 @@ fn resolve_week_period(input: &str) -> Result<ResolvedPeriod, String> {
return Err(missing_week_year_prompt());
}
let Some((year, week)) = extract_year_week(input) else {
return Err(missing_period_prompt());
};
if let Some((year, week)) = extract_year_week(input) {
let Some(week_start) = week_start_date(year, week) else {
return Err(missing_period_prompt());
};
let week_end = week_start + Duration::days(6);
let Some(week_start) = week_start_date(year, week) else {
return Err(missing_period_prompt());
};
let week_end = week_start + Duration::days(6);
return Ok(ResolvedPeriod {
mode: PeriodMode::Week,
mode_code: "2".to_string(),
value: format!("{year}-W{week:02}"),
payload: json!({
"tjzq": "week",
"level": "00",
"weekSfdate": week_start.format("%Y-%m-%d").to_string(),
"weekEfdate": week_end.format("%Y-%m-%d").to_string(),
}),
});
}
Ok(ResolvedPeriod {
if contains_explicit_week_period_hint(input) {
return Err(missing_period_prompt());
}
Ok(default_week_period())
}
fn default_month_period() -> ResolvedPeriod {
let today = Local::now().date_naive();
let (year, month) = if today.month() == 1 {
(today.year() - 1, 12)
} else {
(today.year(), today.month() - 1)
};
let value = format!("{year}-{month:02}");
ResolvedPeriod {
mode: PeriodMode::Month,
mode_code: "1".to_string(),
value: value.clone(),
payload: json!({ "fdate": value }),
}
}
fn default_week_period() -> ResolvedPeriod {
let today = Local::now().date_naive();
let month_start = today.with_day(1).expect("current month should have day 1");
let start = month_start.format("%Y-%m-%d").to_string();
let end = today.format("%Y-%m-%d").to_string();
ResolvedPeriod {
mode: PeriodMode::Week,
mode_code: "2".to_string(),
value: format!("{year}-W{week:02}"),
value: format!("{start}至{end}"),
payload: json!({
"tjzq": "week",
"level": "00",
"weekSfdate": week_start.format("%Y-%m-%d").to_string(),
"weekEfdate": week_end.format("%Y-%m-%d").to_string(),
"weekSfdate": start,
"weekEfdate": end,
}),
})
}
}
fn contains_explicit_month_period_hint(input: &str) -> bool {
let trimmed = input.replace("月累计", "");
trimmed.contains('年')
|| trimmed.contains('月')
|| trimmed.contains('-')
|| trimmed.chars().any(|ch| ch.is_ascii_digit())
}
fn contains_explicit_week_period_hint(input: &str) -> bool {
let trimmed = input.replace("周累计", "");
trimmed.contains('年')
|| trimmed.contains('第')
|| trimmed.contains('周')
|| trimmed.contains('-')
|| trimmed.chars().any(|ch| ch.is_ascii_digit())
}
fn extract_year_month_dash(input: &str) -> Option<String> {