Skip to content

Commit d4b0686

Browse files
committed
feat: add filtering options for application status and type in application serializers and views
1 parent d4a2eec commit d4b0686

17 files changed

Lines changed: 226 additions & 121 deletions

File tree

‎apps/application/api/application_chat.py‎

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
# coding=utf-8
22
"""
3-
@project: MaxKB
4-
@Author:虎虎
5-
@file: application_chat.py
6-
@date:2025/6/10 13:54
7-
@desc:
3+
@project: MaxKB
4+
@Author:虎虎
5+
@file: application_chat.py
6+
@date:2025/6/10 13:54
7+
@desc:
88
"""
9+
910
from django.utils.translation import gettext_lazy as _
1011
from drf_spectacular.types import OpenApiTypes
1112
from drf_spectacular.utils import OpenApiParameter
1213

13-
from application.serializers.application_chat import ApplicationChatQuerySerializers, \
14-
ApplicationChatResponseSerializers, ApplicationChatRecordExportRequest
14+
from application.serializers.application_chat import (
15+
ApplicationChatQuerySerializers,
16+
ApplicationChatResponseSerializers,
17+
ApplicationChatRecordExportRequest,
18+
)
1519
from common.mixins.api_mixin import APIMixin
1620
from common.result import ResultSerializer, ResultPageSerializer
1721

@@ -38,16 +42,17 @@ def get_parameters():
3842
name="workspace_id",
3943
description="工作空间id",
4044
type=OpenApiTypes.STR,
41-
location='path',
45+
location="path",
4246
required=True,
4347
),
4448
OpenApiParameter(
4549
name="application_id",
4650
description="application ID",
4751
type=OpenApiTypes.STR,
48-
location='path',
52+
location="path",
4953
required=True,
50-
), OpenApiParameter(
54+
),
55+
OpenApiParameter(
5156
name="start_time",
5257
description="start Time",
5358
type=OpenApiTypes.STR,
@@ -71,6 +76,12 @@ def get_parameters():
7176
type=OpenApiTypes.STR,
7277
required=False,
7378
),
79+
OpenApiParameter(
80+
name="source",
81+
description="source",
82+
type=OpenApiTypes.STR,
83+
required=False,
84+
),
7485
OpenApiParameter(
7586
name="min_star",
7687
description=_("Minimum number of likes"),
@@ -109,17 +120,16 @@ def get_parameters():
109120
name="current_page",
110121
description=_("Current page"),
111122
type=OpenApiTypes.INT,
112-
location='path',
123+
location="path",
113124
required=True,
114125
),
115126
OpenApiParameter(
116127
name="page_size",
117128
description=_("Page size"),
118129
type=OpenApiTypes.INT,
119-
location='path',
130+
location="path",
120131
required=True,
121132
),
122-
123133
]
124134

125135
@staticmethod

‎apps/application/serializers/application.py‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,16 @@ class ApplicationQueryRequest(serializers.Serializer):
547547
label=_("Publish status"),
548548
choices=[("published", _("Published")), ("unpublished", _("Unpublished"))],
549549
)
550+
status = serializers.ChoiceField(
551+
required=False,
552+
label=_("Publish status"),
553+
choices=[
554+
("published", _("Published")),
555+
("unpublished", _("Unpublished")),
556+
("on_portal", _("On portal")),
557+
],
558+
)
559+
type = serializers.CharField(required=False, allow_null=True, allow_blank=True, label=_("Application type"))
550560
user_id = serializers.UUIDField(required=False, label=_("User ID"))
551561
create_user = serializers.CharField(required=False, allow_null=True, allow_blank=True, label=_("create user"))
552562

