crm之搭建框架

PHP客户关系CRM管理系统源码 企业管理办公协同cms系统 CRM客户关系管理系统源码基于WEB的企业计算,采用PHP+MySQL进行开发,性能稳定可靠。数据存取集中控制,避免了数据泄漏的可能。采用加密数据传递参数,保护系统数据安全。多级的权限控制,完善的密码验证与登录机制更加强了系统安全性,功能强大,安装简单,使用方便,附有完整的图文安装修改教程。源码框架:Thinkphp 需要设置伪静态和运行目录。必须用服务器配置,不支持虚拟主机。后台数据库单独管理功能。 阅读详情

CRM(Customer Relationship Management)就是客户关系管理

具体是干什么的 本人就不解释啦 百度上有~~

第一步: 创建一个web项目

MyCrm

第二步:导入jar包 相应的jarN多在这就不多说啦 

这个项目是s2sh 记得吧这些包都导进来啊

第三步:数据库先整一下

怕接受不拉 还是先整一个部门表把 一步一步来 千万不要偟

create database CRM  charset utf8;

#部门信息表
CREATE TABLE `sys_user_group` (
`id` INTEGER(11) NOT NULL AUTO_INCREMENT, #编号
`remark` TEXT, #备注
`name` VARCHAR(100) DEFAULT NULL, #部门名称
`principal` VARCHAR(50) DEFAULT NULL, #部门负责人
`incumbent` VARCHAR(200) DEFAULT NULL, #部门职能
PRIMARY KEY (`id`)
)

第四步:开始开发 还是从新细分 怕乱~~

-------------------------------------------------------------------------------------------------------

(一)hibernate 打通

第一步 创建 com.crm.domain包

创建SysUserGroup类

