feat(ops): ECR-007 行为分析与 ECR-008 内容运营后台
落地埋点 ingest/数据看板、首页宫格 CMS 与测评上下架;含账号引导、问答流式与免责声明去重,以及 review P1 审计同事务修复。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -6,10 +6,11 @@
|
||||
<BrandLogo size="card" class="av-logo" />
|
||||
</span>
|
||||
<div class="who">
|
||||
<p class="name">愈心谷用户</p>
|
||||
<p class="name">{{ accountLabel }}</p>
|
||||
<p class="meta">档案 {{ profileCount }} 份</p>
|
||||
</div>
|
||||
<router-link class="edit" to="/profile">编辑 ›</router-link>
|
||||
<router-link v-if="!loggedIn" class="edit" to="/login">登录 ›</router-link>
|
||||
<button v-else type="button" class="edit linkish" @click="logout">退出</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -70,12 +71,16 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
import type { MembershipMe } from '@yuxingu/types'
|
||||
import { useRouter } from 'vue-router'
|
||||
import type { AuthUser, MembershipMe } from '@yuxingu/types'
|
||||
import { api } from '../api/client'
|
||||
import BrandLogo from '../components/BrandLogo.vue'
|
||||
import ListRow from '../components/ListRow.vue'
|
||||
import PageShell from '../components/PageShell.vue'
|
||||
import type { HomeToolIconName } from '../components/HomeToolIcon.vue'
|
||||
import { clearAuthToken } from '../lib/authSession'
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
const groupArchive: { to: string; label: string; icon: HomeToolIconName }[] = [
|
||||
{ to: '/profile', label: '个人档案', icon: 'portrait' },
|
||||
@@ -98,6 +103,10 @@ const loading = ref(true)
|
||||
const error = ref('')
|
||||
const membership = ref<MembershipMe | null>(null)
|
||||
const profileCount = ref(0)
|
||||
const me = ref<AuthUser | null>(null)
|
||||
|
||||
const loggedIn = computed(() => !!me.value)
|
||||
const accountLabel = computed(() => me.value?.nickname || me.value?.phone || '未登录')
|
||||
|
||||
const planLabel = computed(() => {
|
||||
const p = membership.value?.plan
|
||||
@@ -111,16 +120,31 @@ async function load() {
|
||||
loading.value = true
|
||||
error.value = ''
|
||||
try {
|
||||
me.value = await api.authMe()
|
||||
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 : '加载失败'
|
||||
me.value = null
|
||||
membership.value = null
|
||||
profileCount.value = 0
|
||||
error.value = e instanceof Error ? e.message : '请先登录'
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function logout() {
|
||||
try {
|
||||
await api.authLogout()
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
clearAuthToken()
|
||||
me.value = null
|
||||
await router.push('/login')
|
||||
}
|
||||
|
||||
onMounted(load)
|
||||
</script>
|
||||
|
||||
@@ -164,6 +188,12 @@ onMounted(load)
|
||||
color: #bbb;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.linkish {
|
||||
border: 0;
|
||||
background: none;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
.assets {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
|
||||
Reference in New Issue
Block a user