187 lines
5.3 KiB
TypeScript
187 lines
5.3 KiB
TypeScript
import { appSharePageMethods } from '../../base/pageMixin';
|
|
import { AGE_BANDS, AgeBandKey } from '../../core/data/difficulty';
|
|
import { parseMiniProgramUrl } from '../../utils/index';
|
|
import {
|
|
AGE_ABILITIES,
|
|
AGE_TAB_SUB,
|
|
AGE_WEEK_PLANS,
|
|
type AbilityItem,
|
|
type WeekPlan,
|
|
} from './age.config';
|
|
|
|
const DEFAULT_AGE: AgeBandKey = '3-4';
|
|
|
|
const TAB_BAR_PATHS = new Set([
|
|
'/pages/home/home',
|
|
'/pages/category/category',
|
|
'/pages/age/age',
|
|
'/pages/favorites/favorites',
|
|
'/pages/profile/profile',
|
|
]);
|
|
|
|
let _navigating = false;
|
|
|
|
function releaseNavigateLock() {
|
|
_navigating = false;
|
|
}
|
|
|
|
function navigateByPath(path?: string, fallbackTitle?: string) {
|
|
if (_navigating) return;
|
|
|
|
const p = String(path || '').trim();
|
|
if (!p) {
|
|
wx.showToast({
|
|
title: fallbackTitle ? `${fallbackTitle} 即将上线` : '即将上线',
|
|
icon: 'none',
|
|
});
|
|
return;
|
|
}
|
|
const { path: basePath, query } = parseMiniProgramUrl(p);
|
|
if (TAB_BAR_PATHS.has(basePath)) {
|
|
if (Object.keys(query).length > 0) {
|
|
console.warn(
|
|
'[age navigateByPath] tabBar 不支持携带参数,已忽略 query:',
|
|
basePath,
|
|
query,
|
|
);
|
|
}
|
|
_navigating = true;
|
|
wx.switchTab({
|
|
url: basePath,
|
|
complete: releaseNavigateLock,
|
|
fail: releaseNavigateLock,
|
|
});
|
|
return;
|
|
}
|
|
_navigating = true;
|
|
wx.navigateTo({
|
|
url: p,
|
|
complete: releaseNavigateLock,
|
|
fail: (err) => {
|
|
console.error('navigateByPath error:', err);
|
|
releaseNavigateLock();
|
|
},
|
|
});
|
|
}
|
|
|
|
type RecommendedItemView = {
|
|
title: string;
|
|
image: string;
|
|
subtitle: string;
|
|
ageBand: string;
|
|
difficulty: string;
|
|
path: string;
|
|
worksheetId?: string;
|
|
};
|
|
const RECOMMENDED_FALLBACK: RecommendedItemView[] = [];
|
|
|
|
const DIFFICULTY_LABELS: Record<string, string> = {
|
|
1: '入门',
|
|
2: '基础',
|
|
3: '进阶',
|
|
4: '挑战',
|
|
};
|
|
|
|
function toDifficultyLabel(value: unknown) {
|
|
const text = String(value || '').trim();
|
|
return DIFFICULTY_LABELS[text] || text;
|
|
}
|
|
|
|
async function fetchAgeRecommended(
|
|
ageKey: AgeBandKey,
|
|
): Promise<RecommendedItemView[]> {
|
|
try {
|
|
const res = await wx.cloud.callFunction({
|
|
name: 'ageRecommendedQuery',
|
|
data: { ageKey },
|
|
});
|
|
const payload = (res && (res.result as any)) || null;
|
|
if (!payload?.success) return [];
|
|
const items = (payload.data?.items || []) as any[];
|
|
return items
|
|
.map((it) => ({
|
|
title: String(it.title || ''),
|
|
image: String(it.previewImg || ''),
|
|
subtitle: String(it.subtitle || ''),
|
|
ageBand: String(it.ageBand || it.ageRange || ''),
|
|
difficulty: toDifficultyLabel(
|
|
it.difficultyLabel || it.difficulty || '',
|
|
),
|
|
path: String(it.path || ''),
|
|
worksheetId: String(it.worksheetId || ''),
|
|
}))
|
|
.filter((it) => it.title);
|
|
} catch (e) {
|
|
console.warn('[age] fetchAgeRecommended failed:', e);
|
|
return [];
|
|
}
|
|
}
|
|
|
|
Page({
|
|
data: {
|
|
ageTabs: AGE_BANDS.map((b) => ({
|
|
key: b.key,
|
|
rangeText: b.label.replace(/\s*岁\s*$/, ''),
|
|
subLabel: AGE_TAB_SUB[b.key],
|
|
})),
|
|
activeAgeKey: DEFAULT_AGE as AgeBandKey,
|
|
goalTitle: '',
|
|
abilityItems: [] as AbilityItem[],
|
|
weekPlans: [] as WeekPlan[],
|
|
recommendedItems: RECOMMENDED_FALLBACK,
|
|
recommendedLoading: false,
|
|
},
|
|
|
|
onLoad() {
|
|
this.applyAge(DEFAULT_AGE);
|
|
},
|
|
|
|
async applyAge(key: AgeBandKey) {
|
|
const band = AGE_BANDS.find((b) => b.key === key);
|
|
const goalTitle = band ? `${band.label}能力目标` : '能力目标';
|
|
this.setData({
|
|
activeAgeKey: key,
|
|
goalTitle,
|
|
abilityItems: AGE_ABILITIES[key] || [],
|
|
weekPlans: AGE_WEEK_PLANS[key] || [],
|
|
recommendedLoading: true,
|
|
});
|
|
|
|
const recommended = await fetchAgeRecommended(key);
|
|
this.setData({
|
|
recommendedItems:
|
|
recommended.length > 0 ? recommended : RECOMMENDED_FALLBACK,
|
|
recommendedLoading: false,
|
|
});
|
|
},
|
|
|
|
onAgeTabTap(e: WechatMiniprogram.TouchEvent) {
|
|
const key = e.currentTarget.dataset.key as AgeBandKey | undefined;
|
|
if (!key) return;
|
|
this.applyAge(key);
|
|
},
|
|
|
|
onPracticeTap(e: WechatMiniprogram.TouchEvent) {
|
|
const path = e.currentTarget.dataset.path as string | undefined;
|
|
const title = e.currentTarget.dataset.title as string | undefined;
|
|
navigateByPath(path, title);
|
|
},
|
|
|
|
onRecommendMore() {
|
|
wx.switchTab({ url: '/pages/home/home' });
|
|
},
|
|
|
|
onTapCard(e: WechatMiniprogram.CustomEvent) {
|
|
const detail = (e.detail || {}) as { title?: string; path?: string };
|
|
const path =
|
|
detail.path ||
|
|
(e.currentTarget.dataset.path as string | undefined);
|
|
const title =
|
|
detail.title ||
|
|
(e.currentTarget.dataset.title as string | undefined);
|
|
navigateByPath(path, title);
|
|
},
|
|
|
|
...appSharePageMethods,
|
|
});
|