Files
zyt/.trellis/tasks/archive/2026-05/05-08-order-amount-edit/prd.md
T

245 lines
9.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 业务订单详情-修改总金额功能
## Goal
在业务订单详情页面(`admin/src/views/consumer/prescription/order_list.vue`)增加修改总金额的功能,支持权限控制,并在操作日志中记录修改历史。已完成状态的订单不允许修改金额。
## What I already know
### 前端架构
- 详情页面:`admin/src/views/consumer/prescription/order_list.vue`60k+ tokens,包含详情抽屉)
- API文件:`admin/src/api/tcm.ts`(已有 `prescriptionOrderDetail``prescriptionOrderEdit``prescriptionOrderLogs` 等接口)
- 订单状态枚举:
- `fulfillment_status = 3`:已完成
- 已完成/已取消订单不可编辑(line 3025)
- 操作日志展示:详情抽屉中已有操作日志时间线(line 1192-1218
### 后端架构
- 控制器:`server/app/adminapi/controller/tcm/PrescriptionOrderController.php`
- 逻辑层:`server/app/adminapi/logic/tcm/PrescriptionOrderLogic.php`
- 模型:`server/app/common/model/tcm/PrescriptionOrder.php`
- 日志模型:`server/app/common/model/tcm/PrescriptionOrderLog.php`
- 日志写入方法:`PrescriptionOrderLogic::writeLog()` (line 2638-2658)
- 日志读取方法:`PrescriptionOrderLogic::getLogs()` (line 1913)
### 现有日志记录模式
```php
self::writeLog($orderId, $adminId, $adminInfo, 'action_name', '操作摘要');
```
日志字段:
- `prescription_order_id`:订单ID
- `admin_id`:操作人ID
- `admin_name`:操作人姓名
- `action`:操作类型(最多32字符)
- `summary`:操作摘要(最多500字符)
- `create_time`:创建时间
## Confirmed Facts
- ✅ 总金额字段:`amount` (decimal(10,2), NOT NULL, DEFAULT '0.00', COMMENT '业务订单金额')
- ✅ 状态限制:已完成(`fulfillment_status = 3`)和已取消(`fulfillment_status = 4`)都不允许修改金额
- ✅ 权限控制:新增独立菜单权限节点 `tcm.prescriptionOrder/updateAmount`
- ✅ 金额校验规则:
- 最小值:必须大于 0(不能为0或负数)
- 最大值:无限制
- 精度:保留2位小数
- ✅ 需代收金额:前端计算属性自动计算(`amount - linked_pay_paid_total`),无需后端处理
- ✅ 按钮位置:放在金额显示区域旁边(在显示总金额的卡片内)
## Requirements (final)
### 功能需求
1. 在业务订单详情页面的金额显示卡片内增加"修改金额"按钮
2. 点击按钮弹出修改金额对话框,显示当前金额,允许输入新金额
3. 已完成(`fulfillment_status = 3`)和已取消(`fulfillment_status = 4`)状态的订单隐藏修改金额按钮
4. 修改金额需要权限控制(`v-perms="['tcm.prescriptionOrder/updateAmount']"`
5. 金额校验:
- 必须大于 0
- 保留2位小数
- 最大值无限制
6. 修改成功后,在操作日志中记录:
- 操作人姓名
- 原金额
- 新金额
- 操作时间
- 日志格式:`将订单金额从 ¥{原金额} 修改为 ¥{新金额}`
7. 修改成功后立即刷新订单详情数据,需代收金额自动重新计算
### 技术需求
- 前端:在金额显示卡片内增加修改按钮和对话框
- 前端:新增API接口 `prescriptionOrderUpdateAmount(params: { id: number; amount: number })`
- 后端:新增控制器方法 `PrescriptionOrderController::updateAmount()`
- 后端:新增验证规则 `PrescriptionOrderValidate::updateAmount`
- 后端:新增逻辑层方法 `PrescriptionOrderLogic::updateAmount()`
- 后端:记录操作日志(action: `update_amount`
- SQL:新增菜单权限记录(`server/sql/1.9.20260508/add_update_amount_menu.sql`
## Acceptance Criteria (final)
- [ ] 已完成和已取消状态的订单不显示"修改金额"按钮
- [ ] 无权限的管理员不显示"修改金额"按钮
- [ ] 修改金额对话框正确显示当前金额
- [ ] 输入金额 ≤ 0 时提示错误
- [ ] 输入金额精度超过2位小数时自动截断或提示
- [ ] 提交成功后,订单 `amount` 字段更新为新金额
- [ ] 操作日志中正确记录:`{操作人} 将订单金额从 ¥{原金额} 修改为 ¥{新金额}`
- [ ] 修改后详情页面数据自动刷新,需代收金额正确显示
- [ ] 后端返回错误时前端正确提示
## Definition of Done
- 前后端代码实现完成
- 新增菜单权限SQL脚本
- 金额修改功能测试通过(正常流程、权限控制、状态限制)
- 操作日志记录正确
- 代码通过 lint/typecheck
- 无 console.log 残留
## Out of Scope (explicit)
- 批量修改金额
- 修改金额审批流程
- 金额修改历史版本对比
- 修改其他订单字段(如运费、优惠等)
## Technical Approach
### 实现流程
#### 1. 后端实现(优先)
**SQL 菜单权限**`server/sql/1.9.20260508/add_update_amount_menu.sql`
```sql
INSERT INTO `zyt_system_menu` (`pid`, `type`, `name`, `icon`, `sort`, `perms`, `paths`, `component`, `selected`, `params`, `is_cache`, `is_show`, `is_disable`)
VALUES
(处方订单菜单ID, 'A', '修改订单金额', '', 0, 'tcm.prescriptionOrder/updateAmount', '', '', '', '', 0, 0, 0);
```
**验证规则**`PrescriptionOrderValidate.php`
```php
public function updateAmount(): PrescriptionOrderValidate
{
return $this->only(['id', 'amount'])
->append('id', 'require|number')
->append('amount', 'require|float|gt:0');
}
```
**逻辑层**`PrescriptionOrderLogic.php`
```php
public static function updateAmount(array $params, int $adminId, array $adminInfo): bool
{
$id = (int) $params['id'];
$newAmount = round((float) $params['amount'], 2);
// 权限检查
$order = PrescriptionOrder::find($id);
if (!$order) {
self::setError('订单不存在');
return false;
}
// 状态检查:已完成(3)和已取消(4)不允许修改
if (in_array($order->fulfillment_status, [3, 4], true)) {
self::setError('已完成或已取消的订单不允许修改金额');
return false;
}
$oldAmount = round((float) $order->amount, 2);
// 更新金额
$order->amount = $newAmount;
$order->save();
// 记录日志
$summary = sprintf('将订单金额从 ¥%.2f 修改为 ¥%.2f', $oldAmount, $newAmount);
self::writeLog($id, $adminId, $adminInfo, 'update_amount', $summary);
return true;
}
```
**控制器**`PrescriptionOrderController.php`
```php
public function updateAmount()
{
$params = (new PrescriptionOrderValidate())->post()->goCheck('updateAmount');
$result = PrescriptionOrderLogic::updateAmount($params, $this->adminId, $this->adminInfo);
if ($result === false) {
return $this->fail(PrescriptionOrderLogic::getError());
}
return $this->success('修改成功');
}
```
#### 2. 前端实现
**API 接口**`admin/src/api/tcm.ts`
```typescript
export function prescriptionOrderUpdateAmount(params: { id: number; amount: number }) {
return request.post({ url: '/tcm.prescriptionOrder/updateAmount', params })
}
```
**页面实现**`admin/src/views/consumer/prescription/order_list.vue`
- 在金额显示卡片内增加"修改金额"按钮(带权限和状态判断)
- 新增修改金额对话框(el-dialog + el-input-number
- 提交后调用 API,成功后刷新详情数据
### 关键判断逻辑
```typescript
// 是否可以修改金额
const canUpdateAmount = (row: any) => {
// 已完成(3)或已取消(4)不允许修改
return row.fulfillment_status !== 3 && row.fulfillment_status !== 4
}
```
## Implementation Plan
### PR1: 后端实现(优先)
- [ ] 创建 SQL 菜单权限文件
- [ ] 添加验证规则 `updateAmount`
- [ ] 实现逻辑层方法 `PrescriptionOrderLogic::updateAmount()`
- [ ] 实现控制器方法 `PrescriptionOrderController::updateAmount()`
- [ ] 测试后端接口(Postman/curl
### PR2: 前端实现
- [ ] 添加 API 接口 `prescriptionOrderUpdateAmount`
- [ ] 在金额卡片内添加"修改金额"按钮(带权限和状态判断)
- [ ] 实现修改金额对话框
- [ ] 实现提交逻辑和数据刷新
- [ ] 测试完整流程(权限、状态、校验、日志)
### PR3: 测试和优化
- [ ] 测试各种边界情况(0、负数、超大金额、精度)
- [ ] 测试权限控制
- [ ] 测试状态限制
- [ ] 验证操作日志记录
- [ ] 代码 lint/typecheck
- [ ] 清理 console.log
## Technical Notes
### 文件清单
- 前端页面:`admin/src/views/consumer/prescription/order_list.vue`
- 前端API`admin/src/api/tcm.ts`
- 后端控制器:`server/app/adminapi/controller/tcm/PrescriptionOrderController.php`
- 后端逻辑:`server/app/adminapi/logic/tcm/PrescriptionOrderLogic.php`
- 后端验证:`server/app/adminapi/validate/tcm/PrescriptionOrderValidate.php`
- SQL脚本:`server/sql/1.9.20260508/add_update_amount_menu.sql`(待创建)
### 参考实现
- 操作日志写入:`PrescriptionOrderLogic::writeLog()` (line 2638)
- 操作日志读取:`PrescriptionOrderLogic::getLogs()` (line 1913)
- 状态判断逻辑:`order_list.vue` line 3025
### 约束
- 日志 action 字段最多32字符
- 日志 summary 字段最多500字符
- 遵循 likeadmin 分层架构:Controller → Logic → Model
- 权限通过菜单节点 + `v-perms` 指令控制