docs(fleet): specify mobile itinerary link copy flow
所有检测均成功
changelog-filename-gate / validate (push) Successful in 1s
所有检测均成功
changelog-filename-gate / validate (push) Successful in 1s
这个提交包含在:
父节点
8737f63a54
当前提交
9b32c2e2e0
@ -103,22 +103,66 @@ generated: "2026-07-23T16:10:00+08:00"
|
|||||||
- `confirmHold` 根据后端 `stageCode/driverConfirmedAt` 恢复流程:等待司机回复时进入第 3 步“待确认”,已登记司机确认时进入第 4 步“确认执行”;
|
- `confirmHold` 根据后端 `stageCode/driverConfirmedAt` 恢复流程:等待司机回复时进入第 3 步“待确认”,已登记司机确认时进入第 4 步“确认执行”;
|
||||||
- `availableActionCodes` 包含 `CHANGE_ASSIGNMENT` 时另行显示“改派”,点击进入第 2 步重新选择车辆或司机;
|
- `availableActionCodes` 包含 `CHANGE_ASSIGNMENT` 时另行显示“改派”,点击进入第 2 步重新选择车辆或司机;
|
||||||
- 两个按钮不得互相替代:“继续派车”推进当前有效派单,“改派”修改当前有效派单;
|
- 两个按钮不得互相替代:“继续派车”推进当前有效派单,“改派”修改当前有效派单;
|
||||||
- “打印行程单”是独立只读能力,直接复用订单详情现有打印预览,不参与派单状态流转。
|
- “复制行程单链接”是独立只读能力,复制后端为当前有效派单签发的司机 H5 链接,不参与派单状态流转。
|
||||||
|
|
||||||
当前 `v2.1@6e6a11bf` 的 `resolveBoardRowActions()` 仍检查已经废弃的 `CONFIRM` 动作码,而后端生命周期实际下发 `RECORD_DRIVER_CONFIRMATION`,因此截图中“继续派车/司机已确认”按钮没有渲染。前端改为消费真实动作码即可,无需后端增加兼容别名。
|
当前 `v2.1@6e6a11bf` 的 `resolveBoardRowActions()` 仍检查已经废弃的 `CONFIRM` 动作码,而后端生命周期实际下发 `RECORD_DRIVER_CONFIRMATION`,因此截图中“继续派车/司机已确认”按钮没有渲染。前端改为消费真实动作码即可,无需后端增加兼容别名。
|
||||||
|
|
||||||
### 看板复用“打印行程单”
|
### 看板复制司机 H5 行程单链接
|
||||||
|
|
||||||
看板不再维护独立的“发行程单”抽屉,也不在前端模拟发送成功。订单详情已经提供完整且权威的打印能力,看板只增加同能力入口:
|
看板不再维护独立的“发行程单”抽屉,也不在前端模拟发送成功。这里不是打开订单详情的“打印行程单”,而是把后端已经为当前有效派单签发的 H5 链接复制到剪贴板,车务再通过微信等渠道发给司机。司机可在手机浏览器中独立打开,不需要登录管理后台。
|
||||||
|
|
||||||
- 将看板按钮文案由“发行程单”改为“打印行程单”;
|
- 将看板按钮文案由“发行程单”改为“复制行程单链接”,事件名同步改为 `copy-itinerary-link`,避免继续表达成“发送”;
|
||||||
- 直接复用 `src/views/order-v2/detail/modals/PrintItineraryModal.vue`;
|
- 点击时先调用既有看板详情接口 `GET /admin/fleet/board/orders/{orderId}`,不要调用订单打印接口;
|
||||||
- 继续调用既有 `getPrintItinerary(orderId)`,即 `GET /v3/admin/order/{orderId}/print-itinerary`;
|
- 默认复制 `currentAssignment.itineraryUrl`;如果入口明确针对某一条有效派单,则复制对应 `activeAssignments[].itineraryUrl`;
|
||||||
- `orderId` 使用 `resolveBoardOrderId(order)` 的字符串结果,禁止传团号、订单号或做 `Number()` 转换;
|
- 链接必须直接使用后端返回值,前端不得自行拼接 H5 地址、token、订单 ID 或派单 ID;
|
||||||
|
- 优先使用 `navigator.clipboard.writeText(itineraryUrl)`;当前管理后台可能运行在 HTTP 内网环境,必须同时提供临时 `textarea + document.execCommand('copy')` 降级实现;
|
||||||
|
- 复制成功提示“行程单链接已复制,可发送给司机”;
|
||||||
|
- `itineraryUrl` 为空时不得复制或提示成功,应提示“行程单链接暂不可用,请确认已派车且 H5 配置正常”;
|
||||||
- 删除/停用看板自己的 `ItinerarySendSheet.vue`、消息模板和本地 `message.success('已发送行程单')` 假流程;
|
- 删除/停用看板自己的 `ItinerarySendSheet.vue`、消息模板和本地 `message.success('已发送行程单')` 假流程;
|
||||||
- 打印内容、彩色/黑白切换、加载失败重试、权限和后端数据源与订单详情完全一致,后续只维护一套。
|
- 不复用 `PrintItineraryModal.vue`,不调用 `GET /v3/admin/order/{orderId}/print-itinerary`;订单详情的“打印行程单”继续作为面向车务的独立打印能力保留;
|
||||||
|
- 链接包含签名 token,前端日志、埋点和错误提示不得记录或展示完整 URL;
|
||||||
|
- 改派成功后必须重新拉取详情并使用新派单的 `itineraryUrl`,不能继续缓存或复制旧派单链接。
|
||||||
|
|
||||||
该打印入口不改变派单状态,也不依赖订单处于待派车、待确认或已派车;是否展示只按订单打印权限和有效订单 ID 判断。
|
后端链接已绑定当前订单与具体派单,有效期至行程结束后 7 天;公开 H5 接口会校验签名、有效期和派单归属,并实时读取行程数据。复制动作本身不改变派单状态,也不产生“已发送”记录。
|
||||||
|
|
||||||
|
建议前端按以下逻辑落地(函数名可按现有工程调整):
|
||||||
|
|
||||||
|
```ts
|
||||||
|
async function onCopyItineraryLink(order: BoardOrder) {
|
||||||
|
const orderId = resolveBoardOrderId(order)
|
||||||
|
const detail = await getBoardOrderDetail(orderId)
|
||||||
|
const itineraryUrl = detail.currentAssignment?.itineraryUrl?.trim()
|
||||||
|
|
||||||
|
if (!itineraryUrl) {
|
||||||
|
message.error('行程单链接暂不可用,请确认已派车且 H5 配置正常')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (navigator.clipboard && window.isSecureContext) {
|
||||||
|
await navigator.clipboard.writeText(itineraryUrl)
|
||||||
|
} else {
|
||||||
|
copyTextByTextarea(itineraryUrl)
|
||||||
|
}
|
||||||
|
message.success('行程单链接已复制,可发送给司机')
|
||||||
|
} catch {
|
||||||
|
message.error('复制失败,请稍后重试')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function copyTextByTextarea(text: string) {
|
||||||
|
const textarea = document.createElement('textarea')
|
||||||
|
textarea.value = text
|
||||||
|
textarea.setAttribute('readonly', '')
|
||||||
|
textarea.style.position = 'fixed'
|
||||||
|
textarea.style.opacity = '0'
|
||||||
|
document.body.appendChild(textarea)
|
||||||
|
textarea.select()
|
||||||
|
const copied = document.execCommand('copy')
|
||||||
|
document.body.removeChild(textarea)
|
||||||
|
if (!copied) throw new Error('copy failed')
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## 三、不影响范围
|
## 三、不影响范围
|
||||||
|
|
||||||
@ -136,8 +180,12 @@ generated: "2026-07-23T16:10:00+08:00"
|
|||||||
- [ ] 技术状态值仍为 `holding`,改派、司机确认和超时判断不因文案变化而改变。
|
- [ ] 技术状态值仍为 `holding`,改派、司机确认和超时判断不因文案变化而改变。
|
||||||
- [ ] 待确认订单在 `RECORD_DRIVER_CONFIRMATION` 可用时显示“继续派车”,点击以 `confirmHold` 恢复第 3/4 步。
|
- [ ] 待确认订单在 `RECORD_DRIVER_CONFIRMATION` 可用时显示“继续派车”,点击以 `confirmHold` 恢复第 3/4 步。
|
||||||
- [ ] “继续派车”和“改派”同时存在且职责分离;前端不再检查不存在的 `CONFIRM` 动作码。
|
- [ ] “继续派车”和“改派”同时存在且职责分离;前端不再检查不存在的 `CONFIRM` 动作码。
|
||||||
- [ ] 看板显示“打印行程单”,打开内容与订单详情的打印预览完全一致。
|
- [ ] 待确认或已派车且存在当前有效派单时,看板显示“复制行程单链接”。
|
||||||
- [ ] 看板不再使用 `ItinerarySendSheet` 或模拟“已发送行程单”,Network 只调用既有打印接口。
|
- [ ] 点击后通过看板详情取得并复制 `currentAssignment.itineraryUrl`,不调用订单打印接口、不在前端拼接链接。
|
||||||
|
- [ ] HTTPS/localhost 使用 Clipboard API,HTTP 内网环境可通过降级方案正常复制。
|
||||||
|
- [ ] 复制成功提示“行程单链接已复制,可发送给司机”;链接为空或复制失败时给出明确错误且不误报成功。
|
||||||
|
- [ ] 复制出的链接可由司机在手机浏览器中独立打开,无需登录管理后台,并展示当前派单的实时行程。
|
||||||
|
- [ ] 看板不再使用 `ItinerarySendSheet` 或模拟“已发送行程单”,改派后不会复制旧派单链接。
|
||||||
- [ ] 打开排车步骤时,候选请求同时携带字符串 `orderId`、`requirementId` 和当前 `fleetItemIndex`,不再出现“改派候选查询必须携带当前订单ID、用车需求ID和车型项索引”。
|
- [ ] 打开排车步骤时,候选请求同时携带字符串 `orderId`、`requirementId` 和当前 `fleetItemIndex`,不再出现“改派候选查询必须携带当前订单ID、用车需求ID和车型项索引”。
|
||||||
- [ ] 提交时调用既有 `changeAssignment`,不调用创建派单接口。
|
- [ ] 提交时调用既有 `changeAssignment`,不调用创建派单接口。
|
||||||
- [ ] `assigned`、`completed`、`canceled` 不误显示入口。
|
- [ ] `assigned`、`completed`、`canceled` 不误显示入口。
|
||||||
|
|||||||
正在加载...
x
在新工单中引用
屏蔽一个用户