# 租户管理页 - PRD

> **文档版本**: v1.0 · 2026-09-03
> **作者**: 平台产品组 + 增长产品组
> **文档状态**: 评审中
> **关联 HTML 原型**: [tenants.html](tenants.html)
> **关联后端服务**: `tenant-service` / `partner-service`
> **关联业务**: 创也·乾坤 —— 渠道商归因 + 租户管理后台

---

## 0. 一句话定位

让平台超管在**一个表格**看清"我有多少租户、各自的渠道来源、贡献了多少推广"，并能基于**渠道维度**做精细化运营（奖励、续约、风控）。

---

## 1. 业务背景与痛点

### 1.1 现状描述

- 渠道来源（俄小满 / 物流商 / 货源商）原本只是一个**字符串枚举字段**，没有专门的统计入口
- 平台超管想看"哪个渠道带来的租户多"，要靠运营手动跑 SQL
- 渠道商（合伙人）无法看到自己带来的租户数 → 见 `partner-dashboard.html` PRD

### 1.2 痛点本质

1. **渠道无统计**：平台超管无法量化渠道贡献，资源投放靠"感觉"
2. **手动打标**：渠道来源字段要运营手工填，错填率 15%
3. **跨字段孤立**：租户的「联系人/电话」与「渠道对接人」混在一起，无法快速识别
4. **操作效率低**：新增/编辑租户要走工单，24h+ 才能上线

### 1.3 价值主张

- **对平台**：4 张渠道统计卡片实时反映渠道贡献，运营决策效率提升 5x
- **对渠道商**：通过 `partner_code` 自动归因，零人工干预
- **对租户**：被精准识别后能享受渠道专属福利

---

## 2. 角色模型与权限边界

### 2.1 涉及角色

| 角色 | 角色定义 | 在本模块中的典型动作 |
| --- | --- | --- |
| **平台超管 (Super Admin)** | 平台方所有权限 | 增删改所有租户、配置权限模板 |
| **运营经理 (Ops Manager)** | 平台运营 | 查看全部、编辑部分（不能删除） |
| **渠道商管理员 (Partner Admin)** | 见 `partner-dashboard.html` | **不能**访问此页 |
| **租户主账号 (Tenant Admin)** | 自己租户的主账号 | **不能**访问此页，只能看自己的 |

### 2.2 权限矩阵

| 能力 | Super Admin | Ops Manager | Partner Admin | Tenant Admin |
| --- | --- | --- | --- | --- |
| 查看租户列表 | ✓ | ✓ | ✗ | ✗（仅自己） |
| 新增租户 | ✓ | ✗ | ✗ | ✗ |
| 编辑租户 | ✓ | ✓ | ✗ | ✗ |
| 删除租户 | ✓ | ✗ | ✗ | ✗ |
| 配置权限模板 | ✓ | ✗ | ✗ | ✗ |
| 导出 CSV | ✓ | ✓ | ✗ | ✗ |

---

## 3. 信息架构与页面规划

### 3.1 页面入口

```
侧边栏 → 全局设置 → 用户与权限 → 租户管理 tab（默认）
```

### 3.2 页面分区

```
┌──────────────────────────────────────────────────────────────┐
│  [Header] 标题 + 「导出」按钮 + 用户头像                       │
├──────────────────────────────────────────────────────────────┤
│  [Tabs] 租户管理 / 用户管理 / 角色管理 / 权限模板               │
├──────────────────────────────────────────────────────────────┤
│  [4 张渠道统计卡]                                               │
│   全部 7个 │ 俄小满 1个 │ 物流商 2个 │ 货源商 1个                │
├──────────────────────────────────────────────────────────────┤
│  [租户列表卡片]                                                  │
│   工具栏: [搜索] [渠道筛选] [状态筛选] [重置] [新增租户]          │
│   表格:                                                          │
│     租户名称 / 编码 / 授权店铺数 / 渠道来源 / 权限 / 状态 /     │
│     联系人 / 电话 / 操作                                          │
└──────────────────────────────────────────────────────────────┘
```

### 3.3 关键交互清单

| 编号 | 触发元素 | 用户动作 | 预期反馈 |
| --- | --- | --- | --- |
| INT-001 | 渠道统计卡 | 点击 | 激活卡片 + 表格筛选该渠道 + 下拉框同步 |
| INT-002 | [新增租户] | 点击 | 弹窗打开，租户编码自动生成 |
| INT-003 | 渠道下拉框 | 选择 | 推荐人字段自动显示/隐藏 |
| INT-004 | [保存] | 点击 | 校验 + 提交 + 表格更新 + 统计更新 |
| INT-005 | 行 [编辑] | 点击 | 弹窗回填 |
| INT-006 | 行 [配置权限] | 点击 | 跳转到权限配置页（v1.1） |
| INT-007 | 行 [删除] | 点击 | 二次确认 + 删除 |
| INT-008 | 搜索框 | 输入 | 实时过滤 |
| INT-009 | 渠道/状态下拉 | 切换 | 表格筛选 |
| INT-010 | [重置] | 点击 | 清空所有筛选条件 |
| INT-011 | [导出] | 点击 | 下载 CSV 文件 |

