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

一、后台管理

采用左边栏多级菜单的形式,前端页面如下:
在这里插入图片描述

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 属性会作为微服务的名称,用于服务发现。也就是说,对应的路径是 在哪个微服务里,就写哪个微服务的名称。 否则报错 :

com.netflix.client.ClientException: Load balancer does not have available server for client: admin 	at com.netflix.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 的依赖,可以使用网址,也可以下到自己的项目中来。
https://cdn.jsdelivr.net/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 值。

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值