猿实战03——猿首战之手把手教你撸品牌

猿实战是一个原创系列文章,通过实战的方式,采用前后端分离的技术结合SpringMVC Spring Mybatis,手把手教你撸一个完整的电商系统,跟着教程走下来,变身猿人找到工作不是问题。

前后端框架已经搭建起来了,接下来的很长一段日子里,猿人君就带着大家撸一个电商系统出来玩耍。实战阶段的目的,是为了让你从需求梳理落地到实现有一个完整的认知,熟练掌握撸码的一些套路,让你具备设计和实现一个完整系统的能力。废话不多说,我们今天开始首战——品牌管理的设计和实现。

需求整理

根据之前的猿设计系列文章猿设计2——电商后台全逻辑需求挖掘,品牌数据是需要维护的,根据对设计文档的梳理,我们需要做的功能如下图所示:

猿实战03——猿首战之手把手教你撸品牌_第1张图片猿实战03——猿首战之手把手教你撸品牌_第2张图片

 

品牌管理的功能包括,品牌列表——支持根据品牌名称模糊查询并分页展示,新增品牌、编辑品牌、删除品牌、停用/启用品牌,以及为了方便运营人员批量操作而提供的勾选记录批量停用/启用/删除功能。

数据库设计

由于之前的设计文章中,我们已经提及过品牌实体的一些属性了,而这些属性背后承载的信息,将为我们的电商系统提供数据支撑,毫无疑问,这些数据是需要持久的,为此我们自然需要建立相应的数据表来支持。

猿实战03——猿首战之手把手教你撸品牌_第3张图片

前端主要组件

由于我们使用了vue-element-admin.git作为基础的后天管理前端开发框架,前端中使用的主要组件,主要是element-ui,关于组件的具体使用办法,大家可以参考官方网站:

https://element.eleme.cn/#/zh-CN

在品牌管理这一功能中,我们主要使用了el-card、el-input、el-button、el-table(列表)、el-pagination(分页)、el-upload(上传组件),考虑到你可能是第一次编写前端代码,很多东西都还不熟悉,这次就把前端的UI代码送给你了。


       
       
          {{ scope.row.brandName }}
       
       
          {{ scope.row.firstChar }}
       
        
          
       
       
          {{ scope.row.status == 1 ? "启用" : "停用"}}
       
       


          
            编辑
           
            停用
           
            启用
           
            删除
           
          
       
      
    
0" :total="total":page.sync="listQuery.page":limit.sync="listQuery.pageSize" @pagination="getList"/> 取消 确定

后端代码之实体层

前端页面的初步代码有了,我们开始后端数据访问层的设计。根据数据库表结构,我们可以迅速的得到我们所需要的实体MallBrand和QueryMallBrand.为什么是两个实体?因为数据查询和持久是两回事情,在查询实体中,可能为了匹配页面的查询条件而增加一些不需要持久的条件,所以我们需要分开。实体层的代码编写在哪里?自然是我们的pzmall-basic-domain模块了。

 

/**
 * Copyright(c) 2004-2020pangzi
 *com.pz.basic.mall.domain.sys.MallCity.java
 */
package com.pz.basic.mall.domain.base;


import org.apache.commons.lang3.builder.ToStringBuilder;


import java.io.Serializable;


/**
 *
 * @author pangzi
 * @date 2020-06-2211:28:19
 *
 *
 */
public class BaseDO implements Serializable {


  private static final longserialVersionUID = 1L;




  /**
   * 如果字段值为null将不包含在toString中
   */
  @Override
  public String toString(){
     returnToStringBuilder.reflectionToString(this);
  }
}

 

package com.pz.basic.mall.domain.sys;


import com.pz.basic.mall.domain.base.BaseDO;


import java.util.Date;




/**
 *
 * @author pangzi
 * @date 2020-06-2718:09:41
 *
 */
public class MallBrand extends BaseDO {


    /**主键**/
  private Long id;


    /**品牌名**/
  private String brandName;


    /**logo图片地址**/
  private String logo;


    /**品牌首字母**/
  private String firstChar;


    /**状态1可用0不可用**/
  private Integer status;


    /**记录状态1有效0删除**/
  private Integer active;


    /**创建人**/
  private StringcreateUser;


    /**修改人**/
  private StringmodifyUser;


    /**创建时间**/
  private Date created;


    /**修改时间**/
  private Date modified;
    //getter setter省略


}

 

package com.pz.basic.mall.domain.sys.query;
import com.pz.basic.mall.domain.base.PaginateBaseDO;


import java.util.Date;




