245 lines
9.1 KiB
Markdown
245 lines
9.1 KiB
Markdown
# 业务订单详情-修改总金额功能
|
||
|
||
## 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` 指令控制
|