# Platform Master — UI 交互规范

> **module**: platform-master
> **doc_type**: UISpec
> **status**: Active (v3 — 6 page 已上线)
> **owner**: FFOA Team
> **upstream_docs**: 01-prd.md, 06-data-model.md, 07-api.md
> **last_verified**: 2026-05-18

---

## 0. 模块入口

平台主数据模块作为**独立顶级菜单**「主数据」，独立 sidebar（不嵌入 robot-manager 模块），路径前缀 `/platform-master/`。

### 侧栏导航

```
─── L1a 主数据 ───
Customers     → /platform-master/customers       客户管理（B2B / B2C / INTERNAL）
Suppliers     → /platform-master/suppliers       供应商管理（4 类 type）
Partners      → /platform-master/partners        合作伙伴管理
Locations     → /platform-master/locations       位置管理（含层级 + customerId 回引）
─── L1b 字典 ───
Currencies    → /platform-master/currencies      货币（admin CRUD）
Dictionaries  → /platform-master/dictionaries    通用字典（5 个 category）
```

未列入 sidebar 的主数据（仅 GET）：Countries / GeoRegions / UnitsOfMeasure —— 引用类参考数据，无前端管理 UI。

---

## 1. 通用 CRUD 页结构

所有 L1a 主数据页（Customers / Suppliers / Partners / Locations）+ Currencies 共用同一 **CrudListPage** 模式：

```
┌─────────────────────────────────────────────────────────────┐
│  [Page Title]                              [+ 新建] [刷新]  │  ← 头部
├─────────────────────────────────────────────────────────────┤
│  Search: [______________]  Filter: [Type ▼] [☐ Enabled]    │  ← 工具栏
├─────────────────────────────────────────────────────────────┤
│  Code        Name        Type    Enabled    Actions         │  ← 列表
│  CUST-001    ACME Corp.  B2B     ✓          [Edit] [Delete] │
│  CUST-002    ...         B2C     ✓          [Edit] [Delete] │
│  ...                                                         │
├─────────────────────────────────────────────────────────────┤
│  Pagination: [< 1 2 3 ... >]                                │  ← 分页
└─────────────────────────────────────────────────────────────┘
```

### 关键交互

| 操作 | UI | API |
|---|---|---|
| 新建 | 点「新建」→ 弹 Dialog → 填表单 → 保存 | POST `/platform-master/{entity}` |
| 编辑 | 行 Actions「Edit」→ 弹 Dialog（含现有值）→ 保存 | PUT `/platform-master/{entity}/:id` |
| 软删除 | 行 Actions「Delete」→ 二次确认 → 删除 | DELETE `/platform-master/{entity}/:id` |
| 恢复（admin）| 列表过滤 `?includeDeleted=true` → 行「Restore」 | POST `/platform-master/{entity}/:id/restore` |
| 搜索 | 搜索框输入 ≥ 3 字符 → debounce 300ms → 列表刷新 | GET `?search=xxx` |
| 类型过滤 | 下拉选 type → 列表刷新 | GET `?type=xxx` |
| 启用过滤 | 复选「仅启用」→ 列表刷新 | GET `?enabledOnly=true` |

### 通用空状态

- 无数据 + 无搜索条件 → 显示「尚无 {实体}」+ 「新建」按钮
- 无数据 + 有搜索/过滤 → 显示「无匹配结果」+ 「清除过滤」链接

### 通用错误态

- 列表加载失败 → Alert + 「重试」按钮
- 写操作失败 → Toast 显示后端 error.code 对应 i18n 文案
- code 冲突（`MASTER_CODE_EXISTS`）→ Dialog 内 inline error 标红 + 提示「code 已存在」

---

## 2. 实体特定字段

### 2.1 Customers (`/platform-master/customers`)

**列表列**：code / name / type（B2B/B2C/INTERNAL）/ currencyCode / regionCode / enabled / 创建时间

