# 员工管理 — 测试用例

> **依据：** 《员工管理功能需求.md》v1.2、《员工管理技术方案.md》v1.1  
> **关联：** 《店铺设置测试用例.md》（配额 SS5）、《账号管理测试用例.md》（平台删号协作）  
> **范围：** 商家端 `/agri/seller/employee`；`MerchantEmployeeSupport` / `MerchantEmployeeService` / `MerchantEmployeeController`  
> **排除：** 角色管理 CRUD 本身、商家端完整登录模块另册、C 端会员  
> **环境：** RuoYi v3.9.2-springboot2；MySQL 5.7.39；请求头 **`X-Shop-Id`** 标识当前店铺

---

## 用例编号说明

| 前缀 | 类型 | 工具 |
|------|------|------|
| EM-UT-xxx | 单元测试 | JUnit 5 + Mockito |
| EM-API-xxx | 接口测试 | MockMvc / Apifox |
| EM-UI-xxx | 界面测试 | Playwright（Chromium） |

---

## 测试数据约定

| 实体 | 说明 |
|------|------|
| 商户 A | 已有经营账号 `13800001001`、店铺 `shopId=101`（另有 102）、当前店铺角色 `roleId=201` |
| 商户 B | 另一商户；店铺 201；角色 `roleId=301`（用于跨商户/跨店越权） |
| 全局配额 | `biz_shop_global_config.max_sub_admin=5`（默认） |
| 经营账号 Token | 商户 A 经营账号；含 `agri:seller:employee:*`；请求头 `X-Shop-Id=101` |
| 员工 Token | 商户 A 下已创建员工账号 Token（默认 **无** 员工管理权限） |

---

## 一、单元测试

### EM-UT-001 列表范围为当前店铺员工

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-UT-001 |
| **测试模块** | 员工管理 |
| **测试项** | selectList 数据范围 |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 + Mockito |
| **测试目的** | 验证 EM1：仅当前店铺（`X-Shop-Id`）有效员工 |
| **前置条件** | 店铺 101 有 2 员工；店铺 102 有 1 员工；商户 B 有 1 员工 |
| **测试步骤** | `X-Shop-Id=101` 上下文调用 `selectEmployeeList` |
| **预期结果** | 返回 2 条 EMPLOYEE；**不含** 店铺 102、商户 B 员工及经营账号 |

### EM-UT-002 列表仅含员工且 operable=true

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-UT-002 |
| **测试模块** | 员工管理 |
| **测试项** | 列表 accountType / operable |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 |
| **测试目的** | 验证 EM2 |
| **前置条件** | 同 EM-UT-001 |
| **测试步骤** | 检查 ListVO 的 `accountType` / `operable` |
| **预期结果** | 全部 `accountType=EMPLOYEE`、`operable=true`；**无** ADMIN 行 |

### EM-UT-003 检索仅员工名称 nick_name

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-UT-003 |
| **测试模块** | 员工管理 |
| **测试项** | employeeName 检索 |
| **测试类型** | 单元测试 / SQL |
| **测试工具** | JUnit 5 |
| **测试目的** | 验证 EM3 |
| **前置条件** | 员工 nick_name=「王小二」，user_name=13900002001 |
| **测试步骤** | `employeeName=王小`；再 `employeeName=139000` |
| **预期结果** | 前者命中；后者 **不** 按手机号/loginAccount 命中 |

### EM-UT-004 列表手机号脱敏

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-UT-004 |
| **测试模块** | 员工管理 |
| **测试项** | mobile 脱敏 |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 |
| **测试目的** | 验证列表展示规则 |
| **前置条件** | 员工手机 13900002001 |
| **测试步骤** | 调用 selectList |
| **预期结果** | `mobile` 含掩码（如 139****2001）；详情接口为完整号 |

### EM-UT-005 配额 usedCount 不含经营账号

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-UT-005 |
| **测试模块** | 员工管理 |
| **测试项** | countEmployeesByMerchantId |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 + Mockito |
| **测试目的** | 验证 EM5、SS5 |
| **前置条件** | 1 经营账号 + 3 员工（shop_id 非空） |
| **测试步骤** | 调用 `countEmployeesByMerchantId` |
| **预期结果** | 返回 3；**不计** 经营账号行 |

