客户需求
用户在线索主页面,点击”创建”按钮,弹出创建线索的模态窗口;
用户在创建线索的模态窗口,填写表单,点击”保存”按钮,完成创建线索的功能。
*所有者、称呼、线索状态、线索来源 是动态
*表单验证
*创建成功之后,关闭模态窗口,刷新线索列表,显示第一页数据,保持每页显示条数不变
*创建失败,提示信息,模态窗口不关闭,列表也不刷新。
功能开发知识点
1,线索:初级销售
数据量最大,每一条数据最详细:tbl_clue
有购买意向的线索,转换到高级销售阶段;
没有购买意向的线索,删除掉.
创建线索,查看线索明细,线索关联市场活动,解除线索和市场活动的关联关系,线索转换
2,创建线索:
tbl_dic_type code 存储下拉列表的类型的,每一个下拉列表在tbl_dic_type对应一条记录,主键值都是各自的编码,有含义的字段做主键,在程序如果需要用到这些主键值,可以直接使用。
tbl_dic_value type_code 存储每一个下拉列表中的选项值,通过type_code区分选项值属于哪一个下拉列表
queryDicValueByTypeCode("type")
功能开发:
1.根据客户需求画出创建线索的UML时序图
2.ClueMapper接口
ClueMapper.xml文件
<insert id="insertClue" parameterType="com.it.crm.workbench.entity.Clue">
insert into tbl_clue(id, fullname, appellation, owner, company, job, email, phone, website, mphone, state,
source, create_by, create_time, description, contact_summary,
next_contact_time, address)
values (#{id},#{fullname},#{ appellation},#{ owner},#{ company},#{ job},#{ email},#{ phone},#{ website},#{ mphone},#{ state},#{
source},#{ createBy},#{ createTime},#{ description},#{ contactSummary},
#{nextContactTime},#{ address})
</insert>
3.ClueService接口
ClueServiceImpl类
4.ClueController类
@RequestMapping(value = "/workbench/clue/saveCreateClue.do")
@ResponseBody
public Object saveCreateClue(Clue clue, HttpSession session){
User user = (User) session.getAttribute(Contants.SESSION_USER);
ReturnObject returnObject=new ReturnObject();
//封装参数
clue.setId(UUIDUtils.getUUID());
clue.setCreateTime(DateUtils.formateDateTime(new Date()));
clue.setCreateBy(user.getId());
try{
//调用service层方法,保存创建的线索
int ret = clueService.saveCreateClue(clue);
if (ret>0){
returnObject.setCode(Contants.RETURN_OBJECT_CODE_SUCCESS);
}else {
returnObject.setCode(Contants.RETURN_OBJECT_CODE_FAIL);
returnObject.setMessage("系统忙,请稍后重试。。。");
}
}catch (Exception e) {
e.printStackTrace();
returnObject.setCode(Contants.RETURN_OBJECT_CODE_FAIL);
returnObject.setMessage("系统忙,请稍后重试。。。");
}
return returnObject;
}
5.clue的index.jsp页面
<%@page contentType="text/html; charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
String basePath=request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+request.getContextPath()+"/";
%>
<html>
<head>
<meta charset="UTF-8">
<base href="<%=basePath%>">
<link href="jquery/bootstrap_3.3.0/css/bootstrap.min.css" type="text/css" rel="stylesheet" />
<link href="jquery/bootstrap-datetimepicker-master/css/bootstrap-datetimepicker.min.css" type="text/css" rel="stylesheet" />
<link href="jquery/bs_pagination-master/css/jquery.bs_pagination.min.css">
<script type="text/javascript" src="jquery/jquery-1.11.1-min.js"></script>
<script type="text/javascript" src="jquery/bootstrap_3.3.0/js/bootstrap.min.js"></script>
<script type="text/javascript" src="jquery/bootstrap-datetimepicker-master/js/bootstrap-datetimepicker.js"></script>
<script type="text/javascript" src="jquery/bootstrap-datetimepicker-master/locale/bootstrap-datetimepicker.zh-CN.js"></script>
<script type="text/javascript" src="jquery/bs_pagination-master/js/jquery.bs_pagination.min.js"></script>
<script type="text/javascript" src="jquery/bs_pagination-master/localization/en.js"></script>
<script type="text/javascript">
$(function(){
//给创建按钮添加单击事件
$("#createClueBtn").click(function () {
//初始化工作,清空表单数据
$("#createClueForm").get(0).reset();
//弹出模态窗口
$("#createClueModal").modal("show");
});
//创建线索的模态窗口,给保存按钮添加单击事件
$("#saveCreateClueBtn").click(function () {
//收集参数
var fullname=$.trim($("#create-fullname").val());
var appellation=$("#create-appellation").val();
var owner=$("#create-owner").val();
var company=$.trim($("#create-company").val());
var job=$.trim($("#create-job").val());
var email=$.trim($("#create-email").val());
var phone=$.trim($("#create-phone").val());
var website=$.trim($("#create-website").val());
var mphone=$.trim($("#create-mphone").val());
var state=$("#create-state").val();
var source=$("#create-source").val();
var description=$.trim($("#create-description").val());
var contactSummary=$.trim($("#create-contactSummary").val());
var nextContactTime=$.trim($("#create-nextContactTime").val());
var address=$.trim($("#create-address").val());
//表单验证
if (company==""){
alert("公司不能为空!");
return;
}
if (fullname==""){
alert("姓名不能为空!");
return;
}
var emailRegExp=/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;
if (!emailRegExp.test(email)){
alert("请输入正确的邮箱格式!");
return;
}
var phoneRegExp=/\d{3}-\d{8}|\d{4}-\d{7}/;
if (!phoneRegExp.test(phone)){
alert("请输入正确的座机格式!");
return;
}
var websiteRegExp=/^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\*\+,;=.]+$/;
if(!websiteRegExp.test(website)){
alert("请输入格式正确的网站!");
return;
}
var mphoneRegExp=/^1((3[\d])|(4[5,6,9])|(5[0-3,5-9])|(6[5-7])|(7[0-8])|(8[1-3,5-8])|(9[1,8,9]))\d{8}$/;
if (!mphoneRegExp.test(mphone)){
alert("请输入正确的手机格式!");
return;
}
//发送请求
$.ajax({
url:"workbench/clue/saveCreateClue.do",
data:{
fullname : fullname ,
appellation : appellation ,
owner : owner ,
company : company ,
job : job ,
email : email ,
phone : phone ,
website : website ,
mphone : mphone ,
state : state ,
source : source ,
description : description ,
contactSummary : contactSummary ,
nextContactTime: nextContactTime,
address : address
},
dataType:'json',
type:'post',
success:function (data) {
if (data.code=="1"){
//关闭模态窗口
$("#createClueModal").modal("hide");
//刷新线索列表,显示第一页数据,保持每页条数不变
queryClueByConditionForPage(1,$("#demo_page").bs_pagination("getOption","rowsPerPage"));
}else {
//提示信息
alert(data.message);
//模态窗口不关闭
$("#createClueModal").modal("show");
}
}
});
});
//给文本框设置时间选择器
$(".mydate").datetimepicker({
language:'zh-CN',//语言
format:'yyyy-mm-dd',//日期的格式
minView:'month',//可以选择的最小视图
initialDate:new Date(),//初始化显示的日期
autoclose:true,//选择完日期后自动关闭日历
todayBtn:true,//设置是否显示今天的按钮
clearBtn:true//设置是否显示清空按钮
});
//当线索主页面加载完成后,查询所有数据的第一页,以及所有数据的总条数,默认每页显示10条
queryClueByConditionForPage(1,10);
//给查询按钮添加单击事件
$("#selectClueByConditionBtn").click(function () {
//查询所有符合条件数据的第一页以及所有符合条件数据的总条数
queryClueByConditionForPage(1,$("#demo_page").bs_pagination("getOption","rowsPerPage"));
});
});
//定义根据条件分页查找数据,和计算每页条目总数
function queryClueByConditionForPage(pageNo,pageSize) {
//收集参数
var fullname=$("#fullnameText").val();
var company=$("#companyText").val();
var phone=$("#phoneText").val();
var source=$("#sourceSelect").val();
var owner=$("#owner").val();
var mphone=$("#mphoneText").val();
var state=$("#stateSelect").val();
//发起请求
$.ajax({
url:"workbench/clue/queryClueByConditionForPage.do",
type: 'post',
data: {
fullname:fullname,
company:company,
phone:phone,
source:source,
owner:owner,
mphone:mphone,
state:state,
pageNo:pageNo,
pageSize:pageSize
},
dataType: 'json',
success:function (data) {
//显示市场活动列表
var htmlStr="";
$.each(data.clues,function (index,obj) {
htmlStr+="<tr class=\"active\">";
htmlStr+="<td><input type=\"checkbox\" /></td>";
htmlStr+="<td><a style=\"text-decoration: none; cursor: pointer;\" onclick=\"window.location.href='detail.html';\">"+obj.fullname+"</a></td>";
htmlStr+="<td>"+obj.company+"</td>";
htmlStr+="<td>"+obj.phone+"</td>";
htmlStr+="<td>"+obj.mphone+"</td>";
htmlStr+="<td>"+obj.source+"</td>";
htmlStr+="<td>"+obj.owner+"</td>";
htmlStr+="<td>"+obj.state+"</td>";
htmlStr+="</tr>";
});
$("#tBody").html(htmlStr);
//取消全选按钮
$("#checkAll").prop("checked",false);
var totalPages=1;
//计算总页数
if (data.totalRows%pageSize==0){
totalPages=data.totalRows/pageSize;
}else{
totalPages=parseInt(data.totalRows/pageSize)+1;
}
//对容器调用bs_pagination工具函数,显示翻页信息
$("#demo_page").bs_pagination({
currentPage:pageNo,//当前页号,相当于pageNo
rowsPerPage:pageSize,//每页显示行数,相当于pageSize
totalRows:data.totalRows,//总条数
totalPages:totalPages,//总页数
visiblePageLinks:10,//最多可以显示的卡片数
onChangePage:function (event,pageObj) {
queryClueByConditionForPage(pageObj.currentPage,pageObj.rowsPerPage);
}
});
}
});
}
</script>
</head>
<body>
<!-- 创建线索的模态窗口 -->
<div class="modal fade" id="createClueModal" role="dialog">
<div class="modal-dialog" role="document" style="width: 90%;">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">
<span aria-hidden="true">×</span>
</button>
<h4 class="modal-title" id="myModalLabel">创建线索</h4>
</div>
<div class="modal-body">
<form id="createClueForm" class="form-horizontal" role="form">
<div class="form-group">
<label for="create-owner" class="col-sm-2 control-label">所有者<span style="font-size: 15px; color: red;">*</span></label>
<div class="col-sm-10" style="width: 300px;">
<select class="form-control" id="create-owner">
<c:forEach items="${userList}" var="user">
<option value="${user.id}">${user.name}</option>
</c:forEach>
</select>
</div>
<label for="create-company" class="col-sm-2 control-label">公司<span style="font-size: 15px; color: red;">*</span></label>
<div class="col-sm-10" style="width: 300px;">
<input type="text" class="form-control" id="create-company">
</div>
</div>
<div class="form-group">
<label for="create-appellation" class="col-sm-2 control-label">称呼</label>
<div class="col-sm-10" style="width: 300px;">
<select class="form-control" id="create-appellation">
<option></option>
<c:forEach items="${appellation}" var="app">
<option value="${app.id}">${app.value}</option>
</c:forEach>
</select>
</div>
<label for="create-fullname" class="col-sm-2 control-label">姓名<span style="font-size: 15px; color: red;">*</span></label>
<div class="col-sm-10" style="width: 300px;">
<input type="text" class="form-control" id="create-fullname">
</div>
</div>
<div class="form-group">
<label for="create-job" class="col-sm-2 control-label">职位</label>
<div class="col-sm-10" style="width: 300px;">
<input type="text" class="form-control" id="create-job">
</div>
<label for="create-email" class="col-sm-2 control-label">邮箱</label>
<div class="col-sm-10" style="width: 300px;">
<input type="text" class="form-control" id="create-email">
</div>
</div>
<div class="form-group">
<label for="create-phone" class="col-sm-2 control-label">公司座机</label>
<div class="col-sm-10" style="width: 300px;">
<input type="text" class="form-control" id="create-phone">
</div>
<label for="create-website" class="col-sm-2 control-label">公司网站</label>
<div class="col-sm-10" style="width: 300px;">
<input type="text" class="form-control" id="create-website">
</div>
</div>
<div class="form-group">
<label for="create-mphone" class="col-sm-2 control-label">手机</label>
<div class="col-sm-10" style="width: 300px;">
<input type="text" class="form-control" id="create-mphone">
</div>
<label for="create-state" class="col-sm-2 control-label">线索状态</label>
<div class="col-sm-10" style="width: 300px;">
<select class="form-control" id="create-state">
<option></option>
<c:forEach items="${clueState}" var="clu">
<option value="${clu.id}">${clu.value}</option>
</c:forEach>
</select>
</div>
</div>
<div class="form-group">
<label for="create-source" class="col-sm-2 control-label">线索来源</label>
<div class="col-sm-10" style="width: 300px;">
<select class="form-control" id="create-source">
<option></option>
<c:forEach items="${source}" var="sou">
<option value="${sou.id}">${sou.value}</option>
</c:forEach>
</select>
</div>
</div>
<div class="form-group">
<label for="create-description" class="col-sm-2 control-label">线索描述</label>
<div class="col-sm-10" style="width: 81%;">
<textarea class="form-control" rows="3" id="create-description"></textarea>
</div>
</div>
<div style="height: 1px; width: 103%; background-color: #D5D5D5; left: -13px; position: relative;"></div>
<div style="position: relative;top: 15px;">
<div class="form-group">
<label for="create-contactSummary" class="col-sm-2 control-label">联系纪要</label>
<div class="col-sm-10" style="width: 81%;">
<textarea class="form-control" rows="3" id="create-contactSummary"></textarea>
</div>
</div>
<div class="form-group">
<label for="create-nextContactTime" class="col-sm-2 control-label">下次联系时间</label>
<div class="col-sm-10" style="width: 300px;">
<input type="text" class="form-control mydate" id="create-nextContactTime">
</div>
</div>
</div>
<div style="height: 1px; width: 103%; background-color: #D5D5D5; left: -13px; position: relative; top : 10px;"></div>
<div style="position: relative;top: 20px;">
<div class="form-group">
<label for="create-address" class="col-sm-2 control-label">详细地址</label>
<div class="col-sm-10" style="width: 81%;">
<textarea class="form-control" rows="1" id="create-address"></textarea>
</div>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
<button type="button" class="btn btn-primary" id="saveCreateClueBtn">保存</button>
</div>
</div>
</div>
</div>
<!-- 修改线索的模态窗口 -->
<div class="modal fade" id="editClueModal" role="dialog">
<div class="modal-dialog" role="document" style="width: 90%;">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">
<span aria-hidden="true">×</span>
</button>
<h4 class="modal-title">修改线索</h4>
</div>
<div class="modal-body">
<form class="form-horizontal" role="form">
<div class="form-group">
<label for="edit-clueOwner" class="col-sm-2 control-label">所有者<span style="font-size: 15px; color: red;">*</span></label>
<div class="col-sm-10" style="width: 300px;">
<select class="form-control" id="edit-clueOwner">
<c:forEach items="${userList}" var="user">
<option value="${user.id}">${user.name}</option>
</c:forEach>
</select>
</div>
<label for="edit-company" class="col-sm-2 control-label">公司<span style="font-size: 15px; color: red;">*</span></label>
<div class="col-sm-10" style="width: 300px;">
<input type="text" class="form-control" id="edit-company" value="动力节点">
</div>
</div>
<div class="form-group">
<label for="edit-call" class="col-sm-2 control-label">称呼</label>
<div class="col-sm-10" style="width: 300px;">
<select class="form-control" id="edit-call">
<option></option>
<c:forEach items="${appellation}" var="app">
<option value="${app.id}">${app.value}</option>
</c:forEach>
</select>
</div>
<label for="edit-surname" class="col-sm-2 control-label">姓名<span style="font-size: 15px; color: red;">*</span></label>
<div class="col-sm-10" style="width: 300px;">
<input type="text" class="form-control" id="edit-surname" value="李四">
</div>
</div>
<div class="form-group">
<label for="edit-job" class="col-sm-2 control-label">职位</label>
<div class="col-sm-10" style="width: 300px;">
<input type="text" class="form-control" id="edit-job" value="CTO">
</div>
<label for="edit-email" class="col-sm-2 control-label">邮箱</label>
<div class="col-sm-10" style="width: 300px;">
<input type="text" class="form-control" id="edit-email" value="lisi@bjpowernode.com">
</div>
</div>
<div class="form-group">
<label for="edit-phone" class="col-sm-2 control-label">公司座机</label>
<div class="col-sm-10" style="width: 300px;">
<input type="text" class="form-control" id="edit-phone" value="010-84846003">
</div>
<label for="edit-website" class="col-sm-2 control-label">公司网站</label>
<div class="col-sm-10" style="width: 300px;">
<input type="text" class="form-control" id="edit-website" value="http://www.bjpowernode.com">
</div>
</div>
<div class="form-group">
<label for="edit-mphone" class="col-sm-2 control-label">手机</label>
<div class="col-sm-10" style="width: 300px;">
<input type="text" class="form-control" id="edit-mphone" value="12345678901">
</div>
<label for="edit-status" class="col-sm-2 control-label">线索状态</label>
<div class="col-sm-10" style="width: 300px;">
<select class="form-control" id="edit-status">
<option></option>
<c:forEach items="${clueState}" var="clu">
<option value="${clu.id}">${clu.value}</option>
</c:forEach>
</select>
</div>
</div>
<div class="form-group">
<label for="edit-source" class="col-sm-2 control-label">线索来源</label>
<div class="col-sm-10" style="width: 300px;">
<select class="form-control" id="edit-source">
<option></option>
<c:forEach items="${source}" var="sou">
<option value="${sou.id}">${sou.value}</option>
</c:forEach>
</select>
</div>
</div>
<div class="form-group">
<label for="edit-describe" class="col-sm-2 control-label">描述</label>
<div class="col-sm-10" style="width: 81%;">
<textarea class="form-control" rows="3" id="edit-describe">这是一条线索的描述信息</textarea>
</div>
</div>
<div style="height: 1px; width: 103%; background-color: #D5D5D5; left: -13px; position: relative;"></div>
<div style="position: relative;top: 15px;">
<div class="form-group">
<label for="edit-contactSummary" class="col-sm-2 control-label">联系纪要</label>
<div class="col-sm-10" style="width: 81%;">
<textarea class="form-control" rows="3" id="edit-contactSummary">这个线索即将被转换</textarea>
</div>
</div>
<div class="form-group">
<label for="edit-nextContactTime" class="col-sm-2 control-label">下次联系时间</label>
<div class="col-sm-10" style="width: 300px;">
<input type="text" class="form-control" id="edit-nextContactTime" value="2017-05-01">
</div>
</div>
</div>
<div style="height: 1px; width: 103%; background-color: #D5D5D5; left: -13px; position: relative; top : 10px;"></div>
<div style="position: relative;top: 20px;">
<div class="form-group">
<label for="edit-address" class="col-sm-2 control-label">详细地址</label>
<div class="col-sm-10" style="width: 81%;">
<textarea class="form-control" rows="1" id="edit-address">北京大兴区大族企业湾</textarea>
</div>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
<button type="button" class="btn btn-primary" data-dismiss="modal">更新</button>
</div>
</div>
</div>
</div>
<div>
<div style="position: relative; left: 10px; top: -10px;">
<div class="page-header">
<h3>线索列表</h3>
</div>
</div>
</div>
<div style="position: relative; top: -20px; left: 0px; width: 100%; height: 100%;">
<div style="width: 100%; position: absolute;top: 5px; left: 10px;">
<div class="btn-toolbar" role="toolbar" style="height: 80px;">
<form class="form-inline" role="form" style="position: relative;top: 8%; left: 5px;">
<div class="form-group">
<div class="input-group">
<div class="input-group-addon">名称</div>
<input class="form-control" type="text" id="fullnameText">
</div>
</div>
<div class="form-group">
<div class="input-group">
<div class="input-group-addon">公司</div>
<input class="form-control" type="text" id="companyText">
</div>
</div>
<div class="form-group">
<div class="input-group">
<div class="input-group-addon">公司座机</div>
<input class="form-control" type="text" id="phoneText">
</div>
</div>
<div class="form-group">
<div class="input-group">
<div class="input-group-addon">线索来源</div>
<select class="form-control" id="sourceSelect">
<option></option>
<c:forEach items="${source}" var="sou">
<option value="${sou.id}">${sou.value}</option>
</c:forEach>
</select>
</div>
</div>
<br>
<div class="form-group">
<div class="input-group">
<div class="input-group-addon">所有者</div>
<input class="form-control" type="text" id="ownerText">
</div>
</div>
<div class="form-group">
<div class="input-group">
<div class="input-group-addon">手机</div>
<input class="form-control" type="text" id="mphoneText">
</div>
</div>
<div class="form-group">
<div class="input-group">
<div class="input-group-addon">线索状态</div>
<select class="form-control" id="stateSelect">
<option></option>
<c:forEach items="${clueState}" var="clu">
<option value="${clu.id}">${clu.value}</option>
</c:forEach>
</select>
</div>
</div>
<button type="submit" class="btn btn-default" id="selectClueByConditionBtn">查询</button>
</form>
</div>
<div class="btn-toolbar" role="toolbar" style="background-color: #F7F7F7; height: 50px; position: relative;top: 40px;">
<div class="btn-group" style="position: relative; top: 18%;">
<button type="button" class="btn btn-primary" id="createClueBtn"><span class="glyphicon glyphicon-plus"></span> 创建</button>
<button type="button" class="btn btn-default" data-toggle="modal" data-target="#editClueModal"><span class="glyphicon glyphicon-pencil"></span> 修改</button>
<button type="button" class="btn btn-danger"><span class="glyphicon glyphicon-minus"></span> 删除</button>
</div>
</div>
<div style="position: relative;top: 50px;">
<table class="table table-hover">
<thead>
<tr style="color: #B3B3B3;">
<td><input type="checkbox" id="checkAll"/></td>
<td>名称</td>
<td>公司</td>
<td>公司座机</td>
<td>手机</td>
<td>线索来源</td>
<td>所有者</td>
<td>线索状态</td>
</tr>
</thead>
<tbody id="tBody">
</tbody>
</table>
</div>
<div style="height: 70px; position: relative;top: 60px;" id="demo_page">
</div>
</div>
</div>
</body>
</html>
功能效果测试
不写公司名时,点击保存按钮弹出警告窗口
2.填写错误的邮箱
3.输入错误的座机号
4.输入错误的网站地址
5.输入错误的手机号
6.利用datetimepicker函数来便捷选择时间
7.全部输入合法的数据,点击保存按钮,提交表单
8.在页面主页,实时显示出来