1. 商品分类信息回显
1.1 数据格式化问题
1.1.1 Item POJO说明
1.1.2 common.js是如何被item-list.jsp所引用的???
说明: 由于用户默认的首页访问的是Index.jsp,在其中引入js
<jsp:include page="/commons/common-js.jsp"></jsp:include>
配置如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<link rel="stylesheet" type="text/css" href="/js/jquery-easyui-1.4.1/themes/default/easyui.css" />
<link rel="stylesheet" type="text/css" href="/js/jquery-easyui-1.4.1/themes/icon.css" />
<link rel="stylesheet" type="text/css" href="/css/jt.css" />
<script type="text/javascript" src="/js/jquery-easyui-1.4.1/jquery.min.js"></script>
<script type="text/javascript" src="/js/jquery-easyui-1.4.1/jquery.easyui.min.js"></script>
<script type="text/javascript" src="/js/jquery-easyui-1.4.1/locale/easyui-lang-zh_CN.js"></script>
<!-- 自己实现业务逻辑 -->
<script type="text/javascript" src="/js/common.js"></script>
补充说明: 由于item-list.jsp页面是index.jsp中的一部分.所以父级引入JS.子级也可以使用JS.
1.1.2 格式化价格
1).页面标识符
formatter 属性是EasyUI中专门负载格式化数据的函数.通过调用js.将返回值的结果进行展现.
传递参数时会传递2个参数. 一个是当前标签的值value.当前标签所在的行号.
<th data-options="field:'price',width:70,align:'right',formatter:KindEditorUtil.formatPrice">价格</th>
格式化函数介绍:
// 格式化价格
formatPrice : function(val,row){
return (val/100).toFixed(2);
},
1.1.3 格式化状态
1.页面JS函数调用
<th data-options="field:'status',width:60,align:'center',formatter:KindEditorUtil.formatItemStatus">状态</th>
2.js编辑说明
// 格式化商品的状态
formatItemStatus : function formatStatus(val,row){
if (val == 1){
return '<span style="color:green;">上架</span>';
} else if(val == 2){
return '<span style="color:red;">下架</span>';
} else {
return '未知';
}
},
1.2 商品分类回显
1.2.1 页面结构分析
需求说明: 如果在没有进行格式化时.展现的是商品分类的ID号.如图:
需要通過格式化的函数,动态获取商品分类的名称,之后进行页面展现.
1.2.2 页面实现说明
1.利用格式化的函数的调用 向后端发送ajax请求.获取商品分类的名称
2.创建商品分类的POJO对象 ItemCat对象
3.创建ItemCatMapper 接口
4.实现通过数据库查询返回itemCat的name属性.
1.2.3 标识页面ajax
//格式化名称
findItemCatName : function(val,row){
var name;
$.ajax({
type:"post",
url:"/item/cat/queryItemName",
data:{itemCatId:val},
cache:true, //缓存
async:false, //表示同步 默认的是异步的true
dataType:"text",//表示返回值参数类型
success:function(data){ //返回商品分类名称
name = data;
}
});
return name;
},
1.2.4 编辑ItemCat POJO对象
package com.jt.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.experimental.Accessors;
@TableName("tb_item_cat")
@Data
@Accessors(chain = true)
public class ItemCat extends BasePojo{
@TableId(type = IdType.AUTO)
private Long id;
private Long parentId; // 父级ID
private String name; //分类名称
private Integer status; //状态信息
private Integer sortOrder; //排序号
private Boolean isParent; //是否为父级.
}
1.2.5 编辑ItemCatController
package com.jt.controller;
import com.jt.service.ItemCatService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/item/cat") //请求业务名称
public class ItemCatController {
@Autowired
private ItemCatService itemCatService;
/**
* 分析业务: 通过itemCatId获取商品分类的名称
* 1.url地址: url:"/item/cat/queryItemName",
* 2.参数: {itemCatId:val},
* 3.返回值: 商品分类名称 String
*/
@RequestMapping("/queryItemName")
public String findItemCatName(Long itemCatId){
return itemCatService.findItemCatNameById(itemCatId);
}
}
1.2.6 编辑ItemCatService
package com.jt.service;
import com.jt.mapper.ItemCatMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class ItemCatServiceImpl implements ItemCatService{ //alt +shift+p
@Autowired
private ItemCatMapper itemCatMapper;
@Override
public String findItemCatNameById(Long itemCatId) {
return itemCatMapper.selectById(itemCatId).getName();
}
}
1.2.7 页面效果展现
1.2.8 Ajax嵌套问题
说明:如果在页面中涉及到ajax嵌套问题,一般的解决的方法就是将内层的ajax设置为同步模式.可以正确的展现数据.
2. 商品分类树形结构展现
2.1 弹出框效果说明
$("#btn1").bind("click",function(){
$("#win1").window({
title:"弹出框",
width:400,
height:400,
modal:true //这是一个模式窗口,只能点击弹出框,不允许点击别处
})
})
2.2 商品分类数据结构分析
说明:一般电商网址的商品分类信息一般都是3级菜单. 级与级之间存在父子级关系. 在数据库中应该如何存储???
解答: 一般涉及到父子级关系时,一般采用parentId的形式进行关联.
例如: 查询一级商品分类信息:
/*查询一级商品分类信息 父级Id=0*/
select * from tb_item_cat where parent_id=0;
/*查询二级商品分类信息 父级一级ID*/
SELECT * FROM tb_item_cat WHERE parent_id=1;
/*查询三级商品分类信息 父级二级ID*/
SELECT * FROM tb_item_cat WHERE parent_id=2;
2.3 树形结构分析
2.3.1 页面分析
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>EasyUI-3-菜单按钮</title>
<script type="text/javascript"
src="/js/jquery-easyui-1.4.1/jquery.min.js"></script>
<script type="text/javascript"
src="/js/jquery-easyui-1.4.1/jquery.easyui.min.js"></script>
<script type="text/javascript"
src="/js/jquery-easyui-1.4.1/locale/easyui-lang-zh_CN.js"></script>
<link rel="stylesheet" type="text/css"
href="/js/jquery-easyui-1.4.1/themes/icon.css" />
<link rel="stylesheet" type="text/css"
href="/js/jquery-easyui-1.4.1/themes/default/easyui.css" />
<script type="text/javascript">
/*通过js创建树形结构 */
$(function(){
$("#tree").tree({
url:"tree.json", //加载远程JSON数据 ajax请求
method:"get", //请求方式 POST
animate:false, //表示显示折叠端口动画效果
checkbox:true, //表述复选框
lines:true, //表示显示连接线
dnd:true, //是否拖拽
onClick:function(node){ //添加点击事件
//控制台
console.info(node);
}
});
})
</script>
</head>
<body>
<h1>EasyUI-树形结构</h1>
<!-- ul-li 定义树形结构-->
<ul id="tree"></ul>
</body>
</html>
2.3.2 关于树形结构JSON串返回值分析
[
{
"id":"3",
"text":"吃鸡游戏",
"state":"open"
}
]
2.3.3 封装EasyUITree VO对象
package com.jt.vo;
import lombok.Data;
import lombok.experimental.Accessors;
//该对象的主要的目的是为了展现树形结构的数据.
@Data
@Accessors(chain = true)
public class EasyUITree implements Serializable{
//"id":"3","text":"吃鸡游戏","state":"open/closed" 数据来源 数据表
private Long id; //商品分类的Id信息
private String text; //商品分类name属性
private String state; //由是否为父级决定 如果是父级则关闭closed 否则为子级open
}
2.3.3 商品分类展现页面说明
2.3.4 编辑ItemCatController
/**
* 业务需求: 实现商品分类的展现
* url地址: http://localhost:8091/item/cat/list
* 参数: parentId = 0 查询一级商品分类菜单.
* 返回值结果: List<EasyUITree>
*/
@RequestMapping("/list")
public List<EasyUITree> findItemCatList(){
Long parentId = 0L;
return itemCatService.findItemCatList(parentId);
}
2.3.5 编辑ItemCatService
/**
* 思路:
* 1.通过parentId查询数据库信息,返回值结果List<ItemCat>
* 2.将ItemCat信息转化为EasyUITree对象
* 3.返回的是List<EasyUITree>
* @param parentId
* @return
*/
@Override
public List<EasyUITree> findItemCatList(Long parentId) {
//1.根据父级分类Id查询数据
QueryWrapper<ItemCat> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("parent_id", parentId);
List<ItemCat> catList = itemCatMapper.selectList(queryWrapper);
//2.需要将数据进行转化. cartList遍历 封装EasyUITree 添加到集合中即可
List<EasyUITree> treeList = new ArrayList<>();
for (ItemCat itemCat: catList){
Long id = itemCat.getId();
String text = itemCat.getName();
//是父级就打开 否则关闭
String state = itemCat.getIsParent()?"closed":"open";
EasyUITree easyUITree = new EasyUITree(id, text, state);
//3.封装返回值数据
treeList.add(easyUITree);
}
return treeList;
}
2.3.6 页面效果展现
2.3.7 商品查询url参数分析
2.3.8 异步树控件加载
树控件读取URL。子节点的加载依赖于父节点的状态。当展开一个封闭的节点,如果节点没有加载子节点,它将会把节点id的值作为http请求参数并命名为’id’,通过URL发送到服务器上面检索子节点。
总结:当展现了树形结构之后,当展开树形节点时会向后台传递该节点的id值格式如下 id:100
/**
* 业务需求: 实现商品分类的展现
* url地址: http://localhost:8091/item/cat/list
* 参数: parentId = 0 查询一级商品分类菜单.
* 返回值结果: List<EasyUITree>
*/
@RequestMapping("/list")
public List<EasyUITree> findItemCatList(Long id){
//当初始时树形结构没有加载不会传递ID,所以ID为null.只需要传递0.
Long parentId = (id==null)?0:id;
return itemCatService.findItemCatList(parentId);
}
3.商品后台维护
3.1 定义系统返回值VO对象
3.1.1 业务说明
由于业务处理一般都会通过JSON串的形式告知客户端程序是否完成.所以一般情况下都会通过vo对象来返回回执信息,
一般情况下VO对象需要返回业务是否正确/业务处理信息/业务处理数据.
3.1.2 封装SysResultVO对象
package com.jt.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class SysResult implements Serializable {
private Integer status; //定义状态信息 200业务处理成功, 201业务处理失败.
private String msg; //服务器返回的提示信息.
private Object data; //服务器返回业务数据.
//封装一些静态API 简化用户调用过程.
public static SysResult fail(){
return new SysResult(201,"服务器调用失败",null);
}
public static SysResult success(){
return new SysResult(200, "业务执行成功!!!", null);
}
public static SysResult success(Object data){
return new SysResult(200, "业务执行成功!!!", data);
}
}
3.2 商品新增
3.2.1 页面URL分析
1).url请求地址
2).页面提交参数
3).页面AJAX展现形式
<a href="javascript:void(0)" class="easyui-linkbutton" onclick="submitForm()">提交</a>
// ajax参数提交方式1json方式 $.post("/xx/xx",{key:value,key2:value2},回调函数)
// ajax参数提交方式1json方式 $.post("/xx/xx",key=value&key2=value....,回调函数)
// jQuery中提供了函数serialize() 将整个表单的数据封装为key=value&key2=value2的形式..
//alert($("#itemAddForm").serialize());
$.post("/item/save",$("#itemAddForm").serialize(), function(data){
if(data.status == 200){
$.messager.alert('提示','新增商品成功!');
}else{
$.messager.alert("提示","新增商品失败!");
}
});
3.2.2 编辑ItemController
/**
* 业务需求: 完成商品入库操作,返回系统vo对象
* url1: /item/save
* 参数: 整个form表单
* 返回值: SysResult对象
*/
@RequestMapping("save")
public SysResult saveItem(Item item){
//全局异常的处理机制!!!!
try {
itemService.saveItem(item);
return SysResult.success();
}catch (Exception e){
e.printStackTrace();
return SysResult.fail();
}
}
3.2.3 编辑ItemService
@Transactional //控制事务
@Override
public void saveItem(Item item) {
//1.默认商品为上架状态
item.setStatus(1).setCreated(new Date()).setUpdated(new Date());
itemMapper.insert(item);
}
3.3 全局异常处理机制
3.3.1 作用
如果在每个方法中添加异常处理机制,则会导致整个代码的结构混乱.即使将来出现了异常,也不能很好的管理.所以需要一种统一的方式实现异常的处理.
该功能在Spring中利用AOP的方式实现.
3.3.2 创建全局异常处理
package com.jt.aop;
import com.jt.vo.SysResult;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice //作用: 标识我是一个通知方法,并且只拦截Controll层的异常.并且返回JSON.
public class SysResultException {
//需要定义一个全局的方法 返回指定的报错信息.
//ExceptionHandler 配置异常的类型,当遇到了某种异常时在执行该方法.
@ExceptionHandler(RuntimeException.class)
public Object exception(Exception e){
e.printStackTrace(); //日志记录/控制台输出. 让程序员知道哪里报错!!!
return SysResult.fail();
}
}