VUE搭建后台管理界面

news2024/11/25 2:26:25

在这里插入图片描述


后台管理

    • 一、前言
    • 二、依赖配置
    • 三、koa框架
    • 四、数据库
    • 五、路由
    • 六、前端界面
      • 6.1 登录界面
      • 6.2 注册界面
      • 6.3 展示界面
    • 七、阿里云部署
      • 7.1 前端项目
      • 7.2 后端node
      • 7.3 mysql安装
      • 7.4 测试
    • 八、总结


一、前言

本篇文章从头到尾过一遍vue3搭建项目的过程,实现一个用户登录、注册,根据身份等级判断登录界面的应用。前端采用vue3+vite+element-plus,后端使用node.js+koa+mysql

2

4

5

项目开源地址:https://github.com/bosombaby/user_manage

二、依赖配置

{
  "name": "user_interface",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  },
  "dependencies": {
    "@element-plus/icons-vue": "^2.0.10",
    "axios": "^1.1.3",
    "element-plus": "^2.2.22",
    "nanoid": "^4.0.0",
    "vue": "^3.2.41",
    "vue-router": "^4.0.12"
  },
  "devDependencies": {
    "@vitejs/plugin-vue": "^3.2.0",
    "less": "^4.1.3",
    "unplugin-auto-import": "^0.11.4",
    "unplugin-vue-components": "^0.22.9",
    "vite": "^3.2.3"
  }
}

在这里插入图片描述

  • node_modules 文件夹用来存放所有已安装到项目中的包。require() 导入第三方包时,就是从这个目录中查找并加载包。
  • package-lock.json 配置文件用来记录 node_modules 目录下的每一个包的下载信息,例如包的名字、版本号、下载地址等。
  • package.json项目的名称、版本号、描述等、用到了哪些包、开发期间使用的包、部署使用的包
    • devDependencies :开发依赖
    • dependencies :核心依赖
  • 注意:程序员不要手动修改 node_modules 或 package-lock.json 文件中的任何代码,npm 包管理工具会自动维护它们,今后在项目开发中,一定要把 node_modules 文件夹,添加到 .gitignore 忽略文件中

三、koa框架

这次采取KOa框架作为后端,Koaexpress同一个团队开发,自由度、灵活度更高,异步请求也更加灵活了。后端主要还是对前端接口返回json数据,前端好进行数据处理。

const Koa = require('koa')
const cors=require('@koa/cors')
const router=require('./router/')
const bodyParser=require('koa-bodyparser')

//静态变量
const PORT = 8080

const app = new Koa()
// 跨域
app.use(bodyParser())
app.use(cors())
app.use(router.routes())

app.listen(PORT, () => {
    console.log(`http://127.0.0.1:${PORT}`);
})

之前看到几个写得比较好的koa框架教程,只不过有点老了,但思想还是通用的。

koa框架

技术博客

四、数据库

user_info

键名字段主键不为空
idVARCHAR(10)11
usernameVARCHAR(45)01
passwordVARCHAR(45)01
levelINT01

其中,level三个数值0 1 2分别代表超级管理员、管理员、普通用户

这次,刚开始请求数据库资源的时候,只用了简单的async/await,导致后端发送的一直是前端上一次请求的数据,淦!后来,发现对数据库整体请求要单独封装一个Promise对象,代码如下:

const mysql = require('mysql')

const pool = mysql.createPool({
    host: '127.0.0.1',
    user: 'root',
    password: '123456',
    database:'3d_resources'
    
})

let query = (sql, values)=> {
    return new Promise((resolve, reject) => {
        pool.getConnection((err, connection) => {
            if (err) {
                reject('数据库连接出错',err)
            } else {
                connection.query(sql, values, (err, results) => {
                    if (err) {
                        reject('数据库语句出错',err)
                    } else {
                        resolve(results)
                    }
                    connection.release()
                })
            }
        })
    })
}

module.exports=query

五、路由

vue3的路由使用和vue2已经完全不一样了,vue3使用起来更加自由,用到什么功能就导入对应的函数,但有时候写代码也下不去手。下面,主要讲解一下路由的基本使用。首先,创建router文件夹,统一管理路由。

