| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418 |
- <?php
- namespace backend\modules\admin\services;
- use common\enums\OrderStatusEnum;
- use common\enums\RedisKeyEnum;
- use common\enums\StatusEnum;
- use common\models\census\CensusMall;
- use common\models\census\CensusMallGoods;
- use common\models\census\CensusMallSingleDay;
- use common\models\mall\Mall;
- use common\models\order\Order;
- use common\models\order\OrderDetail;
- use common\models\statistics\UserStatistics;
- use common\models\statistics\UserStatisticsTotal;
- use common\models\user\User;
- use Yii;
- /**
- * 系统配置
- * Namespace backend\modules\admin\services
- * @Author:lun
- * @Date:2024-09-18 18:07
- * @Copyright:copyright(c)2024 广东七件事集团
- */
- class SystemService extends BaseService
- {
- /**
- * 获取系统配置
- * @Author:lun
- * @Date:2024-09-18 18:15
- * @Copyright:copyright(c)2024 广东七件事集团
- * @return array | bool
- */
- public static function getSystemConfig()
- {
- $status = 0;// 状态[0=失败,1=成功]
- $data = [];// 返回数据
- $msg = '';// 返回信息
- try {
- if (stripos(PHP_OS, 'LINUX') !== false) {// 判断是否是 Linux 系统
- $status = 1;
- $data = self::getLinuxStatus();
- } else {
- $status = 0;
- $msg = '系统暂不支持';
- }
- } catch (\Exception $e) {
- $msg = '第' . $e->getLine() . '行,错误信息:' .$e->getMessage();
- }
- return ['status' => $status, 'data' => $data, 'msg' => $msg];
- }
- /**
- * 获取系统状态
- * @Author:lun
- * @Date:2024-09-18 18:51
- * @Copyright:copyright(c)2024 广东七件事集团
- * @return array
- */
- public static function getLinuxStatus()
- {
- $cpu = self::getCpuUsagePercent();
- $memory = self::getMemoryPercent();
- $disk = self::getDiskPercent();
- $redis = self::getRedisPercent();
- $site_num = Mall::getMallCount();
- return compact('cpu', 'memory', 'disk', 'redis', 'site_num');
- }
- /**
- * 获取内存使用率
- * @Author:lun
- * @Date:2024-09-18 18:46
- * @Copyright:copyright(c)2024 广东七件事集团
- * @return array
- */
- public static function getMemoryPercent()
- {
- exec('free -m', $output);
- $memoryInfo = explode("\n", $output[1]);
- $memoryParts = preg_split('/\s+/', $memoryInfo[0]);
- $total = $memoryParts[1];// 总内存
- $use_total = $memoryParts[2];// 已使用内存
- $freeMemory = $memoryParts[3];// 可用内存
- $percent = round(($use_total / $total) * 100, 2);
- return compact('use_total','total','percent');
- }
- /**
- * 获取磁盘使用率
- * @Author:lun
- * @Date:2024-09-19 17:20
- * @Copyright:copyright(c)2024 广东七件事集团
- * @return array
- */
- public static function getDiskPercent()
- {
- $use_total = $percent = 0;
- $total = disk_total_space("/"); // 更改为你想检测的磁盘路径
- if ($total == 0) return compact('use_total','total','percent');
- // 检测磁盘剩余空间
- $freeDiskSpace = disk_free_space("/"); // 更改为你想检测的磁盘路径
- // 计算磁盘使用率
- $use_total = $total - $freeDiskSpace;
- $percent = round(($use_total / $total) * 100, 2);
- return compact('use_total','total','percent');
- }
- /**
- * 获取CPU使用率
- * @Author:lun
- * @Date:2024-09-18 18:46
- * @Copyright:copyright(c)2024 广东七件事集团
- * @return float
- */
- public static function getCpuUsagePercent() {
- $prevStats = self::getCpuStats();
- sleep(1);
- $currStats = self::getCpuStats();
- $prevIdle = $prevStats['idle'] + $prevStats['iowait'];
- $prevNonIdle = $prevStats['user'] + $prevStats['nice'] + $prevStats['system'] + $prevStats['irq'] + $prevStats['softirq'];
- $prevTotal = $prevIdle + $prevNonIdle;
- $currIdle = $currStats['idle'] + $currStats['iowait'];
- $currNonIdle = $currStats['user'] + $currStats['nice'] + $currStats['system'] + $currStats['irq'] + $currStats['softirq'];
- $currTotal = $currIdle + $currNonIdle;
- $diffTotal = $currTotal - $prevTotal;
- $diffIdle = $currIdle - $prevIdle;
- return round((1 - $diffIdle / $diffTotal) * 100);
- }
- /**
- * 获取CPU使用情况
- * @Author:lun
- * @Date:2024-09-18 18:46
- * @Copyright:copyright(c)2024 广东七件事集团
- * @return int[]
- */
- public static function getCpuStats() {
- exec('cat /proc/stat', $output);
- $parts = preg_split('/\s+/', $output[0]);
- return [
- 'user' => (int)$parts[1],
- 'nice' => (int)$parts[2],
- 'system' => (int)$parts[3],
- 'idle' => (int)$parts[4],
- 'iowait' => (int)$parts[5],
- 'irq' => (int)$parts[6],
- 'softirq' => (int)$parts[7]
- ];
- }
- /**
- * 获取Redis使用率
- * @Author:lun
- * @Date:2024-09-19 16:57
- * @Copyright:copyright(c)2024 广东七件事集团
- * @return array
- */
- public static function getRedisPercent()
- {
- $redis = Yii::$app->redis;
- // 执行 INFO 命令
- $info = $redis->executeCommand('INFO', ['memory']);
- $lines = explode("\r\n", $info);
- $memoryUsage = [];
- foreach ($lines as $line) {
- if (strpos($line, ':') !== false) {
- list($key, $value) = explode(':', $line, 2);
- $memoryUsage[$key] = $value;
- }
- }
- $percent = 0;
- $use_total = empty($memoryUsage['use_memory']) ? 0 : $memoryUsage['use_memory'] / (1024 * 1024);// 已使用内存
- $total = empty($memoryUsage['maxmemory']) ? 0 : $memoryUsage['maxmemory'] / (1024 * 1024);// 最大内存
- if ($use_total > 0 && $total > 0) {// Redis 未开启内存限制,则返回 0
- $percent = round(($use_total / $total) * 100, 2);
- }
- return compact('use_total', 'total', 'percent');
- }
- /**
- * 概括数据
- * @return array
- */
- public static function getWraparound()
- {
- $oneStatus = [
- 'total_money' => 0,
- 'total_users' => 0,
- 'total_orders' => 0,
- 'total_sales' => 0,
- 'total_profit' => 0,
- ];
- // 获取一级概括数据
- try {
- $mallModel = CensusMall::find()
- ->distinct('mall_id')
- ->where(['status' => StatusEnum::ENABLED])
- ->asArray()
- ->orderBy('id desc');
- $batchSize = 1000;
- foreach ($mallModel->batch($batchSize) as $mallList) {
- foreach ($mallList as $item) {
- $oneStatus['total_users'] += $item['total_users'];
- $oneStatus['total_orders'] += $item['total_orders'];
- $oneStatus['total_money'] = bcadd($oneStatus['total_money'], $item['total_pay_money'], 2);
- }
- }
- } catch (\Exception $e) {
- // 处理异常
- Yii::error("Error fetching mall data: " . $e->getMessage());
- }
- // 获取一级概括数据
- try {
- $mallGoodsModel = CensusMallGoods::find()
- ->distinct('mall_id')
- ->where(['status' => StatusEnum::ENABLED])
- ->asArray()
- ->orderBy('id desc');
- foreach ($mallGoodsModel->batch($batchSize) as $mallGoodsList) {
- foreach ($mallGoodsList as $item) {
- $oneStatus['total_sales'] += $item['total_sales_volume'];
- }
- }
- } catch (\Exception $e) {
- // 处理异常
- Yii::error("Error fetching mall goods data: " . $e->getMessage());
- }
- // 获取总利润(不计算已关闭订单)
- try {
- $orderDetailModel = OrderDetail::find()
- ->where(['status' => [StatusEnum::ENABLED, StatusEnum::DISABLED]])
- ->andWhere(['!=', 'order_status', OrderStatusEnum::REPEAL])
- ->asArray()
- ->orderBy('id desc');
- foreach ($orderDetailModel->batch($batchSize) as $orderDetailList) {
- foreach ($orderDetailList as $item) {
- $profit = bcsub($item['goods_price'], bcmul($item['cost_price'], $item['num'], 2), 2);
- $oneStatus['total_profit'] = bcadd($oneStatus['total_profit'], $profit, 2);
- }
- }
- } catch (\Exception $e) {
- // 处理异常
- Yii::error("Error fetching order detail data: " . $e->getMessage());
- }
- // 获取销售额排名
- try {
- $yesterdayDate = date('Ymd', strtotime('-1 day'));
- $yesterdayMoneySubquery = (new \yii\db\Query())
- ->select('sum(pay_money) as total_money')
- ->from(UserStatistics::tableName() . ' ut2')
- ->where(['ut.mall_id' => new \yii\db\Expression('ut2.mall_id'), 'ut2.status' => 1, 'ut2.date' => $yesterdayDate]);
- $threeStatus['total_achievement_ranking'] = UserStatisticsTotal::find()
- ->alias('ut')
- ->leftJoin(Mall::tableName() . ' mall', 'mall.id=ut.mall_id')
- ->select([
- 'sum(ut.pay_money) as total_money',
- 'mall.name as mall_name',
- 'mall.id as mall_id',
- 'IFNULL((' . $yesterdayMoneySubquery->createCommand()->getRawSql() . '), 0) as yesterdayMoney'
- ])
- ->where(['ut.status' => StatusEnum::ENABLED])
- ->groupBy('ut.mall_id')
- ->orderBy('total_money desc')
- ->limit(10)
- ->asArray()
- ->all();
- foreach ($threeStatus['total_achievement_ranking'] as &$item) {
- $item['logo'] = Yii::$app->services->setting->mall->get($item['mall_id'], 'basic.logo');
- if (empty($item['logo'])) {
- $item['logo'] = Yii::$app->request->hostInfo . '/resources/img/admin/mall-logo.png';
- }
- }
- unset($item);
- } catch (\Exception $e) {
- // 处理异常
- Yii::error("Error fetching achievement ranking data: " . $e->getMessage());
- }
- // 获取热销商品排名
- $threeStatus['sales_volume_ranking'] = CensusMallGoods::find()
- ->with([
- 'goods' => function ($query) {
- $query->select(['id', 'goods_name', 'cover_pic']);
- },
- 'mall' => function ($query) {
- $query->select(['id', 'name']);
- }
- ])
- ->where(['status' => StatusEnum::ENABLED])
- ->orderBy('total_pay_money desc')
- ->select('total_pay_money, goods_id, mall_id')
- ->limit(10)
- ->asArray()
- ->all();
- // 获取热销商品排名
- $threeStatus['hot_sales_goods_ranking'] = CensusMallGoods::find()
- ->with([
- 'goods' => function ($query) {
- $query->select(['id', 'goods_name', 'cover_pic']);
- },
- 'mall' => function ($query) {
- $query->select(['id', 'name']);
- }
- ])
- ->where(['status' => StatusEnum::ENABLED])
- ->orderBy('total_sales_volume desc')
- ->select('total_sales_volume, goods_id, mall_id')
- ->limit(10)
- ->asArray()
- ->all();
- $threeStatus['sales_volume_ranking'] = self::getSalesRanking('total_pay_money');
- $threeStatus['hot_sales_goods_ranking'] = self::getSalesRanking('total_sales_volume');
- return compact('oneStatus', 'threeStatus');
- }
- public static function getSalesRanking($orderByField): array
- {
- try {
- return CensusMallGoods::find()
- ->with([
- 'goods' => function ($query) {
- $query->select(['id', 'goods_name', 'cover_pic']);
- },
- 'mall' => function ($query) {
- $query->select(['id', 'name']);
- }
- ])
- ->where(['status' => StatusEnum::ENABLED])
- ->orderBy($orderByField . ' desc')
- ->select([$orderByField, 'goods_id', 'mall_id'])
- ->limit(10)
- ->asArray()
- ->all();
- } catch (\Exception $e) {
- // 处理异常
- Yii::error("Error fetching sales ranking data: " . $e->getMessage());
- return [];
- }
- }
- public static function getSaleTrend()
- {
- // 获取用户活跃度
- $currentDate = date('Y-m-d', time());
- $saleTrendList = [];
- // 获取用户活跃度数据
- $censusMall = CensusMallSingleDay::find()
- ->where(['status' => StatusEnum::ENABLED])
- ->select('date, sum(total_actives) as total_actives, sum(add_users) as add_users, sum(add_pay_people_nums) as add_pay_people_nums')
- ->groupBy('date')
- ->asArray()
- ->all();
- if (!empty($censusMall)) $censusMall = array_column($censusMall, null, 'date');
- for ($i = 0; $i < 7; $i++) { // 获取最近7天数据
- $nowDay = $currentDate;
- if ($i > 0) {
- $nowDay = date("Y-m-d", strtotime("-" . $i . " day", strtotime($currentDate)));
- }
- $item = [
- 'date' => date("m-d", strtotime($nowDay)),
- 'total_actives' => isset($censusMall[$nowDay]) ? $censusMall[$nowDay]['total_actives'] : 0,
- 'add_users' => isset($censusMall[$nowDay]) ? $censusMall[$nowDay]['add_users'] : 0,
- 'add_pay_users' => isset($censusMall[$nowDay]) ? $censusMall[$nowDay]['add_pay_people_nums'] : 0,
- ];
- $saleTrendList[] = $item;
- }
- sort($saleTrendList);
- // 销售趋势
- return compact('saleTrendList');
- }
- public static function getSaleTrendByMonth(string $type = 'month')
- {
- // 获取销售额趋势(因为前端只有周和月所以默认获取前7个月订单)
- $currentMonth = date('Y-m', time());
- $eventMonth = date('Y-m', strtotime("-7 month", strtotime($currentMonth)));
- $orderDetailGroupBy = 'year, month';
- if ($type == 'week') {
- $orderDetailGroupBy = 'year, month, week';
- }
- // 销售额(订单支付金额) 利润(总销售额-总成本)
- $orderDetailSql = "sum(goods_price) as goods_price, sum(goods_price - cost_price) as profit_price,
- YEAR(FROM_UNIXTIME(created_at)) as year, MONTH(FROM_UNIXTIME(created_at)) as month, WEEK(FROM_UNIXTIME(created_at)) as week";
- $orderDetailModel = OrderDetail::find()
- ->where(['status' => [StatusEnum::ENABLED, StatusEnum::DISABLED]])
- ->andWhere(['!=', 'order_status', OrderStatusEnum::REPEAL])
- ->andWhere(['>=', 'created_at', strtotime($eventMonth)])
- ->select($orderDetailSql)
- ->asArray()
- ->groupBy($orderDetailGroupBy)
- ->orderBy('year desc, month desc')
- ->limit(6)
- ->all();
- return compact('orderDetailModel');
- }
- }
|