SpringCloud电商项目开发完整流程

SpringCloud项目开发完整流程

一、新建前端Vue项目(管理后台)

先下载node.js
Node官网
然后win+r,输入cmd打开命令行窗口,输入命令node -v,检测node是否安装成功
在这里插入图片描述

全局安装cnpm (mac需要加上sudo),npm可以理解为前端的maven专门管理前端的js的,cnpm是国内的阿里的镜像库
npm install cnpm -g --registry=https://registry.npmmirror.com(后面地址可以省略)
在这里插入图片描述成功后使用cnpm install安装,版本为3.10.0的Vue
cnpm install -g @vue/cli@3.10.0
在这里插入图片描述
然后就可以在某个磁盘的文件下创建项目了,将文件目录切换到你要创建的文件夹下,输入vue create 文件名(不能有大写) 进行vue文件的创建
在这里插入图片描述
接着就进入了下面的界面中
在这里插入图片描述
不选第一个默认,选择下方的自选,自己选择这个项目包含着哪儿些包

在这里插入图片描述

接着选择Babel、Router(路由)、Vuex(状态管理也就是管理全局参数的)、CSS PRe-processors(CSS编辑器,CSS预处理)、Linter/Formatter(一般不选,这是格式化检查,选了会很自闭)
在这里插入图片描述
按回车,然后输入Y,把路由变成history模式
在这里插入图片描述
实际应用在这里插入图片描述
然后CSS预编译选择第三个Less,这个比较简单
在这里插入图片描述
实际应用
在这里插入图片描述
如果之前选了Linter/Formatter,这时候就要选第一个
在这里插入图片描述
还是第一个
在这里插入图片描述
接着出现问你,你更喜欢把这些配置放在哪儿?选那个都可以
在这里插入图片描述
最后问你是否将其保存为未来项目的预设?选择N
在这里插入图片描述
在项目构建完只后,cd 项目名,切换到你的项目中,然后添加element(UI框架)
在这里插入图片描述
是否全引入?选择第一个选项全引入
在这里插入图片描述
问你是否要加CSS预编译,因为之前已经选了Less预编译这里就输入N
在这里插入图片描述
语言选择中文
在这里插入图片描述
添加axios(vue版的ajax用于进行异步交互),vue add axios

在这里插入图片描述
到这里就结束了,接着就是打开HbulidX,然后左上角打开我们刚刚创建的项目目录
在这里插入图片描述
然后右键项目文件,使用命令行窗口打开所在目录,输入npm run serve即可运行前端项目(ctrl+c可以终止退出)
在这里插入图片描述
详解

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1、Vue的运行过程

Vue为单页开发,只有public下的一个index.html页面,主要显示也是显示在这儿,Vue运行时会加载public下的一个index.html页面和src下的main.js文件
在这里插入图片描述
将App对象通过"#"id选择器,加载到public下index.html中的div id="app"中
在这里插入图片描述
App.vue
为了在Vue这种单页开发的模式下实现多个页面的显示,就得用到路由,将其他页面的一部分或者整个页面做成一个组件,然后根据不同的地址显示不同的组件,需要通过"router-view"标签来实现,它的作用就是路由匹配到的组件将显示在这里
在这里插入图片描述

在这里插入图片描述

通过代码可以看到,我们把src/views/index.vue组件显示到了App.vue中router-view所在的位置,然后App.vue又被引入main.js中,最后在main.js中被加载到了public下的一个index.html的id为app的div中
在这里插入图片描述
品牌子页面BrandIndex
在这里插入图片描述
通过router的子路由
在这里插入图片描述
显示到了views下的index.vue中的右侧内容框内
在这里插入图片描述

2、axios异步请求(显示数据)

上面简述了为什么会显示这些页面,这些页面这么来的,接下来就说页面中的内容数据是怎么来的。

首先是template这个标签中必须只有一个子标签,所以先写一个div,至于div中有多少其他标签就不管了,其次是新建表格什么的,先把框架搭好
在这里插入图片描述
上面的图是完整实现后的,下方是研发中的,需要表格中显示数据
在这里插入图片描述
就得让表格中:tableData(要加:不然后面的" "就不是动态数据而是文本)有对应的数据,只是这数据还是死数据
在这里插入图片描述

要想动态的显示数据就需要拿到对应的后台数据,就得了解axios后异步请求了。

首先要了解一下怎么拿到axios中的数据,在axios.js中一个prototype自定义函数

//例如在axios中
Vue.prototype.aa=  abcd

那么就可以在其他的页面中通过this.aa()来调用

<script>
	// ./表示当前路径 这是静态的写法
	// import BreadEdit from './edit'
	export default {
		// 这是给组件取个名
		name:'BrandIndex',
		// created生命周期,和入口一样,一加载组件就要运行这个
		created(){
		// 调用下方的函数
			console.log(this.aa)
		}
	}
</script>

了解后,我们在axios中,自定义属性prototype

// 自定义属性prototype
Vue.prototype.axios = _axios

这样在brand页面中,再用this.axios.request()发起异步请求,拿到后台返回的数据再赋值给tableData即可。

.then(response =>{})是当你请求成功后你要那返回值response做什么?
在这里插入图片描述
当然这时候运行是肯定会报错的,报错的原因跨域拦截(不允许其他项目访问当前项目),就是你前端是80端口,但是访问的后端是8081端口,所以就报错
在这里插入图片描述
这时候就需要修改后端代码允许跨域请求,允许其他项目访问后台项目,定义一个过滤器即可,在product的config下新建一个ProductConfig类
在这里插入图片描述

于是我们就拿到了返回值,只是返回值刚好在data里面
在这里插入图片描述
我们把返回的数据的response.dat赋值给tableData,就可以动态显示数据了
在这里插入图片描述
在这里插入图片描述
可以在axios中配置baseURL
在这里插入图片描述
第一次修改
当然为了方便,我们可以把请求方法给封装一下,封装到axios中,url传入的地址,method传入的是get还是post方法,callback传入的函数(方法)
在这里插入图片描述
在这里要插入一个概念

//这里response因为是单个函数可以省略括号,如果没有参数必须得有括号
response => {
	this.tableDate = response.data
}
//上面的写法其实和匿名函数一样,也就是说和下面方法的是一样
//funcation表示函数,上面的写法是他的简写
function(response){
	this.tableDate = response.data
}
//既然如此那么封装的函数中的callback你也就可以看作
function(response){
	callback(response.data)
}

我们再修改brand中的代码
在这里插入图片描述
因为封装函数中是直接把response.data传入的,所以我们也就只要把response赋值给tableData即可

function(response){
	this.tableDate = response
}

