diff --git a/class/Api.php b/class/Api.php index 3505ea5..4ae9f25 100755 --- a/class/Api.php +++ b/class/Api.php @@ -738,38 +738,66 @@ class Api { } /** - * 导出HTML链接进行备份 + * 导出HTML链接进行备份(支持二级分类) + * 返回结构: + * [ + * [ + * 'id'=>1,'name'=>'父分类','links'=>[...], + * 'children'=>[ + * ['id'=>2,'name'=>'子分类','links'=>[...]], + * ... + * ] + * ], + * ... + * ] */ public function export_link(){ //鉴权 $this->auth($token); - //查询所有分类 - $categorys = $this->db->select("on_categorys","*"); - - //定义一个空数组用来存储查询后的数据 - $data = []; - - //遍历分类 - foreach ($categorys as $key => $category) { - //查询该分类下的所有链接 - $links = $this->db->select("on_links","*",[ - "fid" => $category['id'] - ]); - // echo $category['name']; - // var_dump($links); - // exit; - //组合为一个一维数组 - - $arr[$category['name']] = $links; - // var_dump(); - // exit; - $data[$category['name']] = $arr[$category['name']]; - - //清除临时数据 - unset($arr); + // 一次性获取所有分类与链接,减少查询次数 + $categories = $this->db->select("on_categorys", [ + "id","name","fid","weight","add_time" + ]); + $links = $this->db->select("on_links", [ + "id","fid","title","url","add_time","weight" + ],[ + "ORDER" => ["weight"=>"DESC","id"=>"DESC"] + ]); + + // 预分配链接到分类 + $linksByCat = []; + foreach ($links as $l) { + $linksByCat[$l['fid']][] = $l; + } + + // 构建分类映射 + $catMap = []; + foreach ($categories as $c) { + $catMap[$c['id']] = [ + 'id' => $c['id'], + 'name' => $c['name'], + 'fid' => $c['fid'], + 'links' => isset($linksByCat[$c['id']]) ? $linksByCat[$c['id']] : [], + 'children' => [] + ]; + } + + // 组装层级(仅两级:fid=0 为顶级,其它挂到父类 children) + $tree = []; + foreach ($catMap as $id => &$node) { + if ($node['fid'] == 0) { + $tree[] = &$node; + } else { + if (isset($catMap[$node['fid']])) { + $catMap[$node['fid']]['children'][] = &$node; + } else { + // 父分类缺失时降级为顶级 + $tree[] = &$node; + } + } } - //返回数据 - return $data; + unset($node); + return $tree; } /** * name:修改链接 @@ -2852,6 +2880,7 @@ class Api { set_time_limit(1200); // 设置执行最大时间为20分钟 // 验证授权 $this->auth($token); + // 验证订阅 $this->check_is_subscribe(); @@ -3116,7 +3145,7 @@ class Api { $messages = [ [ "role" => "system", - "content" => "请自动检测用户输入的语言。当输入内容是中文时,翻译成英文;当输入内容不是中文时,翻译成中文。只需返回翻译后的内容,不需要额外解释或描述。" + "content" => "请自动检测用户输入的语言。当输入内容是中文时,翻译成英文;当输入内容不属于中文时,翻译成中文。只需返回翻译后的内容,不需要额外解释或描述。" ], [ "role" => "user", diff --git a/controller/api.php b/controller/api.php index d8193e7..53a3d91 100755 --- a/controller/api.php +++ b/controller/api.php @@ -519,7 +519,86 @@ function get_theme_config($api) { $api->get_theme_config(); } -//批量设置链接私有属性 +//导出链接数据 +function export_link($api) { + header('Content-Type: text/html; charset=UTF-8'); + + // 若已有树结构(之前的 export_link 方法),复用;否则自行构建。 + $tree = []; + if (method_exists($api,'export_link')) { + $tree = $api->export_link(); + } + + // 兜底:没有返回结构则直接结束 + if (!is_array($tree)) { $tree = []; } + + $now = time(); + + // 递归输出函数(模仿 Chrome 导出格式,目录在前,链接在后) + $printCategory = function ($cat, $depth = 2) use (&$printCategory, $now) { + $indent = str_repeat(' ', $depth); + $indentInner = str_repeat(' ', $depth + 1); + + $name = $cat['name']; + // 特殊处理默认分类名称 + if ($name === '默认分类') { + $name = 'OneNav默认分类'; + } + $name = htmlspecialchars($name, ENT_QUOTES); + $add_date = isset($cat['add_time']) && intval($cat['add_time'])>0 ? intval($cat['add_time']) : $now; + $last_mod = $add_date; + + echo "{$indent}

{$name}

\n"; + echo "{$indent}

\n"; + + // 子目录 + if (!empty($cat['children'])) { + foreach ($cat['children'] as $sub) { + $printCategory($sub, $depth + 1); + } + } + + // 链接 + if (!empty($cat['links'])) { + foreach ($cat['links'] as $link) { + $title = htmlspecialchars($link['title'], ENT_QUOTES); + $url = htmlspecialchars($link['url'], ENT_QUOTES); + $l_add = isset($link['add_time']) && intval($link['add_time'])>0 ? intval($link['add_time']) : $now; + echo "{$indentInner}

{$title}\n"; + } + } + + echo "{$indent}

\n"; + }; + + // 输出头部(保持与 Chrome/Edge 格式一致) + echo << + + +Bookmarks +

Bookmarks

+

+ +HTML; + + // 构造根目录“书签栏”包裹所有顶级分类 + $rootAdd = $now; + $rootMod = $now; + echo "

OneNav

\n"; + echo "

\n"; + + foreach ($tree as $topCat) { + $printCategory($topCat, 2); + } + + echo "

\n"; + echo "

\n"; +} + +// 批量设置链接私有属性 function set_link_attribute($api) { $ids = $_POST['ids']; $property = intval( $_POST['property'] ); @@ -530,33 +609,6 @@ function set_link_attribute($api) { $api->set_link_attribute($data); } -//导出链接数据 -function export_link($api) { - header('Content-Type: text/html;charset=utf8'); - $data = $api->export_link(); - //当前时间 - $current = time(); - echo <<< EOF - -从OneNav导出的书签 -

Bookmarks

-EOF; - //遍历结果 - foreach ($data as $key => $value) { - echo "

$key

\n"; - echo "

\n"; - foreach ($value as $link) { - $title = $link['title']; - $add_time = $link['add_time']; - $url = $link['url']; - echo "
$title
\n"; - } - echo "

\n"; - echo "
\n"; - - } -} - //获取用户登录状态 function check_login($api) { $token = trim($_REQUEST['token']); diff --git a/data/update.log b/data/update.log index b4a518d..e91d010 100755 --- a/data/update.log +++ b/data/update.log @@ -1,3 +1,10 @@ +2025.09.01 +1. 导出所有链接支持二级分类 +2. 删除空白的default3主题 +3. 支持删除分类图标 +4. default2主题支持后台设置每个分类要展示的数量 +5. 新增主题:BookNest + 2025.08.13 1. 后台分类列表,支持按权重排序 2. 移出default2主题侧边栏底部工具按钮 diff --git a/templates/admin/add_category.php b/templates/admin/add_category.php index 08ece36..9eb13c8 100755 --- a/templates/admin/add_category.php +++ b/templates/admin/add_category.php @@ -21,13 +21,18 @@
- +
-
- 图标对照表可参考:FontAwesome4 +
+
+
@@ -79,6 +84,11 @@