3 Achegas 938e7fb8dc ... c40a32f50d

Autor SHA1 Mensaxe Data
  wangyang c40a32f50d 实现食物相关页面的相关跳转' %!s(int64=5) %!d(string=hai) anos
  wangyang 53c6b25ea6 取消显示账户密码提示 %!s(int64=5) %!d(string=hai) anos
  wangyang 37895bedb7 调整食物规格页面' %!s(int64=5) %!d(string=hai) anos

BIN=BIN
src/assets/navigation.png


+ 144 - 0
src/components/FloatingWindow/index.vue

@@ -0,0 +1,144 @@
+<template>
+  <div class="outBox">
+    <div
+      :class="['suspendBox', { move: !canDrag }]"
+      :style="{top:top+'px',left:left+'px'}"
+      @mousedown="start"
+      @mousemove="move"
+      @mouseup="stop"
+      @mouseenter="enter"
+      @mouseleave="leave"
+    >
+      <slot></slot>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  props:{
+    ableMove: {type: Boolean, default: true},  //是否可移动
+    ableHide: {type: Boolean, default: true},  //是否靠边隐藏
+    hoverShow: {type: Boolean, default: true},  //图标隐藏时 鼠标悬浮即展示,否则点击展示
+    distance: {type: Number, default: 5},  //距离边界多少px就隐藏
+    defaultX: {type: Number, default: 1},  //初始横坐标百分比
+    defaultY: {type: Number, default: 0.1}  //初始纵坐标百分比
+  },
+  data() {
+    return {
+      canDrag: false,
+      isClick: true,
+      x0: 0,
+      y0: 0,
+      top: null,
+      left: null
+    };
+  },
+  mounted() {
+    let img = document.querySelector(".suspendBox");
+    let box = document.querySelector(".outBox");
+    this.left = (box.offsetWidth - img.offsetWidth) * this.defaultX;
+    this.top = (box.offsetHeight - img.offsetHeight) * this.defaultY;
+    setTimeout(()=>{
+      this.hide()
+    }, 1000)
+  },
+  methods: {
+    start(e) {
+      console.log("start");
+      e.preventDefault();   //阻止默认的拖拽
+      if (e.button == 0) {
+        this.canDrag = this.ableMove;
+        this.isClick = true;
+        this.x0 = e.clientX;
+        this.y0 = e.clientY;
+      }
+    },
+    move(e) {
+      console.log("move");
+      if (this.canDrag == true) {
+        this.isClick = false;
+        let x = e.clientX - this.x0;
+        let y = e.clientY - this.y0;
+        let img = document.querySelector(".suspendBox");
+        let box = document.querySelector(".outBox");
+        if (
+          img.offsetLeft + x < 0 ||
+          img.offsetTop + y < 0 ||
+          img.offsetLeft + x > box.offsetWidth - img.offsetWidth ||
+          img.offsetTop + y > box.offsetHeight - img.offsetHeight
+        ) {
+          return false;
+        }
+        this.left = img.offsetLeft + x;
+        this.top = img.offsetTop + y;
+        this.x0 = e.clientX;
+        this.y0 = e.clientY;
+      }
+    },
+    stop() {
+      this.canDrag = false;
+      console.log("stop");
+      this.show();
+    },
+    enter() {
+      console.log("enter");
+      if (this.hoverShow) {
+        this.show();
+      }
+    },
+    leave() {
+      console.log("leave");
+      this.canDrag = false;
+      this.hide();
+    },
+    show() {
+      let img = document.querySelector(".suspendBox");
+      let box = document.querySelector(".outBox");
+      if (img.offsetLeft < 0) {
+        this.left = 0;
+      } else if (img.offsetLeft > box.offsetWidth - img.offsetWidth) {
+        this.left = box.offsetWidth - img.offsetWidth
+      } else if(this.isClick){
+        this.clickEvent()
+      }
+    },
+    hide() {
+      if (this.ableHide) {
+        console.log("hide");
+        let img = document.querySelector(".suspendBox");
+        let box = document.querySelector(".outBox");
+        if (!this.canDrag && img.offsetLeft < this.distance) {
+          this.left = -img.offsetWidth * 2 / 3;
+        } else if (!this.canDrag && img.offsetLeft > box.offsetWidth - img.offsetWidth - this.distance) {
+          this.left = box.offsetWidth - img.offsetWidth / 3
+        }
+      }
+    },
+    clickEvent() {      //悬浮窗的点击事件
+      console.log("悬浮窗的点击事件");
+      this.$emit("clickHandle")
+    },
+  },
+};
+</script>
+<style scoped>
+.outBox {
+  width: 100%;
+  height: 100%;
+  position: absolute;
+  overflow: hidden;
+  z-index:100;
+  pointer-events: none;
+}
+.suspendBox {
+  position: absolute;
+  pointer-events: auto;
+}
+.move {
+  transition: 0.3s linear;
+  -moz-transition: 0.3s linear; /* Firefox 4 */
+  -webkit-transition: 0.3s linear; /* Safari 和 Chrome */
+  -o-transition: 0.3s linear; /* Opera */
+}
+</style>