package com.crm.domain;
/**
* 部门表的po对象
*/
public class SysUserGroup {
private Integer id;
private String remark; //备注
private String name; //部门名称
private String principal; //部门负责人
private String incumbent; //部门职能
为啦节省地方 set get 还有构造就不写啦 以后的vo也不写啦 原谅一下.

第二步:让hibernate 认识您这个类啊

创建SysUserGrop.hbm.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.crm.domain.SysUserGroup" table="sys_user_group">
<id name="id" type="integer">
<column name="id" />
<generator class="identity"></generator>
</id>
<property name="name" type="string">
<column name="name" sql-type="varchar(20)"></column>
</property>
<property name="remark" type="string">
<column name="remark" sql-type="varchar(20)"></column>
</property>
<property name="principal" type="string">
<column name="principal" sql-type="varchar(20)"></column>
</property>
<property name="incumbent" type="string">
<column name="incumbent" sql-type="varchar(200)"></column>
</property>
</class>
</hibernate-mapping>

第三步:在src创建一个hibernate.cfg.xml 不解释 代码如下

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">root</property>
<property name="hibernate.connection.url"><![CDATA[jdbc:mysql://127.0.0.1:3306/CRM?useUnicode=true&characterEncoding=UTF-8]]></property>
<property name="hibernate.connection.driver_class">
com.mysql.jdbc.Driver
</property>
<property name="hibernate.connection.autocommit">true</property>
<property name="hibernate.dialect">
org.hibernate.dialect.MySQL5Dialect
</property>
<property name="hibernate.hbm2ddl.auto">update</property>
<property name="hibernate.show_sql">true</property>
<mapping resource="com/crm/domain/SysUserGroup.hbm.xml" />
</session-factory>
</hibernate-configuration>

第四步:当然就是测试啦 不作单元测试 的程序就是垃圾~~(我老师说的 不是我说的啊 ~~~)

public class TestHibernate {
/**
* 测试hibernate是否打通
*/
@Test
public void testHibernateConf(){
Configuration configuration=new Configuration();
configuration.configure(); //从src目录下加载配置文件hibernate.cfg.xml文件
SessionFactory sessionFactory=configuration.buildSessionFactory(); //从hibernate.cfg.xml文件中sessionFactory节点中获得sessionFactory
Session session=sessionFactory.openSession(); //通过sessionFactory中的opernsession获得一个session对象
Transaction transaction=session.beginTransaction(); //通过session打开一个事物
SysUserGroup sysUserGroup=new SysUserGroup();
sysUserGroup.setName("销售部");
sysUserGroup.setPrincipal("杨天赐");
sysUserGroup.setIncumbent("销售产品");
sysUserGroup.setRemark("很有钱途的职业");
session.save(sysUserGroup); //保存对象到数据库
transaction.commit(); //提交
session.close();
}
}

如果看到数据库里面插入数据恭喜你 hibernate通啦

-------------------------------------------------------------------------------------------------------------------------------------

(二)spring 打通

第一步:当然的创建一个beans.xml文件啦

代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<!-- 1 配置注解自動掃描 -->
<context:component-scan base-package="com.crm" />
<!-- 2 暂时不写 -->
<!-- 3 配置本地化代理工程bean,这个是spring整合hibernate的入口 -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property>
</bean>
<!-- 4 创建事物管理器 aop切面 -->
<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!-- 5 配置处理事物的注解 -->
<tx:annotation-driven transaction-manager="txManager"/>
</beans>

第二步:这个也不好测试一下 还是开始整dao 层 在dao层整好以后 一起整怎么样(不管你同意不同意 我就这么整啦你能怎么我~~~)

-------------------------------------------------------------------------------------------------------------------

(二.2)dao层开发

真正的高手是什么样子的 以前我不知道 不过 冯老师让我见识到啦 真正的生命叫java 什么叫面向接口编程 什么叫代码的重用性.. 什么叫可扩展,什么叫高内聚弱耦合 不说啦 代码说话...

因为 想最基本的不就是CRUD吗 抽象一个公共(common)接口 和类 后面的 只需实现和继承即可 里面方法体不用写任何代码

第一步:ICommonDao开发 位于com.crm.dao 下

/**
*
* 创建一个共同的接口
*
* @param <T>
* 通过泛型来注入实例的对象
*/
public interface ICommonDao<T> {
public void save(T entity);

public void update(T entity);

public T findObjectById(Serializable id);

public void deleteByIds(Serializable... ids);

public void deleteAllObjects(Collection<T> entities);

public List<T> findObjectsByConditionWithNoPage(String whereHql,
Object[] params, LinkedHashMap<String, String> orderby);
}

第二步:创建CommonDaoImpl  位于com.crm.dao.impl下 代码如下 (有点多有点乱~~ 如果有心的人看到多多研究 不懂问我(QQ 1007387220))

/**
*
* 继承hibernateDaoSupport类 并且注入sessionFactory
*
* @param <T>
*/
public class CommonDaoImpl<T> extends HibernateDaoSupport implements
ICommonDao<T> {
private Class entityClass = GenericClass.getGenericClass(this.getClass());

/**
* 通过hibernateDaoSupport中的hibernateTemplate模板可以保存对象
*/
public void save(T entity) {
this.getHibernateTemplate().save(entity);
}

/**
* 因为在父类中被设置成啦final类型 所以不能覆盖但是可以从新写个方法 通过super关键在来注入 但外部的dao继承此类是
* 只需注入sessionFactory即可
*/
@Resource(name = "sessionFactory")
public void setSessionFactoryDI(SessionFactory sessionFactory) {
super.setSessionFactory(sessionFactory);
}

public void update(T entity) {
System.err.println("我看进入这里啦吗");
this.getHibernateTemplate().update(entity);
}

/**
* 通过id来查找一个对象
*/
public T findObjectById(Serializable id) {
/**
* 这里需要获得类 可是 我们在这次传递是泛型没有类怎么班那? 通过一个类来获得泛型的类啊
*
*/
if (id == null) {
throw new RuntimeException("您要查找的[" + id + "]不能为空");
}
return (T) this.getHibernateTemplate().get(entityClass, id);
}

/**
* 通过id.. 来删除
*/
public void deleteByIds(Serializable... ids) {
if (ids != null && ids.length > 0) {
for (Serializable id : ids) {
Object entity = this.getHibernateTemplate()
.get(entityClass, id);
if (entity == null) {
throw new RuntimeException("您查找的这个[" + id + "]不存在");
}
this.getHibernateTemplate().delete(entity);
}
}
}

/**
* 通过一个集合来删除 这个集合也就代表对象
*/
public void deleteAllObjects(Collection<T> entities) {
this.getHibernateTemplate().deleteAll(entities);

}

/**
* 返回一个集合 开始拼接hql语句
*/
public List<T> findObjectsByConditionWithNoPage(String whereHql,
final Object[] params, LinkedHashMap<String, String> orderby) {
// 第一: sql 语句为SELECT * FROM SysUserGroup o WHERE
String hql = "select o from " + entityClass.getSimpleName()
+ " o where 1=1";
// 第二: 在where后面动态的添加条件(这一步在service中处理 因为页面传过来的不同)
if (StringUtils.isNotBlank(whereHql)) {
hql = hql + whereHql;
}
// 第三最终极hql 要变成final 在内部类中进行处理
final String fhql = hql;
// 处理排序 order by o.name asc ,o.age desc
String orderbystr = buildOrder(orderby);
hql = hql + orderbystr;
// 通过hibernatetemplate模板中execution(hql)来返回list
List<T> list = (List<T>) this.getHibernateTemplate().execute(
new HibernateCallback() {
public Object doInHibernate(Session paramSession)
throws HibernateException, SQLException {
Query query = paramSession.createQuery(fhql);
setParams(query, params);
return query.list();
}

});
return list;
}

/**
* 设置hql语句传递过来的参数
*
* @param query
* @param params
*/
public void setParams(Query query, Object[] params) {
if (params != null && params.length > 0) {
for (int i = 0; i < params.length; i++) {
query.setParameter(i, params[i]);
}
}
}

/**
* 为什么要用map那? 从外面传过来 在这里拆分一下 然后动态组装就OK order.put("o.id","asc");
* order.put("o.name","desc"); order.put("o.age","asc");
*
* @param orderby
* @return
*/
private String buildOrder(LinkedHashMap<String, String> orderby) {
StringBuffer buf = new StringBuffer("");
if (orderby != null && orderby.isEmpty()) {
buf.append(" order by "); // 这部一定不要忘记啊
for (Map.Entry<String, String> me : orderby.entrySet()) {
buf.append(me.getKey() + " " + me.getValue() + ",");
}
buf.deleteCharAt(buf.length() - 1);// 去掉最后一个的","号
}
return buf.toString();
}
}

大家可能有点郁闷 写这么多代码还说 高手~~ 还说方法体不用写代码 牛b吹打了把  不解释 走着瞧~~

现在公共的搞定啦 开始创建单个的部门dao 和部门实现类把

第三步:创建SysUserGroupDao 部门dao 

public interface ISysUserGroupDao extends ICommonDao<SysUserGroup>{
/**
* 这个静态属性是方便注入用的 在这个接口中什么都不需要写..
*/
public final static String SERVICE_NAME="com.crm.dao.impl.SysUserGroupDaoImpl";
}

第四步:SysUserGroupDaoImpl

/**
* 在这个类中也是什么都不要写 只需要继承CommonDaoImpl即可
* 全部通用的方法全部在CommonDaoImp中实现 这个类只需要继承 不需要写任何方法体
*/
@Repository(ISysUserGroupDao.SERVICE_NAME)
public class SysUserGroupDaoImpl extends CommonDaoImpl<SysUserGroup> implements ISysUserGroupDao {
}

说来这么多开始测试一下dao增删改查 ..

/**
* 测试保存
*/
@Test
public void testSave() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
"beans.xml");
ISysUserGroupDao sysUserGroupDao = (ISysUserGroupDao) applicationContext
.getBean(ISysUserGroupDao.SERVICE_NAME);

SysUserGroup sysUserGroup = new SysUserGroup();
sysUserGroup.setName("市場部");
sysUserGroup.setPrincipal("張鯤鵬");
sysUserGroup.setIncumbent("調研");
sysUserGroup.setRemark("很雙的职业");

sysUserGroupDao.save(sysUserGroup);
}
/**
* 测试更新
*/
@Test
public void testUpdate(){
ISysUserGroupDao sysUserGroupDao=(ISysUserGroupDao) ServiceProvinder.getService(ISysUserGroupDao.SERVICE_NAME);
SysUserGroup sysUserGroup=new SysUserGroup();
sysUserGroup.setId(2);
sysUserGroup.setName("市場部");
sysUserGroup.setPrincipal("田京辉");
sysUserGroup.setIncumbent("調研");
sysUserGroup.setRemark("很雙的职业");
sysUserGroupDao.update(sysUserGroup);
}
/**
* 通过id查找这个部门
*/
@Test
public void findSysUserGroupById(){
ISysUserGroupDao sysUserGroupDao=(ISysUserGroupDao) ServiceProvinder.getService(ISysUserGroupDao.SERVICE_NAME);
//在这里声明为Serializable 是为啦通用性..
Serializable id=1;
SysUserGroup sysUserGroup=sysUserGroupDao.findObjectById(id);
System.err.println(sysUserGroup.getName());

}
/**
* 删除一个或者多个
* 封装成一个数组ids
*/
@Test
public void deleteByIds(){
ISysUserGroupDao sysUserGroupDao=(ISysUserGroupDao) ServiceProvinder.getService(ISysUserGroupDao.SERVICE_NAME);
Serializable[] ids={4,5};
sysUserGroupDao.deleteByIds(ids);
}
/**
* 有时候有需求删除一个集合deleteCollections
*/
@Test
public void deleteCollections(){
ISysUserGroupDao sysUserGroupDao=(ISysUserGroupDao) ServiceProvinder.getService(ISysUserGroupDao.SERVICE_NAME);
List<SysUserGroup> list=new ArrayList<SysUserGroup>();
SysUserGroup s1 = new SysUserGroup();
s1.setId(12);
list.add(s1);
SysUserGroup s2 = new SysUserGroup();
s2.setId(13);
list.add(s2);
sysUserGroupDao.deleteAllObjects(list);
 }
}

