Jelajahi Sumber

完善登录页面

fxs 9 bulan lalu
induk
melakukan
6a2c0b771a
6 mengubah file dengan 93 tambahan dan 53 penghapusan
  1. 0 3
      components.d.ts
  2. TEMPAT SAMPAH
      dist.rar
  3. 0 1
      src/components/form/MyButton.vue
  4. 19 6
      src/components/form/MyInput.vue
  5. 1 0
      src/types/input.ts
  6. 73 43
      src/views/Login/LoginView.vue

+ 0 - 3
components.d.ts

@@ -7,7 +7,6 @@ export {}
 /* prettier-ignore */
 declare module 'vue' {
   export interface GlobalComponents {
-    Button: typeof import('./src/components/form/Button.vue')['default']
     ElButton: typeof import('element-plus/es')['ElButton']
     ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
     ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
@@ -36,13 +35,11 @@ declare module 'vue' {
     IconIcBaselineVisibilityOff: typeof import('~icons/ic/baseline-visibility-off')['default']
     IconMaterialSymbolsLightLogout: typeof import('~icons/material-symbols-light/logout')['default']
     IconMdiPassword: typeof import('~icons/mdi/password')['default']
-    IconMdiPasswordPassword: typeof import('~icons/mdi/password-password')['default']
     MyButton: typeof import('./src/components/form/MyButton.vue')['default']
     MyInput: typeof import('./src/components/form/MyInput.vue')['default']
     RegreshBtn: typeof import('./src/components/toolsBtn/RegreshBtn.vue')['default']
     RouterLink: typeof import('vue-router')['RouterLink']
     RouterView: typeof import('vue-router')['RouterView']
     Table: typeof import('./src/components/Table.vue')['default']
-    TextInput: typeof import('./src/components/form/TextInput.vue')['default']
   }
 }

TEMPAT SAMPAH
dist.rar


+ 0 - 1
src/components/form/MyButton.vue

@@ -1,5 +1,4 @@
 <script setup lang="ts">
-import { onMounted, ref } from 'vue'
 interface ButtonInfo {
   btnInfo: {
     text: string

+ 19 - 6
src/components/form/MyInput.vue

@@ -6,13 +6,15 @@ interface InputInfo {
   modelValue: string
   pInputType: string
   pinputRules: RuleInfo
+  placeholder: string
 }
 
 const props = defineProps<InputInfo>()
 
+// 通过update去更新props上的v-model数据
 const emits = defineEmits(['validateInput', 'update:modelValue'])
 
-let inputType = ref(props.pInputType) // inpt类型
+let inputType = ref(props.pInputType) // 主要用于更改pasword框的类型,因为props的type是只读的,所以额外创建一个
 
 const isPassword = ref(false) // 是否时password框
 
@@ -21,8 +23,8 @@ const inputRef = ref() // input框
 
 let passwordVisiable = ref(false) // 密码是否可见
 let activeClass = ref(false) // 是否被选中
-let showTip = ref(false)
-let errorMsg = ref('')
+let showTip = ref(false) // 是否展示提示框
+let errorMsg = ref('') // 提示的内容
 
 onMounted(() => {
   // 点击输入框则聚焦,并给边框
@@ -32,6 +34,8 @@ onMounted(() => {
       activeClass.value = false
     } else {
       activeClass.value = true
+      // inputRef.value.focus()
+      // 这里有时会出现inputRef.value为空的情况
       if (inputRef.value) {
         inputRef.value.focus()
       }
@@ -40,6 +44,7 @@ onMounted(() => {
   if (inputType.value === 'password') isPassword.value = true
 })
 
+// 改变密码框的可见性及可见按钮的切换
 const changeVisible = () => {
   passwordVisiable.value = !passwordVisiable.value
   if (passwordVisiable.value) {
@@ -49,6 +54,7 @@ const changeVisible = () => {
   }
 }
 
+// 验证input框是否符合规则
 const verifyIpt = () => {
   let rulesInfo = props.pinputRules
   if (rulesInfo) {
@@ -63,6 +69,7 @@ const verifyIpt = () => {
   }
 }
 
+// 当input框触发改变的时候,同步的更新v-model绑定的数据
 const updateValue = (val: any) => {
   emits('update:modelValue', val.target.value)
 }
@@ -80,14 +87,15 @@ const updateValue = (val: any) => {
         <div class="inputContent">
           <input
             ref="inputRef"
-            class="inputBody"
-            :type="inputType"
+            :class="['inputBody', { txtTopassword: inputType === 'password' }]"
+            type="text"
             @input="updateValue"
             @blur="verifyIpt"
+            :placeholder="placeholder"
           />
         </div>
 
-        <div class="inputVisble" v-if="isPassword" @click="changeVisible">
+        <div class="inputVisble" v-if="props.pInputType === 'password'" @click="changeVisible">
           <el-icon v-if="passwordVisiable" class="iconItem">
             <icon-ic-baseline-visibility></icon-ic-baseline-visibility>
           </el-icon>
@@ -171,6 +179,11 @@ const updateValue = (val: any) => {
   cursor: pointer;
 }
 
+/* 需要生成密码框的时候,将输入文字改为点状 */
+.txtTopassword {
+  -webkit-text-security: disc;
+}
+
 input {
   width: 100%;
   background: none;

+ 1 - 0
src/types/input.ts

@@ -5,5 +5,6 @@ export interface RuleType {
 
 export interface RuleInfo {
   name: string
+  placeholder: string
   rules: Array<RuleType>
 }

+ 73 - 43
src/views/Login/LoginView.vue

@@ -1,13 +1,11 @@
 <script setup lang="ts">
-import { onMounted, reactive, ref } from 'vue'
-import type { FormInstance } from 'element-plus'
+import { onMounted, reactive } from 'vue'
 import type { RuleInfo } from '@/types/input'
 import { useRequest } from '@/hooks/useRequest'
 import router from '@/router'
 import axiosInstance from '@/utils/axios/axiosInstance'
 import MyButton from '@/components/form/MyButton.vue'
 import MyInput from '@/components/form/MyInput.vue'
-import login from '@/router/login'
 
 const { AllApi, analysisResCode } = useRequest()
 
@@ -22,35 +20,28 @@ const loginInfo = reactive<LoginInfoType>({
 })
 
 const userLogin = () => {
-  axiosInstance
-    .post(AllApi.userLogin, loginInfo)
-    .then((data) => {
-      let result = JSON.parse(JSON.stringify(data))
-      analysisResCode(result, 'login')
-        .then(() => {
-          localStorage.setItem('token', result.token)
-          localStorage.setItem('refreshToken', result.refreshToken)
-          console.log('设置了')
-          router.push('/')
-        })
-        .catch((err) => {
-          console.log(err)
-        })
-    })
-    .catch((err) => {
-      console.log(err)
-    })
-}
-
-const onSubmit = (formEl: FormInstance | undefined) => {
-  if (!formEl) return
-  formEl.validate((valid, fields) => {
-    if (valid) {
-      userLogin()
-    } else {
-      console.log('error submit!', fields)
-    }
+  let vaild = Object.keys(loginInfo).every((key) => {
+    return formFieldsRules[key].rules.every((item) => item.validator())
   })
+  if (vaild) {
+    axiosInstance
+      .post(AllApi.userLogin, loginInfo)
+      .then((data) => {
+        let result = JSON.parse(JSON.stringify(data))
+        analysisResCode(result, 'login')
+          .then(() => {
+            localStorage.setItem('token', result.token)
+            localStorage.setItem('refreshToken', result.refreshToken)
+            router.push('/')
+          })
+          .catch((err) => {
+            console.log(err)
+          })
+      })
+      .catch((err) => {
+        console.log(err)
+      })
+  }
 }
 
 const formFieldsRules = reactive<{
@@ -58,10 +49,10 @@ const formFieldsRules = reactive<{
 }>({
   userName: {
     name: 'username',
+    placeholder: '请输入用户名',
     rules: [
       {
         validator: (): boolean => {
-          console.log(loginInfo.userName.trim())
           return loginInfo.userName.trim().length > 0
         },
         errMsg: '用户名不能为空'
@@ -70,12 +61,13 @@ const formFieldsRules = reactive<{
         validator: (): boolean => {
           return loginInfo.userName.trim().length >= 1 && loginInfo.userName.trim().length <= 16
         },
-        errMsg: '长度为1-16位'
+        errMsg: '用户名长度为1-16位'
       }
     ]
   },
   password: {
     name: 'password',
+    placeholder: '请输入密码',
     rules: [
       {
         validator: (): boolean => {
@@ -87,7 +79,7 @@ const formFieldsRules = reactive<{
         validator: (): boolean => {
           return loginInfo.password.trim().length >= 1 && loginInfo.password.trim().length <= 16
         },
-        errMsg: '长度为1-16位'
+        errMsg: '密码长度为1-16位'
       }
     ]
   }
@@ -101,16 +93,23 @@ onMounted(() => {})
   <div class="container">
     <div class="loginBox">
       <div class="banner"></div>
-      <div class="logo"></div>
+      <div class="logoBox">
+        <div class="logoImg">
+          <el-image :fit="'fill'" class="logoImg" src="/src/assets/logo.svg"></el-image>
+        </div>
+
+        <span class="logoText">淳皓科技</span>
+      </div>
       <div class="content">
         <div class="loginFormBox">
-          <div class="loginFormTitle">登录管理系统</div>
+          <div class="loginFormTitle">登录淳皓游戏管理系统</div>
           <div class="loginFormSubTitle">登录管理系统</div>
           <form class="loginForm">
             <div class="loginFormItem">
               <MyInput
-                p-input-type="'text'"
+                :p-input-type="'text'"
                 :pinput-rules="formFieldsRules.userName"
+                :placeholder="formFieldsRules.userName.placeholder"
                 v-model="loginInfo.userName"
                 class="userName"
               >
@@ -121,8 +120,9 @@ onMounted(() => {})
             </div>
             <div class="loginFormItem">
               <MyInput
-                p-input-type="'password'"
+                :p-input-type="'password'"
                 :pinput-rules="formFieldsRules.password"
+                :placeholder="formFieldsRules.password.placeholder"
                 v-model="loginInfo.password"
                 class="password"
               >
@@ -145,7 +145,7 @@ onMounted(() => {})
 .container {
   width: 100vw;
   height: 100vh;
-  background-color: lightblue;
+  // background-color: lightblue;
   position: relative;
   font-family:
     Inter,
@@ -168,14 +168,42 @@ onMounted(() => {})
   transform: translate(-50%, -50%);
   width: 900px;
   height: 500px;
-  background-color: lightcoral;
+  // background-color: lightcoral;
   display: flex;
 }
 
 .banner {
   width: 400px;
   height: 100%;
-  background-color: lightgreen;
+  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 {
@@ -185,11 +213,14 @@ onMounted(() => {})
   display: flex;
   align-items: center;
   justify-content: center;
+  border: 1px solid #e5e6eb;
+  border-left: none;
 }
 
 .loginFormBox {
   width: 320px;
 }
+
 .loginFormTitle {
   color: black;
   font-weight: 500;
@@ -207,7 +238,7 @@ onMounted(() => {})
   width: 100%;
   display: flex;
   flex-direction: column;
-
+  margin-top: 15px;
   align-items: center;
 }
 
@@ -218,7 +249,6 @@ onMounted(() => {})
 
 .loginBtn {
   margin-bottom: 30px;
-  margin-top: 30px;
 }
 
 .userName {