# RMDC 项目管理模块详细设计说明书 (DDS)

**产品名称**: RMDC 项目管理模块 (rmdc-project-management)  
**版本**: v5.0  
**编制日期**: 2026-01-16

---

## 1. 概述

### 1.1 模块定位
`rmdc-project-management` 是 RMDC 系统的核心业务模块，负责维护以 K8s Namespace 为粒度的"项目"全生命周期管理。该模块通过与 `rmdc-work-procedure`（工单模块）深度集成，实现了基于 Git Flow 思想的"草稿-审核-发布"的版本控制流程。

### 1.2 核心职责
1. **项目全生命周期管理**: 创建、维护（编辑/通过工单）、发布、归档/删除
2. **版本控制**: 记录项目配置的变更历史，支持版本回溯与差异对比（Diff）
3. **细粒度权限控制**: 基于 ACL 的权限控制，精确到用户与项目模块
4. **授权管理**: 管理项目的一级 TOTP 授权信息，与 Watchdog 交互

### 1.3 版本修订历史

| 版本 | 日期 | 修订内容 |
|:---|:---|:---|
| v1.0 | 2026-01-06 | 初始版本 |
| v2.0 | 2026-01-12 | 增加生命周期状态机设计 |
| v3.0 | 2026-01-14 | 完善草稿版本设计、细化权限模型、优化数据库结构 |
| v4.0 | 2026-01-15 | 新增项目与工单模块状态同步机制设计（HTTP回调、状态映射表、风险处理） |
| v5.0 | 2026-01-16 | 状态同步机制从HTTP回调改为接口注入方式，HTTP回调方案移至备选文档 |

---

## 2. 系统架构

### 2.1 模块依赖关系

```mermaid
graph TB
    subgraph 核心层
        Core[rmdc-core<br/>API Gateway]
    end

    subgraph 业务协作
        PM[rmdc-project-management]
        WP[rmdc-work-procedure<br/>工单流程]
        UA[rmdc-user-auth<br/>用户认证/权限]
        Aud[rmdc-audit-log<br/>审计日志]
    end

    subgraph 边缘交互
        EH[rmdc-exchange-hub<br/>消息网关]
        WD[rmdc-watchdog]
    end

    Core --> PM
    PM -->|用户鉴权/查询| UA
    PM -->|项目权限管理| UA
    PM -->|发起审批/接收回调| WP
    PM -->|记录操作日志| Aud
    PM -->|下发授权指令| EH
    EH <--> WD
```

---

## 3. 项目生命周期管理

### 3.1 生命周期状态机

引入明确的生命周期状态机，管理项目从创建到销毁的全过程。

| 状态 | 说明 | 触发动作 | 权限 |
|:---|:---|:---|:---|
| **INIT** | 项目元数据已创建，等待详细信息录入 | 超级管理员创建项目 | SuperAdmin |
| **DRAFTING** | 正在进行初始信息填写（关联填写工单） | 指定填写人保存/编辑 | 填写人/SuperAdmin |
| **REVIEWING** | 初始信息或变更信息提交审核 | 提交审核 | SuperAdmin |
| **RELEASED** | 审核通过，正常运行中 | 审核通过 | All (View) |
| **MODIFYING** | 存在活跃的变更工单（不影响主线运行） | 发起修改工单 | Owner/SuperAdmin |
| **ARCHIVED** | 软删除状态，不可见但保留数据 | 删除项目 | SuperAdmin |

### 3.2 状态转换图

```mermaid
stateDiagram-v2
    [*] --> INIT: 创建项目
    
    INIT --> DRAFTING: 分配填写人
    
    DRAFTING --> DRAFTING: 保存草稿
    DRAFTING --> REVIEWING: 提交审核
    
    REVIEWING --> DRAFTING: 审核打回
    REVIEWING --> RELEASED: 审核通过
    
    RELEASED --> MODIFYING: 发起修改工单
    RELEASED --> ARCHIVED: 归档删除
    
    MODIFYING --> MODIFYING: 保存草稿
    MODIFYING --> REVIEWING: 提交变更审核
    MODIFYING --> RELEASED: 撤销变更/审核通过
    
    ARCHIVED --> [*]
    
    note right of RELEASED: 项目认证状态=official
    note right of DRAFTING: 支持多次保存草稿
    note right of MODIFYING: 可同时存在多个变更工单
```

### 3.3 生命周期与工单状态映射

| 工单事件 | 工单目标状态 | 项目生命周期状态 | 说明 |
|:---|:---|:---|:---|
| create | created | INIT→DRAFTING | 创建填写工单 |
| draft_save | in_progress | DRAFTING/MODIFYING(保持) | 保存草稿 |
| complete | pending_review | REVIEWING | 提交审核 |
| resubmit | pending_review | REVIEWING | 被打回后重新提交 |
| return | returned | DRAFTING | 审核人打回 |
| approve | approved→closed | RELEASED | 审核人通过 |

### 3.4 状态同步机制设计

#### 3.4.1 设计原则

项目模块（`rmdc-project-management`）与工单模块（`rmdc-work-procedure`）之间需要双向协作：
1. **项目 → 工单**：项目模块调用工单模块创建/转换工单
2. **工单 → 项目**：工单状态变更后同步更新项目生命周期状态

