<script lang="ts" setup>
|
import { nextTick, reactive } from 'vue';
|
|
import { useMessage } from '@jnpf/hooks';
|
import { BasicPopup, usePopupInner } from '@jnpf/ui/popup';
|
import { createAsyncComponent } from '@jnpf/utils';
|
|
import { getConfigData } from '#/api/onlineDev/visualDev';
|
import { getFlowStartFormId } from '#/api/workFlow/template';
|
import { router } from '#/router';
|
import { useBaseStore } from '#/store';
|
import { resolveOpenFlowListConfig } from '#/utils/jnpf';
|
|
const DynamicList = createAsyncComponent(() => import('#/views/common/dynamicModel/list/index.vue'));
|
|
defineOptions({ name: 'GlobalFlowListPopup' });
|
defineEmits(['register']);
|
|
interface OpenFlowListConfig {
|
flow_id?: number | string;
|
flowId?: number | string;
|
menuId?: number | string;
|
params?: Record<string, any>;
|
path?: string;
|
query?: Record<string, any>;
|
routeQuery?: Record<string, any>;
|
title?: string;
|
}
|
|
interface FlowListState {
|
config: any;
|
externalParams: Record<string, any>;
|
flowId: string;
|
key: number;
|
loading: boolean;
|
menuId: string;
|
modelId: string;
|
ready: boolean;
|
title: string;
|
}
|
|
const baseStore = useBaseStore();
|
const { createMessage } = useMessage();
|
const [registerPopup, { closePopup }] = usePopupInner(init);
|
const state = reactive<FlowListState>({
|
config: {},
|
externalParams: {},
|
flowId: '',
|
key: Date.now(),
|
loading: false,
|
menuId: '',
|
modelId: '',
|
ready: false,
|
title: '流程列表',
|
});
|
|
function parseRouteListQuery(value) {
|
if (!value || typeof value !== 'string') return {};
|
try {
|
const data = JSON.parse(value);
|
return data && typeof data === 'object' && !Array.isArray(data) ? data : {};
|
} catch {
|
return {};
|
}
|
}
|
|
function parsePathQuery(path = '') {
|
const query: Record<string, any> = {};
|
const queryString = path.includes('?') ? path.split('?')[1] : '';
|
if (!queryString) return query;
|
const params = new URLSearchParams(queryString);
|
params.forEach((value, key) => {
|
query[key] = value;
|
});
|
return query;
|
}
|
|
function getExternalParams(config: OpenFlowListConfig, menuQuery: Record<string, any> = {}) {
|
const params = config.params || config.query || {};
|
const routeQuery = { ...parsePathQuery(config.path), ...config.routeQuery };
|
const listQueryParams = parseRouteListQuery(routeQuery.jnpfListQuery);
|
delete routeQuery.jnpfListQuery;
|
return { ...menuQuery, ...routeQuery, ...listQueryParams, ...(params && typeof params === 'object' && !Array.isArray(params) ? params : {}) };
|
}
|
|
function getRouteInfo(config: OpenFlowListConfig) {
|
const routes = router.getRoutes();
|
let target: any = null;
|
const configFlowId = config.flowId ?? config.flow_id;
|
if (config.path) {
|
const path = config.path.split('?')[0];
|
target = routes.find((o) => o.path === path);
|
}
|
if (!target && config.menuId) target = routes.find((o) => String(o.meta?.modelId || '') === String(config.menuId));
|
if (!target && configFlowId) {
|
target = routes.find((o) => String(o.meta?.type || '') === '9' && String(o.meta?.relationId || '') === String(configFlowId));
|
}
|
if (!target) return null;
|
return {
|
flowId: String(target.meta?.relationId || configFlowId || ''),
|
menuId: String(target.meta?.modelId || config.menuId || ''),
|
query: target.meta?.query && typeof target.meta.query === 'object' && !Array.isArray(target.meta.query) ? { ...target.meta.query } : {},
|
title: target.meta?.title,
|
type: target.meta?.type,
|
};
|
}
|
|
async function getTargetConfig(config: OpenFlowListConfig) {
|
const resolvedConfig = await resolveOpenFlowListConfig(config);
|
const routeInfo = getRouteInfo(resolvedConfig);
|
const flowId = String(resolvedConfig.flowId ?? resolvedConfig.flow_id ?? routeInfo?.flowId ?? '');
|
if (!flowId) throw new Error('未找到目标流程菜单');
|
if (routeInfo && String(routeInfo.type) !== '9') throw new Error('目标不是流程列表页面');
|
|
const formRes = await getFlowStartFormId(flowId);
|
const modelId = formRes?.data?.formId;
|
if (!modelId) throw new Error('未找到流程发起表单');
|
|
const configRes = await getConfigData(modelId, { onlineUtilsOpen: true });
|
const listConfig = configRes.data;
|
if (!listConfig) throw new Error('未找到流程列表配置');
|
if (listConfig.webType == '1' || listConfig.webType == 1) throw new Error('目标不是列表页面');
|
|
return {
|
config: { ...listConfig, enableFlow: 1, flowId },
|
flowId,
|
menuId: routeInfo?.menuId || String(resolvedConfig.menuId || flowId),
|
modelId: String(modelId),
|
query: routeInfo?.query || {},
|
title: routeInfo?.title,
|
};
|
}
|
|
async function init(config: OpenFlowListConfig) {
|
state.ready = false;
|
state.loading = true;
|
state.config = {};
|
state.flowId = '';
|
state.menuId = '';
|
state.modelId = '';
|
state.externalParams = {};
|
try {
|
await baseStore.getDictionaryAll();
|
const target = await getTargetConfig(config);
|
state.config = target.config;
|
state.flowId = target.flowId;
|
state.modelId = target.modelId;
|
state.menuId = target.menuId;
|
state.title = config.title || target.title || target.config.fullName || '流程列表';
|
state.externalParams = getExternalParams(config, target.query);
|
state.key = Date.now();
|
state.ready = true;
|
await nextTick();
|
} catch (error: any) {
|
console.error('[onlineUtils.openFlowList] open flow list modal failed:', error);
|
createMessage.warning(error?.message || '打开流程列表失败');
|
closePopup();
|
} finally {
|
state.loading = false;
|
}
|
}
|
|
function handleClose() {
|
state.ready = false;
|
state.config = {};
|
return Promise.resolve(true);
|
}
|
</script>
|
|
<template>
|
<BasicPopup v-bind="$attrs" @register="registerPopup" destroy-on-close :show-ok-btn="false" :close-func="handleClose" class="full-popup global-flow-list-popup">
|
<template #title>
|
<div class="text-[16px] font-medium">{{ state.title }}</div>
|
</template>
|
<div class="jnpf-common-form-wrapper" v-loading="state.loading">
|
<div class="jnpf-common-form-wrapper__main">
|
<DynamicList
|
v-if="state.ready"
|
:key="state.key"
|
:config="state.config"
|
:model-id="state.modelId"
|
:menu-id="state.menuId"
|
is-online-utils-open
|
:external-params="state.externalParams" />
|
</div>
|
</div>
|
</BasicPopup>
|
</template>
|