feat: 首页、分类页加载数据逻辑重构

This commit is contained in:
R524809
2026-04-30 16:44:45 +08:00
parent c112c70bab
commit 7126d3a941
63 changed files with 805 additions and 433 deletions
+27 -27
View File
@@ -12,7 +12,7 @@ export type HomeDisplayItem = {
difficulty: '入门' | '基础' | '进阶' | '挑战';
icon: string;
/** 横向滑动卡片顶部图,有则优先展示,可与 icon 二选一 */
img?: string;
previewImg?: string;
badge?: string;
path: string;
available: boolean;
@@ -139,7 +139,7 @@ export const HOME_PRODUCT_TARGET_DATA: HomeDisplayDataset = {
difficulty: '基础',
icon: '',
badge: '热门',
img: '/assets/entrancePicture/math/addition-5.png',
previewImg: '/assets/entrancePicture/math/addition-5.png',
path: '/mathPages/mathDraw/mathDraw?id=addition',
available: true,
source: '现有加减法页面可承接',
@@ -160,7 +160,7 @@ export const HOME_PRODUCT_TARGET_DATA: HomeDisplayDataset = {
ageBand: '3-4岁',
difficulty: '入门',
icon: '🔢',
img: '/assets/entrancePicture/math/number-find.png',
previewImg: '/assets/entrancePicture/math/number-find.png',
path: '/mathPages/mathDraw/mathDraw?id=number-find',
available: true,
source: '现有 找数字/写数字 能力',
@@ -173,7 +173,7 @@ export const HOME_PRODUCT_TARGET_DATA: HomeDisplayDataset = {
ageBand: '4-5岁',
difficulty: '基础',
icon: '🧮',
img: '/assets/entrancePicture/math/count-match.png',
previewImg: '/assets/entrancePicture/math/count-match.png',
path: '/mathPages/mathDraw/mathDraw?id=counting-matching',
available: true,
source: '现有 countMatch/countingSelect',
@@ -186,7 +186,7 @@ export const HOME_PRODUCT_TARGET_DATA: HomeDisplayDataset = {
ageBand: '5-7岁',
difficulty: '基础',
icon: '',
img: '/assets/entrancePicture/math/addition-5.png',
previewImg: '/assets/entrancePicture/math/addition-5.png',
path: '/mathPages/mathDraw/mathDraw?id=addition',
available: true,
source: '现有 addition/calculationPractice',
@@ -355,7 +355,7 @@ export const HOME_PRODUCT_TARGET_DATA: HomeDisplayDataset = {
ageBand: '4-6岁',
difficulty: '基础',
icon: '🧵',
img: '/assets/entrancePicture/focus/dot-connect.png',
previewImg: '/assets/entrancePicture/focus/dot-connect.png',
path: '/focusPages/focusDraw/focusDraw?id=dot-connect',
available: true,
source: '现有 dotConnect/matchConnect',
@@ -435,7 +435,7 @@ export const HOME_CURRENT_CAPABILITY_DATA: HomeDisplayDataset = {
difficulty: '基础',
icon: '',
badge: 'HOT',
img: '/assets/entrancePicture/math/addition-5.png',
previewImg: '/assets/entrancePicture/math/addition-5.png',
path: '/mathPages/mathDraw/mathDraw?id=addition',
available: true,
source: '现有功能清单 addition',
@@ -464,7 +464,7 @@ export const HOME_CURRENT_CAPABILITY_DATA: HomeDisplayDataset = {
difficulty: '基础',
icon: '🔗',
badge: '热门',
img: '/assets/entrancePicture/focus/dot-connect.png',
previewImg: '/assets/entrancePicture/focus/dot-connect.png',
path: '/focusPages/focusDraw/focusDraw?id=dot-connect',
available: true,
source: '现有功能清单 dot-connect',
@@ -480,7 +480,7 @@ export const HOME_CURRENT_CAPABILITY_DATA: HomeDisplayDataset = {
difficulty: '入门',
icon: '🔢',
badge: '热门',
img: '/assets/entrancePicture/math/number-find.png',
previewImg: '/assets/entrancePicture/math/number-find.png',
path: '/mathPages/mathDraw/mathDraw?id=number-find',
available: true,
source: 'number-find',
@@ -494,7 +494,7 @@ export const HOME_CURRENT_CAPABILITY_DATA: HomeDisplayDataset = {
difficulty: '基础',
icon: '🧮',
badge: '热门',
img: '/assets/entrancePicture/math/count-match.png',
previewImg: '/assets/entrancePicture/math/count-match.png',
path: '/mathPages/mathDraw/mathDraw?id=counting-matching',
available: true,
source: 'counting-matching',
@@ -508,7 +508,7 @@ export const HOME_CURRENT_CAPABILITY_DATA: HomeDisplayDataset = {
difficulty: '进阶',
icon: '🟨',
badge: '热门',
img: '/assets/entrancePicture/focus/grid-drawing-5x5.png',
previewImg: '/assets/entrancePicture/focus/grid-drawing-5x5.png',
path: '/focusPages/focusDraw/focusDraw?id=grid-drawing',
available: true,
source: 'grid-drawing-5x5',
@@ -529,7 +529,7 @@ export const HOME_CURRENT_CAPABILITY_DATA: HomeDisplayDataset = {
ageBand: '3-4岁',
difficulty: '入门',
icon: '🔢',
img: '/assets/entrancePicture/math/number-find.png',
previewImg: '/assets/entrancePicture/math/number-find.png',
path: '/mathPages/mathDraw/mathDraw?id=number-find',
available: true,
source: 'number-find / number-write',
@@ -542,7 +542,7 @@ export const HOME_CURRENT_CAPABILITY_DATA: HomeDisplayDataset = {
ageBand: '4-5岁',
difficulty: '基础',
icon: '🧮',
img: '/assets/entrancePicture/math/count-match.png',
previewImg: '/assets/entrancePicture/math/count-match.png',
path: '/mathPages/mathDraw/mathDraw?id=counting-matching',
available: true,
source: 'countMatch / countingSelect',
@@ -555,7 +555,7 @@ export const HOME_CURRENT_CAPABILITY_DATA: HomeDisplayDataset = {
ageBand: '4-5岁',
difficulty: '基础',
icon: '📈',
img: '/assets/entrancePicture/math/number-sort.png',
previewImg: '/assets/entrancePicture/math/number-sort.png',
path: '/mathPages/mathDraw/mathDraw?id=number-sort',
available: true,
source: 'numberSort / missingNumber',
@@ -568,7 +568,7 @@ export const HOME_CURRENT_CAPABILITY_DATA: HomeDisplayDataset = {
ageBand: '5-7岁',
difficulty: '基础',
icon: '',
img: '/assets/entrancePicture/math/addition-5.png',
previewImg: '/assets/entrancePicture/math/addition-5.png',
path: '/mathPages/mathDraw/mathDraw?id=addition',
available: true,
source: 'addition / calculationPractice',
@@ -581,7 +581,7 @@ export const HOME_CURRENT_CAPABILITY_DATA: HomeDisplayDataset = {
ageBand: '7-8岁',
difficulty: '挑战',
icon: '✖️',
img: '/assets/entrancePicture/math/multiplication-table.png',
previewImg: '/assets/entrancePicture/math/multiplication-table.png',
path: '/mathPages/mathDraw/mathDraw?id=multiplication-table',
available: true,
source: 'multiplicationTable',
@@ -646,7 +646,7 @@ export const HOME_CURRENT_CAPABILITY_DATA: HomeDisplayDataset = {
ageBand: '4-6岁',
difficulty: '基础',
icon: '🔗',
img: '/assets/entrancePicture/focus/dot-connect.png',
previewImg: '/assets/entrancePicture/focus/dot-connect.png',
path: '/focusPages/focusDraw/focusDraw?id=dot-connect',
available: true,
source: 'dot-connect',
@@ -659,7 +659,7 @@ export const HOME_CURRENT_CAPABILITY_DATA: HomeDisplayDataset = {
ageBand: '4-6岁',
difficulty: '基础',
icon: '🧵',
img: '/assets/entrancePicture/focus/match-connect.png',
previewImg: '/assets/entrancePicture/focus/match-connect.png',
path: '/focusPages/focusDraw/focusDraw?id=match-connect',
available: true,
source: 'match-connect',
@@ -672,7 +672,7 @@ export const HOME_CURRENT_CAPABILITY_DATA: HomeDisplayDataset = {
ageBand: '4-6岁',
difficulty: '基础',
icon: '🌈',
img: '/assets/entrancePicture/focus/color-pattern.png',
previewImg: '/assets/entrancePicture/focus/color-pattern.png',
path: '/focusPages/focusDraw/focusDraw?id=color-pattern',
available: true,
source: 'color-pattern',
@@ -685,7 +685,7 @@ export const HOME_CURRENT_CAPABILITY_DATA: HomeDisplayDataset = {
ageBand: '5-7岁',
difficulty: '进阶',
icon: '🧠',
img: '/assets/entrancePicture/focus/grid-reasoning.png',
previewImg: '/assets/entrancePicture/focus/grid-reasoning.png',
path: '/focusPages/focusDraw/focusDraw?id=grid-reasoning',
available: true,
source: 'grid-reasoning',
@@ -698,7 +698,7 @@ export const HOME_CURRENT_CAPABILITY_DATA: HomeDisplayDataset = {
ageBand: '4-7岁',
difficulty: '进阶',
icon: '🟨',
img: '/assets/entrancePicture/focus/grid-drawing-5x5.png',
previewImg: '/assets/entrancePicture/focus/grid-drawing-5x5.png',
path: '/focusPages/focusDraw/focusDraw?id=grid-drawing',
available: true,
source: 'grid-drawing',
@@ -719,7 +719,7 @@ export const HOME_CURRENT_CAPABILITY_DATA: HomeDisplayDataset = {
ageBand: '4-7岁',
difficulty: '入门',
icon: '',
img: '/assets/entrancePicture/english/letter-tracing-single.jpg',
previewImg: '/assets/entrancePicture/english/letter-tracing-single.jpg',
path: '/englishPages/letterTracing/letterTracing?id=letter-tracing-single',
available: true,
source: 'letter-tracing-single',
@@ -732,7 +732,7 @@ export const HOME_CURRENT_CAPABILITY_DATA: HomeDisplayDataset = {
ageBand: '4-7岁',
difficulty: '入门',
icon: '',
img: '/assets/entrancePicture/english/letter-tracing-upper-lower.jpg',
previewImg: '/assets/entrancePicture/english/letter-tracing-upper-lower.jpg',
path: '/englishPages/letterTracing/letterTracing?id=letter-tracing-upper-lower',
available: true,
source: 'letter-tracing-upper-lower',
@@ -745,7 +745,7 @@ export const HOME_CURRENT_CAPABILITY_DATA: HomeDisplayDataset = {
ageBand: '4-7岁',
difficulty: '入门',
icon: '',
img: '/assets/entrancePicture/english/letter-tracing-case-pairing.jpg',
previewImg: '/assets/entrancePicture/english/letter-tracing-case-pairing.jpg',
path: '/englishPages/letterTracing/letterTracing?id=letter-tracing-case-pairing',
available: true,
source: 'letter-tracing-case-pairing',
@@ -758,7 +758,7 @@ export const HOME_CURRENT_CAPABILITY_DATA: HomeDisplayDataset = {
ageBand: '4-7岁',
difficulty: '入门',
icon: '',
img: '/assets/entrancePicture/english/letter-tracing-two-column.jpg',
previewImg: '/assets/entrancePicture/english/letter-tracing-two-column.jpg',
path: '/englishPages/letterTracing/letterTracing?id=letter-tracing-two-column',
available: true,
source: 'letter-tracing-two-column',
@@ -771,7 +771,7 @@ export const HOME_CURRENT_CAPABILITY_DATA: HomeDisplayDataset = {
ageBand: '4-7岁',
difficulty: '入门',
icon: '',
img: '/assets/entrancePicture/english/letter-tracing-half.jpg',
previewImg: '/assets/entrancePicture/english/letter-tracing-half.jpg',
path: '/englishPages/letterTracing/letterTracing?id=letter-tracing-half',
available: true,
source: 'letter-tracing-half',
@@ -784,7 +784,7 @@ export const HOME_CURRENT_CAPABILITY_DATA: HomeDisplayDataset = {
ageBand: '4-7岁',
difficulty: '入门',
icon: '',
img: '/assets/entrancePicture/english/letter-tracing-three.jpg',
previewImg: '/assets/entrancePicture/english/letter-tracing-three.jpg',
path: '/englishPages/letterTracing/letterTracing?id=letter-tracing-three',
available: true,
source: 'letter-tracing-three',
+94 -4
View File
@@ -83,6 +83,15 @@
border-top-left-radius: 32rpx;
border-top-right-radius: 32rpx;
overflow: hidden;
border-bottom: 1rpx solid rgba(50, 46, 37, 0.08);
background: #f5edd8;
}
.home-hero-card__cover {
width: 100%;
height: 100%;
display: block;
object-fit: cover;
}
.home-hero-card__icon {
@@ -216,6 +225,8 @@
display: flex;
align-items: flex-start;
justify-content: center;
border-bottom: 1rpx solid rgba(50, 46, 37, 0.08);
background: #f5edd8;
}
.home-track-card__cover {
@@ -242,7 +253,6 @@
padding: 20rpx @page-padding-inner-x 22rpx;
background: #ffffff;
white-space: normal;
border-top: 1rpx solid #c5c5c5;
}
.home-track-card__title {
@@ -264,7 +274,7 @@
box-sizing: border-box;
width: 100%;
margin-top: 8rpx;
font-size: 22rpx;
font-size: 20rpx;
color: @text-gray;
line-height: 1.45;
display: -webkit-box;
@@ -350,12 +360,22 @@
.home-hot-card__thumb {
width: 144rpx;
height: 144rpx;
border-radius: 24rpx;
height: 180rpx;
border-radius: 18rpx;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
overflow: hidden;
border: 1rpx solid rgba(50, 46, 37, 0.08);
background: #f5edd8;
}
.home-hot-card__thumb-img {
width: 100%;
height: 100%;
display: block;
object-fit: cover;
}
.home-hot-card__thumb-emoji {
@@ -367,6 +387,9 @@
flex-direction: column;
min-width: 0;
flex: 1;
justify-content: space-between;
align-self: stretch;
padding: 6rpx 0;
}
.home-hot-card__title {
@@ -438,4 +461,71 @@
background: @brand;
color: @text-selected-btn;
font-weight: 600;
}
// ── Skeleton ──
@keyframes home-skeleton-pulse {
0% {
opacity: 0.6;
}
50% {
opacity: 0.3;
}
100% {
opacity: 0.6;
}
}
.home-hero-card--skeleton {
pointer-events: none;
.home-hero-card__top {
animation: home-skeleton-pulse 1.5s ease-in-out infinite;
}
.home-hero-card__title,
.home-hero-card__sub {
background: #e8e2d5;
border-radius: 8rpx;
color: transparent;
animation: home-skeleton-pulse 1.5s ease-in-out infinite;
}
.home-hero-card__title {
width: 50%;
height: 36rpx;
}
.home-hero-card__sub {
width: 70%;
height: 26rpx;
}
}
.home-hot-card--skeleton {
pointer-events: none;
.home-hot-card__thumb {
animation: home-skeleton-pulse 1.5s ease-in-out infinite;
}
.home-hot-card__title,
.home-hot-card__desc {
background: #e8e2d5;
border-radius: 8rpx;
color: transparent;
animation: home-skeleton-pulse 1.5s ease-in-out infinite;
}
.home-hot-card__title {
width: 40%;
height: 32rpx;
}
.home-hot-card__desc {
width: 65%;
height: 24rpx;
}
}
+101 -38
View File
@@ -3,6 +3,7 @@ import {
HOME_CURRENT_CAPABILITY_DATA,
type HomeDisplayItem,
type HomeDisplaySection,
type HomeDisplayDataset,
} from './home.data';
type AgeBandKey = string;
@@ -21,7 +22,7 @@ type HomeAgeBandView = {
};
type HomeDisplayItemView = HomeDisplayItem & {
topBg: string;
skeleton?: boolean;
};
type HomeDisplaySectionView = HomeDisplaySection & {
@@ -31,14 +32,6 @@ type HomeDisplaySectionView = HomeDisplaySection & {
const AGE_BAND_ICONS = ['🌱', '🚀', '🎓', '🧠', '🏆'] as const;
const CATEGORY_TOP_BG: Record<HomeDisplayItem['category'], string> = {
math: '#fff3c4',
chinese: '#d8f0d0',
english: '#e8f4ff',
puzzle: '#f5e6dc',
craft: '#fce4ec',
};
const SECTION_ANCHOR_PREFIX = 'section-';
const TAB_BAR_PATHS = new Set([
'/pages/home/home',
@@ -50,7 +43,6 @@ const TAB_BAR_PATHS = new Set([
function toItemView(item: HomeDisplayItem): HomeDisplayItemView {
return {
...item,
topBg: CATEGORY_TOP_BG[item.category],
};
}
@@ -64,12 +56,7 @@ function sortSectionsByTabs(
}, {});
return [...sections]
.sort((a, b) => {
const aOrder = orderMap[a.id];
const bOrder = orderMap[b.id];
// 注意:0 需要保留(不能用 || 进行兜底)
return (aOrder ?? 999) - (bOrder ?? 999);
})
.sort((a, b) => (orderMap[a.id] ?? 999) - (orderMap[b.id] ?? 999))
.map((section) => ({
...section,
anchorId: `${SECTION_ANCHOR_PREFIX}${section.id}`,
@@ -78,6 +65,7 @@ function sortSectionsByTabs(
}
function navigateByPath(path?: string, fallbackTitle?: string) {
console.log('path-----:', path);
if (!path) {
wx.showToast({
title: fallbackTitle ? `${fallbackTitle} 即将上线` : '即将上线',
@@ -94,31 +82,109 @@ function navigateByPath(path?: string, fallbackTitle?: string) {
wx.navigateTo({ url: path });
}
// ── Skeleton data ──
function skeletonItem(id: string): HomeDisplayItemView {
return {
id,
title: '\u00A0',
subtitle: '\u00A0',
category: 'math' as any,
ageBand: '',
difficulty: '基础',
icon: '',
path: '',
available: false,
skeleton: true,
};
}
const SKELETON_FEATURED = Array.from({ length: 3 }, (_, i) =>
skeletonItem(`skeleton-featured-${i}`),
);
const SKELETON_HOT = Array.from({ length: 3 }, (_, i) =>
skeletonItem(`skeleton-hot-${i}`),
);
const win = wx.getWindowInfo();
const HOME_DATA = HOME_CURRENT_CAPABILITY_DATA;
const HOME_TABS: HomeTab[] = HOME_DATA.categoryTabs.map((item) => ({
id: item.id,
name: item.name,
}));
const HOME_SECTIONS = sortSectionsByTabs(HOME_TABS, HOME_DATA.sections);
console.log('HOME_DATA', HOME_DATA);
console.log('HOME_SECTIONS', HOME_SECTIONS);
// Page-level mutable state
let _homeData: HomeDisplayDataset | null = null;
function applyHomeData(data: HomeDisplayDataset) {
_homeData = data;
const tabs: HomeTab[] = data.categoryTabs.map((item) => ({
id: item.id,
name: item.name,
}));
const sections = sortSectionsByTabs(tabs, data.sections);
const ageBands: HomeAgeBandView[] = data.ageBands.map((item, idx) => ({
...item,
icon: AGE_BAND_ICONS[idx] || '🌟',
}));
return { tabs, sections, ageBands };
}
Page({
data: {
searchPlaceholder: HOME_DATA.searchPlaceholder,
tabs: HOME_TABS,
searchPlaceholder: '搜索你喜欢的练习册...',
tabs: [] as HomeTab[],
activeTab: 'all',
ageBands: HOME_DATA.ageBands.map((item, idx) => ({
...item,
icon: AGE_BAND_ICONS[idx] || '🌟',
})) as HomeAgeBandView[],
activeAgeBand: HOME_DATA.ageBands[0]?.key || ('3-4' as AgeBandKey),
featuredItems: HOME_DATA.featured.map(toItemView),
hotRecommends: HOME_DATA.hot.map(toItemView),
sections: HOME_SECTIONS,
ageBands: [] as HomeAgeBandView[],
activeAgeBand: '3-4' as AgeBandKey,
featuredItems: SKELETON_FEATURED,
hotRecommends: SKELETON_HOT,
sections: [] as HomeDisplaySectionView[],
loading: true,
},
onLoad() {
void this.initData();
},
async initData() {
wx.showLoading({ title: '加载中', mask: false });
const app = getApp<IAppOption>();
const config = await app.getPageConfig();
let homeData: HomeDisplayDataset;
if (config?.home) {
// Cloud config available — map to HomeDisplayDataset
const raw = config.home as Record<string, any>;
homeData = {
searchPlaceholder:
raw.searchPlaceholder || '搜索你喜欢的练习册...',
categoryTabs: raw.categoryTabs || [],
ageBands: raw.ageBands || [],
featured: (raw.featured || []) as HomeDisplayItem[],
hot: (raw.hot || []) as HomeDisplayItem[],
sections: (raw.sections || []) as HomeDisplaySection[],
};
} else {
homeData = HOME_CURRENT_CAPABILITY_DATA;
}
const { tabs, sections, ageBands } = applyHomeData(homeData);
this.setData({
loading: false,
searchPlaceholder: homeData.searchPlaceholder,
tabs,
ageBands,
activeAgeBand: homeData.ageBands[0]?.key || '3-4',
featuredItems: homeData.featured.map(toItemView),
hotRecommends: homeData.hot.slice(0, 3).map(toItemView),
sections,
});
wx.hideLoading();
},
// ── Tab & Navigation ──
onTabChange(e: WechatMiniprogram.CustomEvent) {
const id = e.detail.id as string | undefined;
if (!id) return;
@@ -126,10 +192,7 @@ Page({
this.setData({ activeTab: id });
if (id === 'all') {
wx.pageScrollTo({
scrollTop: 0,
duration: 400,
});
wx.pageScrollTo({ scrollTop: 0, duration: 400 });
return;
}
+38 -20
View File
@@ -27,14 +27,21 @@
<view
wx:for="{{featuredItems}}"
wx:key="id"
class="home-hero-card"
class="home-hero-card {{item.skeleton ? 'home-hero-card--skeleton' : ''}}"
data-title="{{item.title}}"
data-path="{{item.path}}"
bindtap="onTapFeatured">
<view
class="home-hero-card__top"
style="background-color: {{item.topBg}}">
<text class="home-hero-card__icon">{{item.icon}}</text>
bindtap="{{item.skeleton ? '' : 'onTapFeatured'}}">
<view class="home-hero-card__top">
<image
wx:if="{{!item.skeleton && item.previewImg}}"
class="home-hero-card__cover"
src="{{item.previewImg}}"
mode="aspectFill" />
<text
wx:if="{{!item.skeleton && !item.previewImg}}"
class="home-hero-card__icon"
>{{item.icon}}</text
>
<text
wx:if="{{item.badge}}"
class="home-hero-card__badge"
@@ -46,7 +53,9 @@
<text class="home-hero-card__title"
>{{item.title}}</text
>
<text class="home-hero-card__meta"
<text
wx:if="{{!item.skeleton}}"
class="home-hero-card__meta"
>{{item.ageBand}} · {{item.difficulty}}</text
>
</view>
@@ -98,14 +107,19 @@
<view
wx:for="{{hotRecommends}}"
wx:key="id"
class="home-hot-card"
class="home-hot-card {{item.skeleton ? 'home-hot-card--skeleton' : ''}}"
data-title="{{item.title}}"
data-path="{{item.path}}"
bindtap="onTapHotRecommend">
<view
class="home-hot-card__thumb"
style="background-color: {{item.topBg}}">
<text class="home-hot-card__thumb-emoji"
bindtap="{{item.skeleton ? '' : 'onTapHotRecommend'}}">
<view class="home-hot-card__thumb">
<image
wx:if="{{!item.skeleton && item.previewImg}}"
class="home-hot-card__thumb-img"
src="{{item.previewImg}}"
mode="aspectFill" />
<text
wx:if="{{!item.skeleton && !item.previewImg}}"
class="home-hot-card__thumb-emoji"
>{{item.icon}}</text
>
</view>
@@ -114,7 +128,9 @@
<text class="home-hot-card__desc"
>{{item.subtitle}}</text
>
<view class="home-hot-card__meta">
<view
wx:if="{{!item.skeleton}}"
class="home-hot-card__meta">
<text class="home-hot-card__tag"
>{{item.ageBand}}</text
>
@@ -123,7 +139,11 @@
>
</view>
</view>
<view class="home-hot-card__action"></view>
<view
wx:if="{{!item.skeleton}}"
class="home-hot-card__action"
></view
>
</view>
</view>
</view>
@@ -157,13 +177,11 @@
data-title="{{item.title}}"
data-path="{{item.path}}"
bindtap="onTapTrackCard">
<view
class="home-track-card__top"
style="background-color: {{item.topBg}}">
<view class="home-track-card__top">
<image
wx:if="{{item.img}}"
wx:if="{{item.previewImg}}"
class="home-track-card__cover"
src="{{item.img}}"
src="{{item.previewImg}}"
mode="widthFix" />
<text wx:else class="home-track-card__icon"
>{{item.icon}}</text