|
@@ -1,3 +1,4 @@
|
|
|
+
|
|
|
<template>
|
|
|
<el-form
|
|
|
v-show="getShow"
|
|
@@ -9,17 +10,33 @@
|
|
|
label-width="120px"
|
|
|
size="large"
|
|
|
>
|
|
|
- <el-row style="display: flex;justify-content: center">
|
|
|
- <el-image v-if="loginType === 'uname'" :src="imgsaoma" class="clickable-image" alt="扫码登录" title="扫码登录" @click="changeLogin('dingding')"/>
|
|
|
- <el-image v-if="loginType === 'dingding'" :src="imgreturn" class="clickable-image" alt="返回" title="返回" @click="changeLogin('uname')"/>
|
|
|
- <el-image :src="img" class=" h-100px" style="margin-top: 16%"/>
|
|
|
- <div v-if="loginType === 'uname'" style="width: 90%">
|
|
|
- <el-col :span="24" style="padding-right: 10px; padding-left: 10px; margin-top: 85px">
|
|
|
- <el-form-item prop="username" >
|
|
|
- <el-input v-model="loginData.loginForm.username" :placeholder="t('login.usernamePlaceholder')" type="text" auto-complete="off" :prefix-icon="iconAvatar"/>
|
|
|
+ <el-row style="margin-right: -10px; margin-left: -10px">
|
|
|
+ <el-col :span="24" style="padding-right: 10px; padding-left: 10px">
|
|
|
+ <el-form-item>
|
|
|
+ <LoginFormTitle style="width: 100%" />
|
|
|
</el-form-item>
|
|
|
</el-col>
|
|
|
- <el-col :span="24" style="padding-right: 10px; padding-left: 10px;margin-top: 15px">
|
|
|
+<!-- <el-col :span="24" style="padding-right: 10px; padding-left: 10px">-->
|
|
|
+<!-- <el-form-item v-if="loginData.tenantEnable === 'true'" prop="tenantName">-->
|
|
|
+<!-- <el-input-->
|
|
|
+<!-- v-model="loginData.loginForm.tenantName"-->
|
|
|
+<!-- :placeholder="t('login.tenantNamePlaceholder')"-->
|
|
|
+<!-- :prefix-icon="iconHouse"-->
|
|
|
+<!-- link-->
|
|
|
+<!-- type="primary"-->
|
|
|
+<!-- />-->
|
|
|
+<!-- </el-form-item>-->
|
|
|
+<!-- </el-col>-->
|
|
|
+ <el-col :span="24" style="padding-right: 10px; padding-left: 10px;margin-top: 30px">
|
|
|
+ <el-form-item prop="username">
|
|
|
+ <el-input
|
|
|
+ v-model="loginData.loginForm.username"
|
|
|
+ :placeholder="t('login.usernamePlaceholder')"
|
|
|
+ :prefix-icon="iconAvatar"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="24" style="padding-right: 10px; padding-left: 10px; margin-top: 15px">
|
|
|
<el-form-item prop="password">
|
|
|
<el-input
|
|
|
v-model="loginData.loginForm.password"
|
|
@@ -33,10 +50,10 @@
|
|
|
</el-col>
|
|
|
<el-col
|
|
|
:span="24"
|
|
|
- style="padding-right: 10px; padding-left: 10px; margin-top: 20px;"
|
|
|
+ style="padding-right: 10px; padding-left: 10px; margin-top: 10px; margin-bottom: -20px"
|
|
|
>
|
|
|
<el-form-item>
|
|
|
- <el-row justify="space-between" style="width: 100%;">
|
|
|
+ <el-row justify="space-between" style="width: 100%">
|
|
|
<el-col :span="6">
|
|
|
<el-checkbox v-model="loginData.loginForm.rememberMe">
|
|
|
{{ t('login.remember') }}
|
|
@@ -54,10 +71,9 @@
|
|
|
</el-row>
|
|
|
</el-form-item>
|
|
|
</el-col>
|
|
|
- <el-col :span="24" style="padding-right: 10px; padding-left: 10px;margin-bottom: 10px">
|
|
|
+ <el-col :span="24" style="padding-right: 10px; padding-left: 10px">
|
|
|
<el-form-item>
|
|
|
<XButton
|
|
|
- style="height: 4em;background-color: rgb(11, 26, 50);border: none;opacity: 1;color: rgb(186, 205, 224)"
|
|
|
:loading="loginLoading"
|
|
|
:title="t('login.login')"
|
|
|
class="w-[100%]"
|
|
@@ -74,129 +90,86 @@
|
|
|
mode="pop"
|
|
|
@success="handleLogin"
|
|
|
/>
|
|
|
- </div>
|
|
|
- <div v-if="loginType === 'dingding'" id="login_container" style="margin-left: 8%;margin-top: 18%">
|
|
|
- </div>
|
|
|
+ <el-col :span="24" style="padding-right: 10px; padding-left: 10px">
|
|
|
+ <el-form-item>
|
|
|
+ <el-row :gutter="5" justify="space-between" style="width: 100%">
|
|
|
+<!-- <el-col :span="8">-->
|
|
|
+<!-- <XButton-->
|
|
|
+<!-- :title="t('login.btnMobile')"-->
|
|
|
+<!-- class="w-[100%]"-->
|
|
|
+<!-- @click="setLoginState(LoginStateEnum.MOBILE)"-->
|
|
|
+<!-- />-->
|
|
|
+<!-- </el-col>-->
|
|
|
+ <el-col :span="24">
|
|
|
+ <XButton
|
|
|
+ :title="t('login.btnQRCode')"
|
|
|
+ class="w-[100%]"
|
|
|
+ @click="setLoginState(LoginStateEnum.QR_CODE)"
|
|
|
+ />
|
|
|
+ </el-col>
|
|
|
+<!-- <el-col :span="12">-->
|
|
|
+<!-- <XButton-->
|
|
|
+<!-- :title="t('login.btnRegister')"-->
|
|
|
+<!-- class="w-[100%]"-->
|
|
|
+<!-- @click="setLoginState(LoginStateEnum.REGISTER)"-->
|
|
|
+<!-- />-->
|
|
|
+<!-- </el-col>-->
|
|
|
+ </el-row>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+<!-- <el-divider content-position="center">{{ t('login.otherLogin') }}</el-divider>-->
|
|
|
+<!-- <el-col :span="24" style="padding-right: 10px; padding-left: 10px">-->
|
|
|
+<!-- <el-form-item>-->
|
|
|
+<!-- <div class="w-[100%] flex justify-between">-->
|
|
|
+<!-- <Icon-->
|
|
|
+<!-- v-for="(item, key) in socialList"-->
|
|
|
+<!-- :key="key"-->
|
|
|
+<!-- :icon="item.icon"-->
|
|
|
+<!-- :size="30"-->
|
|
|
+<!-- class="anticon cursor-pointer"-->
|
|
|
+<!-- color="#999"-->
|
|
|
+<!-- @click="doSocialLogin(item.type)"-->
|
|
|
+<!-- />-->
|
|
|
+<!-- </div>-->
|
|
|
+<!-- </el-form-item>-->
|
|
|
+<!-- </el-col>-->
|
|
|
+<!-- <el-divider content-position="center">萌新必读</el-divider>-->
|
|
|
+<!-- <el-col :span="24" style="padding-right: 10px; padding-left: 10px">-->
|
|
|
+<!-- <el-form-item>-->
|
|
|
+<!-- <div class="w-[100%] flex justify-between">-->
|
|
|
+<!-- <el-link href="https://doc.iocoder.cn/" target="_blank">📚开发指南</el-link>-->
|
|
|
+<!-- <el-link href="https://doc.iocoder.cn/video/" target="_blank">🔥视频教程</el-link>-->
|
|
|
+<!-- <el-link href="https://www.iocoder.cn/Interview/good-collection/" target="_blank">-->
|
|
|
+<!-- ⚡面试手册-->
|
|
|
+<!-- </el-link>-->
|
|
|
+<!-- <el-link href="http://static.yudao.iocoder.cn/mp/Aix9975.jpeg" target="_blank">-->
|
|
|
+<!-- 🤝外包咨询-->
|
|
|
+<!-- </el-link>-->
|
|
|
+<!-- </div>-->
|
|
|
+<!-- </el-form-item>-->
|
|
|
+<!-- </el-col>-->
|
|
|
</el-row>
|
|
|
</el-form>
|
|
|
</template>
|
|
|
<script lang="ts" setup>
|
|
|
-import img from '@/assets/imgs/img.png'
|
|
|
-import imgsaoma from '@/assets/imgs/saoma.png'
|
|
|
-import imgreturn from '@/assets/imgs/return.png'
|
|
|
import { ElLoading } from 'element-plus'
|
|
|
+import LoginFormTitle from './LoginFormTitle.vue'
|
|
|
import type { RouteLocationNormalizedLoaded } from 'vue-router'
|
|
|
+
|
|
|
import { useIcon } from '@/hooks/web/useIcon'
|
|
|
-import * as DictDataApi from '@/api/system/dict/dict.data'
|
|
|
+
|
|
|
import * as authUtil from '@/utils/auth'
|
|
|
import { usePermissionStore } from '@/store/modules/permission'
|
|
|
import * as LoginApi from '@/api/login'
|
|
|
import { LoginStateEnum, useFormValid, useLoginState } from './useLogin'
|
|
|
|
|
|
-import { ref,nextTick,onMounted } from 'vue';
|
|
|
-const appId = 'dingik345qmyhtysvs2x'
|
|
|
-const dingRedirectUrl = 'http://1.94.244.160:91/login?loginType=dingding&type=20'
|
|
|
-
|
|
|
-onMounted(()=>{
|
|
|
- getTenantName();
|
|
|
-})
|
|
|
-const getTenantName=async ()=>{
|
|
|
- const queryParams = reactive({
|
|
|
- pageNo: 1,
|
|
|
- pageSize: 10,
|
|
|
- label: '',
|
|
|
- status: undefined,
|
|
|
- dictType: 'tenant_name'
|
|
|
- })
|
|
|
- const data = await DictDataApi.getDictDataPage(queryParams)
|
|
|
- loginData.loginForm.tenantName = data.list[0].label;
|
|
|
-}
|
|
|
-const loginType = ref('uname');
|
|
|
-const changeLogin = async (type) => {
|
|
|
- console.log(loginData.loginForm.tenantName)
|
|
|
- await getTenantId()
|
|
|
- loginType.value = type;
|
|
|
- if (type === 'dingding') {
|
|
|
- initDingLogin();
|
|
|
- }
|
|
|
-};
|
|
|
-
|
|
|
-
|
|
|
-const initDingLogin=()=> {
|
|
|
- // if (window.DDLogin) {
|
|
|
- var url = dingRedirectUrl
|
|
|
- var state = _getRandomString(10);
|
|
|
- var gotoUrl = encodeURIComponent(
|
|
|
- "https://oapi.dingtalk.com/connect/oauth2/sns_authorize?" +
|
|
|
- "appid=" + appId +
|
|
|
- "&response_type=code" +
|
|
|
- "&scope=snsapi_login" +
|
|
|
- "&state=" + state +
|
|
|
- "&redirect_uri=" + url
|
|
|
- );
|
|
|
-
|
|
|
- nextTick(() => {
|
|
|
- var obj = window.DDLogin({
|
|
|
- id: "login_container",
|
|
|
- goto: gotoUrl,
|
|
|
- style: "border:none;background-color:#FFFFFF;",
|
|
|
- width: '90%', // 二维码的宽度
|
|
|
- height: "290", // 二维码的高度
|
|
|
- })
|
|
|
- // 重置扫码登录框的样式,让登录框居中
|
|
|
- let box = document.getElementById('login_container')
|
|
|
- box.querySelector('iframe').style.top = '0'
|
|
|
- box.querySelector('iframe').style.bottom = '0'
|
|
|
- box.querySelector('iframe').style.left = '0'
|
|
|
- box.querySelector('iframe').style.right = '0'
|
|
|
- box.querySelector('iframe').style.margin = 'auto'
|
|
|
- })
|
|
|
-
|
|
|
- /* new window.DDLogin({
|
|
|
- id: "login_container",
|
|
|
- goto: gotoUrl,
|
|
|
- style: "border:none;background-color:#FFFFFF;",
|
|
|
- width: "350",
|
|
|
- height: "350",
|
|
|
- }); */
|
|
|
- var handleMessage = function (event) {
|
|
|
- var origin = event.origin;
|
|
|
- if (origin === "https://login.dingtalk.com") {
|
|
|
- var loginTmpCode = event.data;
|
|
|
- console.log(loginTmpCode)
|
|
|
- window.location.href =
|
|
|
- "https://oapi.dingtalk.com/connect/oauth2/sns_authorize?appid=dingik345qmyhtysvs2x&response_type=code&scope=snsapi_login&state=" +
|
|
|
- state +
|
|
|
- "&redirect_uri=" +
|
|
|
- url +
|
|
|
- "&loginTmpCode=" +
|
|
|
- loginTmpCode;
|
|
|
- }
|
|
|
- };
|
|
|
- if (typeof window.addEventListener != "undefined") {
|
|
|
- window.addEventListener("message", handleMessage, false);
|
|
|
- } else if (typeof window.attachEvent != "undefined") {
|
|
|
- window.attachEvent("onmessage", handleMessage);
|
|
|
- }
|
|
|
- // }
|
|
|
-}
|
|
|
-const _getRandomString=(len)=> {
|
|
|
- len = len || 10;
|
|
|
- let $chars = "ABCDEFGHIJKMNOPQRSTUVWXYZ"; // 默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1
|
|
|
- let maxPos = $chars.length;
|
|
|
- let pwd = "";
|
|
|
- for (var i = 0; i < len; i++) {
|
|
|
- pwd += $chars.charAt(Math.floor(Math.random() * maxPos));
|
|
|
- }
|
|
|
- return pwd;
|
|
|
-}
|
|
|
defineOptions({ name: 'LoginForm' })
|
|
|
|
|
|
const { t } = useI18n()
|
|
|
const message = useMessage()
|
|
|
const iconHouse = useIcon({ icon: 'ep:house' })
|
|
|
-const iconAvatar = useIcon({ icon: 'ep:avatar',size:26 })
|
|
|
-const iconLock = useIcon({ icon: 'ep:lock',size:26 })
|
|
|
+const iconAvatar = useIcon({ icon: 'ep:avatar' })
|
|
|
+const iconLock = useIcon({ icon: 'ep:lock' })
|
|
|
const formLogin = ref()
|
|
|
const { validForm } = useFormValid(formLogin)
|
|
|
const { setLoginState, getLoginState } = useLoginState()
|
|
@@ -219,7 +192,7 @@ const loginData = reactive({
|
|
|
captchaEnable: import.meta.env.VITE_APP_CAPTCHA_ENABLE,
|
|
|
tenantEnable: import.meta.env.VITE_APP_TENANT_ENABLE,
|
|
|
loginForm: {
|
|
|
- tenantName: '瑞气能源',
|
|
|
+ tenantName: import.meta.env.VITE_APP_DEFAULT_LOGIN_TENANT || '',
|
|
|
username: import.meta.env.VITE_APP_DEFAULT_LOGIN_USERNAME || '',
|
|
|
password: import.meta.env.VITE_APP_DEFAULT_LOGIN_PASSWORD || '',
|
|
|
captchaVerification: '',
|
|
@@ -227,12 +200,12 @@ const loginData = reactive({
|
|
|
}
|
|
|
})
|
|
|
|
|
|
-// const socialList = [
|
|
|
-// { icon: 'ant-design:wechat-filled', type: 30 },
|
|
|
-// { icon: 'ant-design:dingtalk-circle-filled', type: 20 },
|
|
|
-// { icon: 'ant-design:github-filled', type: 0 },
|
|
|
-// { icon: 'ant-design:alipay-circle-filled', type: 0 }
|
|
|
-// ]
|
|
|
+const socialList = [
|
|
|
+ { icon: 'ant-design:wechat-filled', type: 30 },
|
|
|
+ { icon: 'ant-design:dingtalk-circle-filled', type: 20 },
|
|
|
+ { icon: 'ant-design:github-filled', type: 0 },
|
|
|
+ { icon: 'ant-design:alipay-circle-filled', type: 0 }
|
|
|
+]
|
|
|
|
|
|
// 获取验证码
|
|
|
const getCode = async () => {
|
|
@@ -317,6 +290,40 @@ const handleLogin = async (params: any) => {
|
|
|
}
|
|
|
|
|
|
// 社交登录
|
|
|
+const doSocialLogin = async (type: number) => {
|
|
|
+ if (type === 0) {
|
|
|
+ message.error('此方式未配置')
|
|
|
+ } else {
|
|
|
+ loginLoading.value = true
|
|
|
+ if (loginData.tenantEnable === 'true') {
|
|
|
+ // 尝试先通过 tenantName 获取租户
|
|
|
+ await getTenantId()
|
|
|
+ // 如果获取不到,则需要弹出提示,进行处理
|
|
|
+ if (!authUtil.getTenantId()) {
|
|
|
+ try {
|
|
|
+ const data = await message.prompt('请输入租户名称', t('common.reminder'))
|
|
|
+ if (data?.action !== 'confirm') throw 'cancel'
|
|
|
+ const res = await LoginApi.getTenantIdByName(data.value)
|
|
|
+ authUtil.setTenantId(res)
|
|
|
+ } catch (error) {
|
|
|
+ if (error === 'cancel') return
|
|
|
+ } finally {
|
|
|
+ loginLoading.value = false
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 计算 redirectUri
|
|
|
+ // tricky: type、redirect需要先encode一次,否则钉钉回调会丢失。
|
|
|
+ // 配合 Login/SocialLogin.vue#getUrlValue() 使用
|
|
|
+ const redirectUri =
|
|
|
+ location.origin +
|
|
|
+ '/social-login?' +
|
|
|
+ encodeURIComponent(`type=${type}&redirect=${redirect.value || '/'}`)
|
|
|
+
|
|
|
+ // 进行跳转
|
|
|
+ window.location.href = await LoginApi.socialAuthRedirect(type, encodeURIComponent(redirectUri))
|
|
|
+ }
|
|
|
+}
|
|
|
watch(
|
|
|
() => currentRoute.value,
|
|
|
(route: RouteLocationNormalizedLoaded) => {
|
|
@@ -333,16 +340,6 @@ onMounted(() => {
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
-::v-deep .el-input__wrapper {
|
|
|
- background-color: transparent !important;
|
|
|
- height: 3.5em;
|
|
|
- color: white;
|
|
|
- box-shadow: none !important;
|
|
|
- border-radius: 0;
|
|
|
- border: none !important;
|
|
|
- border-bottom: 1px solid #bacde0 !important;
|
|
|
- outline: none;
|
|
|
-}
|
|
|
:deep(.anticon) {
|
|
|
&:hover {
|
|
|
color: var(--el-color-primary) !important;
|
|
@@ -362,26 +359,392 @@ onMounted(() => {
|
|
|
cursor: pointer;
|
|
|
}
|
|
|
}
|
|
|
-::v-deep .rqinput .el-input__inner {
|
|
|
- background-color: transparent !important;
|
|
|
- border: none !important;
|
|
|
- border-bottom: 1px solid rgb(186, 205, 224) !important;
|
|
|
- border-radius: 0;
|
|
|
- height: 2.8em;
|
|
|
- //left: 18%;
|
|
|
- padding-left: 3em;
|
|
|
- color: white;
|
|
|
-}
|
|
|
-.clickable-image {
|
|
|
- cursor: pointer;
|
|
|
- position:absolute;
|
|
|
- //top: 2%;
|
|
|
- //right: 2%;
|
|
|
- width: 6%;
|
|
|
- margin-top: -9%;
|
|
|
- margin-left: 111%;
|
|
|
-}
|
|
|
-::v-deep .el-input__inner {
|
|
|
- color: white;
|
|
|
-}
|
|
|
</style>
|
|
|
+
|
|
|
+<!--<template>-->
|
|
|
+<!-- <el-form-->
|
|
|
+<!-- v-show="getShow"-->
|
|
|
+<!-- ref="formLogin"-->
|
|
|
+<!-- :model="loginData.loginForm"-->
|
|
|
+<!-- :rules="LoginRules"-->
|
|
|
+<!-- class="login-form"-->
|
|
|
+<!-- label-position="top"-->
|
|
|
+<!-- label-width="120px"-->
|
|
|
+<!-- size="large"-->
|
|
|
+<!-- >-->
|
|
|
+<!-- <el-row style="display: flex;justify-content: center">-->
|
|
|
+<!-- <el-image v-if="loginType === 'uname'" :src="imgsaoma" class="clickable-image" alt="扫码登录" title="扫码登录" @click="changeLogin('dingding')"/>-->
|
|
|
+<!-- <el-image v-if="loginType === 'dingding'" :src="imgreturn" class="clickable-image" alt="返回" title="返回" @click="changeLogin('uname')"/>-->
|
|
|
+<!-- <el-image :src="img" class=" h-100px" style="margin-top: 16%"/>-->
|
|
|
+<!-- <div v-if="loginType === 'uname'" style="width: 90%">-->
|
|
|
+<!-- <el-col :span="24" style="padding-right: 10px; padding-left: 10px; margin-top: 85px">-->
|
|
|
+<!-- <el-form-item prop="username" >-->
|
|
|
+<!-- <el-input v-model="loginData.loginForm.username" :placeholder="t('login.usernamePlaceholder')" type="text" auto-complete="off" :prefix-icon="iconAvatar"/>-->
|
|
|
+<!-- </el-form-item>-->
|
|
|
+<!-- </el-col>-->
|
|
|
+<!-- <el-col :span="24" style="padding-right: 10px; padding-left: 10px;margin-top: 15px">-->
|
|
|
+<!-- <el-form-item prop="password">-->
|
|
|
+<!-- <el-input-->
|
|
|
+<!-- v-model="loginData.loginForm.password"-->
|
|
|
+<!-- :placeholder="t('login.passwordPlaceholder')"-->
|
|
|
+<!-- :prefix-icon="iconLock"-->
|
|
|
+<!-- show-password-->
|
|
|
+<!-- type="password"-->
|
|
|
+<!-- @keyup.enter="getCode()"-->
|
|
|
+<!-- />-->
|
|
|
+<!-- </el-form-item>-->
|
|
|
+<!-- </el-col>-->
|
|
|
+<!-- <el-col-->
|
|
|
+<!-- :span="24"-->
|
|
|
+<!-- style="padding-right: 10px; padding-left: 10px; margin-top: 20px;"-->
|
|
|
+<!-- >-->
|
|
|
+<!-- <el-form-item>-->
|
|
|
+<!-- <el-row justify="space-between" style="width: 100%;">-->
|
|
|
+<!-- <el-col :span="6">-->
|
|
|
+<!-- <el-checkbox v-model="loginData.loginForm.rememberMe">-->
|
|
|
+<!-- {{ t('login.remember') }}-->
|
|
|
+<!-- </el-checkbox>-->
|
|
|
+<!-- </el-col>-->
|
|
|
+<!-- <el-col :offset="6" :span="12">-->
|
|
|
+<!-- <el-link-->
|
|
|
+<!-- style="float: right"-->
|
|
|
+<!-- type="primary"-->
|
|
|
+<!-- @click="setLoginState(LoginStateEnum.RESET_PASSWORD)"-->
|
|
|
+<!-- >-->
|
|
|
+<!-- {{ t('login.forgetPassword') }}-->
|
|
|
+<!-- </el-link>-->
|
|
|
+<!-- </el-col>-->
|
|
|
+<!-- </el-row>-->
|
|
|
+<!-- </el-form-item>-->
|
|
|
+<!-- </el-col>-->
|
|
|
+<!-- <el-col :span="24" style="padding-right: 10px; padding-left: 10px;margin-bottom: 10px">-->
|
|
|
+<!-- <el-form-item>-->
|
|
|
+<!-- <XButton-->
|
|
|
+<!-- style="height: 4em;background-color: rgb(11, 26, 50);border: none;opacity: 1;color: rgb(186, 205, 224)"-->
|
|
|
+<!-- :loading="loginLoading"-->
|
|
|
+<!-- :title="t('login.login')"-->
|
|
|
+<!-- class="w-[100%]"-->
|
|
|
+<!-- type="primary"-->
|
|
|
+<!-- @click="getCode()"-->
|
|
|
+<!-- />-->
|
|
|
+<!-- </el-form-item>-->
|
|
|
+<!-- </el-col>-->
|
|
|
+<!-- <Verify-->
|
|
|
+<!-- v-if="loginData.captchaEnable === 'true'"-->
|
|
|
+<!-- ref="verify"-->
|
|
|
+<!-- :captchaType="captchaType"-->
|
|
|
+<!-- :imgSize="{ width: '400px', height: '200px' }"-->
|
|
|
+<!-- mode="pop"-->
|
|
|
+<!-- @success="handleLogin"-->
|
|
|
+<!-- />-->
|
|
|
+<!-- </div>-->
|
|
|
+<!-- <div v-if="loginType === 'dingding'" id="login_container" style="margin-left: 8%;margin-top: 18%">-->
|
|
|
+<!-- </div>-->
|
|
|
+<!-- </el-row>-->
|
|
|
+<!-- </el-form>-->
|
|
|
+<!--</template>-->
|
|
|
+<!--<script lang="ts" setup>-->
|
|
|
+<!--import img from '@/assets/imgs/img.png'-->
|
|
|
+<!--import imgsaoma from '@/assets/imgs/saoma.png'-->
|
|
|
+<!--import imgreturn from '@/assets/imgs/return.png'-->
|
|
|
+<!--import { ElLoading } from 'element-plus'-->
|
|
|
+<!--import type { RouteLocationNormalizedLoaded } from 'vue-router'-->
|
|
|
+<!--import { useIcon } from '@/hooks/web/useIcon'-->
|
|
|
+<!--import * as DictDataApi from '@/api/system/dict/dict.data'-->
|
|
|
+<!--import * as authUtil from '@/utils/auth'-->
|
|
|
+<!--import { usePermissionStore } from '@/store/modules/permission'-->
|
|
|
+<!--import * as LoginApi from '@/api/login'-->
|
|
|
+<!--import { LoginStateEnum, useFormValid, useLoginState } from './useLogin'-->
|
|
|
+
|
|
|
+<!--import { ref,nextTick,onMounted } from 'vue';-->
|
|
|
+<!--const appId = 'dingik345qmyhtysvs2x'-->
|
|
|
+<!--const dingRedirectUrl = 'http://1.94.244.160:91/login?loginType=dingding&type=20'-->
|
|
|
+
|
|
|
+<!--onMounted(()=>{-->
|
|
|
+<!-- getTenantName();-->
|
|
|
+<!--})-->
|
|
|
+<!--const getTenantName=async ()=>{-->
|
|
|
+<!-- const queryParams = reactive({-->
|
|
|
+<!-- pageNo: 1,-->
|
|
|
+<!-- pageSize: 10,-->
|
|
|
+<!-- label: '',-->
|
|
|
+<!-- status: undefined,-->
|
|
|
+<!-- dictType: 'tenant_name'-->
|
|
|
+<!-- })-->
|
|
|
+<!-- const data = await DictDataApi.getDictDataPage(queryParams)-->
|
|
|
+<!-- loginData.loginForm.tenantName = data.list[0].label;-->
|
|
|
+<!--}-->
|
|
|
+<!--const loginType = ref('uname');-->
|
|
|
+<!--const changeLogin = async (type) => {-->
|
|
|
+<!-- console.log(loginData.loginForm.tenantName)-->
|
|
|
+<!-- await getTenantId()-->
|
|
|
+<!-- loginType.value = type;-->
|
|
|
+<!-- if (type === 'dingding') {-->
|
|
|
+<!-- initDingLogin();-->
|
|
|
+<!-- }-->
|
|
|
+<!--};-->
|
|
|
+
|
|
|
+
|
|
|
+<!--const initDingLogin=()=> {-->
|
|
|
+<!-- // if (window.DDLogin) {-->
|
|
|
+<!-- var url = dingRedirectUrl-->
|
|
|
+<!-- var state = _getRandomString(10);-->
|
|
|
+<!-- var gotoUrl = encodeURIComponent(-->
|
|
|
+<!-- "https://oapi.dingtalk.com/connect/oauth2/sns_authorize?" +-->
|
|
|
+<!-- "appid=" + appId +-->
|
|
|
+<!-- "&response_type=code" +-->
|
|
|
+<!-- "&scope=snsapi_login" +-->
|
|
|
+<!-- "&state=" + state +-->
|
|
|
+<!-- "&redirect_uri=" + url-->
|
|
|
+<!-- );-->
|
|
|
+
|
|
|
+<!-- nextTick(() => {-->
|
|
|
+<!-- var obj = window.DDLogin({-->
|
|
|
+<!-- id: "login_container",-->
|
|
|
+<!-- goto: gotoUrl,-->
|
|
|
+<!-- style: "border:none;background-color:#FFFFFF;",-->
|
|
|
+<!-- width: '90%', // 二维码的宽度-->
|
|
|
+<!-- height: "290", // 二维码的高度-->
|
|
|
+<!-- })-->
|
|
|
+<!-- // 重置扫码登录框的样式,让登录框居中-->
|
|
|
+<!-- let box = document.getElementById('login_container')-->
|
|
|
+<!-- box.querySelector('iframe').style.top = '0'-->
|
|
|
+<!-- box.querySelector('iframe').style.bottom = '0'-->
|
|
|
+<!-- box.querySelector('iframe').style.left = '0'-->
|
|
|
+<!-- box.querySelector('iframe').style.right = '0'-->
|
|
|
+<!-- box.querySelector('iframe').style.margin = 'auto'-->
|
|
|
+<!-- })-->
|
|
|
+
|
|
|
+<!-- /* new window.DDLogin({-->
|
|
|
+<!-- id: "login_container",-->
|
|
|
+<!-- goto: gotoUrl,-->
|
|
|
+<!-- style: "border:none;background-color:#FFFFFF;",-->
|
|
|
+<!-- width: "350",-->
|
|
|
+<!-- height: "350",-->
|
|
|
+<!-- }); */-->
|
|
|
+<!-- var handleMessage = function (event) {-->
|
|
|
+<!-- var origin = event.origin;-->
|
|
|
+<!-- if (origin === "https://login.dingtalk.com") {-->
|
|
|
+<!-- var loginTmpCode = event.data;-->
|
|
|
+<!-- console.log(loginTmpCode)-->
|
|
|
+<!-- window.location.href =-->
|
|
|
+<!-- "https://oapi.dingtalk.com/connect/oauth2/sns_authorize?appid=dingik345qmyhtysvs2x&response_type=code&scope=snsapi_login&state=" +-->
|
|
|
+<!-- state +-->
|
|
|
+<!-- "&redirect_uri=" +-->
|
|
|
+<!-- url +-->
|
|
|
+<!-- "&loginTmpCode=" +-->
|
|
|
+<!-- loginTmpCode;-->
|
|
|
+<!-- }-->
|
|
|
+<!-- };-->
|
|
|
+<!-- if (typeof window.addEventListener != "undefined") {-->
|
|
|
+<!-- window.addEventListener("message", handleMessage, false);-->
|
|
|
+<!-- } else if (typeof window.attachEvent != "undefined") {-->
|
|
|
+<!-- window.attachEvent("onmessage", handleMessage);-->
|
|
|
+<!-- }-->
|
|
|
+<!-- // }-->
|
|
|
+<!--}-->
|
|
|
+<!--const _getRandomString=(len)=> {-->
|
|
|
+<!-- len = len || 10;-->
|
|
|
+<!-- let $chars = "ABCDEFGHIJKMNOPQRSTUVWXYZ"; // 默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1-->
|
|
|
+<!-- let maxPos = $chars.length;-->
|
|
|
+<!-- let pwd = "";-->
|
|
|
+<!-- for (var i = 0; i < len; i++) {-->
|
|
|
+<!-- pwd += $chars.charAt(Math.floor(Math.random() * maxPos));-->
|
|
|
+<!-- }-->
|
|
|
+<!-- return pwd;-->
|
|
|
+<!--}-->
|
|
|
+<!--defineOptions({ name: 'LoginForm' })-->
|
|
|
+
|
|
|
+<!--const { t } = useI18n()-->
|
|
|
+<!--const message = useMessage()-->
|
|
|
+<!--const iconHouse = useIcon({ icon: 'ep:house' })-->
|
|
|
+<!--const iconAvatar = useIcon({ icon: 'ep:avatar',size:26 })-->
|
|
|
+<!--const iconLock = useIcon({ icon: 'ep:lock',size:26 })-->
|
|
|
+<!--const formLogin = ref()-->
|
|
|
+<!--const { validForm } = useFormValid(formLogin)-->
|
|
|
+<!--const { setLoginState, getLoginState } = useLoginState()-->
|
|
|
+<!--const { currentRoute, push } = useRouter()-->
|
|
|
+<!--const permissionStore = usePermissionStore()-->
|
|
|
+<!--const redirect = ref<string>('')-->
|
|
|
+<!--const loginLoading = ref(false)-->
|
|
|
+<!--const verify = ref()-->
|
|
|
+<!--const captchaType = ref('blockPuzzle') // blockPuzzle 滑块 clickWord 点击文字-->
|
|
|
+
|
|
|
+<!--const getShow = computed(() => unref(getLoginState) === LoginStateEnum.LOGIN)-->
|
|
|
+
|
|
|
+<!--const LoginRules = {-->
|
|
|
+<!-- tenantName: [required],-->
|
|
|
+<!-- username: [required],-->
|
|
|
+<!-- password: [required]-->
|
|
|
+<!--}-->
|
|
|
+<!--const loginData = reactive({-->
|
|
|
+<!-- isShowPassword: false,-->
|
|
|
+<!-- captchaEnable: import.meta.env.VITE_APP_CAPTCHA_ENABLE,-->
|
|
|
+<!-- tenantEnable: import.meta.env.VITE_APP_TENANT_ENABLE,-->
|
|
|
+<!-- loginForm: {-->
|
|
|
+<!-- tenantName: '瑞气能源',-->
|
|
|
+<!-- username: import.meta.env.VITE_APP_DEFAULT_LOGIN_USERNAME || '',-->
|
|
|
+<!-- password: import.meta.env.VITE_APP_DEFAULT_LOGIN_PASSWORD || '',-->
|
|
|
+<!-- captchaVerification: '',-->
|
|
|
+<!-- rememberMe: true // 默认记录我。如果不需要,可手动修改-->
|
|
|
+<!-- }-->
|
|
|
+<!--})-->
|
|
|
+
|
|
|
+<!--// const socialList = [-->
|
|
|
+<!--// { icon: 'ant-design:wechat-filled', type: 30 },-->
|
|
|
+<!--// { icon: 'ant-design:dingtalk-circle-filled', type: 20 },-->
|
|
|
+<!--// { icon: 'ant-design:github-filled', type: 0 },-->
|
|
|
+<!--// { icon: 'ant-design:alipay-circle-filled', type: 0 }-->
|
|
|
+<!--// ]-->
|
|
|
+
|
|
|
+<!--// 获取验证码-->
|
|
|
+<!--const getCode = async () => {-->
|
|
|
+<!-- // 情况一,未开启:则直接登录-->
|
|
|
+<!-- if (loginData.captchaEnable === 'false') {-->
|
|
|
+<!-- await handleLogin({})-->
|
|
|
+<!-- } else {-->
|
|
|
+<!-- // 情况二,已开启:则展示验证码;只有完成验证码的情况,才进行登录-->
|
|
|
+<!-- // 弹出验证码-->
|
|
|
+<!-- verify.value.show()-->
|
|
|
+<!-- }-->
|
|
|
+<!--}-->
|
|
|
+<!--// 获取租户 ID-->
|
|
|
+<!--const getTenantId = async () => {-->
|
|
|
+<!-- if (loginData.tenantEnable === 'true') {-->
|
|
|
+<!-- const res = await LoginApi.getTenantIdByName(loginData.loginForm.tenantName)-->
|
|
|
+<!-- authUtil.setTenantId(res)-->
|
|
|
+<!-- }-->
|
|
|
+<!--}-->
|
|
|
+<!--// 记住我-->
|
|
|
+<!--const getLoginFormCache = () => {-->
|
|
|
+<!-- const loginForm = authUtil.getLoginForm()-->
|
|
|
+<!-- if (loginForm) {-->
|
|
|
+<!-- loginData.loginForm = {-->
|
|
|
+<!-- ...loginData.loginForm,-->
|
|
|
+<!-- username: loginForm.username ? loginForm.username : loginData.loginForm.username,-->
|
|
|
+<!-- password: loginForm.password ? loginForm.password : loginData.loginForm.password,-->
|
|
|
+<!-- rememberMe: loginForm.rememberMe,-->
|
|
|
+<!-- tenantName: loginForm.tenantName ? loginForm.tenantName : loginData.loginForm.tenantName-->
|
|
|
+<!-- }-->
|
|
|
+<!-- }-->
|
|
|
+<!--}-->
|
|
|
+<!--// 根据域名,获得租户信息-->
|
|
|
+<!--const getTenantByWebsite = async () => {-->
|
|
|
+<!-- const website = location.host-->
|
|
|
+<!-- const res = await LoginApi.getTenantByWebsite(website)-->
|
|
|
+<!-- if (res) {-->
|
|
|
+<!-- loginData.loginForm.tenantName = res.name-->
|
|
|
+<!-- authUtil.setTenantId(res.id)-->
|
|
|
+<!-- }-->
|
|
|
+<!--}-->
|
|
|
+<!--const loading = ref() // ElLoading.service 返回的实例-->
|
|
|
+<!--// 登录-->
|
|
|
+<!--const handleLogin = async (params: any) => {-->
|
|
|
+<!-- loginLoading.value = true-->
|
|
|
+<!-- try {-->
|
|
|
+<!-- await getTenantId()-->
|
|
|
+<!-- const data = await validForm()-->
|
|
|
+<!-- if (!data) {-->
|
|
|
+<!-- return-->
|
|
|
+<!-- }-->
|
|
|
+<!-- const loginDataLoginForm = { ...loginData.loginForm }-->
|
|
|
+<!-- loginDataLoginForm.captchaVerification = params.captchaVerification-->
|
|
|
+<!-- const res = await LoginApi.login(loginDataLoginForm)-->
|
|
|
+<!-- if (!res) {-->
|
|
|
+<!-- return-->
|
|
|
+<!-- }-->
|
|
|
+<!-- loading.value = ElLoading.service({-->
|
|
|
+<!-- lock: true,-->
|
|
|
+<!-- text: '正在加载系统中...',-->
|
|
|
+<!-- background: 'rgba(0, 0, 0, 0.7)'-->
|
|
|
+<!-- })-->
|
|
|
+<!-- if (loginDataLoginForm.rememberMe) {-->
|
|
|
+<!-- authUtil.setLoginForm(loginDataLoginForm)-->
|
|
|
+<!-- } else {-->
|
|
|
+<!-- authUtil.removeLoginForm()-->
|
|
|
+<!-- }-->
|
|
|
+<!-- authUtil.setToken(res)-->
|
|
|
+<!-- if (!redirect.value) {-->
|
|
|
+<!-- redirect.value = '/'-->
|
|
|
+<!-- }-->
|
|
|
+<!-- // 判断是否为SSO登录-->
|
|
|
+<!-- if (redirect.value.indexOf('sso') !== -1) {-->
|
|
|
+<!-- window.location.href = window.location.href.replace('/login?redirect=', '')-->
|
|
|
+<!-- } else {-->
|
|
|
+<!-- await push({ path: redirect.value || permissionStore.addRouters[0].path })-->
|
|
|
+<!-- }-->
|
|
|
+<!-- } finally {-->
|
|
|
+<!-- loginLoading.value = false-->
|
|
|
+<!-- loading.value.close()-->
|
|
|
+<!-- }-->
|
|
|
+<!--}-->
|
|
|
+
|
|
|
+<!--// 社交登录-->
|
|
|
+<!--watch(-->
|
|
|
+<!-- () => currentRoute.value,-->
|
|
|
+<!-- (route: RouteLocationNormalizedLoaded) => {-->
|
|
|
+<!-- redirect.value = route?.query?.redirect as string-->
|
|
|
+<!-- },-->
|
|
|
+<!-- {-->
|
|
|
+<!-- immediate: true-->
|
|
|
+<!-- }-->
|
|
|
+<!--)-->
|
|
|
+<!--onMounted(() => {-->
|
|
|
+<!-- getLoginFormCache()-->
|
|
|
+<!-- getTenantByWebsite()-->
|
|
|
+<!--})-->
|
|
|
+<!--</script>-->
|
|
|
+
|
|
|
+<!--<style lang="scss" scoped>-->
|
|
|
+<!--::v-deep .el-input__wrapper {-->
|
|
|
+<!-- background-color: transparent !important;-->
|
|
|
+<!-- height: 3.5em;-->
|
|
|
+<!-- color: white;-->
|
|
|
+<!-- box-shadow: none !important;-->
|
|
|
+<!-- border-radius: 0;-->
|
|
|
+<!-- border: none !important;-->
|
|
|
+<!-- border-bottom: 1px solid #bacde0 !important;-->
|
|
|
+<!-- outline: none;-->
|
|
|
+<!--}-->
|
|
|
+<!--:deep(.anticon) {-->
|
|
|
+<!-- &:hover {-->
|
|
|
+<!-- color: var(--el-color-primary) !important;-->
|
|
|
+<!-- }-->
|
|
|
+<!--}-->
|
|
|
+
|
|
|
+<!--.login-code {-->
|
|
|
+<!-- float: right;-->
|
|
|
+<!-- width: 100%;-->
|
|
|
+<!-- height: 38px;-->
|
|
|
+
|
|
|
+<!-- img {-->
|
|
|
+<!-- width: 100%;-->
|
|
|
+<!-- height: auto;-->
|
|
|
+<!-- max-width: 100px;-->
|
|
|
+<!-- vertical-align: middle;-->
|
|
|
+<!-- cursor: pointer;-->
|
|
|
+<!-- }-->
|
|
|
+<!--}-->
|
|
|
+<!--::v-deep .rqinput .el-input__inner {-->
|
|
|
+<!-- background-color: transparent !important;-->
|
|
|
+<!-- border: none !important;-->
|
|
|
+<!-- border-bottom: 1px solid rgb(186, 205, 224) !important;-->
|
|
|
+<!-- border-radius: 0;-->
|
|
|
+<!-- height: 2.8em;-->
|
|
|
+<!-- //left: 18%;-->
|
|
|
+<!-- padding-left: 3em;-->
|
|
|
+<!-- color: white;-->
|
|
|
+<!--}-->
|
|
|
+<!--.clickable-image {-->
|
|
|
+<!-- cursor: pointer;-->
|
|
|
+<!-- position:absolute;-->
|
|
|
+<!-- //top: 2%;-->
|
|
|
+<!-- //right: 2%;-->
|
|
|
+<!-- width: 6%;-->
|
|
|
+<!-- margin-top: -9%;-->
|
|
|
+<!-- margin-left: 111%;-->
|
|
|
+<!--}-->
|
|
|
+<!--::v-deep .el-input__inner {-->
|
|
|
+<!-- color: white;-->
|
|
|
+<!--}-->
|
|
|
+<!--</style>-->
|