diff --git a/apps/test-server/service/UserService.ts b/apps/test-server/service/UserService.ts index 0c395e5..968313a 100644 --- a/apps/test-server/service/UserService.ts +++ b/apps/test-server/service/UserService.ts @@ -2,8 +2,8 @@ import { Result } from '../utils'; const fakeUserInfo = { userId: '1', - username: 'vben', - realName: 'Vben Admin', + username: 'admin', + name: 'test Admin', desc: 'manager', password: '123456', token: 'fakeToken1', diff --git a/src/api/sys/model/userModel.ts b/src/api/sys/model/userModel.ts index ebd6489..76a16ca 100644 --- a/src/api/sys/model/userModel.ts +++ b/src/api/sys/model/userModel.ts @@ -8,6 +8,26 @@ export interface LoginReq { captchaId: string; } +export interface mobileLoginReq { + phoneNumber: string; + sms: string; + type: number; +} + +export interface registerReq { + username: string; + password: string; + phoneNumber: string; + sms: number; +} + +export interface updatePasswordReq { + username: string; + password: string; + phoneNumber: string; + sms: number; +} + export interface RoleInfo { roleName: string; value: string; diff --git a/src/api/sys/user.ts b/src/api/sys/user.ts index 6f229f2..54f1b69 100644 --- a/src/api/sys/user.ts +++ b/src/api/sys/user.ts @@ -1,60 +1,115 @@ -import { defHttp } from '/@/utils/http/axios'; -import {GetUserInfoModel, LoginReq, LoginResp} from './model/userModel'; +import {defHttp} from '/@/utils/http/axios'; +import {GetUserInfoModel, LoginReq, LoginResp, mobileLoginReq, registerReq, updatePasswordReq} from './model/userModel'; -import { ErrorMessageMode } from '/#/axios'; -import {BaseDataResp} from "@/api/model/baseModel"; +import {ErrorMessageMode} from '/#/axios'; +import {BaseDataResp, BaseResp} from "@/api/model/baseModel"; enum Api { - Login = '/user/login', - Logout = '/user/logout', - GetUserInfo = '/user/info', - GetPermCode = '/getPermCode', - TestRetry = '/testRetry', + Login = '/user/login', + MobileLogin = '/user/mobileLogin', + Logout = '/user/logout', + Register = '/user/register', + SMS = '/v2/common/sms', + UpdatePassword = '/user/updatePassword', + GetUserInfo = '/user/info', + GetPermCode = '/getPermCode', + TestRetry = '/testRetry', } /** * @description: user login api */ export function login(params: LoginReq, mode: ErrorMessageMode = 'notice') { - return defHttp.post>( - { - url: Api.Login, - params, - }, - { - errorMessageMode: mode, - successMessageMode: mode, - }, - ); + return defHttp.post>( + { + url: Api.Login, + params, + }, + { + errorMessageMode: mode, + successMessageMode: mode, + }, + ); +} + +export function mobileLogin(params: mobileLoginReq, mode: ErrorMessageMode = 'notice') { + return defHttp.post>( + { + url: Api.MobileLogin, + params, + }, + { + errorMessageMode: mode, + successMessageMode: mode, + }, + ); +} + +export function register(params: registerReq, mode: ErrorMessageMode = 'notice') { + return defHttp.post( + { + url: Api.Register, + params, + }, + { + errorMessageMode: mode, + successMessageMode: mode, + } + ) +} + +export function sendSmsRegister(type: number, phoneNumber: string, mode: ErrorMessageMode = 'notice') { + return defHttp.get( + { + url: `${Api.SMS}/${type}/${phoneNumber}` + }, + { + errorMessageMode: mode, + successMessageMode: mode, + } + ) +} + +export function updatePassword(params: updatePasswordReq, mode: ErrorMessageMode = 'notice') { + return defHttp.post( + { + url: Api.UpdatePassword, + params, + }, + { + errorMessageMode: mode, + successMessageMode: mode, + } + ) } /** * @description: getUserInfo */ export function getUserInfo() { - return defHttp.get>( - { url: Api.GetUserInfo }, - { errorMessageMode: 'none' }, - ); + return defHttp.get>( + {url: Api.GetUserInfo}, + {errorMessageMode: 'none'}, + ); } export function getPermCode() { - return defHttp.get({ url: Api.GetPermCode }); + return defHttp.get({url: Api.GetPermCode}); } export function doLogout() { - return defHttp.get({ url: Api.Logout }); + return defHttp.get({url: Api.Logout}); } export function testRetry() { - return defHttp.get( - { url: Api.TestRetry }, - { - retryRequest: { - isOpenRetry: true, - count: 5, - waitTime: 1000, - }, - }, - ); + return defHttp.get( + {url: Api.TestRetry}, + { + retryRequest: { + isOpenRetry: true, + count: 5, + waitTime: 1000, + }, + }, + ); } diff --git a/src/hooks/web/useTabs.ts b/src/hooks/web/useTabs.ts index 14dde2f..51f3fce 100644 --- a/src/hooks/web/useTabs.ts +++ b/src/hooks/web/useTabs.ts @@ -24,7 +24,7 @@ export function useTabs(_router?: Router) { if (!show) { throw new Error('The multi-tab page is currently not open, please open it in the settings!'); } - return !!show; + return show; } const tabStore = useMultipleTabStore(); diff --git a/src/layouts/default/header/components/lock/LockModal.vue b/src/layouts/default/header/components/lock/LockModal.vue index e631006..daca092 100644 --- a/src/layouts/default/header/components/lock/LockModal.vue +++ b/src/layouts/default/header/components/lock/LockModal.vue @@ -45,7 +45,7 @@ const userStore = useUserStore(); const lockStore = useLockStore(); - const getRealName = computed(() => userStore.getUserInfo?.realName); + const getRealName = computed(() => userStore.getUserInfo?.name); const [register, { closeModal }] = useModalInner(); const [registerForm, { validateFields, resetFields }] = useForm({ diff --git a/src/layouts/default/header/components/user-dropdown/index.vue b/src/layouts/default/header/components/user-dropdown/index.vue index 755cc0a..33bd167 100644 --- a/src/layouts/default/header/components/user-dropdown/index.vue +++ b/src/layouts/default/header/components/user-dropdown/index.vue @@ -4,7 +4,7 @@ - {{ getUserInfo.realName }} + {{ getUserInfo.name }} @@ -76,8 +76,8 @@ const userStore = useUserStore(); const getUserInfo = computed(() => { - const { realName = '', avatar, desc } = userStore.getUserInfo || {}; - return { realName, avatar: avatar || headerImg, desc }; + const { name = '', avatar, desc } = userStore.getUserInfo || {}; + return { name, avatar: avatar || headerImg, desc }; }); const [register, { openModal }] = useModal(); diff --git a/src/locales/lang/en/sys.ts b/src/locales/lang/en/sys.ts index b85af84..cbfcb4d 100644 --- a/src/locales/lang/en/sys.ts +++ b/src/locales/lang/en/sys.ts @@ -92,6 +92,7 @@ export default { // placeholder accountPlaceholder: 'Please input username', passwordPlaceholder: 'Please input password', + captchaPlaceholder: 'Please input verification code', smsPlaceholder: 'Please input sms code', mobilePlaceholder: 'Please input mobile', policyPlaceholder: 'Register after checking', @@ -100,6 +101,8 @@ export default { userName: 'Username', password: 'Password', confirmPassword: 'Confirm Password', + newPassword: 'New Password', + updatePassword: 'Change Password', email: 'Email', smsCode: 'SMS code', mobile: 'Mobile', diff --git a/src/locales/lang/zh-CN/sys.ts b/src/locales/lang/zh-CN/sys.ts index 4637344..a969392 100644 --- a/src/locales/lang/zh-CN/sys.ts +++ b/src/locales/lang/zh-CN/sys.ts @@ -86,6 +86,7 @@ export default { // placeholder accountPlaceholder: '请输入账号', passwordPlaceholder: '请输入密码', + captchaPlaceholder: '请输入验证码', smsPlaceholder: '请输入验证码', mobilePlaceholder: '请输入手机号码', policyPlaceholder: '勾选后才能注册', @@ -94,6 +95,8 @@ export default { userName: '账号', password: '密码', confirmPassword: '确认密码', + newPassword: '新密码', + updatePassword: '修改密码', email: '邮箱', smsCode: '短信验证码', mobile: '手机号码', diff --git a/src/store/modules/user.ts b/src/store/modules/user.ts index 4587462..fb5e3e0 100644 --- a/src/store/modules/user.ts +++ b/src/store/modules/user.ts @@ -7,9 +7,9 @@ import { ROLES_KEY, ROLES_NAME_KEY, TOKEN_KEY, USER_INFO_KEY } from '/@/enums/ca import { getAuthCache, setAuthCache } from '/@/utils/auth'; import { GetUserInfoModel, - LoginReq, + LoginReq, mobileLoginReq, updatePasswordReq, } from '/@/api/sys/model/userModel'; -import { doLogout, getUserInfo, login} from '/@/api/sys/user'; +import {doLogout, getUserInfo, login, mobileLogin} from '/@/api/sys/user'; import { useI18n } from '/@/hooks/web/useI18n'; import { useMessage } from '/@/hooks/web/useMessage'; import { router } from '/@/router'; @@ -117,6 +117,31 @@ export const useUserStore = defineStore({ } }, + /** + * @description: mobileLogin + */ + async mobileLogin( + params: mobileLoginReq & { + goHome?: boolean; + mode?: ErrorMessageMode; + }, + ): Promise { + try { + const { goHome = true, mode, ...mobileLoginReq } = params; + const data = await mobileLogin(mobileLoginReq, mode); + if (data.code !== '00000') { + return Promise.reject(null); + } + const { token } = data.data; + + // save token + this.setToken(token); + return this.afterLoginAction(goHome); + } catch (error) { + return Promise.reject(error); + } + }, + async afterLoginAction(goHome?: boolean): Promise { if (!this.getToken) return null; // get user info diff --git a/src/views/dashboard/workbench/components/WorkbenchHeader.vue b/src/views/dashboard/workbench/components/WorkbenchHeader.vue index ef4d90d..2e50647 100644 --- a/src/views/dashboard/workbench/components/WorkbenchHeader.vue +++ b/src/views/dashboard/workbench/components/WorkbenchHeader.vue @@ -2,7 +2,7 @@
-

早安, {{ userinfo.realName }}, 开始您一天的工作吧!

+

早安, {{ userinfo.name }}, 开始您一天的工作吧!

今日晴,20℃ - 32℃!
diff --git a/src/views/sys/login/ForgetPasswordForm.vue b/src/views/sys/login/ForgetPasswordForm.vue index aca24aa..7d805fe 100644 --- a/src/views/sys/login/ForgetPasswordForm.vue +++ b/src/views/sys/login/ForgetPasswordForm.vue @@ -1,29 +1,38 @@ diff --git a/src/views/sys/login/LoginForm.vue b/src/views/sys/login/LoginForm.vue index fc6ba01..0e201d9 100644 --- a/src/views/sys/login/LoginForm.vue +++ b/src/views/sys/login/LoginForm.vue @@ -27,9 +27,7 @@
- + @@ -16,6 +16,8 @@ class="fix-auto-fill" v-model:value="formData.sms" :placeholder="t('sys.login.smsCode')" + count=120 + :sendCodeApi="sendCodeApi" /> @@ -37,18 +39,24 @@ import LoginFormTitle from './LoginFormTitle.vue'; import { useI18n } from '/@/hooks/web/useI18n'; import { useLoginState, useFormRules, useFormValid, LoginStateEnum } from './useLogin'; + import {sendSmsRegister} from "@/api/sys/user"; + import {PageEnum} from "@/enums/pageEnum"; + import {useUserStore} from "@/store/modules/user"; + import {useGo} from "@/hooks/web/usePage"; const FormItem = Form.Item; const { t } = useI18n(); const { handleBackLogin, getLoginState } = useLoginState(); const { getFormRules } = useFormRules(); - + const userStore = useUserStore(); + const go = useGo(); const formRef = ref(); const loading = ref(false); const formData = reactive({ - mobile: '', + phoneNumber: '', sms: '', + type: 1 }); const { validForm } = useFormValid(formRef); @@ -58,6 +66,33 @@ async function handleLogin() { const data = await validForm(); if (!data) return; - console.log(data); + loading.value = true; + userStore + .mobileLogin({ + phoneNumber: data.phoneNumber, + sms: data.sms, + type: data.type + }) + .then(() => { + loading.value = false; + go(PageEnum.BASE_HOME); + }) + .catch(() => { + loading.value = false; + }); + } + + async function sendCodeApi():Promise { + const phoneNumber = await formRef.value.validateFields(['phoneNumber']); + if(phoneNumber == false) { + return Promise.resolve(false) + } + // sen code + const result = await sendSmsRegister(1, formData.phoneNumber); + if (result.code !== "A0002") { + return Promise.resolve(false) + } + return Promise.resolve(true) } + diff --git a/src/views/sys/login/RegisterForm.vue b/src/views/sys/login/RegisterForm.vue index a386cbe..6f5a520 100644 --- a/src/views/sys/login/RegisterForm.vue +++ b/src/views/sys/login/RegisterForm.vue @@ -2,18 +2,18 @@
- + - + @@ -22,8 +22,10 @@ @@ -68,25 +70,31 @@ diff --git a/src/views/sys/login/useLogin.ts b/src/views/sys/login/useLogin.ts index bf0a04e..3540d36 100644 --- a/src/views/sys/login/useLogin.ts +++ b/src/views/sys/login/useLogin.ts @@ -1,14 +1,14 @@ -import type { ValidationRule, FormInstance } from 'ant-design-vue/lib/form/Form'; -import type { RuleObject, NamePath } from 'ant-design-vue/lib/form/interface'; -import { ref, computed, unref, Ref } from 'vue'; -import { useI18n } from '/@/hooks/web/useI18n'; +import type {ValidationRule, FormInstance} from 'ant-design-vue/lib/form/Form'; +import type {RuleObject, NamePath} from 'ant-design-vue/lib/form/interface'; +import {ref, computed, unref, Ref} from 'vue'; +import {useI18n} from '/@/hooks/web/useI18n'; export enum LoginStateEnum { - LOGIN, - REGISTER, - RESET_PASSWORD, - MOBILE, - QR_CODE, + LOGIN, + REGISTER, + RESET_PASSWORD, + MOBILE, + QR_CODE, } const currentState = ref(LoginStateEnum.LOGIN); @@ -17,110 +17,137 @@ const currentState = ref(LoginStateEnum.LOGIN); // import { createGlobalState } from '@vueuse/core' export function useLoginState() { - function setLoginState(state: LoginStateEnum) { - currentState.value = state; - } + function setLoginState(state: LoginStateEnum) { + currentState.value = state; + } + + const getLoginState = computed(() => currentState.value); - const getLoginState = computed(() => currentState.value); + function handleBackLogin() { + setLoginState(LoginStateEnum.LOGIN); + } - function handleBackLogin() { - setLoginState(LoginStateEnum.LOGIN); - } + function handleBackMobileLogin() { + setLoginState(LoginStateEnum.MOBILE); + } - return { setLoginState, getLoginState, handleBackLogin }; + return {setLoginState, getLoginState, handleBackLogin, handleBackMobileLogin}; } + export function useFormValid(formRef: Ref) { - const validate = computed(() => { - const form = unref(formRef); - return form?.validate ?? ((_nameList?: NamePath) => Promise.resolve()); - }); - - async function validForm() { - const form = unref(formRef); - if (!form) return; - const data = await form.validate(); - return data as T; - } - - return { validate, validForm }; + const validate = computed(() => { + const form = unref(formRef); + return form?.validate ?? ((_nameList?: NamePath) => Promise.resolve()); + }); + + async function validForm() { + const form = unref(formRef); + if (!form) return; + const data = await form.validate(); + return data as T; + } + + return {validate, validForm}; } + export function useFormRules(formData?: Recordable) { - const { t } = useI18n(); - - const getAccountFormRule = computed(() => createRule(t('sys.login.accountPlaceholder'))); - const getPasswordFormRule = computed(() => createRule(t('sys.login.passwordPlaceholder'))); - const getSmsFormRule = computed(() => createRule(t('sys.login.smsPlaceholder'))); - const getMobileFormRule = computed(() => createRule(t('sys.login.mobilePlaceholder'))); - - const validatePolicy = async (_: RuleObject, value: boolean) => { - return !value ? Promise.reject(t('sys.login.policyPlaceholder')) : Promise.resolve(); - }; - - const validateConfirmPassword = (password: string) => { - return async (_: RuleObject, value: string) => { - if (!value) { - return Promise.reject(t('sys.login.passwordPlaceholder')); - } - if (value !== password) { - return Promise.reject(t('sys.login.diffPwd')); - } - return Promise.resolve(); - }; - }; + const {t} = useI18n(); - const getFormRules = computed((): { [k: string]: ValidationRule | ValidationRule[] } => { - const accountFormRule = unref(getAccountFormRule); - const passwordFormRule = unref(getPasswordFormRule); - const smsFormRule = unref(getSmsFormRule); - const mobileFormRule = unref(getMobileFormRule); + const getAccountFormRule = computed(() => createRule(t('sys.login.accountPlaceholder'))); + const getPasswordFormRule = computed(() => createRule(t('sys.login.passwordPlaceholder'))); + const getCaptchaFormRule = computed(() => createRule(t('sys.login.captchaPlaceholder'))); + const getSmsFormRule = computed(() => createRule(t('sys.login.smsPlaceholder'))); + const getMobileFormRule = computed(() => phoneNumberRule()); - const mobileRule = { - sms: smsFormRule, - mobile: mobileFormRule, + const validatePolicy = async (_: RuleObject, value: boolean) => { + return !value ? Promise.reject(t('sys.login.policyPlaceholder')) : Promise.resolve(); }; - switch (unref(currentState)) { - // register form rules - case LoginStateEnum.REGISTER: - return { - account: accountFormRule, - password: passwordFormRule, - confirmPassword: [ - { validator: validateConfirmPassword(formData?.password), trigger: 'change' }, - ], - policy: [{ validator: validatePolicy, trigger: 'change' }], - ...mobileRule, - }; - // reset password form rules - case LoginStateEnum.RESET_PASSWORD: - return { - account: accountFormRule, - ...mobileRule, + const validateConfirmPassword = (password: string) => { + return async (_: RuleObject, value: string) => { + if (!value) { + return Promise.reject(t('sys.login.passwordPlaceholder')); + } + if (value !== password) { + return Promise.reject(t('sys.login.diffPwd')); + } + return Promise.resolve(); }; + }; - // mobile form rules - case LoginStateEnum.MOBILE: - return mobileRule; + const getFormRules = computed((): { [k: string]: ValidationRule | ValidationRule[] } => { + const accountFormRule = unref(getAccountFormRule); + const passwordFormRule = unref(getPasswordFormRule); + const captchaFormRule = unref(getCaptchaFormRule); + const smsFormRule = unref(getSmsFormRule); + const mobileFormRule = unref(getMobileFormRule); - // login form rules - default: - return { - account: accountFormRule, - password: passwordFormRule, + const mobileRule = { + sms: smsFormRule, + mobile: mobileFormRule, }; - } - }); - return { getFormRules }; + switch (unref(currentState)) { + // register form rules + case LoginStateEnum.REGISTER: + return { + username: accountFormRule, + password: passwordFormRule, + phoneNumber: mobileFormRule, + captcha: captchaFormRule, + confirmPassword: [ + {validator: validateConfirmPassword(formData?.password), trigger: 'change'}, + ], + policy: [{validator: validatePolicy, trigger: 'change'}], + ...mobileRule, + }; + + // reset password form rules + case LoginStateEnum.RESET_PASSWORD: + return { + username: accountFormRule, + password: passwordFormRule, + phoneNumber: mobileFormRule, + sms: smsFormRule, + }; + + // mobile form rules + case LoginStateEnum.MOBILE: + return { + phoneNumber: mobileFormRule, + sms: smsFormRule, + }; + + // login form rules + default: + return { + account: accountFormRule, + password: passwordFormRule, + captcha: captchaFormRule, + }; + } + }); + return {getFormRules}; } function createRule(message: string) { - return [ - { - required: true, - message, - trigger: 'change', - }, - ]; + return [ + { + required: true, + message, + trigger: 'change', + }, + ]; +} + +function phoneNumberRule() { + return [ + { + required: true, + pattern: /^(0|86|17951)?(13[0-9]|15[012356789]|16[6]|19[89]]|17[01345678]|18[0-9]|14[579])[0-9]{8}$/, + message: "请输入正确的手机号", + trigger: 'change', + } + ]; }