| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551 |
- <template>
- <div class="content">
- <div class="top" :style="{ backgroundColor: bgColor }">
- <span class="watchState">{{ watchText }} {{ battery }}</span>
- <div class="toprow">
- <div class="lt">
- <div class="activeLevel">
- <div v-if="activeState">
- <s>%</s>
- <em>{{ activeLevel }}</em>
- </div>
- <div v-else>
- <s class="noValue">--</s>
- </div>
- </div>
- <span @click="showVersion">{{ activeLevelText }}</span>
- </div>
- <div class="md">
- <div class="headContainer">
- <img :src="userHead" />
- </div>
- <span class="username">
- <em>{{ username }}</em>
- <img
- src="../static/images/main/male.png"
- height="60"
- width="60"
- v-if="sex == 1"
- />
- <img
- src="../static/images/main/female.png"
- height="60"
- width="60"
- v-if="sex == 2"
- />
- </span>
- </div>
- <div class="rt">
- <div class="heartJump">
- <div v-if="activeState">
- <img src="../static/images/main/heart.png" height="74" width="86" />
- <em
- :class="[
- { 'normalJump': activeLevel > 30 && activeLevel <= 90 },
- { 'fastJump': activeLevel > 90 },
- { 'slowJump': activeLevel < 30 },
- ]"
- >{{ heartRate }}</em>
- </div>
- <div v-else>
- <s class="noValue">--</s>
- </div>
- </div>
- <span @click="showConsole()">瞬时心率</span>
- </div>
- </div>
- </div>
- <div class="info">
- <ul>
- <li>
- <em>{{ height }}</em>
- <span>身高cm</span>
- </li>
- <li>
- <em>{{ age }}</em>
- <span>年龄</span>
- </li>
- <li>
- <em>{{ weight }}</em>
- <span>体重kg</span>
- </li>
- <li>
- <em>{{ peaceHeart }}</em>
- <span>静息心率</span>
- </li>
- </ul>
- </div>
- <div class="row">
- <div class="rowCenter" v-if="!watchState" @click="connectWatch">
- <img src="../static/images/main/chain.png" />
- <em>心率带未连接</em>
- <button>点击连接</button>
- </div>
- <div class="classInfo" v-if="InClass == 1 && watchState">
- <em>
- <span>课程名称:</span>
- {{ DpName }}
- </em>
- </div>
- <div class="breakConect" v-if="watchState">
- <em>心率带{{ NorMalSn }}已连接</em>
- <button @click="closeBLEConnectionAlert">断开连接</button>
- </div>
- </div>
- <div class="middle">
- <ul>
- <li>
- <div class="center">
- <em>{{ cal | parseToInt }}</em>
- <img src="../static/images/main/normal.png" />
- <span>卡路里</span>
- </div>
- </li>
- <li>
- <div class="center">
- <em>{{ sportCal | parseToInt }}</em>
- <img src="../static/images/main/redfire.png" />
- <span>运动卡路里</span>
- </div>
- </li>
- <li>
- <div class="center">
- <em>{{ ck | parseToFix1 }}</em>
- <img src="../static/images/main/ck.png" class="ck" />
- <span>CK</span>
- </div>
- </li>
- </ul>
- </div>
- <div class="bottom">
- <h5>心率趋势图</h5>
- <span>最大心率 : {{ heartMax }} 平均心率 : {{ heartAverage }}</span>
- <Line-example
- :width="screenWidth"
- :height="screenHeight"
- :dataLabels="dataLabels"
- :datadatasets="dataDatasets"
- />
- <em
- v-if="activeState"
- :class="[
- { 'normalJump': activeLevel > 30 && activeLevel <= 90 },
- { 'fastJump': activeLevel > 90 },
- { 'slowJump': activeLevel < 30 },
- ]"
- :style="{ bottom: parseInt(screenHeight - 30) + 'px' }"
- >{{ heartRate }}</em>
- <div class="logoutBtn">
- <mu-button color="info" @click.native="logoutBtn">退出登陆</mu-button>
- <br />
- <!-- <mu-button color="error" @click.native="delDefault">删除默认</mu-button> -->
- </div>
- </div>
- <mu-dialog
- title
- width="600"
- max-width="80%"
- :esc-press-close="true"
- :overlay-close="true"
- :open.sync="openAlert"
- >
- <p v-if="!watchListState">没有任何设备</p>
- <div class="watchList" v-else>
- <p>请选择设备</p>
- <ul>
- <li v-for="w in watchs" @click="choiceWatch(w)">
- {{ w.localName.substr(6, 13) }}
- <em>信号:{{ w.RSSI | parseLevel }}</em>
- </li>
- </ul>
- </div>
- <br />
- <mu-button
- slot="actions"
- flat
- color="primary"
- @click="closeAlertDialog"
- v-if="watchListState"
- >取消</mu-button>
- <mu-button slot="actions" flat color="primary" @click="searchWatch" v-else>搜索</mu-button>
- </mu-dialog>
- <mu-dialog
- width="600"
- max-width="80%"
- :esc-press-close="false"
- :overlay-close="false"
- :open.sync="openBreakAlert"
- >
- <h5>是否断开心率带蓝牙连接?</h5>
- <p>(断开后将不再上传心率信息)</p>
- <mu-button slot="actions" flat color="primary" @click="openBreakAlert = false">取消</mu-button>
- <mu-button slot="actions" flat color="primary" @click="closeBLEConnection">断开</mu-button>
- </mu-dialog>
- <mu-dialog title="Dialog" width="360" :open.sync="openSimple">
- <p>请求心率带蓝牙失败,请退出APP,重启蓝牙开关</p>
- <mu-button slot="actions" flat color="primary" @click="openSimple = false">知道了</mu-button>
- </mu-dialog>
- </div>
- </template>
- <script>
- import LineExample from '../components/LineExample'
- import {
- UserSelfQuery,
- GetDuInfoAndUserInfoByUserMd5,
- HrSensorsUpdate,
- AddAppHeartRate,
- } from '../api/getApiRes.js'
- let qs = require('qs');
- export default {
- data() {
- return {
- runMode: '',//'' 为正常模式 mock 为模拟操作模式
- isClassTime: 5000,//上课状态检测频率
- isAddHeartTime: 1000,//心率上报检测频率
- dataLabels: [],
- dataDatasets: [],
- watchText: '',
- battery: '',
- userHead: 'http://xhead.beswell.com/flyhead.png',
- watchState: false,//false
- bgColor: '#028FE1',
- activeLevel: 0,
- activeLevelText: '激活放松',
- heartRate: 0,
- activeState: false,//false
- openAlert: false,//false
- openBreakAlert: false,//false
- alertState: false,//false
- watchListState: false,//false
- username: 'XXX',
- sex: 1,
- height: 148,
- age: 8,
- weight: 38,
- peaceHeart: 70,
- heartMax: 0,
- heartAverage: 0,
- cal: 0,
- sportCal: 0,
- ck: 0,
- addCalories: 0,//增量卡路里
- addPureCalories: 0,//增量运动卡路里
- screenWidth: parseInt(document.body.clientWidth - 10),
- screenHeight: parseInt(document.documentElement.clientHeight / 3),
- watchs: [],
- begin: null,
- heartLine: [],
- InClass: 0,//是否上课
- DpName: 'XXXX',//课程名称
- HrId: '',//心率带
- duId: 0,
- sn: '',
- NorMalSn: '',
- deviceId: '',
- sumError: 0,
- openSimple: false,
- breakStateTimer: null,
- }
- },
- mounted() {
- this.init();
- this.getBodyInfo();
- // 获取上课状态
- clearInterval(this.timerisClass);
- this.timerisClass = setInterval(() => {
- this.isClass();
- }, this.isClassTime);
- // 上报心率信息
- clearInterval(this.timerAutoAddAppHeartRate);
- this.timerAutoAddAppHeartRate = setInterval(() => {
- // 已连接时轮询连接状态
- if (this.watchState) {
- // 自动获取心率带蓝牙连接状态
- this.listenerConnection();
- }
- // 上课中,且已连接心率带
- if (this.InClass == 1 && this.watchState && this.runMode != 'mock') {
- // 上课就自动上报
- this.AutoAddAppHeartRate();
- } else {
- // console.log('下课中,不汇报1');
- }
- }, this.isAddHeartTime);
- },
- beforeDestroy() {
- clearInterval(this.timerisClass);
- clearInterval(this.timerAutoAddAppHeartRate);
- },
- watch: {
- activeLevel(val) {
- let that = this;
- switch (true) {
- case parseInt(val) < 39:
- that.bgColor = '#028FE1';
- that.activeLevelText = '激活放松';
- break;
- case parseInt(val) < 54 && parseInt(val) >= 39:
- that.bgColor = '#6D29FA';
- that.activeLevelText = '动态热身';
- break;
- case parseInt(val) < 69 && parseInt(val) >= 54:
- that.bgColor = '#0AB105';
- that.activeLevelText = '脂肪燃烧';
- break;
- case parseInt(val) < 79 && parseInt(val) >= 69:
- that.bgColor = '#B9CB01';
- that.activeLevelText = '糖分消耗';
- break;
- case parseInt(val) < 89 && parseInt(val) >= 79:
- that.bgColor = '#EA8813';
- that.activeLevelText = '心肺训练';
- break;
- case parseInt(val) >= 90:
- that.bgColor = '#D11122';
- that.activeLevelText = '峰值锻炼';
- break;
- }
- // 动态显示背景色
- plus.navigator.setStatusBarBackground(that.bgColor);
- },
- },
- methods: {
- init() {
- let that = this;
- if (this.runMode == 'mock') {
- this.mockCreateDate();
- } else {
- if (window.plus) {
- console.log('mui is plusReady');
- that.allPlusReady();
- } else {
- console.log('mui is not ready');
- document.addEventListener('plusready', function(e) {
- that.allPlusReady();
- });
- }
- }
- },
- allPlusReady() {
- let that = this;
- // that.setWakelock();
- plus.bluetooth.onBLECharacteristicValueChange(function(e) {
- if (e.characteristicId == '00002A19-0000-1000-8000-00805F9B34FB') {
- // 获取电量
- var value = that.buffer2hexPower(e.value);
- that.watchText = '心率带已连接,电量:';
- that.battery = value + '%';
- } else {
- // 成功获取心跳
- that.heartRate = parseInt(that.parseHeartRate(e.value).heartRate);
- that.watchText = '心率带已连接,电量:';
- that.activeState = true;
- // 运动强度计算
- that.calcActLevel(that.heartRate);
- that.openAlert = false;//关闭弹窗
- that.watchState = true;//关闭连接按钮并显示当前课程名
- // 卡路里计算
- that.calcCalorie(that.heartRate);
- that.heartLine.push(that.heartRate);
- that.dataLabels.push('');
- if (that.heartLine.length > 30) {
- that.heartLine.shift();
- that.dataLabels.shift();
- }
- that.DrawHeartLine(that.heartLine, that.dataLabels);
- }
- });
- // 自动重连上次心率带
- that.AutoContectLast();
- },
- // 屏幕常亮
- setWakelock() {
- plus.device.setWakelock(true);
- console.log('屏幕常量已开启');
- },
- // 震动
- vibrate() {
- let milliseconds = 500;
- plus.device.vibrate(milliseconds)
- },
- showConsole() {
- let vconDom = document.getElementById('__vconsole');
- this.toggleClass(vconDom, 'show')
- },
- toggleClass(obj, cls) {
- if (this.hasClass(obj, cls)) {
- this.removeClass(obj, cls);
- } else {
- this.addClass(obj, cls);
- }
- },
- hasClass(obj, cls) {
- return obj.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'));
- },
- addClass(obj, cls) {
- if (!this.hasClass(obj, cls)) obj.className += " " + cls;
- },
- removeClass(obj, cls) {
- if (this.hasClass(obj, cls)) {
- var reg = new RegExp('(\\s|^)' + cls + '(\\s|$)');
- obj.className = obj.className.replace(reg, ' ');
- }
- },
- // 测试 生成心率数据
- mockCreateDate() {
- let that = this;
- clearInterval(this.timermockCreateDate);
- this.timermockCreateDate = setInterval(() => {
- that.battery = '999%';
- // 成功获取心跳
- that.heartRate = parseInt(Math.random() * 100 + 90);
- that.watchText = '心率带已连接';
- that.activeState = true;
- // 运动强度计算
- that.calcActLevel(that.heartRate);
- that.openAlert = false;//关闭弹窗
- that.watchState = true;//关闭连接按钮
- // 卡路里计算
- that.calcCalorie(that.heartRate);
- that.heartLine.push(that.heartRate);
- that.dataLabels.push('');
- if (that.heartLine.length > 3) {
- that.heartLine.shift();
- that.dataLabels.shift();
- }
- that.DrawHeartLine(that.heartLine, that.dataLabels);
- }, 1000);
- },
- // 是否正在上课
- isClass() {
- let that = this;
- let param = {
- token: localStorage.token,
- };
- let postdata = qs.stringify(param);
- GetDuInfoAndUserInfoByUserMd5(postdata).then(res => {
- let json = res;
- if (json.Code == 0) {
- that.InClass = json.InClass;//0下课,1上课
- // 记录duid
- that.duId = parseInt(json.DuInfo.DuId);
- that.DpName = json.DuInfo.DpName;
- // 正在上课且已连心率带
- if (that.InClass == 1 && that.watchState) {
- console.log('InClass' + that.InClass);
- // 上课状态拿一次心率带信息
- that.AddHrSensorsUpdate();
- }
- } else {
- that.Toast(json.Memo);
- }
- })
- },
- buffer2hexPower(value) {
- var t = '';
- if (value) {
- var v = new Uint8Array(value);
- for (var i in v) {
- // t += '0x' + v[i].toString(16) + ' ';
- t += v[i].toString(10) + ' ';
- }
- } else {
- t = '无效值';
- }
- return t;
- },
- connectWatch() {
- // 打开蓝牙适配器
- let that = this;
- if (typeof plus == 'undefined') {
- that.Toast('当前设备不支持蓝牙心率带', 'error');
- return false
- }
- plus.bluetooth.openBluetoothAdapter({
- success: function(e) {
- that.Toast('蓝牙适配器打开成功!', 'success');
- that.openAlert = true;
- that.searchWatch();
- return e
- },
- fail: function(e) {
- that.Toast('打开失败! 请确认蓝牙开关已开启', 'error');
- }
- });
- },
- closeAlertDialog() {
- this.openAlert = false;
- },
- // 监听搜索到新设备
- searchWatch() {
- let that = this;
- that.watchs = [];
- plus.bluetooth.startBluetoothDevicesDiscovery({
- // services: ['heart_rate'],//ios不支持
- success: function(e) {
- that.Toast('开始搜索成功!', 'success');
- plus.bluetooth.onBluetoothDeviceFound(function(e) {
- let devices = e.devices;
- let row = [];
- for (let i in devices) {
- let device = devices[i];
- // localName CL831
- if (device.localName.indexOf('CL831') != -1) {
- console.log(JSON.stringify(device));
- that.watchs.push(device);
- }
- }
- that.watchListState = true;
- });
- },
- fail: function(e) {
- that.Toast('开始搜索失败! ' + JSON.stringify(e));
- }
- });
- },
- choiceWatch(w) {
- let that = this;
- that.Toast('连接心率带' + w.localName.substring(6, 13) + '中...', 'success');
- console.log('连接心率带' + w.deviceId);
- that.deviceId = w.deviceId
- // 建立连接
- plus.bluetooth.createBLEConnection({
- deviceId: w.deviceId,
- success: function(e) {
- // 记录心率带sn
- that.sn = w.localName;
- localStorage.sn = that.sn;
- localStorage.w = JSON.stringify(w);
- that.AddHrSensorsUpdate();
- that.Toast('连接成功!', 'success');
- // 渲染完毕再执行这个,所以才能没有延时的更改
- // 需要一个回调等待5S
- clearTimeout(that.timer); //清除延迟执行
- that.timer = setTimeout(() => { //设置延迟执行
- // 获取服务
- that.getServices(w);
- }, 2000);
- },
- fail: function(e) {
- console.log('连接失败! 请重新连接' + JSON.stringify(e));
- if (e.code == 10000) {
- console.log(123);
- }
- that.Toast('连接失败! 请重新连接' + JSON.stringify(e));
- },
- })
- },
- getServices(w) {
- let that = this;
- that.Toast('获取蓝牙设备服务:', 'success');
- plus.bluetooth.getBLEDeviceServices({
- deviceId: w.deviceId,
- success: function(e) {
- that.Toast('获取蓝牙服务成功!', 'success');
- // 获取服务的特征值
- var HEARTuuid = "0000180D-0000-1000-8000-00805F9B34FB";//HEART RATE
- var Batteryuuid = "0000180F-0000-1000-8000-00805F9B34FB";//Battery
- that.getBatteryCharacteristics(w.deviceId, Batteryuuid);
- clearTimeout(that.timer); //清除延迟执行
- that.timer = setTimeout(() => { //设置延迟执行
- // 获取心跳服务
- that.getCharacteristics(w.deviceId, HEARTuuid);
- }, 3000);
- },
- fail: function(e) {
- console.log('获取服务失败,devicedId:' + w.deviceId);
- console.log('获取服务失败! ' + JSON.stringify(e));
- that.Toast('获取服务失败!请重试 ' + JSON.stringify(e), 'error');
- // 10004无连接, 重启一次蓝牙Adapter
- if (e.code == 10004) {
- that.sumError += 1;
- if (that.sumError > 3) {
- }
- }
- }
- });
- },
- // 获取服务的特征值
- getCharacteristics(deviceId, serviceId) {
- let that = this;
- let chaaracterUuid = '00002A37-0000-1000-8000-00805F9B34FB';
- let characteristicId = null;
- plus.bluetooth.getBLEDeviceCharacteristics({
- deviceId: deviceId,
- serviceId: serviceId,
- success: function(e) {
- let characteristics = e.characteristics;
- that.Toast('获取心率带蓝牙服务成功! ', 'success');
- console.log('特征值列表: ' + JSON.stringify(characteristics));
- plus.bluetooth.notifyBLECharacteristicValueChange({ //监听数据变化
- deviceId: deviceId,
- serviceId: serviceId,
- characteristicId: chaaracterUuid,
- success: function(e) {
- console.log('---> 获取心跳服务' + JSON.stringify(e));
- console.log('---> notifyBLECharacteristicValueChange ' + chaaracterUuid + ' success.');
- // 服务获取成功,震动提示
- // that.vibrate();
- //that.onValuesChange();
- },
- fail: function(e) {
- that.Toast('获取特征值失败!重启APP后再次尝试 ' + JSON.stringify(e));
- }
- });
- },
- fail: function(e) {
- console.log('获取特征值失败! ' + JSON.stringify(e));
- that.Toast('获取特征值失败!重启APP后再次尝试 ' + JSON.stringify(e));
- }
- })
- },
- // 获取服务的特征值
- getBatteryCharacteristics(deviceId, serviceId) {
- let that = this;
- let chaaracterUuid = '00002A19-0000-1000-8000-00805F9B34FB';
- let characteristicId = null;
- that.readValue(deviceId, serviceId, chaaracterUuid);
- plus.bluetooth.getBLEDeviceCharacteristics({
- deviceId: deviceId,
- serviceId: serviceId,
- success: function(e) {
- var characteristics = e.characteristics;
- that.Toast('获取心率带服务成功! ' + characteristics.length, 'success');
- plus.bluetooth.notifyBLECharacteristicValueChange({ //监听数据变化
- deviceId: deviceId,
- serviceId: serviceId,
- characteristicId: chaaracterUuid,
- success: function(e) {
- console.log('notifyBLECharacteristicValueChange' + JSON.stringify(e));
- },
- fail: function(e) {
- that.Toast('notifyBLECharacteristicValueChange失败! ' + JSON.stringify(e));
- }
- });
- },
- fail: function(e) {
- console.log('获取特征值失败! ' + JSON.stringify(e));
- that.Toast('获取特征值失败!重启APP后再次尝试 ' + JSON.stringify(e));
- }
- })
- },
- readValue(deviceId, serviceId, characteristicId) {
- let that = this;
- plus.bluetooth.readBLECharacteristicValue({
- deviceId: deviceId,
- serviceId: serviceId,
- characteristicId: characteristicId,
- success: function(e) {
- console.log("读取电量数据成功" + JSON.stringify(e));
- },
- fail: function(e) {
- that.Toast('读取电量数据失败!重启APP后再次尝试 ' + JSON.stringify(e));
- }
- });
- },
- // 获取基础身体数据
- getBodyInfo() {
- let that = this;
- let param = {
- token: localStorage.token,
- };
- let postdata = qs.stringify(param);
- UserSelfQuery(postdata).then(res => {
- let json = res;
- if (json.Code == 0) {
- that.username = json.Rs.UserName;
- that.sex = json.Rs.Sex;
- that.height = json.Rs.Height;
- // Birthday
- let age = parseInt((new Date().getTime() - new Date(json.Rs.Birthday).getTime()) / (365 * 24 * 60 * 60 * 1000));
- that.age = age;
- that.weight = parseInt(json.Rs.Weight) / 10;
- that.peaceHeart = json.Rs.StaticHr;
- // 有无默认头像
- if (json.Rs.Head) {
- that.userHead = json.Rs.Head;
- } else {
- that.userHead = 'http://xhead.beswell.com/flyhead.png';//默认头像
- }
- } else {
- if (json.Code == 9999999999) {
- that.Toast('登陆已失效,请重新登陆');
- localStorage.token = '';
- this.$router.push({ path: '/login' });
- } else {
- that.Toast(json.Memo, 'error');
- }
- }
- })
- },
- parseHeartRate(data) {
- var data = new DataView(data);
- const flags = data.getUint8(0);
- const rate16Bits = flags & 0x1;
- const result = {};
- let index = 1;
- if (rate16Bits) {
- result.heartRate = data.getUint16(index, /*littleEndian=*/ true);
- index += 2;
- } else {
- result.heartRate = data.getUint8(index);
- index += 1;
- }
- const contactDetected = flags & 0x2;
- const contactSensorPresent = flags & 0x4;
- if (contactSensorPresent) {
- result.contactDetected = !!contactDetected;
- }
- const energyPresent = flags & 0x8;
- if (energyPresent) {
- result.energyExpended = data.getUint16(index, /*littleEndian=*/ true);
- index += 2;
- }
- const rrIntervalPresent = flags & 0x10;
- if (rrIntervalPresent) {
- const rrIntervals = [];
- for (; index + 1 < data.byteLength; index += 2) {
- rrIntervals.push(data.getUint16(index, /*littleEndian=*/ true));
- }
- result.rrIntervals = rrIntervals;
- }
- return result;
- }
- ,
- // 活动强度计算公式
- calcActLevel(heartRate) {
- let actLevel = (heartRate - this.peaceHeart) / (208 - 0.7 * this.age - this.peaceHeart) * 100;
- actLevel = actLevel > 100 ? 100 : actLevel < 0 ? 0 : actLevel;
- this.activeLevel = parseInt(actLevel);
- },
- // 持续时间
- calcHoldTime(curTime) {
- let that = this;
- let res = 0;
- if (this.begin) {
- res = parseInt(curTime.getTime() - this.begin.getTime()) / 1;
- // 上次上报时间
- // console.log('res' + res);
- } else {
- res = 0;
- }
- that.begin = new Date();
- return parseInt(res)
- },
- // 计算卡路里
- calcCalorie(heartRate) {
- let that = this;
- // 取不到正常心跳数就从本地取出来
- if (parseInt(heartRate) == 0) {
- heartRate = localStorage.heartRate
- } else {
- localStorage.heartRate = heartRate
- }
- let calorieNoVo2 = 0;
- let curTime = that.calcHoldTime(new Date());
- // 男
- if (that.sex == 1) {
- calorieNoVo2 = ((-55.0969 + (0.6309 * heartRate) + (0.1988 * that.weight) + (0.2017 * that.age)) / 4.184) / 60000 * curTime;
- } else {
- calorieNoVo2 = ((-20.4022 + (0.4472 * heartRate) - (0.1263 * that.weight) + (0.074 * that.age)) / 4.184) / 60000 * curTime;
- }
- // 记录增量卡路里
- that.addCalories = calorieNoVo2;
- that.cal = that.cal + calorieNoVo2;
- // console.log('heartRate:' + heartRate);
- // console.log('calorieNoVo2:' + calorieNoVo2);
- // 计算CK
- that.calcCk(that.cal);
- that.calcSportCal(calorieNoVo2, curTime)
- },
- // 计算CK
- calcCk(cal) {
- this.ck = parseFloat(cal / this.weight).toFixed(2);
- },
- // 计算运动卡路里
- calcSportCal(calorieNoVo2,curTime) {
- let that = this;
- let bmrMSjDaily = 0;
- // 男
- if (that.sex == 1) {
- bmrMSjDaily = (10.00 * this.weight) + (6.25 * this.height) - (5.00 * this.age) + 5.00;
- } else {
- // 女
- bmrMSjDaily = (10.00 * this.weight) + (6.25 * this.height) - (5.00 * this.age) - 161
- }
- // 不为负值
- if (bmrMSjDaily < 0) {
- bmrMSjDaily = 0;
- }
- let BmrMSjRmrcb = parseFloat((bmrMSjDaily * 1.1) / 24);
- // let calorieNoVo2Pure = (calorieNoVo2 - BmrMSjRmrcb / 3600 * 1);
- let calorieNoVo2Pure = (calorieNoVo2 - BmrMSjRmrcb / curTime);
- // 记录增量运动卡路里
- that.addPureCalories = calorieNoVo2Pure;
- this.sportCal = this.sportCal + calorieNoVo2Pure;
- },
- // 绘制心电图
- DrawHeartLine(heartLine, dataLabels) {
- this.dataLabels = dataLabels;
- this.dataDatasets = heartLine;
- this.calcMaxHr(heartLine);
- this.calcAveHr(heartLine);
- },
- // 最大心率
- calcMaxHr(heartLine) {
- this.heartMax = Math.max(...heartLine);
- },
- // 平均心率
- calcAveHr(heartLine) {
- var sum = 0;
- for (var i = 0; i < heartLine.length; i++) {
- sum += heartLine[i];
- }
- this.heartAverage = parseInt(sum / heartLine.length);
- },
- // 上报信息
- AutoAddAppHeartRate() {
- let that = this;
- // console.log('duId:' + that.duId);
- let NorMalSn = that.sn.substring(6, that.sn.length);
- console.log('NorMalSn:' + parseInt(NorMalSn));
- let param = {
- token: localStorage.token,
- duId: that.duId,
- sn: parseInt(NorMalSn),
- hrId: that.HrId,
- heartRate: that.heartRate,
- rcvTime: new Date().getTime(),
- calories: parseInt(that.addCalories * 1000000), //卡
- pureCalories: parseInt(that.addPureCalories * 1000000), //卡
- };
- console.log(JSON.stringify(param));
- let postdata = qs.stringify(param);
- AddAppHeartRate(postdata).then(res => {
- let json = res;
- if (json.Code == 0) {
- that.InClass = json.InClass;
- console.log('心率数据上传成功!');
- } else {
- // that.Toast( '心率数据上传失败' + json.Memo);
- console.log('心率数据上传失败' + json.Memo);
- }
- })
- },
- AddHrSensorsUpdate() {
- let that = this;
- let NorMalSn = that.sn.substring(6, that.sn.length);
- that.NorMalSn = NorMalSn;
- console.log('==========>NorMalSn:' + parseInt(NorMalSn));
- let param = {
- token: localStorage.token,
- sn: parseInt(NorMalSn),
- };
- let postdata = qs.stringify(param);
- HrSensorsUpdate(postdata).then(res => {
- let json = res;
- console.log('HrSensorsUpdate' + JSON.stringify(json));
- if (json.Code == 0) {
- that.HrId = json.HrId;
- // that.Toast('心率带已连接在线课程', 'success');
- } else {
- that.HrId = '';
- // that.Toast(json.Memo);
- }
- })
- },
- // 监听蓝牙设备连接状态
- listenerConnection() {
- let that = this;
- plus.bluetooth.onBLEConnectionStateChange(function(e) {
- that.watchState = e.connected;
- if (!that.watchState) {
- that.isBreakSteate();
- }
- });
- },
- isBreakSteate() {
- let that = this;
- that.Toast('心率带已断开蓝牙连接,请重新连接', 'error');
- that.battery = '';
- that.watchText = '心率带已断开蓝牙连接';
- that.activeState = false;
- },
- Loading() {
- const loading = this.$loading({
- overlayColor: 'hsla(0,0%,100%,.9)', // 背景色
- size: 48,
- color: 'primary', // color
- });
- setTimeout(() => {
- loading.close();
- }, 3000)
- },
- // 打开断开连接提示窗口
- closeBLEConnectionAlert() {
- this.openBreakAlert = true;
- },
- // 断开连接
- closeBLEConnection() {
- let that = this;
- if (!that.deviceId) {
- that.Toast('当前没有已建立的连接',);
- return false
- }
- plus.bluetooth.closeBLEConnection({
- deviceId: that.deviceId,
- success: function(e) {
- that.Toast('断开操作成功', 'success');
- that.openBreakAlert = false;
- console.log('close success: ' + JSON.stringify(e));
- },
- fail: function(e) {
- that.Toast('断开操作失败,请重试 [res]:' + JSON.stringify(e), 'error');
- console.log('close failed: ' + JSON.stringify(e));
- }
- });
- },
- // 自动重连上次心率带
- AutoContectLast() {
- let that = this;
- if (localStorage.sn) {
- plus.bluetooth.openBluetoothAdapter({
- success: function(e) {
- clearTimeout(that.autoConectTimer); //清除延迟执行
- that.autoConectTimer = setTimeout(() => { //设置延迟执行
- let w = JSON.parse(localStorage.w)
- that.choiceWatch(w);
- that.Toast('即将连接上次心率带', 'success');
- }, 5000);
- },
- fail: function(e) {
- that.Toast('打开失败! 请确认蓝牙开关已开启', 'error');
- }
- });
- } else {
- return false
- }
- },
- // 显示版本号
- showVersion() {
- this.Toast('当前版本号' + localStorage.version, 'success');
- },
- logoutBtn() {
- this.Toast('退出当前账户', 'success');
- localStorage.token = '';
- this.$router.push({ path: '/login' });
- },
- // 删除默认心率带
- delDefault() {
- localStorage.sn = '';
- }
- },
- filters: {
- parseLevel: function(value) {
- if (!value) {
- return '无'
- } else {
- if (parseInt(value) > -60) {
- return '强';
- } else {
- return '弱';
- }
- }
- }
- ,
- parseToInt: function(val) {
- return parseInt(val)
- }
- ,
- parseToFix1: function(val) {
- return parseFloat(val).toFixed(1)
- }
- }
- ,
- components: {
- LineExample
- }
- }
- </script>
- <style scoped>
- .top {
- width: 100%;
- overflow: hidden;
- display: block;
- margin: 0 auto;
- padding-top: 10px;
- padding-bottom: 10px;
- }
- .top .watchState {
- width: 100%;
- overflow: hidden;
- display: block;
- margin: 0 auto;
- height: 20px;
- line-height: 20px;
- color: #fff;
- text-align: center;
- margin-top: 20px;
- margin-bottom: 10px;
- }
- .toprow {
- width: 100%;
- overflow: hidden;
- display: block;
- margin: 0 auto;
- }
- .toprow .lt {
- width: 30%;
- float: left;
- overflow: hidden;
- }
- .toprow .md {
- width: 40%;
- float: left;
- overflow: hidden;
- }
- .toprow .rt {
- width: 30%;
- float: right;
- overflow: hidden;
- }
- .toprow .lt .activeLevel {
- width: 100%;
- overflow: hidden;
- display: block;
- margin: 0 auto;
- margin-top: 10px;
- color: #fff;
- }
- .activeLevel div {
- width: 86px;
- overflow: hidden;
- display: block;
- margin: 0 auto;
- }
- .activeLevel s {
- float: right;
- font-size: 20px;
- }
- .activeLevel em {
- font-size: 40px;
- text-align: right;
- font-weight: bold;
- float: right;
- }
- .toprow .lt span {
- width: 80px;
- height: 20px;
- overflow: hidden;
- display: block;
- margin: 0 auto;
- color: #fff;
- border: 1px solid #fff;
- border-radius: 250px;
- text-align: center;
- line-height: 20px;
- font-size: 12px;
- }
- .toprow .md .headContainer {
- width: 70%;
- height: 70%;
- border: 3px solid rgba(255, 255, 255, 0.71);
- border-radius: 250px;
- overflow: hidden;
- display: block;
- margin: 0 auto;
- }
- .headContainer img {
- width: 100%;
- height: 100%;
- overflow: hidden;
- display: block;
- margin: 0 auto;
- }
- .activeLevel .noValue {
- width: 100%;
- overflow: hidden;
- display: block;
- margin: 0 auto;
- font-weight: bold;
- font-size: 40px;
- text-align: center;
- float: none;
- }
- .username {
- width: 100%;
- height: 30px;
- overflow: hidden;
- display: block;
- margin: 0 auto;
- font-size: 14px;
- color: #fff;
- margin-top: 10px;
- }
- .username em {
- width: 100%;
- overflow: hidden;
- display: block;
- margin: 0 auto;
- text-align: center;
- }
- .username img {
- position: relative;
- bottom: 20px;
- float: right;
- width: 15px;
- height: 15px;
- right: 15%;
- }
- .heartJump {
- width: 90%;
- overflow: hidden;
- float: left;
- margin: 0 auto;
- margin-top: 10px;
- color: #fff;
- }
- .heartJump div {
- width: 86px;
- overflow: hidden;
- display: block;
- margin: 0 auto;
- }
- .heartJump img {
- width: 16px;
- height: 14px;
- float: right;
- }
- .heartJump em {
- font-size: 40px;
- text-align: right;
- font-weight: bold;
- float: right;
- }
- .heartJump .noValue {
- width: 100%;
- overflow: hidden;
- display: block;
- margin: 0 auto;
- font-weight: bold;
- font-size: 40px;
- text-align: center;
- float: none;
- }
- .toprow .rt span {
- width: 80px;
- height: 20px;
- overflow: hidden;
- display: block;
- margin: 0 auto;
- /*float: left;*/
- color: #fff;
- border: 1px solid #fff;
- border-radius: 250px;
- text-align: center;
- line-height: 20px;
- font-size: 12px;
- }
- .info {
- width: 100%;
- overflow: hidden;
- display: block;
- margin: 0 auto;
- }
- .info ul {
- width: 100%;
- overflow: hidden;
- display: block;
- margin: 0 auto;
- margin-top: 10px;
- margin-bottom: 10px;
- }
- .info li {
- width: 25%;
- border-left: 1px solid #fff;
- border-right: 1px solid #fff;
- float: left;
- text-align: center;
- }
- .info li:nth-child(2) {
- border-color: #e2e2e2;
- }
- .info li:nth-child(3) {
- border-color: #e2e2e2;
- border-left: 0;
- }
- .info li em {
- width: 100%;
- overflow: hidden;
- display: block;
- margin: 0 auto;
- color: #363636;
- font-size: 20px;
- text-align: center;
- }
- .info li span {
- width: 100%;
- overflow: hidden;
- display: block;
- margin: 0 auto;
- color: #c4c4c4;
- font-size: 12px;
- text-align: center;
- }
- .row {
- width: 100%;
- overflow: hidden;
- display: block;
- margin: 0 auto;
- background: #efefef;
- padding-top: 5px;
- padding-bottom: 5px;
- }
- .row .rowCenter {
- width: 208px;
- overflow: hidden;
- display: block;
- margin: 0 auto;
- line-height: 30px;
- }
- .rowCenter img {
- width: 11px;
- height: 11px;
- float: left;
- margin-top: 10px;
- margin-right: 5px;
- }
- .rowCenter em {
- font-size: 14px;
- color: #ff4040;
- margin-right: 15px;
- }
- .rowCenter button {
- width: 92px;
- height: 27px;
- text-align: center;
- line-height: 27px;
- color: black;
- background: #ffde93;
- border-radius: 6px;
- border: none;
- outline: none;
- }
- .middle {
- width: 100%;
- overflow: hidden;
- display: block;
- margin: 0 auto;
- border-bottom: 10px solid #efefef;
- }
- .middle ul {
- width: 100%;
- overflow: hidden;
- display: block;
- margin: 0 auto;
- padding-top: 10px;
- padding-bottom: 10px;
- }
- .middle li {
- width: 33%;
- float: left;
- border-left: 1px solid #fff;
- border-right: 1px solid #fff;
- }
- .middle li .center {
- width: 72px;
- overflow: hidden;
- display: block;
- margin: 0 auto;
- }
- .middle li:nth-child(2) {
- border-color: #e2e2e2;
- }
- .middle li img {
- width: 15px;
- float: right;
- margin-top: 4px;
- margin-right: 5px;
- }
- .middle li em {
- float: right;
- text-align: right;
- color: #000;
- font-weight: bold;
- font-size: 22px;
- }
- .middle li span {
- width: 100%;
- overflow: hidden;
- display: block;
- margin: 0 auto;
- text-align: right;
- color: #9a9a9a;
- font-size: 12px;
- }
- .middle .ck {
- width: 19px;
- height: 19px;
- margin-top: 6px;
- }
- .bottom {
- width: 100%;
- overflow: hidden;
- display: block;
- margin: 0 auto;
- }
- .bottom h5 {
- width: 100%;
- overflow: hidden;
- display: block;
- margin: 0 auto;
- color: #363636;
- font-size: 16px;
- text-align: center;
- font-weight: normal;
- margin-top: 14px;
- }
- .bottom span {
- width: 100%;
- overflow: hidden;
- display: block;
- margin: 0 auto;
- text-align: center;
- font-size: 12px;
- color: #9a9a9a;
- }
- .bottom em {
- position: relative;
- bottom: 160px;
- right: 20px;
- float: right;
- color: #ff4040;
- background: #fff;
- }
- .slowJump {
- animation: mymove 3s infinite;
- -webkit-animation: mymove 3s infinite; /*Safari and Chrome*/
- animation-direction: alternate; /*轮流反向播放动画。*/
- animation-timing-function: ease-in-out; /*动画的速度曲线*/
- /* Safari 和 Chrome */
- -webkit-animation-direction: alternate; /*轮流反向播放动画。*/
- -webkit-animation-timing-function: ease-in-out; /*动画的速度曲线*/
- }
- .normalJump {
- animation: mymove 2s infinite;
- -webkit-animation: mymove 2s infinite; /*Safari and Chrome*/
- animation-direction: alternate; /*轮流反向播放动画。*/
- animation-timing-function: ease-in-out; /*动画的速度曲线*/
- /* Safari 和 Chrome */
- -webkit-animation-direction: alternate; /*轮流反向播放动画。*/
- -webkit-animation-timing-function: ease-in-out; /*动画的速度曲线*/
- }
- .fastJump {
- animation: mymove 1s infinite;
- -webkit-animation: mymove 1s infinite; /*Safari and Chrome*/
- animation-direction: alternate; /*轮流反向播放动画。*/
- animation-timing-function: ease-in-out; /*动画的速度曲线*/
- /* Safari 和 Chrome */
- -webkit-animation-direction: alternate; /*轮流反向播放动画。*/
- -webkit-animation-timing-function: ease-in-out; /*动画的速度曲线*/
- }
- @keyframes mymove {
- 0% {
- transform: scale(1); /*开始为原始大小*/
- }
- 25% {
- transform: scale(1.1); /*放大1.1倍*/
- }
- 50% {
- transform: scale(1);
- }
- 75% {
- transform: scale(1.1);
- }
- }
- @-webkit-keyframes mymove /*Safari and Chrome*/ {
- 0% {
- transform: scale(1); /*开始为原始大小*/
- }
- 25% {
- transform: scale(1.1); /*放大1.1倍*/
- }
- 50% {
- transform: scale(1);
- }
- 75% {
- transform: scale(1.1);
- }
- }
- /deep/ .mu-dialog {
- background-color: rgba(0, 0, 0, 0.85);
- color: #fff;
- border-radius: 20px;
- background-size: 100%;
- background-origin: content-box;
- }
- /deep/ .mu-dialog h5 {
- color: #fff;
- text-align: center;
- font-size: 16px;
- }
- /deep/ .mu-dialog p {
- color: #fff;
- text-align: center;
- font-size: 14px;
- }
- /deep/ .mu-dialog .mu-primary-text-color {
- margin: 0 auto;
- border-radius: 9px;
- background-color: rgba(255, 255, 255, 0.1);
- color: #fff;
- }
- .watchList {
- width: 100%;
- overflow: hidden;
- display: block;
- margin: 0 auto;
- min-height: 100px;
- overflow-y: scroll;
- }
- .watchList li {
- width: 100%;
- padding-left: 5%;
- padding-right: 5%;
- padding-top: 5px;
- padding-bottom: 5px;
- overflow: hidden;
- display: block;
- margin: 0 auto;
- background-color: rgba(255, 255, 255, 0.29);
- color: #fff;
- border-radius: 9px;
- font-size: 12px;
- margin-bottom: 5px;
- }
- .watchList li em {
- float: right;
- text-align: right;
- }
- .classInfo {
- width: 100%;
- overflow: hidden;
- display: block;
- margin: 0 auto;
- font-size: 16px;
- text-align: center;
- }
- .classInfo span {
- font-size: 12px;
- }
- .breakConect {
- font-size: 12px;
- text-align: center;
- color: green;
- }
- .breakConect button {
- width: 92px;
- height: 27px;
- text-align: center;
- line-height: 27px;
- color: black;
- background: rgb(255, 123, 0);
- border-radius: 6px;
- border: none;
- outline: none;
- margin-left: 15px;
- font-size: 14px;
- }
- .logoutBtn {
- width: 100px;
- margin: 0 auto;
- }
- /deep/ .mu-loading-wrap {
- position: relative;
- bottom: 30px;
- width: 200px;
- margin: 0 auto;
- }
- </style>
|