optimize(projects): 动态加载组件方法抽取为公共函数

This commit is contained in:
AN 2025-06-21 13:48:11 +08:00
parent e86a6d1b7a
commit 2f8a6b4b84
2 changed files with 34 additions and 18 deletions

View File

@ -1,5 +1,7 @@
import { defineAsyncComponent, markRaw } from 'vue';
import { AcceptType } from '@/enum/business'; import { AcceptType } from '@/enum/business';
import { $t } from '@/locales'; import { $t } from '@/locales';
/** /**
* Transform record to option * Transform record to option
* *
@ -76,6 +78,33 @@ export function humpToLine(str: string, line: string = '-') {
return temp; return temp;
} }
/** 动态加载组件 */
export async function loadDynamicComponent<T extends object = any>(
modules: Record<string, () => Promise<any>>,
formPath: string,
options?: {
delay?: number;
timeout?: number;
}
) {
const expectedPathSuffix = `${humpToLine(formPath)}.vue`;
const matchedKey = Object.keys(modules).find(path => path.endsWith(expectedPathSuffix));
if (!matchedKey) {
window.$message?.error('组件不存在');
throw new Error(`组件不存在: ${expectedPathSuffix}`);
}
return markRaw(
defineAsyncComponent({
loader: async () => (await modules[matchedKey]()) as T,
delay: options?.delay ?? 200,
timeout: options?.timeout ?? 3000
})
);
}
/** 判断是否为空 */ /** 判断是否为空 */
export function isNotNull(value: any) { export function isNotNull(value: any) {
return value !== undefined && value !== null && value !== '' && value !== 'undefined' && value !== 'null'; return value !== undefined && value !== null && value !== '' && value !== 'undefined' && value !== 'null';

View File

@ -1,6 +1,5 @@
<script setup lang="tsx"> <script setup lang="tsx">
import type { AsyncComponentLoader } from 'vue'; import { computed, reactive, ref, shallowRef, watch } from 'vue';
import { computed, defineAsyncComponent, markRaw, reactive, ref, shallowRef, watch } from 'vue';
import { NButton, NDivider, NEmpty, NInput, NRadioButton, NRadioGroup, NSpin, NTag } from 'naive-ui'; import { NButton, NDivider, NEmpty, NInput, NRadioButton, NRadioGroup, NSpin, NTag } from 'naive-ui';
import { useBoolean, useLoading } from '@sa/hooks'; import { useBoolean, useLoading } from '@sa/hooks';
import { workflowActivityStatusRecord } from '@/constants/workflow'; import { workflowActivityStatusRecord } from '@/constants/workflow';
@ -14,7 +13,7 @@ import {
import { useAppStore } from '@/store/modules/app'; import { useAppStore } from '@/store/modules/app';
import { useTable, useTableOperate } from '@/hooks/common/table'; import { useTable, useTableOperate } from '@/hooks/common/table';
import { useDict } from '@/hooks/business/dict'; import { useDict } from '@/hooks/business/dict';
import { humpToLine } from '@/utils/common'; import { loadDynamicComponent } from '@/utils/common';
import DictTag from '@/components/custom/dict-tag.vue'; import DictTag from '@/components/custom/dict-tag.vue';
import { $t } from '@/locales'; import { $t } from '@/locales';
import ButtonIcon from '@/components/custom/button-icon.vue'; import ButtonIcon from '@/components/custom/button-icon.vue';
@ -322,26 +321,14 @@ async function handleShowVariable(id: CommonType.IdType) {
const modules = import.meta.glob('@/components/custom/workflow/**/*.vue'); const modules = import.meta.glob('@/components/custom/workflow/**/*.vue');
const businessId = ref<CommonType.IdType>(); const businessId = ref<CommonType.IdType>();
/** 流程预览,动态加载组件 */
async function handlePreview(row: Api.Workflow.ProcessInstance) { async function handlePreview(row: Api.Workflow.ProcessInstance) {
businessId.value = row.businessId; businessId.value = row.businessId;
const formPath = row.formPath; const formPath = row.formPath;
if (formPath) { if (formPath) {
const url = `/src/components/custom${humpToLine(formPath)}.vue`; dynamicComponent.value = await loadDynamicComponent(modules, formPath);
const loader = modules[url]; showPreviewDrawer();
if (!loader) {
window.$message?.error('组件不存在');
return;
}
dynamicComponent.value = markRaw(
defineAsyncComponent({
loader: async () => (await modules[url]()) as AsyncComponentLoader<any>,
delay: 200,
timeout: 3000
})
);
} }
showPreviewDrawer();
} }
</script> </script>