declare namespace Api {
  /**
   * namespace Project
   *
   * backend api module: "project/project"
   */
  namespace Project {
    /** 项目状态编码 */
    type ProjectStatusCode = 'pending' | 'active' | 'paused' | 'completed' | 'cancelled' | 'archived';

    /** 项目状态动作编码 */
    type ProjectStatusActionCode = 'auto_start' | 'pause' | 'resume' | 'complete' | 'cancel' | 'reopen' | 'archive';

    /** 项目设置基础信息 */
    interface ProjectSettingBaseInfo {
      /** 项目 ID */
      id: string;
      /** 项目编码 */
      projectCode: string;
      /** 项目名称 */
      projectName: string;
      /** 项目方向字典值 */
      directionCode: string;
      /** 项目类型字典值 */
      projectType: string;
      /** 所属产品 ID */
      productId: string | null;
      /** 所属产品名称 */
      productName: string | null;
      /** 项目负责人用户昵称 */
      managerUserNickname: string | null;
      /** 项目负责人用户 ID */
      managerUserId: string | null;
      /** 项目状态编码 */
      statusCode: ProjectStatusCode;
      /** 计划开始日期 */
      plannedStartDate: string | null;
      /** 计划结束日期 */
      plannedEndDate: string | null;
      /** 实际开始日期 */
      actualStartDate: string | null;
      /** 实际结束日期 */
      actualEndDate: string | null;
      /** 项目说明 */
      projectDesc: string | null;
      /** 最近一次状态动作原因 */
      lastStatusReason: string | null;
    }

    /** 项目生命周期动作 */
    interface ProjectLifecycleAction {
      actionCode: Exclude<ProjectStatusActionCode, 'auto_start'>;
      actionName: string;
      needReason: boolean;
    }

    /** 项目生命周期信息 */
    interface ProjectLifecycleInfo {
      statusCode: ProjectStatusCode;
      lastStatusReason: string | null;
      availableActions: ProjectLifecycleAction[];
    }

    /** 执行状态编码 */
    type ProjectExecutionStatusCode = 'pending' | 'active' | 'paused' | 'completed' | 'cancelled';

    /** 执行动作编码 */
    type ProjectExecutionActionCode = 'start' | 'pause' | 'resume' | 'cancel' | 'complete';

    /** 任务状态编码 */
    type ProjectTaskStatusCode = 'pending' | 'active' | 'paused' | 'completed' | 'cancelled';

    /** 任务动作编码 */
    type ProjectTaskActionCode = 'auto_start' | 'pause' | 'resume' | 'complete' | 'cancel';

    interface LifecycleAction<ActionCode extends string = string> {
      actionCode: ActionCode;
      actionName: string;
      needReason: boolean;
    }

    interface StatusBoardItem {
      statusCode: string;
      statusName: string;
      count: number;
      sort: number;
      terminal?: boolean;
    }

    interface StatusBoard {
      total: number;
      items: StatusBoardItem[];
    }

    interface ProjectExecution {
      id: string;
      projectId: string;
      projectRequirementId: string | null;
      /** 关联项目需求名称（service 层批量回填；未关联 = null） */
      projectRequirementName: string | null;
      /** 关联项目需求状态编码（pending_confirm/pending_review/implementing/accepted/closed/rejected/cancelled） */
      projectRequirementStatusCode: string | null;
      executionName: string;
      executionType: string | null;
      ownerId: string;
      ownerNickname?: string | null;
      statusCode: ProjectExecutionStatusCode;
      statusName: string | null;
      terminal: boolean;
      allowEdit: boolean;
      availableActions: LifecycleAction<ProjectExecutionActionCode>[];
      plannedStartDate: string | null;
      plannedEndDate: string | null;
      actualStartDate: string | null;
      actualEndDate: string | null;
      progressRate: number;
      /** 优先级字典 value（rdms_req_priority）："0" P0 / "1" P1（默认）/ "2" P2 / "3" P3，数字越小越高 */
      priority: string;
      /** 优先级标签预留字段；当前后端不填、永远为 null，前端按 priority 自译 */
      priorityName: string | null;
      executionDesc: string | null;
      lastStatusReason: string | null;
      createTime: string;
      updateTime: string;
    }

    interface ExecutionAssignee {
      id: string;
      executionId: string;
      userId: string;
      userNickname?: string | null;
      joinedAt: string | null;
      removedAt: string | null;
      removedReason: string | null;
    }

    /** 执行协办人变更事件类型 */
    type ExecutionAssigneeActionType = 'join' | 'inactive' | 'owner_transfer_in' | 'owner_transfer_out';