/**
 *
 * @author pangzi
 * @date 2020-06-2718:09:41
 *
 *
 */
public class QueryMallBrand extends PaginateBaseDO {


    /**主键**/
  private Long id;


    /**品牌名**/
  private String brandName;


    /**logo图片地址**/
  private String logo;


    /**品牌首字母**/
  private String firstChar;


    /**状态1可用0不可用**/
  private Integer status;


    /**记录状态1有效0删除**/
  private Integer active;


    /**创建人**/
  private StringcreateUser;


    /**修改人**/
  private StringmodifyUser;


    /**创建时间**/
  private Date created;


    /**修改时间**/
  private Date modified;


     /**支持品牌名称模糊查询**/
  private String brandNameLike;
}

大家可能注意到了,两个类都是子类,为什么这样设计?猿人君先卖个关子,先给出实现,至于你猜到几分,也可以考验你功力深浅噢。

package com.pz.basic.mall.domain.base;


import java.io.Serializable;


/**
 *
 * @author pangzi
 * @date 2020-06-2211:28:19
 *
 *
 */
public class PaginateBaseDO implements Serializable {
    /**
     * 默认每页的记录数量
     */
    public static finalint PAGESIZE_DEFAULT = 20;
    /**
     * 每页大小
     */
    private long pageSize;
    /**
     * 当前页。第一页是1
     */
    private long page;


    /**
     * 总记录数
     */
    private long totalItem;
    /**
     * 总页数
     */
    private long totalPage;


    /**
     * 分页后的记录开始的地方
     * 第一条记录是1
     */
    private long startRow;
    /**
     * 分页后的记录结束的地方
     */
    private long endRow;


    /**排序字段**/
    private String orderField;


    /**升序 还是 降序,true为升序,false为降序*/
    private Boolean isAsc;


    /**
     * 默认构造方法
     */
    public PaginateBaseDO() {
        repaginate();
    }


    /**
     * 带当前页和页大小的构造方法
     * @param page 当前页
     * @param pageSize 页大小
     */
    public PaginateBaseDO(long page, long pageSize) {
        this.page = page;
        this.pageSize =pageSize;
        repaginate();
    }


    public void setStartRow(long startRow) {
        this.startRow =startRow;
    }


    public void setEndRow(long endRow) {
        this.endRow =endRow;
    }


    /**
     * 表示是不是第一页
     * @return true 是; false 不是
     */
    public boolean isFirstPage(){
        return page <=1;
    }




    public boolean isMiddlePage() {
        return!(isFirstPage() || isLastPage());
    }




    public boolean isLastPage() {
        return page >=totalPage;
    }




    public boolean isNextPageAvailable() {
        return !isLastPage();
    }


    public boolean isPreviousPageAvailable() {
        return!isFirstPage();
    }


    /**
     * 下一页号
     * @return 取得下一页号
     */
    public long getNextPage() {
        if(isLastPage()) {
            returntotalItem;
        } else {
            return page+1;
        }
    }


    public long getPreviousPage() {
        if(isFirstPage()){
            return 1;
        } else {
            return page -1;
        }
    }
    /**
     * Method getPageSizereturns the pageSize of this PaginatedArrayList object.
     *
     *  每页大小
     *
     * @return thepageSize (type int) of this PaginatedArrayList object.
     */


    public long getPageSize() {
        return pageSize;
    }


    /**
     * Method setPageSizesets the pageSize of this PaginatedArrayList object.
     *
     *  每页大小
     *
     * @param pageSize thepageSize of this PaginatedArrayList object.
     *
     */


    public void setPageSize(long pageSize) {
        this.pageSize =pageSize;
        repaginate();
    }


    /**
     * Method getpagereturns the page of this PaginatedArrayList object.
     *
     *  当前页。第一页是1
     *
     * @return the page(type int) of this PaginatedArrayList object.
     */


    public long getPage(){
        return page;
    }


    /**
     * Method setpage setsthe page of this PaginatedArrayList object.
     *
     *  当前页。第一页是1
     *
     * @param page thepage of this PaginatedArrayList object.
     *
     */


    public void setPage(long page) {
        this.page = page;
        repaginate();
    }


    /**
     * Method getTotalItemreturns the totalItem of this PaginatedArrayList object.
     *
     *  总记录数
     *
     * @return thetotalItem (type int) of this PaginatedArrayList object.
     */


    public long getTotalItem() {
        return totalItem;
    }


    /**
     * Method setTotalItemsets the totalItem of this PaginatedArrayList object.
     *
     *  总记录数
     *
     * @param totalItemthe totalItem of this PaginatedArrayList object.
     *
     */


    public void setTotalItem(long totalItem) {
        this.totalItem =totalItem;
        if( this.totalItem<= 0){
            totalPage = 0;
            page = 1;
            startRow = 0;
        }
        repaginate();
    }






    /**
     * Method getTotalPagereturns the totalPage of this PaginatedArrayList object.
     *
     *  总页数
     *
     * @return thetotalPage (type int) of this PaginatedArrayList object.
     */


    public long getTotalPage() {
        return totalPage;
    }


    /**
     * Method getStartRowreturns the startRow of this PaginatedArrayList object.
     *
     *  分页后的记录开始的地方
     *
     * @return the startRow(type int) of this PaginatedArrayList object.
     */


    public long getStartRow() {
        if (startRow >0) {
            returnstartRow;
        }
        if (page <= 0){
            page = 1;
        }
        return (page - 1)* pageSize;
    }


    /**
     * Method getEndRowreturns the endRow of this PaginatedArrayList object.
     *
     *  分页后的记录结束的地方
     *
     * @return the endRow(type int) of this PaginatedArrayList object.
     */


    public long getEndRow() {
        if (endRow > 0){
            return endRow;
        }
        return page *pageSize;
    }


    public String getOrderField() {
        return orderField;
    }




    public void setOrderField(String orderField) {
        this.orderField =orderField;
    }


    public Boolean getIsAsc() {
        return isAsc;
    }


    public void setIsAsc(Boolean isAsc) {
        this.isAsc = isAsc;
    }


    /**
     * Method repaginate...
     */
    public void repaginate() {
        if (pageSize <1) { //防止程序偷懒,list和分页的混合使用
            pageSize =PAGESIZE_DEFAULT;
        }
        if (page < 1) {
            page = 1;//恢复到第一页
        }
        if (totalItem >0) {
            totalPage =totalItem / pageSize + (totalItem % pageSize > 0 ? 1 : 0);
            if(page >totalPage) {
                page =totalPage; //最大页
            }
            endRow = page* pageSize;
            startRow =(page - 1) * pageSize;
           if(endRow>totalItem) {
                endRow =totalItem;
            }
        }
    }
}

后端代码之数据持久层

实体层的代码我们已经完成了,接下拉我们自然需要完成数据持久层的代码了。考虑到前端页面的功能,查询/新增/修改/编辑/停用/启用的功能,我们在编写的时候,可以让数据操作更加面向对象一些。我们来看代码:

/**
 * Copyright(c) 2004-2020pangzi
 *com.pz.basic.mall.dao.sys.MallBrandDao.java
 */
package com.pz.basic.mall.dao.sys;
import com.pz.basic.mall.domain.sys.MallBrand;
import com.pz.basic.mall.domain.sys.query.QueryMallBrand;


import java.util.List;






/**
 *
 * @author pangzi
 * @date 2020-06-2610:56:01
 */
public interface MallBrandDao {


  /**
   * 根据条件查询总数
   * @param query
   * @return
   */
    long countByQuery(QueryMallBrand query);


    /**
   * 根据条件删除记录
   * @param query
   * @return
   */
    int deleteMallBrandByQuery(QueryMallBrand query);


    /**
   * 根据ID删除记录
   * @param id
   * @return
   */
    int deleteMallBrandById(long id);


    /**
   * 新增记录
   * @param record
   * @return
   */
    long insertMallBrand(MallBrand record);


     /**
   * 新增记录 注意:有值的记录才新增
   * @param record
   * @return
   */
    long insertMallBrandModified(MallBrand record);


    /**
   * 根据查询条件返回列表
   * @param query
   * @return
   */
    List selectMallBrandByQuery(QueryMallBrand query);


  /**
  * 根据查询条件返回列表
  * @param  query
  * @return
  */
     List selectMallBrandByPage(QueryMallBrand query);


     /**
   * 根据ID查询对象
   * @param id
   * @return
   */
    MallBrand selectMallBrandById(long id);




    /**
   * 根据id修改记录 注意:有值的字段才更新
   * @param record
   * @return
   */
    int updateMallBrandByIdModified(MallBrandrecord);
}

对应的mapper文件MallBrandMapper.xml.

