Files
yuxingu-Miniprogram-dev/pages/yxg/reports.vue
T
jackyu66gitandCursor b09d82df8d feat: 小程序统一走 Go 后台,咨询与登录切到 /api/v1
去掉协会 WebView 和魔方账密页,微信登录与咨询接口共用同一 token 和拦截器。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-15 00:26:28 +08:00

106 lines
3.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<yxg-page title="成长报告">
<scroll-view class="chips" scroll-x>
<view v-for="f in filters" :key="f.key" class="chip" :class="{ on: filter === f.key }" @click="filter = f.key">
<text>{{ f.label }}</text>
</view>
</scroll-view>
<view class="vip" @click="yxgGo('/membership')">
<text class="vip-t">成长会员</text>
<text class="vip-s">解锁全部深度报告与节气陪伴 </text>
</view>
<text v-if="loading" class="hint">加载中</text>
<text v-else-if="error" class="err" @click="load">{{ error }} · 重试</text>
<view v-else-if="!filtered.length" class="empty">
<text>还没有{{ filter === 'all' ? '' : '该类' }}成长报告</text>
<view class="btn" @click="yxgGo('/explore')"><text>去探索</text></view>
</view>
<view v-else class="list">
<view v-for="r in filtered" :key="r.id" class="row" @click="yxgGo(`/reports/${r.id}`)">
<yxg-tool-icon :name="toolIconFor(r.type)" :size="36" />
<view class="body">
<text class="t">{{ typeLabel(r.type) }}</text>
<text class="d">{{ headlineOf(r) }}</text>
<text class="m">{{ formatDate(r.created_at) }}</text>
</view>
<text class="chev"></text>
</view>
</view>
</yxg-page>
</template>
<script setup>
import YxgPage from '@/components/yxg/yxg-page.vue'
import YxgToolIcon from '@/components/yxg/yxg-tool-icon.vue'
import { yxgApi } from '@/util/yxgApi.js'
import { ensureAccount } from '@/util/yxgAuth.js'
import { formatDate, headlineOf, toolIconFor, typeLabel } from '@/util/yxgCatalog.js'
import { yxgGo } from '@/util/yxgNav.js'
const filters = [
{ key: 'all', label: '全部' },
{ key: 'portrait', label: '解码' },
{ key: 'star', label: '星座' },
{ key: 'rhythm', label: '节律' },
{ key: 'synastry', label: '合盘' },
]
const filter = ref('all')
const items = ref([])
const loading = ref(true)
const error = ref('')
const filtered = computed(() =>
filter.value === 'all' ? items.value : items.value.filter((r) => r.type === filter.value),
)
async function load() {
loading.value = true
error.value = ''
if (!(await ensureAccount('/reports'))) {
loading.value = false
return
}
try {
const res = await yxgApi.listReports()
items.value = res.items || []
} catch (e) {
error.value = e instanceof Error ? e.message : '加载失败'
} finally {
loading.value = false
}
}
onShow(load)
</script>
<style>
page { background-color: #ffd1c7; }
</style>
<style scoped>
.chips { white-space: nowrap; padding: 8px 16px; }
.chip {
display: inline-block; margin-right: 8px; padding: 6px 12px; border-radius: 999px;
background: #fff; font-size: 13px; color: #666;
}
.chip.on { background: #e54d42; color: #fff; }
.vip {
margin: 0 16px 8px; padding: 12px 14px; border-radius: 14px;
background: linear-gradient(145deg, #fff4e0, #ffd98a);
}
.vip-t { display: block; font-weight: 700; color: #8a5a18; }
.vip-s { display: block; font-size: 12px; color: #a07838; margin-top: 2px; }
.list { margin: 0 16px; background: #fff; border-radius: 16px; }
.row { display: flex; align-items: center; gap: 12px; padding: 14px; border-bottom: 1px solid #f5f5f5; }
.row:last-child { border-bottom: none; }
.body { flex: 1; min-width: 0; }
.t { display: block; font-size: 15px; font-weight: 650; color: #222; }
.d { display: block; font-size: 12px; color: #666; margin-top: 2px; }
.m { display: block; font-size: 11px; color: #bbb; margin-top: 2px; }
.chev { color: #ccc; }
.hint, .err, .empty { display: block; padding: 16px; font-size: 13px; color: #999; text-align: center; }
.err { color: #e54d42; }
.btn {
margin: 12px auto 0; width: 140px; height: 40px; border-radius: 999px; background: #e54d42; color: #fff;
display: flex; align-items: center; justify-content: center; font-weight: 700;
}
</style>