CodeIgniter中Highcharts分支筛选失效,图表空白求助
问题排查与修复
核心错误点
Controller层缺失关键接口与数据传递
- index方法未将
$data['branch_list']传递给视图,导致下拉框无法渲染分支选项 - 未实现AJAX调用的
branch_data接口方法,前端请求无响应 - 原有
data方法调用Model的get_data时未传参,而修改后的get_data需要分支参数,引发报错
- index方法未将
Model层参数处理不当
get_data方法强制要求$branch参数,但原有调用场景(加载全部分支数据)无参数传入,导致执行失败- 未做分支参数的空值判断,无法兼容全部分支查询的场景
View层JS语法错误与功能缺失
load_branchwise_data函数参数定义错误,缺少逗号分隔参数- AJAX请求的语法完全混乱:
url:od:"POST"、data"..."、meth:{...}都是无效写法 - 缺少
drawBranchWiseChart函数,无法接收后端数据并渲染图表 - 初始图表加载后未处理旧实例,切换分支时可能导致DOM冲突
修正后的完整代码
1. Controller(Chart.php)
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); class Chart extends CI_Controller { public function __construct() { parent::__construct(); $this->load->model('data'); } public function index() { $data['branch_list'] = $this->data->getBranch(); // 必须将$data传递给视图,否则分支列表无法渲染 $this->load->view('chart', $data); } // 原有全部分支数据接口,兼容无参数场景 public function data() { // 传null表示查询全部分支 $data = $this->data->get_data(null); $category = array(); $category['name'] = 'Branch'; $series1 = array(); $series1['name'] = 'Issued Quantity'; foreach ($data as $row) { $category['data'][] = $row->branch; $series1['data'][] = $row->issued_qty; } $result = array(); array_push($result,$category); array_push($result,$series1); print json_encode($result, JSON_NUMERIC_CHECK); } // 新增分支筛选数据接口 public function branch_data() { if ($this->input->post('branch')) { $branch = $this->input->post('branch'); $data = $this->data->get_data($branch); $category = array(); $category['name'] = 'Item'; // 筛选单分支时,X轴显示物品名称更合理 $series1 = array(); $series1['name'] = 'Issued Quantity'; foreach ($data as $row) { $category['data'][] = $row->item; $series1['data'][] = $row->issued_qty; } $result = array(); array_push($result,$category); array_push($result,$series1); print json_encode($result, JSON_NUMERIC_CHECK); } else { echo json_encode(array()); } } }
2. Model(Data.php)
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); class Data extends CI_Model { function __construct() { parent::__construct(); } // 给$branch参数设置默认值,兼容全部分支查询 function get_data($branch = null) { $this->db->select('sur.update_stock_id, sus.branch_id, sus.request_no, sus.billed_date, store_branch.branch_name AS branch, si.item_id, si.item_name AS item, tf.avqty, sur.r_qty as r_qty, sur.ap_qty as ap_qty, tf1.issued_qty'); $this->db->from('store_update_request sur'); $this->db->join('store_update_stock sus', 'sus.update_stock_id=sur.update_stock_id', 'left'); $this->db->join('store_branch', 'sus.branch_id=store_branch.branch_id', 'left'); $this->db->join('store_item si', 'sur.item=si.item_id', 'left'); $this->db->join('(select update_stock_id, item, is_qty AS issued_qty from store_update_issue where store_update_issue.status=1 ) AS tf1', 'si.item_id=tf1.item AND sur.update_stock_id = tf1.update_stock_id','left' ); $this->db->join('(select item, sum(qty) AS avqty from store_update_stock_details where store_update_stock_details.status=1 group by item) AS tf', 'si.item_id=tf.item', 'left'); $this->db->where('sus.status', 1); // 仅当$branch不为空时,添加分支筛选条件 if ($branch !== null) { $this->db->where('store_branch.branch_id', $branch); } $query = $this->db->get(); if ($query->num_rows() > 0) { return $query->result(); } return array(); // 返回空数组而非false,避免foreach报错 } function getBranch() { $this->db->select('branch_id, branch_name'); $this->db->from('store_branch'); $this->db->order_by('branch_id', 'ASC'); return $this->db->get(); } }
3. View(chart.php)
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script> <script type='text/javascript' src='<?php echo base_url(); ?>assets/js/highcharts.js'></script> <script type='text/javascript' src='<?php echo base_url(); ?>assets/js/exporting.js'></script> <!-- 分支筛选下拉框 --> <div class="row"> <div class="col-md-6"> <div class="col-md-3"> <select name="branch" id="branch" class="form-control"> <option value="">Select Branch</option> <?php foreach ($branch_list->result_array() as $row) { echo '<option value="' . $row["branch_id"] . '">' . $row["branch_name"] . '</option>'; } ?> </select> </div> </div> </div> <a href="<?= site_url('welcome') ?>"> <input type="button" class="btn btn-warning" value="Back to Home"></a> <div id="container" style="min-width: 400px; height: 400px; margin: 0 auto;"></div> <script type="text/javascript"> var chart; // 全局存储图表实例,方便后续更新或销毁 $(document).ready(function() { // 初始化加载全部分支图表 load_initial_chart(); // 分支选择事件 $('#branch').change(function(){ var branch = $(this).val(); if(branch != '') { load_branchwise_data(branch, 'Item Issuing Summary - '); } else { // 选择"Select Branch"时重新加载全部分支图表 load_initial_chart(); } }); }); // 加载初始全部分支图表 function load_initial_chart() { var options = { chart: { renderTo: 'container', type: 'line', marginRight: 130, marginBottom: 25 }, title: { text: 'Stationary / Consumables Issuing Status', x: -20 //center }, subtitle: { text: '', x: -20 }, xAxis: { categories: [] }, yAxis: { title: { text: 'Qty' }, plotLines: [{ value: 0, width: 1, color: '#808080' }] }, tooltip: { formatter: function() { return '<b>' + this.series.name + '</b><br/>' + this.x + ': ' + this.y; } }, legend: { layout: 'vertical', align: 'right', verticalAlign: 'top', x: -10, y: 100, borderWidth: 0 }, series: [] }; $.getJSON("<?= site_url('chart/data') ?>", function(json) { options.xAxis.categories = json[0]['data']; options.series[0] = json[1]; // 销毁旧图表实例(如果存在) if (chart) { chart.destroy(); } chart = new Highcharts.Chart(options); }); } // 加载指定分支的图表数据 function load_branchwise_data(branch, title) { var temp_title = title + branch; $.ajax({ url: "<?= site_url('chart/branch_data') ?>", method: "POST", data: {branch: branch}, dataType: "JSON", success:function(data) { drawBranchWiseChart(data, temp_title); }, error: function() { alert('加载数据失败,请重试'); } }); } // 渲染分支专属图表 function drawBranchWiseChart(data, chartTitle) { var options = { chart: { renderTo: 'container', type: 'line', marginRight: 130, marginBottom: 25 }, title: { text: chartTitle, x: -20 //center }, subtitle: { text: '', x: -20 }, xAxis: { categories: data[0] ? data[0]['data'] : [] }, yAxis: { title: { text: 'Qty' }, plotLines: [{ value: 0, width: 1, color: '#808080' }] }, tooltip: { formatter: function() { return '<b>' + this.series.name + '</b><br/>' + this.x + ': ' + this.y; } }, legend: { layout: 'vertical', align: 'right', verticalAlign: 'top', x: -10, y: 100, borderWidth: 0 }, series: data[1] ? [data[1]] : [] }; // 销毁旧图表实例 if (chart) { chart.destroy(); } chart = new Highcharts.Chart(options); } </script>
额外说明
- 筛选单分支时,X轴从"分支名称"改为"物品名称",更符合业务逻辑(单分支下展示各物品的发放量)
- 增加了AJAX错误处理,方便排查请求失败问题
- 全局维护
chart实例,避免重复创建图表导致的DOM冲突 - Model的
get_data方法返回空数组而非false,避免前端foreach循环报错
内容的提问来源于stack exchange,提问作者mcode
相关产品推荐
相关产品推荐

