Files
ProjectAGiPrompt/8-CMII-RMDC/4-rmdc-project-management/3-rmdc-project-management-frontend-DDS.md
2026-01-21 16:15:49 +08:00

35 KiB
Raw Permalink Blame History

RMDC 项目详情页面前端详细设计说明书 (Frontend DDS)

文档名称: RMDC 项目详情页面前端设计文档
对应页面:

  • frontend/src/modules/admin/pages/admin/ProjectDetail.vue (管理员端)
  • frontend/src/modules/admin/pages/user/UserProjectDetail.vue (用户端)

版本: v2.0
编制日期: 2026-01-15


文档修订历史

版本 日期 修订内容
v1.0 2026-01-12 初始版本,基础页面架构设计
v1.2 2026-01-14 完善模块设计规范、中间件卡片设计
v2.0 2026-01-15 新增:查看/编辑状态分离、用户侧/管理侧差异化设计、工单关联与跳转机制、多工单场景处理、页面美化规范

1. 设计概述

1.1 设计背景

项目详情页面是 RMDC 系统的核心交互界面,需要支持复杂的生命周期管理流程,并满足不同角色用户的差异化需求。本设计文档详细定义了页面的功能逻辑、交互行为、组件结构和美化规范。

1.2 核心设计目标

目标 说明
状态分离 明确区分「只读查看模式」与「编辑修改模式」,防止误操作
角色差异化 超级管理员与普通用户看到的内容、操作权限不同,但尽量复用组件
生命周期可视化 清晰展示项目当前状态INIT/DRAFTING/REVIEWING/RELEASED/MODIFYING/ARCHIVED
工单关联 支持项目详情页与工单详情页的双向跳转,处理多工单场景
美观专业 采用现代 Material Design 风格,注重留白、排版与微动效
高复用性 最大化组件复用,用户侧与管理侧共用核心表单组件

1.3 页面文件结构

frontend/src/modules/admin/
├── pages/
│   ├── admin/
│   │   └── ProjectDetail.vue         # 超级管理员端项目详情
│   └── user/
│       └── UserProjectDetail.vue     # 普通用户端项目详情(填写人视角)
├── components/
│   ├── BasicInfoForm.vue             # 基本信息编辑表单
│   ├── BasicInfoReadonly.vue         # 基本信息只读展示
│   ├── BusinessInfoReadonly.vue      # 业务信息只读展示
│   ├── DeploymentBusinessForm.vue    # 部署业务编辑表单
│   ├── DeploymentEnvironmentForm.vue # 部署环境编辑表单
│   ├── EnvironmentInfoReadonly.vue   # 环境信息只读展示
│   ├── HostsInfoReadonly.vue         # 主机信息只读展示
│   ├── HostsManagement.vue           # 主机管理组件
│   ├── MiddlewareCardsGrid.vue       # 中间件卡片网格
│   ├── MiddlewareInfoReadonly.vue    # 中间件只读展示
│   ├── AuthorizationManagement.vue   # 授权管理 (SuperAdmin Only)
│   ├── VersionHistory.vue            # 版本历史 (SuperAdmin Only)
│   ├── SaveConfirmDialog.vue         # 保存确认对话框
│   ├── ProjectBasicInfoCard.vue      # 项目基本信息卡片
│   ├── CopyableField.vue             # 可复制字段组件
│   └── index.ts                      # 组件统一导出

2. 页面架构设计

2.1 整体布局结构

页面采用 「固定头部 + 固定 Tab 导航 + 可滚动内容区域」 的三段式布局。

┌─────────────────────────────────────────────────────────────────────────┐
│  [固定区域] 生命周期状态提示横幅 (Alert Banner)                           │
├─────────────────────────────────────────────────────────────────────────┤
│  [固定区域] 页面头部 Header                                               │
│  ┌─────────────────────────────────────┬─────────────────────────────┐  │
│  │  ← 返回  项目名称                     │  [查看工单] [打回] [通过]   │  │
│  │          Namespace | 省份 城市        │  [下载配置] [编辑/保存]     │  │
│  │          状态标签组                    │                            │  │
│  └─────────────────────────────────────┴─────────────────────────────┘  │
├─────────────────────────────────────────────────────────────────────────┤
│  [固定区域] Tab 导航栏                                                    │
│  ┌─────────────────────────────────────────────────────────────────────┐│
│  │  基本信息 | 部署业务 | 部署环境 | 主机管理 | 中间件 | 授权 | 版本历史 ││
│  └─────────────────────────────────────────────────────────────────────┘│
├─────────────────────────────────────────────────────────────────────────┤
│  [滚动区域] Tab 内容区域                                                  │
│  ┌─────────────────────────────────────────────────────────────────────┐│
│  │                                                                      ││
│  │                    当前 Tab 对应的表单/只读内容                        ││
│  │                                                                      ││
│  │                                                                      ││
│  └─────────────────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────────────────┘

