初始化admin pc端

This commit is contained in:
Mrtangl
2022-04-08 10:42:44 +08:00
parent d9c9f27530
commit 19665b64fb
137 changed files with 11991 additions and 0 deletions

View File

@@ -0,0 +1,89 @@
<template>
<div class="layout-aside">
<router-link to="/workbench" class="logo flex col-center">
<img class="logo-img" :src="config.web_logo" alt />
<div class="line-1">{{ config.web_name }}</div>
</router-link>
<div class="scrollbar-wrap">
<el-scrollbar style="height: 100%" class="ls-scrollbar">
<el-menu
active-text-color="#fff"
background-color="#2a2c41"
:default-active="currentPath"
text-color="#E5E5E5"
router
>
<template v-for="(item, index) in sidebar" :key="index">
<sub-menu :route="item">
<template v-for="(item, index) in item?.children" :key="index">
<sub-menu :route="item">
<template v-for="(item, index) in item?.children" :key="index">
<sub-menu :route="item"></sub-menu>
</template>
</sub-menu>
</template>
</sub-menu>
</template>
</el-menu>
</el-scrollbar>
</div>
</div>
</template>
<script lang="ts">
import { computed, defineComponent } from 'vue'
import { useAdmin } from '@/core/hooks/app'
import SubMenu from './sub-menu.vue'
export default defineComponent({
components: {
SubMenu
},
setup() {
const { store, route } = useAdmin()
const sidebar = computed(() => store.state.permission.sidebar)
const currentPath = computed(() => route.meta?.parent ?? route.path)
const config = computed(() => store.getters.config)
return {
config,
sidebar,
currentPath
}
}
})
</script>
<style lang="scss" scoped>
.layout-aside {
height: 100%;
width: 100%;
overflow: hidden;
display: flex;
flex-direction: column;
background-color: #2a2c41;
.logo {
height: $layout-header-height;
font-weight: 500;
font-size: 18px;
color: #fff;
padding: 0 20px;
.logo-img {
width: 30px;
height: 30px;
margin-right: 10px;
}
}
.scrollbar-wrap {
flex: 1;
min-height: 0;
.el-menu {
box-sizing: border-box;
padding: 10px 0 20px;
:deep(.el-menu-item) {
&.is-active {
background-color: $color-primary;
}
}
}
}
}
</style>

View File

@@ -0,0 +1,38 @@
<template>
<template v-if="!route.meta.hidden">
<el-sub-menu v-if="hasChildren" :index="route.path">
<template #title>
<i class="iconfont m-r-10" :class="route.meta.icon"></i>
<span>{{ route.meta.title }}</span>
</template>
<slot></slot>
</el-sub-menu>
<el-menu-item v-else :index="route.path">
<i class="iconfont m-r-10" :class="route.meta.icon"></i>
<span>{{ route.meta.title }}</span>
</el-menu-item>
</template>
</template>
<script lang="ts">
import { computed, defineComponent } from 'vue'
import { RouteRecordRaw } from 'vue-router'
export default defineComponent({
components: {},
props: {
route: {
type: Object,
default: () => ({})
}
},
setup(props) {
const hasChildren = computed(() => {
const children: RouteRecordRaw[] = props.route.children ?? []
return !!children.filter(item => !item.meta?.hidden).length
})
return {
hasChildren
}
}
})
</script>

View File

@@ -0,0 +1,67 @@
<template>
<div class="layout-header">
<!-- <input class="search-input" placeholder="请输入搜索内容…" type="text" /> -->
<div class="admin-info flex flex-center m-l-40">
<el-avatar :size="40" :src="userInfo.avatar"></el-avatar>
<div class="m-l-10">
<el-dropdown trigger="hover" @command="handleCommand">
<div class="flex flex-center">
{{ userInfo.name }}
<el-icon class="el-icon--right"><arrow-down /></el-icon>
</div>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="logout">退出登录</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</div>
</div>
</template>
<script lang="ts">
import { computed, defineComponent } from 'vue'
import { useAdmin } from '@/core/hooks/app'
export default defineComponent({
setup() {
const { store, router } = useAdmin()
const userInfo = computed(() => store.getters.userInfo)
const handleCommand = (command: string) => {
switch (command) {
case 'logout':
store.dispatch('user/logout').then(() => {
router.push('/login')
store.commit('permission/setPermission', {
auth: null,
root: 0
})
})
}
}
return {
userInfo,
handleCommand
}
}
})
</script>
<style lang="scss" scoped>
.layout-header {
display: flex;
align-items: center;
justify-content: flex-end;
flex: none;
height: $layout-header-height;
background: #fff;
padding: 0 24px;
.search-input {
width: 460px;
height: 40px;
border-radius: 20px;
background: #f6f6f6;
padding: 0 20px;
}
}
</style>

View File

@@ -0,0 +1,26 @@
<template>
<div class="layout-main">
<el-scrollbar>
<div class="p-15">
<perm />
</div>
</el-scrollbar>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import Perm from './perm.vue'
export default defineComponent({
components: {
Perm
}
})
</script>
<style lang="scss" scoped>
.layout-main {
flex: 1;
min-height: 0;
}
</style>

View File

@@ -0,0 +1,57 @@
<template>
<div v-if="permission" class="perm">
<template v-if="hasPermission">
<router-view></router-view>
</template>
<template v-else>
<div class="no-perm flex flex-col flex-center">
<img src="@/assets/images/no_perm.png" />
<div class="muted">暂无查看权限</div>
</div>
</template>
</div>
</template>
<script lang="ts">
import { computed, defineComponent } from 'vue'
import { useAdmin } from '@/core/hooks/app'
export default defineComponent({
components: {},
props: {},
setup(props) {
const { store, route } = useAdmin()
const permission = computed(() => store.getters.permission)
const isAdmin = computed(() => store.getters.isAdmin)
const hasPermission = computed(() => {
const { path, meta } = route
if (isAdmin.value) {
return true
}
const actions = permission.value[path]
console.log(permission.value, path)
if (!actions || !meta?.permission) {
return true
}
return actions.some((item: string) => {
return (meta?.permission as string[]).includes(item)
})
})
return {
permission,
hasPermission
}
}
})
</script>
<style scoped lang="scss">
.perm {
.no-perm {
height: calc(100vh - #{$layout-header-height} - 32px);
img {
width: 152px;
height: 152px;
}
}
}
</style>

View File

@@ -0,0 +1,44 @@
<template>
<div class="layout">
<div class="aside">
<layout-aside />
</div>
<div class="main">
<layout-header />
<layout-main />
</div>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import LayoutAside from './components/layout-aside/index.vue'
import LayoutMain from './components/layout-main.vue'
import LayoutHeader from './components/layout-header.vue'
export default defineComponent({
components: {
LayoutAside,
LayoutMain,
LayoutHeader
}
})
</script>
<style lang="scss">
.layout {
display: flex;
height: 100vh;
width: 100vw;
min-width: $layout-min-width;
.aside {
flex: none;
width: $layout-aside-width;
}
.main {
display: flex;
flex-direction: column;
flex: 1;
min-width: 0;
}
}
</style>