第二次修改
将get,post固定下来
在这里插入图片描述
这样brand页面只需要this.get即可,同时把这个函数写成一个方法,让created直接调用更加整洁方便。
在这里插入图片描述
当然以上只有get请求的方法,没有post的,实际上post请求传入的参数更加麻烦所以要特地交代,如果是get请求传递数据就直接用params属性,如果是post请求传递数据则要用data属性 并且不能传json方法,需要传递的是formData对象,该对象需要自己创建,然后调用append方法,传两个参数一个是数据名,一个是数据值,然后一个一个依次传入formData对象,传入后将formData对象赋值给data属性,由data传递给后台

//例如
fornData.append('name','张三')

在这里插入图片描述
在这里插入图片描述
再给post加上通知组件,来提示用户是否操作成功
在这里插入图片描述

3、引入加载组件Loading

需要先引入

import { Loading,Notification } from 'element-ui';

然后再在加载数据的代码下方写上加载时显示的文字,也就是请求之前
在这里插入图片描述
最后在数据被加载出来后,或者加载失败后将加载组件关闭
在这里插入图片描述

4、引入通知组件Notification
import { Loading,Notification } from 'element-ui';

在后台返回了ResultJson数据后,判断code是正确信息还是错误信息,最后通过组件Notification 显示给用户看
在这里插入图片描述
当然请求失败也需要显示
在这里插入图片描述

5、引入分页组件

引入分页组件后,需要将pageNo当前页,size每页显示条数传入给后台,这就涉及到参数传递了,前端的传参其实也就是params参数,params其实也就是个JSON,这里面的数据名会和后台@GetMapping注解的方法的参数进行匹配,如果对应的上就将值转到后台并赋值
在这里插入图片描述
后台返回的数据是对象时,前端在拿值需要看清楚对应的参数是什么
在这里插入图片描述
因为records才是真正的数据,因此应该绑定为tableData.records,而不是原来的tableData
在这里插入图片描述
在理清楚后,去Element-UI找到分页组件并引入,引入后绑定上数据即可在这里插入图片描述

6、引入查询组件

去Element-UI找到查询组件并引入
在这里插入图片描述
通过品牌名称对数据进行查询,那么就得从前端把名称传入到后台,输入框input有个v-model可以进行双向绑定,在原传入后台的json数组query中加入name属性
在这里插入图片描述
点击查询按钮,查询按钮绑定了find事件,然后就通过条件去后台查,查到就从第一页开始显示
在这里插入图片描述
最后再给搜索框配个全局样式

7、Brand页面的增删改查功能
①查询

加载页面时需要将表格中数据加载出来,点击查询按钮能通过品牌首字母进行模糊查询
在这里插入图片描述
之前增加查询组件和分页组件的时候有详细描述,这里也就不细说了

②新增

在查询右边新增添加按钮,点击弹出新增通知栏
在这里插入图片描述
引入通知弹窗组件
在这里插入图片描述
弹窗默认是不显示
在这里插入图片描述
当按钮被点击时触发add事件,这时候显示弹窗
在这里插入图片描述
添加表单(实际保存新增数据)
弹窗的内容有点多,所以需要新增一个组件来专门做edit新增编辑页面
在这里插入图片描述
其实着页面也就是个表单页面,输入各种数据最后被提交,有关post请求数据请查看之前的axios异步请求
在这里插入图片描述
在这里插入图片描述
提交前需要进行表单验证,也就是rules属性
在这里插入图片描述
新增页面做好后通过组件的引入注册,最后通过标签把所有内容显示到通知栏中(也可以使用动态标签来引入)
在这里插入图片描述
在提交后,添加操作成功时会有个小bug,那就是表单中有验证不通过的,但是也进行了数据的传递,因此我们需要在最后发送数据前,进行二次验证,给表单加上ref="txform"这样就可以在vue中,获取到vue版的dom以此来操作表单对象
在这里插入图片描述
通过this.$refs[‘txform’]来获取vue版的dom对象,用来完成二次验证,二次验证的方法名称为validate,如果验证都通过了,才能允许提交,如果有一个没通过都不能提交
在这里插入图片描述
在通知组件内容提交后应该要将组件关闭(下次打开是空白状态),且表格内容要刷新,但是控制关闭属性的brandDialog.show是在父组件中,子组件没办法修改,要想修改就必须先把父组件的关闭显示属性传到子组件中

//在<component>中加入
:show.sync="brandDialog.show"
//show.sync为了在edit组件中修改index组件的brandDialog.show属性,:show这个名
//字自己取,需要将show的值传递过去,加上sync是为了同步两边数据,这样子组件中修
//改后index组件这边的show属性就会跟着更改

同理函数也是,只是函数要加上@符号

//在<component>中加入
@getTable="getTable"
//@getTable="getTable"为了在edit组件中使用index组件的getTable函数,@getTable
//名字自己取但是需要用@开头

v-if表示有没有如果是ture那么这个组件就有

//在<component>中加入
v-if="brandDialog.show"
//加上v-if属性是为了再次点击打开通知栏form表单的时候里面的数据是空白的,是全新的通知栏

在这里插入图片描述

子组件想要修改父组件的值或者使用父组件的方法就必须用

$emit()

在这里插入图片描述
至此在新增了数据后,通知弹窗消失,表格内容刷新

③删除

在表格样式中新增一列加入删除按钮
在这里插入图片描述
新增删除方法
因为删除方法比较危险,所以我们要给人提示,新增MessageBos弹框,在确定要删除后我们只需要传入id,把ative的值变成0就好了,实现逻辑上的删除
在这里插入图片描述
很明显在,删除完数据后,删除和修改按钮是不能再继续使用的,因此在删除操作后,我们将这两个按钮变成“恢复数据”按钮,将active由0再变为1
在这里插入图片描述

④修改

在表格样式中新增一列加入修改按钮,如果要修改就得让后台知道你要修改的是那儿一列,因此需要把id传入后台,通过scope.row.id获取到id并传入修改方法
在这里插入图片描述
新增修改方法,拿到传入的id并赋值给this.brandDialog.id
在这里插入图片描述
通过自定义属性传入id,:id="brandDialog.id"自定义个id属性传入到edit组件后,用props接收
在这里插入图片描述
edit组件中通过props接收传入的id值
在这里插入图片描述
因为和添加共用一个组件,所以需要在程序开始就要运行的方法created中先判断一下id是否存在,如果存在就是修改方法,需要把该列的信息显示到通知组件中,如果不存在就还是原来那样一片空白

