diff --git a/apps/application/serializers/application_chat.py b/apps/application/serializers/application_chat.py index 9ac61205f..52dbfda6d 100644 --- a/apps/application/serializers/application_chat.py +++ b/apps/application/serializers/application_chat.py @@ -23,12 +23,14 @@ from django.utils.translation import gettext_lazy as _, gettext from openpyxl.cell.cell import ILLEGAL_CHARACTERS_RE from rest_framework import serializers -from application.models import Chat, Application, ChatRecord +from application.models import Chat, Application, ChatRecord, ChatUserType +from common.database_model_manage.database_model_manage import DatabaseModelManage from common.db.search import get_dynamics_model, native_search, native_page_search, native_page_handler from common.exception.app_exception import AppApiException from common.utils.common import get_file_content from maxkb.conf import PROJECT_DIR from maxkb.settings import TIME_ZONE, edition +from users.models import User class ApplicationChatResponseSerializers(serializers.Serializer): @@ -147,6 +149,75 @@ class ApplicationChatQuerySerializers(serializers.Serializer): with_table_name=False) return self.append_feedback_content(result) + @staticmethod + def format_user_display_name(nick_name, username): + nick_name = (nick_name or '').strip() + username = (username or '').strip() + if nick_name and username and nick_name != username: + return f'{nick_name}({username})' + return nick_name or username or '游客' + + @classmethod + def build_asker(cls, user): + return { + 'id': str(user.id), + 'email': getattr(user, 'email', ''), + 'phone': getattr(user, 'phone', ''), + 'nick_name': getattr(user, 'nick_name', ''), + 'username': getattr(user, 'username', ''), + 'display_name': cls.format_user_display_name( + getattr(user, 'nick_name', ''), + getattr(user, 'username', '') + ), + 'source': getattr(user, 'source', '') + } + + @classmethod + def normalize_asker(cls, asker): + if isinstance(asker, dict): + nick_name = asker.get('nick_name') or asker.get('name') or '' + username = asker.get('username') or asker.get('user_name') or '' + display_name = asker.get('display_name') or cls.format_user_display_name(nick_name, username) + return {**asker, 'display_name': display_name, 'username': username or display_name} + if asker: + return {'username': str(asker), 'display_name': str(asker)} + return {'username': '游客', 'display_name': '游客'} + + @classmethod + def fill_asker_display_name(cls, records): + if not records: + return records + + platform_user_ids = [ + row.get('chat_user_id') for row in records + if row.get('chat_user_type') == ChatUserType.PLATFORM_USER.value and row.get('chat_user_id') + ] + chat_user_ids = [ + row.get('chat_user_id') for row in records + if row.get('chat_user_type') == ChatUserType.CHAT_USER.value and row.get('chat_user_id') + ] + platform_user_map = { + str(user.id): user for user in QuerySet(User).filter(id__in=platform_user_ids) + } if platform_user_ids else {} + + chat_user_map = {} + chat_user_model = DatabaseModelManage.get_model("chat_user") + if chat_user_model and chat_user_ids: + chat_user_map = { + str(user.id): user for user in QuerySet(chat_user_model).filter(id__in=chat_user_ids) + } + + for row in records: + chat_user_id = str(row.get('chat_user_id') or '') + chat_user_type = row.get('chat_user_type') + if chat_user_type == ChatUserType.PLATFORM_USER.value and chat_user_id in platform_user_map: + row['asker'] = cls.build_asker(platform_user_map[chat_user_id]) + elif chat_user_type == ChatUserType.CHAT_USER.value and chat_user_id in chat_user_map: + row['asker'] = cls.build_asker(chat_user_map[chat_user_id]) + else: + row['asker'] = cls.normalize_asker(row.get('asker')) + return records + @staticmethod def get_feedback_items(details): if not isinstance(details, dict): @@ -163,6 +234,7 @@ class ApplicationChatQuerySerializers(serializers.Serializer): def append_feedback_content(cls, records): if not records: return records + cls.fill_asker_display_name(records) chat_id_list = [row.get('id') for row in records if row.get('id') is not None] feedback_map = {} chat_records = QuerySet(ChatRecord).filter(chat_id__in=chat_id_list).order_by('create_time') @@ -213,7 +285,7 @@ class ApplicationChatQuerySerializers(serializers.Serializer): "\n".join([ f"{improve_paragraph_list[index].get('title')}\n{improve_paragraph_list[index].get('content')}" for index in range(len(improve_paragraph_list))]), - row.get('asker').get('username'), + ApplicationChatQuerySerializers.normalize_asker(row.get('asker')).get('display_name'), (row.get('message_tokens') or 0) + (row.get('answer_tokens') or 0), row.get('run_time'), str(row.get('create_time').astimezone(pytz.timezone(TIME_ZONE)).strftime('%Y-%m-%d %H:%M:%S') if row.get('create_time') is not None else None)] @@ -256,8 +328,9 @@ class ApplicationChatQuerySerializers(serializers.Serializer): ('export_application_chat_ee.sql' if ['PE', 'EE'].__contains__( edition) else 'export_application_chat.sql'))), - with_table_name=False): + with_table_name=False): + self.fill_asker_display_name(data_list) for item in data_list: row = [self.reset_value(v) for v in self.to_row(item)] worksheet.append(row) diff --git a/apps/application/serializers/common.py b/apps/application/serializers/common.py index 5c60512ad..b85252b0f 100644 --- a/apps/application/serializers/common.py +++ b/apps/application/serializers/common.py @@ -25,6 +25,7 @@ from common.exception.app_exception import ChatException from knowledge.models import Document from models_provider.models import Model from models_provider.tools import get_model_credential +from users.models import User class ChatInfo: @@ -99,14 +100,30 @@ class ChatInfo: chat_user_model = DatabaseModelManage.get_model("chat_user") if self.chat_user_type == ChatUserType.CHAT_USER.value and chat_user_model: chat_user = QuerySet(chat_user_model).filter(id=self.chat_user_id).first() + if chat_user is None: + return {'username': '游客'} return { 'id': str(chat_user.id), 'email': chat_user.email, 'phone': chat_user.phone, 'nick_name': chat_user.nick_name, 'username': chat_user.username, + 'display_name': self.format_user_display_name(chat_user.nick_name, chat_user.username), 'source': chat_user.source } + elif self.chat_user_type == ChatUserType.PLATFORM_USER.value: + user = QuerySet(User).filter(id=self.chat_user_id).first() + if user is None: + return {'username': '游客'} + return { + 'id': str(user.id), + 'email': user.email, + 'phone': user.phone, + 'nick_name': user.nick_name, + 'username': user.username, + 'display_name': self.format_user_display_name(user.nick_name, user.username), + 'source': user.source + } else: if asker: if isinstance(asker, dict): @@ -117,6 +134,14 @@ class ChatInfo: self.chat_user = {'username': '游客'} return self.chat_user + @staticmethod + def format_user_display_name(nick_name, username): + nick_name = (nick_name or '').strip() + username = (username or '').strip() + if nick_name and username and nick_name != username: + return f'{nick_name}({username})' + return nick_name or username or '游客' + def to_base_pipeline_manage_params(self): self.get_application() self.get_chat_user() diff --git a/ui/src/components/folder-breadcrumb/index.vue b/ui/src/components/folder-breadcrumb/index.vue index 7dce4985b..854f5c7fa 100644 --- a/ui/src/components/folder-breadcrumb/index.vue +++ b/ui/src/components/folder-breadcrumb/index.vue @@ -1,12 +1,12 @@ diff --git a/ui/src/views/tool/index.vue b/ui/src/views/tool/index.vue index cc550717a..829c4ffd7 100644 --- a/ui/src/views/tool/index.vue +++ b/ui/src/views/tool/index.vue @@ -20,7 +20,12 @@

{{ $t('views.shared.shared_tool') }}

- + {{ $t('views.tool.all') }}