428 lines
20 KiB
HTML
Executable File
428 lines
20 KiB
HTML
Executable File
{include file="Public:header3"/}
|
|
|
|
<body>
|
|
<div class="layui-fluid">
|
|
<div class="layui-card">
|
|
<!-- 搜索条件区域 -->
|
|
<form class="layui-form layui-card-header layuiadmin-card-header-auto">
|
|
<div class="layui-form-item">
|
|
<div class="layui-inline">
|
|
<div class="layui-input-inline" style="width:150px;margin-left: 0px">
|
|
<input type="text" name="goodId" id="goodId" placeholder="请输入盒子Id" autocomplete="off" class="layui-input">
|
|
</div>
|
|
</div>
|
|
<div class="layui-inline">
|
|
<div class="layui-input-inline" style="width:150px;margin-left: 0px">
|
|
<input type="text" name="title" id="title" placeholder="请输入盒子名称" autocomplete="off" class="layui-input">
|
|
</div>
|
|
</div>
|
|
<div class="layui-inline">
|
|
<div class="layui-input-inline" style="width: 180px;margin-left: 0px">
|
|
<select name="status" id="status" style="width:100%">
|
|
<option value="">--请选择盒子状态--</option>
|
|
<option value="1">上架</option>
|
|
<option value="2">下架</option>
|
|
<option value="3">售罄</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="layui-inline">
|
|
<div class="layui-input-inline" style="width: 180px;margin-left: 0px">
|
|
<select name="type" id="goodsType" style="width:100%">
|
|
<option value="">--盒子类型--</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="layui-inline">
|
|
<div class="layui-input-inline" style="width:300px;margin-left: 0px">
|
|
<input type="text" id="addtime" name="addtime" class="layui-input" placeholder="选择时间" autocomplete="off">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="layui-inline">
|
|
<button class="layui-btn layuiadmin-btn-useradmin" id="searchBtn" type="button">
|
|
<i class="layui-icon layui-icon-search layuiadmin-button-btn"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
|
|
<!-- 统计摘要区域 -->
|
|
<div class="layui-card-body">
|
|
<div class="layui-row layui-col-space15" id="statisticsSummary">
|
|
<div class="layui-col-md3">
|
|
<div class="layui-card">
|
|
<div class="layui-card-header">总收入</div>
|
|
<div class="layui-card-body" style="font-size: 24px; color: #01AAED;">
|
|
¥ <span id="totalIncome">0.00</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="layui-col-md3">
|
|
<div class="layui-card">
|
|
<div class="layui-card-header">总出货价值</div>
|
|
<div class="layui-card-body" style="font-size: 24px; color: #FFB800;">
|
|
¥ <span id="totalCost">0.00</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="layui-col-md3">
|
|
<div class="layui-card">
|
|
<div class="layui-card-header">总利润</div>
|
|
<div class="layui-card-body" style="font-size: 24px;">
|
|
¥ <span id="totalProfit" class="profit-value">0.00</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="layui-col-md3">
|
|
<div class="layui-card">
|
|
<div class="layui-card-header">总兑换/发货价值</div>
|
|
<div class="layui-card-body" style="font-size: 24px;">
|
|
<span style="color: #FF9800;">¥ <span id="totalReMoney">0.00</span></span> /
|
|
<span style="color: #673AB7;">¥ <span id="totalFhMoney">0.00</span></span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 数据表格区域 -->
|
|
<table id="profitTable" lay-filter="profitTable"></table>
|
|
|
|
<!-- 表格操作栏模板 -->
|
|
<script type="text/html" id="operationTpl">
|
|
<button class="layui-btn layui-btn-danger layui-btn-xs" lay-event="viewProductsOverview">出货概览</button>
|
|
</script>
|
|
|
|
<!-- 利润和利润率模板 -->
|
|
<script type="text/html" id="profitTpl">
|
|
<span class="layui-badge {{d.profit >= 0 ? 'layui-bg-green' : 'layui-bg-red'}}">
|
|
¥ {{d.profit.toFixed(2)}}
|
|
</span>
|
|
</script>
|
|
|
|
<script type="text/html" id="profitRateTpl">
|
|
<span class="layui-badge {{d.profit_rate >= 0 ? 'layui-bg-green' : 'layui-bg-red'}}">
|
|
{{d.profit_rate.toFixed(2)}}%
|
|
</span>
|
|
</script>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{include file="Public:footer3"/}
|
|
<script type="text/javascript">
|
|
layui.use(['layer', 'laydate', 'table', 'form'], function () {
|
|
var $ = layui.$;
|
|
var layer = layui.layer;
|
|
var laydate = layui.laydate;
|
|
var form = layui.form;
|
|
var table = layui.table;
|
|
|
|
// 日期时间范围
|
|
laydate.render({
|
|
elem: '#addtime',
|
|
type: 'datetime',
|
|
range: true
|
|
});
|
|
|
|
// 加载盒子类型数据
|
|
function loadGoodsTypes() {
|
|
$.ajax({
|
|
url: '{:url("/admin/api/goods/types")}',
|
|
type: 'GET',
|
|
success: function (res) {
|
|
if (res.code === 0) {
|
|
// 更新下拉框
|
|
var html = '<option value="">--盒子类型--</option>';
|
|
|
|
$.each(res.data, function (index, item) {
|
|
html += '<option value="' + item.value + '" title="' + item.remark + '">' + item.fl_name + '</option>';
|
|
});
|
|
$('#goodsType').html(html);
|
|
form.render('select');
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
// 全局变量,存储汇总数据
|
|
var summaryData = {
|
|
totalIncome: 0,
|
|
totalCost: 0,
|
|
totalProfit: 0,
|
|
totalReMoney: 0,
|
|
totalFhMoney: 0
|
|
};
|
|
|
|
// 全局变量,用于控制异步加载
|
|
var loadingQueue = [];
|
|
var isLoading = false;
|
|
var maxConcurrentRequests = 3; // 最大并发请求数
|
|
|
|
// 初始化表格
|
|
var profitTable = table.render({
|
|
elem: '#profitTable',
|
|
url: '{:url("/admin/statistics/profitData")}',
|
|
method: 'get',
|
|
page: true,
|
|
limit: 20,
|
|
where: getSearchParams(),
|
|
parseData: function(res) {
|
|
if (res.code === 0) {
|
|
// 清空汇总数据
|
|
summaryData = {
|
|
totalIncome: 0,
|
|
totalCost: 0,
|
|
totalProfit: 0,
|
|
totalReMoney: 0,
|
|
totalFhMoney: 0
|
|
};
|
|
|
|
// 更新统计摘要数据为0
|
|
updateStatisticsSummary(summaryData);
|
|
|
|
return {
|
|
"code": 0,
|
|
"msg": res.msg,
|
|
"count": res.count,
|
|
"data": res.data
|
|
};
|
|
}
|
|
return {
|
|
"code": res.code,
|
|
"msg": res.msg,
|
|
"count": 0,
|
|
"data": []
|
|
};
|
|
},
|
|
cols: [[
|
|
{field: 'id', title: '盒子ID', width: 80, sort: true, fixed: 'left'},
|
|
{field: 'title', title: '盒子名称', width: 180},
|
|
{templet: function(d) {
|
|
var statusHtml = '';
|
|
if(d.status == 1) {
|
|
statusHtml = '<span class="layui-badge layui-bg-green">上架</span>';
|
|
} else if(d.status == 2) {
|
|
statusHtml = '<span class="layui-badge layui-bg-gray">下架</span>';
|
|
} else if(d.status == 3) {
|
|
statusHtml = '<span class="layui-badge layui-bg-orange">售罄</span>';
|
|
}
|
|
return '<div><button class="layui-btn layui-btn-normal layui-btn-radius layui-btn-xs type-btn" data-type="'+d.type+'">'+d.type_name+'</button> / ' + statusHtml + '</div>';
|
|
}, title: '盒子类型/状态', width: 160},
|
|
{field: 'price', title: '盒子单价', width: 100, templet: '<div>¥ {{d.price}}</div>'},
|
|
{field: 'cj_count', title: '抽奖次数', width: 100, templet: function(d) {
|
|
if (!d.loaded) {
|
|
return '<div><i class="layui-icon layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop"></i></div>';
|
|
}
|
|
return '<div>' + d.cj_count + '</div>';
|
|
}},
|
|
{field: 'use_money', title: '收入', width: 110, templet: function(d) {
|
|
if (!d.loaded) {
|
|
return '<div><i class="layui-icon layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop"></i></div>';
|
|
}
|
|
return '<div><span class="layui-badge layui-bg-blue">¥ ' + d.use_money.toFixed(2) + '</span></div>';
|
|
}},
|
|
{field: 'sc_money', title: '出货价值', width: 110, templet: function(d) {
|
|
if (!d.loaded) {
|
|
return '<div><i class="layui-icon layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop"></i></div>';
|
|
}
|
|
return '<div><span class="layui-badge layui-bg-orange">¥ ' + d.sc_money.toFixed(2) + '</span></div>';
|
|
}},
|
|
{field: 're_money', title: '兑换价值', width: 110, templet: function(d) {
|
|
if (!d.loaded) {
|
|
return '<div><i class="layui-icon layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop"></i></div>';
|
|
}
|
|
return '<div><span class="layui-badge" style="background-color: #FF9800;">¥ ' + d.re_money.toFixed(2) + '</span></div>';
|
|
}},
|
|
{field: 'fh_money', title: '发货价值', width: 110, templet: function(d) {
|
|
if (!d.loaded) {
|
|
return '<div><i class="layui-icon layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop"></i></div>';
|
|
}
|
|
return '<div><span class="layui-badge" style="background-color: #673AB7;">¥ ' + d.fh_money.toFixed(2) + '</span></div>';
|
|
}},
|
|
{field: 'profit', title: '利润', width: 110, templet: function(d) {
|
|
if (!d.loaded) {
|
|
return '<div><i class="layui-icon layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop"></i></div>';
|
|
}
|
|
var colorClass = d.profit >= 0 ? 'layui-bg-green' : 'layui-bg-red';
|
|
return '<div><span class="layui-badge ' + colorClass + '">¥ ' + d.profit.toFixed(2) + '</span></div>';
|
|
}},
|
|
{field: 'profit_rate', title: '利润率', width: 100, templet: function(d) {
|
|
if (!d.loaded) {
|
|
return '<div><i class="layui-icon layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop"></i></div>';
|
|
}
|
|
var colorClass = d.profit_rate >= 0 ? 'layui-bg-green' : 'layui-bg-red';
|
|
return '<div><span class="layui-badge ' + colorClass + '">' + d.profit_rate.toFixed(2) + '%</span></div>';
|
|
}},
|
|
{title: '操作', width: 110, toolbar: '#operationTpl', fixed: 'right'}
|
|
]],
|
|
done: function(res) {
|
|
// 清空加载队列
|
|
loadingQueue = [];
|
|
isLoading = false;
|
|
|
|
// 将所有数据项添加到加载队列中
|
|
var tableData = table.cache.profitTable || [];
|
|
for (var i = 0; i < tableData.length; i++) {
|
|
if (!tableData[i].loaded) {
|
|
loadingQueue.push(tableData[i]);
|
|
}
|
|
}
|
|
|
|
// 开始加载统计数据
|
|
processLoadingQueue();
|
|
}
|
|
});
|
|
|
|
// 处理加载队列
|
|
function processLoadingQueue() {
|
|
if (isLoading || loadingQueue.length === 0) return;
|
|
|
|
isLoading = true;
|
|
var requests = 0;
|
|
var activeRequests = 0;
|
|
|
|
// 获取当前需要处理的项目
|
|
while (requests < maxConcurrentRequests && loadingQueue.length > 0) {
|
|
var item = loadingQueue.shift();
|
|
requests++;
|
|
activeRequests++;
|
|
|
|
loadBoxStatistics(item, function() {
|
|
activeRequests--;
|
|
if (activeRequests === 0) {
|
|
isLoading = false;
|
|
processLoadingQueue();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
// 加载单个盒子的统计数据
|
|
function loadBoxStatistics(item, callback) {
|
|
var params = getSearchParams();
|
|
|
|
$.ajax({
|
|
url: '{:url("/admin/statistics/getBoxStatistics")}',
|
|
type: 'GET',
|
|
data: {
|
|
goods_id: item.id,
|
|
addtime: params.addtime
|
|
},
|
|
success: function(res) {
|
|
if (res.code === 0) {
|
|
var data = res.data;
|
|
|
|
// 更新表格中的数据
|
|
var tableData = table.cache.profitTable;
|
|
for (var i = 0; i < tableData.length; i++) {
|
|
if (tableData[i].id === item.id) {
|
|
tableData[i].use_money = data.use_money;
|
|
tableData[i].sc_money = data.sc_money;
|
|
tableData[i].re_money = data.re_money;
|
|
tableData[i].fh_money = data.fh_money;
|
|
tableData[i].cj_count = data.cj_count;
|
|
tableData[i].profit = data.profit;
|
|
tableData[i].profit_rate = data.profit_rate;
|
|
tableData[i].is_negative = data.is_negative;
|
|
tableData[i].loaded = true;
|
|
|
|
// 更新汇总数据
|
|
summaryData.totalIncome += data.use_money;
|
|
summaryData.totalCost += data.sc_money;
|
|
summaryData.totalReMoney += data.re_money;
|
|
summaryData.totalFhMoney += data.fh_money;
|
|
summaryData.totalProfit = summaryData.totalIncome - summaryData.totalCost;
|
|
|
|
// 更新统计摘要
|
|
updateStatisticsSummary(summaryData);
|
|
|
|
// 设置背景色
|
|
if (data.is_negative) {
|
|
$('tr[data-index="' + i + '"]').css('background-color', '#ffebee');
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
// 重新渲染表格
|
|
table.render({
|
|
elem: '#profitTable',
|
|
data: tableData,
|
|
page: false,
|
|
cols: profitTable.config.cols
|
|
});
|
|
}
|
|
|
|
if (callback) callback();
|
|
},
|
|
error: function() {
|
|
if (callback) callback();
|
|
}
|
|
});
|
|
}
|
|
|
|
// 更新统计摘要
|
|
function updateStatisticsSummary(summary) {
|
|
if (!summary) return;
|
|
|
|
$('#totalIncome').text(summary.totalIncome.toFixed(2));
|
|
$('#totalCost').text(summary.totalCost.toFixed(2));
|
|
$('#totalProfit').text(summary.totalProfit.toFixed(2));
|
|
$('#totalReMoney').text(summary.totalReMoney.toFixed(2));
|
|
$('#totalFhMoney').text(summary.totalFhMoney.toFixed(2));
|
|
|
|
// 设置利润颜色
|
|
var profitElem = $('#totalProfit');
|
|
if (summary.totalProfit >= 0) {
|
|
profitElem.parent().css('color', '#5FB878');
|
|
} else {
|
|
profitElem.parent().css('color', '#FF5722');
|
|
}
|
|
}
|
|
|
|
// 获取搜索参数
|
|
function getSearchParams() {
|
|
return {
|
|
goodId: $('#goodId').val(),
|
|
title: $('#title').val(),
|
|
status: $('#status').val(),
|
|
type: $('#goodsType').val(),
|
|
addtime: $('#addtime').val()
|
|
};
|
|
}
|
|
|
|
// 搜索按钮点击事件
|
|
$('#searchBtn').on('click', function() {
|
|
profitTable.reload({
|
|
where: getSearchParams(),
|
|
page: {
|
|
curr: 1
|
|
}
|
|
});
|
|
});
|
|
|
|
// 监听表格工具条事件
|
|
table.on('tool(profitTable)', function(obj) {
|
|
var data = obj.data;
|
|
if (obj.event === 'viewProductsOverview') {
|
|
// 查看出货概览
|
|
layer.open({
|
|
type: 2,
|
|
title: '出货概览',
|
|
shadeClose: false,
|
|
shade: 0.3,
|
|
area: ['90%', '90%'],
|
|
content: '{:url("/admin/statistics_productsOverview")}?goods_id=' + data.id
|
|
});
|
|
}
|
|
});
|
|
|
|
// 页面加载完成后执行
|
|
$(function() {
|
|
loadGoodsTypes();
|
|
});
|
|
});
|
|
</script>
|
|
</body>
|
|
</html> |