登录页面init

This commit is contained in:
2024-08-19 14:01:14 +08:00
parent 74bd16dc51
commit 41babdfa5c
22 changed files with 244 additions and 139 deletions

View File

@@ -1,4 +1,4 @@
import request from '@/utils/http'
import createAxios from '@/utils/http'
import { useUserInfoStore } from '@/stores/user'
import { sm3Digest } from '@/assets/commjs/sm3.js'
import { sm2, encrypt } from '@/assets/commjs/sm2.js'
@@ -11,7 +11,7 @@ export const publicKey = (params?: any) => {
loginName: encrypt(userInfo.loginName),
}
}
return request({
return createAxios({
url: '/user/generateSm2Key',
method: 'get',
params,
@@ -30,7 +30,7 @@ export const pwdSm3 = async (pwd: any, loginName?: string) => {
export const login = async (params: any) => {
params.password = await pwdSm3(params.password, params.username)
params.username = encrypt(params.username)
return request({
return createAxios({
url: '/pqs-auth/oauth/token',
method: 'post',
params,
@@ -40,7 +40,7 @@ export const login = async (params: any) => {
//获取用户信息
export const getUserById = () => {
const userInfo = useUserInfoStore()
return request({
return createAxios({
url: '/user-boot/user/getUserById?id=' + userInfo.userIndex,
method: 'get',
})

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 KiB

View File

@@ -1,3 +1,19 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@tailwind utilities;
/* 申明字体为东方大楷 */
@font-face {
font-family: 'DongFangDaKai';
src: url('@/assets/font/DongFangDaKai-Regular.woff') format('woff'),
url('@/assets/font/DongFangDaKai-Regular.woff2') format('woff2');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: "MFBanHei"; /* Project id 1513211 */
src: url('@/assets/font/MFBanHei.ttf?t=1643094287456') format('truetype');
}

View File

@@ -1 +0,0 @@
/*文件说明本文件用来定义一些本地缓存的key*/

View File

@@ -0,0 +1,6 @@
/**
* 用户相关的一些常量
*/
// 请求头token拼接的前缀
export const TOKEN_PREFIX = 'bearer '

View File

@@ -1,15 +1,14 @@
import { createApp } from 'vue'
import App from './App.vue'
// element-plus
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
// 使用pinia
import pinia from '@/stores'
import App from './App.vue'
// 导入路由
import Router from './router/index'
// 引入tailwindcss
// 引入项目主CSS
import '@/assets/styles/tailMain.css'
// 导入全局注册的组件

View File

@@ -1,95 +0,0 @@
// 变量名对应含义请在 /stores/* 里边找
import type { RouteRecordRaw, RouteLocationNormalized } from 'vue-router'
export interface Layout {
showDrawer: boolean
shrink: boolean
layoutMode: string
mainAnimation: string
isDark: boolean
menuWidth: number
menuDefaultIcon: string
menuCollapse: boolean
menuUniqueOpened: boolean
menuShowTopBar: boolean
elementUiPrimary: string[]
tableHeaderBackground: string[]
tableHeaderColor: string[]
tableCurrent: string[]
menuBackground: string[]
menuColor: string[]
menuActiveBackground: string[]
menuActiveColor: string[]
menuTopBarBackground: string[]
headerBarTabColor: string[]
headerBarBackground: string[]
headerBarHoverBackground: string[]
headerBarTabActiveBackground: string[]
headerBarTabActiveColor: string[]
}
export interface NavTabs {
activeIndex: number
activeRoute: RouteLocationNormalized | null
tabsView: RouteLocationNormalized[]
tabFullScreen: boolean
tabsViewRoutes: RouteRecordRaw[]
authNode: Map<string, string[]>
}
// 用户信息
export interface UserInfo {
access_token: string
token_type: string
refresh_token: string
expires_in: number
scope: string
nickname: string
userType: number
deptIndex: string
userIndex: string
client_id: string
headSculpture: any
jti: string
name: string
deptId: string
phone: string
email: string
limitIpStart: string
limitIpEnd: string
limitTime: string
casualUser: number
type: number
smsNotice: number
emailNotice: number
role: string[]
devCode: any
id: string
loginName: string
state: number
registerTime: string
loginTime: string
deptName: string
areaId: string
areaName: string
deptLevel: number
roleList: string[]
roleCode: string[]
}
// 字典数据
export interface DictData {
basic: BasicDictData[]
area: BasicDictData[]
areaTree: BasicDictData[]
userList: string[]
}
export interface BasicDictData {
name: string
id: string
code: string
value: null
sort: number | null
children?: BasicDictData[]
}

View File

@@ -1,6 +1,9 @@
import { defineStore } from 'pinia'
import { USER_INFO } from '@/stores/constant/cacheKey'
import type { UserInfo } from '@/stores/interface'
import { USER_INFO } from '@/constants/storeKey'
import { TOKEN_PREFIX } from '@/constants/user'
import type { UserInfo } from '@/types/user'
import { getUserById } from '@/api/user'
import { createPersistedState } from 'pinia-plugin-persistedstate'
export const useUserInfoStore = defineStore('userInfo', {
// 行为
@@ -8,6 +11,9 @@ export const useUserInfoStore = defineStore('userInfo', {
dataFill(state: UserInfo) {
this.$state = { ...this.$state, ...state }
},
async initUserInfo() {
this.dataFill(await getUserById())
},
removeToken() {
this.access_token = ''
this.refresh_token = ''
@@ -18,8 +24,8 @@ export const useUserInfoStore = defineStore('userInfo', {
},
getToken(type: 'auth' | 'refresh' = 'auth') {
if (type === 'auth') {
if (this.token_type && this.access_token) {
return this.token_type + ' ' + this.access_token
if (this.access_token) {
return `${TOKEN_PREFIX}${this.access_token}`
} else {
return ''
}
@@ -32,7 +38,6 @@ export const useUserInfoStore = defineStore('userInfo', {
state: (): UserInfo => {
return {
access_token: '',
token_type: '',
refresh_token: '',
expires_in: 0,
scope: '',
@@ -69,7 +74,10 @@ export const useUserInfoStore = defineStore('userInfo', {
roleCode: [],
}
},
persist: {
key: USER_INFO,
},
plugins: [
createPersistedState({
key: USER_INFO,
storage: window.localStorage
}),
],
})

View File

@@ -0,0 +1,16 @@
// 字典数据
export interface DictData {
basic: BasicDictData[]
area: BasicDictData[]
areaTree: BasicDictData[]
userList: string[]
}
export interface BasicDictData {
name: string
id: string
code: string
value: null
sort: number | null
children?: BasicDictData[]
}

View File

@@ -0,0 +1,39 @@
// 用户信息
export interface UserInfo {
access_token: string
refresh_token: string
expires_in: number
scope: string
nickname: string
userType: number
deptIndex: string
userIndex: string
client_id: string
headSculpture: any
jti: string
name: string
deptId: string
phone: string
email: string
limitIpStart: string
limitIpEnd: string
limitTime: string
casualUser: number
type: number
smsNotice: number
emailNotice: number
role: string[]
devCode: any
id: string
loginName: string
state: number
registerTime: string
loginTime: string
deptName: string
areaId: string
areaName: string
deptLevel: number
roleList: string[]
roleCode: string[]
}

View File

@@ -27,7 +27,7 @@ function createAxios<Data = any, T = ApiPromise<Data>>(
const userInfo = useUserInfoStore()
const Axios = axios.create({
baseURL: import.meta.env.VITE_URL,
baseURL: '/api',
timeout: 1000 * 60 * 5,
headers: {},
responseType: 'json',

View File

@@ -0,0 +1,9 @@
import { useUserInfoStore } from '@/stores/user'
import { USER_INFO } from '@/constants/storeKey'
export function clearUserInfo() {
const userInfo = useUserInfoStore()
userInfo.$reset()
// 清除用户信息缓存
localStorage.removeItem(USER_INFO)
}

View File

@@ -1,26 +1,119 @@
<template>
<div ref="loginContent" class="text-xl text-red-600">
<h1 ref="loginTitle">123</h1>
<svg-icon name="wind" color="#fff" size="100" spin > </svg-icon>
<div ref="loginContent" class="login">
<div class="login_form">
<div class="login_form_title">自动检测平台</div>
<el-form :model="LoginForm" :rules="rules" ref="formRef">
<el-form-item label="" prop="loginUserName">
<el-input
v-model="LoginForm.loginUserName"
:prefix-icon="Avatar"
placeholder="请输入账户"
></el-input>
</el-form-item>
<el-form-item label="" prop="loginUserPassword">
<el-input
v-model="LoginForm.loginUserPassword"
:prefix-icon="Lock"
type="password"
placeholder="请输入密码"
show-password
></el-input>
</el-form-item>
</el-form>
<el-button
type="primary"
@click="handleLogin"
style="width: 100%"
:loading="loginLoading"
> </el-button
>
</div>
</div>
</template>
<script setup lang='ts'>
defineOptions(
{
name: "CustomLogin"
}
)
import {ref, onMounted} from 'vue'
let loginContent = ref()
let loginTitle = ref()
onMounted(() => {
console.log(loginTitle.value);
<script setup lang="ts">
defineOptions({
name: "CustomLogin",
});
import { ref, onMounted } from "vue";
const router = useRouter();
import { useRouter } from "vue-router";
import { Avatar, Lock } from "@element-plus/icons-vue";
import { useUserInfoStore } from "@/stores/user";
const userInfoStore = useUserInfoStore();
const rules = {
loginUserName: [{ required: true, message: "请输入用户名", trigger: "blur" }],
loginUserPassword: [
{ required: true, message: "请输入密码", trigger: "blur" },
],
};
const loginLoading = ref(false);
const LoginForm = ref({
loginUserName: "",
loginUserPassword: "",
});
let loginContent = ref();
const formRef = ref();
const handleLogin = () => {
formRef.value.validate((validate: any) => {
if (validate) {
loginLoading.value = true;
if (LoginForm.value.loginUserName && LoginForm.value.loginUserPassword) {
setTimeout(() => {
// router.push({
// path: "/admin",
// query: {
// name: LoginForm.value.loginUserName,
// },
// });
userInfoStore.dataFill({ loginName: LoginForm.value.loginUserName });
console.log(userInfoStore.loginName)
}, 1500);
}
}
});
};
</script>
<style scoped>
<style scoped lang="scss">
.login {
width: 100%;
height: 100vh;
display: flex;
align-items: center;
justify-content: flex-end;
padding-right: 10%;
background: #0b47a1 url("../assets/images/login/background.png") no-repeat left center;
background-size: auto;
.login_form {
width: 30rem;
height: 27rem;
cursor: pointer;
border-radius: 12px;
box-shadow: 6px 6px 10px #000;
background-color: #fff;
border: 1px solid #eee;
padding: 10px 20px 10px;
.login_form_title {
width: 100%;
height: 4rem;
font-size: 32px;
text-align: center;
padding: 5px 0;
font-family: "DongFangDaKai";
letter-spacing: 4px;
margin-bottom: 40px;
}
.el-button {
margin-top: 10px;
}
}
}
:deep(.el-input){
outline: none !important;
border: 0 !important;
}
</style>