1、将排序做到border-b transition-colors hover:bg-muted/50 has-aria-expanded:bg-muted/50 data-[state=selected]:bg-muted里,无需单独做个button 2、指定重命名使用ICO,无需使用菜单
This commit is contained in:
1 parent
48e85b33d6
commit
86eb67ea0a
15 files changed
+957
-20
No files matched your search
@@ -215,6 +215,9 @@ export const api = {
|
||||
coverage_enabled: input.coverageEnabled ?? true, // 默认开;false=关闭资产覆盖度功能
|
||||
}),
|
||||
taskCategories: () => get<{ categories: TaskCategory[] }>("/task-categories").then((r) => arr(r.categories)),
|
||||
updateTask: (id: string, input: { name?: string; pinned?: boolean }) => patch<Task>(`/tasks/${id}`, input),
|
||||
renameTask: (id: string, name: string) => patch<Task>(`/tasks/${id}`, { name }),
|
||||
pinTask: (id: string, pinned: boolean) => patch<Task>(`/tasks/${id}`, { pinned }),
|
||||
createTaskCategory: (name: string) => post<TaskCategory>("/task-categories", { name }),
|
||||
renameTaskCategory: (id: number, name: string) => patch<TaskCategory>(`/task-categories/${id}`, { name }),
|
||||
deleteTaskCategory: (id: number) => del<{ deleted: number }>(`/task-categories/${id}`),
|
||||
@@ -704,6 +707,8 @@ export const api = {
|
||||
updateConversationProfile: (id: number, llm_profile_id: number | null) =>
|
||||
patch<{ ok: boolean }>(`/conversations/${id}/profile`, { llm_profile_id }),
|
||||
deleteConversation: (id: number) => del<{ deleted: number }>(`/conversations/${id}`),
|
||||
deleteConversations: (ids: number[]) =>
|
||||
post<{ items: { id: number; ok: boolean; error?: string }[] }>("/conversations/delete/batch", { ids }),
|
||||
// Incremental tail: steps after `since` (id ASC) — live poll + post-send fetch.
|
||||
conversationMessages: (id: number, since = 0) =>
|
||||
get<{ items: Activity[]; cursor: number; running: boolean }>(`/conversations/${id}/messages?since=${since}`).then(
|
||||
|
||||
@@ -233,6 +233,16 @@ function sortMockConversations() {
|
||||
});
|
||||
}
|
||||
|
||||
function sortMockTasks() {
|
||||
mockTasks.sort((a, b) => {
|
||||
const aPinned = a.pinned_at ? 1 : 0;
|
||||
const bPinned = b.pinned_at ? 1 : 0;
|
||||
if (aPinned !== bPinned) return bPinned - aPinned;
|
||||
if (a.pinned_at !== b.pinned_at) return (b.pinned_at ?? "").localeCompare(a.pinned_at ?? "");
|
||||
return b.id.localeCompare(a.id, undefined, { numeric: true });
|
||||
});
|
||||
}
|
||||
|
||||
function normalizedTemplateName(value: unknown): string {
|
||||
return String(value ?? "")
|
||||
.trim()
|
||||
@@ -268,7 +278,10 @@ function route(m: string, path: string, seg: string[], q: URLSearchParams, b: Re
|
||||
if (path === "/auth/change-password") return { ok: true };
|
||||
|
||||
// ── tasks ──
|
||||
if (path === "/tasks" && m === "GET") return { tasks: mockTasks, active: mockActiveTask };
|
||||
if (path === "/tasks" && m === "GET") {
|
||||
sortMockTasks();
|
||||
return { tasks: mockTasks, active: mockActiveTask };
|
||||
}
|
||||
if (path === "/tasks" && m === "POST") {
|
||||
let suffix = 1;
|
||||
while (mockTasks.some((item) => item.id === `t-new-${suffix}`)) suffix++;
|
||||
@@ -436,6 +449,17 @@ function route(m: string, path: string, seg: string[], q: URLSearchParams, b: Re
|
||||
if (index >= 0) mockTaskTemplates.splice(index, 1);
|
||||
return { deleted: id };
|
||||
}
|
||||
if (seg[0] === "tasks" && seg.length === 2 && m === "PATCH") {
|
||||
const task = mockTasks.find((item) => item.id === seg[1]);
|
||||
if (!task) throw new Error("任务不存在");
|
||||
if (typeof b.name === "string") task.name = b.name.trim();
|
||||
if (typeof b.pinned === "boolean") {
|
||||
task.pinned = b.pinned;
|
||||
task.pinned_at = b.pinned ? (task.pinned_at ?? new Date().toISOString()) : null;
|
||||
}
|
||||
sortMockTasks();
|
||||
return structuredClone(task);
|
||||
}
|
||||
if (seg[0] === "tasks" && seg.length === 2 && m === "DELETE") {
|
||||
const id = seg[1];
|
||||
const index = mockTasks.findIndex((item) => item.id === id);
|
||||
@@ -1187,6 +1211,18 @@ function route(m: string, path: string, seg: string[], q: URLSearchParams, b: Re
|
||||
if (index >= 0) mockConversations.splice(index, 1);
|
||||
return { deleted: id };
|
||||
}
|
||||
if (path === "/conversations/delete/batch" && m === "POST") {
|
||||
const ids = Array.isArray(b.ids)
|
||||
? [...new Set(b.ids.map(Number).filter((id) => Number.isInteger(id) && id > 0))]
|
||||
: [];
|
||||
const items = ids.map((id) => {
|
||||
const index = mockConversations.findIndex((item) => item.id === id);
|
||||
if (index < 0) return { id, ok: false, error: "conversation not found" };
|
||||
mockConversations.splice(index, 1);
|
||||
return { id, ok: true };
|
||||
});
|
||||
return { items };
|
||||
}
|
||||
if (seg[0] === "conversations" && seg[2] === "messages" && seg.length === 3 && m === "GET") {
|
||||
const items = D.conversationMessages[Number(seg[1])] ?? [];
|
||||
return { items, cursor: items.length ? items[items.length - 1].seq : 0, running: false };
|
||||
|
||||
@@ -9,6 +9,8 @@ export interface Task {
|
||||
name?: string; // 可选任务名称;空/缺省=未命名,展示时回退到描述
|
||||
category_id?: number;
|
||||
category_name?: string;
|
||||
pinned?: boolean;
|
||||
pinned_at?: string | null;
|
||||
description: string;
|
||||
goal: string;
|
||||
status: TaskStatus;
|
||||
|
||||
Reference in new issue
Block a user