import { appSharePageMethods } from '../../base/pageMixin'; import { takePendingCategoryTabId } from '../../utils/index'; import tracker from '../../utils/tracker'; import { ApiRequestError } from '../../services/api-request'; import { getWorksheet, listAllWorksheets, listCategories, } from '../../services/content-api'; import { BASE_TABS, buildCategoryDataset, getCategoryItems, type CategoryDataset, type CategoryItem, } from './category.model'; const TAB_BAR_PATHS = new Set([ '/pages/home/home', '/pages/category/category', '/pages/age/age', '/pages/favorites/favorites', '/pages/profile/profile', ]); const SKELETON_ITEMS: CategoryItem[] = Array.from( { length: 6 }, (_, index) => ({ id: `skeleton-${index}`, title: '\u00a0', subtitle: '\u00a0', icon: '', previewImg: '', ageBand: '', difficultyLabel: '', path: '', available: false, likes: '', downloads: '', date: '', updatedAt: '', skeleton: true, }), ); Page({ data: { searchPlaceholder: '搜索练习纸...', searchKeyword: '', sidebarTabs: BASE_TABS, activeCategoryId: 'all', displayItems: SKELETON_ITEMS, scrollIntoViewId: '', loading: true, errorMessage: '', }, _defaultCategoryId: 'all', _categoryData: null as CategoryDataset | null, _loadVersion: 0, _opening: false, onLoad(options: Record) { tracker.reportPageView('pages/category/category'); if (options.id && options.id !== 'all') { this._defaultCategoryId = options.id; this.setData({ activeCategoryId: options.id }); } }, onShow() { void this.loadWorksheets(takePendingCategoryTabId() ?? undefined); }, onHide() { this._loadVersion++; }, onUnload() { this._loadVersion++; }, /** 每次进入重新读取公开目录与完整分页;失败清空内容,不回退静态数据或旧云服务。 */ async loadWorksheets(overrideCategoryId?: string) { const version = ++this._loadVersion; this._categoryData = null; this.setData({ displayItems: SKELETON_ITEMS, sidebarTabs: BASE_TABS, loading: true, errorMessage: '', }); try { const [categories, worksheets] = await Promise.all([ listCategories(), listAllWorksheets(), ]); if (version !== this._loadVersion) return; const dataset = buildCategoryDataset(categories, worksheets); const desiredId = overrideCategoryId || this.data.activeCategoryId || this._defaultCategoryId; const activeId = dataset.sidebarTabs.some( (tab) => tab.id === desiredId, ) ? desiredId : 'all'; this._categoryData = dataset; this.setData({ loading: false, sidebarTabs: dataset.sidebarTabs, activeCategoryId: activeId, displayItems: getCategoryItems( dataset, activeId, this.data.searchKeyword, ), scrollIntoViewId: '', errorMessage: '', }); } catch (error) { if (version !== this._loadVersion) return; this._categoryData = null; this.setData({ loading: false, displayItems: [], sidebarTabs: BASE_TABS, errorMessage: error instanceof Error ? error.message : '加载失败,请稍后重试', }); } }, onRetry() { void this.loadWorksheets(); }, onTapCategory(e: WechatMiniprogram.TouchEvent) { const id = e.currentTarget.dataset.id as string; if ( !this._categoryData || this.data.loading || !id || id === this.data.activeCategoryId || !this._categoryData.sidebarTabs.some((tab) => tab.id === id) ) return; this.setData({ activeCategoryId: id, displayItems: getCategoryItems( this._categoryData, id, this.data.searchKeyword, ), scrollIntoViewId: '', }); tracker.report('category_select', 'pages/category/category', { category_id: id, }); }, onSearchInput(e: WechatMiniprogram.Input) { const keyword = (e.detail.value ?? '').trim(); this.setData({ searchKeyword: keyword, displayItems: getCategoryItems( this._categoryData, this.data.activeCategoryId, keyword, ), }); }, onClearSearch() { this.setData({ searchKeyword: '', displayItems: getCategoryItems( this._categoryData, this.data.activeCategoryId, ), }); }, /** 点击时重新检查详情,已下架或网络不可用时不进入内置生成页。 */ async onTapItem(e: WechatMiniprogram.TouchEvent) { const id = e.currentTarget.dataset.id as string; if ( this._opening || this.data.loading || !id || !this.data.displayItems.some( (item) => item.id === id && item.available, ) ) return; this._opening = true; const version = this._loadVersion; try { const row = await getWorksheet(id); if (version !== this._loadVersion) return; if (!row.path) throw new Error('内容暂不可用'); tracker.reportWorksheetClick('pages/category/category', { worksheet_id: row.id, worksheet_title: row.title, category_id: this.data.activeCategoryId, source: 'category_list', }); const fail = () => wx.showToast({ title: '暂时无法打开该内容', icon: 'none' }); if (TAB_BAR_PATHS.has(row.path)) wx.switchTab({ url: row.path, fail }); else wx.navigateTo({ url: row.path, fail }); } catch (error) { if (version !== this._loadVersion) return; wx.showToast({ title: error instanceof Error ? error.message : '暂时无法打开,请稍后重试', icon: 'none', }); if (error instanceof ApiRequestError && error.statusCode === 404) void this.loadWorksheets(); } finally { this._opening = false; } }, ...appSharePageMethods, });