04-简单注册和登录

飞一样的编程
飞一样的编程
擅长邻域:Java,MySQL,Linux,nginx,springboot,mongodb,微信小程序,vue

分类: Java springboot vue 专栏: 【带小白做项目】springboot和vue前台开发 标签: 注册登录

2025-10-22 19:16:49 90浏览

简单注册和登录

前提

先看后台开发的教程

https://www.bilibili.com/video/BV1JbUXYyEdx

因为是在这个的基础上开发前台

用到的工具

https://chatglm.cn/

先用这个粗略的画一个 vue 页面

然后自己改造,把死的页面动起来,交互起来,也就是要发请求。

美化页面啥的,或者遇到 bug 可以借助 ai 插件——codegeex

最终效果

几个请求

以下三个接口,杰哥偷懒了,直接共用了之前后台的登录注册

1. 登录接口

username:账号

password:密码

userType:user

2. 注册接口

username:账号

password:密码

rawPassword:确认密码

3. 验证账号唯一性的接口

这个接口要注意异步请求。可能会出现的 bug,

我这里明明写的是数据库存在的一个账号,并且失去焦点的时候已经能正常提示出账号已存在的错误信息,但我就是不管,直接点注册。导致竟然注册成功了,这显然不合理。

核心代码

<template>
  <div>
    <heard-view/>
    <div class="auth-container">
      <div class="auth-card">
        <div class="auth-header">
          <h2>{{ isLogin ? '登录' : '注册' }}</h2>
          <p>{{ isLogin ? '欢迎回来!' : '创建新账户' }}</p>
        </div>

        <form @submit.prevent="handleSubmit" class="auth-form">
          <!-- 账号输入 -->
          <div class="form-group">
            <label for="username">账号</label>
            <input
                id="username"
                v-model="form.username"
                type="text"
                placeholder="请输入账号"
                :class="{ 'error': errors.username }"
                @blur="validateUsername"
            />
            <span v-if="errors.username" class="error-message">{{ errors.username }}</span>
          </div>

          <!-- 密码输入 -->
          <div class="form-group">
            <label for="password">密码</label>
            <div class="password-input">
              <input
                  id="password"
                  v-model="form.password"
                  :type="showPassword ? 'text' : 'password'"
                  placeholder="请输入密码"
                  :class="{ 'error': errors.password }"
                  @blur="validatePassword"
              />
              <button
                  type="button"
                  class="toggle-password"
                  @click="showPassword = !showPassword"
              >
                {{ showPassword ? '隐藏' : '显示' }}
              </button>
            </div>
            <span v-if="errors.password" class="error-message">{{ errors.password }}</span>
          </div>

          <!-- 确认密码(仅注册时显示) -->
          <div v-if="!isLogin" class="form-group">
            <label for="rawPassword">确认密码</label>
            <input
                id="rawPassword"
                v-model="form.rawPassword"
                type="password"
                placeholder="请再次输入密码"
                :class="{ 'error': errors.rawPassword }"
                @blur="validaterawPassword"
            />
            <span v-if="errors.rawPassword" class="error-message">{{ errors.rawPassword }}</span>
          </div>

          <!-- 提交按钮 -->
          <button
              type="submit"
              class="submit-btn"
              :disabled="isSubmitting"
          >
            {{ isSubmitting ? '处理中...' : (isLogin ? '登录' : '注册') }}
          </button>

          <!-- 切换登录/注册 -->
          <div class="switch-auth">
            <span>{{ isLogin ? '还没有账户?' : '已有账户?' }}</span>
            <button
                type="button"
                class="switch-btn"
                @click="toggleAuthMode"
            >
              {{ isLogin ? '立即注册' : '立即登录' }}
            </button>
          </div>
        </form>
      </div>
    </div>
    <foot-view/>
  </div>

</template>