修改,需要查询单条数据,且将原来的url替换为修改的url地址,好让后台接收到正确的修改数据
在这里插入图片描述
查询单条数据,只需要将id传入后台即可查询到,在拿到后台返回的数据后需要对拿到的数据进行处理,name和firstLetter通过for循环正常循环赋值即可,但是file文件不能如此,它需要借助el-upload组件下的file-list属性帮忙,这个属性能够显示初始的文件,因为需要一个JSON 数组因此就新建了个flielist来传递数据
在这里插入图片描述
this.form.id=response.id加上是为了最后更新的时候好用id进行数据修改
在这里插入图片描述

之后需要将filelist的值传到组件中
在这里插入图片描述在one.vue组件中用props下的fileList接收,然后在data中定义一个list数组(这样组件中其他的方法等等才能调用这个数据)将刚刚传入的flieList赋值给this.list
在这里插入图片描述
最后再赋值给file-list属性就可以显示了
在这里插入图片描述
在修改完数据后点击通知栏的保存按钮,进行数据的更新,并关闭通知栏,刷新列表数据
在这里插入图片描述
补全一下原来的添加逻辑
在这里插入图片描述

8、MinIo图片服务器(上传图片)

引入文件上传组件el-upload,然后配置el-upload的属性
在这里插入图片描述
在这里插入图片描述
因为on-change是一个函数,在文件添加时会传入file参数或者filelist参数,因此绑定了一个函数fileChange(file),将传入的函数赋值给form中的file,这样就能通过post请求传入后台了,后台需要用MultipartFile来接收,名字必须和前端传入的文件参数名一致file
在这里插入图片描述
在数据传入后台之后,后台将传入的文件上传到MinIo服务器,并将文件重命名返回给前端,这时候拿到数据需要思考如何将上传的图片文件在表格中显示出来,我们需要用到template自定义列内容,然后植入插槽slot-scop=“scope”,slot-scope=“scope” 是用来取得作用域插槽:data绑定的数据的,scope可以随便替换其他名称,只是定义对象来代表取得的data数据,便于使用,scope.row是获得该行的数据所有消息对象
在这里插入图片描述
通过:src绑定url就可以显示图片了,但是scope.row.img拿到的只是图片名称,缺少完整地址,这时候需要在main.js定义一个全局函数img()来方便图片文件的显示
在这里插入图片描述
自此图片是完全能显示出来了,但是发现一个很不方便的地方,因为图片不支持v-mode也就是双向绑定 ,每次上传文件都要写函数写很多东西,因此我们可以把这个图片上传封装成一个v-model的上传组件one.vue
在这里插入图片描述
在这里插入图片描述
因为很多地方都要用到文件上传,在封装好后就在main.js中进行全局注册
在这里插入图片描述
最后在调用的时候使用注册的标签,v-model绑定数据即可
在这里插入图片描述

9、user页面的增删改查功能

将brand的代码整个拷贝过来,修改里面的关键字已经新增一些字段即可
在这里插入图片描述
每个字段都要进行验证,邮箱有邮箱的验证规则,手机号也有手机号的验证规则,只是手机号需要自己写正则表达式进行验证
在这里插入图片描述

①增删改查

和brand页面的一样,只是改写参数我也就不多写了

10、新商品分类子项目

点击菜单栏中的分类管理,右边主窗口跳转到分类管理页面
在这里插入图片描述
菜单栏是被做成了组件加载到主页中的,右边的main也就是主窗口想要动态显示各个子页面,就要配置router路由
在这里插入图片描述
主路由配置的是主页面,子路由就是各个子页面
在这里插入图片描述
主页面的路由被加载到App.vue中
在这里插入图片描述

最后再配置分类管理子路由,就能在菜单栏点击分类管理后,右侧主窗口挑转到分类管理页面
在这里插入图片描述

①查询

因为是分类项目,所以分页组件,查询组件这些都不需要,只留下新增按钮、表格、通知弹框组织,当然为了分类列表能更好的看出层级关系,我们在table列表上加了row-key属性,然后指定唯一的id属性来作为它的对象,这样通过后台查到所有数据返回后,表格就会根据不同的id进行分层显示
在这里插入图片描述
当然返回的数据中必须要有children字段,也就是存放子集的字段
在这里插入图片描述

增加了两个按钮能跳转到sku列表和attr列表,以及添加下级按钮在这里插入图片描述在这里插入图片描述
要想显示数据只需要发送请求,通过后台查到数据,然后在后台返回后,赋值给this.tableDate = response就能显示出数据了
在这里插入图片描述
效果图
在这里插入图片描述

②新增

在点击右上角添加按钮的时候,新增的属性默认就是顶级,parent_id因此需要传入0,第二个参数为层级level,所以为1级
在这里插入图片描述
在这里插入图片描述
因为要往子组件传递id、parentId、level这三个属性,挨个写比较麻烦,于是加了个params属性,传递时赋值给v-bind就行
v-bind=“brandDialog.params”在这里插入图片描述
v-bind="brandDialog.params"和下面的写法都是一个意思
在这里插入图片描述
将属性传到子组件后,可以用props进行接收,当然也可以用this.$attrs进行数据接收,但是它只接收props没有接收过的参数,如果props已经接收了就不会在这边重复接收
在这里插入图片描述
其实分类中新增只是新增一个属性那就是name分类名称
在这里插入图片描述
所以验证也只需要验证它一个
在这里插入图片描述
如果是新增,要把传入的父级和层级属性进行赋值
在这里插入图片描述
在输入name分类名称的数据后,点击保存按钮保存,前端将参数信息发送到后台,后台处理后发回处理后的JSON信息
在这里插入图片描述
添加下级
添加下级明显再用这个添加按钮去添加就不合适了,我们应该在每一行中加入个添加下级按钮,它传入的参数也就是,当前行的id以级当前层级的id+1毕竟是在该行下添加下级,层级level肯定要加一的
在这里插入图片描述
其他的步骤也就是和新增一样了

③删除

删除也和其他项目类似,传入要删除行的id
在这里插入图片描述
删除后,刷新一下列表即可
在这里插入图片描述
只是后台还是需要判断一下,删除的层级下面还有没有下级,如果有是不允许删除的,能删除的必须是没有下级的

④修改

和新增一样只是修改在从主页面传入数据时只需要传入id属性即可
在这里插入图片描述
然后在created中对id进行判断,如果有传入id就是修改需要调用getOne()并将save进行重新赋值为修改的地址,没有就是新增
在这里插入图片描述
如果是修改的话,就得需要将id传入getOne(),通过id查询单条数据,在拿到后台的返回值后把该数据进行赋值,在组件中进行显示
在这里插入图片描述
在你修改了名称后,点击保存,系统将参数传入后台进行数据更新,然后你拿到返回的数据,进行修改组件的关闭和表格的刷新显示
在这里插入图片描述

⑤属性列表

