first commit

This commit is contained in:
JaguarJack
2022-12-05 23:01:12 +08:00
commit 0024080c28
322 changed files with 27698 additions and 0 deletions

View File

@@ -0,0 +1,33 @@
<template>
<div class="flex flex-row h-16 w-full drop-shadow border-l dark:border-l-0 border-gray-200" style="background-color: var(--header-bg-color)">
<div class="flex flex-row justify-between w-full">
<div class="flex flex-row min-w-[17rem]">
<div class="h-full flex items-center w-8 ml-2 hover:cursor-pointer" @click="store.changeExpaned">
<Icon name="list-bullet" class="w-6 h-8" />
</div>
<div class="w-96 flex items-center pl-3 sm:pl-0">
<Breadcrumbs />
</div>
</div>
<div class="flex w-52 sm:min-w-[18rem] flex-row item-center pl-1 sm:pl-0 justify-end sm:justify-between mr-4">
<div class="w-3/5 hidden sm:flex">
<!-- 搜索 -->
<Search />
<!-- 多语言 -->
<Lang />
<!-- 暗黑主题 -->
<Theme />
<Notification />
</div>
<Profile />
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { useAppStore } from '/admin/stores/modules/app'
import Notification from './notification.vue'
const store = useAppStore()
</script>

View File

@@ -0,0 +1,38 @@
<template>
<div class="w-10 h-10 grid place-items-center rounded-full mt-3 hover:cursor-pointer">
<div class="flex hover:cursor-pointer pl-1 pr-1">
<el-dropdown size="large" class="flex items-center justify-center hover:cursor-pointer w-full" @command="selectLanguage">
<Icon name="language" />
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item v-for="lang in langs" :key="lang.value" :command="lang.value" :disabled="lang.value == defaultLang">
{{ $t('system.' + lang.label) }}
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</div>
</template>
<script lang="ts" setup>
import { reactive, computed } from 'vue'
import { useAppStore } from '/admin/stores/modules/app'
const langs = reactive([
{ label: 'chinese', value: 'zh' },
{ label: 'english', value: 'en' },
])
const appStore = useAppStore()
// select default languages
const defaultLang = computed(() => {
return appStore.getLocale
})
// select language
const selectLanguage = (value: 'zh' | 'en') => {
appStore.changeLocale(value)
location.reload()
}
</script>

View File

@@ -0,0 +1,22 @@
<template>
<div class="h-16 flex items-center justify-center logo-bg">
<img :src="logo" class="h-9 w-9" />
<div class="text-md logo-text pl-3" v-if="store.isExpand">CatchAdmin</div>
</div>
</template>
<script lang="ts" setup>
import { useAppStore } from '/admin/stores/modules/app'
import logo from '/admin/assets/logo.png'
const store = useAppStore()
</script>
<style scoped lang="scss">
.logo-bg {
background-color: var(--header-logo-bg-color);
}
.logo-text {
color: var(--header-logo-text-color);
}
</style>

View File

@@ -0,0 +1,49 @@
<template>
<!-- 通知 -->
<div class="w-10 h-10 grid place-items-center rounded-full mt-3 hover:cursor-pointer" ref="messageRef" v-click-outside="onClickOutside">
<el-badge :value="3">
<Icon name="bell" />
</el-badge>
<el-popover ref="popoverRef" :virtual-ref="messageRef" trigger="hover" virtual-triggering :width="300">
<el-tabs model-value="message">
<el-tab-pane label="消息(8)" name="message">
<div>
<div class="flex flex-row w-full border-b border-b-slate-300 dark:border-b-slate-500 mt-2" v-for="(message, key) in messages" :key="key">
<div>
<el-avatar src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png" class="w-2 h-2" />
</div>
<div class="ml-2 h-10 mt-2">
{{ message }}
</div>
</div>
</div>
</el-tab-pane>
<el-tab-pane label="通知(1)" name="notice">
<div>
<div class="flex flex-row w-full border-b border-b-slate-300 dark:border-b-slate-500 mt-2" v-for="(message, key) in messages" :key="key">
<div>
<el-avatar src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png" class="w-2 h-2" />
</div>
<div class="ml-2 h-10 mt-2">
{{ message }}
</div>
</div>
</div>
</el-tab-pane>
</el-tabs>
</el-popover>
</div>
</template>
<script setup lang="ts">
import { ref, unref } from 'vue'
import { ClickOutside as vClickOutside } from 'element-plus'
const messageRef = ref()
const popoverRef = ref()
const onClickOutside = () => {
unref(popoverRef).popperRef?.delayHide?.()
}
const messages = ref()
messages.value = ['你收到 catchadmin 的好友申请', '你收到 catchadmin pro 的 license 授权', '你收到 catchadmin 通知']
</script>

View File

@@ -0,0 +1,34 @@
<template>
<div class="flex w-2/5 hover:cursor-pointer pl-1 pr-1">
<el-dropdown size="large" placement="bottom-end" class="flex items-center justify-center hover:cursor-pointer w-full">
<div class="flex lg:items-center">
<img :src="userStore.getAvatar" class="w-7 h-7 rounded-full" />
<div class="ml-2 hidden lg:block">{{ userStore.getNickname }}</div>
</div>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item>Action 1</el-dropdown-item>
<el-dropdown-item>Action 2</el-dropdown-item>
<el-dropdown-item>Action 3</el-dropdown-item>
<el-dropdown-item divided @click="logout">
<Icon name="logout" class="mr-1" />
退
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</template>
<script lang="ts" setup>
import { useUserStore } from '/admin/stores/modules/user'
import Message from '/admin/support/message'
const userStore = useUserStore()
const logout = () => {
Message.confirm('确定退出系统吗?', () => {
userStore.logout()
})
}
</script>

View File

@@ -0,0 +1,58 @@
<template>
<div class="w-10 h-10 grid place-items-center rounded-full mt-3 hover:cursor-pointer">
<div class="flex flex-row w-96">
<Icon name="magnifying-glass" class="hidden sm:block" @click="serachMenuVisable = true" />
<Teleport to="body">
<el-dialog v-model="serachMenuVisable" width="30%" draggable>
<el-cascader :filterable="true" :options="options" @change="toWhere" placeholder="请输入菜单名称" clearable class="w-full" :show-all-levels="false" />
</el-dialog>
</Teleport>
</div>
</div>
</template>
<script lang="ts" setup>
import { usePermissionsStore } from '/admin/stores/modules/user/permissions'
import { Menu } from '/admin/types/Menu'
import router from '/admin/router'
import { ref, computed } from 'vue'
const serachMenuVisable = ref(false)
const permissionStore = usePermissionsStore()
const options = computed(() => {
return filterMenus(permissionStore.getMenus)
})
const toWhere = (value: string[]) => {
if (value.length) {
router.push({ path: value[value.length - 1] })
}
serachMenuVisable.value = false
}
/**
* filter menus
*
* @param menus
*/
function filterMenus(menus: Menu[] | undefined): Object[] {
const cascaderMenus: Object[] = []
menus?.forEach(menu => {
if (menu.meta === undefined) {
const child = menu.children?.pop()
cascaderMenus.push(Object.assign({ label: child?.meta?.title, value: child?.path }))
} else {
const cascaderMenu = Object.assign({ label: menu.meta?.title, value: menu.path, children: [] })
cascaderMenu.children = filterMenus(menu.children)
cascaderMenus.push(cascaderMenu)
}
})
return cascaderMenus
}
</script>

View File

@@ -0,0 +1,22 @@
<template>
<div class="w-10 h-10 grid place-items-center rounded-full mt-3 hover:cursor-pointer">
<Icon name="moon" @click="changeTheme()" v-if="isDark" />
<Icon name="sun" @click="changeTheme()" v-else />
</div>
</template>
<script setup lang="ts">
import { useDark, useToggle } from '@vueuse/core'
import { useAppStore } from '/admin/stores/modules/app'
import { unref } from 'vue'
const appStore = useAppStore()
const isDark = useDark()
const toggleDark = useToggle(isDark)
function changeTheme() {
appStore.setDarkMode(!unref(isDark))
toggleDark()
}
</script>