fc-workflow-components
v1.0.28
Published
基于 `Vue 3` + `Ant Design Vue` 的工作流页面组件包,包含审批列表、审批详情、流程管理、流程配置、流程版本等页面能力。
Readme
fc-workflow-components
基于 Vue 3 + Ant Design Vue 的工作流页面组件包,包含审批列表、审批详情、流程管理、流程配置、流程版本等页面能力。
适用于以下场景:
- 宿主项目通过后端动态菜单配置页面
- 宿主项目希望直接复用工作流页面组件
- 宿主项目已有自己的请求、用户状态、上传/附件/组织弹窗等基础能力,需要注入到工作流组件内使用
安装
npm install fc-workflow-components宿主项目需要自行安装并保持兼容版本的依赖:
vuevue-routerant-design-vue
导出内容
包入口当前导出以下内容:
WorkflowApproval:审批列表页WorkflowApprovalDetail:审批详情页WorkflowProcess:流程管理页WorkflowProcessConfiguration:流程配置页WorkflowProcessVersion:流程版本页ApprovalToolbar:审批详情页顶部工具栏workflowEventHub:工作流事件总线getWorkflowEventHubsetWorkflowAdaptersgetWorkflowAdaptersresetWorkflowAdaptersrequireWorkflowAdapterrequireWorkflowComponentgetWorkflowRequestgetWorkflowUserStoregetWorkflowComponentgetWorkflowComponentResolvercreateWorkflowPlugin
快速开始
1. 在宿主项目注入适配器
import { createApp } from 'vue';
import App from './App.vue';
import WorkflowPkg from 'fc-workflow-components';
import Request from '@/utils/request/request-util';
import { useUserStore } from '@/store/modules/user';
import { resolveWorkflowComponentByPath } from '@/router/workflow-component-map';
import FileUpload from '@/components/system/FileUpload/index.vue';
import FileDisplayItem from '@/components/system/FileDisplayItem/index.vue';
import OrganizationDrawer from '@/components/system/OrganizationDrawer/index.vue';
import NotFound from '@/components/Exception/404/index.vue';
const app = createApp(App);
app.use(WorkflowPkg, {
adapters: {
request: Request,
userStore: useUserStore,
resolveComponentByPath,
routes: {
home: '/home',
homeDetail: '/home/detail',
approvalDetail: '/approval/detail'
}
},
components: {
FileUpload,
FileDisplayItem,
OrganizationDrawer,
NotFound
}
});2. 直接在路由中使用
import {
WorkflowApproval,
WorkflowApprovalDetail,
WorkflowProcess,
WorkflowProcessConfiguration,
WorkflowProcessVersion,
ProcessInstanceTaskApi,
ProcessApi
} from 'fc-workflow-components';
export default [
{ path: '/approval', component: WorkflowApproval },
{ path: '/approval/detail', component: WorkflowApprovalDetail },
{ path: '/process', component: WorkflowProcess },
{ path: '/process/configuration', component: WorkflowProcessConfiguration },
{ path: '/process/version', component: WorkflowProcessVersion }
];使用内置 API
import {
ProcessApi,
ProcessInstanceApi,
ProcessInstanceTaskApi,
ProcessVersionConfigApi
} from 'fc-workflow-components';
const { data } = await ProcessInstanceTaskApi.todoList(params);适配器说明
必传适配器
request说明:请求实例,至少需要支持post方法。userStore说明:宿主项目的useUserStore方法。resolveComponentByPath说明:根据路径解析页面组件,供审批详情页内部动态加载业务页面使用。
推荐注入的组件适配器
FileUploadFileDisplayItemOrganizationDrawerNotFound
说明:
- 这些组件通过
components注入 - 插件安装时会自动同步注册到内部适配器仓库
- 如果缺少必需组件,运行时会抛出
Missing component adapter错误
后端动态菜单接入
推荐宿主项目统一维护一份“后端组件路径 -> 实际组件”的映射。
1. 创建工作流路径映射文件
示例:src/router/workflow-component-map.js
import {
WorkflowApproval,
WorkflowApprovalDetail,
WorkflowProcess,
WorkflowProcessConfiguration,
WorkflowProcessVersion
} from 'fc-workflow-components';
const MAP = {
'/workflow/approval/index': WorkflowApproval,
'/workflow/approval/detail': WorkflowApprovalDetail,
'/workflow/process/index': WorkflowProcess,
'/workflow/process/configuration': WorkflowProcessConfiguration,
'/workflow/process/version': WorkflowProcessVersion
};
export function resolveWorkflowComponentByPath(path) {
if (!path) return null;
const normalized = String(path).trim().replace(/\.vue$/i, '').replace(/\/+$/, '');
return MAP[normalized] || null;
}2. 动态注册路由时优先走工作流映射
import { resolveWorkflowComponentByPath } from '@/router/workflow-component-map';
const modules = import.meta.glob('/src/views/**/*.vue');
async function resolveLocalView(componentPath) {
const normalizedPath = String(componentPath || '')
.trim()
.replace(/\.vue$/i, '')
.replace(/^\/+/, '');
if (!normalizedPath) return null;
const fullPath = `/src/views/${normalizedPath}.vue`;
const indexPath = `/src/views/${normalizedPath}/index.vue`;
const loader = modules[fullPath] || modules[indexPath];
if (!loader) return null;
const mod = await loader();
return mod.default || mod;
}
async function resolveMenuComponent(componentPath) {
const workflowComponent = resolveWorkflowComponentByPath(componentPath);
if (workflowComponent) return workflowComponent;
return await resolveLocalView(componentPath);
}3. 在工作流插件中复用同一套解析逻辑
WorkflowApprovalDetail 内部也会根据路径动态渲染业务页面,所以 app.use 时注入的 resolveComponentByPath 必须和路由侧保持一致。
推荐写法:
import { resolveWorkflowComponentByPath } from '@/router/workflow-component-map';
import { useUserStore } from '@/store/modules/user';
const modules = import.meta.glob('/src/views/**/*.vue');
function findComponentByPath(menus, targetPath) {
for (const route of menus || []) {
if (route.path === targetPath) return route.component;
if (route.children?.length) {
const child = findComponentByPath(route.children, targetPath);
if (child) return child;
}
}
return null;
}
export async function resolveComponentByPath(path) {
const workflowComponent = resolveWorkflowComponentByPath(path);
if (workflowComponent) return workflowComponent;
const componentPath = findComponentByPath(useUserStore().menus, path);
const normalizedPath = String(componentPath || path || '')
.trim()
.replace(/\.vue$/i, '')
.replace(/^\/+/, '');
if (!normalizedPath) return null;
const fullPath = `/src/views/${normalizedPath}.vue`;
const indexPath = `/src/views/${normalizedPath}/index.vue`;
const loader = modules[fullPath] || modules[indexPath];
if (!loader) return null;
const mod = await loader();
return mod.default || mod;
}这套逻辑的好处是:
- 如果后端返回的是工作流标准路径,例如
/workflow/process/index,会直接命中工作流组件 - 如果后端返回的是宿主本地页面路径,例如
/business/home/mainProcess,即使菜单未命中,也能兜底从src/views直接加载
宿主约定
工作流组件默认会依赖以下宿主能力:
- 用户信息与菜单树
- 请求封装
- 上传组件
- 附件展示组件
- 组织选择弹窗
- 404 页面
如果宿主项目的组件命名不同,建议在接入层统一做一层适配,不要直接修改工作流组件内部逻辑。
EventHub 用法
import { workflowEventHub } from 'fc-workflow-components';
workflowEventHub.emit('refreshFile');
workflowEventHub.on('quoteFile', file => {
console.log(file);
});行为说明
审批详情页的页面解析顺序
WorkflowApprovalDetail 会按以下顺序解析业务页面:
- 工作流内置路径映射
- 宿主菜单树中的
path -> component - 宿主
src/views下的本地文件兜底加载 - 仍未命中时渲染宿主注入的
NotFound
因此页面中间区域出现 404,通常不是浏览器路由没命中,而是“业务组件路径未解析到”。
办理人支持多选
ApprovalSubmitDrawer 中的“办理人”当前支持多选:
- 下拉框支持多选
- 组织弹窗选人时会追加并自动去重
- 提交时仍写回
handlerUser、handlerName - 默认以逗号分隔字符串形式提交,方便兼容现有后端接口
常见问题
1. 报错:Missing adapter: request
没有注入 request,或者在宿主安装插件前就提前访问了适配器。
请确认:
- 已在
app.use(WorkflowPkg, { adapters })中注入request - 宿主使用的是当前仓库内最新版代码
2. 报错:Missing component adapter: FileDisplayItem
没有通过 components 注入宿主组件,或者宿主仍在使用旧版本打包产物。
请确认:
FileUploadFileDisplayItemOrganizationDrawerNotFound
已在 components 中传入。
3. 页面中间显示 404
通常不是路由没匹配到,而是业务页面组件路径没解析到。
重点检查:
- 后端返回的
version.data.value workflow-component-map.js中是否配置了对应工作流路径- 宿主
src/views下是否存在对应文件 resolveComponentByPath是否包含本地src/views兜底逻辑
4. 控制台提示 onVisibleChange is deprecated
这是 ant-design-vue 的下拉事件升级提示。
请统一改用:
@openChangeonOpenChange
不要再使用:
@visibleChangeonVisibleChange
5. 本地联调时 Vite 报 403 或外部目录不可访问
如果宿主项目通过别名直接引用本地 fc-workflow-components/src/index.js,需要在 Vite 中同时放行宿主目录和组件库目录。
示例:
import { defineConfig, searchForWorkspaceRoot } from 'vite';
export default defineConfig(() => ({
server: {
fs: {
allow: [
searchForWorkspaceRoot(process.cwd()),
'D:/project/process/packages/fc-workflow-components'
]
}
}
}));本地联调建议
如果宿主项目和组件库在同一工作区,推荐直接把宿主项目的别名指向本地源码,而不是 node_modules 中的旧打包文件。
示例思路:
resolve: {
alias: {
'fc-workflow-components': 'D:/project/process/packages/fc-workflow-components/src/index.js'
}
}这样联调时改动可以即时生效,也能避免“源码已修、宿主仍跑旧包”的问题。
构建
npm run build发布前检查建议
- 确认入口导出与 README 一致
- 确认适配器名称未变更
- 确认审批详情页的路径解析逻辑未被破坏
- 确认
components注入会同步进入内部适配器仓库 - 确认宿主联调方式仍可用