当前系统采用 **"模块化单体"架构**，所有模块运行在 `rmdc-core` 同一进程中，因此采用 **接口注入（依赖注入）** 方式实现模块间回调，而非 HTTP 回调。

> **备选方案**：如未来需要微服务化部署，可参考 [HTTP回调设计方案](5-rmdc-project-http-callback-design.md)

#### 3.4.2 架构设计（接口注入方式）

```mermaid
sequenceDiagram
    participant Frontend as 前端
    participant PM as rmdc-project-management
    participant Core as rmdc-core
    participant WP as rmdc-work-procedure
    
    Note over Core: 启动时注入回调接口
    Core->>PM: 注入 WorkflowTransitioner
    Core->>WP: 注入 ProjectLifecycleUpdater
    
    Note over PM,WP: 提交审核流程
    Frontend->>PM: POST /api/project/draft/submit
    PM->>WP: workflowTransitioner.TransitionWorkflow(complete)
    WP->>WP: 状态机转换 (in_progress → pending_review)
    WP->>PM: projectLifecycleUpdater.SetLifecycleToReviewing()
    PM->>PM: 更新 lifecycle_status = REVIEWING
    WP-->>PM: 返回新状态
    PM-->>Frontend: 返回成功响应
```

#### 3.4.3 接口定义

**项目模块调用工单模块的接口**：

```go
// WorkflowTransitioner 工单状态转换接口
// 由 rmdc-core 在初始化时注入，项目模块通过此接口调用工单模块
type WorkflowTransitioner interface {
    // TransitionWorkflow 触发工单状态转换
    // @param workflowID string - 工单ID
    // @param event string - 事件类型 (complete/submit/resubmit等)
    // @param operatorID uint64 - 操作人ID
    // @param operatorName string - 操作人姓名
    // @param remark string - 操作备注
    // @return newStatus string - 工单新状态
    // @return error - 错误
    TransitionWorkflow(workflowID, event string, operatorID uint64, 
                       operatorName string, remark string) (newStatus string, err error)
}
```

**工单模块回调项目模块的接口**：

```go
// ProjectLifecycleUpdater 项目生命周期状态更新接口
// 由 rmdc-core 在初始化时注入，工单模块状态变更时调用
type ProjectLifecycleUpdater interface {
    // UpdateLifecycleStatus 更新项目生命周期状态
    UpdateLifecycleStatus(projectID, lifecycleStatus string) error
    
    // SetLifecycleToDrafting 设置为填写中状态（工单被打回后）
    SetLifecycleToDrafting(projectID string) error
    
    // SetLifecycleToReviewing 设置为审核中状态（提交审核时）
    SetLifecycleToReviewing(projectID string) error
    
    // SetLifecycleToReleased 设置为已发布状态（审批通过时）
    SetLifecycleToReleased(projectID string) error
    
    // SetLifecycleToModifying 设置为变更中状态（发起修改工单时）
    SetLifecycleToModifying(projectID string) error
}
```

#### 3.4.4 依赖注入流程

在 `rmdc-core/cmd/main.go` 中完成模块间的依赖注入：

```go
// 1. 初始化项目和工单服务
projectSvc := projectHandler.RegisterRoutes(r, dbs.Project, authMiddleware)
workflowSvc := workflowHandler.RegisterRoutes(r, dbs.Workflow, authMiddleware)

// 2. 注入工单→项目的回调（状态同步）
projectCallbackSvc := initProjectWorkflowCallbacks(dbs.Project)
workflowSvc.SetProjectLifecycleUpdater(projectCallbackSvc)

// 3. 注入项目→工单的调用（创建/转换工单）
workflowCreator := initProjectWorkflowCreator(workflowSvc)
projectSvc.SetWorkflowCreator(workflowCreator)

workflowTransitioner := initProjectWorkflowTransitioner(workflowSvc)
projectSvc.SetWorkflowTransitioner(workflowTransitioner)
```

#### 3.4.5 接口注入方式的优势

| 特性 | 说明 |
|:---|:---|
| **简单高效** | 进程内调用，无网络开销 |
| **类型安全** | 编译期检查接口实现 |
| **事务一致性** | 可在同一数据库事务中执行 |
| **无需重试** | 不涉及网络失败，无需复杂的重试机制 |
| **开发调试** | 调试更简单，堆栈清晰 |

#### 3.4.6 与 HTTP 回调的对比

| 特性 | 接口注入（当前实现） | HTTP 回调 |
|:---|:---|:---|
| **模块解耦** | ⚠️ 接口级解耦 | ✅ 完全解耦 |
| **分布式支持** | ❌ 不支持 | ✅ 支持 |
| **性能** | ✅ 进程内调用 | ⚠️ 网络开销 |
| **复杂度** | ✅ 简单直接 | ⚠️ 需要重试/幂等处理 |
| **适用场景** | 模块化单体架构 | 微服务架构 |

> 如果未来系统需要微服务化，可参考 [HTTP回调设计方案](5-rmdc-project-http-callback-design.md) 进行迁移。

### 3.5 详细状态映射表

根据工单类型和事件，映射到项目生命周期状态：

#### 3.5.1 填写工单 (project_detail)

