Browse Source

支持导出json

main
xiaoz 3 hours ago
parent
commit
011299a9fe
  1. 154
      class/Api.php
  2. 16
      controller/api.php
  3. 5
      templates/admin/link_list.php
  4. 26
      templates/admin/static/embed.js
  5. 2
      version.txt

154
class/Api.php

@ -822,6 +822,158 @@ class Api { @@ -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 { @@ -3388,5 +3540,3 @@ class Api {
echo curl_get($url);
}
}

16
controller/api.php

@ -598,6 +598,22 @@ HTML; @@ -598,6 +598,22 @@ HTML;
echo "</DL><p>\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'];

5
templates/admin/link_list.php

@ -92,7 +92,8 @@ @@ -92,7 +92,8 @@
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del" onclick = "">删除</a>
</script>
<!-- 表单下面的按钮 -->
<button style="margin-top:16px;" class="layui-btn layui-btn-sm" lay-submit onclick = "export_link()">导出所有链接</button>
<button style="margin-top:16px;" class="layui-btn layui-btn-sm" lay-submit onclick = "export_link()">导出HTML</button>
<button style="margin-top:16px;" class="layui-btn layui-btn-sm layui-btn-normal" lay-submit onclick = "export_json()">导出JSON</button>
<!-- 表单下面的按钮END -->
</div>
<!-- 内容主题区域END -->
@ -396,4 +397,4 @@ function reset_query(){ @@ -396,4 +397,4 @@ function reset_query(){
</script>
<?php include_once('footer.php'); ?>
<?php include_once('footer.php'); ?>

26
templates/admin/static/embed.js

@ -1189,6 +1189,30 @@ function export_link(url, fileName) { @@ -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() { @@ -1316,4 +1340,4 @@ function support() {
area: ['700px', '780px'],
content: support_url // iframe 的 url
});
}
}

2
version.txt

@ -1 +1 @@ @@ -1 +1 @@
v1.2.3-20260427
v1.2.4-20260507
Loading…
Cancel
Save