### EM-UT-006 创建前配额未满可过

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-UT-006 |
| **测试模块** | 员工管理 |
| **测试项** | assertQuotaAvailable |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 |
| **测试目的** | 验证创建正常路径配额校验 |
| **前置条件** | used=4，max=5 |
| **测试步骤** | 调用 `assertQuotaAvailable(merchantId)` |
| **预期结果** | 不抛异常 |

### EM-UT-007 创建前配额已满失败

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-UT-007 |
| **测试模块** | 员工管理 |
| **测试项** | assertQuotaAvailable |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 |
| **测试目的** | 验证超配额 EM5 |
| **前置条件** | used=5，max=5 |
| **测试步骤** | 调用 `assertQuotaAvailable` |
| **预期结果** | 抛 `ServiceException`；msg 含「已达上限」及 max=5 |

### EM-UT-008 停用员工仍占配额

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-UT-008 |
| **测试模块** | 员工管理 |
| **测试项** | 配额计数含停用 |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 |
| **测试目的** | 验证 EM6 |
| **前置条件** | 2 员工均为 status=1（停用） |
| **测试步骤** | countEmployeesByMerchantId |
| **预期结果** | usedCount=2 |

### EM-UT-009 删除员工后配额释放

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-UT-009 |
| **测试模块** | 员工管理 |
| **测试项** | deleteEmployee |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 + Mockito |
| **测试目的** | 验证 EM6 删除释放名额 |
| **前置条件** | used=5，max=5 |
| **测试步骤** | 逻辑删除 1 员工后再 `assertQuotaAvailable` |
| **预期结果** | used=4 后可创建 |

### EM-UT-010 角色须全部属于当前店铺

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-UT-010 |
| **测试模块** | 员工管理 |
| **测试项** | assertRolesBelongToShop |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 |
| **测试目的** | 验证 EM4、草稿 §7 |
| **前置条件** | 店铺 101 角色 201；店铺 102 角色 301 |
| **测试步骤** | `shopId=101` 传入 `roleIds=[201,301]` |
| **预期结果** | 失败；msg 含「当前店铺的角色」 |

### EM-UT-011 禁止绑定 admin 角色

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-UT-011 |
| **测试模块** | 员工管理 |
| **测试项** | 角色 role_key 校验 |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 |
| **测试目的** | 验证 EM7 |
| **前置条件** | role_key=admin 的 roleId 在 biz_shop_role(101) 中 |
| **测试步骤** | 创建/编辑传入该 roleId |
| **预期结果** | 校验失败 |

### EM-UT-012 创建须至少一个角色

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-UT-012 |
| **测试模块** | 员工管理 |
| **测试项** | validateCreate |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 |
| **测试目的** | 验证 EM4 |
| **前置条件** | 合法 CreateDTO，roleIds 为空 |
| **测试步骤** | 调用 createEmployee |
| **预期结果** | 失败；msg 含「至少选择一个角色」 |

### EM-UT-013 未携带店铺上下文失败

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-UT-013 |
| **测试模块** | 员工管理 |
| **测试项** | requireCurrentShopId |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 |
| **测试目的** | 验证 EM11、草稿 §6 |
| **前置条件** | `SellerShopContext.getShopId()` 为空 |
| **测试步骤** | 调用任意员工管理 Service 方法 |
| **预期结果** | 失败；msg 含「请先选择当前店铺」 |

### EM-UT-014 手机号全平台唯一

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-UT-014 |
| **测试模块** | 员工管理 |
| **测试项** | assertMobileUnique |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 |
| **测试目的** | 验证 EM9 |
| **前置条件** | 已有用户 user_name=13900009999 |
| **测试步骤** | 创建员工 mobile=13900009999 |
| **预期结果** | 失败；msg 含「已被使用」 |

### EM-UT-015 创建员工写 sys_user 与绑定

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-UT-015 |
| **测试模块** | 员工管理 |
| **测试项** | createEmployee 事务 |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 + Mockito |
| **测试目的** | 验证 §4.1 主流程 |
| **前置条件** | 配额未满；合法 DTO |
| **测试步骤** | 调用 createEmployee |
| **预期结果** | insert sys_user；insert biz_merchant_account（shop_id=当前 X-Shop-Id）；insertUserRole；**无** shopId 入参 |

### EM-UT-016 创建后 password 为随机 BCrypt

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-UT-016 |
| **测试模块** | 员工管理 |
| **测试项** | 初始密码 |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 |
| **测试目的** | 验证 EM10 |
| **前置条件** | 刚创建员工 |
| **测试步骤** | 读取 sys_user.password |
| **预期结果** | BCrypt 哈希；用户无法用未知密码登录 |

