|
@@ -1,272 +1,267 @@
|
|
|
<template>
|
|
|
- <el-form size="large" class="login-content-form">
|
|
|
- <el-form-item class="login-animation1">
|
|
|
- <el-input text :placeholder="$t('message.account.accountPlaceholder1')" v-model="state.ruleForm.phone" clearable autocomplete="off">
|
|
|
- <template #prefix>
|
|
|
- <el-icon class="el-input__icon"><ele-User /></el-icon>
|
|
|
- </template>
|
|
|
- </el-input>
|
|
|
- </el-form-item>
|
|
|
- <el-form-item class="login-animation2">
|
|
|
- <el-input
|
|
|
- :type="state.isShowPassword ? 'text' : 'password'"
|
|
|
- :placeholder="$t('message.account.accountPlaceholder2')"
|
|
|
- v-model="state.ruleForm.password"
|
|
|
- autocomplete="off"
|
|
|
- >
|
|
|
- <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="state.isShowPassword ? 'icon-yincangmima' : 'icon-xianshimima'"
|
|
|
- @click="state.isShowPassword = !state.isShowPassword"
|
|
|
- >
|
|
|
- </i>
|
|
|
- </template>
|
|
|
- </el-input>
|
|
|
- </el-form-item>
|
|
|
- <el-form-item class="login-animation3">
|
|
|
- <el-col :span="15">
|
|
|
- <el-input
|
|
|
- text
|
|
|
- maxlength="4"
|
|
|
- :placeholder="$t('message.account.accountPlaceholder3')"
|
|
|
- v-model="state.ruleForm.code"
|
|
|
- clearable
|
|
|
- autocomplete="off"
|
|
|
- @keyup.enter="onSignInThor"
|
|
|
- >
|
|
|
- <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-code" v-waves @click="flushCode()">{{ state.codeNum }}</el-button>
|
|
|
- </el-col>
|
|
|
- </el-form-item>
|
|
|
+ <el-form size="large" class="login-content-form">
|
|
|
+ <el-form-item class="login-animation1">
|
|
|
+ <el-input text :placeholder="$t('message.account.accountPlaceholder1')" v-model="state.ruleForm.phone" clearable
|
|
|
+ autocomplete="off">
|
|
|
+ <template #prefix>
|
|
|
+ <el-icon class="el-input__icon"><ele-User /></el-icon>
|
|
|
+ </template>
|
|
|
+ </el-input>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item class="login-animation2">
|
|
|
+ <el-input :type="state.isShowPassword ? 'text' : 'password'"
|
|
|
+ :placeholder="$t('message.account.accountPlaceholder2')" v-model="state.ruleForm.password"
|
|
|
+ autocomplete="off">
|
|
|
+ <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="state.isShowPassword ? 'icon-yincangmima' : 'icon-xianshimima'"
|
|
|
+ @click="state.isShowPassword = !state.isShowPassword">
|
|
|
+ </i>
|
|
|
+ </template>
|
|
|
+ </el-input>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item class="login-animation3">
|
|
|
+ <el-col :span="15">
|
|
|
+ <el-input text maxlength="4" :placeholder="$t('message.account.accountPlaceholder3')"
|
|
|
+ v-model="state.ruleForm.code" clearable autocomplete="off" @keyup.enter="signInThor">
|
|
|
+ <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-code" v-waves @click="flushCode()">{{ state.codeNum }}</el-button>
|
|
|
+ </el-col>
|
|
|
+ </el-form-item>
|
|
|
|
|
|
- <!-- 记住账号和密码 -->
|
|
|
- <view class="checked-box">
|
|
|
- <el-checkbox v-model="state.checked1" label="记住账号和密码" size="large" />
|
|
|
- </view>
|
|
|
+ <!-- 记住账号和密码 -->
|
|
|
+ <view class="checked-box">
|
|
|
+ <el-checkbox v-model="state.checked1" label="记住账号和密码" size="large" />
|
|
|
+ </view>
|
|
|
|
|
|
- <el-form-item class="login-animation4">
|
|
|
- <el-button type="primary" class="login-content-submit" round v-waves @click="onSignInThor" :loading="state.loading.signIn">
|
|
|
- <span>{{ $t('message.account.accountBtnText') }}</span>
|
|
|
- </el-button>
|
|
|
- </el-form-item>
|
|
|
- </el-form>
|
|
|
+ <el-form-item class="login-animation4">
|
|
|
+ <el-button type="primary" class="login-content-submit" round v-waves @click="signInThor"
|
|
|
+ :loading="state.loading.signIn">
|
|
|
+ <span>{{ $t('message.account.accountBtnText') }}</span>
|
|
|
+ </el-button>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts" name="loginAccount">
|
|
|
-import { reactive, computed, onMounted, watch } from 'vue';
|
|
|
-import { useRoute, useRouter } from 'vue-router';
|
|
|
-import { ElMessage } from 'element-plus';
|
|
|
-import { useI18n } from 'vue-i18n';
|
|
|
-import Cookies from 'js-cookie';
|
|
|
-import { storeToRefs } from 'pinia';
|
|
|
-import { useThemeConfig } from '/@/stores/themeConfig';
|
|
|
-import { initFrontEndControlRoutes } from '/@/router/frontEnd';
|
|
|
-import { initBackEndControlRoutes } from '/@/router/backEnd';
|
|
|
-import { Session } from '/@/utils/storage';
|
|
|
-import { formatAxis } from '/@/utils/formatTime';
|
|
|
-import { NextLoading } from '/@/utils/loading';
|
|
|
-import Login from '/@/api/login/login';
|
|
|
-import { debounce, throttle } from 'lodash';
|
|
|
-// import { setBackEndControlRefreshRoutes } from "/@/router/backEnd";
|
|
|
+import { reactive, computed, onMounted, watch, provide } from 'vue';
|
|
|
+import { useRoute, useRouter } from 'vue-router'
|
|
|
+import { ElMessage } from 'element-plus'
|
|
|
+import { useI18n } from 'vue-i18n'
|
|
|
+import Cookies from 'js-cookie'
|
|
|
+import { storeToRefs } from 'pinia'
|
|
|
+import { useThemeConfig } from '/@/stores/themeConfig'
|
|
|
+import { initFrontEndControlRoutes } from '/@/router/frontEnd'
|
|
|
+import { initBackEndControlRoutes } from '/@/router/backEnd'
|
|
|
+import { Session } from '/@/utils/storage'
|
|
|
+import { formatAxis } from '/@/utils/formatTime'
|
|
|
+import { NextLoading } from '/@/utils/loading'
|
|
|
+import Login from '/@/api/login/login'
|
|
|
+import { throttle } from 'lodash'
|
|
|
|
|
|
// 定义变量内容
|
|
|
-const { t } = useI18n();
|
|
|
-const storesThemeConfig = useThemeConfig();
|
|
|
-const { themeConfig } = storeToRefs(storesThemeConfig);
|
|
|
-const route = useRoute();
|
|
|
-const router = useRouter();
|
|
|
+const { t } = useI18n()
|
|
|
+const storesThemeConfig = useThemeConfig()
|
|
|
+const { themeConfig } = storeToRefs(storesThemeConfig)
|
|
|
+const route = useRoute()
|
|
|
+const router = useRouter()
|
|
|
const state = reactive({
|
|
|
- isShowPassword: false,
|
|
|
- ruleForm: {
|
|
|
- phone: '',
|
|
|
- password: '',
|
|
|
- code: '',
|
|
|
- },
|
|
|
- codeNum: '',
|
|
|
- loading: {
|
|
|
- signIn: false,
|
|
|
- },
|
|
|
- checked1: false,
|
|
|
-});
|
|
|
+ isShowPassword: false,
|
|
|
+ ruleForm: {
|
|
|
+ phone: '',
|
|
|
+ password: '',
|
|
|
+ code: '',
|
|
|
+ },
|
|
|
+ codeNum: '',
|
|
|
+ loading: {
|
|
|
+ signIn: false,
|
|
|
+ },
|
|
|
+ checked1: false,
|
|
|
+})
|
|
|
|
|
|
// 读取缓存
|
|
|
-let user_name = localStorage.getItem('user_name');
|
|
|
-let pass_word = localStorage.getItem('pass_word');
|
|
|
+let user_name = localStorage.getItem('user_name')
|
|
|
+let pass_word = localStorage.getItem('pass_word')
|
|
|
if (user_name) {
|
|
|
- state.ruleForm.phone = user_name;
|
|
|
- state.checked1 = true;
|
|
|
- console.log('state.checked1', state.checked1);
|
|
|
+ state.ruleForm.phone = user_name
|
|
|
+ state.checked1 = true
|
|
|
+ console.log('state.checked1', state.checked1)
|
|
|
}
|
|
|
if (pass_word) {
|
|
|
- state.ruleForm.password = pass_word;
|
|
|
+ state.ruleForm.password = pass_word
|
|
|
}
|
|
|
// 监视是否勾选记住账号和密码
|
|
|
watch(
|
|
|
- () => state.checked1,
|
|
|
- (newValue, oldValue) => {
|
|
|
- console.log(newValue, oldValue);
|
|
|
- // 清除缓存
|
|
|
- if (newValue == false) {
|
|
|
- let user_name = localStorage.getItem('user_name');
|
|
|
- let pass_word = localStorage.getItem('pass_word');
|
|
|
- if (user_name) {
|
|
|
- localStorage.removeItem('user_name');
|
|
|
- }
|
|
|
- if (pass_word) {
|
|
|
- localStorage.removeItem('pass_word');
|
|
|
- }
|
|
|
- }
|
|
|
- if (newValue == true) {
|
|
|
- localStorage.setItem('user_name', state.ruleForm.phone);
|
|
|
- localStorage.setItem('pass_word', state.ruleForm.password);
|
|
|
- }
|
|
|
- }
|
|
|
-);
|
|
|
+ () => state.checked1,
|
|
|
+ (newValue, oldValue) => {
|
|
|
+ console.log(newValue, oldValue)
|
|
|
+ // 清除缓存
|
|
|
+ if (newValue == false) {
|
|
|
+ let user_name = localStorage.getItem('user_name')
|
|
|
+ let pass_word = localStorage.getItem('pass_word')
|
|
|
+ if (user_name) {
|
|
|
+ localStorage.removeItem('user_name')
|
|
|
+ }
|
|
|
+ if (pass_word) {
|
|
|
+ localStorage.removeItem('pass_word')
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (newValue == true) {
|
|
|
+ localStorage.setItem('user_name', state.ruleForm.phone)
|
|
|
+ localStorage.setItem('pass_word', state.ruleForm.password)
|
|
|
+ }
|
|
|
+ }
|
|
|
+)
|
|
|
|
|
|
onMounted(() => {
|
|
|
- flushCode();
|
|
|
-});
|
|
|
+ flushCode()
|
|
|
+})
|
|
|
|
|
|
+/**
|
|
|
+ * 刷新验证码
|
|
|
+ */
|
|
|
const flushCode = () => {
|
|
|
- state.codeNum = '';
|
|
|
- for (let i = 0; i < 4; i++) {
|
|
|
- state.codeNum += Number(9 * Math.random()).toFixed(0);
|
|
|
- }
|
|
|
- console.log(state.codeNum);
|
|
|
-};
|
|
|
+ state.codeNum = ''
|
|
|
+ for (let i = 0; i < 4; i++) {
|
|
|
+ state.codeNum += Number(9 * Math.random()).toFixed(0)
|
|
|
+ }
|
|
|
+ console.log(state.codeNum)
|
|
|
+}
|
|
|
|
|
|
-// 时间获取
|
|
|
+/**
|
|
|
+* 时间获取
|
|
|
+*/
|
|
|
const currentTime = computed(() => {
|
|
|
- return formatAxis(new Date());
|
|
|
-});
|
|
|
+ return formatAxis(new Date())
|
|
|
+})
|
|
|
|
|
|
/**
|
|
|
* 登录
|
|
|
*/
|
|
|
-const onSignIn = async () => {
|
|
|
- if (state.ruleForm.code != state.codeNum) {
|
|
|
- return ElMessage.error('验证码不正确');
|
|
|
- }
|
|
|
- let res = await Login.login(state.ruleForm);
|
|
|
- if (res.code != 0) {
|
|
|
- return;
|
|
|
- }
|
|
|
- /* if (res.data.is_pass !== 1 && res.data.is_root !== 1) {
|
|
|
- Session.clear();
|
|
|
- return ElMessage.warning('抱歉,您的账号未审核通过,请联系管理员');
|
|
|
- } */
|
|
|
- state.loading.signIn = true;
|
|
|
- Session.set('userInfo', res.data);
|
|
|
+const signIn = async () => {
|
|
|
+ if (state.ruleForm.code != state.codeNum) {
|
|
|
+ return ElMessage.error('验证码不正确')
|
|
|
+ }
|
|
|
+ let res = await Login.login(state.ruleForm)
|
|
|
+ if (res.code != 0) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ state.loading.signIn = true
|
|
|
+ Session.set('userInfo', res.data)
|
|
|
+
|
|
|
+ // 设置缓存记住账号和密码
|
|
|
+ if (state.checked1 == true) {
|
|
|
+ localStorage.setItem('user_name', state.ruleForm.phone)
|
|
|
+ localStorage.setItem('pass_word', state.ruleForm.password)
|
|
|
+ }
|
|
|
|
|
|
- // 设置缓存记住账号和密码
|
|
|
- if (state.checked1 == true) {
|
|
|
- localStorage.setItem('user_name', state.ruleForm.phone);
|
|
|
- localStorage.setItem('pass_word', state.ruleForm.password);
|
|
|
- }
|
|
|
+ // 存储 token 到浏览器缓存
|
|
|
+ Session.set('token', res.data.token)
|
|
|
|
|
|
- // 存储 token 到浏览器缓存
|
|
|
- // Session.set('token', Math.random().toString(36).substr(0));
|
|
|
- Session.set('token', res.data.token);
|
|
|
+ Cookies.set('userName', res.data.name)
|
|
|
|
|
|
- // 模拟数据,对接接口时,记得删除多余代码及对应依赖的引入。用于 `/src/stores/userInfo.ts` 中不同用户登录判断(模拟数据)
|
|
|
- // Cookies.set('userName', state.ruleForm.phone);
|
|
|
- Cookies.set('userName', res.data.name);
|
|
|
+ let isNoPower: boolean | undefined = false
|
|
|
+ if (!themeConfig.value.isRequestRoutes) {
|
|
|
+ console.log('前端控制路由')
|
|
|
+ // 前端控制路由,2、请注意执行顺序
|
|
|
+ isNoPower = await initFrontEndControlRoutes()
|
|
|
+ } else {
|
|
|
+ console.log('后端控制路由')
|
|
|
+ // 模拟后端控制路由,isRequestRoutes 为 true,则开启后端控制路由
|
|
|
+ // 添加完动态路由,再进行 router 跳转,否则可能报错 No match found for location with path "/"
|
|
|
+ isNoPower = await initBackEndControlRoutes()
|
|
|
+ // 执行完 initBackEndControlRoutes,再执行 signInSuccess
|
|
|
+ }
|
|
|
+ signInRedirct(isNoPower)
|
|
|
+}
|
|
|
|
|
|
- if (!themeConfig.value.isRequestRoutes) {
|
|
|
- console.log('前端控制路由');
|
|
|
- // 前端控制路由,2、请注意执行顺序
|
|
|
- const isNoPower = await initFrontEndControlRoutes();
|
|
|
- signInSuccess(isNoPower);
|
|
|
- } else {
|
|
|
- console.log('后端控制路由');
|
|
|
- // 模拟后端控制路由,isRequestRoutes 为 true,则开启后端控制路由
|
|
|
- // 添加完动态路由,再进行 router 跳转,否则可能报错 No match found for location with path "/"
|
|
|
- const isNoPower = await initBackEndControlRoutes();
|
|
|
- // 执行完 initBackEndControlRoutes,再执行 signInSuccess
|
|
|
- signInSuccess(isNoPower);
|
|
|
- }
|
|
|
-};
|
|
|
/**
|
|
|
* 防抖登录
|
|
|
*/
|
|
|
-const onSignInThor = throttle(onSignIn,1000)
|
|
|
-// 登录成功后的跳转
|
|
|
-const signInSuccess = (isNoPower: boolean | undefined) => {
|
|
|
- if (isNoPower) {
|
|
|
- console.log('lzj500🚀 ~ file: account.vue:198 ~ signInSuccess ~ isNoPower:', isNoPower);
|
|
|
- ElMessage.warning('抱歉,您没有登录权限');
|
|
|
- Session.clear();
|
|
|
- } else {
|
|
|
- // 初始化登录成功时间问候语
|
|
|
- let currentTimeInfo = currentTime.value;
|
|
|
- // 登录成功,跳到转首页
|
|
|
- // 如果是复制粘贴的路径,非首页/登录页,那么登录成功后重定向到对应的路径中
|
|
|
- if (route.query?.redirect) {
|
|
|
- router.push({
|
|
|
- path: <string>route.query?.redirect,
|
|
|
- query: Object.keys(<string>route.query?.params).length > 0 ? JSON.parse(<string>route.query?.params) : '',
|
|
|
- });
|
|
|
- } else {
|
|
|
- router.push('/');
|
|
|
- }
|
|
|
- // 登录成功提示
|
|
|
- const signInText = t('message.signInText');
|
|
|
- ElMessage.success(`${currentTimeInfo},${signInText}`);
|
|
|
- // 添加 loading,防止第一次进入界面时出现短暂空白
|
|
|
- NextLoading.start();
|
|
|
- }
|
|
|
- state.loading.signIn = false;
|
|
|
- // setTimeout(()=>{
|
|
|
- // setBackEndControlRefreshRoutes() // 刷新菜单,未进行后端接口测试
|
|
|
- // },500)
|
|
|
-};
|
|
|
+const signInThor = throttle(signIn, 1000)
|
|
|
+
|
|
|
+/**
|
|
|
+ * 登录成功调转
|
|
|
+ * @param isNoPower
|
|
|
+ */
|
|
|
+const signInRedirct = (isNoPower: boolean | undefined) => {
|
|
|
+ if (isNoPower) {
|
|
|
+ console.log('lzj500🚀 ~ file: account.vue:198 ~ signInSuccess ~ isNoPower:', isNoPower)
|
|
|
+ ElMessage.warning('抱歉,您没有登录权限')
|
|
|
+ Session.clear()
|
|
|
+ } else {
|
|
|
+ // 初始化登录成功时间问候语
|
|
|
+ let currentTimeInfo = currentTime.value
|
|
|
+ // 登录成功,跳到转首页
|
|
|
+ // 如果是复制粘贴的路径,非首页/登录页,那么登录成功后重定向到对应的路径中
|
|
|
+ if (route.query?.redirect) {
|
|
|
+ router.push({
|
|
|
+ path: <string>route.query?.redirect,
|
|
|
+ query: Object.keys(<string>route.query?.params).length > 0 ? JSON.parse(<string>route.query?.params) : '',
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ router.push('/')
|
|
|
+ }
|
|
|
+ // 登录成功提示
|
|
|
+ const signInText = t('message.signInText')
|
|
|
+ ElMessage.success(`${currentTimeInfo},${signInText}`)
|
|
|
+ // 添加 loading,防止第一次进入界面时出现短暂空白
|
|
|
+ NextLoading.start()
|
|
|
+ }
|
|
|
+ state.loading.signIn = false
|
|
|
+}
|
|
|
</script>
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
.checked-box {
|
|
|
- position: absolute;
|
|
|
- margin-top: -25px;
|
|
|
+ position: absolute;
|
|
|
+ margin-top: -25px;
|
|
|
}
|
|
|
+
|
|
|
.login-content-form {
|
|
|
- margin-top: 20px;
|
|
|
- @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-code {
|
|
|
- width: 100%;
|
|
|
- padding: 0;
|
|
|
- font-weight: bold;
|
|
|
- letter-spacing: 5px;
|
|
|
- }
|
|
|
- .login-content-submit {
|
|
|
- width: 100%;
|
|
|
- letter-spacing: 2px;
|
|
|
- font-weight: 300;
|
|
|
- margin-top: 15px;
|
|
|
- }
|
|
|
+ margin-top: 20px;
|
|
|
+
|
|
|
+ @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-code {
|
|
|
+ width: 100%;
|
|
|
+ padding: 0;
|
|
|
+ font-weight: bold;
|
|
|
+ letter-spacing: 5px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .login-content-submit {
|
|
|
+ width: 100%;
|
|
|
+ letter-spacing: 2px;
|
|
|
+ font-weight: 300;
|
|
|
+ margin-top: 15px;
|
|
|
+ }
|
|
|
}
|
|
|
</style>
|