|
@@ -1,165 +1,94 @@
|
|
|
<template>
|
|
|
- <div class="login login-box">
|
|
|
- <div class="login-theme"><h2>知学知考</h2></div>
|
|
|
- <div class="login-body" @keyup.enter="submit">
|
|
|
- <div class="login-title">
|
|
|
- <img v-if="schoolInfo.logo" :src="schoolInfo.logo" alt="学校logo" />
|
|
|
- <h1 v-else>知学知考</h1>
|
|
|
- </div>
|
|
|
- <div class="login-form">
|
|
|
- <a-form
|
|
|
- ref="formRef"
|
|
|
- :model="formData"
|
|
|
- :rules="rules"
|
|
|
- :label-col-props="{ span: 0, offset: 0 }"
|
|
|
- :wrapper-col-props="{ span: 24, offset: 0 }"
|
|
|
- >
|
|
|
- <!-- account -->
|
|
|
- <template v-if="IS_USERNAME_TYPE">
|
|
|
- <a-form-item field="loginName">
|
|
|
- <a-input
|
|
|
- v-model.trim="formData.loginName"
|
|
|
- placeholder="请输入账号"
|
|
|
- allow-clear
|
|
|
- >
|
|
|
- <template #prefix>
|
|
|
- <icon-user />
|
|
|
- </template>
|
|
|
- </a-input>
|
|
|
- </a-form-item>
|
|
|
- <a-form-item field="password">
|
|
|
- <a-input-password
|
|
|
- v-model.trim="formData.password"
|
|
|
- placeholder="请输入密码"
|
|
|
- allow-clear
|
|
|
- >
|
|
|
- <template #prefix>
|
|
|
- <icon-lock />
|
|
|
- </template>
|
|
|
- </a-input-password>
|
|
|
- </a-form-item>
|
|
|
- <a-form-item v-if="schoolInfo.accountSmsVerify" field="code">
|
|
|
- <div class="box-justify">
|
|
|
- <a-input
|
|
|
- v-model.trim="formData.code"
|
|
|
- placeholder="请输入手机验证码"
|
|
|
- allow-clear
|
|
|
- >
|
|
|
- <template #prefix>
|
|
|
- <icon-message />
|
|
|
- </template>
|
|
|
- </a-input>
|
|
|
- <a-button
|
|
|
- type="primary"
|
|
|
- :disabled="isFetchingCode"
|
|
|
- @click="fetchAccountSmsCode"
|
|
|
- >{{ codeContent }}</a-button
|
|
|
- >
|
|
|
- </div>
|
|
|
- </a-form-item>
|
|
|
- </template>
|
|
|
- <!-- mobile -->
|
|
|
- <template v-else>
|
|
|
- <a-form-item field="mobileNumber">
|
|
|
- <a-input
|
|
|
- v-model.trim="formData.mobileNumber"
|
|
|
- placeholder="请输入手机号"
|
|
|
- allow-clear
|
|
|
- >
|
|
|
- <template #prefix> <icon-mobile /> </template>
|
|
|
- </a-input>
|
|
|
- </a-form-item>
|
|
|
- <a-form-item field="code">
|
|
|
- <div class="box-justify">
|
|
|
- <a-input
|
|
|
- v-model.trim="formData.code"
|
|
|
- placeholder="请输入手机验证码"
|
|
|
- allow-clear
|
|
|
- >
|
|
|
- <template #prefix>
|
|
|
- <icon-message />
|
|
|
- </template>
|
|
|
- </a-input>
|
|
|
- <a-button
|
|
|
- type="primary"
|
|
|
- :disabled="isFetchingCode"
|
|
|
- @click="fetchMobileSmsCode"
|
|
|
- >{{ codeContent }}</a-button
|
|
|
- >
|
|
|
- </div>
|
|
|
- </a-form-item>
|
|
|
- </template>
|
|
|
- <a-form-item>
|
|
|
- <a-button type="primary" :loading="loading" long @click="submit"
|
|
|
- >登录</a-button
|
|
|
- >
|
|
|
- </a-form-item>
|
|
|
- </a-form>
|
|
|
- </div>
|
|
|
- <div v-if="schoolInfo.phoneLogin" class="login-action box-justify">
|
|
|
- <div></div>
|
|
|
- <a-button type="text" @click="switchLoginType">
|
|
|
- <i>{{ switchBtnName }}</i>
|
|
|
- <icon-right />
|
|
|
- </a-button>
|
|
|
+ <div class="login" @keyup.enter="submit">
|
|
|
+ <div class="login-spin">
|
|
|
+ <h1>欢迎使用</h1>
|
|
|
+ <h4>知学知考-图片导出工具</h4>
|
|
|
+ </div>
|
|
|
+ <div class="login-body">
|
|
|
+ <div class="login-head">
|
|
|
+ <div class="login-head-left">
|
|
|
+ <h2 class="login-head-title">登录</h2>
|
|
|
+ <h4 class="login-head-subtitle">请选择输入</h4>
|
|
|
+ </div>
|
|
|
+ <div class="login-head-right">
|
|
|
+ <a-button class="login-btn btn-setting" @click="toSet">设置</a-button>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
+ <a-form
|
|
|
+ ref="formRef"
|
|
|
+ :model="formData"
|
|
|
+ :rules="rules"
|
|
|
+ :label-col-props="{ span: 0, offset: 0 }"
|
|
|
+ :wrapper-col-props="{ span: 24, offset: 0 }"
|
|
|
+ >
|
|
|
+ <a-form-item field="schoolCode">
|
|
|
+ <a-select
|
|
|
+ v-model="formData.schoolCode"
|
|
|
+ placeholder="请选择学校"
|
|
|
+ name="schoolCode"
|
|
|
+ :options="schools"
|
|
|
+ >
|
|
|
+ </a-select>
|
|
|
+ </a-form-item>
|
|
|
+ <a-form-item field="loginName">
|
|
|
+ <a-input
|
|
|
+ v-model.trim="formData.loginName"
|
|
|
+ placeholder="请输入账号"
|
|
|
+ name="username"
|
|
|
+ allow-clear
|
|
|
+ >
|
|
|
+ </a-input>
|
|
|
+ </a-form-item>
|
|
|
+ <a-form-item field="password">
|
|
|
+ <a-input
|
|
|
+ v-model.trim="formData.password"
|
|
|
+ type="password"
|
|
|
+ placeholder="请输入密码"
|
|
|
+ allow-clear
|
|
|
+ >
|
|
|
+ </a-input>
|
|
|
+ </a-form-item>
|
|
|
+ <a-form-item>
|
|
|
+ <a-button type="primary" :loading="loading" long @click="submit"
|
|
|
+ >登录</a-button
|
|
|
+ >
|
|
|
+ </a-form-item>
|
|
|
+ </a-form>
|
|
|
</div>
|
|
|
-
|
|
|
- <!-- ResetPwd -->
|
|
|
- <ResetPwd
|
|
|
- ref="ResetPwdRef"
|
|
|
- :user-info="userInfo"
|
|
|
- @modified="resetPwdSuccess"
|
|
|
- @cancel="resetCancel"
|
|
|
- />
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script lang="ts" setup>
|
|
|
- import { ref, reactive, computed, onMounted } from 'vue';
|
|
|
- import { Message } from '@arco-design/web-vue';
|
|
|
- import { useRoute, useRouter } from 'vue-router';
|
|
|
- import type { FormInstance, FieldRule } from '@arco-design/web-vue/es/form';
|
|
|
- import { omit } from 'lodash';
|
|
|
+ import { ref, reactive, onMounted } from 'vue';
|
|
|
+ import { useRouter } from 'vue-router';
|
|
|
+ import type { FormInstance } from '@arco-design/web-vue/es/form';
|
|
|
import useLoading from '@/hooks/loading';
|
|
|
- import useSms from '@/hooks/sms';
|
|
|
- import {
|
|
|
- login,
|
|
|
- getSchoolInfo,
|
|
|
- getAccountSmsCode,
|
|
|
- getSmsCode,
|
|
|
- } from '@/api/user';
|
|
|
+ import { login, schoolList } from '@/api/user';
|
|
|
import { getBase64 } from '@/utils/crypto';
|
|
|
- import { smscode, phone } from '@/utils/formRules';
|
|
|
- import { getOrgCode } from '@/constants/app';
|
|
|
import { useAppStore, useUserStore } from '@/store';
|
|
|
- import { DEFAULT_ROUTE_NAME } from '@/router/constants';
|
|
|
- import { UserSchoolInfoType, UserState } from '@/store/modules/user/types';
|
|
|
- import type { LoginData, SchoolInfoRes } from '@/api/types/user';
|
|
|
- import { ResetPwdUserInfo } from './types';
|
|
|
+ import { UserSchoolInfoType } from '@/store/modules/user/types';
|
|
|
+ import type { LoginData } from '@/api/types/user';
|
|
|
+ import { FormRules, OptionListItem } from '@/types/global';
|
|
|
+ import { objAssign } from '@/utils/utils';
|
|
|
|
|
|
- import ResetPwd from './ResetPwd.vue';
|
|
|
+ defineOptions({
|
|
|
+ name: 'Login',
|
|
|
+ });
|
|
|
|
|
|
- const route = useRoute();
|
|
|
const router = useRouter();
|
|
|
const appStore = useAppStore();
|
|
|
const userStore = useUserStore();
|
|
|
- appStore.resetInfo();
|
|
|
userStore.resetInfo();
|
|
|
|
|
|
- const userInfo = ref({} as ResetPwdUserInfo);
|
|
|
- const schoolInfo = ref({} as SchoolInfoRes);
|
|
|
const formRef = ref<FormInstance>();
|
|
|
- const ResetPwdRef = ref();
|
|
|
- const formData = reactive<Required<LoginData>>({
|
|
|
- loginName: 'admin-zj',
|
|
|
- password: 'a12345678',
|
|
|
- code: '',
|
|
|
- mobileNumber: '',
|
|
|
- schoolCode: 'test-school-2',
|
|
|
+ const formData = reactive<LoginData>({
|
|
|
+ schoolCode: '',
|
|
|
type: 'ACCOUNT',
|
|
|
+ loginName: '',
|
|
|
+ password: '',
|
|
|
});
|
|
|
- const rules: Record<string, FieldRule[]> = {
|
|
|
+
|
|
|
+ const rules: FormRules<keyof LoginData> = {
|
|
|
loginName: [
|
|
|
{
|
|
|
required: true,
|
|
@@ -172,8 +101,6 @@
|
|
|
message: '请输入密码',
|
|
|
},
|
|
|
],
|
|
|
- code: smscode,
|
|
|
- mobileNumber: phone,
|
|
|
schoolCode: [
|
|
|
{
|
|
|
required: true,
|
|
@@ -182,114 +109,23 @@
|
|
|
],
|
|
|
};
|
|
|
|
|
|
- const IS_USERNAME_TYPE = computed(() => {
|
|
|
- return formData.type === 'ACCOUNT';
|
|
|
- });
|
|
|
- const switchBtnName = computed(() => {
|
|
|
- return formData.type === 'ACCOUNT' ? '短信登录' : '账号登录';
|
|
|
- });
|
|
|
-
|
|
|
- async function getSchool() {
|
|
|
- if (route.params.code) {
|
|
|
- formData.schoolCode = route.params.code as string;
|
|
|
- window.sessionStorage.setItem('routeDomainCode', formData.schoolCode);
|
|
|
- } else {
|
|
|
- formData.schoolCode = getOrgCode();
|
|
|
- }
|
|
|
- const data = await getSchoolInfo(formData.schoolCode);
|
|
|
- appStore.setInfo({ version: data.version || '' });
|
|
|
- formData.schoolCode = data.schoolCode;
|
|
|
- schoolInfo.value = data;
|
|
|
- }
|
|
|
-
|
|
|
- function switchLoginType() {
|
|
|
- if (!schoolInfo.value.phoneLogin) return;
|
|
|
- formData.type = formData.type === 'ACCOUNT' ? 'PHONE' : 'ACCOUNT';
|
|
|
+ function toSet() {
|
|
|
+ router.push({ name: 'Setting' });
|
|
|
}
|
|
|
|
|
|
- function resetPwdSuccess(data: UserState) {
|
|
|
- if (data.schoolInfo && data.schoolInfo.length) {
|
|
|
- const curSchool = data.schoolInfo.find(
|
|
|
- (item) => item.code === formData.schoolCode
|
|
|
- );
|
|
|
- data.curSchoolInfo = curSchool || ({} as UserSchoolInfoType);
|
|
|
- }
|
|
|
- userStore.setInfo(data);
|
|
|
-
|
|
|
- if (data.roleList && data.roleList.includes('ADMIN')) {
|
|
|
- router.push({
|
|
|
- name: 'SelectSchool',
|
|
|
- });
|
|
|
- } else {
|
|
|
- router.push({
|
|
|
- name: 'Home',
|
|
|
- });
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- function resetCancel() {
|
|
|
- userStore.resetInfo();
|
|
|
- }
|
|
|
-
|
|
|
- /* sms ----start */
|
|
|
- const { isFetchingCode, codeContent, changeContent } = useSms('login');
|
|
|
-
|
|
|
- async function fetchMobileSmsCode() {
|
|
|
- const unvalid = await formRef.value?.validateField([
|
|
|
- 'mobileNumber',
|
|
|
- 'schoolCode',
|
|
|
- ]);
|
|
|
- if (unvalid) return;
|
|
|
-
|
|
|
- isFetchingCode.value = true;
|
|
|
- const res = await getSmsCode({
|
|
|
- schoolCode: formData.schoolCode,
|
|
|
- mobileNumber: formData.mobileNumber,
|
|
|
- }).catch(() => {
|
|
|
- isFetchingCode.value = false;
|
|
|
- });
|
|
|
- if (!res) return;
|
|
|
-
|
|
|
- if (res.mobileNumber) {
|
|
|
- Message.success(
|
|
|
- `已向手机尾号【${res.mobileNumber.slice(
|
|
|
- -4
|
|
|
- )}】成功发送短信,请在2分钟内进行验证!`
|
|
|
- );
|
|
|
- changeContent();
|
|
|
- } else {
|
|
|
- Message.error('未绑定手机号,请先绑定!');
|
|
|
+ const schools = ref<OptionListItem[]>([]);
|
|
|
+ async function getSchools() {
|
|
|
+ if (!schools.value.length) {
|
|
|
+ schools.value = [{ value: 'test-school-1', label: '学校1' }];
|
|
|
+ return;
|
|
|
}
|
|
|
- }
|
|
|
-
|
|
|
- async function fetchAccountSmsCode() {
|
|
|
- const unvalid = await formRef.value?.validateField([
|
|
|
- 'loginName',
|
|
|
- 'schoolCode',
|
|
|
- 'password',
|
|
|
- ]);
|
|
|
- if (unvalid) return;
|
|
|
|
|
|
- isFetchingCode.value = true;
|
|
|
- const res = await getAccountSmsCode({
|
|
|
- schoolCode: formData.schoolCode,
|
|
|
- loginName: formData.loginName,
|
|
|
- password: getBase64(formData.password),
|
|
|
- }).catch(() => {
|
|
|
- isFetchingCode.value = false;
|
|
|
+ if (!appStore.domain) return;
|
|
|
+ const resData = await schoolList();
|
|
|
+ schools.value = (resData || []).map((item) => {
|
|
|
+ return { value: item.code, label: item.name };
|
|
|
});
|
|
|
- if (!res) return;
|
|
|
-
|
|
|
- if (res) {
|
|
|
- Message.success(
|
|
|
- `已向手机尾号【${res.slice(-4)}】成功发送短信,请在2分钟内进行验证!`
|
|
|
- );
|
|
|
- changeContent();
|
|
|
- } else {
|
|
|
- Message.error('未绑定手机号!');
|
|
|
- }
|
|
|
}
|
|
|
- /* sms ----end */
|
|
|
|
|
|
/* submit */
|
|
|
const { loading, setLoading } = useLoading();
|
|
@@ -298,18 +134,8 @@
|
|
|
if (err) return;
|
|
|
|
|
|
setLoading(true);
|
|
|
- let datas = {} as LoginData;
|
|
|
- if (IS_USERNAME_TYPE.value) {
|
|
|
- datas = omit(
|
|
|
- formData,
|
|
|
- schoolInfo.value.accountSmsVerify
|
|
|
- ? ['mobileNumber']
|
|
|
- : ['code', 'mobileNumber']
|
|
|
- );
|
|
|
- datas.password = getBase64(formData.password);
|
|
|
- } else {
|
|
|
- datas = omit(formData, ['loginName', 'password']);
|
|
|
- }
|
|
|
+ const datas = objAssign(formData, {});
|
|
|
+ datas.password = getBase64(formData.password);
|
|
|
const data = await login(datas).catch(() => {});
|
|
|
setLoading(false);
|
|
|
if (!data) return;
|
|
@@ -322,39 +148,18 @@
|
|
|
}
|
|
|
userStore.setInfo(data);
|
|
|
|
|
|
- // 强制修改密码和绑定手机号
|
|
|
- if (
|
|
|
- data.userLoginCheckResult &&
|
|
|
- (!data.userLoginCheckResult.pwdCount ||
|
|
|
- (!data.userLoginCheckResult.mobileNumber &&
|
|
|
- schoolInfo.value.phoneLogin))
|
|
|
- ) {
|
|
|
- userInfo.value = {
|
|
|
- userId: data.userLoginCheckResult.userId,
|
|
|
- loginName: formData.loginName,
|
|
|
- schoolCode: formData.schoolCode,
|
|
|
- password: formData.password,
|
|
|
- mobileNumber: data.userLoginCheckResult.mobileNumber,
|
|
|
- pwdCount: data.userLoginCheckResult.pwdCount,
|
|
|
- phoneLogin: schoolInfo.value.phoneLogin,
|
|
|
- };
|
|
|
- ResetPwdRef.value?.open();
|
|
|
- return;
|
|
|
- }
|
|
|
+ router.push({
|
|
|
+ name: 'SchoolSelect',
|
|
|
+ });
|
|
|
+ }
|
|
|
|
|
|
- if (data.roleList && data.roleList.includes('ADMIN')) {
|
|
|
- router.push({
|
|
|
- name: 'SchoolSelect',
|
|
|
- });
|
|
|
- } else {
|
|
|
- router.push({
|
|
|
- name: DEFAULT_ROUTE_NAME,
|
|
|
- });
|
|
|
- }
|
|
|
+ async function initData() {
|
|
|
+ const domain = await window.db.getDict('domain');
|
|
|
+ appStore.setInfo({ domain });
|
|
|
+ await getSchools();
|
|
|
}
|
|
|
|
|
|
- // mounted
|
|
|
onMounted(() => {
|
|
|
- getSchool();
|
|
|
+ initData();
|
|
|
});
|
|
|
</script>
|