feat(ops): ECR-007 行为分析与 ECR-008 内容运营后台
ci / h5 (push) Canceled after 0s
ci / api (push) Canceled after 0s
ci / ess-docs (push) Canceled after 0s

落地埋点 ingest/数据看板、首页宫格 CMS 与测评上下架;含账号引导、问答流式与免责声明去重,以及 review P1 审计同事务修复。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
jackyu66git
2026-08-07 02:26:16 +08:00
co-authored by Cursor
parent 7e9023f0a8
commit 7ab9add5dd
132 changed files with 8276 additions and 491 deletions
+34 -4
View File
@@ -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);