首页 > 编程语言 >基于Vue+Nodejs实现医药商城销售系统

基于Vue+Nodejs实现医药商城销售系统

时间:2024-06-20 15:27:41浏览次数:24  
标签:Vue Nodejs res req let xColumnName toRes id 商城

作者简介:Java领域优质创作者、CSDN博客专家 、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、腾讯课堂常驻讲师

主要内容:Java项目、Python项目、前端项目、人工智能与大数据、简历模板、学习资料、面试题库、技术互助

收藏点赞不迷路  关注作者有好处

文末获取源码 

项目编号:BS-QD-013

一,环境介绍

数据库:Mysql: mysql5.7

应用服务器:Nodejs14.15

开发工具:IDEA或VSCODE

技术:Vue+Nodejs

二,项目简介

随着科学技术的飞速发展,各行各业都在努力与现代互联网技术接轨,特别是网上购物更是生活中不可缺少的一部分。现在网络购物发展迅猛,各行业都想通过互联网售卖自己的产品;对于药品在网络售卖当然也不能排除在外,随着网络技术的不断成熟,带动了药店药品网上销售的份额同时店下也在同时销售,由于之前国家对药品的监管力度比较大,在网上售卖难度比较大,随着互联网+的发展,国家也在对药品在网上售卖大力支持,也有对药品合理的监控下药品网络渠道也在快速发展。对于以上分析便决定了要开发一套基于NodeJS技术和Vue框架的医药商城系统。

医药销售平台具有医药商城信息管理功能的选择。流行性传染病医药销售平台采用NodeJS技术,基于MySQL数据库技术开发,实现了首页、个人中心、用户管理、医药信息管理、类型管理、系统管理、订单管理等内容进行管理,本系统具有良好的兼容性和适应性,为用户提供更多的医药信息,也提供了良好的平台,从而提高系统的核心竞争力。

2.1 功能说明

流行性传染病医药销售平台是两种身份的用户,主要涉及管理员和用户。每个身份都是操作起来都是清楚方便的。对于一些医药商城,必须是已经进行注册登录的用户,或者想修改医药商城信息的话,也是需要用户为登录状态。这些用户的基本信息都由管理员对其统一管理。

根据医药商城实际过程的分析,网站有以下几个部分,其中用户注册,发布个人信息,修改个人信息;用户注册登录,发布医药信息;管理员管理用户信息;一般用户只可以浏览不可以发布信息。以上业务过程从用户角度可以分为两类使用本系统的用户角色,包括管理员和用户。以下针对各类用户说明相应的业务过程。

管理员功能描述:

个人中心:管理员可以在此修改自己的密码和个人用户名信息,以确保账户的安全性。

用户管理:管理员可以管理商城中的用户,包括添加、删除和修改用户信息。

药品信息管理:管理员可以对药品的信息进行管理,包括药品的名称、种类、描述、价格等。

类型管理:管理员可以管理药品的类型,如处方药、非处方药、保健品等。

系统管理:管理员可以对系统进行设置主要包括轮播图和公告信息的管理。

订单管理:管理员可以查看和管理用户的订单信息,包括订单的状态、金额、收货人等。

用户功能描述:

首页:用户进入系统后,可以看到首页展示的药品信息和公告信息以用户轮播图展示。

药品信息:用户可以查看所有药品的信息,包括名称、种类、描述、价格等,以便选择适合自己的药品。

公告信息:用户可以查看商城的公告信息,了解商城的重要通知和更新。

个人中心:用户可以在个人中心查看和修改自己的个人信息,如地址、电话、查看订单信息等。

购物车:用户可以将自己喜欢的药品加入购物车,以便进行结算和支付

2.2 数据库逻辑设计

概念是数据库设计的首要步骤,强调业务需求的抽象表示,是一种概念性的模型,其组成要素包括实体、属性及联系。

医药商城系统的实体及属性如下(主键由下划线标识,外键由波浪线标识):

(1)购物车(购物车主键、创建时间、药品表名、用户id、药品id、药品名称、图片)

(2)地址(地址id、创建时间、用户id、地址、收货人、电话、是否默认、址[是/否])

