分类显示搜索引擎列表

This commit is contained in:
2021-05-28 21:49:46 +08:00
parent a941d26116
commit bede90cd72
2 changed files with 339 additions and 275 deletions

View File

@@ -1,118 +1,150 @@
let config = { let config = {
searchEngines: [ searchEngines: {
{ search: {
name: '百度', title: '搜索',
desc: 'www.baidu.com', list: [
url: 'https://www.baidu.com/s?wd=%keyword%', {
icon: 'website/baidu.svg', name: '百度',
show: true desc: 'www.baidu.com',
url: 'https://www.baidu.com/s?wd=%keyword%',
icon: 'website/baidu.svg',
show: true
},
{
name: '必应',
desc: 'cn.bing.com',
url: 'https://cn.bing.com/search?q=%keyword%',
icon: 'website/bing.svg',
show: true
},
{
name: '秘迹',
desc: 'mijisou.com',
url: 'https://mijisou.com/?q=%keyword%',
icon: 'website/mijisou.svg',
show: true
},
{
name: '搜狗',
desc: 'www.sogou.com',
url: 'https://www.sogou.com/web?query=%keyword%',
icon: 'website/sogou.svg',
show: true
},
{
name: '360',
desc: 'www.so.com',
url: 'https://www.so.com/s?q=%keyword%',
icon: 'website/360.svg',
show: true
},
{
name: 'Google',
desc: 'www.google.com',
url: 'https://www.google.com/search?q=%keyword%',
icon: 'website/google.svg',
show: true
},
{
name: 'Yandex',
desc: 'yandex.com',
url: 'https://yandex.com/search/?text=%keyword%',
icon: 'website/yandex.svg',
show: true
}
]
}, },
{ media: {
name: '必应', title: '多媒体',
desc: 'cn.bing.com', list: [
url: 'https://cn.bing.com/search?q=%keyword%', {
icon: 'website/bing.svg', name: '网易云音乐',
show: true desc: 'music.163.com',
url: 'https://music.163.com/#/search/m/?s=%keyword%',
icon: 'website/netease_music.svg',
show: true
},
{
name: 'AcFun',
desc: 'www.acfun.cn',
url: 'https://www.acfun.cn/search/?keyword=%keyword%',
icon: 'website/acfun.svg',
show: true
},
{
name: 'bilibili',
desc: 'search.bilibili.com',
url: 'https://search.bilibili.com/all?keyword=%keyword%',
icon: 'website/bilibili.svg',
show: true
},
]
}, },
{ technology: {
name: '秘迹', title: '技术',
desc: 'mijisou.com', list: [
url: 'https://mijisou.com/?q=%keyword%', {
icon: 'website/mijisou.svg', name: 'CSDN',
show: true desc: 'so.csdn.net',
url: 'https://so.csdn.net/so/search/all?q=%keyword%',
icon: 'website/csdn.svg',
show: true
},
{
name: 'GitHub',
desc: 'github.com',
url: 'https://github.com/search?q=%keyword%',
icon: 'website/github.svg',
show: true
},
{
name: 'MDN',
desc: 'developer.mozilla.org',
url: 'https://developer.mozilla.org/zh-CN/search?q=%keyword%',
icon: 'website/mdn.svg',
show: true
}
]
}, },
{ design: {
name: '搜狗', title: '设计',
desc: 'www.sogou.com', list: [
url: 'https://www.sogou.com/web?query=%keyword%', {
icon: 'website/sogou.svg', name: '站酷',
show: true desc: 'www.zcool.com.cn',
url: 'https://www.zcool.com.cn/search/content?word=%keyword%',
icon: 'website/zcool.svg',
show: true
},
{
name: 'Iconfont',
desc: 'www.iconfont.cn',
url: 'https://www.iconfont.cn/search/index?searchType=icon&q=%keyword%',
icon: 'website/iconfont.svg',
show: true
}
]
}, },
{ community: {
name: '网易云音乐', title: '社区',
desc: 'music.163.com', list: [
url: 'https://music.163.com/#/search/m/?s=%keyword%', {
icon: 'website/netease_music.svg', name: '天涯',
show: true desc: 'search.tianya.cn',
}, url: 'https://search.tianya.cn/bbs?q=%keyword%',
{ icon: 'website/tianya.svg',
name: '站酷', show: true
desc: 'www.zcool.com.cn', },
url: 'https://www.zcool.com.cn/search/content?word=%keyword%', {
icon: 'website/zcool.svg', name: '知乎',
show: true desc: 'www.zhihu.com',
}, url: 'https://www.zhihu.com/search?type=content&q=%keyword%',
{ icon: 'website/zhihu.svg',
name: '知乎', show: true
desc: 'www.zhihu.com', }
url: 'https://www.zhihu.com/search?type=content&q=%keyword%', ]
icon: 'website/zhihu.svg',
show: true
},
{
name: '360',
desc: 'www.so.com',
url: 'https://www.so.com/s?q=%keyword%',
icon: 'website/360.svg',
show: true
},
{
name: 'AcFun',
desc: 'www.acfun.cn',
url: 'https://www.acfun.cn/search/?keyword=%keyword%',
icon: 'website/acfun.svg',
show: true
},
{
name: 'bilibili',
desc: 'search.bilibili.com',
url: 'https://search.bilibili.com/all?keyword=%keyword%',
icon: 'website/bilibili.svg',
show: true
},
{
name: 'CSDN',
desc: 'so.csdn.net',
url: 'https://so.csdn.net/so/search/all?q=%keyword%',
icon: 'website/csdn.svg',
show: true
},
{
name: 'GitHub',
desc: 'github.com',
url: 'https://github.com/search?q=%keyword%',
icon: 'website/github.svg',
show: true
},
{
name: 'Google',
desc: 'www.google.com',
url: 'https://www.google.com/search?q=%keyword%',
icon: 'website/google.svg',
show: true
},
{
name: 'Iconfont',
desc: 'www.iconfont.cn',
url: 'https://www.iconfont.cn/search/index?searchType=icon&q=%keyword%',
icon: 'website/iconfont.svg',
show: true
},
{
name: 'MDN',
desc: 'developer.mozilla.org',
url: 'https://developer.mozilla.org/zh-CN/search?q=%keyword%',
icon: 'website/mdn.svg',
show: true
},
{
name: 'Yandex',
desc: 'yandex.com',
url: 'https://yandex.com/search/?text=%keyword%',
icon: 'website/yandex.svg',
show: true
} }
], },
siteName: 'Frost 网址导航', siteName: 'Frost 网址导航',
storage: { storage: {
fontSize: 16, fontSize: 16,

View File

@@ -3,8 +3,11 @@
<!-- 侧边栏 --> <!-- 侧边栏 -->
<el-aside class="home-aside"> <el-aside class="home-aside">
<el-menu class="side-nav" default-active="search" <el-menu
:collapse="config.sideMenuCollapse" @select="changeCategory" class="side-nav"
default-active="search"
:collapse="config.sideMenuCollapse"
@select="changeCategory"
> >
<!-- 搜索引擎 --> <!-- 搜索引擎 -->
@@ -20,8 +23,10 @@
</el-menu-item> </el-menu-item>
<!-- 分类 --> <!-- 分类 -->
<el-menu-item v-for="(item, itemIndex) in navLinks.list" <el-menu-item
:key="'list-' + itemIndex" :index="itemIndex.toString()" v-for="(item, itemIndex) in navLinks.list"
:key="'list-' + itemIndex"
:index="itemIndex.toString()"
> >
<i :class="item.icon || 'el-icon-link'"></i> <i :class="item.icon || 'el-icon-link'"></i>
<span slot="title">{{ item.title }}</span> <span slot="title">{{ item.title }}</span>
@@ -41,13 +46,18 @@
<div class="search-bar shadow-3"> <div class="search-bar shadow-3">
<!-- 输入 --> <!-- 输入 -->
<input v-model="searchEngine.keyword" class="input" type="text" <input
@blur="searchEngine.isFocus = false" @focus="searchEngine.isFocus = true" v-model="searchEngine.keyword"
class="input" type="text"
@blur="searchEngine.isFocus = false"
@focus="searchEngine.isFocus = true"
@keydown.enter.exact="searchEngineSubmit()" @keydown.enter.exact="searchEngineSubmit()"
/> />
<!-- 清除 --> <!-- 清除 -->
<div v-show="searchEngine.keyword.length > 0" class="btn btn-clear" <div
v-show="searchEngine.keyword.length > 0"
class="btn btn-clear"
@click="searchEngine.keyword = ''" @click="searchEngine.keyword = ''"
> >
<i class="el-icon-close"></i> <i class="el-icon-close"></i>
@@ -61,31 +71,38 @@
</div> </div>
<!-- 选择搜索引擎 --> <!-- 选择搜索引擎 -->
<el-radio-group v-model="config.searchEngine" size="small" <el-radio-group
v-model="config.searchEngine"
size="small"
:class="['search-type', { fade: searchEngine.isFocus }]" :class="['search-type', { fade: searchEngine.isFocus }]"
> >
<!-- 分类 -->
<div v-for="(category, cIndex) in searchEngine.list" :key="cIndex" class="category">
<!-- 自动生成 --> <!-- 标题 -->
<el-radio v-for="item in searchEngine.types" :key="item.name" <div class="title">{{ category.title }}</div>
:label="item.name" class="shadow-2"
>
<Icon :path="item.icon || 'website/default.svg'" size="1.2em" />
<i class="name">{{ item.name }}</i>
<i class="desc">{{ item.desc }}</i>
</el-radio>
<!-- 占位 --> <!-- -->
<el-radio label="0"></el-radio> <el-radio
v-for="item in category.list" :key="item.name"
:label="item.name" class="shadow-2"
>
<Icon :path="item.icon || 'website/default.svg'" size="1.2em" />
<i class="name">{{ item.name }}</i>
<i class="desc limit-line-1">{{ item.desc }}</i>
</el-radio>
</div>
</el-radio-group> </el-radio-group>
</div> </div>
<!-- 链接搜索框 --> <!-- 链接搜索框 -->
<el-input v-show="show.linkSearch" v-model="linkSearch.keyword" <el-input
v-show="show.searchLink" v-model="searchLink.keyword"
class="link-search shadow-2" placeholder="搜索链接" clearable class="link-search shadow-2" placeholder="搜索链接" clearable
> >
<el-select slot="prepend" v-model="linkSearch.type" placeholder="类型"> <el-select slot="prepend" v-model="searchLink.type" placeholder="类型">
<el-option label="全部" value="all"></el-option> <el-option label="全部" value="all"></el-option>
<el-option label="标题" value="title"></el-option> <el-option label="标题" value="title"></el-option>
<el-option label="链接" value="link"></el-option> <el-option label="链接" value="link"></el-option>
@@ -93,12 +110,14 @@
</el-input> </el-input>
<!-- 链接列表树 --> <!-- 链接列表树 -->
<el-tree v-show="show.linkTree" ref="linkTree" class="link-tree shadow-2" <el-tree
v-show="show.linkTree" ref="linkTree" class="link-tree shadow-2"
:data="currentLinks" node-key="id" empty-text="" :data="currentLinks" node-key="id" empty-text=""
:props="{ label: 'title', children: 'sub' }" :filter-node-method="searchLink" :props="{ label: 'title', children: 'sub' }" :filter-node-method="searchLinkSubmit"
:default-expand-all="false" :expand-on-click-node="true" :default-expand-all="false" :expand-on-click-node="true"
> >
<div slot-scope="{ node, data }" class="link-item" :title="data.update" <div
slot-scope="{ node, data }" class="link-item" :title="data.update"
@click="openLink(data.link, data.showOnly)" @click="openLink(data.link, data.showOnly)"
> >
<span class="title">{{ node.label }}</span> <span class="title">{{ node.label }}</span>
@@ -132,21 +151,22 @@ export default {
// 显示的内容 // 显示的内容
show: { show: {
searchEngine: true, searchEngine: true,
linkSearch: false, searchLink: false,
linkTree: false, linkTree: false,
}, },
// 搜索引擎 // 搜索引擎
searchEngine: { searchEngine: {
isFocus: false, isFocus: false,
keyword: '', keyword: '',
types: this.$root.config.searchEngines url: '',
list: this.$root.config.searchEngines
}, },
// 导航链接 // 导航链接
navLinks: this.$root.navLinks, navLinks: this.$root.navLinks,
// 当前显示的链接 // 当前显示的链接
currentLinks: [], currentLinks: [],
// 搜索链接 // 搜索链接
linkSearch: { searchLink: {
debounce: null, debounce: null,
keyword: '', keyword: '',
type: 'all' type: 'all'
@@ -154,19 +174,19 @@ export default {
}; };
}, },
watch: { watch: {
'linkSearch.keyword': { 'searchLink.keyword': {
handler(value) { handler(value) {
clearTimeout(this.linkSearch.debounce); clearTimeout(this.searchLink.debounce);
this.linkSearch.debounce = setTimeout(() => { this.searchLink.debounce = setTimeout(() => {
this.$refs.linkTree.filter(value); this.$refs.linkTree.filter(value);
}, 500); }, 500);
} }
}, },
'linkSearch.type': { 'searchLink.type': {
handler() { handler() {
// 更改搜索类型时自动重新搜索 // 更改搜索类型时自动重新搜索
this.$refs.linkTree.filter(this.linkSearch.keyword); this.$refs.linkTree.filter(this.searchLink.keyword);
} }
} }
}, },
@@ -179,21 +199,21 @@ export default {
if (index == 'search') { if (index == 'search') {
this.currentLinks = []; this.currentLinks = [];
this.show.searchEngine = true; this.show.searchEngine = true;
this.show.linkSearch = false; this.show.searchLink = false;
this.show.linkTree = false; this.show.linkTree = false;
} else if (index == 'all') { } else if (index == 'all') {
this.currentLinks = this.navLinks.list; this.currentLinks = this.navLinks.list;
this.show.searchEngine = false; this.show.searchEngine = false;
this.show.linkSearch = true; this.show.searchLink = true;
this.show.linkTree = true; this.show.linkTree = true;
} else { } else {
this.currentLinks = this.navLinks.list[Number(index)].sub; this.currentLinks = this.navLinks.list[Number(index)].sub;
this.show.searchEngine = false; this.show.searchEngine = false;
this.show.linkSearch = true; this.show.searchLink = true;
this.show.linkTree = true; this.show.linkTree = true;
} }
this.linkSearch.keyword = ''; this.searchLink.keyword = '';
}, },
/** /**
@@ -220,30 +240,34 @@ export default {
searchEngineSubmit() { searchEngineSubmit() {
var vm = this; var vm = this;
var search = this.searchEngine; var search = this.searchEngine;
var selected = this.config.searchEngine;
var keyword = search.keyword; var keyword = search.keyword;
var types = search.types;
var url = ''; var url = '';
if (keyword == '') { if (keyword == '') {
return false; return false;
} else { } else {
// 编码
keyword = window.encodeURIComponent(keyword); keyword = window.encodeURIComponent(keyword);
} }
for (let index in types) { for (let category in search.list) {
if (types[index].name == vm.config.searchEngine) { let list = search.list[category].list;
url = types[index].url.replace(/%keyword%/, keyword);
vm.openLink(url); for (let index in list) {
break; if (list[index].name == selected) {
url = list[index].url.replace(/%keyword%/, keyword);
break;
}
} }
} }
vm.openLink(url);
}, },
/** /**
* 搜索链接 * 搜索链接
*/ */
searchLink(value, data) { searchLinkSubmit(value, data) {
// 关键词为空,显示全部 // 关键词为空,显示全部
if (value === '') { if (value === '') {
@@ -255,7 +279,7 @@ export default {
// 过滤后 // 过滤后
var searchType = this.linkSearch.type; var searchType = this.searchLink.type;
var title = data.title.toLowerCase(); var title = data.title.toLowerCase();
var link = (data.link || ''); var link = (data.link || '');
var result = false; var result = false;
@@ -303,104 +327,103 @@ export default {
min-width: 16rem; min-width: 16rem;
max-width: 60rem; max-width: 60rem;
} }
}
/deep/ .search-engine { .search-engine {
display: flex;
align-items: center;
flex-direction: column;
.search-bar {
display: flex; display: flex;
align-items: center; align-items: center;
flex-direction: column; position: sticky;
top: 3rem;
z-index: 100;
width: 100%;
max-width: 40rem;
height: 2.8rem;
border-radius: .25rem;
background-color: #FFF;
overflow: hidden;
.search-bar { .input {
display: flex; flex-grow: 1;
padding-left: 1rem;
width: 0;
height: 100%;
outline: none;
}
.btn {
display: inline-flex;
align-items: center; align-items: center;
position: sticky; justify-content: center;
top: .5rem; flex-shrink: 0;
z-index: 100; width: 2.8rem;
width: 100%;
max-width: 40rem;
height: 2.8rem; height: 2.8rem;
border-radius: .25rem; background-color: transparent;
background-color: #FFF; font-size: 1.2rem;
overflow: hidden; cursor: pointer;
}
.input { .btn-clear {
flex-grow: 1; width: 2rem;
padding-left: 1rem; opacity: .5;
width: 0; transition: opacity @transitionTime;
height: 100%;
outline: none;
}
.btn { &:hover {
display: inline-flex; opacity: 1;
align-items: center;
justify-content: center;
flex-shrink: 0;
width: 2.8rem;
height: 2.8rem;
background-color: transparent;
font-size: 1.2rem;
cursor: pointer;
}
.btn-clear {
width: 2rem;
opacity: .5;
transition: opacity @transitionTime;
&:hover {
opacity: 1;
}
}
.btn-search {
color: @colorPrimary;
transition: background @transitionTime, color @transitionTime;
&:hover {
background-color: @colorPrimary;
color: #FFF;
}
} }
} }
.search-type { .btn-search {
display: flex; color: @colorPrimary;
align-items: center; transition: background @transitionTime, color @transitionTime;
flex-wrap: wrap;
justify-content: center;
margin: 2rem 0;
font-size: 1rem;
transition: opacity calc(@transitionTime * 4);
&.fade { &:hover {
opacity: 0.5; background-color: @colorPrimary;
color: #FFF;
}
}
}
.search-type {
display: block;
margin: 4.5rem 0;
font-size: 1rem;
transition: opacity calc(@transitionTime * 4);
&.fade {
opacity: .5;
}
/deep/ .category {
padding: .5rem 0;
.title {
margin: .5rem 0;
} }
> label { .el-radio {
margin: 1em .5em; margin: .5rem;
margin-top: 0; padding: .8rem 1rem;
padding: 1em; width: 16rem;
width: 45%; border-radius: .25rem;
min-width: 18em; border-left: solid .2rem transparent;
border-bottom: solid .15rem transparent;
border-radius: .25em;
background-color: #FFF; background-color: #FFF;
text-align: left; text-align: left;
font-weight: normal; font-weight: normal;
transition: border @transitionTime; transition: border @transitionTime;
// 隐藏占位元素 &:hover {
&:last-child { border-left-color: @colorSecondary;
visibility: hidden; color: @colorSecondary;
}
// 若占位元素为第奇数个,不显示
&:last-child:nth-child(odd) {
display: none;
} }
&.is-checked { &.is-checked {
border-bottom-color: @colorPrimary; border-left-color: @colorPrimary;
color: @colorPrimary;
} }
} }
@@ -409,82 +432,91 @@ export default {
} }
.el-radio__label { .el-radio__label {
display: flex;
align-items: center;
padding: 0; padding: 0;
transition: color @transitionTime; transition: color @transitionTime;
i { i {
vertical-align: middle; display: inline-block;
padding: .125rem 0;
font-style: normal; font-style: normal;
} }
.fn-icon { .fn-icon {
margin-right: .4em; flex-shrink: 0;
margin-right: .4rem;
}
.name {
flex-shrink: 0;
} }
.desc { .desc {
margin-left: .5em; flex-grow: 1;
font-size: .8em; margin-left: .5rem;
font-size: .8rem;
color: #CCC; color: #CCC;
} }
} }
} }
} }
}
/deep/ .link-search { /deep/ .link-search {
@height: 2.8rem; @height: 2.8rem;
position: sticky; position: sticky;
z-index: 100; z-index: 100;
top: 0; top: 0;
margin-bottom: 1rem; margin-bottom: 1rem;
border-radius: .25rem; border-radius: .25rem;
line-height: @height; line-height: @height;
overflow: hidden; overflow: hidden;
> div, > input { > div, > input {
border: none; border: none;
} }
.el-input-group__prepend { .el-input-group__prepend {
background-color: #FFF; background-color: #FFF;
.el-select .el-input { .el-select .el-input {
width: 4.5rem; width: 4.5rem;
input { input {
padding: 0 .75rem; padding: 0 .75rem;
}
} }
} }
.el-input__inner {
height: @height;
line-height: @height;
}
} }
.link-tree { .el-input__inner {
padding: .5rem; height: @height;
border-radius: .25rem; line-height: @height;
font-size: 14px; }
}
/deep/ .el-tree-node__content { .link-tree {
height: 3.6em; padding: .5rem;
border-radius: .25rem;
font-size: 14px;
/deep/ .el-tree-node__content {
height: 3.6em;
}
.link-item {
> span {
display: -webkit-box;
} }
.link-item { .title {
> span { font-weight: bold;
display: -webkit-box; }
}
.title { .link {
font-weight: bold; margin-top: .2rem;
} opacity: .5;
.link {
margin-top: .2rem;
opacity: .5;
}
} }
} }
} }