聊聊这个开源项目,如何一步步火爆GitHub!

简介: 近几年悟空CRM开源项目在GitHub和码云上迅速蹿红,并获得了上千用户的关注。目前累计2,000,000下载量。社区人数达到30,000多人。在国内浩瀚的开源市场,悟空CRM在开源道路上倾注10多年的心血。

2010年初,受国外salesforce、zoho等saas供应商的影响,越来越多的企业开始投入CRM的研发。为找到属于自己的品牌方向,悟空团队以openerp(odoo)为标杆,开始了在开源道路上探索,并为之进行了近十年的投入。

2014年第一个版本发布

悟空CRM项目在2010开始启动,对于初创团队来讲,产品的研发迭代以及投入精力有限,直到2104年悟空CRM推出第一个开源CRM版本V0.0.1,当时的国内企业管理软件的开源市场并未完全成熟,再加上V0.0.1版本存在功能和技术的限制,产品发布后并没有获得大量的用户群体。

2016年继续迭代

悟空CRM在版本迭代上并没有想想的那么快,一部分研发投入开源、一部分研发投入二次开发项目,毕竟对于一个企业来讲,生存是第一要素。经过两年的12次迭代代,2016年悟空CRM版本迭代至V0.4.5,并在码云和Github上发布后,获得了上千家用户的下载和体验。V0.4.5该版本在原有的基础上做了全面升级和改造,是目前市场上使用较为稳定一个版本。

但是在这个技术日新月异的时代。node、vue、微服务、Python、AI各种技术不断兴起,悟空CRM开源提供的技术已经很难满足现有技术爱好者的需求,开源道路在国内再一次受到阻力,开源项目暂且搁置。

2019年一次新的挑战

是否继续开源?是一个很艰难的决定。毕竟开源项目要投入大量的精力。对企业的成本是不小的挑战。但是悟空CRM毕竟在开源道路上已经倾注多年的心血,开源是必将继续!

重整旗鼓!这一次在技术方面面临一个重大的调整,悟空CRM决定推出目前流行的前后端分离技术,后端采用PHP和JAVA 两种开发语言,前端采用最火爆的vue架构。两种后台开发语言架构是国内唯一尝试的,无论是PHP或者JAVA任一技术栈的开发人员都可尝试学习。

2019年做极致的开源产品

2019年4月PHP版发布了:基于TP5.0+vue+ElementUI的前后端分离CRM系统
2019年6月JAVA版发布了:基于jfinal+vue+ElementUI的前后端分离CRM系统项目

下载地址:https://gitee.com/wukongcrm

两个产品同年发布,发布后便获得的大量开源爱好者的关注和亲睐。高质量的源码、高标准的UI设计,这一次不仅仅在技术上悟空CRM投入的大量的时间和精力,在用户体验和UI上也进行了全面的升级的改造。

10年磨一剑,悟空CRM的开源道路还需继续前进,也会不断面临更大的挑战,相信这个开源方向已经嵌入悟空CRM的骨髓,悟空的金箍棒总有一天会变得更强大。

悟空CRM开源项目主要功能:悟空CRM开源版一共包含了100多种模块应用

JAVA版本

核心框架:jfinal3.8
缓存:redis caffeine
数据库连接池:Druid
工具类:hutool,fastjson,poi-ooxml
定时任务:jfinal-cron
项目构建工具:maven
Web容器:tomcat,undertow(默认)
前端MVVM框架:Vue.JS 2.5.x
路由:Vue-Router 3.x
数据交互:AxiosUI框架:Element-UI 2.6.3
项目结构