每个商品都有自己的属性,同一类的商品的属性名相同,只是对应的值不同,新建attr属性列表页面
在这里插入图片描述

在商品分类中新增属性列表按钮
在这里插入图片描述
点击的时候将该行关联的id转入到attr组件就好
在这里插入图片描述
当然这里的属性按钮点击如果还是跳出弹框就不太好了,因为这个属性列表中也是要进行增删改查的,现在点击出现弹框,等一下属性列表中增删改查又出现弹框明显不大好,所以这里点击按钮后不仅仅要把该行的id传入,还要进行跳页
在这里插入图片描述
这样跳页也就是整个页面都跳到了新的页面,我们需要的是跳页后显示在菜单栏的右边主窗口,这就要配置router,在子组件配置router后就显示在主窗口中了
在这里插入图片描述
id的传入是通过url的方式
在这里插入图片描述
在attr属性列表页面要想拿到,由浏览器传入的categoryId属性值,需要在created()中,用this.$route在.vue文件中获取当前的路由信息,然后进行赋值
在这里插入图片描述
属性列表下的增删改查

①查询

通过gettable()将query这个Json数据传到后台,后台接收后,通过query中的categoryId查到属性列表list数据再返回给前端,拿到返回的数据后,给tableDate赋值就可以显示出数据了
在这里插入图片描述

②新增、删除、修改

和brand页面一样没有什么新东西

⑥SKU列表

我们买东西买的就是商品的SKU属性,SKU就是商品的最小销售单位,新建SKU属性列表页面
在这里插入图片描述

在商品分类中新增SKU列表按钮
在这里插入图片描述
点击的时候将该行关联的id转入到SKU组件就好
在这里插入图片描述
当然这里的属性按钮点击如果还是跳出弹框就不太好了,因为这个属性列表中也是要进行增删改查的,现在点击出现弹框,等一下属性列表中增删改查又出现弹框明显不大好,所以这里点击按钮后不仅仅要把该行的id传入,还要进行跳页
在这里插入图片描述

这样跳页也就是整个页面都跳到了新的页面,我们需要的是跳页后显示在菜单栏的右边主窗口,这就要配置router,在子组件配置router后就显示在主窗口中了
在这里插入图片描述

id的传入是通过url的方式
在这里插入图片描述

在SKU属性列表页面要想拿到,由浏览器传入的categoryId属性值,需要在created()中,用this.$route在.vue文件中获取当前的路由信息,然后进行赋值
在这里插入图片描述
SKU列表下的增删改查

②查询、删除、新增、修改

这几个和attr属性列表的逻辑也大致相同,就是修改和新增的通知栏显示有点不一样,新增了一个单选框组件
在这里插入图片描述
在这里插入图片描述
依旧是是在sku主页中,点击按钮将当前行的id传入通知栏,通知栏子组件在那到id后根据id进行数据更新操作,如果点击了按钮却没有id传入,那就是点击了新增按钮,新增一条数据。

因为值列表用的是多行文本框,在输入的时候都是输入一个值进行一次回车”\n“,所以在新增的时候要多加一步,把值列表绑定的this.form.inputList进行一次值的替换,将回车”\n“替换成”,“

如果不用逗号分隔,只用回车,那么这个数据存到数据库后会全部挤到一起
在这里插入图片描述
既然新增的时候需要,那么自然在点击修改时,通过id查询到单行数据进行数据的回显需要将”,“重新替换成”\n“
在这里插入图片描述

11、商品模块设计

新增加一个模块无外乎就是把其他项目的拿过来修修改改,然后router配置一下当前模块的路由,好让这个商品模块也显示在右边的主窗口中
在这里插入图片描述
新模块中几乎所有之前用到的功能都存在,甚至还有新加的一些

按关键字模糊查询、新增按钮
在这里插入图片描述
表格,是否上架滑块按钮
在这里插入图片描述
是否热卖滑块按钮,图片属性
在这里插入图片描述
是否有效,删除、修改、恢复数据按钮
在这里插入图片描述
分页组件,添加功能的通知栏组件
在这里插入图片描述
修改功能的通知栏组件
在这里插入图片描述
在这里插入图片描述
商品模块的增删改查功能

①查询

将query传入后台,后台拿到值后,判断是否有传入name,没有就查询所有数据,有就用传入的name属性进行模糊查询
在这里插入图片描述
在这里插入图片描述
最后返回给前端,前端将数据赋值给tableDate进行显示,显示的内容见上方
在这里插入图片描述

②新增

因为新增的属性实在是太多了,所以要把新增页面做成分段式的新增,用新组件Steps步骤条
在这里插入图片描述
v-for=“(item,index) in panels”
挨个循环panels中的值,step步骤从0开始
在这里插入图片描述
v-show="step===0"如果和上面的setp匹配上了,就会显示要添加的属性是哪些,用v-show就是为了显示和隐藏,而不是v-if的有或者没有,因为会有上一步这样的操作,如果是用v-if的有或者没有,上一步的数据就不会显示了
在这里插入图片描述
添加完属性后,点击下一步按钮触发事件
在这里插入图片描述
进行整个表单二次验证,如果全部验证通过,flag变为ture,进入if判断,让步骤step加一,就进入了第二步,所有的新增除了最后一个保存外都需要验证通过才能进行下一步
在这里插入图片描述
这个新增的属性总共分为五步,‘基础资料’,‘商品图片’,‘商品属性’,‘商品SKU’,‘SKU库存’,‘商品详情’

基础资料

是一个form表单
在这里插入图片描述
商品名称就是一个平常的input输入框,关联品牌要用到select选择器,毕竟关联的品牌应该是我们之前在品牌管理中输入的,这时候选择品牌就好
在这里插入图片描述
想用品牌管理选择器来选择,就得拿到品牌id关联的值才能继续显示出来,通过get请求去查询数据,url地址为getData,查到数据后将数据赋值给brandList
在这里插入图片描述
最后通过一个v-for循环将brandList中的数据都显示出来
在这里插入图片描述
然后就是商品分类和2个input输入框标准价格、关键字
在这里插入图片描述
商品分类用的是Cascader 级联选择器,options绑定后台传过来的数据源进行显示,props负责属性配置,同时在你选择后id会绑定到categoryId上
在这里插入图片描述
通过get请求去查询数据,url地址为getData,查到数据后将数据赋值给categoryList
在这里插入图片描述
但是这样显示会有个问题,就是我们最后一级的选项是有children属性的,但是却没有值,所以当我们点到最后一级时会显示暂无数据,我们应该要把这个暂无数据去掉

