其他分享
首页 > 其他分享> > CRM项目-- 基于SSM框架搭建V07

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

作者:互联网

前言:

这一篇应该是这个项目最后一次更新了,是关于交易模块的相关内容的,当然,这个版本里面还是有比较多内容是比较新的,值得记录。
外记:前段时间学校放假了,回家了,再加上干了一些科研的事情,最后不仅科研没有达到自己预想的效果这个项目也放下了[狗头]。后来又去补充了前面的客户和联系人模块,花费了大量的时间。下面就是本期内容啦~

1.创建交易

因为交易的内容比较多,给的前端,他是直接跳转到新的一张页面了。这样的话我们就直接使用超链接,然后后台返回userList集合放到request搭转发到新页面就好了。
创建页面是这样子的:
在这里插入图片描述
内容还是比较丰富比较新的

1.1默认选中当前登录用户为所有者

这里所有者的选中和以前不一样了,因为这里的所有者也是使用JSTL技术动态拼接出来的,JSTL其实也是属于EL表达式,幸运的是,EL表达式里面是可以使用 三目运算符 的,这样就可以做了。

<option></option>
<c:forEach items="${uList}" var="u">
<option value="${u.id}" ${user.id eq u.id ? "selected" : ""}>${u.name}</option>
</c:forEach>

后面的${user.id eq u.id ? "selected" : ""就是表示当前登录用户user.id和后台查出来的用户u.id是否相同,相同就选中,不同就没有。

1.2客户名称文本框的自动补全

这个地方要使用前端bootstrap typeahead插件,去他给的资源里面复制到我们的项目中。然后直接拿到这个文本框给他绑定他提供的函数即可。即:

			//为 客户名称 文本框绑定事件----实现自动补全,这是插件,是直接复制的
			$("#create-customerName").typeahead({
				source: function (query, process) {
					$.post(
							"workbench/transaction/getCustomerName.do",
							{ "name" : query }, //name就是我们输入的内容,会发送到后台
							function (data) {
								process(data);
							},
							"json"
					);
				},
				delay: 1500
			});

然后在后台控制器里面处理这个需求就行了。返回的是List<String>,因为在前端只有String才能被这个插件处理的,其他我们自己写的类他是不认识的。sql语句就是根据name模糊查询出List<String>。
最终实现的效果:
在这里插入图片描述
文本输入1之后查出了三条包含1的内容。完美!

还有说明,我们数据库表中保存的也是顾客的id,但是在前端我们没有办法去处理id,我们是将顾客的名字传到后台,然后在后台进行处理。

1.3市场活动源 和 联系人名称的查询

这里我是直接将两个文本框都变成了只读,只能通过点击旁边的搜索然后去查出相应的集合。这个需求也是前面做过的。这里就说一下步骤。
1)点击放大镜,打开查找的模态窗口。
2)在文本框输入内容,敲回车实现查询功能(绑定敲键盘事件)。
3)然后选中其中的一项,点击提交。(如果没有选中,弹出提示)
4)提交后,将对应的姓名保存到两个文本框里面给用户看;然后将对应的id保存到隐藏域中,这个id是我们到时候提交数据的时候真正要提交的内容。关闭模态窗口。

1.4阶段和可能性的处理

因为在表中没有对应的可能性字段,这是和以前不一样的。那怎么处理呢?这个和之前一样,要把阶段和可能性之间的对应关系放到服务器缓存application域中,在监听器方法里面做。
这个对应关系要使用Unicode编码,不过这个文件他已经提供了,我们直接复制就行,放到resource文件夹里面,是一个properties文件。在监听器里面这样处理:

		//------------------------下面是处理阶段和可能性的对应关系-------------------------------
        System.out.println("--------监听器执行,阶段和可能性对应关系处理开始------");

        Map<String,String> pMap = new HashMap<>();
        ResourceBundle rb = ResourceBundle.getBundle("Stage2Possibility"); //解析属性配置文件,后缀名一定要删除
        Enumeration<String> keys = rb.getKeys();
        while (keys.hasMoreElements()){
            String key = keys.nextElement();  //拿到每个阶段
            String value = (String) rb.getObject(key);  //拿到对应的可能性
            pMap.put(key,value);  //放到map中
        }
        application.setAttribute("pMap",pMap);

        System.out.println("--------监听器执行,阶段和可能性对应关系处理结束------");

