瀏覽代碼

优化推广账号后台展示逻辑

wilhelm wong 2 月之前
父節點
當前提交
150bdc15e1
共有 3 個文件被更改,包括 275 次插入36 次删除
  1. 270 34
      src/controllers/team-domain.controller.ts
  2. 3 0
      src/controllers/team-members.controller.ts
  3. 2 2
      src/routes/team-members.routes.ts

+ 270 - 34
src/controllers/team-domain.controller.ts

@@ -9,16 +9,23 @@ import {
 import { UserRole } from '../entities/user.entity'
 import { TeamMembersService } from '../services/team-members.service'
 import { TeamService } from '../services/team.service'
+import { Repository, Between } from 'typeorm'
+import { Member } from '../entities/member.entity'
+import { IncomeRecords } from '../entities/income-records.entity'
 
 export class TeamDomainController {
   private teamDomainService: TeamDomainService
   private teamMembersService: TeamMembersService
   private teamService: TeamService
+  private memberRepository: Repository<Member>
+  private incomeRecordsRepository: Repository<IncomeRecords>
 
   constructor(app: FastifyInstance) {
     this.teamDomainService = new TeamDomainService(app)
     this.teamMembersService = new TeamMembersService(app)
     this.teamService = new TeamService(app)
+    this.memberRepository = app.dataSource.getRepository(Member)
+    this.incomeRecordsRepository = app.dataSource.getRepository(IncomeRecords)
   }
 
   async create(request: FastifyRequest<{ Body: CreateTeamDomainBody }>, reply: FastifyReply) {
@@ -177,35 +184,40 @@ export class TeamDomainController {
       }
 
       const { domain } = request.query
-      let result = await this.teamDomainService.getDailyStatistics(domain)
 
       if (user.role === UserRole.PROMOTER) {
-        // 推广用户只能查看自己绑定的域名统计
+        // 推广用户只能查看自己分得的金额统计
         try {
           const teamMembers = await this.teamMembersService.findByUserId(user.id)
           const teamDomains = await this.teamDomainService.findByTeamMemberId(teamMembers.id)
           const teamDomainIds = teamDomains.map(d => d.id)
           
-          // 过滤结果,只保留推广用户绑定的域名统计
-          result = result.filter(stat => teamDomainIds.includes(stat.id))
+          // 获取推广用户相关的域名统计(只统计personalIncomeAmount)
+          const result = await this.getPromoterDailyStatistics(teamDomainIds, domain)
+          return reply.send(result)
         } catch (error) {
           // 如果推广用户没有团队成员记录,返回空统计
-          result = []
+          return reply.send([])
         }
-      } else if (user.role === UserRole.TEAM) {
-        // 团队用户只能查看该团队的域名统计
-        const team = await this.teamService.findByUserId(user.id)
-        if (team) {
-          const teamDomains = await this.teamDomainService.findByTeamId(team.id)
-          const teamDomainIds = teamDomains.map(d => d.id)
-          
-          result = result.filter(stat => teamDomainIds.includes(stat.id))
-        } else {
-          result = []
+      } else {
+        // 管理员和团队用户使用原有逻辑
+        let result = await this.teamDomainService.getDailyStatistics(domain)
+
+        if (user.role === UserRole.TEAM) {
+          // 团队用户只能查看该团队的域名统计
+          const team = await this.teamService.findByUserId(user.id)
+          if (team) {
+            const teamDomains = await this.teamDomainService.findByTeamId(team.id)
+            const teamDomainIds = teamDomains.map(d => d.id)
+            
+            result = result.filter(stat => teamDomainIds.includes(stat.id))
+          } else {
+            result = []
+          }
         }
-      }
 
-      return reply.send(result)
+        return reply.send(result)
+      }
     } catch (error) {
       return reply.code(500).send({ message: '获取每日统计数据失败' })
     }
@@ -219,37 +231,261 @@ export class TeamDomainController {
       }
 
       const { domain } = request.query
-      let result = await this.teamDomainService.getAllStatistics(domain)
 
       if (user.role === UserRole.PROMOTER) {
-        // 推广用户只能查看自己绑定的域名统计
+        // 推广用户只能查看自己分得的金额统计
         try {
           const teamMembers = await this.teamMembersService.findByUserId(user.id)
           const teamDomains = await this.teamDomainService.findByTeamMemberId(teamMembers.id)
           const teamDomainIds = teamDomains.map(d => d.id)
           
-          // 过滤结果,只保留推广用户绑定的域名统计
-          result = result.filter(stat => teamDomainIds.includes(stat.id))
+          // 获取推广用户相关的域名统计(只统计personalIncomeAmount)
+          const result = await this.getPromoterAllStatistics(teamDomainIds, domain)
+          return reply.send(result)
         } catch (error) {
           // 如果推广用户没有团队成员记录,返回空统计
-          result = []
+          return reply.send([])
         }
-      } else if (user.role === UserRole.TEAM) {
-        // 团队用户只能查看该团队的域名统计
-        const team = await this.teamService.findByUserId(user.id)
-        if (team) {
-          const teamDomains = await this.teamDomainService.findByTeamId(team.id)
-          const teamDomainIds = teamDomains.map(d => d.id)
-          
-          result = result.filter(stat => teamDomainIds.includes(stat.id))
-        } else {
-          result = []
+      } else {
+        // 管理员和团队用户使用原有逻辑
+        let result = await this.teamDomainService.getAllStatistics(domain)
+
+        if (user.role === UserRole.TEAM) {
+          // 团队用户只能查看该团队的域名统计
+          const team = await this.teamService.findByUserId(user.id)
+          if (team) {
+            const teamDomains = await this.teamDomainService.findByTeamId(team.id)
+            const teamDomainIds = teamDomains.map(d => d.id)
+            
+            result = result.filter(stat => teamDomainIds.includes(stat.id))
+          } else {
+            result = []
+          }
         }
-      }
 
-      return reply.send(result)
+        return reply.send(result)
+      }
     } catch (error) {
       return reply.code(500).send({ message: '获取总统计数据失败' })
     }
   }
