upgrade essentials versions
This commit is contained in:
@@ -22,6 +22,12 @@ pub struct EssentialsRepo {
|
|||||||
pub essentials: Vec<Software>,
|
pub essentials: Vec<Software>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
|
pub struct InstallTask {
|
||||||
|
pub id: String,
|
||||||
|
pub version: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
impl Default for AppSettings {
|
impl Default for AppSettings {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -31,7 +37,7 @@ impl Default for AppSettings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct AppState {
|
struct AppState {
|
||||||
install_tx: mpsc::Sender<String>,
|
install_tx: mpsc::Sender<InstallTask>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Serialize)]
|
#[derive(Clone, Serialize)]
|
||||||
@@ -159,8 +165,8 @@ async fn get_updates(app: AppHandle) -> Vec<Software> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
async fn install_software(id: String, state: State<'_, AppState>) -> Result<(), String> {
|
async fn install_software(id: String, version: Option<String>, state: State<'_, AppState>) -> Result<(), String> {
|
||||||
state.install_tx.send(id).await.map_err(|e| e.to_string())
|
state.install_tx.send(InstallTask { id, version }).await.map_err(|e| e.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
@@ -180,14 +186,17 @@ pub fn run() {
|
|||||||
.plugin(tauri_plugin_opener::init())
|
.plugin(tauri_plugin_opener::init())
|
||||||
.setup(move |app| {
|
.setup(move |app| {
|
||||||
let handle = app.handle().clone();
|
let handle = app.handle().clone();
|
||||||
let (tx, mut rx) = mpsc::channel::<String>(100);
|
let (tx, mut rx) = mpsc::channel::<InstallTask>(100);
|
||||||
app.manage(AppState { install_tx: tx });
|
app.manage(AppState { install_tx: tx });
|
||||||
|
|
||||||
tauri::async_runtime::spawn(async move {
|
tauri::async_runtime::spawn(async move {
|
||||||
let perc_re = Regex::new(r"(\d+)\s*%").unwrap();
|
let perc_re = Regex::new(r"(\d+)\s*%").unwrap();
|
||||||
let size_re = Regex::new(r"([\d\.]+)\s*[a-zA-Z]+\s*/\s*([\d\.]+)\s*[a-zA-Z]+").unwrap();
|
let size_re = Regex::new(r"([\d\.]+)\s*[a-zA-Z]+\s*/\s*([\d\.]+)\s*[a-zA-Z]+").unwrap();
|
||||||
|
|
||||||
while let Some(id) = rx.recv().await {
|
while let Some(task) = rx.recv().await {
|
||||||
|
let id = task.id;
|
||||||
|
let version = task.version;
|
||||||
|
|
||||||
let log_id = format!("install-{}", id);
|
let log_id = format!("install-{}", id);
|
||||||
let _ = handle.emit("install-status", InstallProgress {
|
let _ = handle.emit("install-status", InstallProgress {
|
||||||
id: id.clone(),
|
id: id.clone(),
|
||||||
@@ -195,17 +204,34 @@ pub fn run() {
|
|||||||
progress: 0.0,
|
progress: 0.0,
|
||||||
});
|
});
|
||||||
|
|
||||||
emit_log(&handle, &log_id, &format!("Winget Install: {}", id), "Starting...", "info");
|
let display_cmd = match &version {
|
||||||
|
Some(v) => format!("Winget Install: {} (v{})", id, v),
|
||||||
|
None => format!("Winget Install: {}", id),
|
||||||
|
};
|
||||||
|
emit_log(&handle, &log_id, &display_cmd, "Starting...", "info");
|
||||||
|
|
||||||
let id_for_cmd = id.clone();
|
let id_for_cmd = id.clone();
|
||||||
let h = handle.clone();
|
let h = handle.clone();
|
||||||
|
|
||||||
|
let mut args = vec![
|
||||||
|
"install".to_string(),
|
||||||
|
"--id".to_string(), id_for_cmd.clone(),
|
||||||
|
"-e".to_string(),
|
||||||
|
"--silent".to_string(),
|
||||||
|
"--accept-package-agreements".to_string(),
|
||||||
|
"--accept-source-agreements".to_string(),
|
||||||
|
"--disable-interactivity".to_string(),
|
||||||
|
];
|
||||||
|
|
||||||
|
if let Some(v) = version {
|
||||||
|
if !v.is_empty() {
|
||||||
|
args.push("--version".to_string());
|
||||||
|
args.push(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let child = Command::new("winget")
|
let child = Command::new("winget")
|
||||||
.args([
|
.args(&args)
|
||||||
"install", "--id", &id_for_cmd, "-e", "--silent",
|
|
||||||
"--accept-package-agreements", "--accept-source-agreements",
|
|
||||||
"--disable-interactivity"
|
|
||||||
])
|
|
||||||
.stdout(Stdio::piped())
|
.stdout(Stdio::piped())
|
||||||
.stderr(Stdio::piped())
|
.stderr(Stdio::piped())
|
||||||
.creation_flags(0x08000000)
|
.creation_flags(0x08000000)
|
||||||
|
|||||||
@@ -35,8 +35,16 @@
|
|||||||
</div>
|
</div>
|
||||||
<p class="description" v-if="software.description">{{ software.description }}</p>
|
<p class="description" v-if="software.description">{{ software.description }}</p>
|
||||||
<div class="version-info">
|
<div class="version-info">
|
||||||
<span class="version-tag">当前: {{ software.version || '--' }}</span>
|
<template v-if="software.status === 'installed'">
|
||||||
<span class="version-tag available" v-if="software.available_version">
|
<span class="version-tag">当前: {{ software.version || '--' }}</span>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<span class="version-tag recommended">
|
||||||
|
推荐: {{ software.version || '最新版' }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<span class="version-tag available" v-if="software.status !== 'installed' && software.available_version">
|
||||||
最新: {{ software.available_version }}
|
最新: {{ software.available_version }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -276,7 +284,7 @@ const handleCardClick = () => {
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.version-tag.available {
|
.version-tag.available, .version-tag.recommended {
|
||||||
color: var(--primary-color);
|
color: var(--primary-color);
|
||||||
background: rgba(0, 122, 255, 0.08);
|
background: rgba(0, 122, 255, 0.08);
|
||||||
padding: 0 6px;
|
padding: 0 6px;
|
||||||
|
|||||||
@@ -33,13 +33,16 @@ export const useSoftwareStore = defineStore('software', {
|
|||||||
// ... (mergedEssentials, sortedUpdates, sortedAllSoftware, isBusy getters stay the same)
|
// ... (mergedEssentials, sortedUpdates, sortedAllSoftware, isBusy getters stay the same)
|
||||||
mergedEssentials: (state) => {
|
mergedEssentials: (state) => {
|
||||||
return state.essentials.map(item => {
|
return state.essentials.map(item => {
|
||||||
const isInstalled = state.allSoftware.some(s => s.id.toLowerCase() === item.id.toLowerCase());
|
const installedInfo = state.allSoftware.find(s => s.id.toLowerCase() === item.id.toLowerCase());
|
||||||
|
const isInstalled = !!installedInfo;
|
||||||
const hasUpdate = state.updates.some(s => s.id.toLowerCase() === item.id.toLowerCase());
|
const hasUpdate = state.updates.some(s => s.id.toLowerCase() === item.id.toLowerCase());
|
||||||
|
|
||||||
let displayStatus = item.status;
|
let displayStatus = item.status;
|
||||||
let actionLabel = '安装';
|
let actionLabel = '安装';
|
||||||
|
let currentVersion = item.version; // 默认使用清单中的推荐版本
|
||||||
|
|
||||||
if (isInstalled) {
|
if (isInstalled) {
|
||||||
|
currentVersion = installedInfo.version; // 如果已安装,显示本地真实版本
|
||||||
if (hasUpdate) {
|
if (hasUpdate) {
|
||||||
actionLabel = '更新';
|
actionLabel = '更新';
|
||||||
} else if (displayStatus === 'idle') {
|
} else if (displayStatus === 'idle') {
|
||||||
@@ -47,7 +50,14 @@ export const useSoftwareStore = defineStore('software', {
|
|||||||
actionLabel = '已安装';
|
actionLabel = '已安装';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return { ...item, status: displayStatus, actionLabel };
|
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
version: currentVersion,
|
||||||
|
recommended_version: item.version, // 额外保存一个原始推荐版本字段供前端判断
|
||||||
|
status: displayStatus,
|
||||||
|
actionLabel
|
||||||
|
};
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
sortedUpdates: (state) => [...state.updates].sort(sortByName),
|
sortedUpdates: (state) => [...state.updates].sort(sortByName),
|
||||||
@@ -191,8 +201,10 @@ export const useSoftwareStore = defineStore('software', {
|
|||||||
},
|
},
|
||||||
async install(id: string) {
|
async install(id: string) {
|
||||||
const software = this.findSoftware(id)
|
const software = this.findSoftware(id)
|
||||||
if (software) software.status = 'pending';
|
if (software) {
|
||||||
await invoke('install_software', { id })
|
software.status = 'pending';
|
||||||
|
await invoke('install_software', { id, version: software.version })
|
||||||
|
}
|
||||||
},
|
},
|
||||||
findSoftware(id: string) {
|
findSoftware(id: string) {
|
||||||
return this.essentials.find(s => s.id === id) ||
|
return this.essentials.find(s => s.id === id) ||
|
||||||
|
|||||||
Reference in New Issue
Block a user