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

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"); const result = await api<FolderTreeResponse>("/api/folders");
appState.folders = result.folders; appState.folders = result.folders;
const root = appState.folders.find((folder) => folder.parent_id === null); const root = appState.folders.find((folder) => folder.parent_id === null);
@@ -125,8 +126,10 @@ export async function loadFolders() {
if (appState.selectedFolderId) { if (appState.selectedFolderId) {
$("#folderTree").on("ready.jstree", () => { $("#folderTree").on("ready.jstree", () => {
$("#folderTree").jstree(true).select_node(String(appState.selectedFolderId)); $("#folderTree").jstree(true).select_node(String(appState.selectedFolderId), true);
}); });
} }
await loadModels(); if (reloadModels) {
await loadModels();
}
} }

View File

@@ -45,6 +45,7 @@ let dictionariesLoading: Promise<void> | null = null;
let sceneModelBridgeBound = false; let sceneModelBridgeBound = false;
let pendingSceneModelRequestId = ""; let pendingSceneModelRequestId = "";
let pendingSceneModelRequestTimer: number | null = null; let pendingSceneModelRequestTimer: number | null = null;
let visibleModels = new Map<number, ModelItem>();
export function bindModelActions() { export function bindModelActions() {
const isAdmin = getCurrentUser()?.role === "admin"; 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"); const grid = document.querySelector<HTMLDivElement>("#modelGrid");
if (!grid || !appState.selectedFolderId) return; if (!grid || !appState.selectedFolderId) return;
await loadDictionaries(); await loadDictionaries();
@@ -153,42 +154,85 @@ export async function loadModels() {
await loadModels(); await loadModels();
} }
}); });
grid.innerHTML = result.items.map(renderModelCard).join("") || `<div class="empty-state">当前目录暂无模型</div>`; visibleModels = new Map(result.items.map((item) => [item.id, item]));
grid.querySelectorAll<HTMLButtonElement>("[data-action='preview']").forEach((button) => { renderModelGrid(grid, result.items, options.preserveCards);
const model = result.items.find((item) => item.id === Number(button.dataset.id)); bindModelGridActions(grid);
if (model) { }
button.addEventListener("click", async () => {
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"); const { openModelPreview } = await import("./preview");
openModelPreview(model, loadModels); openModelPreview(model, loadModels);
}); break;
}
case "edit":
await editModel(id);
break;
case "import": {
if (!model) return;
const { createImportScenePayload, emitImportScenePayload } = await import("./preview");
const payload = createImportScenePayload({
model,
basePointEnabled: false,
basePoint: { x: 0, y: 0, z: 0, rx: 0, ry: 0, rz: 0 },
selectedOperationIndex: null
});
emitImportScenePayload(payload);
notify("导入场景数据已输出");
break;
}
case "delete":
await deleteModel(id);
break;
}
} catch (error) {
notifyError(error);
} }
}); });
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));
if (!model) return;
button.addEventListener("click", async () => {
const { createImportScenePayload, emitImportScenePayload } = await import("./preview");
const payload = createImportScenePayload({
model,
basePointEnabled: false,
basePoint: { x: 0, y: 0, z: 0, rx: 0, ry: 0, rz: 0 },
selectedOperationIndex: null
});
emitImportScenePayload(payload);
notify("导入场景数据已输出");
});
});
grid.querySelectorAll<HTMLButtonElement>("[data-action='delete']").forEach((button) => {
button.addEventListener("click", () => deleteModel(Number(button.dataset.id)));
});
} }
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"); const { loadFolders } = await import("./folders");
await loadFolders(); await loadFolders({ reloadModels: false });
await loadModels({ preserveCards: preserveModelCards });
} }
async function loadDictionaries(force = false) { async function loadDictionaries(force = false) {
@@ -786,5 +830,5 @@ async function deleteModel(id: number) {
const confirmed = await confirmDialog("确认删除该模型?"); const confirmed = await confirmDialog("确认删除该模型?");
if (!confirmed) return; if (!confirmed) return;
await api(`/api/models/${id}`, { method: "DELETE" }); await api(`/api/models/${id}`, { method: "DELETE" });
await reloadFoldersAndModels(); await reloadFoldersAndModels(true);
} }