|
@@ -0,0 +1,358 @@
|
|
|
+<template>
|
|
|
+ <div class="single-window-login">
|
|
|
+ <div class="swl-head">
|
|
|
+ <div class="swl-head-center">
|
|
|
+ <a href="https://www.singlewindow.cn"><img src="https://update.singlewindow.cn/images/swLogo.png"></a>
|
|
|
+ <div class="swl-head-lang">
|
|
|
+ <div class="__hover" :class="{ active: config.lang === 'zh-cn' }" @click="configLang('zh-cn')">简体中文</div>
|
|
|
+ <div>/</div>
|
|
|
+ <div class="__hover" :class="{ active: config.lang === 'en' }" @click="configLang('en')">English</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="swl-content">
|
|
|
+ <div class="swl-content-login">
|
|
|
+ <div class="swl-content-login-left"/>
|
|
|
+ <div class="swl-content-login-right">
|
|
|
+ <div class="swlclr-login">
|
|
|
+ <div class="swlclr-login-div">
|
|
|
+ <div class="swlclr-login-div-title">账号登录</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>
|
|
|
+ <div class="agree">
|
|
|
+ <a-checkbox v-model:checked="loginAgree"/>
|
|
|
+ <span style="color:#222222">已阅读并同意</span>
|
|
|
+ <span style="color: #096ac6;text-decoration:underline dotted; cursor:pointer;" onclick="userNameProtocolAgree()">《用户服务协议》</span>
|
|
|
+ <span>和</span>
|
|
|
+ <span style="color: #096ac6;text-decoration:underline dotted; cursor:pointer;" onclick="userNameProtocolPrivacy()">《用户隐私政策》</span>
|
|
|
+ </div>
|
|
|
+ <a-button type="primary" class="w-full mt-4" :loading="loading" round size="large" @click="login"
|
|
|
+ >{{ $t('login.signIn') }}
|
|
|
+ </a-button>
|
|
|
+ </a-form>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="swl-foot" v-if="config.lang === 'zh-cn'"></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 router from "@/router";
|
|
|
+ const { proxy } = getCurrentInstance()
|
|
|
+
|
|
|
+ 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 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 lang = ref([
|
|
|
+ {
|
|
|
+ name: '简体中文',
|
|
|
+ value: 'zh-cn'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: 'English',
|
|
|
+ value: 'en'
|
|
|
+ }
|
|
|
+ ])
|
|
|
+ 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()
|
|
|
+ })
|
|
|
+
|
|
|
+ // 监听语言
|
|
|
+ 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 () => {
|
|
|
+ if (loginAgree.value) {
|
|
|
+ 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
|
|
|
+ // loginApi.login(loginData).then((loginToken) => {
|
|
|
+ // afterLogin(loginToken)
|
|
|
+ // }).catch(() => {
|
|
|
+ // loading.value = false
|
|
|
+ // loginCaptcha()
|
|
|
+ // })
|
|
|
+
|
|
|
+ // 获取token
|
|
|
+ try {
|
|
|
+ const loginToken = await loginApi.login(loginData)
|
|
|
+ const loginAfter = afterLogin(loginToken)
|
|
|
+ } catch (err) {
|
|
|
+ loading.value = false
|
|
|
+ loginCaptcha()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .catch(() => {})
|
|
|
+ } else {
|
|
|
+ Modal.confirm({
|
|
|
+ title: '提示',
|
|
|
+ content: '请阅读并勾选《用户服务协议》和《用户隐私政策》!',
|
|
|
+ centered: true,
|
|
|
+ width: 420,
|
|
|
+ icon: createVNode(ExclamationCircleOutlined),
|
|
|
+ maskClosable: false,
|
|
|
+ onOk() {},
|
|
|
+ onCancel() {}
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const configLang = (key) => {
|
|
|
+ config.value.lang = key
|
|
|
+ }
|
|
|
+</script>
|
|
|
+<style lang="less" scoped>
|
|
|
+.single-window-login {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ .swl-head {
|
|
|
+ background-color: #ffffff;
|
|
|
+ min-width: 1200px;
|
|
|
+ height: 90px;
|
|
|
+ line-height: 90px;
|
|
|
+ display: flex;
|
|
|
+ .swl-head-center {
|
|
|
+ width: 1200px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ margin: 0 auto;
|
|
|
+ .swl-head-lang {
|
|
|
+ margin-left: auto;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 10px;
|
|
|
+ color: #00599C;
|
|
|
+ font-size: 15px;
|
|
|
+ &:nth-child(2) {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #00599C;
|
|
|
+ }
|
|
|
+ .active {
|
|
|
+ color: #00599C;
|
|
|
+ font-weight: bold;
|
|
|
+ font-size: 16px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .swl-content {
|
|
|
+ flex: 1;
|
|
|
+ background-image: url('https://app.singlewindow.cn/cas/images/newLogin/icon_bgNew.png');
|
|
|
+ background-repeat: no-repeat;
|
|
|
+ background-size: 100% 100%;
|
|
|
+ .swl-content-login {
|
|
|
+ height: 659px;
|
|
|
+ max-width: 1200px;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: row;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ margin: 0 auto;
|
|
|
+ .swl-content-login-left {
|
|
|
+ width: 553px;
|
|
|
+ height: 478px;
|
|
|
+ background-image: url('https://app.singlewindow.cn/cas/images/leftimg_04.png');
|
|
|
+ background-repeat: no-repeat;
|
|
|
+ background-position: center;
|
|
|
+ }
|
|
|
+ .swl-content-login-right {
|
|
|
+ width: 600px;
|
|
|
+ height: 478px;
|
|
|
+ .swlclr-login {
|
|
|
+ width: 412px;
|
|
|
+ height: auto;
|
|
|
+ background-color: #FFFFFF;
|
|
|
+ border: solid #ccc 0px;
|
|
|
+ border-radius: 8px;
|
|
|
+ margin: 0px auto;
|
|
|
+ color: #666666;
|
|
|
+ padding-bottom: 12px;
|
|
|
+ .swlclr-login-div {
|
|
|
+ width: 410px;
|
|
|
+ height: 420px;
|
|
|
+ background: #ffffff;
|
|
|
+ border-radius: 10px;
|
|
|
+ margin: 20px auto;
|
|
|
+ padding: 26px 41px 0 39px;
|
|
|
+ box-sizing: border-box;
|
|
|
+ position: relative;
|
|
|
+ .swlclr-login-div-title {
|
|
|
+ font-weight: 700;
|
|
|
+ color: #00599c;
|
|
|
+ font-size: 18px;
|
|
|
+ margin-top: 18px;
|
|
|
+ margin-bottom: 28px;
|
|
|
+ text-align: center;
|
|
|
+ }
|
|
|
+ :deep(.login-form) {
|
|
|
+ .ant-form-item-control-input-content {
|
|
|
+ border-bottom: 1px solid #e5e5e5;
|
|
|
+ .ant-input-affix-wrapper {
|
|
|
+ border: none;
|
|
|
+ box-shadow: none;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .agree {
|
|
|
+ font-size: 12px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .swl-foot {
|
|
|
+ height: 160px;
|
|
|
+ background-color: rgba(230, 230, 230, 1);
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|