modify('-7 days')->format('Y-m-d'); $end_at = now()->format('Y-m-d'); $default_daterange = $start . ' - ' . $end_at; return $this->fetch('index',[ 'default_daterange' => $default_daterange ]); } public function list() { $build = new Order(); $start = now()->modify('-7 days')->format('Y-m-d'); $end_at = now()->format('Y-m-d 23:29:59'); $filter = request()->get('range',''); if (!empty($filter)){ $arr = explode(' - ', $filter); if (trim($arr[0])) { $start = trim($arr[0]); } if (trim($arr[1])) { $end_at = trim($arr[1]) . ' 23:29:59'; } } $area_id = request()->get('area_id'); if ($area_id) { $area_id = $this->trimSpecialZeros($area_id); $build->where('area_id', 'like', $area_id . '%'); } $build->whereBetween('create_time', [$start, $end_at]) ->field([ 'item_title name', // 类型 'sum(total) total', // 营业额 'count(id) count_num', // 单量 'count(if(status=60,1,null)) finish_num', // 单量 'sum(performance) performance', // 收益 'sum(cost) cost', // 收益 'sum(material_cost) material_cost', // 收益 'sum(refund_amount) refund_amount', // 公司退款 'sum(worker_refund_amount) worker_refund_amount', // 工人退款 ])->group('item_title') ->order('count_num', 'desc'); // dd($total); $res = $build->paginate(); $total = $res->total(); $ress = $res->items(); $data = []; // dd($res); foreach ($ress as $re) { $re = $re->toArray(); // dd($re); $cost_total = $re['cost'] + $re['material_cost']; $name = explode('/', $re['name']); $re['name'] = str_replace(' ', '', array_pop($name)); $re['performance_rate'] = $this->mydiv($re['performance'],$re['total']); $re['trans_rate'] = $this->mydiv($re['finish_num'],$re['count_num']); $re['cash_value'] = $this->mydiv($re['performance'],$re['count_num'],2,false); $re['total_avg'] = $this->mydiv($re['total'],$re['count_num'],2,false); $re['performance_avg'] = $this->mydiv($re['performance'],$re['finish_num'],2,false); $re['cost_total'] = $cost_total; // $re['id'] = $re['item_id']; $data [] = $re; } return [ 'rows' => $data, 'total' => $total ]; } function trimSpecialZeros($str) { if (strlen($str) !== 6) { return $str; // 非6位字符串直接返回 } if (substr($str, -4) === "0000") { return substr($str, 0, 2); // 去掉后4位 } elseif (substr($str, -2) === "00") { return substr($str, 0, 4); // 去掉后2位 } return $str; // 不符合条件则原样返回 } public function chartData() { $build = new Order(); $start = now()->modify('-14 days')->format('Y-m-d'); $end_at = now()->format('Y-m-d 23:29:59'); $filter ['daterange'] = request()->post('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'; } } $res = $build ->whereBetween('create_time', [$start, $end_at]) ->field([ 'item_title name', // 类型 'sum(total) total', // 营业额 'count(id) count', // 单量 'count(if(status=60,1,null)) finish_num', // 单量 'sum(performance) performance', // 收益 'sum(refund_amount) refund_amount', // 公司退款 'sum(worker_refund_amount) worker_refund_amount', // 工人退款 ])->group('item_title') ->order('count', 'desc')->select(); $data = []; foreach ($res as $re) { $re = $re->getData(); $name = explode('/', $re['name']); $re['name'] = str_replace(' ', '', array_pop($name)); $data [] = $re; } // dd($data); $xAxis = []; $totalPerformance = []; $conversionRate = []; // 假设转化率 = performance / total(或自定义逻辑) $profitRate = []; // 假设利润率 = (performance - worker_refund_amount) / performance $refundRate = []; // 假设退款率 = refund_amount / total $monetizedValue = []; // 假设变现值 = performance - refund_amount foreach ($data as $item) { $name = $item['name']; $total = (float)$item['total']; $finish_num = (int)$item['finish_num']; $performance = (float)$item['performance']; $refund = (float)($item['refund_amount'] + $item['worker_refund_amount']); $workerRefund = (float)$item['worker_refund_amount']; $count = max((int)$item['count'], 1); // 避免除以0 $xAxis[] = $name; $totalPerformance[] = $total; $conversionRate[] = $total > 0 ? round($finish_num / $count * 100, 2) : 0; $profitRate[] = $total > 0 ? round(($performance) / $total * 100, 2) : 0; $refundRate[] = $total > 0 ? round($refund / $total * 100, 2) : 0; $monetizedValue[] = round($total / $count, 2) ; } if ($totalPerformance){ $result = [ 'xAxis' => $xAxis, 'series' => [ ['name' => '总业绩(¥)', 'type' => 'bar', 'yAxisIndex' => 0, 'data' => $totalPerformance], ['name' => '转化率(%)', 'type' => 'bar', 'yAxisIndex' => 1, 'data' => $conversionRate], ['name' => '利润率(%)', 'type' => 'bar', 'yAxisIndex' => 1, 'data' => $profitRate], ['name' => '退款率(%)', 'type' => 'bar', 'yAxisIndex' => 1, 'data' => $refundRate], ['name' => '变现值(¥)', 'type' => 'line', 'yAxisIndex' => 0, 'data' => $monetizedValue], ] ]; }else{ $result = [ 'xAxis' => ['无'], 'series' => [ ['name' => '总业绩(¥)', 'type' => 'bar', 'yAxisIndex' => 0, 'data' => [0]], ['name' => '转化率(%)', 'type' => 'bar', 'yAxisIndex' => 1, 'data' => [0]], ['name' => '利润率(%)', 'type' => 'bar', 'yAxisIndex' => 1, 'data' => [0]], ['name' => '退款率(%)', 'type' => 'bar', 'yAxisIndex' => 1, 'data' => [0]], ['name' => '变现值(¥)', 'type' => 'line', 'yAxisIndex' => 0, 'data' => [0]], ] ]; } return $result; } private function mydiv($a, $b, int $scale = 4, $is_percent = true): int|string { $val = $b > 0 ? bcdiv($a, $b, $scale) : 0; if ($is_percent) { return bcmul($val, 100, 2); } return $val; } }