+ 52 - 2
src/views/food/components/FoodDetail.vue

@@ -1,5 +1,17 @@
 <template>
   <div class="createPost-container">
+
+    <floating-window v-if="isEdit" :class="{'is_fixed': isFixed}" >
+      <el-dropdown @command="handleCommand">
+        <img width="50px" height="50px" src="@/assets/navigation.png" alt="导航.png" />
+        <el-dropdown-menu slot="dropdown">
+          <el-dropdown-item command="nutrient">营养素关联</el-dropdown-item>
+          <el-dropdown-item command="unit">单位管理</el-dropdown-item>
+          <el-dropdown-item command="modifier">规格管理</el-dropdown-item>
+        </el-dropdown-menu>
+      </el-dropdown>
+    </floating-window>
+
     <el-form ref="postForm" :model="postForm" :rules="rules" label-position="right" label-width="90px" class="form-container">
       <div class="createPost-main-container">
         <el-form-item label="自定义ID:" style="margin-bottom: 40px;width: 60%" prop="id2">
@@ -102,12 +114,13 @@
 import { create, getDetail, update } from '@/api/food'
 import Dropzone from '@/components/Dropzone'
 import SingleImage from '@/components/Upload/SingleImage'
+import FloatingWindow from '@/components/FloatingWindow'
 import { getNutrientTemplates } from '@/api/nutrientTemplate'
 import { getFoodCategories } from '@/api/foodCategory'
 
 export default {
   name: "FoodDetail",
-  components: { Dropzone, SingleImage },
+  components: { Dropzone, SingleImage, FloatingWindow },
   props: {
     isEdit: {
       type: Boolean,
@@ -130,9 +143,18 @@ export default {
       categoriesProp: {
         value: 'id',
         expandTrigger: 'hover'
-      }
+      },
+      isFixed: false,
+      offsetTop: 0
     }
   },
+  mounted() {
+    window.addEventListener('scroll', this.initHeight);
+  },
+  //回调中移除监听
+  destroyed() {
+    window.removeEventListener('scroll', this.handleScroll)
+  },
   created() {
     this.fetchCategories()
     if (this.isEdit) {
@@ -218,6 +240,27 @@ export default {
       } else if (data.imageType === "NUTRIENT") {
         this.$set(this.postForm, 'nutrientImage', data.fileUrl)
       }
+    },
+    initHeight() {
+      // 设置或获取位于对象最顶端和窗口中可见内容的最顶端之间的距离 (被卷曲的高度)
+      const scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
+      //如果被卷曲的高度大于吸顶元素到顶端位置 的距离
+      this.isFixed = scrollTop > this.offsetTop;
+    },
+    handleCommand(value) {
+      let path = ''
+      if (value === 'unit') {
+        path = `/food/${this.foodId}/unit`
+      } else if (value === 'nutrient') {
+        path = `/food/${this.foodId}/nutrient`
+      } else if (value === 'modifier') {
+        path = `/food/${this.foodId}/modifier`
+      } else if (value === 'list') {
+        path = `/food`
+      }
+      if (path) {
+        this.$router.push({ path: path })
+      }
     }
   }
 }
