# Rental Estimate — 管理后台 `/admin/rental-estimates` 完整说明

> 文档对象:`https://propertylabglobal.com/admin/rental-estimates`(需登录,`auth:main`)
> 代码版本:2026-07-22 · branch `dev`(功能于 2026-07-21 上线)
> 配套文档:`/rental-estimate-public.md`(公开估算页说明)

---

## 1. 这个页面是什么

`/rental-estimate` 公开工具收集到的**租金估算线索列表**(页面标题:「租金估算 · 线索」)。
纯**只读**后台:一行一条提交,展示联系方式、户型输入、算出的租金区间、提交时间、
WhatsApp 翻新 CTA 的点击转化,以及一键 WhatsApp 联系该 lead 的快捷链接。

和 `/admin/property-match` 不同,这个后台**刻意做得很轻**:

- **无 Alpine.js、无任何 JS** — 纯服务器渲染 Blade
- **无写操作** — 没有状态 pipeline、分配、标签、备注
- **无按人去重** — 一条提交一行(同一人重复提交会出现多行)
- 搜索是**传统 GET 表单提交**(整页刷新),不是前端即时过滤

---

## 2. 文件与路由一览

| 类型 | 位置 |
| --- | --- |
| Route | `routes/web.php:2971` |
| Controller | `app/Http/Controllers/InvestHink/RentalEstimateAdminController.php`(extends `AuthedController` → **`auth:main` middleware**,未登录 302 去 login) |
| View | `resources/views/investhink/rental-estimate-admin/index.blade.php` |
| Model | `src/InvestHink/RentalEstimateSubmission.php` |
| Table | `rental_estimate_submissions`(字段明细见 public 文档 §6) |

### Route(仅一条)

| Method | URI | Action | Route name | 用途 |
| --- | --- | --- | --- | --- |
| GET | `/admin/rental-estimates?q=` | `index()` | `admin.rental-estimates.index` | 线索列表 + 搜索 |

---

## 3. `index()` 后端逻辑

1. 取 query 参数 `q`(trim)
2. `RentalEstimateSubmission` 按 id 倒序;若有 `q`,LIKE 模糊匹配四个字段(OR):
   `name` / `email` / `phone` / `property_name`
3. **cap 1000 条**(无分页)
4. 统计卡 `$totals`(注意:**统计永远是全表口径,不受搜索影响**):
   - `all` — 总线索数
   - `today` — 今天提交数(`whereDate created_at = 今天`)
   - `found` — 算出估值的条数(`est_found = 1`)
   - `wa` — 点过 WhatsApp CTA 的条数(`wa_clicked_at` 非空)→ 这就是**翻新转化漏斗**指标

---

## 4. 前端 UI 详解(纯 Blade,浅色后台风)

### 4.1 页头

- 标题「租金估算 · 线索」+ 副标「/rental-estimate 公开工具提交的租金估算线索 —— 联系方式 · 户型 · 预估月租」
- 四张统计卡:**TOTAL** / **今日 TODAY**(蓝)/ **有估值 FOUND**(绿)/ **点击 WHATSAPP**(深绿)

### 4.2 搜索条

- 一个 `<input type="search">` + 「搜索」按钮,GET 提交回本页(`?q=...`),搜索词回显在输入框

### 4.3 表格(7 列,min-width 1150px 横向滚动)

| 列 | 内容 |
| --- | --- |
| 线索 | 姓名;空显示「(未填)」 |
| 联系方式 | 手机 + email(等宽字体);空显示 — |
| 楼盘 · 位置 | property_name(空显示「(未填楼盘)」)+ place 定位标签(没有 place 则显示原始 `lat, lng` 坐标) |
| 户型 · 家私 | **N 房 / Studio** · size sqft;第二行家私中文名(经 model 常量 `FURNISH` 映射:空屋(无家私)/ 部分家私 / 全套家私) |
| 预估月租 | 有估值:**RM {est_mid}**(等宽粗体)+ 小字「RM {low}–{high} · {comps_count} 套对比」;无估值:琥珀 badge「**待估算**」 |
| 提交时间 | `m-d H:i` |
| WhatsApp 翻新 | 点过:绿 badge「**✓ 点了翻新**」+ 首次点击时间(点了多次会加「· N次」);没点:灰字「未点击」。下方(只要有手机号)恒有绿色快捷链接「**联系他**」→ `wa.me/{手机去非数字}` 新窗口直达 |

- 空状态:「还没有线索。分享 **/rental-estimate** 收集第一条。」
- 行 hover 高亮;无展开详情、无操作按钮

---

## 5. 团队使用方式(设计意图)

典型跟进优先级,从表格一眼可读:

1. **「✓ 点了翻新」的行** — 最热的 lead:主动点了 WhatsApp 想聊翻新,尽快跟进
2. **「待估算」的行** — 系统没算出估值(周边样本不足),公开页已向用户承诺
   「顾问会在 24 小时内为你精准估算」→ **需要人工回复估值**,这是隐性 SLA
3. 其余有估值但没点 WhatsApp 的 — 已看过市场租金的温 lead,可用「联系他」按钮主动触达

---

## 6. 值得注意的实现细节 / 已知限制

- **1000 条 cap 无分页** — 量大后旧线索会看不到,需要加分页/导出。
- **无去重** — 同一人反复提交出现多行(公开页无防重复提交);电话/email 相同的行需人工识别。
- **无跟进管理** — 没有状态、负责人、备注等字段;如果这个 funnel 跑起来,
  后续大概率要照 `/admin/property-match` 的模式补(pipeline + 分配 + 备注 + personScope)。
- **统计卡与搜索脱钩** — 搜索时表格变化,四张卡仍显示全表数字(口径设计如此,不是 bug)。
- **只读** — 页面无任何写操作,也就无 CSRF 面、无误操作风险;删数据要走 DB。
- 时间格式无年份(`m-d H:i`),跨年后的旧记录看不出年份。
