CRM客户管理系统
一、項目的簡單描述
1.什么是CRM
CRM系統即客戶關系管理系統,是指企業用CRM技術來管理與客戶之間的關系。他的目標是縮減銷售周期和銷售成本,增加收入,尋找擴展業務所需的新的市場和渠道以及提高客戶的價值,滿意度,營利性和忠實度。CRM項目的實施可以分為3步,即應用業務集成。業務詩句分析和決策執行。
2.CRM開發環境和技術
<1> 項目業務介紹
客戶關系管理是指企業為提高核心競爭力,利用相應的技術信息以及互聯網技術協調企業與顧客間在消費,營銷和服務上的交互,從而提升其管理方式,向客戶提供創新式的個性化的客戶交互和服務的過程,其最終目標是吸引新客戶,保留老客戶以及將已有客戶轉為忠實客戶,增加市場
<2>開發環境
項目名稱:CRM客戶管理系統
系統作用:公司客戶關系管理,潛在客戶開發及訂單合同管理
開發環境:IDEA Windows10 jdk1.8 Maven Mysql8
需要的工具:postman fiddler抓包工具或瀏覽器開發者工具
二、項目模塊分析
1. 基礎模塊
包含系統基本的用戶登錄,退出,記住我,密碼修改等基本操作。
2. 營銷管理
營銷機會管理 :企業客戶的質詢需求所建立的信息錄入功能,方便銷售人員進行后續的客戶需求跟
蹤。
3. 客戶管理
客戶信息管理 :Crm 系統中完整記錄客戶信息來源的數據、企業與客戶交往、客戶訂單查詢等信息錄
入功能,方便企業與客戶進行相應的信息交流與后續合作。
客戶流失管理 :Crm 通過一定規則機制所定義的流失客戶(無效客戶),通過該規則可以有效管理客
戶信息資源,提高營銷開發的效率。
4. 服務管理
服務管理是針對客戶而開發的功能,針對客戶要求,Crm 提供客戶相應的信息質詢,反饋與投訴功
能,提高企業對于客戶的服務質量。
營銷開發計劃 :開發計劃是根據營銷機會而來,對于企業質詢的客戶,會有相應的銷售人員對于該客戶進行具 體的溝通交流,此時對于整個 Crm 系統而言,通過營銷開發計劃來進行相應的信息管理,提高客戶的購買企 業產品的可能性。
5. 數據報表
Crm 提供的數據報表功能能夠幫助企業了解客戶整體分布,了解客戶開發結果整體信息,從而幫助企
業整體調整客戶開發計劃,提高企業的在市場中的競爭力度。
6. 系統管理
系統管理包含常量字典維護工作,以及權限管理模塊,Crm 權限管理是基于角色的一種權限控制,基
于 RBAC 實現基于角色的權限控制,通過不同角色的用戶登錄該系統后展示系統不同的操作功能,從而
達到對不同角色完成不同操作功能。
三、環境搭建
1.創建SpringBoot項目,導入依賴(見源代碼)
2.在src/main/resources 目錄下新建 application.yml 配置文件
3.新建 org.example.crm.controller 包,添加系統登錄,主頁面轉發代碼 。
4.添加靜態資源:在 src/main/resources 目錄下新建 public 目錄,存放系統相關靜態資源文件,拷貝靜態文件內容到
public 目錄。
5.添加視圖模板:在 src/main/resources 目錄下新建 views 目錄,添加 index.ftl、main.ftl 等文件。 (具體視圖文件詳見
相關目錄)
6.添加啟動類:在 org.example.crm 包下新建 Starter.java 。
7.添加Base包:主要用戶對Controller,Service Dao層的統一控制,BaseQuery用于控制按條件搜索的對象,ResultInfo是后端返回的對象的統一封裝
8.準備MyBatis代碼統一生成工具(generatorConfig.xml)
9.導入工具類,主要有:根據Cookie獲取作用域,登錄成功返回userIdStr加密,Md5協議加密,判斷電話號碼的格式,userID加解密等
四、項目的正式開發
用戶管理
1.用戶登錄
實現思路
/** * 用戶登錄 * 1. 驗證參數 * 姓名 非空判斷 * 密碼 非空判斷 * 2. 根據用戶名,查詢用戶對象 * 3. 判斷用戶是否存在 * 用戶對象為空,記錄不存在,方法結束 * 4. 用戶對象不為空 * 用戶存在,校驗密碼 * 密碼不正確,方法結束 * 5. 密碼正確 * 用戶登錄成功,返回用戶的相關信息 (定義UserModel類,返回用戶某些信息) */2.全局統一的異常處理及非法請求的攔截
<1> 統一的異常處理
全局異常實現思路:
控制層的方法返回的內容兩種情況
全局異常攔截器的實現,簡化了try-catch代碼
實現 HandlerExceptionResolver 接口 ,處理應用程序異常信息
<2>非法請求攔截
對于后端菜單資源,這里要求用戶必須進行登錄來保護 web 資源的安全性,此時引入非法請求攔截功
能。
實現思路:
判斷用戶是否是登錄狀態
獲取Cookie對象,解析用戶ID的值
如果用戶ID不為空,且在數據庫中存在對應的用戶記錄,表示請求合法
否則,請求不合法,進行攔截,重定向到登錄頁面
定義攔截器:在新建 interceptors 包,創建 NoLoginInterceptor 類,并繼承 HandlerInterceptorAdapter 適配器,
實現攔截器功能。
3.記住我功能
記住我功能核心在于當用戶上次登錄時如果點擊了記住我,下次在重新打開瀏覽器時可以不用選擇登
錄,此時可以借助攔截器 + cookie 來實現,當用戶在登錄時,如果用戶點擊了記住我功能,默認設置
cookie存儲時間為7天即可。
4.密碼修改功能
實現思路
/** * 用戶密碼修改 * 1. 參數校驗 * userId 非空 用戶對象必須存在 * oldPassword 非空 與數據庫中密文密碼保持一致 * newPassword 非空 與原始密碼不能相同 * confirmPassword 非空 與新密碼保持一致 * 2. 設置用戶新密碼 * 新密碼進行加密處理 * 3. 執行更新操作 * 受影響的行數小于1,則表示修改失敗 */5.退出功能
實現思路
找到 “退出登錄” 的元素,并綁定點擊事件。當用戶點擊退出時,清空cookie信息
在 main.js 中,通過類選擇器綁定元素的點擊事件
/** * 用戶退出 * 刪除cookie */ $(".login-out").click(function () { // 刪除 cookie $.removeCookie("userIdStr", {domain:"localhost",path:"/crm"}); $.removeCookie("userName", {domain:"localhost",path:"/crm"}); $.removeCookie("trueName", {domain:"localhost",path:"/crm"}); // 跳轉到登錄頁面 (父窗口跳轉) window.parent.location.href = ctx + "/index"; });營銷機會管理功能實現(CRUD操作)
1.營銷機會數據添加
實現思路
/** * 營銷機會數據添加 * 1.參數校驗 * customerName:非空 * linkMan:非空 * linkPhone:非空 11位手機號 * 2.設置相關參數默認值 * state:默認未分配 如果選擇分配人 state 為已分配 * assignTime:如果 如果選擇分配人 時間為當前系統時間 * devResult:默認未開發 如果選擇分配人devResult為開發中 0-未開發 1-開發中 2-開發成功 3-開發失敗 * isValid:默認有效數據(1-有效 0-無效) * createDate updateDate:默認當前系統時間 * 3.執行添加 判斷結果 */效果圖
2.營銷機會數據查詢
效果圖
3.營銷機會數據更新
實現思路
/** * 營銷機會數據更新 * 1.參數校驗 * id:記錄必須存在 * customerName:非空 * linkMan:非空 * linkPhone:非空,11位手機號 * 2. 設置相關參數值 3.4.1.2. 核心代碼 SaleChanceService.java * updateDate:系統當前時間 * 原始記錄 未分配 修改后改為已分配(由分配人決定) * state 0->1 * assginTime 系統當前時間 * devResult 0-->1 * 原始記錄 已分配 修改后 為未分配 * state 1-->0 * assignTime 待定 null * devResult 1-->0 * 3.執行更新 判斷結果 */效果圖
4. 營銷機會數據刪除
效果圖
CRM - 權限管理
基本概念:RBAC是基于角色的訪問控制( Role-Based Access Control )在RBAC中,權限與角色相關聯,用戶
通過扮演適當的角色從而得到這些角色的權限。這樣管理都是層級相互依賴的,權限賦予給角色,角色
又賦予用戶,這樣的權限設計很清楚,管理起來很方便。
1.用戶管理功能
用戶添加
核心思想
/*** 添加用戶* 1. 參數校驗* 用戶名 非空 唯一性* 郵箱 非空* 手機號 非空 格式合法* 2. 設置默認參數* isValid 1* creteDate 當前時間* updateDate 當前時間* userPwd 123456 -> md5加密* 3. 執行添加,判斷結果 */效果圖
- UserController.java
- UserService.java
用戶更新
核心思想
/** * 更新用戶 * 1. 參數校驗 * id 非空 記錄必須存在 * 用戶名 非空 唯一性 * email 非空 * 手機號 非空 格式合法 * 2. 設置默認參數 * updateDate * 3. 執行更新,判斷結果 * @param user */效果圖
用戶刪除
效果圖
用戶角色關聯
效果圖
2.角色權限功能
當完成角色權限添加功能后,下一步就是對角色操作的資源進行認證操作,這里對于認證包含兩塊:
- 菜單級別顯示控制
- 后端方法訪問控制
查詢出改用戶所擁有的角色,然后根據角色查詢出擁有的權限碼,具體實現如下:
@RequestMapping("main")public String main(HttpServletRequest request) {//通過獲取cookie用戶IDInteger userId = LoginUserUtil.releaseUserIdFromCookie(request);//查詢用戶對象,設置session作用域User user = userService.selectByPrimaryKey(userId);request.getSession().setAttribute("user", user);//通過當前登錄用戶ID,查詢當前登錄用戶擁有的資源列表(查詢對應的資源授權碼)List<String> permissions = null;permissions = permissionService.queryUserHasRoleHasPermissionByUserId(userId);//將集合設置作用域中(Session作用域)request.getSession().setAttribute("permissions", permissions);return "main";}菜單級別顯示控制
系統根據登錄用戶扮演的不同角色來對登錄用戶操作的菜單進行動態控制顯示操作,這里顯示的控制使用freemarker指令+內建函數實現
前端代碼根據權限碼控制前臺
登錄scott用戶
效果圖
后端方法級別訪問控制(AOP+注解實現)
實現了菜單級別顯示控制,但最終客戶端有可能會通過瀏覽器來輸入資源地址從而越過ui界面來訪問后
端資源,所以接下來加入控制方法級別資源的訪問控制操作,這里使用aop+自定義注解實現
自定義注解類:表示資源所需的權限碼
@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented /*** 定義方法需要的對應資源的權限碼*/ public @interface RequiredPermission {//權限碼String code() default ""; }定義aop切面類 攔截指定注解標注的方法:
@Component @Aspect public class PermissionProxy {@Resourceprivate HttpSession session;/*** 切面會攔截指定包下的指定注解* 攔截com.xxxx.crm.annoation的RequiredPermission注解** @param pjp* @return java.lang.Object*/@Around(value = "@annotation(org.example.crm.annotation.RequiredPermission)")public Object around(ProceedingJoinPoint pjp) throws Throwable {Object result = null;// 得到當前登錄用戶擁有的權限 (session作用域)List<String> permissions = (List<String>) session.getAttribute("permissions");// 判斷用戶是否擁有權限if (null == permissions || permissions.size() < 1) {// 拋出認證異常throw new AuthException();}// 得到對應的目標MethodSignature methodSignature = (MethodSignature) pjp.getSignature();// 得到方法上的注解RequiredPermission requiredPermission = methodSignature.getMethod().getDeclaredAnnotation(RequiredPermission.class);// 判斷注解上對應的狀態碼if (!(permissions.contains(requiredPermission.code()))) {// 如果權限中不包含當前方法上注解指定的權限碼,則拋出異常throw new AuthException();}result = pjp.proceed();return result;} }總結
- 上一篇: Linux目录配置及应放置的内容
- 下一篇: DVbbs8.2入侵思路与总结