Skip to content

Commit a8f6584

Browse files
author
Taois
committed
feat:详情返回筛选错误
1 parent 1a7aa9c commit a8f6584

File tree

2 files changed

+122
-14
lines changed

2 files changed

+122
-14
lines changed

dashboard/src/components/CategoryNavigation.vue

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858

5959
<!-- 筛选区域 -->
6060
<FilterSection
61-
v-if="getFiltersForCategory(activeKey) && filterVisible[activeKey]"
61+
v-if="getFiltersForCategory(activeKey) && props.filterVisible[activeKey]"
6262
:filters="getFiltersForCategory(activeKey)"
6363
:selectedFilters="selectedFilters[activeKey] || {}"
6464
:visible="true"
@@ -98,6 +98,11 @@ const props = defineProps({
9898
type: Object,
9999
default: () => ({})
100100
},
101+
// 筛选展开状态
102+
filterVisible: {
103+
type: Object,
104+
default: () => ({})
105+
},
101106
// 特殊分类状态
102107
specialCategoryState: {
103108
type: Object,
@@ -110,7 +115,7 @@ const props = defineProps({
110115
}
111116
});
112117
113-
const emit = defineEmits(['tab-change', 'open-category-modal', 'toggle-filter', 'reset-filters', 'close-special-category']);
118+
const emit = defineEmits(['tab-change', 'open-category-modal', 'toggle-filter', 'reset-filters', 'close-special-category', 'filter-visible-change']);
114119
115120
// 计算默认的activeKey
116121
const getDefaultActiveKey = () => {
@@ -126,8 +131,8 @@ const getDefaultActiveKey = () => {
126131
// 响应式数据
127132
const activeKey = ref(props.activeKey || getDefaultActiveKey());
128133
const navWrapperRef = ref(null);
129-
const filterVisible = ref({});
130134
let wheelHandler = null;
135+
const isInitialized = ref(false);
131136
132137
// 监听props变化,更新activeKey
133138
watch(() => [props.hasRecommendVideos, props.classList, props.activeKey], () => {
@@ -141,12 +146,13 @@ watch(() => [props.hasRecommendVideos, props.classList, props.activeKey], () =>
141146
}
142147
}, { immediate: true });
143148
144-
// 当分类切换时,隐藏之前分类的筛选条件
149+
// 当分类切换时,通知父组件隐藏之前分类的筛选条件
150+
// 注意:不在初始化时触发,避免干扰状态恢复
145151
watch(activeKey, (newKey, oldKey) => {
146-
if (oldKey && filterVisible.value[oldKey]) {
147-
filterVisible.value[oldKey] = false;
152+
if (isInitialized.value && oldKey && oldKey !== newKey && props.filterVisible[oldKey]) {
153+
emit('filter-visible-change', { categoryId: oldKey, visible: false });
148154
}
149-
});
155+
}, { flush: 'post' });
150156
151157
const handleTabChange = (key) => {
152158
activeKey.value = key;
@@ -156,7 +162,9 @@ const handleTabChange = (key) => {
156162
// 处理分类点击(显示/隐藏筛选)
157163
const handleCategoryClick = (categoryId) => {
158164
if (hasFiltersForCategory(categoryId)) {
159-
filterVisible.value[categoryId] = !filterVisible.value[categoryId];
165+
const newVisible = !props.filterVisible[categoryId];
166+
// 通知父组件筛选展开状态变化
167+
emit('filter-visible-change', { categoryId, visible: newVisible });
160168
}
161169
};
162170
@@ -205,6 +213,11 @@ onMounted(() => {
205213
}
206214
};
207215
list.addEventListener('wheel', wheelHandler, { passive: false });
216+
217+
// 设置初始化完成标志,允许后续的筛选状态重置
218+
setTimeout(() => {
219+
isInitialized.value = true;
220+
}, 100);
208221
});
209222
210223
onBeforeUnmount(() => {

dashboard/src/components/VideoList.vue

Lines changed: 101 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@
88
:activeKey="activeKey"
99
:filters="props.classList?.filters || {}"
1010
:selectedFilters="selectedFilters"
11+
:filterVisible="filterVisible"
1112
:specialCategoryState="props.specialCategoryState"
1213
@tab-change="handleTabChange"
1314
@open-category-modal="openCategoryModal"
1415
@toggle-filter="handleToggleFilter"
1516
@reset-filters="handleResetFilters"
17+
@filter-visible-change="handleFilterVisibleChange"
1618
@close-special-category="() => emit('close-special-category')"
1719
/>
1820

@@ -143,6 +145,7 @@ import { usePaginationStore } from '@/stores/paginationStore';
143145
import { getCategoryData } from '@/api/modules/module';
144146
import { processExtendParam } from '@/utils/apiUtils';
145147
import { encodeFilters } from '@/api/utils';
148+
import { useRouter } from 'vue-router';
146149
import CategoryNavigation from './CategoryNavigation.vue';
147150
import FilterSection from './FilterSection.vue';
148151
import VideoGrid from './VideoGrid.vue';
@@ -207,6 +210,8 @@ const props = defineProps({
207210
208211
const emit = defineEmits(['activeKeyChange', 'special-action', 'close-special-category', 'folder-navigate']);
209212
213+
const router = useRouter();
214+
210215
// 使用翻页统计store
211216
const paginationStore = usePaginationStore();
212217
@@ -261,6 +266,69 @@ const selectedFilters = reactive({});
261266
const categoryModalVisible = ref(false);
262267
const videoGridRef = ref(null);
263268
269+
// 筛选条件和展开状态持久化函数
270+
const saveFiltersToUrl = () => {
271+
const currentQuery = { ...router.currentRoute.value.query };
272+
273+
if (Object.keys(selectedFilters).length > 0) {
274+
// 将筛选条件编码为JSON字符串保存到URL
275+
currentQuery.filters = JSON.stringify(selectedFilters);
276+
} else {
277+
// 如果没有筛选条件,删除URL中的filters参数
278+
delete currentQuery.filters;
279+
}
280+
281+
// 保存筛选展开状态
282+
if (Object.keys(filterVisible).length > 0) {
283+
currentQuery.filterVisible = JSON.stringify(filterVisible);
284+
} else {
285+
delete currentQuery.filterVisible;
286+
}
287+
288+
// 更新URL,但不触发页面刷新
289+
router.replace({
290+
query: currentQuery
291+
}).catch(() => {
292+
// 忽略导航重复错误
293+
});
294+
};
295+
296+
// 从URL恢复筛选条件和展开状态
297+
const restoreFiltersFromUrl = () => {
298+
const urlFilters = router.currentRoute.value.query.filters;
299+
const urlFilterVisible = router.currentRoute.value.query.filterVisible;
300+
301+
// 恢复筛选条件
302+
if (urlFilters) {
303+
try {
304+
const parsedFilters = JSON.parse(urlFilters);
305+
// 清空现有筛选条件
306+
Object.keys(selectedFilters).forEach(key => {
307+
delete selectedFilters[key];
308+
});
309+
// 恢复筛选条件
310+
Object.assign(selectedFilters, parsedFilters);
311+
} catch (error) {
312+
console.error('解析URL中的筛选条件失败:', error);
313+
}
314+
}
315+
316+
// 恢复筛选展开状态
317+
if (urlFilterVisible) {
318+
try {
319+
const parsedFilterVisible = JSON.parse(urlFilterVisible);
320+
// 清空现有展开状态
321+
Object.keys(filterVisible).forEach(key => {
322+
delete filterVisible[key];
323+
});
324+
// 恢复展开状态
325+
Object.assign(filterVisible, parsedFilterVisible);
326+
} catch (error) {
327+
console.error('解析URL中的筛选展开状态失败:', error);
328+
}
329+
}
330+
};
331+
264332
// 目录模式翻页状态管理
265333
const folderPageData = reactive({});
266334
const folderLoadingMore = reactive({});
@@ -358,6 +426,9 @@ const toggleFilter = (filterKey, filterValue, filterName) => {
358426
selectedFilters[activeKey.value][filterKey] = filterValue;
359427
}
360428
429+
// 保存筛选条件到URL
430+
saveFiltersToUrl();
431+
361432
// 如果在目录模式下,重新获取目录数据
362433
if (folderIsActive.value && folderCurrentBreadcrumb.value) {
363434
handleFolderNavigate(folderCurrentBreadcrumb.value);
@@ -370,6 +441,9 @@ const toggleFilter = (filterKey, filterValue, filterName) => {
370441
const resetFilters = (categoryId) => {
371442
delete selectedFilters[categoryId];
372443
444+
// 保存筛选条件到URL
445+
saveFiltersToUrl();
446+
373447
// 如果在目录模式下,重新获取目录数据
374448
if (folderIsActive.value && folderCurrentBreadcrumb.value) {
375449
handleFolderNavigate(folderCurrentBreadcrumb.value);
@@ -673,6 +747,13 @@ const handleToggleFilter = (data) => {
673747
toggleFilter(filterKey, filterValue, filterName);
674748
};
675749
750+
const handleFilterVisibleChange = (data) => {
751+
const { categoryId, visible } = data;
752+
filterVisible[categoryId] = visible;
753+
// 保存筛选展开状态到URL
754+
saveFiltersToUrl();
755+
};
756+
676757
const handleResetFilters = () => {
677758
resetFilters(activeKey.value);
678759
};
@@ -721,6 +802,7 @@ watch(() => props.recommendVideos, (newVideos) => {
721802
}, { immediate: true });
722803
723804
// 添加classList watch的防护变量
805+
// 防止递归更新的标志
724806
let isClassListUpdating = false;
725807
let lastClassListHash = '';
726808
@@ -755,8 +837,13 @@ watch(() => props.classList, (newClassList, oldClassList) => {
755837
lastClassListHash = newHash;
756838
757839
try {
758-
if (newClassList !== oldClassList) {
759-
console.log('🗂️ [DEBUG] classList发生变化,清除筛选状态');
840+
// 检查URL中是否有筛选参数需要恢复
841+
const currentQuery = router.currentRoute.value.query;
842+
const hasFiltersInUrl = currentQuery.filters || currentQuery.filterVisible;
843+
844+
// 只有在classList真正发生变化且URL中没有筛选参数时才清除筛选状态
845+
if (newClassList !== oldClassList && !hasFiltersInUrl) {
846+
console.log('🗂️ [DEBUG] classList发生变化且URL中无筛选参数,清除筛选状态');
760847
// 清除筛选状态
761848
Object.keys(selectedFilters).forEach(key => {
762849
delete selectedFilters[key];
@@ -765,6 +852,8 @@ watch(() => props.classList, (newClassList, oldClassList) => {
765852
delete filterVisible[key];
766853
});
767854
console.log('🗂️ [DEBUG] 筛选状态已清除');
855+
} else if (hasFiltersInUrl) {
856+
console.log('🗂️ [DEBUG] URL中有筛选参数,跳过筛选状态清除');
768857
}
769858
770859
// 如果当前处于folder模式,不要重置activeKey,避免覆盖folder状态
@@ -811,15 +900,22 @@ watch(() => props.sourceRoute?.query?.activeKey, (newActiveKey) => {
811900
}
812901
}, { immediate: true });
813902
814-
onMounted(() => {
903+
onMounted(async () => {
904+
// 从URL恢复筛选条件
905+
restoreFiltersFromUrl();
906+
815907
// 优先使用父组件传递的activeKey,如果没有则使用默认值
816908
const parentActiveKey = props.sourceRoute?.query?.activeKey;
817909
const targetActiveKey = parentActiveKey || getDefaultActiveKey();
818910
819-
console.log('[DEBUG] VideoList onMounted - parentActiveKey:', parentActiveKey, 'targetActiveKey:', targetActiveKey);
820-
911+
// 使用nextTick确保筛选状态已经传递给子组件
912+
await nextTick();
821913
activeKey.value = targetActiveKey;
822914
915+
// 再次使用nextTick确保classList watcher执行完毕后,重新恢复筛选状态
916+
await nextTick();
917+
restoreFiltersFromUrl();
918+
823919
// 对于推荐分类,确保loading状态正确
824920
if (targetActiveKey === "recommendTuijian404") {
825921
loadingCategory[targetActiveKey] = false;
@@ -828,7 +924,6 @@ onMounted(() => {
828924
listData[targetActiveKey] = [...props.recommendVideos];
829925
pageData[targetActiveKey] = { page: 1, hasNext: false };
830926
loadingMore[targetActiveKey] = false;
831-
console.log('[DEBUG] 推荐数据已设置,跳过getListData调用');
832927
} else {
833928
// 如果没有推荐数据,才调用getListData
834929
getListData(activeKey.value);

0 commit comments

Comments
 (0)