|
@@ -1,32 +1,25 @@
|
|
|
<template>
|
|
|
- <div>
|
|
|
- <div class="absolute inset-0">
|
|
|
- <img src="/assets/images/auth/bg-gradient.png" alt="image" class="h-full w-full object-cover" />
|
|
|
- </div>
|
|
|
-
|
|
|
- <div
|
|
|
- class="relative flex items-center justify-center bg-[url(/assets/images/auth/map.png)] bg-cover bg-center bg-no-repeat dark:bg-[#060818] sm:px-16">
|
|
|
-
|
|
|
-
|
|
|
- <img src="/assets/images/auth/coming-soon-object3.png" alt="image"
|
|
|
- class="absolute right-0 top-0 h-[300px]" />
|
|
|
+ <div>
|
|
|
+ <div class="absolute inset-0">
|
|
|
+ <img src="/assets/images/auth/bg-gradient.png" alt="image" class="h-full w-full object-cover" />
|
|
|
+ </div>
|
|
|
|
|
|
- <div
|
|
|
- class="relative w-full max-w-[870px] rounded-md bg-[linear-gradient(45deg,#fff9f9_0%,rgba(255,255,255,0)_25%,rgba(255,255,255,0)_75%,_#fff9f9_100%)] p-2 dark:bg-[linear-gradient(52.22deg,#0E1726_0%,rgba(14,23,38,0)_18.66%,rgba(14,23,38,0)_51.04%,rgba(14,23,38,0)_80.07%,#0E1726_100%)]">
|
|
|
- <div
|
|
|
- class="relative flex flex-col justify-center rounded-md bg-white/60 backdrop-blur-lg dark:bg-black/50 px-6 lg:min-h-[758px] py-20">
|
|
|
- <div class="absolute top-6 end-6">
|
|
|
- <div class="dropdown">
|
|
|
+ <div class="relative flex items-center justify-center bg-[url(/assets/images/auth/map.png)] bg-cover bg-center bg-no-repeat dark:bg-[#060818] sm:px-16">
|
|
|
+ <img src="/assets/images/auth/coming-soon-object3.png" alt="image" class="absolute right-0 top-0 h-[300px]" />
|
|
|
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <div class="mx-auto w-full max-w-[440px]">
|
|
|
- <div class="mb-10">
|
|
|
- <h1 class="text-3xl font-extrabold uppercase !leading-snug text-primary md:text-4xl">Sign in
|
|
|
- </h1>
|
|
|
- <p class="text-base font-bold leading-normal text-white-dark">欢迎登录V3StudioApp</p>
|
|
|
- </div>
|
|
|
- <!-- <form class="space-y-5 dark:text-white" @submit.prevent="router.push('/')">
|
|
|
+ <div
|
|
|
+ class="relative w-full max-w-[870px] rounded-md bg-[linear-gradient(45deg,#fff9f9_0%,rgba(255,255,255,0)_25%,rgba(255,255,255,0)_75%,_#fff9f9_100%)] p-2 dark:bg-[linear-gradient(52.22deg,#0E1726_0%,rgba(14,23,38,0)_18.66%,rgba(14,23,38,0)_51.04%,rgba(14,23,38,0)_80.07%,#0E1726_100%)]"
|
|
|
+ >
|
|
|
+ <div class="relative flex flex-col justify-center rounded-md bg-white/60 backdrop-blur-lg dark:bg-black/50 px-6 lg:min-h-[758px] py-20">
|
|
|
+ <div class="absolute top-6 end-6">
|
|
|
+ <div class="dropdown"></div>
|
|
|
+ </div>
|
|
|
+ <div class="mx-auto w-full max-w-[440px]">
|
|
|
+ <div class="mb-10">
|
|
|
+ <h1 class="text-3xl font-extrabold uppercase !leading-snug text-primary md:text-4xl">Sign in</h1>
|
|
|
+ <p class="text-base font-bold leading-normal text-white-dark">欢迎登录V3StudioApp</p>
|
|
|
+ </div>
|
|
|
+ <!-- <form class="space-y-5 dark:text-white" @submit.prevent="router.push('/')">
|
|
|
<div>
|
|
|
<label for="Email">请输入账号</label>
|
|
|
<div class="relative text-white-dark">
|
|
@@ -58,61 +51,68 @@
|
|
|
登录
|
|
|
</button>
|
|
|
</form> -->
|
|
|
- <!-- <el-button @click="goHome">测试</el-button> -->
|
|
|
- <el-form :model="loginForm" :rules="loginRules" ref="loginFormRef" class="login-input">
|
|
|
- <el-form-item prop="username">
|
|
|
- <el-input v-model="loginForm.username" :placeholder="$t('username')" autofocus
|
|
|
- clearable>
|
|
|
- <template v-slot:prefix>
|
|
|
- <svg-icon class="el-input__icon" icon-class="user" />
|
|
|
- </template>
|
|
|
- </el-input>
|
|
|
- </el-form-item>
|
|
|
- <el-form-item prop="password">
|
|
|
- <el-input v-model="loginForm.password" type="password" autocomplete="off"
|
|
|
- :placeholder="$t('password')" :minlength="6" :maxlength="20" clearable>
|
|
|
- <template v-slot:prefix>
|
|
|
- <svg-icon class="el-input__icon" icon-class="password" />
|
|
|
- </template>
|
|
|
- </el-input>
|
|
|
- </el-form-item>
|
|
|
- <el-form-item prop="validcode" v-if="validateInFO.validator_type === 'IMAGE'">
|
|
|
- <el-input v-model="loginForm.validcode" :placeholder="$t('validcode')" :maxlength="4"
|
|
|
- clearable>
|
|
|
- <template v-slot:append>
|
|
|
- <img class="login-validcode-img" :src="validcodeImg" @click="changeValidcode">
|
|
|
- </template>
|
|
|
- </el-input>
|
|
|
- </el-form-item>
|
|
|
- <div v-else-if="validateInFO.validator_type === 'ALIYUN'" style="margin-bottom: 20px">
|
|
|
- <div id="pc-valid" class="nc-container"></div>
|
|
|
- </div>
|
|
|
- <el-form-item>
|
|
|
- <el-button type="primary" :loading="loading" :disabled="!accountAfsSuccess" class="btn"
|
|
|
- @click="submitLogin(loginFormRef)">
|
|
|
- {{ $t('logIn') }}
|
|
|
- </el-button>
|
|
|
- </el-form-item>
|
|
|
- </el-form>
|
|
|
- <!-- 新用户注册账号--暂不开放 -->
|
|
|
- <!-- <div class="relative my-7 text-center md:mb-9">
|
|
|
+ <!-- <el-button @click="goHome">测试</el-button> -->
|
|
|
+ <el-form :model="loginForm" :rules="loginRules" ref="loginFormRef" class="login-input">
|
|
|
+ <el-form-item prop="company_name">
|
|
|
+ <el-select v-model="loginForm.company_name" filterable :placeholder="$t('company_name')" style="width: 240px">
|
|
|
+ <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item prop="username">
|
|
|
+ <el-input v-model="loginForm.username" :placeholder="$t('username')" autofocus clearable>
|
|
|
+ <template v-slot:prefix>
|
|
|
+ <svg-icon class="el-input__icon" icon-class="user" />
|
|
|
+ </template>
|
|
|
+ </el-input>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item prop="password">
|
|
|
+ <el-input
|
|
|
+ v-model="loginForm.password"
|
|
|
+ type="password"
|
|
|
+ autocomplete="off"
|
|
|
+ :placeholder="$t('password')"
|
|
|
+ :minlength="6"
|
|
|
+ :maxlength="20"
|
|
|
+ clearable
|
|
|
+ >
|
|
|
+ <template v-slot:prefix>
|
|
|
+ <svg-icon class="el-input__icon" icon-class="password" />
|
|
|
+ </template>
|
|
|
+ </el-input>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item prop="validcode" v-if="validateInFO.validator_type === 'IMAGE'">
|
|
|
+ <el-input v-model="loginForm.validcode" :placeholder="$t('validcode')" :maxlength="4" clearable>
|
|
|
+ <template v-slot:append>
|
|
|
+ <img class="login-validcode-img h-8 w-full p-0" :src="validcodeImg" @click="changeValidcode" />
|
|
|
+ </template>
|
|
|
+ </el-input>
|
|
|
+ </el-form-item>
|
|
|
+ <div v-else-if="validateInFO.validator_type === 'ALIYUN'" style="margin-bottom: 20px">
|
|
|
+ <div id="pc-valid" class="nc-container"></div>
|
|
|
+ </div>
|
|
|
+ <el-form-item>
|
|
|
+ <el-button type="primary" :loading="loading" :disabled="!accountAfsSuccess" class="btn" @click="submitLogin(loginFormRef)">
|
|
|
+ {{ $t('logIn') }}
|
|
|
+ </el-button>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <!-- 新用户注册账号--暂不开放 -->
|
|
|
+ <!-- <div class="relative my-7 text-center md:mb-9">
|
|
|
<span class="absolute inset-x-0 top-1/2 h-px w-full -translate-y-1/2 bg-white-light dark:bg-white-dark"></span>
|
|
|
<span class="relative bg-white px-2 font-bold uppercase text-white-dark dark:bg-dark dark:text-white-light">or</span>
|
|
|
</div> -->
|
|
|
|
|
|
-
|
|
|
-
|
|
|
- <!-- <div class="text-center dark:text-white">
|
|
|
+ <!-- <div class="text-center dark:text-white">
|
|
|
新用户请注册 ?
|
|
|
<router-link to="/auth/boxed-signup" class="uppercase text-primary underline transition hover:text-black dark:hover:text-white">
|
|
|
注册
|
|
|
</router-link>
|
|
|
</div> -->
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
+ </div>
|
|
|
</template>
|
|
|
<script lang="ts" setup>
|
|
|
import { computed, onMounted, reactive, ref } from 'vue';
|
|
@@ -122,166 +122,168 @@ import appSetting from '@/app-setting';
|
|
|
import { useStore } from 'vuex';
|
|
|
import { useRouter, useRoute } from 'vue-router';
|
|
|
import { useMeta } from '@/composables/use-meta';
|
|
|
-import Storage from '@/utils/storage'
|
|
|
-import * as API_common from '@/api/common'
|
|
|
-import { v4 as uuidv4 } from "uuid";
|
|
|
-import AliyunAfs from '@/composables/AliyunAfs'
|
|
|
-import { ElMessage, FormInstance } from 'element-plus'
|
|
|
+import Storage from '@/utils/storage';
|
|
|
+import * as API_common from '@/api/common';
|
|
|
+import { v4 as uuidv4 } from 'uuid';
|
|
|
+import AliyunAfs from '@/composables/AliyunAfs';
|
|
|
+import { ElMessage, FormInstance } from 'element-plus';
|
|
|
import app from '@/stores/modules/app';
|
|
|
|
|
|
+const loading: any = ref(false);
|
|
|
+
|
|
|
+const options:any=ref([])
|
|
|
|
|
|
-const loading: any = ref(false)
|
|
|
const loginForm = reactive({
|
|
|
- username: '',
|
|
|
- password: '',
|
|
|
- scene: 'LOGIN',
|
|
|
- validcode: '',
|
|
|
- company_name: 'aslkf'
|
|
|
+ username: '',
|
|
|
+ password: '',
|
|
|
+ scene: 'LOGIN',
|
|
|
+ validcode: '',
|
|
|
+ company_name: 'aslkf',
|
|
|
});
|
|
|
const { t } = useI18n();
|
|
|
const loginRules = reactive({
|
|
|
- username: [
|
|
|
- { required: true, message: t('val_username'), trigger: 'blur' }
|
|
|
- ],
|
|
|
- password: [
|
|
|
- { required: true, message: t('val_password'), trigger: 'blur' }
|
|
|
- ],
|
|
|
- validcode: [
|
|
|
- { required: true, message: t('val_validcode'), trigger: 'blur' }
|
|
|
- ]
|
|
|
+ username: [{ required: true, message: t('val_username'), trigger: 'blur' }],
|
|
|
+ password: [{ required: true, message: t('val_password'), trigger: 'blur' }],
|
|
|
+ validcode: [{ required: true, message: t('val_validcode'), trigger: 'blur' }],
|
|
|
});
|
|
|
// 验证信息
|
|
|
-const validateInFO: any = ref({})
|
|
|
-let validcodeImg: any = ref('')
|
|
|
-let uuid: any = ref(Storage.getItem('admin_uuid'))
|
|
|
+const validateInFO: any = ref({});
|
|
|
+let validcodeImg: any = ref('');
|
|
|
+let uuid: any = ref(Storage.getItem('admin_uuid'));
|
|
|
// 阿里云验证条实例
|
|
|
-let afs: any = ref(null)
|
|
|
+let afs: any = ref(null);
|
|
|
// 当滑动验证成功之后返回的参数
|
|
|
const afsParam: any = ref({
|
|
|
- c_sessionid: '',
|
|
|
- sig: '',
|
|
|
- nc_token: ''
|
|
|
-})
|
|
|
+ c_sessionid: '',
|
|
|
+ sig: '',
|
|
|
+ nc_token: '',
|
|
|
+});
|
|
|
// 阿里云滑动验证是否通过 && 如果不是 阿里云验证则直接设置为 true
|
|
|
-const accountAfsSuccess: any = ref(false)
|
|
|
+const accountAfsSuccess: any = ref(false);
|
|
|
// 是否为加盟商登录
|
|
|
-const is_franchise: any = ref(false)
|
|
|
-const loginFormRef = ref<FormInstance>()
|
|
|
-
|
|
|
+const is_franchise: any = ref(false);
|
|
|
+const loginFormRef = ref<FormInstance>();
|
|
|
|
|
|
useMeta({ title: 'Login Boxed' });
|
|
|
const router = useRouter();
|
|
|
-const route = useRoute()
|
|
|
+const route = useRoute();
|
|
|
const store = useStore();
|
|
|
// multi language
|
|
|
const i18n = reactive(useI18n());
|
|
|
console.log(i18n);
|
|
|
const changeLanguage = (item: any) => {
|
|
|
- i18n.locale = item.code;
|
|
|
- appSetting.toggleLanguage(item);
|
|
|
+ i18n.locale = item.code;
|
|
|
+ appSetting.toggleLanguage(item);
|
|
|
};
|
|
|
const currentFlag = computed(() => {
|
|
|
- return `/assets/images/flags/${i18n.locale.toUpperCase()}.svg`;
|
|
|
+ return `/assets/images/flags/${i18n.locale.toUpperCase()}.svg`;
|
|
|
});
|
|
|
|
|
|
onMounted(() => {
|
|
|
- const uuids = Storage.getItem('admin_uuid')
|
|
|
- if (uuids) {
|
|
|
- uuid = uuids
|
|
|
+ const uuids = Storage.getItem('admin_uuid');
|
|
|
+ if (uuids) {
|
|
|
+ uuid = uuids;
|
|
|
+ } else {
|
|
|
+ const _uuid = uuidv4();
|
|
|
+ uuid = _uuid;
|
|
|
+ Storage.setItem('admin_uuid', _uuid, { expires: 30 });
|
|
|
+ }
|
|
|
+ changeValidcode();
|
|
|
+ API_common.getValidator().then((res) => {
|
|
|
+ validateInFO.value = res;
|
|
|
+ const { validator_type, aliyun_afs } = res;
|
|
|
+ if (validator_type === 'ALIYUN') {
|
|
|
+ //afs = new AliyunAfs('#pc-valid', aliyun_afs.scene, aliyun_afs.app_key, initCaptcha)
|
|
|
+ afs.init();
|
|
|
} else {
|
|
|
- const _uuid = uuidv4()
|
|
|
- uuid = _uuid
|
|
|
- Storage.setItem('admin_uuid', _uuid, { expires: 30 })
|
|
|
+ accountAfsSuccess.value = true;
|
|
|
}
|
|
|
- changeValidcode();
|
|
|
- API_common.getValidator().then(res => {
|
|
|
- validateInFO.value = res
|
|
|
- const { validator_type, aliyun_afs } = res
|
|
|
- if (validator_type === 'ALIYUN') {
|
|
|
- //afs = new AliyunAfs('#pc-valid', aliyun_afs.scene, aliyun_afs.app_key, initCaptcha)
|
|
|
- afs.init()
|
|
|
- } else {
|
|
|
- accountAfsSuccess.value = true
|
|
|
- }
|
|
|
- })
|
|
|
+ });
|
|
|
});
|
|
|
|
|
|
/** 阿里云滑动验证 通过后的回调函数 **/
|
|
|
const initCaptcha = (data) => {
|
|
|
- afsParam.c_sessionid = data.csessionid
|
|
|
- afsParam.sig = data.sig
|
|
|
- afsParam.nc_token = data.nc_token
|
|
|
- accountAfsSuccess.value = true
|
|
|
-}
|
|
|
+ afsParam.c_sessionid = data.csessionid;
|
|
|
+ afsParam.sig = data.sig;
|
|
|
+ afsParam.nc_token = data.nc_token;
|
|
|
+ accountAfsSuccess.value = true;
|
|
|
+};
|
|
|
|
|
|
/** 更换图片验证码 */
|
|
|
const changeValidcode = () => {
|
|
|
- validcodeImg = API_common.getValidateCodeUrl('LOGIN', uuid)
|
|
|
- console.log(validcodeImg);
|
|
|
-}
|
|
|
+ validcodeImg.value = API_common.getValidateCodeUrl('LOGIN', uuid);
|
|
|
+ console.log(validcodeImg);
|
|
|
+};
|
|
|
const MixinClone = (obj) => {
|
|
|
- return JSON.parse(JSON.stringify(obj))
|
|
|
-}
|
|
|
+ return JSON.parse(JSON.stringify(obj));
|
|
|
+};
|
|
|
|
|
|
/** 登录处理 */
|
|
|
const dispatchLoginAction = (params) => {
|
|
|
- loading.value = true;
|
|
|
- return new Promise((resolve, reject) => {
|
|
|
- store.dispatch('loginAction', params).then((res: any) => {
|
|
|
- loading.value = false;
|
|
|
- if (res) {
|
|
|
- try {
|
|
|
- const WS = new WebSocket(res.access_token);
|
|
|
- // 使用 provide/inject 或其他方式在 Vue 3 中共享 WebSocket 实例
|
|
|
- app.provide('websocket', WS);
|
|
|
- } catch (error) {
|
|
|
- console.log('websocket 实例化失败:', error);
|
|
|
- }
|
|
|
- }
|
|
|
- const forward = route.query.forward;
|
|
|
- let query = JSON.parse(JSON.stringify(route.query));
|
|
|
- delete query.forward
|
|
|
- router.push({ path: 'dashboard', query }).catch(() => { }); //forward ||
|
|
|
- }).catch(() => {
|
|
|
- loading.value = false;
|
|
|
- reject();
|
|
|
- });
|
|
|
- });
|
|
|
-}
|
|
|
+ loading.value = true;
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
+ store
|
|
|
+ .dispatch('loginAction', params)
|
|
|
+ .then((res: any) => {
|
|
|
+ loading.value = false;
|
|
|
+ if (res) {
|
|
|
+ try {
|
|
|
+ const WS = new WebSocket(res.access_token);
|
|
|
+ // 使用 provide/inject 或其他方式在 Vue 3 中共享 WebSocket 实例
|
|
|
+ app.provide('websocket', WS);
|
|
|
+ } catch (error) {
|
|
|
+ console.log('websocket 实例化失败:', error);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const forward = route.query.forward;
|
|
|
+ let query = JSON.parse(JSON.stringify(route.query));
|
|
|
+ delete query.forward;
|
|
|
+ router.push({ path: '/', query }).catch(() => {}); //forward ||
|
|
|
+ })
|
|
|
+ .catch(() => {
|
|
|
+ loading.value = false;
|
|
|
+ reject();
|
|
|
+ });
|
|
|
+ });
|
|
|
+};
|
|
|
|
|
|
const submitLogin = (formEl: FormInstance | undefined) => {
|
|
|
- if (!accountAfsSuccess) return
|
|
|
- console.log(!afs);
|
|
|
- if (!afs) {
|
|
|
- const params = MixinClone(loginForm)
|
|
|
- params.c_sessionid = afsParam.c_sessionid
|
|
|
- params.sig = afsParam.sig
|
|
|
- params.nc_token = afsParam.nc_token
|
|
|
- delete params.validcode
|
|
|
- delete params.scene
|
|
|
+ if (!accountAfsSuccess) return;
|
|
|
+ console.log(!afs);
|
|
|
+ if (!afs) {
|
|
|
+ const params = MixinClone(loginForm);
|
|
|
+ params.c_sessionid = afsParam.c_sessionid;
|
|
|
+ params.sig = afsParam.sig;
|
|
|
+ params.nc_token = afsParam.nc_token;
|
|
|
+ delete params.validcode;
|
|
|
+ delete params.scene;
|
|
|
+ dispatchLoginAction(params).catch(() => {
|
|
|
+ accountAfsSuccess.value = false;
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ formEl?.validate((valid: boolean) => {
|
|
|
+ if (valid) {
|
|
|
+ const params = MixinClone(loginForm);
|
|
|
+ params.uuid = uuid;
|
|
|
+ params.captcha = params.validcode;
|
|
|
+ delete params.validcode;
|
|
|
dispatchLoginAction(params).catch(() => {
|
|
|
- accountAfsSuccess.value = false
|
|
|
- })
|
|
|
- } else {
|
|
|
- formEl?.validate((valid: boolean) => {
|
|
|
- if (valid) {
|
|
|
- const params = MixinClone(loginForm);
|
|
|
- params.uuid = uuid;
|
|
|
- params.captcha = params.validcode;
|
|
|
- delete params.validcode;
|
|
|
- dispatchLoginAction(params).catch(() => {
|
|
|
- changeValidcode();
|
|
|
- });
|
|
|
- } else {
|
|
|
- // 使用 Element Plus 的消息提示
|
|
|
- ElMessage.error(t('val_form'));
|
|
|
- return false;
|
|
|
- }
|
|
|
+ changeValidcode();
|
|
|
});
|
|
|
- }
|
|
|
-}
|
|
|
+ } else {
|
|
|
+ // 使用 Element Plus 的消息提示
|
|
|
+ ElMessage.error(t('val_form'));
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+};
|
|
|
const goHome = () => {
|
|
|
- router.push({ path: 'dashboard' }).catch(() => { })
|
|
|
-}
|
|
|
-
|
|
|
+ router.push({ path: 'dashboard' }).catch(() => {});
|
|
|
+};
|
|
|
</script>
|
|
|
+<style>
|
|
|
+.el-input-group__append {
|
|
|
+ padding: 0;
|
|
|
+}
|
|
|
+</style>
|