This commit is contained in:
parent
72f6d19a5f
commit
76cd29b088
|
|
@ -10,11 +10,21 @@ public class CommissionQueryRequest : PagedRequest
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public long? UserId { get; set; }
|
public long? UserId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获得佣金的用户UID
|
||||||
|
/// </summary>
|
||||||
|
public string? UserUid { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 来源用户ID
|
/// 来源用户ID
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public long? FromUserId { get; set; }
|
public long? FromUserId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 来源用户UID
|
||||||
|
/// </summary>
|
||||||
|
public string? FromUserUid { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 关联订单ID
|
/// 关联订单ID
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -846,12 +846,24 @@ public class DistributionService : IDistributionService
|
||||||
query = query.Where(c => c.UserId == request.UserId.Value);
|
query = query.Where(c => c.UserId == request.UserId.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 按获得佣金的用户UID筛选
|
||||||
|
if (!string.IsNullOrWhiteSpace(request.UserUid))
|
||||||
|
{
|
||||||
|
query = query.Where(c => c.User != null && c.User.Uid.Contains(request.UserUid));
|
||||||
|
}
|
||||||
|
|
||||||
// 按来源用户ID筛选
|
// 按来源用户ID筛选
|
||||||
if (request.FromUserId.HasValue)
|
if (request.FromUserId.HasValue)
|
||||||
{
|
{
|
||||||
query = query.Where(c => c.FromUserId == request.FromUserId.Value);
|
query = query.Where(c => c.FromUserId == request.FromUserId.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 按来源用户UID筛选
|
||||||
|
if (!string.IsNullOrWhiteSpace(request.FromUserUid))
|
||||||
|
{
|
||||||
|
query = query.Where(c => c.FromUser != null && c.FromUser.Uid.Contains(request.FromUserUid));
|
||||||
|
}
|
||||||
|
|
||||||
// 按订单ID筛选
|
// 按订单ID筛选
|
||||||
if (request.OrderId.HasValue)
|
if (request.OrderId.HasValue)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -36,20 +36,20 @@
|
||||||
<!-- 搜索表单 -->
|
<!-- 搜索表单 -->
|
||||||
<el-card class="search-card" shadow="never">
|
<el-card class="search-card" shadow="never">
|
||||||
<el-form :model="queryParams" inline>
|
<el-form :model="queryParams" inline>
|
||||||
<el-form-item label="用户ID">
|
<el-form-item label="用户UID">
|
||||||
<el-input v-model.number="queryParams.userId" placeholder="请输入用户ID" clearable />
|
<el-input v-model="queryParams.userUid" placeholder="请输入用户UID" clearable />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="来源用户ID">
|
<el-form-item label="来源用户UID">
|
||||||
<el-input v-model.number="queryParams.fromUserId" placeholder="请输入来源用户ID" clearable />
|
<el-input v-model="queryParams.fromUserUid" placeholder="请输入来源用户UID" clearable />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="订单ID">
|
<el-form-item label="订单ID">
|
||||||
<el-input v-model.number="queryParams.orderId" placeholder="请输入订单ID" clearable />
|
<el-input v-model.number="queryParams.orderId" placeholder="请输入订单ID" clearable />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="层级">
|
<el-form-item label="层级">
|
||||||
<DictSelect v-model="queryParams.level" dict-type="commission_level" placeholder="请选择层级" clearable />
|
<DictSelect v-model="queryParams.level" type="commission_level" placeholder="请选择层级" clearable />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="状态">
|
<el-form-item label="状态">
|
||||||
<DictSelect v-model="queryParams.status" dict-type="commission_status" placeholder="请选择状态" clearable />
|
<DictSelect v-model="queryParams.status" type="commission_status" placeholder="请选择状态" clearable />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="创建时间">
|
<el-form-item label="创建时间">
|
||||||
<el-date-picker v-model="dateRange" type="daterange" range-separator="至" start-placeholder="开始日期"
|
<el-date-picker v-model="dateRange" type="daterange" range-separator="至" start-placeholder="开始日期"
|
||||||
|
|
@ -169,8 +169,8 @@ const dateRange = ref<[string, string] | null>(null)
|
||||||
const queryParams = reactive<CommissionQuery>({
|
const queryParams = reactive<CommissionQuery>({
|
||||||
page: 1,
|
page: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
userId: undefined,
|
userUid: undefined,
|
||||||
fromUserId: undefined,
|
fromUserUid: undefined,
|
||||||
orderId: undefined,
|
orderId: undefined,
|
||||||
level: undefined,
|
level: undefined,
|
||||||
status: undefined,
|
status: undefined,
|
||||||
|
|
@ -217,8 +217,8 @@ const handleDateChange = (val: [string, string] | null) => {
|
||||||
|
|
||||||
const handleSearch = () => { queryParams.page = 1; fetchData() }
|
const handleSearch = () => { queryParams.page = 1; fetchData() }
|
||||||
const handleReset = () => {
|
const handleReset = () => {
|
||||||
queryParams.userId = undefined
|
queryParams.userUid = undefined
|
||||||
queryParams.fromUserId = undefined
|
queryParams.fromUserUid = undefined
|
||||||
queryParams.orderId = undefined
|
queryParams.orderId = undefined
|
||||||
queryParams.level = undefined
|
queryParams.level = undefined
|
||||||
queryParams.status = undefined
|
queryParams.status = undefined
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,8 @@
|
||||||
padding: 34px 20px 14px;
|
padding: 34px 20px 14px;
|
||||||
position: relative;
|
position: relative;
|
||||||
background: #FFF5F5;
|
background: #FFF5F5;
|
||||||
|
flex: 1;
|
||||||
|
min-height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.la-conclusion-badge {
|
.la-conclusion-badge {
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ public class InviteService : IInviteService
|
||||||
private readonly IWechatService _wechatService;
|
private readonly IWechatService _wechatService;
|
||||||
private readonly HttpClient _httpClient;
|
private readonly HttpClient _httpClient;
|
||||||
private readonly IUploadConfigService _uploadConfigService;
|
private readonly IUploadConfigService _uploadConfigService;
|
||||||
|
private readonly IConfigService _configService;
|
||||||
|
|
||||||
// 微信小程序码API
|
// 微信小程序码API
|
||||||
private const string WxacodeUnlimitUrl = "https://api.weixin.qq.com/wxa/getwxacodeunlimit";
|
private const string WxacodeUnlimitUrl = "https://api.weixin.qq.com/wxa/getwxacodeunlimit";
|
||||||
|
|
@ -35,23 +36,20 @@ public class InviteService : IInviteService
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 构造函数
|
/// 构造函数
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dbContext">数据库上下文</param>
|
|
||||||
/// <param name="logger">日志记录器</param>
|
|
||||||
/// <param name="wechatService">微信服务</param>
|
|
||||||
/// <param name="httpClient">HTTP客户端</param>
|
|
||||||
/// <param name="uploadConfigService">上传配置服务</param>
|
|
||||||
public InviteService(
|
public InviteService(
|
||||||
MiAssessmentDbContext dbContext,
|
MiAssessmentDbContext dbContext,
|
||||||
ILogger<InviteService> logger,
|
ILogger<InviteService> logger,
|
||||||
IWechatService wechatService,
|
IWechatService wechatService,
|
||||||
HttpClient httpClient,
|
HttpClient httpClient,
|
||||||
IUploadConfigService uploadConfigService)
|
IUploadConfigService uploadConfigService,
|
||||||
|
IConfigService configService)
|
||||||
{
|
{
|
||||||
_dbContext = dbContext;
|
_dbContext = dbContext;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_wechatService = wechatService;
|
_wechatService = wechatService;
|
||||||
_httpClient = httpClient;
|
_httpClient = httpClient;
|
||||||
_uploadConfigService = uploadConfigService;
|
_uploadConfigService = uploadConfigService;
|
||||||
|
_configService = configService;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|
@ -378,25 +376,29 @@ public class InviteService : IInviteService
|
||||||
{
|
{
|
||||||
_logger.LogDebug("申请提现,userId: {UserId}, amount: {Amount}", userId, amount);
|
_logger.LogDebug("申请提现,userId: {UserId}, amount: {Amount}", userId, amount);
|
||||||
|
|
||||||
// 验证提现金额≥1元 (Requirement 13.2)
|
// 从配置读取最低提现金额
|
||||||
if (amount < 1)
|
var minAmountStr = await _configService.GetConfigValueAsync("withdraw_min_amount");
|
||||||
|
var minAmount = decimal.TryParse(minAmountStr, out var ma) ? ma : 1m;
|
||||||
|
|
||||||
|
// 验证提现金额≥最低限额
|
||||||
|
if (amount < minAmount)
|
||||||
{
|
{
|
||||||
_logger.LogWarning("提现金额小于最低限额,userId: {UserId}, amount: {Amount}", userId, amount);
|
_logger.LogWarning("提现金额小于最低限额,userId: {UserId}, amount: {Amount}, minAmount: {MinAmount}", userId, amount, minAmount);
|
||||||
return new ApplyWithdrawResponse
|
return new ApplyWithdrawResponse
|
||||||
{
|
{
|
||||||
Success = false,
|
Success = false,
|
||||||
ErrorMessage = "提现金额不能小于1元"
|
ErrorMessage = $"提现金额不能小于{minAmount}元"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// 验证提现金额为整数 (Requirement 13.3)
|
// 验证提现金额最多2位小数
|
||||||
if (amount != Math.Floor(amount))
|
if (Math.Round(amount, 2) != amount)
|
||||||
{
|
{
|
||||||
_logger.LogWarning("提现金额不是整数,userId: {UserId}, amount: {Amount}", userId, amount);
|
_logger.LogWarning("提现金额小数位超过2位,userId: {UserId}, amount: {Amount}", userId, amount);
|
||||||
return new ApplyWithdrawResponse
|
return new ApplyWithdrawResponse
|
||||||
{
|
{
|
||||||
Success = false,
|
Success = false,
|
||||||
ErrorMessage = "提现金额必须为整数"
|
ErrorMessage = "提现金额最多保留2位小数"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -230,7 +230,8 @@ public class ServiceModule : Module
|
||||||
var wechatService = c.Resolve<IWechatService>();
|
var wechatService = c.Resolve<IWechatService>();
|
||||||
var httpClientFactory = c.Resolve<System.Net.Http.IHttpClientFactory>();
|
var httpClientFactory = c.Resolve<System.Net.Http.IHttpClientFactory>();
|
||||||
var uploadConfigService = c.Resolve<IUploadConfigService>();
|
var uploadConfigService = c.Resolve<IUploadConfigService>();
|
||||||
return new InviteService(dbContext, logger, wechatService, httpClientFactory.CreateClient(), uploadConfigService);
|
var configService = c.Resolve<Core.Interfaces.IConfigService>();
|
||||||
|
return new InviteService(dbContext, logger, wechatService, httpClientFactory.CreateClient(), uploadConfigService, configService);
|
||||||
}).As<IInviteService>().InstancePerLifetimeScope();
|
}).As<IInviteService>().InstancePerLifetimeScope();
|
||||||
|
|
||||||
// ========== 小程序系统模块服务注册 ==========
|
// ========== 小程序系统模块服务注册 ==========
|
||||||
|
|
|
||||||
|
|
@ -128,9 +128,9 @@ async function loadCommissionInfo() {
|
||||||
const res = await getCommission()
|
const res = await getCommission()
|
||||||
if (res.code === 0 && res.data) {
|
if (res.code === 0 && res.data) {
|
||||||
commissionInfo.value = {
|
commissionInfo.value = {
|
||||||
withdrawn: res.data.withdrawn || 0,
|
withdrawn: res.data.withdrawnAmount || 0,
|
||||||
pending: res.data.pending || 0,
|
pending: res.data.pendingAmount || 0,
|
||||||
total: res.data.total || 0
|
total: res.data.totalIncome || 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
@ -302,9 +302,14 @@ function handleShowWithdraw() {
|
||||||
function handleCloseWithdraw() { showWithdrawPopup.value = false }
|
function handleCloseWithdraw() { showWithdrawPopup.value = false }
|
||||||
|
|
||||||
async function handleSubmitWithdraw() {
|
async function handleSubmitWithdraw() {
|
||||||
const amount = parseInt(withdrawAmount.value)
|
const amount = parseFloat(withdrawAmount.value)
|
||||||
if (!amount || amount < 1) {
|
if (!amount || isNaN(amount) || amount <= 0) {
|
||||||
uni.showToast({ title: '最低提现1元', icon: 'none' })
|
uni.showToast({ title: '请输入有效金额', icon: 'none' })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 最多2位小数
|
||||||
|
if (Math.round(amount * 100) / 100 !== amount) {
|
||||||
|
uni.showToast({ title: '金额最多保留2位小数', icon: 'none' })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (amount > commissionInfo.value.pending) {
|
if (amount > commissionInfo.value.pending) {
|
||||||
|
|
@ -513,9 +518,9 @@ onMounted(() => { userStore.restoreFromStorage() })
|
||||||
<view class="popup-container withdraw-popup" @click.stop>
|
<view class="popup-container withdraw-popup" @click.stop>
|
||||||
<text class="withdraw-title">请输入提现金额</text>
|
<text class="withdraw-title">请输入提现金额</text>
|
||||||
<view class="withdraw-input-wrap">
|
<view class="withdraw-input-wrap">
|
||||||
<input class="withdraw-input" type="number" v-model="withdrawAmount" placeholder="请输入" placeholder-class="input-placeholder" />
|
<input class="withdraw-input" type="digit" v-model="withdrawAmount" placeholder="请输入金额" placeholder-class="input-placeholder" />
|
||||||
</view>
|
</view>
|
||||||
<text class="withdraw-tip">每次提现最低一元起</text>
|
<text class="withdraw-tip">提现金额支持2位小数</text>
|
||||||
<view class="withdraw-submit" :class="{ disabled: withdrawLoading }" @click="handleSubmitWithdraw">
|
<view class="withdraw-submit" :class="{ disabled: withdrawLoading }" @click="handleSubmitWithdraw">
|
||||||
<text>申请提现</text>
|
<text>申请提现</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user