1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > 微服务商城系统实战 后台管理页面 商家管理页面 商品列表跳转详情页

微服务商城系统实战 后台管理页面 商家管理页面 商品列表跳转详情页

时间:2024-07-23 11:46:44

相关推荐

微服务商城系统实战 后台管理页面 商家管理页面 商品列表跳转详情页

文章目录

一、后台管理1、根据点击的 div 展示相应页面2、解决 height: 100% 不起作用问题3、 th:onclick 引用的函数参数是 model值 二、商家管理1、th:each="obj,itemStat:${objList}"2、使用 min-height3、获取 input 的 text 值4、ajax 中 async: false5、让 input 填满 td 三、商品详情页四、加入购物车功能1、解决 Long 在 JS 中精度丢失问题2、使用 Vue 实例3、使用 v-bind 绑定数据

一、后台管理

采用左边栏多级菜单的形式,前端页面如下:

1、根据点击的 div 展示相应页面

根据点击不同的选项,需要在右侧页面中显示不同的内容:

<div class="content" style="width: 85%;height:100%;float:right"><div style="background-color:black;display: none;height: 100%;color: #2b2b2b" onclick="cont(this)">我是A的内容</div><div style="background-color: blue;display: none;color: snow" onclick="cont(this)" >我是B的内容</div><div style="background-color: orange;display: none" onclick="cont(this)" >我是C的内容</div><div style="background-color: green;display: none" onclick="cont(this)" >我是D的内容</div></div><script type="text/javascript">//点击菜单执行函数function tab(param) {var sp_an=$(param).attr('list');//获取被点击菜单的list属性值(0,1,2,3)$('.content').children('div').eq(sp_an).click();//点击菜单后,对应的内容被点击,从而实现展示//使用click()方法模拟点击事件,触发下面的cont函数}//这个函数的触发是通过点击菜单的时候触发的function cont(param){$(param).show();//被选中的内容显示$(param).siblings().hide();//没有被选中的内容隐藏}</script>

2、解决 height: 100% 不起作用问题

注意到左边栏的高度并没有充满页面,需要调整一下:

只将此处的 height 改成 100%,是不会奏效的,因为 Web 浏览器在计算有效宽度时会考虑浏览器窗口的打开度。如果不给宽度设定任何缺省值,那浏览器会自动将页面内容平铺填满整个横向宽度。

但是高度的计算方式完全不一样。事实上,浏览器根本就不计算内容的高度,除非内容超出了视窗范围 (导致滚动条出现)。或者给整个页面设置一个绝对高度。否则,浏览器就会简单的让内容往下堆砌,页面的高度根本就无需考虑。

因为页面并没有缺省的高度值,所以,当让一个元素的高度设定为百分比高度时,无法根据获取父元素的高度,也就无法计算自己的高度。换句话说,父元素的高度只是一个缺省值:height: auto;。当要求浏览器根据这样一个缺省值来计算百分比高度时,只能得到undefined 的结果。也就是一个 null 值,浏览器不会对这个值有任何的反应。

也就是说,现在的问题在于,iframe 的父元素 body、body 的父元素 html 都没有设定固定高度,于是子元素的高度 height: 100% 也不会起作用。

如果想让一个元素的百分比高度 height: 100% ;起作用,需要给这个元素的所有父元素的高度设定一个有效值

这时再看效果:

还需要把右边的页面整成靠右,占 85% 的效果(因为左边占 15% 了),但是如果设置成 85% ,有一部分是重叠的,经过调整,83.5% 比较合适:

页面效果:

至此,页面布局和展示没问题了,后续需要设计管理的具体功能实现。

后端提供展示未入驻商家列表的方法。

先在 com.changgou.user.feign 包里提供 :

整成表格的形式:

接下来需要一些后端的逻辑实现,逻辑是相似的,在这里就不一一列举了。

比如,商家管理,展示未入驻商家列表,对应 http://localhost:18087/admin/unCenter 路径,是在 user 微服务中的,而要在 web-admin 工程中调用,就需要使用 feign,先提供个 feign:

@FeignClient(name = "user")@RequestMapping("/admin")public interface AdminFeign {@GetMapping("/unCenter")public Result unCenterList();}

注意!!! 这里的FeignClient 里的 name 属性值不能随便写,它是用来指定 FeignClient 的名称,如果项目使用了 Ribbon,name 属性会作为微服务的名称,用于服务发现。也就是说,对应的路径是在哪个微服务里,就写哪个微服务的名称。 否则报错 :

flix.client.ClientException: Load balancer does not have available server for client: admin at flix.loadbalancer.LoadBalancerContext.getServerFromLoadBalancer(LoadBalancerContext.java:483) ~[ribbon-loadbalancer-2.3.0.jar:2.3.0]

运行结果:

3、 th:onclick 引用的函数参数是 model值

这里主要要注意的是,从后端给 model 赋值后,在表格里获取 model 的值,并用 th:each 进行渲染时,按钮也需要遍历,而不是只写成 button:

<button th:onclick="permitCenter([[${unCenter.storeName}]]);" style="width: 50%;" >允许入驻</button>

permitCenter 方法中还有 ajax 代码:

<script type="text/javascript" src="/js/jquery.min.js"></script><script type="text/javascript">function permitCenter(storeName){$.ajax({url: "http://localhost:18087/admin/permitCenter",type: "GET",dataType: "JSON",contentType: "application/json;charset=UTF-8",data: {storeName:storeName},success: function (result) {alert("商家入驻成功!");},error: function (result) {console.log(result);alert("商家入驻失败!");},cache: false})}</script>

注意 thymeleaf 的 th:onclick 引用的函数参数的入参是 model 值时的写法。

如果传入多个参数,需要使用逗号隔开,并且,可以进行拼接,比如:

th:onclick="update([[${brands.name}]],[[${brands.id}]],'cell'+[[${brandState.index}]])"

二、商家管理

1、th:each=“obj,itemStat:${objList}”

同样的,修改商品品牌数据时,需要根据所在的 tr 获取修改的值,也是要循环遍历的,然后进行拼接:

注意到 thymeleaf 中使用th:each迭代循环对象集合时,还可以获取对象的状态,而且th:id是可以拼接的。

语法格式:

th:each="obj,itemStat:${objList}

itemStat 称作状态变量,属性有:

index:当前迭代对象的index(从0开始计算)count: 当前迭代对象的index(从1开始计算)size:被迭代对象的大小current:当前迭代变量even/odd:布尔值,当前循环是否是偶数/奇数(从0开始计算)first:布尔值,当前循环是否是第一个last:布尔值,当前循环是否是最后一个

2、使用 min-height

当从后端查询出的数据很多,需要滚动条时,需要将 height 改为 min-height ,才能进行数据填充,否则只有一个不滚动页面的容量:

3、获取 input 的 text 值

<td th:text="${brands.image}" th:id="'cell'+${brandState.index}"></td>

function update(name,id,imageid){var image=document.getElementById(imageid).innerText;

通过表格中的 td 的 id,获取 td 的值,需要用innerText

4、ajax 中 async: false

注意,当 js 的方法里不仅有 ajax,还有其他要执行的代码时,需要在 ajax 中添加async: false,将请求设置为同步请求,这样才会按照代码的顺序执行。

5、让 input 填满 td

正确写法:

<td><input id="brandtrnameid" style="width: 90%"></input></td>

错误写法:

<td><input id="brandtrnameid" width="100%"></td>

三、商品详情页

点击商品后跳转至商品详情页的思路,是点击商品图片后,调用 http://localhost:18088/page/createHtml/1148477874278244352 方法,在 changgou-web-item\src\main\resources\static 路径下生成 Html。

同样地,需要解决跨域问题,否则在 GET 方法之前会使用 OPTIONS,而且它还会自己追加 Query String Parameters:

403 状态码是因为跨域,在调用的 createHtml 方法上加 @CrossOrigin 就好啦:

四、加入购物车功能

在 item.html 中,是创建了 Vue 实例,实现的根据 spec 切换 name、price,接下来需要把商品加入购物车,需要 skuid。

1、解决 Long 在 JS 中精度丢失问题

有一个问题,数据库 sku 表中 id 是 bigint 类型,Java 对象中 id 是 long 类型,先试图在网页上渲染 id 值,就会发现,long 类型在 JS 中,发生了精度丢失,比如 : 1148477874387296256 会显示成 1148477874387296300;1148477874399879168 会显示成 1148477874399879200。要解决这个问题,可以使用@JsonSerialize注解进行序列化处理。

这样,获取到的 skuid 的精度不会丢失。

(同理,在 search 服务中,用户在商品详情列表中,点击某个商品时,需要获取 spuid,进而生成对应的 html, Skuinfo 里 的 spuid 也是需要序列化处理的。

Long 类型在数据库、ES 索引库的存储中都是没问题的,但是涉及到 js,比如说传递参数、在页面弹窗显示,就会出现精度损失的问题,一定要引起注意!!!。

2、使用 Vue 实例

复习一下 Vue 实例:

<script th:inline="javascript">var item = new Vue({el: '#itemArray',data: {skuList : [[${skuList}]],sku: {},spec:{}},methods:{......})</script>

可以看到,创建了一个 vue 对象,并赋值给 el,绑定了 id 为 itemArray 的 div 标签,相当于 item 绑定了 id为 itemArray 的标签对象,可以使用此对象操作标签。然后在 data 中,创建了 key 为 skuList、sku 的数据对应的值。

在 div 标签中,使用{{}}大括号,里面写 key 名称,就可以完成相应的渲染。而如果想获取 data 里面的数据的值(而不是渲染),比如当用户点击按钮时,获取此时 vue 实例中的 skuid,可以使用 v-bind 。

3、使用 v-bind 绑定数据

先导入 vue.js 的依赖,可以使用网址,也可以下到自己的项目中来。

/npm/vue/dist/vue.js

<script src="../static/js/vue.js"></script>

使用 v-bind 绑定数据,绑定 button 的 value 为 sku.id,直接引用 sku 对象即可,不需要什么符号。

然后试着在 div 外部获取 button 的值:

$(function () {$('#cart').on('click', function () {var skuid=$('#cart').val();alert(skuid);

运行后成功获取到 skuid 值。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。