StartPowerCheck.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. const API = require("../../lib/API.js")
  2. const db = require('../../plugin/DataBase/db.js')
  3. const { axiosWithQgOutbound } = require('../../lib/Lepao/qgOutboundAxios')
  4. const EmailTemplate = require('../../plugin/Email/emailTemplate')
  5. const { BaseStdResponse } = require("../../BaseStdResponse.js")
  6. class StartPowerCheck extends API {
  7. constructor() {
  8. super()
  9. this.noEncrypt()
  10. this.setPath('/Corn/StartPowerCheck')
  11. this.setMethod('GET')
  12. }
  13. async onRequest(req, res) {
  14. try {
  15. res.json({ ...BaseStdResponse.OK })
  16. this.logger.info('开始执行电费提醒任务')
  17. const sql = 'SELECT id, email, balance, lowest, area, building, room, is_notice FROM power_task'
  18. const tasks = await db.query(sql)
  19. if (!tasks) {
  20. this.logger.error('获取电费提醒任务失败!')
  21. return
  22. }
  23. for (const item of tasks) {
  24. const { id, email, balance, lowest, area, building, room, is_notice } = item
  25. this.logger.info(`${building}-${room} 开始电费查询余额`)
  26. try {
  27. const endpoint = `https://hqpay.ctbu.edu.cn/weixin/ashx/frmuser.ashx?test=lastlist&pid=${room}&dyid=${building}`
  28. const response = await axiosWithQgOutbound({
  29. method: 'get',
  30. url: endpoint,
  31. timeout: 15000,
  32. logger: this.logger,
  33. scene: 'CornPowerCheck'
  34. })
  35. if (!response || !response.data || !response.data[0]) {
  36. this.logger.error('获取电费信息失败!返回数据:' + (response && response.data ? JSON.stringify(response.data) : 'no-response'))
  37. continue
  38. }
  39. const now_balance_raw = response.data[0][1]
  40. const now_change_time = response.data[0][2]
  41. this.logger.info(`${building}-${room} 电费余额:${now_balance_raw},扣费时间:${now_change_time}`)
  42. const time = Date.now()
  43. const nowBalanceNum = parseFloat(String(now_balance_raw).replace(/[^0-9.-]/g, ''))
  44. const balanceNum = parseFloat(String(balance).replace(/[^0-9.-]/g, '')) || 0
  45. const lowestNum = parseFloat(String(lowest).replace(/[^0-9.-]/g, '')) || 0
  46. if (Number.isNaN(nowBalanceNum)) {
  47. this.logger.error(`${building}-${room}:解析当前余额失败,原值:${now_balance_raw}`)
  48. continue
  49. }
  50. // 如果余额未变,跳过当前任务
  51. if (nowBalanceNum === balanceNum) {
  52. continue
  53. }
  54. // 记录变更并更新任务表余额
  55. const insertSql = 'INSERT INTO power_change_record (time, balance, old_balance, change_time, task_id) VALUES (?, ?, ?, ?, ?)'
  56. const insertRows = await db.query(insertSql, [time, nowBalanceNum, balanceNum, now_change_time, id])
  57. const updateSql = 'UPDATE power_task SET update_time = ?, balance = ?, koufei_date = ? WHERE id = ?'
  58. const updateRows = await db.query(updateSql, [time, nowBalanceNum, now_change_time, id])
  59. if (!insertRows || insertRows.affectedRows !== 1 || !updateRows || updateRows.affectedRows !== 1) {
  60. this.logger.error(`${building}-${room}:更新电费信息失败! 数据库错误`)
  61. continue
  62. }
  63. // 余额低于阈值且尚未通知 -> 发邮件并置 is_notice = 1
  64. if (nowBalanceNum < balanceNum && nowBalanceNum <= lowestNum && Number(is_notice) === 0) {
  65. const data = { now_balance: nowBalanceNum, now_change_time, lowest: lowestNum, area, building, room }
  66. try {
  67. await EmailTemplate.powerCheck(email, data)
  68. const upd = await db.query('UPDATE power_task SET is_notice = 1 WHERE id = ?', [id])
  69. if (!upd || upd.affectedRows !== 1) {
  70. this.logger.error(`${building}-${room}:更新 is_notice=1 失败`)
  71. }
  72. } catch (err) {
  73. this.logger.error(`${building}-${room}:发送邮件失败:${err.stack || err}`)
  74. }
  75. }
  76. // 充值后恢复未提醒状态
  77. if (nowBalanceNum > balanceNum && nowBalanceNum > lowestNum) {
  78. const upd = await db.query('UPDATE power_task SET is_notice = 0 WHERE id = ?', [id])
  79. if (!upd || upd.affectedRows !== 1) {
  80. this.logger.error(`${building}-${room}:更新 is_notice=0 失败`)
  81. }
  82. }
  83. } catch (error) {
  84. this.logger.error(`获取电费信息失败!${error.stack || error}`)
  85. continue
  86. }
  87. }
  88. // 删除180天前的记录
  89. const delete_time = new Date().getTime() - 15552000000
  90. let deleteSql = 'DELETE FROM power_change_record WHERE time < ?'
  91. let deleteRows = await db.query(deleteSql, [delete_time])
  92. if (!deleteRows) {
  93. this.logger.error(`删除电费变更记录失败`)
  94. return
  95. }
  96. } catch (error) {
  97. this.logger.error(error)
  98. }
  99. }
  100. }
  101. module.exports.StartPowerCheck = StartPowerCheck