• CRM项目记录(七)



    目录:

    (1)导入市场活动需求分析

    (2)crm演示文件上传

    (3)crm演示使用apache-poi解析excel文件

    (4)crm设计导入市场活动 

    (5)crm实现导入市场活动Controller

    (6)crm实现导入市场活动Controller

    (7)crm实现导入市场活动前台页面

    (8)crm优化导入市场活动

    (9)下面做查看市场活动明细:

    (10) crm实现市场活动明细查询备注信息Mapper层和Serevice层controller层

    (11)crm实现查看市场活动明细前台页面

    (12)crm添加市场活动备注实现Mapper层和Service层

    (13)crm添加市场活动备注实现controller层


    (1)导入市场活动需求分析

    需求:它是导出的逆过程。

    用户在市场活动主页面,点击"导入"按钮,弹出导入市场活动的模态窗口;

             用户在导入市场活动的模态窗口选择要上传的文件,点击"导入"按钮,完成导入市场活动的功能.

             *只支持.xls

             *文件大小不超过5MB

             *导入成功之后,提示成功导入记录条数,关闭模态窗口,刷新市场活动列表,显示第一页数据,保持每页显示条数不变

             *导入失败,提示信息,模态窗口不关闭,列表也不刷新

     (2)crm演示文件上传

    先准备一个小例子:先创建一个fileuploadtest.jsp:

    1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    2. <%
    3. String basePath=request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+request.getContextPath()+"/";
    4. %>
    5. <html>
    6. <head>
    7. <base href="<%=basePath%>">
    8. <title>演示文件上传</title>
    9. </head>
    10. <body>
    11. <!--
    12. 文件上传的表单三个条件:
    13. 1.表单组件标签必须用:<input type="file">
    14. <input type="text|password|radio|checkbox|hidden|button|submit|reset|file">
    15. <select>,<textarea>
    16. 2.请求方式只能用:post
    17. get:参数通过请求头提交到后台,参数放在URL后边;只能向后台提交文本数据;对参数长度有限制;数据不安全;效率高
    18. post:参数通过请求体提交到后台;既能能提交文件数据,又能够提交二进制数据;理论上对参数长度没有限制;相对安全;效率相对较低
    19. 3.表单的编码格式只能用:multipart/form-data
    20. 根据HTTP协议的规定,浏览器每次向后台提交参数,都会对参数进行统一编码;默认采用的编码格式是urlencoded,这种编码格式只能对文本数据进行编码;
    21. 浏览器每次向后台提交参数,都会首先把所有的参数转换成字符串,然后对这些数据统一进行urlencoded编码;
    22. 文件上传的表单编码格式只能用multipart/form-data:enctype="multipart/form-data"
    23. -->
    24. <form action="workbench/activity/fileUpload.do" method="post" enctype="multipart/form-data">
    25. <input type="file" name="myFile"><br>
    26. <input type="text" name="userName"><br>
    27. <input type="submit" value="提交">
    28. </form>
    29. </body>
    30. </html>

    controller不新建了,在ActivityController写就行了:

    1. //测试文件上传
    2. @RequestMapping("/workbench/activity/fileUpload.do")
    3. public @ResponseBody Object fileUpload(String userName, MultipartFile myFile) throws Exception{
    4. //把文本数据打印到控制台
    5. System.out.println("userName="+userName);
    6. //把文件在服务指定的目录中生成一个同样的文件
    7. String originalFilename=myFile.getOriginalFilename();//获取文件名
    8. File file=new File("D:\\AnZhuang\\Java项目\\CRM\\serverDir\\",originalFilename);//路径必须手动创建好,文件如果不存在,会自动创建
    9. myFile.transferTo(file);
    10. //返回响应信息
    11. ReturnObject returnObject=new ReturnObject();
    12. returnObject.setCode(Contants.RETURN_OBJECT_CODE_SUCCESS);
    13. returnObject.setMessage("上传成功");
    14. return returnObject;
    15. }

    在springmvc配置文件中配置文件上传解析器:

    1. <!-- 配置文件上传解析器 id:必须是multipartResolver-->
    2. <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    3. <property name="maxUploadSize" value="#{1024*1024*80}"/>
    4. <property name="defaultEncoding" value="utf-8"/>
    5. </bean>

     运行项目:需要先登录一下,在访问文件上传页面:

    选择上传文件:

    点击提交:

     

     

    (3)crm演示使用apache-poi解析excel文件

    ParseExcelTest: 

     创建测试类:

    1. package com.bjpowernode.crm.poi;
    2. import com.bjpowernode.crm.commons.utils.HSSFUtils;
    3. import org.apache.poi.hssf.usermodel.HSSFCell;
    4. import org.apache.poi.hssf.usermodel.HSSFRow;
    5. import org.apache.poi.hssf.usermodel.HSSFSheet;
    6. import org.apache.poi.hssf.usermodel.HSSFWorkbook;
    7. import java.io.FileInputStream;
    8. import java.io.InputStream;
    9. /**
    10. * 使用apache-poi解析excel文件
    11. */
    12. public class ParseExcelTest {
    13. public static void main(String[] args) throws Exception{
    14. //根据excel文件生成HSSFWorkbook对象,封装了excel文件的所有信息
    15. InputStream is=new FileInputStream("D:\\AnZhuang\\Java项目\\CRM\\serverDir\\activityList.xls");
    16. HSSFWorkbook wb=new HSSFWorkbook(is);
    17. //根据wb获取HSSFSheet对象,封装了一页的所有信息
    18. HSSFSheet sheet=wb.getSheetAt(0);//页的下标,下标从0开始,依次增加
    19. //根据sheet获取HSSFRow对象,封装了一行的所有信息
    20. HSSFRow row=null;
    21. HSSFCell cell=null;
    22. for(int i=0;i<=sheet.getLastRowNum();i++) {//sheet.getLastRowNum():最后一行的下标
    23. row=sheet.getRow(i);//行的下标,下标从0开始,依次增加
    24. for(int j=0;j<row.getLastCellNum();j++) {//row.getLastCellNum():最后一列的下标+1
    25. //根据row获取HSSFCell对象,封装了一列的所有信息
    26. cell=row.getCell(j);//列的下标,下标从0开始,依次增加
    27. //获取列中的数据
    28. System.out.print(HSSFUtils.getCellValueForStr(cell)+" ");;
    29. }
    30. //每一行中所有列都打完,打印一个换行
    31. System.out.println();
    32. }
    33. }
    34. }

    创建工具类:用来解析列的的属性类型,并获取属性值:

    创建工具类HSSFUtils:

    1. package com.bjpowernode.crm.commons.utils;
    2. import org.apache.poi.hssf.usermodel.HSSFCell;
    3. /**
    4. * 关于excel文件操作的工具类
    5. */
    6. public class HSSFUtils {
    7. /**
    8. * 从指定的HSSFCell对象中获取列的值
    9. * @return
    10. */
    11. public static String getCellValueForStr(HSSFCell cell){
    12. String ret="";
    13. if(cell.getCellType()==HSSFCell.CELL_TYPE_STRING){
    14. ret=cell.getStringCellValue();
    15. }else if(cell.getCellType()==HSSFCell.CELL_TYPE_NUMERIC){
    16. ret=cell.getNumericCellValue()+"";
    17. }else if(cell.getCellType()==HSSFCell.CELL_TYPE_BOOLEAN){
    18. ret=cell.getBooleanCellValue()+"";
    19. }else if(cell.getCellType()==HSSFCell.CELL_TYPE_FORMULA){
    20. ret=cell.getCellFormula();
    21. }else{
    22. ret="";
    23. }
    24. return ret;
    25. }
    26. }

     运行ParseExcelTest类:

    (4)crm设计导入市场活动 

     

    在ActivityMapper接口中:

     在AcvtivityMapper.xml中:

    1. <!--批量保存创建的市场活动-->
    2. <insert id="insertActivityByList" parameterType="com.bjpowernode.crm.workbench.domain.Activity">
    3. insert into tbl_activity(id, owner, name, start_date, end_date, cost, description, create_time, create_by)
    4. values
    5. <foreach collection="list" item="obj" separator=",">
    6. (#{obj.id},#{obj.owner},#{obj.name},#{obj.startDate},#{obj.endDate},#{obj.cost},#{obj.description},#{obj.createTime},#{obj.createBy})
    7. </foreach>
    8. </insert>

     在ActivitySertvice接口:

    实现类:

    (6)crm实现导入市场活动Controller

    唯一id工具类: 

    1. package com.bjpowernode.crm.commons.utils;
    2. import java.util.UUID;
    3. public class UUIDUtils {
    4. /**
    5. * 回去uuid的值
    6. * @return
    7. */
    8. public static String getUUID(){
    9. return UUID.randomUUID().toString().replaceAll("-","");
    10. }
    11. }

    时间格式化工具类

    1. package com.bjpowernode.crm.commons.utils;
    2. import java.text.SimpleDateFormat;
    3. import java.util.Date;
    4. /**
    5. * 对Date类型数据进行处理的工具类
    6. */
    7. public class DateUtils {
    8. /**
    9. * 对指定的date对象进行格式化: yyyy-MM-dd HH:mm:ss
    10. * @param date
    11. * @return
    12. */
    13. public static String formateDateTime(Date date){
    14. SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    15. String dateStr=sdf.format(date);
    16. return dateStr;
    17. }
    18. /**
    19. * 对指定的date对象进行格式化: yyyy-MM-dd
    20. * @param date
    21. * @return
    22. */
    23. public static String formateDate(Date date){
    24. SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
    25. String dateStr=sdf.format(date);
    26. return dateStr;
    27. }
    28. /**
    29. * 对指定的date对象进行格式化: HH:mm:ss
    30. * @param date
    31. * @return
    32. */
    33. public static String formateTime(Date date){
    34. SimpleDateFormat sdf=new SimpleDateFormat("HH:mm:ss");
    35. String dateStr=sdf.format(date);
    36. return dateStr;
    37. }
    38. }

    在ActivityController:添加请求 

    1. //导入市场活动请求
    2. @RequestMapping("/workbench/activity/importActivity.do")
    3. public @ResponseBody Object importActivity(MultipartFile activityFile,String userName,HttpSession session){
    4. System.out.println("userName="+userName);
    5. User user=(User) session.getAttribute(Contants.SESSION_USER);
    6. ReturnObject returnObject=new ReturnObject();
    7. try {
    8. //把excel文件写到磁盘目录中
    9. String originalFilename = activityFile.getOriginalFilename();
    10. File file = new File("D:\\AnZhuang\\Java项目\\CRM\\serverDir\\", originalFilename);//路径必须手动创建好,文件如果不存在,会自动创建
    11. activityFile.transferTo(file);
    12. //解析excel文件,获取文件中的数据,并且封装成activityList
    13. //根据excel文件生成HSSFWorkbook对象,封装了excel文件的所有信息
    14. InputStream is=new FileInputStream("D:\\AnZhuang\\Java项目\\CRM\\serverDir\\"+originalFilename);
    15. HSSFWorkbook wb=new HSSFWorkbook(is);
    16. //根据wb获取HSSFSheet对象,封装了一页的所有信息
    17. HSSFSheet sheet=wb.getSheetAt(0);//页的下标,下标从0开始,依次增加
    18. //根据sheet获取HSSFRow对象,封装了一行的所有信息
    19. HSSFRow row=null;
    20. HSSFCell cell=null;
    21. Activity activity=null;
    22. List<Activity> activityList=new ArrayList<>();
    23. for(int i=1;i<=sheet.getLastRowNum();i++) {//sheet.getLastRowNum():最后一行的下标
    24. row=sheet.getRow(i);//行的下标,下标从0开始,依次增加
    25. activity=new Activity();
    26. activity.setId(UUIDUtils.getUUID());
    27. activity.setOwner(user.getId());
    28. activity.setCreateTime(DateUtils.formateDateTime(new Date()));
    29. activity.setCreateBy(user.getId());
    30. for(int j=0;j
    31. //根据row获取HSSFCell对象,封装了一列的所有信息
    32. cell=row.getCell(j);//列的下标,下标从0开始,依次增加
    33. //获取列中的数据 调用工具类HSSFUtils
    34. String cellValue= HSSFUtils.getCellValueForStr(cell);
    35. if(j==0){
    36. activity.setName(cellValue);
    37. }else if(j==1){
    38. activity.setStartDate(cellValue);
    39. }else if(j==2){
    40. activity.setEndDate(cellValue);
    41. }else if(j==3){
    42. activity.setCost(cellValue);
    43. }else if(j==4){
    44. activity.setDescription(cellValue);
    45. }
    46. }
    47. //每一行中所有列都封装完成之后,把activity保存到list中
    48. activityList.add(activity);
    49. }
    50. //调用service层方法,保存市场活动
    51. int ret=activityService.saveCreateActivityByList(activityList);
    52. returnObject.setCode(Contants.RETURN_OBJECT_CODE_SUCCESS);
    53. returnObject.setRetData(ret);//返回数据
    54. }catch (Exception e){
    55. e.printStackTrace();
    56. returnObject.setCode(Contants.RETURN_OBJECT_CODE_FAIL);
    57. returnObject.setMessage("系统忙,请稍后重试....");
    58. }
    59. return returnObject;
    60. }

    (6)crm实现导入市场活动前台页面

     在市场活动index.jsp:

    文件上传ajax需要设置的参数: 

    processData:false,//设置ajax向后台提交参数之前,是否把参数统一转换成字符串:true--是,false--不是,默认是true
    contentType:false,//设置ajax向后台提交参数之前,是否把所有的参数统一按urlencoded编码:true--是,false--不是,默认是true
    1. //"批量导出"按钮添加单击事件
    2. $("#exportActivityAllBtn").click(function () {
    3. //发送同步请求
    4. window.location.href="workbench/activity/exportAllActivitys.do";
    5. });
    6. //"导入"按钮添加单击事件
    7. $("#importActivityBtn").click(function () {
    8. //收集参数
    9. var activityFileName=$("#activityFile").val();
    10. var suffix=activityFileName.substr(activityFileName.lastIndexOf(".")+1).toLocaleLowerCase();//xls,XLS,Xls,xLs,....
    11. if(suffix!="xls"){
    12. alert("只支持xls文件");
    13. return;
    14. }
    15. //获取文件
    16. var activityFile=$("#activityFile")[0].files[0];
    17. if(activityFile.size>5*1024*1024){
    18. alert("文件大小不超过5MB");
    19. return;
    20. }
    21. //FormData是ajax提供的接口,可以模拟键值对向后台提交参数;
    22. //FormData最大的优势是不但能提交文本数据,还能提交二进制数据
    23. var formData=new FormData();
    24. formData.append("activityFile",activityFile);
    25. formData.append("userName","张三");
    26. //发送请求
    27. $.ajax({
    28. url:'workbench/activity/importActivity.do',
    29. data:formData,
    30. processData:false,//设置ajax向后台提交参数之前,是否把参数统一转换成字符串:true--是,false--不是,默认是true
    31. contentType:false,//设置ajax向后台提交参数之前,是否把所有的参数统一按urlencoded编码:true--是,false--不是,默认是true
    32. type:'post',
    33. dataType:'json',
    34. success:function (data) {
    35. if(data.code=="1"){
    36. //提示成功导入记录条数
    37. alert("成功导入"+data.retData+"条记录");
    38. //关闭模态窗口
    39. $("#importActivityModal").modal("hide");
    40. //刷新市场活动列表,显示第一页数据,保持每页显示条数不变
    41. queryActivityByConditionForPage(1,$("#demo_pag1").bs_pagination('getOption', 'rowsPerPage'));
    42. }else{
    43. //提示信息
    44. alert(data.message);
    45. //模态窗口不关闭
    46. $("#importActivityModal").modal("show");
    47. }
    48. }
    49. });
    50. });
    51. });

    我们上传的文件格式都是跟客户约束好的:

    点击上传表数据:

    选择文件:

     

    点击导入:

     

     (8)crm优化导入市场活动

    这一行 代码效率是非常低的,它把内存中的数据写到磁盘上 ,这一过程效率是低的

    File file = new File("D:\\AnZhuang\\Java项目\\CRM\\serverDir\\", originalFilename);//路径必须手动创建好,文件如果不存在,会自动创建
    activityFile.transferTo(file);

    下面的代码效率也低,它需要把磁盘上的数据,读 到内存

    InputStream is=new FileInputStream("D:\\AnZhuang\\Java项目\\CRM\\serverDir\\"+originalFilename);
    
    HSSFWorkbook wb=new HSSFWorkbook(is);

    让他直接从内存读到内存,不进行读磁盘了,更改代码:ActivityController中的代码:

    1. //导入市场活动请求
    2. @RequestMapping("/workbench/activity/importActivity.do")
    3. public @ResponseBody Object importActivity(MultipartFile activityFile,String userName,HttpSession session){
    4. System.out.println("userName="+userName);
    5. User user=(User) session.getAttribute(Contants.SESSION_USER);
    6. ReturnObject returnObject=new ReturnObject();
    7. try {
    8. //把excel文件写到磁盘目录中
    9. /*String originalFilename = activityFile.getOriginalFilename();
    10. File file = new File("D:\\AnZhuang\\Java项目\\CRM\\serverDir\\", originalFilename);//路径必须手动创建好,文件如果不存在,会自动创建
    11. activityFile.transferTo(file);*/
    12. //解析excel文件,获取文件中的数据,并且封装成activityList
    13. //根据excel文件生成HSSFWorkbook对象,封装了excel文件的所有信息
    14. //InputStream is=new FileInputStream("D:\\AnZhuang\\Java项目\\CRM\\serverDir\\"+originalFilename);
    15. InputStream is=activityFile.getInputStream();
    16. HSSFWorkbook wb=new HSSFWorkbook(is);
    17. //根据wb获取HSSFSheet对象,封装了一页的所有信息
    18. HSSFSheet sheet=wb.getSheetAt(0);//页的下标,下标从0开始,依次增加
    19. //根据sheet获取HSSFRow对象,封装了一行的所有信息
    20. HSSFRow row=null;
    21. HSSFCell cell=null;
    22. Activity activity=null;
    23. List<Activity> activityList=new ArrayList<>();
    24. for(int i=1;i<=sheet.getLastRowNum();i++) {//sheet.getLastRowNum():最后一行的下标
    25. row=sheet.getRow(i);//行的下标,下标从0开始,依次增加
    26. activity=new Activity();
    27. activity.setId(UUIDUtils.getUUID());
    28. activity.setOwner(user.getId());
    29. activity.setCreateTime(DateUtils.formateDateTime(new Date()));
    30. activity.setCreateBy(user.getId());
    31. for(int j=0;j
    32. //根据row获取HSSFCell对象,封装了一列的所有信息
    33. cell=row.getCell(j);//列的下标,下标从0开始,依次增加
    34. //获取列中的数据 调用工具类HSSFUtils
    35. String cellValue= HSSFUtils.getCellValueForStr(cell);
    36. if(j==0){
    37. activity.setName(cellValue);
    38. }else if(j==1){
    39. activity.setStartDate(cellValue);
    40. }else if(j==2){
    41. activity.setEndDate(cellValue);
    42. }else if(j==3){
    43. activity.setCost(cellValue);
    44. }else if(j==4){
    45. activity.setDescription(cellValue);
    46. }
    47. }
    48. //每一行中所有列都封装完成之后,把activity保存到list中
    49. activityList.add(activity);
    50. }
    51. //调用service层方法,保存市场活动
    52. int ret=activityService.saveCreateActivityByList(activityList);
    53. returnObject.setCode(Contants.RETURN_OBJECT_CODE_SUCCESS);
    54. returnObject.setRetData(ret);//返回数据
    55. }catch (Exception e){
    56. e.printStackTrace();
    57. returnObject.setCode(Contants.RETURN_OBJECT_CODE_FAIL);
    58. returnObject.setMessage("系统忙,请稍后重试....");
    59. }
    60. return returnObject;
    61. }

    重新运行项目:更改导入内容:

     

     (9)下面做查看市场活动明细:

    点击某个市场活动跳到详细的市场活动的页面:

     需求:

    用户在市场活动主页面,点击市场活动名称超级链接,跳转到明细页面,完成查看市场活动明细的功能.

             *在市场活动明细页面,展示:

               -市场活动的基本信息

               -该市场活动下所有的备注信息

     

     

    在ActivityMapper接口中添加方法:

     ActivityMapper.xml:中写sql语句:

    1. <select id="selectActivityForDetailById" parameterType="string" resultMap="BaseResultMap">
    2. select a.id,u1.name as owner,a.name,a.start_date,a.end_date,a.cost,a.description,a.create_time,u2.name as create_by,
    3. a.edit_time,u3.name as edit_by
    4. from tbl_activity a
    5. join tbl_user u1 on a.owner=u1.id
    6. join tbl_user u2 on a.create_by=u2.id
    7. left join tbl_user u3 on a.edit_by=u3.id
    8. where a.id=#{id}
    9. select>

     在ActivitySeervice接口中添加:

    实现类:

    (10) crm实现市场活动明细查询备注信息Mapper层和Serevice层controller层

    通过Mybatis逆向工程生成市场活动备注 对应的Mapper等代码:

    修改Mybatis逆向工程的配置文件,只修改注释表的信息

     运行:就生成了响应的代码, 生成备注的实体类:ActivityRemmark、备注的ActivityRemarkMapper接口、ActivityRemarkMappe.xml备注的配置文件

    在ActivityRemarkMappe接口里添加一个方法:

    1. /**
    2. * 根据activityId查询该市场活动下所有备注的明细信息
    3. * @param activityId
    4. * @return
    5. */
    6. List selectActivityRemarkForDetailByActivityId(String activityId);

     在ActivityRemarkMappe.xml中写sql语句:

     创建ActivityRemarkService接口

    1. package com.bjpowernode.crm.workbench.service;
    2. import com.bjpowernode.crm.workbench.domain.ActivityRemark;
    3. import java.util.List;
    4. public interface ActivityRemarkService {
    5. //根据activityId查询该市场活动下所有备注的明细信息
    6. List queryActivityRemarkForDetailByActivityId(String activityId);
    7. }

     实现类:

    1. package com.bjpowernode.crm.workbench.service.impl;
    2. import com.bjpowernode.crm.workbench.domain.ActivityRemark;
    3. import com.bjpowernode.crm.workbench.mapper.ActivityRemarkMapper;
    4. import com.bjpowernode.crm.workbench.service.ActivityRemarkService;
    5. import org.springframework.beans.factory.annotation.Autowired;
    6. import org.springframework.stereotype.Service;
    7. import java.util.List;
    8. @Service("activityRemarkService")
    9. public class ActivityRemarkServiceImpl implements ActivityRemarkService {
    10. @Autowired
    11. private ActivityRemarkMapper activityRemarkMapper;
    12. @Override
    13. public List queryActivityRemarkForDetailByActivityId(String activityId) {
    14. return activityRemarkMapper.selectActivityRemarkForDetailByActivityId(activityId);
    15. }
    16. }

    ActivityController:

    1. //根据activityId查询该市场活动和所有备注的明细信息请求
    2. @RequestMapping("/workbench/activity/detailActivity.do")
    3. public String detailActivity(String id,HttpServletRequest request){
    4. //调用service层方法,查询数据
    5. Activity activity=activityService.queryActivityForDetailById(id);
    6. //查看备注信息
    7. List<ActivityRemark> remarkList=activityRemarkService.queryActivityRemarkForDetailByActivityId(id);
    8. //把数据保存到request中
    9. request.setAttribute("activity",activity);
    10. request.setAttribute("remarkList",remarkList);
    11. //请求转发
    12. return "workbench/activity/detail";
    13. }

    把detail.html改为detail.jsp:

    修改从作用域获取数据: 

    1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    2. <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    3. <%
    4. String basePath=request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+request.getContextPath()+"/";
    5. %>
    6. <head>
    7. "<%=basePath%>">
    8. "UTF-8">
    9. <link href="jquery/bootstrap_3.3.0/css/bootstrap.min.css" type="text/css" rel="stylesheet" />
    10. "modal fade" id="editRemarkModal" role="dialog">
    11. <%-- 备注的id --%>
    12. type="hidden" id="remarkId">
    13. "modal-dialog" role="document" style="width: 40%;">
    14. "modal-content">
    15. "modal-header">
    16. "true"
    17. "modal-title" id="myModalLabel">修改备注

  • "modal-body">
  • "form-horizontal" role="form">
  • type="hidden" id="edit-id">
  • "form-group">
  • "col-sm-10" style="width: 81%;">
  • "modal-footer">
  • "position: relative; top: 35px; left: 10px;">
  • "position: relative; left: 40px; top: -30px;">
  • "page-header">
  • 市场活动-${activity.name} ${activity.startDate} ~ ${activity.endDate}




  • "position: relative; top: -70px;">
  • "position: relative; left: 40px; height: 30px;">
  • "width: 300px; color: gray;">所有者
  • "width: 300px;position: relative; left: 200px; top: -20px;">${activity.owner}
  • "width: 300px;position: relative; left: 450px; top: -40px; color: gray;">名称
  • "width: 300px;position: relative; left: 650px; top: -60px;">${activity.name}
  • "height: 1px; width: 400px; background: #D5D5D5; position: relative; top: -60px;">
  • "height: 1px; width: 400px; background: #D5D5D5; position: relative; top: -60px; left: 450px;">
  • "position: relative; left: 40px; height: 30px; top: 10px;">
  • "width: 300px; color: gray;">开始日期
  • "width: 300px;position: relative; left: 200px; top: -20px;">${activity.startDate}
  • "width: 300px;position: relative; left: 450px; top: -40px; color: gray;">结束日期
  • "width: 300px;position: relative; left: 650px; top: -60px;">${activity.endDate}
  • "height: 1px; width: 400px; background: #D5D5D5; position: relative; top: -60px;">
  • "height: 1px; width: 400px; background: #D5D5D5; position: relative; top: -60px; left: 450px;">
  • "position: relative; left: 40px; height: 30px; top: 20px;">
  • "width: 300px; color: gray;">成本
  • "width: 300px;position: relative; left: 200px; top: -20px;">${activity.cost}
  • "height: 1px; width: 400px; background: #D5D5D5; position: relative; top: -20px;">
  • "position: relative; left: 40px; height: 30px; top: 30px;">
  • "width: 300px; color: gray;">创建者
  • "width: 500px;position: relative; left: 200px; top: -20px;">${activity.createBy}  "font-size: 10px; color: gray;">${activity.createTime}
  • "height: 1px; width: 550px; background: #D5D5D5; position: relative; top: -20px;">
  • "position: relative; left: 40px; height: 30px; top: 40px;">
  • "width: 300px; color: gray;">修改者
  • "width: 500px;position: relative; left: 200px; top: -20px;">${activity.editBy}  "font-size: 10px; color: gray;">${activity.editTime}
  • "height: 1px; width: 550px; background: #D5D5D5; position: relative; top: -20px;">
  • "position: relative; left: 40px; height: 30px; top: 50px;">
  • "width: 300px; color: gray;">描述
  • "width: 630px;position: relative; left: 200px; top: -20px;">
  • ${activity.description}
  • "height: 1px; width: 850px; background: #D5D5D5; position: relative; top: -20px;">
  • id="remarkDivList" style="position: relative; top: 30px; left: 40px;">
  • "page-header">
  • 备注

  • "${remarkList}" var="remark">
  • id="div_${remark.id}" class="remarkDiv" style="height: 60px;">
  • "${remark.createBy}" src="image/user-thumbnail.png" style="width: 30px; height:30px;">
  • "position: relative; top: -40px; left: 40px;" >
  • ${remark.noteContent}
  • "gray">市场活动 "gray">- ${activity.name} "color: gray;"> ${remark.editFlag=='1'?remark.editTime:remark.createTime}${remark.editFlag=='1'?remark.editBy:remark.createBy}${remark.editFlag=='1'?'修改':'创建'}
  • "position: relative; left: 500px; top: -30px; height: 30px; width: 100px; display: none;">
  •     
  • <%--
    "remarkDiv" style="height: 60px;">
  • "zhangsan" src="image/user-thumbnail.png" style="width: 30px; height:30px;">
  • "position: relative; top: -40px; left: 40px;" >
  • 哎呦!
  • "gray">市场活动 "gray">- 发传单 "color: gray;"> 2017-01-22 10:10:10 由zhangsan
  • "position: relative; left: 500px; top: -30px; height: 30px; width: 100px; display: none;">
  •     
  • --%>
  • <%--
    "remarkDiv" style="height: 60px;">
  • "zhangsan" src="image/user-thumbnail.png" style="width: 30px; height:30px;">
  • "position: relative; top: -40px; left: 40px;" >
  • 呵呵!
  • "gray">市场活动 "gray">- 发传单 "color: gray;"> 2017-01-22 10:20:10 由zhangsan
  • "position: relative; left: 500px; top: -30px; height: 30px; width: 100px; display: none;">
  •     
  • --%>
  • id="remarkDiv" style="background-color: #E6E6E6; width: 870px; height: 90px;">
  • "form" style="position: relative;top: 10px; left: 10px;">
  • id="cancelAndSaveBtn" style="position: relative;left: 737px; top: 10px; display: none;">

  • "height: 200px;">
  • (11)crm实现查看市场活动明细前台页面

     添加市场活动备注需求:

    用户在市场活动明细页面,输入备注内容,点击"保存"按钮,完成添加市场活动备注的功能.

             *备注内容不能为空

             *添加成功之后,清空输入框,刷新备注列表

             *添加失败,提示信息,输入框不清空,列表也不刷新

     (12)crm添加市场活动备注实现Mapper层和Service层

     在ActivityRemarkMapper接口里添加方法:

     ActivityRemarkMapper.xml中添加sql语句:

    1. <!--保存创建的市场活动备注-->
    2. <insert id="insertActivityRemark" parameterType="com.bjpowernode.crm.workbench.domain.ActivityRemark">
    3. insert into tbl_activity_remark(id, note_content, create_time, create_by, edit_flag, activity_id)
    4. values(#{id},#{ noteContent},#{ createTime},#{ createBy},#{ editFlag},#{ activityId})
    5. </insert>

     在ActivityRemarkService接口添加:

     实现类:

    (13)crm添加市场活动备注实现controller层

     创建ActivityRemarkController类:添加请求

    1. //保存创建的市场活动备注请求
    2. @RequestMapping("/workbench/activity/saveCreateActivityRemark.do")
    3. public @ResponseBody Object saveCreateActivityRemark(ActivityRemark remark, HttpSession session){
    4. User user=(User) session.getAttribute(Contants.SESSION_USER);
    5. //封装参数
    6. remark.setId(UUIDUtils.getUUID());
    7. remark.setCreateTime(DateUtils.formateDateTime(new Date()));
    8. remark.setCreateBy(user.getId());
    9. remark.setEditFlag(Contants.REMARK_EDIT_FLAG_NO_EDITED);//Contants.REMARK_EDIT_FLAG_NO_EDITED:表示常量备注的修改标记
    10. ReturnObject returnObject=new ReturnObject();
    11. try {
    12. //调用service层方法,保存创建的市场活动备注
    13. int ret = activityRemarkService.saveCreateActivityRemark(remark);
    14. if(ret>0){
    15. returnObject.setCode(Contants.RETURN_OBJECT_CODE_SUCCESS);
    16. returnObject.setRetData(remark);
    17. }else{
    18. returnObject.setCode(Contants.RETURN_OBJECT_CODE_FAIL);
    19. returnObject.setMessage("系统忙,请稍后重试....");
    20. }
    21. }catch (Exception e){
    22. e.printStackTrace();
    23. returnObject.setCode(Contants.RETURN_OBJECT_CODE_FAIL);
    24. returnObject.setMessage("系统忙,请稍后重试....");
    25. }
    26. return returnObject;
    27. }

     给detail.jsp的保存按钮添加事件:

    首先给按钮添加一个id:

     

    1. //"保存"按钮添加单击事件
    2. $("#saveCreateActivityRemarkBtn").click(function () {
    3. //收集参数
    4. var noteContent=$.trim($("#remark").val());
    5. var activityId='${activity.id}';
    6. //表单验证
    7. if(noteContent==""){
    8. alert("备注内容不能为空");
    9. return;
    10. }
    11. //发送请求
    12. $.ajax({
    13. url:'workbench/activity/saveCreateActivityRemark.do',
    14. data:{
    15. noteContent:noteContent,
    16. activityId:activityId
    17. },
    18. type:'post',
    19. dateType:'json',
    20. success:function (data) {
    21. if(data.code=="1"){
    22. //清空输入框
    23. $("#remark").val("");
    24. //刷新备注列表
    25. var htmlStr="";
    26. htmlStr+="
      div_"+data.retData.id+"\" class=\"remarkDiv\" style=\"height: 60px;\">";
    27. htmlStr+="${sessionScope.sessionUser.name}\" src=\"image/user-thumbnail.png\" style=\"width: 30px; height:30px;\">";
    28. htmlStr+="
      position: relative; top: -40px; left: 40px;\" >";
    29. htmlStr+="
      "+data.retData.noteContent+"
      "
      ;
    30. htmlStr+="gray\">市场活动 gray\">- ${activity.name} color: gray;\"> "+data.retData.createTime+" 由${sessionScope.sessionUser.name}创建";
    31. htmlStr+="
      position: relative; left: 500px; top: -30px; height: 30px; width: 100px; display: none;\">";
    32. htmlStr+="    ";
    33. htmlStr+="
      ";
    34. htmlStr+="
      ";
    35. htmlStr+="
      ";
    36. $("#remarkDiv").before(htmlStr);//追加显示到指定标签的后面
    37. }else{
    38. //提示信息
    39. alert(data.message);
    40. }
    41. }
    42. });
    43. });

     

    点击第一条测试:i测试07 

    添加备注:

     点击保存:

     

  • 相关阅读:
    探索Kubernetes的高可用性:单master集群和多master节点集群方案
    vscode c/c++ 检测到 #include 错误。请更新 includePath。
    web网页设计期末课程大作业 基于HTML+CSS+JavaScript响应式环保科技公司网站模板(环保主题网站设计)
    使用 Apache Camel 和 Quarkus 的微服务(一)
    GPT-SoVITS声音克隆训练和推理(新手教程,附整合包)
    Unable to find GatewayFilterFactory with name TokenRelay
    安装dai li
    Apache Doris 快速入门
    【毕业设计】基于单片机的智能饮水机系统 - stm32 物联网 嵌入式
    SOLID之DIP-依赖反转原则
  • 原文地址:https://blog.csdn.net/dengfengling999/article/details/127092960