diff --git a/server/src/folders.ts b/server/src/folders.ts
index 3f0a997..464c5b8 100644
--- a/server/src/folders.ts
+++ b/server/src/folders.ts
@@ -20,7 +20,7 @@ const updateSchema = z.object({
function buildTree(rows: FolderRow[]) {
const nodes = rows.map((row) => ({
id: String(row.id),
- text: row.name,
+ text: `${row.name}(${row.model_count ?? 0})`,
parentId: row.parent_id,
path: row.path,
children: [] as unknown[]
@@ -53,7 +53,15 @@ function assertCanRenameRoot(folder: FolderRow) {
export async function folderRoutes(app: FastifyInstance) {
app.get("/api/folders", { preHandler: [requireAuth] }, async () => {
- const rows = db.prepare("SELECT * FROM folders ORDER BY parent_id, name").all() as unknown as FolderRow[];
+ const rows = db.prepare(`
+ SELECT
+ f.*,
+ COUNT(m.id) AS model_count
+ FROM folders f
+ LEFT JOIN models m ON m.folder_id = f.id
+ GROUP BY f.id
+ ORDER BY f.parent_id, f.name
+ `).all() as unknown as FolderRow[];
return { folders: rows, tree: buildTree(rows) };
});
diff --git a/server/src/types.ts b/server/src/types.ts
index 213755c..08a687d 100644
--- a/server/src/types.ts
+++ b/server/src/types.ts
@@ -22,6 +22,7 @@ export interface FolderRow {
parent_id: number | null;
name: string;
path: string;
+ model_count?: number;
created_at: string;
updated_at: string;
}
diff --git a/web/src/pages/app/layout.ts b/web/src/pages/app/layout.ts
index 213be35..36d6f82 100644
--- a/web/src/pages/app/layout.ts
+++ b/web/src/pages/app/layout.ts
@@ -32,7 +32,6 @@ export async function renderApp() {
${isAdmin ? `` : ""}
diff --git a/web/src/pages/app/modules/folders.ts b/web/src/pages/app/modules/folders.ts
index b18af85..15cf309 100644
--- a/web/src/pages/app/modules/folders.ts
+++ b/web/src/pages/app/modules/folders.ts
@@ -14,7 +14,7 @@ type JsTreeNode = {
function selectFolder(node: JsTreeNode) {
appState.selectedFolderId = Number(node.id);
- appState.selectedFolderName = node.text;
+ appState.selectedFolderName = appState.folders.find((folder) => folder.id === Number(node.id))?.name ?? node.text;
}
async function createFolder(parentId: number | null) {
@@ -111,7 +111,7 @@ export async function loadFolders() {
}
}).on("select_node.jstree", async (_event: JQuery.Event, data: { node: { id: string; text: string } }) => {
appState.selectedFolderId = Number(data.node.id);
- appState.selectedFolderName = data.node.text;
+ appState.selectedFolderName = appState.folders.find((folder) => folder.id === appState.selectedFolderId)?.name ?? data.node.text;
appState.page = 1;
await loadModels();
});
diff --git a/web/src/pages/app/modules/models.ts b/web/src/pages/app/modules/models.ts
index 23b27c9..961771e 100644
--- a/web/src/pages/app/modules/models.ts
+++ b/web/src/pages/app/modules/models.ts
@@ -91,7 +91,6 @@ export async function loadModels() {
appState.page -= 1;
return loadModels();
}
- document.querySelector("#modelCount")!.textContent = `${result.total} 个模型`;
renderPagination({
container: document.querySelector("#modelPagination")!,
total: result.total,
diff --git a/web/src/styles/base.css b/web/src/styles/base.css
index fdee96b..be6816c 100644
--- a/web/src/styles/base.css
+++ b/web/src/styles/base.css
@@ -62,6 +62,9 @@ select {
.jstree-default .jstree-anchor {
height: 24px;
line-height: 24px;
+ max-width: 100%;
+ overflow: hidden;
+ text-overflow: ellipsis;
}
.jstree-default .jstree-icon:empty {
diff --git a/web/src/types.ts b/web/src/types.ts
index 11af5c0..7b2e047 100644
--- a/web/src/types.ts
+++ b/web/src/types.ts
@@ -25,6 +25,7 @@ export type Folder = {
parent_id: number | null;
name: string;
path: string;
+ model_count: number;
};
export type ModelItem = {