如果你都能搞定 这就代码打通啦spring

----------------------------------------------------------------------------

(三)打通页面 struts2 这里采用与spring分离的方式整.. 避免过度的依赖..

不多说代码整~~

在打通页面之前 顺便把服务层也整一下把 

第一步创建SysUserGroupService

public interface ISysUserGroupService {
public final static String SERVICE_NAME="com.crm.service.impl.SysUserGroupServiceImpl";
public void saveSysUserGroup(SysUserGroup sysUserGroup);
public List<SysUserGroup> findSysUserGroups(String name, String principal);
}

第二步:创建 SysUserGroupServiceImpl 这里用到很多花招 用心的人捉摸一下 为什么要再service层来组织hql而不是在dao(不管你们知道不知道,反正我知道啦~~)

@Service(ISysUserGroupService.SERVICE_NAME)
@Transactional(readOnly = true)
public class SysUserGroupServiceImpl implements ISysUserGroupService {
@Resource(name = ISysUserGroupDao.SERVICE_NAME)
private ISysUserGroupDao sysUserGroupDao;

@Transactional(isolation=Isolation.DEFAULT,propagation=Propagation.REQUIRED,readOnly=false)
public void saveSysUserGroup(SysUserGroup sysUserGroup) {
this.sysUserGroupDao.save(sysUserGroup);
}

public List<SysUserGroup> findSysUserGroups(String name, String principal) {
/**
* 为了不打扰上层 先模拟一下页面调用啦它
* 假如页面传过来的是 name=销售部 principal=杨天赐
* sql语句应该是这样的吧
* SELECT * FROM sys_user_group o WHERE o.name LIKE '%销售部%' AND o.principal='杨天赐' ORDER BY o.id
* hql为(一般服务层不能出来sql语句 但是可以出现hql语句)
* SELECT * FROM SysUserGroup o WHERE o.name LIKE '%销售部%' AND o.principal='杨天赐'
ORDER BY o.id asc,o.name desc
*/
//第一步组织Hql语句
String whereHql="";
//把从页面传过来的条件进行封装
List paramsList=new ArrayList();
if(StringUtils.isNotBlank(name)){
whereHql=" and o.name like ?";
paramsList.add("%"+name+"%");
}
if(StringUtils.isNotBlank(principal)){
whereHql=whereHql+" and o.principal = ?";
paramsList.add(principal);
}
Object [] params=paramsList.toArray();
//第二步: 组织排序
LinkedHashMap<String,String> orderby=new LinkedHashMap<String, String>();
orderby.put("o.id","asc");//到以后这个也是动态变化的 现在为了..先这样写
orderby.put("o.name", "desc");
List<SysUserGroup> list=sysUserGroupDao.findObjectsByConditionWithNoPage(whereHql, params, orderby);
return list;
}
}

好啦 还是测试一下把 怕~~ 冯老师说我不专业~~

public class TestSysUserGroupService {
@Test
public void testSave() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
"beans.xml");
ISysUserGroupService sysUserGroupService = (ISysUserGroupService) applicationContext
.getBean(ISysUserGroupService.SERVICE_NAME);
SysUserGroup sysUserGroup = new SysUserGroup();
sysUserGroup.setName("人力资源部");
sysUserGroup.setPrincipal("張保佳");
sysUserGroup.setIncumbent("负责人事");
sysUserGroup.setRemark("很清闲的职业");
sysUserGroupService.saveSysUserGroup(sysUserGroup);
}

@Test
public void findObjectsByConditionWithNoPage() {
ISysUserGroupService sysUserGroupService = (ISysUserGroupService) ServiceProvinder
.getService(ISysUserGroupService.SERVICE_NAME);

// 获取部门名称
String name = "销售部";

// 获取部门负责人
String principal = "杨天赐";

@SuppressWarnings("unused")
List<SysUserGroup> list = sysUserGroupService.findSysUserGroups(name,
principal);
System.err.println(list);
/*
* 搞定 select sysusergro0_.id as id0_, sysusergro0_.name as name0_,
* sysusergro0_.remark as remark0_, sysusergro0_.principal as
* principal0_, sysusergro0_.incumbent as incumbent0_ from
* sys_user_group sysusergro0_ where 1=1 and (sysusergro0_.name like ?)
* and sysusergro0_.principal=?
  */
}
}

--------------------------------------------------------------------------

好啦 开始整action com.crm.web.action

第一步: 创建 SysUserGroupAction

public class SysUserGroupAction extends ActionSupport implements ModelDriven<SysUserGroupForm>{
private SysUserGroupForm sysUserGroupForm=new SysUserGroupForm();
public String save(){
System.out.println("sysUserGroupForm.getName() "+sysUserGroupForm.getName());

//实例化po对象
SysUserGroup sysUserGroup=new SysUserGroup();

//赋值vo对象的值到po中
BeanUtils.copyProperties(sysUserGroupForm, sysUserGroup);

//获取业务层的对象(本项目struts2和spring是分离的)
ISysUserGroupService sysUserGroupService = (ISysUserGroupService) ServiceProvinder.getService(ISysUserGroupService.SERVICE_NAME);
//调用业务层保存po对象
sysUserGroupService.saveSysUserGroup(sysUserGroup);
System.err.println("OVER....");
return null;
}
public SysUserGroupForm getModel() {
// TODO Auto-generated method stub
return this.sysUserGroupForm;
}
}

为啦让struts2认识还是整一个struts2.xml文件(在src下)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.1.7//EN"
"http://struts.apache.org/dtds/struts-2.1.7.dtd">
<struts>
<!-- 配置请求后缀名.do -->
<constant name="struts.action.extension" value="do"/>

<!-- 配置主题为简单主题 -->
<constant name="struts.ui.theme" value="simple"/>

<!--配置struts2的模式为开发模式-->
<constant name="struts.devMode" value="true"/>

