flow

5 阅读3分钟

CloudAccountSidePane 数据流分析

完整数据流程图

┌─────────────────────────────────────────────────────────────────────────────┐
│ 1. 后端 API 层                                                              │
└─────────────────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ ServerAPI/Requests/Organizations/Organizations.ts                          │
│                                                                             │
│ getCloudOrganizationsAndAccounts(orgId)                                     │
│   ↓                                                                         │
│ GET v1/organizations/{orgId}/inventory/cloud-organizations                 │
│   ↓                                                                         │
│ 返回: CloudOrganizationsAndAccountsResponse                                 │
│   {                                                                         │
│     organizational_accounts: {                                             │
│       [orgId]: {                                                            │
│         accounts: {                                                          │
│           [accountId]: {                                                    │
│             connection_error: {                                             │
│               exception_message: "...",  ← 赋值点 1                        │
│               error_code: "..."        ← 赋值点 1                            │
│             }                                                               │
│           }                                                                 │
│         }                                                                   │
│       }                                                                     │
│     },                                                                      │
│     single_accounts: [{                                                     │
│       account: {                                                            │
│         connection_error: {                                                 │
│           exception_message: "...",  ← 赋值点 1                            │
│           error_code: "..."        ← 赋值点 1                              │
│         }                                                                   │
│       }                                                                     │
│     }]                                                                      │
│   }                                                                         │
└─────────────────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ 2. 数据解析层                                                                │
└─────────────────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ responseUtils.ts                                                            │
│                                                                             │
│ parseOrganizationsAndAccountsResponse(response)                             │
│   ↓                                                                         │
│ parseCloudOrganizationAccountResponseItem(responseItem)                     │
│   ↓                                                                         │
│ 返回: CloudOrganizationAccountAttributes                                   │
│   {                                                                         │
│     accountId: "...",                                                       │
│     exceptionMessage: responseItem.connection_error?.exception_message,      │
│                       ← 赋值点 2                                            │
│     errorCode: responseItem.connection_error?.error_code,                  │
│                 ← 赋值点 2                                                  │
│     ...                                                                     │
│   }                                                                         │
│   ↓                                                                         │
│ 返回: [organizationsData, singleAccountsData]                              │
│   - organizationsData: Record<string, CloudOrganizationAttributes>         │
│     {                                                                       │
│       [orgId]: {                                                            │
│         accounts: {                                                         │
│           [accountId]: CloudOrganizationAccountAttributes  ← 包含错误信息   │
│         }                                                                   │
│       }                                                                     │
│     }                                                                       │
│   - singleAccountsData: CloudOrganizationAccountAttributes[]              │
│     [                                                                       │
│       CloudOrganizationAccountAttributes  ← 包含错误信息                   │
│     ]                                                                       │
└─────────────────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ 3. Hook 层 - 数据获取和状态管理                                              │
└─────────────────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ useCloudOrganizationAccountsData.ts                                          │
│                                                                             │
│ const { organizationsData, singleAccountsData } =                           │
│   useCloudOrganizationAccountsData()                                        │
│                                                                             │
│ 内部流程:                                                                    │
│   1. 调用 getCloudOrganizationsAndAccounts(orgId)                          │
│   2. 调用 parseOrganizationsAndAccountsResponse(response)                   │
│   3. 使用 useState 存储:                                                    │
│      - organizationsData: Record<string, CloudOrganizationAttributes>      │
│      - singleAccountsData: CloudOrganizationAccountAttributes[]           │
│                                                                             │
│ 返回:                                                                        │
│   {                                                                         │
│     organizationsData,  ← 包含错误信息                                      │
│     singleAccountsData,  ← 包含错误信息                                     │
│     ...                                                                     │
│   }                                                                         │
└─────────────────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ 4. 行数据转换层                                                              │
└─────────────────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ useOrganizationsAndAccountsRows.ts                                          │
│                                                                             │
│ const { rows } = useOrganizationsAndAccountsRows(                           │
│   organizationsData,                                                        │
│   singleAccountsData,                                                       │
│   regionalCoverage,                                                         │
│   isCoverageDataLoading                                                     │
│ )                                                                           │
│                                                                             │
│ 内部流程:                                                                    │
│   1. 遍历 organizationsData,调用 parseCloudOrganizationAccountsToRows()     │
│   2. 遍历 singleAccountsData,创建 CloudOrganizationAccountRowData          │
│   3. 返回: CloudOrganizationAccountRowData[]                                │
│                                                                             │
│ 返回:                                                                        │
│   {                                                                         │
│     rows: CloudOrganizationAccountRowData[]                                │
│       [                                                                     │
│         {                                                                   │
│           accountId: "...",                                                 │
│           exceptionMessage: account.exceptionMessage,  ← 赋值点 3           │
│           errorCode: account.errorCode,        ← 赋值点 3                   │
│           ...                                                               │
│         }                                                                   │
│       ]                                                                     │
│   }                                                                         │
└─────────────────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ 5. 组织数据转换层                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ OrganizationAndAccountsInnerTabs.tsx                                        │
│                                                                             │
│ createByOrganizationRowData(                                                │
│   filteredOrganizationsAndAccountsRowData: CloudOrganizationAccountRowData[]│
│ )                                                                           │
│                                                                             │
│ 内部流程:                                                                    │
│   1. 按组织分组 CloudOrganizationAccountRowData[]                          │
│   2. 创建 AccountsByOrganizationRowData[]                                  │
│                                                                             │
│ 返回:                                                                        │
│   AccountsByOrganizationRowData[]                                           │
│     [                                                                       │
│       {                                                                     │
│         accountRows: CloudOrganizationAccountRowData[]  ← 包含错误信息       │
│           [                                                                 │
│             {                                                               │
│               exceptionMessage: "...",  ← 赋值点 4                         │
│               errorCode: "...",        ← 赋值点 4                           │
│               ...                                                           │
│             }                                                               │
│           ]                                                                 │
│       }                                                                     │
│     ]                                                                       │
└─────────────────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ 6. CloudAccountSidePane 数据获取(当前实现)                                 │
└─────────────────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ CloudAccountSidePane.tsx                                                    │
│                                                                             │
│ const { organizationsData, singleAccountsData } =                          │
│   useCloudOrganizationAccountsData()  ← 直接从第 3 层获取                   │
│                                                                             │
│ // 手动查找匹配的账户                                                        │
│ const accountErrorData = useMemo(() => {                                   │
│   // 在 organizationsData 中查找                                            │
│   // 在 singleAccountsData 中查找                                          │
│   return {                                                                  │
│     exceptionMessage: accountData.exceptionMessage,                        │
│     errorCode: accountData.errorCode                                       │
│   }                                                                         │
│ }, [account, organizationsData, singleAccountsData])                       │
└─────────────────────────────────────────────────────────────────────────────┘

