![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/6f65c6e697ae42008fde6be32de406c6.png)
思路
- 五个tab公用一个柱状图组件
- 切换tab以及切换时间改变数据,传入子组件,子组件监听数据重新更新
- 点击柱状图显示具体数值
- 每个时间点有两个柱子(高压和低压),柱状图显示高压的最大值到最小值的范围
- 除了血压其余只有一条柱子
- 步数比较特殊,不是范围,而是一个具体的步数数值
- 根据tab设置不同的最小值
- 假如最大值==最小值,显示一个点
- 所有横坐标全部显示,不滚动
![image.png](https://img-blog.csdnimg.cn/img_convert/fc0ca7b0ff2db16d3652c3c9a37316b3.png)
堆叠柱状图子组件
![image.png](https://img-blog.csdnimg.cn/img_convert/415b28935c029a262d0a8dbbafd1ee2f.png)
{
"component": true,
"usingComponents": {
"ec-canvas": "../../../ec-canvas/ec-canvas"
}
}
<view class="w100 h100">
<ec-canvas id="mychart-bar" canvas-id="mychart-bar" ec="{{ ec }}"></ec-canvas>
</view>
import * as echarts from '../../../ec-canvas/echarts';
Component({
options: {
addGlobalClass: true,
},
data: {
ec: {
lazyLoad: true
},
time: [],
low1: [],
high1: [],
low2: [],
high2: [],
step: []
},
properties: {
list: {
type: Array,
observer: function (newVal, oldVal) {
if (newVal.length || oldVal.length) {
console.log(newVal, oldVal, 88)
let time = newVal.map(item => item.date)
let low1 = newVal.map(item => item.firstLowIndicators * 1)
let high1 = newVal.map(item => item.firstHighIndicators && item.firstHighIndicators == item.firstLowIndicators ? 'solo' : item.firstHighIndicators * 1 - item.firstLowIndicators * 1)
let low2 = newVal.map(item => item.secondLowIndicators * 1)
let high2 = newVal.map(item => item.secondHighIndicators && item.secondHighIndicators == item.secondLowIndicators ? 'solo' : item.secondHighIndicators * 1 - item.secondLowIndicators * 1)
let step = newVal.map(item => item.firstHighIndicators)
this.setData({
time,
low1,
high1,
low2,
high2,
step
})
this.initChart();
}
}
},
tab: {
type: Number,
value: 1
}
},
methods: {
initChart() {
this.barComponent = this.selectComponent("#mychart-bar");
this.barComponent.init((canvas, width, height, dpr) => {
const chart = echarts.init(canvas, null, {
width: width,
height: height,
devicePixelRatio: dpr
})
chart.setOption(this.getOption())
return chart
})
},
getOption() {
var option = {
tooltip: {
trigger: "axis",
axisPointer: {
type: "shadow",
},
formatter: (params) => {
if (this.data.tab == 5) {
return (
params[0].axisValue +
"\n" +
params[0].marker +
params[1].seriesName +
":" +
(params[0].value || 0)
)
} else if (this.data.tab == 1) {
return (
params[0].axisValue +
"\n" +
params[1].marker +
params[0].seriesName +
":" +
params[0].value +
"~" +
(params[0].value + ((params[1].value + '').slice(-6) == '521125' ? 0 : params[1].value)) +
"\n" +
params[3].marker +
params[2].seriesName +
":" +
params[2].value +
"~" +
(params[2].value * 1 + ((params[3].value + '').slice(-6) == '521125' ? 0 : params[3].value * 1))
);
} else {
return (
params[0].axisValue +
"\n" +
params[1].marker +
params[0].seriesName +
":" +
params[0].value +
"~" +
(params[0].value + ((params[1].value + '').slice(-6) == '521125' ? 0 : params[1].value))
)
}
},
},
grid: {
top: '8%',
left: '5%',
right: '5%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
splitLine: {
show: false
},
data: this.data.time
},
yAxis: {
type: 'value',
min: [40, 80, 50, 34, 0][this.data.tab * 1 - 1],
},
series: [{
name: ['舒张压范围', '血氧范围', '心率范围', '体温范围', '步数'][this.data.tab * 1 - 1],
type: 'bar',
stack: 'Total',
barWidth: 4,
itemStyle: {
borderColor: 'transparent',
color: 'transparent'
},
data: this.data.tab == 5 ? 0 : this.data.low1
},
{
name: '',
type: 'bar',
stack: 'Total',
barWidth: 4,
label: {
position: 'inside'
},
itemStyle: {
color: '#2bdc70',
barBorderRadius: 10
},
data: this.data.tab == 5 ? this.data.step : this.data.high1.map(item => item == 'solo' ? [2.0521125, 0.3521125, 1.0521125, 0.12521125, 0][this.data.tab * 1 - 1] : item)
},
{
name: ['舒张压范围', '血氧范围', '心率范围', '体温范围', '步数'][this.data.tab * 1 - 1],
type: 'bar',
stack: 'Total1',
barWidth: 4,
itemStyle: {
borderColor: 'transparent',
color: 'transparent',
},
data: this.data.low2
},
{
name: '',
type: 'bar',
stack: 'Total1',
barWidth: 4,
label: {
position: 'inside'
},
itemStyle: {
color: '#fa5151',
barBorderRadius: 10
},
data: this.data.high2.map(item => item == 'solo' ? [2.0521125, 0.3521125, 0.521125, 0.0521125, 0][this.data.tab * 1 - 1] : item)
}
]
};
return option
}
}
})
父组件
<view style="width: 100%; height: 260px;">
<my-bar list="{{barList}}"></my-bar>
</view>
"usingComponents": {
"my-bar": "./components/bar/bar",
"solo-table": "./components/table/table"
},
barList: [{
time: this.data.active,
low1: 50,
high1: 80,
low2: 80,
high2: 140
}, {
time: this.data.active,
low1: 50,
high1: 90,
low2: 90,
high2: 150
}, {
time: this.data.active,
low1: 50,
high1: 80,
low2: 70,
high2: 100
}, {
time: this.data.active,
low1: 50,
high1: 80,
low2: 60,
high2: 140
}, {
time: this.data.active,
low1: 70,
high1: 100,
low2: 100,
high2: 140
}, ]
定制echarts.min.js
![image.png](https://img-blog.csdnimg.cn/img_convert/eb86e5eaea1e479745c59e9ad0857337.png)
完整父组件
<view class="w100 min100">
<van-sticky offset-top="{{ 0 }}">
<van-tabs style="z-index: 99;" sticky animated class="gray-2 bold bg-white" active="{{ tab }}" bind:change="onChangeTab" color="#217EF7" line-width="{{20}}" line-height="{{4}}">
<van-tab title="血压" name="1"></van-tab>
<van-tab title="血氧" name="2"></van-tab>
<van-tab title="心率" name="3"></van-tab>
<van-tab title="体温" name="4"></van-tab>
<van-tab title="步数" name="5"></van-tab>
</van-tabs>
</van-sticky>
<time bindchangeTab="onChangeTime" bindchangeDay="onChangeDay"></time>
<view class="flex w100 pl-30 ptb-20">
<view class="bold size-32 flex-1">{{title}}统计分析</view>
<!-- <van-tabs animated type="card" class="gray-2 flex-1" active="{{ active }}" bind:change="onChangeTime" color="#217EF7">
<van-tab title="日" name="1"></van-tab>
<van-tab title="周" name="2"></van-tab>
<van-tab title="月" name="3"></van-tab>
</van-tabs> -->
</view>
<view style="width: 100%; height: 250px;">
<my-bar list="{{barList}}" tab="{{tab*1}}"></my-bar>
</view>
<view class="pd-30">
<table1 head="{{head}}" list="{{tableList}}" tab="{{tab*1}}">
</table1>
</view>
<view wx:if="{{tab==1}}">
<view class="bold size-32 flex-1 plr-30 mt-30 mb-30">近30天血压趋势情况</view>
<view style="width: 100%; height: 320px;">
<my-scatter list="{{scatterList}}"></my-scatter>
</view>
<view class="pd-30">
<solo-table total="{{total}}" list="{{soloTable}}"></solo-table>
</view>
</view>
</view>
{
"usingComponents": {
"my-bar": "./components/bar/bar",
"bar1": "./components/bar1/bar",
"my-scatter": "./components/scatter/scatter",
"solo-table": "./components/solo-table/table",
"table1": "./components/table/table",
"time": "./components-time/time/time"
},
"navigationBarTitleText": "健康监测"
}
Page({
data: {
tab: 1,
title: '血压',
timeRange: 'day',
queryDate: '',
barList: [],
stepList: [],
scatterList: [],
total: 0,
soloTable: [],
head: [{
text: '指标',
prop: 'name'
},
{
text: '最高',
prop: 'max'
},
{
text: '最低',
prop: 'min'
},
{
text: '参考值',
prop: 'range'
}
],
tableList: []
},
onLoad(option) {
let now = this.getNowData(new Date(), 'day')
this.setData({
timeRange: 'day',
queryDate: now.content
})
this.getList()
this.getList30()
},
getList() {
let {
timeRange,
queryDate,
tab
} = this.data
console.log(timeRange, queryDate, 8888888888888, timeRange == 'weeks' ? queryDate.split(' 至 ').join(',') : timeRange == 'day' ? queryDate : queryDate.split(' 至 ')[0].split('-')[0] + '-' + queryDate.split(' 至 ')[0].split('-')[1])
wx.http('occupant/health-records/chartList', Object.assign({
dataSource: 1,
userId: wx.getStorageSync('userInfo').userId,
timeRange: timeRange == 'weeks' ? 'week' : timeRange,
queryDate: timeRange == 'weeks' ? queryDate.split(' 至 ').join(',') : timeRange == 'day' ? queryDate : queryDate.split(' 至 ')[0].split('-')[0] + '-' + queryDate.split(' 至 ')[0].split('-')[1],
firstIndicator: ['diastolic_blood_pressure', 'blood_oxygen', 'heart_rate', 'temperature', 'step_count'][tab * 1 - 1],
}, tab == 1 ? {
secondIndicator: ['systolic_blood_pressure'][tab * 1 - 1]
} : {})).then(res => {
if (res.data.table && res.data.table.length) {
if (tab == 1) {
res.data.table[0].name = '舒张压'
res.data.table[0].range = '60-90'
res.data.table[1].range = '90-140'
res.data.table[1].name = '收缩压'
} else if (tab == 2) {
res.data.table[0].name = '血氧'
res.data.table[0].range = '95-100%'
} else if (tab == 3) {
res.data.table[0].name = '心率'
res.data.table[0].range = '60-100'
} else if (tab == 4) {
res.data.table[0].name = '体温'
res.data.table[0].range = '35.3-37.3℃'
} else if (tab == 5) {
res.data.table[0].name = '步数'
res.data.table[0].range = '5000-10000步'
}
}
this.setData({
barList: res.data.charts || [],
tableList: res.data.table
})
})
},
getList30() {
wx.http('occupant/health-records/bloodPressureTrend', {
dataSource: 1,
userId: wx.getStorageSync('userInfo').userId,
}).then(res => {
this.setData({
scatterList: res.data.charts,
total: res.data.total,
soloTable: res.data.table,
})
})
},
onChangeTab(e) {
this.setData({
tab: e.detail.name,
title: e.detail.title
})
this.getList()
if (this.data.tab == 1) {
this.getList30()
}
},
getNowData(date, dateType, direction) {
let updateData = {};
let content = "";
let year = date.getFullYear();
let month = date.getMonth() + 1;
let day = date.getDate();
let weeksDay = date.getDay();
switch (dateType) {
case 'day': {
year = date.getFullYear();
month = date.getMonth() + 1;
day = date.getDate();
content = year + "-" + month + "-" + day;
break;
}
case 'weeks': {
weeksDay = date.getDay();
let starDate = new Date(date.getTime());
starDate.setDate(date.getDate() - weeksDay + 1);
let startYear = starDate.getFullYear();
let startMonth = starDate.getMonth() + 1;
let startDay = starDate.getDate();
let endDate = new Date(date.getTime());
let endYear = endDate.getFullYear();
let endMonth = endDate.getMonth() + 1;
let endDay = endDate.getDate();
content = startYear + "-" + startMonth + "-" + startDay + ' 至 ' + endYear + "-" + endMonth + "-" + endDay;
break;
}
case 'month': {
let starDate = new Date(date.getTime());
starDate.setDate(1);
let startYear = starDate.getFullYear();
let startMonth = starDate.getMonth() + 1;
let startDay = starDate.getDate();
let endDate = new Date(date.getTime());
let endYear = endDate.getFullYear();
let endMonth = endDate.getMonth() + 1;
let endDay = endDate.getDate();
content = startYear + "-" + startMonth + "-" + startDay + ' 至 ' + endYear + "-" + endMonth + "-" + endDay;
break;
}
}
updateData.content = content;
return updateData;
},
onChangeDay(e) {
console.log(e.detail.id, 999999)
this.setData({
queryDate: e.detail.id.date.curDate,
})
if (e.detail.id.type) {
this.setData({
timeRange: e.detail.id.type,
})
}
this.getList()
},
});