import { createRouter, createWebHashHistory } from 'vue-router'

const routes = [
    {
        path: '/',
        redirect:'/login'
    },
    {
        path: '/login',
        name:'login',
        component:()=>import('../views/Login.vue')
    },
    {
        path: '/register',
        component:()=>import('../views/Register.vue')
    },
    {
        path: '/layout',
        component:()=>import('../views/Layout/Layout.vue'),
        children:[
            {
                path: '/layout/home0',
                name:'home0',
                component:()=>import('../views/Layout/Home0.vue'),
            },
            {
                path: '/layout/home1',
                name:'home1',
                component:()=>import('../views/Layout/Home1.vue'),
            },
            {
                path: '/layout/home2',
                name:'home2',
                component:()=>import('../views/Layout/Home2.vue'),
            },]
    }
]

const router = createRouter({
    history:createWebHashHistory(),
    routes,
   
})
export default router

createWebHashHistory()是路径问题,就是访问的时候带有/#/这个符号。Vue-Router有两种模式:hash模式和history模式。默认的路由模式是hash模式。

对于页面路由跳转,使用,传参啥的,使用 useRouter ,useRoute两个生成参数,不使用this了。

推荐文章:vue3中关于路由hash与History的设置

路由关系

  • 登录
  • 注册
  • 展示
    • 超级管理员界面
    • 管理员界面
    • 用户界面

其中,登录界面可以跳转到注册界面,注册完成跳转到登录界面。登录并且后端数据库验证通过,根据用户的身份进入不同的展示界面。

六、前端界面

6.1 登录界面

3

<template>
    <el-form :model="loginForm" class="login-form" ref="form">
        <!-- 账户 -->
        <el-form-item label="账号" prop="username" :rules="[{ required: true, message: '账号不能为空', trigger: 'blur' }]">
            <el-input v-model=loginForm.username />
        </el-form-item>

        <!-- 密码 -->
        <el-form-item label="密码" prop="password" :rules="[{ required: true, message: '密码不能为空', trigger: 'blur' }]">
            <el-input v-model="loginForm.password" type="password" />
        </el-form-item>

        <el-form-item class="last">
            <el-button type="primary" @click="checkInfo">登录</el-button>
            <el-button type="success" @click="enterRegister">进入注册</el-button>
        </el-form-item>
    </el-form>
</template>

<script setup>
import { ref, reactive,getCurrentInstance,onMounted } from 'vue'
import { useRouter ,useRoute} from 'vue-router'

import axios from 'axios'

const {proxy}=getCurrentInstance()

const loginForm = reactive({
    id: '', username: '', password: '',level:2
})

const router=useRouter()
const route=useRoute()

const request = axios.create({
    baseURL:'http://127.0.0.1:8080'
})



//账号验证
const checkInfo =  () => {
    //服务端验证账号密码
    proxy.$refs.form.validate(async (valid,fields) => {
        if (valid) {
            let userData={}
            let res= await request.post('/user/login', { username: loginForm.username, password: loginForm.password })
            if (!res.data.data.length) {
                alert('用户名或者密码错误!')
            } else {
                const username=res.data.data[0].username
                const level = res.data.data[0].level
                router.push({ name:`home${level}`,query:{username}})
            }
        }
        else {
            alert('数据不合法!')
        }
    })

}

//账号注册
const enterRegister = async () => {
    router.push({path:'/register'})
}


</script>

<style lang="less" scoped>
.login-form{
    width: 250px;
    margin: 200px auto;
    
    :deep(.el-form-item__content)  {
        justify-content: space-between;
    }
}
</style>

本次对利用element-plus快速搭建前端表单样式,对于非空也进行一点小小的判断。这里路由传参是,注意params只能使用name切换路由,而且可能是由于版本问题,params请求参数一直未被收集到。登录成功,根据level进入不同的管理界面。

6.2 注册界面

4

5

