@@ -46,10 +46,9 @@ let knowledgeScroll = ref()
4646let page = 1 ;
4747let pageSize = 35 ;
4848
49- const selectedTagId = ref <string >(" " );
49+ const selectedTagId = ref <string >(" __untagged__ " );
5050const tagList = ref <any []>([]);
5151const tagLoading = ref (false );
52- const overallKnowledgeTotal = ref (0 );
5352const tagSearchQuery = ref (' ' );
5453const TAG_PAGE_SIZE = 50 ;
5554const tagPage = ref (1 );
@@ -60,6 +59,7 @@ let tagSearchDebounce: ReturnType<typeof setTimeout> | null = null;
6059let docSearchDebounce: ReturnType <typeof setTimeout > | null = null ;
6160const docSearchKeyword = ref (' ' );
6261const selectedFileType = ref (' ' );
62+ const UNTAGGED_TAG_ID = ' __untagged__' ;
6363const fileTypeOptions = computed (() => [
6464 { content: t (' knowledgeBase.allFileTypes' ) || ' 全部类型' , value: ' ' },
6565 { content: ' PDF' , value: ' pdf' },
@@ -73,11 +73,13 @@ const fileTypeOptions = computed(() => [
7373type TagInputInstance = ComponentPublicInstance <{ focus: () => void ; select: () => void }>;
7474const tagDropdownOptions = computed (() => {
7575 const options = [
76- { content: t (' knowledgeBase.untagged' ) || ' 未分类' , value: " " },
77- ... tagList .value .map ((tag : any ) => ({
78- content: tag .name ,
79- value: tag .id ,
80- })),
76+ { content: t (' knowledgeBase.untagged' ) || ' 未分类' , value: UNTAGGED_TAG_ID },
77+ ... tagList .value
78+ .filter ((tag : any ) => tag .id !== UNTAGGED_TAG_ID )
79+ .map ((tag : any ) => ({
80+ content: tag .name ,
81+ value: tag .id ,
82+ })),
8183 ];
8284 return options ;
8385});
@@ -88,17 +90,15 @@ const tagMap = computed<Record<string, any>>(() => {
8890 });
8991 return map ;
9092});
91- const sidebarCategoryCount = computed (() => tagList .value .length + 1 );
92- const assignedKnowledgeTotal = computed (() =>
93- tagList .value .reduce ((sum , tag ) => sum + (tag .knowledge_count || 0 ), 0 ),
94- );
95- const untaggedKnowledgeCount = computed (() => {
96- return Math .max (overallKnowledgeTotal .value - assignedKnowledgeTotal .value , 0 );
97- });
93+ const sidebarCategoryCount = computed (() => tagList .value .length );
94+ // Filter out the untagged pseudo-tag from regular tags
95+ const regularTags = computed (() => tagList .value .filter ((tag ) => tag .id !== UNTAGGED_TAG_ID ));
96+ // Get the untagged pseudo-tag from the list
97+ const untaggedTag = computed (() => tagList .value .find ((tag ) => tag .id === UNTAGGED_TAG_ID ));
9898const filteredTags = computed (() => {
9999 const query = tagSearchQuery .value .trim ().toLowerCase ();
100- if (! query ) return tagList .value ;
101- return tagList .value .filter ((tag ) => (tag .name || ' ' ).toLowerCase ().includes (query ));
100+ if (! query ) return regularTags .value ;
101+ return regularTags .value .filter ((tag ) => (tag .name || ' ' ).toLowerCase ().includes (query ));
102102});
103103
104104const editingTagInputRefs = new Map <string , TagInputInstance | null >();
@@ -129,6 +129,7 @@ getPageSize()
129129// 直接调用 API 获取知识库文件列表
130130const getTagName = (tagId ? : string | number ) => {
131131 if (! tagId && tagId !== 0 ) return t (' knowledgeBase.untagged' ) || ' 未分类' ;
132+ if (tagId === UNTAGGED_TAG_ID ) return t (' knowledgeBase.untagged' ) || ' 未分类' ;
132133 const key = String (tagId );
133134 return tagMap .value [key ]?.name || (t (' knowledgeBase.untagged' ) || ' 未分类' );
134135};
@@ -252,8 +253,8 @@ const handleUntaggedClick = () => {
252253 editingTagId .value = null ;
253254 editingTagName .value = ' ' ;
254255 }
255- if (selectedTagId .value === ' ' ) return ;
256- handleTagFilterChange (' ' );
256+ if (selectedTagId .value === UNTAGGED_TAG_ID ) return ;
257+ handleTagFilterChange (UNTAGGED_TAG_ID );
257258};
258259
259260const startCreateTag = () => {
@@ -363,7 +364,7 @@ const confirmDeleteTag = (tag: any) => {
363364 .then (() => {
364365 MessagePlugin .success (t (' knowledgeBase.tagDeleteSuccess' ));
365366 if (selectedTagId .value === tag .id ) {
366- handleTagFilterChange (' ' );
367+ handleTagFilterChange (UNTAGGED_TAG_ID );
367368 }
368369 loadTags (kbId .value );
369370 loadKnowledgeFiles (kbId .value );
@@ -375,7 +376,9 @@ const confirmDeleteTag = (tag: any) => {
375376
376377const handleKnowledgeTagChange = async (knowledgeId : string , tagValue : string ) => {
377378 try {
378- await updateKnowledgeTagBatch ({ updates: { [knowledgeId ]: tagValue || null } });
379+ // When selecting "untagged", pass null to clear the tag
380+ const tagIdToUpdate = tagValue === UNTAGGED_TAG_ID ? null : (tagValue || null );
381+ await updateKnowledgeTagBatch ({ updates: { [knowledgeId ]: tagIdToUpdate } });
379382 MessagePlugin .success (t (' knowledgeBase.tagUpdateSuccess' ) || ' 分类已更新' );
380383 loadKnowledgeFiles (kbId .value );
381384 loadTags (kbId .value );
@@ -393,16 +396,14 @@ const loadKnowledgeBaseInfo = async (targetKbId: string) => {
393396 try {
394397 const res: any = await getKnowledgeBaseById (targetKbId );
395398 kbInfo .value = res ?.data || null ;
396- selectedTagId .value = " " ;
399+ selectedTagId .value = UNTAGGED_TAG_ID ;
397400 if (! isFAQ .value ) {
398- getKnowled ({ page: 1 , page_size: pageSize , tag_id: undefined }, targetKbId );
399401 loadKnowledgeFiles (targetKbId );
400402 } else {
401403 cardList .value = [];
402404 total .value = 0 ;
403405 }
404406 loadTags (targetKbId , true );
405- overallKnowledgeTotal .value = total .value ;
406407 } catch (error ) {
407408 console .error (' Failed to load knowledge base info:' , error );
408409 kbInfo .value = null ;
@@ -440,12 +441,6 @@ watch(selectedTagId, (newVal, oldVal) => {
440441 }
441442});
442443
443- watch (total , (val ) => {
444- if (selectedTagId .value === ' ' ) {
445- overallKnowledgeTotal .value = val || 0 ;
446- }
447- });
448-
449444watch (tagSearchQuery , (newVal , oldVal ) => {
450445 if (newVal === oldVal ) return ;
451446 if (tagSearchDebounce ) {
@@ -857,7 +852,7 @@ const handleScroll = () => {
857852 if (scrollTop + clientHeight >= scrollHeight ) {
858853 page ++ ;
859854 if (cardList .value .length < total .value && page <= pageNum ) {
860- getKnowled ({ page , page_size: pageSize , tag_id: selectedTagId .value || undefined , keyword: docSearchKeyword .value ? docSearchKeyword .value .trim () : undefined , file_type: selectedFileType .value || undefined });
855+ getKnowled ({ page , page_size: pageSize , tag_id: selectedTagId .value , keyword: docSearchKeyword .value ? docSearchKeyword .value .trim () : undefined , file_type: selectedFileType .value || undefined });
861856 }
862857 }
863858 }
@@ -1009,15 +1004,16 @@ async function createNewSession(value: string): Promise<void> {
10091004 <t-loading :loading =" tagLoading" size =" small" >
10101005 <div class =" tag-list" >
10111006 <div
1007+ v-if =" untaggedTag"
10121008 class =" tag-list-item"
1013- :class =" { active: selectedTagId === '' }"
1009+ :class =" { active: selectedTagId === UNTAGGED_TAG_ID }"
10141010 @click =" handleUntaggedClick"
10151011 >
10161012 <div class =" tag-list-left" >
10171013 <t-icon name =" folder" size =" 18px" />
10181014 <span >{{ $t('knowledgeBase.untagged') || '未分类' }}</span >
10191015 </div >
1020- <span class =" tag-count" >{{ untaggedKnowledgeCount }}</span >
1016+ <span class =" tag-count" >{{ untaggedTag.knowledge_count || 0 }}</span >
10211017 </div >
10221018 <div v-if =" creatingTag" class =" tag-list-item tag-editing" @click.stop >
10231019 <div class =" tag-list-left" >
0 commit comments