diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 8b1d0fc..69233c2 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -3,9 +3,12 @@ mod zju_assist; -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; use serde_json::Value; -use std::sync::{Arc, atomic::AtomicBool}; +use std::{ + path::Path, + sync::{atomic::AtomicBool, Arc}, +}; use tauri::{Manager, State, Window}; use tokio::sync::Mutex; use zju_assist::ZjuAssist; @@ -127,14 +130,19 @@ struct Progress { async fn download_courses_upload( state: State<'_, Arc>>, window: Window, - courses: Value + courses: Value, ) -> Result<(), String> { let zju_assist = state.lock().await; let mut all_uploads = Vec::new(); - window.emit("download-progress", Progress { - progress: 0.0, - status: "正在获取文件列表".to_string(), - }).unwrap(); + window + .emit( + "download-progress", + Progress { + progress: 0.0, + status: "正在获取文件列表".to_string(), + }, + ) + .unwrap(); for course in courses.as_array().unwrap() { let course_id = course["id"].as_i64().unwrap(); let course_name = course["name"].as_str().unwrap().replace("/", "-"); @@ -169,19 +177,29 @@ async fn download_courses_upload( // } } for (i, upload) in all_uploads.iter().enumerate() { - window.emit("download-progress", Progress { - progress: i as f64 / all_uploads.len() as f64, - status: format!("正在下载文件 {} ...", upload.file_name), - }).unwrap(); + window + .emit( + "download-progress", + Progress { + progress: i as f64 / all_uploads.len() as f64, + status: format!("正在下载文件 {} ...", upload.file_name), + }, + ) + .unwrap(); zju_assist .download_file(upload.reference_id, &upload.file_name, &upload.path) .await .map_err(|err| err.to_string())?; } - window.emit("download-progress", Progress { - progress: 1.0, - status: "下载完成".to_string(), - }).unwrap(); + window + .emit( + "download-progress", + Progress { + progress: 1.0, + status: "下载完成".to_string(), + }, + ) + .unwrap(); Ok(()) } @@ -202,28 +220,18 @@ async fn get_uploads_list( for upload in activities_uploads { let reference_id = upload["reference_id"].as_i64().unwrap(); let file_name = upload["name"].as_str().unwrap().to_string(); - // let path = format!("download/{}/activities", course_name); - let path = format!("download/{}", course_name); + // let path = format!("download/{}", course_name); + let path = Path::new("download") + .join(&course_name) + .to_str() + .unwrap() + .to_string(); all_uploads.push(Uploads { reference_id, file_name, path, }); } - // let homework_uploads = zju_assist - // .get_homework_uploads(course_id) - // .await - // .map_err(|err| err.to_string())?; - // for upload in homework_uploads { - // let reference_id = upload["reference_id"].as_i64().unwrap(); - // let file_name = upload["name"].as_str().unwrap().to_string(); - // let path = format!("download/{}/homework", course_name); - // all_uploads.push(Uploads { - // reference_id, - // file_name, - // path, - // }); - // } } Ok(all_uploads) } @@ -237,27 +245,47 @@ async fn download_uploads( ) -> Result, String> { let zju_assist = state.lock().await; for (i, upload) in uploads.iter().enumerate() { - if download_state.should_cancel.load(std::sync::atomic::Ordering::SeqCst) { - download_state.should_cancel.store(false, std::sync::atomic::Ordering::SeqCst); - window.emit("download-progress", Progress { - progress: i as f64 / uploads.len() as f64, - status: "下载已取消".to_string(), - }).unwrap(); + if download_state + .should_cancel + .load(std::sync::atomic::Ordering::SeqCst) + { + download_state + .should_cancel + .store(false, std::sync::atomic::Ordering::SeqCst); + window + .emit( + "download-progress", + Progress { + progress: i as f64 / uploads.len() as f64, + status: "下载已取消".to_string(), + }, + ) + .unwrap(); return Ok(uploads[0..i].to_vec()); } - window.emit("download-progress", Progress { - progress: i as f64 / uploads.len() as f64, - status: format!("正在下载文件 {} ...", upload.file_name), - }).unwrap(); + window + .emit( + "download-progress", + Progress { + progress: i as f64 / uploads.len() as f64, + status: format!("正在下载文件 {} ...", upload.file_name), + }, + ) + .unwrap(); zju_assist .download_file(upload.reference_id, &upload.file_name, &upload.path) .await .map_err(|err| err.to_string())?; } - window.emit("download-progress", Progress { - progress: 1.0, - status: "下载完成".to_string(), - }).unwrap(); + window + .emit( + "download-progress", + Progress { + progress: 1.0, + status: "下载完成".to_string(), + }, + ) + .unwrap(); Ok(uploads) } @@ -268,6 +296,30 @@ fn cancel_download(state: State<'_, DownloadState>) -> Result<(), String> { Ok(()) } +#[tauri::command] +fn update_path(path: String, uploads: Vec) -> Result, String> { + let mut new_uploads = Vec::new(); + for upload in uploads { + let new_path = Path::new(&path) + .join( + Path::new(&upload.path) + .file_name() + .unwrap_or_default() + .to_str() + .unwrap(), + ) + .to_str() + .unwrap() + .to_string(); + new_uploads.push(Uploads { + reference_id: upload.reference_id, + file_name: upload.file_name, + path: new_path, + }); + } + Ok(new_uploads) +} + fn main() { tauri::Builder::default() .setup(|app| { @@ -293,6 +345,7 @@ fn main() { get_uploads_list, download_uploads, cancel_download, + update_path, ]) .run(tauri::generate_context!()) .expect("error while running tauri application"); diff --git a/src/Index.jsx b/src/Index.jsx index 3242044..48ea44c 100644 --- a/src/Index.jsx +++ b/src/Index.jsx @@ -2,9 +2,9 @@ import { useEffect, useState } from 'react' import { Form, Input, Button, Card, App, Row, Col, Select, Table, Progress, Tooltip, Typography, FloatButton, ConfigProvider, theme } from 'antd'; import zhCN from 'antd/locale/zh_CN'; import { invoke } from '@tauri-apps/api' -import { UserOutlined, LockOutlined, ReloadOutlined, DownloadOutlined, CloseCircleOutlined, QuestionCircleOutlined } from '@ant-design/icons'; +import { UserOutlined, LockOutlined, ReloadOutlined, DownloadOutlined, CloseCircleOutlined, QuestionCircleOutlined, EditOutlined } from '@ant-design/icons'; import { listen } from '@tauri-apps/api/event' -import { open } from '@tauri-apps/api/shell' +import { dialog, shell } from '@tauri-apps/api'; import { useMediaQuery } from 'react-responsive' const { Text } = Typography @@ -122,6 +122,7 @@ function Home({ setIsLogin }) { const [uploadList, setUploadList] = useState([]) const [selectedUploadKeys, setSelectedUploadKeys] = useState([]) const [downloading, setDownloading] = useState(false) + const [updatingPath, setUpdatingPath] = useState(false) const courseColumns = [ { @@ -130,17 +131,6 @@ function Home({ setIsLogin }) { }, ] - const uploadColumns = [ - { - title: '文件名', - dataIndex: 'file_name', - }, - { - title: '保存路径', - dataIndex: 'path', - } - ] - useEffect(() => { invoke('check_login').then((res) => { if (!res) { @@ -217,7 +207,6 @@ function Home({ setIsLogin }) { if (uploads.length === 0) { notification.error({ message: '请选择课件', - description: '请选择课件' }) return } @@ -227,7 +216,6 @@ function Home({ setIsLogin }) { if (res.length === selectedUploadKeys.length) { notification.success({ message: '下载完成', - description: '下载完成' }) } let haveDownloaded = res.map((item) => item.reference_id) @@ -291,7 +279,6 @@ function Home({ setIsLogin }) { if (courses.length === 0) { notification.error({ message: '请选择课程', - description: '请选择课程' }) return } @@ -322,6 +309,69 @@ function Home({ setIsLogin }) { }) } + const updatePath = () => { + if (uploadList.length === 0) { + notification.error({ + message: '请先获取课件列表', + }) + return + } + dialog.open({ + directory: true, + multiple: false, + message: '选择下载路径' + }).then((res) => { + if (res && res.length !== 0) { + setUpdatingPath(true) + invoke('update_path', { path: res, uploads: uploadList }).then((res) => { + console.log(res) + notification.success({ + message: '下载路径修改成功', + }) + setUploadList(res) + }).catch((err) => { + notification.error({ + message: '下载路径修改失败', + description: err + }) + }).finally(() => { + setUpdatingPath(false) + }) + } + }).catch((err) => { + notification.error({ + message: '下载路径修改失败', + description: err + }) + }) + } + + const uploadColumns = [ + { + title: '文件名', + dataIndex: 'file_name', + }, + { + title: () => ( +
+ 下载路径 + +
+ ), + dataIndex: 'path', + } + ] + return (
- + - + - - @@ -437,7 +474,7 @@ function Home({ setIsLogin }) { }} gutter={20} > - + `课程列表:已选择 ${selectedCourseKeys.length} 门课程`} /> - +
{uploadList && uploadList.length !== 0 && `课件列表:已选择 ${selectedUploadKeys.length} 个文件`} - {(!uploadList || uploadList.length === 0) && -
- 暂未获取课件列表 点此刷新 -
- } + {(!uploadList || uploadList.length === 0) && '课件列表为空 点击右侧刷新👉'} + +