diff --git a/application/admin/controller/Orderplan.php b/application/admin/controller/Orderplan.php index 8c1f39c..ea9c1ea 100644 --- a/application/admin/controller/Orderplan.php +++ b/application/admin/controller/Orderplan.php @@ -13,6 +13,7 @@ use app\admin\model\Worker; use app\admin\model\WorkerItem; use app\common\controller\Backend; use app\common\Logic\OrderLogic; +use Carbon\Carbon; use fast\Tree; use think\Db; use think\Exception; @@ -21,6 +22,7 @@ use think\exception\PDOException; use think\exception\ValidateException; use think\Hook; use think\Model; +use function Carbon\int; use function Symfony\Component\Clock\now; /** @@ -60,11 +62,17 @@ class Orderplan extends Backend $lines = $this->getLine(); $pie = $this->getPie(); $order = $this->getOrder(); + $order_count = $this->getOrderCount(); + $order_rank = $this->orderRank(); + $item_rank = $this->itemRank(); $this->success(data: [ 'top' => $top, 'lines' => $lines, 'pie' => $pie, 'order' => $order, + 'order_count' => $order_count, + 'order_rank' => $order_rank, + 'item_rank' => $item_rank, ]); } @@ -138,7 +146,6 @@ class Orderplan extends Backend $out ['cancel'] = $data; - $build = new \app\admin\model\Order(); $res = $this->buildDate($build) ->field([ @@ -150,8 +157,8 @@ class Orderplan extends Backend $data = []; foreach ($res as $re) { $re = $re->getData(); - $name = explode('/',$re['name']); - $re['name'] = str_replace(' ', '' ,array_pop($name)); + $name = explode('/', $re['name']); + $re['name'] = str_replace(' ', '', array_pop($name)); $data [] = $re; } $out ['item'] = $data; @@ -192,14 +199,14 @@ class Orderplan extends Backend } - private function buildDate($build,$table_name = null) + private function buildDate($build, $table_name = null) { $start = now()->modify('-14 days')->format('Y-m-d'); $end_at = now()->format('Y-m-d'); - if ($table_name){ - $build->where($table_name.'.create_time', 'between', [$start, $end_at]); - }else{ + if ($table_name) { + $build->where($table_name . '.create_time', 'between', [$start, $end_at]); + } else { $build->where('create_time', 'between', [$start, $end_at]); } @@ -207,25 +214,24 @@ class Orderplan extends Backend } - private function getOrder() { $build = new OrderAbnormal(); $res = $build - ->where('status',0) + ->where('status', 0) ->count('id'); $out ['abnormal'] = $res; $build = new \app\admin\model\Order(); $res = $build - ->where('status',\app\admin\model\Order::STATUS_CHECKING) + ->where('status', \app\admin\model\Order::STATUS_CHECKING) ->count('id'); $out ['check'] = $res; $build = new \app\admin\model\Order(); $res = $build - ->where('status',\app\admin\model\Order::STATUS_AUDITING) + ->where('status', \app\admin\model\Order::STATUS_AUDITING) ->count('id'); $out ['auditing'] = $res; @@ -233,8 +239,8 @@ class Orderplan extends Backend $build = new \app\admin\model\Order(); $res = $build ->alias('a') - ->join('order_review b','a.id = b.order_id','left') - ->where('a.status','in',[\app\admin\model\Order::STATUS_FINISHED,\app\admin\model\Order::STATUS_CANCEL]) + ->join('order_review b', 'a.id = b.order_id', 'left') + ->where('a.status', 'in', [\app\admin\model\Order::STATUS_FINISHED, \app\admin\model\Order::STATUS_CANCEL]) ->whereNull('b.id') ->count('a.id'); @@ -243,19 +249,212 @@ class Orderplan extends Backend $build = new Aftersale(); $res = $build - ->where('status',1) + ->where('status', 1) ->count('id'); $out ['after_sale'] = $res; $build = new Invoice(); $res = $build - ->where('status',0) + ->where('status', 0) ->count('id'); $out ['invoice'] = $res; return $out; } + private function getOrderCount() + { + + $start = now()->format('Y-m-d 00:00:00'); + $end_at = now()->format('Y-m-d 23:59:59'); + + $build = new \app\admin\model\Order(); + $build->whereBetween('create_time', [$start, $end_at]); + $data = $build->field([ + 'sum(total) total', + 'count(id) count', + 'count(if(status=-10,1,null)) cancel' + ])->select(); + + $today = [ + 'total' => $data[0]->total ?? 0, + 'count' => $data[0]->count ?? 0, + 'cancel' => $data[0]->cancel ?? 0, + ]; + + $build = new Worker(); + $build->whereBetween('create_time', [$start, $end_at]); + + $data = $build->field([ + 'count(id) count', + ])->select(); +// dd($data); + $today['worker'] = $data[0]->count ?? 0; + + $build = new Aftersale(); + $build->whereBetween('create_time', [$start, $end_at]); + + $data = $build->field([ + 'count(id) count', + ])->select(); + $today['after_sale'] = $data[0]->count ?? 0; + + + // 本月 + $start = now()->format('Y-m-01 00:00:00'); + $end_at = (new Carbon())->endOfMonth()->format('Y-m-d H:m:s'); +// dd($start,$end_at); + $build = new \app\admin\model\Order(); + $build->whereBetween('create_time', [$start, $end_at]); + $data = $build->field([ + 'sum(total) total', + 'count(id) count', + 'count(if(status=-10,1,null)) cancel' + ])->select(); +// dd($data,\app\admin\model\Order::getLastSql()); + $month = [ + 'month_total' => $data[0]->total ?? 0, + 'month_count' => $data[0]->count ?? 0, + 'month_cancel' => $data[0]->cancel ?? 0, + ]; + $build = new Worker(); + $build->whereBetween('create_time', [$start, $end_at]); + + $data = $build->field([ + 'count(id) count', + ])->select(); + $month['month_worker'] = $data[0]->count ?? 0; + + $build = new Aftersale(); + $build->whereBetween('create_time', [$start, $end_at]); + + $data = $build->field([ + 'count(id) count', + ])->select(); + $month['month_after_sale'] = $data[0]->count ?? 0; + + return [ + ...$today, ...$month + ]; + } + + + private function orderRank() + { + $start = now()->format('Y-m-d 00:00:00'); + $end_at = now()->format('Y-m-d 23:59:59'); + + + $build = new \app\admin\model\Order(); + + $build->whereBetween('create_time', [$start, $end_at]); + + $data = $build->field([ + 'admin_id', + 'count(id) count', + ])->group('admin_id') + ->with('user') + ->order('count', 'desc') + ->limit(5) + ->select(); + + $rank = []; + foreach ($data as $da) { + $rank [] = [ + 'name' => $da->user->nickname ?? '', + 'count' => $da->count ?? '', + ]; + } + + + $build = new OrderDispatch(); + + $build->whereBetween('create_time', [$start, $end_at]); + + $data = $build->field([ + 'worker_name', + 'count(id) count', + ])->group('worker_name') + ->order('count', 'desc') + ->limit(5) + ->select(); + + $worker = []; + foreach ($data as $da) { + $worker [] = [ + 'name' => $da->worker_name, + 'count' => $da->count ?? '', + ]; + } + + + return [ + 'dispatch' => $rank, + 'doing' => $worker, + ]; + + } + + private function itemRank() + { + $start = now()->format('Y-m-d 00:00:00'); + $end_at = now()->format('Y-m-d 23:59:59'); + + + + $build = new \app\admin\model\Order(); + + $build->whereBetween('create_time', [$start, $end_at]); + + $total = $build->count('id'); + + $build = new \app\admin\model\Order(); + + $build->whereBetween('create_time', [$start, $end_at]); + + $data = $build->field([ + 'item_id', + 'count(id) count', + ])->group('item_id') + ->with('user') + ->order('count', 'desc') + ->limit(6) + ->select(); + + $rank = []; + foreach ($data as $da) { + $rank [] = [ + 'name' => $da->item->title ?? '', + 'count' => $da->count ?? 0, + 'rate' => $this->mydiv($da->count ?? 0,$total) + ]; + } + + $build = new \app\admin\model\Order(); + $res = $build->whereBetween('create_time', [$start, $end_at]) + ->field([ + 'SUBSTRING(area_id, 1, 2) AS name', + 'count(id) count', + ]) + ->group('name') + ->order('count','desc') + ->limit(6) + ->select(); + $area = []; + foreach ($res as $re) { + $re = $re->getData(); + $re['name'] = $this->getProvinceByCode($re['name']); + $re['rate'] = $this->mydiv($da->count ?? 0,$total); + $area [] = $re; + } + + return [ + 'item' => $rank, + 'area' => $area, + ]; + + } + private function prepareEchartsBarData(array $data, string $startDate, string $endDate): array { @@ -300,7 +499,8 @@ class Orderplan extends Backend } - function getProvinceByCode($code) { + function getProvinceByCode($code) + { // 省级行政区域编码对应数组 $provinces = [ 11 => '北京', @@ -344,5 +544,12 @@ class Orderplan extends Backend } + private function mydiv($a , $b){ + if ($b == 0) { + return '0'; + }else{ + return (int)($a / $b * 100); + } + } } diff --git a/application/admin/model/Order.php b/application/admin/model/Order.php index a037e7e..9f111ba 100644 --- a/application/admin/model/Order.php +++ b/application/admin/model/Order.php @@ -186,6 +186,10 @@ class Order extends Model return $this->belongsTo(Admin::class,'admin_id',); } + public function item(){ + return $this->belongsTo(Item::class,'item_id',); + } + public function area(){ return $this->belongsTo(Area::class,'area_id','area_code'); } diff --git a/application/admin/view/orderplan/index.html b/application/admin/view/orderplan/index.html index 3db852c..372ff91 100644 --- a/application/admin/view/orderplan/index.html +++ b/application/admin/view/orderplan/index.html @@ -17,574 +17,598 @@ -
-
- -
-
-
- - 订单量 -
-
- loading -
-
-
- -
-
-
- - 总业绩 -
-
- loading -
-
-
- - -
-
-
- - 总营业额 -
-
- loading -
-
-
- - -
-
-
- - 师傅总数 -
-
- loading -
-
-
-
+
+ +
-
-
-
-
-
- 进行中的订单 -
-
-
- 1240 / 231 / 23123 / 222 -
-
- 待派单 / 待接单 / 待上门 / 服务中 -
-
-
-
- -
-
-
-
-
-
-

报错

-

单位/笔

-
-
- 详情> -
-
-
- loading -
-
-
- -
-
-
-
-
-

待配置

-

单位/笔

-
-
- 详情> -
-
-
- loading -
-
-
- -
-
-
-
-
-

待审核

-

单位/笔

-
-
- 详情> -
-
-
- loading -
-
-
- -
-
-
-
-
-

待回访

-

单位/笔

-
-
- 详情> -
-
-
- loading -
-
-
- -
-
-
-
-
-

待售后

-

单位/笔

-
-
- 详情> -
-
-
- loading -
-
-
- -
-
-
-
-
-

开票

-

单位/笔

-
-
- 详情> -
-
-
- loading -
-
-
-
-
-
- -
-
- -
-
- -
- -
- -
-
+
+
+
+
+
+ +
+
+
+ + 订单量 +
+
+ loading +
+
+
-
+ +
+
+
+ + 总业绩 +
+
+ loading +
+
+
-
+ +
+
+
+ + 总营业额 +
+
+ loading +
+
+
-
-
+ +
+
+
+ + 师傅总数 +
+
+ loading +
+
+
+
+
+
+
+
+
+
+ 进行中的订单 +
+
+
+ 1240 / 231 / 23123 / 222 +
+
+ 待派单 / 待接单 / 待上门 / 服务中 +
+
+
+
-
-
-
-
+
+
+
+
+
+
+

报错

+

单位/笔

+
+
+ 详情> +
+
+
+ loading +
+
+
-
+
+
+
+
+
+

待配置

+

单位/笔

+
+
+ 详情> +
+
+
+ loading +
+
+
-
+
+
+
+
+
+

待审核

+

单位/笔

+
+
+ 详情> +
+
+
+ loading +
+
+
-
-
+
+
+
+
+
+

待回访

+

单位/笔

+
+
+ 详情> +
+
+
+ loading +
+
+
-
-
-
订单数据
-
-
-
+
+
+
+
+
+

待售后

+

单位/笔

+
+
+ 详情> +
+
+
+ loading +
+
-
-

¥8848

-

今日收款

-
-
-
-
-
-
-
-
-

¥8848

-

本月收款

-
-
-
-
-
-
-
-
-

88

-

今日订单数

-
-
-
-
-
-
-
-
-

8848

-

本月订单数

-
-
-
-
-
-
-
-
-

88

-

今日新增师傅数

-
-
-
-
-
-
-
-
-

8848

-

本月新增师傅数

-
-
-
-
-
-
-
-
-

8

-

今日退款数

-
-
-
-
-
-
-
-
-

88

-

本月退款数

-
-
-
-
-
-
-
-
-

88

-

今日取消订单数

-
-
-
-
-
-
-
-
-

88

-

本月取消订单数

-
-
-
-
-
-
接单排行
-
-
-
-
-
- 小明 -
-
- 14单 +
+
+
+
+
+

开票

+

单位/笔

+
+
+ 详情> +
+
+
+ loading +
+
-
-
-
-
-
-
- 小明 -
-
- 14单 -
-
-
-
-
-
-
-
- 小明 -
-
- 14单 -
-
-
-
-
-
-
-
- 小明 -
-
- 14单 -
-
-
-
-
-
-
-
- 小明 -
-
- 14单 -
-
-
-
+
+
-
-
录单排行
-
-
-
-
- 小明 +
+
+
+ +
+ +
+
-
- 14单 + + +
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+
-
-
-
+
+ + +
+
+
订单数据
+
+
+
+
+
+

¥8848

+

今日收款

+
+
+
+
+
+
+
+
+

¥8848

+

本月收款

+
+
+
+
+
+
+
+
+

88

+

今日订单数

+
+
+
+
+
+
+
+
+

8848

+

本月订单数

+
+
+
+
+
+
+
+
+

88

+

今日新增师傅数

+
+
+
+
+
+
+
+
+

8848

+

本月新增师傅数

+
+
+
+
+
+
+
+
+

8

+

今日退款数

+
+
+
+
+
+
+
+
+

88

+

本月退款数

+
+
+
+
+
+
+
+
+

88

+

今日取消订单数

+
+
+
+
+
+
+
+
+

88

+

本月取消订单数

+
+
+
-
- 小明 + +
+
录单排行
+
+
+
+
+
+ 虚位以待 +
+
+ 0单 +
+
+
+
+
+
+
+
+ 虚位以待 +
+
+ 0单 +
+
+
+
+
+
+
+
+ 虚位以待 +
+
+ 0单 +
+
+
+
+
+
+
+
+ 虚位以待 +
+
+ 0单 +
+
+
+
+
+
+
+
+ 虚位以待 +
+
+ 0单 +
+
+
-
- 14单 + +
+
接单排行
+
+
+
+
+
+ 虚位以待 +
+
+ 0单 +
+
+
+
+
+
+
+
+ 虚位以待 +
+
+ 0单 +
+
+
+
+
+
+
+
+ 虚位以待 +
+
+ 0单 +
+
+
+
+
+
+
+
+ 虚位以待 +
+
+ 0单 +
+
+
+
+
+
+
+
+ 虚位以待 +
+
+ 0单 +
+
+
-
-
-
-
+ +
+

热门服务

+ +
+
🥇
+
+
虚位以待
+
0
+
+
+
+
-
- 小明 +
+
🥈
+
+
虚位以待
+
0
+
+
+
+
-
- 14单 +
+
🥉
+
+
虚位以待
+
0
+
+
+
+
+
+ +
+
#4
+
+
虚位以待
+
0
+
+
+
+
#5
+
+
虚位以待
+
0
+
+
+
+
#6
+
+
虚位以待
+
0
+
-
-
-
-
+
+

热门地区

+ +
+
🥇
+
+
虚位以待
+
0
+
+
+
+
-
- 小明 +
+
🥈
+
+
虚位以待
+
0
+
+
+
+
-
- 14单 +
+
🥉
+
+
虚位以待
+
0
+
+
+
+
-
-
-
-
-
+ +
+
#4
+
+
虚位以待
+
0
+
-
- 小明 +
+
#5
+
+
虚位以待
+
0
+
-
- 14单 +
+
#6
+
+
虚位以待
+
0
+
-
-

热门服务

-
-
🥇
-
-
日常保洁
-
销量47 (19%)
-
-
-
-
-
-
-
🥈
-
-
日常保洁
-
销量47 (19%)
-
-
-
-
-
-
-
🥉
-
-
日常保洁
-
销量47 (19%)
-
-
-
-
-
-
-
#4
-
-
日常保洁
-
销量47 (19%)
-
-
-
-
#5
-
-
日常保洁
-
销量47 (19%)
-
-
-
-
#6
-
-
日常保洁
-
销量47 (19%)
-
-
-
-
-

热门服务

-
-
🥇
-
-
日常保洁
-
销量47 (19%)
-
-
-
-
-
-
-
🥈
-
-
日常保洁
-
销量47 (19%)
-
-
-
-
-
-
-
🥉
-
-
日常保洁
-
销量47 (19%)
-
-
-
-
-
- -
-
#4
-
-
日常保洁
-
销量47 (19%)
-
-
-
-
#5
-
-
日常保洁
-
销量47 (19%)
-
-
-
-
#6
-
-
日常保洁
-
销量47 (19%)
-
-
-
diff --git a/public/assets/js/backend/orderplan.js b/public/assets/js/backend/orderplan.js index 442c715..88966e3 100644 --- a/public/assets/js/backend/orderplan.js +++ b/public/assets/js/backend/orderplan.js @@ -8,6 +8,9 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'echarts','echarts-th }, function (data, ret) { Controller.echarts.top(data.top); Controller.echarts.order(data.order); + Controller.echarts.ordercount(data.order_count); + Controller.echarts.orderrank(data.order_rank); + Controller.echarts.orderItemRank(data.item_rank); Controller.echarts.money_line(data.lines); Controller.echarts.cancel_order_pie(data.pie.cancel); Controller.echarts.item_pie(data.pie.item); @@ -49,6 +52,76 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'echarts','echarts-th $(this).html(data[map[index]]); }); }, + ordercount: function(data){ + let map = [ + 'total', + 'month_total', + 'count', + 'month_count', + 'worker', + 'month_worker', + 'after_sale', + 'month_after_sale', + 'cancel', + 'month_cancel' + ]; + $('.static-text-num').each(function(index) { + $(this).html(data[map[index]]); + }); + }, + orderrank: function(data){ + + $('#order_rank .rank-name').each(function(index) { + $(this).html(data.dispatch[index]?.name ?? '虚位以待'); + }); + $('#order_rank .rank-num').each(function(index) { + $(this).html((data.dispatch[index]?.count ?? 0) + '单'); + }); + + $('#order_worker .rank-name').each(function(index) { + $(this).html(data.doing[index]?.name ?? '虚位以待'); + }); + $('#order_worker .rank-num').each(function(index) { + $(this).html((data.doing[index]?.count ?? 0) + '单'); + }); + + }, + orderItemRank: function(data){ + + $('#hot_item_rank .service-content-title').each(function(index) { + $(this).html(data.item[index]?.name ?? '虚位以待'); + }); + $('#hot_item_rank .service-content-sub').each(function(index) { + let text = data.item[index]?.count ?? ''; + if (text !== ''){ + text ='订单' + text + '('+ (data.item[index]?.rate ?? '0') + '%)'; + } + $(this).html(text); + }); + + $('#hot_item_rank .progress .bg-pink').each(function(index) { + let width = data.item[index]?.rate ?? 0; + $(this).css('width',width+'%'); + }); + + + $('#hot_area_rank .service-content-title').each(function(index) { + $(this).html(data.area[index]?.name ?? '虚位以待'); + }); + $('#hot_area_rank .service-content-sub').each(function(index) { + let text = data.area[index]?.count ?? ''; + if (text !== ''){ + text ='订单' + text + '('+ (data.area[index]?.rate ?? '0') + '%)'; + } + $(this).html(text); + }); + + $('#hot_area_rank .progress .bg-pink').each(function(index) { + let width = data.area[index]?.rate ?? 0; + $(this).css('width',width+'%'); + }); + + }, item_pie: function(data){ // 基本的饼图配置 var myChart = echarts.init(document.getElementById('item_pie'));