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);
+ }
}