This commit is contained in:
zpc 2026-02-06 16:02:18 +08:00
parent 63d0c0d9bf
commit 8aa7983ee0
7 changed files with 166 additions and 16 deletions

View File

@ -452,6 +452,27 @@ public class UserController : BusinessControllerBase
}
}
/// <summary>
/// 获取用户哈尼券流水明细
/// </summary>
/// <param name="id">用户ID</param>
/// <param name="query">查询参数</param>
/// <returns>流水明细列表</returns>
[HttpGet("{id:int}/money2-detail")]
[BusinessPermission("user:view")]
public async Task<IActionResult> 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);
}
}
/// <summary>
/// 获取用户IP登录历史
/// </summary>

View File

@ -149,7 +149,15 @@ public interface IUserBusinessService
Task<PagedResult<MoneyDetailItem>> GetUserIntegralDetailAsync(int userId, MoneyDetailQuery query);
/// <summary>
/// 获取用户钻石流水明细
/// 获取用户哈尼券流水明细
/// </summary>
/// <param name="userId">用户ID</param>
/// <param name="query">查询参数</param>
/// <returns>流水明细列表</returns>
Task<PagedResult<MoneyDetailItem>> GetUserMoney2DetailAsync(int userId, MoneyDetailQuery query);
/// <summary>
/// 获取用户钻石流水明细已废弃请使用GetUserMoney2DetailAsync
/// </summary>
/// <param name="userId">用户ID</param>
/// <param name="query">查询参数</param>

View File

@ -875,6 +875,75 @@ public class UserBusinessService : IUserBusinessService
return PagedResult<MoneyDetailItem>.Create(details, total, query.Page, query.PageSize);
}
/// <inheritdoc />
public async Task<PagedResult<MoneyDetailItem>> 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<MoneyDetailItem>.Create(details, total, query.Page, query.PageSize);
}
/// <inheritdoc />
public async Task<PagedResult<MoneyDetailItem>> GetUserScoreDetailAsync(int userId, MoneyDetailQuery query)
{

View File

@ -376,6 +376,15 @@ export function getUserScoreDetail(id: number, params: MoneyDetailQuery): Promis
})
}
/** 获取用户哈尼券流水明细 */
export function getUserMoney2Detail(id: number, params: MoneyDetailQuery): Promise<ApiResponse<PagedResult<MoneyDetailItem>>> {
return request({
url: `/admin/business/users/${id}/money2-detail`,
method: 'get',
params
})
}
// ==================== IP登录历史相关 ====================
/** IP登录历史项 */

View File

@ -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<MoneyDetailQuery>({
//
const typeLabel = computed(() => {
const labels: Record<string, string> = {
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)

View File

@ -127,7 +127,8 @@
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="gift:coupon">赠送优惠券</el-dropdown-item>
<el-dropdown-item command="gift:card">赠送卡牌</el-dropdown-item>
<!-- 赠送卡牌功能暂时隐藏 -->
<!-- <el-dropdown-item command="gift:card">赠送卡牌</el-dropdown-item> -->
</el-dropdown-menu>
</template>
</el-dropdown>
@ -141,9 +142,9 @@
<el-dropdown-item command="view:team">查看下级</el-dropdown-item>
<el-dropdown-item command="view:box">查看盒柜</el-dropdown-item>
<el-dropdown-item command="view:orders">查看订单</el-dropdown-item>
<el-dropdown-item command="view:moneyDetail">余额流水明细</el-dropdown-item>
<el-dropdown-item command="view:integralDetail">积分流水明细</el-dropdown-item>
<el-dropdown-item command="view:diamondDetail">钻石流水明细</el-dropdown-item>
<el-dropdown-item command="view:moneyDetail">钻石流水明细</el-dropdown-item>
<el-dropdown-item command="view:integralDetail">HH币流水明细</el-dropdown-item>
<el-dropdown-item command="view:diamondDetail">哈尼券流水明细</el-dropdown-item>
<el-dropdown-item command="view:ipLogs">查看IP登录列表</el-dropdown-item>
</el-dropdown-menu>
</template>

View File

@ -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);
}
/// <summary>
/// 发放货币类型奖品GoodsType=3
/// 货币类型奖品直接使用ScMoney字段的值作为钻石/余额发放
/// </summary>
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);
}
}