@@ -3,7 +3,7 @@ import type { Group } from "@/types/models";
33import { getGroupDisplayName } from " @/utils/display" ;
44import { Add , Search } from " @vicons/ionicons5" ;
55import { NButton , NCard , NEmpty , NInput , NSpin , NTag } from " naive-ui" ;
6- import { computed , ref } from " vue" ;
6+ import { computed , ref , watch } from " vue" ;
77import { useI18n } from " vue-i18n" ;
88import GroupFormModal from " ./GroupFormModal.vue" ;
99
@@ -29,6 +29,8 @@ const emit = defineEmits<Emits>();
2929
3030const searchText = ref (" " );
3131const showGroupModal = ref (false );
32+ // 存储分组项 DOM 元素的引用
33+ const groupItemRefs = ref (new Map ());
3234
3335// 过滤后的分组列表
3436const filteredGroups = computed (() => {
@@ -43,6 +45,28 @@ const filteredGroups = computed(() => {
4345 );
4446});
4547
48+ // 监听选中项 ID 的变化,并自动滚动到该项
49+ watch (
50+ () => props .selectedGroup ?.id ,
51+ id => {
52+ if (! id || props .groups .length === 0 ) {
53+ return ;
54+ }
55+
56+ const element = groupItemRefs .value .get (id );
57+ if (element ) {
58+ element .scrollIntoView ({
59+ behavior: " smooth" , // 平滑滚动
60+ block: " nearest" , // 将元素滚动到最近的边缘
61+ });
62+ }
63+ },
64+ {
65+ flush: " post" , // 确保在 DOM 更新后执行回调
66+ immediate: true , // 立即执行一次以处理初始加载
67+ }
68+ );
69+
4670function handleGroupClick(group : Group ) {
4771 emit (" group-select" , group );
4872}
@@ -107,6 +131,11 @@ function handleGroupCreated(group: Group) {
107131 class =" group-item"
108132 :class =" { active: selectedGroup?.id === group.id }"
109133 @click =" handleGroupClick(group)"
134+ :ref ="
135+ el => {
136+ if (el) groupItemRefs.set(group.id, el);
137+ }
138+ "
110139 >
111140 <div class =" group-icon" >
112141 <span v-if =" group.channel_type === 'openai'" >🤖</span >
0 commit comments