Files
digital-psychology/apps/user-h5/src/pages/StarProfilePage.vue
T
jackyu66gitandCursor 77907f79ee feat(ECR-043): StarConfig 写面闭环并 Closed
加法权限 admin.explore.write、POST/PUT+审计、C端 GET /star/configs、
H5 无 active 空态/失败回退;migration 000052。ExploreConfig Loop STOP,禁自动 ECR-044。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-13 20:23:38 +08:00

238 lines
5.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<PageShell>
<template #hero>
<div class="head">
<HomeToolIcon name="star" :size="48" />
<div class="head-text">
<h1 class="title">星座</h1>
<p class="sub">
<button v-if="report" type="button" class="who-link" @click="resetForm">
{{ selfLabel }} · 重新选择
</button>
<template v-else>星象性格 · 本命盘与运势</template>
</p>
</div>
<button v-if="report" type="button" class="share-ico" aria-label="分享" @click="shareOpen = true"></button>
</div>
</template>
<div class="body">
<div v-if="!configAvailable && !report" class="empty-gate">
<HomeToolIcon name="star" :size="56" />
<p class="empty-title">星座配置暂未开放</p>
<p class="empty-sub">运营尚未启用星座配置请稍后再来</p>
<button class="cta-off" type="button" disabled>生成我的星座</button>
</div>
<StarBirthForm
v-else-if="needBirth && !report"
v-model:year="year"
v-model:month="month"
v-model:day="day"
v-model:birth-time="birthTime"
v-model:birth-place="birthPlace"
:loading="loading"
:error="error"
@start="start"
/>
<p v-else-if="loading" class="yxg-hint">正在生成星盘</p>
<p v-else-if="error && !report" class="yxg-err">
{{ error }}
<button type="button" class="yxg-link" @click="load">重试</button>
</p>
<template v-else-if="report">
<StarModeTabs v-model="view" :tabs="starViewTabs" />
<StarOverviewPanel
v-if="view === 'overview'"
:headline="headline"
:one-liner="oneLiner"
:chart-note="chartNote"
:keywords="keywords"
:grid-cells="gridCells"
:sign-tab="signTab"
:active-card="activeCard"
@grid-tap="onGridTap"
/>
<StarChartPanel
v-else-if="view === 'chart'"
v-model:show-outer="showOuter"
v-model:tight-orb="tightOrb"
:wheel-planets="wheelPlanets"
:aspect-lines="aspectLines"
:asc-lon="ascLon"
:houses="houses"
:aspect-preview="aspectPreview"
@wheel-select="onWheelSelect"
/>
<StarFortunePanel
v-else-if="view === 'fortune'"
v-model:fortune-key="fortuneKey"
:fortune-keys="starFortuneKeys"
:active-fortune="activeFortune"
/>
<StarPlanetsPanel
v-else
:planets="planets"
@select="onPlanetSelect"
/>
<StarReportFooter
:summary="summary"
:detail="detail"
:deep="!!report.has_deep_access"
:paying="paying"
:report-id="report.id"
@buy-deep="buyDeep"
/>
</template>
<p class="yxg-disc">运势与星盘为自我探索参考请结合现实判断</p>
</div>
<ShareSheet :open="shareOpen" :payload="sharePayload" @close="shareOpen = false" />
</PageShell>
</template>
<script setup lang="ts">
import PageShell from '../components/PageShell.vue'
import HomeToolIcon from '../components/HomeToolIcon.vue'
import ShareSheet from '../components/ShareSheet.vue'
import StarBirthForm from '../components/star/StarBirthForm.vue'
import StarChartPanel from '../components/star/StarChartPanel.vue'
import StarFortunePanel from '../components/star/StarFortunePanel.vue'
import StarModeTabs from '../components/star/StarModeTabs.vue'
import StarOverviewPanel from '../components/star/StarOverviewPanel.vue'
import StarPlanetsPanel from '../components/star/StarPlanetsPanel.vue'
import StarReportFooter from '../components/star/StarReportFooter.vue'
import { starFortuneKeys, starViewTabs, useStarProfilePage } from '../composables/useStarProfilePage'
import { useAccountNickname } from '../lib/accountNickname'
const { selfLabel } = useAccountNickname()
const {
loading,
needBirth,
configAvailable,
error,
report,
paying,
shareOpen,
year,
month,
day,
birthTime,
birthPlace,
view,
signTab,
fortuneKey,
showOuter,
tightOrb,
summary,
detail,
headline,
oneLiner,
keywords,
chartNote,
ascLon,
houses,
activeCard,
activeFortune,
planets,
wheelPlanets,
aspectPreview,
aspectLines,
gridCells,
sharePayload,
onWheelSelect,
onGridTap,
resetForm,
start,
load,
buyDeep,
} = useStarProfilePage()
function onPlanetSelect(key: string) {
signTab.value = key
view.value = 'overview'
}
</script>
<style scoped>
.head {
display: flex;
align-items: center;
gap: 12px;
margin-top: 8px;
padding-bottom: 8px;
}
.head-text {
flex: 1;
min-width: 0;
}
.title {
font-family: var(--font-display);
font-size: 22px;
font-weight: 700;
letter-spacing: 0.06em;
}
.sub {
font-size: 12px;
color: rgba(0, 0, 0, 0.38);
margin-top: 2px;
}
.who-link {
border: none;
background: transparent;
padding: 0;
font-size: 12px;
color: rgba(0, 0, 0, 0.45);
font-weight: 600;
}
.share-ico {
width: 36px;
height: 36px;
border: none;
border-radius: 12px;
background: rgba(255, 255, 255, 0.8);
font-size: 16px;
flex-shrink: 0;
}
.body { padding: 8px 16px 24px; }
.empty-gate {
text-align: center;
padding: 28px 16px 12px;
}
.empty-title {
font-family: var(--font-display);
font-size: 20px;
font-weight: 700;
margin-top: 10px;
letter-spacing: 0.06em;
}
.empty-sub {
font-size: 13px;
color: rgba(0, 0, 0, 0.42);
margin-top: 8px;
line-height: 1.5;
}
.cta-off {
margin-top: 16px;
width: 100%;
max-width: 320px;
padding: 13px;
border: none;
border-radius: 22px;
color: #fff;
font-size: 15px;
font-weight: 600;
background: linear-gradient(135deg, #ff7a6e, var(--color-primary));
opacity: 0.45;
cursor: not-allowed;
}
</style>