然后,服务器启动的时候,application域里面就有 阶段和可能性的对应关系了。
在前端,我们首先在最前面拿到这个map集合。

<%
//处理可能性
Map<String,String> pMap = (Map<String, String>) application.getAttribute("pMap");
Set<String> set = pMap.keySet();
%>

然后我们需要在<script>标签去拼接出他们对应关系的json串。这样做:

	<script type="text/javascript">
		var json = {
			<%
				for (String key : set){
					String value = pMap.get(key);
			%>
				"<%=key%>" : <%=value%>,
			<%
				}
			%>
		};
	</script>

然后所有的内容都准备好了,我们给这个下拉框绑定一个change事件就行了,在里面将不同的可能性赋值到对应的文本框里面。
这里有一个要注意的地方是:最后在change事件里面使用拼出来的json,json.key的方式取得可能性。
但是在这里的stage不是固定是,是可变的,就不能使用json.key的方式进行取值,取不出来,要使用json[key]来取值。

			//为  阶段 文本框绑定事件,选择不同的阶段,自动填充不同的可能性
			$("#create-stage").change(function (){
				var stage = $("#create-stage").val();
				//拿到对应的可能性,在上面已经拼好json了
				var possibility = json[stage];
				//将可能性写入文本框
				$("#create-possibility").val(possibility);
			})
1.5给保存按钮绑定事件

这里因为表中的字段比较多,我们不可能使用ajax将每一个字段都传递到后端,因为也没有什么要局部刷新的地方,保存完就是跳到了一张全新的页面,这里我们使用提交form表单的形式。form表单提交的内容是name属性的内容,这个要注意。

2.pageList方法,修改,删除等需求

这个内容也是完全和前面一样的。不在这里写了。自己完成即可。和以前不一样的就是这个有可能是一个全新的页面,而不是局部刷新了。

3.跳转到详细信息页

这里的有些内容是和前面一样的,有些是很新的内容,特别是图标的动态展示
这是在第九个阶段的时候:
在这里插入图片描述
第四个阶段的时候是这样的:
在这里插入图片描述
先说一下传统的内容要注意的地方,这里因为也有可能性,而且不是和之前一样有的选的,为了解决这个问题,有两种做法:
1)我们可以在后台将查到的可能性单独放到request域中返回前端。
2)在Tran这个类里面添加多一个 可能性 的属性,虽然实际的表里面没有这个字段,但是我们是可以添加的,为了方便,而且在后面的时候也经常需要使用到这个内容。
这里我们就使用第二种方式。

接下来就是超级超级恶心的图标的动态展示(差点干吐了!):
这里他给出的方案也是有两种,然后我就直接使用了比较简单的第二种。
这里同样,在最前面要提前准备一些我们需要使用的内容:

<%
	//准备字典类型为 stage的List集合
	List<DicValue> dvList = (List<DicValue>) application.getAttribute("stage");
	//准备 类型和可能性的对应关系
	Map<String,String> pMap = (Map<String, String>) application.getAttribute("pMap");

	//准备:  正常阶段和丢失阶段的分界点下面,下标为可能性为0时候的下标
	int fenJiePoint = 0;
	for (int i=0; i<dvList.size(); i++){
		//取得每个字典值
		DicValue dv = dvList.get(i);
		//取得字典值里面的value
		String stage = dv.getValue();
		//取得这个value对应的可能性
		String possibility = pMap.get(stage);
		if ("0".equals(possibility)){
			fenJiePoint = i;
			break;
		}
	}

	//准备pMap中的key集合
	Set<String> set = pMap.keySet();

	//获取 阶段-->下标 之间的对应关系
	Map<String,Integer> rMap = (Map<String, Integer>) request.getAttribute("rMap");
%>

