mirror of
https://github.com/m-xlsea/ruoyi-plus-soybean.git
synced 2025-09-23 23:39:47 +08:00
feat-wip(projects): 流程定义完成
This commit is contained in:
@ -36,3 +36,6 @@ UPDATE `sys_menu` SET `path` = 'https://gitee.com/xlsea/ruoyi-plus-soybean', `co
|
||||
|
||||
-- plus-ui 需要禁用的页面
|
||||
UPDATE `sys_menu` SET `status` = '1' WHERE `menu_id` IN ( '116', '130', '131', '132', '11700', '11701' );
|
||||
|
||||
-- 工作流菜单
|
||||
UPDATE `sys_menu` SET `component` = 'workflow/processDefinition/index', WHERE `menu_id` = 11620;
|
||||
|
@ -236,6 +236,7 @@ const local: App.I18n.Schema = {
|
||||
exception_404: '404',
|
||||
exception_500: '500',
|
||||
'workflow_process-definition': 'Process Definition',
|
||||
'workflow_process-definition_design': 'Process Definition Design',
|
||||
'workflow_process-instance': 'Process Instance',
|
||||
workflow_leave: 'Leave Apply'
|
||||
},
|
||||
|
@ -236,6 +236,7 @@ const local: App.I18n.Schema = {
|
||||
exception_404: '404',
|
||||
exception_500: '500',
|
||||
'workflow_process-definition': '流程定义',
|
||||
'workflow_process-definition_design': '流程设计',
|
||||
'workflow_process-instance': '流程实例',
|
||||
workflow_leave: '请假申请'
|
||||
},
|
||||
|
@ -45,6 +45,7 @@ export const views: Record<LastLevelRouteKey, RouteComponent | (() => Promise<Ro
|
||||
tool_gen: () => import("@/views/tool/gen/index.vue"),
|
||||
workflow_category: () => import("@/views/workflow/category/index.vue"),
|
||||
workflow_leave: () => import("@/views/workflow/leave/index.vue"),
|
||||
"workflow_process-definition": () => import("@/views/workflow/process-definition/index.vue"),
|
||||
"workflow_process-definition": () => import("@/views/workflow/process-definition/definition/index.vue"),
|
||||
"workflow_process-definition_design": () => import("@/views/workflow/process-definition/design/index.vue"),
|
||||
"workflow_process-instance": () => import("@/views/workflow/process-instance/index.vue"),
|
||||
};
|
||||
|
@ -361,13 +361,14 @@ export const generatedRoutes: GeneratedRoute[] = [
|
||||
},
|
||||
{
|
||||
name: 'workflow_process-definition',
|
||||
path: '/workflow/process-definition',
|
||||
path: '/workflow/process-definition/definition',
|
||||
component: 'view.workflow_process-definition',
|
||||
meta: {
|
||||
title: 'workflow_process-definition',
|
||||
i18nKey: 'route.workflow_process-definition'
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
name: 'workflow_process-instance',
|
||||
path: '/workflow/process-instance',
|
||||
|
@ -202,7 +202,8 @@ const routeMap: RouteMap = {
|
||||
"workflow": "/workflow",
|
||||
"workflow_category": "/workflow/category",
|
||||
"workflow_leave": "/workflow/leave",
|
||||
"workflow_process-definition": "/workflow/process-definition",
|
||||
"workflow_process-definition": "/workflow/process-definition/definition",
|
||||
"workflow_process-definition_design": "/workflow/process-definition/design",
|
||||
"workflow_process-instance": "/workflow/process-instance"
|
||||
};
|
||||
|
||||
|
@ -62,3 +62,11 @@ export function fetchPublishDefinition(id: CommonType.IdType) {
|
||||
method: 'put'
|
||||
});
|
||||
}
|
||||
|
||||
/** 复制流程定义 */
|
||||
export function fetchCopyDefinition(id: CommonType.IdType) {
|
||||
return request<boolean>({
|
||||
url: `/workflow/definition/copy/${id}`,
|
||||
method: 'post'
|
||||
});
|
||||
}
|
||||
|
8
src/typings/elegant-router.d.ts
vendored
8
src/typings/elegant-router.d.ts
vendored
@ -56,7 +56,8 @@ declare module "@elegant-router/types" {
|
||||
"workflow": "/workflow";
|
||||
"workflow_category": "/workflow/category";
|
||||
"workflow_leave": "/workflow/leave";
|
||||
"workflow_process-definition": "/workflow/process-definition";
|
||||
"workflow_process-definition": "/workflow/process-definition/definition";
|
||||
"workflow_process-definition_design": "/workflow/process-definition/design";
|
||||
"workflow_process-instance": "/workflow/process-instance";
|
||||
};
|
||||
|
||||
@ -154,6 +155,7 @@ declare module "@elegant-router/types" {
|
||||
| "workflow_category"
|
||||
| "workflow_leave"
|
||||
| "workflow_process-definition"
|
||||
| "workflow_process-definition_design"
|
||||
| "workflow_process-instance"
|
||||
>;
|
||||
|
||||
@ -229,7 +231,7 @@ declare module "@elegant-router/types" {
|
||||
component: `view.${K}`;
|
||||
}
|
||||
: never;
|
||||
|
||||
|
||||
/**
|
||||
* the center level route
|
||||
*/
|
||||
@ -252,7 +254,7 @@ declare module "@elegant-router/types" {
|
||||
children: (CenterLevelRoute<GetChildRouteKey<K>> | LastLevelRoute<GetChildRouteKey<K>>)[];
|
||||
}
|
||||
: never;
|
||||
|
||||
|
||||
/**
|
||||
* the custom first level route
|
||||
*/
|
||||
|
@ -7,6 +7,7 @@ import { workflowPublishStatusRecord } from '@/constants/workflow';
|
||||
import {
|
||||
fetchActiveDefinition,
|
||||
fetchBatchDeleteDefinition,
|
||||
fetchCopyDefinition,
|
||||
fetchGetCategoryTree,
|
||||
fetchGetDefinitionList,
|
||||
fetchGetUnPublishDefinitionList,
|
||||
@ -16,11 +17,12 @@ import { useAppStore } from '@/store/modules/app';
|
||||
import { useAuth } from '@/hooks/business/auth';
|
||||
import { useDownload } from '@/hooks/business/download';
|
||||
import { useTable, useTableOperate } from '@/hooks/common/table';
|
||||
import { useRouterPush } from '@/hooks/common/router';
|
||||
import { $t } from '@/locales';
|
||||
import ButtonIcon from '@/components/custom/button-icon.vue';
|
||||
import DefinitionOperateDrawer from './modules/definition-operate-drawer.vue';
|
||||
import DefinitionSearch from './modules/definition-search.vue';
|
||||
import DefinitionImportModal from './modules/definition-import-modal.vue';
|
||||
import DefinitionOperateDrawer from '../modules/definition-operate-drawer.vue';
|
||||
import DefinitionSearch from '../modules/definition-search.vue';
|
||||
import DefinitionImportModal from '../modules/definition-import-modal.vue';
|
||||
|
||||
defineOptions({
|
||||
name: 'DefinitionList'
|
||||
@ -34,9 +36,9 @@ interface IsPublishOption {
|
||||
const appStore = useAppStore();
|
||||
const { download } = useDownload();
|
||||
const { hasAuth } = useAuth();
|
||||
const { routerPushByKey } = useRouterPush();
|
||||
|
||||
const { bool: importVisible, setTrue: showImportModal } = useBoolean();
|
||||
|
||||
const isPublish = ref<boolean>(true);
|
||||
const isPublishOptions = ref<IsPublishOption[]>([
|
||||
{
|
||||
@ -196,9 +198,23 @@ const {
|
||||
onPositiveClick={() => handleDelete(row.id)}
|
||||
/>
|
||||
),
|
||||
design: <ButtonIcon text type="primary" icon="material-symbols:design-services" tooltipContent="流程设计" />,
|
||||
design: (
|
||||
<ButtonIcon
|
||||
text
|
||||
type="primary"
|
||||
icon="material-symbols:design-services"
|
||||
tooltipContent="流程设计"
|
||||
onClick={() => handleDesign(row.id)}
|
||||
/>
|
||||
),
|
||||
preview: (
|
||||
<ButtonIcon text type="primary" icon="material-symbols:visibility-outline" tooltipContent="查看流程" />
|
||||
<ButtonIcon
|
||||
text
|
||||
type="primary"
|
||||
icon="material-symbols:visibility-outline"
|
||||
tooltipContent="查看流程"
|
||||
onClick={() => handlePreview(row.id)}
|
||||
/>
|
||||
),
|
||||
publish: (
|
||||
<ButtonIcon
|
||||
@ -206,10 +222,20 @@ const {
|
||||
type="primary"
|
||||
icon="material-symbols:publish"
|
||||
tooltipContent="发布流程"
|
||||
onClick={() => handlePublish(row.id)}
|
||||
popconfirmContent={`确定要发布 ${row.flowName} 吗?`}
|
||||
onPositiveClick={() => handlePublish(row.id)}
|
||||
/>
|
||||
),
|
||||
copy: (
|
||||
<ButtonIcon
|
||||
text
|
||||
type="primary"
|
||||
icon="material-symbols:content-copy"
|
||||
tooltipContent="复制流程"
|
||||
popconfirmContent={`确定要复制 ${row.flowName} 吗?`}
|
||||
onPositiveClick={() => handleCopy(row.id)}
|
||||
/>
|
||||
),
|
||||
copy: <ButtonIcon text type="primary" icon="material-symbols:content-copy" tooltipContent="复制流程" />,
|
||||
export: (
|
||||
<ButtonIcon
|
||||
text
|
||||
@ -287,6 +313,36 @@ async function handlePublish(id: CommonType.IdType) {
|
||||
getDataByPage();
|
||||
}
|
||||
|
||||
async function handleCopy(id: CommonType.IdType) {
|
||||
const { error } = await fetchCopyDefinition(id);
|
||||
if (error) return;
|
||||
window.$message?.success('复制成功');
|
||||
// 如果当前是已发布状态,则切换到未发布状态
|
||||
if (isPublish.value) {
|
||||
isPublish.value = false;
|
||||
} else {
|
||||
getDataByPage();
|
||||
}
|
||||
}
|
||||
|
||||
function handleDesign(id: CommonType.IdType) {
|
||||
routerPushByKey('workflow_process-definition_design', {
|
||||
query: {
|
||||
definitionId: id.toString(),
|
||||
disabled: 'false'
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function handlePreview(id: CommonType.IdType) {
|
||||
routerPushByKey('workflow_process-definition_design', {
|
||||
query: {
|
||||
definitionId: id.toString(),
|
||||
disabled: 'true'
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function handleExport(row: TableDataWithIndex<Api.Workflow.Definition>) {
|
||||
download(`/workflow/definition/exportDef/${row.id}`, {}, `${row.flowCode}.json`);
|
||||
}
|
||||
@ -325,7 +381,7 @@ const selectable = computed(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<TableSiderLayout :sider-title="$t('page.system.dept.title')">
|
||||
<TableSiderLayout sider-title="流程分类">
|
||||
<template #header-extra>
|
||||
<NButton size="small" text class="h-18px" @click.stop="() => handleResetTreeData()">
|
||||
<template #icon>
|
||||
@ -352,7 +408,7 @@ const selectable = computed(() => {
|
||||
@update:selected-keys="handleClickTree"
|
||||
>
|
||||
<template #empty>
|
||||
<NEmpty :description="$t('page.system.dept.empty')" class="h-full min-h-200px justify-center" />
|
||||
<NEmpty description="暂无流程分类" class="h-full min-h-200px justify-center" />
|
||||
</template>
|
||||
</NTree>
|
||||
</NSpin>
|
48
src/views/workflow/process-definition/design/index.vue
Normal file
48
src/views/workflow/process-definition/design/index.vue
Normal file
@ -0,0 +1,48 @@
|
||||
<script setup lang="ts">
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useEventListener } from '@vueuse/core';
|
||||
import { stringify } from 'qs';
|
||||
import { getToken } from '@/store/modules/auth/shared';
|
||||
import { getTabIdByRoute } from '@/store/modules/tab/shared';
|
||||
import { useTabStore } from '@/store/modules/tab';
|
||||
import { useRouterPush } from '@/hooks/common/router';
|
||||
import { getServiceBaseURL } from '@/utils/service';
|
||||
|
||||
const isHttpProxy = import.meta.env.DEV && import.meta.env.VITE_HTTP_PROXY === 'Y';
|
||||
const { baseURL } = getServiceBaseURL(import.meta.env, isHttpProxy);
|
||||
|
||||
const { removeTab } = useTabStore();
|
||||
const { routerPushByKey } = useRouterPush();
|
||||
const route = useRoute();
|
||||
const disabled = route.query.disabled === 'true';
|
||||
|
||||
const urlParams = {
|
||||
Authorization: `Bearer ${getToken()}`,
|
||||
id: route.query.definitionId,
|
||||
clientid: import.meta.env.VITE_APP_CLIENT_ID,
|
||||
disabled
|
||||
};
|
||||
|
||||
const iframeUrl = `${baseURL}/warm-flow-ui/index.html?${stringify(urlParams)}`;
|
||||
|
||||
function messageHandler(event: MessageEvent) {
|
||||
switch (event.data.method) {
|
||||
case 'close': {
|
||||
const tabId = getTabIdByRoute(route);
|
||||
removeTab(tabId);
|
||||
routerPushByKey('workflow_process-definition');
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// iframe监听组件内设计器保存事件
|
||||
useEventListener('message', messageHandler);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<iframe :src="iframeUrl" class="size-full"></iframe>
|
||||
</template>
|
Reference in New Issue
Block a user