├──  LICENSE
├──  README.md
├──  build                        //  配置
│      ├──  build.js
│      ├──  check-versions.js
│      ├──  logo.png
│      ├──  utils.js
│      ├──  vue-loader.conf.js
│      ├──  webpack.base.conf.js
│      ├──  webpack.dev.conf.js
│      └──  webpack.prod.conf.js
├──  config
│      ├──  dev.env.js
│      ├──  index.js
│      └──  prod.env.js
├──  favicon.ico
├──  index.html                      //  入口html文件
├──  package-lock.json
├──  package.json                     //  定义项目所需要的各种模块,以及配置信息
├──  src
│      ├──  App.vue                   //  页面入口
│      ├──  api                        //  api接口
│      │      ├──  businessIntelligence    //  商业智能
│      │      ├──  common.js                   //  公共
│      │      ├──  customermanagement        //  客户管理
│      │      ├──  login.js                   //  登录
│      │      ├──  oamanagement                    //办公
│      │      ├──  personCenter
│      │      └──  systemManagement
│      ├──  assets                            //  图片和图标
│      │      ├──  401_images
│      │      ├──  404_images
│      │      ├──  iconfont
│      │      └──  img
│      ├──  components                         //  自定义组件
│      │      ├──  CreateCom                     //  新建
│      │      │      ├──  CrmRelative.vue              //  关联客户管理列表
│      │      │      ├──  CrmRelativeCell.vue
│      │      │      ├──  CrmRelativeTable.vue
│      │      │      ├──  XhBusinessStatus.vue        //  商机状态
│      │      │      ├──  XhCustomerAddress.vue  //  新建客户下的地图位置
│      │      │      ├──  XhDate.vue                        //  时间选择
│      │      │      ├──  XhDateTime.vue
│      │      │      ├──  XhFiles.vue                        //  附件
│      │      │      ├──  XhInput.vue                      //  单行输入框
│      │      │      ├──  XhMultipleSelect.vue        //  多选
│      │      │      ├──  XhProduct.vue                  //  产品关联
│      │      │      ├──  XhProuctCate.vue              //  产品类别
│      │      │      ├──  XhReceivablesPlan.vue      //  回款计划
│      │      │      ├──  XhSelect.vue                        //  单选
│      │      │      ├──  XhStrucUserCell.vue            //  员工部门选择框
│      │      │      ├──  XhStructure.vue                    //  部门选择
│      │      │      ├──  XhStructureCell.vue
│      │      │      ├──  XhTextarea.vue                      //  多行输入框
│      │      │      ├──  XhUser.vue                            //  员工选择
│      │      │      ├──  XhUserCell.vue
│      │      │      ├──  arrayMixin.js                            //  公共逻辑
│      │      │      ├──  index.js
│      │      │      ├──  objMixin.js
│      │      │      └──  stringMixin.js
│      │      ├──  CreateSections.vue                          //  容器布局
│      │      ├──  CreateView.vue
│      │      ├──  DetailCell.vue
│      │      ├──  EditImage.vue                                    //  编辑图片
│      │      ├──  Examine                                          //  审批展示和操作
│      │      ├──  MapView.vue                                      //  地图预览位置
│      │      ├──  SlideView.vue
│      │      ├──  emoji.vue                                              //  表情
│      │      ├──  flexbox                                                  //  flex
│      │      │      ├──  flexbox-item.vue
│      │      │      ├──  flexbox.vue
│      │      │      └──  index.js
│      │      ├──  relatedBusiness.vue                              //  关联客户内容
│      │      ├──  reminder.vue
│      │      ├──  selectEmployee                                    //  选择员工
│      │      └──  vuePictureViewer                                  //  文件预览
│      ├──  directives                                            //  自定义指令
│      │      ├──  empty
│      │      ├──  photo
│      ├──  filters                                          //  过滤器
│      ├──  main.js                                         //  程序入口
│      ├──  permission.js                                                    //  路由处理
│      ├──  route加载更多

复制代码通过权限注解在拦截器判断用户是否拥有访问权限

@Override
public void intercept(Invocation invocation) {
    //TODO 权限功能后台拦截
    Permissions permissions=invocation.getMethod().getAnnotation(Permissions.class);
    if(permissions!=null&&permissions.value().length>0){
        JSONObject jsonObject= Aop.get(AdminRoleService.class).auth(BaseUtil.getUserId());
        //组装应有权限列表
        List<String> arr=queryAuth(jsonObject, "");
        boolean isRelease=false;
        for (String key : permissions.value()) {
            if(!isRelease){
                if(arr.contains(key)){
                    isRelease=true;
                }
            }
        }
        if(!isRelease){
            invocation.getController().renderJson(R.error("无权访问"));
            return;
        }
    }
    invocation.invoke();

}复制代码通过AOP和注解对数据进行非空校验,无需一个个判断参数是否为空,数据为空直接返回 自定义分页数据接收,自动处理分页参数和数据对象,给controller方法加上参数 BasePageRequest,T为对象类型,然后参数就会自动组装成分页参数和定义的对象类,以下为实现代码:

