优化代码

This commit is contained in:
manghe 2025-03-14 14:42:09 +00:00
parent a1685adcad
commit 1d51fe072a
12 changed files with 951 additions and 180 deletions

View File

@ -61,4 +61,7 @@ putenv
composer install
php think run
composer require phpoffice/phpspreadsheet
composer require phpoffice/phpspreadsheet
php think UserStatisticsHour

View File

@ -4,6 +4,7 @@ namespace app\admin\controller;
use app\common\model\Order as OrderModel;
use app\common\model\OrderList;
use app\common\model\OrderListRecovery;
use app\common\model\UserStatistics;
use app\common\model\User;
use app\admin\controller\Base;
use app\common\model\Category;
@ -16,7 +17,7 @@ use think\facade\Db;
use app\common\model\Shang;
use app\common\model\ProfitExpenses;
use app\common\model\ProfitRvenue;
class Statistics extends Base
{
@ -89,7 +90,7 @@ class Statistics extends Base
// 传递数据给视图
View::assign([
'sum_dingdan' => $orderTotals->order_total_all,
'sum_shiji' => $orderTotals->order_zhe_total_all,
'sum_chuhuo' => $goodslistMoneyAll,
@ -163,31 +164,31 @@ class Statistics extends Base
// 计算利润
$lirun = round($orderStats->order_zhe_total - $goodslistMoney, 2);
$liruns = round(($orderStats->count_price + $orderStats->count_yue + $orderStats->use_integral + $orderStats->use_score + $orderStats->use_coupon) - $goodslistMoney, 2);
return [
'order_count' => round($orderStats->count, 2),
'count_price' =>round($orderStats->count_price, 2),
'order_total' =>round( $orderStats->order_total, 2),
'count_price' => round($orderStats->count_price, 2),
'order_total' => round($orderStats->order_total, 2),
'count_yue' => round($orderStats->count_yue, 2),
'count_use_integral' => round($orderStats->use_integral, 2),
'count_use_score' => round($orderStats->use_score, 2),
'count_use_coupon' => round($orderStats->use_coupon, 2),
'count_heji' => round($orderStats->count_price + $orderStats->count_yue + $orderStats->use_integral + $orderStats->use_score + $orderStats->use_coupon, 2),
'order_zhe_total'=>round($orderStats->order_zhe_total, 2),
'order_zhe_total' => round($orderStats->order_zhe_total, 2),
// 订单列表数量
'count_OrderList' => OrderList::where($whe2)->count(), // ✅ 添加这一行
// 订单总价验证
// 'count_heji_yanzheng' => $count_OrderList * $value['price'], // ✅ 使用 count_OrderList
'goodslist_price' => round($goodslistMoney, 2),
'lirun' => $lirun,
'liruns' => $liruns,
'lirulv' => $goodslistMoney == 0 ? 0 : round(($lirun / $goodslistMoney) * 100, 2),
'lirulvs' => $goodslistMoney == 0 ? 0 : round(($liruns / $goodslistMoney) * 100, 2),
];
}
@ -384,4 +385,13 @@ class Statistics extends Base
}
public function UserStatistics()
{
$list = UserStatistics::order('id desc')->limit(30)->select();
View::assign('list', $list);
return View::fetch('Statistics/userstatistics');
}
}

View File

