index.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  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: null,
  45. maxDate: null,
  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. this.gettodaydate()
  213. } else {
  214. this.setData({
  215. day: '7'
  216. })
  217. this.echartsComponnet = this.selectComponent('#mychart')
  218. this.initChart()
  219. this.getweekday()
  220. }
  221. },
  222. //获取目标步数
  223. async gettarget() {
  224. const currentUser = Parse.User.current();
  225. let userquery = new Parse.Query('_User');
  226. userquery.equalTo('company', company);
  227. userquery.equalTo('objectId', currentUser.id);
  228. userquery.notEqualTo('isDeleted', true)
  229. let user = await userquery.find();
  230. let num = user.map(item => item.toJSON());
  231. if (num[0].num) {
  232. this.setData({
  233. target: num[0].num
  234. })
  235. console.log('当前步数', this.data.target);
  236. }
  237. },
  238. //获取当天运动数据
  239. async order() {
  240. const currentUser = Parse.User.current();
  241. let ActivityDataquery = new Parse.Query('ActivityData');
  242. ActivityDataquery.equalTo('user', currentUser.id);
  243. ActivityDataquery.equalTo('company', company);
  244. ActivityDataquery.equalTo('type', 'today');
  245. ActivityDataquery.notEqualTo('isDeleted', true);
  246. // 获取今天的日期
  247. const today = new Date();
  248. const todayStart = new Date(today.getFullYear(), today.getMonth(), today.getDate()); // 今天的开始时间
  249. const todayEnd = new Date(todayStart);
  250. todayEnd.setHours(23, 59, 59, 999); // 今天的结束时间
  251. // 在查询条件中添加对 createdAt 的限制
  252. ActivityDataquery.greaterThanOrEqualTo('createdAt', todayStart);
  253. ActivityDataquery.lessThanOrEqualTo('createdAt', todayEnd);
  254. ActivityDataquery.include('user');
  255. let r = await ActivityDataquery.find();
  256. let sharList = r.map(item => item.toJSON());
  257. this.setData({
  258. sharList
  259. });
  260. this.getBackgroundColor()
  261. console.log(this.data.sharList);
  262. },
  263. //获取生涯运动数据
  264. async allorder() {
  265. const currentUser = Parse.User.current();
  266. let ActivityDataquery = new Parse.Query('ActivityData');
  267. ActivityDataquery.equalTo('user', currentUser.id);
  268. ActivityDataquery.equalTo('company', company);
  269. ActivityDataquery.equalTo('type', 'today');
  270. ActivityDataquery.notEqualTo('isDeleted', true);
  271. let r = await ActivityDataquery.find();
  272. let allList = r.map(item => item.toJSON());
  273. // 根据 createdAt 日期从以前到现在排列
  274. allList.sort((a, b) => new Date(a.createdAt) - new Date(b.createdAt));
  275. // 获取最早的 createdAt 日期
  276. const earliestDate = new Date(allList[0].createdAt);
  277. // 格式化为 YYYY年MM月DD日
  278. const formattedDate = `${earliestDate.getFullYear()}年${String(earliestDate.getMonth() + 1).padStart(2, '0')}月${String(earliestDate.getDate()).padStart(2, '0')}日`;
  279. // 计算从最早日期到今天的天数
  280. const today = new Date();
  281. // 清零时间部分
  282. earliestDate.setHours(0, 0, 0, 0); // 将最早日期的时间部分清零
  283. today.setHours(0, 0, 0, 0); // 将今天的时间部分清零
  284. // 计算日期差值
  285. const timeDifference = today - earliestDate; // 时间差(毫秒)
  286. const daysDifference = Math.floor(timeDifference / (1000 * 60 * 60 * 24)); // 转换为天数
  287. // 计算 steps、distance 和 burnCalories 的总和
  288. let totalSteps = 0;
  289. let totalDistance = 0;
  290. let totalBurnCalories = 0;
  291. let totalsportDate = 0;
  292. allList.forEach(item => {
  293. totalSteps += Number(item.steps) || 0; // 确保为数字类型,避免 NaN
  294. totalDistance += Number(item.distance) || 0; // 确保为数字类型,避免 NaN
  295. totalBurnCalories += Number(item.burnCalories) || 0; // 确保为数字类型,避免 NaN
  296. totalsportDate += Number(item.sportDate) || 0;
  297. });
  298. // 将总运动时间转换为天、小时、分钟
  299. const days = Math.floor(totalsportDate / (60 * 24)); // 转换为天数
  300. const hours = Math.floor((totalsportDate % (60 * 24)) / 60); // 剩余小时
  301. const minutes = totalsportDate % 60; // 剩余分钟
  302. // 设置 stardate 和 daysDifference
  303. this.setData({
  304. stardate: formattedDate,
  305. daysDifference: daysDifference,
  306. totalSteps,
  307. totalDistance,
  308. totalBurnCalories,
  309. totalsportDate: `${days}天 ${hours}小时 ${minutes}分钟` // 格式化为字符串
  310. });
  311. console.log(allList, this.data.totalsportDate);
  312. },
  313. //修改光圈
  314. getBackgroundColor() {
  315. const steps = this.data.sharList[0].steps || 0;
  316. let percent = (steps / this.data.target) * 100;
  317. console.log('目标', percent);
  318. if (percent > 100) {
  319. percent = 100;
  320. }
  321. // 保留两位小数
  322. percent = parseFloat(percent.toFixed(2));
  323. this.setData({
  324. percent,
  325. percentage: `conic-gradient(from 0deg, #015EEA ${percent}%, white 0%)`,
  326. })
  327. console.log('百分比', this.data.percentage);
  328. },
  329. //获取本周记录
  330. async getweekday() {
  331. const currentUser = Parse.User.current();
  332. let ActivityDataquery = new Parse.Query('ActivityData');
  333. ActivityDataquery.equalTo('user', currentUser.id);
  334. ActivityDataquery.equalTo('company', company);
  335. ActivityDataquery.equalTo('type', 'today');
  336. ActivityDataquery.notEqualTo('isDeleted', true);
  337. let r = await ActivityDataquery.find();
  338. let allList = r.map(item => item.toJSON());
  339. // 按时间降序排序(从现在到以前)
  340. allList.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt));
  341. // 获取今天是星期几(0 = 周日, 1 = 周一, ..., 6 = 周六)
  342. const today = new Date();
  343. const dayOfWeek = today.getDay(); // 获取当前星期几
  344. // 根据星期几决定取多少条数据
  345. let numItemsToTake;
  346. if (dayOfWeek === 0) {
  347. numItemsToTake = 7; // 周日取7条数据
  348. } else {
  349. numItemsToTake = dayOfWeek; // 周一至周六取对应条数
  350. }
  351. // 取出对应数量的数据
  352. const resultList = allList.slice(0, numItemsToTake);
  353. const stepsData = resultList.map((item, index) => {
  354. if (index === 0) {
  355. // 如果是第一条数据,设置特殊样式
  356. return {
  357. value: item.steps,
  358. itemStyle: {
  359. color: '#a90000',
  360. }
  361. };
  362. } else {
  363. // 其他数据直接返回 steps
  364. return item.steps;
  365. }
  366. });
  367. stepsData.reverse()
  368. //总计,平均
  369. let totle = 0
  370. for (let i = 0; i < resultList.length; i++) {
  371. totle = totle + Number(resultList[i].steps)
  372. }
  373. const average = totle / resultList.length
  374. console.log('totle', totle, average);
  375. this.setData({
  376. resultList,
  377. stepsData,
  378. totle,
  379. average,
  380. })
  381. console.log('resultList', resultList);
  382. },
  383. //获取今日排名百分比
  384. async gettoday() {
  385. const currentUser = Parse.User.current();
  386. let ActivityDataquery = new Parse.Query('ActivityData');
  387. ActivityDataquery.equalTo('company', company);
  388. ActivityDataquery.equalTo('type', "today");
  389. ActivityDataquery.notEqualTo('isDeleted', true);
  390. // 获取今天的日期
  391. const today = new Date();
  392. const todayStart = new Date(today.getFullYear(), today.getMonth(), today.getDate()); // 今天的开始时间
  393. const todayEnd = new Date(todayStart);
  394. todayEnd.setHours(23, 59, 59, 999); // 今天的结束时间
  395. console.log(todayStart, todayEnd);
  396. // 在查询条件中添加对 createdAt 的限制
  397. ActivityDataquery.greaterThanOrEqualTo('createdAt', todayStart);
  398. ActivityDataquery.lessThanOrEqualTo('createdAt', todayEnd);
  399. // 根据 steps 字段进行降序排序
  400. ActivityDataquery.descending('steps');
  401. ActivityDataquery.include('user');
  402. try {
  403. let P = await ActivityDataquery.find();
  404. let todayList = P.map(item => item.toJSON());
  405. console.log('todayList', todayList);
  406. let rank = 0
  407. // 更新页面数据
  408. todayList.forEach((item, index) => {
  409. if (item.user.objectId == currentUser.id) {
  410. rank = index + 1;
  411. return
  412. }
  413. })
  414. var ranper = 100 - (rank / todayList.length) * 100
  415. ranper = parseFloat(ranper.toFixed(2));
  416. this.setData({
  417. percebtage: ranper
  418. })
  419. console.log('percebtage', this.data.percebtage);
  420. } catch (error) {
  421. console.error('Error fetching today\'s data:', error);
  422. }
  423. },
  424. //获取当月第一天日期和最后一天日期
  425. gettodaydate() {
  426. // 获取今天的日期
  427. const today = new Date();
  428. // 获取当月第一天的日期
  429. const startOfMonth = new Date(today.getFullYear(), today.getMonth(), 1).getTime();
  430. // 获取当月最后一天的日期
  431. const endOfMonth = new Date(today.getFullYear(), today.getMonth() + 1, 0).getTime();
  432. this.setData({
  433. minDate:startOfMonth,
  434. maxDate:endOfMonth
  435. })
  436. }
  437. })