fix:修复暗黑模式失效,优化样式结构,组件进行分离

This commit is contained in:
zouzhibing 2022-11-11 23:58:05 +08:00
parent f7dac95732
commit 940d9af6fb
12 changed files with 300 additions and 319 deletions

BIN
src/assets/image/avatar.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -1,16 +1,26 @@
<template>
<el-switch @change="(val) => changeSwitch(val)" v-model="isDark"/>
<el-switch
@change="switchDark"
inline-prompt
v-model="themeConfig.isDark"
:active-icon="Sunny"
:inactive-icon="Moon"
/>
</template>
<script setup lang="ts" name="switchDark">
import { Sunny, Moon } from "@element-plus/icons-vue";
import {computed, ref} from "vue";
import { useDark, useToggle } from '@vueuse/core'
import {useSettingStore} from "@/store/modules/setting"
const SettingStore = useSettingStore()
// //
const isDark = ref(SettingStore.themeConfig.isDark)
const changeSwitch = ()=>{
let isDark = useDark()
useToggle(isDark)
}
//
const themeConfig = computed(()=>SettingStore.themeConfig)
//
const switchDark = () => {
const body = document.documentElement as HTMLElement;
if (themeConfig.value.isDark) body.setAttribute("class", "dark");
else body.setAttribute("class", "");
};
</script>

View File

@ -0,0 +1,80 @@
<template>
<el-dropdown @command="commandAction">
<span class="el-dropdown-link">
<el-avatar :size="30" class="avatar" :src="AvatarLogo"/>
{{userInfo.username}}
<el-icon class="el-icon--right">
<arrow-down />
</el-icon>
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item :command="2" >
<el-icon><Edit /></el-icon></el-dropdown-item>
<el-dropdown-item :command="1" divided>
<el-icon><SwitchButton /></el-icon>退</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<PersonalDialog ref="person"/>
</template>
<script lang="ts" setup>
import { useRouter } from 'vue-router'
import {ElMessage, ElMessageBox} from "element-plus";
import {computed, ref} from "vue";
import AvatarLogo from '@/assets/image/avatar.png'
import {useUserStore} from "@/store/modules/user"
import {useTagsViewStore} from "@/store/modules/tagsView"
import PersonalDialog from './PersonalDialog.vue'
const router = useRouter()
const UserStore = useUserStore()
const TagsViewStore = useTagsViewStore()
//
const userInfo = computed(() => UserStore.userInfo)
const person = ref()
const logOut = async () => {
ElMessageBox.confirm('您是否确认退出登录?', '温馨提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(async () => {
await router.push({path: '/login'})
await UserStore.logout()
TagsViewStore.clearVisitedView()
ElMessage({
type: "success",
message: "退出登录成功!"
});
})
.catch(() => {})
}
const commandAction = (key: number) => {
switch (key) {
case 1:
logOut()
break
case 2:
person.value.show()
break
}
}
</script>
<style lang="scss" scoped>
.avatar{
margin-right: 6px
}
.el-dropdown-link {
cursor: pointer;
//color: var(--el-color-primary);
display: flex;
align-items: center;
}
</style>

View File

@ -1,5 +1,5 @@
<template>
<el-dialog v-model="dialogVisible" title="修改密码" width="60%">
<el-dialog v-model="dialogVisible" title="修改密码" width="40%">
<el-form
ref="ruleFormRef"
:model="ruleForm"

View File

@ -0,0 +1,70 @@
.mobile {
.m-layout-header {
left: 0 !important;
width: 100%!important;
}
}
.header {
height: 50px;
width: 100%;
border-bottom: 1px solid #eee;
display: flex;
align-items: center;
padding: 0 10px 0 0;
box-sizing: border-box;
justify-content: space-between;
.left {
display: flex;
align-items: center;
height: 100%;
}
.tool-bar-right {
display: flex;
align-items: center;
.right-item-menu{
margin-right: 22px;
}
}
}
.zb-fixed-header{
position: fixed;
top: 0;
right: 0;
z-index: 9;
}
.zb-no-fixed-header{
width: 100%!important;;
}
.m-layout-header {
width: 100%;
background: white;
transition: width 0.28s;
flex-shrink: 0;
box-sizing: border-box;
box-shadow: 0 1px 4px rgb(0 21 41 / 8%);
}
.fixed-header-collapse{
width: calc(100% - 60px);
}
.fixed-header-no-collapse{
width: calc(100% - 210px);
}
.el-dropdown {
display: flex;
height: 100%;
align-items: center;
}
.transverseMenu{
display: flex;
.el-menu{
overflow: hidden;
}
.tool-bar-right{
display: flex;
justify-content: flex-end;
min-width:300px ;
flex-shrink: 0;
}
}