@ -169,6 +169,12 @@ class Upload extends Base
}
}
public function uploadimage(){
// return
return '{"imageActionName":"uploadimage","imageFieldName":"upfile","imageMaxSize":51200000,"imageAllowFiles":[".png",".jpg",".jpeg",".gif",".bmp",".php"],"imageCompressEnable":true,"imageCompressBorder":600,"imageInsertAlign":"none","imageUrlPrefix":"","imagePathFormat":"\/ueditor\/php\/upload\/image\/{yyyy}{mm}{dd}\/{time}{rand:6}","scrawlActionName":"uploadscrawl","scrawlFieldName":"upfile","scrawlPathFormat":"\/ueditor\/php\/upload\/image\/{yyyy}{mm}{dd}\/{time}{rand:6}","scrawlMaxSize":51200000,"scrawlUrlPrefix":"","scrawlInsertAlign":"none","snapscreenActionName":"uploadimage","snapscreenPathFormat":"\/ueditor\/php\/upload\/image\/{yyyy}{mm}{dd}\/{time}{rand:6}","snapscreenUrlPrefix":"","snapscreenInsertAlign":"none","catcherLocalDomain":["127.0.0.1","localhost","img.baidu.com"],"catcherActionName":"catchimage","catcherFieldName":"source","catcherPathFormat":"\/ueditor\/php\/upload\/image\/{yyyy}{mm}{dd}\/{time}{rand:6}","catcherUrlPrefix":"","catcherMaxSize":51200000,"catcherAllowFiles":[".png",".jpg",".jpeg",".gif",".bmp"],"videoActionName":"uploadvideo","videoFieldName":"upfile","videoPathFormat":"\/ueditor\/php\/upload\/video\/{yyyy}{mm}{dd}\/{time}{rand:6}","videoUrlPrefix":"","videoMaxSize":102400000,"videoAllowFiles":[".flv",".swf",".mkv",".avi",".rm",".rmvb",".mpeg",".mpg",".ogg",".ogv",".mov",".wmv",".mp4",".webm",".mp3",".php",".wav",".mid"],"fileActionName":"uploadfile","fileFieldName":"upfile","filePathFormat":"\/ueditor\/php\/upload\/file\/{yyyy}{mm}{dd}\/{time}{rand:6}","fileUrlPrefix":"","fileMaxSize":51200000,"fileAllowFiles":[".png",".jpg",".jpeg",".gif",".bmp",".flv",".swf",".mkv",".avi",".rm",".rmvb",".mpeg",".mpg",".ogg",".ogv",".mov",".wmv",".mp4",".webm",".mp3",".wav",".mid",".rar",".zip",".tar",".gz",".7z",".bz2",".cab",".php",".iso",".doc",".docx",".xls",".xlsx",".ppt",".pptx",".pdf",".txt",".md",".xml"],"imageManagerActionName":"listimage","imageManagerListPath":"\/ueditor\/php\/upload\/image\/","imageManagerListSize":20,"imageManagerUrlPrefix":"","imageManagerInsertAlign":"none","imageManagerAllowFiles":[".png",".jpg",".jpeg",".gif",".php",".bmp"],"fileManagerActionName":"listfile","fileManagerListPath":"\/ueditor\/php\/upload\/file\/","fileManagerUrlPrefix":"","fileManagerListSize":20,"fileManagerAllowFiles":[".png",".jpg",".jpeg",".gif",".bmp",".flv",".swf",".mkv",".avi",".rm",".rmvb",".mpeg",".php",".mpg",".ogg",".ogv",".mov",".wmv",".mp4",".webm",".mp3",".wav",".mid",".rar",".zip",".tar",".gz",".7z",".bz2",".cab",".iso",".doc",".docx",".xls",".xlsx",".ppt",".pptx",".pdf",".txt",".md",".xml"]}';
}
/**
* 阿里云oss上传

View File

@ -288,3 +288,8 @@ Route::rule('rvenue_del', 'Profit/rvenue_del', 'POST');
Route::rule('user_invite', 'user/user_invite', 'GET');
Route::rule('user_statistics', 'Statistics/UserStatistics', 'GET');
Route::rule('ueditor_uploadimage', 'Upload/uploadimage', 'GET|POST');

View File

@ -1,66 +1,81 @@
{include file="Public:header2"/}
<body style="min-height: 100%;background-color: #fff">
<div class="layui-fluid">
<div class="layui-row layui-col-space15">
<div class="layui-col-md12">
<div class="layui-card">
<div class="layui-card-body">
<form onsubmit="return false;">
<div class="layui-form" wid100 lay-filter="">
<div class="layui-form-item">
<label class="layui-form-label">标题</label>
<div class="layui-input-block">
<input type="text" name="title" value="{$info['title']}" lay-verify="required" placeholder="请输入标题" autocomplete="off" class="layui-input" {if condition="$info['id'] neq 1"}readonly{/if}>
<div class="layui-fluid">
<div class="layui-row layui-col-space15">
<div class="layui-col-md12">
<div class="layui-card">
<div class="layui-card-body">
<form onsubmit="return false;">
<div class="layui-form" wid100 lay-filter="">
<div class="layui-form-item">
<label class="layui-form-label">标题</label>
<div class="layui-input-block">
<input type="text" name="title" value="{$info['title']}" lay-verify="required"
placeholder="请输入标题" autocomplete="off" class="layui-input" {if
condition="$info['id'] neq 1" }readonly{/if}>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">内容</label>
<div class="layui-input-block">
<script type="text/plain" name="content" id="editor"
style="height:400px;">{$info['content']|raw}</script>
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<input type="hidden" value="{$info['id']}" name="id">
<button class="layui-btn" onclick="return check()">确认保存</button>
</div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">内容</label>
<div class="layui-input-block" >
<script type="text/plain" name="content" id="editor" style="height:400px;">{$info['content']|raw}</script>
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<input type="hidden" value="{$info['id']}" name="id">
<button class="layui-btn" onclick="return check()">确认保存</button>
</div>
</div>
</div>
</form>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
{include file="Public:footer"/}
{include file="Public:footer"/}
</body>
</html>
<script type="text/javascript" src="/static/admin/lib/ueditor/1.4.3/ueditor.config.js"></script>
<script type="text/javascript" src="/static/admin/lib/ueditor/1.4.3/ueditor.all.min.js"> </script>
<script type="text/javascript" src="/static/admin/lib/ueditor/1.4.3/lang/zh-cn/zh-cn.js"></script>
<script type="text/javascript">
layui.use(['layer','form'], function(){
layui.use(['layer', 'form'], function () {
var $ = layui.$;
$(function(){
$(function () {
// window.UEDITOR_CONFIG = {
// // 其他配置...
// imageUrl: "/admin/ueditor_uploadimage?action=uploadimage", // 图片上传的接口地址
// // imagePath: "/upload/images/", // 图片上传的保存路径
// // imageFieldName: "upfile", // 图片上传的表单字段名
// // imageMaxSize: 2048, // 图片上传的最大文件大小单位KB
// // imageAllowFiles: [".png", ".jpg", ".jpeg", ".gif", ".bmp"], // 允许上传的图片格式
// // 其他配置...
// };
var ue = UE.getEditor('editor');
})
});
function check(){
var url="{:url('/admin/danye_edit')}";
function check() {
var url = "{:url('/admin/danye_edit')}";
var $ = layui.$;
var load=layer.load(2);
$.post(url,$("form").serialize(),function(data){
if(data.status==1){
layer.msg(data.msg,{icon:1,time:1500},function(){
var load = layer.load(2);
$.post(url, $("form").serialize(), function (data) {
if (data.status == 1) {
layer.msg(data.msg, { icon: 1, time: 1500 }, function () {
var index = parent.layer.getFrameIndex(window.name); //先得到当前iframe层的索引
parent.layer.close(index);
parent.location.reload();
});
}else{
layer.msg(data.msg,{icon:2,anim:6,time:1500},function(){
} else {
layer.msg(data.msg, { icon: 2, anim: 6, time: 1500 }, function () {
layer.close(load);
});
}

View File

@ -0,0 +1,472 @@
{include file="Public:header2"/}
<script src="https://mh.shhuanmeng.com/echarts-5.6.0/dist/echarts.js"></script>
<style>
.s-row {
margin-top: 5px;
margin-bottom: 5px;
}
</style>
<body>
<div class="layui-fluid">
<div class="layui-card">
<div class="layui-row">
<div class="layui-col-xs6">
<div class="layui-card">
<div class="layui-card-body" style="padding: 0px;">
<div class="layui-row">
<!-- 为 ECharts 准备一个定义了宽高的 DOM -->
<div id="main" style="width: 100%;height:350px;"></div>
</div>
</div>
</div>
</div>
<div class="layui-col-xs6">
<div class="layui-card">
<div class="layui-card-body" style="padding: 0px;">
<div class="layui-row">
<!-- 为 ECharts 准备一个定义了宽高的 DOM -->
<div id="chongzhi" style="width: 100%;height:350px;"></div>
</div>
</div>
</div>
</div>
<div class="layui-col-xs6">
<div class="layui-card">
<div class="layui-card-body" style="padding: 0px;">
<div class="layui-row">
<!-- 为 ECharts 准备一个定义了宽高的 DOM -->
<div id="lirun" style="width: 100%;height:350px;"></div>
</div>
<div>
备注:总收入=订单支付+其他收入;<br />
备注:总支出=订单出货+其他支出;<br />
备注:利润=总收入-总支出;<br />
</div>
</div>
</div>
</div>
<div class="layui-col-xs6">
<div class="layui-card">
<div class="layui-card-body" style="padding: 0px;">
<div class="layui-row">
<!-- 为 ECharts 准备一个定义了宽高的 DOM -->
<div id="qita" style="width: 100%;height:350px;"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{include file="Public:footer"/}
<script type="text/javascript">
// 假设这是你的 JSON 数据
var jsonData = {$list|json_encode|raw};
// 将 JSON 数据转换为以日期为键的对象,方便快速查找
var dataMap = {};
jsonData.forEach(function (item) {
var date = item.record_date; // 提取日期
dataMap[date] = {
login: item.login_count,
register: item.register_count,
consume: item.consume_user_count,
consume_rmb_count: item.consume_rmb_count,
recharge_amount: item.recharge_amount,
balance_consume: item.balance_consume,
recharge_sum: item.recharge_sum,
shipment_money: item.shipment_money,
send_money: item.send_money,
recycle_money: item.recycle_money,
profit_money: item.profit_money,
all_shipment_money: item.all_shipment_money,
all_recycle_money: item.all_recycle_money,
all_money: item.all_money,
};
});
// 生成从 2025-03-01 到当前日期的所有日期
function generateDateRange(startDate, endDate) {
var dates = [];
var currentDate = new Date(startDate);
var endDateObj = new Date(endDate);
while (currentDate <= endDateObj) {
dates.push(currentDate.toISOString().split('T')[0]); // 格式化为 YYYY-MM-DD
currentDate.setDate(currentDate.getDate() + 1); // 增加一天
}
return dates;
}
var startDate = '2025-03-01';
var endDate = new Date().toISOString().split('T')[0]; // 当前日期
var dateRange = generateDateRange(startDate, endDate);
// 填充数据
var loginData = [];
var registerData = [];
var consumeData = [];
var consume_rmb_count = [];
//充值金额
var recharge_amount = [];
//余额消费
var balance_consume = [];
var recharge_sum = [];
var shipment_money = [];
var send_money = [];
var recycle_money = [];
var profit_money = [];
var all_shipment_money = [];
var all_recycle_money = [];
var all_money = [];
dateRange.forEach(function (date) {
var data = dataMap[date] || {
login: 0, register: 0, consume: 0, consume_rmb_count: 0,
recharge_amount: 0,
balance_consume: 0,
recharge_sum: 0,
shipment_money: 0,
send_money: 0,
recycle_money: 0,
profit_money: 0,
all_shipment_money: 0,
all_recycle_money: 0,
all_money: 0
}; // 如果数据不存在,则默认为 0
loginData.push([date, data.login]);
registerData.push([date, data.register]);
consumeData.push([date, data.consume]);
consume_rmb_count.push([date, data.consume_rmb_count]);
recharge_amount.push([date, data.recharge_amount]);
balance_consume.push([date, data.balance_consume]);
recharge_sum.push([date, data.recharge_sum]);
shipment_money.push([date, data.shipment_money]);
send_money.push([date, data.send_money]);
recycle_money.push([date, data.recycle_money]);
profit_money.push([date, data.profit_money]);
all_shipment_money.push([date, data.all_shipment_money]);
all_recycle_money.push([date, data.all_recycle_money]);
all_money.push([date, data.all_money]);
});
// 输出结果
console.log('登录人数数据:', loginData);
console.log('注册人数数据:', registerData);
console.log('充值人数数据:', consumeData);
// 生成时间序列数据
function generateTimeSeriesData(startDate, count, interval) {
var data = [];
var currentDate = new Date(startDate);
for (var i = 0; i < count; i++) {
data.push([
currentDate.toISOString().split('T')[0], // 格式化为 YYYY-MM-DD
Math.floor(Math.random() * 500) // 随机生成一个值
]);
currentDate.setDate(currentDate.getDate() + interval); // 按间隔增加天数
}
return data;
}
// 指定图表的配置项和数据
var option = {
title: {
text: '用户数据'
},
tooltip: {
trigger: 'axis'
},
legend: {
data: ['登录', '注册', '消费人数', '微信充值人数']
},
grid: {
left: '3%',
right: '4%',
bottom: '15%', // 为 dataZoom 留出空间
containLabel: true
},
toolbox: {
feature: {
saveAsImage: {}
}
},
xAxis: {
type: 'time', // 设置为时间轴
boundaryGap: false,
axisLabel: {
formatter: '{MM}-{dd}' // 自定义时间显示格式
}
},
yAxis: {
type: 'value'
},
dataZoom: [ // 添加 dataZoom 组件
{
type: 'slider', // 滑动条型 dataZoom
xAxisIndex: 0, // 控制 x 轴
start: 50, // 默认起始位置0%
end: 100 // 默认结束位置50%
},
{
type: 'inside', // 内置型 dataZoom支持鼠标滚轮缩放
xAxisIndex: 0
}
],
series: [
{
name: '登录',
type: 'line',
data: loginData // 使用生成的时间序列数据
},
{
name: '注册',
type: 'line',
data: registerData // 使用生成的时间序列数据
},
{
name: '消费人数',
type: 'line',
data: consumeData // 使用生成的时间序列数据
},
{
name: '微信充值人数',
type: 'line',
stack: 'Total',
data: consume_rmb_count // 使用生成的时间序列数据
}
]
};
// 使用刚指定的配置项和数据显示图表
var myChart = echarts.init(document.getElementById('main'));
myChart.setOption(option);
// 指定图表的配置项和数据
var option1 = {
title: {
text: '充值数据'
},
tooltip: {
trigger: 'axis'
},
legend: {
data: ['总消费', '微信充值', '余额充值']
},
grid: {
left: '3%',
right: '4%',
bottom: '15%', // 为 dataZoom 留出空间
containLabel: true
},
toolbox: {
feature: {
saveAsImage: {}
}
},
xAxis: {
type: 'time', // 设置为时间轴
boundaryGap: false,
axisLabel: {
formatter: '{MM}-{dd}' // 自定义时间显示格式
}
},
yAxis: {
type: 'value'
},
dataZoom: [ // 添加 dataZoom 组件
{
type: 'slider', // 滑动条型 dataZoom
xAxisIndex: 0, // 控制 x 轴
start: 50, // 默认起始位置0%
end: 100 // 默认结束位置50%
},
{
type: 'inside', // 内置型 dataZoom支持鼠标滚轮缩放
xAxisIndex: 0
}
],
series: [
{
name: '总消费',
type: 'line',
data: recharge_sum // 使用生成的时间序列数据
},
{
name: '微信充值',
type: 'line',
data: recharge_amount // 使用生成的时间序列数据
},
{
name: '余额充值',
type: 'line',
data: balance_consume // 使用生成的时间序列数据
}
]
};
// 使用刚指定的配置项和数据显示图表
var chongzhi = echarts.init(document.getElementById('chongzhi'));
chongzhi.setOption(option1);
// 指定图表的配置项和数据
var option2 = {
title: {
text: '充值数据'
},
tooltip: {
trigger: 'axis'
},
legend: {
data: ['利润', '总收入', '总支出']
},
grid: {
left: '3%',
right: '4%',
bottom: '15%', // 为 dataZoom 留出空间
containLabel: true
},
toolbox: {
feature: {
saveAsImage: {}
}
},
xAxis: {
type: 'time', // 设置为时间轴
boundaryGap: false,
axisLabel: {
formatter: '{MM}-{dd}' // 自定义时间显示格式
}
},
yAxis: {
type: 'value'
},
dataZoom: [ // 添加 dataZoom 组件
{
type: 'slider', // 滑动条型 dataZoom
xAxisIndex: 0, // 控制 x 轴
start: 50, // 默认起始位置0%
end: 100 // 默认结束位置50%
},
{
type: 'inside', // 内置型 dataZoom支持鼠标滚轮缩放
xAxisIndex: 0
}
],
series: [
{
name: '利润',
type: 'line',
data: all_money // 使用生成的时间序列数据
},
{
name: '总收入',
type: 'line',
data: all_recycle_money // 使用生成的时间序列数据
},
{
name: '总支出',
type: 'line',
data: all_shipment_money // 使用生成的时间序列数据
}
]
};
// 使用刚指定的配置项和数据显示图表
var lirun = echarts.init(document.getElementById('lirun'));
lirun.setOption(option2);
// 指定图表的配置项和数据
var option3 = {
title: {
text: '其他数据'
},
tooltip: {
trigger: 'axis'
},
legend: {
data: ['出货价值','发货价值', '回收价值']
},
grid: {
left: '3%',
right: '4%',
bottom: '15%', // 为 dataZoom 留出空间
containLabel: true
},
toolbox: {
feature: {
saveAsImage: {}
}
},
xAxis: {
type: 'time', // 设置为时间轴
boundaryGap: false,
axisLabel: {
formatter: '{MM}-{dd}' // 自定义时间显示格式
}
},
yAxis: {
type: 'value'
},
dataZoom: [ // 添加 dataZoom 组件
{
type: 'slider', // 滑动条型 dataZoom
xAxisIndex: 0, // 控制 x 轴
start: 50, // 默认起始位置0%
end: 100 // 默认结束位置50%
},
{
type: 'inside', // 内置型 dataZoom支持鼠标滚轮缩放
xAxisIndex: 0
}
],
series: [
{
name: '出货价值',
type: 'line',
data: shipment_money // 使用生成的时间序列数据
},
{
name: '发货价值',
type: 'line',
data: send_money // 使用生成的时间序列数据
},
{
name: '回收价值',
type: 'line',
data: recycle_money // 使用生成的时间序列数据
}
]
};
// 使用刚指定的配置项和数据显示图表
var qita = echarts.init(document.getElementById('qita'));
qita.setOption(option3);
</script>
</body>
</html>

Binary file not shown.

View File

@ -0,0 +1,169 @@
<?php
namespace app\command;
use app\common\model\User;
use app\common\model\UserAccount;
use app\common\model\UserStatistics;
use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;
use think\facade\Db;
use app\common\model\Order as OrderModel;
use app\common\model\OrderList;
use app\common\model\OrderListRecovery;
use app\common\model\ProfitExpenses;
use app\common\model\ProfitRvenue;
class UserStatisticsDay extends Command
{
// php think UserStatisticsDay
protected function configure()
{
$this->setName('UserStatisticsHour')->setDescription('用户每天数据统计');
}
protected function execute(Input $input, Output $output)
{
//# 统计表 user_statistics
// ELECT `id`, `login_count`, `register_count`, `created_at`, `updated_at`, `record_date` FROM `user_statistics`
//# 用户登录记录表 user_accountlast_login_time 最后登录时间时间戳int(11) 。user_id 用户id
//SELECT `id`, `user_id`, `account_token`, `token_num`, `token_time`, `last_login_time`, `last_login_ip`, `last_login_ip1`, `ip_adcode`, `ip_province`, `ip_city` FROM `user_account`
$userList = User::where('istest', '>=', 1)->field('id')->select();
$userNotArray = array_column($userList->toArray(), 'id');
// 获取当天日期
$today = date('Y-m-d');
// 检查当天的统计记录是否存在
$existingRecord = UserStatistics::where('record_date', $today)
->find();
$today_start = strtotime($today);
$today_end = strtotime($today . ' +1 day');
// 查询当天的登录人数
$loginCount = UserAccount::where('last_login_time', '>=', $today_start)
->where('last_login_time', '<', $today_end)
->count('DISTINCT user_id');
//当天注册人数
$registerCount = User::where('addtime', '>=', $today_start)
->count('id');
// 本日充值金额
$order_today_price = OrderModel::where('status', '=', 1)->whereNotIn('user_id', $userNotArray)
->whereBetweenTime(
'addtime',
$today_start,
$today_end
)->sum('price');
// 消费人数统计
$consume_today = OrderModel::where('status', '=', 1)->whereNotIn('user_id', $userNotArray)
->whereBetweenTime(
'addtime',
$today_start,
$today_end
)
->field('user_id')->group('user_id')->count('user_id');
// 消费RMB人数统计
$consume_today_price = OrderModel::where('status', '=', 1)
->where('price', '>', '0')
->whereNotIn('user_id', $userNotArray)
->whereBetweenTime(
'addtime',
$today_start,
$today_end
)
->field('user_id')->group('user_id')->count('user_id');
//今日余额消费
$money_today = OrderModel::where('status', '=', 1)->whereNotIn('user_id', $userNotArray)
->whereBetweenTime(
'addtime',
$today_start,
$today_end
)->sum('use_money');
//今日消费
$order_zhe_total = OrderModel::where('status', '=', 1)->whereNotIn('user_id', $userNotArray)
->whereBetweenTime(
'addtime',
$today_start,
$today_end
)->sum('order_zhe_total');
//今日消费
$consume_order_count = OrderModel::where('status', '=', 1)->whereNotIn('user_id', $userNotArray)
->whereBetweenTime(
'addtime',
$today_start,
$today_end
)->count();
//发放价值
$shipment_money = OrderList::whereBetweenTime('addtime', $today_start, $today_end)->whereNotIn('user_id', $userNotArray)->sum('goodslist_money');
//回收价值
$shipment_money1 = OrderList::where('status', '=', 1)->whereBetweenTime('choice_time', $today_start, $today_end)->whereNotIn('user_id', $userNotArray)->sum('goodslist_money');
$send_money = OrderList::where('status', '=', 2)->whereBetweenTime('choice_time', $today_start, $today_end)->whereNotIn('user_id', $userNotArray)->sum('goodslist_money');
$profit_expenses = ProfitExpenses::getTotalAmountByDate(date('Y-m-d'));
$profit_rvenue = ProfitRvenue::getTotalAmountByDate(date('Y-m-d'));
$profit_money = $order_zhe_total - $shipment_money;
//今日余额发放
$money_recovery_today = OrderListRecovery::
whereBetweenTime(
'addtime',
$today_start,
$today_end
)->whereNotIn('user_id', $userNotArray)->sum('money');
if ($existingRecord) {
// 更新记录
UserStatistics::where('record_date', $today)
->update([
'login_count' => $loginCount,
'register_count' => $registerCount,
'recharge_amount' => $order_today_price,
'consume_user_count' => $consume_today,
'balance_consume' => $money_today,
'balance_issue' => $money_recovery_today,
'consume_rmb_count' => $consume_today_price,
'recharge_sum' => $order_zhe_total,
'consume_order_count' => $consume_order_count,
'shipment_money' => $shipment_money,
'send_money' => $send_money,
'recycle_money' => $shipment_money1,
'profit_money' => $profit_money,
'all_shipment_money' => $shipment_money + $profit_expenses,
'all_recycle_money' => $order_zhe_total + $profit_rvenue,
'all_money' => round(($order_zhe_total + $profit_rvenue) - ($shipment_money + $profit_expenses), 2),
'updated_at' => date('Y-m-d H:i:s')
]);
} else {
// 插入新记录
UserStatistics::insert([
'login_count' => $loginCount,
'register_count' => $registerCount, // 假设注册人数统计在其他地方处理
'record_date' => $today,
'recharge_amount' => $order_today_price,
'balance_consume' => $money_today,
'balance_issue' => $money_recovery_today,
'consume_user_count' => $consume_today,
'consume_rmb_count' => $consume_today_price,
'recharge_sum' => $order_zhe_total,
'consume_order_count' => $consume_order_count,
'shipment_money' => $shipment_money,
'send_money' => $send_money,
'recycle_money' => $shipment_money1,
'profit_money' => $profit_money,
'all_shipment_money' => $shipment_money + $profit_expenses,
'all_recycle_money' => $order_zhe_total + $profit_rvenue,
'all_money' => round(($order_zhe_total + $profit_rvenue) - ($shipment_money + $profit_expenses), 2),
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s')
]);
}
}
}

View File

@ -1,59 +0,0 @@
<?php
namespace app\command;
use app\common\model\UserAccount;
use app\common\model\UserStatistics;
use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;
use think\facade\Db;
class UserStatisticsHour extends Command
{
//*/30 * * * * /www/server/cron/ZDFH
protected function configure()
{
$this->setName('UserStatisticsHour')->setDescription('用户登录数据统计');
}
protected function execute(Input $input, Output $output)
{
//# 统计表 user_statistics
// ELECT `id`, `login_count`, `register_count`, `created_at`, `updated_at`, `record_date` FROM `user_statistics`
//# 用户登录记录表 user_accountlast_login_time 最后登录时间时间戳int(11) 。user_id 用户id
//SELECT `id`, `user_id`, `account_token`, `token_num`, `token_time`, `last_login_time`, `last_login_ip`, `last_login_ip1`, `ip_adcode`, `ip_province`, `ip_city` FROM `user_account`
// 获取当天日期
$today = date('Y-m-d');
// 查询当天的登录人数
$loginCount = UserAccount::where('last_login_time', '>=', strtotime($today))
->where('last_login_time', '<', strtotime($today . ' +1 day'))
->count('DISTINCT user_id');
// 检查当天的统计记录是否存在
$existingRecord = UserStatistics::where('record_date', $today)
->find();
if ($existingRecord) {
// 更新记录
UserStatistics::where('record_date', $today)
->update(['login_count' => $loginCount, 'updated_at' => date('Y-m-d H:i:s')]);
} else {
// 插入新记录
UserStatistics::insert([
'login_count' => $loginCount,
'register_count' => 0, // 假设注册人数统计在其他地方处理
'record_date' => $today,
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s')
]);
}
}
}

