系统各配置优化

This commit is contained in:
Xubx 2025-03-04 15:47:57 +08:00
parent 0e890d96c5
commit dbc9d8b458
15 changed files with 1304 additions and 1354 deletions

2
.env
View File

@ -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

View File

@ -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>

BIN
logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

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

View File

@ -4,22 +4,23 @@
--> -->
<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
*/ */
@ -32,40 +33,43 @@
* 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{ &.jeecg-layout-mix-sider-logo,
background:@sider-logo-bg-color; &.jeecg-layout-menu-logo {
background: @sider-logo-bg-color;
} }
// &.light { // &.light {
// border-bottom: 1px solid @border-color-base; // border-bottom: 1px solid @border-color-base;
// } // }
@ -88,5 +92,5 @@
transition: all 0.5s; transition: all 0.5s;
line-height: normal; line-height: normal;
} }
} }
</style> </style>

View File

@ -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,14 +26,14 @@
</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 },
@ -115,10 +129,10 @@
handleScroll, handleScroll,
}; };
}, },
}); });
</script> </script>
<style lang="less"> <style lang="less">
.scrollbar { .scrollbar {
position: relative; position: relative;
height: 100%; height: 100%;
overflow: hidden; overflow: hidden;
@ -168,7 +182,7 @@
top: 2px; top: 2px;
width: 6px; width: 6px;
& > div { &>div {
width: 100%; width: 100%;
} }
} }
@ -177,17 +191,17 @@
left: 2px; left: 2px;
height: 6px; height: 6px;
& > div { &>div {
height: 100%; height: 100%;
} }
} }
} }
} }
.scrollbar:active > .scrollbar__bar, .scrollbar:active>.scrollbar__bar,
.scrollbar:focus > .scrollbar__bar, .scrollbar:focus>.scrollbar__bar,
.scrollbar:hover > .scrollbar__bar { .scrollbar:hover>.scrollbar__bar {
opacity: 1; opacity: 1;
transition: opacity 340ms ease-out; transition: opacity 340ms ease-out;
} }
</style> </style>

View File

@ -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,35 +28,35 @@
<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,
@ -191,12 +187,12 @@
lockActionVisible, 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;
@ -242,10 +238,11 @@
&-dropdown-overlay { &-dropdown-overlay {
// update-begin--author:liaozhiyang---date:20231226---forQQYUN-7512 // update-begin--author:liaozhiyang---date:20231226---forQQYUN-7512
width: 160px; width: 160px;
// update-end--author:liaozhiyang---date:20231226---forQQYUN-7512 // update-end--author:liaozhiyang---date:20231226---forQQYUN-7512
.ant-dropdown-menu-item { .ant-dropdown-menu-item {
min-width: 160px; min-width: 160px;
} }
} }
} }
</style> </style>

View File

@ -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,61 +19,50 @@
<!-- 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,
@ -218,15 +203,15 @@
t 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;
@ -249,10 +234,13 @@
.headerIntroductionClass { .headerIntroductionClass {
color: rgba(255, 255, 255, 0.6); color: rgba(255, 255, 255, 0.6);
} }
.anticon, .truncate {
.anticon,
.truncate {
color: rgba(255, 255, 255, 0.8); color: rgba(255, 255, 255, 0.8);
} }
} }
//update-end---author:scott ---date::2022-09-30 for-------------- //update-end---author:scott ---date::2022-09-30 for--------------
} }
</style> </style>

View File

@ -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,
// 菜单折叠 // 菜单折叠

View File

@ -1,13 +0,0 @@
<template>
<div>
<h1>学生信息</h1>
</div>
</template>
<script>
export default {
}
</script>
<style></style>

View File

@ -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>

View File

@ -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,69 +77,76 @@
<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 {
@ -171,8 +179,8 @@
handleChangeCheckCode(); handleChangeCheckCode();
//update-end-author:taoyan date:2022-5-3 for: issues/41 //update-end-author:taoyan date:2022-5-3 for: issues/41
} }
} }
function handleChangeCheckCode() { function handleChangeCheckCode() {
formData.inputCode = ''; formData.inputCode = '';
//TODO mock //TODO mock
randCodeData.checkKey = 1629428467008; //new Date().getTime(); randCodeData.checkKey = 1629428467008; //new Date().getTime();
@ -180,17 +188,17 @@
randCodeData.randCodeImage = res; randCodeData.randCodeImage = res;
randCodeData.requestCodeSuccess = true; randCodeData.requestCodeSuccess = true;
}); });
} }
/** /**
* 第三方登录 * 第三方登录
* @param type * @param type
*/ */
function onThirdLogin(type) { function onThirdLogin(type) {
thirdModalRef.value.onThirdLogin(type); thirdModalRef.value.onThirdLogin(type);
} }
// //
onMounted(() => { onMounted(() => {
handleChangeCheckCode(); handleChangeCheckCode();
}); });
</script> </script>

