小白误入(需要一定的vue基础 )使用node建立服务器——vue前端登录注册页面连接到数据库

第一步:首先明确需要编写的文件:

vue前端的登录页面:login.vue

vue前端的注册页面:sign.vue

vue前端的路由页面,负责vue框架内页面的跳转:index.js

node后端连接数据,建立请求文件 :app.js

node后端连接数据库文件:mysql.js

一定要确保对应文件的连接位置。

代码架构:

javascript 复制代码
主目录
    src目录
        view目录
            login.vue
            sign.vue
        router目录
            index.js
        api目录
            app.js
            mysql.js

第二步书写对应的文件

login.vue

html 复制代码
<template>
  <div class="login-container">
    <div class="layer">
      <div class="some-space">
        <div class="form">
          <h2>大数据可视化平台</h2>
          <div class="item">
            <i class="iconfont icon-user"></i>
            <label for="username">登录</label>
            <input autocomplete="off"
                   type="text"
                   class="input"
                   v-model="form.username"
                   placeholder="请输入用户名" />
          </div>
          <div class="item">
            <i class="iconfont icon-password"></i>
            <label for="password">密码</label>
            <input autocomplete="off"
                   type="password"
                   class="input"
                   v-model="form.password"
                   maxlength="20"
                   @keyup.enter="login"
                   placeholder="请输入密码" />
          </div>
          <!-- 添加验证码相关的输入框和显示区域 -->
          <div class="item">
            <i class="iconfont icon-password"></i>
            <label for="verificationCode">验证码</label>
            <input autocomplete="off"
                   type="text"
                   class="input"
                   v-model="form.verificationCode"
                   placeholder="请输入验证码" />
            <span class="verification-code-img" @click="refreshVerificationCode">
              {
  
  { verificationCodeText }}
            </span>
          </div>
          <button class="loginBtn"
                  :disabled="isLoginAble"
                  @click.stop="login">
            立即登录
          </button>
          <button class="registerBtn" @click="goToRegister">
            注册用户
          </button>
          <div class="tip">
            默认用户名:admin ,默认密码:123456
          </div>
        </div>
      </div>
    </div>
    <vue-particles color="#6495ED"
                   :particleOpacity="0.7"
                   :particlesNumber="80"
                   shapeType="circle"
                   :particleSize="4"
                   linesColor="#6495ED"
                   :linesWidth="1"
                   :lineLinked="true"
                   :lineOpacity="0.6"
                   :linesDistance="150"
                   :moveSpeed="3"
                   :hoverEffect="true"
                   hoverMode="grab"
                   :clickEffect="true"
                   clickMode="push">
    </vue-particles>
    <bgAnimation />
  </div>
</template>


<script>
import { userLogin } from '../api/user';
import router from '../router';
export default {
  name: 'Home',
  data() {
    return {
      form: {
        username: '',
        password: '',
        verificationCode: '' // 添加验证码字段
      },
      verificationCodeText: '1234' // 模拟验证码文本,实际应用中应从后端获取并更新
    };
  },
  methods: {
    login() {
      // 简单验证验证码是否正确(这里只是简单示例,实际要对接后端验证逻辑)
      if (this.form.verificationCode === this.verificationCodeText) {
        userLogin(this.form)
        .then((res) => {
            alert(res.data.msg);
            router.push({
              path: '/traffic'
            });
          })
        .catch((err) => {
            alert(err.response.data.msg);
          });
      } else {
        alert('验证码错误,请重新输入');
      }
    },
    goToRegister() {
      console.log('准备跳转');
      router.push({
        path: '/about'
      });
      console.log('已执行跳转操作');
    },
    refreshVerificationCode() {
      // 模拟刷新验证码,这里简单修改文本,实际应从后端获取新的验证码
      this.verificationCodeText = Math.floor(Math.random() * 10000).toString().padStart(4, '0');
    }
  }
};
</script>

<style lang="scss" scoped>
.login-container {
.layer {
    position: absolute;
    height: 100%;
    width: 100%;
    background-image: url('../assets/bg-4.jpg');
    background-size: cover;
    background-repeat: no-repeat;
  }
  #particles-js {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: 1000;
  }
