|
|
@@ -0,0 +1,606 @@
|
|
|
+import { Repository, Between, MoreThanOrEqual, LessThanOrEqual, Like } from 'typeorm'
|
|
|
+import { FastifyInstance } from 'fastify'
|
|
|
+import { UserShareRecord } from '../entities/user-invite-record.entity'
|
|
|
+import { User } from '../entities/user.entity'
|
|
|
+import { Member } from '../entities/member.entity'
|
|
|
+import { Team } from '../entities/team.entity'
|
|
|
+import { TeamMembers } from '../entities/team-members.entity'
|
|
|
+import { SysConfigService } from './sys-config.service'
|
|
|
+import { IncomeRecordsService } from './income-records.service'
|
|
|
+import { IncomeRecords, IncomeType, OrderType } from '../entities/income-records.entity'
|
|
|
+import { PaginationResponse } from '../dto/common.dto'
|
|
|
+import { UserRole } from '../entities/user.entity'
|
|
|
+
|
|
|
+export class UserShareService {
|
|
|
+ private userShareRecordRepository: Repository<UserShareRecord>
|
|
|
+ private userRepository: Repository<User>
|
|
|
+ private memberRepository: Repository<Member>
|
|
|
+ private teamRepository: Repository<Team>
|
|
|
+ private teamMembersRepository: Repository<TeamMembers>
|
|
|
+ private sysConfigService: SysConfigService
|
|
|
+ private incomeRecordsService: IncomeRecordsService
|
|
|
+
|
|
|
+ constructor(app: FastifyInstance) {
|
|
|
+ this.userShareRecordRepository = app.dataSource.getRepository(UserShareRecord)
|
|
|
+ this.userRepository = app.dataSource.getRepository(User)
|
|
|
+ this.memberRepository = app.dataSource.getRepository(Member)
|
|
|
+ this.teamRepository = app.dataSource.getRepository(Team)
|
|
|
+ this.teamMembersRepository = app.dataSource.getRepository(TeamMembers)
|
|
|
+ this.sysConfigService = new SysConfigService(app)
|
|
|
+ this.incomeRecordsService = new IncomeRecordsService(app)
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取用户昵称和团队信息
|
|
|
+ */
|
|
|
+ private async getUserAndTeamInfo(userId: number): Promise<{ inviterName: string; teamId: number | null; teamName: string | null }> {
|
|
|
+ // 获取用户信息
|
|
|
+ const user = await this.userRepository.findOne({ where: { id: userId } })
|
|
|
+ if (!user) {
|
|
|
+ throw new Error('用户不存在')
|
|
|
+ }
|
|
|
+
|
|
|
+ let teamId: number | null = null
|
|
|
+ let teamName: string | null = null
|
|
|
+
|
|
|
+ // 根据用户角色获取团队信息
|
|
|
+ if (user.role === UserRole.TEAM) {
|
|
|
+ // 队长从team表中获取团队信息
|
|
|
+ const team = await this.teamRepository.findOne({ where: { userId } })
|
|
|
+ if (team) {
|
|
|
+ teamId = team.id
|
|
|
+ teamName = team.name
|
|
|
+ }
|
|
|
+ } else if (user.role === UserRole.PROMOTER) {
|
|
|
+ // 推广员从team-members表中获取团队信息
|
|
|
+ const teamMember = await this.teamMembersRepository.findOne({ where: { userId } })
|
|
|
+ if (teamMember) {
|
|
|
+ teamId = teamMember.teamId
|
|
|
+ // 获取团队名称
|
|
|
+ const team = await this.teamRepository.findOne({ where: { id: teamMember.teamId } })
|
|
|
+ if (team) {
|
|
|
+ teamName = team.name
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return {
|
|
|
+ inviterName: user.name,
|
|
|
+ teamId,
|
|
|
+ teamName
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 记录用户分享单片
|
|
|
+ */
|
|
|
+ async recordShare(userId: number, resourceId: string, resourceName?: string): Promise<UserShareRecord> {
|
|
|
+ // 检查是否已经分享过该资源
|
|
|
+ const existingShare = await this.userShareRecordRepository.findOne({
|
|
|
+ where: {
|
|
|
+ inviterId: userId,
|
|
|
+ resourceId,
|
|
|
+ delFlag: false
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ if (existingShare) {
|
|
|
+ return existingShare
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取用户和团队信息
|
|
|
+ const { inviterName, teamId, teamName } = await this.getUserAndTeamInfo(userId)
|
|
|
+
|
|
|
+ // 创建分享记录
|
|
|
+ const shareRecord = this.userShareRecordRepository.create({
|
|
|
+ inviterId: userId,
|
|
|
+ resourceId,
|
|
|
+ resourceName,
|
|
|
+ inviterName,
|
|
|
+ teamId,
|
|
|
+ teamName,
|
|
|
+ status: true
|
|
|
+ } as Partial<UserShareRecord>)
|
|
|
+
|
|
|
+ const savedRecord = await this.userShareRecordRepository.save(shareRecord)
|
|
|
+
|
|
|
+ // 检查是否需要给予单片资格奖励
|
|
|
+ await this.checkAndRewardInviter(userId, resourceId)
|
|
|
+
|
|
|
+ return savedRecord
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 记录分享链接点击
|
|
|
+ */
|
|
|
+ async recordShareClick(userId: number, resourceId: string, clickerIp: string, resourceName?: string): Promise<UserShareRecord> {
|
|
|
+ // 获取用户和团队信息
|
|
|
+ const { inviterName, teamId, teamName } = await this.getUserAndTeamInfo(userId)
|
|
|
+
|
|
|
+ // 校验当天是否已有相同 inviterId + resourceId + ip 的记录
|
|
|
+ const today = new Date()
|
|
|
+ today.setHours(0, 0, 0, 0)
|
|
|
+ const tomorrow = new Date(today)
|
|
|
+ tomorrow.setDate(tomorrow.getDate() + 1)
|
|
|
+
|
|
|
+ const duplicatedToday = await this.userShareRecordRepository.count({
|
|
|
+ where: {
|
|
|
+ inviterId: userId,
|
|
|
+ resourceId,
|
|
|
+ invitedUserIp: clickerIp,
|
|
|
+ createdAt: Between(today, tomorrow),
|
|
|
+ delFlag: false
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ // 校验邀请人在 member 表中的登录 IP 是否与当前相同
|
|
|
+ const inviterMember = await this.memberRepository.findOne({ where: { userId } })
|
|
|
+ const isSelfIp = inviterMember?.ip && inviterMember.ip === clickerIp
|
|
|
+
|
|
|
+ // 创建分享记录(重复则标记失败)
|
|
|
+ const shareRecord = this.userShareRecordRepository.create({
|
|
|
+ inviterId: userId,
|
|
|
+ resourceId,
|
|
|
+ resourceName,
|
|
|
+ invitedUserIp: clickerIp,
|
|
|
+ inviterName,
|
|
|
+ teamId,
|
|
|
+ teamName,
|
|
|
+ status: (duplicatedToday > 0 || isSelfIp) ? false : true
|
|
|
+ } as Partial<UserShareRecord>)
|
|
|
+
|
|
|
+ const savedRecord = await this.userShareRecordRepository.save(shareRecord)
|
|
|
+
|
|
|
+ // 仅对成功记录检查奖励
|
|
|
+ if (savedRecord.status) {
|
|
|
+ await this.checkAndRewardInviter(userId, resourceId)
|
|
|
+ }
|
|
|
+
|
|
|
+ return savedRecord
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 通过分享链接注册用户
|
|
|
+ */
|
|
|
+ async registerByShareLink(
|
|
|
+ name: string,
|
|
|
+ password: string,
|
|
|
+ inviterId: number,
|
|
|
+ resourceId: string,
|
|
|
+ ip: string,
|
|
|
+ email?: string,
|
|
|
+ phone?: string,
|
|
|
+ resourceName?: string
|
|
|
+ ): Promise<{ user: User; member: Member; inviterId: number }> {
|
|
|
+ // 验证邀请者是否存在
|
|
|
+ const inviter = await this.userRepository.findOne({ where: { id: inviterId } })
|
|
|
+ if (!inviter) {
|
|
|
+ throw new Error('邀请者不存在')
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查IP是否已被使用(防薅羊毛)
|
|
|
+ const ipUsedToday = await this.checkIpUsageToday(ip)
|
|
|
+ if (ipUsedToday) {
|
|
|
+ throw new Error('该IP今日已使用过邀请注册')
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查用户名是否已存在
|
|
|
+ const existingUser = await this.userRepository.findOne({ where: { name } })
|
|
|
+ if (existingUser) {
|
|
|
+ throw new Error('用户名已存在')
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查邮箱是否已存在
|
|
|
+ if (email) {
|
|
|
+ const existingEmail = await this.memberRepository.findOne({ where: { email } })
|
|
|
+ if (existingEmail) {
|
|
|
+ throw new Error('邮箱已存在')
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查手机号是否已存在
|
|
|
+ if (phone) {
|
|
|
+ const existingPhone = await this.memberRepository.findOne({ where: { phone } })
|
|
|
+ if (existingPhone) {
|
|
|
+ throw new Error('手机号已存在')
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 创建用户
|
|
|
+ const hashedPassword = await require('bcryptjs').hash(password, 10)
|
|
|
+ const user = this.userRepository.create({
|
|
|
+ name,
|
|
|
+ password: hashedPassword,
|
|
|
+ role: 'user' as any,
|
|
|
+ parentId: inviterId
|
|
|
+ })
|
|
|
+ const savedUser = await this.userRepository.save(user)
|
|
|
+
|
|
|
+ // 创建会员记录
|
|
|
+ const member = this.memberRepository.create({
|
|
|
+ userId: savedUser.id,
|
|
|
+ teamId: 1, // 默认团队
|
|
|
+ domainId: 0,
|
|
|
+ email,
|
|
|
+ phone,
|
|
|
+ vipLevel: 'free' as any,
|
|
|
+ status: 'active' as any,
|
|
|
+ ip: ip || 'unknown',
|
|
|
+ lastLoginAt: new Date()
|
|
|
+ })
|
|
|
+ const savedMember = await this.memberRepository.save(member)
|
|
|
+
|
|
|
+ // 分享记录已在点击时创建,这里不需要再创建
|
|
|
+ // 只需要更新已存在的分享记录,关联被邀请用户
|
|
|
+ const existingShare = await this.userShareRecordRepository.findOne({
|
|
|
+ where: {
|
|
|
+ inviterId,
|
|
|
+ resourceId,
|
|
|
+ delFlag: false
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ if (existingShare) {
|
|
|
+ // 更新分享记录,关联被邀请用户
|
|
|
+ await this.userShareRecordRepository.update(existingShare.id, {
|
|
|
+ invitedUserId: savedUser.id
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ return {
|
|
|
+ user: savedUser,
|
|
|
+ member: savedMember,
|
|
|
+ inviterId
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 检查IP今日使用情况(防薅羊毛)
|
|
|
+ */
|
|
|
+ private async checkIpUsageToday(ip: string): Promise<boolean> {
|
|
|
+ const today = new Date()
|
|
|
+ today.setHours(0, 0, 0, 0)
|
|
|
+ const tomorrow = new Date(today)
|
|
|
+ tomorrow.setDate(tomorrow.getDate() + 1)
|
|
|
+
|
|
|
+ const count = await this.userShareRecordRepository.count({
|
|
|
+ where: {
|
|
|
+ invitedUserIp: ip,
|
|
|
+ createdAt: Between(today, tomorrow),
|
|
|
+ status: true
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ return count > 0
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 检查并奖励邀请者
|
|
|
+ */
|
|
|
+ private async checkAndRewardInviter(inviterId: number, resourceId?: string): Promise<void> {
|
|
|
+ // 获取系统配置:需要多少次邀请才能获得单片资格
|
|
|
+ const configs = await this.sysConfigService.getUserTeamConfigs(inviterId)
|
|
|
+ const inviteRewardConfig = configs.find((c: any) => c.name === 'invite_reward_count')
|
|
|
+ const requiredCount = inviteRewardConfig ? parseInt(inviteRewardConfig.value) : 3
|
|
|
+
|
|
|
+ // 统计用户的有效邀请数
|
|
|
+ const successCount = await this.userShareRecordRepository.count({
|
|
|
+ where: {
|
|
|
+ inviterId,
|
|
|
+ status: true,
|
|
|
+ delFlag: false
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ // 检查是否达到奖励条件
|
|
|
+ if (successCount >= requiredCount) {
|
|
|
+ // 检查是否已经给过该资源的奖励
|
|
|
+ const existingReward = await this.incomeRecordsService.findAll({
|
|
|
+ page: 0,
|
|
|
+ size: 1,
|
|
|
+ userId: inviterId,
|
|
|
+ incomeType: IncomeType.TIP,
|
|
|
+ orderType: OrderType.SINGLE_TIP,
|
|
|
+ resourceId: resourceId || 'invite_reward'
|
|
|
+ })
|
|
|
+
|
|
|
+ // 如果已经给过该资源的奖励,则不再发放
|
|
|
+ if (existingReward.content.length > 0) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查今日是否已达到每日限制(最多3条)
|
|
|
+ const today = new Date()
|
|
|
+ today.setHours(0, 0, 0, 0)
|
|
|
+ const tomorrow = new Date(today)
|
|
|
+ tomorrow.setDate(tomorrow.getDate() + 1)
|
|
|
+
|
|
|
+ const todayRewards = await this.incomeRecordsService.findAll({
|
|
|
+ page: 0,
|
|
|
+ size: 10, // 获取足够多的记录来检查
|
|
|
+ userId: inviterId,
|
|
|
+ incomeType: IncomeType.TIP,
|
|
|
+ orderType: OrderType.SINGLE_TIP,
|
|
|
+ startDate: today.toISOString().split('T')[0],
|
|
|
+ endDate: today.toISOString().split('T')[0]
|
|
|
+ })
|
|
|
+
|
|
|
+ // 如果今日已达到3条限制,则不再发放
|
|
|
+ if (todayRewards.content.length >= 3) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 生成正常的支付订单号
|
|
|
+ const orderNo = `INVITE_REWARD_${inviterId}_${Date.now()}${Math.floor(Math.random() * 10000).toString().padStart(4, '0')}`
|
|
|
+
|
|
|
+ // 给予单片资格奖励
|
|
|
+ await this.incomeRecordsService.create({
|
|
|
+ agentId: 0,
|
|
|
+ userId: inviterId,
|
|
|
+ incomeAmount: 0, // 免费单片
|
|
|
+ incomeType: IncomeType.TIP,
|
|
|
+ resourceId: resourceId || 'invite_reward', // 使用实际的resourceId,如果没有则使用默认值
|
|
|
+ orderType: OrderType.SINGLE_TIP,
|
|
|
+ orderNo: orderNo,
|
|
|
+ orderPrice: 0,
|
|
|
+ payChannel: 'system',
|
|
|
+ payNo: orderNo, // 使用正常的订单号作为payNo
|
|
|
+ status: true
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取用户的分享统计
|
|
|
+ */
|
|
|
+ async getUserShareStats(userId: number): Promise<{
|
|
|
+ totalShares: number
|
|
|
+ successShares: number
|
|
|
+ todayShares: number
|
|
|
+ hasReward: boolean
|
|
|
+ todayRewards: number
|
|
|
+ dailyLimitReached: boolean
|
|
|
+ }> {
|
|
|
+ const today = new Date()
|
|
|
+ today.setHours(0, 0, 0, 0)
|
|
|
+ const tomorrow = new Date(today)
|
|
|
+ tomorrow.setDate(tomorrow.getDate() + 1)
|
|
|
+
|
|
|
+ // 获取当前用户信息
|
|
|
+ const currentUser = await this.userRepository.findOne({ where: { id: userId } })
|
|
|
+ if (!currentUser) {
|
|
|
+ throw new Error('用户不存在')
|
|
|
+ }
|
|
|
+
|
|
|
+ let whereCondition: any = { delFlag: false }
|
|
|
+ let successWhereCondition: any = { status: true, delFlag: false }
|
|
|
+ let todayWhereCondition: any = {
|
|
|
+ createdAt: Between(today, tomorrow),
|
|
|
+ delFlag: false
|
|
|
+ }
|
|
|
+
|
|
|
+ // 根据用户角色设置查询条件
|
|
|
+ if (currentUser.role === 'admin') {
|
|
|
+ // 管理员可以查看所有记录
|
|
|
+ whereCondition = { delFlag: false }
|
|
|
+ successWhereCondition = { status: true, delFlag: false }
|
|
|
+ todayWhereCondition = {
|
|
|
+ createdAt: Between(today, tomorrow),
|
|
|
+ delFlag: false
|
|
|
+ }
|
|
|
+ } else if (currentUser.role === 'team') {
|
|
|
+ // 团队账号可以查看团队下辖邀请人的记录
|
|
|
+ const teamMembers = await this.userRepository.find({
|
|
|
+ where: { parentId: userId }
|
|
|
+ })
|
|
|
+ const teamMemberIds = teamMembers.map(member => member.id)
|
|
|
+
|
|
|
+ if (teamMemberIds.length > 0) {
|
|
|
+ whereCondition = {
|
|
|
+ inviterId: teamMemberIds,
|
|
|
+ delFlag: false
|
|
|
+ }
|
|
|
+ successWhereCondition = {
|
|
|
+ inviterId: teamMemberIds,
|
|
|
+ status: true,
|
|
|
+ delFlag: false
|
|
|
+ }
|
|
|
+ todayWhereCondition = {
|
|
|
+ inviterId: teamMemberIds,
|
|
|
+ createdAt: Between(today, tomorrow),
|
|
|
+ delFlag: false
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 如果没有下辖用户,返回0
|
|
|
+ whereCondition = { inviterId: -1, delFlag: false }
|
|
|
+ successWhereCondition = { inviterId: -1, status: true, delFlag: false }
|
|
|
+ todayWhereCondition = { inviterId: -1, createdAt: Between(today, tomorrow), delFlag: false }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 推广员和普通用户只能查看自己的记录
|
|
|
+ whereCondition = { inviterId: userId, delFlag: false }
|
|
|
+ successWhereCondition = { inviterId: userId, status: true, delFlag: false }
|
|
|
+ todayWhereCondition = {
|
|
|
+ inviterId: userId,
|
|
|
+ createdAt: Between(today, tomorrow),
|
|
|
+ delFlag: false
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 总分享数
|
|
|
+ const totalShares = await this.userShareRecordRepository.count({
|
|
|
+ where: whereCondition
|
|
|
+ })
|
|
|
+
|
|
|
+ // 成功分享数
|
|
|
+ const successShares = await this.userShareRecordRepository.count({
|
|
|
+ where: successWhereCondition
|
|
|
+ })
|
|
|
+
|
|
|
+ // 今日分享数
|
|
|
+ const todayShares = await this.userShareRecordRepository.count({
|
|
|
+ where: todayWhereCondition
|
|
|
+ })
|
|
|
+
|
|
|
+ // 检查是否已获得奖励
|
|
|
+ const hasReward = await this.incomeRecordsService.findAll({
|
|
|
+ page: 0,
|
|
|
+ size: 1,
|
|
|
+ userId,
|
|
|
+ incomeType: IncomeType.TIP,
|
|
|
+ orderType: OrderType.SINGLE_TIP,
|
|
|
+ resourceId: 'invite_reward'
|
|
|
+ })
|
|
|
+
|
|
|
+ // 获取今日奖励数量
|
|
|
+ const todayRewards = await this.incomeRecordsService.findAll({
|
|
|
+ page: 0,
|
|
|
+ size: 10,
|
|
|
+ userId,
|
|
|
+ incomeType: IncomeType.TIP,
|
|
|
+ orderType: OrderType.SINGLE_TIP,
|
|
|
+ startDate: today.toISOString().split('T')[0],
|
|
|
+ endDate: today.toISOString().split('T')[0]
|
|
|
+ })
|
|
|
+
|
|
|
+ return {
|
|
|
+ totalShares,
|
|
|
+ successShares,
|
|
|
+ todayShares,
|
|
|
+ hasReward: hasReward.content.length > 0,
|
|
|
+ todayRewards: todayRewards.content.length,
|
|
|
+ dailyLimitReached: todayRewards.content.length >= 3
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取分享记录列表
|
|
|
+ */
|
|
|
+ async getShareRecords(
|
|
|
+ userId: number,
|
|
|
+ page: number = 0,
|
|
|
+ size: number = 20,
|
|
|
+ filters?: {
|
|
|
+ status?: boolean
|
|
|
+ startDate?: string
|
|
|
+ endDate?: string
|
|
|
+ resourceId?: string
|
|
|
+ inviterId?: number
|
|
|
+ teamId?: number
|
|
|
+ inviterName?: string
|
|
|
+ sortField?: string
|
|
|
+ sortOrder?: string
|
|
|
+ }
|
|
|
+ ): Promise<PaginationResponse<UserShareRecord>> {
|
|
|
+ // 获取当前用户信息
|
|
|
+ const currentUser = await this.userRepository.findOne({ where: { id: userId } })
|
|
|
+ if (!currentUser) {
|
|
|
+ throw new Error('用户不存在')
|
|
|
+ }
|
|
|
+
|
|
|
+ let whereCondition: any = { delFlag: false }
|
|
|
+
|
|
|
+ // 根据用户角色设置查询条件
|
|
|
+ if (currentUser.role === 'admin') {
|
|
|
+ // 管理员可以查看所有记录
|
|
|
+ whereCondition = { delFlag: false }
|
|
|
+ } else if (currentUser.role === 'team') {
|
|
|
+ // 团队账号可以查看团队下辖邀请人的记录
|
|
|
+ // 查找所有parentId为当前团队ID的用户(推广员和普通用户)
|
|
|
+ const teamMembers = await this.userRepository.find({
|
|
|
+ where: { parentId: userId }
|
|
|
+ })
|
|
|
+ const teamMemberIds = teamMembers.map(member => member.id)
|
|
|
+
|
|
|
+ if (teamMemberIds.length > 0) {
|
|
|
+ whereCondition = {
|
|
|
+ inviterId: teamMemberIds,
|
|
|
+ delFlag: false
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 如果没有下辖用户,返回空结果
|
|
|
+ whereCondition = { inviterId: -1, delFlag: false }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 推广员和普通用户只能查看自己的记录
|
|
|
+ whereCondition = { inviterId: userId, delFlag: false }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 应用筛选条件
|
|
|
+ if (filters) {
|
|
|
+ if (filters.status !== undefined) {
|
|
|
+ // 将布尔值转换为数字:true -> 1, false -> 0
|
|
|
+ whereCondition.status = filters.status ? 1 : 0
|
|
|
+ }
|
|
|
+
|
|
|
+ if (filters.resourceId) {
|
|
|
+ whereCondition.resourceId = filters.resourceId
|
|
|
+ }
|
|
|
+
|
|
|
+ if (filters.inviterId) {
|
|
|
+ whereCondition.inviterId = filters.inviterId
|
|
|
+ }
|
|
|
+
|
|
|
+ if (filters.teamId) {
|
|
|
+ whereCondition.teamId = filters.teamId
|
|
|
+ }
|
|
|
+
|
|
|
+ // 邀请者姓名筛选
|
|
|
+ if (filters.inviterName) {
|
|
|
+ whereCondition.inviterName = Like(`%${filters.inviterName}%`)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 时间范围筛选
|
|
|
+ if (filters.startDate || filters.endDate) {
|
|
|
+ const startDate = filters.startDate ? new Date(filters.startDate) : undefined
|
|
|
+ const endDate = filters.endDate ? new Date(filters.endDate) : undefined
|
|
|
+
|
|
|
+ if (endDate) {
|
|
|
+ endDate.setHours(23, 59, 59, 999) // 设置为当天的最后一刻
|
|
|
+ }
|
|
|
+
|
|
|
+ if (startDate && endDate) {
|
|
|
+ whereCondition.createdAt = Between(startDate, endDate)
|
|
|
+ } else if (startDate) {
|
|
|
+ whereCondition.createdAt = MoreThanOrEqual(startDate)
|
|
|
+ } else if (endDate) {
|
|
|
+ whereCondition.createdAt = LessThanOrEqual(endDate)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 构建排序条件
|
|
|
+ let orderCondition: any = { createdAt: 'DESC' } // 默认按创建时间倒序
|
|
|
+
|
|
|
+ if (filters?.sortField) {
|
|
|
+ const sortOrder = filters.sortOrder === '1' ? 'ASC' : 'DESC'
|
|
|
+ orderCondition = { [filters.sortField]: sortOrder }
|
|
|
+ }
|
|
|
+
|
|
|
+ const [records, total] = await this.userShareRecordRepository.findAndCount({
|
|
|
+ where: whereCondition,
|
|
|
+ skip: page * size,
|
|
|
+ take: size,
|
|
|
+ order: orderCondition
|
|
|
+ })
|
|
|
+
|
|
|
+ return {
|
|
|
+ content: records,
|
|
|
+ metadata: {
|
|
|
+ total: Number(total),
|
|
|
+ page: Number(page),
|
|
|
+ size: Number(size)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 验证邀请者是否存在
|
|
|
+ */
|
|
|
+ async validateInviter(inviterId: number): Promise<boolean> {
|
|
|
+ const inviter = await this.userRepository.findOne({
|
|
|
+ where: { id: inviterId }
|
|
|
+ })
|
|
|
+ return !!inviter
|
|
|
+ }
|
|
|
+}
|