广州市白云区网站建设维护,网站视频封面怎么做,搬瓦工wordpress安装,公众电影网站怎么做记录一些踩坑的地方#xff0c;以及理顺一些思路。 通过管理系统页面#xff0c;完成商品属性分组和商品属性#xff08;基本属性#xff09;关联维护
属性表 与 属性组表 的功能完善#xff1a;显示属性组与属性表的一对多关系
前端
1. 引入组件#xff0c;是否显示使…记录一些踩坑的地方以及理顺一些思路。 通过管理系统页面完成商品属性分组和商品属性基本属性关联维护
属性表 与 属性组表 的功能完善显示属性组与属性表的一对多关系
前端
1. 引入组件是否显示使用v-if但是还要注意引入的组件本身是否自己也有 :visible.syncvisible这样的属性。只有当两层是否显示的变量都为true的时候才会显示。
2. 使用子组件的方法使用ref
3. 需要在执行完毕后才立即执行的情况使用this.$nextTick(()-{ lambda表达式的方法体 }) 移除中间表即连接属性表与属性组表的AttrAttrgroupRelation表
后端
需求说明
批量删除关联表内容。
我的方案问题及解决方案:
1.我写了(RequestBody Map params) 来获取参数结果参数都拿不到直接报错。 前端传递的问题。使用postman可以正常传输。 这个方案不好①获取参数麻烦②传递数组也不方便
2.还有底层不知道给两个基本参数还是给一个对象比较好 传给一个关联表的entity对象。可以使用RequestBody来直接封装到该自定义的entity里面。 而且参数使用数组的形式前端使用Json只有数组没有集合格式 再在后端转为集合因为dao层foreach遍历传参用的是集合。这样便可以实现批量删除
3.我的想法要先去mysql查到要删除的数据然后再去mysql删除多了一个查询的步骤。
4.想返回受影响的行数。 测试发现在dao层返回类型设为Integer是可以直接返回受影响行数的不用额外写代码。
细节踩坑
1、在dao层的接口方法依然要使用注解Param 传参 通过删除该注解发现参数会值为空且不能正确运行。
2、测试数据的类型要求数组所以格式要求“ [ ] ”这样来表示数组 通过在postman哪怕是单一entity没有使用[ ]也发生了错误。
3、Mapper语句中字段名来自于mysql 值来自于java的Entity。 没有写错再次提醒而已。
4、找了2个小时的bug。在service层调用dao层的方法时使用了this.方法结果调的是service层自己就变成了无限嵌套导致出错。根本原因还是对这儿的this理解不够。 错误原因 ① 错误写法形成的原因。之前的代码因为有“工具类”可能形容不准确的存在所以能使用this.方法使得能通过this.方法在service层调用dao层的对应方法。 ② 出错的原因。因为当前方法是我在dao层自定义的service没有进行实现需要我自己调用dao层来实现结果我写个this.方法成了自己调用自己当前方法就形成了没有返回的嵌套。 最好的解决办法不要使用this代码规范有要求
查询某个商品属性分组可以关联的商品属性基本属性支持分页和条件检索
RequestBody和RequestParam区别全面详细
还是对this的理解不够深刻。为什么
为什么在AttrServiceImpl.java就可以 IPageAttrEntity page this.page(new QueryAttrEntity().getPage(params),//终于看懂这个wrapper了它是个变量放在这儿作参数用的。wrapper);
在AttrgroupServiceImpl.java就不可以 IPageAttrEntity page new AttrServiceImpl().page(new QueryAttrEntity().getPage(params),wrapper);
显示可建立关联的基本属性
涉及多表联查使用AB两表查询得到限制条件通过限制条件在C表直接分页查询完成。
新建属性组与基础属性的关联
调用service提供的接口即可完成。
因为支持批量增加所以参数是List类型的使用RequestBody进行传递 商品发布
SPU和SKU介绍
1、SPU的概述 1)SPU(Standard Product Unit):标准化产品单元 2)用简单的话来说就是一类商品比如手机里的一种牌子如小米苹果都是一类。然后加入具体的类型如小米10、苹果X。那么它就是一个spu 2、sku的概述 1)SKU(Stock keeping Unit):库存保有单位 2)sku简单来说就是在spu原有的基础上加入具体的类型如小米10银色8128g。组合起来就是一个完整地sku。所以sku就是一类商品的各种样式的组合。 3、spu和sku的关系 1)spu和sku就是上下级关系没有spu就没有sku。因为假如没有这一类商品就没法谈这件商品具体的颜色尺寸 2)如下图假如没有选择任何类型那么他就是一个单独的spu,但是当它选择了具体的颜色版本购买方式等等那么他就是一个sku 完成商品发布页面 1.完成选择商品分类时联动获取该分类下的品牌 指定商品分类后自动显示可以选择的品牌列表
实现
利用categoryId查询关联表得到brandId使用它查询brand表的行并返回
注意
1.当输入的categoryId没有时会报异常
2.当输入的categoryId在关联表找不到对应的brandId时也会报错
因为这时的mysql的语句里面in()后面的内容为空所以报异常
解决办法是直接使用stream流进行处理处理完的BrandEntity进行返回这样允许返回为[]。 2.完成获取某个分类的关联的所有属性分组和这些属性分组关联的基本属性并显示供发布选择 1. 当目前的实体类/对象格式不能满足需求时可以使用VO(View Object)视图对象 2. VO可以根据需求组合己有的实体类字段或者增加或者删除一些字段
难点
1.多表查询。使用流式计算提高效率。
2.使用BeanUtils.copyProperties(数据源目的数据)将数据封装到VO里面。以前在JavaWeb的时候用过。
debug:
1.前后端的debug都没有反馈居然是因为PathVariable(catalogId) 括号里面的单词拼错了
2.后端测试正确前端不显示结果。原因是前端遍历子属性的名称和后端不一致导致无法遍历。将后端名称改为和前端一致便解决了。
3.完成获取某个分类的销售属性并显示供发布选择 debug:
1.因为不带查询条件所以代码要判断查询条件是否为空否则mysql会导致异常。
2.查询条件的字段需要与mysql保持一致否则也会引起异常。
3.检查前端的分隔符split(,)里面的符号和后端是否保持一致同时注意中英文。 4.完成根据前面填写的多个销售属性构建成商品SKU信息也就是各种组合关系 由前端页面完成 5.完成保存商品信息功能
需要设计VO类
1、通过前端获得提交的json格式的数据在JSON在线解析及格式化验证 - JSON.cn里面选择“json生成java实体”
2、根据业务要求修改生成类的类型以及必要的增删
功能1-保存spu基本信息
创建数据库使用renren-fast生成crud代码
复制/剪切到后端程序中
报错 java: 找不到符号 符号: 类 SpuInfoEntity 位置: 程序包 com.stein.steinliving.commodity.entity
解决办法 1.Maven 刷新Reload All Maven Project 2.菜单栏build-Build Module xxxxxx”
上两步依然没有解决实际解决 Mavenlifecircle- clean。重新运行module即可。。
bug 前端点击继续添加如果不重新手动选择categoryId和品牌brand那么前端显示有数据后端得不到数据库内会显示为null。
功能2-保存spu图片描述url
开始认为是一对多使用一个id多行decript保存结果是用“,”逗号分割保存在一行里面。
所以当初设计的时候mysql对应的字段属性是LONGTEXT。 /** * 商品 id * 因为 commodity_spu_info_desc 表的 id 不是自增长的而是我们指定的 * 因此我们这里给 spuId 标识上 TableId(type IdType.INPUT) * , 否则底层的 sql 语句时不会生成添加 supId 的 sql 语句 ( 可以通过日志输出看看 ) */ TableId ( type IdType.INPUT ) private Long spuId ; 功能3-保存spu图片集信息
功能4-保存spu的基本属性/规格参数
功能5-保存sku的基本信息
注意字段的命名
因为mysql不区分大小写所以将java属性的spuId写作spu_id。不按照这个格式进行对应可能会出错。
功能6-保存sku的图片信息
完善上传功能
在前端的src/components/upload/multiUpload.vue文件下
el-upload 中的action进行设置改为自己的oss地址比如
actionhttp://xxxxxx.oss-cn-beijing.aliyuncs.com
功能7-保存sku的销售属性 spu管理页面
添加订阅发布功能
因为要使用到订阅发布功能所以我们需要做如下操作 1.使用npm添加依赖npm install --save pubsub-js
(失败的话使用此命令cnpm install --save pubsub-js)
2.修改在src下的views/main.js,增加语句 import cloneDeep from lodash/cloneDeep import PubSub from pubsub-js
3.挂载全局下面添加
Vue.prototype.PubSub PubSub // 组件发布订阅消息
完善分页检索功能
其中的模糊检索
wrapper.and(w-{w.eq(id,key).or().like(spu_name,key);});
完善“上架”和“下架”
1.先编写dao层。 可以使用快捷键altenter找mybatis的选项自动填充注解 继续使用快捷键找mybatis的选项自动完善要实现的result部分
void productUpOrDown(Param(spuId) Long spuId,
Param(statusCode) Integer statusCode);
实现语句 先在mysql里面测试语句是否正确再写到实现语句
2.完善service层
3.controller层进行接口调用。
sku管理页面
同上
1.引入新页面打不开可以重启下前端。
2.查看前端检索条件注意看条件的名称
key: this.dataForm.key,
catalogId: this.dataForm.catalogId,
brandId: this.dataForm.brandId,
min: this.dataForm.price.min,
max: this.dataForm.price.max
然后判断出封装在哪个变量this.dataForm然后输出查看:
console.log(检索条件,this.dataForm)3.检索条件。价格区间
这儿给max加了一条不为“0”的限制条件。
因为前端默认min、max0。不利于初始化显示。 //这儿的min和max是在price的子属性上也是这么取吗?// 是的。因为封装的时候是遍历price的属性再进行封装的。//这儿是比较的数字还是使用String接收吗? 是的//如何比较的大小? ge(GreatEqual),le(LittleEqual)String min (String)params.get(min);if(StringUtils.isNotBlank(min)){wrapper.ge(price,min);}String max (String)params.get(max);if(StringUtils.isNotBlank(max) !0.equals(max)){wrapper.le(price,max);}
搭建客户端显示的首页面 Thymeleaf的导入/引入
1.将资源包中的resources文件解压放到后端项目的中的resources中。
2.maven中引入thymeleaf。在pom.xml中添加不设置版本号由版本仲裁控制 dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-thymeleaf/artifactId/dependency
3.application.properties设置关闭缓存便于随时刷新变化。 spring.thymeleaf.cachefalse4.添加前端web控制层。
Controller
public class IndexController {//响应用户请求首页面GetMapping(value{/,/index.html})private String indexPage(){// 默认找到就是classpath\templatesindex.htmlreturn index;}
}
5.index.html文件引入命名空间。否则后期使用th标签时无法识别。
文件路径src/main/resources/templates/index.html
html langenxmlns thhttp://www.thymeleaf.org
首页显示1级目录
首页显示2、3级目录
1.创建2-3级VO类的数据结构
2.实现VO类数据的封装
2.1逻辑删除
通过查询发现返回的数据不会有逻辑删除的内容。回忆之前逻辑删除的实现方法 2.1.1 修改 hspliving\hspliving-commodity\src\main\resources\ application.yml mybatis-plus:mapper-locations: classpath:/mapper/**/*.xmlglobal-config:db-config:id-type: auto #配置主键自增logic-delete-value: 0 # 逻辑已删除值(默认为 1, 提示:调整成我们自己的)logic-not-delete-value: 1 # 逻辑未删除值(默认为 0 提示:调整成我们自己的) 2.1.2 属性添加响应的注解 TableLogic private Integer isShow ; 2.2 categoryService层编写方法
2.2.1 可以编写一个测试类随时查看返回值是否正确
Controller
public class Test {Resourceprivate CategoryService categoryService;RequestMapping(/t1)ResponseBody //返回Json格式的数据。使用了便没有报错public MapString, ListCategoryLevel2OV test(){MapString, ListCategoryLevel2OV categoryLevelJson categoryService.getCategoryLevelJson();return categoryLevelJson;}
}
2.2.2代码实现
Overridepublic MapString, ListCategoryLevel2OV getCategoryLevelJson() {ListCategoryEntity categoryList this.baseMapper.selectList(null);//System.out.println(categoryList.toString());// 1级-2级-3级 再组装//获取1级分类ListCategoryEntity level1 getCategoryByParentId(categoryList, 0l);//通过流遍历1级分类并把数据进行封装并从List转换为前端需要的MapMapString,ListCategoryLevel2OV categoryMap level1.stream().collect(Collectors.toMap(k - {return k.getId().toString();}, v - {//第二级的封装//先获取2级分类ListCategoryEntity level2 getCategoryByParentId(categoryList, v.getId());ListCategoryLevel2OV level2OV level2.stream().map(l2 - {CategoryLevel2OV categoryLevel2 new CategoryLevel2OV();categoryLevel2.setCatalog1Id(v.getParentId().toString());categoryLevel2.setId(v.getId().toString());categoryLevel2.setName(v.getName());//第三级的封装ListCategoryEntity level3 getCategoryByParentId(categoryList, l2.getId());ListCategoryLevel2OV.Catalog3List level3VO level3.stream().map(l3 - {CategoryLevel2OV.Catalog3List level3Entity new CategoryLevel2OV.Catalog3List();level3Entity.setId(l3.getId().toString());level3Entity.setName(l3.getName());level3Entity.setParentCId(l3.getParentId().toString());return level3Entity;}).collect(Collectors.toList());categoryLevel2.setCatalog3List(level3VO);return categoryLevel2;}).collect(Collectors.toList());return level2OV;}));return categoryMap;}//私有方法起到一个筛选作用。在数据列表中筛出符合条件的的categoryEntities。private ListCategoryEntity getCategoryByParentId(ListCategoryEntity selectList, Long parentId) {ListCategoryEntity categoryEntities selectList.stream().filter(item - {return item.getParentId().equals(parentId);}).collect(Collectors.toList());return categoryEntities;}
因为它是一个映射所以返回类型是
3.连接前端
3.1找到前端发送Ajax请求的位置
src\main\resources\static\index\js\catalogLoader.js,该js文件就是向服务器发出ajax请求返回第2级和第3级json数据然后由前端人员完成显示【我们直接使用即可】
由这句$.getJSON(index/catalog.json, function (data)可以看出访问路径为index/catalog.json由此设置后端访问接口
3.2完善前端属性便于数据显示
完善属性便可在首页正常显示。
a href# classheader_main_left_a th:attrctg-data${category.id}
但是在控制台的data不能正常显示显示一些类似当前行高的数字随鼠标滑轮变化。看不懂。。
0
secend.js:3 0.9090908765792847
secend.js:3 6.363636016845703
secend.js:3 19.09090805053711
secend.js:3 40.909088134765625
secend.js:3 70.90908813476562
secend.js:3 108.18181610107422
secend.js:3 148.1818084716797
secend.js:3 185.4545440673828
secend.js:3 215.4545440673828
secend.js:3 235.4545440673828
secend.js:3 244.5454559326172
secend.js:3 246.36363220214844
secend.js:3 245.4545440673828
secend.js:3 240.90908813476562
secend.js:3 234.5454559326172
secend.js:3 224.5454559326172
secend.js:3 209.09091186523438
完善搜素首页
1.创建OV类 注意Thymeleaf是通过对象传输的而不是Json
2.实现搜索功能-Service层
3.实现数据的二次封装。添加Model参数用于传输属性。-Controller层
4.前端调用封装到Model里面的数据。
添加Thymeleaf的命名空间
找到显示的list.html文件通过搜索显示的实例里面的价格找到对应的属性进行关联。 完善分页导航栏 完善搜索框搜索 只搜索状态为上架的商品
1.添加搜索spuInfo表的dao层完成搜索获得上架spuIds
2.把原来的搜索添加spuId这个搜索条件限定搜索范围在spuIds上架状态
注意
要判断spuIds.size0如果真则执行限定in()
如果假便直接返回。为了统一返回内容为SearchResult便开始重构
重构搜索功能
//返回购买用户检索的结果PageUtils-SearchResult / Result
完善分页查询功能用户点击某页超链接显示对应页的数据
分析源代码查看导航页的参数属性构成情况。
没有输入便按照默认设置的参数执行。 添加前端导航条分页代码 //分页请求$(.page_a).click(function () {var pn $(this).attr(pn);var href location.href;if (href.indexOf(page) ! -1) {//替换, 这里的page 是因为我们后台分页插件是按照 page 这个参数来当做当前页//的参数//所以写成 page ,同学们应当根据你的后台是安装什么参数名来接收当前页进行相应改变location.href replaceParamVal(href, page, pn);} else {//增加 pageNuwif (href.indexOf(?) ! -1) {location.href location.href page pn;} else {location.href location.href ?page pn;}}return false;})
在搜索框保留检索关键字
原理前端发送到 - 后端添加类字段保存keyword通过result回传 - 前端回显
1.前端原始代码通过placeholder显示默认内容。此时内容固定显示
input idkeyword_input typetext placeholder家居~/
2.后端封装返回数据的SearchResultOV.java类添加keyword属性
3.业务代码完善SkuInfoServiceImpl.java类中keyword的内容封装
//添加搜索框回显内容
//三元操作符searchResultOV.setKeyword(params.get(keyword)null?:params.get(keyword).toString());
4.前端回显
input idkeyword_input th:value${result.keyword}
typetext placeholder家居~/
通过value取出result.keyword进行回显。
加入Nginx-完成反向代理、负载均衡和动静分离
https://blog.csdn.net/weixin_49764008/article/details/132887378?csdn_share_tail%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22132887378%22%2C%22source%22%3A%22weixin_49764008%22%7D
完成 Nginx的添加