SendCount.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. const API = require("../../lib/API")
  2. const db = require("../../plugin/DataBase/db")
  3. const AccessControl = require("../../lib/AccessControl")
  4. const { BaseStdResponse } = require("../../BaseStdResponse")
  5. const EmailTemplate = require("../../plugin/Email/emailTemplate")
  6. class SendCount extends API {
  7. constructor() {
  8. super()
  9. this.setPath("/Goods/SendCount")
  10. this.setMethod("POST")
  11. }
  12. async onRequest(req, res) {
  13. let { uuid, session, username, count } = req.body
  14. username = typeof username === "string" ? username.trim() : username
  15. count = Number(count)
  16. if ([uuid, session, username, count].some(v => v == null || v === "" || Number.isNaN(count)))
  17. return res.json({ ...BaseStdResponse.MISSING_PARAMETER })
  18. if (!Number.isInteger(count) || count < 1 || count > 9999)
  19. return res.json({ ...BaseStdResponse.ERR, msg: "超出赠送的次数范围,请重新选择赠送次数" })
  20. if (!(await AccessControl.checkSession(uuid, session)))
  21. return res.status(401).json({ ...BaseStdResponse.ACCESS_DENIED })
  22. const conn = await db.connect() // 这里直接拿 connection
  23. try {
  24. await conn.beginTransaction()
  25. const [senderRows] = await conn.execute(
  26. "SELECT id, username, lepao_count FROM users WHERE uuid = ?",
  27. [uuid]
  28. )
  29. if (!senderRows || senderRows.length !== 1) {
  30. await conn.rollback()
  31. return res.json({ ...BaseStdResponse.MISSING_FILE, msg: "获取用户信息失败!" })
  32. }
  33. const [targetRows] = await conn.execute(
  34. "SELECT id, uuid FROM users WHERE username = ?",
  35. [username]
  36. )
  37. if (!targetRows || targetRows.length !== 1) {
  38. await conn.rollback()
  39. return res.json({ ...BaseStdResponse.ERR, msg: "未找到接收用户,请检查用户名是否正确!" })
  40. }
  41. if (targetRows[0].uuid === uuid) {
  42. await conn.rollback()
  43. return res.json({ ...BaseStdResponse.ERR, msg: "不能给自己赠送次数!" })
  44. }
  45. const [decResult] = await conn.execute(
  46. "UPDATE users SET lepao_count = lepao_count - ? WHERE uuid = ? AND lepao_count >= ?",
  47. [count, uuid, count]
  48. )
  49. if (decResult.affectedRows !== 1) {
  50. await conn.rollback()
  51. return res.json({ ...BaseStdResponse.ERR, msg: "剩余乐跑次数不足,请购买后再赠送!" })
  52. }
  53. const [insertResult] = await conn.execute(
  54. `INSERT INTO lepao_send_count_request
  55. (sender_uuid, receiver_user_id, count, status, created_at)
  56. VALUES (?, ?, ?, 'pending', NOW())`,
  57. [uuid, targetRows[0].id, count]
  58. )
  59. if (!insertResult || insertResult.affectedRows !== 1) {
  60. await conn.rollback()
  61. return res.json({ ...BaseStdResponse.ERR, msg: "提交赠送审核失败,请稍后再试!" })
  62. }
  63. await conn.commit()
  64. const requestId = insertResult.insertId
  65. const createTime = new Date().getTime()
  66. // 非阻塞通知管理员,不影响主业务流程
  67. Promise.resolve().then(async () => {
  68. try {
  69. const adminSql = `
  70. SELECT email
  71. FROM users
  72. WHERE email IS NOT NULL
  73. AND email <> ''
  74. AND (JSON_CONTAINS(permission, '"admin"') OR JSON_CONTAINS(permission, '"service"'))
  75. `
  76. const adminRows = await db.query(adminSql)
  77. if (!adminRows || adminRows.length === 0) {
  78. this.logger.warn(`[SendCountNotify][submit][requestId=${requestId}] 未找到可通知的管理员邮箱`)
  79. return
  80. }
  81. const emails = [...new Set(adminRows.map(row => row.email).filter(Boolean))]
  82. for (const email of emails) {
  83. await EmailTemplate.sendCountRequestNotifyAdmins(email, {
  84. requestId,
  85. senderUsername: senderRows[0].username,
  86. receiverUsername: username,
  87. count,
  88. createTime
  89. })
  90. }
  91. } catch (mailErr) {
  92. this.logger.error(`[SendCountNotify][submit][requestId=${requestId}] 管理员通知发送失败:${mailErr.message || "未知错误"}`)
  93. }
  94. })
  95. return res.json({ ...BaseStdResponse.OK, msg: "已提交审核,审核通过后接收方将到账" })
  96. } catch (err) {
  97. try { await conn.rollback() } catch (_) { }
  98. this.logger.error(`赠送乐跑次数失败!${err.message || "未知错误"}`)
  99. return res.json({
  100. ...BaseStdResponse.ERR,
  101. msg: `赠送次数失败,请稍后再试!`
  102. })
  103. }
  104. }
  105. }
  106. module.exports.SendCount = SendCount