From 4c7a5e6a60d980fac6690b537aa4f18e9d8ce17f Mon Sep 17 00:00:00 2001 From: Zuoling Rong Date: Sun, 6 Jul 2025 23:20:50 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=8C=E5=96=84MeNav=E6=B5=8F?= =?UTF-8?q?=E8=A7=88=E5=99=A8=E6=89=A9=E5=B1=95API=E8=A7=84=E8=8C=83?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/script.js | 192 ++++++++++++++++++++---- templates/components/category.hbs | 6 +- templates/components/navigation.hbs | 8 +- templates/components/search-results.hbs | 10 +- templates/components/site-card.hbs | 8 +- templates/components/social-links.hbs | 6 +- templates/layouts/default.hbs | 3 +- templates/pages/articles.hbs | 4 +- templates/pages/bookmarks.hbs | 4 +- templates/pages/friends.hbs | 4 +- templates/pages/home.hbs | 6 +- templates/pages/page.hbs | 4 +- templates/pages/projects.hbs | 4 +- templates/pages/search-results.hbs | 10 +- 14 files changed, 206 insertions(+), 63 deletions(-) diff --git a/src/script.js b/src/script.js index 60683e0..a1c4c18 100644 --- a/src/script.js +++ b/src/script.js @@ -8,24 +8,56 @@ window.MeNav = { return configData ? JSON.parse(configData.textContent) : null; }, - // 更新DOM元素 - updateElement: function(id, newData) { - const element = document.querySelector(`[data-menav-id="${id}"]`); - if (!element) return false; + // 获取元素的唯一标识符 + _getElementId: function(element) { + const type = element.getAttribute('data-type'); + if (type === 'nav-item') { + return element.getAttribute('data-id'); + } else if (type === 'social-link') { + return element.getAttribute('data-url'); + } else { + return element.getAttribute('data-name'); + } + }, - // 根据元素类型更新内容 - const type = element.getAttribute('data-menav-type'); + // 根据类型和ID查找元素 + _findElement: function(type, id) { + let selector; + if (type === 'nav-item') { + selector = `[data-type="${type}"][data-id="${id}"]`; + } else if (type === 'social-link') { + selector = `[data-type="${type}"][data-url="${id}"]`; + } else { + selector = `[data-type="${type}"][data-name="${id}"]`; + } + return document.querySelector(selector); + }, + + // 更新DOM元素 + updateElement: function(type, id, newData) { + const element = this._findElement(type, id); + if (!element) return false; if (type === 'site') { // 更新站点卡片 - if (newData.url) element.href = newData.url; - if (newData.name) element.querySelector('h3').textContent = newData.name; - if (newData.description) element.querySelector('p').textContent = newData.description; + if (newData.url) { + element.href = newData.url; + element.setAttribute('data-url', newData.url); + } + if (newData.name) { + element.querySelector('h3').textContent = newData.name; + element.setAttribute('data-name', newData.name); + } + if (newData.description) { + element.querySelector('p').textContent = newData.description; + element.setAttribute('data-description', newData.description); + } if (newData.icon) { const iconElement = element.querySelector('i'); if (iconElement) { iconElement.className = newData.icon; } + element.setAttribute('data-icon', newData.icon); } if (newData.title) element.title = newData.title; @@ -47,6 +79,10 @@ window.MeNav = { const iconClass = iconElement ? iconElement.className : ''; titleElement.innerHTML = ` ${newData.name}`; } + element.setAttribute('data-name', newData.name); + } + if (newData.icon) { + element.setAttribute('data-icon', newData.icon); } // 触发元素更新事件 @@ -56,6 +92,60 @@ window.MeNav = { data: newData }); + return true; + } else if (type === 'nav-item') { + // 更新导航项 + if (newData.name) { + const textElement = element.querySelector('.nav-text'); + if (textElement) { + textElement.textContent = newData.name; + } + element.setAttribute('data-name', newData.name); + } + if (newData.icon) { + const iconElement = element.querySelector('i'); + if (iconElement) { + iconElement.className = newData.icon; + } + element.setAttribute('data-icon', newData.icon); + } + + // 触发元素更新事件 + this.events.emit('elementUpdated', { + id: id, + type: 'nav-item', + data: newData + }); + + return true; + } else if (type === 'social-link') { + // 更新社交链接 + if (newData.url) { + element.href = newData.url; + element.setAttribute('data-url', newData.url); + } + if (newData.name) { + const textElement = element.querySelector('.nav-text'); + if (textElement) { + textElement.textContent = newData.name; + } + element.setAttribute('data-name', newData.name); + } + if (newData.icon) { + const iconElement = element.querySelector('i'); + if (iconElement) { + iconElement.className = newData.icon; + } + element.setAttribute('data-icon', newData.icon); + } + + // 触发元素更新事件 + this.events.emit('elementUpdated', { + id: id, + type: 'social-link', + data: newData + }); + return true; } @@ -64,12 +154,15 @@ window.MeNav = { // 添加新元素 addElement: function(type, parentId, data) { - const parent = document.querySelector(`[data-menav-id="${parentId}"]`); - if (!parent) return null; + let parent; + + if (type === 'site') { + // 查找父级分类 + parent = document.querySelector(`[data-type="category"][data-name="${parentId}"]`); + if (!parent) return null; - if (type === 'site' && parent.getAttribute('data-menav-type') === 'category') { // 添加站点卡片到分类 - const sitesGrid = parent.querySelector('.sites-grid'); + const sitesGrid = parent.querySelector('[data-container="sites"]'); if (!sitesGrid) return null; // 创建新的站点卡片 @@ -77,10 +170,13 @@ window.MeNav = { newSite.className = 'site-card'; newSite.href = data.url || '#'; newSite.title = data.name + (data.description ? ' - ' + data.description : ''); - const elementId = `site-new-${Date.now()}`; - newSite.setAttribute('data-menav-id', elementId); - newSite.setAttribute('data-menav-type', 'site'); - newSite.setAttribute('data-menav-category', parent.id); + + // 设置数据属性 + newSite.setAttribute('data-type', 'site'); + newSite.setAttribute('data-name', data.name || '未命名站点'); + newSite.setAttribute('data-url', data.url || ''); + newSite.setAttribute('data-icon', data.icon || 'fas fa-link'); + newSite.setAttribute('data-description', data.description || ''); // 添加内容 newSite.innerHTML = ` @@ -100,26 +196,65 @@ window.MeNav = { // 触发元素添加事件 this.events.emit('elementAdded', { - id: elementId, + id: data.name, type: 'site', parentId: parentId, data: data }); - return elementId; + return data.name; + } else if (type === 'category') { + // 查找父级页面容器 + parent = document.querySelector(`[data-container="categories"]`); + if (!parent) return null; + + // 创建新的分类 + const newCategory = document.createElement('section'); + newCategory.className = 'category'; + + // 设置数据属性 + newCategory.setAttribute('data-type', 'category'); + newCategory.setAttribute('data-name', data.name || '未命名分类'); + newCategory.setAttribute('data-icon', data.icon || 'fas fa-folder'); + newCategory.setAttribute('data-container', 'categories'); + + // 添加内容 + newCategory.innerHTML = ` +