@@ -248,4 +291,11 @@ export default {
       top: 0px;
     }
   }
+
+  .is_fixed{
+    width: 100%;
+    position: fixed;
+    top: 0;
+    z-index: 999;
+  }
 </style>

+ 49 - 2
src/views/food/nutrient.vue

@@ -1,6 +1,19 @@
 <template>
   <div class="app-container">
-    <div class="filter-container">
+    <div class="filter-container" style="position: relative">
+
+      <floating-window :class="{'is_fixed': isFixed}" >
+        <el-dropdown @command="handleCommand">
+          <img width="50px" height="50px" src="@/assets/navigation.png" alt="导航.png" />
+          <el-dropdown-menu slot="dropdown">
+            <el-dropdown-item command="detail">食物更新</el-dropdown-item>
+            <el-dropdown-item command="unit">单位管理</el-dropdown-item>
+            <el-dropdown-item command="modifier">规格管理</el-dropdown-item>
+            <el-dropdown-item command="list">食物列表</el-dropdown-item>
+          </el-dropdown-menu>
+        </el-dropdown>
+      </floating-window>
+
       <el-row>
         营养素:
         <el-select
@@ -250,12 +263,21 @@
 <script>
 import { getNutrientList, addFoodNutrient, updateFoodNutrient, removeFoodNutrient,
   updateFoodNutrientSort, confirmDeleteFoodNutrient, importNutrientsFromTemplate } from '@/api/food'
+import FloatingWindow from '@/components/FloatingWindow'
 import { getList, getNutrientUnits } from '@/api/nutrient'
 import { getList as getUnits } from '@/api/unit'
 import { getNutrientTemplates } from '@/api/nutrientTemplate'
 
 export default {
   name: 'AddNutrient',
+  components: { FloatingWindow },
+  mounted() {
+    window.addEventListener('scroll', this.initHeight);
+  },
+  //回调中移除监听
+  destroyed() {
+    window.removeEventListener('scroll', this.handleScroll)
+  },
   created() {
     this.foodId = this.$route.params && this.$route.params.id
     this.fetchData()
@@ -291,7 +313,9 @@ export default {
       dialogFormVisible: false,
       templateLoading: false,
       templateId: '',
-      templates: []
+      templates: [],
+      isFixed: false,
+      offsetTop: 0
     }
   },
   methods: {
@@ -448,6 +472,29 @@ export default {
         this.templateLoading = false
         this.dialogFormVisible = false
       })
+    },
+    initHeight() {
+      // 设置或获取位于对象最顶端和窗口中可见内容的最顶端之间的距离 (被卷曲的高度)
+      const scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
+      //如果被卷曲的高度大于吸顶元素到顶端位置 的距离
+      this.isFixed = scrollTop > this.offsetTop;
+    },
+    handleCommand(value) {
+      let path = ''
+      if (value === 'detail') {
+        path = `/food/edit/${this.foodId}`
+      } else if (value === 'unit') {
+        path = `/food/${this.foodId}/unit`
+      } else if (value === 'nutrient') {
+        path = `/food/${this.foodId}/nutrient`
+      } else if (value === 'modifier') {
+        path = `/food/${this.foodId}/modifier`
+      } else if (value === 'list') {
+        path = `/food`
+      }
+      if (path) {
+        this.$router.push({ path: path })
+      }
     }
   }
 }

+ 49 - 2
src/views/food/unit.vue

@@ -1,6 +1,19 @@
 <template>
   <div class="app-container">
-    <div class="filter-container">
+    <div class="filter-container" style="position: relative">
+
+      <floating-window :class="{'is_fixed': isFixed}" >
+        <el-dropdown @command="handleCommand">
+          <img width="50px" height="50px" src="@/assets/navigation.png" alt="导航.png" />
+          <el-dropdown-menu slot="dropdown">
+            <el-dropdown-item command="detail">食物更新</el-dropdown-item>
+            <el-dropdown-item command="nutrient">营养素关联</el-dropdown-item>
+            <el-dropdown-item command="modifier">规格管理</el-dropdown-item>
+            <el-dropdown-item command="list">食物列表</el-dropdown-item>
+          </el-dropdown-menu>
+        </el-dropdown>
+      </floating-window>
+
       From单位:
       <el-autocomplete
         ref="fromUnitSelect"
