This commit is contained in:
Felix
2025-12-11 10:53:22 +08:00
parent e5abc263b8
commit 1fa9349e6d
2 changed files with 129 additions and 108 deletions

View File

@@ -34,6 +34,8 @@ Page({
todaySize: 10,
// 添加加载状态
isLoading: true,
isLoadingToday: false,
isLoadingHistory: false,
// 添加文件基础URL
fileBaseUrl: FILE_BASE_URL,
// 添加表情位置状态
@@ -67,6 +69,7 @@ Page({
animateWaterfall: true,
dateStripScrollLeft: 0,
dateStripTransform: '',
isSwitchingDate: false,
},
onLoad() {
@@ -200,7 +203,7 @@ Page({
try {
// 只有在第一页时才显示加载状态(下拉刷新)
if (page === 1) {
this.setData({ isLoading: true });
this.setData({ isLoadingHistory: true });
}
const result = await apiManager.getDailySummary(page, this.data.dailySize);
@@ -302,14 +305,13 @@ Page({
dailyPage: page,
dailyTotal: result.total,
dailyHasMore: page * this.data.dailySize < result.total,
isLoading: false,
isLoadingHistory: false,
}, () => {
this.rebuildDateData();
this.fetchSecureImageUrls();
});
} catch (error) {
console.error('加载每日摘要失败:', error);
this.setData({ isLoading: false });
this.setData({ isLoadingHistory: false });
wx.showToast({
title: '加载失败',
icon: 'none'
@@ -320,7 +322,7 @@ Page({
// 加载今日摘要数据(当天记录,只加载第一页)
async loadTodaySummary(page: number = 1) {
try {
this.setData({ isLoading: true });
this.setData({ isLoadingToday: true });
const result = await apiManager.getTodaySummary(page, this.data.todaySize);
// 处理数据,按时间分组
@@ -351,7 +353,7 @@ Page({
// 设置今日摘要数据
this.setData({
todaySummary: processedItems,
isLoading: false
isLoadingToday: false
}, () => {
this.rebuildDateData();
this.fetchSecureTodayImageUrls();
@@ -361,7 +363,7 @@ Page({
return processedItems;
} catch (error) {
console.error('加载今日摘要失败:', error);
this.setData({ isLoading: false });
this.setData({ isLoadingToday: false });
wx.showToast({
title: '加载今日数据失败',
icon: 'none'
@@ -372,7 +374,7 @@ Page({
// 触底加载更多数据(只加载每日摘要的下一页)
onReachBottom() {
if (this.data.dailyHasMore && !this.data.isLoading) {
if (this.data.dailyHasMore && !this.data.isLoadingHistory) {
const nextPage = this.data.dailyPage + 1;
this.loadDailySummary(nextPage);
}
@@ -394,126 +396,89 @@ Page({
// 获取安全的图片URL
async fetchSecureImageUrls() {
try {
console.log('开始获取安全的图片URL');
// 遍历所有分组的历史记录
const updatedHistory = [...this.data.groupedHistory];
let hasChanges = false;
for (const yearGroup of updatedHistory) {
for (const item of yearGroup.items) {
const tasks: Array<() => Promise<void>> = [];
for (const yg of updatedHistory) {
for (const item of yg.items) {
const d = new Date(item.summary_time);
const dk = `${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,'0')}-${String(d.getDate()).padStart(2,'0')}`;
for (const image of item.images) {
// 如果还没有获取过安全URL且有thumbnail_file_id
if ((!image.thumbnail_url || image.thumbnail_url === '') && image.thumbnail_file_id) {
try {
// 首先检查本地缓存中是否已有该缩略图
const cachedThumbnail = this.getCachedThumbnail(image.thumbnail_file_id);
if (cachedThumbnail) {
image.thumbnail_url = cachedThumbnail;
tasks.push(async () => {
const cached = this.getCachedThumbnail(image.thumbnail_file_id);
if (cached) {
image.thumbnail_url = typeof cached === 'string' ? cached.trim() : cached;
image.thumbnail_loading = false;
hasChanges = true;
// console.log('使用缓存的缩略图:', image.thumbnail_file_id);
continue;
} else {
try {
image.thumbnail_url = (await apiManager.getFileDisplayUrl(image.thumbnail_file_id)).trim();
this.cacheThumbnail(image.thumbnail_file_id, image.thumbnail_url);
image.thumbnail_loading = false;
} catch {
image.thumbnail_url = '/static/sun-2.png';
image.thumbnail_loading = false;
}
}
// 获取安全的缩略图URL
image.thumbnail_url = await apiManager.getFileDisplayUrl(image.thumbnail_file_id);
// 缓存缩略图到本地存储
this.cacheThumbnail(image.thumbnail_file_id, image.thumbnail_url);
image.thumbnail_loading = false; // 设置加载完成状态
hasChanges = true;
} catch (error) {
console.error('获取缩略图URL失败:', error);
// 如果获取失败,使用默认的占位图
image.thumbnail_url = '/static/sun-2.png';
image.thumbnail_loading = false; // 设置加载完成状态
}
// 单张图片加载完成后不逐张触发大范围 setData避免卡顿
});
}
// 如果还没有获取过安全URL且有image_file_id
// if (!image.image_url && image.image_file_id) {
// try {
// // 获取安全的原图URL
// image.image_url = await apiManager.getFileDisplayUrl(image.image_file_id);
// hasChanges = true;
// } catch (error) {
// console.error('获取原图URL失败:', error);
// // 如果获取失败,使用默认的占位图
// image.image_url = '/static/placeholder.png';
// }
// }
}
}
}
// 如果有变化,更新数据
if (hasChanges) {
this.setData({
groupedHistory: updatedHistory
}, () => {
this.rebuildDateData();
await this.runConcurrent(tasks, 5);
if (tasks.length) {
this.setData({ groupedHistory: updatedHistory }, () => {
if (!this.data.isSwitchingDate) {
this.rebuildDateData();
} else {
try { wx.nextTick(() => { setTimeout(() => { if (!this.data.isSwitchingDate) this.rebuildDateData(); }, 200); }); } catch (e) {}
}
});
}
} catch (error) {
console.error('获取安全图片URL失败:', error);
}
} catch {}
},
// 获取安全的今日摘要图片URL
async fetchSecureTodayImageUrls() {
try {
console.log('开始获取今日摘要安全的图片URL');
// 获取今日摘要数据
const todaySummary = [...this.data.todaySummary];
let hasChanges = false;
const tasks: Array<() => Promise<void>> = [];
for (const item of todaySummary) {
const d = new Date(item.summary_time);
const dk = `${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,'0')}-${String(d.getDate()).padStart(2,'0')}`;
for (const image of item.images) {
// 如果还没有获取过安全URL且有thumbnail_file_id
if ((!image.thumbnail_url || image.thumbnail_url === '') && image.thumbnail_file_id) {
try {
// 首先检查本地缓存中是否已有该缩略图
const cachedThumbnail = this.getCachedThumbnail(image.thumbnail_file_id);
if (cachedThumbnail) {
image.thumbnail_url = cachedThumbnail;
tasks.push(async () => {
const cached = this.getCachedThumbnail(image.thumbnail_file_id);
if (cached) {
image.thumbnail_url = typeof cached === 'string' ? cached.trim() : cached;
image.thumbnail_loading = false;
hasChanges = true;
// console.log('使用缓存的缩略图:', image.thumbnail_file_id);
continue;
} else {
try {
image.thumbnail_url = (await apiManager.getFileDisplayUrl(image.thumbnail_file_id)).trim();
this.cacheThumbnail(image.thumbnail_file_id, image.thumbnail_url);
image.thumbnail_loading = false;
} catch {
image.thumbnail_url = '/static/sun-2.png';
image.thumbnail_loading = false;
}
}
// 获取安全的缩略图URL
image.thumbnail_url = await apiManager.getFileDisplayUrl(image.thumbnail_file_id);
// 缓存缩略图到本地存储
this.cacheThumbnail(image.thumbnail_file_id, image.thumbnail_url);
image.thumbnail_loading = false; // 设置加载完成状态
hasChanges = true;
} catch (error) {
console.error('获取缩略图URL失败:', error);
// 如果获取失败,使用默认的占位图
image.thumbnail_url = '/static/sun-2.png';
image.thumbnail_loading = false; // 设置加载完成状态
}
// 单张图片加载完成后不逐张触发大范围 setData避免卡顿
});
}
}
}
// 如果有变化,更新数据
if (hasChanges) {
this.setData({
todaySummary: todaySummary
}, () => {
this.rebuildDateData();
await this.runConcurrent(tasks, 5);
if (tasks.length) {
this.setData({ todaySummary }, () => {
if (!this.data.isSwitchingDate) {
this.rebuildDateData();
} else {
try { wx.nextTick(() => { setTimeout(() => { if (!this.data.isSwitchingDate) this.rebuildDateData(); }, 200); }); } catch (e) {}
}
});
}
} catch (error) {
console.error('获取安全图片URL失败:', error);
}
} catch {}
},
// 缓存缩略图到本地存储
@@ -946,6 +911,7 @@ Page({
} else {
wx.nextTick(() => { this.setData({ animateWaterfall: true }); });
}
this.fetchSecureImagesForDate(selectedKey);
} catch (err) {
console.error('重建日期条失败:', err);
}
@@ -962,7 +928,7 @@ Page({
if (useWaterfall) {
images.forEach((img, idx) => { (idx % 2 === 0 ? waterfallLeft : waterfallRight).push(img); });
}
this.setData({ animateWaterfall: false });
this.setData({ animateWaterfall: false, isSwitchingDate: true });
this.setData({
selectedDateKey: dateKey,
selectedDateImages: images,
@@ -976,14 +942,50 @@ Page({
// 在setData回调中处理瀑布流平衡
if (useWaterfall && images.length > 0) {
this.balanceWaterfall(images).then(() => {
wx.nextTick(() => { this.setData({ animateWaterfall: true }); });
wx.nextTick(() => { this.setData({ animateWaterfall: true, isSwitchingDate: false }); });
});
} else {
wx.nextTick(() => { this.setData({ animateWaterfall: true }); });
wx.nextTick(() => { this.setData({ animateWaterfall: true, isSwitchingDate: false }); });
}
this.fetchSecureImagesForDate(dateKey);
});
},
async fetchSecureImagesForDate(dateKey: string) {
try {
const images = (this.data.imagesByDate || {})[dateKey] || [];
if (!images || images.length === 0) return;
const tasks: Array<() => Promise<void>> = [];
for (const img of images) {
if ((!img.thumbnail_url || img.thumbnail_url === '') && img.thumbnail_file_id) {
tasks.push(async () => {
const cached = this.getCachedThumbnail(img.thumbnail_file_id);
if (cached) {
img.thumbnail_url = typeof cached === 'string' ? cached.trim() : cached;
img.thumbnail_loading = false;
return;
}
try {
img.thumbnail_url = (await apiManager.getFileDisplayUrl(img.thumbnail_file_id)).trim();
this.cacheThumbnail(img.thumbnail_file_id, img.thumbnail_url);
img.thumbnail_loading = false;
} catch {
img.thumbnail_url = '/static/sun-2.png';
img.thumbnail_loading = false;
}
});
}
}
await this.runConcurrent(tasks, 5);
if (dateKey === this.data.selectedDateKey) {
this.setData({ selectedDateImages: [...images] });
if (this.data.useWaterfall) {
this.balanceWaterfall(images);
}
}
} catch (e) {}
},
async ensureThumbSize(img: any): Promise<{ w: number; h: number } | null> {
if (img && typeof img._thumbW === 'number' && typeof img._thumbH === 'number') {
return { w: img._thumbW, h: img._thumbH };
@@ -1070,5 +1072,24 @@ Page({
} catch (e) {}
},
async runConcurrent<T>(fns: Array<() => Promise<T>>, limit: number = 5): Promise<void> {
const total = fns.length;
if (total === 0) return;
const workers = Math.min(limit, total);
let idx = 0;
const runWorker = async () => {
while (idx < total) {
const current = idx++;
const fn = fns[current];
await fn();
}
};
const pool: Promise<void>[] = [];
for (let i = 0; i < workers; i++) {
pool.push(runWorker());
}
await Promise.all(pool);
},
})

View File

@@ -78,14 +78,14 @@
</view>
</scroll-view>
</view>
<view wx:if="{{!isLoading && !takePhoto && selectedDateImages && selectedDateImages.length > 0}}" class="history-wrap">
<view wx:if="{{!takePhoto && selectedDateImages && selectedDateImages.length > 0}}" class="history-wrap">
<view class="history-card-item white-card">
<scroll-view scroll-y>
<block wx:if="{{!useWaterfall}}">
<view class="image-list">
<view class="list-item {{animateWaterfall ? 'fade-in' : ''}}" wx:for="{{selectedDateImages}}" wx:for-item="image" wx:for-index="k" wx:key="image_id" catch:tap="onImageTap" data-image-id="{{image.image_id}}" style="animation-delay: {{k * 0.15}}s;">
<t-skeleton wx:if="{{image.thumbnail_loading}}" class="full-image" row-col="{{[1]}}" animation="gradient" loading></t-skeleton>
<image wx:else class="full-image" src="{{image.thumbnail_url}}" mode="widthFix" />
<image wx:else class="full-image" src="{{image.thumbnail_url}}" mode="widthFix"/>
</view>
</view>
</block>
@@ -100,7 +100,7 @@
<view class="wf-col">
<view class="wf-item {{animateWaterfall ? 'fade-in' : ''}}" wx:for="{{waterfallRight}}" wx:for-index="j" wx:key="image_id" catch:tap="onImageTap" data-image-id="{{item.image_id}}" style="animation-delay: {{j * 0.15 + 0.15}}s;">
<t-skeleton wx:if="{{item.thumbnail_loading}}" class="wf-image" row-col="{{[1]}}" animation="gradient" loading></t-skeleton>
<image wx:else class="wf-image" src="{{item.thumbnail_url}}" mode="widthFix" />
<image wx:else class="wf-image" src="{{item.thumbnail_url}}" mode="widthFix"/>
</view>
</view>
</view>
@@ -108,7 +108,7 @@
</scroll-view>
</view>
</view>
<view wx:if="{{!isLoading && !takePhoto && selectedDateKey === todayKey && (!selectedDateImages || selectedDateImages.length === 0)}}" class="history-wrap">
<view wx:if="{{!isLoadingToday && !takePhoto && selectedDateKey === todayKey && (!selectedDateImages || selectedDateImages.length === 0)}}" class="history-wrap">
<view class="history-card-item blank-card">
<view class="blank-content {{animateWaterfall ? 'visible' : ''}}" bindtap="handleImageSelect">
<view class="photo-inner">