vue3+node构建后台管理系统

在这里插入图片描述
整合vite+vue3前端与node+express后端,通过 concurrently插件 同时启动前后端项目

🤔 前端技术栈:

viteelement-plusvue3typescriptaxiospiniavue-routerecharts

🤔 后端技术栈:

nodeexpressbody-parserjsonwebtokenmongoosenodemonpassportpassport-jwtnode-rsa

一、整体目录

full-stack-admin
|- client        				# vue前端
|	  |- public					# 系统静态资源(不会被打包)
|     |- src					# 项目主要文件
|	  |	    |- api				# 封装request及http请求文件
|	  |		|- assets			# 静态资源文件
|	  |		|- components   	# 存放全局组件
|     |     |- layout 			# 框架布局模块
|     |     |- router			# 路由管理
|     |     |- store        	# pinia状态管理
|	  |     |- types			# 全局ts声明
|     |     |- utils			# 存放封装好的常用函数
|     |     |- views			# 项目页面
|	  |     |- vite-env.d.ts	# 指定ts识别vue
|	  |     |- main.ts			# 项目入口文件
| 	  |     |- App.vue			# 项目主组件
|	  |- package.json			# 依赖包管理
|     |- README.md				# README介绍
|	  |- tsconfig.json			# typeScript 全局配置
|	  |- index.html				# 入口 html
|	  |- .eslintrc.cjs			# eslint配置文件
|     |- .prettierrc.cjs		# prettier配置文件
|	  |- vite.config.ts	 	  	# vite全局配置文件
|- service       				# node后端
|     |- app.js					# 入口文件
|	  |- package.json			# 依赖包管理
|     |- Shemas					# mongodb数据库对象集合
|     |- router					# express路由
|	  |- config					# 引用配置项,包含jwt函数及rsa函数
|- package.json  				# 依赖包管理
|- README.md     				# README介绍

二、项目搭建

mongodb安装
vue-cli安装
nvm安装管理node

1. 新建项目主文件夹 full-stack-admin

npm init
npm install concurrently

2.full-stack-admin 下 新建service文件夹

pnpm install weboack webpack-cli -D
pnpm install express
pnpm install mongoose
pnpm install nodemon
pnpm install body-parser
pnpm install jsonwebtoken
pnpm install node-rsa
pnpm install passport passport-jwt

修改package.json
"script": {
	"start": "nodemon app.js"  //我主文件命名为app.js   大部分人习惯server.js
}
service新建config文件夹

config文件夹新建passport.js

// jwt验证
const JwtStrategy = require('passport-jwt').Strategy,
      ExtractJwt = require('passport-jwt').ExtractJwt
const User = require('../Schemas/userSchema')

const opts = {}
opts.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken()
opts.secretOrKey = 'secret'

module.exports = (passport) => {
  passport.use(
    new JwtStrategy(opts, (jwt_payload, done) => {
      User.findOne(jwt_payload.id).then((user) => {
        if(user) {
          return done(null, user)
        }
        return done(null, false)
      }).catch((err) => console.log(err))
    })
  )
}

config文件夹新建rsa.js

const NodeRSA = require('node-rsa')

const priKey = `***`  publickey和primarykey在网上生成https://uutool.cn/rsa-generate/

const RSA = {
  decrypted(data){
    const privateKey = new NodeRSA(priKey)
    privateKey.setOptions({ encryptionScheme: 'pkcs1'})
    const deStr = privateKey.decrypt(data, 'utf8')
    return deStr
  }
}

module.exports = RSA
service新建Schemas文件夹

schemas新建userSchema.js

const mongoose = require('mongoose')
const Schema = mongoose.Schema

// create schema
const UserSchema = new Schema({
  userName: String,
  userPassword: String
})

let UserModel = mongoose.model('user', UserSchema)
module.exports = UserModel
service新建router文件夹

router文件夹新建api文件夹 router的下级文件夹 对应接口中/api /ws等
api文件夹新建user.js

const express = require('express')
const router = express.Router()
const jwt = require('jsonwebtoken')
const passport = require('passport')
const RSA = require('../../config/rsa')

const User = require('../../Schemas/userSchema')

/**
 * @description 用户注册接口
 * @method post
 */
router.post('/register', (req, res) => {
  // 使用rsa解密参数
  const userName = RSA.decrypted(req.body.userName)
  const userPassword = RSA.decrypted(req.body.userPassword)
  // 首先判断用户是否已被注册
  User.findOne({ userName: userName }).then((user) => {
    if (user) {
      return res.json({ data: { code: 40000, message: '该用户已被注册' } })
    } else {
      const newUser = new User({
        userName: userName,
        userPassword: userPassword
      })
      newUser.save().then((result) => {
        res.json({ data: { code: 20000, message: '注册成功' } })
      }).catch(err => {
        console.log(err)
      })
    }
  })
})

/**
 * @description 用户登录接口
 * @method post
 */
