修改导航,支持多级子菜单展示

This commit is contained in:
hdm 2022-06-02 22:36:50 +08:00
parent 338eaf66e2
commit ed83cffe3e
8 changed files with 321 additions and 61 deletions

1
.gitignore vendored
View File

@ -8,3 +8,4 @@
/runtime/*
/public/storage/*
/public/backup/*
/public/static/home/dev

View File

@ -64,32 +64,6 @@ function format_bytes($size, $delimiter = '')
return round($size, 2) . $delimiter . $units[$i];
}
function list_to_tree($list, $pk = 'id', $pid = 'pid', $child = 'list', $root = 0)
{
// 创建Tree
$tree = array();
if (is_array($list)) {
// 创建基于主键的数组引用
$refer = array();
foreach ($list as $key => $data) {
$refer[$data[$pk]] = &$list[$key];
}
foreach ($list as $key => $data) {
// 判断是否存在parent
$parentId = $data[$pid];
if ($root == $parentId) {
$tree[$data[$pk]] = &$list[$key];
} else {
if (isset($refer[$parentId])) {
$parent = &$refer[$parentId];
$parent[$child][$data[$pk]] = &$list[$key];
}
}
}
}
return $tree;
}
function create_tree_list($pid, $arr, $group, &$tree = [])
{
foreach ($arr as $key => $vo) {

View File

@ -172,6 +172,32 @@ function table_assign($code = 0, $msg = '请求成功', $data = [], $httpCode =
throw new \think\exception\HttpResponseException($response);
}
//菜单转为父子菜单
function list_to_tree($list, $pk = 'id', $pid = 'pid', $child = 'list', $root = 0)
{
// 创建Tree
$tree = array();
if (is_array($list)) {
// 创建基于主键的数组引用
$refer = array();
foreach ($list as $key => $data) {
$refer[$data[$pk]] = &$list[$key];
}
foreach ($list as $key => $data) {
// 判断是否存在parent
$parentId = $data[$pid];
if ($root == $parentId) {
$tree[$data[$pk]] = &$list[$key];
} else {
if (isset($refer[$parentId])) {
$parent = &$refer[$parentId];
$parent[$child][$data[$pk]] = &$list[$key];
}
}
}
}
return $tree;
}
/**
* 时间戳格式化
* @param int $time

View File

@ -67,11 +67,9 @@ abstract class BaseController
'mobile_status' => 0,
'version' => get_config('webconfig.version'),
];
$login_class = "nav-login";
$login_top = '<a id="topLogin" class="nav-a" href="/home/login/index"><span class="login-span">登录</span></a><a class="nav-a" href="/home/login/reg"><span class="reg-span">注册</span></a>';
$login_top = '';
$info = $this->checkLogin();
if ($info) {
$login_class = 'nav-login nav-logined';
$login_top = '<a class="nav-img" href="/home/user/index"><img src="' . $info['headimgurl'] . '" alt="' . $info['username'] . '" />' . $info['username'] . '</a>';
$params['isLogin'] = 1;
$params['uid'] = $info['id'];
@ -82,7 +80,6 @@ abstract class BaseController
View::assign('COMMON_NAV', $COMMON_NAV);
View::assign('webconfig', get_config('webconfig'));
View::assign('params', $params);
View::assign('login_class', $login_class);
View::assign('login_top', $login_top);
}
// 检测用户登录状态

View File

@ -15,8 +15,9 @@ function get_navs($name)
if (empty($nav_id)) {
return '';
}
$list = \think\facade\Db::name('NavInfo')->where(['nav_id' => $nav_id, 'status' => 1])->order('sort asc')->select();
\think\facade\Cache::tag('homeNav')->set('homeNav' . $name, $list);
$list = \think\facade\Db::name('NavInfo')->where(['nav_id' => $nav_id, 'status' => 1])->order('sort asc')->select()->toArray();
$nav = list_to_tree($list);
\think\facade\Cache::tag('homeNav')->set('homeNav' . $name, $nav);
}
$navs = get_cache('homeNav' . $name);
return $navs;

View File

@ -1,14 +1,49 @@
<div class="nav">
<header class="header">
<div class="nav-box">
<div class="l nav-logo">
<a href="/"><img src="{__IMG__}/logo.png" height="60" alt="勾股BI" /></a>
<a href="/"><img src="{__IMG__}/logo.png" height="60" alt="勾股CMS" /></a>
</div>
<div class="r nav-menu">
<div class="r navbar">
<ul>
{volist name="COMMON_NAV" id="vo"}
<li {if condition="strpos($vo.param,$params.action) nheq false"}class="on"{/if}><a class="nav-a" href="{$vo.src}" {eq name="vo.target" value="1"} target="_blank"{/eq}>{$vo.title}</a></li>
{/volist}
<li class="{$login_class}">
{foreach name="COMMON_NAV" item="a"}
{empty name="$a.list"}
<li {if condition="strpos($a.param,$params.action) nheq false"}class="active"{/if}>
<a href="{$a.src==''?'javascript:;':$a.src}" {eq name="a.target" value="1"} target="_blank"{/eq}>{$a.title}</a>
</li>
{else/}
<li class="dropdown">
<a href="{$a.src==''?'javascript:;':$a.src}" {eq name="a.target" value="1"} target="_blank"{/eq}>{$a.title}<i class="bi bi-chevron-down"></i></a>
<ul>
{foreach name="$a.list" item="b"}
<li {notempty name="$b.list"} class="dropdown" {/notempty}>
<a href="{$b.src==''?'javascript:;':$b.src}" {eq name="b.target" value="1"} target="_blank"{/eq}>{$b.title}{notempty name="$b.list"}<i class="bi bi-chevron-down"></i>{/notempty}</a>
{notempty name="$b.list"}
<ul>
{foreach name="$b.list" item="c"}
<li <li {notempty name="$c.list"} class="dropdown" {/notempty}>
<a href="{$b.src==''?'javascript:;':$b.src}" {eq name="b.target" value="1"} target="_blank"{/eq}>{$b.title}{notempty name="$c.list"}<i class="bi bi-chevron-down"></i>{/notempty}</a>
{notempty name="$c.list"}
<ul>
{foreach name="$c.list" item="d"}
<li><a href="{$d.src==''?'javascript:;':$d.src}" {eq name="d.target" value="1"} target="_blank"{/eq}>{$d.title}</a></li>
{/foreach}
</ul>
{/notempty}
</li>
{/foreach}
</ul>
{/notempty}
</li>
{/foreach}
</ul>
</li>
{/empty}
{/foreach}
{empty name="$login_top"}
<li><a class="login-btn scrollto" href="/home/login/index">登录</a></li>
<li><a class="reg-btn scrollto" href="/home/login/reg">注册</a></li>
{else/}
<li class="nav-logined">
{:htmlspecialchars_decode($login_top)}
<div class="nav-login-box">
<div class="login-menu">
@ -20,6 +55,7 @@
</div>
</div>
</li>
{/empty}
</ul>
</div>
</div>
@ -40,4 +76,4 @@
})
})
</script>
</div>
</header>

View File

@ -0,0 +1,209 @@
{extend name="common/base"/}
{block name="style"}
<link rel="stylesheet" href="https://www.gougucms.com/static/home/dev/aos.css" />
<link rel="stylesheet" href="https://www.gougucms.com/static/home/dev/dev.css" />
{/block}
{block name="title"}
<title>{$detail.title}</title>
{/block}
{block name="keywords"}
<meta name="keywords" content="{$detail.keyword_names}" />
<meta name="description" content="{$detail.desc}" />
{/block}
<!-- 主体 -->
{block name="body"}
{include file="common/header" nav='index' /}
<section class="banner">
<div class="container">
<div class="banner-text">
<h1 data-aos="fade-up">项目研发管理工具</h1>
<h2 data-aos="fade-up" data-aos-delay="400">让项目管理变得简单,实现『研发+管理』全面提升</h2>
<div data-aos="fade-up" data-aos-delay="800">
<a href="https://gitee.com/gougucms/dev.git" class="btn-down" target="_blank"><span>立即下载(Gitee)</span></a>
<a href="https://dev.gougucms.com/" class="btn-go" target="_blank"><span>体验演示</span></a>
<span class="btn-view">查看体验账号</span>
</div>
</div>
<div class="banner-img" data-aos="zoom-out" data-aos-delay="300">
<img src="https://www.gougucms.com/static/home/dev/banner_bg.png" alt="">
</div>
</div>
</div>
</section>
<section class="advantage">
<div class="container" data-aos="fade-up">
<header class="section-header">
<h2>适合各行业软件开发团队</h2>
<p>在线管理团队的工作、项目和任务,覆盖从需求提出到研发完成上线的研发管理全生命周期</p>
</header>
<div class="item-wrap">
<div class="item-col-4">
<div class="box" data-aos="fade-up" data-aos-delay="200">
<img src="https://www.gougucms.com/static/home/dev/p1.png" class="img-fluid" alt="">
<h3>协同</h3>
<p>日程 / 日报 / 项目 / 任务</p>
</div>
</div>
<div class="item-col-4">
<div class="box" data-aos="fade-up" data-aos-delay="400">
<img src="https://www.gougucms.com/static/home/dev/p2.png" class="img-fluid" alt="">
<h3>项目</h3>
<p>需求 / 设计 / 研发 / 测试 </p>
</div>
</div>
<div class="item-col-4">
<div class="box" data-aos="fade-up" data-aos-delay="600">
<img src="https://www.gougucms.com/static/home/dev/p3.png" class="img-fluid" alt="">
<h3>工时</h3>
<p>进度 / 成本 / 绩效 / 质量</p>
</div>
</div>
<div class="item-col-4">
<div class="box" data-aos="fade-up" data-aos-delay="800">
<img src="https://www.gougucms.com/static/home/dev/p4.png" class="img-fluid" alt="">
<h3>知识库</h3>
<p>文档 / 经验 / 规范 / 分享</p>
</div>
</div>
</div>
</div>
</section>
<section class="step">
<div class="container" data-aos="fade-up">
<div class="item-wrap">
<div class="item-col-6">
<div class="step-box">
<i class="bi bi-file-text"></i>
<div>
<span>10%</span>
<p>需求分析</p>
</div>
</div>
</div>
<div class="item-col-6">
<div class="step-box">
<i class="bi bi-file-medical" style="color: #ee6c20;"></i>
<div>
<span style="color: #ee6c20;">20%</span>
<p>产品策划</p>
</div>
</div>
</div>
<div class="item-col-6">
<div class="step-box">
<i class="bi bi-file-richtext" style="color: #52CD75;"></i>
<div>
<span style="color: #52CD75;">60%</span>
<p>UI设计</p>
</div>
</div>
</div>
<div class="item-col-6">
<div class="step-box">
<i class="bi bi-file-code" style="color: #EA4335;"></i>
<div>
<span style="color: #EA4335;">60%</span>
<p>项目研发</p>
</div>
</div>
</div>
<div class="item-col-6">
<div class="step-box">
<i class="bi bi-file-ruled" style="color: #9B74D7;"></i>
<div>
<span style="color: #9B74D7;">95%</span>
<p>测试运维</p>
</div>
</div>
</div>
<div class="item-col-6">
<div class="step-box">
<i class="bi bi-file-check" style="color: #f51f9c;"></i>
<div>
<span style="color: #f51f9c;">95%</span>
<p>成功上线</p>
</div>
</div>
</div>
</div>
</div>
</section>
<section class="services">
<div class="container" data-aos="fade-down">
<header class="section-header">
<h2>六大功能模块</h2>
<p>改进项目管理模式 提升团队的研发效率,低成本、全流程、快速定制,属于您团队的研发协同工具</p>
</header>
<div class="item-wrap">
<div class="item-col-3" data-aos="fade-up" data-aos-delay="200">
<div class="service-box blue">
<i class="bi bi-grid-1x2-fill"></i>
<h3>产品</h3>
<p>支持多产品路线,把控进度,协调团队资源</p>
</div>
</div>
<div class="item-col-3" data-aos="fade-up" data-aos-delay="300">
<div class="service-box orange">
<i class="bi bi-box2-fill"></i>
<h3>项目</h3>
<p>项目操作记录全覆盖跟踪,项目进度一目了然</p>
</div>
</div>
<div class="item-col-3" data-aos="fade-up" data-aos-delay="400">
<div class="service-box green">
<i class="bi bi-map-fill"></i>
<h3>任务</h3>
<p>时间跟踪机制,多状态流转,任务成果可见可控</p>
</div>
</div>
<div class="item-col-3" data-aos="fade-up" data-aos-delay="500">
<div class="service-box red">
<i class="bi bi-calendar-check-fill"></i>
<h3>工时</h3>
<p>日报周报,工时登记,团队工作精细化管理</p>
</div>
</div>
<div class="item-col-3" data-aos="fade-up" data-aos-delay="600">
<div class="service-box purple">
<i class="bi bi-terminal-fill"></i>
<h3>测试</h3>
<p>编写测试用例库BUG记录、跟踪和管理</p>
</div>
</div>
<div class="item-col-3" data-aos="fade-up" data-aos-delay="700">
<div class="service-box pink">
<i class="bi bi-collection-fill"></i>
<h3>知识库</h3>
<p>技术文档、开发经验、规则规范、支持多人分享</p>
</div>
</div>
</div>
</div>
</section>
{/block}
{block name="script"}
<script src="https://www.gougucms.com/static/home/dev/aos.js"></script>
<script src="https://www.gougucms.com/static/home/js/layer/layer.js"></script>
<script>
AOS.init({
easing: 'ease-in-out-sine'
});
$('.btn-view').on('click',function(){
layer.open({
'title':'体验账号',
'content':'技术总监gougujishu&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;123456<br> 工 程 师 ligong&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;123456<br>产品经理ouyangchanpin&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;123456'
});
})
</script>
{/block}
</body>
</html>

View File

@ -1,3 +1,4 @@
@import url("../../assets/icon/bootstrap-icons.css");
/*reset*/
body {margin:0; padding:0; font-size:12px ; color:#323232; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji","Microsoft YaHei",tahoma,arial,"\5B8B\4F53"; font-weight:normal!important; background-color: #F5F5F5;}
div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,textarea,blockquote,p{padding:0; margin:0;}
@ -9,6 +10,7 @@ h1,h2,h3,h4,h5,h6 {font-size:14px;}
address,code,em,th,s,i{font-weight:normal; font-style:normal;}
s{color:#909090; margin:0 10px; text-decoration:none;}
body.right-open{overflow-y:clip;}
.img-fluid{max-width: 100%;height: auto;}
/*form*/
label input{vertical-align:middle; margin-right:3px;}
label{cursor:pointer;}
@ -73,39 +75,53 @@ a:active {color:#4385F5;}
.text-overflow-5{-webkit-line-clamp: 4;}
/*----------------导航-----------------*/
.nav{width:100%; height:60px;position: fixed; left:0; top:0; z-index: 999; box-shadow: 0 5px 8px 0 rgba(0,0,0,.1); background: rgba(255,255,255,.95);}
.nav-box{width:1226px; margin:0 auto;}
.header{width:100%; height:60px;position: fixed; left:0; top:0; z-index: 996; box-shadow: 0 5px 8px 0 rgba(0,0,0,.1); background: rgba(255,255,255,.95);transition: all 0.5s;}
.nav-box{width:1226px; height:60px; margin:0 auto;}
.nav-logo{width:180px; height:60px;}
.nav-logo a{width:180px; height:60px; display:block;}
.nav-menu{font-size:16px;}
.nav-menu li{height:60px; float:left; color:#fff; padding: 0 16px;}
.nav-menu li a.nav-a{height:60px; position: relative; min-width:36px; text-align:center; line-height:60px; padding:0 3px; display:inline-block; color:#323232;transition: all 0.6s ;}
.nav-menu li a.nav-a:hover{color:#186AF2; transition: all 0.6s;}
.nav-menu li.on a.nav-a{color:#186AF2}
.navbar {padding: 9px 0; height:42px;}
.navbar ul {display: flex; list-style: none; align-items: center;}
.navbar li { position: relative;}
.navbar a { display: flex; align-items: center; justify-content: space-between; padding: 10px 24px; font-size: 16px; color:#323232; font-weight: 400; white-space: nowrap; transition: 0.3s;}
.navbar a i {font-size: 12px; line-height: 0; margin-left: 4px;}
.navbar a:hover, .navbar .active, .navbar li:hover > a { color: #186AF2;}
.navbar .login-btn {padding: 4px 12px; margin-left: 20px; border-radius: 3px; font-size: 14px; background-color:#186AF2; color:#fff}
.navbar .login-btn:hover {opacity:0.72; color:#fff}
.navbar .reg-btn {padding: 4px 12px; margin-left: 20px; border-radius: 3px; font-size: 14px; background-color:#EA4335; color:#fff}
.navbar .reg-btn:hover {opacity:0.72; color:#fff}
.navbar .dropdown ul { display: block; position: absolute; left: 14px; top: calc(100% + 30px); margin: 0; padding: 10px 0; z-index: 99; opacity: 0; visibility: hidden; background: #fff; box-shadow: 0px 0px 30px rgba(127, 137, 161, 0.25); transition: 0.3s; border-radius: 3px;}
.navbar .dropdown ul li {min-width: 200px;}
.navbar .dropdown ul a {padding: 8px 20px; font-size: 14px; text-transform: none; font-weight: 400;}
.navbar .dropdown ul a i { font-size: 12px;}
.navbar .dropdown ul a:hover, .navbar .dropdown ul .active:hover, .navbar .dropdown ul li:hover > a { color: #186AF2;}
.navbar .dropdown:hover > ul { opacity: 1; top: 100%; visibility: visible;}
.navbar .dropdown .dropdown ul { top: 0;left: calc(100% - 30px); visibility: hidden;}
.navbar .dropdown .dropdown:hover > ul { opacity: 1; top: 0; left: 100%; visibility: visible;}
.nav-menu li.nav-login{position:relative; padding-left:20px; padding-right: 0;}
.nav-menu li.nav-login a.nav-a{padding:0 2px; margin-left:5px}
.nav-menu li.nav-login span{padding:5px 16px 6px; border-radius:3px; font-size:14px; background-color:#186AF2; color:#fff}
.nav-menu li.nav-login span.reg-span{background-color:#EA4335;}
.nav-menu li a.nav-a:hover{color:#186AF2; transition: all 0.6s;}
.nav-menu li.on a.nav-a{color:#186AF2}
.nav-menu li.nav-login a:hover span{opacity:0.8;transition: all 0.5s;}
.nav-menu li.on a.nav-a:after { position: absolute; bottom: -1px; left: 0; content: ''; height: 3px; width: 100%; background-color: #186AF2;}
.nav-login-box{width:320px; border-radius:2px; position:absolute; top:60px; right:0; background-color:#fff; z-index:-1; color:#333; font-size:14px;-webkit-transform:scale(0.5);transform:scale(0.5);-webkit-transition:.2s;transition:.2s;opacity:0;-webkit-transform-origin:center top;transform-origin:center top;-webkit-box-shadow:0 15px 30px rgba(0,0,0,.2);box-shadow:0 15px 30px rgba(0,0,0,.2);}
.login-note{padding: 15px 15px 0; color: #FF5722;}
.nav-login-box .login-menu{padding:15px 10px;}
.nav-menu .login-menu a{width:76px; color:#333; padding:10px; display:inline-block; font-size:15px;}
.nav-login-box .login-menu-bottom{background-color:#f2f2f2; padding:9px 20px; border-top:1px solid #eee;}
.nav-login-box .login-menu-bottom a{color:#666; font-size:12px;}
.nav-menu li.nav-logined .nav-login-box:after {content: '';display: block;width: 20px; height: 20px;background-color: #fff; position: absolute; top: -5px;right: 30px;
.navbar .login-menu a{width:76px; color:#333; padding:2px 12px; display:inline-block; font-size:15px;}
.nav-login-box .login-menu-bottom{background-color:#f2f2f2; border-top:1px solid #eee;}
.nav-login-box .login-menu-bottom a{color:#666; font-size:12px; padding: 12px;}
.navbar li.nav-logined .nav-login-box:after {content: '';display: block;width: 20px; height: 20px;background-color: #fff; position: absolute; top: -5px;right: 30px;
-webkit-transform: rotate(-45deg);
transform: rotate(-45deg);
}
.nav-menu li a.nav-img{height:32px; text-align:center; padding:14px 20px; display:block; line-height: 32px; font-size: 16px;}
.navbar li a.nav-img{height:32px; text-align:center; padding:0 20px; display:block; line-height: 32px; font-size: 16px;}
.navbar li.nav-logined:hover .nav-login-box{z-index:99;-webkit-transform:scale(1);transform:scale(1);opacity:1;}
.nav-img img{width:30px; height:30px; border-radius:50%; border:1px solid #fff; margin-right: 6px;}
.nav-menu li.nav-logined:hover .nav-login-box{z-index:99;-webkit-transform:scale(1);transform:scale(1);opacity:1;}
@media (max-width: 1280px) {
.navbar .dropdown .dropdown ul {left: -90%;}
.navbar .dropdown .dropdown:hover > ul { left: -100%;}
.nav-box{width:1026px;}
.navbar a { padding: 10px 18px;}
}
/*----------------页脚-----------------*/
.footer{width:100%; background-color:#1c1a1d;}