@@ -231,15 +231,6 @@
< button class = "btn btn-secondary" id = "addFeedbackTypeBtn" > + 添加< / button >
< / div >
< / div >
< div class = "section-card" >
< div class = "section-header" >
< h2 > 合作伙伴< / h2 >
< / div >
< div class = "section-body" >
< div id = "partnerList" > < / div >
< button class = "btn btn-secondary" id = "addPartnerBtn" > + 添加< / button >
< / div >
< / div >
< / section >
<!-- JSON编辑器 -->
@@ -334,7 +325,6 @@
renderFriendlyLinks ( data . friendly _link || [ ] ) ;
renderSides ( data . side || [ ] ) ;
renderFeedbackTypes ( data . feedback _type || [ ] ) ;
renderPartners ( data . partner || [ ] ) ;
}
// 获取嵌套属性值
@@ -365,7 +355,6 @@
data . friendly _link = collectFriendlyLinks ( ) ;
data . side = collectSides ( ) ;
data . feedback _type = collectFeedbackTypes ( ) ;
data . partner = collectPartners ( ) ;
data . header _nav = collectHeaderNav ( ) ;
data . footer _nav = collectFooterNav ( ) ;
@@ -667,34 +656,88 @@
renderFeedbackTypes ( types ) ;
} ;
// ========== 合作伙伴 ==========
function renderPartners ( partner s ) {
const container = document . getElementById ( 'partner List' ) ;
// ========== 顶部导航 ==========
function renderHeaderNav ( nav s ) {
const container = document . getElementById ( 'headerNav List' ) ;
container . innerHTML = '' ;
partners . forEach ( ( partner , index ) => {
navs . forEach ( ( nav , index ) => {
const item = document . createElement ( 'div' ) ;
item . className = 'config-item' ;
const hasChildren = Array . isArray ( nav . children ) && nav . children . length > 0 ;
item . innerHTML = `
<div class="config-item__header">
<h4>伙伴 ${ index + 1 } </h4>
<button class="btn-icon btn-icon-danger" onclick="removePartner( ${ index } )">× </button >
<h4>导航 ${ index + 1 } : ${ nav . name || '(未命名)' } </h4>
<div style="display: flex; gap: 4px;" >
<button class="btn-icon" onclick="toggleHeaderNavChildren( ${ index } )" title="子菜单">☰ ${ hasChildren ? ` ( ${ nav . children . length } ) ` : '' } </button>
<button class="btn-icon btn-icon-danger" onclick="removeHeaderNav( ${ index } )">× </button>
</div>
</div>
<div class="config-item__body">
<div class="form-fields">
<div class="form-item">
<label>名称</label>
<input type="text" class="form-control" data-partner =" ${ index } " data-field="name" value=" ${ partner . name || '' } " placeholder="合作伙伴名称 ">
<input type="text" class="form-control" data-header-nav =" ${ index } " data-field="name" value=" ${ nav . name || '' } " placeholder="产品中心 ">
</div>
<div class="form-item">
<label>Logo地址 </label>
<div class="upload -control">
<input type="text" class="form-control" data-partner=" ${ index } " data-field="img" value=" ${ partner . img || '' } " placeholder="/upload/partner.png" >
<button class="btn btn-secondary upload-btn" data-target-partner=" ${ index } .img">选择文件</button >
<label>链接 </label>
<input type="text" class="form -control" data-header-nav=" ${ index } " data-field="file_address" value=" ${ nav . file _address || '' } " placeholder="/products.html" >
</div >
<div class="form-item" >
<div class="form-switch">
<label>新窗口</label>
<input type="checkbox" data-header-nav=" ${ index } " data-field="blank" ${ nav . blank ? 'checked' : '' } >
</div>
</div>
</div>
<div id="header-nav-children- ${ index } " style="display: ${ hasChildren ? 'block' : 'none' } ; margin-top:12px; padding-top:12px; border-top:1px solid #eee;">
<h5 style="margin:0 0 8px; font-size:13px;">子菜单</h5>
<div id="header-nav-children-list- ${ index } "></div>
<button class="btn btn-secondary btn-sm" onclick="addHeaderNavChild( ${ index } )" style="margin-top:8px;">+ 添加子菜单</button>
</div>
</div>
` ;
container . appendChild ( item ) ;
if ( hasChildren ) {
renderHeaderNavChildren ( index , nav . children ) ;
}
} ) ;
}
function renderHeaderNavChildren ( parentIndex , children ) {
const container = document . getElementById ( ` header-nav-children-list- ${ parentIndex } ` ) ;
container . innerHTML = '' ;
children . forEach ( ( child , childIndex ) => {
const item = document . createElement ( 'div' ) ;
item . className = 'config-item' ;
item . style . marginLeft = '20px' ;
item . innerHTML = `
<div class="config-item__header">
<h4 style="font-size:13px;">子项 ${ childIndex + 1 } </h4>
<button class="btn-icon btn-icon-danger" onclick="removeHeaderNavChild( ${ parentIndex } , ${ childIndex } )">× </button>
</div>
<div class="config-item__body">
<div class="form-fields">
<div class="form-item">
<label>描述 </label>
<input type="text" class="form-control" data-partner=" ${ i ndex } " data-field="description " value=" ${ partner . description || '' } " placeholder="简介 ">
<label>名称 </label>
<input type="text" class="form-control" data-header-nav-child=" ${ parentIndex } . ${ childI ndex } " data-field="name " value=" ${ child . name || '' } " placeholder="轻量云 ">
</div>
<div class="form-item">
<label>链接</label>
<input type="text" class="form-control" data-header-nav-child=" ${ parentIndex } . ${ childIndex } " data-field="file_address" value=" ${ child . file _address || '' } " placeholder="/light.html">
</div>
<div class="form-item">
<label>图标URL</label>
<input type="text" class="form-control" data-header-nav-child=" ${ parentIndex } . ${ childIndex } " data-field="icon" value=" ${ child . icon || '' } " placeholder="/upload/icon.png">
</div>
<div class="form-item">
<div class="form-switch">
<label>新窗口</label>
<input type="checkbox" data-header-nav-child=" ${ parentIndex } . ${ childIndex } " data-field="blank" ${ child . blank ? 'checked' : '' } >
</div>
</div>
</div>
</div>
@@ -703,63 +746,194 @@
} ) ;
}
function collectPartners ( ) {
const partners = [ ] ;
document . querySelectorAll ( '[data-partner]' ) . forEach ( input => {
const index = parseInt ( input . dataset . partner ) ;
const field = input . dataset . field ;
if ( ! partners [ index ] ) partners [ index ] = { } ;
partners [ index ] [ field ] = input . value ;
} ) ;
return partners . filter ( p => p ) ;
}
window . addPartner = function ( ) {
const partners = collectPartners ( ) ;
partners . push ( { name : '' , img : '' , description : '' } ) ;
renderPartners ( partners ) ;
} ;
window . removePartner = function ( index ) {
const partners = collectPartners ( ) ;
partners . splice ( index , 1 ) ;
renderPartners ( partners ) ;
} ;
// ========== 顶部导航(简化版) ==========
function renderHeaderNav ( navs ) {
const container = document . getElementById ( 'headerNavList' ) ;
container . innerHTML = '<div class="alert alert-info">顶部导航较复杂,建议使用JSON编辑器编辑</div>' ;
}
function collectHeaderNav ( ) {
return config . header _ nav || [ ] ;
const navs = [ ] ;
document . querySelectorAll ( '[data-header-nav]' ) . forEach ( input => {
const index = parseInt ( input . dataset . headerNav ) ;
const field = input . dataset . field ;
if ( ! navs [ index ] ) navs [ index ] = { children : [ ] } ;
navs [ index ] [ field ] = input . type === 'checkbox' ? input . checked : input . value ;
} ) ;
document . querySelectorAll ( '[data-header-nav-child]' ) . forEach ( input => {
const [ parentIndex , childIndex ] = input . dataset . headerNavChild . split ( '.' ) . map ( Number ) ;
const field = input . dataset . field ;
if ( ! navs [ parentIndex ] . children [ childIndex ] ) navs [ parentIndex ] . children [ childIndex ] = { } ;
navs [ parentIndex ] . children [ childIndex ] [ field ] = input . type === 'checkbox' ? input . checked : input . value ;
} ) ;
return navs . filter ( n => n ) ;
}
window . addHeaderNav = function ( ) {
alert ( '请使用JSON编辑器编辑顶部导航' ) ;
window . addHeaderNav = function ( ) {
const navs = collectHeaderNav ( ) ;
navs . push ( { name : '' , file _address : '' , blank : false , children : [ ] } ) ;
renderHeaderNav ( navs ) ;
} ;
// ========== 底部导航(简化版) ==========
window . removeHeaderNav = function ( index ) {
if ( confirm ( '确定删除此导航项吗?' ) ) {
const navs = collectHeaderNav ( ) ;
navs . splice ( index , 1 ) ;
renderHeaderNav ( navs ) ;
}
} ;
window . toggleHeaderNavChildren = function ( index ) {
const container = document . getElementById ( ` header-nav-children- ${ index } ` ) ;
container . style . display = container . style . display === 'none' ? 'block' : 'none' ;
} ;
window . addHeaderNavChild = function ( parentIndex ) {
const navs = collectHeaderNav ( ) ;
if ( ! navs [ parentIndex ] . children ) navs [ parentIndex ] . children = [ ] ;
navs [ parentIndex ] . children . push ( { name : '' , file _address : '' , blank : false , icon : '' , description : '' } ) ;
renderHeaderNav ( navs ) ;
document . getElementById ( ` header-nav-children- ${ parentIndex } ` ) . style . display = 'block' ;
} ;
window . removeHeaderNavChild = function ( parentIndex , childIndex ) {
if ( confirm ( '确定删除此子菜单吗?' ) ) {
const navs = collectHeaderNav ( ) ;
navs [ parentIndex ] . children . splice ( childIndex , 1 ) ;
renderHeaderNav ( navs ) ;
}
} ;
// ========== 底部导航 ==========
function renderFooterNav ( navs ) {
const container = document . getElementById ( 'footerNavList' ) ;
container . innerHTML = '<div class="alert alert-info">底部导航较复杂,建议使用JSON编辑器编辑</div> ' ;
container . innerHTML = '' ;
navs . forEach ( ( col , colIndex ) => {
const item = document . createElement ( 'div' ) ;
item . className = 'config-item' ;
const hasChildren = Array . isArray ( col . children ) && col . children . length > 0 ;
item . innerHTML = `
<div class="config-item__header">
<h4>栏目 ${ colIndex + 1 } : ${ col . name || '(未命名)' } </h4>
<div style="display: flex; gap: 4px;">
<button class="btn-icon" onclick="toggleFooterNavChildren( ${ colIndex } )" title="链接列表">☰ ${ hasChildren ? ` ( ${ col . children . length } ) ` : '' } </button>
<button class="btn-icon btn-icon-danger" onclick="removeFooterNav( ${ colIndex } )">× </button>
</div>
</div>
<div class="config-item__body">
<div class="form-item">
<label>栏目名称</label>
<input type="text" class="form-control" data-footer-nav=" ${ colIndex } " data-field="name" value=" ${ col . name || '' } " placeholder="热门云产品">
</div>
<div id="footer-nav-children- ${ colIndex } " style="display: ${ hasChildren ? 'block' : 'none' } ; margin-top:12px; padding-top:12px; border-top:1px solid #eee;">
<h5 style="margin:0 0 8px; font-size:13px;">链接列表</h5>
<div id="footer-nav-children-list- ${ colIndex } "></div>
<button class="btn btn-secondary btn-sm" onclick="addFooterNavChild( ${ colIndex } )" style="margin-top:8px;">+ 添加链接</button>
</div>
</div>
` ;
container . appendChild ( item ) ;
if ( hasChildren ) {
renderFooterNavChildren ( colIndex , col . children ) ;
}
} ) ;
}
function renderFooterNavChildren ( colIndex , children ) {
const container = document . getElementById ( ` footer-nav-children-list- ${ colIndex } ` ) ;
container . innerHTML = '' ;
children . forEach ( ( link , linkIndex ) => {
const item = document . createElement ( 'div' ) ;
item . className = 'config-item' ;
item . style . marginLeft = '20px' ;
item . innerHTML = `
<div class="config-item__header">
<h4 style="font-size:13px;">链接 ${ linkIndex + 1 } </h4>
<button class="btn-icon btn-icon-danger" onclick="removeFooterNavChild( ${ colIndex } , ${ linkIndex } )">× </button>
</div>
<div class="config-item__body">
<div class="form-fields">
<div class="form-item">
<label>名称</label>
<input type="text" class="form-control" data-footer-nav-child=" ${ colIndex } . ${ linkIndex } " data-field="name" value=" ${ link . name || '' } " placeholder="云服务器">
</div>
<div class="form-item">
<label>链接</label>
<input type="text" class="form-control" data-footer-nav-child=" ${ colIndex } . ${ linkIndex } " data-field="url" value=" ${ link . url || '' } " placeholder="/products/ecs.html">
</div>
<div class="form-item">
<div class="form-switch">
<label>新窗口</label>
<input type="checkbox" data-footer-nav-child=" ${ colIndex } . ${ linkIndex } " data-field="blank" ${ link . blank ? 'checked' : '' } >
</div>
</div>
</div>
</div>
` ;
container . appendChild ( item ) ;
} ) ;
}
function collectFooterNav ( ) {
return config . footer _ nav || [ ] ;
const navs = [ ] ;
document . querySelectorAll ( '[data-footer-nav]' ) . forEach ( input => {
const index = parseInt ( input . dataset . footerNav ) ;
if ( ! navs [ index ] ) navs [ index ] = { children : [ ] } ;
navs [ index ] [ input . dataset . field ] = input . value ;
} ) ;
document . querySelectorAll ( '[data-footer-nav-child]' ) . forEach ( input => {
const [ colIndex , linkIndex ] = input . dataset . footerNavChild . split ( '.' ) . map ( Number ) ;
const field = input . dataset . field ;
if ( ! navs [ colIndex ] . children [ linkIndex ] ) navs [ colIndex ] . children [ linkIndex ] = { } ;
navs [ colIndex ] . children [ linkIndex ] [ field ] = input . type === 'checkbox' ? input . checked : input . value ;
} ) ;
return navs . filter ( n => n ) ;
}
window . addFooterNav = function ( ) {
alert ( '请使用JSON编辑器编辑底部导航' ) ;
window . addFooterNav = function ( ) {
const navs = collectFooterNav ( ) ;
navs . push ( { name : '' , children : [ ] } ) ;
renderFooterNav ( navs ) ;
} ;
window . removeFooterNav = function ( index ) {
if ( confirm ( '确定删除此栏目吗?' ) ) {
const navs = collectFooterNav ( ) ;
navs . splice ( index , 1 ) ;
renderFooterNav ( navs ) ;
}
} ;
window . toggleFooterNavChildren = function ( index ) {
const container = document . getElementById ( ` footer-nav-children- ${ index } ` ) ;
container . style . display = container . style . display === 'none' ? 'block' : 'none' ;
} ;
window . addFooterNavChild = function ( colIndex ) {
const navs = collectFooterNav ( ) ;
if ( ! navs [ colIndex ] . children ) navs [ colIndex ] . children = [ ] ;
navs [ colIndex ] . children . push ( { name : '' , url : '' , blank : false } ) ;
renderFooterNav ( navs ) ;
document . getElementById ( ` footer-nav-children- ${ colIndex } ` ) . style . display = 'block' ;
} ;
window . removeFooterNavChild = function ( colIndex , linkIndex ) {
if ( confirm ( '确定删除此链接吗?' ) ) {
const navs = collectFooterNav ( ) ;
navs [ colIndex ] . children . splice ( linkIndex , 1 ) ;
renderFooterNav ( navs ) ;
}
} ;
// 文件上传
document . addEventListener ( 'click' , ( e ) => {
if ( e . target . closest ( '.upload-btn' ) ) {
e . preventDefault ( ) ;
const btn = e . target . closest ( '.upload-btn' ) ;
currentUploadTarget = btn . dataset . target || btn . dataset . targetBanner || btn . dataset . targetHonor || btn . dataset . targetSide || btn . dataset . targetPartner ;
currentUploadTarget = btn . dataset . target || btn . dataset . targetBanner || btn . dataset . targetHonor || btn . dataset . targetSide ;
document . getElementById ( 'fileInput' ) . click ( ) ;
}
} ) ;
@@ -836,7 +1010,6 @@
document . getElementById ( 'addFriendlyLinkBtn' ) . addEventListener ( 'click' , addFriendlyLink ) ;
document . getElementById ( 'addSideBtn' ) . addEventListener ( 'click' , addSide ) ;
document . getElementById ( 'addFeedbackTypeBtn' ) . addEventListener ( 'click' , addFeedbackType ) ;
document . getElementById ( 'addPartnerBtn' ) . addEventListener ( 'click' , addPartner ) ;
document . getElementById ( 'addHeaderNavBtn' ) . addEventListener ( 'click' , addHeaderNav ) ;
document . getElementById ( 'addFooterNavBtn' ) . addEventListener ( 'click' , addFooterNav ) ;