    /** 执行协办人变更历史 */
    interface ExecutionAssigneeLog {
      id: string;
      executionId: string;
      actionType: ExecutionAssigneeActionType;
      userId: string;
      userNicknameSnapshot: string | null;
      operatorUserId: string;
      operatorNicknameSnapshot: string | null;
      actionTime: string;
      reason: string | null;
    }

    type ExecutionAssigneeLogSearchParams = CommonType.RecordNullable<
      Pick<PageParams, 'pageNo' | 'pageSize'> & {
        actionTypes: ExecutionAssigneeActionType[];
        userId: string;
        startTime: string;
        endTime: string;
      }
    >;

    /** 通用附件元数据（任务 / 工时等域共用，规则见 AttachmentValidator） */
    interface AttachmentItem {
      /**
       * 文件 ID（infra_file.id 字符串形式）。
       * 用于会话级清理时调用 DELETE /system/file/delete?id=xxx 删除孤儿文件。
       */
      fileId: string;
      url: string;
      name: string;
      size?: number;
      contentType?: string;
    }

    /** 任务详情 / 分页响应里嵌入的活跃协办人引用（按加入时间正序） */
    interface TaskAssigneeRef {
      id: string;
      userId: string;
      nickname: string;
      /** 加入时间，5.6 路径返；5.3 嵌入路径不返，留 undefined */
      joinedAt?: string | null;
    }

    /** 协办人变更事件类型（5.9 actionType） */
    type TaskAssigneeActionType = 'join' | 'inactive';

    /** 协办人变更日志 */
    interface TaskAssigneeLog {
      id: string;
      taskId: string;
      actionType: TaskAssigneeActionType;
      userId: string;
      userNicknameSnapshot: string | null;
      operatorUserId: string;
      operatorNicknameSnapshot: string | null;
      actionTime: string;
      reason: string | null;
    }

    type TaskAssigneeLogSearchParams = CommonType.RecordNullable<
      Pick<PageParams, 'pageNo' | 'pageSize'> & {
        actionTypes: TaskAssigneeActionType[];
        userId: string;
        startTime: string;
        endTime: string;
      }
    >;

    /** 5.7 加入协办人入参 */
    interface CreateTaskAssigneeParams {
      userId: string;
    }

    /** 5.8 退出协办人入参 */
    interface InactiveTaskAssigneeParams {
      reason: string;
    }

    interface ProjectTask {
      id: string;
      projectId: string;
      executionId: string;
      /** 所属执行名称；跨执行查询必有，单执行查询可缺省 */
      executionName?: string | null;
      /** 所属执行状态编码；跨执行查询必有，单执行查询可缺省（用于灰显已完成执行的任务行） */
      executionStatusCode?: ProjectExecutionStatusCode | null;
      parentTaskId: string | null;
      /** 所属执行关联的项目需求 ID（透传，未关联 = null） */
      projectRequirementId: string | null;
      /** 所属执行关联的项目需求名称（透传，未关联 = null；跨执行查询永远为 null，前端不在跨执行视角展示） */
      projectRequirementName: string | null;
      /** 所属执行关联的项目需求状态编码（同上） */
      projectRequirementStatusCode: string | null;
      taskTitle: string;
      type: string;
      ownerId: string;
      ownerNickname?: string | null;
      /** 所属执行的负责人 userId（按钮可见度公式用）；跨执行查询永远为 null，按钮判定退化为只看权限码 */
      executionOwnerId: string | null;
      /** 父任务负责人 userId（一级任务为 null） */
      parentTaskOwnerId: string | null;
      statusCode: ProjectTaskStatusCode;
      statusName: string | null;
      terminal: boolean;
      allowEdit: boolean;
      availableActions: LifecycleAction<ProjectTaskActionCode>[];
      progressRate: number;
      plannedStartDate: string | null;
      plannedEndDate: string | null;
      actualStartDate: string | null;
      actualEndDate: string | null;
      /** 优先级字典 value（rdms_req_priority）："0" P0 / "1" P1（默认）/ "2" P2 / "3" P3，数字越小越高 */
      priority: string;
      /** 优先级标签预留字段；当前后端不填、永远为 null，前端按 priority 自译 */
      priorityName: string | null;
      taskDesc: string | null;
      lastStatusReason: string | null;
      assignees?: TaskAssigneeRef[] | null;
      attachments?: AttachmentItem[] | null;
      /** 已填报工时合计，单位小时（0.5 颗粒，BigDecimal）。逻辑删除的工时不计入。 */
      totalSpentHours?: number | null;
      createTime: string;
      updateTime: string;
    }

