123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302 |
- <!--
- * @Author: fxs bjnsfxs@163.com
- * @Date: 2024-08-20
- * @LastEditors: fxs bjnsfxs@163.com
- * @LastEditTime: 2024-12-03
- * @Description:
- *
- -->
- <script setup lang="ts">
- import { useUser } from '@/stores/useUser.ts'
- import type { RuleInfo } from '@/types/input'
- import { onMounted, reactive, ref } from 'vue'
- import { useRequest } from '@/hooks/useRequest'
- import { initLoadResource } from '@/utils/resource'
- import { setRefreshToken, setToken } from '@/utils/token/token'
- import { setLoginState } from '@/utils/localStorage/localStorage'
- import router from '@/router'
- import axiosInstance from '@/utils/axios/axiosInstance'
- import MyButton from '@/components/form/MyButton.vue'
- import MyInput from '@/components/form/MyInput.vue'
- const { AllApi, analysisResCode } = useRequest()
- const { setUserInfo } = useUser()
- interface LoginInfoType {
- userName: string
- password: string
- }
- const loginInfo = reactive<LoginInfoType>({
- userName: '',
- password: ''
- })
- // 判断目前是否在登陆
- const isLogin = ref(false)
- const formFieldsRules = reactive<{
- [key: string]: RuleInfo
- }>({
- userName: {
- name: 'username',
- placeholder: '请输入用户名',
- rules: [
- {
- validator: (): boolean => {
- return loginInfo.userName.trim().length > 0
- },
- errMsg: '用户名不能为空'
- },
- {
- validator: (): boolean => {
- return loginInfo.userName.trim().length >= 1 && loginInfo.userName.trim().length <= 16
- },
- errMsg: '用户名长度为1-16位'
- }
- ]
- },
- password: {
- name: 'password',
- placeholder: '请输入密码',
- rules: [
- {
- validator: (): boolean => {
- return loginInfo.password.trim().length > 0
- },
- errMsg: '密码不能为空'
- },
- {
- validator: (): boolean => {
- return loginInfo.password.trim().length >= 1 && loginInfo.password.trim().length <= 16
- },
- errMsg: '密码长度为1-16位'
- }
- ]
- }
- })
- // 资源的加载路径
- const resourceInfo: Record<string, string> = {
- logo: `/img/logo.svg`
- }
- // 使用blob的资源路径数组
- const blobUrlInfo = reactive<Record<string, string>>({})
- /**
- * @description: 验证登录信息是否符合表单规则
- * @param {*} loginInfo 登录信息
- * @return {*}
- */
- const validLoginInfo = (loginInfo: LoginInfoType): boolean => {
- return Object.keys(loginInfo).every((key) =>
- formFieldsRules[key].rules.every((item) => item.validator())
- )
- }
- /**
- * @description: 用户登录
- */
- const userLogin = async () => {
- if (isLogin.value) return
- isLogin.value = true
- let valid = validLoginInfo(loginInfo)
- if (valid) {
- try {
- let data = await axiosInstance.post(AllApi.userLogin, loginInfo)
- let result = JSON.parse(JSON.stringify(data))
- await analysisResCode(result, 'login')
- setToken(result.token)
- setRefreshToken(result.refreshToken)
- setLoginState(true)
- // TODO 保存和验证用户信息
- setUserInfo(result.isSuper)
- axiosInstance.defaults.headers['Authorization'] = result.token // 需要在这里设置,不然又会触发拦截器
- void router.push('/')
- } catch (err) {
- console.log(err)
- } finally {
- isLogin.value = false
- }
- }
- }
- onMounted(() => {
- // 去加载所有需要的资源
- initLoadResource(resourceInfo).then((data) => {
- Object.assign(blobUrlInfo, data)
- })
- })
- </script>
- <template>
- <!-- <img :src="urlList.head" style="width: 50px; height: 50px" alt="" /> -->
- <div class="container">
- <div class="loginBox">
- <div class="banner"></div>
- <div class="logoBox">
- <div class="logoImg">
- <el-image :fit="'fill'" class="logoImg" :src="blobUrlInfo.logo"></el-image>
- </div>
- <span class="logoText">淳皓科技</span>
- </div>
- <div class="content">
- <div class="loginFormBox">
- <div class="loginFormTitle">登录淳皓游戏管理系统</div>
- <div class="loginFormSubTitle">登录管理系统</div>
- <form class="loginForm" @submit.prevent>
- <!-- 一定要阻止默认提交事件,不然会导致第一次自动跳转 -->
- <div class="loginFormItem">
- <MyInput
- :p-input-type="'text'"
- :input-rules="formFieldsRules.userName"
- :placeholder="formFieldsRules.userName.placeholder"
- v-model="loginInfo.userName"
- class="userName"
- >
- <template #icon>
- <UserFilled />
- </template>
- </MyInput>
- </div>
- <div class="loginFormItem">
- <MyInput
- :p-input-type="'password'"
- :input-rules="formFieldsRules.password"
- :placeholder="formFieldsRules.password.placeholder"
- v-model="loginInfo.password"
- class="password"
- >
- <template #icon>
- <icon-mdi-password></icon-mdi-password>
- </template>
- </MyInput>
- </div>
- <div class="loginFormItem loginBtn">
- <MyButton @click-event="userLogin" :btn-info="{ text: '登录' }"></MyButton>
- </div>
- </form>
- </div>
- </div>
- </div>
- </div>
- </template>
- <style scoped lang="less">
- .container {
- width: 100vw;
- height: 100vh;
- // background-color: lightblue;
- position: relative;
- font-family:
- Inter,
- -apple-system,
- BlinkMacSystemFont,
- PingFang SC,
- Hiragino Sans GB,
- noto sans,
- Microsoft YaHei,
- Helvetica Neue,
- Helvetica,
- Arial,
- sans-serif;
- }
- .loginBox {
- position: absolute;
- left: 50%;
- top: 50%;
- transform: translate(-50%, -50%);
- width: 900px;
- height: 500px;
- // background-color: lightcoral;
- display: flex;
- }
- .banner {
- width: 400px;
- height: 100%;
- background-image: linear-gradient(to top, #30cfd0 0%, #330867 100%);
- // background-color: lightgreen;
- }
- .logoBox {
- box-sizing: border-box;
- position: fixed;
- left: 24px;
- top: 22px;
- min-height: 33px;
- display: flex;
- align-items: center;
- }
- .logoImg {
- width: 33px;
- height: 33px;
- }
- .logoText {
- display: inline-flex;
- align-items: center;
- height: 100%;
- min-height: 32px;
- margin-right: 4px;
- margin-left: 10px;
- color: white;
- font-size: 20px;
- font-weight: 600;
- }
- .content {
- width: 500px;
- position: relative;
- background-color: white;
- display: flex;
- align-items: center;
- justify-content: center;
- border: 1px solid #e5e6eb;
- border-left: none;
- }
- .loginFormBox {
- width: 320px;
- }
- .loginFormTitle {
- color: black;
- font-weight: 500;
- font-size: 24px;
- line-height: 32px;
- }
- .loginFormSubTitle {
- color: rgb(134, 144, 156);
- font-size: 16px;
- line-height: 24px;
- }
- .loginForm {
- width: 100%;
- display: flex;
- flex-direction: column;
- margin-top: 15px;
- align-items: center;
- }
- .loginFormItem {
- width: 100%;
- // min-height: 52px;
- }
- .loginBtn {
- margin-bottom: 30px;
- }
- .userName {
- margin: 1% 0;
- }
- </style>
|