# fix(user): /admin/user 列表非字典 status (status=1) 致 total > 0 records=0

**PR**: [#1834](https://git.1814.love:8443/wx/HL/pulls/1834)(主修复)+ #1831 + #1832(回滚于 #1833) **Issue**: [#1829](https://git.1814.love:8443/wx/HL/issues/1829) **合并**: 2026-05-07

通知对象: 无前端配合(后端 controller 防御兜底,前端可继续传任意值后端兜底)

---

## 现象

正式 admin: `https://admin.1814.love/admin/user?page=1&pageSize=100&status=1` 显示「有数量没有数据」。

测试服真 admin token round-trip 完美复现:

| 请求 | total | records | 备注 |
|---|---|---|---|
| `status=1` | **28** | **0** | ❌ BUG |
| 其他无效值(0/2/ABCXYZ/true) | 0 | 0 | ✅ 一致 |
| `status=ACTIVE` | 28 | 28 | ✅ |

仅 `status=1` 这个特定值出 BUG。

## 根因(深度排查 3 轮才定位)

MP `PaginationInnerInterceptor` 用 jsqlparser 把 records SELECT SQL parse 改成 count SQL。`status='1'` 这个字面值 + `.select(projection)` + `.ne(status, X)` + `.eq(status, '1')` 组合触发 jsqlparser 解析失败,**fallback 到 `SELECT COUNT(*) FROM admin_user`**(丢全部 WHERE)→ count=28(全表)records=0。

3 轮修复教训:
- **r1 PR #1831**: wrapper 从 `LambdaQueryWrapper` 迁 `LambdaQueryWrapperX` + Mapper default 方法。合 CODE_RULES 1.2,顺手修了 `status=""` 空串过滤。**但 status=1 BUG 仍在**。
- **r2 PR #1832**: 试图 `selectCount(w) + setSearchCount(false) + selectPage(page,w)` 绕过 PaginationInnerInterceptor 自动 count。**炸 SQL 全 500 BadSqlGrammarException**(wrapper state mutation 引发)→ PR #1833 revert 紧急回滚。
- **r3 PR #1834 (最终)**: 在 controller 层加 status 字典白名单 (`ACTIVE/LOCKED/DISABLED`),非字典值直接返 `PageResult.empty()` 不进 mapper。**从源头杜绝 MP BUG 路径**。

## 后端修了什么

`AdminUserController.listAdmins`(`hl-user-service/.../controller/AdminUserController.java`)在 role 鉴权之后、调 service 之前加:

```java
private static final Set<String> VALID_ADMIN_STATUS = Set.of(
        UserConstants.STATUS_ACTIVE,
        UserConstants.ADMIN_STATUS_LOCKED,
        UserConstants.STATUS_DISABLED);

if (status != null && !status.isEmpty() && !VALID_ADMIN_STATUS.contains(status)) {
    return Result.success(PageResult.of(Collections.emptyList(), 0L, page, pageSize));
}
```

mapper / service 0 改动。守护单测 `listAdmins_invalidStatus_returnsEmptyPage` 验证 status="1" 时 mapper 不被调用 + 响应空。

## 前端无需改动

前端可继续传任意值,后端兜底返空。但**建议前端只传字典值**(ACTIVE/LOCKED/DISABLED)避免无意义请求。

## 部署依赖

无 nacos / SQL / 第三方配置变更。直接部署即生效。

## 受影响范围

- `/admin/user` 列表所有 status 过滤路径(修复)
- 其他 GET 列表接口同样 PaginationInnerInterceptor 行为可能存在类似潜在 BUG,但本 PR 不范围内修复
- 已识别遗留(本次未处理): MP `PaginationInnerInterceptor` jsqlparser fallback BUG 根因仍在,需要升级 MP 版本或换 SQL 方案,留后续 PR

## 测试服 round-trip 验证 (PR #1834 部署后)

```
status=1     → total=0 records.length=0  ✅
status=0/2/ABCXYZ/true → 0/0  ✅
status=ACTIVE → 28/28  ✅
status=DISABLED → 0/0  ✅
不传 status → 28/28  ✅
status=ACTIVE&roleId=1 → 7/7  ✅
```
