# 工作流、待办、站内通知与附件(公共扩展基础版 v1) 网站入口:[简明使用指南](/docs/collaboration) | [高级指南](/docs/advanced#collaboration)。四个组件作为独立公共能力模块发布,各有自定义 H5、Docker 容器、PostgreSQL 账号和 schema;核心不包含它们的流程规则或表结构。首次安装由运维核对包并明确批准提供者。 ## 普通用户如何使用 1. 登录工作空间,左侧打开“工作流中心”。填写标题,逐个增加审批节点并选择审批人;节点按排列顺序执行,最多 8 级。可保存为个人模板,发起时保存独立节点快照。 2. 发起人及被选参与人可查看流程;只有当前节点的指定审批人可同意或拒绝,拒绝必须填写原因。发起人可撤销尚未结束的流程。修改和审批须携带当前版本,冲突后刷新。 3. 打开“统一待办”,查看人工任务及分配给自己的当前审批任务。人工任务由负责人完成、创建人撤销;审批任务在工作流中心处理,不维护另一份审批状态。 4. 打开“站内通知”,查看收到的消息、审批动态和人工待办动态,可逐条或批量标记已读。刷新获取新消息;本版不发送业务邮件或短信,也没有浏览器推送。 5. 打开“附件中心”,选择文件并选择共享人;未选择则仅上传者可见。下载先验证权限和完整性,再由工作空间确认并交给浏览器保存,不在 iframe 内执行文件。 当前测试网站新注册账号按既有策略获得系统管理员角色。其他部署给员工分配 `workflow-user`、`todos-user`、`notifications-user`、`attachments-user` 等实际需要的模块角色;统一待办还需工作流读取权限,站内通知还需工作流、待办读取权限。模板不会自动授予员工,也不会因管理员角色而跳过指定审批人、收件人及附件共享名单的业务检查。 ## 能力接口 | 扩展 | 能力名 → 底座动作 | 用途 | |---|---|---| | workflow | read → list;start → create;define → edit;approve → publish;reject → reject;cancel → submit | 查询、发起、保存个人模板、同意、拒绝、撤销 | | todos | read → list;create → create;complete → edit;cancel → reject | 人工待办及当前审批视图 | | notifications | read → list;send → create;markread → edit | 本人收件箱、发送站内消息、本人已读标记 | | attachments | read/download → list;begin/chunk/finish → create;delete → edit | 文件元数据、分片上传下载、删除 | 以上能力名实际加模块前缀,例如 `workflow.start`、`attachments.finish`。接口主版本均为 1。底座动作是现有通用传输动作,对外业务方法名表达实际含义,不要求修改核心支持某一种审批业务。 ### 业务应用接入工作流 ```json { "capabilities": ["identity.get", "workflow.start", "workflow.read"], "dependencies": [{"extension": "workflow", "api_version": 1}] } ``` 消费者后端以当前请求的 ActorID/RequestID 调用 `host.call`;不能在 H5 中指定模块或伪造调用人。Go 示例: ```go out, err := host.Call(modulekit.HostRequest{ Service: "workflow.start", ActorID: req.ActorID, RequestID: req.RequestID, Payload: json.RawMessage(`{ "title":"采购申请", "business_key":"PO-2026-001", "summary":"采购办公用品", "steps":[{"name":"经理审批","assignee_id":"实际核心用户ID"}] }`), }) // 成功后将返回实例 id/version/status/body。应用自己保存实例 id。 ``` Python、Java 使用同一协议发送相同 service 与 JSON。审批人必须是当前可选通讯录中的启用用户;使用核心用户 ID,不用邮箱作主键。发起人自己成为审批人目前允许,需要“四眼审批”等规则时由业务应用或后续模板策略限制。 `workflow.read` 输入 `{}` 返回列表,`{"id":"实例ID"}` 返回指定实例,`{"status":"pending"}` 按状态查询。返回 `{items,definitions,events,contacts,more}`。对消费者只返回该可信来源应用的对象;直接进入工作流中心则能看到本人作为发起人或参与人的跨应用对象。 `workflow.define` 输入与 start 相同,保存不可变的个人模板;start 可以传 `definition_id` 代替 steps。不能同时覆盖节点。模板可被模板所有者及预设参与人查看使用;不是全公司共享模板设计器。每个进行中实例已有独立快照,不受后续新模板影响。 同意、拒绝、撤销输入均为 `{"id":"实例ID","version":1,"comment":"意见"}`。同意须当前节点本人;拒绝须填写原因;撤销须发起人且流程未结束。同一个业务标识在同一来源、同一发起人下只能有一个进行中实例;结束后可重新发起。 ### 待办与站内通知 `todos.create` 输入 `{"title":"准备材料","assignee_id":"核心用户ID","description":"说明","due_at":"2026-11-05T09:00:00Z"}`,due_at 可省略。complete/cancel 输入 `{id,version,comment}`。read 返回 `{items,workflow_tasks,events,contacts,more}`;前者是人工任务,后者是当前分配的审批任务。 `notifications.send` 输入 `{"title":"材料提醒","message":"请补充附件","recipients":["用户ID"]}`,收件人 1–20 个。read 返回 `{items,unread,contacts,more}`,其中通知 ID 含来源前缀。markread 输入 `{"ids":["通知ID"]}`,最多 200 个,必须属于当前收件箱。 `workflow.inbox` 和 `todos.inbox` 是这组提供者之间的内部汇总能力,只接受已明确批准的 `todos` / `notifications` 来源并始终按当前参与人过滤;普通业务应用不能借其查询其他来源。跨应用查询不能从 payload 传 source、actor 或任意 URL。 ### 附件分片协议 | 步骤 | 能力 | 输入 | |---|---|---| | 申请上传 | attachments.begin | `{name,size,sha256,share_with:[用户ID]}` | | 按序上传 | attachments.chunk | `{id,index,data:Base64}`,index 从 0 开始,每片最多 20KiB 原文 | | 确认完整 | attachments.finish | `{id}`,核对总大小、分片、SHA256 与基本文件头 | | 列出可见文件 | attachments.read | `{}` | | 下载一片 | attachments.download | `{id,index}` | | 删除 | attachments.delete | `{id,version}`,仅上传者可操作 | 直接使用 H5 的动作接口时,在 payload 增加 `operation`,值为表中 begin/chunk/finish/read/download/delete;后端按当前授权动作再次核验。先 begin,再顺序 chunk,最后 finish。每一步保存自己的 request_id;经业务模块转调时,每片应使用一次独立的外层业务动作请求,不能在同一次 Execute 中用同一能力提交不同分片。未知结果或断连时使用原号重试;换新号重传已接收分片会被顺序检查拒绝。页面内重试保留上传进度,重新加载页面后可删除未完成记录并重传;未完成记录 24 小时后,在本人下一次新上传事务中清理。 单文件最多 2MiB,每人跨来源合计 32MiB;支持 PDF、PNG、JPEG、TXT、CSV、DOCX、XLSX。默认私人,最多共享 20 人;共享接收人不能代替上传者删除或补写文件。共享名单本版不支持发布后修改。文件名与路径、分片顺序、大小、摘要及常见格式文件头均检查;这不等同病毒查杀,Office/文档本身仍可能含有有害内容。文件永不由服务器执行,不在线内嵌渲染;下一阶段可接入专用查杀/隔离服务。 浏览器通过通用 `PlatformUI.saveFile(name, base64)` 请求工作空间保存文件。父页面只接收有限类型和最大 2MiB 的内容,使用 application/octet-stream 并要求用户确认;不授予 iframe 同源权限、联网或 allow-downloads。业务动作桥每分钟最多 300 次、最多 8 个在途;后端原有每用户每秒 20、并发 4、总并发 16 等限制不变。附件页按序分片并处理限流。 ## 数据库与一致性 每个组件的 manifest 声明 database.engine=postgres、database.connect 与 database/schema.sql。实际账号/schema 由受控 PostgreSQL 服务分配;在“模块管理 → 组件 → 数据库定义”查看 SQL,在“应用数据库”查看分配状态;密码只给该后端,不回传页面。 主要表:collaboration_objects(对象与版本)、collaboration_events(事务内事件)、collaboration_receipts(用户/可信来源/请求号与内容指纹)、collaboration_read_marks(个人已读)、collaboration_chunks(文件分片)、collaboration_audit(动作审计)。四个 schema 各自建同名表,并不共享账号或查询彼此数据库。所有写入将对象修改、事件、回执、审计放入单个本扩展事务。 审批任务直接由流程状态计算,避免跨库双写。通知从工作流及待办的已提交事件读取,已读状态保存在通知扩展;依赖不可用时明确返回失败,不宣称“空列表”。这是按需汇总,不是后台消息总线或可靠推送服务。业务应用自己的单据和流程实例仍处于不同事务:先保留稳定业务标识与请求号,保存实例ID,按实例ID查询确认后更新业务状态;需要原子提交或异步回调时另做 outbox/补偿设计。 列表按最近记录做有界返回:对象最多 50 条,通知最多 200 条,more 表示截断;工作流支持指定 ID 与按状态查询,待办的审批查询只读取分配给本人的进行中实例,不被已完成历史挤占。本版尚无完整历史分页、批量导出和自动保留策略,适合作为基础能力起步。 ## 安装与维护 源码:internal/extensions/collaboration;程序入口:cmd/collaboration-extension。分别使用 `-ldflags "-X main.component=workflow"`(其他三个同理)构建,配套 examples/extensions//manifest.json、ui/、database/schema.sql。先安装 workflow,再 todos,最后 notifications;attachments 无模块依赖。只有通过受控安装和明确批准的提供者才启动,个人应用发布不能创建或覆盖这些公共服务。 升级先备份平台状态、全部组件包和专属 PostgreSQL;核对运行中流程,不随意改变已保存的步骤。所有者/参与人 ACL 是扩展自身规则,不自动继承普通 records.* 的部门范围,也不会因为系统管理员就开放所有私有业务数据。当前不支持并行网关、条件表达式、会签、转办、可视化 BPMN、跨库原子事务、邮件/短信通知或病毒扫描。已有 CMS、请假、报销不会在安装时自动迁移到新引擎,业务应用可按上述契约逐步接入。 隔离验收入口为 `TestCollaborationDockerFixture`,必须在新建 `/var/lib/oa-collaboration-*` 目录显式开启,使用独立注册表和数据库 scope;涵盖审批、待办、通知、附件、越权、来源隔离、幂等及重启,不使用生产业务数据或发送真实邮件。