1. 注意:当分类下存在链接时,此分类不允许删除,如果需要删除分类请先前往【我的链接】删除此分类下的所有链接后再操作!
+diff --git a/README.md b/README.md index 3a8b2e1..6727b6a 100755 --- a/README.md +++ b/README.md @@ -1,6 +1,10 @@ # OneNav -OneNav是一款开源免费的书签(导航)管理程序,使用使用PHP + SQLite 3开发,界面简洁,安装简单,使用方便。OneNav可帮助你你将浏览器书签集中式管理,解决跨设备、跨平台、跨浏览器之间同步和访问困难问题,做到一处部署,随处访问。 +中文 | [English](./README_EN.md) + +___ + +OneNav是一款开源免费的书签(导航)管理程序,使用使用PHP + SQLite 3开发,界面简洁,安装简单,使用方便。OneNav可帮助你将浏览器书签集中式管理,解决跨设备、跨平台、跨浏览器之间同步和访问困难问题,做到一处部署,随处访问。 ![](https://i.bmp.ovh/imgs/2020/12/40f222b7da7a89c9.png) @@ -53,7 +57,7 @@ docker run -itd --name="onenav" -p 80:80 \ ``` * 第一个`80`是自定义访问端口,可以自行修改,第二个`80`是容器端口,请勿修改 * `/data/onenav`:本机挂载目录,用于持久存储Onenav数据 -* `0.9.30`:改成OneNav最新版本号,可以通过[releases](https://github.com/helloxz/onenav/releases)查看最新版本号 +* `0.9.31`:改成OneNav最新版本号,可以通过[releases](https://github.com/helloxz/onenav/releases)查看最新版本号 > 更多说明,请参考帮助文档:https://dwz.ovh/onenav @@ -77,7 +81,7 @@ ___ ## 鸣谢 -感谢`@落幕`/`@百素`/`@itushan`的代码贡献及主题开发,以及其它OneNav贡献者和使用者,名字太多无法一一列举,还请谅解。 +感谢`@百素`/`@itushan`的代码贡献及主题开发,以及其它OneNav贡献者和使用者,名字太多无法一一列举,还请谅解。 OneNav诞生离不开以下项目,在此表示感谢(排名不分先后)。 diff --git a/README_EN.md b/README_EN.md new file mode 100644 index 0000000..3c103d7 --- /dev/null +++ b/README_EN.md @@ -0,0 +1,91 @@ +# OneNav + +[中文](./README.md) | English + +___ + +OneNav is an open-source, free bookmark (navigation) management program developed using PHP + SQLite 3. It features a simple interface, easy installation, and convenient usage. OneNav helps you manage your browser bookmarks centrally, solving the problems of syncing and accessing across devices, platforms, and browsers. Deploy it in one place and access it from anywhere. + +![](https://i.bmp.ovh/imgs/2020/12/40f222b7da7a89c9.png) + +![](https://i.bmp.ovh/imgs/2021/04/5c46f84f158d8d3a.png) + +![](https://img.rss.ink/imgs/2022/03/cba9f1946776a8f0.png) + +![](https://img.rss.ink/imgs/2022/03/4b1d6c95484e69bc.png) + +![](https://img.rss.ink/imgs/2022/06/08/401b42279dd971f0.png) + +![](https://img.rss.ink/imgs/2022/06/07/1a2f6c3f81b64f6a.png) + +![](https://img.rss.ink/imgs/2022/06/06/172432e9d3564113.png) + +![](https://i.bmp.ovh/imgs/2020/12/abba0af566f3c16a.png) + +> **Special Note: Without the author's permission, do not use OneNav for profit-making or commercial activities, nor use it for illegal purposes. Otherwise, you will bear the corresponding legal responsibility!!!** + +## Feature Highlights + +* Supports backend management +* Supports private links +* Supports bulk import of bookmarks from Chrome/Firefox/Edge +* Supports multiple theme styles +* Supports automatic link information recognition +* Supports API +* Supports Docker deployment +* Supports uTools plugins +* Supports secondary categories +* Supports [browser extension](https://dwz.ovh/4kxn2) for Chromium kernel (plugin) +* Supports online updates +* Mobile version backend + +## Installation + +**Regular Installation:** + +1. Requires PHP environment and must support SQLite3 +2. Download and unzip the source code to the root directory of the site +3. Visit the homepage and follow the prompts to initialize username/password +4. Access the backend: `http://IP/index.php?c=login` + +**Docker Deployment:** + +```bash +docker run -itd --name="onenav" -p 80:80 \ + -v /data/onenav:/data/wwwroot/default/data \ + helloz/onenav:0.9.31 +``` +* The first `80` is the customized access port, which can be modified, and the second `80` is the container port, please do not modify +* `/data/onenav`: Local mount directory for persistent storage of Onenav data +* `0.9.31`: Replace with the latest version number of OneNav, which can be found through [releases](https://github.com/helloxz/onenav/releases) + +> For more instructions, please refer to the help document: https://dwz.ovh/onenav + +## Demo + +* **Official demo site:** [http://demo.onenav.top/](http://demo.onenav.top/index.php?c=login) +* Account/Password: `xiaoz`/`xiaoz.me` + +___ + +The following are some user demo sites of OneNav, in no particular order. + +* OneNav: [https://nav.rss.ink/](https://nav.rss.ink/) +* Thousand-line Bookmark: [http://www.52qx.club/](http://www.52qx.club/) +* Nyuji Bookmark: [http://www.1006788.com/](http://www.1006788.com/) +* DiscoveryNav: [https://nav.miooku.com/](https://nav.miooku.com/) + +## OneNav Exchange Group + +* [https://dwz.ovh/qxsul](https://dwz.ovh/qxsul) + +## Acknowledgements + +Thanks to `@Baisu`/`@itushan` for their code contributions and theme development, as well as other OneNav contributors and users. There are too many to list, so please understand. + +OneNav would not be possible without the following projects. We express our gratitude (in no particular order). + +* [WebStackPage](https://github.com/WebStackPage/WebStackPage.github.io) +* [LayUI](https://github.com/sentsin/layui) +* [Medoo](https://github.com/catfan/Medoo) +* [MDUI](https://github.com/zdhxiong/mdui) diff --git a/class/Api.php b/class/Api.php index 2582387..94a2846 100644 --- a/class/Api.php +++ b/class/Api.php @@ -303,6 +303,28 @@ class Api { $this->return_json(-2000,"failed"); } } + /** + * name:分类批量设置为私有或公有 + * + */ + public function set_cat_batch($data) { + $this->auth($token); + //获取链接ID,是一个数组 + $ids = implode(',',$data['ids']); + $property = intval($data['property']); + //拼接SQL文件 + $sql = "UPDATE on_categorys SET property = $property WHERE id IN ($ids)"; + // echo $sql; + $re = $this->db->query($sql); + //返回影响行数 + $row = $re->rowCount(); + if ( $row > 0 ){ + $this->return_json(200,"success"); + } + else{ + $this->return_json(-2000,"failed"); + } + } /** * 批量导入链接 @@ -836,7 +858,7 @@ class Api { //如果使用cookie登录成功,或者token不为空,则使用token进行验证 if( $this->is_login() || ( !empty($token) && $this->auth($token) ) ){ - $sql = "SELECT *,(SELECT name FROM on_categorys WHERE id = a.fid LIMIT 1) AS fname FROM on_categorys as a ORDER BY weight DESC,id DESC LIMIT {$limit} OFFSET {$offset}"; + $sql = "SELECT *,(SELECT name FROM on_categorys WHERE id = a.fid LIMIT 1) AS fname,(SELECT COUNT(id) FROM on_links WHERE fid = a.id) AS link_num FROM on_categorys as a ORDER BY weight DESC,id DESC LIMIT {$limit} OFFSET {$offset}"; //统计总数 $count = $this->db->count('on_categorys','*'); } @@ -844,12 +866,12 @@ class Api { else if( !empty($token) ) { $this->auth($token); //查询所有分类 - $sql = "SELECT *,(SELECT name FROM on_categorys WHERE id = a.fid LIMIT 1) AS fname FROM on_categorys as a ORDER BY weight DESC,id DESC LIMIT {$limit} OFFSET {$offset}"; + $sql = "SELECT *,(SELECT name FROM on_categorys WHERE id = a.fid LIMIT 1) AS fname,(SELECT COUNT(id) FROM on_links WHERE fid = a.id) AS link_num FROM on_categorys as a ORDER BY weight DESC,id DESC LIMIT {$limit} OFFSET {$offset}"; //统计总数 $count = $this->db->count('on_categorys','*'); } else{ - $sql = "SELECT *,(SELECT name FROM on_categorys WHERE id = a.fid LIMIT 1) AS fname FROM on_categorys as a WHERE property = 0 ORDER BY weight DESC,id DESC LIMIT {$limit} OFFSET {$offset}"; + $sql = "SELECT *,(SELECT name FROM on_categorys WHERE id = a.fid LIMIT 1) AS fname,(SELECT COUNT(id) FROM on_links WHERE fid = a.id) AS link_num FROM on_categorys as a WHERE property = 0 ORDER BY weight DESC,id DESC LIMIT {$limit} OFFSET {$offset}"; //统计总数 $count = $this->db->count('on_categorys','*',[ "property" => 0 @@ -2351,6 +2373,79 @@ class Api { $this->return_json(-2000,'','图标删除失败,请检查目录权限!'); } } + + /** + * name:优先使用POST获取数据,其次GET获取数据 + */ + protected function getData($param) { + if(isset($_POST[$param])) { + return $_POST[$param]; + } elseif(isset($_GET[$param])) { + return $_GET[$param]; + } else { + return null; + } + } + + /** + * name: 全局搜索 + */ + public function global_search() { + //验证授权 + $this->auth($token); + // 获取关键词 + $keyword = htmlspecialchars( $this->getData("keyword") ); + + // 判断关键词长度 + if( strlen($keyword) < 2 ) { + $this->return_json(-2000,'','The length of the keyword is too short.'); + } + else if( strlen($keyword) > 32 ) { + $this->return_json(-2000,'','The keyword length is too long'); + } + + $keyword = '%'.$keyword.'%'; + + // 通过标题、链接、备用链接、描述进行模糊匹配 + $data = $this->db->select('on_links', '*', [ + "OR" => [ + "title[~]" => $keyword, + "url[~]" => $keyword, + "url_standby[~]" => $keyword, + "description[~]" => $keyword, + ], + "ORDER" => [ + "weight" => "DESC" + ] + ]); + + + // 查询出分类名称 + $categorys = $this->db->select("on_categorys",[ + 'id', + 'name' + ]); + // 遍历分类,以id作为键名 + foreach ($categorys as $category) { + + $newCategorys[$category['id']] = $category['name']; + } + + // 遍历查询的数据,然后添加父级分类名称 + foreach ($data as $key => $value) { + $data[$key]['category_name'] = $newCategorys[$value['fid']]; + } + + // 返回数据 + $datas = [ + 'code' => 0, + 'msg' => '', + 'count' => count($data), + 'data' => $data + ]; + + exit( json_encode($datas) ); + } } diff --git a/controller/admin.php b/controller/admin.php index 74052c4..1ec6fdb 100755 --- a/controller/admin.php +++ b/controller/admin.php @@ -101,7 +101,7 @@ if( $page == 'setting/backup' ) { } //如果页面是修改link -if ($page == 'edit_link') { +if ( ( $page == 'edit_link' ) || ( $page === 'edit_link_new' ) ) { //查询所有分类信息,用于分类框选择 $categorys = $db->select('on_categorys','*',[ 'ORDER' => ['weigth' => 'DESC'] ]); //获取id diff --git a/controller/api.php b/controller/api.php index b6d739b..0b6c5d9 100755 --- a/controller/api.php +++ b/controller/api.php @@ -647,4 +647,18 @@ function del_link_icon() { function edit_link_row(){ global $api; $api->edit_link_row(); +} + +// 批量修改分类属性 +function set_cat_batch() { + $data['ids'] = $_POST['ids']; + $data['property'] = $_POST['property']; + global $api; + $api->set_cat_batch($data); +} + +// 全局搜索 +function global_search() { + global $api; + $api->global_search(); } \ No newline at end of file diff --git a/controller/index.php b/controller/index.php index f963c1c..d733e93 100755 --- a/controller/index.php +++ b/controller/index.php @@ -6,8 +6,8 @@ //获取当前站点信息 $site = $db->get('on_options','value',[ 'key' => "s_site" ]); $site = unserialize($site); -// 获取链接数量 -$link_num = empty( $site['link_num'] ) ? 20 : intval($site['link_num']); +// 获取链接数量,默认为30 +$link_num = empty( $site['link_num'] ) ? 30 : intval($site['link_num']); //如果已经登录,获取所有分类和链接 // 载入辅助函数 @@ -57,6 +57,7 @@ if( is_login() ){ ]); return $links; } + //根据category id查询有限链接 function get_limit_links($fid) { global $db; @@ -247,6 +248,8 @@ else{ } + + //判断文件夹是否存在 if( is_dir('templates/'.$template) ){ $tpl_dir = 'templates/'; @@ -303,5 +306,12 @@ if( $info_json ) { } } } + +// 该分类下可见的链接数量 +function get_links_number($fid){ + $number = count(get_links($fid)); + return $number; +} + //载入主题 require($tpl_dir.$template.'/index.php'); \ No newline at end of file diff --git a/data/update.log b/data/update.log index bcb558e..e536185 100755 --- a/data/update.log +++ b/data/update.log @@ -204,4 +204,41 @@ CREATE INDEX on_options_key_IDX ON on_options ("key"); 20230507 1. 修复平板电脑登录时循环重定向的BUG 2. 优化了后台页面,去除了顶部重复按钮,添加了加群按钮 -3. 后台左侧导航栏,点击后高亮显示 \ No newline at end of file +3. 后台左侧导航栏,点击后高亮显示 + +20230626 +1. 分类列表新增批量操作,可批量设置为私有或公开,对应API的 set_cat_batch 方法 +2. 优化时间戳函数,2023-05-6 11:51 优化后显示为 2023-05-06 11:51,分钟数或秒数为个位时补0 +3. 链接列表新增下级链接数量(link_num)展示 +4. 登录页面新增“忘记密码”按钮 +5. 默认主题优化 + a. 进入分类时,隐藏侧边栏,同时添加一个返回按钮 + b. 搜索框移动到顶部栏下方展示 + c. 去除导航栏上的Github按钮 + d. index.php 新增get_links_number()函数,用于获取指定分类下可见的链接数量 + e. 默认主题,更多链接优化,当分类下链接数量大于设置的数量时才显示更多 + +20230627 +1. baisuNew主题适配手机 +2. baisuNew主题优化分类链接更多显示 +3. 适配tushan2 主题 + a. 全部改为自定义图标 + b. 增加书签本地搜索 + c. 增加自定义header + d. 模板缓存指定路径为data +4. 增加全局搜索API:/index.php?c=api&method=global_search&keyword=xxx +5. 我的链接,新增关键词搜索功能,可通过链接名称、链接、描述进行匹配 +6. 修改链接改为当前窗口iframe弹窗修改 + +20230628 +1. 优化baisuNew主题 + a. 进入更多页面时,左侧遮罩不可点击 + b. 进入更多页面时,显示关闭当前页面的按钮 + c. 当分类下实际书签数量小于设置的数量时,不显示更多按钮 +2. 分类链接数量由默认20修改为30 +3. 优化baisuTwo主题 + a. 更多链接放到末尾 + b. 进入更多链接遮罩左侧导航栏 + c. 进入更多链接,显示返回按钮 +4. 优化5iux主题 +5. 优化webstack主题 \ No newline at end of file diff --git a/templates/admin/category_list.php b/templates/admin/category_list.php index 259810e..7efc6f4 100755 --- a/templates/admin/category_list.php +++ b/templates/admin/category_list.php @@ -4,6 +4,13 @@
1. 权重越大,排序越靠前
+2. 识别功能可以自动获取链接标题和描述信息,但不确保一定成功
+