| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497 |
- <template>
- <view class="page">
- <text class="nav-edit" @tap="toggleEdit">{{ isEditing ? '完成' : '编辑' }}</text>
- <!-- 头部摘要 -->
- <view class="header-summary" v-if="!isEditing && risks.length > 0">
- <view class="summary-stat">
- <text class="stat-num stat-abnormal">{{ importantRisks.length }}</text>
- <text class="stat-label">需关注</text>
- </view>
- <view class="summary-stat">
- <text class="stat-num stat-low">{{ normalRisks.length }}</text>
- <text class="stat-label">低风险</text>
- </view>
- <view class="summary-stat">
- <text class="stat-num stat-total">{{ risks.length }}</text>
- <text class="stat-label">总计</text>
- </view>
- </view>
- <scroll-view class="content" scroll-y>
- <view class="content-inner">
- <!-- 重要风险 -->
- <view class="section-header" v-if="importantRisks.length > 0">
- <view class="section-line"></view>
- <text class="section-label">⚠ 需重点关注</text>
- </view>
- <view class="risk-card important-card" v-for="(item, idx) in importantRisks" :key="idx"
- :class="'risk-level-' + (item._cssClass || 'low')">
- <view class="card-top">
- <view class="card-title-row">
- <text class="risk-help" @tap.stop="showDiseaseKnowledge(item)">?</text>
- <text class="risk-name">{{ item.diseaseName }}</text>
- <text class="risk-badge" :class="'badge-' + (item._cssClass || 'low')">
- {{ riskBadgeText(item.riskLevel) }}
- </text>
- </view>
- <view class="risk-progress-wrap" v-if="item.riskValue != null">
- <view class="risk-progress-bg">
- <view class="risk-progress-fill" :class="'fill-' + (item._cssClass || 'low')"
- :style="'width:' + calcProgress(item.riskValue) + '%'"></view>
- </view>
- <text class="risk-value-text">{{ item.riskValue }}</text>
- </view>
- </view>
- <view class="card-desc" v-if="item.diseaseDesc">
- <text class="desc-label">说明:</text>
- <text class="desc-content">{{ item.diseaseDesc }}</text>
- </view>
- <view class="risk-detail-row" v-if="!isEditing">
- <text class="risk-tag" :class="'tag-' + (item._cssClass || 'low')">
- {{ item.riskLevel || '--' }}
- </text>
- <text class="risk-value" v-if="item.riskValue">风险值 {{ item.riskValue }}</text>
- </view>
- <view class="risk-edit-row" v-if="isEditing">
- <text class="edit-label">风险值:</text>
- <input class="edit-input" type="text" v-model="item.riskValue" />
- <text class="edit-label">等级:</text>
- <picker :value="riskLevelIndex(item.riskLevel)" :range="riskLevels" @change="onRiskLevelChange($event, item)">
- <text class="edit-picker">{{ item.riskLevel || '请选择' }}</text>
- </picker>
- </view>
- </view>
- <!-- 其它风险 -->
- <view class="section-header" v-if="normalRisks.length > 0">
- <view class="section-line"></view>
- <text class="section-label">✓ 低风险项</text>
- </view>
- <view class="risk-card normal-card" v-for="(item, idx) in normalRisks" :key="idx"
- :class="'risk-level-' + (item._cssClass || 'low')">
- <view class="card-top">
- <view class="card-title-row">
- <text class="risk-help" @tap.stop="showDiseaseKnowledge(item)">?</text>
- <text class="risk-name">{{ item.diseaseName }}</text>
- <text class="risk-badge" :class="'badge-' + (item._cssClass || 'low')">
- {{ riskBadgeText(item.riskLevel) }}
- </text>
- </view>
- </view>
- <view class="card-desc" v-if="item.diseaseDesc">
- <text class="desc-label">说明:</text>
- <text class="desc-content">{{ item.diseaseDesc }}</text>
- </view>
- <view class="risk-detail-row" v-if="!isEditing">
- <text class="risk-tag" :class="'tag-' + (item._cssClass || 'low')">{{ item.riskLevel || '--' }}</text>
- </view>
- <view class="risk-edit-row" v-if="isEditing">
- <text class="edit-label">风险值:</text>
- <input class="edit-input" type="text" v-model="item.riskValue" />
- <text class="edit-label">等级:</text>
- <picker :value="riskLevelIndex(item.riskLevel)" :range="riskLevels" @change="onRiskLevelChange($event, item)">
- <text class="edit-picker">{{ item.riskLevel || '请选择' }}</text>
- </picker>
- </view>
- </view>
- <view class="empty-hint" v-if="risks.length === 0">暂无疾病风险评估</view>
- <view class="bottom-spacer"></view>
- </view>
- </scroll-view>
- <!-- 疾病知识库弹窗 -->
- <health-knowledge-popup :visible="knowledgeVisible" :data="knowledgeData" @close="closeKnowledge" />
- <view class="bottom-bar" v-if="isEditing">
- <view class="btn-cancel" @tap="cancelEdit">取消</view>
- <view class="btn-save" @tap="saveEdit">保存</view>
- </view>
- </view>
- </template>
- <script>
- import { getReportDetail, editHealthReport, queryKnowledgeBase, queryIndicatorKnowledge, queryDiseaseKnowledge } from '../../utils/api.js'
- import HealthKnowledgePopup from '@/pages/health/components/health-knowledge-popup.vue'
- export default {
- components: { HealthKnowledgePopup },
- data() {
- return {
- reportId: null,
- reportData: null,
- risks: [],
- isEditing: false,
- editRisks: [],
- riskLevels: ['低风险', '需注意', '高风险', '异常'],
- knowledgeVisible: false,
- knowledgeData: {}
- }
- },
- computed: {
- importantRisks: function() {
- return this.getRisks().filter(function(item) {
- var level = item.riskLevel || ''
- return level === '需注意' || level === '注意' || level === '高风险' || level === '异常'
- })
- },
- normalRisks: function() {
- return this.getRisks().filter(function(item) {
- var level = item.riskLevel || ''
- return level !== '需注意' && level !== '注意' && level !== '高风险' && level !== '异常'
- })
- }
- },
- onLoad: function(options) {
- this.reportId = options.reportId ? parseInt(options.reportId) : null
- if (this.reportId) {
- this.loadData()
- }
- },
- methods: {
- goBack: function() { uni.navigateBack() },
- /** 中文风险等级 → CSS安全英文 */
- _cssForRiskLevel: function(level) {
- var map = { '低风险': 'low', '注意': 'warning', '需注意': 'warning', '高风险': 'high', '异常': 'abnormal' }
- return map[level] || 'low'
- },
- /** 风险值归一化进度(0~1范围映射到百分比) */
- calcProgress: function(value) {
- var v = parseFloat(value)
- if (isNaN(v)) return 0
- return Math.min(100, Math.max(0, v * 100))
- },
- getRisks: function() {
- return this.isEditing ? this.editRisks : this.risks
- },
- loadData: function() {
- var self = this
- getReportDetail(this.reportId).then(function(res) {
- if (res.code === 200 && res.data) {
- self.reportData = res.data
- var rawRisks = res.data.diseaseRisks || []
- self.risks = rawRisks.map(function(item) {
- item._cssClass = self._cssForRiskLevel(item.riskLevel)
- return item
- })
- // 批量预加载疾病知识库
- self.preloadDiseaseKnowledge(self.risks)
- }
- })
- },
- /** 批量加载疾病知识库,补充到 risks 数据中 */
- preloadDiseaseKnowledge: function(risks) {
- var self = this
- risks.forEach(function(item) {
- if (item.diseaseName) {
- queryDiseaseKnowledge(item.diseaseName).then(function(res) {
- if (res.code === 200 && res.data) {
- var d = res.data
- // 兼容不同字段名
- item.diseaseDesc = d.description || d.说明 || d.category || ''
- item.diseaseRelatedBacteria = d.relatedBacteria || d.关联菌种 || ''
- }
- }).catch(function() {})
- }
- })
- },
- toggleEdit: function() {
- this.isEditing = true
- this.editRisks = JSON.parse(JSON.stringify(this.risks))
- },
- cancelEdit: function() {
- this.isEditing = false
- this.editRisks = []
- },
- saveEdit: function() {
- var self = this
- editHealthReport(self.reportId, { diseaseRisks: self.editRisks }, 0).then(function(res) {
- if (res.code === 200) {
- uni.showToast({ title: '已保存', icon: 'success' })
- self.isEditing = false
- self.loadData()
- } else {
- uni.showToast({ title: res.message || '保存失败', icon: 'none' })
- }
- })
- },
- riskBadgeText: function(level) {
- var map = { '低风险': '✓ 低', '需注意': '⚠ 注意', '高风险': '⚠ 高', '异常': '⚠ 异常' }
- return map[level] || level || ''
- },
- riskLevelIndex: function(level) {
- var idx = this.riskLevels.indexOf(level)
- return idx >= 0 ? idx : 0
- },
- onRiskLevelChange: function(e, item) {
- item.riskLevel = this.riskLevels[e.detail.value]
- item._cssClass = this._cssForRiskLevel(item.riskLevel)
- },
- showDiseaseKnowledge: function(item) {
- this.showKnowledge('disease', item && item.diseaseName)
- },
- showKnowledge: function(type, name) {
- var self = this
- // 优先查询疾病知识库
- queryDiseaseKnowledge(name).then(function(res) {
- if (res.code === 200 && res.data) {
- var d = res.data
- self.knowledgeData = {
- itemName: d.name || d.名称 || name,
- category: d.category || d.分类 || d.description || d.说明 || '',
- description: d.description || d.说明 || d.relatedBacteria || d.关联菌种 || '',
- suggestion: d.suggestion || d.调整建议 || ''
- }
- self.knowledgeVisible = true
- return
- }
- // 回退到指标知识库
- queryIndicatorKnowledge(name).then(function(res2) {
- if (res2.code === 200 && res2.data) {
- var v3 = res2.data
- var high = v3['偏高影响'] || ''
- var low = v3['偏低影响'] || ''
- self.knowledgeData = {
- itemName: v3['名称'] || name,
- category: v3['说明'] || '',
- description: (high ? '偏高影响:' + high + '\n' : '') + (low ? '偏低影响:' + low : ''),
- suggestion: v3['调整建议'] || ''
- }
- self.knowledgeVisible = true
- } else {
- self.queryOldKnowledgeBase(type, name)
- }
- }).catch(function() {
- self.queryOldKnowledgeBase(type, name)
- })
- }).catch(function() {
- self.queryOldKnowledgeBase(type, name)
- })
- },
- queryOldKnowledgeBase: function(type, name) {
- var self = this
- queryKnowledgeBase(type, name).then(function(res) {
- if (res.code === 200 && res.data) {
- self.knowledgeData = res.data
- self.knowledgeVisible = true
- } else {
- self.knowledgeData = { itemName: name }
- self.knowledgeVisible = true
- }
- })
- },
- closeKnowledge: function() {
- this.knowledgeVisible = false
- this.knowledgeData = {}
- }
- }
- }
- </script>
- <style scoped>
- .page { min-height: 100vh; background: #f5f6fa; }
- .nav-edit { font-size: 28rpx; color: #4A9BD7; padding: 10rpx 30rpx; text-align: right; display: block; }
- /* ===== 头部摘要 ===== */
- .header-summary {
- display: flex;
- align-items: center;
- justify-content: space-around;
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
- padding: 32rpx 30rpx;
- margin: 0 0 16rpx;
- }
- .summary-stat {
- display: flex;
- flex-direction: column;
- align-items: center;
- }
- .stat-num {
- font-size: 44rpx;
- font-weight: 700;
- color: #fff;
- }
- .stat-abnormal { color: #FFD6D6; }
- .stat-low { color: #d4edda; }
- .stat-total { color: #fff; }
- .stat-label {
- font-size: 22rpx;
- color: rgba(255,255,255,0.8);
- margin-top: 6rpx;
- }
- .content { height: calc(100vh - 200rpx); }
- .content-inner { padding: 0 24rpx; }
- /* ===== 区块标题 ===== */
- .section-header {
- display: flex;
- align-items: center;
- gap: 12rpx;
- margin: 24rpx 0 16rpx;
- }
- .section-line {
- width: 6rpx;
- height: 28rpx;
- border-radius: 3rpx;
- background: #4A9BD7;
- }
- .section-label {
- font-size: 28rpx;
- font-weight: 600;
- color: #333;
- }
- /* ===== 风险卡片 ===== */
- .risk-card {
- background: #fff;
- border-radius: 20rpx;
- padding: 28rpx 24rpx;
- margin-bottom: 16rpx;
- box-shadow: 0 2rpx 16rpx rgba(0,0,0,0.06);
- border-left: 10rpx solid #10B981;
- transition: all 0.2s;
- }
- .risk-level-warning { border-left-color: #F59E0B; }
- .risk-level-high { border-left-color: #EF4444; }
- .risk-level-abnormal { border-left-color: #C62828; }
- /* 重要风险卡片背景微 tint */
- .important-card.risk-level-warning { background: linear-gradient(135deg, #fff 60%, #FFF8E1 100%); }
- .important-card.risk-level-high { background: linear-gradient(135deg, #fff 60%, #FFEBEE 100%); }
- .important-card.risk-level-abnormal { background: linear-gradient(135deg, #fff 60%, #FFEBEE 100%); }
- .card-top {
- display: flex;
- justify-content: space-between;
- align-items: flex-start;
- margin-bottom: 12rpx;
- }
- .card-title-row {
- display: flex;
- align-items: center;
- flex: 1;
- gap: 12rpx;
- min-width: 0;
- }
- .risk-name {
- font-size: 30rpx;
- font-weight: 600;
- color: #333;
- flex: 1;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- }
- .risk-badge {
- padding: 4rpx 16rpx;
- border-radius: 20rpx;
- font-size: 22rpx;
- flex-shrink: 0;
- }
- .badge-low { background: #E8F5E9; color: #2E7D32; }
- .badge-warning { background: #FFF3E0; color: #E65100; }
- .badge-high { background: #FFEBEE; color: #C62828; }
- .badge-abnormal { background: #C62828; color: #fff; }
- /* 风险进度条 */
- .risk-progress-wrap {
- display: flex;
- flex-direction: column;
- align-items: flex-end;
- gap: 6rpx;
- flex-shrink: 0;
- margin-left: 16rpx;
- width: 160rpx;
- }
- .risk-progress-bg {
- width: 100%;
- height: 10rpx;
- background: #f0f0f0;
- border-radius: 5rpx;
- overflow: hidden;
- }
- .risk-progress-fill {
- height: 100%;
- border-radius: 5rpx;
- transition: width 0.6s ease;
- }
- .fill-low { background: #10B981; }
- .fill-warning { background: #F59E0B; }
- .fill-high { background: #EF4444; }
- .fill-abnormal { background: #C62828; }
- .risk-value-text {
- font-size: 22rpx;
- color: #999;
- }
- /* 疾病说明 */
- .card-desc {
- display: flex;
- gap: 6rpx;
- margin-bottom: 14rpx;
- padding: 12rpx 16rpx;
- background: #f8f9fc;
- border-radius: 10rpx;
- }
- .desc-label {
- font-size: 22rpx;
- color: #999;
- flex-shrink: 0;
- }
- .desc-content {
- font-size: 22rpx;
- color: #666;
- line-height: 1.5;
- flex: 1;
- }
- /* 底部标签行 */
- .risk-detail-row {
- display: flex;
- align-items: center;
- gap: 16rpx;
- flex-wrap: wrap;
- }
- .risk-tag {
- font-size: 22rpx;
- padding: 4rpx 14rpx;
- border-radius: 8rpx;
- }
- .tag-low { background: #E8F5E9; color: #2E7D32; }
- .tag-warning { background: #FFF3E0; color: #E65100; }
- .tag-high { background: #FFEBEE; color: #C62828; }
- .tag-abnormal { background: #C62828; color: #fff; }
- .risk-value {
- font-size: 24rpx;
- color: #666;
- }
- .risk-more {
- font-size: 24rpx;
- color: #4A9BD7;
- margin-left: auto;
- }
- /* 编辑行 */
- .risk-edit-row {
- display: flex;
- align-items: center;
- gap: 12rpx;
- flex-wrap: wrap;
- padding-top: 12rpx;
- border-top: 1rpx solid #f0f0f0;
- margin-top: 4rpx;
- }
- .edit-label { font-size: 26rpx; color: #666; }
- .edit-input { border: 1rpx solid #ddd; border-radius: 8rpx; padding: 8rpx 12rpx; font-size: 26rpx; width: 120rpx; }
- .edit-picker { border: 1rpx solid #ddd; border-radius: 8rpx; padding: 8rpx 12rpx; font-size: 26rpx; color: #333; }
- .empty-hint { text-align: center; color: #ccc; padding: 80rpx 0; font-size: 28rpx; }
- .bottom-spacer { height: 40rpx; }
- /* 底栏 */
- .bottom-bar { position: fixed; bottom: 0; left: 0; right: 0; display: flex; padding: 20rpx 30rpx; background: #fff; border-top: 1rpx solid #eee; gap: 20rpx; z-index: 100; }
- .btn-cancel { flex: 1; padding: 20rpx; border: 1rpx solid #ddd; border-radius: 12rpx; text-align: center; font-size: 28rpx; color: #666; }
- .btn-save { flex: 1; padding: 20rpx; background: #4A9BD7; border-radius: 12rpx; text-align: center; font-size: 28rpx; color: #fff; }
- </style>
|