每账号仅一条 self(migration 40902);合盘只选 TA;账号昵称可改;首页穿衣/颜色/养生贴士。 Co-authored-by: Cursor <cursoragent@cursor.com>
220 lines
6.3 KiB
TypeScript
220 lines
6.3 KiB
TypeScript
import { computed, onMounted, ref } from 'vue'
|
|
import { useRoute, useRouter } from 'vue-router'
|
|
import type { GrowthReport, Profile } from '@yuxingu/types'
|
|
import {
|
|
asPlanets,
|
|
ascLonFromChart,
|
|
birthLabel,
|
|
buildRelationSharePayload,
|
|
chartBlock,
|
|
chartPlanetsFromSummary,
|
|
chartTip as chartTipFromCharts,
|
|
labelList,
|
|
mainTabs,
|
|
overlayEntriesFrom,
|
|
profileInitial,
|
|
relationTypes,
|
|
resolveActiveChartKey,
|
|
sectionsFromDetail,
|
|
type SynastryMainTab,
|
|
} from '../lib/synastryChart'
|
|
import { ensureAccount } from '../lib/authSession'
|
|
import { createSynastryPageActions } from './synastryPageActions'
|
|
|
|
export type MainTab = SynastryMainTab
|
|
export { relationTypes, mainTabs, birthLabel, profileInitial }
|
|
|
|
export function useSynastryPage() {
|
|
const route = useRoute()
|
|
const router = useRouter()
|
|
|
|
const loading = ref(false)
|
|
const adding = ref(false)
|
|
const paying = ref(false)
|
|
const inviting = ref(false)
|
|
const nearbyLoading = ref(false)
|
|
const error = ref('')
|
|
const nearbyHint = ref('')
|
|
const invitePath = ref('')
|
|
const inviteHighlight = ref(false)
|
|
const profiles = ref<Profile[]>([])
|
|
const nearby = ref<{ profile: Profile; distance_km: number }[]>([])
|
|
const profileA = ref('')
|
|
const profileB = ref('')
|
|
const asOf = ref(new Date().toISOString().slice(0, 10))
|
|
const report = ref<GrowthReport | null>(null)
|
|
const shareOpen = ref(false)
|
|
const ty = ref('')
|
|
const tm = ref('')
|
|
const td = ref('')
|
|
const tName = ref('TA')
|
|
const mainTab = ref<MainTab>('compare')
|
|
const subTab = ref<'natal' | 'prog'>('natal')
|
|
const marksWho = ref<'me' | 'other'>('me')
|
|
const relationType = ref('伴侣')
|
|
const showClassicSelects = ref(false)
|
|
const showQuickAdd = ref(false)
|
|
|
|
const needsSubTab = computed(() => ['composite', 'davison', 'marks'].includes(mainTab.value))
|
|
const pickableProfiles = computed(() =>
|
|
profiles.value.filter((p) => p.relation === 'other' && p.id !== profileA.value),
|
|
)
|
|
const selfProfiles = computed(() => profiles.value.filter((p) => p.relation === 'self'))
|
|
const profileAName = computed(() => {
|
|
const p = profiles.value.find((x) => x.id === profileA.value)
|
|
return p?.display_name || ''
|
|
})
|
|
const selfInitial = computed(() => (profileAName.value || '我').slice(0, 1))
|
|
|
|
const summary = computed(() => (report.value?.summary || {}) as Record<string, unknown>)
|
|
const detail = computed(() => (report.value?.detail || null) as Record<string, unknown> | null)
|
|
const charts = computed(() => (summary.value.charts || {}) as Record<string, unknown>)
|
|
const headline = computed(() => String(summary.value.headline || ''))
|
|
const oneLiner = computed(() => String(summary.value.one_liner || ''))
|
|
const love = computed(() => Number(summary.value.love_index || 0))
|
|
const friend = computed(() => Number(summary.value.friend_index || 0))
|
|
const marriage = computed(() => Number(summary.value.marriage_index || 0))
|
|
const loveNote = computed(() => String(summary.value.love_note || ''))
|
|
const asOfLabel = computed(() => String(summary.value.as_of || asOf.value))
|
|
|
|
const planetsA = computed(() => chartPlanetsFromSummary(summary.value, 'chart_a'))
|
|
const planetsB = computed(() => chartPlanetsFromSummary(summary.value, 'chart_b'))
|
|
const ascA = computed(() => ascLonFromChart(summary.value.chart_a))
|
|
const ascB = computed(() => ascLonFromChart(summary.value.chart_b))
|
|
const aspectPreview = computed(() => labelList(summary.value.aspects_preview))
|
|
|
|
function chartTip(key: string): string {
|
|
return chartTipFromCharts(charts.value, key)
|
|
}
|
|
|
|
const activeChartKey = computed(() =>
|
|
resolveActiveChartKey(mainTab.value, subTab.value, marksWho.value),
|
|
)
|
|
const activePlanets = computed(() => asPlanets(chartBlock(charts.value, activeChartKey.value)?.planets))
|
|
const activeAsc = computed(() => {
|
|
const lon = chartBlock(charts.value, activeChartKey.value)?.asc_lon
|
|
return typeof lon === 'number' ? lon : null
|
|
})
|
|
const activeAspectPreview = computed(() =>
|
|
labelList(chartBlock(charts.value, activeChartKey.value)?.aspects_preview),
|
|
)
|
|
const activeChartTip = computed(() => chartTip(activeChartKey.value))
|
|
const overlayTip = computed(() => String(chartBlock(charts.value, 'overlay')?.tip || ''))
|
|
const overlayEntries = computed(() => overlayEntriesFrom(charts.value))
|
|
const fullAspects = computed(() => labelList(detail.value?.aspects))
|
|
const sections = computed(() => sectionsFromDetail(detail.value))
|
|
const sharePayload = computed(() =>
|
|
buildRelationSharePayload(
|
|
report.value,
|
|
summary.value,
|
|
headline.value,
|
|
love.value,
|
|
friend.value,
|
|
marriage.value,
|
|
),
|
|
)
|
|
|
|
const { loadProfiles, addTemp, generate, createInvite, loadNearby, buyDeep, reset } =
|
|
createSynastryPageActions({
|
|
loading,
|
|
adding,
|
|
paying,
|
|
inviting,
|
|
nearbyLoading,
|
|
error,
|
|
nearbyHint,
|
|
invitePath,
|
|
profiles,
|
|
nearby,
|
|
profileA,
|
|
profileB,
|
|
asOf,
|
|
report,
|
|
ty,
|
|
tm,
|
|
td,
|
|
tName,
|
|
mainTab,
|
|
showQuickAdd,
|
|
})
|
|
|
|
onMounted(async () => {
|
|
if (!(await ensureAccount(router, route.fullPath))) return
|
|
await loadProfiles()
|
|
if (route.query.invite === '1') {
|
|
inviteHighlight.value = true
|
|
if (profileA.value) {
|
|
await createInvite()
|
|
} else {
|
|
error.value = '请先完成自己的档案,再邀请好友合盘'
|
|
}
|
|
void router.replace({ path: '/synastry', query: {} })
|
|
}
|
|
})
|
|
|
|
return {
|
|
loading,
|
|
adding,
|
|
paying,
|
|
inviting,
|
|
nearbyLoading,
|
|
error,
|
|
nearbyHint,
|
|
invitePath,
|
|
inviteHighlight,
|
|
profiles,
|
|
nearby,
|
|
profileA,
|
|
profileB,
|
|
asOf,
|
|
report,
|
|
shareOpen,
|
|
ty,
|
|
tm,
|
|
td,
|
|
tName,
|
|
mainTab,
|
|
subTab,
|
|
marksWho,
|
|
relationType,
|
|
showClassicSelects,
|
|
showQuickAdd,
|
|
needsSubTab,
|
|
pickableProfiles,
|
|
selfProfiles,
|
|
profileAName,
|
|
selfInitial,
|
|
profileInitial,
|
|
headline,
|
|
oneLiner,
|
|
love,
|
|
friend,
|
|
marriage,
|
|
loveNote,
|
|
asOfLabel,
|
|
planetsA,
|
|
planetsB,
|
|
ascA,
|
|
ascB,
|
|
aspectPreview,
|
|
chartTip,
|
|
activePlanets,
|
|
activeAsc,
|
|
activeAspectPreview,
|
|
activeChartTip,
|
|
overlayTip,
|
|
overlayEntries,
|
|
fullAspects,
|
|
sections,
|
|
sharePayload,
|
|
detail,
|
|
birthLabel,
|
|
addTemp,
|
|
generate,
|
|
createInvite,
|
|
loadNearby,
|
|
buyDeep,
|
|
reset,
|
|
}
|
|
}
|