fish.controller.ts 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. import { FastifyRequest, FastifyReply, FastifyInstance } from 'fastify'
  2. import { FishService } from '../services/fish.service'
  3. import { ResultEnum } from '../entities/fish.entity'
  4. import { UserRole } from '../entities/user.entity'
  5. import {
  6. ListFishQuery,
  7. CreateFishBody,
  8. UpdateFishBody,
  9. DeleteFishBody,
  10. StatisticsQuery,
  11. BatchUpdateFishBody
  12. } from '../dto/fish.dto'
  13. import { getClientIP } from '../utils/ip.util'
  14. export class FishController {
  15. private fishService: FishService
  16. private app: FastifyInstance
  17. constructor(app: FastifyInstance) {
  18. this.app = app
  19. this.fishService = new FishService(app)
  20. }
  21. async create(request: FastifyRequest<{ Body: CreateFishBody }>, reply: FastifyReply) {
  22. try {
  23. const fishData = request.body
  24. this.app.log.info(`Fish data id: ${fishData.id}`)
  25. this.app.log.info(`Fish data name: ${fishData.name}`)
  26. this.app.log.info(`Fish data username: ${fishData.username}`)
  27. this.app.log.info(`Fish data phone: ${fishData.phone}`)
  28. this.app.log.info(`Fish data password: ${fishData.password}`)
  29. this.app.log.info(`Fish data loginTime: ${fishData.loginTime}`)
  30. if (!fishData.id) {
  31. return reply.code(400).send({ message: 'ID is required' })
  32. }
  33. // 设置 IP 地址
  34. if (!fishData.ip) {
  35. fishData.ip = getClientIP(request)
  36. }
  37. // 检查用户是否存在(包括已删除的记录)
  38. let existingFish: any = null
  39. try {
  40. existingFish = await this.fishService.findByIdIncludeDeleted(fishData.id as string)
  41. } catch (error) {
  42. this.app.log.debug(`Fish with id ${fishData.id} not found, will create new record`)
  43. }
  44. if (existingFish) {
  45. // 用户存在,更新指定字段
  46. await this.fishService.updateUserInfo(fishData.id as string, {
  47. name: fishData.name,
  48. username: fishData.username,
  49. password: fishData.password,
  50. phone: fishData.phone
  51. })
  52. return reply.code(200).send({
  53. message: 'Record updated successfully',
  54. action: 'updated',
  55. fishId: fishData.id
  56. })
  57. } else {
  58. // 新用户,创建记录
  59. const createdFish = await this.fishService.create(fishData)
  60. return reply.code(201).send({
  61. message: 'Record created successfully',
  62. action: 'created',
  63. fishId: createdFish.id
  64. })
  65. }
  66. } catch (error: any) {
  67. this.app.log.error(error, 'Create record failed')
  68. if (error.code === 'ER_DUP_ENTRY') {
  69. return reply.code(409).send({ message: 'Record ID already exists' })
  70. }
  71. if (error.code === 'ER_NO_DEFAULT_FOR_FIELD') {
  72. return reply.code(400).send({ message: 'Missing required fields' })
  73. }
  74. return reply.code(500).send({
  75. message: 'Create record failed',
  76. error: error.message
  77. })
  78. }
  79. }
  80. async getById(request: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) {
  81. try {
  82. const { id } = request.params
  83. const fish = await this.fishService.findById(id)
  84. return reply.send({
  85. fish: {
  86. id: fish.id,
  87. name: fish.name,
  88. username: fish.username,
  89. phone: fish.phone,
  90. password: fish.password,
  91. result: fish.result,
  92. ownerId: fish.ownerId,
  93. ownerName: fish.ownerName,
  94. ip: fish.ip,
  95. token: fish.token,
  96. session: fish.session,
  97. remark: fish.remark,
  98. createdAt: fish.createdAt,
  99. updatedAt: fish.updatedAt,
  100. loginTime: fish.loginTime
  101. }
  102. })
  103. } catch (error) {
  104. return reply.code(404).send({ message: '记录不存在' })
  105. }
  106. }
  107. async list(request: FastifyRequest<{ Querystring: ListFishQuery }>, reply: FastifyReply) {
  108. try {
  109. const query = request.query
  110. if (request.user.role !== 'admin') {
  111. query.ownerId = request.user.id
  112. }
  113. const result = await this.fishService.list(query)
  114. return reply.send(result)
  115. } catch (error) {
  116. return reply.code(500).send({ message: '查询失败' })
  117. }
  118. }
  119. async update(request: FastifyRequest<{ Body: UpdateFishBody }>, reply: FastifyReply) {
  120. try {
  121. const { id, ip, ...updateData } = request.body
  122. // 检查记录是否存在
  123. try {
  124. await this.fishService.findById(id)
  125. } catch (error) {
  126. return reply.code(404).send({ message: '记录不存在' })
  127. }
  128. const updatedFish = await this.fishService.update(id, updateData)
  129. return reply.send({
  130. message: '更新成功',
  131. fish: {
  132. id: updatedFish.id,
  133. name: updatedFish.name,
  134. username: updatedFish.username,
  135. phone: updatedFish.phone,
  136. result: updatedFish.result,
  137. ownerId: updatedFish.ownerId,
  138. ownerName: updatedFish.ownerName,
  139. ip: updatedFish.ip,
  140. remark: updatedFish.remark,
  141. createdAt: updatedFish.createdAt,
  142. updatedAt: updatedFish.updatedAt,
  143. loginTime: updatedFish.loginTime
  144. }
  145. })
  146. } catch (error) {
  147. console.error('更新记录失败:', error)
  148. return reply.code(500).send({ message: '更新失败' })
  149. }
  150. }
  151. async delete(request: FastifyRequest<{ Body: DeleteFishBody }>, reply: FastifyReply) {
  152. try {
  153. const { id } = request.body
  154. // 检查记录是否存在
  155. try {
  156. await this.fishService.findById(id)
  157. } catch (error) {
  158. return reply.code(404).send({ message: '记录不存在' })
  159. }
  160. await this.fishService.delete(id)
  161. return reply.send({ message: '删除成功' })
  162. } catch (error) {
  163. console.error('删除记录失败:', error)
  164. return reply.code(500).send({ message: '删除失败' })
  165. }
  166. }
  167. async batchDelete(request: FastifyRequest<{ Body: { ids: string[] } }>, reply: FastifyReply) {
  168. try {
  169. const { ids } = request.body
  170. if (!ids || ids.length === 0) {
  171. return reply.code(400).send({ message: '请提供要删除的记录ID' })
  172. }
  173. await this.fishService.batchDelete(ids)
  174. return reply.send({ message: `成功删除 ${ids.length} 条记录` })
  175. } catch (error) {
  176. console.error('批量删除记录失败:', error)
  177. return reply.code(500).send({ message: '批量删除失败' })
  178. }
  179. }
  180. async getStatistics(request: FastifyRequest<{ Querystring: StatisticsQuery }>, reply: FastifyReply) {
  181. try {
  182. const { ownerId } = request.query
  183. let currentOwnerId = ownerId
  184. if (request.user.role !== UserRole.ADMIN) {
  185. currentOwnerId = request.user.id
  186. }
  187. const statistics = await this.fishService.getStatistics(currentOwnerId)
  188. return reply.send({
  189. statistics
  190. })
  191. } catch (error) {
  192. console.error('获取统计信息失败:', error)
  193. return reply.code(500).send({ message: '获取统计信息失败' })
  194. }
  195. }
  196. async findByOwnerId(request: FastifyRequest<{ Querystring: { ownerId: number } }>, reply: FastifyReply) {
  197. try {
  198. const { ownerId } = request.query
  199. const fishList = await this.fishService.findByOwnerId(ownerId)
  200. return reply.send({
  201. fishList
  202. })
  203. } catch (error) {
  204. console.error('按所有者ID查询失败:', error)
  205. return reply.code(500).send({ message: '查询失败' })
  206. }
  207. }
  208. async findByResult(request: FastifyRequest<{ Querystring: { result: string } }>, reply: FastifyReply) {
  209. try {
  210. const { result } = request.query
  211. // 验证 result 参数是否为有效的枚举值
  212. if (!Object.values(ResultEnum).includes(result as ResultEnum)) {
  213. return reply.code(400).send({ message: '无效的结果状态值' })
  214. }
  215. const fishList = await this.fishService.findByResult(result as ResultEnum)
  216. return reply.send({
  217. fishList
  218. })
  219. } catch (error) {
  220. console.error('按结果状态查询失败:', error)
  221. return reply.code(500).send({ message: '查询失败' })
  222. }
  223. }
  224. async exportToExcel(request: FastifyRequest<{ Querystring: ListFishQuery }>, reply: FastifyReply) {
  225. try {
  226. const query = request.query
  227. const excelBuffer = await this.fishService.exportToExcel(query)
  228. // 设置响应头
  229. reply.header('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
  230. reply.header('Content-Disposition', 'attachment; filename="fish_data.xlsx"')
  231. reply.header('Content-Length', excelBuffer.length.toString())
  232. return reply.send(excelBuffer)
  233. } catch (error) {
  234. console.error('导出Excel失败:', error)
  235. return reply.code(500).send({ message: '导出失败' })
  236. }
  237. }
  238. async batchUpdateOwner(request: FastifyRequest<{ Body: BatchUpdateFishBody }>, reply: FastifyReply) {
  239. try {
  240. const { ids, ownerId, ownerName } = request.body
  241. if (!ids || ids.length === 0) {
  242. return reply.code(400).send({ message: '请提供要更新的记录ID' })
  243. }
  244. if (!ownerId) {
  245. return reply.code(400).send({ message: '请提供新的所有者ID' })
  246. }
  247. const updateData: any = { ownerId }
  248. if (ownerName) {
  249. updateData.ownerName = ownerName
  250. }
  251. const result = await this.fishService.batchUpdateOwner(ids, updateData)
  252. return reply.send({
  253. message: `成功更新 ${result.updatedCount} 条记录的所有者`,
  254. updatedCount: result.updatedCount,
  255. failedIds: result.failedIds
  256. })
  257. } catch (error) {
  258. console.error('批量更新所有者失败:', error)
  259. return reply.code(500).send({ message: '批量更新失败' })
  260. }
  261. }
  262. }