    /**
     * 执行截止时间范围（基于 plannedEndDate）：overdue 逾期 / today 今天到期 / thisWeek 本周到期。
     * 与任务侧 dueRange 同口径，后端三档均排除终态执行（已完成 / 已取消）；未知值 = 不过滤。
     */
    type ProjectExecutionDueRange = 'overdue' | 'today' | 'thisWeek';

    /**
     * 项目执行分页入参（`GET /project/project/{projectId}/executions/page`）。
     *
     * - `involveUserId` / `ownerId` 互斥：同传后端不报错但语义变 AND，前端切视角时务必清另一字段。
     * - 不传 `involveUserId` 且不传 `ownerId` = 项目下全部执行。
     * - `dueRange` 按计划结束日期过滤，与其它参数 AND；详见 ProjectExecutionDueRange。
     */
    type ProjectExecutionSearchParams = CommonType.RecordNullable<
      Pick<PageParams, 'pageNo' | 'pageSize'> & {
        keyword: string;
        executionType: string;
        /** "我参与"语义：当前用户作为 owner 或活跃协办；与 ownerId 二选一 */
        involveUserId: string;
        /** 仅作为 owner 匹配；与 involveUserId 二选一 */
        ownerId: string;
        statusCode: string;
        /** 优先级筛选（字典 value：String "0"~"3"），不传 = 全部档位 */
        priority: string;
        dueRange: ProjectExecutionDueRange;
        updateTime: string[];
      }
    >;

    type ProjectExecutionStatusBoardParams = CommonType.RecordNullable<{
      keyword: string;
      executionType: string;
      /** "我参与"语义：当前用户作为 owner 或活跃协办；与 ownerId 二选一 */
      involveUserId: string;
      /** 仅作为 owner 匹配；与 involveUserId 二选一 */
      ownerId: string;
      /** 截止时间范围过滤，传入后各状态分组计数均在该范围内统计（口径同 page） */
      dueRange: ProjectExecutionDueRange;
      updateTime: string[];
    }>;

    /** 创建执行入参（含 ownerId + assigneeUserIds） */
    interface CreateProjectExecutionParams {
      executionName: string;
      executionType: string;
      ownerId: string;
      projectRequirementId: string | null;
      plannedStartDate: string | null;
      plannedEndDate: string | null;
      /** 优先级字典 value，必填，String "0"~"3" */
      priority: string;
      executionDesc: string | null;
      assigneeUserIds?: string[];
    }

    /** 执行创建/编辑弹层 emit 的统一 payload（创建时含 ownerId + assigneeUserIds；编辑时不含） */
    type SaveProjectExecutionParams = CreateProjectExecutionParams;

    /** 编辑执行入参（不含 ownerId / assigneeUserIds） */
    interface UpdateProjectExecutionParams {
      executionName: string;
      executionType: string;
      projectRequirementId: string | null;
      plannedStartDate: string | null;
      plannedEndDate: string | null;
      /** 优先级字典 value，必填，String "0"~"3" */
      priority: string;
      executionDesc: string | null;
    }

    interface ChangeExecutionOwnerParams {
      newOwnerId: string;
      reason: string | null;
    }

    interface ChangeExecutionStatusParams {
      actionCode: ProjectExecutionActionCode;
      reason: string | null;
    }

    interface CreateExecutionAssigneeParams {
      userId: string;
    }

    interface InactiveExecutionAssigneeParams {
      reason: string;
    }

    type ProjectTaskSearchParams = CommonType.RecordNullable<
      Pick<PageParams, 'pageNo' | 'pageSize'> & {
        keyword: string;
        parentTaskId: string;
        ownerId: string;
        statusCode: string;
        /** 优先级筛选（字典 value：String "0"~"3"），不传 = 全部档位 */
        priority: string;
        updateTime: string[];
      }
    >;

    type ProjectTaskStatusBoardParams = CommonType.RecordNullable<{
      keyword: string;
      parentTaskId: string;
      ownerId: string;
      updateTime: string[];
    }>;

