index.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  1. // nova-werun/pages/home/statistics/index.js
  2. import * as echarts from "../../../components/ec-canvas/echarts.min"
  3. const Parse = getApp().Parse;
  4. const company = getApp().globalData.company;
  5. Page({
  6. /**
  7. * 页面的初始数据
  8. */
  9. data: {
  10. //屏幕高度
  11. statusBarHeight: 0, // 状态栏高度
  12. screenHeight: 0, // 屏幕高度
  13. customHeight: 0, // 自定义导航栏高度(如小程序右上角胶囊按钮)
  14. bottomNavHeight: 0, // 底部导航栏高度
  15. contentHeight: 0, // 可用内容高度
  16. contentHeight2: 0,
  17. contentpadding: 0, //顶部padding高度
  18. active: 0,
  19. //
  20. day: '7',
  21. target: '',
  22. sharList: [],
  23. //生涯数据
  24. stardate: '',
  25. daysDifference: "",
  26. totalSteps: 0,
  27. totalDistance: 0,
  28. totalBurnCalories: 0,
  29. totalsportDate: 0,
  30. ec: {
  31. onInit: null
  32. },
  33. resultList: [],
  34. stepsData: [], //统计图柱状
  35. xAxis: [], //x轴
  36. percentage: '',
  37. percent: '',
  38. //排名百分比
  39. percebtage:0,
  40. //
  41. average:0,
  42. totle:0,
  43. },
  44. /**
  45. * 生命周期函数--监听页面加载
  46. */
  47. onLoad: async function (options) {
  48. // 计算
  49. const systemInfo = wx.getSystemInfoSync();
  50. const statusBarHeight = systemInfo.statusBarHeight || 0;
  51. const screenHeight = systemInfo.screenHeight || 0;
  52. const custom = wx.getMenuButtonBoundingClientRect();
  53. const customHeight = custom.height + 10 + 2 || 0;
  54. const bottomNavHeight = systemInfo.screenHeight - systemInfo.safeArea.bottom || 0;
  55. const contentpadding = (statusBarHeight + customHeight) * 750 / systemInfo.windowWidth;
  56. const contentHeight = (screenHeight - 50 - bottomNavHeight - statusBarHeight - customHeight) * 750 / systemInfo.windowWidth;
  57. this.setData({
  58. statusBarHeight,
  59. screenHeight,
  60. customHeight,
  61. bottomNavHeight,
  62. contentpadding,
  63. contentHeight
  64. });
  65. await this.gettarget()
  66. await this.order()
  67. this.allorder()
  68. await this.getweekday()
  69. this.echartsComponnet = this.selectComponent('#mychart')
  70. await this.initChart()
  71. this.gettoday()
  72. },
  73. //图表
  74. // 将 initChart 定义在 Page 上下文中
  75. initChart() {
  76. if (this.chart) {
  77. this.chart.clear();
  78. }
  79. this.echartsComponnet.init((canvas, width, height, dpr) => {
  80. // 初始化图表
  81. this.chart = echarts.init(canvas, null, {
  82. width: width,
  83. height: height,
  84. devicePixelRatio: dpr // 清晰度 使canvas的图表更加清晰
  85. });
  86. this.chart.setOption(this.getOption())
  87. return this.chart;
  88. });
  89. },
  90. getOption() {
  91. var option = {
  92. xAxis: {
  93. type: 'category',
  94. data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
  95. axisLabel: {
  96. formatter: (value, index) => this.formatter(value, index)
  97. }
  98. },
  99. yAxis: {
  100. type: 'value',
  101. max: 20000, // 设置Y轴最大值为20000
  102. axisLabel: {
  103. formatter: function (value) {
  104. if (value >= 10000) {
  105. return (value / 1000) + 'k'; // 格式化为20k
  106. }
  107. return value;
  108. }
  109. }
  110. },
  111. series: [{
  112. // data: [
  113. // 12000,
  114. // {
  115. // value: 12000,
  116. // itemStyle: {
  117. // color: '#a90000',
  118. // }
  119. // },
  120. // 12000,
  121. // 12000,
  122. // 12000,
  123. // 12000,
  124. // 12000
  125. // ],
  126. data: this.data.stepsData,
  127. type: 'bar',
  128. barWidth: '10',
  129. itemStyle: {
  130. borderRadius: 15,
  131. }
  132. }],
  133. };
  134. return option; // 返回 option 对象
  135. },
  136. // 返回x轴底下的字
  137. formatter(value, index) {
  138. let daylist = this.data.resultList.map(item => {
  139. const day = new Date(item.createdAt); // 获取当前日期
  140. const dayOfMonth = day.getDate(); // 获取今天是几号
  141. return dayOfMonth
  142. })
  143. daylist.reverse()
  144. const dayindex = daylist.length-1
  145. if (daylist.length < 7) {
  146. for (let i = daylist.length; i < 7; i++) {
  147. const lastDay = daylist[daylist.length - 1];
  148. daylist.push(lastDay + (i - daylist.length + 1)); // 补充后续日期
  149. }
  150. }
  151. const dates = daylist.map(item=>{
  152. return `${item}号`
  153. })
  154. return index === dayindex ? '今天'+'\n' + '\n' + dates[index] : value + '\n' + '\n' + dates[index];
  155. },
  156. /**
  157. * 生命周期函数--监听页面初次渲染完成
  158. */
  159. onReady: function () {
  160. },
  161. /**
  162. * 生命周期函数--监听页面显示
  163. */
  164. onShow: function () {
  165. },
  166. /**
  167. * 生命周期函数--监听页面隐藏
  168. */
  169. onHide: function () {
  170. },
  171. /**
  172. * 生命周期函数--监听页面卸载
  173. */
  174. onUnload: function () {
  175. },
  176. /**
  177. * 页面相关事件处理函数--监听用户下拉动作
  178. */
  179. onPullDownRefresh: function () {
  180. },
  181. /**
  182. * 页面上拉触底事件的处理函数
  183. */
  184. onReachBottom: function () {
  185. },
  186. /**
  187. * 用户点击右上角分享
  188. */
  189. onShareAppMessage: function () {
  190. },
  191. //底部tab栏修改
  192. onChange(event) {
  193. this.setData({
  194. active: event.detail
  195. });
  196. this.echartsComponnet = this.selectComponent('#mychart')
  197. this.initChart()
  198. },
  199. //修改30天或者7天数据
  200. changeday() {
  201. if (this.data.day == '7') {
  202. this.setData({
  203. day: '30'
  204. })
  205. } else {
  206. this.setData({
  207. day: '7'
  208. })
  209. this.echartsComponnet = this.selectComponent('#mychart')
  210. this.initChart()
  211. this.getweekday()
  212. }
  213. },
  214. //获取目标步数
  215. async gettarget() {
  216. const currentUser = Parse.User.current();
  217. let userquery = new Parse.Query('_User');
  218. userquery.equalTo('company', company);
  219. userquery.equalTo('objectId', currentUser.id);
  220. userquery.notEqualTo('isDeleted', true)
  221. let user = await userquery.find();
  222. let num = user.map(item => item.toJSON());
  223. if (num[0].num) {
  224. this.setData({
  225. target: num[0].num
  226. })
  227. console.log('当前步数', this.data.target);
  228. }
  229. },
  230. //获取当天运动数据
  231. async order() {
  232. const currentUser = Parse.User.current();
  233. let ActivityDataquery = new Parse.Query('ActivityData');
  234. ActivityDataquery.equalTo('user', currentUser.id);
  235. ActivityDataquery.equalTo('company', company);
  236. ActivityDataquery.equalTo('type', 'today');
  237. ActivityDataquery.notEqualTo('isDeleted', true);
  238. // 获取今天的日期
  239. const today = new Date();
  240. const todayStart = new Date(today.getFullYear(), today.getMonth(), today.getDate()); // 今天的开始时间
  241. const todayEnd = new Date(todayStart);
  242. todayEnd.setHours(23, 59, 59, 999); // 今天的结束时间
  243. // 在查询条件中添加对 createdAt 的限制
  244. ActivityDataquery.greaterThanOrEqualTo('createdAt', todayStart);
  245. ActivityDataquery.lessThanOrEqualTo('createdAt', todayEnd);
  246. ActivityDataquery.include('user');
  247. let r = await ActivityDataquery.find();
  248. let sharList = r.map(item => item.toJSON());
  249. this.setData({
  250. sharList
  251. });
  252. this.getBackgroundColor()
  253. console.log(this.data.sharList);
  254. },
  255. //获取生涯运动数据
  256. async allorder() {
  257. const currentUser = Parse.User.current();
  258. let ActivityDataquery = new Parse.Query('ActivityData');
  259. ActivityDataquery.equalTo('user', currentUser.id);
  260. ActivityDataquery.equalTo('company', company);
  261. ActivityDataquery.equalTo('type', 'today');
  262. ActivityDataquery.notEqualTo('isDeleted', true);
  263. let r = await ActivityDataquery.find();
  264. let allList = r.map(item => item.toJSON());
  265. // 根据 createdAt 日期从以前到现在排列
  266. allList.sort((a, b) => new Date(a.createdAt) - new Date(b.createdAt));
  267. // 获取最早的 createdAt 日期
  268. const earliestDate = new Date(allList[0].createdAt);
  269. // 格式化为 YYYY年MM月DD日
  270. const formattedDate = `${earliestDate.getFullYear()}年${String(earliestDate.getMonth() + 1).padStart(2, '0')}月${String(earliestDate.getDate()).padStart(2, '0')}日`;
  271. // 计算从最早日期到今天的天数
  272. const today = new Date();
  273. // 清零时间部分
  274. earliestDate.setHours(0, 0, 0, 0); // 将最早日期的时间部分清零
  275. today.setHours(0, 0, 0, 0); // 将今天的时间部分清零
  276. // 计算日期差值
  277. const timeDifference = today - earliestDate; // 时间差(毫秒)
  278. const daysDifference = Math.floor(timeDifference / (1000 * 60 * 60 * 24)); // 转换为天数
  279. // 计算 steps、distance 和 burnCalories 的总和
  280. let totalSteps = 0;
  281. let totalDistance = 0;
  282. let totalBurnCalories = 0;
  283. let totalsportDate = 0;
  284. allList.forEach(item => {
  285. totalSteps += Number(item.steps) || 0; // 确保为数字类型,避免 NaN
  286. totalDistance += Number(item.distance) || 0; // 确保为数字类型,避免 NaN
  287. totalBurnCalories += Number(item.burnCalories) || 0; // 确保为数字类型,避免 NaN
  288. totalsportDate += Number(item.sportDate) || 0;
  289. });
  290. // 将总运动时间转换为天、小时、分钟
  291. const days = Math.floor(totalsportDate / (60 * 24)); // 转换为天数
  292. const hours = Math.floor((totalsportDate % (60 * 24)) / 60); // 剩余小时
  293. const minutes = totalsportDate % 60; // 剩余分钟
  294. // 设置 stardate 和 daysDifference
  295. this.setData({
  296. stardate: formattedDate,
  297. daysDifference: daysDifference,
  298. totalSteps,
  299. totalDistance,
  300. totalBurnCalories,
  301. totalsportDate: `${days}天 ${hours}小时 ${minutes}分钟` // 格式化为字符串
  302. });
  303. console.log(allList, this.data.totalsportDate);
  304. },
  305. //修改光圈
  306. getBackgroundColor() {
  307. const steps = this.data.sharList[0].steps || 0;
  308. let percent = (steps / this.data.target) * 100;
  309. console.log('目标', percent);
  310. if (percent > 100) {
  311. percent = 100;
  312. }
  313. // 保留两位小数
  314. percent = parseFloat(percent.toFixed(2));
  315. this.setData({
  316. percent,
  317. percentage: `conic-gradient(from 0deg, #015EEA ${percent}%, white 0%)`,
  318. })
  319. console.log('百分比', this.data.percentage);
  320. },
  321. //获取本周记录
  322. async getweekday() {
  323. const currentUser = Parse.User.current();
  324. let ActivityDataquery = new Parse.Query('ActivityData');
  325. ActivityDataquery.equalTo('user', currentUser.id);
  326. ActivityDataquery.equalTo('company', company);
  327. ActivityDataquery.equalTo('type', 'today');
  328. ActivityDataquery.notEqualTo('isDeleted', true);
  329. let r = await ActivityDataquery.find();
  330. let allList = r.map(item => item.toJSON());
  331. // 按时间降序排序(从现在到以前)
  332. allList.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt));
  333. // 获取今天是星期几(0 = 周日, 1 = 周一, ..., 6 = 周六)
  334. const today = new Date();
  335. const dayOfWeek = today.getDay(); // 获取当前星期几
  336. // 根据星期几决定取多少条数据
  337. let numItemsToTake;
  338. if (dayOfWeek === 0) {
  339. numItemsToTake = 7; // 周日取7条数据
  340. } else {
  341. numItemsToTake = dayOfWeek; // 周一至周六取对应条数
  342. }
  343. // 取出对应数量的数据
  344. const resultList = allList.slice(0, numItemsToTake);
  345. const stepsData = resultList.map((item, index) => {
  346. if (index === 0) {
  347. // 如果是第一条数据,设置特殊样式
  348. return {
  349. value: item.steps,
  350. itemStyle: {
  351. color: '#a90000',
  352. }
  353. };
  354. } else {
  355. // 其他数据直接返回 steps
  356. return item.steps;
  357. }
  358. });
  359. stepsData.reverse()
  360. //总计,平均
  361. let totle=0
  362. for(let i = 0;i<resultList.length;i++){
  363. totle=totle+ Number(resultList[i].steps)
  364. }
  365. const average = totle/resultList.length
  366. console.log('totle',totle,average);
  367. this.setData({
  368. resultList,
  369. stepsData,
  370. totle,
  371. average,
  372. })
  373. console.log('resultList', resultList);
  374. },
  375. //获取今日排名百分比
  376. async gettoday() {
  377. const currentUser = Parse.User.current();
  378. let ActivityDataquery = new Parse.Query('ActivityData');
  379. ActivityDataquery.equalTo('company', company);
  380. ActivityDataquery.equalTo('type', "today");
  381. ActivityDataquery.notEqualTo('isDeleted', true);
  382. // 获取今天的日期
  383. const today = new Date();
  384. const todayStart = new Date(today.getFullYear(), today.getMonth(), today.getDate()); // 今天的开始时间
  385. const todayEnd = new Date(todayStart);
  386. todayEnd.setHours(23, 59, 59, 999); // 今天的结束时间
  387. console.log(todayStart, todayEnd);
  388. // 在查询条件中添加对 createdAt 的限制
  389. ActivityDataquery.greaterThanOrEqualTo('createdAt', todayStart);
  390. ActivityDataquery.lessThanOrEqualTo('createdAt', todayEnd);
  391. // 根据 steps 字段进行降序排序
  392. ActivityDataquery.descending('steps');
  393. ActivityDataquery.include('user');
  394. try {
  395. let P = await ActivityDataquery.find();
  396. let todayList = P.map(item => item.toJSON());
  397. console.log('todayList',todayList);
  398. let rank = 0
  399. // 更新页面数据
  400. todayList.forEach((item,index)=>{
  401. if(item.user.objectId==currentUser.id){
  402. rank = index+1;
  403. return
  404. }
  405. })
  406. var ranper =100 - (rank/todayList.length)*100
  407. ranper = parseFloat(ranper.toFixed(2));
  408. this.setData({
  409. percebtage:ranper
  410. })
  411. console.log('percebtage',this.data.percebtage);
  412. } catch (error) {
  413. console.error('Error fetching today\'s data:', error);
  414. }
  415. },
  416. })