feat: 支持游客免登录浏览核心页面

未登录用户可先浏览衣橱、穿搭、运势、分享等内容,登录改为用户主动选择,并在登录页增加协议勾选确认与暂不登录入口。
This commit is contained in:
2026-09-16 21:44:04 +08:00
parent c07a969642
commit 45222317af
47 changed files with 996 additions and 12150 deletions
+57 -3
View File
@@ -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)