feat(ECR-018): Entitlement 用户权益只读并 Closed
聚合 GET /admin/users/:id/entitlements(Membership∪DeepAccess∪问答额度)与 admin-h5 权益 Tab;无 migration / 无真支付。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
<script setup lang="ts">
|
||||
import { RouterLink } from 'vue-router'
|
||||
import { adminApi } from '@/api/client'
|
||||
|
||||
export type Entitlement = Awaited<ReturnType<typeof adminApi.userEntitlements>>
|
||||
|
||||
defineProps<{
|
||||
data: Entitlement
|
||||
}>()
|
||||
|
||||
const typeLabel: Record<string, string> = {
|
||||
portrait: '愈心解码',
|
||||
star: '星座',
|
||||
rhythm: '节律',
|
||||
relation: '关系',
|
||||
synastry: '合盘',
|
||||
image_card: '意象卡',
|
||||
}
|
||||
|
||||
function fmtTime(iso?: string | null) {
|
||||
if (!iso) return '—'
|
||||
try {
|
||||
return new Date(iso).toLocaleString('zh-CN')
|
||||
} catch {
|
||||
return iso
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div class="card block">
|
||||
<h2>权益概览</h2>
|
||||
<div class="kv">
|
||||
<div>
|
||||
<span>报告 detail(会员)</span>
|
||||
<strong>{{ data.flags.report_detail_via_membership ? '是' : '否' }}</strong>
|
||||
</div>
|
||||
<div>
|
||||
<span>DeepAccess 份数</span>
|
||||
<strong>{{ data.flags.deep_access_count }}</strong>
|
||||
</div>
|
||||
<div>
|
||||
<span>已购问答余量</span>
|
||||
<strong>{{ data.ask_paid_quota_left }}</strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card block">
|
||||
<h2>成长会员</h2>
|
||||
<p v-if="data.membership">
|
||||
{{ data.membership.active ? '有效' : '无效' }} ·
|
||||
{{ data.membership.plan || '—' }} ·
|
||||
会员问答 {{ data.membership.ask_quota_left ?? 0 }} ·
|
||||
到期 {{ fmtTime(data.membership.expires_at) }}
|
||||
</p>
|
||||
<p v-else class="muted">无会员记录</p>
|
||||
</div>
|
||||
<div class="card block">
|
||||
<h2>深度版(DeepAccess)</h2>
|
||||
<p v-if="!data.deep_accesses?.length" class="muted">无单份深度版</p>
|
||||
<table v-else>
|
||||
<thead>
|
||||
<tr><th>类型</th><th>报告</th><th>时间</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="d in data.deep_accesses" :key="d.id">
|
||||
<td>{{ typeLabel[d.report_type || ''] || d.report_type || '—' }}</td>
|
||||
<td><code>{{ d.report_id.slice(0, 8) }}…</code></td>
|
||||
<td>{{ fmtTime(d.created_at) }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p class="hint">
|
||||
<RouterLink :to="`/users/${data.user_id}`">返回基础信息可授予会员 / 问答额度</RouterLink>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
h2 { margin: 0 0 0.6rem; font-size: 1.05rem; }
|
||||
.block { margin-bottom: 1rem; }
|
||||
.kv {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
|
||||
gap: 0.75rem;
|
||||
}
|
||||
.kv span { display: block; font-size: 0.75rem; color: var(--muted); margin-bottom: 0.15rem; }
|
||||
.hint { margin-top: 0.75rem; font-size: 0.85rem; }
|
||||
.hint a { color: var(--accent); }
|
||||
</style>
|
||||
Reference in New Issue
Block a user