├── src ├── main │ ├── resources │ │ ├── public │ │ │ ├── favicon.ico │ │ │ ├── login-img.jpg │ │ │ ├── login-img.png │ │ │ ├── home.html │ │ │ ├── app.css │ │ │ └── app.js │ │ ├── tpl │ │ │ ├── header.html │ │ │ ├── erupt.html │ │ │ ├── operation.ftl │ │ │ ├── velocity │ │ │ │ └── velocity.vm │ │ │ ├── freemarker.ftl │ │ │ └── thymeleaf.html │ │ └── application.yml │ └── java │ │ └── com │ │ └── example │ │ └── demo │ │ ├── action │ │ ├── VelocityTplAction.java │ │ ├── ThymeleafAction.java │ │ └── FreemarkerAction.java │ │ ├── controller │ │ └── TestController.java │ │ ├── handler │ │ ├── AutoCompleteHandlerImpl.java │ │ └── ComponentDataProxy.java │ │ ├── model │ │ ├── blog │ │ │ ├── BlogTagHandler.java │ │ │ ├── PicturesCategory.java │ │ │ ├── BlogTag.java │ │ │ ├── BlogCategory.java │ │ │ ├── FriendlyLink.java │ │ │ ├── Pictures.java │ │ │ └── Blog.java │ │ ├── complex │ │ │ ├── ComplexTab.java │ │ │ ├── ComplexExt.java │ │ │ ├── fun │ │ │ │ ├── OperationHandlerImpl.java │ │ │ │ └── ComplexDataProxy.java │ │ │ ├── ComplexDialog.java │ │ │ └── Complex.java │ │ ├── mall │ │ │ ├── GoodsSpec.java │ │ │ ├── GoodsCategory.java │ │ │ ├── Goods.java │ │ │ └── Coupon.java │ │ ├── TreeView.java │ │ ├── Simple.java │ │ ├── CurdDemo.java │ │ ├── Article.java │ │ └── Component.java │ │ └── ExampleApplication.java └── test │ └── java │ └── com │ └── example │ └── demo │ └── ExampleApplicationTests.java ├── .gitignore ├── LICENSE ├── pom.xml └── README.md /src/main/resources/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erupts/erupt-example/HEAD/src/main/resources/public/favicon.ico -------------------------------------------------------------------------------- /src/main/resources/public/login-img.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erupts/erupt-example/HEAD/src/main/resources/public/login-img.jpg -------------------------------------------------------------------------------- /src/main/resources/public/login-img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erupts/erupt-example/HEAD/src/main/resources/public/login-img.png -------------------------------------------------------------------------------- /src/main/resources/tpl/header.html: -------------------------------------------------------------------------------- 1 |
2 |

Common Header

3 |
-------------------------------------------------------------------------------- /src/main/resources/tpl/erupt.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 |

Hello erupt-tpl

9 | 10 | -------------------------------------------------------------------------------- /src/main/resources/public/home.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | home 5 | 6 | 7 | 8 | 9 | 10 |

I'm home

