|
@@ -0,0 +1,549 @@
|
|
|
+<template>
|
|
|
+ <div class="login-container flex z-10">
|
|
|
+ <div class="login-left">
|
|
|
+ <div class="login-left-logo">
|
|
|
+ <img :src="siteLogo" /><!-- siteLogo -->
|
|
|
+ <div class="login-left-logo-text">
|
|
|
+ <span>{{ getSystemConfig['login.site_title'] || getThemeConfig.globalViceTitle }}</span><!-- -->
|
|
|
+ <span class="login-left-logo-text-msg" style="margin-top: 5px">{{
|
|
|
+ getSystemConfig['login.site_name'] || getThemeConfig.globalViceTitleMsg
|
|
|
+ }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="login-right flex z-10">
|
|
|
+ <div class="login-right-warp flex-margin">
|
|
|
+ <!-- <span class="login-right-warp-one"></span>-->
|
|
|
+ <!-- <span class="login-right-warp-two"></span>-->
|
|
|
+ <div class="login-right-warp-mian">
|
|
|
+ <div class="login-right-warp-main-title">
|
|
|
+ 超级管理员登陆
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="login-right-warp-main-form pt-4">
|
|
|
+ <el-form ref="superformRef" size="large" class="login-content-form" :model="superForm"
|
|
|
+ :rules="superRules" @keyup.enter="loginClick">
|
|
|
+ <el-form-item class="login-animation1" prop="username">
|
|
|
+ <el-input type="text" placeholder="请输入登录账号" v-model="superForm.username" clearable>
|
|
|
+ <template #prefix>
|
|
|
+ <el-icon class="el-input__icon"><ele-User /></el-icon>
|
|
|
+ </template>
|
|
|
+ </el-input>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item class="login-animation2" prop="password">
|
|
|
+ <el-input :type="isShowPassword ? 'text' : 'password'"
|
|
|
+ :placeholder="$t('message.account.accountPlaceholder4')"
|
|
|
+ v-model="superForm.password">
|
|
|
+ <template #prefix>
|
|
|
+ <el-icon class="el-input__icon"><ele-Unlock /></el-icon>
|
|
|
+ </template>
|
|
|
+ <template #suffix>
|
|
|
+ <i class="iconfont el-input__icon login-content-password"
|
|
|
+ :class="isShowPassword ? 'icon-yincangmima' : 'icon-xianshimima'"
|
|
|
+ @click="isShowPassword = !isShowPassword">
|
|
|
+ </i>
|
|
|
+ </template>
|
|
|
+ </el-input>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item class="login-animation3" v-if="isShowCaptcha" prop="captcha">
|
|
|
+ <el-col :span="15">
|
|
|
+ <el-input type="text" maxlength="4"
|
|
|
+ :placeholder="$t('message.account.accountPlaceholder3')"
|
|
|
+ v-model="superForm.captcha" clearable autocomplete="off">
|
|
|
+ <template #prefix>
|
|
|
+ <el-icon class="el-input__icon"><ele-Position /></el-icon>
|
|
|
+ </template>
|
|
|
+ </el-input>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="1"></el-col>
|
|
|
+ <el-col :span="8">
|
|
|
+ <el-button class="login-content-captcha">
|
|
|
+ <el-image :src="superForm.captchaImgBase" @click="refreshCaptcha" />
|
|
|
+ </el-button>
|
|
|
+ </el-col>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item class="login-animation4">
|
|
|
+ <el-button type="primary" class="login-content-submit w-full" round @click="loginClick"
|
|
|
+ :loading="loading.signIn">
|
|
|
+ <span>{{ $t('message.account.accountBtnText') }}</span>
|
|
|
+ </el-button>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="login-authorization z-10">
|
|
|
+ <!-- <p>Copyright © {{ getSystemConfig['login.copyright'] || '2021-2024 北京信码新创科技有限公司' }} 版权所有</p> -->
|
|
|
+ <!-- <p class="la-other" style="margin-top: 5px">
|
|
|
+ <a href="https://beian.miit.gov.cn" target="_blank">{{ getSystemConfig['login.keep_record'] || '京ICP备2021031018号' }}</a>
|
|
|
+ |
|
|
|
+ <a :href="getSystemConfig['login.help_url'] ? getSystemConfig['login.help_url'] : '#'" target="_blank">帮助</a>
|
|
|
+ |
|
|
|
+ <a :href="getSystemConfig['login.privacy_url'] ? getBaseURL(getSystemConfig['login.privacy_url']) : '#'">隐私</a>
|
|
|
+ |
|
|
|
+ <a :href="getSystemConfig['login.clause_url'] ? getBaseURL(getSystemConfig['login.clause_url']) : '#'">条款</a>
|
|
|
+ </p> -->
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div v-if="loginBg">
|
|
|
+ <img :src="loginBg" class="loginBg fixed inset-0 z-1 w-full h-full" />
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup lang="ts" name="loginIndex">
|
|
|
+import { defineAsyncComponent, onMounted, reactive, computed, watch, ref } from 'vue';
|
|
|
+import { storeToRefs } from 'pinia';
|
|
|
+import { useThemeConfig } from '/@/stores/themeConfig';
|
|
|
+import { NextLoading } from '/@/utils/loading';
|
|
|
+import logoMini from '/@/assets/logo-mini.svg';
|
|
|
+import loginMain from '/@/assets/login-main.svg';
|
|
|
+import loginBg from '/@/assets/login_background.jpg';
|
|
|
+import { SystemConfigStore } from '/@/stores/systemConfig';
|
|
|
+import { getBaseURL } from '/@/utils/baseUrl';
|
|
|
+import { useI18n } from 'vue-i18n';
|
|
|
+import * as api from './api';
|
|
|
+import * as loginApi from '/@/views/system/login/api';
|
|
|
+import { useUserInfo } from '/@/stores/userInfo';
|
|
|
+import { ElMessage } from 'element-plus';
|
|
|
+import { useRouter } from 'vue-router';
|
|
|
+import { Md5 } from 'ts-md5';
|
|
|
+import Cookies from 'js-cookie';
|
|
|
+import { Session } from '/@/utils/storage';
|
|
|
+import * as _ from 'lodash-es';
|
|
|
+
|
|
|
+// 引入组件
|
|
|
+const Account = defineAsyncComponent(() => import('/@/views/system/login/component/account.vue'));
|
|
|
+const Mobile = defineAsyncComponent(() => import('/@/views/system/login/component/mobile.vue'));
|
|
|
+const Scan = defineAsyncComponent(() => import('/@/views/system/login/component/scan.vue'));
|
|
|
+const ChangePwd = defineAsyncComponent(() => import('/@/views/system/login/component/changePwd.vue'));
|
|
|
+const { userInfos } = storeToRefs(useUserInfo());
|
|
|
+
|
|
|
+// 定义变量内容
|
|
|
+const storesThemeConfig = useThemeConfig();
|
|
|
+const { themeConfig } = storeToRefs(storesThemeConfig);
|
|
|
+const state = reactive({
|
|
|
+ tabsActiveName: 'account',
|
|
|
+ isScan: false,
|
|
|
+});
|
|
|
+const { t } = useI18n();
|
|
|
+watch(
|
|
|
+ () => userInfos.value.pwd_change_count,
|
|
|
+ (val) => {
|
|
|
+ if (val === 0) {
|
|
|
+ state.tabsActiveName = 'changePwd';
|
|
|
+ } else {
|
|
|
+ state.tabsActiveName = 'account';
|
|
|
+ }
|
|
|
+ },
|
|
|
+ { deep: true, immediate: true }
|
|
|
+);
|
|
|
+
|
|
|
+// 获取布局配置信息
|
|
|
+const getThemeConfig = computed(() => {
|
|
|
+ return themeConfig.value;
|
|
|
+});
|
|
|
+
|
|
|
+const systemConfigStore = SystemConfigStore();
|
|
|
+const { systemConfig } = storeToRefs(systemConfigStore);
|
|
|
+const getSystemConfig = computed(() => {
|
|
|
+ return systemConfig.value;
|
|
|
+});
|
|
|
+
|
|
|
+const siteLogo = computed(() => {
|
|
|
+ if (!_.isEmpty(getSystemConfig.value['login.site_logo'])) {
|
|
|
+ return getSystemConfig.value['login.site_logo'];
|
|
|
+ }
|
|
|
+ return logoMini;
|
|
|
+});
|
|
|
+
|
|
|
+const siteBg = computed(() => {
|
|
|
+ if (!_.isEmpty(getSystemConfig.value['login.login_background'])) {
|
|
|
+ return getSystemConfig.value['login.login_background'];
|
|
|
+ }
|
|
|
+});
|
|
|
+const superLogin = ref(true);
|
|
|
+
|
|
|
+// 添加loading状态
|
|
|
+const loading = reactive({
|
|
|
+ signIn: false,
|
|
|
+});
|
|
|
+/* 超级管理员登录表单 */
|
|
|
+const superForm = ref({
|
|
|
+ username: '', // 设置默认用户名
|
|
|
+ password: '',
|
|
|
+ captcha: '',
|
|
|
+ captchaKey: '',
|
|
|
+ captchaImgBase: '',
|
|
|
+});
|
|
|
+// 添加表单校验规则
|
|
|
+const superRules = reactive({
|
|
|
+ username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
|
|
|
+ password: [
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ message: '请填写密码',
|
|
|
+ trigger: 'blur',
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ captcha: [
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ message: '请填写验证码',
|
|
|
+ trigger: 'blur',
|
|
|
+ },
|
|
|
+ ],
|
|
|
+});
|
|
|
+
|
|
|
+const superformRef = ref();
|
|
|
+const router = useRouter();
|
|
|
+const formRef = ref();
|
|
|
+
|
|
|
+// 添加 formatAxis 函数定义
|
|
|
+const formatAxis = (date: Date): string => {
|
|
|
+ const hours = date.getHours();
|
|
|
+ const minutes = date.getMinutes();
|
|
|
+ // 格式化时间为 HH:MM 格式
|
|
|
+ return `${hours < 10 ? '0' + hours : hours}:${minutes < 10 ? '0' + minutes : minutes}`;
|
|
|
+};
|
|
|
+
|
|
|
+// 时间获取
|
|
|
+const currentTime = computed(() => {
|
|
|
+ return formatAxis(new Date());
|
|
|
+});
|
|
|
+
|
|
|
+// 是否关闭验证码
|
|
|
+const isShowCaptcha = computed(() => {
|
|
|
+ return SystemConfigStore().systemConfig['base.captcha_state'];
|
|
|
+});
|
|
|
+
|
|
|
+const getCaptcha = async () => {
|
|
|
+ loginApi.getCaptcha().then((ret: any) => {
|
|
|
+ console.log(ret);
|
|
|
+ superForm.value.captchaImgBase = ret.data.image_base;
|
|
|
+ superForm.value.captchaKey = ret.data.key;
|
|
|
+ console.log(superForm);
|
|
|
+ });
|
|
|
+};
|
|
|
+const applyBtnClick = async () => {
|
|
|
+ window.open(getBaseURL('/api/system/apply_for_trial/'));
|
|
|
+};
|
|
|
+const refreshCaptcha = async () => {
|
|
|
+ superForm.value.captcha = '';
|
|
|
+ loginApi.getCaptcha().then((ret: any) => {
|
|
|
+ superForm.value.captchaImgBase = ret.data.image_base;
|
|
|
+ superForm.value.captchaKey = ret.data.key;
|
|
|
+ });
|
|
|
+};
|
|
|
+// 添加登录方法
|
|
|
+const loginClick = async () => {
|
|
|
+ if (!superformRef.value) return;
|
|
|
+ await superformRef.value.validate(async (valid: boolean) => {
|
|
|
+ if (valid) {
|
|
|
+ try {
|
|
|
+ loading.signIn = true;
|
|
|
+ // 创建一个简单的登录数据对象,避免直接使用响应式对象
|
|
|
+ const loginData = {
|
|
|
+ username: superForm.value.username,
|
|
|
+ password: superForm.value.password,
|
|
|
+ captcha: superForm.value.captcha,
|
|
|
+ captchaKey: superForm.value.captchaKey,
|
|
|
+ captchaImgBase: superForm.value.captchaImgBase,
|
|
|
+ };
|
|
|
+ /* const res = */
|
|
|
+ loginApi.login({ ...loginData, password: Md5.hashStr(loginData.password) }).then((res: any) => {
|
|
|
+ console.log(res);
|
|
|
+ if (res?.code === 2000) {
|
|
|
+ ElMessage.success('登录成功');
|
|
|
+ Cookies.set('username', res.data.username);
|
|
|
+ Session.set('token', res.data.access);
|
|
|
+ Session.set('superKey',res.data.role_info[0].key)
|
|
|
+ Session.set('merchant_info', res.data.merchant_info);
|
|
|
+ router.push('/');
|
|
|
+ } else {
|
|
|
+ ElMessage.error(res?.msg || '登录失败');
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ } catch (error: any) {
|
|
|
+ console.error('登录失败:', error);
|
|
|
+ ElMessage.error(error?.message || '登录失败,请稍后重试');
|
|
|
+ } finally {
|
|
|
+ loading.signIn = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+const isShowPassword = ref(false);
|
|
|
+/* 跳转至超级管理员登录 */
|
|
|
+const goSuper = async () => {
|
|
|
+ superLogin.value = !superLogin.value;
|
|
|
+};
|
|
|
+
|
|
|
+// 页面加载时
|
|
|
+onMounted(() => {
|
|
|
+ getCaptcha();
|
|
|
+ NextLoading.done();
|
|
|
+});
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped lang="scss">
|
|
|
+.login-container {
|
|
|
+ height: 100%;
|
|
|
+ background: var(--el-color-white);
|
|
|
+
|
|
|
+ .login-left {
|
|
|
+ flex: 1;
|
|
|
+ position: relative;
|
|
|
+ background-color: rgba(211, 239, 255, 1);
|
|
|
+ margin-right: 100px;
|
|
|
+
|
|
|
+ .login-left-logo {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ position: absolute;
|
|
|
+ top: 50px;
|
|
|
+ left: 80px;
|
|
|
+ z-index: 1;
|
|
|
+ animation: logoAnimation 0.3s ease;
|
|
|
+
|
|
|
+ img {
|
|
|
+ width: 52px;
|
|
|
+ height: 52px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .login-left-logo-text {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+
|
|
|
+ span {
|
|
|
+ margin-left: 10px;
|
|
|
+ font-size: 16px;
|
|
|
+ color: var(--el-color-primary);
|
|
|
+ }
|
|
|
+
|
|
|
+ .login-left-logo-text-msg {
|
|
|
+ font-size: 12px;
|
|
|
+ color: var(--el-color-primary);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .login-left-img {
|
|
|
+ position: absolute;
|
|
|
+ top: 50%;
|
|
|
+ left: 50%;
|
|
|
+ transform: translate(-50%, -50%);
|
|
|
+ width: 100%;
|
|
|
+ height: 52%;
|
|
|
+
|
|
|
+ img {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ animation: error-num 0.6s ease;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .login-left-waves {
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ right: -100px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .login-right {
|
|
|
+ width: 700px;
|
|
|
+
|
|
|
+ .login-right-warp {
|
|
|
+ //border: 1px solid var(--el-color-primary-light-3);
|
|
|
+ border-radius: 10px;
|
|
|
+ width: 450px;
|
|
|
+ height: 501px;
|
|
|
+ position: relative;
|
|
|
+ overflow: hidden;
|
|
|
+ //background-color: var(--el-color-white);
|
|
|
+
|
|
|
+ .login-right-warp-one,
|
|
|
+ .login-right-warp-two {
|
|
|
+ position: absolute;
|
|
|
+ display: block;
|
|
|
+ width: inherit;
|
|
|
+ height: inherit;
|
|
|
+
|
|
|
+ &::before,
|
|
|
+ &::after {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ z-index: 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .login-right-warp-one {
|
|
|
+ &::before {
|
|
|
+ filter: hue-rotate(0deg);
|
|
|
+ top: 0px;
|
|
|
+ left: 0;
|
|
|
+ width: 100%;
|
|
|
+ height: 3px;
|
|
|
+ background: linear-gradient(90deg, transparent, var(--el-color-primary));
|
|
|
+ animation: loginLeft 3s linear infinite;
|
|
|
+ }
|
|
|
+
|
|
|
+ &::after {
|
|
|
+ filter: hue-rotate(60deg);
|
|
|
+ top: -100%;
|
|
|
+ right: 2px;
|
|
|
+ width: 3px;
|
|
|
+ height: 100%;
|
|
|
+ background: linear-gradient(180deg, transparent, var(--el-color-primary));
|
|
|
+ animation: loginTop 3s linear infinite;
|
|
|
+ animation-delay: 0.7s;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .login-right-warp-two {
|
|
|
+ &::before {
|
|
|
+ filter: hue-rotate(120deg);
|
|
|
+ bottom: 2px;
|
|
|
+ right: -100%;
|
|
|
+ width: 100%;
|
|
|
+ height: 3px;
|
|
|
+ background: linear-gradient(270deg, transparent, var(--el-color-primary));
|
|
|
+ animation: loginRight 3s linear infinite;
|
|
|
+ animation-delay: 1.4s;
|
|
|
+ }
|
|
|
+
|
|
|
+ &::after {
|
|
|
+ filter: hue-rotate(300deg);
|
|
|
+ bottom: -100%;
|
|
|
+ left: 0px;
|
|
|
+ width: 3px;
|
|
|
+ height: 100%;
|
|
|
+ background: linear-gradient(360deg, transparent, var(--el-color-primary));
|
|
|
+ animation: loginBottom 3s linear infinite;
|
|
|
+ animation-delay: 2.1s;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .login-right-warp-mian {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ height: 100%;
|
|
|
+ background: #fff;
|
|
|
+
|
|
|
+ .login-right-warp-main-title {
|
|
|
+ height: 130px;
|
|
|
+ line-height: 130px;
|
|
|
+ font-size: 32px;
|
|
|
+ font-weight: 600;
|
|
|
+ text-align: center;
|
|
|
+ letter-spacing: 3px;
|
|
|
+ animation: logoAnimation 0.3s ease;
|
|
|
+ animation-delay: 0.3s;
|
|
|
+ color: var(--el-text-color-primary);
|
|
|
+ }
|
|
|
+
|
|
|
+ .login-right-warp-main-form {
|
|
|
+ flex: 1;
|
|
|
+ padding: 0 50px 50px;
|
|
|
+
|
|
|
+ .login-content-main-sacn {
|
|
|
+ position: absolute;
|
|
|
+ top: 2px;
|
|
|
+ right: 12px;
|
|
|
+ width: 50px;
|
|
|
+ height: 50px;
|
|
|
+ overflow: hidden;
|
|
|
+ cursor: pointer;
|
|
|
+ transition: all ease 0.3s;
|
|
|
+ color: var(--el-color-primary);
|
|
|
+
|
|
|
+ &-delta {
|
|
|
+ position: absolute;
|
|
|
+ width: 35px;
|
|
|
+ height: 70px;
|
|
|
+ z-index: 2;
|
|
|
+ top: 2px;
|
|
|
+ right: 21px;
|
|
|
+ background: var(--el-color-white);
|
|
|
+ transform: rotate(-45deg);
|
|
|
+ }
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ opacity: 1;
|
|
|
+ transition: all ease 0.3s;
|
|
|
+ color: var(--el-color-primary) !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ i {
|
|
|
+ width: 47px;
|
|
|
+ height: 50px;
|
|
|
+ display: inline-block;
|
|
|
+ font-size: 48px;
|
|
|
+ position: absolute;
|
|
|
+ right: 1px;
|
|
|
+ top: 0px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .login-authorization {
|
|
|
+ position: absolute;
|
|
|
+ bottom: 30px;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ text-align: center;
|
|
|
+
|
|
|
+ p {
|
|
|
+ font-size: 14px;
|
|
|
+ color: rgba(0, 0, 0, 0.5);
|
|
|
+ }
|
|
|
+
|
|
|
+ a {
|
|
|
+ color: var(--el-color-primary);
|
|
|
+ margin: 0 5px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.login-content-form {
|
|
|
+ @for $i from 1 through 4 {
|
|
|
+ .login-animation#{$i} {
|
|
|
+ opacity: 0;
|
|
|
+ animation-name: error-num;
|
|
|
+ animation-duration: 0.5s;
|
|
|
+ animation-fill-mode: forwards;
|
|
|
+ animation-delay: calc($i/10) + s;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .login-content-password {
|
|
|
+ display: inline-block;
|
|
|
+ width: 20px;
|
|
|
+ cursor: pointer;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ color: #909399;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .login-content-captcha {
|
|
|
+ width: 100%;
|
|
|
+ padding: 0;
|
|
|
+ font-weight: bold;
|
|
|
+ letter-spacing: 5px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .login-content-submit {
|
|
|
+ width: 100%;
|
|
|
+ letter-spacing: 2px;
|
|
|
+ font-weight: 800;
|
|
|
+ margin-top: 15px;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|