1602 lines
64 KiB
PHP
Executable File
1602 lines
64 KiB
PHP
Executable File
<?php
|
||
|
||
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;
|
||
use app\common\model\Yushou;
|
||
use \think\Request;
|
||
use think\facade\View;
|
||
use app\common\model\Goods as GoodsModel;
|
||
use app\common\model\GoodsList;
|
||
use think\facade\Db;
|
||
use app\common\model\Shang;
|
||
use app\common\model\ProfitExpenses;
|
||
use app\common\model\ProfitRvenue;
|
||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
||
use PhpOffice\PhpSpreadsheet\Style\Alignment;
|
||
use PhpOffice\PhpSpreadsheet\Style\Fill;
|
||
|
||
class Statistics extends Base
|
||
{
|
||
|
||
public function profit(Request $request)
|
||
{
|
||
$goodId = trim(input('get.goodId'));
|
||
$title = trim(input('get.title'));
|
||
$status = trim(input('get.status'));
|
||
$type = trim(input('get.type'));
|
||
$addtime = trim(input('get.addtime'));
|
||
|
||
// 构建查询条件
|
||
$where = [['delete_time', '=', null]];
|
||
if ($goodId) {
|
||
$where[] = ['id', '=', $goodId];
|
||
}
|
||
if ($title) {
|
||
$where[] = ['title', 'like', '%' . $title . '%'];
|
||
}
|
||
if ($status) {
|
||
$where[] = ['status', '=', $status];
|
||
}
|
||
if ($type) {
|
||
$where[] = ['type', '=', $type];
|
||
}
|
||
return View::fetch("Statistics/profit");
|
||
}
|
||
/**
|
||
* 盒子利润统计数据接口(用于前端分离模式)
|
||
* @param Request $request
|
||
* @return \think\response\Json
|
||
*/
|
||
public function profitData(Request $request)
|
||
{
|
||
$goodId = trim(input('get.goodId'));
|
||
$title = trim(input('get.title'));
|
||
$status = trim(input('get.status'));
|
||
$type = trim(input('get.type'));
|
||
$addtime = trim(input('get.addtime'));
|
||
$page = intval(input('page', 1));
|
||
$limit = intval(input('limit', 20));
|
||
|
||
// 构建查询条件
|
||
$where = [['delete_time', '=', null]];
|
||
if ($goodId) {
|
||
$where[] = ['id', '=', $goodId];
|
||
}
|
||
if ($title) {
|
||
$where[] = ['title', 'like', '%' . $title . '%'];
|
||
}
|
||
if ($status) {
|
||
$where[] = ['status', '=', $status];
|
||
}
|
||
if ($type) {
|
||
$where[] = ['type', '=', $type];
|
||
}
|
||
|
||
// 构建SQL查询,只返回基本信息
|
||
$query = Db::name('goods')->alias('goods')
|
||
->field([
|
||
'goods.id',
|
||
'goods.title',
|
||
'goods.imgurl',
|
||
'goods.price',
|
||
'goods.stock',
|
||
'goods.status',
|
||
'goods.type'
|
||
])
|
||
->where($where)
|
||
->order(['goods.id' => 'desc']);
|
||
|
||
// 获取总数量
|
||
$total = $query->count();
|
||
|
||
// 分页
|
||
$list = $query->page($page, $limit)->select()->toArray();
|
||
|
||
// 获取盒子类型名称
|
||
$typesList = $this->getGoodsTypes();
|
||
$typesMap = [];
|
||
foreach ($typesList as $item) {
|
||
$typesMap[$item['value']] = $item['fl_name'];
|
||
}
|
||
|
||
// 初始化统计数据为0
|
||
foreach ($list as &$item) {
|
||
// 添加类型名称
|
||
$item['type_name'] = isset($typesMap[$item['type']]) ? $typesMap[$item['type']] : '未知类型';
|
||
|
||
// 初始化统计字段为0,后续会异步加载
|
||
$item['use_money'] = 0;
|
||
$item['sc_money'] = 0;
|
||
$item['re_money'] = 0;
|
||
$item['fh_money'] = 0;
|
||
$item['cj_count'] = 0;
|
||
$item['profit'] = 0;
|
||
$item['profit_rate'] = 0;
|
||
$item['is_negative'] = false;
|
||
$item['loaded'] = false; // 标记是否已加载统计数据
|
||
}
|
||
|
||
// 返回JSON数据
|
||
return json([
|
||
'code' => 0,
|
||
'msg' => '获取数据成功',
|
||
'count' => $total,
|
||
'data' => $list,
|
||
'summary' => [
|
||
'totalIncome' => 0,
|
||
'totalCost' => 0,
|
||
'totalProfit' => 0,
|
||
'totalReMoney' => 0,
|
||
'totalFhMoney' => 0,
|
||
]
|
||
]);
|
||
}
|
||
|
||
/**
|
||
* 获取盒子类型列表(用于API调用)
|
||
*/
|
||
private function getGoodsTypes()
|
||
{
|
||
$types = Db::name('goods_type')
|
||
->field('value, fl_name, remark')
|
||
->where('is_fenlei', 1)
|
||
->order('sort_order asc')
|
||
->select()
|
||
->toArray();
|
||
return $types;
|
||
}
|
||
/**
|
||
* 解析时间范围
|
||
*/
|
||
private function parseTimeRange($addtime)
|
||
{
|
||
$time = explode(' - ', $addtime);
|
||
$start_time = strtotime($time[0]);
|
||
$end_time = strtotime($time[1]) - 1;
|
||
if ($start_time > $end_time) {
|
||
throw new \Exception('开始时间不能大于结束时间');
|
||
}
|
||
return [$start_time, $end_time];
|
||
}
|
||
|
||
/**
|
||
* 计算商品的订单详情
|
||
*/
|
||
private function calculateOrderDetails($goodsId, $userList, $addtime)
|
||
{
|
||
$whe1 = [['goods_id', '=', $goodsId], ['status', '=', 1], ['user_id', 'not in', $userList]];
|
||
$whe2 = [['user_id', 'not in', $userList], ['goods_id', '=', $goodsId]];
|
||
|
||
if ($addtime) {
|
||
[$start_time, $end_time] = $this->parseTimeRange($addtime);
|
||
$whe1[] = ['addtime', 'BETWEEN', [$start_time, $end_time]];
|
||
$whe2[] = ['addtime', 'BETWEEN', [$start_time, $end_time]];
|
||
}
|
||
|
||
// 订单统计
|
||
$orderStats = OrderModel::where($whe1)
|
||
->field('COUNT(*) as count,
|
||
SUM(order_total) as order_total,
|
||
SUM(price) as count_price,
|
||
SUM(use_money) as count_yue,
|
||
SUM(use_integral) / 100 as use_integral,
|
||
SUM(use_score) as use_score,
|
||
SUM(use_coupon) as use_coupon,
|
||
SUM(order_zhe_total) as order_zhe_total')
|
||
->find();
|
||
|
||
if (!$orderStats) {
|
||
$orderStats = (object) [
|
||
'count' => 0,
|
||
'order_total' => 0,
|
||
'count_price' => 0,
|
||
'count_yue' => 0,
|
||
'use_integral' => 0,
|
||
'use_score' => 0,
|
||
'use_coupon' => 0,
|
||
'order_zhe_total' => 0
|
||
];
|
||
}
|
||
$goodslistMoney = OrderList::where($whe2)->sum('goodslist_money');
|
||
|
||
// 计算利润
|
||
$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);
|
||
|
||
$order_zhe_total = $orderStats->order_zhe_total;
|
||
// $order_zhe_total 转int
|
||
$order_zhe_total = intval($order_zhe_total);
|
||
if ($order_zhe_total <= 0) {
|
||
$order_zhe_total = 1;
|
||
}
|
||
$order_total = ($orderStats->count_price + $orderStats->count_yue + $orderStats->use_integral + $orderStats->use_score + $orderStats->use_coupon);
|
||
if ($order_total <= 0) {
|
||
$order_total = 1;
|
||
}
|
||
return [
|
||
'order_count' => round($orderStats->count, 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),
|
||
'count_OrderList' => OrderList::where($whe2)->count(), // ✅ 添加这一行
|
||
'goodslist_price' => round($goodslistMoney, 2),
|
||
'lirun' => $lirun,
|
||
'liruns' => $liruns,
|
||
'lirulv' => $goodslistMoney == 0 ? 0 : round(($order_zhe_total - $goodslistMoney) / $order_zhe_total * 100, 2),
|
||
'lirulvs' => $goodslistMoney == 0 ? 0 : round(($order_total - $goodslistMoney) / $order_total * 100, 2),
|
||
];
|
||
|
||
|
||
}
|
||
|
||
|
||
/**
|
||
* 数据统计
|
||
* @param \think\Request $request
|
||
* @return string
|
||
*/
|
||
public function DataStand(Request $request)
|
||
{
|
||
$userCount = User::count("id");
|
||
$userList = User::where('istest', '>', 0)->field('id')->select();
|
||
$userArray = array_column($userList->toArray(), 'id');
|
||
// 本日充值金额
|
||
// $order_today = OrderModel::whereNotIn('user_id', $userArray)->where('status', '=', 1)->whereBetweenTime('addtime', $ranges['today_start'], $ranges['today_end'])->sum('price');
|
||
// 今日时间
|
||
$ranges['today_start'] = strtotime('today');
|
||
$ranges['today_end'] = strtotime('tomorrow') - 1;
|
||
|
||
// 昨日时间
|
||
$ranges['yesterday_start'] = strtotime('yesterday');
|
||
$ranges['yesterday_end'] = strtotime('today') - 1;
|
||
|
||
// 本周时间(周一到周日)
|
||
$ranges['this_week_start'] = strtotime('monday this week');
|
||
$ranges['this_week_end'] = strtotime('sunday this week') + 86399;
|
||
|
||
// 上周时间(上周一到上周日)
|
||
$ranges['last_week_start'] = strtotime('monday last week');
|
||
$ranges['last_week_end'] = strtotime('sunday last week') + 86399;
|
||
|
||
// 本月时间(1号到月末)
|
||
$ranges['this_month_start'] = strtotime(date('Y-m-01'));
|
||
$ranges['this_month_end'] = strtotime(date('Y-m-t')) + 86399;
|
||
|
||
// 上月时间(上个月1号到月末)
|
||
$ranges['last_month_start'] = strtotime(date('Y-m-01', strtotime('-1 month')));
|
||
$ranges['last_month_end'] = strtotime(date('Y-m-t', strtotime('-1 month'))) + 86399;
|
||
|
||
|
||
// 今日注册人数
|
||
$user_today = User::whereBetweenTime('addtime', $ranges['today_start'], $ranges['today_end'])->count('id');
|
||
|
||
// 昨日注册人数
|
||
$user_yesterday = User::whereBetweenTime('addtime', $ranges['yesterday_start'], $ranges['yesterday_end'])->count('id');
|
||
|
||
// 本周注册人数
|
||
$user_this_week = User::whereBetweenTime('addtime', $ranges['this_week_start'], $ranges['this_week_end'])->count('id');
|
||
|
||
// 上周注册人数
|
||
$user_last_week = User::whereBetweenTime('addtime', $ranges['last_week_start'], $ranges['last_week_end'])->count('id');
|
||
|
||
// 本月注册人数
|
||
$user_this_month = User::whereBetweenTime('addtime', $ranges['this_month_start'], $ranges['this_month_end'])->count('id');
|
||
// 上月注册人数
|
||
$user_last_month = User::whereBetweenTime('addtime', $ranges['last_month_start'], $ranges['last_month_end'])->count('id');
|
||
|
||
// 本日充值金额
|
||
$order_today = OrderModel::where('status', '=', 1)->whereNotIn('user_id', $userArray)->whereBetweenTime('addtime', $ranges['today_start'], $ranges['today_end'])->sum('price');
|
||
|
||
// 昨日充值金额
|
||
$order_yesterday = OrderModel::where('status', '=', 1)->whereNotIn('user_id', $userArray)->whereBetweenTime('addtime', $ranges['yesterday_start'], $ranges['yesterday_end'])->sum('price');
|
||
|
||
// 本周充值金额
|
||
$order_this_week = OrderModel::where('status', '=', 1)->whereNotIn('user_id', $userArray)->whereBetweenTime('addtime', $ranges['this_week_start'], $ranges['this_week_end'])->sum('price');
|
||
|
||
// 上周充值金额
|
||
$order_last_week = OrderModel::where('status', '=', 1)->whereNotIn('user_id', $userArray)->whereBetweenTime('addtime', $ranges['last_week_start'], $ranges['last_week_end'])->sum('price');
|
||
|
||
// 本月充值金额
|
||
$order_this_month = OrderModel::where('status', '=', 1)->whereNotIn('user_id', $userArray)->whereBetweenTime('addtime', $ranges['this_month_start'], $ranges['this_month_end'])->sum('price');
|
||
|
||
// 上月充值金额
|
||
$order_last_month = OrderModel::where('status', '=', 1)->whereNotIn('user_id', $userArray)->whereBetweenTime('addtime', $ranges['last_month_start'], $ranges['last_month_end'])->sum('price');
|
||
// 消费人数统计
|
||
$consume_today = OrderModel::where('status', '=', 1)->whereNotIn('user_id', $userArray)->whereBetweenTime('addtime', $ranges['today_start'], $ranges['today_end'])->field('user_id')->group('user_id')->count('user_id');
|
||
$consume_yesterday = OrderModel::where('status', '=', 1)->whereNotIn('user_id', $userArray)->whereBetweenTime('addtime', $ranges['yesterday_start'], $ranges['yesterday_end'])->field('user_id')->group('user_id')->count('user_id');
|
||
$consume_this_week = OrderModel::where('status', '=', 1)->whereNotIn('user_id', $userArray)->whereBetweenTime('addtime', $ranges['this_week_start'], $ranges['this_week_end'])->field('user_id')->group('user_id')->count('user_id');
|
||
$consume_last_week = OrderModel::where('status', '=', 1)->whereNotIn('user_id', $userArray)->whereBetweenTime('addtime', $ranges['last_week_start'], $ranges['last_week_end'])->field('user_id')->group('user_id')->count('user_id');
|
||
$consume_this_month = OrderModel::where('status', '=', 1)->whereNotIn('user_id', $userArray)->whereBetweenTime('addtime', $ranges['this_month_start'], $ranges['this_month_end'])->field('user_id')->group('user_id')->count('user_id');
|
||
$consume_last_month = OrderModel::where('status', '=', 1)->whereNotIn('user_id', $userArray)->whereBetweenTime('addtime', $ranges['last_month_start'], $ranges['last_month_end'])->field('user_id')->group('user_id')->count('user_id');
|
||
|
||
// RMB消费人数统计
|
||
$rmb_consume_today = OrderModel::where('status', '=', 1)->whereNotIn('user_id', $userArray)->where('price', '>', 0)->whereBetweenTime('addtime', $ranges['today_start'], $ranges['today_end'])->field('user_id')->group('user_id')->count('user_id');
|
||
$rmb_consume_yesterday = OrderModel::where('status', '=', 1)->whereNotIn('user_id', $userArray)->where('price', '>', 0)->whereBetweenTime('addtime', $ranges['yesterday_start'], $ranges['yesterday_end'])->field('user_id')->group('user_id')->count('user_id');
|
||
$rmb_consume_this_week = OrderModel::where('status', '=', 1)->whereNotIn('user_id', $userArray)->where('price', '>', 0)->whereBetweenTime('addtime', $ranges['this_week_start'], $ranges['this_week_end'])->field('user_id')->group('user_id')->count('user_id');
|
||
$rmb_consume_last_week = OrderModel::where('status', '=', 1)->whereNotIn('user_id', $userArray)->where('price', '>', 0)->whereBetweenTime('addtime', $ranges['last_week_start'], $ranges['last_week_end'])->field('user_id')->group('user_id')->count('user_id');
|
||
$rmb_consume_this_month = OrderModel::where('status', '=', 1)->whereNotIn('user_id', $userArray)->where('price', '>', 0)->whereBetweenTime('addtime', $ranges['this_month_start'], $ranges['this_month_end'])->field('user_id')->group('user_id')->count('user_id');
|
||
$rmb_consume_last_month = OrderModel::where('status', '=', 1)->whereNotIn('user_id', $userArray)->where('price', '>', 0)->whereBetweenTime('addtime', $ranges['last_month_start'], $ranges['last_month_end'])->field('user_id')->group('user_id')->count('user_id');
|
||
|
||
//今日余额消费
|
||
$money_today = OrderModel::where('status', '=', 1)->whereNotIn('user_id', $userArray)->whereBetweenTime('addtime', $ranges['today_start'], $ranges['today_end'])->sum('use_money');
|
||
$money_yesterday = OrderModel::where('status', '=', 1)->whereNotIn('user_id', $userArray)->whereBetweenTime('addtime', $ranges['yesterday_start'], $ranges['yesterday_end'])->sum('use_money');
|
||
//今日积分抵扣
|
||
$score_yesterday = OrderModel::where('status', '=', 1)->whereNotIn('user_id', $userArray)->whereBetweenTime('addtime', $ranges['yesterday_start'], $ranges['yesterday_end'])->sum('use_score');
|
||
$score_today = OrderModel::where('status', '=', 1)->whereNotIn('user_id', $userArray)->whereBetweenTime('addtime', $ranges['today_start'], $ranges['today_end'])->sum('use_score');
|
||
//今日余额发放
|
||
$money_recovery_today = OrderListRecovery::whereBetweenTime('addtime', $ranges['today_start'], $ranges['today_end'])->whereNotIn('user_id', $userArray)->sum('money');
|
||
$money_recovery_yesterday = OrderListRecovery::whereBetweenTime('addtime', $ranges['yesterday_start'], $ranges['yesterday_end'])->whereNotIn('user_id', $userArray)->sum('money');
|
||
//今日优惠卷消费
|
||
$coupon_today = OrderModel::where('status', '=', 1)->whereBetweenTime('addtime', $ranges['today_start'], $ranges['today_end'])->whereNotIn('user_id', $userArray)->sum('use_coupon');
|
||
|
||
//今日收入
|
||
$order_zhe_total = OrderModel::where('status', '=', 1)->whereNotIn('user_id', $userArray)->whereBetweenTime('addtime', $ranges['today_start'], $ranges['today_end'])->sum('order_zhe_total');
|
||
$order_goodslist_money = OrderList::whereBetweenTime('addtime', $ranges['today_start'], $ranges['today_end'])->whereNotIn('user_id', $userArray)->sum('goodslist_money');
|
||
$order_goodslist_count = OrderList::whereBetweenTime('addtime', $ranges['today_start'], $ranges['today_end'])->whereNotIn('user_id', $userArray)->count();
|
||
$order_count = OrderModel::where('status', '=', 1)->whereNotIn('user_id', $userArray)->whereBetweenTime('addtime', $ranges['today_start'], $ranges['today_end'])->count();
|
||
|
||
$order_zhe_total_yester = round(OrderModel::where('status', '=', 1)->whereNotIn('user_id', $userArray)->whereBetweenTime('addtime', $ranges['yesterday_start'], $ranges['yesterday_end'])->sum('order_zhe_total'), 2);
|
||
$order_goodslist_money_yester = round(OrderList::whereBetweenTime('addtime', $ranges['yesterday_start'], $ranges['yesterday_end'])->whereNotIn('user_id', $userArray)->sum('goodslist_money'), 2);
|
||
|
||
$order_zhe_total_week = round(OrderModel::where('status', '=', 1)->whereNotIn('user_id', $userArray)->whereBetweenTime('addtime', $ranges['this_week_start'], $ranges['this_week_end'])->sum('order_zhe_total'), 2);
|
||
$order_goodslist_money_week = round(OrderList::whereBetweenTime('addtime', $ranges['this_week_start'], $ranges['this_week_end'])->whereNotIn('user_id', $userArray)->sum('goodslist_money'), 2);
|
||
|
||
$order_zhe_total_last_week = round(OrderModel::where('status', '=', 1)->whereBetweenTime('addtime', $ranges['last_week_start'], $ranges['last_week_end'])->whereNotIn('user_id', $userArray)->sum('order_zhe_total'), 2);
|
||
$order_goodslist_money__last_week = round(OrderList::whereBetweenTime('addtime', $ranges['last_week_start'], $ranges['last_week_end'])->whereNotIn('user_id', $userArray)->sum('goodslist_money'), 2);
|
||
|
||
|
||
$order_zhe_total_month = round(OrderModel::where('status', '=', 1)->whereBetweenTime('addtime', $ranges['this_month_start'], $ranges['this_month_end'])->whereNotIn('user_id', $userArray)->sum('order_zhe_total'), 2);
|
||
$order_goodslist_money_month = round(OrderList::whereBetweenTime('addtime', $ranges['this_month_start'], $ranges['this_month_end'])->whereNotIn('user_id', $userArray)->sum('goodslist_money'), 2);
|
||
|
||
$order_zhe_total_last_month = round(OrderModel::where('status', '=', 1)->whereBetweenTime('addtime', $ranges['last_month_start'], $ranges['last_month_end'])->whereNotIn('user_id', $userArray)->sum('order_zhe_total'), 2);
|
||
$order_goodslist_money__last_month = round(OrderList::whereBetweenTime('addtime', $ranges['last_month_start'], $ranges['last_month_end'])->whereNotIn('user_id', $userArray)->sum('goodslist_money'), 2);
|
||
|
||
$profit_expenses = ProfitExpenses::getTotalAmountByDate(date('Y-m-d'));
|
||
$profit_expenses_yester = ProfitExpenses::getTotalAmountByDate(date('Y-m-d', strtotime('-1 day')));
|
||
$profit_expenses_week = ProfitExpenses::getTotalAmountByDates(date('Y-m-d', $ranges['this_week_start']), date('Y-m-d', $ranges['this_week_end']));
|
||
$profit_expenses_last_week = ProfitExpenses::getTotalAmountByDates(date('Y-m-d', $ranges['last_week_start']), date('Y-m-d', $ranges['last_week_end']));
|
||
$profit_expenses_money = ProfitExpenses::getTotalAmountByDates(date('Y-m-d', $ranges['this_month_start']), date('Y-m-d', $ranges['this_month_end']));
|
||
$profit_expenses_last_money = ProfitExpenses::getTotalAmountByDates(date('Y-m-d', $ranges['last_month_start']), date('Y-m-d', $ranges['last_month_end']));
|
||
|
||
$profit_rvenue = ProfitRvenue::getTotalAmountByDate(date('Y-m-d'));
|
||
$profit_rvenue_yester = ProfitRvenue::getTotalAmountByDate(date('Y-m-d', strtotime('-1 day')));
|
||
$profit_rvenue_week = ProfitRvenue::getTotalAmountByDates(date('Y-m-d', $ranges['this_week_start']), date('Y-m-d', $ranges['this_week_end']));
|
||
$profit_rvenue_last_week = ProfitRvenue::getTotalAmountByDates(date('Y-m-d', $ranges['last_week_start']), date('Y-m-d', $ranges['last_week_end']));
|
||
$profit_rvenue_money = ProfitRvenue::getTotalAmountByDates(date('Y-m-d', $ranges['this_month_start']), date('Y-m-d', $ranges['this_month_end']));
|
||
$profit_rvenue_last_money = ProfitRvenue::getTotalAmountByDates(date('Y-m-d', $ranges['last_month_start']), date('Y-m-d', $ranges['last_month_end']));
|
||
|
||
|
||
View::assign('profit_expenses', $profit_expenses);
|
||
View::assign('money_today', $money_today);
|
||
View::assign('money_yesterday', $money_yesterday);
|
||
View::assign('coupon_today', $coupon_today);
|
||
View::assign('profit_rvenue', $profit_rvenue);
|
||
View::assign('score_today', $score_today);
|
||
View::assign('score_yesterday', $score_yesterday);
|
||
View::assign('money_recovery_today', $money_recovery_today);
|
||
View::assign('money_recovery_yesterday', $money_recovery_yesterday);
|
||
View::assign('order_zhe_total', $order_zhe_total);
|
||
View::assign('order_goodslist_money', $order_goodslist_money);
|
||
View::assign('order_goodslist_count', $order_goodslist_count);
|
||
View::assign('order_count', $order_count);
|
||
View::assign('order_lirun', round($order_zhe_total + $profit_rvenue - $order_goodslist_money - $profit_expenses, 2));
|
||
View::assign('order_lirun_yester', round($order_zhe_total_yester + $profit_rvenue_yester - $order_goodslist_money_yester - $profit_expenses_yester, 2) . " ($order_zhe_total_yester + $profit_rvenue_yester - $order_goodslist_money_yester - $profit_expenses_yester)");
|
||
View::assign('order_lirun_week', round($order_zhe_total_week + $profit_rvenue_week - $order_goodslist_money_week - $profit_expenses_week, 2) . " ({$order_zhe_total_week} + $profit_rvenue_week - $order_goodslist_money_week - $profit_expenses_week)");
|
||
View::assign('order_lirun_last_week', round($order_zhe_total_last_week + $profit_rvenue_last_week - $order_goodslist_money__last_week - $profit_expenses_last_week, 2) . " ($order_zhe_total_last_week +$profit_rvenue_last_week - $order_goodslist_money__last_week - $profit_expenses_last_week)");
|
||
View::assign('order_zhe_total_month', round($order_zhe_total_month + $profit_rvenue_money - $order_goodslist_money_month - $profit_expenses_money, 2) . " ($order_zhe_total_month + $profit_rvenue_money - $order_goodslist_money_month - $profit_expenses_money)");
|
||
View::assign('order_lirun_last_month', round($order_zhe_total_last_month + $profit_rvenue_last_money - $order_goodslist_money__last_month - $profit_expenses_last_money, 2) . " ($order_zhe_total_last_month + $profit_rvenue_last_money - $order_goodslist_money__last_month- $profit_expenses_last_money)");
|
||
|
||
// 赋值给模板
|
||
View::assign('userCount', $userCount);
|
||
View::assign('user_today', $user_today);
|
||
View::assign('user_yesterday', $user_yesterday);
|
||
View::assign('user_this_week', $user_this_week);
|
||
View::assign('user_last_week', $user_last_week);
|
||
View::assign('user_this_month', $user_this_month);
|
||
View::assign('user_last_month', $user_last_month);
|
||
// 充值订单数据
|
||
View::assign('order_today', $order_today);
|
||
View::assign('order_yesterday', $order_yesterday);
|
||
View::assign('order_this_week', $order_this_week);
|
||
View::assign('order_last_week', $order_last_week);
|
||
View::assign('order_this_month', $order_this_month);
|
||
View::assign('order_last_month', $order_last_month);
|
||
|
||
View::assign('consume_today', $consume_today);
|
||
View::assign('consume_yesterday', $consume_yesterday);
|
||
View::assign('consume_this_week', $consume_this_week);
|
||
View::assign('consume_last_week', $consume_last_week);
|
||
View::assign('consume_this_month', $consume_this_month);
|
||
View::assign('consume_last_month', $consume_last_month);
|
||
|
||
View::assign('rmb_consume_today', $rmb_consume_today);
|
||
View::assign('rmb_consume_yesterday', $rmb_consume_yesterday);
|
||
View::assign('rmb_consume_this_week', $rmb_consume_this_week);
|
||
View::assign('rmb_consume_last_week', $rmb_consume_last_week);
|
||
View::assign('rmb_consume_this_month', $rmb_consume_this_month);
|
||
View::assign('rmb_consume_last_month', $rmb_consume_last_month);
|
||
|
||
View::assign('ranges', $ranges);
|
||
|
||
|
||
return View::fetch("Statistics/dataStand");
|
||
}
|
||
|
||
|
||
public function UserStatistics()
|
||
{
|
||
|
||
$list = UserStatistics::order('id desc')->limit(30)->select();
|
||
View::assign('list', $list);
|
||
return View::fetch('Statistics/userstatistics');
|
||
}
|
||
|
||
/**
|
||
* 订单列表
|
||
*/
|
||
public function orderList(Request $request)
|
||
{
|
||
$goodsId = $request->param('goods_id', 0, 'intval');
|
||
|
||
// 获取测试用户ID
|
||
$testUsers = User::where('istest', '>', 0)->column('id');
|
||
|
||
// 查询条件
|
||
$where = [
|
||
['status', '=', 1],
|
||
['goods_id', '=', $goodsId]
|
||
];
|
||
|
||
if (!empty($testUsers)) {
|
||
$where[] = ['user_id', 'not in', $testUsers];
|
||
}
|
||
|
||
// 获取订单列表
|
||
$list = OrderModel::where($where)
|
||
->append(['user_info'])
|
||
->order('id', 'desc')
|
||
->paginate(['list_rows' => 50, 'query' => request()->param()]);
|
||
|
||
// 传递数据给视图
|
||
View::assign([
|
||
'list' => $list,
|
||
'page' => $list->render(),
|
||
'goods_id' => $goodsId
|
||
]);
|
||
|
||
return View::fetch("Statistics/orderList");
|
||
}
|
||
|
||
/**
|
||
* 出货列表
|
||
*/
|
||
public function goodsList(Request $request)
|
||
{
|
||
$goodsId = $request->param('goods_id', 0, 'intval');
|
||
|
||
// 获取测试用户ID
|
||
$testUsers = User::where('istest', '>', 0)->column('id');
|
||
|
||
// 查询条件
|
||
$where = [
|
||
['goods_id', '=', $goodsId]
|
||
];
|
||
|
||
if (!empty($testUsers)) {
|
||
$where[] = ['user_id', 'not in', $testUsers];
|
||
}
|
||
|
||
// 获取出货列表
|
||
$list = OrderList::where($where)
|
||
->order('id', 'desc')
|
||
->paginate(['list_rows' => 50, 'query' => request()->param()]);
|
||
|
||
// 传递数据给视图
|
||
View::assign([
|
||
'list' => $list,
|
||
'page' => $list->render(),
|
||
'goods_id' => $goodsId
|
||
]);
|
||
|
||
return View::fetch("Statistics/goodsList");
|
||
}
|
||
|
||
/**
|
||
* 兑换列表
|
||
*/
|
||
public function exchangeList(Request $request)
|
||
{
|
||
$goodsId = $request->param('goods_id', 0, 'intval');
|
||
|
||
// 获取测试用户ID
|
||
$testUsers = User::where('istest', '>', 0)->column('id');
|
||
|
||
// 查询条件
|
||
$where = [
|
||
['goods_id', '=', $goodsId]
|
||
];
|
||
|
||
$where[] = ['recovery_num', '!=', ''];
|
||
// $where[] = ['recovery_num', '!=', null];
|
||
|
||
if (!empty($testUsers)) {
|
||
$where[] = ['user_id', 'not in', $testUsers];
|
||
}
|
||
|
||
// 获取兑换列表
|
||
$list = OrderList::where($where)
|
||
->order('id', 'desc')
|
||
->paginate(['list_rows' => 50, 'query' => request()->param()]);
|
||
|
||
// 传递数据给视图
|
||
View::assign([
|
||
'list' => $list,
|
||
'page' => $list->render(),
|
||
'goods_id' => $goodsId
|
||
]);
|
||
|
||
return View::fetch("Statistics/exchangeList");
|
||
}
|
||
|
||
/**
|
||
* 发货列表
|
||
*/
|
||
public function shipmentList(Request $request)
|
||
{
|
||
$goodsId = $request->param('goods_id', 0, 'intval');
|
||
|
||
// 获取测试用户ID
|
||
$testUsers = User::where('istest', '>', 0)->column('id');
|
||
|
||
// 查询条件
|
||
$where = [
|
||
['goods_id', '=', $goodsId]
|
||
];
|
||
|
||
$where[] = ['send_num', '<>', ''];
|
||
// $where[] = ['send_num', '<>', null];
|
||
|
||
if (!empty($testUsers)) {
|
||
$where[] = ['user_id', 'not in', $testUsers];
|
||
}
|
||
|
||
// 获取发货列表
|
||
$list = OrderList::where($where)
|
||
->order('id', 'desc')
|
||
->paginate(['list_rows' => 50, 'query' => request()->param()]);
|
||
|
||
// 传递数据给视图
|
||
View::assign([
|
||
'list' => $list,
|
||
'page' => $list->render(),
|
||
'goods_id' => $goodsId
|
||
]);
|
||
|
||
return View::fetch("Statistics/shipmentList");
|
||
}
|
||
|
||
/**
|
||
* 出货概览
|
||
*/
|
||
public function productsOverview(Request $request)
|
||
{
|
||
$goodsId = $request->param('goods_id', 0, 'intval');
|
||
|
||
// 获取测试用户ID
|
||
$testUsers = User::where('istest', '>', 0)->column('id');
|
||
|
||
// 查询条件
|
||
$where = [
|
||
['goods_id', '=', $goodsId]
|
||
];
|
||
|
||
if (!empty($testUsers)) {
|
||
$where[] = ['user_id', 'not in', $testUsers];
|
||
}
|
||
|
||
// 第一个SQL:按奖品ID分组统计出货数量
|
||
$productStats = OrderList::where($where)
|
||
->field('goodslist_id, COUNT(1) as goods_count')
|
||
->group('goodslist_id')
|
||
->select()
|
||
->toArray();
|
||
|
||
// 获取所有涉及的奖品ID
|
||
$goodslistIds = array_column($productStats, 'goodslist_id');
|
||
|
||
// 第二个SQL:查询奖品详细信息
|
||
$productInfos = [];
|
||
if (!empty($goodslistIds)) {
|
||
$productInfos = GoodsList::where('id', 'in', $goodslistIds)
|
||
->field('id, title, imgurl, price, money, sc_money, real_pro, shang_id')
|
||
->select()
|
||
->toArray();
|
||
}
|
||
|
||
// 将两个查询结果合并,以奖品ID为键
|
||
$productInfoMap = [];
|
||
foreach ($productInfos as $info) {
|
||
$productInfoMap[$info['id']] = $info;
|
||
}
|
||
|
||
// 合并结果
|
||
$result = [];
|
||
foreach ($productStats as $stat) {
|
||
$goodslistId = $stat['goodslist_id'];
|
||
if (array_key_exists($goodslistId, $productInfoMap)) {
|
||
$result[] = array_merge($stat, $productInfoMap[$goodslistId]);
|
||
}
|
||
}
|
||
|
||
// 获取盒子信息
|
||
$boxInfo = GoodsModel::where('id', $goodsId)->find();
|
||
|
||
// 传递数据给视图
|
||
View::assign([
|
||
'list' => $result,
|
||
'goods_id' => $goodsId,
|
||
'boxInfo' => $boxInfo
|
||
]);
|
||
|
||
return View::fetch('Statistics/productsOverview');
|
||
}
|
||
|
||
/**
|
||
* 获取单个盒子的统计数据
|
||
* @param Request $request
|
||
* @return \think\response\Json
|
||
*/
|
||
public function getBoxStatistics(Request $request)
|
||
{
|
||
$goodId = intval(input('get.goods_id', 0));
|
||
$addtime = trim(input('get.addtime', ''));
|
||
|
||
if ($goodId <= 0) {
|
||
return json(['code' => 1, 'msg' => '参数错误']);
|
||
}
|
||
|
||
// 解析时间范围
|
||
$hasTimeRange = false;
|
||
$startTime = 0;
|
||
$endTime = 0;
|
||
if (!empty($addtime)) {
|
||
$hasTimeRange = true;
|
||
$times = explode(' - ', $addtime);
|
||
$startTime = strtotime($times[0]);
|
||
$endTime = strtotime($times[1]);
|
||
}
|
||
|
||
// 获取测试用户ID
|
||
$testUsers = User::where('istest', '>', 0)
|
||
->whereOr('status', '=', 2)
|
||
->column('id');
|
||
$testUserIds = empty($testUsers) ? [0] : $testUsers;
|
||
|
||
// 获取盒子基本信息
|
||
$goodsInfo = Db::name('goods')
|
||
->where('id', '=', $goodId)
|
||
->field('id')
|
||
->find();
|
||
|
||
if (!$goodsInfo) {
|
||
return json(['code' => 1, 'msg' => '盒子不存在']);
|
||
}
|
||
|
||
// 查询1:获取充值金额和余额消费总和
|
||
$orderQuery = Db::name('order')
|
||
->where('status', '=', 1)
|
||
->where(function ($query) {
|
||
$query->where('price', '>', 0)
|
||
->whereOr('use_money', '>', 0);
|
||
})
|
||
->where('goods_id', '=', $goodId)
|
||
->where('user_id', 'not in', $testUserIds);
|
||
|
||
// 只有在有时间范围时才添加时间条件
|
||
if ($hasTimeRange) {
|
||
$orderQuery->where('pay_time', '>', $startTime)
|
||
->where('pay_time', '<', $endTime);
|
||
}
|
||
|
||
// 分别获取price和use_money的总和后相加
|
||
$priceSum = $orderQuery->sum('price');
|
||
$useMoneySum = $orderQuery->sum('use_money');
|
||
$useMoney = floatval($priceSum) + floatval($useMoneySum);
|
||
|
||
// 查询2:获取出货成本
|
||
$scMoneyQuery = Db::name('order_list')
|
||
->where('goods_id', '=', $goodId)
|
||
->where('user_id', 'not in', $testUserIds);
|
||
|
||
if ($hasTimeRange) {
|
||
$scMoneyQuery->where('addtime', '>', $startTime)
|
||
->where('addtime', '<', $endTime);
|
||
}
|
||
|
||
$scMoney = $scMoneyQuery->sum('goodslist_money');
|
||
|
||
// 查询3:获取兑换成本
|
||
$reMoneyQuery = Db::name('order_list')
|
||
->where('goods_id', '=', $goodId)
|
||
->where('LENGTH(recovery_num)', '>', 0)
|
||
->where('user_id', 'not in', $testUserIds);
|
||
|
||
if ($hasTimeRange) {
|
||
$reMoneyQuery->where('addtime', '>', $startTime)
|
||
->where('addtime', '<', $endTime);
|
||
}
|
||
|
||
$reMoney = $reMoneyQuery->sum('goodslist_money');
|
||
|
||
// 查询4:获取发货成本
|
||
$fhMoneyQuery = Db::name('order_list')
|
||
->where('goods_id', '=', $goodId)
|
||
->where('LENGTH(send_num)', '>', 0)
|
||
->where('user_id', 'not in', $testUserIds);
|
||
|
||
if ($hasTimeRange) {
|
||
$fhMoneyQuery->where('addtime', '>', $startTime)
|
||
->where('addtime', '<', $endTime);
|
||
}
|
||
|
||
$fhMoney = $fhMoneyQuery->sum('goodslist_money');
|
||
|
||
// 查询5:获取抽奖次数
|
||
$cjCountQuery = Db::name('order_list')
|
||
->where('goods_id', '=', $goodId)
|
||
->where('user_id', 'not in', $testUserIds)
|
||
->where('parent_goods_list_id', '=', 0);
|
||
|
||
if ($hasTimeRange) {
|
||
$cjCountQuery->where('addtime', '>', $startTime)
|
||
->where('addtime', '<', $endTime);
|
||
}
|
||
|
||
$cjCount = $cjCountQuery->count();
|
||
|
||
// 组合数据
|
||
$data = [
|
||
'id' => $goodId,
|
||
'use_money' => floatval($useMoney),
|
||
'sc_money' => floatval($scMoney),
|
||
're_money' => floatval($reMoney),
|
||
'fh_money' => floatval($fhMoney),
|
||
'cj_count' => intval($cjCount)
|
||
];
|
||
|
||
// 计算利润和利润率
|
||
$data['profit'] = $data['use_money'] - ($data['sc_money'] - $data['re_money']);
|
||
$data['profit_rate'] = $data['use_money'] > 0 ? round(($data['profit'] / $data['use_money']) * 100, 2) : 0;
|
||
$data['is_negative'] = $data['profit'] < 0;
|
||
|
||
return json(['code' => 0, 'msg' => '获取成功', 'data' => $data]);
|
||
}
|
||
|
||
/**
|
||
* 获取所有盒子的统计数据汇总
|
||
* @param Request $request
|
||
* @return \think\response\Json
|
||
*/
|
||
public function getSummaryStatistics(Request $request)
|
||
{
|
||
$goodId = trim(input('get.goodId'));
|
||
$title = trim(input('get.title'));
|
||
$status = trim(input('get.status'));
|
||
$type = trim(input('get.type'));
|
||
$addtime = trim(input('get.addtime'));
|
||
|
||
// 解析时间范围
|
||
$hasTimeRange = false;
|
||
$startTime = 0;
|
||
$endTime = 0;
|
||
if (!empty($addtime)) {
|
||
$hasTimeRange = true;
|
||
$times = explode(' - ', $addtime);
|
||
$startTime = strtotime($times[0]);
|
||
$endTime = strtotime($times[1]);
|
||
}
|
||
|
||
// 构建查询条件
|
||
$goodsWhere = [['delete_time', '=', null]];
|
||
if ($goodId) {
|
||
$goodsWhere[] = ['id', '=', $goodId];
|
||
}
|
||
if ($title) {
|
||
$goodsWhere[] = ['title', 'like', '%' . $title . '%'];
|
||
}
|
||
if ($status) {
|
||
$goodsWhere[] = ['status', '=', $status];
|
||
}
|
||
if ($type) {
|
||
$goodsWhere[] = ['type', '=', $type];
|
||
}
|
||
|
||
// 获取符合条件的盒子ID列表
|
||
$goodsIds = Db::name('goods')
|
||
->where($goodsWhere)
|
||
->column('id');
|
||
|
||
if (empty($goodsIds)) {
|
||
return json([
|
||
'code' => 0,
|
||
'msg' => '没有找到符合条件的盒子',
|
||
'data' => [
|
||
'totalIncome' => 0,
|
||
'totalCost' => 0,
|
||
'totalProfit' => 0,
|
||
'totalReMoney' => 0,
|
||
'totalFhMoney' => 0
|
||
]
|
||
]);
|
||
}
|
||
|
||
// 获取测试用户ID
|
||
$testUsers = User::where('istest', '>', 0) ->whereOr('status', '=', 2)->column('id');
|
||
$testUserIds = empty($testUsers) ? [0] : $testUsers;
|
||
|
||
// 查询1:获取充值金额和余额消费总和
|
||
$orderQuery = Db::name('order')
|
||
->where('status', '=', 1)
|
||
->where(function ($query) {
|
||
$query->where('price', '>', 0)
|
||
->whereOr('use_money', '>', 0);
|
||
})
|
||
->where('goods_id', 'in', $goodsIds)
|
||
->where('user_id', 'not in', $testUserIds);
|
||
|
||
// 只有在有时间范围时才添加时间条件
|
||
if ($hasTimeRange) {
|
||
$orderQuery->where('pay_time', '>', $startTime)
|
||
->where('pay_time', '<', $endTime);
|
||
}
|
||
|
||
// 分别获取price和use_money的总和后相加
|
||
$priceSum = $orderQuery->sum('price');
|
||
$useMoneySum = $orderQuery->sum('use_money');
|
||
$totalIncome = floatval($priceSum) + floatval($useMoneySum);
|
||
|
||
// 查询2:获取出货成本
|
||
$scMoneyQuery = Db::name('order_list')
|
||
->where('goods_id', 'in', $goodsIds)
|
||
->where('user_id', 'not in', $testUserIds);
|
||
|
||
if ($hasTimeRange) {
|
||
$scMoneyQuery->where('addtime', '>', $startTime)
|
||
->where('addtime', '<', $endTime);
|
||
}
|
||
|
||
$totalCost = floatval($scMoneyQuery->sum('goodslist_money'));
|
||
|
||
// 查询3:获取兑换成本
|
||
$reMoneyQuery = Db::name('order_list')
|
||
->where('goods_id', 'in', $goodsIds)
|
||
->where('LENGTH(recovery_num)', '>', 0)
|
||
->where('user_id', 'not in', $testUserIds);
|
||
|
||
if ($hasTimeRange) {
|
||
$reMoneyQuery->where('addtime', '>', $startTime)
|
||
->where('addtime', '<', $endTime);
|
||
}
|
||
|
||
$totalReMoney = floatval($reMoneyQuery->sum('goodslist_money'));
|
||
|
||
// 查询4:获取发货成本
|
||
$fhMoneyQuery = Db::name('order_list')
|
||
->where('goods_id', 'in', $goodsIds)
|
||
->where('LENGTH(send_num)', '>', 0)
|
||
->where('user_id', 'not in', $testUserIds);
|
||
|
||
if ($hasTimeRange) {
|
||
$fhMoneyQuery->where('addtime', '>', $startTime)
|
||
->where('addtime', '<', $endTime);
|
||
}
|
||
|
||
$totalFhMoney = floatval($fhMoneyQuery->sum('goodslist_money'));
|
||
|
||
// 计算总利润
|
||
$totalProfit = $totalIncome - ($totalCost - $totalReMoney);
|
||
|
||
// 返回汇总数据
|
||
$data = [
|
||
'totalIncome' => $totalIncome,
|
||
'totalCost' => $totalCost,
|
||
'totalProfit' => $totalProfit,
|
||
'totalReMoney' => $totalReMoney,
|
||
'totalFhMoney' => $totalFhMoney
|
||
];
|
||
|
||
return json(['code' => 0, 'msg' => '获取成功', 'data' => $data]);
|
||
}
|
||
|
||
/**
|
||
* 导出盒子利润统计数据
|
||
* @return void
|
||
*/
|
||
public function exportProfit()
|
||
{
|
||
// 获取查询参数
|
||
$goodId = trim(input('get.goodId'));
|
||
$title = trim(input('get.title'));
|
||
$status = trim(input('get.status'));
|
||
$type = trim(input('get.type'));
|
||
$addtime = trim(input('get.addtime'));
|
||
|
||
// 解析时间范围
|
||
$hasTimeRange = false;
|
||
$startTime = 0;
|
||
$endTime = 0;
|
||
if (!empty($addtime)) {
|
||
$hasTimeRange = true;
|
||
$times = explode(' - ', $addtime);
|
||
$startTime = strtotime($times[0]);
|
||
$endTime = strtotime($times[1]);
|
||
}
|
||
|
||
// 构建查询条件
|
||
$where = [['delete_time', '=', null]];
|
||
if ($goodId) {
|
||
$where[] = ['id', '=', $goodId];
|
||
}
|
||
if ($title) {
|
||
$where[] = ['title', 'like', '%' . $title . '%'];
|
||
}
|
||
if ($status) {
|
||
$where[] = ['status', '=', $status];
|
||
}
|
||
if ($type) {
|
||
$where[] = ['type', '=', $type];
|
||
}
|
||
|
||
// 获取测试用户ID
|
||
$testUsers = User::where('istest', '>', 0) ->whereOr('status', '=', 2)->column('id');
|
||
$testUserIds = empty($testUsers) ? [0] : $testUsers;
|
||
|
||
// 获取盒子类型名称映射
|
||
$typesList = $this->getGoodsTypes();
|
||
$typesMap = [];
|
||
foreach ($typesList as $item) {
|
||
$typesMap[$item['value']] = $item['fl_name'];
|
||
}
|
||
|
||
// 查询所有符合条件的盒子
|
||
$goods = Db::name('goods')
|
||
->where($where)
|
||
->field(['id', 'title', 'status', 'type', 'price', 'imgurl'])
|
||
->order('id desc')
|
||
->select()
|
||
->toArray();
|
||
|
||
// 如果没有数据,返回错误提示
|
||
if (empty($goods)) {
|
||
return json(['code' => 1, 'msg' => '没有找到符合条件的数据']);
|
||
}
|
||
|
||
// 创建一个新的工作簿
|
||
$spreadsheet = new Spreadsheet();
|
||
$sheet = $spreadsheet->getActiveSheet();
|
||
|
||
// 设置工作表名称
|
||
$sheet->setTitle('盒子利润统计');
|
||
|
||
// 设置表头
|
||
$headers = [
|
||
'ID', '盒子名称', '盒子类型', '状态', '单价', '抽奖次数',
|
||
'收入(微信+钻石)', '出货价值', '已兑换达达卷', '已申请发货',
|
||
'单盒子利润', '单盒子利润比(%)', '利润', '利润率(%)'
|
||
];
|
||
|
||
foreach ($headers as $col => $header) {
|
||
$sheet->setCellValueByColumnAndRow($col + 1, 1, $header);
|
||
}
|
||
|
||
// 设置表头样式
|
||
$headerStyle = [
|
||
'font' => ['bold' => true],
|
||
'alignment' => [
|
||
'horizontal' => Alignment::HORIZONTAL_CENTER,
|
||
],
|
||
'fill' => [
|
||
'fillType' => Fill::FILL_SOLID,
|
||
'startColor' => ['rgb' => 'E0E0E0'],
|
||
],
|
||
];
|
||
$sheet->getStyle('A1:N1')->applyFromArray($headerStyle);
|
||
|
||
// 填充数据
|
||
$row = 2;
|
||
foreach ($goods as $item) {
|
||
// 获取该盒子的统计数据
|
||
$statsData = $this->getBoxProfitStats($item['id'], $hasTimeRange, $startTime, $endTime, $testUserIds);
|
||
|
||
// 获取状态文字
|
||
$statusText = '';
|
||
switch ($item['status']) {
|
||
case 1: $statusText = '上架'; break;
|
||
case 2: $statusText = '下架'; break;
|
||
case 3: $statusText = '售罄'; break;
|
||
default: $statusText = '自动下架'; break;
|
||
}
|
||
|
||
// 计算单盒子利润和单盒子利润比
|
||
$boxIncome = $item['price'] * $statsData['cj_count'];
|
||
$singleBoxProfit = $boxIncome - $statsData['sc_money'];
|
||
$singleBoxProfitRate = 0;
|
||
if ($boxIncome > 0) {
|
||
$singleBoxProfitRate = ($singleBoxProfit / $boxIncome) * 100;
|
||
}
|
||
|
||
// 填充一行数据
|
||
$sheet->setCellValue('A' . $row, $item['id']);
|
||
$sheet->setCellValue('B' . $row, $item['title']);
|
||
$sheet->setCellValue('C' . $row, isset($typesMap[$item['type']]) ? $typesMap[$item['type']] : '未知类型');
|
||
$sheet->setCellValue('D' . $row, $statusText);
|
||
$sheet->setCellValue('E' . $row, $item['price']);
|
||
$sheet->setCellValue('F' . $row, $statsData['cj_count']);
|
||
$sheet->setCellValue('G' . $row, $statsData['use_money']);
|
||
$sheet->setCellValue('H' . $row, $statsData['sc_money']);
|
||
$sheet->setCellValue('I' . $row, $statsData['re_money']);
|
||
$sheet->setCellValue('J' . $row, $statsData['fh_money']);
|
||
$sheet->setCellValue('K' . $row, $singleBoxProfit);
|
||
$sheet->setCellValue('L' . $row, round($singleBoxProfitRate, 2));
|
||
$sheet->setCellValue('M' . $row, $statsData['profit']);
|
||
$sheet->setCellValue('N' . $row, $statsData['profit_rate']);
|
||
|
||
// 设置负利润的行为红色背景
|
||
if ($statsData['profit'] < 0) {
|
||
$sheet->getStyle('A' . $row . ':N' . $row)->getFill()
|
||
->setFillType(Fill::FILL_SOLID)
|
||
->getStartColor()->setRGB('FFEBEE');
|
||
}
|
||
|
||
$row++;
|
||
}
|
||
|
||
// 调整列宽
|
||
foreach (range('A', 'N') as $col) {
|
||
$sheet->getColumnDimension($col)->setAutoSize(true);
|
||
}
|
||
|
||
// 添加汇总行
|
||
$summaryData = $this->getSummaryStatisticsData($goodId, $title, $status, $type, $addtime);
|
||
|
||
$row++;
|
||
$sheet->setCellValue('A' . $row, '汇总');
|
||
$sheet->mergeCells('A' . $row . ':F' . $row);
|
||
$sheet->setCellValue('G' . $row, $summaryData['totalIncome']);
|
||
$sheet->setCellValue('H' . $row, $summaryData['totalCost']);
|
||
$sheet->setCellValue('I' . $row, $summaryData['totalReMoney']);
|
||
$sheet->setCellValue('J' . $row, $summaryData['totalFhMoney']);
|
||
|
||
// 计算汇总单盒子利润和利润比
|
||
$totalSingleBoxProfit = $summaryData['totalIncome'] - $summaryData['totalCost'];
|
||
$sheet->setCellValue('K' . $row, $totalSingleBoxProfit);
|
||
|
||
$totalSingleBoxProfitRate = 0;
|
||
if ($summaryData['totalIncome'] > 0) {
|
||
$totalSingleBoxProfitRate = ($totalSingleBoxProfit / $summaryData['totalIncome']) * 100;
|
||
}
|
||
$sheet->setCellValue('L' . $row, round($totalSingleBoxProfitRate, 2));
|
||
|
||
$sheet->setCellValue('M' . $row, $summaryData['totalProfit']);
|
||
|
||
// 计算总体利润率
|
||
$profitRate = 0;
|
||
if ($summaryData['totalIncome'] > 0) {
|
||
$profitRate = ($summaryData['totalProfit'] / $summaryData['totalIncome']) * 100;
|
||
}
|
||
$sheet->setCellValue('N' . $row, round($profitRate, 2));
|
||
|
||
// 设置汇总行样式
|
||
$summaryStyle = [
|
||
'font' => ['bold' => true],
|
||
'fill' => [
|
||
'fillType' => Fill::FILL_SOLID,
|
||
'startColor' => ['rgb' => ($summaryData['totalProfit'] >= 0 ? 'E8F5E9' : 'FFEBEE')],
|
||
],
|
||
];
|
||
$sheet->getStyle('A' . $row . ':N' . $row)->applyFromArray($summaryStyle);
|
||
|
||
// 设置Excel文件属性
|
||
$spreadsheet->getProperties()
|
||
->setCreator('盒子利润统计系统')
|
||
->setLastModifiedBy('盒子利润统计系统')
|
||
->setTitle('盒子利润统计数据')
|
||
->setSubject('盒子利润统计数据')
|
||
->setDescription('导出的盒子利润统计数据');
|
||
|
||
// 设置输出文件名
|
||
$filename = '盒子利润统计_' . date('YmdHis') . '.xlsx';
|
||
|
||
// 设置HTTP头,表明这是一个Excel文件
|
||
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
||
header('Content-Disposition: attachment;filename="' . $filename . '"');
|
||
header('Cache-Control: max-age=0');
|
||
|
||
// 将工作簿写入到PHP输出流
|
||
$writer = new Xlsx($spreadsheet);
|
||
$writer->save('php://output');
|
||
exit;
|
||
}
|
||
|
||
/**
|
||
* 获取单个盒子的利润统计数据(用于导出)
|
||
* @param int $goodId 盒子ID
|
||
* @param bool $hasTimeRange 是否有时间范围限制
|
||
* @param int $startTime 开始时间
|
||
* @param int $endTime 结束时间
|
||
* @param array $testUserIds 测试用户ID列表
|
||
* @return array 统计数据
|
||
*/
|
||
private function getBoxProfitStats($goodId, $hasTimeRange, $startTime, $endTime, $testUserIds)
|
||
{
|
||
// 查询1:获取充值金额和余额消费总和
|
||
$orderQuery = Db::name('order')
|
||
->where('status', '=', 1)
|
||
->where(function ($query) {
|
||
$query->where('price', '>', 0)
|
||
->whereOr('use_money', '>', 0);
|
||
})
|
||
->where('goods_id', '=', $goodId)
|
||
->where('user_id', 'not in', $testUserIds);
|
||
|
||
// 只有在有时间范围时才添加时间条件
|
||
if ($hasTimeRange) {
|
||
$orderQuery->where('pay_time', '>', $startTime)
|
||
->where('pay_time', '<', $endTime);
|
||
}
|
||
|
||
// 分别获取price和use_money的总和后相加
|
||
$priceSum = $orderQuery->sum('price');
|
||
$useMoneySum = $orderQuery->sum('use_money');
|
||
$useMoney = floatval($priceSum) + floatval($useMoneySum);
|
||
|
||
// 查询2:获取出货成本
|
||
$scMoneyQuery = Db::name('order_list')
|
||
->where('goods_id', '=', $goodId)
|
||
->where('user_id', 'not in', $testUserIds);
|
||
|
||
if ($hasTimeRange) {
|
||
$scMoneyQuery->where('addtime', '>', $startTime)
|
||
->where('addtime', '<', $endTime);
|
||
}
|
||
|
||
$scMoney = $scMoneyQuery->sum('goodslist_money');
|
||
|
||
// 查询3:获取兑换成本
|
||
$reMoneyQuery = Db::name('order_list')
|
||
->where('goods_id', '=', $goodId)
|
||
->where('LENGTH(recovery_num)', '>', 0)
|
||
->where('user_id', 'not in', $testUserIds);
|
||
|
||
if ($hasTimeRange) {
|
||
$reMoneyQuery->where('addtime', '>', $startTime)
|
||
->where('addtime', '<', $endTime);
|
||
}
|
||
|
||
$reMoney = $reMoneyQuery->sum('goodslist_money');
|
||
|
||
// 查询4:获取发货成本
|
||
$fhMoneyQuery = Db::name('order_list')
|
||
->where('goods_id', '=', $goodId)
|
||
->where('LENGTH(send_num)', '>', 0)
|
||
->where('user_id', 'not in', $testUserIds);
|
||
|
||
if ($hasTimeRange) {
|
||
$fhMoneyQuery->where('addtime', '>', $startTime)
|
||
->where('addtime', '<', $endTime);
|
||
}
|
||
|
||
$fhMoney = $fhMoneyQuery->sum('goodslist_money');
|
||
|
||
// 查询5:获取抽奖次数
|
||
$cjCountQuery = Db::name('order_list')
|
||
->where('goods_id', '=', $goodId)
|
||
->where('user_id', 'not in', $testUserIds)
|
||
->where('parent_goods_list_id', '=', 0);
|
||
|
||
if ($hasTimeRange) {
|
||
$cjCountQuery->where('addtime', '>', $startTime)
|
||
->where('addtime', '<', $endTime);
|
||
}
|
||
|
||
$cjCount = $cjCountQuery->count();
|
||
|
||
// 计算利润和利润率
|
||
$profit = floatval($useMoney) - floatval($scMoney);
|
||
$profitRate = 0;
|
||
if ($useMoney > 0) {
|
||
$profitRate = round(($profit / $useMoney) * 100, 2);
|
||
}
|
||
|
||
return [
|
||
'use_money' => floatval($useMoney),
|
||
'sc_money' => floatval($scMoney),
|
||
're_money' => floatval($reMoney),
|
||
'fh_money' => floatval($fhMoney),
|
||
'cj_count' => intval($cjCount),
|
||
'profit' => $profit,
|
||
'profit_rate' => $profitRate
|
||
];
|
||
}
|
||
|
||
/**
|
||
* 获取汇总统计数据(用于导出)
|
||
*/
|
||
private function getSummaryStatisticsData($goodId, $title, $status, $type, $addtime)
|
||
{
|
||
// 解析时间范围
|
||
$hasTimeRange = false;
|
||
$startTime = 0;
|
||
$endTime = 0;
|
||
if (!empty($addtime)) {
|
||
$hasTimeRange = true;
|
||
$times = explode(' - ', $addtime);
|
||
$startTime = strtotime($times[0]);
|
||
$endTime = strtotime($times[1]);
|
||
}
|
||
|
||
// 构建查询条件
|
||
$goodsWhere = [['delete_time', '=', null]];
|
||
if ($goodId) {
|
||
$goodsWhere[] = ['id', '=', $goodId];
|
||
}
|
||
if ($title) {
|
||
$goodsWhere[] = ['title', 'like', '%' . $title . '%'];
|
||
}
|
||
if ($status) {
|
||
$goodsWhere[] = ['status', '=', $status];
|
||
}
|
||
if ($type) {
|
||
$goodsWhere[] = ['type', '=', $type];
|
||
}
|
||
|
||
// 获取符合条件的盒子ID列表
|
||
$goodsIds = Db::name('goods')
|
||
->where($goodsWhere)
|
||
->column('id');
|
||
|
||
if (empty($goodsIds)) {
|
||
return [
|
||
'totalIncome' => 0,
|
||
'totalCost' => 0,
|
||
'totalProfit' => 0,
|
||
'totalReMoney' => 0,
|
||
'totalFhMoney' => 0
|
||
];
|
||
}
|
||
|
||
// 获取测试用户ID
|
||
$testUsers = User::where('istest', '>', 0) ->whereOr('status', '=', 2)->column('id');
|
||
$testUserIds = empty($testUsers) ? [0] : $testUsers;
|
||
|
||
// 查询1:获取充值金额和余额消费总和
|
||
$orderQuery = Db::name('order')
|
||
->where('status', '=', 1)
|
||
->where(function ($query) {
|
||
$query->where('price', '>', 0)
|
||
->whereOr('use_money', '>', 0);
|
||
})
|
||
->where('goods_id', 'in', $goodsIds)
|
||
->where('user_id', 'not in', $testUserIds);
|
||
|
||
// 只有在有时间范围时才添加时间条件
|
||
if ($hasTimeRange) {
|
||
$orderQuery->where('pay_time', '>', $startTime)
|
||
->where('pay_time', '<', $endTime);
|
||
}
|
||
|
||
// 分别获取price和use_money的总和后相加
|
||
$priceSum = $orderQuery->sum('price');
|
||
$useMoneySum = $orderQuery->sum('use_money');
|
||
$totalIncome = floatval($priceSum) + floatval($useMoneySum);
|
||
|
||
// 查询2:获取出货成本
|
||
$scMoneyQuery = Db::name('order_list')
|
||
->where('goods_id', 'in', $goodsIds)
|
||
->where('user_id', 'not in', $testUserIds);
|
||
|
||
if ($hasTimeRange) {
|
||
$scMoneyQuery->where('addtime', '>', $startTime)
|
||
->where('addtime', '<', $endTime);
|
||
}
|
||
|
||
$totalCost = floatval($scMoneyQuery->sum('goodslist_money'));
|
||
|
||
// 查询3:获取兑换成本
|
||
$reMoneyQuery = Db::name('order_list')
|
||
->where('goods_id', 'in', $goodsIds)
|
||
->where('status', '=', 1)
|
||
->where('user_id', 'not in', $testUserIds);
|
||
|
||
if ($hasTimeRange) {
|
||
$reMoneyQuery->where('addtime', '>', $startTime)
|
||
->where('addtime', '<', $endTime);
|
||
}
|
||
|
||
$totalReMoney = floatval($reMoneyQuery->sum('goodslist_money'));
|
||
|
||
// 查询4:获取发货成本
|
||
$fhMoneyQuery = Db::name('order_list')
|
||
->where('goods_id', 'in', $goodsIds)
|
||
->where('status', '=', 2)
|
||
->where('user_id', 'not in', $testUserIds);
|
||
|
||
if ($hasTimeRange) {
|
||
$fhMoneyQuery->where('addtime', '>', $startTime)
|
||
->where('addtime', '<', $endTime);
|
||
}
|
||
|
||
$totalFhMoney = floatval($fhMoneyQuery->sum('goodslist_money'));
|
||
|
||
// 计算总利润
|
||
$totalProfit = $totalIncome - ($totalCost - $totalReMoney);
|
||
|
||
// 返回汇总数据
|
||
return [
|
||
'totalIncome' => $totalIncome,
|
||
'totalCost' => $totalCost,
|
||
'totalProfit' => $totalProfit,
|
||
'totalReMoney' => $totalReMoney,
|
||
'totalFhMoney' => $totalFhMoney
|
||
];
|
||
}
|
||
|
||
/**
|
||
* 抽奖用户列表页面
|
||
*/
|
||
public function lotteryUsers()
|
||
{
|
||
return View::fetch("Statistics/lotteryUsers");
|
||
}
|
||
|
||
/**
|
||
* 抽奖用户数据接口
|
||
*/
|
||
public function lotteryUsersData()
|
||
{
|
||
$goodsId = input('goods_id', 0, 'intval');
|
||
if(empty($goodsId)) {
|
||
return json(['code' => 1, 'msg' => '参数错误']);
|
||
}
|
||
|
||
// 获取盒子信息
|
||
$boxInfo = \app\common\model\Goods::where('id', $goodsId)->field('id,title')->find();
|
||
|
||
// 获取测试用户ID
|
||
$testUsers = \app\common\model\User::where('istest', '>', 0)
|
||
->whereOr('status', '=', 2)
|
||
->column('id');
|
||
$testUserIds = empty($testUsers) ? [0] : $testUsers;
|
||
|
||
// 构建分页查询
|
||
$query = Db::name('order_list')
|
||
->alias('ol')
|
||
->join('user u', 'ol.user_id = u.id')
|
||
->where('ol.goods_id', $goodsId)
|
||
->where('ol.user_id', 'not in', $testUserIds)
|
||
->field([
|
||
'ol.user_id',
|
||
'u.nickname',
|
||
'COUNT(DISTINCT ol.id) as lottery_count',
|
||
'SUM(ol.goodslist_money) as output_value',
|
||
'0 as wx_payment',
|
||
'0 as diamond_payment'
|
||
])
|
||
->group('ol.user_id')
|
||
->order('lottery_count', 'desc')
|
||
->paginate(input('limit', 20))
|
||
->toArray();
|
||
|
||
// 获取每个用户的支付信息
|
||
if (!empty($query['data'])) {
|
||
$userIds = array_column($query['data'], 'user_id');
|
||
|
||
// 获取微信支付金额
|
||
$wxPayments = Db::name('order')
|
||
->where('goods_id', $goodsId)
|
||
->where('user_id', 'in', $userIds)
|
||
->where('price', '>', 0)
|
||
->where('status', 1)
|
||
->field('user_id, SUM(price) as payment')
|
||
->group('user_id')
|
||
->select()
|
||
->toArray();
|
||
|
||
$wxPaymentMap = [];
|
||
foreach ($wxPayments as $payment) {
|
||
$wxPaymentMap[$payment['user_id']] = $payment['payment'];
|
||
}
|
||
|
||
// 获取钻石支付金额
|
||
$diamondPayments = Db::name('order')
|
||
->where('goods_id', $goodsId)
|
||
->where('user_id', 'in', $userIds)
|
||
->where('use_money', '>', 0)
|
||
->where('status', 1)
|
||
->field('user_id, SUM(use_money) as payment')
|
||
->group('user_id')
|
||
->select()
|
||
->toArray();
|
||
|
||
$diamondPaymentMap = [];
|
||
foreach ($diamondPayments as $payment) {
|
||
$diamondPaymentMap[$payment['user_id']] = $payment['payment'];
|
||
}
|
||
|
||
// 更新用户支付信息
|
||
foreach ($query['data'] as &$user) {
|
||
$user['wx_payment'] = isset($wxPaymentMap[$user['user_id']]) ? floatval($wxPaymentMap[$user['user_id']]) : 0;
|
||
$user['diamond_payment'] = isset($diamondPaymentMap[$user['user_id']]) ? floatval($diamondPaymentMap[$user['user_id']]) : 0;
|
||
$user['total_payment'] = $user['wx_payment'] + $user['diamond_payment'];
|
||
$user['output_value'] = floatval($user['output_value']);
|
||
}
|
||
}
|
||
|
||
return json([
|
||
'code' => 0,
|
||
'msg' => '获取成功',
|
||
'count' => $query['total'],
|
||
'data' => $query['data'],
|
||
'boxInfo' => $boxInfo
|
||
]);
|
||
}
|
||
|
||
/**
|
||
* 用户抽奖详情页面
|
||
*/
|
||
public function userLotteryDetail()
|
||
{
|
||
return View::fetch("Statistics/userLotteryDetail");
|
||
}
|
||
|
||
/**
|
||
* 用户抽奖详情数据接口
|
||
*/
|
||
public function userLotteryDetailData()
|
||
{
|
||
$goodsId = input('goods_id', 0, 'intval');
|
||
$userId = input('user_id', 0, 'intval');
|
||
|
||
if(empty($goodsId) || empty($userId)) {
|
||
return json(['code' => 1, 'msg' => '参数错误']);
|
||
}
|
||
|
||
// 获取用户和盒子信息
|
||
$userInfo = \app\common\model\User::where('id', $userId)->field('id,nickname')->find();
|
||
$boxInfo = \app\common\model\Goods::where('id', $goodsId)->field('id,title')->find();
|
||
|
||
if(!$userInfo || !$boxInfo) {
|
||
return json(['code' => 1, 'msg' => '用户或盒子不存在']);
|
||
}
|
||
|
||
// 获取用户的抽奖记录
|
||
$records = Db::name('order_list')
|
||
->alias('ol')
|
||
->leftJoin('goods_list gl', 'ol.goodslist_id = gl.id')
|
||
->leftJoin('order o', 'ol.order_id = o.id')
|
||
->where('ol.goods_id', $goodsId)
|
||
->where('ol.status', 1)
|
||
->where('ol.user_id', $userId)
|
||
->field([
|
||
'ol.id',
|
||
'ol.addtime',
|
||
'ol.goodslist_id',
|
||
'gl.title as goodslist_title',
|
||
'ol.goodslist_money',
|
||
'ol.order_id',
|
||
'o.price',
|
||
'o.use_money',
|
||
'ol.send_num',
|
||
'CASE WHEN o.price > 0 THEN "wx" WHEN o.use_money > 0 THEN "diamond" ELSE "other" END as payment_type',
|
||
'CASE WHEN o.price > 0 THEN o.price WHEN o.use_money > 0 THEN o.use_money ELSE 0 END as payment_amount',
|
||
'IF(LENGTH(ol.send_num) > 0, 1, 0) as is_shipped'
|
||
])
|
||
->order('ol.addtime', 'desc')
|
||
->paginate(input('limit', 20))
|
||
->toArray();
|
||
|
||
// 获取用户抽奖汇总信息
|
||
$summary = $this->getUserLotterySummaryData($goodsId, $userId);
|
||
|
||
return json([
|
||
'code' => 0,
|
||
'msg' => '获取成功',
|
||
'count' => $records['total'],
|
||
'data' => $records['data'],
|
||
'userInfo' => $userInfo,
|
||
'boxInfo' => $boxInfo,
|
||
'summary' => $summary
|
||
]);
|
||
}
|
||
|
||
/**
|
||
* 用户抽奖汇总数据
|
||
*/
|
||
public function userLotterySummary()
|
||
{
|
||
$goodsId = input('goods_id', 0, 'intval');
|
||
$userId = input('user_id', 0, 'intval');
|
||
|
||
if(empty($goodsId) || empty($userId)) {
|
||
return json(['code' => 1, 'msg' => '参数错误']);
|
||
}
|
||
|
||
// 获取用户和盒子信息
|
||
$userInfo = \app\common\model\User::where('id', $userId)->field('id,nickname')->find();
|
||
$boxInfo = \app\common\model\Goods::where('id', $goodsId)->field('id,title')->find();
|
||
|
||
if(!$userInfo || !$boxInfo) {
|
||
return json(['code' => 1, 'msg' => '用户或盒子不存在']);
|
||
}
|
||
|
||
// 获取用户抽奖汇总数据
|
||
$data = $this->getUserLotterySummaryData($goodsId, $userId);
|
||
|
||
return json([
|
||
'code' => 0,
|
||
'msg' => '获取成功',
|
||
'data' => $data,
|
||
'userInfo' => $userInfo,
|
||
'boxInfo' => $boxInfo
|
||
]);
|
||
}
|
||
|
||
/**
|
||
* 获取用户抽奖汇总数据
|
||
*/
|
||
private function getUserLotterySummaryData($goodsId, $userId)
|
||
{
|
||
// 获取抽奖次数
|
||
$totalCount = Db::name('order_list')
|
||
->where('goods_id', $goodsId)
|
||
->where('user_id', $userId)
|
||
->count();
|
||
|
||
// 获取出货价值
|
||
$totalOutput = Db::name('order_list')
|
||
->where('goods_id', $goodsId)
|
||
->where('user_id', $userId)
|
||
->sum('goodslist_money');
|
||
|
||
// 获取微信支付金额
|
||
$wxPayment = Db::name('order')
|
||
->where('goods_id', $goodsId)
|
||
->where('user_id', $userId)
|
||
->where('price', '>', 0)
|
||
->where('status', 1)
|
||
->sum('price');
|
||
|
||
// 获取钻石支付金额
|
||
$diamondPayment = Db::name('order')
|
||
->where('goods_id', $goodsId)
|
||
->where('user_id', $userId)
|
||
->where('use_money', '>', 0)
|
||
->where('status', 1)
|
||
->sum('use_money');
|
||
|
||
// 总支付金额
|
||
$totalPayment = $wxPayment + $diamondPayment;
|
||
|
||
return [
|
||
'totalCount' => intval($totalCount),
|
||
'totalOutput' => floatval($totalOutput),
|
||
'wxPayment' => floatval($wxPayment),
|
||
'diamondPayment' => floatval($diamondPayment),
|
||
'totalPayment' => floatval($totalPayment)
|
||
];
|
||
}
|
||
|
||
}
|