summaryrefslogtreecommitdiff
path: root/UI source code/dns_mapping_ui-master/src/layout/components
diff options
context:
space:
mode:
Diffstat (limited to 'UI source code/dns_mapping_ui-master/src/layout/components')
-rw-r--r--UI source code/dns_mapping_ui-master/src/layout/components/AppMain.vue63
-rw-r--r--UI source code/dns_mapping_ui-master/src/layout/components/HeadNavbar/FixiOSBug.js26
-rw-r--r--UI source code/dns_mapping_ui-master/src/layout/components/HeadNavbar/Item.vue29
-rw-r--r--UI source code/dns_mapping_ui-master/src/layout/components/HeadNavbar/Link.vue36
-rw-r--r--UI source code/dns_mapping_ui-master/src/layout/components/HeadNavbar/Logo.vue44
-rw-r--r--UI source code/dns_mapping_ui-master/src/layout/components/HeadNavbar/SidebarItem.vue105
-rw-r--r--UI source code/dns_mapping_ui-master/src/layout/components/HeadNavbar/index.vue90
-rw-r--r--UI source code/dns_mapping_ui-master/src/layout/components/Navbar.vue210
-rw-r--r--UI source code/dns_mapping_ui-master/src/layout/components/Settings/index.vue141
-rw-r--r--UI source code/dns_mapping_ui-master/src/layout/components/Sidebar/FixiOSBug.js26
-rw-r--r--UI source code/dns_mapping_ui-master/src/layout/components/Sidebar/Item.vue29
-rw-r--r--UI source code/dns_mapping_ui-master/src/layout/components/Sidebar/Link.vue36
-rw-r--r--UI source code/dns_mapping_ui-master/src/layout/components/Sidebar/Logo.vue82
-rw-r--r--UI source code/dns_mapping_ui-master/src/layout/components/Sidebar/SidebarItem.vue95
-rw-r--r--UI source code/dns_mapping_ui-master/src/layout/components/Sidebar/index.vue56
-rw-r--r--UI source code/dns_mapping_ui-master/src/layout/components/TagsView/ScrollPane.vue86
-rw-r--r--UI source code/dns_mapping_ui-master/src/layout/components/TagsView/index.vue286
-rw-r--r--UI source code/dns_mapping_ui-master/src/layout/components/index.js6
18 files changed, 1446 insertions, 0 deletions
diff --git a/UI source code/dns_mapping_ui-master/src/layout/components/AppMain.vue b/UI source code/dns_mapping_ui-master/src/layout/components/AppMain.vue
new file mode 100644
index 0000000..1a737b2
--- /dev/null
+++ b/UI source code/dns_mapping_ui-master/src/layout/components/AppMain.vue
@@ -0,0 +1,63 @@
+<template>
+ <section class="app-main">
+ <transition name="fade-transform" mode="out-in">
+ <keep-alive :include="cachedViews">
+ <router-view :key="key" />
+ </keep-alive>
+ </transition>
+ <!-- <div v-if="$store.state.settings.showFooter" id="el-main-footer">
+ <span v-html="$store.state.settings.footerTxt" />
+ <span> ⋅ </span>
+ <a href="https://beian.miit.gov.cn/#/Integrated/index" target="_blank">{{ $store.state.settings.caseNumber }}</a>
+ </div> -->
+ </section>
+</template>
+
+<script>
+export default {
+ name: 'AppMain',
+ computed: {
+ cachedViews() {
+ return this.$store.state.tagsView.cachedViews
+ },
+ key() {
+ return this.$route.path
+ }
+ }
+}
+</script>
+
+<style lang="scss" scoped>
+.app-main {
+ /* 50= navbar 50 */
+ min-height: calc(100vh - 50px);
+ width: 100%;
+ position: relative;
+ overflow: hidden;
+ background: #f7f9fc;
+}
+
+.fixed-header+.app-main {
+ padding-top: 50px;
+}
+
+.hasTagsView {
+ .app-main {
+ /* 84 = navbar + tags-view = 50 + 34 */
+ min-height: calc(100vh - 84px);
+ }
+
+ .fixed-header+.app-main {
+ padding-top: 84px;
+ }
+}
+</style>
+
+<style lang="scss">
+// fix css style bug in open el-dialog
+.el-popup-parent--hidden {
+ .fixed-header {
+ padding-right: 15px;
+ }
+}
+</style>
diff --git a/UI source code/dns_mapping_ui-master/src/layout/components/HeadNavbar/FixiOSBug.js b/UI source code/dns_mapping_ui-master/src/layout/components/HeadNavbar/FixiOSBug.js
new file mode 100644
index 0000000..bc14856
--- /dev/null
+++ b/UI source code/dns_mapping_ui-master/src/layout/components/HeadNavbar/FixiOSBug.js
@@ -0,0 +1,26 @@
+export default {
+ computed: {
+ device() {
+ return this.$store.state.app.device
+ }
+ },
+ mounted() {
+ // In order to fix the click on menu on the ios device will trigger the mouseleave bug
+ // https://github.com/PanJiaChen/vue-element-admin/issues/1135
+ this.fixBugIniOS()
+ },
+ methods: {
+ fixBugIniOS() {
+ const $subMenu = this.$refs.subMenu
+ if ($subMenu) {
+ const handleMouseleave = $subMenu.handleMouseleave
+ $subMenu.handleMouseleave = (e) => {
+ if (this.device === 'mobile') {
+ return
+ }
+ handleMouseleave(e)
+ }
+ }
+ }
+ }
+}
diff --git a/UI source code/dns_mapping_ui-master/src/layout/components/HeadNavbar/Item.vue b/UI source code/dns_mapping_ui-master/src/layout/components/HeadNavbar/Item.vue
new file mode 100644
index 0000000..b515f61
--- /dev/null
+++ b/UI source code/dns_mapping_ui-master/src/layout/components/HeadNavbar/Item.vue
@@ -0,0 +1,29 @@
+<script>
+export default {
+ name: 'MenuItem',
+ functional: true,
+ props: {
+ icon: {
+ type: String,
+ default: ''
+ },
+ title: {
+ type: String,
+ default: ''
+ }
+ },
+ render(h, context) {
+ const { icon, title } = context.props
+ const vnodes = []
+
+ if (icon) {
+ vnodes.push(<svg-icon icon-class={icon}/>)
+ }
+
+ if (title) {
+ vnodes.push(<span slot='title'>{(title)}</span>)
+ }
+ return vnodes
+ }
+}
+</script>
diff --git a/UI source code/dns_mapping_ui-master/src/layout/components/HeadNavbar/Link.vue b/UI source code/dns_mapping_ui-master/src/layout/components/HeadNavbar/Link.vue
new file mode 100644
index 0000000..eb4dd10
--- /dev/null
+++ b/UI source code/dns_mapping_ui-master/src/layout/components/HeadNavbar/Link.vue
@@ -0,0 +1,36 @@
+
+<template>
+ <!-- eslint-disable vue/require-component-is -->
+ <component v-bind="linkProps(to)">
+ <slot />
+ </component>
+</template>
+
+<script>
+import { isExternal } from '@/utils/validate'
+
+export default {
+ props: {
+ to: {
+ type: String,
+ required: true
+ }
+ },
+ methods: {
+ linkProps(url) {
+ if (isExternal(url)) {
+ return {
+ is: 'a',
+ href: url,
+ target: '_blank',
+ rel: 'noopener'
+ }
+ }
+ return {
+ is: 'router-link',
+ to: url
+ }
+ }
+ }
+}
+</script>
diff --git a/UI source code/dns_mapping_ui-master/src/layout/components/HeadNavbar/Logo.vue b/UI source code/dns_mapping_ui-master/src/layout/components/HeadNavbar/Logo.vue
new file mode 100644
index 0000000..e50a338
--- /dev/null
+++ b/UI source code/dns_mapping_ui-master/src/layout/components/HeadNavbar/Logo.vue
@@ -0,0 +1,44 @@
+<template>
+ <div class="log">
+ <img :src="logo" alt="">
+ <p>DiamondV</p>
+ </div>
+</template>
+
+<script>
+import Logo from '@/assets/images/newlogo.png'
+export default {
+ data() {
+ return {
+ logo: Logo
+ }
+ }
+}
+</script>
+
+<style lang="scss" scoped>
+
+.log{
+ width: 13%;
+ height: 56px;
+ background-color: #4608ad;
+ color: white;
+ text-align: center;
+ display: flex;
+ justify-content:center;
+ align-items: center;
+ font-size: 25px;
+ font-weight: 600;
+ p{
+ font-family:"仿宋";
+ font-style:italic;
+ font-size: 20px;
+ }
+ img{
+ margin-right: 18px;
+ width: 50px;
+ height: 55px;
+ }
+}
+
+</style>
diff --git a/UI source code/dns_mapping_ui-master/src/layout/components/HeadNavbar/SidebarItem.vue b/UI source code/dns_mapping_ui-master/src/layout/components/HeadNavbar/SidebarItem.vue
new file mode 100644
index 0000000..b4d2911
--- /dev/null
+++ b/UI source code/dns_mapping_ui-master/src/layout/components/HeadNavbar/SidebarItem.vue
@@ -0,0 +1,105 @@
+<template>
+ <!-- <div v-if="!item.hidden">-->
+ <!-- todo 增加了style样式 style="display:inline-block;"-->
+ <div v-if="!item.hidden" style="display:inline-block;">
+ <template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren)&&!item.alwaysShow">
+ <app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path)">
+ <el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}">
+ <item :icon="onlyOneChild.meta.icon||(item.meta&&item.meta.icon)" :title="onlyOneChild.meta.title" />
+ </el-menu-item>
+ </app-link>
+ </template>
+
+ <el-submenu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body>
+ <template slot="title">
+ <item v-if="item.meta" :icon="item.meta && item.meta.icon" :title="item.meta.title" />
+ <!--todo 增加div固定宽度,用于菜单上的小箭头显示-->
+ <div style="display: inline-block; width:20px;" />
+ </template>
+ <sidebar-item
+ v-for="child in item.children"
+ :key="child.path"
+ :is-nest="true"
+ :item="child"
+ :base-path="resolvePath(child.path)"
+ class="nest-menu"
+ />
+ </el-submenu>
+ </div>
+</template>
+
+<script>
+import path from 'path'
+import { isExternal } from '@/utils/validate'
+import Item from './Item'
+import AppLink from './Link'
+import FixiOSBug from './FixiOSBug'
+
+export default {
+ name: 'SidebarItem',
+ components: { Item, AppLink },
+ mixins: [FixiOSBug],
+ props: {
+ // route object
+ item: {
+ type: Object,
+ required: true
+ },
+ isNest: {
+ type: Boolean,
+ default: false
+ },
+ basePath: {
+ type: String,
+ default: ''
+ }
+ },
+ data() {
+ // To fix https://github.com/PanJiaChen/vue-admin-template/issues/237
+ // TODO: refactor with render function
+ this.onlyOneChild = null
+ return {}
+ },
+ methods: {
+ hasOneShowingChild(children = [], parent) {
+ const showingChildren = children.filter(item => {
+ if (item.hidden) {
+ return false
+ } else {
+ // Temp set(will be used if only has one showing child)
+ this.onlyOneChild = item
+ return true
+ }
+ })
+
+ // When there is only one child router, the child router is displayed by default
+ if (showingChildren.length === 1) {
+ return true
+ }
+
+ // Show parent if there are no child router to display
+ if (showingChildren.length === 0) {
+ this.onlyOneChild = { ... parent, path: '', noShowingChildren: true }
+ return true
+ }
+
+ return false
+ },
+ resolvePath(routePath) {
+ if (isExternal(routePath)) {
+ return routePath
+ }
+ if (isExternal(this.basePath)) {
+ return this.basePath
+ }
+ return path.resolve(this.basePath, routePath)
+ }
+ }
+}
+</script>
+<style scoped>
+.el-menu-item {
+ font-size: 17px;
+ color: white !important;
+}
+</style> \ No newline at end of file
diff --git a/UI source code/dns_mapping_ui-master/src/layout/components/HeadNavbar/index.vue b/UI source code/dns_mapping_ui-master/src/layout/components/HeadNavbar/index.vue
new file mode 100644
index 0000000..1076b36
--- /dev/null
+++ b/UI source code/dns_mapping_ui-master/src/layout/components/HeadNavbar/index.vue
@@ -0,0 +1,90 @@
+<template>
+ <!-- <div :class="{'has-logo':showLogo}" > -->
+ <div class="menu">
+ <!--TODO 文章中删除了logo,有验证了一次,可以不删除-->
+ <!-- <logo v-if="showLogo" :collapse="isCollapse"/> -->
+ <Logo />
+ <el-scrollbar id="navlist" wrap-class="scrollbar-wrapper">
+ <!--TODO 将el-menu标签下的mode属性更改为horizontal-->
+ <!-- <span>1111</span> -->
+ <el-menu
+ :default-active="activeMenu"
+ :collapse="isCollapse"
+ :background-color="variables.menuBg"
+ :text-color="variables.menuText"
+ :unique-opened="false"
+ :active-text-color="variables.menuActiveText"
+ :collapse-transition="false"
+ mode="horizontal"
+ >
+ <sidebar-item v-for="route in sidebarRouters" :key="route.path" :item="route" :base-path="route.path" />
+ </el-menu>
+ </el-scrollbar>
+ <navbar />
+ </div>
+</template>
+
+<script>
+import { mapGetters } from 'vuex'
+import SidebarItem from './SidebarItem'
+import variables from '@/assets/styles/variables.scss'
+import Navbar from '../Navbar.vue'
+import Logo from './Logo.vue'
+
+export default {
+ // components: {Logo },
+ components: { SidebarItem, Navbar, Logo },
+ computed: {
+ ...mapGetters([
+ 'sidebarRouters',
+ 'sidebar'
+ ]),
+ activeMenu() {
+ const route = this.$route
+ const { meta, path } = route
+ // if set path, the sidebar will highlight the path you set
+ if (meta.activeMenu) {
+ return meta.activeMenu
+ }
+ return path
+ },
+ showLogo() {
+ return this.$store.state.settings.sidebarLogo
+ },
+ variables() {
+ return variables
+ },
+ isCollapse() {
+ return !this.sidebar.opened
+ }
+ }
+}
+</script>
+<style lang="scss" scoped>
+.menu{
+ display: flex;
+}
+#navlist {
+width: 80% !important;
+float: left;
+}
+
+ #navlist >>> .el-submenu__title {
+ font-weight: 100;
+ font-size:18px !important;
+ color: white !important;
+ }
+ #navlist >>> .is-active{
+ font-size: 18px !important;
+ font-weight: 600 !important;
+ background-color: rgb(50, 4, 122) !important;
+ }
+ #navlist >>> .el-scrollbar__wrap{
+ margin-bottom: 0px;
+ overflow: hidden;
+ }
+/* .el-scrollbar__view{
+ display: flex;
+} */
+
+</style>
diff --git a/UI source code/dns_mapping_ui-master/src/layout/components/Navbar.vue b/UI source code/dns_mapping_ui-master/src/layout/components/Navbar.vue
new file mode 100644
index 0000000..e763c91
--- /dev/null
+++ b/UI source code/dns_mapping_ui-master/src/layout/components/Navbar.vue
@@ -0,0 +1,210 @@
+<template>
+ <div class="navbar">
+ <!-- <hamburger
+ v-if="menuInLeft"
+ id="hamburger-container"
+ :is-active="sidebar.opened"
+ class="hamburger-container"
+ @toggleClick="toggleSideBar"
+ /> -->
+
+ <!-- <breadcrumb id="breadcrumb-container" class="breadcrumb-container" /> -->
+
+ <div class="right-menu">
+ <!-- <template v-if="device !== 'mobile'">
+ <search id="header-search" class="right-menu-item" />
+
+ <el-tooltip content="项目文档" effect="dark" placement="bottom">
+ <Doc class="right-menu-item hover-effect" />
+ </el-tooltip>
+
+ <el-tooltip content="全屏缩放" effect="dark" placement="bottom">
+ <screenfull id="screenfull" class="right-menu-item hover-effect" />
+ </el-tooltip>
+
+ <el-tooltip content="布局设置" effect="dark" placement="bottom">
+ <size-select id="size-select" class="right-menu-item hover-effect" />
+ </el-tooltip>
+ </template> -->
+
+ <el-dropdown
+ class="avatar-container right-menu-item hover-effect"
+ trigger="click"
+ >
+ <div class="avatar-wrapper">
+ <!-- <img
+ :src="
+ user.avatarName ? baseApi + '/avatar/' + user.avatarName : Avatar
+ "
+ class="user-avatar"
+ /> -->
+ <i class="el-icon-user" />
+ <!-- <span>{{user.content.createBy}}</span> -->
+ <span>{{ user.username }}</span>
+ <i class="el-icon-caret-bottom" />
+ </div>
+ <el-dropdown-menu slot="dropdown">
+ <!-- <span style="display: block" @click="show = true">
+ <el-dropdown-item> 布局设置 </el-dropdown-item>
+ </span>
+ <router-link to="/user/center">
+ <el-dropdown-item> 个人中心 </el-dropdown-item>
+ </router-link> -->
+ <span style="display: block" @click="open">
+ <el-dropdown-item divided> 退出登录 </el-dropdown-item>
+ </span>
+ </el-dropdown-menu>
+ </el-dropdown>
+ </div>
+ </div>
+</template>
+
+<script>
+import { mapGetters, mapState } from 'vuex'
+// import Breadcrumb from "@/components/Breadcrumb";
+// import Hamburger from "@/components/Hamburger";
+// import Doc from "@/components/Doc";
+// import Screenfull from "@/components/Screenfull";
+// import SizeSelect from "@/components/SizeSelect";
+// import Search from "@/components/HeaderSearch";
+// import Avatar from "@/assets/images/avatar.png";
+
+export default {
+ components: {
+ // Breadcrumb,
+ // Hamburger,
+ // Screenfull,
+ // SizeSelect,
+ // Search,
+ // Doc,
+ },
+ data() {
+ return {
+ // Avatar: Avatar,
+ dialogVisible: false
+ }
+ },
+ computed: {
+ ...mapGetters(['sidebar', 'device', 'user', 'baseApi']),
+ ...mapState({
+ menuInLeft: state => state.settings.menuInLeft
+ }),
+ show: {
+ get() {
+ return this.$store.state.settings.showSettings
+ },
+ set(val) {
+ this.$store.dispatch('settings/changeSetting', {
+ key: 'showSettings',
+ value: val
+ })
+ }
+ }
+ },
+ methods: {
+ toggleSideBar() {
+ this.$store.dispatch('app/toggleSideBar')
+ },
+ open() {
+ this.$confirm('确定注销并退出系统吗?', '提示', {
+ confirmButtonText: '确定',
+ cancelButtonText: '取消',
+ type: 'warning'
+ }).then(() => {
+ this.logout()
+ })
+ },
+ logout() {
+ this.$store.dispatch('LogOut').then(() => {
+ location.reload()
+ })
+ }
+ }
+}
+</script>
+
+<style lang="scss" scoped>
+.navbar {
+ width: 10%;
+ height: 56px;
+ overflow: hidden;
+ position: relative;
+ background: #4608ad;
+ // box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
+
+ // .hamburger-container {
+ // line-height: 46px;
+ // height: 100%;
+ // float: left;
+ // cursor: pointer;
+ // transition: background 0.3s;
+ // -webkit-tap-highlight-color: transparent;
+
+ // &:hover {
+ // background: rgba(0, 0, 0, 0.025);
+ // }
+ // }
+
+ // .breadcrumb-container {
+ // float: left;
+ // }
+
+ // .errLog-container {
+ // display: inline-block;
+ // vertical-align: top;
+ // }
+
+ .right-menu {
+ // float: right;
+ height: 100%;
+ line-height: 50px;
+
+ &:focus {
+ outline: none;
+ }
+
+ .right-menu-item {
+ display: inline-block;
+ padding: 0 8px;
+ height: 100%;
+ font-size: 18px;
+ color: #5a5e66;
+ vertical-align: text-bottom;
+
+ &.hover-effect {
+ cursor: pointer;
+ transition: background 0.3s;
+
+ &:hover {
+ background: rgba(0, 0, 0, 0.025);
+ }
+ }
+ }
+
+ .avatar-container {
+ margin-right: 30px;
+
+ .avatar-wrapper {
+ margin-top: 5px;
+ position: relative;
+ color: white;
+
+ // .user-avatar {
+ // cursor: pointer;
+ // width: 40px;
+ // height: 40px;
+ // border-radius: 10px;
+ // }
+
+ .el-icon-caret-bottom {
+ cursor: pointer;
+ position: absolute;
+ right: -20px;
+ top: 25px;
+ font-size: 12px;
+ }
+ }
+ }
+ }
+}
+</style>
diff --git a/UI source code/dns_mapping_ui-master/src/layout/components/Settings/index.vue b/UI source code/dns_mapping_ui-master/src/layout/components/Settings/index.vue
new file mode 100644
index 0000000..3ed8092
--- /dev/null
+++ b/UI source code/dns_mapping_ui-master/src/layout/components/Settings/index.vue
@@ -0,0 +1,141 @@
+<template>
+ <div class="drawer-container">
+ <div>
+ <h3 class="drawer-title">系统布局设置</h3>
+
+ <div class="drawer-item">
+ <span>主题颜色</span>
+ <theme-picker style="float: right;height: 26px;margin: -3px 8px 0 0;" @change="themeChange" />
+ </div>
+
+ <div class="drawer-item">
+ <span>显示标签</span>
+ <el-switch v-model="tagsView" class="drawer-switch" />
+ </div>
+
+ <div class="drawer-item">
+ <span>固定头部</span>
+ <el-switch v-model="fixedHeader" class="drawer-switch" />
+ </div>
+
+ <div class="drawer-item">
+ <span>显示LOGO</span>
+ <el-switch v-model="sidebarLogo" class="drawer-switch" />
+ </div>
+
+ <div class="drawer-item">
+ <span>菜单UniqueOpened</span>
+ <el-switch v-model="uniqueOpened" class="drawer-switch" />
+ </div>
+
+ <div class="drawer-item">
+ <span>切换菜单位置</span>
+ <el-switch v-model="menuInLeft" class="drawer-switch" />
+ </div>
+
+ </div>
+ </div>
+</template>
+
+<script>
+import ThemePicker from '@/components/ThemePicker'
+
+export default {
+ components: { ThemePicker },
+ data() {
+ return {}
+ },
+ computed: {
+ fixedHeader: {
+ get() {
+ return this.$store.state.settings.fixedHeader
+ },
+ set(val) {
+ this.$store.dispatch('settings/changeSetting', {
+ key: 'fixedHeader',
+ value: val
+ })
+ }
+ },
+ tagsView: {
+ get() {
+ return this.$store.state.settings.tagsView
+ },
+ set(val) {
+ this.$store.dispatch('settings/changeSetting', {
+ key: 'tagsView',
+ value: val
+ })
+ }
+ },
+ sidebarLogo: {
+ get() {
+ return this.$store.state.settings.sidebarLogo
+ },
+ set(val) {
+ this.$store.dispatch('settings/changeSetting', {
+ key: 'sidebarLogo',
+ value: val
+ })
+ }
+ },
+ uniqueOpened: {
+ get() {
+ return this.$store.state.settings.uniqueOpened
+ },
+ set(val) {
+ this.$store.dispatch('settings/changeSetting', {
+ key: 'uniqueOpened',
+ value: val
+ })
+ }
+ },
+ // 增加绑定的menuInLeft值
+ menuInLeft: {
+ get() {
+ return this.$store.state.settings.menuInLeft
+ },
+ set(val) {
+ this.$store.dispatch('settings/changeSetting', {
+ key: 'menuInLeft',
+ value: val
+ })
+ }
+ }
+ },
+ methods: {
+ themeChange(val) {
+ this.$store.dispatch('settings/changeSetting', {
+ key: 'theme',
+ value: val
+ })
+ }
+ }
+}
+</script>
+
+<style lang="scss" scoped>
+.drawer-container {
+ padding: 24px;
+ font-size: 14px;
+ line-height: 1.5;
+ word-wrap: break-word;
+
+ .drawer-title {
+ margin-bottom: 12px;
+ color: rgba(0, 0, 0, .85);
+ font-size: 14px;
+ line-height: 22px;
+ }
+
+ .drawer-item {
+ color: rgba(0, 0, 0, .65);
+ font-size: 14px;
+ padding: 12px 0;
+ }
+
+ .drawer-switch {
+ float: right
+ }
+}
+</style>
diff --git a/UI source code/dns_mapping_ui-master/src/layout/components/Sidebar/FixiOSBug.js b/UI source code/dns_mapping_ui-master/src/layout/components/Sidebar/FixiOSBug.js
new file mode 100644
index 0000000..bc14856
--- /dev/null
+++ b/UI source code/dns_mapping_ui-master/src/layout/components/Sidebar/FixiOSBug.js
@@ -0,0 +1,26 @@
+export default {
+ computed: {
+ device() {
+ return this.$store.state.app.device
+ }
+ },
+ mounted() {
+ // In order to fix the click on menu on the ios device will trigger the mouseleave bug
+ // https://github.com/PanJiaChen/vue-element-admin/issues/1135
+ this.fixBugIniOS()
+ },
+ methods: {
+ fixBugIniOS() {
+ const $subMenu = this.$refs.subMenu
+ if ($subMenu) {
+ const handleMouseleave = $subMenu.handleMouseleave
+ $subMenu.handleMouseleave = (e) => {
+ if (this.device === 'mobile') {
+ return
+ }
+ handleMouseleave(e)
+ }
+ }
+ }
+ }
+}
diff --git a/UI source code/dns_mapping_ui-master/src/layout/components/Sidebar/Item.vue b/UI source code/dns_mapping_ui-master/src/layout/components/Sidebar/Item.vue
new file mode 100644
index 0000000..b515f61
--- /dev/null
+++ b/UI source code/dns_mapping_ui-master/src/layout/components/Sidebar/Item.vue
@@ -0,0 +1,29 @@
+<script>
+export default {
+ name: 'MenuItem',
+ functional: true,
+ props: {
+ icon: {
+ type: String,
+ default: ''
+ },
+ title: {
+ type: String,
+ default: ''
+ }
+ },
+ render(h, context) {
+ const { icon, title } = context.props
+ const vnodes = []
+
+ if (icon) {
+ vnodes.push(<svg-icon icon-class={icon}/>)
+ }
+
+ if (title) {
+ vnodes.push(<span slot='title'>{(title)}</span>)
+ }
+ return vnodes
+ }
+}
+</script>
diff --git a/UI source code/dns_mapping_ui-master/src/layout/components/Sidebar/Link.vue b/UI source code/dns_mapping_ui-master/src/layout/components/Sidebar/Link.vue
new file mode 100644
index 0000000..eb4dd10
--- /dev/null
+++ b/UI source code/dns_mapping_ui-master/src/layout/components/Sidebar/Link.vue
@@ -0,0 +1,36 @@
+
+<template>
+ <!-- eslint-disable vue/require-component-is -->
+ <component v-bind="linkProps(to)">
+ <slot />
+ </component>
+</template>
+
+<script>
+import { isExternal } from '@/utils/validate'
+
+export default {
+ props: {
+ to: {
+ type: String,
+ required: true
+ }
+ },
+ methods: {
+ linkProps(url) {
+ if (isExternal(url)) {
+ return {
+ is: 'a',
+ href: url,
+ target: '_blank',
+ rel: 'noopener'
+ }
+ }
+ return {
+ is: 'router-link',
+ to: url
+ }
+ }
+ }
+}
+</script>
diff --git a/UI source code/dns_mapping_ui-master/src/layout/components/Sidebar/Logo.vue b/UI source code/dns_mapping_ui-master/src/layout/components/Sidebar/Logo.vue
new file mode 100644
index 0000000..1233dcd
--- /dev/null
+++ b/UI source code/dns_mapping_ui-master/src/layout/components/Sidebar/Logo.vue
@@ -0,0 +1,82 @@
+<template>
+ <div class="sidebar-logo-container" :class="{'collapse':collapse}">
+ <transition name="sidebarLogoFade">
+ <router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/">
+ <img v-if="logo" :src="logo" class="sidebar-logo">
+ <h1 v-else class="sidebar-title">{{ title }} </h1>
+ </router-link>
+ <router-link v-else key="expand" class="sidebar-logo-link" to="/">
+ <img v-if="logo" :src="logo" class="sidebar-logo">
+ <h1 class="sidebar-title">{{ title }} </h1>
+ </router-link>
+ </transition>
+ </div>
+</template>
+
+<script>
+import Logo from '@/assets/images/logo.png'
+export default {
+ name: 'SidebarLogo',
+ props: {
+ collapse: {
+ type: Boolean,
+ required: true
+ }
+ },
+ data() {
+ return {
+ title: 'DiamondV后台管理',
+ logo: Logo
+ }
+ }
+}
+</script>
+
+<style lang="scss" scoped>
+.sidebarLogoFade-enter-active {
+ transition: opacity 1.5s;
+}
+
+.sidebarLogoFade-enter,
+.sidebarLogoFade-leave-to {
+ opacity: 0;
+}
+
+.sidebar-logo-container {
+ position: relative;
+ width: 100%;
+ height: 50px;
+ line-height: 50px;
+ text-align: center;
+ overflow: hidden;
+
+ & .sidebar-logo-link {
+ height: 100%;
+ width: 100%;
+
+ & .sidebar-logo {
+ width: 32px;
+ height: 32px;
+ vertical-align: middle;
+ margin-right: 6px;
+ }
+
+ & .sidebar-title {
+ display: inline-block;
+ margin: 0;
+ color: #fff;
+ font-weight: 600;
+ line-height: 50px;
+ font-size: 14px;
+ font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif;
+ vertical-align: middle;
+ }
+ }
+
+ &.collapse {
+ .sidebar-logo {
+ margin-right: 0px;
+ }
+ }
+}
+</style>
diff --git a/UI source code/dns_mapping_ui-master/src/layout/components/Sidebar/SidebarItem.vue b/UI source code/dns_mapping_ui-master/src/layout/components/Sidebar/SidebarItem.vue
new file mode 100644
index 0000000..2d49dd8
--- /dev/null
+++ b/UI source code/dns_mapping_ui-master/src/layout/components/Sidebar/SidebarItem.vue
@@ -0,0 +1,95 @@
+<template>
+ <div v-if="!item.hidden" class="menu-wrapper">
+ <template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren)&&!item.alwaysShow">
+ <app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path)">
+ <el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}">
+ <item :icon="onlyOneChild.meta.icon||(item.meta&&item.meta.icon)" :title="onlyOneChild.meta.title" />
+ </el-menu-item>
+ </app-link>
+ </template>
+
+ <el-submenu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body>
+ <template slot="title">
+ <item v-if="item.meta" :icon="item.meta && item.meta.icon" :title="item.meta.title" />
+ </template>
+ <sidebar-item
+ v-for="child in item.children"
+ :key="child.path"
+ :is-nest="true"
+ :item="child"
+ :base-path="resolvePath(child.path)"
+ class="nest-menu"
+ />
+ </el-submenu>
+ </div>
+</template>
+
+<script>
+import path from 'path'
+import { isExternal } from '@/utils/validate'
+import Item from './Item'
+import AppLink from './Link'
+import FixiOSBug from './FixiOSBug'
+
+export default {
+ name: 'SidebarItem',
+ components: { Item, AppLink },
+ mixins: [FixiOSBug],
+ props: {
+ // route object
+ item: {
+ type: Object,
+ required: true
+ },
+ isNest: {
+ type: Boolean,
+ default: false
+ },
+ basePath: {
+ type: String,
+ default: ''
+ }
+ },
+ data() {
+ // To fix https://github.com/PanJiaChen/vue-admin-template/issues/237
+ // TODO: refactor with render function
+ this.onlyOneChild = null
+ return {}
+ },
+ methods: {
+ hasOneShowingChild(children = [], parent) {
+ const showingChildren = children.filter(item => {
+ if (item.hidden) {
+ return false
+ } else {
+ // Temp set(will be used if only has one showing child)
+ this.onlyOneChild = item
+ return true
+ }
+ })
+
+ // When there is only one child router, the child router is displayed by default
+ if (showingChildren.length === 1) {
+ return true
+ }
+
+ // Show parent if there are no child router to display
+ if (showingChildren.length === 0) {
+ this.onlyOneChild = { ... parent, path: '', noShowingChildren: true }
+ return true
+ }
+
+ return false
+ },
+ resolvePath(routePath) {
+ if (isExternal(routePath)) {
+ return routePath
+ }
+ if (isExternal(this.basePath)) {
+ return this.basePath
+ }
+ return path.resolve(this.basePath, routePath)
+ }
+ }
+}
+</script>
diff --git a/UI source code/dns_mapping_ui-master/src/layout/components/Sidebar/index.vue b/UI source code/dns_mapping_ui-master/src/layout/components/Sidebar/index.vue
new file mode 100644
index 0000000..b192bd2
--- /dev/null
+++ b/UI source code/dns_mapping_ui-master/src/layout/components/Sidebar/index.vue
@@ -0,0 +1,56 @@
+<template>
+ <div :class="{ 'has-logo': showLogo }">
+ <logo v-if="showLogo" :collapse="isCollapse" />
+ <el-scrollbar wrap-class="scrollbar-wrapper">
+ <el-menu
+ :default-active="activeMenu"
+ :collapse="isCollapse"
+ :background-color="variables.menuBg"
+ :text-color="variables.menuText"
+ :unique-opened="$store.state.settings.uniqueOpened"
+ :active-text-color="variables.menuActiveText"
+ :collapse-transition="false"
+ mode="vertical"
+ >
+ <sidebar-item
+ v-for="route in sidebarRouters"
+ :key="route.path"
+ :item="route"
+ :base-path="route.path"
+ />
+ </el-menu>
+ </el-scrollbar>
+ </div>
+</template>
+
+<script>
+import { mapGetters } from 'vuex'
+import Logo from './Logo'
+import SidebarItem from './SidebarItem'
+import variables from '@/assets/styles/variables.scss'
+
+export default {
+ components: { SidebarItem, Logo },
+ computed: {
+ ...mapGetters(['sidebarRouters', 'sidebar']),
+ activeMenu() {
+ const route = this.$route
+ const { meta, path } = route
+ // if set path, the sidebar will highlight the path you set
+ if (meta.activeMenu) {
+ return meta.activeMenu
+ }
+ return path
+ },
+ showLogo() {
+ return this.$store.state.settings.sidebarLogo
+ },
+ variables() {
+ return variables
+ },
+ isCollapse() {
+ return !this.sidebar.opened
+ }
+ }
+}
+</script>
diff --git a/UI source code/dns_mapping_ui-master/src/layout/components/TagsView/ScrollPane.vue b/UI source code/dns_mapping_ui-master/src/layout/components/TagsView/ScrollPane.vue
new file mode 100644
index 0000000..018f1aa
--- /dev/null
+++ b/UI source code/dns_mapping_ui-master/src/layout/components/TagsView/ScrollPane.vue
@@ -0,0 +1,86 @@
+<template>
+ <el-scrollbar ref="scrollContainer" :vertical="false" class="scroll-container" @wheel.native.prevent="handleScroll">
+ <slot />
+ </el-scrollbar>
+</template>
+
+<script>
+const tagAndTagSpacing = 4 // tagAndTagSpacing
+
+export default {
+ name: 'ScrollPane',
+ data() {
+ return {
+ left: 0
+ }
+ },
+ computed: {
+ scrollWrapper() {
+ return this.$refs.scrollContainer.$refs.wrap
+ }
+ },
+ methods: {
+ handleScroll(e) {
+ const eventDelta = e.wheelDelta || -e.deltaY * 40
+ const $scrollWrapper = this.scrollWrapper
+ $scrollWrapper.scrollLeft = $scrollWrapper.scrollLeft + eventDelta / 4
+ },
+ moveToTarget(currentTag) {
+ const $container = this.$refs.scrollContainer.$el
+ const $containerWidth = $container.offsetWidth
+ const $scrollWrapper = this.scrollWrapper
+ const tagList = this.$parent.$refs.tag
+
+ let firstTag = null
+ let lastTag = null
+
+ // find first tag and last tag
+ if (tagList.length > 0) {
+ firstTag = tagList[0]
+ lastTag = tagList[tagList.length - 1]
+ }
+
+ if (firstTag === currentTag) {
+ $scrollWrapper.scrollLeft = 0
+ } else if (lastTag === currentTag) {
+ $scrollWrapper.scrollLeft = $scrollWrapper.scrollWidth - $containerWidth
+ } else {
+ // find preTag and nextTag
+ const currentIndex = tagList.findIndex(item => item === currentTag)
+ const prevTag = tagList[currentIndex - 1]
+ const nextTag = tagList[currentIndex + 1]
+
+ // the tag's offsetLeft after of nextTag
+ const afterNextTagOffsetLeft = nextTag.$el.offsetLeft + nextTag.$el.offsetWidth + tagAndTagSpacing
+
+ // the tag's offsetLeft before of prevTag
+ const beforePrevTagOffsetLeft = prevTag.$el.offsetLeft - tagAndTagSpacing
+
+ if (afterNextTagOffsetLeft > $scrollWrapper.scrollLeft + $containerWidth) {
+ $scrollWrapper.scrollLeft = afterNextTagOffsetLeft - $containerWidth
+ } else if (beforePrevTagOffsetLeft < $scrollWrapper.scrollLeft) {
+ $scrollWrapper.scrollLeft = beforePrevTagOffsetLeft
+ }
+ }
+ }
+ }
+}
+</script>
+
+<style lang="scss" scoped>
+.scroll-container {
+ white-space: nowrap;
+ position: relative;
+ overflow: hidden;
+ width: 100%;
+ ::v-deep {
+ .el-scrollbar__bar {
+ bottom: 0px;
+ }
+ .el-scrollbar__wrap {
+ height: 49px;
+ // width: 80% !important;
+ }
+ }
+}
+</style>
diff --git a/UI source code/dns_mapping_ui-master/src/layout/components/TagsView/index.vue b/UI source code/dns_mapping_ui-master/src/layout/components/TagsView/index.vue
new file mode 100644
index 0000000..9dd84f9
--- /dev/null
+++ b/UI source code/dns_mapping_ui-master/src/layout/components/TagsView/index.vue
@@ -0,0 +1,286 @@
+<template>
+ <div id="tags-view-container" class="tags-view-container">
+ <scroll-pane ref="scrollPane" class="tags-view-wrapper">
+ <router-link
+ v-for="tag in visitedViews"
+ ref="tag"
+ :key="tag.path"
+ :class="isActive(tag)?'active':''"
+ :to="{ path: tag.path, query: tag.query, fullPath: tag.fullPath }"
+ tag="span"
+ class="tags-view-item"
+ @click.middle.native="closeSelectedTag(tag)"
+ @contextmenu.prevent.native="openMenu(tag,$event)"
+ >
+ {{ tag.title }}
+ <span v-if="!tag.meta.affix" class="el-icon-close" @click.prevent.stop="closeSelectedTag(tag)" />
+ </router-link>
+ </scroll-pane>
+ <ul v-show="visible" :style="{left:left+'px',top:top+'px'}" class="contextmenu">
+ <li @click="refreshSelectedTag(selectedTag)">刷新</li>
+ <li v-if="!(selectedTag.meta&&selectedTag.meta.affix)" @click="closeSelectedTag(selectedTag)">关闭</li>
+ <li @click="closeOthersTags">关闭其他</li>
+ <li @click="closeAllTags(selectedTag)">关闭全部</li>
+ </ul>
+ </div>
+</template>
+
+<script>
+import ScrollPane from './ScrollPane'
+import path from 'path'
+
+export default {
+ components: { ScrollPane },
+ data() {
+ return {
+ visible: false,
+ top: 0,
+ left: 0,
+ selectedTag: {},
+ affixTags: []
+ }
+ },
+ computed: {
+ visitedViews() {
+ return this.$store.state.tagsView.visitedViews
+ },
+ routes() {
+ return this.$store.state.permission.routers
+ }
+ },
+ watch: {
+ $route() {
+ this.addTags()
+ this.moveToCurrentTag()
+ },
+ visible(value) {
+ if (value) {
+ document.body.addEventListener('click', this.closeMenu)
+ } else {
+ document.body.removeEventListener('click', this.closeMenu)
+ }
+ }
+ },
+ mounted() {
+ this.initTags()
+ this.addTags()
+ },
+ methods: {
+ isActive(route) {
+ return route.path === this.$route.path
+ },
+ filterAffixTags(routes, basePath = '/') {
+ let tags = []
+ routes.forEach(route => {
+ if (route.meta && route.meta.affix) {
+ const tagPath = path.resolve(basePath, route.path)
+ tags.push({
+ fullPath: tagPath,
+ path: tagPath,
+ name: route.name,
+ meta: { ...route.meta }
+ })
+ }
+ if (route.children) {
+ const tempTags = this.filterAffixTags(route.children, route.path)
+ if (tempTags.length >= 1) {
+ tags = [...tags, ...tempTags]
+ }
+ }
+ })
+ return tags
+ },
+ initTags() {
+ const affixTags = this.affixTags = this.filterAffixTags(this.routes)
+ for (const tag of affixTags) {
+ // Must have tag name
+ if (tag.name) {
+ this.$store.dispatch('tagsView/addVisitedView', tag)
+ }
+ }
+ },
+ addTags() {
+ const { name } = this.$route
+ if (name) {
+ this.$store.dispatch('tagsView/addView', this.$route)
+ }
+ return false
+ },
+ moveToCurrentTag() {
+ const tags = this.$refs.tag
+ this.$nextTick(() => {
+ for (const tag of tags) {
+ if (tag.to.path === this.$route.path) {
+ this.$refs.scrollPane.moveToTarget(tag)
+ // when query is different then update
+ if (tag.to.fullPath !== this.$route.fullPath) {
+ this.$store.dispatch('tagsView/updateVisitedView', this.$route)
+ }
+ break
+ }
+ }
+ })
+ },
+ refreshSelectedTag(view) {
+ this.$store.dispatch('tagsView/delCachedView', view).then(() => {
+ const { fullPath } = view
+ this.$nextTick(() => {
+ this.$router.replace({
+ path: '/redirect' + fullPath
+ })
+ })
+ })
+ },
+ closeSelectedTag(view) {
+ this.$store.dispatch('tagsView/delView', view).then(({ visitedViews }) => {
+ if (this.isActive(view)) {
+ this.toLastView(visitedViews, view)
+ }
+ })
+ },
+ closeOthersTags() {
+ this.$router.push(this.selectedTag)
+ this.$store.dispatch('tagsView/delOthersViews', this.selectedTag).then(() => {
+ this.moveToCurrentTag()
+ })
+ },
+ closeAllTags(view) {
+ this.$store.dispatch('tagsView/delAllViews').then(({ visitedViews }) => {
+ if (this.affixTags.some(tag => tag.path === view.path)) {
+ return
+ }
+ this.toLastView(visitedViews, view)
+ })
+ },
+ toLastView(visitedViews, view) {
+ const latestView = visitedViews.slice(-1)[0]
+ if (latestView) {
+ this.$router.push(latestView)
+ } else {
+ // now the default is to redirect to the home page if there is no tags-view,
+ // you can adjust it according to your needs.
+ if (view.name === 'Dashboard') {
+ // to reload home page
+ this.$router.replace({ path: '/redirect' + view.fullPath })
+ } else {
+ this.$router.push('/')
+ }
+ }
+ },
+ openMenu(tag, e) {
+ const menuMinWidth = 105
+ const offsetLeft = this.$el.getBoundingClientRect().left // container margin left
+ const offsetWidth = this.$el.offsetWidth // container width
+ const maxLeft = offsetWidth - menuMinWidth // left boundary
+ const left = e.clientX - offsetLeft + 15 // 15: margin right
+
+ if (left > maxLeft) {
+ this.left = maxLeft
+ } else {
+ this.left = left
+ }
+
+ this.top = e.clientY
+ this.visible = true
+ this.selectedTag = tag
+ },
+ closeMenu() {
+ this.visible = false
+ }
+ }
+}
+</script>
+
+<style lang="scss" scoped>
+.tags-view-container {
+ height: 34px;
+ width: 100%;
+ background: #fff;
+ border-bottom: 1px solid #d8dce5;
+ box-shadow: 0 1px 3px 0 rgba(0, 0, 0, .12), 0 0 3px 0 rgba(0, 0, 0, .04);
+ .tags-view-wrapper {
+ .tags-view-item {
+ display: inline-block;
+ position: relative;
+ cursor: pointer;
+ height: 26px;
+ line-height: 26px;
+ border: 1px solid #d8dce5;
+ color: #495060;
+ background: #fff;
+ padding: 0 8px;
+ font-size: 12px;
+ margin-left: 5px;
+ margin-top: 4px;
+ &:first-of-type {
+ margin-left: 15px;
+ }
+ &:last-of-type {
+ margin-right: 15px;
+ }
+ &.active {
+ background-color: #42b983;
+ color: #fff;
+ border-color: #42b983;
+ &::before {
+ content: '';
+ background: #fff;
+ display: inline-block;
+ width: 8px;
+ height: 8px;
+ border-radius: 50%;
+ position: relative;
+ margin-right: 2px;
+ }
+ }
+ }
+ }
+ .contextmenu {
+ margin: 0;
+ background: #fff;
+ z-index: 3000;
+ position: absolute;
+ list-style-type: none;
+ padding: 5px 0;
+ border-radius: 4px;
+ font-size: 12px;
+ font-weight: 400;
+ color: #333;
+ box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, .3);
+ li {
+ margin: 0;
+ padding: 7px 16px;
+ cursor: pointer;
+ &:hover {
+ background: #eee;
+ }
+ }
+ }
+}
+</style>
+
+<style lang="scss">
+//reset element css of el-icon-close
+.tags-view-wrapper {
+ .tags-view-item {
+ .el-icon-close {
+ width: 16px;
+ height: 16px;
+ vertical-align: 2px;
+ border-radius: 50%;
+ text-align: center;
+ transition: all .3s cubic-bezier(.645, .045, .355, 1);
+ transform-origin: 100% 50%;
+ &:before {
+ transform: scale(.6);
+ display: inline-block;
+ vertical-align: -3px;
+ }
+ &:hover {
+ background-color: #b4bccc;
+ color: #fff;
+ }
+ }
+ }
+}
+</style>
diff --git a/UI source code/dns_mapping_ui-master/src/layout/components/index.js b/UI source code/dns_mapping_ui-master/src/layout/components/index.js
new file mode 100644
index 0000000..61ef939
--- /dev/null
+++ b/UI source code/dns_mapping_ui-master/src/layout/components/index.js
@@ -0,0 +1,6 @@
+export { default as AppMain } from './AppMain'
+export { default as Navbar } from './Navbar'
+export { default as HeadNavbar } from './HeadNavbar/index.vue'
+export { default as Settings } from './Settings'
+export { default as Sidebar } from './Sidebar/index.vue'
+export { default as TagsView } from './TagsView/index.vue'