CRM项目-- 基于SSM框架搭建V05

这个版本是一个全新的模块----【线索模块】,也称为**【潜在客户】**,这个模块里面有很多内容都是和市场活动模态一样的,但是我还是自己写了,可能在这里记录的时候我就只说自己完成了哪些内容,至于具体的代码什么的就不放了。
这个全新的模态还是有很多新东西可以玩的。接下来就来看吧~

1.数据字典的使用(cache缓存机制)

数据字典:指的是在应用程序中,做表单元素选择内容用的相关的数据。比如:下拉框,单选框,复选框。这里里面的内容,使用数据字典进行完成比较好,这样就不必每次加载的时候和数据库连接取数据,直接从缓存里面取。
数据字典普遍被应用在下拉框中。

缓存(cache):是指内存中的数据。这里要使用的是一种服务器缓存的机制。就相当于要将数据保存到服务器的内存中。
如果服务器处于开启状态,我们就一直能够从该缓存中取得数据。为了实现这个目的,我们是要把数据扔到application(全局作用域,也叫 上下文作用域)里面的。
在服务器启动阶段,将数据保存到服务器缓存中,服务器启动阶段,数据始终存在。
将数据保存到服务器缓存中的手段:application setattribute();
从服务器缓存中取出数据:application.getAttribute();
在这里插入图片描述
那么,上面的数据字典通常是什么怎么实现的呢?其实知道的话就不难。具体实现是:
使用监听器,监听上下文作用域对象的创建。他创建的时候把数据字典扔到application里面。
如何使用监听器?
你要监听哪个对象,你就实现对应的对象监听器接口,然后使用里面的方法。写完之后还要再web.xml文件里面配一下。

具体:在监听器类里面调用service来完成,给我们返回一个Map,里面有7个List集合,装着不同的codeType。这里面使用的service不能使用自动注入的原理来拿到,否则会出现java.lang.IllegalStateException异常,必须在初始化方法里面使用getBean的方式拿到,还得给service起名(这里是需要注意的地方),代码如下:

//这个类的上边不知道要不要加Component注解----试了之后发现加了也没用,还是得用下面的方式
public class SysInitListener implements ServletContextListener {
    //@Autowired
    //private DicService dicService;---这里不能使用这种方式获得service
    @Override
    public void contextInitialized(ServletContextEvent event) {
        System.out.println("=====监听器执行,数据字典初始化开始====");
        //拿到全局作用域对象
        ServletContext application = event.getServletContext();

        WebApplicationContext wac = ContextLoader.getCurrentWebApplicationContext();
        DicService dicService = (DicService) wac.getBean("dicService");

        //调用service,把查到的那些东西扔到application里面
        Map<String, List<DicValue>> map = dicService.getAllDicValue();
        //遍历map
        Set<String> keySet = map.keySet();
        for (String key : keySet){
            application.setAttribute(key,map.get(key));
        }
        System.out.println("=====监听器执行,数据字典初始化结束====");
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
    }
}

在service里面是这样实现的:

@Service("dicService")
public class DicServiceImpl implements DicService {
    @Autowired
    private DicValueDao dicValueDao;
    @Autowired
    private DicTypeDao dicTypeDao;

    @Override
    public Map<String, List<DicValue>> getAllDicValue() {
        Map<String, List<DicValue>> map = new HashMap<>();

        //1.获取所有的DicType,就是有哪些类型
        List<DicType> dicTypeList = dicTypeDao.getDicCode();

        //2.获取上面每种类型对应的Value值,遍历List集合
        for (DicType dicType : dicTypeList){
            String code = dicType.getCode();  //对应的code,根据这个code去查对应的Value
            List<DicValue> dicValueList = dicValueDao.getListByCode(code);
            map.put(code,dicValueList);
        }

        return map;
    }
}

在两个dao里面:

<?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.bjpowernode.crm.settings.dao.DicTypeDao">
    <select id="getDicCode" resultType="DicType">
        select * from tbl_dic_type
    </select>
</mapper>
<select id="getListByCode" resultType="DicValue">
        select * from tbl_dic_value where typeCode=#{code}
    </select>

在web.xml文件里面,把他配在spring的监听器下面就行了。

<!--数据字典的监听器-->
  <listener>
    <listener-class>com.bjpowernode.crm.web.listener.SysInitListener</listener-class>
  </listener>

