| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361 |
- <template>
- <view class="detail-container">
- <!-- 导航栏 -->
- <view class="nav-bar">
- <text class="nav-back" @click="goBack">‹ 返回</text>
- <text class="nav-title">体检报告详情</text>
- <view class="nav-placeholder"></view>
- </view>
- <!-- 加载状态 -->
- <view class="loading-wrap" v-if="loading">
- <text class="loading-text">加载中...</text>
- </view>
- <template v-else>
- <!-- 报告摘要卡片 -->
- <view class="summary-card">
- <view class="summary-header">
- <text class="summary-icon">🏥</text>
- <text class="summary-title">体检报告</text>
- </view>
- <view class="summary-body">
- <view class="summary-row">
- <text class="summary-label">报告日期</text>
- <text class="summary-value">{{ report.reportDate || '--' }}</text>
- </view>
- <view class="summary-row">
- <text class="summary-label">综合评分</text>
- <text class="summary-score" :class="scoreClass">{{ report.overallScore || '--' }}<text class="score-unit">分</text></text>
- </view>
- <view class="summary-row">
- <text class="summary-label">报告编号</text>
- <text class="summary-value">{{ report.reportNumber || '--' }}</text>
- </view>
- <view class="summary-row">
- <text class="summary-label">备注</text>
- <text class="summary-value">{{ report.remark || '无' }}</text>
- </view>
- </view>
- </view>
- <!-- 指标分类列表 -->
- <view class="indicator-section" v-for="(group, groupName) in groupedIndicators" :key="groupName">
- <view class="group-header">
- <text class="group-icon">{{ getCategoryIcon(groupName) }}</text>
- <text class="group-title">{{ groupName }}</text>
- <text class="group-count">{{ group.length }}项</text>
- </view>
- <view class="indicator-list">
- <view class="indicator-item" v-for="(ind, idx) in group" :key="idx">
- <view class="indicator-left">
- <text class="indicator-name">{{ ind.indicatorName }}</text>
- <text class="indicator-range" v-if="ind.refRange">参考值: {{ ind.refRange }}</text>
- </view>
- <view class="indicator-right">
- <text class="indicator-value" :class="ind.statusClass">{{ ind.indicatorValue }}</text>
- <text class="indicator-unit" v-if="ind.unit">{{ ind.unit }}</text>
- <text class="indicator-status" :class="ind.statusClass">{{ ind.status || '--' }}</text>
- </view>
- </view>
- </view>
- </view>
- <!-- 空状态 -->
- <view class="empty-wrap" v-if="!loading && indicators.length === 0">
- <text class="empty-icon">📋</text>
- <text class="empty-text">暂无指标数据</text>
- </view>
- </template>
- <view class="bottom-spacer"></view>
- <!-- AI 解读入口(已屏蔽)
- <view class="ai-fab" @click="goAIChat" v-if="report && reportId">
- <text class="fab-icon">🤖</text>
- <text class="fab-text">AI 解读报告</text>
- </view> -->
- </view>
- </template>
- <script>
- import { getReportDetail } from '../../utils/api.js'
- export default {
- data() {
- return {
- reportId: null,
- report: {},
- indicators: [],
- loading: false
- }
- },
- computed: {
- groupedIndicators: function() {
- var groups = {}
- var self = this
- self.indicators.forEach(function(ind) {
- var cat = ind.category || '其他指标'
- if (!groups[cat]) {
- groups[cat] = []
- }
- groups[cat].push(ind)
- })
- // 按分类排序,常用分类在前
- var priority = ['血常规', '肝功能', '肾功能', '血脂', '血糖', '尿常规', '便常规',
- '甲状腺功能', '肿瘤标志物', '维生素', '微量元素', '营养状况', '炎症指标',
- '免疫指标', '其他指标']
- var sorted = {}
- priority.forEach(function(p) {
- if (groups[p]) {
- sorted[p] = groups[p]
- delete groups[p]
- }
- })
- // 剩余分类保持原序
- Object.keys(groups).forEach(function(k) {
- sorted[k] = groups[k]
- })
- return sorted
- },
- scoreClass: function() {
- var s = parseInt(this.report.overallScore)
- if (isNaN(s)) return ''
- if (s >= 80) return 'score-good'
- if (s >= 60) return 'score-warn'
- return 'score-bad'
- }
- },
- onLoad: function(options) {
- this.reportId = options.reportId ? parseInt(options.reportId) : null
- this.loadData()
- },
- methods: {
- loadData: function() {
- var self = this
- if (!self.reportId) {
- uni.showToast({ title: '参数错误', icon: 'none' })
- return
- }
- self.loading = true
- getReportDetail(self.reportId).then(function(res) {
- if (res.code === 200 && res.data) {
- var data = res.data
- self.report = data.report || data
- // 指标可能来自 indicators 字段或直接是 report 的一部分
- var list = []
- if (data.indicators) {
- list = data.indicators
- } else if (data.indicatorList) {
- list = data.indicatorList
- }
- // 预计算状态样式类(小程序 :class 不支持方法调用语法)
- list.forEach(function(ind) {
- ind.statusClass = self.getStatusClass(ind)
- })
- self.indicators = list
- } else {
- uni.showToast({ title: res.message || '加载失败', icon: 'none' })
- }
- }).catch(function(e) {
- console.log('获取报告详情失败', e)
- uni.showToast({ title: '加载失败', icon: 'none' })
- }).finally(function() {
- self.loading = false
- })
- },
- getCategoryIcon: function(cat) {
- var icons = {
- '血常规': '🩸',
- '肝功能': '🫁',
- '肾功能': '🫘',
- '血脂': '🫧',
- '血糖': '🍬',
- '尿常规': '💧',
- '便常规': '💩',
- '甲状腺功能': '🦋',
- '肿瘤标志物': '🔬',
- '维生素': '🍊',
- '微量元素': '⚗️',
- '营养状况': '🥗',
- '炎症指标': '🔥',
- '免疫指标': '🛡️',
- }
- return icons[cat] || '📊'
- },
- getStatusClass: function(ind) {
- var status = (ind.status || '').toLowerCase()
- if (status.indexOf('偏高') !== -1 || status.indexOf('高') !== -1 || status.indexOf('过多') !== -1) {
- return 'status-high'
- }
- if (status.indexOf('偏低') !== -1 || status.indexOf('低') !== -1 || status.indexOf('缺乏') !== -1) {
- return 'status-low'
- }
- if (status.indexOf('注意') !== -1 || status.indexOf('风险') !== -1) {
- return 'status-warn'
- }
- if (status.indexOf('正常') !== -1 || status.indexOf('未检出') !== -1) {
- return 'status-normal'
- }
- return ''
- },
- // AI问答功能已屏蔽
- goAIChat: function() {},
- goBack: function() {
- uni.navigateBack()
- }
- }
- }
- </script>
- <style scoped>
- .detail-container {
- min-height: 100vh;
- background: #F5F7FA;
- }
- .nav-bar {
- position: sticky;
- top: 0;
- background: #fff;
- display: flex;
- flex-direction: row;
- align-items: center;
- justify-content: space-between;
- padding: 20rpx 30rpx;
- box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.06);
- z-index: 100;
- }
- .nav-back { font-size: 32rpx; color: #5B9BD5; }
- .nav-title { font-size: 32rpx; font-weight: bold; color: #333; }
- .nav-placeholder { width: 80rpx; }
- .loading-wrap {
- display: flex;
- justify-content: center;
- padding: 80rpx 0;
- }
- .loading-text { font-size: 28rpx; color: #999; }
- /* 摘要卡片 */
- .summary-card {
- background: linear-gradient(135deg, #E3F2FD, #BBDEFB);
- border-radius: 20rpx;
- margin: 20rpx 30rpx;
- padding: 28rpx 24rpx;
- }
- .summary-header {
- display: flex;
- flex-direction: row;
- align-items: center;
- margin-bottom: 20rpx;
- }
- .summary-icon { font-size: 40rpx; margin-right: 12rpx; }
- .summary-title { font-size: 32rpx; font-weight: bold; color: #1565C0; }
- .summary-body { display: flex; flex-direction: column; gap: 14rpx; }
- .summary-row {
- display: flex;
- flex-direction: row;
- align-items: center;
- justify-content: space-between;
- }
- .summary-label { font-size: 26rpx; color: #555; }
- .summary-value { font-size: 26rpx; color: #333; font-weight: 500; }
- .summary-score { font-size: 40rpx; font-weight: bold; }
- .score-unit { font-size: 22rpx; font-weight: normal; }
- .score-good { color: #2E7D32; }
- .score-warn { color: #E65100; }
- .score-bad { color: #C62828; }
- /* 指标分组 */
- .indicator-section {
- margin: 0 30rpx 20rpx;
- }
- .group-header {
- display: flex;
- flex-direction: row;
- align-items: center;
- padding: 16rpx 20rpx;
- background: #fff;
- border-radius: 16rpx 16rpx 0 0;
- border-bottom: 2rpx solid #E2E8F0;
- }
- .group-icon { font-size: 28rpx; margin-right: 8rpx; }
- .group-title { font-size: 28rpx; font-weight: bold; color: #333; flex: 1; }
- .group-count { font-size: 22rpx; color: #999; }
- .indicator-list {
- background: #fff;
- border-radius: 0 0 16rpx 16rpx;
- overflow: hidden;
- }
- .indicator-item {
- display: flex;
- flex-direction: row;
- align-items: center;
- justify-content: space-between;
- padding: 18rpx 20rpx;
- border-bottom: 1rpx solid #F0F0F0;
- }
- .indicator-item:last-child { border-bottom: none; }
- .indicator-left {
- flex: 1;
- display: flex;
- flex-direction: column;
- gap: 4rpx;
- }
- .indicator-name { font-size: 28rpx; color: #333; font-weight: 500; }
- .indicator-range { font-size: 22rpx; color: #999; }
- .indicator-right {
- display: flex;
- flex-direction: column;
- align-items: flex-end;
- gap: 4rpx;
- margin-left: 20rpx;
- min-width: 120rpx;
- }
- .indicator-value { font-size: 32rpx; font-weight: bold; }
- .indicator-unit { font-size: 22rpx; color: #999; }
- .indicator-status { font-size: 20rpx; padding: 2rpx 10rpx; border-radius: 10rpx; }
- /* 状态颜色 */
- .status-high { color: #C62828; }
- .status-low { color: #E65100; }
- .status-warn { color: #F57F17; }
- .status-normal { color: #2E7D32; }
- /* 空状态 */
- .empty-wrap {
- display: flex;
- flex-direction: column;
- align-items: center;
- padding: 100rpx 0;
- }
- .empty-icon { font-size: 80rpx; margin-bottom: 20rpx; }
- .empty-text { font-size: 28rpx; color: #999; }
- .bottom-spacer { height: 60rpx; }
- .ai-fab {
- position: fixed;
- right: 30rpx;
- bottom: 100rpx;
- display: flex;
- flex-direction: row;
- align-items: center;
- background: linear-gradient(135deg, #6366F1, #8B5CF6);
- border-radius: 40rpx;
- padding: 16rpx 28rpx;
- box-shadow: 0 4rpx 16rpx rgba(99, 102, 241, 0.4);
- z-index: 100;
- }
- .ai-fab .fab-icon {
- font-size: 32rpx;
- margin-right: 12rpx;
- }
- .ai-fab .fab-text {
- font-size: 26rpx;
- color: #fff;
- font-weight: 500;
- }
- </style>
|