From dbd804d6e3d6b72a3b0b0fc939bbfb84e5bb833d Mon Sep 17 00:00:00 2001 From: wizardchen Date: Thu, 30 Apr 2026 15:14:49 +0800 Subject: [PATCH] feat(sessions): add keyword search, user-scoped pinning, and IM source visibility Sessions today are a flat list ordered by updated_at. Two gaps showed up in practice: - Users cannot find specific chats as the list grows beyond a screen. - IM-created sessions (WeCom/Feishu/Slack/...) are indistinguishable: every title was "IM-" or "IM--" and the list API hid the underlying im_channel_sessions mapping, so admins had no way to tell which Feishu group a session came from. Backend - Migration 000039 adds sessions.user_id (owner), is_pinned, pinned_at plus a composite index for the list query. Existing rows keep user_id NULL and stay visible at the tenant level for backward compatibility. - CreateSession now writes the caller's user_id from auth context. - GET /sessions accepts keyword / source / agent_id. When any filter is set, the response switches to enriched items that LEFT JOIN im_channel_sessions and expose im_platform / im_chat_id / im_thread_id / im_user_id / im_agent_id / im_channel_id. No filters => legacy shape, existing clients unaffected. - Ordering: is_pinned DESC, pinned_at DESC NULLS LAST, updated_at DESC. - POST/DELETE /sessions/:id/pin for user-scoped pin/unpin. - IM session titles: "[platform] " with short ID suffixes so group/DM/thread sessions are visually distinct without needing a round-trip to fetch a display name from the IM adapter. Frontend - Search input debounced at 300ms drives the keyword filter. - Pinned chats render in a dedicated group above the time-based groups, with a pin icon and a pin/unpin entry in the per-chat dropdown. - IM chats get a short [platform] badge in the list. - Pin toggle is optimistic and guards against double-clicks. - zh/en/ko/ru i18n keys added for the new strings. --- frontend/src/api/chat/index.ts | 22 ++- frontend/src/components/menu.vue | 162 +++++++++++++++--- frontend/src/i18n/locales/en-US.ts | 11 +- frontend/src/i18n/locales/ko-KR.ts | 9 + frontend/src/i18n/locales/ru-RU.ts | 11 +- frontend/src/i18n/locales/zh-CN.ts | 9 + internal/application/repository/session.go | 104 +++++++++++ internal/application/service/session.go | 41 +++++ internal/handler/session/handler.go | 99 ++++++++++- internal/im/service.go | 58 +++++-- internal/router/router.go | 2 + internal/types/interfaces/session.go | 10 ++ internal/types/session.go | 35 ++++ .../000039_session_user_id_and_pin.down.sql | 8 + .../000039_session_user_id_and_pin.up.sql | 21 +++ 15 files changed, 564 insertions(+), 38 deletions(-) create mode 100644 migrations/versioned/000039_session_user_id_and_pin.down.sql create mode 100644 migrations/versioned/000039_session_user_id_and_pin.up.sql diff --git a/frontend/src/api/chat/index.ts b/frontend/src/api/chat/index.ts index 2b98c382..f8ca9e77 100644 --- a/frontend/src/api/chat/index.ts +++ b/frontend/src/api/chat/index.ts @@ -6,8 +6,26 @@ export async function createSessions(data = {}) { return post("/api/v1/sessions", data); } -export async function getSessionsList(page: number, page_size: number) { - return get(`/api/v1/sessions?page=${page}&page_size=${page_size}`); +export async function getSessionsList( + page: number, + page_size: number, + filters: { keyword?: string; source?: string; agent_id?: string } = {} +) { + const params = new URLSearchParams(); + params.set("page", String(page)); + params.set("page_size", String(page_size)); + if (filters.keyword) params.set("keyword", filters.keyword); + if (filters.source) params.set("source", filters.source); + if (filters.agent_id) params.set("agent_id", filters.agent_id); + return get(`/api/v1/sessions?${params.toString()}`); +} + +export async function pinSession(session_id: string) { + return post(`/api/v1/sessions/${session_id}/pin`, {}); +} + +export async function unpinSession(session_id: string) { + return del(`/api/v1/sessions/${session_id}/pin`); } export async function generateSessionsTitle(session_id: string, data: any) { diff --git a/frontend/src/components/menu.vue b/frontend/src/components/menu.vue index dd62b2a7..c0a51978 100644 --- a/frontend/src/components/menu.vue +++ b/frontend/src/components/menu.vue @@ -61,6 +61,18 @@