update file struct
This commit is contained in:
@@ -16,6 +16,12 @@ pub struct AppSettings {
|
|||||||
pub repo_url: String,
|
pub repo_url: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
|
pub struct EssentialsRepo {
|
||||||
|
pub version: String,
|
||||||
|
pub essentials: Vec<Software>,
|
||||||
|
}
|
||||||
|
|
||||||
impl Default for AppSettings {
|
impl Default for AppSettings {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -99,15 +105,15 @@ async fn sync_essentials(app: AppHandle) -> Result<bool, String> {
|
|||||||
Ok(response) => {
|
Ok(response) => {
|
||||||
if response.status().is_success() {
|
if response.status().is_success() {
|
||||||
let content = response.text().await.map_err(|e| e.to_string())?;
|
let content = response.text().await.map_err(|e| e.to_string())?;
|
||||||
// 验证 JSON 格式
|
// 验证 JSON 格式(新格式:{ version: string, essentials: Vec<Software> })
|
||||||
let validation: Result<Vec<Software>, _> = serde_json::from_str(&content);
|
let validation: Result<EssentialsRepo, _> = serde_json::from_str(&content);
|
||||||
if validation.is_ok() {
|
if validation.is_ok() {
|
||||||
let path = get_essentials_path(&app);
|
let path = get_essentials_path(&app);
|
||||||
fs::write(path, content).map_err(|e| e.to_string())?;
|
fs::write(path, content).map_err(|e| e.to_string())?;
|
||||||
emit_log(&app, "sync-essentials", "Result", "Essentials list updated successfully.", "success");
|
emit_log(&app, "sync-essentials", "Result", "Essentials list updated successfully.", "success");
|
||||||
Ok(true)
|
Ok(true)
|
||||||
} else {
|
} else {
|
||||||
emit_log(&app, "sync-essentials", "Error", "Invalid JSON format from repository.", "error");
|
emit_log(&app, "sync-essentials", "Error", "Invalid JSON format from repository. Expected { version, essentials }.", "error");
|
||||||
Err("Invalid JSON format".to_string())
|
Err("Invalid JSON format".to_string())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -118,7 +124,7 @@ async fn sync_essentials(app: AppHandle) -> Result<bool, String> {
|
|||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
emit_log(&app, "sync-essentials", "Skipped", &format!("Network issue: {}. Using local cache.", e), "info");
|
emit_log(&app, "sync-essentials", "Skipped", &format!("Network issue: {}. Using local cache.", e), "info");
|
||||||
Ok(false) // 静默失败,返回 false 表示未更新但可继续
|
Ok(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -132,14 +138,14 @@ async fn initialize_app(app: AppHandle) -> Result<bool, String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
fn get_essentials(app: AppHandle) -> Vec<Software> {
|
fn get_essentials(app: AppHandle) -> Option<EssentialsRepo> {
|
||||||
let file_path = get_essentials_path(&app);
|
let file_path = get_essentials_path(&app);
|
||||||
if !file_path.exists() {
|
if !file_path.exists() {
|
||||||
return vec![];
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let content = fs::read_to_string(file_path).unwrap_or_else(|_| "[]".to_string());
|
let content = fs::read_to_string(file_path).unwrap_or_default();
|
||||||
serde_json::from_str(&content).unwrap_or_default()
|
serde_json::from_str(&content).ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ export interface LogEntry {
|
|||||||
export const useSoftwareStore = defineStore('software', {
|
export const useSoftwareStore = defineStore('software', {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
essentials: [] as any[],
|
essentials: [] as any[],
|
||||||
|
essentialsVersion: '',
|
||||||
updates: [] as any[],
|
updates: [] as any[],
|
||||||
allSoftware: [] as any[],
|
allSoftware: [] as any[],
|
||||||
selectedEssentialIds: [] as string[],
|
selectedEssentialIds: [] as string[],
|
||||||
@@ -117,7 +118,14 @@ export const useSoftwareStore = defineStore('software', {
|
|||||||
},
|
},
|
||||||
|
|
||||||
async fetchEssentials() {
|
async fetchEssentials() {
|
||||||
this.essentials = await invoke('get_essentials')
|
const res = await invoke('get_essentials') as any;
|
||||||
|
if (res) {
|
||||||
|
this.essentials = res.essentials;
|
||||||
|
this.essentialsVersion = res.version;
|
||||||
|
} else {
|
||||||
|
this.essentials = [];
|
||||||
|
this.essentialsVersion = '';
|
||||||
|
}
|
||||||
},
|
},
|
||||||
async fetchUpdates() {
|
async fetchUpdates() {
|
||||||
if (this.isBusy) return;
|
if (this.isBusy) return;
|
||||||
@@ -156,12 +164,20 @@ export const useSoftwareStore = defineStore('software', {
|
|||||||
// 在获取全量数据之前,先同步云端清单
|
// 在获取全量数据之前,先同步云端清单
|
||||||
await invoke('sync_essentials').catch(() => {});
|
await invoke('sync_essentials').catch(() => {});
|
||||||
|
|
||||||
const [essentials, all, updates] = await Promise.all([
|
const [repo, all, updates] = await Promise.all([
|
||||||
invoke('get_essentials'),
|
invoke('get_essentials') as Promise<any>,
|
||||||
invoke('get_all_software'),
|
invoke('get_all_software'),
|
||||||
invoke('get_updates')
|
invoke('get_updates')
|
||||||
]);
|
]);
|
||||||
this.essentials = essentials as any[];
|
|
||||||
|
if (repo) {
|
||||||
|
this.essentials = repo.essentials;
|
||||||
|
this.essentialsVersion = repo.version;
|
||||||
|
} else {
|
||||||
|
this.essentials = [];
|
||||||
|
this.essentialsVersion = '';
|
||||||
|
}
|
||||||
|
|
||||||
this.allSoftware = all as any[];
|
this.allSoftware = all as any[];
|
||||||
this.updates = updates as any[];
|
this.updates = updates as any[];
|
||||||
this.lastFetched = Date.now();
|
this.lastFetched = Date.now();
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
<header class="content-header">
|
<header class="content-header">
|
||||||
<div class="header-left">
|
<div class="header-left">
|
||||||
<h1>装机必备</h1>
|
<h1>装机必备</h1>
|
||||||
|
<span v-if="store.essentialsVersion" class="version-badge">版本: {{ store.essentialsVersion }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-actions">
|
<div class="header-actions">
|
||||||
<button
|
<button
|
||||||
@@ -101,6 +102,21 @@ onMounted(() => {
|
|||||||
margin-bottom: 24px;
|
margin-bottom: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.header-left {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.version-badge {
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--text-sec);
|
||||||
|
background-color: rgba(0, 0, 0, 0.05);
|
||||||
|
padding: 4px 10px;
|
||||||
|
border-radius: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
.content-header h1 {
|
.content-header h1 {
|
||||||
font-size: 32px;
|
font-size: 32px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
|
|||||||
Reference in New Issue
Block a user