Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
茶陵後
Git2
提交
118c40cc
G
Git2
项目概览
茶陵後
/
Git2
与 Fork 源项目一致
Fork自
gitcode_dev / 开源百科
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
G
Git2
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
118c40cc
编写于
2月 10, 2021
作者:
X
xjh22222228
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat: Bookmark import
上级
9b2773b5
变更
6
显示空白变更内容
内联
并排
Showing
6 changed file
with
184 addition
and
8 deletion
+184
-8
README.md
README.md
+10
-1
src/assets/img/bookmark.svg
src/assets/img/bookmark.svg
+1
-0
src/utils/bookmark.ts
src/utils/bookmark.ts
+112
-0
src/view/admin/index.component.html
src/view/admin/index.component.html
+14
-1
src/view/admin/index.component.scss
src/view/admin/index.component.scss
+21
-5
src/view/admin/index.component.ts
src/view/admin/index.component.ts
+26
-1
未找到文件。
README.md
浏览文件 @
118c40cc
...
...
@@ -48,16 +48,17 @@
-
🍰 三叉树分类、结构清晰、分类清晰。
-
🍰 支持一个网站多个分类。
-
🍰 颜值与简约并存,不再是杀马特时代。
-
🍰 完全开源,轻松定制化。
-
🍰 支持多种浏览模式,创新。
-
🍰 支持足迹记忆。
-
🍰 支持移动端浏览。
-
🍰 支持搜索查询。
-
🍰 支持自定义引擎搜索。
-
🍰 完全开源,轻松定制化。
-
🍰 多款主题切换。
-
🍰 支持暗黑模式。
-
🍰 支持快捷键操作,一步到位。
-
🍰 支持后台管理, 无需部署。
-
🍰 支持从Chrome书签导入
...
...
@@ -93,6 +94,14 @@ server {
```
## 书签导入
支持从 Chrome 书签导入,必须满足三级分类,否则会导入失败:
![](
https://raw.githubusercontent.com/xjh22222228/public/gh-pages/nav/import.png
)
浏览器打开
[
chrome://bookmarks/
](
chrome://bookmarks/
)
导出书签得到 html 文件, 接着从导航网站后台导入即可。
...
...
src/assets/img/bookmark.svg
0 → 100644
浏览文件 @
118c40cc
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg
t=
"1612860706297"
class=
"icon"
viewBox=
"0 0 1024 1024"
version=
"1.1"
xmlns=
"http://www.w3.org/2000/svg"
p-id=
"4885"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
width=
"200"
height=
"200"
><defs><style
type=
"text/css"
></style></defs><path
d=
"M823.7 79.9c13.8 0 26.8 5.4 36.6 15.2 9.8 9.8 15.2 22.8 15.2 36.6v733.8c0 13.8-5.4 26.8-15.2 36.6-9.8 9.8-22.8 15.2-36.6 15.2H200.3c-13.8 0-26.8-5.4-36.6-15.2-9.8-9.8-15.2-22.8-15.2-36.6V131.8c0-13.8 5.4-26.8 15.2-36.6 9.8-9.8 22.8-15.2 36.6-15.2h623.4"
fill=
"#FFB36E"
p-id=
"4886"
></path><path
d=
"M618.5 79.9H200.3c-13.8 0-26.8 5.4-36.6 15.2-9.8 9.8-15.2 22.8-15.2 36.6L142.6 820c0 5 92.1-22.8 93.5-18.1l382.4-722z"
fill=
"#FFBB88"
p-id=
"4887"
></path><path
d=
"M891.5 667.3c-0.1-4.3-3.7-7.8-8-7.8s-7.9 3.5-8 7.8c0 23.1-9.1 44.8-25.5 61.2-16.4 16.4-38.2 25.5-61.2 25.5H235.2c-56.5 0-102.7 46.2-102.7 102.7s46.2 102.7 102.7 102.7h553.6c56.5 0 102.7-46.2 102.7-102.7V667.4v-0.1z m-15.9 189.5c-0.1 0-0.1 0 0 0 0 23.1-9.1 44.8-25.5 61.2-16.4 16.4-38.2 25.5-61.2 25.5H235.2c-23.1 0-44.8-9.1-61.2-25.5-16.4-16.4-25.5-38.2-25.5-61.2s9.1-44.8 25.5-61.2c16.4-16.4 38.2-25.5 61.2-25.5h553.6c36.4 0 68.5-19.2 86.7-47.9v134.3c0 0.1 0 0.2 0.1 0.3z"
fill=
"#581166"
p-id=
"4888"
></path><path
d=
"M823.7 79.9c13.8 0 26.8 5.4 36.6 15.2 9.8 9.8 15.2 22.8 15.2 36.6v733.8c0 13.8-5.4 26.8-15.2 36.6-9.8 9.8-22.8 15.2-36.6 15.2H200.3c-13.8 0-26.8-5.4-36.6-15.2-9.8-9.8-15.2-22.8-15.2-36.6V131.8c0-13.8 5.4-26.8 15.2-36.6 9.8-9.8 22.8-15.2 36.6-15.2h623.4m0-16.1H200.3c-37.3 0-67.9 30.5-67.9 67.9v733.8c0 37.3 30.5 67.9 67.9 67.9h623.3c37.3 0 45.6-44.1 67.9-76.7v-725c0-37.3-30.5-67.9-67.8-67.9z"
fill=
"#581166"
p-id=
"4889"
></path><path
d=
"M875.6 856.8c-0.1 0-0.1 0 0 0 0 23.1-9.1 44.8-25.5 61.2-16.4 16.4-38.2 25.5-61.2 25.5H235.2c-23.1 0-44.8-9.1-61.2-25.5-16.4-16.4-25.5-38.2-25.5-61.2s9.1-44.8 25.5-61.2c16.4-16.4 38.2-25.5 61.2-25.5h553.6c36.4 0 68.5-19.2 86.7-47.9v134.3c0 0.1 0 0.2 0.1 0.3z"
fill=
"#FFEBDE"
p-id=
"4890"
></path><path
d=
"M883.6 722.2c-4.4 0-8 3.6-8 8v35c0 23.1-9.1 44.8-25.5 61.2-16.4 16.4-38.2 25.5-61.2 25.5H252.7c-4.4 0-8 3.6-8 8s3.6 8 8 8H792c53.5-1.6 97.1-44.6 99.6-97.9 0.1-0.5 0.1-0.9 0.1-1.4v-38.4c-0.1-4.4-3.7-8-8.1-8z"
fill=
"#581166"
p-id=
"4891"
></path><path
d=
"M445.2 867.9v81.6l-53.8-42.1-8.6-6.7-8.6 6.7-53.8 42.1v-81.6h124.8m14.7-16H305.7v128.7l77.1-60.3 77.1 60.3V851.9z"
fill=
"#581166"
p-id=
"4892"
></path><path
d=
"M445.2 867.9v81.5l-53.9-42.1-8.5-6.6-8.6 6.6-53.8 42.1v-81.5h124.8"
fill=
"#FF5855"
p-id=
"4893"
></path><path
d=
"M719.6 79.9V241H689V79.9h30.6m16-16H673V257h62.6V63.9z"
fill=
"#581166"
p-id=
"4894"
></path><path
d=
"M719.6 79.9V241h-30.7V79.9h30.7"
fill=
"#FFD18D"
p-id=
"4895"
></path><path
d=
"M719.6 368.3V754H689V368.3h30.6m16-16H673V770h62.6V352.3z"
fill=
"#581166"
p-id=
"4896"
></path><path
d=
"M719.6 368.3v385.8h-30.7V368.3h30.7"
fill=
"#FFD18D"
p-id=
"4897"
></path><path
d=
"M704.2 273.3m-103 0a103 103 0 1 0 206 0 103 103 0 1 0-206 0Z"
fill=
"#FF5855"
p-id=
"4898"
></path><path
d=
"M704.2 186.3c48 0 87 39 87 87s-39 87-87 87-87-39-87-87 39.1-87 87-87m0-16c-56.9 0-103 46.1-103 103s46.1 103 103 103 103-46.1 103-103c0.1-56.9-46.1-103-103-103z"
fill=
"#581166"
p-id=
"4899"
></path><path
d=
"M704.2 273.3m-42.3 0a42.3 42.3 0 1 0 84.6 0 42.3 42.3 0 1 0-84.6 0Z"
fill=
"#FFFFFF"
p-id=
"4900"
></path><path
d=
"M704.2 247c14.5 0 26.3 11.8 26.3 26.3s-11.8 26.3-26.3 26.3-26.3-11.8-26.3-26.3 11.8-26.3 26.3-26.3m0-16c-23.4 0-42.3 19-42.3 42.3 0 23.4 19 42.3 42.3 42.3 23.4 0 42.3-19 42.3-42.3 0.1-23.4-18.9-42.3-42.3-42.3z"
fill=
"#581166"
p-id=
"4901"
></path></svg>
\ No newline at end of file
src/utils/bookmark.ts
0 → 100644
浏览文件 @
118c40cc
// Copyright @ 2018-2021 xiejiahe. All rights reserved. MIT license.
// See https://github.com/xjh22222228/nav
import
{
INavProps
}
from
'
../types
'
import
{
websiteList
}
from
'
../store
'
export
function
parseBookmark
(
htmlStr
:
string
)
{
const
data
:
INavProps
[]
=
[]
const
importEl
=
document
.
createElement
(
'
div
'
)
importEl
.
innerHTML
=
htmlStr
const
roolDL
=
importEl
.
querySelector
(
'
dl dl
'
)
let
ii
=
0
let
jj
=
0
let
kk
=
0
try
{
// One Level
for
(
let
i
=
0
;
i
<
roolDL
.
childElementCount
;
i
++
)
{
const
iItem
=
roolDL
.
childNodes
[
i
]
as
any
if
(
iItem
&&
iItem
.
nodeName
===
'
DT
'
)
{
const
titleEl
=
iItem
.
querySelector
(
'
h3
'
)
if
(
!
titleEl
)
continue
ii
++
const
title
=
titleEl
.
textContent
const
createdAt
=
new
Date
(
titleEl
.
getAttribute
(
'
add_date
'
)
*
1000
).
toISOString
()
data
.
push
({
title
,
createdAt
,
icon
:
null
,
nav
:
[]
})
// Two Level
jj
=
0
const
DL
=
iItem
.
querySelector
(
'
dl
'
)
for
(
let
j
=
0
;
j
<
DL
.
childElementCount
;
j
++
)
{
const
jItem
=
DL
.
childNodes
[
j
]
if
(
jItem
&&
jItem
.
nodeName
===
'
DT
'
)
{
const
titleEl
=
jItem
.
querySelector
(
'
h3
'
)
if
(
!
titleEl
)
continue
jj
++
const
title
=
titleEl
.
textContent
const
createdAt
=
new
Date
(
titleEl
.
getAttribute
(
'
add_date
'
)
*
1000
).
toISOString
()
data
[
ii
-
1
].
nav
.
push
({
title
,
createdAt
,
icon
:
null
,
nav
:
[]
})
// Three Level
kk
=
0
const
DL3
=
jItem
.
querySelector
(
'
dl
'
)
for
(
let
k
=
0
;
k
<
DL3
.
childElementCount
;
k
++
)
{
const
kItem
=
DL3
.
childNodes
[
k
]
if
(
kItem
&&
kItem
.
nodeName
===
'
DT
'
)
{
const
titleEl
=
kItem
.
querySelector
(
'
h3
'
)
if
(
!
titleEl
)
continue
kk
++
const
title
=
titleEl
.
textContent
const
createdAt
=
new
Date
(
titleEl
.
getAttribute
(
'
add_date
'
)
*
1000
).
toISOString
()
data
[
ii
-
1
].
nav
[
jj
-
1
].
nav
.
push
({
title
,
createdAt
,
nav
:
[],
icon
:
null
})
// Website Level
const
DL3
=
kItem
.
querySelector
(
'
dl
'
)
for
(
let
b
=
0
;
b
<
DL3
.
childElementCount
;
b
++
)
{
const
kItem
=
DL3
.
childNodes
[
b
]
if
(
kItem
&&
kItem
.
nodeName
===
'
DT
'
)
{
const
titleEl
=
kItem
.
querySelector
(
'
a
'
)
if
(
!
titleEl
)
continue
const
title
=
titleEl
.
textContent
const
createdAt
=
new
Date
(
titleEl
.
getAttribute
(
'
add_date
'
)
*
1000
).
toISOString
()
const
icon
=
titleEl
.
getAttribute
(
'
icon
'
)
||
null
const
url
=
titleEl
.
getAttribute
(
'
href
'
)
data
[
ii
-
1
].
nav
[
jj
-
1
].
nav
[
kk
-
1
].
nav
.
push
({
name
:
title
,
createdAt
,
url
,
desc
:
''
,
urls
:
{},
icon
})
}
}
}
}
}
}
}
}
}
catch
(
error
)
{
return
error
}
const
mergeList
=
[...
data
,
...
websiteList
]
const
newList
=
[];
for
(
let
i
=
0
;
i
<
mergeList
.
length
;
i
++
)
{
const
item
=
mergeList
[
i
]
const
exists
=
newList
.
some
(
el
=>
el
.
title
===
item
.
title
)
if
(
!
exists
)
{
newList
.
push
(
item
)
}
}
return
newList
}
src/view/admin/index.component.html
浏览文件 @
118c40cc
...
...
@@ -16,11 +16,24 @@
<input
type=
"file"
name=
"file"
(change)=
"on
File
Change($event)"
(change)=
"on
Logo
Change($event)"
accept=
"image/png"
>
</label>
</div>
<div
class=
"book-wrapper"
>
<label
id=
"file"
>
<img
src=
"assets/img/bookmark.svg"
alt=
""
class=
"logo"
>
<p
style=
"white-space: nowrap; margin-top: 5px;"
>
从Chrome书签导入
</p>
<input
type=
"file"
name=
"file"
(change)=
"onBookChange($event)"
accept=
"text/html"
>
</label>
</div>
</div>
<nz-tabset
*ngIf=
"isLogin"
[nzSelectedIndex]=
"tabActive"
(nzSelectedIndexChange)=
"onTabChange($event)"
>
...
...
src/view/admin/index.component.scss
浏览文件 @
118c40cc
...
...
@@ -13,7 +13,6 @@
text-align
:
center
;
cursor
:
pointer
;
text-align
:
center
;
}
.logo
{
width
:
100px
;
...
...
@@ -22,6 +21,23 @@
border-radius
:
50%
;
cursor
:
pointer
;
}
}
.book-wrapper
{
position
:
absolute
;
top
:
-45px
;
left
:
650px
;
width
:
180px
;
text-align
:
center
;
cursor
:
pointer
;
text-align
:
center
;
.logo
{
width
:
100px
;
height
:
100px
;
cursor
:
pointer
;
}
}
input
[
type
=
"file"
]
{
display
:
none
;
...
...
src/view/admin/index.component.ts
浏览文件 @
118c40cc
...
...
@@ -15,6 +15,7 @@ import { updateFileContent } from '../../services'
import
{
DB_PATH
,
LOGO_PATH
}
from
'
../../constants
'
import
*
as
__tag
from
'
../../../data/tag.json
'
import
config
from
'
../../../nav.config
'
import
{
parseBookmark
}
from
'
../../utils/bookmark
'
const
tagMap
:
ITagProp
=
(
__tag
as
any
).
default
const
tagKeys
=
Object
.
keys
(
tagMap
)
...
...
@@ -70,7 +71,31 @@ export default class WebpComponent {
});
}
onFileChange
(
e
)
{
onBookChange
(
e
)
{
const
that
=
this
const
{
files
}
=
e
.
target
if
(
files
.
length
<=
0
)
return
;
const
file
=
files
[
0
]
const
fileReader
=
new
FileReader
()
fileReader
.
readAsText
(
file
)
fileReader
.
onload
=
function
()
{
const
html
=
this
.
result
as
string
const
result
=
parseBookmark
(
html
)
if
(
!
Array
.
isArray
(
result
))
{
that
.
notification
.
error
(
`错误: 书签解析失败`
,
`
${
result
?.
message
??
''
}
`
)
}
else
{
that
.
message
.
success
(
'
导入成功,2秒后刷新!
'
)
that
.
websiteList
=
result
setWebsiteList
(
that
.
websiteList
)
setTimeout
(()
=>
window
.
location
.
reload
(),
2000
)
}
}
}
onLogoChange
(
e
)
{
const
that
=
this
const
{
files
}
=
e
.
target
if
(
files
.
length
<=
0
)
return
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录