<template>
    <el-form :model="registerForm" class="register-form" ref="form" >
        <!-- 账户 -->
        <el-form-item label="账号" prop="username" :rules="[{ required: true, message: '账号不能为空', trigger: 'blur' }]">
            <el-input v-model=registerForm.username  />
        </el-form-item>

        <!-- 密码 -->
        <el-form-item label="密码" prop="password" :rules="[{ required: true, message: '密码不能为空', trigger: 'blur' }]">
            <el-input v-model="registerForm.password" type="password" />
        </el-form-item>

        <el-form-item >
            <el-button type="primary" @click="sumbitInfo">注册</el-button>
        </el-form-item>
    </el-form>
</template>

<script setup>

import { ref, reactive, getCurrentInstance } from 'vue'
import { useRouter } from 'vue-router';
import { customAlphabet } from 'nanoid'
import axios from 'axios'

const {proxy} =getCurrentInstance()
const router=useRouter()
//后端请求
const request = axios.create({
    baseURL:'http://127.0.0.1:8080'
})

const registerForm = reactive({
    id: '', username: '', password: '',level:2
})

const createId = () => {
    const nanoid = customAlphabet('vrteam_123456789', 9)
    return nanoid()

}

//注册用户
const sumbitInfo =  () => {

    proxy.$refs.form.validate(async (valid, fields) => {
        if (valid) {
            //唯一id
            registerForm.id = createId()
            registerForm.level = 2
            let userData={username:registerForm.username}
            let onlyCheck = await request.get('/user/check', { params: userData })

            if (onlyCheck.data.data.length) {
                alert('用户名已存在,请重新输入!')
            } else {
                let res = await request.post('/user/register', registerForm)
                if (res.data.data.affectedRows) {
                    alert('注册成功')
                    router.push({path:'/login'})
                } else {
                    alert('注册失败')
                }
            }
        } else {
            alert('数据不合法')
        }
    })
    
}
</script>

<style lang="less" scoped>
.register-form{
    width: 250px;
    margin:200px auto;
    
    :deep( .el-form-item__content){
        justify-content: space-around;
    }
}
</style>

注册界面对于后端有两次请求,一次是判断用户名是否唯一化的预检查,第二次才是真正的写入数据库。对于id的生成,采用nanoid

6.3 展示界面

6

7

就是普通的展示,没写太多东西,纯纯练手小项目。

七、阿里云部署

都写到这了,就体验一下项目上线的流程吧,本次采用阿里云服务器加上内置的宝塔面板部署。

7.1 前端项目

vue输入命令 npm run build打包项目,生成dist文件夹,文件夹上传服务器,进入宝塔面板。

在这里插入图片描述

填写公网ip或者域名,部署网站,这里默认80端口,切换端口再ip后端直接写就行。这里注意一点,端口一定要再宝塔面板的安全和服务器的防火请开启,不然访问不了。

7.2 后端node

这里采9

pm2配置项目,软件商店下载pm2,这里node版本尽量和本机开发环境一致,模块管理也就是npm包管理,这里的项目端口注意开放。这里我部署的时候还有一个问题,终端输入pm2node -v无法识别command,这里是没有配置环境变量的问题。我们可以使用软连接配置或者写入环境变量,这里直接网上搜一下就行了。

7.3 mysql安装

这里mysql添加,注意数据库的参数要和后端一致,编码也要一致。数据库创建完成之后,把mysql数据导入本地,然后上传服务器

在这里插入图片描述

7.4 测试

在这里插入图片描述

没啥问题

八、总结

本次对于vue3+koa前后端交互的项目有了一个大的了解,对于项目开发、上线流程有了一个大体的了解。但对于用户的持久化(cookie、sessioj)、路由限制这些没有应用到项目里面去,后续有时间慢慢完善技术,go!!!。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/28055.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux上使用telnet连接本机IP地址端口

场景 Linux开启了iptables&#xff01;&#xff01;&#xff01; 开启本机TCP80端口服务。Linux本机IP地址是192.168.204.129。本机telnet连接本机的TCP80端口。 目的 telnet 192.168.204.129 80&#xff0c;能够连接通。 输入规则 1&#xff09;需要配置一个让本机TCP80端…

日置IM3570阻抗分析仪产品介绍分享

