Browse Source

实现批量更新食物营养素

wangyang 4 years ago
parent
commit
47aaf31390

+ 9 - 0
src/api/food.js

@@ -61,6 +61,15 @@ export function updateFoodNutrient(id, nutrientId, data) {
   })
 }
 
+// 批量更新食物关联的营养素
+export function multiUpdateNutrients(id, data) {
+  return request({
+    url: `/api/foods/${id}/nutrients/multi-update`,
+    method: 'post',
+    data
+  })
+}
+
 // 更新食物关联的营养素的排序
 export function updateFoodNutrientSort(id, nutrientId, data) {
   return request({

+ 98 - 0
src/views/food/components/MultiEditNutrients.vue

@@ -0,0 +1,98 @@
+<template>
+  <div>
+    <el-table
+      :key="tableKey"
+      :data="data"
+      border
+      fit
+      highlight-current-row
+      style="width: 100%;margin-top: 10px"
+    >
+      <el-table-column type="index" label="序号" align="center" width="60px" />
+      <el-table-column label="营养素名称" align="center">
+        <template slot-scope="{row}">
+          <span>{{ row.nutrientName }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="营养素计量" align="center" :width="150">
+        <template slot-scope="{row}">
+          <el-radio v-model="row.radio" :label="0" @change="radioChange(row)">值</el-radio>
+          <el-radio v-model="row.radio" :label="1" @change="radioChange(row)">范围</el-radio>
+          <el-radio v-model="row.radio" :label="2" @change="radioChange(row)">误差</el-radio>
+          <div v-if="row.radio === 1" style="display: inline-block">
+            大于等于:
+            <el-input v-model="row.quantityMin" @focus="getInputFocus" />
+            小于等于:
+            <el-input v-model="row.quantityMax" @focus="getInputFocus" />
+          </div>
+          <div v-else-if="row.radio === 2" style="display: inline-block">
+            基准:
+            <el-input v-model="row.quantity" @focus="getInputFocus" />
+            ±:
+            <el-input v-model="row.stdError" @focus="getInputFocus" />
+          </div>
+          <el-input
+            v-else
+            v-model="row.quantity"
+            style="width: 80px;"
+            class="filter-item"
+            @focus="getInputFocus"
+          />
+        </template>
+      </el-table-column>
+      <el-table-column label="计量单位" align="center" width="150">
+        <template slot-scope="{row}">
+          <el-autocomplete
+            v-model="row.unit"
+            @input="handleRowUnitChanged(row)"
+            :fetch-suggestions="(query, cb) => {queryNutrientUnits(query, row.nutrientId, cb)}"
+            placeholder="单位关键词"
+          />
+          <el-select
+            clearable
+            v-show="showRowNutrientSource"
+            v-model="row.nutrientSource"
+            placeholder="请选择营养素来源"
+          >
+            <el-option v-for="item in nutrientSources" :key="item" :label="item" :value="item" />
+          </el-select>
+        </template>
+      </el-table-column>
+    </el-table>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'MultiEditNutrients',
+  props: {
+    data: {
+      type: Array,
+      default: []
+    }
+  },
+  data() {
+    return {
+      tableKey: 0,
+
+    }
+  },
+  created() {
+  },
+  methods: {
+    radioChange(row) {
+      this.$set(row, 'stdError', '')
+      this.$set(row, 'quantityMin', '')
+      this.$set(row, 'quantityMax', '')
+      this.$set(row, 'quantity', '')
+    },
+    getInputFocus(event) {
+      event.currentTarget.select();
+    },
+  }
+}
+</script>
+
+<style scoped>
+
+</style>

+ 82 - 0
src/views/food/components/NutrientQuantity.vue

@@ -0,0 +1,82 @@
+<template>
+  <div v-if="edit">
+    <el-radio v-model="data.radio" :label="0" @change="radioChange(data)">值</el-radio>
+    <el-radio v-model="data.radio" :label="1" @change="radioChange(data)">范围</el-radio>
+    <el-radio v-model="data.radio" :label="2" @change="radioChange(data)">误差</el-radio>
+    <div v-if="data.radio === 1" style="display: inline-block">
+      大于等于:
+      <el-input v-model="data.quantityMin" @focus="getInputFocus" />
+      小于等于:
+      <el-input v-model="data.quantityMax" @focus="getInputFocus" />
+    </div>
+    <div v-else-if="data.radio === 2" style="display: inline-block">
+      基准:
+      <el-input v-model="data.quantity" @focus="getInputFocus" />
+      ±:
+      <el-input v-model="data.stdError" @focus="getInputFocus" />
+    </div>
+    <el-input
+      v-else
+      v-model="data.quantity"
+      style="width: 80px;"
+      class="filter-item"
+      @focus="getInputFocus"
+    />
+  </div>
+  <div v-else>
+    <span>{{ data | nutrientQuantityFilter }}</span>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'NutrientQuantity',
+  props: {
+    data: { type: Object, default: {} },
+    edit: { type: Boolean, default: false }
+  },
+  filters: {
+    nutrientQuantityFilter(data) {
+      if (data.stdError) {
+        return `${data.quantity} ± ${data.stdError}`
+      }else if (data.quantityMin && data.quantityMax) {
+        return `${data.quantityMin} ~ ${data.quantityMax}`
+      } else if (data.quantityMin) {
+        return `≥${data.quantityMin}`
+      } else if (data.quantityMax) {
+        return `≤${data.quantityMax}`
+      } else {
+        return data.quantity
+      }
+    }
+  },
+  methods: {
+    radioChange(data) {
+      this.$set(data, 'stdError', '')
+      this.$set(data, 'quantityMin', '')
+      this.$set(data, 'quantityMax', '')
+      this.$set(data, 'quantity', '')
+    },
+    getInputFocus(event) {
+      event.currentTarget.select();
+    },
+  },
+  watch: {
+    edit(value) {
+      if (value) {
+        if (this.data.quantityMax || this.data.quantityMin) {
+          this.$set(this.data, 'radio', 1)
+        } else if (this.data.stdError) {
+          this.$set(this.data, 'radio', 2)
+        } else {
+          this.$set(this.data, 'radio', 0)
+        }
+      }
+    }
+  }
+}
+</script>
+
+<style scoped>
+
+</style>

+ 81 - 0
src/views/food/components/NutrientUnit.vue

@@ -0,0 +1,81 @@
+<template>
+  <div v-if="edit">
+    <el-autocomplete
+      v-model="data.unit"
+      @input="handleRowUnitChanged(data)"
+      :fetch-suggestions="(query, cb) => {queryNutrientUnits(query, data.nutrientId, cb)}"
+      placeholder="单位关键词"
+    />
+    <el-select
+      clearable
+      v-show="showRowNutrientSource"
+      v-model="data.nutrientSource"
+      placeholder="请选择营养素来源"
+    >
+      <el-option v-for="item in nutrientSources" :key="item" :label="item" :value="item" />
+    </el-select>
+  </div>
+  <div v-else>
+    <span>{{ data.nutrientSource ? `${data.unit}(${data.nutrientSource})` : data.unit }}</span>
+  </div>
+</template>
+
+<script>
+import { getNutrientSources, getNutrientUnits } from '@/api/nutrient'
+
+// 特殊营养素 若单位不为baseUnit,则需要填写来源
+const SPECIAL_NUTRIENT_NAMES = ['维生素A', '维生素D', '维生素E', '烟酸', '叶酸']
+
+export default {
+  name: 'NutrientUnit',
+  props: {
+    data: { type: Object, default: {} },
+    edit: { type: Boolean, default: false }
+  },
+  data() {
+    return {
+      nutrientSources: [],
+      showRowNutrientSource: false
+    }
+  },
+  methods: {
+    handleRowUnitChanged(data) {
+      if (SPECIAL_NUTRIENT_NAMES.indexOf(data.nutrientName) > -1) {
+        getNutrientSources(data.nutrientId, { unit: data.unit }).then(res => {
+          this.nutrientSources = res.data
+          if (this.nutrientSources.length > 0){
+            if (!data.nutrientSource) {
+              data.nutrientSource = this.nutrientSources[0]
+            }
+            this.showRowNutrientSource = true
+          } else {
+            this.showRowNutrientSource = false
+            data.nutrientSource = null
+          }
+        })
+      } else {
+        this.showRowNutrientSource = false
+        data.nutrientSource = null
+      }
+    },
+    queryNutrientUnits(query, nutrientId, cb) {
+      let units = []
+      getNutrientUnits(nutrientId, { query }).then(res => {
+        res.data.forEach(item => units.push({ value: item }))
+        cb(units)
+      })
+    },
+  },
+  watch: {
+    edit(value) {
+      if (value) {
+        this.handleRowUnitChanged(this.data)
+      }
+    }
+  }
+}
+</script>
+
+<style scoped>
+
+</style>

+ 54 - 59
src/views/food/nutrient.vue

@@ -116,6 +116,24 @@
           @click="handleImport">
           导入营养素
         </el-button>
+        <el-button
+          class="filter-item"
+          style="margin-left: 10px;"
+          type="success"
+          :disabled="!canEdit"
+          v-if="!editAll"
+          @click="handleMultiEdit">
+          批量编辑
+        </el-button>
+        <el-button
+          class="filter-item"
+          style="margin-left: 10px;"
+          type="primary"
+          :disabled="!canEdit"
+          v-else
+          @click="submitMulti">
+          批量提交
+        </el-button>
       </el-row>
     </div>
 
@@ -137,57 +155,17 @@
       </el-table-column>
       <el-table-column label="营养素计量" align="center" :width="150">
         <template slot-scope="{row}">
-          <template v-if="row.edit">
-            <el-radio v-model="row.radio" :label="0" @change="radioChange(row)">值</el-radio>
-            <el-radio v-model="row.radio" :label="1" @change="radioChange(row)">范围</el-radio>
-            <el-radio v-model="row.radio" :label="2" @change="radioChange(row)">误差</el-radio>
-            <div v-if="row.radio === 1" style="display: inline-block">
-              大于等于:
-              <el-input v-model="row.quantityMin" @focus="getInputFocus" />
-              小于等于:
-              <el-input v-model="row.quantityMax" @focus="getInputFocus" />
-            </div>
-            <div v-else-if="row.radio === 2" style="display: inline-block">
-              基准:
-              <el-input v-model="row.quantity" @focus="getInputFocus" />
-              ±:
-              <el-input v-model="row.stdError" @focus="getInputFocus" />
-            </div>
-            <el-input
-              v-else
-              v-model="row.quantity"
-              style="width: 80px;"
-              class="filter-item"
-              @focus="getInputFocus"
-            />
-          </template>
-          <span v-else>{{ row | nutrientQuantityFilter }}</span>
+          <nutrient-quantity :data="row" :edit="editAll || row.edit" />
         </template>
       </el-table-column>
       <el-table-column label="计量单位" align="center" width="150">
         <template slot-scope="{row}">
-          <template v-if="row.edit">
-            <el-autocomplete
-              v-model="row.unit"
-              @input="handleRowUnitChanged(row)"
-              :fetch-suggestions="(query, cb) => {queryNutrientUnits(query, row.nutrientId, cb)}"
-              placeholder="单位关键词"
-            />
-            <el-select
-              clearable
-              v-show="showRowNutrientSource"
-              v-model="row.nutrientSource"
-              placeholder="请选择营养素来源"
-            >
-              <el-option v-for="item in nutrientSources" :key="item" :label="item" :value="item" />
-            </el-select>
-          </template>
-          <span v-else>{{ row.nutrientSource ? `${row.unit}(${row.nutrientSource})` : row.unit }}</span>
+          <nutrient-unit :data="row" :edit="editAll || row.edit" />
         </template>
       </el-table-column>
       <el-table-column label="NRV%" align="center" width="80">
         <template slot-scope="{row}">
-          <template v-if="row.edit">
+          <template v-if="row.edit || editAll">
             <el-input v-show="!isPercentByVolumeUnit(row)" v-model="row.nrvPercent"/>
           </template>
           <span v-else>{{ row.nrvPercent }}</span>
@@ -195,7 +173,7 @@
       </el-table-column>
       <el-table-column label="Nv_Spec" align="center" width="80">
         <template slot-scope="{row}" v-if="!isPercentByVolumeUnit(row)">
-          <template v-if="row.edit">
+          <template v-if="row.edit || editAll">
             <el-input v-model="row.nvSpec" class="filter-item" @focus="getInputFocus" />
           </template>
           <span v-else>{{ row.nvSpec }}</span>
@@ -203,7 +181,7 @@
       </el-table-column>
       <el-table-column label="计量单位" align="center" width="150">
         <template slot-scope="{row}" v-if="!isPercentByVolumeUnit(row)">
-          <template v-if="row.edit">
+          <template v-if="row.edit || editAll">
             <el-autocomplete v-model="row.nvSpecUnit" :fetch-suggestions="queryUnits" placeholder="单位关键词" />
           </template>
           <span v-else>{{ row.nvSpecUnit }}</span>
@@ -211,7 +189,7 @@
       </el-table-column>
       <el-table-column label="信息来源" align="center" width="200">
         <template slot-scope="{row}">
-          <template v-if="row.edit">
+          <template v-if="row.edit || editAll">
             <el-autocomplete
               v-model="row.source"
               :fetch-suggestions="querySources"
@@ -223,13 +201,13 @@
       </el-table-column>
       <el-table-column label="信息来源备注" align="center" width="200">
         <template slot-scope="{row}">
-          <template v-if="row.edit">
+          <template v-if="row.edit || editAll">
             <el-input type="text" :rows="2" v-model="row.sourceNote" @focus="getInputFocus" />
           </template>
           <span v-else>{{ row.sourceNote }}</span>
         </template>
       </el-table-column>
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="320" fixed="right">
+      <el-table-column v-if="!editAll" label="操作" align="center" class-name="small-padding fixed-width" width="350" fixed="right">
         <template slot-scope="{row}">
           <template v-if="row.edit">
             <el-button
@@ -280,10 +258,10 @@
         </el-form-item>
       </el-form>
       <div slot="footer" class="dialog-footer">
-        <el-button @click="dialogFormVisible = false">
+        <el-button v-if="!editAll" @click="dialogFormVisible = false">
           取消
         </el-button>
-        <el-button type="primary" @click="submitImport">
+        <el-button v-if="!editAll" type="primary" @click="submitImport">
           提交
         </el-button>
       </div>
@@ -294,19 +272,21 @@
 <script>
 import { getNutrientList, addFoodNutrient, updateFoodNutrient, removeFoodNutrient,
   updateFoodNutrientSort, confirmDeleteFoodNutrient, importNutrientsFromTemplate,
-  getList as getFoodList, importNutrientFromSimilarFood, getDetail } from '@/api/food'
+  getList as getFoodList, importNutrientFromSimilarFood, getDetail, multiUpdateNutrients } from '@/api/food'
 import FloatingWindow from '@/components/FloatingWindow'
 import { getList, getNutrientUnits, getNutrientSources } from '@/api/nutrient'
 import { getList as getUnits } from '@/api/unit'
 import { getNutrientTemplates } from '@/api/nutrientTemplate'
 import store from '@/store'
+import NutrientQuantity from '@/views/food/components/NutrientQuantity'
+import NutrientUnit from '@/views/food/components/NutrientUnit'
 
 // 特殊营养素 若单位不为baseUnit,则需要填写来源
 const SPECIAL_NUTRIENT_NAMES = ['维生素A', '维生素D', '维生素E', '烟酸', '叶酸']
 
 export default {
   name: 'AddNutrient',
-  components: { FloatingWindow },
+  components: { FloatingWindow, NutrientQuantity, NutrientUnit },
   mounted() {
     window.addEventListener('scroll', this.initHeight);
   },
@@ -357,15 +337,20 @@ export default {
       showRowNutrientSource: false,
       nutrientSources: [],
       showNRV: false,
-      canEdit: true
+      canEdit: true,
+      editAll: false
     }
   },
   methods: {
     fetchData() {
       this.listLoading = true
+      getDetail(this.foodId).then(res => {
+        if (!store.getters.isAdmin && res.data.userId !== store.getters.userId) {
+          this.canEdit = false
+        }
+      })
       getNutrientList(this.foodId).then(res => {
         this.list = res.data
-        this.listLoading = false
         if (this.list.length > 0) {
           this.$set(this.params, "nvSpec", this.list[0].nvSpec)
           this.$set(this.params, "nvSpecUnit", this.list[0].nvSpecUnit)
@@ -373,12 +358,13 @@ export default {
           this.$set(this.params, 'nvSpec', 100)
           this.$set(this.params, 'nvSpecUnit', '克')
         }
+
+        this.resetParams()
       })
-      getDetail(this.foodId).then(res => {
-        if (!store.getters.isAdmin && res.data.userId !== store.getters.userId) {
-          this.canEdit = false
-        }
-      })
+    },
+    resetParams() {
+      this.listLoading = false
+      this.editAll = false
     },
     addNutrient() {
       this.params.foodId = this.foodId
@@ -508,6 +494,15 @@ export default {
       this.queryImportItems()
       this.dialogFormVisible = true
     },
+    handleMultiEdit() {
+      this.editAll = !this.editAll
+    },
+    submitMulti() {
+      multiUpdateNutrients(this.foodId, this.list).then(res => {
+        this.fetchData()
+        this.$notify.success('提交成功')
+      })
+    },
     handleImportTypeChange() {
       this.importId = ''
       this.importItems = []

+ 0 - 0
src/views/food/utils/index.js