第一次提交

This commit is contained in:
2026-04-03 09:56:14 +08:00
commit 60e2c8debd
3598 changed files with 746659 additions and 0 deletions

View File

@@ -0,0 +1,19 @@
export type DynamicViewsRecord = Record<string, () => Promise<Recordable>>;
/** 已注册模块的动态页面 */
export const packageViews: DynamicViewsRecord = {};
/**
* 注册动态路由页面
* @param getViews 获取该模块下所有页面的方法
*/
export function registerDynamicRouter(getViews: () => DynamicViewsRecord) {
if (typeof getViews === 'function') {
let dynamicViews = getViews();
Object.keys(dynamicViews).forEach((key) => {
// 处理动态页面的key使其可以让路由识别
let newKey = key.replace('./src/views', '../../views');
packageViews[newKey] = dynamicViews[key];
});
}
}

View File

@@ -0,0 +1,134 @@
import type { App } from 'vue';
import { warn } from '/@/utils/log';
import { registerDynamicRouter } from '/@/utils/monorepo/dynamicRouter';
import { add } from '/@/components/Form/src/componentMap';
// 懒加载模块配置(按需加载,访问相关路由时才加载对应包)
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,
};
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
const importGlobs = [import.meta.glob('../../utils/**/*.{ts,js,tsx}'), import.meta.glob('../../hooks/**/*.{ts,js,tsx}')];
/**
* 基础项目导包
* 目前支持导入如下
* /@/utils/**
* /@/hooks/**
*
* @param path 文件路径ts无需输入后缀名。如/@/utils/common/compUtils
*/
async function baseImport(path: string) {
if (path) {
// 将 /@/ 替换成 ../../
path = path.replace(/^\/@\//, '../../');
for (const glob of importGlobs) {
for (const key of Object.keys(glob)) {
if (path === key || `${path}.ts` === key || `${path}.tsx` === key) {
return glob[key]();
}
}
}
warn(`引入失败:${path} 不存在`);
}
return null;
}