日置IM3570阻抗分析仪 日本日置IM3570阻抗分析仪1台仪器实现不同测量条件下的高速检查,1台仪器实现LCR测量、DCR测量、扫描测量等的连续测量和高速检查,日本日置IM3570阻抗分析仪LCR模式下*快1.5ms&#xff08;1kHz&#xff09;&#xff0c;0.5ms&#xff08;100kHz&#xff0…

基于keras构建lstm模型自动生成音乐系统

目录 LSTM 机器学习生成音乐 1 数据集介绍 1 将 mid 转成 note 数组 4 将 note 数组转成 mid 文件 5 获取数据集并将其保存 6 将 note 进行编号 7 构建数据集 8 截取数据 8 进行 one-hot 编码 10 构建模型 11 训练 13 生成音乐 13 加载数据 16 加载模型 16 构建 id 与 note 的映…

我服了!SpringBoot升级后这服务我一个星期都没跑起来!(下)

14. DiscoveryEnabledServer Not Found 主要问题还是 eureka 中没有了 ribbon 相关的依赖。 Caused by: java.lang.NoClassDefFoundError: com/netflix/niws/loadbalancer/DiscoveryEnabledServerat java.lang.Class.getDeclaredMethods0(Native Method) ~[?:?]at java.lan…

论文笔记(二十二):GRiD: GPU-Accelerated Rigid Body Dynamics with Analytical Gradients

GRiD: GPU-Accelerated Rigid Body Dynamics with Analytical Gradients文章概括摘要1. 介绍2. 相关工作3. 背景A. *计算硬件&#xff1a;CPU vs. GPU*B. 刚体动力学4. GRiD库A. 设计B. 当前特征C. 代码优化方法5. 性能基准A. 方法B. 多重计算延时C. 单一计算延时扩展6. 结论和…

母线电容及其计算方法

母线电容及其计算方法 1.母线电容是什么&#xff1f; 2.母线电容有什么作用&#xff1f; 3.母线电容的参数。 4.母线电容参数计算。 1.母线电容是什么&#xff1f; 工程定义&#xff1a; &#xff08;1&#xff09;在电机控制器中&#xff0c;电池包的直流电作为输入电源&am…

关于 SAP ABAP SYSTEM_SHM_OPEN_CHANGE_LOCK 运行时错误的问题

有朋友在技术讨论群里提问&#xff1a; 遇到 SYSTEM_SHM_OPEN_CHANGE_LOCK 的运行时错误&#xff1a;Open change lock on transactional area in COMMIT: 上图显示&#xff0c;错误在 SAP ABAP 标准程序 SAPMHTTP 里抛出&#xff0c;这说明是 ABAP 服务器进行 HTTP 请求处理或…

SpringBoot SpringBoot 开发实用篇 5 整合第三方技术 5.23 SpringBoot 整合 RabbitMQ(direct 模式)

SpringBoot 【黑马程序员SpringBoot2全套视频教程&#xff0c;springboot零基础到项目实战&#xff08;spring boot2完整版&#xff09;】 SpringBoot 开发实用篇 文章目录SpringBootSpringBoot 开发实用篇5 整合第三方技术5.23 SpringBoot 整合 RabbitMQ(direct 模式)5.23.1…

web前端期末大作业——基于html+css+javascript+jquery+bootstrap响应式户外旅游网站

&#x1f468;‍&#x1f393;学生HTML静态网页基础水平制作&#x1f469;‍&#x1f393;&#xff0c;页面排版干净简洁。使用HTMLCSS页面布局设计,web大学生网页设计作业源码&#xff0c;这是一个不错的旅游网页制作&#xff0c;画面精明&#xff0c;排版整洁&#xff0c;内容…

分析高数值孔径物镜的聚焦

摘要 高数值孔径物镜广泛用于光学光刻、显微镜等。因此&#xff0c;在聚焦模拟中考虑光的矢量性质是非常重要的。 VirtualLab非常容易支持这种镜头的光线和光场追迹分析。 通过光场追迹&#xff0c;可以清楚地展示不对称焦斑&#xff0c;这源于矢量效应。 照相机探测器和电磁场…

解决台式机麦克风不可用问题,只有音频输出,无音频输入

