From 0737c6165e228344f8915a982989d4fc8eb462ab Mon Sep 17 00:00:00 2001 From: R524809 Date: Thu, 7 May 2026 10:30:39 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E6=94=B6=E8=97=8F=E4=B8=8B=E8=BD=BD?= =?UTF-8?q?=E9=A1=B5=E4=BC=98=E5=8C=96loading=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- miniprogram/pages/category/category.less | 4 +- miniprogram/pages/category/category.wxml | 4 +- miniprogram/pages/favorites/favorites.json | 1 + miniprogram/pages/favorites/favorites.less | 53 +++++++-- miniprogram/pages/favorites/favorites.ts | 132 ++++++++++++++++----- miniprogram/pages/favorites/favorites.wxml | 95 +++++++-------- 6 files changed, 201 insertions(+), 88 deletions(-) diff --git a/miniprogram/pages/category/category.less b/miniprogram/pages/category/category.less index fc786ec..ae952ef 100644 --- a/miniprogram/pages/category/category.less +++ b/miniprogram/pages/category/category.less @@ -225,14 +225,14 @@ display: flex; flex-direction: row; align-items: center; - gap: 16rpx; + gap: 18rpx; } .cat-card__stat { display: flex; flex-direction: row; align-items: center; - gap: 4rpx; + gap: 6rpx; font-size: 20rpx; color: #7c766a; line-height: 20rpx; diff --git a/miniprogram/pages/category/category.wxml b/miniprogram/pages/category/category.wxml index e1abb94..e31fdac 100644 --- a/miniprogram/pages/category/category.wxml +++ b/miniprogram/pages/category/category.wxml @@ -95,14 +95,14 @@ {{item.likes}} {{item.downloads}} diff --git a/miniprogram/pages/favorites/favorites.json b/miniprogram/pages/favorites/favorites.json index 958b6cf..7ef154c 100644 --- a/miniprogram/pages/favorites/favorites.json +++ b/miniprogram/pages/favorites/favorites.json @@ -6,6 +6,7 @@ "backgroundColor": "#FEF6E7", "usingComponents": { "van-icon": "@vant/weapp/icon/index", + "toy-icon": "../../toy/icon/icon", "nav-bar": "../../components3.0/nav-bar/nav-bar" } } diff --git a/miniprogram/pages/favorites/favorites.less b/miniprogram/pages/favorites/favorites.less index d15e4c1..bfc88fc 100644 --- a/miniprogram/pages/favorites/favorites.less +++ b/miniprogram/pages/favorites/favorites.less @@ -87,17 +87,19 @@ flex-direction: row; align-items: center; gap: 32rpx; - padding: 32rpx; + padding: 24rpx 26rpx; background: @bg-header; box-shadow: @shadow; } .fav-card__thumb { - width: 160rpx; - height: 160rpx; + width: 144rpx; + height: 180rpx; border-radius: @radius; flex-shrink: 0; background: @fav-thumb-placeholder; + border: 1rpx solid rgba(50, 46, 37, 0.08); + overflow: hidden; } .fav-card__main { @@ -106,7 +108,9 @@ display: flex; flex-direction: column; align-items: flex-start; - gap: 8rpx; + justify-content: space-between; + align-self: stretch; + padding: 16rpx 0; } .fav-card__title { @@ -137,6 +141,7 @@ } .fav-card__badge { + display: inline-block; margin-top: 4rpx; font-size: 18rpx; font-weight: 600; @@ -281,7 +286,7 @@ flex-direction: row; align-items: center; gap: 32rpx; - padding: 32rpx; + padding: 24rpx 26rpx; background: @bg-header; border-radius: @radius-lg; box-shadow: @shadow; @@ -293,11 +298,13 @@ } .fav-dl-row__thumb { - width: 160rpx; - height: 160rpx; + width: 144rpx; + height: 180rpx; border-radius: @radius; flex-shrink: 0; background: @fav-thumb-placeholder; + border: 1rpx solid rgba(50, 46, 37, 0.08); + overflow: hidden; } .fav-dl-row__thumb--ph { @@ -310,6 +317,12 @@ .fav-dl-row__main { flex: 1; min-width: 0; + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: space-between; + align-self: stretch; + padding: 16rpx 0; } .fav-dl-row__title { @@ -317,7 +330,6 @@ font-weight: 700; color: @text-title; line-height: 1.25; - margin-bottom: 12rpx; } .fav-dl-row__meta { @@ -328,6 +340,7 @@ gap: 12rpx; font-size: 26rpx; color: fade(@text-secondary, 88%); + line-height: 26rpx; } .fav-dl-row__time { @@ -361,6 +374,30 @@ border-radius: 50%; } +/* Loading */ +.fav-loading { + display: flex; + align-items: center; + justify-content: center; + padding: 120rpx 0; +} + +.fav-loading__icon { + font-size: 56rpx; + color: @text-secondary; + animation: fav-spin 0.8s linear infinite; +} + +@keyframes fav-spin { + from { + transform: rotate(0deg); + } + + to { + transform: rotate(360deg); + } +} + /* 空状态 */ .fav-empty { display: flex; diff --git a/miniprogram/pages/favorites/favorites.ts b/miniprogram/pages/favorites/favorites.ts index 6766fbe..ccbef69 100644 --- a/miniprogram/pages/favorites/favorites.ts +++ b/miniprogram/pages/favorites/favorites.ts @@ -3,6 +3,7 @@ import { getFavoriteList, removeFavorite } from '../../utils/favorites'; import { getDownloadLogs } from '../../utils/downloadLogs'; import type { FavoriteRecord } from '../../utils/favorites'; import type { DownloadLogRecord } from '../../utils/downloadLogs'; +import { getCategoryName } from '../../core/data/categories'; const { statusBarHeight } = wx.getWindowInfo(); const NAV_BLOCK_HEIGHT = statusBarHeight + NAV_INNER_PX; @@ -12,7 +13,7 @@ type FavoritesTab = 'favorites' | 'downloads'; type FavoriteItem = { id: string; worksheetId: string; - variant: 'standard'; + path: string; title: string; metaLine: string; stars: number; @@ -22,7 +23,11 @@ type FavoriteItem = { type DownloadRow = { id: string; + worksheetId: string; + path: string; title: string; + metaLine: string; + stars: number; time: string; status: string; statusHighlight: boolean; @@ -36,19 +41,34 @@ type DownloadSection = { items: DownloadRow[]; }; +function buildWorksheetPath(worksheetId: string, category: string): string { + if (category === 'math') { + return `/mathPages/mathDraw/mathDraw?id=${worksheetId}`; + } + if (category === 'puzzle') { + return `/focusPages/focusDraw/focusDraw?id=${worksheetId}`; + } + if (category === 'english') { + return `/englishPages/letterTracing/letterTracing?id=${worksheetId}`; + } + return `/mathPages/mathDraw/mathDraw?id=${worksheetId}`; +} + function mapFavoriteToItem(record: FavoriteRecord): FavoriteItem { const ws = record.worksheet; const title = ws?.title || '未知题型'; const category = ws?.category || ''; + const categoryName = getCategoryName(category); const ageRange = ws ? `${ws.ageMin}-${ws.ageMax}岁` : ''; - const metaLine = [category, ageRange].filter(Boolean).join(' · ') + ' · '; + const metaLine = + [categoryName, ageRange].filter(Boolean).join(' · ') + ' · '; const difficulty = ws?.difficulty || 0; const timeBadge = formatTimeBadge(record.createdAt); return { id: record._id, worksheetId: record.worksheetId, - variant: 'standard', + path: buildWorksheetPath(record.worksheetId, category), title, metaLine, stars: Math.min(difficulty, 3), @@ -60,8 +80,19 @@ function mapFavoriteToItem(record: FavoriteRecord): FavoriteItem { function formatTimeBadge(dateStr: string): string { const date = new Date(dateStr); const now = new Date(); - const diff = now.getTime() - date.getTime(); - const days = Math.floor(diff / (1000 * 60 * 60 * 24)); + + // 按日历天数计算差值 + const todayStart = new Date( + now.getFullYear(), + now.getMonth(), + now.getDate(), + ).getTime(); + const dateStart = new Date( + date.getFullYear(), + date.getMonth(), + date.getDate(), + ).getTime(); + const days = Math.round((todayStart - dateStart) / (1000 * 60 * 60 * 24)); if (days === 0) return '收藏于今天'; if (days === 1) return '收藏于昨天'; @@ -96,11 +127,21 @@ function groupDownloadsByDate(records: DownloadLogRecord[]): DownloadSection[] { } const ws = record.worksheet; + const category = ws?.category || ''; + const categoryName = getCategoryName(category); + const ageRange = ws ? `${ws.ageMin}-${ws.ageMax}岁` : ''; + const metaLine = + [categoryName, ageRange].filter(Boolean).join(' · ') + ' · '; + const difficulty = ws?.difficulty || 0; groups[key].items.push({ id: record._id, + worksheetId: record.worksheetId, + path: buildWorksheetPath(record.worksheetId, category), title: ws?.title || '未知题型', + metaLine, + stars: Math.min(difficulty, 3), time: `${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`, - status: '已保存相册', + status: '已保存到相册', statusHighlight: true, thumb: ws?.previewImg, }); @@ -123,7 +164,8 @@ Page({ activeTab: 'favorites' as FavoritesTab, favoriteList: [] as FavoriteItem[], downloadSections: [] as DownloadSection[], - loading: false, + favLoading: false, + dlLoading: false, }, onLoad() { @@ -139,37 +181,68 @@ Page({ this.setData({ activeTab: tab }); wx.removeStorageSync('favorites_active_tab'); } - this.loadData(); + this.setData({ favoriteList: [], downloadSections: [] }); + this.loadActiveTab(); + }, + + loadActiveTab() { + const tab = this.data.activeTab; + if (tab === 'favorites' && this.data.favoriteList.length === 0) { + this.loadFavorites(); + } else if (tab === 'downloads' && this.data.downloadSections.length === 0) { + this.loadDownloads(); + } }, onTabSwitch(e: WechatMiniprogram.TouchEvent) { const tab = e.currentTarget.dataset.tab as FavoritesTab; if (tab !== 'favorites' && tab !== 'downloads') return; + if (tab === this.data.activeTab) return; this.setData({ activeTab: tab }); - }, - - async loadData() { - this.setData({ loading: true }); - await Promise.all([this.loadFavorites(), this.loadDownloads()]); - this.setData({ loading: false }); + // 只在数据为空时才请求 + if (tab === 'favorites' && this.data.favoriteList.length === 0) { + this.loadFavorites(); + } else if ( + tab === 'downloads' && + this.data.downloadSections.length === 0 + ) { + this.loadDownloads(); + } }, async loadFavorites() { - const records = await getFavoriteList(); - const list = records.map((r) => mapFavoriteToItem(r)); - this.setData({ favoriteList: list }); + this.setData({ favLoading: true }); + try { + const records = await getFavoriteList(); + this.setData({ + favoriteList: records.map((r) => mapFavoriteToItem(r)), + }); + } finally { + this.setData({ favLoading: false }); + } }, async loadDownloads() { - const records = await getDownloadLogs(); - const sections = groupDownloadsByDate(records); - this.setData({ downloadSections: sections }); + this.setData({ dlLoading: true }); + try { + const records = await getDownloadLogs(); + this.setData({ downloadSections: groupDownloadsByDate(records) }); + } finally { + this.setData({ dlLoading: false }); + } }, onDiscoverTap() { wx.switchTab({ url: '/pages/home/home' }); }, + onCardTap(e: WechatMiniprogram.TouchEvent) { + const path = e.currentTarget.dataset.path as string | undefined; + console.log('path:', path); + if (!path) return; + wx.navigateTo({ url: path }); + }, + onSearchTap() { wx.showToast({ title: '搜索功能开发中', icon: 'none' }); }, @@ -183,15 +256,16 @@ Page({ ); if (!item) return; - // 乐观更新 UI - const list = (this.data.favoriteList as FavoriteItem[]).filter( - (i) => i.id !== id, - ); - this.setData({ favoriteList: list }); - wx.showToast({ title: '已取消收藏', icon: 'none' }); - - // 调用云端 - await removeFavorite(item.worksheetId); + try { + await removeFavorite(item.worksheetId); + const list = (this.data.favoriteList as FavoriteItem[]).filter( + (i) => i.id !== id, + ); + this.setData({ favoriteList: list }); + wx.showToast({ title: '已取消收藏', icon: 'success' }); + } catch { + wx.showToast({ title: '操作失败,请重试', icon: 'none' }); + } }, onClearHistory() { diff --git a/miniprogram/pages/favorites/favorites.wxml b/miniprogram/pages/favorites/favorites.wxml index 6a79311..703d6b0 100644 --- a/miniprogram/pages/favorites/favorites.wxml +++ b/miniprogram/pages/favorites/favorites.wxml @@ -25,7 +25,12 @@ - + + + + 🦆 鸭丫还没找到收藏呢 去发现好玩的练习纸吧~ @@ -33,11 +38,12 @@ 去发现 - + + class="fav-card fav-card--row" + data-path="{{item.path}}" + bindtap="onCardTap"> - - - {{item.title}} - {{item.metaLine}} - - # {{tag}} - - - - - - - @@ -134,8 +104,13 @@ + + + - + + class="fav-dl-row {{row.placeholder === 'draw' ? 'fav-dl-row--muted' : ''}}" + data-path="{{row.path}}" + bindtap="onCardTap"> @@ -178,6 +155,30 @@ {{row.title}} + + {{row.metaLine}} + + + + + + - +