| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 |
- <template>
- <div class="health-indicators page-container">
- <el-card>
- <div slot="header"><span>健康指标</span></div>
- <el-table :data="indicators" v-loading="loading" border stripe :max-height="tableHeight" :cell-style="cellStyle">
- <el-table-column prop="id" label="ID" width="80">
- <template slot="header">
- <span class="sort-header" @click.stop="onSortClick('id', $event)">ID<span v-if="sortIndex('id') !== null" class="sort-index" :class="sortClass('id') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('id') }}</span>{{ sortIcon('id') }}</span>
- </template>
- </el-table-column>
- <el-table-column prop="childName" label="孩子" width="120">
- <template slot="header">
- <span class="sort-header" @click.stop="onSortClick('childName', $event)">孩子<span v-if="sortIndex('childName') !== null" class="sort-index" :class="sortClass('childName') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('childName') }}</span>{{ sortIcon('childName') }}</span>
- </template>
- </el-table-column>
- <el-table-column prop="indicatorName" label="指标名称" width="120">
- <template slot="header">
- <span class="sort-header" @click.stop="onSortClick('indicatorName', $event)">指标名称<span v-if="sortIndex('indicatorName') !== null" class="sort-index" :class="sortClass('indicatorName') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('indicatorName') }}</span>{{ sortIcon('indicatorName') }}</span>
- </template>
- <template slot-scope="{ row }">
- <span :style="row.status && row.status !== '正常' ? 'color: #DC2626; font-weight: bold' : ''">
- {{ row.indicatorName }}
- </span>
- </template>
- </el-table-column>
- <el-table-column prop="value" label="数值" width="100">
- <template slot="header">
- <span class="sort-header" @click.stop="onSortClick('value', $event)">数值<span v-if="sortIndex('value') !== null" class="sort-index" :class="sortClass('value') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('value') }}</span>{{ sortIcon('value') }}</span>
- </template>
- </el-table-column>
- <el-table-column prop="status" label="状态" width="80">
- <template slot="header">
- <span class="sort-header" @click.stop="onSortClick('status', $event)">状态<span v-if="sortIndex('status') !== null" class="sort-index" :class="sortClass('status') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('status') }}</span>{{ sortIcon('status') }}</span>
- </template>
- <template slot-scope="{ row }">
- <el-tag v-if="row.status && row.status !== '正常'" :type="statusTagType(row.status)" size="small">
- {{ row.status }}
- </el-tag>
- <span v-else>{{ row.status || '正常' }}</span>
- </template>
- </el-table-column>
- <el-table-column label="关联营养素" width="120">
- <template slot-scope="{ row }">
- <template v-if="row.linkedNutrients && row.linkedNutrients.length > 0">
- <el-tag v-for="nutrient in row.linkedNutrients" :key="nutrient" size="mini" style="margin-right: 4px">
- {{ nutrient }}
- </el-tag>
- </template>
- <span v-else style="color: #999; font-size: 12px">—</span>
- </template>
- </el-table-column>
- <el-table-column prop="recordedAt" label="记录时间" width="180">
- <template slot="header">
- <span class="sort-header" @click.stop="onSortClick('recordedAt', $event)">记录时间<span v-if="sortIndex('recordedAt') !== null" class="sort-index" :class="sortClass('recordedAt') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('recordedAt') }}</span>{{ sortIcon('recordedAt') }}</span>
- </template>
- </el-table-column>
- </el-table>
- </el-card>
- </div>
- </template>
- <script>
- import SortMixin from '@/mixins/SortMixin'
- export default {
- mixins: [SortMixin],
- name: 'HealthIndicators',
- computed: {
- tableHeight() {
- return window.innerHeight - 280
- }
- },
- data() { return { loading: false, indicators: [], sortableColumns: { id: 'ID', recordedAt: '记录时间', childName: '孩子', indicatorName: '指标名称', value: '数值', status: '状态' } } },
- created() { this.loadIndicators() },
- methods: {
- loadList() { this.loadIndicators() },
- async loadIndicators() {
- this.loading = true
- try {
- const baseURL = process.env.VUE_APP_BASE_API || ''
- const token = localStorage.getItem('token')
- const axios = this.$axios || (await import('axios')).default
- const params = {}
- if (this.sortState.length > 0) params.sort = this.sortState
- const res = await axios.post(baseURL + '/api/health/indicator/list', params, {
- headers: { Authorization: 'Bearer ' + token }
- })
- this.indicators = res.data?.data || []
- } catch (e) {
- this.$message?.error?.('加载健康指标失败')
- } finally {
- this.loading = false
- }
- },
- cellStyle({ row, columnIndex }) {
- if (columnIndex === 1 && row.status && row.status !== '正常') {
- return 'background: #FEF2F2'
- }
- return ''
- },
- statusTagType(status) {
- if (!status) return 'info'
- var s = status.toLowerCase()
- if (s.indexOf('低') >= 0 || s.indexOf('缺乏') >= 0 || s.indexOf('不足') >= 0 || s === 'low') return 'danger'
- if (s.indexOf('高') >= 0 || s.indexOf('过量') >= 0 || s === 'high') return 'warning'
- if (s.indexOf('临界') >= 0 || s.indexOf('边缘') >= 0 || s === 'borderline') return 'warning'
- return 'info'
- }
- }
- }
- </script>
- <style scoped>
- .sort-header {
- cursor: pointer;
- user-select: none;
- font-weight: 500;
- font-size: 12px;
- }
- .sort-header:hover {
- color: #409eff;
- }
- </style>
|