上一个章节,猿人君教会了你如何去实现前台类目,虽然已经讲得很详细了,还是有朋友认为比较困难。可能是每个人的基础真的不一样吧。
今天猿人君打算再讲一次很基础的内容,希望通过设置广告牌这样的一个完整小功能,帮助到你走向开发之路。
功能概览
在一级前台类目页面,可以设置一级类目的广告牌,注意,是设置,如果当前类目已经存在广告牌,那么展示原有内容,之后可以修改广告牌内容,如果没有设置,那么设置广告牌信息之后,是新增操作。
广告牌数据库设计
根据广告牌设置功能,整理出来的数据库表如上图所示。广告牌本质上是一个图片,点击图片后,可以跳转链接,支持位图跳转的方式。
广告牌功能后端功能实现
因为要满足广告牌设置的功能,后端需要给前端提供新增/编辑,以及查找的功能。
我们看看controller:
/**
* Copyright(c) 2004-2020 pangzi
* com.pz.basic.mall.controller.product.fncategory. MallFnCategoryBillboardController.java
*/
package com.pz.basic.mall.controller.product.fncategory;
import com.pz.basic.mall.domain.base.Result;
import com.pz.basic.mall.domain.product.fncategory. MallFnCategoryBillboard;
import com.pz.basic.mall.domain.product.fncategory.query.QueryMallFnCategoryBillboard;
import com.pz.basic.mall.service.product.fncategory. MallFnCategoryBillboardService;
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-22 20:47:27
*
*
*/
@RestController
@RequestMapping("/fncategorybillboard")
public class MallFnCategoryBillboardController {
private MallFnCategoryBillboardService mallFnCategoryBillboardService;
public void setMallFnCategoryBillboardService( MallFnCategoryBillboardService mallFnCategoryBillboardService) {
this.mallFnCategoryBillboardService = mallFnCategoryBillboardService;
}
/**
* 新增广告牌
* @param mallFnCategoryBillboard
* @return
*/
@RequestMapping("/addMallFnCategoryBillboard")
public Result< MallFnCategoryBillboard> addMallFnCategoryBillboard(@RequestBody MallFnCategoryBillboard mallFnCategoryBillboard){
try{
return mallFnCategoryBillboardService.addMallFnCategoryBillboard( mallFnCategoryBillboard);
}catch(Exception e){
e.printStackTrace();
return new Result(false);
}
}
/**
* 根据ID查找广告牌
* @param mallFnCategoryBillboard
* @return
*/
@RequestMapping("/findMallFnCategoryBillboardById")
public Result< MallFnCategoryBillboard> findMallFnCategoryBillboardById(@RequestBody MallFnCategoryBillboard mallFnCategoryBillboard){
return mallFnCategoryBillboardService.getMallFnCategoryBillboardById(mallFnCategoryBillboard.getId());
}
/**
* 修改广告牌
* @param mallFnCategoryBillboard
* @return
*/
@RequestMapping("/updateMallFnCategoryBillboard")
public Result updateMallFnCategoryBillboard(@RequestBody MallFnCategoryBillboard mallFnCategoryBillboard){
try{
return mallFnCategoryBillboardService.updateMallFnCategoryBillboardById(mallFnCategoryBillboard);
}catch(Exception e){
e.printStackTrace();
return new Result(false);
}
}
/**
* 分页返回广告牌列表
* @param queryMallFnCategoryBillboard
* @return
*/
@RequestMapping("/findByPage")
public Result<List< MallFnCategoryBillboard>> findByPage(@RequestBody QueryMallFnCategoryBillboard queryMallFnCategoryBillboard){
return mallFnCategoryBillboardService.getMallFnCategoryBillboardsByPage(queryMallFnCategoryBillboard);
}
}
Service层及实现
/**
* Copyright(c) 2004-2020 pangzi
* com.pz.basic.mall.service.product.fncategory.MallFnCategoryBillboardService.java
*/
package com.pz.basic.mall.service.product.fncategory;
import com.pz.basic.mall.domain.base.Result;
import com.pz.basic.mall.domain.product.fncategory.MallFnCategoryBillboard;
import com.pz.basic.mall.domain.product.fncategory.query.QueryMallFnCategoryBillboard;
import java.util.List;
/**
* service层,组装外部接口 和 本地业务,为本业务 或者其他业务提供服务,统一返回Result
* 通过Result.isSuccess判断调用是否成功
* 此类中新增业务接口设计(接口命令,入参数据,返回值)要 能尽量完整的表达业务 含义
* @author pangzi
* @date 2020-07-02 11:09:13
*/
public interface MallFnCategoryBillboardService {
/**
* 新增 mallFnCategoryBillboard
* 返回result,通过result.isSuccess()判断服务调用是否成功
* 通过result.getModel()得到新增 mallFnCategoryBillboard
* @param mallFnCategoryBillboard
* @return
*/
public Result<MallFnCategoryBillboard> addMallFnCategoryBillboard(MallFnCategoryBillboard mallFnCategoryBillboard) ;
/**
* 按照主键id更新mallFnCategoryBillboard,请重新new MallFnCategoryBillboard 的更新对象,设置要更新的字段
* 返回result,通过result.isSuccess()判断更新是否成功
* @param mallFnCategoryBillboard
* @return
*/
public Result updateMallFnCategoryBillboardById( MallFnCategoryBillboard mallFnCategoryBillboard);
/**
* 按照主键id 删除 记录
* 返回result,通过result.isSuccess()判断删除是否成功
* @param id
* @return
*/
public Result deleteMallFnCategoryBillboardById(long id);
/**
* 查询列表,此接口不包含分页查询
* 返回result,通过result.isSuccess()判断服务调用是否成功
* 通过result.getModel()得到列表信息
* @param queryMallFnCategoryBillboard
* @return
*/
public Result<List<MallFnCategoryBillboard>> getMallFnCategoryBillboardsByQuery(QueryMallFnCategoryBillboard queryMallFnCategoryBillboard);
/**
* 通过主键id查询MallFnCategoryBillboard
* 返回result,通过result.isSuccess()判断服务调用是否成功
* 通过result.getModel()得到查询的单条mallFnCategoryBillboard信息
* @param id
* @return
*/
public Result<MallFnCategoryBillboard> getMallFnCategoryBillboardById(long id);
/**
* 查询列表,包含分页查询
* 查询分页信息,请设置
* QueryMallFnCategoryBillboard.setIndex(设置当前页数)
* QueryMallFnCategoryBillboard.setPageSize(设置当前页面数据行数)
* 返回result,通过result.isSuccess()判断服务调用是否成功
* 通过result.getTotal()返回结果总数
* 通过result.getModel()得到查询的单页列表信息
* @param queryMallFnCategoryBillboard
* @return
*/
public Result<List<MallFnCategoryBillboard>> getMallFnCategoryBillboardsByPage(QueryMallFnCategoryBillboard queryMallFnCategoryBillboard);
/**
* 查询总数
* @param queryMallFnCategoryBillboard
* @return
*/
public Result<Long> count(QueryMallFnCategoryBillboard queryMallFnCategoryBillboard);
}
/**
* Copyright(c) 2004-2020 pangzi
* com.pz.basic.mall.service.product.fncategory.impl.MallFnCategoryBillboardService.java
*/
package com.pz.basic.mall.service.product.fncategory.impl;
import java.util.List;
import com.pz.basic.mall.domain.base.Result;
import com.pz.basic.mall.domain.product.fncategory.MallFnCategoryBillboard;
import com.pz.basic.mall.dao.product.fncategory.MallFnCategoryBillboardDao;
import com.pz.basic.mall.domain.product.fncategory.query.QueryMallFnCategoryBillboard;
import com.pz.basic.mall.service.product.fncategory.MallFnCategoryBillboardService;
import java.util.ArrayList;
import java.util.Map;
import java.io.Serializable;
/**
*
* @author pangzi
* @date 2020-07-02 11:09:13
*/
public class MallFnCategoryBillboardServiceImpl implements MallFnCategoryBillboardService {
private MallFnCategoryBillboardDao mallFnCategoryBillboardDao;
public void setMallFnCategoryBillboardDao(MallFnCategoryBillboardDao mallFnCategoryBillboardDao) {
this.mallFnCategoryBillboardDao = mallFnCategoryBillboardDao;
}
public Result<MallFnCategoryBillboard> addMallFnCategoryBillboard(MallFnCategoryBillboard mallFnCategoryBillboard) {
Result<MallFnCategoryBillboard> result = new Result<MallFnCategoryBillboard>();
try {
mallFnCategoryBillboardDao.insertMallFnCategoryBillboardModified(mallFnCategoryBillboard);
result.addDefaultModel(mallFnCategoryBillboard);
} catch(Exception e) {
result.setSuccess(false);
}
return result;
}
public Result updateMallFnCategoryBillboardById(MallFnCategoryBillboard mallFnCategoryBillboard) {
Result result = new Result();
try {
int count= mallFnCategoryBillboardDao.updateMallFnCategoryBillboardByIdModified(mallFnCategoryBillboard);
if(count>0){
result.setSuccess(true);
}
} catch(Exception e) {
result.setSuccess(false);
}
return result;
}
public Result deleteMallFnCategoryBillboardById(long id) {
Result result = new Result();
try {
int count= mallFnCategoryBillboardDao.deleteMallFnCategoryBillboardById(id);
if(count>0){
result.setSuccess(true);
}
} catch(Exception e) {
result.setSuccess(false);
}
return result;
}
public Result<List<MallFnCategoryBillboard>> getMallFnCategoryBillboardsByQuery(QueryMallFnCategoryBillboard queryMallFnCategoryBillboard) {
Result<List<MallFnCategoryBillboard>> result = new Result<List<MallFnCategoryBillboard>>();
try {
result.addDefaultModel( mallFnCategoryBillboardDao.selectMallFnCategoryBillboardByQuery(queryMallFnCategoryBillboard));
} catch(Exception e) {
result.setSuccess(false);
}
return result;
}
public Result<MallFnCategoryBillboard> getMallFnCategoryBillboardById(long id) {
Result<MallFnCategoryBillboard> result = new Result<MallFnCategoryBillboard>();
try {
result.addDefaultModel(mallFnCategoryBillboardDao.selectMallFnCategoryBillboardById(id));
} catch(Exception e) {
result.setSuccess(false);
}
return result;
}
public Result<List<MallFnCategoryBillboard>> getMallFnCategoryBillboardsByPage(QueryMallFnCategoryBillboard queryMallFnCategoryBillboard) {
Result<List<MallFnCategoryBillboard>> result = new Result<List<MallFnCategoryBillboard>>();
long totalItem = mallFnCategoryBillboardDao.countByQuery(queryMallFnCategoryBillboard);
queryMallFnCategoryBillboard.setTotalItem(totalItem);
queryMallFnCategoryBillboard.repaginate();
if (totalItem > 0) {
result.addDefaultModel( mallFnCategoryBillboardDao.selectMallFnCategoryBillboardByPage(queryMallFnCategoryBillboard));
} else {
result.addDefaultModel(new ArrayList<MallFnCategoryBillboard>());
}
result.setTotalItem(totalItem);
result.setPageSize(queryMallFnCategoryBillboard.getPageSize());
result.setPage(queryMallFnCategoryBillboard.getPage());
return result;
}
public Result<Long> count(QueryMallFnCategoryBillboard queryMallFnCategoryBillboard) {
Result<Long> result = new Result<Long>();
try {
result.addDefaultModel(mallFnCategoryBillboardDao.countByQuery(queryMallFnCategoryBillboard));
} catch(Exception e) {
result.setSuccess(false);
}
return result;
}
}
Dao层:
/**
* Copyright(c) 2004-2020 pangzi
* com.pz.basic.mall.dao.product.fncategory.MallFnCategoryBillboardDao.java
*/
package com.pz.basic.mall.dao.product.fncategory;
import java.util.List;
import com.pz.basic.mall.domain.product.fncategory.MallFnCategoryBillboard;
import com.pz.basic.mall.domain.product.fncategory.query.QueryMallFnCategoryBillboard;
import java.util.Map;
import java.io.Serializable;
/**
*
* @author pangzi
* @date 2020-07-02 11:09:13
*/
public interface MallFnCategoryBillboardDao {
/**
* 根据条件查询总数
* @param QueryMallFnCategoryBillboard query
* @return
*/
long countByQuery(QueryMallFnCategoryBillboard query);
/**
* 根据条件删除记录
* @param MallFnCategoryBillboardQuery query
* @return
*/
int deleteMallFnCategoryBillboardByQuery(QueryMallFnCategoryBillboard query);
/**
* 根据ID删除记录
* @param id
* @return
*/
int deleteMallFnCategoryBillboardById(long id);
/**
* 新增记录
* @param MallFnCategoryBillboard record
* @return
*/
long insertMallFnCategoryBillboard(MallFnCategoryBillboard record);
/**
* 新增记录 注意:有值的记录才新增
* @param MallFnCategoryBillboard record
* @return
*/
long insertMallFnCategoryBillboardModified(MallFnCategoryBillboard record);
/**
* 根据查询条件返回列表
* @param QueryMallFnCategoryBillboard query
* @return
*/
List<MallFnCategoryBillboard> selectMallFnCategoryBillboardByQuery(QueryMallFnCategoryBillboard query);
/**
* 根据查询条件返回列表
* @param QueryMallFnCategoryBillboard query
* @return
*/
List<MallFnCategoryBillboard> selectMallFnCategoryBillboardByPage(QueryMallFnCategoryBillboard query);
/**
* 根据ID查询对象
* @param Long id
* @return
*/
MallFnCategoryBillboard selectMallFnCategoryBillboardById(long id);
/**
* 根据id修改记录 注意:有值的字段才更新
* @param MallFnCategoryBillboard record
* @return
*/
int updateMallFnCategoryBillboardByIdModified(MallFnCategoryBillboard record);
}
Mapper:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.pz.basic.mall.dao.product.fncategory.MallFnCategoryBillboardDao">
<resultMap id="ResultMap" type="MallFnCategoryBillboard">
<id property="id" column="id"/>
<id property="fnCategoryId" column="fn_category_id"/>
<id property="imageUrl" column="image_url"/>
<id property="type" column="type"/>
<id property="redirectArea" column="redirect_area"/>
<id property="features" column="features"/>
<id property="status" column="status"/>
<id property="createUser" column="create_user"/>
<id property="modifyUser" column="modify_user"/>
<id property="created" column="created"/>
<id property="modified" column="modified"/>
</resultMap>
<sql id="ALL_TABLE_COLOUM">
id,
fn_category_id,
image_url,
type,
redirect_area,
features,
status,
create_user,
modify_user,
created,
modified
</sql>
<sql id="Query_Where_Clause" >
<where >
1=1
<if test="id != null and id != ''">
and id = #{id}
</if>
<if test="fnCategoryId != null and fnCategoryId != ''">
and fn_category_id = #{fnCategoryId}
</if>
<if test="imageUrl != null and imageUrl != ''">
and image_url = #{imageUrl}
</if>
<if test="type != null and type != ''">
and type = #{type}
</if>
<if test="redirectArea != null and redirectArea != ''">
and redirect_area = #{redirectArea}
</if>
<if test="features != null and features != ''">
and features = #{features}
</if>
<if test="status != null and status != ''">
and status = #{status}
</if>
<if test="createUser != null and createUser != ''">
and create_user = #{createUser}
</if>
<if test="modifyUser != null and modifyUser != ''">
and modify_user = #{modifyUser}
</if>
<if test="created != null and created != ''">
and created = #{created}
</if>
<if test="modified != null and modified != ''">
and modified = #{modified}
</if>
</where>
</sql>
<sql id="Update_By_Query_Where_Clause" >
<where >
<choose>
<when test="id != null and id != ''">
id = #{id},
</when>
<when test="fnCategoryId != null and fnCategoryId != ''">
fn_category_id = #{fnCategoryId},
</when>
<when test="imageUrl != null and imageUrl != ''">
image_url = #{imageUrl},
</when>
<when test="type != null and type != ''">
type = #{type},
</when>
<when test="redirectArea != null and redirectArea != ''">
redirect_area = #{redirectArea},
</when>
<when test="features != null and features != ''">
features = #{features},
</when>
<when test="status != null and status != ''">
status = #{status},
</when>
<when test="createUser != null and createUser != ''">
create_user = #{createUser},
</when>
<when test="modifyUser != null and modifyUser != ''">
modify_user = #{modifyUser},
</when>
<when test="created != null and created != ''">
created = #{created},
</when>
<when test="modified != null and modified != ''">
modified = #{modified},
</when>
</choose>
</where>
</sql>
<select id="selectMallFnCategoryBillboardByQuery" resultMap="ResultMap" parameterType="QueryMallFnCategoryBillboard" >
select
<include refid="ALL_TABLE_COLOUM" />
from mall_fn_category_billboard
<if test="page != null" >
<include refid="Query_Where_Clause" />
</if>
</select>
<select id="selectMallFnCategoryBillboardByPage" resultMap="ResultMap" parameterType="QueryMallFnCategoryBillboard" >
select
<include refid="ALL_TABLE_COLOUM" />
from mall_fn_category_billboard
<if test="page != null" >
<include refid="Query_Where_Clause" />
</if>
LIMIT #{startRow},#{pageSize}
</select>
<select id="selectMallFnCategoryBillboardById" resultMap="ResultMap" parameterType="long" >
select
<include refid="ALL_TABLE_COLOUM" />
from mall_fn_category_billboard
where id = #{id}
</select>
<delete id="deleteMallFnCategoryBillboardById" parameterType="long" >
delete from mall_fn_category_billboard
where id = #{id}
</delete>
<delete id="deleteMallFnCategoryBillboardByQuery" parameterType= "QueryMallFnCategoryBillboard" >
delete from mall_fn_category_billboard
<if test="page != null" >
<include refid="Query_Where_Clause" />
</if>
</delete>
<insert id="insertMallFnCategoryBillboard" parameterType="MallFnCategoryBillboard" >
INSERT INTO
mall_fn_category_billboard(id,fn_category_id,image_url,type,redirect_area,features,status,create_user,modify_user,created,modified)
VALUES(#{id},#{fnCategoryId},#{imageUrl},#{type},#{redirectArea},#{features},#{status},#{createUser},#{modifyUser},#{created},#{modified})
<selectKey resultType="long" keyProperty="id">
SELECT @@IDENTITY AS ID
</selectKey>
</insert>
<insert id="insertMallFnCategoryBillboardModified" parameterType="MallFnCategoryBillboard" >
insert into mall_fn_category_billboard
<trim prefix="(" suffix=")" suffixOverrides="," >
<if test="id != null" >
id,
</if>
<if test="fnCategoryId != null" >
fn_category_id,
</if>
<if test="imageUrl != null" >
image_url,
</if>
<if test="type != null" >
type,
</if>
<if test="redirectArea != null" >
redirect_area,
</if>
<if test="features != null" >
features,
</if>
<if test="status != null" >
status,
</if>
<if test="createUser != null" >
create_user,
</if>
<if test="modifyUser != null" >
modify_user,
</if>
<if test="created == null" >
created,
</if>
<if test="modified == null" >
modified,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides="," >
<if test="id != null" >
#{id},
</if>
<if test="fnCategoryId != null" >
#{fnCategoryId},
</if>
<if test="imageUrl != null" >
#{imageUrl},
</if>
<if test="type != null" >
#{type},
</if>
<if test="redirectArea != null" >
#{redirectArea},
</if>
<if test="features != null" >
#{features},
</if>
<if test="status != null" >
#{status},
</if>
<if test="createUser != null" >
#{createUser},
</if>
<if test="modifyUser != null" >
#{modifyUser},
</if>
<if test="created == null" >
now(),
</if>
<if test="modified == null" >
now(),
</if>
</trim>
<selectKey resultType="long" keyProperty="id">
SELECT @@IDENTITY AS ID
</selectKey>
</insert>
<select id="countByQuery" parameterType="QueryMallFnCategoryBillboard" resultType="java.lang.Long" >
select count(*) from mall_fn_category_billboard
<if test="page != null" >
<include refid="Query_Where_Clause" />
</if>
</select>
<update id="updateMallFnCategoryBillboardByIdModified" parameterType="MallFnCategoryBillboard" >
update mall_fn_category_billboard
<set >
<if test="fnCategoryId != null" >
fn_category_id = #{fnCategoryId},
</if>
<if test="imageUrl != null" >
image_url = #{imageUrl},
</if>
<if test="type != null" >
type = #{type},
</if>
<if test="redirectArea != null" >
redirect_area = #{redirectArea},
</if>
<if test="features != null" >
features = #{features},
</if>
<if test="status != null" >
status = #{status},
</if>
<if test="createUser != null" >
create_user = #{createUser},
</if>
<if test="modifyUser != null" >
modify_user = #{modifyUser},
</if>
<if test="created != null" >
created = #{created},
</if>
<if test="modified != null" >
modified=now(),
</if>
</set>
where id = #{id}
</update>
</mapper>
前后端功能实现
要设置广告牌,我们首先需要点击列表上的按钮,然后新增弹窗。
我们在每行记录上放置一个按钮,并为它的点击事件绑定一个函数,用于打开弹窗。
大家注意,由于是设置功能,所以需要在打开弹窗之前,做一次数据查询,如果有广告牌数据,那么接下来要做的就是编辑操作,如果没有数据就是新增操作。
为了区分是新增还是修改,我们通过定义一个变量addBillboard来区分,操作时新增还是编辑。
有的朋友会疑问,既然你的数据是单个的,为什么后端的数据接口却是列表数据?是这样,从业务上讲广告牌数据和前端类目数据是一一对应的,但是从数据本身出发,咱们每次能获取到的查询条件,是类目ID。类目ID并非广告牌的主键,所以我们使用列表查询也是可以的,每次取1条记录就好了。
假如数据发生了问题,数据库里有两条记录,那么在查询时返回单个对象,会发生异常,所以后端使用List的结构处理了单个对象的数据,增加了系统的数据容错性。也是一点小经验,可以帮助到你。
想一想,还有什么办法也可以解决类似的问题呢?
接下来,自然就是保存数据了,大家来看一下。
嗯,似乎还忘记了一个很重要的事情,api还没有封装呢。我们现在就封装它吧。