php+ajax 实现无限树列表

首先介绍我实现的是xhprof插件的日志转为无限树状图,先看效果图:

废话不多说,直接看代码:(辛辛苦苦敲了好久才搞定,逻辑比较多,新手多揣摩)

控制器:

  1 <?php
  2 
  3 namespace Admin\Controller;
  4
  7 
  8 class XhprofController extends AdminbaseController
  9 { 10 function _initialize() 11  { 12 parent::_initialize(); 13  } 14 15 //获取当前文件目录 16 public function index() 17  { 18 $file = scandir("./public"); 19 $str = ".xhprof"; 20 foreach ($file as $value) { 21 if (preg_replace("/($str)/", "", $value) != $value) { 22 $dir[] = $value; 23  } 24  } 25 // $count = count($dir); 26 // $page = $this->page($count, 20); 27 // $this -> assign( "Page", $page->show( 'Admin' ) ); 28 $this->assign("dir", $dir); 29 $this->display(); 30  } 31 32 //获取适当的结构 33 public function tree($file_name) 34  { 35 $file_path = "./public/xhprof/$file_name"; 36 $file_name = str_replace('.', '', $file_name); 37 if (F($file_name)) { 38 $mainTree = F($file_name); 39 } else { 40 if (file_exists($file_path)) { 41 $fp = fopen($file_path, "r"); 42 $str = fread($fp, filesize($file_path));//指定读取大小,这里把整个文件内容读取出来 43 $array = json_decode($str, true); 44 $array_keys = array_keys($array); 45 //按照调用者整理数据 46 $calls = []; 47 foreach ($array_keys as $array_key) { 48 $caller = explode("==>", $array_key)[0]; 49 $beCall = explode("==>", $array_key)[1]; 50 if (!$calls[$caller]) { 51 $calls[$caller] = [ 52 "caller" => $caller, 53 "beCalls" => [] 54  ]; 55  } 56 $status = 0;//是否有子目录 57 foreach ($array_keys as $keyv) { 58 if (strpos($keyv, $beCall . '==>') !== false && strpos($keyv, "@") === false && $beCall !== null && $beCall !== "count") { 59 $status = 1; 60  } 61  } 62 if ($beCall !== null) { 63 $calls[$caller]['beCalls'][] = array('name' => $beCall, "status" => $status, 'data' => $array[$array_key]); 64  } 65  } 66 foreach ($calls as &$v) { 67 $tmpAll = 0; 68 foreach ($v['beCalls'] as $vv) { 69 $tmpAll += $vv['data']['wt']; 70  } 71 foreach ($v['beCalls'] as &$vv1) { 72 $vv1['data']['wtp'] = round($vv1['data']['wt'] * 100 / $tmpAll, 2); 73 $vv1['wtp'] = $vv1['data']['wt']; 74  } 75  } 76 $mainTree = $calls; 77 //缓存$mainTree 78 F($file_name, $mainTree); 79 } else { 80 $mainTree = ""; 81  } 82  } 83 array_multisort(array_column($mainTree["main()"]["beCalls"], "wtp"), SORT_DESC, array_column($mainTree["main()"]["beCalls"], "name"), SORT_DESC, $mainTree["main()"]["beCalls"]); 84 $this->assign("main", $array["main()"]); 85 $this->assign("mainTree", $mainTree["main()"]); 86 $this->assign("level", 1); 87 $this->assign("file_name", $file_name); 88 $this->assign("file_path", $file_path); 89 $this->display(); 90  } 91 92 public function ajax() 93  { 94 $note = htmlspecialchars_decode(I("post.note")); 95 $file_name = htmlspecialchars_decode(I("post.file_name")); 96 $file_path = htmlspecialchars_decode(I("post.file_path")); 97 //处理$mainTree 98 if (F($file_name)) { 99 $mainTree = F($file_name); 100 } else { 101 if (file_exists($file_path)) { 102 $fp = fopen($file_path, "r"); 103 $str = fread($fp, filesize($file_path));//指定读取大小,这里把整个文件内容读取出来 104 $array = json_decode($str, true); 105 $array_keys = array_keys($array); 106 //按照调用者整理数据 107 $calls = []; 108 foreach ($array_keys as $array_key) { 109 $caller = explode("==>", $array_key)[0]; 110 $beCall = explode("==>", $array_key)[1]; 111 if (!$calls[$caller]) { 112 $calls[$caller] = [ 113 "caller" => $caller, 114 "beCalls" => [] 115  ]; 116  } 117 $status = 0;//是否有子目录 118 foreach ($array_keys as $keyv) { 119 if (strpos($keyv, $beCall . '==>') !== false && strpos($keyv, "@") === false && $beCall !== null && $beCall !== "count") { 120 $status = 1; 121  } 122  } 123 if ($beCall !== null) { 124 $calls[$caller]['beCalls'][] = array('name' => $beCall, "status" => $status, 'data' => $array[$array_key]); 125  } 126  } 127 foreach ($calls as &$v) { 128 $tmpAll = 0; 129 foreach ($v['beCalls'] as $vv) { 130 $tmpAll += $vv['data']['wt']; 131  } 132 foreach ($v['beCalls'] as &$vv1) { 133 $vv1['data']['wtp'] = round($vv1['data']['wt'] * 100 / $tmpAll, 2); 134 $vv1['wtp'] = $vv1['data']['wt']; 135  } 136  } 137 $mainTree = $calls; 138 //缓存$mainTree 139 F($file_name, $mainTree); 140 } else { 141 $mainTree = ""; 142  } 143  } 144 array_multisort(array_column($mainTree[$note]["beCalls"], "wtp"), SORT_DESC, array_column($mainTree[$note]["beCalls"], "name"), SORT_DESC, $mainTree[$note]["beCalls"]); 145 $this->ajaxReturn($mainTree[$note]); 146  } 147 148 149 }

veiw界面:

 1 </head>
 2 <body>
 3 <div class="wrap">
 4     <ul class="nav nav-tabs">
 5         <li class="active"><a href="">{:L('ADMIN_XHPROF')}</a></li>
 6     </ul>
 7     <form method="post" class="js-ajax-form" action="{:U('AdminTerm/listorders')}">
 8         <table class="table table-hover table-bordered table-list">
 9             <thead>
10             <tr>
11                 <th width="2">ID</th>
12                 <th width="50">{:L('FILE_NAME')}</th>
13             </tr>
14             </thead>
15             <tbody>
16             <volist name="dir" id="vo" key="k">
17                 <tr>
18                     <th width="2">{$k}</th>
19                     <th width="50"><a href="{:U('admin/xhprof/tree',array('file_name'=>$vo))}">{$vo}</a></th>
20                 </tr>
21             </volist>
22             </tbody>
23             <tfoot>
24             <tr>
25                 <th width="2">ID</th>
26                 <th width="50">{:L('FILE_NAME')}</th>
27             </tr>
28             </tfoot>
29         </table>
30         <div class="pagination">{$Page}</div>
31     </form>
32 </div>
33 <script src="__PUBLIC__/js/common.js"></script>
34 </body>
35 </html>
View Code

 

  1 <html>
  2 <head>
  3     <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  4     <title>Xhprof数据分析</title>
  5     <link rel="stylesheet" type="text/css" href="__TMPL__Public/assets/css/bootstrap.min.css"/>
  6     <link rel="stylesheet" type="text/css" href="__TMPL__Public/assets/css/xhprof.css"/>
  7     <script type="text/javascript" src="__PUBLIC__/js/jquery.js"></script>
  8 </head>
  9 <body>
 10 <div class="tree well">
 11     <ul>
 12         <li>
 13             <span class="main">
 14                 <i class='icon-minus'> </i>  <b class="name">main()</b>
 15                             第<b>&nbsp;1&nbsp;</b>级&emsp;&emsp;&emsp;
 16                             ct:<b class="bw">{$main.ct}</b>
 17                             wt:<b class="red" >{$main.wt} (100%)</b>
 18                             cpu:<b class="bw">{$main.cpu}</b>
 19                             mu:<b class="bw">{$main.mu}</b>
 20                             pmu:<b class="bw">{$main.pmu}</b>
 21             </span>
 22             <foreach name="mainTree['beCalls']" item="vo">
 23                 <ul>
 24                     <li class='parent_li'>
 25                         <span title='Collapse this branch' note="{$vo.name}" level="2" file_name={$file_name} file_path={$file_path}>
 26                              <if condition="$vo['status']==1">
 27                                  <i class="icon-plus"></i>
 28                                  <else/>
 29                                  <b style='width:14px;display: inline-block;'></b>
 30                              </if>
 31                             <div style="display: inline-block;">
 32                              <b class="name" title={$vo.name}>{$vo.name}</b>
 33                              第<b>&nbsp;2&nbsp;</b>级&emsp;&emsp;&emsp;
 34                              ct:<b class="ct">{$vo.data.ct}</b>
 35                              <if condition="$vo['data']['wtp'] gt 10">
 36                                  wt:<b class="red">{$vo.data.wt} ({$vo.data.wtp|round=2}%)</b>
 37                                  <else/>
 38                                  wt:<b class="wt" style="display: inline-block;min-width: 150px;">{$vo.data.wt} ({$vo.data.wtp|round=2}%)</b>
 39                              </if>
 40                             cpu:<b class="bw">{$vo.data.cpu}</b>
 41                             mu:<b class="bw">{$vo.data.mu}</b>
 42                             pmu:<b class="bw">{$vo.data.pmu}</b>
 43                             </div>
 44                         </span>
 45                     </li>
 46                 </ul>
 47             </foreach>
 48         </li>
 49     </ul>
 50 </div>
 51 </body>
 52 <script>
 53     $(function () {
 54         $('.tree li:has(ul)').addClass('parent_li').find(' > span').attr('title', 'Collapse this branch');
 55         $('body').on('click', "span", function (e) {
 56             e.stopPropagation(); 57 if ($(this).attr('is_click') === 1) { 58 return false; 59  } 60 $(this).attr('is_click', 1); 61 var children = $(this).parent('li.parent_li').find(' > ul > li'); 62 if (children.is(":visible")) { 63 children.hide('fast'); 64 $(this).attr('title', 'Expand this branch').find(' > i').addClass('icon-plus').removeClass('icon-minus'); 65 $(this).attr('is_click', 0); 66 } else { 67 children.show('fast'); 68 $(this).attr('title', 'Collapse this branch').find(' > i').addClass('icon-minus').removeClass('icon-plus'); 69 if ($(this).hasClass('main')) { 70 $(this).attr('is_click', 0); 71 return; 72  } 73 if (!$(this).siblings('.child').length) { 74  do_ajax($(this)); 75 } else { 76 $(this).attr('is_click', 0); 77  } 78  } 79  }); 80 81 function do_ajax(e) { 82 var note_js = e.attr('note'); 83 var level_js = e.attr('level'); 84 var file_name_js = e.attr('file_name'); 85 var file_path_js = e.attr('file_path'); 86 $.ajax({ 87 type: "post", 88 cache: false, 89 dataType: "json", 90 url: "{:U('Admin/Xhprof/ajax')}", 91 data: { 92 note: note_js, 93 level: level_js, 94 file_name: file_name_js, 95 file_path: file_path_js 96 }, 97 success: function (data) { 98 if (data.beCalls !== null) { 99 var str = ""; 100 for (var i = 0; i < data.beCalls.length; i++) { 101 str += "<ul class='child'>"; 102 str += "<li class='parent_li'>"; 103 str += "<span title='Collapse this branch' class='load' note=" + data.beCalls[i].name + " level= " + eval(Number(level_js) + 1) + " file_name= " + file_name_js + " file_path= " + file_path_js + ">"; 104 if (data.beCalls[i].status == 1) { 105 str += "<i class='icon-plus' ></i>"; 106 } else { 107 str += "<b style='width:14px;display: inline-block;'> </b>"; 108  } 109 str += "<b class='name' title="+ data.beCalls[i].name + ">" + data.beCalls[i].name + '</b>第<b>&nbsp;' + eval(Number(level_js) + 1) + "</b>&nbsp;级&emsp;&emsp;&emsp;ct:<b class='ct'>" + data.beCalls[i].data.ct + "</b> wt:<b class= " + (data.beCalls[i].data.wtp < 10 ? 'wt' : 'red') + " >" + data.beCalls[i].data.wt + "(" + data.beCalls[i].data.wtp + "%)</b> cpu:<b class='bw' >" + data.beCalls[i].data.cpu + "</b> mu:<b class='bw'>" + data.beCalls[i].data.mu + "</b> pmu:<b class='bw'>" + data.beCalls[i].data.pmu + "</b></span>"; 110 str += '</li>'; 111 str += '</ul>'; 112  } 113 e.siblings('.child').remove(); 114 e.after(str); 115 e.attr('is_click', 0); 116  } 117 }, 118 error: function () { 119  } 120  }) 121  } 122  }); 123 </script> 124 </html>

转载于:https://www.cnblogs.com/joker-one/p/10137883.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值