    /**
     * 任务看板按状态分组的分页入参。
     *
     * - `statusCode` 缺省 → 返回该执行下任务状态字典中的全部状态（即使该状态下当前没有任务，也要回该列、`total=0`、`list=[]`）。
     * - 传入数组 → 只返回这些状态的列。
     * - `pageNo` / `pageSize` 应用到所有返回的状态（同一页码下各状态各自分页），前端不需要"每列独立 pageNo"。
     */
    type ProjectTaskBoardPageParams = CommonType.RecordNullable<
      Pick<PageParams, 'pageNo' | 'pageSize'> & {
        statusCode: string[];
        keyword: string;
        parentTaskId: string;
        ownerId: string;
        /** 优先级筛选（字典 value：String "0"~"3"），不传 = 全部档位 */
        priority: string;
        updateTime: string[];
      }
    >;

    interface ProjectTaskBoardColumn {
      statusCode: string;
      statusName: string;
      sort: number;
      terminal?: boolean;
      list: ProjectTask[];
      total: number;
    }

    interface ProjectTaskBoardPage {
      items: ProjectTaskBoardColumn[];
    }

    /** 截止时间快速选项（跨执行接口专属） */
    type ProjectTaskDueRange = 'overdue' | 'today' | 'thisWeek';

    /** 跨执行任务排序字段 */
    type ProjectTaskCrossSortBy = 'plannedEndDate' | 'priority' | 'updateTime' | 'createTime';

    type ProjectTaskCrossSortOrder = 'asc' | 'desc';

    /**
     * 项目级跨执行任务分页入参（`GET /project/project/{projectId}/tasks/page`）。
     *
     * - `involveUserId` / `ownerId` 互斥：同传只 `ownerId` 生效（后端 SQL 双重过滤）。
     * - `executionIds` 不传 = 项目内全部执行；空数组 `[]` = 明确返空。
     * - `executionInvolveUserId` = 限定到"该用户参与的执行"（owner 或活跃执行协办）；未参与任何执行时返空；
     *   与 `executionIds` 同传为 AND。用它表达"我参与的执行"范围，无需前端先查执行 id 再回传。
     * - `executionStatusCodes` 在任务可见性之上叠加"任务所属执行状态 ∈ 白名单"过滤；多值 OR；
     *   与 `executionIds` 同传时为 AND。详见 `docs/debt/跨执行任务接口-按执行状态过滤-契约调整.html`。
     * - 不传 `involveUserId / ownerId` 且无 `project:task:query` 权限时，后端静默降级为"自己有身份的范围"，不抛 403。
     */
    type ProjectTaskCrossSearchParams = CommonType.RecordNullable<
      Pick<PageParams, 'pageNo' | 'pageSize'> & {
        keyword: string;
        executionIds: string[];
        /**
         * 执行成员过滤：该用户作为执行 owner 或活跃执行协办人的执行 → 其下任务；未参与任何执行时返空。
         * 与 `involveUserId`（任务成员）正交，可同传取交集。
         */
        executionInvolveUserId: string;
        /** 任务所属执行的状态白名单（用于左侧执行池按状态 chip 切换时的任务范围过滤） */
        executionStatusCodes: ProjectExecutionStatusCode[];
        /** "我参与"语义：当前用户作为 owner 或活跃协办；与 ownerId 二选一 */
        involveUserId: string;
        /** 仅作为 owner 匹配；与 involveUserId 二选一 */
        ownerId: string;
        statusCodes: ProjectTaskStatusCode[];
        /** 优先级字典 value（"0"~"3"） */
        priority: string;
        parentTaskId: string;
        dueRange: ProjectTaskDueRange;
        /** 更新时间范围 [start, end]，格式 yyyy-MM-dd HH:mm:ss */
        updateTime: string[];
        sortBy: ProjectTaskCrossSortBy;
        sortOrder: ProjectTaskCrossSortOrder;
      }
    >;

    /** 项目级跨执行任务状态看板入参（与 page 同口径但不含 pageNo/pageSize/statusCodes/sortBy/sortOrder） */
    type ProjectTaskCrossStatusBoardParams = Omit<
      ProjectTaskCrossSearchParams,
      'pageNo' | 'pageSize' | 'statusCodes' | 'sortBy' | 'sortOrder'
    >;

    /** 项目级跨执行任务看板分页入参 */
    type ProjectTaskCrossBoardPageParams = Omit<ProjectTaskCrossSearchParams, 'sortBy' | 'sortOrder'>;

    /** 项目级"今日小条"汇总入参 */
    interface ProjectTaskSummaryParams {
      /** 默认 mine（不传也走 mine）；all 必须有 project:task:query 权限，否则 403 */
      scope?: 'mine' | 'all';
    }