+
+  /**
+   * 获取推广用户每日统计(只统计personalIncomeAmount)
+   */
+  private async getPromoterDailyStatistics(domainIds: number[], domain?: string): Promise<any[]> {
+    if (domainIds.length === 0) {
+      return []
+    }
+
+    // 获取今天的开始和结束时间(使用UTC时区)
+    const today = new Date()
+    today.setUTCHours(0, 0, 0, 0)
+    const tomorrow = new Date(today)
+    tomorrow.setUTCDate(tomorrow.getUTCDate() + 1)
+
+    const results: any[] = []
+
+    for (const domainId of domainIds) {
+      // 获取域名信息
+      const teamDomain = await this.teamDomainService.findById(domainId)
+      
+      // 如果指定了域名过滤,跳过不匹配的域名
+      if (domain && !teamDomain.domain.includes(domain)) {
+        continue
+      }
+
+      // 统计今日新增用户数
+      const todayNewUsers = await this.memberRepository.count({
+        where: {
+          domainId: domainId,
+          createdAt: Between(today, tomorrow)
+        }
+      })
+
+      // 统计今日活跃用户数(基于lastLoginAt字段)
+      const todayActiveUsers = await this.memberRepository.count({
+        where: {
+          domainId: domainId,
+          lastLoginAt: Between(today, tomorrow)
+        }
+      })
+
+      // 统计今日收入(只统计personalIncomeAmount)
+      const todayIncomeRecords = await this.incomeRecordsRepository
+        .createQueryBuilder('record')
+        .innerJoin('member', 'm', 'm.userId = record.userId')
+        .select('SUM(CAST(record.personalIncomeAmount AS DECIMAL(10,5)))', 'totalIncome')
+        .where('m.domainId = :domainId', { domainId: domainId })
+        .andWhere('record.createdAt >= :startDate', { startDate: today })
+        .andWhere('record.createdAt < :endDate', { endDate: tomorrow })
+        .andWhere('record.delFlag = :delFlag', { delFlag: false })
+        .andWhere('record.status = :status', { status: true })
+        .andWhere('record.personalIncomeAmount > 0')
+        .getRawOne()
+
+      const todayIncome = todayIncomeRecords?.totalIncome ? parseFloat(todayIncomeRecords.totalIncome) : 0
+
+      // 统计历史总收入(只统计personalIncomeAmount)
+      const totalIncomeRecords = await this.incomeRecordsRepository
+        .createQueryBuilder('record')
+        .innerJoin('member', 'm', 'm.userId = record.userId')
+        .select('SUM(CAST(record.personalIncomeAmount AS DECIMAL(10,5)))', 'totalIncome')
+        .where('m.domainId = :domainId', { domainId: domainId })
+        .andWhere('record.delFlag = :delFlag', { delFlag: false })
+        .andWhere('record.status = :status', { status: true })
+        .andWhere('record.personalIncomeAmount > 0')
+        .getRawOne()
+
+      const totalIncome = totalIncomeRecords?.totalIncome ? parseFloat(totalIncomeRecords.totalIncome) : 0
+
+      // 统计历史总销售额
+      const totalSalesRecords = await this.incomeRecordsRepository
+        .createQueryBuilder('record')
+        .innerJoin('member', 'm', 'm.userId = record.userId')
+        .select('SUM(CAST(record.orderPrice AS DECIMAL(10,5)))', 'totalSales')
+        .where('m.domainId = :domainId', { domainId: domainId })
+        .andWhere('record.delFlag = :delFlag', { delFlag: false })
+        .andWhere('record.status = :status', { status: true })
+        .getRawOne()
+
+      const totalSales = totalSalesRecords?.totalSales ? parseFloat(totalSalesRecords.totalSales) : 0
+
+      // 统计今日销售额
+      const todaySalesRecords = await this.incomeRecordsRepository
+        .createQueryBuilder('record')
+        .innerJoin('member', 'm', 'm.userId = record.userId')
+        .select('SUM(CAST(record.orderPrice AS DECIMAL(10,5)))', 'totalSales')
+        .where('m.domainId = :domainId', { domainId: domainId })
+        .andWhere('record.createdAt >= :startDate', { startDate: today })
+        .andWhere('record.createdAt < :endDate', { endDate: tomorrow })
+        .andWhere('record.delFlag = :delFlag', { delFlag: false })
+        .andWhere('record.status = :status', { status: true })
+        .getRawOne()
+
+      const todaySales = todaySalesRecords?.totalSales ? parseFloat(todaySalesRecords.totalSales) : 0
+
+      results.push({
+        id: teamDomain.id,
+        domain: teamDomain.domain,
+        todayNewUsers,
+        todayIncome,
+        todayActiveUsers,
+        totalIncome,
+        totalSales,
+        todaySales
+      })
+    }
+
+    return results
+  }
+
+  /**
+   * 获取推广用户总统计(只统计personalIncomeAmount)
+   */
+  private async getPromoterAllStatistics(domainIds: number[], domain?: string): Promise<any[]> {
+    if (domainIds.length === 0) {
+      return []
+    }
+
+    // 获取今天的开始和结束时间(使用UTC时区)
+    const today = new Date()
+    today.setUTCHours(0, 0, 0, 0)
+    const tomorrow = new Date(today)
+    tomorrow.setUTCDate(tomorrow.getUTCDate() + 1)
+
+    const results: any[] = []
+
+    for (const domainId of domainIds) {
+      // 获取域名信息
+      const teamDomain = await this.teamDomainService.findById(domainId)
+      
+      // 如果指定了域名过滤,跳过不匹配的域名
+      if (domain && !teamDomain.domain.includes(domain)) {
+        continue
+      }
+
+      // 统计总新增用户数
+      const totalNewUsers = await this.memberRepository.count({
+        where: {
+          domainId: domainId
+        }
+      })
+
+      // 统计今日活跃用户数(基于lastLoginAt字段)
+      const todayActiveUsers = await this.memberRepository.count({
+        where: {
+          domainId: domainId,
+          lastLoginAt: Between(today, tomorrow)
+        }
+      })
+
+      // 统计总收入(只统计personalIncomeAmount)
+      const totalIncomeRecords = await this.incomeRecordsRepository
+        .createQueryBuilder('record')
+        .innerJoin('member', 'm', 'm.userId = record.userId')
+        .select('SUM(CAST(record.personalIncomeAmount AS DECIMAL(10,5)))', 'totalIncome')
+        .where('m.domainId = :domainId', { domainId: domainId })
+        .andWhere('record.delFlag = :delFlag', { delFlag: false })
+        .andWhere('record.status = :status', { status: true })
+        .andWhere('record.personalIncomeAmount > 0')
+        .getRawOne()
+
+      const totalIncome = totalIncomeRecords?.totalIncome ? parseFloat(totalIncomeRecords.totalIncome) : 0
+
+      // 统计今日收入(只统计personalIncomeAmount)
+      const todayIncomeRecords = await this.incomeRecordsRepository
+        .createQueryBuilder('record')
+        .innerJoin('member', 'm', 'm.userId = record.userId')
+        .select('SUM(CAST(record.personalIncomeAmount AS DECIMAL(10,5)))', 'totalIncome')
+        .where('m.domainId = :domainId', { domainId: domainId })
+        .andWhere('record.createdAt >= :startDate', { startDate: today })
+        .andWhere('record.createdAt < :endDate', { endDate: tomorrow })
+        .andWhere('record.delFlag = :delFlag', { delFlag: false })
+        .andWhere('record.status = :status', { status: true })
+        .andWhere('record.personalIncomeAmount > 0')
+        .getRawOne()
+
+      const todayIncome = todayIncomeRecords?.totalIncome ? parseFloat(todayIncomeRecords.totalIncome) : 0
+
+      // 统计历史总销售额
+      const totalSalesRecords = await this.incomeRecordsRepository
+        .createQueryBuilder('record')
+        .innerJoin('member', 'm', 'm.userId = record.userId')
+        .select('SUM(CAST(record.orderPrice AS DECIMAL(10,5)))', 'totalSales')
+        .where('m.domainId = :domainId', { domainId: domainId })
+        .andWhere('record.delFlag = :delFlag', { delFlag: false })
+        .andWhere('record.status = :status', { status: true })
+        .getRawOne()
+
+      const totalSales = totalSalesRecords?.totalSales ? parseFloat(totalSalesRecords.totalSales) : 0
+
+      // 统计今日销售额
+      const todaySalesRecords = await this.incomeRecordsRepository
+        .createQueryBuilder('record')
+        .innerJoin('member', 'm', 'm.userId = record.userId')
+        .select('SUM(CAST(record.orderPrice AS DECIMAL(10,5)))', 'totalSales')
+        .where('m.domainId = :domainId', { domainId: domainId })
+        .andWhere('record.createdAt >= :startDate', { startDate: today })
+        .andWhere('record.createdAt < :endDate', { endDate: tomorrow })
+        .andWhere('record.delFlag = :delFlag', { delFlag: false })
+        .andWhere('record.status = :status', { status: true })
+        .getRawOne()
+
+      const todaySales = todaySalesRecords?.totalSales ? parseFloat(todaySalesRecords.totalSales) : 0
+
+      results.push({
+        id: teamDomain.id,
+        domain: teamDomain.domain,
+        totalNewUsers,
+        totalIncome,
+        todayActiveUsers,
+        todayIncome,
+        totalSales,
+        todaySales
+      })
+    }
+
+    return results
+  }
 }

