77@desc: 门户配置序列化器
88"""
99
10+ from django .core .cache import cache
1011from django .db .models import Exists , OuterRef
1112from django .utils .translation import gettext_lazy as _
1213from rest_framework import serializers
1314
1415from application .models import Application , Chat
1516from 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
1619from common .db .search import page_search
1720from system_manage .models .chat_user import (
1821 ChatUser ,
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+
2672class 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
103161class 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