通过以上,就可以在服务器启动的时候,把不同类型的数据加入到服务器缓存里面了,我们在前端配合JSTL进行使用,非常的方便。jsp页面前面要加入相关的约束:

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

要使用的时候,因为他们是集合,来foreach:

<c:forEach items=”${appellation}var=”a”>
	    <option value=”${a.value}>${a.text}</option>
</c:forEach>

2.线索相关的操作–创建、pageList()、删除、修改等

1)然后接着就是和市场活动模块一样,完成线索的创建。思路和前面一样,就是这次文本框的内容比之前多了很多,还要在里面要使用到上面的数据字典给那些下拉框赋值。所有者还是照常过后台取。
2)pageList()方法,这个也要完成,有一些要处理的小细节包括:引入时间插件,分页插件,全选框操作,点击查询的时候出现的问题—>使用隐藏域解决。
3)删除线索操作。可以同时删除多条,先删备注,再删关系,再删线索。
4)修改线索。一次只能修改一条,直接复制创建的。

3.跳转至线索的详细信息页

这个也是和之前一样的,先过后台,然后在后台把取得的Clue扔到request里面,接一个请求转发跳转至新的jsp页面。这里controller里面的返回值使用的是ModelAndView。
下面的内容也是和之前重复的,课程里面没讲,但是自己完成了:
1)备注信息自动刷新。这个是页面加载完成后自动执行方法。
2)备注的删除、添加、修改操作。这里备注的修改因为他前端没有修改的模态窗口,所以我就没做修改的这个。

4.备注信息页市场活动自动刷新

这个和上面的备注信息的自动刷新是一样的,不过这个需求涉及到3个表的连接,sql是第一次写。因为市场活动和线索是多对多的关系,多对多的时候需要建立其第三张关联关系表。
在这里插入图片描述

前端:

	//展现该线索关联的市场活动
	function showActivityList(){
		$.ajax({
			url:"workbench/clue/getActivityListByCId.do",
			data:{"clueId":"${clue.id}"},
			type:"GET",
			dataType:"json",    //预期服务器返回的数据类型
			success:function (data){
				// aList: [{市场活动1},{2},{3}]---->返回的id是关联关系表的id
				var html = "";
				$.each(data,function (i,n){
					html += '<tr id="'+n.id+'">';
					html += '<td>'+n.name+'</td>';
					html += '<td>'+n.startDate+'</td>';
					html += '<td>'+n.endDate+'</td>';
					html += '<td>'+n.owner+'</td>';
					html += '<td><a href="javascript:void(0);" οnclick="deleteRelation(\''+n.id+'\')"  style="text-decoration: none;"><span class="glyphicon glyphicon-remove"></span>解除关联</a></td>';
					html += '</tr>';
				})
				$("#activityBody").html(html);
			}
		})
	}

后端dao的sql语句:因为这里要查出的是市场活动的List集合,所以使用的是activityDao,因为有所有者,要关联user表,另外他们的关系是使用第三张关联关系表进行连接的,也要使用到他。还有一个巧妙的地方就是保存的id直接保存成关联关系表的id,到时候接触关联的时候直接根据id进行解除就行,方便了许多。

<select id="getActivityListByCId" resultType="Activity">
        select
            car.id as id,
            u.name as owner,
            a.name,
            a.startDate,
            a.endDate
        from tbl_activity a
        join tbl_user u
        on a.owner=u.id
        join tbl_clue_activity_relation car
        on a.id=car.activityId
        where car.clueId=#{clueId}
    </select>

5.解除市场活动和线索的关联关系

这个也是直接使用超链接进行触发,比较简单。

6.市场活动和线索的关联