这上面的rMap是什么呢?因为给的第二种方案要有阶段和对应下标之间的关系,本来我是想在前端拼的,但是拼来拼去觉得太麻烦,最后直接在后台进行处理了,将他们之间的关系封装成了一个map集合。因为这里他是用第一种方案做的,我们的就不一样了。
后台:

	@ResponseBody
    @RequestMapping("/workbench/transaction/detail.do")
    public ModelAndView detail(HttpServletRequest request,String id){
        System.out.println("交易控制器,跳转至详细信息页");
        Tran tran = tranService.getTranById(id);

        //获取阶段和可能性之间的对应关系--从服务器缓存中取
        Map<String,String> pMap = (Map<String, String>) request.getServletContext().getAttribute("pMap");
        String possibility = pMap.get(tran.getStage());
        //将可能性封装到tran中
        tran.setPossibility(possibility);

        //阶段 和 下标的对应关系
        Map<String,Integer> relationMap = new HashMap<>();
        relationMap.put("01资质审查",0);
        relationMap.put("02需求分析",1);
        relationMap.put("03价值建议",2);
        relationMap.put("04确定决策者",3);
        relationMap.put("05提案/报价",4);
        relationMap.put("06谈判/复审",5);
        relationMap.put("07成交",6);
        relationMap.put("08丢失的线索",7);
        relationMap.put("09因竞争丢失关闭",8);

        ModelAndView mv = new ModelAndView();
        mv.addObject("t",tran);
        mv.addObject("rMap",relationMap);
        mv.setViewName("/workbench/transaction/detail.jsp");
        return mv;
    }

然后在前端下面具体的地方,将原来的图标注释了,我们要自己对这部分内容进行拼接了。
代码:

	<!-- 阶段状态 -->
	<div style="position: relative; left: 40px; top: -50px;">
		阶段&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

<%
			Tran t = (Tran) request.getAttribute("t");
			//当前阶段
			String currentStage = t.getStage();
			//当前阶段的可能性
			String currentPossibility = pMap.get(currentStage);
			//当前阶段对应的下标
			Integer currentIndex = rMap.get(currentStage);
			//正常和丢失阶段的分界点下标  fenjiePoint

			//当前阶段的可能性为0,前7个是黑圈,后两个不确定
			if ("0".equals(currentPossibility)){
				//遍历前7个
				for (int i=0; i<fenJiePoint; i++){
					//取得遍历过程中的阶段
					DicValue dv = dvList.get(i);
					//-----------------黑圈----------------
%>
					<span id="<%=i%>" onclick="changeStage('<%=dv.getValue()%>','<%=i%>')" class="glyphicon glyphicon-record mystage"
					data-toggle="popover" data-placement="bottom"
					data-content="资质审查" style="color: #000000;"></span>
							-----------
<%
				}
				//遍历后2个
				for (int i=fenJiePoint; i<dvList.size(); i++){
					DicValue dv = dvList.get(i);
					//是当前阶段
					if (i==currentIndex){
						//----------红叉-------------
%>
		<span id="<%=i%>" onclick="changeStage('<%=dv.getValue()%>','<%=i%>')" class="glyphicon glyphicon-remove mystage"
			  data-toggle="popover" data-placement="bottom"
			  data-content="资质审查" style="color: #FF0000;"></span>
		-----------
<%
					//不是当前阶段
					}else {
						//----------黑叉-------------
%>
		<span id="<%=i%>" onclick="changeStage('<%=dv.getValue()%>','<%=i%>')" class="glyphicon glyphicon-remove mystage"
			  data-toggle="popover" data-placement="bottom"
			  data-content="资质审查" style="color: #000000;"></span>
		-----------
<%
					}
				}

			//当前不是0,后两个是黑叉,前7个不确定
			}else {
				//遍历前7个
				for (int i=0; i<fenJiePoint; i++){
					DicValue dv = dvList.get(i);
					//当前阶段
					if (i==currentIndex){
						//---------绿标----------
%>
		<span id="<%=i%>" onclick="changeStage('<%=dv.getValue()%>','<%=i%>')" class="glyphicon glyphicon-map-marker mystage"
			  data-toggle="popover" data-placement="bottom"
			  data-content="资质审查" style="color: #90F790;"></span>
		-----------
<%
					//大于当前阶段
					}else if(i>currentIndex){
						//-------------黑圈------
%>
		<span id="<%=i%>" onclick="changeStage('<%=dv.getValue()%>','<%=i%>')" class="glyphicon glyphicon-record mystage"
			  data-toggle="popover" data-placement="bottom"
			  data-content="资质审查" style="color: #000000;"></span>
		-----------
<%
					//小于当前阶段
					}else {
						//-------------绿圈-------
%>
		<span id="<%=i%>" onclick="changeStage('<%=dv.getValue()%>','<%=i%>')" class="glyphicon glyphicon-ok-circle mystage"
			  data-toggle="popover" data-placement="bottom"
			  data-content="资质审查" style="color: #90F790;"></span>
		-----------
<%
					}

				}
				//遍历后2个
				for (int i=fenJiePoint; i<dvList.size(); i++){
					DicValue dv = dvList.get(i);
					//---------黑叉-------
%>
		<span id="<%=i%>" onclick="changeStage('<%=dv.getValue()%>','<%=i%>')" class="glyphicon glyphicon-remove mystage"
			  data-toggle="popover" data-placement="bottom"
			  data-content="资质审查" style="color: #000000;"></span>
		-----------
<%
				}
			}