<package name="sys" namespace="/sys" extends="struts-default">
<action name="sysUserGroupAction_*" class="com.crm.web.action.SysUserGroupAction" method="{1}">
<result name="add">/sys/group/add.jsp</result>
</action>
</package>
</struts>

第二部: 一定不要忘记在web.xml中配置过滤器啊~~

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<filter>
<filter-name>StrutsPrepareAndExecuteFilter</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>StrutsPrepareAndExecuteFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>

好啦 到底为之 strts2 打通啦 第一天也就over啦

--------------------------------------------------------------

杂碎总结一下 这里啰嗦一句

啰嗦一: 因为用的泛型 T 在里面怎么获得类那  就用到啦一个工具来 GenericClass

/**
*
*获得父类的类型
*clazz.getGenericSuperclass(); j就可用获得 一个ParameterizedType类型的类
*通过这个类的getActualTypeArguments()来获得它的真是的类型 不过这个方法返回的是个数组
*Class entityClass=(Class) type.getActualTypeArguments()[0];
*这个entityClass 就代表 父类的类型啦
*/
public class GenericClass {
public static Class getGenericClass(Class clazz){
ParameterizedType type=(ParameterizedType) clazz.getGenericSuperclass();
//type====com.crm.dao.impl.CommonDaoImpl<com.crm.domain.SysUserGroup>
Class entityClass=(Class) type.getActualTypeArguments()[0];
//entityClass===class com.crm.domain.SysUserGroup
return entityClass;
}
}

啰嗦二: 因为说要让struts2 和spring不要有过多的依赖怎么办 自己整个类 叫ServiceProvinder和ServiceProvinderCore类

public class ServiceProvinderCore {
protected ApplicationContext applicationContext;
/**
*
* @param fileName beans.xml
*/
public void load(String fileName){
applicationContext=new ClassPathXmlApplicationContext(fileName);
}
}

------------------------------------