View File

@ -1,52 +1,53 @@
<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 class="app-loading-title">评阅人员管理系统</div>
</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(); const userStore = useUserStore();
userStore.ThirdLogin({ token, thirdType:'email', goHome: false }).then(res => { userStore.ThirdLogin({ token, thirdType: 'email', goHome: false }).then(res => {
console.log("res====>doThirdLogin",res) console.log("res====>doThirdLogin", res)
if(res && res.userInfo){ if (res && res.userInfo) {
requestSuccess(res) requestSuccess(res)
}else{ } else {
requestFailed(res) requestFailed(res)
} }
}); });
function requestFailed (err) { function requestFailed(err) {
notification.error({ notification.error({
message: '登录失败', message: '登录失败',
description: ((err.response || {}).data || {}).message || err.message || "请求出现错误,请稍后再试", description: ((err.response || {}).data || {}).message || err.message || "请求出现错误,请稍后再试",
@ -54,16 +55,16 @@
}); });
} }
function requestSuccess(res){ function requestSuccess(res) {
let info = routeQuery.info; let info = routeQuery.info;
if(info){ if (info) {
let query = JSON.parse(info); let query = JSON.parse(info);
//update-begin-author:taoyan date:2023-4-27 for: QQYUN-4882 //update-begin-author:taoyan date:2023-4-27 for: QQYUN-4882
let path = ''; let path = '';
if(query.isLowApp === 1){ if (query.isLowApp === 1) {
path = '/myapps/personalOffice/myTodo' path = '/myapps/personalOffice/myTodo'
}else{ } else {
let taskId = query.taskId; let taskId = query.taskId;
path = '/task/handle/' + taskId path = '/task/handle/' + taskId
} }
@ -75,7 +76,7 @@
description: `${t('sys.login.loginSuccessDesc')}: ${res.userInfo.realname}`, description: `${t('sys.login.loginSuccessDesc')}: ${res.userInfo.realname}`,
duration: 3, duration: 3,
}); });
}else{ } else {
notification.error({ notification.error({
message: '参数失效', message: '参数失效',
description: "页面跳转参数丢失,请查看日志", description: "页面跳转参数丢失,请查看日志",
@ -84,20 +85,19 @@
} }
} }
} }
} }
</script> </script>
<style scoped> <style scoped>
html[data-theme='dark'] .app-loading {
html[data-theme='dark'] .app-loading {
background-color: #2c344a; background-color: #2c344a;
} }
html[data-theme='dark'] .app-loading .app-loading-title { html[data-theme='dark'] .app-loading .app-loading-title {
color: rgba(255, 255, 255, 0.85); color: rgba(255, 255, 255, 0.85);
} }
.app-loading { .app-loading {
display: flex; display: flex;
width: 100%; width: 100%;
height: 100%; height: 100%;
@ -105,9 +105,9 @@
align-items: center; align-items: center;
flex-direction: column; flex-direction: column;
background-color: #f4f7f9; background-color: #f4f7f9;
} }
.app-loading .app-loading-wrap { .app-loading .app-loading-wrap {
position: absolute; position: absolute;
top: 50%; top: 50%;
left: 50%; left: 50%;
@ -117,32 +117,32 @@
justify-content: center; justify-content: center;
align-items: center; align-items: center;
flex-direction: column; flex-direction: column;
} }
.app-loading .dots { .app-loading .dots {
display: flex; display: flex;
padding: 98px; padding: 98px;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
} }
.app-loading .app-loading-title { .app-loading .app-loading-title {
display: flex; display: flex;
margin-top: 30px; margin-top: 30px;
font-size: 30px; font-size: 30px;
color: rgba(0, 0, 0, 0.85); color: rgba(0, 0, 0, 0.85);
justify-content: center; justify-content: center;
align-items: center; align-items: center;
} }
.app-loading .app-loading-logo { .app-loading .app-loading-logo {
display: block; display: block;
width: 90px; width: 90px;
margin: 0 auto; margin: 0 auto;
margin-bottom: 20px; margin-bottom: 20px;
} }
.dot { .dot {
position: relative; position: relative;
display: inline-block; display: inline-block;
width: 48px; width: 48px;
@ -152,9 +152,9 @@
transform: rotate(45deg); transform: rotate(45deg);
box-sizing: border-box; box-sizing: border-box;
animation: antRotate 1.2s infinite linear; animation: antRotate 1.2s infinite linear;
} }
.dot i { .dot i {
position: absolute; position: absolute;
display: block; display: block;
width: 20px; width: 20px;
@ -165,54 +165,57 @@
transform: scale(0.75); transform: scale(0.75);
animation: antSpinMove 1s infinite linear alternate; animation: antSpinMove 1s infinite linear alternate;
transform-origin: 50% 50%; transform-origin: 50% 50%;
} }
.dot i:nth-child(1) { .dot i:nth-child(1) {
top: 0; top: 0;
left: 0; left: 0;
} }
.dot i:nth-child(2) { .dot i:nth-child(2) {
top: 0; top: 0;
right: 0; right: 0;
-webkit-animation-delay: 0.4s; -webkit-animation-delay: 0.4s;
animation-delay: 0.4s; animation-delay: 0.4s;
} }
.dot i:nth-child(3) { .dot i:nth-child(3) {
right: 0; right: 0;
bottom: 0; bottom: 0;
-webkit-animation-delay: 0.8s; -webkit-animation-delay: 0.8s;
animation-delay: 0.8s; animation-delay: 0.8s;
} }
.dot i:nth-child(4) { .dot i:nth-child(4) {
bottom: 0; bottom: 0;
left: 0; left: 0;
-webkit-animation-delay: 1.2s; -webkit-animation-delay: 1.2s;
animation-delay: 1.2s; 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;
}
}
@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;
}
}
</style> </style>

