You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel框架下如何为图表配置日期范围选择器并加载数据

解决方案:关联日期选择器、API与Chart.js图表

1. 修正后端控制器逻辑

当前控制器接收参数与前端传递格式不匹配,同时需要处理默认显示当日数据的需求,调整代码如下:

public function LoadPendapatan(Request $request) {      
    // 获取前端传递的日期范围,默认当日
    $dateRange = $request->get('from-to', now()->toDateString() . ' - ' . now()->toDateString());
    list($startDate, $endDate) = explode(' - ', $dateRange);

    // 查询KasMasuk的总和
    $pendapatan = KasMasuk::whereDate('created_at', '>=', trim($startDate))
        ->whereDate('created_at', '<=', trim($endDate))
        ->sum('debet');

    // 查询KasKeluar的总和
    $penjualan = KasKeluar::whereDate('created_at', '>=', trim($startDate))
        ->whereDate('created_at', '<=', trim($endDate))
        ->sum('sub_total');
    
    $income = $pendapatan - $penjualan;

    // 返回结构化JSON,方便前端解析
    return response()->json([
        'pendapatan' => $pendapatan,
        'penjualan' => $penjualan,
        'income' => $income
    ]);
}

2. 重构前端脚本:封装数据获取与图表更新逻辑

把数据请求和图表更新封装成独立函数,在页面初始化和日期选择器变化时调用:

$(function () {
    // 初始化日期选择器的默认日期(当日)
    let start = moment();
    let end = moment();

    // 从URL参数获取已选中的日期范围(如果有)
    let searchParams = new URLSearchParams(window.location.search);
    let dateInterval = searchParams.get('from-to');
    if (dateInterval) {
        [start, end] = dateInterval.split(' - ');
        start = moment(start);
        end = moment(end);
    }

    // 初始化Chart.js实例(保留原有配置,优化数据结构)
    'use strict'
    var ticksStyle = {
        fontColor: '#495057',
        fontStyle: 'bold'
    }
    var mode = 'index'
    var intersect = true
    
    var $salesChart = $('#sales-chart')
    var salesChart = new Chart($salesChart, {
        type: 'bar',
        data: {
            labels: ['Pendapatan', 'Penjualan', 'Income'], // 匹配实际数据的标签
            datasets: [{
                backgroundColor: ['#007bff', '#dc3545', '#28a745'],
                data: [0, 0, 0] // 初始空数据
            }]
        },
        options: {
            maintainAspectRatio: false,
            tooltips: {
                mode: mode,
                intersect: intersect
            },
            hover: {
                mode: mode,
                intersect: intersect
            },
            legend: {
                display: false
            },
            scales: {
                yAxes: [{
                    gridLines: {
                        display: true,
                        lineWidth: '4px',
                        color: 'rgba(0, 0, 0, .2)',
                        zeroLineColor: 'transparent'
                    },
                    ticks: $.extend({
                        beginAtZero: true,
                        callback: function (value) {
                            if (value >= 1000000) {
                                value /= 1000000
                                value += 'jt'
                            } else if (value >= 1000) {
                                value /= 1000
                                value += 'k'
                            }
                            return 'Rp. ' + value
                        }
                    }, ticksStyle)
                }],
                xAxes: [{
                    display: true,
                    gridLines: {
                        display: false
                    },
                    ticks: ticksStyle
                }]
            }
        }
    });

    // 封装:获取数据并更新图表
    function updateChart(startDate, endDate) {
        // 拼接日期范围参数
        let dateRange = `${startDate.format('YYYY-MM-DD')} - ${endDate.format('YYYY-MM-DD')}`;
        
        // 调用API获取数据
        $.get('/load-pendapatan', { 'from-to': dateRange }, function(response) {
            // 更新图表数据并触发重绘
            salesChart.data.datasets[0].data = [response.pendapatan, response.penjualan, response.income];
            salesChart.update();
        });
    }

    // 初始化日期选择器
    $('#reservation').daterangepicker({
        "showWeekNumbers": true,
        "alwaysShowCalendars": true,
        startDate: start,
        endDate: end,
        locale: {
            format: 'YYYY-MM-DD',
            firstDay: 1,
        },
        ranges: {
            'Today': [moment(), moment()],
            'Yesterday': [moment().subtract(1, 'days'), moment().subtract(1, 'days')],
            'Last 7 Days': [moment().subtract(6, 'days'), moment()],
            'Last 30 Days': [moment().subtract(29, 'days'), moment()],
            'This Month': [moment().startOf('month'), moment().endOf('month')],
            'Last Month': [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')],
            'This Year': [moment().startOf('year'), moment().endOf('year')],
            'Last Year': [moment().subtract(1, 'year').startOf('year'), moment().subtract(1, 'year').endOf('year')],
            'All time': [moment().subtract(30, 'year').startOf('month'), moment().endOf('month')],
        }
    }, function(start, end) {
        // 日期选择完成后触发图表更新
        updateChart(start, end);
        // 可选:更新URL参数,刷新页面时保留选中的日期
        searchParams.set('from-to', `${start.format('YYYY-MM-DD')} - ${end.format('YYYY-MM-DD')}`);
        window.history.replaceState({}, '', `${window.location.pathname}?${searchParams}`);
    });

    // 页面加载完成后,初始化图表数据(默认当日)
    updateChart(start, end);
});

3. 关键修改说明

  • 后端:
    • 改为接收from-to参数(与前端表单name一致)
    • 默认值设为当日日期范围,满足页面加载时显示当日数据的需求
    • 返回结构化JSON,前端更易解析
  • 前端:
    • 封装updateChart函数,统一处理数据请求和图表更新
    • 日期选择器的回调中调用updateChart,实现选择日期后自动刷新图表
    • 修改图表标签为实际数据对应的名称,优化展示
    • 添加URL参数更新,刷新页面时保留用户选中的日期范围

内容的提问来源于stack exchange,提问作者Firdan Mahendra Wardana

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 00:50:14