(3)用户(用户id、主键、创建时间、账号、密码、姓名、性别、邮箱、手机号码、相片、余额)

(4)公告(公告id、公告名称、公告图片、公告类型、公告发布时间、公告详情、创建时间)

(5)管理员表(管理员id、用户名、密码、角色、新增时间)

(6)医药信息(医药信息id、创建时间、医药名称、医药封面、类型、品牌、厂商、医药简介、医药详情、发布日期、最近点击时间、点击次数、价格)

(7)收藏(收藏id、创建时间、用户id、收藏id、表名、收藏名称、收藏图片、类型(1:收藏,21:赞,22:踩)、推荐类型)

(8)订单(订单id、创建时间、订单编号、药品表名、用户id、药品id、药品名称、药品图片、购买数量、价格/积分、折扣价格、总价格/总积、、折扣总价格、支付类型、状态、地址、电话、收货人、物流)

(9)公告(公告id、创建时间、标题、简介、图片、内容)

(10)类型(类型id、创建时间、类型)

(11)医药评价(医药评价id、创建时间、关联表id、用户id、用户名、评、内容、回复内容)

三,系统展示

3.1 前端用户功能

登录与注册

系统首页

药品信息

个人中心

3.2 后台管理功能

用户管理

药品信息管理

药品类型管理

订单管理

系统管理

四,核心代码展示

import { version } from '../../package.json'
import { Router } from 'express'
import { Sequelize, Op, QueryTypes } from 'sequelize'
import sequelize from '../models/sequelize'
import toRes from '../lib/toRes'
import CartModel from '../models/CartModel'
import md5 from 'md5-node'
import util from '../lib/util'
import jwt from 'jsonwebtoken'
import moment from 'moment'