View File

@ -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,83 +95,69 @@
</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();
const localeStore = useLocaleStore();
const showLocale = localeStore.getShowPicker;
const randCodeData = reactive<any>({
randCodeImage: '', randCodeImage: '',
requestCodeSuccess: false, requestCodeSuccess: false,
checkKey: null, checkKey: null,
}); });
const rememberMe = ref<string>('0'); //
// const activeIndex = ref<string>('accountLogin');
const activeIndex = ref<string>('accountLogin'); const type = ref<string>('login');
const type = ref<string>('login'); //
// const formData = reactive<any>({
const formData = reactive<any>({
inputCode: '', inputCode: '',
username: 'admin', username: 'admin',
password: '123456', password: '123456',
}); });
// //
const phoneFormData = reactive<any>({ const phoneFormData = reactive<any>({
mobile: '', mobile: '',
smscode: '', smscode: '',
}); });
const loginRef = ref(); const loginRef = ref();
// //
const thirdModalRef = ref(); const thirdModalRef = ref();
// //
const codeRef = ref(); const codeRef = ref();
// //
const showInterval = ref<boolean>(true); const showInterval = ref<boolean>(true);
//60s //60s
const timeRuning = ref<number>(60); const timeRuning = ref<number>(60);
// //
const timer = ref<any>(null); const timer = ref<any>(null);
// //
const forgotRef = ref(); const forgotRef = ref();
// //
const registerRef = ref(); const registerRef = ref();
const loginLoading = ref<boolean>(false); const loginLoading = ref<boolean>(false);
const { getIsMobile } = useAppInject(); const { getIsMobile } = useAppInject();
defineProps({
sessionTimeout: {
type: Boolean,
},
});
/** /**
* 获取验证码 * 获取验证码
*/ */
function handleChangeCheckCode() { function handleChangeCheckCode() {
formData.inputCode = ''; formData.inputCode = '';
randCodeData.checkKey = 1629428467008; randCodeData.checkKey = 1629428467008;
@ -231,28 +165,28 @@
randCodeData.randCodeImage = res; randCodeData.randCodeImage = res;
randCodeData.requestCodeSuccess = true; randCodeData.requestCodeSuccess = true;
}); });
} }
/** /**
* 切换登录方式 * 切换登录方式
*/ */
function loginClick(type) { function loginClick(type) {
activeIndex.value = type; activeIndex.value = type;
} }
/** /**
* 账号或者手机登录 * 账号或者手机登录
*/ */
async function loginHandleClick() { async function loginHandleClick() {
if (unref(activeIndex) === 'accountLogin') { if (unref(activeIndex) === 'accountLogin') {
accountLogin(); accountLogin();
} else { } else {
// //
phoneLogin(); phoneLogin();
} }
} }
async function accountLogin() { async function accountLogin() {
if (!formData.username) { if (!formData.username) {
createMessage.warn(t('sys.login.accountPlaceholder')); createMessage.warn(t('sys.login.accountPlaceholder'));
return; return;
@ -289,12 +223,12 @@
} finally { } finally {
loginLoading.value = false; loginLoading.value = false;
} }
} }
/** /**
* 手机号登录 * 手机号登录
*/ */
async function phoneLogin() { async function phoneLogin() {
if (!phoneFormData.mobile) { if (!phoneFormData.mobile) {
createMessage.warn(t('sys.login.mobilePlaceholder')); createMessage.warn(t('sys.login.mobilePlaceholder'));
return; return;
@ -326,12 +260,12 @@
} finally { } finally {
loginLoading.value = false; loginLoading.value = false;
} }
} }
/** /**
* 获取手机验证码 * 获取手机验证码
*/ */
async function getLoginCode() { async function getLoginCode() {
if (!phoneFormData.mobile) { if (!phoneFormData.mobile) {
createMessage.warn(t('sys.login.mobilePlaceholder')); createMessage.warn(t('sys.login.mobilePlaceholder'));
return; return;
@ -353,80 +287,70 @@
}, 1000); }, 1000);
} }
} }
} }
/**
* 第三方登录
* @param type
*/
function onThirdLogin(type) {
thirdModalRef.value.onThirdLogin(type);
}
/**
* 忘记密码
*/
function forgetHandelClick() {
type.value = 'forgot';
setTimeout(() => {
forgotRef.value.initForm();
}, 300);
}
/** /**
* 返回登录页面 * 返回登录页面
*/ */
function goBack() { function goBack() {
activeIndex.value = 'accountLogin'; activeIndex.value = 'accountLogin';
type.value = 'login'; type.value = 'login';
} }
/** /**
* 忘记密码/注册账号回调事件 * 忘记密码/注册账号回调事件
* @param value * @param value
*/ */
function handleSuccess(value) { function handleSuccess(value) {
Object.assign(formData, value); Object.assign(formData, value);
Object.assign(phoneFormData, { mobile: "", smscode: "" }); Object.assign(phoneFormData, { mobile: "", smscode: "" });
type.value = 'login'; type.value = 'login';
activeIndex.value = 'accountLogin'; activeIndex.value = 'accountLogin';
handleChangeCheckCode(); handleChangeCheckCode();
} }
/** /**
* 注册 * 注册
*/ */
function registerHandleClick() { function registerHandleClick() {
type.value = 'register'; type.value = 'register';
setTimeout(() => { setTimeout(() => {
registerRef.value.initForm(); registerRef.value.initForm();
}, 300); }, 300);
} }
/**
* 注册
*/
function codeHandleClick() {
type.value = 'codeLogin';
setTimeout(() => {
codeRef.value.initFrom();
}, 300);
}
onMounted(() => { onMounted(() => {
// //
handleChangeCheckCode(); 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) { //
.introduce-text1 {
font-size: 30px;
color: #fff;
font-weight: bold;
transform: translate(-50%, -50%);
}
.introduce-text {
font-size: 40px;
color: #fff;
font-weight: bold;
transform: translate(-50%, -50%);
}
:deep(.ant-input:focus) {
box-shadow: none; box-shadow: none;
} }
.aui-get-code {
.aui-get-code {
float: right; float: right;
position: relative; position: relative;
z-index: 3; z-index: 3;
@ -437,22 +361,23 @@
margin: 7px; margin: 7px;
border: 1px solid #1573e9; border: 1px solid #1573e9;
top: 12px; top: 12px;
} }
.aui-get-code:hover { .aui-get-code:hover {
color: #1573e9; color: #1573e9;
} }
.code-shape { .code-shape {
border-color: #dadada !important; border-color: #dadada !important;
color: #aaa !important; color: #aaa !important;
} }
:deep(.jeecg-dark-switch){ :deep(.jeecg-dark-switch) {
position:absolute; position: absolute;
margin-right: 10px; margin-right: 10px;
} }
.aui-link-login{
.aui-link-login {
height: 42px; height: 42px;
padding: 10px 15px; padding: 10px 15px;
font-size: 14px; font-size: 14px;
@ -461,17 +386,19 @@
margin-bottom: 8px; margin-bottom: 8px;
flex: 1; flex: 1;
color: #fff; color: #fff;
} }
.aui-phone-logo{
.aui-phone-logo {
position: absolute; position: absolute;
margin-left: 10px; margin-left: 10px;
width: 60px; width: 60px;
top:2px; top: 2px;
z-index: 4; z-index: 4;
} }
.top-3{
.top-3 {
top: 0.45rem; 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 forQQYUN-6363------------ //update-begin---author:wangshuai ---date:20230828 forQQYUN-6363------------
&-sign-in-way { &-sign-in-way {
.anticon { .anticon {
@ -541,6 +479,7 @@ html[data-theme='dark'] {
} }
} }
} }
//update-end---author:wangshuai ---date:20230828 forQQYUN-6363------------ //update-end---author:wangshuai ---date:20230828 forQQYUN-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;
} }
} }