# 发送记录页面开发文档

## 一、功能概述

发送记录页面用于查询历史上通过现场一体机或小程序下达的配方记录，了解某段时间内下发了哪些配方、多少车数、什么时间下发的。

**数据来源**：`R_TRANSFER` 表（现场 PC 执行后反向写入）
**查询方式**：日期范围查询（最多 5 天）
**展示形式**：表格（序号、配方名称、设定车数、发送端、发送时间、批号）

## 二、数据来源决策

| 表名 | 数据来源 | 是否可选 |
|------|----------|----------|
| `M_TRANSFER` | 小程序端下达时写入 | ❌ 不含现场 PC 端直接写入的记录 |
| `R_TRANSFER` | 现场 PC 端执行后反向写入 | ✅ 包含所有实际执行过的配方（小程序+现场） |

**决策**：从 `R_TRANSFER` 读取。`R_TRANSFER` 是现场 PC 执行后的统一记录表，虽然数据有延迟（需等 PC 执行后才会出现），但覆盖范围最全。用户要求"有啥显示啥"，直接读取即可。

## 三、查询方式设计

### 3.1 为什么用日期范围查询而非状态筛选？

`R_TRANSFER` 没有"执行状态"字段（没有 STATE 列），只有 `LOCAL_FLAG`（来源标识）和 `SAVE_TIME`（发送时间）。因此无法用"待执行/已完成"等状态筛选，只能用时间范围查询。

### 3.2 为什么限制最多5天？

- `R_TRANSFER` 是现场 PC 高频写入的表，数据量增长快
- 展会场景下，用户通常只关心最近几天的记录
- 限制5天可以防止误选过长时间导致查询缓慢、数据传输过大

### 3.3 默认范围：昨天 ~ 今天

页面加载时自动查询最近2天的数据，用户打开页面即可看到最新记录，无需手动选择后点击查询。

## 四、接口文档

### 4.1 获取发送记录

```
GET /api/exhibition/send-record.php?startDate=YYYY-MM-DD&endDate=YYYY-MM-DD
```

**请求参数**：

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| startDate | string | 否 | 开始日期，格式 `YYYY-MM-DD`，默认昨天 |
| endDate | string | 否 | 结束日期，格式 `YYYY-MM-DD`，默认今天 |

**响应示例**：
```json
{
  "code": 0,
  "message": "获取成功",
  "data": {
    "list": [
      {
        "id": 62,
        "lotId": "202604281441237312",
        "recipeName": "444",
        "batchSet": 13,
        "localFlag": 1,
        "sourceText": "本地",
        "saveTime": "20260428144123"
      }
    ],
    "startDate": "2026-04-28",
    "endDate": "2026-04-28"
  }
}
```

**后端逻辑**：
1. 校验日期格式
2. 校验时间范围不超过5天
3. 将日期转为 `Ymd000000` / `Ymd235959` 格式
4. 查询 `R_TRANSFER` 表中 `SAVE_TIME` 范围内的记录
5. `LOCAL_FLAG` 映射：1 → "本地"，2 → "手机"

## 五、界面设计

### 5.1 布局结构

```
┌──────────────────────────────────────────┐
│ 2026/05/05  至  2026/05/06         🔍   │  ← 日期筛选区
├──────────────────────────────────────────┤
│ 序号  配方名称  车数  发送端  发送时间  批号 │  ← 表头
│  1     444     13    本地   2026-04... ... │  ← 数据行
│  2     3332    12    本地   2026-04... ... │
│ ...                                      │
└──────────────────────────────────────────┘
```

### 5.2 UI 布局演进

#### 第一阶段：卡片列表 + 状态筛选标签

最初设计模仿常见 App 的消息/记录列表，每条记录一张卡片，顶部有"全部/待执行/已完成/失败"筛选标签。

**问题**：
- `R_TRANSFER` 没有 STATE 字段，状态筛选无意义
- 卡片形式在字段少（仅4列）时浪费纵向空间
- 用户需要看到时间范围的记录，而非按状态过滤

#### 第二阶段：表格 + 日期筛选

改为顶部日期筛选区 + 下方表格展示。表格在移动端通过横向滚动条容纳6列数据（序号、配方名称、车数、发送端、发送时间、批号）。

**查询按钮位置演进**：
- 第一版：查询按钮在标题栏右侧（和"发送记录"标题同行）
- 第二版：查询按钮在日期筛选区最右侧，改为放大镜 SVG 图标
- 最终版：去掉页面内标题栏（微信小程序自带导航栏已显示标题），整个页面只有日期筛选区和表格

### 5.3 字段映射与显示设计

| 字段 | 原始值 | 显示值 | 说明 |
|------|--------|--------|------|
| `LOCAL_FLAG` | 1 | 本地 | 现场一体机本地操作 |
| `LOCAL_FLAG` | 2 | 手机 | 小程序/手机端操作 |
| `SAVE_TIME` | `20260428144123` | `2026-04-28 14:41:23` | 字符串格式化解析 |
| `BATCH_SET` | 13 | 13 | 直接显示，不加"车"字（节省列宽） |
| `LOT_ID` | `202604281441...` | 完整显示 | 作为批号列 |

**发送端显示**：
- 初版：绿色/蓝色圆角标签（"微信端"/"现场端"）
- 终版：普通文字（"手机"/"本地"），不加背景色，减少视觉干扰

**列宽设计**（移动端横向滚动场景）：
- 序号：32px（最窄，仅显示数字）
- 配方名称：80px（最长8个汉字，超出截断）
- 车数：60px（仅两位数）
- 发送端：50px（仅两个汉字）
- 发送时间、批号：自适应

**对齐方式**：
- 表头全部居中
- 数据行：配方名称左对齐，其余居中

## 六、开发说明

### 6.1 文件清单

| 文件路径 | 说明 |
|----------|------|
| `mobile/exhibition/send-record/index.html` | 发送记录页面（日期筛选 + 表格） |
| `api/exhibition/send-record.php` | 发送记录查询API（查询 `R_TRANSFER`） |

### 6.2 关键代码说明

#### 日期范围校验
```javascript
function validateDateRange() {
    const start = new Date(startDateInput.value);
    const end = new Date(endDateInput.value);
    const diffDays = (end - start) / 86400000;
    if (diffDays > 5) {
        showToast('查询时间范围不能超过5天');
        return false;
    }
    return true;
}
```

#### 日期变化提示（不自动调整）
```javascript
function checkDateRangeHint() {
    const start = new Date(startDateInput.value);
    const end = new Date(endDateInput.value);
    if (isNaN(start.getTime()) || isNaN(end.getTime())) return;
    const diffDays = (end - start) / 86400000;
    if (diffDays > 5 || diffDays < -5) {
        showToast('时间范围不能超过5天，请手动调整');
    }
}
```

> **设计说明**：日期变化时只做提示，不自动调整。因为用户可能先选一个很远的日期，再调整另一个日期，自动调整会打断用户操作节奏。最终校验在点击查询时完成。

#### 后端日期转换
```php
$startTime = date('Ymd000000', $startTs);
$endTime = date('Ymd235959', $endTs);
```

## 七、开发中的关键问题与解决方案

### 问题 1：iOS 日期输入框显示不全

**现象**：`<input type="date">` 在 iPhone 上显示 "2026/05/"，后面的日期被截断。

**根因**：iOS Safari 的日期输入框自带右侧日历图标，占用约 30-40px 宽度。加上"开始"/"结束"文字标签后，留给日期框的可用宽度仅约 110px，不足以显示完整 "2026/05/05"。

**解决**：去掉"开始"/"结束"两个文字标签，两个日期框之间用"至"字连接。释放标签占用的宽度后，日期框可通过 `flex: 1` 自动分配足够空间。

### 问题 2：查询按钮 SVG 图标被 JS 覆盖

**现象**：查询按钮初始显示放大镜 SVG 图标，点击后变成"查询中..."文字，且之后永远显示"查询"文字。

**根因**：`loadRecords()` 函数中有 `queryBtn.textContent = '查询中...'` 和 `queryBtn.textContent = '查询'`。`textContent` 会清空元素内所有子节点（包括 SVG），替换为纯文本。

**解决**：删除这两行 `textContent` 赋值。查询状态由表格区域的"加载中..."提示，按钮只保留 `disabled` 状态切换。

### 问题 3：微信 WebView 缓存导致按钮不更新

**现象**：代码已改为 SVG 图标，但微信预览中按钮仍显示旧版"查询"文字。

**根因**：微信内置浏览器对 H5 页面有强缓存。

**解决**：小程序 WebView URL 追加 `?v=${Date.now()}` 时间戳，或在微信开发者工具中清除缓存。

### 问题 4：表格列宽与横向滚动

**现象**：6 列数据在小屏幕（375px）上一行放不下，列内容被挤压变形。

**解决**：
- 给表格设置 `min-width: 560px`，强制总宽度超过屏幕，触发 `overflow-x: auto` 横向滚动
- 关键列（序号、车数、发送端）设置固定窄宽度，减少横向占用
- 添加 `-webkit-overflow-scrolling: touch` 改善 iOS 滚动体验

### 问题 5：顶部导航栏安全距离（已回退）

**现象**：曾尝试给 `body` 加 `padding-top: 80px` 再改 `44px`，导致日期框大幅下移，和导航栏之间出现大片空白。

**根因**：微信小程序 WebView 在 Android 和 iOS 上的内容区域起点不同。iOS 会自动避开导航栏，Android 下内容从屏幕顶部开始，但本项目的实际测试表明默认布局并无遮挡问题（之前的"遮挡"是缓存导致的旧版本渲染异常）。

**解决**：去掉 `padding-top`，保持原始布局。微信 WebView 的内容区域已自动处理导航栏避让。

## 八、最佳实践总结

1. **移动端日期输入**：去掉文字标签，用连接符"至"分隔两个日期框，释放宽度给输入框本身
2. **SVG 图标按钮**：避免用 `textContent` 修改含 SVG 的按钮内容，改用 `disabled` + 外部 loading 提示
3. **表格横向滚动**：固定窄列宽 + `min-width` 强制溢出 + `overflow-x: auto`
4. **数据映射清晰**：后端统一映射 `sourceText`，前端只做展示，不处理业务逻辑
5. **缓存意识**：微信 WebView 修改后必须清缓存，否则 UI 和逻辑更新都无法生效

## 九、更新记录

| 日期 | 版本 | 更新内容 |
|------|------|----------|
| 2026-05-06 | v1.1 | 修正文档中日期校验函数描述：`checkDateRangeHint` 只提示不自动调整，与代码保持一致；补充分层校验设计说明 |
| 2026-05-05 | v1.0 | 发送记录页面定稿：表格形式展示、日期范围查询（最多5天）、LOCAL_FLAG 映射（本地/手机）、去掉页面内标题栏、查询按钮改 SVG 放大镜 |
