feat: 小程序统一走 Go 后台,咨询与登录切到 /api/v1
去掉协会 WebView 和魔方账密页,微信登录与咨询接口共用同一 token 和拦截器。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
<template>
|
||||
<yxg-page :title="typeLabel(report?.type) || '报告详情'">
|
||||
<text v-if="loading" class="hint">加载中…</text>
|
||||
<text v-else-if="error" class="err">{{ error }}</text>
|
||||
<view v-else-if="report" class="card">
|
||||
<yxg-tool-icon :name="toolIconFor(report.type)" :size="40" />
|
||||
<text class="h1">{{ headlineOf(report) }}</text>
|
||||
<text class="meta">{{ formatDate(report.created_at) }}</text>
|
||||
<text v-if="oneLiner" class="lead">{{ oneLiner }}</text>
|
||||
<view v-if="keywords.length" class="tags">
|
||||
<text v-for="k in keywords" :key="k" class="tag">{{ k }}</text>
|
||||
</view>
|
||||
<text v-if="bodyText" class="body">{{ bodyText }}</text>
|
||||
<rich-text v-else-if="html" class="html" :nodes="html" />
|
||||
<view class="btn" @click="yxgGo('/share', { id: report.id })"><text>分享</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 id = ref('')
|
||||
const report = ref(null)
|
||||
const loading = ref(true)
|
||||
const error = ref('')
|
||||
|
||||
const summary = computed(() => report.value?.summary || {})
|
||||
const detail = computed(() => report.value?.detail || {})
|
||||
const oneLiner = computed(() => String(summary.value.one_liner || summary.value.overview || ''))
|
||||
const keywords = computed(() => (Array.isArray(summary.value.keywords) ? summary.value.keywords : []))
|
||||
const bodyText = computed(() => {
|
||||
const d = detail.value || {}
|
||||
return String(d.body_text || d.narrative || d.content || summary.value.body || '')
|
||||
})
|
||||
const html = computed(() => String(detail.value?.html || detail.value?.rich_html || ''))
|
||||
|
||||
async function load() {
|
||||
loading.value = true
|
||||
error.value = ''
|
||||
if (!(await ensureAccount(`/reports/${id.value}`))) {
|
||||
loading.value = false
|
||||
return
|
||||
}
|
||||
try {
|
||||
report.value = await yxgApi.getReport(id.value)
|
||||
} catch (e) {
|
||||
error.value = e instanceof Error ? e.message : '加载失败'
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onLoad((q) => {
|
||||
id.value = q.id || ''
|
||||
load()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
page { background-color: #ffd1c7; }
|
||||
</style>
|
||||
<style scoped>
|
||||
.hint, .err { display: block; padding: 16px; font-size: 13px; color: #999; }
|
||||
.err { color: #e54d42; }
|
||||
.card { margin: 12px 16px; padding: 18px 16px; background: #fff; border-radius: 18px; }
|
||||
.h1 { display: block; margin-top: 10px; font-size: 20px; font-weight: 700; color: #333; }
|
||||
.meta { display: block; margin-top: 4px; font-size: 12px; color: #bbb; }
|
||||
.lead { display: block; margin-top: 12px; font-size: 14px; color: #555; line-height: 1.6; }
|
||||
.tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
|
||||
.tag { padding: 3px 8px; border-radius: 8px; background: #ffe4e4; color: #e54d42; font-size: 11px; }
|
||||
.body { display: block; margin-top: 14px; font-size: 14px; color: #444; line-height: 1.7; white-space: pre-wrap; }
|
||||
.html { margin-top: 14px; }
|
||||
.btn {
|
||||
margin-top: 16px; height: 42px; border-radius: 999px; background: #e54d42; color: #fff;
|
||||
display: flex; align-items: center; justify-content: center; font-weight: 700;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user