Browse Source

Merge pull request #157 from helloxz/dev

0.9.31
main 0.9.31
xiaoz 2 years ago committed by GitHub
parent
commit
fc96867d9e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 10
      README.md
  2. 91
      README_EN.md
  3. 101
      class/Api.php
  4. 2
      controller/admin.php
  5. 14
      controller/api.php
  6. 14
      controller/index.php
  7. 39
      data/update.log
  8. 76
      templates/admin/category_list.php
  9. 123
      templates/admin/edit_link_new.php
  10. 176
      templates/admin/link_list.php
  11. 4
      templates/admin/login.php
  12. 2
      templates/admin/setting/site.php
  13. 5
      templates/admin/static/css/new.css
  14. 51
      templates/admin/static/embed.js
  15. 67
      templates/default/index.php
  16. 6
      templates/default/info.json
  17. 25
      templates/default/static/embed.js
  18. 33
      templates/default/static/style.css
  19. 2
      version.txt

10
README.md

@ -1,6 +1,10 @@ @@ -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 \ @@ -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 @@ ___ @@ -77,7 +81,7 @@ ___
## 鸣谢
感谢`@落幕`/`@百素`/`@itushan`的代码贡献及主题开发,以及其它OneNav贡献者和使用者,名字太多无法一一列举,还请谅解。
感谢`@百素`/`@itushan`的代码贡献及主题开发,以及其它OneNav贡献者和使用者,名字太多无法一一列举,还请谅解。
OneNav诞生离不开以下项目,在此表示感谢(排名不分先后)。

91
README_EN.md

@ -0,0 +1,91 @@ @@ -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)

101
class/Api.php

@ -303,6 +303,28 @@ class Api { @@ -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 { @@ -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 { @@ -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 { @@ -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) );
}
}

2
controller/admin.php

