import analysisDao from '../dao/analysis-dao'; import orm from '../entity/orm'; import email from '../entity/email'; import { desc, count, eq, and, ne, isNotNull } from 'drizzle-orm'; import { emailConst } from '../const/entity-const'; import kvConst from '../const/kv-const'; import dayjs from 'dayjs'; import { toUtc } from '../utils/date-uitil'; const analysisService = { async echarts(c, params) { if (!this.analysisCacheEnabled(c)) { return await this.queryEcharts(c, params); } const cacheKey = this.echartsCacheKey(params); const cache = await c.env.kv.get(cacheKey, { type: 'json' }); if (cache) { return cache; } return await this.refreshEchartsCacheByKey(c, cacheKey); }, async refreshEchartsCacheByKey(c, cacheKey) { const params = this.echartsParamsByCacheKey(cacheKey); const data = await this.queryEcharts(c, params); await c.env.kv.put(cacheKey, JSON.stringify(data)); return data; }, async refreshEchartsCache(c) { if (!this.analysisCacheEnabled(c)) { return; } const { keys } = await c.env.kv.list({ prefix: kvConst.ANALYSIS_ECHARTS }); await Promise.all(keys.map(key => this.refreshEchartsCacheByKey(c, key.name))); }, async queryEcharts(c, params) { const { timeZone } = params; let utcDate = toUtc().startOf('day'); let localDate = utcDate.tz(timeZone); utcDate = dayjs(utcDate.format('YYYY-MM-DD HH:mm:ss')) localDate = dayjs(localDate.format('YYYY-MM-DD HH:mm:ss')) //获取时差 const diffHours = localDate.diff(utcDate, 'hour',true); const [ numberCount, nameRatio, userDayCountRaw, receiveDayCountRaw, sendDayCountRaw, daySendTotalRaw ] = await Promise.all([ analysisDao.numberCount(c), orm(c) .select({ name: email.name, total: count() }) .from(email) .where(and(eq(email.type, emailConst.type.RECEIVE), isNotNull(email.name),ne(email.name,'noreply'), ne(email.name,''))) .groupBy(email.name) .orderBy(desc(count())) .limit(6), analysisDao.userDayCount(c, diffHours), analysisDao.receiveDayCount(c, diffHours), analysisDao.sendDayCount(c, diffHours), c.env.kv.get(kvConst.SEND_DAY_COUNT + dayjs().format('YYYY-MM-DD')), ]); const userDayCount = this.filterEmptyDay(userDayCountRaw, timeZone); const receiveDayCount = this.filterEmptyDay(receiveDayCountRaw, timeZone); const sendDayCount = this.filterEmptyDay(sendDayCountRaw, timeZone); const daySendTotal = daySendTotalRaw || 0; return { numberCount, userDayCount, receiveRatio: { nameRatio }, emailDayCount: { receiveDayCount, sendDayCount }, daySendTotal: Number(daySendTotal) }; }, filterEmptyDay(data, timeZone) { const today = toUtc().tz(timeZone).subtract(1, 'day'); const previousDays = Array.from({ length: 15 }, (_, i) => { return today.subtract(i, 'day').format('YYYY-MM-DD'); }).reverse(); return previousDays.map(day => { const index = data.findIndex(item => item.date === day) const total = index > - 1 ? data[index].total : 0 return {date: day,total} }) }, echartsCacheKey(params = {}) { return kvConst.ANALYSIS_ECHARTS + encodeURIComponent(params.timeZone || 'UTC'); }, echartsParamsByCacheKey(cacheKey) { return { timeZone: decodeURIComponent(cacheKey.replace(kvConst.ANALYSIS_ECHARTS, '')) }; }, analysisCacheEnabled(c) { return c.env.analysis_cache === true || c.env.analysis_cache === 'true'; } } export default analysisService