diff --git a/application/admin/controller/Orderplan.php b/application/admin/controller/Orderplan.php
index 4c22078..ba2d728 100644
--- a/application/admin/controller/Orderplan.php
+++ b/application/admin/controller/Orderplan.php
@@ -3,8 +3,10 @@
namespace app\admin\controller;
use app\admin\addresmart\Address;
+use app\admin\model\Abnormal;
use app\admin\model\AuthGroupAccess;
use app\admin\model\order\Invoice;
+use app\admin\model\OrderAbnormal;
use app\admin\model\OrderDispatch;
use app\admin\model\Worker;
use app\admin\model\WorkerItem;
@@ -41,16 +43,246 @@ class Orderplan extends Backend
parent::_initialize();
$this->model = new \app\admin\model\Order;
-
- //$this->view->assign("collectList", $this->model->getCollectList());
- //$this->view->assign("dispatchTypeList", $this->model->getDispatchTypeList());
}
- public function dashboard(){
+ public function dashboard()
+ {
return $this->fetch('orderplan/index');
}
+ public function data()
+ {
+ $top = $this->getTopTotal();
+ $lines = $this->getLine();
+ $pie = $this->getPie();
+ $this->success(data: [
+ 'top' => $top,
+ 'lines' => $lines,
+ 'pie' => $pie,
+ ]);
+ }
+
+ private function getTopTotal()
+ {
+ $build = new \app\admin\model\Order();
+
+ $build->field([
+ 'sum(total) total',
+ 'count(id) count',
+ 'sum(performance) performance'
+ ])->limit(1);
+
+ $res = $this->buildDate($build)->select();
+
+ $res = $res[0] ?? false;
+ $worker = Worker::where('status', 1)->count();
+ if ($res) {
+ return [
+ 'total' => $res->total,
+ 'count' => $res->count,
+ 'performance' => $res->performance,
+ 'worker' => $worker,
+ ];
+ }
+
+ return [
+ 'total' => 0,
+ 'count' => 0,
+ 'performance' => 0,
+ 'worker' => 0,
+ ];
+ }
+
+ private function getLine()
+ {
+ $build = new \app\admin\model\Order();
+ $start = now()->modify('-14 days')->format('Y-m-d');
+ $end_at = now()->format('Y-m-d');
+ $build->field([
+ 'DATE(create_time) day',
+ 'sum(total) total',
+ 'count(id) count',
+ 'sum(performance) performance'
+ ])->group(' DATE(create_time)');
+
+ $res = $this->buildDate($build)->select();
+ $data = [];
+ foreach ($res as $re) {
+ $re = $re->getData();
+ $data [] = $re;
+ }
+ return $this->prepareEchartsBarData($data, $start, $end_at);
+ }
+
+ private function getPie()
+ {
+ $build = new OrderAbnormal();
+ $res = $this->buildDate($build)
+ ->field([
+ 'abnormal_title name',
+ 'count(id) value',
+ ])
+ ->group('abnormal_title')
+ ->select();
+ $data = [];
+ foreach ($res as $re) {
+ $re = $re->getData();
+ $data [] = $re;
+ }
+ $out ['cancel'] = $data;
+
+
+
+ $build = new \app\admin\model\Order();
+ $res = $this->buildDate($build)
+ ->field([
+ 'item_title name',
+ 'count(id) value',
+ ])
+ ->group('item_title')
+ ->select();
+ $data = [];
+ foreach ($res as $re) {
+ $re = $re->getData();
+ $name = explode('/',$re['name']);
+ $re['name'] = str_replace(' ', '' ,array_pop($name));
+ $data [] = $re;
+ }
+ $out ['item'] = $data;
+
+ $build = new \app\admin\model\Order();
+ $res = $this->buildDate($build)
+ ->field([
+ 'SUBSTRING(area_id, 1, 2) AS name',
+ 'count(id) value',
+ ])
+ ->group('name')
+ ->select();
+ $data = [];
+ foreach ($res as $re) {
+ $re = $re->getData();
+ $re['name'] = $this->getProvinceByCode($re['name']);
+ $data [] = $re;
+ }
+ $out ['area'] = $data;
+
+ $build = new \app\admin\model\Order();
+ $res = $this->buildDate($build)
+ ->field([
+ 'source_shop AS name',
+ 'count(id) value',
+ ])
+ ->group('name')
+ ->select();
+ $data = [];
+ foreach ($res as $re) {
+ $re = $re->getData();
+ $data [] = $re;
+ }
+ $out ['source'] = $data;
+
+
+ return $out;
+ }
+
+
+ private function buildDate($build)
+ {
+ $start = now()->modify('-14 days')->format('Y-m-d');
+ $end_at = now()->format('Y-m-d');
+
+ $build->where('create_time', 'between', [$start, $end_at]);
+ return $build;
+ }
+
+ private function prepareEchartsBarData(array $data, string $startDate, string $endDate): array
+ {
+ // 将原始数据用日期作为键索引
+ $indexed = [];
+ foreach ($data as $item) {
+ $indexed[$item['day']] = $item;
+ }
+
+ $start = strtotime($startDate);
+ $end = strtotime($endDate);
+
+ $xAxis = [];
+ $series_total = [];
+ $series_count = [];
+ $series_performance = [];
+ $rate = [];
+
+ for ($date = $start; $date <= $end; $date += 86400) {
+ $day = date('Y-m-d', $date);
+ $xAxis[] = $day;
+
+ $total = isset($indexed[$day]) ? (float)$indexed[$day]['total'] : 0;
+ $count = isset($indexed[$day]) ? (int)$indexed[$day]['count'] : 0;
+ $performance = isset($indexed[$day]) ? (float)$indexed[$day]['performance'] : 0;
+
+ $series_total[] = $total;
+ $series_count[] = $count;
+ $series_performance[] = $performance;
+ $rate[] = $total ? number_format($performance / $total * 100, 2) : '0';
+ }
+
+ return [
+ 'xAxis' => $xAxis,
+ 'series' => [
+ 'total' => $series_total,
+ 'count' => $series_count,
+ 'performance' => $series_performance,
+ 'rate' => $rate,
+ ],
+ ];
+ }
+
+
+ function getProvinceByCode($code) {
+ // 省级行政区域编码对应数组
+ $provinces = [
+ 11 => '北京',
+ 12 => '天津',
+ 13 => '河北',
+ 14 => '山西',
+ 15 => '内蒙古',
+ 21 => '辽宁',
+ 22 => '吉林',
+ 23 => '黑龙江',
+ 31 => '上海',
+ 32 => '江苏',
+ 33 => '浙江',
+ 34 => '安徽',
+ 35 => '福建',
+ 36 => '江西',
+ 37 => '山东',
+ 41 => '河南',
+ 42 => '湖北',
+ 43 => '湖南',
+ 44 => '广东',
+ 45 => '广西',
+ 46 => '海南',
+ 50 => '重庆',
+ 51 => '四川',
+ 52 => '贵州',
+ 53 => '云南',
+ 54 => '西藏',
+ 61 => '陕西',
+ 62 => '甘肃',
+ 63 => '青海',
+ 64 => '宁夏',
+ 65 => '新疆',
+ 71 => '台湾',
+ 81 => '香港',
+ 82 => '澳门'
+ ];
+
+ // 如果提供的代码存在于数组中,返回对应的省名称,否则返回未知
+ return isset($provinces[$code]) ? $provinces[$code] : '未知';
+ }
+
+
}
diff --git a/application/admin/view/orderplan/index.html b/application/admin/view/orderplan/index.html
index cc916c8..1a730f4 100644
--- a/application/admin/view/orderplan/index.html
+++ b/application/admin/view/orderplan/index.html
@@ -26,7 +26,7 @@
订单量
- 1,240
+ loading
@@ -39,7 +39,7 @@
总业绩
- 1,240
+ loading
@@ -52,7 +52,7 @@
师傅总数
- 1,240
+ loading
diff --git a/public/assets/js/backend/orderplan.js b/public/assets/js/backend/orderplan.js
index f10d39b..7d0fc59 100644
--- a/public/assets/js/backend/orderplan.js
+++ b/public/assets/js/backend/orderplan.js
@@ -2,13 +2,20 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'echarts','echarts-th
var Controller = {
dashboard: function () {
+ Fast.api.ajax({
+ url: 'orderplan/data',
+ }, function (data, ret) {
+ Controller.echarts.top(data.top);
+ Controller.echarts.money_line(data.lines);
+ Controller.echarts.cancel_order_pie(data.pie.cancel);
+ Controller.echarts.item_pie(data.pie.item);
+ Controller.echarts.area_pie(data.pie.area);
+ Controller.echarts.source_pie(data.pie.source);
+ });
Controller.api.bindevent();
- Controller.echarts.item_pie();
- Controller.echarts.area_pie();
- Controller.echarts.source_pie();
Controller.echarts.cancel_order_pie();
- Controller.echarts.money_line();
+
console.log(123);
},
@@ -24,13 +31,26 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'echarts','echarts-th
}
},
echarts: {
- item_pie: function(){
+ top: function(data){
+ let map = [
+ 'count','performance','worker'
+ ];
+ $('.myplan-num').each(function(index) {
+ if (index === 1){
+ $(this).html('¥' + data[map[index]]);
+ }else {
+ $(this).html(data[map[index]]);
+
+ }
+ });
+ },
+ item_pie: function(data){
// 基本的饼图配置
var myChart = echarts.init(document.getElementById('item_pie'));
var option = {
title: {
- text: '取消订单类型',
+ text: '订单项目类型',
subtext: '',
left: 'right'
},
@@ -49,7 +69,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'echarts','echarts-th
legend: {
orient: 'vertical',
left: 'left',
- data: ['直接访问', '邮件营销', '联盟广告', '视频广告', '搜索引擎']
+ data: data.map(item => item.name)
},
series: [
{
@@ -57,13 +77,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'echarts','echarts-th
type: 'pie',
radius: '50%',
center: ['50%', '60%'],
- data: [
- { value: 335, name: '直接访问' },
- { value: 310, name: '邮件营销' },
- { value: 234, name: '联盟广告' },
- { value: 135, name: '视频广告' },
- { value: 1548, name: '搜索引擎' }
- ],
+ data: data,
emphasis: {
itemStyle: {
shadowBlur: 10,
@@ -82,13 +96,13 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'echarts','echarts-th
myChart.resize();
});
},
- area_pie: function(){
+ area_pie: function(data){
// 基本的饼图配置
var myChart = echarts.init(document.getElementById('area_pie'));
var option = {
title: {
- text: '取消订单类型',
+ text: '订单区域',
subtext: '',
left: 'right'
},
@@ -96,11 +110,6 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'echarts','echarts-th
trigger: 'item',
formatter: '{a}
{b}: {c} ({d}%)'
},
- legend: {
- orient: 'vertical',
- left: 'left',
- data: ['直接访问', '邮件营销', '联盟广告', '视频广告', '搜索引擎']
- },
color: [
"#18d1b1",
"#3fb1e3",
@@ -109,19 +118,18 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'echarts','echarts-th
"#c4ebad",
"#96dee8"
],
+ legend: {
+ orient: 'vertical',
+ left: 'left',
+ data: data.map(item => item.name)
+ },
series: [
{
- name: '访问来源',
+ name: '订单区域',
type: 'pie',
radius: '50%',
center: ['50%', '60%'],
- data: [
- { value: 335, name: '直接访问' },
- { value: 310, name: '邮件营销' },
- { value: 234, name: '联盟广告' },
- { value: 135, name: '视频广告' },
- { value: 1548, name: '搜索引擎' }
- ],
+ data: data,
emphasis: {
itemStyle: {
shadowBlur: 10,
@@ -140,13 +148,13 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'echarts','echarts-th
myChart.resize();
});
},
- source_pie: function(){
+ source_pie: function(data){
// 基本的饼图配置
var myChart = echarts.init(document.getElementById('source_pie'));
var option = {
title: {
- text: '订单地区',
+ text: '来源店铺',
subtext: '',
left: 'right'
},
@@ -165,21 +173,15 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'echarts','echarts-th
legend: {
orient: 'vertical',
left: 'left',
- data: ['直接访问', '邮件营销', '联盟广告', '视频广告', '搜索引擎']
+ data: data.map(item => item.name)
},
series: [
{
- name: '访问来源',
+ name: '来源店铺',
type: 'pie',
radius: '50%',
center: ['50%', '60%'],
- data: [
- { value: 335, name: '直接访问' },
- { value: 310, name: '邮件营销' },
- { value: 234, name: '联盟广告' },
- { value: 135, name: '视频广告' },
- { value: 1548, name: '搜索引擎' }
- ],
+ data: data,
emphasis: {
itemStyle: {
shadowBlur: 10,
@@ -198,13 +200,13 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'echarts','echarts-th
myChart.resize();
});
},
- cancel_order_pie: function(){
+ cancel_order_pie: function(data){
// 基本的饼图配置
var myChart = echarts.init(document.getElementById('cancel_order_pie'));
var option = {
title: {
- text: '订单来源',
+ text: '异常订单占比',
subtext: '',
left: 'right'
},
@@ -223,7 +225,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'echarts','echarts-th
legend: {
orient: 'vertical',
left: 'left',
- data: ['直接访问', '邮件营销', '联盟广告', '视频广告', '搜索引擎']
+ data: data.map(item => item.name)
},
series: [
{
@@ -231,13 +233,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'echarts','echarts-th
type: 'pie',
radius: '50%',
center: ['50%', '60%'],
- data: [
- { value: 335, name: '直接访问' },
- { value: 310, name: '邮件营销' },
- { value: 234, name: '联盟广告' },
- { value: 135, name: '视频广告' },
- { value: 1548, name: '搜索引擎' }
- ],
+ data: data,
emphasis: {
itemStyle: {
shadowBlur: 10,
@@ -256,7 +252,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'echarts','echarts-th
myChart.resize();
});
},
- money_line: function (){
+ money_line: function (data){
var myChart = echarts.init(document.getElementById('money_line'));
var option = {
@@ -283,13 +279,13 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'echarts','echarts-th
"#96dee8"
],
legend: {
- data: ['柱状图1', '柱状图2', '折线图'],
+ data: ['订单量', '营销额', '收益','收益率'],
left: 'left'
},
xAxis: [
{
type: 'category',
- data: ['1月', '2月', '3月', '4月', '5月', '6月'],
+ data: data.xAxis,
axisPointer: {
type: 'shadow'
}
@@ -298,41 +294,51 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'echarts','echarts-th
yAxis: [
{
type: 'value',
- name: '柱状图数值',
+ name: '金额',
position: 'left'
},
{
type: 'value',
- name: '折线图数值',
+ name: '单量/百分比',
position: 'right',
min: 0, // 设置右侧y轴的最小值
- max: 1 // 设置右侧y轴的最大值
+ max: 100 // 设置右侧y轴的最大值
}
],
series: [
{
- name: '柱状图1',
+ name: '订单量',
type: 'bar',
- data: [120, 132, 101, 134, 90, 230],
+ data: data.series.count,
+ emphasis: {
+ focus: 'series'
+ },
+ yAxisIndex: 1,
+ barGap: '10%' // 调整柱状图1与柱状图2之间的间距
+ },
+ {
+ name: '营销额',
+ type: 'bar',
+ data: data.series.total,
emphasis: {
focus: 'series'
},
barGap: '10%' // 调整柱状图1与柱状图2之间的间距
},
{
- name: '柱状图2',
+ name: '收益',
type: 'bar',
- data: [220, 182, 191, 234, 290, 330],
+ data: data.series.performance,
emphasis: {
focus: 'series'
},
barGap: '10%' // 调整柱状图1与柱状图2之间的间距
},
{
- name: '折线图',
+ name: '收益率',
type: 'line',
yAxisIndex: 1,
- data: [0.2, 0.3, 0.4, 0.6, 0.5, 0.8],
+ data: data.series.rate,
smooth: true,
lineStyle: {
color: '#ff6600'