---

## 4. 核心功能模块设计

### 4.1 模块 A：渠道统计卡

#### 4.1.1 4 张卡片定义

| 卡片 | data-channel | 显示规则 |
| --- | --- | --- |
| 全部租户 | `''` | 显示全部租户总数 + 启用/停用数 |
| 俄小满 | `'exiaoman'` | 渠道来源=exiaoman 的租户数 + 占比 |
| 物流商 | `'logistics'` | 渠道来源=logistics 的租户数 + 占比 |
| 货源商 | `'goods'` | 渠道来源=goods 的租户数 + 占比 |

#### 4.1.2 字段定义

| 字段 | 类型 | 计算 |
| --- | --- | --- |
| `total_count` | int | tenants.length |
| `enabled_count` | int | tenants.filter(t => t.status === 'enabled').length |
| `disabled_count` | int | total - enabled |
| `channel_count` | int | tenants.filter(t => t.channel === key).length |
| `channel_rate` | string | `${(channel_count / total * 100).toFixed(0)}%` |

#### 4.1.3 业务规则

- **规则 1**：4 张卡片互斥激活，只能选一张（点「全部」取消其他筛选）
- **规则 2**：卡片的视觉激活态用渐变背景 + 阴影区分
- **规则 3**：占比保留整数（90% 而非 90.5%），避免数字闪烁

### 4.2 模块 B：租户列表

#### 4.2.1 字段定义

| 列 | 字段 | 类型 | 说明 |
| --- | --- | --- | --- |
| 租户名称 | `name` | string | 必填，2-100 字符 |
| 租户编码 | `code` | string | 系统生成或手动，唯一 |
| 授权店铺数 | `storeLimit` | int | 1-100 |
| 渠道来源 | `channel` | enum | `none`/`exiaoman`/`logistics`/`goods` |
| 权限范围 | — | derived | 「运营+财务版 23/41」（固定显示） |
| 状态 | `status` | enum | `enabled`/`disabled` |
| 联系人 | `contactName` | string | 可选 |
| 电话 | `contactPhone` | string | 可选，11 位手机号 |
| 操作 | — | — | 编辑 / 配置权限 / 删除 |

#### 4.2.2 渠道标签颜色规范

| 渠道 | 颜色 token | 背景 | 边框 | 文字 |
| --- | --- | --- | --- | --- |
| `none` | `none` | `#f5f5f5` | `#d9d9d9` | `#8c8c8c` |
| `exiaoman` | `exiaoman` | `#f0f0ff` | `#d6d6f5` | `#5b5ce2` |
| `logistics` | `logistics` | `#e6fffb` | `#87e8de` | `#08979c` |
| `goods` | `goods` | `#fff7e6` | `#ffd591` | `#d46b08` |

#### 4.2.3 业务规则

- **规则 1**：表格行支持点击 row（不含按钮区域）选中（v1.1 实现）
- **规则 2**：表格默认按「授权店铺数」降序
- **规则 3**：租户编码格式建议 `tenant-{prefix}{timestamp36}`，但允许自定义

### 4.3 模块 C：新增 / 编辑租户弹窗

#### 4.3.1 字段定义

| 字段 | 必填 | 校验 | 说明 |
| --- | --- | --- | --- |
| 租户名称 | ✓ | 2-100 字符 | |
| 租户编码 | ✓ | 4-50，唯一 | 新增时自动生成 |
| 授权店铺数 | ✓ | 1-100 | |
| 渠道来源 | ✓ | enum | |
| 推荐人 / 渠道对接人 | ✗ | 0-50 字符 | 选非"无"渠道时显示 |
| 联系人 | ✗ | 0-20 字符 | |
| 联系电话 | ✗ | 11 位手机号 | |
| 权限范围 | — | 固定「运营+财务版」 | |
| 状态 | ✓ | enabled/disabled | 编辑时显示，新增默认 enabled |

#### 4.3.2 状态机

```
[弹窗关闭] -- 新增 --> [新增租户]
[弹窗关闭] -- 编辑 --> [编辑租户 id=N]
[新增租户] -- 保存成功 --> [弹窗关闭 + 表格新增]
[编辑租户] -- 保存成功 --> [弹窗关闭 + 表格更新]
[任何状态] -- 取消/关闭 --> [弹窗关闭]
```

#### 4.3.3 业务规则

- **规则 1**：租户编码新增时自动生成（`tenant-{Date.now().toString(36)}`），编辑时可改
- **规则 2**：渠道来源选择 `none` 时，**隐藏**推荐人字段；选其他渠道时**显示**
- **规则 3**：删除时**二次确认**，提示「该租户下的店铺与配置将一并被清除」

### 4.4 模块 D：CSV 导出

#### 4.4.1 导出规则