public class ServiceProvinder {
private static ServiceProvinderCore serviceProvinderCore;
static{
System.err.println("加载啦ClassPathApplicationContext(beans.xml)");
serviceProvinderCore=new ServiceProvinderCore();
serviceProvinderCore.load("beans.xml");
}
public static Object getService(String beanName){
if(StringUtils.isBlank(beanName)){
throw new RuntimeException("您要访问的服务名称不能为空");
}
Object bean=null;
//如果spring容器中包含beanName
if(serviceProvinderCore.applicationContext.containsBean(beanName)){
System.err.println("加载啦applicationgetbean(SysUserDao)");
bean=serviceProvinderCore.applicationContext.getBean(beanName);
System.err.println(bean);
}
if(bean==null){
throw new RuntimeException("您要访问的服务名称["+beanName+"]不存在");
  }
return bean;
}

还是测试一下..

public class TestServiceProvinder {
@Test
 public void testProvinder() {
ISysUserGroupService sysUserGroupService = (ISysUserGroupService) ServiceProvinder.getService(ISysUserGroupService.SERVICE_NAME);
SysUserGroup sysUserGroup = new SysUserGroup();
sysUserGroup.setName("財務部");
sysUserGroup.setPrincipal("付小杰");
sysUserGroup.setIncumbent("负责財務");
sysUserGroup.setRemark("管錢的职业");
sysUserGroupService.saveSysUserGroup(sysUserGroup);
}
}

啰嗦三:还有一个问题 就是 vo和po的问题

package com.crm.web.form;
@SuppressWarnings("serial")
public class SysUserGroupForm implements java.io.Serializable{
private String id;
private String name;
private String remark;
private String principal;
private String incumbent;

vo 是页面的数据 po是数据库 在action中 通过copy 转移到 数据库中这样安全~~

第一天嘛 先试着把框架 打起来 后面以后慢慢整 crm这个项目挺大的 我也有很大鸭梨~~ 不过 天赐 加油~~ 没人给你打气 自己鼓励自己


从零搭建私有化CRM系统:基于若依框架的客户管理实战 客户关系管理(CRM)是企业数字化运营的基础设施,从Excel表格到完整业务系统的跨越,本质是将静态记录转化为动态流程。私有化部署让团队掌握数据主权,同时兼顾定制化需求,成为中小团队的优选。以若依框架为底座,借助其成熟的RBAC权限模型和代码生成器,可快速构建覆盖线索、客户、跟进、商机、合同回款的全链路系统。通过数据权限隔离、跟进待办驱动、销售漏斗可视化,真正实现客户资产沉淀与协同效率提升。文章聚焦一套实际自建的DeskcommCRM系统,从技术选型、核心模块设计到生产环境部署,全程分享踩坑与优化经验,为技 阅读详情

相关推荐

从零开始的SSM框架CRM系统搭建教程

SSM框架由三个著名框架组成:Spring、SpringMVC和MyBatis。Spring是一个开源的Java/Java EE全功能栈应用程序框架,它为解决企业应用开发的复杂性提供了一种轻量级和全面的解决方案。SpringMVC是Spring的一个模块,它提供了一个构建Web应用程序的模型-视图-控制器(Model-View-Controller)框架。而MyBatis则是一个持久层框架,它提供了一种在Java应用中管理和操作数据的方式。

weixin_35307279的博客 655

2023最新PHP客户关系CRM管理系统源码+企业CRM管理系统源码

3、 客户管理:我的客户、客户列表、成交客户、行业类别、预查、地区列表、客户状态、客户级别。PHP客户关系CRM管理系统源码 企业crm管理系统PHP源码下载。2、 线索管理:我的线索、线索列表、线索状态、线索来源。6、 权限管理:管理员列表、用户组列表、权限管理。1、 公海管理:公海类型、客户公海。4、 业绩订单:订单列表、我的订单。5、 系统设置:系统设置、邮箱配置。

greffg的博客 853

Selenium+unittest搭建CRM自动化测试框架实战

Web UI自动化测试是保障系统稳定性和回归效率的关键手段,其核心在于模拟真实用户操作验证业务流程。Selenium作为浏览器自动化执行器,配合Python内置的unittest标准库,能够实现用例组织、执行与断言,形成一套轻量级测试框架。工程实践中常引入Page Object模式提升维护性,通过HTMLTestRunner生成可视化报告,并结合SMTP邮件发送结果,形成闭环交付。此类框架适用于登录、增删改查等典型业务场景,尤其适合以CRM这类业务模型清晰的系统作为练手目标。本文以一套本地CRM系统为例,从

weixin_27743991的博客 159

悟空crm php 部署,悟空crm开源版本环境搭建

安装步骤JDK需要预先安装,下载后执行install.sh链接: link.硬件配置因为只有一台机器所以安装在一台机器上了|cpu内存硬盘系统8核32Gssd100Gcentos7基础软件mysql安装1.卸载mariadbrpm -qa | grep mariadbrpm -e --nodeps mariadb-libs-5.5.56-2.el7.x86_642.安装mysqlrpm -ivh ...

weixin_34229622的博客 2768

用Selenium+Unittest搭建CRM自动化回归测试框架

自动化测试是软件质量保障的核心手段,通过模拟用户在浏览器端的操作,实现回归测试的高效执行。Selenium作为主流的Web自动化工具,结合Python标准库Unittest,能构建稳定易维护的测试框架。采用页面对象模式(PO)将元素定位与业务逻辑分离,配合显式等待和数据驱动,可大幅降低脚本维护成本。利用HTMLTestRunner生成可视化报告,并通过smtplib自动发送邮件,形成完整的测试闭环。在企业级CRM系统的回归场景中,该方案能将数小时的手工验证压缩至二十分钟,并支持定时自动执行、持续集成。本文以

weixin_42635064的博客 143

Selenium+unittest实战:从零搭建CRM系统UI自动化测试框架

自动化测试是现代软件质量保障的重要环节,其中UI自动化测试尤为考验测试人员的工程能力。基于Python生态,Selenium作为浏览器自动化库,负责模拟用户操作,而unittest作为标准单元测试框架,提供用例组织与断言机制,二者结合可构建稳定可维护的自动化测试脚本。通过Page Object模式封装页面元素,配合显式等待、失败截图等实践,能有效提升测试脚本的稳定性与复用性。在CRM客户管理系统等典型后台业务场景中,覆盖登录、增删改查等核心流程,并将测试结果生成HTML测试报告,通过邮件自动发送,即可形成完

weixin_32187037的博客 283

PHP开发的CRM客户关系管理系统

面向中小企业,易于安装维护,安全便捷,支持虚拟主机空间 系统简介: 本CRM客户管理系统基于先进的CRM营销理念设计,集客户档案、销售记录、业务往来于一身,以凝聚客户关系、提升资源价值为核心,将潜在客户变为现实客户、从而提升销售量、提高用户的满意度,并增加企业竞争力。本CRM是适用于中小企业的通用型客户关系管理系统,融合了长期从事管理软件开发的丰富经验与先进技术,该系统采用领先的B/S(浏览器/服务器)操作方式,使得网络办公不受地域限制。在功能上注重实用、易用、安全、稳定。在性能方面也表现优异,使用普通

风清扬的专栏 2686

crm框架 经典

crm .net 开发框架 经典

如何搭建一个CRM系统

搭建一个客户关系管理系统 (CRM) 需要以下几个步骤: 定义需求:明确您对 CRM 系统的要求,以便确定它应该具有哪些功能和特性。 选择技术:根据您的需求,选择合适的技术平台,例如使用自主开发、购买现成软件或使用云 CRM 服务。 数据收集:收集所需的客户数据,包括客户资料、联系方式、历史交易记录等。 系统构建:根据您的需求,构建 CRM 系统的后端数据库和前端用户界面。 数据迁移:将...

weixin_35754676的博客 1629

手把手教你用支付宝密钥工具生成RSA2密钥对(含Windows/Mac操作截图)

本文详细介绍了如何使用支付宝密钥工具生成RSA2密钥对,包括Windows和Mac平台的操作步骤与截图。从工具下载、安装到密钥生成、配置支付宝平台,再到开发环境集成实战,手把手教你完成支付宝支付接口对接。特别强调密钥安全管理和最佳实践,帮助开发者避免常见安全隐患。

mongodb5scout的博客 257

postman响应体:“msg“: “请求缺失签名Sign“、 “msg“: “请求缺失时间戳“

请求标头有Sign、Timestamp,但是直接将网址复制到postman时,Headers没有自动生成这两个参数,所以运行时会报错。

m0_46862648的博客 1706

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

CRM项目-- 基于SSM框架搭建V01 这是我使用SSM框架来搭建CRM(客户管理系统)的过程,在这里记录自己学习的过程,以及踩到的一些坑,也希望能给那些和我一样刚接触这个的一些帮助。 这个项目是某个机构的一个开源课程,由于他现在并没有使用SSM框架来做,我已经过了一遍他的课了,现在就是我自己来采坑的时候了。 第一天:主要是搭建项目的一些结构,把必要的包、资源、配置文件什么的给完成,还有配置服务器看有没有问题。 1.使用maven来构建项目 在pom文件里面加入我们需要的依赖,有:springmvc,sp

weixin_41362471的博客 524

思科模拟器实战:MQTT协议实现物联网设备通信全流程解析

本文详细解析了如何在思科模拟器中利用MQTT协议实现物联网设备通信的全流程。通过搭建网络拓扑、配置MQTT Broker与客户端,并编写发布/订阅逻辑,手把手指导读者完成一个“开关控制电灯”的经典物联网场景实验,帮助零成本掌握物联网通信核心。

weixin_29294975的博客 382

(crm笔记1-1) 框架的搭建

crm(框架采用ssh) * 客户关系管理系统:管理、重要、签约等等客户 *OA管理系统 *进销存管理系统关于dao层的实现思路:1、先设计一个总的dao的接口,定义通用方法接口 2、然后构建一个实现类实现通用方法, 3、利用一个接口,继承并添加新的接口 4、写一个新的类,继承已经实现的通用的实现方法,并且实现新添加的接口的方法在搭建ssh框架的时候,需要首先用hibernate连接

灰羽 1099

Marvell 88E6390x交换芯片:从零构建No-CPU模式网络交换系统

本文详细介绍了如何为Marvell 88E6390x以太网交换芯片构建No-CPU模式网络交换系统。通过解析其核心价值与硬件准备,并手把手指导使用CodeBlocks、IMPGUI和SwitchGUI等软件工具进行配置代码编写、镜像生成与烧录,最终实现交换芯片脱离外部CPU独立工作,适用于成本敏感、空间受限的嵌入式网络设备设计。

plant的博客 484

ROS学习笔记之——无人机PID调参过程记录

For cooperaive inquiries, please visit the website:guanweipeng.com

gwpscut的博客 6829

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

这是CRM项目的第二个版本。相比于上次,这次完成的内容主要有: 1.使用ajax技术实现登录验证的局部刷新技术。登录成功,则跳转到新的页面;否则,在对应的位置显示错误的原因。 2.还要实现点"登录"或者敲回车都能发送请求。 3.使登录窗口始终都处于最顶层窗口 **一个很大的问题:**在使用springMVC的拦截器来验证用户是否登录的时候,发现拦截器一点都不起作用,里面的方法根本就执行不了,找了一下午,至今没有解决!!! 1.让用户名文本框自动获得焦点 这是为了提升用户体验,让一进入到页面就能直接输入。 /

weixin_41362471的博客 351

YOLOv11的QAT(训练感知量化)实战

本文总结了YOLO模型量化感知训练(QAT)的实践要点:QAT通过模拟量化噪声训练模型,比训练后量化(PTQ)更适合密集预测任务。关键实现包括:1)配置对称/非对称量化器;2)排除检测头量化;3)调整学习率策略并添加量化正则;4)选择困难样本校准;5)转换前稳定BN统计量。调试时需检查量化范围、数值分布和逐层突变,并注意SPP等敏感层。建议小模型使用QAT,大模型可能适得其反,且TensorRT的FP16模式可能优于INT8-QAT。量化应以功能正确为前提,避免过度优化。

