|
|
@@ -140,33 +140,126 @@ export class FishService {
|
|
|
return this.fishRepository.count({ where: { ownerId } })
|
|
|
}
|
|
|
|
|
|
- async getStatistics(): Promise<{
|
|
|
+ async getStatistics(ownerId?: number): Promise<{
|
|
|
total: number
|
|
|
noTag: number
|
|
|
tagged: number
|
|
|
success: number
|
|
|
+ dailyStats: Array<{
|
|
|
+ date: string
|
|
|
+ newCount: number
|
|
|
+ taggedCount: number
|
|
|
+ untaggedCount: number
|
|
|
+ }>
|
|
|
}> {
|
|
|
- const [total, noTag, tagged, success] = await Promise.all([
|
|
|
- this.fishRepository.count(),
|
|
|
- this.countByResult(ResultEnum.NoTag),
|
|
|
- this.countByResult(ResultEnum.Tagged),
|
|
|
- this.countByResult(ResultEnum.Success)
|
|
|
+ const days = 7
|
|
|
+ const today = new Date()
|
|
|
+ today.setHours(23, 59, 59, 999)
|
|
|
+
|
|
|
+ const startDate = new Date()
|
|
|
+ startDate.setDate(startDate.getDate() - 6)
|
|
|
+ startDate.setHours(0, 0, 0, 0)
|
|
|
+
|
|
|
+ // 提取日期格式化函数
|
|
|
+ const formatDate = (date: Date): string => {
|
|
|
+ const year = date.getFullYear()
|
|
|
+ const month = String(date.getMonth() + 1).padStart(2, '0')
|
|
|
+ const day = String(date.getDate()).padStart(2, '0')
|
|
|
+ return `${year}-${month}-${day}`
|
|
|
+ }
|
|
|
+
|
|
|
+ // 构建查询条件 - 统一处理
|
|
|
+ const buildWhereClause = (includeTimeRange = false) => {
|
|
|
+ const conditions: string[] = []
|
|
|
+ const parameters: any = {}
|
|
|
+
|
|
|
+ if (ownerId) {
|
|
|
+ conditions.push('fish.ownerId = :ownerId')
|
|
|
+ parameters.ownerId = ownerId
|
|
|
+ }
|
|
|
+
|
|
|
+ if (includeTimeRange) {
|
|
|
+ conditions.push('fish.createdAt >= :startDate', 'fish.createdAt <= :today')
|
|
|
+ parameters.startDate = startDate
|
|
|
+ parameters.today = today
|
|
|
+ }
|
|
|
+
|
|
|
+ return {
|
|
|
+ whereClause: conditions.length ? conditions.join(' AND ') : '1=1',
|
|
|
+ parameters
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ const baseQuery = this.fishRepository.createQueryBuilder('fish')
|
|
|
+
|
|
|
+ const [totalStats, recentData] = await Promise.all([
|
|
|
+ // 总体统计
|
|
|
+ (() => {
|
|
|
+ const { whereClause, parameters } = buildWhereClause()
|
|
|
+ return baseQuery
|
|
|
+ .clone()
|
|
|
+ .where(whereClause, parameters)
|
|
|
+ .select([
|
|
|
+ 'COUNT(*) as total',
|
|
|
+ `SUM(CASE WHEN fish.result = '${ResultEnum.NoTag}' THEN 1 ELSE 0 END) as noTag`,
|
|
|
+ `SUM(CASE WHEN fish.result = '${ResultEnum.Tagged}' THEN 1 ELSE 0 END) as tagged`,
|
|
|
+ `SUM(CASE WHEN fish.result = '${ResultEnum.Success}' THEN 1 ELSE 0 END) as success`
|
|
|
+ ])
|
|
|
+ .getRawOne()
|
|
|
+ })(),
|
|
|
+
|
|
|
+ // 最近7天详细数据
|
|
|
+ (() => {
|
|
|
+ const { whereClause, parameters } = buildWhereClause(true)
|
|
|
+ return baseQuery.clone().where(whereClause, parameters).select(['fish.createdAt', 'fish.result']).getMany()
|
|
|
+ })()
|
|
|
])
|
|
|
+
|
|
|
+ const dateRange = Array.from({ length: days }, (_, i) => {
|
|
|
+ const date = new Date(startDate)
|
|
|
+ date.setDate(startDate.getDate() + i)
|
|
|
+ return formatDate(date)
|
|
|
+ })
|
|
|
+
|
|
|
+ const dailyStatsMap = new Map(dateRange.map(date => [date, { newCount: 0, taggedCount: 0, untaggedCount: 0 }]))
|
|
|
+
|
|
|
+ recentData.forEach(item => {
|
|
|
+ const dateKey = formatDate(new Date(item.createdAt))
|
|
|
+ const stats = dailyStatsMap.get(dateKey)
|
|
|
+
|
|
|
+ if (stats) {
|
|
|
+ stats.newCount++
|
|
|
+ switch (item.result) {
|
|
|
+ case ResultEnum.Tagged:
|
|
|
+ stats.taggedCount++
|
|
|
+ break
|
|
|
+ case ResultEnum.NoTag:
|
|
|
+ stats.untaggedCount++
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ const dailyStats = dateRange.map(date => ({
|
|
|
+ date,
|
|
|
+ ...dailyStatsMap.get(date)!
|
|
|
+ }))
|
|
|
|
|
|
return {
|
|
|
- total,
|
|
|
- noTag,
|
|
|
- tagged,
|
|
|
- success
|
|
|
+ total: parseInt(totalStats.total),
|
|
|
+ noTag: parseInt(totalStats.noTag),
|
|
|
+ tagged: parseInt(totalStats.tagged),
|
|
|
+ success: parseInt(totalStats.success),
|
|
|
+ dailyStats
|
|
|
}
|
|
|
}
|
|
|
|
|
|
async exportToExcel(query?: ListFishQuery): Promise<Buffer> {
|
|
|
const whereConditions: any = {}
|
|
|
-
|
|
|
+
|
|
|
if (query) {
|
|
|
const { id, name, username, phone, result, ownerName, remark, createdAt, loginTime } = query
|
|
|
-
|
|
|
+
|
|
|
if (id) {
|
|
|
whereConditions.id = id
|
|
|
}
|
|
|
@@ -248,10 +341,10 @@ export class FishService {
|
|
|
{ wch: 20 }
|
|
|
]
|
|
|
worksheet['!cols'] = colWidths
|
|
|
-
|
|
|
+
|
|
|
XLSX.utils.book_append_sheet(workbook, worksheet, 'Fish数据')
|
|
|
const excelBuffer = XLSX.write(workbook, { type: 'buffer', bookType: 'xlsx' })
|
|
|
-
|
|
|
+
|
|
|
return excelBuffer
|
|
|
}
|
|
|
}
|