| 工单事件 | 工单From状态 | 工单To状态 | 项目生命周期状态 | 说明 |
|:---|:---|:---|:---|:---|
| `create` | - | `created` | `INIT→DRAFTING` | 创建填写工单，分配填写人 |
| `accept` | `assigned` | `in_progress` | `DRAFTING` (保持) | 填写人开始填写 |
| `draft_save` | `in_progress` | `in_progress` | `DRAFTING` (保持) | 保存草稿 |
| `submit/complete` | `in_progress` | `pending_review` | `REVIEWING` | 提交审核 |
| `return` | `pending_review` | `returned` | `DRAFTING` | 审核人打回 |
| `resubmit` | `returned` | `pending_review` | `REVIEWING` | 重新提交 |
| `approve` | `pending_review` | `approved` | `RELEASED` | 审核通过，项目发布 |
| `revoke` | any | `revoked` | `INIT` | 撤销工单，恢复初始状态 |

#### 3.5.2 修改工单 (project_modify)

| 工单事件 | 工单From状态 | 工单To状态 | 项目生命周期状态 | 说明 |
|:---|:---|:---|:---|:---|
| `create` | - | `created` | `RELEASED→MODIFYING` | 发起修改工单 |
| `accept` | `assigned` | `in_progress` | `MODIFYING` (保持) | 开始修改 |
| `draft_save` | `in_progress` | `in_progress` | `MODIFYING` (保持) | 保存草稿 |
| `submit/complete` | `in_progress` | `pending_review` | `REVIEWING` | 提交审核 |
| `return` | `pending_review` | `returned` | `MODIFYING` | 审核人打回 |
| `resubmit` | `returned` | `pending_review` | `REVIEWING` | 重新提交 |
| `approve` | `pending_review` | `approved` | `RELEASED` | 审核通过，合并修改 |
| `revoke` | any | `revoked` | `RELEASED` | 撤销工单，恢复发布状态 |

### 3.6 回调处理实现

工单模块状态转换后，自动调用已注入的 `ProjectLifecycleUpdater` 接口更新项目状态：

```go
// 工单模块 - 状态转换后触发项目状态更新
func (s *WorkflowService) handleProjectLifecycleCallback(workflow *entity.Workflow, event string) {
    // 从业务载荷中获取项目ID
    projectID, ok := workflow.BusinessPayload["project_id"].(string)
    if !ok || projectID == "" {
        return
    }
    
    // 根据事件类型更新项目生命周期状态
    if s.projectLifecycleUpdater != nil {
        switch event {
        case entity.EventApprove:
            s.projectLifecycleUpdater.SetLifecycleToReleased(projectID)
        case entity.EventReturn:
            s.projectLifecycleUpdater.SetLifecycleToDrafting(projectID)
        case entity.EventComplete, entity.EventResubmit:
            s.projectLifecycleUpdater.SetLifecycleToReviewing(projectID)
        }
    }
}
```

---

## 4. 权限控制模型

### 4.1 设计原则

权限控制分为 **功能权限** (RBAC) 和 **数据权限** (ACL)，**数据权限需精确到项目模块级别**。

> **重要决策**：项目权限相关表设计在 `rmdc-user-auth` 模块中，由该模块统一管理所有权限数据。

### 4.2 功能权限 (RBAC)

| 权限代码 | 说明 | 角色 |
|:---|:---|:---|
| `project:create` | 创建项目 | SuperAdmin |
| `project:delete` | 删除/归档项目 | SuperAdmin |
| `project:edit` | 直接编辑项目 | SuperAdmin |
| `project:edit_workflow` | 通过工单编辑项目 | User (有ACL权限) |
| `project:auth_manage` | 一级/二级授权管理 | SuperAdmin |
| `project:permission_manage` | 项目权限分配 | SuperAdmin |

### 4.3 数据权限 (ACL) - 模块级别

#### 4.3.1 权限模块定义

| 模块代码 | 模块名称 | 说明 |
|:---|:---|:---|
| `basic_info` | 基本信息模块 | 项目名称、命名空间、省份城市等 |
| `business_info` | 部署业务模块 | 部署人、部署时间、系统版本等 |
| `environment_info` | 部署环境模块 | 主机信息、网络环境、域名等 |
| `middleware_info` | 部署中间件模块 | MySQL、Redis、EMQX等中间件配置 |
| `authorization_info` | 项目授权模块 | TOTP授权信息（仅SuperAdmin） |

#### 4.3.2 权限类型

| 权限类型 | 说明 |
|:---|:---|
| `view` | 查看权限（可查看项目信息，可发起修改工单） |
| `export` | 导出权限（可导出项目信息） |

> **说明**：编辑权限通过工单系统实现，拥有 `view` 权限的用户可以发起修改工单，由 SuperAdmin 审批后生效。

### 4.4 权限规则

1. **SuperAdmin**: 拥有所有项目的所有模块的全部权限，可直接修改
2. **Admin**: 可以访问自己被授权的项目模块，可以向普通用户转授权限
3. **Normal User**: 只能访问被授权的项目模块，修改需通过工单
4. **项目填写人**: 自动获得该项目的查看权限
5. **授权模块**: 仅 SuperAdmin 可见

---

## 5. 版本控制设计 (GIT-like)

### 5.1 设计原则

采用**统一版本表**设计，将正式版本和草稿版本存储在同一张表中，通过 `version_type` 字段区分。

### 5.2 版本类型