11 | 12 | -------------------------------------------------------------------------------- /src/main/resources/public/app.css: -------------------------------------------------------------------------------- 1 | /* 例:修改登录页样式 */ 2 | layout-passport > .container { 3 | background-position: center !important; 4 | background-repeat: repeat !important; 5 | background-size: cover !important; 6 | background-color: #fff !important; 7 | /*background-image: url(./login-img.jpg) !important;*/ 8 | background-image: url(https://www.erupt.xyz/demo/login-bg.svg) !important; 9 | } 10 | -------------------------------------------------------------------------------- /src/main/resources/public/app.js: -------------------------------------------------------------------------------- 1 | //如果修改后不生效请清除浏览器缓存后刷新重试 2 | window.eruptSiteConfig = { 3 | //erupt接口地址,在前后端分离时指定 4 | domain: "", 5 | //附件地址,一般情况下不需要指定,如果自定义对象存储空间,则需在此指定附件资源访问地址 6 | fileDomain: "", 7 | //标题 8 | title: "Erupt Example", 9 | //描述 10 | desc: "通用数据管理框架", 11 | //高德地图api key,使用地图组件须指定此属性,amapKey获取地址:https://lbs.amap.com 12 | amapKey: "6ba79a8db11b51aeb1176bd4cfa049f4", 13 | //logo路径 14 | logoPath: "erupt.svg", 15 | //logo文字 16 | logoText: "erupt", 17 | copyright: false 18 | }; -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /src/main/resources/tpl/operation.ftl: -------------------------------------------------------------------------------- 1 | 11 |
12 | 13 | <#list rows as row> 14 | 15 | 16 | 17 | 18 | 19 | 20 |
${row.id}${row.id!''}${row.code!''}
21 |
-------------------------------------------------------------------------------- /src/test/java/com/example/demo/ExampleApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import com.example.demo.model.Article; 4 | import org.junit.jupiter.api.Test; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import xyz.erupt.jpa.dao.EruptDao; 7 | 8 | import jakarta.annotation.Resource; 9 | import java.util.List; 10 | 11 | @SpringBootTest 12 | class ExampleApplicationTests { 13 | 14 | 15 | @Resource 16 | private EruptDao eruptDao; 17 | 18 | //查询 19 | @Test 20 | public void query() { 21 | List
articles = eruptDao.lambdaQuery(Article.class) 22 | .eq(Article::getTopUp, false).list(); 23 | System.out.println(articles); 24 | } 25 | 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/action/VelocityTplAction.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.action; 2 | 3 | import xyz.erupt.annotation.sub_erupt.Tpl; 4 | import xyz.erupt.tpl.annotation.EruptTpl; 5 | import xyz.erupt.tpl.annotation.TplAction; 6 | 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | 10 | /** 11 | * @author YuePeng 12 | * date 2021/3/30 19:38 13 | */ 14 | @EruptTpl(engine = Tpl.Engine.Velocity) 15 | public class VelocityTplAction { 16 | 17 | @TplAction(value = "velocity.vm", path = "/tpl/velocity/velocity.vm") 18 | public Map velocity() { 19 | Map map = new HashMap<>(); 20 | map.put("num", new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9}); 21 | return map; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/controller/TestController.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.controller; 2 | 3 | import com.example.demo.model.Article; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | import xyz.erupt.jpa.dao.EruptDao; 7 | 8 | import jakarta.annotation.Resource; 9 | import java.util.List; 10 | 11 | @RestController 12 | public class TestController { 13 | 14 | @Resource 15 | private EruptDao eruptDao; 16 | 17 | //获取文章列表 18 | @RequestMapping("/list") 19 | public List
testArticle() { 20 | // Erupt jdbc方式查询 21 | return eruptDao.lambdaQuery(Article.class) 22 | .eq(Article::getTopUp, false) 23 | .limit(10).list(); 24 | } 25 | 26 | } -------------------------------------------------------------------------------- /src/main/java/com/example/demo/handler/AutoCompleteHandlerImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.handler; 2 | 3 | import org.springframework.stereotype.Component; 4 | import xyz.erupt.annotation.fun.AutoCompleteHandler; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | /** 11 | * @author liyuepeng 12 | * @date 2020-08-14 13 | */ 14 | @Component // 可以使用依赖注入等操作 15 | public class AutoCompleteHandlerImpl implements AutoCompleteHandler { 16 | 17 | @Override 18 | public List completeHandler(Map formData, String val, String[] param) { 19 | List list = new ArrayList<>(); 20 | for (int i = 0; i < 26; i++) { 21 | list.add(val + " -> " + (char) (i + 64)); 22 | } 23 | return list; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/model/blog/BlogTagHandler.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.model.blog; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.stereotype.Component; 5 | import xyz.erupt.annotation.fun.TagsFetchHandler; 6 | import xyz.erupt.jpa.dao.EruptDao; 7 | 8 | import jakarta.annotation.Resource; 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | import java.util.Map; 12 | 13 | /** 14 | * @author YuePeng 15 | * date 2020/12/15 13:47 16 | */ 17 | @Component 18 | public class BlogTagHandler implements TagsFetchHandler { 19 | 20 | @Resource 21 | private EruptDao eruptDao; 22 | 23 | @Override 24 | public List fetchTags(String[] params) { 25 | return eruptDao.lambdaQuery(BlogTag.class).listSelect(BlogTag::getName); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/ExampleApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.boot.autoconfigure.domain.EntityScan; 6 | import xyz.erupt.core.annotation.EruptScan; 7 | 8 | import java.awt.*; 9 | import java.net.URI; 10 | 11 | @SpringBootApplication 12 | @EruptScan 13 | @EntityScan 14 | public class ExampleApplication { 15 | 16 | //详细使用方法详见项目内 README.md 文件说明 17 | public static void main(String[] args) { 18 | SpringApplication.run(ExampleApplication.class, args); 19 | try { 20 | System.setProperty("java.awt.headless", "false"); 21 | Desktop.getDesktop().browse(new URI("http://localhost:8080")); 22 | } catch (Exception ignore) { 23 | } 24 | System.err.println("详细使用方法,请阅读:README.md"); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/resources/tpl/velocity/velocity.vm: -------------------------------------------------------------------------------- 1 | 27 | #include("/tpl/header.html") 28 | #foreach($i in $num) 29 |

30 | #foreach($j in $num) 31 | #if($i >= $j) 32 | #set($multi = $i * $j) 33 | $i * $j = $multi 34 | #end 35 | #end 36 |

37 | #end -------------------------------------------------------------------------------- /src/main/java/com/example/demo/model/complex/ComplexTab.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.model.complex; 2 | 3 | import xyz.erupt.annotation.Erupt; 4 | import xyz.erupt.annotation.EruptField; 5 | import xyz.erupt.annotation.sub_field.Edit; 6 | import xyz.erupt.annotation.sub_field.View; 7 | import xyz.erupt.jpa.model.BaseModel; 8 | 9 | import jakarta.persistence.Entity; 10 | import jakarta.persistence.Table; 11 | 12 | /** 13 | * @author liyuepeng 14 | * @date 2021-01-02. 15 | */ 16 | @Erupt(name = "一对多新增") 17 | @Table(name = "demo_complex_tab") 18 | @Entity 19 | public class ComplexTab extends BaseModel { 20 | 21 | @EruptField( 22 | views = @View(title = "文本"), 23 | edit = @Edit(title = "文本", notNull = true) 24 | ) 25 | private String input; 26 | 27 | @EruptField( 28 | views = @View(title = "数值", sortable = true), 29 | edit = @Edit(title = "数值") 30 | ) 31 | private Float number; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/model/blog/PicturesCategory.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.model.blog; 2 | 3 | import xyz.erupt.annotation.Erupt; 4 | import xyz.erupt.annotation.EruptField; 5 | import xyz.erupt.annotation.sub_field.Edit; 6 | import xyz.erupt.annotation.sub_field.View; 7 | import xyz.erupt.upms.model.base.HyperModel; 8 | 9 | import jakarta.persistence.Entity; 10 | import jakarta.persistence.Table; 11 | 12 | /** 13 | * @author YuePeng 14 | * date 2020-05-28 15 | */ 16 | @Erupt( 17 | name = "图床分类", 18 | orderBy = "sort" 19 | ) 20 | @Table(name = "blog_picture_category") 21 | @Entity 22 | public class PicturesCategory extends HyperModel { 23 | 24 | @EruptField( 25 | views = @View(title = "名称"), 26 | edit = @Edit(title = "名称", notNull = true) 27 | ) 28 | private String name; 29 | 30 | @EruptField( 31 | views = @View(title = "排序"), 32 | edit = @Edit(title = "排序", notNull = true) 33 | ) 34 | private Integer sort; 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/model/mall/GoodsSpec.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.model.mall; 2 | 3 | import xyz.erupt.annotation.Erupt; 4 | import xyz.erupt.annotation.EruptField; 5 | import xyz.erupt.annotation.sub_field.Edit; 6 | import xyz.erupt.annotation.sub_field.View; 7 | import xyz.erupt.jpa.model.BaseModel; 8 | 9 | import jakarta.persistence.Entity; 10 | import jakarta.persistence.Table; 11 | 12 | @Erupt(name = "商品型号") 13 | @Table(name = "mall_goods_spec") 14 | @Entity 15 | public class GoodsSpec extends BaseModel { 16 | 17 | @EruptField( 18 | views = @View(title = "名称"), 19 | edit = @Edit(title = "名称", notNull = true) 20 | ) 21 | private String name; 22 | 23 | @EruptField( 24 | views = @View(title = "价格"), 25 | edit = @Edit(title = "价格", notNull = true) 26 | ) 27 | private Double price; 28 | 29 | @EruptField( 30 | views = @View(title = "库存"), 31 | edit = @Edit(title = "库存", notNull = true) 32 | ) 33 | private Integer inventory; 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/model/complex/ComplexExt.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.model.complex; 2 | 3 | import xyz.erupt.annotation.Erupt; 4 | import xyz.erupt.annotation.EruptField; 5 | import xyz.erupt.annotation.sub_field.Edit; 6 | import xyz.erupt.annotation.sub_field.View; 7 | import xyz.erupt.annotation.sub_field.sub_edit.BoolType; 8 | import xyz.erupt.jpa.model.BaseModel; 9 | 10 | import jakarta.persistence.Entity; 11 | import jakarta.persistence.Table; 12 | 13 | /** 14 | * @author YuePeng 15 | * date 2023/4/2 21:47 16 | */ 17 | @Erupt(name = "complex_ext") 18 | @Entity 19 | @Table(name = "demo_complex_ext") 20 | public class ComplexExt extends BaseModel { 21 | 22 | @EruptField( 23 | views = @View(title = "姓名"), 24 | edit = @Edit(title = "姓名", notNull = true) 25 | ) 26 | private String name; 27 | 28 | @EruptField( 29 | views = @View(title = "性别"), 30 | edit = @Edit(title = "性别", 31 | boolType = @BoolType(trueText = "男", falseText = "女")) 32 | ) 33 | private Boolean sex; 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/action/ThymeleafAction.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.action; 2 | 3 | import org.springframework.stereotype.Service; 4 | import xyz.erupt.annotation.sub_erupt.Tpl; 5 | import xyz.erupt.tpl.annotation.EruptTpl; 6 | import xyz.erupt.tpl.annotation.TplAction; 7 | 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | 11 | /** 12 | * @author YuePeng 13 | * date 2020-02-24 14 | */ 15 | @EruptTpl(engine = Tpl.Engine.Thymeleaf) 16 | @Service 17 | public class ThymeleafAction { 18 | 19 | @TplAction("thymeleaf.html") 20 | public Map dashboard2() { 21 | Map map = new HashMap<>(); 22 | map.put("list", new String[]{ 23 | "E", "R", "U", "P", "T", "-", "-", "-" 24 | , "-", "-", "-" 25 | }); 26 | map.put("color", new String[]{ 27 | "#eb776e", "#56aad6", "#69d5e7", "#f686e5", "#29ae94", "#fbd364", 28 | "#4da1ff", "#ff6e4b", "#ffc524", "#e07de9", "#42e9e1", "#a9f", "#a90", 29 | "#09f", "#555", "#92abff" 30 | }); 31 | return map; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 erupts 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/model/blog/BlogTag.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.model.blog; 2 | 3 | import xyz.erupt.annotation.Erupt; 4 | import xyz.erupt.annotation.EruptField; 5 | import xyz.erupt.annotation.sub_field.Edit; 6 | import xyz.erupt.annotation.sub_field.View; 7 | import xyz.erupt.annotation.sub_field.sub_edit.InputType; 8 | import xyz.erupt.annotation.sub_field.sub_edit.Search; 9 | import xyz.erupt.upms.model.base.HyperModel; 10 | 11 | import jakarta.persistence.Entity; 12 | import jakarta.persistence.Table; 13 | 14 | /** 15 | * @author YuePeng 16 | * date 2020/12/15 12:06 17 | */ 18 | @Erupt( 19 | name = "博客标签", 20 | desc = "sort" 21 | ) 22 | @Table(name = "blog_tag") 23 | @Entity 24 | public class BlogTag extends HyperModel { 25 | 26 | 27 | @EruptField( 28 | views = @View(title = "标签名称"), 29 | edit = @Edit(title = "标签名称", notNull = true, search = @Search(vague = true), inputType = @InputType(fullSpan = true)) 30 | ) 31 | private String name; 32 | 33 | @EruptField( 34 | views = @View(title = "排序"), 35 | edit = @Edit(title = "排序", notNull = true) 36 | ) 37 | private Integer sort; 38 | 39 | public String getName() { 40 | return name; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/model/complex/fun/OperationHandlerImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.model.complex.fun; 2 | 3 | import com.example.demo.model.complex.Complex; 4 | import com.example.demo.model.complex.ComplexDialog; 5 | import org.springframework.stereotype.Component; 6 | import xyz.erupt.annotation.fun.OperationHandler; 7 | import xyz.erupt.jpa.dao.EruptDao; 8 | 9 | import jakarta.annotation.Resource; 10 | import java.util.List; 11 | 12 | /** 13 | * @author YuePeng 14 | * date 2018-10-10. 15 | */ 16 | @Component 17 | public class OperationHandlerImpl implements OperationHandler { 18 | 19 | @Resource 20 | private EruptDao eruptDao; 21 | 22 | @Override 23 | public String exec(List data, ComplexDialog complexDialog, String[] param) { 24 | // throw new EruptWebApiRuntimeException("出错了!!!"); 25 | // return "msg.info('customer hint')"; 26 | return "codeModal('sql',`select * from xxx`)"; 27 | } 28 | 29 | @Override 30 | public ComplexDialog eruptFormValue(List data, ComplexDialog complexDialog, String[] param) { 31 | complexDialog.setText(data.get(0).getColor()); 32 | complexDialog.setNumber(8L); 33 | return complexDialog; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/model/complex/ComplexDialog.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.model.complex; 2 | 3 | import xyz.erupt.annotation.Erupt; 4 | import xyz.erupt.annotation.EruptField; 5 | import xyz.erupt.annotation.fun.DataProxy; 6 | import xyz.erupt.annotation.sub_field.Edit; 7 | import xyz.erupt.jpa.model.BaseModel; 8 | 9 | import java.time.LocalDateTime; 10 | import java.util.Date; 11 | 12 | 13 | @Erupt(name = "complex dialog") 14 | public class ComplexDialog extends BaseModel { 15 | 16 | @EruptField( 17 | edit = @Edit(title = "文本", notNull = true) 18 | ) 19 | private String text; 20 | 21 | @EruptField( 22 | edit = @Edit(title = "时间", notNull = true) 23 | ) 24 | private LocalDateTime date; 25 | 26 | @EruptField( 27 | edit = @Edit(title = "数值", notNull = true) 28 | ) 29 | private Long number; 30 | 31 | public String getText() { 32 | return text; 33 | } 34 | 35 | public void setText(String text) { 36 | this.text = text; 37 | } 38 | 39 | public LocalDateTime getDate() { 40 | return date; 41 | } 42 | 43 | public Long getNumber() { 44 | return number; 45 | } 46 | 47 | public void setNumber(Long number) { 48 | this.number = number; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/action/FreemarkerAction.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.action; 2 | 3 | import org.springframework.stereotype.Service; 4 | import xyz.erupt.tpl.annotation.EruptTpl; 5 | import xyz.erupt.tpl.annotation.TplAction; 6 | 7 | import java.util.HashMap; 8 | import java.util.LinkedHashMap; 9 | import java.util.Map; 10 | 11 | /** 12 | * @author YuePeng 13 | * date 2020-02-24 14 | */ 15 | @EruptTpl 16 | @Service 17 | public class FreemarkerAction { 18 | 19 | @TplAction(value = "freemarker.ftl") 20 | public Map dashboard() { 21 | Map map = new HashMap<>(); 22 | Map mp = new LinkedHashMap<>(); 23 | mp.put("annotation", 'E'); 24 | mp.put("core", 'R'); 25 | mp.put("auth", 'U'); 26 | mp.put("web", 'P'); 27 | mp.put("mongodb", 'T'); 28 | mp.put("bi", '-'); 29 | mp.put("job", '-'); 30 | mp.put("tpl", '-'); 31 | mp.put("generator", '-'); 32 | map.put("color", new String[]{ 33 | "#eb776e", "#56aad6", "#69d5e7", "#f686e5", "#29ae94", "#fbd364", 34 | "#4da1ff", "#ff6e4b", "#ffc524", "#e07de9", "#42e9e1", "#a9f", "#a90", 35 | "#09f", "#928bff" 36 | }); 37 | map.put("map", mp); 38 | return map; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/model/complex/fun/ComplexDataProxy.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.model.complex.fun; 2 | 3 | import com.example.demo.model.complex.Complex; 4 | import xyz.erupt.annotation.fun.DataProxy; 5 | import xyz.erupt.annotation.model.Column; 6 | import xyz.erupt.annotation.model.Row; 7 | import xyz.erupt.annotation.query.Condition; 8 | 9 | import java.util.*; 10 | 11 | /** 12 | * @author YuePeng 13 | * date 2023/4/11 23:31 14 | */ 15 | public class ComplexDataProxy implements DataProxy { 16 | 17 | @Override 18 | public void afterAdd(Complex complex) { 19 | System.out.println(complex); 20 | } 21 | 22 | @Override 23 | public void afterFetch(Collection> list) { 24 | DataProxy.super.afterFetch(list); 25 | } 26 | 27 | @Override 28 | public List extraRow(List conditions) { 29 | List rows = new ArrayList<>(); 30 | List columns = new ArrayList<>(); 31 | columns.add(Column.builder().value("自定义行").colspan(2).build()); 32 | columns.add(Column.builder().value(100 + "").colspan(10).className("text-red").build()); 33 | rows.add(Row.builder().columns(columns).build()); 34 | return rows; 35 | } 36 | 37 | @Override 38 | public void editBehavior(Complex complex) { 39 | complex.setCode("xxx"); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/model/blog/BlogCategory.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.model.blog; 2 | 3 | import xyz.erupt.annotation.Erupt; 4 | import xyz.erupt.annotation.EruptField; 5 | import xyz.erupt.annotation.sub_field.Edit; 6 | import xyz.erupt.annotation.sub_field.EditType; 7 | import xyz.erupt.annotation.sub_field.View; 8 | import xyz.erupt.annotation.sub_field.sub_edit.Search; 9 | import xyz.erupt.jpa.model.BaseModel; 10 | 11 | import jakarta.persistence.Entity; 12 | import jakarta.persistence.Table; 13 | 14 | /** 15 | * @author YuePeng 16 | * date 2020/12/15 12:07 17 | */ 18 | @Erupt( 19 | name = "博客类别", 20 | desc = "sort" 21 | ) 22 | @Table(name = "blog_category") 23 | @Entity 24 | public class BlogCategory extends BaseModel { 25 | 26 | @EruptField( 27 | views = @View(title = "名称"), 28 | edit = @Edit(title = "名称", notNull = true, search = @Search(vague = true)) 29 | ) 30 | private String name; 31 | 32 | @EruptField( 33 | views = @View(title = "顺序"), 34 | edit = @Edit(title = "顺序", notNull = true) 35 | ) 36 | private Integer sort; 37 | 38 | @EruptField( 39 | views = @View(title = "是否显示"), 40 | edit = @Edit(title = "是否显示", notNull = true) 41 | ) 42 | private Boolean isShow; 43 | 44 | @EruptField( 45 | views = @View(title = "分类介绍"), 46 | edit = @Edit(title = "分类介绍", type = EditType.TEXTAREA) 47 | ) 48 | private String remark; 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/model/mall/GoodsCategory.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.model.mall; 2 | 3 | import xyz.erupt.annotation.Erupt; 4 | import xyz.erupt.annotation.EruptField; 5 | import xyz.erupt.annotation.sub_erupt.Tree; 6 | import xyz.erupt.annotation.sub_field.Edit; 7 | import xyz.erupt.annotation.sub_field.EditType; 8 | import xyz.erupt.annotation.sub_field.sub_edit.AttachmentType; 9 | import xyz.erupt.annotation.sub_field.sub_edit.ReferenceTreeType; 10 | import xyz.erupt.jpa.model.BaseModel; 11 | 12 | import jakarta.persistence.Entity; 13 | import jakarta.persistence.ManyToOne; 14 | import jakarta.persistence.Table; 15 | 16 | @Erupt(name = "商品类别", tree = @Tree(pid = "parent.id"), orderBy = "GoodsCategory.sort") 17 | @Table(name = "mall_goods_category") 18 | @Entity 19 | public class GoodsCategory extends BaseModel { 20 | 21 | @EruptField( 22 | edit = @Edit(title = "分类图片", type = EditType.ATTACHMENT, 23 | attachmentType = @AttachmentType(type = AttachmentType.Type.IMAGE)) 24 | ) 25 | private String image; 26 | 27 | @EruptField( 28 | edit = @Edit(title = "类别名称", notNull = true) 29 | ) 30 | private String name; 31 | 32 | @EruptField( 33 | edit = @Edit(title = "显示顺序") 34 | ) 35 | private Integer sort; 36 | 37 | @ManyToOne 38 | @EruptField( 39 | edit = @Edit(title = "上级分类", type = EditType.REFERENCE_TREE, referenceTreeType = @ReferenceTreeType(pid = "parent.id")) 40 | ) 41 | private GoodsCategory parent; 42 | 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/model/TreeView.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.model; 2 | 3 | import jakarta.persistence.Entity; 4 | import jakarta.persistence.ManyToOne; 5 | import jakarta.persistence.Table; 6 | import xyz.erupt.annotation.Erupt; 7 | import xyz.erupt.annotation.EruptField; 8 | import xyz.erupt.annotation.sub_erupt.Tree; 9 | import xyz.erupt.annotation.sub_field.Edit; 10 | import xyz.erupt.annotation.sub_field.EditType; 11 | import xyz.erupt.annotation.sub_field.View; 12 | import xyz.erupt.annotation.sub_field.sub_edit.ReferenceTreeType; 13 | import xyz.erupt.jpa.model.BaseModel; 14 | 15 | /** 16 | * @author yuepeng 17 | * @date 12/7/18. 18 | */ 19 | 20 | @Entity 21 | @Table(name = "demo_tree") 22 | @Erupt( 23 | name = "树示例", 24 | orderBy = "TreeView.sort", 25 | tree = @Tree(pid = "parent.id") 26 | ) 27 | public class TreeView extends BaseModel { 28 | 29 | @EruptField( 30 | views = @View(title = "名称"), 31 | edit = @Edit(title = "名称", notNull = true) 32 | ) 33 | private String name; 34 | 35 | @EruptField( 36 | views = @View(title = "显示顺序"), 37 | edit = @Edit(title = "显示顺序") 38 | ) 39 | private Integer sort; 40 | 41 | @ManyToOne 42 | @EruptField( 43 | edit = @Edit( 44 | title = "上级树节点", 45 | type = EditType.REFERENCE_TREE, 46 | referenceTreeType = @ReferenceTreeType(pid = "parent.id") 47 | ) 48 | ) 49 | private TreeView parent; 50 | 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/model/blog/FriendlyLink.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.model.blog; 2 | 3 | import xyz.erupt.annotation.Erupt; 4 | import xyz.erupt.annotation.EruptField; 5 | import xyz.erupt.annotation.sub_field.Edit; 6 | import xyz.erupt.annotation.sub_field.View; 7 | import xyz.erupt.annotation.sub_field.ViewType; 8 | import xyz.erupt.jpa.model.BaseModel; 9 | 10 | import jakarta.persistence.Entity; 11 | import jakarta.persistence.Table; 12 | 13 | /** 14 | * @author YuePeng 15 | * date 2020/12/15 12:11 16 | */ 17 | @Erupt( 18 | name = "友情链接", 19 | orderBy = "sort" 20 | ) 21 | @Table(name = "blog_link") 22 | @Entity 23 | public class FriendlyLink extends BaseModel { 24 | 25 | @EruptField( 26 | views = @View(title = "友链名"), 27 | edit = @Edit(title = "友链名", notNull = true) 28 | ) 29 | private String name; 30 | 31 | @EruptField( 32 | views = @View(title = "友链简介"), 33 | edit = @Edit(title = "友链简介", notNull = true) 34 | ) 35 | private String remark; 36 | 37 | @EruptField( 38 | views = @View(title = "友链URL", type = ViewType.LINK_DIALOG), 39 | edit = @Edit(title = "友链URL", notNull = true) 40 | ) 41 | private String url; 42 | 43 | @EruptField( 44 | views = @View(title = "站长邮箱"), 45 | edit = @Edit(title = "站长邮箱") 46 | ) 47 | private String email; 48 | 49 | @EruptField( 50 | views = @View(title = "排序"), 51 | edit = @Edit(title = "排序") 52 | ) 53 | private Integer sort; 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | erupt-app: 2 | # 是否开启水印 3 | water-mark: false 4 | # 登录失败几次,需要验证码 5 | verify-code-count: 2 6 | erupt: 7 | # 是否开启csrf防御 8 | csrf-inspect: true 9 | # 是否开启redis方式存储session,默认false,开启后需在配置文件中添加redis配置(同 spring boot) 10 | redis-session: true 11 | # 附件上传存储路径, 默认路径为:/opt/erupt-attachment 12 | upload-path: D:/erupt/attachment 13 | # 是否保留上传文件原始名称 14 | keep-upload-file-name: false 15 | upms: 16 | # 登录session时长(redisSession为true时有效) 17 | expire-time-by-login: 60 18 | security: 19 | # 是否记录操作日志,默认true,该功能开启后可在【系统管理 → 操作日志】中查看操作日志 20 | record-operate-log: true 21 | 22 | magic-api: 23 | web: /magic/web 24 | # 接口配置文件存放路径 25 | resource.location: D:/erupt/magic-script 26 | show-url: false 27 | 28 | spring: 29 | datasource: 30 | url: jdbc:mysql://localhost:3306/erupt-example?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai 31 | username: root 32 | password: 12345678 33 | jpa: 34 | show-sql: true 35 | generate-ddl: true 36 | database: mysql 37 | mail: 38 | username: xxxx@qq.com 39 | password: xxxxxxx 40 | host: smtp.qq.com 41 | properties: 42 | mail.smtp.ssl.auth: true 43 | mail.smtp.ssl.enable: true 44 | mail.smtp.ssl.required: true 45 | servlet: 46 | multipart: 47 | max-file-size: 100MB 48 | max-request-size: 100MB 49 | data: 50 | redis: 51 | host: 127.0.0.1 52 | port: 6379 53 | timeout: 10000 54 | 55 | server: 56 | # 启用 gzip 压缩 57 | compression: 58 | mime-types: application/javascript,text/css,application/json,application/xml,text/html,text/xml,text/plain 59 | enabled: true 60 | error: 61 | includeException: true 62 | includeStacktrace: ALWAYS 63 | includeMessage: ALWAYS -------------------------------------------------------------------------------- /src/main/java/com/example/demo/model/Simple.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.model; 2 | 3 | import xyz.erupt.annotation.Erupt; 4 | import xyz.erupt.annotation.EruptField; 5 | import xyz.erupt.annotation.sub_field.Edit; 6 | import xyz.erupt.annotation.sub_field.EditType; 7 | import xyz.erupt.annotation.sub_field.View; 8 | import xyz.erupt.annotation.sub_field.sub_edit.Search; 9 | import xyz.erupt.annotation.sub_field.sub_edit.SliderType; 10 | import xyz.erupt.jpa.model.BaseModel; 11 | 12 | import jakarta.persistence.Entity; 13 | import jakarta.persistence.Table; 14 | 15 | import java.time.LocalDate; 16 | import java.util.Date; 17 | 18 | /** 19 | * @author yuepeng 20 | * @date 2020/12/28 11:24 21 | */ 22 | @Table(name = "demo_simple") 23 | @Entity 24 | @Erupt(name = "简单示例") 25 | public class Simple extends BaseModel { 26 | 27 | @EruptField( 28 | views = @View(title = "文本"), 29 | edit = @Edit(title = "文本", notNull = true, search = @Search) 30 | ) 31 | private String input; 32 | 33 | @EruptField( 34 | views = @View(title = "数值", sortable = true), 35 | edit = @Edit(title = "数值", search = @Search) 36 | ) 37 | private Float number; 38 | 39 | @EruptField( 40 | views = @View(title = "布尔"), 41 | edit = @Edit(title = "布尔") 42 | ) 43 | private Boolean bool; 44 | 45 | @EruptField( 46 | views = @View(title = "时间"), 47 | edit = @Edit(title = "时间", search = @Search(vague = true)) 48 | ) 49 | private LocalDate date; 50 | 51 | @EruptField( 52 | views = @View(title = "滑动条"), 53 | edit = @Edit(title = "滑动条", type = EditType.SLIDER, search = @Search, 54 | sliderType = @SliderType(max = 100, markPoints = {30, 60})) 55 | ) 56 | private Integer slide; 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/main/resources/tpl/freemarker.ftl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 52 | 53 | 54 |
55 | <#include "./header.html"> 56 |
57 | 58 | 59 | 60 | <#list map?keys as key> 61 |
62 |
63 |

${key}

64 |

${map[key]}

65 |
66 |
67 | 68 |
69 |
70 | 71 | -------------------------------------------------------------------------------- /src/main/resources/tpl/thymeleaf.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 51 | 52 | 53 |
54 |
55 |
56 | 57 | 58 | 59 |
60 |
61 |

62 |

erupt.xyz

63 |
64 |
65 |
66 |
67 | 70 | 71 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/handler/ComponentDataProxy.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.handler; 2 | 3 | import com.example.demo.model.Component; 4 | import org.apache.poi.ss.usermodel.Workbook; 5 | import xyz.erupt.annotation.fun.DataProxy; 6 | import xyz.erupt.annotation.query.Condition; 7 | 8 | import java.util.Collection; 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | /** 13 | * @author liyuepeng 14 | * @date 2021/1/2 21:29 15 | */ 16 | @org.springframework.stereotype.Component 17 | public class ComponentDataProxy implements DataProxy { 18 | 19 | @Override 20 | public void addBehavior(Component o) { 21 | o.setInput("China🇨🇳"); 22 | o.setNumber1(3.1415926); 23 | o.setColor("#0099ff"); 24 | } 25 | 26 | @Override 27 | public void beforeAdd(Component o) { 28 | System.err.println("beforeAdd"); 29 | } 30 | 31 | @Override 32 | public void afterAdd(Component o) { 33 | System.err.println("afterAdd"); 34 | } 35 | 36 | @Override 37 | public void beforeUpdate(Component o) { 38 | System.err.println("beforeUpdate"); 39 | } 40 | 41 | @Override 42 | public void afterUpdate(Component o) { 43 | System.err.println("afterUpdate"); 44 | } 45 | 46 | @Override 47 | public void beforeDelete(Component o) { 48 | System.err.println("beforeDelete"); 49 | } 50 | 51 | @Override 52 | public void afterDelete(Component o) { 53 | System.err.println("afterDelete"); 54 | } 55 | 56 | @Override 57 | public String beforeFetch(List conditions) { 58 | System.err.println("beforeFetch"); 59 | return null; 60 | } 61 | 62 | @Override 63 | public void afterFetch(Collection> list) { 64 | System.err.println("afterFetch"); 65 | } 66 | 67 | @Override 68 | public void editBehavior(Component o) { 69 | System.err.println("editBehavior"); 70 | } 71 | 72 | @Override 73 | public void excelExport(Object obj) { 74 | Workbook wb = (Workbook) obj; 75 | System.err.println("excelExport"); 76 | } 77 | 78 | @Override 79 | public void excelImport(Object o) { 80 | System.err.println("excelImport"); 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/model/CurdDemo.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.model; 2 | 3 | import xyz.erupt.annotation.Erupt; 4 | import xyz.erupt.annotation.EruptField; 5 | import xyz.erupt.annotation.fun.DataProxy; 6 | import xyz.erupt.annotation.sub_field.Edit; 7 | import xyz.erupt.annotation.sub_field.View; 8 | import xyz.erupt.annotation.sub_field.sub_edit.Search; 9 | import xyz.erupt.core.exception.EruptApiErrorTip; 10 | import xyz.erupt.jpa.model.BaseModel; 11 | 12 | import jakarta.persistence.Entity; 13 | import jakarta.persistence.Table; 14 | import java.util.Collection; 15 | import java.util.Map; 16 | 17 | /** 18 | * @author YuePeng 19 | * date 2021/5/11 13:56 20 | * see link 21 | */ 22 | @Erupt( 23 | name = "服务层逻辑扩展 @DataProxy (扩展CURD)", 24 | desc = "提供增、删、改、查、导入、导出、数据初始化等事件触发逻辑接口,相当于传统开发中的 service 层\n" + 25 | "可以实现如:缓存写入,数据校验,RPC调用,动态赋值等功能 !)", 26 | dataProxy = CurdDemo.class 27 | ) 28 | @Entity 29 | @Table(name = "demo_curd_extension") 30 | public class CurdDemo extends BaseModel implements DataProxy { 31 | 32 | @EruptField( 33 | views = @View(title = "名称"), 34 | edit = @Edit(title = "名称", notNull = true, search = @Search(vague = true)) 35 | ) 36 | private String name; 37 | 38 | public String getName() { 39 | return name; 40 | } 41 | 42 | public void setName(String name) { 43 | this.name = name; 44 | } 45 | 46 | @Override 47 | public void beforeAdd(CurdDemo curdDemo) { 48 | //字段校验 49 | if ("张三".equals(curdDemo.getName())) { 50 | throw new EruptApiErrorTip("名称禁止为张三!"); 51 | } 52 | } 53 | 54 | @Override 55 | public void afterAdd(CurdDemo curdDemo) { 56 | //TODO 添加完成后处理逻辑 57 | } 58 | 59 | @Override 60 | public void beforeUpdate(CurdDemo curdDemo) { 61 | //动态写数据 62 | curdDemo.setName(curdDemo.getName() + "xxx"); 63 | } 64 | 65 | @Override 66 | public void afterUpdate(CurdDemo curdDemo) { 67 | //TODO 修改完成后处理逻辑 68 | } 69 | 70 | @Override 71 | public void beforeDelete(CurdDemo curdDemo) { 72 | //TODO 删除前事件处理逻辑 73 | } 74 | 75 | @Override 76 | public void afterDelete(CurdDemo curdDemo) { 77 | //TODO 删除后事件处理逻辑 78 | } 79 | 80 | @Override 81 | public void afterFetch(Collection> list) { 82 | //TODO 查询结果处理 83 | } 84 | 85 | @Override 86 | public void addBehavior(CurdDemo curdDemo) { 87 | //TODO 数据初始化逻辑 88 | } 89 | 90 | @Override 91 | public void editBehavior(CurdDemo curdDemo) { 92 | //TODO 编辑时数据处理逻辑 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/model/mall/Goods.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.model.mall; 2 | 3 | import xyz.erupt.annotation.Erupt; 4 | import xyz.erupt.annotation.EruptField; 5 | import xyz.erupt.annotation.sub_erupt.LinkTree; 6 | import xyz.erupt.annotation.sub_field.Edit; 7 | import xyz.erupt.annotation.sub_field.EditType; 8 | import xyz.erupt.annotation.sub_field.View; 9 | import xyz.erupt.annotation.sub_field.ViewType; 10 | import xyz.erupt.annotation.sub_field.sub_edit.*; 11 | import xyz.erupt.upms.model.base.HyperModel; 12 | 13 | import jakarta.persistence.*; 14 | import java.util.Set; 15 | 16 | @Erupt(name = "商品管理", linkTree = @LinkTree(field = "category")) 17 | @Table(name = "mall_goods") 18 | @Entity 19 | public class Goods extends HyperModel { 20 | 21 | @EruptField( 22 | views = @View(title = "商品图片"), 23 | edit = @Edit(title = "商品图片", notNull = true, type = EditType.ATTACHMENT, 24 | attachmentType = @AttachmentType(type = AttachmentType.Type.IMAGE, maxLimit = 6)) 25 | ) 26 | private String image; 27 | 28 | @EruptField( 29 | views = @View(title = "商品名称"), 30 | edit = @Edit(title = "商品名称", notNull = true, inputType = @InputType(fullSpan = true), search = @Search(vague = true)) 31 | ) 32 | private String name; 33 | 34 | @ManyToOne 35 | @EruptField( 36 | views = @View(title = "所属分类", column = "name"), 37 | edit = @Edit(title = "所属分类", type = EditType.REFERENCE_TREE, search = @Search, notNull = true, referenceTreeType = @ReferenceTreeType(pid = "parent.id")) 38 | ) 39 | private GoodsCategory category; 40 | 41 | // @EruptField( 42 | // views = @View(title = "价格"), 43 | // edit = @Edit(title = "价格",notNull = true, numberType = @NumberType(min = 0)) 44 | // ) 45 | // private Double price; 46 | 47 | @EruptField( 48 | views = @View(title = "运费"), 49 | edit = @Edit(title = "运费", notNull = true, search = @Search(vague = true)) 50 | ) 51 | private final Double freight = 0D; 52 | 53 | @EruptField( 54 | views = @View(title = "商品状态"), 55 | edit = @Edit(title = "商品状态", notNull = true, boolType = @BoolType(trueText = "上架", falseText = "下架"), search = @Search) 56 | ) 57 | private Boolean status; 58 | 59 | @Column(length = 10_485_760) 60 | @EruptField( 61 | views = @View(title = "商品描述", type = ViewType.HTML), 62 | edit = @Edit(title = "商品描述", type = EditType.HTML_EDITOR) 63 | ) 64 | private String description; 65 | 66 | @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) 67 | @JoinColumn(name = "goods_id") 68 | @EruptField( 69 | edit = @Edit(title = "商品型号", type = EditType.TAB_TABLE_ADD) 70 | ) 71 | private Set goodsSpecs; 72 | 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/model/mall/Coupon.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.model.mall; 2 | 3 | import xyz.erupt.annotation.Erupt; 4 | import xyz.erupt.annotation.EruptField; 5 | import xyz.erupt.annotation.sub_field.Edit; 6 | import xyz.erupt.annotation.sub_field.EditType; 7 | import xyz.erupt.annotation.sub_field.View; 8 | import xyz.erupt.annotation.sub_field.sub_edit.DateType; 9 | import xyz.erupt.annotation.sub_field.sub_edit.InputType; 10 | import xyz.erupt.annotation.sub_field.sub_edit.ReferenceTreeType; 11 | import xyz.erupt.annotation.sub_field.sub_edit.Search; 12 | import xyz.erupt.jpa.model.BaseModel; 13 | 14 | import jakarta.persistence.Entity; 15 | import jakarta.persistence.ManyToOne; 16 | import jakarta.persistence.Table; 17 | 18 | import java.time.LocalDateTime; 19 | import java.util.Date; 20 | 21 | /** 22 | * @author YuePeng 23 | * date 2020/12/11 13:29 24 | */ 25 | @Erupt(name = "优惠券管理") 26 | @Table(name = "mall_goods_coupon") 27 | @Entity 28 | public class Coupon extends BaseModel { 29 | 30 | @EruptField( 31 | views = @View(title = "名称"), 32 | edit = @Edit(title = "名称", notNull = true, search = @Search, inputType = @InputType(fullSpan = true)) 33 | ) 34 | private String name; 35 | 36 | @EruptField( 37 | views = @View(title = "金额"), 38 | edit = @Edit(title = "金额", notNull = true, search = @Search) 39 | ) 40 | private Double price; 41 | 42 | @EruptField( 43 | views = @View(title = "商品金额满多少可用"), 44 | edit = @Edit(title = "商品金额满多少可用", notNull = true, search = @Search) 45 | ) 46 | private Double priceMax; 47 | 48 | @EruptField( 49 | views = @View(title = "发行量"), 50 | edit = @Edit(title = "发行量", notNull = true, search = @Search(vague = true)) 51 | ) 52 | private Integer maxCount; 53 | 54 | @EruptField( 55 | views = @View(title = "颜色", template = "'
'"), 56 | edit = @Edit(title = "颜色", notNull = true, inputType = @InputType(type = "color")) 57 | ) 58 | private String color; 59 | 60 | @EruptField( 61 | views = @View(title = "生效时间"), 62 | edit = @Edit(title = "生效时间", notNull = true, dateType = @DateType(type = DateType.Type.DATE_TIME)) 63 | ) 64 | private LocalDateTime startTime; 65 | 66 | @EruptField( 67 | views = @View(title = "失效时间"), 68 | edit = @Edit(title = "失效时间", notNull = true, dateType = @DateType(type = DateType.Type.DATE_TIME)) 69 | ) 70 | private LocalDateTime endTime; 71 | 72 | @ManyToOne 73 | @EruptField( 74 | views = @View(title = "指定类别商品可用", column = "name"), 75 | edit = @Edit(title = "指定类别商品可用", desc = "不选择全场可用", type = EditType.REFERENCE_TREE, search = @Search, referenceTreeType = @ReferenceTreeType(pid = "parent.id")) 76 | ) 77 | private GoodsCategory category; 78 | 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/model/blog/Pictures.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.model.blog; 2 | 3 | import xyz.erupt.annotation.Erupt; 4 | import xyz.erupt.annotation.EruptField; 5 | import xyz.erupt.annotation.fun.DataProxy; 6 | import xyz.erupt.annotation.sub_erupt.LinkTree; 7 | import xyz.erupt.annotation.sub_erupt.Power; 8 | import xyz.erupt.annotation.sub_field.Edit; 9 | import xyz.erupt.annotation.sub_field.EditType; 10 | import xyz.erupt.annotation.sub_field.View; 11 | import xyz.erupt.annotation.sub_field.ViewType; 12 | import xyz.erupt.annotation.sub_field.sub_edit.Search; 13 | import xyz.erupt.core.prop.EruptProp; 14 | import xyz.erupt.upms.model.base.HyperModel; 15 | 16 | import jakarta.annotation.Resource; 17 | import jakarta.persistence.Entity; 18 | import jakarta.persistence.ManyToOne; 19 | import jakarta.persistence.Table; 20 | import jakarta.persistence.Transient; 21 | 22 | import javax.imageio.ImageIO; 23 | import java.awt.image.BufferedImage; 24 | import java.io.File; 25 | import java.io.FileInputStream; 26 | import java.io.IOException; 27 | 28 | /** 29 | * @author YuePeng 30 | * date 2020-05-28 31 | */ 32 | @Erupt( 33 | name = "图片管理", 34 | dataProxy = Pictures.class, 35 | power = @Power(edit = false), 36 | linkTree = @LinkTree(dependNode = true, field = "picturesCategory") 37 | ) 38 | @Table(name = "blog_picture") 39 | @Entity 40 | public class Pictures extends HyperModel implements DataProxy { 41 | 42 | @EruptField( 43 | views = { 44 | @View(title = "缩略图", type = ViewType.IMAGE) 45 | }, 46 | edit = @Edit(title = "图片地址", notNull = true, type = EditType.ATTACHMENT) 47 | ) 48 | private String filePath; 49 | 50 | @EruptField( 51 | views = @View(title = "大小", template = "(value/1024/1024).toFixed(2) + 'MB'") 52 | ) 53 | private Integer sizes; 54 | 55 | @EruptField( 56 | views = @View(title = "宽度"), 57 | edit = @Edit(title = "宽度", show = false, search = @Search(vague = true)) 58 | ) 59 | private Integer width; 60 | 61 | @EruptField( 62 | views = @View(title = "高度"), 63 | edit = @Edit(title = "高度", show = false, search = @Search(vague = true)) 64 | ) 65 | private Integer height; 66 | 67 | @EruptField( 68 | views = { 69 | @View(title = "备注") 70 | }, 71 | edit = @Edit(title = "图片备注", type = EditType.TEXTAREA) 72 | ) 73 | private String remark; 74 | 75 | @ManyToOne 76 | private PicturesCategory picturesCategory; 77 | 78 | @Transient 79 | @Resource 80 | private EruptProp eruptProp; 81 | 82 | @Override 83 | public void beforeAdd(Pictures pictures) { 84 | File file = new File(eruptProp.getUploadPath() + pictures.filePath); 85 | try { 86 | BufferedImage bufferedImage = ImageIO.read(new FileInputStream(file)); 87 | pictures.setHeight(bufferedImage.getHeight()); 88 | pictures.setWidth(bufferedImage.getWidth()); 89 | pictures.setSizes((int) file.length()); 90 | } catch (IOException e) { 91 | e.printStackTrace(); 92 | } 93 | } 94 | 95 | 96 | public Integer getSizes() { 97 | return sizes; 98 | } 99 | 100 | public void setSizes(Integer sizes) { 101 | this.sizes = sizes; 102 | } 103 | 104 | public Integer getWidth() { 105 | return width; 106 | } 107 | 108 | public void setWidth(Integer width) { 109 | this.width = width; 110 | } 111 | 112 | public Integer getHeight() { 113 | return height; 114 | } 115 | 116 | public void setHeight(Integer height) { 117 | this.height = height; 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/model/blog/Blog.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.model.blog; 2 | 3 | import xyz.erupt.annotation.Erupt; 4 | import xyz.erupt.annotation.EruptField; 5 | import xyz.erupt.annotation.sub_erupt.LinkTree; 6 | import xyz.erupt.annotation.sub_field.Edit; 7 | import xyz.erupt.annotation.sub_field.EditType; 8 | import xyz.erupt.annotation.sub_field.View; 9 | import xyz.erupt.annotation.sub_field.ViewType; 10 | import xyz.erupt.annotation.sub_field.sub_edit.*; 11 | import xyz.erupt.upms.model.base.HyperModel; 12 | 13 | import jakarta.persistence.*; 14 | 15 | /** 16 | * @author YuePeng 17 | * date 2020/12/15 12:06 18 | */ 19 | @Erupt( 20 | name = "博客管理", 21 | linkTree = @LinkTree(field = "blogCategory") 22 | ) 23 | @Table(name = "blog_article") 24 | @Entity 25 | public class Blog extends HyperModel { 26 | 27 | @EruptField( 28 | views = { 29 | @View(title = "标题图", type = ViewType.IMAGE) 30 | }, 31 | edit = @Edit(title = "标题图", notNull = true, type = EditType.ATTACHMENT, 32 | attachmentType = @AttachmentType(type = AttachmentType.Type.IMAGE)) 33 | ) 34 | private String image; 35 | 36 | @EruptField( 37 | views = @View(title = "标题"), 38 | edit = @Edit(title = "标题", notNull = true, search = @Search(vague = true), inputType = @InputType(fullSpan = true)) 39 | ) 40 | private String name; 41 | 42 | // @EruptField( 43 | // views = @View(title = "简介", type = ViewType.HTML), 44 | // edit = @Edit(title = "简介", notNull = true, search = @Search(vague = true), inputType = @InputType(fullSpan = true)) 45 | // ) 46 | // private String intro; 47 | 48 | @EruptField( 49 | views = @View(title = "是否原创"), 50 | edit = @Edit(title = "是否原创", notNull = true) 51 | ) 52 | private Boolean original; 53 | 54 | @EruptField( 55 | views = @View(title = "是否发布"), 56 | edit = @Edit(title = "是否发布", notNull = true) 57 | ) 58 | private Boolean publish; 59 | 60 | @EruptField( 61 | views = @View(title = "推荐等级"), 62 | edit = @Edit(title = "推荐等级", notNull = true, type = EditType.CHOICE, 63 | choiceType = @ChoiceType(vl = { 64 | @VL(value = "0", label = "正常"), 65 | @VL(value = "10", label = "一级推荐"), 66 | @VL(value = "20", label = "二级推荐"), 67 | @VL(value = "30", label = "三级推荐") 68 | })) 69 | ) 70 | private Integer recommendedLevel; 71 | 72 | @ManyToOne 73 | @EruptField( 74 | views = @View(title = "分类", column = "name"), 75 | edit = @Edit(title = "分类", notNull = true, type = EditType.REFERENCE_TREE) 76 | ) 77 | private BlogCategory blogCategory; 78 | 79 | @EruptField( 80 | views = @View(title = "标签", template = "value&&value.replace(/\\|/g,' | ')"), 81 | edit = @Edit(title = "标签", notNull = true, type = EditType.TAGS, 82 | tagsType = @TagsType(fetchHandler = BlogTagHandler.class) 83 | ) 84 | ) 85 | private String tag; 86 | 87 | @Column(length = 10_485_760) 88 | @EruptField( 89 | views = @View(title = "内容", type = ViewType.HTML), 90 | edit = @Edit(title = "内容", notNull = true, type = EditType.HTML_EDITOR) 91 | ) 92 | private String content; 93 | 94 | @EruptField( 95 | views = @View(title = "备注"), 96 | edit = @Edit(title = "备注", type = EditType.TEXTAREA) 97 | ) 98 | private String remark; 99 | 100 | @EruptField( 101 | views = @View(title = "点击数") 102 | ) 103 | private Integer clickNum = 0; //需要通过前端接口向数据库写入! 104 | 105 | } 106 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/model/Article.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.model; 2 | 3 | import xyz.erupt.annotation.Erupt; 4 | import xyz.erupt.annotation.EruptField; 5 | import xyz.erupt.annotation.sub_erupt.Power; 6 | import xyz.erupt.annotation.sub_field.Edit; 7 | import xyz.erupt.annotation.sub_field.EditType; 8 | import xyz.erupt.annotation.sub_field.View; 9 | import xyz.erupt.annotation.sub_field.ViewType; 10 | import xyz.erupt.annotation.sub_field.sub_edit.AttachmentType; 11 | import xyz.erupt.annotation.sub_field.sub_edit.BoolType; 12 | import xyz.erupt.annotation.sub_field.sub_edit.Search; 13 | import xyz.erupt.upms.model.base.HyperModel; 14 | 15 | import jakarta.persistence.Column; 16 | import jakarta.persistence.Entity; 17 | import jakarta.persistence.Lob; 18 | import jakarta.persistence.Table; 19 | 20 | /** 21 | * Created by liyuepeng on 2019-09-18. 22 | */ 23 | @Erupt(name = "文章发布", 24 | power = @Power(importable = true, export = true), 25 | orderBy = "Article.topUp desc" 26 | ) 27 | @Entity 28 | @Table(name = "demo_article") 29 | public class Article extends HyperModel { 30 | 31 | @EruptField( 32 | views = @View(title = "封面图"), 33 | edit = @Edit(title = "封面图", type = EditType.ATTACHMENT, 34 | attachmentType = @AttachmentType(type = AttachmentType.Type.IMAGE, maxLimit = 3)) 35 | ) 36 | private String pic; 37 | 38 | @EruptField( 39 | views = @View(title = "标题"), 40 | edit = @Edit(title = "标题", notNull = true, search = @Search(vague = true)) 41 | ) 42 | private String title; 43 | 44 | @EruptField( 45 | views = @View(title = "置顶"), 46 | edit = @Edit(title = "置顶", notNull = true, search = @Search) 47 | ) 48 | private Boolean topUp = false; 49 | 50 | @EruptField( 51 | views = @View(title = "发布状态"), 52 | edit = @Edit(title = "发布状态", notNull = true, boolType = @BoolType(trueText = "发布", falseText = "草稿"), search = @Search) 53 | ) 54 | private Boolean publish; 55 | 56 | @Column(length = 10_485_760) 57 | @EruptField( 58 | views = @View(title = "内容(UEditor)", type = ViewType.HTML, export = false), 59 | edit = @Edit(title = "内容(UEditor)", type = EditType.HTML_EDITOR, notNull = true) 60 | ) 61 | private String content; 62 | 63 | @Column(length = 5000) 64 | @EruptField( 65 | views = @View(title = "备注"), 66 | edit = @Edit(title = "备注", type = EditType.TEXTAREA) 67 | ) 68 | private String remark; 69 | 70 | 71 | public String getPic() { 72 | return pic; 73 | } 74 | 75 | public void setPic(String pic) { 76 | this.pic = pic; 77 | } 78 | 79 | public String getTitle() { 80 | return title; 81 | } 82 | 83 | public void setTitle(String title) { 84 | this.title = title; 85 | } 86 | 87 | public Boolean getTopUp() { 88 | return topUp; 89 | } 90 | 91 | public Boolean getPublish() { 92 | return publish; 93 | } 94 | 95 | public void setPublish(Boolean publish) { 96 | this.publish = publish; 97 | } 98 | 99 | public String getContent() { 100 | return content; 101 | } 102 | 103 | public void setContent(String content) { 104 | this.content = content; 105 | } 106 | 107 | public String getRemark() { 108 | return remark; 109 | } 110 | 111 | public void setRemark(String remark) { 112 | this.remark = remark; 113 | } 114 | 115 | @Override 116 | public String toString() { 117 | return "Article{" + 118 | "pic='" + pic + '\'' + 119 | ", title='" + title + '\'' + 120 | ", topUp=" + topUp + 121 | ", publish=" + publish + 122 | ", content='" + content + '\'' + 123 | ", remark='" + remark + '\'' + 124 | '}'; 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 3.5.6 9 | 10 | 11 | 12 | jar 13 | 14 | com.example 15 | erupt-example 16 | 0.0.1-SNAPSHOT 17 | Erupt Example project for Spring Boot 18 | 19 | 20 | 17 21 | 1.13.1 22 | 23 | 24 | 25 | 26 | 27 | org.springframework.boot 28 | spring-boot-starter-test 29 | test 30 | 31 | 32 | mysql 33 | mysql-connector-java 34 | 8.0.29 35 | 36 | 37 | 38 | 39 | xyz.erupt 40 | erupt-admin 41 | ${erupt.version} 42 | 43 | 44 | 45 | xyz.erupt 46 | erupt-web 47 | ${erupt.version} 48 | 49 | 50 | 51 | 52 | 53 | xyz.erupt 54 | erupt-cloud-server 55 | ${erupt.version} 56 | 57 | 58 | 59 | xyz.erupt 60 | erupt-job 61 | ${erupt.version} 62 | 63 | 64 | 65 | xyz.erupt 66 | erupt-generator 67 | ${erupt.version} 68 | 69 | 70 | 71 | xyz.erupt 72 | erupt-monitor 73 | ${erupt.version} 74 | 75 | 76 | 77 | xyz.erupt 78 | erupt-magic-api 79 | ${erupt.version} 80 | 81 | 82 | 83 | xyz.erupt 84 | erupt-ai 85 | ${erupt.version} 86 | 87 | 88 | 89 | xyz.erupt 90 | erupt-websocket 91 | ${erupt.version} 92 | 93 | 94 | 95 | xyz.erupt 96 | erupt-tpl 97 | ${erupt.version} 98 | 99 | 100 | 101 | xyz.erupt 102 | erupt-tpl-ui.element-ui 103 | ${erupt.version} 104 | 105 | 106 | 107 | org.apache.velocity 108 | velocity-engine-core 109 | 2.3 110 | 111 | 112 | 113 | 114 | 115 | 116 | org.springframework.boot 117 | spring-boot-maven-plugin 118 | 119 | 120 | 121 | 122 | 123 | 124 | nexus-aliyun 125 | nexus-aliyun 126 | http://maven.aliyun.com/nexus/content/repositories/central 127 | 128 | true 129 | 130 | 131 | false 132 | 133 | 134 | 135 | 136 | 137 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/model/Component.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.model; 2 | 3 | import com.example.demo.handler.AutoCompleteHandlerImpl; 4 | import com.example.demo.handler.ComponentDataProxy; 5 | import xyz.erupt.annotation.Erupt; 6 | import xyz.erupt.annotation.EruptField; 7 | import xyz.erupt.annotation.sub_field.Edit; 8 | import xyz.erupt.annotation.sub_field.EditType; 9 | import xyz.erupt.annotation.sub_field.View; 10 | import xyz.erupt.annotation.sub_field.sub_edit.*; 11 | import xyz.erupt.jpa.model.BaseModel; 12 | 13 | import jakarta.persistence.Entity; 14 | import jakarta.persistence.ManyToOne; 15 | import jakarta.persistence.Table; 16 | import jakarta.persistence.Transient; 17 | import java.time.LocalDate; 18 | import java.time.LocalDateTime; 19 | import java.util.Date; 20 | 21 | /** 22 | * @author liyuepeng 23 | * @date 2020-02-29 24 | */ 25 | @Erupt( 26 | name = "组件示例", 27 | dataProxy = ComponentDataProxy.class //事件代理,非常有用的功能 ! 28 | ) 29 | @Table(name = "demo_component") 30 | @Entity 31 | public class Component extends BaseModel { 32 | 33 | @EruptField( 34 | views = @View(title = "文本"), 35 | edit = @Edit(title = "文本", search = @Search(vague = true)) 36 | ) 37 | private String input; 38 | 39 | @EruptField( 40 | views = @View(title = "数字"), 41 | edit = @Edit(title = "数字", search = @Search(vague = true)) 42 | ) 43 | private Double number1; 44 | 45 | @EruptField( 46 | views = @View(title = "数字滑块"), 47 | edit = @Edit(title = "数字滑块", type = EditType.SLIDER) 48 | ) 49 | private Integer slider; 50 | 51 | @EruptField( 52 | views = @View(title = "布尔"), 53 | edit = @Edit(title = "布尔", search = @Search) 54 | ) 55 | private Boolean bool; 56 | 57 | @EruptField( 58 | views = @View(title = "自动完成"), 59 | edit = @Edit(title = "自动完成", search = @Search(vague = true), type = EditType.AUTO_COMPLETE, 60 | autoCompleteType = @AutoCompleteType(handler = AutoCompleteHandlerImpl.class)) 61 | ) 62 | private String autoComplete; 63 | 64 | @EruptField( 65 | views = @View(title = "颜色选择"), 66 | edit = @Edit(title = "颜色选择", search = @Search(vague = true), inputType = @InputType(type = "color")) 67 | ) 68 | private String color; 69 | 70 | @EruptField( 71 | views = @View(title = "周选择器"), 72 | edit = @Edit(title = "周选择器", search = @Search(vague = true), inputType = @InputType(type = "week")) 73 | ) 74 | private String weekInput; 75 | 76 | @ManyToOne 77 | @EruptField( 78 | edit = @Edit(title = "文章选择", type = EditType.REFERENCE_TABLE, 79 | referenceTableType = @ReferenceTableType(label = "title")) 80 | ) 81 | private Article article; 82 | 83 | @ManyToOne 84 | @EruptField( 85 | edit = @Edit(title = "多对一树", search = @Search, type = EditType.REFERENCE_TREE, 86 | referenceTreeType = @ReferenceTreeType(id = "id", label = "name", pid = "parent.id")) 87 | ) 88 | private TreeView tree; 89 | 90 | @EruptField( 91 | views = @View(title = "标签选择"), 92 | edit = @Edit(title = "标签选择", search = @Search, type = EditType.TAGS) 93 | ) 94 | private String tags; 95 | 96 | @Transient 97 | @EruptField( 98 | edit = @Edit(title = "时间选择", type = EditType.DIVIDE) 99 | ) 100 | private String dateDiv; 101 | 102 | @EruptField( 103 | views = @View(title = "日期"), 104 | edit = @Edit(title = "日期", type = EditType.DATE, dateType = @DateType(type = DateType.Type.DATE), search = @Search(vague = true)) 105 | ) 106 | private LocalDate date1; 107 | 108 | @EruptField( 109 | views = @View(title = "时间日期"), 110 | edit = @Edit(title = "时间日期", type = EditType.DATE, dateType = @DateType(type = DateType.Type.DATE_TIME), search = @Search(vague = true)) 111 | ) 112 | private LocalDateTime dateTime; 113 | 114 | @EruptField( 115 | views = @View(title = "时间"), 116 | edit = @Edit(title = "时间", type = EditType.DATE, dateType = @DateType(type = DateType.Type.TIME), search = @Search) 117 | ) 118 | private String time; 119 | 120 | @EruptField( 121 | views = @View(title = "周"), 122 | edit = @Edit(title = "周", type = EditType.DATE, dateType = @DateType(type = DateType.Type.WEEK), search = @Search) 123 | ) 124 | private String week; 125 | 126 | @EruptField( 127 | views = @View(title = "月"), 128 | edit = @Edit(title = "月", type = EditType.DATE, dateType = @DateType(type = DateType.Type.MONTH), search = @Search) 129 | ) 130 | private String month; 131 | 132 | @EruptField( 133 | views = @View(title = "年"), 134 | edit = @Edit(title = "年", type = EditType.DATE, dateType = @DateType(type = DateType.Type.YEAR), search = @Search) 135 | ) 136 | private String year; 137 | 138 | @EruptField( 139 | views = @View(title = "过去时间"), 140 | edit = @Edit(title = "过去时间", type = EditType.DATE, dateType = @DateType(pickerMode = DateType.PickerMode.HISTORY), search = @Search) 141 | ) 142 | private String history; 143 | 144 | @EruptField( 145 | views = @View(title = "未来时间"), 146 | edit = @Edit(title = "未来时间", type = EditType.DATE, dateType = @DateType(pickerMode = DateType.PickerMode.FUTURE), search = @Search) 147 | ) 148 | private String feature; 149 | 150 | public void setInput(String input) { 151 | this.input = input; 152 | } 153 | 154 | public void setNumber1(Double number1) { 155 | this.number1 = number1; 156 | } 157 | 158 | public void setColor(String color) { 159 | this.color = color; 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

logo

2 |

Erupt Framework   🚀   框架演示代码

3 |

零前端代码,几行 Java 注解,搞定后台管理系统

4 |

https://www.erupt.xyz

5 | 6 | --- 7 | 8 |

9 | Erupt Framework 10 | jdk 8+ 11 | license Apache 2.0 12 | Gitee star 13 | Gitee fork 14 | GitHub stars 15 | GitHub forks 16 | size 17 |

18 | 19 |

20 | Github 仓库   |   21 | Gitee 仓库   |   22 | 官方网站   |   23 | 贡献指南   |   24 | 在线体验   |   25 | 使用文档 26 |

27 | 28 |

29 | QQ交流群:821389129 🔥 30 |

31 | 32 | ### 使用方法: 33 | 34 | 1. 前往 src/main/resources/application.yml 修改数据库连接配置 35 | 2. 前往 src/main/java/DemoApplication 运行main方法即可(无需sql文件,表结构自动创建) 36 | 3. src/main/resources/application.yml 其他配置 37 | 38 | 默认用户名密码: erupt / erupt 39 | 40 | ### 将model下的类添加到菜单: 41 | 42 | 启动成功后,前往系统管理 → 菜单维护 → 新增,将已定义好的演示类添加到菜单中,填写数据如下: 43 | 44 | | 菜单名称 | 菜单类型 | 类型值(类名) | 描述 | 45 | |-------------|------|---------------------------------|---------------------------------------| 46 | | 入门示例 | 表格 | Simple | | 47 | | 文章管理 | 表格 | Article | | 48 | | 树示例 | 树 | TreeView | | 49 | | 组件示例 | 表格 | Component | 各类组件与事件代理使用方法 | 50 | | 复杂示例 🌟 | 表格 | Complex | 动态下拉列表与定义按钮等功能(内含多个高级功能,建议仔细研究) | 51 | | 按钮权限 | 按钮 | ComplexBtn | 控制 Complex '多行操作'的按钮权限 | 52 | | **服务层逻辑扩展** | 表格 | CurdDemo | @DataProxy(扩展CURD) | 53 | | ---- | ---- | ---- | ---- | 54 | | 链接 | 链接 | https://www.erupt.xyz | | 55 | | 新页面 | 新页签 | https://github.com/erupts/erupt | | 56 | | 自定义页面 | 模板 | erupt.html | 自定义页面 | 57 | | velocity | 模板 | velocity.vm | Velocity服务端渲染的页面 | 58 | | freemarker | 模板 | freemarker.ftl | Freemarker服务端渲染的页面 | 59 | | thymeleaf | 模板 | thymeleaf.html | Thymeleaf服务端渲染的页面(请提前导入thymeleaf jar) | 60 | | ---- | ---- | ---- | ---- | 61 | | 博客管理 | 表格 | Blog | | 62 | | 博客类型 | 树 | BlogCategory | | 63 | | 博客标签 | 树 | BlogTag | | 64 | | 友情链接 | 表格 | FriendlyLink | | 65 | | ---- | ---- | ---- | ---- | 66 | | 商品管理 | 表格 | Goods | | 67 | | 商品分类 | 树 | GoodsCategory | | 68 | | 优惠券管理 | 表格 | Coupon | | 69 | 70 | **配置项说明** 71 | > 编码:确保唯一即可,建议是字母 72 | 73 | ### 常见问题 74 | 75 | + 如果图片上传失败请前往 application.yml 修改 erupt.uploadPath 配置 76 | + 地图组件无法使用请前往 app.js 修改 eruptSiteConfig.amapKey 的值 77 | + 继承HyperModel的作用,可帮助管理,创建时间,修改时间,修改人,更新人字段 78 | 79 | ### 目录说明 80 | 81 | ```lua 82 | erupt-example 83 | ├── src 84 | ├── main.java -- 源码 85 | └── com.example.demo -- 包名 86 | ├── ExampleApplication -- 入口类 87 | ├── action -- 自定义页面数据绑定与路由转换器 88 | ├── handler 89 | ├── AutoCompleteHandlerImpl -- 自动完成示例 90 | ├── ComponentDataProxy -- 事件代理代码示例 91 | └── OperationHandlerImpl -- 操作按钮处理类 92 | └── model 93 | ├── blog -- 博客示例包 94 | ├── mall -- 商城示例包 95 | ├── Article -- 文章示例 96 | ├── Complex -- 复杂示例包 97 | ├── Component -- 组件示例 98 | ├── Simple -- 基本示例 99 | ├── CurdDemo -- 自定义 service 层示例 100 | └── TreeView -- 树视图 101 | ├── test.java -- 测试包 102 | └── com.example.demo -- 包名 103 | └── ExampleApplicationTests -- 包含调用 ArticleRepository 演示代码,直接点击运行单个方法即可 104 | └── resources -- 配置包 105 | ├── application.yml -- 后台配置 106 | ├── tpl 107 | ├── erupt.html -- 自定义页面 108 | └── xxxx.html -- 使用模板引擎渲染 109 | └── public 110 | ├── app.css -- 前端样式 111 | ├── app.js -- 前端配置 112 | ├── favicon.ico -- 网站图标 113 | └── home.html -- 首页样式 114 | └── pom.xml -- 依赖配置 115 | ``` -------------------------------------------------------------------------------- /src/main/java/com/example/demo/model/complex/Complex.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.model.complex; 2 | 3 | import com.example.demo.model.Article; 4 | import com.example.demo.model.complex.fun.ComplexDataProxy; 5 | import com.example.demo.model.complex.fun.OperationHandlerImpl; 6 | import xyz.erupt.annotation.Erupt; 7 | import xyz.erupt.annotation.EruptField; 8 | import xyz.erupt.annotation.expr.ExprBool; 9 | import xyz.erupt.annotation.fun.ChoiceFetchHandler; 10 | import xyz.erupt.annotation.fun.VLModel; 11 | import xyz.erupt.annotation.sub_erupt.*; 12 | import xyz.erupt.annotation.sub_field.*; 13 | import xyz.erupt.annotation.sub_field.sub_edit.*; 14 | import xyz.erupt.jpa.model.BaseModel; 15 | import xyz.erupt.toolkit.handler.SqlChoiceFetchHandler; 16 | import xyz.erupt.upms.handler.DictCodeChoiceFetchHandler; 17 | import xyz.erupt.upms.handler.ViaMenuValueCtrl; 18 | 19 | import jakarta.persistence.*; 20 | import java.util.ArrayList; 21 | import java.util.List; 22 | import java.util.Set; 23 | 24 | /** 25 | * @author YuePeng 26 | * date 2023-10-08. 27 | */ 28 | @Erupt( 29 | name = "复杂示例", 30 | desc = "复杂示例: erupt", 31 | power = @Power(export = true, importable = true), 32 | dataProxy = ComplexDataProxy.class, 33 | drills = { 34 | @Drill(title = "下钻", link = @Link(joinColumn = "id", linkErupt = Complex.class, linkCondition = "1 = 1 and Complex.bool = true")) 35 | }, 36 | rowOperation = { 37 | @RowOperation( 38 | title = "单行操作", 39 | operationHandler = OperationHandlerImpl.class, 40 | ifExpr = "item.bool", 41 | callHint = "", 42 | ifExprBehavior = RowOperation.IfExprBehavior.DISABLE, 43 | mode = RowOperation.Mode.SINGLE, 44 | icon = "fa fa-toggle-on" 45 | ), 46 | @RowOperation( 47 | title = "多行操作", 48 | eruptClass = ComplexDialog.class, 49 | operationHandler = OperationHandlerImpl.class 50 | ), 51 | @RowOperation( 52 | title = "按钮操作", 53 | tip = "不依赖任何数据即可执行", 54 | mode = RowOperation.Mode.BUTTON, 55 | operationHandler = OperationHandlerImpl.class, 56 | eruptClass = ComplexDialog.class, 57 | show = @ExprBool(exprHandler = ViaMenuValueCtrl.class, params = "ComplexBtn"), 58 | icon = "fa fa-google-wallet" 59 | ), 60 | @RowOperation(type = RowOperation.Type.TPL, mode = RowOperation.Mode.MULTI, 61 | tpl = @Tpl(path = "/tpl/operation.ftl", engine = Tpl.Engine.FreeMarker, width = "80%"), 62 | title = "自定义模板", 63 | icon = "fa fa-pagelines" 64 | ) 65 | }, 66 | orderBy = "id", 67 | layout = @Layout(tableLeftFixed = 1) 68 | ) 69 | @Table(name = "demo_complex_pro") 70 | @Entity 71 | public class Complex extends BaseModel implements ChoiceFetchHandler, Readonly.ReadonlyHandler { 72 | 73 | @EruptField( 74 | views = @View(title = "颜色", sortable = true), 75 | edit = @Edit(title = "颜色", search = @Search, type = EditType.COLOR, notNull = true) 76 | ) 77 | private String color; 78 | 79 | @EruptField( 80 | views = @View(title = "布尔", sortable = true), 81 | edit = @Edit(title = "布尔", search = @Search) 82 | ) 83 | private Boolean bool = true; 84 | 85 | @EruptField( 86 | views = @View(title = "SQL选择"), 87 | edit = @Edit( 88 | search = @Search, 89 | title = "SQL选择", type = EditType.CHOICE, desc = "下拉值为动态获取", 90 | choiceType = @ChoiceType( 91 | anewFetch = true, 92 | fetchHandler = SqlChoiceFetchHandler.class, 93 | // dependField = "bool", 94 | // dependExpr = "dependValue == vl.value", 95 | fetchHandlerParams = {"select id,name from e_upms_menu where type = 'table'", "100000"} 96 | )) 97 | ) 98 | private String sqlChoice; 99 | 100 | @EruptField( 101 | views = @View(title = "字典项选择"), 102 | edit = @Edit( 103 | search = @Search, 104 | title = "字典项选择", type = EditType.CHOICE, desc = "动态获取字典项的值", 105 | choiceType = @ChoiceType( 106 | fetchHandler = DictCodeChoiceFetchHandler.class, 107 | fetchHandlerParams = {"code", "10000"} 108 | )) 109 | ) 110 | private String fromDict; 111 | 112 | @EruptField( 113 | views = @View(title = "封面图", sortable = true), 114 | edit = @Edit(title = "封面图", type = EditType.ATTACHMENT, readonly = @Readonly(exprHandler = Complex.class), 115 | attachmentType = @AttachmentType(type = AttachmentType.Type.IMAGE, maxLimit = 3)) 116 | ) 117 | private String img; 118 | 119 | @EruptField( 120 | views = @View(title = "RADIO"), 121 | edit = @Edit( 122 | search = @Search(vague = true), 123 | title = "RADIO", type = EditType.CHOICE, desc = "值为动态获取", 124 | choiceType = @ChoiceType( 125 | anewFetch = true, 126 | type = ChoiceType.Type.RADIO, 127 | fetchHandler = Complex.class 128 | )) 129 | ) 130 | private String radio; 131 | 132 | @OneToOne(cascade = CascadeType.ALL) 133 | @EruptField( 134 | views = @View(title = "扩展表姓名", column = "name"), 135 | edit = @Edit(title = "扩展表定义", type = EditType.COMBINE) 136 | ) 137 | private ComplexExt complexExt; 138 | 139 | 140 | @Column(length = 10_485_760) 141 | @EruptField( 142 | views = @View(title = "Python代码", type = ViewType.CODE), 143 | edit = @Edit(title = "Python代码编辑器", type = EditType.CODE_EDITOR, codeEditType = @CodeEditorType(language = "python")) 144 | ) 145 | private String code; 146 | 147 | @ManyToMany 148 | @JoinTable( 149 | name = "demo_complex_article", 150 | joinColumns = @JoinColumn(name = "complex_id", referencedColumnName = "id"), 151 | inverseJoinColumns = @JoinColumn(name = "article_id", referencedColumnName = "id")) 152 | @EruptField( 153 | views = @View(title = "多对多,关联多篇文章"), 154 | edit = @Edit(title = "多对多,关联多篇文章", type = EditType.TAB_TABLE_REFER, 155 | referenceTableType = @ReferenceTableType(label = "title")) 156 | ) 157 | private Set
articleTab; 158 | 159 | @OneToMany(cascade = CascadeType.ALL) 160 | @JoinColumn(name = "complex_id") 161 | @EruptField( 162 | edit = @Edit(title = "一对多新增", type = EditType.TAB_TABLE_ADD) 163 | ) 164 | private Set complexTab; 165 | 166 | @Override 167 | public List fetch(String[] params) { 168 | List list = new ArrayList<>(); 169 | int c = 65; 170 | for (int i = 0; i < 20; i++) { 171 | list.add(new VLModel(i + "", (char) (c + i) + " → " + (char) (c + i + 5) + " → " + (char) (c + i + 10), i % 2 == 0)); 172 | } 173 | return list; 174 | } 175 | 176 | @Override 177 | public boolean add(boolean add, String[] params) { 178 | return true; 179 | } 180 | 181 | @Override 182 | public boolean edit(boolean edit, String[] params) { 183 | return false; 184 | } 185 | 186 | public String getColor() { 187 | return color; 188 | } 189 | 190 | public void setColor(String color) { 191 | this.color = color; 192 | } 193 | 194 | public String getCode() { 195 | return code; 196 | } 197 | 198 | public void setCode(String code) { 199 | this.code = code; 200 | } 201 | } 202 | --------------------------------------------------------------------------------