更新
This commit is contained in:
parent
116b3f2bdf
commit
e83bade96b
@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import {defineProps, reactive, toRefs} from 'vue'
|
||||
import {reactive, toRefs} from 'vue'
|
||||
import * as ElIcons from '@element-plus/icons-vue'
|
||||
|
||||
const prop = defineProps({
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import {defineProps, reactive, toRefs, watch} from 'vue'
|
||||
import {reactive, toRefs, watch} from 'vue'
|
||||
import common from '@/utils/common'
|
||||
|
||||
const prop = defineProps({
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div id="amisid" ref="boxRef"></div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import {defineProps,watch,ref} from "vue"
|
||||
import {watch,ref} from "vue"
|
||||
import {ElMessage} from 'element-plus'
|
||||
import 'amis/sdk/sdk.js'
|
||||
import 'amis/lib/themes/default.css'
|
||||
|
||||
@ -4,12 +4,13 @@
|
||||
import en from 'element-plus/dist/locale/en.mjs'
|
||||
import { getMenus } from "@/api/auth"
|
||||
import TbMenu from "./component/TbMenu.vue"
|
||||
import TbHeader from "./component/TbHeader.vue"
|
||||
import TbNavTabs from "./component/TbNavTabs.vue"
|
||||
import TbSetting from "./component/TbSetting.vue"
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
const logo = new URL('../../assets/image/logo.png', import.meta.url).href
|
||||
const state = reactive({
|
||||
headerHeight: '50px',
|
||||
headerHeight: '33px',
|
||||
asideWidth: '220px',
|
||||
defaultHeight: null,
|
||||
isCollapse: false,
|
||||
@ -75,14 +76,15 @@
|
||||
</el-aside>
|
||||
<el-container>
|
||||
<el-header :height="state.headerHeight">
|
||||
<TbHeader :height="state.headerHeight" :isCollapse="state.isCollapse" @onLanguage="onLanguage"/>
|
||||
<TbNavTabs />
|
||||
</el-header>
|
||||
<el-main>
|
||||
<el-card :shadow="proxy.$global.cardShadow">
|
||||
<el-scrollbar :height="state.defaultHeight-126">
|
||||
<el-scrollbar :height="state.defaultHeight-100">
|
||||
<router-view />
|
||||
</el-scrollbar>
|
||||
</el-card>
|
||||
<TbSetting :isCollapse="state.isCollapse" @onLanguage="onLanguage"/>
|
||||
</el-main>
|
||||
</el-container>
|
||||
</el-container>
|
||||
@ -101,10 +103,11 @@
|
||||
transition: all .5s;
|
||||
}
|
||||
.el-header{
|
||||
margin-top: 0.4rem;
|
||||
padding: 0 0.6rem 0 0;
|
||||
}
|
||||
.el-main{
|
||||
padding: 1.2rem 0.6rem 0 0;
|
||||
padding: 0rem 0.6rem 0 0;
|
||||
overflow-x: hidden;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
@ -1,197 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import {defineProps,reactive,ref,getCurrentInstance} from 'vue'
|
||||
import { isDark, toggleDark } from '@/composables'
|
||||
import type { FormInstance, Action } from 'element-plus'
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
import TbNavTabs from "./TbNavTabs.vue"
|
||||
import { logout } from "@/api/auth"
|
||||
import { modifyPass } from "@/api/system/user"
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
const emit = defineEmits(['onLanguage'])
|
||||
const props = defineProps({
|
||||
height: Number
|
||||
})
|
||||
|
||||
const state = reactive({
|
||||
userVisible: false,
|
||||
user: {
|
||||
avatar: proxy.$global.user.info ? proxy.$global.user.info.avatar : '',
|
||||
username: proxy.$global.user.info ? proxy.$global.user.info.username : '',
|
||||
nickname: proxy.$global.user.info ? proxy.$global.user.info.nickname : '未登录',
|
||||
password: '',
|
||||
rePassword: '',
|
||||
oldPassword: ''
|
||||
}
|
||||
})
|
||||
|
||||
function onPersonal(){
|
||||
state.userVisible = true
|
||||
}
|
||||
|
||||
const userRef = ref<FormInstance>();
|
||||
const validatePass = (rule:any, value:any, callback:any) => {
|
||||
if (value === '') {
|
||||
callback(new Error('请输入确认密码'));
|
||||
} else if (value !== state.user.password) {
|
||||
callback(new Error('两次输入密码不一致!'));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
const onUserSubmit = async (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return;
|
||||
await formEl.validate((valid)=>{
|
||||
if(valid){
|
||||
modifyPass({
|
||||
username: state.user.username,
|
||||
password: state.user.password,
|
||||
oldPassword: state.user.oldPassword
|
||||
}).then(res=>{
|
||||
if(res){
|
||||
state.userVisible = false
|
||||
ElMessageBox.alert('修改密码成功,请重新登录!', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
type: 'warning',
|
||||
callback: (action: Action) =>{
|
||||
logout()
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function onLogout(){
|
||||
ElMessageBox.confirm('确定要退出登录吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}).then(()=>{
|
||||
logout()
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<div class="tb-header">
|
||||
<TbNavTabs />
|
||||
<div>
|
||||
<el-card :shadow="proxy.$global.cardShadow" :body-style="{padding: '0 1rem', 'line-height': height +'px'}">
|
||||
<el-popover placement="bottom" trigger="hover">
|
||||
<template #reference>
|
||||
<el-button link>
|
||||
<template #icon>
|
||||
<el-icon :size="20"><Setting /></el-icon>
|
||||
</template>
|
||||
</el-button>
|
||||
</template>
|
||||
<div>
|
||||
<el-button @click="$emit('onLanguage', 'zh-cn')" link>中文</el-button><br/>
|
||||
<el-button @click="$emit('onLanguage', 'en')" link>English</el-button>
|
||||
</div>
|
||||
</el-popover>
|
||||
<el-button link>
|
||||
<template #icon>
|
||||
<el-icon :size="20"><Monitor /></el-icon>
|
||||
</template>
|
||||
</el-button>
|
||||
<el-button link>
|
||||
<template #icon>
|
||||
<el-icon :size="20"><FullScreen /></el-icon>
|
||||
</template>
|
||||
</el-button>
|
||||
<el-button @click="toggleDark()" link>
|
||||
<template #icon>
|
||||
<el-icon :size="24"><Sunny v-show="!isDark"/></el-icon>
|
||||
<el-icon :size="24"><Sunrise v-show="isDark"/></el-icon>
|
||||
</template>
|
||||
</el-button>
|
||||
<el-popover placement="bottom" :width="260" trigger="hover">
|
||||
<template #reference>
|
||||
<el-button link>{{state.user.nickname}}</el-button>
|
||||
</template>
|
||||
<div style="text-align: center;">
|
||||
<div><el-avatar :size="50" :src="state.user.avatar" /></div>
|
||||
<div style="font-size: 22px; padding: 0.4rem 0;">{{state.user.username}}</div>
|
||||
<el-button @click="onPersonal()" type="primary" plain>个人中心</el-button>
|
||||
<el-button @click="onLogout()" type="danger" plain>注销登录</el-button>
|
||||
</div>
|
||||
</el-popover>
|
||||
</el-card>
|
||||
</div>
|
||||
<el-dialog v-model="state.userVisible" title="个人中心" width="40%" :show-close="false">
|
||||
<el-form :model="state.user" ref="userRef" :rules="rules" label-width="80px" status-icon>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="用户头像" prop="avatar">
|
||||
<el-avatar :size="50" :src="state.user.avatar" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="用户名称" prop="username">
|
||||
<el-input v-model="state.user.username" disabled style="width: 100%"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="用户昵称" prop="nickname">
|
||||
<el-input v-model="state.user.nickname" disabled placeholder="请输入昵称" style="width: 100%"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="用户电话" prop="phone">
|
||||
<el-input v-model="state.user.phone" disabled style="width: 100%"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="用户邮箱" prop="email">
|
||||
<el-input v-model="state.user.email" disabled style="width: 100%"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="原始密码" prop="oldPassword" :rules="[{required: true, message: '请输入原始密码', trigger: 'blur'}]">
|
||||
<el-input v-model="state.user.oldPassword" type="password" placeholder="请输入原始密码" style="width: 100%"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="用户密码" prop="password" :rules="[{required: true, message: '请输入密码', trigger: 'blur'},
|
||||
{pattern: /^[a-zA-Z]\w{5,17}$/, message: '以字母开头,长度在6~18之间,只能包含字母、数字和下划线', trigger: 'blur'}]">
|
||||
<el-input v-model="state.user.password" type="password" placeholder="请输入密码" style="width: 100%"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item prop="rePassword" label="确认密码" :rules="[{required: true, message: '请输入确认密码', trigger: 'blur'},{validator: validatePass, trigger: 'blur'}]">
|
||||
<el-input v-model="state.user.rePassword" type="password" placeholder="请输入确认密码"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="onUserSubmit(userRef)" type="primary">修改密码</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
.tb-header{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
.el-card{
|
||||
.el-button{
|
||||
margin: 0.8rem 0.6rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,5 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
import {defineProps} from 'vue'
|
||||
import {useRouter} from 'vue-router'
|
||||
import TbSubmenu from "./TbSubmenu.vue"
|
||||
|
||||
|
||||
@ -86,7 +86,7 @@
|
||||
</script>
|
||||
<template>
|
||||
<div class="tabs-menu">
|
||||
<el-tabs v-model="tabsMenuValue" @tab-click="onTabMenuClick" @tab-remove="onTabMenuRemove">
|
||||
<el-tabs type="card" v-model="tabsMenuValue" @tab-click="onTabMenuClick" @tab-remove="onTabMenuRemove">
|
||||
<el-tab-pane v-for="item in tabsMenuList"
|
||||
:key="item.path"
|
||||
:path="item.path"
|
||||
@ -95,6 +95,9 @@
|
||||
:closable="item.close"
|
||||
@node-contextmenu="onTabMenuRemove">
|
||||
<template #label>
|
||||
<el-icon v-if="item.icon" style="vertical-align: middle;">
|
||||
<component :is="item.icon"></component>
|
||||
</el-icon>
|
||||
<el-dropdown :id="item.path" trigger="contextmenu">
|
||||
<span style="vertical-align: middle">{{ item.title }}</span>
|
||||
<template #dropdown>
|
||||
@ -112,6 +115,17 @@
|
||||
</template>
|
||||
<style lang="scss">
|
||||
.tabs-menu{
|
||||
margin-top: 1.2rem;
|
||||
width: 100%;
|
||||
.el-tabs > .el-tabs__header,.el-tabs__item {
|
||||
box-sizing: border-box;
|
||||
height: 32px;
|
||||
}
|
||||
.el-tabs--card > .el-tabs__header{
|
||||
border: none;
|
||||
}
|
||||
.el-tabs--card > .el-tabs__header .el-tabs__nav{
|
||||
border-bottom: none;
|
||||
// background: #ffffff;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
199
tansci-boot-ui/src/components/layout/component/TbSetting.vue
Normal file
199
tansci-boot-ui/src/components/layout/component/TbSetting.vue
Normal file
@ -0,0 +1,199 @@
|
||||
<script setup lang="ts">
|
||||
import {reactive,ref,getCurrentInstance} from 'vue'
|
||||
import { isDark, toggleDark } from '@/composables'
|
||||
import type { FormInstance, Action } from 'element-plus'
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
import { logout } from "@/api/auth"
|
||||
import { modifyPass } from "@/api/system/user"
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
const emit = defineEmits(['onLanguage'])
|
||||
const props = defineProps({
|
||||
height: Number
|
||||
})
|
||||
|
||||
const state = reactive({
|
||||
userVisible: false,
|
||||
user: {
|
||||
avatar: proxy.$global.user.info ? proxy.$global.user.info.avatar : '',
|
||||
username: proxy.$global.user.info ? proxy.$global.user.info.username : '',
|
||||
nickname: proxy.$global.user.info ? proxy.$global.user.info.nickname : '未登录',
|
||||
password: '',
|
||||
rePassword: '',
|
||||
oldPassword: ''
|
||||
}
|
||||
})
|
||||
|
||||
function onPersonal(){
|
||||
state.userVisible = true
|
||||
}
|
||||
|
||||
const userRef = ref<FormInstance>();
|
||||
const validatePass = (rule:any, value:any, callback:any) => {
|
||||
if (value === '') {
|
||||
callback(new Error('请输入确认密码'));
|
||||
} else if (value !== state.user.password) {
|
||||
callback(new Error('两次输入密码不一致!'));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
const onUserSubmit = async (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return;
|
||||
await formEl.validate((valid)=>{
|
||||
if(valid){
|
||||
modifyPass({
|
||||
username: state.user.username,
|
||||
password: state.user.password,
|
||||
oldPassword: state.user.oldPassword
|
||||
}).then(res=>{
|
||||
if(res){
|
||||
state.userVisible = false
|
||||
ElMessageBox.alert('修改密码成功,请重新登录!', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
type: 'warning',
|
||||
callback: (action: Action) =>{
|
||||
logout()
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function onLogout(){
|
||||
ElMessageBox.confirm('确定要退出登录吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}).then(()=>{
|
||||
logout()
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<div class="tb-setting">
|
||||
<div>
|
||||
<el-tooltip effect="light" placement="right">
|
||||
<template #default>
|
||||
<el-button size="large" circle>
|
||||
<template #icon>
|
||||
<el-icon :size="22" color="#777aaf"><Setting /></el-icon>
|
||||
</template>
|
||||
</el-button>
|
||||
</template>
|
||||
<template #content>
|
||||
<div style="text-align: center;">
|
||||
<div><el-avatar :size="50" :src="state.user.avatar" /></div>
|
||||
<div style="font-size: 22px; padding: 0.4rem 0;">{{state.user.username}}</div>
|
||||
<el-button @click="onPersonal()" type="primary" plain>个人中心</el-button>
|
||||
<el-button @click="onLogout()" type="danger" plain>注销登录</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-tooltip>
|
||||
<el-dialog v-model="state.userVisible" title="个人中心" width="40%" :show-close="false">
|
||||
<el-form :model="state.user" ref="userRef" :rules="rules" label-width="80px" status-icon>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="用户头像" prop="avatar">
|
||||
<el-avatar :size="50" :src="state.user.avatar" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="用户名称" prop="username">
|
||||
<el-input v-model="state.user.username" disabled style="width: 100%"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="用户昵称" prop="nickname">
|
||||
<el-input v-model="state.user.nickname" disabled placeholder="请输入昵称" style="width: 100%"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="用户电话" prop="phone">
|
||||
<el-input v-model="state.user.phone" disabled style="width: 100%"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="用户邮箱" prop="email">
|
||||
<el-input v-model="state.user.email" disabled style="width: 100%"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="原始密码" prop="oldPassword" :rules="[{required: true, message: '请输入原始密码', trigger: 'blur'}]">
|
||||
<el-input v-model="state.user.oldPassword" type="password" placeholder="请输入原始密码" style="width: 100%"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="用户密码" prop="password" :rules="[{required: true, message: '请输入密码', trigger: 'blur'},
|
||||
{pattern: /^[a-zA-Z]\w{5,17}$/, message: '以字母开头,长度在6~18之间,只能包含字母、数字和下划线', trigger: 'blur'}]">
|
||||
<el-input v-model="state.user.password" type="password" placeholder="请输入密码" style="width: 100%"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item prop="rePassword" label="确认密码" :rules="[{required: true, message: '请输入确认密码', trigger: 'blur'},{validator: validatePass, trigger: 'blur'}]">
|
||||
<el-input v-model="state.user.rePassword" type="password" placeholder="请输入确认密码"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="onUserSubmit(userRef)" type="primary">修改密码</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
<div>
|
||||
<el-tooltip effect="light" placement="right">
|
||||
<template #default>
|
||||
<el-button size="large" circle>
|
||||
<template #icon>
|
||||
<el-icon :size="22" color="#777aaf"><Mic /></el-icon>
|
||||
</template>
|
||||
</el-button>
|
||||
</template>
|
||||
<template #content>
|
||||
<div>
|
||||
<el-button @click="$emit('onLanguage', 'zh-cn')" link>中文</el-button><br/>
|
||||
<el-button @click="$emit('onLanguage', 'en')" link>English</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<div>
|
||||
<el-tooltip effect="light" placement="right" content="全屏展示">
|
||||
<template #default>
|
||||
<el-button @click="toggleDark()" size="large" circle >
|
||||
<template #icon>
|
||||
<el-icon :size="22" color="#777aaf"><Sunny v-show="!isDark"/></el-icon>
|
||||
<el-icon :size="22" color="#777aaf"><Sunrise v-show="isDark"/></el-icon>
|
||||
</template>
|
||||
</el-button>
|
||||
</template>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
.tb-setting{
|
||||
z-index: 9999;
|
||||
position: absolute;
|
||||
right: 1.5rem;
|
||||
// top: 0.4rem;
|
||||
bottom: 2rem;
|
||||
div{
|
||||
margin: 0.2rem 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,5 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
import {defineProps} from 'vue'
|
||||
const props = defineProps({
|
||||
data: Array
|
||||
})
|
||||
|
||||
Loading…
Reference in New Issue
Block a user