as1225120794的博客 510

用若依框架从零搭建团队自用CRM系统:选型、设计、部署与踩坑实践

客户数据管理是团队业务运转和数据资产积累的核心。很多中小团队依赖Excel或免费CRM记录客户,但当业务规模扩大后,免费版在功能阉割、数据导出限制、数据主权和定制成本上的短板就会集中暴露。免费CRM与SaaS在线工具虽然开箱即用,却难以满足销售流程中的个性化需求。基于Java生态下的开源框架若依(RuoYi)自建一套私有化CRM系统,成为很多技术团队解决客户管理痛点的可行选择。若依自带用户权限、菜单管理、代码生成器等基础能力,结合Spring Boot后端与Vue前端,可以快速搭建覆盖客户生命周期、联系人、

weixin_32050773的博客 150

基于四旋翼模型的火箭型无人机视线角保持控制仿真设计

本文针对火箭型无人机的视线角保持控制问题展开研究。基于四旋翼动力学模型,通过改造设计了一种摄像头朝上安装的特殊无人机系统,用于追踪空中目标。文章详细推导了坐标系定义、运动学和动力学方程,重点分析了摄像头安装与视线几何关系,建立了目标运动模型和视线向量计算方法。通过解算期望姿态角,实现了使机体Z轴始终对准目标的控制目标。仿真结果表明,该系统能有效完成视线角保持任务,为空对空监视等应用场景提供了可行方案。~~~~~