public class PageParaGetter extends ParaGetter<BasePageRequest> {
    public PageParaGetter(String parameterName, String defaultValue) {
        super(parameterName, defaultValue);
    }
    @Override
    protected BasePageRequest to(String s) {
        return null;
    }
@Override
@SuppressWarnings("unchecked")
public BasePageRequest get(Action action, Controller controller) {
    Parameter[] parameters=action.getMethod().getParameters();
    Class clazz=null;
    for (Parameter parameter:parameters){
        if(BasePageRequest.class.isAssignableFrom(parameter.getType())){
            Type parameterizedType=parameter.getParameterizedType();
            if (parameterizedType instanceof ParameterizedType) {
                Type[] params = ((ParameterizedType) parameterizedType).getActualTypeArguments();
                clazz= TypeUtils.getClass(params[0]);
            }
            break;
        }
    }
    boolean isJson=controller.getHeader("Content-Type")!=null&&controller.getHeader("Content-Type").toLowerCase().contains("application/json");
    return isJson?new BasePageRequest(controller.getRawData(),clazz):new BasePageRequest(controller.getKv(),clazz);
}
}

复制代码自定义json工厂,实现对数据的个性化解析返回,如实现将数据返回时将数据转成驼峰规则,自定义某种类型的对象的返回格式等。可以自定义错误处理模板,在出现错误或者其他异常的情况下,可以给予用户一个清晰的提示,避免用户看到一些无用的错误信息等功能文件可以上传到项目目录之外,避免了重新打包项目后文件的丢失

@Override
public void configConstant(Constants me) {
    me.setDevMode(prop.getBoolean("jfinal.devMode", true));
    me.setInjectDependency(true);
    //设置上传文件到哪个目录
    me.setBaseUploadPath(BaseConstant.UPLOAD_PATH);
    me.setBaseDownloadPath(BaseConstant.UPLOAD_PATH);
  //自定义json工厂
    me.setJsonFactory(new ErpJsonFactory());
    //限制上传100M
    me.setMaxPostSize(104857600);
}

复制代码采用项目分层化的设计,职责分工明确,降低代码的耦合性Hander->对指定规则的url进行捕获或者放心Interceptor->环绕式AOP拦截,对访问权限,数据权限,参数等进行校验,可以配置在全局,单个路由,单个controller,单个方法等上面,可进行自定义实现,对数据进行处理Router->对不同规则的数据进行分发,不同url进入不同路由和controllerController->对参数进行组装,将数据传入到service处理后进行render返回Service->对业务代码进行处理,并将数据转入Db处理或缓存 Db->对数据库进行操作 Render->将service返回的数据在controller进行返回,以及出错后通过SQL模板功能,将sql写入到xx.sql文件中,如果sql文件有变动,无需重新编译打包,直接改动sql文件中的sql即可,以下为自动扫描指定路径下sql文件的代码:

private void getSqlTemplate(String path, ActiveRecordPlugin arp) {
    File file = new File(path);
    if (file.exists()) {
        File[] files = file.listFiles();
        if (files != null && files.length > 0) {
            for (File childFile : files) {
                if (childFile.isDirectory()) {
                    getSqlTemplate(childFile.getAbsolutePath(), arp);
                } else {
                    if (childFile.getName().toLowerCase().endsWith(".sql")) {
                        arp.addSqlTemplate(childFile.getAbsolutePath().replace(PathKit.getRootClassPath(), "").replace("\\", "/"));
                    }
                }
            }
        }
    }
}

PHP版本后端框架:

ThinkPHP 5.0.2
前端MVVM框架:Vue.JS 2.5.x
路由:Vue-Router 3.x
数据交互:AxiosUI
框架:Element-UI 2.6.3
悟空crm9.0的运行环境要求PHP5.6以上悟空CRM9.0(PHP)版本应用部署
目录结构