这个需求时通过点击“关联市场活动”按钮,然后会打开一个相关的查询模态窗口,根据市场活动的名称模糊查询出还未关联的市场活动,最后点击关联按钮,实现市场活动和线索之间的关联,在关联关系表增加记录。
在这里插入图片描述
在这里插入图片描述
1)首先是文本框绑定敲回车事件,然后查询,这个查询要注意的地方就是除了名字模糊查询之外,还要把已经关联的市场活动去除。
还有一个非常重要的内容就是:在模态窗口中,敲回车会默认触发一个事件:强制刷新并清空当前页面,这样会导致我们页面的数据全部被清空,我们应该将此功能禁用。方式,在展现完市场活动列表后,return false; 即可。
前端:

		//为关联市场活动模态窗口的搜索框绑定敲键盘事件
        $("#searchActivity").keydown(function (event){
            if (event.keyCode==13){  //回车
                //展现查询出来的市场活动列表
                $.ajax({
                    url:"workbench/clue/getActivityListByNameAndNotByCId.do",
                    data:{
                        "name":$.trim($("#searchActivity").val()),
                        "cid":"${clue.id}"
                    },
                    type:"GET",
                    dataType:"json",    //预期服务器返回的数据类型
                    success:function (data){
                        //data:  [{市场活动1},{2},{3}]
                        var html = "";
                        $.each(data,function (i,n){
                            html += '<tr>';
                            html += '<td><input type="checkbox" name="xuanze" value="'+n.id+'"/></td>';
                            html += '<td>'+n.name+'</td>';
                            html += '<td>'+n.startDate+'</td>';
                            html += '<td>'+n.endDate+'</td>';
                            html += '<td>'+n.owner+'</td>';
                            html += '</tr>';
                        })
                        //写入上面拼的内容
                        $("#search-activityBody").html(html);
                    }
                })

                //将模态窗口默认的回车功能禁用
                return false;
            }
        })

查询的sql语句:(包括了多表联查子查询

<select id="getActivityListByNameAndNotByCId" resultType="Activity">
        select
            a.id,
            u.name as owner,
            a.name,
            a.startDate,
            a.endDate
        from tbl_activity a
        join tbl_user u
        on a.owner=u.id
        where a.name like '%' #{name} '%' and a.id not in(
            select activityId from tbl_clue_activity_relation where clueId=#{cid}
        )
</select>

2)就是根据查询出来的结果,勾选需要关联的市场活动,点击关联即可。这里从前端向后端发送的数据由:线索的id,一个或多个市场活动的id,所以这里也不能使用json进行传数据,得用拼字符串的方式。最后,通过实验,我还发现了一个非常有趣的内容,就是springmvc框架在接收参数的时候,如果你的id值有多个,在方法的参数里面可以直接使用数组进行接收,这是比较有趣的。
前端:

		//为关联按钮绑定事件
		$("#addRelationforAC").click(function (){
			//要传线索id和多个activityId
			var param = "cid="+"${clue.id}"+"&";
			//拿到打钩的复选框
			var $xuanzhong = $("input[name=xuanze]:checked");

			if ($xuanzhong.length==0){
				alert("请选择需要关联的市场活动~");
			}else {
				for (var i=0; i<$xuanzhong.length; i++){
					param += "aid="+$($xuanzhong[i]).val();
					if (i<$xuanzhong.length-1){
						param += "&";
					}
				}

				$.ajax({
					url:"workbench/clue/saveACRelation.do",
					data:param,
					type:"POST",
					dataType:"json",    //预期服务器返回的数据类型
					success:function (data){
						if (data){
							//清空搜索框
							$("#searchActivity").val("");
							//清空搜索框里面的search-activityBody里面的内容
							$("#search-activityBody").remove();
							//全选框取消选择
							$("#quanxuan").prop("checked",false);
							//关闭模态窗口
							$("#bundModal").modal("hide");

							//刷新市场活动列表
							showActivityList();

						}else {
							alert("关联市场活动失败~");
						}
					}
				})
			}
		})

controller里面:

	@ResponseBody
    @RequestMapping("/workbench/clue/saveACRelation.do")
    public Boolean saveACRelation(String cid,String[] aid){ //可以直接使用数据进行接收aid,有点意思
        System.out.println("=====线索控制器,增加线索和市场活动的关联关系=====");
        Boolean flag = clueService.saveACRelation(cid,aid);
        return flag;
    }

service里面:

	@Override
    public Boolean saveACRelation(String cid, String[] aid) {
        Boolean flag = true;
        ClueActivityRelation car = new ClueActivityRelation();
        for (String id : aid){
            car.setId(UUIDUtil.getUUID());
            car.setClueId(cid);
            car.setActivityId(id);
            int count = clueActivityRelationDao.saveACRelation(car);
            if (count != 1) {
                flag = false;
            }
        }
        return flag;
    }

sql语句比较简单,不放了。


以上就是这个版本的全部内容啦~重复的内容比较多,练练手,练熟一点。比较新的内容即使第一个数据字典的使用,还有最后第4个的三表联查,第6个的多表联查结合子查询

然后下个版本还是线索模块的,实现线索的转换。=============

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值