mirror of
https://github.com/continew-org/continew-admin-ui.git
synced 2026-01-17 16:57:16 +08:00
first commit
This commit is contained in:
56
src/layout/components/HeaderRightBar/Message.vue
Normal file
56
src/layout/components/HeaderRightBar/Message.vue
Normal file
@@ -0,0 +1,56 @@
|
||||
<template>
|
||||
<div class="message">
|
||||
<a-tabs default-active-key="1">
|
||||
<a-tab-pane key="1">
|
||||
<template #title>通知(1)</template>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="2">
|
||||
<template #title>关注(1)</template>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="3">
|
||||
<template #title>待办(2)</template>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
|
||||
<section>
|
||||
<a-comment
|
||||
v-for="(item, index) in list"
|
||||
:key="index"
|
||||
:author="item.name"
|
||||
:content="item.content"
|
||||
:datetime="item.datetime"
|
||||
>
|
||||
<template #actions></template>
|
||||
<template #avatar>
|
||||
<a-avatar><img :src="item.avatar" /></a-avatar>
|
||||
</template>
|
||||
</a-comment>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
defineOptions({ name: 'Message' })
|
||||
const list = [
|
||||
{
|
||||
name: 'Socrates',
|
||||
datetime: '1小时之前',
|
||||
content: 'Comment body content.',
|
||||
avatar: 'https://lolicode.gitee.io/scui-doc/demo/img/avatar2.gif'
|
||||
},
|
||||
{
|
||||
name: '木木糖醇',
|
||||
datetime: '2小时之前',
|
||||
content: '关注了你',
|
||||
avatar: 'https://s1.ax1x.com/2022/06/14/XhteeO.jpg'
|
||||
},
|
||||
{
|
||||
name: '徐欣',
|
||||
datetime: '2个半小时之前',
|
||||
content: '收藏了你的文章',
|
||||
avatar: 'https://s1.ax1x.com/2022/06/14/XhtSwF.jpg'
|
||||
}
|
||||
]
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
158
src/layout/components/HeaderRightBar/SettingDrawer.vue
Normal file
158
src/layout/components/HeaderRightBar/SettingDrawer.vue
Normal file
@@ -0,0 +1,158 @@
|
||||
<template>
|
||||
<a-drawer v-model:visible="visible" title="项目配置" width="300px" unmount-on-close :footer="false">
|
||||
<a-space :size="15" direction="vertical" fill>
|
||||
<a-divider orientation="center">系统布局</a-divider>
|
||||
<a-row justify="center">
|
||||
<a-space>
|
||||
<a-badge>
|
||||
<template #content>
|
||||
<icon-check-circle-fill
|
||||
v-if="appStore.layout === 'left'"
|
||||
style="color: rgb(var(--success-6))"
|
||||
:size="16"
|
||||
></icon-check-circle-fill>
|
||||
</template>
|
||||
<LayoutItem mode="left" @click="appStore.layout = 'left'"></LayoutItem>
|
||||
<p class="layout-text">默认布局</p>
|
||||
</a-badge>
|
||||
<a-badge>
|
||||
<template #content>
|
||||
<icon-check-circle-fill
|
||||
v-if="appStore.layout === 'mix'"
|
||||
:size="16"
|
||||
style="color: rgb(var(--success-6))"
|
||||
></icon-check-circle-fill>
|
||||
</template>
|
||||
<LayoutItem mode="mix" @click="appStore.layout = 'mix'"></LayoutItem>
|
||||
<p class="layout-text">混合布局</p>
|
||||
</a-badge>
|
||||
</a-space>
|
||||
</a-row>
|
||||
|
||||
<a-divider orientation="center">系统主题</a-divider>
|
||||
<a-row justify="center">
|
||||
<ColorPicker
|
||||
theme="dark"
|
||||
:color="appStore.themeColor"
|
||||
:sucker-hide="true"
|
||||
:colors-default="defaultColorList"
|
||||
@changeColor="changeColor"
|
||||
></ColorPicker>
|
||||
</a-row>
|
||||
|
||||
<a-divider orientation="center">界面显示</a-divider>
|
||||
|
||||
<a-descriptions :column="1" :align="{ value: 'right' }" :value-style="{ paddingRight: 0 }">
|
||||
<a-descriptions-item label="页签显示">
|
||||
<a-switch v-model="appStore.tab" />
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="页签风格">
|
||||
<a-select
|
||||
v-model="appStore.tabMode"
|
||||
placeholder="请选择"
|
||||
:options="tabModeList"
|
||||
:disabled="!appStore.tab"
|
||||
:trigger-props="{ autoFitPopupMinWidth: true }"
|
||||
:style="{ width: '120px' }"
|
||||
>
|
||||
</a-select>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="动画显示">
|
||||
<a-switch v-model="appStore.animate" />
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="动画显示">
|
||||
<a-select
|
||||
v-model="appStore.animateMode"
|
||||
placeholder="请选择"
|
||||
:options="animateModeList"
|
||||
:disabled="!appStore.animate"
|
||||
:style="{ width: '120px' }"
|
||||
>
|
||||
</a-select>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="深色菜单">
|
||||
<a-switch v-model="appStore.menuDark" />
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="手风琴效果">
|
||||
<a-switch v-model="appStore.menuAccordion" />
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</a-space>
|
||||
</a-drawer>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useAppStore } from '@/stores'
|
||||
import { ColorPicker } from 'vue-color-kit'
|
||||
import 'vue-color-kit/dist/vue-color-kit.css'
|
||||
import LayoutItem from './components/LayoutItem.vue'
|
||||
|
||||
defineOptions({ name: 'SettingDrawer' })
|
||||
const appStore = useAppStore()
|
||||
const visible = ref(false)
|
||||
|
||||
const tabModeList: App.TabItem[] = [
|
||||
{ label: '卡片', value: 'card' },
|
||||
{ label: '间隔卡片', value: 'card-gutter' },
|
||||
{ label: '圆角', value: 'rounded' }
|
||||
]
|
||||
|
||||
const animateModeList: App.AnimateItem[] = [
|
||||
{ label: '默认', value: 'zoom-fade' },
|
||||
{ label: '滑动', value: 'fade-slide' },
|
||||
{ label: '渐变', value: 'fade' },
|
||||
{ label: '底部滑出', value: 'fade-bottom' },
|
||||
{ label: '缩放消退', value: 'fade-scale' }
|
||||
]
|
||||
|
||||
const open = () => {
|
||||
visible.value = true
|
||||
}
|
||||
|
||||
defineExpose({ open })
|
||||
|
||||
// 默认显示的主题色列表
|
||||
const defaultColorList = [
|
||||
'#165DFF',
|
||||
'#409EFF',
|
||||
'#18A058',
|
||||
'#2d8cf0',
|
||||
'#007AFF',
|
||||
'#5ac8fa',
|
||||
'#5856D6',
|
||||
'#536dfe',
|
||||
'#9c27b0',
|
||||
'#AF52DE',
|
||||
'#0096c7',
|
||||
'#00C1D4',
|
||||
'#43a047',
|
||||
'#e53935',
|
||||
'#f4511e',
|
||||
'#6d4c41'
|
||||
]
|
||||
|
||||
type ColorObj = {
|
||||
hex: string
|
||||
hsv: { h: number; s: number; v: number }
|
||||
rgba: { r: number; g: number; b: number; a: number }
|
||||
}
|
||||
|
||||
// 改变主题色
|
||||
const changeColor = (colorObj: ColorObj) => {
|
||||
if (!/^#[0-9A-Za-z]{6}/.test(colorObj.hex)) return
|
||||
appStore.setThemeColor(colorObj.hex)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep(.arco-descriptions-item-label-block) {
|
||||
color: var(--color-text-1);
|
||||
}
|
||||
|
||||
.layout-text {
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
color: var(--color-text-2);
|
||||
margin-top: 4px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,62 @@
|
||||
<template>
|
||||
<div class="layout-item" :class="`layout-item-${mode}`" @click="emit('click')"></div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
interface Props {
|
||||
mode: 'left' | 'top' | 'mix'
|
||||
}
|
||||
|
||||
withDefaults(defineProps<Props>(), {})
|
||||
|
||||
const emit = defineEmits(['click'])
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.layout-item {
|
||||
width: 60px;
|
||||
height: 50px;
|
||||
background-color: var(--color-fill-3);
|
||||
border-radius: 3px;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
&::before {
|
||||
content: '';
|
||||
width: 12px;
|
||||
height: 100%;
|
||||
background-color: rgb(var(--gray-9));
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: none;
|
||||
}
|
||||
&::after {
|
||||
content: '';
|
||||
width: 100%;
|
||||
height: 10px;
|
||||
background-color: rgb(var(--gray-9));
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: none;
|
||||
}
|
||||
&-left {
|
||||
&::before {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
&-top {
|
||||
&::after {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
&-mix {
|
||||
&::before,
|
||||
&::after {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
125
src/layout/components/HeaderRightBar/index.vue
Normal file
125
src/layout/components/HeaderRightBar/index.vue
Normal file
@@ -0,0 +1,125 @@
|
||||
<template>
|
||||
<a-row justify="end" align="center">
|
||||
<a-space size="medium">
|
||||
<!-- 项目配置 -->
|
||||
<a-tooltip content="项目配置" position="bl">
|
||||
<a-button size="mini" class="gi_hover_btn" @click="SettingDrawerRef?.open">
|
||||
<template #icon>
|
||||
<icon-settings :size="18" />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
|
||||
<!-- 消息通知 -->
|
||||
<a-popover position="bottom" trigger="click">
|
||||
<a-badge :count="9" dot>
|
||||
<a-button size="mini" class="gi_hover_btn">
|
||||
<template #icon>
|
||||
<icon-notification :size="18" />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-badge>
|
||||
<template #content>
|
||||
<Message></Message>
|
||||
</template>
|
||||
</a-popover>
|
||||
|
||||
<!-- 全屏切换组件 -->
|
||||
<a-tooltip v-if="!isMobile()" content="全屏切换" position="bottom">
|
||||
<a-button size="mini" class="gi_hover_btn" @click="toggle">
|
||||
<template #icon>
|
||||
<icon-fullscreen :size="18" v-if="!isFullscreen" />
|
||||
<icon-fullscreen-exit :size="18" v-else />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
|
||||
<!-- 暗黑模式切换 -->
|
||||
<a-tooltip content="主题切换" position="bottom">
|
||||
<GiThemeBtn></GiThemeBtn>
|
||||
</a-tooltip>
|
||||
|
||||
<!-- 管理员账户 -->
|
||||
<a-dropdown trigger="hover">
|
||||
<a-row align="center" :wrap="false" class="user">
|
||||
<!-- 管理员头像 -->
|
||||
<a-avatar :size="32">
|
||||
<img :src="userStore.avatar" alt="avatar" />
|
||||
</a-avatar>
|
||||
<span class="username">{{ userStore.name }}</span>
|
||||
<icon-down />
|
||||
</a-row>
|
||||
<template #content>
|
||||
<a-doption @click="toUser">
|
||||
<span>账号管理</span>
|
||||
</a-doption>
|
||||
<a-divider :margin="0" />
|
||||
<a-doption @click="logout">
|
||||
<span>退出登录</span>
|
||||
</a-doption>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</a-space>
|
||||
</a-row>
|
||||
|
||||
<SettingDrawer ref="SettingDrawerRef"></SettingDrawer>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Modal } from '@arco-design/web-vue'
|
||||
import { useUserStore } from '@/stores'
|
||||
import SettingDrawer from './SettingDrawer.vue'
|
||||
import Message from './Message.vue'
|
||||
import { isMobile } from '@/utils'
|
||||
import { useFullscreen } from '@vueuse/core'
|
||||
|
||||
const { isFullscreen, toggle } = useFullscreen()
|
||||
|
||||
defineOptions({ name: 'HeaderRight' })
|
||||
const router = useRouter()
|
||||
const userStore = useUserStore()
|
||||
const SettingDrawerRef = ref<InstanceType<typeof SettingDrawer>>()
|
||||
|
||||
// 跳转基本信息
|
||||
const toUser = () => {
|
||||
router.push('/setting/profile')
|
||||
}
|
||||
|
||||
// 退出登录
|
||||
const logout = () => {
|
||||
Modal.warning({
|
||||
title: '提示',
|
||||
content: '确认退出登录?',
|
||||
hideCancel: false,
|
||||
closable: true,
|
||||
onBeforeOk: async () => {
|
||||
try {
|
||||
await userStore.logout()
|
||||
router.replace('/login')
|
||||
return true
|
||||
} catch (error) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.arco-dropdown-open .arco-icon-down {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.user {
|
||||
cursor: pointer;
|
||||
color: var(--color-text-1);
|
||||
.username {
|
||||
margin-left: 10px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.arco-icon-down {
|
||||
transition: all 0.3s;
|
||||
margin-left: 2px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user