36 changed files with 804 additions and 522 deletions
@ -1,9 +1,10 @@
@@ -1,9 +1,10 @@
|
||||
import { Store } from 'noob-mengyxu'; |
||||
import { Store, Styles } from 'noob-mengyxu'; |
||||
class State extends Store.State { |
||||
test = [ |
||||
{ key: 'a', value: 'A' }, |
||||
{ key: 'b', value: 'B' }, |
||||
{ key: 'c', value: 'C' }, |
||||
]; |
||||
style = Styles.plainb; |
||||
} |
||||
export default new State(); |
||||
|
@ -1,92 +0,0 @@
@@ -1,92 +0,0 @@
|
||||
<template> |
||||
<el-form label-position="right" class="login-form" :model="param" ref="loginForm" :rules="rules"> |
||||
<div class="logo-item" v-if="logo"> |
||||
<el-image class="logo" :src="logo" fit="fit" /> |
||||
</div> |
||||
<el-form-item> |
||||
<div class="lte-title"> {{ t('title') }} </div> |
||||
</el-form-item> |
||||
<el-form-item prop="userId"> |
||||
<NoobInput v-model="param.userId" :placeholder="t('pwd.userId')" :full="true"></NoobInput> |
||||
</el-form-item> |
||||
<el-form-item prop="password"> |
||||
<NoobInput v-model="param.password" type="password" :placeholder="t('pwd.pwd')" :full="true"></NoobInput> |
||||
</el-form-item> |
||||
<el-form-item> |
||||
<NoobButton @click="login">{{ t('pwd.login') }}</NoobButton> |
||||
</el-form-item> |
||||
</el-form> |
||||
</template> |
||||
|
||||
<script lang="ts" setup> |
||||
import { useStore } from "vuex"; |
||||
import { reactive, onMounted, ref } from "vue"; |
||||
import { FormInstance } from "element-plus"; |
||||
import { NoobInput, NoobButton, Element } from "noob-mengyxu"; |
||||
import { useI18n } from "vue3-i18n"; |
||||
|
||||
const { t } = useI18n(); |
||||
const { state } = useStore(); |
||||
const { SimpleRequired } = Element; |
||||
|
||||
const emit = defineEmits(["login"]); |
||||
const param = ref<any>({}); |
||||
const loginForm = ref<FormInstance>(); |
||||
|
||||
const rules = { |
||||
userId: [new SimpleRequired('pwd.userId')], |
||||
password: [new SimpleRequired('pwd.pwd')] |
||||
} |
||||
|
||||
const props = defineProps({ |
||||
logo: { |
||||
type: String, |
||||
default: null, |
||||
}, |
||||
}); |
||||
|
||||
const login = () => { |
||||
if (!loginForm.value) return; |
||||
loginForm.value?.validate((valid, fields) => { |
||||
if (valid) { |
||||
emit("login", param.value); |
||||
loginForm.value?.clearValidate(); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
onMounted(() => { }); |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
//@import url(); 引入公共css类 |
||||
.login-form { |
||||
width: v-bind('state.size.loginWidth'); |
||||
height: v-bind('state.size.loginHeight'); |
||||
} |
||||
|
||||
.logo-item { |
||||
text-align: center; |
||||
align-items: center; |
||||
} |
||||
|
||||
.logo { |
||||
width: 50px; |
||||
height: 50px; |
||||
|
||||
img { |
||||
display: inline !important; |
||||
} |
||||
} |
||||
|
||||
.lte-title { |
||||
font-size: 1.5em; |
||||
font-weight: bold; |
||||
text-align: center; |
||||
width: 100%; |
||||
color: rgb(49, 89, 143); |
||||
} |
||||
|
||||
.el-button { |
||||
width: 100%; |
||||
} |
||||
</style> |
@ -1,283 +0,0 @@
@@ -1,283 +0,0 @@
|
||||
<template> |
||||
<el-button v-if="closeAble" class="close-btn" :icon="isClose ? 'CaretRight' : 'CaretLeft'" circle |
||||
:size="state.size.size" @click="close"></el-button> |
||||
<div class="head"> |
||||
<div class="title"> |
||||
<el-image class="logo" v-if="logo" :src="logo" fit="fit" /> |
||||
{{ title || t('title') }} |
||||
</div> |
||||
<div class="menu"> |
||||
<el-dropdown class="icon" :size="state.size.size" :teleported="false"> |
||||
<el-button :size="state.size.size" icon="Avatar" circle></el-button> |
||||
<template #dropdown> |
||||
<el-dropdown-menu> |
||||
<el-dropdown-item v-if="center" @click="router.push(center)"> |
||||
{{ t('head.center') }} |
||||
</el-dropdown-item> |
||||
<el-dropdown-item @click="updatePass">{{ t('pwd.changePwd') }}</el-dropdown-item> |
||||
<el-dropdown-item @click="dispatch('logout'); emit('logout')">{{ t('head.logout') |
||||
}}</el-dropdown-item> |
||||
</el-dropdown-menu> |
||||
</template> |
||||
</el-dropdown> |
||||
<el-tooltip effect="dark" :content="t('head.fullScreen')" placement="bottom"> |
||||
<el-icon @click="fullscreen" class="icon"> |
||||
<FullScreen /> |
||||
</el-icon> |
||||
</el-tooltip> |
||||
<el-tooltip effect="dark" :content="t('head.changeStyle')" placement="left"> |
||||
<el-dropdown v-show="styleAble" class="icon" :size="state.size.size" trigger="click" :teleported="false"> |
||||
<el-button :size="state.size.size" icon="Opportunity" circle></el-button> |
||||
<template #dropdown> |
||||
<el-dropdown-menu> |
||||
<el-dropdown-item @click="changeStyle('plain')"> |
||||
<el-tooltip effect="dark" :content="t('head.default')" placement="left"> |
||||
<el-icon class="dropdown-icon"> |
||||
<Sunset /> |
||||
</el-icon> |
||||
</el-tooltip> |
||||
</el-dropdown-item> |
||||
<el-dropdown-item @click="changeStyle('light')"> |
||||
<el-tooltip effect="dark" :content="t('head.light')" placement="left"> |
||||
<el-icon class="dropdown-icon"> |
||||
<Sunny /> |
||||
</el-icon> |
||||
</el-tooltip> |
||||
</el-dropdown-item> |
||||
<el-dropdown-item @click="changeStyle('dark')"> |
||||
<el-tooltip effect="dark" :content="t('head.dark')" placement="left"> |
||||
<el-icon class="dropdown-icon"> |
||||
<MoonNight /> |
||||
</el-icon> |
||||
</el-tooltip> |
||||
</el-dropdown-item> |
||||
</el-dropdown-menu> |
||||
</template> |
||||
</el-dropdown> |
||||
</el-tooltip> |
||||
<el-tooltip effect="dark" :content="t('head.language')" placement="left"> |
||||
<el-dropdown v-show="langAble" class="icon" :size="state.size.size" trigger="click" :teleported="false"> |
||||
<el-button icon="Flag" :size="state.size.size" circle></el-button> |
||||
<template #dropdown> |
||||
<el-dropdown-menu> |
||||
<el-dropdown-item @click="changeLang('zh')">{{ t('head.zh') }}</el-dropdown-item> |
||||
<el-dropdown-item @click="changeLang('en')">{{ t('head.en') }}</el-dropdown-item> |
||||
</el-dropdown-menu> |
||||
</template> |
||||
</el-dropdown> |
||||
</el-tooltip> |
||||
<el-tooltip effect="dark" :content="t('head.size')" placement="left"> |
||||
<el-dropdown v-show="sizeAble" class="icon" :size="state.size.size" trigger="click" :teleported="false"> |
||||
<el-button icon="Switch" :size="state.size.size" circle></el-button> |
||||
<template #dropdown> |
||||
<el-dropdown-menu> |
||||
<el-dropdown-item @click="changeSize('small')">{{ t('head.small') }}</el-dropdown-item> |
||||
<el-dropdown-item @click="changeSize('normal')">{{ t('head.normal') }}</el-dropdown-item> |
||||
<el-dropdown-item @click="changeSize('large')">{{ t('head.large') }}</el-dropdown-item> |
||||
</el-dropdown-menu> |
||||
</template> |
||||
</el-dropdown> |
||||
</el-tooltip> |
||||
<span class="username" v-if="username">{{ username }}</span> |
||||
</div> |
||||
</div> |
||||
|
||||
<el-dialog :title="t('pwd.changePwd')" v-model="flag.update" :size="state.size.size" :close-on-click-modal="false" |
||||
top="10vh" width="40%"> |
||||
<ModifyForm :width="150" :param="password" @cancel="flag.update = false" |
||||
@confirm="emit('updatePwd', password); flag.update = false" :rules="rules" :items="items"> |
||||
</ModifyForm> |
||||
</el-dialog> |
||||
</template> |
||||
|
||||
<script lang="ts" setup> |
||||
import { useStore } from "vuex"; |
||||
import { reactive, onMounted, ref } from "vue"; |
||||
import { ModifyForm } from "noob-mengyxu"; |
||||
import { Element, Styles, Size, NoobInput } from "noob-mengyxu"; |
||||
import { useRouter } from "vue-router"; |
||||
import { useI18n } from "vue3-i18n"; |
||||
|
||||
const { SimpleRequired, SimplePassword } = Element; |
||||
const { state, commit, dispatch } = useStore(); |
||||
const router = useRouter(); |
||||
const i18n = useI18n(); |
||||
const { t } = useI18n(); |
||||
const emit = defineEmits(["updatePwd", "logout"]); |
||||
const flag = reactive({ |
||||
update: false |
||||
}) |
||||
const password = ref({ |
||||
new: '', |
||||
reNew: '', |
||||
old: '' |
||||
}) |
||||
|
||||
const props = defineProps({ |
||||
title: { |
||||
type: String, |
||||
default: null, |
||||
}, |
||||
username: { |
||||
type: String, |
||||
default: null, |
||||
}, |
||||
styleAble: { |
||||
type: Boolean, |
||||
}, |
||||
sizeAble: { |
||||
type: Boolean, |
||||
}, |
||||
langAble: { |
||||
type: Boolean, |
||||
}, |
||||
center: { |
||||
type: String, |
||||
default: null, |
||||
}, |
||||
closeAble: { |
||||
type: Boolean, |
||||
default: false, |
||||
}, |
||||
logo: { |
||||
type: String, |
||||
default: null, |
||||
}, |
||||
}); |
||||
|
||||
const isClose = ref(false) |
||||
const close = () => { |
||||
isClose.value = !isClose.value; |
||||
if (isClose.value) { |
||||
state.size.asideWidth = '0px'; |
||||
commit("initSize"); |
||||
} else { |
||||
state.size.asideWidth = state.size.aside + 'px'; |
||||
commit("initSize"); |
||||
} |
||||
} |
||||
|
||||
const rules = { |
||||
old: [new SimpleRequired('pwd.oldPwd')], |
||||
new: [new SimpleRequired('pwd.newPwd'), new SimplePassword()], |
||||
reNew: [{ |
||||
required: true, |
||||
trigger: 'blur', |
||||
validator: (rule: any, value: any, callback: any) => { |
||||
if (value == null || value === '') { |
||||
callback(new Error(t('pwd.plsRePwd'))); |
||||
} else if (value != password.value.new) { |
||||
callback(new Error(t('pwd.rePwdError'))); |
||||
} |
||||
callback(); |
||||
} |
||||
}] |
||||
} |
||||
|
||||
const items = [ |
||||
{ i18n: 'pwd.oldPwd', code: 'old', type: "password" }, |
||||
{ i18n: 'pwd.newPwd', code: 'new', type: "password" }, |
||||
{ i18n: 'pwd.rePwd', code: 'reNew', type: "password" }, |
||||
] |
||||
|
||||
const updatePass = () => { |
||||
password.value = { |
||||
new: '', |
||||
reNew: '', |
||||
old: '' |
||||
}; |
||||
flag.update = true; |
||||
} |
||||
|
||||
const fullscreen = () => { |
||||
if (!document.fullscreenElement) { |
||||
document.documentElement.requestFullscreen(); |
||||
} else { |
||||
if (document.exitFullscreen) { |
||||
document.exitFullscreen(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
const changeStyle = type => { |
||||
commit('updateState', ['style', Styles[type]]); |
||||
} |
||||
|
||||
const changeLang = type => { |
||||
i18n.setLocale(type); |
||||
} |
||||
|
||||
const changeSize = type => { |
||||
commit('updateState', ['size', Size[type]]) |
||||
commit('initSize', window.innerHeight); |
||||
} |
||||
|
||||
onMounted(() => { }); |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
.close-btn { |
||||
position: absolute; |
||||
z-index: 99; |
||||
top: v-bind('state.size.closeTop'); |
||||
left: -5px; |
||||
color: red; |
||||
background: transparent; |
||||
} |
||||
|
||||
.head { |
||||
background-color: v-bind('state.style.headBg'); |
||||
height: v-bind('state.size.headHeight'); |
||||
} |
||||
|
||||
.logo { |
||||
float: left; |
||||
width: v-bind('state.size.headHeight'); |
||||
height: v-bind('state.size.headHeight'); |
||||
} |
||||
|
||||
.title { |
||||
height: v-bind('state.size.headHeight'); |
||||
// width: v-bind('state.size.asideWidth'); |
||||
text-align: center; |
||||
float: left; |
||||
font-size: v-bind('state.size.titleSize'); |
||||
line-height: v-bind('state.size.headHeight'); |
||||
font-weight: bold; |
||||
color: v-bind('state.style.titleColor'); |
||||
} |
||||
|
||||
.menu { |
||||
float: right; |
||||
line-height: v-bind('state.size.headHeight'); |
||||
width: v-bind('state.size.headMenuWidth'); |
||||
padding-right: 10px; |
||||
|
||||
align-items: center; |
||||
justify-content: center; |
||||
|
||||
.icon { |
||||
float: right; |
||||
cursor: pointer; |
||||
height: v-bind('state.size.headHeight'); |
||||
margin-right: 20px; |
||||
font-size: v-bind('state.size.headIconSize'); |
||||
align-items: center; |
||||
color: v-bind('state.style.color'); |
||||
} |
||||
|
||||
.username { |
||||
float: right; |
||||
height: v-bind('state.size.headHeight'); |
||||
margin-right: 20px; |
||||
font-size: v-bind('state.size.titleSize'); |
||||
font-weight: bold; |
||||
color: v-bind('state.style.color'); |
||||
} |
||||
|
||||
} |
||||
|
||||
.dropdown-icon { |
||||
font-size: 20px; |
||||
margin: 5px 3px; |
||||
} |
||||
</style> |
@ -0,0 +1,4 @@
@@ -0,0 +1,4 @@
|
||||
import Login from './login.vue'; |
||||
import Login2 from './login2.vue'; |
||||
|
||||
export default { Login, Login2 }; |
@ -0,0 +1,127 @@
@@ -0,0 +1,127 @@
|
||||
<template> |
||||
<div class="login"> |
||||
<el-form label-position="right" class="login-form" :model="param" ref="loginForm" :rules="rules"> |
||||
<div class="logo-item" v-if="logo"> |
||||
<el-image class="logo" :src="logo" fit="fit" /> |
||||
</div> |
||||
<el-form-item> |
||||
<div class="lte-title"> {{ t('title') }} </div > |
||||
</el-form-item> |
||||
<el-form-item prop="userId"> |
||||
<NoobInput v-model="param.userId" :placeholder="t('pwd.userId')" :full="true"></NoobInput> |
||||
</el-form-item> |
||||
<el-form-item prop="password"> |
||||
<NoobInput v-model="param.password" type="password" :placeholder="t('pwd.pwd')" :full="true"> |
||||
</NoobInput> |
||||
</el-form-item> |
||||
<el-form-item> |
||||
<NoobButton @click="login">{{ t('pwd.login') }}</NoobButton> |
||||
</el-form-item> |
||||
</el-form> |
||||
</div> |
||||
</template> |
||||
|
||||
<script lang="ts" setup> |
||||
import { useStore } from "vuex"; |
||||
import { onBeforeMount, onMounted, ref } from "vue"; |
||||
import { useRouter } from "vue-router"; |
||||
import { FormInstance } from "element-plus"; |
||||
import { Api, NoobInput, NoobButton, Element } from "noob-mengyxu"; |
||||
import md5 from "js-md5"; |
||||
import { useI18n } from "vue3-i18n"; |
||||
|
||||
const { t } = useI18n(); |
||||
const { state, commit, dispatch } = useStore(); |
||||
const { SimpleRequired } = Element; |
||||
|
||||
const emit = defineEmits(["login"]); |
||||
const param = ref<any>({}); |
||||
const loginForm = ref<FormInstance>(); |
||||
|
||||
const rules = { |
||||
userId: [new SimpleRequired('pwd.userId')], |
||||
password: [new SimpleRequired('pwd.pwd')] |
||||
} |
||||
|
||||
const props = defineProps({ |
||||
logo: { |
||||
type: String, |
||||
default: null, |
||||
}, |
||||
}); |
||||
|
||||
const router = useRouter(); |
||||
|
||||
onBeforeMount(() => { |
||||
state.size.headHeight = '0px'; |
||||
state.size.asideWidth = '0px'; |
||||
commit("initSize"); |
||||
}); |
||||
|
||||
const loginConfirm = user => { |
||||
const param = JSON.parse(JSON.stringify(user)); |
||||
param.password = md5(param.password); |
||||
Api.pub.login(param).then(rsp => { |
||||
if (rsp) { |
||||
state.size.headHeight = state.size.head + 'px'; |
||||
state.size.asideWidth = state.size.aside + 'px'; |
||||
commit("initSize"); |
||||
dispatch("getMenus"); |
||||
router.back(); |
||||
} |
||||
}) |
||||
}; |
||||
|
||||
const login = () => { |
||||
if (!loginForm.value) return; |
||||
loginForm.value?.validate((valid, fields) => { |
||||
if (valid) { |
||||
loginConfirm(param.value); |
||||
loginForm.value?.clearValidate(); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
onMounted(() => { }); |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
.login { |
||||
width: 100%; |
||||
height: 100%; |
||||
display: flex; |
||||
align-items: center; |
||||
justify-content: center; |
||||
} |
||||
|
||||
.login-form { |
||||
width: v-bind('state.size.loginWidth'); |
||||
height: v-bind('state.size.loginHeight'); |
||||
align-self: center; |
||||
} |
||||
|
||||
.logo-item { |
||||
text-align: center; |
||||
align-items: center; |
||||
} |
||||
|
||||
.logo { |
||||
width: 50px; |
||||
height: 50px; |
||||
|
||||
img { |
||||
display: inline !important; |
||||
} |
||||
} |
||||
|
||||
.lte-title { |
||||
font-size: 1.5em; |
||||
font-weight: bold; |
||||
text-align: center; |
||||
width: 100%; |
||||
color: rgb(49, 89, 143); |
||||
} |
||||
|
||||
.el-button { |
||||
width: 100%; |
||||
} |
||||
</style> |
@ -0,0 +1,145 @@
@@ -0,0 +1,145 @@
|
||||
<template> |
||||
<div class="login"> |
||||
<el-form label-position="right" class="login-form" :model="param" ref="loginForm" :rules="rules"> |
||||
<div class="logo-item" v-if="logo"> |
||||
<el-image class="logo" :src="logo" fit="fit" /> |
||||
</div> |
||||
<div class="lte-title"> {{ t('title') }} </div> |
||||
<el-form-item vlass prop="userId"> |
||||
<span class="login-label">{{ t('pwd.userId') }}:</span> |
||||
<NoobInput class="login-input " v-model="param.userId" :full="true" placeholder=" " /> |
||||
</el-form-item> |
||||
<el-form-item prop="password"> |
||||
<span class="login-label">{{ t('pwd.pwd') }}:</span> |
||||
<NoobInput class="login-input" v-model="param.password" type="password" :full="true" placeholder=" " /> |
||||
</el-form-item> |
||||
<el-form-item> |
||||
<NoobButton class="login-btn" @click="login">{{ t('pwd.login') }}</NoobButton> |
||||
</el-form-item> |
||||
</el-form> |
||||
</div> |
||||
</template> |
||||
|
||||
<script lang="ts" setup> |
||||
import { useStore } from "vuex"; |
||||
import { onBeforeMount, onMounted, ref } from "vue"; |
||||
import { useRouter } from "vue-router"; |
||||
import { FormInstance } from "element-plus"; |
||||
import { Api, NoobInput, NoobButton, Element } from "noob-mengyxu"; |
||||
import md5 from "js-md5"; |
||||
import { useI18n } from "vue3-i18n"; |
||||
|
||||
const { t } = useI18n(); |
||||
const { state, commit, dispatch } = useStore(); |
||||
const { SimpleRequired } = Element; |
||||
|
||||
const emit = defineEmits(["login"]); |
||||
const param = ref<any>({}); |
||||
const loginForm = ref<FormInstance>(); |
||||
|
||||
const rules = { |
||||
userId: [new SimpleRequired('pwd.userId')], |
||||
password: [new SimpleRequired('pwd.pwd')] |
||||
} |
||||
|
||||
const props = defineProps({ |
||||
logo: { |
||||
type: String, |
||||
default: null, |
||||
}, |
||||
}); |
||||
|
||||
const router = useRouter(); |
||||
|
||||
onBeforeMount(() => { |
||||
state.size.headHeight = '0px'; |
||||
state.size.asideWidth = '0px'; |
||||
commit("initSize"); |
||||
}); |
||||
|
||||
const loginConfirm = user => { |
||||
const param = JSON.parse(JSON.stringify(user)); |
||||
param.password = md5(param.password); |
||||
Api.pub.login(param).then(rsp => { |
||||
if (rsp) { |
||||
state.size.headHeight = state.size.head + 'px'; |
||||
state.size.asideWidth = state.size.aside + 'px'; |
||||
commit("initSize"); |
||||
dispatch("getMenus"); |
||||
router.back(); |
||||
} |
||||
}) |
||||
}; |
||||
|
||||
const login = () => { |
||||
if (!loginForm.value) return; |
||||
loginForm.value?.validate((valid, fields) => { |
||||
if (valid) { |
||||
loginConfirm(param.value); |
||||
loginForm.value?.clearValidate(); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
onMounted(() => { }); |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
.login { |
||||
width: 100%; |
||||
height: 100%; |
||||
display: flex; |
||||
align-items: center; |
||||
justify-content: center; |
||||
} |
||||
|
||||
.login-form { |
||||
width: 600px; |
||||
height: 600px; |
||||
align-self: center; |
||||
} |
||||
|
||||
.logo-item { |
||||
text-align: center; |
||||
align-items: center; |
||||
} |
||||
|
||||
.logo { |
||||
width: 50px; |
||||
height: 50px; |
||||
|
||||
img { |
||||
display: inline !important; |
||||
} |
||||
} |
||||
|
||||
.lte-title { |
||||
font-size: 2.5em; |
||||
height: 100px; |
||||
line-height: 100px; |
||||
font-weight: bold; |
||||
text-align: center; |
||||
width: 100%; |
||||
color: #424242; |
||||
} |
||||
|
||||
.login-input { |
||||
|
||||
::v-deep .el-input__inner { |
||||
font-size: 2rem; |
||||
line-height: 3.5rem; |
||||
height: 3.5rem; |
||||
padding: 1rem; |
||||
} |
||||
} |
||||
|
||||
.el-button { |
||||
width: 100%; |
||||
} |
||||
|
||||
.login-btn { |
||||
margin-top: 1.2rem; |
||||
font-size: 1.5rem; |
||||
line-height: 2rem; |
||||
height: 3rem; |
||||
} |
||||
</style> |
@ -0,0 +1,26 @@
@@ -0,0 +1,26 @@
|
||||
<template> |
||||
<el-tooltip effect="dark" :content="t('head.fullScreen')" placement="bottom"> |
||||
<el-icon @click="fullscreen" class="head-icon"> |
||||
<FullScreen /> |
||||
</el-icon> |
||||
</el-tooltip> |
||||
</template> |
||||
|
||||
<script lang="ts" setup> |
||||
import { onMounted } from "vue"; |
||||
import { useI18n } from "vue3-i18n"; |
||||
const { t } = useI18n(); |
||||
|
||||
const fullscreen = () => { |
||||
if (!document.fullscreenElement) { |
||||
document.documentElement.requestFullscreen(); |
||||
} else { |
||||
if (document.exitFullscreen) { |
||||
document.exitFullscreen(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
onMounted(() => { }); |
||||
</script> |
||||
<style lang="scss" scoped></style> |
@ -0,0 +1,119 @@
@@ -0,0 +1,119 @@
|
||||
<template> |
||||
<el-button v-if="closeAble" class="close-aside-btn" :icon="isClose ? 'CaretRight' : 'CaretLeft'" circle |
||||
:size="state.size.size" @click="close"></el-button> |
||||
<div class="head"> |
||||
<div class="head-left"> |
||||
<div class="title"> |
||||
<el-image class="logo" v-if="logo" :src="logo" fit="fit" /> |
||||
{{ title || t('title') }} |
||||
</div> |
||||
<slot name="left"></slot> |
||||
</div> |
||||
<div class="head-right"> |
||||
<slot></slot> |
||||
<span class="username" v-if="username">{{ username }}</span> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script lang="ts" setup> |
||||
import { useStore } from "vuex"; |
||||
import { reactive, onMounted, ref } from "vue"; |
||||
import { useI18n } from "vue3-i18n"; |
||||
const { t } = useI18n(); |
||||
|
||||
const { state, commit, dispatch } = useStore(); |
||||
|
||||
const props = defineProps({ |
||||
closeAble: { |
||||
type: Boolean, |
||||
default: false, |
||||
}, |
||||
title: { |
||||
type: String, |
||||
default: null, |
||||
}, |
||||
logo: { |
||||
type: String, |
||||
default: null, |
||||
}, |
||||
username: { |
||||
type: String, |
||||
default: null, |
||||
}, |
||||
}) |
||||
|
||||
const isClose = ref(false) |
||||
const close = () => { |
||||
isClose.value = !isClose.value; |
||||
if (isClose.value) { |
||||
state.size.asideWidth = '0px'; |
||||
commit("initSize"); |
||||
} else { |
||||
state.size.asideWidth = state.size.aside + 'px'; |
||||
commit("initSize"); |
||||
} |
||||
} |
||||
|
||||
onMounted(() => { }); |
||||
</script> |
||||
<style lang="scss"> |
||||
//@import url(); 引入公共css类 |
||||
.close-aside-btn { |
||||
position: absolute; |
||||
z-index: 99; |
||||
top: v-bind('state.size.closeTop'); |
||||
left: -5px; |
||||
color: red; |
||||
background: transparent; |
||||
} |
||||
|
||||
.title { |
||||
height: v-bind('state.size.headHeight'); |
||||
// width: v-bind('state.size.asideWidth'); |
||||
text-align: center; |
||||
float: left; |
||||
font-size: v-bind('state.size.titleSize'); |
||||
line-height: v-bind('state.size.headHeight'); |
||||
font-weight: bold; |
||||
color: v-bind('state.style.titleColor'); |
||||
} |
||||
|
||||
.head-left { |
||||
float: left; |
||||
line-height: v-bind('state.size.headHeight'); |
||||
width: v-bind('state.size.headLeftWidth'); |
||||
align-items: center; |
||||
justify-content: center; |
||||
} |
||||
|
||||
.head-right { |
||||
float: right; |
||||
line-height: v-bind('state.size.headHeight'); |
||||
width: v-bind('state.size.headRightWidth'); |
||||
padding-right: 10px; |
||||
|
||||
align-items: center; |
||||
justify-content: center; |
||||
|
||||
.head-icon { |
||||
float: right; |
||||
cursor: pointer; |
||||
height: v-bind('state.size.headHeight'); |
||||
margin-right: 20px; |
||||
font-size: v-bind('state.size.headIconSize'); |
||||
align-items: center; |
||||
color: v-bind('state.style.color'); |
||||
} |
||||
|
||||
.username { |
||||
float: right; |
||||
height: v-bind('state.size.headHeight'); |
||||
margin-right: 20px; |
||||
font-size: v-bind('state.size.titleSize'); |
||||
font-weight: bold; |
||||
color: v-bind('state.style.color'); |
||||
} |
||||
|
||||
} |
||||
</style> |
@ -0,0 +1,9 @@
@@ -0,0 +1,9 @@
|
||||
import Head from './head.vue'; |
||||
import HeadPersonal from './personal.vue'; |
||||
import Fullscreen from './fullscreen.vue'; |
||||
import StyleChange from './style-change.vue'; |
||||
import LangChange from './lang-change.vue'; |
||||
import SizeChange from './size-change.vue'; |
||||
import MenuTree from './menu-tree.vue'; |
||||
|
||||
export default { MenuTree, Head, HeadPersonal, Fullscreen, StyleChange, LangChange, SizeChange }; |
@ -0,0 +1,29 @@
@@ -0,0 +1,29 @@
|
||||
<template> |
||||
<el-tooltip effect="dark" :content="t('head.language')" placement="left"> |
||||
<el-dropdown class="head-icon" :size="state.size.size" trigger="click" :teleported="false"> |
||||
<el-button icon="Flag" :size="state.size.size" circle></el-button> |
||||
<template #dropdown> |
||||
<el-dropdown-menu> |
||||
<el-dropdown-item @click="changeLang('zh')">{{ t('head.zh') }}</el-dropdown-item> |
||||
<el-dropdown-item @click="changeLang('en')">{{ t('head.en') }}</el-dropdown-item> |
||||
</el-dropdown-menu> |
||||
</template> |
||||
</el-dropdown> |
||||
</el-tooltip> |
||||
</template> |
||||
|
||||
<script lang="ts" setup> |
||||
import { useStore } from "vuex"; |
||||
import { reactive, onMounted, ref } from "vue"; |
||||
import { useI18n } from "vue3-i18n"; |
||||
const { t, setLocale } = useI18n(); |
||||
|
||||
const { state, commit, dispatch } = useStore(); |
||||
|
||||
const changeLang = type => { |
||||
setLocale(type); |
||||
} |
||||
|
||||
onMounted(() => { }); |
||||
</script> |
||||
<style lang="scss" scoped></style> |
@ -0,0 +1,87 @@
@@ -0,0 +1,87 @@
|
||||
<template> |
||||
<el-dropdown class="head-icon" :size="state.size.size" :teleported="false"> |
||||
<el-button :size="state.size.size" icon="Avatar" circle></el-button> |
||||
<template #dropdown> |
||||
<el-dropdown-menu> |
||||
<el-dropdown-item v-if="center" @click="router.push(center)"> |
||||
{{ t('head.center') }} |
||||
</el-dropdown-item> |
||||
<el-dropdown-item @click="updatePass">{{ t('pwd.changePwd') }}</el-dropdown-item> |
||||
<el-dropdown-item @click="dispatch('logout'); emit('logout')">{{ t('head.logout') |
||||
}}</el-dropdown-item> |
||||
</el-dropdown-menu> |
||||
</template> |
||||
</el-dropdown> |
||||
|
||||
<el-dialog :title="t('pwd.changePwd')" v-model="flag.update" :size="state.size.size" :close-on-click-modal="false" |
||||
top="10vh" width="40%"> |
||||
<ModifyForm :width="150" :param="password" @cancel="flag.update = false" |
||||
@confirm="emit('updatePwd', password); flag.update = false" :rules="rules" :items="items"> |
||||
</ModifyForm> |
||||
</el-dialog> |
||||
|
||||
</template> |
||||
|
||||
<script lang="ts" setup> |
||||
import { useStore } from "vuex"; |
||||
import { reactive, onMounted, ref } from "vue"; |
||||
import { Element, ModifyForm } from "noob-mengyxu"; |
||||
import { useRouter } from "vue-router"; |
||||
import { useI18n } from "vue3-i18n"; |
||||
const { t } = useI18n(); |
||||
|
||||
const { state, commit, dispatch } = useStore(); |
||||
const { SimpleRequired, SimplePassword } = Element; |
||||
const router = useRouter(); |
||||
const flag = reactive({ |
||||
update: false |
||||
}) |
||||
const password = ref({ |
||||
new: '', |
||||
reNew: '', |
||||
old: '' |
||||
}) |
||||
const emit = defineEmits(["updatePwd", "logout"]); |
||||
|
||||
const props = defineProps({ |
||||
center: { |
||||
type: String, |
||||
default: null, |
||||
}, |
||||
}) |
||||
|
||||
const rules = { |
||||
old: [new SimpleRequired('pwd.oldPwd')], |
||||
new: [new SimpleRequired('pwd.newPwd'), new SimplePassword()], |
||||
reNew: [{ |
||||
required: true, |
||||
trigger: 'blur', |
||||
validator: (rule: any, value: any, callback: any) => { |
||||
if (value == null || value === '') { |
||||
callback(new Error(t('pwd.plsRePwd'))); |
||||
} else if (value != password.value.new) { |
||||
callback(new Error(t('pwd.rePwdError'))); |
||||
} |
||||
callback(); |
||||
} |
||||
}] |
||||
} |
||||
|
||||
const items = [ |
||||
{ i18n: 'pwd.oldPwd', code: 'old', type: "password" }, |
||||
{ i18n: 'pwd.newPwd', code: 'new', type: "password" }, |
||||
{ i18n: 'pwd.rePwd', code: 'reNew', type: "password" }, |
||||
] |
||||
|
||||
const updatePass = () => { |
||||
password.value = { |
||||
new: '', |
||||
reNew: '', |
||||
old: '' |
||||
}; |
||||
flag.update = true; |
||||
} |
||||
|
||||
onMounted(() => { }); |
||||
</script> |
||||
<style lang="scss" scoped></style> |
@ -0,0 +1,32 @@
@@ -0,0 +1,32 @@
|
||||
<template> |
||||
<el-tooltip effect="dark" :content="t('head.size')" placement="left"> |
||||
<el-dropdown class="head-icon" :size="state.size.size" trigger="click" :teleported="false"> |
||||
<el-button icon="Switch" :size="state.size.size" circle></el-button> |
||||
<template #dropdown> |
||||
<el-dropdown-menu> |
||||
<el-dropdown-item @click="changeSize('small')">{{ t('head.small') }}</el-dropdown-item> |
||||
<el-dropdown-item @click="changeSize('normal')">{{ t('head.normal') }}</el-dropdown-item> |
||||
<el-dropdown-item @click="changeSize('large')">{{ t('head.large') }}</el-dropdown-item> |
||||
</el-dropdown-menu> |
||||
</template> |
||||
</el-dropdown> |
||||
</el-tooltip> |
||||
</template> |
||||
|
||||
<script lang="ts" setup> |
||||
import { useStore } from "vuex"; |
||||
import { reactive, onMounted, ref } from "vue"; |
||||
import { useI18n } from "vue3-i18n"; |
||||
import { Size } from "noob-mengyxu"; |
||||
const { t } = useI18n(); |
||||
|
||||
const { state, commit, dispatch } = useStore(); |
||||
|
||||
const changeSize = type => { |
||||
commit('updateState', ['size', Size[type]]) |
||||
commit('initSize', [window.innerHeight, window.innerWidth]); |
||||
} |
||||
|
||||
onMounted(() => { }); |
||||
</script> |
||||
<style lang="scss" scoped></style> |
@ -0,0 +1,63 @@
@@ -0,0 +1,63 @@
|
||||
<template> |
||||
<el-tooltip effect="dark" :content="t('head.changeStyle')" placement="left"> |
||||
<el-dropdown class="head-icon" :size="state.size.size" trigger="click" :teleported="false"> |
||||
<el-button :size="state.size.size" icon="Opportunity" circle></el-button> |
||||
<template #dropdown> |
||||
<el-dropdown-menu> |
||||
|
||||
<!-- <el-dropdown-item v-for="item in Styles" @click="changeStyle(item.name)"> |
||||
<el-tooltip effect="dark" :content="t(item.i18n)" placement="left"> |
||||
<component class="icon" :is="item.icon"></component> |
||||
</el-tooltip> |
||||
</el-dropdown-item> --> |
||||
|
||||
<el-dropdown-item @click="changeStyle('plainb')"> |
||||
<el-tooltip effect="dark" :content="t('styles[3]')" placement="left"> |
||||
<el-icon class="dropdown-icon"> |
||||
<Sunset /> |
||||
</el-icon> |
||||
</el-tooltip> |
||||
</el-dropdown-item> |
||||
<el-dropdown-item @click="changeStyle('plain')"> |
||||
<el-tooltip effect="dark" :content="t('styles[0]')" placement="left"> |
||||
<el-icon class="dropdown-icon"> |
||||
<Sunset /> |
||||
</el-icon> |
||||
</el-tooltip> |
||||
</el-dropdown-item> |
||||
<el-dropdown-item @click="changeStyle('light')"> |
||||
<el-tooltip effect="dark" :content="t('styles[1]')" placement="left"> |
||||
<el-icon class="dropdown-icon"> |
||||
<Sunny /> |
||||
</el-icon> |
||||
</el-tooltip> |
||||
</el-dropdown-item> |
||||
<el-dropdown-item @click="changeStyle('dark')"> |
||||
<el-tooltip effect="dark" :content="t('styles[2]')" placement="left"> |
||||
<el-icon class="dropdown-icon"> |
||||
<MoonNight /> |
||||
</el-icon> |
||||
</el-tooltip> |
||||
</el-dropdown-item> |
||||
</el-dropdown-menu> |
||||
</template> |
||||
</el-dropdown> |
||||
</el-tooltip> |
||||
</template> |
||||
|
||||
<script lang="ts" setup> |
||||
import { useStore } from "vuex"; |
||||
import { onMounted } from "vue"; |
||||
import { Styles } from "noob-mengyxu"; |
||||
import { useI18n } from "vue3-i18n"; |
||||
const { t } = useI18n(); |
||||
|
||||
const { state, commit, dispatch } = useStore(); |
||||
|
||||
const changeStyle = type => { |
||||
commit('updateState', ['style', Styles[type]]); |
||||
} |
||||
|
||||
onMounted(() => { }); |
||||
</script> |
||||
<style lang="scss" scoped></style> |
@ -1,5 +1,5 @@
@@ -1,5 +1,5 @@
|
||||
import Index from './router/index.vue'; |
||||
import MenuTree from './common/menu-tree.vue'; |
||||
import Head from './common/head.vue'; |
||||
import Common from './common'; |
||||
import NoobHead from './head'; |
||||
import Views from './views'; |
||||
export { Index, MenuTree, Head, Views }; |
||||
export { Index, Common, NoobHead, Views }; |
||||
|
@ -1,58 +0,0 @@
@@ -1,58 +0,0 @@
|
||||
<template> |
||||
<div class="login"> |
||||
<LoginForm @login="login"> |
||||
</LoginForm> |
||||
</div> |
||||
</template> |
||||
|
||||
<script lang="ts" setup> |
||||
import { onBeforeMount } from "vue"; |
||||
import { useStore } from "vuex"; |
||||
import { useRouter } from "vue-router"; |
||||
import md5 from "js-md5"; |
||||
import { Api, LoginForm } from "noob-mengyxu"; |
||||
|
||||
const { state, commit, dispatch } = useStore(); |
||||
const router = useRouter(); |
||||
|
||||
onBeforeMount(() => { |
||||
state.size.headHeight = '0px'; |
||||
state.size.asideWidth = '0px'; |
||||
commit("initSize"); |
||||
}); |
||||
|
||||
const login = user => { |
||||
const param = JSON.parse(JSON.stringify(user)); |
||||
param.password = md5(param.password); |
||||
Api.pub.login(param).then(rsp => { |
||||
if (rsp) { |
||||
state.size.headHeight = state.size.head + 'px'; |
||||
state.size.asideWidth = state.size.aside + 'px'; |
||||
commit("initSize"); |
||||
dispatch("getMenus"); |
||||
router.back(); |
||||
} |
||||
}) |
||||
}; |
||||
|
||||
</script> |
||||
<style lang='scss' scoped> |
||||
//@import url(); 引入公共css类 |
||||
.login { |
||||
width: 100%; |
||||
height: 100%; |
||||
display: flex; |
||||
align-items: center; |
||||
justify-content: center; |
||||
} |
||||
|
||||
.canvas { |
||||
position: fixed; |
||||
z-index: -1; // background-color: black; |
||||
} |
||||
|
||||
.logo { |
||||
width: 300px; |
||||
height: 90px; |
||||
} |
||||
</style> |
@ -1,6 +1,8 @@
@@ -1,6 +1,8 @@
|
||||
import Plain from './plain'; |
||||
import Plainb from './plainb'; |
||||
import Light from './light'; |
||||
import Dark from './dark'; |
||||
export const plain = new Plain(); |
||||
export const plainb = new Plainb(); |
||||
export const light = new Light(); |
||||
export const dark = new Dark(); |
||||
|
@ -0,0 +1,17 @@
@@ -0,0 +1,17 @@
|
||||
import Plain from './plain'; |
||||
import { light, dark, grey } from './color'; |
||||
|
||||
export default class Plainb extends Plain { |
||||
name = 'plainb'; //总体样式名称
|
||||
i18n = 'styles.3'; //样式提示i18n配置
|
||||
// bodyBg = light[0]; //全局背景颜色
|
||||
bodyBg = light[0]; //全局背景颜色
|
||||
titleColor = light[3]; //标题颜色
|
||||
subTitleColor = '#424242'; //二级标题颜色
|
||||
color = grey[0]; //全局字体颜色
|
||||
selectionBg = '#9255f4'; //全局文字选中后背景
|
||||
|
||||
headBg = '#6200ee'; //头部背景颜色
|
||||
|
||||
menuBg = '#ebebeb'; //菜单背景颜色
|
||||
} |
Loading…
Reference in new issue