系统各配置优化
This commit is contained in:
parent
0e890d96c5
commit
dbc9d8b458
2
.env
2
.env
|
@ -2,7 +2,7 @@
|
||||||
VITE_PORT = 3100
|
VITE_PORT = 3100
|
||||||
|
|
||||||
# 网站标题
|
# 网站标题
|
||||||
VITE_GLOB_APP_TITLE = JeecgBoot 企业级低代码平台
|
VITE_GLOB_APP_TITLE = 哈尔滨师范大学评阅人员管理系统
|
||||||
|
|
||||||
# 简称,用于配置文件名字 不要出现空格、数字开头等特殊字符
|
# 简称,用于配置文件名字 不要出现空格、数字开头等特殊字符
|
||||||
VITE_GLOB_APP_SHORT_NAME = JeecgBootAdmin
|
VITE_GLOB_APP_SHORT_NAME = JeecgBootAdmin
|
||||||
|
|
|
@ -157,7 +157,7 @@
|
||||||
</style>
|
</style>
|
||||||
<div class="app-loading">
|
<div class="app-loading">
|
||||||
<div class="app-loading-wrap">
|
<div class="app-loading-wrap">
|
||||||
<img src="/resource/img/logo.png" class="app-loading-logo" alt="Logo" />
|
<!--<img src="/logo.png" class="app-loading-logo" alt="Logo" />-->
|
||||||
<div class="app-loading-dots">
|
<div class="app-loading-dots">
|
||||||
<span class="dot dot-spin"><i></i><i></i><i></i><i></i></span>
|
<span class="dot dot-spin"><i></i><i></i><i></i><i></i></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
Binary file not shown.
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 5.3 KiB |
|
@ -4,89 +4,93 @@
|
||||||
-->
|
-->
|
||||||
<template>
|
<template>
|
||||||
<div class="anticon" :class="getAppLogoClass" @click="goHome">
|
<div class="anticon" :class="getAppLogoClass" @click="goHome">
|
||||||
<img src="../../../assets/images/logo.png" />
|
<img style="width: 100%;" src="../../../assets/images/logo-red.png" />
|
||||||
<div class="ml-2 truncate md:opacity-100" :class="getTitleClass" v-show="showTitle">
|
<div style="display: flex;" class="ml-2 truncate md:opacity-100" :class="getTitleClass" v-show="showTitle">
|
||||||
{{ title }}
|
<!-- {{ title }} -->
|
||||||
|
<!-- <span>英语四六级综合管理平台</span> -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, unref } from 'vue';
|
import { computed, unref } from 'vue';
|
||||||
import { useGlobSetting } from '/@/hooks/setting';
|
import { useGlobSetting } from '/@/hooks/setting';
|
||||||
import { useGo } from '/@/hooks/web/usePage';
|
import { useGo } from '/@/hooks/web/usePage';
|
||||||
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
||||||
import { useDesign } from '/@/hooks/web/useDesign';
|
import { useDesign } from '/@/hooks/web/useDesign';
|
||||||
import { PageEnum } from '/@/enums/pageEnum';
|
import { PageEnum } from '/@/enums/pageEnum';
|
||||||
import { useUserStore } from '/@/store/modules/user';
|
import { useUserStore } from '/@/store/modules/user';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
/**
|
/**
|
||||||
* The theme of the current parent component
|
* The theme of the current parent component
|
||||||
*/
|
*/
|
||||||
theme: { type: String, validator: (v: string) => ['light', 'dark'].includes(v) },
|
theme: { type: String, validator: (v: string) => ['light', 'dark'].includes(v) },
|
||||||
/**
|
/**
|
||||||
* Whether to show title
|
* Whether to show title
|
||||||
*/
|
*/
|
||||||
showTitle: { type: Boolean, default: true },
|
showTitle: { type: Boolean, default: true },
|
||||||
/**
|
/**
|
||||||
* The title is also displayed when the menu is collapsed
|
* The title is also displayed when the menu is collapsed
|
||||||
*/
|
*/
|
||||||
alwaysShowTitle: { type: Boolean },
|
alwaysShowTitle: { type: Boolean },
|
||||||
});
|
});
|
||||||
|
|
||||||
const { prefixCls } = useDesign('app-logo');
|
const { prefixCls } = useDesign('app-logo');
|
||||||
const { getCollapsedShowTitle } = useMenuSetting();
|
const { getCollapsedShowTitle } = useMenuSetting();
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
const { title } = useGlobSetting();
|
const { title } = useGlobSetting();
|
||||||
const go = useGo();
|
const go = useGo();
|
||||||
|
|
||||||
const getAppLogoClass = computed(() => [prefixCls, props.theme, { 'collapsed-show-title': unref(getCollapsedShowTitle) }]);
|
const getAppLogoClass = computed(() => [prefixCls, props.theme, { 'collapsed-show-title': unref(getCollapsedShowTitle) }]);
|
||||||
|
|
||||||
const getTitleClass = computed(() => [
|
const getTitleClass = computed(() => [
|
||||||
`${prefixCls}__title`,
|
`${prefixCls}__title`,
|
||||||
{
|
{
|
||||||
'xs:opacity-0': !props.alwaysShowTitle,
|
'xs:opacity-0': !props.alwaysShowTitle,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
function goHome() {
|
function goHome() {
|
||||||
go(userStore.getUserInfo.homePath || PageEnum.BASE_HOME);
|
go(userStore.getUserInfo.homePath || PageEnum.BASE_HOME);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
@prefix-cls: ~'@{namespace}-app-logo';
|
@prefix-cls: ~'@{namespace}-app-logo';
|
||||||
|
|
||||||
.@{prefix-cls} {
|
.@{prefix-cls} {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding-left: 7px;
|
padding-left: 7px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
//左侧菜单模式和左侧菜单混合模式加渐变背景色
|
|
||||||
&.jeecg-layout-mix-sider-logo,&.jeecg-layout-menu-logo{
|
|
||||||
background:@sider-logo-bg-color;
|
|
||||||
}
|
|
||||||
// &.light {
|
|
||||||
// border-bottom: 1px solid @border-color-base;
|
|
||||||
// }
|
|
||||||
|
|
||||||
&.collapsed-show-title {
|
//左侧菜单模式和左侧菜单混合模式加渐变背景色
|
||||||
padding-left: 20px;
|
&.jeecg-layout-mix-sider-logo,
|
||||||
}
|
&.jeecg-layout-menu-logo {
|
||||||
|
background: @sider-logo-bg-color;
|
||||||
&.light &__title {
|
|
||||||
color: @primary-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.dark &__title {
|
|
||||||
color: @white;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__title {
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 700;
|
|
||||||
transition: all 0.5s;
|
|
||||||
line-height: normal;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// &.light {
|
||||||
|
// border-bottom: 1px solid @border-color-base;
|
||||||
|
// }
|
||||||
|
|
||||||
|
&.collapsed-show-title {
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.light &__title {
|
||||||
|
color: @primary-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.dark &__title {
|
||||||
|
color: @white;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 700;
|
||||||
|
transition: all 0.5s;
|
||||||
|
line-height: normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,6 +1,20 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="scrollbar">
|
<div class="scrollbar">
|
||||||
<div ref="wrap" :class="[wrapClass, 'scrollbar__wrap', native ? '' : 'scrollbar__wrap--hidden-default']" :style="style" @scroll="handleScroll">
|
<div ref="wrap" :class="[wrapClass, 'scrollbar__wrap', native ? '' : 'scrollbar__wrap--hidden-default']"
|
||||||
|
:style="style" @scroll="handleScroll">
|
||||||
|
<div style="display: flex; justify-content: center; align-items: center">
|
||||||
|
<span style="
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 700;
|
||||||
|
transition: all 0.5s;
|
||||||
|
line-height: normal;
|
||||||
|
padding: 5px;
|
||||||
|
">
|
||||||
|
评阅人员管理系统
|
||||||
|
</span>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
<component :is="tag" ref="resize" :class="['scrollbar__view', viewClass]" :style="viewStyle">
|
<component :is="tag" ref="resize" :class="['scrollbar__view', viewClass]" :style="viewStyle">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</component>
|
</component>
|
||||||
|
@ -12,182 +26,182 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { addResizeListener, removeResizeListener } from '/@/utils/event';
|
import { addResizeListener, removeResizeListener } from '/@/utils/event';
|
||||||
import componentSetting from '/@/settings/componentSetting';
|
import componentSetting from '/@/settings/componentSetting';
|
||||||
const { scrollbar } = componentSetting;
|
const { scrollbar } = componentSetting;
|
||||||
import { toObject } from './util';
|
import { toObject } from './util';
|
||||||
import { defineComponent, ref, onMounted, onBeforeUnmount, nextTick, provide, computed, unref } from 'vue';
|
import { defineComponent, ref, onMounted, onBeforeUnmount, nextTick, provide, computed, unref } from 'vue';
|
||||||
import Bar from './bar';
|
import Bar from './bar';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'Scrollbar',
|
name: 'Scrollbar',
|
||||||
// inheritAttrs: false,
|
// inheritAttrs: false,
|
||||||
components: { Bar },
|
components: { Bar },
|
||||||
props: {
|
props: {
|
||||||
native: {
|
native: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: scrollbar?.native ?? false,
|
default: scrollbar?.native ?? false,
|
||||||
},
|
|
||||||
wrapStyle: {
|
|
||||||
type: [String, Array],
|
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
wrapClass: {
|
|
||||||
type: [String, Array],
|
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
viewClass: {
|
|
||||||
type: [String, Array],
|
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
viewStyle: {
|
|
||||||
type: [String, Array],
|
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
noresize: Boolean, // 如果 container 尺寸不会发生变化,最好设置它可以优化性能
|
|
||||||
tag: {
|
|
||||||
type: String,
|
|
||||||
default: 'div',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
setup(props) {
|
wrapStyle: {
|
||||||
const sizeWidth = ref('0');
|
type: [String, Array],
|
||||||
const sizeHeight = ref('0');
|
default: '',
|
||||||
const moveX = ref(0);
|
|
||||||
const moveY = ref(0);
|
|
||||||
const wrap = ref();
|
|
||||||
const resize = ref();
|
|
||||||
|
|
||||||
provide('scroll-bar-wrap', wrap);
|
|
||||||
|
|
||||||
const style = computed(() => {
|
|
||||||
if (Array.isArray(props.wrapStyle)) {
|
|
||||||
return toObject(props.wrapStyle);
|
|
||||||
}
|
|
||||||
return props.wrapStyle;
|
|
||||||
});
|
|
||||||
|
|
||||||
const handleScroll = () => {
|
|
||||||
if (!props.native) {
|
|
||||||
moveY.value = (unref(wrap).scrollTop * 100) / unref(wrap).clientHeight;
|
|
||||||
moveX.value = (unref(wrap).scrollLeft * 100) / unref(wrap).clientWidth;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const update = () => {
|
|
||||||
if (!unref(wrap)) return;
|
|
||||||
|
|
||||||
const heightPercentage = (unref(wrap).clientHeight * 100) / unref(wrap).scrollHeight;
|
|
||||||
const widthPercentage = (unref(wrap).clientWidth * 100) / unref(wrap).scrollWidth;
|
|
||||||
|
|
||||||
sizeHeight.value = heightPercentage < 100 ? heightPercentage + '%' : '';
|
|
||||||
sizeWidth.value = widthPercentage < 100 ? widthPercentage + '%' : '';
|
|
||||||
};
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
if (props.native) return;
|
|
||||||
nextTick(update);
|
|
||||||
if (!props.noresize) {
|
|
||||||
addResizeListener(unref(resize), update);
|
|
||||||
addResizeListener(unref(wrap), update);
|
|
||||||
addEventListener('resize', update);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
|
||||||
if (props.native) return;
|
|
||||||
if (!props.noresize) {
|
|
||||||
removeResizeListener(unref(resize), update);
|
|
||||||
removeResizeListener(unref(wrap), update);
|
|
||||||
removeEventListener('resize', update);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
moveX,
|
|
||||||
moveY,
|
|
||||||
sizeWidth,
|
|
||||||
sizeHeight,
|
|
||||||
style,
|
|
||||||
wrap,
|
|
||||||
resize,
|
|
||||||
update,
|
|
||||||
handleScroll,
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
});
|
wrapClass: {
|
||||||
|
type: [String, Array],
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
viewClass: {
|
||||||
|
type: [String, Array],
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
viewStyle: {
|
||||||
|
type: [String, Array],
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
noresize: Boolean, // 如果 container 尺寸不会发生变化,最好设置它可以优化性能
|
||||||
|
tag: {
|
||||||
|
type: String,
|
||||||
|
default: 'div',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
setup(props) {
|
||||||
|
const sizeWidth = ref('0');
|
||||||
|
const sizeHeight = ref('0');
|
||||||
|
const moveX = ref(0);
|
||||||
|
const moveY = ref(0);
|
||||||
|
const wrap = ref();
|
||||||
|
const resize = ref();
|
||||||
|
|
||||||
|
provide('scroll-bar-wrap', wrap);
|
||||||
|
|
||||||
|
const style = computed(() => {
|
||||||
|
if (Array.isArray(props.wrapStyle)) {
|
||||||
|
return toObject(props.wrapStyle);
|
||||||
|
}
|
||||||
|
return props.wrapStyle;
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleScroll = () => {
|
||||||
|
if (!props.native) {
|
||||||
|
moveY.value = (unref(wrap).scrollTop * 100) / unref(wrap).clientHeight;
|
||||||
|
moveX.value = (unref(wrap).scrollLeft * 100) / unref(wrap).clientWidth;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const update = () => {
|
||||||
|
if (!unref(wrap)) return;
|
||||||
|
|
||||||
|
const heightPercentage = (unref(wrap).clientHeight * 100) / unref(wrap).scrollHeight;
|
||||||
|
const widthPercentage = (unref(wrap).clientWidth * 100) / unref(wrap).scrollWidth;
|
||||||
|
|
||||||
|
sizeHeight.value = heightPercentage < 100 ? heightPercentage + '%' : '';
|
||||||
|
sizeWidth.value = widthPercentage < 100 ? widthPercentage + '%' : '';
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (props.native) return;
|
||||||
|
nextTick(update);
|
||||||
|
if (!props.noresize) {
|
||||||
|
addResizeListener(unref(resize), update);
|
||||||
|
addResizeListener(unref(wrap), update);
|
||||||
|
addEventListener('resize', update);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
if (props.native) return;
|
||||||
|
if (!props.noresize) {
|
||||||
|
removeResizeListener(unref(resize), update);
|
||||||
|
removeResizeListener(unref(wrap), update);
|
||||||
|
removeEventListener('resize', update);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
moveX,
|
||||||
|
moveY,
|
||||||
|
sizeWidth,
|
||||||
|
sizeHeight,
|
||||||
|
style,
|
||||||
|
wrap,
|
||||||
|
resize,
|
||||||
|
update,
|
||||||
|
handleScroll,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
.scrollbar {
|
.scrollbar {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
&__wrap {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: hidden;
|
overflow: auto;
|
||||||
|
|
||||||
&__wrap {
|
&--hidden-default {
|
||||||
height: 100%;
|
scrollbar-width: none;
|
||||||
overflow: auto;
|
|
||||||
|
|
||||||
&--hidden-default {
|
&::-webkit-scrollbar {
|
||||||
scrollbar-width: none;
|
display: none;
|
||||||
|
width: 0;
|
||||||
&::-webkit-scrollbar {
|
height: 0;
|
||||||
display: none;
|
opacity: 0;
|
||||||
width: 0;
|
|
||||||
height: 0;
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__thumb {
|
|
||||||
position: relative;
|
|
||||||
display: block;
|
|
||||||
width: 0;
|
|
||||||
height: 0;
|
|
||||||
cursor: pointer;
|
|
||||||
background-color: rgba(144, 147, 153, 0.3);
|
|
||||||
border-radius: inherit;
|
|
||||||
transition: 0.3s background-color;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: rgba(144, 147, 153, 0.5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__bar {
|
|
||||||
position: absolute;
|
|
||||||
right: 2px;
|
|
||||||
bottom: 2px;
|
|
||||||
z-index: 1;
|
|
||||||
border-radius: 4px;
|
|
||||||
opacity: 0;
|
|
||||||
-webkit-transition: opacity 80ms ease;
|
|
||||||
transition: opacity 80ms ease;
|
|
||||||
|
|
||||||
&.is-vertical {
|
|
||||||
top: 2px;
|
|
||||||
width: 6px;
|
|
||||||
|
|
||||||
& > div {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.is-horizontal {
|
|
||||||
left: 2px;
|
|
||||||
height: 6px;
|
|
||||||
|
|
||||||
& > div {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.scrollbar:active > .scrollbar__bar,
|
&__thumb {
|
||||||
.scrollbar:focus > .scrollbar__bar,
|
position: relative;
|
||||||
.scrollbar:hover > .scrollbar__bar {
|
display: block;
|
||||||
opacity: 1;
|
width: 0;
|
||||||
transition: opacity 340ms ease-out;
|
height: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: rgba(144, 147, 153, 0.3);
|
||||||
|
border-radius: inherit;
|
||||||
|
transition: 0.3s background-color;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba(144, 147, 153, 0.5);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__bar {
|
||||||
|
position: absolute;
|
||||||
|
right: 2px;
|
||||||
|
bottom: 2px;
|
||||||
|
z-index: 1;
|
||||||
|
border-radius: 4px;
|
||||||
|
opacity: 0;
|
||||||
|
-webkit-transition: opacity 80ms ease;
|
||||||
|
transition: opacity 80ms ease;
|
||||||
|
|
||||||
|
&.is-vertical {
|
||||||
|
top: 2px;
|
||||||
|
width: 6px;
|
||||||
|
|
||||||
|
&>div {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-horizontal {
|
||||||
|
left: 2px;
|
||||||
|
height: 6px;
|
||||||
|
|
||||||
|
&>div {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.scrollbar:active>.scrollbar__bar,
|
||||||
|
.scrollbar:focus>.scrollbar__bar,
|
||||||
|
.scrollbar:hover>.scrollbar__bar {
|
||||||
|
opacity: 1;
|
||||||
|
transition: opacity 340ms ease-out;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -11,12 +11,8 @@
|
||||||
|
|
||||||
<template #overlay>
|
<template #overlay>
|
||||||
<Menu @click="handleMenuClick">
|
<Menu @click="handleMenuClick">
|
||||||
<MenuItem key="doc" :text="t('layout.header.dropdownItemDoc')" icon="ion:document-text-outline" v-if="getShowDoc" />
|
<MenuItem key="password" :text="t('layout.header.dropdownItemSwitchPassword')"
|
||||||
<MenuDivider v-if="getShowDoc" />
|
icon="ant-design:edit-outlined" />
|
||||||
<MenuItem key="account" :text="t('layout.header.dropdownItemSwitchAccount')" icon="ant-design:setting-outlined" />
|
|
||||||
<MenuItem key="password" :text="t('layout.header.dropdownItemSwitchPassword')" icon="ant-design:edit-outlined" />
|
|
||||||
<MenuItem key="depart" :text="t('layout.header.dropdownItemSwitchDepart')" icon="ant-design:cluster-outlined" />
|
|
||||||
<MenuItem key="cache" :text="t('layout.header.dropdownItemRefreshCache')" icon="ion:sync-outline" />
|
|
||||||
<!-- <MenuItem
|
<!-- <MenuItem
|
||||||
v-if="getUseLockPage"
|
v-if="getUseLockPage"
|
||||||
key="lock"
|
key="lock"
|
||||||
|
@ -32,220 +28,221 @@
|
||||||
<UpdatePassword v-if="passwordVisible" ref="updatePasswordRef" />
|
<UpdatePassword v-if="passwordVisible" ref="updatePasswordRef" />
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
// components
|
// components
|
||||||
import { Dropdown, Menu } from 'ant-design-vue';
|
import { Dropdown, Menu } from 'ant-design-vue';
|
||||||
|
|
||||||
import { defineComponent, computed, ref } from 'vue';
|
import { defineComponent, computed, ref } from 'vue';
|
||||||
|
|
||||||
import { SITE_URL } from '/@/settings/siteSetting';
|
import { SITE_URL } from '/@/settings/siteSetting';
|
||||||
|
|
||||||
import { useUserStore } from '/@/store/modules/user';
|
import { useUserStore } from '/@/store/modules/user';
|
||||||
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
|
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
|
||||||
import { useI18n } from '/@/hooks/web/useI18n';
|
import { useI18n } from '/@/hooks/web/useI18n';
|
||||||
import { useDesign } from '/@/hooks/web/useDesign';
|
import { useDesign } from '/@/hooks/web/useDesign';
|
||||||
import { useModal } from '/@/components/Modal';
|
import { useModal } from '/@/components/Modal';
|
||||||
import { useMessage } from '/src/hooks/web/useMessage';
|
import { useMessage } from '/src/hooks/web/useMessage';
|
||||||
import { useGo } from '/@/hooks/web/usePage';
|
import { useGo } from '/@/hooks/web/usePage';
|
||||||
import headerImg from '/@/assets/images/header.jpg';
|
import headerImg from '/@/assets/images/header.jpg';
|
||||||
import { propTypes } from '/@/utils/propTypes';
|
import { propTypes } from '/@/utils/propTypes';
|
||||||
import { openWindow } from '/@/utils';
|
import { openWindow } from '/@/utils';
|
||||||
|
|
||||||
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
|
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
|
||||||
|
|
||||||
import { refreshCache, queryAllDictItems } from '/@/views/system/dict/dict.api';
|
import { refreshCache, queryAllDictItems } from '/@/views/system/dict/dict.api';
|
||||||
import { DB_DICT_DATA_KEY } from '/src/enums/cacheEnum';
|
import { DB_DICT_DATA_KEY } from '/src/enums/cacheEnum';
|
||||||
import { removeAuthCache, setAuthCache } from '/src/utils/auth';
|
import { removeAuthCache, setAuthCache } from '/src/utils/auth';
|
||||||
import { getFileAccessHttpUrl } from '/@/utils/common/compUtils';
|
import { getFileAccessHttpUrl } from '/@/utils/common/compUtils';
|
||||||
import { getRefPromise } from '/@/utils/index';
|
import { getRefPromise } from '/@/utils/index';
|
||||||
|
|
||||||
type MenuEvent = 'logout' | 'doc' | 'lock' | 'cache' | 'depart';
|
type MenuEvent = 'logout' | 'doc' | 'lock' | 'cache' | 'depart';
|
||||||
const { createMessage } = useMessage();
|
const { createMessage } = useMessage();
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'UserDropdown',
|
name: 'UserDropdown',
|
||||||
components: {
|
components: {
|
||||||
Dropdown,
|
Dropdown,
|
||||||
Menu,
|
Menu,
|
||||||
MenuItem: createAsyncComponent(() => import('./DropMenuItem.vue')),
|
MenuItem: createAsyncComponent(() => import('./DropMenuItem.vue')),
|
||||||
MenuDivider: Menu.Divider,
|
MenuDivider: Menu.Divider,
|
||||||
LockAction: createAsyncComponent(() => import('../lock/LockModal.vue')),
|
LockAction: createAsyncComponent(() => import('../lock/LockModal.vue')),
|
||||||
DepartSelect: createAsyncComponent(() => import('./DepartSelect.vue')),
|
DepartSelect: createAsyncComponent(() => import('./DepartSelect.vue')),
|
||||||
UpdatePassword: createAsyncComponent(() => import('./UpdatePassword.vue')),
|
UpdatePassword: createAsyncComponent(() => import('./UpdatePassword.vue')),
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
theme: propTypes.oneOf(['dark', 'light']),
|
theme: propTypes.oneOf(['dark', 'light']),
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
const { prefixCls } = useDesign('header-user-dropdown');
|
const { prefixCls } = useDesign('header-user-dropdown');
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { getShowDoc, getUseLockPage } = useHeaderSetting();
|
const { getShowDoc, getUseLockPage } = useHeaderSetting();
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
const go = useGo();
|
const go = useGo();
|
||||||
const passwordVisible = ref(false);
|
const passwordVisible = ref(false);
|
||||||
const lockActionVisible = ref(false);
|
const lockActionVisible = ref(false);
|
||||||
const lockActionRef = ref(null);
|
const lockActionRef = ref(null);
|
||||||
|
|
||||||
const getUserInfo = computed(() => {
|
const getUserInfo = computed(() => {
|
||||||
const { realname = '', avatar, desc } = userStore.getUserInfo || {};
|
const { realname = '', avatar, desc } = userStore.getUserInfo || {};
|
||||||
return { realname, avatar: avatar || headerImg, desc };
|
return { realname, avatar: avatar || headerImg, desc };
|
||||||
});
|
});
|
||||||
|
|
||||||
const getAvatarUrl = computed(() => {
|
const getAvatarUrl = computed(() => {
|
||||||
let { avatar } = getUserInfo.value;
|
let { avatar } = getUserInfo.value;
|
||||||
if (avatar == headerImg) {
|
if (avatar == headerImg) {
|
||||||
return avatar;
|
return avatar;
|
||||||
} else {
|
} else {
|
||||||
return getFileAccessHttpUrl(avatar);
|
return getFileAccessHttpUrl(avatar);
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const [register, { openModal }] = useModal();
|
|
||||||
/**
|
|
||||||
* 多部门弹窗逻辑
|
|
||||||
*/
|
|
||||||
const loginSelectRef = ref();
|
|
||||||
// update-begin--author:liaozhiyang---date:20230901---for:【QQYUN-6333】空路由问题—首次访问资源太大
|
|
||||||
async function handleLock() {
|
|
||||||
await getRefPromise(lockActionRef);
|
|
||||||
openModal(true);
|
|
||||||
}
|
|
||||||
// update-end--author:liaozhiyang---date:20230901---for:【QQYUN-6333】空路由问题—首次访问资源太大
|
|
||||||
// login out
|
|
||||||
function handleLoginOut() {
|
|
||||||
userStore.confirmLoginOut();
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// open doc
|
const [register, { openModal }] = useModal();
|
||||||
function openDoc() {
|
/**
|
||||||
openWindow(SITE_URL);
|
* 多部门弹窗逻辑
|
||||||
}
|
*/
|
||||||
|
const loginSelectRef = ref();
|
||||||
|
// update-begin--author:liaozhiyang---date:20230901---for:【QQYUN-6333】空路由问题—首次访问资源太大
|
||||||
|
async function handleLock() {
|
||||||
|
await getRefPromise(lockActionRef);
|
||||||
|
openModal(true);
|
||||||
|
}
|
||||||
|
// update-end--author:liaozhiyang---date:20230901---for:【QQYUN-6333】空路由问题—首次访问资源太大
|
||||||
|
// login out
|
||||||
|
function handleLoginOut() {
|
||||||
|
userStore.confirmLoginOut();
|
||||||
|
}
|
||||||
|
|
||||||
// 清除缓存
|
// open doc
|
||||||
async function clearCache() {
|
function openDoc() {
|
||||||
const result = await refreshCache();
|
openWindow(SITE_URL);
|
||||||
if (result.success) {
|
}
|
||||||
const res = await queryAllDictItems();
|
|
||||||
removeAuthCache(DB_DICT_DATA_KEY);
|
|
||||||
setAuthCache(DB_DICT_DATA_KEY, res.result);
|
|
||||||
// update-begin--author:liaozhiyang---date:20240124---for:【QQYUN-7970】国际化
|
|
||||||
createMessage.success(t('layout.header.refreshCacheComplete'));
|
|
||||||
// update-end--author:liaozhiyang---date:20240124---for:【QQYUN-7970】国际化
|
|
||||||
} else {
|
|
||||||
// update-begin--author:liaozhiyang---date:20240124---for:【QQYUN-7970】国际化
|
|
||||||
createMessage.error(t('layout.header.refreshCacheFailure'));
|
|
||||||
// update-end--author:liaozhiyang---date:20240124---for:【QQYUN-7970】国际化
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 切换部门
|
|
||||||
function updateCurrentDepart() {
|
|
||||||
loginSelectRef.value.show();
|
|
||||||
}
|
|
||||||
// 修改密码
|
|
||||||
const updatePasswordRef = ref();
|
|
||||||
// update-begin--author:liaozhiyang---date:20230901---for:【QQYUN-6333】空路由问题—首次访问资源太大
|
|
||||||
async function updatePassword() {
|
|
||||||
passwordVisible.value = true;
|
|
||||||
await getRefPromise(updatePasswordRef);
|
|
||||||
updatePasswordRef.value.show(userStore.getUserInfo.username);
|
|
||||||
}
|
|
||||||
// update-end--author:liaozhiyang---date:20230901---for:【QQYUN-6333】空路由问题—首次访问资源太大
|
|
||||||
function handleMenuClick(e: { key: MenuEvent }) {
|
|
||||||
switch (e.key) {
|
|
||||||
case 'logout':
|
|
||||||
handleLoginOut();
|
|
||||||
break;
|
|
||||||
case 'doc':
|
|
||||||
openDoc();
|
|
||||||
break;
|
|
||||||
case 'lock':
|
|
||||||
handleLock();
|
|
||||||
break;
|
|
||||||
case 'cache':
|
|
||||||
clearCache();
|
|
||||||
break;
|
|
||||||
case 'depart':
|
|
||||||
updateCurrentDepart();
|
|
||||||
break;
|
|
||||||
case 'password':
|
|
||||||
updatePassword();
|
|
||||||
break;
|
|
||||||
case 'account':
|
|
||||||
//update-begin---author:wangshuai ---date:20221125 for:进入用户设置页面------------
|
|
||||||
go(`/system/usersetting`);
|
|
||||||
//update-end---author:wangshuai ---date:20221125 for:进入用户设置页面--------------
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
// 清除缓存
|
||||||
prefixCls,
|
async function clearCache() {
|
||||||
t,
|
const result = await refreshCache();
|
||||||
getUserInfo,
|
if (result.success) {
|
||||||
getAvatarUrl,
|
const res = await queryAllDictItems();
|
||||||
handleMenuClick,
|
removeAuthCache(DB_DICT_DATA_KEY);
|
||||||
getShowDoc,
|
setAuthCache(DB_DICT_DATA_KEY, res.result);
|
||||||
register,
|
// update-begin--author:liaozhiyang---date:20240124---for:【QQYUN-7970】国际化
|
||||||
getUseLockPage,
|
createMessage.success(t('layout.header.refreshCacheComplete'));
|
||||||
loginSelectRef,
|
// update-end--author:liaozhiyang---date:20240124---for:【QQYUN-7970】国际化
|
||||||
updatePasswordRef,
|
} else {
|
||||||
passwordVisible,
|
// update-begin--author:liaozhiyang---date:20240124---for:【QQYUN-7970】国际化
|
||||||
lockActionVisible,
|
createMessage.error(t('layout.header.refreshCacheFailure'));
|
||||||
};
|
// update-end--author:liaozhiyang---date:20240124---for:【QQYUN-7970】国际化
|
||||||
},
|
}
|
||||||
});
|
}
|
||||||
|
// 切换部门
|
||||||
|
function updateCurrentDepart() {
|
||||||
|
loginSelectRef.value.show();
|
||||||
|
}
|
||||||
|
// 修改密码
|
||||||
|
const updatePasswordRef = ref();
|
||||||
|
// update-begin--author:liaozhiyang---date:20230901---for:【QQYUN-6333】空路由问题—首次访问资源太大
|
||||||
|
async function updatePassword() {
|
||||||
|
passwordVisible.value = true;
|
||||||
|
await getRefPromise(updatePasswordRef);
|
||||||
|
updatePasswordRef.value.show(userStore.getUserInfo.username);
|
||||||
|
}
|
||||||
|
// update-end--author:liaozhiyang---date:20230901---for:【QQYUN-6333】空路由问题—首次访问资源太大
|
||||||
|
function handleMenuClick(e: { key: MenuEvent }) {
|
||||||
|
switch (e.key) {
|
||||||
|
case 'logout':
|
||||||
|
handleLoginOut();
|
||||||
|
break;
|
||||||
|
case 'doc':
|
||||||
|
openDoc();
|
||||||
|
break;
|
||||||
|
case 'lock':
|
||||||
|
handleLock();
|
||||||
|
break;
|
||||||
|
case 'cache':
|
||||||
|
clearCache();
|
||||||
|
break;
|
||||||
|
case 'depart':
|
||||||
|
updateCurrentDepart();
|
||||||
|
break;
|
||||||
|
case 'password':
|
||||||
|
updatePassword();
|
||||||
|
break;
|
||||||
|
case 'account':
|
||||||
|
//update-begin---author:wangshuai ---date:20221125 for:进入用户设置页面------------
|
||||||
|
go(`/system/usersetting`);
|
||||||
|
//update-end---author:wangshuai ---date:20221125 for:进入用户设置页面--------------
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
prefixCls,
|
||||||
|
t,
|
||||||
|
getUserInfo,
|
||||||
|
getAvatarUrl,
|
||||||
|
handleMenuClick,
|
||||||
|
getShowDoc,
|
||||||
|
register,
|
||||||
|
getUseLockPage,
|
||||||
|
loginSelectRef,
|
||||||
|
updatePasswordRef,
|
||||||
|
passwordVisible,
|
||||||
|
lockActionVisible,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
@prefix-cls: ~'@{namespace}-header-user-dropdown';
|
@prefix-cls: ~'@{namespace}-header-user-dropdown';
|
||||||
|
|
||||||
.@{prefix-cls} {
|
.@{prefix-cls} {
|
||||||
height: @header-height;
|
height: @header-height;
|
||||||
padding: 0 0 0 10px;
|
padding: 0 0 0 10px;
|
||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
img {
|
img {
|
||||||
width: 24px;
|
width: 24px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
margin-right: 12px;
|
margin-right: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__header {
|
&__header {
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__name {
|
&__name {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&--dark {
|
&--dark {
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: @header-dark-bg-hover-color;
|
background-color: @header-dark-bg-hover-color;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&--light {
|
|
||||||
&:hover {
|
|
||||||
background-color: @header-light-bg-hover-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
.@{prefix-cls}__name {
|
|
||||||
color: @text-color-base;
|
|
||||||
}
|
|
||||||
|
|
||||||
.@{prefix-cls}__desc {
|
|
||||||
color: @header-light-desc-color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&-dropdown-overlay {
|
|
||||||
// update-begin--author:liaozhiyang---date:20231226---for:【QQYUN-7512】顶部账号划过首次弹出时位置会变更一下
|
|
||||||
width: 160px;
|
|
||||||
// update-end--author:liaozhiyang---date:20231226---for:【QQYUN-7512】顶部账号划过首次弹出时位置会变更一下
|
|
||||||
.ant-dropdown-menu-item {
|
|
||||||
min-width: 160px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&--light {
|
||||||
|
&:hover {
|
||||||
|
background-color: @header-light-bg-hover-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.@{prefix-cls}__name {
|
||||||
|
color: @text-color-base;
|
||||||
|
}
|
||||||
|
|
||||||
|
.@{prefix-cls}__desc {
|
||||||
|
color: @header-light-desc-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-dropdown-overlay {
|
||||||
|
// update-begin--author:liaozhiyang---date:20231226---for:【QQYUN-7512】顶部账号划过首次弹出时位置会变更一下
|
||||||
|
width: 160px;
|
||||||
|
|
||||||
|
// update-end--author:liaozhiyang---date:20231226---for:【QQYUN-7512】顶部账号划过首次弹出时位置会变更一下
|
||||||
|
.ant-dropdown-menu-item {
|
||||||
|
min-width: 160px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -3,15 +3,11 @@
|
||||||
<!-- left start -->
|
<!-- left start -->
|
||||||
<div :class="`${prefixCls}-left`">
|
<div :class="`${prefixCls}-left`">
|
||||||
<!-- logo -->
|
<!-- logo -->
|
||||||
<AppLogo v-if="getShowHeaderLogo || getIsMobile" :class="`${prefixCls}-logo`" :theme="getHeaderTheme" :style="getLogoWidth" />
|
<AppLogo v-if="getShowHeaderLogo || getIsMobile" :class="`${prefixCls}-logo`" :theme="getHeaderTheme"
|
||||||
<LayoutTrigger
|
:style="getLogoWidth" />
|
||||||
v-if="(getShowContent && getShowHeaderTrigger && !getSplit && !getIsMixSidebar) || getIsMobile"
|
<LayoutTrigger v-if="(getShowContent && getShowHeaderTrigger && !getSplit && !getIsMixSidebar) || getIsMobile"
|
||||||
:theme="getHeaderTheme"
|
:theme="getHeaderTheme" :sider="false" />
|
||||||
:sider="false"
|
|
||||||
/>
|
|
||||||
<LayoutBreadcrumb v-if="getShowContent && getShowBread" :theme="getHeaderTheme" />
|
<LayoutBreadcrumb v-if="getShowContent && getShowBread" :theme="getHeaderTheme" />
|
||||||
<!-- 欢迎语 -->
|
|
||||||
<span v-if="getShowContent && getShowBreadTitle && !getIsMobile" :class="[prefixCls, `${prefixCls}--${getHeaderTheme}`,'headerIntroductionClass']"> {{t('layout.header.welcomeIn')}} {{ title }} </span>
|
|
||||||
</div>
|
</div>
|
||||||
<!-- left end -->
|
<!-- left end -->
|
||||||
|
|
||||||
|
@ -23,236 +19,228 @@
|
||||||
|
|
||||||
<!-- action -->
|
<!-- action -->
|
||||||
<div :class="`${prefixCls}-action`">
|
<div :class="`${prefixCls}-action`">
|
||||||
<AppSearch :class="`${prefixCls}-action__item `" v-if="getShowSearch" />
|
|
||||||
|
|
||||||
<ErrorAction v-if="getUseErrorHandle" :class="`${prefixCls}-action__item error-action`" />
|
<ErrorAction v-if="getUseErrorHandle" :class="`${prefixCls}-action__item error-action`" />
|
||||||
|
|
||||||
<Notify v-if="getShowNotice" :class="`${prefixCls}-action__item notify-item`" />
|
|
||||||
|
|
||||||
<FullScreen v-if="getShowFullScreen" :class="`${prefixCls}-action__item fullscreen-item`" />
|
<FullScreen v-if="getShowFullScreen" :class="`${prefixCls}-action__item fullscreen-item`" />
|
||||||
|
|
||||||
<LockScreen v-if="getUseLockPage" />
|
|
||||||
|
|
||||||
<AppLocalePicker v-if="getShowLocalePicker" :reload="true" :showText="false" :class="`${prefixCls}-action__item`" />
|
|
||||||
|
|
||||||
<UserDropDown :theme="getHeaderTheme" />
|
<UserDropDown :theme="getHeaderTheme" />
|
||||||
|
|
||||||
<SettingDrawer v-if="getShowSetting" :class="`${prefixCls}-action__item`" />
|
<SettingDrawer v-if="getShowSetting" :class="`${prefixCls}-action__item`" />
|
||||||
<!-- ai助手 -->
|
|
||||||
<Aide></Aide>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</Header>
|
</Header>
|
||||||
<LoginSelect ref="loginSelectRef" @success="loginSelectOk"></LoginSelect>
|
<LoginSelect ref="loginSelectRef" @success="loginSelectOk"></LoginSelect>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, unref, computed, ref, onMounted, toRaw } from 'vue';
|
import { defineComponent, unref, computed, ref, onMounted, toRaw } from 'vue';
|
||||||
import { useGlobSetting } from '/@/hooks/setting';
|
import { useGlobSetting } from '/@/hooks/setting';
|
||||||
import { propTypes } from '/@/utils/propTypes';
|
import { propTypes } from '/@/utils/propTypes';
|
||||||
|
|
||||||
import { Layout } from 'ant-design-vue';
|
import { Layout } from 'ant-design-vue';
|
||||||
import { AppLogo } from '/@/components/Application';
|
import { AppLogo } from '/@/components/Application';
|
||||||
import LayoutMenu from '../menu/index.vue';
|
import LayoutMenu from '../menu/index.vue';
|
||||||
import LayoutTrigger from '../trigger/index.vue';
|
import LayoutTrigger from '../trigger/index.vue';
|
||||||
|
|
||||||
import { AppSearch } from '/@/components/Application';
|
import { AppSearch } from '/@/components/Application';
|
||||||
|
|
||||||
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
|
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
|
||||||
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
||||||
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
|
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
|
||||||
|
|
||||||
import { MenuModeEnum, MenuSplitTyeEnum } from '/@/enums/menuEnum';
|
import { MenuModeEnum, MenuSplitTyeEnum } from '/@/enums/menuEnum';
|
||||||
import { SettingButtonPositionEnum } from '/@/enums/appEnum';
|
import { SettingButtonPositionEnum } from '/@/enums/appEnum';
|
||||||
import { AppLocalePicker } from '/@/components/Application';
|
import { AppLocalePicker } from '/@/components/Application';
|
||||||
|
|
||||||
import { UserDropDown, LayoutBreadcrumb, FullScreen, Notify, ErrorAction, LockScreen } from './components';
|
import { UserDropDown, LayoutBreadcrumb, FullScreen, Notify, ErrorAction, LockScreen } from './components';
|
||||||
import { useAppInject } from '/@/hooks/web/useAppInject';
|
import { useAppInject } from '/@/hooks/web/useAppInject';
|
||||||
import { useDesign } from '/@/hooks/web/useDesign';
|
import { useDesign } from '/@/hooks/web/useDesign';
|
||||||
|
|
||||||
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
|
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
|
||||||
import { useLocale } from '/@/locales/useLocale';
|
import { useLocale } from '/@/locales/useLocale';
|
||||||
|
|
||||||
import LoginSelect from '/@/views/sys/login/LoginSelect.vue';
|
import LoginSelect from '/@/views/sys/login/LoginSelect.vue';
|
||||||
import { useUserStore } from '/@/store/modules/user';
|
import { useUserStore } from '/@/store/modules/user';
|
||||||
import { useI18n } from '/@/hooks/web/useI18n';
|
import { useI18n } from '/@/hooks/web/useI18n';
|
||||||
import Aide from "@/views/dashboard/ai/components/aide/index.vue"
|
import Aide from "@/views/dashboard/ai/components/aide/index.vue"
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'LayoutHeader',
|
name: 'LayoutHeader',
|
||||||
components: {
|
components: {
|
||||||
Header: Layout.Header,
|
Header: Layout.Header,
|
||||||
AppLogo,
|
AppLogo,
|
||||||
LayoutTrigger,
|
LayoutTrigger,
|
||||||
LayoutBreadcrumb,
|
LayoutBreadcrumb,
|
||||||
LayoutMenu,
|
LayoutMenu,
|
||||||
UserDropDown,
|
UserDropDown,
|
||||||
AppLocalePicker,
|
AppLocalePicker,
|
||||||
FullScreen,
|
FullScreen,
|
||||||
Notify,
|
Notify,
|
||||||
AppSearch,
|
AppSearch,
|
||||||
ErrorAction,
|
ErrorAction,
|
||||||
LockScreen,
|
LockScreen,
|
||||||
LoginSelect,
|
LoginSelect,
|
||||||
SettingDrawer: createAsyncComponent(() => import('/@/layouts/default/setting/index.vue'), {
|
SettingDrawer: createAsyncComponent(() => import('/@/layouts/default/setting/index.vue'), {
|
||||||
loading: true,
|
loading: true,
|
||||||
}),
|
}),
|
||||||
Aide
|
Aide
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
fixed: propTypes.bool,
|
fixed: propTypes.bool,
|
||||||
},
|
},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const { prefixCls } = useDesign('layout-header');
|
const { prefixCls } = useDesign('layout-header');
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
const { getShowTopMenu, getShowHeaderTrigger, getSplit, getIsMixMode, getMenuWidth, getIsMixSidebar } = useMenuSetting();
|
const { getShowTopMenu, getShowHeaderTrigger, getSplit, getIsMixMode, getMenuWidth, getIsMixSidebar } = useMenuSetting();
|
||||||
const { getUseErrorHandle, getShowSettingButton, getSettingButtonPosition } = useRootSetting();
|
const { getUseErrorHandle, getShowSettingButton, getSettingButtonPosition } = useRootSetting();
|
||||||
const { title } = useGlobSetting();
|
const { title } = useGlobSetting();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
getHeaderTheme,
|
getHeaderTheme,
|
||||||
getShowFullScreen,
|
getShowFullScreen,
|
||||||
getShowNotice,
|
getShowNotice,
|
||||||
getShowContent,
|
getShowContent,
|
||||||
getShowBread,
|
getShowBread,
|
||||||
getShowHeaderLogo,
|
getShowHeaderLogo,
|
||||||
getShowHeader,
|
getShowHeader,
|
||||||
getShowSearch,
|
getShowSearch,
|
||||||
getUseLockPage,
|
getUseLockPage,
|
||||||
getShowBreadTitle,
|
getShowBreadTitle,
|
||||||
} = useHeaderSetting();
|
} = useHeaderSetting();
|
||||||
|
|
||||||
const { getShowLocalePicker } = useLocale();
|
const { getShowLocalePicker } = useLocale();
|
||||||
|
|
||||||
const { getIsMobile } = useAppInject();
|
const { getIsMobile } = useAppInject();
|
||||||
|
|
||||||
const getHeaderClass = computed(() => {
|
const getHeaderClass = computed(() => {
|
||||||
const theme = unref(getHeaderTheme);
|
const theme = unref(getHeaderTheme);
|
||||||
return [
|
return [
|
||||||
prefixCls,
|
|
||||||
{
|
|
||||||
[`${prefixCls}--fixed`]: props.fixed,
|
|
||||||
[`${prefixCls}--mobile`]: unref(getIsMobile),
|
|
||||||
[`${prefixCls}--${theme}`]: theme,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
});
|
|
||||||
|
|
||||||
const getShowSetting = computed(() => {
|
|
||||||
if (!unref(getShowSettingButton)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const settingButtonPosition = unref(getSettingButtonPosition);
|
|
||||||
|
|
||||||
if (settingButtonPosition === SettingButtonPositionEnum.AUTO) {
|
|
||||||
return unref(getShowHeader);
|
|
||||||
}
|
|
||||||
return settingButtonPosition === SettingButtonPositionEnum.HEADER;
|
|
||||||
});
|
|
||||||
|
|
||||||
const getLogoWidth = computed(() => {
|
|
||||||
if (!unref(getIsMixMode) || unref(getIsMobile)) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
const width = unref(getMenuWidth) < 180 ? 180 : unref(getMenuWidth);
|
|
||||||
return { width: `${width}px` };
|
|
||||||
});
|
|
||||||
|
|
||||||
const getSplitType = computed(() => {
|
|
||||||
return unref(getSplit) ? MenuSplitTyeEnum.TOP : MenuSplitTyeEnum.NONE;
|
|
||||||
});
|
|
||||||
|
|
||||||
const getMenuMode = computed(() => {
|
|
||||||
return unref(getSplit) ? MenuModeEnum.HORIZONTAL : null;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 首页多租户部门弹窗逻辑
|
|
||||||
*/
|
|
||||||
const loginSelectRef = ref();
|
|
||||||
|
|
||||||
function showLoginSelect() {
|
|
||||||
//update-begin---author:liusq Date:20220101 for:判断登录进来是否需要弹窗选择租户----
|
|
||||||
//判断是否是登陆进来
|
|
||||||
const loginInfo = toRaw(userStore.getLoginInfo) || {};
|
|
||||||
if (!!loginInfo.isLogin) {
|
|
||||||
loginSelectRef.value.show(loginInfo);
|
|
||||||
}
|
|
||||||
//update-end---author:liusq Date:20220101 for:判断登录进来是否需要弹窗选择租户----
|
|
||||||
}
|
|
||||||
|
|
||||||
function loginSelectOk() {
|
|
||||||
console.log('成功。。。。。');
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
showLoginSelect();
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
prefixCls,
|
prefixCls,
|
||||||
getHeaderClass,
|
{
|
||||||
getShowHeaderLogo,
|
[`${prefixCls}--fixed`]: props.fixed,
|
||||||
getHeaderTheme,
|
[`${prefixCls}--mobile`]: unref(getIsMobile),
|
||||||
getShowHeaderTrigger,
|
[`${prefixCls}--${theme}`]: theme,
|
||||||
getIsMobile,
|
},
|
||||||
getShowBreadTitle,
|
];
|
||||||
getShowBread,
|
});
|
||||||
getShowContent,
|
|
||||||
getSplitType,
|
const getShowSetting = computed(() => {
|
||||||
getSplit,
|
if (!unref(getShowSettingButton)) {
|
||||||
getMenuMode,
|
return false;
|
||||||
getShowTopMenu,
|
}
|
||||||
getShowLocalePicker,
|
const settingButtonPosition = unref(getSettingButtonPosition);
|
||||||
getShowFullScreen,
|
|
||||||
getShowNotice,
|
if (settingButtonPosition === SettingButtonPositionEnum.AUTO) {
|
||||||
getUseErrorHandle,
|
return unref(getShowHeader);
|
||||||
getLogoWidth,
|
}
|
||||||
getIsMixSidebar,
|
return settingButtonPosition === SettingButtonPositionEnum.HEADER;
|
||||||
getShowSettingButton,
|
});
|
||||||
getShowSetting,
|
|
||||||
getShowSearch,
|
const getLogoWidth = computed(() => {
|
||||||
getUseLockPage,
|
if (!unref(getIsMixMode) || unref(getIsMobile)) {
|
||||||
loginSelectOk,
|
return {};
|
||||||
loginSelectRef,
|
}
|
||||||
title,
|
const width = unref(getMenuWidth) < 180 ? 180 : unref(getMenuWidth);
|
||||||
t
|
return { width: `${width}px` };
|
||||||
};
|
});
|
||||||
},
|
|
||||||
});
|
const getSplitType = computed(() => {
|
||||||
|
return unref(getSplit) ? MenuSplitTyeEnum.TOP : MenuSplitTyeEnum.NONE;
|
||||||
|
});
|
||||||
|
|
||||||
|
const getMenuMode = computed(() => {
|
||||||
|
return unref(getSplit) ? MenuModeEnum.HORIZONTAL : null;
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 首页多租户部门弹窗逻辑
|
||||||
|
*/
|
||||||
|
const loginSelectRef = ref();
|
||||||
|
|
||||||
|
function showLoginSelect() {
|
||||||
|
//update-begin---author:liusq Date:20220101 for:判断登录进来是否需要弹窗选择租户----
|
||||||
|
//判断是否是登陆进来
|
||||||
|
const loginInfo = toRaw(userStore.getLoginInfo) || {};
|
||||||
|
if (!!loginInfo.isLogin) {
|
||||||
|
loginSelectRef.value.show(loginInfo);
|
||||||
|
}
|
||||||
|
//update-end---author:liusq Date:20220101 for:判断登录进来是否需要弹窗选择租户----
|
||||||
|
}
|
||||||
|
|
||||||
|
function loginSelectOk() {
|
||||||
|
console.log('成功。。。。。');
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
showLoginSelect();
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
prefixCls,
|
||||||
|
getHeaderClass,
|
||||||
|
getShowHeaderLogo,
|
||||||
|
getHeaderTheme,
|
||||||
|
getShowHeaderTrigger,
|
||||||
|
getIsMobile,
|
||||||
|
getShowBreadTitle,
|
||||||
|
getShowBread,
|
||||||
|
getShowContent,
|
||||||
|
getSplitType,
|
||||||
|
getSplit,
|
||||||
|
getMenuMode,
|
||||||
|
getShowTopMenu,
|
||||||
|
getShowLocalePicker,
|
||||||
|
getShowFullScreen,
|
||||||
|
getShowNotice,
|
||||||
|
getUseErrorHandle,
|
||||||
|
getLogoWidth,
|
||||||
|
getIsMixSidebar,
|
||||||
|
getShowSettingButton,
|
||||||
|
getShowSetting,
|
||||||
|
getShowSearch,
|
||||||
|
getUseLockPage,
|
||||||
|
loginSelectOk,
|
||||||
|
loginSelectRef,
|
||||||
|
title,
|
||||||
|
t
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
@import './index.less';
|
@import './index.less';
|
||||||
//update-begin---author:scott ---date:2022-09-30 for:默认隐藏顶部菜单面包屑-----------
|
//update-begin---author:scott ---date:2022-09-30 for:默认隐藏顶部菜单面包屑-----------
|
||||||
//顶部欢迎语展示样式
|
//顶部欢迎语展示样式
|
||||||
@prefix-cls: ~'@{namespace}-layout-header';
|
@prefix-cls: ~'@{namespace}-layout-header';
|
||||||
|
|
||||||
.ant-layout .@{prefix-cls} {
|
.ant-layout .@{prefix-cls} {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
height: 48px;
|
height: 48px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
.headerIntroductionClass {
|
.headerIntroductionClass {
|
||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
margin-bottom: 2px;
|
margin-bottom: 2px;
|
||||||
border-bottom: 0px;
|
border-bottom: 0px;
|
||||||
border-left: 0px;
|
border-left: 0px;
|
||||||
}
|
|
||||||
|
|
||||||
&--light {
|
|
||||||
.headerIntroductionClass {
|
|
||||||
color: @breadcrumb-item-normal-color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&--dark {
|
|
||||||
.headerIntroductionClass {
|
|
||||||
color: rgba(255, 255, 255, 0.6);
|
|
||||||
}
|
|
||||||
.anticon, .truncate {
|
|
||||||
color: rgba(255, 255, 255, 0.8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//update-end---author:scott ---date::2022-09-30 for:默认隐藏顶部菜单面包屑--------------
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&--light {
|
||||||
|
.headerIntroductionClass {
|
||||||
|
color: @breadcrumb-item-normal-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--dark {
|
||||||
|
.headerIntroductionClass {
|
||||||
|
color: rgba(255, 255, 255, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.anticon,
|
||||||
|
.truncate {
|
||||||
|
color: rgba(255, 255, 255, 0.8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//update-end---author:scott ---date::2022-09-30 for:默认隐藏顶部菜单面包屑--------------
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -65,13 +65,13 @@ const setting: ProjectConfig = {
|
||||||
// 头部配置
|
// 头部配置
|
||||||
headerSetting: {
|
headerSetting: {
|
||||||
// 背景色
|
// 背景色
|
||||||
bgColor: HEADER_PRESET_BG_COLOR_LIST[0],
|
bgColor: HEADER_PRESET_BG_COLOR_LIST[5],
|
||||||
// 固定头部
|
// 固定头部
|
||||||
fixed: true,
|
fixed: true,
|
||||||
// 是否显示顶部
|
// 是否显示顶部
|
||||||
show: true,
|
show: true,
|
||||||
// 主题
|
// 主题
|
||||||
theme: ThemeEnum.LIGHT,
|
theme: ThemeEnum.DARK,
|
||||||
// 开启锁屏功能
|
// 开启锁屏功能
|
||||||
useLockPage: true,
|
useLockPage: true,
|
||||||
// 显示全屏按钮
|
// 显示全屏按钮
|
||||||
|
@ -87,7 +87,7 @@ const setting: ProjectConfig = {
|
||||||
// 菜单配置
|
// 菜单配置
|
||||||
menuSetting: {
|
menuSetting: {
|
||||||
// 背景色
|
// 背景色
|
||||||
bgColor: SIDE_BAR_BG_COLOR_LIST[0],
|
bgColor: SIDE_BAR_BG_COLOR_LIST[3],
|
||||||
// 是否固定住左侧菜单
|
// 是否固定住左侧菜单
|
||||||
fixed: true,
|
fixed: true,
|
||||||
// 菜单折叠
|
// 菜单折叠
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<h1>学生信息</h1>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style></style>
|
|
|
@ -1,5 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<IndexDef v-if="indexStyle === 0"></IndexDef>
|
<div class="mod-home">
|
||||||
|
<h3>欢迎使用评阅人员管理系统</h3>
|
||||||
|
</div>
|
||||||
|
<!--<IndexDef v-if="indexStyle === 0"></IndexDef>
|
||||||
<IndexChart v-if="indexStyle === 1"></IndexChart>
|
<IndexChart v-if="indexStyle === 1"></IndexChart>
|
||||||
<IndexBdc v-if="indexStyle == 2"></IndexBdc>
|
<IndexBdc v-if="indexStyle == 2"></IndexBdc>
|
||||||
<IndexTask v-if="indexStyle == 3"></IndexTask>
|
<IndexTask v-if="indexStyle == 3"></IndexTask>
|
||||||
|
@ -11,14 +14,20 @@
|
||||||
<a-radio :value="2">业务统计</a-radio>
|
<a-radio :value="2">业务统计</a-radio>
|
||||||
<a-radio :value="3">我的任务</a-radio>
|
<a-radio :value="3">我的任务</a-radio>
|
||||||
</a-radio-group>
|
</a-radio-group>
|
||||||
</div>
|
</div>-->
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from 'vue';
|
//import { ref } from 'vue';
|
||||||
import IndexDef from './homePage/IndexDef.vue';
|
//import IndexDef from './homePage/IndexDef.vue';
|
||||||
import IndexChart from './homePage/IndexChart.vue';
|
//import IndexChart from './homePage/IndexChart.vue';
|
||||||
import IndexBdc from './homePage/IndexBdc.vue';
|
//import IndexBdc from './homePage/IndexBdc.vue';
|
||||||
import IndexTask from './homePage/IndexTask.vue';
|
//import IndexTask from './homePage/IndexTask.vue';
|
||||||
|
|
||||||
const indexStyle = ref(0);
|
//const indexStyle = ref(0);
|
||||||
</script>
|
</script>
|
||||||
|
<style>
|
||||||
|
.mod-home {
|
||||||
|
line-height: 2.5;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -1,29 +1,30 @@
|
||||||
<template>
|
<template>
|
||||||
<LoginFormTitle v-show="getShow" class="enter-x" />
|
<LoginFormTitle v-show="getShow" class="enter-x" />
|
||||||
<Form class="p-4 enter-x" :model="formData" :rules="getFormRules" ref="formRef" v-show="getShow" @keypress.enter="handleLogin">
|
<Form class="p-4 enter-x" :model="formData" :rules="getFormRules" ref="formRef" v-show="getShow"
|
||||||
|
@keypress.enter="handleLogin">
|
||||||
<FormItem name="account" class="enter-x">
|
<FormItem name="account" class="enter-x">
|
||||||
<Input size="large" v-model:value="formData.account" :placeholder="t('sys.login.userName')" class="fix-auto-fill" />
|
<Input size="large" v-model:value="formData.account" :placeholder="t('sys.login.userName')"
|
||||||
|
class="fix-auto-fill" />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
<FormItem name="password" class="enter-x">
|
<FormItem name="password" class="enter-x">
|
||||||
<InputPassword size="large" visibilityToggle v-model:value="formData.password" :placeholder="t('sys.login.password')" />
|
<InputPassword size="large" visibilityToggle v-model:value="formData.password"
|
||||||
|
:placeholder="t('sys.login.password')" />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
|
|
||||||
<!--验证码-->
|
<!--验证码-->
|
||||||
<ARow class="enter-x">
|
<ARow class="enter-x">
|
||||||
<ACol :span="12">
|
<ACol :span="12">
|
||||||
<FormItem name="inputCode" class="enter-x">
|
<FormItem name="inputCode" class="enter-x">
|
||||||
<Input size="large" v-model:value="formData.inputCode" :placeholder="t('sys.login.inputCode')" style="min-width: 100px" />
|
<Input size="large" v-model:value="formData.inputCode" :placeholder="t('sys.login.inputCode')"
|
||||||
|
style="min-width: 100px" />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
</ACol>
|
</ACol>
|
||||||
<ACol :span="8">
|
<ACol :span="8">
|
||||||
<FormItem :style="{ 'text-align': 'right', 'margin-left': '20px' }" class="enter-x">
|
<FormItem :style="{ 'text-align': 'right', 'margin-left': '20px' }" class="enter-x">
|
||||||
<img
|
<img v-if="randCodeData.requestCodeSuccess" style="margin-top: 2px; max-width: initial"
|
||||||
v-if="randCodeData.requestCodeSuccess"
|
:src="randCodeData.randCodeImage" @click="handleChangeCheckCode" />
|
||||||
style="margin-top: 2px; max-width: initial"
|
<img v-else style="margin-top: 2px; max-width: initial" src="../../../assets/images/checkcode.png"
|
||||||
:src="randCodeData.randCodeImage"
|
@click="handleChangeCheckCode" />
|
||||||
@click="handleChangeCheckCode"
|
|
||||||
/>
|
|
||||||
<img v-else style="margin-top: 2px; max-width: initial" src="../../../assets/images/checkcode.png" @click="handleChangeCheckCode" />
|
|
||||||
</FormItem>
|
</FormItem>
|
||||||
</ACol>
|
</ACol>
|
||||||
</ARow>
|
</ARow>
|
||||||
|
@ -76,121 +77,128 @@
|
||||||
<Divider class="enter-x">{{ t('sys.login.otherSignIn') }}</Divider>
|
<Divider class="enter-x">{{ t('sys.login.otherSignIn') }}</Divider>
|
||||||
|
|
||||||
<div class="flex justify-evenly enter-x" :class="`${prefixCls}-sign-in-way`">
|
<div class="flex justify-evenly enter-x" :class="`${prefixCls}-sign-in-way`">
|
||||||
<a @click="onThirdLogin('github')" title="github"><GithubFilled /></a>
|
<a @click="onThirdLogin('github')" title="github">
|
||||||
<a @click="onThirdLogin('wechat_enterprise')" title="企业微信"> <icon-font class="item-icon" type="icon-qiyeweixin3" /></a>
|
<GithubFilled />
|
||||||
<a @click="onThirdLogin('dingtalk')" title="钉钉"><DingtalkCircleFilled /></a>
|
</a>
|
||||||
<a @click="onThirdLogin('wechat_open')" title="微信"><WechatFilled /></a>
|
<a @click="onThirdLogin('wechat_enterprise')" title="企业微信"> <icon-font class="item-icon"
|
||||||
|
type="icon-qiyeweixin3" /></a>
|
||||||
|
<a @click="onThirdLogin('dingtalk')" title="钉钉">
|
||||||
|
<DingtalkCircleFilled />
|
||||||
|
</a>
|
||||||
|
<a @click="onThirdLogin('wechat_open')" title="微信">
|
||||||
|
<WechatFilled />
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
<!-- 第三方登录相关弹框 -->
|
<!-- 第三方登录相关弹框 -->
|
||||||
<ThirdModal ref="thirdModalRef"></ThirdModal>
|
<ThirdModal ref="thirdModalRef"></ThirdModal>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { reactive, ref, toRaw, unref, computed, onMounted } from 'vue';
|
import { reactive, ref, toRaw, unref, computed, onMounted } from 'vue';
|
||||||
|
|
||||||
import { Checkbox, Form, Input, Row, Col, Button, Divider } from 'ant-design-vue';
|
import { Checkbox, Form, Input, Row, Col, Button, Divider } from 'ant-design-vue';
|
||||||
import { GithubFilled, WechatFilled, DingtalkCircleFilled, createFromIconfontCN } from '@ant-design/icons-vue';
|
import { GithubFilled, WechatFilled, DingtalkCircleFilled, createFromIconfontCN } from '@ant-design/icons-vue';
|
||||||
import LoginFormTitle from './LoginFormTitle.vue';
|
import LoginFormTitle from './LoginFormTitle.vue';
|
||||||
import ThirdModal from './ThirdModal.vue';
|
import ThirdModal from './ThirdModal.vue';
|
||||||
import { useI18n } from '/@/hooks/web/useI18n';
|
import { useI18n } from '/@/hooks/web/useI18n';
|
||||||
import { useMessage } from '/@/hooks/web/useMessage';
|
import { useMessage } from '/@/hooks/web/useMessage';
|
||||||
|
|
||||||
import { useUserStore } from '/@/store/modules/user';
|
import { useUserStore } from '/@/store/modules/user';
|
||||||
import { LoginStateEnum, useLoginState, useFormRules, useFormValid } from './useLogin';
|
import { LoginStateEnum, useLoginState, useFormRules, useFormValid } from './useLogin';
|
||||||
import { useDesign } from '/@/hooks/web/useDesign';
|
import { useDesign } from '/@/hooks/web/useDesign';
|
||||||
import { getCodeInfo } from '/@/api/sys/user';
|
import { getCodeInfo } from '/@/api/sys/user';
|
||||||
//import { onKeyStroke } from '@vueuse/core';
|
//import { onKeyStroke } from '@vueuse/core';
|
||||||
|
|
||||||
const ACol = Col;
|
const ACol = Col;
|
||||||
const ARow = Row;
|
const ARow = Row;
|
||||||
const FormItem = Form.Item;
|
const FormItem = Form.Item;
|
||||||
const InputPassword = Input.Password;
|
const InputPassword = Input.Password;
|
||||||
const IconFont = createFromIconfontCN({
|
const IconFont = createFromIconfontCN({
|
||||||
scriptUrl: '//at.alicdn.com/t/font_2316098_umqusozousr.js',
|
scriptUrl: '//at.alicdn.com/t/font_2316098_umqusozousr.js',
|
||||||
});
|
});
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { notification, createErrorModal } = useMessage();
|
const { notification, createErrorModal } = useMessage();
|
||||||
const { prefixCls } = useDesign('login');
|
const { prefixCls } = useDesign('login');
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
|
|
||||||
const { setLoginState, getLoginState } = useLoginState();
|
const { setLoginState, getLoginState } = useLoginState();
|
||||||
const { getFormRules } = useFormRules();
|
const { getFormRules } = useFormRules();
|
||||||
|
|
||||||
const formRef = ref();
|
const formRef = ref();
|
||||||
const thirdModalRef = ref();
|
const thirdModalRef = ref();
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const rememberMe = ref(false);
|
const rememberMe = ref(false);
|
||||||
|
|
||||||
const formData = reactive({
|
const formData = reactive({
|
||||||
account: 'admin',
|
account: 'admin',
|
||||||
password: '123456',
|
password: '123456',
|
||||||
inputCode: '',
|
inputCode: '',
|
||||||
});
|
});
|
||||||
const randCodeData = reactive({
|
const randCodeData = reactive({
|
||||||
randCodeImage: '',
|
randCodeImage: '',
|
||||||
requestCodeSuccess: false,
|
requestCodeSuccess: false,
|
||||||
checkKey: null,
|
checkKey: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { validForm } = useFormValid(formRef);
|
const { validForm } = useFormValid(formRef);
|
||||||
|
|
||||||
//onKeyStroke('Enter', handleLogin);
|
//onKeyStroke('Enter', handleLogin);
|
||||||
|
|
||||||
const getShow = computed(() => unref(getLoginState) === LoginStateEnum.LOGIN);
|
const getShow = computed(() => unref(getLoginState) === LoginStateEnum.LOGIN);
|
||||||
|
|
||||||
async function handleLogin() {
|
async function handleLogin() {
|
||||||
const data = await validForm();
|
const data = await validForm();
|
||||||
if (!data) return;
|
if (!data) return;
|
||||||
try {
|
try {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const { userInfo } = await userStore.login(
|
const { userInfo } = await userStore.login(
|
||||||
toRaw({
|
toRaw({
|
||||||
password: data.password,
|
password: data.password,
|
||||||
username: data.account,
|
username: data.account,
|
||||||
captcha: data.inputCode,
|
captcha: data.inputCode,
|
||||||
checkKey: randCodeData.checkKey,
|
checkKey: randCodeData.checkKey,
|
||||||
mode: 'none', //不要默认的错误提示
|
mode: 'none', //不要默认的错误提示
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
if (userInfo) {
|
if (userInfo) {
|
||||||
notification.success({
|
notification.success({
|
||||||
message: t('sys.login.loginSuccessTitle'),
|
message: t('sys.login.loginSuccessTitle'),
|
||||||
description: `${t('sys.login.loginSuccessDesc')}: ${userInfo.realname}`,
|
description: `${t('sys.login.loginSuccessDesc')}: ${userInfo.realname}`,
|
||||||
duration: 3,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
notification.error({
|
|
||||||
message: t('sys.api.errorTip'),
|
|
||||||
description: error.message || t('sys.api.networkExceptionMsg'),
|
|
||||||
duration: 3,
|
duration: 3,
|
||||||
});
|
});
|
||||||
loading.value = false;
|
|
||||||
|
|
||||||
//update-begin-author:taoyan date:2022-5-3 for: issues/41 登录页面,当输入验证码错误时,验证码图片要刷新一下,而不是保持旧的验证码图片不变
|
|
||||||
handleChangeCheckCode();
|
|
||||||
//update-end-author:taoyan date:2022-5-3 for: issues/41 登录页面,当输入验证码错误时,验证码图片要刷新一下,而不是保持旧的验证码图片不变
|
|
||||||
}
|
}
|
||||||
}
|
} catch (error) {
|
||||||
function handleChangeCheckCode() {
|
notification.error({
|
||||||
formData.inputCode = '';
|
message: t('sys.api.errorTip'),
|
||||||
//TODO 兼容mock和接口,暂时这样处理
|
description: error.message || t('sys.api.networkExceptionMsg'),
|
||||||
randCodeData.checkKey = 1629428467008; //new Date().getTime();
|
duration: 3,
|
||||||
getCodeInfo(randCodeData.checkKey).then((res) => {
|
|
||||||
randCodeData.randCodeImage = res;
|
|
||||||
randCodeData.requestCodeSuccess = true;
|
|
||||||
});
|
});
|
||||||
}
|
loading.value = false;
|
||||||
|
|
||||||
/**
|
//update-begin-author:taoyan date:2022-5-3 for: issues/41 登录页面,当输入验证码错误时,验证码图片要刷新一下,而不是保持旧的验证码图片不变
|
||||||
* 第三方登录
|
|
||||||
* @param type
|
|
||||||
*/
|
|
||||||
function onThirdLogin(type) {
|
|
||||||
thirdModalRef.value.onThirdLogin(type);
|
|
||||||
}
|
|
||||||
//初始化验证码
|
|
||||||
onMounted(() => {
|
|
||||||
handleChangeCheckCode();
|
handleChangeCheckCode();
|
||||||
|
//update-end-author:taoyan date:2022-5-3 for: issues/41 登录页面,当输入验证码错误时,验证码图片要刷新一下,而不是保持旧的验证码图片不变
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function handleChangeCheckCode() {
|
||||||
|
formData.inputCode = '';
|
||||||
|
//TODO 兼容mock和接口,暂时这样处理
|
||||||
|
randCodeData.checkKey = 1629428467008; //new Date().getTime();
|
||||||
|
getCodeInfo(randCodeData.checkKey).then((res) => {
|
||||||
|
randCodeData.randCodeImage = res;
|
||||||
|
randCodeData.requestCodeSuccess = true;
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 第三方登录
|
||||||
|
* @param type
|
||||||
|
*/
|
||||||
|
function onThirdLogin(type) {
|
||||||
|
thirdModalRef.value.onThirdLogin(type);
|
||||||
|
}
|
||||||
|
//初始化验证码
|
||||||
|
onMounted(() => {
|
||||||
|
handleChangeCheckCode();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,218 +1,221 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="app-loading">
|
<div class="app-loading">
|
||||||
<div class="app-loading-wrap">
|
<div class="app-loading-wrap">
|
||||||
<img src="/resource/img/logo.png" class="app-loading-logo" alt="Logo">
|
<!--<img src="/resource/img/logo.png" class="app-loading-logo" alt="Logo">-->
|
||||||
<div class="app-loading-dots">
|
<div class="app-loading-dots">
|
||||||
<span class="dot dot-spin"><i></i><i></i><i></i><i></i></span>
|
<span class="dot dot-spin"><i></i><i></i><i></i><i></i></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="app-loading-title">JeecgBoot 企业级低代码平台</div>
|
<div class="app-loading-title">哈尔滨师范大学</div>
|
||||||
</div>
|
<div class="app-loading-title">评阅人员管理系统</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
/**
|
/**
|
||||||
* 地址中携带token,跳转至此页面进行登录操作
|
* 地址中携带token,跳转至此页面进行登录操作
|
||||||
*/
|
*/
|
||||||
import { useRoute, useRouter } from 'vue-router';
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
import { useMessage } from '/@/hooks/web/useMessage';
|
import { useMessage } from '/@/hooks/web/useMessage';
|
||||||
import { useUserStore } from '/@/store/modules/user';
|
import { useUserStore } from '/@/store/modules/user';
|
||||||
import { useI18n } from '/@/hooks/web/useI18n';
|
import { useI18n } from '/@/hooks/web/useI18n';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "TokenLogin",
|
name: "TokenLogin",
|
||||||
setup(){
|
setup() {
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
let router = useRouter();
|
let router = useRouter();
|
||||||
const {createMessage, notification} = useMessage()
|
const { createMessage, notification } = useMessage()
|
||||||
const {t} = useI18n();
|
const { t } = useI18n();
|
||||||
const routeQuery:any = route.query;
|
const routeQuery: any = route.query;
|
||||||
if(!routeQuery){
|
if (!routeQuery) {
|
||||||
createMessage.warning('参数无效')
|
createMessage.warning('参数无效')
|
||||||
}
|
}
|
||||||
|
|
||||||
const token = routeQuery['loginToken'];
|
const token = routeQuery['loginToken'];
|
||||||
if(!token){
|
if (!token) {
|
||||||
createMessage.warning('token无效')
|
createMessage.warning('token无效')
|
||||||
|
}
|
||||||
|
const userStore = useUserStore();
|
||||||
|
userStore.ThirdLogin({ token, thirdType: 'email', goHome: false }).then(res => {
|
||||||
|
console.log("res====>doThirdLogin", res)
|
||||||
|
if (res && res.userInfo) {
|
||||||
|
requestSuccess(res)
|
||||||
|
} else {
|
||||||
|
requestFailed(res)
|
||||||
}
|
}
|
||||||
const userStore = useUserStore();
|
});
|
||||||
userStore.ThirdLogin({ token, thirdType:'email', goHome: false }).then(res => {
|
|
||||||
console.log("res====>doThirdLogin",res)
|
function requestFailed(err) {
|
||||||
if(res && res.userInfo){
|
notification.error({
|
||||||
requestSuccess(res)
|
message: '登录失败',
|
||||||
}else{
|
description: ((err.response || {}).data || {}).message || err.message || "请求出现错误,请稍后再试",
|
||||||
requestFailed(res)
|
duration: 4,
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function requestFailed (err) {
|
function requestSuccess(res) {
|
||||||
|
let info = routeQuery.info;
|
||||||
|
if (info) {
|
||||||
|
let query = JSON.parse(info);
|
||||||
|
|
||||||
|
//update-begin-author:taoyan date:2023-4-27 for: QQYUN-4882【简流】节点消息通知 邮箱 点击办理跳到了应用首页
|
||||||
|
let path = '';
|
||||||
|
if (query.isLowApp === 1) {
|
||||||
|
path = '/myapps/personalOffice/myTodo'
|
||||||
|
} else {
|
||||||
|
let taskId = query.taskId;
|
||||||
|
path = '/task/handle/' + taskId
|
||||||
|
}
|
||||||
|
//update-end-author:taoyan date:2023-4-27 for: QQYUN-4882【简流】节点消息通知 邮箱 点击办理跳到了应用首页
|
||||||
|
|
||||||
|
router.replace({ path, query });
|
||||||
|
notification.success({
|
||||||
|
message: t('sys.login.loginSuccessTitle'),
|
||||||
|
description: `${t('sys.login.loginSuccessDesc')}: ${res.userInfo.realname}`,
|
||||||
|
duration: 3,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
notification.error({
|
notification.error({
|
||||||
message: '登录失败',
|
message: '参数失效',
|
||||||
description: ((err.response || {}).data || {}).message || err.message || "请求出现错误,请稍后再试",
|
description: "页面跳转参数丢失,请查看日志",
|
||||||
duration: 4,
|
duration: 4,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function requestSuccess(res){
|
|
||||||
let info = routeQuery.info;
|
|
||||||
if(info){
|
|
||||||
let query = JSON.parse(info);
|
|
||||||
|
|
||||||
//update-begin-author:taoyan date:2023-4-27 for: QQYUN-4882【简流】节点消息通知 邮箱 点击办理跳到了应用首页
|
|
||||||
let path = '';
|
|
||||||
if(query.isLowApp === 1){
|
|
||||||
path = '/myapps/personalOffice/myTodo'
|
|
||||||
}else{
|
|
||||||
let taskId = query.taskId;
|
|
||||||
path = '/task/handle/' + taskId
|
|
||||||
}
|
|
||||||
//update-end-author:taoyan date:2023-4-27 for: QQYUN-4882【简流】节点消息通知 邮箱 点击办理跳到了应用首页
|
|
||||||
|
|
||||||
router.replace({ path, query });
|
|
||||||
notification.success({
|
|
||||||
message: t('sys.login.loginSuccessTitle'),
|
|
||||||
description: `${t('sys.login.loginSuccessDesc')}: ${res.userInfo.realname}`,
|
|
||||||
duration: 3,
|
|
||||||
});
|
|
||||||
}else{
|
|
||||||
notification.error({
|
|
||||||
message: '参数失效',
|
|
||||||
description: "页面跳转参数丢失,请查看日志",
|
|
||||||
duration: 4,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
html[data-theme='dark'] .app-loading {
|
||||||
|
background-color: #2c344a;
|
||||||
|
}
|
||||||
|
|
||||||
html[data-theme='dark'] .app-loading {
|
html[data-theme='dark'] .app-loading .app-loading-title {
|
||||||
background-color: #2c344a;
|
color: rgba(255, 255, 255, 0.85);
|
||||||
}
|
}
|
||||||
|
|
||||||
html[data-theme='dark'] .app-loading .app-loading-title {
|
.app-loading {
|
||||||
color: rgba(255, 255, 255, 0.85);
|
display: flex;
|
||||||
}
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: column;
|
||||||
|
background-color: #f4f7f9;
|
||||||
|
}
|
||||||
|
|
||||||
.app-loading {
|
.app-loading .app-loading-wrap {
|
||||||
display: flex;
|
position: absolute;
|
||||||
width: 100%;
|
top: 50%;
|
||||||
height: 100%;
|
left: 50%;
|
||||||
justify-content: center;
|
display: flex;
|
||||||
align-items: center;
|
-webkit-transform: translate3d(-50%, -50%, 0);
|
||||||
flex-direction: column;
|
transform: translate3d(-50%, -50%, 0);
|
||||||
background-color: #f4f7f9;
|
justify-content: center;
|
||||||
}
|
align-items: center;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
.app-loading .app-loading-wrap {
|
.app-loading .dots {
|
||||||
position: absolute;
|
display: flex;
|
||||||
top: 50%;
|
padding: 98px;
|
||||||
left: 50%;
|
justify-content: center;
|
||||||
display: flex;
|
align-items: center;
|
||||||
-webkit-transform: translate3d(-50%, -50%, 0);
|
}
|
||||||
transform: translate3d(-50%, -50%, 0);
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.app-loading .dots {
|
.app-loading .app-loading-title {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 98px;
|
margin-top: 30px;
|
||||||
justify-content: center;
|
font-size: 30px;
|
||||||
align-items: center;
|
color: rgba(0, 0, 0, 0.85);
|
||||||
}
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
.app-loading .app-loading-title {
|
.app-loading .app-loading-logo {
|
||||||
display: flex;
|
display: block;
|
||||||
margin-top: 30px;
|
width: 90px;
|
||||||
font-size: 30px;
|
margin: 0 auto;
|
||||||
color: rgba(0, 0, 0, 0.85);
|
margin-bottom: 20px;
|
||||||
justify-content: center;
|
}
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.app-loading .app-loading-logo {
|
.dot {
|
||||||
display: block;
|
position: relative;
|
||||||
width: 90px;
|
display: inline-block;
|
||||||
margin: 0 auto;
|
width: 48px;
|
||||||
margin-bottom: 20px;
|
height: 48px;
|
||||||
}
|
margin-top: 30px;
|
||||||
|
font-size: 32px;
|
||||||
|
transform: rotate(45deg);
|
||||||
|
box-sizing: border-box;
|
||||||
|
animation: antRotate 1.2s infinite linear;
|
||||||
|
}
|
||||||
|
|
||||||
.dot {
|
.dot i {
|
||||||
position: relative;
|
position: absolute;
|
||||||
display: inline-block;
|
display: block;
|
||||||
width: 48px;
|
width: 20px;
|
||||||
height: 48px;
|
height: 20px;
|
||||||
margin-top: 30px;
|
background-color: #0065cc;
|
||||||
font-size: 32px;
|
border-radius: 100%;
|
||||||
transform: rotate(45deg);
|
opacity: 0.3;
|
||||||
box-sizing: border-box;
|
transform: scale(0.75);
|
||||||
animation: antRotate 1.2s infinite linear;
|
animation: antSpinMove 1s infinite linear alternate;
|
||||||
}
|
transform-origin: 50% 50%;
|
||||||
|
}
|
||||||
|
|
||||||
.dot i {
|
.dot i:nth-child(1) {
|
||||||
position: absolute;
|
top: 0;
|
||||||
display: block;
|
left: 0;
|
||||||
width: 20px;
|
}
|
||||||
height: 20px;
|
|
||||||
background-color: #0065cc;
|
|
||||||
border-radius: 100%;
|
|
||||||
opacity: 0.3;
|
|
||||||
transform: scale(0.75);
|
|
||||||
animation: antSpinMove 1s infinite linear alternate;
|
|
||||||
transform-origin: 50% 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dot i:nth-child(1) {
|
.dot i:nth-child(2) {
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
right: 0;
|
||||||
}
|
-webkit-animation-delay: 0.4s;
|
||||||
|
animation-delay: 0.4s;
|
||||||
|
}
|
||||||
|
|
||||||
.dot i:nth-child(2) {
|
.dot i:nth-child(3) {
|
||||||
top: 0;
|
right: 0;
|
||||||
right: 0;
|
bottom: 0;
|
||||||
-webkit-animation-delay: 0.4s;
|
-webkit-animation-delay: 0.8s;
|
||||||
animation-delay: 0.4s;
|
animation-delay: 0.8s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dot i:nth-child(3) {
|
.dot i:nth-child(4) {
|
||||||
right: 0;
|
bottom: 0;
|
||||||
bottom: 0;
|
left: 0;
|
||||||
-webkit-animation-delay: 0.8s;
|
-webkit-animation-delay: 1.2s;
|
||||||
animation-delay: 0.8s;
|
animation-delay: 1.2s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dot i:nth-child(4) {
|
@keyframes antRotate {
|
||||||
bottom: 0;
|
to {
|
||||||
left: 0;
|
-webkit-transform: rotate(405deg);
|
||||||
-webkit-animation-delay: 1.2s;
|
transform: rotate(405deg);
|
||||||
animation-delay: 1.2s;
|
}
|
||||||
}
|
}
|
||||||
@keyframes antRotate {
|
|
||||||
to {
|
|
||||||
-webkit-transform: rotate(405deg);
|
|
||||||
transform: rotate(405deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@-webkit-keyframes antRotate {
|
|
||||||
to {
|
|
||||||
-webkit-transform: rotate(405deg);
|
|
||||||
transform: rotate(405deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@keyframes antSpinMove {
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@-webkit-keyframes antSpinMove {
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@-webkit-keyframes antRotate {
|
||||||
|
to {
|
||||||
|
-webkit-transform: rotate(405deg);
|
||||||
|
transform: rotate(405deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes antSpinMove {
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@-webkit-keyframes antSpinMove {
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
|
@ -1,86 +1,65 @@
|
||||||
<template>
|
<template>
|
||||||
<div :class="prefixCls" class="login-background-img">
|
<div :class="prefixCls" class="login-background-img">
|
||||||
<AppLocalePicker class="absolute top-4 right-4 enter-x xl:text-gray-600" :showText="false"/>
|
<AppLocalePicker class="absolute top-4 right-4 enter-x xl:text-gray-600" :showText="false" />
|
||||||
<AppDarkModeToggle class="absolute top-3 right-7 enter-x" />
|
<AppDarkModeToggle class="absolute top-3 right-7 enter-x" />
|
||||||
<div class="aui-logo" v-if="!getIsMobile">
|
|
||||||
<div>
|
|
||||||
<h3>
|
|
||||||
<img :src="logoImg" alt="jeecg" />
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div v-else class="aui-phone-logo">
|
|
||||||
<img :src="logoImg" alt="jeecg" />
|
|
||||||
</div>
|
|
||||||
<div v-show="type === 'login'">
|
<div v-show="type === 'login'">
|
||||||
<div class="aui-content">
|
<div class="aui-content">
|
||||||
<div class="aui-container">
|
<div class="aui-container">
|
||||||
<div class="aui-form">
|
<div class="aui-form">
|
||||||
<div class="aui-image">
|
<div class="aui-image">
|
||||||
<div class="aui-image-text">
|
<div class="aui-image-text">
|
||||||
<img :src="adTextImg" />
|
<div>
|
||||||
|
<span class="introduce-text1">哈尔滨师范大学</span>
|
||||||
|
<br>
|
||||||
|
<span class="introduce-text">评阅人员管理系统</span>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<!--<span class="introduce-text" style="font-size: 18px;">深入分析 多维展示</span>-->
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="aui-formBox">
|
<div class="aui-formBox">
|
||||||
<div class="aui-formWell">
|
<div class="aui-formWell">
|
||||||
<div class="aui-flex aui-form-nav investment_title">
|
<div class="aui-flex aui-form-nav investment_title">
|
||||||
<div class="aui-flex-box" :class="activeIndex === 'accountLogin' ? 'activeNav on' : ''" @click="loginClick('accountLogin')"
|
<div class="aui-flex-box" :class="activeIndex === 'accountLogin' ? 'activeNav on' : ''"
|
||||||
>{{ t('sys.login.signInFormTitle') }}
|
@click="loginClick('accountLogin')">{{ t('sys.login.signInFormTitle') }}
|
||||||
</div>
|
|
||||||
<div class="aui-flex-box" :class="activeIndex === 'phoneLogin' ? 'activeNav on' : ''" @click="loginClick('phoneLogin')"
|
|
||||||
>{{ t('sys.login.mobileSignInFormTitle') }}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="aui-form-box" style="height: 180px">
|
<div class="aui-form-box" style="height: 140px">
|
||||||
<a-form ref="loginRef" :model="formData" v-if="activeIndex === 'accountLogin'" @keyup.enter.native="loginHandleClick">
|
<a-form ref="loginRef" :model="formData" v-if="activeIndex === 'accountLogin'"
|
||||||
|
@keyup.enter.native="loginHandleClick">
|
||||||
<div class="aui-account">
|
<div class="aui-account">
|
||||||
<div class="aui-inputClear">
|
<div class="aui-inputClear">
|
||||||
<i class="icon icon-code"></i>
|
<i class="icon icon-code"></i>
|
||||||
<a-form-item>
|
<a-form-item>
|
||||||
<a-input class="fix-auto-fill" :placeholder="t('sys.login.userName')" v-model:value="formData.username" />
|
<a-input class="fix-auto-fill" :placeholder="t('sys.login.userName')"
|
||||||
|
v-model:value="formData.username" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</div>
|
</div>
|
||||||
<div class="aui-inputClear">
|
<div class="aui-inputClear">
|
||||||
<i class="icon icon-password"></i>
|
<i class="icon icon-password"></i>
|
||||||
<a-form-item>
|
<a-form-item>
|
||||||
<a-input class="fix-auto-fill" type="password" :placeholder="t('sys.login.password')" v-model:value="formData.password" />
|
<a-input class="fix-auto-fill" type="password" :placeholder="t('sys.login.password')"
|
||||||
|
v-model:value="formData.password" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</div>
|
</div>
|
||||||
<div class="aui-inputClear">
|
|
||||||
<i class="icon icon-code"></i>
|
|
||||||
<a-form-item>
|
|
||||||
<a-input class="fix-auto-fill" type="text" :placeholder="t('sys.login.inputCode')" v-model:value="formData.inputCode" />
|
|
||||||
</a-form-item>
|
|
||||||
<div class="aui-code">
|
|
||||||
<img v-if="randCodeData.requestCodeSuccess" :src="randCodeData.randCodeImage" @click="handleChangeCheckCode" />
|
|
||||||
<img v-else style="margin-top: 2px; max-width: initial" :src="codeImg" @click="handleChangeCheckCode" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="aui-flex">
|
|
||||||
<div class="aui-flex-box">
|
|
||||||
<div class="aui-choice">
|
|
||||||
<a-input class="fix-auto-fill" type="checkbox" v-model:value="rememberMe" />
|
|
||||||
<span style="margin-left: 5px">{{ t('sys.login.rememberMe') }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="aui-forget">
|
|
||||||
<a @click="forgetHandelClick"> {{ t('sys.login.forgetPassword') }}</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</a-form>
|
</a-form>
|
||||||
<a-form v-else ref="phoneFormRef" :model="phoneFormData" @keyup.enter.native="loginHandleClick">
|
<a-form v-else ref="phoneFormRef" :model="phoneFormData" @keyup.enter.native="loginHandleClick">
|
||||||
<div class="aui-account phone">
|
<div class="aui-account phone">
|
||||||
<div class="aui-inputClear phoneClear">
|
<div class="aui-inputClear phoneClear">
|
||||||
<a-input class="fix-auto-fill" :placeholder="t('sys.login.mobile')" v-model:value="phoneFormData.mobile" />
|
<a-input class="fix-auto-fill" :placeholder="t('sys.login.mobile')"
|
||||||
|
v-model:value="phoneFormData.mobile" />
|
||||||
</div>
|
</div>
|
||||||
<div class="aui-inputClear">
|
<div class="aui-inputClear">
|
||||||
<a-input class="fix-auto-fill" :maxlength="6" :placeholder="t('sys.login.smsCode')" v-model:value="phoneFormData.smscode" />
|
<a-input class="fix-auto-fill" :maxlength="6" :placeholder="t('sys.login.smsCode')"
|
||||||
|
v-model:value="phoneFormData.smscode" />
|
||||||
<div v-if="showInterval" class="aui-code" @click="getLoginCode">
|
<div v-if="showInterval" class="aui-code" @click="getLoginCode">
|
||||||
<a>{{ t('component.countdown.normalText') }}</a>
|
<a>{{ t('component.countdown.normalText') }}</a>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="aui-code">
|
<div v-else class="aui-code">
|
||||||
<span class="aui-get-code code-shape">{{ t('component.countdown.sendText', [unref(timeRuning)]) }}</span>
|
<span class="aui-get-code code-shape">{{ t('component.countdown.sendText',
|
||||||
|
[unref(timeRuning)]) }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -92,42 +71,11 @@
|
||||||
{{ t('sys.login.loginButton') }}</a-button>
|
{{ t('sys.login.loginButton') }}</a-button>
|
||||||
</div>
|
</div>
|
||||||
<div class="aui-flex">
|
<div class="aui-flex">
|
||||||
<a class="aui-linek-code aui-flex-box" @click="codeHandleClick">{{ t('sys.login.qrSignInFormTitle') }}</a>
|
<a class="aui-linek-code aui-flex-box" @click="registerHandleClick">{{ t('sys.login.registerButton')
|
||||||
</div>
|
}}</a>
|
||||||
<div class="aui-flex">
|
|
||||||
<a class="aui-linek-code aui-flex-box" @click="registerHandleClick">{{ t('sys.login.registerButton') }}</a>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<a-form @keyup.enter.native="loginHandleClick">
|
|
||||||
<div class="aui-flex aui-third-text">
|
|
||||||
<div class="aui-flex-box aui-third-border">
|
|
||||||
<span>{{ t('sys.login.otherSignIn') }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="aui-flex" :class="`${prefixCls}-sign-in-way`">
|
|
||||||
<div class="aui-flex-box">
|
|
||||||
<div class="aui-third-login">
|
|
||||||
<a title="github" @click="onThirdLogin('github')"><GithubFilled /></a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="aui-flex-box">
|
|
||||||
<div class="aui-third-login">
|
|
||||||
<a title="企业微信" @click="onThirdLogin('wechat_enterprise')"><icon-font class="item-icon" type="icon-qiyeweixin3" /></a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="aui-flex-box">
|
|
||||||
<div class="aui-third-login">
|
|
||||||
<a title="钉钉" @click="onThirdLogin('dingtalk')"><DingtalkCircleFilled /></a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="aui-flex-box">
|
|
||||||
<div class="aui-third-login">
|
|
||||||
<a title="微信" @click="onThirdLogin('wechat_open')"><WechatFilled /></a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</a-form>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -147,331 +95,310 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup name="login-mini">
|
<script lang="ts" setup name="login-mini">
|
||||||
import { getCaptcha, getCodeInfo } from '/@/api/sys/user';
|
import { getCaptcha, getCodeInfo } from '/@/api/sys/user';
|
||||||
import { computed, onMounted, reactive, ref, toRaw, unref } from 'vue';
|
import { onMounted, reactive, ref, toRaw, unref } from 'vue';
|
||||||
import codeImg from '/@/assets/images/checkcode.png';
|
import { useUserStore } from '/@/store/modules/user';
|
||||||
import { Rule } from '/@/components/Form';
|
import { useMessage } from '/@/hooks/web/useMessage';
|
||||||
import { useUserStore } from '/@/store/modules/user';
|
import { useI18n } from '/@/hooks/web/useI18n';
|
||||||
import { useMessage } from '/@/hooks/web/useMessage';
|
import { SmsEnum } from '/@/views/sys/login/useLogin';
|
||||||
import { useI18n } from '/@/hooks/web/useI18n';
|
import ThirdModal from '/@/views/sys/login/ThirdModal.vue';
|
||||||
import { SmsEnum } from '/@/views/sys/login/useLogin';
|
import MiniForgotpad from './MiniForgotpad.vue';
|
||||||
import ThirdModal from '/@/views/sys/login/ThirdModal.vue';
|
import MiniRegister from './MiniRegister.vue';
|
||||||
import MiniForgotpad from './MiniForgotpad.vue';
|
import MiniCodelogin from './MiniCodelogin.vue';
|
||||||
import MiniRegister from './MiniRegister.vue';
|
import adTextImg from '/@/assets/loginmini/icon/jeecg_ad_text.png';
|
||||||
import MiniCodelogin from './MiniCodelogin.vue';
|
import { AppLocalePicker, AppDarkModeToggle } from '/@/components/Application';
|
||||||
import logoImg from '/@/assets/loginmini/icon/jeecg_logo.png';
|
import { useLocaleStore } from '/@/store/modules/locale';
|
||||||
import adTextImg from '/@/assets/loginmini/icon/jeecg_ad_text.png';
|
import { useDesign } from "/@/hooks/web/useDesign";
|
||||||
import { AppLocalePicker, AppDarkModeToggle } from '/@/components/Application';
|
import { useAppInject } from "/@/hooks/web/useAppInject";
|
||||||
import { useLocaleStore } from '/@/store/modules/locale';
|
|
||||||
import { useDesign } from "/@/hooks/web/useDesign";
|
|
||||||
import { useAppInject } from "/@/hooks/web/useAppInject";
|
|
||||||
import { GithubFilled, WechatFilled, DingtalkCircleFilled, createFromIconfontCN } from '@ant-design/icons-vue';
|
|
||||||
|
|
||||||
const IconFont = createFromIconfontCN({
|
const { prefixCls } = useDesign('mini-login');
|
||||||
scriptUrl: '//at.alicdn.com/t/font_2316098_umqusozousr.js',
|
const { notification, createMessage } = useMessage();
|
||||||
});
|
const userStore = useUserStore();
|
||||||
const { prefixCls } = useDesign('mini-login');
|
const { t } = useI18n();
|
||||||
const { notification, createMessage } = useMessage();
|
const localeStore = useLocaleStore();
|
||||||
const userStore = useUserStore();
|
const randCodeData = reactive<any>({
|
||||||
const { t } = useI18n();
|
randCodeImage: '',
|
||||||
const localeStore = useLocaleStore();
|
requestCodeSuccess: false,
|
||||||
const showLocale = localeStore.getShowPicker;
|
checkKey: null,
|
||||||
const randCodeData = reactive<any>({
|
});
|
||||||
randCodeImage: '',
|
//手机号登录还是账号登录
|
||||||
requestCodeSuccess: false,
|
const activeIndex = ref<string>('accountLogin');
|
||||||
checkKey: null,
|
const type = ref<string>('login');
|
||||||
});
|
//账号登录表单字段
|
||||||
const rememberMe = ref<string>('0');
|
const formData = reactive<any>({
|
||||||
//手机号登录还是账号登录
|
inputCode: '',
|
||||||
const activeIndex = ref<string>('accountLogin');
|
username: 'admin',
|
||||||
const type = ref<string>('login');
|
password: '123456',
|
||||||
//账号登录表单字段
|
});
|
||||||
const formData = reactive<any>({
|
//手机登录表单字段
|
||||||
inputCode: '',
|
const phoneFormData = reactive<any>({
|
||||||
username: 'admin',
|
mobile: '',
|
||||||
password: '123456',
|
smscode: '',
|
||||||
});
|
});
|
||||||
//手机登录表单字段
|
const loginRef = ref();
|
||||||
const phoneFormData = reactive<any>({
|
//第三方登录弹窗
|
||||||
mobile: '',
|
const thirdModalRef = ref();
|
||||||
smscode: '',
|
//扫码登录
|
||||||
});
|
const codeRef = ref();
|
||||||
const loginRef = ref();
|
//是否显示获取验证码
|
||||||
//第三方登录弹窗
|
const showInterval = ref<boolean>(true);
|
||||||
const thirdModalRef = ref();
|
//60s
|
||||||
//扫码登录
|
const timeRuning = ref<number>(60);
|
||||||
const codeRef = ref();
|
//定时器
|
||||||
//是否显示获取验证码
|
const timer = ref<any>(null);
|
||||||
const showInterval = ref<boolean>(true);
|
//忘记密码
|
||||||
//60s
|
const forgotRef = ref();
|
||||||
const timeRuning = ref<number>(60);
|
//注册
|
||||||
//定时器
|
const registerRef = ref();
|
||||||
const timer = ref<any>(null);
|
const loginLoading = ref<boolean>(false);
|
||||||
//忘记密码
|
const { getIsMobile } = useAppInject();
|
||||||
const forgotRef = ref();
|
|
||||||
//注册
|
|
||||||
const registerRef = ref();
|
|
||||||
const loginLoading = ref<boolean>(false);
|
|
||||||
const { getIsMobile } = useAppInject();
|
|
||||||
|
|
||||||
defineProps({
|
|
||||||
sessionTimeout: {
|
/**
|
||||||
type: Boolean,
|
* 获取验证码
|
||||||
},
|
*/
|
||||||
|
function handleChangeCheckCode() {
|
||||||
|
formData.inputCode = '';
|
||||||
|
|
||||||
|
randCodeData.checkKey = 1629428467008;
|
||||||
|
getCodeInfo(randCodeData.checkKey).then((res) => {
|
||||||
|
randCodeData.randCodeImage = res;
|
||||||
|
randCodeData.requestCodeSuccess = true;
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取验证码
|
* 切换登录方式
|
||||||
*/
|
*/
|
||||||
function handleChangeCheckCode() {
|
function loginClick(type) {
|
||||||
formData.inputCode = '';
|
activeIndex.value = type;
|
||||||
|
}
|
||||||
|
|
||||||
randCodeData.checkKey = 1629428467008;
|
/**
|
||||||
getCodeInfo(randCodeData.checkKey).then((res) => {
|
* 账号或者手机登录
|
||||||
randCodeData.randCodeImage = res;
|
*/
|
||||||
randCodeData.requestCodeSuccess = true;
|
async function loginHandleClick() {
|
||||||
});
|
if (unref(activeIndex) === 'accountLogin') {
|
||||||
|
accountLogin();
|
||||||
|
} else {
|
||||||
|
//手机号登录
|
||||||
|
phoneLogin();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
async function accountLogin() {
|
||||||
* 切换登录方式
|
if (!formData.username) {
|
||||||
*/
|
createMessage.warn(t('sys.login.accountPlaceholder'));
|
||||||
function loginClick(type) {
|
return;
|
||||||
activeIndex.value = type;
|
|
||||||
}
|
}
|
||||||
|
if (!formData.password) {
|
||||||
/**
|
createMessage.warn(t('sys.login.passwordPlaceholder'));
|
||||||
* 账号或者手机登录
|
return;
|
||||||
*/
|
|
||||||
async function loginHandleClick() {
|
|
||||||
if (unref(activeIndex) === 'accountLogin') {
|
|
||||||
accountLogin();
|
|
||||||
} else {
|
|
||||||
//手机号登录
|
|
||||||
phoneLogin();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
async function accountLogin() {
|
loginLoading.value = true;
|
||||||
if (!formData.username) {
|
const { userInfo } = await userStore.login(
|
||||||
createMessage.warn(t('sys.login.accountPlaceholder'));
|
toRaw({
|
||||||
return;
|
password: formData.password,
|
||||||
}
|
username: formData.username,
|
||||||
if (!formData.password) {
|
captcha: formData.inputCode,
|
||||||
createMessage.warn(t('sys.login.passwordPlaceholder'));
|
checkKey: randCodeData.checkKey,
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
loginLoading.value = true;
|
|
||||||
const { userInfo } = await userStore.login(
|
|
||||||
toRaw({
|
|
||||||
password: formData.password,
|
|
||||||
username: formData.username,
|
|
||||||
captcha: formData.inputCode,
|
|
||||||
checkKey: randCodeData.checkKey,
|
|
||||||
mode: 'none', //不要默认的错误提示
|
|
||||||
})
|
|
||||||
);
|
|
||||||
if (userInfo) {
|
|
||||||
notification.success({
|
|
||||||
message: t('sys.login.loginSuccessTitle'),
|
|
||||||
description: `${t('sys.login.loginSuccessDesc')}: ${userInfo.realname}`,
|
|
||||||
duration: 3,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
notification.error({
|
|
||||||
message: t('sys.api.errorTip'),
|
|
||||||
description: error.message || t('sys.login.networkExceptionMsg'),
|
|
||||||
duration: 3,
|
|
||||||
});
|
|
||||||
handleChangeCheckCode();
|
|
||||||
} finally {
|
|
||||||
loginLoading.value = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 手机号登录
|
|
||||||
*/
|
|
||||||
async function phoneLogin() {
|
|
||||||
if (!phoneFormData.mobile) {
|
|
||||||
createMessage.warn(t('sys.login.mobilePlaceholder'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!phoneFormData.smscode) {
|
|
||||||
createMessage.warn(t('sys.login.smsPlaceholder'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
loginLoading.value = true;
|
|
||||||
const { userInfo }: any = await userStore.phoneLogin({
|
|
||||||
mobile: phoneFormData.mobile,
|
|
||||||
captcha: phoneFormData.smscode,
|
|
||||||
mode: 'none', //不要默认的错误提示
|
mode: 'none', //不要默认的错误提示
|
||||||
});
|
})
|
||||||
if (userInfo) {
|
);
|
||||||
notification.success({
|
if (userInfo) {
|
||||||
message: t('sys.login.loginSuccessTitle'),
|
notification.success({
|
||||||
description: `${t('sys.login.loginSuccessDesc')}: ${userInfo.realname}`,
|
message: t('sys.login.loginSuccessTitle'),
|
||||||
duration: 3,
|
description: `${t('sys.login.loginSuccessDesc')}: ${userInfo.realname}`,
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
notification.error({
|
|
||||||
message: t('sys.api.errorTip'),
|
|
||||||
description: error.message || t('sys.login.networkExceptionMsg'),
|
|
||||||
duration: 3,
|
duration: 3,
|
||||||
});
|
});
|
||||||
} finally {
|
|
||||||
loginLoading.value = false;
|
|
||||||
}
|
}
|
||||||
}
|
} catch (error) {
|
||||||
|
notification.error({
|
||||||
/**
|
message: t('sys.api.errorTip'),
|
||||||
* 获取手机验证码
|
description: error.message || t('sys.login.networkExceptionMsg'),
|
||||||
*/
|
duration: 3,
|
||||||
async function getLoginCode() {
|
});
|
||||||
if (!phoneFormData.mobile) {
|
|
||||||
createMessage.warn(t('sys.login.mobilePlaceholder'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const result = await getCaptcha({ mobile: phoneFormData.mobile, smsmode: SmsEnum.FORGET_PASSWORD });
|
|
||||||
if (result) {
|
|
||||||
const TIME_COUNT = 60;
|
|
||||||
if (!unref(timer)) {
|
|
||||||
timeRuning.value = TIME_COUNT;
|
|
||||||
showInterval.value = false;
|
|
||||||
timer.value = setInterval(() => {
|
|
||||||
if (unref(timeRuning) > 0 && unref(timeRuning) <= TIME_COUNT) {
|
|
||||||
timeRuning.value = timeRuning.value - 1;
|
|
||||||
} else {
|
|
||||||
showInterval.value = true;
|
|
||||||
clearInterval(unref(timer));
|
|
||||||
timer.value = null;
|
|
||||||
}
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 第三方登录
|
|
||||||
* @param type
|
|
||||||
*/
|
|
||||||
function onThirdLogin(type) {
|
|
||||||
thirdModalRef.value.onThirdLogin(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 忘记密码
|
|
||||||
*/
|
|
||||||
function forgetHandelClick() {
|
|
||||||
type.value = 'forgot';
|
|
||||||
setTimeout(() => {
|
|
||||||
forgotRef.value.initForm();
|
|
||||||
}, 300);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 返回登录页面
|
|
||||||
*/
|
|
||||||
function goBack() {
|
|
||||||
activeIndex.value = 'accountLogin';
|
|
||||||
type.value = 'login';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 忘记密码/注册账号回调事件
|
|
||||||
* @param value
|
|
||||||
*/
|
|
||||||
function handleSuccess(value) {
|
|
||||||
Object.assign(formData, value);
|
|
||||||
Object.assign(phoneFormData, { mobile: "", smscode: "" });
|
|
||||||
type.value = 'login';
|
|
||||||
activeIndex.value = 'accountLogin';
|
|
||||||
handleChangeCheckCode();
|
handleChangeCheckCode();
|
||||||
|
} finally {
|
||||||
|
loginLoading.value = false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注册
|
* 手机号登录
|
||||||
*/
|
*/
|
||||||
function registerHandleClick() {
|
async function phoneLogin() {
|
||||||
type.value = 'register';
|
if (!phoneFormData.mobile) {
|
||||||
setTimeout(() => {
|
createMessage.warn(t('sys.login.mobilePlaceholder'));
|
||||||
registerRef.value.initForm();
|
return;
|
||||||
}, 300);
|
|
||||||
}
|
}
|
||||||
|
if (!phoneFormData.smscode) {
|
||||||
/**
|
createMessage.warn(t('sys.login.smsPlaceholder'));
|
||||||
* 注册
|
return;
|
||||||
*/
|
|
||||||
function codeHandleClick() {
|
|
||||||
type.value = 'codeLogin';
|
|
||||||
setTimeout(() => {
|
|
||||||
codeRef.value.initFrom();
|
|
||||||
}, 300);
|
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
loginLoading.value = true;
|
||||||
|
const { userInfo }: any = await userStore.phoneLogin({
|
||||||
|
mobile: phoneFormData.mobile,
|
||||||
|
captcha: phoneFormData.smscode,
|
||||||
|
mode: 'none', //不要默认的错误提示
|
||||||
|
});
|
||||||
|
if (userInfo) {
|
||||||
|
notification.success({
|
||||||
|
message: t('sys.login.loginSuccessTitle'),
|
||||||
|
description: `${t('sys.login.loginSuccessDesc')}: ${userInfo.realname}`,
|
||||||
|
duration: 3,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
notification.error({
|
||||||
|
message: t('sys.api.errorTip'),
|
||||||
|
description: error.message || t('sys.login.networkExceptionMsg'),
|
||||||
|
duration: 3,
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
loginLoading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
/**
|
||||||
//加载验证码
|
* 获取手机验证码
|
||||||
handleChangeCheckCode();
|
*/
|
||||||
});
|
async function getLoginCode() {
|
||||||
|
if (!phoneFormData.mobile) {
|
||||||
|
createMessage.warn(t('sys.login.mobilePlaceholder'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const result = await getCaptcha({ mobile: phoneFormData.mobile, smsmode: SmsEnum.FORGET_PASSWORD });
|
||||||
|
if (result) {
|
||||||
|
const TIME_COUNT = 60;
|
||||||
|
if (!unref(timer)) {
|
||||||
|
timeRuning.value = TIME_COUNT;
|
||||||
|
showInterval.value = false;
|
||||||
|
timer.value = setInterval(() => {
|
||||||
|
if (unref(timeRuning) > 0 && unref(timeRuning) <= TIME_COUNT) {
|
||||||
|
timeRuning.value = timeRuning.value - 1;
|
||||||
|
} else {
|
||||||
|
showInterval.value = true;
|
||||||
|
clearInterval(unref(timer));
|
||||||
|
timer.value = null;
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回登录页面
|
||||||
|
*/
|
||||||
|
function goBack() {
|
||||||
|
activeIndex.value = 'accountLogin';
|
||||||
|
type.value = 'login';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 忘记密码/注册账号回调事件
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
|
function handleSuccess(value) {
|
||||||
|
Object.assign(formData, value);
|
||||||
|
Object.assign(phoneFormData, { mobile: "", smscode: "" });
|
||||||
|
type.value = 'login';
|
||||||
|
activeIndex.value = 'accountLogin';
|
||||||
|
handleChangeCheckCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册
|
||||||
|
*/
|
||||||
|
function registerHandleClick() {
|
||||||
|
type.value = 'register';
|
||||||
|
setTimeout(() => {
|
||||||
|
registerRef.value.initForm();
|
||||||
|
}, 300);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
//加载验证码
|
||||||
|
handleChangeCheckCode();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
@import '/@/assets/loginmini/style/home.less';
|
@import '/@/assets/loginmini/style/home.less';
|
||||||
@import '/@/assets/loginmini/style/base.less';
|
@import '/@/assets/loginmini/style/base.less';
|
||||||
|
|
||||||
:deep(.ant-input:focus) {
|
// 介绍文字
|
||||||
box-shadow: none;
|
.introduce-text1 {
|
||||||
}
|
font-size: 30px;
|
||||||
.aui-get-code {
|
color: #fff;
|
||||||
float: right;
|
font-weight: bold;
|
||||||
position: relative;
|
transform: translate(-50%, -50%);
|
||||||
z-index: 3;
|
}
|
||||||
background: #ffffff;
|
|
||||||
color: #1573e9;
|
|
||||||
border-radius: 100px;
|
|
||||||
padding: 5px 16px;
|
|
||||||
margin: 7px;
|
|
||||||
border: 1px solid #1573e9;
|
|
||||||
top: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.aui-get-code:hover {
|
.introduce-text {
|
||||||
color: #1573e9;
|
font-size: 40px;
|
||||||
}
|
color: #fff;
|
||||||
|
font-weight: bold;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
||||||
|
|
||||||
.code-shape {
|
:deep(.ant-input:focus) {
|
||||||
border-color: #dadada !important;
|
box-shadow: none;
|
||||||
color: #aaa !important;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.jeecg-dark-switch){
|
.aui-get-code {
|
||||||
position:absolute;
|
float: right;
|
||||||
margin-right: 10px;
|
position: relative;
|
||||||
}
|
z-index: 3;
|
||||||
.aui-link-login{
|
background: #ffffff;
|
||||||
height: 42px;
|
color: #1573e9;
|
||||||
padding: 10px 15px;
|
border-radius: 100px;
|
||||||
font-size: 14px;
|
padding: 5px 16px;
|
||||||
border-radius: 8px;
|
margin: 7px;
|
||||||
margin-top: 15px;
|
border: 1px solid #1573e9;
|
||||||
margin-bottom: 8px;
|
top: 12px;
|
||||||
flex: 1;
|
}
|
||||||
color: #fff;
|
|
||||||
}
|
.aui-get-code:hover {
|
||||||
.aui-phone-logo{
|
color: #1573e9;
|
||||||
position: absolute;
|
}
|
||||||
margin-left: 10px;
|
|
||||||
width: 60px;
|
.code-shape {
|
||||||
top:2px;
|
border-color: #dadada !important;
|
||||||
z-index: 4;
|
color: #aaa !important;
|
||||||
}
|
}
|
||||||
.top-3{
|
|
||||||
top: 0.45rem;
|
:deep(.jeecg-dark-switch) {
|
||||||
}
|
position: absolute;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aui-link-login {
|
||||||
|
height: 42px;
|
||||||
|
padding: 10px 15px;
|
||||||
|
font-size: 14px;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-top: 15px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
flex: 1;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aui-phone-logo {
|
||||||
|
position: absolute;
|
||||||
|
margin-left: 10px;
|
||||||
|
width: 60px;
|
||||||
|
top: 2px;
|
||||||
|
z-index: 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-3 {
|
||||||
|
top: 0.45rem;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
@ -486,9 +413,11 @@ html[data-theme='dark'] {
|
||||||
&::before {
|
&::before {
|
||||||
background-image: url(/@/assets/svg/login-bg-dark.svg);
|
background-image: url(/@/assets/svg/login-bg-dark.svg);
|
||||||
}
|
}
|
||||||
.aui-inputClear{
|
|
||||||
|
.aui-inputClear {
|
||||||
background-color: #232a3b !important;
|
background-color: #232a3b !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-input,
|
.ant-input,
|
||||||
.ant-input-password {
|
.ant-input-password {
|
||||||
background-color: #232a3b !important;
|
background-color: #232a3b !important;
|
||||||
|
@ -505,30 +434,39 @@ html[data-theme='dark'] {
|
||||||
.app-iconify {
|
.app-iconify {
|
||||||
color: #fff !important;
|
color: #fff !important;
|
||||||
}
|
}
|
||||||
.aui-inputClear input,.aui-input-line input,.aui-choice{
|
|
||||||
|
.aui-inputClear input,
|
||||||
|
.aui-input-line input,
|
||||||
|
.aui-choice {
|
||||||
color: #c9d1d9 !important;
|
color: #c9d1d9 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.aui-formBox{
|
.aui-formBox {
|
||||||
background-color: @dark-bg !important;
|
background-color: @dark-bg !important;
|
||||||
}
|
}
|
||||||
.aui-third-text span{
|
|
||||||
|
.aui-third-text span {
|
||||||
background-color: @dark-bg !important;
|
background-color: @dark-bg !important;
|
||||||
}
|
}
|
||||||
.aui-form-nav .aui-flex-box{
|
|
||||||
|
.aui-form-nav .aui-flex-box {
|
||||||
color: #c9d1d9 !important;
|
color: #c9d1d9 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.aui-formButton .aui-linek-code{
|
.aui-formButton .aui-linek-code {
|
||||||
background: @dark-bg !important;
|
background: @dark-bg !important;
|
||||||
color: white !important;
|
color: white !important;
|
||||||
}
|
}
|
||||||
.aui-code-line{
|
|
||||||
|
.aui-code-line {
|
||||||
border-left: none !important;
|
border-left: none !important;
|
||||||
}
|
}
|
||||||
.ant-checkbox-inner,.aui-success h3{
|
|
||||||
|
.ant-checkbox-inner,
|
||||||
|
.aui-success h3 {
|
||||||
border-color: #c9d1d9;
|
border-color: #c9d1d9;
|
||||||
}
|
}
|
||||||
|
|
||||||
//update-begin---author:wangshuai ---date:20230828 for:【QQYUN-6363】这个样式代码有问题,不在里面,导致表达式有问题------------
|
//update-begin---author:wangshuai ---date:20230828 for:【QQYUN-6363】这个样式代码有问题,不在里面,导致表达式有问题------------
|
||||||
&-sign-in-way {
|
&-sign-in-way {
|
||||||
.anticon {
|
.anticon {
|
||||||
|
@ -541,6 +479,7 @@ html[data-theme='dark'] {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//update-end---author:wangshuai ---date:20230828 for:【QQYUN-6363】这个样式代码有问题,不在里面,导致表达式有问题------------
|
//update-end---author:wangshuai ---date:20230828 for:【QQYUN-6363】这个样式代码有问题,不在里面,导致表达式有问题------------
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -554,7 +493,8 @@ html[data-theme='dark'] {
|
||||||
font-size: 12px !important;
|
font-size: 12px !important;
|
||||||
color: @text-color-secondary !important;
|
color: @text-color-secondary !important;
|
||||||
}
|
}
|
||||||
.aui-third-login a{
|
|
||||||
|
.aui-third-login a {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue