From 00e486c3fece8d88bebefbca3fe83c9aff01a1ca Mon Sep 17 00:00:00 2001 From: shaohuzhang1 <80892890+shaohuzhang1@users.noreply.github.com> Date: Tue, 17 Jun 2025 11:58:35 +0800 Subject: [PATCH] feat: chat message ui (#3275) --- apps/chat/serializers/chat.py | 7 +- apps/chat/serializers/chat_authentication.py | 5 +- apps/chat/urls.py | 10 +-- apps/chat/views/chat.py | 10 ++- ui/src/api/chat/chat.ts | 42 ++++++---- ui/src/api/type/chat.ts | 15 ++++ ui/src/components/ai-chat/index.vue | 48 +++++++----- ui/src/request/chat/index.ts | 16 ++-- ui/src/router/chat/index.ts | 37 ++++++--- ui/src/router/chat/routes.ts | 10 ++- ui/src/stores/index.ts | 2 + ui/src/stores/modules/chat-user.ts | 74 ++++++++++++++++++ ui/src/views/404/index.vue | 51 ++++++++++++ ui/src/views/chat/index.vue | 81 ++------------------ ui/vite.config.ts | 4 +- 15 files changed, 269 insertions(+), 143 deletions(-) create mode 100644 ui/src/api/type/chat.ts create mode 100644 ui/src/stores/modules/chat-user.ts create mode 100644 ui/src/views/404/index.vue diff --git a/apps/chat/serializers/chat.py b/apps/chat/serializers/chat.py index 047ae564a..c7eacabc4 100644 --- a/apps/chat/serializers/chat.py +++ b/apps/chat/serializers/chat.py @@ -315,7 +315,7 @@ class ChatSerializers(serializers.Serializer): class OpenChatSerializers(serializers.Serializer): - workspace_id = serializers.CharField(required=True) + workspace_id = serializers.CharField(required=False, allow_null=True, allow_blank=True, label=_("Workspace ID")) application_id = serializers.UUIDField(required=True) chat_user_id = serializers.CharField(required=True, label=_("Client id")) chat_user_type = serializers.CharField(required=True, label=_("Client Type")) @@ -325,7 +325,10 @@ class OpenChatSerializers(serializers.Serializer): super().is_valid(raise_exception=True) workspace_id = self.data.get('workspace_id') application_id = self.data.get('application_id') - if not QuerySet(Application).filter(id=application_id, workspace_id=workspace_id).exists(): + query_set = QuerySet(Application).filter(id=application_id) + if workspace_id: + query_set = query_set.filter(workspace_id=workspace_id) + if not query_set.exists(): raise AppApiException(500, gettext('Application does not exist')) def open(self): diff --git a/apps/chat/serializers/chat_authentication.py b/apps/chat/serializers/chat_authentication.py index 953fdb595..0b83ca4df 100644 --- a/apps/chat/serializers/chat_authentication.py +++ b/apps/chat/serializers/chat_authentication.py @@ -126,6 +126,8 @@ class ApplicationProfileSerializer(serializers.Serializer): 'user_avatar': application_setting.user_avatar, 'show_user_avatar': application_setting.show_user_avatar, 'float_location': application_setting.float_location} + base_node = [node for node in ((application.work_flow or {}).get('nodes', []) or []) if + node.get('id') == 'base-node'] return {**ApplicationSerializerModel(application).data, 'stt_model_id': application.stt_model_id, 'tts_model_id': application.tts_model_id, @@ -136,8 +138,7 @@ class ApplicationProfileSerializer(serializers.Serializer): 'stt_autosend': application.stt_autosend, 'file_upload_enable': application.file_upload_enable, 'file_upload_setting': application.file_upload_setting, - 'work_flow': {'nodes': [node for node in ((application.work_flow or {}).get('nodes', []) or []) if - node.get('id') == 'base-node']}, + 'work_flow': {'nodes': base_node} if base_node else None, 'show_source': application_access_token.show_source, 'language': application_access_token.language, **application_setting_dict} diff --git a/apps/chat/urls.py b/apps/chat/urls.py index 8550572b6..f15980cdd 100644 --- a/apps/chat/urls.py +++ b/apps/chat/urls.py @@ -5,10 +5,10 @@ from . import views app_name = 'chat' urlpatterns = [ - path('chat/embed', views.ChatEmbedView.as_view()), - path('application/anonymous_authentication', views.AnonymousAuthentication.as_view()), - path('auth/profile', views.AuthProfile.as_view()), - path('profile', views.ApplicationProfile.as_view()), + path('embed', views.ChatEmbedView.as_view()), + path('auth/anonymous', views.AnonymousAuthentication.as_view()), + path('profile', views.AuthProfile.as_view()), + path('application/profile', views.ApplicationProfile.as_view()), path('chat_message/', views.ChatView.as_view()), - path('workspace//application//open', views.OpenView.as_view()) + path('open', views.OpenView.as_view()) ] diff --git a/apps/chat/views/chat.py b/apps/chat/views/chat.py index ed2dd71ff..c254bfb2a 100644 --- a/apps/chat/views/chat.py +++ b/apps/chat/views/chat.py @@ -100,7 +100,8 @@ class ChatView(APIView): return ChatSerializers(data={'chat_id': chat_id, 'chat_user_id': request.auth.chat_user_id, 'chat_user_type': request.auth.chat_user_type, - 'application_id': request.auth.application_id} + 'application_id': request.auth.application_id, + 'debug': False} ).chat(request.data) @@ -116,7 +117,8 @@ class OpenView(APIView): responses=None, tags=[_('Chat')] # type: ignore ) - def get(self, request: Request, workspace_id: str, application_id: str): + def get(self, request: Request): return result.success(OpenChatSerializers( - data={'workspace_id': workspace_id, 'application_id': application_id, - 'chat_user_id': request.auth.chat_user_id, 'chat_user_type': request.auth.chat_user_type}).open()) + data={'application_id': request.auth.application_id, + 'chat_user_id': request.auth.chat_user_id, 'chat_user_type': request.auth.chat_user_type, + 'debug': False}).open()) diff --git a/ui/src/api/chat/chat.ts b/ui/src/api/chat/chat.ts index 3db1548aa..7340cb6fc 100644 --- a/ui/src/api/chat/chat.ts +++ b/ui/src/api/chat/chat.ts @@ -9,7 +9,7 @@ import { download, exportFile, } from '@/request/chat/index' - +import { type ChatProfile } from '@/api/type/chat' import { type Ref } from 'vue' import useStore from '@/stores' @@ -27,11 +27,9 @@ Object.defineProperty(prefix, 'value', { * @param loading 加载器 * @returns */ -const open: (application_id: string, loading?: Ref) => Promise> = ( - application_id, - loading, -) => { - return get(`${prefix.value}/${application_id}/open`, {}, loading) +const open: (loading?: Ref) => Promise> = (loading) => { + return get('/open', {}, loading) + } /** * 对话 @@ -40,22 +38,38 @@ const open: (application_id: string, loading?: Ref) => Promise Promise = (chat_id, data) => { - return postStream(`/api/chat_message/${chat_id}`, data) + return postStream(`/chat/api/chat_message/${chat_id}`, data) } -const chatProfile: (assessToken: string, loading?: Ref) => Promise> = ( +const chatProfile: (assessToken: string, loading?: Ref) => Promise> = ( assessToken, loading, ) => { - return get('/auth/profile', { access_token: assessToken }, loading) + return get('/profile', { access_token: assessToken }, loading) } -const applicationProfile: (assessToken: string, loading?: Ref) => Promise> = ( - assessToken, - loading, -) => { - return get('/chat/api/profile') +/** + * 匿名认证 + * @param assessToken + * @param loading + * @returns + */ +const anonymousAuthentication: ( + assessToken: string, + loading?: Ref, +) => Promise> = (assessToken, loading) => { + return post('/auth/anonymous', { access_token: assessToken }, {}, loading) +} +/** + * 获取应用相关信息 + * @param loading + * @returns + */ +const applicationProfile: (loading?: Ref) => Promise> = (loading) => { + return get('/application/profile', {}, loading) } export default { open, chat, chatProfile, + anonymousAuthentication, + applicationProfile, } diff --git a/ui/src/api/type/chat.ts b/ui/src/api/type/chat.ts new file mode 100644 index 000000000..7b8f3a9b8 --- /dev/null +++ b/ui/src/api/type/chat.ts @@ -0,0 +1,15 @@ +interface ChatProfile { + // 是否开启认证 + authentication: boolean + // icon + icon?: string + // 应用名称 + application_name?: string + // 背景图 + bg_icon?: string + // 认证类型 + authentication_type?: 'password' | 'login' + // 登录类型 + login_value?: Array +} +export { type ChatProfile } diff --git a/ui/src/components/ai-chat/index.vue b/ui/src/components/ai-chat/index.vue index 3349b2a34..655ee624f 100644 --- a/ui/src/components/ai-chat/index.vue +++ b/ui/src/components/ai-chat/index.vue @@ -85,9 +85,10 @@ + diff --git a/ui/src/views/chat/index.vue b/ui/src/views/chat/index.vue index 261f218c3..ebcd23e44 100644 --- a/ui/src/views/chat/index.vue +++ b/ui/src/views/chat/index.vue @@ -1,35 +1,19 @@ diff --git a/ui/vite.config.ts b/ui/vite.config.ts index 369afc6c0..f49590a47 100644 --- a/ui/vite.config.ts +++ b/ui/vite.config.ts @@ -13,6 +13,7 @@ const envDir = './env' // https://vite.dev/config/ export default defineConfig(({ mode }) => { const ENV = loadEnv(mode, envDir) + console.log(ENV) const prefix = process.env.VITE_DYNAMIC_PREFIX || ENV.VITE_BASE_PATH const proxyConf: Record = {} proxyConf['/api'] = { @@ -25,10 +26,9 @@ export default defineConfig(({ mode }) => { changeOrigin: true, rewrite: (path: string) => path.replace(ENV.VITE_BASE_PATH, '/'), } - proxyConf['/chat'] = { + proxyConf['/chat/api'] = { target: 'http://127.0.0.1:8080', changeOrigin: true, - rewrite: (path: string) => path.replace(ENV.VITE_BASE_PATH, '/'), } proxyConf['/doc'] = { target: 'http://127.0.0.1:8080',