Accept Merge Request #44: (feature/hant -> develop)

Merge Request: 面板

Created By: @todayswind
Accepted By: @todayswind
URL: https://g-bcrc3009.coding.net/p/allocatr/d/allocatr/git/merge/44?initial=true
This commit is contained in:
todayswind 2025-05-11 17:05:33 +08:00 committed by Coding
commit b9eef2ea5c
3 changed files with 246 additions and 61 deletions

View File

@ -9,6 +9,7 @@ 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\orders\Dispatchlog;
use app\admin\model\Worker;
use app\admin\model\WorkerItem;
use app\common\controller\Backend;
@ -65,6 +66,7 @@ class Orderplan extends Backend
$order_count = $this->getOrderCount();
$order_rank = $this->orderRank();
$item_rank = $this->itemRank();
$order_doing = $this->orderDoing();
$this->success(data: [
'top' => $top,
'lines' => $lines,
@ -73,6 +75,7 @@ class Orderplan extends Backend
'order_count' => $order_count,
'order_rank' => $order_rank,
'item_rank' => $item_rank,
'order_doing' => $order_doing,
]);
}
@ -92,10 +95,10 @@ class Orderplan extends Backend
$worker = Worker::where('status', 1)->count();
if ($res) {
return [
'total' => $res->total,
'count' => $res->count,
'performance' => $res->performance,
'worker' => $worker,
'total' => $res->total ?? 0,
'count' => $res->count ?? 0,
'performance' => $res->performance ?? 0,
'worker' => $worker ?? 0,
];
}
@ -110,8 +113,21 @@ class Orderplan extends Backend
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');
$end_at = now()->format('Y-m-d 23:29:59');
$filter ['daterange'] = request()->get('daterange');
if (!empty($filter['daterange'])) {
$arr = explode(' - ', $filter['daterange']);
if (trim($arr[0])) {
$start = trim($arr[0]);
}
if (trim($arr[1])) {
$end_at = trim($arr[1]) . ' 23:29:59';
}
}
$this->buildDate($build);
$build->field([
'DATE(create_time) day',
'sum(total) total',
@ -202,8 +218,18 @@ class Orderplan extends Backend
private function buildDate($build, $table_name = null)
{
$start = now()->modify('-14 days')->format('Y-m-d');
$end_at = now()->format('Y-m-d');
$end_at = now()->format('Y-m-d 23:29:59');
$filter ['daterange'] = request()->get('daterange');
if (!empty($filter['daterange'])) {
$arr = explode(' - ', $filter['daterange']);
if (trim($arr[0])) {
$start = trim($arr[0]);
}
if (trim($arr[1])) {
$end_at = trim($arr[1]) . ' 23:29:59';
}
}
// dd([$start, $end_at]);
if ($table_name) {
$build->where($table_name . '.create_time', 'between', [$start, $end_at]);
} else {
@ -401,7 +427,6 @@ class Orderplan extends Backend
$end_at = now()->format('Y-m-d 23:59:59');
$build = new \app\admin\model\Order();
$build->whereBetween('create_time', [$start, $end_at]);
@ -426,7 +451,7 @@ class Orderplan extends Backend
$rank [] = [
'name' => $da->item->title ?? '',
'count' => $da->count ?? 0,
'rate' => $this->mydiv($da->count ?? 0,$total)
'rate' => $this->mydiv($da->count ?? 0, $total)
];
}
@ -437,14 +462,14 @@ class Orderplan extends Backend
'count(id) count',
])
->group('name')
->order('count','desc')
->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);
$re['rate'] = $this->mydiv($da->count ?? 0, $total);
$area [] = $re;
}
@ -454,6 +479,35 @@ class Orderplan extends Backend
];
}
private function orderDoing()
{
$build = new \app\admin\model\Order();
$dispatch = $build->where('status',10)->count('id');
$build = new OrderDispatch();
$build->whereIn('status',[
OrderDispatch::STATUS_TOGET,
OrderDispatch::STATUS_PLANIT,
OrderDispatch::STATUS_CLOCK,
]);
$data = $build->field([
'count(if(status=0,1,null)) toget',
'count(if(status=20,1,null)) plan',
'count(if(status=30,1,null)) doing',
])->select();
return [
'dispatch' => $dispatch,
'toget' => $data[0]->toget ?? 0,
'plan' => $data[0]->plan ?? 0,
'doing' => $data[0]->doing ?? 0,
];
}
private function prepareEchartsBarData(array $data, string $startDate, string $endDate): array
@ -487,7 +541,7 @@ class Orderplan extends Backend
$rate[] = $total ? number_format($performance / $total * 100, 2) : '0';
}
return [
$data = [
'xAxis' => $xAxis,
'series' => [
'total' => $series_total,
@ -496,6 +550,56 @@ class Orderplan extends Backend
'rate' => $rate,
],
];
// 判断是否需要按月归档
if (count($data['xAxis']) > 31) {
$monthly = [];
foreach ($data['xAxis'] as $i => $date) {
$month = date('Y-m', strtotime($date));
if (!isset($monthly[$month])) {
$monthly[$month] = [
'total' => 0,
'count' => 0,
'performance' => 0,
'rate_sum' => 0,
'rate_count' => 0,
];
}
$monthly[$month]['total'] += $data['series']['total'][$i];
$monthly[$month]['count'] += $data['series']['count'][$i];
$monthly[$month]['performance'] += $data['series']['performance'][$i];
// 处理 rate字符串转换为 float
$rate = (float)$data['series']['rate'][$i];
$monthly[$month]['rate_sum'] += $rate;
$monthly[$month]['rate_count'] += 1;
}
// 重新生成 xAxis 和 series
$data['xAxis'] = array_keys($monthly);
$data['series'] = [
'total' => [],
'count' => [],
'performance' => [],
'rate' => []
];
foreach ($monthly as $month => $values) {
$data['series']['total'][] = $values['total'];
$data['series']['count'][] = $values['count'];
$data['series']['performance'][] = $values['performance'];
// 平均 rate保留 2 位小数
$averageRate = $values['rate_count'] > 0 ? $values['rate_sum'] / $values['rate_count'] : 0;
$data['series']['rate'][] = number_format($averageRate, 2);
}
}
return $data;
}
@ -544,11 +648,12 @@ class Orderplan extends Backend
}
private function mydiv($a , $b){
private function mydiv($a, $b)
{
if ($b == 0) {
return '0';
}else{
return (int)($a / $b * 100);
} else {
return (int)($a / $b * 100);
}
}

View File

@ -31,6 +31,18 @@
<div class="panel-body">
<div id="myTabContent" class="tab-content">
<div class="tab-pane fade active in" id="first">
<div class="form-inline" id="chart-filter" style="margin-top:20px;margin-bottom: 30px;">
<!-- 单选:维度 -->
<!-- 时间范围 -->
<div class="form-group" style="margin-left: 15px;">
<input type="text" class="form-control datetimerange" data-locale='{"format":"YYYY-MM-DD"}' placeholder="指定日期" name="filter[daterange]" id="daterange" autocomplete="off" style="width: 180px;">
</div>
<!-- 查询按钮 -->
<button class="btn btn-default" id="filter-btn" style="margin-left: 15px;">查询</button>
</div>
<div class="col-md-12" style="margin-bottom: 10px">
<div style="display: flex">
<!-- 卡片 1: 总用户数 -->
@ -86,26 +98,6 @@
</div>
</div>
</div>
<div class="col-md-12">
<div class="col-md-3">
<div class="order-count-plan" style="color: #55d2fe">
<div class="order-count-title">
<div class="todo-plan-title-text text-left" style="flex: 1">
<span class="fa fa-clock-o"></span> 进行中的订单
</div>
</div>
<div class="order-count-num text-left">
1240 / 231 / 23123 / 222
</div>
<div class="order-count-num-sub text-left">
待派单 / 待接单 / 待上门 / 服务中
</div>
</div>
</div>
</div>
<div class="col-md-12" style="margin-top: 10px;margin-bottom: 10px">
<div class="col-md-2">
<div class="todo-plan" style="color: #55d2fe">
@ -255,7 +247,23 @@
</div>
<div class="tab-pane fade" id="second">
<div class="col-md-12">
<div class="col-md-3">
<div class="order-count-plan" style="color: #55d2fe">
<div class="order-count-title">
<div class="todo-plan-title-text text-left" style="flex: 1">
<span class="fa fa-clock-o"></span> 进行中的订单
</div>
</div>
<div class="order-count-num text-left">
0 / 0 / 0 / 0
</div>
<div class="order-count-num-sub text-left">
待派单 / 待接单 / 待上门 / 服务中
</div>
</div>
</div>
</div>
<div class="col-md-12">
<div class="col-md-6">
<div class="col-md-12">订单数据</div>
@ -264,7 +272,7 @@
<div class="static-img fa fa-jpy" style="color: #2281df">
</div>
<div class="static-text">
<p class="static-text-num">¥8848</p>
<p class="static-text-num">loading</p>
<p class="static-text-sub">今日收款</p>
</div>
</div>
@ -274,7 +282,7 @@
<div class="static-img fa fa-jpy" style="color: #2281df">
</div>
<div class="static-text">
<p class="static-text-num">¥8848</p>
<p class="static-text-num">loading</p>
<p class="static-text-sub">本月收款</p>
</div>
</div>
@ -294,7 +302,7 @@
<div class="static-img fa fa-building-o" style="background-color: #eee4ff;color: #0a4b3e">
</div>
<div class="static-text">
<p class="static-text-num">8848</p>
<p class="static-text-num">loading</p>
<p class="static-text-sub">本月订单数</p>
</div>
</div>
@ -314,7 +322,7 @@
<div class="static-img fa fa-users fa-fw" style="background-color: #eee4ff;color: #8951fd">
</div>
<div class="static-text">
<p class="static-text-num">8848</p>
<p class="static-text-num">loading</p>
<p class="static-text-sub">本月新增师傅数</p>
</div>
</div>
@ -324,7 +332,7 @@
<div class="static-img fa fa-users fa-fw" style="color: #f34f61;background-color: #fce1e4">
</div>
<div class="static-text">
<p class="static-text-num">8</p>
<p class="static-text-num">loading</p>
<p class="static-text-sub">今日退款数</p>
</div>
</div>
@ -334,7 +342,7 @@
<div class="static-img fa fa-users fa-fw" style="color: #f34f61;background-color: #fce1e4">
</div>
<div class="static-text">
<p class="static-text-num">88</p>
<p class="static-text-num">loading</p>
<p class="static-text-sub">本月退款数</p>
</div>
</div>
@ -344,7 +352,7 @@
<div class="static-img fa fa-strikethrough fa-fw" style="color:#48cac2;background-color: #f5f6ff">
</div>
<div class="static-text">
<p class="static-text-num">88</p>
<p class="static-text-num">loading</p>
<p class="static-text-sub">今日取消订单数</p>
</div>
</div>
@ -354,7 +362,7 @@
<div class="static-img fa fa-strikethrough fa-fw" style="color:#48cac2;background-color: #f5f6ff">
</div>
<div class="static-text">
<p class="static-text-num">88</p>
<p class="static-text-num">loading</p>
<p class="static-text-sub">本月取消订单数</p>
</div>
</div>

View File

@ -2,22 +2,8 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'echarts','echarts-th
var Controller = {
dashboard: function () {
Fast.api.ajax({
url: 'orderplan/data',
method:'get'
}, 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);
Controller.echarts.area_pie(data.pie.area);
Controller.echarts.source_pie(data.pie.source);
});
Controller.api.getData();
Controller.datetime();
},
add: function () {
Controller.api.bindevent();
@ -28,8 +14,86 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'echarts','echarts-th
api: {
bindevent: function () {
Form.api.bindevent($("form[role=form]"));
},
getData:function (){
// 获取日期范围值
var daterange = $('#daterange').val();
// 构建查询参数
var params = {
'daterange': daterange
};
console.log(params);
Fast.api.ajax({
url: 'orderplan/data',
data: params,
method:'get'
}, function (data, ret) {
Controller.echarts.top(data.top);
Controller.echarts.order(data.order);
Controller.echarts.orderdoing(data.order_doing);
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);
Controller.echarts.area_pie(data.pie.area);
Controller.echarts.source_pie(data.pie.source);
return;
});
}
},
datetime:function () {
var form = $("#chart-filter");
var ranges = {};
ranges[__('Today')] = [Moment().startOf('day'), Moment().endOf('day')];
ranges[__('Yesterday')] = [Moment().subtract(1, 'days').startOf('day'), Moment().subtract(1, 'days').endOf('day')];
ranges[__('Last 7 Days')] = [Moment().subtract(6, 'days').startOf('day'), Moment().endOf('day')];
ranges[__('Last 30 Days')] = [Moment().subtract(29, 'days').startOf('day'), Moment().endOf('day')];
ranges[__('This Month')] = [Moment().startOf('month'), Moment().endOf('month')];
ranges[__('Last Month')] = [Moment().subtract(1, 'month').startOf('month'), Moment().subtract(1, 'month').endOf('month')];
ranges[__('今年')] = [Moment().startOf('year'), Moment()];
var options = {
timePicker: false,
autoUpdateInput: false,
timePickerSeconds: true,
timePicker24Hour: true,
autoApply: true,
locale: {
format: 'YYYY-MM-DD',
customRangeLabel: __("Custom Range"),
applyLabel: __("Apply"),
cancelLabel: __("Clear"),
},
ranges: ranges,
};
var callback = function (start, end) {
$(this.element).val(start.format(options.locale.format)
+ " - " + end.format(options.locale.format));
};
require(['bootstrap-daterangepicker'], function () {
$(".datetimerange", form).each(function () {
$(this).on('apply.daterangepicker', function (ev, picker) {
callback.call(picker, picker.startDate, picker.endDate);
var label = picker.chosenLabel;
$(picker.element).data('label', label).trigger("change");
});
$(this).on('cancel.daterangepicker', function (ev, picker) {
$(this).val('');
});
$(this).daterangepicker($.extend({}, options), callback);
});
});
// 绑定查询按钮的点击事件
$('#filter-btn').on('click', function() {
Controller.api.getData();
});
},
echarts: {
top: function(data){
let map = [
@ -52,6 +116,11 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'echarts','echarts-th
$(this).html(data[map[index]]);
});
},
orderdoing: function(data){
const text = `${data.dispatch} / ${data.toget} / ${data.plan} / ${data.doing}`;
$('.order-count-num ').html(text);
},
ordercount: function(data){
let map = [
'total',
@ -125,7 +194,6 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'echarts','echarts-th
item_pie: function(data){
// 基本的饼图配置
var myChart = echarts.init(document.getElementById('item_pie'));
var option = {
title: {
text: '订单项目类型',
@ -147,6 +215,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'echarts','echarts-th
legend: {
orient: 'vertical',
left: 'left',
type: 'scroll', // 启用分页
data: data.map(item => item.name)
},
series: [
@ -199,6 +268,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'echarts','echarts-th
legend: {
orient: 'vertical',
left: 'left',
type: 'scroll', // 启用分页
data: data.map(item => item.name)
},
series: [
@ -251,6 +321,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'echarts','echarts-th
legend: {
orient: 'vertical',
left: 'left',
type: 'scroll', // 启用分页
data: data.map(item => item.name)
},
series: [
@ -303,6 +374,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'echarts','echarts-th
legend: {
orient: 'vertical',
left: 'left',
type: 'scroll', // 启用分页
data: data.map(item => item.name)
},
series: [