天天看點

基于node vue的電商系統 mongodb express架構前言一、運作截圖?二、使用步驟

提示:文章寫完後,目錄可以自動生成,如何生成可參考右邊的幫助文檔

基于node vue的電商系統 mongodb express架構

  • 前言
    • 技術棧
    • 基本功能
      • 普通使用者
      • 管理者
  • 一、運作截圖?
  • 二、使用步驟
    • 1.前端main.js
    • 2.後端admin路由

前言

技術棧

  • 本項目采用前後端分離的開發方式,使用的技術棧是:Vue+Node+MongoDB
  • 前端:用vue-cli搭建,使用vue全家桶+element-ui
  • 後端:express架構
  • 資料庫:mongodb

基本功能

普通使用者

  • 注冊、登入
  • 根據關鍵詞對商品模糊搜尋
  • 根據分類查詢商品
  • 商品詳情展示
  • 加入購物車及建立訂單
  • 商品評論
  • 使用者個人中心(修改個人資訊及檢視訂單)

管理者

  • 登入
  • 使用者管理
  • 權限管理
  • 商品管理
  • 訂單管理
  • 資料統計

提示:以下是本篇文章正文内容,下面案例可供參考

一、運作截圖?

基于node vue的電商系統 mongodb express架構前言一、運作截圖?二、使用步驟
基于node vue的電商系統 mongodb express架構前言一、運作截圖?二、使用步驟
基于node vue的電商系統 mongodb express架構前言一、運作截圖?二、使用步驟
基于node vue的電商系統 mongodb express架構前言一、運作截圖?二、使用步驟
基于node vue的電商系統 mongodb express架構前言一、運作截圖?二、使用步驟
基于node vue的電商系統 mongodb express架構前言一、運作截圖?二、使用步驟
基于node vue的電商系統 mongodb express架構前言一、運作截圖?二、使用步驟
基于node vue的電商系統 mongodb express架構前言一、運作截圖?二、使用步驟
基于node vue的電商系統 mongodb express架構前言一、運作截圖?二、使用步驟
基于node vue的電商系統 mongodb express架構前言一、運作截圖?二、使用步驟

二、使用步驟

1.前端main.js

代碼如下(示例):

import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store'

Vue.config.productionTip = false

//圖檔懶加載
import LazyLoad from 'vue-lazyload'
Vue.use(LazyLoad, {
  error:require('./assets/img/error.png'),
  // 占位圖
  loading:require('./assets/img/loading.png')
})

//引入ElementUI庫
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI);

//省市區關聯
import VueAreaLinkage from 'vue-area-linkage';
import 'vue-area-linkage/dist/index.css';
Vue.use(VueAreaLinkage);

//引入圖示庫
import 'assets/fonts/iconfont.css'

//引入全局樣式
import 'assets/css/base.css'

//事件總線
Vue.prototype.$bus = new Vue();

new Vue({
    router,
    store,
    render: h => h(App)
}).$mount('#app')

//通過methods裡的代碼跳轉路由需要寫下面代碼: (不然重複點選會報錯)
import Router from 'vue-router'
const routerPush = Router.prototype.replace
Router.prototype.replace = function replace(location) {
  return routerPush.call(this, location).catch(error => error)
}

           

2.後端admin路由

代碼如下(示例):

import express from 'express'
import mongoose from 'mongoose'
import path from 'path'
import md5 from 'blueimp-md5'
import formidable from 'formidable'
import config from '../src/config.js'
import {
	Administrator,
	User,
	Category,
	Goods,
	Comment,
	Order
} from '../db/db'
const router = express.Router();

const S_KEY = '[email protected]' //鹽

//管理者登入
router.post('/login', async (req, res) => {
	let adminName = req.body.adminName;
	let adminPsw = md5(md5(req.body.adminPsw) + S_KEY);
	let result = await Administrator.findOne({
		adminName
	})
	if (result) {
		if (adminPsw === result.password) {
			req.session.admin = adminName;
			res.json({
				status_code: 200,
				message: '登入成功',
			})
		} else {
			res.json({
				status_code: 400,
				message: '密碼錯誤'
			})
		}
	} else {
		res.json({
			status_code: 400,
			message: '使用者名不存在'
		})
	}
})

//設定背景通路權限
router.use((req, res, next) => {
	if (!req.session.admin) {
		res.json({
			status_code: 400,
			message: '無權通路'
		})
	}
	next();
})

// 驗證登入狀态,若未被中間件攔截則為登入狀态
router.get('/isadmin', async (req, res) => {
	console.log(req.session.admin)
	if(req.session.admin){
		let result = await Administrator.findOne({
			adminName: req.session.admin
		})
		console.log(result)
		res.json({
			status_code: 200,
			message: '進入管理者界面',
			adminName: req.session.admin,
			role: result.role
		})
	}

})

