<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>
$("#btn1").bind("click",function(){
//EasyUI框架提供的js
$("#win1").window({
title:"弹出框",
width:400,
height:400,
modal:true //这是一个模式窗口,只能点击弹出框,不允许点击别处
})
})
<!--主要展现弹出框 -->
<a id="btn1" href="#" class="easyui-linkbutton" data-options="iconCls:'icon-search'">搜索</a>
<div id="win1">如果需要展现页面效果,则需要在指定的div中设计</div>
/*定义退出消息框 */
$("#btn4").click(function(){
$.messager.confirm('系统消息','你确定要XXX吗',function(r){
if (r){
alert("成功XXX!!!");
} else{
alert("下次再来!!!");
}
});
})
<div style="float: right">
<a id="btn4" href="#" class="easyui-linkbutton" data-options="iconCls:'icon-cancel'">退款</a>
</div>
<tr>
<td>商品类目:</td>
<td>
<a href="javascript:void(0)" class="easyui-linkbutton selectItemCat">选择类目</a>
<input type="hidden" name="cid" style="width: 280px;"></input>
</td>
</tr>
点击按钮,出现下面的弹出框(class=“easyui-linkbutton”)
// 初始化选择类目组件
initItemCat : function(data){
$(".selectItemCat").each(function(i,e){//i= index 下标,e:element:元素
var _ele = $(e);
if(data && data.cid){ //循环遍历
_ele.after(""+data.cid+"");
}else{
_ele.after("");
}
_ele.unbind('click').click(function(){
$("").css({padding:"5px"}).html(""
)
//下面几个药理解一下
.window({
width:'500',
height:"450",
modal:true,
closed:true, //是否可以被关闭
iconCls:'icon-save',
title:'选择类目',
onOpen : function(){ //当窗口打开后执行
var _win = this;
$("ul",_win).tree({
url:'/item/cat/list',
animate:true,
onClick : function(node){
if($(this).tree("isLeaf",node.target)){
// 填写到cid中
_ele.parent().find("[name=cid]").val(node.id);
_ele.next().text(node.text).attr("cid",node.id);
$(_win).window('close');
if(data && data.fun){
data.fun.call(this,node);
}
}
}
});
},
onClose : function(){
$(this).window("destroy");
}
}).window('open');
});
});
},
createEditor : function(select){
return KindEditor.create(select, TT.kingEditorParams);
},
1.3 商品分类数据表分析
1.3.1 业务表分析
/*一级商品分类信息 parent_id=0*/
SELECT * FROM tb_item_cat WHERE parent_id=0
/*二级商品分类信息 parent_id=0*/
SELECT * FROM tb_item_cat WHERE parent_id=1
/*三级商品分类信息 parent_id=0*/
SELECT * FROM tb_item_cat WHERE parent_id=24
1.4 EasyUI中树形结构分析
1.4.1页面数据展现
<body>
<h1>EasyUI-树形结构</h1>
<ul id="tree"></ul>
</body>
<script type="text/javascript">
/*通过js创建树形结构 */
$(function(){
$("#tree").tree({
url:"tree.json", //加载远程JSON数据
method:"get", //请求方式 POST
animate:true, //表示显示折叠端口动画效果
checkbox:true, //表述复选框
lines:true, //表示显示连接线
dnd:true, //是否拖拽
onClick:function(node){ //添加点击事件
//控制台
console.info(node);
}
});
})
</script>
tree.json—字符串
[
{
"id":"1",
"text":"英雄联盟",
"iconCls":"icon-save",
"children":[
{
"id":"4",
"text":"沙漠死神"
},{
"id":"5",
"text":"德玛西亚"
},{
"id":"6",
"text":"诺克萨斯之手"
},
{
"id":"7",
"text":"蛮族之王"
},
{
"id":"8",
"text":"孙悟空"
}
],
"state":"open" //默认打开
},{
"id":"2",
"text":"王者荣耀",
"children":[
{
"id":"10",
"text":"阿科"
},{
"id":"11",
"text":"吕布"
},{
"id":"12",
"text":"陈咬金"
},{
"id":"13",
"text":"典韦"
}
],
"state":"closed"
},
{
"id":"3",
"text":"吃鸡游戏",
"iconCls":"icon-save"
}
]
1.4.2数据结构分析
JSON串格式说明:[{“id”:“1”,“text”:“英雄联盟”,“state”:“open”,},{“id”:“2”,“text”:“王者联盟”,“state”:“closed”,}]
1.5 商品分类业务实现
1.5.1页面分析
- 页面url分析
1.5.2封装树形结构的VO对象
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true) //开启链式加载结构
public class EasyUITree{
//{"id":"1","text":"英雄联盟","iconCls":"icon-save",}
private Long id; //id值 与ItemCat中的Id一致的
private String text; //文本信息 与ItemCat中的name属性一致
private String state; //状态 打开:open 关闭:closed
}
1.5.3在ItemCatController中添加
/**
* 业务:查询商品分类信息,返回 VO对象
* url地址:http://localhost:8091/item/cat/list
* 参数:暂时没有
* 返回值: EsayUITree对象
* json格式:[{"id":"1","text":"英雄联盟","state":"open",},{"id":"2","text":"王者联盟","state":"closed",}]
* sql语句:1.查询一级商品分类信息: SELECT * FROM tb_item_cat WHERE parent_id=0
*/
@RequestMapping("/list")
public List<EasyUITree> findItemCatList() {
//1.查询一级商品分类信息
Long parentId = 0L;
return itemCatService.findItemCatByParentId(parentId);
}
1.5.4编辑ItemCatService
/**
* 数据的来源:数据库中
* 数据库中的数据类型:ItemCat对象信息
* 需要的类型: EasyUITree对象信息,VO对象
* 思路:将ItemCat转化为EasyUITree对象.
*/
@Override
public List<EasyUITree> findItemCatByParentId(Long parentId) {
//1.根据parentId查询数据库信息 根据父级查询子级信息.
QueryWrapper<ItemCat> queryWrapper=new QueryWrapper<ItemCat>();
queryWrapper.eq("parent_id", parentId);
List<ItemCat> itemCatList = itemCatMapper.selectList(queryWrapper);
//2.将数据库记录转化为VO数据
List<EasyUITree> treeList = new ArrayList<EasyUITree>(); //创建一个空集合用于返回数据
for (ItemCat itemCat : itemCatList) {
Long id=itemCat.getId();
String text=itemCat.getName();
//如果是父级标题,则默认关闭closed,否则开启,open
String state=itemCat.getIsParent()?"closed":"open";
EasyUITree uiTree =new EasyUITree(id,text,state);
treeList.add(uiTree);
}
return treeList;
}
1.5.5展示效果
1.5.6、实现树形结构(编辑Controller)
参数:暂时没有—>id:一级分类的Id值
@RequestMapping("/list")
public List<EasyUITree> findItemCatByParentId(Long id) {
//初始化时应该设置应该默认值.
//1.查询一级商品分类信息
Long parentId = id ==null?0L:id;
return itemCatService.findItemCatByParentId(parentId);
}
或者
@RequestMapping("/list")
public List<EasyUITree> findItemCatByParentId(@RequestParam(value = "id",defaultValue = "0")Long parentId) {
//初始化时应该设置应该默认值.
//1.查询一级商品分类信息
//Long parentId = id ==null?0L:id;
return itemCatService.findItemCatByParentId(parentId);
}
2商品信息后端维护
2.1新增商品
2.1.1页面分析
<div style="padding:10px 10px 10px 10px">
<form id="itemAddForm" class="itemForm" method="post">
<table cellpadding="5">
<tr>
<td>商品类目:</td>
<td>
<a href="javascript:void(0)" class="easyui-linkbutton selectItemCat">选择类目</a>
<input type="hidden" name="cid" style="width: 280px;"></input>
</td>
</tr>
<tr>
<td>商品标题:</td>
<td><input class="easyui-textbox" type="text" name="title" data-options="required:true" style="width: 280px;"></input></td>
</tr>
<tr>
<td>商品卖点:</td>
<td><input class="easyui-textbox" name="sellPoint" data-options="multiline:true,validType:'length[0,150]'" style="height:60px;width: 280px;"></input></td>
</tr>
<tr>
<td>商品价格:</td>
<td><input class="easyui-numberbox" type="text" name="priceView" data-options="min:1,max:99999999,precision:2,required:true" />
<input type="hidden" name="price"/>
</td>
</tr>
<tr>
<td>库存数量:</td>
<td><input class="easyui-numberbox" type="text" name="num" data-options="min:1,max:99999999,precision:0,required:true" /></td>
</tr>
<tr>
<td>条形码:</td>
<td>
<input class="easyui-textbox" type="text" name="barcode" data-options="validType:'length[1,30]'" />
</td>
</tr>
<tr>
<td>商品图片:</td>
<td>
<a href="javascript:void(0)" class="easyui-linkbutton picFileUpload">上传图片</a>
<input type="hidden" name="image"/>
</td>
</tr>
<tr>
<td>商品描述:</td>
<td>
<textarea style="width:800px;height:300px;visibility:hidden;" name="itemDesc"></textarea>
</td>
</tr>
<tr class="params hide">
<td>商品规格:</td>
<td>
</td>
</tr>
</table>
<input type="hidden" name="itemParams"/>
</form>
<div style="padding:5px">
<a href="javascript:void(0)" class="easyui-linkbutton" onclick="submitForm()">提交</a>
<a href="javascript:void(0)" class="easyui-linkbutton" onclick="clearForm()">重置</a>
</div>
</div>
function submitForm(){
//表单校验
if(!$('#itemAddForm').form('validate')){
$.messager.alert('提示','表单还未填写完成!');
return ;
}
//转化价格单位,将元转化为分 $("元素").val(100) 赋值操作 $("元素").val()取值
//eveal()专门做算术运算的封装体 - - ->
$("#itemAddForm [name=price]").val(eval($("#itemAddForm [name=priceView]").val()) * 100);
itemAddEditor.sync();//将输入的内容同步到多行文本中
var paramJson = [];
$("#itemAddForm .params li").each(function(i,e){
var trs = $(e).find("tr");
var group = trs.eq(0).text();
var ps = [];
for(var i = 1;i<trs.length;i++){
var tr = trs.eq(i);
ps.push({
"k" : $.trim(tr.find("td").eq(0).find("span").text()),
"v" : $.trim(tr.find("input").val())
});
}
paramJson.push({
"group" : group,
"params": ps
});
});
paramJson = JSON.stringify(paramJson);//将对象转化为json字符串
$("#itemAddForm [name=itemParams]").val(paramJson);
/*
参数类型:
1.{"key":"value","key2":"value2",.......} 少量数据提交
2.key=value&key2=value2...... 基于字符串拼接,少量数据提交
js表单常用方法:(海量数据)
3.($("#itemAddForm").serialize()); 将所有的from表单中的数据,采用字符串的形式自动拼接之后提交
关于回调函数业务说明
需求:确定后端服务器调用是否正确!!!
策略说明:
属性1:status==200 调用正确 status==201 调用失败
属性2:msg 提交服务器相关说明信息
属性3: data 服务器返回页面的业务数据 一般都是对象的JSON.
*/
//$.post/get((地址)url,(提交参数信息)JSON,(回调函数)function(data){....})
//alert($("#itemAddForm").serialize());
$.post("/item/save",$("#itemAddForm").serialize(), function(data){
if(data.status == 200){
$.messager.alert('提示','新增商品成功!');
}else{
$.messager.alert("提示","新增商品失败!");
}
});
}
2.1.2封装VO对象
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true) //开启链式加载结构
public class SysResult {
/** 策略说明:
* 属性1:status==200 调用正确 status!=200 调用失败
* 属性2:msg 提交服务器相关说明信息
* 属性3: data 服务器返回页面的业务数据 一般都是对象的JSON.
*
*/
private Integer Status;
private String msg;
private Object data;
//准备工具API 方便用户调用
public static SysResult fail() {
return new SysResult(201,"业务调用失败",null);
}
//成功方式1.需要返回服务器数据data
public static SysResult success() {
return new SysResult(200,"业务调用成功",null);
}
//成功方式2.需要返回服务器数据data
public static SysResult success(Object data) {
return new SysResult(200,"业务调用成功",data);
}
//成功方式3.可能告知服务器信息及服务器
public static SysResult success(String msg,Object data) {
return new SysResult(200,msg,data);
}
}
2.1.3编辑ItemController
/**
* 业务:商品的新增操作
* url:/item/save
* 参数:from表单数据
* 返回值结果:SysResult对象
*/
@RequestMapping("/save")
public SysResult saveItem(Item item) {
try {
itemService.saveItem(item);
return SysResult.success();
}catch(Exception e) {
e.printStackTrace(); //打印错误信息
return SysResult.fail();
}
}
2.1.4编辑ItemServiceImpl
@Transactional //控制数据库事务
@Override
public void saveItem(Item item) {
item.setStatus(1)
.setCreated(new Date())
.setUpdated(item.getCreated());
itemMapper.insert(item);
}
2.2全局异常处理机制
2.2.1说明
代码中频繁出现cry{}catch,则可能影响代码结构. 不便于阅读. 能否利用全局的异常的捕获机制,简化try-catch个数
捕获位置: 常规捕获的位置是Controller层,因为Controller层是业务调用的最后的控制层.
2.2.2实现
//表示该类是全局异常处理机制类
@RestControllerAdvice //advice-->通知 Rest-->返回的数据都是json串
@Slf4j //添加日志
public class SystemExceptionAOP {
/*
* 添加通用的异常返回的方法
* 底层原理:AOP的异常通知
*/
@ExceptionHandler(RuntimeException.class) //拦截运行时异常
public Object systemResultException(Exception e) {
e.printStackTrace(); //如果有问题,则直接在控制台打印
log.error("{~~~业务调用异常~~~}",e);
return SysResult.fail(); //返回统一的失败数据
}
}
2.3商品修改
2.3.1修改提交页面分析
- 定义弹出框位置
<div id="itemEditWindow" class="easyui-window" title="编辑商品" data-options="modal:true,closed:true,iconCls:'icon-save',href:'/page/item-edit'" style="width:80%;height:80%;padding:10px;"></div>
- 点击编辑按钮效果
{
text:'编辑',
iconCls:'icon-edit',
handler:function(){
//获取用户选中的数据
var ids = getSelectionsIds();
if(ids.length == 0){
$.messager.alert('提示','必须选择一个商品才能编辑!');
return ;
}
//通过","号判断用户选择几个
if(ids.indexOf(',') > 0){
$.messager.alert('提示','只能选择一个商品!');
return ;
}
//做完校验之后,执行弹出框操作,之后跳转到商品修改页面href:'/page/item-edit'"
$("#itemEditWindow").window({
...}
- 修改页面js
$("#itemeEditForm [name=itemParams]").val(paramJson);
//alert($("#itemeEditForm").serialize());
$.post("/item/update",$("#itemeEditForm").serialize(), function(data){
if(data.status == 200){
$.messager.alert('提示','修改商品成功!','info',function(){
$("#itemEditWindow").window('close');
$("#itemList").datagrid("reload");
});
}else{
$.message.alert("提示",data.msg);
}
});
2.3.2编辑ItemController
/**
* 业务:商品的修改操作
* url:/item/update
* 参数:from表单数据
* 返回值结果:SysResult对象
*/
@RequestMapping("/update")
public SysResult updateItem(Item item) {
itemService.updateItem(item);
return SysResult.success();
}
2.3.2编辑ItemServiceImpl
@Transactional //控制数据库事务
@Override
public void updateItem(Item item) {
item.setCreated(new Date());
itemMapper.updateById(item);
}
2.4商品删除
2.4.1编辑ItemController
/**
* 业务:商品的删除操作
* url:http://localhost:8091/item/delete
* 参数:from表单数据
* 返回值结果:SysResult对象
*/
@RequestMapping("/delete")
public SysResult deleteItem(Integer... ids) {
itemService.deleteItem(ids);
return SysResult.success();
}
2.4.2编辑ItemServiceImpl
@Transactional //控制数据库事务
@Override
public void deleteItem(Integer[] ids) {
itemMapper.deleteBatchIds(Arrays.asList(ids));
}
2.5上架下架
2.5.1编辑ItemController
/**
* 业务:商品的上架/下架操作
* url:/item/reshelf(instock)
* 参数:from表单数据
* 返回值结果:SysResult对象
*/
@RequestMapping("/reshelf")
public SysResult reshelfItem(Long[] ids) {
itemService.reshelfItem(ids);
return SysResult.success();
}
@RequestMapping("/instock")
public SysResult instockItem(Long[] ids) {
itemService.instockItem(ids);
return SysResult.success();
}
2.5.2编辑ItemServiceImpl
@Transactional //控制数据库事务
@Override
public void reshelfItem(Long[] ids) {
Item item=new Item();
item.setStatus(1)
.setUpdated(new Date());
//2.定义条件构造器
UpdateWrapper<Item> updateWrapper =new UpdateWrapper<>();
updateWrapper.in("id", Arrays.asList(ids));
itemMapper.update(item, updateWrapper);
}
@Transactional //控制数据库事务
@Override
public void instockItem(Long[] ids) {
Item item=new Item();
item.setStatus(2)
.setUpdated(new Date());
//2.定义条件构造器
UpdateWrapper<Item> updateWrapper =new UpdateWrapper<>();
updateWrapper.in("id", Arrays.asList(ids));
itemMapper.update(item, updateWrapper);
}
2.5.3将上架下架合并
@RequestMapping("/status")
public SysResult statusItem(Long[] ids) {
itemService.statusItem(ids);
return SysResult.success();
}
@Transactional //控制数据库事务
@Override
public void statusItem(Long[] ids) {
Item item=new Item();
Integer status;
for (Long id : ids) {
item= itemMapper.selectById(id);
status=item.getStatus();
//Item item=new Item();
status=status==1?2:1; //status=1则改为2,,!=1则改为1
item.setStatus(status).setUpdated(new Date()); //设置状态和更新时间
itemMapper.updateById(item);
}
最后再加一个按钮
{
text:'上/下架',
iconCls:'icon-remove',
handler:function(){
//获取选中的ID串中间使用","号分割
var ids = getSelectionsIds();
if(ids.length == 0){
$.messager.alert('提示','未选中商品!');
return ;
}
$.messager.confirm('确认','确定上/下架ID为 '+ids+' 的商品吗?',function(r){
if (r){
var params = {"ids":ids,"status":status};
$.post("/item/status",params, function(data){
if(data.status == 200){
$.messager.alert('提示','上/下架商品成功!',undefined,function(){
$("#itemList").datagrid("reload");
});
}
});
}
});
}
}