mirror of
https://gitee.com/ssssssss-team/magic-boot.git
synced 2025-03-03 22:32:50 +08:00
组件集成到magic-api
This commit is contained in:
parent
61aa570cf2
commit
35da78b14e
82
magic-api-plugin-component/pom.xml
Normal file
82
magic-api-plugin-component/pom.xml
Normal file
@ -0,0 +1,82 @@
|
||||
<?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>
|
||||
<groupId>org.ssssssss</groupId>
|
||||
<artifactId>magic-api-plugins</artifactId>
|
||||
<version>2.0.0</version>
|
||||
<relativePath/>
|
||||
</parent>
|
||||
<artifactId>magic-api-plugin-component</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>magic-api-plugin-component</name>
|
||||
<description>magic-api-plugin-component</description>
|
||||
|
||||
<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>
|
18
magic-api-plugin-component/src/console/package.json
Normal file
18
magic-api-plugin-component/src/console/package.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "magic-component",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"build": "vite build"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"vue": "^3.2.31",
|
||||
"@vitejs/plugin-vue": "^2.2.4",
|
||||
"vite-plugin-svg-icons": "^1.1.0",
|
||||
"vite": "^2.8.6"
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
<template>
|
||||
<div class="magic-component-info">
|
||||
<form>
|
||||
<label>{{ $i('component.form.componentName') }}</label>
|
||||
<magic-input v-model:value="info.name" :placeholder="$i('component.form.placeholder.componentName')" width="250px"/>
|
||||
</form>
|
||||
<div style="flex:1;padding-top:5px;">
|
||||
<magic-textarea v-model:value="info.description" :placeholder="$i('component.form.placeholder.description')"/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { inject } from 'vue'
|
||||
const $i = inject('i18n.format')
|
||||
const info = inject('info')
|
||||
</script>
|
||||
<style scoped>
|
||||
.magic-component-info{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
padding: 5px;
|
||||
}
|
||||
.magic-component-info form{
|
||||
display: flex;
|
||||
}
|
||||
.magic-component-info form label{
|
||||
display: inline-block;
|
||||
width: 75px;
|
||||
height: 22px;
|
||||
line-height: 22px;
|
||||
font-weight: 400;
|
||||
text-align: right;
|
||||
padding: 0 5px;
|
||||
}
|
||||
.magic-component-info form :deep(.magic-textarea){
|
||||
margin: 5px;
|
||||
}
|
||||
</style>
|
14
magic-api-plugin-component/src/console/src/i18n/en.js
Normal file
14
magic-api-plugin-component/src/console/src/i18n/en.js
Normal file
@ -0,0 +1,14 @@
|
||||
export default {
|
||||
component: {
|
||||
title: 'Component Info',
|
||||
name: 'Component',
|
||||
form: {
|
||||
componentName: 'Component Name',
|
||||
description: 'Component Description',
|
||||
placeholder: {
|
||||
componentName: 'Please Enter Component Name',
|
||||
description: 'Please Enter Component Description'
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
14
magic-api-plugin-component/src/console/src/i18n/zh-cn.js
Normal file
14
magic-api-plugin-component/src/console/src/i18n/zh-cn.js
Normal file
@ -0,0 +1,14 @@
|
||||
export default {
|
||||
component: {
|
||||
title: '组件信息',
|
||||
name: '组件',
|
||||
form: {
|
||||
componentName: '组件名称',
|
||||
description: '组件描述',
|
||||
placeholder: {
|
||||
componentName: '请输入组件名称',
|
||||
description: '请输入组件描述'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1647853515880" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1190" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css">@font-face { font-family: feedback-iconfont; src: url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.woff2?t=1630033759944") format("woff2"), url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.woff?t=1630033759944") format("woff"), url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.ttf?t=1630033759944") format("truetype"); }
|
||||
</style></defs><path d="M914.5 653.5c-5.5 0-11 1.1-16 3.3l-0.2 0.1h-0.2L510.2 822.2 122.2 657h-0.2l-0.2-0.1c-5-2.1-10.3-3.3-16-3.3-23.1 0-41.8 19.3-41.8 43.1 0 18 10.7 33.3 25.8 39.8l403.9 172.1 0.4 0.1c10.2 4.4 21.8 4.4 32 0l0.2-0.1c0.1 0 0.1-0.1 0.2-0.1l403.9-172.1c15.1-6.5 25.8-21.8 25.8-39.8 0.1-23.8-18.6-43.1-41.7-43.1z m0-186.5c-7.9-0.2-16 3.2-16 3.2L510.2 635.6 121.8 470.2s-10.3-3.2-16-3.2C82.7 467 64 486.2 64 510c0 17.9 10.7 33.3 25.8 39.7l403.9 172c0.1 0 0.1 0.1 0.2 0.1l0.1 0.1c5 2.1 10.3 3.3 16 3.3 5.7 0 11.1-1.2 16-3.3l0.2-0.1c0.1 0 0.1 0 0.2-0.1l403.9-172c15.1-6.4 25.8-21.8 25.9-39.7 0.1-23.8-18.6-43-41.7-43zM89.8 363.2l403.9 172.1c0.1 0 0.1 0 0.2 0.1l0.1 0.1c5 2.1 10.3 3.2 16 3.2 5.5 0 10.9-1.1 16-3.2l0.2-0.1 0.2-0.1 403.9-172c15.1-6.5 25.8-21.8 25.9-39.7 0-18-10.7-33.3-25.8-39.8L526.5 111.6c-0.1 0-0.1 0-0.2-0.1l-0.2-0.1c-10.2-4.4-21.8-4.4-32 0l-0.1 0.1L89.8 283.7C74.7 290.1 64 305.5 64 323.5c0 17.9 10.7 33.2 25.8 39.7z" p-id="1191" fill="#000000"></path></svg>
|
After Width: | Height: | Size: 1.6 KiB |
35
magic-api-plugin-component/src/console/src/index.js
Normal file
35
magic-api-plugin-component/src/console/src/index.js
Normal file
@ -0,0 +1,35 @@
|
||||
import MagicComponent from './service/magic-component.js'
|
||||
import localZhCN from './i18n/zh-cn.js'
|
||||
import localEn from './i18n/en.js'
|
||||
import MagicComponentInfo from './components/magic-component-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: 'component',
|
||||
// 展示图标
|
||||
icon: '#magic-component-component', // #开头表示图标在插件中
|
||||
// 展示名称
|
||||
title: 'component.name',
|
||||
// 运行服务
|
||||
service: MagicComponent(opt.bus, opt.constants, i18n.format, opt.Message, opt.request),
|
||||
}],
|
||||
// 底部工具条
|
||||
toolbars: [{
|
||||
// 当打开的资源类型为 task 时显示
|
||||
type: 'component',
|
||||
// 工具条展示的标题
|
||||
title: 'component.title',
|
||||
// 展示图标
|
||||
icon: 'parameter',
|
||||
// 对应的组件
|
||||
component: MagicComponentInfo,
|
||||
}]
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
export default function (bus, constants, $i, Message, request) {
|
||||
return {
|
||||
// svg text
|
||||
getIcon: item => ['COMPONENT', '#9012FE'],
|
||||
// 任务名称
|
||||
name: $i('component.name'),
|
||||
// 脚本语言
|
||||
language: 'html',
|
||||
// 默认脚本
|
||||
defaultScript: `<template>
|
||||
|
||||
</template>
|
||||
<script setup>
|
||||
|
||||
</script>
|
||||
<style scoped>
|
||||
|
||||
</style>`,
|
||||
// 是否允许执行测试
|
||||
runnable: false,
|
||||
// 是否需要填写路径
|
||||
requirePath: false,
|
||||
// 合并
|
||||
merge: item => item
|
||||
}
|
||||
}
|
37
magic-api-plugin-component/src/console/vite.config.js
Normal file
37
magic-api-plugin-component/src/console/vite.config.js
Normal file
@ -0,0 +1,37 @@
|
||||
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/index.js'),
|
||||
name: 'MagicComponent',
|
||||
fileName: (format) => `magic-component.${pkg.version}.${format}.js`
|
||||
},
|
||||
rollupOptions: {
|
||||
// 确保外部化处理那些你不想打包进库的依赖
|
||||
external: ['vue'],
|
||||
output: {
|
||||
// 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量
|
||||
globals: {
|
||||
vue: 'Vue'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
vue(),
|
||||
viteSvgIcons({
|
||||
iconDirs: [path.resolve(process.cwd(), 'src/icons')],
|
||||
symbolId: 'magic-component-[name]'
|
||||
}),
|
||||
]
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package org.ssssssss.magicapi.component.model;
|
||||
|
||||
import org.ssssssss.magicapi.core.model.MagicEntity;
|
||||
import org.ssssssss.magicapi.core.model.PathMagicEntity;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class ComponentInfo extends PathMagicEntity {
|
||||
|
||||
/**
|
||||
* 组件描述
|
||||
*/
|
||||
private String description;
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public ComponentInfo copy() {
|
||||
ComponentInfo info = new ComponentInfo();
|
||||
super.copyTo(info);
|
||||
info.setDescription(this.description);
|
||||
return info;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MagicEntity simple() {
|
||||
ComponentInfo info = new ComponentInfo();
|
||||
super.simple(info);
|
||||
return info;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
if (!super.equals(o)) return false;
|
||||
ComponentInfo componentInfo = (ComponentInfo) o;
|
||||
return Objects.equals(id, componentInfo.id) &&
|
||||
Objects.equals(path, componentInfo.path) &&
|
||||
Objects.equals(script, componentInfo.script) &&
|
||||
Objects.equals(name, componentInfo.name) &&
|
||||
Objects.equals(description, componentInfo.description);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id, path, script, name, groupId, description);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
package org.ssssssss.magicapi.component.service;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.ssssssss.magicapi.component.model.ComponentInfo;
|
||||
import org.ssssssss.magicapi.core.exception.InvalidArgumentException;
|
||||
import org.ssssssss.magicapi.core.model.Group;
|
||||
import org.ssssssss.magicapi.core.model.JsonCode;
|
||||
import org.ssssssss.magicapi.core.model.MagicEntity;
|
||||
import org.ssssssss.magicapi.core.model.TreeNode;
|
||||
import org.ssssssss.magicapi.core.service.AbstractPathMagicResourceStorage;
|
||||
import org.ssssssss.magicapi.core.service.MagicResourceService;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class ComponentInfoMagicResourceStorage extends AbstractPathMagicResourceStorage<ComponentInfo> {
|
||||
|
||||
@Override
|
||||
public String folder() {
|
||||
return "component";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<ComponentInfo> magicClass() {
|
||||
return ComponentInfo.class;
|
||||
}
|
||||
|
||||
private boolean strIsEnglish(String word) {
|
||||
boolean sign = true;
|
||||
for (int i = 0; i < word.length(); i++) {
|
||||
if (!(word.charAt(i) >= 'A' && word.charAt(i) <= 'Z')
|
||||
&& !(word.charAt(i) >= 'a' && word.charAt(i) <= 'z')) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void isNameRepeat(List<TreeNode<Group>> groupChildren, String name, String id){
|
||||
groupChildren.stream().forEach(it -> {
|
||||
Group node = it.getNode();
|
||||
List<TreeNode<Group>> chi = it.getChildren();
|
||||
magicResourceService.listFiles(node.getId()).forEach(file -> {
|
||||
if(null != id){
|
||||
if(!file.getId().equals(id) && file.getName().equals(name)){
|
||||
throw new InvalidArgumentException(new JsonCode(9004, "组件名称已存在"));
|
||||
}
|
||||
}else{
|
||||
if(file.getName().equals(name)){
|
||||
throw new InvalidArgumentException(new JsonCode(9004, "组件名称已存在"));
|
||||
}
|
||||
}
|
||||
});
|
||||
if(chi.size() > 0){
|
||||
isNameRepeat(chi, name, id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate(ComponentInfo entity) {
|
||||
if(null == entity.getPath() || entity.getPath().equals("")){
|
||||
entity.setPath(UUID.randomUUID().toString().replace("-", ""));
|
||||
}
|
||||
isNameRepeat(magicResourceService.tree("component").getChildren(), entity.getName(), entity.getId());
|
||||
notBlank(entity.getName(), new JsonCode(9001, "组件名称不能为空"));
|
||||
if(!strIsEnglish(entity.getName())){
|
||||
throw new InvalidArgumentException(new JsonCode(9002, "组件名称必须是英文"));
|
||||
}
|
||||
notBlank(entity.getDescription(), new JsonCode(9003, "组件描述不能为空"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildMappingKey(ComponentInfo info) {
|
||||
return buildMappingKey(info, magicResourceService.getGroupPath(info.getGroupId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requirePath() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package org.ssssssss.magicapi.component.service;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.ssssssss.magicapi.component.model.ComponentInfo;
|
||||
import org.ssssssss.magicapi.core.event.FileEvent;
|
||||
import org.ssssssss.magicapi.core.event.GroupEvent;
|
||||
import org.ssssssss.magicapi.core.service.AbstractMagicDynamicRegistry;
|
||||
import org.ssssssss.magicapi.core.service.MagicResourceStorage;
|
||||
|
||||
public class ComponentMagicDynamicRegistry extends AbstractMagicDynamicRegistry<ComponentInfo> {
|
||||
|
||||
public ComponentMagicDynamicRegistry(MagicResourceStorage<ComponentInfo> magicResourceStorage) {
|
||||
super(magicResourceStorage);
|
||||
}
|
||||
|
||||
@EventListener(condition = "#event.type == 'component'")
|
||||
public void onFileEvent(FileEvent event) {
|
||||
processEvent(event);
|
||||
}
|
||||
|
||||
@EventListener(condition = "#event.type == 'component'")
|
||||
public void onGroupEvent(GroupEvent event) {
|
||||
processEvent(event);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package org.ssssssss.magicapi.component.starter;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.ssssssss.magicapi.component.service.ComponentInfoMagicResourceStorage;
|
||||
import org.ssssssss.magicapi.component.service.ComponentMagicDynamicRegistry;
|
||||
import org.ssssssss.magicapi.core.config.MagicPluginConfiguration;
|
||||
import org.ssssssss.magicapi.core.model.Plugin;
|
||||
|
||||
@Configuration
|
||||
public class MagicAPIComponentConfiguration implements MagicPluginConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public ComponentInfoMagicResourceStorage componentInfoMagicResourceStorage() {
|
||||
return new ComponentInfoMagicResourceStorage();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public ComponentMagicDynamicRegistry componentMagicDynamicRegistry(ComponentInfoMagicResourceStorage componentInfoMagicResourceStorage) {
|
||||
return new ComponentMagicDynamicRegistry(componentInfoMagicResourceStorage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plugin plugin() {
|
||||
return new Plugin("组件", "MagicComponent", "magic-component.1.0.0.iife.js");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.ssssssss.magicapi.component.starter.MagicAPIComponentConfiguration
|
@ -52,6 +52,16 @@
|
||||
<artifactId>sa-token-spring-boot-starter</artifactId>
|
||||
<version>${sa-token.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.ssssssss</groupId>
|
||||
<artifactId>magic-api-plugin-task</artifactId>
|
||||
<version>${magic-api.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.ssssssss</groupId>
|
||||
<artifactId>magic-api-plugin-component</artifactId>
|
||||
<version>${magic-api.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
Loading…
Reference in New Issue
Block a user