|
@@ -0,0 +1,269 @@
|
|
|
+<template>
|
|
|
+ <div class="gsc-login">
|
|
|
+ <div class="login-main">
|
|
|
+ <div class="title">{{ sysBaseConfig.SNOWY_SYS_NAME }}</div>
|
|
|
+ <a-form class="login-form" ref="loginForm" :model="ruleForm" :rules="rules">
|
|
|
+ <a-form-item name="account">
|
|
|
+ <a-input
|
|
|
+ v-model:value="ruleForm.account"
|
|
|
+ :placeholder="$t('login.accountPlaceholder')"
|
|
|
+ size="large"
|
|
|
+ @keyup.enter="login"
|
|
|
+ >
|
|
|
+ <template #prefix>
|
|
|
+ <UserOutlined class="login-icon-gray" />
|
|
|
+ </template>
|
|
|
+ </a-input>
|
|
|
+ </a-form-item>
|
|
|
+ <a-form-item name="password">
|
|
|
+ <a-input-password
|
|
|
+ v-model:value="ruleForm.password"
|
|
|
+ :placeholder="$t('login.PWPlaceholder')"
|
|
|
+ size="large"
|
|
|
+ autocomplete="off"
|
|
|
+ @keyup.enter="login"
|
|
|
+ >
|
|
|
+ <template #prefix>
|
|
|
+ <LockOutlined class="login-icon-gray" />
|
|
|
+ </template>
|
|
|
+ </a-input-password>
|
|
|
+ </a-form-item>
|
|
|
+ <a-form-item name="validCode" v-if="captchaOpen === 'true'">
|
|
|
+ <a-row :gutter="8">
|
|
|
+ <a-col :span="17">
|
|
|
+ <a-input
|
|
|
+ v-model:value="ruleForm.validCode"
|
|
|
+ :placeholder="$t('login.validLaceholder')"
|
|
|
+ size="large"
|
|
|
+ @keyup.enter="login"
|
|
|
+ >
|
|
|
+ <template #prefix>
|
|
|
+ <verified-outlined class="login-icon-gray" />
|
|
|
+ </template>
|
|
|
+ </a-input>
|
|
|
+ </a-col>
|
|
|
+ <a-col :span="7">
|
|
|
+ <img :src="validCodeBase64" class="login-validCode-img" @click="loginCaptcha" />
|
|
|
+ </a-col>
|
|
|
+ </a-row>
|
|
|
+ </a-form-item>
|
|
|
+ </a-form>
|
|
|
+ <a-button type="primary" class="button" :loading="loading" round size="large" @click="login()">
|
|
|
+ {{ $t('login.signIn') }}
|
|
|
+ </a-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+<script setup>
|
|
|
+import loginApi from '@/api/auth/loginApi'
|
|
|
+import smCrypto from '@/utils/smCrypto'
|
|
|
+import {required} from '@/utils/formRules'
|
|
|
+import {afterLogin} from './util'
|
|
|
+import configData from '@/config'
|
|
|
+import configApi from '@/api/dev/configApi'
|
|
|
+import tool from '@/utils/tool'
|
|
|
+import {globalStore, iframeStore, keepAliveStore, viewTagsStore} from '@/store'
|
|
|
+import {message, Modal} from "ant-design-vue";
|
|
|
+import {createVNode} from "vue";
|
|
|
+import {ExclamationCircleOutlined} from "@ant-design/icons-vue";
|
|
|
+import {useRoute} from "vue-router";
|
|
|
+
|
|
|
+const {proxy} = getCurrentInstance()
|
|
|
+const route = useRoute()
|
|
|
+
|
|
|
+const activeKey = ref('userAccount')
|
|
|
+const captchaOpen = ref(configData.SYS_BASE_CONFIG.SNOWY_SYS_DEFAULT_CAPTCHA_OPEN)
|
|
|
+const validCodeBase64 = ref('')
|
|
|
+const loading = ref(false)
|
|
|
+const loginAgree = ref(false)
|
|
|
+const agreeTipsYhfwxy = ref(false)
|
|
|
+const agreeTipsYhyszc = ref(false)
|
|
|
+const loginMode = ref('account')
|
|
|
+
|
|
|
+const ruleForm = reactive({
|
|
|
+ account: '', // superAdmin
|
|
|
+ password: '', // 123456
|
|
|
+ validCode: '',
|
|
|
+ validCodeReqNo: '',
|
|
|
+ autologin: false
|
|
|
+})
|
|
|
+
|
|
|
+const rules = reactive({
|
|
|
+ account: [required(proxy.$t('login.accountError'), 'blur')],
|
|
|
+ password: [required(proxy.$t('login.PWError'), 'blur')]
|
|
|
+})
|
|
|
+const config = ref({
|
|
|
+ lang: tool.data.get('APP_LANG') || proxy.$CONFIG.LANG,
|
|
|
+ theme: tool.data.get('APP_THEME') || 'default'
|
|
|
+})
|
|
|
+
|
|
|
+const store = globalStore()
|
|
|
+const kStore = keepAliveStore()
|
|
|
+const iStore = iframeStore()
|
|
|
+const vStore = viewTagsStore()
|
|
|
+
|
|
|
+const setSysBaseConfig = store.setSysBaseConfig
|
|
|
+const clearKeepLive = kStore.clearKeepLive
|
|
|
+const clearIframeList = iStore.clearIframeList
|
|
|
+const clearViewTags = vStore.clearViewTags
|
|
|
+
|
|
|
+const sysBaseConfig = computed(() => {
|
|
|
+ return store.sysBaseConfig
|
|
|
+})
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ let formData = ref(configData.SYS_BASE_CONFIG)
|
|
|
+ configApi.configSysBaseList().then((data) => {
|
|
|
+ if (data) {
|
|
|
+ data.forEach((item) => {
|
|
|
+ formData.value[item.configKey] = item.configValue
|
|
|
+ })
|
|
|
+ captchaOpen.value = formData.value.SNOWY_SYS_DEFAULT_CAPTCHA_OPEN
|
|
|
+ tool.data.set('SNOWY_SYS_BASE_CONFIG', formData.value)
|
|
|
+ setSysBaseConfig(formData.value)
|
|
|
+ refreshSwitch()
|
|
|
+ }
|
|
|
+ })
|
|
|
+})
|
|
|
+
|
|
|
+onBeforeMount(() => {
|
|
|
+ clearViewTags()
|
|
|
+ clearKeepLive()
|
|
|
+ clearIframeList()
|
|
|
+ if (route.query.loginMode) {
|
|
|
+ loginMode.value = route.query.loginMode
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
+// 监听语言
|
|
|
+watch(
|
|
|
+ () => config.value.lang,
|
|
|
+ (newValue) => {
|
|
|
+ proxy.$i18n.locale = newValue
|
|
|
+ tool.data.set('APP_LANG', newValue)
|
|
|
+ }
|
|
|
+)
|
|
|
+// 主题
|
|
|
+watch(
|
|
|
+ () => config.value.theme,
|
|
|
+ (newValue) => {
|
|
|
+ document.body.setAttribute('data-theme', newValue)
|
|
|
+ }
|
|
|
+)
|
|
|
+// 通过开关加载内容
|
|
|
+const refreshSwitch = () => {
|
|
|
+ // 判断是否开启验证码
|
|
|
+ if (captchaOpen.value === 'true') {
|
|
|
+ // 加载验证码
|
|
|
+ loginCaptcha()
|
|
|
+ // 加入校验
|
|
|
+ rules.validCode = [required(proxy.$t('login.validError'), 'blur')]
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 获取验证码
|
|
|
+const loginCaptcha = () => {
|
|
|
+ loginApi.getPicCaptcha().then((data) => {
|
|
|
+ validCodeBase64.value = data.validCodeBase64
|
|
|
+ ruleForm.validCodeReqNo = data.validCodeReqNo
|
|
|
+ })
|
|
|
+}
|
|
|
+//登陆
|
|
|
+const loginForm = ref()
|
|
|
+const login = async () => {
|
|
|
+ loginForm.value
|
|
|
+ .validate()
|
|
|
+ .then(async () => {
|
|
|
+ loading.value = true
|
|
|
+ const loginData = {
|
|
|
+ account: ruleForm.account,
|
|
|
+ // 密码进行SM2加密,传输过程中看到的只有密文,后端存储使用hash
|
|
|
+ password: smCrypto.doSm2Encrypt(ruleForm.password),
|
|
|
+ validCode: ruleForm.validCode,
|
|
|
+ validCodeReqNo: ruleForm.validCodeReqNo
|
|
|
+ }
|
|
|
+ // 获取token
|
|
|
+ try {
|
|
|
+ const loginToken = await loginApi.login(loginData)
|
|
|
+ const loginAfter = afterLogin(loginToken)
|
|
|
+ } catch (err) {
|
|
|
+ loading.value = false
|
|
|
+ loginCaptcha()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .catch(() => {
|
|
|
+ })
|
|
|
+}
|
|
|
+</script>
|
|
|
+<style lang="less" scoped>
|
|
|
+.gsc-login {
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ background-image: url("./img/login-bg.png");
|
|
|
+ background-size: 100% 100%;
|
|
|
+ background-repeat: no-repeat;
|
|
|
+
|
|
|
+ .login-main {
|
|
|
+ padding: 22px 20px;
|
|
|
+ width: 308px;
|
|
|
+ background-color: rgba(134, 197, 255, 0.3);
|
|
|
+ border-radius: 4px;
|
|
|
+ border: 2px solid #8BBCFF;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ .title {
|
|
|
+ font-family: PingFang SC;
|
|
|
+ font-weight: bold;
|
|
|
+ font-size: 16px;
|
|
|
+ color: #FFFFFF;
|
|
|
+ }
|
|
|
+ :deep(.login-form) {
|
|
|
+ margin-top: 20px;
|
|
|
+ .ant-form-item {
|
|
|
+ margin-bottom: 20px;
|
|
|
+ .ant-input-affix-wrapper {
|
|
|
+ background-color: rgba(9, 28, 63, 0.5);
|
|
|
+ border-color: transparent;
|
|
|
+ padding-top: 4px;
|
|
|
+ padding-bottom: 4px;
|
|
|
+ .ant-input-prefix, .ant-input-suffix > .ant-input-password-icon {
|
|
|
+ color: #ffffff;
|
|
|
+ margin-right: 10px;
|
|
|
+ }
|
|
|
+ .ant-input {
|
|
|
+ background-color: transparent !important;
|
|
|
+ color: #ffffff;
|
|
|
+ &:-webkit-autofill {
|
|
|
+ -webkit-text-fill-color: #ededed !important;
|
|
|
+ -webkit-box-shadow: 0 0 0px 1000px transparent inset !important;
|
|
|
+ background-color:transparent;
|
|
|
+ background-image: none;
|
|
|
+ transition: background-color 50000s ease-in-out 0s;
|
|
|
+ }
|
|
|
+ &::placeholder {
|
|
|
+ color: rgba(255, 255, 255, 0.3);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .login-validCode-img {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .button {
|
|
|
+ width: 100%;
|
|
|
+ height: 30px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ margin-top: 16px;
|
|
|
+ font-size: 12px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|