xinli/xinlidsj/pages/comprehensive/detail.vue
2026-02-24 16:49:05 +08:00

175 lines
6.4 KiB
Vue
Raw Permalink 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>
<view class="page" :class="{ big: isH5 }">
<view class="panel">
<view class="title">综合报告详情</view>
<view class="subtitle">reportId{{ reportId || '—' }}</view>
</view>
<view v-if="loading" class="placeholder">加载中...</view>
<view v-else>
<view v-if="errorMsg" class="panel">
<view class="error">{{ errorMsg }}</view>
</view>
<view v-else class="panel">
<view class="kv">
<view class="kv-item"><text class="k">标题</text><text class="v">{{ report.reportTitle || '—' }}</text></view>
<view class="kv-item"><text class="k">创建时间</text><text class="v">{{ formatTime(report.createTime) }}</text></view>
</view>
<view class="section-title">内容</view>
<view class="mode-switch">
<view class="chip" :class="{ active: renderMode === 'html' }" @click="renderMode = 'html'">HTML</view>
<view class="chip" :class="{ active: renderMode === 'text' }" @click="renderMode = 'text'">纯文本</view>
</view>
<view v-if="renderMode === 'html'" class="content">
<rich-text :nodes="htmlNodes"></rich-text>
<view v-if="htmlFallback" class="hint">内容不是标准HTML已自动按纯文本显示。</view>
</view>
<view v-else class="content">
<text selectable user-select>{{ plainText }}</text>
</view>
</view>
</view>
</view>
</template>
<script>
import { getComprehensiveReport } from '../../api/psychology/comprehensiveReport'
function escapeHtml(str) {
return String(str)
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;')
}
export default {
data() {
return {
isH5: false,
loading: false,
errorMsg: '',
reportId: '',
report: {},
renderMode: 'html',
htmlNodes: '',
plainText: '',
htmlFallback: false
}
},
onLoad(options) {
try {
const info = uni.getSystemInfoSync()
const p = info ? (info.uniPlatform || info.platform) : ''
this.isH5 = p === 'web' || p === 'h5'
} catch (e) {
this.isH5 = false
}
this.reportId = options && options.reportId ? options.reportId : ''
if (!this.reportId) {
this.errorMsg = '缺少 reportId'
return
}
this.fetchDetail()
},
methods: {
formatTime(val) {
if (!val) return '—'
try {
const d = new Date(val)
if (isNaN(d.getTime())) return '—'
const y = d.getFullYear()
const m = String(d.getMonth() + 1).padStart(2, '0')
const day = String(d.getDate()).padStart(2, '0')
const hh = String(d.getHours()).padStart(2, '0')
const mm = String(d.getMinutes()).padStart(2, '0')
return `${y}-${m}-${day} ${hh}:${mm}`
} catch (e) {
return '—'
}
},
buildRender(content) {
const raw = content == null ? '' : String(content)
this.plainText = raw
const looksLikeHtml = /<\s*\w+[\s\S]*>/.test(raw)
if (looksLikeHtml) {
this.htmlNodes = raw
this.htmlFallback = false
return
}
this.htmlNodes = `<pre style="white-space:pre-wrap;word-break:break-word;">${escapeHtml(raw)}</pre>`
this.htmlFallback = true
},
fetchDetail() {
this.loading = true
this.errorMsg = ''
return getComprehensiveReport(this.reportId)
.then((res) => {
this.loading = false
const data = res && res.data ? res.data : null
if (!data || data.code !== 200) {
this.errorMsg = (data && data.msg) ? data.msg : '加载失败'
return
}
this.report = data.data || {}
this.buildRender(this.report.reportContent)
})
.catch((e) => {
this.loading = false
this.errorMsg = e && e.message ? e.message : '网络错误'
})
}
}
}
</script>
<style>
.page { min-height: 100vh; padding: 32rpx; box-sizing: border-box; background: #f6f7fb; }
.page.big {
padding: 14rpx 14rpx 120rpx;
background-image:
radial-gradient(1100rpx 520rpx at 50% 14%, rgba(43, 107, 255, 0.30) 0%, rgba(6, 16, 40, 0.0) 65%),
linear-gradient(180deg, rgba(5, 11, 24, 0.90) 0%, rgba(8, 20, 45, 0.85) 42%, rgba(6, 16, 40, 0.92) 100%),
url('/static/bg.png');
background-size: auto, auto, cover;
background-position: center, center, center;
background-repeat: no-repeat, no-repeat, no-repeat;
}
.panel { background: #fff; border-radius: 20rpx; padding: 24rpx; border: 1px solid rgba(0,0,0,0.05); margin-bottom: 24rpx; }
.title { font-size: 36rpx; font-weight: 700; color: #1f2329; }
.subtitle { margin-top: 10rpx; font-size: 24rpx; color: #646a73; line-height: 36rpx; }
.section-title { margin-top: 18rpx; font-size: 28rpx; font-weight: 700; color: #1f2329; }
.kv-item { display: flex; justify-content: space-between; padding: 12rpx 0; border-bottom: 1px solid rgba(0,0,0,0.06); }
.kv-item:last-child { border-bottom: 0; }
.k { color: #8f959e; font-size: 24rpx; }
.v { color: #1f2329; font-size: 24rpx; font-weight: 700; }
.mode-switch { display: flex; margin-top: 14rpx; }
.chip { padding: 10rpx 18rpx; border-radius: 999rpx; font-size: 24rpx; color: #646a73; background: #f7f8fa; margin-right: 14rpx; }
.chip.active { color: #1677ff; background: rgba(22,119,255,0.12); }
.content { margin-top: 14rpx; font-size: 26rpx; color: #1f2329; line-height: 44rpx; }
.placeholder { height: 240rpx; border-radius: 20rpx; background: #fff; border: 1px dashed rgba(0,0,0,0.15); display: flex; align-items: center; justify-content: center; color: #8f959e; font-size: 24rpx; }
.error { font-size: 24rpx; color: #ff4d4f; line-height: 36rpx; }
.hint { margin-top: 10rpx; font-size: 22rpx; color: #8f959e; }
.page.big .panel,
.page.big .placeholder {
border: 1px solid rgba(116, 216, 255, 0.22);
background: linear-gradient(180deg, rgba(10, 18, 38, 0.75) 0%, rgba(5, 10, 22, 0.55) 100%);
box-shadow: 0 12rpx 24rpx rgba(0, 0, 0, 0.35);
}
.page.big .title,
.page.big .section-title,
.page.big .v { color: rgba(235, 248, 255, 0.92); }
.page.big .subtitle,
.page.big .k,
.page.big .hint,
.page.big .placeholder { color: rgba(201, 242, 255, 0.65); }
.page.big .placeholder { border-style: solid; }
.page.big .kv-item { border-bottom-color: rgba(116, 216, 255, 0.12); }
.page.big .chip { color: rgba(201, 242, 255, 0.70); background: rgba(10, 18, 38, 0.65); border: 1px solid rgba(116, 216, 255, 0.20); }
.page.big .chip.active { color: #0b1226; background: linear-gradient(90deg, rgba(116, 216, 255, 0.95) 0%, rgba(43, 107, 255, 0.90) 100%); border-color: rgba(116, 216, 255, 0.5); }
.page.big .content { color: rgba(235, 248, 255, 0.88); }
</style>