添加热量分析图表

This commit is contained in:
huangdeliang 2021-03-17 17:17:09 +08:00
parent ba372bee26
commit b36cef2948
4 changed files with 336 additions and 30 deletions

View File

@ -6,6 +6,7 @@
<meta name="renderer" content="webkit"> <meta name="renderer" content="webkit">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<link rel="icon" href="<%= BASE_URL %>favicon.ico"> <link rel="icon" href="<%= BASE_URL %>favicon.ico">
<link rel="stylesheet" href="//at.alicdn.com/t/font_2343184_8rlvxcc41j5.css">
<title><%= webpackConfig.name %></title> <title><%= webpackConfig.name %></title>
<style> <style>
html, html,

View File

@ -517,6 +517,10 @@ const getters = {
obj.fHeat = obj.fWeight * 9; obj.fHeat = obj.fWeight * 9;
obj.cWeight += (igd.weight / 100) * igd.carbonRatio; obj.cWeight += (igd.weight / 100) * igd.carbonRatio;
obj.cHeat = obj.cWeight * 4; obj.cHeat = obj.cWeight * 4;
obj[`heat${cur.type}`] +=
(igd.weight / 100) * igd.proteinRatio * 4 +
(igd.weight / 100) * igd.fatRatio * 9 +
(igd.weight / 100) * igd.carbonRatio * 4;
}); });
return obj; return obj;
}, },
@ -527,7 +531,13 @@ const getters = {
cWeight: 0, cWeight: 0,
pHeat: 0, pHeat: 0,
fHeat: 0, fHeat: 0,
cHeat: 0 cHeat: 0,
heat1: 0,
heat2: 0,
heat3: 0,
heat4: 0,
heat5: 0,
heat6: 0,
} }
) )
); );

View File

@ -0,0 +1,171 @@
<template>
<div
:class="`energy_pie_chart_wrapper ${className || ''}`"
:style="{ height: height, width: width }"
>
<div ref="echart" :style="{ height: height, width: '100px' }" />
</div>
</template>
<script>
import echarts from "echarts";
require("@/utils/echarts/myShine");
import resize from "@/views/dashboard/mixins/resize";
import TextInfo from "@/components/TextInfo";
import { createNamespacedHelpers } from "vuex";
const { mapMutations, mapState } = createNamespacedHelpers("recipes");
export default {
mixins: [resize],
components: {
TextInfo,
},
props: {
className: {
type: String,
default: "chart",
},
width: {
type: String,
default: "100%",
},
height: {
type: String,
default: "300px",
},
data: {
type: Array,
default: [],
},
},
data() {
return {
chart: null,
totalHeat: 0,
nameDict: {
p: "蛋白质",
f: "脂肪",
c: "碳水",
},
typeDict: {
Weight: "摄入量",
Rate: "供能比",
},
};
},
computed: {
mData() {
const [data] = this.data;
if (!data) {
this.totalHeat = 0;
return [];
}
this.totalHeat = data.cHeat + data.fHeat + data.pHeat;
const mData = ["Weight", "Rate"].map((t, idx) => ({
type: this.typeDict[t],
...["p", "f", "c"].reduce((obj, cur) => {
obj[cur] = idx
? `${((data[`${cur}Heat`] / this.totalHeat) * 100).toFixed(2)}%`
: `${data[`${cur}Weight`].toFixed(1)}`;
return obj;
}, {}),
}));
// console.log(mData);
return mData;
},
...mapState(["recipesData"]),
},
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");
this.updateChart(this.data.length > 0 ? this.data[0] : {});
},
backToAll() {
this.resetCurrentDay({ currentDay: -1 });
},
updateChart(data) {
this.chart.clear();
this.chart.setOption({
title: {
text: "营养分析",
subtext: data.name,
},
tooltip: {
position: "right",
trigger: "item",
// appendToBody: true,
formatter: (params) => {
const {
name,
marker,
percent,
data: { value, oriData, dim },
} = params;
return [
`${marker} ${name}`,
`摄入量:${oriData[`${dim}Weight`].toFixed(1)}`,
`摄入热量:${value.toFixed(1)}千卡`,
`供能比:${percent}%`,
].join("</br>");
},
},
series: [
{
name: data.name,
type: "pie",
radius: [0, 40],
center: ["50%", "55%"],
data: ["p", "f", "c"].map((dim) => ({
dim,
value: data[`${dim}Heat`],
name: this.nameDict[dim],
oriData: data,
})),
// labelLine: {
// length: 5,
// length2: 5,
// },
label: {
show: true,
position: "inside",
color: "#fff",
fontSize: 10,
fontWeight: "bold",
},
itemStyle: {
borderWidth: 1,
borderColor: "#fff",
},
},
],
});
},
...mapMutations(["resetCurrentDay"]),
},
watch: {
data(newVal, oldVal) {
if (newVal) {
this.$nextTick(() => {
this.updateChart(newVal[0]);
});
}
},
},
};
</script>
<style lang="scss" scoped>
.energy_pie_chart_wrapper {
}
</style>