    /**
     * 项目级"今日小条"汇总响应（`GET /project/project/{projectId}/tasks/summary`）。
     *
     * 数字一致性：dueThisWeek 的范围与 page?dueRange=thisWeek 完全一致（本周一~本周日）。
     * today / weekStart / weekEnd 直接展示，不要前端再算"今天/本周一"（服务器时区为 Asia/Shanghai）。
     */
    interface ProjectTaskSummary {
      overdue: number;
      dueToday: number;
      dueThisWeek: number;
      doneThisWeek: number;
      today: string;
      weekStart: string;
      weekEnd: string;
    }

    interface SaveProjectTaskParams {
      parentTaskId: string | null;
      taskTitle: string;
      type: string;
      ownerId: string | null;
      progressRate?: number;
      plannedStartDate: string | null;
      plannedEndDate: string | null;
      /** 优先级字典 value，必填，String "0"~"3" */
      priority: string;
      taskDesc: string | null;
      /** 仅创建任务时生效，编辑接口静默忽略；userId 必须是当前有效执行协办人且不能等于 ownerId */
      assigneeUserIds?: string[];
      /** 编辑语义：null 保留原值 / [] 清空 / [...] 整体替换 */
      attachments?: AttachmentItem[] | null;
    }

    interface ChangeTaskStatusParams {
      actionCode: ProjectTaskActionCode;
      reason: string | null;
    }

    /** 任务工时记录 */
    interface TaskWorklog {
      id: string;
      taskId: string;
      userId: string;
      userNickname: string | null;
      /** 段起始日期（含），YYYY-MM-DD；单天=与 endDate 相等 */
      startDate: string;
      /** 段结束日期（含），YYYY-MM-DD；单天=与 startDate 相等 */
      endDate: string;
      /** 本次填报小时数（BigDecimal，0.5 颗粒，> 0） */
      durationHours: number;
      /** 本次填报进度（0~100，scale=2） */
      progressRate: number;
      /** 难度，来自字典 rdms_task_item_worklog_difficulty */
      difficulty: string;
      /** 后端预留字段，目前始终为 null，前端按 difficulty + 字典 cache 自译 */
      difficultyName?: string | null;
      workContent: string | null;
      attachments?: AttachmentItem[] | null;
      createTime: string;
      updateTime: string;
    }

    type TaskWorklogSearchParams = CommonType.RecordNullable<
      Pick<PageParams, 'pageNo' | 'pageSize'> & {
        userId: string;
        startDate: string;
        endDate: string;
        /** 完成难度筛选，等值匹配；不传 = 全部 */
        difficulty: string;
      }
    >;

    interface SaveTaskWorklogParams {
      /** 段起始日期（含），YYYY-MM-DD */
      startDate: string;
      /** 段结束日期（含），YYYY-MM-DD；不得早于 startDate */
      endDate: string;
      /** 本次填报小时数，> 0 且 0.5 整数倍 */
      durationHours: number;
      /** 本次填报进度（0~100，scale=2，必填） */
      progressRate: number;
      /** 难度，来自字典 rdms_task_item_worklog_difficulty */
      difficulty: string;
      workContent?: string | null;
      /** 编辑语义：null 保留原值 / [] 清空 / [...] 替换 */
      attachments?: AttachmentItem[] | null;
    }

    /** 项目设置参数 */
    interface ProjectSettings {
      baseInfo: ProjectSettingBaseInfo;
      lifecycle: ProjectLifecycleInfo;
    }

    /** 项目设置基础信息参数 */
    interface UpdateProjectSettingBaseInfoParams {
      projectName: string;
      directionCode: string;
      projectType: string;
      plannedStartDate: string | null;
      plannedEndDate: string | null;
      projectDesc: string | null;
    }

    /** 项目成员状态 */
    type ProjectMemberStatus = 0 | 1;

    interface PageParams {
      pageNo: number;
      pageSize: number;
    }

    interface PageResult<T = any> {
      total: number;
      list: T[];
    }

    /** 项目入口页概览统计 */
    interface ProjectOverviewSummary {
      /** 项目状态数量映射，key 为后端状态编码 */
      statusCounts: Record<string, number>;
    }