@@ -86,17 +99,28 @@
 <script>
 import { getBaseUnits, getList } from '@/api/unit'
 import { getFoodUnits, createOrUpdateFoodUnit, removeFoodUnit } from '@/api/food'
+import FloatingWindow from '@/components/FloatingWindow'
 
 export default {
   name: 'FoodUnit',
+  components: { FloatingWindow },
   data() {
     return {
       units: [],
       params: {},
       listLoading: false,
-      list: []
+      list: [],
+      isFixed: false,
+      offsetTop: 0
     }
   },
+  mounted() {
+    window.addEventListener('scroll', this.initHeight);
+  },
+  //回调中移除监听
+  destroyed() {
+    window.removeEventListener('scroll', this.handleScroll)
+  },
   created() {
     this.foodId = this.$route.params && this.$route.params.id
     this.fetchBaseUnits()
@@ -149,6 +173,29 @@ export default {
         res.data.list.forEach(item => units.push({ value: item.name }))
         cb(units)
       })
+    },
+    initHeight() {
+      // 设置或获取位于对象最顶端和窗口中可见内容的最顶端之间的距离 (被卷曲的高度)
+      const scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
+      //如果被卷曲的高度大于吸顶元素到顶端位置 的距离
+      this.isFixed = scrollTop > this.offsetTop;
+    },
+    handleCommand(value) {
+      let path = ''
+      if (value === 'detail') {
+        path = `/food/edit/${this.foodId}`
+      } else if (value === 'unit') {
+        path = `/food/${this.foodId}/unit`
+      } else if (value === 'nutrient') {
+        path = `/food/${this.foodId}/nutrient`
+      } else if (value === 'modifier') {
+        path = `/food/${this.foodId}/modifier`
+      } else if (value === 'list') {
+        path = `/food`
+      }
+      if (path) {
+        this.$router.push({ path: path })
+      }
     }
   }
 }

+ 87 - 23
src/views/foodModifier/components/ModifierDetail.vue

@@ -1,32 +1,63 @@
 <template>
-  <div class="createPost-container">
+  <div class="createPost-container" style="position: relative">
+
+    <floating-window :class="{'is_fixed': isFixed}" >
+      <el-dropdown @command="handleCommand">
+        <img width="50px" height="50px" src="@/assets/navigation.png" alt="导航.png" />
+        <el-dropdown-menu slot="dropdown">
+          <el-dropdown-item command="detail">食物更新</el-dropdown-item>
+          <el-dropdown-item command="nutrient">营养素关联</el-dropdown-item>
+          <el-dropdown-item command="unit">单位管理</el-dropdown-item>
+          <el-dropdown-item command="modifier">规格管理</el-dropdown-item>
+          <el-dropdown-item command="list">食物列表</el-dropdown-item>
+        </el-dropdown-menu>
+      </el-dropdown>
+    </floating-window>
+
     <el-form ref="postForm" :model="postForm" :rules="rules" label-position="right" label-width="130px" class="form-container">
       <div class="createPost-main-container">
         <el-checkbox @change="checkboxChange" :disabled="isEdit" v-model="isDefaultModifier" style="margin: 0 0 10px 100px">默认规格</el-checkbox>
         <el-form-item label="规格名称:" style="margin-bottom: 40px;width: 60%" prop="name">
           <el-input :disabled="isDefaultModifier" v-model="postForm.name" placeholder="请输入名称" @blur="updateUnit" />
         </el-form-item>
-        <el-form-item v-show="!isDefaultModifier" label="数值:" style="margin-bottom: 40px;width: 60%" prop="quantity">
-          <el-input v-model="postForm.quantity" placeholder="请输入数值" />
-        </el-form-item>
-        <el-form-item v-show="!isDefaultModifier"  label="单位名称:" style="margin-bottom: 40px;width: 60%" prop="unit">
-          <el-autocomplete
-            style="width: 100%"
-            v-model="postForm.unit"
-            :fetch-suggestions="queryUnits"
-            placeholder="单位关键词"
-          />
-        </el-form-item>
-        <el-form-item label="推荐摄入量:" style="margin-bottom: 40px;width: 60%" prop="inInit">
-          <el-input v-model="postForm.inInit" placeholder="请输入推荐量" />
+        <el-row style="width: 60%">
+          <el-col :span="12">
+            <el-form-item v-show="!isDefaultModifier" label="数值:" style="margin-bottom: 40px" prop="quantity">
+              <el-input v-model="postForm.quantity" placeholder="请输入数值" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item v-show="!isDefaultModifier"  label="单位名称:" style="margin-bottom: 40px" prop="unit">
+              <el-autocomplete
+                style="width: 100%"
+                v-model="postForm.unit"
+                :fetch-suggestions="queryUnits"
+                placeholder="单位关键词"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-form-item label="CNVR" style="margin-bottom: 40px;width: 60%" prop="unitTip">
+          <el-input v-model="postForm.unitTip" placeholder="请输入CNVR" />
         </el-form-item>
-        <el-form-item label="推荐量单位名称:" style="margin-bottom: 40px;width: 60%" prop="inInitUnit">
-          <el-autocomplete
-            style="width: 100%"
-            v-model="postForm.inInitUnit"
-            :fetch-suggestions="queryUnits"
-            placeholder="单位关键词"
-          />
+        <el-row style="width: 60%">
+          <el-col :span="12">
+            <el-form-item label="推荐摄入量:" style="margin-bottom: 40px" prop="inInit">
+              <el-input v-model="postForm.inInit" placeholder="请输入推荐量" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="推荐量单位名称:" style="margin-bottom: 40px" prop="inInitUnit">
+              <el-autocomplete
+                v-model="postForm.inInitUnit"
+                :fetch-suggestions="queryUnits"
+                placeholder="单位关键词"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-form-item label="CF" style="margin-bottom: 40px;width: 60%" prop="cf">
+          <el-input v-model="postForm.cf" :disabled="true" />
         </el-form-item>
         <el-form-item label="最小刻度:" prop="minScale" style="margin-bottom: 40px;width: 60%">
           <el-input v-model="postForm.minScale" placeholder="请输入最小刻度" />
@@ -55,6 +86,7 @@
 
 <script>
 import Dropzone from '@/components/Dropzone'
+import FloatingWindow from '@/components/FloatingWindow'
 import { addFoodModifier, updateFoodModifier, getFoodModifier } from '@/api/food'
 import { getList as getUnits } from '@/api/unit'
 
@@ -66,7 +98,7 @@ export default {
       default: false
     }
   },