| 版本类型 | 代码 | 说明 |
|:---|:---|:---|
| 正式版本 | `official` | 审核通过后的正式版本，构成版本历史 |
| 填写草稿 | `fill_draft` | 项目创建时填写人的草稿 |
| 修改草稿 | `modify_draft` | 发起变更工单时的草稿 |

### 5.3 版本与工单关系

1. **填写草稿**: 与填写工单 1:1 关联
2. **修改草稿**: 与修改工单 1:1 关联
3. **正式版本**: 审核通过后由草稿转化而来
4. **一个项目可以有多个修改草稿**（对应多个修改工单）


### 5.4. 版本快照机制

每次审核通过后，系统自动生成一个**完整快照**存储到 `project_versions` 表中。

#### 5.4.1 快照结构

```go
// VersionSnapshot 版本快照结构
type VersionSnapshot struct {
    BasicInfo        *BasicInfo        `json:"basic_info"`
    DeployBusiness   *DeployBusiness   `json:"deploy_business"`
    DeployEnv        *DeployEnv        `json:"deploy_env"`
    DeployMiddleware *DeployMiddleware `json:"deploy_middleware"`
}
```

#### 5.4.2 快照生成时机

| 场景 | 版本号 | 版本类型 | 说明 |
|:---|:---|:---|:---|
| 项目首次审批通过 | v1 | official | 项目初始版本 |
| 修改工单审批通过 | v(N+1) | official | 增量版本 |
| **超管直接修改** | v(N+1) | official | **重要：超管直改也必须生成新版本** |
| 用户保存草稿 | 0 | fill_draft/modify_draft | 临时版本，不计入历史 |

#### 5.4.3 超级管理员直改与版本一致性

**问题风险**：
如果超级管理员直接修改 `projects` 表数据而不生成版本历史，会导致版本链断裂，后续基于旧版本的工单 Diff 结果将失效或产生误导。

**解决方案**：
超级管理员的 "Direct Edit" 操作必须被视为一次**自动审批通过的事务**：

1.  **原子操作**：更新 `projects` 表 + 插入 `project_versions` 表必须在同一数据库事务中完成。
2.  **版本归属**：生成的 Version 记录中，`workflow_id` 为空（或特定系统标识），`committer_id` 记录为 SuperAdmin ID，`commit_message` 强制填写或自动生成（如 "SuperAdmin Direct Update"）。
3.  **结果**：确保 `projects.current_version` 永远指向最新的 `project_versions.version`。

#### 5.4.4 并发修改与冲突检测 (Optimistic Locking)

由于超级管理员可能在其他用户编辑草稿期间直接修改项目，需要引入乐观锁机制处理冲突。

**冲突场景**：
1.  用户 A 基于 v3 版本创建草稿（Draft based on v3）。
2.  超级管理员直接修改项目，版本升级为 v4（Current = v4）。
3.  用户 A 提交草稿审核。

**处理策略**：
1.  **提交时校验**：工单提交/审核接口需校验 `draft.base_version == project.current_version`。
2.  **冲突提示**：如果版本不一致，后端返回 `409 Conflict` 错误。
3.  **前端交互**：
    *   提示用户："项目已被修改，当前草稿已过期"。
    *   提供 **"Rebase" (变基)** 选项：将当前草稿的修改重新应用到最新的 v4 版本上（即自动合并，若有字段冲突则让用户手动解决）。
    *   或者提供 **"Diff Check"**：让用户查看当前草稿与最新 v4 的差异，决定是否覆盖或调整。

---

### 5.5 版本 Diff 算法

采用 **JSON Diff** 算法，对比两个版本快照的差异。

#### 5.5.1 差异结构

```go
// DiffResult 差异结果
type DiffResult struct {
    Module     string       `json:"module"`       // 模块名称
    FieldDiffs []FieldDiff  `json:"field_diffs"`  // 字段差异列表
}

// FieldDiff 字段差异
type FieldDiff struct {
    FieldPath  string      `json:"field_path"`   // 字段路径 如 "deploy_business.deployer_name"
    FieldName  string      `json:"field_name"`   // 字段中文名
    OldValue   interface{} `json:"old_value"`    // 旧值
    NewValue   interface{} `json:"new_value"`    // 新值
    ChangeType string      `json:"change_type"`  // add/modify/delete
}
```

#### 5.5.2 Diff 实现

```go
// CompareVersions 比较两个版本的差异
// @param baseVersion 基准版本（通常是较早的版本或 master）
// @param targetVersion 目标版本（通常是较新的版本或草稿）
// @return []DiffResult 差异结果列表，按模块分组
func (s *VersionService) CompareVersions(
    ctx context.Context, 
    baseVersion, targetVersion *VersionSnapshot,
) ([]DiffResult, error) {
    var results []DiffResult
    
    // 分模块对比
    modules := []struct {
        Name   string
        Base   interface{}
        Target interface{}
    }{
        {"基本信息", baseVersion.BasicInfo, targetVersion.BasicInfo},
        {"部署业务", baseVersion.DeployBusiness, targetVersion.DeployBusiness},
        {"部署环境", baseVersion.DeployEnv, targetVersion.DeployEnv},
        {"部署中间件", baseVersion.DeployMiddleware, targetVersion.DeployMiddleware},
    }
    
    for _, m := range modules {
        diffs := s.diffJSON(m.Base, m.Target)
        if len(diffs) > 0 {
            results = append(results, DiffResult{
                Module:     m.Name,
                FieldDiffs: diffs,
            })
        }
    }
    return results, nil
}
```

