238 lines
9.1 KiB
PHP
238 lines
9.1 KiB
PHP
<?php
|
||
|
||
namespace app\admin\controller;
|
||
use app\admin\model\OrderGoods;
|
||
use app\admin\model\OrderRecharge;
|
||
use app\admin\model\OrderYearcard;
|
||
use app\admin\model\User;
|
||
use app\common\server\UrlServer;
|
||
use think\facade\Url;
|
||
use app\admin\model\Order;
|
||
|
||
class BulletinBoard extends AdminBase
|
||
{
|
||
|
||
//看板统计
|
||
public function index()
|
||
{
|
||
//查询商品订单
|
||
$orderMoney = Order::where('status','<>', 0)->sum('order_amount');
|
||
//年卡订单
|
||
$yearCardOrderMoney = OrderYearcard::where('status', 1)->sum('pay_fee');
|
||
//订单管理
|
||
$orderGoods = OrderGoods::where('status', 1)->sum('total_fee');
|
||
//充值订单
|
||
$rechargeOrderMoney = OrderRecharge::where('pay_status', 1)->sum('order_amount');
|
||
|
||
// 计算月销售总额(所有订单类型的总和)
|
||
$monthlySales = ($orderMoney ?: 0) + ($yearCardOrderMoney ?: 0) + ($orderGoods ?: 0) + ($rechargeOrderMoney ?: 0);
|
||
|
||
// 计算月订单量(本月订单数量)
|
||
$monthlyOrders = Order::where('status','<>', 0)
|
||
->whereTime('create_time', 'month')
|
||
->count();
|
||
$monthlyOrders += OrderYearcard::where('status', 1)
|
||
->whereTime('createtime', 'month')
|
||
->count();
|
||
$monthlyOrders += OrderGoods::where('status', 1)
|
||
->whereTime('createtime', 'month')
|
||
->count();
|
||
$monthlyOrders += OrderRecharge::where('pay_status', 1)
|
||
->whereTime('create_time', 'month')
|
||
->count();
|
||
|
||
// 计算月客户数(本月新增用户)
|
||
$monthlyCustomers = User::whereTime('create_time', 'month')
|
||
->where('del', 0)
|
||
->count();
|
||
|
||
// 计算同比(上个月的数据)
|
||
$lastMonthSales = Order::where('status','<>', 0)
|
||
->whereTime('create_time', 'last month')
|
||
->sum('order_amount');
|
||
$lastMonthSales += OrderYearcard::where('status', 1)
|
||
->whereTime('createtime', 'last month')
|
||
->sum('pay_fee');
|
||
$lastMonthSales += OrderGoods::where('status', 1)
|
||
->whereTime('createtime', 'last month')
|
||
->sum('total_fee');
|
||
$lastMonthSales += OrderRecharge::where('pay_status', 1)
|
||
->whereTime('create_time', 'last month')
|
||
->sum('order_amount');
|
||
|
||
$lastMonthOrders = Order::where('status','<>', 0)
|
||
->whereTime('create_time', 'last month')
|
||
->count();
|
||
$lastMonthOrders += OrderYearcard::where('status', 1)
|
||
->whereTime('createtime', 'last month')
|
||
->count();
|
||
$lastMonthOrders += OrderGoods::where('status', 1)
|
||
->whereTime('createtime', 'last month')
|
||
->count();
|
||
$lastMonthOrders += OrderRecharge::where('pay_status', 1)
|
||
->whereTime('create_time', 'last month')
|
||
->count();
|
||
|
||
$lastMonthCustomers = User::whereTime('create_time', 'last month')
|
||
->where('del', 0)
|
||
->count();
|
||
|
||
// 计算同比变化率
|
||
$salesCompare = $lastMonthSales > 0 ? round((($monthlySales - $lastMonthSales) / $lastMonthSales) * 100, 2) : 0;
|
||
$ordersCompare = $lastMonthOrders > 0 ? round((($monthlyOrders - $lastMonthOrders) / $lastMonthOrders) * 100, 2) : 0;
|
||
$customersCompare = $lastMonthCustomers > 0 ? round((($monthlyCustomers - $lastMonthCustomers) / $lastMonthCustomers) * 100, 2) : 0;
|
||
|
||
// 统计本月客户分析(老客户 vs 新客户)
|
||
// 本月所有用户ID列表
|
||
$monthUsers = User::whereTime('create_time', 'month')
|
||
->where('del', 0)
|
||
->column('id');
|
||
|
||
// 如果本月有用户,查询这些用户中哪些有订单(老客户)
|
||
$oldCustomerCount = 0;
|
||
$newCustomerCount = 0;
|
||
if (!empty($monthUsers)) {
|
||
// 查询本月注册的用户中,在Order表中有订单的用户(老客户)
|
||
// 只要有订单就算老客户,不限制订单时间
|
||
$oldCustomerIds = Order::where('status','<>', 0)
|
||
->where('user_id', 'in', $monthUsers)
|
||
->where('user_id', '>', 0)
|
||
->distinct(true)
|
||
->column('user_id');
|
||
|
||
$oldCustomerCount = count($oldCustomerIds);
|
||
// 本月注册但没下过单的(新客户)
|
||
$newCustomerCount = count($monthUsers) - $oldCustomerCount;
|
||
}
|
||
|
||
// 传递数据到视图
|
||
$this->assign([
|
||
'monthlySales' => $monthlySales,
|
||
'monthlyOrders' => $monthlyOrders,
|
||
'monthlyCustomers' => $monthlyCustomers,
|
||
'salesCompare' => $salesCompare,
|
||
'ordersCompare' => $ordersCompare,
|
||
'customersCompare' => $customersCompare,
|
||
'oldCustomers' => $oldCustomerCount, // 老客户数量(本月注册且下过单的)
|
||
'newCustomers' => $newCustomerCount, // 新客户数量(本月注册但没下过单的)
|
||
]);
|
||
|
||
return $this->fetch();
|
||
}
|
||
|
||
|
||
//地图上显示注册用户位置
|
||
public function map()
|
||
{
|
||
//查询商品订单
|
||
$orderMoney = Order::where('status','<>', 0)->sum('order_amount');
|
||
//年卡订单
|
||
$yearCardOrderMoney = OrderYearcard::where('status', 1)->sum('pay_fee');
|
||
//订单管理
|
||
$orderGoods = OrderGoods::where('status', 1)->sum('total_fee');
|
||
//充值订单
|
||
$rechargeOrderMoney = OrderRecharge::where('pay_status', 1)->sum('order_amount');
|
||
return $this->fetch();
|
||
}
|
||
|
||
public function getUserMap()
|
||
{
|
||
// 查询有经纬度的用户
|
||
$userArray = User::where('latitude', '<>', '')
|
||
->where('longitude', '<>', '')
|
||
->field('id,nickname,mobile,avatar,longitude,latitude')
|
||
->select();
|
||
// 格式化数据,转换为前端期望的字段名
|
||
$result = [];
|
||
foreach ($userArray as $user) {
|
||
// 处理头像URL,使用代理接口避免CORS问题
|
||
$avatar = '';
|
||
if (!empty($user['avatar'])) {
|
||
$originalUrl = UrlServer::getFileUrl($user['avatar']);
|
||
// 去掉JSON编码时产生的转义反斜杠
|
||
$originalUrl = str_replace('\\/', '/', $originalUrl);
|
||
|
||
// 如果URL是跨域的,使用代理接口
|
||
$currentDomain = $this->request->domain();
|
||
if (strpos($originalUrl, $currentDomain) === false) {
|
||
// 跨域,使用代理(手动构建URL避免双重编码)
|
||
$avatar = $this->request->domain() . '/admin/bulletin_board/proxyImage?url=' . rawurlencode($originalUrl);
|
||
} else {
|
||
// 同域,直接使用
|
||
$avatar = $originalUrl;
|
||
}
|
||
}
|
||
|
||
$result[] = [
|
||
'id' => $user['id'] ?? 0,
|
||
'lng' => floatval($user['longitude'] ?? 0),
|
||
'lat' => floatval($user['latitude'] ?? 0),
|
||
'name' => $user['nickname'] ?? '',
|
||
'contact' => $user['nickname'] ?? '', // 兼容两种字段名
|
||
'mobile' => $user['mobile'] ?? '',
|
||
'phone' => $user['mobile'] ?? '', // 兼容 telephone/phone
|
||
'telephone' => $user['mobile'] ?? '',
|
||
'avatar' => $avatar
|
||
];
|
||
}
|
||
|
||
return $this->_success('获取成功', $result);
|
||
}
|
||
|
||
/**
|
||
* 图片代理接口,解决CORS跨域问题
|
||
*/
|
||
public function proxyImage()
|
||
{
|
||
$url = $this->request->get('url', '');
|
||
if (empty($url)) {
|
||
header('HTTP/1.1 404 Not Found');
|
||
exit;
|
||
}
|
||
|
||
// 解码URL
|
||
$url = urldecode($url);
|
||
|
||
// 验证URL格式
|
||
if (!filter_var($url, FILTER_VALIDATE_URL)) {
|
||
header('HTTP/1.1 400 Bad Request');
|
||
exit;
|
||
}
|
||
|
||
// 只允许图片格式
|
||
$allowedExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
|
||
$extension = strtolower(pathinfo(parse_url($url, PHP_URL_PATH), PATHINFO_EXTENSION));
|
||
if (!in_array($extension, $allowedExtensions)) {
|
||
header('HTTP/1.1 403 Forbidden');
|
||
exit;
|
||
}
|
||
|
||
// 获取图片
|
||
$context = stream_context_create([
|
||
'http' => [
|
||
'method' => 'GET',
|
||
'timeout' => 10,
|
||
'header' => [
|
||
'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
|
||
]
|
||
]
|
||
]);
|
||
|
||
$imageData = @file_get_contents($url, false, $context);
|
||
|
||
if ($imageData === false) {
|
||
header('HTTP/1.1 404 Not Found');
|
||
exit;
|
||
}
|
||
|
||
// 设置响应头
|
||
header('Content-Type: image/' . ($extension === 'jpg' ? 'jpeg' : $extension));
|
||
header('Cache-Control: public, max-age=3600');
|
||
header('Access-Control-Allow-Origin: *');
|
||
header('Access-Control-Allow-Methods: GET');
|
||
|
||
// 输出图片
|
||
echo $imageData;
|
||
exit;
|
||
}
|
||
} |