├─application           应用目录(可设置)
│  ├─admin               系统设置目录
│  │  ├─config.php      模块配置文件
│  │  ├─common.php      模块函数文件
│  │  ├─controller      控制器目录
│  │  ├─model           模型目录
│  │  ├─validate        验证器目录
│  │  ├─view            视图目录
│  │  └─lang            语言包
│  ├─bi                  商业智能模块目录
│  │  ├─config.php      模块配置文件
│  │  ├─common.php      模块函数文件
│  │  ├─controller      控制器目录
│  │  ├─model           模型目录
│  │  ├─validate        验证器目录
│  │  ├─view            视图目录
│  │  └─lang            语言包
│  ├─common              公共模块目录
│  │  ├─adapter         认证权限类目录
│  │  ├─behavior        行为(钩子)目录
│  │  ├─controller      公共控制器目录
│  │  └─lang            语言包
​
│  ├─crm                 客户管理目录
│  │  ├─config.php      模块配置文件
│  │  ├─common.php      模块函数文件
│  │  ├─controller      控制器目录
│  │  ├─model           模型目录
│  │  ├─validate        验证器目录
│  │  ├─view            视图目录
│  │  └─lang            语言包
│  ├─lang                语言包
│  ├─oa                  办公目录
│  │  ├─config.php      模块配置文件
│  │  ├─common.php      模块函数文件
│  │  ├─controller      控制器目录
│  │  ├─model           模型目录
│  │  ├─validate        验证器目录
│  │  ├─view            视图目录
│  │  └─lang            语言包
│  ├─work                项目管理目录
│  │  ├─config.php      模块配置文件
│  │  ├─common.php      模块函数文件
│  │  ├─controller      控制器目录
│  │  ├─model           模型目录
│  │  ├─validate        验证器目录
│  │  ├─view            视图目录
│  │  └─lang            语言包
│  ├─command.php        命令行工具配置文件
│  ├─common.php         应用公共(函数)文件
│  ├─tags.php           应用行为扩展定义文件
├─config                配置目录(可定义)
│  ├─config.php         应用(公共)配置文件
│  ├─database.php       数据库配置文件
│  ├─route_admin.php    系统设置路由文件
│  ├─route_bi.php       商业智能路由文件
│  ├─route_crm.php      客户管理路由文件
│  ├─route_oa.php       办公路由文件
│  ├─route_work.php     项目管理路由文件
│  └─version.php        版本信息文件
├─extend                扩展类库目录(可定义)
├─public                WEB 部署目录(对外访问目录)
│  ├─sql                安装及更新sql目录
│  ├─static             静态资源存放目录(css,js,image)
│  └─.uploads           上传文件目录
├─runtime               应用的运行时目录(可写,可设置)
├─static                前端VUE打包目录=
├─vendor                第三方类库目录(Composer)
├─thinkphp              框架系统目录
│  ├─lang               语言包目录
│  ├─library            框架核心类库目录
│  │  ├─think           Think 类库包目录
│  │  └─traits          系统 Traits 目录
│  ├─tpl                系统模板目录
│  ├─.htaccess          用于 apache 的重写
│  ├─.travis.yml        CI 定义文件
│  ├─base.php           基础定义文件
│  ├─composer.json      composer 定义文件
│  ├─console.php        控制台入口文件
│  ├─convention.php     惯例配置文件
│  ├─helper.php         助手函数文件(可选)
│  ├─LICENSE.txt        授权说明文件
│  ├─phpunit.xml        单元测试配置文件
│  ├─README.md          README 文件
│  └─start.php          框架引导文件
├─composer.json         composer 定义文件
├─LICENSE.txt           授权说明文件
├─README.md             README 文件
├─think                  命令行入口文件
├─index.php             应用入口文件
├─index.html            前端展示入口文件复制代码系统截图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

