diff --git a/class/Api.php b/class/Api.php index 0b6ddf7..a88064b 100755 --- a/class/Api.php +++ b/class/Api.php @@ -822,6 +822,158 @@ class Api { $sortCategoryTree($tree); return $tree; } + + /** + * 导出JSON链接数据,格式兼容ZMark导入 + */ + public function export_json(){ + //鉴权 + $this->auth(''); + + $categories = $this->db->select("on_categorys", [ + "id","name","fid","description","weight","add_time" + ],[ + "ORDER" => ["fid" => "ASC", "weight" => "DESC", "id" => "DESC"] + ]); + $links = $this->db->select("on_links", [ + "id","fid","title","url","description","url_standby","weight","add_time" + ],[ + "ORDER" => ["weight" => "DESC", "id" => "DESC"] + ]); + + $decodeText = function ($value) { + return html_entity_decode((string)(isset($value) ? $value : ''), ENT_QUOTES, 'UTF-8'); + }; + + $toExportLink = function ($link) use ($decodeText) { + return [ + 'title' => $decodeText($link['title']), + 'url' => (string)(isset($link['url']) ? $link['url'] : ''), + 'description' => $decodeText($link['description']), + 'backup_url' => (string)(isset($link['url_standby']) ? $link['url_standby'] : ''), + 'sort_order' => intval(isset($link['weight']) ? $link['weight'] : 0) + ]; + }; + + $createDefaultCategory = function () { + return [ + 'name' => '默认分类', + 'description' => '', + 'links' => [], + 'children' => [] + ]; + }; + + $categoryMap = []; + $topCategoryIds = []; + $defaultCategory = null; + + foreach ($categories as $category) { + $categoryMap[$category['id']] = [ + 'id' => $category['id'], + 'fid' => $category['fid'], + 'weight' => intval(isset($category['weight']) ? $category['weight'] : 0), + 'name' => $decodeText($category['name']), + 'description' => $decodeText($category['description']), + 'links' => [], + 'children' => [] + ]; + } + + foreach ($categoryMap as $id => &$category) { + if (intval($category['fid']) === 0) { + $topCategoryIds[] = $id; + continue; + } + + if (isset($categoryMap[$category['fid']])) { + $categoryMap[$category['fid']]['children'][] = &$category; + continue; + } + + if ($defaultCategory === null) { + $defaultCategory = $createDefaultCategory(); + } + $defaultCategory['children'][] = &$category; + } + unset($category); + + foreach ($links as $link) { + $fid = intval($link['fid']); + $exportLink = $toExportLink($link); + + if (isset($categoryMap[$fid])) { + $categoryMap[$fid]['links'][] = $exportLink; + continue; + } + + if ($defaultCategory === null) { + $defaultCategory = $createDefaultCategory(); + } + $defaultCategory['links'][] = $exportLink; + } + + $sortCategories = function (&$items) use (&$sortCategories) { + usort($items, function ($a, $b) { + $weightDiff = intval(isset($b['weight']) ? $b['weight'] : 0) - intval(isset($a['weight']) ? $a['weight'] : 0); + if ($weightDiff !== 0) { + return $weightDiff; + } + return intval(isset($b['id']) ? $b['id'] : 0) - intval(isset($a['id']) ? $a['id'] : 0); + }); + + foreach ($items as &$item) { + if (!empty($item['children'])) { + $sortCategories($item['children']); + } + } + unset($item); + }; + + $topCategories = []; + foreach ($topCategoryIds as $id) { + $topCategories[] = $categoryMap[$id]; + } + $sortCategories($topCategories); + + $stripL2Category = function ($category) { + return [ + 'name' => $category['name'], + 'description' => $category['description'], + 'links' => $category['links'] + ]; + }; + + $stripL1Category = function ($category) use ($stripL2Category) { + $children = []; + foreach ($category['children'] as $child) { + $children[] = $stripL2Category($child); + } + + return [ + 'name' => $category['name'], + 'description' => $category['description'], + 'links' => $category['links'], + 'children' => $children + ]; + }; + + $exportCategories = []; + foreach ($topCategories as $category) { + $exportCategories[] = $stripL1Category($category); + } + + if ($defaultCategory !== null) { + $sortCategories($defaultCategory['children']); + $exportCategories[] = $stripL1Category($defaultCategory); + } + + return [ + 'type' => 'onenav.bookmarks', + 'version' => 1, + 'categories' => $exportCategories + ]; + } /** * name:修改链接 */ @@ -3388,5 +3540,3 @@ class Api { echo curl_get($url); } } - - diff --git a/controller/api.php b/controller/api.php index a6601c6..d805b75 100755 --- a/controller/api.php +++ b/controller/api.php @@ -598,6 +598,22 @@ HTML; echo "

\n"; } +//导出JSON链接数据 +function export_json($api) { + header('Content-Type: application/json; charset=UTF-8'); + + $payload = []; + if (method_exists($api,'export_json')) { + $payload = $api->export_json(); + } + + if (!is_array($payload)) { $payload = []; } + + $fileName = 'OneNav_Export_' . date('Ymd') . '.json'; + header('Content-Disposition: attachment; filename="' . $fileName . '"'); + echo json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT) . "\n"; +} + // 批量设置链接私有属性 function set_link_attribute($api) { $ids = $_POST['ids']; diff --git a/templates/admin/link_list.php b/templates/admin/link_list.php index 03c2e3e..f9c3e3e 100755 --- a/templates/admin/link_list.php +++ b/templates/admin/link_list.php @@ -92,7 +92,8 @@ 删除 - + + @@ -396,4 +397,4 @@ function reset_query(){ - \ No newline at end of file + diff --git a/templates/admin/static/embed.js b/templates/admin/static/embed.js index acea03c..f7a2906 100755 --- a/templates/admin/static/embed.js +++ b/templates/admin/static/embed.js @@ -1189,6 +1189,30 @@ function export_link(url, fileName) { } +//导出JSON链接数据 +function export_json(url, fileName) { + layer.confirm('导出的JSON数据支持导入到ZMark中,请妥善保存导出的文件。', {icon: 3, title:'确定导出JSON?'}, function(index){ + var date = new Date(); + var current_time = date.toLocaleDateString(); + current_time = current_time.replaceAll("/","."); + var url = "index.php?c=api&method=export_json"; + var fileName = "OneNav_Export_" + current_time + ".json"; + var x = new XMLHttpRequest(); + x.open("GET", url, true); + x.responseType = 'blob'; + x.onload=function(e) { + var url = window.URL.createObjectURL(x.response) + var a = document.createElement('a'); + a.href = url + a.download = fileName; + a.click() + } + x.send(); + + layer.close(index); + }); +} + //删除主题 function delete_theme(name) { layer.confirm('确认删除此主题(' + name + ')?', {icon: 3, title:'重要提示'}, function(index){ @@ -1316,4 +1340,4 @@ function support() { area: ['700px', '780px'], content: support_url // iframe 的 url }); -} \ No newline at end of file +} diff --git a/version.txt b/version.txt index 15842ff..96007bd 100755 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -v1.2.3-20260427 \ No newline at end of file +v1.2.4-20260507 \ No newline at end of file