forked from github/dataease
perf(X-Pack): 插件管理-前端分布式加载静态资源
This commit is contained in:
parent
f6a8f2b947
commit
54d254e290
@ -1 +1,20 @@
|
|||||||
ALTER TABLE `core_export_task` ADD COLUMN `msg` LONGTEXT NULL COMMENT '错误信息' AFTER `params`;
|
ALTER TABLE `core_export_task`
|
||||||
|
ADD COLUMN `msg` LONGTEXT NULL COMMENT '错误信息' AFTER `params`;
|
||||||
|
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `xpack_plugin`;
|
||||||
|
CREATE TABLE `xpack_plugin`
|
||||||
|
(
|
||||||
|
`id` bigint NOT NULL COMMENT 'ID',
|
||||||
|
`name` varchar(255) NOT NULL COMMENT '插件名称',
|
||||||
|
`icon` longtext NOT NULL COMMENT '图标',
|
||||||
|
`version` varchar(255) NOT NULL COMMENT '版本',
|
||||||
|
`install_time` bigint NOT NULL COMMENT '安装时间',
|
||||||
|
`flag` varchar(255) NOT NULL COMMENT '类型',
|
||||||
|
`developer` varchar(255) NOT NULL COMMENT '开发者',
|
||||||
|
`config` longtext NOT NULL COMMENT '插件配置',
|
||||||
|
`require_version` varchar(255) NOT NULL COMMENT 'DE最低版本',
|
||||||
|
`module_name` varchar(255) NOT NULL COMMENT '模块名称',
|
||||||
|
`jar_name` varchar(255) NOT NULL COMMENT 'Jar包名称',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) COMMENT ='插件表';
|
@ -14,7 +14,7 @@ export default {
|
|||||||
],
|
],
|
||||||
build: {
|
build: {
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
external: id => /de-xpack/.test(id) || /extensions-view-3dpie/.test(id),
|
external: id => /de-xpack/.test(id) || /extensions/.test(id),
|
||||||
output: {
|
output: {
|
||||||
// 用于命名代码拆分时创建的共享块的输出命名
|
// 用于命名代码拆分时创建的共享块的输出命名
|
||||||
chunkFileNames: `assets/chunk/[name]-${pkg.version}-${pkg.name}.js`,
|
chunkFileNames: `assets/chunk/[name]-${pkg.version}-${pkg.name}.js`,
|
||||||
|
@ -1490,25 +1490,6 @@ defineExpose({
|
|||||||
@linkJumpSetOpen="linkJumpSetOpen(item)"
|
@linkJumpSetOpen="linkJumpSetOpen(item)"
|
||||||
@linkageSetOpen="linkageSetOpen(item)"
|
@linkageSetOpen="linkageSetOpen(item)"
|
||||||
>
|
>
|
||||||
<!--如果是图表 则动态获取预存的chart-view数据-->
|
|
||||||
<!-- <PluginComponent
|
|
||||||
v-if="item['isPlugin']"
|
|
||||||
:jsname="item['pluginFlag'] || 'L2NvbXBvbmVudC9pbmRleA=='"
|
|
||||||
class="component"
|
|
||||||
:id="'component' + item.id"
|
|
||||||
:active="item.id === curComponentId"
|
|
||||||
:dv-type="dvInfo.type"
|
|
||||||
:scale="curBaseScale"
|
|
||||||
:style="getComponentStyle(item.style)"
|
|
||||||
:prop-value="item.propValue"
|
|
||||||
:is-edit="true"
|
|
||||||
:view="canvasViewInfo[item.id]"
|
|
||||||
:element="item"
|
|
||||||
:request="item.request"
|
|
||||||
@input="handleInput"
|
|
||||||
:dv-info="dvInfo"
|
|
||||||
:canvas-active="canvasActive"
|
|
||||||
/> -->
|
|
||||||
<component
|
<component
|
||||||
:is="findComponent(item.component)"
|
:is="findComponent(item.component)"
|
||||||
v-if="item.component === 'UserView' || item['isPlugin']"
|
v-if="item.component === 'UserView' || item['isPlugin']"
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
import noLic from './nolic.vue'
|
import noLic from './nolic.vue'
|
||||||
import { ref, useAttrs, onMounted } from 'vue'
|
import { ref, useAttrs, onMounted } from 'vue'
|
||||||
import { execute, randomKey, formatArray } from './convert'
|
import { execute, randomKey, formatArray } from './convert'
|
||||||
import { loadPluginApi, loadDistributed, xpackModelApi } from '@/api/plugin'
|
import { loadPluginApi, xpackModelApi } from '@/api/plugin'
|
||||||
import { useCache } from '@/hooks/web/useCache'
|
import { useCache } from '@/hooks/web/useCache'
|
||||||
import { i18n } from '@/plugins/vue-i18n'
|
import { i18n } from '@/plugins/vue-i18n'
|
||||||
import * as Vue from 'vue'
|
import * as Vue from 'vue'
|
||||||
@ -10,7 +10,7 @@ import axios from 'axios'
|
|||||||
import * as Pinia from 'pinia'
|
import * as Pinia from 'pinia'
|
||||||
import * as vueRouter from 'vue-router'
|
import * as vueRouter from 'vue-router'
|
||||||
import { useEmitt } from '@/hooks/web/useEmitt'
|
import { useEmitt } from '@/hooks/web/useEmitt'
|
||||||
|
import request from '@/config/axios'
|
||||||
const { wsCache } = useCache()
|
const { wsCache } = useCache()
|
||||||
|
|
||||||
const plugin = ref()
|
const plugin = ref()
|
||||||
@ -33,15 +33,12 @@ const generateRamStr = (len: number) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const importProxy = (bytesArray: any[]) => {
|
const importProxy = (bytesArray: any[]) => {
|
||||||
/* const promise = import(
|
|
||||||
`../../../../../../../${formatArray(bytesArray[7])}/${formatArray(bytesArray[8])}/${formatArray(
|
|
||||||
bytesArray[9]
|
|
||||||
)}/${formatArray(bytesArray[10])}/${formatArray(bytesArray[11])}.vue`
|
|
||||||
) */
|
|
||||||
const promise = import(
|
const promise = import(
|
||||||
`../../../../../../../extensions-view-3dpie/${formatArray(bytesArray[8])}/${formatArray(
|
`../../../../../../../extensions/${formatArray(bytesArray[8])}/${formatArray(
|
||||||
bytesArray[9]
|
bytesArray[9]
|
||||||
)}/${formatArray(bytesArray[10])}/${formatArray(bytesArray[11])}.vue`
|
)}/${formatArray(bytesArray[10])}/${formatArray(bytesArray[11])}/${formatArray(
|
||||||
|
bytesArray[12]
|
||||||
|
)}.vue`
|
||||||
)
|
)
|
||||||
promise
|
promise
|
||||||
.then((res: any) => {
|
.then((res: any) => {
|
||||||
@ -53,16 +50,23 @@ const importProxy = (bytesArray: any[]) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getModuleName = () => {
|
||||||
|
const jsPath = window.atob(attrs.jsname.toString())
|
||||||
|
return jsPath.split('/')[0]
|
||||||
|
}
|
||||||
const loadComponent = () => {
|
const loadComponent = () => {
|
||||||
|
const moduleName = getModuleName()
|
||||||
loading.value = true
|
loading.value = true
|
||||||
const byteArray = wsCache.get(`de-plugin-proxy-plugin`)
|
const byteArray = wsCache.get(`de-plugin-proxy-${moduleName}`)
|
||||||
if (byteArray) {
|
if (byteArray) {
|
||||||
importProxy(JSON.parse(byteArray))
|
importProxy(JSON.parse(byteArray))
|
||||||
loading.value = false
|
loading.value = false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const key = generateRamStr(randomKey())
|
const key = generateRamStr(randomKey())
|
||||||
loadPluginApi(key)
|
const moduleNameKey = window.btoa(moduleName)
|
||||||
|
const saltKey = `${key},${moduleNameKey}`
|
||||||
|
loadPluginApi(saltKey)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
let code = response.data
|
let code = response.data
|
||||||
const byteArray = execute(code, key)
|
const byteArray = execute(code, key)
|
||||||
@ -82,7 +86,8 @@ const storeCacheProxy = byteArray => {
|
|||||||
byteArray.forEach(item => {
|
byteArray.forEach(item => {
|
||||||
result.push([...item])
|
result.push([...item])
|
||||||
})
|
})
|
||||||
wsCache.set(`de-plugin-proxy-plugin`, JSON.stringify(result))
|
const moduleName = getModuleName()
|
||||||
|
wsCache.set(`de-plugin-proxy-${moduleName}`, JSON.stringify(result))
|
||||||
}
|
}
|
||||||
const pluginProxy = ref(null)
|
const pluginProxy = ref(null)
|
||||||
const invokeMethod = param => {
|
const invokeMethod = param => {
|
||||||
@ -104,8 +109,9 @@ onMounted(async () => {
|
|||||||
distributed = wsCache.get(key)
|
distributed = wsCache.get(key)
|
||||||
}
|
}
|
||||||
if (distributed) {
|
if (distributed) {
|
||||||
if (window['DEXPack']) {
|
const moduleName = getModuleName()
|
||||||
const xpack = await window['DEXPack'].mapping[attrs.jsname]
|
if (window[moduleName]) {
|
||||||
|
const xpack = await window[moduleName].mapping[attrs.jsname]
|
||||||
plugin.value = xpack.default
|
plugin.value = xpack.default
|
||||||
} else {
|
} else {
|
||||||
window['Vue'] = Vue
|
window['Vue'] = Vue
|
||||||
@ -114,9 +120,10 @@ onMounted(async () => {
|
|||||||
window['vueRouter'] = vueRouter
|
window['vueRouter'] = vueRouter
|
||||||
window['MittAll'] = useEmitt().emitter.all
|
window['MittAll'] = useEmitt().emitter.all
|
||||||
window['I18n'] = i18n
|
window['I18n'] = i18n
|
||||||
loadDistributed().then(async res => {
|
const url = `/xpackComponent/pluginStaticInfo/${moduleName}`
|
||||||
new Function(res.data)()
|
request.get({ url }).then(async res => {
|
||||||
const xpack = await window['DEXPack'].mapping[attrs.jsname]
|
new Function(res.data || res)()
|
||||||
|
const xpack = await window[moduleName].mapping[attrs.jsname]
|
||||||
plugin.value = xpack.default
|
plugin.value = xpack.default
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -173,6 +173,8 @@ service.interceptors.response.use(
|
|||||||
return response
|
return response
|
||||||
} else if (response.config.url.includes('DEXPack.umd.js')) {
|
} else if (response.config.url.includes('DEXPack.umd.js')) {
|
||||||
return response
|
return response
|
||||||
|
} else if (response.config.url.startsWith('/xpackComponent/pluginStaticInfo/extensions-')) {
|
||||||
|
return response
|
||||||
} else {
|
} else {
|
||||||
if (
|
if (
|
||||||
!response?.config?.url.startsWith('/xpackComponent/content') &&
|
!response?.config?.url.startsWith('/xpackComponent/content') &&
|
||||||
|
@ -48,8 +48,8 @@ const anchorPosition = anchor => {
|
|||||||
scrollTo(element.offsetTop)
|
scrollTo(element.offsetTop)
|
||||||
}
|
}
|
||||||
|
|
||||||
const newComponent = (innerType, isPlugin) => {
|
const newComponent = (innerType, staticMap) => {
|
||||||
eventBus.emit('handleNew', { componentName: 'UserView', innerType: innerType, isPlugin })
|
eventBus.emit('handleNew', { componentName: 'UserView', innerType: innerType, staticMap })
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleDragStart = e => {
|
const handleDragStart = e => {
|
||||||
@ -66,14 +66,15 @@ const groupActiveChange = category => {
|
|||||||
}
|
}
|
||||||
const loadPluginCategory = data => {
|
const loadPluginCategory = data => {
|
||||||
data.forEach(item => {
|
data.forEach(item => {
|
||||||
const { category, title, render, chartValue, chartTitle, icon } = item
|
const { category, title, render, chartValue, chartTitle, icon, staticMap } = item
|
||||||
const node = {
|
const node = {
|
||||||
render,
|
render,
|
||||||
category,
|
category,
|
||||||
icon,
|
icon,
|
||||||
value: chartValue,
|
value: chartValue,
|
||||||
title: chartTitle,
|
title: chartTitle,
|
||||||
isPlugin: true
|
isPlugin: true,
|
||||||
|
staticMap
|
||||||
}
|
}
|
||||||
const stack = [...state.chartGroupList]
|
const stack = [...state.chartGroupList]
|
||||||
let findParent = false
|
let findParent = false
|
||||||
@ -128,7 +129,7 @@ const loadPluginCategory = data => {
|
|||||||
:key="chartInfo.title"
|
:key="chartInfo.title"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-on:click="newComponent(chartInfo.value, chartInfo['isPlugin'])"
|
v-on:click="newComponent(chartInfo.value, chartInfo['staticMap'])"
|
||||||
class="item-top"
|
class="item-top"
|
||||||
draggable="true"
|
draggable="true"
|
||||||
:data-id="'UserView&' + chartInfo.value"
|
:data-id="'UserView&' + chartInfo.value"
|
||||||
|
@ -518,8 +518,9 @@ export function findNewComponentFromList(
|
|||||||
componentName,
|
componentName,
|
||||||
innerType,
|
innerType,
|
||||||
curOriginThemes,
|
curOriginThemes,
|
||||||
isPlugin?: boolean
|
staticMap?: object
|
||||||
) {
|
) {
|
||||||
|
const isPlugin = !!staticMap
|
||||||
let newComponent
|
let newComponent
|
||||||
list.forEach(comp => {
|
list.forEach(comp => {
|
||||||
if (comp.component === componentName) {
|
if (comp.component === componentName) {
|
||||||
@ -540,6 +541,9 @@ export function findNewComponentFromList(
|
|||||||
newComponent.label = viewConfig?.title
|
newComponent.label = viewConfig?.title
|
||||||
newComponent.render = viewConfig?.render
|
newComponent.render = viewConfig?.render
|
||||||
newComponent.isPlugin = !!isPlugin
|
newComponent.isPlugin = !!isPlugin
|
||||||
|
if (isPlugin) {
|
||||||
|
newComponent.staticMap = staticMap
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return newComponent
|
return newComponent
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
declare interface ChartPlugin {
|
declare interface ChartPlugin {
|
||||||
isPlugin: boolean
|
isPlugin: boolean
|
||||||
pluginResourceId?: string
|
staticMap?: object
|
||||||
}
|
}
|
||||||
|
@ -391,7 +391,7 @@ export const dvMainStore = defineStore('dataVisualization', {
|
|||||||
render: component.render,
|
render: component.render,
|
||||||
plugin: {
|
plugin: {
|
||||||
isPlugin: component.isPlugin,
|
isPlugin: component.isPlugin,
|
||||||
pluginResourceId: component.pluginResourceId
|
staticMap: component.staticMap
|
||||||
}
|
}
|
||||||
} as unknown as ChartObj
|
} as unknown as ChartObj
|
||||||
// 处理配置项默认值,不同图表的同一配置项默认值不同
|
// 处理配置项默认值,不同图表的同一配置项默认值不同
|
||||||
|
@ -73,10 +73,9 @@ const editStyle = computed(() => {
|
|||||||
|
|
||||||
// 通过实时监听的方式直接添加组件
|
// 通过实时监听的方式直接添加组件
|
||||||
const handleNewFromCanvasMain = newComponentInfo => {
|
const handleNewFromCanvasMain = newComponentInfo => {
|
||||||
const { componentName, innerType, isPlugin } = newComponentInfo
|
const { componentName, innerType, staticMap } = newComponentInfo
|
||||||
if (componentName) {
|
if (componentName) {
|
||||||
const component = findNewComponentFromList(componentName, innerType, curOriginThemes, isPlugin)
|
const component = findNewComponentFromList(componentName, innerType, curOriginThemes, staticMap)
|
||||||
component.isPlugin = !!isPlugin
|
|
||||||
syncShapeItemStyle(component, baseWidth.value, baseHeight.value)
|
syncShapeItemStyle(component, baseWidth.value, baseHeight.value)
|
||||||
component.id = guid()
|
component.id = guid()
|
||||||
component.y = 200
|
component.y = 200
|
||||||
|
@ -1605,7 +1605,7 @@ const deleteChartFieldItem = id => {
|
|||||||
</div>
|
</div>
|
||||||
<plugin-component
|
<plugin-component
|
||||||
v-else-if="view.plugin?.isPlugin"
|
v-else-if="view.plugin?.isPlugin"
|
||||||
jsname="L2NvbXBvbmVudC9lZGl0b3IvaW5kZXg="
|
:jsname="view.plugin.staticMap['editor']"
|
||||||
:view="view"
|
:view="view"
|
||||||
:dimension="state.dimension"
|
:dimension="state.dimension"
|
||||||
:quota="state.quota"
|
:quota="state.quota"
|
||||||
|
@ -762,7 +762,7 @@ const showActionIcons = computed(() => {
|
|||||||
<div v-if="chartAreaShow" style="flex: 1; overflow: hidden">
|
<div v-if="chartAreaShow" style="flex: 1; overflow: hidden">
|
||||||
<plugin-component
|
<plugin-component
|
||||||
v-if="view.plugin?.isPlugin"
|
v-if="view.plugin?.isPlugin"
|
||||||
jsname="L2NvbXBvbmVudC9pbmRleA=="
|
:jsname="view.plugin.staticMap['index']"
|
||||||
:scale="scale"
|
:scale="scale"
|
||||||
:dynamic-area-id="dynamicAreaId"
|
:dynamic-area-id="dynamicAreaId"
|
||||||
:view="view"
|
:view="view"
|
||||||
|
@ -20,4 +20,7 @@ public interface XpackComponentApi {
|
|||||||
|
|
||||||
@GetMapping("/viewPlugins")
|
@GetMapping("/viewPlugins")
|
||||||
List<XpackPluginsViewVO> viewPlugins();
|
List<XpackPluginsViewVO> viewPlugins();
|
||||||
|
|
||||||
|
@GetMapping("/pluginStaticInfo/{moduleName}")
|
||||||
|
void pluginStaticInfo(@PathVariable("moduleName") String moduleName);
|
||||||
}
|
}
|
||||||
|
@ -63,6 +63,7 @@ public class WhitelistUtils {
|
|||||||
|| StringUtils.startsWithAny(requestURI, "/appearance/image/")
|
|| StringUtils.startsWithAny(requestURI, "/appearance/image/")
|
||||||
|| StringUtils.startsWithAny(requestURI, "/share/proxyInfo")
|
|| StringUtils.startsWithAny(requestURI, "/share/proxyInfo")
|
||||||
|| StringUtils.startsWithAny(requestURI, "/xpackComponent/content")
|
|| StringUtils.startsWithAny(requestURI, "/xpackComponent/content")
|
||||||
|
|| StringUtils.startsWithAny(requestURI, "/xpackComponent/pluginStaticInfo")
|
||||||
|| StringUtils.startsWithAny(requestURI, "/geo/")
|
|| StringUtils.startsWithAny(requestURI, "/geo/")
|
||||||
|| StringUtils.startsWithAny(requestURI, "/websocket")
|
|| StringUtils.startsWithAny(requestURI, "/websocket")
|
||||||
|| StringUtils.startsWithAny(requestURI, "/map/")
|
|| StringUtils.startsWithAny(requestURI, "/map/")
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
package io.dataease.extensions.view.factory;
|
package io.dataease.extensions.view.factory;
|
||||||
|
|
||||||
|
import io.dataease.exception.DEException;
|
||||||
import io.dataease.extensions.view.template.PluginsChartTemplate;
|
import io.dataease.extensions.view.template.PluginsChartTemplate;
|
||||||
import io.dataease.extensions.view.vo.XpackPluginsViewVO;
|
import io.dataease.extensions.view.vo.XpackPluginsViewVO;
|
||||||
|
import io.dataease.license.utils.LogUtil;
|
||||||
|
import io.dataease.plugins.factory.DataEasePluginFactory;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -11,6 +14,7 @@ public class PluginsChartFactory {
|
|||||||
|
|
||||||
private static final Map<String, PluginsChartTemplate> templateMap = new ConcurrentHashMap<>();
|
private static final Map<String, PluginsChartTemplate> templateMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
|
||||||
public static PluginsChartTemplate getInstance(String render, String type) {
|
public static PluginsChartTemplate getInstance(String render, String type) {
|
||||||
String key = render + "_" + type;
|
String key = render + "_" + type;
|
||||||
return templateMap.get(key);
|
return templateMap.get(key);
|
||||||
@ -20,13 +24,16 @@ public class PluginsChartFactory {
|
|||||||
String key = render + "_" + type;
|
String key = render + "_" + type;
|
||||||
if (templateMap.containsKey(key)) return;
|
if (templateMap.containsKey(key)) return;
|
||||||
templateMap.put(key, template);
|
templateMap.put(key, template);
|
||||||
|
try {
|
||||||
|
String moduleName = template.getPluginInfo().getModuleName();
|
||||||
|
DataEasePluginFactory.loadTemplate(moduleName, template);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogUtil.error(e.getMessage(), new Throwable(e));
|
||||||
|
DEException.throwException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<XpackPluginsViewVO> getViewConfigList() {
|
public static List<XpackPluginsViewVO> getViewConfigList() {
|
||||||
return templateMap.values().stream().map(PluginsChartTemplate::getConfig).toList();
|
return templateMap.values().stream().map(PluginsChartTemplate::getConfig).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<String> getAllPlugins() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import lombok.Data;
|
|||||||
|
|
||||||
import java.io.Serial;
|
import java.io.Serial;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class XpackPluginsViewVO implements Serializable {
|
public class XpackPluginsViewVO implements Serializable {
|
||||||
@ -26,4 +27,6 @@ public class XpackPluginsViewVO implements Serializable {
|
|||||||
|
|
||||||
private String render;
|
private String render;
|
||||||
|
|
||||||
|
private Map<String, String> staticMap;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user