//登出
router.get('/logout', (req, res) => {
	req.session.admin = '';
	res.json({
		status_code: 200,
		message: '已登出'
	})
})


/**************************************** 使用者管理 *******************************************/

//擷取使用者清單
router.get('/userlist', async (req, res) => {
	let result;
	if (req.query.userName) {
		result = await User.find({
			userName: {
				$regex: req.query.userName,
				$options: 'gi'
			}
		});
	} else {
		result = await User.find({});
	}
	res.json({
		status_code: 200,
		message: '擷取使用者清單成功',
		total: result.length,
		users: result
	})
})

//添加使用者
router.post('/adduser', (req, res) => {
	const form = new formidable.IncomingForm();
	form.uploadDir = config.uploadsAvatarPath; // 上傳圖檔放置的檔案夾
	form.keepExtensions = true; // 保持檔案的原始擴充名
	form.parse(req, (err, fields, files) => {
		let avatar;
		if (fields.userSex == '男') {
			avatar = 'http://localhost:' + config.port + '/boy_avatar.svg'
		} else {
			avatar = 'http://localhost:' + config.port + '/girl_avatar.svg'
		}
		if (files.userAvatar) {
			avatar = 'http://localhost:' + config.port + '/avatar_uploads/' + path.basename(files.userAvatar.path);
		}
		let userInfo = {
			userName: fields.userName,
			password: md5(md5(fields.userPsw) + S_KEY), //加密密碼
			userEmail: fields.userEmail,
			userPhone: fields.userPhone,
			userSex: fields.userSex,
			userSign: fields.userSign,
			userAdress: fields.userAdress,
			nickName: fields.nickName,
			// userAdress:fields.userAdress.replace(/,/g,''),
			userAvatar: avatar
		}
		User.create(userInfo, (err, doc) => {
			console.log(err, doc)
			if (!err) {
				res.json({
					status_code: 200,
					message: '添加使用者成功',
				})
			} else {
				res.json({
					status_code: 400,
					message: '内部錯誤,添加使用者失敗',
				})
			}
		})
	})
})

//編輯使用者
router.post('/edituser', (req, res) => {
	const form = new formidable.IncomingForm();
	form.uploadDir = config.uploadsAvatarPath; // 上傳圖檔放置的檔案夾
	form.keepExtensions = true; // 保持檔案的原始擴充名
	form.parse(req, (err, fields, files) => {
		let avatar;
		let userInfo = {
			userName: fields.userName,
			userEmail: fields.userEmail,
			userPhone: fields.userPhone,
			userSex: fields.userSex,
			userSign: fields.userSign,
			userAdress: fields.userAdress,
			nickName: fields.nickName
		}
		if (files.userAvatar) {
			avatar = 'http://localhost:' + config.port + '/avatar_uploads/' + path.basename(files.userAvatar.path);
			userInfo.userAvatar = avatar
		}
		if (fields.userPsw) {
			userInfo.password = md5(md5(fields.userPsw) + S_KEY); //加密密碼
		}
		User.updateOne({
			userName: fields.userName
		}, userInfo).then((doc) => {
			res.json({
				status_code: 200,
				message: '修改使用者成功',
			})
		}).catch((err) => {
			res.json({
				status_code: 400,
				message: '内部錯誤,修改使用者資訊失敗',
			})
		})
	})
})

//删除使用者
router.get('/deleteuser', (req, res) => {
	let userName = req.query.userName;
	User.findOneAndDelete({
		userName
	}).then((doc) => {
		res.json({
			status_code: 200,
			message: '删除使用者成功',
		})
	}).catch((err) => {
		res.json({
			status_code: 400,
			message: '内部錯誤,删除使用者失敗',
		})
	})
})

/**************************************** 權限管理 *******************************************/

//擷取管理者清單
router.get('/adminlist', async (req, res) => {
	let result;
	if (req.query.adminName) {
		result = await Administrator.find({
			adminName: {
				$regex: req.query.adminName,
				$options: 'gi'
			}
		});
	} else {
		result = await Administrator.find({});
	}
	res.json({
		status_code: 200,
		message: '擷取管理者清單成功',
		total: result.length,
		administrators: result
	})
})

