# vue_shop **Repository Path**: l1470362551/vue-shop ## Basic Information - **Project Name**: vue_shop - **Description**: 使用vue构建后台管理系统 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 7 - **Forks**: 0 - **Created**: 2021-04-07 - **Last Updated**: 2021-09-14 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 电商后台管理系统(前端项目) [预览](https://www.hejiu.ren:442/login) ### 大家有问题尽量在这里提: https://gitee.com/l1470362551/vue-shop/issues #### 超级管理员 用户名:admin 密码:123456 #### 普通用户 用户名:test123 密码:123456 #### 其他角色 用户名:【linken,asdf1,asdf123】 密码:123456 ### 项目在本地运行的步骤如下 1. 安装node.js,[下载地址](https://nodejs.org/zh-cn/download/),如果已经安装则无需安装 2. 下载npm淘宝镜像: `npm install -g cnpm --registry=https://registry.npm.taobao.org` 3. 使用cnpm 下载vue-cli: `cnpm install -g vue-cli` 4. cd 到当前项目的根目录,即vue-shop目录,打开CMD命令行 5. 下载该项目的node_modules: `cnpm install` 6. 启动项目:`npm run serve` 7. 启动Mock服务器提供模拟API:`npm run mock` 8. 本地运行不需要后端服务器,因为Mock服务器充当了后端服务器角色 ### 一些目录和文件的说明 1. mock目录存放了使用mock.js模拟的数据,数据的格式由后端的接口文档来确定,由于是前后端分离,所以只能通过模拟数据来调试页面,后端的API接口可能没有开发完成 2. router目录用于设置前端的API服务器的路由,通过路由获取前端API服务器的数据 3. server.js是用于设置前端的API服务器,前端API的服务器是通过node的express快速搭建的 4. 通过 `npm run mock ` 就可以启动前端API服务器 ## 电商后台管理系统(前端项目) [预览](https://www.hejiu.ren:442/login) ### 后端API接口源码 [下载](https://gitee.com/l1470362551/vue_server_api/repository/archive/master.zip). [接口API](./电商管理后台%20API%20接口文档.md) ### 功能 > 用于管理用户账号,商品分类,商品信息,订单,数据统计等业务功能 ![](https://gitee.com/wBekvam/vue-shop-admin/raw/master/image/mall_desc01.png) ### 开发模式 > 电商后台管理系统整体采用前后端分离的开发模式,其中前端项目是基于Vue技术栈的SPA项目,后端项目是基于Java技术栈API接口项目 ![](https://gitee.com/wBekvam/vue-shop-admin/raw/master/image/mall_desc02.png) ### 技术选型 #### 前端项目技术栈 - Vue - Vue-router - Element-UI - Axios - Echarts - Nginx #### 后端项目技术栈 - Java - SpringBoot - Spring - SpringMVC - Mybatis - JWT - Shiro - Mysql - Redis ##### [接口API](./电商管理后台%20API%20接口文档.md). 后端源码 [下载](https://gitee.com/l1470362551/vue_server_api.git). ### 项目初始化 #### 前端项目初始化步骤 1. 安装 Vue 脚手架 2. 通过 Vue-Cli 创建项目 3. 配置 Vue-router 4. 配置 Element-UI 组件库 5. 配置 Axios 库 6. 初始化 git 远程仓库 ##### 相关依赖-按需导入 ![](https://gitee.com/wBekvam/vue-shop-admin/raw/master/image/mall_desc03.png) #### 后端项目的环境安装配置 1. 阿里云购买服务器,服务器配置如下,由于后端提供数据量不是很大,所以带宽不需要很大。 | CPU | 内存 | 操作系统 | 带宽 | | :--: | :---: | :-------------: | :---: | | 2核 | 4 GiB | CentOS 7.4 64位 | 1Mbps | 2. 安装MySQL数据库,并配置相关信息 3. 通过在数据库中执行`source vue_api.sql`命令来导入数据 4. 安装Redis数据库 5. 安装Jdk1.9 6. 通过 `java -jar jar包` 运行项目 7. 使用Postman测试后台项目接口是否正常 8. 购买域名,[API接口](https://www.gaborder.top:442) 9. 为域名配置SSL证书 10. 给API配置HTTPS ![image-20210514153300216](https://gitee.com/l1470362551/typora_imgs/raw/master/imgs/image-20210514153300216.png) 11. 在Centos7中通过nohub工具让后端项目在服务器上以后端形式启动,不影响后续的操作 `nohup java -jar /home/vue_api/vue_api_server-0.0.1-SNAPSHOT.jar > consoleMsg.log 2>&1 &` ### 登录概述 #### 登录业务流程 1. 在登录页面输入用户名和密码 2. 调用后台接口进行验证 3. 通过验证之后,根据后台的响应状态跳转到项目主页 #### 登录业务相关技术点 1. http是无状态的 2. 通过cookie在客户端记录状态 3. 通过sesion在服务器端记录状态 4. 通过token维持状态(不允许跨域使用) ![](https://gitee.com/wBekvam/vue-shop-admin/raw/master/image/mall_desc04.png) #### 登录业务流程 ##### 登录页面的布局 通过Element-UI组件实现布局 - el-form - el-form-item - el-input - el-button - 字体图标 ##### 创建git分支 ``` // 创建并切换登录分支 git checkout -b login // login分支合并到主分支 // 1.切换到master分支 git checkout master // 2.合并分支到master git merge login // 将本地login子分支推送到github git push -u origin login ``` ##### 路由导航守卫控制访问权限 > 如果用户没有登录,但是直接通过URL访问特定页面,需要重新导航到登录页面 ```js //为路由对象,添加beforeEach导航守卫 router.beforeEach((to,from,next) => { //如果用户访问的登录页,直接放行 if (to.path === 'login') return next() //从sessionStorage中获取到保存的token值 const tokenStr = window.sessionStorage.getItem('token') //如果么有token,强制跳转到登录页 if(!tokenStr) return next('/login') next() }) ``` ### 退出 #### 退出功能实现原理 > 基于token的方式实现退出比较简单,只需要销毁本地的token即可。这样,后续的请求就不会携带token,必须重新登录生成一个新的token之后才可以访问页面。 ```javascript logout() { window.sessionStorage.clear(); this.$router.push('/login'); this.$message.success('退出成功'); } ``` ### 主页布局 #### 通过接口获取菜单数据 > 通过axios请求拦截器添加token,保证拥有获取数据的权限 ```js // axios请求拦截 axios.interceptors.request.use(config => { // 为请求头对象,添加token验证的Authorization字段 config.headers.Authorization = window.sessionStorage.getItem('token') return config }) ``` ### 用户管理 #### 用户管理概述 > 通过用户管理模块对用户进行控制 #### 用户列表概述 > 查看所有用户,对用户的角色和身份信息进行CRUD操作 ![image-20210514160040283](https://gitee.com/l1470362551/typora_imgs/raw/master/imgs/image-20210514160040283.png) ### 权限管理 #### 权限管理概述 > 通过权限管理模块控制不同的用户可以进行哪些操作,具体可以通过角色的方式进行控制,即每个用户分配一个特定的角色,角色包括不同的功能权限 ![image-20210514155213583](https://gitee.com/l1470362551/typora_imgs/raw/master/imgs/image-20210514155537118.png) #### 角色列表 > 查看所有角色对应的所有权限,对角色进行权限的分配,可以删除和编辑角色 ![image-20210514155537118](https://gitee.com/l1470362551/typora_imgs/raw/master/imgs/image-20210514155213583.png) #### 权限列表 > 查看系统的所有权限和权限的等级 ![image-20210514155724212](https://gitee.com/l1470362551/typora_imgs/raw/master/imgs/image-20210514155028547.png) ### 订单管理 #### 订单管理概述 > 订单管理用于对用户的订单进行管理,可以查看或修改订单的编号,价格,是否付款,是否发货等信息 #### 订单列表 > 订单列表对用户订单进行一系列的CRUD操作 ![image-20210514155028547](https://gitee.com/l1470362551/typora_imgs/raw/master/imgs/image-20210514155724212.png) ### 参数管理 #### 参数管理概述 > 商品参数用于显示商品的特征信息,可以通过电商平台详情页面直观的看到 #### 商品列表 > 商品列表用于显示所有商品信息 ![image-20210514154312271](https://gitee.com/l1470362551/typora_imgs/raw/master/imgs/image-20210514154312271.png) #### 分类参数 > 分类参数用于对商品动态参数和静态属性进行一系列的CRUD ![image-20210514154435126](https://gitee.com/l1470362551/typora_imgs/raw/master/imgs/image-20210514154435126.png) #### 商品分类 > 商品分类用于对商品类别进行一系列的CRUD ![image-20210514154633878](https://gitee.com/l1470362551/typora_imgs/raw/master/imgs/image-20210514154633878.png) ### 数据统计 #### 数据统计概述 > 数据统计用于统计在不同地区的用户数量 #### 数据报表 > 数据报表以图表的形式用于展示用户的来源 ### 项目所用依赖(vue全家桶不描述) 1. 运行依赖 - axios => 发送请求 - echarts => 图表 - element-ui => element ui组件 - lodash => js工具库,该项目用到深拷贝与对象合并 - moment => 时间处理工具库 - nprogress => 进度条库 - v-viewer => 图片预览工具库 - vue-quill-editor => 富文本编辑器 - vue-table-with-tree-grid => 树形菜单/表格 2. 开发依赖 - babel => es6+语法转换 - eslint/babel-eslint => 语法检查 - less/less-loader => less语法 - babel-plugin-transform-remove-console => 移除console插件 ### 项目优化 ### 项目优化策略 - #### 生成Vue打包报告 - 通过命令行参数形式生成报告=>vue-cli-service build --report - 通过可视化ui面板直接查看报告(通过控制台和分析面板) ![image-20210514170913095](https://gitee.com/l1470362551/typora_imgs/raw/master/imgs/image-20210514170929889.png) ![image-20210514170929889](https://gitee.com/l1470362551/typora_imgs/raw/master/imgs/image-20210514170913095.png) ![image-20210514171013217](https://gitee.com/l1470362551/typora_imgs/raw/master/imgs/image-20210514171013217.png) - #### 通过vue.config.js修改webpack的默认配置 > 通过vue-cli 3.0工具生成的项目,默认隐藏了所有webpack的配置项,目的是为了屏蔽项目的配置过程,让开发人员把工作的 重心,放在具体功能和业务逻辑的实现上 - #### 为开发模式与发布模式指定不同的打包入口 > 默认情况下,vue项目的开发与发布模式,共用同一个打包的入口文件(即src/main.js),为了将项目的开发过程与发布过程分离,可以为两种模式,各自指定打包的入口文件,即: > > 1. 开发模式入口文件 src/main-dev.js > 2. 发布模式入口文件 src/main-prod.js > > 方案:configureWebpack(通过链式编程形式)和chainWebpack(通过操作对象形式) > > 在vue.config.js导出的配置文件中,新增configureWebpack或chainWebpack节点,来自定义webpack的打包配置 ```js // 代码示例 module.exports = { chainWebpack: config => { // 发布模式 config.when(process.env.NODE_ENV === 'production', config => { config.entry('app').clear().add('./src/main-prod.js') }) // 开发模式 config.when(process.env.NODE_ENV === 'development', config => { config.entry('app').clear().add('./src/main-dev.js') }) } } ``` - #### 第三方库启用CDN - ##### 通过externals加载外部cdn资源 > 默认情况下,通过import语法导入的第三方依赖包,最终会打包合并到同一个文件中,从而导致打包成功后,单文件体积过大的问题 => **chunk-vendors**体积过大 > > 为了解决上述问题,可以通过webpack的externals节点,来配置加载外部的cdn资源,凡是声明在externals中的第三方依赖包,都不会被打包 1. ###### 步骤1 ```js module.exports = { chainWebpack: config => { config.when(process.env.NODE_ENV === 'production', config => { config.entry('app').clear().add('./src/main-prod.js') // 在vue.config.js如下配置 config.set('externals', { vue: 'Vue', 'vue-router': 'VueRouter', axios: 'axios', lodash: '_', echarts: 'echarts', nporgress: 'NProgress', 'vue-quill-editor': 'VueQuillEditor' }) }) config.when(process.env.NODE_ENV === 'development', config => { config.entry('app').clear().add('./src/main-dev.js') }) } } ``` 2. ###### 步骤2 > 在public/index.html文件头部,将main-prod中的已经进行配置的import(样式表)删除替换为cdn引入 ```css ``` 3. ###### 步骤3 > 在public/index.html文件头部,将main-prod中的已经进行配置的import(js文件)删除替换为cdn引入 ```css ``` 4. ###### cdn加速前后对比( **chunk-vendors**打包文件) > Parsed大小 2.6m=> **596.9kB** - #### 使用cdn优化elementui打包 > 具体操作流程 > > 1. 在main-prod.js中,注释掉element-ui按需加载的代码 > 2. 在index.html头部区域中,通过cdn加载element-ui的js和css样式 > > `` > > `` - #### 首页内容定制 > 不同打包环境下,首页内容可能会有所不同,通过插件方式定制 - vue.config.js配置 ```js config.plugin('html').tap(args => { args[0].isProd = true或false return args }) ``` - index.html修改 ```html <%= htmlWebpackPlugin.options.isProd ? '' : 'dev-' %>vue-mall <% if(htmlWebpackPlugin.options.isProd) { %> css | js放在这儿 <% } %> ``` - #### Element-UI组件按需加载 ```js import Vue from 'vue' import { Button, Form, FormItem, Input, Message, Container, Header, Aside, Main, Menu, Submenu, MenuItemGroup, MenuItem, Breadcrumb, BreadcrumbItem, Card, Row, Col, Table, TableColumn, Switch, Tooltip, Pagination, Dialog, MessageBox, Tag, Tree, Select, Option, Cascader, Alert, Tabs, TabPane, Step, Steps, Checkbox, CheckboxGroup, Upload, Timeline, TimelineItem } from 'element-ui' ``` - #### 开启Gzip压缩 ![image-20210514161650717](https://gitee.com/l1470362551/typora_imgs/raw/master/imgs/image-20210514161650717.png) ```javascript plugins: [ new CompressionWebpackPlugin({ filename: "[path].gz[query]", algorithm: "gzip", test: new RegExp("\\.(" + productionGzipExtensions.join("|") + ")$"), threshold: 10240, //对10K以上的数据进行压缩 deleteOriginalAssets: false //是否删除源文件 }) ] ``` - #### 路由懒加载 > 在打包构建项目时,javascript包会变得特别大,影响页面加载,如果我们能把不同路由对应的组件分隔成不同的代码块,然后当路由被访问的时候才加载对应组件,这样更加高效 - 安装@babel/plugin-syntax-dynamic-import包 - 在babel.config.js配置文件声明该插件 - 将路由改为按需加载形式 ```js // 示例: const Foo = () => import(/* webpackChunkName: "group-foo" */ './Foo.vue') const Bar = () => import(/* webpackChunkName: "group-foo" */ './Bar.vue') const Baz = () => import(/* webpackChunkName: "group-foo" */ './Baz.vue') // import Login from '../components/Login.vue' const Login = () => import(/* webpackChunkName: "login_home_welcome" */ '../components/Login.vue') // import Home from '../components/Home.vue' const Home = () => import(/* webpackChunkName: "login_home_welcome" */ '../components/Home.vue') // import Welcome from '../components/Welcome.vue' const Welcome = () => import(/* webpackChunkName: "login_home_welcome" */ '../components/Welcome.vue') ... ``` 具体内容参考文章底部链接 ### 项目上线 #### 配置Nginx服务器 > 购买服务器,安装Nginx软件,将项目部署到Nginx服务器上,将vue打包生成的dist文件夹,托管为静态资源即可,关键代码如下,该项目使用了**Vue的History路由模式** ```nginx server { listen 81 ;#服务器监听端口 server_name www.kpxikxy.cn;#域名或ip地址 #charset koi8-r; #access_log logs/host.access.log main; #采用Vue的history路由模式 location / { root /home/apps/vue/dist;#dist目录 index index.html index.htm; try_files $uri $uri/ /index.html; } } ``` #### 开启服务器的Gzip配置 > 通过gzip减小文件体积,使传输速度更快 在服务器端使用Nginx做gzip压缩,配置如下 ```nginx gzip on; gzip_min_length 1000; gzip_buffers 4 8k; gzip_http_version 1.1; gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png application/vnd.ms-fontobject font/ttf font/opentype font/x-woff image/svg+xml; ``` #### 在阿里云配置服务器域名 ![image-20210514162936176](https://gitee.com/l1470362551/typora_imgs/raw/master/imgs/image-20210514162936176.png) #### 配置服务器SSL证书 ##### 下载SSL证书 ![image-20210514163059013](https://gitee.com/l1470362551/typora_imgs/raw/master/imgs/image-20210514163059013.png) ##### 给Nginx配置证书 ```nginx ssl_certificate /usr/local/nginx/cert/cert.pem;#从步骤一下载的证书 ssl_certificate_key /usr/local/nginx/cert/cert.key;#从步骤一下载的证书 ``` #### 开启SSL认证和Http2.0 ```nginx server { listen 442 ssl http2; server_name www.kpxikxy.cn; ssl_certificate /usr/local/nginx/cert/cert.pem; ssl_certificate_key /usr/local/nginx/cert/cert.key; ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; location / { root /home/apps/vue/dist; index index.html index.htm; try_files $uri $uri/ /index.html; } } ``` ##### 为什么要启用SSL服务 - 传统的http协议传输的数据都是明文,不安全 - 采用https协议对传输的数据进行了加密处理,可以防止数据被中间人窃取,使用更安全 申请ssl证书(https://freessl.org) => 正常企业还是使用收费ssh(http协议默认运行在80端口,https默认运行在443端口) ##### 为什么要启用HTTP2.0 - 采用二进制格式传输数据,http1.1使用文本格式。 - 对消息头采用hpack压缩,提升传输效率,而http1.1只是对消息体使用gzip压缩。 - 基于帧和流的多路复用,真正实现了基于一个链接的多请求并发处理 - 支持服务器推送。 #### 将http请求强制跳转到https ```nginx server { listen 81 ;#服务器监听端口 server_name www.kpxikxy.cn;#域名或ip地址 #charset koi8-r; #access_log logs/host.access.log main; return 302 https://$server_name$request_uri; } ``` --- ### 网站首页性能报告 > 通过Chrome的DevTools工具的Lighthouse生成网站的性能报告 ![image-20210514171830762](https://gitee.com/l1470362551/typora_imgs/raw/master/imgs/image-20210514172317009.png) ![image-20210514172317009](https://gitee.com/l1470362551/typora_imgs/raw/master/imgs/image-20210514171830762.png) ![image-20210514173319020](https://gitee.com/l1470362551/typora_imgs/raw/master/imgs/image-20210514172416685.png) ![image-20210514173332865](https://gitee.com/l1470362551/typora_imgs/raw/master/imgs/image-20210514173332865.png) ![image-20210514173403973](https://gitee.com/l1470362551/typora_imgs/raw/master/imgs/image-20210514173319020.png) ![image-20210514203406667](https://gitee.com/l1470362551/typora_imgs/raw/master/imgs/image-20210514173403973.png) ![image-20210514173452578](https://gitee.com/l1470362551/typora_imgs/raw/master/imgs/image-20210514173452578.png) ![image-20210514173239313](https://gitee.com/l1470362551/typora_imgs/raw/master/imgs/image-20210514173239313.png) **优化后** ![image-20210514172416685](https://gitee.com/l1470362551/typora_imgs/raw/master/imgs/image-20210514203406667.png) ![image-20210517161806695](https://gitee.com/l1470362551/typora_imgs/raw/master/imgs/image-20210517161806695.png) ### 配置文件大全 [接口API](./电商管理后台%20API%20接口文档.md) [vue.config.js配置](https://gitee.com/l1470362551/vue-shop/blob/master/vue.config.js) [路由懒加载](https://router.vuejs.org/zh/guide/advanced/lazy-loading.html) [babel配置](https://babeljs.io/docs/en/babel-plugin-syntax-dynamic-import/) [Nginx配置](./nginx.conf) ### Project preview ![image-20210514164400344](https://gitee.com/l1470362551/typora_imgs/raw/master/imgs/image-20210514164502177.png) ![image-20210514164502177](https://gitee.com/l1470362551/typora_imgs/raw/master/imgs/image-20210514164400344.png) ![user](https://gitee.com/wBekvam/vue-shop-admin/raw/master/image/user.png) ![user1](https://gitee.com/wBekvam/vue-shop-admin/raw/master/image/user1.png) ![role](https://gitee.com/wBekvam/vue-shop-admin/raw/master/image/role.png) ![auth](https://gitee.com/wBekvam/vue-shop-admin/raw/master/image/auth.png) ![goods](https://gitee.com/wBekvam/vue-shop-admin/raw/master/image/goods.png) ![params](https://gitee.com/wBekvam/vue-shop-admin/raw/master/image/params.png) ![addGoods](https://gitee.com/wBekvam/vue-shop-admin/raw/master/image/addGoods.png) ![addGoods1](https://gitee.com/wBekvam/vue-shop-admin/raw/master/image/addGoods1.png) ![image-20210514202231710](https://gitee.com/l1470362551/typora_imgs/raw/master/imgs/image-20210514211531759.png) ## 操作系统和软件和插件的版本信息 | 操作系统 | CentOS 7.6 | | :--------------: | :--------: | | CPU | 1核 | | 内存 | 2GB | | 磁盘 | 60GB | | 带宽 | 5Mbps | | Vue | 2.5.22 | | Vue-Router | 3.0.1 | | Nprogress | 0.2.0 | | axios | 0.18.0 | | element-ui | 2.6.3 | | lodash | 4.17.15 | | echarts | 4.1.0 | | quill | 1.3.4 | | vue-quill-editor | 3.0.4 | | Nginx | 1.16.0 |