2.2 CSS 布局实现

.project-detail-page {
  height: 100%;
  max-height: 100%;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.header-section {
  flex-shrink: 0;
  background: rgb(var(--v-theme-surface));
  z-index: 1;
}

.content-area {
  flex: 1 1 auto;
  overflow-y: auto;
  overflow-x: hidden;
  min-height: 0;  /* 关键:防止 Flex 子元素撑破父容器 */
  padding-bottom: 24px;
}

3. 查看状态 vs 编辑状态

3.1 状态定义

状态 变量名 说明
查看状态 isEditMode = false 默认状态,展示只读组件
编辑状态 isEditMode = true 编辑模式,展示表单组件

3.2 查看状态 (默认)

3.2.1 展示形式

  • 使用 *Readonly.vue 系列组件展示数据
  • 采用 v-row/v-col 布局,键值对形式展示
  • 关键字段IP、URL、密码支持一键复制
  • 敏感字段(密码)默认脱敏显示 ******

3.2.2 交互行为

交互 说明
一键复制 使用 CopyableField 组件,点击复制图标复制到剪贴板
密码查看 点击"小眼睛"图标切换明文/密文
链接跳转 URL 字段支持点击新窗口打开

3.2.3 组件列表

组件名称 对应模块 说明
BasicInfoReadonly.vue 基本信息 项目名、NS、省市、性质
BusinessInfoReadonly.vue 部署业务 部署人、系统版本、入口URL
EnvironmentInfoReadonly.vue 部署环境 网络、IP、域名、主机统计
HostsInfoReadonly.vue 主机管理 主机列表只读表格
MiddlewareInfoReadonly.vue 中间件 中间件卡片只读展示

3.3 编辑状态

3.3.1 进入条件

  • 点击 Header 的「编辑」按钮
  • 用户必须具备编辑权限(基于角色和生命周期状态)

3.3.2 数据流

sequenceDiagram
    participant User as 用户
    participant View as 查看模式
    participant Edit as 编辑模式
    participant API as 后端API

    User->>View: 点击[编辑]按钮
    View->>Edit: isEditMode = true
    Edit->>Edit: 深拷贝 masterData → editForm
    Edit-->>User: 显示表单组件

    User->>Edit: 修改字段
    Edit->>Edit: computed hasChanges = true

    User->>Edit: 点击[保存]
    Edit->>Edit: 弹出 SaveConfirmDialog
    User->>Edit: 确认保存
    Edit->>API: 调用更新接口
    API-->>Edit: 返回成功
    Edit->>View: isEditMode = false, 刷新数据

3.3.3 退出保护

  • 脏数据检测:通过 computed hasChanges 检测是否有未保存的修改
  • 退出确认:如有未保存修改,点击「取消」或切换页面时弹出确认对话框
const exitEditMode = () => {
  if (hasChanges.value) {
    exitConfirmDialog.value = true  // 弹出确认对话框
  } else {
    isEditMode.value = false
  }
}

3.3.4 编辑状态指示器

编辑模式下Header 区域显示明显的「编辑模式」标签:

<v-chip v-if="isEditMode" color="info" variant="tonal" class="ml-2">
  <v-icon start size="small">mdi-pencil</v-icon>
  编辑模式
</v-chip>

4. 用户侧 vs 管理侧差异化设计

4.1 页面对照表

特性 管理员端 (ProjectDetail.vue) 用户端 (UserProjectDetail.vue)
默认模式 查看模式 根据工单状态决定
查看权限 所有模块 ACL 授权模块
授权信息 Tab 可见 不可见
版本历史 Tab 可见 不可见
主机管理 Tab 可见 不可见
基本信息 可编辑 只读(由管理员填写)
编辑操作 直接保存(上帝模式) 草稿 → 提交审核(工单流程)
审批操作 通过/打回按钮
保存按钮 「保存修改」 「保存草稿」
提交按钮 「提交审核」

4.2 Tab 导航差异

管理员端 Tabs

<v-tabs v-model="activeTab">
  <v-tab value="basic">基本信息</v-tab>
  <v-tab value="business">部署业务</v-tab>
  <v-tab value="environment">部署环境</v-tab>
  <v-tab value="hosts">主机管理</v-tab>
  <v-tab value="middlewares">中间件</v-tab>
  <v-tab value="authorization" v-if="isSuperAdmin">授权信息</v-tab>
  <v-tab value="version-history" v-if="isSuperAdmin">版本历史</v-tab>
</v-tabs>

用户端 Tabs

<v-tabs v-model="activeTab">
  <v-tab value="basic">基本信息</v-tab>
  <v-tab value="business">部署业务</v-tab>
  <v-tab value="environment">部署环境</v-tab>
  <v-tab value="middlewares">中间件</v-tab>
</v-tabs>

4.3 组件复用策略

graph TB
    subgraph 共用组件
        A[BasicInfoForm]
        B[DeploymentBusinessForm]
        C[DeploymentEnvironmentForm]
        D[MiddlewareCardsGrid]
        E[BasicInfoReadonly]
        F[BusinessInfoReadonly]
        G[EnvironmentInfoReadonly]
        H[MiddlewareInfoReadonly]
    end

    subgraph 管理端专用
        I[AuthorizationManagement]
        J[VersionHistory]
        K[HostsManagement]
        L[SaveConfirmDialog]
    end

    subgraph 用户端专用
        M[ProjectBasicInfoCard]
    end

    Admin[ProjectDetail.vue] --> A
    Admin --> B
    Admin --> C
    Admin --> D
    Admin --> E
    Admin --> F
    Admin --> G
    Admin --> H
    Admin --> I
    Admin --> J
    Admin --> K
    Admin --> L

    User[UserProjectDetail.vue] --> B
    User --> C
    User --> D
    User --> M

4.4 权限控制逻辑

// 管理员端 - 编辑权限判断
const canEdit = computed(() => {
  if (!masterData.value) return false
  const status = masterData.value.lifecycle_status

  // 超级管理员在已发布、变更中状态可以编辑
  if (isSuperAdmin.value) {
    return status === 'released' || status === 'modifying'
  }
  return false
})

// 用户端 - 编辑权限判断
const canEdit = computed(() => {
  if (!workflowInfo.value) return true  // 没有工单信息时默认可编辑
  const status = workflowInfo.value.status

  // 已分配、处理中、已打回状态可编辑
  return ['assigned', 'in_progress', 'returned', 'draft_saved'].includes(status)
})

5. 项目生命周期状态展示

5.1 状态标签设计

项目详情页 Header 区域展示三类状态标签:

<div class="d-flex align-center gap-2">
  <h1 class="text-h4 font-weight-bold">{{ masterData.project_name }}</h1>
  
  <!-- 1. 连接状态 -->
  <v-chip :color="getStatusColor(masterData.status)" size="small" variant="tonal">
    {{ PROJECT_STATUS[masterData.status] }}
  </v-chip>
  
  <!-- 2. 生命周期状态 -->
  <v-chip :color="getLifecycleStatusColor(masterData.lifecycle_status)" 
          size="small" variant="tonal">
    <v-icon start size="small">{{ getLifecycleStatusIcon(masterData.lifecycle_status) }}</v-icon>
    {{ LIFECYCLE_STATUS[masterData.lifecycle_status] }}
  </v-chip>
  
  <!-- 3. 认证状态 -->
  <v-chip :color="masterData.project_certification === 'official' ? 'success' : 'warning'"
          size="small" variant="tonal">
    {{ PROJECT_CERTIFICATION[masterData.project_certification] }}
  </v-chip>
  
  <!-- 4. 编辑模式指示器 -->
  <v-chip v-if="isEditMode" color="info" variant="tonal">
    <v-icon start size="small">mdi-pencil</v-icon>
    编辑模式
  </v-chip>
</div>

5.2 生命周期状态配置

// 生命周期状态枚举
export const LIFECYCLE_STATUS = {
  init: '初始化',
  drafting: '填写中',
  reviewing: '审核中',
  released: '已发布',
  modifying: '变更中',
  archived: '已归档'
}

// 状态颜色映射
export const LIFECYCLE_STATUS_COLORS: Record<string, string> = {
  init: 'grey',
  drafting: 'info',
  reviewing: 'warning',
  released: 'success',
  modifying: 'primary',
  archived: 'grey-darken-1'
}

// 状态图标
const getLifecycleStatusIcon = (status: string): string => {
  const icons: Record<string, string> = {
    init: 'mdi-clock-outline',
    drafting: 'mdi-pencil',
    reviewing: 'mdi-eye',
    released: 'mdi-check-circle',
    modifying: 'mdi-sync',
    archived: 'mdi-archive'
  }
  return icons[status] || 'mdi-help-circle'
}

5.3 生命周期提示横幅 (Alert Banner)

根据当前生命周期状态,在 Header 下方显示上下文提示:

interface LifecycleAlert {
  type: 'info' | 'warning' | 'success' | 'error'
  message: string
  action?: {
    text: string
    handler: () => void
  }
}

const lifecycleStatusAlert = computed((): LifecycleAlert | null => {
  if (!masterData.value) return null
  const status = masterData.value.lifecycle_status

  switch (status) {
    case 'init':
      return {
        type: 'info',
        message: '项目已创建,等待指定填写人录入详细信息'
      }
    case 'drafting':
      return {
        type: 'info',
        message: `项目详情正在由 ${masterData.value.detail_filler_name || '填写人'} 填写中`,
        action: masterData.value.workflow_id ? {
          text: '查看工单',
          handler: () => router.push(`/admin/workflows/${masterData.value?.workflow_id}`)
        } : undefined
      }
    case 'reviewing':
      return {
        type: 'warning',
        message: '项目详情已提交,等待审核',
        action: masterData.value.workflow_id ? {
          text: '查看工单',
          handler: () => router.push(`/admin/workflows/${masterData.value?.workflow_id}`)
        } : undefined
      }
    case 'modifying':
      return {
        type: 'info',
        message: '项目存在活跃的变更工单,主线数据不受影响',
        action: masterData.value.workflow_id ? {
          text: '查看工单',
          handler: () => router.push(`/admin/workflows/${masterData.value?.workflow_id}`)
        } : undefined
      }
    case 'archived':
      return {
        type: 'warning',
        message: '项目已归档,仅保留历史数据'
      }
    default:
      return null
  }
})

6. 工单关联与跳转机制

6.1 工单与项目的关系

工单类型 生命周期状态 数量关系 说明
填写工单 (project_detail) INIT → DRAFTING 1:1 项目创建时只能有一个
修改工单 (project_modify) RELEASED → MODIFYING 1:N 已发布项目可有多个

6.2 工单按钮显示逻辑

// 是否显示工单按钮
const showWorkflowButton = computed(() => {
  if (!masterData.value?.workflow_id) return false
  const status = masterData.value.lifecycle_status
  // 在填写中、审核中、变更中状态显示工单按钮
  return ['drafting', 'reviewing', 'modifying'].includes(status)
})

// 工单按钮文本
const workflowButtonText = computed(() => {
  if (!masterData.value) return '查看工单'
  const status = masterData.value.lifecycle_status
  switch (status) {
    case 'drafting':
      return '查看填写工单'
    case 'reviewing':
      return '查看审核工单'
    case 'modifying':
      return '查看修改工单'
    default:
      return '查看工单'
  }
})

6.3 多工单场景处理

当项目处于 MODIFYING 状态时,可能同时存在多个修改工单。需要设计专门的工单列表展示。

6.3.1 设计方案

方案一:下拉菜单选择

<v-menu v-if="multipleWorkflows">
  <template v-slot:activator="{ props }">
    <v-btn v-bind="props" color="info" variant="tonal" prepend-icon="mdi-sitemap">
      查看工单 ({{ workflowCount }})
      <v-icon end>mdi-chevron-down</v-icon>
    </v-btn>
  </template>
  <v-list>
    <v-list-item 
      v-for="wf in relatedWorkflows" 
      :key="wf.workflow_id"
      @click="navigateToWorkflow(wf.workflow_id)"
    >
      <v-list-item-title>{{ wf.workflow_id }}</v-list-item-title>
      <v-list-item-subtitle>
        {{ wf.creator_name }} | {{ formatDate(wf.created_at) }}
      </v-list-item-subtitle>
    </v-list-item>
  </v-list>
</v-menu>

方案二:工单列表对话框(推荐用于工单较多的场景)

<v-dialog v-model="workflowListDialog" max-width="600">
  <v-card>
    <v-card-title>
      <v-icon start>mdi-sitemap</v-icon>
      关联工单列表
    </v-card-title>
    <v-card-text>
      <v-data-table
        :headers="workflowHeaders"
        :items="relatedWorkflows"
        density="compact"
        hover
      >
        <template v-slot:item.workflow_id="{ item }">
          <a @click="navigateToWorkflow(item.workflow_id)">
            {{ item.workflow_id }}
          </a>
        </template>
        <template v-slot:item.status="{ item }">
          <v-chip :color="getWorkflowStatusColor(item.status)" size="small">
            {{ item.status_name }}
          </v-chip>
        </template>
      </v-data-table>
    </v-card-text>
  </v-card>
</v-dialog>

6.4 从工单页面跳转回项目详情

工单详情页应提供「查看项目」按钮:

// 工单详情页
const navigateToProject = () => {
  if (workflowDetail.value?.business_context?.project_id) {
    router.push(`/admin/projects/${workflowDetail.value.business_context.project_id}`)
  }
}

7. 模块详细设计规范

7.1 基本信息模块 (Basic Info)

字段 类型 只读模式 编辑模式
项目名称 String 文本展示 + 复制 v-text-field
命名空间 String 文本展示 + 复制 disabled 不可编辑
省份 Enum 文本展示 级联选择器
城市 Enum 文本展示 级联选择器(依赖省份)
项目性质 Enum 文本展示 v-select
行业组人员 String 文本展示 v-text-field
行业组电话 String 文本展示 v-text-field
项目描述 String 多行文本 v-textarea

7.2 部署业务模块 (Deployment Business)

字段 类型 只读模式 编辑模式
部署人姓名 String 文本展示 v-text-field 或用户搜索
部署人电话 String 文本展示 v-text-field
部署系统 Enum 文本展示 v-select
系统版本 String 文本展示 v-text-field
业务入口 URL String 可点击链接 v-text-field
超管账号 String 文本展示 + 复制 v-text-field
超管密码 Password 脱敏 + 查看按钮 v-text-field 密码输入

7.3 部署环境模块 (Deployment Environment)

字段 类型 只读模式 编辑模式
网络环境 Enum 文本展示 v-select
主公网 IP String 文本展示 + 复制 v-text-field IP 校验
域名 URL String 可点击链接 v-text-field
启用 SSL Boolean 图标显示 v-switch
主机管理方式 Enum 文本展示 v-select
管理控制台 URL String 可点击链接 v-text-field
主机数量 Number 文本展示 v-text-field type=number
CPU 总核数 Number 统计卡片 v-text-field type=number
内存总量 Number 统计卡片 v-text-field type=number
存储总量 Number 统计卡片 v-text-field type=number

7.4 中间件模块 (Middleware)

采用 卡片网格 (Card Grid) 设计:

7.4.1 数据结构

interface MiddlewareFormItem {
  middleware_type: string
  public_ip: string
  public_port: number
  internal_ip: string
  internal_port: number
  admin_user: string
  admin_password?: string
}

7.4.2 只读模式

  • 每个中间件一张卡片,响应式网格布局
  • 卡片包含:类型图标 + 标题 + IP/Port 信息
  • 图标映射逻辑:
const MIDDLEWARE_ICONS: Record<string, string> = {
  'mysql': 'mdi-database',
  'redis': 'mdi-database-clock',
  'emqx': 'mdi-broadcast',
  'minio': 'mdi-bucket',
  'influxdb': 'mdi-chart-timeline-variant',
  'nacos': 'mdi-cog-outline',
  'k8s-dashboard': 'mdi-kubernetes'
}

7.4.3 编辑模式

  • 现有卡片右上角显示「编辑」「删除」按钮
  • 列表末尾显示「添加中间件」虚线框卡片
  • 点击添加/编辑弹出对话框:
    • 类型选择:v-combobox 支持预设 + 自定义
    • 选择预设类型时自动填充默认端口

7.5 主机管理模块 (Hosts Management)

  • 复用 HostsManagement.vue 组件
  • 支持表格展示所有主机信息
  • 编辑模式支持添加/删除主机

7.6 授权信息模块 (Authorization) - SuperAdmin Only

功能 说明
TOTP 密钥展示 二维码 + 文本形式
授权类型切换 永久/限时
授权天数设置 数字输入
下发授权 调用 Exchange-Hub 接口
撤销授权 调用 Exchange-Hub 接口

7.7 版本历史模块 (Version History) - SuperAdmin Only

功能 说明
版本列表 时间轴形式展示
版本详情 点击查看完整快照
版本对比 选择两个版本进行 Diff
工单关联 点击跳转关联工单

8. 组件设计规范

8.1 CopyableField 组件

用于展示可复制的字段值:

<template>
  <div class="copyable-field d-flex align-center gap-2">
    <span class="field-value">{{ displayValue }}</span>
    <v-btn 
      icon="mdi-content-copy" 
      size="x-small" 
      variant="text"
      @click="copyToClipboard"
    >
      <v-tooltip activator="parent" location="top">复制</v-tooltip>
    </v-btn>
  </div>
</template>

8.2 SaveConfirmDialog 组件

保存前的确认对话框,展示变更差异:

<v-dialog v-model="visible" max-width="600">
  <v-card>
    <v-card-title class="bg-primary text-white">
      <v-icon start>mdi-check-circle</v-icon>
      确认保存修改
    </v-card-title>
    <v-card-text>
      <v-alert type="info" variant="tonal" class="mb-4">
        以下字段将被修改:
      </v-alert>
      <v-table density="compact">
        <thead>
          <tr>
            <th>字段</th>
            <th>修改前</th>
            <th>修改后</th>
          </tr>
        </thead>
        <tbody>
          <tr v-for="item in diffItems" :key="item.field">
            <td>{{ item.label }}</td>
            <td class="text-error">{{ item.oldValue || '空' }}</td>
            <td class="text-success">{{ item.newValue || '空' }}</td>
          </tr>
        </tbody>
      </v-table>
    </v-card-text>
    <v-card-actions>
      <v-spacer />
      <v-btn variant="text" @click="cancel">取消</v-btn>
      <v-btn color="primary" :loading="loading" @click="confirm">确认保存</v-btn>
    </v-card-actions>
  </v-card>
</v-dialog>

8.3 DiffTextField 组件

编辑模式下显示与主线数据差异的输入框:

<template>
  <v-text-field
    v-model="inputValue"
    :label="label"
    :class="{ 'diff-highlight': hasDiff }"
    :hint="hasDiff ? `主线值: ${masterValue}` : ''"
    persistent-hint
  >
    <template v-slot:prepend-inner v-if="hasDiff">
      <v-icon color="warning" size="small">mdi-alert-circle</v-icon>
    </template>
  </v-text-field>
</template>

<style scoped>
.diff-highlight :deep(.v-field__outline) {
  --v-field-border-color: rgb(var(--v-theme-warning));
}
</style>

9. 交互时序图

9.1 管理员编辑保存流程

sequenceDiagram
    participant Admin as 超级管理员
    participant Page as ProjectDetail.vue
    participant Dialog as SaveConfirmDialog
    participant API as 后端API

    Admin->>Page: 点击[编辑]按钮
    Page->>Page: isEditMode = true
    Page->>Page: editForm = deepClone(masterData)

    Admin->>Page: 修改字段
    Page->>Page: hasChanges = true

    Admin->>Page: 点击[保存修改]
    Page->>Page: 计算 diffItems
    Page->>Dialog: 显示确认对话框

    Admin->>Dialog: 确认保存
    Dialog->>API: updateProject()
    API-->>Dialog: 成功
    Dialog->>Page: emit('confirm')
    Page->>API: loadProject()
    Page->>Page: isEditMode = false
    Page-->>Admin: Snackbar: 保存成功

9.2 用户草稿提交流程

sequenceDiagram
    participant User as 普通用户
    participant Page as UserProjectDetail.vue
    participant Dialog as SubmitDialog
    participant API as 后端API
    participant WF as 工单模块

    User->>Page: 填写表单
    User->>Page: 点击[保存草稿]
    Page->>API: saveDraft()
    API-->>Page: 草稿保存成功

    User->>Page: 点击[提交审核]
    Page->>Dialog: 显示确认对话框
    User->>Dialog: 填写备注并确认
    Dialog->>API: saveDraft() (最终版本)
    Dialog->>API: submitProjectDetail()
    API->>WF: 触发工单状态转换
    WF-->>API: 成功
    API-->>Dialog: 提交成功
    Page-->>User: 跳转至工单详情页

9.3 管理员审批流程

sequenceDiagram
    participant Admin as 超级管理员
    participant Page as ProjectDetail.vue
    participant Dialog as ApproveDialog/RejectDialog
    participant API as 后端API
    participant WF as 工单模块

    Note over Page: lifecycle_status = reviewing

    Admin->>Page: 查看待审核内容
    
    alt 通过审批
        Admin->>Page: 点击[通过]
        Page->>Dialog: 显示审批对话框
        Admin->>Dialog: 填写备注并确认
        Dialog->>API: transitionWorkflow(approve)
        API->>WF: 工单状态 → approved
        WF-->>API: 回调更新项目状态
        API-->>Dialog: 成功
        Page->>API: updateProjectCertification('official')
        Page-->>Admin: Snackbar: 审批通过
    else 打回修改
        Admin->>Page: 点击[打回]
        Page->>Dialog: 显示打回对话框
        Admin->>Dialog: 填写打回原因并确认
        Dialog->>API: transitionWorkflow(return)
        API->>WF: 工单状态 → returned
        WF-->>API: 回调更新项目状态
        API-->>Dialog: 成功
        Page-->>Admin: Snackbar: 已打回
    end

10. 视觉设计规范

10.1 色彩系统

用途 颜色 Vuetify 类
主色调 Deep Purple color="primary"
成功状态 Green color="success"
警告状态 Orange color="warning"
错误状态 Red color="error"
信息状态 Blue color="info"
页面背景 Light Grey bg-grey-lighten-4
卡片背景 White bg-white

10.2 卡片设计

<v-card elevation="2" rounded="lg" class="pa-4">
  <!-- 卡片内容 -->
</v-card>
  • 圆角:rounded-lg (8px)
  • 阴影:elevation-2
  • 内边距:pa-4 (16px)
  • Hover 效果:轻微上浮 + 阴影加深

10.3 排版规范

元素 字体样式
页面标题 text-h4 font-weight-bold
卡片标题 text-h6
字段标签 text-medium-emphasis text-body-2
字段值 text-high-emphasis
辅助文字 text-caption text-grey

10.4 间距规范

遵循 8px 网格系统:

间距 Vuetify 类
紧凑 pa-2 / ma-2 8px
标准 pa-4 / ma-4 16px
宽松 pa-6 / ma-6 24px
组件间距 gap-2 8px
卡片间距 gap-4 16px

10.5 动画与过渡

场景 效果
Tab 切换 v-window 默认滑动过渡
模式切换 v-expand-transition
按钮 Hover 0.2s 缓动
卡片 Hover transform: translateY(-2px)
加载状态 v-skeleton-loader 骨架屏

11. 响应式设计

11.1 断点配置

遵循 Vuetify 默认断点:

断点 宽度范围
xs < 600px
sm 600px - 960px
md 960px - 1280px
lg 1280px - 1920px
xl > 1920px

11.2 布局适配

<!-- 中间件卡片网格 -->
<v-row>
  <v-col 
    v-for="mw in middlewares" 
    :key="mw.type"
    cols="12" 
    sm="6" 
    md="4" 
    lg="3"
  >
    <MiddlewareCard :data="mw" />
  </v-col>
</v-row>

11.3 移动端适配要点

  1. Tab 导航:使用 show-arrows 支持左右滑动
  2. 操作按钮:使用 v-bottom-sheet 或收起到菜单
  3. 表单布局:单列堆叠
  4. 表格:使用 mobile-breakpoint 切换卡片视图

12. 数据类型定义

12.1 核心类型

// 项目详情
interface ProjectDetail {
  id: number
  project_id: string
  project_name: string
  namespace: string
  province: string
  city: string
  project_nature: string
  industry_group_member: string
  industry_group_phone: string
  description: string
  status: string
  lifecycle_status: string
  project_certification: string
  workflow_id: string
  detail_filler_id: number
  detail_filler_name: string
  deployment_business: DeploymentBusiness | null
  deployment_environment: DeploymentEnvironment | null
  middlewares: Middleware[]
  hosts: Host[]
  draft_data: Record<string, unknown> | null
  created_at: string
  updated_at: string
}

// 表单数据类型
interface BasicFormData {
  project_name: string
  province: string
  city: string
  industry_group_member: string
  industry_group_phone: string
  project_nature: string
  description: string
}

interface BusinessFormData {
  deployer_name: string
  deployer_phone: string
  deploy_system: string
  system_version: string
  business_entry_url: string
  super_admin_user: string
  super_admin_password: string
}

interface EnvironmentFormData {
  network_environment: string
  main_public_ip: string
  domain_url: string
  enable_ssl: boolean
  host_management_method: string
  management_console_url: string
  host_count: number
  total_cpu: number
  total_memory_gb: number
  total_storage_gb: number
}

interface MiddlewareFormItem {
  middleware_type: string
  public_ip: string
  public_port: number
  internal_ip: string
  internal_port: number
  admin_user: string
  admin_password?: string
}

// Diff 项
interface DiffItem {
  field: string
  label: string
  oldValue: string | number | boolean
  newValue: string | number | boolean
}

13. API 调用规范

13.1 项目管理 API

方法 路径 说明
POST /api/project/detail 获取项目详情
POST /api/project/update 更新项目信息 (Admin)
POST /api/project/draft/save 保存草稿
POST /api/project/draft/submit 提交审核
POST /api/project/draft/discard 放弃草稿
POST /api/project/export 导出配置

13.2 调用示例

// 获取项目详情
const loadProject = async () => {
  const res = await getProjectDetail(projectId.value)
  if (res.code === 0) {
    masterData.value = res.data
  }
}

// 管理员保存修改
const confirmSave = async () => {
  await updateProject(projectId.value, {
    project_name: editForm.basic.project_name,
    province: editForm.basic.province,
    // ...
  })
}

// 用户保存草稿
const handleSaveDraft = async () => {
  const draftData = {
    formData: { ...businessFormData.value, ...environmentFormData.value },
    middlewareList: getMiddlewareList()
  }
  await saveDraft(projectId.value, draftData)
}

14. 附录

14.1 相关文档

文档 说明
项目管理 PRD 产品需求文档
项目管理后端 DDS 后端详细设计
Vue3 TypeScript 规范 前端开发规范
API 开发规范 接口设计规范

14.2 组件清单

组件 文件路径 说明
BasicInfoForm components/BasicInfoForm.vue 基本信息编辑表单
BasicInfoReadonly components/BasicInfoReadonly.vue 基本信息只读
BusinessInfoReadonly components/BusinessInfoReadonly.vue 业务信息只读
DeploymentBusinessForm components/DeploymentBusinessForm.vue 业务信息表单
DeploymentEnvironmentForm components/DeploymentEnvironmentForm.vue 环境信息表单
EnvironmentInfoReadonly components/EnvironmentInfoReadonly.vue 环境信息只读
HostsInfoReadonly components/HostsInfoReadonly.vue 主机信息只读
HostsManagement components/HostsManagement.vue 主机管理
MiddlewareCardsGrid components/MiddlewareCardsGrid.vue 中间件卡片网格
MiddlewareInfoReadonly components/MiddlewareInfoReadonly.vue 中间件只读
AuthorizationManagement components/AuthorizationManagement.vue 授权管理
VersionHistory components/VersionHistory.vue 版本历史
SaveConfirmDialog components/SaveConfirmDialog.vue 保存确认对话框
CopyableField components/CopyableField.vue 可复制字段
ProjectBasicInfoCard components/ProjectBasicInfoCard.vue 项目基本信息卡片