|
@@ -0,0 +1,142 @@
|
|
|
|
|
+<template>
|
|
|
|
|
+ <div class="nutrition-mappings">
|
|
|
|
|
+ <el-card>
|
|
|
|
|
+ <div slot="header">
|
|
|
|
|
+ <span>营养素映射管理</span>
|
|
|
|
|
+ <el-button type="primary" size="mini" style="float:right" @click="openCreateDialog">新增映射</el-button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <el-table :data="mappings" v-loading="loading" border stripe>
|
|
|
|
|
+ <el-table-column prop="id" label="ID" width="60" />
|
|
|
|
|
+ <el-table-column prop="indicatorNamePattern" label="指标名模式" width="180" />
|
|
|
|
|
+ <el-table-column prop="nutrient" label="营养素" width="100" />
|
|
|
|
|
+ <el-table-column prop="severityWeight" label="权重" width="80" />
|
|
|
|
|
+ <el-table-column prop="deficiencySymptoms" label="缺乏症状" min-width="150" show-overflow-tooltip />
|
|
|
|
|
+ <el-table-column prop="foodSuggestions" label="推荐食物" min-width="180" show-overflow-tooltip />
|
|
|
|
|
+ <el-table-column prop="sortOrder" label="排序" width="80" />
|
|
|
|
|
+ <el-table-column label="操作" width="150" fixed="right">
|
|
|
|
|
+ <template slot-scope="{ row }">
|
|
|
|
|
+ <el-button size="mini" @click="openEditDialog(row)">编辑</el-button>
|
|
|
|
|
+ <el-button size="mini" type="danger" @click="handleDelete(row)">删除</el-button>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ </el-table>
|
|
|
|
|
+ </el-card>
|
|
|
|
|
+
|
|
|
|
|
+ <el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="600px">
|
|
|
|
|
+ <el-form :model="form" label-width="120px">
|
|
|
|
|
+ <el-form-item label="指标名模式">
|
|
|
|
|
+ <el-input v-model="form.indicatorNamePattern" placeholder="如: 铁蛋白, 维生素D%" />
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ <el-form-item label="营养素">
|
|
|
|
|
+ <el-input v-model="form.nutrient" placeholder="如: 铁, 维生素D" />
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ <el-form-item label="权重(0-1)">
|
|
|
|
|
+ <el-input-number v-model="form.severityWeight" :min="0" :max="1" :step="0.1" />
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ <el-form-item label="缺乏症状">
|
|
|
|
|
+ <el-input v-model="form.deficiencySymptoms" type="textarea" :rows="2" />
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ <el-form-item label="过量症状">
|
|
|
|
|
+ <el-input v-model="form.excessSymptoms" type="textarea" :rows="2" />
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ <el-form-item label="推荐食物">
|
|
|
|
|
+ <el-input v-model="form.foodSuggestions" placeholder="逗号分隔,如: 动物肝脏,红肉,菠菜" />
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ <el-form-item label="排序">
|
|
|
|
|
+ <el-input-number v-model="form.sortOrder" :min="0" />
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ </el-form>
|
|
|
|
|
+ <div slot="footer">
|
|
|
|
|
+ <el-button @click="dialogVisible = false">取消</el-button>
|
|
|
|
|
+ <el-button type="primary" @click="handleSave">保存</el-button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </el-dialog>
|
|
|
|
|
+ </div>
|
|
|
|
|
+</template>
|
|
|
|
|
+
|
|
|
|
|
+<script>
|
|
|
|
|
+export default {
|
|
|
|
|
+ name: 'NutritionMappings',
|
|
|
|
|
+ data() {
|
|
|
|
|
+ return {
|
|
|
|
|
+ loading: false,
|
|
|
|
|
+ mappings: [],
|
|
|
|
|
+ dialogVisible: false,
|
|
|
|
|
+ dialogTitle: '新增映射',
|
|
|
|
|
+ form: {
|
|
|
|
|
+ id: null,
|
|
|
|
|
+ indicatorNamePattern: '',
|
|
|
|
|
+ nutrient: '',
|
|
|
|
|
+ severityWeight: 1.0,
|
|
|
|
|
+ deficiencySymptoms: '',
|
|
|
|
|
+ excessSymptoms: '',
|
|
|
|
|
+ foodSuggestions: '',
|
|
|
|
|
+ sortOrder: 10
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ created() {
|
|
|
|
|
+ this.loadMappings()
|
|
|
|
|
+ },
|
|
|
|
|
+ methods: {
|
|
|
|
|
+ async loadMappings() {
|
|
|
|
|
+ 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 res = await axios.post(baseURL + '/api/health/nutrition/mappings', {}, {
|
|
|
|
|
+ headers: { Authorization: 'Bearer ' + token }
|
|
|
|
|
+ })
|
|
|
|
|
+ this.mappings = res.data?.data || []
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ this.$message?.error?.('加载映射列表失败')
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ this.loading = false
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ openCreateDialog() {
|
|
|
|
|
+ this.form = { id: null, indicatorNamePattern: '', nutrient: '', severityWeight: 1.0, deficiencySymptoms: '', excessSymptoms: '', foodSuggestions: '', sortOrder: 10 }
|
|
|
|
|
+ this.dialogTitle = '新增映射'
|
|
|
|
|
+ this.dialogVisible = true
|
|
|
|
|
+ },
|
|
|
|
|
+ openEditDialog(row) {
|
|
|
|
|
+ this.form = { ...row }
|
|
|
|
|
+ this.dialogTitle = '编辑映射'
|
|
|
|
|
+ this.dialogVisible = true
|
|
|
|
|
+ },
|
|
|
|
|
+ async handleSave() {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const baseURL = process.env.VUE_APP_BASE_API || ''
|
|
|
|
|
+ const token = localStorage.getItem('token')
|
|
|
|
|
+ const axios = this.$axios || (await import('axios')).default
|
|
|
|
|
+ const url = this.form.id ? '/api/health/nutrition/mapping/update' : '/api/health/nutrition/mapping/create'
|
|
|
|
|
+ await axios.post(baseURL + url, this.form, {
|
|
|
|
|
+ headers: { Authorization: 'Bearer ' + token }
|
|
|
|
|
+ })
|
|
|
|
|
+ this.$message?.success?.('保存成功')
|
|
|
|
|
+ this.dialogVisible = false
|
|
|
|
|
+ this.loadMappings()
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ this.$message?.error?.('保存失败')
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ async handleDelete(row) {
|
|
|
|
|
+ this.$confirm('确认删除映射 "' + row.nutrient + '" 吗?', '提示', { type: 'warning' }).then(async () => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const baseURL = process.env.VUE_APP_BASE_API || ''
|
|
|
|
|
+ const token = localStorage.getItem('token')
|
|
|
|
|
+ const axios = this.$axios || (await import('axios')).default
|
|
|
|
|
+ await axios.post(baseURL + '/api/health/nutrition/mapping/delete', { id: row.id }, {
|
|
|
|
|
+ headers: { Authorization: 'Bearer ' + token }
|
|
|
|
|
+ })
|
|
|
|
|
+ this.$message?.success?.('删除成功')
|
|
|
|
|
+ this.loadMappings()
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ this.$message?.error?.('删除失败')
|
|
|
|
|
+ }
|
|
|
|
|
+ }).catch(() => {})
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+</script>
|