diff --git a/worker.js b/worker.js
index 52de3f3..282db93 100644
--- a/worker.js
+++ b/worker.js
@@ -1,2097 +1,2155 @@
-addEventListener('fetch', (event) => {
- event.respondWith(handleRequest(event.request));
- });
-
- async function handleRequest(request) {
- const url = new URL(request.url);
- const { pathname } = url;
-
- try {
- // 登录请求处理
- if (pathname === '/login' && request.method === 'POST') {
- const formData = new URLSearchParams(await request.text());
- const username = formData.get('username');
- const password = formData.get('password');
-
- if (username === envusername && password === envpassword) {
- return new Response(await renderNavigationPage(), {
- headers: { 'Content-Type': 'text/html; charset=utf-8' },
- });
- }
- // 登录失败时直接返回登录页面并显示错误
- return new Response(await renderLoginPage(true), {
- headers: { 'Content-Type': 'text/html; charset=utf-8' }
- });
- }
-
- // 路由处理
- switch (pathname) {
- case '/':
- case '/login.html':
- return new Response(await renderLoginPage(), {
- headers: { 'Content-Type': 'text/html; charset=utf-8' }
- });
-
- case '/privacy':
- return serveStaticFile('privacy.html');
-
- case '/data':
- return fetchNavigationData();
-
- case '/add-category':
- if (request.method === 'POST') return addCategory(request);
- break;
-
- case '/add-site':
- if (request.method === 'POST') return addSite(request);
- break;
-
- case '/delete-category':
- if (request.method === 'POST') return deleteCategory(request);
- break;
-
- case '/delete-site':
- if (request.method === 'POST') return deleteSite(request);
- break;
-
- case '/edit-site':
- if (request.method === 'POST') return editSite(request);
- break;
- case '/edit-category':
- if (request.method === 'POST') return editCategory(request);
- break;
- // 在handleRequest中添加切换分类状态的路由
- case '/toggle-category':
- if (request.method === 'POST') return toggleCategory(request);
- break;
- // 在handleRequest的switch语句中添加新路由
- case '/reorder-site':
- if (request.method === 'POST') return reorderSite(request);
- break;
- case '/load-notification':
- return loadNotification();
- }
-
- // 未匹配的路由返回404
- return serveStaticFile('NotFound.html', 404);
- } catch (error) {
- console.error('Error handling request:', error);
- return new Response('Internal Server Error', { status: 500 });
- }
- }
-
- // KV 数据操作函数
- async function getNavigationData() {
- const data = await NAVIGATION_DATA.get('data');
- const parsedData = data ? JSON.parse(data) : { categories: [] };
-
- // 初始化折叠状态
- parsedData.categories.forEach(category => {
- if (typeof category.collapsed === 'undefined') {
- category.collapsed = false; // 默认展开状态
- }
- });
-
- return parsedData;
- }
- // 添加站点重新排序功能
- async function reorderSite(request) {
- const requestBody = await request.json();
- const { categoryIndex, oldIndex, newIndex } = requestBody;
- const navigationData = await getNavigationData();
-
- // 验证分类索引
- if (categoryIndex < 0 || categoryIndex >= navigationData.categories.length) {
- return new Response(JSON.stringify({ error: '无效分类索引' }), {
- status: 400,
- headers: { 'Content-Type': 'application/json' }
- });
- }
-
- const category = navigationData.categories[categoryIndex];
- // 验证站点索引
- if (oldIndex < 0 || oldIndex >= category.sites.length ||
- newIndex < 0 || newIndex >= category.sites.length) {
- return new Response(JSON.stringify({ error: '无效站点索引' }), {
- status: 400,
- headers: { 'Content-Type': 'application/json' }
- });
- }
-
- // 移动站点位置
- const siteToMove = category.sites.splice(oldIndex, 1)[0];
- category.sites.splice(newIndex, 0, siteToMove);
-
- await setNavigationData(navigationData);
- return new Response(JSON.stringify({ message: '站点顺序已更新' }), {
- headers: { 'Content-Type': 'application/json; charset=utf-8' }
- });
- }
- // 添加编辑分类的API处理函数
-async function editCategory(request) {
- const requestBody = await request.json();
- const navigationData = await getNavigationData();
-
- // 验证索引有效性
- if (requestBody.categoryIndex < 0 ||
- requestBody.categoryIndex >= navigationData.categories.length) {
- return new Response(JSON.stringify({ error: '无效分类索引' }), {
- status: 400,
- headers: { 'Content-Type': 'application/json' }
- });
- }
-
- // 检查新名称是否已存在
- const newName = requestBody.newName.trim();
- const categoryExists = navigationData.categories.some(
- (cat, index) => index !== requestBody.categoryIndex && cat.name === newName
- );
-
- if (categoryExists) {
- return new Response(JSON.stringify({ error: '分类名称已存在' }), {
- status: 400,
- headers: { 'Content-Type': 'application/json' }
- });
- }
-
- // 更新分类名称
- navigationData.categories[requestBody.categoryIndex].name = newName;
-
- await setNavigationData(navigationData);
- return new Response(JSON.stringify({ message: '分类名称修改成功' }), {
- headers: { 'Content-Type': 'application/json; charset=utf-8' }
- });
- }
- // 添加切换分类折叠状态的API处理函数
-async function toggleCategory(request) {
- const requestBody = await request.json();
- const navigationData = await getNavigationData();
-
- // 验证索引有效性
- if (requestBody.categoryIndex < 0 ||
- requestBody.categoryIndex >= navigationData.categories.length) {
- return new Response(JSON.stringify({ error: '无效分类索引' }), {
- status: 400,
- headers: { 'Content-Type': 'application/json' }
- });
- }
-
- // 切换折叠状态
- const category = navigationData.categories[requestBody.categoryIndex];
- category.collapsed = !category.collapsed;
-
- await setNavigationData(navigationData);
- return new Response(JSON.stringify({
- message: '状态更新成功',
- collapsed: category.collapsed
- }), {
- headers: { 'Content-Type': 'application/json; charset=utf-8' }
- });
- }
-
- // 切换分类折叠状态
-async function toggleCategoryState(categoryIndex) {
- const response = await fetch('/toggle-category', {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ categoryIndex })
- });
-
- if (response.ok) {
- const result = await response.json();
- const categoryElement = document.getElementById(`category-sites-${categoryIndex}`);
- const toggleIcon = document.querySelector(`.toggle-btn[onclick="toggleCategoryState(${categoryIndex})"] .iconify`);
-
- if (result.collapsed) {
- categoryElement.style.display = 'none';
- toggleIcon.setAttribute('data-icon', 'mdi:chevron-right');
- } else {
- categoryElement.style.display = 'flex';
- toggleIcon.setAttribute('data-icon', 'mdi:chevron-down');
- }
- }
- }
-
-
- async function setNavigationData(data) {
- await NAVIGATION_DATA.put('data', JSON.stringify(data));
- }
-
- // 静态文件服务
- async function serveStaticFile(filename, status = 200) {
- const content = await STATIC_FILES.get(filename);
- if (content) {
- return new Response(content, {
- status,
- headers: { 'Content-Type': 'text/html; charset=utf-8' }
- });
- }
- return new Response(`${filename} not found`, { status: 404 });
- }
-
- // API 端点处理函数
- async function fetchNavigationData() {
- const navigationData = await getNavigationData();
- return new Response(JSON.stringify(navigationData), {
- headers: {
- 'Content-Type': 'application/json; charset=utf-8',
- 'Cache-Control': 'no-cache'
- }
- });
- }
-
- async function addCategory(request) {
- const requestBody = await request.json();
- const navigationData = await getNavigationData();
-
- // 检查分类是否已存在
- const categoryExists = navigationData.categories.some(
- cat => cat.name === requestBody.name
- );
-
- if (categoryExists) {
- return new Response(JSON.stringify({ error: '分类已存在' }), {
- status: 400,
- headers: { 'Content-Type': 'application/json' }
- });
- }
-
- navigationData.categories.push({
- name: requestBody.name,
- sites: []
- });
-
- await setNavigationData(navigationData);
- return new Response(JSON.stringify({ message: '分类添加成功' }), {
- headers: { 'Content-Type': 'application/json; charset=utf-8' }
- });
- }
-
- async function addSite(request) {
- const requestBody = await request.json();
- const navigationData = await getNavigationData();
-
- // 验证索引有效性
- if (requestBody.categoryIndex < 0 ||
- requestBody.categoryIndex >= navigationData.categories.length) {
- return new Response(JSON.stringify({ error: '无效分类索引' }), {
- status: 400,
- headers: { 'Content-Type': 'application/json' }
- });
- }
-
- // 添加站点描述字段
- navigationData.categories[requestBody.categoryIndex].sites.push({
- name: requestBody.siteName,
- url: requestBody.siteUrl,
- icon: requestBody.siteIcon,
- info: requestBody.siteInfo || '' // 添加站点描述
- });
-
- await setNavigationData(navigationData);
- return new Response(JSON.stringify({ message: '站点添加成功' }), {
- headers: { 'Content-Type': 'application/json; charset=utf-8' }
- });
- }
-
- async function editSite(request) {
- const requestBody = await request.json();
- const navigationData = await getNavigationData();
-
- // 获取原始分类索引和新分类索引
- const originalCategoryIndex = requestBody.originalCategoryIndex;
- const newCategoryIndex = requestBody.newCategoryIndex;
- const siteIndex = requestBody.siteIndex;
-
- // 验证索引有效性
- if (originalCategoryIndex < 0 ||
- originalCategoryIndex >= navigationData.categories.length ||
- newCategoryIndex < 0 ||
- newCategoryIndex >= navigationData.categories.length) {
- return new Response(JSON.stringify({ error: '无效分类索引' }), {
- status: 400,
- headers: { 'Content-Type': 'application/json' }
- });
- }
-
- const originalCategory = navigationData.categories[originalCategoryIndex];
- if (siteIndex < 0 || siteIndex >= originalCategory.sites.length) {
- return new Response(JSON.stringify({ error: '无效站点索引' }), {
- status: 400,
- headers: { 'Content-Type': 'application/json' }
- });
- }
-
- // 获取站点对象
- const site = originalCategory.sites[siteIndex];
-
- // 更新站点信息
- site.name = requestBody.siteName;
- site.url = requestBody.siteUrl;
- site.icon = requestBody.siteIcon;
- site.info = requestBody.siteInfo || '';
-
- // 如果分类发生变化,移动站点到新分类
- if (originalCategoryIndex !== newCategoryIndex) {
- // 从原分类移除
- originalCategory.sites.splice(siteIndex, 1);
-
- // 添加到新分类
- navigationData.categories[newCategoryIndex].sites.push(site);
- }
-
- await setNavigationData(navigationData);
- return new Response(JSON.stringify({ message: '站点更新成功' }), {
- headers: { 'Content-Type': 'application/json; charset=utf-8' }
- });
- }
-
- async function deleteCategory(request) {
- const requestBody = await request.json();
- const navigationData = await getNavigationData();
-
- // 验证索引有效性
- if (requestBody.categoryIndex < 0 ||
- requestBody.categoryIndex >= navigationData.categories.length) {
- return new Response(JSON.stringify({ error: '无效分类索引' }), {
- status: 400,
- headers: { 'Content-Type': 'application/json' }
- });
- }
-
- navigationData.categories.splice(requestBody.categoryIndex, 1);
- await setNavigationData(navigationData);
- return new Response(JSON.stringify({ message: '分类删除成功' }), {
- headers: { 'Content-Type': 'application/json; charset=utf-8' }
- });
- }
-
- async function deleteSite(request) {
- const requestBody = await request.json();
- const navigationData = await getNavigationData();
-
- // 验证索引有效性
- if (requestBody.categoryIndex < 0 ||
- requestBody.categoryIndex >= navigationData.categories.length) {
- return new Response(JSON.stringify({ error: '无效分类索引' }), {
- status: 400,
- headers: { 'Content-Type': 'application/json' }
- });
- }
-
- const category = navigationData.categories[requestBody.categoryIndex];
- if (requestBody.siteIndex < 0 || requestBody.siteIndex >= category.sites.length) {
- return new Response(JSON.stringify({ error: '无效站点索引' }), {
- status: 400,
- headers: { 'Content-Type': 'application/json' }
- });
- }
-
- category.sites.splice(requestBody.siteIndex, 1);
- await setNavigationData(navigationData);
- return new Response(JSON.stringify({ message: '站点删除成功' }), {
- headers: { 'Content-Type': 'application/json; charset=utf-8' }
- });
- }
-
- async function loadNotification() {
- const notification = await NAVIGATION_DATA.get('info');
- return new Response(notification || '', {
- headers: { 'Cache-Control': 'no-cache' }
- });
- }
-
- // 页面渲染函数
- async function renderLoginPage(showError = false) {
- return `
-
-
-
-
-
- Dispark|点滴星火登录页
-
-
-
-
-
-
-
- Dispark|点滴星火
-
-
-
-
-
-
- `;
- }
-
- async function renderNavigationPage() {
- const navigationData = await getNavigationData();
-
- const html = `
-
-
-
-
-
- Dispark|点滴星火
-
-
-
-
-
-
-
-
-
- ${renderCategories(navigationData.categories)}
-
-
-
-
-
-
-
-
-
-
-
-
-
修改分类名称
-
-
-
-
-
-
-
-
-
-
-
-
- `;
-
- return html;
- }
-
- /// 修复renderCategories函数 - 关键修改
-function renderCategories(categories) {
- return categories.map((category, categoryIndex) => `
-
-
-
-
-
- ${category.name}
-
-
-
-
-
-
-
-
-
-
-
-
- ${category.sites.map((site, siteIndex) => `
- -
-
-
-
-
-
-
-
-
-
- ${site.name}
-
-
- ${site.info ? `
-
- ` : ''}
-
-
-
-
-
-
-
- `).join('')}
-
-
- `).join('');
-}
-
- // 辅助函数:转义特殊字符
- function escapeString(str) {
- return str ? str
- .replace(/\\/g, '\\\\')
- .replace(/'/g, "\\'")
- .replace(/"/g, '\\"')
- .replace(/\n/g, '\\n')
- .replace(/\r/g, '\\r') : '';
- }
+addEventListener('fetch', (event) => {
+ event.respondWith(handleRequest(event.request));
+ });
+
+ async function handleRequest(request) {
+ const url = new URL(request.url);
+ const { pathname } = url;
+
+ try {
+ // 登录请求处理
+ if (pathname === '/login' && request.method === 'POST') {
+ const formData = new URLSearchParams(await request.text());
+ const username = formData.get('username');
+ const password = formData.get('password');
+
+ if (username === envusername && password === envpassword) {
+ return new Response(await renderNavigationPage(), {
+ headers: { 'Content-Type': 'text/html; charset=utf-8' },
+ });
+ }
+ // 登录失败时直接返回登录页面并显示错误
+ return new Response(await renderLoginPage(true), {
+ headers: { 'Content-Type': 'text/html; charset=utf-8' }
+ });
+ }
+
+ // 路由处理
+ switch (pathname) {
+ case '/':
+ case '/login.html':
+ return new Response(await renderLoginPage(), {
+ headers: { 'Content-Type': 'text/html; charset=utf-8' }
+ });
+
+ case '/privacy':
+ return serveStaticFile('privacy.html');
+
+ case '/data':
+ return fetchNavigationData();
+
+ case '/add-category':
+ if (request.method === 'POST') return addCategory(request);
+ break;
+
+ case '/add-site':
+ if (request.method === 'POST') return addSite(request);
+ break;
+
+ case '/delete-category':
+ if (request.method === 'POST') return deleteCategory(request);
+ break;
+
+ case '/delete-site':
+ if (request.method === 'POST') return deleteSite(request);
+ break;
+
+ case '/edit-site':
+ if (request.method === 'POST') return editSite(request);
+ break;
+ case '/edit-category':
+ if (request.method === 'POST') return editCategory(request);
+ break;
+ // 在handleRequest中添加切换分类状态的路由
+ case '/toggle-category':
+ if (request.method === 'POST') return toggleCategory(request);
+ break;
+ // 在handleRequest的switch语句中添加新路由
+ case '/reorder-site':
+ if (request.method === 'POST') return reorderSite(request);
+ break;
+ case '/load-notification':
+ return loadNotification();
+ case '/export':
+ return exportData(); // 导出接口
+
+ case '/import':
+ if (request.method === 'POST') return importData(request);
+ break;
+ }
+
+ // 未匹配的路由返回404
+ return serveStaticFile('NotFound.html', 404);
+ } catch (error) {
+ console.error('Error handling request:', error);
+ return new Response('Internal Server Error', { status: 500 });
+ }
+ }
+
+ // KV 数据操作函数
+ async function getNavigationData() {
+ const data = await NAVIGATION_DATA.get('data');
+ const parsedData = data ? JSON.parse(data) : { categories: [] };
+
+ // 初始化折叠状态
+ parsedData.categories.forEach(category => {
+ if (typeof category.collapsed === 'undefined') {
+ category.collapsed = false; // 默认展开状态
+ }
+ });
+
+ return parsedData;
+ }
+ // 导出导航数据为 JSON 文件
+ async function exportData() {
+ const navigationData = await getNavigationData(); // 复用已有函数
+ const jsonStr = JSON.stringify(navigationData, null, 2);
+
+ return new Response(jsonStr, {
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Content-Disposition': 'attachment; filename="navigation_backup.json"',
+ },
+ });
+ }
+ // 从上传的 JSON 文件导入导航数据
+ async function importData(request) {
+ try {
+ const formData = await request.formData();
+ const file = formData.get('file');
+
+ if (!file) {
+ return new Response(JSON.stringify({ error: '请选择要导入的文件' }), {
+ status: 400,
+ headers: { 'Content-Type': 'application/json' },
+ });
+ }
+
+ // 读取文件内容
+ const fileText = await file.text();
+ const importedData = JSON.parse(fileText);
+
+ // 简单验证格式:必须包含 categories 数组
+ if (!importedData || !Array.isArray(importedData.categories)) {
+ return new Response(JSON.stringify({ error: '无效的备份文件格式,缺少 categories 数组' }), {
+ status: 400,
+ headers: { 'Content-Type': 'application/json' },
+ });
+ }
+
+ // 可选:进一步验证每个分类和站点结构(这里略,可根据需要补充)
+
+ // 写入 KV
+ await NAVIGATION_DATA.put('data', JSON.stringify(importedData));
+
+ return new Response(JSON.stringify({ message: '数据导入成功' }), {
+ headers: { 'Content-Type': 'application/json; charset=utf-8' },
+ });
+ } catch (error) {
+ return new Response(JSON.stringify({ error: '导入失败:' + error.message }), {
+ status: 500,
+ headers: { 'Content-Type': 'application/json' },
+ });
+ }
+ }
+ // 添加站点重新排序功能
+ async function reorderSite(request) {
+ const requestBody = await request.json();
+ const { categoryIndex, oldIndex, newIndex } = requestBody;
+ const navigationData = await getNavigationData();
+
+ // 验证分类索引
+ if (categoryIndex < 0 || categoryIndex >= navigationData.categories.length) {
+ return new Response(JSON.stringify({ error: '无效分类索引' }), {
+ status: 400,
+ headers: { 'Content-Type': 'application/json' }
+ });
+ }
+
+ const category = navigationData.categories[categoryIndex];
+ // 验证站点索引
+ if (oldIndex < 0 || oldIndex >= category.sites.length ||
+ newIndex < 0 || newIndex >= category.sites.length) {
+ return new Response(JSON.stringify({ error: '无效站点索引' }), {
+ status: 400,
+ headers: { 'Content-Type': 'application/json' }
+ });
+ }
+
+ // 移动站点位置
+ const siteToMove = category.sites.splice(oldIndex, 1)[0];
+ category.sites.splice(newIndex, 0, siteToMove);
+
+ await setNavigationData(navigationData);
+ return new Response(JSON.stringify({ message: '站点顺序已更新' }), {
+ headers: { 'Content-Type': 'application/json; charset=utf-8' }
+ });
+ }
+ // 添加编辑分类的API处理函数
+async function editCategory(request) {
+ const requestBody = await request.json();
+ const navigationData = await getNavigationData();
+
+ // 验证索引有效性
+ if (requestBody.categoryIndex < 0 ||
+ requestBody.categoryIndex >= navigationData.categories.length) {
+ return new Response(JSON.stringify({ error: '无效分类索引' }), {
+ status: 400,
+ headers: { 'Content-Type': 'application/json' }
+ });
+ }
+
+ // 检查新名称是否已存在
+ const newName = requestBody.newName.trim();
+ const categoryExists = navigationData.categories.some(
+ (cat, index) => index !== requestBody.categoryIndex && cat.name === newName
+ );
+
+ if (categoryExists) {
+ return new Response(JSON.stringify({ error: '分类名称已存在' }), {
+ status: 400,
+ headers: { 'Content-Type': 'application/json' }
+ });
+ }
+
+ // 更新分类名称
+ navigationData.categories[requestBody.categoryIndex].name = newName;
+
+ await setNavigationData(navigationData);
+ return new Response(JSON.stringify({ message: '分类名称修改成功' }), {
+ headers: { 'Content-Type': 'application/json; charset=utf-8' }
+ });
+ }
+ // 添加切换分类折叠状态的API处理函数
+async function toggleCategory(request) {
+ const requestBody = await request.json();
+ const navigationData = await getNavigationData();
+
+ // 验证索引有效性
+ if (requestBody.categoryIndex < 0 ||
+ requestBody.categoryIndex >= navigationData.categories.length) {
+ return new Response(JSON.stringify({ error: '无效分类索引' }), {
+ status: 400,
+ headers: { 'Content-Type': 'application/json' }
+ });
+ }
+
+ // 切换折叠状态
+ const category = navigationData.categories[requestBody.categoryIndex];
+ category.collapsed = !category.collapsed;
+
+ await setNavigationData(navigationData);
+ return new Response(JSON.stringify({
+ message: '状态更新成功',
+ collapsed: category.collapsed
+ }), {
+ headers: { 'Content-Type': 'application/json; charset=utf-8' }
+ });
+ }
+
+ // 切换分类折叠状态
+async function toggleCategoryState(categoryIndex) {
+ const response = await fetch('/toggle-category', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ categoryIndex })
+ });
+
+ if (response.ok) {
+ const result = await response.json();
+ const categoryElement = document.getElementById(`category-sites-${categoryIndex}`);
+ const toggleIcon = document.querySelector(`.toggle-btn[onclick="toggleCategoryState(${categoryIndex})"] .iconify`);
+
+ if (result.collapsed) {
+ categoryElement.style.display = 'none';
+ toggleIcon.setAttribute('data-icon', 'mdi:chevron-right');
+ } else {
+ categoryElement.style.display = 'flex';
+ toggleIcon.setAttribute('data-icon', 'mdi:chevron-down');
+ }
+ }
+ }
+
+
+ async function setNavigationData(data) {
+ await NAVIGATION_DATA.put('data', JSON.stringify(data));
+ }
+
+ // 静态文件服务
+ async function serveStaticFile(filename, status = 200) {
+ const content = await STATIC_FILES.get(filename);
+ if (content) {
+ return new Response(content, {
+ status,
+ headers: { 'Content-Type': 'text/html; charset=utf-8' }
+ });
+ }
+ return new Response(`${filename} not found`, { status: 404 });
+ }
+
+ // API 端点处理函数
+ async function fetchNavigationData() {
+ const navigationData = await getNavigationData();
+ return new Response(JSON.stringify(navigationData), {
+ headers: {
+ 'Content-Type': 'application/json; charset=utf-8',
+ 'Cache-Control': 'no-cache'
+ }
+ });
+ }
+
+ async function addCategory(request) {
+ const requestBody = await request.json();
+ const navigationData = await getNavigationData();
+
+ // 检查分类是否已存在
+ const categoryExists = navigationData.categories.some(
+ cat => cat.name === requestBody.name
+ );
+
+ if (categoryExists) {
+ return new Response(JSON.stringify({ error: '分类已存在' }), {
+ status: 400,
+ headers: { 'Content-Type': 'application/json' }
+ });
+ }
+
+ navigationData.categories.push({
+ name: requestBody.name,
+ sites: []
+ });
+
+ await setNavigationData(navigationData);
+ return new Response(JSON.stringify({ message: '分类添加成功' }), {
+ headers: { 'Content-Type': 'application/json; charset=utf-8' }
+ });
+ }
+
+ async function addSite(request) {
+ const requestBody = await request.json();
+ const navigationData = await getNavigationData();
+
+ // 验证索引有效性
+ if (requestBody.categoryIndex < 0 ||
+ requestBody.categoryIndex >= navigationData.categories.length) {
+ return new Response(JSON.stringify({ error: '无效分类索引' }), {
+ status: 400,
+ headers: { 'Content-Type': 'application/json' }
+ });
+ }
+
+ // 添加站点描述字段
+ navigationData.categories[requestBody.categoryIndex].sites.push({
+ name: requestBody.siteName,
+ url: requestBody.siteUrl,
+ icon: requestBody.siteIcon,
+ info: requestBody.siteInfo || '' // 添加站点描述
+ });
+
+ await setNavigationData(navigationData);
+ return new Response(JSON.stringify({ message: '站点添加成功' }), {
+ headers: { 'Content-Type': 'application/json; charset=utf-8' }
+ });
+ }
+
+ async function editSite(request) {
+ const requestBody = await request.json();
+ const navigationData = await getNavigationData();
+
+ // 获取原始分类索引和新分类索引
+ const originalCategoryIndex = requestBody.originalCategoryIndex;
+ const newCategoryIndex = requestBody.newCategoryIndex;
+ const siteIndex = requestBody.siteIndex;
+
+ // 验证索引有效性
+ if (originalCategoryIndex < 0 ||
+ originalCategoryIndex >= navigationData.categories.length ||
+ newCategoryIndex < 0 ||
+ newCategoryIndex >= navigationData.categories.length) {
+ return new Response(JSON.stringify({ error: '无效分类索引' }), {
+ status: 400,
+ headers: { 'Content-Type': 'application/json' }
+ });
+ }
+
+ const originalCategory = navigationData.categories[originalCategoryIndex];
+ if (siteIndex < 0 || siteIndex >= originalCategory.sites.length) {
+ return new Response(JSON.stringify({ error: '无效站点索引' }), {
+ status: 400,
+ headers: { 'Content-Type': 'application/json' }
+ });
+ }
+
+ // 获取站点对象
+ const site = originalCategory.sites[siteIndex];
+
+ // 更新站点信息
+ site.name = requestBody.siteName;
+ site.url = requestBody.siteUrl;
+ site.icon = requestBody.siteIcon;
+ site.info = requestBody.siteInfo || '';
+
+ // 如果分类发生变化,移动站点到新分类
+ if (originalCategoryIndex !== newCategoryIndex) {
+ // 从原分类移除
+ originalCategory.sites.splice(siteIndex, 1);
+
+ // 添加到新分类
+ navigationData.categories[newCategoryIndex].sites.push(site);
+ }
+
+ await setNavigationData(navigationData);
+ return new Response(JSON.stringify({ message: '站点更新成功' }), {
+ headers: { 'Content-Type': 'application/json; charset=utf-8' }
+ });
+ }
+
+ async function deleteCategory(request) {
+ const requestBody = await request.json();
+ const navigationData = await getNavigationData();
+
+ // 验证索引有效性
+ if (requestBody.categoryIndex < 0 ||
+ requestBody.categoryIndex >= navigationData.categories.length) {
+ return new Response(JSON.stringify({ error: '无效分类索引' }), {
+ status: 400,
+ headers: { 'Content-Type': 'application/json' }
+ });
+ }
+
+ navigationData.categories.splice(requestBody.categoryIndex, 1);
+ await setNavigationData(navigationData);
+ return new Response(JSON.stringify({ message: '分类删除成功' }), {
+ headers: { 'Content-Type': 'application/json; charset=utf-8' }
+ });
+ }
+
+ async function deleteSite(request) {
+ const requestBody = await request.json();
+ const navigationData = await getNavigationData();
+
+ // 验证索引有效性
+ if (requestBody.categoryIndex < 0 ||
+ requestBody.categoryIndex >= navigationData.categories.length) {
+ return new Response(JSON.stringify({ error: '无效分类索引' }), {
+ status: 400,
+ headers: { 'Content-Type': 'application/json' }
+ });
+ }
+
+ const category = navigationData.categories[requestBody.categoryIndex];
+ if (requestBody.siteIndex < 0 || requestBody.siteIndex >= category.sites.length) {
+ return new Response(JSON.stringify({ error: '无效站点索引' }), {
+ status: 400,
+ headers: { 'Content-Type': 'application/json' }
+ });
+ }
+
+ category.sites.splice(requestBody.siteIndex, 1);
+ await setNavigationData(navigationData);
+ return new Response(JSON.stringify({ message: '站点删除成功' }), {
+ headers: { 'Content-Type': 'application/json; charset=utf-8' }
+ });
+ }
+
+ async function loadNotification() {
+ const notification = await NAVIGATION_DATA.get('info');
+ return new Response(notification || '', {
+ headers: { 'Cache-Control': 'no-cache' }
+ });
+ }
+
+ // 页面渲染函数
+ async function renderLoginPage(showError = false) {
+ return `
+
+
+
+
+
+ Dispark|点滴星火登录页
+
+
+
+
+
+
+
+ Dispark|点滴星火
+
+
+
+
+
+
+ `;
+ }
+
+ async function renderNavigationPage() {
+ const navigationData = await getNavigationData();
+
+ const html = `
+
+
+
+
+
+ Dispark|点滴星火
+
+
+
+
+
+
+
+
+
+ ${renderCategories(navigationData.categories)}
+
+
+
+
+
+
+
+
+
+
+
+
+
修改分类名称
+
+
+
+
+
+
+
+
+
+
+
+
+ `;
+
+ return html;
+ }
+
+ /// 修复renderCategories函数 - 关键修改
+function renderCategories(categories) {
+ return categories.map((category, categoryIndex) => `
+
+
+
+
+
+ ${category.name}
+
+
+
+
+
+
+
+
+
+
+
+
+ ${category.sites.map((site, siteIndex) => `
+ -
+
+
+
+
+
+
+
+
+
+ ${site.name}
+
+
+ ${site.info ? `
+
+ ` : ''}
+
+
+
+
+
+
+
+ `).join('')}
+
+
+ `).join('');
+}
+
+ // 辅助函数:转义特殊字符
+ function escapeString(str) {
+ return str ? str
+ .replace(/\\/g, '\\\\')
+ .replace(/'/g, "\\'")
+ .replace(/"/g, '\\"')
+ .replace(/\n/g, '\\n')
+ .replace(/\r/g, '\\r') : '';
+ }