---

### 5.6 版本历史查询

#### 5.6.1 版本列表结构

```go
// VersionHistory 版本历史记录
type VersionHistory struct {
    Version       int       `json:"version"`        // 版本号
    VersionType   string    `json:"version_type"`   // 版本类型
    CommitMessage string    `json:"commit_message"` // 变更说明
    CommitterID   int64     `json:"committer_id"`   // 提交人 ID
    CommitterName string    `json:"committer_name"` // 提交人姓名
    WorkflowID    string    `json:"workflow_id"`    // 关联工单 ID
    CreatedAt     time.Time `json:"created_at"`     // 创建时间
    ChangeSummary string    `json:"change_summary"` // 变更摘要（如：修改了 3 个字段）
}
```

#### 5.6.2 版本历史 API

| 方法 | 路径 | 描述 |
|:---|:---|:---|
| POST | `/api/project/version/list` | 获取版本历史列表 |
| POST | `/api/project/version/detail` | 获取指定版本详情 |
| POST | `/api/project/version/diff` | 对比两个版本差异 |
| POST | `/api/project/version/diff-with-current` | 对比指定版本与当前版本差异 |

---

### 5.7 前端展示设计

#### 5.7.1 版本历史页面

```
┌─────────────────────────────────────────────────────────────────┐
│  项目版本历史 - [项目名称]                                        │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  ●──v3 (当前版本)  2026-01-14 15:30  张三                        │
│  │   └─ 变更说明: 更新部署环境信息                                │
│  │   └─ 关联工单: #WF-20260114-001                              │
│  │                                                              │
│  ●──v2              2026-01-10 10:00  李四                      │
│  │   └─ 变更说明: 修改中间件配置                                  │
│  │   └─ 关联工单: #WF-20260110-002                              │
│  │                                                              │
│  ●──v1 (初始版本)   2026-01-05 09:00  王五                       │
│      └─ 变更说明: 项目初始填写                                    │
│      └─ 关联工单: #WF-20260105-001                              │
│                                                                 │
│  [查看详情]  [对比版本]                                          │
└─────────────────────────────────────────────────────────────────┘
```

#### 5.7.2 Diff 对比页面

```
┌─────────────────────────────────────────────────────────────────┐
│  版本对比: v2 → v3                                               │
├─────────────────────────────────────────────────────────────────┤
│  模块: 部署环境                                                  │
│  ┌───────────────────────────────────────────────────────────┐  │
│  │ 字段           │ v2 (旧值)        │ v3 (新值)             │  │
│  ├───────────────────────────────────────────────────────────┤  │
│  │ 主机台数       │ 3                │ 5                     │  │
│  │ 主要公网 IP    │ 10.0.0.1         │ 192.168.1.100         │  │
│  │ 域名 URL       │ -                │ www.example.com [新增] │  │
│  └───────────────────────────────────────────────────────────┘  │
│                                                                 │
│  模块: 部署中间件                                                │
│  ┌───────────────────────────────────────────────────────────┐  │
│  │ 字段              │ v2 (旧值)     │ v3 (新值)             │  │
│  ├───────────────────────────────────────────────────────────┤  │
│  │ MySQL.内网端口    │ 3306          │ 3307                  │  │
│  └───────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────┘
```

---

## 6. 数据模型设计

### 6.1 设计决策

| 决策点 | 决策 | 理由 |
|:---|:---|:---|
| JSONB vs 分表 | 使用JSONB存储 | 1. 项目信息结构复杂但查询简单 2. 版本快照需完整存储 3. 减少JOIN提升性能 |
| 草稿存储位置 | project_versions表 | 统一版本管理，方便Diff比较 |
| 权限表位置 | rmdc-user-auth模块 | 统一权限管理，便于跨模块授权 |

### 6.2 ER 图

```mermaid
erDiagram
    projects ||--o{ project_versions : has
    projects ||--o{ project_workflows : has
    projects ||--|| project_auth_configs : has
    
    projects {
        bigint id PK
        string project_id UK
        string name
        string namespace UK
        string lifecycle_status
        string certification_status
        bigint detail_filler_id
        string detail_filler_name
        int current_version
        jsonb basic_info
        jsonb deploy_business
        jsonb deploy_env
        jsonb deploy_middleware
        datetime created_at
        datetime updated_at
        datetime deleted_at
    }
    
    project_versions {
        bigint id PK
        string project_id FK
        int version
        string version_type
        bigint user_id
        string workflow_id
        jsonb snapshot_data
        string commit_message
        bigint committer_id
        string committer_name
        datetime created_at
        datetime updated_at
    }
    
    project_workflows {
        bigint id PK
        string project_id FK
        string workflow_id UK
        string workflow_type
        string status
        datetime created_at
    }
    
    project_auth_configs {
        bigint id PK
        string project_id FK
        string tier_one_secret
        int time_offset
        bool totp_enabled
        string auth_type
        int auth_days
        datetime created_at
        datetime updated_at
    }
```

**表关系说明**：

