OcrChannelController.ts 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
  2. import PaginationService from 'App/Services/PaginationService'
  3. import OcrChannel from 'App/Models/OcrChannel'
  4. import { schema } from '@ioc:Adonis/Core/Validator'
  5. import { DateTime } from 'luxon'
  6. import OcrDevice from 'App/Models/OcrDevice'
  7. import OcrRecord from 'App/Models/OcrRecord'
  8. import * as console from 'node:console'
  9. import Database from '@ioc:Adonis/Lucid/Database'
  10. export default class OcrChannelController {
  11. private paginationService = new PaginationService(OcrChannel)
  12. public async index({ request, bouncer }: HttpContextContract) {
  13. return await this.paginationService.paginate(request.all())
  14. }
  15. public async store({ request, bouncer }: HttpContextContract) {
  16. await request.validate({
  17. schema: schema.create({
  18. name: schema.string.optional(),
  19. deviceNum: schema.number(),
  20. recordNum: schema.number(),
  21. scanNum: schema.number()
  22. })
  23. })
  24. const ocrChannel = await OcrChannel.create(request.all())
  25. await this.updateChannelStats(ocrChannel)
  26. return ocrChannel
  27. }
  28. public async show({ params, bouncer }: HttpContextContract) {
  29. await bouncer.authorize('admin')
  30. return await OcrChannel.findOrFail(params.id)
  31. }
  32. public async update({ params, request, bouncer }: HttpContextContract) {
  33. await bouncer.authorize('admin')
  34. const ocrChannel = await OcrChannel.findOrFail(params.id)
  35. const data = await request.validate({
  36. schema: schema.create({
  37. name: schema.string.optional(),
  38. deviceNum: schema.number.optional(),
  39. recordNum: schema.number.optional(),
  40. scanNum: schema.number.optional()
  41. })
  42. })
  43. return await ocrChannel.merge(data).save()
  44. }
  45. public async findApiChannel({ auth, response }: HttpContextContract) {
  46. if (!auth.user) {
  47. return response.unauthorized({ message: 'unauthorized' })
  48. }
  49. return await OcrChannel.findBy('name', auth.user.username)
  50. }
  51. public async plusDeviceNum({ request, response }: HttpContextContract) {
  52. try {
  53. const ocrChannel = await OcrChannel.findBy('id', request.param('id'))
  54. if (!ocrChannel) {
  55. return response.notFound({ message: `未找到ID为 ${request.param('id')} 的OCR渠道` })
  56. }
  57. ocrChannel.deviceNum += 1
  58. await ocrChannel.save()
  59. return ocrChannel
  60. } catch (error) {
  61. return response.internalServerError({
  62. message: '更新设备数量时发生错误',
  63. error: error.message
  64. })
  65. }
  66. }
  67. public async plusRecordNum({ request, response }: HttpContextContract) {
  68. try {
  69. const ocrChannel = await OcrChannel.findBy('id', request.param('id'))
  70. if (!ocrChannel) {
  71. return response.notFound({ message: `未找到ID为 ${request.param('id')} 的OCR渠道` })
  72. }
  73. ocrChannel.recordNum += 1
  74. await ocrChannel.save()
  75. return ocrChannel
  76. } catch (error) {
  77. return response.internalServerError({
  78. message: '更新记录数量时发生错误',
  79. error: error.message
  80. })
  81. }
  82. }
  83. public async plusScanNum({ request, response }: HttpContextContract) {
  84. const scanCount = Number(request.param('scanCount'))
  85. if (isNaN(scanCount)) {
  86. return response.badRequest({ message: 'scanCount 参数必须是有效数字' })
  87. }
  88. try {
  89. const ocrChannel = await OcrChannel.findBy('id', request.param('id'))
  90. if (!ocrChannel) {
  91. return response.notFound({
  92. message: `未找到 ID 为 ${request.param('id')} 的 OCR 渠道`
  93. })
  94. }
  95. ocrChannel.scanNum = (Number(ocrChannel.scanNum) || 0) + scanCount
  96. await ocrChannel.save()
  97. return response.ok(ocrChannel)
  98. } catch (error) {
  99. return response.internalServerError({
  100. message: '更新扫描数量时发生错误',
  101. error: error.message
  102. })
  103. }
  104. }
  105. public async getStatistics({ request, response }: HttpContextContract) {
  106. try {
  107. const name = request.input('name')
  108. let query = Database.from('ocr_channels')
  109. if (name) {
  110. query = query.where('name', name)
  111. }
  112. const sevenDaysAgo = DateTime.now().minus({ days: 7 }).startOf('day').toSQL()
  113. const data = await query
  114. .where('created_at', '>=', sevenDaysAgo)
  115. .orderBy('created_at', 'asc')
  116. .select(
  117. 'created_at',
  118. 'device_num as deviceNum',
  119. 'record_num as recordNum',
  120. 'scan_num as scanNum'
  121. )
  122. const result = {
  123. dates: data.map((item) => DateTime.fromISO(item.created_at).toFormat('yyyy-MM-dd')),
  124. deviceNum: data.map((item) => item.deviceNum),
  125. recordNum: data.map((item) => item.recordNum),
  126. scanNum: data.map((item) => item.scanNum)
  127. }
  128. return response.ok(result)
  129. } catch (error) {
  130. return response.internalServerError({
  131. message: '获取统计数据时发生错误',
  132. error: error.message
  133. })
  134. }
  135. }
  136. public async getChannelNames({ auth, response }: HttpContextContract) {
  137. try {
  138. const user = auth.user
  139. const role = user?.$attributes?.role
  140. // 验证管理员或操作员权限
  141. if (role !== 'admin' && role !== 'operator') {
  142. return response.forbidden({
  143. message: 'unauthorized'
  144. })
  145. }
  146. // 获取所有渠道名称
  147. const channels = await OcrChannel.query().select('name').orderBy('name', 'asc')
  148. return response.ok({
  149. data: channels.map((channel) => channel.name)
  150. })
  151. } catch (error) {
  152. return response.internalServerError({
  153. message: '获取渠道名称列表时发生错误',
  154. error: error.message
  155. })
  156. }
  157. }
  158. private async updateChannelStats(channel: OcrChannel) {
  159. // 获取设备数量
  160. const deviceCountResult = await Database.from('ocr_devices')
  161. .where('channel', channel.name)
  162. .count('* as total')
  163. // 获取记录数量
  164. const recordCountResult = await Database.from('ocr_records')
  165. .where('channel', channel.name)
  166. .count('* as total')
  167. // 获取扫描数量总和
  168. const scanSumResult = await Database.from('ocr_devices')
  169. .where('channel', channel.name)
  170. .sum('scanned as total')
  171. // 更新渠道数据
  172. channel.deviceNum = parseInt(deviceCountResult[0].total || '0', 10)
  173. channel.recordNum = parseInt(recordCountResult[0].total || '0', 10)
  174. channel.scanNum = parseInt(scanSumResult[0].total || '0', 10)
  175. await channel.save()
  176. return {
  177. id: channel.id,
  178. name: channel.name,
  179. deviceNum: channel.deviceNum,
  180. recordNum: channel.recordNum,
  181. scanNum: channel.scanNum
  182. }
  183. }
  184. public async updateStatistics({ response }: HttpContextContract) {
  185. try {
  186. // 获取所有渠道
  187. const channels = await OcrChannel.all()
  188. const results = await Promise.all(
  189. channels.map((channel) => this.updateChannelStats(channel))
  190. )
  191. return response.ok({
  192. message: '所有渠道统计数据已更新',
  193. data: results
  194. })
  195. } catch (error) {
  196. return response.internalServerError({
  197. message: '更新所有渠道统计数据时发生错误',
  198. error: error.message
  199. })
  200. }
  201. }
  202. }