资讯动态

DooTask 子任务机制详解:parent_id 驱动的父子任务模型、硬性限制与源码实现

发布时间:2026/10/15 2:34:02 来源:尧图企业网站定制
后端前端协同办公即时通讯企业应用【免费下载链接】dootaskDooTask是一款开源在线项目任务管理工具提供各类文档协作工具、在线思维导图、在线流程图、项目管理、任务分发、即时IM文件管理等工具同时消息功能使用非对称加密技术让你的沟通更安全。项目地址https://gitcode.com/gh_mirrors/do/dootask点击查看免费下载本文基于 DooTask 知识库文档《子任务是什么》及其配套的限制说明展开讲清子任务subtask的定义、关键属性、创建方式与全部硬性限制并结合 ProjectTask 模型、ProjectController 接口 与数据库迁移文件把「50 个子任务上限」「只允许 1 层嵌套」「父删子级联删」等规则逐条落到源码证据上。读完本文你将能准确判断子任务与关联任务的适用边界并能通过 API 或界面正确地拆分、统计和管理任务。一、子任务是什么子任务是挂在某个父任务下的下级任务用于把一个较大的工作拆分成多个可独立分配、独立完成的小步骤。父子关系通过project_tasks表的parent_id字段维护parent_id 0表示主任务根任务parent_id 0表示它是某个父任务的子任务。这一点在数据库迁移中可以直接确认建表脚本 中定义了该字段$table-bigInteger(parent_id)-nullable()-default(0)-comment(父级任务ID);同时 2023 年的索引迁移 为parent_id补充了复合索引([parent_id, deleted_at])说明「按父任务查子任务」是高频查询路径。从源码结构看DooTask 没有为子任务单独建表——每个子任务都是一条完整的project_tasks记录是一个独立的任务实例可以有自己的负责人、截止时间、状态。二、关键属性与源码印证知识库文档给出的四个关键属性都能在源码中找到对应实现2.1 从属关系父任务删除子任务级联删除子任务必须有父任务删除父任务时所有子任务一起删除软删还原父任务时子任务一并还原。ProjectTask::deleteTask() 的实现非常直白public function deleteTask($pushMsg true) { AbstractModel::transaction(function () { if ($this-dialog_id) { $dialog WebSocketDialog::find($this-dialog_id); $dialog?-deleteDialog(); } self::whereParentId($this-id)-remove(); // 级联软删全部子任务 $this-deleted_userid User::userid(); $this-save(); $this-addLog(删除{任务}); $this-delete(); }); ... }restoreTask() 对称地执行self::whereParentId($this-id)-withTrashed()-restore()保证父任务还原后子任务不丢失。2.2 独立性子任务有自己的状态、负责人与时间子任务写入ProjectTaskUser表时维护task_pid字段若任务本身是主任务则等于自身 id若是子任务则等于父任务 id。这一设计让「查某主任务的全部相关人员」可以一次性带出子任务成员见 relationUserids()。日志体系也利用了这种独立性addLog() 中子任务的日志文案会显示为「子任务」且日志的task_id记录在父任务名下task_id $this-parent_id ?: $this-id并附加record.subtask记录子任务自身信息因此任务动态里能看到「某某子任务被完成」这类细粒度操作。2.3 可见性继承父任务不可单独配置修改主任务可见性时ProjectTaskObserver::visibilityUpdate() 会执行ProjectTask::whereParentId($projectTask-id)-change([visibility $projectTask-visibility]);即父任务可见性一变其全部子任务的visibility被同步改写。创建子任务时同样如此task__addsub() 直接将父任务的visibility传给addTask()。2.4 完成度父任务显示「子任务 X/Y」模型内的 generateSubTaskData() 负责计算这三个对外属性sub_numparent_id等于本任务 id 的子任务总数sub_complete其中complete_at非空已完成的数量percent主任务已完成则强制 100否则取sub_complete / sub_num * 100。注意该函数开头有一段判断若parent_id 0自身是子任务sub_num与sub_complete直接置 0——这与「子任务不能再挂子任务」的限制相互印证。前端刷新进度不必拉全量任务task__subdata()api/project/task/subdata就是专门为此设计的轻量接口只返回{ id: 123, sub_num: 5, sub_complete: 2, percent: 40 }三、使用场景拆分大功能为多个开发步骤前端 / 后端 / 测试 / 上线将复杂请求分配给团队不同成员每个子任务有独立负责人在一个任务卡片里管理多个相关动作父任务进度条自动反映整体完成度。四、创建方式与默认值4.1 界面操作进入任务详情页 → 「子任务」区 → 「 新增子任务」→ 输入名称 → 回车。名称必填且不超过 255 字符addTask() 中校验mb_strlen($name) 255时抛出「子任务描述最多只能设置255个字」。4.2 API 创建task/addsubtask__addsub() 对应api/project/task/addsub需要 token 身份且要求调用者具备TASK_ADD项目权限。参数只有两个task_id父任务 id与name子任务名称。默认值规则从源码可完整读出字段默认值源码依据负责人当前登录用户owner [User::userid()]parent_id父任务 id直接取$task-idproject_id/column_id继承父任务直接取$task-project_id、$task-column_id计划时间继承父任务时间范围times [$task-start_at, $task-end_at]可见性继承父任务visibility $task-visibility创建成功后会向「子任务相关人员 项目主/副负责人」逐一推送add消息。另一个前置校验值得注意if ($task-complete_at) { return Base::retError(主任务已完成无法添加子任务); }即已完成的主任务不能追加子任务。4.3 建主任务时批量携带子任务api/project/task/add支持subtasks数组参数格式[{name, owner, times}]可在创建主任务的同时落库多个子任务。addTask() 中对每个子任务执行两个约束子任务若自带时间开始时间不能早于主任务开始时间、结束时间不能晚于主任务结束时间否则分别抛出「子任务开始时间不能小于主任务开始时间」「子任务结束时间不能大于主任务结束时间」未指定时间时继承主任务时间。五、硬性限制只允许 1 层、最多 50 个、不能跨项目DooTask 对子任务模型刻意做了简化以下三条限制由配套文档《子任务的限制嵌套 / 数量 / 跨项目》明确说明并均有代码兜底5.1 嵌套层级最多 1 层子任务的parent_id必须指向主任务parent_id 0的任务。批量创建分支只存在于if ($task-parent_id 0 $subtasks is_array($subtasks))中见 addTask()api/project/task/addsub也不做「父任务是子任务」时的拒绝提示之外的特殊分支——从整体数据约束看parent_id链被设计为深度 1。想表达更深层级官方建议改用关联任务或按业务拆成多个独立任务。5.2 数量上限单个父任务最多 50 个子任务addTask() 在落库前做硬校验if ($parent_id 0 ProjectTask::whereParentId($parent_id) -whereNull(project_tasks.complete_at) -whereNull(project_tasks.archived_at) -count() 50) { throw new ApiException(每个任务的子任务最多不能超过50个); }注意这里统计的是未完成且未归档的子任务——这意味着「归档已完成的子任务腾位置」是官方认可的扩容手段归档文档见知识库 howto 中任务归档条目。同一方法里还有两道相邻的容量红线供容量规划参考单个项目未完成任务不超过 2000 个、单个列表未完成任务不超过 500 个。5.3 跨项目禁止子任务自动继承父任务的project_id、column_id、可见性与对话归属不能把子任务移到别的项目。历史上存在子任务与父任务项目不一致的脏数据时由迁移脚本修复例如 2024_12_16 的修复迁移 会按父任务回写子任务的project_id/column_id2024_12_21 的迁移 则统一了子任务可见性——可见「与父任务同项目」是系统长期维护的不变式。若父任务被整体移动到其他项目子任务随之一起走。跨项目协作应使用关联任务。六、子任务不支持的功能清单以下能力在子任务上被显式屏蔽接口文档task__update() 的参数注释逐条标注了「子任务不支持」不支持项说明 / 源码依据独立任务聊天室dialog_id子任务无独立对话syncDialogUser() 中若parent_id 0直接把同步请求转发给父任务处理直接上传附件file_numgetFileNumAttribute() 中parent_id 0时file_num恒为 0附件必须挂在父任务重复周期loop更新接口参数loop标注「子任务不支持」传入会返回「子任务不支持此功能」错误分支、另一处校验任务详情content、背景色color同上参数标注「子任务不支持」修改协助人assist、任务标签task_tag同上优先级p_level/p_name/p_color主任务缺省时按系统优先级配置补齐addTask() 中if ($parent_id 0)分支才处理优先级子任务在升级为主任务时会从父任务继承优先级单独配置 visibility创建时继承父任务父任务变更时被 Observer 强制同步见 2.3此外还有一条时间约束addsub创建时子任务时间窗口被固定为父任务的时间范围批量创建时子任务时间必须落在主任务时间范围内见 4.3。七、父子联动行为汇总结合文档与 ProjectTask 模型父子联动可归纳为一张表父任务操作子任务行为删除级联软删deleteTask()中whereParentId($this-id)-remove()还原级联还原restoreTask()中withTrashed()-restore()归档 / 取消归档子任务跟随归档archived_at、archived_userid、archived_follow三个字段被整体同步归档逻辑跨项目移动子任务整体随迁完成不会自动完成子任务需要手动逐个完成此时父任务percent直接按 100% 展示修改可见性子任务 visibility 被批量改写其中archived_follow字段建表注释跟随项目归档在 模型属性注释 中也有说明用于区分「跟随归档」与「独立归档」两种状态。八、与「关联任务」的区别这是最容易混淆的一对概念两者底层实现完全不同维度子任务parent_id关联任务ProjectTaskRelation层级父子从属关系平级引用互不从属跨项目禁止强制同project_id允许删除联动父删则子级联软删两边互不影响只是关系记录消失完成度统计父任务显示「子任务 X/Y」并计算 percent不参与统计数量限制单个父任务最多 50 个子任务无硬上限附加能力—关联双向可见A 关联 B 后B 侧也能看到 Aapi/project/task/related返回task__related()从源码结构看关联任务由ProjectTaskRelation表承载字段含task_id、related_task_id、direction、userid方向分为消息提及mention / mentioned_by绑定dialog_idmsg_id与任务直接关联两类。选型经验法则有归属、要统计进度、要一起生灭用子任务只是引用、要跨项目、不希望删除联动用关联。一个有趣的衔接点「子任务升级为主任务」成功后系统会自动在两者之间写入一条 mention 方向的关联记录task__upgrade()让升级前的父子痕迹仍可通过关联任务找回。九、进阶把子任务升级为主任务DooTask 支持将子任务反转为独立主任务对应api/project/task/upgradetask__upgrade()参数为子任务task_id。执行过程在一个事务中完成校验parent_id 0直接返回「当前任务已是主任务」需具备TASK_MOVE权限置parent_id 0并从父任务继承p_level/p_name/p_color补齐子任务缺失的优先级字段将该任务在ProjectTaskUser中的task_pid改写为自身 id脱离父任务的人员聚合若可见性是「指定人可见」将原可见人列表重建到本任务名下父任务可见人记录不再自动跟随时需自持一份双端写入日志「子任务升级为主任务」「升级为主任务」并向双方推送update再补写双向关联见上一节。十、查询子任务的接口约定任务列表接口支持用parent_id直接查询子任务集合task 查询接口 的参数约定parent_id 0只查该主任务下的子任务此时归档过滤强制为 all忽略 project_id / scopeparent_id -1只查主任务where(parent_id, 0)。列表数据中还带聚合出的sub_num/sub_complete/ 进度百分比SQL 聚合count(*)与sum(CASE WHEN complete_at IS NOT NULL ...)按parent_id分组保证看板卡片不点开详情也能显示「子任务 X/Y」。十一、小结DooTask 的子任务是一个刻意保持简单的两层模型parent_id一个字段承载父子关系子任务复用完整任务表从而天然具备负责人、状态与时间等独立属性同时通过可见性继承、附件/对话/标签禁用、50 个上限与禁止跨项目等约束把复杂度控制在「一个父任务、一层子任务」之内。理解上述规则后你可以用task/addsub或建任务时携带subtasks参数完成拆分用sub_num/sub_complete/percent三件套跟踪整体进度在触及 50 上限时用「归档已完成子任务」腾出空间需要更深层级或跨项目引用时果断切换到关联任务ProjectTaskRelation。以上行为均基于当前仓库代码与知识库文档文档标注last_verified: v1.7.90核对若你的版本较旧或较新建议以 ProjectController.php 与 ProjectTask.php 中的实际实现为准。赞分享后端前端协同办公即时通讯企业应用【免费下载链接】dootaskDooTask是一款开源在线项目任务管理工具提供各类文档协作工具、在线思维导图、在线流程图、项目管理、任务分发、即时IM文件管理等工具同时消息功能使用非对称加密技术让你的沟通更安全。项目地址https://gitcode.com/gh_mirrors/do/dootask点击查看免费下载相关推荐DooTask 子任务的硬限制嵌套层级、数量上限与跨项目禁令的源码解析DooTask 子任务的硬限制嵌套层级、数量上限与跨项目禁令的源码解析 DooTask 的子任务subtask通过 parent_id 字段把大任务拆分为后端前端协同办公即时通讯企业应用CacheCloud Redis 任务流管理实战以 RedisClusterAppDeployTask 为例解读父子任务、步骤执行与重试机制CacheCloud Redis 任务流管理实战以 RedisClusterAppDeployTask 为例解读父子任务、步骤执行与重试机制 CacheClo后端运维Resque任务调度系统中的钩子机制详解Resque任务调度系统中的钩子机制详解 概述 Resque是一个基于Redis的Ruby后台任务处理系统它提供了一套完善的钩子 Hook 机制允许开发者在任务调度消息队列后端上一篇TrollStore 完整使用指南iOS 上永久签名安装 IPA 的实操手册下一篇Pulumi模块化开发创建可重用的基础设施组件库创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