### EM-UT-017 员工改手机同步 user_name

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-UT-017 |
| **测试模块** | 员工管理 |
| **测试项** | updateProfile 员工分支 |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 |
| **测试目的** | 验证 EM9；**不同步** 经营账号 |
| **前置条件** | 员工原 mobile=13900002001 |
| **测试步骤** | 改 mobile=13900002002 |
| **预期结果** | user_name 与 phonenumber 均为新号；经营账号 user_name **不变** |

### EM-UT-018 改密两次不一致失败

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-UT-018 |
| **测试模块** | 员工管理 |
| **测试项** | validatePasswordUpdate |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 |
| **测试目的** | 验证改密规则 |
| **前置条件** | password≠confirmPassword |
| **测试步骤** | 调用 updatePassword |
| **预期结果** | 失败；msg 含「不一致」 |

### EM-UT-019 改密成功 BCrypt 入库

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-UT-019 |
| **测试模块** | 员工管理 |
| **测试项** | updatePassword |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 |
| **测试目的** | 验证 EM10 改密后可登录 |
| **前置条件** | 合法 password+confirmPassword（≥6 位） |
| **测试步骤** | 调用 updatePassword |
| **预期结果** | password 更新为 BCrypt；下次可用新密码登录 |

### EM-UT-020 编辑员工可改停用与角色

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-UT-020 |
| **测试模块** | 员工管理 |
| **测试项** | updateEmployee |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 |
| **测试目的** | 验证编辑主流程 |
| **前置条件** | 员工 status=0，roleIds=[201] |
| **测试步骤** | 改 status=1；roleIds=[201,202] |
| **预期结果** | sys_user.status=1；sys_user_role 更新；**不可改** shopId |

### EM-UT-021 停用后启用不增配额计数

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-UT-021 |
| **测试模块** | 员工管理 |
| **测试项** | 停用→启用 |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 |
| **测试目的** | 验证 EM6 启用路径 |
| **前置条件** | used=max=5，目标员工 status=1 |
| **测试步骤** | 编辑 status=0 |
| **预期结果** | 成功；used 仍为 5（启用不突破 count 逻辑） |

### EM-UT-022 删除员工三表一致

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-UT-022 |
| **测试模块** | 员工管理 |
| **测试项** | deleteEmployee |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 + Mockito |
| **测试目的** | 验证 §4.4 |
| **前置条件** | 有效员工 userId=1001 |
| **测试步骤** | deleteEmployee(1001) |
| **预期结果** | biz_merchant_account del_flag=2；sys_user del_flag=2；sys_user_role 清除 |

### EM-UT-023 不可删除经营账号绑定

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-UT-023 |
| **测试模块** | 员工管理 |
| **测试项** | deleteEmployee 拦截 |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 |
| **测试目的** | 验证 EM2 |
| **前置条件** | userId 为经营账号（shop_id IS NULL）或属其他店铺 |
| **测试步骤** | deleteEmployees |
| **预期结果** | 失败；msg 含「不存在」或「经营账号」 |

### EM-UT-024 非经营账号调用 requireMerchantAdmin 失败

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-UT-024 |
| **测试模块** | 员工管理 |
| **测试项** | requireMerchantAdmin |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 |
| **测试目的** | 验证访问约束 |
| **前置条件** | 当前用户为员工绑定（shop_id 非空） |
| **测试步骤** | 任意写操作入口 |
| **预期结果** | 失败；msg 含「仅商户经营账号」 |

### EM-UT-025 跨商户员工不可操作

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-UT-025 |
| **测试模块** | 员工管理 |
| **测试项** | requireEmployeeOfMerchant |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 |
| **测试目的** | 验证商户数据隔离 |
| **前置条件** | 商户 B 的员工 userId=2001 |
| **测试步骤** | 商户 A、`X-Shop-Id=101` 编辑/删/改密 店铺 102 的员工 |
| **预期结果** | 失败；msg 含不存在或无权限 |

### EM-UT-026 创建时姓名为空失败

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-UT-026 |
| **测试模块** | 员工管理 |
| **测试项** | validateCreate |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 |
| **测试目的** | 验证必填校验 |
| **前置条件** | employeeName 为空 |
| **测试步骤** | createEmployee |
| **预期结果** | 失败；msg 含员工名称 |

