# 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
API Gateway]
end
subgraph 业务协作
PM[rmdc-project-management]
WP[rmdc-work-procedure
工单流程]
UA[rmdc-user-auth
用户认证/权限]
Aud[rmdc-audit-log
审计日志]
end
subgraph 边缘交互
EH[rmdc-exchange-hub
消息网关]
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) | 用户权限设计 |