diff --git a/src/store/getters.js b/src/store/getters.js index 9780358..c33a49d 100644 --- a/src/store/getters.js +++ b/src/store/getters.js @@ -1,4 +1,6 @@ const getters = { + visitedViews: state => state.tagsView.visitedViews, + cachedViews: state => state.tagsView.cachedViews, sidebar: state => state.app.sidebar, // 侧边栏 device: state => state.app.device, // 设备 kaptcha: state => state.app.kaptcha, // 验证码 diff --git a/src/store/getters.js b/src/store/getters.js index 9780358..c33a49d 100644 --- a/src/store/getters.js +++ b/src/store/getters.js @@ -1,4 +1,6 @@ const getters = { + visitedViews: state => state.tagsView.visitedViews, + cachedViews: state => state.tagsView.cachedViews, sidebar: state => state.app.sidebar, // 侧边栏 device: state => state.app.device, // 设备 kaptcha: state => state.app.kaptcha, // 验证码 diff --git a/src/store/index.js b/src/store/index.js index 9bfa6a7..c7e23ff 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -3,6 +3,7 @@ import app from './modules/app' import user from './modules/user' import permission from './modules/permission' +import tagsView from './modules/tagsView' import getters from './getters' Vue.use(Vuex) @@ -11,7 +12,8 @@ modules: { app, user, - permission + permission, + tagsView }, getters }) diff --git a/src/store/getters.js b/src/store/getters.js index 9780358..c33a49d 100644 --- a/src/store/getters.js +++ b/src/store/getters.js @@ -1,4 +1,6 @@ const getters = { + visitedViews: state => state.tagsView.visitedViews, + cachedViews: state => state.tagsView.cachedViews, sidebar: state => state.app.sidebar, // 侧边栏 device: state => state.app.device, // 设备 kaptcha: state => state.app.kaptcha, // 验证码 diff --git a/src/store/index.js b/src/store/index.js index 9bfa6a7..c7e23ff 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -3,6 +3,7 @@ import app from './modules/app' import user from './modules/user' import permission from './modules/permission' +import tagsView from './modules/tagsView' import getters from './getters' Vue.use(Vuex) @@ -11,7 +12,8 @@ modules: { app, user, - permission + permission, + tagsView }, getters }) diff --git a/src/store/modules/tagsView.js b/src/store/modules/tagsView.js new file mode 100644 index 0000000..b7e3be9 --- /dev/null +++ b/src/store/modules/tagsView.js @@ -0,0 +1,165 @@ +const state = { + visitedViews: [], // 用户访问过的页面 + cachedViews: [] // 实际keep-alive的路由,可以在配置路由的时候通过meta.noCache来设置是否需要缓存,默认都缓存 +} + +const mutations = { + ADD_VISITED_VIEW: (state, view) => { + if (state.visitedViews.some(v => v.path === view.path)) return + state.visitedViews.push( + Object.assign({}, view, { + title: view.meta.title || 'no-name' + }) + ) + }, + ADD_CACHED_VIEW: (state, view) => { + if (state.cachedViews.includes(view.name)) return + if (!view.meta.noCache) { + state.cachedViews.push(view.name) + } + }, + + DEL_VISITED_VIEW: (state, view) => { + for (const [i, v] of state.visitedViews.entries()) { + if (v.path === view.path) { + state.visitedViews.splice(i, 1) + break + } + } + }, + DEL_CACHED_VIEW: (state, view) => { + for (const i of state.cachedViews) { + if (i === view.name) { + const index = state.cachedViews.indexOf(i) + state.cachedViews.splice(index, 1) + break + } + } + }, + + DEL_OTHERS_VISITED_VIEWS: (state, view) => { + state.visitedViews = state.visitedViews.filter(v => { + return v.meta.affix || v.path === view.path + }) + }, + DEL_OTHERS_CACHED_VIEWS: (state, view) => { + for (const i of state.cachedViews) { + if (i === view.name) { + const index = state.cachedViews.indexOf(i) + state.cachedViews = state.cachedViews.slice(index, index + 1) + break + } + } + }, + + DEL_ALL_VISITED_VIEWS: state => { + // keep affix tags + const affixTags = state.visitedViews.filter(tag => tag.meta.affix) + state.visitedViews = affixTags + }, + DEL_ALL_CACHED_VIEWS: state => { + state.cachedViews = [] + }, + + UPDATE_VISITED_VIEW: (state, view) => { + for (let v of state.visitedViews) { + if (v.path === view.path) { + v = Object.assign(v, view) + break + } + } + } +} + +const actions = { + addView({ dispatch }, view) { + dispatch('addVisitedView', view) + dispatch('addCachedView', view) + }, + addVisitedView({ commit }, view) { + commit('ADD_VISITED_VIEW', view) + }, + addCachedView({ commit }, view) { + commit('ADD_CACHED_VIEW', view) + }, + + delView({ dispatch, state }, view) { + return new Promise(resolve => { + dispatch('delVisitedView', view) + dispatch('delCachedView', view) + resolve({ + visitedViews: [...state.visitedViews], + cachedViews: [...state.cachedViews] + }) + }) + }, + delVisitedView({ commit, state }, view) { + return new Promise(resolve => { + commit('DEL_VISITED_VIEW', view) + resolve([...state.visitedViews]) + }) + }, + delCachedView({ commit, state }, view) { + return new Promise(resolve => { + commit('DEL_CACHED_VIEW', view) + resolve([...state.cachedViews]) + }) + }, + + delOthersViews({ dispatch, state }, view) { + return new Promise(resolve => { + dispatch('delOthersVisitedViews', view) + dispatch('delOthersCachedViews', view) + resolve({ + visitedViews: [...state.visitedViews], + cachedViews: [...state.cachedViews] + }) + }) + }, + delOthersVisitedViews({ commit, state }, view) { + return new Promise(resolve => { + commit('DEL_OTHERS_VISITED_VIEWS', view) + resolve([...state.visitedViews]) + }) + }, + delOthersCachedViews({ commit, state }, view) { + return new Promise(resolve => { + commit('DEL_OTHERS_CACHED_VIEWS', view) + resolve([...state.cachedViews]) + }) + }, + + delAllViews({ dispatch, state }, view) { + return new Promise(resolve => { + dispatch('delAllVisitedViews', view) + dispatch('delAllCachedViews', view) + resolve({ + visitedViews: [...state.visitedViews], + cachedViews: [...state.cachedViews] + }) + }) + }, + delAllVisitedViews({ commit, state }) { + return new Promise(resolve => { + commit('DEL_ALL_VISITED_VIEWS') + resolve([...state.visitedViews]) + }) + }, + delAllCachedViews({ commit, state }) { + return new Promise(resolve => { + commit('DEL_ALL_CACHED_VIEWS') + resolve([...state.cachedViews]) + }) + }, + + updateVisitedView({ commit }, view) { + commit('UPDATE_VISITED_VIEW', view) + } +} + +export default { + namespaced: true, + state, + mutations, + actions +} diff --git a/src/store/getters.js b/src/store/getters.js index 9780358..c33a49d 100644 --- a/src/store/getters.js +++ b/src/store/getters.js @@ -1,4 +1,6 @@ const getters = { + visitedViews: state => state.tagsView.visitedViews, + cachedViews: state => state.tagsView.cachedViews, sidebar: state => state.app.sidebar, // 侧边栏 device: state => state.app.device, // 设备 kaptcha: state => state.app.kaptcha, // 验证码 diff --git a/src/store/index.js b/src/store/index.js index 9bfa6a7..c7e23ff 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -3,6 +3,7 @@ import app from './modules/app' import user from './modules/user' import permission from './modules/permission' +import tagsView from './modules/tagsView' import getters from './getters' Vue.use(Vuex) @@ -11,7 +12,8 @@ modules: { app, user, - permission + permission, + tagsView }, getters }) diff --git a/src/store/modules/tagsView.js b/src/store/modules/tagsView.js new file mode 100644 index 0000000..b7e3be9 --- /dev/null +++ b/src/store/modules/tagsView.js @@ -0,0 +1,165 @@ +const state = { + visitedViews: [], // 用户访问过的页面 + cachedViews: [] // 实际keep-alive的路由,可以在配置路由的时候通过meta.noCache来设置是否需要缓存,默认都缓存 +} + +const mutations = { + ADD_VISITED_VIEW: (state, view) => { + if (state.visitedViews.some(v => v.path === view.path)) return + state.visitedViews.push( + Object.assign({}, view, { + title: view.meta.title || 'no-name' + }) + ) + }, + ADD_CACHED_VIEW: (state, view) => { + if (state.cachedViews.includes(view.name)) return + if (!view.meta.noCache) { + state.cachedViews.push(view.name) + } + }, + + DEL_VISITED_VIEW: (state, view) => { + for (const [i, v] of state.visitedViews.entries()) { + if (v.path === view.path) { + state.visitedViews.splice(i, 1) + break + } + } + }, + DEL_CACHED_VIEW: (state, view) => { + for (const i of state.cachedViews) { + if (i === view.name) { + const index = state.cachedViews.indexOf(i) + state.cachedViews.splice(index, 1) + break + } + } + }, + + DEL_OTHERS_VISITED_VIEWS: (state, view) => { + state.visitedViews = state.visitedViews.filter(v => { + return v.meta.affix || v.path === view.path + }) + }, + DEL_OTHERS_CACHED_VIEWS: (state, view) => { + for (const i of state.cachedViews) { + if (i === view.name) { + const index = state.cachedViews.indexOf(i) + state.cachedViews = state.cachedViews.slice(index, index + 1) + break + } + } + }, + + DEL_ALL_VISITED_VIEWS: state => { + // keep affix tags + const affixTags = state.visitedViews.filter(tag => tag.meta.affix) + state.visitedViews = affixTags + }, + DEL_ALL_CACHED_VIEWS: state => { + state.cachedViews = [] + }, + + UPDATE_VISITED_VIEW: (state, view) => { + for (let v of state.visitedViews) { + if (v.path === view.path) { + v = Object.assign(v, view) + break + } + } + } +} + +const actions = { + addView({ dispatch }, view) { + dispatch('addVisitedView', view) + dispatch('addCachedView', view) + }, + addVisitedView({ commit }, view) { + commit('ADD_VISITED_VIEW', view) + }, + addCachedView({ commit }, view) { + commit('ADD_CACHED_VIEW', view) + }, + + delView({ dispatch, state }, view) { + return new Promise(resolve => { + dispatch('delVisitedView', view) + dispatch('delCachedView', view) + resolve({ + visitedViews: [...state.visitedViews], + cachedViews: [...state.cachedViews] + }) + }) + }, + delVisitedView({ commit, state }, view) { + return new Promise(resolve => { + commit('DEL_VISITED_VIEW', view) + resolve([...state.visitedViews]) + }) + }, + delCachedView({ commit, state }, view) { + return new Promise(resolve => { + commit('DEL_CACHED_VIEW', view) + resolve([...state.cachedViews]) + }) + }, + + delOthersViews({ dispatch, state }, view) { + return new Promise(resolve => { + dispatch('delOthersVisitedViews', view) + dispatch('delOthersCachedViews', view) + resolve({ + visitedViews: [...state.visitedViews], + cachedViews: [...state.cachedViews] + }) + }) + }, + delOthersVisitedViews({ commit, state }, view) { + return new Promise(resolve => { + commit('DEL_OTHERS_VISITED_VIEWS', view) + resolve([...state.visitedViews]) + }) + }, + delOthersCachedViews({ commit, state }, view) { + return new Promise(resolve => { + commit('DEL_OTHERS_CACHED_VIEWS', view) + resolve([...state.cachedViews]) + }) + }, + + delAllViews({ dispatch, state }, view) { + return new Promise(resolve => { + dispatch('delAllVisitedViews', view) + dispatch('delAllCachedViews', view) + resolve({ + visitedViews: [...state.visitedViews], + cachedViews: [...state.cachedViews] + }) + }) + }, + delAllVisitedViews({ commit, state }) { + return new Promise(resolve => { + commit('DEL_ALL_VISITED_VIEWS') + resolve([...state.visitedViews]) + }) + }, + delAllCachedViews({ commit, state }) { + return new Promise(resolve => { + commit('DEL_ALL_CACHED_VIEWS') + resolve([...state.cachedViews]) + }) + }, + + updateVisitedView({ commit }, view) { + commit('UPDATE_VISITED_VIEW', view) + } +} + +export default { + namespaced: true, + state, + mutations, + actions +} diff --git a/src/views/layout/Layout.vue b/src/views/layout/Layout.vue index a451849..c9b481f 100644 --- a/src/views/layout/Layout.vue +++ b/src/views/layout/Layout.vue @@ -9,6 +9,8 @@
+ + @@ -22,10 +24,12 @@ diff --git a/src/store/getters.js b/src/store/getters.js index 9780358..c33a49d 100644 --- a/src/store/getters.js +++ b/src/store/getters.js @@ -1,4 +1,6 @@ const getters = { + visitedViews: state => state.tagsView.visitedViews, + cachedViews: state => state.tagsView.cachedViews, sidebar: state => state.app.sidebar, // 侧边栏 device: state => state.app.device, // 设备 kaptcha: state => state.app.kaptcha, // 验证码 diff --git a/src/store/index.js b/src/store/index.js index 9bfa6a7..c7e23ff 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -3,6 +3,7 @@ import app from './modules/app' import user from './modules/user' import permission from './modules/permission' +import tagsView from './modules/tagsView' import getters from './getters' Vue.use(Vuex) @@ -11,7 +12,8 @@ modules: { app, user, - permission + permission, + tagsView }, getters }) diff --git a/src/store/modules/tagsView.js b/src/store/modules/tagsView.js new file mode 100644 index 0000000..b7e3be9 --- /dev/null +++ b/src/store/modules/tagsView.js @@ -0,0 +1,165 @@ +const state = { + visitedViews: [], // 用户访问过的页面 + cachedViews: [] // 实际keep-alive的路由,可以在配置路由的时候通过meta.noCache来设置是否需要缓存,默认都缓存 +} + +const mutations = { + ADD_VISITED_VIEW: (state, view) => { + if (state.visitedViews.some(v => v.path === view.path)) return + state.visitedViews.push( + Object.assign({}, view, { + title: view.meta.title || 'no-name' + }) + ) + }, + ADD_CACHED_VIEW: (state, view) => { + if (state.cachedViews.includes(view.name)) return + if (!view.meta.noCache) { + state.cachedViews.push(view.name) + } + }, + + DEL_VISITED_VIEW: (state, view) => { + for (const [i, v] of state.visitedViews.entries()) { + if (v.path === view.path) { + state.visitedViews.splice(i, 1) + break + } + } + }, + DEL_CACHED_VIEW: (state, view) => { + for (const i of state.cachedViews) { + if (i === view.name) { + const index = state.cachedViews.indexOf(i) + state.cachedViews.splice(index, 1) + break + } + } + }, + + DEL_OTHERS_VISITED_VIEWS: (state, view) => { + state.visitedViews = state.visitedViews.filter(v => { + return v.meta.affix || v.path === view.path + }) + }, + DEL_OTHERS_CACHED_VIEWS: (state, view) => { + for (const i of state.cachedViews) { + if (i === view.name) { + const index = state.cachedViews.indexOf(i) + state.cachedViews = state.cachedViews.slice(index, index + 1) + break + } + } + }, + + DEL_ALL_VISITED_VIEWS: state => { + // keep affix tags + const affixTags = state.visitedViews.filter(tag => tag.meta.affix) + state.visitedViews = affixTags + }, + DEL_ALL_CACHED_VIEWS: state => { + state.cachedViews = [] + }, + + UPDATE_VISITED_VIEW: (state, view) => { + for (let v of state.visitedViews) { + if (v.path === view.path) { + v = Object.assign(v, view) + break + } + } + } +} + +const actions = { + addView({ dispatch }, view) { + dispatch('addVisitedView', view) + dispatch('addCachedView', view) + }, + addVisitedView({ commit }, view) { + commit('ADD_VISITED_VIEW', view) + }, + addCachedView({ commit }, view) { + commit('ADD_CACHED_VIEW', view) + }, + + delView({ dispatch, state }, view) { + return new Promise(resolve => { + dispatch('delVisitedView', view) + dispatch('delCachedView', view) + resolve({ + visitedViews: [...state.visitedViews], + cachedViews: [...state.cachedViews] + }) + }) + }, + delVisitedView({ commit, state }, view) { + return new Promise(resolve => { + commit('DEL_VISITED_VIEW', view) + resolve([...state.visitedViews]) + }) + }, + delCachedView({ commit, state }, view) { + return new Promise(resolve => { + commit('DEL_CACHED_VIEW', view) + resolve([...state.cachedViews]) + }) + }, + + delOthersViews({ dispatch, state }, view) { + return new Promise(resolve => { + dispatch('delOthersVisitedViews', view) + dispatch('delOthersCachedViews', view) + resolve({ + visitedViews: [...state.visitedViews], + cachedViews: [...state.cachedViews] + }) + }) + }, + delOthersVisitedViews({ commit, state }, view) { + return new Promise(resolve => { + commit('DEL_OTHERS_VISITED_VIEWS', view) + resolve([...state.visitedViews]) + }) + }, + delOthersCachedViews({ commit, state }, view) { + return new Promise(resolve => { + commit('DEL_OTHERS_CACHED_VIEWS', view) + resolve([...state.cachedViews]) + }) + }, + + delAllViews({ dispatch, state }, view) { + return new Promise(resolve => { + dispatch('delAllVisitedViews', view) + dispatch('delAllCachedViews', view) + resolve({ + visitedViews: [...state.visitedViews], + cachedViews: [...state.cachedViews] + }) + }) + }, + delAllVisitedViews({ commit, state }) { + return new Promise(resolve => { + commit('DEL_ALL_VISITED_VIEWS') + resolve([...state.visitedViews]) + }) + }, + delAllCachedViews({ commit, state }) { + return new Promise(resolve => { + commit('DEL_ALL_CACHED_VIEWS') + resolve([...state.cachedViews]) + }) + }, + + updateVisitedView({ commit }, view) { + commit('UPDATE_VISITED_VIEW', view) + } +} + +export default { + namespaced: true, + state, + mutations, + actions +} diff --git a/src/views/layout/Layout.vue b/src/views/layout/Layout.vue index a451849..c9b481f 100644 --- a/src/views/layout/Layout.vue +++ b/src/views/layout/Layout.vue @@ -9,6 +9,8 @@
+ + @@ -22,10 +24,12 @@ diff --git a/src/views/layout/components/TagsView/ScrollPane.vue b/src/views/layout/components/TagsView/ScrollPane.vue new file mode 100644 index 0000000..0ec76e7 --- /dev/null +++ b/src/views/layout/components/TagsView/ScrollPane.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/src/store/getters.js b/src/store/getters.js index 9780358..c33a49d 100644 --- a/src/store/getters.js +++ b/src/store/getters.js @@ -1,4 +1,6 @@ const getters = { + visitedViews: state => state.tagsView.visitedViews, + cachedViews: state => state.tagsView.cachedViews, sidebar: state => state.app.sidebar, // 侧边栏 device: state => state.app.device, // 设备 kaptcha: state => state.app.kaptcha, // 验证码 diff --git a/src/store/index.js b/src/store/index.js index 9bfa6a7..c7e23ff 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -3,6 +3,7 @@ import app from './modules/app' import user from './modules/user' import permission from './modules/permission' +import tagsView from './modules/tagsView' import getters from './getters' Vue.use(Vuex) @@ -11,7 +12,8 @@ modules: { app, user, - permission + permission, + tagsView }, getters }) diff --git a/src/store/modules/tagsView.js b/src/store/modules/tagsView.js new file mode 100644 index 0000000..b7e3be9 --- /dev/null +++ b/src/store/modules/tagsView.js @@ -0,0 +1,165 @@ +const state = { + visitedViews: [], // 用户访问过的页面 + cachedViews: [] // 实际keep-alive的路由,可以在配置路由的时候通过meta.noCache来设置是否需要缓存,默认都缓存 +} + +const mutations = { + ADD_VISITED_VIEW: (state, view) => { + if (state.visitedViews.some(v => v.path === view.path)) return + state.visitedViews.push( + Object.assign({}, view, { + title: view.meta.title || 'no-name' + }) + ) + }, + ADD_CACHED_VIEW: (state, view) => { + if (state.cachedViews.includes(view.name)) return + if (!view.meta.noCache) { + state.cachedViews.push(view.name) + } + }, + + DEL_VISITED_VIEW: (state, view) => { + for (const [i, v] of state.visitedViews.entries()) { + if (v.path === view.path) { + state.visitedViews.splice(i, 1) + break + } + } + }, + DEL_CACHED_VIEW: (state, view) => { + for (const i of state.cachedViews) { + if (i === view.name) { + const index = state.cachedViews.indexOf(i) + state.cachedViews.splice(index, 1) + break + } + } + }, + + DEL_OTHERS_VISITED_VIEWS: (state, view) => { + state.visitedViews = state.visitedViews.filter(v => { + return v.meta.affix || v.path === view.path + }) + }, + DEL_OTHERS_CACHED_VIEWS: (state, view) => { + for (const i of state.cachedViews) { + if (i === view.name) { + const index = state.cachedViews.indexOf(i) + state.cachedViews = state.cachedViews.slice(index, index + 1) + break + } + } + }, + + DEL_ALL_VISITED_VIEWS: state => { + // keep affix tags + const affixTags = state.visitedViews.filter(tag => tag.meta.affix) + state.visitedViews = affixTags + }, + DEL_ALL_CACHED_VIEWS: state => { + state.cachedViews = [] + }, + + UPDATE_VISITED_VIEW: (state, view) => { + for (let v of state.visitedViews) { + if (v.path === view.path) { + v = Object.assign(v, view) + break + } + } + } +} + +const actions = { + addView({ dispatch }, view) { + dispatch('addVisitedView', view) + dispatch('addCachedView', view) + }, + addVisitedView({ commit }, view) { + commit('ADD_VISITED_VIEW', view) + }, + addCachedView({ commit }, view) { + commit('ADD_CACHED_VIEW', view) + }, + + delView({ dispatch, state }, view) { + return new Promise(resolve => { + dispatch('delVisitedView', view) + dispatch('delCachedView', view) + resolve({ + visitedViews: [...state.visitedViews], + cachedViews: [...state.cachedViews] + }) + }) + }, + delVisitedView({ commit, state }, view) { + return new Promise(resolve => { + commit('DEL_VISITED_VIEW', view) + resolve([...state.visitedViews]) + }) + }, + delCachedView({ commit, state }, view) { + return new Promise(resolve => { + commit('DEL_CACHED_VIEW', view) + resolve([...state.cachedViews]) + }) + }, + + delOthersViews({ dispatch, state }, view) { + return new Promise(resolve => { + dispatch('delOthersVisitedViews', view) + dispatch('delOthersCachedViews', view) + resolve({ + visitedViews: [...state.visitedViews], + cachedViews: [...state.cachedViews] + }) + }) + }, + delOthersVisitedViews({ commit, state }, view) { + return new Promise(resolve => { + commit('DEL_OTHERS_VISITED_VIEWS', view) + resolve([...state.visitedViews]) + }) + }, + delOthersCachedViews({ commit, state }, view) { + return new Promise(resolve => { + commit('DEL_OTHERS_CACHED_VIEWS', view) + resolve([...state.cachedViews]) + }) + }, + + delAllViews({ dispatch, state }, view) { + return new Promise(resolve => { + dispatch('delAllVisitedViews', view) + dispatch('delAllCachedViews', view) + resolve({ + visitedViews: [...state.visitedViews], + cachedViews: [...state.cachedViews] + }) + }) + }, + delAllVisitedViews({ commit, state }) { + return new Promise(resolve => { + commit('DEL_ALL_VISITED_VIEWS') + resolve([...state.visitedViews]) + }) + }, + delAllCachedViews({ commit, state }) { + return new Promise(resolve => { + commit('DEL_ALL_CACHED_VIEWS') + resolve([...state.cachedViews]) + }) + }, + + updateVisitedView({ commit }, view) { + commit('UPDATE_VISITED_VIEW', view) + } +} + +export default { + namespaced: true, + state, + mutations, + actions +} diff --git a/src/views/layout/Layout.vue b/src/views/layout/Layout.vue index a451849..c9b481f 100644 --- a/src/views/layout/Layout.vue +++ b/src/views/layout/Layout.vue @@ -9,6 +9,8 @@
+ + @@ -22,10 +24,12 @@ diff --git a/src/views/layout/components/TagsView/ScrollPane.vue b/src/views/layout/components/TagsView/ScrollPane.vue new file mode 100644 index 0000000..0ec76e7 --- /dev/null +++ b/src/views/layout/components/TagsView/ScrollPane.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/src/views/layout/components/TagsView/index.vue b/src/views/layout/components/TagsView/index.vue new file mode 100644 index 0000000..8683a46 --- /dev/null +++ b/src/views/layout/components/TagsView/index.vue @@ -0,0 +1,287 @@ + + + + + + +