View File

@ -6,56 +6,29 @@
mode === 'horizontal'?'':isCollapse?'fixed-header-collapse':'fixed-header-no-collapse'
]"
>
<div
class="header"
:class="{
transverseMenu: mode === 'horizontal',
}"
>
<div class="header" :class="{ transverseMenu: mode === 'horizontal', }">
<UMenu v-if="mode === 'horizontal'" />
<div class="left" v-if="mode === 'vertical'">
<CollapseIcon/>
<Hamburger />
</div>
<div class="right">
<div class="tool-bar-right">
<GlobalComSize class="right-item-menu"/>
<HeaderSearch class="right-item-menu"/>
<Remind class="right-item-menu"/>
<ScreenFull class="right-item-menu"/>
<Setting class="right-item-menu"/>
<el-dropdown @command="commandAction">
<span class="el-dropdown-link">
<el-avatar :icon="UserFilled" :size="30" style="margin-right: 6px" />{{
userInfo.username
}}
<el-icon class="el-icon--right">
<arrow-down />
</el-icon>
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item :command="2" >
<el-icon><Edit /></el-icon></el-dropdown-item>
<el-dropdown-item :command="1" divided>
<el-icon><SwitchButton /></el-icon>退</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<Avatar/>
</div>
</div>
<tag-views v-if="showTag" />
<personal ref="person" />
</div>
</template>
<script lang="ts" setup>
import { UserFilled } from '@element-plus/icons-vue'
import Personal from './components/Personal.vue'
import TagViews from '../TagsView/index.vue'
import GlobalComSize from './components/globalComSize.vue'
import Hamburger from '@/components/Hamburger/index.vue'
@ -64,141 +37,27 @@
import Remind from './components/Remind'
import HeaderSearch from './components/HeaderSearch'
import CollapseIcon from './components/CollapseIcon'
import Avatar from './components/Avatar'
import UMenu from '../Sidebar/components/Menu.vue'
import { computed, ref } from 'vue'
import { useRouter } from 'vue-router'
import { ElMessageBox, ElMessage } from 'element-plus'
import {useSettingStore} from "@/store/modules/setting"
import {useUserStore} from "@/store/modules/user"
import {usePermissionStore} from "@/store/modules/permission"
import {useTagsViewStore} from "@/store/modules/tagsView"
const person = ref()
const router = useRouter()
const SettingStore = useSettingStore()
const UserStore = useUserStore()
const PermissionStore = usePermissionStore()
const TagsViewStore = useTagsViewStore()
const isCollapse = computed(() =>!SettingStore.isCollapse)
// menu
const mode = computed(() => SettingStore.themeConfig.mode)
// tag
const showTag = computed(() =>SettingStore.themeConfig.showTag)
//
const userInfo = computed(() => UserStore.userInfo)
const logOut = async () => {
ElMessageBox.confirm('确定退出登录吗?', '退出登录', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(async () => {
try {
router.push({ path: '/login' })
await UserStore.logout()
PermissionStore.clearRoutes()
TagsViewStore.clearVisitedView()
ElMessage({
type: "success",
message: "退出登录成功!"
});
} catch (e) {}
})
.catch(() => {})
}
const commandAction = (key: number) => {
switch (key) {
case 1:
logOut()
break
case 2:
person.value.show()
break
}
}
const handleCollapse = () => {
SettingStore.setCollapse(isCollapse.value)
}
</script>
<style lang="scss" scoped>
.mobile {
.m-layout-header {
left: 0 !important;
width: 100%!important;
}
}
.header {
height: 50px;
width: 100%;
border-bottom: 1px solid #eee;
display: flex;
align-items: center;
padding: 0 10px 0 0;
box-sizing: border-box;
justify-content: space-between;
.left {
display: flex;
align-items: center;
height: 100%;
}
.right {
display: flex;
align-items: center;
.right-item-menu{
margin-right: 22px;
}
}
}
.zb-fixed-header{
position: fixed;
top: 0;
right: 0;
z-index: 9;
}
.zb-no-fixed-header{
width: 100%!important;;
}
.m-layout-header {
width: 100%;
background: white;
transition: width 0.28s;
flex-shrink: 0;
box-sizing: border-box;
box-shadow: 0 1px 4px rgb(0 21 41 / 8%);
}
.fixed-header-collapse{
width: calc(100% - 60px);
}
.fixed-header-no-collapse{
width: calc(100% - 210px);
}
.el-dropdown {
display: flex;
height: 100%;
align-items: center;
}
.el-dropdown-link {
cursor: pointer;
color: var(--el-color-primary);
display: flex;
align-items: center;
}
.transverseMenu{
display: flex;
.el-menu{
overflow: hidden;
}
.right{
display: flex;
justify-content: flex-end;
min-width:300px ;
flex-shrink: 0;
}
}
@import "./index";
</style>

View File

@ -21,9 +21,9 @@
import {useSettingStore} from "@/store/modules/setting"
import {usePermissionStore} from "@/store/modules/permission"
const SettingStore = useSettingStore()
const PermissionStor = usePermissionStore()
const PermissionStore = usePermissionStore()
const cacheRoutes = computed(() =>PermissionStor.getCacheRoutes())
const cacheRoutes = computed(() =>PermissionStore.getCacheRoutes())
const isReload = computed(() => SettingStore.isReload)
</script>

View File

@ -6,7 +6,7 @@
<div class="contact-nickname">{{ item.created_at }} 林峰</div>
<div class="receive-message-wrap">
<div class="avatar-show">
<img src="@/assets/image/avator.png" />
<img src="@/assets/image/avatar.png" />
</div>
<div style="position: relative; display: flex">
<div class="receive-message-info" v-html="item.content"></div>
@ -30,7 +30,7 @@
</div>
</div>
<div class="avatar-show">
<img src="@/assets/image/avator.png" />
<img src="@/assets/image/avatar.png" />
</div>
</div>
</div>
@ -53,7 +53,7 @@
<script lang="ts" setup>
import { onMounted, ref, nextTick } from 'vue'
import UToolbar from '../u-toolbar/index.vue'
import defalutAvator from '@/assets/image/avator.png'
import defalutAvator from '@/assets/image/avatar.png'
import { chatData } from './chat.js'
import { ElMessage } from 'element-plus'
import dayjs from 'dayjs'

View File

@ -0,0 +1,27 @@
export const iconData = [
'management',
'baseball',
'Basketball',
'BellFilled',
'Bell',
'AddLocation',
'Aim',
'AlarmClock',
'Apple',
'ArrowDownBold',
'Burger',
'Brush',
'BrushFilled',
'RemoveFilled',
'QuestionFilled',
'Promotion',
'Printer',
'School',
'Setting',
'WarningFilled',
'ZoomOut',
'WalletFilled',
'User',
'ToiletPaper', 'Sunrise', 'Sunny', 'SwitchButton', 'TakeawayBox', 'Ticket',
'StarFilled', 'Stamp', 'Stopwatch', 'SortDown', 'SemiSelect', 'Search'
]

View File

@ -0,0 +1,50 @@
.m-card-drag{
height: 100%;
width: 100%;
display: flex;
flex-direction: column;
.header{
flex-shrink: 0;
}
}
.footer{
flex: 1;
padding: 10px;
box-sizing: border-box;
overflow: hidden;
}
.card {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
height: 100%;
box-sizing: border-box;
padding: 20px;
overflow-x: hidden;
background-color: var(--el-fill-color-blank);
border: 1px solid var(--el-border-color-light);
border-radius: 4px;
box-shadow: 0 0 12px rgb(0 0 0 / 5%);
}
.item-group-item {
position: relative;
width: calc(100% / 5.3);
margin-bottom: 10px;
flex-direction: column;
display: flex;
align-items: center;
justify-content: center;
min-height: 100px;
cursor: move;
font-weight: 500;
border: 1px solid rgba(0, 0, 0, 0.125);
}
.chosenClass {
opacity: 0.6;
border: 1px solid rgba(64,158,255,0.2);
}
.item-icon{
width: 100%;
display: flex;
justify-content: center
}

View File

@ -1,182 +1,67 @@
<template>
<u-container-layout class="row">
<div style="margin-bottom: 10px">卡片拖拽排序</div>
<div style="display: flex;align-items: center">
<el-button class="btn" @click="sorter" type="primary" style="margin-bottom: 20px"
>还原</el-button
>
<el-button
class="btn"
@click="getDataAction"
type="primary"
style="margin-bottom: 20px; margin-left: 20px"
>获取数据</el-button
>
</div>
<div class="col-6" style="">
<el-row :gutter="10">
<draggable
:list="message"
:animation="300"
@end="drag = false"
@start="drag = true"
item-key="order"
v-bind="dragOptions"
class="list-group"
ghost-class="ghost"
<div class="m-card-drag">
<el-card class="header">
<el-button @click="sorter" type="primary" >还原</el-button>
<el-button @click="getDataAction" type="primary" style="margin-left: 20px">获取数据</el-button>
</el-card>
<div class="footer">
<draggable
class="card grid-container"
v-model="dragList"
item-key="id"
animation="300"
chosenClass="chosenClass"
@change="onMoveCallback"
:move="getdata"
>
<template #item="{ element }">
<el-col :xs="6" :sm="6" :md="6" :lg="4" :xl="4">
<el-card shadow="hover" class="list-group-item">
<el-icon
:size="30"
:color="element.color"
style="width: 100%; display: flex; justify-content: center"
>
<component :is="element.icon"></component>
</el-icon>
<div style="margin-top: 10px">按住拖拽排序</div>
</el-card>
</el-col>
</template>
</draggable>
</el-row>
forceFallback="true"
>
<template #item="{ element }">
<div class="item-group-item" >
<el-icon
:size="30"
:color="element.color"
class="item-icon"
>
<component :is="element.icon"></component>
</el-icon>
<div style="margin-top: 10px">按住拖拽排序</div>
</div>
</template>
</draggable>
</div>
</u-container-layout>
</div>
</template>
<script lang="ts" setup>
// https://sortablejs.github.io/vue.draggable.next/#/transition-example-2
// https://github.com/SortableJS/vue.draggable.next/blob/master/package.json
import draggable from 'vuedraggable'
import { computed, ref, reactive } from 'vue'
import {ElMessage, ElMessageBox} from "element-plus";
import { ref} from 'vue'
import { getColor } from '@/utils/index'
import {iconData} from './data'
const message = ref([])
const tags = ref([])
const icon = [
'management',
'baseball',
'Basketball',
'BellFilled',
'Bell',
'AddLocation',
'Aim',
'AlarmClock',
'Apple',
'ArrowDownBold',
'Burger',
'Brush',
'BrushFilled',
'RemoveFilled',
'QuestionFilled',
'Promotion',
'Printer',
'School',
'Setting',
'WarningFilled',
'ZoomOut',
'WalletFilled',
'User',
// 'ToiletPaper', 'Sunrise', 'Sunny', 'SwitchButton', 'TakeawayBox', 'Ticket',
// 'StarFilled', 'Stamp', 'Stopwatch', 'SortDown', 'SemiSelect', 'Search'
]
const dragList = ref([])
const drag = ref(false)
//
for (let i = 0; i < 30; i++) {
message.value.push({
name: i,
order: i + 1,
icon: icon[i],
for (let i = 0; i < 20; i++) {
dragList.value.push({
id: i + 1,
icon: iconData[i],
color: getColor(),
})
}
const drag = ref(false)
//
const dragOptions = computed(() => {
return {
animation: 200,
group: 'description',
disabled: false,
ghostClass: 'ghost', //
}
})
const sorter = () => {
message.value = message.value.sort((a, b) => a.name - b.name)
dragList.value = dragList.value.sort((a, b) => a.id - b.id)
ElMessage.success(`还原成功`)
}
const onMoveCallback = (val) => {
console.log('拖动前的索引 :' + val.moved.newIndex)
console.log('拖动后的索引 :' + val.moved.oldIndex)
}
//
const getdata = () => {
console.log(11111111)
}
//
const getDataAction = () => {
console.log(message.value)
ElMessage.success(`获取数据:${JSON.stringify(dragList.value)}`)
}
</script>
<style lang="scss" scoped>
.list-group-item {
position: relative;
/*width: 100px;*/
min-width: 160px;
margin-right: 10px;
margin-bottom: 10px;
display: flex;
align-items: center;
justify-content: center;
min-height: 100px;
/*padding: 0.75rem 1.25rem;*/
background-color: #fff;
font-weight: 500;
/*font-size: 24px;*/
border: 1px solid rgba(0, 0, 0, 0.125);
}
.button {
margin-top: 35px;
}
.flip-list-move {
transition: transform 0.5s;
}
.no-move {
transition: transform 0s;
}
.ghost {
opacity: 0.5;
background: #c8ebfb;
}
.list-group {
display: flex;
flex-wrap: wrap;
}
/*.list-group {*/
/* display: flex;*/
/* display: -webkit-box;*/
/* display: flex;*/
/* -ms-flex-direction: column;*/
/* -webkit-box-orient: vertical;*/
/* -webkit-box-direction: normal;*/
/* //flex-direction: column;*/
/* padding-left: 0;*/
/* flex-wrap: wrap;*/
/* margin-bottom: 0;*/
/* border-radius: 0.25rem;*/
/*}*/
.list-group-item {
cursor: move;
}
.list-group-item i {
cursor: pointer;
}
@import "./index";
</style>