EasyBoot是一个追求易学、易用、易扩展的快速开发框架。
EasyBoot内主要是基础的功能和平台。
EasyPlugins项目里面主要包含一些扩展插件
EasyStarter简单的示例启动项目
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>easyboot</artifactId>
<groupId>com.rankeiot.easy</groupId>
<version>1.1-SNAPSHOT</version>
</parent>
<groupId>yourgroupId</groupId>
<artifactId>youartifactId</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<repositories>
<repository>
<id>rankeiot-public-central</id>
<name>central</name>
<url>https://rankeiot-maven.pkg.coding.net/repository/public/central/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>rankeiot-public-central</id>
<name>central</name>
<url>https://rankeiot-maven.pkg.coding.net/repository/public/central/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
<dependencies>
<dependency>
<groupId>com.rankeiot.easy</groupId>
<artifactId>easy-vue</artifactId>
</dependency>
<dependency>
<groupId>com.rankeiot.easy</groupId>
<artifactId>easy-dev</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.rankeiot.easy</groupId>
<artifactId>easy-platform</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
<includeSystemScope>true</includeSystemScope>
</configuration>
</plugin>
</plugins>
</build>
</project>
启动后打开浏览器进入 http://localhost:8080
目前只支持了mysql,当然sqltoy本身是适配了多数据库的。填写完数据库信息后点确定即可进行数据库的初始化。初始化完成后会在项目目录下生成application-dev.yml文件。 可将application-dev.yml移动到src/main/resources目录下面,这样打包后运行不需要重新配置。也可以将application-dev.yml放置与jar包同一目录(工作目录) 初始化完成后不出意外的化,我们会看到下面的界面
进入系统后我们会看到一个非常干净的首页。可通过新建文件 src/main/resources/static/home.vue 来覆盖首页,其他页面也可以通过这种方式覆盖。
到这里基本的系统已经跑起来了。
建议使用IDEA进行开发,根据Maven的profile配置,IDEA会在项目打开的时候会显示对于的配置选项。EasyBoot开发依赖数据库设计,当设计好数据库后,我们可以从系统中直接导入表模型进行代码生成。
开发的时候,maven默认选择了dev这个profile。在打包的时候应该选择prod,maven会根据参数替换application.yml中的配置,并去掉开发和接口api模块进行打包
在开发模式下(profile=dev),进入http://localhost:8080,选择代码生成器进入下面菜单。通过导入数据库中以及设计好的数据库表的方式,我们可以导入模型,生成对应代码。数据库表设计时,请添加必要的表注释及字段注释。
Easy Boot后端采用SpringBoot和sqltoy进行开发
Easy Boot按照业务划分包模块,可在模块中配置模块的业务菜单,固定配置项,字典项等
对于需要独立出来的模块,需要进行下面的定义
//可参考com.rankeiot.platform.PlatformModule
@Configuration
public class DemoModule implements Module {
public void start(ApplicationContext context) {
//注册菜单
//regMenu(TestMenu.class);
}
}
//按spring自动组件的要求,新建文件 /sources/META-INF/spring.factories,加入:
//org.springframework.boot.autoconfigure.EnableAutoConfiguration=模块完整类名,如:com.rankeiot.platform.PlatformModule
Easy Framework使用注解方式来声明权限
import com.rankeiot.core.anno.Menu;
import com.rankeiot.core.anno.Permission;
//这里声明了菜单以及权限
@Menu(value = "测试", icon = "icon-file", id = TestMenu.ID)
public interface TestMenu {
String ID = "Demo";
@Menu(value = "示例", path = "test/demo.vue", icon = "icon-file")
String DEMO = ID + ".demo";
// demo增删改权限
@Permission(value = "新增", parent = DEMO)
String DEMO_ADD = DEMO + ".add";
@Permission(value = "修改", parent = DEMO)
String DEMO_EDIT = DEMO + ".edit";
@Permission(value = "删除", parent = DEMO)
String DEMO_DELETE = DEMO + ".delete";
}
/**
*
* 示例 @Auth 表示需要登录,@Auth(string)表示调用该方法需要的权限,也可指定所需角色(role)
* 当传入多个权限或者角色时,表示有当中任意一个条件满足即可调用该方法
* 以下@Api和ApiOperation注解为Swagger注解,使用Swagger注解的Controller才会出现在API文档中
* 除此外,Controller写法与常规SpringBoot Controller相同
* */
@Api(tags="学生")
@Auth
@RestController
@RequestMapping("demo")
@RequiredArgsConstructor
public class DemoController {
final SqlToyLazyDao dao;
/**
* 新增学生
*/
@ApiOperation("新增学生")
@Auth(StuMenu.STUDENT_ADD)
@PostMapping("add")
public Resp add(@Valid @RequestBody Student student){
dao.save(student);
return Resp.ok();
}
/**
* 删除学生
*/
@ApiOperation("删除学生")
@Auth(StuMenu.STUDENT_DELETE)
@Transactional
@PostMapping("delete")
public Resp delete(List<Integer> ids){
// dao.loadAll(students);
List<Student> students = CollectionUtil.map(ids,Student::new);
dao.deleteAll(students);
return Resp.ok();
}
/**
* 更新学生
*/
@ApiOperation("更新学生")
@Auth(StuMenu.STUDENT_EDIT)
@PostMapping("save")
public Resp save(@Valid @RequestBody Student student){
dao.update(student);
return Resp.ok();
}
/**
* 获取学生
*/
@ApiOperation("获取学生详细")
@Auth(StuMenu.STUDENT)
@GetMapping("detail")
public Resp<Student> detail(Integer id){
Student student=dao.load(new Student(id));
return Resp.of(student);
}
/**
* 获取学生列表
*/
@ApiOperation("列出学生")
@Auth(StuMenu.STUDENT)
@PostMapping("list")
public Resp<Map> list(QueryPage query){
Page result = dao.findPageBySql(query.page(),"student_list",query.getParams());
return Resp.of(result);
}
/**
* 导出学生
*/
@ApiOperation("导出学生")
@Auth(StuMenu.STUDENT)
@PostMapping(value="export",produces = "application/vnd.ms-excel")
public ResponseEntity<StreamingResponseBody> export(QueryParams query){
return Resp.export("学生" + DateUtil.format(new Date(), "yyMMdd") + ".xlsx"
, out -> {
ExcelStreamExporter exporter = new ExcelStreamExporter(out);
dao.fetchStream(query.getQueryExecutor("student_list").resultType(Student.class), exporter);
});
}
/**
* 导入学生
*/
@ApiOperation("导入学生")
@Auth(StuMenu.STUDENT_ADD)
@Transactional
@PostMapping("import")
public Resp importData(MultipartFile file) throws IOException {
if(file==null){
Resp.fail("未上传文件");
}
ExcelBatchImporter importer=new ExcelBatchImporter(file.getInputStream(), Student.class);
importer.start((batchData,lastIndex)->{
dao.saveAll(batchData);
});
return Resp.ok();
}
}
import com.rankeiot.core.config.ControlType;
import com.rankeiot.core.config.IConfigItem;
import com.rankeiot.core.config.Item;
/**
* 系统配置项,通过enum+@Item注解的方式声明配置项,配置项的key值为enum类名+条目名,
* 比如下面这个DemoName的Key值为DemoConfig.DemoName。该可以值作为数据库中t_config表的sn列
* 或者前端调用时使用,如: _config[key]
* 当front=true时,表示可以在前端页面中直接使用_config[key]获取对应key的配置值
* 固定配置项需要在模块配置中注册,在任意代码初始化的地方调用注册方法即可,一般是在main方法或Configuration类中调用
* ConfigManager.register("配置所属分组",DemoConfig.class);
* 也可在Module的start 方法中调用
* regConfigs(DemoConfig.class);
*/
public enum DemoConfig implements IConfigItem {
@Item(title="测试配置",defaultValue = "Hello",front = true)
DemoName;
//后端获取配置项的值
public static void demo(){
String str= DemoConfig.DemoName.value().asString();
Date date= DemoConfig.DemoName.value().asDate();
// ...
}
}
import com.rankeiot.core.dict.IFixedDict;
import com.rankeiot.core.dict.Title;
/**
* 在任意代码初始化的地方调用注册方法,一般是在main方法或Configuration类中调用
* FixedDictManager.regFixedDict(Gender.class);
* 会把该固定字典项注册到系统,在系统的字典菜单中可以看到该字典
* 也可在Module的start 方法中调用
* regFixedDict(Gender.class);
*/
/**
* 字典常规写法,表示
*
* 性别:Gender
* 男:M
* 女:F
*/
@Title("性别")
@Getter
@RequiredArgsConstructor
public enum Gender implements ITitleFixedDict {
M("男"),
F("女");
final String title;
}
/**
* 字典,可以指定特定值,但是无法直接通过字面量转换为Enum,如下:表示
* 性别:Gender
* 男:1
* 女:0
*/
@Title("性别")
@Getter
@RequiredArgsConstructor
public enum Gender implements ITitleFixedDict {
M("1","男"),
F("0","女");
final String value;
final String title;
}
/**
* 字典常规写法,效果同示例1,表示
*
* 性别:Gender
* 男:M
* 女:F
*/
@Title("性别")
public enum Gender implements IFixedDict {
@Title("男") //Male
M,
@Title("女")//Female
F
}
后端通过定义Excel Bean的方式来实现Excel的导入导出
import com.rankeiot.core.anno.Excel;
@Data
public class ExportVo{
@Excel("姓名")
String name;
@Excel("出生日期")
@JsonFormat(pattern="yyyy年MM月dd日")
Date brith;
//也可通过 @Translate() 注解处理格式
}
public class ExportImportController{
//在spring 的controller中通过 ResponseEntity 导出
public ResponseEntity<StreamingResponseBody> exportExcel(QueryParams query){
return Resp.export("导出文件名.xlsx",out->{
ExcelStreamExporter exporter=new ExcelStreamExporter(out);
//可设置数据转换翻译
//exporter.translate("field",Translator)
QueryExecutor qe=new QueryExecutor("export sql id",(Map<String, Object>) query.getParams());
qe.resultType(ExportVo.class);
dao.fetchStream(qe,exporter);
});
}
//简单导入
public void importExcel(MultipartFile mf){
ExcelBatchImporter bi=new ExcelBatchImporter(mf.getInputStream(),ExportVo.class);
//可设置数据转换翻译
//exporter.translate("field",Translator)
//默认500条一批数据读入,如果需要全部读入内存后处理,可在下面缓存后处理
//bi.setBatchSize(500);
bi.start((batch,index)->{
//
});
}
}
<FileImport to="xxx/import">
<Button icon="jeicon-upload" color="primary">导入文件</Button>
</FileImport>
//文件上传方法
@PostMapping("xx/import")
public SseEmitter importFile(@RequestParam("file") MultipartFile file) {
UserInfo user=Current.user();
return FrontendProcess.create(p -> {
p.info("文件上传完成,导入中...");
ExcelBatchImporter<ExpendRecordImportVo> bi = new ExcelBatchImporter(file.getInputStream(), ExpendRecordImportVo.class);
bi.start((list, idx) -> {
//list就是处理好的数据列表
});
p.info("导入完成...");
});
}
//数据模板
@Data
//指定起始行
@ExcelTemplate(startRow = 2)
public static class ExpendRecordImportVo {
//指定字段列
@Excel(columnName = "A")
private String projectName;
}
pom.xml中加入依赖,在后台配置界面配置好阿里云短信服务的相关配置后,可以通过com.rankeiot.platform.service.SmsService进行相关的短信发送操作
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>dysmsapi20170525</artifactId>
</dependency>
easy-platform.jar 中的uni/api目录下内置了两个uni-app的后端接口文件。把它放入uni项目中,配置后端路径。 支持前端用户登录,用户信息获取,ajax请求自动处理token 同时在后端配置设置中配置好对应的小程序ID和secretKey可使用小程序的登录和手机快捷登录
EasyBoot 前端开发框架基于Vue3,采用RequireJS结合自定义loader做vue文件加载。 采用es-module-shims做vue和js,css文件加载。 在调试模式下,loader直接加载.vue模板文件,通过loader将模板动态编译为js模块。打包发布时,vue模板文件会被打包为压缩混淆的js文件,loader直接加载js文件,减少响应的数据量,加快响应速度。需要注意的是,前端所有文件应放在文件夹resources/static/下面,该目录对应了web请求的根目录。
本文默认前端掌握ES6及Vue3基础知识
EasyBoot 完全支持RequireJS,可以按照RequireJS文档配置自定义的三方库。
使用es-module-shims实现了ES modules的加载,
Vue UI库方面,EasyBoot 集成了好用的HeyUI,同时也集成了其他常用的Vue库,如果要引入自定义三方库,三方库需要支持Vue3及RequireJS(AMD规范,可通过配置shim方式配置常用库,如:Jquery) ,另外,EasyBoot支持加载以.mjs结尾的js模块文件,和以.less结尾的less文件,mjs文件为满足esm模块需求的js文件,EasyBoot将其转换为了CMD模块,支持大多数的esm语法,支持部分ES6语法,支持程度视浏览器兼容性而定,EasyBoot没有除了做压缩混淆外,没有做额外的语法支持
//hello.mjs 满足esm语法
function hello(){
}
export default{
hello
}
//引用
import {hello} from './hello'
/**demo.less**/
.some{
.color{
color:red;
}
}
/**
* html中引用
* <link href='./demo.css'/>
*/
/**
* js文件中引用
* require('./demo.css')
* mjs或者vue模块中引用
* require('./demo.css') 或 import './demo.css'
*/
framework中封装了常用的一些方法
//ajax 相关,ajax相关操作除特殊说明外,均返回promise
import {ajax} from 'framework'
//get 请求
let promise=ajax.get(url,{...params})
//post 请求
let promise=ajax.post(url,{...params})
//put 请求
let promise=ajax.put(url,{...params})
//delete 请求
let promise=ajax.delete(url,{...params})
//post 以表单方式提交
ajax.formPost(url,{...params})
//post 上传单个,
let params={
file:File
}
//或者多个文件
let params={
file:[...files]
}
//或者 命名的多个文件,需要后端对应属性名
let params={
file:file,
file1:file1
}
ajax.upload(url,{...params})
/**
* 文件下载,也可以用window.open(url)等方式下载文件,
* 若需要登录用户授权,可以添加url参数 _token=sessionStorage._token
*/
ajax.download(url,params={},method="POST")
//ajax方式的文件下载
downloadA(path, fileName = "", params = {}, method = 'GET')
/**
* 加载带缓存数据,可直接用于vue数据绑定,
* @param url
* @param defaultValue
* @returns VueRef
*/
ajax.data(url, defaultValue)
/**
* 通过url创建数据集,可用于datatable,select等数据绑定
*/
ajax.createDs(uri, pageAble = false)
//数据集使用
const ds=ajax.createDs('someurl',true)
//数据集中的数据,可以直接绑定到datatable上
ds.data
//设置附加查询参数,也可直接绑定到vue查询控件上
ds.params.param1='value1'
//加载数据,也可通过该方法重新加载数据
ds.load()
//设置数据转换,每次数据加载后会通过这方法转换数据
ds.transformer((v)=>v);
//清空数据
ds.clean()
//设置自定义数据
ds.putData([...data])
//可在数据加载前修改查询参数
ds.on('beforeLoad',(params)=>undefined)
//可在数据加载后修改响应数据
ds.on('load',(data)=>undefined)
//数据加载错误时调用
ds.on('error',(error)=>undefined)
//其他用法
import {uuid,format,hasPermission,hasRole,mapState,mapActions} from 'framework'
//生成一个随机id 如:'1gk2o6462g94p92'
uuid()
//数据格式化,两种调用方式 '1.00'
format(1,"####.00")
const fmt=format("####.00");
fmt(1)
//日期格式化,两种调用方式 '2022-12-12'
format(Date.now(),"yyyy-MM-dd")
const fmt=format("yyyy-MM-dd");
fmt(Date.now())
//判断用户是否有某个权限/角色
hasPermission('some.priv')
hasRole('some.role')
//引用vue store,也可直接使用 vuex
const [user,theme]=mapState(['user','theme'])
const loadUserInfo = mapActions(['loadUserInfo'])
//framework util中包含了一些数据操作的方法
import {util} from 'framework'
/**
* 数组转换为map
* @param list 数组
* @param getId
* @param getValue
* @returns {{}}
*/
util.asMap(list, getId = (it, idx) => idx, getValue = it => it)
/**
* 数组转换为树,parentId为0,false,null的或者获取不到parent的节点转为根节点
* @param list
* @param getId
* @param getParentId
* @param getValue
* @returns {*[]}
*/
util.asTree(list, getId = it => it, getParentId = it => null, getValue = it => it)
/**
* 获取一个对象中的多个值
*/
util.fields(obj, fields)
let obja={a:1,b:2,c:3}
//obj2={a:1,b:2}
let obj2=util.fields(obj,"a,b")
//折叠/展开字段。由于现在后台本身支持类似的解码,所以本方法使用较少
// 输出 {a:"1,2,3",b:"1,2,3"}
util.fold({a:[1,2,3],b:[1,2,3]}, "a,b")
// 输出 {a:[1,2,3],b:[1,2,3]}
util.unfold({a:"1,2,3",b:"1,2,3"}, "a,b")
//清除对象的数据,输出: {a:null,b:null}
util.clean({a:1,b:1})
/**
* 导入Excel文件到浏览器
* <FileInput accept=".xlsx" @change="doImport">
* <Button>Excel导入浏览器</Button>
* </FileInput>
*/
function doImport(file){
//是否作为对象数组导出,以第一行为key值,默认为false,导出为二维数组
let asObj=true
util.importExcel(file,asObj).then(r =>{
console.log(r)
})
}
import {useEvent,useStore,toRef,useDlg,getToken} from 'framework'
//事件总线
//定义事件总线,其中server为服务器推送事件
let events=userEvent("server")
//派发事件,server总线中的事件由后台派发com.rankeiot.platform.service.ServerEventPushService 派发
events.dispatchEvent("eventname",data)
//添加监听
events.addEventListener("eventname",listener)
//全局状态,第二个参数为默认值,可以是直接值,函数,异步函数,返回值为ref类型
let theme=useStore('theme','green')
//将直接值,函数返回值,异步函数响应值转换为ref
let data=toRef(ajax.get('xxxx'))
/**
* 封装内联对话框需要数据和方法
* dlg.isOpen
* dlg.data
* dlg.open(opendata=null)
* dlg.close()
* dlg.submit()
*/
let dlg=useDlg({},function onSubmit(){
})
//获取用户认证所需token
let token = getToken()
EasyBoot添加了部分Vue组件
<!--数据集合,与framework中createDs方法对应,具体使用方法产考生成的代码中的list页面-->
<DataSet url="some/url">
<template #default="table">
<Table :datas="table.data" :loading="table.loading"/>
</template>
</DataSet>
<!--组件对话框,基于HeyUI中的Modal组件实现,具体使用方法产考生成的代码中的list页面-->
<Dialog href="dialog/url"></Dialog>
<!--Chart 基于Echarts的图表实现,options为Echarts中的options-->
<EChart :options="options"/>
<!--基于 [Chart.js](https://www.chartjs.org) 轻便好用-->
<Chart :options="options"/>
<!--FileDrop 文件拖入组件,拖入文件后会触发事件,可以用于表格中拖入文件上传等-->
<FileDrop accet=".png,.jpg" @drop="onFileDrop">
把图片文件拖入到这里
</FileDrop>
<!--FileInput 类似于<input type='file'/>-->
<FileInput v-model="form.file" @change="onFileChange">
<!--可在这里自定义显示-->
</FileInput>
<!--ImageViewer 图片预览-->
<ImageViewer :urlList="['img1.png','img2.jpg']" :initialIndex="0" v-model="show"/>
<!--代码编辑器 基于Monaco Editor-->
<MonacoEditor v-model="source" language="javascript" @change="onchange" @save="onCtrAndSPressed"/>
<!--RichTextEditor 富文本编辑器 基于wangEditor-->
<RichTextEditor v-model="source"/>
<!--FileUploader 文件上传组件,类似于HeyUI的Uploader,支持文件拖拽上传,文件拖拽排序。除v-model外,其他属性为非必需属性-->
<FileUploader v-model="files"
accept=".jpg,.png"
:readonly="false"
:limit="-1"
uploadPath="file/upload"
deletePath="file/delete"
@delete="onFileItemDelete">
</FileUploader>
<!-- 高德地图 经纬度绑定-->
<AMapInput v-model:lngLat="lngLat"/>
<!--二维码 https://www.jsdelivr.com/package/npm/qrcode.vue-next-->
<QRCode value="需要显示的值"/>
用于获取后台数据的封装
<template>
<DataSet url="some/url">
<template #default="table">
<Input v-model="table.params.queryParamA"/>
<Table :datas="table.data" :loading="table.loading"/>
</template>
</DataSet>
</template>
参数
参数 | 类型 | 默认值 | 说明 |
---|---|---|---|
url | string | 获取数据的URL地址 | |
pageable | boolean | false | 是否分页 |
pageSize | number | 10 | 每页数据长度 |
method | string | post | 数据提交方式 |
lazy | boolean | false | lazy为true时,需要手动调用 load 方法载入数据 |
transform | Function | (data)=>data | 数据转换方法,用于在显示前处理数据 |
事件
事件 | 参数 | 说明 |
---|---|---|
beforeLoad | param | 在请求前被调用,传入请求参数param,可通过修改param的值修改请求 |
load | data | 在请求完成后,数据展示前被调用 ,传入参数为响应的数据,可在这里修改展示数据 |
afterLoad | data | 在数据转换完成后被调用,传入转换处理过的数据 |
属性方法,通常通过 ref 的方式获取到其引用,同时slot中具有相同属性
方法/属性 | 类型 | 说明 |
---|---|---|
load | ()=>{} | 载入数据 |
reload | ()=>{} | 重新载入数据,相较于load,reload会把分页设置为第一页 |
setData | (data)=>{} | 手动设置其数据 |
setSort | ({prop,type})=>{} | 设置排序,prop为排序的字段,type为 desc/asc 排序类型 |
params | Object | 当前的查询参数 ,在slot中可用于绑定查询参数 |
pagination | {page,size} | 当前的分页状态,可用于绑定分页条 |
loading | ref(bool) | 当前数据加载状态,可用于绑定数据加载装状态 |
用于打开对话框,用HeyUI Modal实现,继承了Modal弹出框组件所有属性 不通处在于这里指定的url所对应组件为懒加载
<template>
<Dialog href="path/dlg.vue" ref="dlgRef" hasDivider hasCloseIcon>
<template #header>对话框标题</template>
<template #footer="dlg">
<Button @click="dlg.cancel">取消</Button>
<Button :loading="dlg.loading" color="primary" @click="dlg.submit">确认</Button>
</template>
</Dialog>
</template>
<script setup>
import {ref} from 'vue'
const dlgRef=ref()
await dlgRef.value.open()
</script>
dlg.vue
<templage>
</templage>
<script setup>
//通过params获取 对话框open方法传入的参数
const {params,dialog} = defineProps({
params: Object,
dialog:Object
})
//设置数据提交监听
dialog.onSubmit(()=>{
//状态修改为数据提交中
dialog.loading(true)
//处理完成后把数据作为open方法的返回值
dialog.success("some data")
//处理失败时把数据状态设置回来
dialog.loading( false)
})
//dialog.cancel() 关闭对话框
</script>
options 即为Echarts的options
<Chart :options="options"/>
<template>
<FileInput accept=".xlsx" @change="onFile">
<Button> 测试Excel导入</Button>
</FileInput>
</template>
<script setup>
import xlsx from 'xlsx'
const reader = new FileReader();
reader.readAsBinaryString(file);
reader.onload = function (e) {
const data = e.target.result;
const excel = xlsx.read(data, {
type: 'binary'
});
const result = [];
for (let i = 0; i < excel.SheetNames.length; i++) {
const newData = xlsx.utils.sheet_to_json(excel.Sheets[excel.SheetNames[i]]);
result.push(...newData)
}
//获取到导入的数据
console.log(JSON.stringify(result));
}
</script>
//过期时间(s) 默认1800s
let expire = 1800;
//到期时间
let time = parseInt(Date.now() / 1000) + expire;
//到期时间转换为7位36进制的字符串,不足位数以0补全
let t = leftPad(time.toString(36), '0', 7);
//后端应用签名,一般为启动类类名,可通过配置 spring.application.name 这个配置项/环境变量来设置
let appSign='com.ranke.xxx.xxApplication'
//userType为一位字符串一般为U或M,表示用户类型为用户或者会员,用户后端寻找用户
let value=userType+username
//盐,用于验证签名,md5以hex形式展示
let salt=md5hex(username + "$" + password) + appSign
let v = value + time + salt;
//最后的token,长度为7+24+n,其中base64算法为urlbase64,即结果中的‘+/’会变为‘-_’
let token=t + md5base64(v) + urlbase64(value)
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>easyboot</artifactId>
<groupId>com.rankeiot.easy</groupId>
<version>${lastVersion}</version>
</parent>
<groupId>com.your.groupid</groupId>
<artifactId>yourartifact</artifactId>
<version>1.0-SNAPSHOT</version>
<repositories>
<repository>
<id>rankeiot-public-central</id>
<name>central</name>
<url>https://rankeiot-maven.pkg.coding.net/repository/public/central/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>rankeiot-public-central</id>
<name>central</name>
<url>https://rankeiot-maven.pkg.coding.net/repository/public/central/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
</snapshots>
</pluginRepository>
</pluginRepositories>
<dependencies>
<dependency>
<groupId>com.rankeiot.easy</groupId>
<artifactId>easy-vue</artifactId>
</dependency>
<dependency>
<groupId>com.rankeiot.easy</groupId>
<artifactId>easy-platform</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
public static void main(String[] args) {
new PlatformApplication().start(args);
}
应用插件配置说明 插件目录结构,将插件的jar文件及依赖jar(主框架已经包含的不需要再次添加)文件和插件描述文件plugin.json一起打为zip包(没有二级目录)
/
├── plugin.json
├── lib1.jar
├── lib2.jar
├── ...
描述文件,其中id,version,framework为必填项,其他为选填项
{
"id":"plugin-id", //插件ID,必填
"version":"1.0-SNAPSHOT",//插件版本号,必填
"framework": "1.1-SNAPSHOT", //主框架版本,必填
"name":"插件名称",
"author":"EasyBoot",
"description":"一个插件",
"homepage":"https://gitee.com/desire1/app_manager",
"depends":[
{"id":"other-plugin","version":"1.0.0"} //其他插件依赖
]
}
应用功能文件结构
/root
├── pom.xml
├── src
│ ├── main
│ │ ├── java
│ │ │ └── yourpackage
│ │ │ └── YourModule.java
│ │ └── resources
│ │ ├── META-INF
│ │ │ └── spring
│ │ │ └── org.springframework.boot.autoconfigure.AutoConfiguration.imports
│ │ ├── static
│ │ │ └── moduledir
│ │ │ └── somefunction.vue
│ │ ├── application-plugin.yml //可选的插件默认配置文件,按spirng的规范来配置
│ │ └── plugin.json
│ └── test
│ ├── java
│ │ └── yourpackage
│ │ └── MainTestApp.java
│ └── resources
│ └── application.yml //测试用配置文件
MainTestApp.java
//MainTestApp.java
public static void main(String[] args) {
new PlatformApplication().start(args);
}
plugin.json
{
"id": "${artifactId}",
"version": "${version}",
"framework": "${easy.ver}",
"author": "EasyBoot",
"name": "${name}",
"description": "${description}",
"depends": [
]
}
pom
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>easyboot</artifactId>
<groupId>com.rankeiot.easy</groupId>
<version>${lastVersion}</version>
</parent>
<groupId>com.your.groupid</groupId>
<artifactId>yourartifact</artifactId>
<version>1.0-SNAPSHOT</version>
<name>DemoAPP</name>
<description>
demo app是一个测试接口应用
</description>
<repositories>
<repository>
<id>rankeiot-public-central</id>
<name>central</name>
<url>https://rankeiot-maven.pkg.coding.net/repository/public/central/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>rankeiot-public-central</id>
<name>central</name>
<url>https://rankeiot-maven.pkg.coding.net/repository/public/central/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
</snapshots>
</pluginRepository>
</pluginRepositories>
<dependencies>
<dependency>
<groupId>com.rankeiot.easy</groupId>
<artifactId>easy-vue</artifactId>
</dependency>
<dependency>
<groupId>com.rankeiot.easy</groupId>
<artifactId>easy-platform</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
</dependencies>
<!--插件自动生成配置模板-->
<build>
<plugins>
<!--生成plugin.json-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-resources</id>
<phase>generate-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.outputDirectory}/</outputDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>plugin.json</include>
</includes>
</resource>
</resources>
<delimiters>
<delimiter>${*}</delimiter>
</delimiters>
</configuration>
</execution>
</executions>
</plugin>
<!-- 根据条件配置需要导出的依赖-->
<!--
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib/</outputDirectory>
<includeArtifactIds>
commons-beanutils,commons-text
</includeArtifactIds>
</configuration>
</execution>
<execution>
<id>list-dependencies</id>
<phase>compile</phase>
<goals>
<goal>list</goal>
</goals>
<configuration>
<outputFile>${project.build.directory}/dependency-list.text</outputFile>
</configuration>
</execution>
</executions>
</plugin>
-->
</plugins>
</build>
</project>
应用模块配置类
package com.your.groupid;
//配置类的包名尽量不要与其他模块及框架的包名冲突
@Configuration
public class YourModule implements Module {
public void start(ApplicationContext applicationContext) {
//注册所需的各种功能
//regFixedDict(AppPlatform.class);
//regFixedDict(ResourceType.class);
//regMenu(AppMenu.class);
//regConfigs(AppMgConfig.class);
}
}
插件自动扫描配置
com.your.groupid.YourModule
插件默认配置文件
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。