| 关系 | 说明 |
|:---|:---|
| `projects` → `project_versions` | 一对多，一个项目有多个版本记录（含草稿） |
| `projects` → `project_workflows` | 一对多，一个项目可关联多个工单 |
| `projects` → `project_auth_configs` | 一对一，一个项目对应一个授权配置 |

**字段说明**：

| 表 | 字段 | 说明 |
|:---|:---|:---|
| projects | lifecycle_status | INIT/DRAFTING/REVIEWING/RELEASED/MODIFYING/ARCHIVED |
| projects | certification_status | draft/pending/official |
| project_versions | version_type | official/fill_draft/modify_draft |
| project_versions | workflow_id | 关联 rmdc-work-procedure 模块的工单 ID |
| project_workflows | workflow_type | fill(填写)/modify(修改) |


> **注意**：`workflow_id` 字段引用 `rmdc-work-procedure` 模块的 `workflows` 表，属于跨模块关联，不在本模块ER图中展示外部表结构。

### 6.3 主表 DDL - projects

```go
// Project 项目主表
type Project struct {
    ID                int64           `gorm:"primaryKey;autoIncrement" json:"id"`
    ProjectID         string          `gorm:"type:varchar(64);uniqueIndex;not null" json:"project_id"`
    Name              string          `gorm:"type:varchar(128);not null" json:"name"`
    Namespace         string          `gorm:"type:varchar(64);uniqueIndex;not null" json:"namespace"`
    
    // 生命周期状态
    LifecycleStatus   string          `gorm:"type:varchar(32);default:'INIT'" json:"lifecycle_status"`
    // 认证状态 (draft/pending/official)
    CertificationStatus string        `gorm:"type:varchar(32);default:'draft'" json:"certification_status"`
    
    // 当前正式版本号
    CurrentVersion    int             `gorm:"default:0" json:"current_version"`
    
    // 主版本数据 (使用JSONB存储，便于版本快照)
    BasicInfo         json.RawMessage `gorm:"type:jsonb" json:"basic_info"`
    DeployBusiness    json.RawMessage `gorm:"type:jsonb" json:"deploy_business"`
    DeployEnv         json.RawMessage `gorm:"type:jsonb" json:"deploy_env"`
    DeployMiddleware  json.RawMessage `gorm:"type:jsonb" json:"deploy_middleware"`
    
    // 项目填写人
    DetailFillerID    int64           `json:"detail_filler_id"`
    DetailFillerName  string          `gorm:"type:varchar(64)" json:"detail_filler_name"`
    
    // 审计字段
    CreatedBy         int64           `json:"created_by"`
    CreatedByName     string          `gorm:"type:varchar(64)" json:"created_by_name"`
    
    common.BaseModel
}
```

### 6.4 版本表 DDL - project_versions

```go
// ProjectVersion 项目版本表 (含草稿)
type ProjectVersion struct {
    ID            int64           `gorm:"primaryKey;autoIncrement" json:"id"`
    ProjectID     string          `gorm:"type:varchar(64);index;not null" json:"project_id"`
    
    // 版本号 (正式版本递增, 草稿为0)
    Version       int             `gorm:"not null;default:0" json:"version"`
    
    // 版本类型: official/fill_draft/modify_draft
    VersionType   string          `gorm:"type:varchar(32);not null" json:"version_type"`
    
    // 草稿所属用户ID (仅草稿类型有值)
    UserID        int64           `gorm:"index" json:"user_id"`
    UserName      string          `gorm:"type:varchar(64)" json:"user_name"`
    
    // 关联工单ID (1:1关系, 仅草稿类型有值)
    WorkflowID    string          `gorm:"type:varchar(64);index" json:"workflow_id"`
    
    // 完整快照数据
    SnapshotData  json.RawMessage `gorm:"type:jsonb" json:"snapshot_data"`
    
    // 变更信息
    CommitMessage string          `gorm:"type:varchar(255)" json:"commit_message"`
    CommitterID   int64           `json:"committer_id"`
    CommitterName string          `gorm:"type:varchar(64)" json:"committer_name"`
    
    CreatedAt     time.Time       `json:"created_at"`
    UpdatedAt     time.Time       `json:"updated_at"`
}
```

### 6.5 项目工单关联表 DDL - project_workflows

```go
// ProjectWorkflow 项目与工单关联表
type ProjectWorkflow struct {
    ID           int64     `gorm:"primaryKey;autoIncrement" json:"id"`
    ProjectID    string    `gorm:"type:varchar(64);index;not null" json:"project_id"`
    WorkflowID   string    `gorm:"type:varchar(64);uniqueIndex;not null" json:"workflow_id"`
    
    // 工单类型: fill(填写)/modify(修改)
    WorkflowType string    `gorm:"type:varchar(32);not null" json:"workflow_type"`
    
    // 工单状态 (冗余存储，便于查询)
    Status       string    `gorm:"type:varchar(32)" json:"status"`
    
    CreatedAt    time.Time `json:"created_at"`
    UpdatedAt    time.Time `json:"updated_at"`
}
```

### 6.6 权限表 DDL (位于 rmdc-user-auth 模块)

