550 lines
26 KiB
HTML
Executable File
550 lines
26 KiB
HTML
Executable File
{include file="Public:header3"/}
|
|
|
|
<body>
|
|
<div class="layui-fluid" style="padding: 0px;">
|
|
<div class="layui-card">
|
|
<!-- 搜索条件区域 -->
|
|
<form class="layui-form layui-card-header layuiadmin-card-header-auto" style="padding-top: 15px;">
|
|
<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 class="layui-inline">
|
|
<button class="layui-btn layui-btn-normal" id="exportBtn" type="button">
|
|
<i class="layui-icon layui-icon-export"></i> 导出Excel
|
|
</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">
|
|
总收入
|
|
<i class="layui-icon layui-icon-about" style="font-size: 14px; color: #1E9FFF;"
|
|
title="收入 = 微信支付 + 钻石支付"></i>
|
|
</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">
|
|
总出货价值
|
|
<i class="layui-icon layui-icon-about" style="font-size: 14px; color: #FFB800;"
|
|
title="出货价值 = 奖品的兑换价格"></i>
|
|
</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">
|
|
总利润
|
|
<i class="layui-icon layui-icon-about" style="font-size: 14px; color: #5FB878;"
|
|
title="利润 = 收入 - 出货价值"></i>
|
|
</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,
|
|
height:'full-180',
|
|
limit: 50,
|
|
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: 200 },
|
|
{
|
|
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>';
|
|
} else {
|
|
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: '收入 <i class="layui-icon layui-icon-about" title="微信支付+钻石支付"></i>', width: 150, 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: '出货价值 <i class="layui-icon layui-icon-about" title="奖品的兑换价格"></i>', width: 150, 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: 150, 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: '利润 <i class="layui-icon layui-icon-about" title="收入-出货价值"></i>', 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]);
|
|
}
|
|
}
|
|
|
|
// 加载汇总数据
|
|
loadSummaryStatistics();
|
|
|
|
// 开始加载详细统计数据
|
|
processLoadingQueue();
|
|
}
|
|
});
|
|
|
|
// 加载汇总统计数据
|
|
function loadSummaryStatistics() {
|
|
var params = getSearchParams();
|
|
|
|
$.ajax({
|
|
url: '{:url("/admin/statistics_getSummaryStatistics")}',
|
|
type: 'GET',
|
|
data: params,
|
|
success: function (res) {
|
|
if (res.code === 0) {
|
|
// 更新汇总数据
|
|
summaryData = res.data;
|
|
|
|
// 更新统计摘要显示
|
|
updateStatisticsSummary(summaryData);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
// 处理加载队列
|
|
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;
|
|
|
|
// 直接更新单元格内容,不重新渲染表格
|
|
var tr = $('#profitTable').next().find('tr[data-index="' + i + '"]');
|
|
if (tr.length > 0) {
|
|
// 设置背景色
|
|
if (data.is_negative) {
|
|
tr.css('background-color', '#ffebee');
|
|
}
|
|
|
|
// 更新单元格内容
|
|
tr.find('td[data-field="use_money"] div').html('<span class="layui-badge layui-bg-blue">¥ ' + data.use_money.toFixed(2) + '</span>');
|
|
tr.find('td[data-field="sc_money"] div').html('<span class="layui-badge layui-bg-orange">¥ ' + data.sc_money.toFixed(2) + '</span>');
|
|
tr.find('td[data-field="re_money"] div').html('<span class="layui-badge" style="background-color: #FF9800;">¥ ' + data.re_money.toFixed(2) + '</span>');
|
|
tr.find('td[data-field="fh_money"] div').html('<span class="layui-badge" style="background-color: #673AB7;">¥ ' + data.fh_money.toFixed(2) + '</span>');
|
|
tr.find('td[data-field="cj_count"] div').html(data.cj_count);
|
|
|
|
var profitColorClass = data.profit >= 0 ? 'layui-bg-green' : 'layui-bg-red';
|
|
tr.find('td[data-field="profit"] div').html('<span class="layui-badge ' + profitColorClass + '">¥ ' + data.profit.toFixed(2) + '</span>');
|
|
|
|
var rateColorClass = data.profit_rate >= 0 ? 'layui-bg-green' : 'layui-bg-red';
|
|
tr.find('td[data-field="profit_rate"] div').html('<span class="layui-badge ' + rateColorClass + '">' + data.profit_rate.toFixed(2) + '%</span>');
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
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
|
|
}
|
|
});
|
|
|
|
// 重新加载汇总数据
|
|
loadSummaryStatistics();
|
|
});
|
|
|
|
// 导出按钮点击事件
|
|
$('#exportBtn').on('click', function () {
|
|
// 获取当前查询参数
|
|
var params = getSearchParams();
|
|
|
|
// 弹出确认对话框
|
|
layer.confirm('确定要导出当前条件下的所有盒子利润统计数据吗?', {
|
|
btn: ['确定', '取消'],
|
|
title: '导出确认'
|
|
}, function(index) {
|
|
layer.close(index);
|
|
|
|
// 显示加载层
|
|
var loadIndex = layer.load(2, {shade: [0.3, '#fff']});
|
|
|
|
// 构建导出URL及参数
|
|
var exportUrl = '{:url("/admin/statistics_exportProfit")}';
|
|
var queryString = $.param(params);
|
|
if (queryString) {
|
|
exportUrl += '?' + queryString;
|
|
}
|
|
|
|
// 创建一个隐藏的a标签用于下载
|
|
var downloadLink = document.createElement('a');
|
|
downloadLink.style.display = 'none';
|
|
downloadLink.href = exportUrl;
|
|
downloadLink.target = '_blank';
|
|
document.body.appendChild(downloadLink);
|
|
|
|
// 模拟点击下载
|
|
downloadLink.click();
|
|
|
|
// 移除临时元素
|
|
setTimeout(function() {
|
|
document.body.removeChild(downloadLink);
|
|
layer.close(loadIndex);
|
|
}, 2000);
|
|
});
|
|
});
|
|
|
|
// 监听表格工具条事件
|
|
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();
|
|
|
|
// 初始化提示图标
|
|
initTips();
|
|
});
|
|
|
|
// 初始化提示信息
|
|
function initTips() {
|
|
// 为提示图标添加鼠标悬停事件
|
|
$('.layui-icon-about').on('mouseenter', function () {
|
|
var that = this;
|
|
layer.tips($(that).attr('title'), that, {
|
|
tips: [1, '#3595CC'],
|
|
time: 4000
|
|
});
|
|
});
|
|
}
|
|
});
|
|
</script>
|
|
</body>
|
|
|
|
</html> |