feat: 支持游客免登录浏览核心页面
未登录用户可先浏览衣橱、穿搭、运势、分享等内容,登录改为用户主动选择,并在登录页增加协议勾选确认与暂不登录入口。
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
import { HoroscopeData } from '../types/models'
|
||||
import { logger } from './logger'
|
||||
|
||||
// 日志模块名
|
||||
const LOG = 'guest'
|
||||
|
||||
/**
|
||||
* 游客态唯一数据源:未登录浏览时展示的本地示例内容 + 统一登录引导。
|
||||
*
|
||||
* 合规背景(微信审核驳回整改):
|
||||
* 1. 打开小程序不得直接要求授权登录,用户应能先浏览体验功能服务;
|
||||
* 2. 仅在用户主动点击受限功能时,才由用户自行选择是否登录。
|
||||
*
|
||||
* 本模块不发起任何网络请求、不改动登录态,只提供静态示例数据与登录跳转入口。
|
||||
*/
|
||||
|
||||
// 衣物示例:icon 取 styles/icons.wxss 的线稿图标类名
|
||||
export interface GuestClothes {
|
||||
key: string
|
||||
name: string
|
||||
category: string // 与衣橱分类条 value 对齐
|
||||
color: string
|
||||
icon: string
|
||||
}
|
||||
|
||||
// 穿搭示例:icons 为拼图封面里的线稿占位图标
|
||||
export interface GuestOutfit {
|
||||
key: string
|
||||
name: string
|
||||
scene: string
|
||||
desc: string
|
||||
icons: string[]
|
||||
}
|
||||
|
||||
// 分享示例
|
||||
export interface GuestShare {
|
||||
key: string
|
||||
kind: 'closet' | 'outfit'
|
||||
title: string
|
||||
typeText: string
|
||||
expireText: string
|
||||
}
|
||||
|
||||
export const GUEST_WARDROBE: GuestClothes[] = [
|
||||
{ key: 'g1', name: '白衬衫', category: '上装', color: '白', icon: 'icon-shirt' },
|
||||
{ key: 'g2', name: '直筒牛仔裤', category: '下装', color: '蓝', icon: 'icon-hanger' },
|
||||
{ key: 'g3', name: '针织开衫', category: '外套', color: '灰', icon: 'icon-shirt' },
|
||||
{ key: 'g4', name: '黑色连衣裙', category: '连衣裙', color: '黑', icon: 'icon-hanger' },
|
||||
{ key: 'g5', name: '小白鞋', category: '鞋', color: '白', icon: 'icon-image' },
|
||||
{ key: 'g6', name: '丝巾', category: '配饰', color: '米', icon: 'icon-sparkles' },
|
||||
{ key: 'g7', name: '风衣', category: '外套', color: '卡其', icon: 'icon-shirt' },
|
||||
{ key: 'g8', name: '半身裙', category: '下装', color: '棕', icon: 'icon-hanger' },
|
||||
]
|
||||
|
||||
export const GUEST_OUTFITS: GuestOutfit[] = [
|
||||
{
|
||||
key: 'go1',
|
||||
name: '通勤的干净线条',
|
||||
scene: '通勤',
|
||||
desc: '衬衫配直筒裤,外搭一件风衣',
|
||||
icons: ['icon-shirt', 'icon-hanger', 'icon-image'],
|
||||
},
|
||||
{
|
||||
key: 'go2',
|
||||
name: '周末的松弛感',
|
||||
scene: '周末',
|
||||
desc: '针织开衫配半身裙,鞋选小白鞋',
|
||||
icons: ['icon-shirt', 'icon-hanger'],
|
||||
},
|
||||
{
|
||||
key: 'go3',
|
||||
name: '晚间约会的黑色',
|
||||
scene: '约会',
|
||||
desc: '黑色连衣裙加一条丝巾点亮',
|
||||
icons: ['icon-hanger', 'icon-sparkles'],
|
||||
},
|
||||
]
|
||||
|
||||
export const GUEST_SHARES: GuestShare[] = [
|
||||
{ key: 'gs1', kind: 'closet', title: '衣柜分享 · 12 件', typeText: '全量衣橱', expireText: '示例内容' },
|
||||
{ key: 'gs2', kind: 'outfit', title: '通勤的干净线条', typeText: '穿搭分享 · 3 件', expireText: '示例内容' },
|
||||
]
|
||||
|
||||
// 运势示例:日期取当天,保证页头日期不出现过去时间
|
||||
export function guestHoroscope(): HoroscopeData {
|
||||
const d = new Date()
|
||||
const pad = (n: number) => (n < 10 ? `0${n}` : String(n))
|
||||
return {
|
||||
stat_date: Number(`${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}`),
|
||||
zodiac: '天秤座',
|
||||
overall_score: 4,
|
||||
love_score: 4,
|
||||
career_score: 3,
|
||||
wealth_score: 3,
|
||||
daily_text:
|
||||
'适合整理衣橱的一天:把常穿的几件放在最容易拿到的位置,出门前的犹豫会少很多。新的配色值得记录,晚间适合与朋友聊聊近况。',
|
||||
lucky_color: '蓝色',
|
||||
lucky_number: '7',
|
||||
}
|
||||
}
|
||||
|
||||
// 登录跳转防抖:连续点击多个受限入口时只跳一次
|
||||
let lastNavAt = 0
|
||||
|
||||
/**
|
||||
* 统一登录引导入口(游客态所有受限操作都走这里)。
|
||||
*
|
||||
* 与 utils/request.ts 的 redirectToLogin 的区别:
|
||||
* - redirectToLogin 用于「登录态失效」的被动兜底,reLaunch 清栈;
|
||||
* - goLogin 用于用户主动点击受限功能的场景,navigateTo 保留返回路径,
|
||||
* 用户可随时返回继续浏览,不会被强制清栈。
|
||||
*/
|
||||
export function goLogin(options: { redirect?: string } = {}): void {
|
||||
const pages = typeof getCurrentPages === 'function' ? getCurrentPages() : []
|
||||
const current = pages[pages.length - 1]
|
||||
if (current && current.route === 'pages/login/login') {
|
||||
logger.debug(LOG, '已在登录页,忽略本次登录引导')
|
||||
return
|
||||
}
|
||||
const now = Date.now()
|
||||
if (now - lastNavAt < 800) {
|
||||
logger.debug(LOG, '登录引导防抖,忽略重复点击')
|
||||
return
|
||||
}
|
||||
lastNavAt = now
|
||||
|
||||
const query = options.redirect ? `?redirect=${encodeURIComponent(options.redirect)}` : ''
|
||||
logger.info(LOG, '引导进入登录页, redirect=', options.redirect || '')
|
||||
wx.navigateTo({
|
||||
url: `/pages/login/login${query}`,
|
||||
fail: (e) => {
|
||||
// 页面栈过深或跳转被占用时降级 redirectTo,保证受限操作一定有出口
|
||||
logger.warn(LOG, 'navigateTo 登录页失败,降级 redirectTo, err=', e && e.errMsg)
|
||||
wx.redirectTo({
|
||||
url: `/pages/login/login${query}`,
|
||||
fail: (err) => logger.warn(LOG, 'redirectTo 登录页失败, err=', err && err.errMsg),
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user