基于javaweb+mysql的springbootcrm客户关系管理系统(java+springboot+echarts+freemarker+layui+maven+mysql)

基于javaweb+mysql的springbootcrm客户关系管理系统(java+springboot+echarts+freemarker+layui+maven+mysql)

私信源码获取及调试交流

运行环境

Java≥8、MySQL≥5.7

开发工具

eclipse/idea/myeclipse/sts等均可配置运行

适用

课程设计,大作业,毕业设计,项目练习,学习演示等

功能说明

基于javaweb+mysql的SpringBootcrm客户关系管理系统(java+springboot+echarts+freemarker+layui+maven+mysql)

CRM智能办公

项目介绍

本应用是一个客户关系管理系统,主要包括五大模块,分别是营销管理,客户管理,服务管理,统计报表和系统管理,为客户关系管理提供简单的数据管理与分析

技术选型方面,该项目是一个SpringBoot的单体应用,项目使用SpringBoot2框架快速开发,数据访问层使用Mybatis框架,页面渲染引擎使用Freemarker,页面样式使用Layui,日志方面选用的是logback,统计报表部分使用的是ECharts,数据库使用的Mysql 8.0版本;

安装教程

  1. 在mysql(默认为mysql8)中创建名为crm的数据库,并执行源码根目录的crm.sql脚本生成数据库表以及数据 2. 将项目源码导入idea中,指定项目的jdk版本为jdk8或以上,并标记为maven项目,下载所需依赖 3. 修改application.yml中针对于数据库的配置(主要是数据库名和数据库密码) 4. 修改logback.xml中,第4行,日志文件的存储地址,改为自己的路径;

  2. 启动项目测试是否正常,默认启动地址首页为http://localhost:1212/crm,默认数据库中的管理员为admin,密码为123456,可在登录系统之后自行修改用户密码

    private Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    @Autowired
    private ResultInfo resultInfo;

    /**
     * 全局异常处理
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @return
     */
    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        // 设置默认视图
        ModelAndView view = new ModelAndView("error");
        view.addObject("code", "500");
        view.addObject("msg", "系统资源繁忙");

        // 处理未登录异常
        if (ex instanceof NoLoginException) {
            // 清除view设置
            view.clear();
            // 返回到登录页面
            view.setViewName("redirect:/index");
            logger.error("未登录异常");
            return view;
        }

        // 判断handler
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            Annotation responseBody = handlerMethod.getMethod().getDeclaredAnnotation(ResponseBody.class);
            // 返回视图
            if (responseBody == null) {
                // 自定义异常
                if (ex instanceof ParamsException) {
                    ParamsException paramsException = (ParamsException) ex;
                    view.addObject("code", paramsException.getCode());
                    view.addObject("msg", paramsException.getMsg());
                }else if (ex instanceof AuthException) {
                    AuthException authException = (AuthException) ex;
                    view.addObject("code", authException.getCode());
                    view.addObject("msg", authException.getMsg());
                }
                logger.error("返回视图异常:viewName={}",view.getViewName());
            } else {    // 返回json数据
                // 设置默认值
                resultInfo.setAll(500, ex.getMessage(), null);
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 获取session
        Object user = request.getSession().getAttribute("user");
        // 获取cookie
        int userId = LoginUserUtil.releaseUserIdFromCookie(request);
        // session为空
        if (user != null) {
            return true;
        }else if (userId != -1 && userMapper.selectByPrimaryKey(userId) != null) {
            return true;
        }else {
            throw new NoLoginException();
        }
    }
}

/**
 * 资源管理控制器
 *
 * @version 1.0
 */
@Controller
@RequestMapping("/permission")
public class PermissionController {

    @Autowired
    private PermissionService permissionService;

    @Autowired
    private ResultInfo resultInfo;


/**
 * 客户开发计划控制器
 *
 * @version 1.0
 */
@RequestMapping("/cusDevPlan")
@Controller
public class CusDevPlanController extends BaseController {

    @Autowired
    private SaleChanceService saleChanceService;

    @Autowired
    private CusDevPlanService cusDevPlanService;

    @Autowired
    private ResultInfo resultInfo;

    /**
     * 跳转到客户开发计划首页
     * @return
     */
    @GetMapping("/index")
    public String index() {
        return "cusDevPlan/cusDevPlan";
    }

