Skip to content

Commit 6c8d91c

Browse files
committed
refactor: enhance portal application settings retrieval and improve chat history mapping
1 parent 88313cf commit 6c8d91c

1 file changed

Lines changed: 97 additions & 26 deletions

File tree

apps/chat/serializers/portal.py

Lines changed: 97 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,15 @@
77
@desc: 门户配置序列化器
88
"""
99

10+
from django.core.cache import cache
1011
from django.db.models import Exists, OuterRef
1112
from django.utils.translation import gettext_lazy as _
1213
from rest_framework import serializers
1314

1415
from application.models import Application, Chat
1516
from application.models.application_access_token import ApplicationAccessToken
17+
from common.constants.cache_version import Cache_Version
18+
from common.database_model_manage.database_model_manage import DatabaseModelManage
1619
from common.db.search import page_search
1720
from system_manage.models.chat_user import (
1821
ChatUser,
@@ -23,14 +26,61 @@
2326
)
2427

2528

29+
def build_application_setting_dict(setting, show_source):
30+
return {
31+
"show_source": show_source,
32+
"show_history": setting.show_history,
33+
"draggable": setting.draggable,
34+
"show_guide": setting.show_guide,
35+
"avatar": setting.avatar,
36+
"show_avatar": setting.show_avatar,
37+
"float_icon": setting.float_icon,
38+
"disclaimer": setting.disclaimer,
39+
"disclaimer_value": setting.disclaimer_value,
40+
"custom_theme": setting.custom_theme or {"theme_color": "", "header_font_color": ""},
41+
"user_avatar": setting.user_avatar,
42+
"show_user_avatar": setting.show_user_avatar,
43+
"show_share": setting.show_share,
44+
"float_location": setting.float_location or {"x": {"type": "", "value": ""}, "y": {"type": "", "value": ""}},
45+
"chat_background": setting.chat_background,
46+
}
47+
48+
49+
def get_application_settings_map(application_ids):
50+
"""批量返回 application_id -> 门户设置信息;license 无效或模型缺失时返回空 dict"""
51+
application_setting_model = DatabaseModelManage.get_model("application_setting")
52+
if application_setting_model is None or not application_ids:
53+
return {}
54+
license_is_valid = cache.get(
55+
Cache_Version.SYSTEM.get_key(key="license_is_valid"), version=Cache_Version.SYSTEM.get_version()
56+
)
57+
if not license_is_valid:
58+
return {}
59+
settings = application_setting_model.objects.filter(application_id__in=application_ids)
60+
access_tokens = ApplicationAccessToken.objects.filter(application_id__in=application_ids).values_list(
61+
"application_id", "show_source"
62+
)
63+
token_map = {str(application_id): show_source for application_id, show_source in access_tokens}
64+
return {
65+
str(setting.application_id): build_application_setting_dict(
66+
setting, token_map.get(str(setting.application_id), False)
67+
)
68+
for setting in settings
69+
}
70+
71+
2672
class PortalApplicationAuthMixin:
2773
"""门户应用授权过滤公共逻辑"""
2874

2975
@staticmethod
30-
def get_authorized_application_queryset(user_id):
76+
def get_authorized_application_ids(user_id):
3177
public_apps = ApplicationAccessToken.objects.filter(application_id=OuterRef("id"), authentication=False)
3278
if not ChatUser.objects.filter(id=user_id).exists():
33-
return Application.objects.filter(is_publish=True, is_portal=True).filter(Exists(public_apps))
79+
return (
80+
Application.objects.filter(is_publish=True, is_portal=True)
81+
.filter(Exists(public_apps))
82+
.values_list("id", flat=True)
83+
)
3484
authed_token_exists = ApplicationAccessToken.objects.filter(application_id=OuterRef("id"), authentication=True)
3585
direct_auth = ResourceChatUserAuthorize.objects.filter(
3686
resource_id=OuterRef("id"), resource_type=ResourceType.APPLICATION.value, is_auth=True, user_id=user_id
@@ -42,8 +92,10 @@ def get_authorized_application_queryset(user_id):
4292
is_auth=True,
4393
user_group_id__in=user_groups,
4494
)
45-
return Application.objects.filter(is_publish=True, is_portal=True).filter(
46-
Exists(public_apps) | (Exists(authed_token_exists) & (Exists(direct_auth) | Exists(group_auth)))
95+
return (
96+
Application.objects.filter(is_publish=True, is_portal=True)
97+
.filter(Exists(public_apps) | (Exists(authed_token_exists) & (Exists(direct_auth) | Exists(group_auth))))
98+
.values_list("id", flat=True)
4799
)
48100

49101

@@ -76,7 +128,7 @@ def page(self, current_page, page_size, user_id, with_valid=True):
76128
if with_valid:
77129
self.is_valid(raise_exception=True)
78130
queryset = self.get_query_set()
79-
queryset = queryset.filter(id__in=self.get_authorized_application_queryset(user_id).values("id"))
131+
queryset = queryset.filter(id__in=self.get_authorized_application_ids(user_id))
80132
return page_search(
81133
current_page,
82134
page_size,
@@ -85,19 +137,25 @@ def page(self, current_page, page_size, user_id, with_valid=True):
85137
)
86138

87139

88-
class PortalHistoricalConversationResponseSerializer(serializers.Serializer):
89-
id = serializers.CharField(required=True)
90-
abstract = serializers.CharField(required=True)
91-
create_time = serializers.CharField(required=True)
92-
update_time = serializers.CharField(required=True)
93-
application = serializers.SerializerMethodField()
94-
95-
def get_application(self, chat):
96-
return {
97-
"id": str(chat.application_id),
98-
"name": chat.application.name,
99-
"icon": chat.application.icon,
100-
}
140+
def get_recent_chats_map(user_id, application_ids, limit=5):
141+
"""批量返回 application_id -> 该应用最近的 limit 条历史会话;show_history=false 的应用不在此表里"""
142+
chats = Chat.objects.filter(chat_user_id=user_id, is_deleted=False, application_id__in=application_ids).order_by(
143+
"application_id", "-update_time", "id"
144+
)
145+
result = {}
146+
for chat in chats:
147+
key = str(chat.application_id)
148+
if len(result.get(key, [])) >= limit:
149+
continue
150+
result.setdefault(key, []).append(
151+
{
152+
"id": str(chat.id),
153+
"abstract": chat.abstract,
154+
"create_time": str(chat.create_time),
155+
"update_time": str(chat.update_time),
156+
}
157+
)
158+
return result
101159

102160

103161
class PortalHistoricalConversationSerializer(serializers.Serializer):
@@ -107,22 +165,35 @@ class Query(PortalApplicationAuthMixin, serializers.Serializer):
107165
)
108166

109167
def get_query_set(self, user_id):
110-
queryset = Chat.objects.filter(
111-
chat_user_id=user_id,
112-
is_deleted=False,
113-
application_id__in=self.get_authorized_application_queryset(user_id).values("id"),
168+
# 主表是应用:返回用户有权限访问的已发布门户应用
169+
queryset = Application.objects.filter(
170+
is_publish=True,
171+
is_portal=True,
172+
id__in=self.get_authorized_application_ids(user_id),
114173
)
115174
name = self.data.get("name")
116175
if name:
117-
queryset = queryset.filter(application__name__icontains=name)
118-
return queryset.select_related("application").order_by("-update_time", "id")
176+
queryset = queryset.filter(name__icontains=name)
177+
return queryset.order_by("-create_time")
119178

120179
def page(self, current_page, page_size, user_id, with_valid=True):
121180
if with_valid:
122181
self.is_valid(raise_exception=True)
123-
return page_search(
182+
result = page_search(
124183
current_page,
125184
page_size,
126185
self.get_query_set(user_id),
127-
post_records_handler=lambda chat: PortalHistoricalConversationResponseSerializer(chat).data,
186+
post_records_handler=lambda app: {
187+
"id": str(app.id),
188+
"name": app.name,
189+
"icon": app.icon,
190+
},
128191
)
192+
app_ids = [record["id"] for record in result["records"]]
193+
settings_map = get_application_settings_map(app_ids)
194+
show_history_ids = [aid for aid in app_ids if settings_map.get(aid, {}).get("show_history")]
195+
chat_map = get_recent_chats_map(user_id, show_history_ids) if show_history_ids else {}
196+
for record in result["records"]:
197+
record.update(settings_map.get(record["id"], {}))
198+
record["conversations"] = chat_map.get(record["id"], [])
199+
return result

0 commit comments

Comments
 (0)