    interface Project {
      /** 项目 ID */
      id: string;
      /** 项目编码 */
      projectCode: string;
      /** 项目名称 */
      projectName: string;
      /** 项目方向字典值 */
      directionCode: string;
      /** 项目类型字典值 */
      projectType: string;
      /** 所属产品 ID */
      productId: string | null;
      /** 所属产品名称 */
      productName?: string | null;
      /** 项目负责人用户 ID */
      managerUserId: string;
      /** 项目负责人用户昵称 */
      managerUserNickname?: string | null;
      /** 项目状态编码 */
      statusCode: ProjectStatusCode;
      /** 计划开始日期 */
      plannedStartDate: string | null;
      /** 计划结束日期 */
      plannedEndDate: string | null;
      /** 实际开始日期 */
      actualStartDate: string | null;
      /** 实际结束日期 */
      actualEndDate: string | null;
      /** 进度百分比 */
      progressRate: number;
      /** 项目说明 */
      projectDesc: string | null;
      /** 最近一次状态动作原因 */
      lastStatusReason: string | null;
      /** 创建时间 */
      createTime: string;
      /** 更新时间 */
      updateTime: string;
    }

    interface ProjectContext {
      currentProject: {
        id: string;
        projectCode: string;
        projectName: string;
        projectType: string;
        productId: string | null;
        managerUserId: string;
        statusCode: ProjectStatusCode;
      };
      currentRole: {
        roleId: string | null;
        roleCode: string | null;
        roleName: string | null;
        guestFlag: boolean;
      };
      navs: Array<{
        id: string;
        name: string;
        path: string;
        icon: string;
        sort: number;
      }>;
      buttons: string[];
    }

    interface ProjectMember {
      /** 成员关系 ID */
      id: string;
      /** 用户 ID */
      userId: string;
      /** 用户昵称 */
      userNickname: string;
      /** 角色 ID */
      roleId: string;
      /** 角色名称 */
      roleName: string;
      /** 角色编码 */
      roleCode: string;
      /** 是否项目负责人 */
      managerFlag: boolean;
      /** 成员状态 */
      status: ProjectMemberStatus;
      /** 加入时间 */
      joinedTime: string;
      /** 退出时间 */
      leftTime: string | null;
      /** 备注 */
      remark: string | null;
    }

    /** 项目搜索参数 */
    type ProjectSearchParams = CommonType.RecordNullable<
      Pick<PageParams, 'pageNo' | 'pageSize'> & {
        keyword: string;
        directionCode: string;
        projectType: string;
        productId: string;
        managerUserId: string;
        statusCode: ProjectStatusCode;
        updateTime: string[];
      }
    >;

    /** 创建/保存项目参数 */
    type SaveProjectParams = Pick<Project, 'projectName' | 'directionCode' | 'projectType' | 'projectDesc'> & {
      projectCode: string | null;
      productId: string | null;
      managerUserId: string;
      plannedStartDate: string | null;
      plannedEndDate: string | null;
      actualStartDate?: string | null;
      actualEndDate?: string | null;
    };

    /** 更新项目参数 */
    type UpdateProjectParams = { id: string } & SaveProjectParams;

    /** 变更项目状态参数 */
    interface ChangeProjectStatusParams {
      id: string;
      actionCode: ProjectStatusActionCode;
      reason: string | null;
    }

    /** 删除项目参数 */
    interface DeleteProjectParams {
      id: string;
      projectName: string;
      confirmText: string;
      reason: string;
    }

    /** 删除执行入参 */
    interface DeleteProjectExecutionParams {
      /** 二次确认：必须与当前执行名称完全一致 */
      executionName: string;
      /** 删除确认口令：接受 "删除" 或 "DELETE" */
      confirmText: string;
      /** 删除原因，写入审计日志 */
      reason: string;
    }

    /** 删除任务入参 */
    interface DeleteProjectTaskParams {
      /** 二次确认：必须与当前任务名称完全一致 */
      taskName: string;
      /** 删除确认口令：接受 "删除" 或 "DELETE" */
      confirmText: string;
      /** 删除原因，写入审计日志 */
      reason: string;
    }

    /** 执行删除预检（spec §2.1：判断是否需要走重型确认弹层） */
    interface ProjectExecutionDeletePrecheck {
      /** 该执行下任务总数（含子孙，含 completed），展示用 */
      taskCount: number;
      /** taskCount > 0 视为 true */
      hasDependentData: boolean;
    }

    /** 任务删除预检（spec §2.1） */
    interface ProjectTaskDeletePrecheck {
      /** 直接子任务数 */
      childTaskCount: number;
      /** 工作日志条数 */
      worklogCount: number;
      /** childTaskCount + worklogCount > 0 视为 true */
      hasDependentData: boolean;
    }

    /** 创建项目成员参数 */
    interface CreateProjectMemberParams {
      userId: string;
      roleId: string;
      remark: string | null;
      previousManagerUserId?: string | null;
      previousManagerRoleId?: string | null;
    }