//添加管理者
router.post('/addadmin', (req, res) => {
	let regFrom = req.body;
	console.log(regFrom)
	let adminInfo = {
		adminName: regFrom.adminName,
		password: md5(md5(regFrom.adminPsw) + S_KEY), //加密密碼
		role: regFrom.adminRole
	}
	Administrator.create(adminInfo, (err, doc) => {
		console.log(err, doc)
		if (!err) {
			res.json({
				status_code: 200,
				message: '添加管理者成功',
			})
		} else {
			res.json({
				status_code: 400,
				message: '内部錯誤,添加管理者失敗',
			})
		}
	})
})

//檢查管理者名是否已注冊
router.get('/checkname', async (req, res) => {
	let adminName = req.query.adminName;
	let isNameReg = await Administrator.findOne({
		adminName
	})
	if (isNameReg) {
		res.json({
			status_code: 400,
			message: '該名稱已注冊'
		})
	} else {
		res.json({
			status_code: 200,
			message: '該名稱可以使用'
		})
	}
})

//編輯管理者
router.post('/editadmin', async (req, res) => {
	let regFrom = req.body;
	console.log(regFrom);
	let adminInfo = {
		adminName: regFrom.adminName,
		role: regFrom.adminRole
	}
	if (regFrom.adminPsw) {
		adminInfo.password = md5(md5(regFrom.adminPsw) + S_KEY); //加密密碼
	}
	Administrator.updateOne({
		adminName: regFrom.adminName
	}, adminInfo).then((doc) => {
		res.json({
			status_code: 200,
			message: '修改管理者資訊成功',
		})
	}).catch((err) => {
		res.json({
			status_code: 400,
			message: '内部錯誤,修改管理者資訊失敗',
		})
	})
})

//删除管理者
router.get('/deleteadmin', (req, res) => {
	let adminName = req.query.adminName;
	Administrator.findOneAndDelete({
		adminName
	}).then((doc) => {
		res.json({
			status_code: 200,
			message: '删除管理者成功',
		})
	}).catch((err) => {
		res.json({
			status_code: 400,
			message: '内部錯誤,删除管理者失敗',
		})
	})
})

/**************************************** 商品管理 *******************************************/

//擷取分類清單
router.get('/catelist', async (req, res) => {
	let result;
	if (req.query.cateId) {
		result = await Category.find({
			cateId: req.query.cateId
		}).sort('cateId');
	} else {
		result = await Category.find({}).sort('cateId');
	}
	res.json({
		status_code: 200,
		message: '擷取分類清單成功',
		total: result.length,
		categories: result
	})
})

//檢查分類ID是否已存在
router.get('/checkcateid', async (req, res) => {
	let cateId = req.query.cateId;
	let isIdReg = await Category.findOne({
		cateId
	})
	if (isIdReg) {
		res.json({
			status_code: 400,
			message: '此ID已被使用'
		})
	} else {
		res.json({
			status_code: 200,
			message: '此ID可以使用'
		})
	}
})

//檢查分類名稱是否已存在
router.get('/checkcatename', async (req, res) => {
	let cateName = req.query.cateName;
	let isIdReg = await Category.findOne({
		cateName
	})
	if (isIdReg) {
		res.json({
			status_code: 400,
			message: '此名稱已被使用'
		})
	} else {
		res.json({
			status_code: 200,
			message: '此名稱可以使用'
		})
	}
})

//添加分類
router.post('/addcate', (req, res) => {
	let regFrom = req.body;
	console.log(regFrom)
	let cateInfo = {
		cateId: regFrom.cateId,
		cateName: regFrom.cateName,
		cateCounts: 0,
		cateSales: 0
	}
	Category.create(cateInfo, (err, doc) => {
		console.log(err, doc)
		if (!err) {
			res.json({
				status_code: 200,
				message: '添加分類成功',
			})
		} else {
			res.json({
				status_code: 400,
				message: '内部錯誤,添加分類失敗',
			})
		}
	})
})

//編輯分類
router.post('/editcate', async (req, res) => {
	let editFrom = req.body;
	Category.updateOne({cateId: editFrom.cateId}, editFrom).then((doc) => {
		res.json({status_code: 200,message: '修改分類資訊成功',})
	}).catch((err) => {
		res.json({status_code: 400,message: '内部錯誤,修改分類資訊失敗',})
	})
})

//删除分類
router.get('/deletecate', (req, res) => {
	let cateId = req.query.cateId;
	Category.findOneAndDelete({
		cateId
	}).then(async (doc) => {
		//删除商品下評論
		let result = await Goods.find({
			goodsCategory: cateId
		})
		console.log('result', result)
		for (let i = 0; i < result.length; i++) {
			await Comment.deleteMany({
				goodsId: result[i].goodsId
			})
		}
		//删除分類下所有商品
		await Goods.deleteMany({
			goodsCategory: cateId
		})
		res.json({
			status_code: 200,
			message: '删除分類成功',
		})
	}).catch((err) => {
		res.json({
			status_code: 400,
			message: '内部錯誤,删除分類失敗',
		})
	})
})

