feat: 小程序统一走 Go 后台,咨询与登录切到 /api/v1

去掉协会 WebView 和魔方账密页,微信登录与咨询接口共用同一 token 和拦截器。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
jackyu66git
2026-09-15 00:26:28 +08:00
co-authored by Cursor
parent 6e97f01378
commit b09d82df8d
40 changed files with 3852 additions and 285 deletions
+139
View File
@@ -0,0 +1,139 @@
export const ICON_NAMES = [
'mbti', 'star', 'portrait', 'rhythm', 'synastry', 'astro',
'companion', 'ask', 'cards', 'reports', 'growth', 'relation',
'nine', 'eq', 'stress', 'sleep',
]
export function resolveIcon(raw, fallback = 'mbti') {
return ICON_NAMES.includes(raw) ? raw : fallback
}
export function toolIconFor(pathOrKey) {
const s = String(pathOrKey || '').toLowerCase()
if (s.includes('mbti') || s.includes('人格类型') || s.includes('tests')) return 'mbti'
if (s.includes('synastry') || s.includes('合盘')) return 'synastry'
if (s.includes('portrait') || s.includes('decode') || s.includes('解码')) return 'portrait'
if (s.includes('star') || s.includes('星座') || s.includes('星盘')) return 'star'
if (s.includes('rhythm') || s.includes('节律')) return 'rhythm'
if (s.includes('companion') || s.includes('节气') || s.includes('mood')) return 'companion'
if (s.includes('ask') || s.includes('问答')) return 'ask'
if (s.includes('card') || s.includes('意象')) return 'cards'
if (s.includes('report') || s.includes('报告')) return 'reports'
if (s.includes('growth') || s.includes('计划') || s.includes('会员') || s.includes('member')) return 'growth'
if (s.includes('relation') || s.includes('匹配') || s.includes('love')) return 'relation'
if (s.includes('astro') || s.includes('星象')) return 'astro'
if (s.includes('explore') || s.includes('探索') || s.includes('分类')) return 'mbti'
return 'portrait'
}
export function typeLabel(type) {
const map = {
portrait: '愈心解码',
star: '星座排盘',
rhythm: '身心节律',
synastry: '合盘',
relation: '人格匹配',
scale: '测评',
}
return map[type] || '成长报告'
}
export function formatDate(iso) {
if (!iso) return ''
const d = new Date(iso)
if (Number.isNaN(d.getTime())) return String(iso).slice(0, 10)
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`
}
export function headlineOf(report) {
const s = report?.summary || {}
return s.headline || s.one_liner || s.label || s.title || typeLabel(report?.type)
}
export const homeGridRow1 = [
{ to: '/scales/mbti-lite', icon: 'mbti', label: 'MBTI测试' },
{ to: '/star', icon: 'star', label: '星座' },
{ to: '/portrait', icon: 'portrait', label: '愈心解码', badge: '热', badgeTone: 'hot' },
{ to: '/rhythm', icon: 'rhythm', label: '身心节律' },
{ to: '/synastry', icon: 'synastry', label: '合盘', badge: '新', badgeTone: 'new' },
{ to: '/star', icon: 'astro', label: '星象性格' },
]
export const homeGridRow2 = [
{ to: '/companion', icon: 'companion', label: '节气陪伴' },
{ to: '/ask', icon: 'ask', label: 'AI问答' },
{ to: '/cards', icon: 'cards', label: '意象卡片' },
{ to: '/reports', icon: 'reports', label: '成长报告', badge: '新', badgeTone: 'new' },
{ to: '/growth-plan', icon: 'growth', label: '成长计划' },
{ to: '/relation', icon: 'relation', label: '人格匹配' },
]
export const homeFeeds = [
{ to: '/portrait', icon: 'portrait', title: '愈心解码', meta: '一个生日,读懂性格与身心节奏', stat: '核心入口', tone: 'fc-e', tag: '热' },
{ to: '/ask', icon: 'ask', title: 'AI 成长助手', meta: '结合档案聊聊卡住的事', stat: '随时可问', tone: 'fc-a', tag: 'AI' },
{ to: '/star', icon: 'star', title: '星座排盘', meta: '本命盘 · 相位 · 日周月运势', stat: '本周热门', tone: 'fc-b', tag: '新' },
{ to: '/synastry', icon: 'synastry', title: '合盘', meta: '恋爱 / 友情 / 婚姻指数', stat: '了解彼此', tone: 'fc-c' },
{ to: '/scales/mbti-lite', icon: 'mbti', title: 'MBTI测试', meta: '四维偏好探索,看见自己的能量与决策节奏', stat: '热门测评', tone: 'fc-a' },
{ to: '/membership', icon: 'growth', title: '成长会员', meta: '深度报告与全年节气陪伴', stat: '解锁更多', tone: 'fc-e' },
]
export const mineGroupArchive = [
{ to: '/profile', label: '个人档案', icon: 'portrait' },
{ to: '/reports', label: '我的成长报告', icon: 'reports' },
{ to: '/portrait', label: '愈心解码', icon: 'portrait' },
{ to: '/star', label: '星象性格', icon: 'star' },
{ to: '/rhythm', label: '身心节律', icon: 'rhythm' },
{ to: '/cards', label: '意象卡片', icon: 'cards' },
]
export const mineGroupGrowth = [
{ to: '/relation', label: '人格匹配', icon: 'relation' },
{ to: '/ask', label: 'AI 成长助手', icon: 'ask' },
{ to: '/explore', label: '探索测试', icon: 'mbti' },
{ to: '/growth-plan', label: '成长计划', icon: 'growth' },
{ to: '/membership', label: '成长会员', icon: 'growth' },
]
const FEED_TONES = ['fc-e', 'fc-a', 'fc-b', 'fc-c', 'fc-a', 'fc-e']
export function mapHomeBannersToFeeds(items) {
const sorted = [...(items || [])].sort((a, b) => (a.sort_order ?? 0) - (b.sort_order ?? 0))
const out = []
for (let i = 0; i < sorted.length; i++) {
const it = sorted[i]
const to = String(it.link_path || '').trim()
if (!to.startsWith('/') || to.includes('://')) continue
out.push({
to,
icon: 'portrait',
title: it.title,
meta: '运营推荐',
stat: '推荐',
tone: FEED_TONES[i % FEED_TONES.length],
tag: '荐',
})
}
return out
}
export function mapHomeTools(items) {
const toTool = (it) => {
if (!ICON_NAMES.includes(it.icon)) return null
const t = { to: it.path, icon: it.icon, label: it.label }
if (it.badge) t.badge = it.badge
if (it.badge_tone === 'hot' || it.badge_tone === 'new') t.badgeTone = it.badge_tone
return t
}
const sorted = [...(items || [])].sort(
(a, b) => a.row_index - b.row_index || a.sort_order - b.sort_order,
)
const row1 = []
const row2 = []
for (const it of sorted) {
const t = toTool(it)
if (!t) continue
if (it.row_index === 1) row1.push(t)
else if (it.row_index === 2) row2.push(t)
}
return { row1, row2 }
}