LoginView.vue 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. <!--
  2. * @Author: fxs bjnsfxs@163.com
  3. * @Date: 2024-08-20
  4. * @LastEditors: fxs bjnsfxs@163.com
  5. * @LastEditTime: 2024-12-03
  6. * @Description:
  7. *
  8. -->
  9. <script setup lang="ts">
  10. import { useUser } from '@/stores/useUser.ts'
  11. import type { RuleInfo } from '@/types/input'
  12. import { onMounted, reactive, ref } from 'vue'
  13. import { useRequest } from '@/hooks/useRequest'
  14. import { initLoadResource } from '@/utils/resource'
  15. import { setRefreshToken, setToken } from '@/utils/token/token'
  16. import { setLoginState } from '@/utils/localStorage/localStorage'
  17. import router from '@/router'
  18. import axiosInstance from '@/utils/axios/axiosInstance'
  19. import MyButton from '@/components/form/MyButton.vue'
  20. import MyInput from '@/components/form/MyInput.vue'
  21. const { AllApi, analysisResCode } = useRequest()
  22. const { setUserInfo } = useUser()
  23. interface LoginInfoType {
  24. userName: string
  25. password: string
  26. }
  27. const loginInfo = reactive<LoginInfoType>({
  28. userName: '',
  29. password: ''
  30. })
  31. // 判断目前是否在登陆
  32. const isLogin = ref(false)
  33. const formFieldsRules = reactive<{
  34. [key: string]: RuleInfo
  35. }>({
  36. userName: {
  37. name: 'username',
  38. placeholder: '请输入用户名',
  39. rules: [
  40. {
  41. validator: (): boolean => {
  42. return loginInfo.userName.trim().length > 0
  43. },
  44. errMsg: '用户名不能为空'
  45. },
  46. {
  47. validator: (): boolean => {
  48. return loginInfo.userName.trim().length >= 1 && loginInfo.userName.trim().length <= 16
  49. },
  50. errMsg: '用户名长度为1-16位'
  51. }
  52. ]
  53. },
  54. password: {
  55. name: 'password',
  56. placeholder: '请输入密码',
  57. rules: [
  58. {
  59. validator: (): boolean => {
  60. return loginInfo.password.trim().length > 0
  61. },
  62. errMsg: '密码不能为空'
  63. },
  64. {
  65. validator: (): boolean => {
  66. return loginInfo.password.trim().length >= 1 && loginInfo.password.trim().length <= 16
  67. },
  68. errMsg: '密码长度为1-16位'
  69. }
  70. ]
  71. }
  72. })
  73. // 资源的加载路径
  74. const resourceInfo: Record<string, string> = {
  75. logo: `/img/logo.svg`
  76. }
  77. // 使用blob的资源路径数组
  78. const blobUrlInfo = reactive<Record<string, string>>({})
  79. /**
  80. * @description: 验证登录信息是否符合表单规则
  81. * @param {*} loginInfo 登录信息
  82. * @return {*}
  83. */
  84. const validLoginInfo = (loginInfo: LoginInfoType): boolean => {
  85. return Object.keys(loginInfo).every((key) =>
  86. formFieldsRules[key].rules.every((item) => item.validator())
  87. )
  88. }
  89. /**
  90. * @description: 用户登录
  91. */
  92. const userLogin = async () => {
  93. if (isLogin.value) return
  94. isLogin.value = true
  95. let valid = validLoginInfo(loginInfo)
  96. if (valid) {
  97. try {
  98. let data = await axiosInstance.post(AllApi.userLogin, loginInfo)
  99. let result = JSON.parse(JSON.stringify(data))
  100. await analysisResCode(result, 'login')
  101. setToken(result.token)
  102. setRefreshToken(result.refreshToken)
  103. setLoginState(true)
  104. // TODO 保存和验证用户信息
  105. setUserInfo(result.isSuper)
  106. axiosInstance.defaults.headers['Authorization'] = result.token // 需要在这里设置,不然又会触发拦截器
  107. void router.push('/')
  108. } catch (err) {
  109. console.log(err)
  110. } finally {
  111. isLogin.value = false
  112. }
  113. }
  114. }
  115. onMounted(() => {
  116. // 去加载所有需要的资源
  117. initLoadResource(resourceInfo).then((data) => {
  118. Object.assign(blobUrlInfo, data)
  119. })
  120. })
  121. </script>
  122. <template>
  123. <!-- <img :src="urlList.head" style="width: 50px; height: 50px" alt="" /> -->
  124. <div class="container">
  125. <div class="loginBox">
  126. <div class="banner"></div>
  127. <div class="logoBox">
  128. <div class="logoImg">
  129. <el-image :fit="'fill'" class="logoImg" :src="blobUrlInfo.logo"></el-image>
  130. </div>
  131. <span class="logoText">淳皓科技</span>
  132. </div>
  133. <div class="content">
  134. <div class="loginFormBox">
  135. <div class="loginFormTitle">登录淳皓游戏管理系统</div>
  136. <div class="loginFormSubTitle">登录管理系统</div>
  137. <form class="loginForm" @submit.prevent>
  138. <!-- 一定要阻止默认提交事件,不然会导致第一次自动跳转 -->
  139. <div class="loginFormItem">
  140. <MyInput
  141. :p-input-type="'text'"
  142. :input-rules="formFieldsRules.userName"
  143. :placeholder="formFieldsRules.userName.placeholder"
  144. v-model="loginInfo.userName"
  145. class="userName"
  146. >
  147. <template #icon>
  148. <UserFilled />
  149. </template>
  150. </MyInput>
  151. </div>
  152. <div class="loginFormItem">
  153. <MyInput
  154. :p-input-type="'password'"
  155. :input-rules="formFieldsRules.password"
  156. :placeholder="formFieldsRules.password.placeholder"
  157. v-model="loginInfo.password"
  158. class="password"
  159. >
  160. <template #icon>
  161. <icon-mdi-password></icon-mdi-password>
  162. </template>
  163. </MyInput>
  164. </div>
  165. <div class="loginFormItem loginBtn">
  166. <MyButton @click-event="userLogin" :btn-info="{ text: '登录' }"></MyButton>
  167. </div>
  168. </form>
  169. </div>
  170. </div>
  171. </div>
  172. </div>
  173. </template>
  174. <style scoped lang="less">
  175. .container {
  176. width: 100vw;
  177. height: 100vh;
  178. // background-color: lightblue;
  179. position: relative;
  180. font-family:
  181. Inter,
  182. -apple-system,
  183. BlinkMacSystemFont,
  184. PingFang SC,
  185. Hiragino Sans GB,
  186. noto sans,
  187. Microsoft YaHei,
  188. Helvetica Neue,
  189. Helvetica,
  190. Arial,
  191. sans-serif;
  192. }
  193. .loginBox {
  194. position: absolute;
  195. left: 50%;
  196. top: 50%;
  197. transform: translate(-50%, -50%);
  198. width: 900px;
  199. height: 500px;
  200. // background-color: lightcoral;
  201. display: flex;
  202. }
  203. .banner {
  204. width: 400px;
  205. height: 100%;
  206. background-image: linear-gradient(to top, #30cfd0 0%, #330867 100%);
  207. // background-color: lightgreen;
  208. }
  209. .logoBox {
  210. box-sizing: border-box;
  211. position: fixed;
  212. left: 24px;
  213. top: 22px;
  214. min-height: 33px;
  215. display: flex;
  216. align-items: center;
  217. }
  218. .logoImg {
  219. width: 33px;
  220. height: 33px;
  221. }
  222. .logoText {
  223. display: inline-flex;
  224. align-items: center;
  225. height: 100%;
  226. min-height: 32px;
  227. margin-right: 4px;
  228. margin-left: 10px;
  229. color: white;
  230. font-size: 20px;
  231. font-weight: 600;
  232. }
  233. .content {
  234. width: 500px;
  235. position: relative;
  236. background-color: white;
  237. display: flex;
  238. align-items: center;
  239. justify-content: center;
  240. border: 1px solid #e5e6eb;
  241. border-left: none;
  242. }
  243. .loginFormBox {
  244. width: 320px;
  245. }
  246. .loginFormTitle {
  247. color: black;
  248. font-weight: 500;
  249. font-size: 24px;
  250. line-height: 32px;
  251. }
  252. .loginFormSubTitle {
  253. color: rgb(134, 144, 156);
  254. font-size: 16px;
  255. line-height: 24px;
  256. }
  257. .loginForm {
  258. width: 100%;
  259. display: flex;
  260. flex-direction: column;
  261. margin-top: 15px;
  262. align-items: center;
  263. }
  264. .loginFormItem {
  265. width: 100%;
  266. // min-height: 52px;
  267. }
  268. .loginBtn {
  269. margin-bottom: 30px;
  270. }
  271. .userName {
  272. margin: 1% 0;
  273. }
  274. </style>