.some-space {
    color: white;
    font-weight: 100;
    letter-spacing: 2px;
    position: absolute;
    top: 50%;
    left: 50%;
    z-index: 1001;
    -webkit-transform: translate3d(-50%, -50%, 0);
    transform: translate3d(-50%, -50%, 0);
    -ms-animation: cloud 2s 3s ease-in infinite alternate;
    -moz-animation: cloud 2s 3s ease-in infinite alternate;
    -webkit-animation: cloud 2s 3s ease-in infinite alternate;
    -o-animation: cloud 2s 3s ease-in infinite alternate;
    animation: cloud 2s 3s ease-in infinite alternate;

  .form {
      width: 460px;
      height: auto;
      background: rgba(36, 36, 85, 0.5);
      margin: 0 auto;
      padding: 35px 30px 25px;
      box-shadow: 0 0 25px rgba(255, 255, 255, 0.5);
      border-radius: 10px;

    .item {
        display: flex;
        align-items: center;
        margin-bottom: 25px;
        border-bottom: 1px solid #d3d7f7;

        i {
          color: #d3d7f7;
          margin-right: 10px;
        }
      }

      h2 {
        text-align: center;
        font-weight: normal;
        font-size: 26px;
        color: #d3d7f7;
        padding-bottom: 35px;
      }

    .input {
        font-size: 16px;
        line-height: 30px;
        width: 100%;
        color: #d3d7f7;
        outline: none;
        border: none;
        background-color: rgba(0, 0, 0, 0);
        padding: 10px 0;
      }

    .loginBtn {
        width: 100%;
        padding: 12px 0;
        border: 1px solid #d3d7f7;
        font-size: 16px;
        color: #d3d7f7;
        cursor: pointer;
        background: transparent;
        border-radius: 4px;
        margin-top: 10px;
        &:hover {
          color: #fff;
          background: #0090ff;
          border-color: #0090ff;
        }
      }

    .registerBtn {
        width: 100%;
        padding: 12px 0;
        border: 1px solid #d3d7f7;
        font-size: 16px;
        color: #d3d7f7;
        cursor: pointer;
        background: transparent;
        border-radius: 4px;
        margin-top: 10px;
        &:hover {
          color: #fff;
          background: #0090ff;
          border-color: #0090ff;
        }
      }

    .tip {
        font-size: 12px;
        padding-top: 20px;
      }
      // 验证码显示区域样式
     .verification-code-img {
        margin-left: 10px;
        cursor: pointer;
        color: #d3d7f7;
      }
    }
  }
}

input::-webkit-input-placeholder {
  color: #d3d7f7;
}
input::-moz-placeholder {
  /* Mozilla Firefox 19+ */
  color: #d3d7f7;
}
input:-moz-placeholder {
  /* Mozilla Firefox 4 to 18 */
  color: #d3d7f7;
}
input:-ms-input-placeholder {
  /* Internet Explorer 10-11 */
  color: #d3d7f7;
}

@-ms-keyframes cloud {
  0% {
    -ms-transform: translate(-50%, -50%);
  }
  40% {
    opacity: 1;
  }
  60% {
    opacity: 1;
  }
  100% {
    -ms-transform: translate(-50%, -40%);
  }
}
@-moz-keyframes cloud {
  0% {
    -moz-transform: translate(-50%, -50%);
  }
  40% {
    opacity: 1;
  }
  60% {
    opacity: 1;
  }
  100% {
    -moz-transform: translate(-50%, -40%);
  }
}
@-o-keyframes cloud {
  0% {
    -o-transform: translate(-50%, -50%);
  }
  40% {
    opacity: 1;
  }
  60% {
    opacity: 1;
  }
  100% {
    -o-transform: translate(-50%, -40%);
  }
}
@-webkit-keyframes cloud {
  0% {
    -webkit-transform: translate(-50%, -50%);
  }
  40% {
    opacity: 1;
  }
  60% {
    opacity: 1;
  }
  100% {
    -webkit-transform: translate(-50%, -40%);
  }
}
@keyframes cloud {
  0% {
    transform: translate(-50%, -50%);
  }
  40% {
    opacity: 1;
  }
  60% {
    opacity: 1;
  }
  100% {
    transform: translate(-50%, -40%);
  }
}
</style>

sign.vue

html 复制代码
<template>
  <div class="login-container">
    <div class="layer"></div>
    <div id="particles-js"></div>
    <div class="some-space">
      <div class="form">
        <h2>用户登录/注册</h2>
        <div class="item">
          <i class="icon-user"></i>
          <input type="text" v-model="form.username" placeholder="请输入用户名" class="input" />
        </div>
        <div class="item">
          <i class="icon-lock"></i>
          <input type="password" v-model="form.password" placeholder="请输入密码" class="input" />
        </div>
        <div class="item">
          <i class="icon-lock"></i>
          <input type="password" v-model="form.confirmPassword" placeholder="请再次输入密码" class="input" />
        </div>
        <button @click="register" class="loginBtn">注册</button>
        <button @click="getUser" class="loginBtn">登录</button>
        <div class="tip">温馨提示:请按照要求填写信息哦~</div>
      </div>
    </div>
  </div>
</template>

<script>
import { getUserInfo, register } from '../api/user';
export default {
  data() {
    return {
      form: {
        username: '',
        password: '',
        confirmPassword: ''
      },
      userInfo: {}
    };
  },
  methods: {
    getUser() {
      getUserInfo(this.form.username).then(res => {
        this.userInfo = res.data.data[0];
      }).catch((err) => {
        console.log(err);
      });
    },
    register() {
      if (
        this.form.username === '' ||
        this.form.password === '' ||
        this.form.confirmPassword === ''
      ) {
        alert('数据不能为空');
        return;
      }
      // 验证两次输入的密码是否一致
      if (this.form.password!== this.form.confirmPassword) {
        alert('两次输入的密码不一致,请重新输入');
        return;
      }
      register({
        username: this.form.username,
        password: this.form.password
      })
    .then((res) => {
          alert(res.data.msg);
          this.$router.push('/');
        })
    .catch((err) => {
          alert(err.response.data.msg);
        });
    }
  }
};
</script>

<style lang="scss" scoped>
.login-container {
 .layer {
    position: absolute;
    height: 100%;
    width: 100%;
    background-image: url('../assets/bg-4.jpg');
    background-size: cover;
    background-repeat: no-repeat;
  }
  #particles-js {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: 1000;
  }
 .some-space {
    color: white;
    font-weight: 100;
    letter-spacing: 2px;
    position: absolute;
    top: 50%;
    left: 50%;
    z-index: 1001;
    -webkit-transform: translate3d(-50%, -50%, 0);
    transform: translate3d(-50%, -50%, 0);
    -ms-animation: cloud 2s 3s ease-in infinite alternate;
    -moz-animation: cloud 2s 3s ease-in infinite alternate;
    -webkit-animation: cloud 2s 3s ease-in infinite alternate;
    -o-animation: cloud 2s 3s ease-in infinite alternate;
    animation: cloud 2s 3s ease-in infinite alternate;

   .form {
      width: 460px;
      height: auto;
      background: rgba(36, 36, 85, 0.5);
      margin: 0 auto;
      padding: 35px 30px 25px;
      box-shadow: 0 0 25px rgba(255, 255, 255, 0.5);
      border-radius: 10px;

     .item {
        display: flex;
        align-items: center;
        margin-bottom: 25px;
        border-bottom: 1px solid #d3d7f7;

        i {
          color: #d3d7f7;
          margin-right: 10px;
        }
      }

      h2 {
        text-align: center;
        font-weight: normal;
        font-size: 26px;
        color: #d3d7f7;
        padding-bottom: 35px;
      }

     .input {
        font-size: 16px;
        line-height: 30px;
        width: 100%;
        color: #d3d7f7;
        outline: none;
        border: none;
        background-color: rgba(0, 0, 0, 0);
        padding: 10px 0;
      }

     .loginBtn {
        width: 100%;
        padding: 12px 0;
        border: 1px solid #d3d7f7;
        font-size: 16px;
        color: #d3d7f7;
        cursor: pointer;
        background: transparent;
        border-radius: 4px;
        margin-top: 10px;
        &:hover {
          color: #fff;
          background: #0090ff;
          border-color: #0090ff;
        }
      }

      // 注册按钮样式,与登录按钮样式保持一致
     .registerBtn {
        width: 100%;
        padding: 12px 0;
        border: 1px solid #d3d7f7;
        font-size: 16px;
        color: #d3d7f7;
        cursor: pointer;
        background: transparent;
        border-radius: 4px;
        margin-top: 10px;
        &:hover {
          color: #fff;
          background: #0090ff;
          border-color: #0090ff;
        }
      }

     .tip {
        font-size: 12px;
        padding-top: 20px;
      }
    }
  }
}

