目录
学习目标:
营销机会下拉框显示销售
营销机会删除功能以及客户开发计划的增删改查功能
学习内容:
营销机会下拉框显示销售(后端)
DAO层
因为设计到多表连接,首先将SQL语句写出来
SELECT
u.id,u.userName uname
FROM
t_user u
LEFT JOIN
t_user_role ur
ON
u.id = ur.user_id
LEFT JOIN
t_role r
ON
r.id = ur.role_id
WHERE
u.isValid = 1
AND
r.is_Valid = 1
AND
r.role_name = '销售'
在Mapper.xml中加入新的查询
<select id="queryAllSales" resultType="java.util.Map">
SELECT
u.id,u.userName uname
FROM
t_user u
LEFT JOIN
t_user_role ur
ON
u.id = ur.user_id
LEFT JOIN
t_role r
ON
r.id = ur.role_id
WHERE
u.isValid = 1
AND
r.is_Valid = 1
AND
r.role_name = '销售'
</select>
UserMapper中加入对应方法
//查询所以的销售人员
public List<Map<String,Object>> queryAllSales();
Service层
/**
* @author QQ星
* 查询所有销售人员
*
* @param
* @return java.util.List<java.util.
Map<java.lang.String,java.lang.Object>>
* @Date 2022/3/7 17:21
*/
public List<Map<String,Object>> queryAllSales(){
return userMapper.queryAllSales();
}
Controller层
/**
* @author QQ星
* 查询所有销售人员
*
* @param
* @return java.util.List<java.util.
Map<java.lang.String,java.lang.Object>>
* @Date 2022/3/7 17:24
*/
@RequestMapping("queryAllSales")
@ResponseBody
public List<Map<String,Object>>queryAllSales(){
return userService.queryAllSales();
}
测试结果:
下拉框前端:
add_update.ftl
<#-- 设置指派人的隐藏域ID -->
<input type="hidden" id="assignManId" value="${(saleChance.assignMan)!}">
add.update.js
/**
* 加载指派人的下拉框
*/
$.ajax({
type:"get",
url:ctx + "/user/queryAllSales",
data:{},
success:function (data) {
// console.log(data);
// 判断返回的数据是否为空
if (data != null) {
// 获取隐藏域设置的指派人ID
var assignManId = $("#assignManId").val();
// 遍历返回的数据
for(var i = 0; i < data.length; i++) {
var opt = "";
// 如果循环得到的ID与隐藏域的ID相等,则表示被选中
if (assignManId == data[i].id) {
// 设置下拉选项 设置下拉选项选中
opt = "<option value='"+data[i].id+"' selected>"+data[i].uname+"</option>";
} else {
// 设置下拉选项
opt = "<option value='"+data[i].id+"'>"+data[i].uname+"</option>";
}
// 将下拉项设置到下拉框中
$("#assignMan").append(opt);
}
}
// 重新渲染下拉框的内容(解决无法显示问题)
layui.form.render("select");
}
});
删除功能后端
新思想:保留原纪录只是将状态改为0,数据库中还存在此纪录,但是显示时会因为不是有效状态而被过滤
Dao层
<update id="deleteBatch">
update
t_sale_chance
set
is_valid =0
where
id
in
<foreach collection="array" separator="," open="(" close=")" item="id">
#{id}
</foreach>
</update>
Service层
/**
* 删除营销机会
* @author QQ星
*
* @param ids
* @return void
* @Date 2022/3/7 21:37
*/
@Transactional(propagation = Propagation.REQUIRED)
public void deleteSaleChance(Integer[] ids){
// 判断ID是否为空
AssertUtil.isTrue(null == ids || ids.length < 1, "待删除记录不存在!");
// 执行删除(更新)操作,判断受影响的行数
AssertUtil.isTrue(saleChanceMapper.deleteBatch(ids) != ids.length, "营销机会数据删除失败!");
}
Controler层
/** 删除营销机会
* @author QQ星
*
* @param ids
* @return com.xxxx.crm.base.ResultInfo
* @Date 2022/3/7 21:38
*/
@PostMapping("delete")
@ResponseBody
public ResultInfo deleteSaleChance(Integer[] ids){
//调用Service层删除方法
saleChanceService.deleteSaleChance(ids);
return success("营销机会删除成功!");
}
测试:
删除前端:
else if (data.event == "del") { // 删除操作
// 弹出确认框,询问用户是否确认删除
layer.confirm('确定要删除该记录吗?',{icon:3, title:"营销机会管理"}, function (index) {
// 关闭确认框
layer.close(index);
// 发送ajax请求,删除记录
$.ajax({
type:"post",
url:ctx + "/sale_chance/delete",
data:{
ids:data.data.id
},
success:function (result) {
// 判断删除结果
if (result.code == 200) {
// 提示成功
layer.msg("删除成功!",{icon:6});
// 刷新表格
tableIns.reload();
} else {
// 提示失败
layer.msg(result.msg, {icon:5});
}
}
});
});
}
多条删除前端
/**
* 加载数据表格
*/
var tableIns = table.render({
id:'saleChanceTable'
/**
* 删除营销机会(删除多条记录)
* @param data
*/
function deleteSaleChance(data) {
// 获取数据表格选中的行数据 table.checkStatus('数据表格的ID属性值');
var checkStatus = table.checkStatus("saleChanceTable");
console.log(checkStatus);
// 获取所有被选中的记录对应的数据
var saleChanceData = checkStatus.data;
// 判断用户是否选择的记录 (选中行的数量大于0)
if (saleChanceData.length < 1) {
layer.msg("请选择要删除的记录!",{icon:5});
return;
}
// 询问用户是否确认删除
layer.confirm('您确定要删除选中的记录吗?',{icon:3, title:'营销机会管理'}, function (index) {
// 关闭确认框
layer.close(index);
// 传递的参数是数组 ids=1&ids=2&ids=3
var ids = "ids=";
// 循环选中的行记录的数据
for(var i = 0; i < saleChanceData.length; i++) {
if(i < saleChanceData.length -1) {
ids = ids + saleChanceData[i].id + "&ids="
} else {
ids = ids + saleChanceData[i].id;
}
}
// console.log(ids);
// 发送ajax请求,执行删除营销机会
$.ajax({
type:"post",
url:ctx + "/sale_chance/delete",
data:ids, // 传递的参数是数组 ids=1&ids=2&ids=3
success:function (result) {
// 判断删除结果
if (result.code == 200) {
// 提示成功
layer.msg("删除成功!",{icon:6});
// 刷新表格
tableIns.reload();
} else {
// 提示失败
layer.msg(result.msg, {icon:5});
}
}
});
});
}
客户开发计划(后端)
新思想:客户开发计划为当前销售下的所有客户,本质上和营销机会管理一样,查询的表是同一个,但是需要用前端传一个参数来判断是客户开发计划还是营销机会
在mapper.xml中加入新的查询条件
<!-- 根据开发状态进行查询 -->
<if test="devResult != null">
and s.dev_result = #{devResult}
</if>
<!-- 根据指派人进行查询 -->
<if test="assignMan != null">
and s.assign_man = #{assignMan}
</if>
在saleChanceQuery中加入新的变量
//客户开发计划 条件查询
private String devResult; //开发状态
private Integer assignMan; //指派人
public String getDevResult() {
return devResult;
}
public void setDevResult(String devResult) {
this.devResult = devResult;
}
public Integer getAssignMan() {
return assignMan;
}
public void setAssignMan(Integer assignMan) {
this.assignMan = assignMan;
}
在Controller中加入判断,可以根据传的flag来辨别,如果flag存在就给这个query加入assgman属性和state的属性
public Map<String, Object> querySaleChanceByParams(SaleChanceQuery saleChanceQuery,
Integer flag, HttpServletRequest request) {
//判断flag的值
if (flag != null && flag == 1) {
//查询客户开发计划
//设置分配状态
saleChanceQuery.setState(StateStatus.STATED.getType());
//设置指派人(当前登录用户的ID)
//从cookie中获取当前登录用户的ID
Integer userId = LoginUserUtil.releaseUserIdFromCookie(request);
saleChanceQuery.setAssignMan(userId);
}
return saleChanceService.querySaleChanceByParams(saleChanceQuery);
}
在CusDevPlanController中加入index界面
/**
* 进入客户开发计划
* @author QQ星
*
* @param
* @return java.lang.String
* @Date 2022/3/9 21:49
*/
@RequestMapping("index")
public String index(Integer id, HttpServletRequest request){
// 通过id查询营销机会对象
SaleChance saleChance = saleChanceService.selectByPrimaryKey(id);
// 将对象设置到请求域中
request.setAttribute("saleChance", saleChance);
return "cusDevPlan/cus_dev_plan";
}
前端
导入模板
根据sale.chance.js来改
// 访问数据的URL(后台的数据接口) 设置flag参数,表示查询的事客户开发计划数据
,url: ctx + '/sale_chance/list?flag=1'
遇到问题:
无法使用查询
原因:因为定义了String属性的devResult会传递空字符串进来,所以查询不到
解决方案:
在mappper.xml排除掉空字符串即可
进入客户开发页面:
在controller中加入页面返回即可
/**
* 打开计划项开发与详情页面
* @author QQ星
*
* @param id
* @param request
* @return java.lang.String
* @Date 2022/3/10 17:08
*/
@RequestMapping("toCusDevPlanPage")
public String toSaleChancePage(Integer id, HttpServletRequest request) {
//通过id查询营销机会对象
SaleChance saleChance = saleChanceService.selectByPrimaryKey(id);
//将对象设置到请求域中
request.setAttribute("saleChance",saleChance);
return "cusDevPlan/cus_dev_plan_data";
}
客户开发计划数据查询后端代码:
用generator来根据t_cus_dev_plan表来创建好VO,mapper和service后让这些基础各个的base类后
Dao层
加入多条件查询的sql语句
<select id="selectByParams" parameterType="com.xxxx.crm.query.CusDevPlanQuery" resultType="com.xxxx.crm.vo.CusDevPlan">
select
<include refid="Base_Column_List"></include>
from
t_cus_dev_plan
where
is_valid = 1
and
sale_chance_id = #{saleChanceId}
</select>
Service层
返回一个map可以让前端layui来获取到数据
创建分页然后将对象放进区之后利用map来把成功信息put进去之后然后再返回
/**
* 多条件分页查询客户开发计划 (返回的数据格式必须满足LayUi中数据表格要求的格式)
* @author QQ星
*
* @param cusDevPlanQuery
* @return java.util.Map<java.lang.String,java.lang.Object>
* @Date 2022/3/10 17:05
*/
public Map<String, Object> queryCusDevPlanByParams(CusDevPlanQuery cusDevPlanQuery) {
Map<String, Object> map = new HashMap<>();
// 开启分页
PageHelper.startPage(cusDevPlanQuery.getPage(), cusDevPlanQuery.getLimit());
// 得到对应分页对象
PageInfo<CusDevPlan> pageInfo = new PageInfo<>(cusDevPlanMapper.selectByParams(cusDevPlanQuery));
// 设置map对象
map.put("code",0);
map.put("msg","success");
map.put("count",pageInfo.getTotal());
// 设置分页好的列表
map.put("data",pageInfo.getList());
return map;
}
controller层
/**
* 客户开发计划数据查询
* @author QQ星
*
* @param cusDevPlanQuery
* @return java.util.Map<java.lang.String,java.lang.Object>
* @Date 2022/3/10 17:10
*/
@RequestMapping("list")
public Map<String, Object> queryCusDevPlanByParams(CusDevPlanQuery cusDevPlanQuery) {
return cusDevPlanService.queryCusDevPlanByParams(cusDevPlanQuery);
}
遇到问题:
接口返回不了参数
原因:粗心大意漏写@ResponseBody导致返回不了参数
返回的是JSON字符串需要 @ResponseBody来注释不然回返回不了
用户计划前端:
var tableIns = table.render({
id:'cusDevPlanTable'
// 容器元素的ID属性值
,elem: '#cusDevPlanList'
// 容器的高度 full-差值
,height: 'full-125'
// 单元格最小的宽度
,cellMinWidth:95
// 访问数据的URL(后台的数据接口)
,url: ctx + '/cus_dev_plan/list?saleChanceId=' + $("[name='id']").val()
// 开启分页
,page: true
// 默认每页显示的数量
,limit:10
// 每页页数的可选项
,limits:[10,20,30,40,50]
// 开启头部工具栏
,toolbar:'#toolbarDemo'
// 表头
,cols: [[
// field:要求field属性值与返回的数据中对应的属性字段名一致
// title:设置列的标题
// sort:是否允许排序(默认:false)
// fixed:固定列
{type:'checkbox', fixed:'center'}
,{field: 'id', title: '编号', sort: true, fixed: 'left'}
,{field: 'planItem', title: '计划项', align:'center'}
,{field: 'planDate', title: '计划时间', align:'center'}
,{field: 'exeAffect', title: '执行效果', align:'center'}
,{field: 'createDate', title: '创建时间', align:'center'}
,{field: 'updateDate', title: '修改时间', align:'center'}
,{title:'操作',templet:'#cusDevPlanListBar', fixed: 'right', align:'center', minWidth:150}
]]
});
/**
* 监听头部工具栏
*/
table.on('toolbar(cusDevPlans)', function (data) {
if (data.event == "add") { // 添加计划项
// 打开添加或修改计划项的页面
openAddOrUpdateCusDevPlanDialog();
} else if (data.event == "success") { // 开发成功
// 更新营销机会的开发状态
updateSaleChanceDevResult(2); // 开发成功
} else if (data.event == "failed") { // 开发失败
// 更新营销机会的开发状态
updateSaleChanceDevResult(3); // 开发失败
}
});
/**
* 监听行工具栏
*/
table.on('tool(cusDevPlans)',function (data) {
if (data.event == "edit") { // 更新计划项
// 打开添加或修改计划项的页面
openAddOrUpdateCusDevPlanDialog(data.data.id);
} else if (data.event == "del") { // 删除计划项
// 删除计划项
deleteCusDevPlan(data.data.id);
}
});
function openAddOrUpdateCusDevPlanDialog(id) {
var title = "计划项管理 - 添加计划项";
var url = ctx + "/cus_dev_plan/toAddOrUpdateCusDevPlanPage?sId="+$("[name='id']").val();
// 判断计划项的ID是否为空 (如果为空,则表示添加;不为空则表示更新操作)
if (id != null && id != '') {
// 更新计划项
title = "计划项管理 - 更新计划项";
url += "&id="+id;
}
// iframe层
layui.layer.open({
// 类型
type: 2,
// 标题
title: title,
// 宽高
area: ['500px', '300px'],
// url地址
content: url,
// 可以最大化与最小化
maxmin:true
});
}
遇到问题:
创建时间显示不了
表中列名写错代码自动生成的全是creadate
改掉即可
用户计划添加后端
思路:
添加客户开发计划项数据 1. 参数校验 营销机会ID 非空,数据存在 计划项内容 非空 计划时间 非空 2. 设置参数的默认值 是否有效 默认有效 创建时间 系统当前时间 修改时间 系统当前时间 3. 执行添加操作,判断受影响的行数
dao层
直接调用insertSelective方法即可
Service层
根据思路写出参数校检,设置默认值和判断是否添加成功即可
注意需要获取到cusDevPlan里面的SaleChanceId然后去根据SaleChanceMapper来查询是否存在这个营销然后再去执行添加操作
/**
* 添加客户开发计划项数据
*
* 1. 参数校验
* 营销机会ID 非空,数据存在
* 计划项内容 非空
* 计划时间 非空
* 2. 设置参数的默认值
* 是否有效 默认有效
* 创建时间 系统当前时间
* 修改时间 系统当前时间
* 3. 执行添加操作,判断受影响的行数
* @author QQ星
*
* @param cusDevPlan
* @return void
* @Date 2022/3/11 20:59
*/
@Transactional(propagation = Propagation.REQUIRED)
public void addCusDevPlan(CusDevPlan cusDevPlan){
/* 1. 校检参数 */
checkSaleChanceParams(cusDevPlan);
/* 2. 设置参数默认值 */
//是否有效 默认有效
cusDevPlan.setIsValid(1);
//创建时间 系统当前时间
cusDevPlan.setCreatDate(new Date());
//修改时间 系统当前时间
cusDevPlan.setUpdateDate(new Date());
/* 3.执行添加操作,判断受影响的行数 */
AssertUtil.isTrue(cusDevPlanMapper.insertSelective(cusDevPlan)!=1,"计划项添加数据失败!");
}
/**
* 参数校检
* @author QQ星
*
* @param cusDevPlan
* @return void
* @Date 2022/3/12 0:29
*/
private void checkSaleChanceParams(CusDevPlan cusDevPlan) {
//营销Id 非空数据存在
Integer saleChanceId =cusDevPlan.getSaleChanceId();
AssertUtil.isTrue(saleChanceId==null|| saleChanceMapper.selectByPrimaryKey(saleChanceId)==null,"营销不存在,数据异常!");
//计划项内容 非空
AssertUtil.isTrue(StringUtils.isBlank(cusDevPlan.getPlanItem()),"计划项内容不能为空!");
//计划时间 非空
AssertUtil.isTrue(cusDevPlan.getPlanDate()==null,"计划项时间不能为空!");
}
controller层
执行service层方法即可,返回调用success方法可以直接return一个ResultInfo
/**
* 添加计划项
* @author QQ星
*
* @param cusDevPlan
* @return com.xxxx.crm.base.ResultInfo
* @Date 2022/3/10 23:39
*/
@RequestMapping("add")
@ResponseBody
public ResultInfo addCusDevPlan(CusDevPlan cusDevPlan){
cusDevPlanService.addCusDevPlan(cusDevPlan);
return success("添加成功");
}
遇到问题
无法接收到日期数据
传入的是字符串但是封装类里面是日期所以需要在日期上面加入可收到字符串的格式
依旧无法添加成功
DeBug发现数据缺少主键Id
数据库中没有设置自增主键
改正即可
添加用户计划前端
/**
* 监听头部工具栏
*/
table.on('toolbar(cusDevPlans)', function (data) {
if (data.event == "add") { // 添加计划项
// 打开添加或修改计划项的页面
openAddOrUpdateCusDevPlanDialog();
} else if (data.event == "success") { // 开发成功
} else if (data.event == "failed") { // 开发失败
}
});
/**
* 打开添加或修改计划项的页面
*/
function openAddOrUpdateCusDevPlanDialog(id) {
var title = "计划项管理 - 添加计划项";
var url = ctx + "/cus_dev_plan/toAddOrUpdateCusDevPlanPage";
// 判断计划项的ID是否为空 (如果为空,则表示添加;不为空则表示更新操作)
if (id != null && id != '') {
// 更新计划项
title = "计划项管理 - 更新计划项";
url += "&id="+id;
}
// iframe层
layui.layer.open({
// 类型
type: 2,
// 标题
title: title,
// 宽高
area: ['500px', '300px'],
// url地址
content: url,
// 可以最大化与最小化
maxmin:true
});
}
/**
* 进入添加或修改计划项的页面
* @author QQ星
*
* @param request
* @param sId
* @param id
* @return java.lang.String
* @Date 2022/3/12 1:21
*/
@RequestMapping("toAddOrUpdateCusDevPlanPage")
public String toAddOrUpdateCusDevPlanPage() {
return "cusDevPlan/add_update";
}
新思想:
总共有三个页面,再最小的页面上 执行添加操作,把要添加的内容传到后端,但是小窗口是无法确认营销Id,所以需要再看第二个页面的时候把营销Id传给后端,再由后端把这个营销Id传给增加数据的页面。
cus_dev_plan_data.ftl ->CusDevPlanController ->add_update.ftl
public String toAddOrUpdateCusDevPlanPage(HttpServletRequest request, Integer sId, Integer id) {
// 将营销机会ID设置到请求域中,给计划项页面获取
request.setAttribute("sId", sId);
// 通过计划项ID查询记录
CusDevPlan cusDevPlan = cusDevPlanService.selectByPrimaryKey(id);
// 将计划项数据设置到请求域中
request.setAttribute("cusDevPlan", cusDevPlan);
return "cusDevPlan/add_update";
}
前端添加成功
心得:
最近事情真的很多,论文需要开题了,查阅了很多资料,翻译了两篇论文还简要准备了一下开题需要的ppt,然后又是遇到余杭区快递事件,又要排着老长的队伍去做核算,明天开始进度加快,需要明天一天之内完成营销模块的尾巴。