### EM-UT-027 邮箱格式非法失败

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-UT-027 |
| **测试模块** | 员工管理 |
| **测试项** | validateCreate / update |
| **测试类型** | 单元测试 |
| **测试工具** | JUnit 5 |
| **测试目的** | 验证邮箱格式 |
| **前置条件** | email=`not-an-email` |
| **测试步骤** | 创建或编辑 |
| **预期结果** | 失败；msg 含邮箱格式 |

---

## 二、接口测试

### EM-API-001 列表分页成功

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-API-001 |
| **测试模块** | 员工管理 |
| **测试项** | GET /list |
| **测试类型** | 接口测试 |
| **测试工具** | MockMvc / Apifox |
| **测试目的** | 验证列表主流程 |
| **前置条件** | 经营账号 Token；`X-Shop-Id=101`；`agri:seller:employee:list` |
| **测试步骤** | `GET /agri/seller/employee/list?pageNum=1&pageSize=10`（Header: X-Shop-Id=101） |
| **预期结果** | `code=200`；rows 仅含当前店铺员工；含 loginAccount、employeeName、mobile（脱敏）等 |

### EM-API-002 列表 employeeName 检索

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-API-002 |
| **测试模块** | 员工管理 |
| **测试项** | GET /list 检索 |
| **测试类型** | 接口测试 |
| **测试工具** | Apifox |
| **测试目的** | 验证 EM3 |
| **前置条件** | 员工 nick_name 含「张三」 |
| **测试步骤** | `GET .../list?employeeName=张三` |
| **预期结果** | 仅命中名称匹配行 |

### EM-API-003 配额接口

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-API-003 |
| **测试模块** | 员工管理 |
| **测试项** | GET /quota |
| **测试类型** | 接口测试 |
| **测试工具** | MockMvc |
| **测试目的** | 验证配额展示 |
| **前置条件** | 3 员工；max_sub_admin=5 |
| **测试步骤** | `GET /agri/seller/employee/quota` |
| **预期结果** | `data.usedCount=3`、`maxCount=5`、`merchantName` 与 `shopName` 非空 |

### EM-API-004 角色下拉仅当前店铺

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-API-004 |
| **测试模块** | 员工管理 |
| **测试项** | GET /roleOptions |
| **测试类型** | 接口测试 |
| **测试工具** | Apifox |
| **测试目的** | 验证 EM4、草稿 §7 |
| **前置条件** | `biz_shop_role` 店铺 101 挂角色 201；店铺 102 挂 301 |
| **测试步骤** | `GET /agri/seller/employee/roleOptions`，`X-Shop-Id=101` |
| **预期结果** | 仅返回店铺 101 角色；**不含** admin、不含店铺 102 角色 |

### EM-API-005 员工详情含 roleIds

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-API-005 |
| **测试模块** | 员工管理 |
| **测试项** | GET /{userId} |
| **测试类型** | 接口测试 |
| **测试工具** | MockMvc |
| **测试目的** | 验证详情回显 |
| **前置条件** | `agri:seller:employee:query`；员工已绑 role 201 |
| **测试步骤** | `GET /agri/seller/employee/{userId}` |
| **预期结果** | `code=200`；mobile 完整 11 位；`roleIds` 含 201 |

### EM-API-006 创建员工成功

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-API-006 |
| **测试模块** | 员工管理 |
| **测试项** | POST / |
| **测试类型** | 接口测试 |
| **测试工具** | MockMvc / Apifox |
| **测试目的** | 验证创建主流程 |
| **前置条件** | `agri:seller:employee:add`；配额未满；合法 body |
| **测试步骤** | `POST /agri/seller/employee` Header `X-Shop-Id=101`；body：employeeName、mobile、roleIds、status=0（**无 shopId**） |
| **预期结果** | `code=200`；列表新增 EMPLOYEE 行且 shop_id=101 |

### EM-API-007 创建超配额失败

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-API-007 |
| **测试模块** | 员工管理 |
| **测试项** | POST / 配额 |
| **测试类型** | 接口测试 |
| **测试工具** | Apifox |
| **测试目的** | 验证 EM5 |
| **前置条件** | 已有 5 员工；max=5 |
| **测试步骤** | POST 创建第 6 个 |
| **预期结果** | 失败；msg 含「已达上限（5）」 |

