From 83ea700eac06dc6454e4d0b8a7e56849c3cb7c46 Mon Sep 17 00:00:00 2001
From: Frost-ZX <30585462+Frost-ZX@users.noreply.github.com>
Date: Sun, 20 Mar 2022 21:49:43 +0800
Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=85=A8=E5=B1=80=E7=8A=B6?=
=?UTF-8?q?=E6=80=81=E8=AF=BB=E5=86=99=E9=80=BB=E8=BE=91=EF=BC=8C=E4=BD=BF?=
=?UTF-8?q?=E7=94=A8=20Vuex?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/App.vue | 85 +++++-----
src/assets/js/config.js | 154 -----------------
src/assets/js/search-utils.js | 292 +++++++++++++++++++++++++++------
src/assets/js/utils.js | 4 +-
src/components/FloatingBtn.vue | 26 +--
src/main.js | 11 --
src/router/index.js | 8 +-
src/store/index.js | 108 +++++++++++-
src/views/AboutView.vue | 4 +-
src/views/HomeView.vue | 164 +++++++++---------
src/views/SettingsView.vue | 96 ++++++++---
src/views/ToolsDetail.vue | 6 +-
12 files changed, 556 insertions(+), 402 deletions(-)
diff --git a/src/App.vue b/src/App.vue
index 6fe69a6..fe47238 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -2,7 +2,7 @@
-
+
@@ -20,7 +20,7 @@
diff --git a/src/assets/js/config.js b/src/assets/js/config.js
index 3c1f7aa..4fab6af 100644
--- a/src/assets/js/config.js
+++ b/src/assets/js/config.js
@@ -2,160 +2,6 @@ let config = {
loading: {
subPage: false
},
- searchEngines: {
- search: {
- title: '搜索',
- list: [
- {
- name: '百度',
- 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: {
- title: '多媒体',
- list: [
- {
- name: '网易云音乐',
- 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
- },
- {
- name: 'QQ音乐',
- desc: 'y.qq.com',
- url: 'https://y.qq.com/n/ryqq/search?w=%keyword%',
- icon: 'website/qq_music.svg',
- show: true
- }
- ]
- },
- technology: {
- title: '技术',
- list: [
- {
- 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: 'MDN',
- desc: 'developer.mozilla.org',
- url: 'https://developer.mozilla.org/zh-CN/search?q=%keyword%',
- icon: 'website/mdn.svg',
- show: true
- }
- ]
- },
- design: {
- title: '设计',
- list: [
- {
- name: '站酷',
- 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: {
- title: '社区',
- list: [
- {
- name: '天涯',
- desc: 'search.tianya.cn',
- url: 'https://search.tianya.cn/bbs?q=%keyword%',
- icon: 'website/tianya.svg',
- show: true
- },
- {
- name: '知乎',
- desc: 'www.zhihu.com',
- url: 'https://www.zhihu.com/search?type=content&q=%keyword%',
- icon: 'website/zhihu.svg',
- show: true
- }
- ]
- }
- },
- siteName: 'Frost 网址导航',
storage: {
fontSize: 16,
showSiteTitle: true,
diff --git a/src/assets/js/search-utils.js b/src/assets/js/search-utils.js
index 243062d..d1e2201 100644
--- a/src/assets/js/search-utils.js
+++ b/src/assets/js/search-utils.js
@@ -1,52 +1,3 @@
-/**
- * @description 解析推荐的关键词
- * @param {string} type 来源类型
- * @param {*} datas 关键词数据
- * @param {number} [max] 最大返回数量
- * @returns {string[]} 关键词列表
- */
-function parseSearchWords(type = '', datas = null, max = 10) {
- if (!datas) {
- return [];
- }
-
- /** @type {string[]} */
- let words = [];
-
- try {
- switch (type) {
- case '360':
- words = parseSearch360(datas);
- case 'baidu':
- words = parseSearchBaidu(datas);
- case 'bing':
- words = parseSearchBing(datas);
- default:
- break;
- }
- } catch (error) {
- console.error('解析失败');
- return [];
- }
-
- const arrLength = words.length;
- const cutLength = Math.max(arrLength - max, 0);
- const cutStart = arrLength - cutLength;
-
- words.splice(cutStart, cutLength);
-
- let value = '';
-
- for (value of words) {
- if (typeof value !== 'string') {
- console.error('关键词的数据类型错误');
- return [];
- }
- }
-
- return words;
-}
-
/**
* @desc 解析 360 推荐关键词(2021-12-29)
* @param {{ result: { word: string }[] }} datas
@@ -91,10 +42,41 @@ function parseSearchBing(datas) {
return words;
}
+/**
+ * @typedef MDNSearchIndexDatas
+ * @type {{ title: string, url: string }[]}
+ */
+
+/**
+ * @description 解析 MDN 搜索关键词
+ * @param {MDNSearchIndexDatas} datas 关键词数据
+ * @param {string} keyword 输入的关键词
+ * @param {number} [max] 最多返回的结果数量,默认为 10
+ * @returns {MDNSearchIndexDatas} 匹配到的关键词
+ */
+function parseSearchMDN(datas = [], keyword = '', max = 10) {
+ /** @type {MDNSearchIndexDatas} */
+ const result = [];
+ const word = String(keyword).toLowerCase();
+
+ let count = 0;
+
+ for (const item of datas) {
+ if (item.title.toLowerCase().indexOf(word) > -1) {
+ result.push(item);
+ if ((count += 1) >= max) {
+ break;
+ }
+ }
+ }
+
+ return result;
+}
+
/**
* @description 获取搜索 URL
- * @param {string} type 搜索引擎类型
- * @param {string} word 搜索关键词
+ * @param {string} type 搜索引擎类型
+ * @param {string} word 搜索关键词
* @param {string} [cbName] 回调函数名称,用于获取推荐关键词
* @returns {(string|null)} 根据参数返回不同的结果
* - 无 `cbName` 时返回搜索结果页面 URL
@@ -128,6 +110,207 @@ function getSearchURL(type, word, cbName) {
}
}
+/**
+ * @description 解析推荐的关键词
+ * @param {string} type 来源类型
+ * @param {*} datas 关键词数据
+ * @param {number} [max] 最大返回数量
+ * @returns {string[]} 关键词列表
+ */
+function parseSearchWords(type = '', datas = null, max = 10) {
+ if (!datas) {
+ return [];
+ }
+
+ /** @type {string[]} */
+ let words = [];
+
+ try {
+ switch (type) {
+ case '360':
+ words = parseSearch360(datas);
+ break;
+ case 'baidu':
+ words = parseSearchBaidu(datas);
+ break;
+ case 'bing':
+ words = parseSearchBing(datas);
+ break;
+ default:
+ console.error('来源类型错误');
+ return [];
+ }
+ } catch (error) {
+ console.error('解析失败');
+ return [];
+ }
+
+ const arrLength = words.length;
+ const cutLength = Math.max(arrLength - max, 0);
+ const cutStart = arrLength - cutLength;
+
+ words.splice(cutStart, cutLength);
+
+ let value = '';
+
+ for (value of words) {
+ if (typeof value !== 'string') {
+ console.error('关键词的数据类型错误');
+ return [];
+ }
+ }
+
+ return words;
+}
+
+/** 搜索引擎列表 */
+const searchEngines = {
+ search: {
+ title: '搜索',
+ list: [
+ {
+ name: '百度',
+ 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: '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: {
+ title: '多媒体',
+ list: [
+ {
+ name: '网易云音乐',
+ 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
+ },
+ {
+ name: 'QQ音乐',
+ desc: 'y.qq.com',
+ url: 'https://y.qq.com/n/ryqq/search?w=%keyword%',
+ icon: 'website/qq_music.svg',
+ show: true
+ }
+ ]
+ },
+ technology: {
+ title: '技术',
+ list: [
+ {
+ 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: 'MDN',
+ desc: 'developer.mozilla.org',
+ url: 'https://developer.mozilla.org/zh-CN/search?q=%keyword%',
+ icon: 'website/mdn.svg',
+ show: true
+ }
+ ]
+ },
+ design: {
+ title: '设计',
+ list: [
+ {
+ name: '站酷',
+ 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: {
+ title: '社区',
+ list: [
+ {
+ name: '天涯',
+ desc: 'search.tianya.cn',
+ url: 'https://search.tianya.cn/bbs?q=%keyword%',
+ icon: 'website/tianya.svg',
+ show: true
+ },
+ {
+ name: '知乎',
+ desc: 'www.zhihu.com',
+ url: 'https://www.zhihu.com/search?type=content&q=%keyword%',
+ icon: 'website/zhihu.svg',
+ show: true
+ }
+ ]
+ }
+};
+
/**
* @typedef {object} SearchItem
* @property {string} name 名称
@@ -154,3 +337,10 @@ const searchItems = [
// wordURL: 'https://sg1.api.bing.com/qsonhs.aspx?type=cb&cb={cb}&q={w}',
},
];
+
+export default {
+ getSearchURL,
+ parseSearchMDN,
+ parseSearchWords,
+ searchEngines,
+};
diff --git a/src/assets/js/utils.js b/src/assets/js/utils.js
index b842c25..8aa22a7 100644
--- a/src/assets/js/utils.js
+++ b/src/assets/js/utils.js
@@ -1,5 +1,3 @@
-import config from './config.js';
-
class Utils {
constructor() { }
@@ -9,7 +7,7 @@ class Utils {
* @param {string} [value] 新的标题
*/
changeTitle(value) {
- document.title = (value ? (value + ' - ') : '') + config.siteName;
+ document.title = ((value ? `${value} - ` : '') + 'Frost 网址导航');
}
/**
diff --git a/src/components/FloatingBtn.vue b/src/components/FloatingBtn.vue
index ba3cf57..7d6de89 100644
--- a/src/components/FloatingBtn.vue
+++ b/src/components/FloatingBtn.vue
@@ -24,8 +24,7 @@ export default {
name: 'FloatingBtn',
data() {
return {
- config: this.$root.config.storage,
- showInner: false
+ showInner: false,
}
},
mounted () {
@@ -33,9 +32,7 @@ export default {
},
methods: {
- /**
- * 设置动画
- */
+ /** 设置动画 */
initAnimation() {
var vm = this;
var el = vm.$refs['floatingBtn'];
@@ -53,16 +50,12 @@ export default {
});
},
- /**
- * 切换按钮显示
- */
+ /** 切换按钮显示 */
toggleInnerBtns() {
this.showInner = !this.showInner;
},
- /**
- * 返回主页
- */
+ /** 返回主页 */
backToHome() {
const routeName = 'Home';
@@ -77,19 +70,14 @@ export default {
}
},
- /**
- * 刷新
- */
+ /** 刷新 */
refreshPage() {
window.location.reload();
},
- /**
- * 切换侧边菜单折叠状态
- */
+ /** 切换侧边菜单折叠状态 */
toggleSideCollapse() {
- var cfg = this.config;
- cfg.sideMenuCollapse = !cfg.sideMenuCollapse;
+ this.$store.dispatch('toggleSideCollapse');
},
},
diff --git a/src/main.js b/src/main.js
index 21f189b..0c5208a 100644
--- a/src/main.js
+++ b/src/main.js
@@ -4,10 +4,6 @@ import App from './App.vue';
import router from './router';
import store from './store';
-import config from './assets/js/config';
-import navLinks from './assets/js/navLinks';
-import utils from './assets/js/utils';
-
import 'ress/ress.css';
import 'font-awesome/css/font-awesome.min.css';
import './assets/css/element.scss';
@@ -20,12 +16,5 @@ Vue.config.productionTip = false;
new Vue({
router,
store,
- data: function () {
- return {
- config,
- navLinks,
- utils
- }
- },
render: h => h(App)
}).$mount('#app');
diff --git a/src/router/index.js b/src/router/index.js
index 292077c..fd16d1d 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -2,8 +2,8 @@ import Vue from 'vue';
import VueRouter from 'vue-router';
import routes from './routes';
-import config from '@/assets/js/config';
import utils from '@/assets/js/utils';
+import store from '@/store/index';
Vue.use(VueRouter);
@@ -11,18 +11,16 @@ const router = new VueRouter({
routes
});
-// to, from, next
router.beforeEach((to, from, next) => {
if (to.meta.loadingBar) {
- config.loading.subPage = true;
+ store.commit('toggleLoading', true);
}
next();
});
-// to, from
router.afterEach((to) => {
if (to.meta.loadingBar) {
- config.loading.subPage = false;
+ store.commit('toggleLoading', false);
}
utils.changeTitle(to.meta.title);
});
diff --git a/src/store/index.js b/src/store/index.js
index 0533d49..1ebeac5 100644
--- a/src/store/index.js
+++ b/src/store/index.js
@@ -4,9 +4,111 @@ import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.Store({
- state: {},
+ state: {
+
+ /** 设置 */
+ config: {
+ fontSize: 16,
+ showSiteTitle: true,
+ sideMenuCollapse: true,
+ searchEngine: '百度',
+ searchSuggestion: false,
+ },
+
+ /** 显示加载动画 */
+ showLoading: false,
+
+ },
getters: {},
- mutations: {},
- actions: {},
+ mutations: {
+
+ /** 从本地储存中读取设置 */
+ readConfig(state) {
+
+ let keyName = 'fn_config';
+ let storage = localStorage.getItem(keyName);
+ let parsed = null;
+ let config = state.config;
+
+ try {
+ parsed = JSON.parse(storage);
+ } catch (error) {
+ console.error('解析保存的设置失败。');
+ }
+
+ if (parsed && parsed.constructor === Object) {
+ // [本地储存中有数据,读取]
+ for (let key in config) {
+ let value = parsed[key];
+
+ if (typeof value !== 'undefined') {
+ config[key] = value;
+ }
+ }
+ } else {
+ // [本地储存中无数据,写入]
+ localStorage.setItem(keyName, JSON.stringify(config));
+ }
+
+ },
+
+ /** 重置保存的设置 */
+ resetConfig() {
+ localStorage.removeItem('fn_config');
+ },
+
+ /**
+ * @description 更新设置
+ * @param {object} payload
+ * @param {string} payload.key
+ * @param {any} payload.value
+ */
+ setConfig(state, payload) {
+
+ const {
+ key: cKey = null,
+ value: cValue = null,
+ } = payload;
+
+ const { config } = state;
+
+ if (cKey === null) {
+ console.error('更新设置失败,key 为空。');
+ return;
+ }
+
+ if (typeof config[cKey] === 'undefined') {
+ console.error('更新设置失败,key 不存在。');
+ return;
+ }
+
+ // 更新设置
+ config[cKey] = cValue;
+ // 保存设置
+ localStorage.setItem('fn_config', JSON.stringify(config));
+
+ },
+
+ /** 切换加载动画显示隐藏 */
+ toggleLoading(state, payload = false) {
+ state.showLoading = payload;
+ },
+
+ },
+ actions: {
+
+ /** 切换导航链接侧边菜单显示隐藏 */
+ toggleSideCollapse(store) {
+
+ const { sideMenuCollapse } = store.state.config;
+
+ store.commit('setConfig', {
+ key: 'sideMenuCollapse',
+ value: !sideMenuCollapse,
+ });
+
+ },
+
+ },
modules: {},
});
diff --git a/src/views/AboutView.vue b/src/views/AboutView.vue
index ad1a5c2..fa73c2c 100644
--- a/src/views/AboutView.vue
+++ b/src/views/AboutView.vue
@@ -41,11 +41,13 @@