View File

@ -3,8 +3,25 @@
:class="`aspect_pie_chart_wrapper ${className || ''}`" :class="`aspect_pie_chart_wrapper ${className || ''}`"
:style="{ height: height, width: width }" :style="{ height: height, width: width }"
> >
<div ref="echart" :style="{ height: height, width: '100px' }" /> <div
<div> ref="echart"
:style="{ height: height, width: !view ? '100px' : '100%' }"
/>
<div class="icon_btns">
<el-tooltip effect="dark" content="营养分析" placement="top">
<em
:class="['iconfont', 'icon-03', { sel_icon: view === 0 }]"
@click="handleOnViewChange(0)"
/>
</el-tooltip>
<el-tooltip effect="dark" content="热量分析" placement="top">
<em
:class="['iconfont', 'icon-fenxi', { sel_icon: view === 1 }]"
@click="handleOnViewChange(1)"
/>
</el-tooltip>
</div>
<div v-if="view === 0" class="table_zone">
<el-table <el-table
:data="mData" :data="mData"
size="mini" size="mini"
@ -24,16 +41,11 @@
{{ totalHeat.toFixed(1) }}千卡 {{ totalHeat.toFixed(1) }}千卡
</div> </div>
</div> </div>
<div </div>
style="text-align: right; margin-top: 4px" <el-button size="mini" type="text" @click="backToAll" class="see_all"
v-if="recipesData.length > 1"
>
<el-button size="mini" type="text" @click="backToAll"
>查看全部</el-button >查看全部</el-button
> >
</div> </div>
</div>
</div>
</template> </template>
<script> <script>
@ -76,10 +88,19 @@ export default {
f: "脂肪", f: "脂肪",
c: "碳水", c: "碳水",
}, },
menuDict: {
1: "早餐",
2: "早加餐",
3: "午餐",
4: "午加餐",
5: "晚餐",
6: "晚加餐",
},
typeDict: { typeDict: {
Weight: "摄入量", Weight: "摄入量",
Rate: "供能比", Rate: "供能比",
}, },
view: 1,
}; };
}, },
computed: { computed: {
@ -119,16 +140,17 @@ export default {
methods: { methods: {
initChart() { initChart() {
this.chart = echarts.init(this.$refs.echart, "myShine"); this.chart = echarts.init(this.$refs.echart, "myShine");
this.updateChart(this.data.length > 0 ? this.data[0] : {}); this.updateChart(this.data[0] || {});
}, },
backToAll() { backToAll() {
this.resetCurrentDay({ currentDay: -1 }); this.resetCurrentDay({ currentDay: -1 });
}, },
updateChart(data) { updateChart(data) {
// console.log(data);
this.chart.clear(); this.chart.clear();
this.chart.setOption({ const option = {
title: { title: {
text: "营养分析", text: !this.view ? "营养分析" : "热量分析",
subtext: data.name, subtext: data.name,
}, },
tooltip: { tooltip: {
@ -142,26 +164,90 @@ export default {
percent, percent,
data: { value, oriData, dim }, data: { value, oriData, dim },
} = params; } = params;
return [ return !this.view
? [
`${marker} ${name}`, `${marker} ${name}`,
`摄入量:${oriData[`${dim}Weight`].toFixed(1)}`, `摄入量:${oriData[`${dim}Weight`].toFixed(1)}`,
`摄入热量:${value.toFixed(1)}千卡`, `摄入热量:${value.toFixed(1)}千卡`,
`供能比:${percent}%`, `供能比:${percent}%`,
]
: [
`${marker} ${name}`,
`热量:${data[`heat${dim}`].toFixed(1)}千卡`,
`供能比:${percent}%`,
].join("</br>"); ].join("</br>");
}, },
}, },
graphic:
this.view === 1
? [
{
type: "group",
top: 60,
left: 10,
silent: true,
children: [
{
type: "text",
style: {
text: "总热量",
fill: "#606266",
},
},
{
type: "text",
top: 18,
left: 8,
style: {
text: `${this.totalHeat.toFixed(1)}千卡`,
font: '14px "Microsoft YaHei", sans-serif',
},
},
],
},
{
type: "group",
top: 36,
right: 10,
silent: true,
children: Object.keys(this.menuDict).reduce((arr, cur) => {
const tarData = data[`heat${cur}`];
if (tarData) {
arr.push({
type: "text",
top: arr.length * 20,
right: 10,
style: {
text: `${this.menuDict[cur]}${tarData.toFixed(1)}`,
fill: "#606266",
},
});
}
return arr;
}, []),
},
]
: [],
series: [ series: [
{ {
name: data.name, name: data.name,
type: "pie", type: "pie",
radius: [0, 40], radius: [0, !this.view ? 40 : 60],
center: ["50%", "55%"], center: ["50%", "55%"],
data: ["p", "f", "c"].map((dim) => ({ data: (!this.view
? Object.keys(this.nameDict)
: Object.keys(this.menuDict)
).reduce((arr, dim) => {
if (!this.view || data[`heat${dim}`]) {
arr.push({
dim, dim,
value: data[`${dim}Heat`], value: !this.view ? data[`${dim}Heat`] : data[`heat${dim}`],
name: this.nameDict[dim], name: (!this.view ? this.nameDict : this.menuDict)[dim],
oriData: data, oriData: data,
})), });
}
return arr;
}, []),
// labelLine: { // labelLine: {
// length: 5, // length: 5,
// length2: 5, // length2: 5,
@ -170,7 +256,7 @@ export default {
show: true, show: true,
position: "inside", position: "inside",
color: "#fff", color: "#fff",
fontSize: 10, fontSize: !this.view ? 10 : 12,
fontWeight: "bold", fontWeight: "bold",
}, },
itemStyle: { itemStyle: {
@ -179,7 +265,16 @@ export default {
}, },
}, },
], ],
};
console.log(option);
this.chart.setOption(option);
},
handleOnViewChange(view) {
this.view = view;
this.chart.resize({
width: !this.view ? 100 : 364,
}); });
this.updateChart(this.data[0] || {});
}, },
...mapMutations(["resetCurrentDay"]), ...mapMutations(["resetCurrentDay"]),
}, },
@ -195,21 +290,24 @@ export default {
}; };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
/deep/ :focus {
outline: 0;
}
.aspect_pie_chart_wrapper { .aspect_pie_chart_wrapper {
width: 100%; width: 100%;
display: flex; display: flex;
position: relative;
& > div:nth-child(1) { & > div:nth-child(1) {
// width: 200px // width: 200px
} }
// & > div:nth-child(2) {
.small_table { .small_table {
.my_cell { .my_cell {
padding: 2px 0 !important; padding: 2px 0 !important;
} }
} }
// }
.summary { .summary {
padding: 2px; padding: 2px;
@ -222,5 +320,31 @@ export default {
text-align: center; text-align: center;
} }
} }
.see_all {
position: absolute;
bottom: 4px;
left: 4px;
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> </style>