一:商家后台-商品管理【商品列表】(在商家后台,显示该商家的商品列表信息)
不能修改service层代码,因为会影响运营商和商家后台
因此只能在商家后台的Controller修改代码
并且在service层将模糊查询改成精确查询
@RequestMapping("/search")
public PageResult search(@RequestBody TbGoods goods, int page, int rows ){
//获取商家ID
String sellerId=SecurityContextHolder.getContext().getAuthentication().getName();
//添加查询条件
goods.setSellerId(sellerId);
return goodsService.findPage(goods, page, rows);
}
criteria.andSellerIdEqualTo(goods.getSellerId());
//引入js
<script type="text/javascript" src="../plugins/angularjs/angular.min.js"></script>
<!-- 分页组件开始 -->
<script src="../plugins/angularjs/pagination.js"></script>
<link rel="stylesheet" href="../plugins/angularjs/pagination.css">
<!-- 分页组件结束 -->
<script type="text/javascript" src="../js/base_pagination.js"></script>
<script type="text/javascript" src="../js/service/goodsService.js"></script>
<script type="text/javascript" src="../js/service/itemCatService.js"></script>
<script type="text/javascript" src="../js/service/uploadService.js"></script>
<script type="text/javascript" src="../js/service/typeTemplateService.js"></script>
<script type="text/javascript" src="../js/controller/baseController.js"></script>
<script type="text/javascript" src="../js/controller/goodsController.js"></script>
<body class="hold-transition skin-red sidebar-mini" ng-app="pinyougou" ng-controller="goodsController">
//在页面上放置分页控件
<tm-pagination conf="paginationConf"></tm-pagination>
//循环
<tr ng-repeat="entity in list">
<td><input type="checkbox"></td>
<td>{{entity.id}}</td>
<td>{{entity.goodsName}}</td>
<td>{{entity.price}}</td>
<td>{{entity.category1Id}}</td>
<td>{{entity.category2Id}}</td>
<td>{{entity.category3Id}}</td>
<td>
{{entity.auditStatus}}
</td>
<td class="text-center">
<button type="button" class="btn bg-olive btn-xs">修改</button>
</td>
</tr>
二:显示状态
方式一:在页面通过ng-if来判断,不过需要写4个
方式二:在前端写一个数组 下标和数据库对应的值相等
$scope.status=['未审核','已审核','审核未通过','关闭'];
{{status[entity.auditStatus]}}
三:显示分类
方案一:在后端代码写关联查询语句,返回的数据中直接有分类名称。
方案二:在前端代码用ID去查询后端,异步返回商品分类名称。
采用方式二:
以ID作为下标,以名称作为值,
和刚刚状态是一样的,不过状态是写死的,分类是从数据库查询的
$scope.itemCatList=[];//商品分类列表
//加载商品分类列表
$scope.findItemCatList=function(){
itemCatService.findAll().success(
function(response){
for(var i=0;i<response.length;i++){
$scope.itemCatList[response[i].id]=response[i].name;
}
}
);
}
ng-init="findItemCatList()"
<td>{{itemCatList[entity.category1Id]}}</td>
<td>{{itemCatList[entity.category2Id]}}</td>
<td>{{itemCatList[entity.category3Id]}}</td>
四:条件查询
<div class="has-feedback">
状态:<select ng-model="searchEntity.auditStatus">
<option value="">全部</option>
<option value="0">未审核</option>
<option value="1">已审核</option>
<option value="2">审核未通过</option>
<option value="3">关闭</option>
</select>
商品名称:<input ng-model="searchEntity.goodsName">
<button class="btn btn-default" ng-click="reloadList()">查询</button>
</div>
五:商家后台-商品管理【商品修改】
1)基本信息读取
public Goods findOne(Long id);
public Goods findOne(Long id){
Goods goods=new Goods();
//商品基本表
TbGoods tbGoods = goodsMapper.selectByPrimaryKey(id);
goods.setGoods(tbGoods);
//商品扩展表
TbGoodsDesc tbGoodsDesc =goodsDescMapper.selectByPrimaryKey(id);
goods.setGoodsDesc(tbGoodsDesc);
return goods;
}
//将后端Controller改成Goods
$location.search()['id'];//获取参数值
注意: ?前要加# ,则是angularJS的地址路由的书写形式
//在goodsController中引入$location服务
app.controller('goodsController',function($scope,$controller,
$location,goodsService,uploadService,item_catService,type_templateService){}
//查询实体
$scope.findOne=function(){
var id= $location.search()['id'];//获取参数值
if(id==null){
return ;
}
goodsService.findOne(id).success(
function(response){
$scope.entity= response;
}
);
}
//在goods_edit.html页面上添加指令
<body class="hold-transition skin-red sidebar-mini" ng-app="pinyougou"
ng-controller="goodsController" ng-init="selectItemCat1List();findOne()">
2)读取商品介绍(富文本编辑器)
//向富文本编辑器添加商品介绍
editor.html($scope.entity.goodsDesc.introduction);
3)显示商品图片列表
//显示图片列表
$scope.entity.goodsDesc.itemImages=JSON.parse($scope.entity.goodsDesc.itemImages);
4)读取商品扩展属性
//显示扩展属性
$scope.entity.goodsDesc.customAttributeItems=JSON.parse($scope.entity.goodsDesc.customAttributeItems);
//如果没有ID,则加载模板中的扩展数据
if($location.search()['id']==null){
//扩展属性
$scope.entity.goodsDesc.customAttributeItems = JSON.parse($scope.typeTemplate.customAttributeItems);
}
5)读取商品规格属性
//规格
$scope.entity.goodsDesc.specificationItems=JSON.parse($scope.entity.goodsDesc.specificationItems);
//根据规格名称和选项名称返回是否被勾选
$scope.checkAttributeValue=function(specName,optionName){
var items=$scope.entity.goodsDesc.specificationItems;
var object= $scope.searchObjectByKey(items,'attributeName',specName);
if(object !=null){
if(object.attributeValue.indexOf(optionName)>=0){
return true;
}else{
return false;
}
}else{
return false;
}
}
ng-checked="checkAttributeValue(pojo.text,option.optionName)"
ng-checked指令控制复选框的勾选状态,若选中,则返回true,若没有选中,则返回false
6)读取SKU数据
public class Goods implements Serializable{
private TbGoods goods; //商品SPU
private TbGoodsDesc goodsDesc; //商品扩展
private List<TbItem> itemList; //商品SKU列表
}
// 根据ID获取实体
public Goods findOne(Long id){
Goods goods=new Goods();
TbGoods tbGoods = goodsMapper.selectByPrimaryKey(id);
goods.setGoods(tbGoods);
TbGoodsDesc tbGoodsDesc =goodsDescMapper.selectByPrimaryKey(id);
goods.setGoodsDesc(tbGoodsDesc);
//查询SKU商品列表
TbItemExample example=new TbItemExample();
com.pinyougou.pojo.TbItemExample.Criteria criteria = example.createCriteria();
criteria.andGoodsIdEqualTo(id);//查询条件:商品ID
List<TbItem> itemList=itemMapper.selectByExample(example);
goods.setItemList(itemList);
return goods;
}
//SKU列表规格列转换
for(var i=0;i<$scope.entity.itemList.length;i++){
$scope.entity.itemList[i].spec=JSON.parse($scope.entity.itemList[i].spec);
}
7)保存数据
public void update(Goods goods);
//写一个方法,专门用来插入SKU的列表数据
private void saveItemList(Goods goods){
//启用规格
if("1".equals(goods.getGoods().getIsEnableSpec())){
System.out.println("111"+"勾选");
for(TbItem item:goods.getItemList()){
//构建标题 SPU名称+ 规格选项值
String title=goods.getGoods().getGoodsName();//SPU名称
//{"机身内存":"16G","网络":"联通2G"}
Map<String,Object> map=JSON.parseObject(item.getSpec());
for (String key : map.keySet()) {
title+=" "+map.get(key);
}
item.setTitle(title);
setItemValus(goods,item);
itemMapper.insert(item);
}
}else{
System.out.println("000"+"不勾选");
//不启用规格
TbItem item=new TbItem();
item.setTitle(goods.getGoods().getGoodsName());//商品KPU+规格描述串作为SKU名称
item.setPrice( goods.getGoods().getPrice() );//价格
item.setStatus("1");//状态
item.setIsDefault("1");//是否默认
item.setNum(99999);//库存数量
item.setSpec("{}");
setItemValus(goods,item);
itemMapper.insert(item);
}
}
// 修改
public void update(Goods goods){
goods.getGoods().setAuditStatus("0");//设置未申请状态:如果是经过修改的商品,需要重新设置状态
//更新基本表数据
goodsMapper.updateByPrimaryKey(goods.getGoods());
//更新扩展表数据
goodsDescMapper.updateByPrimaryKey(goods.getGoodsDesc());
//删除原有的SKU列表数据
TbItemExample example=new TbItemExample();
com.pinyougou.pojo.TbItemExample.Criteria criteria = example.createCriteria();
criteria.andGoodsIdEqualTo(goods.getGoods().getId());
itemMapper.deleteByExample(example);
//插入新的SKU列表数据
saveItemList(goods);
}
// 修改
//出于安全考虑,在商户后台执行的商品修改,必须要校验提交的商品属于该商户
@RequestMapping("/update")
public Result update(@RequestBody Goods goods){
//校验是否是当前商家的id
Goods goods2 = goodsService.findOne(goods.getGoods().getId());
//获取当前登录的商家ID
String sellerId = SecurityContextHolder.getContext().getAuthentication().getName();
//如果传递过来的商家ID并不是当前登录的用户的ID,则属于非法操作
if(!goods2.getGoods().getSellerId().equals(sellerId) ||
!goods.getGoods().getSellerId().equals(sellerId) ){
return new Result(false, "操作非法");
}
try {
goodsService.update(goods);
return new Result(true, "修改成功");
} catch (Exception e) {
e.printStackTrace();
return new Result(false, "修改失败");
}
}
//保存
$scope.save=function(){
//获取富文本编辑器里面的内容
$scope.entity.goodsDesc.introduction=editor.html();
var serviceObject;//服务层对象
if($scope.entity.goods.id!=null){//如果有ID
serviceObject=goodsService.update( $scope.entity ); //修改
}else{
serviceObject=goodsService.add( $scope.entity );//增加
}
serviceObject.success(
function(response){
if(response.success){
alert("保存成功");
$scope.entity={}; //添加成功后,清空
editor.html(''); //清空富文本编辑器
}else{
alert(response.message);
}
}
);
}
ng-click="save()"
8)页面跳转
//修改
<a href="goods_edit.html#?id={{entity.id}}" class="btn bg-olive btn-xs">修改</a>
//返回列表
<a href="goods.html" class="btn btn-default" >返回列表</a>
//保存成功,跳转到goods.html页面
alert("保存成功");
location.href="goods.html";
//新建
<a href="goods_edit.html" class="btn btn-default">新建</a>
六:运营商后台-商品管理【商品审核】
1)待审核商品列表
//要记得在goodsController.js里面注入itemCatService
$scope.status=['未审核','已审核','审核未通过','关闭'];//商品状态
$scope.itemCatList=[];//商品分类列表
//查询商品分类
$scope.findItemCatList=function(){
itemCatService.findAll().success(
function(response){
for(var i=0;i<response.length;i++){
$scope.itemCatList[response[i].id ]=response[i].name;
}
}
);
}
<script type="text/javascript" src="../plugins/angularjs/angular.min.js"></script>
<!-- 分页组件开始 -->
<script src="../plugins/angularjs/pagination.js"></script>
<link rel="stylesheet" href="../plugins/angularjs/pagination.css">
<!-- 分页组件结束 -->
<script type="text/javascript" src="../js/base_pagination.js"></script>
<script type="text/javascript" src="../js/service/goodsService.js"></script>
<script type="text/javascript" src="../js/service/itemCatService.js"></script>
<script type="text/javascript" src="../js/controller/baseController.js"></script>
<script type="text/javascript" src="../js/controller/goodsController.js"></script>
<body class="hold-transition skin-red sidebar-mini" ng-app="pinyougou" ng-controller="goodsController"
ng-init="searchEntity={auditStatus:'0'};findItemCatList()">
<tbody>
<tr ng-repeat="entity in list">
<td><input type="checkbox"></td>
<td>{{entity.id}}</td>
<td>{{entity.goodsName}}</td>
<td>{{entity.price}}</td>
<td>{{itemCatList[entity.category1Id]}}</td>
<td>{{itemCatList[entity.category2Id]}}</td>
<td>{{itemCatList[entity.category3Id]}}</td>
<td>{{status[entity.auditStatus]}}</td>
<td class="text-center"> </td>
</tr>
</tbody>
<tm-pagination conf="paginationConf"></tm-pagination>
2)商品审核与驳回
需求:商品审核的状态值为1,驳回的状态值为2 。用户在列表中选中ID后,点击审核或驳回,修改商品状态,并刷新列表。
//批量修改状态
public void updateStatus(Long [] ids,String status);
public void updateStatus(Long[] ids, String status) {
for (Long id : ids) {
TbGoods goods=goodsMapper.selectByPrimaryKey(id);
goods.setAuditStatus(status);
goodsMapper.updateByPrimaryKey(goods);
}
//更新状态
@RequestMapping("/updateStatus")
public Result updateStatus(Long[] ids, String status) {
try {
goodsService.updateStatus(ids, status);
return new Result(true, "成功");
} catch (Exception e) {
e.printStackTrace();
return new Result(false, "失败");
}
}
this.updateStatus=function(ids,status){
return $http.get('../goods/updateStatus.do?ids='+ids+"&status="+status);
}
$scope.updateStatus=function(status){
goodsService.updateStatus($scope.selectIds,status).success(
function(response){
if(response.success){//成功
$scope.reloadList();//刷新列表
$scope.selectIds=[];//清空ID集合
}else{
alert(response.message);
}
}
);
}
<input type="checkbox" ng-click="updateSelected($event,entity.id)" >
<button type="button" title="审核通过" ng-click="updateStatus('1')"> 审核通过</button>
<button type="button" title="驳回" ng-click="updateStatus('2')"> 驳回</button>
七:运营商后台-商品管理【商品删除】(逻辑删除的实现)
// 批量删除
public void delete(Long[] ids) {
for(Long id:ids){
TbGoods goods=goodsMapper.selectByPrimaryKey(id);
goods.setIsDelete("1");//1表示逻辑删除
goodsMapper.updateByPrimaryKey(goods);
}
}
//指定某个字段是null
criteria.andIsDeleteIsNull();//非删除状态
ng-click="dele()"
八:注解式事务配置(在需要的serviceImpl方法上加上 @Transactional)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 开启事务控制的注解支持 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>