input::-webkit-input-placeholder {
  color: #d3d7f7;
}
input::-moz-placeholder {
  /* Mozilla Firefox 19+ */
  color: #d3d7f7;
}
input:-moz-placeholder {
  /* Mozilla Firefox 4 to 18 */
  color: #d3d7f7;
}
input:-ms-input-placeholder {
  /* Internet Explorer 10-11 */
  color: #d3d7f7;
}

@-ms-keyframes cloud {
  0% {
    -ms-transform: translate(-50%, -50%);
  }
  40% {
    opacity: 1;
  }
  60% {
    opacity: 1;
  }
  100% {
    -ms-transform: translate(-50%, -40%);
  }
}
@-moz-keyframes cloud {
  0% {
    -moz-transform: translate(-50%, -50%);
  }
  40% {
    opacity: 1;
  }
  60% {
    opacity: 1;
  }
  100% {
    -moz-transform: translate(-50%, -40%);
  }
}
@-o-keyframes cloud {
  0% {
    -o-transform: translate(-50%, -50%);
  }
  40% {
    opacity: 1;
  }
  60% {
    opacity: 1;
  }
  100% {
    -o-transform: translate(-50%, -40%);
  }
}
@-webkit-keyframes cloud {
  0% {
    -webkit-transform: translate(-50%, -50%);
  }
  40% {
    opacity: 1;
  }
  60% {
    opacity: 1;
  }
  100% {
    -webkit-transform: translate(-50%, -40%);
  }
}
@keyframes cloud {
  0% {
    transform: translate(-50%, -50%);
  }
  40% {
    opacity: 1;
  }
  60% {
    opacity: 1;
  }
  100% {
    transform: translate(-50%, -40%);
  }
}
</style> 

index.js

javascript 复制代码
import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter);

const routes = [
    {
        path: '/',
        name: 'Home',
        component: () => import('@/views/Home.vue'),
        meta: {
            title: '登录界面'
        }
    },
    {
        path: '/login',
        redirect: '/'
    },
    {
        path: '/about',
        name: 'About',
        component: () => import('@/views/About.vue'),
    }
];

const router = new VueRouter({
    routes,
});

export default router;

app.js

javascript 复制代码
const express = require('express');
const bodyParser = require('body-parser');
const multiparty = require('connect-multiparty');
const fs = require('fs');
let { conMysql } = require('./mysql');

// 创建统一的返回报文对象
class Response {
    constructor(isSucceed, msg, code, data) {
        this.isSucceed = isSucceed;
        this.msg = msg;
        this.code = code;
        this.data = data;
    }
}

// 创建
const app = express();

// 处理 x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true }));

// 处理 application/json
app.use(bodyParser.json());

// 处理 multipart/form-data
app.use(multiparty());

// 设置跨域访问
const cors = require('cors');
app.use(cors());

// 测试接口能否正常调用
app.get('/info', (req, res) => {
    res.send('Hello shaoyahu!');
});

// 测试数据库连接是否正常
app.get('/getUser', (req, res) => {
    let sql = 'select * from userinfo';
    conMysql(sql).then(result => {
        res.send(result);
    });
});

// 登录
app.post('/login', (req, res) => {
    let sql = `select * from userinfo where username = '${req.body.username}'`;
    conMysql(sql).then(result => {
        if (result[0]?.password === req.body.password) {
            let response = new Response(true, '登录成功', 200, result);
            res.send(response);
        } else {
            let response = new Response(false, '用户名或密码错误', 400);
            res.status(400).send(response);
        }
    }).catch(err => {
        res.status(500).send('数据库连接出错!');
    });
});

// 修改密码
app.post('/updatePassword', (req, res) => {
    let sql = `update userinfo set password = '${req.body.newPassword}' where username = '${req.body.username}'`;
    conMysql(sql).then(result => {
        if (result.affectedRows == 1) {
            let response = new Response(true, '修改成功', 200, result);
            res.send(response);
        } else {
            let response = new Response(false, '修改失败,请稍后重试', 400);
            res.status(400).send(response);
        }
    }).catch(err => {
        res.status(500).send('数据库连接出错!');
    });
});