@ -101,7 +101,7 @@ if( $page == 'setting/backup' ) { @@ -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

14
controller/api.php

@ -647,4 +647,18 @@ function del_link_icon() { @@ -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();
}

14
controller/index.php

@ -6,8 +6,8 @@ @@ -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() ){ @@ -57,6 +57,7 @@ if( is_login() ){
]);
return $links;
}
//根据category id查询有限链接
function get_limit_links($fid) {
global $db;
@ -247,6 +248,8 @@ else{ @@ -247,6 +248,8 @@ else{
}
//判断文件夹是否存在
if( is_dir('templates/'.$template) ){
$tpl_dir = 'templates/';
@ -303,5 +306,12 @@ if( $info_json ) { @@ -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');

39
data/update.log

@ -204,4 +204,41 @@ CREATE INDEX on_options_key_IDX ON on_options ("key"); @@ -204,4 +204,41 @@ CREATE INDEX on_options_key_IDX ON on_options ("key");
20230507
1. 修复平板电脑登录时循环重定向的BUG
2. 优化了后台页面,去除了顶部重复按钮,添加了加群按钮
3. 后台左侧导航栏,点击后高亮显示
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主题

76
templates/admin/category_list.php

@ -4,6 +4,13 @@ @@ -4,6 +4,13 @@
<div class="layui-body">
<!-- 内容主体区域 -->
<div class="layui-row content-body place-holder">
<!-- 说明提示框 -->
<div class="layui-col-lg12">
<div class="setting-msg">
<p>1. 注意:当分类下存在链接时,此分类不允许删除,如果需要删除分类请先前往【<a href = "/index.php?c=admin&page=link_list">我的链接</a>】删除此分类下的所有链接后再操作!</p>
</div>
</div>
<!-- 说明提示框END -->
<div class="layui-col-lg12">
<table id="category_list" lay-filter="mycategory"></table>
</div>
@ -11,8 +18,75 @@ @@ -11,8 +18,75 @@
<a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a>
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del" onclick = "">删除</a>
</script>
<!-- 表头工具栏 -->
<script type="text/html" id="catToolbar">
<div class="layui-btn-container">
<button class="layui-btn layui-btn-sm" lay-event="setPrivate">设为私有</button>
<button class="layui-btn layui-btn-sm" lay-event="setPublic">设为公开</button>
</div>
</script>
<!-- 表头工具栏END -->
</div>
<!-- 内容主题区域END -->
</div>
<?php include_once('footer.php'); ?>
<?php include_once('footer.php'); ?>
<script>
layui.use(['table','layer','form'], function(){
var table = layui.table;
var form = layui.form;
layer = layui.layer;
// 表头工具栏事件
table.on('toolbar(mycategory)', function(obj){
var id = obj.config.id;
var checkStatus = table.checkStatus(id);
var othis = lay(this);
var data = checkStatus.data;
var ids = [];
data.map(function(value,index){
ids.push(value.id);
});
switch(obj.event){
case 'setPrivate':
// 设为私有,1
set_cat_batch(ids,1);
break;
case 'setPublic':
// 设为公开,0
set_cat_batch(ids,0);
break;
};
});
});
//设置分类属性,
function set_cat_batch(ids,property) {
if( ids.length === 0 ) {
layer.msg("请先选择分类!",{icon:5});
}
else{
$.post("/index.php?c=api&method=set_cat_batch",{ids:ids,property:property},function(data,status){
if( data.code == 200 ){
layui.use(function(){
var table = layui.table;
table.reloadData('category_list', {
where: {
abc: '123456',
},
scrollPos: 'fixed', // 保持滚动条位置不变 - v2.7.3 新增
});
});
layer.msg("设置已更新!",{icon:1});
}
else{
layer.msg("设置失败!",{icon:5});
}
});
}
}
</script>

123
templates/admin/edit_link_new.php

@ -0,0 +1,123 @@ @@ -0,0 +1,123 @@
<?php include_once('s_header.php'); ?>
<div class="layui-container"">
<!-- 内容主体区域 -->
<div class="layui-row">
<!-- 说明提示框 -->
<div class="layui-col-lg12">
<div class="setting-msg">
<p>1. 权重越大,排序越靠前</p>
<p>2. 识别功能可以自动获取链接标题和描述信息,但不确保一定成功</p>
</div>
</div>
<!-- 说明提示框END -->
<div class="layui-col-lg12">
<form class="layui-form layui-form-pane">
<div class="layui-form-item" style = "display:none;">
<label class="layui-form-label">链接ID</label>
<div class="layui-input-block">
<input type="text" name="id" required lay-verify="required" value = '<?php echo $id; ?>' placeholder="请输入分类名称" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">URL</label>
<div class="layui-input-block">
<input type="url" id = "url" name="url" value = "<?php echo $link['url']; ?>" required lay-verify="required|url" placeholder="请输入有效链接" autocomplete="off" class="layui-input">
</div>
</div>
<!-- 添加备用链接 -->
<div class="layui-col-lg12">
<form class="layui-form">
<div class="layui-form-item">
<label class="layui-form-label">备用URL</label>
<div class="layui-input-block">
<input type="url" id = "url_standby" value = "<?php echo $link['url_standby']; ?>" name="url_standby" placeholder="请输入备用链接,如果没有,请留空" autocomplete="off" class="layui-input">
</div>
</div>
<!-- 备用链接END -->
<div class="layui-form-item">
<label class="layui-form-label">图标</label>
<div class="layui-input-inline" style="width:810px;">
<button type="button" id = "iconUpload" name="iconUpload" class="layui-btn"><i class="layui-icon">&#xe67c;</i>上传图标</button>
<button type="button" class="layui-btn layui-btn-danger" onclick="del_link_icon()">删除图标</button>
<!-- 显示图标 -->
<div id="show_icon">
<img src="<?php echo empty( $link['font_icon'] ) ? 'static/images/white64.png' : $link['font_icon']."?random=".rand(); ?>" alt="">
</div>
<!-- 显示图标 -->
<div class="layui-form-mid layui-word-aux" style = "float:right;">图标最小尺寸建议为 64 * 64像素,大小不超过100KB,仅部分主题支持自定义图标!</div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">图标链接</label>
<div class="layui-input-block">
<input type="url" id = "font_icon" value = "<?php echo $link['font_icon']; ?>" name="font_icon" placeholder="请输入图标链接,如果没有,请留空" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">链接名称</label>
<div class="layui-input-block">
<input type="text" id = "title" name="title" value = "<?php echo $link['title']; ?>" required lay-verify="required" placeholder="请输入链接名称" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">所属分类</label>
<div class="layui-input-block">
<select name="fid" lay-verify="required" lay-search>
<option value="<?php echo $link['fid'] ?>"><?php echo $cat_name; ?></option>
<?php foreach ($categorys as $category) {
# code...
?>
<option value="<?php echo $category['id'] ?>"><?php echo $category['name']; ?></option>
<?php } ?>
</select>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">权重</label>
<div class="layui-input-block">
<input type="number" name="weight" value = "<?php echo $link['weight']; ?>" min = "0" max = "999" value = "0" required lay-verify="required|number" placeholder="权重越高,排名越靠前,范围为0-999" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">是否私有</label>
<div class="layui-input-inline">
<input type="checkbox" name="property" value = "1" lay-skin="switch" <?php echo $link['checked'];?> lay-text="是|否">
</div>
<div class="layui-form-mid layui-word-aux">私有链接需要登录后才能查看!</div>
</div>
<div class="layui-form-item layui-form-text">
<label class="layui-form-label">描述(选填)</label>
<div class="layui-input-block">
<textarea name="description" id = "description" placeholder="请输入内容" class="layui-textarea"><?php echo $link['description']; ?></textarea>
</div>
</div>
<div class="layui-form-item">
<button class="layui-btn" lay-submit lay-filter="edit_link">更新</button>
<!-- <button class="layui-btn" lay-submit lay-filter="get_link_info">识别</button> -->
<a href="javascript:;" class="layui-btn" onclick="get_link_info()">识别</a>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</form>
</div>
</div>
<!-- 内容主题区域END -->
</div>
<script>
$(document).ready(function(){
let font_icon = $("#font_icon").val();
console.log(font_icon);
if( font_icon == "" ) {
set_icon_name();
}
});
</script>

176
templates/admin/link_list.php

@ -10,19 +10,32 @@ @@ -10,19 +10,32 @@
<div class="layui-form-item">
<div class="layui-inline">
<div class="layui-input-inline">
<select name="fid" lay-verify="" lay-search id = "fid">
<option value="">请选择一个分类</option>
<?php foreach( $categorys AS $category ){ ?>
<option value="<?php echo $category['id'] ?>"><?php echo $category['name']; ?></option>
<?php } ?>
</select>
<div class="layui-input-inline">
<select name="fid" lay-verify="" lay-search id = "fid">
<option value="">请选择一个分类</option>
<?php foreach( $categorys AS $category ){ ?>
<option value="<?php echo $category['id'] ?>"><?php echo $category['name']; ?></option>
<?php } ?>
</select>
</div>
<div class="layui-input-inline" style="width: 100px;">
<button class="layui-btn" lay-submit lay-filter="screen_link">查询此分类下的链接</button>
</div>
</div>
<div class="layui-input-inline" style="width: 100px;">
<button class="layui-btn" lay-submit lay-filter="screen_link">查询此分类下的链接</button>
</div>
<div style="width:50px;display: inline-block;"></div>
<!-- 顶部搜索 -->
<div class="layui-inline">
<div class="layui-input-inline">
<input type="text" name="keyword" id="keyword" lay-verify="required" placeholder="请输入关键词" autocomplete="off" class="layui-input">
</div>
<div class="layui-input-inline" style="width: 100px;">
<button class="layui-btn" lay-submit lay-filter="search_keyword">搜索</button>
</div>
</div>
<!-- 顶部搜索END -->
</div>
</form>
</div>
@ -36,6 +49,7 @@ @@ -36,6 +49,7 @@
<button class="layui-btn layui-btn-sm" lay-event="readmoredata">批量修改分类</button>
<button class="layui-btn layui-btn-sm" lay-event="set_private">设为私有</button>
<button class="layui-btn layui-btn-sm" lay-event="set_public">设为公有</button>
<button class="layui-btn layui-btn-sm" lay-event="reset_query">重置查询</button>
<!-- <button class="layui-btn layui-btn-sm" lay-event="getCheckLength">获取选中数目</button>
<button class="layui-btn layui-btn-sm" lay-event="isAll">验证是否全选</button> -->
</div>
@ -54,8 +68,9 @@ @@ -54,8 +68,9 @@
</div>
<script>
layui.use(['table'], function(){
layui.use(['table','form'], function(){
var table = layui.table;
var form = layui.form;
// 编辑单行
table.on('edit(mylink)',function(obj){
@ -98,8 +113,143 @@ layui.use(['table'], function(){ @@ -98,8 +113,143 @@ layui.use(['table'], function(){
layer.msg("修改失败!",{icon:5});
}
});
})
});
// 提交搜索
form.on('submit(search_keyword)', function(data){
console.log(data.field);
let keyword = data.field.keyword;
//渲染链接列表
table.render({
elem: '#link_list'
,height: 530
,url: 'index.php?c=api&method=global_search&keyword=' + keyword //数据接口
,method: 'post'
,toolbar: '#linktool'
,cols: [[ //表头
{type:'checkbox'} //开启复选框
,{field: 'id', title: 'ID', width:80, sort: true}
,{field: 'font_icon', title: '图标', width:60, templet:function(d){
if(d.font_icon == null || d.font_icon == "")
{
return '<img src="static/images/default.png" width="28" height="28">';
}
else
{
let random = getRandStr(4);
let font_icon = d.font_icon;
return `<img src="${font_icon}?random=${random}" width="28" height="28">`;
}
}}
// ,{field: 'fid', title: '分类ID',sort:true, width:90}
,{field: 'category_name', title: '所属分类',sort:true,width:120}
,{field: 'url', title: 'URL',width:140,templet:function(d){
var url = '<a target = "_blank" href = "' + d.url + '" title = "' + d.url + '">' + d.url + '</a>';
return url;
}}
,{field: 'title', title: '链接标题', width:140,edit: 'text'}
,{field: 'add_time', title: '添加时间', width:148, sort: true,templet:function(d){
var add_time = timestampToTime(d.add_time);
return add_time;
}}
,{field: 'up_time', title: '修改时间', width:148,sort:true,templet:function(d){
if(d.up_time == null){
return '';
}
else{
var up_time = timestampToTime(d.up_time);
return up_time;
}
}}
,{field: 'weight', title: '权重', width: 75,sort:true,edit: 'text'}
,{field: 'property', title: '私有', width: 80, sort: true,templet: function(d){
if(d.property == 1) {
return '<button type="button" class="layui-btn layui-btn-xs"></button>';
}
else {
return '<button type="button" class="layui-btn layui-btn-xs layui-btn-danger"></button>';
}
}}
,{field: 'click', title: '点击数',width:90,sort:true}
,{fixed: 'right', title:'操作', toolbar: '#link_operate'}
]]
});
// 渲染链接列表END
return false;
});
});
// 重置查询
function reset_query(){
// 清空关键词
$("#keyword").val("");
layui.use(['table'], function(){
var table = layui.table;
//渲染链接列表
table.render({
elem: '#link_list'
,height: 530
,url: 'index.php?c=api&method=link_list'
,method: 'post'
,page: true //开启分页
,toolbar: '#linktool'
,cols: [[ //表头
{type:'checkbox'} //开启复选框
,{field: 'id', title: 'ID', width:80, sort: true}
,{field: 'font_icon', title: '图标', width:60, templet:function(d){
if(d.font_icon == null || d.font_icon == "")
{
return '<img src="static/images/default.png" width="28" height="28">';
}
else
{
let random = getRandStr(4);
let font_icon = d.font_icon;
return `<img src="${font_icon}?random=${random}" width="28" height="28">`;
}
}}
// ,{field: 'fid', title: '分类ID',sort:true, width:90}
,{field: 'category_name', title: '所属分类',sort:true,width:120}
,{field: 'url', title: 'URL',width:140,templet:function(d){
var url = '<a target = "_blank" href = "' + d.url + '" title = "' + d.url + '">' + d.url + '</a>';
return url;
}}
,{field: 'title', title: '链接标题', width:140,edit: 'text'}
,{field: 'add_time', title: '添加时间', width:148, sort: true,templet:function(d){
var add_time = timestampToTime(d.add_time);
return add_time;
}}
,{field: 'up_time', title: '修改时间', width:148,sort:true,templet:function(d){
if(d.up_time == null){
return '';
}
else{
var up_time = timestampToTime(d.up_time);
return up_time;
}
}}
,{field: 'weight', title: '权重', width: 75,sort:true,edit: 'text'}
,{field: 'property', title: '私有', width: 80, sort: true,templet: function(d){
if(d.property == 1) {
return '<button type="button" class="layui-btn layui-btn-xs"></button>';
}
else {
return '<button type="button" class="layui-btn layui-btn-xs layui-btn-danger"></button>';
}
}}
,{field: 'click', title: '点击数',width:90,sort:true}
,{fixed: 'right', title:'操作', toolbar: '#link_operate'}
]]
});
// 渲染链接列表END
})
}
</script>

4
templates/admin/login.php

@ -41,6 +41,7 @@ @@ -41,6 +41,7 @@
<input type="submit" lay-submit lay-filter="new_login" class="submit" value="登录">
</div>
</form>
<div class = "forgot_pass"> <a href="https://dwz.ovh/isbyv" target = "_blank" rel = "nofollow">忘记密码?</a> </div>
</div>
</div>
</section>
@ -61,8 +62,9 @@ @@ -61,8 +62,9 @@
<input type="submit" lay-submit lay-filter="new_mobile_login" class="submit" value="登录">
</div>
</form>
<div style = "padding-left:30px;"> <a style="color:#FFFFFF;" href="https://dwz.ovh/isbyv" target = "_blank" rel = "nofollow">忘记密码?</a> </div>
</div>
<footer>© 2022 Powered by <a style = "color:#FFFFFF;padding-left:6px;" href = "https://www.onenav.top/" target = "_blank" title = "开源免费书签管理系统"> OneNav</a></footer>
<footer>© 2023 Powered by <a style = "color:#FFFFFF;padding-left:6px;" href = "https://www.onenav.top/" target = "_blank" title = "开源免费书签管理系统"> OneNav</a></footer>
</body>
<script>
//自己封装的弹出框

2
templates/admin/setting/site.php

@ -64,7 +64,7 @@ @@ -64,7 +64,7 @@
<div class="layui-input-inline">
<input type="number" name="link_num" value = "<?php echo $site['link_num']; ?>" autocomplete="off" placeholder="分类需要展示的链接数量" class="layui-input">
</div>
<div class="layui-form-mid layui-word-aux">指的是首页单个分类下需要展示的链接数量,默认20,值越低,性能越好</div>
<div class="layui-form-mid layui-word-aux">指的是首页单个分类下需要展示的链接数量,默认30,值越低,性能越好</div>
</div>
<div class="layui-form-item layui-form-text">

5
templates/admin/static/css/new.css

@ -1 +1,6 @@ @@ -1 +1,6 @@
*{margin:0;padding:0}.login{opacity:0;width:100vw;height:100vh;background:url("../image/bg.svg") no-repeat center/cover;display:flex;align-items:center;justify-content:center}.login>.root{position:absolute;width:70%;height:600px;transition:all 0.3s;box-shadow:0px 0px 10px rgba(250,250,250,0.227);border-radius:15px;overflow:hidden;display:flex}.login>.root .left{transition:all 0.3s;position:relative;width:50%;background:#000}.login>.root .left>.cover{position:absolute;display:block;width:100%;height:100%;object-fit:cover}.login>.root .right{transition:all 0.5s;min-width:550px;width:50%;display:flex;flex-direction:column;background:#fbfbfb}.login>.root .right>h2{margin:40px 20px 0px;text-align:center;font-size:32px;font-family:Source Han Sans CN-Bold, Source Han Sans CN;font-weight:bold;color:#2a2a2a;line-height:48px}.login>.root .right>h2:hover{color:#0088ea}.login>.root .right .login_frame{display:flex;justify-content:center}.login>.root .right .login_box{margin-top:100px;padding:20px;width:320px;height:300px;background:#ffffff;box-shadow:0px 3px 8px 1px rgba(0,0,0,0.16);border-radius:16px 16px 16px 16px;opacity:1}.login>.root .right .login_box>h4{width:411px;height:24px;font-size:24px;font-family:Source Han Sans CN-Regular, Source Han Sans CN;font-weight:400;color:#000000;line-height:24px}.login>.root .right .login_box>h6{margin-top:10px;width:411px;height:24px;font-size:16px;font-family:Helvetica Neue-常规体, Helvetica Neue;font-weight:normal;color:#323232;line-height:24px;margin-bottom:30px}.login>.root .right .login_box>form>.inp{margin-bottom:15px;display:flex;flex-direction:column}.login>.root .right .login_box>form>.inp>.label{height:16px;font-size:12px;font-family:Source Han Sans CN-Bold, Source Han Sans CN;font-weight:bold;color:#1a1a1a;line-height:16px;margin-bottom:5px}.login>.root .right .login_box>form>.inp>input{width:calc(100% - 30px);height:35px;border-radius:8px 8px 8px 8px;opacity:1;outline:none;border:1px solid #bfbfbf;padding:0px 15px}.login>.root .right .login_box>form>.submit{margin-top:25px}.login>.root .right .login_box>form>.submit>input{width:100%;height:40px;background:#0088ea;outline:none;border:1px solid #0088ea;border-radius:8px;font-size:16px;font-family:Source Han Sans CN-Regular, Source Han Sans CN;font-weight:400;color:#ffffff}.login .mobile{display:none}@media screen and (max-width: 1278px){.login .left{display:none}.login .right{min-width:100% !important;width:100%}}@media screen and (max-width: 658px){.login .root{display:none !important}.login .mobile{width:100%;height:100%;position:absolute;display:block}.login .mobile>h1{margin:20px;color:#ffffff}.login .mobile>form{position:relative;margin:15px;padding:15px;margin-top:100px}.login .mobile>form>.inp{margin-bottom:15px;display:flex;flex-direction:column}.login .mobile>form>.inp>.label{height:16px;font-size:13px;font-family:Source Han Sans CN-Bold, Source Han Sans CN;font-weight:bold;color:#1a1a1a;line-height:16px;margin-bottom:5px;color:#ffffff}.login .mobile>form>.inp>input{width:calc(100% - 30px);height:40px;border-radius:8px 8px 8px 8px;opacity:1;outline:none;border:1px solid #bfbfbf;padding:0px 15px}.login .mobile>form>.submit{margin-top:25px}.login .mobile>form>.submit>input{width:100%;height:40px;background:#0088ea;outline:none;border:1px solid #0088ea;border-radius:8px;font-size:16px;font-family:Source Han Sans CN-Regular, Source Han Sans CN;font-weight:400;color:#ffffff}}footer{width:100%;position:absolute;z-index:9;bottom:10px;display:flex;font-size:12px;align-items:center;justify-content:center;color:#9e9e9e}footer>img{margin-right:5px;width:20px;height:20px}
.forgot_pass{
margin-top:14px;
padding-left:1px;
margin-bottom:14px;
}

51
templates/admin/static/embed.js

@ -92,17 +92,20 @@ layui.use(['element','table','layer','form','upload','iconHhysFa'], function(){ @@ -92,17 +92,20 @@ layui.use(['element','table','layer','form','upload','iconHhysFa'], function(){
//第一个实例
table.render({
elem: '#category_list'
,height: 500
elem: '#category_list',
toolbar: '#catToolbar',
height: 525
,url: 'index.php?c=api&method=category_list' //数据接口
,page: true //开启分页
,cols: [[ //表头
{type: 'checkbox', fixed: 'left'},
{field: 'id', title: 'ID', width:80, sort: true, fixed: 'left'}
,{field: 'font_icon', title: '图标', width:60, templet: function(d){
return '<i class="fa-lg '+d.font_icon+'"></i>';
}}
,{field: 'name', title: '分类名称', width:160}
,{field: 'fname', title: '父级分类', width:160}
,{field: 'link_num', title: '链接数量', width:110,sort:true}
,{field: 'add_time', title: '添加时间', width:160, sort: true,templet:function(d){
var add_time = timestampToTime(d.add_time);
return add_time;
@ -327,6 +330,9 @@ layui.use(['element','table','layer','form','upload','iconHhysFa'], function(){ @@ -327,6 +330,9 @@ layui.use(['element','table','layer','form','upload','iconHhysFa'], function(){
case 'isAll':
layer.msg(checkStatus.isAll ? '全选': '未全选');
break;
case "reset_query":
reset_query();
break;
//自定义头工具栏右侧图标 - 提示
case 'LAYTABLE_TIPS':
@ -352,7 +358,23 @@ layui.use(['element','table','layer','form','upload','iconHhysFa'], function(){ @@ -352,7 +358,23 @@ layui.use(['element','table','layer','form','upload','iconHhysFa'], function(){
layer.close(index);
});
} else if(obj.event === 'edit'){
window.location.href = '/index.php?c=admin&page=edit_link&id=' + obj.data.id;
// window.location.href = '/index.php?c=admin&page=edit_link&id=' + obj.data.id;
let height = window.innerHeight;
if( height >= 800 ) {
height = 800;
}
else{
height = 700;
}
// 改成iframe编辑
layer.open({
type: 2,
title: '编辑链接',
shadeClose: true,
maxmin: true, //开启最大化最小化按钮
area: ['1000px', height + 'px'],
content: '/index.php?c=admin&page=edit_link_new&id=' + obj.data.id
});
}
});
@ -903,14 +925,21 @@ function get_link_info() { @@ -903,14 +925,21 @@ function get_link_info() {
}
function timestampToTime(timestamp) {
var date = new Date(timestamp * 1000); //时间戳为10位需*1000,时间戳为13位的话不需乘1000
Y = date.getFullYear() + '-' ;
M = (date.getMonth()+1 < 10 ? '0' +(date.getMonth()+1) : date.getMonth()+1) + '-' ;
D = date.getDate() + ' ' ;
h = date.getHours() + ':' ;
m = date.getMinutes();
s = date.getSeconds();
return Y+M+D+h+m;
// 将时间戳转换为毫秒
let timestampInMilliseconds = timestamp * 1000;
// 创建新的Date对象
let date = new Date(timestampInMilliseconds);
// 获取年、月、日、小时、分钟,月份需要+1,因为Date对象中月份从0开始计数
let year = date.getFullYear();
let month = ("0" + (date.getMonth() + 1)).slice(-2);
let day = ("0" + date.getDate()).slice(-2);
let hours = ("0" + date.getHours()).slice(-2);
let minutes = ("0" + date.getMinutes()).slice(-2);
// 生成并返回格式化的日期字符串
return `${year}-${month}-${day} ${hours}:${minutes}`;
}
function del_category(id){

67
templates/default/index.php

@ -45,23 +45,9 @@ @@ -45,23 +45,9 @@
<a href="/" class = "mdui-typo-headline" title = "<?php echo $site['description'] ?>"><span class="mdui-typo-title default-title"><h1><?php echo $site['title']; ?></h1></span></a>
<div class="mdui-toolbar-spacer"></div>
<!-- 新版搜索框 -->
<div class="mdui-col-md-3 mdui-col-xs-6">
<div class="mdui-textfield mdui-textfield-floating-label">
<!-- <label class="mdui-textfield-label">输入书签关键词进行搜索</label> -->
<input class="mdui-textfield-input search" style = "color:#FFFFFF;" placeholder="输入书签关键词进行搜索" type="text" />
<i class="mdui-icon material-icons" style = "position:absolute;right:2px;">search</i>
</div>
</div>
<!-- 新版搜索框END -->
<a class = "mdui-hidden-xs" href="https://github.com/helloxz/onenav" rel = "nofollow" target="_blank" class="mdui-btn mdui-btn-icon mdui-ripple mdui-ripple-white" mdui-tooltip="{content: '查看 Github'}">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 36 36" enable-background="new 0 0 36 36" xml:space="preserve" class="mdui-icon" style="width: 24px;height:24px;">
<path fill-rule="evenodd" clip-rule="evenodd" fill="#ffffff" d="M18,1.4C9,1.4,1.7,8.7,1.7,17.7c0,7.2,4.7,13.3,11.1,15.5
c0.8,0.1,1.1-0.4,1.1-0.8c0-0.4,0-1.4,0-2.8c-4.5,1-5.5-2.2-5.5-2.2c-0.7-1.9-1.8-2.4-1.8-2.4c-1.5-1,0.1-1,0.1-1
c1.6,0.1,2.5,1.7,2.5,1.7c1.5,2.5,3.8,1.8,4.7,1.4c0.1-1.1,0.6-1.8,1-2.2c-3.6-0.4-7.4-1.8-7.4-8.1c0-1.8,0.6-3.2,1.7-4.4
c-0.2-0.4-0.7-2.1,0.2-4.3c0,0,1.4-0.4,4.5,1.7c1.3-0.4,2.7-0.5,4.1-0.5c1.4,0,2.8,0.2,4.1,0.5c3.1-2.1,4.5-1.7,4.5-1.7
c0.9,2.2,0.3,3.9,0.2,4.3c1,1.1,1.7,2.6,1.7,4.4c0,6.3-3.8,7.6-7.4,8c0.6,0.5,1.1,1.5,1.1,3c0,2.2,0,3.9,0,4.5
c0,0.4,0.3,0.9,1.1,0.8c6.5-2.2,11.1-8.3,11.1-15.5C34.3,8.7,27,1.4,18,1.4z"></path>
</svg>
<?php
if( is_login() ) {
?>
@ -166,16 +152,22 @@ @@ -166,16 +152,22 @@
<!--正文内容部分-->
<div class="<?php echo ( $theme_config->full_width_mode == "off") ? "mdui-container" : "mdui-container-fluid"; ?>">
<!-- 搜索框 -->
<!-- <div class="mdui-row">
<div class="mdui-col-xs-12" style = "z-index:99999;">
<div class="mdui-row">
<div class="mdui-col-md-12 mdui-col-xs-12 mdui-col-xl-6 mdui-col-offset-xl-3">
<div class="mdui-textfield mdui-textfield-floating-label">
<label class="mdui-textfield-label">输入书签关键词进行搜索</label>
<input class="mdui-textfield-input search" type="text" />
<!-- <label class="mdui-textfield-label">输入书签关键词进行搜索</label> -->
<input class="mdui-textfield-input search" placeholder="输入书签关键词进行搜索" type="text" />
<i class="mdui-icon material-icons" style = "position:absolute;right:2px;">search</i>
</div>
</div>
</div> -->
</div>
<!-- 搜索框END -->
<div class="mdui-row">
<?php
if( isset($_GET['cid']) ) {
echo '<a href="/" id = "backButton"> << 返回</a>';
}
?>
<!-- 遍历分类目录 -->
<?php foreach ( $categorys as $category ) {
$fid = $category['id'];
@ -192,11 +184,6 @@ @@ -192,11 +184,6 @@
<div id = "category-<?php echo $category['id']; ?>" class = "mdui-col-xs-12 mdui-typo-title cat-title">
<?php echo $font_icon; ?>
<?php echo htmlspecialchars_decode($category['name']); ?> <?php echo $property; ?>
<?php if(empty($cid)) { ?>
<span class="more-link">
<a href="/index.php?cid=<?php echo $category['id']; ?>" title = "点此查看此分类下的全部链接">>></a>
</span>
<?php } ?>
</div>
<!-- 遍历链接 -->
<?php
@ -246,6 +233,34 @@ @@ -246,6 +233,34 @@
</a>
<?php } ?>
<!-- 遍历链接END -->
<!-- 更多 -->
<?php
if( !isset($_GET['cid']) && get_links_number($fid) > $link_num ) {
?>
<a href="/index.php?cid=<?php echo $category['id']; ?>" title = "点此可查看该分类下的所有链接">
<div class="mdui-col-lg-2 mdui-col-md-3 mdui-col-sm-4 mdui-col-xs-6 link-space">
<!--定义一个卡片-->
<div class="mdui-card link-line mdui-hoverable">
<div class="mdui-card-primary" style = "padding-top:16px;">
<div class="mdui-card-primary-title link-title">
<!-- 网站图标显示方式 -->
<img src="/index.php?c=ico&text=更" alt="" width="16" height="16" />
<span class="link_title">查看更多>></span>
</div>
</div>
<!-- 卡片的内容end -->
<div class="mdui-card-content mdui-text-color-black-disabled" style="padding-top:0px;">
<span class="link-content">
点此可查看该分类下的所有链接!
</span>
</div>
</div>
<!--卡片END-->
</div>
</a>
<!-- 更多END -->
<?php } ?>
<?php } ?>
</div>
<!-- row end -->

6
templates/default/info.json

@ -3,13 +3,13 @@ @@ -3,13 +3,13 @@
"description": "OneNav默认主题",
"homepage": "https:\/\/www.xiaoz.me",
"help_url":"https://dwz.ovh/gnae4",
"version": "0.9.29",
"update": "2023\/05\/06",
"version": "0.9.31",
"update": "2023\/06\/28",
"author": "xiaoz<xiaoz93@outlook.com>",
"screenshot": "https:\/\/img.rss.ink\/imgs\/2022\/03\/42ed3ef2c4a50f6d.png",
"demo":"",
"require":{
"min":"0.9.30",
"min":"0.9.31",
"max":""
},
"config": {

25
templates/default/static/embed.js

@ -284,3 +284,28 @@ function change_theme() { @@ -284,3 +284,28 @@ function change_theme() {
window.location.href = "/";
}
$(document).ready(function(){
let $ = mdui.$;
var inst = new mdui.Drawer('#drawer');
var cid = getURLParam('cid');
console.log(cid);
if( cid !== null ) {
// 关闭左侧抽屉栏
inst.close();
}
});
// 获取参数值
function getURLParam(paramName) {
// 获取URL的查询参数部分
var queryString = window.location.search;
// 创建一个新的URLSearchParams实例
var urlParams = new URLSearchParams(queryString);
// 使用get()方法来获取指定参数的值
var paramValue = urlParams.get(paramName);
return paramValue;
}

33
templates/default/static/style.css

@ -142,8 +142,8 @@ footer a{ @@ -142,8 +142,8 @@ footer a{
background-color: #FF2377;
}
.cat-title{
margin-top: -50px;
padding-top:68px;
margin-top: -40px;
padding-top:79px;
/* margin-bottom: 0; */
}
@ -172,4 +172,33 @@ footer a{ @@ -172,4 +172,33 @@ footer a{
.more-link a{
color:#31bdec;
text-decoration: none;
}
#backButton {
background-color: #f2f2f2; /* 淡灰色 */
color: #333; /* 按钮文本颜色为深灰色 */
border: none;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 4px 2px;
cursor: pointer;
border-radius: 4px;
transition-duration: 0.4s;
box-shadow: 0 2px 3px rgba(0, 0, 0, 0.1); /* 添加阴影效果 */
z-index:9999;
display: block;
position: relative;
}
#backButton:hover {
background-color: #e0e0e0; /* 悬停时的颜色稍暗 */
color: #000; /* 悬停时文本颜色为黑色 */
}
.search{
z-index:9999;
position: relative;
}

2
version.txt

@ -1 +1 @@ @@ -1 +1 @@
v0.9.30-20230508
v0.9.31-20230628
Loading…
Cancel
Save