目录
相关文章
|
27天前
|
编解码 Oracle Java
java9到java17的新特性学习--github新项目
本文宣布了一个名为"JavaLearnNote"的新GitHub项目,该项目旨在帮助Java开发者深入理解和掌握从Java 9到Java 17的每个版本的关键新特性,并通过实战演示、社区支持和持续更新来促进学习。
64 3
|
9天前
|
编解码 人工智能 自然语言处理
MaskGCT:登上GitHub趋势榜榜首的TTS开源大模型
近日,香港中文大学(深圳)联手趣丸科技推出了新一代大规模声音克隆TTS模型——MaskGCT。一起看看该模型的一些表现吧!
|
28天前
|
数据采集 应用服务中间件 Go
开源的键鼠共享工具「GitHub 热点速览」
开源的键鼠共享工具「GitHub 热点速览」
|
3月前
|
SQL JavaScript 前端开发
Github 2024-08-05 开源项目周报 Top15
根据 Github Trendings 的统计,本周(2024年8月5日统计)共有15个项目上榜。以下是根据开发语言汇总的项目数量: - Go 项目:4个 - JavaScript 项目:3个 - Python 项目:3个 - Java 项目:2个 - TypeScript 项目:2个 - C 项目:1个 - Shell 项目:1个 - Dockerfile 项目:1个 - 非开发语言项目:1个
85 2
|
3月前
|
人工智能 Rust JavaScript
Github 2024-08-26 开源项目周报Top15
根据Github Trendings的统计,本周共有15个项目上榜。以下是按开发语言汇总的项目数量:Python项目8个,TypeScript、C++ 和 Rust 项目各2个,Jupyter Notebook、Shell、Swift 和 Dart 项目各1个。其中,RustDesk 是一款用 Rust 编写的开源远程桌面软件,可作为 TeamViewer 的替代品;Whisper 是一个通用的语音识别模型,基于大规模音频数据集训练而成;初学者的生成式人工智能(第2版)则是由微软提供的18门课程,教授构建生成式AI应用所需的知识。
114 1
|
3月前
|
Rust Dart 前端开发
Github 2024-08-19 开源项目周报Top15
根据Github Trendings的统计,本周(2024年8月19日统计)共有15个项目上榜。按开发语言分类,上榜项目数量如下:Python项目最多,有7项;其次是JavaScript和TypeScript,各有3项;Dart有2项;HTML、PowerShell、Clojure和C++各1项。此外,还介绍了多个热门项目,包括Bootstrap 5、RustDesk、ComfyUI、易采集、Penpot等,涵盖了Web开发、远程桌面、自动化测试、设计工具等多个领域。
104 1
|
3月前
|
JavaScript 前端开发 Go
Github 2024-08-12 开源项目周报 Top14
本周Github Trendings共有14个项目上榜,按开发语言汇总如下:Python项目7个,TypeScript项目5个,C项目2个,JavaScript项目2个,Go和Batchfile项目各1个。其中亮点包括开发者职业成长指南、Windows激活工具、ComfyUI图形界面、AFFiNE知识库、易采集可视化爬虫等项目,涵盖多种实用工具和开源平台。
103 1
|
3月前
|
JavaScript 前端开发 Java
Github 2024-08-01 开源项目月报 Top17
根据Github Trendings统计,2024年8月共有17个项目上榜。按开发语言分类,项目数量如下:Python项目6个,非开发语言项目与TypeScript项目各4个,JavaScript项目3个,Java、Go及Vue项目各1个。其中,免费编程学习平台freeCodeCamp.org以381,011个Star数领先,提供全栈网页开发和机器学习课程。其他项目涵盖编程书籍、API集合、低代码开发平台等多种资源。
35 1
|
3月前
|
存储 安全 Java
【事故】记一次意外把公司项目放到GitHub并被fork,如何使用DMCA下架政策保障隐私
在一次意外中,作者因三年前将测试代码遗忘在GitHub上而遭遇了代码被他人fork的问题。为解决这一危机,作者详细介绍了如何通过GitHub的DMCA下架通知流程安全删除敏感代码,包括处理私人信息和商标侵权的具体步骤。本文不仅提供了实用的操作指南,还强调了及时响应的重要性,帮助读者避免类似风险
36 0
【事故】记一次意外把公司项目放到GitHub并被fork,如何使用DMCA下架政策保障隐私