mainpage.vue 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551
  1. <template>
  2. <div class="content">
  3. <div class="top" :style="{ backgroundColor: bgColor }">
  4. <span class="watchState">{{ watchText }} {{ battery }}</span>
  5. <div class="toprow">
  6. <div class="lt">
  7. <div class="activeLevel">
  8. <div v-if="activeState">
  9. <s>%</s>
  10. <em>{{ activeLevel }}</em>
  11. </div>
  12. <div v-else>
  13. <s class="noValue">--</s>
  14. </div>
  15. </div>
  16. <span @click="showVersion">{{ activeLevelText }}</span>
  17. </div>
  18. <div class="md">
  19. <div class="headContainer">
  20. <img :src="userHead" />
  21. </div>
  22. <span class="username">
  23. <em>{{ username }}</em>
  24. <img
  25. src="../static/images/main/male.png"
  26. height="60"
  27. width="60"
  28. v-if="sex == 1"
  29. />
  30. <img
  31. src="../static/images/main/female.png"
  32. height="60"
  33. width="60"
  34. v-if="sex == 2"
  35. />
  36. </span>
  37. </div>
  38. <div class="rt">
  39. <div class="heartJump">
  40. <div v-if="activeState">
  41. <img src="../static/images/main/heart.png" height="74" width="86" />
  42. <em
  43. :class="[
  44. { 'normalJump': activeLevel > 30 && activeLevel <= 90 },
  45. { 'fastJump': activeLevel > 90 },
  46. { 'slowJump': activeLevel < 30 },
  47. ]"
  48. >{{ heartRate }}</em>
  49. </div>
  50. <div v-else>
  51. <s class="noValue">--</s>
  52. </div>
  53. </div>
  54. <span @click="showConsole()">瞬时心率</span>
  55. </div>
  56. </div>
  57. </div>
  58. <div class="info">
  59. <ul>
  60. <li>
  61. <em>{{ height }}</em>
  62. <span>身高cm</span>
  63. </li>
  64. <li>
  65. <em>{{ age }}</em>
  66. <span>年龄</span>
  67. </li>
  68. <li>
  69. <em>{{ weight }}</em>
  70. <span>体重kg</span>
  71. </li>
  72. <li>
  73. <em>{{ peaceHeart }}</em>
  74. <span>静息心率</span>
  75. </li>
  76. </ul>
  77. </div>
  78. <div class="row">
  79. <div class="rowCenter" v-if="!watchState" @click="connectWatch">
  80. <img src="../static/images/main/chain.png" />
  81. <em>心率带未连接</em>
  82. <button>点击连接</button>
  83. </div>
  84. <div class="classInfo" v-if="InClass == 1 && watchState">
  85. <em>
  86. <span>课程名称:</span>
  87. {{ DpName }}
  88. </em>
  89. </div>
  90. <div class="breakConect" v-if="watchState">
  91. <em>心率带{{ NorMalSn }}已连接</em>
  92. <button @click="closeBLEConnectionAlert">断开连接</button>
  93. </div>
  94. </div>
  95. <div class="middle">
  96. <ul>
  97. <li>
  98. <div class="center">
  99. <em>{{ cal | parseToInt }}</em>
  100. <img src="../static/images/main/normal.png" />
  101. <span>卡路里</span>
  102. </div>
  103. </li>
  104. <li>
  105. <div class="center">
  106. <em>{{ sportCal | parseToInt }}</em>
  107. <img src="../static/images/main/redfire.png" />
  108. <span>运动卡路里</span>
  109. </div>
  110. </li>
  111. <li>
  112. <div class="center">
  113. <em>{{ ck | parseToFix1 }}</em>
  114. <img src="../static/images/main/ck.png" class="ck" />
  115. <span>CK</span>
  116. </div>
  117. </li>
  118. </ul>
  119. </div>
  120. <div class="bottom">
  121. <h5>心率趋势图</h5>
  122. <span>最大心率 : {{ heartMax }} 平均心率 : {{ heartAverage }}</span>
  123. <Line-example
  124. :width="screenWidth"
  125. :height="screenHeight"
  126. :dataLabels="dataLabels"
  127. :datadatasets="dataDatasets"
  128. />
  129. <em
  130. v-if="activeState"
  131. :class="[
  132. { 'normalJump': activeLevel > 30 && activeLevel <= 90 },
  133. { 'fastJump': activeLevel > 90 },
  134. { 'slowJump': activeLevel < 30 },
  135. ]"
  136. :style="{ bottom: parseInt(screenHeight - 30) + 'px' }"
  137. >{{ heartRate }}</em>
  138. <div class="logoutBtn">
  139. <mu-button color="info" @click.native="logoutBtn">退出登陆</mu-button>
  140. <br />
  141. <!-- <mu-button color="error" @click.native="delDefault">删除默认</mu-button> -->
  142. </div>
  143. </div>
  144. <mu-dialog
  145. title
  146. width="600"
  147. max-width="80%"
  148. :esc-press-close="true"
  149. :overlay-close="true"
  150. :open.sync="openAlert"
  151. >
  152. <p v-if="!watchListState">没有任何设备</p>
  153. <div class="watchList" v-else>
  154. <p>请选择设备</p>
  155. <ul>
  156. <li v-for="w in watchs" @click="choiceWatch(w)">
  157. {{ w.localName.substr(6, 13) }}
  158. <em>信号:{{ w.RSSI | parseLevel }}</em>
  159. </li>
  160. </ul>
  161. </div>
  162. <br />
  163. <mu-button
  164. slot="actions"
  165. flat
  166. color="primary"
  167. @click="closeAlertDialog"
  168. v-if="watchListState"
  169. >取消</mu-button>
  170. <mu-button slot="actions" flat color="primary" @click="searchWatch" v-else>搜索</mu-button>
  171. </mu-dialog>
  172. <mu-dialog
  173. width="600"
  174. max-width="80%"
  175. :esc-press-close="false"
  176. :overlay-close="false"
  177. :open.sync="openBreakAlert"
  178. >
  179. <h5>是否断开心率带蓝牙连接?</h5>
  180. <p>(断开后将不再上传心率信息)</p>
  181. <mu-button slot="actions" flat color="primary" @click="openBreakAlert = false">取消</mu-button>
  182. <mu-button slot="actions" flat color="primary" @click="closeBLEConnection">断开</mu-button>
  183. </mu-dialog>
  184. <mu-dialog title="Dialog" width="360" :open.sync="openSimple">
  185. <p>请求心率带蓝牙失败,请退出APP,重启蓝牙开关</p>
  186. <mu-button slot="actions" flat color="primary" @click="openSimple = false">知道了</mu-button>
  187. </mu-dialog>
  188. </div>
  189. </template>
  190. <script>
  191. import LineExample from '../components/LineExample'
  192. import {
  193. UserSelfQuery,
  194. GetDuInfoAndUserInfoByUserMd5,
  195. HrSensorsUpdate,
  196. AddAppHeartRate,
  197. } from '../api/getApiRes.js'
  198. let qs = require('qs');
  199. export default {
  200. data() {
  201. return {
  202. runMode: '',//'' 为正常模式 mock 为模拟操作模式
  203. isClassTime: 5000,//上课状态检测频率
  204. isAddHeartTime: 1000,//心率上报检测频率
  205. dataLabels: [],
  206. dataDatasets: [],
  207. watchText: '',
  208. battery: '',
  209. userHead: 'http://xhead.beswell.com/flyhead.png',
  210. watchState: false,//false
  211. bgColor: '#028FE1',
  212. activeLevel: 0,
  213. activeLevelText: '激活放松',
  214. heartRate: 0,
  215. activeState: false,//false
  216. openAlert: false,//false
  217. openBreakAlert: false,//false
  218. alertState: false,//false
  219. watchListState: false,//false
  220. username: 'XXX',
  221. sex: 1,
  222. height: 148,
  223. age: 8,
  224. weight: 38,
  225. peaceHeart: 70,
  226. heartMax: 0,
  227. heartAverage: 0,
  228. cal: 0,
  229. sportCal: 0,
  230. ck: 0,
  231. addCalories: 0,//增量卡路里
  232. addPureCalories: 0,//增量运动卡路里
  233. screenWidth: parseInt(document.body.clientWidth - 10),
  234. screenHeight: parseInt(document.documentElement.clientHeight / 3),
  235. watchs: [],
  236. begin: null,
  237. heartLine: [],
  238. InClass: 0,//是否上课
  239. DpName: 'XXXX',//课程名称
  240. HrId: '',//心率带
  241. duId: 0,
  242. sn: '',
  243. NorMalSn: '',
  244. deviceId: '',
  245. sumError: 0,
  246. openSimple: false,
  247. breakStateTimer: null,
  248. }
  249. },
  250. mounted() {
  251. this.init();
  252. this.getBodyInfo();
  253. // 获取上课状态
  254. clearInterval(this.timerisClass);
  255. this.timerisClass = setInterval(() => {
  256. this.isClass();
  257. }, this.isClassTime);
  258. // 上报心率信息
  259. clearInterval(this.timerAutoAddAppHeartRate);
  260. this.timerAutoAddAppHeartRate = setInterval(() => {
  261. // 已连接时轮询连接状态
  262. if (this.watchState) {
  263. // 自动获取心率带蓝牙连接状态
  264. this.listenerConnection();
  265. }
  266. // 上课中,且已连接心率带
  267. if (this.InClass == 1 && this.watchState && this.runMode != 'mock') {
  268. // 上课就自动上报
  269. this.AutoAddAppHeartRate();
  270. } else {
  271. // console.log('下课中,不汇报1');
  272. }
  273. }, this.isAddHeartTime);
  274. },
  275. beforeDestroy() {
  276. clearInterval(this.timerisClass);
  277. clearInterval(this.timerAutoAddAppHeartRate);
  278. },
  279. watch: {
  280. activeLevel(val) {
  281. let that = this;
  282. switch (true) {
  283. case parseInt(val) < 39:
  284. that.bgColor = '#028FE1';
  285. that.activeLevelText = '激活放松';
  286. break;
  287. case parseInt(val) < 54 && parseInt(val) >= 39:
  288. that.bgColor = '#6D29FA';
  289. that.activeLevelText = '动态热身';
  290. break;
  291. case parseInt(val) < 69 && parseInt(val) >= 54:
  292. that.bgColor = '#0AB105';
  293. that.activeLevelText = '脂肪燃烧';
  294. break;
  295. case parseInt(val) < 79 && parseInt(val) >= 69:
  296. that.bgColor = '#B9CB01';
  297. that.activeLevelText = '糖分消耗';
  298. break;
  299. case parseInt(val) < 89 && parseInt(val) >= 79:
  300. that.bgColor = '#EA8813';
  301. that.activeLevelText = '心肺训练';
  302. break;
  303. case parseInt(val) >= 90:
  304. that.bgColor = '#D11122';
  305. that.activeLevelText = '峰值锻炼';
  306. break;
  307. }
  308. // 动态显示背景色
  309. plus.navigator.setStatusBarBackground(that.bgColor);
  310. },
  311. },
  312. methods: {
  313. init() {
  314. let that = this;
  315. if (this.runMode == 'mock') {
  316. this.mockCreateDate();
  317. } else {
  318. if (window.plus) {
  319. console.log('mui is plusReady');
  320. that.allPlusReady();
  321. } else {
  322. console.log('mui is not ready');
  323. document.addEventListener('plusready', function(e) {
  324. that.allPlusReady();
  325. });
  326. }
  327. }
  328. },
  329. allPlusReady() {
  330. let that = this;
  331. // that.setWakelock();
  332. plus.bluetooth.onBLECharacteristicValueChange(function(e) {
  333. if (e.characteristicId == '00002A19-0000-1000-8000-00805F9B34FB') {
  334. // 获取电量
  335. var value = that.buffer2hexPower(e.value);
  336. that.watchText = '心率带已连接,电量:';
  337. that.battery = value + '%';
  338. } else {
  339. // 成功获取心跳
  340. that.heartRate = parseInt(that.parseHeartRate(e.value).heartRate);
  341. that.watchText = '心率带已连接,电量:';
  342. that.activeState = true;
  343. // 运动强度计算
  344. that.calcActLevel(that.heartRate);
  345. that.openAlert = false;//关闭弹窗
  346. that.watchState = true;//关闭连接按钮并显示当前课程名
  347. // 卡路里计算
  348. that.calcCalorie(that.heartRate);
  349. that.heartLine.push(that.heartRate);
  350. that.dataLabels.push('');
  351. if (that.heartLine.length > 30) {
  352. that.heartLine.shift();
  353. that.dataLabels.shift();
  354. }
  355. that.DrawHeartLine(that.heartLine, that.dataLabels);
  356. }
  357. });
  358. // 自动重连上次心率带
  359. that.AutoContectLast();
  360. },
  361. // 屏幕常亮
  362. setWakelock() {
  363. plus.device.setWakelock(true);
  364. console.log('屏幕常量已开启');
  365. },
  366. // 震动
  367. vibrate() {
  368. let milliseconds = 500;
  369. plus.device.vibrate(milliseconds)
  370. },
  371. showConsole() {
  372. let vconDom = document.getElementById('__vconsole');
  373. this.toggleClass(vconDom, 'show')
  374. },
  375. toggleClass(obj, cls) {
  376. if (this.hasClass(obj, cls)) {
  377. this.removeClass(obj, cls);
  378. } else {
  379. this.addClass(obj, cls);
  380. }
  381. },
  382. hasClass(obj, cls) {
  383. return obj.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'));
  384. },
  385. addClass(obj, cls) {
  386. if (!this.hasClass(obj, cls)) obj.className += " " + cls;
  387. },
  388. removeClass(obj, cls) {
  389. if (this.hasClass(obj, cls)) {
  390. var reg = new RegExp('(\\s|^)' + cls + '(\\s|$)');
  391. obj.className = obj.className.replace(reg, ' ');
  392. }
  393. },
  394. // 测试 生成心率数据
  395. mockCreateDate() {
  396. let that = this;
  397. clearInterval(this.timermockCreateDate);
  398. this.timermockCreateDate = setInterval(() => {
  399. that.battery = '999%';
  400. // 成功获取心跳
  401. that.heartRate = parseInt(Math.random() * 100 + 90);
  402. that.watchText = '心率带已连接';
  403. that.activeState = true;
  404. // 运动强度计算
  405. that.calcActLevel(that.heartRate);
  406. that.openAlert = false;//关闭弹窗
  407. that.watchState = true;//关闭连接按钮
  408. // 卡路里计算
  409. that.calcCalorie(that.heartRate);
  410. that.heartLine.push(that.heartRate);
  411. that.dataLabels.push('');
  412. if (that.heartLine.length > 3) {
  413. that.heartLine.shift();
  414. that.dataLabels.shift();
  415. }
  416. that.DrawHeartLine(that.heartLine, that.dataLabels);
  417. }, 1000);
  418. },
  419. // 是否正在上课
  420. isClass() {
  421. let that = this;
  422. let param = {
  423. token: localStorage.token,
  424. };
  425. let postdata = qs.stringify(param);
  426. GetDuInfoAndUserInfoByUserMd5(postdata).then(res => {
  427. let json = res;
  428. if (json.Code == 0) {
  429. that.InClass = json.InClass;//0下课,1上课
  430. // 记录duid
  431. that.duId = parseInt(json.DuInfo.DuId);
  432. that.DpName = json.DuInfo.DpName;
  433. // 正在上课且已连心率带
  434. if (that.InClass == 1 && that.watchState) {
  435. console.log('InClass' + that.InClass);
  436. // 上课状态拿一次心率带信息
  437. that.AddHrSensorsUpdate();
  438. }
  439. } else {
  440. that.Toast(json.Memo);
  441. }
  442. })
  443. },
  444. buffer2hexPower(value) {
  445. var t = '';
  446. if (value) {
  447. var v = new Uint8Array(value);
  448. for (var i in v) {
  449. // t += '0x' + v[i].toString(16) + ' ';
  450. t += v[i].toString(10) + ' ';
  451. }
  452. } else {
  453. t = '无效值';
  454. }
  455. return t;
  456. },
  457. connectWatch() {
  458. // 打开蓝牙适配器
  459. let that = this;
  460. if (typeof plus == 'undefined') {
  461. that.Toast('当前设备不支持蓝牙心率带', 'error');
  462. return false
  463. }
  464. plus.bluetooth.openBluetoothAdapter({
  465. success: function(e) {
  466. that.Toast('蓝牙适配器打开成功!', 'success');
  467. that.openAlert = true;
  468. that.searchWatch();
  469. return e
  470. },
  471. fail: function(e) {
  472. that.Toast('打开失败! 请确认蓝牙开关已开启', 'error');
  473. }
  474. });
  475. },
  476. closeAlertDialog() {
  477. this.openAlert = false;
  478. },
  479. // 监听搜索到新设备
  480. searchWatch() {
  481. let that = this;
  482. that.watchs = [];
  483. plus.bluetooth.startBluetoothDevicesDiscovery({
  484. // services: ['heart_rate'],//ios不支持
  485. success: function(e) {
  486. that.Toast('开始搜索成功!', 'success');
  487. plus.bluetooth.onBluetoothDeviceFound(function(e) {
  488. let devices = e.devices;
  489. let row = [];
  490. for (let i in devices) {
  491. let device = devices[i];
  492. // localName CL831
  493. if (device.localName.indexOf('CL831') != -1) {
  494. console.log(JSON.stringify(device));
  495. that.watchs.push(device);
  496. }
  497. }
  498. that.watchListState = true;
  499. });
  500. },
  501. fail: function(e) {
  502. that.Toast('开始搜索失败! ' + JSON.stringify(e));
  503. }
  504. });
  505. },
  506. choiceWatch(w) {
  507. let that = this;
  508. that.Toast('连接心率带' + w.localName.substring(6, 13) + '中...', 'success');
  509. console.log('连接心率带' + w.deviceId);
  510. that.deviceId = w.deviceId
  511. // 建立连接
  512. plus.bluetooth.createBLEConnection({
  513. deviceId: w.deviceId,
  514. success: function(e) {
  515. // 记录心率带sn
  516. that.sn = w.localName;
  517. localStorage.sn = that.sn;
  518. localStorage.w = JSON.stringify(w);
  519. that.AddHrSensorsUpdate();
  520. that.Toast('连接成功!', 'success');
  521. // 渲染完毕再执行这个,所以才能没有延时的更改
  522. // 需要一个回调等待5S
  523. clearTimeout(that.timer); //清除延迟执行
  524. that.timer = setTimeout(() => { //设置延迟执行
  525. // 获取服务
  526. that.getServices(w);
  527. }, 2000);
  528. },
  529. fail: function(e) {
  530. console.log('连接失败! 请重新连接' + JSON.stringify(e));
  531. if (e.code == 10000) {
  532. console.log(123);
  533. }
  534. that.Toast('连接失败! 请重新连接' + JSON.stringify(e));
  535. },
  536. })
  537. },
  538. getServices(w) {
  539. let that = this;
  540. that.Toast('获取蓝牙设备服务:', 'success');
  541. plus.bluetooth.getBLEDeviceServices({
  542. deviceId: w.deviceId,
  543. success: function(e) {
  544. that.Toast('获取蓝牙服务成功!', 'success');
  545. // 获取服务的特征值
  546. var HEARTuuid = "0000180D-0000-1000-8000-00805F9B34FB";//HEART RATE
  547. var Batteryuuid = "0000180F-0000-1000-8000-00805F9B34FB";//Battery
  548. that.getBatteryCharacteristics(w.deviceId, Batteryuuid);
  549. clearTimeout(that.timer); //清除延迟执行
  550. that.timer = setTimeout(() => { //设置延迟执行
  551. // 获取心跳服务
  552. that.getCharacteristics(w.deviceId, HEARTuuid);
  553. }, 3000);
  554. },
  555. fail: function(e) {
  556. console.log('获取服务失败,devicedId:' + w.deviceId);
  557. console.log('获取服务失败! ' + JSON.stringify(e));
  558. that.Toast('获取服务失败!请重试 ' + JSON.stringify(e), 'error');
  559. // 10004无连接, 重启一次蓝牙Adapter
  560. if (e.code == 10004) {
  561. that.sumError += 1;
  562. if (that.sumError > 3) {
  563. }
  564. }
  565. }
  566. });
  567. },
  568. // 获取服务的特征值
  569. getCharacteristics(deviceId, serviceId) {
  570. let that = this;
  571. let chaaracterUuid = '00002A37-0000-1000-8000-00805F9B34FB';
  572. let characteristicId = null;
  573. plus.bluetooth.getBLEDeviceCharacteristics({
  574. deviceId: deviceId,
  575. serviceId: serviceId,
  576. success: function(e) {
  577. let characteristics = e.characteristics;
  578. that.Toast('获取心率带蓝牙服务成功! ', 'success');
  579. console.log('特征值列表: ' + JSON.stringify(characteristics));
  580. plus.bluetooth.notifyBLECharacteristicValueChange({ //监听数据变化
  581. deviceId: deviceId,
  582. serviceId: serviceId,
  583. characteristicId: chaaracterUuid,
  584. success: function(e) {
  585. console.log('---> 获取心跳服务' + JSON.stringify(e));
  586. console.log('---> notifyBLECharacteristicValueChange ' + chaaracterUuid + ' success.');
  587. // 服务获取成功,震动提示
  588. // that.vibrate();
  589. //that.onValuesChange();
  590. },
  591. fail: function(e) {
  592. that.Toast('获取特征值失败!重启APP后再次尝试 ' + JSON.stringify(e));
  593. }
  594. });
  595. },
  596. fail: function(e) {
  597. console.log('获取特征值失败! ' + JSON.stringify(e));
  598. that.Toast('获取特征值失败!重启APP后再次尝试 ' + JSON.stringify(e));
  599. }
  600. })
  601. },
  602. // 获取服务的特征值
  603. getBatteryCharacteristics(deviceId, serviceId) {
  604. let that = this;
  605. let chaaracterUuid = '00002A19-0000-1000-8000-00805F9B34FB';
  606. let characteristicId = null;
  607. that.readValue(deviceId, serviceId, chaaracterUuid);
  608. plus.bluetooth.getBLEDeviceCharacteristics({
  609. deviceId: deviceId,
  610. serviceId: serviceId,
  611. success: function(e) {
  612. var characteristics = e.characteristics;
  613. that.Toast('获取心率带服务成功! ' + characteristics.length, 'success');
  614. plus.bluetooth.notifyBLECharacteristicValueChange({ //监听数据变化
  615. deviceId: deviceId,
  616. serviceId: serviceId,
  617. characteristicId: chaaracterUuid,
  618. success: function(e) {
  619. console.log('notifyBLECharacteristicValueChange' + JSON.stringify(e));
  620. },
  621. fail: function(e) {
  622. that.Toast('notifyBLECharacteristicValueChange失败! ' + JSON.stringify(e));
  623. }
  624. });
  625. },
  626. fail: function(e) {
  627. console.log('获取特征值失败! ' + JSON.stringify(e));
  628. that.Toast('获取特征值失败!重启APP后再次尝试 ' + JSON.stringify(e));
  629. }
  630. })
  631. },
  632. readValue(deviceId, serviceId, characteristicId) {
  633. let that = this;
  634. plus.bluetooth.readBLECharacteristicValue({
  635. deviceId: deviceId,
  636. serviceId: serviceId,
  637. characteristicId: characteristicId,
  638. success: function(e) {
  639. console.log("读取电量数据成功" + JSON.stringify(e));
  640. },
  641. fail: function(e) {
  642. that.Toast('读取电量数据失败!重启APP后再次尝试 ' + JSON.stringify(e));
  643. }
  644. });
  645. },
  646. // 获取基础身体数据
  647. getBodyInfo() {
  648. let that = this;
  649. let param = {
  650. token: localStorage.token,
  651. };
  652. let postdata = qs.stringify(param);
  653. UserSelfQuery(postdata).then(res => {
  654. let json = res;
  655. if (json.Code == 0) {
  656. that.username = json.Rs.UserName;
  657. that.sex = json.Rs.Sex;
  658. that.height = json.Rs.Height;
  659. // Birthday
  660. let age = parseInt((new Date().getTime() - new Date(json.Rs.Birthday).getTime()) / (365 * 24 * 60 * 60 * 1000));
  661. that.age = age;
  662. that.weight = parseInt(json.Rs.Weight) / 10;
  663. that.peaceHeart = json.Rs.StaticHr;
  664. // 有无默认头像
  665. if (json.Rs.Head) {
  666. that.userHead = json.Rs.Head;
  667. } else {
  668. that.userHead = 'http://xhead.beswell.com/flyhead.png';//默认头像
  669. }
  670. } else {
  671. if (json.Code == 9999999999) {
  672. that.Toast('登陆已失效,请重新登陆');
  673. localStorage.token = '';
  674. this.$router.push({ path: '/login' });
  675. } else {
  676. that.Toast(json.Memo, 'error');
  677. }
  678. }
  679. })
  680. },
  681. parseHeartRate(data) {
  682. var data = new DataView(data);
  683. const flags = data.getUint8(0);
  684. const rate16Bits = flags & 0x1;
  685. const result = {};
  686. let index = 1;
  687. if (rate16Bits) {
  688. result.heartRate = data.getUint16(index, /*littleEndian=*/ true);
  689. index += 2;
  690. } else {
  691. result.heartRate = data.getUint8(index);
  692. index += 1;
  693. }
  694. const contactDetected = flags & 0x2;
  695. const contactSensorPresent = flags & 0x4;
  696. if (contactSensorPresent) {
  697. result.contactDetected = !!contactDetected;
  698. }
  699. const energyPresent = flags & 0x8;
  700. if (energyPresent) {
  701. result.energyExpended = data.getUint16(index, /*littleEndian=*/ true);
  702. index += 2;
  703. }
  704. const rrIntervalPresent = flags & 0x10;
  705. if (rrIntervalPresent) {
  706. const rrIntervals = [];
  707. for (; index + 1 < data.byteLength; index += 2) {
  708. rrIntervals.push(data.getUint16(index, /*littleEndian=*/ true));
  709. }
  710. result.rrIntervals = rrIntervals;
  711. }
  712. return result;
  713. }
  714. ,
  715. // 活动强度计算公式
  716. calcActLevel(heartRate) {
  717. let actLevel = (heartRate - this.peaceHeart) / (208 - 0.7 * this.age - this.peaceHeart) * 100;
  718. actLevel = actLevel > 100 ? 100 : actLevel < 0 ? 0 : actLevel;
  719. this.activeLevel = parseInt(actLevel);
  720. },
  721. // 持续时间
  722. calcHoldTime(curTime) {
  723. let that = this;
  724. let res = 0;
  725. if (this.begin) {
  726. res = parseInt(curTime.getTime() - this.begin.getTime()) / 1;
  727. // 上次上报时间
  728. // console.log('res' + res);
  729. } else {
  730. res = 0;
  731. }
  732. that.begin = new Date();
  733. return parseInt(res)
  734. },
  735. // 计算卡路里
  736. calcCalorie(heartRate) {
  737. let that = this;
  738. // 取不到正常心跳数就从本地取出来
  739. if (parseInt(heartRate) == 0) {
  740. heartRate = localStorage.heartRate
  741. } else {
  742. localStorage.heartRate = heartRate
  743. }
  744. let calorieNoVo2 = 0;
  745. let curTime = that.calcHoldTime(new Date());
  746. // 男
  747. if (that.sex == 1) {
  748. calorieNoVo2 = ((-55.0969 + (0.6309 * heartRate) + (0.1988 * that.weight) + (0.2017 * that.age)) / 4.184) / 60000 * curTime;
  749. } else {
  750. calorieNoVo2 = ((-20.4022 + (0.4472 * heartRate) - (0.1263 * that.weight) + (0.074 * that.age)) / 4.184) / 60000 * curTime;
  751. }
  752. // 记录增量卡路里
  753. that.addCalories = calorieNoVo2;
  754. that.cal = that.cal + calorieNoVo2;
  755. // console.log('heartRate:' + heartRate);
  756. // console.log('calorieNoVo2:' + calorieNoVo2);
  757. // 计算CK
  758. that.calcCk(that.cal);
  759. that.calcSportCal(calorieNoVo2, curTime)
  760. },
  761. // 计算CK
  762. calcCk(cal) {
  763. this.ck = parseFloat(cal / this.weight).toFixed(2);
  764. },
  765. // 计算运动卡路里
  766. calcSportCal(calorieNoVo2,curTime) {
  767. let that = this;
  768. let bmrMSjDaily = 0;
  769. // 男
  770. if (that.sex == 1) {
  771. bmrMSjDaily = (10.00 * this.weight) + (6.25 * this.height) - (5.00 * this.age) + 5.00;
  772. } else {
  773. // 女
  774. bmrMSjDaily = (10.00 * this.weight) + (6.25 * this.height) - (5.00 * this.age) - 161
  775. }
  776. // 不为负值
  777. if (bmrMSjDaily < 0) {
  778. bmrMSjDaily = 0;
  779. }
  780. let BmrMSjRmrcb = parseFloat((bmrMSjDaily * 1.1) / 24);
  781. // let calorieNoVo2Pure = (calorieNoVo2 - BmrMSjRmrcb / 3600 * 1);
  782. let calorieNoVo2Pure = (calorieNoVo2 - BmrMSjRmrcb / curTime);
  783. // 记录增量运动卡路里
  784. that.addPureCalories = calorieNoVo2Pure;
  785. this.sportCal = this.sportCal + calorieNoVo2Pure;
  786. },
  787. // 绘制心电图
  788. DrawHeartLine(heartLine, dataLabels) {
  789. this.dataLabels = dataLabels;
  790. this.dataDatasets = heartLine;
  791. this.calcMaxHr(heartLine);
  792. this.calcAveHr(heartLine);
  793. },
  794. // 最大心率
  795. calcMaxHr(heartLine) {
  796. this.heartMax = Math.max(...heartLine);
  797. },
  798. // 平均心率
  799. calcAveHr(heartLine) {
  800. var sum = 0;
  801. for (var i = 0; i < heartLine.length; i++) {
  802. sum += heartLine[i];
  803. }
  804. this.heartAverage = parseInt(sum / heartLine.length);
  805. },
  806. // 上报信息
  807. AutoAddAppHeartRate() {
  808. let that = this;
  809. // console.log('duId:' + that.duId);
  810. let NorMalSn = that.sn.substring(6, that.sn.length);
  811. console.log('NorMalSn:' + parseInt(NorMalSn));
  812. let param = {
  813. token: localStorage.token,
  814. duId: that.duId,
  815. sn: parseInt(NorMalSn),
  816. hrId: that.HrId,
  817. heartRate: that.heartRate,
  818. rcvTime: new Date().getTime(),
  819. calories: parseInt(that.addCalories * 1000000), //卡
  820. pureCalories: parseInt(that.addPureCalories * 1000000), //卡
  821. };
  822. console.log(JSON.stringify(param));
  823. let postdata = qs.stringify(param);
  824. AddAppHeartRate(postdata).then(res => {
  825. let json = res;
  826. if (json.Code == 0) {
  827. that.InClass = json.InClass;
  828. console.log('心率数据上传成功!');
  829. } else {
  830. // that.Toast( '心率数据上传失败' + json.Memo);
  831. console.log('心率数据上传失败' + json.Memo);
  832. }
  833. })
  834. },
  835. AddHrSensorsUpdate() {
  836. let that = this;
  837. let NorMalSn = that.sn.substring(6, that.sn.length);
  838. that.NorMalSn = NorMalSn;
  839. console.log('==========>NorMalSn:' + parseInt(NorMalSn));
  840. let param = {
  841. token: localStorage.token,
  842. sn: parseInt(NorMalSn),
  843. };
  844. let postdata = qs.stringify(param);
  845. HrSensorsUpdate(postdata).then(res => {
  846. let json = res;
  847. console.log('HrSensorsUpdate' + JSON.stringify(json));
  848. if (json.Code == 0) {
  849. that.HrId = json.HrId;
  850. // that.Toast('心率带已连接在线课程', 'success');
  851. } else {
  852. that.HrId = '';
  853. // that.Toast(json.Memo);
  854. }
  855. })
  856. },
  857. // 监听蓝牙设备连接状态
  858. listenerConnection() {
  859. let that = this;
  860. plus.bluetooth.onBLEConnectionStateChange(function(e) {
  861. that.watchState = e.connected;
  862. if (!that.watchState) {
  863. that.isBreakSteate();
  864. }
  865. });
  866. },
  867. isBreakSteate() {
  868. let that = this;
  869. that.Toast('心率带已断开蓝牙连接,请重新连接', 'error');
  870. that.battery = '';
  871. that.watchText = '心率带已断开蓝牙连接';
  872. that.activeState = false;
  873. },
  874. Loading() {
  875. const loading = this.$loading({
  876. overlayColor: 'hsla(0,0%,100%,.9)', // 背景色
  877. size: 48,
  878. color: 'primary', // color
  879. });
  880. setTimeout(() => {
  881. loading.close();
  882. }, 3000)
  883. },
  884. // 打开断开连接提示窗口
  885. closeBLEConnectionAlert() {
  886. this.openBreakAlert = true;
  887. },
  888. // 断开连接
  889. closeBLEConnection() {
  890. let that = this;
  891. if (!that.deviceId) {
  892. that.Toast('当前没有已建立的连接',);
  893. return false
  894. }
  895. plus.bluetooth.closeBLEConnection({
  896. deviceId: that.deviceId,
  897. success: function(e) {
  898. that.Toast('断开操作成功', 'success');
  899. that.openBreakAlert = false;
  900. console.log('close success: ' + JSON.stringify(e));
  901. },
  902. fail: function(e) {
  903. that.Toast('断开操作失败,请重试 [res]:' + JSON.stringify(e), 'error');
  904. console.log('close failed: ' + JSON.stringify(e));
  905. }
  906. });
  907. },
  908. // 自动重连上次心率带
  909. AutoContectLast() {
  910. let that = this;
  911. if (localStorage.sn) {
  912. plus.bluetooth.openBluetoothAdapter({
  913. success: function(e) {
  914. clearTimeout(that.autoConectTimer); //清除延迟执行
  915. that.autoConectTimer = setTimeout(() => { //设置延迟执行
  916. let w = JSON.parse(localStorage.w)
  917. that.choiceWatch(w);
  918. that.Toast('即将连接上次心率带', 'success');
  919. }, 5000);
  920. },
  921. fail: function(e) {
  922. that.Toast('打开失败! 请确认蓝牙开关已开启', 'error');
  923. }
  924. });
  925. } else {
  926. return false
  927. }
  928. },
  929. // 显示版本号
  930. showVersion() {
  931. this.Toast('当前版本号' + localStorage.version, 'success');
  932. },
  933. logoutBtn() {
  934. this.Toast('退出当前账户', 'success');
  935. localStorage.token = '';
  936. this.$router.push({ path: '/login' });
  937. },
  938. // 删除默认心率带
  939. delDefault() {
  940. localStorage.sn = '';
  941. }
  942. },
  943. filters: {
  944. parseLevel: function(value) {
  945. if (!value) {
  946. return '无'
  947. } else {
  948. if (parseInt(value) > -60) {
  949. return '强';
  950. } else {
  951. return '弱';
  952. }
  953. }
  954. }
  955. ,
  956. parseToInt: function(val) {
  957. return parseInt(val)
  958. }
  959. ,
  960. parseToFix1: function(val) {
  961. return parseFloat(val).toFixed(1)
  962. }
  963. }
  964. ,
  965. components: {
  966. LineExample
  967. }
  968. }
  969. </script>
  970. <style scoped>
  971. .top {
  972. width: 100%;
  973. overflow: hidden;
  974. display: block;
  975. margin: 0 auto;
  976. padding-top: 10px;
  977. padding-bottom: 10px;
  978. }
  979. .top .watchState {
  980. width: 100%;
  981. overflow: hidden;
  982. display: block;
  983. margin: 0 auto;
  984. height: 20px;
  985. line-height: 20px;
  986. color: #fff;
  987. text-align: center;
  988. margin-top: 20px;
  989. margin-bottom: 10px;
  990. }
  991. .toprow {
  992. width: 100%;
  993. overflow: hidden;
  994. display: block;
  995. margin: 0 auto;
  996. }
  997. .toprow .lt {
  998. width: 30%;
  999. float: left;
  1000. overflow: hidden;
  1001. }
  1002. .toprow .md {
  1003. width: 40%;
  1004. float: left;
  1005. overflow: hidden;
  1006. }
  1007. .toprow .rt {
  1008. width: 30%;
  1009. float: right;
  1010. overflow: hidden;
  1011. }
  1012. .toprow .lt .activeLevel {
  1013. width: 100%;
  1014. overflow: hidden;
  1015. display: block;
  1016. margin: 0 auto;
  1017. margin-top: 10px;
  1018. color: #fff;
  1019. }
  1020. .activeLevel div {
  1021. width: 86px;
  1022. overflow: hidden;
  1023. display: block;
  1024. margin: 0 auto;
  1025. }
  1026. .activeLevel s {
  1027. float: right;
  1028. font-size: 20px;
  1029. }
  1030. .activeLevel em {
  1031. font-size: 40px;
  1032. text-align: right;
  1033. font-weight: bold;
  1034. float: right;
  1035. }
  1036. .toprow .lt span {
  1037. width: 80px;
  1038. height: 20px;
  1039. overflow: hidden;
  1040. display: block;
  1041. margin: 0 auto;
  1042. color: #fff;
  1043. border: 1px solid #fff;
  1044. border-radius: 250px;
  1045. text-align: center;
  1046. line-height: 20px;
  1047. font-size: 12px;
  1048. }
  1049. .toprow .md .headContainer {
  1050. width: 70%;
  1051. height: 70%;
  1052. border: 3px solid rgba(255, 255, 255, 0.71);
  1053. border-radius: 250px;
  1054. overflow: hidden;
  1055. display: block;
  1056. margin: 0 auto;
  1057. }
  1058. .headContainer img {
  1059. width: 100%;
  1060. height: 100%;
  1061. overflow: hidden;
  1062. display: block;
  1063. margin: 0 auto;
  1064. }
  1065. .activeLevel .noValue {
  1066. width: 100%;
  1067. overflow: hidden;
  1068. display: block;
  1069. margin: 0 auto;
  1070. font-weight: bold;
  1071. font-size: 40px;
  1072. text-align: center;
  1073. float: none;
  1074. }
  1075. .username {
  1076. width: 100%;
  1077. height: 30px;
  1078. overflow: hidden;
  1079. display: block;
  1080. margin: 0 auto;
  1081. font-size: 14px;
  1082. color: #fff;
  1083. margin-top: 10px;
  1084. }
  1085. .username em {
  1086. width: 100%;
  1087. overflow: hidden;
  1088. display: block;
  1089. margin: 0 auto;
  1090. text-align: center;
  1091. }
  1092. .username img {
  1093. position: relative;
  1094. bottom: 20px;
  1095. float: right;
  1096. width: 15px;
  1097. height: 15px;
  1098. right: 15%;
  1099. }
  1100. .heartJump {
  1101. width: 90%;
  1102. overflow: hidden;
  1103. float: left;
  1104. margin: 0 auto;
  1105. margin-top: 10px;
  1106. color: #fff;
  1107. }
  1108. .heartJump div {
  1109. width: 86px;
  1110. overflow: hidden;
  1111. display: block;
  1112. margin: 0 auto;
  1113. }
  1114. .heartJump img {
  1115. width: 16px;
  1116. height: 14px;
  1117. float: right;
  1118. }
  1119. .heartJump em {
  1120. font-size: 40px;
  1121. text-align: right;
  1122. font-weight: bold;
  1123. float: right;
  1124. }
  1125. .heartJump .noValue {
  1126. width: 100%;
  1127. overflow: hidden;
  1128. display: block;
  1129. margin: 0 auto;
  1130. font-weight: bold;
  1131. font-size: 40px;
  1132. text-align: center;
  1133. float: none;
  1134. }
  1135. .toprow .rt span {
  1136. width: 80px;
  1137. height: 20px;
  1138. overflow: hidden;
  1139. display: block;
  1140. margin: 0 auto;
  1141. /*float: left;*/
  1142. color: #fff;
  1143. border: 1px solid #fff;
  1144. border-radius: 250px;
  1145. text-align: center;
  1146. line-height: 20px;
  1147. font-size: 12px;
  1148. }
  1149. .info {
  1150. width: 100%;
  1151. overflow: hidden;
  1152. display: block;
  1153. margin: 0 auto;
  1154. }
  1155. .info ul {
  1156. width: 100%;
  1157. overflow: hidden;
  1158. display: block;
  1159. margin: 0 auto;
  1160. margin-top: 10px;
  1161. margin-bottom: 10px;
  1162. }
  1163. .info li {
  1164. width: 25%;
  1165. border-left: 1px solid #fff;
  1166. border-right: 1px solid #fff;
  1167. float: left;
  1168. text-align: center;
  1169. }
  1170. .info li:nth-child(2) {
  1171. border-color: #e2e2e2;
  1172. }
  1173. .info li:nth-child(3) {
  1174. border-color: #e2e2e2;
  1175. border-left: 0;
  1176. }
  1177. .info li em {
  1178. width: 100%;
  1179. overflow: hidden;
  1180. display: block;
  1181. margin: 0 auto;
  1182. color: #363636;
  1183. font-size: 20px;
  1184. text-align: center;
  1185. }
  1186. .info li span {
  1187. width: 100%;
  1188. overflow: hidden;
  1189. display: block;
  1190. margin: 0 auto;
  1191. color: #c4c4c4;
  1192. font-size: 12px;
  1193. text-align: center;
  1194. }
  1195. .row {
  1196. width: 100%;
  1197. overflow: hidden;
  1198. display: block;
  1199. margin: 0 auto;
  1200. background: #efefef;
  1201. padding-top: 5px;
  1202. padding-bottom: 5px;
  1203. }
  1204. .row .rowCenter {
  1205. width: 208px;
  1206. overflow: hidden;
  1207. display: block;
  1208. margin: 0 auto;
  1209. line-height: 30px;
  1210. }
  1211. .rowCenter img {
  1212. width: 11px;
  1213. height: 11px;
  1214. float: left;
  1215. margin-top: 10px;
  1216. margin-right: 5px;
  1217. }
  1218. .rowCenter em {
  1219. font-size: 14px;
  1220. color: #ff4040;
  1221. margin-right: 15px;
  1222. }
  1223. .rowCenter button {
  1224. width: 92px;
  1225. height: 27px;
  1226. text-align: center;
  1227. line-height: 27px;
  1228. color: black;
  1229. background: #ffde93;
  1230. border-radius: 6px;
  1231. border: none;
  1232. outline: none;
  1233. }
  1234. .middle {
  1235. width: 100%;
  1236. overflow: hidden;
  1237. display: block;
  1238. margin: 0 auto;
  1239. border-bottom: 10px solid #efefef;
  1240. }
  1241. .middle ul {
  1242. width: 100%;
  1243. overflow: hidden;
  1244. display: block;
  1245. margin: 0 auto;
  1246. padding-top: 10px;
  1247. padding-bottom: 10px;
  1248. }
  1249. .middle li {
  1250. width: 33%;
  1251. float: left;
  1252. border-left: 1px solid #fff;
  1253. border-right: 1px solid #fff;
  1254. }
  1255. .middle li .center {
  1256. width: 72px;
  1257. overflow: hidden;
  1258. display: block;
  1259. margin: 0 auto;
  1260. }
  1261. .middle li:nth-child(2) {
  1262. border-color: #e2e2e2;
  1263. }
  1264. .middle li img {
  1265. width: 15px;
  1266. float: right;
  1267. margin-top: 4px;
  1268. margin-right: 5px;
  1269. }
  1270. .middle li em {
  1271. float: right;
  1272. text-align: right;
  1273. color: #000;
  1274. font-weight: bold;
  1275. font-size: 22px;
  1276. }
  1277. .middle li span {
  1278. width: 100%;
  1279. overflow: hidden;
  1280. display: block;
  1281. margin: 0 auto;
  1282. text-align: right;
  1283. color: #9a9a9a;
  1284. font-size: 12px;
  1285. }
  1286. .middle .ck {
  1287. width: 19px;
  1288. height: 19px;
  1289. margin-top: 6px;
  1290. }
  1291. .bottom {
  1292. width: 100%;
  1293. overflow: hidden;
  1294. display: block;
  1295. margin: 0 auto;
  1296. }
  1297. .bottom h5 {
  1298. width: 100%;
  1299. overflow: hidden;
  1300. display: block;
  1301. margin: 0 auto;
  1302. color: #363636;
  1303. font-size: 16px;
  1304. text-align: center;
  1305. font-weight: normal;
  1306. margin-top: 14px;
  1307. }
  1308. .bottom span {
  1309. width: 100%;
  1310. overflow: hidden;
  1311. display: block;
  1312. margin: 0 auto;
  1313. text-align: center;
  1314. font-size: 12px;
  1315. color: #9a9a9a;
  1316. }
  1317. .bottom em {
  1318. position: relative;
  1319. bottom: 160px;
  1320. right: 20px;
  1321. float: right;
  1322. color: #ff4040;
  1323. background: #fff;
  1324. }
  1325. .slowJump {
  1326. animation: mymove 3s infinite;
  1327. -webkit-animation: mymove 3s infinite; /*Safari and Chrome*/
  1328. animation-direction: alternate; /*轮流反向播放动画。*/
  1329. animation-timing-function: ease-in-out; /*动画的速度曲线*/
  1330. /* Safari 和 Chrome */
  1331. -webkit-animation-direction: alternate; /*轮流反向播放动画。*/
  1332. -webkit-animation-timing-function: ease-in-out; /*动画的速度曲线*/
  1333. }
  1334. .normalJump {
  1335. animation: mymove 2s infinite;
  1336. -webkit-animation: mymove 2s infinite; /*Safari and Chrome*/
  1337. animation-direction: alternate; /*轮流反向播放动画。*/
  1338. animation-timing-function: ease-in-out; /*动画的速度曲线*/
  1339. /* Safari 和 Chrome */
  1340. -webkit-animation-direction: alternate; /*轮流反向播放动画。*/
  1341. -webkit-animation-timing-function: ease-in-out; /*动画的速度曲线*/
  1342. }
  1343. .fastJump {
  1344. animation: mymove 1s infinite;
  1345. -webkit-animation: mymove 1s infinite; /*Safari and Chrome*/
  1346. animation-direction: alternate; /*轮流反向播放动画。*/
  1347. animation-timing-function: ease-in-out; /*动画的速度曲线*/
  1348. /* Safari 和 Chrome */
  1349. -webkit-animation-direction: alternate; /*轮流反向播放动画。*/
  1350. -webkit-animation-timing-function: ease-in-out; /*动画的速度曲线*/
  1351. }
  1352. @keyframes mymove {
  1353. 0% {
  1354. transform: scale(1); /*开始为原始大小*/
  1355. }
  1356. 25% {
  1357. transform: scale(1.1); /*放大1.1倍*/
  1358. }
  1359. 50% {
  1360. transform: scale(1);
  1361. }
  1362. 75% {
  1363. transform: scale(1.1);
  1364. }
  1365. }
  1366. @-webkit-keyframes mymove /*Safari and Chrome*/ {
  1367. 0% {
  1368. transform: scale(1); /*开始为原始大小*/
  1369. }
  1370. 25% {
  1371. transform: scale(1.1); /*放大1.1倍*/
  1372. }
  1373. 50% {
  1374. transform: scale(1);
  1375. }
  1376. 75% {
  1377. transform: scale(1.1);
  1378. }
  1379. }
  1380. /deep/ .mu-dialog {
  1381. background-color: rgba(0, 0, 0, 0.85);
  1382. color: #fff;
  1383. border-radius: 20px;
  1384. background-size: 100%;
  1385. background-origin: content-box;
  1386. }
  1387. /deep/ .mu-dialog h5 {
  1388. color: #fff;
  1389. text-align: center;
  1390. font-size: 16px;
  1391. }
  1392. /deep/ .mu-dialog p {
  1393. color: #fff;
  1394. text-align: center;
  1395. font-size: 14px;
  1396. }
  1397. /deep/ .mu-dialog .mu-primary-text-color {
  1398. margin: 0 auto;
  1399. border-radius: 9px;
  1400. background-color: rgba(255, 255, 255, 0.1);
  1401. color: #fff;
  1402. }
  1403. .watchList {
  1404. width: 100%;
  1405. overflow: hidden;
  1406. display: block;
  1407. margin: 0 auto;
  1408. min-height: 100px;
  1409. overflow-y: scroll;
  1410. }
  1411. .watchList li {
  1412. width: 100%;
  1413. padding-left: 5%;
  1414. padding-right: 5%;
  1415. padding-top: 5px;
  1416. padding-bottom: 5px;
  1417. overflow: hidden;
  1418. display: block;
  1419. margin: 0 auto;
  1420. background-color: rgba(255, 255, 255, 0.29);
  1421. color: #fff;
  1422. border-radius: 9px;
  1423. font-size: 12px;
  1424. margin-bottom: 5px;
  1425. }
  1426. .watchList li em {
  1427. float: right;
  1428. text-align: right;
  1429. }
  1430. .classInfo {
  1431. width: 100%;
  1432. overflow: hidden;
  1433. display: block;
  1434. margin: 0 auto;
  1435. font-size: 16px;
  1436. text-align: center;
  1437. }
  1438. .classInfo span {
  1439. font-size: 12px;
  1440. }
  1441. .breakConect {
  1442. font-size: 12px;
  1443. text-align: center;
  1444. color: green;
  1445. }
  1446. .breakConect button {
  1447. width: 92px;
  1448. height: 27px;
  1449. text-align: center;
  1450. line-height: 27px;
  1451. color: black;
  1452. background: rgb(255, 123, 0);
  1453. border-radius: 6px;
  1454. border: none;
  1455. outline: none;
  1456. margin-left: 15px;
  1457. font-size: 14px;
  1458. }
  1459. .logoutBtn {
  1460. width: 100px;
  1461. margin: 0 auto;
  1462. }
  1463. /deep/ .mu-loading-wrap {
  1464. position: relative;
  1465. bottom: 30px;
  1466. width: 200px;
  1467. margin: 0 auto;
  1468. }
  1469. </style>