2 07.封装通用弹框表单组件
封装组件
src/components/FormDrawer.vue
<template>
<el-drawer
v-model="showDrawer"
:title=title
:size=size
:close-on-click-modal="true"
:destroy-on-close="destroyOnClose"
>
<div class="formDrawer">
<div class="body">
<slot></slot>
</div>
<div class="actions">
<el-button type="primary" @click="submit" :loading="loading">{{ confirmText }}</el-button>
<el-button type="default" @click="close">取消</el-button>
</div>
</div>
</el-drawer>
</template>
<script setup>
import { ref } from 'vue'
const showDrawer = ref(false)
// 打开
const open = ()=> showDrawer.value = true
// 关闭
const close = ()=> showDrawer.value = false
// 提交加载
const loading = ref(false)
const showLoading = ()=>loading.value = true
const hideLoading = ()=>loading.value = false
// 向父组件暴露方法
defineExpose({
open,
close,
showLoading,
hideLoading
})
// 传参
const props = defineProps({
title: String,
size:{
type:String,
default: '45%'
},
destroyOnClose: {
type:Boolean,
default: false
},
confirmText: {
type:String,
default: '提交'
}
})
// 提交
const emit = defineEmits(['submit'])
const submit = ()=> emit("submit")
</script>
<style>
.formDrawer{
width: 100%;
height: 100%;
position: relative;
@apply flex flex-col;
}
.formDrawer .body{
flex: 1;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 50px;
overflow-y: auto;
}
.formDrawer .actions{
height: 50px;
@apply mt-auto flex items-center;
}
</style>
src/layouts/components/FHeader.vue
<template>
<div class="f-header">
<span class="logo">
<el-icon class="mr-1"><eleme-filled></eleme-filled></el-icon>
Vue+Vite编程
</span>
<el-icon class="icon-btn"><fold /></el-icon>
<el-tooltip effect="dark" content="刷新" placement="bottom">
<el-icon class="icon-btn" @click="handleRefresh"><refresh /></el-icon>
</el-tooltip>
<div class="ml-auto flex items-center">
<el-tooltip effect="dark" content="全屏" placement="bottom">
<el-icon class="icon-btn" @click="toggle">
<full-screen v-if="!isFullscreen"/>
<aim v-else/>
</el-icon>
</el-tooltip>
<el-dropdown class="dropdown" @command="handleCommand">
<span class="flex items-center text-light-50">
<el-avatar class="mr-2" :size="25" :src="$store.state.user.avatar"></el-avatar>
{{ $store.state.user.username }}
<el-icon class="el-icon--right"> <arrow-down /></el-icon>
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="rePassword">修改密码</el-dropdown-item>
<el-dropdown-item command="logout">退出登录</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</div>
<!-- 修改密码 Start -->
<form-drawer ref="formDrawerRef" title="修改密码" destroyOnClose @submit="onSubmit">
<el-form ref="formRef" :rules="rules" :model="form" label-width="80px" size="small">
<el-form-item prop="oldpassword" label="旧密码">
<el-input v-model="form.oldpassword" placeholder="请输入旧密码">
<template #prefix>
<el-icon><User /></el-icon>
</template>
</el-input>
</el-form-item>
<el-form-item prop="password" label="新密码">
<el-input type="password" v-model="form.password" placeholder="请输入新密码" show-password>
<template #prefix>
<el-icon><Lock /></el-icon>
</template>
</el-input>
</el-form-item>
<el-form-item prop="repassword" label="确认密码">
<el-input type="password" v-model="form.repassword" placeholder="请输入确认密码" show-password>
<template #prefix>
<el-icon><Lock /></el-icon>
</template>
</el-input>
</el-form-item>
</el-form>
</form-drawer>
<!-- 修改密码 End -->
</template>
<script setup>
import { ref,reactive } from 'vue'
import FormDrawer from '~/components/FormDrawer.vue'
import { logout,updatepassword } from "~/api/manager"
import { showModal,toast } from "~/composables/util"
import { useRouter } from "vue-router"
import { useStore } from "vuex"
import { useFullscreen } from '@vueuse/core'
const {
// 是否全屏状态
isFullscreen,
toggle
} = useFullscreen()
const store = useStore()
const router = useRouter()
// do not use same name with ref
const form = reactive({
oldpassword: '',
password: '',
repassword: '',
})
// 定义验证规则
const rules = {
oldpassword: [
{
required: true,
message: '旧密码不能为空',
trigger: 'blur',
},
],
password: [
{
required: true,
message: '新密码不能为空',
trigger: 'blur',
},
],
repassword: [
{
required: true,
message: '确认密码不能为空',
trigger: 'blur',
},
]
}
// 点击登录验证
const formDrawerRef = ref(null)
const formRef = ref(null)
const onSubmit = () => {
formRef.value.validate((valid) => {
if (!valid) {
console.log('error')
}
// 加载动画
formDrawerRef.value.showLoading()
updatepassword(form).then(res=>{
toast('修改密码成功,请重新登录')
store.dispatch('logout')
router.push('/login')
}).finally(()=>{
formDrawerRef.value.hideLoading()
})
})
}
// 修改密码
const handleCommand = (c) =>{
switch (c) {
case "logout":
handleLogout()
break;
case "rePassword":
// showDrawer.value = true
formDrawerRef.value.open()
break;
}
}
// 刷新
const handleRefresh = () => location.reload()
function handleLogout(){
showModal("是否要退出登录?").then(res=>{
logout()
.finally(()=>{
// 退出
store.dispatch('logout')
// 跳转回登录页
router.push('/login')
// 提示退出登录成功
toast('退出登录成功')
})
})
}
</script>
<style>
.f-header{
@apply flex items-center bg-indigo-500 text-light-50 fixed top-0 left-0 right-0;
height: 64px;
}
.logo{
width: 250px;
@apply flex justify-center items-center text-xl font-thin;
}
.icon-btn{
@apply flex justify-center items-center;
width: 42px;
height: 64px;
cursor: pointer;
}
.icon-btn:hover{
@apply bg-indigo-600;
}
.f-header .dropdown{
height: 64x;
cursor: pointer;
@apply flex justify-center items-center mx-5;
}
</style>
Last updated