index.js 16 KB

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