feat: 支持游客免登录浏览核心页面
未登录用户可先浏览衣橱、穿搭、运势、分享等内容,登录改为用户主动选择,并在登录页增加协议勾选确认与暂不登录入口。
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { request, redirectToLogin } from '../../utils/request'
|
||||
import { request } from '../../utils/request'
|
||||
import * as auth from '../../utils/auth'
|
||||
import { PagedResult, ClothesItem, QuotaItem } from '../../types/models'
|
||||
import { QuotaType } from '../../utils/config'
|
||||
@@ -7,6 +7,7 @@ import { clothesStatusFlag } from '../../utils/clothes-status'
|
||||
import { resolvePendingClothes } from '../../utils/pending-clothes'
|
||||
import { setTabBarSelected } from '../../utils/tabbar'
|
||||
import { navScroll } from '../../utils/nav'
|
||||
import { GUEST_WARDROBE, GuestClothes, goLogin } from '../../utils/guest'
|
||||
import { logger } from '../../utils/logger'
|
||||
|
||||
// 日志模块名
|
||||
@@ -22,6 +23,12 @@ const CATEGORIES = [
|
||||
{ name: '配饰', value: '配饰' },
|
||||
]
|
||||
|
||||
// 游客态分类筛选:与分类条 value 对齐,「全部」返回完整示例
|
||||
function filterGuestClothes(index: number): GuestClothes[] {
|
||||
const cat = CATEGORIES[index] ? CATEGORIES[index].value : ''
|
||||
return cat ? GUEST_WARDROBE.filter((it) => it.category === cat) : GUEST_WARDROBE
|
||||
}
|
||||
|
||||
Page({
|
||||
data: {
|
||||
categories: CATEGORIES,
|
||||
@@ -45,16 +52,37 @@ Page({
|
||||
{ text: '知道了', value: '' },
|
||||
{ text: '查看衣物', value: 'ok', type: 'main' },
|
||||
],
|
||||
// 游客态(未登录):展示本地示例内容,不发任何需要授权的请求
|
||||
guest: false,
|
||||
guestList: GUEST_WARDROBE,
|
||||
},
|
||||
|
||||
// scroll-view 滚动 → 导航收缩为玻璃小标题
|
||||
onNavScroll: navScroll,
|
||||
|
||||
onLoad() {
|
||||
// 首帧渲染前判定游客态:未登录直接渲染本地示例,避免首帧 setData 冲突
|
||||
if (!auth.isLoggedIn()) {
|
||||
this.setData({ guest: true, loading: false })
|
||||
logger.info(LOG, '未登录进入首页,渲染游客态示例内容')
|
||||
}
|
||||
},
|
||||
|
||||
onShow() {
|
||||
this.syncTabBar()
|
||||
// 未登录直接回登录页(幂等跳转),不再发出必然 401 的请求
|
||||
// 未登录:游客态浏览,零请求,不再强制跳登录(微信审核合规要求:
|
||||
// 用户可先浏览体验功能服务,登录与否由用户自行选择)
|
||||
if (!auth.isLoggedIn()) {
|
||||
redirectToLogin()
|
||||
if (!this.data.guest) this.setData({ guest: true, list: [], loading: false })
|
||||
return
|
||||
}
|
||||
// 登录成功回到首页:清空示例数据,切回真实衣橱
|
||||
if (this.data.guest) {
|
||||
logger.info(LOG, '检测到登录态,从游客态切换为真实衣橱')
|
||||
;(this as any).firstShown = true
|
||||
this.setData({ guest: false, guestList: [], list: [], total: 0, uploadRemain: 0, loading: true })
|
||||
this.resolvePending()
|
||||
this.refresh()
|
||||
return
|
||||
}
|
||||
// 核对「上传后退出小程序」的衣物最终处理结果(pending 为空时零请求)
|
||||
@@ -82,6 +110,11 @@ Page({
|
||||
},
|
||||
|
||||
onRefresh() {
|
||||
// 游客态没有服务端数据可刷新,直接收起下拉动画
|
||||
if (this.data.guest) {
|
||||
this.setData({ refreshing: false })
|
||||
return
|
||||
}
|
||||
this.setData({ refreshing: true })
|
||||
Promise.all([this.fetchList(1), this.fetchQuota()]).finally(() => {
|
||||
this.setData({ refreshing: false })
|
||||
@@ -89,6 +122,7 @@ Page({
|
||||
},
|
||||
|
||||
onReachBottom() {
|
||||
if (this.data.guest) return
|
||||
if (!this.data.hasMore || this.data.loading || this.data.loadingMore) return
|
||||
this.fetchList(this.data.page + 1)
|
||||
},
|
||||
@@ -186,11 +220,27 @@ Page({
|
||||
onCategoryTap(e: WechatMiniprogram.TouchEvent) {
|
||||
const index = Number(e.currentTarget.dataset.index)
|
||||
if (index === this.data.activeCategory) return
|
||||
this.setData({ activeCategory: index, list: [], loading: true })
|
||||
this.setData({ activeCategory: index })
|
||||
// 游客态:本地示例数据即时筛选,提供可操作的浏览体验,不发请求
|
||||
if (this.data.guest) {
|
||||
this.setData({ guestList: filterGuestClothes(index) })
|
||||
return
|
||||
}
|
||||
this.setData({ list: [], loading: true })
|
||||
this.refresh()
|
||||
},
|
||||
|
||||
// 游客态点击示例内容 / 受限入口:统一进入登录页,由用户自行选择是否登录
|
||||
onGuestLogin() {
|
||||
logger.debug(LOG, '游客态点击受限入口,引导登录')
|
||||
goLogin()
|
||||
},
|
||||
|
||||
onClothesTap(e: WechatMiniprogram.CustomEvent) {
|
||||
if (this.data.guest) {
|
||||
this.onGuestLogin()
|
||||
return
|
||||
}
|
||||
const item = e.detail.item as ClothesItem
|
||||
logger.debug(LOG, '点击衣物, uuid=', item && item.clothes_uuid)
|
||||
wx.navigateTo({
|
||||
@@ -200,6 +250,11 @@ Page({
|
||||
},
|
||||
|
||||
onUpload() {
|
||||
// 上传需登录:游客态先引导登录,不直接进入上传页
|
||||
if (!auth.isLoggedIn()) {
|
||||
this.onGuestLogin()
|
||||
return
|
||||
}
|
||||
wx.navigateTo({
|
||||
url: '/pages/upload/upload',
|
||||
fail: (e) => logger.warn(LOG, 'navigateTo 上传页失败, err=', e && e.errMsg),
|
||||
|
||||
@@ -14,7 +14,16 @@
|
||||
<view class="head">
|
||||
<view class="eyebrow">Wardrobe</view>
|
||||
<view class="display">我的衣橱</view>
|
||||
<view class="wd-stat num">共 {{total}} 件 · 上传额度剩余 {{uploadRemain}} 次</view>
|
||||
<view wx:if="{{guest}}" class="wd-stat">浏览模式 · 以下为功能示例,登录后同步你的衣物</view>
|
||||
<view wx:else class="wd-stat num">共 {{total}} 件 · 上传额度剩余 {{uploadRemain}} 次</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>
|
||||
|
||||
<!-- 下划线式极简分类条 -->
|
||||
@@ -33,7 +42,7 @@
|
||||
</view>
|
||||
|
||||
<!-- 骨架屏 -->
|
||||
<view wx:if="{{loading}}" class="wd-grid">
|
||||
<view wx:if="{{!guest && loading}}" class="wd-grid">
|
||||
<view class="wd-skel" wx:for="{{[1, 2, 3, 4, 5, 6]}}" wx:key="*this">
|
||||
<view class="sk sk-img"></view>
|
||||
<view class="sk sk-ln" style="width: 70%;"></view>
|
||||
@@ -43,7 +52,7 @@
|
||||
|
||||
<!-- 空态 -->
|
||||
<empty-state
|
||||
wx:elif="{{!list.length}}"
|
||||
wx:elif="{{!guest && !list.length}}"
|
||||
icon="icon-hanger"
|
||||
title="衣橱还空着"
|
||||
desc="拍照上传第一件衣物,AI 自动抠图并识别属性"
|
||||
@@ -51,6 +60,19 @@
|
||||
bind:action="onUpload"
|
||||
/>
|
||||
|
||||
<!-- 游客态:本地示例衣物网格(可切换分类即时筛选) -->
|
||||
<view wx:elif="{{guest}}" class="wd-grid">
|
||||
<view class="wd-tile" wx:for="{{guestList}}" wx:key="key" bindtap="onGuestLogin">
|
||||
<view class="gd-img">
|
||||
<view class="icon {{item.icon}} gd-ph"></view>
|
||||
<view class="guest-flag">示例</view>
|
||||
</view>
|
||||
<view class="tile-name">{{item.name}}</view>
|
||||
<view class="tile-sub">{{item.category}} · {{item.color}}色</view>
|
||||
</view>
|
||||
<view wx:if="{{!guestList.length}}" class="gd-none">该分类暂无示例内容</view>
|
||||
</view>
|
||||
|
||||
<!-- 衣物网格 -->
|
||||
<view wx:else class="wd-grid">
|
||||
<view class="wd-tile" wx:for="{{list}}" wx:key="clothes_uuid">
|
||||
@@ -63,7 +85,11 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view wx:if="{{list.length && !hasMore}}" class="foot-note">没有更多了</view>
|
||||
<view wx:if="{{!guest && list.length && !hasMore}}" class="foot-note">没有更多了</view>
|
||||
<view wx:if="{{guest}}" class="guest-foot" bindtap="onGuestLogin">
|
||||
<text>登录后上传你的衣物,AI 自动抠图与识别</text>
|
||||
<text class="gf-a">去登录</text>
|
||||
</view>
|
||||
<view class="gap-64"></view>
|
||||
</scroll-view>
|
||||
|
||||
|
||||
@@ -52,3 +52,32 @@
|
||||
.wd-tile:active {
|
||||
transform: scale(.975);
|
||||
}
|
||||
|
||||
/* ===== 游客态:示例衣物瓦片(线稿占位 + 示例角标) ===== */
|
||||
.gd-img {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
aspect-ratio: 1 / 1;
|
||||
background: var(--paper-2);
|
||||
border-radius: var(--r-img);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.gd-img .gd-ph {
|
||||
width: 56%;
|
||||
height: 56%;
|
||||
color: var(--art);
|
||||
}
|
||||
|
||||
/* 分类下无示例时的整行占位 */
|
||||
.gd-none {
|
||||
grid-column: 1 / -1;
|
||||
padding: 72rpx 0;
|
||||
text-align: center;
|
||||
font-size: 24rpx;
|
||||
color: var(--ink-3);
|
||||
letter-spacing: .02em;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user