数据流关键点总结

赋值点追踪

  1. 赋值点 1: 后端 API 响应

    • 位置: CloudOrganizationAccountResponseItem.connection_error
    • 包含: exception_message, error_code
  2. 赋值点 2: 解析层

    • 位置: responseUtils.tsparseCloudOrganizationAccountResponseItem()
    • 转换: responseItem.connection_error?.exception_messageCloudOrganizationAccountAttributes.exceptionMessage
    • 转换: responseItem.connection_error?.error_codeCloudOrganizationAccountAttributes.errorCode
  3. 赋值点 3: 行数据转换

    • 位置: useOrganizationsAndAccountsRows.ts
    • 转换: account.exceptionMessageCloudOrganizationAccountRowData.exceptionMessage
    • 转换: account.errorCodeCloudOrganizationAccountRowData.errorCode
  4. 赋值点 4: 组织数据转换

    • 位置: createByOrganizationRowData()
    • 数据保留在: AccountsByOrganizationRowData.accountRows[].exceptionMessage/errorCode

orgData 的来源追踪

orgData 的创建流程:

  1. 后端 APIgetCloudOrganizationsAndAccounts()

    • 返回 CloudOrganizationsAndAccountsResponse.organizational_accounts
    • 包含组织信息: org_id, org_display_name, orchestrator_account, aws_management_account
  2. 解析层parseOrganizationsAndAccountsResponse()

    • 位置: responseUtils.ts (第88-130行)
    • organizational_accounts 解析为 CloudOrganizationAttributes
    organizationalAccounts[cloudOrganizationId] = {
      cloudOrganizationId: cloudOrganizationId,
      orgDisplayName: orgDisplayName,
      orchestratorAccount: organizationData.orchestrator_account,
      awsManagementAccount: organizationData.aws_management_account,
      accounts: { ... },  // 包含账户信息(包括错误信息)
      ...
    }
    
  3. Hook 层useCloudOrganizationAccountsData()

    • 返回 organizationsData: Record<string, CloudOrganizationAttributes>
  4. 行数据转换parseCloudOrganizationAccountsToRows()

    • 位置: parseCloudOrganizationAccountsToRows.ts (第26-85行)
    • cloudOrganization: CloudOrganizationAttributes 提取信息创建 orgData
    orgData: {
      cloudOrganizationId: cloudOrganization.cloudOrganizationId,  // ← 从 CloudOrganizationAttributes 提取
      orgDisplayName: cloudOrganization.orgDisplayName,              // ← 从 CloudOrganizationAttributes 提取
      orchestratorAccount: cloudOrganization.orchestratorAccount,    // ← 从 CloudOrganizationAttributes 提取
      awsManagementAccount: cloudOrganization.awsManagementAccount   // ← 从 CloudOrganizationAttributes 提取
    }
    

