一,業務場景
該項目是一個大數據報表系統,使用php的Yii框架結合smarty,主要的業務報表分為兩種,一種是iframe嵌入的外鏈報表,還有項目自己的報表。
為了查看方便,項目增加了收藏和最近訪問報表菜單欄,
收藏菜單欄:根據後端$collet返回的數據遍歷生成二級菜單,並根據$menu_id,$url_tpl,$isWhiteTable控制class中是否添加open從而控制一級菜單欄的展開收起;通過$url_tpl中是否有“visual”控制箭頭的朝向;通過$coll.id eq $id是否相等添加選中菜單高亮active
<li class='submenu {/if $menu_id eq 0 && $url_tpl eq '' && $isWhiteTable !== 1 /}open{//if/}'>
<a href="#" class="{/if $menu_id eq 0/}
{/if $url_tpl eq 'visual'/}
iconfont icon-shousuojiahao
{/else/}
iconfont icon-shousuojianhao
{//if/}
{/else/}
iconfont icon-shousuojiahao
{//if/}">
<span style='font-weight:bolder'>收藏</span>
</a>
<!--收藏子菜單-->
{/if $collect|@count neq 0 /}
<ul>
{/foreach from = $collect item= coll key=key/}
<li {/if $coll.id eq $id /} class='active' {/$second_menu = $coll.name/}{//if/}>
<a href="/visual/index/{/$coll.id/}">{/$coll.name/}</a>
</li>
{//foreach/}
</ul>
{//if/}
</li>
最近訪問菜單欄:由於最近訪問菜單需要在點擊時展開並實時獲取,所以通過整個頁面刷新從後端拿接口這種方式體驗不好,不予採取,於是設計需求為點擊最近訪問列表菜單通過ajax調取接口異步獲取最新數據動態渲染出菜單
<!--最近訪問報表菜單-->
<li class='submenu history' id="history">
<a class="d_first_menu a_history">
<i class="icon-angle-right h-right" style="float: right;margin-top: 15px;margin-right: 20px !important"></i>
<i class="icon-angle-down h-down" style="float: right;margin-top: 15px;margin-right: 20px !important;display:none"></i>
<i class="icon-time"></i>
<span>最近訪問報表</span>
</a>
</li>
<!--最近訪問子菜單-->
<ul class="d_secoed_menu d_history" style="width: 200px!important;padding: 0px 0px;">
</ul>
動態生成菜單js代碼
var flag = true;
$('#history').on('click',function(e){
var $this = $(this);
if(flag && ($(".h-right").css('display') == 'block')){
flag = false;
//防止多次點擊發請求
setTimeout(() => {
$.ajax({
type: 'get',
url: '/visual/gethistory',
success: function(d){
var data = d.data;
var html = "";
for(var i=0; i < data.length; i++){
html +="<li><a class='history_"+data[i].id+"' href='/visual/index/"+data[i].id+"?history="+data[i].id+"'>"+data[i].name+"</a></li>";
}
$('.d_history').empty();
$('.d_history').append(html);
$('.d_history').show();
$('.h-right').hide();
$('.h-down').show();
toolTip();
flag = true;
},
error:function(e){
console.log("e",e)
},
dataType: 'json'
});
}, 500);
}
if(flag && ($(".h-down").css('display') == 'block')){
$('.d_history').hide();
$('.h-right').show();
$('.h-down').hide();
}
})
這時候基本實現了功能,但是出現了一個問題,當收藏菜單下的報表和最近訪問報表下是同一個報表時,他們瀏覽器中對應的url是相同的,導致當點擊最近訪問報表下的同一報表時,瀏覽器刷新,重新通過$url_tpl中是否有“visual”控制箭頭的朝向;通過$coll.id eq $id是否相等添加選中菜單高亮active,這時就會鎖定收藏菜單下的同一報表。
二,提出方案
所以點擊時就需要對收藏菜單和最近訪問歷史下的報表做區分,每次點擊不同菜單下的報表都要記錄是收藏的還是最近訪問的,有兩種解決方案,一種是後端返回數據時給收藏或歷史訪問返回一個特殊字段,每次點擊對應菜單下的報表要通過特殊字段做區分,但是需要後端同學配合,後端修改時間成本較大,另一種是在前端點擊菜單報表時做標記,即要區分是收藏還是最近訪問歷史下的報表,還要記錄點擊的是哪個報表,頁面刷新的時候需要根據上次點擊的報表做選中高亮。
三,前端解決方案實踐
1.點擊最近訪問列表做標記需要把標記,將標記加入a標籤的href中
href中加一個參數history(帶history的是最近訪問列表,對收藏列表做區分),class加一個記錄報表id的類(為了頁面刷新選中高亮li)
for(var i=0; i < data.length; i++){
html +="<li><a class='history_"+data[i].id+"' href='/visual/index/"+data[i].id+"?history="+data[i].id+"'>"+data[i].name+"</a></li>";
}
點擊最近訪問報表裏的報表(等同於頁面刷新)時執行以下js代碼:
解決了最近訪問報表的所有問題
//刷新時判斷是否是最近訪問列表裏的報表
var urlS = window.location.search;
var value = urlS.split('=')[1]
if(urlS.indexOf('history') >= 0){
$.ajax({
type: 'get',
url: '/visual/gethistory',
success: function(d){
var data = d.data;
var html = "";
for(var i=0; i < data.length; i++){
html +="<li><a class='history_"+data[i].id+"' href='/visual/index/"+data[i].id+"?history="+data[i].id+"'>"+data[i].name+"</a></li>";
}
$('.d_history').empty();
$('.d_history').append(html);
$('.d_history').show();
$('.history_'+value).attr({'style':'color:#FFFFFF !important'});
toolTip();
},
error:function(e){
console.log("e",e)
},
dataType: 'json'
});
}
2.解決收藏列表展開收起及選中報表高亮問題
只需要在頁面加載時獲取到url中是否有history做判斷,如果沒有説明是收藏菜單欄下的報表,首先需要用php的方式獲取url,然後用php語法做判斷即可,主要是這句代碼,
$smarty.server.REQUEST_URI|strpos:'history',在控制展開收起和報表選中高亮的部分加入判斷即可
<!--收藏-->
<li class='submenu {/if $menu_id eq 0 && $url_tpl eq '' && ($smarty.server.REQUEST_URI|strpos:'history' lte 1) && $isWhiteTable !== 1/}open{//if/}'>
<a href="#" class="d_first_menu">
{/if $menu_id eq 0/}
{/if $smarty.server.REQUEST_URI|strpos:'history' lte 1 /}
<i class="icon-angle-down show"></i>
{/else/}
<i class='icon-angle-right show'></i>
{//if/}
{/else/}
<i class="icon-angle-right show"></i>
{//if/}
<i class="icon-heart"></i>
<span>收藏</span>
</a>
<!--收藏子菜單-->
{/if $collect|@count neq 0 || $isCollectCustom|@count neq 0/}
<ul class="d_secoed_menu">
{/foreach from = $collect item= coll key=key/}
<li
{/if $coll.id eq $id && ($smarty.server.REQUEST_URI|strpos:'history' lte 1)/}
class='active'
{/$first_menu = "收藏"/}
{/$second_menu = $coll.name/}
{//if/}
>
<a href="/visual/index/{/$coll.id/}">{/$coll.name/}</a>
</li>
{//foreach/}
</ul>
{//if/}
</li>