lepaoWechatTemplate.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. function display(value, fallback = '-') {
  2. if (value === undefined || value === null || value === '') return fallback
  3. return String(value)
  4. }
  5. function formatTime(time = Date.now()) {
  6. return new Date(Number(time) || Date.now()).toLocaleString('zh-CN', {
  7. year: 'numeric',
  8. month: '2-digit',
  9. day: '2-digit',
  10. hour: '2-digit',
  11. minute: '2-digit'
  12. })
  13. }
  14. function formatSecondsToMinSec(totalSeconds) {
  15. const seconds = Number(totalSeconds) || 0
  16. if (seconds <= 0) return '-'
  17. const minutes = Math.floor(seconds / 60)
  18. const remain = Math.floor(seconds % 60)
  19. return `${minutes}分${String(remain).padStart(2, '0')}秒`
  20. }
  21. function calculatePace(seconds, kilometers) {
  22. const totalSeconds = Number(seconds) || 0
  23. const distance = Number(kilometers) || 0
  24. if (totalSeconds <= 0 || distance <= 0) return '-'
  25. const paceInSeconds = totalSeconds / distance
  26. const minutes = Math.floor(paceInSeconds / 60)
  27. const remain = Math.round(paceInSeconds % 60)
  28. return `${minutes}'${String(remain).padStart(2, '0')}''`
  29. }
  30. function divider() {
  31. return '\n---\n'
  32. }
  33. function kv(label, value) {
  34. return `> **${label}**:${display(value)}`
  35. }
  36. function buildUpdateSuccess(data = {}) {
  37. const autoNote = Number(data.auto_run) === 0
  38. ? '当前未开启自动乐跑。如需跑步,请登录 RunForge 后手动发起。'
  39. : '已为您开启自动乐跑,系统将按计划代为完成跑步任务,请留意后续提醒。'
  40. return [
  41. `## ✅ 乐跑账号信息已更新`,
  42. '',
  43. `${display(data.name, '同学')},您的乐跑账号登录信息已更新成功。`,
  44. divider(),
  45. kv('学号', data.account),
  46. kv('年级', data.grade_id),
  47. kv('学院', data.academy_name),
  48. kv('更新时间', formatTime()),
  49. divider(),
  50. `**自动乐跑状态** \n${autoNote}`,
  51. '',
  52. `> 请在当前登录乐跑账号的设备上使用「智慧体育」小程序;请勿在其他设备登录该小程序,以免登录状态失效并需重新绑定。`
  53. ].join('\n')
  54. }
  55. function buildRunSuccess(data = {}) {
  56. const targetCount = Number(data.target_count) || 0
  57. const totalNum = Number(data.total_num) || 0
  58. const timeSec = Number(data.time ?? data.used_time) || 0
  59. const distanceKm = Number(data.distance) || 0
  60. const goalLines = targetCount > 0
  61. ? [kv('目标次数', `${targetCount} 次`), kv('累计次数', `${totalNum} 次`)]
  62. : [kv('累计次数', `${totalNum} 次`)]
  63. return [
  64. `## ✅ 乐跑成功通知`,
  65. '',
  66. `${display(data.name, '同学')},系统已成功代您完成一次乐跑。`,
  67. divider(),
  68. kv('学号', data.account),
  69. kv('跑区', data.pass_tit || data.run_zone_name),
  70. kv('用时', formatSecondsToMinSec(timeSec)),
  71. kv('平均配速', calculatePace(timeSec, distanceKm)),
  72. kv('距离', distanceKm > 0 ? `${distanceKm} km` : '-'),
  73. ...goalLines,
  74. kv('完成时间', formatTime()),
  75. divider(),
  76. `> 若已开启自动乐跑,请勿在除更新乐跑账号信息以外的其他设备登录「智慧体育」小程序,以免登录状态失效。`
  77. ].join('\n')
  78. }
  79. function buildRunFail(data = {}) {
  80. return [
  81. `## ❌ 乐跑未能完成`,
  82. '',
  83. `${display(data.name || data.account, '同学')},系统在尝试执行乐跑任务时未成功。`,
  84. divider(),
  85. kv('学号', data.account),
  86. kv('时间', formatTime()),
  87. kv('原因', data.reason || '系统繁忙,请稍后再试'),
  88. divider(),
  89. `> 若为登录失效,请在 RunForge 乐跑登录器中重新完成登录后再试。若问题持续存在,请联系 RunForge 客服并说明学号与失败时间。`
  90. ].join('\n')
  91. }
  92. function buildTargetComplete(data = {}) {
  93. return [
  94. `## 🏁 乐跑目标已全部完成`,
  95. '',
  96. `${display(data.name || data.account, '同学')},您设定的乐跑目标已全部完成,系统已为您关闭自动乐跑功能。`,
  97. divider(),
  98. kv('学号', data.account),
  99. kv('目标次数', `${display(data.target_count, 0)} 次`),
  100. kv('累计次数', `${display(data.total_num, 0)} 次`),
  101. kv('完成时间', formatTime()),
  102. divider(),
  103. `如仍需跑步,可在 RunForge 中按需重新开启相关功能。`
  104. ].join('\n')
  105. }
  106. module.exports = {
  107. buildUpdateSuccess,
  108. buildRunSuccess,
  109. buildRunFail,
  110. buildTargetComplete
  111. }