From 8aa7983ee05f6e8eaea75e4127802e3d5ab899fb Mon Sep 17 00:00:00 2001 From: zpc Date: Fri, 6 Feb 2026 16:02:18 +0800 Subject: [PATCH] 213 --- .../Controllers/UserController.cs | 21 ++++++ .../Interfaces/IUserBusinessService.cs | 10 ++- .../Services/UserBusinessService.cs | 69 +++++++++++++++++++ .../admin-web/src/api/business/user.ts | 9 +++ .../user/components/MoneyDetailDialog.vue | 12 ++-- .../business/user/components/UserTable.vue | 9 +-- .../WelfareLotteryService.cs | 52 ++++++++++++-- 7 files changed, 166 insertions(+), 16 deletions(-) diff --git a/server/HoneyBox/src/HoneyBox.Admin.Business/Controllers/UserController.cs b/server/HoneyBox/src/HoneyBox.Admin.Business/Controllers/UserController.cs index 4a89add7..27b0cd19 100644 --- a/server/HoneyBox/src/HoneyBox.Admin.Business/Controllers/UserController.cs +++ b/server/HoneyBox/src/HoneyBox.Admin.Business/Controllers/UserController.cs @@ -452,6 +452,27 @@ public class UserController : BusinessControllerBase } } + /// + /// 获取用户哈尼券流水明细 + /// + /// 用户ID + /// 查询参数 + /// 流水明细列表 + [HttpGet("{id:int}/money2-detail")] + [BusinessPermission("user:view")] + public async Task GetUserMoney2Detail(int id, [FromQuery] MoneyDetailQuery query) + { + try + { + var result = await _userService.GetUserMoney2DetailAsync(id, query); + return Ok(result); + } + catch (BusinessException ex) + { + return Error(ex.Code, ex.Message); + } + } + /// /// 获取用户IP登录历史 /// diff --git a/server/HoneyBox/src/HoneyBox.Admin.Business/Services/Interfaces/IUserBusinessService.cs b/server/HoneyBox/src/HoneyBox.Admin.Business/Services/Interfaces/IUserBusinessService.cs index 515686f6..e76f5054 100644 --- a/server/HoneyBox/src/HoneyBox.Admin.Business/Services/Interfaces/IUserBusinessService.cs +++ b/server/HoneyBox/src/HoneyBox.Admin.Business/Services/Interfaces/IUserBusinessService.cs @@ -149,7 +149,15 @@ public interface IUserBusinessService Task> GetUserIntegralDetailAsync(int userId, MoneyDetailQuery query); /// - /// 获取用户钻石流水明细 + /// 获取用户哈尼券流水明细 + /// + /// 用户ID + /// 查询参数 + /// 流水明细列表 + Task> GetUserMoney2DetailAsync(int userId, MoneyDetailQuery query); + + /// + /// 获取用户钻石流水明细(已废弃,请使用GetUserMoney2DetailAsync) /// /// 用户ID /// 查询参数 diff --git a/server/HoneyBox/src/HoneyBox.Admin.Business/Services/UserBusinessService.cs b/server/HoneyBox/src/HoneyBox.Admin.Business/Services/UserBusinessService.cs index eda9868e..ac1980f6 100644 --- a/server/HoneyBox/src/HoneyBox.Admin.Business/Services/UserBusinessService.cs +++ b/server/HoneyBox/src/HoneyBox.Admin.Business/Services/UserBusinessService.cs @@ -875,6 +875,75 @@ public class UserBusinessService : IUserBusinessService return PagedResult.Create(details, total, query.Page, query.PageSize); } + /// + public async Task> GetUserMoney2DetailAsync(int userId, MoneyDetailQuery query) + { + // 验证用户存在 + var userExists = await _dbContext.Users.AnyAsync(u => u.Id == userId); + if (!userExists) + { + throw new BusinessException(BusinessErrorCodes.NotFound, "用户不存在"); + } + + var detailQuery = _dbContext.ProfitMoney2s + .AsNoTracking() + .Where(pm => pm.UserId == userId); + + // 应用过滤条件 + if (query.Type.HasValue) + { + detailQuery = detailQuery.Where(pm => pm.Type == query.Type.Value); + } + + if (!string.IsNullOrWhiteSpace(query.ChangeType)) + { + if (query.ChangeType == "add") + { + detailQuery = detailQuery.Where(pm => pm.ChangeMoney > 0); + } + else if (query.ChangeType == "sub") + { + detailQuery = detailQuery.Where(pm => pm.ChangeMoney < 0); + } + } + + if (!string.IsNullOrWhiteSpace(query.Content)) + { + detailQuery = detailQuery.Where(pm => pm.Content != null && pm.Content.Contains(query.Content)); + } + + if (query.StartTime.HasValue) + { + detailQuery = detailQuery.Where(pm => pm.CreatedAt >= query.StartTime.Value); + } + + if (query.EndTime.HasValue) + { + var endDate = query.EndTime.Value.Date.AddDays(1); + detailQuery = detailQuery.Where(pm => pm.CreatedAt < endDate); + } + + var total = await detailQuery.CountAsync(); + + var details = await detailQuery + .OrderByDescending(pm => pm.Id) + .Skip(query.Skip) + .Take(query.PageSize) + .Select(pm => new MoneyDetailItem + { + Id = pm.Id, + ChangeMoney = pm.ChangeMoney, + Money = pm.Money, + Type = pm.Type, + Content = pm.Content ?? "", + Other = pm.Other, + Addtime = pm.CreatedAt + }) + .ToListAsync(); + + return PagedResult.Create(details, total, query.Page, query.PageSize); + } + /// public async Task> GetUserScoreDetailAsync(int userId, MoneyDetailQuery query) { diff --git a/server/HoneyBox/src/HoneyBox.Admin/admin-web/src/api/business/user.ts b/server/HoneyBox/src/HoneyBox.Admin/admin-web/src/api/business/user.ts index 9ecb639d..75d24334 100644 --- a/server/HoneyBox/src/HoneyBox.Admin/admin-web/src/api/business/user.ts +++ b/server/HoneyBox/src/HoneyBox.Admin/admin-web/src/api/business/user.ts @@ -376,6 +376,15 @@ export function getUserScoreDetail(id: number, params: MoneyDetailQuery): Promis }) } +/** 获取用户哈尼券流水明细 */ +export function getUserMoney2Detail(id: number, params: MoneyDetailQuery): Promise>> { + return request({ + url: `/admin/business/users/${id}/money2-detail`, + method: 'get', + params + }) +} + // ==================== IP登录历史相关 ==================== /** IP登录历史项 */ diff --git a/server/HoneyBox/src/HoneyBox.Admin/admin-web/src/views/business/user/components/MoneyDetailDialog.vue b/server/HoneyBox/src/HoneyBox.Admin/admin-web/src/views/business/user/components/MoneyDetailDialog.vue index 366750b7..15dcb1d5 100644 --- a/server/HoneyBox/src/HoneyBox.Admin/admin-web/src/views/business/user/components/MoneyDetailDialog.vue +++ b/server/HoneyBox/src/HoneyBox.Admin/admin-web/src/views/business/user/components/MoneyDetailDialog.vue @@ -111,7 +111,7 @@ import { User } from '@element-plus/icons-vue' import { getUserMoneyDetail, getUserIntegralDetail, - getUserScoreDetail, + getUserMoney2Detail, type UserListItem, type MoneyDetailQuery, type MoneyDetailItem @@ -152,11 +152,11 @@ const queryParams = reactive({ // 类型标签 const typeLabel = computed(() => { const labels: Record = { - money: '余额', - integral: '积分', - diamond: '钻石' + money: '钻石', + integral: 'HH币', + diamond: '哈尼券' } - return labels[props.type] || '余额' + return labels[props.type] || '钻石' }) // 对话框标题 @@ -215,7 +215,7 @@ const fetchData = async () => { res = await getUserIntegralDetail(props.user.id, queryParams) break case 'diamond': - res = await getUserScoreDetail(props.user.id, queryParams) + res = await getUserMoney2Detail(props.user.id, queryParams) break default: res = await getUserMoneyDetail(props.user.id, queryParams) diff --git a/server/HoneyBox/src/HoneyBox.Admin/admin-web/src/views/business/user/components/UserTable.vue b/server/HoneyBox/src/HoneyBox.Admin/admin-web/src/views/business/user/components/UserTable.vue index e9aeced2..2799d106 100644 --- a/server/HoneyBox/src/HoneyBox.Admin/admin-web/src/views/business/user/components/UserTable.vue +++ b/server/HoneyBox/src/HoneyBox.Admin/admin-web/src/views/business/user/components/UserTable.vue @@ -127,7 +127,8 @@ @@ -141,9 +142,9 @@ 查看下级 查看盒柜 查看订单 - 余额流水明细 - 积分流水明细 - 钻石流水明细 + 钻石流水明细 + HH币流水明细 + 哈尼券流水明细 查看IP登录列表 diff --git a/server/HoneyBox/src/HoneyBox.Api/BackgroundServices/WelfareLotteryService.cs b/server/HoneyBox/src/HoneyBox.Api/BackgroundServices/WelfareLotteryService.cs index ecf437e1..4ced7404 100644 --- a/server/HoneyBox/src/HoneyBox.Api/BackgroundServices/WelfareLotteryService.cs +++ b/server/HoneyBox/src/HoneyBox.Api/BackgroundServices/WelfareLotteryService.cs @@ -175,15 +175,28 @@ public class WelfareLotteryService : BackgroundService continue; } - // 发放奖励(如果有reward_id) - if (!string.IsNullOrEmpty(prize.RewardId) && int.TryParse(prize.RewardId, out var rewardId) && rewardId > 0) + // 发放奖励 + // 1. 如果是货币类型奖品(GoodsType=3),直接发放ScMoney金额 + if (prize.GoodsType == 3 && prize.ScMoney > 0) + { + await SendCurrencyPrizeAsync(dbContext, participant.UserId, prize.ScMoney, + $"{goods.Title}开奖-{prize.Title}", stoppingToken); + _logger.LogInformation("发放货币奖品成功: GoodsId={GoodsId}, UserId={UserId}, Prize={Prize}, Amount={Amount}", + goods.Id, participant.UserId, prize.Title, prize.ScMoney); + } + // 2. 如果有reward_id,通过奖励配置发放 + else if (!string.IsNullOrEmpty(prize.RewardId) && int.TryParse(prize.RewardId, out var rewardId) && rewardId > 0) { await SendRewardAsync(dbContext, participant.UserId, rewardId, $"{goods.Title}开奖", stoppingToken); + _logger.LogInformation("发放奖励成功: GoodsId={GoodsId}, UserId={UserId}, Prize={Prize}, RewardId={RewardId}", + goods.Id, participant.UserId, prize.Title, rewardId); + } + else + { + _logger.LogInformation("发放奖品成功: GoodsId={GoodsId}, UserId={UserId}, Prize={Prize}", + goods.Id, participant.UserId, prize.Title); } - - _logger.LogInformation("发放奖品成功: GoodsId={GoodsId}, UserId={UserId}, Prize={Prize}", - goods.Id, participant.UserId, prize.Title); prizeIndex++; } @@ -273,4 +286,33 @@ public class WelfareLotteryService : BackgroundService await dbContext.SaveChangesAsync(stoppingToken); } + + /// + /// 发放货币类型奖品(GoodsType=3) + /// 货币类型奖品直接使用ScMoney字段的值作为钻石/余额发放 + /// + private async Task SendCurrencyPrizeAsync( + HoneyBoxDbContext dbContext, + int userId, + decimal amount, + string remark, + CancellationToken stoppingToken) + { + var user = await dbContext.Users + .Where(u => u.Id == userId) + .FirstOrDefaultAsync(stoppingToken); + + if (user == null) + { + _logger.LogWarning("用户不存在: UserId={UserId}", userId); + return; + } + + // 货币类型奖品默认发放钻石/余额 + user.Money += amount; + _logger.LogInformation("发放货币奖品(钻石): UserId={UserId}, Amount={Amount}, Remark={Remark}", + userId, amount, remark); + + await dbContext.SaveChangesAsync(stoppingToken); + } }