export default ({ config, db }) => {
	let api = Router()


	// 分页接口(后端)
	api.get('/page', async (req, res) => {

		try {

			let page = parseInt(req.query.page) || 1
			let limit = parseInt(req.query.limit) || 10
			let sort = req.query.sort || 'id'
			let order = req.query.order || 'asc'

			let where = {}
            if (jwt.decode(req.headers.token).role != '管理员') {
				where.userid = {
					[Op.eq]: req.session.userinfo === undefined ? jwt.decode(req.headers.token).id : req.session.userinfo.id
				}
            }

			let result = await CartModel.findAndCountAll({
				order: [[sort, order]],
				where,
				offset: (page - 1) * limit,
				limit
			})
			
			result.currPage = page
			result.pageSize = limit

			toRes.page(res, 0, result)
		} catch(err) {

			toRes.session(res, 500, '服务器错误!', '', 500)
		}
	})

    // 分页接口(前端)
	api.get('/list', async (req, res) => {

		try {

			let page = parseInt(req.query.page) || 1
			let limit = parseInt(req.query.limit) || 10
			let sort = req.query.sort || 'id'
			let order = req.query.order || 'asc'

			let where = {}
			let userid = req.query.userid
			let goodid = req.query.goodid
			if (userid) {
				where.userid = {
					[Op.eq]: userid
				}
			}
			if (goodid) {
				where.goodid = {
					[Op.eq]: goodid
				}
			}

			let result = await CartModel.findAndCountAll({
				order: [[sort, order]],
				where,
				offset: (page - 1) * limit,
				limit
			})
			
			result.currPage = page
			result.pageSize = limit

			toRes.page(res, 0, result)
		} catch(err) {
			
			toRes.session(res, 401, '您的权限不够!', '', 200)
		}
	})


	// 保存接口(后端)
	api.post('/save', async (req, res) => {

		try {

			Object.keys(req.body).forEach(item=>{
				if(req.body[item] == '')  delete req.body[item]
			})

			if (!req.body.userid) {
				req.body.userid = req.session.userinfo === undefined ? jwt.decode(req.headers.token).id : req.session.userinfo.id
			}

			const userinfo = await CartModel.create(req.body)

			if (userinfo === null) {

				toRes.session(res, -1, '添加失败!')
			} else {

				toRes.session(res, 0, '添加成功!')
			}
		} catch(err) {
			
			toRes.session(res, 500, '服务器错误!', '', 500)
		}
	})

    // 保存接口(前端)
	api.post('/add', async (req, res) => {

		try {

			Object.keys(req.body).forEach(item=>{
				if(req.body[item] == '')  delete req.body[item]
			})

			req.body.userid = req.session.userinfo === undefined ? jwt.decode(req.headers.token).id : req.session.userinfo.id

			const userinfo = await CartModel.create(req.body)

			if (userinfo === null) {

				toRes.session(res, -1, '添加失败!')
			} else {

				toRes.session(res, 0, '添加成功!')
			}
		} catch(err) {
			
			toRes.session(res, 500, '服务器错误!', '', 500)
		}
	})

	// 更新接口
	api.post('/update', async (req, res) => {

		try {

			await CartModel.update(req.body, {
				where: {
				  id: req.body.id
				}
			})

			toRes.session(res, 0, '编辑成功!')
		} catch(err) {
			
			toRes.session(res, 500, '服务器错误!', '', 500)
		}
	})

	// 删除接口
	api.post('/delete', async (req, res) => {

		try {

			await CartModel.destroy({
				where: {
				  id: {
					[Op.in]: req.body
				  }
				}
			})

			toRes.session(res, 0, '删除成功!')
		} catch(err) {

			toRes.session(res, 500, '服务器错误!', '', 500)
		}
	})

	// 详情接口(后端)
	api.all('/info/:id', async (req, res) => {

		try {


			toRes.record(res, 0, await CartModel.findOne({ where: { id: req.params.id } }))
		} catch(err) {

			toRes.session(res, 500, '服务器错误!', '', 500)
		}
	})

    // 详情接口(前端)
	api.all('/detail/:id', async (req, res) => {

		try {


			toRes.record(res, 0, await CartModel.findOne({ where: { id: req.params.id } }))
		} catch(err) {

			toRes.session(res, 500, '服务器错误!', '', 500)
		}
	})

	// 获取需要提醒的记录数接口
	api.get('/remind/:columnName/:type', async (req, res) => {

		try {

			let sql = 'SELECT 0 AS count'
			
			if (req.params.type == 1) {
				if (req.query.remindstart) sql = "SELECT COUNT(*) AS count FROM cart WHERE " + req.params.columnName + " >= '" + req.query.remindstart + "'"
				if (req.query.remindend) sql = "SELECT COUNT(*) AS count FROM cart WHERE " + req.params.columnName + " <= '" + req.query.remindend + "'"

				if (req.query.remindstart && req.query.remindend) {
					sql = "SELECT COUNT(*) AS count FROM cart WHERE " + req.params.columnName + " >= '" + req.query.remindstart + "' AND " + req.params.columnName + " <= '" + req.query.remindend + "'"
				}
			}

			if (req.params.type == 2) {
				if (req.query.remindstart) {
					let remindStart = util.getDateTimeFormat(0 - req.query.remindstart, "yyyy-MM-dd")
					sql = "SELECT COUNT(*) AS count FROM cart WHERE " + req.params.columnName + " >= '" + remindStart + "'"
				}
				if (req.query.remindend) {
					let remindEnd = util.getDateTimeFormat(req.query.remindend, "yyyy-MM-dd")
					sql = "SELECT COUNT(*) AS count FROM cart WHERE " + req.params.columnName + " <= '" + remindEnd + "'"
				}

				if (req.query.remindstart && req.query.remindend) {
					let remindStart = util.getDateTimeFormat(0 - req.query.remindstart, "yyyy-MM-dd")
					let remindEnd = util.getDateTimeFormat(req.query.remindend, "yyyy-MM-dd")
					sql = "SELECT COUNT(*) AS count FROM cart WHERE " + req.params.columnName + " >= '" + remindStart + "' AND " + req.params.columnName + " <= '" + remindEnd + "'"
				}
			}

			const results = await sequelize.query(sql, {
				plain: true,
				raw: true,
				type: QueryTypes.SELECT
			})

			toRes.count(res, 0, results.count)
		} catch(err) {
			
			toRes.session(res, 500, '服务器错误!', '', 500)
		}
	})










	api.get('/group/:columnName', async (req, res) => {

		try {

			let sql = ""
			let columnName = req.params.columnName
			let tableName = "cart"
			let where = " WHERE 1 = 1 "
			sql = "SELECT COUNT(*) AS total, " + columnName + " FROM " + tableName + where + " GROUP BY " + columnName
			toRes.record(res, 0, await sequelize.query(sql, {
				plain: false,
				raw: true,
				type: QueryTypes.SELECT
			}))
		} catch(err) {

			toRes.session(res, 500, '服务器错误!', '', 500)
		}
	})

	api.get('/value/:xColumnName/:yColumnName', async (req, res) => {

		try {

			let sql = ""
			let xColumnName = req.params.xColumnName
			let yColumnName = req.params.yColumnName
			let tableName = "cart"
			let where = " WHERE 1 = 1 "
			if ("cart" == "orders") {
				where += " AND status IN ('已支付', '已发货', '已完成') ";
			}

			sql = "SELECT " + xColumnName + ", SUM(" + yColumnName + ") AS total FROM " + tableName + where + " GROUP BY " + xColumnName + " DESC"
			
			toRes.record(res, 0, await sequelize.query(sql, {
				plain: false,
				raw: true,
				type: QueryTypes.SELECT
			}))
		} catch(err) {

			toRes.session(res, 500, '服务器错误!', '', 500)
		}
	})

	api.get('/value/:xColumnName/:yColumnName/:timeStatType', async (req, res) => {

		try {
			
			let sql = ""
			let xColumnName = req.params.xColumnName
			let yColumnName = req.params.yColumnName
			let timeStatType = req.params.timeStatType
			let tableName = "cart"
			let where = " WHERE 1 = 1 "
			if ("cart" == "orders") {
				where += " AND status IN ('已支付', '已发货', '已完成') ";
			}

            if (config.dbConnection.dbtype.toLowerCase() == "mysql") {
                if (timeStatType == "日")
                    sql = "SELECT DATE_FORMAT(" + xColumnName + ", '%Y-%m-%d') " + xColumnName + ", sum(" + yColumnName + ") total FROM " + tableName + where + " GROUP BY DATE_FORMAT(" + xColumnName + ", '%Y-%m-%d')";
                if (timeStatType == "月")
                    sql = "SELECT DATE_FORMAT(" + xColumnName + ", '%Y-%m') " + xColumnName + ", sum(" + yColumnName + ") total FROM " + tableName + where + " GROUP BY DATE_FORMAT(" + xColumnName + ", '%Y-%m')";
                if (timeStatType == "年")
                    sql = "SELECT DATE_FORMAT(" + xColumnName + ", '%Y') " + xColumnName + ", sum(" + yColumnName + ") total FROM " + tableName + where + " GROUP BY DATE_FORMAT(" + xColumnName + ", '%Y')";
            } else {
                if (timeStatType == "日")
                    sql = "SELECT DATE_FORMAT(VARCHAR(10)," + xColumnName + ", 120) " + xColumnName + ", sum(" + yColumnName + ") total FROM " + tableName + where + " GROUP BY DATE_FORMAT(VARCHAR(10)," + xColumnName + ", 120)";
                if (timeStatType == "月")
                    sql = "SELECT DATE_FORMAT(VARCHAR(7)," + xColumnName + ", 120) " + xColumnName + ", sum(" + yColumnName + ") total FROM " + tableName + where + " GROUP BY DATE_FORMAT(VARCHAR(7)," + xColumnName + ", 120)";
                if (timeStatType == "年")
                    sql = "SELECT DATE_FORMAT(VARCHAR(4)," + xColumnName + ", 120) " + xColumnName + ", sum(" + yColumnName + ") total FROM " + tableName + where + " GROUP BY DATE_FORMAT(VARCHAR(4)," + xColumnName + ", 120)";
            }
			toRes.record(res, 0, await sequelize.query(sql, {
				plain: false,
				raw: true,
				type: QueryTypes.SELECT
			}))
		} catch(err) {

			toRes.session(res, 500, '服务器错误!', '', 500)
		}
	})


	return api
}

