Files
digital-psychology/apps/user-h5/src/composables/useHomePage.ts
T
jackyu66gitandCursor 7ab9add5dd
ci / h5 (push) Canceled after 0s
ci / api (push) Canceled after 0s
ci / ess-docs (push) Canceled after 0s
feat(ops): ECR-007 行为分析与 ECR-008 内容运营后台
落地埋点 ingest/数据看板、首页宫格 CMS 与测评上下架;含账号引导、问答流式与免责声明去重,以及 review P1 审计同事务修复。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-07 02:26:16 +08:00

116 lines
3.0 KiB
TypeScript

import { computed, onMounted, reactive, ref, toRefs } from 'vue'
import { useRouter } from 'vue-router'
import { api } from '../api/client'
import { AnalyticsEvent, track } from '../lib/analytics'
import {
homeFeeds,
homeGridRow1,
homeGridRow2,
homeSearchHints,
type HomeTool,
} from '../lib/homeCatalog'
import type { HomeToolIconName } from '../components/HomeToolIcon.vue'
import { useHomeMood } from './useHomeMood'
const ICONS = new Set([
'mbti', 'star', 'portrait', 'rhythm', 'synastry', 'astro',
'companion', 'ask', 'cards', 'reports', 'growth', 'relation',
])
function mapTools(
items: Array<{
row_index: number
sort_order: number
path: string
icon: string
label: string
badge?: string | null
badge_tone?: string | null
}>,
): { row1: HomeTool[]; row2: HomeTool[] } {
const toTool = (it: (typeof items)[0]): HomeTool | null => {
if (!ICONS.has(it.icon)) return null
const t: HomeTool = {
to: it.path,
icon: it.icon as HomeToolIconName,
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: HomeTool[] = []
const row2: HomeTool[] = []
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 }
}
export function useHomePage() {
const router = useRouter()
const profileLabel = ref('自己')
const plusOpen = ref(false)
const mood = useHomeMood()
const grid = reactive({
gridRow1: [...homeGridRow1] as HomeTool[],
gridRow2: [...homeGridRow2] as HomeTool[],
})
onMounted(() => {
void api
.getHomeTools()
.then((res) => {
const mapped = mapTools(res.items || [])
if (mapped.row1.length || mapped.row2.length) {
grid.gridRow1 = mapped.row1
grid.gridRow2 = mapped.row2
}
})
.catch(() => {
/* keep static fallback */
})
})
const searchHint = computed(() => {
const i = new Date().getHours() % homeSearchHints.length
return homeSearchHints[i]
})
function goPlus(kind: 'inviteFill' | 'add' | 'synastry') {
plusOpen.value = false
track(AnalyticsEvent.HomeCtaPortrait, { source: 'home_plus', kind })
if (kind === 'inviteFill') {
router.push({ path: '/profile', query: { inviteFill: '1' } })
return
}
if (kind === 'add') {
router.push({ path: '/profile', query: { add: '1' } })
return
}
router.push({ path: '/synastry', query: { invite: '1' } })
}
function trackGrid(label: string) {
track(AnalyticsEvent.HomeCtaPortrait, { source: 'home_grid', label })
}
return {
router,
profileLabel,
plusOpen,
mood,
searchHint,
...toRefs(grid),
feeds: homeFeeds,
goPlus,
trackGrid,
}
}