在这里插入图片描述
新建一个checkChildren方法,判断一下,如果children下面没有值就将children属性删除,有值的话就递归调用,再遍历一遍,直到所有的JSON包括子集的children中都有值为止
在这里插入图片描述
这样最后就不会在显示再无数据了,如果有注意可以在发现,在新建这个项目的数据表的时候我们是将关联类别设置成了文本类型的
在这里插入图片描述
因为商品类别在输出时是直接输出一个数组,关联了多少层,每一层
都会做个记录
在这里插入图片描述

商品图片

接着我们来看商品图片
效果图
在这里插入图片描述
在这里插入图片描述

其中商品图片是上传单个照片作为封面来用的,因为全局注册了当个文件上传类
在这里插入图片描述
所以在代码中直接引入就可以用了
在这里插入图片描述
简单回忆一下,当文件上传发生改变的时候调用fileChange方法
在这里插入图片描述
然后在方法中用input把文件信息再向外输出,实现双向绑定,然后我们在引用这个组件时使用v-model="form.file"将数据进行绑定即可
在这里插入图片描述
而商品相册却是上传多个图片,我们封装一个上传多个文件的组件
首先将limit最小上传数量改成能允许自己传的
在这里插入图片描述
默认为五个
在这里插入图片描述
新建一个arr数组专门存放传入的图片信息,用for循环将所有的图片都传入arr这个数组,最后将这个arr数组给输出出去
在这里插入图片描述

当然tx-uploadMore也是进行了全局注册的,直接使用就好
在这里插入图片描述

商品属性

效果图
在这里插入图片描述
商品属性将查到的商品属性值进行for循环将每个name都赋值给label,v-model进行双向绑定,绑定item.value,ruls规则也直接写在el-form-item中
在这里插入图片描述
商品属性的值,是根据之前基础资料中的商品分类选择来的,同时也拿到了商品SKU
在这里插入图片描述
我们知道传入的{categoryIds: categoryIds}是一个数组(因为商品分类有各个子集,所以一般会有多个categoryIds),如果数组直接进行get方法的传递,那么会出现链接的参数后面带[]的情况

传入的数组
[{categoryIds: 3},{categoryIds: 5},{categoryIds: 1}]
get请求的url链接
http://localhost:8090/pms-product/getAttrs?categoryIds[]=3&categoryIds[]=5&categoryIds[]=11

这样的传入显然是有问题的,因此我们要在axios中的过滤器来进行修改转换,需要引入qs包,qs包就是专门用来转换JSON的
在这里插入图片描述
在这里插入图片描述

在商品分类选择的时候传入的分类id就查出了,商品属性和商品SKU
在这里插入图片描述

商品SKU

效果图
在这里插入图片描述
商品SKU应该是在前面选择商品分类后得到的属性,这些属性应该是可以多选的,这里用多选框Checkbox 多选框,这多选框的内容也是通过v-for循环出来的,循环的对象是用splir分割成数组的inputList
在这里插入图片描述
为了达预期的显示效果(也就是一个多选框一个属性),我们还要把后台返回的数据,添加上value属性且要变成数组类型,这样el-checkbox-group才能用v-model进行绑定显示
在这里插入图片描述
同时我们还要判断addType的属性是否为1,如果是1的话就让属性可以进行动态添加,这里的v-model绑定的是新加的属性addvalue
在这里插入图片描述
如果addType是1,那么在点击添加按钮时就会触发方法addsku,将添加的item传入方法,先判断输入框的addvalue是否有值,如果有值就将值添加到inputList中,最后再清空addvalue,修改的数据都是sku的属性,最后的时候传入这个属性就能进行新增
在这里插入图片描述

SKU库存

效果图
在这里插入图片描述

SKU的库存是根据前面商品SKU中选择的数据来的,通过笛卡尔积来获得每一种的数据
在这里插入图片描述
为了能实现上述效果,需要将JSON放入数组中,然后再套一个大数组,在商品SKU的最后点击下一步会触发createsku()这个事件函数,因此我们来先看看这个函数对skus的处理

[[{key:颜色, value:黑色}],[{key:尺码, value:S}],[{key:季节,value:夏}]]

在这里插入图片描述
首先是组合第一层的JSON
在这里插入图片描述

第二乃至后面的组合方法写到了appendsku方法中
在这里插入图片描述
在appendsku方法中
在这里插入图片描述
最后再接收并清空一次数据,将sku得每一个对象赋值给一个skulist属性,并添加store库存,和price单价属性,数据都处理好后放入this.form.skus中,并在验证后进入下一个步骤
在这里插入图片描述
最后将数据绑定到表格中显示,主要修改的也就是form.skus属性,最后将这个属性通过save方法发生到后台新增就好
在这里插入图片描述

商品详情

效果图
在这里插入图片描述
商品详情其实就是个富文本编辑器,因为大多数的使用者都是不懂代码不懂排版的,如果想给字加粗变颜色等等,如果不懂肯定是不会的,所以要用富文本编辑器。
在这里插入图片描述
这里直接使用了全局注册的tx-editor来实现富文本编辑器,详情可以看附10富文本编辑器的实现

保存数据

最后就是点击保存按钮将上述的所有新增的属性this.form传入后台进行新增即可
在这里插入图片描述
当然在这之前要处理一些数据
首先是将attrs放入this.form.attrs中,请求传入过程中会将数组转换为字符串,就会让它的值变成[object Object],[object Object]因此我们要将数组的每一个值拿出来先转换为String类型再传入即可
在这里插入图片描述

因为是post请求,所以直接传入数组需要进行特殊处理,需要将数组中的值取出来一个一个传
在这里插入图片描述
最后在数据新增后,将组件关闭,刷新页面即可

③删除

添加删除按钮进行逻辑删除,删除和修改按钮变成恢复数据按钮
在这里插入图片描述
有效变成无效
在这里插入图片描述
传入id和active的值到后台,后台通过id对active的值进行更新,实现逻辑上的删除
在这里插入图片描述

④修改

新建一个修改组件update.vue
在这里插入图片描述
然后需要引入、注册到product的index.vue中
在这里插入图片描述
点击修改按钮的时候,触发update事件并传入当前行的id
在这里插入图片描述
在这里插入图片描述
然后显示修改通知栏,并通过组件下的:id="updateDialog.id"将值传入update组件中
在这里插入图片描述
created,在组件开始的时候加载三个方法来查询数据让修改组件出现内容
在这里插入图片描述
接收开始从index页面传进来的id
在这里插入图片描述
this.getOne()

拿到productId后,用getOne把数据查到并将返回数据赋值给baseform、imglist、picfiles、piclist、detailHtml,也需要给baseform加上id属性,并把response的id赋值给baseform.id,这样修改时就能根据id进行修改了,

在这里插入图片描述

