mirror of
https://gitee.com/bootx/dax-pay-ui.git
synced 2025-09-23 12:44:28 +00:00
feat 登录和token对接
This commit is contained in:
@@ -1,9 +1,19 @@
|
|||||||
/**
|
/**
|
||||||
* @description: Login interface parameters
|
* 账密登录参数
|
||||||
*/
|
*/
|
||||||
export interface LoginParams {
|
export interface LoginParams {
|
||||||
username: string
|
// 账号/手机号/邮箱
|
||||||
|
account: string
|
||||||
|
// 密码
|
||||||
password: string
|
password: string
|
||||||
|
// 终端
|
||||||
|
client: string
|
||||||
|
// 登录方式
|
||||||
|
loginType: string
|
||||||
|
// 验证码key
|
||||||
|
captchaKey: string
|
||||||
|
// 验证码
|
||||||
|
captcha: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RoleInfo {
|
export interface RoleInfo {
|
||||||
@@ -12,27 +22,15 @@ export interface RoleInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description: Login interface return value
|
* 登录后用户信息
|
||||||
*/
|
|
||||||
export interface LoginResultModel {
|
|
||||||
userId: string | number
|
|
||||||
token: string
|
|
||||||
role: RoleInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description: Get user information return value
|
|
||||||
*/
|
*/
|
||||||
export interface GetUserInfoModel {
|
export interface GetUserInfoModel {
|
||||||
roles: RoleInfo[]
|
|
||||||
// 用户id
|
// 用户id
|
||||||
userId: string | number
|
userId: number
|
||||||
// 用户名
|
// 名称
|
||||||
|
name: string
|
||||||
|
// 账号
|
||||||
username: string
|
username: string
|
||||||
// 真实名字
|
|
||||||
realName: string
|
|
||||||
// 头像
|
// 头像
|
||||||
avatar: string
|
avatar: string
|
||||||
// 介绍
|
|
||||||
desc?: string
|
|
||||||
}
|
}
|
||||||
|
@@ -1,46 +1,51 @@
|
|||||||
import { defHttp } from '/@/utils/http/axios'
|
import { defHttp } from '/@/utils/http/axios'
|
||||||
import { LoginParams, LoginResultModel, GetUserInfoModel } from './model/userModel'
|
import { LoginParams, GetUserInfoModel } from './model/userModel'
|
||||||
|
|
||||||
import { ErrorMessageMode, Result } from '/#/axios'
|
import { ErrorMessageMode, Result } from '/#/axios'
|
||||||
|
|
||||||
enum Api {
|
enum Api {
|
||||||
Login = '/login',
|
|
||||||
Logout = '/logout',
|
Logout = '/logout',
|
||||||
GetUserInfo = '/getUserInfo',
|
|
||||||
GetPermCode = '/getPermCode',
|
GetPermCode = '/getPermCode',
|
||||||
TestRetry = '/testRetry',
|
TestRetry = '/testRetry',
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description: user login api
|
* 登录接口 返回token
|
||||||
*/
|
*/
|
||||||
export function loginApi(params: LoginParams, mode: ErrorMessageMode = 'modal') {
|
export function loginApi(params: LoginParams) {
|
||||||
return defHttp.post<Result<LoginResultModel>>(
|
return defHttp.post<Result<string>>({
|
||||||
{
|
url: '/token/login',
|
||||||
url: Api.Login,
|
params,
|
||||||
params,
|
})
|
||||||
},
|
}
|
||||||
{
|
/**
|
||||||
errorMessageMode: mode,
|
* 登录后获取用户信息
|
||||||
},
|
*/
|
||||||
)
|
export function getUserInfo() {
|
||||||
|
return defHttp.get<Result<GetUserInfoModel>>({ url: '/user/getLoginAfterUserInfo' })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description: getUserInfo
|
* 获取用户菜单和资源权限
|
||||||
*/
|
*/
|
||||||
export function getUserInfo() {
|
export function getPermissions(clientCode: string) {
|
||||||
return defHttp.get<Result<GetUserInfoModel>>({ url: Api.GetUserInfo }, { errorMessageMode: 'none' })
|
return defHttp.get<Result<GetUserInfoModel>>({ url: '/role/menu/getPermissions', params: { clientCode } })
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getPermCode() {
|
export function getPermCode() {
|
||||||
return defHttp.get<string[]>({ url: Api.GetPermCode })
|
return defHttp.get<string[]>({ url: Api.GetPermCode })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 退出
|
||||||
|
*/
|
||||||
export function doLogout() {
|
export function doLogout() {
|
||||||
return defHttp.get({ url: Api.Logout })
|
return defHttp.post({ url: '/token/logout' })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试重试
|
||||||
|
*/
|
||||||
export function testRetry() {
|
export function testRetry() {
|
||||||
return defHttp.get(
|
return defHttp.get(
|
||||||
{ url: Api.TestRetry },
|
{ url: Api.TestRetry },
|
||||||
|
@@ -4,17 +4,17 @@
|
|||||||
<img :class="`${prefixCls}__header`" :src="getUserInfo.avatar" />
|
<img :class="`${prefixCls}__header`" :src="getUserInfo.avatar" />
|
||||||
<span :class="`${prefixCls}__info hidden md:block`">
|
<span :class="`${prefixCls}__info hidden md:block`">
|
||||||
<span :class="`${prefixCls}__name `" class="truncate">
|
<span :class="`${prefixCls}__name `" class="truncate">
|
||||||
{{ getUserInfo.realName }}
|
{{ getUserInfo.name }}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<template #overlay>
|
<template #overlay>
|
||||||
<Menu @click="handleMenuClick">
|
<Menu @click="handleMenuClick">
|
||||||
<MenuItem key="doc" :text="t('layout.header.dropdownItemDoc')" icon="ion:document-text-outline" v-if="getShowDoc" />
|
<!-- <MenuItem key="doc" text="文档" icon="ion:document-text-outline" v-if="getShowDoc" />-->
|
||||||
<MenuDivider v-if="getShowDoc" />
|
<!-- <MenuDivider v-if="getShowDoc" />-->
|
||||||
<MenuItem v-if="getUseLockPage" key="lock" :text="t('layout.header.tooltipLock')" icon="ion:lock-closed-outline" />
|
<MenuItem v-if="getUseLockPage" key="lock" text="锁定屏幕" icon="ion:lock-closed-outline" />
|
||||||
<MenuItem key="logout" :text="t('layout.header.dropdownItemLoginOut')" icon="ion:power-outline" />
|
<MenuItem key="logout" text="退出系统" icon="ion:power-outline" />
|
||||||
</Menu>
|
</Menu>
|
||||||
</template>
|
</template>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
@@ -49,7 +49,7 @@
|
|||||||
Dropdown,
|
Dropdown,
|
||||||
Menu,
|
Menu,
|
||||||
MenuItem: createAsyncComponent(() => import('./DropMenuItem.vue')),
|
MenuItem: createAsyncComponent(() => import('./DropMenuItem.vue')),
|
||||||
MenuDivider: Menu.Divider,
|
// MenuDivider: Menu.Divider,
|
||||||
LockAction: createAsyncComponent(() => import('../lock/LockModal.vue')),
|
LockAction: createAsyncComponent(() => import('../lock/LockModal.vue')),
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
@@ -57,15 +57,14 @@
|
|||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
const { prefixCls } = useDesign('header-user-dropdown')
|
const { prefixCls } = useDesign('header-user-dropdown')
|
||||||
const { t } = useI18n()
|
|
||||||
const { getShowDoc, getUseLockPage } = useHeaderSetting()
|
const { getShowDoc, getUseLockPage } = useHeaderSetting()
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
|
|
||||||
|
// 用户信息
|
||||||
const getUserInfo = computed(() => {
|
const getUserInfo = computed(() => {
|
||||||
const { realName = '', avatar, desc } = userStore.getUserInfo || {}
|
const { name = '', avatar } = userStore.getUserInfo || {}
|
||||||
return { realName, avatar: avatar || headerImg, desc }
|
return { name, avatar: headerImg }
|
||||||
})
|
})
|
||||||
|
|
||||||
const [register, { openModal }] = useModal()
|
const [register, { openModal }] = useModal()
|
||||||
|
|
||||||
function handleLock() {
|
function handleLock() {
|
||||||
@@ -98,10 +97,9 @@
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
prefixCls,
|
prefixCls,
|
||||||
t,
|
|
||||||
getUserInfo,
|
getUserInfo,
|
||||||
handleMenuClick,
|
handleMenuClick,
|
||||||
getShowDoc,
|
// getShowDoc,
|
||||||
register,
|
register,
|
||||||
getUseLockPage,
|
getUseLockPage,
|
||||||
}
|
}
|
||||||
|
@@ -57,6 +57,7 @@ export const useUserStore = defineStore({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
|
// token信心
|
||||||
setToken(info: string | undefined) {
|
setToken(info: string | undefined) {
|
||||||
this.token = info ? info : '' // for null or undefined value
|
this.token = info ? info : '' // for null or undefined value
|
||||||
setAuthCache(TOKEN_KEY, info)
|
setAuthCache(TOKEN_KEY, info)
|
||||||
@@ -80,36 +81,33 @@ export const useUserStore = defineStore({
|
|||||||
this.sessionTimeout = false
|
this.sessionTimeout = false
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* @description: login
|
* 登录方法
|
||||||
*/
|
*/
|
||||||
async login(
|
async login(params: LoginParams) {
|
||||||
params: LoginParams & {
|
|
||||||
goHome?: boolean
|
|
||||||
mode?: ErrorMessageMode
|
|
||||||
},
|
|
||||||
): Promise<GetUserInfoModel | null> {
|
|
||||||
try {
|
try {
|
||||||
const { goHome = true, mode, ...loginParams } = params
|
const { data: token } = await loginApi(params)
|
||||||
const data = await loginApi(loginParams, mode)
|
// 保存token
|
||||||
const { token } = data.data
|
|
||||||
|
|
||||||
// save token
|
|
||||||
this.setToken(token)
|
this.setToken(token)
|
||||||
return this.afterLoginAction(goHome)
|
await this.afterLoginAction(true)
|
||||||
|
return token
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return Promise.reject(error)
|
return Promise.reject(error)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async afterLoginAction(goHome?: boolean): Promise<GetUserInfoModel | null> {
|
/**
|
||||||
|
* 登录后操作
|
||||||
|
*/
|
||||||
|
async afterLoginAction(goHome?: boolean) {
|
||||||
if (!this.getToken) return null
|
if (!this.getToken) return null
|
||||||
// get user info
|
// 获取用户信息
|
||||||
const userInfo = await this.getUserInfoAction()
|
await this.getUserInfoAction()
|
||||||
|
|
||||||
const sessionTimeout = this.sessionTimeout
|
const sessionTimeout = this.sessionTimeout
|
||||||
|
// 超时
|
||||||
if (sessionTimeout) {
|
if (sessionTimeout) {
|
||||||
this.setSessionTimeout(false)
|
this.setSessionTimeout(false)
|
||||||
} else {
|
} else {
|
||||||
const permissionStore = usePermissionStore()
|
const permissionStore = usePermissionStore()
|
||||||
|
console.log(permissionStore)
|
||||||
if (!permissionStore.isDynamicAddedRoute) {
|
if (!permissionStore.isDynamicAddedRoute) {
|
||||||
const routes = await permissionStore.buildRoutesAction()
|
const routes = await permissionStore.buildRoutesAction()
|
||||||
routes.forEach((route) => {
|
routes.forEach((route) => {
|
||||||
@@ -118,21 +116,13 @@ export const useUserStore = defineStore({
|
|||||||
router.addRoute(PAGE_NOT_FOUND_ROUTE as unknown as RouteRecordRaw)
|
router.addRoute(PAGE_NOT_FOUND_ROUTE as unknown as RouteRecordRaw)
|
||||||
permissionStore.setDynamicAddedRoute(true)
|
permissionStore.setDynamicAddedRoute(true)
|
||||||
}
|
}
|
||||||
goHome && (await router.replace(userInfo?.homePath || PageEnum.BASE_HOME))
|
goHome && (await router.replace(PageEnum.BASE_HOME))
|
||||||
}
|
}
|
||||||
return userInfo
|
|
||||||
},
|
},
|
||||||
async getUserInfoAction(): Promise<UserInfo | null> {
|
// 获取并存储用户信息
|
||||||
|
async getUserInfoAction() {
|
||||||
if (!this.getToken) return null
|
if (!this.getToken) return null
|
||||||
const { data: userInfo } = await getUserInfo()
|
const { data: userInfo } = await getUserInfo()
|
||||||
const { roles = [] } = userInfo
|
|
||||||
if (isArray(roles)) {
|
|
||||||
const roleList = roles.map((item) => item.value) as RoleEnum[]
|
|
||||||
this.setRoleList(roleList)
|
|
||||||
} else {
|
|
||||||
userInfo.roles = []
|
|
||||||
this.setRoleList([])
|
|
||||||
}
|
|
||||||
this.setUserInfo(userInfo)
|
this.setUserInfo(userInfo)
|
||||||
return userInfo
|
return userInfo
|
||||||
},
|
},
|
||||||
|
@@ -135,8 +135,8 @@ const transform: AxiosTransform = {
|
|||||||
// 请求之前处理config
|
// 请求之前处理config
|
||||||
const token = getToken()
|
const token = getToken()
|
||||||
if (token && (config as Recordable)?.requestOptions?.withToken !== false) {
|
if (token && (config as Recordable)?.requestOptions?.withToken !== false) {
|
||||||
// jwt token
|
// 添加 token 到请求头
|
||||||
;(config as Recordable).headers.Authorization = options.authenticationScheme ? `${options.authenticationScheme} ${token}` : token
|
;(config as Recordable).headers.AccessToken = token
|
||||||
}
|
}
|
||||||
return config
|
return config
|
||||||
},
|
},
|
||||||
|
@@ -10,13 +10,13 @@
|
|||||||
<a-spin :spinning="confirmLoading">
|
<a-spin :spinning="confirmLoading">
|
||||||
<a-form class="small-from-item" ref="formRef" :label-col="labelCol" :wrapper-col="wrapperCol">
|
<a-form class="small-from-item" ref="formRef" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||||
<a-form-item label="主键" :hidden="true">
|
<a-form-item label="主键" :hidden="true">
|
||||||
<a-input v-model:value="form.id" :disabled="showable" />
|
<Input v-model:value="form.id" :disabled="showable" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="编码" v-bind="validateInfos.code" name="code">
|
<a-form-item label="编码" v-bind="validateInfos.code" name="code">
|
||||||
<a-input v-model:value="form.code" :disabled="showable" @blur="validate('code')" placeholder="请输入编码" />
|
<Input v-model:value="form.code" :disabled="showable" @blur="validate('code')" placeholder="请输入编码" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="名称" v-bind="validateInfos.name" name="name">
|
<a-form-item label="名称" v-bind="validateInfos.name" name="name">
|
||||||
<a-input v-model:value="form.name" :disabled="showable" @blur="validate('name')" placeholder="请输入名称" />
|
<Input v-model:value="form.name" :disabled="showable" @blur="validate('name')" placeholder="请输入名称" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="启用状态" v-bind="validateInfos.enable" name="enable">
|
<a-form-item label="启用状态" v-bind="validateInfos.enable" name="enable">
|
||||||
<a-switch checked-children="开" un-checked-children="关" v-model:checked="form.enable" :disabled="showable || form.system" />
|
<a-switch checked-children="开" un-checked-children="关" v-model:checked="form.enable" :disabled="showable || form.system" />
|
||||||
@@ -59,9 +59,8 @@
|
|||||||
import { nextTick, reactive, ref } from 'vue'
|
import { nextTick, reactive, ref } from 'vue'
|
||||||
import useFormEdit from '/@/hooks/bootx/useFormEdit'
|
import useFormEdit from '/@/hooks/bootx/useFormEdit'
|
||||||
import { add, Client, existsByCode, existsByCodeNotId, get, update } from './Client.api'
|
import { add, Client, existsByCode, existsByCodeNotId, get, update } from './Client.api'
|
||||||
import { Rule, useForm } from "ant-design-vue/lib/form";
|
import { FormInstance, Rule, useForm } from 'ant-design-vue/lib/form'
|
||||||
import { FormEditType } from '/@/enums/formTypeEnum'
|
import { FormEditType } from '/@/enums/formTypeEnum'
|
||||||
import { FormInstance } from 'ant-design-vue/es'
|
|
||||||
import { findAll, LoginType } from '/@/views/modules/system/loginType/LoginType.api'
|
import { findAll, LoginType } from '/@/views/modules/system/loginType/LoginType.api'
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
@@ -10,13 +10,13 @@
|
|||||||
<a-spin :spinning="confirmLoading">
|
<a-spin :spinning="confirmLoading">
|
||||||
<a-form class="small-from-item" ref="formRef" :model="form" :rules="rules" :label-col="labelCol" :wrapper-col="wrapperCol">
|
<a-form class="small-from-item" ref="formRef" :model="form" :rules="rules" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||||
<a-form-item label="主键" name="id" :hidden="true">
|
<a-form-item label="主键" name="id" :hidden="true">
|
||||||
<a-input v-model:value="form.id" :disabled="showable" />
|
<Input v-model:value="form.id" :disabled="showable" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="编码" name="code">
|
<a-form-item label="编码" name="code">
|
||||||
<a-input v-model:value="form.code" :disabled="showable" placeholder="请输入登录方式编码" />
|
<Input v-model:value="form.code" :disabled="showable" placeholder="请输入登录方式编码" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="名称" name="name">
|
<a-form-item label="名称" name="name">
|
||||||
<a-input v-model:value="form.name" :disabled="showable" placeholder="请输入登录方式名称" />
|
<Input v-model:value="form.name" :disabled="showable" placeholder="请输入登录方式名称" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="类型" name="type">
|
<a-form-item label="类型" name="type">
|
||||||
<a-radio-group v-model:value="form.type" button-style="solid">
|
<a-radio-group v-model:value="form.type" button-style="solid">
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
<a-switch checked-children="开" un-checked-children="关" v-model:checked="form.captcha" :disabled="showable" />
|
<a-switch checked-children="开" un-checked-children="关" v-model:checked="form.captcha" :disabled="showable" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="超时时间(分钟)" name="timeout">
|
<a-form-item label="超时时间(分钟)" name="timeout">
|
||||||
<a-input-number
|
<Input-number
|
||||||
v-model:value="form.timeout"
|
v-model:value="form.timeout"
|
||||||
:disabled="showable"
|
:disabled="showable"
|
||||||
:precision="0"
|
:precision="0"
|
||||||
@@ -45,7 +45,7 @@
|
|||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="密码可错误次数" name="pwdErrNum" v-show="form.type === PASSWORD">
|
<a-form-item label="密码可错误次数" name="pwdErrNum" v-show="form.type === PASSWORD">
|
||||||
<a-input-number
|
<Input-number
|
||||||
v-model:value="form.pwdErrNum"
|
v-model:value="form.pwdErrNum"
|
||||||
:disabled="showable"
|
:disabled="showable"
|
||||||
:min="-1"
|
:min="-1"
|
||||||
@@ -73,8 +73,7 @@
|
|||||||
import { nextTick, reactive, ref } from 'vue'
|
import { nextTick, reactive, ref } from 'vue'
|
||||||
import { add, LoginType, get, existsByCode, existsByCodeNotId, update, PASSWORD, OPEN_ID } from './LoginType.api'
|
import { add, LoginType, get, existsByCode, existsByCodeNotId, update, PASSWORD, OPEN_ID } from './LoginType.api'
|
||||||
import { FormEditType } from '/@/enums/formTypeEnum'
|
import { FormEditType } from '/@/enums/formTypeEnum'
|
||||||
import { FormInstance } from 'ant-design-vue/es'
|
import { FormInstance, Rule } from 'ant-design-vue/lib/form'
|
||||||
import { Rule } from 'ant-design-vue/lib/form'
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
initFormModel,
|
initFormModel,
|
||||||
@@ -99,7 +98,7 @@
|
|||||||
enable: true,
|
enable: true,
|
||||||
description: '',
|
description: '',
|
||||||
} as LoginType)
|
} as LoginType)
|
||||||
|
const formRef = ref<FormInstance>()
|
||||||
// 校验状态
|
// 校验状态
|
||||||
const rules = reactive({
|
const rules = reactive({
|
||||||
code: [
|
code: [
|
||||||
@@ -118,7 +117,6 @@
|
|||||||
const res = formEditType.value === FormEditType.Edit ? await existsByCodeNotId(code, id) : await existsByCode(code)
|
const res = formEditType.value === FormEditType.Edit ? await existsByCodeNotId(code, id) : await existsByCode(code)
|
||||||
return res.data ? Promise.reject('该编码已存在!') : Promise.resolve()
|
return res.data ? Promise.reject('该编码已存在!') : Promise.resolve()
|
||||||
}
|
}
|
||||||
const formRef = ref<FormInstance>()
|
|
||||||
|
|
||||||
// 事件
|
// 事件
|
||||||
const emits = defineEmits(['ok'])
|
const emits = defineEmits(['ok'])
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
<div :class="prefixCls" class="relative w-full h-full px-4">
|
<div :class="prefixCls" class="relative w-full h-full px-4">
|
||||||
<div class="flex items-center absolute right-4 top-4">
|
<div class="flex items-center absolute right-4 top-4">
|
||||||
<AppDarkModeToggle class="enter-x mr-2" v-if="!sessionTimeout" />
|
<AppDarkModeToggle class="enter-x mr-2" v-if="!sessionTimeout" />
|
||||||
<AppLocalePicker class="text-white enter-x xl:text-gray-600" :show-text="false" v-if="!sessionTimeout && showLocale" />
|
<!-- <AppLocalePicker class="text-white enter-x xl:text-gray-600" :show-text="false" v-if="!sessionTimeout && showLocale" />-->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="-enter-x xl:hidden">
|
<span class="-enter-x xl:hidden">
|
||||||
@@ -16,10 +16,10 @@
|
|||||||
<div class="my-auto">
|
<div class="my-auto">
|
||||||
<img :alt="title" src="../../../assets/svg/login-box-bg.svg" class="w-1/2 -mt-16 -enter-x" />
|
<img :alt="title" src="../../../assets/svg/login-box-bg.svg" class="w-1/2 -mt-16 -enter-x" />
|
||||||
<div class="mt-10 font-medium text-white -enter-x">
|
<div class="mt-10 font-medium text-white -enter-x">
|
||||||
<span class="inline-block mt-4 text-3xl"> {{ t('sys.login.signInTitle') }}</span>
|
<span class="inline-block mt-4 text-3xl"> 开箱即用的中后台管理系统</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-5 font-normal text-white dark:text-gray-500 -enter-x">
|
<div class="mt-5 font-normal text-white dark:text-gray-500 -enter-x">
|
||||||
{{ t('sys.login.signInDesc') }}
|
输入您的个人详细信息开始使用!
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -61,9 +61,9 @@
|
|||||||
|
|
||||||
const globSetting = useGlobSetting()
|
const globSetting = useGlobSetting()
|
||||||
const { prefixCls } = useDesign('login')
|
const { prefixCls } = useDesign('login')
|
||||||
const { t } = useI18n()
|
// const { t } = useI18n()
|
||||||
const localeStore = useLocaleStore()
|
const localeStore = useLocaleStore()
|
||||||
const showLocale = localeStore.getShowPicker
|
// const showLocale = localeStore.getShowPicker
|
||||||
const title = computed(() => globSetting?.title ?? '')
|
const title = computed(() => globSetting?.title ?? '')
|
||||||
</script>
|
</script>
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
@@ -2,58 +2,46 @@
|
|||||||
<LoginFormTitle v-show="getShow" class="enter-x" />
|
<LoginFormTitle v-show="getShow" class="enter-x" />
|
||||||
<Form class="p-4 enter-x" :model="formData" :rules="getFormRules" ref="formRef" v-show="getShow" @keypress.enter="handleLogin">
|
<Form class="p-4 enter-x" :model="formData" :rules="getFormRules" ref="formRef" v-show="getShow" @keypress.enter="handleLogin">
|
||||||
<FormItem name="account" class="enter-x">
|
<FormItem name="account" class="enter-x">
|
||||||
<Input size="large" v-model:value="formData.account" :placeholder="t('sys.login.userName')" class="fix-auto-fill" />
|
<Input size="large" v-model:value="formData.account" placeholder="账号" class="fix-auto-fill" />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
<FormItem name="password" class="enter-x">
|
<FormItem name="password" class="enter-x">
|
||||||
<InputPassword size="large" visibilityToggle v-model:value="formData.password" :placeholder="t('sys.login.password')" />
|
<InputPassword size="large" visibilityToggle v-model:value="formData.password" placeholder="密码" />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
|
|
||||||
<ARow class="enter-x">
|
<ARow class="enter-x">
|
||||||
<ACol :span="12">
|
<ACol :span="12">
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<!-- No logic, you need to deal with it yourself -->
|
<!-- No logic, you need to deal with it yourself -->
|
||||||
<Checkbox v-model:checked="rememberMe" size="small">
|
<Checkbox v-model:checked="rememberMe" size="small"> 记住我 </Checkbox>
|
||||||
{{ t('sys.login.rememberMe') }}
|
|
||||||
</Checkbox>
|
|
||||||
</FormItem>
|
</FormItem>
|
||||||
</ACol>
|
</ACol>
|
||||||
<ACol :span="12">
|
<ACol :span="12">
|
||||||
<FormItem :style="{ 'text-align': 'right' }">
|
<FormItem :style="{ 'text-align': 'right' }">
|
||||||
<!-- No logic, you need to deal with it yourself -->
|
<!-- 没有逻辑,你需要自己处理 -->
|
||||||
<Button type="link" size="small" @click="setLoginState(LoginStateEnum.RESET_PASSWORD)">
|
<Button type="link" size="small" @click="setLoginState(LoginStateEnum.RESET_PASSWORD)"> 忘记密码? </Button>
|
||||||
{{ t('sys.login.forgetPassword') }}
|
|
||||||
</Button>
|
|
||||||
</FormItem>
|
</FormItem>
|
||||||
</ACol>
|
</ACol>
|
||||||
</ARow>
|
</ARow>
|
||||||
|
|
||||||
<FormItem class="enter-x">
|
<FormItem class="enter-x">
|
||||||
<Button type="primary" size="large" block @click="handleLogin" :loading="loading">
|
<Button type="primary" size="large" block @click="handleLogin" :loading="loading"> 登录 </Button>
|
||||||
{{ t('sys.login.loginButton') }}
|
|
||||||
</Button>
|
|
||||||
<!-- <Button size="large" class="mt-4 enter-x" block @click="handleRegister">
|
<!-- <Button size="large" class="mt-4 enter-x" block @click="handleRegister">
|
||||||
{{ t('sys.login.registerButton') }}
|
{{ t('sys.login.registerButton') }}
|
||||||
</Button> -->
|
</Button> -->
|
||||||
</FormItem>
|
</FormItem>
|
||||||
<ARow class="enter-x">
|
<ARow class="enter-x">
|
||||||
<ACol :md="8" :xs="24">
|
<ACol :md="8" :xs="24">
|
||||||
<Button block @click="setLoginState(LoginStateEnum.MOBILE)">
|
<Button block @click="setLoginState(LoginStateEnum.MOBILE)"> 手机登录 </Button>
|
||||||
{{ t('sys.login.mobileSignInFormTitle') }}
|
|
||||||
</Button>
|
|
||||||
</ACol>
|
</ACol>
|
||||||
<ACol :md="8" :xs="24" class="!my-2 !md:my-0 xs:mx-0 md:mx-2">
|
<ACol :md="8" :xs="24" class="!my-2 !md:my-0 xs:mx-0 md:mx-2">
|
||||||
<Button block @click="setLoginState(LoginStateEnum.QR_CODE)">
|
<Button block @click="setLoginState(LoginStateEnum.QR_CODE)"> 二维码登录 </Button>
|
||||||
{{ t('sys.login.qrSignInFormTitle') }}
|
|
||||||
</Button>
|
|
||||||
</ACol>
|
</ACol>
|
||||||
<ACol :md="6" :xs="24">
|
<ACol :md="6" :xs="24">
|
||||||
<Button block @click="setLoginState(LoginStateEnum.REGISTER)">
|
<Button block @click="setLoginState(LoginStateEnum.REGISTER)"> 注册 </Button>
|
||||||
{{ t('sys.login.registerButton') }}
|
|
||||||
</Button>
|
|
||||||
</ACol>
|
</ACol>
|
||||||
</ARow>
|
</ARow>
|
||||||
|
|
||||||
<Divider class="enter-x">{{ t('sys.login.otherSignIn') }}</Divider>
|
<Divider class="enter-x">其他登录方式</Divider>
|
||||||
|
|
||||||
<div class="flex justify-evenly enter-x" :class="`${prefixCls}-sign-in-way`">
|
<div class="flex justify-evenly enter-x" :class="`${prefixCls}-sign-in-way`">
|
||||||
<GithubFilled />
|
<GithubFilled />
|
||||||
@@ -93,10 +81,10 @@
|
|||||||
|
|
||||||
const formRef = ref()
|
const formRef = ref()
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const rememberMe = ref(false)
|
const rememberMe = ref(true)
|
||||||
|
|
||||||
const formData = reactive({
|
const formData = reactive({
|
||||||
account: 'vben',
|
account: 'xxm1995',
|
||||||
password: '123456',
|
password: '123456',
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -111,15 +99,18 @@
|
|||||||
if (!data) return
|
if (!data) return
|
||||||
try {
|
try {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
const userInfo = await userStore.login({
|
const token = await userStore.login({
|
||||||
|
client: 'admin',
|
||||||
|
loginType: 'password',
|
||||||
password: data.password,
|
password: data.password,
|
||||||
username: data.account,
|
account: data.account,
|
||||||
mode: 'none', //不要默认的错误提示
|
captchaKey: data.captchaKey,
|
||||||
|
captcha: data.captcha,
|
||||||
})
|
})
|
||||||
if (userInfo) {
|
if (token) {
|
||||||
notification.success({
|
notification.success({
|
||||||
message: t('sys.login.loginSuccessTitle'),
|
message: t('sys.login.loginSuccessTitle'),
|
||||||
description: `${t('sys.login.loginSuccessDesc')}: ${userInfo.realName}`,
|
description: `${t('sys.login.loginSuccessDesc')}`,
|
||||||
duration: 3,
|
duration: 3,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
11
types/store.d.ts
vendored
11
types/store.d.ts
vendored
@@ -31,13 +31,14 @@ export interface ErrorLogInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface UserInfo {
|
export interface UserInfo {
|
||||||
userId: string | number
|
// 用户id
|
||||||
|
userId: number
|
||||||
|
// 名称
|
||||||
|
name: string
|
||||||
|
// 账号
|
||||||
username: string
|
username: string
|
||||||
realName: string
|
// 头像
|
||||||
avatar: string
|
avatar: string
|
||||||
desc?: string
|
|
||||||
homePath?: string
|
|
||||||
roles: RoleInfo[]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BeforeMiniState {
|
export interface BeforeMiniState {
|
||||||
|
Reference in New Issue
Block a user