@@ -584,6 +594,14 @@ def get_query_set(self, instance: Dict, workspace_manage: bool, is_x_pack_ee: bo
584594
if publish_status is not None:
585595
is_publish = True if publish_status == "published" else False
586596
application_query_set = application_query_set.filter(is_publish=is_publish)
597+
status = instance.get("status")
598+
if status is not None:
599+
if status == "unpublished":
600+
application_query_set = application_query_set.filter(is_publish=False)
601+
elif status == "published":
602+
application_query_set = application_query_set.filter(is_publish=True)
603+
elif status == "on_portal":
604+
application_query_set = application_query_set.filter(is_portal=True)
587605
if workspace_id is not None:
588606
folder_query_set = folder_query_set.filter(workspace_id=workspace_id)
589607
application_query_set = application_query_set.filter(workspace_id=workspace_id)
@@ -599,6 +617,9 @@ def get_query_set(self, instance: Dict, workspace_manage: bool, is_x_pack_ee: bo
599617
application_query_set = application_query_set.filter(desc__contains=desc)
600618
if create_user is not None:
601619
application_query_set = application_query_set.filter(user_id=create_user)
620+
application_type = instance.get("type")
621+
if application_type:
622+
application_query_set = application_query_set.filter(type=application_type)
602623
application_custom_sql_query_set = application_query_set
603624
application_query_set = application_query_set.order_by("-create_time")
604625

‎apps/application/serializers/application_chat.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ class ApplicationChatQuerySerializers(serializers.Serializer):
5858
start_time = serializers.DateField(format="%Y-%m-%d", label=_("Start time"))
5959
end_time = serializers.DateField(format="%Y-%m-%d", label=_("End time"))
6060
application_id = serializers.UUIDField(required=True, label=_("Application ID"))
61+
source = serializers.CharField(required=False, allow_blank=True, allow_null=True, label=_("Source"))
6162
min_star = serializers.IntegerField(required=False, min_value=0, label=_("Minimum number of likes"))
6263
min_trample = serializers.IntegerField(required=False, min_value=0, label=_("Minimum number of clicks"))
6364
comparer = serializers.CharField(
@@ -96,6 +97,7 @@ def get_query_set(self, select_ids=None):
9697
"application_chat.application_id": models.CharField(),
9798
"application_chat.abstract": models.CharField(),
9899
"application_chat.asker": models.JSONField(),
100+
"application_chat.source": models.JSONField(),
99101
"star_num": models.IntegerField(),
100102
"trample_num": models.IntegerField(),
101103
"comparer": models.CharField(),
@@ -113,6 +115,8 @@ def get_query_set(self, select_ids=None):
113115
}
114116
if "abstract" in self.data and self.data.get("abstract") is not None:
115117
base_query_dict["application_chat.abstract__icontains"] = self.data.get("abstract")
118+
if "source" in self.data and self.data.get("source") is not None:
119+
base_query_dict["application_chat.source__type"] = self.data.get("source")
116120
if select_ids is not None and len(select_ids) > 0:
117121
base_query_dict["application_chat.id__in"] = select_ids
118122
base_condition = Q(**base_query_dict)

‎apps/knowledge/serializers/knowledge.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ class Query(serializers.Serializer):
231231
max_length=256,
232232
min_length=1,
233233
)
234+
type = serializers.IntegerField(required=False, label=_("knowledge type"), allow_null=True)
234235
user_id = serializers.UUIDField(required=False, label=_("user id"), allow_null=True)
235236
scope = serializers.CharField(required=False, label=_("knowledge scope"), allow_null=True)
236237
create_user = serializers.UUIDField(required=False, label=_("create user"), allow_null=True)
@@ -250,6 +251,7 @@ def get_query_set(self, workspace_manage, is_x_pack_ee):
250251
{
251252
"temp.name": models.CharField(),
252253
"temp.desc": models.CharField(),
254+
"temp.type": models.IntegerField(),
253255
"document_temp.char_length": models.IntegerField(),
254256
"temp.create_time": models.DateTimeField(),
255257
"temp.user_id": models.CharField(),
@@ -268,6 +270,8 @@ def get_query_set(self, workspace_manage, is_x_pack_ee):
268270
if "name" in self.data and self.data.get("name") is not None:
269271
query_set = query_set.filter(**{"temp.name__icontains": self.data.get("name")})
270272
folder_query_set = folder_query_set.filter(**{"name__icontains": self.data.get("name")})
273+
if "type" in self.data and self.data.get("type") is not None:
274+
query_set = query_set.filter(**{"temp.type": self.data.get("type")})
271275
if "workspace_id" in self.data and self.data.get("workspace_id") is not None:
272276
query_set = query_set.filter(**{"temp.workspace_id": self.data.get("workspace_id")})
273277
folder_query_set = folder_query_set.filter(**{"workspace_id": self.data.get("workspace_id")})

‎apps/knowledge/views/knowledge.py‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,7 @@ def get(self, request: Request, workspace_id: str, current_page: int, page_size:
301301
"folder_id": request.query_params.get("folder_id"),
302302
"name": request.query_params.get("name"),
303303
"desc": request.query_params.get("desc"),
304+
"type": request.query_params.get("type"),
304305
"scope": KnowledgeScope.WORKSPACE,
305306
"user_id": request.user.id,
306307
"create_user": request.query_params.get("create_user"),

‎apps/tools/serializers/tool.py‎

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -623,7 +623,7 @@ def convert_value(name: str, value: str, _type: str, is_required: bool):
623623
return None
624624
try:
625625
return common_convert_value(_type, value)
626-
except Exception as e:
626+
except Exception:
627627
raise AppApiException(
628628
500,
629629
_("Field: {name} Type: {type} Value: {value} Type conversion error").format(
@@ -1087,7 +1087,7 @@ def update_template_workflow(self, tool_id: str):
10871087
tool_instance_bytes = self.data.get("file").read()
10881088
try:
10891089
tool_instance = RestrictedUnpickler(io.BytesIO(tool_instance_bytes)).load()
1090-
except Exception as e:
1090+
except Exception:
10911091
raise AppApiException(1001, _("Unsupported file format"))
10921092
tool = tool_instance.tool
10931093
tool["id"] = tool_id
@@ -1109,7 +1109,7 @@ def import_(self, scope=ToolScope.WORKSPACE, name=None, source=None):
11091109
tool_instance_bytes = self.data.get("file").read()
11101110
try:
11111111
tool_instance = RestrictedUnpickler(io.BytesIO(tool_instance_bytes)).load()
1112-
except Exception as e:
1112+
except Exception:
11131113
raise AppApiException(1001, _("Unsupported file format"))
11141114
if self.data.get("folder_id") is None:
11151115
folder_id = self.data.get("workspace_id")
@@ -1731,6 +1731,7 @@ class Query(serializers.Serializer):
17311731
child=serializers.CharField(), required=False, label=_("tool type list"), allow_null=True, allow_empty=True
17321732
)
17331733
create_user = serializers.UUIDField(required=False, label=_("create user"), allow_null=True)
1734+
is_active = serializers.BooleanField(required=False, label=_("is active"), allow_null=True)
17341735

17351736
def page_tool(self, current_page: int, page_size: int):
17361737
self.is_valid(raise_exception=True)
@@ -1792,6 +1793,10 @@ def get_query_set(self, workspace_manage, is_x_pack_ee):
17921793
if scope is not None:
17931794
tool_query_set = tool_query_set.filter(scope=scope)
17941795

1796+
is_active = self.data.get("is_active")
1797+
if is_active is not None:
1798+
tool_query_set = tool_query_set.filter(is_active=is_active)
1799+
17951800
tool_type_list = self.data.get("tool_type_list")
17961801
if tool_type_list:
17971802
tool_query_set = tool_query_set.filter(tool_type__in=tool_type_list)

‎apps/tools/views/tool.py‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,7 @@ def get(self, request: Request, workspace_id: str, current_page: int, page_size:
347347
"tool_type": request.query_params.get("tool_type"),
348348
"user_id": request.user.id,
349349
"create_user": request.query_params.get("create_user"),
350+
"is_active": request.query_params.get("is_active"),
350351
}
351352
).page_tool_with_folders(current_page, page_size)
352353
)

‎ui/src/components/business/related-resources-drawer/index.vue‎

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ const resourceTypeOptions = Object.entries(resourceLabels).map(([value, label])
3333
const searchFields = [
3434
{ label: '名称', value: 'resource_name' },
3535
{ label: '创建者', value: 'user_name' },
36-
{ label: '类型', value: 'resource_type', multiple: true, options: resourceTypeOptions },
3736
]
3837
const relationTabs = [
3938
{ value: 'dependency', label: '依赖' },
@@ -53,12 +52,13 @@ const resourceRows = computed(() =>
5352
)
5453
const pagination = ref({ currentPage: 1, pageSize: 20, total: 0 })
5554
const searchQuery = ref<Dict<unknown>>({})
55+
const selectedResourceType = ref<string | null>(null)
5656
5757
function loadResources() {
5858
if (!visible.value || !targetResource.value) return
5959
const isDependency = relationDirection.value === 'dependency'
60-
const { resource_type, ...query } = searchQuery.value
61-
if (resource_type) query[isDependency ? 'target_type' : 'source_type'] = resource_type
60+
const query: Dict<unknown> = { ...searchQuery.value }
61+
if (selectedResourceType.value) query[isDependency ? 'target_type' : 'source_type'] = [selectedResourceType.value]
6262
if (showWorkspace.value && selectedWorkspaceIds.value.length) query.workspace_ids = JSON.stringify(selectedWorkspaceIds.value)
6363
const request = isDependency ? props.api.getUsingResources : props.api.getUsedByResources
6464
loading.value = true
@@ -80,16 +80,17 @@ function searchResources(query?: Dict<unknown>) {
8080
8181
function changeDirection() {
8282
searchQuery.value = {}
83+
selectedResourceType.value = null
8384
selectedWorkspaceIds.value = []
8485
relatedResources.value = []
8586
pagination.value = { currentPage: 1, pageSize: 20, total: 0 }
8687
loadResources()
8788
}
8889
89-
/* 工作空间筛选:确认或重置后从第一页查询。 */
90+
/* 表头筛选:确认或重置后从第一页查询。 */
9091
const workspaceOptions = ref<OptionItem<string>[]>([])
9192
const selectedWorkspaceIds = ref<string[]>([])
92-
function handleWorkspaceFilterChange() {
93+
function handleFilterChange() {
9394
pagination.value.currentPage = 1
9495
loadResources()
9596
}
@@ -130,6 +131,7 @@ function resetData() {
130131
relatedResources.value = []
131132
pagination.value = { currentPage: 1, pageSize: 20, total: 0 }
132133
searchQuery.value = {}
134+
selectedResourceType.value = null
133135
relationDirection.value = 'dependency'
134136
workspaceOptions.value = []
135137
selectedWorkspaceIds.value = []
@@ -183,6 +185,9 @@ defineExpose({ open, close })
183185
</el-table-column>
184186
<el-table-column prop="desc" label="描述" min-width="160" show-overflow-tooltip />
185187
<el-table-column label="类型" min-width="100">
188+
<template #header>
189+
<MkTableFilter mode="single" v-model="selectedResourceType" label="类型" :options="resourceTypeOptions" @change="handleFilterChange" />
190+
</template>
186191
<template #default="{ row }">{{ resourceLabels[row.resourceType as ResourceType] }}</template>
187192
</el-table-column>
188193
<el-table-column v-if="showWorkspace" prop="workspace_name" label="工作空间" min-width="140" show-overflow-tooltip>
@@ -193,7 +198,7 @@ defineExpose({ open, close })
193198
v-model="selectedWorkspaceIds"
194199
label="工作空间"
195200
:options="workspaceOptions"
196-
@change="handleWorkspaceFilterChange"
201+
@change="handleFilterChange"
197202
/>
198203
</template>
199204
</el-table-column>

‎ui/src/views/application-detail/chat-log/index.vue‎

Lines changed: 11 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,11 @@ const { application } = useApplicationDetailContext()
2525
const loading = ref(false)
2626
const chatLogs = ref<ChatLog[]>([])
2727
const paginationConfig = ref({ currentPage: 1, pageSize: 20, total: 0 })
28+
const sourceOptions: OptionItem<string>[] = Object.entries(CHAT_LOG_SOURCE_LABELS).map(([value, label]) => ({ value, label }))
2829
const searchFields: OptionItem<string>[] = [
2930
{ label: '摘要', value: 'abstract' },
3031
{ label: '用户', value: 'username' },
32+
{ label: '来源', value: 'source', options: sourceOptions },
3133
]
3234
const chatLogSearchQuery = ref<Dict<unknown>>()
3335
const chatLogDateQuery = ref({ start_time: beforeDay(7), end_time: beforeDay(0) })
@@ -44,9 +46,12 @@ function handleDateFilterChange({ startTime, endTime }: MkDateRangeValue) {
4446
return loadChatLogs()
4547
}
4648
47-
// 反馈筛选的草稿、重置和确认由 MkTableFilter 管理
48-
const feedbackResetValue = { min_star: 0, min_trample: 0 }
49-
const feedbackFilter = ref({ ...feedbackResetValue })
49+
// 表头用户反馈筛选,单选复用 min_star/min_trample 参数
50+
const selectedFeedback = ref<string | null>(null)
51+
const feedbackOptions: OptionItem<string>[] = [
52+
{ label: '赞同', value: 'star' },
53+
{ label: '反对', value: 'trample' },
54+
]
5055
5156
function handleFeedbackChange() {
5257
paginationConfig.value.currentPage = 1
@@ -56,7 +61,8 @@ function handleFeedbackChange() {
5661
const chatLogQuery = computed<Dict<unknown>>(() => ({
5762
...chatLogSearchQuery.value,
5863
...chatLogDateQuery.value,
59-
...feedbackFilter.value,
64+
...(selectedFeedback.value === 'star' ? { min_star: 1 } : {}),
65+
...(selectedFeedback.value === 'trample' ? { min_trample: 1 } : {}),
6066
comparer: 'and',
6167
}))
6268
@@ -184,45 +190,7 @@ onMounted(() => loadChatLogs())
184190
<el-table-column prop="chat_record_count" label="对话次数" width="100" />
185191
<el-table-column width="140">
186192
<template #header>
187-
<MkTableFilter
188-
v-model="feedbackFilter"
189-
mode="custom"
190-
label="用户反馈"
191-
width="180"
192-
:reset-value="feedbackResetValue"
193-
@change="handleFeedbackChange"
194-
>
195-
<template #default="{ value }">
196-
<div class="space-y-3">
197-
<div class="flex-between gap-2">
198-
<span>赞同 ≥</span>
199-
<el-input-number
200-
v-model="value.min_star"
201-
class="w-25!"
202-
size="small"
203-
controls-position="right"
204-
align="left"
205-
:min="0"
206-
:value-on-clear="0"
207-
step-strictly
208-
/>
209-
</div>
210-
<div class="flex-between gap-2">
211-
<span>反对 ≥</span>
212-
<el-input-number
213-
v-model="value.min_trample"
214-
class="w-25!"
215-
size="small"
216-
controls-position="right"
217-
align="left"
218-
:min="0"
219-
:value-on-clear="0"
220-
step-strictly
221-
/>
222-
</div>
223-
</div>
224-
</template>
225-
</MkTableFilter>
193+
<MkTableFilter v-model="selectedFeedback" mode="single" label="用户反馈" :options="feedbackOptions" @change="handleFeedbackChange" />
226194
</template>
227195
<template #default="{ row }">
228196
<span v-if="!row.star_num && !row.trample_num">-</span>

0 commit comments

Comments
 (0)