index.js 15 KB

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