Skip to content

Commit d3764d8

Browse files
committed
支持修改资源路径
1 parent 2af4b69 commit d3764d8

File tree

4 files changed

+195
-29
lines changed

4 files changed

+195
-29
lines changed

src-tauri/src/api/launcher_api.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,17 @@ pub async fn modify_resource_name(
284284
Ok(())
285285
}
286286

287+
/// 修改资源路径
288+
#[tauri::command]
289+
pub async fn modify_resource_path(
290+
db: State<'_, DatabaseManager>,
291+
resource_id: i64,
292+
path: &str,
293+
) -> Result<(), OneClickLaunchError> {
294+
launcher_resource::modify_path(&db.pool, resource_id, path).await?;
295+
Ok(())
296+
}
297+
287298
/// 删除启动器中的资源
288299
#[tauri::command]
289300
pub async fn delete_resource(

src-tauri/src/db/launcher_resource.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,19 @@ where
8585
Ok(())
8686
}
8787

88+
// 修改路径
89+
pub async fn modify_path<'a, E>(executor: E, resource_id: i64, path: &str) -> Result<()>
90+
where
91+
E: Executor<'a, Database = Sqlite>,
92+
{
93+
sqlx::query("UPDATE launcher_resource SET path = ? WHERE id = ?")
94+
.bind(path)
95+
.bind(resource_id)
96+
.execute(executor)
97+
.await?;
98+
Ok(())
99+
}
100+
88101
// 按launcher_id删除
89102
pub async fn delete_by_launcher<'a, E>(executor: E, launcher_id: i64) -> Result<()>
90103
where

