erupt低代码平台
前言
记录学习成果,以便温故而知新最近对低代码平台很有兴趣,忽然发现了erupt,就学习了一下,下面的内容有些是直接来自于官方example
1.新建springboot项目
如图:
2.修改pom.xml
直接列出所用到的jar包及其他的修改
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.fy</groupId>
<artifactId>erupt</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>fy-erupt</name>
<description>erupt project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<erupt.version>1.10.6</erupt.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--用户权限管理-->
<dependency>
<groupId>xyz.erupt</groupId>
<artifactId>erupt-upms</artifactId>
<version>${erupt.version}</version>
</dependency>
<!--接口数据安全-->
<dependency>
<groupId>xyz.erupt</groupId>
<artifactId>erupt-security</artifactId>
<version>${erupt.version}</version>
</dependency>
<!--后台WEB界面-->
<dependency>
<groupId>xyz.erupt</groupId>
<artifactId>erupt-web</artifactId>
<version>${erupt.version}</version>
</dependency>
<!--任务管理模块-->
<dependency>
<groupId>xyz.erupt</groupId>
<artifactId>erupt-job</artifactId>
<version>${erupt.version}</version>
</dependency>
<!--代码生成器模块-->
<dependency>
<groupId>xyz.erupt</groupId>
<artifactId>erupt-generator</artifactId>
<version>${erupt.version}</version>
</dependency>
<!--服务监控模块-->
<dependency>
<groupId>xyz.erupt</groupId>
<artifactId>erupt-monitor</artifactId>
<version>${erupt.version}</version>
</dependency>
<!-- mysql驱动包,其他数据库驱动依赖请查阅 Maven Repository → https://mvnrepository.com -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
erupt最新版在登录后如果没有修改密码,弹出的修改密码窗口没有关闭按钮,而1.10.6版本的弹出的修改密码窗口是有关闭按钮的,所以用了此版本。
3.建数据及application.yml文件
(1)建数据库fy-erupt
(2)新建application.yml文件
内容如下:
erupt-app:
# 登录失败几次,需要验证码
verifyCodeCount: 2
erupt:
# 是否开启csrf防御
csrfInspect: true
# 是否开启redis方式存储session,默认false,开启后需在配置文件中添加redis配置(同 spring boot)
redisSession: false
# 附件上传存储路径, 默认路径为:/opt/erupt-attachment
uploadPath: D:/erupt/attachment
# 是否保留上传文件原始名称
keepUploadFileName: false
# 登录session时长(redisSession为true时有效)
upms.expireTimeByLogin: 60
# 是否记录操作日志,默认true,该功能开启后可在【系统管理 → 操作日志】中查看操作日志
security.recordOperateLog: true
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/fy-erupt?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
username: root
password: root
jpa:
show-sql: true
generate-ddl: true
open-in-view: true
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
database: mysql
hibernate:
ddl-auto: update
profiles:
active: dev
mail:
username: xxxx@qq.com
password: xxxxxxx
host: smtp.qq.com
properties:
mail.smtp.ssl.auth: true
mail.smtp.ssl.enable: true
mail.smtp.ssl.required: true
servlet:
multipart:
max-file-size: 100MB
max-request-size: 100MB
server:
# 启用 gzip 压缩
compression:
mime-types: application/javascript,text/css,application/json,application/xml,text/html,text/xml,text/plain
enabled: true
error:
includeException: true
includeStacktrace: ALWAYS
includeMessage: ALWAYS
(3)启动项目
自动生成相关数据表若干张,如图:
4.运行项目
(1)修改main函数所在类
修改后的文件如图:
package cn.fy.erupt;
import java.awt.Desktop;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import xyz.erupt.core.annotation.EruptScan;
@SpringBootApplication
@EntityScan
@EruptScan
public class FyEruptApplication {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(FyEruptApplication.class, args);
ConfigurableEnvironment environment = run.getEnvironment();
String port = environment.getProperty("local.server.port");
try {
System.setProperty("java.awt.headless", "false");
Desktop.getDesktop().browse(new URI("http://localhost:"+port));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
(2)新增app.js文件
在resources目录下新建public目录,然后建app.js文件,内容如下:
//如果修改后不生效请清除浏览器缓存后刷新重试
window.eruptSiteConfig = {
//erupt接口地址,在前后端分离时指定
domain: "",
//附件地址,一般情况下不需要指定,如果自定义对象存储空间,则需在此指定附件资源访问地址
fileDomain: "",
//标题
title: "Erupt Example",
//描述
desc: "通用数据管理框架",
//高德地图api key,使用地图组件须指定此属性,amapKey获取地址:https://lbs.amap.com
amapKey: "6ba79a8db11b51aeb1176bd4cfa049f4",
//logo路径
logoPath: "erupt.svg",
//logo文字
logoText: "管理系统",
//是否开启路由复用
routerReuse: true,
};
项目的部分配置项是在这个文件里配置的,文件中已有注释,不再赘述。
(3)启动程序
启动成功后会自动打开系统默认浏览器,显示项目的登录页面。默认登录账密是erupt/erupt。
5.代码生成
(1)排班
在菜单“代码生成”中子菜单“生成Erupt代码”中新增如图信息:
如果代码预览有问题,请刷新浏览器再预览。
在项目中新建包“cn.fy.erupt.model.work”,在“操作”列点击“代码预览”按钮,把代码拷到新建的包中,然后参考文档,再结合自己的需求修改代码如下:
package cn.fy.erupt.model.work;
import javax.persistence.*;
import org.hibernate.annotations.SQLDelete;
import xyz.erupt.annotation.*;
import xyz.erupt.annotation.sub_erupt.*;
import xyz.erupt.annotation.sub_field.*;
import xyz.erupt.annotation.sub_field.sub_edit.*;
import xyz.erupt.upms.handler.DictCodeChoiceFetchHandler;
import xyz.erupt.upms.helper.HyperModelVo;
import xyz.erupt.upms.model.EruptUser;
import xyz.erupt.upms.model.base.HyperModel;
import xyz.erupt.jpa.model.BaseModel;
import java.util.Set;
import java.util.Date;
@Erupt(
name = "排班表",
filter = @Filter("deleted = false"),
power = @Power(importable = true, export = true)
)
@Table(name = "t_work_scheduling")
@SQLDelete(sql="update t_work_scheduling set deleted = true, deleteTime = now() where id = ?")
@Entity
public class Scheduling extends HyperModelVo {
@EruptField(
views = @View(
title = "日期"
),
edit = @Edit(
title = "日期",
type = EditType.DATE, search = @Search, notNull = true,
dateType = @DateType,
placeHolder = "请选择日期"
)
)
private Date date;
@EruptField(
views = @View(
title = "人员",
column = "name"
),
edit = @Edit(
title = "人员",
type = EditType.REFERENCE_TREE, search = @Search, notNull = true,
filter = @Filter("EruptUser.isAdmin = false"),
referenceTreeType = @ReferenceTreeType(id = "id", label = "name"),
placeHolder = "请选择人员"
)
)
@ManyToOne
private EruptUser user;
@EruptField(
views = @View(
title = "班次"
),
edit = @Edit(
title = "班次",
type = EditType.CHOICE, search = @Search, notNull = true,
choiceType = @ChoiceType(
fetchHandler = DictCodeChoiceFetchHandler.class,
//参数一必填,需替换成实际的字典编码
//参数二可不填,表示缓存时间,默认为3000毫秒
fetchHandlerParams = {"TimeType"}
),
placeHolder = "请选择班次"
)
)
private String timeType;
//逻辑删除
private Boolean deleted = false;
}
先建主菜单“生产工作”,再建子菜单“排班”,如图:
菜单类型选“表格”,类型值输入刚刚新建代码的类名。
重新启动后,则生成类对应的表,登录后,菜单可以访问,新增表的增删改查都已经实现了。
(2)工作日报与工作日报项、一对多关联
工作日报代码信息截图:
工作日报代码如下:
package cn.fy.erupt.model.work;
import javax.persistence.*;
import xyz.erupt.annotation.*;
import xyz.erupt.annotation.sub_erupt.*;
import xyz.erupt.annotation.sub_field.*;
import xyz.erupt.annotation.sub_field.sub_edit.*;
import xyz.erupt.upms.handler.DictCodeChoiceFetchHandler;
import xyz.erupt.upms.helper.HyperModelVo;
import xyz.erupt.upms.model.base.HyperModel;
import xyz.erupt.jpa.model.BaseModel;
import java.util.Set;
import java.util.Date;
@Erupt(
name = "工作日报",
drills = @Drill(
title = "工作日报项",
link = @Link(
linkErupt = DailyItem.class, joinColumn = "daily.id"
)
))
@Table(name = "t_work_daily")
@Entity
public class Daily extends HyperModelVo {
@EruptField(
views = @View(
title = "日期"
),
edit = @Edit(
title = "日期",
type = EditType.DATE, search = @Search, notNull = true,
dateType = @DateType,
placeHolder = "请选择日期"
)
)
private Date date;
@EruptField(
views = @View(
title = "班次"
),
edit = @Edit(
title = "班次",
type = EditType.CHOICE, search = @Search, notNull = true,
choiceType = @ChoiceType(
fetchHandler = DictCodeChoiceFetchHandler.class,
//参数一必填,需替换成实际的字典编码
//参数二可不填,表示缓存时间,默认为3000毫秒
fetchHandlerParams = {"TimeType"}
),
placeHolder = "请选择班次"
)
)
private String timeType;
@EruptField(
views = @View(
title = "工时"
),
edit = @Edit(
title = "工时",
type = EditType.NUMBER, notNull = true,
numberType = @NumberType(min=0, max=24),
placeHolder = "请输入工时"
)
)
private Double hour;
}
工作日报项代码信息截图:
工作日报项代码:
package cn.fy.erupt.model.work;
import javax.persistence.*;
import xyz.erupt.annotation.*;
import xyz.erupt.annotation.sub_erupt.*;
import xyz.erupt.annotation.sub_field.*;
import xyz.erupt.annotation.sub_field.sub_edit.*;
import xyz.erupt.upms.model.base.HyperModel;
import xyz.erupt.jpa.model.BaseModel;
import java.util.Set;
import java.util.Date;
@Erupt(name = "工作日报项")
@Table(name = "t_work_daily_item")
@Entity
public class DailyItem extends HyperModel {
@EruptField(
views = @View(
title = "产品名称"
),
edit = @Edit(
title = "产品名称",
type = EditType.INPUT, search = @Search, notNull = true,
inputType = @InputType,
placeHolder = "请输入产品名称"
)
)
private String productName;
@EruptField(
views = @View(
title = "产量"
),
edit = @Edit(
title = "产量",
type = EditType.NUMBER, notNull = true,
numberType = @NumberType(min=0, max=99999999),
placeHolder = "请输入产量"
)
)
private Double num;
@EruptField(
views = @View(
title = "备注",
width = "200px"
),
edit = @Edit(
title = "备注",
type = EditType.TEXTAREA,
placeHolder = "请输入备注"
)
)
private @Lob String remark;
@ManyToOne
@EruptField
@JoinColumn(name = "daily_id")
private Daily daily;
}
在“生产工作”菜单下分别建“工作日报”菜单与“工作日报项”菜单,区别是“工作日报项”菜单是隐藏的,如图:
由于工作日报类配置了钻取(drills)项,实现了一对多的效果,就是在工作日报列表的操作项中多了工作日报项按钮,点击后弹出“工作日报项”列表窗口。两个窗口的增删改查功能均已实现,如下图所示:
6.组织、岗位、角色与用户
默认一个用户只能选一个组织与一个岗位,可以多选角色。角色是赋菜单权限的。
7.定时任务erupt-job
独立的任务模块。
定时任务的Java类需要实现EruptJobHandler接口的exec方法,代码如下:
package cn.fy.erupt.job;
import org.springframework.stereotype.Service;
import xyz.erupt.core.annotation.EruptHandlerNaming;
import xyz.erupt.job.handler.EruptJobHandler;
@Service
@EruptHandlerNaming("自定义任务1")
public class TestJob implements EruptJobHandler {
@Override
public String exec(String arg0, String arg1) {
System.out.println(arg0);
System.out.println(arg1);
return null;
}
}
然后在“任务”管理菜单的子菜单“任务维护”中新增任务,如图:
其中Cron表达式需要自己编辑,本项目不带辅助功能,有点坑!!!JOB处理类就是代码里注解的文字。
新增启用后就能运行定时任务。
定时任务代码中如果没有掌握操作数据库的方法或者对项目框架功能不熟,这个功能似乎施展不了什么用途。
8.自定义freemarker模板页
这里代码来源于官方。
java代码:
package cn.fy.erupt.action;
import org.springframework.stereotype.Service;
import xyz.erupt.tpl.annotation.EruptTpl;
import xyz.erupt.tpl.annotation.TplAction;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
@EruptTpl
@Service
public class FreemarkerAction {
@TplAction(value = "freemarker.ftl")
public Map<String, Object> dashboard() {
Map<String, Object> map = new HashMap<>();
Map<String, Object> mp = new LinkedHashMap<>();
mp.put("annotation", 'E');
mp.put("core", 'R');
mp.put("auth", 'U');
mp.put("web", 'P');
mp.put("mongodb", 'T');
mp.put("bi", '-');
mp.put("job", '-');
mp.put("tpl", '-');
mp.put("generator", '-');
map.put("color", new String[]{
"#eb776e", "#56aad6", "#69d5e7", "#f686e5", "#29ae94", "#fbd364",
"#4da1ff", "#ff6e4b", "#ffc524", "#e07de9", "#42e9e1", "#a9f", "#a90",
"#09f", "#928bff"
});
map.put("map", mp);
return map;
}
}
重点两个标签@EruptTpl和@TplAction(value = “freemarker.ftl”)
在resources目录下新建tpl,然后新建问题件“freemarker.ftl”和“header.html”。
freemarker.ftl文件内容:
<!DOCTYPE html>
<html lang="en" style="background: #fff">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.card {
float: left;
width: 25%;
box-sizing: border-box;
}
.card > .item {
transition: .5s all;
cursor: pointer;
margin: 10px;
border: 1px solid #ccc;
/*border-top: 6px solid #;*/
}
.card > .item .title {
margin: 0;
padding: 15px 0;
text-align: center;
color: #fff;
/*border-bottom: 1px dashed #ccc;*/
transition: 1s all;
}
.card > .item:hover {
/*background: #333;*/
/*color: #fff;*/
transform: translateY(-8px);
transition: all .25s ease-in-out;
box-shadow: 0 25px 60px -20px rgba(155, 165, 163, .45);
}
.card > .item:hover .title {
background: #333;
color: #fff;
}
@media screen and (max-width: 767px) {
.card {
float: left;
width: 50%;
box-sizing: border-box;
}
}
</style>
</head>
<body>
<div>
<#include "./header.html">
<div style="margin:0 15px">
<!--<h1 style="padding-left:10px;text-align: center">-->
<!--<span style="font-size: 2em">Use Erupt tpl draw</span>-->
<!--</h1>-->
<#list map?keys as key>
<div class="card">
<div class="item">
<p class="title" style="background: ${color[key_index]}">${key}</p>
<p style="text-align: center;font-size: 2.2em;color: ${color[key_index]}">${map[key]}</p>
</div>
</div>
</#list>
</div>
</div>
</body>
</html>
header.html文件内容:
<header style="margin:0 25px;">
<h1 style="line-height: 60px;text-align: center">Common Header</h1>
</header>
先建菜单“页面一”,如图:
建好后重启就能访问新建页面。
这个功能也是一样,不知道查库的方法,还是不带好用。
9.体会
一对多,多对一这样关联关系的增删改查实现起来一般没什么问题,只要实体类就可以。目前看,搞一些复杂一点的功能,学习的成本就不太好说了。