解决台式机麦克风不可用问题 戴尔灵越3880 最近因为需要开线上会议&#xff0c;发现戴尔台式机音频只有输出没有输入&#xff0c;也就是只能听见声音&#xff0c;无法输入声音。 先后尝试了各种驱动安装更新之类的调试&#xff0c;无果。 之后通过戴尔支持解决~ 这里多说一…

京东主图视频上传,如何关联商品投放?

京东主图视频怎么做&#xff0c;如何上传主图视频&#xff1f;大家都知道商品可以展示五张主图&#xff0c;主图可以帮助买家更好地了解产品卖点。而主图视频可以更全面的展示产品&#xff0c;对此京麦还设置了不同类型的视频模板&#xff0c;但是很多新手商家往往在上传视频的…

适配器模式(Gateway中GatewayFilter和GlobalFilter整合实现)

文章目录GlobalFilter(代表全局过滤器)GatewayFilter(代表路由过滤器)GlobalFilterAdapter(适配器关键)测试类执行结果在SpringCloud Gateway中有两个不同的过滤器接口&#xff0c;分别是GatewayFilter和GlobalFilter。 GlobalFilter&#xff1a;全局过滤器。不需要再配置文件…

在外公网调阅公司内网资料文件【内网穿透】

优盘体积小巧重量轻&#xff0c;是不少人移动存储数据的首选。但优盘虽然方便携带&#xff0c;但也正是因为小巧和轻便&#xff0c;导致一不留神就会丢失&#xff0c;并且存储的数据也会有损坏的风险&#xff0c;因此在云存储概念兴起后&#xff0c;就快速成为数据存储的新风尚…

网络安全之反序列化漏洞复现

0x01 Apereo cas简介 Apereo CAS 单点登陆系统是Java服务器环境下使用较为广泛的单点登陆系统。 CAS 全程Central Authentication Service&#xff08;中心认证服务&#xff09;&#xff0c;是一个单点登录协议&#xff0c;Apereo CAS是实现该协议的软件包。 单点登录定义 …

【面试】Android 大厂必问的8大模块,你掌握了几个?

自15年毕业进入社会从事 Android 开发行业&#xff0c;&#xff0c;已经将近有八年的时光了&#xff1b; 在这将近八年的时间内&#xff0c; 我从 小厂打杂到进入到核心团队&#xff0c;再跳槽到大厂&#xff1b; 在华为呆过一段时间&#xff0c;18年四月份进了阿里一直到现在&…

体态识别算法在 Android 端部署实例

背景介绍 随着软硬件技术的发展&#xff0c;智能穿戴式设备逐渐从概念走向商用化。在过去几年内&#xff0c;Google、Apple以及Sony等科技公司在体积、功耗控制以及成本等方面做得越来越好&#xff0c;推出了一大批可穿戴产品&#xff0c;具有代表性的成果有&#xff1a;1. 智能…

Cy5 Alkyne,1223357-57-0,花青素Cyanine5炔基用于点击化学标记反应

CAS号&#xff1a;1223357-57-0 | 英文名&#xff1a; Cyanine5 alkyne&#xff0c;Cy5 Alkyne | 中文名&#xff1a;花青素CY5炔基 CASNumber&#xff1a;1223357-57-0 Molecular formula&#xff1a;C35H42ClN3O Molecular weight&#xff1a;556.19 Purity&#xff1a;9…

【CNN】ResNet——开启的深度学习从1到无限可能的新时代

前言 深度残差网络&#xff08;Deep residual network, ResNet&#xff09;的提出是CNN图像史上的一件里程碑事件&#xff0c;ResNet在2015年发表当年取得了图像分类&#xff0c;检测等等5项大赛第一&#xff0c;并又一次刷新了CNN模型在ImageNet上的历史记录。直到今天&#…

《看漫画学Python》1、2版分享,python最佳入门教程,中学生用业余时间都能学会,北大教授看完都这样定义它

前言 学习Python的小伙伴大部分应该都知道《看漫画学Python&#xff1a;有趣、有料、好玩、好用&#xff08;全彩版&#xff09;》这本书&#xff01; 但是刚开始接触Python的朋友都会有一个共同的烦恼&#xff0c;自学好无聊&#xff0c;好枯燥&#xff0c;不想坚持了……所…