|
|
@@ -3,6 +3,7 @@ import PaginationService from 'App/Services/PaginationService'
|
|
|
import { schema } from '@ioc:Adonis/Core/Validator'
|
|
|
import OcrDevice from 'App/Models/OcrDevice'
|
|
|
import OcrChannel from 'App/Models/OcrChannel'
|
|
|
+import { DateTime } from 'luxon'
|
|
|
|
|
|
export default class OcrDevicesController {
|
|
|
private paginationService = new PaginationService(OcrDevice)
|
|
|
@@ -91,4 +92,118 @@ export default class OcrDevicesController {
|
|
|
})
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ public async getStatistics({ request, response, auth }: HttpContextContract) {
|
|
|
+ try {
|
|
|
+ const user = auth.user
|
|
|
+ const isApiUser = user?.$attributes?.role === 'api'
|
|
|
+ const query = OcrDevice.query()
|
|
|
+
|
|
|
+ // 如果是 API 用户,强制使用其 username 作为 channel
|
|
|
+ if (isApiUser) {
|
|
|
+ query.where('channel', user.username)
|
|
|
+ } else {
|
|
|
+ // 如果不是 API 用户,则使用请求中的 channel 参数
|
|
|
+ const channel = request.input('channel')
|
|
|
+ if (channel) {
|
|
|
+ query.where('channel', channel)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取近7天的数据
|
|
|
+ const sevenDaysAgo = DateTime.now().minus({ days: 7 }).startOf('day').toSQL()
|
|
|
+ const data = await query
|
|
|
+ .where('createdAt', '>=', sevenDaysAgo)
|
|
|
+ .orderBy('createdAt', 'asc')
|
|
|
+ .select('createdAt', 'total', 'scanned')
|
|
|
+
|
|
|
+ // 按日期分组并计算每天的总数
|
|
|
+ const dailyStats = data.reduce(
|
|
|
+ (acc, item) => {
|
|
|
+ const date = item.createdAt.toFormat('yyyy-MM-dd')
|
|
|
+ if (!acc[date]) {
|
|
|
+ acc[date] = {
|
|
|
+ total: 0,
|
|
|
+ scanned: 0,
|
|
|
+ deviceCount: 0
|
|
|
+ }
|
|
|
+ }
|
|
|
+ acc[date].total += item.total
|
|
|
+ acc[date].scanned += item.scanned
|
|
|
+ acc[date].deviceCount += 1
|
|
|
+ return acc
|
|
|
+ },
|
|
|
+ {} as Record<string, { total: number; scanned: number; deviceCount: number }>
|
|
|
+ )
|
|
|
+
|
|
|
+ // 确保所有日期都有数据,没有数据的日期填充0
|
|
|
+ const dates: string[] = []
|
|
|
+ const totals: number[] = []
|
|
|
+ const scanned: number[] = []
|
|
|
+ const deviceCounts: number[] = []
|
|
|
+ for (let i = 0; i < 7; i++) {
|
|
|
+ const date = DateTime.now().minus({ days: i }).toFormat('yyyy-MM-dd')
|
|
|
+ dates.unshift(date)
|
|
|
+ totals.unshift(dailyStats[date]?.total || 0)
|
|
|
+ scanned.unshift(dailyStats[date]?.scanned || 0)
|
|
|
+ deviceCounts.unshift(dailyStats[date]?.deviceCount || 0)
|
|
|
+ }
|
|
|
+
|
|
|
+ return response.ok({
|
|
|
+ dates,
|
|
|
+ total: totals,
|
|
|
+ scanned: scanned,
|
|
|
+ deviceCount: deviceCounts
|
|
|
+ })
|
|
|
+ } catch (error) {
|
|
|
+ return response.internalServerError({
|
|
|
+ message: '获取设备统计数据时发生错误',
|
|
|
+ error: error.message
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public async getTodayStatistics({ request, response, auth }: HttpContextContract) {
|
|
|
+ try {
|
|
|
+ const user = auth.user
|
|
|
+ const isApiUser = user?.$attributes?.role === 'api'
|
|
|
+ const query = OcrDevice.query()
|
|
|
+
|
|
|
+ // 如果是 API 用户,强制使用其 username 作为 channel
|
|
|
+ if (isApiUser) {
|
|
|
+ query.where('channel', user.username)
|
|
|
+ } else {
|
|
|
+ // 如果不是 API 用户,则使用请求中的 channel 参数
|
|
|
+ const channel = request.input('channel')
|
|
|
+ if (channel) {
|
|
|
+ query.where('channel', channel)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取今天的数据
|
|
|
+ const today = DateTime.now().startOf('day').toSQL()
|
|
|
+ const data = await query.where('createdAt', '>=', today).select('total', 'scanned')
|
|
|
+
|
|
|
+ // 计算今日统计数据
|
|
|
+ const stats = data.reduce(
|
|
|
+ (acc, item) => {
|
|
|
+ acc.total += item.total
|
|
|
+ acc.scanned += item.scanned
|
|
|
+ acc.deviceCount += 1
|
|
|
+ return acc
|
|
|
+ },
|
|
|
+ { total: 0, scanned: 0, deviceCount: 0 }
|
|
|
+ )
|
|
|
+
|
|
|
+ return response.ok({
|
|
|
+ date: DateTime.now().toFormat('yyyy-MM-dd'),
|
|
|
+ ...stats
|
|
|
+ })
|
|
|
+ } catch (error) {
|
|
|
+ return response.internalServerError({
|
|
|
+ message: '获取今日统计数据时发生错误',
|
|
|
+ error: error.message
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|