重要发现:

  • 组织账户: orgData 有值,包含组织信息
  • 单账户: orgDatanullsingleAccountsData 中的账户不属于任何组织)

在 CloudAccountSidePane 中的使用:

  • 可以通过 accountIdorganizationsAndAccountsRowData 中查找
  • 如果找到的 CloudOrganizationAccountRowDataorgData,说明它属于某个组织
  • orgData 本身不包含错误信息,但同一条 CloudOrganizationAccountRowData 中包含 exceptionMessageerrorCode

当前实现分析

CloudAccountSidePane 当前使用的数据源

  • 数据源: useCloudOrganizationAccountsData() (第 3 层)
  • 数据结构:
    • organizationsData: Record<string, CloudOrganizationAttributes>
    • singleAccountsData: CloudOrganizationAccountAttributes[]
  • 查找方式: 手动遍历查找匹配的 accountId

可选的数据源

  1. 第 3 层: useCloudOrganizationAccountsData() ✅ 当前使用

    • 优点: 原始数据,最完整
    • 缺点: 需要手动查找
  2. 第 4 层: useOrganizationsAndAccountsRows()

    • 优点: 已经是扁平化的 CloudOrganizationAccountRowData[],查找更方便
    • 缺点: 只在 Settings 页面使用,不是全局可用
  3. 第 5 层: byOrganizationData (AccountsByOrganizationRowData[])

    • 优点: 已经按组织分组,结构清晰
    • 缺点: 只在 OrganizationAndAccountsInnerTabs 组件内可用

建议的数据传递方案

方案 A: 使用共享 Hook(推荐)

创建一个全局可用的 hook,返回 CloudOrganizationAccountRowData[]:

// hooks/useCloudOrganizationAccountRows.ts
export const useCloudOrganizationAccountRows = () => {
  const { organizationsData, singleAccountsData, regionalCoverage, isCoverageDataLoading } = 
    useCloudOrganizationAccountsData();
  
  return useOrganizationsAndAccountsRows(
    organizationsData,
    singleAccountsData,
    regionalCoverage,
    isCoverageDataLoading
  );
};

优点:

  • 全局可用
  • 数据结构扁平化,查找方便
  • 包含所有必要信息(包括错误信息)

方案 B: 使用共享存储

CloudOrganizationAccountRowData[] 存储在共享的 DataStorage 中,供全局访问。

优点:

  • 数据集中管理
  • 自动更新和事件通知

缺点:

  • 需要额外的存储层
  • 可能过度设计

方案 C: 保持当前实现(已实现)

继续使用 useCloudOrganizationAccountsData(),在 CloudAccountSidePane 中手动查找。

优点:

  • 已实现
  • 不依赖其他组件

缺点:

  • 需要手动查找逻辑
  • 代码重复(如果其他地方也需要)

推荐方案

推荐使用方案 A: 创建 useCloudOrganizationAccountRows hook,因为:

  1. 数据结构更友好(扁平数组,易于查找)
  2. 全局可用
  3. 代码复用
  4. 保持数据一致性