当前开发的是一个电商全栈项目,技术选型:
Vue(框架) + Vue-Router(路由) + Vuex(用于本地的缓存处理,全局状态管理) + axios(请求) + Vant(组件库)
Vue(框架) + Vue-Router(路由) + Vuex(用于本地的缓存处理,全局状态管理) + axios(请求) ElementUI(组件库)
Node + Express + mongoose(链接数据库模块) + cors(解决跨域) + jwt(登录)
注意:后台管理系统 与 APP 需要分开创建,因为在 `main.js` 中同时引入 element-ui 和 vant 组件库容易冲突。
第一步:创建项目并安装依赖:
创建项目命令:
vue create admin
( 使用 vue create 命令创建项目,项目名为 admin)注意:创建项目时,后台管理系统选择history模式,选择y【 Use history mode for router? (Requires proper server setup for index fallback in production) (Y/n)】
进入项目文件夹 :
cd admin
安装axios请求:
cnpm i axios --save
安装组件库:
cnpm i element-ui --save
安装Vuex 数据持久化:
cnpm i vuex-persistedstate --save
指令汇总(除创建项目外(需手动选择项),可全部复制,交给cmd 自动一步一步安装,最后一项需回车,或者复制上回车):vue create admin
cd admin
cnpm i axios --save
cnpm i element-ui --save
cnpm i vuex-persistedstate --save
第二步:精简项目(项目文件夹保留文件)
- public 静态资源目录
- src
- http 封装axios请求
- components 封装公共组件
- router 路由配置目录
- store 状态管理目录
- views 封装视图组件
- App.vue 根组件
- main.js 入口文件
- package.json
第三步:在 main.js
中引入组件库
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
第四步:启动项目(端口 8080):
npm run serve
cmd返回上一级:
cd ..
第一步:创建项目并安装依赖:
创建项目命令:
vue create app
( 使用 vue create 命令创建项目,项目名为 app)注意:创建项目时,app系统选择hash模式(地址带个中#),选择n【 Use history mode for router? (Requires proper server setup for index fallback in production) (Y/n)】
进入项目文件夹 :
cd app
安装axios请求:
cnpm i axios --save
安装组件库:
cnpm i vant --save
安装Vuex 数据持久化:
cnpm i vuex-persistedstate --save
指令汇总(除创建项目外(需手动选择项),可全部复制,交给cmd 自动一步一步安装,最后一项需回车,或者复制上回车):vue create app
cd app
cnpm i axios --save
cnpm i vant --save
cnpm i vuex-persistedstate --save
第二步:精简项目(项目文件夹保留文件)
- public 静态资源目录
- src
- http 封装axios请求
- components 封装公共组件
- router 路由配置目录
- store 状态管理目录
- views 封装视图组件
- App.vue 根组件
- main.js 入口文件
- package.json
第三步:在 main.js
中引入组件库
import Vant from 'vant'
import 'vant/lib/index.css'
Vue.use(Vant)
第四步:启动项目(端口 8080):
npm run serve
cmd返回上一级:
cd ..
第一步:创建项目并安装依赖:
先检查是否安装Express,查看版本号(安装了显示版本号,提示没有内部外部命令就是没有安装,需要进行下一步安装):
express --version
全局安装Express项目生成器(只需要安装一次,类似于脚手架工具):
cnpm i express express-generator -g
使用 express 命令创建项目,项目名为 server:
express server
进入项目文件:
cd server
初始化依赖(因为当前建完项目没有任何依赖):
cnpm i
链接数据库模块:
cnpm i mongoose --save
解决跨域:
cnpm i cors --save
全局安装 nodemon 热启动:
cnpm i nodemon -g
指令汇总(除创建项目外(需手动选择项),可全部复制,交给cmd 自动一步一步安装,最后一项需回车,或者复制上回车):
express --version
cnpm i express express-generator -g
express server
cd server
cnpm i
cnpm i mongoose --save
cnpm i cors --save
cnpm i nodemon -g
第二步:精简项目
- public 静态资源目录
- db 用于管理数据连接的目录
- models 用于管理数据模块对象的目录
- crud 用于管理增删改查封装的目录
- routes 用于管理路由的目录
- views 视图模板引擎管理目录(可删除)
- app.js 入口文件
- package.json
第三步:配置跨域请求
在 app.js
入口文件中引入 cors
模块
var express = require('express');
var cors = require('cors'); // 引入 cors
//var app = express();
app.use(cors())
// 将 cors 模块注册到中间件中,必须在路由跳转之前配置
//app.use('/',indexRouter) ;
//app.use(',users',usersRouter) ;
第四步:配置 nodemon
启动
在 pageage.json
文件中配置 scripts
命令:
"scripts": {
"start": "nodemon ./bin/www"
}
第五步:启动项目(端口 3000):
npm start
server文件中创建文件搭建目录
↓ server
→ db //用于链接数据库
→ index.js
→ models //模块 用于创建数据模型
→ crud // 用于增删改查 缩写
→ index.js
第一步:在 db/index.js
中封装连接数据库的函数:
//引入mongoose
//下载地址~官网 : https://www.mongodb.com/
// 前端教程网:https://web1024.cn/tool
var mongoose = require('mongoose')
/**
* 声明一个函数,用于连接数据库的函数
*/
function dbConnect(){
// mongoose 是异步 返回一个 promise 对象
// mongodb 协议链接数据库在哪台机器上,本机:localhost:27017 ;指定链接库的名字:eshop2
mongoose.connect('mongodb://localhost:27017/eshop2',{
//如果数据库中没有这个集合 将会自动创建
useNewUrlParser: true,
useUnifiedTopology: true
//调用 方法接收连接成功之后
}).then(()=>{
console.log('数据库连接成功')
}).catch(err=>{
console.error('数据库连接失败', err)
})
}
//函数抛出
module.exports = dbConnect
第二步:在 app.js
入口文件中调用数据库连接方法:
//引入 db
var dbConnect = require('./db');
//调用方法
dbConnect();//连接数据库
第三步:启动服务
npm start
服务启动成功后,查看cmd 控制台是否输出了 “数据库连接成功” 的内容。
在 models
目录下创建模型对象文件,
例如:我们要设计一个商品分类的模块,就创建 models/classify.js
文件,示例代码如下:
//引入
var mongoose = require('mongoose')
/**
* 创建商品分类的模型对象
*/
let schema = new mongoose.Schema({ // schema 用于定义和数据库中字段相同的属性名称和数据类型
name: String //分类的名称name 属性 值是String类型
})
//Classify就是把数据库转换成js后拿到的一个对象,将来做增删改查操作
let Classify = mongoose.model('classifys', schema)
//抛出
module.exports = Classify
例如:我们要设计一个商品的模块,就创建 models/goods.js
文件,示例代码如下:
var mongoose = require('mongoose')
/**
* 创建商品的模型对象
*/
let schema = new mongoose.Schema({ // schema 用于定义和数据库中字段相同的属性名称和数据类型
title: String, //商晶标题
price: Number, //商品价格
guige: Array, //商品规格
content: String, //商品详情
state: {
type: Number, //Number类型 可以多条件设置
default: 1 //商品状态,1为上架,2为下架
},
hot: {
type: Number,
default: 1 //是 否为热销商品,1为普通商品,2为热销商品
}
//等等。。。
})
let Goods = mongoose.model('goods', schema)
module.exports = Goods
如果再创建其他模块,参考此步骤。
此处以添加商品分类为例。
第一步:在 routes
目录下创建对应的路由文件,例如 classify.js
,示例代码如下:
//对应 3.6.1 接口规范
//没有调用封装的crud,就会每次都要写
var express = require('express');
var router = express.Router();
var Classify = require('../models/classify');
//添加商品分类 /classify/add
router.post('/add', function(req,res){
//接收参数
let {name} = req.body
//保存到数据库
Classify.create({name}).then(result=>{
if(result){
//添加成功后的响应
res.json({
code: 200, //自定义标识,不是状态码
msg: '添加成标识功'
})
}else{
res.json({
code: 300,
msg: '添加失败'
})
}
}).catch(err=>{
res.json({
code: 400,
msg: '添加时出现异常'
})
})
})
//修改分类
router.post('/update', function(req,res){
let C = req.body
if(!c._id){
res.json({
code:300,
msg:'id参数不能为空!'
})
return
}
crud.update(Classify,{_id:c._id}, {name: c.name,no: c.no},res )
})
//删除分类
router.get('/de1' , function(req,res){
let {_id} = req.query
if(!_id){
res.json({
code:300,
msg:'id参数不能为空!'
})
return
}
crud.del(Classify,{_id},res)
})
//分页查询
router.get('/find', function(req,res){
//let {page,pagesize,kw,s} = req.query
//let where = {}
//if(kw){
// where = {name: {$regex: kw}}
//}
//let sort = {}
//if(s == 1){
// sort = {no: -1}
//}else if(s == 2){
// sort = {no: 1}
//}
//crud-find(classify,page, pegeSize,where,sart ,res)
let {page,pagesize,sort = 1} = req.query //sort 排序 1降序 2升序,有值的话按值,没值的话按默认值
//s为排序的条件对象
let s = {}
if(sort == 1){
s = {no: -1}
}else if(sort == 2){
s = {no: 1}
}
crud.find(Classify,page, pegeSize,{},s ,res)
})
//非分页查询
router.get('/query', function(req,res){
let {sort = 1} = req.query //sort 排序 1降序 2升序,有值的话按值,没值的话按默认值
//s为排序的条件对象
let s = {}
if(sort == 1){
s = {no: -1}
}else if(sort == 2){
s = {no: 1}
}
crud.query(Classify,{},s ,res)
})
module.exports = router;
第二步:
在 app.js
入口文件引入路由,示例代码如下:
//引入路由文件
var classifyRouter = require('./routes/classify');
//配置一个路由
app.use('/classify', classifyRouter);
# 请求的路由地址
http://localhost:3000/classify/add
# 请求参数
{
"name": "男装"
}
# 添加成功的响应结果
{
code: 200,
msg: '添加成功'
}
公共方法,写一遍不用动直接就可以用
在 crud/index.js
中封装增删改查的方法,示例代码如下:
添加的功能方法:
/**
* 用于添加数据的公共方法(文档注释 可以一键生成API文档 ,两个*加@ 是竹节)【服务端才有】
* @param {*} model 数据模型对象
* @param {*} params 要添加的数据对象
* @param {*} res 响应对象
*/
function add(model,params,res){
model.create(params).then(result=>{
if(result){
//添加成功后的响应
res.json({
code: 200,
msg: '添加成功'
})
}else{
res.json({
code: 300,
msg: '添加失败'
})
}
}).catch(err=>{
res.json({
code: 400,
msg: '添加时出现异常'
})
})
}
修改的公共方法:
/**
* 用于修改的公共方法
* @param {*} model 数据模型对象
* @param {*} where 要修改的条件
* @param {*} params 修改后的新对象
* @param {*} res 响应对象
*/
function update(model,where,params,res){
// 修改的时候传入两个条件(修改的条件,修改的值) 返回一个result
model.updateOne(where,params).then(result=>{
//result 里面放的是修改结果的对象
//result里面有个对象 n ,n>0 证明修改成功了很多条,n是几就是几条
//else 就是修改失败
//catch 就是修改时出现异常
if(result.n > 0){
res.json({
code: 200,
msg: '修改成功'
})
}else{
res.json({
code: 300,
msg: '修改失败'
})
}
}).catch(err=>{
res.json({
code: 400,
msg: '修改时出现异常'
})
})
}
删除的公共方法:
/**
* 删除的公共方法
* @param {*} model 数据模型对象
* @param {*} where 要删除的条件
* @param {*} res 响应对象
*/
function del(model,where,res){
model.findOneAndDelete(where).then(result=>{
if(result){
//添加成功后的响应
res.json({
code: 200,
msg: '删除成功'
})
}else{
res.json({
code: 300,
msg: '删除失败'
})
}
}).catch(err=>{
res.json({
code: 400,
msg: '删除时出现异常'
})
})
}
分页查询公共方法:(与上面不分页查询按需要选其一即可)
/**
* 用于分页查询的公共方法
* @param {*} model 模型对象
* @param {*} page 当前页码
* @param {*} pageSize 每页条数
* @param {*} where 查询条件
* @param {*} sort 排序条件
* @param {*} res 响应对象
*/
async function find(model,page,pageSize,where,sort,res){
//判断page是否存在
if(!page){
page = 1
}else{
page = parseInt(page)
if(isNaN(page)){ //非数字
page = 1
}else{ //是数字
if(page < 1){
page = 1
}
}
}
//判断pageSize是否为空
if(!pageSize){
pageSize = 10
}else{
//默认每页10条,如果进行赋值,每页最低每5条换页,最多不超过30条换页
pageSize = parseInt(pageSize)
if(isNaN(pageSize)){ //非数字
pageSize = 10
}else{ //是数字
if(pageSize < 5){
pageSize = 5
}else if(pageSize > 30){
pageSize = 30
}meyiye
}
}
//计算总页数,总页数 = Math.ceil(总记录数 ÷ 每页条数)
let count = 0
await model.find(where).countDocuments().then(result=>{
count = result
})
// await model.find(where).count().then(result=>{
// count = result
// })
//如果上一步还没执行完,就执行下一步,就会出错,所以要把异步变同步,所以要在上一步 和 执行查询操作 前面加上 await
//总页数 totalPage
let totalPage = Math.ceil(count/pageSize)
//判断当前页码是否大于总页数
//如果一条都没有的话,count为0 所以totalPage也会为0(0/每页条数 还为0)
if(totalPage > 0 && page > totalPage){
page = totalPage
}
//skip查询的起始位置,起始位置 = (当前页码 - 1)× 每页条数
let start = (page - 1)*pageSize
//执行查询操作
//跳过多少条 skip从哪里开始看 limit看多少条
await model.find(where).sort(sort).skip(start).limit(pageSize).then(result=>{
if(result && result.length > 0){
res.json({
code: 200,
msg: '查询成功',
data: result,
page,
pageSize,
count,
totalPage
})
}else{
res.json({
code: 300,
msg: '没有查询到数据',
data: [],
page,
pageSize,
count,
totalPage
})
}
}).catch(err=>{
res.json({
code: 400,
msg: '查询时出现异常'
})
})
}
非分页查询公共方法:(与下面分页查询按需要选其一即可)
/**
* 用于分页查询的公共方法
* @param {*} model 模型对象
* @param {*} where 查询条件
* @param {*} sort 排序条件
* @param {*} res 响应对象
*/
function query(model,where,sort,res){
model.query(where).sort(sort).then(result=>{
if(result && result.length > 0){
res.json({
code: 200,
msg: '查询成功',
data: result
})
}else{
res.json({
code: 300,
msg: '没有查询到数据',
data: []
})
}
}).catch(err=>{
res.json({
code: 400,
msg: '查询时出现异常'
})
})
}
需要在 crud/index.js
文件中抛出以上函数:
module.exports = {
add, //添加
update, //修改
del, //删除
find, //分页查询
query //非分页查询
}
实现一个用户有关的模块 (模型对象,路由在app中的引用,封装好的,写完不用再改,唯一修改的就是,有新的功能写一个新的二级路由)
第一步:创建模型、在models
文件下创建一个users.js
模块
我们要设计一个用户模块,就创建 models/users.js
文件,示例代码如下:
(与其他模块不一样的地方,需要改的就是schema里面的属性;集合的名称 users 改成对应的以及抛出对象的名称)
//引入
var mongoose = require('mongoose')
/**
* 创建用户的模型对象
*/
let schema = new mongoose.Schema({ // schema 用于定义和数据库中字段相同的属性名称和数据类型
username: String , //用户的名称
pwd: String //用户密码
})
// users 将来数据库中叫的名字 最后一个字母必须s
let Users= mongoose.model('users', schema)
//抛出
module.exports = Users
第二步:创建路由、
在routes
文件下创建一个users.js
文件
//通过 express 导入一个路由
var express = require('express');
var router = express.Router();
//抛出一个路由
module.exports = router;
在 app.js
入口文件引入路由,示例代码如下:
//引入路由文件
var usersRouter = require('./routes/users');
//配置一级路由
app.use('/users', usersRouter );//确定有没有引入成功,可以按住 Ctrl 鼠标放在 usersRouter 上呈现小手状,点击直接跳转到路由界面,能定位到,说明引入成功
第三步:功能接口,在routes/users.js
中(如果其他模块直接改掉 Users 对应部分)
//var express = require('express'); 这是第一步的内容保留,这里只是为了展示写入位置
//var router = express.Router(); 这是第一步的内容保留,这里只是为了展示写入位置
//保存到数据库里面,导入Users
var Users = require('../models/users');
//存储数据库的方法全在 crud 里封装着
var crud = require('../crud');
//与crud里面对应
//添加用户
//通过 post 或 get , /users 后面 /add 找到这个方法
//服务端路由,就是通过 url地址与一个 函数 之间的 映射
router.post('/add', function(req,res){
//接收参数 只要是post请求 就用body封装
let {username,pwd} = req.body
//调用自己封装的方法 .add( 放现在操作的模型,添加的数据就是{username=username 直接写username, pwd=pwd直接写pwd },res响应)
crud.add(Users,{username,pwd},res) //可以按住 Ctrl 鼠标放在 add 上呈现小手状,点击直接跳转查看封装思维
//或者写成
//let user = req.body
//crud.add(Users,user,res)
})
//修改用户
router.post('/update', function(req,res){
//接收参数 只要是post请求 就用body
//user 整个对象
let user = req.body
//数组里只有ID是唯一修改的条件
crud.update(Users,{_id:user._id},{
username:user.username,
pwd:user.pwd
},res)
})
//删除用户
router.get('/del',function(req ,res){
let {_id} = req.query
crud.del(Users,{_id},res)
})
//分页查询
router.get('/find' , function(req,res){
let {page,pageSize} = req.query
//目前没有 查询条件, 排序 不需要 所以{}
crud.find(Users,page,pageSize,{},{},res)
})
//module.exports = router; 这是第一步的内容保留,这里只是为了展示写入位置
全局配置:
# 服务器IP与端口(根据实际更改)
baseURL: http://localhost:3000
添加分类:
接口地址(路由,发请求):/classify/add
请求方法:POST
返回数据格式:JSON
请求参数:
参数名称 | 参数类型 | 是否必填 | 参数描述 |
---|---|---|---|
name | String | 是 | 分类的名称 |
no | Number | 否,默认值0 | 分类的排序 |
响应参数:
参数名称 | 参数类型 | 参数示例 | 参数描述 |
---|---|---|---|
code | Number | 200 | 自定义,请求的结果状态,200为成功,300为失败,400为服务端异常 |
msg | String | “添加成功” | 请求的结果描述 |
修改分类:
接口地址(路由,发请求):/classify/update
请求方法:POST
返回数据格式:JSON
请求参数:
参数名称 | 参数类型 | 是否必填 | 参数描述 |
---|---|---|---|
_id | String | 是 | 要修改的分类id |
name | String | 否 | 分类的新名称 |
no | Number | 否,默认值0 | 分类的新排序 |
响应参数:
参数名称 | 参数类型 | 参数示例 | 参数描述 |
---|---|---|---|
code | Number | 200 | 自定义,请求的结果状态,200为成功,300为失败,400为服务端异常 |
msg | String | “修改成功” | 请求的结果描述 |
删除分类:
接口地址(路由,发请求):/classify/del
请求方法:GET
返回数据格式:JSON
请求参数:
参数名称 | 参数类型 | 是否必填 | 参数描述 |
---|---|---|---|
_id | String | 是 | 分类的id |
响应参数:
参数名称 | 参数类型 | 参数示例 | 参数描述 |
---|---|---|---|
code | Number | 200 | 自定义,请求的结果状态,200为成功,300为失败,400为服务端异常 |
msg | String | “删除成功” | 请求的结果描述 |
分页查询分类:
接口地址:/classify/find
请求方法:GET
返回数据格式:JSON
请求参数:
参数名称 | 参数类型 | 是否必填 | 参数描述 |
---|---|---|---|
page | Number | 否,默认值1 | 当前页码 |
pageSize | Number | 否,默认值10 | 每页查询条数,最少5条,最多30条 |
sort | Number | 否,默认值1 | 按no字段的排序规则,1为降序,2为升序 |
响应参数:
参数名称 | 参数类型 | 参数示例 | 参数描述 |
---|---|---|---|
code | Number | 200 | 请求的结果状态,200为成功,300为失败,400为服务端异常 |
msg | String | “查询成功” | 请求的结果描述 |
data | any | [{name:’’,no:’’},{}] | 请求成功返回的数据 |
page | Number | 1 | 当前访问的页码 |
pageSize | Number | 10 | 每页返回条数 |
count | Number | 2000 | 总记录数 |
totalPage | Number | 50 | 总页数 |
非分页查询所有分类:
接口地址:/classify/query
请求方法:GET
返回数据格式:JSON
请求参数:
参数名称 | 参数类型 | 是否必填 | 参数描述 |
---|---|---|---|
sort | Number | 否,默认值1 | 按no字段的排序规则,1为降序,2为升序 |
响应参数:
参数名称 | 参数类型 | 参数示例 | 参数描述 |
---|---|---|---|
code | Number | 200 | 请求的结果状态,200为成功,300为失败,400为服务端异常 |
msg | String | “查询成功” | 请求的结果描述 |
data | any | [{name:’’,no:’’},{}] | 请求成功返回的数据 |
同上
同上
在 router/index.js
中设计路由
import Vue from 'vue'
import VueRouter from 'vue-router'
import routes from './routes' //将路由的模块进行封装
Vue.use(VueRouter)
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
router/routes.js
文件代码示例:
//路由对象
const routes = [
{
path: '/',
component: ()=>import('@/views/Main'),
redirect: '/home', //默认到home
children: [
{
path: '/home', //控制台 数据统计
component: ()=>import('@/views/Home')
},
{
path: '/classify', //分类管理
component: ()=>import('@/views/Classify')
},
{
path: '/goods/add', //发布商品
component: ()=>import('@/views/Goods/add.vue')
},
{
path: '/goods/list/:state', //当前的状态,1上架,2下架
component: ()=>import('@/views/Goods/list.vue')
}
]
}
]
export default routes
封装全局的前置守卫,router/beforeEach.js
文件代码示例:
import router from './index'
/**
* 路由的前置守卫
*/
export default ()=>{
router.beforeEach((to,from,next)=>{
console.log('beforeEach...')
next()
})
}
全局守卫封装好之后,需要在 main.js
入口文件调用守卫方法:
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import beforeEach from './router/beforeEach' //导入全局守卫模块
Vue.use(ElementUI);
Vue.config.productionTip = false
beforeEach() //调用守卫方法
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
创建 src/http/index.js
文件,代码示例如下:
var axios = require('axios')
//创建axios实例
var instance = axios.create({
baseURL: 'http://localhost:3000'
})
//请求拦截
instance.interceptors.request.use(config=>{
// console.log('请求拦截...',config)
return config
},err=>{
console.error('请求时异常', err)
return
})
//响应拦截
instance.interceptors.response.use(res=>{
//请求成功对响应数据做处理
// console.log('响应拦截', res)
return res //该返回对象会传到请求方法的响应对象中
},err=>{
// 响应错误处理
console.error('响应时异常', err)
return
})
/**
* 用于发送HTTP请求的方法
* @param {*} option 发送请求的配置项
* @returns 响应结果
*/
async function http({path,method,params}){
let result
//get、delete
if(method == 'get' || method == 'delete'){
await instance[method](path,{
params
}).then(res=>{
result = res.data
}).catch(err=>{
result = err
})
}else if(method == 'post' || method == 'put' || method == 'patch'){
await instance[method](path,params).then(res=>{
result = res.data
}).catch(err=>{
result = err
})
}
return result
}
export default http
在 main.js
文件中引入 http
模块:
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import http from './http' //引入 http 模块
Vue.prototype.$http = http //将http函数挂载到Vue的实例上
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
在组件中使用 http
模块:
安装相关依赖
cnpm i multer --save
创建 routes/upload.js
路由文件,示例代码如下:
var express = require('express');
var router = express.Router();
var multer = require('multer');
var fs = require('fs');
var path = require('path');
//使用表单上传
var upload = multer({
storage: multer.diskStorage({
//设置文件存储位置
destination: function(req, file, cb) {
let date = new Date();
let year = date.getFullYear();
let month = (date.getMonth() + 1).toString().padStart(2, '0');
let day = date.getDate();
let dir = "./public/img/" + year + month + day;
//判断目录是否存在,没有则创建
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, {
recursive: true
});
}
//dir就是上传文件存放的目录
cb(null, dir);
},
//设置文件名称
filename: function(req, file, cb) {
let fileName = file.fieldname + '-' + Date.now() + path.extname(file.originalname);
//fileName就是上传文件的文件名
cb(null, fileName);
}
})
})
//文件上传的路由
router.post('/img', upload.single("mainPic"), function(req,res){
let file = req.file
let path = file.path.replace('public',"")
// console.log(path)
res.json({
file: path
})
} )
module.exports = router;
在 app.js
入口文件中引入路由
var uploadRouter = require('./routes/upload');
app.use('/upload', uploadRouter);
服务端上传接口地址: http://localhost:3000/update/img
前端以 elementui
为例。
使用
上传组件,示例代码如下:
上传
以 wangEditor
为例。
安装依赖
cnpm i wangeditor --save
在组件中引入
设置高度
// 设置编辑区域高度为 500px
editor.config.height = 500
设置菜单
// 默认情况下,显示所有菜单
editor.config.menus = [
'head',
'bold',
'fontSize',
'fontName',
'italic',
'underline',
'strikeThrough',
'indent',
'lineHeight',
'foreColor',
'backColor',
'link',
'list',
'todo',
'justify',
'quote',
'emoticon',
'image',
'video',
'table',
'code',
'splitLine',
'undo',
'redo',
]
配置上传图片
//配置服务器地址
this.editor.config.uploadImgServer = this.serverIP+"/upload/editor/img"
//配置文件上传的字段名
this.editor.config.uploadFileName = 'img'
//服务端返回的数据格式,非常重要!!!
res.json({
errno: 0,
data: [
{
url: "", //访问图片的地址
alt: "",
href: ""
}
]
})
配置上传图片后的自定义插入
//图片上传的钩子函数
this.editor.config.uploadImgHooks = {
//图片上传成功并返回结果时执行,可以手动插入图片
customInsert: (insertImgFn,result) => {
console.log(result.file)
//插入图片的函数,参数为要插入的图片地址(切记:要有服务端的IP!)
insertImgFn(result.file)
}
}
安装依赖
cnpm i echarts --save
创建图表组件,例如创建 src/components/EchartsAxis.vue
组件,示例代码如下:
API说明:
属性名 | 数据类型 | 默认值 | 描述 |
---|---|---|---|
width | String | 600px | 图表区域的宽度,单位px |
height | String | 400px | 图表区域的高度,单位px |
type | String | line | 图表的样式,支持line/bar |
smooth | Boolean | false | 当type属性为line时,该项有效,true为平滑线,false为折线 |
title | String | - | 当前图表的标题 |
data | Object | - | 必填,格式为 {key: Value} |
align | String | auto | 标题的位置,支持left/center/right/auto |