this.getData()

this.getData()获取到brandList和没有chukdren属性的categoryList
在这里插入图片描述
this.getAttrsAndSkus()

通过productId查到对应的attrs和skus
在这里插入图片描述

在修改组件中修改的属性也得分段来修改,新增是因为数据太多要一段段新增,那么修改自然也是需要一段一段修改

基础资料

效果图
在这里插入图片描述
通过gatOne()方法给baseform所有参数赋值
在这里插入图片描述
修改的话用标签页tabs比较好,将基础资料的数据绑定为baseform,修改完后直接进行保存
在这里插入图片描述
在这里插入图片描述
在上述中的关联品牌循环的是brandList,数据都是由this.getData()t来的,只是el-select选中的属性是baseform.brandId,显示什么内容都是根据baseform.brandId来的,baseform.brandId可以实现双向绑定
在这里插入图片描述
在基础资料的数据修改完毕后,点击保存按钮会触发updateBase()事件
在这里插入图片描述

在form表单验证通过后将baseform数据传给后台,并在拿到后台返回值后刷新列表
在这里插入图片描述

商品图片

效果图
在这里插入图片描述
通过gatOne()方法给imgform所有参数赋值 ,还有两个默认显示图片的list
在这里插入图片描述
在这里插入图片描述
在修改完图片信息后,点击保存触发updateImg()事件
在这里插入图片描述
在updateImg()事件中,其实商品图片的修改很简单只需要往后台传入this.imgform.file的值就好,后台可以判断file这个值是否为空、是否有内容,如果有再进行上传就好,但是商品相册的修改就比较麻烦了
在这里插入图片描述
因为商品相册如果被修改了然后直接保存,那么剩下的图片的值会变成undefined未定义
在这里插入图片描述
会出现这样undefined未定义,是因为在我们原来封装的UploadMore组件中,当图片发生改变时,对外输出的直接就是该文件的raw,也就是说对外v-model绑定的是当前图片的raw
在这里插入图片描述
然而老的图片的fileList中却并没有raw,只有新上传的图片才有,所以当我们去掉了一个商品相册的图片后想保存,输出的都是undefined未定义,因为他压根就没有这个属性
上面是之前的图片信息,下面的是新的图片信息包含raw
在这里插入图片描述
所以我们要修改UploadMore组件,在change绑定的fileChange事件中判断一下图片是不是新上传的(判断fileList中有没有raw属性),如果是新上传的就对外输出raw,不是就对外输出name(也就是图片的名称一般后台返回的一个字符串类型的路径)
在这里插入图片描述
有raw输出raw,没有输出name
在这里插入图片描述
然后循环一下this.imgform.picfiles,把里面的值拿出来判断一下是不是Stirng类型的,如果是那么肯定就是UploadMore组件中输出的fileList[i].name,说明是老的数据,将老的数据存入names中,如果不是就是新的数据,新的数据存入files,最后再把id也传入,通过post请求将url为this.url.updateImg发送到后台,拿到返回数据 ,进行页面刷新就好了

在这里插入图片描述

商品属性

效果图
在这里插入图片描述
通过getAttrsAndSkus()方法给attrform所有参数赋值
在这里插入图片描述

在修改完attr商品属性信息后,点击保存触发updateAttr()事件
在这里插入图片描述
将attrs数据转换为String后存入attrs,通过post将url为this.url.updateAttr,参数为attrs的请求发送给后台
在这里插入图片描述

SKU库存

效果图
在这里插入图片描述
通过getAttrsAndSkus()方法给attrform所有参数赋值
在这里插入图片描述

sku商品库存因为修改的数据太多了用的是表格显示,为了更好的让skulist循环,我们应该要将其转换为数组,同时为了标题的更好显示,可以将第一条数据的key取出来全部存入skukey
在这里插入图片描述

在修改完sku商品库存信息后,点击保存触发updateSku()事件
在这里插入图片描述
将skus数据转换为String后存入skus数组,通过post将url为this.url.updateSku,参数为skus的请求发送给后台
在这里插入图片描述

商品详情

效果图
在这里插入图片描述
通过gatOne()方法给detailHtm参数赋值
在这里插入图片描述

因为商品详情是用富文本编辑器进行显示的,将detailHtm数据通过v-model传给富文本编辑器的tx-editor全局组件后,会由其组件中的prop下的value进行接收,在经过富文本编辑器的处理后会返回处理后的图片路径等等
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在修改完商品详情的信息后,点击保存触发saveDetail()事件
在这里插入图片描述
通过post将url为this.url.saveDetail,参数为detailHtm和id的请求发送给后台
在这里插入图片描述

⑤是否上架、是否热买的修改

当点击滑块的时候,触发@change绑定的事件changePublishStatus将id和修改后的publishStatus值传入,后台根据id进行更新数据
在这里插入图片描述
在这里插入图片描述

12、新增login登陆子项目

新建一个login文件下的index.vue,然后配置路由,这次的login页面不会显示在菜单右边的主页面中,而是和整个view下的index.vue页面平行
在这里插入图片描述
页面框架设计,大体是底部从白到天蓝的渐变色,中间一个白色的登陆框
在这里插入图片描述
引用动态组件,将loginForm引入内容放在白色的登陆框中
在这里插入图片描述
编写登陆框中的内容
效果图
在这里插入图片描述
样式
在这里插入图片描述
显示代码
在这里插入图片描述
当用户点击登陆按钮时触发login事件,将form表单中的数据传入后台
在这里插入图片描述
在拿到返回的加密token后,将数据通过cmmint设置到全局域中存入Session Storage(浏览器不关闭就一直在)浏览器的本地存储,然后跳转到首页(根目录下)

总结一下
当前端发起登陆请求后,后端控制器类会返回一个通过JWT加密的token,前端会把这个token放到全局域Session Storage中,每次发送请求时前端都会过滤如果是"/login"或者带有token就放行,并且会将token放到参数头重在每一次请求时传到后台,因为所有请求都会先到gateway中由gateway来进行分配,所以我们在gataway也新建一个过滤器,来判断请求中是否有token,如果没有或者token不合法,都会向前端输出错误信息,前端在axios中接收到错误信息并显示到页面上,token合法的话就会放行通过

附1、npm是什么?

可以看做是前端的maven,也就是管理引用包的工具

附2、运行和停止VUE项目

打开HbuilderX,导入项目,在项目上右键选择"使用命令行窗口打开所在目录",然后在下方输入"npm run serve":运行该项目,“Ctrll+c”:停止运行
在这里插入图片描述
找到package.json后,可以看到实际执行的命令是什么,我们输入的是"npm run serve"实际执行的是"vue-cli-service serve",在这行命令后面加上"–port 80",可以改变端口号
在这里插入图片描述

