elmentPlus + vuex 配置 login页面

260 阅读1分钟

该项目git地址

  • 结合项目源码更容易看懂 里面有很多注释

设计思路

  • image.png

  • image.png

  • 如图所示

  • Login 里面注册 panel 页面 主要用来设置样式 居中

    • panel 为父组件
    • account 和 phone 为子组件 两种不同的登录方式 只讲一下 account 的登录
    • 把登录放在 vuex 中对数据进行全局保存

具体实现

  • panel

    • <template>
        <div class="login-panel">
          <h1 class="title">后台管理系统</h1>
          <el-tabs v-model="currentTab" type="border-card" stretch>
            <el-tab-pane name="account">
              <template #label>
                <span><i class="el-icon-user-solid"></i> 账号登录</span>
              </template>
              <login-account ref="accountRef" />
            </el-tab-pane>
            <el-tab-pane name="phone">
              <template #label>
                <span><i class="el-icon-mobile-phone"></i> 手机登录</span>
              </template>
              <login-phone ref="phoneRef" />
            </el-tab-pane>
          </el-tabs>
      ​
          <div class="account-control">
            <el-checkbox v-model="isKeepPassword">记住密码</el-checkbox>
            <el-link type="primary">忘记密码</el-link>
          </div>
      ​
          <el-button type="primary" class="login-btn" @click="handleLoginClick"
            >立即登录</el-button
          >
        </div>
      </template><script setup lang="ts">
      import { ref } from 'vue'
      import LoginAccount from './login-account.vue'
      import LoginPhone from './login-phone.vue'// 1.定义属性
      // 记住密码
      const isKeepPassword = ref(true)
      // 获取输入账号信息 模块
      const accountRef = ref<InstanceType<typeof LoginAccount>>()
      // 获取输入手机号 验证码
      const phoneRef = ref<InstanceType<typeof LoginPhone>>()
      // 获取登录方式模块
      const currentTab = ref('account')
      ​
      // 2.定义方法
      const handleLoginClick = () => {
        console.log(accountRef.value)
        if (currentTab.value === 'account') {
          accountRef.value?.loginAction(isKeepPassword.value)
        } else {
          console.log('phoneRef调用loginAction')
        }
      }
      </script><style scoped lang="less">
      .login-panel {
        margin-bottom: 150px;
        width: 320px;
      ​
        .title {
          text-align: center;
        }
      ​
        .account-control {
          margin-top: 10px;
          display: flex;
          justify-content: space-between;
        }
      ​
        .login-btn {
          width: 100%;
          margin-top: 10px;
        }
      }
      </style>
  • account

    • <template>
        <div class="login-account">
          <el-form ref="formRef" label-width="60px" :rules="rules" :model="account">
            <el-form-item label="账号" prop="name">
              <el-input v-model="account.name" />
            </el-form-item>
            <el-form-item label="密码" prop="password">
              <el-input v-model="account.password" show-password />
            </el-form-item>
          </el-form>
        </div>
      </template><script setup lang="ts">
      import { reactive, ref } from 'vue'
      import { useStore } from 'vuex'
      import { ElForm } from 'element-plus'
      // 导入本地缓存模块
      import localCache from '../../../utils/cache'
      // 导入账号密码输入规则
      import { rules } from '../config/account-config'const store = useStore()
      // 获取账号密码组件
      const account = reactive({
        name: localCache.getCache('name') ?? '',
        password: localCache.getCache('password') ?? '',
      })
      // 获取哪种登录方式
      const formRef = ref<InstanceType<typeof ElForm>>()
      ​
      const loginAction = (isKeepPassword: boolean) => {
        formRef.value?.validate((valid) => {
          if (valid) {
            // 1.判断是否需要记住密码
            if (isKeepPassword) {
              // 本地缓存
              localCache.setCache('name', account.name)
              localCache.setCache('password', account.password)
            } else {
              localCache.deleteCache('name')
              localCache.deleteCache('password')
            }
      ​
            // 2.开始进行登录验证 这里的方法在 store action 中有定义 名字要相同 传入账号密码参数
            store.dispatch('login/accountLoginAction', { ...account })
          }
        })
      }
      // 因为使用了 setup 语法糖 父组件要获取函数属性的话 就要使用这个暴露 因为没有 return 了
      defineExpose({
        loginAction,
      })
      </script><style scoped></style>

store

  • import { Module } from 'vuex'import {
      accountLoginRequest
    } from '@/service/login/login'
    import localCache from '@/utils/cache'
    import router from '@/router'import { IAccount } from '@/service/login/type'
    import { ILoginState } from './types'
    import { IRootState } from '../types'const loginModule: Module<ILoginState, IRootState> = {
      namespaced: true,
      state() {
        return {
          token: ''
        }
      },
      getters: {},
      mutations: {
        changeToken(state, token: string) {
          state.token = token
        }
      },
      actions: {
        async accountLoginAction({ commit }, payload: IAccount) {
          // 实现登录逻辑
          const loginResult = await accountLoginRequest(payload)
          const { token } = loginResult.data
          commit('changeToken', token)
          localCache.setCache('token', token)
    ​
          // 跳到首页
          router.push('/main')
        },
        loadLocalLogin({ commit }) {
          // 用于更新公共仓库储存的数据 比如换了账号登录 这些信息就要更新
          const token = localCache.getCache('token')
          if (token) {
            commit('changeToken', token)
          }
        },
      },
    }
    ​
    export default loginModule
    ​
    

\