- 視頻教程:【黑馬程序員】Java大型電商項目—品優購【配套源碼+筆記】_嗶哩嗶哩_bilibili
- 源碼下載:??
- 鏈接:https://pan.baidu.com/s/1fECz5In_XCB-aW6ed6ZTbA?
- 提取碼:27xa?
技術選型:
后端框架:Spring+SpringMVC+mybatis+Dubbox
前端:angularJS+Bootstrap
- 分布式:Dubbox框架
- 注冊中心:Zookeeper
前端出錯,先清理一下瀏覽器的緩存,再刷新一下頁面,,還是報錯,再去看代碼?
第一部分?
運行環境
1、linux虛擬機
- 運行linux虛擬機
- 打開linux的終端,不可關閉虛擬機
- 打開SecureCRT代替linux的終端寫命令,更清楚
- 啟動zookeeper
- cd
- cd zookeeper-3.4.6
- cd bin
- ./zkServer.sh start
- ./zkServer.sh status 查看zookeeper運行狀態,是否開啟了
- 每次重啟虛擬機,ip地址會發生變化,所以把虛擬機掛起就行,不用關機
- 查看ip地址的命令:ifconfig
- 如果ip地址變化,則相應地修改springmvc.xml文件里的zookeeper信息。2181是zookeeper的默認端口,如果配置文件里沒有改動,就不變
- 后續寫代碼時,在瀏覽器訪問html文件時,不報錯,但就是不顯示表格,除了表格什么都正常,很難排錯。后來發現是zookeeper的端口發生了變化,但是代碼里沒有修改過來。
2、mysql數據庫
- mysql如何導入.sql文件:http://t.csdnimg.cn/mhP9M
- 保持打開狀態,才可運行其他代碼
后端:在IDEA上搭建工程
1、先建父工程,后建子模塊
- ? ? ? ? ? ? ? ?
2、引入依賴
- 主要問題:
- 有些依賴maven的本地倉庫里沒有,需要手動導入
- 解決教程:http://t.csdnimg.cn/m4fCs
- 有些依賴的版本需要修改,比如dubbo的2.8.4版本已經不維護了,要改成2.5.3;還有mysql的版本也要和自己電腦里8.0版本的mysql相對應,不能用5.0版本的。
- 解決辦法:只需對著pom.xml文件里的依賴在maven的本地倉庫里逐個尋找,把爆紅的依賴版本改成倉庫里現有的依賴版本
- 父工程的pom.xml文件需要手動導入的jar包命令如下
? ? ? ? mvn install:install-file-Dfile=D:\各種jar包\fastdfs-client-java-1.29.jar-DgroupId=org.csource-DartifactId=fastdfs-client-java-Dversion=1.29?-Dpackaging=jar
? ? ? ? mvn install:install-file-Dfile=D:\各種jar包\spring-security-cas-4.1.0.RELEASE.jar-DgroupId=org.springframework.security-DartifactId=spring-security-cas-Dversion=4.1.0.RELEASE-Dpackaging=jar
?? ? ? ? mvn install:install-file-Dfile=D:\各種jar包\cas-client-core-3.5.1.jar-DgroupId=org.jasig.cas.client-DartifactId=cas-client-core-Dversion=3.3.3-Dpackaging=jar
? ? ? ? mvn install:install-file-Dfile=D:\各種jar包\kaptcha-2.3.2.jar-DgroupId=com.github.penggle-DartifactId=kaptcha-Dversion=2.3.2?-Dpackaging=jar
? ? ? ? mvn install:install-file-Dfile=D:\各種jar包\solr-solrj-4.10.3.jar-DgroupId=org.apache.solr-DartifactId=solr-solrj-Dversion=4.10.3-Dpackaging=jar
? ? ? ? mvn install:install-file-Dfile=D:\各種jar包\activemq-all-5.11.2.jar-DgroupId=org.apache.activemq-DartifactId=activemq-all-Dversion=5.11.2?-Dpackaging=jar
????????mvn install:install-file-Dfile=D:\各種jar包\ikanalyzer-2012_u6.jar-DgroupId=com.janeluo-DartifactId=ikanalyzer-Dversion=2012_u6-Dpackaging=jar
3、逆向工程
- 目的:實現實體類與數據訪問層代碼的自動生成
- 老師發的資料里沒有逆向工程的最新代碼,把舊的代碼修改一下,即可用,具體代碼已放資源里
- 修改的地方主要有
- 1、mapper映射文件的生成位置
<!-- targetProject:mapper映射文件生成的位置 --><sqlMapGenerator targetPackage="com.pinyougou.mapper" targetProject=".\src\main\resources"><!-- enableSubPackages:是否讓schema作為包的后綴 --><property name="enableSubPackages" value="false" /></sqlMapGenerator>
- 2、數據庫的連接密碼
逆向代碼運行教程:http://t.csdnimg.cn/Qt5ti
沒有逆向工程源碼也行,直接從老師發的資料里其他源碼里拿到pojo包,接口包和mapper映射文件包三個包即可
容易出現的問題:逆向工程的代碼生錯了,要仔細辨別?
4、編寫后端代碼
- 注意@Service和@Refrence(遠程調用)注解引入要用dubbo的,否則會注入失敗,報空指針異常
- import com.alibaba.dubbo.config.annotation.Reference;
- import com.alibaba.dubbo.config.annotation.Service;
5、測試
- 地址:http://localhost:9101/brand/findAll.do
- 錯誤一:
- 解決辦法:http://t.csdnimg.cn/ZnSSP
- 修改了db.properties文件里的jdbc.url和jdbc.driver
jdbc.driver=com.mysql.cj.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/pinyougoudb?serverTimezone=Asia/Shanghai&characterEncoding=utf-8&useSSL=false
- 然后把pinyougou-dao該重新clean和install,真正修改完數據庫文件后,再運行
- 測試成功后
- 測試這里出了很多錯,無奈之下,把項目又重新做了一遍,發現父工程的依賴無法爆紅,無法正常導入;逆向工程代碼出錯了;zookeeper的ip地址也有變化;數據庫的相關配置也沒有修改完全,修改后又沒有更新到數據庫配置文件里……想過很多次放棄,但也沒有更好的選擇,所以還是堅持下來了,最大的收獲還是可以靜下心來好好分析報錯信息了。
前端:框架AngularJS
四大特性
- 1、MVC模式
- 2、雙向綁定
- 3、依賴注入
- 4、模塊化設計
基本內容
- 表達式
<html> <head><title>angularJS demo 表達式</title><script src="angular.min.js"></script> </head> <body ng-app> {{100+100}} </body> </html>
- 雙向綁定
<html> <head><title>angularJS demo 雙向綁定</title><script src="angular.min.js"></script> </head> <body ng-app> 請輸入你的名稱:<input ng-model="myname"> {{myname}},你好 </body> </html>
- 初始化指令
<html> <head><title>angularJS demo 初始化指令</title><script src="angular.min.js"></script> </head> <body ng-app ng-init="myname='abc'"> 請輸入你的名稱:<input ng-model="myname"> {{myname}},你好 </body> </html>
- 控制器
<html> <head><title>angularJS demo 控制器</title><script src="angular.min.js"></script><script>// 定義一個名為myApp的模塊,下面的<body>塊內的代碼都屬于該模塊var app=angular.module("myApp",[]);// 定義控制器,可以控制頁面的某個功能// $scope在視圖和控制器之間建立了一個通道,雙向更新app.controller("myController",function($scope){$scope.add=function(){//parseInt把字符串類型轉換成數值類型return parseInt($scope.x)+parseInt($scope.y);}});</script> </head> <body ng-app="myApp" ng-controller="myController"> <!--輸入綁定變量x--> x:<input ng-model="x"> <!--輸入綁定變量y--> y:<input ng-model="y"> <!--在頁面顯示x+y的結果add--> {{add()}} </body> </html>
- 事件指令
<html> <head><title>angularJS demo 事件指令</title><script src="angular.min.js"></script><script>var app=angular.module("myApp",[]);app.controller("myController",function($scope){$scope.add=function(){$scope.z=parseInt($scope.x)+parseInt($scope.y);}});</script> </head> <body ng-app="myApp" ng-controller="myController"> x:<input ng-model="x"> y:<input ng-model="y"> <!--點擊“運算”按鈕后,觸發add()方法,輸出x+y的結果--> <button ng-click="add()">運算</button> {{z}} </body> </html>
- 循環數組
<html> <head><title>angularJS demo 循環數組</title><script src="angular.min.js"></script><script>var app=angular.module("myApp",[]);app.controller("myController",function($scope){$scope.list=[100,200,300,400];});</script> </head> <body ng-app="myApp" ng-controller="myController"> <!-- 利用循環把list里的元素打印到表格中--><table><tr ng-repeat="x in list"><td>{{x}}</td></tr></table> </body> </html>
- 循環對象數組
<html> <head><title>angularJS demo 循環對象數組</title><script src="angular.min.js"></script><script>var app=angular.module("myApp",[]);app.controller("myController",function($scope){$scope.list=[{name:"張三",chinese:1,math:1},{name:"李四",chinese:2,math:2},{name:"王五",chinese:3,math:3},{name:"趙六",chinese:4,math:4}];});</script> </head> <body ng-app="myApp" ng-controller="myController"><table><tr ng-repeat="x in list"><td>{{x.name}}</td><td>{{x.chinese}}</td><td>{{x.math}}</td></tr></table> </body> </html>
- 內置服務
<html> <head><title>angularJS demo 內置服務</title><meta charset="utf-8"><script src="angular.min.js"></script><script>var app=angular.module("myApp",[]);// $http從后端獲取數據,數據修改更靈活app.controller("myController",function($scope,$http){$scope.findList=function(){$http.get("data.json").success(function(response){$scope.list=response;});}});</script> </head> <!--初始化時,順便觸發findList()方法--> <body ng-app="myApp" ng-controller="myController" ng-init="findList()"><table><tr ng-repeat="x in list"><td>{{x.name}}</td><td>{{x.chinese}}</td><td>{{x.math}}</td></tr></table> </body> </html>
//json數據 [ // key用雙引號括起,value若是字符串也要用雙引號括起{"name":"張三","chinese":1,"math":1},{"name":"李四","chinese":2,"math":2},{"name":"王五","chinese":3,"math":3},{"name":"趙六","chinese":4,"math":4} ]
常用指令
- ng-app:定義AngularJS應用程序的根元素
- ng-model:用于綁定變量(輸入端和變量端,雙向綁定)
- ng-init:初始化變量
- ng-controller:用于指定所用控制器
- ng-click:單擊事件指令,點擊時觸發控制器的某個方法
- ng-repeat:用于循環數組變量
第二部分(實現功能)
品牌列表分頁
1、后端
PageResult
pinyougou-pojo模塊
package entity;import java.io.Serializable;
import java.util.List;/*** 分布結果實體類* 模塊:pinyougou-pojo* 路徑:src/main/java/entity*/
public class PageResult implements Serializable {private long total;//記錄總條數private List rows;//當面頁記錄//getter,setter方法和構造器省略
}
BrandService
pinyougou-sellergoods-interface模塊
package com.pinyougou.sellergoods.service;import com.pinyougou.pojo.TbBrand;
import entity.PageResult;import java.util.List;/*** 品牌業務接口*/
public interface BrandService {/*** 分布查詢* @param pageNum* @param pageSize* @return*/public PageResult findPage(int pageNum,int pageSize);
}
?BrandServiceImpl
pinyougou-sellergoods-service模塊
package com.pinyougou.sellergoods.service.impl;import com.alibaba.dubbo.config.annotation.Service;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.pinyougou.mapper.TbBrandMapper;
import com.pinyougou.pojo.TbBrand;
import com.pinyougou.sellergoods.service.BrandService;
import entity.PageResult;
import org.springframework.beans.factory.annotation.Autowired;import java.util.List;/*** 品牌服務層實現類*/
@Service
public class BrandServiceImpl implements BrandService {/*** 分頁的服務層代碼* @param pageNum* @param pageSize* @return*/@Overridepublic PageResult findPage(int pageNum, int pageSize) {PageHelper.startPage(pageNum,pageSize);//分頁插件Page<TbBrand> page=(Page<TbBrand>)brandMapper.selectByExample(null);//使用分頁可以簡化前端工作量,不必返回全部內容return new PageResult(page.getTotal(),page.getResult());}
}
BrandController
pinyougou-manager-web模塊
package com.pinyougou.manager.controller;import com.alibaba.dubbo.config.annotation.Reference;
import com.pinyougou.pojo.TbBrand;
import com.pinyougou.sellergoods.service.BrandService;
import entity.PageResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.List;/*** 品牌的控制器層*/
public class BrandController {@RequestMapping("/findPage")public PageResult findPage(int page,int rows){return brandService.findPage(page,rows);}
}
?父工程重新install后,運行結果:
2、前端?
<!DOCTYPE html>
<html>
<head><!--導入資源--><script src="../plugins/jQuery/jquery-2.2.3.min.js"></script><script src="../plugins/bootstrap/js/bootstrap.min.js"></script><script src="../plugins/angularjs/angular.min.js"></script><!--分頁組件開始--><script src="../plugins/angularjs/pagination.js"></script><link rel="stylesheet" href="../plugins/angularjs/pagination.css"><!--分頁組件結束--><script>//定義名為app的模塊var app=angular.module("pinyougou",["pagination"]);app.controller("brandController",function ($scope,$http) {//讀取列表數據綁定到表單中// $scope.findAll=function () {// $http.get("../brand/findAll.do").success(function(response){// $scope.list=response;// })//// }//分頁$scope.findPage=function(page,rows) {$http.get("../brand/findPage.do?page="+page+"&rows="+rows).success(function(response){$scope.list=response.rows;$scope.paginationConf.totalItems=response.total;//定義總記錄數})}//定義對象paginationConf,分布的配置$scope.paginationConf={currentPage: 1,//當前頁totalItems: 10,//總記錄條數itemsPerPage: 10,//每頁的記錄條數perPageOptions: [10,20,30,40,50],//頁碼選項,每頁10條還是20還是...onChange: function () {//當頁碼發生變化時自動觸發的方法$scope.reloadList();}}//重新加載記錄$scope.reloadList=function () {$scope.findPage($scope.paginationConf.currentPage,$scope.paginationConf.itemsPerPage);}})</script></head>
<body class="hold-transition skin-red sidebar-mini" ng-app="pinyougou" ng-controller="brandController" ng-init="findAll()"><!-- .box-body --><!-- 數據表格 --><div class="table-box"><!--數據列表--><table id="dataList" class="table table-bordered table-striped table-hover dataTable"><!--表體--><tbody><!--使用循環填寫表格--><tr ng-repeat="entity in list"><td><input type="checkbox" ></td> <td>{{entity.id}}</td><td>{{entity.name}}</td><td>{{entity.firstChar}}</td><td class="text-center"> <button type="button" class="btn bg-olive btn-xs" data-toggle="modal" data-target="#editModal" >修改</button> </td></tr></tbody></table><!--數據列表/--><!--在數據表格下放置分頁組件,那個分頁的小欄--><tm-pagination conf="paginationConf"></tm-pagination> </div><!-- 數據表格 /--> </div>
</body>
</html>
運行結果:
增加品牌
1、后端?
BrandService
pinyougou-sellergoods-interface
package com.pinyougou.sellergoods.service;import com.pinyougou.pojo.TbBrand;
import entity.PageResult;import java.util.List;/*** 品牌業務接口*/
public interface BrandService {/*** 增加品牌* @param brand*/public void add(TbBrand brand);
}
BrandServiceImpl
pinyougou-sellergoods-service
package com.pinyougou.sellergoods.service.impl;import com.alibaba.dubbo.config.annotation.Service;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.pinyougou.mapper.TbBrandMapper;
import com.pinyougou.pojo.TbBrand;
import com.pinyougou.sellergoods.service.BrandService;
import entity.PageResult;
import org.springframework.beans.factory.annotation.Autowired;import java.util.List;/*** 品牌服務層實現類*/
@Service
public class BrandServiceImpl implements BrandService {/*** 增加品牌* @param brand*/@Overridepublic void add(TbBrand brand) {brandMapper.insert(brand);}
}
?BrandController
pinyougou-manager-web
package com.pinyougou.manager.controller;import com.alibaba.dubbo.config.annotation.Reference;
import com.pinyougou.pojo.TbBrand;
import com.pinyougou.sellergoods.service.BrandService;
import entity.PageResult;
import entity.Result;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.List;/*** 品牌的控制器層*/
@RestController
@RequestMapping("/brand")
public class BrandController {//增加品牌@RequestMapping("/add")public Result add(@RequestBody TbBrand brand){try {brandService.add(brand);return new Result(true,"添加成功?");} catch (Exception e) {e.printStackTrace();return new Result(false,"添加失敗🙃");}}
}
Result
pinyougou-pojo
package entity;import java.io.Serializable;/*** 增加品牌的返回結果實體類*/
public class Result implements Serializable {private boolean success;private String message;//getter,setter方法,構造器省略
}
2、前端
<!DOCTYPE html>
<html>
<head><script>//定義名為app的模塊var app=angular.module("pinyougou",["pagination"]);app.controller("brandController",function ($scope,$http) {//增加品牌$scope.add=function () {$http.post("../brand/add.do",$scope.entity).success(function(response){if(response.success){$scope.reloadList();//刷新數據}else{alert(response.message);//打印信息}})}})</script></head>
<body class="hold-transition skin-red sidebar-mini" ng-app="pinyougou" ng-controller="brandController" ng-init="findAll()"><!-- .box-body --><div class="box-body"><!-- 數據表格 --><div class="table-box"><!--工具欄--><div class="pull-left"><div class="form-group form-inline"><div class="btn-group"><!--添加的ng-click可以讓每次打開新建的窗口里,都保持空白頁面--><button type="button" class="btn btn-default" title="新建" ng-click="entity={}" data-toggle="modal" data-target="#editModal" ><i class="fa fa-file-o"></i> 新建</button></div></div></div><!--工具欄/--><!--數據列表--><table id="dataList" class="table table-bordered table-striped table-hover dataTable"><!--表頭--><thead><tr><th class="" style="padding-right:0px"><input id="selall" type="checkbox" class="icheckbox_square-blue"></th> <th class="sorting_asc">品牌ID</th><th class="sorting">品牌名稱</th> <th class="sorting">品牌首字母</th> <th class="text-center">操作</th></tr></thead></table> </div><!-- 數據表格 /--> </div><!-- /.box-body --><!-- 編輯窗口 -->
<div class="modal fade" id="editModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"><div class="modal-dialog" ><div class="modal-content"><div class="modal-body"> <table class="table table-bordered table-striped" width="800px"><tr><td>品牌名稱</td><!--此處的ng-model是將屬性name和品牌名稱綁定,獲取到品牌名稱后,綁定后name屬性中--><td><input class="form-control" ng-model="entity.name" placeholder="品牌名稱" > </td></tr> <tr><td>首字母</td><td><input class="form-control" ng-model="entity.firstChar" placeholder="首字母"> </td></tr> </table> </div><div class="modal-footer"> <!--此處的ng-click是為了在點擊保存時,觸發add()方法--> <button class="btn btn-success" data-dismiss="modal" ng-click="add()" aria-hidden="true">保存</button></div></div></div>
</div></body>
</html>
運行結果:
修改品牌
1、后端?
BrandService
pinyougou-sellergoods-interface
package com.pinyougou.sellergoods.service;import com.pinyougou.pojo.TbBrand;
import entity.PageResult;import java.util.List;/*** 品牌業務接口*/
public interface BrandService {/*** 根據ID查詢實體* @param id* @return*/public TbBrand findOne(Long id);/*** 修改* @param brand*/public void update(TbBrand brand);
}
BrandServiceImpl
pinyougou-sellergoods-service
package com.pinyougou.sellergoods.service.impl;import com.alibaba.dubbo.config.annotation.Service;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.pinyougou.mapper.TbBrandMapper;
import com.pinyougou.pojo.TbBrand;
import com.pinyougou.sellergoods.service.BrandService;
import entity.PageResult;
import org.springframework.beans.factory.annotation.Autowired;import java.util.List;/*** 品牌服務層實現類*/
@Service
public class BrandServiceImpl implements BrandService {//根據ID查詢@Overridepublic TbBrand findOne(Long id) {return brandMapper.selectByPrimaryKey(id);}//修改@Overridepublic void update(TbBrand brand) {brandMapper.updateByPrimaryKey(brand);}
}
BrandController
pinyougou-manager-web
package com.pinyougou.manager.controller;import com.alibaba.dubbo.config.annotation.Reference;
import com.pinyougou.pojo.TbBrand;
import com.pinyougou.sellergoods.service.BrandService;
import entity.PageResult;
import entity.Result;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.List;/*** 品牌的控制器層*/
public class BrandController {//根據ID查詢@RequestMapping("/findOne")public TbBrand findOne(Long id){return brandService.findOne(id);}//修改@RequestMapping("/update")public Result update(@RequestBody TbBrand brand){try {brandService.update(brand);return new Result(true,"修改成功?");} catch (Exception e) {e.printStackTrace();return new Result(false,"修改失敗🙃");}}
}
運行結果:
2、前端
<!DOCTYPE html>
<html>
<head><script>//定義名為app的模塊var app=angular.module("pinyougou",["pagination"]);app.controller("brandController",function ($scope,$http) {//保存(新增和修改)$scope.save=function () {var methodName="add";//新增時,id為空;但修改時,id不為空if($scope.entity.id!=null){methodName="update";}$http.post("../brand/"+methodName+".do",$scope.entity).success(function(response){if(response.success){$scope.reloadList();//刷新數據}else{alert(response.message);//打印信息}})}//根據ID查詢$scope.findOne=function(id){$http.get("../brand/findOne.do?id="+id).success(function (response) {$scope.entity=response;})}})</script></head>
<body class="hold-transition skin-red sidebar-mini" ng-app="pinyougou" ng-controller="brandController" ng-init="findAll()"><!-- .box-body --><div class="box-body"><!-- 數據表格 --><div class="table-box"><!--數據列表--><table id="dataList" class="table table-bordered table-striped table-hover dataTable"><!--表體--><tbody><!--使用循環填寫表格--><tr ng-repeat="entity in list"><td><input type="checkbox" ></td><!--此處要加雙花括號,是因為entity.id是表達式--><td>{{entity.id}}</td><td>{{entity.name}}</td><td>{{entity.firstChar}}</td><td class="text-center"><!--此處的findOne()里entity.id不用雙括號是因為在這里它是變量--><button type="button" class="btn bg-olive btn-xs" data-toggle="modal" ng-click="findOne(entity.id)" data-target="#editModal" >修改</button></td></tr></tbody></table> </div><!-- 數據表格 /--></div><!-- /.box-body --><!-- 編輯窗口 -->
<div class="modal fade" id="editModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"><div class="modal-dialog" ><div class="modal-content"><div class="modal-footer"> <button class="btn btn-success" data-dismiss="modal" ng-click="save()" aria-hidden="true">保存</button></div></div></div>
</div>
</body>
</html>
運行結果:
刪除品牌
1、后端?
BrandService
pinyougou-sellergoods-interface
package com.pinyougou.sellergoods.service;import com.pinyougou.pojo.TbBrand;
import entity.PageResult;import java.util.List;/*** 品牌業務接口*/
public interface BrandService {/*** 刪除* @param ids*/public void delete(Long []ids);
}
BrandServiceImpl
pinyougou-sellergoods-service
package com.pinyougou.sellergoods.service.impl;import com.alibaba.dubbo.config.annotation.Service;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.pinyougou.mapper.TbBrandMapper;
import com.pinyougou.pojo.TbBrand;
import com.pinyougou.sellergoods.service.BrandService;
import entity.PageResult;
import org.springframework.beans.factory.annotation.Autowired;import java.util.List;/*** 品牌服務層實現類*/
@Service
public class BrandServiceImpl implements BrandService {//刪除@Overridepublic void delete(Long[] ids) {for(Long id:ids){brandMapper.deleteByPrimaryKey(id);}}
}
BrandController
pinyougou-manager-web
package com.pinyougou.manager.controller;import com.alibaba.dubbo.config.annotation.Reference;
import com.pinyougou.pojo.TbBrand;
import com.pinyougou.sellergoods.service.BrandService;
import entity.PageResult;
import entity.Result;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.List;/*** 品牌的控制器層*/
@RestController
@RequestMapping("/brand")
public class BrandController {//刪除@RequestMapping("/delete")public Result delete(Long []ids){try {brandService.delete(ids);return new Result(true,"刪除成功?");} catch (Exception e) {e.printStackTrace();return new Result(false,"刪除失敗🙃");}}
}
運行結果:
2、前端
<!DOCTYPE html>
<html>
<head><script>//定義名為app的模塊var app=angular.module("pinyougou",["pagination"]);app.controller("brandController",function ($scope,$http) {//批量選中$scope.selectIds=[];//選中的ID數組,準備批量刪除的數據$scope.updateSelection=function($event,id){if($event.target.checked){//判斷是否選中$scope.selectIds.push(id);//向數組中添加數據}else{var idx=$scope.selectIds.indexOf(id);//id在選中數據的數組中的位置$scope.selectIds.splice(idx,1);//從數組中刪除數據,重復點復選框,選擇和取消選擇反復橫跳}}//刪除$scope.dele=function () {$http.get("../brand/delete.do?ids="+$scope.selectIds).success(function (response) {if(response.success){$scope.reloadList();//刷新列表$scope.selectIds=[];}else{alert(response.message);//打印信息}})}})</script>
</head>
<body class="hold-transition skin-red sidebar-mini" ng-app="pinyougou" ng-controller="brandController" ng-init="findAll()"><!-- .box-body --><div class="box-body"><!-- 數據表格 --><div class="table-box"><!--工具欄--><div class="pull-left"><div class="form-group form-inline"><button type="button" class="btn btn-default" title="刪除" ng-click="dele()"><i class="fa fa-trash-o"></i> 刪除</button> </div></div></div><!--工具欄/--><!--在數據表格下放置分頁組件,那個分頁的小欄--><tm-pagination conf="paginationConf"></tm-pagination>{{selectIds}} </div><!-- 數據表格 /--> </div><!-- /.box-body -->
</body>
</html>
條件查詢
1、后端?
BrandService
pinyougou-sellergoods-interface
package com.pinyougou.sellergoods.service;import com.pinyougou.pojo.TbBrand;
import entity.PageResult;import java.util.List;/*** 品牌業務接口*/
public interface BrandService {/*** 條件查詢* @param pageNum* @param pageSize* @return*///直接傳遞一個實體類TbBrand比逐個傳遞它的屬性要更靈活public PageResult findPage(TbBrand brand,int pageNum,int pageSize);
}
BrandServiceImpl
pinyougou-sellergoods-service
package com.pinyougou.sellergoods.service.impl;import com.alibaba.dubbo.config.annotation.Service;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.pinyougou.mapper.TbBrandMapper;
import com.pinyougou.pojo.TbBrand;
import com.pinyougou.pojo.TbBrandExample;
import com.pinyougou.sellergoods.service.BrandService;
import entity.PageResult;
import org.springframework.beans.factory.annotation.Autowired;import java.util.List;/*** 品牌服務層實現類*/
@Service
public class BrandServiceImpl implements BrandService {//條件查詢@Overridepublic PageResult findPage(TbBrand brand, int pageNum, int pageSize) {//分頁插件PageHelper.startPage(pageNum,pageSize);//封裝查詢條件TbBrandExample example = new TbBrandExample();//構建查詢條件的類TbBrandExample.Criteria criteria = example.createCriteria();if(brand!=null){//如果有名稱的條件if(brand.getName()!=null && brand.getName().length() > 0){//where name like %s%criteria.andNameLike("%"+brand.getName()+"%");}//如果有首字母的條件if(brand.getFirstChar()!=null && brand.getFirstChar().length() > 0){criteria.andFirstCharEqualTo(brand.getFirstChar());}}Page<TbBrand> page=(Page<TbBrand>)brandMapper.selectByExample(null);return new PageResult(page.getTotal(),page.getResult());}
}
BrandController
pinyougou-manager-web
package com.pinyougou.manager.controller;import com.alibaba.dubbo.config.annotation.Reference;
import com.pinyougou.pojo.TbBrand;
import com.pinyougou.sellergoods.service.BrandService;
import entity.PageResult;
import entity.Result;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.List;/*** 品牌的控制器層*/
@RestController
@RequestMapping("/brand")
public class BrandController {//條件查詢@RequestMapping("/search")public PageResult search(@RequestBody TbBrand brand, int page,int rows){return brandService.findPage(brand,page,rows);}
}
2、前端
<!DOCTYPE html>
<html>
<head><script>//定義名為app的模塊var app=angular.module("pinyougou",["pagination"]);app.controller("brandController",function ($scope,$http) {//定義搜索對象$scope.searchEntity={};//條件查詢+分頁$scope.search=function(page,rows){$http.post("../brand/search.do?page="+page+"&rows="+rows,$scope.searchEntity).success(function (response) {$scope.list=response.rows;//給列表變量賦值$scope.paginationConf.totalItems=response.total;//定義總記錄數})}//重新加載記錄$scope.reloadList=function () {$scope.search($scope.paginationConf.currentPage,$scope.paginationConf.itemsPerPage);}})</script></head>
<body class="hold-transition skin-red sidebar-mini" ng-app="pinyougou" ng-controller="brandController" ng-init="findAll()"><!-- .box-body --><div class="box-body"><!-- 數據表格 --><div class="table-box"><!--工具欄--><div class="box-tools pull-right"><div class="has-feedback">名稱: <input ng-model="searchEntity.name">首字母: <input ng-model="searchEntity.firstChar"><button ng-click="reloadList()">查詢</button></div></div><!--工具欄/--> </div><!-- 數據表格 /--> </div><!-- /.box-body -->
</body>
</html>
運行結果:
第三部分(簡化開發)
前端分層開發(后端MVC的分層思想)
brand.html
<!DOCTYPE html>
<html>
<head><script src="../js/base_pagination.js"></script><script src="../js/service/brandService.js"></script><script src="../js/controller/brandController.js"></script>
</body>
</html>
base_pagination.js
//使用分頁插件時,引入該資源
var app=angular.module("pinyougou",["pagination"]);
base.js
//不使用分頁插件時,引入該資源
var app=angular.module("pinyougou",[]);
brandService.js
//構建前端服務層
//和后端打交道的代碼寫在服務層
app.service("brandService",function($http){//$get:傳遞屬性,變量; $post:傳遞對象this.findAll=function () {return $http.get('../brand/findAll.do');}this.findPage=function (page,rows) {return $http.get("../brand/findPage.do?page="+page+"&rows="+rows);}this.search=function (page,rows,searchEntity) {return $http.post("../brand/search.do?page="+page+"&rows="+rows,searchEntity);}this.add=function (entity) {return $http.post("../brand/add.do?",entity);}this.update=function (entity) {return $http.post("../brand/update.do?",entity);}this.findOne=function (id) {return $http.get("../brand/findOne.do?id="+id);}this.dele=function (ids) {return $http.get("../brand/delete.do?ids="+ids);}
})
brandController.js?
//構建前端的控制層
//和頁面打交道的代碼寫在控制層
app.controller("brandController",function ($scope,brandService) {//讀取列表數據綁定到表單中$scope.findAll=function () {brandService.findAll().success(function(response){$scope.list=response;})}//定義搜索對象$scope.searchEntity={};//條件查詢+分頁$scope.search=function(page,rows){brandService.search(page,rows,$scope.searchEntity).success(function (response) {$scope.list=response.rows;//給列表變量賦值$scope.paginationConf.totalItems=response.total;//定義總記錄數})}//分頁$scope.findPage=function(page,rows) {brandService.findPage(page,rows).success(function(response){$scope.list=response.rows;$scope.paginationConf.totalItems=response.total;//定義總記錄數})}//定義對象paginationConf,分布的配置$scope.paginationConf={currentPage: 1,//當前頁totalItems: 10,//總記錄條數itemsPerPage: 10,//每頁的記錄條數perPageOptions: [10,20,30,40,50],//頁碼選項,每頁10條還是20還是...onChange: function () {//當頁碼發生變化時自動觸發的方法$scope.reloadList();}}//重新加載記錄$scope.reloadList=function () {$scope.search($scope.paginationConf.currentPage,$scope.paginationConf.itemsPerPage);}//保存(新增和修改)$scope.save=function () {var object=null;//新增時,id為空;但修改時,id不為空if($scope.entity.id!=null){object=brandService.update($scope.entity);}else{object=brandService.add($scope.entity);}object.success(function(response){if(response.success){$scope.reloadList();//刷新數據}else{alert(response.message);//打印信息}})}//根據ID查詢$scope.findOne=function(id){brandService.findOne(id).success(function (response) {$scope.entity=response;})}//批量選中$scope.selectIds=[];//選中的ID數組,準備批量刪除的數據$scope.updateSelection=function($event,id){if($event.target.checked){//判斷是否選中$scope.selectIds.push(id);//向數組中添加數據}else{var idx=$scope.selectIds.indexOf(id);//id在選中數據的數組中的位置$scope.selectIds.splice(idx,1);//從數組中刪除數據,重復點復選框,選擇和取消選擇反復橫跳}}//刪除$scope.dele=function () {brandService.dele($scope.selectIds).success(function (response) {if(response.success){$scope.reloadList();//刷新列表$scope.selectIds=[];}else{alert(response.message);//打印信息}})}
})
?控制器繼承(提高代碼復用率)
brand.html
<!DOCTYPE html>
<html>
<head><script src="../js/controller/baseController.js"></script><script src="../js/controller/brandController.js"></script>
</body>
</html>
baseController.js
//父控制器
app.controller("baseController",function ($scope) {//定義搜索對象$scope.searchEntity={};//定義對象paginationConf,分布的配置$scope.paginationConf={currentPage: 1,//當前頁totalItems: 10,//總記錄條數itemsPerPage: 10,//每頁的記錄條數perPageOptions: [10,20,30,40,50],//頁碼選項,每頁10條還是20還是...onChange: function () {//當頁碼發生變化時自動觸發的方法$scope.reloadList();}}//重新加載記錄$scope.reloadList=function () {$scope.search($scope.paginationConf.currentPage,$scope.paginationConf.itemsPerPage);}//批量選中$scope.selectIds=[];//選中的ID數組,準備批量刪除的數據$scope.updateSelection=function($event,id){if($event.target.checked){//判斷是否選中$scope.selectIds.push(id);//向數組中添加數據}else{var idx=$scope.selectIds.indexOf(id);//id在選中數據的數組中的位置$scope.selectIds.splice(idx,1);//從數組中刪除數據,重復點復選框,選擇和取消選擇反復橫跳}}})
brandController.js
//構建前端的控制層
//和頁面打交道的代碼寫在控制層
app.controller("brandController",function ($scope,$controller,brandService) {//把baseController的$scope傳遞給brandController的$scope,偽繼承$controller("baseController",{$scope:$scope});//讀取列表數據綁定到表單中$scope.findAll=function () {brandService.findAll().success(function(response){$scope.list=response;})}//條件查詢+分頁$scope.search=function(page,rows){brandService.search(page,rows,$scope.searchEntity).success(function (response) {$scope.list=response.rows;//給列表變量賦值$scope.paginationConf.totalItems=response.total;//定義總記錄數})}//分頁$scope.findPage=function(page,rows) {brandService.findPage(page,rows).success(function(response){$scope.list=response.rows;$scope.paginationConf.totalItems=response.total;//定義總記錄數})}//保存(新增和修改)$scope.save=function () {var object=null;//新增時,id為空;但修改時,id不為空if($scope.entity.id!=null){object=brandService.update($scope.entity);}else{object=brandService.add($scope.entity);}object.success(function(response){if(response.success){$scope.reloadList();//刷新數據}else{alert(response.message);//打印信息}})}//根據ID查詢$scope.findOne=function(id){brandService.findOne(id).success(function (response) {$scope.entity=response;})}//刪除$scope.dele=function () {brandService.dele($scope.selectIds).success(function (response) {if(response.success){$scope.reloadList();//刷新列表$scope.selectIds=[];}else{alert(response.message);//打印信息}})}
})
規格管理(深入理解和使用雙向綁定)
代碼較散,前后端不斷切換寫代碼,調試
第四部分
模板管理
一、品牌下拉列表(使用select2實現下拉列表功能
寫代碼的思路、邏輯、順序基本如下
后端
TbBrandMapper.xml
<select id="selectOptionList" resultType="java.util.Map">select id,name as text from tb_brand</select>
TbBrandMapper
/*** 下拉列表數據* @return*/List<Map> selectOptionList();
?BrandService
public List<Map> selectOptionList();
BrandServiceImpl
@Overridepublic List<Map> selectOptionList() {return brandMapper.selectOptionList();}
?BrandController
@RequestMapping("/selectOptionList")public List<Map> selectOptionList(){return brandService.selectOptionList();}
運行結果:
?前端
?brandService.js
this.selectOptionList=function () {return $http.get("../brand/selectOptionList.do")}
typeTemplateController.js?
//控制層
app.controller('typeTemplateController' ,function($scope,$controller,typeTemplateService,brandService,specificationService){$controller('baseController',{$scope:$scope});//繼承//搜索$scope.search=function(page,rows){ typeTemplateService.search(page,rows,$scope.searchEntity).success(function(response){$scope.list=response.rows; $scope.paginationConf.totalItems=response.total;//更新總記錄數} );}$scope.brandList={data:[]};//品牌列表//查詢品牌列表$scope.findBrandList=function(){brandService.selectOptionList().success(function(response){$scope.brandList={data:response};}); }
});
typeTemplate.html
<!DOCTYPE html>
<html><head><script src="../plugins/angularjs/angular.min.js"></script><!--分頁組件開始--><script src="../plugins/angularjs/pagination.js"></script><link rel="stylesheet" href="../plugins/angularjs/pagination.css"><!--分頁組件結束--><script src="../js/base_pagination.js"></script><script src="../js/angular-select2.js"></script><script src="../js/service/typeTemplateService.js"></script><script src="../js/service/brandService.js"></script><script src="../js/service/specificationService.js"></script><script src="../js/controller/baseController.js"></script><script src="../js/controller/typeTemplateController.js"></script>
</head><body class="hold-transition skin-red sidebar-mini" ng-app="pinyougou" ng-controller="typeTemplateController" ng-init="findAll();findBrandList()"><!-- .box-body --><div class="box-body"><!--工具欄/--><!--數據列表--><table id="dataList" class="table table-bordered table-striped table-hover dataTable"><tbody><tr ng-repeat="entity in list"><td><input type="checkbox"></td><td>{{entity.id}}</td><td>{{entity.name}}</td><td>{{entity.brandIds}}</td><td>{{entity.specIds}}</td><td>{{entity.customAttributeItems}}</td><td class="text-center"><button type="button" class="btn bg-olive btn-xs" data-toggle="modal" data-target="#editModal">修改</button></td></tr></tbody></table><!--數據列表/--><tm-pagination conf="paginationConf"></tm-pagination></div><!-- 數據表格 /--> </div><!-- /.box-body --><!-- 編輯窗口 -->
<div class="modal fade" id="editModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"><div class="modal-dialog" ><div class="modal-content"><div class="modal-header"><button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button><h3 id="myModalLabel">商品類型模板編輯</h3></div><div class="modal-body"> <table class="table table-bordered table-striped" width="800px"> <tr><td>關聯品牌</td><td><!--multiple表示可多選config用于配置數據來源select2-model用于指定用戶選擇后提交的變量--><input select2 select2-model="entity.brandIds" config="brandList" multiple placeholder="支持多選" class="form-control" type="text"/></td></tr><tr></tr> <tr><td>擴展屬性</td><td><div class="btn-group"> </div> </td></tr> </table> </div></div></div>
</div></body></html>
運行結果:
規格下拉列表(同上)
注意事項:
typeTemplate.html文件里的ng-init必須帶上findAll()方法,用瀏覽器訪問時才會正常顯示表格
<body class="hold-transition skin-red sidebar-mini" ng-app="pinyougou" ng-controller="typeTemplateController" ng-init="findAll();findBrandList();findSpecList()">
二、擴展屬性(增加、刪除行)
typeTemplateController.js
//增加擴展屬性行$scope.addTableRow=function(){$scope.entity.customAttributeItems.push({});}//刪除擴展屬性行$scope.deleTableRow=function(index){$scope.entity.customAttributeItems.splice(index,1);}
typeTemplate.html
<!DOCTYPE html>
<html>
<body class="hold-transition skin-red sidebar-mini" ng-app="pinyougou" ng-controller="typeTemplateController" ng-init="findAll();findBrandList();findSpecList()"><!-- .box-body --><div class="box-body"><!-- 數據表格 --><div class="table-box"><!--工具欄--><div class="pull-left"><div class="form-group form-inline"><div class="btn-group"><button type="button" class="btn btn-default" title="新建" data-toggle="modal" data-target="#editModal" ng-click="entity={customAttributeItems:[]}"><i class="fa fa-file-o"></i> 新建</button></div></div></div><!--工具欄/--></div><!-- 數據表格 /--></div><!-- /.box-body -->
<!-- 編輯窗口 -->
<div class="modal fade" id="editModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"><div class="modal-dialog" ><div class="modal-content"><div class="modal-header"><button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button><h3 id="myModalLabel">商品類型模板編輯</h3></div><div class="modal-body"> <table class="table table-bordered table-striped" width="800px"></tr><tr><td>關聯規格</td><td><input select2 select2-model="entity.specIds" config="specList" multiple placeholder="支持多選" class="form-control" type="text"/></td></tr> <tr><td>擴展屬性</td><td><div class="btn-group"><button type="button" class="btn btn-default" title="新增擴展屬性" ng-click="addTableRow()"><i class="fa fa-file-o"></i> 新增擴展屬性</button></div><table class="table table-bordered table-striped" width="800px"><tbody><tr ng-repeat="pojo in entity.customAttributeItems"><td><input type="checkbox" class="icheckbox_square-blue" ></td><td><input class="form-control" ng-model="pojo.text" placeholder="屬性名稱" ></td><td><button type="button" class="btn btn-default" title="刪除" ng-click="deleTableRow($index)"><i class="fa fa-trash-o"></i> 刪除</button></td></tr></tbody></table> </td></tr> </table> </div></div></div>
</div></body></html>
?運行結果:
三、新增模板
typeTemplate.html
1、綁定文本框
<tbody><tr ng-repeat="pojo in entity.customAttributeItems"><td><input type="checkbox" class="icheckbox_square-blue" ></td><td><input class="form-control" ng-model="pojo.text" placeholder="屬性名稱" ></td><td><button type="button" class="btn btn-default" title="刪除" ng-click="deleTableRow($index)"><i class="fa fa-trash-o"></i> 刪除</button></td></tr></tbody>
2、保存按鈕
<div class="modal-footer"> <button class="btn btn-success" data-dismiss="modal" aria-hidden="true" ng-click="save()">保存</button></div>
?運行結果:
四、修改模板
typeTemplateController.js
//查詢實體 $scope.findOne=function(id){ typeTemplateService.findOne(id).success(function(response){$scope.entity= response; //轉換字符串為json對象(集合)$scope.entity.brandIds= JSON.parse( $scope.entity.brandIds);//品牌$scope.entity.specIds= JSON.parse($scope.entity.specIds);//規格$scope.entity.customAttributeItems = JSON.parse($scope.entity.customAttributeItems);//自定義屬性// JSON.parse(string): 將字符串轉成對象// JSON.stringify(object): 將對象轉成字符串}); }
typeTemplate.html
修改按鈕
<td class="text-center"><button type="button" class="btn bg-olive btn-xs" data-toggle="modal" data-target="#editModal" ng-click="findOne(entity.id)">修改</button></td>
運行結果:?
?五、刪除模板
typeTemplate.html
1、復選框勾選
<tr ng-repeat="entity in list"><td><input type="checkbox" ng-click="updateSelection($event,entity.id)"></td><td>{{entity.id}}</td><td>{{entity.name}}</td><td>{{entity.brandIds}}</td><td>{{entity.specIds}}</td><td>{{entity.customAttributeItems}}</td><td class="text-center"><button type="button" class="btn bg-olive btn-xs" data-toggle="modal" data-target="#editModal" ng-click="findOne(entity.id)">修改</button></td></tr>
2、刪除按鈕
<div class="btn-group"><button type="button" class="btn btn-default" title="刪除" ng-click="dele()"><i class="fa fa-trash-o"></i> 刪除</button> </div>
?運行結果:
六、優化頁面
baseController.js
//提取json字符串數據中某個屬性,返回拼接字符串,逗號分隔// 讓瀏覽器訪問的html文件上的數據更通俗易懂$scope.jsonToString=function (jsonString,key) {var json=JSON.parse(jsonString);var value="";for(var i=0;i<json.length;i++){if(i>0){//第一個值前面不用加逗號分隔value+=",";//使用逗號分隔}value+=json[i][key];//key是json[i]的某個屬性}return value;}
typeTemplate.html
<tbody><tr ng-repeat="entity in list"><td><input type="checkbox" ng-click="updateSelection($event,entity.id)"></td><td>{{entity.id}}</td><td>{{entity.name}}</td><td>{{ jsonToString(entity.brandIds,"text") }}</td><td>{{ jsonToString(entity.specIds,"text") }}</td><td>{{ jsonToString(entity.customAttributeItems,"text") }}</td><td class="text-center"><button type="button" class="btn bg-olive btn-xs" data-toggle="modal" data-target="#editModal" ng-click="findOne(entity.id)">修改</button></td></tr></tbody>
優化前:
?優化后:
經常出現的問題:
????????如果出現更改了前端代碼,前端代碼沒有問題,但前端頁面顯示不正常(一般是規定的數據不顯示),就清除一下瀏覽器的數據(另外去百度),再刷新一下頁面
?商品分類
一、商品列表
后端
ItemCatService
public List<TbItemCat> findByParentId(Long parentId);
ItemCatServiceImpl
@Overridepublic List<TbItemCat> findByParentId(Long parentId) {TbItemCatExample example = new TbItemCatExample();TbItemCatExample.Criteria criteria = example.createCriteria();criteria.andParentIdEqualTo(parentId);return tbItemCatMapper.selectByExample(example);}
ItemCatController
/*** 根據上級ID查詢商品分類* @param parentId* @return*/@RequestMapping("/findByParentId")public List<TbItemCat> findByParentId(Long parentId){return itemCatService.findByParentId(parentId);}
運行結果:
前端
itemCatService.js
//根據上級ID查詢列表this.findByParentId=function (parentId) {return $http.get('../itemCat/findByParentId.do?parentId='+parentId);}
itemCatController.js
//根據上級ID查詢列表$scope.findByParentId=function (parentId) {itemCatService.findByParentId(parentId).success(function (response) {$scope.list=response;});}
item_cat.html
<!DOCTYPE html>
<html>
<head><script src="../plugins/angularjs/angular.min.js"></script><script src="../js/base.js"></script><script src="../js/service/itemCatService.js"></script><script src="../js/controller/baseController.js"></script><script src="../js/controller/itemCatController.js"></script>
</head>
<body class="hold-transition skin-red sidebar-mini" ng-app="pinyougou" ng-controller="itemCatController" ng-init="findAll();findByParentId()"><tbody><tr ng-repeat="entity in list"><td><input type="checkbox" ></td> <td>{{entity.id}}</td><td>{{entity.name}}</td><td>{{entity.typeId}}</td><td class="text-center"> <button type="button" class="btn bg-olive btn-xs" ng-click="findByParentId(entity.id)">查詢下級</button><button type="button" class="btn bg-olive btn-xs" data-toggle="modal" data-target="#editModal" >修改</button> </td></tr></tbody>
</body>
?運行結果:
二、面包屑導航(Breadcrumb Navigation)
面包屑導航(Breadcrumb Navigation)這個概念來自童話故事“漢賽爾和格萊特”,當漢賽爾和格萊特穿過森林時,不小心迷路了,但是他們發現沿途走過的地方都撒下了面包屑,讓這些面包屑來幫助他們找到回家的路。?
itemCatController.js
//定義面包屑$scope.breadcrumb=[{id:0,name:"頂級分類列表"}];$scope.search=function (id,name) {//添加面包屑$scope.breadcrumb.push({id:id,name:name});$scope.findByParentId(id);}$scope.showList=function (index,id) {//截斷面包屑//index+1: 表示從當前索引的后一個索引開始截斷(從面包屑中去除)//2: 表示截斷的個數,在此最大是3級,所以寫2,寫100也沒關系$scope.breadcrumb.splice(index+1,2);$scope.findByParentId(id);}
item_cat.html
1、查詢下級按鈕
<button ng-if="breadcrumb.length<3" type="button" class="btn bg-olive btn-xs" ng-click="search(entity.id,entity.name)">查詢下級</button>
2、綁定面包屑
<ol class="breadcrumb"><!--綁定面包屑--><li ng-repeat="pojo in breadcrumb"><a href="#" ng-click="showList($index,pojo.id)">{{pojo.name}}</a></li></ol>
?運行結果:
三、新增商品分類
在哪一級新增商品分類,那新增數據就應該顯示在哪一級,而不是全部顯示在頂級。
關鍵在于查詢時記錄下當前級parentId
itemCatController.js
//保存 $scope.save=function(){ var serviceObject;//服務層對象 if($scope.entity.id!=null){//如果有IDserviceObject=itemCatService.update( $scope.entity ); //修改 }else{serviceObject=itemCatService.add( $scope.entity );//增加 } serviceObject.success(function(response){if(response.success){//重新查詢$scope.findByParentId($scope.entity.parentId);}else{alert(response.message);}} ); }$scope.searchEntity={};//定義搜索對象//定義變量parentId,記錄本級的ID//entity是表單所綁定的實體// $socpe.entity={parentId:0};//根據上級ID查詢列表$scope.findByParentId=function (parentId) {//查詢時記錄上級ID$scope.entity={parentId:parentId};itemCatService.findByParentId(parentId).success(function (response) {$scope.list=response;});}
item_cat.html
<div class="modal-body"> <table class="table table-bordered table-striped" width="800px"><tr><td>上級商品分類</td><td><!--綁定面包屑--><span ng-repeat="pojo in breadcrumb">{{pojo.name}}</span></td></tr><tr><td>商品分類名稱</td><td><input ng-model="entity.name" class="form-control" placeholder="商品分類名稱" > </td></tr> <tr><td>類型模板</td><td> <input ng-model="entity.typeId" placeholder="商品類型模板" class="form-control" type="text"/></td> </tr> </table> </div><div class="modal-footer"> <button class="btn btn-success" data-dismiss="modal" aria-hidden="true" ng-click="save()">保存</button></div>
注意:
itemCatController.js文件去除了??$socpe.entity={parentId:0}; 這句給parentId賦初值的語句,因為parentId后續在function函數中再次被修改,這兩個操作會發生沖突,導致前端引用$scope.entity對象時出錯,如果要修改,最好使用深拷貝,而非直接賦值
?運行結果:
四、模板下拉列表
itemCatController.js
//查詢模板列表 (下拉框顯示模板)$scope.findTypeTemplateList=function () {typeTemplateService.findAll().success(function (response) {$scope.typeTemplateList=response;//模板列表})}
item_cat.html
<tr><td>類型模板</td><td><select ng-model="entity.typeId" ng-options="item.id as item.name for item in typeTemplateList"></select></td></tr>
運行結果:
五、修改商品分類
item_cat.html
<button type="button" class="btn bg-olive btn-xs" data-toggle="modal" data-target="#editModal" ng-click="findOne(entity.id)">修改</button>
六、刪除商品分類
itemCatServiceImpl
/*** 批量刪除*/@Overridepublic void delete(Long[] ids) {for(Long id:ids){List<TbItemCat> list=findByParentId(id);if(list.size()>0){//要刪除的商品有下級商品分類,拋出運行時異常throw new RuntimeException("不能刪除有下級分類的商品分類!");}else{//刪除tbItemCatMapper.deleteByPrimaryKey(id);}}}
itemCatController
@RequestMapping("/delete")public Result delete(Long [] ids){try {itemCatService.delete(ids);return new Result(true, "刪除成功"); } catch(RuntimeException e){//把拋出的運行時異常信息打印出來e.printStackTrace();return new Result(false,e.getMessage());} catch (Exception e) {e.printStackTrace();return new Result(false, "刪除失敗");}}
itemCatController.js
//批量刪除 $scope.dele=function(){ //獲取選中的復選框 itemCatService.dele( $scope.selectIds ).success(function(response){if(response.success) {$scope.findByParentId($scope.entity.parentId);$scope.selectIds = [];}else{alert(response.message);//把異常信息顯示在前端頁面}} ); }
item_cat.html
1、復選框,實現多選
<td><input type="checkbox" ng-click="updateSelection($event,entity.id)"></td>
2、刪除按鈕
<button type="button" class="btn btn-default" title="刪除" ng-click="dele()"><i class="fa fa-trash-o" ></i> 刪除</button>
?七、顯示模板名稱
itemCatController.js
//定義一個變量$scope.typeTemplateMap=[];//查詢模板列表 (下拉框顯示模板)$scope.findTypeTemplateList=function () {typeTemplateService.findAll().success(function (response) {$scope.typeTemplateList=response;//模板列表//構建模板數據,用于列表顯示名稱for(var i=0;i<$scope.typeTemplateList.length;i++){//得到一個對象var typeTemplate=$scope.typeTemplateList[i];//把對象的id值修改成name$scope.typeTemplateMap[typeTemplate.id]=typeTemplate.name;}})}
item_cat.html
<tr ng-repeat="entity in list"><!--ng-click是勾選復選框,實現多選--><td><input type="checkbox" ng-click="updateSelection($event,entity.id)"></td><td>{{entity.id}}</td><td>{{entity.name}}</td><td>{{typeTemplateMap[entity.typeId]}}</td><td class="text-center"> <button ng-if="breadcrumb.length<3" type="button" class="btn bg-olive btn-xs" ng-click="search(entity.id,entity.name)">查詢下級</button><button type="button" class="btn bg-olive btn-xs" data-toggle="modal" data-target="#editModal" ng-click="findOne(entity.id)">修改</button></td></tr>
?運行結果: