Bläddra i källkod

修改食物功能

sh 4 år sedan
förälder
incheckning
59ea563a04

+ 2 - 0
.env.development

@@ -8,3 +8,5 @@ VUE_APP_BASE_API = ''
 
 # h5 url
 VUE_APP_H5_URL = 'http://localhost/static-web/pages/feuc-test'
+
+static_path = './'

+ 2 - 0
.env.production

@@ -7,3 +7,5 @@ VUE_APP_BASE_API = ''
 
 # h5 url
 VUE_APP_H5_URL = 'https://h5.liveplus.online/static-web/feuc'
+
+static_path = 'https://liveplus-static.oss-cn-beijing.aliyuncs.com/feuc/prod'

+ 2 - 0
.env.test

@@ -7,3 +7,5 @@ VUE_APP_BASE_API = ''
 
 # h5 url
 VUE_APP_H5_URL = 'http://h5.liveplus.online/static-web/feuc-test'
+
+static_path = 'https://liveplus-static.oss-cn-beijing.aliyuncs.com/feuc/test'

+ 7 - 0
aliyun-oss-config.js

@@ -0,0 +1,7 @@
+module.exports = {
+  region: 'oss-cn-beijing',
+  accessKeyId: 'LTAI5tEoYCxusAdyByFWNTXz',
+  accessKeySecret: 'fuwL4GmjzDhZYyVEasG0dQOvlReDbQ',
+  bucket: 'liveplus-static',
+  path: 'feuc/test'
+}

+ 48 - 0
deploy-to-oss.js

@@ -0,0 +1,48 @@
+const ALIOSS = require('ali-oss')
+const WebpackAliyunOSS = require("webpack-aliyun-oss")
+
+const OSSCFG = require('./aliyun-oss-config')
+
+const aliyunOSSClient = new ALIOSS({
+  region: OSSCFG.region,
+  accessKeyId: OSSCFG.accessKeyId,
+  accessKeySecret: OSSCFG.accessKeySecret,
+  bucket: OSSCFG.bucket
+});
+
+async function deleteFile(filename) {
+  await aliyunOSSClient.delete(filename)
+}
+
+async function deleteOldFiles() {
+  let result = await aliyunOSSClient.list({
+    "max-keys": 1000
+  })
+  result.objects && result.objects.forEach(obj => {
+    deleteFile(obj.name)
+  })
+}
+
+deleteOldFiles()
+
+new WebpackAliyunOSS({
+  from: ['./dist/**', '!./dist/**/*.html'],
+  dist: '/',
+  region: OSSCFG.region,
+  deletOrigin: false,
+  accessKeyId: OSSCFG.accessKeyId,
+  accessKeySecret: OSSCFG.accessKeySecret,
+  bucket: OSSCFG.bucket,
+  setOssPath: filePath => {
+    let index = filePath.lastIndexOf('dist')
+    let path = filePath.substring(index + 4, filePath.length)
+    return OSSCFG.path + '/' + path.replace(/\\/g, '/')
+  },
+  setHeaders(filePath) {
+    // some operations to filePath
+    return {
+      'Cache-Control': 'max-age=31536000',
+      'Access-Control-Allow-Origin': '*'
+    }
+  }
+}).apply()

+ 2 - 1
package.json

@@ -53,7 +53,8 @@
     "serve-static": "1.13.2",
     "svg-sprite-loader": "4.1.3",
     "svgo": "1.2.2",
