233 lines
7.0 KiB
TypeScript
233 lines
7.0 KiB
TypeScript
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<string, string>) {
|
|
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,
|
|
});
|