Merge pull request #9443 from liaozhiyang/master

@jeecg/online和@jeecg/aiflow库按需加载
This commit is contained in:
JEECG 2026-03-17 10:36:45 +08:00 committed by GitHub
commit 1cece6aba8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 112 additions and 21 deletions

View File

@ -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);

View File

@ -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) {

View File

@ -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

View File

@ -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