附3、将Vue的外部终端改为内置终端

点击上方工具——>设置——>运行配置(下滑即可找到)
在这里插入图片描述

附4、router的两种引入方法

router下的index.js,在这个文件中通过routes匹配到的组件都会显示在"router-view"标签中
第一种引入方法
在这里插入图片描述
第二种引入方法在这里插入图片描述

附5、JS6语法import可以拿到export的值
//假如这是a.js
let i=100
export default {
	// 给自己的组件取个名字 default是关键字
  i: i
}

//在另外一个js中就可以引入,这个js和a.js在同一目录下
import a from './a.js' //  ./是当前目录  上面export什么东西那么a就是什么
console.log(a.i)
附6、ajax的封装版是axios
附7、新增自定义模板

vue在新建.vue项目的时候可以选择模板,因此我们自定义一个模板可以事半功倍。
在这里插入图片描述
点击自定义模板即可去自己定义
在这里插入图片描述

附8、静态引入组件和动态引入组件

静态的写法

<template>
	<div>
		<el-dialog 
		width="450px"
		:close-on-click-modal="false"
		:title="brandDialog.title"
		:visible.sync="brandDialog.show">
		<!-- 这是静态的写法 -->
		<BreadEdit></BreadEdit>
		</el-dialog>
	</div>
</template>

<script>
	// ./表示当前路径 这是静态的写法,需要在script中引入、注册后才能通过标签使用
	import BreadEdit from './edit'
	export default {
		// 这是给组件取个名
		name:'BrandIndex',
		// 导入之后注册一下才可以使用 这是静态的写法
		components:{
			BreadEdit
		}
	}		
</script>

动态的写法

<template>
	<div>
		<el-dialog 
		width="450px"
		:close-on-click-modal="false"
		:title="brandDialog.title"
		:visible.sync="brandDialog.show">
		
		<!-- 这是动态的写法 is是我们用的组件对象这里就是下方动态引入的brandDialog.component -->
		<!-- v-if表示有没有,如果是ture那么这个组件就有 -->
		<!-- show.sync为了在edit组件中修改index组件的brandDialog.show属性,名字自己取,需要将show的值传递过去,
		加上sync是为了同步两边数据,这样子组件中修改后index组件这边的show属性就会跟着更改 -->
		<!-- @getTable="getTable"为了在edit组件中使用index组件的函数,名字自己取但是需要用@开头,传的具体的函数名称 -->
		<!-- :id="brandDialog.id"自定义个id属性传入到edit组件后,用props接收 -->
		<component 
		v-if="brandDialog.show"
		:is="brandDialog.component" 
		:show.sync="brandDialog.show"
		:id="brandDialog.id"
		@getTable="getTable"
		></component>
			
		</el-dialog>
	</div>
</template>

<script>
	export default {
		// 这是给组件取个名
		name:'BrandIndex',
		// data是个函数,可以在Vue中加载动态数据
		data(){
			return{
				brandDialog:{
					show: false,
					title: '',
					// 动态引入组件,这里就相当于component为组件对象了
					component: () => import('./edit'),
					id: null
				}
			}
		}
</script>
附9、Vue进入调试模式

在代码中加入debugger进入调试模式

附10、引入富文本编辑器组件

几乎所有的富文本编辑器都是基于html的,基于vue组件的用vue2Editor,还有一个npm网站(类似于后端的maven,maven引jar包依赖,npm引前端依赖、js的)

如果要用需要先install安装,再导入
在这里插入图片描述
安装,记得安装好后要重启一下
在这里插入图片描述
新建一个tx-editor组件,引入富文本编辑器,并用components进行注册
在这里插入图片描述

通过图中我们可以看到,在我们对输入的文字进行加粗、斜体、排序等一系列操作后,我们对其保存时,保存的其实是一堆html标签
在这里插入图片描述
并且当我们传入图片时,富文本编辑器会直接转换为字节流,这样并不好,因为存在数据库中太大了
在这里插入图片描述
这时候我们同样需要再用到minio文件服务器来进行存储,当我们在VueEditor标签中加上useCustomImageHandler属性后,也就是使用客户的上传方式(也就是我们自己的上传方法),用我们自己的方法进行上传返回一个图片的url路径,将图片存储到minio中明显会更好些,添加一个添加图片的事件@image-added=“handleImageAdded”
在这里插入图片描述
然后上传图片的事件对应的函数就得我们自己写了,这个事件会往函数中传入四个参数file文件对象、Editor富文本编辑器对象、cursorLocation图片现在所在的位置,以及resetUploader一个函数代表重新加载,因为是用Editor.insertEmbed添加了一个image标签,所以同时也会将文件新的文件值赋值给content
在这里插入图片描述
在图片的路径重新加载和显示后,需要加一个监听器,因为刚刚的上传图片事件中导致了v-model绑定的content的属性变化,但是却并没有对外做输出,也就是说组件外的v-model并没有发生改变,所以这里要加个监听器,来监听content的,如果content发生了变化,就将改变的值对外输出,同时也要给value加上一个监听器,这样修改的时候,把值赋给v-model后组件也就会显示了,不会因为组件先加载而导致赋值没附上,显示不出,要修改的值
在这里插入图片描述

至此富文本编辑器完毕

最后将tx-editor组件全局注册到main.js中,这样商品详情中就可以直接通过TXEditor使用了
在这里插入图片描述

附11、Vue项目的部署(nginx)

需要构建它(也就是打包)npm run build,
在这里插入图片描述
打包好后会多出一个dist文件
在这里插入图片描述
然后右键当前项目然后选择在外部资源管理器打开,通过Xftp把这个dist文件放入Linux服务器
在这里插入图片描述
和后端的部署一样也是需要构建服务器,因为这是纯静态页,这里用一个静态服务器就好了,用静态服务器的话nginx比较合适,nginx的镜像是不带配置文件的,所以我们还要自己加个配置文件上去
在这里插入图片描述

当然配置文件得根据实际情况进行修改

#nginx静态部署配置文件
#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    server {
    	#端口80可以不改
        listen       80;
        server_name  localhost;
        #首页
		index  index.html;
		#dist所在的路径要根据实际情况修改
		root /app/front/dist/;
        #charset koi8-r;

        #access_log  logs/host.access.log  main;
		location ~ ^/favicon.ico$ {
			root /app/front/dist/;
		}

        location / {
            try_files $uri $uri/ @fallback;
			index index.html;
			proxy_set_header   Host             $host;
			proxy_set_header   X-Real-IP        $remote_addr;
			proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
			proxy_set_header   X-Forwarded-Proto  $scheme;
        }
		location @fallback {
			rewrite ^.*$ /index.html break;
		}
		
        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }


    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}


    # HTTPS server
    #
    #server {
    #    listen       443 ssl;
    #    server_name  localhost;

    #    ssl_certificate      cert.pem;
    #    ssl_certificate_key  cert.key;

    #    ssl_session_cache    shared:SSL:1m;
    #    ssl_session_timeout  5m;

    #    ssl_ciphers  HIGH:!aNULL:!MD5;
    #    ssl_prefer_server_ciphers  on;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}

}

在Linux中下载nginx镜像 docker pull nginx:1.18.0
在这里插入图片描述
在docker Hub上找到配置nginx运行的方法
在这里插入图片描述
在这里插入图片描述

docker --name tx-nginx -p 80:80 -v /app/front/nginx-vue.conf:/etc/nginx-vue.conf -v /app/front/dist:/app/front/dist -d nginx:1.18.0

//大多数都和后台部署gateway的设置一样,只是这个文件在同-v映射时必须映射到etc中,而且在映射nginx-vue.conf的同时也要把dist也放入容器的app文件夹中

运行完后通过日志查看是否启动

进入nginx容器中,查看刚刚映射的文件是否存在
在这里插入图片描述
接着尝试访问192.168.149.131:80
在这里插入图片描述
页面显示成功,说明前端vue的部署也是成功的

附12、README

在这里插入图片描述
在这里插入图片描述

附13、Vuex状态管理(设置全局数据)

前端拿到了后台的返回的加密token后,又面临一个新的问题,要将token存到哪儿去?因为后面每一次请求这个token都要传到后端,存在当前页面的data中肯定不行,因为离开了当前页面也就访问不到了,因此就是要将数据存到 Vuex状态管理中(从建项目时添加了但是就没用过)也就全局域中,对应的文件是store下的index.js

那什么叫Vuex状态管理呢?
首先Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。这个状态管理说白了就是一个data,不过它不是一个页面中的data,而是整项目的data(全局data),也可以看做是数据域,数据管理

在mutations中定义了一个设置token的方法其他页面要将数据设置成全局数据就用它,在getters中定义了一个拿到全局数据token的方法
在这里插入图片描述

因为store中把Vuex作为一个Vue对象的插件,那么在通过this点对象的时候就会有$store,拿到可以直接用getters,但是设置token是要用commit
在这里插入图片描述
设置全局域
在这里插入图片描述

附14、Vuex的持久化存储

全局数据设置好了后,也有新问题,就是当我页面刷新的时候,这个全局数据token就消失了变成了空字符串,因为我们在Vuex中存的数据是不能刷新的,刷新浏览器意味着main.js要重新加载,那么main.js下的所有组件就要重新引入,重新创建vue对象(有给new Vue当中包含store),那么一切都会初始化,store中的toekn也会重新变成空字符串。

这就需要Vuex的持久化了
Local Storage(不主动删除就会一直在,即使第二天再打开浏览器也一样)和Session Storage(浏览器不关闭就一直在)都是浏览器的本地存储,一般用Session Storage,如果Local Storage就怕某天你电脑给别人用了,人家就直接登陆进去了(token毕竟就是存储登陆的认证信息的)
在这里插入图片描述
先安装npm install vuex-persistedstate --save
在这里插入图片描述
然后引入
在这里插入图片描述
再植入一个插件就好了,默认是存入Local Storage中的,配置一个JSON{storage:window.sessionStorage}, 就能存入Session Storage中了
在这里插入图片描述

附15、router过滤器

如果除登陆页面外的其他页面中,没有token的存在,可以看做是没有登陆,这样直接访问能访问到显然是不行的,要强制跳转到登陆页面进行登陆。

需要在router中的index.js下定义一个过滤器,每一次跳页都要经过router中过滤看它是否有登陆,没有登陆就跳转到登录页面进行登陆
在这里插入图片描述
在前端也结束router过滤器中,我们只能通过store.getters.GET_TOKEN有没有这个token,但是不能判断这个token的合法性,可以直接在浏览器的Session Storage中随便伪造一个,然后也就可以绕过登陆正常访问页面了,为了验证这个token就只能到后端的gateway再新建一个过滤器进行认证了

附16、token认证前端

axios中也有过滤器,发请求前你要做什么可以在这儿完成,在请求头中加入‘token’,将store.getters.GET_TOKEN的值赋值给这个‘token’
在这里插入图片描述
传入token后,在后台GatewayFilter进行token认证,如果是正确的token会直接被后端的过滤器过滤通过,只有错误的会返回,在axios中接收错误的返回信息,然后将页面跳转到登陆页

二、新建SpringCloud电商后台项目

三、新建SpringCloud电商前端Vant项目

  • 15
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
该项目是采用目前比较流行的SpringBoot/SpringCloud构建微服务电商项目,项目叫 《果然新鲜》,实现一套串联的微服务电商项目。完全符合一线城市微服务电商的需求,对学习微服务电商架构,有非常大的帮助,该项目涵盖从微服务电商需求讨论、数据库设计、技术选型、互联网安全架构、整合SpringCloud各自组件、分布式基础设施等实现一套完整的微服务解决方案。 项目使用分布式微服务框架,涉及后台管理员服务、地址服务、物流服务、广告服务、商品服务、商品类别服务、品牌服务、订单服务 、购物车服务、首页频道服务、公告服务、留言服务、搜索服务、会员服务等。  系统架构图   SpringBoot+SpringCloud+SSM构建微服务电商项目使用SpringCloud Eureka作为注册中心,实现服务治理使用Zuul网关框架管理服务请求入口使用Ribbon实现本地负载均衡器和Feign HTTP客户端调用工具使用Hystrix服务保护框架(服务降级、隔离、熔断、限流)使用消息总线Stream RabbitMQ和 Kafka微服务API接口安全控制和单点登录系统CAS+JWT+OAuth2.0分布式基础设施构建分布式任务调度平台XXL-JOB分布式日志采集系统ELK分布式事务解决方案LCN分布式锁解决方案Zookeeper、Redis分布式配置中心(携程Apollo)高并发分布式全局ID生成(雪花算法)分布式Session框架Spring-Session分布式服务追踪与调用链Zipkin项目运营与部署环境分布式设施环境,统一采用Docker安装使用jenkins+docker+k8s实现自动部署微服务API管理ApiSwagger使用GitLab代码管理(GitHub  GitEE)统一采用第三方云数据库使用七牛云服务器对静态资源实现加速 开发环境要求JDK统一要求:JDK1.8Maven统一管理依赖 统一采用Docker环境部署编码统一采用UTF-8开发工具IDEA 或者 Eclipse 

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值