### EM-API-008 创建手机号重复失败

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-API-008 |
| **测试模块** | 员工管理 |
| **测试项** | POST / 唯一性 |
| **测试类型** | 接口测试 |
| **测试工具** | Apifox |
| **测试目的** | 验证 EM9 |
| **前置条件** | mobile 已被占用 |
| **测试步骤** | POST 同 mobile |
| **预期结果** | 失败；msg 含「已被使用」 |

### EM-API-009 创建绑定他商户角色失败

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-API-009 |
| **测试模块** | 员工管理 |
| **测试项** | POST / 角色 |
| **测试类型** | 接口测试 |
| **测试工具** | Apifox |
| **测试目的** | 验证 EM4、EM7 |
| **前置条件** | roleIds 含商户 B 的 301 |
| **测试步骤** | POST 创建 |
| **预期结果** | 失败；msg 含「当前店铺的角色」 |

### EM-API-010 未携带 X-Shop-Id 失败

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-API-010 |
| **测试模块** | 员工管理 |
| **测试项** | 店铺上下文 |
| **测试类型** | 接口测试 |
| **测试工具** | Apifox |
| **测试目的** | 验证 EM11、草稿 §6 |
| **前置条件** | 合法 Token，**不** 传 X-Shop-Id |
| **测试步骤** | GET /list 或 POST 创建 |
| **预期结果** | 失败；msg 含「请先选择当前店铺」 |

### EM-API-011 创建未选角色失败

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-API-011 |
| **测试模块** | 员工管理 |
| **测试项** | POST / roleIds |
| **测试类型** | 接口测试 |
| **测试工具** | Apifox |
| **测试目的** | 验证 EM4 |
| **前置条件** | roleIds=[] |
| **测试步骤** | POST 创建 |
| **预期结果** | 失败；msg 含「至少选择一个角色」 |

### EM-API-012 编辑员工成功

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-API-012 |
| **测试模块** | 员工管理 |
| **测试项** | PUT / |
| **测试类型** | 接口测试 |
| **测试工具** | MockMvc |
| **测试目的** | 验证编辑主流程 |
| **前置条件** | `agri:seller:employee:edit` |
| **测试步骤** | `PUT /agri/seller/employee` 改名称、头像、status、roleIds |
| **预期结果** | `code=200`；列表与详情同步更新 |

### EM-API-013 修改账号（profile）成功

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-API-013 |
| **测试模块** | 员工管理 |
| **测试项** | PUT /profile |
| **测试类型** | 接口测试 |
| **测试工具** | Apifox |
| **测试目的** | 验证草稿 §4(1) |
| **前置条件** | 目标为员工 |
| **测试步骤** | `PUT /agri/seller/employee/profile` 改 employeeName、mobile、email |
| **预期结果** | `code=200`；loginAccount 随 mobile 更新 |

### EM-API-014 跨店铺编辑员工失败

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-API-014 |
| **测试模块** | 员工管理 |
| **测试项** | PUT / 跨店 |
| **测试类型** | 接口测试 |
| **测试工具** | Apifox |
| **测试目的** | 验证 EM1、EM2 |
| **前置条件** | `X-Shop-Id=101`；userId 属店铺 102 |
| **测试步骤** | PUT 编辑该 userId |
| **预期结果** | 失败；msg 含「不存在」 |

### EM-API-015 修改密码成功

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-API-015 |
| **测试模块** | 员工管理 |
| **测试项** | PUT /resetPwd |
| **测试类型** | 接口测试 |
| **测试工具** | MockMvc |
| **测试目的** | 验证草稿 §4(2)、EM10 |
| **前置条件** | `agri:seller:employee:resetPwd` |
| **测试步骤** | `PUT /agri/seller/employee/resetPwd` password+confirmPassword |
| **预期结果** | `code=200`；该员工可用新密码登录商家端 |

### EM-API-016 改密不一致失败

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-API-016 |
| **测试模块** | 员工管理 |
| **测试项** | PUT /resetPwd 校验 |
| **测试类型** | 接口测试 |
| **测试工具** | Apifox |
| **测试目的** | 验证改密约束 |
| **前置条件** | confirmPassword 与 password 不同 |
| **测试步骤** | PUT resetPwd |
| **预期结果** | 失败；msg 含「不一致」 |