${data.name || '未命名分类'}

+
+

暂无网站

+
+ `; + + // 添加到DOM + parent.appendChild(newCategory); + + // 触发元素添加事件 + this.events.emit('elementAdded', { + id: data.name, + type: 'category', + data: data + }); + + return data.name; } return null; }, // 删除元素 - removeElement: function(id) { - const element = document.querySelector(`[data-menav-id="${id}"]`); + removeElement: function(type, id) { + const element = this._findElement(type, id); if (!element) return false; - // 获取元素类型和分类(如果是站点卡片) - const type = element.getAttribute('data-menav-type'); - const category = element.getAttribute('data-menav-category'); + // 获取父级容器(如果是站点卡片) + let parentId = null; + if (type === 'site') { + const categoryElement = element.closest('[data-type="category"]'); + if (categoryElement) { + parentId = categoryElement.getAttribute('data-name'); + } + } // 删除元素 element.remove(); @@ -128,7 +263,7 @@ window.MeNav = { this.events.emit('elementRemoved', { id: id, type: type, - category: category + parentId: parentId }); return true; @@ -136,10 +271,11 @@ window.MeNav = { // 获取所有元素 getAllElements: function(type) { - return Array.from(document.querySelectorAll(`[data-menav-type="${type}"]`)).map(el => { + return Array.from(document.querySelectorAll(`[data-type="${type}"]`)).map(el => { + const id = this._getElementId(el); return { - id: el.getAttribute('data-menav-id'), - type: el.getAttribute('data-menav-type'), + id: id, + type: type, element: el }; }); diff --git a/templates/components/category.hbs b/templates/components/category.hbs index 0467ace..71550f2 100644 --- a/templates/components/category.hbs +++ b/templates/components/category.hbs @@ -1,6 +1,6 @@ -
-

{{name}}

-
+
+

{{name}}

+
{{#if sites.length}} {{#each sites}} {{> site-card}} diff --git a/templates/components/navigation.hbs b/templates/components/navigation.hbs index 2570204..3a8a165 100644 --- a/templates/components/navigation.hbs +++ b/templates/components/navigation.hbs @@ -1,10 +1,11 @@ +
{{#each this}} {{/if}}
-{{/each}} \ No newline at end of file +{{/each}} +
\ No newline at end of file diff --git a/templates/components/search-results.hbs b/templates/components/search-results.hbs index 370474e..f2adff8 100644 --- a/templates/components/search-results.hbs +++ b/templates/components/search-results.hbs @@ -1,11 +1,11 @@
-

搜索结果

-

在所有页面中找到的匹配项

+

搜索结果

+

在所有页面中找到的匹配项

{{#each navigation}} -