index.js 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927
  1. // nova-werun/pages/home/sport/sport-start/index.js
  2. const Parse = getApp().Parse;
  3. const company = getApp().globalData.company;
  4. Page({
  5. /**
  6. * 页面的初始数据
  7. */
  8. data: {
  9. //屏幕高度
  10. statusBarHeight: 0, // 状态栏高度
  11. screenHeight: 0, // 屏幕高度
  12. customHeight: 0, // 自定义导航栏高度(如小程序右上角胶囊按钮)
  13. bottomNavHeight: 0, // 底部导航栏高度
  14. contentHeight: 0, // 可用内容高度
  15. contentHeight2: 0,
  16. contentpadding: 0, //顶部padding高度
  17. navheight: 0,
  18. //地图
  19. longitude: 0,
  20. latitude: 0,
  21. markers: [],
  22. //是否暂停
  23. isstop: false,
  24. //标题
  25. title: '',
  26. percentage: '',
  27. timer: null,
  28. startTime: 0,
  29. show: false,
  30. //
  31. timer2: null,
  32. totalSeconds: 0, // 用于存储总秒数
  33. formattedTime: '00:00:00', // 用于存储格式化后的时间
  34. isRunning: false, // 计时器是否在运行
  35. steps: 0, //运动步数
  36. defferentstep: 0,
  37. distance: 0,
  38. calorie: 0,
  39. pace: 0,
  40. //
  41. activitdateid: '', //ActivityData的id
  42. show2: false, //继续上次运动
  43. runlogList: [],
  44. iscontinue: false
  45. },
  46. /**
  47. * 生命周期函数--监听页面加载
  48. */
  49. onLoad: async function (options) {
  50. // 计算
  51. const systemInfo = wx.getSystemInfoSync();
  52. const statusBarHeight = systemInfo.statusBarHeight || 0;
  53. const screenHeight = systemInfo.screenHeight || 0;
  54. const custom = wx.getMenuButtonBoundingClientRect();
  55. const customHeight = custom.height + 10 + 2 || 0;
  56. const bottomNavHeight = systemInfo.screenHeight - systemInfo.safeArea.bottom || 0;
  57. const navheight = (statusBarHeight + customHeight) * 750 / systemInfo.windowWidth;
  58. const contentHeight = (screenHeight - bottomNavHeight) * 750 / systemInfo.windowWidth;
  59. this.setData({
  60. statusBarHeight,
  61. screenHeight,
  62. customHeight,
  63. bottomNavHeight,
  64. contentHeight,
  65. navheight,
  66. });
  67. if (options.id) {
  68. this.setData({
  69. title: options.id
  70. })
  71. }
  72. // 地图
  73. this.Getlocation();
  74. this.getWeRunData2(); // 获取初始步数
  75. //判断是否继续运动
  76. this.searchrulog()
  77. },
  78. //查询是否有为完成的记录
  79. async searchrulog() {
  80. const currentUser = Parse.User.current();
  81. const {
  82. startOfDay,
  83. endOfDay
  84. } = this.getTodayRange(); // 获取今天的日期范围
  85. let query = new Parse.Query('ActivityRunLog');
  86. query.equalTo('company', company);
  87. query.equalTo('user', currentUser.id);
  88. query.notEqualTo('isDeleted', true);
  89. query.greaterThanOrEqualTo('createdAt', startOfDay);
  90. query.lessThanOrEqualTo('createdAt', endOfDay);
  91. query.descending('createdAt');
  92. let P = await query.find();
  93. let runlogList = P.map(item => item.toJSON());
  94. if (runlogList.length == 0) {
  95. console.log('今日无数据');
  96. // 今日无数据
  97. this.startdate(); // 创建开始数据
  98. this.getWeRunData2(); // 获取初始步数
  99. this.startbackgroumd(); // 开启后台定位
  100. return
  101. } else {
  102. console.log('今日有数据');
  103. console.log(runlogList);
  104. if (runlogList[0].stage == 'end') {
  105. console.log('可以开始');
  106. this.startdate(); // 创建开始数据
  107. this.getWeRunData2(); // 获取初始步数
  108. this.startbackgroumd(); // 开启后台定位
  109. return
  110. } else {
  111. console.log('是否继续运动');
  112. this.setData({
  113. runlogList,
  114. show2: true,
  115. })
  116. this.stop()
  117. return
  118. }
  119. }
  120. },
  121. // 继续上次运动
  122. async continueLastActivity(lastRunlog) {
  123. console.log(lastRunlog);
  124. const id = await this.getActivityDataid(); // 获取 ActivityData ID
  125. console.log('id', id);
  126. this.setData({
  127. distance: lastRunlog.distance,
  128. totalSeconds: lastRunlog.sportDate,
  129. defferentstep: lastRunlog.steps,
  130. calorie: lastRunlog.burnCalories,
  131. activitdateid: id,
  132. })
  133. this.startbackgroumd(); // 开启后台定位
  134. },
  135. // 开启新运动
  136. async startNewActivity() {
  137. await this.getWeRunData2(); // 获取初始步数
  138. this.startbackgroumd(); // 开启后台定位
  139. await this.startdate(); // 创建开始数据
  140. },
  141. //今天时间范围
  142. getTodayRange() {
  143. const now = new Date();
  144. const startOfDay = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0, 0); // 今天的开始时间
  145. const endOfDay = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 23, 59, 59, 999); // 今天的结束时间
  146. return {
  147. startOfDay,
  148. endOfDay
  149. };
  150. },
  151. //查找继续运动的ActivityData的id
  152. async getActivityDataid() {
  153. try {
  154. const currentUser = Parse.User.current();
  155. const {
  156. startOfDay,
  157. endOfDay
  158. } = this.getTodayRange(); // 获取今天的日期范围
  159. // 查询最近一条 stage 为 "start" 的 ActivityRunLog
  160. const runlogQuery = new Parse.Query('ActivityRunLog');
  161. runlogQuery.equalTo('company', company);
  162. runlogQuery.equalTo('user', currentUser.id);
  163. runlogQuery.notEqualTo('isDeleted', true);
  164. runlogQuery.equalTo('stage', 'start');
  165. runlogQuery.greaterThanOrEqualTo('createdAt', startOfDay);
  166. runlogQuery.lessThanOrEqualTo('createdAt', endOfDay);
  167. runlogQuery.descending('createdAt');
  168. runlogQuery.limit(1);
  169. const latestRunlog = await runlogQuery.first();
  170. if (!latestRunlog) {
  171. throw new Error('未找到符合条件的 ActivityRunLog 记录');
  172. }
  173. // 查询对应的 ActivityData
  174. const activityDataQuery = new Parse.Query('ActivityData');
  175. activityDataQuery.equalTo('company', company);
  176. activityDataQuery.equalTo('user', currentUser.id);
  177. activityDataQuery.notEqualTo('isDeleted', true);
  178. activityDataQuery.equalTo('runlog', latestRunlog.id); // 使用 latestRunlog.id
  179. const activityData = await activityDataQuery.first();
  180. if (!activityData) {
  181. throw new Error('未找到对应的 ActivityData 记录');
  182. }
  183. return activityData.id; // 返回 ActivityData 的 objectId
  184. } catch (error) {
  185. console.error('获取 ActivityData ID 失败:', error);
  186. throw error;
  187. }
  188. },
  189. //取消弹窗
  190. onClose2() {
  191. this.setData({
  192. show2: false,
  193. });
  194. this.getWeRunData2(); // 获取初始步数
  195. this.continue()
  196. this.startNewActivity()
  197. },
  198. //确认返回
  199. onConfirm2() {
  200. this.setData({
  201. show2: false,
  202. iscontinue: true
  203. });
  204. this.getWeRunData2(); // 获取初始步数
  205. this.continue()
  206. this.continueLastActivity(this.data.runlogList[0]);
  207. },
  208. /**
  209. * 生命周期函数--监听页面初次渲染完成
  210. */
  211. onReady: function () {
  212. },
  213. /**
  214. * 生命周期函数--监听页面显示
  215. */
  216. onShow: function () {
  217. if (!this.data.isstop) {
  218. this.startTimer();
  219. }
  220. },
  221. /**
  222. * 生命周期函数--监听页面隐藏
  223. */
  224. onHide: function () {
  225. if (this.data.isRunning) {
  226. this.stopTimer();
  227. }
  228. },
  229. /**
  230. * 生命周期函数--监听页面卸载
  231. */
  232. onUnload: function () {
  233. this.stopTimer();
  234. },
  235. /**
  236. * 页面相关事件处理函数--监听用户下拉动作
  237. */
  238. onPullDownRefresh: function () {
  239. },
  240. /**
  241. * 页面上拉触底事件的处理函数
  242. */
  243. onReachBottom: function () {
  244. },
  245. /**
  246. * 用户点击右上角分享
  247. */
  248. onShareAppMessage: function () {
  249. },
  250. //获取当前位置信息
  251. Getlocation() {
  252. // 获取当前位置信息
  253. wx.getLocation({
  254. type: 'gcj02',
  255. success: (res) => {
  256. const {
  257. latitude,
  258. longitude
  259. } = res;
  260. console.log('获取到的经纬度:', latitude, longitude); // 添加日志
  261. //调用api解析地址
  262. wx.request({
  263. url: 'https://api.map.baidu.com/reverse_geocoding/v3/?ak=sHZTomd7grslfP7sPKB8tRgT49FK9TEu&output=json&coordtype=gcj02&location=' + latitude + ',' + longitude,
  264. data: {},
  265. header: {
  266. 'Content-Type': 'application/json'
  267. },
  268. success: (ops) => { // 使用箭头函数
  269. const address = ops.data.result.formatted_address;
  270. this.setData({
  271. address: address,
  272. latitude: latitude, // 保证 latitude 被设置
  273. longitude: longitude, // 保证 longitude 被设置
  274. markers: [{ // 设置 markers
  275. id: 1,
  276. latitude: latitude,
  277. longitude: longitude,
  278. iconPath: 'https://file-cloud.fmode.cn/13WZ0W7u3l/20240724/7ebg0k104325941.png?imageView2/1/w/200/h/200', // 自定义标记图标
  279. width: 40,
  280. height: 40,
  281. // callout: {
  282. // content: address, // 可以显示解析出的地址
  283. // color: '#ffffff',
  284. // bgColor: '#7F56B2',
  285. // padding: 10,
  286. // borderRadius: 5,
  287. // display: 'ALWAYS'
  288. // }
  289. }]
  290. });
  291. },
  292. fail: function (resq) {
  293. wx.showModal({
  294. title: '信息提示',
  295. content: '请求失败',
  296. showCancel: false,
  297. confirmColor: '#f37938'
  298. });
  299. },
  300. complete: function () {}
  301. })
  302. },
  303. fail: (err) => {
  304. console.error(err);
  305. wx.showToast({
  306. title: '获取位置失败',
  307. icon: 'none'
  308. });
  309. }
  310. });
  311. },
  312. //继续计时
  313. continue () {
  314. this.setData({
  315. isstop: false
  316. })
  317. this.startTimer()
  318. },
  319. //停止计时
  320. stop() {
  321. this.setData({
  322. isstop: true,
  323. })
  324. this.stopTimer()
  325. console.log(this.data.isstop);
  326. },
  327. //结束光环展示
  328. startIncrease() {
  329. // 记录开始时间
  330. this.setData({
  331. startTime: Date.now(),
  332. });
  333. // 清除之前的定时器
  334. if (this.data.timer) {
  335. clearInterval(this.data.timer);
  336. }
  337. // 设置定时器,每隔 40 毫秒更新一次 percentage
  338. this.setData({
  339. timer: setInterval(() => {
  340. const currentTime = Date.now();
  341. const elapsedTime = currentTime - this.data.startTime;
  342. const percentage = Math.min((elapsedTime / 4000) * 100, 100);
  343. this.setData({
  344. percentage: `conic-gradient(from 0deg, #015EEA ${percentage}%, white 0%)`,
  345. });
  346. if (percentage >= 100) {
  347. wx.showToast({
  348. title: '运动已结束',
  349. icon: 'success',
  350. duration: 500
  351. });
  352. this.enddate() //结束数据
  353. this.endActivitydate()
  354. setTimeout(() => {
  355. this.onConfirm()
  356. }, 500)
  357. }
  358. // 如果达到 100%,清除定时器
  359. if (percentage >= 100) {
  360. clearInterval(this.data.timer);
  361. this.setData({
  362. timer: null,
  363. });
  364. }
  365. }, 40),
  366. });
  367. },
  368. stopIncrease() {
  369. // 清除定时器
  370. if (this.data.timer) {
  371. clearInterval(this.data.timer);
  372. this.setData({
  373. timer: null,
  374. });
  375. // 如果未达到 100%,清零 percentage
  376. const elapsedTime = Date.now() - this.data.startTime;
  377. if (elapsedTime < 4000) {
  378. this.setData({
  379. percentage: '',
  380. });
  381. }
  382. }
  383. },
  384. //点击返回按钮
  385. goback() {
  386. this.setData({
  387. show: true,
  388. isstop: true,
  389. })
  390. },
  391. //取消弹窗
  392. onClose() {
  393. this.setData({
  394. show: false
  395. });
  396. },
  397. //确认返回
  398. onConfirm() {
  399. wx.navigateBack({
  400. delta: 1 // 返回的页面层数,1 表示返回上一页
  401. });
  402. this.stopBackgroundLocation() // 停止后台定位和位置监听
  403. },
  404. //开始计时或继续计时
  405. startTimer: function () {
  406. if (this.data.isRunning) return; // 如果已经在运行,则不再启动
  407. const that = this;
  408. this.data.timer2 = setInterval(function () {
  409. that.data.totalSeconds += 1; // 增加总秒数
  410. that.setData({
  411. formattedTime: that.formatTime(that.data.totalSeconds) // 更新格式化后的时间
  412. });
  413. // 每30秒调用一次getWeRunData
  414. if (that.data.totalSeconds % 4 === 0) {
  415. that.getWeRunData(); // 调用获取微信步数的函数
  416. }
  417. that.onLocationChange((res) => {
  418. // 这里可以处理位置变化的逻辑
  419. console.log('位置已更新:', res);
  420. });
  421. }, 1000);
  422. this.setData({
  423. isRunning: true // 设置为运行状态
  424. });
  425. },
  426. //暂停
  427. stopTimer: function () {
  428. clearInterval(this.data.timer2);
  429. this.setData({
  430. isRunning: false // 设置为未运行状态
  431. });
  432. wx.offLocationChange();
  433. },
  434. formatTime: function (seconds) {
  435. const hours = Math.floor(seconds / 3600);
  436. const minutes = Math.floor((seconds % 3600) / 60);
  437. const secs = seconds % 60;
  438. // 格式化为两位数
  439. const formattedHours = String(hours).padStart(2, '0');
  440. const formattedMinutes = String(minutes).padStart(2, '0');
  441. const formattedSeconds = String(secs).padStart(2, '0');
  442. return `${formattedHours}:${formattedMinutes}:${formattedSeconds}`;
  443. },
  444. //获取初始步数
  445. async getWeRunData2() {
  446. wx.getWeRunData({
  447. success: (res) => {
  448. // 获取到的加密数据
  449. const encryptedData = res.encryptedData;
  450. const iv = res.iv;
  451. const userInfo = wx.getStorageSync('userInfo');
  452. const session_key = userInfo.session_key
  453. // 这里需要调用你的后端接口进行解密
  454. // 假设你有一个解密函数 decryptData
  455. this.decryptData(encryptedData, iv, session_key).then(async steps => {
  456. console.log('再次赋值');
  457. await this.setData({
  458. steps: steps,
  459. });
  460. console.log('用户步数:', this.data.steps);
  461. }).catch(err => {
  462. console.error('解密失败:', err);
  463. });
  464. },
  465. fail: (err) => {
  466. console.error('获取运动数据失败:', err);
  467. }
  468. });
  469. },
  470. //获取微信步数
  471. async getWeRunData() {
  472. wx.getWeRunData({
  473. success: (res) => {
  474. // 获取到的加密数据
  475. const encryptedData = res.encryptedData;
  476. const iv = res.iv;
  477. const userInfo = wx.getStorageSync('userInfo');
  478. const session_key = userInfo.session_key
  479. // 这里需要调用你的后端接口进行解密
  480. // 假设你有一个解密函数 decryptData
  481. this.decryptData(encryptedData, iv, session_key).then(async steps => {
  482. console.log('再次赋值');
  483. const defferentstep = steps - this.data.steps + this.data.defferentstep
  484. await this.setData({
  485. // defferentstep: steps - this.data.startsteps
  486. defferentstep,
  487. steps,
  488. });
  489. console.log('用户步数:', this.data.steps);
  490. }).catch(err => {
  491. console.error('解密失败:', err);
  492. });
  493. },
  494. fail: (err) => {
  495. console.error('获取运动数据失败:', err);
  496. }
  497. });
  498. },
  499. // 解密
  500. decryptData(encryptedData, iv, session_key) {
  501. return new Promise((resolve, reject) => {
  502. // 发送请求到后端进行解密
  503. wx.request({
  504. url: 'https://server.fmode.cn/api/wxapp/decrypt_phone', // 替换为你的后端解密接口
  505. method: 'get',
  506. data: {
  507. encryptedData: encryptedData,
  508. iv: iv,
  509. appId: 'wxe6ecc0193c09696c',
  510. sessionKey: session_key
  511. },
  512. success: (res) => {
  513. if (res.data.data) {
  514. const stepInfoList = res.data.data.stepInfoList
  515. const todaylist = stepInfoList.filter(item => {
  516. console.log(this.isToday(item));
  517. return this.isToday(item); // 使用 isToday 函数判断是否是今天
  518. });
  519. const steps = todaylist[0].step;
  520. resolve(steps);
  521. } else {
  522. reject('解密返回数据格式错误');
  523. }
  524. },
  525. fail: (err) => {
  526. reject(err);
  527. }
  528. });
  529. });
  530. },
  531. // 判断日期是否是今天
  532. isToday(item) {
  533. const today = new Date();
  534. const date = new Date(item.timestamp * 1000); // 假设时间戳是以秒为单位
  535. // 比较年、月、日
  536. return date.getFullYear() === today.getFullYear() &&
  537. date.getMonth() === today.getMonth() &&
  538. date.getDate() === today.getDate();
  539. },
  540. // 开启后台定位
  541. startbackgroumd() {
  542. console.log('后台定位函数执行');
  543. wx.startLocationUpdateBackground({
  544. success: (res) => {
  545. // 开始监听GPS数据
  546. this.onLocationChange((res) => {
  547. // 在这里处理位置变化的逻辑
  548. console.log('位置已更新:', res);
  549. });
  550. console.log('后台定位打开');
  551. },
  552. fail: (res) => {
  553. console.log(res);
  554. // 授权失败后引导用户打开定位信息
  555. // 可以添加提示或引导用户操作的代码
  556. }
  557. });
  558. },
  559. // 监听位置变化
  560. onLocationChange(callback) {
  561. console.log('运行了');
  562. // 监听位置变化
  563. // this.Getlocation2()
  564. wx.onLocationChange((res) => {
  565. // 计算距离
  566. let distance = this.haversineDistance(this.data.longitude, this.data.latitude, res.longitude, res.latitude);
  567. // 更新总距离
  568. const totalDistance = parseFloat((Number(this.data.distance) + Number(distance)).toFixed(3));
  569. if (totalDistance != this.data.distance) {
  570. this.progressdate()
  571. this.progressActivitydate()
  572. }
  573. // 计算卡路里
  574. const calorie = this.getCalorie(60, totalDistance); // 假设体重为60kg
  575. let pace = 0
  576. // if (this.data.title == '步行') {
  577. // pace = (totalDistance / (this.data.totalSeconds / 3600)) || 0;
  578. // pace = parseFloat(pace.toFixed(2));
  579. // }else{
  580. // }
  581. if(this.data.totalSeconds&&totalDistance){
  582. pace = ((this.data.totalSeconds / 60)/totalDistance) || 0;
  583. pace = parseFloat(pace.toFixed(2));
  584. }
  585. // if (res.speed > 0) {
  586. // pace = parseFloat(Number((res.speed * 3.6).toFixed(2))); // 配速(km/h)
  587. // console.log(pace);
  588. // }
  589. console.log('总距离', totalDistance, '段距离', distance, '总卡路里', calorie, '配速', pace);
  590. // 更新状态
  591. this.setData({
  592. pace,
  593. distance: totalDistance,
  594. calorie: calorie,
  595. latitude: res.latitude,
  596. longitude: res.longitude
  597. });
  598. // 打印更新后的经纬度(可选)
  599. console.log('更新后的经纬度:', this.data.latitude, this.data.longitude);
  600. // 调用回调函数(如果有提供的话)
  601. if (callback) {
  602. callback(res);
  603. }
  604. });
  605. },
  606. //位置变化
  607. Getlocation2() {
  608. // 获取当前位置信息
  609. wx.getLocation({
  610. type: 'gcj02',
  611. success: (res) => {
  612. const {
  613. latitude,
  614. longitude
  615. } = res;
  616. if (this.data.longitude == res.longitude && this.data.latitude == res.latitude) {
  617. console.log('位置没变');
  618. } else {
  619. // 计算距离
  620. let distance = this.haversineDistance(this.data.longitude, this.data.latitude, res.longitude, res.latitude);
  621. // 更新总距离
  622. const totalDistance = parseFloat((Number(this.data.distance) + Number(distance)).toFixed(3));
  623. // 计算卡路里
  624. const calorie = this.getCalorie(60, totalDistance); // 假设体重为60kg
  625. const pace = parseFloat(Number((totalDistance / (this.data.totalSeconds / 3600)).toFixed(2))); // 配速(km/h)
  626. console.log('总距离', totalDistance, '段距离', distance, '总卡路里', calorie, '配速', pace);
  627. // 更新状态
  628. this.setData({
  629. pace,
  630. distance: totalDistance,
  631. calorie: calorie,
  632. latitude: res.latitude,
  633. longitude: res.longitude
  634. });
  635. console.log('更新经纬度:', latitude, longitude); // 添加日志
  636. }
  637. },
  638. fail: (err) => {
  639. console.error(err);
  640. wx.showToast({
  641. title: '获取位置失败',
  642. icon: 'none'
  643. });
  644. }
  645. });
  646. },
  647. //计算两点距离
  648. haversineDistance(longitude1, latitude1, longitude2, latitude2) {
  649. let lat1 = latitude1
  650. let lon1 = longitude1
  651. let lat2 = latitude2
  652. let lon2 = longitude2
  653. function toRad(degree) {
  654. return degree * Math.PI / 180;
  655. }
  656. const R = 6371e3; // 地球半径,单位为米
  657. const φ1 = toRad(lat1);
  658. const φ2 = toRad(lat2);
  659. const Δφ = toRad(lat2 - lat1);
  660. const Δλ = toRad(lon2 - lon1);
  661. const a = Math.sin(Δφ / 2) * Math.sin(Δφ / 2) +
  662. Math.cos(φ1) * Math.cos(φ2) *
  663. Math.sin(Δλ / 2) * Math.sin(Δλ / 2);
  664. const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
  665. const distance = (R * c) / 1000; // 距离,单位为公里
  666. console.log('计算出距离', distance);
  667. return parseFloat(distance.toFixed(3));
  668. },
  669. //计算卡路里
  670. getCalorie(weight, distance) {
  671. weight = weight || 60 // 国人平均体重 60kg
  672. const Calorie = weight * distance * 0.75
  673. console.log('卡路里为', Calorie);
  674. return parseFloat(Calorie.toFixed(2)); // 保留两位小数并转换为数字
  675. },
  676. //创建开始数据
  677. async startdate() {
  678. if (!this.data.iscontinue) {
  679. const currentUser = Parse.User.current();
  680. let Userquery = new Parse.Query('_User');
  681. Userquery.equalTo('company', company);
  682. Userquery.equalTo('objectId', currentUser.id);
  683. Userquery.notEqualTo('isDeleted', true)
  684. let user = await Userquery.first();
  685. let companyPointer = Parse.Object.extend('Company').createWithoutData(company);
  686. let query = new Parse.Object('ActivityRunLog');
  687. query.set('user', user.toPointer())
  688. query.set('company', companyPointer)
  689. query.set('stage', 'start')
  690. query.set('steps', 0) //步数
  691. query.set('distance', 0) //距离
  692. query.set('matchSpeed', 0) //配速
  693. query.set('sportDate', 0) //运动时间
  694. query.set('burnCalories', 0) //卡路里
  695. try {
  696. let saveDate2 = await query.save();
  697. console.log(saveDate2);
  698. const id = saveDate2.id
  699. await this.startActivitdate(id)
  700. console.log("创建开始数据");
  701. } catch (error) {
  702. console.error("保存数据时出现错误:", error);
  703. }
  704. }
  705. },
  706. //创建ActivityData数据
  707. async startActivitdate(objectId) {
  708. const currentUser = Parse.User.current();
  709. let Userquery = new Parse.Query('_User');
  710. Userquery.equalTo('company', company);
  711. Userquery.equalTo('objectId', currentUser.id);
  712. Userquery.notEqualTo('isDeleted', true)
  713. let user = await Userquery.first();
  714. let Activitdate = new Parse.Query('ActivityRunLog');
  715. Activitdate.equalTo('objectId', objectId);
  716. Activitdate.notEqualTo('isDeleted', true)
  717. let Activit = await Activitdate.first();
  718. let companyPointer = Parse.Object.extend('Company').createWithoutData(company);
  719. let query = new Parse.Object('ActivityData');
  720. query.set('user', user.toPointer())
  721. query.set('company', companyPointer)
  722. query.set('runlog', Activit.toPointer())
  723. // if (this.data.title == '步行') {
  724. // query.set('type', 'walk')
  725. // } else if (this.data.title == '跑步') {
  726. // query.set('type', 'run')
  727. // } else {
  728. // query.set('type', 'activity')
  729. // }
  730. if (this.data.title) {
  731. query.set('type', 'activity')
  732. }
  733. try {
  734. let saveDate2 = await query.save();
  735. this.setData({
  736. activitdateid: saveDate2.id
  737. })
  738. console.log("ActivityData数据", this.data.activitdate);
  739. } catch (error) {
  740. console.error("保存数据时出现错误:", error);
  741. }
  742. },
  743. //创建过程数据
  744. async progressdate() {
  745. if (this.data.totalSeconds % 4 != 0) {
  746. return
  747. }
  748. const currentUser = Parse.User.current();
  749. let Userquery = new Parse.Query('_User');
  750. Userquery.equalTo('company', company);
  751. Userquery.equalTo('objectId', currentUser.id);
  752. Userquery.notEqualTo('isDeleted', true)
  753. let user = await Userquery.first();
  754. let companyPointer = Parse.Object.extend('Company').createWithoutData(company);
  755. let query = new Parse.Object('ActivityRunLog');
  756. query.set('user', user.toPointer())
  757. query.set('company', companyPointer)
  758. query.set('stage', 'progress')
  759. query.set('steps', this.data.defferentstep) //步数
  760. query.set('distance', this.data.distance) //距离
  761. query.set('matchSpeed', this.data.pace) //配速
  762. query.set('sportDate', this.data.totalSeconds) //运动时间
  763. query.set('burnCalories', this.data.calorie) //卡路里
  764. try {
  765. console.log('上传成功', this.data.defferentstep, this.data.distance, this.data.pace, this.data.totalSeconds, this.data.calorie);
  766. let saveDate2 = await query.save();
  767. console.log("新数据保存成功");
  768. } catch (error) {
  769. console.error("保存数据时出现错误:", error);
  770. }
  771. },
  772. //上传ActivityData过程数据
  773. async progressActivitydate() {
  774. if (this.data.totalSeconds % 4 != 0) {
  775. return
  776. }
  777. let query = new Parse.Query('ActivityData');
  778. query.equalTo('objectId', this.data.activitdateid);
  779. query.notEqualTo('isDeleted', true)
  780. let Activit = await query.first();
  781. console.log('Activit', Activit);
  782. if (Activit) {
  783. Activit.set('steps', this.data.defferentstep) //步数
  784. Activit.set('distance', this.data.distance) //距离
  785. Activit.set('matchSpeed', this.data.pace) //配速
  786. Activit.set('sportDate', this.data.totalSeconds) //运动时间
  787. Activit.set('burnCalories', this.data.calorie) //卡路里
  788. try {
  789. let saveDate2 = await Activit.save();
  790. console.log("ActivityData过程数据数据");
  791. } catch (error) {
  792. console.error("保存数据时出现错误:", error);
  793. }
  794. }
  795. },
  796. //创建结束数据
  797. async enddate() {
  798. const currentUser = Parse.User.current();
  799. let Userquery = new Parse.Query('_User');
  800. Userquery.equalTo('company', company);
  801. Userquery.equalTo('objectId', currentUser.id);
  802. Userquery.notEqualTo('isDeleted', true)
  803. let user = await Userquery.first();
  804. let companyPointer = Parse.Object.extend('Company').createWithoutData(company);
  805. let query = new Parse.Object('ActivityRunLog');
  806. query.set('user', user.toPointer())
  807. query.set('company', companyPointer)
  808. query.set('stage', 'end')
  809. query.set('steps', this.data.defferentstep) //步数
  810. query.set('distance', this.data.distance) //距离
  811. query.set('matchSpeed', this.data.pace) //配速
  812. query.set('sportDate', this.data.totalSeconds) //运动时间
  813. query.set('burnCalories', this.data.calorie) //卡路里
  814. try {
  815. console.log('上传成功', this.data.defferentstep, this.data.distance, this.data.pace, this.data.totalSeconds, this.data.calorie);
  816. let saveDate2 = await query.save();
  817. console.log("新数据保存成功");
  818. } catch (error) {
  819. console.error("保存数据时出现错误:", error);
  820. }
  821. },
  822. //上传ActivityData结束数据
  823. async endActivitydate() {
  824. let query = new Parse.Query('ActivityData');
  825. query.equalTo('objectId', this.data.activitdateid);
  826. query.notEqualTo('isDeleted', true)
  827. let Activit = await query.first();
  828. if (Activit) {
  829. Activit.set('steps', this.data.defferentstep) //步数
  830. Activit.set('distance', this.data.distance) //距离
  831. Activit.set('matchSpeed', this.data.pace) //配速
  832. Activit.set('sportDate', this.data.totalSeconds) //运动时间
  833. Activit.set('burnCalories', this.data.calorie) //卡路里
  834. try {
  835. let saveDate2 = await Activit.save();
  836. console.log("ActivityData结束数据数据");
  837. } catch (error) {
  838. console.error("保存数据时出现错误:", error);
  839. }
  840. }
  841. },
  842. // 停止后台定位和位置监听
  843. stopBackgroundLocation() {
  844. wx.stopLocationUpdate({
  845. success: (res) => {
  846. console.log('后台定位已停止');
  847. },
  848. fail: (res) => {
  849. console.error('停止后台定位失败', res);
  850. }
  851. });
  852. wx.offLocationChange(); // 停止监听位置变化
  853. },
  854. })