<script>
import heardView from "@/views/front/HeardView.vue";
import footView from "@/views/front/FootView.vue";
import {checkUsername, loginApi, regUser} from "@/api/app";
// import axios from "axios";
export default {
  name: 'AuthComponent',
  components: {footView, heardView},
  data() {
    return {
      isLogin: true,
      showPassword: false,
      isSubmitting: false,
      form: {
        username: '',
        password: '',
        userType: 'user',
        rawPassword: ''
      },
      errors: {
        username: '',
        password: '',
        rawPassword: ''
      },

    }
  },
  methods: {
    // 切换登录/注册模式
    toggleAuthMode() {
      this.isLogin = !this.isLogin
      this.resetForm()
      this.clearErrors()
    },

    // 重置表单
    resetForm() {
      this.form = {
        username: '',
        password: '',
        rawPassword: '',
        userType: 'user'
      }
    },

    // 清除错误信息
    clearErrors() {
      this.errors = {
        username: '',
        password: '',
        rawPassword: ''
      }
    },

    // 验证用户名
      async validateUsername() {
      if (!this.form.username.trim()) {
        this.errors.username = '账号不能为空'
        return false
      }

      if (this.form.username.length < 3) {
        this.errors.username = '账号长度至少3个字符'
        return false
      }

      if (!/^[a-zA-Z0-9_]+$/.test(this.form.username)) {
        this.errors.username = '账号只能包含字母、数字和下划线'
        return false
      }

      // 注册时检查用户名唯一性
      if (!this.isLogin) {

       // const  res=await axios.get(`/dev-api/user/check/${this.form.username}`)
       const  res=await checkUsername(this.form.username)
        console.log(res)
        this.errors.username = ''
        return true

      } else {
        //登录
        this.errors.username = ''
        return true
      }



    },

    // 验证密码
    validatePassword() {
      if (!this.form.password) {
        this.errors.password = '密码不能为空'
        return false
      }

      if (this.form.password.length < 6) {
        this.errors.password = '密码长度至少6个字符'
        return false
      }

      if (!/(?=.*[a-zA-Z])(?=.*\d)/.test(this.form.password)) {
        this.errors.password = '密码必须包含字母和数字'
        return false
      }

      this.errors.password = ''
      return true
    },

    // 验证确认密码
    validaterawPassword() {
      if (!this.form.rawPassword) {
        this.errors.rawPassword = '请确认密码'
        return false
      }

      if (this.form.password !== this.form.rawPassword) {
        this.errors.rawPassword = '两次输入的密码不一致'
        return false
      }

      this.errors.rawPassword = ''
      return true
    },

    // 验证整个表单
    async validateForm() {
      const isUsernameValid = await this.validateUsername()
      const isPasswordValid = this.validatePassword()

      if (!this.isLogin) {
        const israwPasswordValid = this.validaterawPassword()
        console.log(isUsernameValid)
        console.log(israwPasswordValid)
        console.log(isPasswordValid)
        return isUsernameValid && isPasswordValid && israwPasswordValid
      }

      return isUsernameValid && isPasswordValid
    },

    // 提交表单
    async handleSubmit() {
      const isValid = await this.validateForm()
      console.log('表单验证结果:', isValid)

      if (!isValid) {
        return
      }

      this.isSubmitting = true

      try {
        if (this.isLogin) {

          loginApi(this.form).then(res =>{
            console.log(res)
            this.$message.success('登录成功')
            sessionStorage.setItem("token", res.data);
            sessionStorage.setItem("username", this.form.username);
            sessionStorage.setItem("role", this.form.userType);
            this.$router.push("/index")
          })

        } else {

          regUser(this.form).then(res =>{
            console.log(res)
            this.$message.success('注册成功')
            this.toggleAuthMode()
          })
        }
      } catch (error) {
        console.error('操作失败:', error)
        alert('操作失败,请重试')
      } finally {
        this.isSubmitting = false
      }
    }
  }
}
</script>

<style scoped>
.auth-container {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: calc(100vh - 60px);
  padding-top: 60px; /* 导航栏高度 */
  background-color: #f5f7fa;
  font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', Arial, sans-serif;
}

.auth-card {
  background: white;
  padding: 40px;
  border-radius: 8px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  width: 100%;
  max-width: 400px;
  margin-bottom: 40px;
  transition: all 0.3s ease;
}

.auth-card:hover {
  box-shadow: 0 4px 20px 0 rgba(0, 0, 0, 0.15);
  transform: translateY(-2px);
}

.auth-header {
  text-align: center;
  margin-bottom: 30px;
  position: relative;
}

.auth-header h2 {
  color: #303133;
  margin-bottom: 12px;
  font-size: 24px;
  font-weight: bold;
}

.auth-header p {
  color: #909399;
  font-size: 14px;
}

.auth-form {
  display: flex;
  flex-direction: column;
  gap: 24px;
}

.form-group {
  display: flex;
  flex-direction: column;
}

.form-group label {
  margin-bottom: 8px;
  color: #606266;
  font-weight: 500;
  font-size: 14px;
}

.form-group input {
  padding: 12px 15px;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  font-size: 14px;
  transition: all 0.3s;
  height: 40px;
  line-height: 1;
  box-sizing: border-box;
}

.form-group input:focus {
  outline: none;
  border-color: #409eff;
  box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
}

.form-group input:hover {
  border-color: #c0c4cc;
}

.form-group input.error {
  border-color: #f56c6c;
}

.password-input {
  position: relative;
}

.toggle-password {
  position: absolute;
  right: 10px;
  top: 50%;
  transform: translateY(-50%);
  background: none;
  border: none;
  color: #909399;
  cursor: pointer;
  font-size: 14px;
  padding: 0;
}

.toggle-password:hover {
  color: #409eff;
}

.error-message {
  color: #f56c6c;
  font-size: 12px;
  margin-top: 6px;
  line-height: 1;
}

.submit-btn {
  background-color: #409eff;
  color: white;
  border: none;
  padding: 12px 20px;
  border-radius: 4px;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.3s;
  margin-top: 10px;
}

.submit-btn:hover:not(:disabled) {
  background-color: #66b1ff;
}

.submit-btn:active:not(:disabled) {
  background-color: #3a8ee6;
}

.submit-btn:disabled {
  background-color: #a0cfff;
  cursor: not-allowed;
}

.switch-auth {
  text-align: center;
  margin-top: 20px;
  font-size: 14px;
}

.switch-auth span {
  color: #606266;
}

.switch-btn {
  background: none;
  border: none;
  color: #409eff;
  cursor: pointer;
  font-size: 14px;
  margin-left: 5px;
  padding: 0;
}

.switch-btn:hover {
  color: #66b1ff;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .auth-container {
    padding: 20px;
  }

  .auth-card {
    padding: 30px 20px;
  }
}

</style>

好博客就要一起分享哦!分享海报

此处可发布评论

评论(0展开评论

暂无评论,快来写一下吧

展开评论

您可能感兴趣的博客

客服QQ 1913284695