猿实战03——猿首战之手把手教你撸品牌_第4张图片








  
          
                   
                   
                   
                   
                   
                   
                   
                   
                   
                                      


  
                   id,
                     brand_name,
                     logo,
                     first_char,
                     status,
                     active,
                     create_user,
                     modify_user,
                     created,
                     modified
          


  
    
          1=1


                               
                  and     id =  #{id}
               
                               
                  and      brand_name =  #{brandName}
               
                               
                  and      logo = #{logo}
               
                               
                  and      first_char =  #{firstChar}
               
                                
                  and      status = #{status}
               
                               
                  and      active = #{active}
               
                               
                  and      create_user =  #{createUser}
               
                               
                  and      modify_user =  #{modifyUser}
               
                               
                  and      created = #{created}
               
                                
                  and      modified =  #{modified}
               


                    
                        and      brand_name likeconcat(#{brandNameLike},'%')
                    


    
  




  




    




  
  
    delete from mall_brand
    where id = #{id}
  




  
    delete from mall_brand
    
      
    
  




  
    INSERT INTO
  mall_brand(id,brand_name,logo,first_char,status,active,create_user,modify_user,created,modified)
  VALUES(#{id},#{brandName},#{logo},#{firstChar},#{status},#{active},#{createUser},#{modifyUser},#{created},#{modified})
      
    select count(*) frommall_brand
    
      
    
  






  
    update mall_brand
    


                                                          
                     brand_name =  #{brandName},
                


                                                
                     logo=  #{logo},
                


                                                
                    first_char =  #{firstChar},
                


                                                
                    status =  #{status},
                


                                                
                    active =  #{active},
                


                                                
                    create_user =  #{createUser},
                


                                                
                    modify_user =  #{modifyUser},
                 


                                                
                    created =  #{created},
                


                                                
                    modified=now(),
                




    
    where id = #{id}
  





最后别忘了在mybatis的总控文件SqlMapConfig.xml中增加需要用到的别名和引用。

猿实战03——猿首战之手把手教你撸品牌_第5张图片

后端代码之service层

   我们之前已经说了,service层是编写业务的核心逻辑,通过调用dao方式完成业务逻辑对应的数据操作。

  

 /**
 * Copyright(c) 2004-2020 pangzi
 *com.pz.basic.mall.service.sys.MallBrandService.java
 */
package com.pz.basic.mall.service.sys;
import com.pz.basic.mall.domain.base.Result;
import com.pz.basic.mall.domain.sys.MallBrand;
import com.pz.basic.mall.domain.sys.query.QueryMallBrand;


import java.util.List;






/**
 * service层,组装外部接口和 本地业务,为本业务 或者其他业务提供服务,统一返回Result
 * 通过Result.isSuccess判断调用是否成功
 * 此类中新增业务接口设计(接口命令,入参数据,返回值)要能尽量完整的表达业务 含义
 * @author pangzi
 * @date 2020-06-26 11:20:40
 */
public interface MallBrandService {


   /**
    * 新增 mallBrand
    * 返回result,通过result.isSuccess()判断服务调用是否成功
    * 通过result.getModel()得到新增mallBrand
    * @param mallBrand
    * @return
    */
    public Result addMallBrand(MallBrand mallBrand) ;


    /**
     * 按照主键id更新mallBrand,请重新new MallBrand 的更新对象,设置要更新的字段
    * 返回result,通过result.isSuccess()判断更新是否成功
     * @param mallBrand
     * @return
     */
    public Result updateMallBrandById(MallBrandmallBrand);


    /**
     * 按照主键id 删除 记录
    * 返回result,通过result.isSuccess()判断删除是否成功
     * @return
     */
    public Result deleteMallBrandById(MallBrandmallBrand);


    /**
     * 查询列表,此接口不包含分页查询
    * 返回result,通过result.isSuccess()判断服务调用是否成功
    * 通过result.getModel()得到列表信息
     * @param queryMallBrand
     * @return
     */
    public Result> getMallBrandsByQuery(QueryMallBrand queryMallBrand);


    /**
     * 通过主键id查询MallBrand
    * 返回result,通过result.isSuccess()判断服务调用是否成功
    * 通过result.getModel()得到查询的单条mallBrand信息
     * @param id
     * @return
     */
    public Result getMallBrandById(long id);


    /**
     * 查询列表,包含分页查询
    * 查询分页信息,请设置
    * QueryMallBrand.setIndex(设置当前页数)
    *QueryMallBrand.setPageSize(设置当前页面数据行数)
    * 返回result,通过result.isSuccess()判断服务调用是否成功
    * 通过result.getTotal()返回结果总数
    * 通过result.getModel()得到查询的单页列表信息
     * @param queryMallBrand
     * @return
     */
    public Result> getMallBrandsByPage(QueryMallBrand queryMallBrand);


    /**
     * 查询总数
     * @param queryMallBrand
     * @return
     */
    public Result count(QueryMallBrand queryMallBrand);


   /**
    * 停用启用品牌列表
    * 返回result,通过result.isSuccess()判断服务调用是否成功
    * 通过result.getModel()得到列表信息
    * @param brandList
    * @param disable true 停用 false 启用
    * @return
    */
   public Result disableEnableMallBrandList(ListbrandList, boolean disable);


   /**
    * 逻辑删除品牌列表
    * 返回result,通过result.isSuccess()判断服务调用是否成功
    * 通过result.getModel()得到列表信息
    * @param brandList
    * @return
    */
   public Result deleteMallBrandList(ListbrandList);


}

 



/**
 * Copyright(c) 2004-2020 pangzi
 *com.pz.basic.mall.service.sys.impl.MallBrandService.java
 */
package com.pz.basic.mall.service.sys.impl;
import com.pz.basic.mall.dao.sys.MallBrandDao;


import java.util.ArrayList;
import java.util.List;


import com.pz.basic.mall.domain.base.Result;
import com.pz.basic.mall.domain.base.enums.DataActiveStatusEnum;
import com.pz.basic.mall.domain.base.enums.DataStatusEnum;
import com.pz.basic.mall.domain.sys.query.QueryMallBrand;
import com.pz.basic.mall.service.sys.MallBrandService;


import com.pz.basic.mall.domain.sys.MallBrand;




/**
 *
 * @author pangzi
 * @date 2020-06-26 11:25:00
 */
public class MallBrandServiceImpl implements MallBrandService {




   private MallBrandDao mallBrandDao;


   public void setMallBrandDao(MallBrandDao mallBrandDao) {
      this.mallBrandDao =mallBrandDao;
   }
    public Result addMallBrand(MallBrand mallBrand) {
      Result result = new Result();
      try {
        QueryMallBrand query = new QueryMallBrand();
        query.setBrandName(mallBrand.getBrandName());
        long count = mallBrandDao.countByQuery(query);
        if(count>0){
           result.setSuccess(false);
           result.setMessage("品牌名已存在");
           return result;
        }
      mallBrand.setStatus(DataStatusEnum.STATUS_ENABLE.getStatusValue());
      mallBrand.setActive(DataActiveStatusEnum.STATUS_ACTIVE.getStatusValue());
      mallBrandDao.insertMallBrand(mallBrand);
            result.addDefaultModel(mallBrand);
      } catch(Exception e) {
        result.setSuccess(false);
      }
      return result;
    }


    public Result updateMallBrandById(MallBrandmallBrand) {
      Result result = new Result();
      try {
        int count=mallBrandDao.updateMallBrandByIdModified(mallBrand);
        if(count>0){
        result.setSuccess(true);
           }
      } catch(Exception e) {
        result.setSuccess(false);
      }
      return result;
    }


    public Result deleteMallBrandById(MallBrandmallBrand) {
      Result result = new Result();
      try {
        int count=0;
        MallBrand modifiedMallBrand = new MallBrand();
        modifiedMallBrand.setId(mallBrand.getId());
      modifiedMallBrand.setActive(DataActiveStatusEnum.STATUS_DELETED.getStatusValue());
         count=mallBrandDao.updateMallBrandByIdModified(modifiedMallBrand);
        if(count>0){
        result.setSuccess(true);
            }
      } catch(Exception e) {
        result.setSuccess(false);
      }
      return result;
    }


    public Result> getMallBrandsByQuery(QueryMallBrand queryMallBrand) {
      Result> result = newResult>();
      try {
      queryMallBrand.setActive(DataActiveStatusEnum.STATUS_ACTIVE.getStatusValue());
        result.addDefaultModel("MallBrands",mallBrandDao.selectMallBrandByQuery(queryMallBrand));
      } catch(Exception e) {
        result.setSuccess(false);
      }
      return result;  
    }


    public Result getMallBrandById(longid) {
      Result result = new Result();
      try {  
        result.addDefaultModel("MallBrand",mallBrandDao.selectMallBrandById(id));
      } catch(Exception e) {
        result.setSuccess(false);
      }
      return result;  
    }




   public Result> getMallBrandsByPage(QueryMallBrand queryMallBrand) {


      Result> result = newResult>();
   queryMallBrand.setActive(DataActiveStatusEnum.STATUS_ACTIVE.getStatusValue());
        long totalItem =mallBrandDao.countByQuery(queryMallBrand);
      queryMallBrand.setTotalItem(totalItem);
      queryMallBrand.repaginate();
      if (totalItem > 0) {
   result.addDefaultModel(mallBrandDao.selectMallBrandByPage(queryMallBrand));
      } else {
      result.addDefaultModel(new ArrayList());
      }
      result.setTotalItem(totalItem);
      result.setPageSize(queryMallBrand.getPageSize());
      result.setPage(queryMallBrand.getPage());


      return result;
    }


    public Result count(QueryMallBrand queryMallBrand) {
      Result result = new Result();
   queryMallBrand.setActive(DataActiveStatusEnum.STATUS_ACTIVE.getStatusValue());
      try {
         result.addDefaultModel(mallBrandDao.countByQuery(queryMallBrand));
      } catch(Exception e) {
        result.setSuccess(false);
      }
      return result;  
    }




   public Result disableEnableMallBrandList(ListbrandList, boolean disable) {


      Result result = new Result();
      try {
        for (MallBrand brand : brandList) {
           if (disable) {
              brand.setStatus(DataStatusEnum.STATUS_DISABLE.getStatusValue());
           } else {
              brand.setStatus(DataStatusEnum.STATUS_ENABLE.getStatusValue());
           }
           mallBrandDao.updateMallBrandByIdModified(brand);
        }
      }catch(Exception e){
        result.setSuccess(false);
      }
      return result;
   }
 
   public Result deleteMallBrandList(List brandList){
      Result result = new Result();
      try {
        for (MallBrand brand : brandList) {
        brand.setActive(DataActiveStatusEnum.STATUS_DELETED.getStatusValue());
           mallBrandDao.updateMallBrandByIdModified(brand);
        }
      }catch(Exception e){
        result.setSuccess(false);
      }
      return result;
   }
}

最后,不要忘记了,在spring-service.xml增加service的配置


后端代码之Controller层

我们提供给前端访问的数据接口,是通过Controller暴露出去的,前端通过HttpJSON的方式到后端获取需要的数据。在这一点上,我们使用SpringMVC的RestController能够获得比较好的支持。

/**
 * Copyright(c) 2004-2020pangzi
 *com.pz.basic.mall.controller.sys.MallBrandController.java
 */
package com.pz.basic.mall.controller.sys;


import com.pz.basic.mall.domain.base.Result;
import com.pz.basic.mall.domain.base.enums.DataStatusEnum;
import com.pz.basic.mall.domain.sys.MallBrand;
import com.pz.basic.mall.domain.sys.query.QueryMallBrand;
import com.pz.basic.mall.service.sys.MallBrandService;
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;




/**
 *
 * @author pangzi
 * @date 2020-06-2220:47:27
 *
 *
 */
@RestController
@RequestMapping("/brandManage")
public class MallBrandController {




    private MallBrandService mallBrandService;




    public void setMallBrandService(MallBrandService mallBrandService) {
        this.mallBrandService= mallBrandService;
    }






    /**
     * 新增品牌
     * @param mallBrand
     * @return
     */
   @RequestMapping("/addMallBrand")
    public Result addMallBrand(@RequestBody MallBrand mallBrand){
        try{


            return   mallBrandService.addMallBrand(mallBrand);
        }catch(Exceptione){
           e.printStackTrace();
            return newResult(false);
        }
    }




    /**
     * 修改品牌
     * @param mallBrand
     * @return
     */
   @RequestMapping("/updateMallBrand")
    public Result updateMallBrand(@RequestBody MallBrand mallBrand){
        try{
            return mallBrandService.updateMallBrandById(mallBrand);
        }catch(Exceptione){
           e.printStackTrace();
            return newResult(false);
        }
    }


    /**
     * 启用品牌
     * @param mallBrand
     * @return
     */
   @RequestMapping("/enableMallBrand")
    public Result enableMallBrand(@RequestBody MallBrand mallBrand){
        try{
            MallBrandmodifiedData =new MallBrand ();
           modifiedData.setId(mallBrand.getId());
           modifiedData.setStatus(DataStatusEnum.STATUS_ENABLE.getStatusValue());
            return mallBrandService.updateMallBrandById(modifiedData);
        }catch(Exceptione){
            e.printStackTrace();
            return newResult(false);
        }
    }




    /**
     * 停用品牌
     * @param mallBrand
     * @return
     */
   @RequestMapping("/disableMallBrand")
    public Result disableMallBrand(@RequestBody MallBrand mallBrand){
        try{
            MallBrandmodifiedData =new MallBrand ();
           modifiedData.setId(mallBrand.getId());
           modifiedData.setStatus(DataStatusEnum.STATUS_DISABLE.getStatusValue());
            return  mallBrandService.updateMallBrandById(modifiedData);
        }catch(Exceptione){
           e.printStackTrace();
            return newResult(false);
        }
    }


    /**
     * 删除品牌
     * @param mallBrand
     * @return
     */
   @RequestMapping("/deleteMallBrand")
    public Result deleteMallBrand(@RequestBody MallBrand mallBrand){
        try{
            return mallBrandService.deleteMallBrandById(mallBrand);
        }catch(Exceptione){
           e.printStackTrace();
            return newResult(false);
        }
    }




    /**
     * 分页返回品牌列表
     * @paramqueryMallBrand
     * @return
     */
   @RequestMapping("/findByPage")
    public  Result> findByPage(@RequestBody  QueryMallBrandqueryMallBrand){
        returnmallBrandService.getMallBrandsByPage(queryMallBrand);
    }




    /**
     * 修改品牌
     * @param brandList
     * @return
     */
   @RequestMapping("/disableMallBrandList")
    public Result disableMallBrandList(@RequestBody List brandList){
        try{
            return  mallBrandService.disableEnableMallBrandList(brandList,true);
        }catch(Exceptione){
           e.printStackTrace();
            return newResult(false);
        }
    }


    /**
     * 修改品牌
     * @param brandList
     * @return
     */
    @RequestMapping("/enableMallBrandList")
    public Result enableMallBrandList(@RequestBody List brandList){
        try{
            return mallBrandService.disableEnableMallBrandList(brandList,false);
        }catch(Exceptione){
           e.printStackTrace();
            return newResult(false);
        }
    }


    /**
     * 修改品牌
     * @param brandList
     * @return
     */
   @RequestMapping("/deleteMallBrandList")
    public Result deleteMallBrandList(@RequestBody List brandList){
        try{
            return mallBrandService.deleteMallBrandList(brandList);
        }catch(Exceptione){
           e.printStackTrace();
            return newResult(false);
        }
    }


}

到目前为止,后端代码的编写告一段落。

前端代码之API层

后端接口的主要作用是为前端提供数据支撑,前端针对这些后端接口,可以做一些封装,然后交由需要调用的页面使用。为了保证功能的相对独立和后续前端代码的维护,我们需要对品牌管理相关的功能做一些封装——在api目录下建立basedataManage目录,然后建立basedataManage.js文件,之后基础数据相关的api我们都维护在这里。

根据页面后端提供的数据接口,我们需要封装如下封装。

export function fetchBrandList(query) {
  return request({
    url:'/brandManage/findByPage',
    method: 'post',
    data: query
  })
}


export function createBrand(data) {
  return request({
    url:'/brandManage/addMallBrand',
    method: 'post',
    data: data
  })
}


export function updateBrand(data) {
  return request({
    url: '/brandManage/updateMallBrand',
    method: 'post',
    data: data
  })
}


export function disableMallBrandList(data) {
  return request({
    url:'/brandManage/disableMallBrandList',
    method: 'post',
    data: data
  })
}


export function enableMallBrand(data) {
  return request({
    url:'/brandManage/enableMallBrand',
    method: 'post',
    data: data
  })
}


export function deleteMallBrand(data) {
  return request({
    url:'/brandManage/deleteMallBrand',
    method: 'post',
    data: data
  })
}


export function disableMallBrand(data) {
  return request({
    url:'/brandManage/disableMallBrand',
    method: 'post',
    data: data
  })
}


export function enableMallBrandList(data) {
  return request({
    url:'/brandManage/enableMallBrandList',
    method: 'post',
    data: data
  })
}


export function deleteMallBrandList(data) {
  return request({
    url:'/brandManage/deleteMallBrandList',
    method: 'post',
    data: data
  })
}

前端代码之组件引入

我们已经封装好了数据操作相关的API了,那么接下来的事情,自然是引入我们需要的组件了。在brand-management.vue文件中,建立如下标记。


其中import的就是我们封装的API以及Pagination组件了。注意这个结构,components暴露出来的就是组件在页面具体使用的名称。

data()函数的返回值,就是页面中需要的数据。created函数,会在页面创建时执行,如果有一些需要初始化的事情,可以交由它进行处理。

methods中我们可以定义页面所需要的函数。

前端代码之列表数据

我们怎样才能实现品牌列表的功能呢?自然是需要前端页面来调用后端接口来完成了。由于我们还要支持品牌名的模糊查询,所以我们还要为此定义一个数据结构用于存放查询条件。定义一个数组用于存放返回的数据。

// table数据集合
list: null,
listQuery: {
        brandName: '',
        firsChar: '',
        page: 1,
        pageSize: 10
      }

注意噢,以json的格式放在data()函数中,作为返回值的一部分返回就好。同时在methods区域编写获取列表的函数

// 列表方法查询
    getList() {
      this.listLoading =true
     fetchBrandList(this.listQuery).then(response => {
        this.list =response.model
        this.total =response.totalItem
        // Just to simulatethe time of the request
        setTimeout(()=> {
          this.listLoading= false
        }, 1.5 * 1000)
      })
    }

为了方便页面初始化的时候有数据展示,我们可以在created函数中调用它。

created() {
    // 列表查询
    this.getList()
  }

至于列表数据的展示,当然是的el-table去展示了。

猿实战03——猿首战之手把手教你撸品牌_第6张图片

前端代码之新增/编辑

新增和修改品牌的功能主要是由el-dialog组件来实现的,通过表单,隐藏和展示的方式来完成新增/编辑工作。为此我们同样需要定义数据来处理这些页面逻辑。

temp: {
        id: undefined,
        // 品牌名称
        brandName: '',
        // 品牌首字母
        firsChar: '',
        logo: '',
        imageUrl: ''
      },
      dialogStatus: '',
      textMap: {
        update: '编辑品牌',
        create: '新增品牌'
      },
      // 弹框是否显示
      dialogFormVisible:false,

至于页面数据的前端校验,我们可以使用定义Rule规则的方式完成。

 

 rules: {
        brandName: [{required: true, message: '请输入品牌名称',trigger: 'change' }],
        firstChar: [{required: true, message: '请输入品牌首字母(英文大写)', trigger: 'change' }],
        logo: [{ required:true, message: '请上传品牌logo', trigger:'change' }]
      }

注意噢,每一种规则都是一个数组,一个规则是支持同时存在多条的噢。

至于新增/编辑弹出页面动作,则是通过定义函数,通过button的事件触发来完成的。

resetTemp() {
      this.temp = {
        id: undefined,
        // 品牌名称
        brandName: '',
        // 品牌首字母
        firstChar: '',
        logo: ''
      }
      this.dialogVisible =false
      if(this.$refs.upload !== null && undefined !== this.$refs.upload) {
       this.$refs.upload.clearFiles()
      }
     console.log(this.$refs.upload)
    },
    // 新增
    addBrand() {
      this.resetTemp()
      this.dialogStatus ='create'
     this.dialogFormVisible = true
      this.$nextTick(()=> {
       this.$refs['dataForm'].clearValidate()
      })
    },
至于数据持久,同样也是button绑定函数的方式来完成。
// 更新保存方法
    updateData() {
      this.$refs['dataForm'].validate((valid)=> {
        if (valid) {
          const tempData =Object.assign({}, this.temp)
         updateBrand(tempData).then(() => {
            const index =this.list.findIndex(v => v.id === this.temp.id)
           this.list.splice(index, 1, this.temp)
           this.dialogFormVisible = false
            this.$notify({
              title:'Success',
              message:'Update Successfully',
              type:'success',
              duration:2000
            })
          })
        }
      })
    },
    // 创建保存方法
    createData() {
     this.$refs['dataForm'].validate((valid) => {
        if (valid) {
         createBrand(this.temp).then((res) => {
            this.temp.id =res.model.id
           this.list.unshift(this.temp)
           this.dialogFormVisible = false
            this.$notify({
              title:'Success',
              message:'Created Successfully',
              type:'success',
              duration:2000
            })
          })
        }
      })
    },

前端代码之其它功能

前端的停用/启用/删除功能,大家可以看下,篇幅有限,就不一一例举了——最主要的是你不能懒惰,敲代码的事情,必须自己搞了。给你一些例子,自己去完善!

猿实战03——猿首战之手把手教你撸品牌_第7张图片

猿实战03——猿首战之手把手教你撸品牌_第8张图片

猿实战03——猿首战之手把手教你撸品牌_第9张图片

猿实战03——猿首战之手把手教你撸品牌_第10张图片

猿实战03——猿首战之手把手教你撸品牌_第11张图片

猿实战03——猿首战之手把手教你撸品牌_第12张图片

猿实战03——猿首战之手把手教你撸品牌_第13张图片

猿实战03——猿首战之手把手教你撸品牌_第14张图片

到此为止,我们项目的开发框架搭建完毕。
  如学习过程中遇到疑难杂症,自己实在搞不定,可以在blog中寻找联系方式或通过评论的方式,帮你解决。
  

 

 

你可能感兴趣的:(猿进化,java,mysql,数据库,大数据,spring)