| @@ -1,180 +0,0 @@ | ||||
| <template> | ||||
|   <div :class="className" :style="{ height: height, width: width }" /> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import echarts from "echarts"; | ||||
| import VueScrollTo from "vue-scrollto"; | ||||
| require("@/utils/echarts/myShine"); | ||||
| import resize from "@/views/dashboard/mixins/resize"; | ||||
| import { createNamespacedHelpers } from "vuex"; | ||||
| const { mapMutations } = createNamespacedHelpers("recipes"); | ||||
| const animationDuration = 6000; | ||||
|  | ||||
| export default { | ||||
|   mixins: [resize], | ||||
|   props: { | ||||
|     className: { | ||||
|       type: String, | ||||
|       default: "chart", | ||||
|     }, | ||||
|     width: { | ||||
|       type: String, | ||||
|       default: "100%", | ||||
|     }, | ||||
|     height: { | ||||
|       type: String, | ||||
|       default: "300px", | ||||
|     }, | ||||
|     data: { | ||||
|       type: Array, | ||||
|       default: [], | ||||
|     }, | ||||
|     max: { | ||||
|       type: Number, | ||||
|       default: 0, | ||||
|     }, | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       chart: null, | ||||
|       nameDict: { | ||||
|         pHeat: "蛋白质", | ||||
|         fHeat: "脂肪", | ||||
|         cHeat: "碳水", | ||||
|       }, | ||||
|     }; | ||||
|   }, | ||||
|   mounted() { | ||||
|     this.$nextTick(() => { | ||||
|       this.initChart(); | ||||
|     }); | ||||
|   }, | ||||
|   beforeDestroy() { | ||||
|     if (!this.chart) { | ||||
|       return; | ||||
|     } | ||||
|     this.chart.dispose(); | ||||
|     this.chart = null; | ||||
|   }, | ||||
|   updated() { | ||||
|     // console.log("updated"); | ||||
|   }, | ||||
|   methods: { | ||||
|     ...mapMutations(["setCurrentDay"]), | ||||
|     initChart() { | ||||
|       this.chart = echarts.init(this.$el, "myShine"); | ||||
|       this.chart.on("click", this.handleOnClick); | ||||
|       this.updateChart(this.data.length > 0 ? this.data : {}); | ||||
|     }, | ||||
|     updateChart(source) { | ||||
|       // console.log(this.max); | ||||
|       this.chart.clear(); | ||||
|       this.chart.setOption({ | ||||
|         title: { | ||||
|           text: "营养统计", | ||||
|         }, | ||||
|         tooltip: { | ||||
|           trigger: "axis", | ||||
|           // appendToBody: true, | ||||
|           formatter: (params) => { | ||||
|             // console.log(params); | ||||
|             const [param] = params; | ||||
|             const { name } = param; | ||||
|             let totalHeat = 0; | ||||
|             const tooltips = params.reduce( | ||||
|               (arr, cur) => { | ||||
|                 const { value, seriesName } = cur; | ||||
|                 const nutriName = this.nameDict[seriesName]; | ||||
|                 totalHeat += value[seriesName]; | ||||
|                 const heatVal = value[seriesName].toFixed(1); | ||||
|                 const weightVal = value[ | ||||
|                   `${seriesName.substring(0, 1)}Weight` | ||||
|                 ].toFixed(1); | ||||
|                 arr.push( | ||||
|                   `${cur.marker} ${nutriName}:${weightVal}克(${heatVal}千卡)` | ||||
|                 ); | ||||
|                 return arr; | ||||
|               }, | ||||
|               [name] | ||||
|             ); | ||||
|             tooltips[0] += ` - 共${totalHeat.toFixed(1)}千卡`; | ||||
|             return tooltips.join("</br>"); | ||||
|           }, | ||||
|         }, | ||||
|         dataset: { | ||||
|           dimensions: [ | ||||
|             "name", | ||||
|             "pWeight", | ||||
|             "pHeat", | ||||
|             "fWeight", | ||||
|             "fHeat", | ||||
|             "cWeight", | ||||
|             "cHeat", | ||||
|           ], | ||||
|           source, | ||||
|         }, | ||||
|         grid: { | ||||
|           top: 50, | ||||
|           left: 10, | ||||
|           right: 50, | ||||
|           bottom: 10, | ||||
|           containLabel: true, | ||||
|         }, | ||||
|         xAxis: { | ||||
|           type: "category", | ||||
|           // axisLabel: { | ||||
|           //   rotate: 45, | ||||
|           // }, | ||||
|         }, | ||||
|         yAxis: { | ||||
|           type: "value", | ||||
|           name: "热量/千卡", | ||||
|           nameTextStyle: { | ||||
|             color: "#262626", | ||||
|             fontSize: 12, | ||||
|           }, | ||||
|         }, | ||||
|         series: ["pHeat", "fHeat", "cHeat"].map((dim, idx) => ({ | ||||
|           name: dim, | ||||
|           type: "bar", | ||||
|           barWidth: 24, | ||||
|           stack: "bar", | ||||
|           encode: { | ||||
|             y: dim, | ||||
|             x: 0, | ||||
|           }, | ||||
|           markLine: { | ||||
|             data: [{ name: "BMR", yAxis: this.max ? this.max - 400 : 0 }], | ||||
|             symbol: "none", | ||||
|             lineStyle: { | ||||
|               color: "#d96969", | ||||
|             }, | ||||
|           }, | ||||
|           itemStyle: { | ||||
|             borderWidth: 2, | ||||
|             borderColor: "#fff", | ||||
|           }, | ||||
|         })), | ||||
|       }); | ||||
|     }, | ||||
|     handleOnClick(params) { | ||||
|       // console.log(params); | ||||
|       const { dataIndex } = params; | ||||
|       this.setCurrentDay({ currentDay: dataIndex }); | ||||
|       VueScrollTo.scrollTo(`#recipes${dataIndex}`, 500, { | ||||
|         container: "#recipes_content", | ||||
|       }); | ||||
|     }, | ||||
|   }, | ||||
|   watch: { | ||||
|     data(newVal, oldVal) { | ||||
|       if (newVal) { | ||||
|         this.$nextTick(() => { | ||||
|           this.updateChart(newVal); | ||||
|         }); | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
| }; | ||||
| </script> | ||||
| @@ -0,0 +1,276 @@ | ||||
| <template> | ||||
|   <div ref="echart" :style="{ height: height, width: width }" /> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import echarts from "echarts"; | ||||
| require("@/utils/echarts/myShine"); | ||||
| import resize from "@/views/dashboard/mixins/resize"; | ||||
| import { createNamespacedHelpers } from "vuex"; | ||||
| const { mapMutations, mapState } = createNamespacedHelpers("recipes"); | ||||
|  | ||||
| export default { | ||||
|   mixins: [resize], | ||||
|   props: { | ||||
|     className: { | ||||
|       type: String, | ||||
|       default: "chart", | ||||
|     }, | ||||
|     width: { | ||||
|       type: String, | ||||
|       default: "100%", | ||||
|     }, | ||||
|     height: { | ||||
|       type: String, | ||||
|       default: "200px", | ||||
|     }, | ||||
|     data: { | ||||
|       type: Array, | ||||
|       default: [], | ||||
|     }, | ||||
|     subTitle: { | ||||
|       type: String, | ||||
|       default: "", | ||||
|     }, | ||||
|     title: { | ||||
|       type: String, | ||||
|       default: "", | ||||
|     }, | ||||
|     type: { | ||||
|       type: String, | ||||
|       default: "", | ||||
|     }, | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       chart: null, | ||||
|     }; | ||||
|   }, | ||||
|   computed: {}, | ||||
|   mounted() { | ||||
|     this.$nextTick(() => { | ||||
|       this.initChart(); | ||||
|     }); | ||||
|   }, | ||||
|   beforeDestroy() { | ||||
|     if (!this.chart) { | ||||
|       return; | ||||
|     } | ||||
|     this.chart.dispose(); | ||||
|     this.chart = null; | ||||
|   }, | ||||
|   methods: { | ||||
|     initChart() { | ||||
|       this.chart = echarts.init(this.$refs.echart, "myShine"); | ||||
|       if (this.data.length > 0) { | ||||
|         this.updateChart(this.data); | ||||
|       } | ||||
|     }, | ||||
|     backToAll() { | ||||
|       this.resetCurrentDay({ currentDay: -1 }); | ||||
|     }, | ||||
|     getTooltipArr(params) { | ||||
|       console.log(params); | ||||
|       let tooltips; | ||||
|       const { name, marker, percent, value } = params; | ||||
|       switch (this.type) { | ||||
|         case "nutrition": | ||||
|           const weight = value[1] / (name === "脂肪" ? 9 : 4); | ||||
|           tooltips = [ | ||||
|             `${marker} ${name}`, | ||||
|             `摄入量:${weight.toFixed(1)}克`, | ||||
|             `摄入热量:${value[1].toFixed(1)}千卡`, | ||||
|             `供能比:${percent}%`, | ||||
|           ]; | ||||
|           break; | ||||
|         case "calories": | ||||
|           tooltips = [ | ||||
|             `${marker} ${name}`, | ||||
|             `热量:${value[1].toFixed(1)}千卡`, | ||||
|             `占比:${percent}%`, | ||||
|           ]; | ||||
|           break; | ||||
|         case "weight": | ||||
|           tooltips = [ | ||||
|             `${marker} ${name}`, | ||||
|             `质量:${value[1].toFixed(1)}克`, | ||||
|             `占比:${percent}%`, | ||||
|           ]; | ||||
|           break; | ||||
|       } | ||||
|       return tooltips.join("</br>"); | ||||
|     }, | ||||
|     updateChart(source) { | ||||
|       console.log(source); | ||||
|       const total = source.reduce((acc, cur) => acc + cur[1], 0); | ||||
|       this.chart.clear(); | ||||
|       const option = { | ||||
|         title: { | ||||
|           text: this.title, | ||||
|           subtext: this.subTitle, | ||||
|         }, | ||||
|         legend: { | ||||
|           left: 100, | ||||
|           itemWidth: 8, | ||||
|           itemHeight: 8, | ||||
|           pageIconSize: 10, | ||||
|           textStyle: { | ||||
|             fontSize: 10, | ||||
|           }, | ||||
|         }, | ||||
|         dataset: { | ||||
|           source, | ||||
|         }, | ||||
|         tooltip: { | ||||
|           trigger: "item", | ||||
|           appendToBody: true, | ||||
|           formatter: this.getTooltipArr, | ||||
|         }, | ||||
|         graphic: [ | ||||
|           { | ||||
|             type: "group", | ||||
|             top: 60, | ||||
|             left: 10, | ||||
|             silent: true, | ||||
|             children: [ | ||||
|               { | ||||
|                 type: "text", | ||||
|                 style: { | ||||
|                   text: this.type === "weight" ? "总质量" : "总热量约", | ||||
|                   fill: "#606266", | ||||
|                 }, | ||||
|               }, | ||||
|               { | ||||
|                 type: "text", | ||||
|                 top: 18, | ||||
|                 left: 8, | ||||
|                 style: { | ||||
|                   text: `${total.toFixed(1)}${ | ||||
|                     this.type === "weight" ? "克" : "千卡" | ||||
|                   }`, | ||||
|                   font: '14px "Microsoft YaHei", sans-serif', | ||||
|                 }, | ||||
|               }, | ||||
|             ], | ||||
|           }, | ||||
|           { | ||||
|             type: "group", | ||||
|             top: 36, | ||||
|             right: 10, | ||||
|             silent: true, | ||||
|             children: source.map((item, idx) => { | ||||
|               const data = | ||||
|                 this.type == "nutrition" | ||||
|                   ? item[1] / (idx === 1 ? 9 : 4) | ||||
|                   : item[1]; | ||||
|               return { | ||||
|                 type: "text", | ||||
|                 top: idx * 20, | ||||
|                 right: 10, | ||||
|                 style: { | ||||
|                   text: `${item[0]}:${data.toFixed(1)}${ | ||||
|                     this.type === "calories" ? "千卡" : "克" | ||||
|                   }`, | ||||
|                   fill: "#606266", | ||||
|                 }, | ||||
|               }; | ||||
|             }), | ||||
|           }, | ||||
|         ], | ||||
|         series: [ | ||||
|           { | ||||
|             type: "pie", | ||||
|             radius: [0, 60], | ||||
|             center: ["50%", "55%"], | ||||
|             // labelLine: { | ||||
|             //   length: 5, | ||||
|             //   length2: 5, | ||||
|             // }, | ||||
|             label: { | ||||
|               show: true, | ||||
|               position: "inside", | ||||
|               color: "#fff", | ||||
|               fontSize: 12, | ||||
|               fontWeight: "bold", | ||||
|             }, | ||||
|             itemStyle: { | ||||
|               borderWidth: 1, | ||||
|               borderColor: "#fff", | ||||
|             }, | ||||
|           }, | ||||
|         ], | ||||
|       }; | ||||
|       // console.log(option); | ||||
|       this.chart.setOption(option); | ||||
|     }, | ||||
|   }, | ||||
|   watch: { | ||||
|     data(newVal, oldVal) { | ||||
|       if (newVal) { | ||||
|         this.$nextTick(() => { | ||||
|           this.updateChart(newVal); | ||||
|         }); | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
| }; | ||||
| </script> | ||||
| <style lang="scss" scoped> | ||||
| /deep/ :focus { | ||||
|   outline: 0; | ||||
| } | ||||
|  | ||||
| .aspect_pie_chart_wrapper { | ||||
|   width: 100%; | ||||
|   display: flex; | ||||
|   position: relative; | ||||
|  | ||||
|   & > div:nth-child(1) { | ||||
|     // width: 200px | ||||
|   } | ||||
|  | ||||
|   .small_table { | ||||
|     .my_cell { | ||||
|       padding: 2px 0 !important; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .summary { | ||||
|     padding: 2px; | ||||
|     border-bottom: 1px solid #dfe6ec; | ||||
|     border-left: 1px solid #dfe6ec; | ||||
|     border-right: 1px solid #dfe6ec; | ||||
|  | ||||
|     & > div { | ||||
|       padding: 3px; | ||||
|       text-align: center; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .see_all { | ||||
|     position: absolute; | ||||
|     bottom: 4px; | ||||
|     left: 24px; | ||||
|     padding: 0; | ||||
|   } | ||||
|  | ||||
|   .icon_btns { | ||||
|     position: absolute; | ||||
|     right: 0; | ||||
|  | ||||
|     em { | ||||
|       display: inline-block; | ||||
|       padding: 4px; | ||||
|       cursor: pointer; | ||||
|     } | ||||
|  | ||||
|     .sel_icon { | ||||
|       color: #1890ff; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .table_zone { | ||||
|     margin-top: 26px; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
| @@ -0,0 +1,110 @@ | ||||
| <template> | ||||
|   <div class="daily_analyze_com_wrapper"> | ||||
|     <pie-chart | ||||
|       title="营养统计" | ||||
|       :data="nutritionSource" | ||||
|       type="nutrition" | ||||
|       :subTitle="subTitle" | ||||
|     /> | ||||
|     <pie-chart | ||||
|       title="热量统计" | ||||
|       :data="caloriesSource" | ||||
|       type="calories" | ||||
|       :subTitle="subTitle" | ||||
|     /> | ||||
|     <pie-chart | ||||
|       title="质量统计" | ||||
|       :data="weightSource" | ||||
|       type="weight" | ||||
|       :subTitle="subTitle" | ||||
|     /> | ||||
|     <el-button size="mini" type="text" @click="backToAll" class="see_all" | ||||
|       >查看全部</el-button | ||||
|     > | ||||
|   </div> | ||||
| </template> | ||||
| <script> | ||||
| import PieChart from "./PieChart"; | ||||
| import { createNamespacedHelpers } from "vuex"; | ||||
| const { mapGetters, mapMutations } = createNamespacedHelpers("recipes"); | ||||
| export default { | ||||
|   name: "DailyAnalyzeCom", | ||||
|   data() { | ||||
|     return { | ||||
|       subTitle: "", | ||||
|     }; | ||||
|   }, | ||||
|   components: { | ||||
|     PieChart, | ||||
|   }, | ||||
|   methods: { | ||||
|     backToAll() { | ||||
|       this.resetCurrentDay({ currentDay: -1 }); | ||||
|     }, | ||||
|     ...mapMutations(["resetCurrentDay"]), | ||||
|   }, | ||||
|   computed: { | ||||
|     nutritionSource() { | ||||
|       const [data] = this.analyseData; | ||||
|       this.subTitle = data.name; | ||||
|       return [ | ||||
|         ["蛋白质", data.pCalories], | ||||
|         ["脂肪", data.fCalories], | ||||
|         ["碳水", data.cCalories], | ||||
|       ]; | ||||
|     }, | ||||
|     caloriesSource() { | ||||
|       const [data] = this.analyseData; | ||||
|       const source = [ | ||||
|         ["早餐", data.calories1], | ||||
|         ["午餐", data.calories3], | ||||
|         ["晚餐", data.calories5], | ||||
|       ]; | ||||
|       if (data.calories2) { | ||||
|         source.push(["早加餐", data.calories2]); | ||||
|       } | ||||
|       if (data.calories4) { | ||||
|         source.push(["午加餐", data.calories4]); | ||||
|       } | ||||
|       if (data.calories6) { | ||||
|         source.push(["晚加餐", data.calories6]); | ||||
|       } | ||||
|       return source; | ||||
|     }, | ||||
|     weightSource() { | ||||
|       const [data] = this.analyseData; | ||||
|       const source = [ | ||||
|         ["早餐", data.weight1], | ||||
|         ["午餐", data.weight3], | ||||
|         ["晚餐", data.weight5], | ||||
|       ]; | ||||
|       if (data.weight2) { | ||||
|         source.push(["早加餐", data.weight2]); | ||||
|       } | ||||
|       if (data.weight4) { | ||||
|         source.push(["午加餐", data.weight4]); | ||||
|       } | ||||
|       if (data.weight6) { | ||||
|         source.push(["晚加餐", data.weight6]); | ||||
|       } | ||||
|       return source; | ||||
|     }, | ||||
|     ...mapGetters(["analyseData"]), | ||||
|   }, | ||||
| }; | ||||
| </script> | ||||
| <style lang="scss" scoped> | ||||
| .daily_analyze_com_wrapper { | ||||
|   position: relative; | ||||
|   & > div:not(:nth-child(1)) { | ||||
|     margin-top: 12px; | ||||
|   } | ||||
|  | ||||
|   .see_all { | ||||
|     position: absolute; | ||||
|     top: 0; | ||||
|     right: 0; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
|  | ||||
| @@ -0,0 +1,221 @@ | ||||
| <template> | ||||
|   <div :class="className" :style="{ height: height, width: width }" /> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import echarts from "echarts"; | ||||
| require("@/utils/echarts/myShine"); | ||||
| import resize from "@/views/dashboard/mixins/resize"; | ||||
| const animationDuration = 6000; | ||||
|  | ||||
| export default { | ||||
|   mixins: [resize], | ||||
|   props: { | ||||
|     className: { | ||||
|       type: String, | ||||
|       default: "chart", | ||||
|     }, | ||||
|     width: { | ||||
|       type: String, | ||||
|       default: "100%", | ||||
|     }, | ||||
|     height: { | ||||
|       type: String, | ||||
|       default: "180px", | ||||
|     }, | ||||
|     data: { | ||||
|       type: Array, | ||||
|       default: [], | ||||
|     }, | ||||
|     max: { | ||||
|       type: Number, | ||||
|       default: 0, | ||||
|     }, | ||||
|     title: { | ||||
|       type: String, | ||||
|       default: "", | ||||
|     }, | ||||
|     type: { | ||||
|       type: String, | ||||
|       default: "", | ||||
|     }, | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       chart: null, | ||||
|     }; | ||||
|   }, | ||||
|   mounted() { | ||||
|     this.$nextTick(() => { | ||||
|       this.initChart(); | ||||
|     }); | ||||
|   }, | ||||
|   beforeDestroy() { | ||||
|     if (!this.chart) { | ||||
|       return; | ||||
|     } | ||||
|     this.chart.dispose(); | ||||
|     this.chart = null; | ||||
|   }, | ||||
|   computed: {}, | ||||
|   updated() { | ||||
|     // console.log("updated"); | ||||
|   }, | ||||
|   methods: { | ||||
|     initChart() { | ||||
|       this.chart = echarts.init(this.$el, "myShine"); | ||||
|       this.chart.on("click", this.handleOnClick); | ||||
|       if (this.data.length > 0) { | ||||
|         this.updateChart(this.data); | ||||
|       } | ||||
|     }, | ||||
|     getTooltipArr(params) { | ||||
|       // console.log(params); | ||||
|       const [param] = params; | ||||
|       const { name } = param; | ||||
|       let tooltips; | ||||
|       let total = 0; | ||||
|       switch (this.type) { | ||||
|         case "nutrition": | ||||
|           tooltips = params.reduce( | ||||
|             (arr, cur) => { | ||||
|               const { value, seriesName, seriesIndex, marker } = cur; | ||||
|               const calories = value[seriesIndex + 1]; | ||||
|               total += calories; | ||||
|               const weight = ( | ||||
|                 calories / (seriesName === "脂肪" ? 9 : 4) | ||||
|               ).toFixed(1); | ||||
|               arr.push( | ||||
|                 `${marker} ${seriesName}:${weight}克(${calories.toFixed( | ||||
|                   1 | ||||
|                 )}千卡)` | ||||
|               ); | ||||
|               return arr; | ||||
|             }, | ||||
|             [name] | ||||
|           ); | ||||
|           tooltips[0] += ` - 约${total.toFixed(1)}千卡`; | ||||
|           break; | ||||
|         case "calories": | ||||
|           tooltips = params.reduce( | ||||
|             (arr, cur) => { | ||||
|               const { value, seriesName, seriesIndex, marker } = cur; | ||||
|               const calories = value[seriesIndex + 1]; | ||||
|               total += calories; | ||||
|               if (calories) { | ||||
|                 arr.push(`${marker} ${seriesName}:${calories.toFixed(1)}千卡`); | ||||
|               } | ||||
|               return arr; | ||||
|             }, | ||||
|             [name] | ||||
|           ); | ||||
|           tooltips[0] += ` - 约${total.toFixed(1)}千卡`; | ||||
|           break; | ||||
|         case "weight": | ||||
|           tooltips = params.reduce( | ||||
|             (arr, cur) => { | ||||
|               const { value, seriesName, seriesIndex, marker } = cur; | ||||
|               const weight = value[seriesIndex + 1]; | ||||
|               total += weight; | ||||
|               if (weight) { | ||||
|                 arr.push(`${marker} ${seriesName}:${weight.toFixed(1)}克`); | ||||
|               } | ||||
|               return arr; | ||||
|             }, | ||||
|             [name] | ||||
|           ); | ||||
|           tooltips[0] += ` - 共${total.toFixed(1)}克`; | ||||
|           break; | ||||
|       } | ||||
|       return tooltips.join("</br>"); | ||||
|     }, | ||||
|     updateChart(source) { | ||||
|       // console.log(this.max); | ||||
|       // console.log(source); | ||||
|       this.chart.clear(); | ||||
|       const option = { | ||||
|         title: { | ||||
|           text: this.title, | ||||
|         }, | ||||
|         legend: { | ||||
|           // type: "scroll", | ||||
|           left: 100, | ||||
|           itemWidth: 8, | ||||
|           itemHeight: 8, | ||||
|           pageIconSize: 10, | ||||
|           textStyle: { | ||||
|             fontSize: 10, | ||||
|           }, | ||||
|         }, | ||||
|         tooltip: { | ||||
|           trigger: "axis", | ||||
|           appendToBody: true, | ||||
|           formatter: this.getTooltipArr, | ||||
|         }, | ||||
|         dataset: { | ||||
|           source, | ||||
|         }, | ||||
|         grid: { | ||||
|           top: 50, | ||||
|           left: 10, | ||||
|           right: 50, | ||||
|           bottom: 10, | ||||
|           containLabel: true, | ||||
|         }, | ||||
|         xAxis: { | ||||
|           type: "category", | ||||
|           // axisLabel: { | ||||
|           //   rotate: 45, | ||||
|           // }, | ||||
|         }, | ||||
|         yAxis: { | ||||
|           type: "value", | ||||
|           name: this.type === "weight" ? "质量/克" : "热量/千卡", | ||||
|           nameTextStyle: { | ||||
|             color: "#262626", | ||||
|             fontSize: 10, | ||||
|           }, | ||||
|         }, | ||||
|         series: source[0].slice(1).map((name, idx) => ({ | ||||
|           name, | ||||
|           type: "bar", | ||||
|           barWidth: 24, | ||||
|           stack: "bar", | ||||
|           encode: { | ||||
|             y: idx + 1, | ||||
|             x: 0, | ||||
|           }, | ||||
|           itemStyle: { | ||||
|             borderWidth: 2, | ||||
|             borderColor: "#fff", | ||||
|           }, | ||||
|         })), | ||||
|       }; | ||||
|       if (this.max) { | ||||
|         option.series[0].markLine = { | ||||
|           data: [{ name: "BMR", yAxis: this.max ? this.max - 400 : 0 }], | ||||
|           symbol: "none", | ||||
|           lineStyle: { | ||||
|             color: "#d96969", | ||||
|           }, | ||||
|         }; | ||||
|       } | ||||
|       this.chart.setOption(option); | ||||
|     }, | ||||
|     handleOnClick(params) { | ||||
|       // console.log(params); | ||||
|       const { dataIndex } = params; | ||||
|       this.$emit("onClick", dataIndex); | ||||
|     }, | ||||
|   }, | ||||
|   watch: { | ||||
|     data(newVal, oldVal) { | ||||
|       if (newVal) { | ||||
|         this.$nextTick(() => { | ||||
|           this.updateChart(newVal); | ||||
|         }); | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
| }; | ||||
| </script> | ||||
| @@ -0,0 +1,110 @@ | ||||
| <template> | ||||
|   <div class="weakly_analyze_com_wrapper"> | ||||
|     <bar-chart | ||||
|       :data="nutritionSource" | ||||
|       :max="max" | ||||
|       title="营养统计" | ||||
|       type="nutrition" | ||||
|       @onClick="handleOnClick" | ||||
|     /> | ||||
|     <bar-chart | ||||
|       :data="caloriesSource" | ||||
|       title="热量统计" | ||||
|       type="calories" | ||||
|       @onClick="handleOnClick" | ||||
|     /> | ||||
|     <bar-chart | ||||
|       :data="weightSource" | ||||
|       title="质量统计" | ||||
|       type="weight" | ||||
|       @onClick="handleOnClick" | ||||
|     /> | ||||
|   </div> | ||||
| </template> | ||||
| <script> | ||||
| import { createNamespacedHelpers } from "vuex"; | ||||
| const { mapState, mapGetters, mapMutations } = createNamespacedHelpers( | ||||
|   "recipes" | ||||
| ); | ||||
| import VueScrollTo from "vue-scrollto"; | ||||
| import BarChart from "./BarChart"; | ||||
| export default { | ||||
|   name: "WeaklyAnalyzeCom", | ||||
|   components: { | ||||
|     BarChart, | ||||
|   }, | ||||
|   data() { | ||||
|     return {}; | ||||
|   }, | ||||
|   props: ["data"], | ||||
|   methods: { | ||||
|     handleOnClick(currentDay) { | ||||
|       this.setCurrentDay({ currentDay }); | ||||
|       VueScrollTo.scrollTo(`#recipes${currentDay}`, 500, { | ||||
|         container: "#recipes_content", | ||||
|       }); | ||||
|     }, | ||||
|     ...mapMutations(["setCurrentDay"]), | ||||
|   }, | ||||
|   computed: { | ||||
|     nutritionSource() { | ||||
|       return this.analyseData.reduce( | ||||
|         (arr, cur) => { | ||||
|           arr.push([cur.name, cur.pCalories, cur.fCalories, cur.cCalories]); | ||||
|           return arr; | ||||
|         }, | ||||
|         [["日期", "蛋白质", "脂肪", "碳水"]] | ||||
|       ); | ||||
|     }, | ||||
|     caloriesSource() { | ||||
|       return this.analyseData.reduce( | ||||
|         (arr, cur) => { | ||||
|           arr.push([ | ||||
|             cur.name, | ||||
|             cur.calories1, | ||||
|             cur.calories2, | ||||
|             cur.calories3, | ||||
|             cur.calories4, | ||||
|             cur.calories5, | ||||
|             cur.calories6, | ||||
|           ]); | ||||
|           return arr; | ||||
|         }, | ||||
|         [["日期", "早餐", "早加餐", "午餐", "午加餐", "晚餐", "晚加餐"]] | ||||
|       ); | ||||
|     }, | ||||
|     weightSource() { | ||||
|       return this.analyseData.reduce( | ||||
|         (arr, cur) => { | ||||
|           arr.push([ | ||||
|             cur.name, | ||||
|             cur.weight1, | ||||
|             cur.weight2, | ||||
|             cur.weight3, | ||||
|             cur.weight4, | ||||
|             cur.weight5, | ||||
|             cur.weight6, | ||||
|           ]); | ||||
|           return arr; | ||||
|         }, | ||||
|         [["日期", "早餐", "早加餐", "午餐", "午加餐", "晚餐", "晚加餐"]] | ||||
|       ); | ||||
|     }, | ||||
|     max() { | ||||
|       const { basicBMR } = this.healthyData || {}; | ||||
|       return basicBMR | ||||
|         ? parseFloat(basicBMR.substring(0, basicBMR.indexOf("千卡"))) | ||||
|         : 0; | ||||
|     }, | ||||
|     ...mapState(["healthyData"]), | ||||
|     ...mapGetters(["analyseData"]), | ||||
|   }, | ||||
| }; | ||||
| </script> | ||||
| <style lang="scss" scoped> | ||||
| .weakly_analyze_com_wrapper { | ||||
|   & > div:not(:nth-child(1)) { | ||||
|     margin-top: 12px; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
| @@ -1,50 +1,46 @@ | ||||
| <template> | ||||
|   <div class="recipes_build_info_view_wrapper"> | ||||
|     <div class="top" v-if="showChart"> | ||||
|       <BarChart | ||||
|         v-if="analyseData.length > 1" | ||||
|         :data="analyseData" | ||||
|         height="160px" | ||||
|         width="100%" | ||||
|         :max="max" | ||||
|       /> | ||||
|       <PieChart | ||||
|         v-if="analyseData.length === 1" | ||||
|         :data="analyseData" | ||||
|         height="160px" | ||||
|         width="100%" | ||||
|       /> | ||||
|     </div> | ||||
|     <div | ||||
|       class="content" | ||||
|       :style="`height: calc(100vh - ${showChart ? 192 : 32}px);`" | ||||
|     > | ||||
|       <TemplateInfoView v-if="!!temId" :data="templateInfo" /> | ||||
|       <HealthyView :data="healthyData" v-else-if="healthyDataType === 0" dev /> | ||||
|       <BodySignView :data="healthyData" v-else dev /> | ||||
|     </div> | ||||
|     <el-tabs v-model="activeName" @tab-click="handleOnTabClick"> | ||||
|       <el-tab-pane label="食谱分析" name="0" v-if="showChart"> | ||||
|         <div class="content"> | ||||
|           <WeaklyAnalyzeCom v-if="analyseData.length > 1" /> | ||||
|           <DailyAnalyzeCom v-else /> | ||||
|         </div> | ||||
|       </el-tab-pane> | ||||
|       <el-tab-pane label="模板信息" name="1" v-if="!!temId"> | ||||
|         <div class="content"> | ||||
|           <TemplateInfoView :data="templateInfo" /> | ||||
|         </div> | ||||
|       </el-tab-pane> | ||||
|       <el-tab-pane label="客户信息" name="2" v-else> | ||||
|         <div class="content"> | ||||
|           <HealthyView :data="healthyData" v-if="healthyDataType === 0" dev /> | ||||
|           <BodySignView :data="healthyData" v-else dev /> | ||||
|         </div> | ||||
|       </el-tab-pane> | ||||
|     </el-tabs> | ||||
|   </div> | ||||
| </template> | ||||
| <script> | ||||
| import { createNamespacedHelpers } from "vuex"; | ||||
| const { mapActions, mapState, mapGetters } = createNamespacedHelpers("recipes"); | ||||
| import BarChart from "./BarChart"; | ||||
| import PieChart from "./PieChart"; | ||||
| import TemplateInfoView from "./TemplateInfoView"; | ||||
| import HealthyView from "@/components/HealthyView"; | ||||
| import BodySignView from "@/components/BodySignView"; | ||||
| import WeaklyAnalyzeCom from "./WeaklyAnalyzeCom"; | ||||
| import DailyAnalyzeCom from "./DailyAnalyzeCom"; | ||||
| export default { | ||||
|   name: "InfoView", | ||||
|   data() { | ||||
|     const { temId } = this.$route.query; | ||||
|     return { temId }; | ||||
|     return { temId, activeName: "0" }; | ||||
|   }, | ||||
|   components: { | ||||
|     BarChart, | ||||
|     PieChart, | ||||
|     HealthyView, | ||||
|     BodySignView, | ||||
|     TemplateInfoView, | ||||
|     WeaklyAnalyzeCom, | ||||
|     DailyAnalyzeCom, | ||||
|   }, | ||||
|   computed: { | ||||
|     max() { | ||||
| @@ -64,16 +60,18 @@ export default { | ||||
|     ]), | ||||
|     ...mapGetters(["analyseData"]), | ||||
|   }, | ||||
|   methods: { | ||||
|     handleOnTabClick(tab) { | ||||
|       this.activeName = tab.name; | ||||
|     }, | ||||
|   }, | ||||
| }; | ||||
| </script> | ||||
| <style lang="scss" scoped> | ||||
| .recipes_build_info_view_wrapper { | ||||
|   .top { | ||||
|     height: 160px; | ||||
|   } | ||||
|  | ||||
|   .content { | ||||
|     overflow: auto; | ||||
|     height: calc(100vh - 88px); | ||||
|   } | ||||
| } | ||||
| </style> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user