```go
// ProjectACL 项目权限表 (模块级别)
type ProjectACL struct {
    ID           int64     `gorm:"primaryKey;autoIncrement" json:"id"`
    ProjectID    string    `gorm:"type:varchar(64);index;not null" json:"project_id"`
    UserID       int64     `gorm:"index;not null" json:"user_id"`
    
    // 模块代码: basic_info/business_info/environment_info/middleware_info/authorization_info
    ModuleCode   string    `gorm:"type:varchar(32);not null" json:"module_code"`
    
    // 权限类型
    CanView      bool      `gorm:"default:false" json:"can_view"`
    
    // 授权信息
    GrantedBy    int64     `json:"granted_by"`
    GrantedAt    time.Time `json:"granted_at"`
    
    UpdatedAt    time.Time `json:"updated_at"`
}
```

---

## 7. 接口设计 (API)

### 7.1 项目管理接口

| 方法 | 路径 | 描述 | 权限 |
|:---|:---|:---|:---|
| POST | `/api/project/list` | 获取项目列表 (自动过滤ACL) | Login |
| POST | `/api/project/detail` | 获取项目详情 (Master版本) | View ACL |
| POST | `/api/project/create` | 创建项目 | SuperAdmin |
| POST | `/api/project/update` | 直接更新项目 | SuperAdmin |
| POST | `/api/project/delete` | 删除项目 (软删除) | SuperAdmin |
| POST | `/api/project/export` | 导出项目信息 | Export ACL |

### 7.2 版本管理接口

| 方法 | 路径 | 描述 | 权限 |
|:---|:---|:---|:---|
| POST | `/api/project/version/list` | 获取版本历史列表 | View ACL |
| POST | `/api/project/version/detail` | 获取指定版本详情 | View ACL |
| POST | `/api/project/version/diff` | 获取版本差异 | View ACL |

### 7.3 草稿管理接口

| 方法 | 路径 | 描述 | 权限 |
|:---|:---|:---|:---|
| POST | `/api/project/draft/get` | 获取当前用户的草稿 | View ACL |
| POST | `/api/project/draft/save` | 保存草稿 | View ACL |
| POST | `/api/project/draft/submit` | 提交审核 | View ACL |
| POST | `/api/project/draft/discard` | 放弃草稿 | View ACL |

### 7.4 权限管理接口 (SuperAdmin)

| 方法 | 路径 | 描述 | 权限 |
|:---|:---|:---|:---|
| POST | `/api/project/permission/list` | 获取项目权限列表 | SuperAdmin |
| POST | `/api/project/permission/grant` | 授予权限 | SuperAdmin |
| POST | `/api/project/permission/revoke` | 撤销权限 | SuperAdmin |
| POST | `/api/project/permission/batch` | 批量设置权限 | SuperAdmin |

---

## 8. 业务流程

### 8.1 项目创建流程

```mermaid
sequenceDiagram
    participant Admin as 超级管理员
    participant PM as rmdc-project-management
    participant WP as rmdc-work-procedure
    participant User as 填写人

    Admin->>PM: POST /api/project/create
    PM->>PM: 创建Project记录 (status=INIT)
    PM->>WP: 创建project_detail工单
    WP-->>PM: 返回workflow_id
    PM->>PM: 创建ProjectVersion草稿记录
    PM->>PM: 创建ProjectWorkflow关联记录
    PM-->>Admin: 返回项目创建成功

    PM->>User: 通知填写人
    User->>PM: POST /api/project/draft/save
    PM->>PM: 更新ProjectVersion草稿
    User->>PM: POST /api/project/draft/submit
    PM->>WP: 状态转换为pending_review
    PM->>PM: 更新lifecycle_status=REVIEWING
```

### 8.2 项目与工单关系

| 关系类型 | 项目状态 | 说明 |
|:---|:---|:---|
| 项目:填写工单 = 1:1 | INIT/DRAFTING | 项目创建时只能有一个填写工单 |
| 项目:修改工单 = 1:N | RELEASED/MODIFYING | 已发布项目可以有多个修改工单 |
| 用户:修改工单 = 1:1 (per project) | - | 非SuperAdmin用户同一项目只能有一个活跃修改工单 |

---

## 9. 安全与规范

### 9.1 敏感字段加密

遵循系统规范，以下字段必须加密存储 (AES-256):
- `DeployBusiness.AdminPassword`
- `DeployEnv.SSHPassword`
- `DeployEnv.ManagementPassword`
- `DeployMiddleware.*.AdminPassword`

### 9.2 审计日志

所有对 `projects` 表的写操作均需通过 `rmdc-audit-log` 记录：
- **Resource**: `project`
- **Action**: `create`, `update`, `publish_version`, `delete`, `permission_grant`
- **Payload**: 记录关键变更字段

---

## 10. 附录

### 10.1 基本信息结构体

### 10.1 基本信息结构体 (BasicInfo)

```go
type BasicInfo struct {
    Province         string `json:"province"`         // 省份
    City             string `json:"city"`             // 城市 (级联)
    IndustryContact  string `json:"industry_contact"` // 行业组人员姓名
    IndustryPhone    string `json:"industry_phone"`   // 行业组人员电话
    ProjectNature    string `json:"project_nature"`   // 项目性质: research(科研)/test(测试)/trial(试用)/market(市场化)/sub_platform(二级平台)
}
```

### 10.2 业务部署结构体 (DeployBusiness)