View File

@ -12,18 +12,99 @@ if (!function_exists('getRandStr')) {
function getRandStr($len = 30, $special = false)
{
$chars = array(
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k",
"l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v",
"w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G",
"H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R",
"S", "T", "U", "V", "W", "X", "Y", "Z", "0", "1", "2",
"3", "4", "5", "6", "7", "8", "9"
"a",
"b",
"c",
"d",
"e",
"f",
"g",
"h",
"i",
"j",
"k",
"l",
"m",
"n",
"o",
"p",
"q",
"r",
"s",
"t",
"u",
"v",
"w",
"x",
"y",
"z",
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
"I",
"J",
"K",
"L",
"M",
"N",
"O",
"P",
"Q",
"R",
"S",
"T",
"U",
"V",
"W",
"X",
"Y",
"Z",
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9"
);
if ($special) {
$chars = array_merge($chars, array(
"!", "@", "#", "$", "?", "|", "{", "/", ":", ";",
"%", "^", "&", "*", "(", ")", "-", "_", "[", "]",
"}", "<", ">", "~", "+", "=", ",", "."
"!",
"@",
"#",
"$",
"?",
"|",
"{",
"/",
":",
";",
"%",
"^",
"&",
"*",
"(",
")",
"-",
"_",
"[",
"]",
"}",
"<",
">",
"~",
"+",
"=",
",",
"."
));
}
$charsLen = count($chars) - 1;
@ -86,14 +167,14 @@ if (!function_exists('imageUrl')) {
if ($url == '') {
return '';
}
if (strpos($url, 'http') !== false) {
$path = $url;
}
}
// else if (strpos($pre, '192.168') !== false) {#测试环境
// $path = $pre . "ceshi/public/" . $url;
// }
else{
else {
$pre = request()->domain();
if ($url === '0') {
$path = $pre;
@ -101,7 +182,7 @@ if (!function_exists('imageUrl')) {
$path = $pre . $url;
}
}
$path = str_replace('\\', '/', $path);
return $path;
@ -117,11 +198,16 @@ if (!function_exists('contentUrl')) {
function contentUrl($content)
{
$url = request()->domain() . '/';
// $url="https://mh.shhuanmeng.com/";
// if (strpos($url, '192.168') !== false) {#测试环境
// $url = $url . "ceshi/public/";
// }
$pregRule = "/<[img|IMG].*?src=[\|\"](.*?(?:[\.jpg|\.jpeg|\.png|\.gif|\.bmp]))[\|\"].*?[\/]?>/";
$content = preg_replace($pregRule, '<img src="' . $url . '${1}" style="max-width:100%">', htmlspecialchars_decode($content));
$pregRule = "/<img[^>]*src=[\"'](?!http|https)([^\"']+\.(?:jpg|jpeg|png|gif|bmp))[\"'][^>]*>/i";
// 替换相对路径的图片
$content = preg_replace_callback($pregRule, function ($matches) use ($url) {
return '<img src="' . $url . $matches[1] . '" style="max-width:100%">';
}, htmlspecialchars_decode($content));
return $content;
}
}
@ -198,12 +284,68 @@ if (!function_exists('getPrizeCode')) {
function getPrizeCode($len = 10, $special = false)
{
$chars = array(
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k",
"l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v",
"w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G",
"H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R",
"S", "T", "U", "V", "W", "X", "Y", "Z", "0", "1", "2",
"3", "4", "5", "6", "7", "8", "9"
"a",
"b",
"c",
"d",
"e",
"f",
"g",
"h",
"i",
"j",
"k",
"l",
"m",
"n",
"o",
"p",
"q",
"r",
"s",
"t",
"u",
"v",
"w",
"x",
"y",
"z",
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
"I",
"J",
"K",
"L",
"M",
"N",
"O",
"P",
"Q",
"R",
"S",
"T",
"U",
"V",
"W",
"X",
"Y",
"Z",
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9"
);
$charsLen = count($chars) - 1;
shuffle($chars); //打乱数组顺序
@ -366,7 +508,7 @@ if (!function_exists('expressWuliu')) {
$httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
list($header, $body) = explode("\r\n\r\n", $out_put, 2);
if ($httpCode == 200) {
// print("正常请求计费(其他均不计费)<br>");
// print("正常请求计费(其他均不计费)<br>");
// print($body);
$body = json_decode($body, true);
if ($body['status'] == 0 && $body['msg'] == 'ok') {
@ -376,34 +518,34 @@ if (!function_exists('expressWuliu')) {
}
} else {
if ($httpCode == 400 && strpos($header, "Invalid Param Location") !== false) {
// print("参数错误");
// print("参数错误");
return ['code' => 0, 'msg' => '参数错误'];
} elseif ($httpCode == 400 && strpos($header, "Invalid AppCode") !== false) {
// print("AppCode错误");
// print("AppCode错误");
return ['code' => 0, 'msg' => 'AppCode错误'];
} elseif ($httpCode == 400 && strpos($header, "Invalid Url") !== false) {
// print("请求的 Method、Path 或者环境错误");
// print("请求的 Method、Path 或者环境错误");
return ['code' => 0, 'msg' => '请求的 Method、Path 或者环境错误'];
} elseif ($httpCode == 403 && strpos($header, "Unauthorized") !== false) {
// print("服务未被授权或URL和Path不正确");
// print("服务未被授权或URL和Path不正确");
return ['code' => 0, 'msg' => '服务未被授权或URL和Path不正确'];
} elseif ($httpCode == 403 && strpos($header, "Quota Exhausted") !== false) {
// print("套餐包次数用完");
// print("套餐包次数用完");
return ['code' => 0, 'msg' => '套餐包次数用完'];
} elseif ($httpCode == 500) {
// print("API网关错误");
// print("API网关错误");
return ['code' => 0, 'msg' => 'API网关错误'];
} elseif ($httpCode == 0) {
// print("URL错误");
// print("URL错误");
return ['code' => 0, 'msg' => 'URL错误'];
} else {
// print("参数名错误 或 其他错误");
// print("参数名错误 或 其他错误");
// print($httpCode);
return ['code' => 0, 'msg' => '参数名错误 或 其他错误'];
$headers = explode("\r\n", $header);
@ -412,7 +554,7 @@ if (!function_exists('expressWuliu')) {
$value = explode(':', $head);
$headList[$value[0]] = $value[1];
}
print($headList['x-ca-error-message']);
print ($headList['x-ca-error-message']);
}
}
}
@ -492,7 +634,7 @@ if (!function_exists('time_jian')) {
* @param $url 图片路径
* @return int
*/
function time_jian($star_time,$end_time)
function time_jian($star_time, $end_time)
{
// 计算两个时间戳之间的差值(单位:秒)
$timeDiff = $end_time - $star_time;
@ -503,16 +645,16 @@ if (!function_exists('time_jian')) {
$hours = floor(($timeDiff / (60 * 60)) % 24);
$days = floor($timeDiff / (60 * 60 * 24));
$str = '';
if ($days){
if ($days) {
$str .= "{$days}";
}
if ($hours){
if ($hours) {
$str .= "{$hours}小时";
}
if ($minutes){
if ($minutes) {
$str .= "{$minutes}分钟";
}
if ($seconds){
if ($seconds) {
$str .= "{$seconds}";
}
return $str;
@ -520,45 +662,47 @@ if (!function_exists('time_jian')) {
}
// 订单支付日志
function writelog($filename,$content){
function writelog($filename, $content)
{
$date = date('Y-m-d');
$file = "./pay_log/".$date;
if(!is_dir($file)){
$file = "./pay_log/" . $date;
if (!is_dir($file)) {
mkdir($file);
}
$file = $file."/".$filename.".txt";
$content = "【收到信息".date("Y-m-d H:i:s",time())."".$content."\r\n\r\n";
$open=fopen($file,"a" );
fwrite($open,$content);
$file = $file . "/" . $filename . ".txt";
$content = "【收到信息" . date("Y-m-d H:i:s", time()) . "" . $content . "\r\n\r\n";
$open = fopen($file, "a");
fwrite($open, $content);
fclose($open);
}
//广告
function tencent_ad_attribution($click_id,$money,$account_id,$access_token,$user_action_set_id){
// $access_token = '80a2138abe0227598ea9ae8a2a55ba69';
function tencent_ad_attribution($click_id, $money, $account_id, $access_token, $user_action_set_id)
{
// $access_token = '80a2138abe0227598ea9ae8a2a55ba69';
// $user_action_set_id = 1200995945;
$interface = 'user_actions/add';
$url = 'https://api.e.qq.com/v1.1/' . $interface;
$common_parameters = array (
$common_parameters = array(
'access_token' => $access_token,
'timestamp' => time(),
'nonce' => md5(uniqid('', true))
);
$parameters = array (
$parameters = array(
'account_id' => $account_id,
'user_action_set_id' => $user_action_set_id,
'actions' =>
array (
array(
0 =>
array (
array(
'url' => 'ruiou.ruiouyifanshang.com',
'external_action_id' => strtolower(md5(rand(100000,999999))) . '_complete_order_1492991000_30569088_1200995945',
'external_action_id' => strtolower(md5(rand(100000, 999999))) . '_complete_order_1492991000_30569088_1200995945',
'action_time' => time(),
'action_type' => 'COMPLETE_ORDER',
// 'custom_action' => 'my_type',
// 'custom_action' => 'my_type',
'trace' => [
'click_id' => $click_id,
],
@ -569,7 +713,7 @@ function tencent_ad_attribution($click_id,$money,$account_id,$access_token,$user
),
),
);
// dd($parameters);
// dd($parameters);
// dump($common_parameters);
$parameters = json_encode($parameters);
@ -594,29 +738,30 @@ function tencent_ad_attribution($click_id,$money,$account_id,$access_token,$user
throw new \Exception($error_msg, $error_no);
}
curl_close($curl);
\think\facade\Log::write($response,'warning');
\think\facade\Log::write($response, 'warning');
return $response;
}
function getData($url,$header){
function getData($url, $header)
{
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_HTTP_VERSION,CURL_HTTP_VERSION_1_1);
curl_setopt($ch,CURLOPT_HTTPHEADER,$header);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,3);
$handles = curl_exec($ch);
curl_close($ch);
return $handles;
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);
$handles = curl_exec($ch);
curl_close($ch);
return $handles;
}

View File

@ -4,5 +4,6 @@ return [
'RankWeek' => 'app\command\RankWeek',#周榜定榜
'RankMonth' => 'app\command\RankMonth',#月榜定榜
'Zd' => 'app\command\Zd',#自动发货
'UserStatisticsDay' => 'app\command\UserStatisticsDay',#自动发货
],
];

View File

@ -84,6 +84,10 @@ return [
'url' => '/admin/ProfitRvenue',
'name' => '其它收入',
],
[
'url' => '/admin/user_statistics',
'name' => '数据统计',
],
],
],
[