    /**
     * 多条件查询客户开发计划数据
     *
     * @param saleChanceQuery
     * @return
     */
    @GetMapping("/cusDevPlanList")
    @ResponseBody
        return "customerServe/customerServeBackForEdit";
    }

    /**
     * 客户管理模块的视图有此方法执行跳转
     *
     * @return
     */
    @GetMapping("/index/{index}")
    public String index(@PathVariable("index") Integer index) {
        // 校验参数
        AssertUtil.isTrue(index == null, "非法页面跳转");
        if (index == 1) {
            // 服务创建
            return "customerServe/customerServe";
        } else if (index == 2) {
            // 服务分配
            return "customerServe/customerServeAssigner";
        } else if (index == 3) {
            // 服务处理
            return "customerServe/customerServeHandle";
        } else if (index == 4) {
            // 服务反馈
            return "customerServe/customerServeBack";
        } else if (index == 5) {
            // 服务反馈
            return "customerServe/customerServeArchive";
        } else {
            AssertUtil.isTrue(true, "非法页面跳转");
        }
        return null;
    }

}

}

/**
 * 销售机会控制层
 *
 * @version 1.0
 */
@Controller
@RequestMapping("/saleChance")
public class SaleChanceController extends BaseController {

    private Logger logger = LoggerFactory.getLogger(SaleChanceController.class);

    @Autowired
    private SaleChanceService saleChanceService;

            // 存放到session中
            request.getSession().setAttribute("permissions", permissions);
        }
        request.getSession().setAttribute("user", user);
        return "main";
    }

}

public class CookieUtil {

	/**
	 * 设置Cookie
	 * @param key Cookie名称
	 * @param value Cookie Value
	 * @param domain
	 * @param response
	 */
	public static void setCookie(String key, String value, String domain,
			HttpServletResponse response) {
		try {
			value = URLEncoder.encode(value, "UTF-8");
			if (StringUtils.isNotBlank(value)) {
                value = value.replaceAll("\\+", "%20");
			}
			Cookie cookie = new Cookie(key, value);
			cookie.setMaxAge(-1);
			cookie.setPath("/");
			cookie.setDomain(domain);
			response.addCookie(cookie);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 设置Cookie
	 * @param key Cookie名称
	 * @param value Cookie Value
    @GetMapping("/toOrderDetailPage")
    public String toOrderDetailPage(@RequestParam("id") Integer id, Model model) {
        // 查询订单信息
        model.addAttribute("customer", customerOrderService.findCustomerOrderById(id));
        model.addAttribute("sum", orderDetailService.findSum(id));
        return "customerOrder/orderDetail";
    }

}

/**
 * 权限拦截处理器
 *
 * @version 1.0
 */
@Component
@Aspect
public class PermissionHandler {

    @Autowired
    HttpSession session;

    /**
     * 权限控制
     */
    @Around("@annotation(com.wuhunyu.annotation.RequestCode)")
    public void permissionHandler(ProceedingJoinPoint joinPoint) throws Throwable {
        List<String> permissions = (List<String>) session.getAttribute("permissions");
        System.out.println("permissions:"+permissions);
        if (permissions == null || permissions.size() == 0) {
            // 抛出没有权限的异常
            throw new AuthException();
        } else {
            // 获取注解上的授权码
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            RequestCode requestCode = signature.getMethod().getDeclaredAnnotation(RequestCode.class);
     * 新增客户信息
     * @param customer
     * @return
     */
    @PostMapping("/addCustomer")
    @ResponseBody
    public ResultInfo addCustomer(Customer customer) {
        customerService.addCustomer(customer);
        resultInfo.setAll(200, "添加客户信息成功", null);
        return resultInfo;
    }

    /**
     * 修改客户信息
     * @param customer
     * @return
     */
    @PostMapping("/updateCustomer")
    @ResponseBody
    public ResultInfo updateCustomer(Customer customer) {
        customerService.updateCustomer(customer);
        resultInfo.setAll(200, "更新客户信息成功", null);
        return resultInfo;
    }

    /**
     * 批量删除客户信息
     * @param ids
     * @return
     */
    @PostMapping("/deleteCustomer")
    @ResponseBody
    public ResultInfo deleteCustomer(@RequestParam("ids") Integer[] ids) {
        customerService.deleteCustomerByIds(ids);
        resultInfo.setAll(200, "删除客户信息成功", null);
        return resultInfo;
    }

    /**
     * 查询所有客户级别
     * @return
     */
    @GetMapping("/getLevels")
    @ResponseBody
    public List<String> findLevels() {
        return customerService.findLevels();
    }

    /**

    /**
     * 新增/修改公用页面
     * @param roleId
     * @return
     */
    @GetMapping("/toAddAndUpdatePage")
    public String toAddAndUpdatePage(@Nullable Integer roleId, Model model) {
        // 修改
        if (roleId != null) {
            Role role = roleService.selectByPrimaryKey(roleId);
            AssertUtil.isTrue(role == null, "角色不存在");
            model.addAttribute("role", role);
        }
        return "role/addAndUpdateRole";
    }

    /**
     * 新增角色
     * @param role
     * @return
     */
    @RequestCode("601001")
    @PostMapping("/addRole")
    @ResponseBody
    public ResultInfo addRole(Role role) {
        roleService.addRole(role);
        resultInfo.setAll(200, "新增角色成功", null);
        return resultInfo;
    }

    /**
     * 修改角色信息
     * @param role
     * @return
     */
    @RequestCode("601003")
    @PostMapping("/updateRole")
    @ResponseBody
    public ResultInfo updateRole(Role role) {
        roleService.updateRole(role);
        resultInfo.setAll(200, "修改角色成功", null);
        return resultInfo;
    }

    /**
     * 批量删除角色
     * @param ids
     * @return
     */
    @RequestCode("601004")
    @PostMapping("/deleteRole")
    @ResponseBody
    public ResultInfo updateRole(@RequestParam("ids") Integer[] ids) {
        dataDicService.updateDic(dataDic);
        resultInfo.setAll(200, "字典数据修改成功", null);
        return resultInfo;
    }

    @PostMapping("/deleteDicById")
    @ResponseBody
    public ResultInfo deleteDicById(@RequestParam("id") Integer id) {
        dataDicService.deleteDicById(id);
        resultInfo.setAll(200, "字典数据删除成功", null);
        return resultInfo;
    }

    @GetMapping("/toAddAndUpdatePage")
    public String toAddAndUpdate(@Nullable Integer id, Model model) {
        // 修改
        if (id != null) {
            model.addAttribute("dic", dataDicService.selectDataDicById(id));
        }
        // 新增
        return "dic/addAndUpdate";
    }

}

    private ResultInfo resultInfo;

    /**
     * 根据流失客户id查询流失客户详情信息
     * @param lossId
     * @return
     */
    @GetMapping("/customerReprieveList")
    @ResponseBody
    public Map<String, Object> findCustomerReprieveByLossId(@RequestParam("lossId") Integer lossId) {
        return customerReprieveService.findCustomerReprieveByLossId(lossId);
    }

    /**
     * 添加客户流失信息
     * @param customerReprieve
     * @return
     */
    @PostMapping("addCustomerReprieve")
    @ResponseBody
    public ResultInfo addCustomerReprieve(CustomerReprieve customerReprieve) {
        customerReprieveService.addCustomerReprieve(customerReprieve);
        resultInfo.setAll(200, "添加客户流失信息成功", null);
        return resultInfo;
    }

    /**
     * 更新客户流失信息
     * @param customerReprieve
     * @return
     */
    @PostMapping("updateCustomerReprieve")
    @ResponseBody
    public ResultInfo updateCustomerReprieve(CustomerReprieve customerReprieve) {
        customerReprieveService.updateCustomerReprieve(customerReprieve);
        resultInfo.setAll(200, "更新客户流失信息成功", null);
        return resultInfo;
    }

    /**
     * 删除客户流失信息
     * @param ids
     * @return
     */
    @PostMapping("deleteCustomerReprieve")
    @ResponseBody
    public ResultInfo deleteCustomerReprieve(@RequestParam("ids") Integer[] ids) {
        customerReprieveService.deleteCustomerReprieveByIds(ids);
    }

    @GetMapping("/toCountCustomerMakePage")
    public String toCountCustomerMakePage() {
        return "customerCount/countCustomerMake";
    }

    @GetMapping("/countCustomerMake")
    @ResponseBody
    public ResultInfo countCustomerMake() {
        resultInfo.setAll(200, "查询客户组成信息成功", customerCountService.countCustomerMake());
        return resultInfo;
    }

    @GetMapping("/toCountCustomerLossPage")
    public String toCountCustomerLossPage() {
        return "customerCount/customerCountLoss";
    }

    @GetMapping("/countCustomerLoss")
    @ResponseBody
    public ResultInfo countCustomerLoss(CustomerLossQuery customerLossQuery) {
        resultInfo.setAll(200, "查询客户流失信息成功", customerCountService.countCustomerLoss(customerLossQuery));
        return resultInfo;
    }

}

 * @version 1.0
 */
@Controller
@RequestMapping("/customerCount")
public class CustomerCountController extends BaseController {

    @Autowired
    private ResultInfo resultInfo;

    @Autowired
    private CustomerCountService customerCountService;

    @GetMapping("/toCustomerContributionPage")
    public String toCustomerContributionPage() {
        return "customerCount/customerCount";
    }

    @GetMapping("/countCustomerContribution")
    @ResponseBody
    public Map<String, Object> countCustomerContribution(CustomerContributionQuery customerContributionQuery) {
        return customerCountService.countCustomerContribution(customerContributionQuery);
    }

    @GetMapping("/toCountCustomerMakePage")
    public String toCountCustomerMakePage() {
        return "customerCount/countCustomerMake";
    }

    @GetMapping("/countCustomerMake")
    @ResponseBody
    public ResultInfo countCustomerMake() {
        resultInfo.setAll(200, "查询客户组成信息成功", customerCountService.countCustomerMake());
        return resultInfo;
    }

    @GetMapping("/toCountCustomerLossPage")
    public String toCountCustomerLossPage() {
        return "customerCount/customerCountLoss";
    }

    @GetMapping("/countCustomerLoss")
    @ResponseBody
    public ResultInfo countCustomerLoss(CustomerLossQuery customerLossQuery) {
        resultInfo.setAll(200, "查询客户流失信息成功", customerCountService.countCustomerLoss(customerLossQuery));
        return resultInfo;
    }

}
    @GetMapping("/toAddAndUpdatePage")
    public String toAddAndUpdatePage(@RequestParam("saleChanceId") Integer saleChanceId,@Nullable Integer id , Model model) {
        // 封装销售机会id
        model.addAttribute("saleChanceId", saleChanceId);
        // 如果id不为空,则表示需要跳转到计划向修改页面
        if (id != null) {
            CusDevPlan cusDevPlan = cusDevPlanService.selectByPrimaryKey(id);
            AssertUtil.isTrue(cusDevPlan == null, "查询的计划项数据不存在");
            model.addAttribute("cusDevPlan", cusDevPlan);
        }
        return "cusDevPlan/addAndUpdate";
    }

}

/**
 * 全局异常处理类
 *
 * @version 1.0
 */
@Component
public class GlobalExceptionHandler implements HandlerExceptionResolver {

    private Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    @Autowired
    private ResultInfo resultInfo;

    private CustomerReprieveService customerReprieveService;

    @Autowired
    private ResultInfo resultInfo;

    /**
     * 根据流失客户id查询流失客户详情信息
     * @param lossId
     * @return
     */
    @GetMapping("/customerReprieveList")
    @ResponseBody
    public Map<String, Object> findCustomerReprieveByLossId(@RequestParam("lossId") Integer lossId) {
        return customerReprieveService.findCustomerReprieveByLossId(lossId);
    }

    /**
     * 添加客户流失信息
     * @param customerReprieve
     * @return
     */
    @PostMapping("addCustomerReprieve")
    @ResponseBody
    public ResultInfo addCustomerReprieve(CustomerReprieve customerReprieve) {
        customerReprieveService.addCustomerReprieve(customerReprieve);
        resultInfo.setAll(200, "添加客户流失信息成功", null);
        return resultInfo;
    }

    /**
     * 更新客户流失信息
     * @param customerReprieve
     * @return
     */
    @PostMapping("updateCustomerReprieve")
    @ResponseBody
    public ResultInfo updateCustomerReprieve(CustomerReprieve customerReprieve) {
        customerReprieveService.updateCustomerReprieve(customerReprieve);
        resultInfo.setAll(200, "更新客户流失信息成功", null);
        return resultInfo;
    }

    /**
     * 删除客户流失信息
     * @param ids
     * @return
     */
    @PostMapping("deleteCustomerReprieve")
    @ResponseBody
    public ResultInfo deleteCustomerReprieve(@RequestParam("ids") Integer[] ids) {
        customerReprieveService.deleteCustomerReprieveByIds(ids);
        resultInfo.setAll(200, "删除客户流失信息成功", null);
        return resultInfo;
    }
    @ResponseBody
    public ResultInfo getAssignMan() {
        List<Map<String, Object>> assignMans = saleChanceService.getAssignMan();
        logger.info("assignMans={}",assignMans);
        AssertUtil.isTrue(assignMans == null, "获取指派人信息失败");
        AssertUtil.isTrue(assignMans.size() == 0, "没有可获取的指派人信息");
        resultInfo.setAll(200, "获取指派人成功", assignMans);
        return resultInfo;
    }

    /**
     * 批量删除销售机会记录
     * @return
     */
    @PostMapping("/deleteSaleChance")
    @ResponseBody
    public ResultInfo deleteSaleChance(@RequestParam("ids") Integer[] ids) {
        System.out.println("ids="+ids);
        saleChanceService.deleteSaleChance(ids);
        resultInfo.setAll(200, "删除成功", null);
        return resultInfo;
    }

}

/**
 * 菜单资源管理控制器
 *
 * @version 1.0
 */
@Controller
@RequestMapping("/module")
        // 若存在cookie,则自动填充登录用户名
        String userName = CookieUtil.getCookieValue(request, "userName");
        String password = CookieUtil.getCookieValue(request, "password");
        if (!StringUtils.isBlank(userName)) {
            model.addAttribute("userName", userName);
        }
        if (!StringUtils.isBlank(password)) {
            model.addAttribute("password", password);
        }
        return "index";
    }