```go
type DeployBusiness struct {
    DeployerName      string `json:"deployer_name"`       // 部署人姓名
    DeployerPhone     string `json:"deployer_phone"`      // 部署人电话
    DeployStartTime   string `json:"deploy_start_time"`   // 部署开始时间
    DeployEndTime     string `json:"deploy_end_time"`     // 部署结束时间
    SystemVersion     string `json:"system_version"`      // 部署系统版本
    SystemType        string `json:"system_type"`         // 系统类型: business/fly-control/supervisor
    MainEntrance      string `json:"main_entrance"`       // 业务主要入口URL
    AdminUsername     string `json:"admin_username"`      // 系统超管用户名
    AdminPassword     string `json:"admin_password"`      // 系统超管密码 (加密存储)
}
```

### 10.3 部署环境结构体 (DeployEnv)

```go
type DeployEnv struct {
    // 主机信息
    Hosts             []HostInfo `json:"hosts"`
    
    // 网络环境
    NetworkType       string     `json:"network_type"`     // internal(完全内网)/single_public(单主机公网)/full_public(全访问公网)
    MainPublicIP      string     `json:"main_public_ip"`   // 主要公网IP
    DomainURL         string     `json:"domain_url"`       // 域名URL
    SSLEnabled        bool       `json:"ssl_enabled"`      // 是否开启SSL
    
    // 管理方式
    ManagementType    string     `json:"management_type"`  // bastion(堡垒机)/whitelist(白名单)/vpn
    ManagementURL     string     `json:"management_url"`   // 管理后台URL
    ManagementUser    string     `json:"management_user"`  // 管理后台用户名
    ManagementPwd     string     `json:"management_pwd"`   // 管理后台密码 (加密存储)
    
    // 统计信息
    HostCount         int        `json:"host_count"`       // 主机台数
    TotalCPU          int        `json:"total_cpu"`        // CPU总核数
    CPUModel          string     `json:"cpu_model"`        // CPU型号
    TotalMemory       int        `json:"total_memory"`     // 内存总大小(GB)
    TotalStorage      int        `json:"total_storage"`    // 存储总大小(GB)
}

type HostInfo struct {
    Hostname          string `json:"hostname"`
    InternalIP        string `json:"internal_ip"`
    PublicIP          string `json:"public_ip"`
    CanAccessPublic   bool   `json:"can_access_public"` // 能否访问公网
    SSHPort           int    `json:"ssh_port"`
    SSHUser           string `json:"ssh_user"`
    SSHPwd            string `json:"ssh_pwd"`           // SSH密码 (加密存储)
    Role              string `json:"role"`              // master/worker/storage
}
```

### 10.4 部署中间件结构体 (DeployMiddleware)

```go
type DeployMiddleware struct {
    MySQL         MiddlewareInfo `json:"mysql"`
    Redis         MiddlewareInfo `json:"redis"`
    EMQX          MiddlewareInfo `json:"emqx"`
    MinIO         MiddlewareInfo `json:"minio"`
    InfluxDB      MiddlewareInfo `json:"influxdb"`
    Nacos         MiddlewareInfo `json:"nacos"`
    K8SDashboard  MiddlewareInfo `json:"k8s_dashboard"`
}

// MiddlewareInfo 通用中间件信息
type MiddlewareInfo struct {
    PublicIP        string `json:"public_ip"`
    PublicPort      int    `json:"public_port"`
    InternalIP      string `json:"internal_ip"`
    InternalPort    int    `json:"internal_port"`
    K8SAddress      string `json:"k8s_address"`     // K8S集群内访问地址 (Service Name)
    K8SPort         int    `json:"k8s_port"`
    AdminUser       string `json:"admin_user"`
    AdminPwd        string `json:"admin_pwd"`       // 超管密码 (加密存储)
    Version         string `json:"version"`         // 中间件版本
}
```

### 10.5 项目授权信息结构体 (AuthorizationInfo)

> **注意**：此结构对应 `project_auth_configs` 表，通常不作为 JSONB 存储在 `projects` 表中，而是通过关联表存储。此处列出仅供各种 DTO 参考。

```go
type AuthorizationInfo struct {
    TierOneSecret    string    `json:"tier_one_secret"`    // 一级TOTP密钥
    TimeOffset       int       `json:"time_offset"`        // 允许时间偏移(秒)
    TOTPEnabled      bool      `json:"totp_enabled"`       // 是否开启TOTP
    TierTwoSecret    string    `json:"tier_two_secret"`    // 二级TOTP密钥 (来自Watchdog)
    
    AuthType         string    `json:"auth_type"`          // permanent(永久)/time_limited(限时)
    AuthDays         int       `json:"auth_days"`          // 授权有效期(天)
    AuthorizedAt     time.Time `json:"authorized_at"`      // 授权时间
    RevokedAt        time.Time `json:"revoked_at"`         // 撤销授权时间
    IsOffline        bool      `json:"is_offline"`         // 是否离线授权
}
```

### 10.6 相关文档

| 文档 | 说明 |
|:---|:---|
| [项目管理PRD](1-rmdc-project-management-PRD.md) | 产品需求文档 |
| [项目状态说明](4-project-状态说明.md) | 状态转换说明 |
| [工单模块DDS](../7-rmdc-work-procedure/1-rmdc-work-procedure-DDS.md) | 工单流程设计 |
| [用户权限DDS](../9-rmdc-user-auth/1-user-auth-PRD.md) | 用户权限设计 |
