优化模型删除后的列表刷新

This commit is contained in:
zhangshun
2026-06-01 13:26:31 +08:00
parent 00f7dc1686
commit 6206c9556b
2 changed files with 81 additions and 34 deletions

View File

@@ -63,7 +63,8 @@ async function runFolderAction(action: () => Promise<void>) {
}
}
export async function loadFolders() {
export async function loadFolders(options: { reloadModels?: boolean } = {}) {
const reloadModels = options.reloadModels ?? true;
const result = await api<FolderTreeResponse>("/api/folders");
appState.folders = result.folders;
const root = appState.folders.find((folder) => folder.parent_id === null);
@@ -125,8 +126,10 @@ export async function loadFolders() {
if (appState.selectedFolderId) {
$("#folderTree").on("ready.jstree", () => {
$("#folderTree").jstree(true).select_node(String(appState.selectedFolderId));
$("#folderTree").jstree(true).select_node(String(appState.selectedFolderId), true);
});
}
if (reloadModels) {
await loadModels();
}
}

View File

@@ -45,6 +45,7 @@ let dictionariesLoading: Promise<void> | null = null;
let sceneModelBridgeBound = false;
let pendingSceneModelRequestId = "";
let pendingSceneModelRequestTimer: number | null = null;
let visibleModels = new Map<number, ModelItem>();
export function bindModelActions() {
const isAdmin = getCurrentUser()?.role === "admin";
@@ -123,7 +124,7 @@ export function bindModelActions() {
});
}
export async function loadModels() {
export async function loadModels(options: { preserveCards?: boolean } = {}) {
const grid = document.querySelector<HTMLDivElement>("#modelGrid");
if (!grid || !appState.selectedFolderId) return;
await loadDictionaries();
@@ -153,23 +154,33 @@ export async function loadModels() {
await loadModels();
}
});
grid.innerHTML = result.items.map(renderModelCard).join("") || `<div class="empty-state">当前目录暂无模型</div>`;
grid.querySelectorAll<HTMLButtonElement>("[data-action='preview']").forEach((button) => {
const model = result.items.find((item) => item.id === Number(button.dataset.id));
if (model) {
button.addEventListener("click", async () => {
visibleModels = new Map(result.items.map((item) => [item.id, item]));
renderModelGrid(grid, result.items, options.preserveCards);
bindModelGridActions(grid);
}
function bindModelGridActions(grid: HTMLDivElement) {
if (grid.dataset.actionsBound === "true") return;
grid.dataset.actionsBound = "true";
grid.addEventListener("click", async (event) => {
const target = event.target instanceof Element ? event.target : null;
const button = target?.closest<HTMLButtonElement>("button[data-action][data-id]");
if (!button || !grid.contains(button)) return;
const id = Number(button.dataset.id);
const model = visibleModels.get(id);
try {
switch (button.dataset.action) {
case "preview": {
if (!model) return;
const { openModelPreview } = await import("./preview");
openModelPreview(model, loadModels);
});
break;
}
});
grid.querySelectorAll<HTMLButtonElement>("[data-action='edit']").forEach((button) => {
button.addEventListener("click", () => editModel(Number(button.dataset.id)));
});
grid.querySelectorAll<HTMLButtonElement>("[data-action='import']").forEach((button) => {
const model = result.items.find((item) => item.id === Number(button.dataset.id));
case "edit":
await editModel(id);
break;
case "import": {
if (!model) return;
button.addEventListener("click", async () => {
const { createImportScenePayload, emitImportScenePayload } = await import("./preview");
const payload = createImportScenePayload({
model,
@@ -179,16 +190,49 @@ export async function loadModels() {
});
emitImportScenePayload(payload);
notify("导入场景数据已输出");
});
});
grid.querySelectorAll<HTMLButtonElement>("[data-action='delete']").forEach((button) => {
button.addEventListener("click", () => deleteModel(Number(button.dataset.id)));
break;
}
case "delete":
await deleteModel(id);
break;
}
} catch (error) {
notifyError(error);
}
});
}
async function reloadFoldersAndModels() {
function renderModelGrid(grid: HTMLDivElement, items: ModelItem[], preserveCards = false) {
if (!preserveCards) {
grid.innerHTML = items.map(renderModelCard).join("") || `<div class="empty-state">当前目录暂无模型</div>`;
return;
}
if (items.length === 0) {
grid.innerHTML = `<div class="empty-state">当前目录暂无模型</div>`;
return;
}
const existingCards = new Map(
Array.from(grid.querySelectorAll<HTMLElement>(".model-card[data-model-id]"))
.map((card) => [Number(card.dataset.modelId), card])
);
const fragment = document.createDocumentFragment();
for (const item of items) {
const existingCard = existingCards.get(item.id);
if (existingCard) {
fragment.append(existingCard);
continue;
}
const template = document.createElement("template");
template.innerHTML = renderModelCard(item).trim();
fragment.append(template.content);
}
grid.replaceChildren(fragment);
}
async function reloadFoldersAndModels(preserveModelCards = false) {
const { loadFolders } = await import("./folders");
await loadFolders();
await loadFolders({ reloadModels: false });
await loadModels({ preserveCards: preserveModelCards });
}
async function loadDictionaries(force = false) {
@@ -786,5 +830,5 @@ async function deleteModel(id: number) {
const confirmed = await confirmDialog("确认删除该模型?");
if (!confirmed) return;
await api(`/api/models/${id}`, { method: "DELETE" });
await reloadFoldersAndModels();
await reloadFoldersAndModels(true);
}