一,业务场景
该项目是一个大数据报表系统,使用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>