五,相关作品展示

基于Java开发、Python开发、PHP开发、C#开发等相关语言开发的实战项目

基于Nodejs、Vue等前端技术开发的前端实战项目

基于微信小程序和安卓APP应用开发的相关作品

基于51单片机等嵌入式物联网开发应用

基于各类算法实现的AI智能应用

基于大数据实现的各类数据管理和推荐系统

 

 

标签:Vue,Nodejs,res,req,let,xColumnName,toRes,id,商城
From: https://blog.csdn.net/BS009/article/details/139730616

相关文章

  • Vue 3 + Element Plus实现PC和移动端兼容的技术探讨
    在现代Web开发中,实现PC端和移动端的兼容性已经成为一个必备的技能。Vue3作为一款流行的前端框架,结合ElementPlus这个优秀的UI组件库,为我们提供了丰富的工具和解决方案。在本文中,我们将探讨如何使用Vue3和ElementPlus来实现PC和移动端的兼容性,并结合vh、vw等单位实现响应......
  • uniapp vue3 虚拟下拉滚动
    下面是vue3的写法  如果想查看vue2的写法  请移步至github链接   https://github.com/Arvin-Cui/vue-virtual-scroll/blob/master/pages/index/index.vue1.index.vue  index.vue页面中加一个共用组件VirtualList.vue<template> <view>  <VirtualList:lis......
  • 学生个人html静态网页制作 基于HTML+CSS+JavaScript+jquery仿苏宁易购官网商城模板
    ......
  • Vue - 使用 transition 过渡动画、Animate.css 库动画
     一.transitiontransition标签包裹的内容会有一个过渡的动画效果使用transition过渡组件需要满足的条件:条件渲染(v-if)条件展示(v-show)动态组件可以使用 name 属性给 transition 标签起名字class选择器名字和 name 属性有关系,这里 name 属性名为 fade,则cla......
  • 基于fastapi+vue登记系统
    1.创建fastapi项目2.创建vue项目npmcreatevue@latestcdwebnpminstallnpminstallelement-plus修改main.js注册elementui和routerimport'./assets/main.css'importAppfrom'./App.vue'import{createApp}from'vue'importrouterfrom......
  • Vue 中 v-for 的全方位解读:含案例与 key 属性运用及常用数组方法
    目录v-for介绍v-forkey属性的使用Vue数组方法v-for介绍        v-for能够对数字、数组以及对象进行遍历。值得注意的是,当v-for与v-if一同运用时,v-for的优先级要高于v-if。正因如此,应尽量避免将v-if和v-for共同使用。特别是在嵌套使用的情况下,每一......
  • Vue生态工具组合
    文章目录1.Vue版本2.构建工具3.包管理器4.状态管理5.http库6.UI库7.站点生成器8.优质内容收录vue生态工具多种多样,我们要如何选择并组合起来才最好呢。接下来给大家推荐我认为比较好的工具组合方式,方便大家在搭建vue项目时可做一个参考。1.Vue版本新项目推荐优先选......
  • Java计算机毕业设计+Vue实习实训管理系统(开题报告+源码+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景在当今社会,实习实训已成为高等教育中不可或缺的一部分,对于学生实践能力和职业素养的提升具有重要意义。然而,传统的实习实训管理方式存在着诸多不便,如......
  • 防抖ref如何在vue中被定义
    本文由ChatMoney团队出品为什么ref要实现防抖在vue的开发过程中,我们通常会使用到ref,但在我们需要对一个频繁的赋值操作做防抖操作时,我们通常只能通过编写一个独立的防抖函数来实现,这样相对会多一些步骤(麻烦一些)。例如我们给一个即时搜索框的input实现防抖输入(即在输入文本n秒......
  • 在vue中定义一个防抖ref
    本文由ChatMoney团队出品为什么ref要实现防抖在vue的开发过程中,我们通常会使用到ref,但在我们需要对一个频繁的赋值操作做防抖操作时,我们通常只能通过编写一个独立的防抖函数来实现,这样相对会多一些步骤(麻烦一些)。例如我们给一个即时搜索框的input实现防抖输入(即在输入文本n秒......