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, OutfitItem, CommunityOutfitItem } from '../../types/models'
|
||||
import { OutfitSource, STORAGE_KEYS } from '../../utils/config'
|
||||
@@ -8,6 +8,7 @@ import { OutfitStatusPill, isPendingSave, outfitStatusPill } from '../../utils/o
|
||||
import { setTabBarSelected } from '../../utils/tabbar'
|
||||
import { formatRelativeTime } from '../../utils/format'
|
||||
import { navScroll } from '../../utils/nav'
|
||||
import { GUEST_OUTFITS, goLogin } from '../../utils/guest'
|
||||
import { logger } from '../../utils/logger'
|
||||
|
||||
// 日志模块名
|
||||
@@ -44,16 +45,36 @@ Page({
|
||||
pendingCount: 0,
|
||||
// 滚动收缩:由 utils/nav.ts 的共享 handler 驱动
|
||||
navScrolled: false,
|
||||
// 游客态(未登录):展示本地示例穿搭,不发需要授权的请求
|
||||
guest: false,
|
||||
guestList: GUEST_OUTFITS,
|
||||
},
|
||||
|
||||
// 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: [], loading: true })
|
||||
this.refresh()
|
||||
this.fetchPendingCount()
|
||||
return
|
||||
}
|
||||
const openCollect = wx.getStorageSync(STORAGE_KEYS.OPEN_COLLECT)
|
||||
@@ -86,16 +107,32 @@ Page({
|
||||
onTabChange(e: WechatMiniprogram.TouchEvent) {
|
||||
const index = Number(e.currentTarget.dataset.index)
|
||||
if (index === this.data.activeTab) return
|
||||
// 游客态:分段仍可切换,示例内容用于体验浏览,不发请求
|
||||
if (this.data.guest) {
|
||||
this.setData({ activeTab: index })
|
||||
return
|
||||
}
|
||||
this.setData({ activeTab: index, list: [], loading: true })
|
||||
this.refresh()
|
||||
},
|
||||
|
||||
// 游客态点击示例穿搭 / 受限入口:统一进入登录页,由用户自行选择是否登录
|
||||
onGuestLogin() {
|
||||
logger.debug(LOG, '游客态点击受限入口,引导登录')
|
||||
goLogin()
|
||||
},
|
||||
|
||||
refresh() {
|
||||
this.setData({ page: 1, hasMore: true, loading: this.data.list.length === 0 })
|
||||
this.fetchList(1)
|
||||
},
|
||||
|
||||
onRefresh() {
|
||||
// 游客态没有服务端数据可刷新,直接收起下拉动画
|
||||
if (this.data.guest) {
|
||||
this.setData({ refreshing: false })
|
||||
return
|
||||
}
|
||||
this.setData({ refreshing: true })
|
||||
Promise.all([this.fetchList(1), this.fetchPendingCount()]).finally(() =>
|
||||
this.setData({ refreshing: false })
|
||||
@@ -103,6 +140,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)
|
||||
},
|
||||
@@ -192,6 +230,10 @@ Page({
|
||||
},
|
||||
|
||||
onCreate() {
|
||||
if (this.data.guest) {
|
||||
this.onGuestLogin()
|
||||
return
|
||||
}
|
||||
wx.navigateTo({
|
||||
url: '/pages/outfit-edit/outfit-edit',
|
||||
fail: (e) => logger.warn(LOG, 'navigateTo 新建穿搭失败, err=', e && e.errMsg),
|
||||
@@ -199,6 +241,10 @@ Page({
|
||||
},
|
||||
|
||||
onAiRecommend() {
|
||||
if (this.data.guest) {
|
||||
this.onGuestLogin()
|
||||
return
|
||||
}
|
||||
wx.navigateTo({
|
||||
url: '/pages/ai-recommend/ai-recommend',
|
||||
fail: (e) => logger.warn(LOG, 'navigateTo AI 推荐失败, err=', e && e.errMsg),
|
||||
@@ -207,6 +253,10 @@ Page({
|
||||
|
||||
// 进入 AI 穿搭页:AI 生成结果的统一管理入口(待保存 / 已保存)
|
||||
onAiPending() {
|
||||
if (this.data.guest) {
|
||||
this.onGuestLogin()
|
||||
return
|
||||
}
|
||||
wx.navigateTo({
|
||||
url: '/pages/ai-pending/ai-pending',
|
||||
fail: (e) => logger.warn(LOG, 'navigateTo AI 穿搭失败, err=', e && e.errMsg),
|
||||
@@ -214,6 +264,10 @@ Page({
|
||||
},
|
||||
|
||||
onOutfitTap(e: WechatMiniprogram.TouchEvent) {
|
||||
if (this.data.guest) {
|
||||
this.onGuestLogin()
|
||||
return
|
||||
}
|
||||
const uuid = e.currentTarget.dataset.uuid as string
|
||||
const owner = this.data.activeTab === 0 ? '1' : '0'
|
||||
logger.debug(LOG, '点击穿搭, uuid=', uuid, 'owner=', owner)
|
||||
|
||||
@@ -16,6 +16,14 @@
|
||||
<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">
|
||||
@@ -32,12 +40,12 @@
|
||||
<view class="ae-t">AI 穿搭</view>
|
||||
<view class="ae-s">AI 生成的搭配在这里保存与管理</view>
|
||||
</view>
|
||||
<text wx:if="{{pendingCount > 0}}" class="pill pill--ink">{{pendingCount}} 套待保存</text>
|
||||
<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="{{loading}}" class="of-skel">
|
||||
<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>
|
||||
@@ -47,7 +55,7 @@
|
||||
|
||||
<!-- 空态 -->
|
||||
<empty-state
|
||||
wx:elif="{{!list.length}}"
|
||||
wx:elif="{{!guest && !list.length}}"
|
||||
icon="icon-shirt"
|
||||
title="{{activeTab === 0 ? '还没有穿搭' : activeTab === 1 ? '还没有收藏的穿搭' : '还没有公开的穿搭'}}"
|
||||
desc="{{activeTab === 0 ? '从衣橱挑几件,搭一套吧' : activeTab === 1 ? '在社区或 AI 推荐中点亮小星星,喜欢的穿搭会出现在这里' : '把喜欢的穿搭公开到社区,让大家看到你的搭配'}}"
|
||||
@@ -55,6 +63,31 @@
|
||||
bind:action="onCreate"
|
||||
/>
|
||||
|
||||
<!-- 游客态:本地示例穿搭(点击任一示例进入登录页) -->
|
||||
<view wx:elif="{{guest}}" class="of-list">
|
||||
<view class="of-card" wx:for="{{guestList}}" wx:key="key" bindtap="onGuestLogin">
|
||||
<view class="collage collage--{{item.icons.length}}">
|
||||
<view class="cg" wx:for="{{item.icons}}" wx:for-item="ic" wx:key="*this">
|
||||
<view class="ph icon {{ic}}"></view>
|
||||
</view>
|
||||
<view class="guest-flag">示例</view>
|
||||
</view>
|
||||
<view class="of-trow">
|
||||
<text class="of-title">{{item.name}}</text>
|
||||
<text class="pill pill--line">{{item.scene}}</text>
|
||||
</view>
|
||||
<view class="of-desc">{{item.desc}}</view>
|
||||
<view class="of-meta">
|
||||
<text class="of-m">{{item.icons.length}} 件衣物</text>
|
||||
<view class="spacer"></view>
|
||||
<view class="of-m">
|
||||
<view class="icon icon-heart"></view>
|
||||
<text class="num">-</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 卡片流 -->
|
||||
<view wx:else class="of-list">
|
||||
<view
|
||||
@@ -105,7 +138,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>登录后查看你的专属穿搭与收藏</text>
|
||||
<text class="gf-a">去登录</text>
|
||||
</view>
|
||||
<view class="gap-64"></view>
|
||||
</scroll-view>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user