-  components: { Dropzone },
+  components: { Dropzone, FloatingWindow },
   data() {
     return {
       defaultModifierName: '-',
@@ -75,9 +107,18 @@ export default {
       loading: false,
       foodId: '',
       modifierId: '',
-      isDefaultModifier: false
+      isDefaultModifier: false,
+      isFixed: false,
+      offsetTop: 0
     }
   },
+  mounted() {
+    window.addEventListener('scroll', this.initHeight);
+  },
+  //回调中移除监听
+  destroyed() {
+    window.removeEventListener('scroll', this.handleScroll)
+  },
   created() {
     this.foodId = this.$route.params && this.$route.params.id
     if (this.isEdit) {
@@ -152,6 +193,29 @@ export default {
     checkboxChange(value) {
       const name = value ? this.defaultModifierName : ''
       this.$set(this.postForm, 'name', name)
+    },
+    initHeight() {
+      // 设置或获取位于对象最顶端和窗口中可见内容的最顶端之间的距离 (被卷曲的高度)
+      const scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
+      //如果被卷曲的高度大于吸顶元素到顶端位置 的距离
+      this.isFixed = scrollTop > this.offsetTop;
+    },
+    handleCommand(value) {
+      let path = ''
+      if (value === 'detail') {
+        path = `/food/edit/${this.foodId}`
+      } else if (value === 'unit') {
+        path = `/food/${this.foodId}/unit`
+      } else if (value === 'nutrient') {
+        path = `/food/${this.foodId}/nutrient`
+      } else if (value === 'modifier') {
+        path = `/food/${this.foodId}/modifier`
+      } else if (value === 'list') {
+        path = `/food`
+      }
+      if (path) {
+        this.$router.push({ path: path })
+      }
     }
   }
 }

+ 49 - 3
src/views/foodModifier/index.vue

@@ -1,9 +1,10 @@
 <template>
   <div class="app-container">
+
     <div class="filter-container">
       <el-button
         class="filter-item"
-        style="margin: 0 10px 20px 0; float: right;"
+        style="margin: 0 10px 20px 0; float: left;"
         type="success"
         icon="el-icon-circle-plus-outline"
         @click="handleCreate"
@@ -12,6 +13,18 @@
       </el-button>
     </div>
 
+    <floating-window :able-hide="false" :class="{'is_fixed': isFixed}" >
+      <el-dropdown @command="handleCommand">
+        <img width="50px" height="50px" src="@/assets/navigation.png" alt="导航.png" />
+        <el-dropdown-menu slot="dropdown">
+          <el-dropdown-item command="detail">食物更新</el-dropdown-item>
+          <el-dropdown-item command="nutrient">营养素关联</el-dropdown-item>
+          <el-dropdown-item command="unit">单位管理</el-dropdown-item>
+          <el-dropdown-item command="list">食物列表</el-dropdown-item>
+        </el-dropdown-menu>
+      </el-dropdown>
+    </floating-window>
+
     <el-table
       :key="0"
       v-loading="listLoading"
@@ -101,10 +114,11 @@
 <script>
 import { getFoodModifiers, removeFoodModifier, updateFoodModifierSort, convertFoodUnit, getNutrientList,
   getDetail, calculateNutrientsContent } from '@/api/food'
-import { convertUnits } from '@/api/unit'
+import FloatingWindow from '@/components/FloatingWindow'
 
 export default {
   name: 'FoodModifierIndex',
+  components: { FloatingWindow },
   data() {
     return {
       listLoading: false,
@@ -112,9 +126,18 @@ export default {
       food: {},
       foodId: '',
       dialogHtml: '',
-      dialogFormVisible: false
+      dialogFormVisible: false,
+      isFixed: false,
+      offsetTop: 0
     }
   },
+  mounted() {
+    window.addEventListener('scroll', this.initHeight);
+  },
+  //回调中移除监听
+  destroyed() {
+    window.removeEventListener('scroll', this.handleScroll)
+  },
   created() {
     this.foodId = this.$route.params && this.$route.params.id
     this.fetchData()
@@ -166,6 +189,29 @@ export default {
       }).catch(res => {
         this.$message.error(res.data.message)
       })
+    },
+    initHeight() {
+      // 设置或获取位于对象最顶端和窗口中可见内容的最顶端之间的距离 (被卷曲的高度)
+      const scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
+      //如果被卷曲的高度大于吸顶元素到顶端位置 的距离
+      this.isFixed = scrollTop > this.offsetTop;
+    },
+    handleCommand(value) {
+      let path = ''
+      if (value === 'detail') {
+        path = `/food/edit/${this.foodId}`
+      } else if (value === 'unit') {
+        path = `/food/${this.foodId}/unit`
+      } else if (value === 'nutrient') {
+        path = `/food/${this.foodId}/nutrient`
+      } else if (value === 'modifier') {
+        path = `/food/${this.foodId}/modifier`
+      } else if (value === 'list') {
+        path = `/food`
+      }
+      if (path) {
+        this.$router.push({ path: path })
+      }
     }
   }
 }

+ 2 - 2
src/views/login/index.vue

@@ -64,8 +64,8 @@
       <el-button :loading="loading" type="primary" style="width:100%;margin-bottom:30px;" @click.native.prevent="handleLogin">Login</el-button>
 
       <div class="tips">
-        <span style="margin-right:20px;">username: admin</span>
-        <span> password: 123456</span>
+        <span style="margin-right:20px;"></span>
+        <span></span>
       </div>
 
     </el-form>