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: {
|
||||
rollupOptions: {
|
||||
external: id => /de-xpack/.test(id) || /extensions-view-3dpie/.test(id),
|
||||
external: id => /de-xpack/.test(id) || /extensions/.test(id),
|
||||
output: {
|
||||
// 用于命名代码拆分时创建的共享块的输出命名
|
||||
chunkFileNames: `assets/chunk/[name]-${pkg.version}-${pkg.name}.js`,
|
||||
|
@ -1490,25 +1490,6 @@ defineExpose({
|
||||
@linkJumpSetOpen="linkJumpSetOpen(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
|
||||
:is="findComponent(item.component)"
|
||||
v-if="item.component === 'UserView' || item['isPlugin']"
|
||||
|
@ -2,7 +2,7 @@
|
||||
import noLic from './nolic.vue'
|
||||
import { ref, useAttrs, onMounted } from 'vue'
|
||||
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 { i18n } from '@/plugins/vue-i18n'
|
||||
import * as Vue from 'vue'
|
||||
@ -10,7 +10,7 @@ import axios from 'axios'
|
||||
import * as Pinia from 'pinia'
|
||||
import * as vueRouter from 'vue-router'
|
||||
import { useEmitt } from '@/hooks/web/useEmitt'
|
||||
|
||||
import request from '@/config/axios'
|
||||
const { wsCache } = useCache()
|
||||
|
||||
const plugin = ref()
|
||||
@ -33,15 +33,12 @@ const generateRamStr = (len: number) => {
|
||||
}
|
||||
|
||||
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(
|
||||
`../../../../../../../extensions-view-3dpie/${formatArray(bytesArray[8])}/${formatArray(
|
||||
`../../../../../../../extensions/${formatArray(bytesArray[8])}/${formatArray(
|
||||
bytesArray[9]
|
||||
)}/${formatArray(bytesArray[10])}/${formatArray(bytesArray[11])}.vue`
|
||||
)}/${formatArray(bytesArray[10])}/${formatArray(bytesArray[11])}/${formatArray(
|
||||
bytesArray[12]
|
||||
)}.vue`
|
||||
)
|
||||
promise
|
||||
.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 moduleName = getModuleName()
|
||||
loading.value = true
|
||||
const byteArray = wsCache.get(`de-plugin-proxy-plugin`)
|
||||
const byteArray = wsCache.get(`de-plugin-proxy-${moduleName}`)
|
||||
if (byteArray) {
|
||||
importProxy(JSON.parse(byteArray))
|
||||
loading.value = false
|
||||
return
|
||||
}
|
||||
const key = generateRamStr(randomKey())
|
||||
loadPluginApi(key)
|
||||
const moduleNameKey = window.btoa(moduleName)
|
||||
const saltKey = `${key},${moduleNameKey}`
|
||||
loadPluginApi(saltKey)
|
||||
.then(response => {
|
||||
let code = response.data
|
||||
const byteArray = execute(code, key)
|
||||
@ -82,7 +86,8 @@ const storeCacheProxy = byteArray => {
|
||||
byteArray.forEach(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 invokeMethod = param => {
|
||||
@ -104,8 +109,9 @@ onMounted(async () => {
|
||||
distributed = wsCache.get(key)
|
||||
}
|
||||
if (distributed) {
|
||||
if (window['DEXPack']) {
|
||||
const xpack = await window['DEXPack'].mapping[attrs.jsname]
|
||||
const moduleName = getModuleName()
|
||||
if (window[moduleName]) {
|
||||
const xpack = await window[moduleName].mapping[attrs.jsname]
|
||||
plugin.value = xpack.default
|
||||
} else {
|
||||
window['Vue'] = Vue
|
||||
@ -114,9 +120,10 @@ onMounted(async () => {
|
||||
window['vueRouter'] = vueRouter
|
||||
window['MittAll'] = useEmitt().emitter.all
|
||||
window['I18n'] = i18n
|
||||
loadDistributed().then(async res => {
|
||||
new Function(res.data)()
|
||||
const xpack = await window['DEXPack'].mapping[attrs.jsname]
|
||||
const url = `/xpackComponent/pluginStaticInfo/${moduleName}`
|
||||
request.get({ url }).then(async res => {
|
||||
new Function(res.data || res)()
|
||||
const xpack = await window[moduleName].mapping[attrs.jsname]
|
||||
plugin.value = xpack.default
|
||||
})
|
||||
}
|
||||
|
@ -173,6 +173,8 @@ service.interceptors.response.use(
|
||||
return response
|
||||
} else if (response.config.url.includes('DEXPack.umd.js')) {
|
||||
return response
|
||||
} else if (response.config.url.startsWith('/xpackComponent/pluginStaticInfo/extensions-')) {
|
||||
return response
|
||||
} else {
|
||||
if (
|
||||
!response?.config?.url.startsWith('/xpackComponent/content') &&
|
||||
|
@ -48,8 +48,8 @@ const anchorPosition = anchor => {
|
||||
scrollTo(element.offsetTop)
|
||||
}
|
||||
|
||||
const newComponent = (innerType, isPlugin) => {
|
||||
eventBus.emit('handleNew', { componentName: 'UserView', innerType: innerType, isPlugin })
|
||||
const newComponent = (innerType, staticMap) => {
|
||||
eventBus.emit('handleNew', { componentName: 'UserView', innerType: innerType, staticMap })
|
||||
}
|
||||
|
||||
const handleDragStart = e => {
|
||||
@ -66,14 +66,15 @@ const groupActiveChange = category => {
|
||||
}
|
||||
const loadPluginCategory = data => {
|
||||
data.forEach(item => {
|
||||
const { category, title, render, chartValue, chartTitle, icon } = item
|
||||
const { category, title, render, chartValue, chartTitle, icon, staticMap } = item
|
||||
const node = {
|
||||
render,
|
||||
category,
|
||||
icon,
|
||||
value: chartValue,
|
||||
title: chartTitle,
|
||||
isPlugin: true
|
||||
isPlugin: true,
|
||||
staticMap
|
||||
}
|
||||
const stack = [...state.chartGroupList]
|
||||
let findParent = false
|
||||
@ -128,7 +129,7 @@ const loadPluginCategory = data => {
|
||||
:key="chartInfo.title"
|
||||
>
|
||||
<div
|
||||
v-on:click="newComponent(chartInfo.value, chartInfo['isPlugin'])"
|
||||
v-on:click="newComponent(chartInfo.value, chartInfo['staticMap'])"
|
||||
class="item-top"
|
||||
draggable="true"
|
||||
:data-id="'UserView&' + chartInfo.value"
|
||||
|
@ -518,8 +518,9 @@ export function findNewComponentFromList(
|
||||
componentName,
|
||||
innerType,
|
||||
curOriginThemes,
|
||||
isPlugin?: boolean
|
||||
staticMap?: object
|
||||
) {
|
||||
const isPlugin = !!staticMap
|
||||
let newComponent
|
||||
list.forEach(comp => {
|
||||
if (comp.component === componentName) {
|
||||
@ -540,6 +541,9 @@ export function findNewComponentFromList(
|
||||
newComponent.label = viewConfig?.title
|
||||
newComponent.render = viewConfig?.render
|
||||
newComponent.isPlugin = !!isPlugin
|
||||
if (isPlugin) {
|
||||
newComponent.staticMap = staticMap
|
||||
}
|
||||
}
|
||||
return newComponent
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
declare interface ChartPlugin {
|
||||
isPlugin: boolean
|
||||
pluginResourceId?: string
|
||||
staticMap?: object
|
||||
}
|
||||
|
@ -391,7 +391,7 @@ export const dvMainStore = defineStore('dataVisualization', {
|
||||
render: component.render,
|
||||
plugin: {
|
||||
isPlugin: component.isPlugin,
|
||||
pluginResourceId: component.pluginResourceId
|
||||
staticMap: component.staticMap
|
||||
}
|
||||
} as unknown as ChartObj
|
||||
// 处理配置项默认值,不同图表的同一配置项默认值不同
|
||||
|
@ -73,10 +73,9 @@ const editStyle = computed(() => {
|
||||
|
||||
// 通过实时监听的方式直接添加组件
|
||||
const handleNewFromCanvasMain = newComponentInfo => {
|
||||
const { componentName, innerType, isPlugin } = newComponentInfo
|
||||
const { componentName, innerType, staticMap } = newComponentInfo
|
||||
if (componentName) {
|
||||
const component = findNewComponentFromList(componentName, innerType, curOriginThemes, isPlugin)
|
||||
component.isPlugin = !!isPlugin
|
||||
const component = findNewComponentFromList(componentName, innerType, curOriginThemes, staticMap)
|
||||
syncShapeItemStyle(component, baseWidth.value, baseHeight.value)
|
||||
component.id = guid()
|
||||
component.y = 200
|
||||
|
@ -1605,7 +1605,7 @@ const deleteChartFieldItem = id => {
|
||||
</div>
|
||||
<plugin-component
|
||||
v-else-if="view.plugin?.isPlugin"
|
||||
jsname="L2NvbXBvbmVudC9lZGl0b3IvaW5kZXg="
|
||||
:jsname="view.plugin.staticMap['editor']"
|
||||
:view="view"
|
||||
:dimension="state.dimension"
|
||||
:quota="state.quota"
|
||||
|
@ -762,7 +762,7 @@ const showActionIcons = computed(() => {
|
||||
<div v-if="chartAreaShow" style="flex: 1; overflow: hidden">
|
||||
<plugin-component
|
||||
v-if="view.plugin?.isPlugin"
|
||||
jsname="L2NvbXBvbmVudC9pbmRleA=="
|
||||
:jsname="view.plugin.staticMap['index']"
|
||||
:scale="scale"
|
||||
:dynamic-area-id="dynamicAreaId"
|
||||
:view="view"
|
||||
|
@ -20,4 +20,7 @@ public interface XpackComponentApi {
|
||||
|
||||
@GetMapping("/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, "/share/proxyInfo")
|
||||
|| StringUtils.startsWithAny(requestURI, "/xpackComponent/content")
|
||||
|| StringUtils.startsWithAny(requestURI, "/xpackComponent/pluginStaticInfo")
|
||||
|| StringUtils.startsWithAny(requestURI, "/geo/")
|
||||
|| StringUtils.startsWithAny(requestURI, "/websocket")
|
||||
|| StringUtils.startsWithAny(requestURI, "/map/")
|
||||
|
@ -1,7 +1,10 @@
|
||||
package io.dataease.extensions.view.factory;
|
||||
|
||||
import io.dataease.exception.DEException;
|
||||
import io.dataease.extensions.view.template.PluginsChartTemplate;
|
||||
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.Map;
|
||||
@ -11,6 +14,7 @@ public class PluginsChartFactory {
|
||||
|
||||
private static final Map<String, PluginsChartTemplate> templateMap = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
public static PluginsChartTemplate getInstance(String render, String type) {
|
||||
String key = render + "_" + type;
|
||||
return templateMap.get(key);
|
||||
@ -20,13 +24,16 @@ public class PluginsChartFactory {
|
||||
String key = render + "_" + type;
|
||||
if (templateMap.containsKey(key)) return;
|
||||
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() {
|
||||
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.Serializable;
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
public class XpackPluginsViewVO implements Serializable {
|
||||
@ -26,4 +27,6 @@ public class XpackPluginsViewVO implements Serializable {
|
||||
|
||||
private String render;
|
||||
|
||||
private Map<String, String> staticMap;
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user