新的版本

This commit is contained in:
2021-02-06 23:36:46 +08:00
commit b821611027
28 changed files with 17544 additions and 0 deletions

42
.github/ISSUE_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,42 @@
## 类型
> 请勾选其中符合的一项。
- [ ] 提交链接
- [ ] 修正链接
- [ ] 发现 BUG
- [ ] 建议
## 具体内容
> 请根据选择的“类型”,保留其中一项。
### 提交链接
> 不接受非正常网站
- 链接分类(例如 `资源 - 软件 - 工具`
- 链接名称(例如 `GitHub`
- 具体链接(例如 `https://github.com/`
### 修正链接
- 链接所在的分类(例如 `资源 - 软件 - 工具`
- 链接名称(例如 `GitHub`
- 修正后的分类:
- 修正后的名称:
- 修正后的链接:
### 发现 BUG
#### BUG 描述(例如 BUG 是在什么情况下出现的)
请在此处填写
#### 解决方法(可选)
请在此处填写
### 建议
请在此处填写具体的建议内容

1
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1 @@
请填写描述,例如:修改的内容、作用。

23
.gitignore vendored Normal file
View File

@@ -0,0 +1,23 @@
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 Frost-ZX
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

67
README.md Normal file
View File

@@ -0,0 +1,67 @@
## 简介
### 名称
- Frost 网址导航
- Frost Navigation
### 使用方法
#### 在线
- [GitHub Pages](https://frost-zx.github.io/frost-navigation/)
#### 离线(需要手动更新)
1. [点击此处下载](https://github.com/Frost-ZX/frost-navigation/archive/master.zip)
2. 解压出其中的 `docs` 文件夹,放置于任意合适的喜欢的位置(可重命名)
2. 在浏览器中打开 `index.html`(也可以将其加入浏览器的书签栏或在浏览器设置中将其设置为主页)
#### 自定义
- 该功能待开发
## 本项目使用
- [Vue CLI](https://cli.vuejs.org/)
- [Vue Router](https://router.vuejs.org/)
- [Element UI - 桌面端组件库](https://element.eleme.cn/)
- [ress - Modern CSS reset](https://github.com/filipelinhares/ress)
## 反馈
### 提交链接
请到 [Issues](https://github.com/Frost-ZX/frost-navigation/issues) ,根据相关提示进行提交。
### 修正链接
请到 [Issues](https://github.com/Frost-ZX/frost-navigation/issues) ,根据相关提示进行提交。
## 开发
### Project setup
```
npm install
```
### Compiles and hot-reloads for development
```
npm run serve
```
### Compiles and minifies for production
```
npm run build
```
### Lints and fixes files
```
npm run lint
```

5
babel.config.js Normal file
View File

@@ -0,0 +1,5 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
};

BIN
docs/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 KiB

1
docs/index.html Normal file
View File

@@ -0,0 +1 @@
<!DOCTYPE html><html><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="favicon.ico"><title>Frost 网址导航</title><link href="static/css/chunk-vendors.08db079c.css" rel="preload" as="style"><link href="static/css/mainPage.0ffdc46d.css" rel="preload" as="style"><link href="static/js/chunk-vendors.3f17c3d0.js" rel="preload" as="script"><link href="static/js/mainPage.9e0582fd.js" rel="preload" as="script"><link href="static/css/chunk-vendors.08db079c.css" rel="stylesheet"><link href="static/css/mainPage.0ffdc46d.css" rel="stylesheet"></head><body><noscript><strong>浏览器未启用或不支持 JavaScript。</strong></noscript><div id="app"></div><script src="static/js/chunk-vendors.3f17c3d0.js"></script><script src="static/js/mainPage.9e0582fd.js"></script></body></html>

File diff suppressed because one or more lines are too long

1
docs/static/css/mainPage.0ffdc46d.css vendored Normal file
View File

@@ -0,0 +1 @@
::-webkit-scrollbar{width:.5rem;height:.5rem}::-webkit-scrollbar-track{background-color:transparent}::-webkit-scrollbar-thumb{border-radius:1rem;background-color:#f5f5f5}::-webkit-scrollbar-thumb:hover{background-color:#409eff}html{font-size:16px}body{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.shadow-1{box-shadow:0 0 .5rem rgba(0,0,0,.1)}.loading-link{background-color:hsla(0,0%,100%,.5)!important;-webkit-backdrop-filter:blur(.2rem);backdrop-filter:blur(.2rem)}.loading-link .el-icon-loading{font-size:2rem!important}.loading-link .el-loading-text{font-size:1.5rem!important}.main-header{display:flex;align-items:center;z-index:200;height:4rem!important;background-color:#fff}.main-header .menu{height:2.5rem;border:none!important}.main-header .menu>li{height:100%;line-height:2.5rem}.main-header .menu>li.is-active{color:#409eff!important}.main-header .menu .title{font-size:1.2rem;color:#409eff;opacity:1;cursor:default}.main-container{height:calc(100vh - 4rem)}[data-v-d436b1cc]::-webkit-scrollbar{width:.5rem;height:.5rem}[data-v-d436b1cc]::-webkit-scrollbar-track{background-color:transparent}[data-v-d436b1cc]::-webkit-scrollbar-thumb{border-radius:1rem;background-color:#f5f5f5}[data-v-d436b1cc]::-webkit-scrollbar-thumb:hover{background-color:#409eff}html[data-v-d436b1cc]{font-size:16px}body[data-v-d436b1cc]{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.shadow-1[data-v-d436b1cc]{box-shadow:0 0 .5rem rgba(0,0,0,.1)}.loading-link[data-v-d436b1cc]{background-color:hsla(0,0%,100%,.5)!important;-webkit-backdrop-filter:blur(.2rem);backdrop-filter:blur(.2rem)}.loading-link .el-icon-loading[data-v-d436b1cc]{font-size:2rem!important}.loading-link .el-loading-text[data-v-d436b1cc]{font-size:1.5rem!important}.home-aside[data-v-d436b1cc]{width:18rem!important;overflow-x:hidden}.home-aside .side-nav[data-v-d436b1cc]{min-height:100%}.home-content[data-v-d436b1cc]{position:relative}.home-content .link-search[data-v-d436b1cc]{position:sticky;z-index:100;top:0;margin-bottom:1rem}.home-content .link-tree[data-v-d436b1cc]{font-size:14px}.home-content .link-tree[data-v-d436b1cc] .el-tree-node__content{height:3.6em}.home-content .link-tree .link-item>span[data-v-d436b1cc]{display:block}.home-content .link-tree .link-item .title[data-v-d436b1cc]{font-weight:700}.home-content .link-tree .link-item .link[data-v-d436b1cc]{margin-top:.2rem;opacity:.5}

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

1
docs/static/js/mainPage.9e0582fd.js vendored Normal file

File diff suppressed because one or more lines are too long

2362
docs/static/js/navLinks.js vendored Normal file

File diff suppressed because it is too large Load Diff

12106
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

57
package.json Normal file
View File

@@ -0,0 +1,57 @@
{
"name": "frost-navigation",
"version": "2.0.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"core-js": "^3.6.5",
"element-ui": "^2.15.0",
"ress": "^3.0.0",
"vue": "^2.6.11",
"vue-router": "^3.2.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-plugin-router": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"babel-eslint": "^10.1.0",
"eslint-plugin-vue": "^6.2.2",
"eslint": "^6.7.2",
"less-loader": "^5.0.0",
"less": "^3.0.4",
"style-resources-loader": "^1.4.1",
"vue-cli-plugin-style-resources-loader": "^0.1.4",
"vue-template-compiler": "^2.6.11"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/recommended",
"eslint:recommended"
],
"parserOptions": {
"parser": "babel-eslint"
},
"rules": {
"vue/html-closing-bracket-newline": "off",
"vue/html-indent": "off",
"vue/html-self-closing": "off",
"vue/max-attributes-per-line": "off",
"vue/multiline-html-element-content-newline": "off",
"vue/singleline-html-element-content-newline": "off"
}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 KiB

17
public/index.html Normal file
View File

@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>浏览器未启用或不支持 JavaScript。</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

2362
public/static/js/navLinks.js Normal file

File diff suppressed because it is too large Load Diff

58
src/App.vue Normal file
View File

@@ -0,0 +1,58 @@
<template>
<div id="app">
<el-container>
<!-- Header -->
<el-header class="main-header shadow-1">
<!-- LOGO -->
<el-avatar class="logo" shape="square" size="medium" src="./favicon.ico"></el-avatar>
<!-- 菜单 -->
<el-menu class="menu" default-active="home" mode="horizontal">
<el-menu-item index="title" class="title" disabled>Frost 网址导航</el-menu-item>
<el-menu-item index="home">主页</el-menu-item>
<el-menu-item index="tools" disabled>小工具</el-menu-item>
</el-menu>
</el-header>
<!-- Container -->
<router-view class="main-container" />
</el-container>
</div>
</template>
<style lang="less">
.main-header {
display: flex;
align-items: center;
z-index: 200;
height: @headerHeight !important;
background-color: #FFF;
.menu {
height: 2.5rem;
border: none !important;
> li {
height: 100%;
line-height: 2.5rem;
&.is-active {
color: @colorPrimary !important;
}
}
.title {
font-size: 1.2rem;
color: @colorPrimary;
opacity: 1;
cursor: default;
}
}
}
.main-container {
height: calc(100vh - @headerHeight);
}
</style>

View File

@@ -0,0 +1,60 @@
/* -- 全局样式 -- */
// 变量
@headerHeight: 4rem;
@colorPrimary: #409EFF;
@colorSecondary: #67C23A;
@colorWhite: #F5F5F5;
// 滚动条
::-webkit-scrollbar {
width: 0.5rem;
height: 0.5rem;
}
::-webkit-scrollbar-track {
background-color: transparent;
}
::-webkit-scrollbar-thumb {
border-radius: 1rem;
background-color: #F5F5F5;
&:hover {
background-color: @colorPrimary;
}
}
// 标签
html {
font-size: 16px;
}
body {
user-select: none;
}
// 阴影
.shadow-1 {
box-shadow: 0 0 0.5rem rgba(0, 0, 0, 0.1);
}
// 加载中(链接列表)
.loading-link {
background-color: rgba(255, 255, 255, 0.5) !important;
backdrop-filter: blur(0.2rem);
.el-icon-loading {
font-size: 2rem !important;
}
.el-loading-text {
font-size: 1.5rem !important;
}
}

68
src/assets/js/utils.js Normal file
View File

@@ -0,0 +1,68 @@
import { Loading } from 'element-ui';
class Utils {
constructor() { }
/**
* 初始化链接列表设置唯一ID
*/
initNavLinkID() {
// 加载中提示
var loading = Loading.service({
customClass: 'loading-link',
lock: true,
spinner: 'el-icon-loading',
text: '载入中,请稍候'
});
var currentIndex = 0;
var currentIndexCpy = 0;
var fn = (obj) => {
currentIndex += 1;
obj.id = currentIndex;
// 有链接,无子路径
if (obj.links != undefined && obj.sub === undefined) {
obj.sub = [];
}
// 递归
if (obj.links != undefined) {
obj.links.forEach(item => {
// 添加到子路径(适配 Element UI - Tree
obj.sub.push(item);
});
}
// 递归
if (obj.sub != undefined) {
obj.sub.forEach(item => {
setTimeout(() => {
fn(item);
}, 0);
});
}
};
// 检测 currentIndex 是否已停止变化
var timer = setInterval(() => {
if (currentIndex == currentIndexCpy) {
clearInterval(timer);
// 加载中提示
loading.close();
}
// 同步
currentIndexCpy = currentIndex;
}, 1000);
return fn;
}
}
const utils = new Utils;
export default utils;

33
src/main.js Normal file
View File

@@ -0,0 +1,33 @@
import Vue from 'vue';
import ElementUI from 'element-ui';
import App from './App.vue';
import router from './router';
import navLinks from '../public/static/js/navLinks'
import utils from './assets/js/utils'
import 'ress/ress.css';
import 'element-ui/lib/theme-chalk/index.css';
(function () {
var init = utils.initNavLinkID();
navLinks.forEach(item => {
init(item);
});
})();
Vue.use(ElementUI);
Vue.config.productionTip = false;
new Vue({
router,
data: function () {
return {
navLinks,
utils
}
},
render: h => h(App)
}).$mount('#app');

12
src/router/index.js Normal file
View File

@@ -0,0 +1,12 @@
import Vue from 'vue';
import VueRouter from 'vue-router';
import routes from './routes';
Vue.use(VueRouter);
const router = new VueRouter({
routes
});
export default router;

16
src/router/routes.js Normal file
View File

@@ -0,0 +1,16 @@
import Home from '@/views/Home.vue';
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
// {
// path: '/about',
// name: 'About',
// component: () => import('@/views/About.vue')
// }
];
export default routes;

160
src/views/Home.vue Normal file
View File

@@ -0,0 +1,160 @@
<template>
<el-container class="home">
<!-- 侧边栏 -->
<el-aside class="home-aside">
<el-menu class="side-nav" default-active="0" @select="changeCategory">
<!-- 全部 -->
<el-menu-item index="all">
<i class="el-icon-menu"></i>
<span slot="title">全部</span>
</el-menu-item>
<!-- 分类 -->
<el-menu-item v-for="(item, itemIndex) in navLinks" :key="'list-' + itemIndex" :index="itemIndex.toString()">
<i class="el-icon-menu"></i>
<span slot="title">{{ item.title }}</span>
</el-menu-item>
</el-menu>
</el-aside>
<!-- 内容 -->
<el-main class="home-content">
<!-- 链接搜索框 -->
<el-input v-model="linkSearchText" class="link-search" placeholder="输入关键词以搜索链接"></el-input>
<!-- 链接列表树 -->
<el-tree ref="linkTree" class="link-tree" :data="currentLinks" :props="{ label: 'title', children: 'sub' }"
node-key="id" :default-expand-all="false" :expand-on-click-node="false" :filter-node-method="searchLink"
>
<div slot-scope="{ node, data }" class="link-item" @click="openLink(data.link)">
<span class="title">{{ node.label }}</span>
<span class="link">{{ data.link }}</span>
</div>
</el-tree>
</el-main>
</el-container>
</template>
<script>
export default {
name: 'Home',
data() {
return {
// 所有链接
navLinks: this.$root.navLinks,
// 当前显示的链接
currentLinks: [],
// 搜索关键词
linkSearchText: '',
linkSearchDebounce: null
};
},
watch: {
'linkSearchText': {
handler(value) {
clearTimeout(this.linkSearchDebounce);
this.linkSearchDebounce = setTimeout(() => {
this.$refs.linkTree.filter(value);
}, 500);
}
}
},
methods: {
log(...datas) {
console.log(datas);
},
/**
* 更改当前显示的分类
*/
changeCategory(index) {
if (index == 'all') {
this.currentLinks = this.navLinks;
} else {
this.currentLinks = this.navLinks[Number(index)].sub;
}
},
/**
* 打开链接
*
* @param {string} link 需要打开的链接
*/
openLink(link) {
if (link != undefined) {
window.open(link, '_blank');
}
},
/**
* 搜索链接
*/
searchLink(value, data) {
// 关键词为空,显示全部
if (value == '') {
return true
}
// 过滤后
var result = (data.title.indexOf(value) !== -1) || (data.link && (data.link.indexOf(value) !== -1));
return result;
}
},
beforeRouteEnter(from, to, next) {
next(vm => {
setTimeout(() => {
vm.changeCategory(0);
}, 1000);
});
}
}
</script>
<style lang="less" scoped>
.home-aside {
width: 18rem !important;
overflow-x: hidden;
.side-nav {
min-height: 100%;
}
}
.home-content {
position: relative;
.link-search {
position: sticky;
z-index: 100;
top: 0;
margin-bottom: 1rem;
}
.link-tree {
font-size: 14px;
/deep/ .el-tree-node__content {
height: 3.6em;
}
.link-item {
> span {
display: block;
}
.title {
font-weight: bold;
}
.link {
margin-top: 0.2rem;
opacity: 0.5;
}
}
}
}
</style>

37
vue.config.js Normal file
View File

@@ -0,0 +1,37 @@
const path = require('path');
module.exports = {
productionSourceMap: false,
assetsDir: 'static',
publicPath: './',
outputDir: 'docs',
pages: {
mainPage: {
// 入口
entry: 'src/main.js',
// 模板来源
template: 'public/index.html',
// 在 dist 的输出
filename: 'index.html',
// 标题
title: 'Frost 网址导航',
// 包含的块
chunks: ['chunk-common', 'chunk-vendors', 'mainPage']
}
},
pluginOptions: {
'style-resources-loader': {
preProcessor: 'less',
// 全局 Less
patterns: [
path.resolve(__dirname, 'src/assets/css/global.less')
]
}
},
devServer: {
port: 9005
}
};