-    "vue-template-compiler": "2.6.10"
+    "vue-template-compiler": "2.6.10",
+    "webpack-aliyun-oss": "^0.5.2"
   },
   "browserslist": [
     "> 1%",

+ 6 - 0
public/index.html

@@ -62,5 +62,11 @@
 .el-card__body {
   padding: 15px 5px 5px 5px;
 }
+.el-input-group__append, .el-input-group__prepend {
+  padding: 0 5px;
+}
+.el-input__inner {
+  padding: 0 8px;
+}
 </style>
 </html>

+ 27 - 0
src/api/fn.js

@@ -0,0 +1,27 @@
+export function moveUp(list, index) {
+  if (index == 0) {
+    return
+  }
+  const item = list[index]
+  list.splice(index, 1)
+  list.splice(index - 1, 0, item)
+}
+
+export function moveDown(list, index) {
+  if (index == list.length - 1) {
+    return
+  }
+  const item = list[index]
+  list.splice(index, 1)
+  list.splice(index + 1, 0, item)
+}
+
+export function remove(list, index) {
+  list.splice(index, 1)
+}
+
+export default {
+  moveUp,
+  moveDown,
+  remove
+}

+ 30 - 6
src/views/components/DataSelect/index.vue

@@ -2,15 +2,17 @@
   <span>
     <el-select
       v-model="selectValue"
+      size="mini"
       filterable
       remote
       :placeholder="placeholder||''"
       :remote-method="search"
-      size="mini"
-      style="width:100%"
-      clearable
+      :style="`width:${width||'100%'}`"
+      :allow-create="allowCreate"
+      :clearable="clearable"
       @change="onChange">
       <el-option v-if="!!value&&!!label&&!options.find(v=>v.value==value)" :key="value" :label="label" :value="value" />
+      <el-option v-for="item in initOptions" :key="item.value" :label="item.label" :value="item.value" />
       <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
     </el-select>
   </span>
@@ -36,6 +38,24 @@ export default {
     label: {
       type: String,
       required: false
+    },
+    width: {
+      type: String,
+      default: ''
+    },
+    allowCreate: {
+      type: Boolean,
+      default: false
+    },
+    clearable: {
+      type: Boolean,
+      default: true
+    },
+    initOptions: {
+      type: Array,
+      default() {
+        return []
+      }
     }
   },
   watch: {
@@ -62,7 +82,7 @@ export default {
       if (!!!this.url) {
         return
       }
-      fGet(this.url, { name: query || '' }).then(res => {
+      fGet(this.url, { name: query || '', limit: 20 }).then(res => {
         this.options = res.data.map(v => {
           return {
             value: v.id,
@@ -80,8 +100,12 @@ export default {
           this.$emit('update:label', data.label)
           this.$emit('select', data)
         } else {
-          this.$emit('update:label', data.label)
-          this.$emit('select', data)
+          this.$emit('update:label', this.selectValue)
+          this.$emit('select', {
+            label: this.selectValue,
+            value: this.selectValue,
+            _data: {}
+          })
         }
         return
       }

+ 453 - 92
src/views/food/index.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="app-container">
     <div class="filter-container">
-      <el-select v-model="list.main.query.baseUnit" class="filter-item" size="mini" placeholder="食物类型" style="width:150px;margin-right:5px;" clearable>
+      <!-- <el-select v-model="list.main.query.baseUnit" class="filter-item" size="mini" placeholder="食物类型" style="width:150px;margin-right:5px;" clearable>
         <el-option label="是" :value="true" />
         <el-option label="否" :value="false" />
       </el-select>
@@ -14,7 +14,7 @@
       <el-select v-model="list.main.query.baseUnit" class="filter-item" size="mini" placeholder="状态" style="width:150px;margin-right:5px;" clearable>
         <el-option label="是" :value="true" />
         <el-option label="否" :value="false" />
-      </el-select>
+      </el-select> -->
       <el-button class="filter-item" size="mini" type="primary" @click="M.list()">查询</el-button>
       <el-button class="filter-item" size="mini" @click="() => {M.reset({ data: { page: 1, limit: list.main.query.limit } })}">重置</el-button>
 
@@ -23,11 +23,11 @@
       </div>
     </div>
     <el-table v-loading="list.main.loading" :data="list.main.list" border fit highlight-current-row style="width:100%" :max-height="maxHeight">
-      <el-table-column width="50" header-align="center" label="权重">
+      <!-- <el-table-column width="50" header-align="center" label="权重">
         <template slot-scope="{row}">
           <span>{{ row.sortOrder }}</span>
         </template>
-      </el-table-column>
+      </el-table-column> -->
       <el-table-column width="70" align="center" label="图片">
         <template slot-scope="{row}">
           <el-image v-if="row.mainImage" style="width:50px;height:50px;" :src="row.mainImage" fit="contain" />
@@ -35,7 +35,7 @@
       </el-table-column>
       <el-table-column min-width="150" header-align="center" label="名称">
         <template slot-scope="{row}">
-          <el-tag size="mini" effect="plain">类型</el-tag><span>{{ row.name }}</span>
+          <el-tag v-if="!!row.typeName" size="mini" effect="plain">{{ row.typeName }}</el-tag><span>{{ row.name }}</span>
         </template>
       </el-table-column>
       <el-table-column min-width="180" header-align="center" label="英文名称">
@@ -95,39 +95,133 @@
     </el-table>
     <pagination v-show="list.main.total>0" :total="list.main.total" :page.sync="list.main.query.page" :limit.sync="list.main.query.limit" @pagination="M.list()" />
 
-    <el-dialog :title="dlg.form.title" :visible.sync="dlg.form.visible" width="80%" top="3vh">
+    <el-dialog :title="dlg.form.title" :visible.sync="dlg.form.visible" width="95%" top="3vh">
       <el-form ref="form" :rules="dlg.form.rules" :model="dlg.form.data" size="mini" label-position="right" label-width="100px">
-        <el-tabs v-model="dlg.form.infoTab">
+        <el-tabs v-model="dlg.form.infoTab" @tab-click="foodInfoTabClick">
           <el-tab-pane label="食物基本信息" name="base">
-            <el-form-item label="主/辅材" prop="category">
-              <el-input v-model="dlg.form.data.category" placeholder="请输入单位类别" />
-            </el-form-item>
-            <el-form-item label="食物类别" prop="name">
-              <el-input v-model="dlg.form.data.name" placeholder="请输入单位名称,不能重复" />
-            </el-form-item>
-            <el-form-item label="名称" prop="name">
-              <el-input v-model="dlg.form.data.name" placeholder="请输入单位名称,不能重复" />
-            </el-form-item>
+            <el-row :gutter="10">
+              <el-col :span="6">
+                <el-form-item label="名称" prop="name">
+                  <el-input v-model="dlg.form.data.name" placeholder="请输入食物名称,不能重复" />
+                </el-form-item>
+              </el-col>
+              <el-col :span="6">
+                <el-form-item label="主/辅料" prop="type">
+                  <el-select v-model="dlg.form.data.type" class="filter-item" size="mini" placeholder="请选择主/辅料" style="width:100%;">
+                    <el-option label="主料" value="MAIN" />
+                    <el-option label="辅料" value="SUB" />
+                  </el-select>
+                </el-form-item>
+              </el-col>
+              <el-col :span="6">
+                <el-form-item label="食物形态">
+                  <el-select v-model="dlg.form.data.som" class="filter-item" size="mini" placeholder="请选择食物形态" style="width:70%;">
+                    <el-option label="固态" value="SOLID" />
+                    <el-option label="液态" value="LIQUID" />
+                  </el-select>
+                  <el-checkbox v-model="dlg.form.data.isGranular" style="float:right;">颗粒状</el-checkbox>
+                </el-form-item>
+              </el-col>
+              <el-col :span="6">
+                <el-form-item label="食物类别">
+                  <el-input v-model="dlg.form.data.categoryId" placeholder="请选择食物类别" />
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row :gutter="10">
+              <el-col :span="6">
+                <el-form-item label="可食部">
+                  <el-input v-model="dlg.form.data.ep" :min="0" :max="100" placeholder="可食部(0~100%)">
+                    <span slot="append">%</span>
+                  </el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="6">
+                <el-form-item label="[计算]可食部">
+                  <el-input v-model="dlg.form.data.calcEp" :min="0" :max="100" placeholder="计算用可食部(0~100%)">
+                    <span slot="append">%</span>
+                  </el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="6">
+                <el-form-item label="GI">
+                  <el-input v-model="dlg.form.data.gi" placeholder="请输入GI" />
+                </el-form-item>
+              </el-col>
+              <el-col :span="6">
+                <el-form-item label="GL">
+                  <el-input v-model="dlg.form.data.gl" placeholder="请输入GL" />
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row :gutter="10">
+              <el-col :span="8">
+                <el-form-item label="密度">
+                  <el-input v-model="dlg.form.data.densityAmt" placeholder="密度" style="width:60px;" />
+                  <DataSelect
+                    url="/api/units"
+                    placeholder="密度单位"
+                    :value.sync="dlg.form.data.densityUnitId"
+                    :label.sync="dlg.form.data.densityUnit"
+                    width="130px;margin-left:1px;"
+                  />
+                  <span style="color:red;font-size:14px;font-weight:700;">&nbsp;=&nbsp;</span>
+                  <el-input v-model="dlg.form.data.densityVolumeAmt" placeholder="体积" style="width:60px;" />
+                  <DataSelect
+                    url="/api/units"
+                    placeholder="体积单位"
+                    :value.sync="dlg.form.data.densityVolumeUnitId"
+                    :label.sync="dlg.form.data.densityVolumeUnit"
+                    width="130px;margin-left:1px;"
+                  />
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="堆密度">
+                  <el-input v-model="dlg.form.data.bulkDensityAmt" placeholder="堆密度" style="width:60px;" />
+                  <DataSelect
+                    url="/api/units"
+                    placeholder="堆密度单位"
+                    :value.sync="dlg.form.data.bulkDensityUnitId"
+                    :label.sync="dlg.form.data.bulkDensityUnit"
+                    width="130px;margin-left:1px;"
+                  />
+                  <span style="color:red;font-size:14px;font-weight:700;">&nbsp;=&nbsp;</span>
+                  <el-input v-model="dlg.form.data.bulkDensityVolumeAmt" placeholder="体积" style="width:60px;" />
+                  <DataSelect
+                    url="/api/units"
+                    placeholder="体积单位"
+                    :value.sync="dlg.form.data.bulkDensityVolumeUnitId"
+                    :label.sync="dlg.form.data.bulkDensityVolumeUnit"
+                    width="130px;margin-left:1px;"
+                  />
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="[计算]密度">
+                  <el-input v-model="dlg.form.data.calcDensityAmt" placeholder="密度" style="width:60px;" />
+                  <DataSelect
+                    url="/api/units"
+                    placeholder="密度单位"
+                    :value.sync="dlg.form.data.calcDensityUnitId"
+                    :label.sync="dlg.form.data.calcDensityUnit"
+                    width="130px;margin-left:1px;"
+                  />
+                  <span style="color:red;font-size:14px;font-weight:700;">&nbsp;=&nbsp;</span>
+                  <el-input v-model="dlg.form.data.calcDensityVolumeAmt" placeholder="体积" style="width:60px;" />
+                  <DataSelect
+                    url="/api/units"
+                    placeholder="体积单位"
+                    :value.sync="dlg.form.data.calcDensityVolumeUnitId"
+                    :label.sync="dlg.form.data.calcDensityVolumeUnit"
+                    width="130px;margin-left:1px;"
+                  />
+                </el-form-item>
+              </el-col>
+            </el-row>
             <el-form-item label="描述">
               <el-input v-model="dlg.form.data.code" type="textarea" rows="3" placeholder="请输入单位编码,可为空,但不能重复" />
             </el-form-item>
-            <el-form-item v-if="!dlg.form.data.baseUnit" label="可食部" required>
-              <el-input v-model="dlg.form.data.ratio" placeholder="百分比">
-                <span slot="append">%</span>
-              </el-input>
-            </el-form-item>
-            <el-form-item label="GI">
-              <el-input v-model="dlg.form.data.name" placeholder="请输入单位名称,不能重复" />
-            </el-form-item>
-            <el-form-item label="GL">
-              <el-input v-model="dlg.form.data.name" placeholder="请输入单位名称,不能重复" />
-            </el-form-item>
-            <el-form-item label="密度">
-              <el-input v-model="dlg.form.data.name" placeholder="请输入单位名称,不能重复" />
-            </el-form-item>
-            <el-form-item label="堆密度">
-              <el-input v-model="dlg.form.data.name" placeholder="请输入单位名称,不能重复" />
-            </el-form-item>
             <el-form-item label="食物图">
             </el-form-item>
             <el-form-item label="营养素图">
@@ -137,60 +231,200 @@
           </el-tab-pane>
           <el-tab-pane label="规格" name="modifier">
             <div style="margin-bottom:5px;">
-              <el-button size="mini" type="primary" plain>添加</el-button>
+              <el-button size="mini" type="primary" plain @click="addModifier(dlg.form.data)">添加</el-button>
             </div>
-            <el-table :data="tempList" :show-header="true" border fit highlight-current-row style="width:100%">
+            <el-table :data="dlg.form.data.modifiers" :show-header="false" border fit highlight-current-row style="width:100%">
               <el-table-column type="index" width="50" align="center" />
-              <el-table-column label="包装名称" width="70" align="center">
-                <el-input size="mini" />
-              </el-table-column>
-              <el-table-column label="包装单位" width="70" align="center">
-                <el-select size="mini" style="width:100%;">
-                </el-select>
-              </el-table-column>
-              <el-table-column label="CNVR" width="70" align="center">
-                <el-input size="mini" />
-              </el-table-column>
-              <el-table-column label="规格转换" width="180" align="center">
-                <el-input size="mini">
-                  <span slot="prepend">1随身包装=</span>
-                </el-input>
-              </el-table-column>
-              <el-table-column label="净含量" width="70" align="center">
-                <el-input size="mini" />
-              </el-table-column>
-              <el-table-column label="状态" width="70" align="center">
-                <el-input size="mini" />
-              </el-table-column>
-              <el-table-column label="卡尺" width="70" align="center">
-                <el-input size="mini" />
-              </el-table-column>
-              <el-table-column label="规格图片" width="70" align="center">
+              <el-table-column>
+                <template slot-scope="{row}">
+                  <span v-if="row._edit">
+                    <el-input v-model="row.name" placeholder="规格名称" style="width:130px;margin-right:5px;" @change="modifierUnitChange" />
+                    <DataSelect
+                      url="/api/units"
+                      placeholder="规格单位"
+                      :value.sync="row.unitId"
+                      :label.sync="row.unitName"
+                      width="100px"
+                      :allowCreate="true"
+                      @select="modifierUnitChange"
+                    />
+                    [
+                      <span style="color:blue;font-size:13px;">&nbsp;规格转换:&nbsp;</span>
+                      <el-input v-model="row.toModifierInput" placeholder="数量" style="width:60px;" />
+                      <span>{{ row.key || '' }}</span>
+                      <span style="color:red;font-size:14px;font-weight:700;">&nbsp;=&nbsp;</span>
+                      <el-input v-model="row.toModifierAmt" placeholder="数量" style="width:60px;margin-right:10px;" />
+                      <el-select v-model="row.toModifierName" placeholder="规格单位" style="width:120px" clearable>
+                        <el-option v-for="opt in dlg.form.modifierUnitOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
+                      </el-select>
+                    ]
+                    [
+                      <span style="color:blue;font-size:13px;">&nbsp;标准单位转换:&nbsp;</span>
+                      <el-input v-model="row.stdMeasureInput" placeholder="数量" style="width:60px;" />
+                      <span>{{ row.key || '' }}</span>
+                      <span style="color:red;font-size:14px;font-weight:700;">&nbsp;=&nbsp;</span>
+                      <el-input v-model="row.stdMeasureAmt" placeholder="数量" style="width:60px;margin-right:10px;" />
+                      <DataSelect
+                        url="/api/units"
+                        placeholder="标准单位"
+                        :value.sync="row.stdMeasureUnitId"
+                        :label.sync="row.stdMeasureUnit"
+                        width="90px"
+                      />
+                    ]
+                    [
+                      <span style="color:blue;font-size:13px;">&nbsp;推荐量:&nbsp;</span>
+                      <el-input v-model="row.inInit" placeholder="数量" style="width:60px;" />
+                      <DataSelect
+                        url="/api/units"
+                        placeholder="推荐量单位"
+                        :value.sync="row.inInitUnitId"
+                        :label.sync="row.inInitUnit"
+                        :initOptions="dlg.form.modifierUnitOptions"
+                        width="90px"
+                      />
+                    ]
+                  </span>
+                  <span v-else>
+                    -
+                  </span>
+                </template>
               </el-table-column>
-              <el-table-column width="70" align="center">
+              <el-table-column width="90" align="center">
+                <template slot-scope="{$index}">
+                  <i class="el-icon-delete" style="cursor:pointer;color:#999999;margin-right:5px;" @click="fn.remove(dlg.form.data.modifiers, $index)"></i>
+                  &nbsp;&nbsp;
+                  <i class="el-icon-top" style="cursor:pointer;color:#999999;margin-right:5px;" @click="fn.moveUp(dlg.form.data.modifiers, $index)"></i>
+                  &nbsp;&nbsp;
+                  <i class="el-icon-bottom" style="cursor:pointer;color:#999999;" @click="fn.moveDown(dlg.form.data.modifiers, $index)"></i>
+                </template>
               </el-table-column>
             </el-table>
           </el-tab-pane>
           <el-tab-pane label="营养素" name="nutrient">
-            <el-table :data="tempList" :show-header="false" border fit highlight-current-row style="width:100%">
+            <div style="margin-bottom:5px;">
+              <el-button size="mini" type="primary" plain @click="addNutrient(dlg.form.data)">添加</el-button>
+            </div>
+            <el-table :data="dlg.form.data.nutrients" :show-header="false" border fit highlight-current-row style="width:100%">
               <el-table-column type="index" width="50" align="center" />
               <el-table-column>
                 <template slot-scope="{row}">
-                  名称选择<br>
-                  计量方式<br>
-                  计量单位<br>
-                  转换关系<br>
-                  NVR(%)<br>
-                  nv_spec<br>
-                  nv_spec_unit<br>
-                  来源
+                  <span v-if="row._edit">
+                    <DataSelect
+                      url="/api/nutrients"
+                      placeholder="请选择营养素"
+                      width="130px;margin-right:5px;"
+                      :value.sync="row.nutrientId"
+                      :label.sync="row.nutrientName"
+                      @select="(nutrient) => nutrientSelect(nutrient, row)"
+                    />
+                    <el-select v-model="row.nvMeasureMode" size="mini" placeholder="计量" style="width:80px;margin-right:5px;">
+                      <el-option label="值" value="VALUE" />
+                      <el-option label="范围" value="RANGE" />
+                      <el-option label="误差" value="ADJUST" />
+                    </el-select>
+                    <span style="color:red;font-size:15px;font-weight:700;">(</span>
+                    <span v-if="row.nvMeasureMode=='VALUE'">
+                      <el-input v-model="row.nv" placeholder="取值" style="width:70px;margin-right:10px;" />
+                    </span>
+                    <span v-else-if="row.nvMeasureMode=='RANGE'">
+                      <el-input v-model="row.nvMin" placeholder="最小值" style="width:70px;margin-right:10px;" />
+                      -
+                      <el-input v-model="row.nvMax" placeholder="最大值" style="width:70px;margin-right:10px;" />
+                    </span>
+                    <span v-else-if="row.nvMeasureMode=='ADJUST'">
+                      <el-input v-model="row.nv" placeholder="取值" style="width:70px;margin-right:10px;" />
+                      <el-input v-model="row.nv_adjust" placeholder="误差" style="width:80px;margin-right:10px;">
+                        <span slot="prepend">±</span>
+                      </el-input>
+                    </span>
+                    <el-select v-model="row.nvUnitId" placeholder="营养素单位" style="width:100px" clearable>
+                      <el-option v-if="!!row.nvUnitId && row._nutrientUnitOptions && !row._nutrientUnitOptions.find(v => v.value == row.nvUnitId)" :key="row.nvUnitId" :label="row.nvUnit" :value="row.nvUnitId" />
+                      <el-option v-for="opt in row._nutrientUnitOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
+                    </el-select>
+                    <!-- <DataSelect
+                      url="/api/units"
+                      placeholder="营养素单位"
+                      :value.sync="row.nvUnitId"
+                      :label.sync="row.nvUnitName"
+                      :clearable="true"
+                      width="100px"
+                    /> -->
+                    <span style="color:red;font-weight:700;">&nbsp;/&nbsp;</span>
+                    <el-input v-model="row.nvSpec" placeholder="nv_spec" style="width:70px;margin-right:10px;" />
+                    <DataSelect
+                      url="/api/units"
+                      placeholder="nv_spec单位"
+                      :value.sync="row.nvSpecUnitId"
+                      :label.sync="row.nvSpecUnit"
+                      width="110px"
+                      :allowCreate="true"
+                      :initOptions="dlg.form.modifierUnitOptions"
+                    />
+                    <span style="color:red;font-size:15px;font-weight:700;">)</span>
+                    <!-- [
+                    <span style="color:green;font-weight:700;">1</span>&nbsp;<span style="color:red">{{ row.nvSpecUnit }}</span>
+                    &nbsp;*&nbsp;
+                    <el-input v-model="row.cfNvUnitToBaseUnit" style="width:80px;margin-right:5px;" />
+                    =&nbsp;*&nbsp; 1 {{ row.nutrient && row.nutrient.baseUnitName || '基础单位' }}
+                    ] -->
+                  </span>
+                  <span v-else>
+                  </span>
+                </template>
+              </el-table-column>
+              <el-table-column width="90" align="center">
+                <template slot-scope="{$index}">
+                  <i class="el-icon-delete" style="cursor:pointer;color:#999999;margin-right:5px;" @click="fn.remove(dlg.form.data.nutrients, $index)"></i>
+                  &nbsp;&nbsp;
+                  <i class="el-icon-top" style="cursor:pointer;color:#999999;margin-right:5px;" @click="fn.moveUp(dlg.form.data.nutrients, $index)"></i>
+                  &nbsp;&nbsp;
+                  <i class="el-icon-bottom" style="cursor:pointer;color:#999999;" @click="fn.moveDown(dlg.form.data.nutrients, $index)"></i>
                 </template>
               </el-table-column>
             </el-table>
           </el-tab-pane>
           <el-tab-pane label="CF" name="cf">
+            <el-table :data="dlg.form.data.cfs" border fit highlight-current-row style="width:100%">
+              <el-table-column type="index" width="50" align="center" />
+              <el-table-column min-width="180" header-align="center" label="源单位">
+                <template slot-scope="{row}">
+                  <span>{{ row.fromUnit }}</span>
+                </template>
+              </el-table-column>
+              <el-table-column min-width="180" header-align="center" label="转换后单位">
+                <template slot-scope="{row}">
+                  <span>{{ row.toUnit }}</span>
+                </template>
+              </el-table-column>
+              <el-table-column min-width="210" header-align="center" label="转换关系">
+                <template slot-scope="{row}">
+                  <span>1 {{ row.fromUnit }} * 
+                    <el-input v-model="row.cf" style="width:100px;margin-right:10px;" @blur="saveCf(row)" />
+                    =1 {{ row.toUnit }}</span>
+                </template>
+              </el-table-column>
+            </el-table>
           </el-tab-pane>
           <el-tab-pane label="营养素含量计算" name="calc">
+            <div>
+              <el-input v-model="calc.req.amt" placeholder="摄入量" style="width:100px;margin-right:10px;" />
+              <DataSelect
+                url="/api/units"
+                placeholder="摄入量单位"
+                :value.sync="calc.req.unitId"
+                :label.sync="calc.req.unitName"
+                :initOptions="dlg.form.modifierUnitOptions"
+                width="110px"
+              />
+              <el-button :loading="calc.loading" size="mini" type="success" style="margin-left:15px;" @click="calcNvIn">计算</el-button>
+              <span>
+                {{ calc.rsp.amt }}{{ calc.rsp.unitName }}
+              </span>
+            </div>
+            <div style="margin-top:5px;">
+              <p v-for="nv in calc.rsp.nvList" :key="nv.name">{{ nv.name }} 摄入:{{ nv.nvIn }}{{ nv.nvUnit }}, ({{ nv.nv }}{{ nv.nvUnit }}/{{ nv.nvSpec }}{{ nv.nvSpecUnit }})</p>
+            </div>
           </el-tab-pane>
         </el-tabs>
       </el-form>
@@ -198,8 +432,11 @@
         <el-button size="mini" @click="dlg.form.visible = false">
           取消
         </el-button>
+        <el-button :loading="dlg.form.saveLoading" size="mini" type="primary" @click="onlySave">
+          仅保存
+        </el-button>
         <el-button :loading="dlg.form.saveLoading" size="mini" type="primary" @click="M.save()">
-          确认
+          保存并退出
         </el-button>
       </div>
     </el-dialog>
@@ -208,24 +445,37 @@
 
 <script>
 import Pagination from '@/components/Pagination'
-import { fGet, fPost } from '@/api/rest'
+import { fGet, fPost, fSave } from '@/api/rest'
 import { M } from '@/api/op'
+import DataSelect from '@/views/components/DataSelect/index'
+import fn from '@/api/fn'
 
 export default {
-  components: { Pagination },
+  components: { Pagination, DataSelect },
   data() {
     return {
       M: new M(this),
+      fn,
       URI: '/api/foods',
       maxHeight: 600,
       baseUnitOptions: [],
-      tempList: [{},{}],
+      tempList: [{
+        _edit: true
+      },{}],
       list: {
         main: {
           loading: true,
           total: 0,
           list: [],
           render(row) {
+            row.modifiers = row.modifiers || []
+            row.nutrients = row.nutrients || []
+            row.modifiers && row.modifiers.forEach(v => v._edit = true)
+            row.nutrients && row.nutrients.forEach(v => {
+              v._edit = true
+              v._nutrientUnitOptions = []
+            })
+            row.cfs = row.cfs || []
             return row
           },
           query: {
@@ -234,15 +484,32 @@ export default {
           }
         }
       },
+      calc: {
+        loading: false,
+        req: {
+          amt: undefined,
+          unitId: undefined,
+          unitName: undefined
+        },
+        rsp: {
+          amt: undefined,
+          unitName: undefined,
+          nvList: []
+        }
+      },
       dlg: {
         form: {
-          infoTab: 'modifier',
+          infoTab: 'base',
           visible: false,
           title: '',
-          data: {},
+          data: {
+            modifiers: [],
+            nutrients: []
+          },
           saveLoading: false,
+          modifierUnitOptions: [],
           rules: {
-            category: [{ required: true, message: '类别不能为空', trigger: 'blur' }],
+            // type: [{ required: true, message: '请选择主/辅料', trigger: 'blur' }],
             name: [{ required: true, message: '名称不能为空', trigger: 'blur' }]
           }
         }
@@ -252,34 +519,128 @@ export default {
   created() {
     this.maxHeight = document.documentElement.clientHeight - 135
     this.M.list()
-    this.dlg.form.visible = true
   },
   methods: {
-    loadBaseUnit() {
-      fGet(this.URI, { baseUnit: true, size: 10000 }).then(res => {
-        this.baseUnitOptions = res.data.map(v => {
-          return {
-            label: v.name,
-            value: v.id
-          }
+    // 加载详细信息
+    loadDetail(id) {
+      fGet(`${this.URI}/${id}`).then(res => {
+        const detail = {
+          ...res
+        }
+        detail.modifiers && detail.modifiers.forEach(v => v._edit = true)
+        detail.nutrients && detail.nutrients.forEach(v => {
+          v._edit = true
+          v._nutrientUnitOptions = []
         })
+        this.dlg.form.data = detail
+        this.modifierUnitChange()
       })
     },
+    // 新增
     create() {
+      this.dlg.form.modifierUnitOptions = []
       this.M.create({ form: 'form', title: '新增', data: {} })
     },
+    // 编辑
     edit(row) {
+      this.dlg.form.modifierUnitOptions = []
       this.M.edit({ form: 'form', title: 'name', row: row })
+      this.loadDetail(row.id)
     },
-    baseUnitChange() {
-      if (!!this.dlg.form.data.baseUnitId) {
-        const baseUnit = this.baseUnitOptions.find(v => v.value == this.dlg.form.data.baseUnitId)
-        if (!!baseUnit) {
-          this.dlg.form.data.baseUnitName = baseUnit.label
+    // 规格单位列表生成
+    modifierUnitChange() {
+      const modifierUnitOptions = []
+      const modifierUnitInclude = {}
+      this.dlg.form.data.modifiers.forEach(modifier => {
+        if (!!(modifier.unitName) && modifier.unitName.trim().length > 0) {
+          const unitName = modifier.unitName || ''
+          const name = modifier.name || ''
+          modifier.key = (unitName == name ? unitName : `${unitName}${name}`)
+          modifierUnitOptions.push({
+            label: modifier.key,
+            value: modifier.key
+          })
+          modifierUnitInclude[modifier.key] = true
+        }
+      })
+      this.dlg.form.data.modifiers.forEach(modifier => {
+        if (!!(modifier.toModifierName) && !modifierUnitInclude[modifier.toModifierName]) {
+          modifier.toModifierId = undefined
+          modifier.toModifierName = undefined
         }
-      } else {
-        this.dlg.form.data.baseUnitName = undefined
+      })
+      this.dlg.form.modifierUnitOptions = modifierUnitOptions
+    },
+    // 添加规格
+    addModifier(row) {
+      row.modifiers.push({
+        _edit: true
+      })
+    },
+    // 删除规格
+    removeModifier(row, index) {
+      row.modifiers.splice(index, 1)
+    },
+    // 添加营养素
+    addNutrient(row) {
+      row.nutrients.push({
+        _edit: true,
+        _nutrientUnitOptions: []
+      })
+    },
+    // 删除营养素
+    removeNutrient(row, index) {
+      row.nutrients.splice(index, 1)
+    },
+    // 营养素选择
+    nutrientSelect(nutrient, row) {
+      row._nutrientUnitOptions = []
+      if (nutrient._data && nutrient._data.unitName) {
+        row._nutrientUnitOptions.push({
+          value: nutrient._data.unitId == 'CUSTOM_UNIT' ? nutrient._data.unitName : nutrient._data.unitId,
+          label: nutrient._data.unitName
+        })
+      }
+      if (nutrient._data && nutrient._data.optionUnits) {
+        nutrient._data.optionUnits.forEach(optionUnit => {
+          row._nutrientUnitOptions.push({
+            value: optionUnit.unitId == 'CUSTOM_UNIT' ? optionUnit.name : optionUnit.unitId,
+            label: optionUnit.name
+          })
+        })
       }
+    },
+    // 食物信息标签切换
+    foodInfoTabClick(tab) {
+    },
+    // 计算营养素摄入量
+    calcNvIn() {
+      this.calc.loading = true
+      fPost(`/api/foods/${this.dlg.form.data.id}`, this.calc.req).then(res => {
+        this.calc.rsp = res
+      }).finally(() => {
+        this.calc.loading = false
+      })
+    },
+    // 刷新 CF
+    refreshCf() {
+      fGet(`/api/foods/${this.dlg.form.data.id}/cfs`).then(res => {
+        this.dlg.form.data.cfs = res || []
+      })
+    },
+    // 保存 CF
+    saveCf(cf) {
+      fPost(`/api/foods/${this.dlg.form.data.id}/cfs`, cf)
+    },
+    // 仅保存
+    onlySave() {
+      this.dlg.form.saveLoading = true
+      fSave(this.URI, this.dlg.form.data).then(res => {
+        this.$message.success('保存成功')
+        this.refreshCf()
+      }).finally(() => {
+        this.dlg.form.saveLoading = false
+      })
     }
   }
 }

+ 98 - 33
src/views/nutrient/index.vue

@@ -4,7 +4,6 @@
       <el-input v-model="list.main.query.name" class="filter-item" size="mini" placeholder="名称" style="width:150px;margin-right:5px;" clearable />
       <el-input v-model="list.main.query.code" class="filter-item" size="mini" placeholder="编码" style="width:150px;margin-right:5px;" clearable />
       <el-input v-model="list.main.query.enName" class="filter-item" size="mini" placeholder="英文名称" style="width:150px;margin-right:5px;" clearable />
-      <DataSelect url="/api/units" class="filter-item" placeholder="基础单位" :value.sync="list.main.query.baseUnitId" style="width:150px;margin-right:5px;" />
       <DataSelect :url="URI" class="filter-item" placeholder="上级营养素" :value.sync="list.main.query.parentId" style="width:150px;margin-right:5px;" />
       <el-button class="filter-item" size="mini" type="primary" @click="M.list()">查询</el-button>
       <el-button class="filter-item" size="mini" @click="() => {M.reset({ data: { page: 1, limit: list.main.query.limit } })}">重置</el-button>
@@ -19,7 +18,7 @@
           <span>{{ row.name }}</span>
         </template>
       </el-table-column>
-      <el-table-column width="150" align="center" label="编码">
+      <el-table-column width="130" align="center" label="编码">
         <template slot-scope="{row}">
           <span>{{ row.code }}</span>
         </template>
@@ -31,7 +30,12 @@
       </el-table-column>
       <el-table-column width="110" align="center" label="基础单位">
         <template slot-scope="{row}">
-          {{ row.baseUnitName }}
+          {{ row.unitName }}
+        </template>
+      </el-table-column>
+      <el-table-column width="200" align="center" label="可选单位">
+        <template slot-scope="{row}">
+          {{ row.optionUnits && row.optionUnits.map(v => v.name).join(',') || '-' }}
         </template>
       </el-table-column>
       <el-table-column width="130" header-align="center" label="上级营养素">
@@ -49,21 +53,21 @@
           <span>{{ row.updateTime }}</span>
         </template>
       </el-table-column>
-      <el-table-column width="160" align="center" label="操作">
+      <el-table-column width="140" align="center" label="操作">
         <template slot-scope="{row}">
           <i class="el-icon-edit" style="cursor:pointer;color:#999999;margin-right:5px;" @click="edit(row)"></i>
-          &nbsp;&nbsp;
+          <!-- &nbsp;&nbsp;
           <i class="el-icon-delete" style="cursor:pointer;color:#999999;margin-right:5px;"></i>
           &nbsp;&nbsp;
           <i class="el-icon-top" style="cursor:pointer;color:#999999;margin-right:5px;"></i>
           &nbsp;&nbsp;
-          <i class="el-icon-bottom" style="cursor:pointer;color:#999999;"></i>
+          <i class="el-icon-bottom" style="cursor:pointer;color:#999999;"></i> -->
         </template>
       </el-table-column>
     </el-table>
     <pagination v-show="list.main.total>0" :total="list.main.total" :page.sync="list.main.query.page" :limit.sync="list.main.query.limit" @pagination="M.list()" />
 
-    <el-dialog :title="dlg.form.title" :visible.sync="dlg.form.visible" width="500px">
+    <el-dialog :title="dlg.form.title" :visible.sync="dlg.form.visible" width="700px">
       <el-form ref="form" :rules="dlg.form.rules" :model="dlg.form.data" size="mini" label-position="right" label-width="100px">
         <el-form-item label="名称" prop="name">
           <el-input v-model="dlg.form.data.name" placeholder="请输入营养素名称,不能重复" />
@@ -74,12 +78,13 @@
         <el-form-item label="英文名称">
           <el-input v-model="dlg.form.data.enName" placeholder="请输入营养素英文名称" />
         </el-form-item>
-        <el-form-item label="基础单位" prop="baseUnitId">
+        <el-form-item label="基础单位" prop="unitId">
           <DataSelect
             url="/api/units"
-            placeholder="请选择基础单位"
-            :value.sync="dlg.form.data.baseUnitId"
-            :label.sync="dlg.form.data.baseUnitName"
+            placeholder="请输入基础单位"
+            :value.sync="dlg.form.data.unitId"
+            :label.sync="dlg.form.data.unitName"
+            :allowCreate="true"
           />
         </el-form-item>
         <el-form-item label="上级单位">
@@ -90,6 +95,53 @@
             :label.sync="dlg.form.data.parentName"
           />
         </el-form-item>
+        <el-form-item label="可选单位">
+          <div style="margin-bottom:3px;">
+            <el-button type="primary" @click="addUnit" plain>添加</el-button>
+          </div>
+          <el-table :data="dlg.form.data.optionUnits" border fit highlight-current-row style="width:100%">
+            <el-table-column type="index" width="50" align="center" />
+            <el-table-column min-width="150" header-align="center" label="单位名称">
+              <template slot-scope="{row}">
+                <span v-if="row._edit">
+                  <DataSelect
+                    url="/api/units"
+                    placeholder="请输入单位"
+                    :value.sync="row.unitId"
+                    :label.sync="row.name"
+                    :allowCreate="true"
+                  />
+                </span>
+                <span v-else>{{ row.name }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column min-width="200" align="center" label="到基础单位转换关系">
+              <template slot-scope="{row}">
+                <span v-if="row._edit">
+                  <el-input v-model="row.cf" size="mini" placeholder="转换关系">
+                    <span slot="prepend">1{{ row.name || '单位' }}<b style="color:red;">*</b></span>
+                    <span slot="append">=1{{ dlg.form.data.unitName }}</span>
+                  </el-input>
+                </span>
+                <span v-else>
+                  1{{ row.name || '单位' }}<b style="color:red;">*</b>{{ row.cf }}=1{{ dlg.form.data.unitName }}
+                </span>
+              </template>
+            </el-table-column>
+            <el-table-column width="100" align="center" label="操作">
+            <template slot-scope="{$index,row}">
+              <i v-if="row._edit" class="el-icon-check" style="cursor:pointer;color:#999999;margin-right:5px;" @click="row._edit=false"></i>
+              <i v-else class="el-icon-edit" style="cursor:pointer;color:#999999;margin-right:5px;" @click="row._edit=true"></i>
+              &nbsp;&nbsp;
+              <i class="el-icon-delete" style="cursor:pointer;color:#999999;margin-right:5px;" @click="removeUnit($index)"></i>
+              &nbsp;&nbsp;
+              <i class="el-icon-top" style="cursor:pointer;color:#999999;margin-right:5px;" @click="upUnit($index)"></i>
+              &nbsp;&nbsp;
+              <i class="el-icon-bottom" style="cursor:pointer;color:#999999;" @click="downUnit($index)"></i>
+            </template>
+          </el-table-column>
+          </el-table>
+        </el-form-item>
       </el-form>
       <div slot="footer" class="dialog-footer">
         <el-button size="mini" @click="dlg.form.visible = false">
@@ -116,13 +168,21 @@ export default {
       M: new M(this),
       URI: '/api/nutrients',
       maxHeight: 600,
-      baseUnitOptions: [],
       list: {
         main: {
           loading: true,
           total: 0,
           list: [],
           render(row) {
+            if (row.unitId == 'CUSTOM_UNIT') {
+              row.unitId = row.unitName
+            }
+            row.optionUnits && row.optionUnits.forEach(v => {
+              if (v.unitId == 'CUSTOM_UNIT') {
+                v.unitId = v.name
+              }
+              v._edit = false
+            })
             return row
           },
           query: {
@@ -135,12 +195,14 @@ export default {
         form: {
           visible: false,
           title: '',
-          data: {},
+          data: {
+            optionUnits: []
+          },
           saveLoading: false,
           rules: {
             name: [{ required: true, message: '营养素名称不能为空', trigger: 'blur' }],
             code: [{ required: true, message: '营养素编码不能为空', trigger: 'blur' }],
-            baseUnitId: [{ required: true, message: '请选择基本单位', trigger: 'blur' }]
+            baseUnitName: [{ required: true, message: '营养素基本单位不能为空', trigger: 'blur' }]
           }
         }
       }
@@ -149,34 +211,37 @@ export default {
   created() {
     this.maxHeight = document.documentElement.clientHeight - 135
     this.M.list()
-    this.loadBaseUnit()
   },
   methods: {
-    loadBaseUnit() {
-      fGet(this.URI, { baseUnit: true, size: 10000 }).then(res => {
-        this.baseUnitOptions = res.data.map(v => {
-          return {
-            label: v.name,
-            value: v.id
-          }
-        })
-      })
-    },
     create() {
       this.M.create({ form: 'form', title: '新增', data: {} })
     },
     edit(row) {
       this.M.edit({ form: 'form', title: 'name', row: row })
     },
-    baseUnitChange() {
-      if (!!this.dlg.form.data.baseUnitId) {
-        const baseUnit = this.baseUnitOptions.find(v => v.value == this.dlg.form.data.baseUnitId)
-        if (!!baseUnit) {
-          this.dlg.form.data.baseUnitName = baseUnit.label
-        }
-      } else {
-        this.dlg.form.data.baseUnitName = undefined
+    addUnit() {
+      this.dlg.form.data.optionUnits.push({
+        _edit: true
+      })
+    },
+    removeUnit(index) {
+      this.dlg.form.data.optionUnits.splice(index, 1)
+    },
+    upUnit(index) {
+      if (index == 0) {
+        return
+      }
+      const item = this.dlg.form.data.optionUnits[index]
+      this.dlg.form.data.optionUnits.splice(index, 1)
+      this.dlg.form.data.optionUnits.splice(index - 1, 0, item)
+    },
+    downUnit(index) {
+      if (index == this.dlg.form.data.optionUnits.length - 1) {
+        return
       }
+      const item = this.dlg.form.data.optionUnits[index]
+      this.dlg.form.data.optionUnits.splice(index, 1)
+      this.dlg.form.data.optionUnits.splice(index + 1, 0, item)
     }
   }
 }

+ 38 - 34
src/views/unit/index.vue

@@ -1,11 +1,14 @@
 <template>
   <div class="app-container">
     <div class="filter-container">
-      <el-input v-model="list.main.query.category" class="filter-item" size="mini" placeholder="类别" style="width:150px;margin-right:5px;" clearable />
+      <el-select v-model="list.main.query.category" class="filter-item" size="mini" placeholder="类别" style="width:110px;margin-right:5px;" clearable>
+        <el-option label="质量" value="MASS" />
+        <el-option label="体积" value="VOLUME" />
+      </el-select>
       <el-input v-model="list.main.query.name" class="filter-item" size="mini" placeholder="名称" style="width:150px;margin-right:5px;" clearable />
       <el-input v-model="list.main.query.code" class="filter-item" size="mini" placeholder="编码" style="width:150px;margin-right:5px;" clearable />
-      <el-input v-model="list.main.query.enName" class="filter-item" size="mini" placeholder="英文名称" style="width:150px;margin-right:5px;" clearable />
-      <el-select v-model="list.main.query.baseUnit" class="filter-item" size="mini" placeholder="是否基础单位" style="width:150px;margin-right:5px;" clearable>
+      <el-input v-model="list.main.query.nameEn" class="filter-item" size="mini" placeholder="英文名称" style="width:150px;margin-right:5px;" clearable />
+      <el-select v-model="list.main.query.base" class="filter-item" size="mini" placeholder="是否基础单位" style="width:150px;margin-right:5px;" clearable>
         <el-option label="是" :value="true" />
         <el-option label="否" :value="false" />
       </el-select>
@@ -22,7 +25,7 @@
     <el-table v-loading="list.main.loading" :data="list.main.list" border fit highlight-current-row style="width:100%" :max-height="maxHeight">
       <el-table-column width="100" align="center" label="类别">
         <template slot-scope="{row}">
-          <span>{{ row.category }}</span>
+          <span>{{ row.categoryName }}</span>
         </template>
       </el-table-column>
       <el-table-column min-width="150" header-align="center" label="名称">
@@ -35,32 +38,38 @@
           <span>{{ row.code }}</span>
         </template>
       </el-table-column>
-      <el-table-column width="100" header-align="center" label="英文名称">
+      <el-table-column width="130" header-align="center" label="英文名称">
         <template slot-scope="{row}">
-          <span>{{ row.enName }}</span>
+          <span>{{ row.nameEn }}</span>
         </template>
       </el-table-column>
       <el-table-column width="100" align="center" label="是否基础单位">
         <template slot-scope="{row}">
-          <span v-if="row.baseUnit" style="color:green;">是</span>
+          <span v-if="row.isBase" style="color:green;">是</span>
           <span v-else style="color:gray;">否</span>
         </template>
       </el-table-column>
+      <el-table-column width="100" align="center" label="基础单位">
+        <template slot-scope="{row}">
+          <span v-if="row.isBase" style="color:green;">{{ row.baseUnit || '-' }}</span>
+          <span v-else style="color:gray;">-</span>
+        </template>
+      </el-table-column>
       <el-table-column width="200" header-align="center" align="right" label="转换比例">
         <span slot="header">
           转换关系
-          <el-tooltip effect="dark" content="1 * unit = ratio * baseUnit" placement="top">
+          <el-tooltip effect="dark" content="1 unit * cf = 1 baseUnit" placement="top">
             <i class="el-icon-question" />
           </el-tooltip>
         </span>
         <template slot-scope="{row}">
-          <span v-if="row.baseUnit">-</span>
+          <span v-if="row.isBase">-</span>
           <span v-else>
             <span style="color:blue;font-weight:700;">1</span>({{ row.name }})
-            <span style="color:red;font-weight:700;">&nbsp;=&nbsp;</span>
-            <span style="color:purple;font-weight:700;">{{ row.ratio }}</span>
-            <span style="color:red;font-weight:700;">*</span>
-            <span style="color:green;font-weight:700;">1</span>{{ row.baseUnitName || '基础单位' }}
+            <span style="color:red;font-weight:700;">&nbsp;*&nbsp;</span>
+            <span style="color:purple;font-weight:700;">{{ row.cf }}</span>
+            <span style="color:red;font-weight:700;">=</span>
+            <span style="color:green;font-weight:700;">1</span>{{ row.baseUnit || '基础单位' }}
           </span>
         </template>
       </el-table-column>
@@ -82,12 +91,12 @@
       <el-table-column width="160" align="center" label="操作">
         <template slot-scope="{row}">
           <i class="el-icon-edit" style="cursor:pointer;color:#999999;margin-right:5px;" @click="edit(row)"></i>
-          &nbsp;&nbsp;
+          <!-- &nbsp;&nbsp;
           <i class="el-icon-delete" style="cursor:pointer;color:#999999;margin-right:5px;"></i>
           &nbsp;&nbsp;
           <i class="el-icon-top" style="cursor:pointer;color:#999999;margin-right:5px;"></i>
           &nbsp;&nbsp;
-          <i class="el-icon-bottom" style="cursor:pointer;color:#999999;"></i>
+          <i class="el-icon-bottom" style="cursor:pointer;color:#999999;"></i> -->
         </template>
       </el-table-column>
     </el-table>
@@ -96,7 +105,10 @@
     <el-dialog :title="dlg.form.title" :visible.sync="dlg.form.visible" width="500px">
       <el-form ref="form" :rules="dlg.form.rules" :model="dlg.form.data" size="mini" label-position="right" label-width="100px">
         <el-form-item label="类别" prop="category">
-          <el-input v-model="dlg.form.data.category" placeholder="请输入单位类别" />
+          <el-select v-model="dlg.form.data.category" class="filter-item" size="mini" placeholder="请选择单位类别" style="width:100%;" clearable>
+            <el-option label="质量" value="MASS" />
+            <el-option label="体积" value="VOLUME" />
+          </el-select>
         </el-form-item>
         <el-form-item label="名称" prop="name">
           <el-input v-model="dlg.form.data.name" placeholder="请输入单位名称,不能重复" />
@@ -108,28 +120,20 @@
           <el-input v-model="dlg.form.data.enName" placeholder="请输入单位英文名称" />
         </el-form-item>
         <el-form-item label="是否基础单位">
-          <el-checkbox v-model="dlg.form.data.baseUnit" />
+          <el-checkbox v-model="dlg.form.data.isBase" />
         </el-form-item>
-        <el-form-item v-if="!dlg.form.data.baseUnit" label="基础单位" required>
+        <el-form-item v-if="!dlg.form.data.isBase" label="基础单位" required>
           <el-select v-model="dlg.form.data.baseUnitId" class="filter-item" size="mini" placeholder="基础单位" style="width:100%;" @change="baseUnitChange" filterable>
+            <el-option v-if="!!dlg.form.data.baseUnitId && !baseUnitOptions.find(v => v.value==dlg.form.data.baseUnitId)" :label="dlg.form.data.baseUnit" :value="dlg.form.data.baseUnitId" />
             <el-option v-for="item in baseUnitOptions" :key="item.value" :label="item.label" :value="item.value" />
           </el-select>
         </el-form-item>
-        <el-form-item v-if="!dlg.form.data.baseUnit" label="转换关系" required>
-          <el-input v-model="dlg.form.data.ratio" placeholder="转换比例">
-            <span slot="prepend">1 {{ dlg.form.data.name }} = </span>
-            <span slot="append"> * {{ dlg.form.data.baseUnitName || '基础单位' }}</span>
+        <el-form-item v-if="!dlg.form.data.isBase" label="转换关系" required>
+          <el-input v-model="dlg.form.data.cf" placeholder="CF">
+            <span slot="prepend">1 {{ dlg.form.data.name }} * </span>
+            <span slot="append"> = 1 {{ dlg.form.data.baseUnit || '基础单位' }}</span>
           </el-input>
         </el-form-item>
-        <el-form-item label="最小刻度">
-          <el-input v-model="dlg.form.data.minScale" placeholder="请输入卡尺最小刻度" />
-        </el-form-item>
-        <el-form-item label="最大刻度">
-          <el-input v-model="dlg.form.data.maxScale" placeholder="请输入卡尺最大刻度" />
-        </el-form-item>
-        <el-form-item label="卡尺每格刻度">
-          <el-input v-model="dlg.form.data.stepScale" placeholder="请输入卡尺每格刻度" />
-        </el-form-item>
       </el-form>
       <div slot="footer" class="dialog-footer">
         <el-button size="mini" @click="dlg.form.visible = false">
@@ -191,7 +195,7 @@ export default {
   },
   methods: {
     loadBaseUnit() {
-      fGet(this.URI, { baseUnit: true, size: 10000 }).then(res => {
+      fGet(this.URI, { base: true, limit: 10000 }).then(res => {
         this.baseUnitOptions = res.data.map(v => {
           return {
             label: v.name,
@@ -210,10 +214,10 @@ export default {
       if (!!this.dlg.form.data.baseUnitId) {
         const baseUnit = this.baseUnitOptions.find(v => v.value == this.dlg.form.data.baseUnitId)
         if (!!baseUnit) {
-          this.dlg.form.data.baseUnitName = baseUnit.label
+          this.dlg.form.data.baseUnit = baseUnit.label
         }
       } else {
-        this.dlg.form.data.baseUnitName = undefined
+        this.dlg.form.data.baseUnit = undefined
       }
     }
   }

+ 20 - 0
upload.sh

@@ -0,0 +1,20 @@
+
+workdir=$(pwd)
+
+app=feuc
+
+env=test
+host=59.110.65.177
+
+ssh ${host} <<- EOF
+  rm -rf /opt/${app}/${env}/temp/admin;
+  mkdir -p /opt/${app}/${env}/temp/admin;
+EOF
+scp -r ${workdir}/dist/index.html ${host}:/opt/${app}/${env}/temp/admin/
+ssh ${host} <<- EOF
+  rm -rf /opt/${app}/${env}/admin;
+  mkdir -p /opt/${app}/${env}/admin;
+  cp -r /opt/${app}/${env}/temp/admin/* /opt/${app}/${env}/admin;
+EOF
+
+node ./deploy-to-oss.js

+ 2 - 1
vue.config.js

@@ -24,7 +24,8 @@ module.exports = {
    * In most cases please use '/' !!!
    * Detail: https://cli.vuejs.org/config/#publicpath
    */
-  publicPath: '/',
+  // publicPath: '/',
+  publicPath: process.env.static_path,
   outputDir: 'dist',
   assetsDir: 'static',
   lintOnSave: process.env.NODE_ENV === 'development',