插件开发
# 开发准备
- 熟悉
Java
- 熟悉
Spring Boot
- 熟悉
Vue3
、JavaScript
(如果涉及到前端的话)
# 目录结构
magic-api-plugin-xxx
├─src
│ ├─console --- 存放前端源码
│ │ ├─src
│ │ │ ├─components --- 存放前端组件信息
│ │ │ ├─i18n --- i18n相关信息
│ │ │ ├─icons --- 图标相关资源
│ │ │ ├─service --- js运行服务
| | | └─magic-api.js --- 前端入口
| | ├─vite.config.js --- 打包配置
| | └─package.json
│ └─main
│ ├─java
│ │ └─org
│ │ └─ssssssss
│ │ └─magicapi
│ │ └─xxx --- 插件后端源码
│ └─resources
│ └─META-INF
│ └─spring.factories --- spring factory配置
└ pom.xml --- pom.xml
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
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>
<groupId>org.ssssssss</groupId>
<artifactId>magic-api-plugins</artifactId>
<version>magic-api-lastest-version</version>
</parent>
<artifactId>magic-api-plugin-xxx</artifactId>
<packaging>jar</packaging>
<name>magic-api-plugin-xxx</name>
<description>magic-api-plugin-xxx</description>
<dependencies>
<!-- 添加你需要加的依赖 -->
</dependencies>
<!-- 如果有前端代码的话,则添加下方配置,如果没有则不需要。 -->
<build>
<plugins>
<!-- npm install && npm run build -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<executions>
<execution>
<id>exec-npm-install</id>
<phase>generate-resources</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>npm</executable>
<arguments>
<argument>install</argument>
</arguments>
<workingDirectory>${basedir}/src/console</workingDirectory>
</configuration>
</execution>
<execution>
<id>exec-npm-run-build</id>
<phase>generate-resources</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>npm</executable>
<arguments>
<argument>run</argument>
<argument>build</argument>
</arguments>
<workingDirectory>${basedir}/src/console</workingDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<id>copy-resource</id>
<phase>generate-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/target/classes/magic-editor/plugins</outputDirectory>
<resources>
<resource>
<directory>${basedir}/src/console/dist</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Java入口
@Configuration
public class MagicAPITaskConfiguration implements MagicPluginConfiguration {
@Override
public Plugin plugin() {
return new Plugin("定时任务");
// 如果有前端的话,需要返回此格式。
// return new Plugin("定时任务", "MagicTask", "magic-task.1.0.0.iife.js");
}
/**
* 注册Controller,如果有的话
*/
@Override
public MagicControllerRegister controllerRegister() {
return (mapping, configuration) -> mapping.registerController(new MagicAPITaskController(configuration));
}
// 在这里你可以定义你需要的Bean。以实现插件机制,关于magic-api支持的,可以查看高级应用中的说明。
}
spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.ssssssss.magicapi.task.starter.MagicAPITaskConfiguration
package.json
{
"name": "magic-test",
"version": "1.0.0",
"main": "magic-api.js",
"scripts": {
"build": "vite build"
},
"devDependencies": {
"vue": "^3.2.31",
"@vitejs/plugin-vue": "^2.2.4",
"vite-plugin-svg-icons": "^1.1.0",
"vite": "^2.8.6"
}
}
vite.config.js
import vue from '@vitejs/plugin-vue'
import viteSvgIcons from 'vite-plugin-svg-icons'
import path from 'path'
import pkg from './package.json'
export default {
base: './',
build: {
minify: false,
cssCodeSplit: true, // 将组件的 style 打包到 js 文件中
outDir: 'dist',
lib: {
target: 'esnext',
formats: ['iife'],
entry: path.resolve(__dirname, 'src/magic-api.js'),
name: 'MagicTask',
fileName: (format) => `magic-task.${pkg.version}.${format}.js`
},
rollupOptions: {
// 确保外部化处理那些你不想打包进库的依赖
external: ['vue'],
output: {
// 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量
globals: {
vue: 'Vue'
}
}
}
},
plugins: [
vue(),
viteSvgIcons({
iconDirs: [path.resolve(process.cwd(), 'src/icons')],
symbolId: 'magic-task-[name]'
}),
]
}
前端入口 magic-api.js
import MagicTask from './service/magic-task.js'
import localZhCN from './i18n/zh-cn.js'
import localEn from './i18n/en.js'
import MagicTaskInfo from './components/magic-task-info.vue'
import 'vite-plugin-svg-icons/register'
export default (opt) => {
const i18n = opt.i18n
// 添加i18n 国际化信息
i18n.add('zh-cn', localZhCN)
i18n.add('en', localEn)
return {
// 左侧资源
resource: [{
// 资源类型,和后端存储结构一致
type: 'task',
// 展示图标
icon: '#magic-task-task', // #开头表示图标在插件中
// 展示名称
title: 'task.name',
// 运行服务
service: MagicTask(opt.bus, opt.constants, i18n.format, opt.Message, opt.request),
}],
// 右侧资源
// datasources: [{
// // 资源类型,和后端存储结构一致
// type: 'redis',
// // 展示图标
// icon: '#magic-redis-redis', // #开头表示图标在插件中
// // 展示标题
// title: 'Redis',
// // 展示名称
// name: i18n.format('redis.name'),
// // 表单组件
// component: MagicDataResourceRedis
// }]
// 底部工具条
toolbars: [{
// 当打开的资源类型为 task 时显示
type: 'task',
// 工具条展示的标题
title: 'task.title',
// 展示图标
icon: 'parameter',
// 对应的组件
component: MagicTaskInfo,
}]
}
}
service.js 左侧资源案例
export default function (bus, constants, $i, Message, request) {
return {
// svg text
getIcon: item => ['TASK', '#9012FE'],
// 任务名称
name: $i('task.name'),
// 脚本语言
language: 'magicscript',
// 执行测试的逻辑
doTest: (opened) => {
opened.running = true
const info = opened.item
const requestConfig = {
baseURL: constants.SERVER_URL,
url: '/task/execute',
method: 'POST',
responseType: 'json',
headers: {},
withCredentials: true
}
bus.$emit(Message.SWITCH_TOOLBAR, 'log')
requestConfig.headers[constants.HEADER_REQUEST_CLIENT_ID] = constants.CLIENT_ID
requestConfig.headers[constants.HEADER_REQUEST_SCRIPT_ID] = opened.item.id
requestConfig.headers[constants.HEADER_MAGIC_TOKEN] = constants.HEADER_MAGIC_TOKEN_VALUE
// 设置断点
requestConfig.headers[constants.HEADER_REQUEST_BREAKPOINTS] = (opened.decorations || []).filter(it => it.options.linesDecorationsClassName === 'breakpoints').map(it => it.range.startLineNumber).join(',')
const fullName = opened.path()
bus.status(`开始测试定时任务「${fullName}」`)
request.sendPost('/task/execute', { id: info.id }, requestConfig).success(res => {
opened.running = false
}).end(() => {
bus.status(`定时任务「${fullName}」测试完毕`)
opened.running = false
})
},
// 是否允许执行测试
runnable: true,
// 是否需要填写路径
requirePath: true,
// 合并
merge: item => item
}
}
右侧资源案例
export default (request, $i, modal, JavaClass)=> {
let findResources
// 设置代码提示
JavaClass.setExtensionAttribute('org.ssssssss.magicapi.mongo.MongoModule', () => {
return findResources && (findResources('mongo')[0]?.children || []).filter(it => it.key).map(it => {
return {
name: it.key,
type: 'org.ssssssss.magicapi.pro.mongo.MongoModule',
comment: it.name
}
}) || []
})
return {
// 注入查找资源的方法
injectResources: fn => findResources = fn,
dialogWidth: '1100px', // 创建数据源的dialog宽度
// 执行测试连接
doTest: info => {
request.sendJson('/datasource/mongo/test', info).success(res => {
if(res === 'ok'){
modal.alert($i('datasource.connected'), $i('datasource.test'))
}else {
modal.alert($i('datasource.connectFailed', res), $i('datasource.test'))
}
})
}
}
}
上次更新: 2023-03-23 13:11:51