1 changed files with 201 additions and 0 deletions
@ -0,0 +1,201 @@ |
|||
# 航线库编辑 / 删除设计 |
|||
|
|||
日期:2026-09-01 |
|||
状态:已批准(对话确认) |
|||
范围:`laic-frontend` 航线库前端能力补齐 |
|||
|
|||
## 背景 |
|||
|
|||
任务管理 → 航线库当前仅支持: |
|||
|
|||
- 列表展示与搜索 |
|||
- 新建航线(地图点选航点 → `POST /v1/routes`) |
|||
|
|||
卡片 `RouteCard` 为纯展示,无编辑 / 删除入口。 |
|||
后端已具备完整 CRUD: |
|||
|
|||
| 能力 | 接口 | |
|||
|------|------| |
|||
| 列表 | `GET /v1/routes` | |
|||
| 详情 | `GET /v1/routes/:id` | |
|||
| 新建 | `POST /v1/routes` | |
|||
| 更新 | `PUT /v1/routes/:id`(`waypoints` 有值则整体替换) | |
|||
| 删除 | `DELETE /v1/routes/:id` | |
|||
|
|||
缺口仅在前端接线。 |
|||
|
|||
## 目标 |
|||
|
|||
1. 航线卡片提供 **编辑**、**删除** 操作。 |
|||
2. 编辑复用现有航线编辑器(地图 + 航点侧栏),不新建第二套 UI。 |
|||
3. 删除需二次确认。 |
|||
4. 新建路径行为保持不变。 |
|||
|
|||
## 非目标 |
|||
|
|||
- 航线复制、导入 / 导出、只读详情页 |
|||
- 任务占用拦截(后端未暴露占用校验时前端不做) |
|||
- 管理端特殊权限 UI(沿用接口 401/403) |
|||
- 后端改动 |
|||
- `description` 字段(当前新建流程也未采集) |
|||
|
|||
## 交互 |
|||
|
|||
### 列表卡片 |
|||
|
|||
- 每张 `RouteCard` 增加操作区:**编辑**、**删除** |
|||
- 布局:卡片内容下方操作条(对齐设备 / 任务 `.row-actions` 文字按钮风格) |
|||
- 删除使用危险色(`theme="danger"`) |
|||
- 不采用「整卡点击进编辑」;操作显式按钮,避免误触 |
|||
|
|||
### 编辑 |
|||
|
|||
1. 点击「编辑」 |
|||
2. 请求 `GET /v1/routes/:id` |
|||
3. 成功后打开现有 `route-editor`: |
|||
- 标题:`编辑航线` |
|||
- 主按钮:`保存修改`(保存中:`保存中…`) |
|||
4. 回填: |
|||
- 航线名称 |
|||
- 航点列表与地图轨迹 |
|||
- 默认高度 / 速度:取首航点;无航点时回退 `50` / `10` |
|||
- `turnMode`:`holdSec > 0` → `stop`,否则 `auto` |
|||
5. 编辑器内仍可增删改航点、撤销、清空、应用到全部航点(与新建相同) |
|||
6. 保存校验与新建一致: |
|||
- 名称必填 |
|||
- 至少 2 个航点 |
|||
7. 提交 `PUT /v1/routes/:id`,body: |
|||
```json |
|||
{ |
|||
"name": "...", |
|||
"waypoints": [ |
|||
{ "longitude": 0, "latitude": 0, "altitude": 0, "speed": 0, "yaw": 0, "holdSec": 0 } |
|||
] |
|||
} |
|||
``` |
|||
8. 成功:toast「航线已更新」→ 关闭编辑器 → 刷新列表 |
|||
9. 失败:编辑器内 `routeFormError` 展示错误,不关闭 |
|||
|
|||
### 删除 |
|||
|
|||
1. 点击「删除」 |
|||
2. `ui.confirm`: |
|||
- 标题:`确认删除航线「{name}」?` |
|||
- 说明:删除后不可恢复;已绑定该航线的任务需自行处理(简短文案即可) |
|||
3. 确认后 `DELETE /v1/routes/:id` |
|||
4. 成功:toast「航线已删除」→ 刷新列表 |
|||
5. 失败:toast 错误信息 |
|||
6. 删除入口仅在卡片;编辑器内不放删除(按已选交互) |
|||
|
|||
### 新建(不变) |
|||
|
|||
- `editingRouteId = null` |
|||
- 标题仍为「新建航线」 |
|||
- 主按钮仍为「保存航线」 |
|||
- 仍 `POST /v1/routes` |
|||
|
|||
## 数据流与状态 |
|||
|
|||
### URL |
|||
|
|||
`src/config/urls.js` 增补: |
|||
|
|||
```js |
|||
export const ROUTES = '/v1/routes' |
|||
export const ROUTE = (id) => `/v1/routes/${id}` |
|||
``` |
|||
|
|||
### 视图状态(TasksView) |
|||
|
|||
| 状态 | 含义 | |
|||
|------|------| |
|||
| `editingRouteId` | `null` = 新建;非空 = 正在编辑的航线 id | |
|||
| `routeEditorOpen` | 编辑器显隐(已有) | |
|||
| `routeForm` / `routePoints` | 已有表单与航点 | |
|||
| `routeSaving` | 保存中禁用(已有) | |
|||
|
|||
生命周期: |
|||
|
|||
- `openRouteEditor()`:reset → `editingRouteId=null` → open(新建) |
|||
- `openRouteEditorForEdit(route)`:reset → GET 详情 → 填表 → `editingRouteId=id` → open |
|||
- `closeRouteEditor()`:teardown map → close → `editingRouteId=null` + reset |
|||
- `submitRoute()`:按 `editingRouteId` 分支 POST / PUT |
|||
- `deleteRoute(route)`:confirm → DELETE → reload |
|||
|
|||
### 航点映射 |
|||
|
|||
``` |
|||
API → UI: |
|||
longitude/latitude/altitude/speed 原样 Number |
|||
turnMode = holdSec > 0 ? 'stop' : 'auto' |
|||
|
|||
UI → API: |
|||
yaw = 0 |
|||
holdSec = turnMode === 'stop' ? 1 : 0 |
|||
``` |
|||
|
|||
与现有 `submitRoute` 映射保持一致。 |
|||
`PUT` **始终**携带全量 `waypoints`,触发后端整体替换。 |
|||
|
|||
### 列表映射注意 |
|||
|
|||
当前列表用分页 records 映射卡片;列表项可能不含完整 waypoints(取决于后端 page 是否 embed)。 |
|||
|
|||
- 列表展示:继续用现有 fields(name、waypoints 计数、distance、collectedAt) |
|||
- 编辑回填:**必须以详情接口为准**,不信任列表里的精简数据 |
|||
- 若列表无 waypoints 导致 distance/`waypoints` 计数为 0,属既有问题,本需求不强制修 page API;编辑保存后 `load()` 刷新 |
|||
|
|||
## 组件改动 |
|||
|
|||
### `RouteCard.vue` |
|||
|
|||
Props 保持展示字段;新增: |
|||
|
|||
- emit:`edit`、`delete` |
|||
- 模板底部操作条:编辑(primary text)、删除(danger text) |
|||
- 点击操作 `@click.stop`,避免未来卡片可点时冒泡 |
|||
|
|||
### `TasksView.vue` |
|||
|
|||
- 绑定 `@edit` / `@delete` |
|||
- 实现上述 open/submit/delete 逻辑 |
|||
- 编辑器 header 文案随 `editingRouteId` 切换 |
|||
|
|||
### `prototype.css`(或 RouteCard 局部样式) |
|||
|
|||
- `.route-card-actions`:flex、间距、与卡片底部分隔 |
|||
- 对齐现有 `.row-actions` 观感,不引入新视觉体系 |
|||
|
|||
## 错误处理 |
|||
|
|||
| 场景 | 行为 | |
|||
|------|------| |
|||
| 详情加载失败 | toast,不打开编辑器 | |
|||
| 保存校验失败 | editor 内错误文案 | |
|||
| 保存接口失败 | editor 内错误文案,保持编辑态 | |
|||
| 删除取消 | 无副作用 | |
|||
| 删除接口失败 | toast | |
|||
| 401/403 | 走现有 axios 拦截器 | |
|||
|
|||
## 验收标准 |
|||
|
|||
1. 航线库卡片可见「编辑」「删除」。 |
|||
2. 编辑:名称与航点回填正确,地图显示轨迹。 |
|||
3. 修改后保存:列表名称 / 航点数更新。 |
|||
4. 删除确认后卡片从列表消失。 |
|||
5. 新建航线流程与文案不受影响。 |
|||
6. 保存中按钮禁用,防止重复提交。 |
|||
|
|||
## 测试建议 |
|||
|
|||
- 手工:本地 / 远端各走一遍新建、编辑、删除。 |
|||
- 无需新增自动化测试套件(项目现无前端单测约定);若后续有 component test 基建再补。 |
|||
|
|||
## 实现顺序建议 |
|||
|
|||
1. `urls.ROUTE` |
|||
2. `RouteCard` 操作 UI + emit |
|||
3. TasksView:delete |
|||
4. TasksView:edit open + submit 分支 |
|||
5. 样式微调 |
|||
6. 手工验收 |
|||
Loading…
Reference in new issue