// 用户注册接口
app.post('/register', (req, res) => {
    const { username, password } = req.body;
    // 简单的合法性校验,用户名和密码都不能为空
    if (!username ||!password) {
        let response = new Response(false, '用户名和密码不能为空', 400);
        res.status(400).send(response);
        return;
    }

    // 检查用户名是否已存在
    let checkSql = `select * from userinfo where username = '${username}'`;
    conMysql(checkSql).then(existResult => {
        if (existResult.length > 0) {
            let response = new Response(false, '用户名已存在,请更换用户名', 400);
            res.status(400).send(response);
            return;
        }

        // 插入新用户信息到数据库
        let insertSql = `insert into userinfo (username, password) values ('${username}', '${password}')`;
        conMysql(insertSql).then(insertResult => {
            if (insertResult.affectedRows === 1) {
                let response = new Response(true, '注册成功', 200, insertResult);
                res.send(response);
            } else {
                let response = new Response(false, '注册失败,请稍后重试', 400);
                res.status(400).send(response);
            }
        }).catch(err => {
            res.status(500).send('数据库连接出错!');
        });
    }).catch(err => {
        res.status(500).send('数据库连接出错!');
    });
});

// 获取当前用户信息
app.get('/getUserInfo', (req, res) => {
    let sql = `select * from userinfo where username = '${req.query.username}'`;
    conMysql(sql).then(result => {
        let response = new Response(true, '获取成功', 200, result);
        res.send(response);
    }).catch(err => {
        res.status(500).send('数据库连接出错!');
    });
});

// 生成文件的接口
app.get('/generateFile', async (req, res) => {
    try {
        let sql = 'select * from userinfo';
        const result = await conMysql(sql);
        const dataString = JSON.stringify(result, null, 2);
        fs.writeFileSync('userinfo.json', dataString);
        let response = new Response(true, '文件生成成功', 200, null);
        res.send(response);
    } catch (err) {
        res.status(500).send('数据库连接出错或文件生成失败!');
    }
});

// 启动
app.listen(3000, () => {
    console.log('express server running at http://127.0.0.1:' + 3000);
});

mysql.js

javascript 复制代码
let mysql = require('mysql')
const db_config = {
  host: 'localhost',
  user: 'root',
  password: 'mysql',
  port: '3306',
  database: 'db1'
}


function conMysql(sql) {
  let connect = mysql.createConnection(db_config)
  // 开始连接数据库
  connect.connect(function (err) {
    if (err) {
      console.log(`mysql连接失败: ${err}!`)
    } else {
      console.log('mysql连接成功!')
    }
  })
  return new Promise((resolve, reject) => {
    connect.query(sql, (err, result) => {
      if (err) {
        reject(err)
      } else {
        let res = JSON.parse(JSON.stringify(result))
        closeMysql(connect)
        resolve(res)
      }
    })
  })
}
// 查询成功后关闭mysql
function closeMysql(connect) {
  connect.end((err) => {
    if (err) {
      console.log(`mysql关闭失败:${err}!`)
    } else {
      console.log('mysql关闭成功!')
    }
  })
}
exports.conMysql = conMysql

要注意对应版本和环境

记得添加对应下载环境包

javascript 复制代码
{
  "name": "express",
  "version": "1.0.0",
  "main": "app.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "body-parser": "^1.20.0",
    "connect-multiparty": "^2.2.0",
    "cors": "^2.8.5",
    "express": "^4.18.1",
    "mysql": "^2.18.1"
  },
  "devDependencies": {
    "babel-preset-env": "^1.7.0"
  },
  "description": ""
}

第三部进pnpm命令安装和运行------效果展示

相关推荐
Danileaf_Guo3 小时前
256台H100服务器算力中心的带外管理网络建设方案
运维·服务器
我是小路路呀4 小时前
element级联选择器:已选中一个二级节点,随后又点击了一个一级节点(仅浏览,未确认选择),此时下拉框失去焦点并关闭
javascript·vue.js·elementui
程序员爱钓鱼4 小时前
Node.js 编程实战:文件读写操作
前端·后端·node.js
PineappleCoder5 小时前
工程化必备!SVG 雪碧图的最佳实践:ID 引用 + 缓存友好,无需手动算坐标
前端·性能优化
拾贰_C5 小时前
【Linux | Windows | Terminal Command】 Linux---grep | Windows--- findstr
linux·运维·服务器
JIngJaneIL5 小时前
基于springboot + vue古城景区管理系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot·后端
敲敲了个代码5 小时前
隐式类型转换:哈基米 == 猫 ? true :false
开发语言·前端·javascript·学习·面试·web
澄江静如练_5 小时前
列表渲染(v-for)
前端·javascript·vue.js
JustHappy6 小时前
「chrome extensions🛠️」我写了一个超级简单的浏览器插件Vue开发模板
前端·javascript·github