    /** 更新项目成员参数 */
    interface UpdateProjectMemberParams {
      roleId: string;
      reason: string | null;
      remark: string | null;
      previousManagerUserId?: string | null;
      previousManagerRoleId?: string | null;
    }

    /** 移出项目成员参数 */
    interface InactiveProjectMemberParams {
      reason: string | null;
    }

    /**
     * 批量新增项目成员参数
     *
     * 刻意不复用 CreateProjectMemberParams：批量接口不承担"项目负责人交接"语义，
     * 后端兜底拒绝 roleId 为项目负责人角色的项。
     */
    interface BatchCreateProjectMembersParams {
      members: Array<{
        userId: string;
        roleId: string;
        remark?: string | null;
      }>;
    }

    /** 批量移出项目成员参数 */
    interface BatchInactiveProjectMembersParams {
      memberIds: string[];
      reason?: string | null;
    }

    /**
     * 项目创建（含初始团队）原子接口参数
     *
     * 新增项目两步向导提交的载荷。经理成员也由前端聚合到 members 数组中。
     */
    interface CreateProjectWithTeamParams {
      project: SaveProjectParams;
      members: CreateProjectMemberParams[];
      /** 关注人 user_id 数组（选填）；后端按 (user, object, role) 三元组幂等写入 project_watcher 角色 */
      watcherUserIds?: string[];
    }

    // ========== 项目需求相关类型定义 ==========
    /** 项目需求状态编码 */
    type ProjectRequirementStatusCode =
      | 'pending_claim'
      | 'pending_review'
      | 'reviewed'
      | 'review_rejected'
      | 'implementing'
      | 'accepted'
      | 'closed'
      | 'rejected'
      | 'cancelled';

    /** 项目需求状态动作编码 */
    type ProjectRequirementStatusActionCode =
      | 'claim_to_review'
      | 'claim_to_implement'
      | 'pass_review'
      | 'reject_review'
      | 'start_implement'
      | 'accept'
      | 'cancel'
      | 'close'
      | 'reject';

    /** 项目需求来源类型 */
    type ProjectRequirementSourceType = 'manual' | 'work_order' | 'product_requirement';

    /** 项目需求优先级 */
    type ProjectRequirementPriority = 0 | 1 | 2 | 3;

    /** 是否需要评审 */
    type ProjectRequirementReviewRequired = 0 | 1;

    interface ProjectRequirement {
      /** 需求 ID */
      id: string;
      /** 所属项目 ID */
      projectId: string;
      /** 父需求 ID，0 表示顶级需求 */
      parentId: string;
      /** 所属模块 ID */
      moduleId: string;
      /** 是否需要评审 */
      reviewRequired: ProjectRequirementReviewRequired;
      /** 需求标题 */
      title: string;
      /** 需求描述 */
      description?: string | null;
      /** 附件列表 */
      attachments?: AttachmentItem[] | null;
      /** 需求分类字典值 */
      category: string;
      /** 需求分类名称 */
      categoryName?: string | null;
      /** 需求来源类型 */
      sourceType: ProjectRequirementSourceType;
      /** 来源业务 ID */
      sourceBizId?: string | null;
      /** 优先级 */
      priority: ProjectRequirementPriority;
      /** 优先级名称 */
      priorityName?: string | null;
      /** 当前状态编码 */
      statusCode: ProjectRequirementStatusCode;
      /** 当前状态名称 */
      statusName?: string | null;
      /** 最近一次状态动作原因 */
      lastStatusReason?: string | null;
      /** 提出人用户 ID */
      proposerId: string;
      /** 提出人昵称 */
      proposerNickname?: string | null;
      /** 当前处理人用户 ID */
      currentHandlerUserId?: string | null;
      /** 当前处理人昵称 */
      currentHandlerUserNickname?: string | null;
      /** 预期完成日期 */
      expectedTime?: string | null;
      /** 排序值 */
      sort: number;
      /** 项目需求进度（BigDecimal，0.00 ~ 1.00；HALF_UP 两位小数）。读时聚合，后端不接受写入。 */
      progressRate: number;
      /** 创建时间 */
      createTime: string;
      /** 更新时间 */
      updateTime: string;
      /** 子需求列表 */
      children?: ProjectRequirement[];
    }

    interface ProjectRequirementModule {
      /** 模块 ID */
      id: string;
      /** 父模块 ID，0 表示顶级 */
      parentId: string;
      /** 所属项目 ID */
      projectId: string;
      /** 模块名称 */
      moduleName: string;
      /** 模块说明 */
      remark?: string | null;
      /** 图标 */
      icon?: string | null;
      /** 排序值 */
      sort: number;
      /** 子模块列表 */
      children?: ProjectRequirementModule[];
    }

