Commit 551fe6bc authored by qinhaitao's avatar qinhaitao

refactor: 💡 数据优化

parent b1a4368f
......@@ -4,7 +4,7 @@ import { USER_DB_NAME, ACCESS_DB_NAME, AWARDS_DB_NAME } from '../db'
import { resultsModel, dateFormatter, transformBeijingDate, BaseDao } from '../sdk'
import { CODE_TYPES } from '../constants'
import * as xlsx from 'node-xlsx'
import { services, registeInfos } from '../decorator/common'
import { checkParams, services } from '../decorator/common'
import { StatService } from '../service'
export interface IGetStatsParams {
......@@ -26,154 +26,21 @@ export default class StatController {
@services([StatService])
async addStat(context: IContext<IAddStatsParams>, { userInfo }: IControllerInfos, [statService]: [StatService]) {
const { type } = context.data
await statService.addStat(type, userInfo)
return resultsModel.success(true)
const result = await statService.addStat(type, userInfo)
return resultsModel.success(result)
}
/**
* 统计数据
*/
async getStats(context: IContext<IGetStatsParams>) {
@checkParams(['activityId', 'startDay', 'endDay'])
@services([StatService])
async getStats(context: IContext<IGetStatsParams>, {}: IControllerInfos, [statService]: [StatService]) {
const { activityId, startDay, endDay } = context.data
const userDao: IBaseDao = new BaseDao(context, USER_DB_NAME)
const accessDao: IBaseDao = new BaseDao(context, ACCESS_DB_NAME)
const oneDay = 24 * 3600 * 1000
const xlsxData = []
try {
let day = startDay
while (new Date(day).getTime() <= new Date(endDay).getTime()) {
// 访问PV
const PV = await accessDao.count({ activityId, createDay: day })
// 访问UV
const UV = (
await accessDao.aggregate([
{ $match: { activityId, createDay: day } },
{ $group: { _id: '$openId', count: { $sum: 1 } } },
{ $count: 'uv' }
])
)?.[0]?.uv
// 新增UV
const newUV = await userDao.count({
activityId,
createDay: day
})
// 已入会(老会员)PV
const vipPV = await accessDao.count({
activityId,
createDay: day,
//@ts-ignore
$or: [{ 'member.flag': true }, { 'member.newMember': true }],
'member.bememberDay': {
$not: {
$eq: day
}
}
})
// 已入会(老会员)UV
const vipUV = (
await accessDao.aggregate(
[
{
$match: {
activityId,
createDay: day,
$or: [{ 'member.flag': true }, { 'member.newMember': true }],
'member.bememberDay': {
$not: {
$eq: day
}
}
}
},
{ $project: { openId: true } },
{ $group: { _id: '$openId', count: { $sum: 1 } } },
{ $count: 'uv' }
],
{ allowDiskUse: true }
)
)?.[0]?.uv
// 未入会PV
const noVipPV = await accessDao.count({ activityId, createDay: day, isVip: false })
// 未入会UV
const noVipUV = (
await accessDao.aggregate([
{ $match: { activityId, createDay: day, isVip: false } },
{ $group: { _id: '$openId', count: { $sum: 1 } } }
])
).length
// 新增入会UV
const newVipUV = await userDao.count({
activityId,
'member.newMember': true,
'member.bememberDay': day
})
const xlsxData = await statService.getStats(activityId, startDay, endDay)
const newFollowUV = await userDao.count({
activityId,
'follow.newFollow': true,
'follow.followDay': day
})
const result = await statService.buildExcel(startDay, endDay, xlsxData)
// 根据任务类型获取完成任务的人数
// example: await getTaskCompleteUV('collectGoods', day)
const getTaskCompleteUV = async (task: string, day: string) => {
return await userDao.count({
activityId,
[`taskInfo.${day}.${task}`]: {
$exists: true
}
})
}
const keyValueMapper = {
时间: day,
访问PV: PV,
访问UV: UV,
新增UV: newUV,
已入会PV: vipPV,
已入会UV: vipUV,
未入会PV: noVipPV,
未入会UV: noVipUV,
新入会UV: newVipUV,
新增关注UV: newFollowUV
//收藏商品UV: await getTaskCompleteUV('collectGoods', day)
}
console.log(keyValueMapper, 'xlsxData')
if (day === startDay) {
xlsxData.push(Object.keys(keyValueMapper))
}
// @ts-ignore
xlsxData.push(Object.values(keyValueMapper))
let tommorrow = new Date(day).getTime() + oneDay
day = dateFormatter(transformBeijingDate(tommorrow), 'yyyy/MM/dd')
}
let buffer = xlsx.build([
{
name: `数据统计${startDay.replace(/\//g, '-')}-${endDay.replace(/\//g, '-')}`,
data: xlsxData
}
])
let result = await context.cloud.file.uploadFile({
fileContent: buffer,
fileName: `数据统计${startDay.replace(/\//g, '-')}-${endDay.replace(/\//g, '-')}.xlsx`
})
if (result.url) {
result.url = result.url.replace('http', 'https').replace('-internal', '')
}
return resultsModel.success(result)
} catch (e) {
console.log('上传文件出错', e)
// 打印日志
return resultsModel.error(CODE_TYPES.SYSTEM_ERROR, `上传文件错误`)
}
}
}
......@@ -82,11 +82,9 @@ export default class Task {
const { rewardsKey } = context.data
const { taskType } = context.data
const rewards = await taskService.receiveTaskRewards(taskType, rewardsKey, userInfo)
const rewardsResult = await taskService.receiveTaskRewards(taskType, rewardsKey, userInfo)
return resultsModel.success({
rewards
})
return resultsModel.success(rewardsResult)
}
/**
......
......@@ -4,17 +4,24 @@
* @format
*/
import { BaseDao } from '../sdk'
import { STAT_DB_NAME } from '../db'
import { BaseDao, dateFormatter, transformBeijingDate } from '../sdk'
import { STAT_DB_NAME, ACCESS_DB_NAME, USER_DB_NAME, AWARDS_DB_NAME } from '../db'
import * as xlsx from 'node-xlsx'
import { getToday } from '../utils'
import { STAT_TYPE } from '../constants'
export default class StatService {
context: IContext<any>
statdao: IBaseDao
accessdao: IBaseDao
userdao: IBaseDao
awardsdao: IBaseDao
constructor(context: IContext<IParams>) {
this.context = context
this.statdao = new BaseDao(context, STAT_DB_NAME)
this.accessdao = new BaseDao(context, ACCESS_DB_NAME)
this.userdao = new BaseDao(context, USER_DB_NAME)
this.awardsdao = new BaseDao(context, AWARDS_DB_NAME)
}
/**
......@@ -42,6 +49,118 @@ export default class StatService {
})
}
async getStats(activityId: string, startDay: string, endDay: string): Promise<any> {
let day = startDay
const oneDay = 24 * 3600 * 1000
let xlsxData = []
let curDayTimestamp = new Date(day).getTime()
const endDayTimestamp = new Date(endDay).getTime()
while (curDayTimestamp <= endDayTimestamp) {
// 访问PV
const PV = await this.accessdao.count({ activityId, createDay: day })
// 访问UV
const UV = await this.userdao.count({ activityId, [`login.${day}`]: { $exists: true } })
// 新增UV
const newUV = await this.userdao.count({ activityId, createDay: day })
// 已入会(老会员)PV
const vipPV = await this.accessdao.count({
activityId,
createDay: day,
//@ts-ignore
$or: [{ 'member.flag': true }, { 'member.newMember': true }],
'member.bememberDay': { $not: { $eq: day } }
})
// 已入会(老会员)UV
const vipUV = (
await this.accessdao.aggregate([
{
$match: {
activityId,
createDay: day,
$or: [{ 'member.flag': true }, { 'member.newMember': true }],
'member.bememberDay': { $not: { $eq: day } }
}
},
{ $project: { openId: true } },
{ $group: { _id: '$openId', count: { $sum: 1 } } },
{ $count: 'uv' }
])
)?.[0]?.uv
// 未入会PV
const noVipPV = await this.accessdao.count({ activityId, createDay: day, isVip: false })
// 未入会UV
const noVipUV = (
await this.accessdao.aggregate([
{ $match: { activityId, createDay: day, isVip: false } },
{ $project: { openId: true } },
{ $group: { _id: '$openId', count: { $sum: 1 } } }
])
).length
// 新增入会UV
const newVipUV = await this.userdao.count({ activityId, 'member.newMember': true, 'member.bememberDay': day })
const newFollowUV = await this.userdao.count({ activityId, 'follow.newFollow': true, 'follow.followDay': day })
// 根据任务类型获取完成任务的人数
// example: await getTaskCompleteUV('collectGoods', day)
const getTaskCompleteUV = async (task: string, day: string) => {
return await this.userdao.count({
activityId,
[`taskInfo.${day}.${task}`]: { $exists: true }
})
}
const keyValueMapper = {
时间: day,
访问PV: PV,
访问UV: UV,
新增UV: newUV,
已入会PV: vipPV,
已入会UV: vipUV,
未入会PV: noVipPV,
未入会UV: noVipUV,
新入会UV: newVipUV,
新增关注UV: newFollowUV
//收藏商品UV: await getTaskCompleteUV('collectGoods', day)
}
console.log(keyValueMapper, 'xlsxData')
if (day === startDay) {
xlsxData.push(Object.keys(keyValueMapper))
}
// @ts-ignore
xlsxData.push(Object.values(keyValueMapper))
const tommorrow = new Date(day).getTime() + oneDay
curDayTimestamp = tommorrow
day = dateFormatter(transformBeijingDate(tommorrow), 'yyyy/MM/dd')
}
return xlsxData
}
async buildExcel(startDay: string, endDay: string, xlsxData: []) {
let buffer = xlsx.build([
{
name: `数据统计${startDay.replace(/\//g, '-')}-${endDay.replace(/\//g, '-')}`,
data: xlsxData
}
])
let result = await this.context.cloud.file.uploadFile({
fileContent: buffer,
fileName: `数据统计${startDay.replace(/\//g, '-')}-${endDay.replace(/\//g, '-')}.xlsx`
})
if (result.url) {
result.url = result.url.replace('http', 'https').replace('-internal', '')
}
return result
}
async getStatCountByquery(query: IMongoQuery) {
return await this.statdao.count(query)
}
......
......@@ -79,7 +79,13 @@ export default class TaskService extends UserService {
* @return {number} rewards
* @memberof TaskService
*/
async receiveTaskRewards(taskType: ITaskType, awardsTargetKey: string, userInfo: IUserInfo): Promise<number> {
async receiveTaskRewards(
taskType: ITaskType,
awardsTargetKey: string,
userInfo: IUserInfo
): Promise<{
rewards: number
}> {
const waitReceiveTimes = userInfo?.remainTimes?.[taskType]
await this.updateUser(userInfo._id, {
......@@ -91,7 +97,9 @@ export default class TaskService extends UserService {
}
})
return waitReceiveTimes
return {
rewards: waitReceiveTimes
}
}
/**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment