manghe/app/admin/view/Statistics/profit.html
2025-04-19 18:38:30 +08:00

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>