{"remainingRequest":"D:\\源码\\vue-element-admin-master\\node_modules\\vue-loader\\lib\\index.js??vue-loader-options!D:\\源码\\vue-element-admin-master\\src\\layout\\components\\TagsView\\index.vue?vue&type=style&index=0&id=fac8ca64&lang=scss&scoped=true&","dependencies":[{"path":"D:\\源码\\vue-element-admin-master\\src\\layout\\components\\TagsView\\index.vue","mtime":1649647926000},{"path":"D:\\源码\\vue-element-admin-master\\node_modules\\css-loader\\dist\\cjs.js","mtime":499162500000},{"path":"D:\\源码\\vue-element-admin-master\\node_modules\\vue-loader\\lib\\loaders\\stylePostLoader.js","mtime":499162500000},{"path":"D:\\源码\\vue-element-admin-master\\node_modules\\postcss-loader\\src\\index.js","mtime":499162500000},{"path":"D:\\源码\\vue-element-admin-master\\node_modules\\sass-loader\\dist\\cjs.js","mtime":499162500000},{"path":"D:\\源码\\vue-element-admin-master\\node_modules\\cache-loader\\dist\\cjs.js","mtime":499162500000},{"path":"D:\\源码\\vue-element-admin-master\\node_modules\\vue-loader\\lib\\index.js","mtime":499162500000}],"contextDependencies":[],"result":[{"type":"Buffer","data":"base64:CgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoudGFncy12aWV3LWNvbnRhaW5lciB7CiAgaGVpZ2h0OiAzNHB4OwogIHdpZHRoOiAxMDAlOwogIGJhY2tncm91bmQ6ICNmZmY7CiAgYm9yZGVyLWJvdHRvbTogMXB4IHNvbGlkICNkOGRjZTU7CiAgYm94LXNoYWRvdzogMCAxcHggM3B4IDAgcmdiYSgwLCAwLCAwLCAuMTIpLCAwIDAgM3B4IDAgcmdiYSgwLCAwLCAwLCAuMDQpOwogIC50YWdzLXZpZXctd3JhcHBlciB7CiAgICAudGFncy12aWV3LWl0ZW0gewogICAgICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7CiAgICAgIHBvc2l0aW9uOiByZWxhdGl2ZTsKICAgICAgY3Vyc29yOiBwb2ludGVyOwogICAgICBoZWlnaHQ6IDI2cHg7CiAgICAgIGxpbmUtaGVpZ2h0OiAyNnB4OwogICAgICBib3JkZXI6IDFweCBzb2xpZCAjZDhkY2U1OwogICAgICBjb2xvcjogIzQ5NTA2MDsKICAgICAgYmFja2dyb3VuZDogI2ZmZjsKICAgICAgcGFkZGluZzogMCA4cHg7CiAgICAgIGZvbnQtc2l6ZTogMTJweDsKICAgICAgbWFyZ2luLWxlZnQ6IDVweDsKICAgICAgbWFyZ2luLXRvcDogNHB4OwogICAgICAmOmZpcnN0LW9mLXR5cGUgewogICAgICAgIG1hcmdpbi1sZWZ0OiAxNXB4OwogICAgICB9CiAgICAgICY6bGFzdC1vZi10eXBlIHsKICAgICAgICBtYXJnaW4tcmlnaHQ6IDE1cHg7CiAgICAgIH0KICAgICAgJi5hY3RpdmUgewogICAgICAgIGJhY2tncm91bmQtY29sb3I6ICM0MmI5ODM7CiAgICAgICAgY29sb3I6ICNmZmY7CiAgICAgICAgYm9yZGVyLWNvbG9yOiAjNDJiOTgzOwogICAgICAgICY6OmJlZm9yZSB7CiAgICAgICAgICBjb250ZW50OiAnJzsKICAgICAgICAgIGJhY2tncm91bmQ6ICNmZmY7CiAgICAgICAgICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7CiAgICAgICAgICB3aWR0aDogOHB4OwogICAgICAgICAgaGVpZ2h0OiA4cHg7CiAgICAgICAgICBib3JkZXItcmFkaXVzOiA1MCU7CiAgICAgICAgICBwb3NpdGlvbjogcmVsYXRpdmU7CiAgICAgICAgICBtYXJnaW4tcmlnaHQ6IDJweDsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICB9CiAgLmNvbnRleHRtZW51IHsKICAgIG1hcmdpbjogMDsKICAgIGJhY2tncm91bmQ6ICNmZmY7CiAgICB6LWluZGV4OiAzMDAwOwogICAgcG9zaXRpb246IGFic29sdXRlOwogICAgbGlzdC1zdHlsZS10eXBlOiBub25lOwogICAgcGFkZGluZzogNXB4IDA7CiAgICBib3JkZXItcmFkaXVzOiA0cHg7CiAgICBmb250LXNpemU6IDEycHg7CiAgICBmb250LXdlaWdodDogNDAwOwogICAgY29sb3I6ICMzMzM7CiAgICBib3gtc2hhZG93OiAycHggMnB4IDNweCAwIHJnYmEoMCwgMCwgMCwgLjMpOwogICAgbGkgewogICAgICBtYXJnaW46IDA7CiAgICAgIHBhZGRpbmc6IDdweCAxNnB4OwogICAgICBjdXJzb3I6IHBvaW50ZXI7CiAgICAgICY6aG92ZXIgewogICAgICAgIGJhY2tncm91bmQ6ICNlZWU7CiAgICAgIH0KICAgIH0KICB9Cn0K"},{"version":3,"sources":["index.vue"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"index.vue","sourceRoot":"src/layout/components/TagsView","sourcesContent":["<template>\n <div id=\"tags-view-container\" class=\"tags-view-container\">\n <scroll-pane ref=\"scrollPane\" class=\"tags-view-wrapper\" @scroll=\"handleScroll\">\n <router-link\n v-for=\"tag in visitedViews\"\n ref=\"tag\"\n :key=\"tag.path\"\n :class=\"isActive(tag)?'active':''\"\n :to=\"{ path: tag.path, query: tag.query, fullPath: tag.fullPath }\"\n tag=\"span\"\n class=\"tags-view-item\"\n @click.middle.native=\"!isAffix(tag)?closeSelectedTag(tag):''\"\n @contextmenu.prevent.native=\"openMenu(tag,$event)\"\n >\n {{ tag.title }}\n <span v-if=\"!isAffix(tag)\" class=\"el-icon-close\" @click.prevent.stop=\"closeSelectedTag(tag)\" />\n </router-link>\n </scroll-pane>\n <ul v-show=\"visible\" :style=\"{left:left+'px',top:top+'px'}\" class=\"contextmenu\">\n <li @click=\"refreshSelectedTag(selectedTag)\">Refresh</li>\n <li v-if=\"!isAffix(selectedTag)\" @click=\"closeSelectedTag(selectedTag)\">Close</li>\n <li @click=\"closeOthersTags\">Close Others</li>\n <li @click=\"closeAllTags(selectedTag)\">Close All</li>\n </ul>\n </div>\n</template>\n\n<script>\nimport ScrollPane from './ScrollPane'\nimport path from 'path'\n\nexport default {\n components: { ScrollPane },\n data() {\n return {\n visible: false,\n top: 0,\n left: 0,\n selectedTag: {},\n affixTags: []\n }\n },\n computed: {\n visitedViews() {\n return this.$store.state.tagsView.visitedViews\n },\n routes() {\n return this.$store.state.permission.routes\n }\n },\n watch: {\n $route() {\n this.addTags()\n this.moveToCurrentTag()\n },\n visible(value) {\n if (value) {\n document.body.addEventListener('click', this.closeMenu)\n } else {\n document.body.removeEventListener('click', this.closeMenu)\n }\n }\n },\n mounted() {\n this.initTags()\n this.addTags()\n },\n methods: {\n isActive(route) {\n return route.path === this.$route.path\n },\n isAffix(tag) {\n return tag.meta && tag.meta.affix\n },\n filterAffixTags(routes, basePath = '/') {\n let tags = []\n routes.forEach(route => {\n if (route.meta && route.meta.affix) {\n const tagPath = path.resolve(basePath, route.path)\n tags.push({\n fullPath: tagPath,\n path: tagPath,\n name: route.name,\n meta: { ...route.meta }\n })\n }\n if (route.children) {\n const tempTags = this.filterAffixTags(route.children, route.path)\n if (tempTags.length >= 1) {\n tags = [...tags, ...tempTags]\n }\n }\n })\n return tags\n },\n initTags() {\n const affixTags = this.affixTags = this.filterAffixTags(this.routes)\n for (const tag of affixTags) {\n // Must have tag name\n if (tag.name) {\n this.$store.dispatch('tagsView/addVisitedView', tag)\n }\n }\n },\n addTags() {\n const { name } = this.$route\n if (name) {\n this.$store.dispatch('tagsView/addView', this.$route)\n }\n return false\n },\n moveToCurrentTag() {\n const tags = this.$refs.tag\n this.$nextTick(() => {\n for (const tag of tags) {\n if (tag.to.path === this.$route.path) {\n this.$refs.scrollPane.moveToTarget(tag)\n // when query is different then update\n if (tag.to.fullPath !== this.$route.fullPath) {\n this.$store.dispatch('tagsView/updateVisitedView', this.$route)\n }\n break\n }\n }\n })\n },\n refreshSelectedTag(view) {\n this.$store.dispatch('tagsView/delCachedView', view).then(() => {\n const { fullPath } = view\n this.$nextTick(() => {\n this.$router.replace({\n path: '/redirect' + fullPath\n })\n })\n })\n },\n closeSelectedTag(view) {\n this.$store.dispatch('tagsView/delView', view).then(({ visitedViews }) => {\n if (this.isActive(view)) {\n this.toLastView(visitedViews, view)\n }\n })\n },\n closeOthersTags() {\n this.$router.push(this.selectedTag)\n this.$store.dispatch('tagsView/delOthersViews', this.selectedTag).then(() => {\n this.moveToCurrentTag()\n })\n },\n closeAllTags(view) {\n this.$store.dispatch('tagsView/delAllViews').then(({ visitedViews }) => {\n if (this.affixTags.some(tag => tag.path === view.path)) {\n return\n }\n this.toLastView(visitedViews, view)\n })\n },\n toLastView(visitedViews, view) {\n const latestView = visitedViews.slice(-1)[0]\n if (latestView) {\n this.$router.push(latestView.fullPath)\n } else {\n // now the default is to redirect to the home page if there is no tags-view,\n // you can adjust it according to your needs.\n if (view.name === 'Dashboard') {\n // to reload home page\n this.$router.replace({ path: '/redirect' + view.fullPath })\n } else {\n this.$router.push('/')\n }\n }\n },\n openMenu(tag, e) {\n const menuMinWidth = 105\n const offsetLeft = this.$el.getBoundingClientRect().left // container margin left\n const offsetWidth = this.$el.offsetWidth // container width\n const maxLeft = offsetWidth - menuMinWidth // left boundary\n const left = e.clientX - offsetLeft + 15 // 15: margin right\n\n if (left > maxLeft) {\n this.left = maxLeft\n } else {\n this.left = left\n }\n\n this.top = e.clientY\n this.visible = true\n this.selectedTag = tag\n },\n closeMenu() {\n this.visible = false\n },\n handleScroll() {\n this.closeMenu()\n }\n }\n}\n</script>\n\n<style lang=\"scss\" scoped>\n.tags-view-container {\n height: 34px;\n width: 100%;\n background: #fff;\n border-bottom: 1px solid #d8dce5;\n box-shadow: 0 1px 3px 0 rgba(0, 0, 0, .12), 0 0 3px 0 rgba(0, 0, 0, .04);\n .tags-view-wrapper {\n .tags-view-item {\n display: inline-block;\n position: relative;\n cursor: pointer;\n height: 26px;\n line-height: 26px;\n border: 1px solid #d8dce5;\n color: #495060;\n background: #fff;\n padding: 0 8px;\n font-size: 12px;\n margin-left: 5px;\n margin-top: 4px;\n &:first-of-type {\n margin-left: 15px;\n }\n &:last-of-type {\n margin-right: 15px;\n }\n &.active {\n background-color: #42b983;\n color: #fff;\n border-color: #42b983;\n &::before {\n content: '';\n background: #fff;\n display: inline-block;\n width: 8px;\n height: 8px;\n border-radius: 50%;\n position: relative;\n margin-right: 2px;\n }\n }\n }\n }\n .contextmenu {\n margin: 0;\n background: #fff;\n z-index: 3000;\n position: absolute;\n list-style-type: none;\n padding: 5px 0;\n border-radius: 4px;\n font-size: 12px;\n font-weight: 400;\n color: #333;\n box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, .3);\n li {\n margin: 0;\n padding: 7px 16px;\n cursor: pointer;\n &:hover {\n background: #eee;\n }\n }\n }\n}\n</style>\n\n<style lang=\"scss\">\n//reset element css of el-icon-close\n.tags-view-wrapper {\n .tags-view-item {\n .el-icon-close {\n width: 16px;\n height: 16px;\n vertical-align: 2px;\n border-radius: 50%;\n text-align: center;\n transition: all .3s cubic-bezier(.645, .045, .355, 1);\n transform-origin: 100% 50%;\n &:before {\n transform: scale(.6);\n display: inline-block;\n vertical-align: -3px;\n }\n &:hover {\n background-color: #b4bccc;\n color: #fff;\n }\n }\n }\n}\n</style>\n"]}]}
|