//擷取商品清單
router.get('/goodslist', async (req, res) => {
	let result;
	if (req.query.goodsCategory) {
		if (req.query.goodsId) {
			let resultId = await Goods.find({
				goodsId: req.query.goodsId,
				goodsCategory: req.query.goodsCategory
			}).sort('goodsCategory');
			let resultName = await Goods.find({
				goodsName: {
					$regex: req.query.goodsId,
					$options: 'gi'
				},
				goodsCategory: req.query.goodsCategory
			}).sort('goodsCategory');
			if (resultId.length != 0) {
				result = resultId
			} else {
				result = resultName
			}
		} else {
			result = await Goods.find({
				goodsCategory: req.query.goodsCategory
			}).sort('goodsCategory');
		}
	} else {
		if (req.query.goodsId) {
			let resultId = await Goods.find({
				goodsId: req.query.goodsId
			}).sort('goodsCategory');
			let resultName = await Goods.find({
				goodsName: {
					$regex: req.query.goodsId,
					$options: 'gi'
				}
			}).sort('goodsCategory');
			if (resultId.length != 0) {
				result = resultId
			} else {
				result = resultName
			}
		} else {
			result = await Goods.find({}).sort('goodsCategory');
		}
	}
	res.json({
		status_code: 200,
		message: '擷取分類清單成功',
		total: result.length,
		goods: result
	})
})

//擷取商品的分類
router.get('/goodscate', async (req, res) => {
	let result = await Category.findOne({cateId: req.query.cateId});
	res.json({
		status_code: 200,
		message: '擷取分類資訊成功',
		goodsCate: result.cateName
	})
})

//檢查商品ID是否已存在
router.get('/checkgoodsid', async (req, res) => {
	let goodsId = req.query.goodsId;
	let isIdReg = await Goods.findOne({
		goodsId
	})
	console.log(isIdReg)
	if (isIdReg) {
		res.json({
			status_code: 400,
			message: '此ID已被使用'
		})
	} else {
		res.json({
			status_code: 200,
			message: '此ID可以使用'
		})
	}
})

//添加商品
router.post('/addgoods', (req, res) => {
	const form = new formidable.IncomingForm();
	form.uploadDir = config.uploadsGoodsPath; // 上傳圖檔放置的檔案夾
	form.keepExtensions = true; // 保持檔案的原始擴充名
	form.parse(req, (err, fields, files) => {
		let goodsInfo = {
			goodsId: fields.goodsId,
			shortName: fields.shortName,
			goodsName: fields.goodsName,
			goodsPrice: fields.goodsPrice,
			normalPrice: fields.normalPrice,
			salesTips: fields.salesTips,
			goodsCategory: fields.goodsCategory,
			goodsCounts: Number(fields.goodsCounts),
			goodsImg: 'http://localhost:' + config.port + '/uploads/' + path.basename(files.goodsImg.path),
			goodsComments: 0
		}
		Goods.create(goodsInfo, async (err, doc) => {
			//更新商品分類裡的商品數量
			let result = await Goods.find({
				goodsCategory: fields.goodsCategory
			});
			Category.updateOne({
				cateId: fields.goodsCategory
			}, {
				cateCounts: result.length
			}).then(doc => console.log('doc', doc)).catch(err => console.log('err', err))

			if (!err) {
				res.json({
					status_code: 200,
					message: '添加商品成功',
				})
			} else {
				res.json({
					status_code: 400,
					message: '内部錯誤,添加商品失敗',
				})
			}
		})
	})
})

