mirror of
https://github.com/1Panel-dev/MaxKB.git
synced 2025-12-25 17:22:55 +00:00
feat: 页面结构
This commit is contained in:
parent
439400d023
commit
46e291ec5c
|
|
@ -5,65 +5,5 @@
|
|||
</template>
|
||||
|
||||
<style scoped>
|
||||
header {
|
||||
line-height: 1.5;
|
||||
max-height: 100vh;
|
||||
}
|
||||
|
||||
.logo {
|
||||
display: block;
|
||||
margin: 0 auto 2rem;
|
||||
}
|
||||
|
||||
nav {
|
||||
width: 100%;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
nav a.router-link-exact-active {
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
nav a.router-link-exact-active:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
nav a {
|
||||
display: inline-block;
|
||||
padding: 0 1rem;
|
||||
border-left: 1px solid var(--color-border);
|
||||
}
|
||||
|
||||
nav a:first-of-type {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
header {
|
||||
display: flex;
|
||||
place-items: center;
|
||||
padding-right: calc(var(--section-gap) / 2);
|
||||
}
|
||||
|
||||
.logo {
|
||||
margin: 0 2rem 0 0;
|
||||
}
|
||||
|
||||
header .wrapper {
|
||||
display: flex;
|
||||
place-items: flex-start;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
nav {
|
||||
text-align: left;
|
||||
margin-left: -1rem;
|
||||
font-size: 1rem;
|
||||
|
||||
padding: 1rem 0;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
? iconMap[iconName].iconReader()
|
||||
: iconMap['404'].iconReader()
|
||||
"
|
||||
class="app-icon"
|
||||
class="el-icon app-icon"
|
||||
>
|
||||
</component>
|
||||
<el-icon v-else-if="iconName">
|
||||
|
|
|
|||
|
|
@ -94,5 +94,25 @@ export const iconMap: any = {
|
|||
)
|
||||
])
|
||||
}
|
||||
},
|
||||
'app-team': {
|
||||
iconReader: () => {
|
||||
return h('i', [
|
||||
h(
|
||||
'svg',
|
||||
{
|
||||
viewBox: '0 0 1024 1024',
|
||||
version: '1.1',
|
||||
xmlns: 'http://www.w3.org/2000/svg'
|
||||
},
|
||||
[
|
||||
h('path', {
|
||||
d: 'M 824.2 699.9 c -25.4 -25.4 -54.7 -45.7 -86.4 -60.4 C 783.1 602.8 812 546.8 812 484 c 0 -110.8 -92.4 -201.7 -203.2 -200 c -109.1 1.7 -197 90.6 -197 200 c 0 62.8 29 118.8 74.2 155.5 c -31.7 14.7 -60.9 34.9 -86.4 60.4 C 345 754.6 314 826.8 312 903.8 c -0.1 4.5 3.5 8.2 8 8.2 h 56 c 4.3 0 7.9 -3.4 8 -7.7 c 1.9 -58 25.4 -112.3 66.7 -153.5 C 493.8 707.7 551.1 684 612 684 c 60.9 0 118.2 23.7 161.3 66.8 C 814.5 792 838 846.3 840 904.3 c 0.1 4.3 3.7 7.7 8 7.7 h 56 c 4.5 0 8.1 -3.7 8 -8.2 c -2 -77 -33 -149.2 -87.8 -203.9 Z M 612 612 c -34.2 0 -66.4 -13.3 -90.5 -37.5 c -24.5 -24.5 -37.9 -57.1 -37.5 -91.8 c 0.3 -32.8 13.4 -64.5 36.3 -88 c 24 -24.6 56.1 -38.3 90.4 -38.7 c 33.9 -0.3 66.8 12.9 91 36.6 c 24.8 24.3 38.4 56.8 38.4 91.4 c 0 34.2 -13.3 66.3 -37.5 90.5 c -24.2 24.2 -56.4 37.5 -90.6 37.5 Z M 361.5 510.4 c -0.9 -8.7 -1.4 -17.5 -1.4 -26.4 c 0 -15.9 1.5 -31.4 4.3 -46.5 c 0.7 -3.6 -1.2 -7.3 -4.5 -8.8 c -13.6 -6.1 -26.1 -14.5 -36.9 -25.1 c -25.8 -25.2 -39.7 -59.3 -38.7 -95.4 c 0.9 -32.1 13.8 -62.6 36.3 -85.6 c 24.7 -25.3 57.9 -39.1 93.2 -38.7 c 31.9 0.3 62.7 12.6 86 34.4 c 7.9 7.4 14.7 15.6 20.4 24.4 c 2 3.1 5.9 4.4 9.3 3.2 c 17.6 -6.1 36.2 -10.4 55.3 -12.4 c 5.6 -0.6 8.8 -6.6 6.3 -11.6 c -32.5 -64.3 -98.9 -108.7 -175.7 -109.9 c -110.9 -1.7 -203.3 89.2 -203.3 199.9 c 0 62.8 28.9 118.8 74.2 155.5 c -31.8 14.7 -61.1 35 -86.5 60.4 c -54.8 54.7 -85.8 126.9 -87.8 204 c -0.1 4.5 3.5 8.2 8 8.2 h 56.1 c 4.3 0 7.9 -3.4 8 -7.7 c 1.9 -58 25.4 -112.3 66.7 -153.5 c 29.4 -29.4 65.4 -49.8 104.7 -59.7 c 3.9 -1 6.5 -4.7 6 -8.7 Z',
|
||||
fill: 'currentColor'
|
||||
})
|
||||
]
|
||||
)
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { type App } from 'vue'
|
||||
import AppIcon from './icons/AppIcon.vue'
|
||||
import LoginLayout from './layout/login-layout/index.vue'
|
||||
import LoginContainer from './layout/login-container/index.vue'
|
||||
import LoginLayout from './login-layout/index.vue'
|
||||
import LoginContainer from './login-container/index.vue'
|
||||
|
||||
export default {
|
||||
install(app: App) {
|
||||
|
|
|
|||
|
|
@ -1,39 +0,0 @@
|
|||
<script setup lang="ts">
|
||||
import { ref, onBeforeUpdate } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import TopBar from '@/components/layout/top-bar/index.vue'
|
||||
|
||||
const route = useRoute()
|
||||
const cachedViews: any = ref([])
|
||||
|
||||
onBeforeUpdate(() => {
|
||||
let isCached = route.meta?.cache
|
||||
let name = route.name
|
||||
if (isCached && name && !cachedViews.value.includes(name)) {
|
||||
cachedViews.value.push(name)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="app-layout">
|
||||
<div class="app-header">
|
||||
<TopBar></TopBar>
|
||||
</div>
|
||||
<div class="app-main">
|
||||
<router-view v-slot="{ Component }">
|
||||
<transition appear name="fade-transform" mode="out-in">
|
||||
<keep-alive :include="cachedViews">
|
||||
<component :is="Component" />
|
||||
</keep-alive>
|
||||
</transition>
|
||||
</router-view>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
.app-main {
|
||||
height: calc(100vh - var(--app-header-height));
|
||||
padding: 0 !important;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
<template>
|
||||
<el-scrollbar>
|
||||
<div class="content-container">
|
||||
<div class="content-container__header" v-if="slots.header || header">
|
||||
<slot name="header">
|
||||
<back-button :path="backPath" :name="backName" :to="backTo" v-if="showBack"></back-button>
|
||||
<span>{{ header }}</span>
|
||||
</slot>
|
||||
</div>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, useSlots } from 'vue';
|
||||
import BackButton from '@/components/back-button/index.vue';
|
||||
defineOptions({ name: 'LayoutContent' });
|
||||
const slots = useSlots();
|
||||
const prop = defineProps({
|
||||
header: String,
|
||||
backPath: String,
|
||||
backName: String,
|
||||
backTo: [Object, String],
|
||||
});
|
||||
|
||||
const showBack = computed(() => {
|
||||
const { backPath, backName, backTo } = prop;
|
||||
return backPath || backName || backTo;
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@use '@/styles/common/mixins.scss' as *;
|
||||
@use '@/styles/common/variables.scss' as *;
|
||||
|
||||
.content-container {
|
||||
transition: 0.3s;
|
||||
color: var(--el-text-color-primary);
|
||||
padding: $view-padding;
|
||||
|
||||
.content-container__header {
|
||||
font-weight: 500;
|
||||
padding-bottom: $view-padding;
|
||||
font-size: 20px;
|
||||
box-sizing: border-box;
|
||||
span {
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
<template>
|
||||
<div class="content-container__main">
|
||||
<div class="content-container__toolbar" v-if="slots.toolbar">
|
||||
<slot name="toolbar"></slot>
|
||||
</div>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useSlots } from 'vue';
|
||||
defineOptions({ name: 'LayoutContentMain' });
|
||||
const slots = useSlots();
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@use '@/styles/common/mixins.scss' as *;
|
||||
@use '@/styles/common/variables.scss' as *;
|
||||
|
||||
.content-container__main {
|
||||
background-color: #ffffff;
|
||||
padding: $view-padding;
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
min-height: calc(100vh - 210px);
|
||||
|
||||
.content-container__toolbar {
|
||||
@include flex-row(space-between, center);
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
<script setup lang="ts">
|
||||
import { TopBar, AppMain } from '../components'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="app-layout">
|
||||
<div class="app-header">
|
||||
<TopBar />
|
||||
</div>
|
||||
<div class="app-main">
|
||||
<AppMain />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
.app-layout {
|
||||
background-color: var(--app-layout-bg-color);
|
||||
}
|
||||
|
||||
.app-main {
|
||||
height: calc(100vh - var(--app-header-height));
|
||||
padding: 0 !important;
|
||||
}
|
||||
.app-header {
|
||||
background-color: var(--app-header-bg-color);
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
<template>
|
||||
<router-view v-slot="{ Component }">
|
||||
<transition appear name="fade-transform" mode="out-in">
|
||||
<keep-alive :include="cachedViews">
|
||||
<component :is="Component" />
|
||||
</keep-alive>
|
||||
</transition>
|
||||
</router-view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onBeforeUpdate } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
const route = useRoute()
|
||||
const cachedViews: any = ref([])
|
||||
|
||||
onBeforeUpdate(() => {
|
||||
let isCached = route.meta?.cache
|
||||
let name = route.name
|
||||
if (isCached && name && !cachedViews.value.includes(name)) {
|
||||
cachedViews.value.push(name)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
export { default as Sidebar } from './sidebar/index.vue'
|
||||
export { default as AppMain } from './app-main/index.vue'
|
||||
export { default as TopBar } from './top-bar/index.vue'
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<template>
|
||||
<div v-if="!menu.meta || !menu.meta.hidden">
|
||||
<el-menu-item ref="subMenu" :index="menu.path" popper-class="sidebar-popper">
|
||||
<template #title>
|
||||
<AppIcon v-if="menu.meta && menu.meta.icon" :iconName="menu.meta.icon" />
|
||||
<span v-if="menu.meta && menu.meta.title">{{ menu.meta.title }}</span>
|
||||
</template>
|
||||
</el-menu-item>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { RouteRecordRaw } from 'vue-router'
|
||||
|
||||
defineProps<{
|
||||
menu: RouteRecordRaw
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
<template>
|
||||
<div class="sidebar">
|
||||
<el-scrollbar wrap-class="scrollbar-wrapper">
|
||||
<el-menu :default-active="activeMenu">
|
||||
<sidebar-item
|
||||
:menu="menu"
|
||||
v-hasPermission="menu.meta?.permission"
|
||||
v-for="(menu, index) in subMenuList"
|
||||
:key="index"
|
||||
>
|
||||
</sidebar-item>
|
||||
</el-menu>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { getChildRouteListByPathAndName } from '@/router/index'
|
||||
import SidebarItem from './SidebarItem.vue'
|
||||
|
||||
const route = useRoute()
|
||||
const subMenuList = computed(() => {
|
||||
return getChildRouteListByPathAndName(route.path, route.name)
|
||||
})
|
||||
|
||||
const activeMenu = computed(() => {
|
||||
const { meta, path } = route
|
||||
if (meta.activeMenu) {
|
||||
return meta.activeMenu
|
||||
}
|
||||
return path
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.sidebar {
|
||||
.el-menu {
|
||||
height: 100%;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
import { computed, ref } from 'vue'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
import { useRouter } from 'vue-router'
|
||||
import ResetPassword from '@/components/layout/top-bar/components/avatar/ResetPasssword.vue'
|
||||
import ResetPassword from './ResetPasssword.vue'
|
||||
const userStore = useUserStore()
|
||||
const router = useRouter()
|
||||
const firstUserName = computed(() => {
|
||||
|
|
@ -14,13 +14,13 @@
|
|||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import TopMenu from '@/components/layout/top-bar/components/top-menu/index.vue'
|
||||
import Avatar from '@/components/layout/top-bar/components/avatar/index.vue'
|
||||
import TopMenu from './top-menu/index.vue'
|
||||
import Avatar from './avatar/index.vue'
|
||||
const defaultTitle = import.meta.env.VITE_APP_TITLE
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.top-bar-container {
|
||||
border-bottom: 1px solid rgba(229, 229, 229, 1);
|
||||
border-bottom: 1px solid var(--el-border-color);
|
||||
height: var(--app-header-height);
|
||||
box-sizing: border-box;
|
||||
padding: var(--app-header-padding);
|
||||
|
|
@ -12,7 +12,8 @@
|
|||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { getChildRouteListByPathAndName } from '@/router/index'
|
||||
import MenuItem from '@/components/layout/top-bar/components/top-menu/MenuItem.vue'
|
||||
import MenuItem from './MenuItem.vue'
|
||||
|
||||
const topMenuList = computed(() => {
|
||||
return getChildRouteListByPathAndName('/', 'home')
|
||||
})
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<template>
|
||||
<div class="main-layout h-full flex">
|
||||
<div class="sidebar-container"><Sidebar /></div>
|
||||
<div class="view-container">
|
||||
<AppMain />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Sidebar, AppMain } from '../components'
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.sidebar-container {
|
||||
transition: width 0.28s;
|
||||
width: var(--sidebar-width);
|
||||
background-color: var(--sidebar-bg-color);
|
||||
border-right: 1px solid var(--el-border-color);
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,8 +1,32 @@
|
|||
import Layout from '@/layout/main-layout/index.vue'
|
||||
const datasetRouter = {
|
||||
path: '/dataset',
|
||||
name: 'dataset',
|
||||
meta: { icon: 'app-dataset', title: '数据集', permission: 'DATASET:READ' },
|
||||
component: () => import('@/views/dataset/index.vue')
|
||||
redirect: '/dataset',
|
||||
children: [
|
||||
{
|
||||
path: '/dataset',
|
||||
name: 'dataset',
|
||||
component: () => import('@/views/dataset/index.vue')
|
||||
},
|
||||
{
|
||||
path: '/dataset/doc',
|
||||
name: 'DatasetDoc',
|
||||
meta: { icon: 'House', title: '文档', activeMenu: '/dataset' },
|
||||
component: Layout,
|
||||
hidden: true,
|
||||
redirect: '/dataset/doc',
|
||||
children: [
|
||||
{
|
||||
path: '/dataset/doc',
|
||||
name: 'DatasetDoc',
|
||||
meta: { icon: 'House', title: '文档' },
|
||||
component: () => import('@/views/dataset/DatasetDoc.vue')
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
export default datasetRouter
|
||||
|
|
|
|||
|
|
@ -1,8 +1,18 @@
|
|||
import Layout from '@/layout/main-layout/index.vue'
|
||||
const settingRouter = {
|
||||
path: '/setting',
|
||||
name: 'setting',
|
||||
meta: { icon: 'Setting', title: '系统设置', permission: 'SETTING:READ' },
|
||||
component: () => import('@/views/setting/index.vue')
|
||||
redirect: '/setting',
|
||||
component: Layout,
|
||||
children: [
|
||||
{
|
||||
path: '/setting',
|
||||
name: 'setting',
|
||||
meta: { icon: 'app-team', title: '团队管理' },
|
||||
component: () => import('@/views/setting/index.vue')
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
export default settingRouter
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ export const routes: Array<RouteRecordRaw> = [
|
|||
{
|
||||
path: '/',
|
||||
name: 'home',
|
||||
component: () => import('@/components/layout/app-layout/index.vue'),
|
||||
component: () => import('@/layout/app-layout/index.vue'),
|
||||
children: [
|
||||
{
|
||||
path: '/first',
|
||||
|
|
@ -19,6 +19,7 @@ export const routes: Array<RouteRecordRaw> = [
|
|||
...rolesRoutes
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
path: '/login',
|
||||
name: 'login',
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
padding: 0;
|
||||
margin: 0 24px;
|
||||
height: 56px;
|
||||
border-bottom: 1px solid #d5d6d8;
|
||||
border-bottom: 1px solid var(--el-border-color);
|
||||
.el-drawer__title {
|
||||
color: #1f2329;
|
||||
font-weight: 500;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
:root {
|
||||
--el-color-primary: rgba(51, 112, 255, 1);
|
||||
--app-layout-bg-color: #f3f5f6;
|
||||
--app-base-text-color: rgba(31, 35, 41, 1);
|
||||
--app-base-text-font-size: 14px;
|
||||
--app-base-text-hover-color: rgba(51, 112, 255, 1);
|
||||
|
|
@ -8,7 +9,8 @@
|
|||
/** header 组件 */
|
||||
--app-header-height: 56px;
|
||||
--app-header-padding: 0 20px;
|
||||
--app-header-bg-color: #252b3c;
|
||||
/** top-bar 组件 */
|
||||
|
||||
--app-header-bg-color: #ffffff;
|
||||
/** sidebar 组件 */
|
||||
--sidebar-bg-color: #ffffff;
|
||||
--sidebar-width: 200px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
<template>
|
||||
<div>dataset 文档</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
|
||||
</script>
|
||||
<style lang="scss" scoped></style>
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
<template >
|
||||
<template>
|
||||
<div>
|
||||
dataset
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,235 @@
|
|||
<template >
|
||||
<div>
|
||||
setting
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
<template>
|
||||
<div>团队管理</div>
|
||||
|
||||
<!-- <div class="sales-department__tree">
|
||||
<support-tree
|
||||
ref="salesDepartmentTree"
|
||||
v-model:data="dataSource"
|
||||
:title="`飞致云 ${regionName}`"
|
||||
buttonName="新建部门"
|
||||
:beforeAppend="appendDepartment"
|
||||
:beforeRemove="removedDepartment"
|
||||
:beforeEdit="editDepartment"
|
||||
:filterable="true"
|
||||
:highlight-current="true"
|
||||
node-key="id"
|
||||
:props="defaultProps"
|
||||
@node-click="treeClick"
|
||||
/>
|
||||
</div>
|
||||
<div class="sales-department__table">
|
||||
<complex-table v-if="currentDepartment" :data="memberTable" border>
|
||||
<template #toolbar>
|
||||
<div class="table-header">
|
||||
<h3>{{ currentDepartment?.name }}</h3>
|
||||
<div>
|
||||
<el-button type="primary" @click="addMember">设置人员</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<el-table-column label="账户ID" prop="username" show-overflow-tooltip />
|
||||
<el-table-column label="姓名">
|
||||
<template #default="{ row }">
|
||||
<icon
|
||||
icon="iconfont icon-vip"
|
||||
v-if="currentDepartment?.leaderId === row.userId"
|
||||
style="color: #f8bc2e"
|
||||
></icon>
|
||||
{{ row.name }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="手机号" prop="phone" />
|
||||
<el-table-column label="邮箱" prop="email" show-overflow-tooltip />
|
||||
<el-table-column label="角色">
|
||||
<template #default="{ row }">
|
||||
{{ currentDepartment?.leaderId === row.userId ? '销售主管' : '销售' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="80" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button
|
||||
type="primary"
|
||||
size="small"
|
||||
v-if="currentDepartment?.leaderId !== row.userId"
|
||||
@click="setLeader(row)"
|
||||
>升级</el-button
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</complex-table>
|
||||
<el-empty :image-size="200" v-else />
|
||||
</div> -->
|
||||
<!-- 设置部门
|
||||
<department-dialog ref="departmentDialogRef" :title="dialogTitle" @refresh="refresh" />
|
||||
<member-dialog ref="memberDialogRef" @refresh="refresh" /> -->
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref, watch, nextTick } from 'vue'
|
||||
// import DepartmentDialog from './components/DepartmentDialog.vue'
|
||||
// import MemberDialog from './components/MemberDialog.vue'
|
||||
// import { getSalesTeams, deleteSalesTeams, putSetLeader } from '@/api/sales-team-controller'
|
||||
// import { searchiInTree } from '@/utils/utils'
|
||||
// import { $error, $confirm, $success } from '@/utils/message'
|
||||
|
||||
// import useStore from '@/store'
|
||||
// const { user } = useStore()
|
||||
|
||||
// const defaultProps = {
|
||||
// children: 'subTeams'
|
||||
// }
|
||||
|
||||
// const salesDepartmentTree = ref()
|
||||
// const memberDialogRef = ref()
|
||||
// const departmentDialogRef = ref()
|
||||
// const loading = ref(false)
|
||||
|
||||
// const regionName = ref('')
|
||||
// const dialogTitle = ref('')
|
||||
// const dataSource = ref([])
|
||||
// const salesOptions = ref([])
|
||||
// const currentDepartment = ref(null)
|
||||
// const memberTable = ref([])
|
||||
|
||||
// watch([salesOptions, currentDepartment], (val) => {
|
||||
// if (val[0]?.length && val[1]) {
|
||||
// const leader = val[0].filter((item) => item.userId === val[1]?.leaderId)
|
||||
// const member = val[1]?.teamMember
|
||||
// ? val[0].filter((item) => val[1]?.teamMember.includes(item.userId))
|
||||
// : []
|
||||
// memberTable.value = [...leader, ...member]
|
||||
// }
|
||||
// })
|
||||
|
||||
// function addMember() {
|
||||
// memberDialogRef.value.open(currentDepartment.value)
|
||||
// }
|
||||
|
||||
// const appendDepartment = (data) => {
|
||||
// dialogTitle.value = '新建部门'
|
||||
// departmentDialogRef.value.open('create', data)
|
||||
// return false
|
||||
// }
|
||||
|
||||
// const removedDepartment = (node, data) => {
|
||||
// $confirm('确定要删除这个部门吗?', {
|
||||
// confirmButtonText: '确定',
|
||||
// cancelButtonText: '取消',
|
||||
// type: 'warning'
|
||||
// })
|
||||
// .then(() => {
|
||||
// loading.value = true
|
||||
// deleteSalesTeams(data.id)
|
||||
// .then(() => {
|
||||
// $success('删除成功')
|
||||
// getTeams()
|
||||
// })
|
||||
// .catch(() => {
|
||||
// loading.value = false
|
||||
// })
|
||||
// })
|
||||
// .catch(() => {})
|
||||
|
||||
// return false
|
||||
// }
|
||||
|
||||
// const editDepartment = (node) => {
|
||||
// dialogTitle.value = '编辑部门'
|
||||
// const parent = node.isLeaf ? node.parent.data : null
|
||||
// departmentDialogRef.value.open('edit', node.data, parent)
|
||||
// return false
|
||||
// }
|
||||
|
||||
// function setLeader(row) {
|
||||
// loading.value = true
|
||||
// putSetLeader(currentDepartment.value.id, row.userId)
|
||||
// .then((data) => {
|
||||
// getTeams()
|
||||
// })
|
||||
// .catch(() => {
|
||||
// loading.value = false
|
||||
// })
|
||||
// }
|
||||
|
||||
// function treeClick(node) {
|
||||
// currentDepartment.value = node
|
||||
// }
|
||||
|
||||
// function getTeams() {
|
||||
// loading.value = true
|
||||
// getSalesTeams({ includeUsers: true })
|
||||
// .then((data) => {
|
||||
// dataSource.value = data
|
||||
// currentDepartment.value = currentDepartment.value
|
||||
// ? searchiInTree(dataSource.value, currentDepartment.value, 'subTeams')
|
||||
// : dataSource.value?.length && dataSource.value[0]
|
||||
// nextTick(() => {
|
||||
// salesDepartmentTree.value.setCurrentKey(currentDepartment.value?.id)
|
||||
// })
|
||||
|
||||
// loading.value = false
|
||||
// })
|
||||
// .catch(() => {
|
||||
// loading.value = false
|
||||
// })
|
||||
// }
|
||||
|
||||
// function getSalesList() {
|
||||
// loading.value = true
|
||||
// user
|
||||
// .asyncGetInternalUsers({ group: ['sales', 'sales_leader', 'region_sales_admin'] })
|
||||
// .then((res) => {
|
||||
// salesOptions.value = res
|
||||
// loading.value = false
|
||||
// })
|
||||
// .catch(() => {
|
||||
// loading.value = false
|
||||
// })
|
||||
// }
|
||||
|
||||
// function getInfo() {
|
||||
// loading.value = true
|
||||
// user
|
||||
// .asyncGetUserInfo()
|
||||
// .then((data) => {
|
||||
// regionName.value = data?.region?.name ? `- ${data?.region?.name}` : ''
|
||||
// loading.value = false
|
||||
// })
|
||||
// .catch(() => {
|
||||
// loading.value = false
|
||||
// })
|
||||
// }
|
||||
|
||||
// function refresh() {
|
||||
// getTeams()
|
||||
// }
|
||||
|
||||
onMounted(() => {
|
||||
// getSalesList()
|
||||
// getInfo()
|
||||
// getTeams()
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$department-left-width: 300px;
|
||||
|
||||
.sales-department {
|
||||
&__tree {
|
||||
width: $department-left-width;
|
||||
min-width: $department-left-width;
|
||||
padding-right: 20px;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
&__table {
|
||||
border-left: 1px solid var(--el-border-color);
|
||||
width: calc(100% - $department-left-width - 40px);
|
||||
padding-left: 20px;
|
||||
.table-header {
|
||||
h3 {
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
Loading…
Reference in New Issue