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

Highcharts stockChart 校正日期索引与显示当前日期方案

核心问题定位
  • Highcharts.stockChart 默认X轴为datetime时间类型,不支持直接传入字符串数组作为categories分类绑定,这是X轴日期显示错位、索引不匹配的直接原因,原代码中给X轴传categories的写法仅适配普通Highcharts.chart的分类轴场景。
  • 后端查询逻辑仅返回存在销售记录的日期,缺失无销量的间隔日期、从最早销售日到当前日期的空档日期,图表无法自动补全日期到当日。
  • 原代码chart配置中冗余写了renderTo: 'container',和初始化时传入的grafico容器冲突,会导致渲染目标异常。

分步修复方案

1. 后端逻辑修正:补全全量自然日数据

修改CodeIgniter模型层的montos方法,生成从最早销售日期到当日的连续自然日序列,无销售额的日期自动填充0,保证日期无断层。控制器代码无需改动。

public function montos(){
    // 查询最早的交易日期
    $this->db->select("MIN(DATE(fecha_actualizacion)) as start_date");
    $this->db->from("venta");
    $this->db->where("pago_id","2");
    $this->db->where("estado","1");
    $start_res = $this->db->get()->row();
    $start_date = $start_res->start_date ?? date('Y-m-d');
    $end_date = date('Y-m-d');

    // 生成起止日期内所有自然日,默认金额为0
    $all_dates = [];
    $period = new DatePeriod(
        new DateTime($start_date),
        new DateInterval('P1D'),
        new DateTime($end_date . ' +1 day')
    );
    foreach ($period as $d) {
        $all_dates[$d->format('Y-m-d')] = 0;
    }

    // 查询实际销售数据
    $this->db->select("DATE(fecha_actualizacion) as fecha, SUM(total) as monto");
    $this->db->from("venta");
    $this->db->where("pago_id","2");
    $this->db->where("estado","1");
    $this->db->where("fecha_actualizacion >= ", $start_date);
    $this->db->group_by('DATE(fecha_actualizacion)');
    $this->db->order_by('DATE(fecha_actualizacion)');
    $sales_data = $this->db->get()->result();

    // 合并销售数据到全量日期序列
    foreach ($sales_data as $row) {
        $all_dates[$row->fecha] = (float)$row->monto;
    }

    // 组装接口返回格式
    $result = [];
    foreach ($all_dates as $fecha => $monto) {
        $result[] = [
            'fecha_actualizacion' => $fecha,
            'monto' => $monto
        ];
    }
    return $result;
}

2. 前端逻辑修正:适配stockChart时间轴规则

废弃categories传参方式,将数据转换为stockChart要求的[UTC时间戳, 数值]二维格式,显式配置X轴为时间类型,补充日期格式化、列宽适配配置。

function datagrafico(base_url){
    $.ajax({
        url: base_url + "index.php/Admin/getDataDias",
        type:"POST",
        dataType:"json",
        success:function(data){
            var chart_data = [];
            $.each(data,function(key, value){
                // 日期转UTC时间戳,避免时区偏差导致日期错位
                const date = new Date(value.fecha_actualizacion);
                const timestamp = Date.UTC(date.getFullYear(), date.getMonth(), date.getDate());
                chart_data.push([timestamp, Number(value.monto)]);
            });
            graficar(chart_data);
        }
    });
}

function graficar(chart_data){
    Highcharts.stockChart('grafico', {
        chart: {
            type: 'column'
            // 删除冗余冲突的renderTo配置,初始化第一个参数已指定渲染容器
        },
        title: {
            text: 'Monto acumulado por ventas diarias'
        },
        subtitle: {
            text: ''
        },
        xAxis: {
            type: 'datetime', // 显式指定X轴为时间类型
            crosshair: true,
            dateTimeLabelFormats: { // 配置不同缩放级别下的日期显示格式
                day: '%Y-%m-%d',
                week: '%Y-%m-%d',
                month: '%Y-%m'
            }
        },
        yAxis: {
            min: 0,
            title: {
                text: 'Monto Acumulado (Colombiano)'
            }
        },
        tooltip: {
            headerFormat: '<span style="font-size:10px">{point.key:%Y-%m-%d}</span><table>',
            pointFormat: '<tr><td style="color:{series.color};padding:0">Monto: </td>' +
            '<td style="padding:0"><b>{point.y} Colombiano</b></td></tr>',
            footerFormat: '</table>',
            shared: true,
            useHTML: true
        },
        plotOptions: {
            column: {
                pointPadding: 0,
                borderWidth: 0,
                pointRange: 24 * 3600 * 1000 // 单柱宽度占满1天,避免时间轴下列宽异常
            },
            series:{
                dataLabels:{
                    enabled:true,
                    formatter:function(){
                        return Highcharts.numberFormat(this.y)
                    }
                }
            }
        },
        rangeSelector: {
            buttons: [
                {type: 'week', count: 1, text: '1周'},
                {type: 'month', count: 1, text: '1月'},
                {type: 'all', text: '全部'}
            ],
            inputPosition: {
                align: 'right',
                x: 0,
                y: 0
            },
            selected: 2 // 默认加载全量数据,直接展示到当日
        },
        series: [{
            name: '日销售额',
            data: chart_data,
            tooltip: {
                valueDecimals: 0
            }
        }]
    });
}

修复后校验项
  • 接口返回的日期序列从最早有交易记录的自然日连续覆盖到当日,无销售的日期对应金额自动填充为0
  • X轴按自然日顺序显示日期标签,无错位、格式异常问题
  • 柱状图每列宽度匹配1天的时间跨度,无重叠、过窄问题
  • 图表默认加载即可展示到当日数据,当日无销售额时对应列显示0
  • 时间范围选择器可正常按周、月筛选数据,日期标签随缩放自动适配格式

内容的提问来源于stack exchange,提问作者Robinson Davis Villabon Trujil

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 00:45:31