### EM-API-017 删除员工成功

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-API-017 |
| **测试模块** | 员工管理 |
| **测试项** | DELETE /{userIds} |
| **测试类型** | 接口测试 |
| **测试工具** | MockMvc |
| **测试目的** | 验证草稿 §4(3) |
| **前置条件** | `agri:seller:employee:remove` |
| **测试步骤** | `DELETE /agri/seller/employee/{userId}` |
| **预期结果** | `code=200`；列表不再展示；quota usedCount-1 |

### EM-API-018 跨店铺删除员工失败

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-API-018 |
| **测试模块** | 员工管理 |
| **测试项** | DELETE 跨店 |
| **测试类型** | 接口测试 |
| **测试工具** | Apifox |
| **测试目的** | 验证 EM1 |
| **前置条件** | `X-Shop-Id=101`；userId 属店铺 102 |
| **测试步骤** | DELETE 该 userId |
| **预期结果** | 失败；员工未被删 |

### EM-API-019 员工账号访问列表被拒绝

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-API-019 |
| **测试模块** | 员工管理 |
| **测试项** | 访问控制 |
| **测试类型** | 接口测试 |
| **测试工具** | MockMvc |
| **测试目的** | 验证 §1.4 默认员工不可管理 |
| **前置条件** | Token 为员工账号（非经营账号） |
| **测试步骤** | GET /list |
| **预期结果** | 403 或业务失败；msg 含「仅商户经营账号」 |

### EM-API-020 无 list 权限拒绝

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-API-020 |
| **测试模块** | 员工管理 |
| **测试项** | @PreAuthorize |
| **测试类型** | 接口测试 |
| **测试工具** | MockMvc |
| **测试目的** | 验证权限注解 |
| **前置条件** | Token **不含** `agri:seller:employee:list` |
| **测试步骤** | GET /list |
| **预期结果** | HTTP 403 |

### EM-API-021 创建后未改密登录失败

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-API-021 |
| **测试模块** | 员工管理 |
| **测试项** | 登录协作 |
| **测试类型** | 接口测试 |
| **测试工具** | Apifox |
| **测试目的** | 验证 EM10 |
| **前置条件** | 刚 POST 创建员工，未 resetPwd |
| **测试步骤** | 用 mobile + 任意猜测密码调用登录 |
| **预期结果** | 登录失败 |

### EM-API-022 改密后员工可登录

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-API-022 |
| **测试模块** | 员工管理 |
| **测试项** | 登录协作 |
| **测试类型** | 接口测试 |
| **测试工具** | Apifox |
| **测试目的** | 验证 EM10 闭环 |
| **前置条件** | 已 resetPwd；员工 status=0 |
| **测试步骤** | 登录 → 携带 Token 访问 `/agri/seller/shop`（X-Shop-Id） |
| **预期结果** | 登录成功；商家端接口可访问（按角色菜单） |

### EM-API-023 停用员工登录失败

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-API-023 |
| **测试模块** | 员工管理 |
| **测试项** | 停用 |
| **测试类型** | 接口测试 |
| **测试工具** | Apifox |
| **测试目的** | 验证 EM6 停用不可登录 |
| **前置条件** | 员工 status=1 |
| **测试步骤** | 正确密码登录 |
| **预期结果** | 登录失败或账号停用提示 |

### EM-API-024 平台账号管理可检索员工

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-API-024 |
| **测试模块** | 员工管理（协作） |
| **测试项** | 平台 /agri/accountManage |
| **测试类型** | 接口测试 |
| **测试工具** | Apifox |
| **测试目的** | 验证与平台边界 |
| **前置条件** | 平台管理员 Token |
| **测试步骤** | `GET /agri/accountManage/list?accountName=员工名` |
| **预期结果** | 能查到该 sys_user；shopCount 为空 |

### EM-API-025 跨商户编辑他户员工失败

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-API-025 |
| **测试模块** | 员工管理 |
| **测试项** | 数据隔离 |
| **测试类型** | 接口测试 |
| **测试工具** | Apifox |
| **测试目的** | 验证商户隔离 |
| **前置条件** | 商户 A Token；userId 属商户 B |
| **测试步骤** | PUT 编辑该 userId |
| **预期结果** | 失败；无跨商户写库 |

---

## 三、界面测试（Playwright）

> **通用前置：** Chromium；商家端 URL 以环境为准；经营账号 `13800001001` 登录；设置 `X-Shop-Id`；菜单「账号管理 → 员工管理」。

