feat: P1 合盘/星座/问答与测测完整设计包及模拟器取证工具
落地 synastry/star/ask API 与 H5 页面,补齐 cece-frontend-re complete-design 证据文档,并加入 Android 模拟器截图抓取脚本。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,20 +1,98 @@
|
||||
<template>
|
||||
<main class="page">
|
||||
<h1>我的</h1>
|
||||
<p class="sub">个人档案 · 成长报告 · 成长会员</p>
|
||||
<ul class="list">
|
||||
<li><router-link to="/profile">个人档案</router-link></li>
|
||||
<li><router-link to="/portrait">个人画像</router-link></li>
|
||||
<li><router-link to="/relation">关系理解</router-link></li>
|
||||
<li><router-link to="/membership">成长会员</router-link></li>
|
||||
</ul>
|
||||
<main class="yxg-page">
|
||||
<div class="yxg-hero">
|
||||
<PageTitle feature="profile" title="我的" sub="个人档案 · 成长报告 · 成长会员" />
|
||||
</div>
|
||||
|
||||
<div class="yxg-sheet">
|
||||
<p v-if="loading" class="yxg-hint pad">加载中…</p>
|
||||
<p v-else-if="error" class="yxg-err pad">
|
||||
{{ error }}
|
||||
<button type="button" class="yxg-link" @click="load">重试</button>
|
||||
</p>
|
||||
<template v-else>
|
||||
<div class="yxg-card member">
|
||||
<p class="yxg-chip-ico">
|
||||
<span class="yxg-mark icon-purple tiny" aria-hidden="true">⑨</span>
|
||||
<span class="member-text">
|
||||
<strong v-if="membership?.active">成长会员有效 · {{ planLabel }}</strong>
|
||||
<strong v-else>尚未开通成长会员</strong>
|
||||
<span class="yxg-meta">档案 {{ profileCount }} 份</span>
|
||||
</span>
|
||||
</p>
|
||||
<router-link class="yxg-btn" to="/membership">
|
||||
{{ membership?.active ? '查看会员' : '开通成长会员' }}
|
||||
</router-link>
|
||||
</div>
|
||||
<ul class="yxg-list">
|
||||
<li v-for="item in links" :key="item.to">
|
||||
<router-link :to="item.to">
|
||||
<span class="yxg-mark" :class="'icon-' + item.tone" aria-hidden="true">{{ item.icon }}</span>
|
||||
<span class="yxg-body"><strong>{{ item.label }}</strong></span>
|
||||
<span class="chev" aria-hidden="true">›</span>
|
||||
</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
</div>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
import type { MembershipMe } from '@yuxingu/types'
|
||||
import { api } from '../api/client'
|
||||
import PageTitle from '../components/PageTitle.vue'
|
||||
import type { IconTone } from '../lib/featureIcons'
|
||||
|
||||
const links: { to: string; icon: string; label: string; tone: IconTone }[] = [
|
||||
{ to: '/profile', icon: '◍', label: '个人档案', tone: 'mute' },
|
||||
{ to: '/reports', icon: '▣', label: '我的成长报告', tone: 'orange' },
|
||||
{ to: '/', icon: '△', label: '个人画像', tone: 'gold' },
|
||||
{ to: '/star', icon: '✦', label: '星象性格', tone: 'night' },
|
||||
{ to: '/rhythm', icon: '☯', label: '身心节律', tone: 'green' },
|
||||
{ to: '/cards', icon: '◈', label: '意象卡片', tone: 'teal' },
|
||||
{ to: '/relation', icon: '♡', label: '关系理解', tone: 'rose' },
|
||||
{ to: '/ask', icon: '◎', label: 'AI 成长助手', tone: 'gold' },
|
||||
{ to: '/explore', icon: '◆', label: '探索测试', tone: 'blue' },
|
||||
{ to: '/membership', icon: '⑨', label: '成长会员', tone: 'purple' },
|
||||
]
|
||||
|
||||
const loading = ref(true)
|
||||
const error = ref('')
|
||||
const membership = ref<MembershipMe | null>(null)
|
||||
const profileCount = ref(0)
|
||||
|
||||
const planLabel = computed(() => {
|
||||
const p = membership.value?.plan
|
||||
if (p === 'quarter') return '季卡'
|
||||
if (p === 'year') return '年卡'
|
||||
if (p === 'month') return '月卡'
|
||||
return '成长会员'
|
||||
})
|
||||
|
||||
async function load() {
|
||||
loading.value = true
|
||||
error.value = ''
|
||||
try {
|
||||
const [m, profiles] = await Promise.all([api.getMembership(), api.listProfiles()])
|
||||
membership.value = m
|
||||
profileCount.value = (profiles.items || []).length
|
||||
} catch (e) {
|
||||
error.value = e instanceof Error ? e.message : '加载失败'
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(load)
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.page{padding:24px 16px}
|
||||
h1{font-size:22px}
|
||||
.sub{color:var(--yxg-sub);font-size:13px;margin:6px 0 16px}
|
||||
.list{background:#fff;border-radius:16px;padding:8px 16px;line-height:2.2;font-size:14px;color:#555}
|
||||
.list a{color:inherit;text-decoration:none}
|
||||
.pad{padding:8px 16px}
|
||||
.member{display:flex;flex-direction:column;gap:12px;align-items:flex-start}
|
||||
.member-text{display:flex;flex-direction:column;gap:2px}
|
||||
.member-text strong{font-size:15px;color:#222;font-weight:650}
|
||||
.tiny{width:36px!important;height:36px!important;font-size:16px!important;border-radius:12px!important}
|
||||
.yxg-btn{margin-top:2px}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user