//編輯商品
router.post('/editgoods', (req, res) => {
	const form = new formidable.IncomingForm();
	form.uploadDir = config.uploadsGoodsPath; // 上傳圖檔放置的檔案夾
	form.keepExtensions = true; // 保持檔案的原始擴充名
	form.parse(req, (err, fields, files) => {
		console.log(fields, files)
		let goodsInfo = {
			goodsId: fields.goodsId,
			shortName: fields.shortName,
			goodsName: fields.goodsName,
			goodsPrice: fields.goodsPrice,
			normalPrice: fields.normalPrice,
			salesTips: fields.salesTips,
			goodsCategory: fields.goodsCategory,
			goodsCounts: Number(fields.goodsCounts),
		}
		if (files.goodsImg) {
			goodsInfo.userAvatar = 'http://localhost:' + config.port + '/uploads/' + path.basename(files.goodsImg.path);
		}
		Goods.updateOne({
			goodsId: fields.goodsId
		}, goodsInfo).then(async (doc) => {
			//更新編輯前商品分類裡的商品數量
			let resultOld = await Goods.find({
				goodsCategory: fields.goodsOldCate
			});
			Category.updateOne({
				cateId: fields.goodsOldCate
			}, {
				cateCounts: resultOld.length
			}).then(doc => console.log('doc', doc)).catch(err => console.log('err', err));
			//更新編輯後商品分類裡的商品數量
			let result = await Goods.find({
				goodsCategory: fields.goodsCategory
			});
			Category.updateOne({
				cateId: fields.goodsCategory
			}, {
				cateCounts: result.length
			}).then(doc => console.log('doc', doc)).catch(err => console.log('err', err));
			res.json({
				status_code: 200,
				message: '修改商品成功',
			})
		}).catch((err) => {
			console.log(err)
			res.json({
				status_code: 400,
				message: '内部錯誤,修改商品資訊失敗',
			})
		})
	})
})

//删除商品
router.get('/deletegoods', (req, res) => {
	let goodsId = req.query.goodsId;
	let goodsCategory = req.query.goodsCategory;
	Goods.findOneAndDelete({
		goodsId
	}).then(async (doc) => {
		//删除該商品下所有評論
		Comment.deleteMany({
			goodsId
		}).then(doc => console.log(doc))
		//更新删除後商品分類裡的商品數量
		let result = await Goods.find({
			goodsCategory
		});
		Category.updateOne({
			cateId: goodsCategory
		}, {
			cateCounts: result.length
		}).then(doc => console.log('doc', doc)).catch(err => console.log('err', err));
		res.json({
			status_code: 200,
			message: '删除商品成功',
		})
	}).catch((err) => {
		res.json({
			status_code: 400,
			message: '内部錯誤,删除商品失敗',
		})
	})
})

/**************************************** 訂單管理 *******************************************/

//擷取訂單清單
router.get('/orderlist', async (req, res) => {
	let result;
	if (req.query.userName) {
		let resultId = [];
		if (req.query.userName.length == 24) {
			resultId = await Order.find({
				_id: mongoose.Types.ObjectId(req.query.userName)
			}).sort('-orderTime');
		}
		let resultName = await Order.find({
			userName: {
				$regex: req.query.userName,
				$options: 'gi'
			}
		}).sort('-orderTime');
		if (resultId.length != 0) {
			result = resultId
		} else {
			result = resultName
		}
	} else {
		result = await Order.find({}).sort('-orderTime');
	}
	res.json({
		status_code: 200,
		message: '擷取訂單清單成功',
		total: result.length,
		orders: result
	})
})

//編輯訂單資訊
router.post('/editorder', async (req, res) => {
	let editFrom = req.body;
	console.log(editFrom);
	Order.updateOne({
		_id: mongoose.Types.ObjectId(editFrom._id)
	}, editFrom).then((doc) => {
		res.json({
			status_code: 200,
			message: '修改訂單資訊成功',
		})
	}).catch((err) => {
		console.log(err)
		res.json({
			status_code: 400,
			message: '内部錯誤,修改訂單資訊失敗',
		})
	})
})

//删除訂單
router.get('/deleteorder', (req, res) => {
	Order.findOneAndDelete({
		_id: mongoose.Types.ObjectId(req.query._id)
	}).then((doc) => {
		res.json({
			status_code: 200,
			message: '删除訂單成功',
		})
	}).catch((err) => {
		res.json({
			status_code: 400,
			message: '内部錯誤,删除訂單失敗',
		})
	})
})

/**************************************** 資料統計 *******************************************/

//擷取資料統計資料
router.get('/datalist', async (req, res) => {
	let result = await Category.find({}).sort('cateId');
	let xAxisData =[];
	let seriesData = [];
	for (let i = 0; i < result.length; i++) {
		xAxisData.push(result[i].cateName);
		seriesData.push(result[i].cateSales);
	}
	let option = {
		title: {
			text: '各分類月銷量'
		},
		tooltip: {},
		legend: {
			data: ['銷量']
		},
		xAxis: {
			data: xAxisData
		},
		yAxis: {},
		series: [{
			name: '銷量',
			type: 'bar',
			data: seriesData
		}]
	};
	console.log(xAxisData,seriesData,option)
	res.json({
		status_code: 200,
		message: '擷取資料統計資訊成功',
		option: option
	})
})


export default router;


---

# 源碼
https://pan.baidu.com/s/1ADfDdHbOYui8vwOTzwCbUA?pwd=8767 

           

繼續閱讀