+ 3 - 0
src/controllers/team-members.controller.ts

@@ -75,6 +75,9 @@ export class TeamMembersController {
       if (user.role === UserRole.TEAM) {
         const team = await this.teamService.findByUserId(user.id)
         request.query.teamId = team.id
+      } else if (user.role === UserRole.PROMOTER) {
+        // 推广员只能查看自己的团队成员信息
+        request.query.userId = user.id
       }
       const result = await this.teamMembersService.findAll(request.query)
       return reply.send(result)

+ 2 - 2
src/routes/team-members.routes.ts

@@ -24,7 +24,7 @@ export default async function teamMembersRoutes(fastify: FastifyInstance) {
   // 获取团队成员列表
   fastify.get<{ Querystring: ListTeamMembersQuery }>(
     '/',
-    { onRequest: [authenticate, hasAnyRole(UserRole.ADMIN, UserRole.TEAM)] },
+    { onRequest: [authenticate, hasAnyRole(UserRole.ADMIN, UserRole.TEAM, UserRole.PROMOTER)] },
     teamMembersController.findAll.bind(teamMembersController)
   )
 
@@ -66,7 +66,7 @@ export default async function teamMembersRoutes(fastify: FastifyInstance) {
   // 获取统计数据
   fastify.get(
     '/statistics/summary',
-    { onRequest: [authenticate, hasRole(UserRole.ADMIN)] },
+    { onRequest: [authenticate, hasAnyRole(UserRole.ADMIN, UserRole.PROMOTER)] },
     teamMembersController.getStatistics.bind(teamMembersController)
   )