### EM-UI-001 进入列表展示商户与配额

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-UI-001 |
| **测试模块** | 员工管理 |
| **测试项** | 列表页 |
| **测试类型** | 界面测试 |
| **测试工具** | Playwright (Chrome) |
| **测试目的** | 验证 §5.1 上下文与配额 |
| **前置条件** | 经营账号已登录；商户 A 有 2 员工；max=5 |
| **测试步骤** | 1. 登录商家端 2. 进入「员工管理」 |
| **预期结果** | 展示当前店铺名称、商户名称；配额提示如「员工 2/5」；表格含员工账号、名称、手机、邮箱、状态、操作 |

### EM-UI-002 切换店铺后列表变化

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-UI-002 |
| **测试模块** | 员工管理 |
| **测试项** | 店铺切换 |
| **测试类型** | 界面测试 |
| **测试工具** | Playwright |
| **测试目的** | 验证 EM11 |
| **前置条件** | 店铺 101、102 各有员工 |
| **测试步骤** | 切换当前店铺为 102 → 进入员工管理 |
| **预期结果** | 列表仅展示店铺 102 员工 |

### EM-UI-004 按员工名称检索

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-UI-004 |
| **测试模块** | 员工管理 |
| **测试项** | 高级检索 |
| **测试类型** | 界面测试 |
| **测试工具** | Playwright |
| **测试目的** | 验证 EM3 |
| **前置条件** | 员工「李小明」、员工「王大锤」 |
| **测试步骤** | 检索框输入「小明」→ 查询 |
| **预期结果** | 仅展示「李小明」；清空后恢复全量 |

### EM-UI-005 创建员工成功

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-UI-005 |
| **测试模块** | 员工管理 |
| **测试项** | 创建 |
| **测试类型** | 界面测试 |
| **测试工具** | Playwright |
| **测试目的** | 验证 §7 主流程 |
| **前置条件** | 配额未满；存在本商户角色；有 add 权限 |
| **测试步骤** | 1. 点「创建员工」2. 填名称/手机/邮箱/选当前店铺角色 3. 提交 |
| **预期结果** | 成功提示；列表新增员工行；**表单无密码项**；提示「请为该员工设置登录密码」 |

### EM-UI-006 创建超配额前端提示

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-UI-006 |
| **测试模块** | 员工管理 |
| **测试项** | 创建配额 |
| **测试类型** | 界面测试 |
| **测试工具** | Playwright |
| **测试目的** | 验证 EM5 |
| **前置条件** | 已 5/5；或「创建」按钮应禁用 |
| **测试步骤** | 尝试打开创建并提交 |
| **预期结果** | 按钮禁用或提交后提示「已达上限（5）」 |

### EM-UI-007 创建手机号重复提示

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-UI-007 |
| **测试模块** | 员工管理 |
| **测试项** | 创建校验 |
| **测试类型** | 界面测试 |
| **测试工具** | Playwright |
| **测试目的** | 验证 EM9 |
| **前置条件** | 手机号已被占用 |
| **测试步骤** | 创建表单填重复手机号提交 |
| **预期结果** | 错误提示「该手机号已被使用」 |

### EM-UI-008 编辑员工含角色与停用

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-UI-008 |
| **测试模块** | 员工管理 |
| **测试项** | 编辑 |
| **测试类型** | 界面测试 |
| **测试工具** | Playwright |
| **测试目的** | 验证 §8 |
| **前置条件** | 员工行 operable=true |
| **测试步骤** | 编辑→改名称、换头像、切换停用、改角色→保存 |
| **预期结果** | 成功刷新；状态列变为停用；角色更新 |

### EM-UI-009 修改账号弹窗

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-UI-009 |
| **测试模块** | 员工管理 |
| **测试项** | 修改账号 |
| **测试类型** | 界面测试 |
| **测试工具** | Playwright |
| **测试目的** | 验证草稿 §4(1) |
| **前置条件** | 员工行 |
| **测试步骤** | 点「修改账号」→ 改名称/手机/邮箱→确定 |
| **预期结果** | 成功；列表手机脱敏更新；loginAccount 随手机号变 |

### EM-UI-010 修改密码弹窗

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-UI-010 |
| **测试模块** | 员工管理 |
| **测试项** | 修改密码 |
| **测试类型** | 界面测试 |
| **测试工具** | Playwright |
| **测试目的** | 验证草稿 §4(2) |
| **前置条件** | 员工行 |
| **测试步骤** | 点「修改密码」→ 填新密码与确认→确定 |
| **预期结果** | 成功提示；两次不一致时表单校验拦截 |