| 字段 | 导出映射 |
| --- | --- |
| 渠道来源枚举 | 转为中文（`none` → `无`） |
| 状态枚举 | 转为中文（`enabled` → `启用`） |
| 字段名为中文表头 | 租户名称 / 租户编码 / 授权店铺数 / 渠道来源 / 联系人 / 电话 / 状态 |
| 文件名 | `租户列表_${YYYY-MM-DD}.csv` |
| 编码 | UTF-8 with BOM（Excel 直接打开不乱码） |

---

## 5. 交互细节与校验规则

### 5.1 表单校验

| 字段 | 触发时机 | 规则 | 错误提示 |
| --- | --- | --- | --- |
| 租户名称 | 用户离开输入框时 + 提交时 | 非空，2-100 字符 | 请输入租户名称（2-100 字符） |
| 租户编码 | 用户离开输入框时 + 提交时 | 非空，4-50 字符 | 请输入租户编码 |
| 授权店铺数 | 用户离开输入框时 + 提交时 | 1-100 | 授权店铺数应为 1 ~ 100 |
| 渠道来源 | 提交时 | 必选 | 请选择渠道来源 |
| 联系电话 | 用户离开输入框时 + 提交时 | 11 位手机号（如果填了） | 请输入正确的手机号 |

### 5.2 异常路径

| 异常场景 | 触发条件 | 用户感知 | 系统处理 |
| --- | --- | --- | --- |
| 网络断开 | 用户无网络 | 顶部黄色提示 | 阻断保存 |
| 保存失败 | 后端报错 | 顶部红色提示 | 不自动重试 |
| 删除冲突 | 该租户下有未完成任务 | 红色提示 + 详情 | 不删除 |
| 编码重复 | 后端返回「租户编码已存在」 | 字段红字 + 焦点 | 不发请求外层 |
| 推荐人为空 | 选了非「无」渠道但没填 | 不报错，仅提示 | 系统建议但不强制 |

### 5.3 可访问性

> 给有视力障碍用户使用的辅助功能。

- 表格行操作按钮单独 Tab 可达
- 渠道统计卡用语义化按钮，空格键可触发
- 弹窗用语义化对话框标签
- 错误提示要被屏幕阅读器读出

---

## 6. 异常与边界场景

### 6.1 数据边界

- **租户列表为空**：显示「暂无匹配的租户」+ 引导到「新增租户」
- **租户名称超长**：最多 100 字符，超出截断不报错
- **租户编码特殊字符**：限制只能含字母、数字、下划线、横线

### 6.2 业务边界

- **删除租户前**：检查是否有未完成的 AI 任务、进行中的同步
- **批量启用/停用**：最多 100 个/次（v1.1）
- **渠道来源修改**：会同步到合伙人 Dashboard 的渠道商统计

---

## 7. 验收标准

> 上线前必须满足的条件，每条都打勾才算完成。

- [ ] **功能完整性**：
  - [ ] 4 张渠道统计卡点击切换 + 表格筛选同步
  - [ ] 租户列表搜索 + 多条件筛选 + 重置
  - [ ] 新增 / 编辑 / 删除 租户全链路
  - [ ] 渠道来源切换显示/隐藏推荐人字段
  - [ ] CSV 导出 + Excel 兼容
- [ ] **校验规则**：§5.1 所有字段校验均实现
- [ ] **异常路径**：§6 所有边界场景均有测试覆盖
- [ ] **性能**：表格 1000 行 < 0.5 秒渲染
- [ ] **浏览器兼容**：Chrome 100+ / Safari 15+ / Edge 100+
- [ ] **响应式**：≥ 1280px、1024px、768px 三个屏幕宽度下都验证过
- [ ] **无障碍**：键盘可完全操作
- [ ] **数据埋点**：
  - [ ] 每个渠道统计卡点击
  - [ ] 新增/编辑/删除 租户事件
  - [ ] CSV 导出事件
- [ ] **设计走查**：UI 同事 review 通过
- [ ] **对接回归**：
  - [ ] 与 [register.html](register.html) 的来源渠道字段对齐
  - [ ] 与 [partner-dashboard.html](partner-dashboard.html) 的渠道商统计对齐
  - [ ] 与 [settings.html](settings.html) 的店铺列表对齐

---

## 8. 未来迭代 (本期不做)

| 版本 | 计划内容 | 价值评估 |
| --- | --- | --- |
| v1.1 | 租户详情抽屉（点击行打开右侧详情） | 高 |
| v1.1 | 批量启用/停用 + 批量删除 | 高 |
| v1.1 | 权限模板独立管理 | 中 |
| v2.0 | 租户分群标签 + 自动化运营 | 中 |
| v2.0 | 租户导入（Excel 批量） | 中 |

---

## 9. 修订记录

| 版本 | 日期 | 修改人 | 修改内容 |
| --- | --- | --- | --- |
| v1.0 | 2026-09-03 | 平台产品组 + 增长产品组 | 初稿 |
| v1.1 | 2026-09-03 | 平台产品组 + 增长产品组 | 移除技术细节章节（API/接口/组件映射），统一为产品语言 |