router.post('/login', (req, res) => {
  let userName = RSA.decrypted(req.body.userName),
      userPassword = RSA.decrypted(req.body.userPassword)
  User.findOne({ userName: userName }).then((user) => {
    if (!user) {
      return res.json({ data: { code: 40100, message: '账号或密码错误' } })
    } else {
      if (userName === user.userName && userPassword === userPassword) {
        let date = new Date()
        let year = date.getFullYear()
        let month = date.getMonth()
        let day = date.getDate()
        let h = date.getHours()
        let m = date.getMinutes()
        let nowDate = year + '/' + month + '/' + day + ' ' + h + ':' + m
        let userInfo

        let rule = {
          userName: user.userName,
          userPassword: user.userPassword,
          nowDate: nowDate
        }
        jwt.sign(rule, 'secret', { expiresIn: 60 * 60 * 24 }, (err, token) => {
          if (err) throw err
          return res.json({
            data: {
              code: 20000,
              message: '登录成功',
              token: 'Bearer ' + token,
            }
          })
        })
      } else {
        return res.json({ data: { code: 40100, message: '账号或密码错误' } })
      }
    }
  })
})

module.exports = router
service新建app.js 作为后端项目入口文件
const express = require('express')
const bodyparser = require('body-parser')
const mongoose = require('mongoose')
const passport = require('passport')

const app = express()
const hostname = 'localhost'
const port = 3000

// 连接mongodb
mongoose.connect('mongodb://127.0.0.1:27017/fullstack', {
  useNewUrlParser: true,
  useUnifiedTopology: true
}).then(() => {
  console.log('Mongodb Connected')
}).catch((err) => {
  console.log(err)
})

// CORS跨域
app.all('*', (req, res, next) => {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Content-Type, Authorization");
  res.header("Access-Control-Allow-Methods", "*");
  next();
})

// use bodyparser
app.use(bodyparser.urlencoded({ extended: false }))
app.use(bodyparser.json())

// passport 初始化
app.use(passport.initialize())
require('./config/passport')(passport)

// 模拟日志 打印访问时间及路径
function loggingMiddleware(req, res, next) {
  const time = new Date()
  console.log(`[${time.toLocaleString()}] ${req.method} ${req.url}`)
  next()
}
app.use(loggingMiddleware)

// 引入并使用接口
const user = require('./router/api/user')
app.use('/api/user', user)

app.listen(port, ()=> {
  console.log(`Service running at http://${hostname}:${port}`)
})
service新建webpack.config.js
const path = require('path')

module.exports = {
  mode: "production",
  entry: './app.js',
  target:"node",
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js',
    clean: true
  }
};
修改package.json
"scripts": {
    "start": "nodemon app.js",
    "build": "webpack"
  }

3.full-stack-admin 打开终端,创建client前端项目

pnpm create vite

输入项目名
? Project name: » client

选择Vue框架
? Select a framework: » - Use arrow-keys. Return to submit.
    Vanilla
>   Vue
    React
    Preact
    Lit
    Svelte
    Others

选择TypeScript
? Select a variant: » - Use arrow-keys. Return to submit.
    JavaScript
>   TypeScript
    Customize with create-vue ↗
    Nuxt ↗

进入创建的项目  可以直接控制台 cd client 也可以编辑器打开文件夹client
pnpm install
pnpm run dev

前端项目的基本配置参考vite+vue3+ts详细配置

win+R打开cmd 输入ipconfig查看本地ip

在这里插入图片描述

修改vite.config.ts 配置跨域
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import eslint from 'vite-plugin-eslint'
import { resolve } from 'path'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue(),
    eslint(),
    AutoImport({
      resolvers: [ElementPlusResolver()]
    }),
    Components({
      resolvers: [ElementPlusResolver()]
    })
  ],
  resolve: {
    alias: {
      '@': resolve(__dirname, './src'),
      'vue-i18n': 'vue-i18n/dist/vue-i18n.cjs.js'
    }
  },
  server: {
    host: true,
    cors: true,
    port: 3000,
    proxy: {
      '/api': {
        target: 'http: //192.168.50.173:3000',
        changeOrigin: true,
        rewrite: path => path.replace(/^\/api\//, '')
      }
    }
  }
})

三、基本配置完毕

终端进入full-stack-admin

PS D:\workDemo\vue_demo\Full-Stack-Admin> npm start

> full-stack-admin@1.0.0 start
> concurrently "npm run client" "npm run service"

[0] 
[0] > full-stack-admin@1.0.0 client
[0] > npm start --prefix client
[0] 
[1] 
[1] > full-stack-admin@1.0.0 service
[1] > npm start --prefix service
[1] 
[1] 
[1] > service@1.0.0 start
[1] > nodemon app.js
[1] 
[0] 
[0] > client@0.0.0 start
[0] > vite --host --open
[0] 
[1] [nodemon] 3.0.1
[1] [nodemon] to restart at any time, enter `rs`
[1] [nodemon] watching path(s): *.*
[1] [nodemon] watching extensions: js,mjs,cjs,json
[1] [nodemon] starting `node app.js`
[1] Service running at http://localhost:3001
[0] 
[0]   VITE v4.4.5  ready in 793 ms
[0] 
[0]   ➜  Local:   http://localhost:3000/
[0]   ➜  Network: http://192.168.50.173:3000/
[1] Mongodb Connected

此时 终端输出Mongodb Connected,并且页面正常显示,就代表项目就完整启动了
在这里插入图片描述
在这里插入图片描述

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值