huanghm88的专栏 142

把 MCP Server 直接装进 SAP ABAP:用 Unlimited Display Tools 打通 Agentic SDK 与 SAP ECC / S/4HANA 的最后一公里

摘要:AI与SAP集成的MCP解决方案 企业在AI集成中面临工具链复杂、数据对接繁琐的挑战。Model Context Protocol (MCP)通过标准化工具与数据暴露方式,将集成复杂度从N×M降至N+M。在SAP生态中,MCP Server for SAP直接部署于ABAP层,利用DDIC/CDS视图对接各类Agent SDK,避免中间件风险。 MCP核心包含三类对象: Tools:带元数据的可执行动作 Resources:结构化上下文数据 Prompts:可参数化提示模板 ABAP层实现MCP Se

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 685

从免费CRM到自建系统:基于RuoYi框架搭建DeskcommCRM的全过程实战

客户管理是销售团队稳定运转的基石,然而大量团队仍深陷客户数据分散、归属不清、历史记录难追溯的困境。免费CRM与私人网站的区别在哪?前者虽零门槛上手快,但数据归属、字段定制、扩展成本与迁移风险往往成为隐形成本。随着Spring Boot与Vue等开源技术栈的成熟,借助RuoYi这类低代码框架,中小企业完全能以极低成本搭建私有化部署的客户管理系统。本文从业务流程设计、核心数据表结构、权限隔离到跟进时间线等细节出发,完整还原一套自建CRM的落地过程,并分享数据迁移、团队协作、运维排障等工程实践。无论是正在调研免费

weixin_33391446的博客 108

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

我用 AI 花 2 天搭建 CRM 基础框架,再用两周死磕打磨客户信息管理功能

AI 能生成代码、画出页面,却不懂真实销售业务:客户线索流转、负责人权限隔离、批量导入导出、客户详情、跟进记录、管理员后台与普通员工个人版视图分离,这些业务细节 AI 无法自动做好。写这篇文章一方面记录开发历程,另一方面提前寻找一批潜在的中小微企业、销售团队朋友,如果你正在选型私有化 CRM、受限于市面 CRM 功能臃肿、价格太高、不想用通用 SaaS,可以持续关注我的项目。普通个人版只聚焦自己负责的客户、线索、跟进任务。✅客户信息表单:客户编号、名称、联系人、手机号、线索来源、客户阶段、负责人分配。

挨踢学霸 158

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

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

这个版本是一个全新的模块----【线索模块】,也称为**【潜在客户】**,这个模块里面有很多内容都是和市场活动模态一样的,但是我还是自己写了,可能在这里记录的时候我就只说自己完成了哪些内容,至于具体的代码什么的就不放了。 这个全新的模态还是有很多新东西可以玩的。接下来就来看吧~ 1.数据字典的使用(cache缓存机制) 数据字典:指的是在应用程序中,做表单元素选择内容用的相关的数据。比如:下拉框,单选框,复选框。这里里面的内容,使用数据字典进行完成比较好,这样就不必每次加载的时候和数据库连接取数据,直接从缓

weixin_41362471的博客 476

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

零代码搭建 vs 成品CRM:中小企业选型的务实分析框架

零代码搭建CRM适合有IT能力、业务高度非标、愿意投入大量时间自建的企业;成品励拓云CRM适合追求快速落地、高性价比、功能成熟、可能需要私有化部署的中小微企业。对于绝大多数5-50人、没有专职IT的中小微企业,成品励拓云CRM是更务实的选择——用更低的总拥有成本、更短的落地时间、更成熟的功能,实现客户管理数字化。零代码平台的灵活性确实诱人,但“能建”和“建好、用好、维护好”之间,隔着巨大的人力和经验鸿沟。

COLORl的博客 160

从零搭建CRM系统

Server URL一定要改为https://start.aliyun.com,不然下面Java版本选不了java8这个,点击Next进入下一步,选择工程所需的依赖。在主工程处单击右键,选择new 》module,点击后弹出new Module弹出,在Name处输入自己的模块名。搭建一个适合自己的CRM系统,以供将来完成快速二开。点击Create创建了一个基本的Spring Boot工程。至此,一个Spring Boot的基本工程搭建完成。点击Create后,创建了主工程的一个模块。

HooliJia的专栏 929
上一篇: Socket详解(转)
下一篇: crm之权限整理1
pheodor
博客等级 码龄15年 6粉丝 16原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值