import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' import PaginationService from 'App/Services/PaginationService' import OcrChannel from 'App/Models/OcrChannel' import { schema } from '@ioc:Adonis/Core/Validator' import { DateTime } from 'luxon' import Database from '@ioc:Adonis/Lucid/Database' import User, { UserRoles } from 'App/Models/User' import UserService from 'App/Services/UserService' import * as console from 'node:console' export default class OcrChannelController { private paginationService = new PaginationService(OcrChannel) public async index({ request, response, auth }: HttpContextContract) { try { const { page = 1, size = 20, id, deviceId, channel } = request.qs() const user = auth.user const role = user?.$attributes?.role if (!role) { return response.forbidden({ error: 'Forbidden', message: 'Unauthorized access' }) } let userChannel: string | undefined if (role === UserRoles.Api) { userChannel = user!.username } else if (['admin', 'operator'].includes(role)) { const apiUsers = await UserService.findReferredUsers(user!.id) const allowedChannels = apiUsers.map((user) => user.username as string) // 如果请求中指定了channel,检查是否在允许的channel列表中 if (channel) { if (!allowedChannels.includes(channel)) { return response.ok({ data: [], meta: { total: 0, per_page: Number(size), current_page: Number(page), last_page: 0, first_page: 1, first_page_url: '/?page=1', last_page_url: '/?page=0', next_page_url: null, previous_page_url: null } }) } userChannel = channel } else { userChannel = allowedChannels.join(',') } } else { return response.forbidden({ error: 'Forbidden', message: 'You are not authorized to access this resource' }) } // 构建查询条件 const query = OcrChannel.query() if (id) { query.where('id', id) } if (deviceId) { query.whereIn('name', function (builder) { builder.select('channel').from('ocr_devices').where('id', deviceId) }) } if (userChannel) { query.whereIn('name', userChannel.split(',')) } // 执行分页查询 const result = await query.orderBy('created_at', 'desc').paginate(page, size) return response.ok(result) } catch (error) { return response.internalServerError({ message: '获取OCR渠道列表时发生错误', error: error.message }) } } public async store({ request, bouncer }: HttpContextContract) { await request.validate({ schema: schema.create({ name: schema.string.optional(), deviceNum: schema.number(), recordNum: schema.number(), scanNum: schema.number() }) }) const ocrChannel = await OcrChannel.create(request.all()) await this.updateChannelStats(ocrChannel) return ocrChannel } public async show({ params, bouncer }: HttpContextContract) { await bouncer.authorize('admin') return await OcrChannel.findOrFail(params.id) } public async update({ params, request, bouncer }: HttpContextContract) { await bouncer.authorize('admin') const ocrChannel = await OcrChannel.findOrFail(params.id) const data = await request.validate({ schema: schema.create({ name: schema.string.optional(), deviceNum: schema.number.optional(), recordNum: schema.number.optional(), scanNum: schema.number.optional() }) }) return await ocrChannel.merge(data).save() } public async findApiChannel({ auth, response }: HttpContextContract) { if (!auth.user) { return response.unauthorized({ message: 'unauthorized' }) } return await OcrChannel.findBy('name', auth.user.username) } public async plusDeviceNum({ request, response }: HttpContextContract) { try { const ocrChannel = await OcrChannel.findBy('id', request.param('id')) if (!ocrChannel) { return response.notFound({ message: `未找到ID为 ${request.param('id')} 的OCR渠道` }) } ocrChannel.deviceNum += 1 await ocrChannel.save() return ocrChannel } catch (error) { return response.internalServerError({ message: '更新设备数量时发生错误', error: error.message }) } } public async plusRecordNum({ request, response }: HttpContextContract) { try { const ocrChannel = await OcrChannel.findBy('id', request.param('id')) if (!ocrChannel) { return response.notFound({ message: `未找到ID为 ${request.param('id')} 的OCR渠道` }) } ocrChannel.recordNum += 1 await ocrChannel.save() return ocrChannel } catch (error) { return response.internalServerError({ message: '更新记录数量时发生错误', error: error.message }) } } public async plusScanNum({ request, response }: HttpContextContract) { const scanCount = Number(request.param('scanCount')) if (isNaN(scanCount)) { return response.badRequest({ message: 'scanCount 参数必须是有效数字' }) } try { const ocrChannel = await OcrChannel.findBy('id', request.param('id')) if (!ocrChannel) { return response.notFound({ message: `未找到 ID 为 ${request.param('id')} 的 OCR 渠道` }) } ocrChannel.scanNum = (Number(ocrChannel.scanNum) || 0) + scanCount await ocrChannel.save() return response.ok(ocrChannel) } catch (error) { return response.internalServerError({ message: '更新扫描数量时发生错误', error: error.message }) } } public async getStatistics({ request, response }: HttpContextContract) { try { const name = request.input('name') let query = Database.from('ocr_channels') if (name) { query = query.where('name', name) } const sevenDaysAgo = DateTime.now().minus({ days: 7 }).startOf('day').toSQL() const data = await query .where('created_at', '>=', sevenDaysAgo) .orderBy('created_at', 'asc') .select( 'created_at', 'device_num as deviceNum', 'record_num as recordNum', 'scan_num as scanNum' ) const result = { dates: data.map((item) => DateTime.fromISO(item.created_at).toFormat('yyyy-MM-dd')), deviceNum: data.map((item) => item.deviceNum), recordNum: data.map((item) => item.recordNum), scanNum: data.map((item) => item.scanNum) } return response.ok(result) } catch (error) { return response.internalServerError({ message: '获取统计数据时发生错误', error: error.message }) } } public async getChannelNames({ auth, response }: HttpContextContract) { try { const user = auth.user const role = user?.$attributes?.role if (!role) { return response.forbidden({ error: 'Forbidden', message: 'Unauthorized access' }) } let channel: string = '' if (['admin', 'operator'].includes(role)) { const apiUsers = await UserService.findReferredUsers(user!.id) const allowedChannels = apiUsers.map((user) => user.username as string) channel = allowedChannels.join(',') } else { return response.forbidden({ error: 'Forbidden', message: 'You are not authorized to access this resource' }) } // 获取指定渠道名称 const channels = await OcrChannel.query() .select('name') .whereIn('name', channel.split(',')) .orderBy('name', 'asc') return response.ok({ data: channels.map((channel) => channel.name) }) } catch (error) { return response.internalServerError({ message: '获取渠道名称列表时发生错误', error: error.message }) } } private async updateChannelStats(channel: OcrChannel) { // 获取设备数量 const deviceCountResult = await Database.from('ocr_devices') .where('channel', channel.name) .count('* as total') // 获取记录数量 const recordCountResult = await Database.from('ocr_records') .where('channel', channel.name) .count('* as total') // 获取扫描数量总和 const scanSumResult = await Database.from('ocr_devices') .where('channel', channel.name) .sum('scanned as total') // 更新渠道数据 channel.deviceNum = parseInt(deviceCountResult[0].total || '0', 10) channel.recordNum = parseInt(recordCountResult[0].total || '0', 10) channel.scanNum = parseInt(scanSumResult[0].total || '0', 10) await channel.save() return { id: channel.id, name: channel.name, deviceNum: channel.deviceNum, recordNum: channel.recordNum, scanNum: channel.scanNum } } public async updateStatistics({ response }: HttpContextContract) { try { // 获取所有渠道 const channels = await OcrChannel.all() const results = await Promise.all( channels.map((channel) => this.updateChannelStats(channel)) ) return response.ok({ message: '所有渠道统计数据已更新', data: results }) } catch (error) { return response.internalServerError({ message: '更新所有渠道统计数据时发生错误', error: error.message }) } } public async getChannelOcrLevel({ params, response }: HttpContextContract) { try { const { name } = params if (!name) { return response.ok({ level: 0 }) } const ocrChannel = await OcrChannel.findBy('name', name) if (!ocrChannel) { return response.ok({ level: 0 }) } return response.ok({ level: ocrChannel.ocrLevel }) } catch (error) { return response.ok({ level: 0 }) } } }