docs: update work order display plan
This commit is contained in:
@@ -2,9 +2,9 @@
|
||||
|
||||
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
||||
|
||||
**Goal:** 在装箱编号模块的信息区增加工令号(work_order_no)显示,采用"字段名称一行、实际值一行"的两行布局,排产号和工令号并排展示。
|
||||
**Goal:** 在装箱编号模块的信息区增加工令号(work_order_no)显示。信息区不显示字段名称,只并排显示排产号和工令号的具体值,并通过更大字号和加粗突出关键信息;装箱详情页也同步显示工令号。
|
||||
|
||||
**Architecture:** 后端从 ERP 视图 `vw_productionContractData` 额外查询 `工令号` 列,通过已有的 `/box/info` 接口返回给前端。Flutter 端解析后渲染为两行布局(标签行 + 值行)。
|
||||
**Architecture:** 后端从 ERP 视图 `vw_productionContractData` 额外查询 `工令号` 列,通过已有的 `/box/info` 接口返回给前端。Flutter 端解析后,在装箱主页面信息区和装箱详情页中展示。
|
||||
|
||||
**Tech Stack:** FastAPI + SQLAlchemy (后端), Flutter (前端), PostgreSQL (连接 ERP 视图)
|
||||
|
||||
@@ -126,8 +126,8 @@ def test_box_info_success(client: TestClient):
|
||||
data = resp.json()
|
||||
assert data["zongpai_no"] == "26BW0011"
|
||||
assert data["paichan_no"] == "W00009"
|
||||
assert data["work_order_no"] is not None
|
||||
assert isinstance(data["work_order_no"], str)
|
||||
assert "work_order_no" in data
|
||||
assert data["work_order_no"] is None or isinstance(data["work_order_no"], str)
|
||||
assert data["quantity"] == 80
|
||||
assert "existing_boxes" in data
|
||||
assert "max_box_no" in data
|
||||
@@ -142,7 +142,7 @@ source ../../.venv/Scripts/activate # 或项目虚拟环境
|
||||
pytest tests/test_box_api.py -v
|
||||
```
|
||||
|
||||
预期:`test_box_info_success` 通过,`work_order_no` 有值。
|
||||
预期:`test_box_info_success` 通过,响应中包含 `work_order_no` 字段。
|
||||
|
||||
**Step 3: 格式化代码**
|
||||
|
||||
@@ -202,7 +202,7 @@ class BoxInfoResult {
|
||||
success: true,
|
||||
zongpaiNo: json['zongpai_no'] as String?,
|
||||
paichanNo: json['paichan_no'] as String?,
|
||||
workOrderNo: json['work_order_no'] as String?,
|
||||
workOrderNo: json['work_order_no']?.toString(),
|
||||
quantity: json['quantity'] as int?,
|
||||
existingBoxes: boxes,
|
||||
maxBoxNo: json['max_box_no'] as int? ?? 0,
|
||||
@@ -270,7 +270,7 @@ setState(() {
|
||||
|
||||
---
|
||||
|
||||
### Task 6: 重写信息区 UI — 两行布局
|
||||
### Task 6: 重写信息区 UI — 仅显示值并突出关键信息
|
||||
|
||||
**Files:**
|
||||
- Modify: `apps/pad_scanner/lib/pages/boxing_page.dart` (`_buildInfoArea` 方法,约第 659-744 行)
|
||||
@@ -278,57 +278,41 @@ setState(() {
|
||||
**Step 1: 用新布局替换整个 `_buildInfoArea` 方法**
|
||||
|
||||
将原来的 `排产号标签 → 排产号值 → 已有箱数/最大箱号` 布局,改为:
|
||||
- 第一行:`排产号:` + `工令号:`(标签行)
|
||||
- 第二行:`W00009` + `6-1(7)`(值行)
|
||||
- 第三行:`已有箱数:3箱 最大箱号:3` + `详情 →`(不变)
|
||||
- 第一行:只显示具体值,`W00009` 和 `6-1(7)` 两列并排,不显示 `排产号:`、`工令号:` 字段名称
|
||||
- 排产号和工令号都使用更大字号、加粗,等待状态显示 `--`
|
||||
- 第二行:`已有箱数:3箱 最大箱号:3` + `详情 →`(不变)
|
||||
|
||||
```dart
|
||||
Widget _buildInfoArea(bool isWaiting, ColorScheme colorScheme) {
|
||||
final grey = isWaiting;
|
||||
final paichanText = grey ? '--' : (_paichanNo ?? '--');
|
||||
final workOrderText = grey ? '--' : (_workOrderNo ?? '--');
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// 字段名称行:排产号 + 工令号
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
'排产号:',
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: grey ? Colors.grey : Colors.black54,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 24),
|
||||
Text(
|
||||
'工令号:',
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: grey ? Colors.grey : Colors.black54,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
// 实际值行
|
||||
// 排产号 + 工令号:只显示值,突出关键信息
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
_paichanNo ?? '--',
|
||||
paichanText,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: grey ? Colors.grey : Colors.black87,
|
||||
),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Text(
|
||||
_workOrderNo ?? '--',
|
||||
workOrderText,
|
||||
textAlign: TextAlign.right,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: grey ? Colors.grey : Colors.black87,
|
||||
),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
@@ -336,7 +320,7 @@ Widget _buildInfoArea(bool isWaiting, ColorScheme colorScheme) {
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
const SizedBox(height: 10),
|
||||
|
||||
// 已有箱数 + 最大箱号 + 详情按钮(不变)
|
||||
Row(
|
||||
@@ -415,7 +399,102 @@ flutter analyze lib/pages/boxing_page.dart
|
||||
|
||||
---
|
||||
|
||||
### Task 7: 构建、安装并手动验证
|
||||
### Task 7: 在装箱详情页显示工令号
|
||||
|
||||
**Files:**
|
||||
- Modify: `apps/pad_scanner/lib/pages/boxing_page.dart` (`_openDetail` 方法)
|
||||
- Modify: `apps/pad_scanner/lib/pages/boxing_detail_page.dart`
|
||||
|
||||
**Step 1: 给 `BoxingDetailPage` 增加工令号参数**
|
||||
|
||||
在 `BoxingDetailPage` 中新增 `workOrderNo` 字段,并在构造函数中要求传入:
|
||||
|
||||
```dart
|
||||
class BoxingDetailPage extends StatelessWidget {
|
||||
final String paichanNo;
|
||||
final String workOrderNo;
|
||||
final List<BoxDetailData> existingBoxes;
|
||||
|
||||
const BoxingDetailPage({
|
||||
super.key,
|
||||
required this.paichanNo,
|
||||
required this.workOrderNo,
|
||||
required this.existingBoxes,
|
||||
});
|
||||
```
|
||||
|
||||
**Step 2: 在详情页标题区域显示排产号和工令号**
|
||||
|
||||
将 AppBar 标题中的单个 `paichanNo` 文本改成更紧凑的两行展示:
|
||||
|
||||
```dart
|
||||
appBar: AppBar(
|
||||
title: Row(
|
||||
children: [
|
||||
const Text('装箱详情'),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
paichanNo,
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
Text(
|
||||
workOrderNo,
|
||||
style: const TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
```
|
||||
|
||||
如果工令号为空,传入方应使用 `--`,避免详情页出现空白。
|
||||
|
||||
**Step 3: 从装箱主页面传入工令号**
|
||||
|
||||
修改 `_openDetail`:
|
||||
|
||||
```dart
|
||||
void _openDetail() {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => BoxingDetailPage(
|
||||
paichanNo: _paichanNo ?? '',
|
||||
workOrderNo: _workOrderNo ?? '--',
|
||||
existingBoxes: _existingBoxes,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
**Step 4: 验证编译和静态分析**
|
||||
|
||||
```bash
|
||||
cd apps/pad_scanner
|
||||
flutter analyze lib/pages/boxing_page.dart lib/pages/boxing_detail_page.dart
|
||||
```
|
||||
|
||||
预期:无错误。
|
||||
|
||||
---
|
||||
|
||||
### Task 8: 构建、安装并手动验证
|
||||
|
||||
**Step 1: 构建 APK**
|
||||
|
||||
@@ -434,16 +513,18 @@ adb install -r build/app/outputs/flutter-apk/app-release.apk
|
||||
|
||||
在设备上操作:
|
||||
1. 进入装箱编号页面
|
||||
2. 确认等待状态下信息区显示 `排产号:` 和 `工令号:` 标签并排,值均为 `--`
|
||||
2. 确认等待状态下信息区不显示字段名称,只显示两个并排的 `--`
|
||||
3. 扫描一个真实的执行卡(如 `26BW0011`)
|
||||
4. 确认信息区显示:
|
||||
- 标签行:`排产号:` | `工令号:`
|
||||
- 值行:`W00009`(加粗)| `6-1(7)`(常规)
|
||||
5. 在三种模式下分别测试确认布局正确
|
||||
- `W00009` 和 `6-1(7)` 两个值并排
|
||||
- 两个值都比原信息区更醒目,并且加粗
|
||||
- 不显示 `排产号:`、`工令号:` 标签
|
||||
5. 点击 `详情 →`,确认装箱详情页显示排产号和工令号
|
||||
6. 在三种模式下分别测试确认布局正确
|
||||
|
||||
**Step 4: 提交**
|
||||
|
||||
```bash
|
||||
git add apps/pad_scanner/lib/services/api_service.dart apps/pad_scanner/lib/pages/boxing_page.dart
|
||||
git commit -m "feat(boxing): display work order number in info area with two-row layout"
|
||||
git add apps/pad_scanner/lib/services/api_service.dart apps/pad_scanner/lib/pages/boxing_page.dart apps/pad_scanner/lib/pages/boxing_detail_page.dart
|
||||
git commit -m "feat(boxing): display work order number in boxing views"
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user