    /**
     * 系统欢迎页
     * @return
     */
    @GetMapping("/welcome")
    public String welcome() {
        return "welcome";
    }

    /**
     * 后端管理主页面
     * @return
     */
    @GetMapping({"/","/main"})
    public String main(HttpServletRequest request) {
        // 获取cookie中的userId
        int userId = LoginUserUtil.releaseUserIdFromCookie(request);
        User user = new User();
        if (userId == -1) {
            user.setUserName("游客");
        } else {
            // 根据userId查询userName
            user = userService.selectByPrimaryKey(userId);
            // 获取权限码
            List<String> permissions = permissionService.findAclValueByUserId(userId);
            // 存放到session中
            request.getSession().setAttribute("permissions", permissions);
        }
        request.getSession().setAttribute("user", user);
        return "main";
    }

}

请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
需求概述 1.1.1 坐席(用户)登录系统,根据用户的角色和权限,得到相应功能 1.1.2 客户电话呼入,坐席定位客户信息(未查找到),如果客户为新客户,首先增加新客户,针对该客户进行业务咨询或者订单预定请求处理,为客户提供个性化服务。 1.1.3 客户电话呼入,坐席定位大客户信息(查找到),针对客户进行业务咨询或者订单预定请求处理,为客户提供个性化服务。 1.1.4 根据客户请求坐席进行订单管理: 订单受理:生成订单(含客户信息、用户信息、订单信息、产品等) 订单查询:根据客户要求进行订单查询,包括订单状态等查询; 订单处理:根据客户请求,进行订单修改,包括订单信息修改,订单 产品的增加、修改及删除等; 1.1.5 坐席对产品进行管理: 产品查询:订单受理及处理中,选择查询产品; 产品增加:增加新产品信息; 产品修改:修改产品规格及状态信息; 1.1.6 根据订单确认需要,坐席查询订单列表,生成电话回呼列表( CallBack List),准备进行电话回呼及电话营销。 1.1.7 根据公司新产品市场推广需要,通过对客户资料的挖掘,筛选电话营销的客户群,批量生成电话营销列表( CallBack List),准备进行电话营销。 1.1.8 外呼坐席(用户)拥有电话营销角色及权限,进入电话回呼列表页面,选择相应的外呼任务,针对客户进行个性化的营销活动,如果客户接受则下订单,并且记录营销结果。 1.1.9 统计报表:生成座席订单业务量统计 、座席产品销售情况统计 、产品销售情况统计、外呼情况统计等报表(暂不实现); 主要需求环节: 坐席登录系统——〉客户电话打入——〉坐席响应服务——〉 坐席定位客户信息(客户管理)——〉客户下定单(订单管 理)——〉选择订购产品(产品管理)——〉订单处理 (订 单管理)——〉生成电话营销信息 ——〉坐席电话营销 —— 〉营销成功生成订单 ——〉 记录电话营销结果 ——〉 生成统计报表(暂不实现)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值