Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
兴科Sinco
开源百科
提交
b1846d48
开
开源百科
项目概览
兴科Sinco
/
开源百科
与 Fork 源项目一致
Fork自
GitCode官方 / 开源百科
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
开
开源百科
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
b1846d48
编写于
3月 28, 2021
作者:
X
xjh22222228
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat(#77): Bookmark Merge
上级
f79e8aa3
变更
6
显示空白变更内容
内联
并排
Showing
6 changed file
with
121 addition
and
48 deletion
+121
-48
README.md
README.md
+10
-2
src/services/index.ts
src/services/index.ts
+16
-23
src/utils/bookmark.ts
src/utils/bookmark.ts
+66
-8
src/utils/http.ts
src/utils/http.ts
+24
-11
src/view/admin/index.component.html
src/view/admin/index.component.html
+3
-3
src/view/admin/index.component.ts
src/view/admin/index.component.ts
+2
-1
未找到文件。
README.md
浏览文件 @
b1846d48
...
...
@@ -65,8 +65,9 @@
## 部署
推荐使用
`github pages`
服务, 这样就不需要提供服务器, 并且项目里自带了自动化部署服务,
像数
`321`
一样简单。
像数
`321`
一样简单。
#### 方式一(gh-pages免费)
1、Fork 当前项目。
2、
[
https://github.com/settings/tokens
](
https://github.com/settings/tokens
)
申请 token, 勾选相应的权限, 如果不懂就全部选中,复制并保存Token。
...
...
@@ -79,6 +80,13 @@
6、5分钟后打开 https://用户名.github.io/nav 就能看到一个非常强大的导航网站了。
### 推荐方式二(Vercel免费)
和方式一的步骤一样,除了第4步不用。
具体使用跟着步骤走即可
[
https://github.com/apps/vercel
](
https://github.com/apps/vercel
)
注:如果想部署到自己的域名,那么以上教程同样适合,因为它提供了自动化部署, 之后可以通过
`CNAME`
或
`反向代理`
实现:
...
...
@@ -97,7 +105,7 @@ server {
## 书签导入
支持从 Chrome 书签导入(WebKit内核应该都是支持的~),会自动检测满足三级分类的导航,其他一律
跳过
:
支持从 Chrome 书签导入(WebKit内核应该都是支持的~),会自动检测满足三级分类的导航,其他一律
设为未分类
:
![](
https://raw.githubusercontent.com/xjh22222228/public/gh-pages/nav/import.png
)
...
...
src/services/index.ts
浏览文件 @
b1846d48
...
...
@@ -3,7 +3,6 @@
import
config
from
'
../../nav.config
'
import
http
from
'
../utils/http
'
import
{
encode
}
from
'
js-base64
'
import
{
getToken
}
from
'
../utils/user
'
const
{
gitRepoUrl
}
=
config
const
s
=
gitRepoUrl
.
split
(
'
/
'
)
...
...
@@ -11,7 +10,6 @@ const DEFAULT_BRANCH = config.branch
export
const
authorName
=
s
[
s
.
length
-
2
]
export
const
repoName
=
s
[
s
.
length
-
1
]
const
token
=
getToken
()
// 验证Token
export
function
verifyToken
(
token
:
string
)
{
...
...
@@ -23,12 +21,8 @@ export function verifyToken(token: string) {
}
// 获取文件信息
export
function
getFileContent
(
path
:
string
,
authToken
?:
string
,
branch
:
string
=
DEFAULT_BRANCH
)
{
const
_token
=
`
${
authToken
?
authToken
:
token
}
`
.
trim
()
export
function
getFileContent
(
path
:
string
,
branch
:
string
=
DEFAULT_BRANCH
)
{
return
http
.
get
(
`/repos/
${
authorName
}
/
${
repoName
}
/contents/
${
path
}
`
,
{
headers
:
{
Authorization
:
`token
${
_token
}
`
},
params
:
{
ref
:
branch
}
...
...
@@ -44,38 +38,37 @@ type Iupdate = {
isEncode
?:
boolean
}
export
async
function
updateFileContent
(
{
message
,
content
,
path
,
branch
=
DEFAULT_BRANCH
,
isEncode
=
true
}:
Iupdate
,
authToken
?:
string
{
message
,
content
,
path
,
branch
=
DEFAULT_BRANCH
,
isEncode
=
true
}:
Iupdate
,
)
{
const
_token
=
`
${
authToken
?
authToken
:
token
}
`
.
trim
()
const
fileInfo
=
await
getFileContent
(
path
,
_token
,
branch
)
const
fileInfo
=
await
getFileContent
(
path
,
branch
)
return
http
.
put
(
`/repos/
${
authorName
}
/
${
repoName
}
/contents/
${
path
}
`
,
{
message
:
`rebot(CI):
${
message
}
`
,
branch
,
content
:
isEncode
?
encode
(
content
)
:
content
,
sha
:
fileInfo
.
data
.
sha
},
{
headers
:
{
Authorization
:
`token
${
_token
}
`
}
})
}
export
async
function
createFile
(
{
message
,
content
,
path
,
branch
=
DEFAULT_BRANCH
,
isEncode
=
true
}:
Iupdate
,
authToken
?:
string
{
message
,
content
,
path
,
branch
=
DEFAULT_BRANCH
,
isEncode
=
true
}:
Iupdate
,
)
{
const
_token
=
`
${
authToken
?
authToken
:
token
}
`
.
trim
()
return
http
.
put
(
`/repos/
${
authorName
}
/
${
repoName
}
/contents/
${
path
}
`
,
{
message
:
`rebot(CI):
${
message
}
`
,
branch
,
content
:
isEncode
?
encode
(
content
)
:
content
,
},
{
headers
:
{
Authorization
:
`token
${
_token
}
`
}
})
}
...
...
src/utils/bookmark.ts
浏览文件 @
b1846d48
...
...
@@ -5,11 +5,52 @@ import { INavProps } from '../types'
import
{
websiteList
}
from
'
../store
'
export
function
parseBookmark
(
htmlStr
:
string
)
{
const
copyWebList
=
JSON
.
parse
(
JSON
.
stringify
(
websiteList
))
const
data
:
INavProps
[]
=
[]
const
importEl
=
document
.
createElement
(
'
div
'
)
importEl
.
innerHTML
=
htmlStr
const
roolDL
=
importEl
.
querySelector
(
'
dl dl
'
)
// 未分类
let
hasNoCate
=
false
const
cateCreateAt
=
new
Date
().
toISOString
()
const
noCate
:
INavProps
=
{
title
:
'
未分类
'
,
createdAt
:
cateCreateAt
,
nav
:
[
{
createdAt
:
cateCreateAt
,
title
:
'
未分类
'
,
nav
:
[
{
title
:
'
未分类
'
,
nav
:
[]
}
]
}
]
}
function
findA
(
node
:
Element
)
{
let
a
=
node
.
firstElementChild
if
(
!
a
&&
a
.
nodeName
===
'
a
'
)
return
hasNoCate
=
true
const
name
=
a
.
textContent
const
createdAt
=
new
Date
(
Number
(
a
.
getAttribute
(
'
add_date
'
))
*
1000
).
toISOString
()
const
icon
=
a
.
getAttribute
(
'
icon
'
)
||
null
const
url
=
a
.
getAttribute
(
'
href
'
)
noCate
.
nav
[
0
].
nav
[
0
].
nav
.
push
({
name
,
createdAt
,
icon
,
url
,
urls
:
{},
desc
:
''
,
rate
:
5
})
}
let
ii
=
0
let
jj
=
0
let
kk
=
0
...
...
@@ -18,6 +59,7 @@ export function parseBookmark(htmlStr: string) {
for
(
let
i
=
0
;
i
<
roolDL
.
childElementCount
;
i
++
)
{
const
iItem
=
roolDL
.
childNodes
[
i
]
as
any
if
(
iItem
&&
iItem
.
nodeName
===
'
DT
'
)
{
findA
(
iItem
)
const
titleEl
=
iItem
.
querySelector
(
'
h3
'
)
if
(
!
titleEl
)
continue
ii
++
...
...
@@ -36,6 +78,7 @@ export function parseBookmark(htmlStr: string) {
for
(
let
j
=
0
;
j
<
DL
.
childElementCount
;
j
++
)
{
const
jItem
=
DL
.
childNodes
[
j
]
if
(
jItem
&&
jItem
.
nodeName
===
'
DT
'
)
{
findA
(
jItem
)
const
titleEl
=
jItem
.
querySelector
(
'
h3
'
)
if
(
!
titleEl
)
continue
jj
++
...
...
@@ -54,6 +97,7 @@ export function parseBookmark(htmlStr: string) {
for
(
let
k
=
0
;
k
<
DL3
.
childElementCount
;
k
++
)
{
const
kItem
=
DL3
.
childNodes
[
k
]
if
(
kItem
&&
kItem
.
nodeName
===
'
DT
'
)
{
findA
(
kItem
)
const
titleEl
=
kItem
.
querySelector
(
'
h3
'
)
if
(
!
titleEl
)
continue
kk
++
...
...
@@ -99,16 +143,30 @@ export function parseBookmark(htmlStr: string) {
return
error
}
const
mergeList
=
[...
data
,
...
websiteList
]
const
newList
=
[];
if
(
hasNoCate
)
{
data
.
push
(
noCate
)
}
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
)
// 增量导入
function
r
(
data
:
any
[],
list
:
any
[])
{
for
(
let
i
=
0
;
i
<
data
.
length
;
i
++
)
{
const
item
=
data
[
i
]
as
any
const
title
=
item
.
title
||
item
?.
name
const
idx
=
list
.
findIndex
(
item
=>
(
item
.
title
||
item
.
name
)
===
title
)
// Repeat
if
(
idx
!==
-
1
)
{
if
(
Array
.
isArray
(
item
.
nav
))
{
r
(
item
.
nav
,
list
[
idx
].
nav
)
}
}
else
{
list
.
push
(
item
)
}
}
}
r
(
data
,
copyWebList
)
console
.
log
(
copyWebList
)
return
new
List
return
copyWeb
List
}
src/utils/http.ts
浏览文件 @
b1846d48
...
...
@@ -4,34 +4,47 @@ import axios from 'axios'
import
NProgress
from
'
nprogress
'
import
{
getToken
}
from
'
../utils/user
'
const
token
=
getToken
()
const
DEFAULT_TITLE
=
document
.
title
const
headers
:
{[
k
:
string
]:
string
}
=
{}
if
(
token
)
{
headers
.
Authorization
=
`token
${
token
}
`
}
const
httpInstance
=
axios
.
create
({
timeout
:
60000
*
3
,
baseURL
:
'
https://api.github.com
'
baseURL
:
'
https://api.github.com
'
,
headers
})
const
token
=
getToken
()
function
startLoad
()
{
NProgress
.
start
()
document
.
title
=
'
Connecting...
'
}
function
stopLoad
()
{
NProgress
.
done
()
document
.
title
=
DEFAULT_TITLE
}
Object
.
setPrototypeOf
(
httpInstance
,
axios
)
httpInstance
.
interceptors
.
request
.
use
(
function
(
config
)
{
NProgress
.
start
()
config
.
headers
=
{
Authorization
:
`token
${
token
}
`
,
...
config
.
headers
}
startLoad
()
return
config
},
function
(
error
)
{
NProgress
.
done
()
stopLoad
()
return
Promise
.
reject
(
error
)
})
httpInstance
.
interceptors
.
response
.
use
(
function
(
res
)
{
NProgress
.
done
()
stopLoad
()
return
res
},
function
(
error
)
{
NProgress
.
done
()
stopLoad
()
return
Promise
.
reject
(
error
)
})
...
...
src/view/admin/index.component.html
浏览文件 @
b1846d48
...
...
@@ -290,7 +290,7 @@
<td>
<a
[href]=
"data.url"
target=
"_blank"
>
{{ data.name }}
</a>
</td>
<td>
<td
nzWidth=
"100px"
>
<nz-tag
*ngFor=
"let key of objectKeys(data.urls)"
[nzColor]=
"tagMap[key].color || '#2db7f5'"
>
<a
[href]=
"data.urls[key]"
target=
"_blank"
>
{{ key }}
</a>
</nz-tag>
...
...
@@ -298,8 +298,8 @@
<td>
<pre
class=
"desc"
>
{{ data.desc }}
</pre>
</td>
<td>
{{ data.createdAt }}
</td>
<td>
<td
nzWidth=
"200px"
>
{{ data.createdAt }}
</td>
<td
nzWidth=
"100px"
>
<a
(click)=
"toggleCreateWebModal(); websiteDetail = data; editIdx = idx"
>
编辑
</a>
<a
nz-popconfirm
...
...
src/view/admin/index.component.ts
浏览文件 @
b1846d48
...
...
@@ -112,7 +112,7 @@ export default class WebpComponent {
path
:
LOGO_PATH
,
branch
:
'
image
'
}).
then
(()
=>
{
that
.
message
.
success
(
'
更换成功, 由于CDN缓存问题
预计至少需要10分钟才能看到最
新
'
)
that
.
message
.
success
(
'
更换成功, 由于CDN缓存问题
需要次日更
新
'
)
}).
catch
(
res
=>
{
logoEL
.
src
=
tempSrc
that
.
notification
.
error
(
...
...
@@ -120,6 +120,7 @@ export default class WebpComponent {
`
${
res
?.
response
?.
data
?.
message
??
'
更换LOGO失败,请重试!
'
}
`
)
}).
finally
(()
=>
{
e
.
target
.
value
=
''
that
.
uploading
=
false
})
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录