### EM-UI-011 删除员工二次确认

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-UI-011 |
| **测试模块** | 员工管理 |
| **测试项** | 删除 |
| **测试类型** | 界面测试 |
| **测试工具** | Playwright |
| **测试目的** | 验证 §11 二次确认 |
| **前置条件** | 员工行 |
| **测试步骤** | 点「删除」→ 确认框点确定 |
| **预期结果** | 确认文案含无法登录说明；确认后行消失；配额 used-1 |

### EM-UI-012 角色下拉仅当前店铺

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-UI-012 |
| **测试模块** | 员工管理 |
| **测试项** | 角色选择 |
| **测试类型** | 界面测试 |
| **测试工具** | Playwright |
| **测试目的** | 验证 EM4、草稿 §7 |
| **前置条件** | 当前店铺 101；打开创建/编辑表单 |
| **测试步骤** | 展开「绑定角色」下拉 |
| **预期结果** | 仅当前店铺角色；**不含** 平台超管或其他店铺角色 |

### EM-UI-013 员工账号登录不可见员工管理菜单

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-UI-013 |
| **测试模块** | 员工管理 |
| **测试项** | 菜单权限 |
| **测试类型** | 界面测试 |
| **测试工具** | Playwright |
| **测试目的** | 验证 §1.4 默认员工无入口 |
| **前置条件** | 用员工账号（已改密）登录商家端 |
| **测试步骤** | 查看侧栏「账号管理」 |
| **预期结果** | **无**「员工管理」菜单；直接访问 URL 被拒绝或跳转无权限 |

### EM-UI-014 创建后立即改密引导

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-UI-014 |
| **测试模块** | 员工管理 |
| **测试项** | 创建后改密 |
| **测试类型** | 界面测试 |
| **测试工具** | Playwright |
| **测试目的** | 验证 EM10 闭环 |
| **前置条件** | 刚创建员工成功 |
| **测试步骤** | 1. 点提示中的「设置密码」或行内「修改密码」2. 设置密码 3. 退出用新员工登录 |
| **预期结果** | 改密成功；新员工可登录商家端 |

### EM-UI-015 列表手机号脱敏展示

| 要素 | 内容 |
|------|------|
| **用例编号** | EM-UI-015 |
| **测试模块** | 员工管理 |
| **测试项** | 列表脱敏 |
| **测试类型** | 界面测试 |
| **测试工具** | Playwright |
| **测试目的** | 验证列表与详情差异 |
| **前置条件** | 员工手机 13900002001 |
| **测试步骤** | 看列表手机列；打开详情/编辑看完整号 |
| **预期结果** | 列表为掩码；详情/表单为完整 11 位 |

---

## 四、业务规则覆盖矩阵

| 规则 | 单元 | 接口 | UI |
|------|:----:|:----:|:--:|
| EM1 当前店铺列表 | UT-001 | API-001 | UI-001,002 |
| EM2 仅员工 CRUD | UT-002,023 | API-014,018 | — |
| EM3 名称检索 | UT-003 | API-002 | UI-004 |
| EM4 当前店铺角色 | UT-010,012 | API-004,009,011 | UI-012 |
| EM5 配额 | UT-005~009 | API-003,007 | UI-006 |
| EM6 停用/配额 | UT-008,021 | API-023 | UI-008 |
| EM7 角色隔离 | UT-011 | API-009 | UI-012 |
| EM9 手机=登录号 | UT-014,017 | API-008,013 | UI-007,009 |
| EM10 创建无密/改密登录 | UT-016,019 | API-006,015,021,022 | UI-005,010,014 |
| EM11 店铺上下文 | UT-013 | API-010 | UI-002 |
| EM12 响应格式 | — | API-001 等 | — |
| 仅经营账号管理 | UT-024 | API-019 | UI-013 |
| 跨店/跨商户隔离 | UT-025 | API-025 | — |
| 平台协作 | — | API-024 | — |

---

## 五、修订记录

| 版本 | 说明 |
|------|------|
| **v1.1** | 对齐需求 v1.2：当前店铺列表、`biz_shop_role`、`X-Shop-Id`、类名 MerchantEmployee* |
| **v1.0** | 首版：27 单元 + 25 接口 + 15 UI |

---

*文档版本：v1.1 · 关联《员工管理功能需求.md》v1.2、《员工管理技术方案.md》v1.1*