    interface ProjectRequirementStatusDict {
      /** 状态编码 */
      statusCode: string;
      /** 状态名称 */
      statusName: string;
      /** 排序值 */
      sort: number;
      /** 是否初始状态 */
      initialFlag: boolean;
      /** 是否终态 */
      terminalFlag: boolean;
      /** 是否允许编辑 */
      allowEdit: boolean;
    }

    interface ProjectRequirementLifecycleAction {
      actionCode: ProjectRequirementStatusActionCode;
      actionName: string;
      toStatusCode: string;
      toStatusName: string;
      needReason: boolean;
    }

    interface ProjectRequirementBatchReqVO {
      projectId: string;
      requirementIds: string[];
    }

    interface ProjectRequirementAllowedTransitionBatchRespVO {
      requirementId: string;
      transitions: ProjectRequirementLifecycleAction[];
    }

    type ProjectRequirementReviewConclusion = 0 | 1;

    interface ProjectRequirementReviewAttendeeItem {
      userId: string;
      nickname: string;
    }

    interface ProjectRequirementReview {
      id: string;
      objectType: 'project_requirement';
      requirementId: string;
      operatorId: string;
      conclusion: ProjectRequirementReviewConclusion;
      reviewContent?: string | null;
      requirementEstimatedHours?: number | string | null;
      attendees?: ProjectRequirementReviewAttendeeItem[];
      attachments?: AttachmentItem[] | null;
      reviewTime?: string | null;
      createTime?: string;
      updateTime?: string;
    }

    interface ProjectRequirementReviewSubmitParams {
      projectId: string;
      requirementId: string;
      operatorId: string;
      conclusion: ProjectRequirementReviewConclusion;
      reviewContent?: string | null;
      requirementEstimatedHours?: number | string | null;
      attendees?: ProjectRequirementReviewAttendeeItem[];
      attachments?: AttachmentItem[] | null;
      reviewTime?: string | null;
    }

    /** 项目需求分页查询参数 */
    type ProjectRequirementSearchParams = CommonType.RecordNullable<
      Pick<PageParams, 'pageNo' | 'pageSize'> &
        Pick<
          ProjectRequirement,
          'moduleId' | 'parentId' | 'category' | 'priority' | 'statusCode' | 'currentHandlerUserId' | 'sourceType'
        > & {
          projectId: string;
          title: string;
        }
    >;

    /** 创建项目需求参数 */
    type SaveProjectRequirementParams = Pick<
      ProjectRequirement,
      | 'projectId'
      | 'moduleId'
      | 'reviewRequired'
      | 'title'
      | 'description'
      | 'attachments'
      | 'category'
      | 'priority'
      | 'proposerId'
      | 'proposerNickname'
      | 'currentHandlerUserId'
      | 'currentHandlerUserNickname'
      | 'expectedTime'
      | 'sort'
    >;

    /** 更新项目需求参数 */
    type UpdateProjectRequirementParams = { id: string } & SaveProjectRequirementParams;

    /** 变更项目需求状态参数 */
    interface ChangeProjectRequirementStatusParams {
      id: string;
      projectId: string;
      actionCode: string;
      reason?: string | null;
    }

    /** 关闭项目需求参数 */
    interface CloseProjectRequirementParams {
      id: string;
      projectId: string;
      reason: string;
    }

    /** 拆分项目需求参数 */
    type SplitProjectRequirementParams = Pick<
      ProjectRequirement,
      | 'parentId'
      | 'projectId'
      | 'moduleId'
      | 'reviewRequired'
      | 'title'
      | 'description'
      | 'attachments'
      | 'category'
      | 'priority'
      | 'proposerId'
      | 'proposerNickname'
      | 'currentHandlerUserId'
      | 'currentHandlerUserNickname'
      | 'expectedTime'
      | 'sort'
    >;

    /** 删除项目需求参数 */
    interface DeleteProjectRequirementParams {
      id: string;
      projectId: string;
    }

    /** 保存项目需求模块参数 */
    interface SaveProjectRequirementModuleParams {
      id?: string;
      projectId: string;
      parentId?: string | null;
      moduleName: string;
      remark?: string | null;
      icon?: string | null;
      sort?: number;
    }

    /** 删除项目需求模块参数 */
    interface DeleteProjectRequirementModuleParams {
      id?: string;
      projectId: string;
    }
  }
}
