加法权限 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>
238 lines
5.8 KiB
Vue
238 lines
5.8 KiB
Vue
<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>
|