diff --git a/src/main.rs b/src/main.rs index bf5de1f..7a04954 100644 --- a/src/main.rs +++ b/src/main.rs @@ -22,7 +22,7 @@ use tracing::info; async fn get_version() -> impl IntoResponse { Json(serde_json::json!({ - "version": "1.0.6", + "version": "1.0.7", "timestamp": chrono::Utc::now().timestamp() })) } @@ -192,17 +192,19 @@ async fn create_print( ) -> Result, (StatusCode, String)> { info!("📥 Получен запрос на печать"); - let mut settings_map: HashMap = HashMap::new(); + let mut settings_list: Vec> = Vec::new(); let mut files_data: Vec<(String, bytes::Bytes)> = Vec::new(); while let Some(field) = multipart.next_field().await.unwrap_or(None) { let field_name = field.name().unwrap_or("").to_string(); + if field_name == "settings" { - if let Ok(text) = field.text().await { - if let Ok(s) = serde_json::from_str::(&text) { - settings_map.insert(s.filename.clone(), s); - } - } + let parsed = match field.text().await { + Ok(text) => serde_json::from_str::(&text).ok(), + Err(_) => None, + }; + // Пушим даже при ошибке парсинга (None), чтобы индексы не съезжали + settings_list.push(parsed); } else if field_name == "files" { let file_name = field.file_name().unwrap_or("unknown").to_string(); if let Ok(data) = field.bytes().await { @@ -216,21 +218,26 @@ async fn create_print( } let mut job_files: Vec = Vec::new(); - for (file_name, data) in files_data { + + for (i, (file_name, data)) in files_data.into_iter().enumerate() { let ext = Path::new(&file_name) .extension() .and_then(|e| e.to_str()) .unwrap_or("") .to_lowercase(); + let temp = if ext.is_empty() { NamedTempFile::new() } else { NamedTempFile::with_suffix(&format!(".{}", ext)) }; + if let Ok(temp) = temp { let path = temp.into_temp_path(); if fs::write(&*path, &data).await.is_ok() { - let settings = settings_map.get(&file_name).cloned(); + // i-й файл ↔ i-й набор настроек — имена могут совпадать + let settings = settings_list.get(i).cloned().flatten(); + job_files.push(JobFile { name: file_name, path, @@ -258,6 +265,7 @@ async fn create_print( let view = job.view(); store.lock().unwrap().insert(job_id.clone(), job); + Ok(Json(view)) } @@ -526,27 +534,18 @@ fn run_lp(path: &Path, settings: Option<&PrintSettings>, duplex_pass: Option<&st } } - // ────────────────────────────────────────────────────────── - // СЛОТЫ: - // • Первый проход дуплекса (odd) → Upper - // • Второй проход дуплекса (even) → Lower (ручная подача) - // • Обычная печать (не дуплекс) → Upper - // ────────────────────────────────────────────────────────── match duplex_pass { Some("odd") => { - // ПЕРВЫЙ проход — обычный лоток cmd.arg("-o").arg("InputSlot=Upper"); - cmd.arg("-o").arg("page-set=odd"); + cmd.arg("-o").arg("page-set=odd"); // Нечётные страницы } Some("even") => { - // ВТОРОЙ проход — ручная подача cmd.arg("-o").arg("InputSlot=Lower"); - cmd.arg("-o").arg("page-set=even"); + cmd.arg("-o").arg("page-set=even"); // Чётные страницы cmd.arg("-o").arg("outputorder=reverse"); cmd.arg("-o").arg("orientation-requested=6"); } _ => { - // Обычная односторонняя печать cmd.arg("-o").arg("InputSlot=Upper"); } }