feat(image-cache): 新增图片本地缓存并全站接入

引入 cached-image 组件与 image-cache 工具,实现签名 URL 稳定 key 剥离、downloadFile 落盘及 TTL/LRU 清理,替换 11 个页面与 clothes-card 共 22 处网络图片渲染点,减少 CDN 重复流量。
This commit is contained in:
2026-09-26 19:49:54 +08:00
parent 7cd6c169c2
commit f169777f4a
30 changed files with 754 additions and 25 deletions
@@ -1,6 +1,7 @@
{
"usingComponents": {
"navigation-bar": "/components/navigation-bar/navigation-bar",
"cached-image": "/components/cached-image/cached-image",
"empty-state": "/components/empty-state/empty-state",
"v2-overlay": "/components/v2-overlay/index"
}
+1 -1
View File
@@ -63,7 +63,7 @@
<!-- 无缝拼图封面 -->
<view class="collage {{item._collageCls}}">
<view class="cg" wx:for="{{item._covers}}" wx:for-item="c" wx:key="k">
<image wx:if="{{c.img}}" class="pic" src="{{c.img}}" mode="aspectFill" lazy-load />
<cached-image wx:if="{{c.img}}" class="pic" src="{{c.img}}" mode="aspectFill" lazy-load="{{true}}" />
<view wx:else class="ph icon icon-hanger"></view>
</view>
<view wx:if="{{item._moreCount > 0}}" class="cg-more">+{{item._moreCount}}</view>
@@ -1,6 +1,7 @@
{
"usingComponents": {
"navigation-bar": "/components/navigation-bar/navigation-bar",
"cached-image": "/components/cached-image/cached-image",
"empty-state": "/components/empty-state/empty-state",
"v2-overlay": "/components/v2-overlay/index"
}
@@ -44,7 +44,7 @@ module.exports = { cls: cls }
<view class="ai-cover">
<view class="collage {{cl.cls(clothes.length)}}">
<view class="cg" wx:for="{{clothes}}" wx:key="clothes_uuid" wx:if="{{index < 4}}">
<image wx:if="{{item.processed_image}}" class="pic" src="{{item.processed_image}}" mode="aspectFill" />
<cached-image wx:if="{{item.processed_image}}" class="pic" src="{{item.processed_image}}" mode="aspectFill" />
<view wx:else class="ph icon icon-hanger"></view>
</view>
<view wx:if="{{clothes.length > 4}}" class="cg-more">+{{clothes.length - 4}}</view>
@@ -77,7 +77,7 @@ module.exports = { cls: cls }
<view class="ai-items-row">
<view class="ai-chip" wx:for="{{clothes}}" wx:key="clothes_uuid">
<view class="ai-thumb">
<image wx:if="{{item.processed_image}}" class="pic" src="{{item.processed_image}}" mode="aspectFill" />
<cached-image wx:if="{{item.processed_image}}" class="pic" src="{{item.processed_image}}" mode="aspectFill" />
<view wx:else class="ph icon icon-hanger"></view>
</view>
<text class="ai-chip-n">{{item.name || '未命名'}}</text>
@@ -1,6 +1,7 @@
{
"usingComponents": {
"navigation-bar": "/components/navigation-bar/navigation-bar",
"cached-image": "/components/cached-image/cached-image",
"clothes-card": "/components/clothes-card/clothes-card",
"v2-overlay": "/components/v2-overlay/index"
}
@@ -95,7 +95,7 @@
<view class="csc-preview">
<view class="csc-preview-hd">
<view class="csc-av">
<image wx:if="{{avatar}}" class="pic" src="{{avatar}}" mode="aspectFill" />
<cached-image wx:if="{{avatar}}" class="pic" src="{{avatar}}" mode="aspectFill" />
<view wx:else class="icon icon-user"></view>
</view>
<text class="csc-preview-n">{{nickname}} 向你分享了 {{selectedCount || '全部'}} 件衣物</text>
@@ -1,6 +1,7 @@
{
"usingComponents": {
"navigation-bar": "/components/navigation-bar/navigation-bar",
"cached-image": "/components/cached-image/cached-image",
"empty-state": "/components/empty-state/empty-state",
"v2-overlay": "/components/v2-overlay/index"
}
@@ -28,7 +28,7 @@
<view class="csd-owner">
<view class="csd-av">
<image wx:if="{{detail.owner_avatar}}" class="pic" src="{{detail.owner_avatar}}" mode="aspectFill" />
<cached-image wx:if="{{detail.owner_avatar}}" class="pic" src="{{detail.owner_avatar}}" mode="aspectFill" />
<view wx:else class="icon icon-user"></view>
</view>
<view class="csd-owner-body">
@@ -41,7 +41,7 @@
<view class="csd-grid">
<view class="csd-tile" wx:for="{{detail.clothes}}" wx:key="clothes_uuid">
<view class="tile-img">
<image wx:if="{{item.processed_image}}" class="pic" src="{{item.processed_image}}" mode="aspectFill" lazy-load />
<cached-image wx:if="{{item.processed_image}}" class="pic" src="{{item.processed_image}}" mode="aspectFill" lazy-load="{{true}}" />
<view wx:else class="ph icon icon-hanger"></view>
</view>
<view class="tile-name">{{item.name || '未命名'}}</view>
@@ -1,6 +1,7 @@
{
"usingComponents": {
"navigation-bar": "/components/navigation-bar/navigation-bar",
"cached-image": "/components/cached-image/cached-image",
"empty-state": "/components/empty-state/empty-state"
}
}
@@ -59,13 +59,13 @@
</view>
<!-- 穿搭分享:封面 -->
<view class="cs-thumb is-photo" wx:else>
<image wx:if="{{item.cover}}" class="pic" src="{{item.cover}}" mode="aspectFill" />
<cached-image wx:if="{{item.cover}}" class="pic" src="{{item.cover}}" mode="aspectFill" />
<view wx:else class="ph icon icon-hanger"></view>
</view>
<view class="cs-body">
<view class="cs-owner" wx:if="{{activeTab === 1}}">
<image wx:if="{{item.owner_avatar}}" class="oav" src="{{item.owner_avatar}}" mode="aspectFill" />
<cached-image wx:if="{{item.owner_avatar}}" class="oav" src="{{item.owner_avatar}}" mode="aspectFill" />
<view wx:else class="oav">
<view class="icon icon-user"></view>
</view>
@@ -1,6 +1,7 @@
{
"usingComponents": {
"navigation-bar": "/components/navigation-bar/navigation-bar",
"cached-image": "/components/cached-image/cached-image",
"empty-state": "/components/empty-state/empty-state",
"v2-overlay": "/components/v2-overlay/index"
}
@@ -110,7 +110,7 @@ module.exports = { hex: hex, tags: tags }
<block wx:else>
<!-- 大图:买手店目录式线稿/实拍 -->
<view class="cd-photo">
<image
<cached-image
wx:if="{{detail.processed_image}}"
class="pic"
src="{{detail.processed_image}}"
@@ -1,6 +1,7 @@
{
"usingComponents": {
"navigation-bar": "/components/navigation-bar/navigation-bar",
"cached-image": "/components/cached-image/cached-image",
"empty-state": "/components/empty-state/empty-state",
"v2-overlay": "/components/v2-overlay/index"
}
@@ -57,7 +57,7 @@ module.exports = { cls: cls }
<view class="od-cover">
<view class="collage {{cl.cls(clothes.length)}}">
<view class="cg" wx:for="{{clothes}}" wx:key="clothes_uuid" wx:if="{{index < 4}}">
<image wx:if="{{item.processed_image}}" class="pic" src="{{item.processed_image}}" mode="aspectFill" />
<cached-image wx:if="{{item.processed_image}}" class="pic" src="{{item.processed_image}}" mode="aspectFill" />
<view wx:else class="ph icon icon-hanger"></view>
</view>
<view wx:if="{{clothes.length > 4}}" class="cg-more">+{{clothes.length - 4}}</view>
@@ -100,7 +100,7 @@ module.exports = { cls: cls }
bindtap="onItemTap"
>
<view class="od-thumb">
<image wx:if="{{item.processed_image}}" class="pic" src="{{item.processed_image}}" mode="aspectFill" />
<cached-image wx:if="{{item.processed_image}}" class="pic" src="{{item.processed_image}}" mode="aspectFill" />
<view wx:else class="ph icon icon-hanger"></view>
</view>
<text class="od-chip-n">{{item.name || '未命名'}}</text>
@@ -1,6 +1,7 @@
{
"usingComponents": {
"navigation-bar": "/components/navigation-bar/navigation-bar",
"cached-image": "/components/cached-image/cached-image",
"clothes-card": "/components/clothes-card/clothes-card",
"v2-overlay": "/components/v2-overlay/index"
}
@@ -32,7 +32,7 @@ module.exports = { cls: cls }
bindtap="openSelect"
>
<view class="cg" wx:for="{{selectedItems}}" wx:key="clothes_uuid" wx:if="{{index < 4}}">
<image wx:if="{{item.processed_image}}" class="pic" src="{{item.processed_image}}" mode="aspectFill" />
<cached-image wx:if="{{item.processed_image}}" class="pic" src="{{item.processed_image}}" mode="aspectFill" />
<view wx:else class="ph icon icon-hanger"></view>
</view>
<view wx:if="{{selectedItems.length > 4}}" class="cg-more">+{{selectedItems.length - 4}}</view>
@@ -1,6 +1,7 @@
{
"usingComponents": {
"navigation-bar": "/components/navigation-bar/navigation-bar",
"cached-image": "/components/cached-image/cached-image",
"empty-state": "/components/empty-state/empty-state",
"v2-overlay": "/components/v2-overlay/index"
}
@@ -38,7 +38,7 @@ module.exports = { cls: cls }
<view class="osd-owner">
<view class="osd-av">
<image wx:if="{{detail.owner_avatar}}" class="pic" src="{{detail.owner_avatar}}" mode="aspectFill" />
<cached-image wx:if="{{detail.owner_avatar}}" class="pic" src="{{detail.owner_avatar}}" mode="aspectFill" />
<view wx:else class="icon icon-user"></view>
</view>
<view class="osd-owner-body">
@@ -51,7 +51,7 @@ module.exports = { cls: cls }
<view class="osd-cover">
<view class="collage {{cl.cls(outfit.items.length)}}">
<view class="cg" wx:for="{{outfit.items}}" wx:key="clothes_uuid" wx:if="{{index < 4}}">
<image wx:if="{{item.processed_image}}" class="pic" src="{{item.processed_image}}" mode="aspectFill" />
<cached-image wx:if="{{item.processed_image}}" class="pic" src="{{item.processed_image}}" mode="aspectFill" />
<view wx:else class="ph icon icon-hanger"></view>
</view>
<view wx:if="{{outfit.items.length > 4}}" class="cg-more">+{{outfit.items.length - 4}}</view>
@@ -84,7 +84,7 @@ module.exports = { cls: cls }
bindtap="onItemTap"
>
<view class="osd-thumb">
<image wx:if="{{item.processed_image}}" class="pic" src="{{item.processed_image}}" mode="aspectFill" />
<cached-image wx:if="{{item.processed_image}}" class="pic" src="{{item.processed_image}}" mode="aspectFill" />
<view wx:else class="ph icon icon-hanger"></view>
</view>
</view>
+1
View File
@@ -1,6 +1,7 @@
{
"usingComponents": {
"navigation-bar": "/components/navigation-bar/navigation-bar",
"cached-image": "/components/cached-image/cached-image",
"empty-state": "/components/empty-state/empty-state"
}
}
+4 -4
View File
@@ -68,7 +68,7 @@
<view class="of-card" bindtap="onGuestOutfitTap">
<view class="collage collage--2">
<view class="cg" wx:for="{{guestOutfit.items}}" wx:key="clothes_uuid">
<image class="pic" src="{{item.processed_image}}" mode="aspectFit" />
<cached-image class="pic" src="{{item.processed_image}}" mode="aspectFit" />
</view>
</view>
<view class="of-trow">
@@ -98,7 +98,7 @@
>
<!-- 作者行:仅社区分段 -->
<view class="of-author" wx:if="{{activeTab === 2}}">
<image wx:if="{{item.owner_avatar}}" class="of-av" src="{{item.owner_avatar}}" mode="aspectFill" />
<cached-image wx:if="{{item.owner_avatar}}" class="of-av" src="{{item.owner_avatar}}" mode="aspectFill" />
<view wx:else class="of-av">
<view class="icon icon-user"></view>
</view>
@@ -109,7 +109,7 @@
<!-- 无缝拼图封面(_covers 由 outfitCover 组装,缺失时整体不渲染,避免 1:1 空白方块撑满屏幕) -->
<view wx:if="{{item._covers}}" class="collage {{item._collageCls}}">
<view class="cg" wx:for="{{item._covers}}" wx:for-item="c" wx:key="k">
<image wx:if="{{c.img}}" class="pic" src="{{c.img}}" mode="aspectFill" lazy-load />
<cached-image wx:if="{{c.img}}" class="pic" src="{{c.img}}" mode="aspectFill" lazy-load="{{true}}" />
<view wx:else class="ph icon icon-hanger"></view>
</view>
<view wx:if="{{item._moreCount > 0}}" class="cg-more">+{{item._moreCount}}</view>
@@ -172,7 +172,7 @@
<view class="gd-items">
<view class="gd-item" wx:for="{{guestOutfit.items}}" wx:key="clothes_uuid">
<view class="gd-item-img">
<image class="pic" src="{{item.processed_image}}" mode="aspectFit" />
<cached-image class="pic" src="{{item.processed_image}}" mode="aspectFit" />
</view>
<view class="tile-name">{{item.name}}</view>
<view class="tile-sub">{{item.category_main}}{{item.category_sub ? ' · ' + item.category_sub : ''}}</view>
+2 -1
View File
@@ -1,5 +1,6 @@
{
"usingComponents": {
"navigation-bar": "/components/navigation-bar/navigation-bar"
"navigation-bar": "/components/navigation-bar/navigation-bar",
"cached-image": "/components/cached-image/cached-image"
}
}
+2 -2
View File
@@ -27,7 +27,7 @@
<!-- 资料区:大号头像 + 衬线昵称 + 胶囊标签 -->
<view wx:else class="pf-hero">
<view class="pf-av">
<image wx:if="{{userInfo.avatar}}" class="pf-av-img" src="{{userInfo.avatar}}" mode="aspectFill" />
<cached-image wx:if="{{userInfo.avatar}}" class="pf-av-img" src="{{userInfo.avatar}}" mode="aspectFill" />
<view wx:else class="icon icon-user"></view>
</view>
<view class="pf-info">
@@ -150,7 +150,7 @@
<view class="sheet-body">
<view class="avatar-wrap">
<image wx:if="{{editForm.avatar}}" class="avatar-img" src="{{editForm.avatar}}" mode="aspectFill" />
<cached-image wx:if="{{editForm.avatar}}" class="avatar-img" src="{{editForm.avatar}}" mode="aspectFill" />
<view wx:else class="icon icon-user avatar-placeholder"></view>
<button class="avatar-btn" open-type="chooseAvatar" bindchooseavatar="onChooseAvatar"></button>
</view>