321
This commit is contained in:
parent
633d47fa12
commit
4a80fc27ca
|
|
@ -151,5 +151,12 @@ namespace CoreCms.Net.Model.Entities
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Display(Name = "订单id")]
|
[Display(Name = "订单id")]
|
||||||
public string paymentId { get; set; }
|
public string paymentId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 签到时间
|
||||||
|
/// </summary>
|
||||||
|
[Display(Name = "签到时间")]
|
||||||
|
public System.DateTime? check_reservation { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -164,9 +164,6 @@ namespace CoreCms.Net.Model.Entities
|
||||||
[Display(Name = "是否禁烟:0=不限制,1=禁烟,2=不禁烟")]
|
[Display(Name = "是否禁烟:0=不限制,1=禁烟,2=不禁烟")]
|
||||||
|
|
||||||
[Required(ErrorMessage = "请输入{0}")]
|
[Required(ErrorMessage = "请输入{0}")]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public System.Int32 is_smoking { get; set; }
|
public System.Int32 is_smoking { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -174,11 +171,7 @@ namespace CoreCms.Net.Model.Entities
|
||||||
/// 性别限制:0=不限,1=男,2=女
|
/// 性别限制:0=不限,1=男,2=女
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Display(Name = "性别限制:0=不限,1=男,2=女")]
|
[Display(Name = "性别限制:0=不限,1=男,2=女")]
|
||||||
|
|
||||||
[Required(ErrorMessage = "请输入{0}")]
|
[Required(ErrorMessage = "请输入{0}")]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public System.Int32 gender_limit { get; set; }
|
public System.Int32 gender_limit { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -186,11 +179,6 @@ namespace CoreCms.Net.Model.Entities
|
||||||
/// 最低信誉分
|
/// 最低信誉分
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Display(Name = "最低信誉分")]
|
[Display(Name = "最低信誉分")]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public System.Decimal? credit_limit { get; set; }
|
public System.Decimal? credit_limit { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* Project: CoreCms
|
* Project: CoreCms
|
||||||
* ProjectName: 核心内容管理系统
|
* ProjectName: 核心内容管理系统
|
||||||
* Web: https://www.corecms.net
|
* Web: https://www.corecms.net
|
||||||
|
|
@ -133,6 +133,12 @@ namespace CoreCms.Net.Repository
|
||||||
isDelete = p.isDelete,
|
isDelete = p.isDelete,
|
||||||
type = (int)sWeChatInfo.type,
|
type = (int)sWeChatInfo.type,
|
||||||
parentNickName = sParentUser.nickName,
|
parentNickName = sParentUser.nickName,
|
||||||
|
dove_count=p.dove_count,
|
||||||
|
credit_score=p.credit_score,
|
||||||
|
pending_earnings=p.pending_earnings,
|
||||||
|
play_level=p.play_level,
|
||||||
|
skills_level=p.skills_level,
|
||||||
|
withdrawn_earnings=p.withdrawn_earnings,
|
||||||
childNum = SqlFunc.Subqueryable<CoreCmsUser>().Where(o => o.parentId == p.id).Count()
|
childNum = SqlFunc.Subqueryable<CoreCmsUser>().Where(o => o.parentId == p.id).Count()
|
||||||
})
|
})
|
||||||
.MergeTable().With(SqlWith.Null)
|
.MergeTable().With(SqlWith.Null)
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,10 @@
|
||||||
<div class="layui-form-item">
|
<div class="layui-form-item">
|
||||||
<label class="layui-form-label"><span class="x-red">*</span>房费</label>
|
<label class="layui-form-label"><span class="x-red">*</span>房费</label>
|
||||||
<div class="layui-input-block">
|
<div class="layui-input-block">
|
||||||
<input type="number" name="room_fee" id="room_fee" placeholder="请输入房费" class="layui-input" lay-verify="required|number" lay-reqtext="请输入房费" step="0.01" value="0">
|
<div style="display: flex; align-items: center; gap: 10px;">
|
||||||
|
<input type="number" name="room_fee" id="room_fee" placeholder="请输入房费" class="layui-input" lay-verify="required|number" lay-reqtext="请输入房费" step="0.01" value="0" style="flex: 1;">
|
||||||
|
<button type="button" class="layui-btn layui-btn-primary layui-btn-sm" id="calcBtn">计算10%佣金</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layui-form-item">
|
<div class="layui-form-item">
|
||||||
|
|
@ -57,12 +60,9 @@
|
||||||
<textarea name="remark" placeholder="请输入备注" class="layui-textarea"></textarea>
|
<textarea name="remark" placeholder="请输入备注" class="layui-textarea"></textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layui-form-item">
|
<!-- 隐藏的提交按钮,供弹窗底部按钮触发 -->
|
||||||
<div class="layui-input-block">
|
<div style="display: none;">
|
||||||
<button type="button" class="layui-btn" lay-submit lay-filter="LAY-app-SQEarnings-add-submit">提交</button>
|
<button type="button" class="layui-btn" lay-submit lay-filter="LAY-app-SQEarnings-add-submit" id="LAY-app-SQEarnings-add-submit">提交</button>
|
||||||
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
|
|
||||||
<button type="button" class="layui-btn layui-btn-primary" id="calcBtn">计算10%佣金</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
|
@ -133,6 +133,16 @@
|
||||||
var form = layui.form;
|
var form = layui.form;
|
||||||
var coreHelper = layui.coreHelper;
|
var coreHelper = layui.coreHelper;
|
||||||
|
|
||||||
|
// 检查是否有预选的用户信息(从用户列表页面传入)
|
||||||
|
if (d && d.data && d.data.preSelectedUser) {
|
||||||
|
var preUser = d.data.preSelectedUser;
|
||||||
|
$('#user_id').val(preUser.id);
|
||||||
|
$('#user_display').val(preUser.displayName);
|
||||||
|
// 默认设置为佣金类型
|
||||||
|
$('select[name="type"]').val('1');
|
||||||
|
form.render('select');
|
||||||
|
}
|
||||||
|
|
||||||
// 加载房间列表
|
// 加载房间列表
|
||||||
coreHelper.Post('Api/SQEarnings/GetRoomList', {}, function (res) {
|
coreHelper.Post('Api/SQEarnings/GetRoomList', {}, function (res) {
|
||||||
if (res.code === 0 && res.data) {
|
if (res.code === 0 && res.data) {
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,7 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
layui.data.done = function (d) {
|
layui.data.done = function (d) {
|
||||||
|
layui.use(['admin', 'table', 'dropdown', 'form', 'view', 'coreHelper'], function () {
|
||||||
var $ = layui.$;
|
var $ = layui.$;
|
||||||
var admin = layui.admin;
|
var admin = layui.admin;
|
||||||
var setter = layui.setter;
|
var setter = layui.setter;
|
||||||
|
|
@ -89,6 +90,7 @@
|
||||||
var dropdown = layui.dropdown;
|
var dropdown = layui.dropdown;
|
||||||
var form = layui.form;
|
var form = layui.form;
|
||||||
var view = layui.view;
|
var view = layui.view;
|
||||||
|
var coreHelper = layui.coreHelper;
|
||||||
|
|
||||||
table.render({
|
table.render({
|
||||||
elem: '#LAY-app-SQEarnings-tableBox',
|
elem: '#LAY-app-SQEarnings-tableBox',
|
||||||
|
|
@ -152,18 +154,13 @@
|
||||||
}
|
}
|
||||||
layer.confirm('确定要删除选中的数据吗?', function (index) {
|
layer.confirm('确定要删除选中的数据吗?', function (index) {
|
||||||
var ids = data.map(function (item) { return item.id; });
|
var ids = data.map(function (item) { return item.id; });
|
||||||
admin.req({
|
coreHelper.Post('Api/SQEarnings/DoBatchDelete', { id: ids }, function (res) {
|
||||||
url: layui.setter.apiUrl + 'Api/SQEarnings/DoBatchDelete',
|
|
||||||
data: JSON.stringify({ id: ids }),
|
|
||||||
type: 'post',
|
|
||||||
done: function (res) {
|
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
layer.msg('删除成功');
|
layer.msg('删除成功');
|
||||||
table.reload('LAY-app-SQEarnings-tableBox');
|
table.reload('LAY-app-SQEarnings-tableBox');
|
||||||
} else {
|
} else {
|
||||||
layer.msg(res.msg);
|
layer.msg(res.msg);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
layer.close(index);
|
layer.close(index);
|
||||||
});
|
});
|
||||||
|
|
@ -199,20 +196,16 @@
|
||||||
table.on('tool(LAY-app-SQEarnings-tableBox)', function (obj) {
|
table.on('tool(LAY-app-SQEarnings-tableBox)', function (obj) {
|
||||||
var data = obj.data;
|
var data = obj.data;
|
||||||
if (obj.event === 'del') {
|
if (obj.event === 'del') {
|
||||||
admin.req({
|
coreHelper.Post('Api/SQEarnings/DoDelete', { id: data.id }, function (res) {
|
||||||
url: layui.setter.apiUrl + 'Api/SQEarnings/DoDelete',
|
|
||||||
data: JSON.stringify({ id: data.id }),
|
|
||||||
type: 'post',
|
|
||||||
done: function (res) {
|
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
layer.msg('删除成功');
|
layer.msg('删除成功');
|
||||||
obj.del();
|
obj.del();
|
||||||
} else {
|
} else {
|
||||||
layer.msg(res.msg);
|
layer.msg(res.msg);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -88,12 +88,14 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
layui.data.done = function (d) {
|
layui.data.done = function (d) {
|
||||||
|
layui.use(['admin', 'table', 'dropdown', 'form', 'coreHelper'], function () {
|
||||||
var $ = layui.$;
|
var $ = layui.$;
|
||||||
var admin = layui.admin;
|
var admin = layui.admin;
|
||||||
var setter = layui.setter;
|
var setter = layui.setter;
|
||||||
var table = layui.table;
|
var table = layui.table;
|
||||||
var dropdown = layui.dropdown;
|
var dropdown = layui.dropdown;
|
||||||
var form = layui.form;
|
var form = layui.form;
|
||||||
|
var coreHelper = layui.coreHelper;
|
||||||
|
|
||||||
table.render({
|
table.render({
|
||||||
elem: '#LAY-app-SQWithdraw-tableBox',
|
elem: '#LAY-app-SQWithdraw-tableBox',
|
||||||
|
|
@ -139,18 +141,13 @@
|
||||||
}
|
}
|
||||||
layer.confirm('确定要删除选中的数据吗?', function (index) {
|
layer.confirm('确定要删除选中的数据吗?', function (index) {
|
||||||
var ids = data.map(function (item) { return item.id; });
|
var ids = data.map(function (item) { return item.id; });
|
||||||
admin.req({
|
coreHelper.Post('Api/SQWithdraw/DoBatchDelete', { id: ids }, function (res) {
|
||||||
url: layui.setter.apiUrl + 'Api/SQWithdraw/DoBatchDelete',
|
|
||||||
data: JSON.stringify({ id: ids }),
|
|
||||||
type: 'post',
|
|
||||||
done: function (res) {
|
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
layer.msg('删除成功');
|
layer.msg('删除成功');
|
||||||
table.reload('LAY-app-SQWithdraw-tableBox');
|
table.reload('LAY-app-SQWithdraw-tableBox');
|
||||||
} else {
|
} else {
|
||||||
layer.msg(res.msg);
|
layer.msg(res.msg);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
layer.close(index);
|
layer.close(index);
|
||||||
});
|
});
|
||||||
|
|
@ -162,33 +159,23 @@
|
||||||
table.on('tool(LAY-app-SQWithdraw-tableBox)', function (obj) {
|
table.on('tool(LAY-app-SQWithdraw-tableBox)', function (obj) {
|
||||||
var data = obj.data;
|
var data = obj.data;
|
||||||
if (obj.event === 'del') {
|
if (obj.event === 'del') {
|
||||||
admin.req({
|
coreHelper.Post('Api/SQWithdraw/DoDelete', { id: data.id }, function (res) {
|
||||||
url: layui.setter.apiUrl + 'Api/SQWithdraw/DoDelete',
|
|
||||||
data: JSON.stringify({ id: data.id }),
|
|
||||||
type: 'post',
|
|
||||||
done: function (res) {
|
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
layer.msg('删除成功');
|
layer.msg('删除成功');
|
||||||
obj.del();
|
obj.del();
|
||||||
} else {
|
} else {
|
||||||
layer.msg(res.msg);
|
layer.msg(res.msg);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
} else if (obj.event === 'approve') {
|
} else if (obj.event === 'approve') {
|
||||||
layer.confirm('确定已线下打款给该用户?', function (index) {
|
layer.confirm('确定已线下打款给该用户?', function (index) {
|
||||||
admin.req({
|
coreHelper.Post('Api/SQWithdraw/DoApprove', { id: data.id }, function (res) {
|
||||||
url: layui.setter.apiUrl + 'Api/SQWithdraw/DoApprove',
|
|
||||||
data: JSON.stringify({ id: data.id }),
|
|
||||||
type: 'post',
|
|
||||||
done: function (res) {
|
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
layer.msg('操作成功');
|
layer.msg('操作成功');
|
||||||
table.reload('LAY-app-SQWithdraw-tableBox');
|
table.reload('LAY-app-SQWithdraw-tableBox');
|
||||||
} else {
|
} else {
|
||||||
layer.msg(res.msg);
|
layer.msg(res.msg);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
layer.close(index);
|
layer.close(index);
|
||||||
});
|
});
|
||||||
|
|
@ -201,22 +188,18 @@
|
||||||
if (!value) {
|
if (!value) {
|
||||||
return layer.msg('请输入拒绝原因');
|
return layer.msg('请输入拒绝原因');
|
||||||
}
|
}
|
||||||
admin.req({
|
coreHelper.Post('Api/SQWithdraw/DoReject', { id: data.id, remark: value }, function (res) {
|
||||||
url: layui.setter.apiUrl + 'Api/SQWithdraw/DoReject',
|
|
||||||
data: JSON.stringify({ id: data.id, remark: value }),
|
|
||||||
type: 'post',
|
|
||||||
done: function (res) {
|
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
layer.msg('操作成功');
|
layer.msg('操作成功');
|
||||||
table.reload('LAY-app-SQWithdraw-tableBox');
|
table.reload('LAY-app-SQWithdraw-tableBox');
|
||||||
} else {
|
} else {
|
||||||
layer.msg(res.msg);
|
layer.msg(res.msg);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
layer.close(promptIndex);
|
layer.close(promptIndex);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -106,8 +106,7 @@
|
||||||
|
|
||||||
<script type="text/html" id="LAY-app-CoreCmsUser-tableBox-bar">
|
<script type="text/html" id="LAY-app-CoreCmsUser-tableBox-bar">
|
||||||
<a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a>
|
<a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a>
|
||||||
<a class="layui-btn layui-btn-xs" lay-event="editBalance">修改余额</a>
|
<a class="layui-btn layui-btn-xs layui-btn-normal" lay-event="addCommission">添加佣金</a>
|
||||||
<a class="layui-btn layui-btn-xs" lay-event="editPoint">修改积分</a>
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
@ -205,15 +204,41 @@
|
||||||
},
|
},
|
||||||
{ field: 'nickName', title: '昵称', sort: false },
|
{ field: 'nickName', title: '昵称', sort: false },
|
||||||
{
|
{
|
||||||
field: 'balance', title: '余额', sort: false, width: 70, templet: function (data) {
|
field: 'totalEarnings', title: '全部收益', sort: false, width: 90, templet: function (data) {
|
||||||
var html = '<a class="link-hot option-show balance" data-id="' + data.id + '">' + data.balance + '</a>';
|
var total = (parseFloat(data.pending_earnings) || 0) + (parseFloat(data.withdrawn_earnings) || 0);
|
||||||
return html;
|
return '<span class="layui-badge layui-badge-orange">' + total.toFixed(2) + '</span>';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'point', title: '积分', sort: false, width: 70, templet: function (data) {
|
field: 'pending_earnings', title: '待提现', sort: false, width: 90, templet: function (data) {
|
||||||
var html = '<a class="link-hot option-show point" data-id="' + data.id + '">' + data.point + '</a>';
|
return '<span class="layui-badge layui-badge-blue">' + (parseFloat(data.pending_earnings) || 0).toFixed(2) + '</span>';
|
||||||
return html;
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'withdrawn_earnings', title: '已提现', sort: false, width: 90, templet: function (data) {
|
||||||
|
return '<span class="layui-badge layui-badge-green">' + (parseFloat(data.withdrawn_earnings) || 0).toFixed(2) + '</span>';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'play_level', title: '牌品', sort: false, width: 80, templet: function (data) {
|
||||||
|
return (parseFloat(data.play_level) || 0).toFixed(1);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'skills_level', title: '牌技', sort: false, width: 80, templet: function (data) {
|
||||||
|
return (parseFloat(data.skills_level) || 0).toFixed(1);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'credit_score', title: '信誉分', sort: false, width: 80, templet: function (data) {
|
||||||
|
return '<span class="layui-badge layui-badge-cyan">' + (parseFloat(data.credit_score) || 0).toFixed(1) + '</span>';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'dove_count', title: '鸽子次数', sort: false, width: 90, templet: function (data) {
|
||||||
|
var count = parseInt(data.dove_count) || 0;
|
||||||
|
var badgeClass = count === 0 ? 'layui-badge-green' : (count <= 2 ? 'layui-badge-orange' : 'layui-badge');
|
||||||
|
return '<span class="layui-badge ' + badgeClass + '">' + count + '</span>';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -254,7 +279,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
//{ field: 'isDelete', title: '删除标志', width: 105, templet: '#switch_isDelete', sort: false, unresize: true },
|
//{ field: 'isDelete', title: '删除标志', width: 105, templet: '#switch_isDelete', sort: false, unresize: true },
|
||||||
{ width: 202, align: 'center', title: '操作', fixed: 'right', toolbar: '#LAY-app-CoreCmsUser-tableBox-bar' }
|
{ width: 140, align: 'center', title: '操作', fixed: 'right', toolbar: '#LAY-app-CoreCmsUser-tableBox-bar' }
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
@ -311,10 +336,8 @@
|
||||||
doDelete(obj);
|
doDelete(obj);
|
||||||
} else if (obj.event === 'edit') {
|
} else if (obj.event === 'edit') {
|
||||||
doEdit(obj)
|
doEdit(obj)
|
||||||
} else if (obj.event === 'editBalance') {
|
} else if (obj.event === 'addCommission') {
|
||||||
doEditBalance(obj);
|
doAddCommission(obj);
|
||||||
} else if (obj.event === 'editPoint') {
|
|
||||||
doEditPoint(obj)
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
//执行创建操作
|
//执行创建操作
|
||||||
|
|
@ -400,81 +423,71 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//执行编辑余额
|
//执行添加佣金
|
||||||
function doEditBalance(obj) {
|
function doAddCommission(obj) {
|
||||||
coreHelper.Post("Api/CoreCmsUser/GetEditBalance", { id: obj.data.id }, function (e) {
|
coreHelper.Post("Api/SQEarnings/GetCreate", null, function (e) {
|
||||||
if (e.code === 0) {
|
if (e.code === 0) {
|
||||||
admin.popup({
|
admin.popup({
|
||||||
shadeClose: false,
|
shadeClose: false,
|
||||||
title: '修改余额',
|
title: '添加佣金 - ' + (obj.data.nickName || '用户ID:' + obj.data.id),
|
||||||
area: ['500px', '300px'],
|
area: ['700px', '600px'],
|
||||||
id: 'LAY-popup-CoreCmsUser-EditBalance',
|
id: 'LAY-popup-CoreCmsUser-AddCommission',
|
||||||
success: function (layero, index) {
|
success: function (layero, index) {
|
||||||
view(this.id).render('user/userInfo/editBalance', { data: e.data }).done(function () {
|
// 传递用户信息到页面
|
||||||
//监听提交
|
var pageData = e.data || {};
|
||||||
form.on('submit(LAY-app-CoreCmsUser-editBalanceForm-submit)',
|
pageData.preSelectedUser = {
|
||||||
function (data) {
|
id: obj.data.id,
|
||||||
var field = data.field; //获取提交的字段
|
nickName: obj.data.nickName || '',
|
||||||
field.data = parseFloat(field.data).toFixed(2);
|
mobile: obj.data.mobile || '',
|
||||||
|
displayName: (obj.data.nickName || '') + '(ID: ' + obj.data.id + ')'
|
||||||
|
};
|
||||||
|
|
||||||
//提交 Ajax 成功后,关闭当前弹层并重载表格
|
view(this.id).render('user/sqearnings/add', { data: pageData }).done(function () {
|
||||||
coreHelper.Post("Api/CoreCmsUser/DoEditBalance", field, function (e) {
|
// 预填充用户信息和设置收益类型(add.html 中已处理,这里确保设置)
|
||||||
console.log(e)
|
if (pageData.preSelectedUser) {
|
||||||
if (e.code === 0) {
|
$('#user_id').val(pageData.preSelectedUser.id);
|
||||||
layui.table.reloadData('LAY-app-CoreCmsUser-tableBox'); //重载表格
|
$('#user_display').val(pageData.preSelectedUser.displayName);
|
||||||
layer.close(index); //再执行关闭
|
}
|
||||||
layer.msg(e.msg);
|
$('select[name="type"]').val('1');
|
||||||
|
form.render('select');
|
||||||
|
|
||||||
|
// 覆盖提交监听,确保 type=1 并刷新用户列表
|
||||||
|
form.on('submit(LAY-app-SQEarnings-add-submit)', function (data) {
|
||||||
|
var field = data.field;
|
||||||
|
var formData = {
|
||||||
|
user_id: parseInt(field.user_id),
|
||||||
|
room_id: field.room_select ? parseInt(field.room_select) : null,
|
||||||
|
room_number: field.room_number,
|
||||||
|
room_name: field.room_name,
|
||||||
|
room_fee: parseFloat(field.room_fee) || 0,
|
||||||
|
earnings: parseFloat(field.earnings) || 0,
|
||||||
|
type: 1, // 固定为佣金类型
|
||||||
|
remark: field.remark
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!formData.user_id || formData.user_id <= 0) {
|
||||||
|
return layer.msg('请选择用户');
|
||||||
|
}
|
||||||
|
if (formData.earnings <= 0) {
|
||||||
|
return layer.msg('收益金额必须大于0');
|
||||||
|
}
|
||||||
|
|
||||||
|
coreHelper.Post("Api/SQEarnings/DoCreate", formData, function (res) {
|
||||||
|
if (res.code === 0) {
|
||||||
|
layer.msg('添加佣金成功');
|
||||||
|
layui.table.reloadData('LAY-app-CoreCmsUser-tableBox');
|
||||||
|
layer.close(index);
|
||||||
} else {
|
} else {
|
||||||
layer.msg(e.msg);
|
layer.msg(res.msg);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
return false;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
})
|
|
||||||
}
|
}
|
||||||
, btn: ['确定', '取消']
|
, btn: ['确定', '取消']
|
||||||
, yes: function (index, layero) {
|
, yes: function (index, layero) {
|
||||||
layero.contents().find("#LAY-app-CoreCmsUser-editBalanceForm-submit").click();
|
layero.contents().find("#LAY-app-SQEarnings-add-submit").click();
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
layer.msg(e.msg);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
//执行编辑积分
|
|
||||||
function doEditPoint(obj) {
|
|
||||||
coreHelper.Post("Api/CoreCmsUser/GetEditPoint", { id: obj.data.id }, function (e) {
|
|
||||||
if (e.code === 0) {
|
|
||||||
admin.popup({
|
|
||||||
shadeClose: false,
|
|
||||||
title: '修改余额',
|
|
||||||
area: ['500px', '300px'],
|
|
||||||
id: 'LAY-popup-CoreCmsUser-EditPoint',
|
|
||||||
success: function (layero, index) {
|
|
||||||
view(this.id).render('user/userInfo/editPoint', { data: e.data }).done(function () {
|
|
||||||
//监听提交
|
|
||||||
form.on('submit(LAY-app-CoreCmsUser-editPointForm-submit)',
|
|
||||||
function (data) {
|
|
||||||
var field = data.field; //获取提交的字段
|
|
||||||
|
|
||||||
//提交 Ajax 成功后,关闭当前弹层并重载表格
|
|
||||||
coreHelper.Post("Api/CoreCmsUser/DoEditPoint", field, function (e) {
|
|
||||||
console.log(e)
|
|
||||||
if (e.code === 0) {
|
|
||||||
layui.table.reloadData('LAY-app-CoreCmsUser-tableBox'); //重载表格
|
|
||||||
layer.close(index); //再执行关闭
|
|
||||||
layer.msg(e.msg);
|
|
||||||
} else {
|
|
||||||
layer.msg(e.msg);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
})
|
|
||||||
}
|
|
||||||
, btn: ['确定', '取消']
|
|
||||||
, yes: function (index, layero) {
|
|
||||||
layero.contents().find("#LAY-app-CoreCmsUser-editPointForm-submit").click();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -506,53 +519,6 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//积分记录
|
|
||||||
$(document).on('click', '.point', function () {
|
|
||||||
var id = $(this).attr('data-id');
|
|
||||||
coreHelper.Post("Api/CoreCmsUser/GetDetailsPointLog", { id: id }, function (e) {
|
|
||||||
if (e.code === 0) {
|
|
||||||
admin.popup({
|
|
||||||
shadeClose: false,
|
|
||||||
title: '查看详情',
|
|
||||||
area: ['90%', '90%'],
|
|
||||||
id: 'LAY-popup-CoreCmsUser-details',
|
|
||||||
success: function (layero, index) {
|
|
||||||
view(this.id).render('user/userInfo/detailsPointLog', { data: e.data, id: id }).done(function () {
|
|
||||||
form.render();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
, btn: ['取消']
|
|
||||||
, btnAlign: 'c'
|
|
||||||
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
layer.msg(e.msg);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
//余额明细
|
|
||||||
$(document).on('click', '.balance', function () {
|
|
||||||
var id = $(this).attr('data-id');
|
|
||||||
coreHelper.Post("Api/CoreCmsUser/GetDetailsBalanceLog", { id: id }, function (e) {
|
|
||||||
if (e.code === 0) {
|
|
||||||
admin.popup({
|
|
||||||
shadeClose: false,
|
|
||||||
title: '查看详情',
|
|
||||||
area: ['90%', '90%'],
|
|
||||||
id: 'LAY-popup-CoreCmsUser-details',
|
|
||||||
success: function (layero, index) {
|
|
||||||
view(this.id).render('user/userInfo/detailsBalanceLog', { data: e.data, id: id }).done(function () {
|
|
||||||
form.render();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
, btn: ['取消']
|
|
||||||
, btnAlign: 'c'
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
layer.msg(e.msg);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
//执行单个删除
|
//执行单个删除
|
||||||
function doDelete(obj) {
|
function doDelete(obj) {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
|
|
||||||
using CoreCms.Net.Auth.HttpContextUser;
|
using CoreCms.Net.Auth.HttpContextUser;
|
||||||
using CoreCms.Net.IRepository.UnitOfWork;
|
using CoreCms.Net.IRepository.UnitOfWork;
|
||||||
|
|
@ -1387,7 +1387,8 @@ public class SQController : ControllerBase
|
||||||
await _SQReservationParticipantsServices.UpdateAsync(
|
await _SQReservationParticipantsServices.UpdateAsync(
|
||||||
it => new SQReservationParticipants
|
it => new SQReservationParticipants
|
||||||
{
|
{
|
||||||
is_arrive = 1
|
is_arrive = 1,
|
||||||
|
check_reservation=DateTime.Now
|
||||||
},
|
},
|
||||||
it => it.reservation_id == dto.reservation_id && it.status == 0 && it.user_id == userId);
|
it => it.reservation_id == dto.reservation_id && it.status == 0 && it.user_id == userId);
|
||||||
|
|
||||||
|
|
|
||||||
266
server/鸽子费审核功能需求文档.md
Normal file
266
server/鸽子费审核功能需求文档.md
Normal file
|
|
@ -0,0 +1,266 @@
|
||||||
|
# 鸽子费审核功能需求文档
|
||||||
|
|
||||||
|
## 📌 功能概述
|
||||||
|
|
||||||
|
开发后台鸽子费审核功能,允许员工审核未按时赴约用户的鸽子费处理。审核通过则扣除鸽子费并分发给已赴约用户,审核未通过则退还鸽子费。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 核心功能
|
||||||
|
|
||||||
|
### 1. 待审核列表展示
|
||||||
|
|
||||||
|
#### 1.1 筛选条件
|
||||||
|
- **用户状态**:`is_arrive = 2`(未赴约,待审核)
|
||||||
|
- **预约状态**:预约未结束或已结束但未处理
|
||||||
|
- **鸽子费条件**:`deposit_fee > 0`(有鸽子费的预约)
|
||||||
|
- **参与状态**:`status = 0`(未退出)
|
||||||
|
|
||||||
|
#### 1.2 列表显示字段
|
||||||
|
| 字段 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| 预约ID | reservation_id |
|
||||||
|
| 预约标题 | reservation.title |
|
||||||
|
| 用户ID | user_id |
|
||||||
|
| 用户昵称 | 关联用户表获取 |
|
||||||
|
| 用户手机号 | 关联用户表获取 |
|
||||||
|
| 鸽子费金额 | reservation.deposit_fee |
|
||||||
|
| 预约时间 | reservation.start_time ~ end_time |
|
||||||
|
| 标记时间 | 发起者签到时间(is_arrive=2的更新时间) |
|
||||||
|
| 操作按钮 | 审核通过 / 审核未通过 |
|
||||||
|
|
||||||
|
#### 1.3 列表规则
|
||||||
|
- 只显示有鸽子费(`deposit_fee > 0`)的未赴约用户
|
||||||
|
- 已审核通过的(`is_arrive = 3`)不显示在列表中
|
||||||
|
- 按标记时间倒序排列
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✅ 审核通过流程
|
||||||
|
|
||||||
|
### 2.1 状态更新
|
||||||
|
- 将用户状态改为:`is_arrive = 3`(未赴约,已审核)
|
||||||
|
- 用户参与状态保持:`status = 0`(未退出,但已标记为未赴约)
|
||||||
|
|
||||||
|
### 2.2 鸽子费分配规则
|
||||||
|
|
||||||
|
#### 分配对象
|
||||||
|
- **已赴约且未退出的参与者**:`is_arrive = 1` 且 `status = 0`
|
||||||
|
- **时间限制**:只计算在签到时间之前加入的参与者(`join_time < 签到时间`)
|
||||||
|
- **排除对象**:
|
||||||
|
- 未赴约的用户(`is_arrive = 2` 或 `is_arrive = 3`)
|
||||||
|
- 已退出的用户(`status = 1`)
|
||||||
|
- 签到时间之后加入的用户
|
||||||
|
|
||||||
|
#### 分配计算
|
||||||
|
```
|
||||||
|
鸽子费总额 = reservation.deposit_fee
|
||||||
|
参与人数 = 符合条件的已赴约用户数量(不包括发起者)
|
||||||
|
每人分得金额 = 鸽子费总额 / 参与人数(保留两位小数,四舍五入)
|
||||||
|
```
|
||||||
|
|
||||||
|
**注意**:
|
||||||
|
- 如果参与人数为0,鸽子费不分配(但状态仍改为已审核)
|
||||||
|
- 金额保留两位小数,使用四舍五入
|
||||||
|
- 分配后的总金额可能略有差异(因四舍五入),需要处理尾差
|
||||||
|
|
||||||
|
### 2.3 收益记录创建
|
||||||
|
|
||||||
|
为每个分到鸽子费的用户创建收益记录: 使用现有的收益服务
|
||||||
|
- **表**:`SQEarningsRecord`
|
||||||
|
- **字段**:
|
||||||
|
- `user_id`:分到钱的用户ID
|
||||||
|
- `reservation_id`:预约ID
|
||||||
|
- `room_id`:预约的房间ID
|
||||||
|
- `room_number`:房间号
|
||||||
|
- `room_name`:房间名
|
||||||
|
- `room_fee`:预约的房费(可为空)
|
||||||
|
- `earnings`:分到的鸽子费金额
|
||||||
|
- `type`:2(鸽子费)
|
||||||
|
- `remark`:`"未赴约用户鸽子费分配"`
|
||||||
|
- `create_time`:当前时间
|
||||||
|
- `operator_id`:审核员工ID
|
||||||
|
|
||||||
|
### 2.4 用户收益更新
|
||||||
|
|
||||||
|
为每个分到鸽子费的用户更新:
|
||||||
|
- `CoreCmsUser.pending_earnings` += 分到的金额
|
||||||
|
|
||||||
|
### 2.5 消息通知
|
||||||
|
|
||||||
|
#### 2.5.1 给未赴约用户发送消息
|
||||||
|
- **接收人**:被扣除鸽子费的用户
|
||||||
|
- **标题**:`"鸽子费扣除通知"`
|
||||||
|
- **内容**:`"您未按时参加预约,鸽子费已扣除{金额}元。"`
|
||||||
|
- **消息类型**:系统通知(`message_type = 0`)
|
||||||
|
- **关联业务**:`related_type = 1`(组局),`related_id = reservation_id`
|
||||||
|
|
||||||
|
#### 2.5.2 给分到钱的用户发送消息
|
||||||
|
- **接收人**:每个分到鸽子费的用户
|
||||||
|
- **标题**:`"鸽子费分配通知"`
|
||||||
|
- **内容**:`"{未赴约用户昵称} 未能按时参加预约,您收到鸽子费{金额}元"`
|
||||||
|
- **消息类型**:系统通知(`message_type = 0`)
|
||||||
|
- **关联业务**:`related_type = 1`(组局),`related_id = reservation_id`
|
||||||
|
|
||||||
|
### 2.6 列表更新
|
||||||
|
- 审核通过后,该记录不再显示在待审核列表中(因为 `is_arrive = 3`)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ❌ 审核未通过流程
|
||||||
|
|
||||||
|
### 3.1 状态更新
|
||||||
|
- `is_arrive = 1`(已赴约)
|
||||||
|
- `status = 0`(正常,未退出)
|
||||||
|
- `is_refund = 3`(发起退款,由退款任务处理)
|
||||||
|
|
||||||
|
### 3.2 退款处理
|
||||||
|
- 不立即退款,只标记为 `is_refund = 3`
|
||||||
|
- 由现有的退款定时任务统一处理实际退款
|
||||||
|
|
||||||
|
### 3.3 消息通知
|
||||||
|
- **接收人**:被审核的用户
|
||||||
|
- **标题**:`"鸽子费审核结果"`
|
||||||
|
- **内容**:`"您的鸽子费已原路退回。"`
|
||||||
|
- **消息类型**:系统通知(`message_type = 0`)
|
||||||
|
- **关联业务**:`related_type = 1`(组局),`related_id = reservation_id`
|
||||||
|
|
||||||
|
### 3.4 列表更新
|
||||||
|
- 审核未通过后,该记录不再显示在待审核列表中(因为 `is_arrive = 1`)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔍 业务规则说明
|
||||||
|
|
||||||
|
### 4.1 时间限制说明
|
||||||
|
|
||||||
|
**"按照时间去处理一下,后面参与的人不算平均"** 的含义:
|
||||||
|
|
||||||
|
- **签到时间**:发起者执行签到操作的时间(`check_reservation` 接口调用时间)
|
||||||
|
- **目的**:防止在签到之后才加入的用户也能分到钱
|
||||||
|
|
||||||
|
### 4.2 特殊情况处理
|
||||||
|
|
||||||
|
1. **没有已赴约用户**:
|
||||||
|
- 仍然将状态改为 `is_arrive = 3`
|
||||||
|
- 不分配鸽子费(鸽子费保留在系统中或按其他规则处理)
|
||||||
|
- 只给未赴约用户发送扣除通知
|
||||||
|
|
||||||
|
2. **只有发起者一人**:
|
||||||
|
- 如果发起者已赴约,鸽子费不分配(因为没有其他参与者)
|
||||||
|
- 如果发起者未赴约,这种情况不应该出现(发起者不能标记自己未赴约)
|
||||||
|
|
||||||
|
3. **金额尾差处理**:
|
||||||
|
- 由于四舍五入,分配总额可能略小于或大于原金额
|
||||||
|
- 建议:将尾差加给最后一个用户,或加给发起者
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 后台管理功能
|
||||||
|
|
||||||
|
### 5.1 页面路径
|
||||||
|
- **建议路径**:`/views/sq/sqreservations/pigeon-fee-audit.html`
|
||||||
|
- **或**:在现有的预约管理页面中新增一个标签页
|
||||||
|
|
||||||
|
### 5.2 功能按钮
|
||||||
|
- **审核通过**:点击后弹出确认框,确认后执行审核通过流程
|
||||||
|
- **审核未通过**:点击后弹出确认框(可选填写原因),确认后执行审核未通过流程
|
||||||
|
|
||||||
|
### 5.3 筛选功能
|
||||||
|
- 按预约ID筛选
|
||||||
|
- 按用户ID/昵称/手机号筛选
|
||||||
|
- 按预约时间范围筛选
|
||||||
|
- 按标记时间范围筛选
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🗄️ 数据库影响
|
||||||
|
|
||||||
|
### 6.1 涉及的表
|
||||||
|
1. **SQReservationParticipants**:更新 `is_arrive`、`status`、`is_refund`
|
||||||
|
2. **SQEarningsRecord**:新增收益记录
|
||||||
|
3. **CoreCmsUser**:更新 `pending_earnings`
|
||||||
|
4. **SQMessage**:新增消息记录
|
||||||
|
|
||||||
|
### 6.2 事务要求
|
||||||
|
- 审核通过操作需要使用事务,确保:
|
||||||
|
- 状态更新成功
|
||||||
|
- 收益记录创建成功
|
||||||
|
- 用户收益更新成功
|
||||||
|
- 消息发送成功
|
||||||
|
- 任一环节失败,全部回滚
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 接口设计建议
|
||||||
|
|
||||||
|
### 7.1 获取待审核列表
|
||||||
|
- **接口**:`POST /api/SQReservations/GetPigeonFeeAuditList`
|
||||||
|
- **参数**:分页参数、筛选条件
|
||||||
|
- **返回**:待审核列表数据
|
||||||
|
|
||||||
|
### 7.2 审核通过
|
||||||
|
- **接口**:`POST /api/SQReservations/ApprovePigeonFee`
|
||||||
|
- **参数**:`{ participantId: int, reservationId: int }`
|
||||||
|
- **返回**:操作结果
|
||||||
|
|
||||||
|
### 7.3 审核未通过
|
||||||
|
- **接口**:`POST /api/SQReservations/RejectPigeonFee`
|
||||||
|
- **参数**:`{ participantId: int, reservationId: int, reason?: string }`
|
||||||
|
- **返回**:操作结果
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚠️ 注意事项
|
||||||
|
|
||||||
|
1. **并发控制**:同一用户的审核操作需要加锁,防止重复审核
|
||||||
|
2. **数据一致性**:所有涉及金额的操作必须使用事务
|
||||||
|
3. **审计日志**:记录审核操作的操作员ID和时间
|
||||||
|
4. **消息发送**:消息发送失败不应影响审核流程(可异步处理或记录日志)(使用现有的消息服务)
|
||||||
|
5. **金额精度**:所有金额计算使用 `decimal(18,2)`,保留两位小数
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔄 业务流程总结
|
||||||
|
|
||||||
|
### 审核通过流程
|
||||||
|
```
|
||||||
|
员工查看待审核列表
|
||||||
|
→ 点击"审核通过"
|
||||||
|
→ 系统计算已赴约用户(按时间筛选)
|
||||||
|
→ 计算每人分得金额
|
||||||
|
→ 开启事务
|
||||||
|
→ 更新用户状态 is_arrive=3
|
||||||
|
→ 为每个分到钱的用户创建收益记录(使用SQEarningsServices,看有没有满足的方法)
|
||||||
|
→ 更新每个用户的 pending_earnings
|
||||||
|
→ 发送消息给未赴约用户(使用现有的消息服务SQMessageServices,看有没有满足的方法)
|
||||||
|
→ 发送消息给每个分到钱的用户(使用现有的消息服务SQMessageServices,看有没有满足的方法)
|
||||||
|
→ 提交事务
|
||||||
|
→ 刷新列表(该记录不再显示)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 审核未通过流程
|
||||||
|
```
|
||||||
|
员工查看待审核列表
|
||||||
|
→ 点击"审核未通过"
|
||||||
|
→ 开启事务
|
||||||
|
→ 更新用户状态 is_arrive=1, status=0, is_refund=3
|
||||||
|
→ 发送消息给用户(使用现有的消息服务SQMessageServices,看有没有满足的方法)
|
||||||
|
→ 提交事务
|
||||||
|
→ 刷新列表(该记录不再显示)
|
||||||
|
→ 退款由定时任务处理
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ❓ 已确认问题
|
||||||
|
|
||||||
|
1. **签到时间的获取**:如何准确获取发起者签到的具体时间?是否需要在 `check_reservation` 接口中记录签到时间?
|
||||||
|
|
||||||
|
2. **尾差处理**:当分配金额因四舍五入产生尾差时,如何处理?是加给最后一个用户,还是加给发起者,还是忽略?(忽略,只保留两位小数)
|
||||||
|
|
||||||
|
3. **没有已赴约用户的情况**:如果所有参与者都未赴约,鸽子费如何处理?是保留在系统中,还是退还给未赴约用户?(如果发起者未签到,不处理,如果是发起者签到了,按现在的流程走,由员工去线下判断,审核)
|
||||||
|
|
||||||
|
4. **发起者未赴约**:如果发起者自己未赴约(这种情况是否可能?),如何处理?(不处理,发起者未签到,不处理)
|
||||||
|
|
||||||
|
5. **批量审核**:是否需要支持批量审核功能?(不需要)
|
||||||
Loading…
Reference in New Issue
Block a user