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('JSelectDepartPost', JSelectDepartPost);
|
||||||
componentMap.set('JSelectUserByDeptPost', JSelectUserByDeptPost);
|
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) {
|
export function add(compName: ComponentType, component: Component) {
|
||||||
componentMap.set(compName, component);
|
componentMap.set(compName, component);
|
||||||
|
|||||||
@ -6,10 +6,6 @@ import { ref, onUnmounted, unref, nextTick, watch } from 'vue';
|
|||||||
import { isProdMode } from '/@/utils/env';
|
import { isProdMode } from '/@/utils/env';
|
||||||
import { error } from '/@/utils/log';
|
import { error } from '/@/utils/log';
|
||||||
import { getDynamicProps, getValueType, getValueTypeBySchema } from '/@/utils';
|
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>;
|
export declare type ValidateFields = (nameList?: NamePath[], options?: ValidateOptions) => Promise<Recordable>;
|
||||||
|
|
||||||
type Props = Partial<DynamicProps<FormProps>>;
|
type Props = Partial<DynamicProps<FormProps>>;
|
||||||
@ -18,11 +14,6 @@ export function useForm(props?: Props): UseFormReturnType {
|
|||||||
const formRef = ref<Nullable<FormActionType>>(null);
|
const formRef = ref<Nullable<FormActionType>>(null);
|
||||||
const loadedRef = ref<Nullable<boolean>>(false);
|
const loadedRef = ref<Nullable<boolean>>(false);
|
||||||
|
|
||||||
//集成online专用控件
|
|
||||||
add("OnlineSelectCascade", OnlineSelectCascade)
|
|
||||||
add("LinkTableCard", LinkTableCard)
|
|
||||||
add("LinkTableSelect", LinkTableSelect)
|
|
||||||
|
|
||||||
async function getForm() {
|
async function getForm() {
|
||||||
const form = unref(formRef);
|
const form = unref(formRef);
|
||||||
if (!form) {
|
if (!form) {
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import { getTenantId, getToken } from "/@/utils/auth";
|
|||||||
import { URL_HASH_TAB, _eval } from '/@/utils';
|
import { URL_HASH_TAB, _eval } from '/@/utils';
|
||||||
//引入online lib路由
|
//引入online lib路由
|
||||||
import { packageViews } from '/@/utils/monorepo/dynamicRouter';
|
import { packageViews } from '/@/utils/monorepo/dynamicRouter';
|
||||||
|
import { loadPackageComponent } from '/@/utils/monorepo/registerPackages';
|
||||||
import {useI18n} from "/@/hooks/web/useI18n";
|
import {useI18n} from "/@/hooks/web/useI18n";
|
||||||
|
|
||||||
export type LayoutMapKey = 'LAYOUT';
|
export type LayoutMapKey = 'LAYOUT';
|
||||||
@ -120,6 +121,12 @@ function dynamicImport(dynamicViewsModules: Record<string, () => Promise<Recorda
|
|||||||
);
|
);
|
||||||
return;
|
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
|
// Turn background objects into routing objects
|
||||||
|
|||||||
@ -1,24 +1,109 @@
|
|||||||
import type { App } from 'vue';
|
import type { App } from 'vue';
|
||||||
import { warn } from '/@/utils/log';
|
import { warn } from '/@/utils/log';
|
||||||
import { registerDynamicRouter } from '/@/utils/monorepo/dynamicRouter';
|
import { registerDynamicRouter } from '/@/utils/monorepo/dynamicRouter';
|
||||||
// 引入模块
|
import { add } from '/@/components/Form/src/componentMap';
|
||||||
import PACKAGE_JEECG_ONLINE from '@jeecg/online';
|
|
||||||
import PACKAGE_JEECG_AIFLOW from '@jeecg/aiflow';
|
|
||||||
|
|
||||||
export function registerPackages(app: App) {
|
// 懒加载模块配置(按需加载,访问相关路由时才加载对应包)
|
||||||
use(app, PACKAGE_JEECG_ONLINE);
|
const lazyPackages = [
|
||||||
use(app, PACKAGE_JEECG_AIFLOW);
|
{ name: '@jeecg/online', importer: () => import('@jeecg/online') },
|
||||||
}
|
{ name: '@jeecg/aiflow', importer: () => import('@jeecg/aiflow') },
|
||||||
|
];
|
||||||
|
|
||||||
|
let appInstance: App | null = null;
|
||||||
|
|
||||||
// noinspection JSUnusedGlobalSymbols
|
// noinspection JSUnusedGlobalSymbols
|
||||||
const installOptions = {
|
const installOptions = {
|
||||||
baseImport,
|
baseImport,
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 注册模块 */
|
export function registerPackages(app: App) {
|
||||||
function use(app: App, pkg) {
|
// 仅保存 app 实例,不立即加载模块
|
||||||
app.use(pkg, installOptions);
|
appInstance = app;
|
||||||
registerDynamicRouter(pkg.getViews);
|
}
|
||||||
|
|
||||||
|
/** 已加载的包缓存 */
|
||||||
|
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
|
// 模块里可使用的import
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user