%>



		<%--  原本的动态图标
		<span class="glyphicon glyphicon-ok-circle mystage" data-toggle="popover" data-placement="bottom" data-content="资质审查" style="color: #90F790;"></span>
		-----------
		<span class="glyphicon glyphicon-ok-circle mystage" data-toggle="popover" data-placement="bottom" data-content="需求分析" style="color: #90F790;"></span>
		-----------
		<span class="glyphicon glyphicon-ok-circle mystage" data-toggle="popover" data-placement="bottom" data-content="价值建议" style="color: #90F790;"></span>
		-----------
		<span class="glyphicon glyphicon-ok-circle mystage" data-toggle="popover" data-placement="bottom" data-content="确定决策者" style="color: #90F790;"></span>
		-----------
		<span class="glyphicon glyphicon-map-marker mystage" data-toggle="popover" data-placement="bottom" data-content="提案/报价" style="color: #90F790;"></span>
		-----------
		<span class="glyphicon glyphicon-record mystage" data-toggle="popover" data-placement="bottom" data-content="谈判/复审"></span>
		-----------
		<span class="glyphicon glyphicon-record mystage" data-toggle="popover" data-placement="bottom" data-content="成交"></span>
		-----------
		<span class="glyphicon glyphicon-record mystage" data-toggle="popover" data-placement="bottom" data-content="丢失的线索"></span>
		-----------
		<span class="glyphicon glyphicon-record mystage" data-toggle="popover" data-placement="bottom" data-content="因竞争丢失关闭"></span>
		-----------
		--%>


		<span class="closingDate">${t.expectedDate}</span>
	</div>

这里就是逻辑看起来比较繁琐一点,让人头疼。
如果是当前阶段是什么图标,就给他拼上什么对应的图标。
最后通过测试,是可以实现对应的功能的。

然后他的课里面还包括点击上面的图标可以变更阶段,还有eCharts表格的内容,我就没做了。这个写完,感觉写了好多代码,不过感觉SSM框架怎么搭,到后面又忘了,基本就是在最开始搭结构的时候才会记住,可能这也说明SSM框架真的很不错吧,确实能让我们只关注在代码的编写上,而不用去管其他的问题。

后面我可能要去学SpringBoot还有数据结构的内容了。

马上就快到农历的除夕了,好快啊,提前祝大家 除夕快乐 啊!!!

哈哈哈哈哈哈,要加油啊!
对了,后面学了新的内容,我也会继续记录的~~~~

标签:glyphicon,-----------,V07,--,对应,SSM,pMap,data,id
来源: https://blog.csdn.net/weixin_41362471/article/details/113435658