引入 cached-image 组件与 image-cache 工具,实现签名 URL 稳定 key 剥离、downloadFile 落盘及 TTL/LRU 清理,替换 11 个页面与 clothes-card 共 22 处网络图片渲染点,减少 CDN 重复流量。
188 lines
8.1 KiB
Plaintext
188 lines
8.1 KiB
Plaintext
<view class="page page-flex">
|
|
<navigation-bar title="穿搭" back="{{false}}" scrolled="{{navScrolled}}" />
|
|
|
|
<scroll-view
|
|
scroll-y
|
|
class="scroll-body pb-float"
|
|
refresher-enabled
|
|
refresher-triggered="{{refreshing}}"
|
|
bindrefresherrefresh="onRefresh"
|
|
bindscrolltolower="onReachBottom"
|
|
bindscroll="onNavScroll"
|
|
>
|
|
<!-- 大标题页头 -->
|
|
<view class="head">
|
|
<view class="eyebrow">Styling</view>
|
|
<view class="display">穿搭</view>
|
|
</view>
|
|
|
|
<!-- 游客态提示条:未登录也可先浏览,登录由用户自行选择 -->
|
|
<view wx:if="{{guest}}" class="guest-bar" bindtap="onGuestLogin">
|
|
<view class="icon icon-lock"></view>
|
|
<text class="gb-t">浏览模式 · 以下为示例穿搭</text>
|
|
<text class="gb-a">登录</text>
|
|
<view class="icon icon-chevron-right"></view>
|
|
</view>
|
|
|
|
<!-- 下划线式文字分段 -->
|
|
<view class="segbar">
|
|
<view class="seg">
|
|
<view class="seg-item {{activeTab === 0 ? 'is-on' : ''}}" data-index="0" bindtap="onTabChange">我的穿搭</view>
|
|
<view class="seg-item {{activeTab === 1 ? 'is-on' : ''}}" data-index="1" bindtap="onTabChange">已收藏</view>
|
|
<view class="seg-item {{activeTab === 2 ? 'is-on' : ''}}" data-index="2" bindtap="onTabChange">社区</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- AI 穿搭入口:AI 生成结果统一在这里保存与管理(待保存 / 已保存) -->
|
|
<view wx:if="{{activeTab === 0}}" class="ai-entry" bindtap="onAiPending">
|
|
<view class="icon icon-sparkles ae-ic"></view>
|
|
<view class="ae-txt">
|
|
<view class="ae-t">AI 穿搭</view>
|
|
<view class="ae-s">AI 生成的搭配在这里保存与管理</view>
|
|
</view>
|
|
<text wx:if="{{!guest && pendingCount > 0}}" class="pill pill--ink">{{pendingCount}} 套待保存</text>
|
|
<view class="icon icon-chevron-right ae-ch"></view>
|
|
</view>
|
|
|
|
<!-- 骨架屏 -->
|
|
<view wx:if="{{!guest && loading}}" class="of-skel">
|
|
<view class="of-skel-item" wx:for="{{[1, 2]}}" wx:key="*this">
|
|
<view class="sk sk-img sk-cover"></view>
|
|
<view class="sk sk-ln" style="width: 44%;"></view>
|
|
<view class="sk sk-ln" style="width: 72%;"></view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 空态 -->
|
|
<empty-state
|
|
wx:elif="{{!guest && !list.length}}"
|
|
icon="icon-shirt"
|
|
title="{{activeTab === 0 ? '还没有穿搭' : activeTab === 1 ? '还没有收藏的穿搭' : '还没有公开的穿搭'}}"
|
|
desc="{{activeTab === 0 ? '从衣橱挑几件,搭一套吧' : activeTab === 1 ? '在社区或 AI 推荐中点亮小星星,喜欢的穿搭会出现在这里' : '把喜欢的穿搭公开到社区,让大家看到你的搭配'}}"
|
|
buttonText="{{activeTab === 0 ? '创建穿搭' : ''}}"
|
|
bind:action="onCreate"
|
|
/>
|
|
|
|
<!-- 游客态:只展示一套本地示例搭配,点击可完整浏览(不要求登录) -->
|
|
<view wx:elif="{{guest}}" class="of-list">
|
|
<view class="of-card" bindtap="onGuestOutfitTap">
|
|
<view class="collage collage--2">
|
|
<view class="cg" wx:for="{{guestOutfit.items}}" wx:key="clothes_uuid">
|
|
<cached-image class="pic" src="{{item.processed_image}}" mode="aspectFit" />
|
|
</view>
|
|
</view>
|
|
<view class="of-trow">
|
|
<text class="of-title">{{guestOutfit.name}}</text>
|
|
<text class="pill pill--line">{{guestOutfit.scene}}</text>
|
|
</view>
|
|
<view class="of-desc">{{guestOutfit.desc}}</view>
|
|
<view class="of-meta">
|
|
<text class="pill">示例</text>
|
|
<text class="of-m">{{guestOutfit.items.length}} 件衣物</text>
|
|
<view class="spacer"></view>
|
|
<view class="of-m">
|
|
<view class="icon icon-chevron-right"></view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 卡片流 -->
|
|
<view wx:else class="of-list">
|
|
<view
|
|
class="of-card"
|
|
wx:for="{{list}}"
|
|
wx:key="outfit_uuid"
|
|
data-uuid="{{item.outfit_uuid}}"
|
|
bindtap="onOutfitTap"
|
|
>
|
|
<!-- 作者行:仅社区分段 -->
|
|
<view class="of-author" wx:if="{{activeTab === 2}}">
|
|
<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>
|
|
<text class="of-aname">{{item.owner_name || '穿搭达人'}}</text>
|
|
<text class="of-atime">{{item._time}}</text>
|
|
</view>
|
|
|
|
<!-- 无缝拼图封面(_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">
|
|
<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>
|
|
<text class="cg-badge num">{{item.items.length}} 件</text>
|
|
</view>
|
|
|
|
<view class="of-trow">
|
|
<text class="of-title">{{item.outfit_name}}</text>
|
|
<text wx:if="{{activeTab !== 2}}" class="pill {{item._status.cls}}">{{item._status.text}}</text>
|
|
</view>
|
|
<view class="of-desc" wx:if="{{item.outfit_desc}}">{{item.outfit_desc}}</view>
|
|
<view class="of-meta">
|
|
<text class="pill pill--line" wx:if="{{item.scene}}">{{item.scene}}</text>
|
|
<text class="of-m">{{item.items.length}} 件衣物</text>
|
|
<view class="spacer"></view>
|
|
<view class="of-m">
|
|
<view class="icon icon-heart"></view>
|
|
<text class="num">{{item._likeCount || 0}}</text>
|
|
</view>
|
|
<view class="of-m" wx:if="{{activeTab === 2}}">
|
|
<view class="icon icon-star"></view>
|
|
<text class="num">{{item._collectCount || 0}}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view wx:if="{{!guest && list.length && !hasMore}}" class="foot-note">没有更多了</view>
|
|
<view wx:if="{{guest}}" class="guest-foot" bindtap="onGuestLogin">
|
|
<text>登录后查看你的专属穿搭与收藏</text>
|
|
<text class="gf-a">去登录</text>
|
|
</view>
|
|
<view class="gap-64"></view>
|
|
</scroll-view>
|
|
|
|
<!-- 悬浮玻璃双按钮条(社区为浏览场景,不展示管理入口) -->
|
|
<view class="float-duo" wx:if="{{activeTab !== 2}}">
|
|
<view class="btn btn--glass" bindtap="onCreate">创建穿搭</view>
|
|
<view class="btn btn--ink" bindtap="onAiRecommend">AI 推荐</view>
|
|
</view>
|
|
|
|
<!-- 游客态示例搭配抽屉:可完整浏览示例单品,登录仅由用户主动选择 -->
|
|
<view wx:if="{{guestSheetVisible}}" class="scrim" bindtap="onGuestSheetClose"></view>
|
|
<view wx:if="{{guestSheetVisible}}" class="sheet-wrap">
|
|
<view class="sheet" catchtap="noop">
|
|
<view class="sheet-grab"></view>
|
|
<view class="sheet-hd">
|
|
<text class="sheet-t">示例搭配</text>
|
|
<text class="sheet-x" bindtap="onGuestSheetClose">关闭</text>
|
|
</view>
|
|
<view class="sheet-body">
|
|
<view class="gd-hd">
|
|
<view class="t-lg">{{guestOutfit.name}}</view>
|
|
<view class="gd-tags">
|
|
<text class="pill pill--line">{{guestOutfit.scene}}</text>
|
|
<text class="pill">示例</text>
|
|
</view>
|
|
</view>
|
|
<view class="gd-desc">{{guestOutfit.desc}}</view>
|
|
<view class="gd-items">
|
|
<view class="gd-item" wx:for="{{guestOutfit.items}}" wx:key="clothes_uuid">
|
|
<view class="gd-item-img">
|
|
<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>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<view class="sheet-foot">
|
|
<view class="btn btn--ghost btn--block" bindtap="onGuestSheetLogin">登录后可创建你的穿搭</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|