|
|
@@ -14,30 +14,9 @@
|
|
|
<!-- view mode -->
|
|
|
<view v-if="pageMode==='view'">
|
|
|
<report-blocks-renderer v-if="blocks && blocks.length > 0" :blocks="blocks" />
|
|
|
- <view v-else-if="hasPayloadData" class="payload-fallback">
|
|
|
- <view class="card" v-if="payload.summary && payload.summary.overallScore">
|
|
|
- <view class="card-title">综合评分</view>
|
|
|
- <text class="score-text">{{ payload.summary.overallScore }}</text>
|
|
|
- </view>
|
|
|
- <view class="card" v-if="payload.indicators && payload.indicators.length">
|
|
|
- <view class="card-title">健康指标({{ payload.indicators.length }} 项)</view>
|
|
|
- <view class="indicator-item" v-for="(ind, idx) in payload.indicators" :key="'fallback-' + idx">
|
|
|
- <text class="ind-name">{{ ind.indicatorName || ind.name || '' }}</text>
|
|
|
- <text class="ind-value">{{ ind.indicatorValue || ind.value || '' }}{{ ind.unit || '' }}</text>
|
|
|
- <text class="ind-status" :class="'status-' + _cssClass(ind.status)">{{ statusText(ind.status) }}</text>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
- <view class="card" v-if="payload.diseaseRisks && payload.diseaseRisks.length">
|
|
|
- <view class="card-title">疾病风险</view>
|
|
|
- <view class="risk-item" v-for="(risk, idx) in payload.diseaseRisks" :key="'risk-fb-' + idx">
|
|
|
- <text class="risk-name">{{ risk.diseaseName || '' }}</text>
|
|
|
- <view class="risk-level" :class="'risk-' + (risk.riskLevel || 'low')">{{ riskLevelText(risk.riskLevel) }}</view>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
<view class="empty-hint" v-else>暂无报告内容</view>
|
|
|
<view class="edit-btn" v-if="isGutFlora && pageMode==='view'">
|
|
|
- <view class="nav-edit" @tap="enterEditMode"><text>{{ blocks && blocks.length > 0 ? '编辑' : '查看完整数据 ›' }}</text></view>
|
|
|
+ <view class="nav-edit" @tap="enterEditMode"><text>{{ backendBlocksExist ? '编辑' : '查看完整数据 ›' }}</text></view>
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
@@ -404,6 +383,7 @@ export default {
|
|
|
memberId: null,
|
|
|
familyId: null,
|
|
|
blocks: [],
|
|
|
+ backendBlocksExist: false,
|
|
|
headInfo: null,
|
|
|
pageMode: 'view', // view / draft / edit
|
|
|
parsing: false,
|
|
|
@@ -564,10 +544,21 @@ export default {
|
|
|
head.childName = report.childName || ''
|
|
|
head.reportDateText = report.reportDate ? parseDate(report.reportDate) : ''
|
|
|
self.headInfo = head
|
|
|
- self.blocks = (res.data && res.data.blocks) || report.blocks || []
|
|
|
+ var backendBlocks = (res.data && res.data.blocks) || report.blocks || []
|
|
|
if (res.data.payload) {
|
|
|
self.payload = Object.assign({}, self.defaultPayload(), res.data.payload)
|
|
|
}
|
|
|
+ // 后端无 blocks 时从 payload 自动组装
|
|
|
+ if (backendBlocks.length > 0) {
|
|
|
+ self.blocks = backendBlocks
|
|
|
+ self.backendBlocksExist = true
|
|
|
+ } else if (self.hasPayloadData) {
|
|
|
+ self.blocks = self.assembleBlocksFromPayload()
|
|
|
+ self.backendBlocksExist = false
|
|
|
+ } else {
|
|
|
+ self.blocks = []
|
|
|
+ self.backendBlocksExist = false
|
|
|
+ }
|
|
|
self.needBind = !!report.needBind
|
|
|
self.selectedMemberId = report.subjectId || null
|
|
|
} else {
|
|
|
@@ -871,6 +862,186 @@ export default {
|
|
|
uni.hideLoading()
|
|
|
uni.showToast({ title: '保存异常', icon: 'none' })
|
|
|
})
|
|
|
+ },
|
|
|
+ /** 从 payload 数据自动组装展示块(后端无 blocks 时使用) */
|
|
|
+ assembleBlocksFromPayload: function() {
|
|
|
+ var blocks = []
|
|
|
+ var p = this.payload
|
|
|
+ if (!p) return blocks
|
|
|
+
|
|
|
+ // 1. 评分圆环块
|
|
|
+ var scoreItems = []
|
|
|
+ if (p.summary) {
|
|
|
+ this._addScoreItem(scoreItems, '综合', p.summary.overallScore)
|
|
|
+ this._addScoreItem(scoreItems, '菌群健康', p.summary.gutHealthScore)
|
|
|
+ this._addScoreItem(scoreItems, '慢病控制', p.summary.chronicDiseaseScore)
|
|
|
+ // 子项
|
|
|
+ if (p.summary.nutritionScore != null) { this._addSubScore(scoreItems, '综合', '营养均衡', p.summary.nutritionScore) }
|
|
|
+ if (p.summary.gutBalanceScore != null) { this._addSubScore(scoreItems, '菌群健康', '平衡', p.summary.gutBalanceScore) }
|
|
|
+ if (p.summary.gutDiversityScore != null) { this._addSubScore(scoreItems, '菌群健康', '多样性', p.summary.gutDiversityScore) }
|
|
|
+ if (p.summary.beneficialBacteriaScore != null) { this._addSubScore(scoreItems, '菌群健康', '有益菌', p.summary.beneficialBacteriaScore) }
|
|
|
+ if (p.summary.harmfulBacteriaScore != null) { this._addSubScore(scoreItems, '菌群健康', '有害菌', p.summary.harmfulBacteriaScore) }
|
|
|
+ if (p.summary.coreSpeciesScore != null) { this._addSubScore(scoreItems, '菌群健康', '核心菌属', p.summary.coreSpeciesScore) }
|
|
|
+ // 肠道年龄/肠型
|
|
|
+ if (p.summary.gutAge) { this._addScoreItem(scoreItems, '肠道年龄', p.summary.gutAge) }
|
|
|
+ if (p.summary.gutType) { this._addScoreItem(scoreItems, '肠型', p.summary.gutType) }
|
|
|
+ }
|
|
|
+ if (scoreItems.length > 0) {
|
|
|
+ blocks.push({ type: 'score', title: '健康评分', items: scoreItems })
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 疾病风险分组块
|
|
|
+ var risks = p.diseaseRisks || []
|
|
|
+ if (risks.length > 0) {
|
|
|
+ var important = []
|
|
|
+ var normal = []
|
|
|
+ for (var ri = 0; ri < risks.length; ri++) {
|
|
|
+ var r = risks[ri]
|
|
|
+ var level = r.riskLevel || ''
|
|
|
+ var item = { name: r.diseaseName || '', value: r.riskValue || '', level: level }
|
|
|
+ if (level === '需注意' || level === '注意' || level === '高风险' || level === '异常') {
|
|
|
+ important.push(item)
|
|
|
+ } else {
|
|
|
+ normal.push(item)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (important.length > 0) blocks.push({ type: 'risk_group', title: '重要风险', items: important })
|
|
|
+ if (normal.length > 0) blocks.push({ type: 'risk_group', title: '其它风险', items: normal })
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3. 指标分组块
|
|
|
+ var inds = p.indicators || []
|
|
|
+ if (inds.length > 0) {
|
|
|
+ var byCat = {}
|
|
|
+ for (var ii = 0; ii < inds.length; ii++) {
|
|
|
+ var ind = inds[ii]
|
|
|
+ var cat = ind.category || '其他指标'
|
|
|
+ if (!byCat[cat]) byCat[cat] = []
|
|
|
+ byCat[cat].push({
|
|
|
+ name: ind.indicatorName || ind.name || '',
|
|
|
+ value: ind.indicatorValue || ind.value || '',
|
|
|
+ unit: ind.unit || '',
|
|
|
+ refRange: ind.refRange || '',
|
|
|
+ status: ind.status || ''
|
|
|
+ })
|
|
|
+ }
|
|
|
+ var catKeys = Object.keys(byCat)
|
|
|
+ for (var ck = 0; ck < catKeys.length; ck++) {
|
|
|
+ blocks.push({ type: 'indicator', title: catKeys[ck], items: byCat[catKeys[ck]] })
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 4. 菌种列表块
|
|
|
+ var floraItems = []
|
|
|
+ // 肠道菌群
|
|
|
+ var gf = p.gutFlora || []
|
|
|
+ for (var fi = 0; fi < gf.length; fi++) {
|
|
|
+ var f = gf[fi]
|
|
|
+ floraItems.push({
|
|
|
+ name: f.name || f.bacteriaName || '',
|
|
|
+ value: f.abundance != null ? f.abundance : (f.bacteriaValue || ''),
|
|
|
+ range: f.normalRange || '',
|
|
|
+ status: f.populationLevel || f.level || f.status || ''
|
|
|
+ })
|
|
|
+ }
|
|
|
+ // 病原菌
|
|
|
+ var pg = p.pathogenGenus || []
|
|
|
+ for (var pi = 0; pi < pg.length; pi++) {
|
|
|
+ var pgi = pg[pi]
|
|
|
+ floraItems.push({
|
|
|
+ name: pgi.name || pgi.bacteriaName || '',
|
|
|
+ value: pgi.abundance != null ? pgi.abundance : (pgi.bacteriaValue || ''),
|
|
|
+ range: pgi.normalRange || '',
|
|
|
+ status: pgi.populationLevel || pgi.level || pgi.status || ''
|
|
|
+ })
|
|
|
+ }
|
|
|
+ var pd = p.pathogenDetection || []
|
|
|
+ for (var pdi = 0; pdi < pd.length; pdi++) {
|
|
|
+ var pdiItem = pd[pdi]
|
|
|
+ floraItems.push({
|
|
|
+ name: pdiItem.name || pdiItem.bacteriaName || '',
|
|
|
+ value: pdiItem.abundance != null ? pdiItem.abundance : (pdiItem.bacteriaValue || ''),
|
|
|
+ range: pdiItem.normalRange || '',
|
|
|
+ status: pdiItem.populationLevel || pdiItem.level || pdiItem.status || ''
|
|
|
+ })
|
|
|
+ }
|
|
|
+ if (floraItems.length > 0) {
|
|
|
+ blocks.push({
|
|
|
+ type: 'list', title: '菌种详情',
|
|
|
+ columns: [{ key: 'name', label: '菌种' }, { key: 'value', label: '数值' }, { key: 'range', label: '正常范围' }, { key: 'status', label: '状态' }],
|
|
|
+ items: floraItems
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ // 5. 食物推荐列表
|
|
|
+ var foods = p.foods || []
|
|
|
+ if (foods.length > 0) {
|
|
|
+ var foodItems = []
|
|
|
+ for (var fdi = 0; fdi < foods.length; fdi++) {
|
|
|
+ var fd = foods[fdi]
|
|
|
+ foodItems.push({ name: fd.foodName || fd.name || '', category: fd.category || '', score: fd.score != null ? fd.score : '' })
|
|
|
+ }
|
|
|
+ blocks.push({
|
|
|
+ type: 'list', title: '食物推荐',
|
|
|
+ columns: [{ key: 'name', label: '食材' }, { key: 'category', label: '类别' }, { key: 'score', label: '推荐指数' }],
|
|
|
+ items: foodItems
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ // 6. 益生菌种列表
|
|
|
+ var ps = p.probioticSpecies || []
|
|
|
+ if (ps.length > 0) {
|
|
|
+ var psItems = []
|
|
|
+ for (var psi = 0; psi < ps.length; psi++) {
|
|
|
+ var psiItem = ps[psi]
|
|
|
+ psItems.push({
|
|
|
+ name: psiItem.name || psiItem.bacteriaName || '',
|
|
|
+ value: psiItem.abundance != null ? psiItem.abundance : (psiItem.bacteriaValue || ''),
|
|
|
+ range: psiItem.normalRange || '',
|
|
|
+ status: psiItem.populationLevel || psiItem.level || psiItem.status || ''
|
|
|
+ })
|
|
|
+ }
|
|
|
+ blocks.push({
|
|
|
+ type: 'list', title: '益生菌种',
|
|
|
+ columns: [{ key: 'name', label: '菌种' }, { key: 'value', label: '数值' }, { key: 'range', label: '正常范围' }, { key: 'status', label: '状态' }],
|
|
|
+ items: psItems
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ // 7. 分类学列表(纲/目/科/属/种)
|
|
|
+ var taxLabels = [
|
|
|
+ { key: 'taxonomyClass', label: '菌纲 (Class)' },
|
|
|
+ { key: 'taxonomyOrder', label: '菌目 (Order)' },
|
|
|
+ { key: 'taxonomyFamily', label: '菌科 (Family)' },
|
|
|
+ { key: 'taxonomyGenus', label: '菌属 (Genus)' },
|
|
|
+ { key: 'taxonomySpecies', label: '菌种 (Species)' }
|
|
|
+ ]
|
|
|
+ for (var tli = 0; tli < taxLabels.length; tli++) {
|
|
|
+ var tl = taxLabels[tli]
|
|
|
+ var taxList = p[tl.key] || []
|
|
|
+ if (taxList.length > 0) {
|
|
|
+ var taxItems = []
|
|
|
+ for (var txi = 0; txi < taxList.length; txi++) {
|
|
|
+ var tx = taxList[txi]
|
|
|
+ taxItems.push({ name: tx.name || '', value: tx.abundance != null ? tx.abundance : '' })
|
|
|
+ }
|
|
|
+ blocks.push({
|
|
|
+ type: 'list', title: tl.label,
|
|
|
+ columns: [{ key: 'name', label: '名称' }, { key: 'value', label: '丰度' }],
|
|
|
+ items: taxItems
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return blocks
|
|
|
+ },
|
|
|
+ _addScoreItem: function(items, label, value) {
|
|
|
+ if (value == null || value === '') return
|
|
|
+ items.push({ label: label, value: value, max: 100 })
|
|
|
+ },
|
|
|
+ _addSubScore: function(items, parentLabel, label, value) {
|
|
|
+ if (value == null) return
|
|
|
+ items.push({ parentLabel: parentLabel, label: label, value: value, max: 100 })
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -920,8 +1091,6 @@ export default {
|
|
|
font-size: 26rpx;
|
|
|
padding: 60rpx 0;
|
|
|
}
|
|
|
-.payload-fallback { padding: 0; }
|
|
|
-.payload-fallback .score-text { font-size: 48rpx; font-weight: bold; color: #4A9BD7; text-align: center; display: block; padding: 20rpx 0; }
|
|
|
.edit-btn {
|
|
|
margin: 30rpx 0;
|
|
|
display: flex;
|