This commit is contained in:
@@ -127,50 +127,76 @@ $(function () {
|
||||
};
|
||||
function initHeader() {
|
||||
let showIndex = 0;
|
||||
let hoverTimer = null;
|
||||
let leaveTimer = null;
|
||||
|
||||
$(".nav-menu .nav-item").hover(
|
||||
function () {
|
||||
const index = $(".nav-menu .nav-item").index($(this));
|
||||
$(".nav-cont .nav-cont-menu")
|
||||
.eq(index)
|
||||
.attr("style", "display: block;");
|
||||
|
||||
// $('.nav-cont').attr('style','display: block;')
|
||||
if (
|
||||
!$(".nav-cont .nav-cont-menu").eq(index).hasClass("nav-cont-empty")
|
||||
) {
|
||||
const height = $(".nav-cont .nav-cont-menu").eq(index).height();
|
||||
$(".nav-cont").attr("style", `height: ${height}px;`);
|
||||
|
||||
// 清除离开定时器
|
||||
if (leaveTimer) {
|
||||
clearTimeout(leaveTimer);
|
||||
leaveTimer = null;
|
||||
}
|
||||
showIndex = index;
|
||||
|
||||
// 添加150ms延迟,防止误触
|
||||
hoverTimer = setTimeout(() => {
|
||||
$(".nav-cont .nav-cont-menu")
|
||||
.eq(index)
|
||||
.css("display", "block");
|
||||
|
||||
if (
|
||||
!$(".nav-cont .nav-cont-menu").eq(index).hasClass("nav-cont-empty")
|
||||
) {
|
||||
const height = $(".nav-cont .nav-cont-menu").eq(index).outerHeight(true);
|
||||
$(".nav-cont").css("height", height + "px");
|
||||
}
|
||||
showIndex = index;
|
||||
}, 150);
|
||||
},
|
||||
function () {
|
||||
const index = $(".nav-menu .nav-item").index($(this));
|
||||
$(".nav-cont ").eq(index).attr("style", "display: none;");
|
||||
$(".nav-cont .nav-cont-menu").eq(index).attr("style", "display: none;");
|
||||
$(".nav-cont").attr("style", "height:0");
|
||||
// 清除悬停定时器
|
||||
if (hoverTimer) {
|
||||
clearTimeout(hoverTimer);
|
||||
hoverTimer = null;
|
||||
}
|
||||
|
||||
leaveTimer = setTimeout(() => {
|
||||
const index = $(".nav-menu .nav-item").index($(this));
|
||||
$(".nav-cont .nav-cont-menu").eq(index).css("display", "none");
|
||||
$(".nav-cont").css("height", "0");
|
||||
}, 100);
|
||||
}
|
||||
);
|
||||
|
||||
$(".nav-cont").hover(
|
||||
function () {
|
||||
//$('.nav-cont ').attr('style','display: block;')
|
||||
// 清除离开定时器
|
||||
if (leaveTimer) {
|
||||
clearTimeout(leaveTimer);
|
||||
leaveTimer = null;
|
||||
}
|
||||
|
||||
$(".nav-cont .nav-cont-menu")
|
||||
.eq(showIndex)
|
||||
.attr("style", "display: block;");
|
||||
//if (showIndex != 0) {
|
||||
if (!$(this).hasClass("nav-cont-empty")) {
|
||||
const height = $(".nav-cont .nav-cont-menu").eq(showIndex).height();
|
||||
$(".nav-cont").attr("style", `height: ${height}px;`);
|
||||
.css("display", "block");
|
||||
|
||||
if (!$(".nav-cont .nav-cont-menu").eq(showIndex).hasClass("nav-cont-empty")) {
|
||||
const height = $(".nav-cont .nav-cont-menu").eq(showIndex).outerHeight(true);
|
||||
$(".nav-cont").css("height", height + "px");
|
||||
}
|
||||
},
|
||||
function () {
|
||||
//$('.nav-cont ').attr('style','display: none;')
|
||||
$(".nav-cont .nav-cont-menu")
|
||||
.eq(showIndex)
|
||||
.attr("style", "display: none;");
|
||||
$(".nav-cont").attr("style", "height:0");
|
||||
leaveTimer = setTimeout(() => {
|
||||
$(".nav-cont .nav-cont-menu")
|
||||
.eq(showIndex)
|
||||
.css("display", "none");
|
||||
$(".nav-cont").css("height", "0");
|
||||
}, 100);
|
||||
}
|
||||
);
|
||||
|
||||
if (localStorage.jwt) {
|
||||
if (sessionStorage.accountInfo) {
|
||||
const obj = JSON.parse(sessionStorage.accountInfo);
|
||||
|
||||
222
css/nav-mega-menu.css
Normal file
222
css/nav-mega-menu.css
Normal file
@@ -0,0 +1,222 @@
|
||||
/* 三级导航菜单样式 - Mega Menu风格 */
|
||||
|
||||
/* 导航容器 */
|
||||
.nav-cont {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
background: #fff;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
|
||||
z-index: 1000;
|
||||
overflow: hidden;
|
||||
transition: height 0.3s ease-out;
|
||||
}
|
||||
|
||||
/* Mega Menu 内容区 */
|
||||
.nav-cont-menu.mega-menu {
|
||||
display: none;
|
||||
padding: 24px 0;
|
||||
}
|
||||
|
||||
.nav-cont-menu.mega-menu .nav-content {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 32px;
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
/* 二级菜单项(带三级菜单的分类) */
|
||||
.nav-category {
|
||||
flex: 0 0 auto;
|
||||
min-width: 200px;
|
||||
max-width: 280px;
|
||||
}
|
||||
|
||||
.nav-category-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 8px 12px;
|
||||
margin-bottom: 12px;
|
||||
border-radius: 6px;
|
||||
background: linear-gradient(135deg, #f0f7ff 0%, #e6f3ff 100%);
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.nav-category-header:hover {
|
||||
background: linear-gradient(135deg, #e6f3ff 0%, #d9edff 100%);
|
||||
transform: translateX(2px);
|
||||
}
|
||||
|
||||
.nav-category-icon {
|
||||
flex-shrink: 0;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.nav-category-icon img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.nav-category-info {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.nav-category-title {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #1890ff;
|
||||
margin-bottom: 2px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.nav-category-desc {
|
||||
font-size: 12px;
|
||||
color: #8c8c8c;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
/* 三级菜单列表 */
|
||||
.nav-third-level {
|
||||
padding-left: 12px;
|
||||
}
|
||||
|
||||
.nav-third-item {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.nav-third-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 6px 12px;
|
||||
border-radius: 4px;
|
||||
color: #333;
|
||||
font-size: 13px;
|
||||
text-decoration: none;
|
||||
transition: all 0.2s ease;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.nav-third-link::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 3px;
|
||||
height: 0;
|
||||
background: #1890ff;
|
||||
border-radius: 2px;
|
||||
transition: height 0.2s ease;
|
||||
}
|
||||
|
||||
.nav-third-link:hover {
|
||||
background: #f5f5f5;
|
||||
color: #1890ff;
|
||||
padding-left: 16px;
|
||||
}
|
||||
|
||||
.nav-third-link:hover::before {
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.nav-third-name {
|
||||
flex: 1;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.nav-third-desc {
|
||||
font-size: 11px;
|
||||
color: #999;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
/* 没有三级菜单的二级菜单项(旧版兼容) */
|
||||
.nav-item-box {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
padding: 12px 16px;
|
||||
border-radius: 6px;
|
||||
transition: all 0.2s ease;
|
||||
text-decoration: none;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.nav-item-box:hover {
|
||||
background: #f5f5f5;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.nav-item-box img {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
flex-shrink: 0;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.item-box-title .title {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.item-box-title .desc {
|
||||
font-size: 12px;
|
||||
color: #8c8c8c;
|
||||
}
|
||||
|
||||
/* 空菜单占位 */
|
||||
.nav-cont-menu.nav-cont-empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* 响应式调整 */
|
||||
@media (max-width: 768px) {
|
||||
.nav-cont {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.nav-cont-menu.mega-menu {
|
||||
padding: 16px 0;
|
||||
}
|
||||
|
||||
.nav-cont-menu.mega-menu .nav-content {
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.nav-category {
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
/* 加载动画 */
|
||||
@keyframes fadeInDown {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.nav-cont-menu.animated {
|
||||
animation: fadeInDown 0.3s ease-out;
|
||||
}
|
||||
209
header.html
209
header.html
@@ -2,112 +2,113 @@
|
||||
<html lang="en" theme-color="default" theme-mode id="addons_js" addons_js='{:json_encode($addons)}'>
|
||||
|
||||
<head>
|
||||
{php}
|
||||
// 在渲染阶段从主题配置插件读取配置,并覆盖 $data 与 SEO 变量,实现 SSR
|
||||
if (class_exists('\\addon\\theme_configurator\\model\\ThemeConfigModel')) {
|
||||
$cfgModel = new \addon\theme_configurator\model\ThemeConfigModel();
|
||||
$themeCfg = $cfgModel->getConfig();
|
||||
{php}
|
||||
// 在渲染阶段从主题配置插件读取配置,并覆盖 $data 与 SEO 变量,实现 SSR
|
||||
if (class_exists('\\addon\\theme_configurator\\model\\ThemeConfigModel')) {
|
||||
$cfgModel = new \addon\theme_configurator\model\ThemeConfigModel();
|
||||
$themeCfg = $cfgModel->getConfig();
|
||||
|
||||
if (is_array($themeCfg)) {
|
||||
$site = isset($themeCfg['site_config']) && is_array($themeCfg['site_config'])
|
||||
? $themeCfg['site_config']
|
||||
: [];
|
||||
if (is_array($themeCfg)) {
|
||||
$site = isset($themeCfg['site_config']) && is_array($themeCfg['site_config'])
|
||||
? $themeCfg['site_config']
|
||||
: [];
|
||||
|
||||
if (!isset($data) || !is_array($data)) {
|
||||
$data = [];
|
||||
}
|
||||
if (!isset($data) || !is_array($data)) {
|
||||
$data = [];
|
||||
}
|
||||
|
||||
// 覆盖 / 补充首页相关结构数据
|
||||
if (isset($themeCfg['banner'])) {
|
||||
$data['banner'] = $themeCfg['banner'];
|
||||
}
|
||||
if (isset($themeCfg['honor'])) {
|
||||
$data['honor'] = $themeCfg['honor'];
|
||||
}
|
||||
if (isset($themeCfg['friendly_link'])) {
|
||||
$data['friendly_link'] = $themeCfg['friendly_link'];
|
||||
}
|
||||
if (isset($themeCfg['header_nav'])) {
|
||||
$data['header_nav'] = $themeCfg['header_nav'];
|
||||
}
|
||||
if (isset($themeCfg['footer_nav'])) {
|
||||
$data['footer_nav'] = $themeCfg['footer_nav'];
|
||||
}
|
||||
if (isset($themeCfg['side'])) {
|
||||
$data['side_floating_window'] = $themeCfg['side'];
|
||||
}
|
||||
// 覆盖 / 补充首页相关结构数据
|
||||
if (isset($themeCfg['banner'])) {
|
||||
$data['banner'] = $themeCfg['banner'];
|
||||
}
|
||||
if (isset($themeCfg['honor'])) {
|
||||
$data['honor'] = $themeCfg['honor'];
|
||||
}
|
||||
if (isset($themeCfg['friendly_link'])) {
|
||||
$data['friendly_link'] = $themeCfg['friendly_link'];
|
||||
}
|
||||
if (isset($themeCfg['header_nav'])) {
|
||||
$data['header_nav'] = $themeCfg['header_nav'];
|
||||
}
|
||||
if (isset($themeCfg['footer_nav'])) {
|
||||
$data['footer_nav'] = $themeCfg['footer_nav'];
|
||||
}
|
||||
if (isset($themeCfg['side'])) {
|
||||
$data['side_floating_window'] = $themeCfg['side'];
|
||||
}
|
||||
|
||||
// 站点基础信息,供 header/footer 与其他模板直接使用
|
||||
$data['enterprise_name'] = $site['enterprise_name'] ?? ($data['enterprise_name'] ?? '');
|
||||
$data['enterprise_telephone'] = $site['enterprise_telephone'] ?? ($data['enterprise_telephone'] ?? '');
|
||||
$data['enterprise_mailbox'] = $site['enterprise_mailbox'] ?? ($data['enterprise_mailbox'] ?? '');
|
||||
$data['enterprise_qrcode'] = $site['enterprise_qrcode'] ?? ($data['enterprise_qrcode'] ?? '');
|
||||
$data['official_website_logo']= $site['official_website_logo']?? ($data['official_website_logo']?? '');
|
||||
$data['online_customer_service_link'] =
|
||||
$site['online_customer_service_link'] ?? ($data['online_customer_service_link'] ?? '');
|
||||
$data['icp_info'] = $site['icp_info'] ?? ($data['icp_info'] ?? '');
|
||||
$data['icp_info_link'] = $site['icp_info_link'] ?? ($data['icp_info_link'] ?? '');
|
||||
$data['public_security_network_preparation'] =
|
||||
$site['public_security_network_preparation'] ??
|
||||
($data['public_security_network_preparation'] ?? '');
|
||||
$data['public_security_network_preparation_link'] =
|
||||
$site['public_security_network_preparation_link'] ??
|
||||
($data['public_security_network_preparation_link'] ?? '');
|
||||
$data['telecom_appreciation'] = $site['telecom_appreciation'] ?? ($data['telecom_appreciation'] ?? '');
|
||||
$data['copyright_info'] = $site['copyright_info'] ?? ($data['copyright_info'] ?? '');
|
||||
$data['terms_service_url'] = $site['terms_service_url'] ?? ($data['terms_service_url'] ?? '');
|
||||
$data['terms_privacy_url'] = $site['terms_privacy_url'] ?? ($data['terms_privacy_url'] ?? '');
|
||||
$data['cloud_product_link'] = $site['cloud_product_link'] ?? ($data['cloud_product_link'] ?? '');
|
||||
$data['dcim_product_link'] = $site['dcim_product_link'] ?? ($data['dcim_product_link'] ?? '');
|
||||
// 站点基础信息,供 header/footer 与其他模板直接使用
|
||||
$data['enterprise_name'] = $site['enterprise_name'] ?? ($data['enterprise_name'] ?? '');
|
||||
$data['enterprise_telephone'] = $site['enterprise_telephone'] ?? ($data['enterprise_telephone'] ?? '');
|
||||
$data['enterprise_mailbox'] = $site['enterprise_mailbox'] ?? ($data['enterprise_mailbox'] ?? '');
|
||||
$data['enterprise_qrcode'] = $site['enterprise_qrcode'] ?? ($data['enterprise_qrcode'] ?? '');
|
||||
$data['official_website_logo']= $site['official_website_logo']?? ($data['official_website_logo']?? '');
|
||||
$data['online_customer_service_link'] =
|
||||
$site['online_customer_service_link'] ?? ($data['online_customer_service_link'] ?? '');
|
||||
$data['icp_info'] = $site['icp_info'] ?? ($data['icp_info'] ?? '');
|
||||
$data['icp_info_link'] = $site['icp_info_link'] ?? ($data['icp_info_link'] ?? '');
|
||||
$data['public_security_network_preparation'] =
|
||||
$site['public_security_network_preparation'] ??
|
||||
($data['public_security_network_preparation'] ?? '');
|
||||
$data['public_security_network_preparation_link'] =
|
||||
$site['public_security_network_preparation_link'] ??
|
||||
($data['public_security_network_preparation_link'] ?? '');
|
||||
$data['telecom_appreciation'] = $site['telecom_appreciation'] ?? ($data['telecom_appreciation'] ?? '');
|
||||
$data['copyright_info'] = $site['copyright_info'] ?? ($data['copyright_info'] ?? '');
|
||||
$data['terms_service_url'] = $site['terms_service_url'] ?? ($data['terms_service_url'] ?? '');
|
||||
$data['terms_privacy_url'] = $site['terms_privacy_url'] ?? ($data['terms_privacy_url'] ?? '');
|
||||
$data['cloud_product_link'] = $site['cloud_product_link'] ?? ($data['cloud_product_link'] ?? '');
|
||||
$data['dcim_product_link'] = $site['dcim_product_link'] ?? ($data['dcim_product_link'] ?? '');
|
||||
|
||||
// SEO:如插件配置了 SEO,则覆盖控制器传入的标题/关键词/描述
|
||||
if (!empty($themeCfg['seo']['title'])) {
|
||||
$title = $themeCfg['seo']['title'];
|
||||
}
|
||||
if (!empty($themeCfg['seo']['keywords'])) {
|
||||
$keywords = $themeCfg['seo']['keywords'];
|
||||
}
|
||||
if (!empty($themeCfg['seo']['description'])) {
|
||||
$description = $themeCfg['seo']['description'];
|
||||
}
|
||||
}
|
||||
}
|
||||
{/php}
|
||||
// SEO:如插件配置了 SEO,则覆盖控制器传入的标题/关键词/描述
|
||||
if (!empty($themeCfg['seo']['title'])) {
|
||||
$title = $themeCfg['seo']['title'];
|
||||
}
|
||||
if (!empty($themeCfg['seo']['keywords'])) {
|
||||
$keywords = $themeCfg['seo']['keywords'];
|
||||
}
|
||||
if (!empty($themeCfg['seo']['description'])) {
|
||||
$description = $themeCfg['seo']['description'];
|
||||
}
|
||||
}
|
||||
}
|
||||
{/php}
|
||||
|
||||
<meta charset="UTF-8">
|
||||
<title>{$title}</title>
|
||||
<meta name="keywords" content="{$keywords}" />
|
||||
<meta name="description" content="{$description}" />
|
||||
<meta charset="UTF-8">
|
||||
<title>{$title}</title>
|
||||
<meta name="keywords" content="{$keywords}" />
|
||||
<meta name="description" content="{$description}" />
|
||||
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta http-equiv="Content-Language" content="zh-cn">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta http-equiv="Content-Language" content="zh-cn">
|
||||
|
||||
<!-- 公共区域 -->
|
||||
<link rel="icon" type="image/x-icon" href="/favicon.ico">
|
||||
<link rel="stylesheet" href="/web/BlackFruit-web/assets/font/iconfont.css">
|
||||
<link rel="stylesheet" href="/web/BlackFruit-web/common/reset.css">
|
||||
<link rel="stylesheet" href="/web/BlackFruit-web/common/style.css">
|
||||
<link rel="stylesheet" href="/web/BlackFruit-web/common/theme.css">
|
||||
<link rel="stylesheet" href="/web/BlackFruit-web/common/common.css">
|
||||
<!-- Modular header/footer/nav styles -->
|
||||
<link rel="stylesheet" href="/web/BlackFruit-web/css/common.css">
|
||||
<link rel="stylesheet" href="/web/BlackFruit-web/vender/animate/animate.css">
|
||||
<script src="/web/BlackFruit-web/vender/jQuery/jquery-3.5.1.min.js"></script>
|
||||
<!-- 公共区域 -->
|
||||
<link rel="icon" type="image/x-icon" href="/favicon.ico">
|
||||
<link rel="stylesheet" href="/web/BlackFruit-web/assets/font/iconfont.css">
|
||||
<link rel="stylesheet" href="/web/BlackFruit-web/common/reset.css">
|
||||
<link rel="stylesheet" href="/web/BlackFruit-web/common/style.css">
|
||||
<link rel="stylesheet" href="/web/BlackFruit-web/common/theme.css">
|
||||
<link rel="stylesheet" href="/web/BlackFruit-web/common/common.css">
|
||||
<!-- Modular header/footer/nav styles -->
|
||||
<link rel="stylesheet" href="/web/BlackFruit-web/css/common.css">
|
||||
<link rel="stylesheet" href="/web/BlackFruit-web/css/nav-mega-menu.css">
|
||||
<link rel="stylesheet" href="/web/BlackFruit-web/vender/animate/animate.css">
|
||||
<script src="/web/BlackFruit-web/vender/jQuery/jquery-3.5.1.min.js"></script>
|
||||
|
||||
<!-- bootstrap -->
|
||||
<link rel="stylesheet" href="/web/BlackFruit-web/vender/bootstrap/css/bootstrap.min.css">
|
||||
<script src="/web/BlackFruit-web/vender/bootstrap/js/bootstrap.min.js"></script>
|
||||
<!-- swiper -->
|
||||
<link rel="stylesheet" href="/web/BlackFruit-web/vender/swiper/swiper-bundle.min.css">
|
||||
<script src="/web/BlackFruit-web/vender/swiper/swiper-bundle.min.js"></script>
|
||||
<!-- bootstrap -->
|
||||
<link rel="stylesheet" href="/web/BlackFruit-web/vender/bootstrap/css/bootstrap.min.css">
|
||||
<script src="/web/BlackFruit-web/vender/bootstrap/js/bootstrap.min.js"></script>
|
||||
<!-- swiper -->
|
||||
<link rel="stylesheet" href="/web/BlackFruit-web/vender/swiper/swiper-bundle.min.css">
|
||||
<script src="/web/BlackFruit-web/vender/swiper/swiper-bundle.min.js"></script>
|
||||
|
||||
<script src="/web/BlackFruit-web/common/common.js"></script>
|
||||
<script src="/web/BlackFruit-web/js/ai.js"></script>
|
||||
<script src="/web/BlackFruit-web/common/common.js"></script>
|
||||
<script src="/web/BlackFruit-web/js/ai.js"></script>
|
||||
|
||||
<link rel="alternate" hreflang="zh-Hans" href="{$url}">
|
||||
<link rel="canonical" href="{$url}">
|
||||
<script type="application/ld+json">
|
||||
<link rel="alternate" hreflang="zh-Hans" href="{$url}">
|
||||
<link rel="canonical" href="{$url}">
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://ziyuan.baidu.com/contexts/cambrian.jsonld",
|
||||
"@id": "{$url}",
|
||||
@@ -117,12 +118,12 @@
|
||||
"upDate": "{$up_date}"
|
||||
}
|
||||
</script>
|
||||
<script>
|
||||
// 将后端注入的配置映射到前端变量,供旧脚本兼容使用,避免再次通过接口请求主题配置
|
||||
window.__themeCommon = {: json_encode(isset($data) ? $data : [])};
|
||||
try {
|
||||
if (!sessionStorage.commentData) {
|
||||
sessionStorage.commentData = JSON.stringify(window.__themeCommon || {});
|
||||
}
|
||||
} catch (e) { }
|
||||
</script>
|
||||
<script>
|
||||
// 将后端注入的配置映射到前端变量,供旧脚本兼容使用,避免再次通过接口请求主题配置
|
||||
window.__themeCommon = {: json_encode(isset($data) ? $data : [])};
|
||||
try {
|
||||
if (!sessionStorage.commentData) {
|
||||
sessionStorage.commentData = JSON.stringify(window.__themeCommon || {});
|
||||
}
|
||||
} catch (e) { }
|
||||
</script>
|
||||
@@ -130,8 +130,70 @@ class ThemeConfigModel
|
||||
'keywords' => '云服务器,主题云,BlackFruit',
|
||||
'description' => 'BlackFruit-UI 默认站点说明',
|
||||
],
|
||||
// 顶部/底部导航
|
||||
'header_nav' => [],
|
||||
// 顶部/底部导航(第一个默认为产品中心,支持三级菜单)
|
||||
'header_nav' => [
|
||||
[
|
||||
'name' => '产品中心',
|
||||
'file_address' => '',
|
||||
'blank' => false,
|
||||
'children' => [
|
||||
[
|
||||
'name' => 'SAS轻量云服务器',
|
||||
'file_address' => '/cloud.html',
|
||||
'icon' => '/web/BlackFruit-web/assets/img/index/cloud-icon.png',
|
||||
'description' => '高性能SSD云服务器',
|
||||
'blank' => false,
|
||||
'children' => [
|
||||
[
|
||||
'name' => '香港SAS',
|
||||
'file_address' => '/cloud.html?region=hk',
|
||||
'description' => '香港数据中心',
|
||||
'blank' => false
|
||||
],
|
||||
[
|
||||
'name' => '美国SAS',
|
||||
'file_address' => '/cloud.html?region=us',
|
||||
'description' => '美国数据中心',
|
||||
'blank' => false
|
||||
],
|
||||
[
|
||||
'name' => '日本SAS',
|
||||
'file_address' => '/cloud.html?region=jp',
|
||||
'description' => '日本数据中心',
|
||||
'blank' => false
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
'name' => 'ECS精品云服务器',
|
||||
'file_address' => '/dedicated.html',
|
||||
'icon' => '/web/BlackFruit-web/assets/img/index/server-icon.png',
|
||||
'description' => '企业级云服务器',
|
||||
'blank' => false,
|
||||
'children' => [
|
||||
[
|
||||
'name' => '宁波ECS',
|
||||
'file_address' => '/dedicated.html?region=nb',
|
||||
'description' => '宁波数据中心',
|
||||
'blank' => false
|
||||
],
|
||||
[
|
||||
'name' => '镇江ECS',
|
||||
'file_address' => '/dedicated.html?region=zj',
|
||||
'description' => '镇江数据中心',
|
||||
'blank' => false
|
||||
],
|
||||
[
|
||||
'name' => '北京ECS',
|
||||
'file_address' => '/dedicated.html?region=bj',
|
||||
'description' => '北京数据中心',
|
||||
'blank' => false
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
'footer_nav' => [],
|
||||
// 站点基础信息
|
||||
'site_config' => [
|
||||
|
||||
@@ -718,25 +718,109 @@
|
||||
container.innerHTML = '';
|
||||
|
||||
children.forEach((child, childIndex) => {
|
||||
const hasGrandChildren = Array.isArray(child.children) && child.children.length > 0;
|
||||
const item = document.createElement('div');
|
||||
item.style.cssText = 'padding:8px; margin-bottom:8px; background:#f9f9f9; border-radius:4px;';
|
||||
item.style.cssText = 'padding:12px; margin-bottom:12px; background:#f9f9f9; border-radius:4px; border-left:3px solid #1890ff;';
|
||||
item.innerHTML = `
|
||||
<div style="display:flex; justify-content:space-between; align-items:start;">
|
||||
<div style="flex:1; display:grid; gap:8px;">
|
||||
<input type="text" class="form-control" data-hnav-child="${navIndex}.${childIndex}" data-field="name" value="${child.name || ''}" placeholder="子菜单名称">
|
||||
<input type="text" class="form-control" data-hnav-child="${navIndex}.${childIndex}" data-field="file_address" value="${child.file_address || ''}" placeholder="链接地址">
|
||||
<input type="text" class="form-control" data-hnav-child="${navIndex}.${childIndex}" data-field="icon" value="${child.icon || ''}" placeholder="图标URL(可选)">
|
||||
<input type="text" class="form-control" data-hnav-child="${navIndex}.${childIndex}" data-field="description" value="${child.description || ''}" placeholder="描述(可选)">
|
||||
<label style="font-size:12px;"><input type="checkbox" data-hnav-child="${navIndex}.${childIndex}" data-field="blank" ${child.blank ? 'checked' : ''}> 新窗口打开</label>
|
||||
<div style="margin-bottom:8px; display:flex; justify-content:space-between; align-items:center;">
|
||||
<strong style="color:#1890ff;">二级菜单 ${childIndex + 1}</strong>
|
||||
<div style="display:flex; gap:4px;">
|
||||
<button class="btn btn-info btn-sm" onclick="toggleThirdLevel(${navIndex}, ${childIndex})" style="font-size:11px;">
|
||||
${hasGrandChildren ? '收起三级' : '展开三级'}
|
||||
</button>
|
||||
<button class="btn-icon btn-icon-danger btn-sm" onclick="removeHeaderNavChild(${navIndex}, ${childIndex})">×</button>
|
||||
</div>
|
||||
<button class="btn-icon btn-icon-danger" onclick="removeHeaderNavChild(${navIndex}, ${childIndex})" style="margin-left:8px;">×</button>
|
||||
</div>
|
||||
<div style="display:grid; gap:8px;">
|
||||
<input type="text" class="form-control" data-hnav-child="${navIndex}.${childIndex}" data-field="name" value="${child.name || ''}" placeholder="二级菜单名称(如:SAS轻量云服务器)">
|
||||
<input type="text" class="form-control" data-hnav-child="${navIndex}.${childIndex}" data-field="file_address" value="${child.file_address || ''}" placeholder="链接地址(可选)">
|
||||
<input type="text" class="form-control" data-hnav-child="${navIndex}.${childIndex}" data-field="icon" value="${child.icon || ''}" placeholder="图标URL(可选)">
|
||||
<input type="text" class="form-control" data-hnav-child="${navIndex}.${childIndex}" data-field="description" value="${child.description || ''}" placeholder="描述文字(如:高性能SSD云服务器)">
|
||||
<label style="font-size:12px;"><input type="checkbox" data-hnav-child="${navIndex}.${childIndex}" data-field="blank" ${child.blank ? 'checked' : ''}> 新窗口打开</label>
|
||||
</div>
|
||||
<div id="third-level-${navIndex}-${childIndex}" style="display:${hasGrandChildren ? 'block' : 'none'}; margin-top:12px; padding:12px; background:#fff; border-radius:4px; border:1px dashed #d9d9d9;">
|
||||
<h6 style="margin:0 0 8px; font-size:12px; color:#666;">三级菜单</h6>
|
||||
<div id="third-level-list-${navIndex}-${childIndex}"></div>
|
||||
<button class="btn btn-secondary btn-sm" onclick="addThirdLevelItem(${navIndex}, ${childIndex})" style="margin-top:8px; font-size:11px;">+ 添加三级菜单</button>
|
||||
</div>
|
||||
`;
|
||||
container.appendChild(item);
|
||||
|
||||
// 渲染三级菜单
|
||||
if (hasGrandChildren) {
|
||||
renderThirdLevel(navIndex, childIndex, child.children);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 渲染三级菜单
|
||||
function renderThirdLevel(navIndex, childIndex, grandChildren) {
|
||||
const container = document.getElementById(`third-level-list-${navIndex}-${childIndex}`);
|
||||
if (!container) return;
|
||||
container.innerHTML = '';
|
||||
|
||||
grandChildren.forEach((grandChild, grandIndex) => {
|
||||
const item = document.createElement('div');
|
||||
item.style.cssText = 'padding:8px; margin-bottom:6px; background:#fafafa; border-radius:3px; border-left:2px solid #52c41a;';
|
||||
item.innerHTML = `
|
||||
<div style="display:flex; gap:6px; align-items:start;">
|
||||
<div style="flex:1; display:grid; gap:6px;">
|
||||
<input type="text" class="form-control form-control-sm" data-hnav-grandchild="${navIndex}.${childIndex}.${grandIndex}" data-field="name" value="${grandChild.name || ''}" placeholder="三级菜单名称(如:香港SAS)" style="font-size:12px;">
|
||||
<input type="text" class="form-control form-control-sm" data-hnav-grandchild="${navIndex}.${childIndex}.${grandIndex}" data-field="file_address" value="${grandChild.file_address || ''}" placeholder="链接地址" style="font-size:12px;">
|
||||
<input type="text" class="form-control form-control-sm" data-hnav-grandchild="${navIndex}.${childIndex}.${grandIndex}" data-field="description" value="${grandChild.description || ''}" placeholder="描述(可选)" style="font-size:12px;">
|
||||
<label style="font-size:11px;"><input type="checkbox" data-hnav-grandchild="${navIndex}.${childIndex}.${grandIndex}" data-field="blank" ${grandChild.blank ? 'checked' : ''}> 新窗口</label>
|
||||
</div>
|
||||
<button class="btn-icon btn-icon-danger btn-sm" onclick="removeThirdLevelItem(${navIndex}, ${childIndex}, ${grandIndex})" style="font-size:11px;">×</button>
|
||||
</div>
|
||||
`;
|
||||
container.appendChild(item);
|
||||
});
|
||||
}
|
||||
|
||||
// 切换三级菜单显示
|
||||
window.toggleThirdLevel = function (navIndex, childIndex) {
|
||||
const container = document.getElementById(`third-level-${navIndex}-${childIndex}`);
|
||||
const btn = event.target;
|
||||
if (container) {
|
||||
const isHidden = container.style.display === 'none';
|
||||
container.style.display = isHidden ? 'block' : 'none';
|
||||
btn.textContent = isHidden ? '收起三级' : '展开三级';
|
||||
}
|
||||
};
|
||||
|
||||
// 添加三级菜单项
|
||||
window.addThirdLevelItem = function (navIndex, childIndex) {
|
||||
const navs = collectHeaderNav();
|
||||
if (!navs[navIndex]) return;
|
||||
if (!navs[navIndex].children[childIndex]) return;
|
||||
|
||||
if (!navs[navIndex].children[childIndex].children) {
|
||||
navs[navIndex].children[childIndex].children = [];
|
||||
}
|
||||
|
||||
navs[navIndex].children[childIndex].children.push({
|
||||
name: '',
|
||||
file_address: '',
|
||||
description: '',
|
||||
blank: false
|
||||
});
|
||||
|
||||
renderHeaderNav(navs);
|
||||
// 确保展开
|
||||
document.getElementById(`third-level-${navIndex}-${childIndex}`).style.display = 'block';
|
||||
};
|
||||
|
||||
// 删除三级菜单项
|
||||
window.removeThirdLevelItem = function (navIndex, childIndex, grandIndex) {
|
||||
const navs = collectHeaderNav();
|
||||
if (navs[navIndex] && navs[navIndex].children[childIndex] && navs[navIndex].children[childIndex].children) {
|
||||
navs[navIndex].children[childIndex].children.splice(grandIndex, 1);
|
||||
renderHeaderNav(navs);
|
||||
}
|
||||
};
|
||||
|
||||
function collectHeaderNav() {
|
||||
|
||||
const navs = [];
|
||||
|
||||
// 收集主导航
|
||||
@@ -754,7 +838,7 @@
|
||||
|
||||
if (!navs[navIndex]) navs[navIndex] = { children: [] };
|
||||
if (!navs[navIndex].children[childIndex]) {
|
||||
navs[navIndex].children[childIndex] = {};
|
||||
navs[navIndex].children[childIndex] = { children: [] };
|
||||
}
|
||||
|
||||
if (input.type === 'checkbox') {
|
||||
@@ -764,6 +848,45 @@
|
||||
}
|
||||
});
|
||||
|
||||
// 收集三级菜单
|
||||
document.querySelectorAll('[data-hnav-grandchild]').forEach(input => {
|
||||
const [navIndex, childIndex, grandIndex] = input.dataset.hnavGrandchild.split('.').map(Number);
|
||||
const field = input.dataset.field;
|
||||
|
||||
if (!navs[navIndex]) navs[navIndex] = { children: [] };
|
||||
if (!navs[navIndex].children[childIndex]) {
|
||||
navs[navIndex].children[childIndex] = { children: [] };
|
||||
}
|
||||
if (!navs[navIndex].children[childIndex].children) {
|
||||
navs[navIndex].children[childIndex].children = [];
|
||||
}
|
||||
if (!navs[navIndex].children[childIndex].children[grandIndex]) {
|
||||
navs[navIndex].children[childIndex].children[grandIndex] = {};
|
||||
}
|
||||
|
||||
if (input.type === 'checkbox') {
|
||||
navs[navIndex].children[childIndex].children[grandIndex][field] = input.checked;
|
||||
} else {
|
||||
navs[navIndex].children[childIndex].children[grandIndex][field] = input.value;
|
||||
}
|
||||
});
|
||||
|
||||
// 清理空的children数组
|
||||
navs.forEach(nav => {
|
||||
if (nav && nav.children) {
|
||||
nav.children = nav.children.filter(child => child);
|
||||
nav.children.forEach(child => {
|
||||
if (child && child.children) {
|
||||
child.children = child.children.filter(gc => gc);
|
||||
// 如果三级菜单为空,删除children属性
|
||||
if (child.children.length === 0) {
|
||||
delete child.children;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return navs.filter(n => n);
|
||||
}
|
||||
|
||||
|
||||
@@ -64,21 +64,59 @@
|
||||
{if isset($data.header_nav) && !empty($data.header_nav)}
|
||||
{foreach $data.header_nav as $k=>$item}
|
||||
{if isset($item.children) && !empty($item.children)}
|
||||
<div class="nav-cont-menu animated slideInDown">
|
||||
<div class="nav-cont-menu mega-menu animated">
|
||||
<div class="nav-content">
|
||||
{foreach $item.children as $child}
|
||||
{* 判断是否有三级菜单 *}
|
||||
{if isset($child.children) && !empty($child.children)}
|
||||
{* 有三级菜单的二级分类 *}
|
||||
<div class="nav-category">
|
||||
<a href="{if !empty($child.file_address)}{$child.file_address}{else/}javascript:;{/if}"
|
||||
class="nav-category-header" {if !empty($child.blank)}target="_blank" {/if}>
|
||||
{if !empty($child.icon)}
|
||||
<div class="nav-category-icon">
|
||||
<img src="{$child.icon}" alt="{$child.name}">
|
||||
</div>
|
||||
{/if}
|
||||
<div class="nav-category-info">
|
||||
<div class="nav-category-title">{$child.name}</div>
|
||||
{if !empty($child.description)}
|
||||
<div class="nav-category-desc">{$child.description}</div>
|
||||
{/if}
|
||||
</div>
|
||||
</a>
|
||||
{* 三级菜单列表 *}
|
||||
<div class="nav-third-level">
|
||||
{foreach $child.children as $grandchild}
|
||||
<div class="nav-third-item">
|
||||
<a href="{if !empty($grandchild.file_address)}{$grandchild.file_address}{else/}javascript:;{/if}"
|
||||
class="nav-third-link" {if !empty($grandchild.blank)}target="_blank" {/if}>
|
||||
<span class="nav-third-name">{$grandchild.name}</span>
|
||||
{if !empty($grandchild.description)}
|
||||
<span class="nav-third-desc">{$grandchild.description}</span>
|
||||
{/if}
|
||||
</a>
|
||||
</div>
|
||||
{/foreach}
|
||||
</div>
|
||||
</div>
|
||||
{else /}
|
||||
{* 没有三级菜单的二级项(旧版样式兼容) *}
|
||||
<a href="{if !empty($child.file_address)}{$child.file_address}{else/}javascript:;{/if}" {if
|
||||
!empty($child.blank)}target="_blank" {/if}>
|
||||
!empty($child.blank)}target="_blank" {/if} style="text-decoration: none;">
|
||||
<div class="nav-item-box">
|
||||
{if !empty($child.icon)}
|
||||
<img src="{$child.icon}" alt="">
|
||||
<img src="{$child.icon}" alt="{$child.name}">
|
||||
{/if}
|
||||
<div class="item-box-title">
|
||||
<div class="title">{$child.name}</div>
|
||||
{if !empty($child.description)}
|
||||
<div class="desc">{$child.description}</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
{/if}
|
||||
{/foreach}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user