mirror of
https://github.com/jeecgboot/JeecgBoot.git
synced 2026-03-26 15:23:11 +00:00
Merge pull request #9443 from liaozhiyang/master
@jeecg/online和@jeecg/aiflow库按需加载
This commit is contained in:
commit
1cece6aba8
@ -179,7 +179,15 @@ componentMap.set('JInputSelect', JInputSelect);
|
||||
componentMap.set('JSelectDepartPost', JSelectDepartPost);
|
||||
componentMap.set('JSelectUserByDeptPost', JSelectUserByDeptPost);
|
||||
|
||||
|
||||
componentMap.set('OnlineSelectCascade', createAsyncComponent(() => {
|
||||
return import('@jeecg/online').then(mod => mod.OnlineSelectCascade);
|
||||
}));
|
||||
componentMap.set('LinkTableCard', createAsyncComponent(() => {
|
||||
return import('@jeecg/online').then(mod => mod.LinkTableCard);
|
||||
}));
|
||||
componentMap.set('LinkTableSelect', createAsyncComponent(() => {
|
||||
return import('@jeecg/online').then(mod => mod.LinkTableSelect);
|
||||
}));
|
||||
|
||||
export function add(compName: ComponentType, component: Component) {
|
||||
componentMap.set(compName, component);
|
||||
|
||||
@ -6,10 +6,6 @@ import { ref, onUnmounted, unref, nextTick, watch } from 'vue';
|
||||
import { isProdMode } from '/@/utils/env';
|
||||
import { error } from '/@/utils/log';
|
||||
import { getDynamicProps, getValueType, getValueTypeBySchema } from '/@/utils';
|
||||
import { add } from "/@/components/Form/src/componentMap";
|
||||
//集成online专用控件
|
||||
import { OnlineSelectCascade, LinkTableCard, LinkTableSelect } from '@jeecg/online';
|
||||
|
||||
export declare type ValidateFields = (nameList?: NamePath[], options?: ValidateOptions) => Promise<Recordable>;
|
||||
|
||||
type Props = Partial<DynamicProps<FormProps>>;
|
||||
@ -18,11 +14,6 @@ export function useForm(props?: Props): UseFormReturnType {
|
||||
const formRef = ref<Nullable<FormActionType>>(null);
|
||||
const loadedRef = ref<Nullable<boolean>>(false);
|
||||
|
||||
//集成online专用控件
|
||||
add("OnlineSelectCascade", OnlineSelectCascade)
|
||||
add("LinkTableCard", LinkTableCard)
|
||||
add("LinkTableSelect", LinkTableSelect)
|
||||
|
||||
async function getForm() {
|
||||
const form = unref(formRef);
|
||||
if (!form) {
|
||||
|
||||
@ -9,6 +9,7 @@ import { getTenantId, getToken } from "/@/utils/auth";
|
||||
import { URL_HASH_TAB, _eval } from '/@/utils';
|
||||
//引入online lib路由
|
||||
import { packageViews } from '/@/utils/monorepo/dynamicRouter';
|
||||
import { loadPackageComponent } from '/@/utils/monorepo/registerPackages';
|
||||
import {useI18n} from "/@/hooks/web/useI18n";
|
||||
|
||||
export type LayoutMapKey = 'LAYOUT';
|
||||
@ -120,6 +121,12 @@ function dynamicImport(dynamicViewsModules: Record<string, () => Promise<Recorda
|
||||
);
|
||||
return;
|
||||
}
|
||||
// online/aiflow 本地未找到,尝试从懒加载包中按需加载
|
||||
if (component.startsWith('/super/online') || component.startsWith('/super/aiflow')) {
|
||||
return () => {
|
||||
return loadPackageComponent(component).then((factory) => (factory ? factory() : Promise.reject(`组件 ${component} 未找到`)));
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Turn background objects into routing objects
|
||||
|
||||
@ -1,24 +1,109 @@
|
||||
import type { App } from 'vue';
|
||||
import { warn } from '/@/utils/log';
|
||||
import { registerDynamicRouter } from '/@/utils/monorepo/dynamicRouter';
|
||||
// 引入模块
|
||||
import PACKAGE_JEECG_ONLINE from '@jeecg/online';
|
||||
import PACKAGE_JEECG_AIFLOW from '@jeecg/aiflow';
|
||||
import { add } from '/@/components/Form/src/componentMap';
|
||||
|
||||
export function registerPackages(app: App) {
|
||||
use(app, PACKAGE_JEECG_ONLINE);
|
||||
use(app, PACKAGE_JEECG_AIFLOW);
|
||||
}
|
||||
// 懒加载模块配置(按需加载,访问相关路由时才加载对应包)
|
||||
const lazyPackages = [
|
||||
{ name: '@jeecg/online', importer: () => import('@jeecg/online') },
|
||||
{ name: '@jeecg/aiflow', importer: () => import('@jeecg/aiflow') },
|
||||
];
|
||||
|
||||
let appInstance: App | null = null;
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
const installOptions = {
|
||||
baseImport,
|
||||
};
|
||||
|
||||
/** 注册模块 */
|
||||
function use(app: App, pkg) {
|
||||
app.use(pkg, installOptions);
|
||||
registerDynamicRouter(pkg.getViews);
|
||||
export function registerPackages(app: App) {
|
||||
// 仅保存 app 实例,不立即加载模块
|
||||
appInstance = app;
|
||||
}
|
||||
|
||||
/** 已加载的包缓存 */
|
||||
const loadedPackages = new Map<string, any>();
|
||||
/** 正在加载的包 Promise 缓存(防止重复加载) */
|
||||
const loadingPromises = new Map<string, Promise<any>>();
|
||||
|
||||
/**
|
||||
* 按需加载包并注册
|
||||
*/
|
||||
async function ensurePackageLoaded(pkgConfig: typeof lazyPackages[number]) {
|
||||
const { name, importer } = pkgConfig;
|
||||
if (loadedPackages.has(name)) {
|
||||
return loadedPackages.get(name);
|
||||
}
|
||||
if (!loadingPromises.has(name)) {
|
||||
const promise = importer().then((pkg) => {
|
||||
const mod = pkg.default || pkg;
|
||||
if (appInstance) {
|
||||
appInstance.use(mod, installOptions);
|
||||
registerDynamicRouter(mod.getViews);
|
||||
}
|
||||
loadedPackages.set(name, mod);
|
||||
loadingPromises.delete(name);
|
||||
return mod;
|
||||
});
|
||||
loadingPromises.set(name, promise);
|
||||
}
|
||||
return loadingPromises.get(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 component 路径关键字匹配优先加载的包
|
||||
*/
|
||||
function getMatchedPackage(component: string): typeof lazyPackages[number] | null {
|
||||
const lc = component.toLowerCase();
|
||||
for (const pkgConfig of lazyPackages) {
|
||||
// 从包名中提取关键字,如 @jeecg/online -> online, @jeecg/aiflow -> aiflow
|
||||
const keyword = pkgConfig.name.split('/').pop()!;
|
||||
if (lc.includes(keyword)) {
|
||||
return pkgConfig;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从指定包中查找组件
|
||||
*/
|
||||
async function findComponentInPackage(pkgConfig: typeof lazyPackages[number], component: string): Promise<(() => Promise<Recordable>) | null> {
|
||||
try {
|
||||
const mod = await ensurePackageLoaded(pkgConfig);
|
||||
const views = mod.getViews();
|
||||
for (const key of Object.keys(views)) {
|
||||
const k = key.replace('./src/views', '');
|
||||
const startFlag = component.startsWith('/');
|
||||
const endFlag = component.endsWith('.vue') || component.endsWith('.tsx');
|
||||
const startIndex = startFlag ? 0 : 1;
|
||||
const lastIndex = endFlag ? k.length : k.lastIndexOf('.');
|
||||
if (k.substring(startIndex, lastIndex) === component) {
|
||||
return views[key];
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// 包不存在或加载失败,跳过
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 按需加载包组件:当路由匹配不到本地组件时调用
|
||||
* 根据 component 路径中的关键字优先匹配对应包,避免无意义的遍历
|
||||
*/
|
||||
export async function loadPackageComponent(component: string): Promise<(() => Promise<Recordable>) | null> {
|
||||
// 优先根据关键字精准匹配包
|
||||
const matched = getMatchedPackage(component);
|
||||
if (matched) {
|
||||
return findComponentInPackage(matched, component);
|
||||
}
|
||||
// 未匹配到关键字,依次尝试所有包
|
||||
for (const pkgConfig of lazyPackages) {
|
||||
const result = await findComponentInPackage(pkgConfig, component);
|
||||
if (result) return result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// 模块里可使用的import
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user