src-tauri/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ pub async fn run() -> Result<()> {
172172
launcher_api::add_resource,
173173
launcher_api::add_resources,
174174
launcher_api::modify_resource_name,
175+
launcher_api::modify_resource_path,
175176
launcher_api::delete_resource,
176177
launcher_api::query_launchers,
177178
launcher_api::launch,

src/launcher.vue

Lines changed: 170 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<template>
2-
<div class="launcher" @contextmenu="handleRightClick">
2+
<div class="launcher" @contextmenu="handleRightClick">
33
<div class="header">
44
<span v-if="!isEditing" class="name" @dblclick="editLauncherName" title="双击修改名称">
55
{{ this.data.name }}
@@ -49,14 +49,36 @@
4949

5050
<div class="data-row" v-for="(item, index) in data.resources" :key="item.id" :title="item.path">
5151
<span class="data-text">
52+
<!-- 名称编辑部分 -->
5253
<span v-if="!editingResourceState.get(item.id)" @dblclick="editResourceName(item)" title="双击修改名称">
5354
<strong>{{ item.name }}:</strong>
5455
</span>
55-
<input v-if="editingResourceState.get(item.id)" v-model="newResourceName" class="name-input"
56-
@blur="saveResourceName(item)" @keyup.enter="saveResourceName(item)" />
57-
<span>
56+
<input
57+
v-if="editingResourceState.get(item.id)"
58+
v-model="resourceEditData.get(item.id).name"
59+
class="name-input"
60+
@blur="saveResourceName(item)"
61+
@keyup.enter="saveResourceName(item)"
62+
ref="getResourceNameInputRef(item.id)"
63+
/>
64+
65+
<!-- 路径编辑部分 -->
66+
<span
67+
v-if="!editingResourcePathState.get(item.id)"
68+
@dblclick="editResourcePath(item)"
69+
title="双击修改路径"
70+
class="path-text"
71+
>
5872
{{ item.path }}
5973
</span>
74+
<input
75+
v-if="editingResourcePathState.get(item.id)"
76+
v-model="resourceEditData.get(item.id).path"
77+
class="path-input"
78+
@blur="saveResourcePath(item)"
79+
@keyup.enter="saveResourcePath(item)"
80+
ref="getResourcePathInputRef(item.id)"
81+
/>
6082
</span>
6183
<Press class="press" theme="outline" size="19" @click="openPath(item)" />
6284
<el-popconfirm title="确定要删除吗?" confirm-button-text="确认" cancel-button-text="取消"
@@ -124,48 +146,161 @@ export default {
124146
const addUrlNamePlaceholder = ref("网页");
125147
// 是否正在启动
126148
const isLaunching = ref(false);
127-
const editingResourceState = ref(new Map());
128-
const newResourceName = ref("");
149+
// 编辑状态管理 - 使用Map存储每个资源的编辑状态
150+
const editingResourceState = ref(new Map()); // 名称编辑状态
151+
const editingResourcePathState = ref(new Map()); // 路径编辑状态
152+
153+
// 核心修复:使用Map为每个资源存储独立的编辑数据
154+
const resourceEditData = ref(new Map()); // 存储格式: { 资源ID => { name: '', path: '' } }
155+
156+
// 输入框引用管理
129157
const launcherNameInputRef = ref(null);
130-
const resourceNameInputRef = ref(null);
158+
const resourceNameInputRefs = ref(new Map()); // 名称输入框引用
159+
const resourcePathInputRefs = ref(new Map()); // 路径输入框引用
160+
131161
const debouncedLaunch = ref(null);
162+
163+
// 获取名称输入框引用
164+
const getResourceNameInputRef = (id) => {
165+
return (el) => {
166+
if (el) {
167+
resourceNameInputRefs.value.set(id, el);
168+
} else {
169+
resourceNameInputRefs.value.delete(id);
170+
}
171+
};
172+
};
173+
174+
// 获取路径输入框引用
175+
const getResourcePathInputRef = (id) => {
176+
return (el) => {
177+
if (el) {
178+
resourcePathInputRefs.value.set(id, el);
179+
} else {
180+
resourcePathInputRefs.value.delete(id);
181+
}
182+
};
183+
};
132184
133185
const editLauncherName = () => {
134-
isEditing.value = true; // 进入编辑模式
135-
newLauncherName.value = props.launcherData.name; // 预填当前名称
186+
isEditing.value = true;
187+
newLauncherName.value = props.launcherData.name;
136188
nextTick(() => {
137189
launcherNameInputRef.value && launcherNameInputRef.value.focus();
138190
});
139191
};
192+
140193
const saveLauncherName = async () => {
141194
if (newLauncherName.value.trim()) {
142-
newLauncherName.value = newLauncherName.value.trim(); // 保存修改后的名称
195+
newLauncherName.value = newLauncherName.value.trim();
143196
}
144197
await invoke("modify_launcher_name", { launcherId: props.launcherData.id, name: newLauncherName.value });
145-
isEditing.value = false; // 退出编辑模式
198+
isEditing.value = false;
146199
emit("launcher-updated", props.launcherData.id);
147200
};
201+
148202
const editResourceName = (item) => {
149-
editingResourceState.value.set(item.id, true); // 进入编辑模式
150-
newResourceName.value = item.name; // 预填当前名称
203+
// 关闭当前资源的路径编辑状态(避免冲突)
204+
editingResourcePathState.value.set(item.id, false);
205+
206+
// 标记为名称编辑状态
207+
editingResourceState.value.set(item.id, true);
208+
209+
// 初始化该资源的编辑数据(确保每个资源有独立存储)
210+
const currentData = resourceEditData.value.get(item.id) || { name: '', path: '' };
211+
currentData.name = item.name; // 仅更新名称字段
212+
resourceEditData.value.set(item.id, currentData);
213+
214+
// 自动聚焦
151215
nextTick(() => {
152-
// 自动聚焦到输入框
153-
resourceNameInputRef.value && resourceNameInputRef.value.focus();
216+
const inputRef = resourceNameInputRefs.value.get(item.id);
217+
inputRef && inputRef.focus();
154218
});
155219
};
220+
156221
const saveResourceName = async (item) => {
157-
if (newResourceName.value.trim()) {
158-
const trimName = newResourceName.value.trim();
159-
if (item.name === trimName) {
160-
editingResourceState.value.set(item.id, false); // 退出编辑模式
161-
return;
162-
}
163-
newResourceName.value = trimName; // 保存修改后的名称
222+
// 获取该资源的独立编辑数据
223+
const editData = resourceEditData.value.get(item.id);
224+
if (!editData) return;
225+
226+
const trimmedName = editData.name.trim();
227+
228+
// 验证和退出编辑状态
229+
if (!trimmedName) {
230+
editingResourceState.value.set(item.id, false);
231+
toast.warning("名称不能为空!");
232+
return;
233+
}
234+
235+
if (trimmedName === item.name) {
236+
editingResourceState.value.set(item.id, false);
237+
return;
238+
}
239+
240+
// 保存修改
241+
try {
242+
await invoke("modify_resource_name", {
243+
resourceId: item.id,
244+
name: trimmedName
245+
});
246+
editingResourceState.value.set(item.id, false);
247+
emit("launcher-updated", props.launcherData.id);
248+
} catch (error) {
249+
console.error("修改资源名称失败:", error);
164250
}
165-
await invoke("modify_resource_name", { resourceId: item.id, name: newResourceName.value });
166-
editingResourceState.value.set(item.id, false); // 退出编辑模式
167-
emit("launcher-updated", props.launcherData.id);
168251
};
252+
253+
const editResourcePath = (item) => {
254+
// 关闭当前资源的名称编辑状态(避免冲突)
255+
editingResourceState.value.set(item.id, false);
256+
257+
// 标记为路径编辑状态
258+
editingResourcePathState.value.set(item.id, true);
259+
260+
// 初始化该资源的编辑数据
261+
const currentData = resourceEditData.value.get(item.id) || { name: '', path: '' };
262+
currentData.path = item.path; // 仅更新路径字段
263+
resourceEditData.value.set(item.id, currentData);
264+
265+
// 自动聚焦
266+
nextTick(() => {
267+
const inputRef = resourcePathInputRefs.value.get(item.id);
268+
inputRef && inputRef.focus();
269+
});
270+
};
271+
272+
const saveResourcePath = async (item) => {
273+
// 获取该资源的独立编辑数据
274+
const editData = resourceEditData.value.get(item.id);
275+
if (!editData) return;
276+
277+
const trimmedPath = editData.path.trim();
278+
279+
// 验证和退出编辑状态
280+
if (!trimmedPath) {
281+
editingResourcePathState.value.set(item.id, false);
282+
toast.warning("路径不能为空!");
283+
return;
284+
}
285+
286+
if (trimmedPath === item.path) {
287+
editingResourcePathState.value.set(item.id, false);
288+
return;
289+
}
290+
291+
// 保存修改
292+
try {
293+
await invoke("modify_resource_path", {
294+
resourceId: item.id,
295+
path: trimmedPath
296+
});
297+
editingResourcePathState.value.set(item.id, false);
298+
emit("launcher-updated", props.launcherData.id);
299+
} catch (error) {
300+
console.error("修改资源路径失败:", error);
301+
}
302+
};
303+
169304
const addRow = async (directory) => {
170305
try {
171306
@@ -260,6 +395,7 @@ export default {
260395
timer = setTimeout(() => func.apply(this, args), delay);
261396
};
262397
};
398+
263399
onBeforeMount(() => {
264400
// 包装 launch 方法为防抖函数
265401
debouncedLaunch.value = debounce(launch, 2000); // 2秒防抖
@@ -275,8 +411,6 @@ export default {
275411
addUrlContent,
276412
addUrlNamePlaceholder,
277413
isLaunching,
278-
editingResourceState,
279-
newResourceName,
280414
editLauncherName,
281415
saveLauncherName,
282416
editResourceName,
@@ -293,7 +427,15 @@ export default {
293427
debounce,
294428
debouncedLaunch,
295429
openPath,
296-
handleRightClick
430+
handleRightClick,
431+
editResourcePath,
432+
saveResourcePath,
433+
editingResourceState,
434+
editingResourcePathState,
435+
resourceEditData,
436+
launcherNameInputRef,
437+
resourceNameInputRefs,
438+
resourcePathInputRefs
297439
};
298440
}
299441
};
@@ -584,5 +726,4 @@ hr {
584726
/* 取消 active 缩小 */
585727
transform: none;
586728
}
587-
588729
</style>

0 commit comments

Comments
 (0)