**新建 / 编辑 Dialog**：
- code（unique，create 必填，edit 只读）
- name（必填）
- type（必填，下拉 B2B/B2C/INTERNAL）
- currencyCode（下拉，来自 `/platform-master/currencies`）
- regionCode（下拉，来自 `/platform-master/geo-regions`）
- description（可选 textarea）
- enabled（checkbox，默认 true）

### 2.2 Suppliers (`/platform-master/suppliers`)

**列表列**：code / name / type（MANUFACTURER/PARTS/LOGISTICS/SERVICE）/ currencyCode / enabled

**新建 / 编辑 Dialog**：
- code / name / type / currencyCode / description / enabled
- type 选项映射 i18n 字典

### 2.3 Partners (`/platform-master/partners`)

**列表列**：code / name / typeCode（字典 partner_type）/ enabled

**新建 / 编辑 Dialog**：
- code / name / typeCode（下拉，来自 `/dictionaries?category=partner_type`）/ description / enabled

### 2.4 Locations (`/platform-master/locations`)

**列表列**：code / name / type（WAREHOUSE / SHOP / SITE 等）/ parentLocation / customerId / enabled

**新建 / 编辑 Dialog**：
- code / name / type / parentId（下拉，可选）/ customerId（下拉，可选回引 Customer）/ description / enabled
- parentId 改变时，下游 children 显示在「子位置」段（只读）

### 2.5 Currencies (`/platform-master/currencies`)

**列表列**：code（USD/CNY/EUR/AED 等）/ name / symbol / decimals / enabled

**新建 / 编辑 Dialog**：
- code（unique，create 必填，edit 只读）
- name / symbol（如 `$` `¥` `€`）/ decimals（默认 2）/ enabled

**特殊状态**：
- 已被业务表引用的 currency，DELETE 时后端可能返回 `CURRENCY_IN_USE`（实际允许软删，后续禁选）

### 2.6 Dictionaries (`/platform-master/dictionaries`)

**双栏布局**：
- 左：Category 列表（5 个：label_type / tariff_type / declaration_type / service_issue_type / industry）
- 右：选中 category 下的 entries 列表 + CRUD

**新建 / 编辑 entry Dialog**：
- category（只读，来自当前选中）
- code / labelEn / labelZh / sortOrder / enabled / metadata（JSON 编辑器）

---

## 3. 权限矩阵

| 操作 | 所需权限 |
|---|---|
| List / Get（所有页）| `robot-manager:read` |
| Customers CRUD | `robot-manager:manage:customers` |
| Suppliers CRUD | `robot-manager:manage:suppliers` |
| Partners CRUD | `robot-manager:manage:partners` |
| Locations CRUD | `robot-manager:manage:locations` |
| Currencies CRUD | `robot-manager:manage:customers`（v3 临时复用，待 issue 改 `platform-master:manage:reference-data`） |
| Dictionaries CRUD | `robot-manager:manage:fields` |

> **架构债**：v3 权限点仍前缀 `robot-manager:` 是历史复用，跟 platform-master 模块语义不匹配。followup PR 改 `platform-master:manage:*`（需要 seed 新权限点 + 角色挂权限）。

---

## 4. i18n / 双语

- 所有列表表头 / Dialog 字段 label / 按钮文案 / Toast 走 i18n
- type / typeCode 等枚举值在 `frontend/src/locales/platform-master/{zh,en}.ts` 字典查
- 日期 / 货币按 `Accept-Language` 格式化

---

## 5. 已知 UI 债 / 改进点

- **5.1 platform-master 6 page 反向依赖 robot-manager 的 API client**（`@/app/(modules)/robot-manager/_lib/api` import）— 应该把 6 类 API + types 迁到 platform-master 自己 `_lib/api/`，robot-manager 通过 re-export 维持向后兼容。详见 PR #426 ai-review risk #4 + followup issue。
- **5.2 dictionaries 双栏没虚拟滚动** — entry 数量 > 100 时滚动卡顿，需要补 react-window
- **5.3 Locations 层级选择没树状 picker** — 现在用 flat 下拉，深层级用户体验差
