v66 续:旅程三项设置(车辆管理 / 出行方式 / 节点类型)

用户 2026-10-20:「旅程的……车辆管理、出行方式、节点设置,这些东西都还没完成。」
这三项的 `action` 一直是**空串**(点了没反应),是本次批量需求里最后一块。

三项的真实能力并不一样,按真实情况做,不摆假入口:
· **车辆管理**:`vehicles` 表 + `Vehicle::save/destroy` 早就有,缺的只是 API
  ⇒ 新增 `GET/POST/PATCH/DELETE /api/v1/vehicles`;端上列表 + 内嵌表单
  (车型 / 车牌 / 自家·租的·借的 / 车主或租车公司 / 订单号 / 默认车 / 备注)
· **节点类型**:`node_types` 表 + `NodeType::save/destroy` 同理
  ⇒ 新增 `GET/POST/PATCH/DELETE /api/v1/nodetypes`;改名会**级联**到已有行程
  (`trip_nodes.node_type` 存的是名字,服务端 `NodeType::save` 里做)
  · 内置类型**不画删除按钮**(服务端会拒,画了就是"点了没反应")
· **出行方式**:**枚举常量**(`Trip::TRAVEL_MODES`),没有"管理"这回事
  ⇒ 只做一份只读对照表 + "加行程时选",**不做可编辑表单**
  (反向验证里有一条专门锁"这个浮层里不许出现保存/删除")

几个实现上的要点:
· 两条新路由是**平级资源**(`/vehicles`、`/nodetypes`),不是 `trips/xxx` 子路由 ——
  `Api::dispatch()` 只解析三段,写成四段会落到「trips 的第 0 条」= 列表
· 删不掉(还有 N 段行程在用 / 内置类型)回 **422 + 服务端原话**,不是 500:
  那是"现在不能删",不是"服务器出错"
· 表单输入框**不按值传 value**:`@Builder` 的值参数不参与状态观察,
  而这个浮层是"列表 + 内嵌表单"(点另一行的「编辑」时表单已经渲染着)
  ⇒ 会显示上一辆车的内容。改成传 key、builder 内部直接读 `this.fXxx`
· 三个浮层都遵守浮层铁律(根 `Stack` 叠放 + `hitTestBehavior(Transparent)`),
  各挂一个 `@Monitor` 让底部悬浮栏让位;`backOnce()` 按层级顺序关

服务端(`app/ApiHandler.php`)已随 `familybook_push.sh` 部署,线上核对:
`/api/v1/ping` 的 features 里 `trips_vehicles` / `trips_nodetypes` 均为 1,
两个端点无令牌时回 **401 unauthorized**(说明路由存在,而不是 404 not_found)。

验证:`hvigorw assembleHap` BUILD SUCCESSFUL;静态守卫 769 条全绿;
反向验证 116 条注入全部能让守卫变红(含"字段名拼错""按值传 value"等假绿陷阱)。
⚠️ 设备仍断连,真机未验收。
This commit is contained in:
2026-10-20 16:36:30 +08:00
parent b3e1330244
commit 58f5509c1c
5 changed files with 1198 additions and 5 deletions
+90 -2
View File
@@ -31,6 +31,8 @@ import { FB_TOKEN_STORE } from '../../data/FbTokenStore';
import { fetchTripNodes } from '../../data/FbTripRepo';
import { FbTripNewSheet } from '../../components/FbTripNewSheet';
import { FbTripNodeSheet } from '../../components/FbTripNodeSheet';
/* v66:旅程三项设置(车辆 / 出行方式 / 节点类型) */
import { FbNodeTypeSheet, FbTravelModesSheet, FbVehicleSheet } from '../../components/FbTripsSettingsSheets';
@ComponentV2
export struct FbTripsPage {
@@ -94,6 +96,15 @@ export struct FbTripsPage {
/** 「加一段行程」浮层是否打开,以及它属于哪一趟旅程(0 = 关着) */
@Local nodeSheetTripId: number = 0;
/**
* 🔴 v66(用户 2026-10-20):「旅程的……车辆管理、出行方式、节点设置,
* 这些东西都还没完成。」
* 三项设置各管一个开关(同时只会开一个 —— 设置菜单点一项就关菜单再开它)。
*/
@Local vehiclesOpen: boolean = false;
@Local travelModesOpen: boolean = false;
@Local nodeTypesOpen: boolean = false;
/**
* 页面出现:先缓存、再网络(与观影/名册同一套"本地优先"流程)。
*
@@ -117,6 +128,20 @@ export struct FbTripsPage {
this.nodeSheetTripId = 0;
return true;
}
/* v66:三项设置浮层。⚠️ 内部还有"表单展开 / 待确认删除"两层,
按返回先由浮层自己处理(组件的遮罩 onClick 也会关)—— 这里只负责关整层。 */
if (this.vehiclesOpen) {
this.vehiclesOpen = false;
return true;
}
if (this.travelModesOpen) {
this.travelModesOpen = false;
return true;
}
if (this.nodeTypesOpen) {
this.nodeTypesOpen = false;
return true;
}
if (this.newOpen) {
this.newOpen = false;
return true;
@@ -178,6 +203,28 @@ export struct FbTripsPage {
fbAppState().sheetCount = this.nodeSheetTripId > 0 ? 1 : 0;
}
/**
* 三个设置浮层同样要让悬浮栏让位。
*
* ⚠️ 三个 `@Monitor` 各写一个(V2 里一个 `@Monitor` 只能盯一个变量);
* 它们**不会同时为真**(设置菜单点一项就关菜单、只开一个浮层),
* 所以每次都直接赋值即可 —— 不用"有几个开着就加几"。
*/
@Monitor('vehiclesOpen')
onVehiclesChanged(): void {
fbAppState().sheetCount = this.vehiclesOpen ? 1 : 0;
}
@Monitor('travelModesOpen')
onTravelModesChanged(): void {
fbAppState().sheetCount = this.travelModesOpen ? 1 : 0;
}
@Monitor('nodeTypesOpen')
onNodeTypesChanged(): void {
fbAppState().sheetCount = this.nodeTypesOpen ? 1 : 0;
}
build() {
// 🔴 外层 Stack:**模块设置浮层**要浮在页面之上
// (本页原来是 Scroll 直接作根,没有 Stack,这里补一层)
@@ -282,8 +329,18 @@ export struct FbTripsPage {
this.settingsOpen = false;
},
onPick: (action: string): void => {
// 条目里 `action === ''` 的是「暂未开放」(组件里已画灰、点了不响应)
// ⇒ 这里只需处理已实现的;目前都还没有,保持浮层开着即可。
/* 🔴 v66:三项设置终于接上了(原来这里的注释写着"目前都还没有")。
⚠️ 先关设置菜单再开目标浮层:两个浮层叠在一起时,
`sheetCount` 会被后赋值的那个覆盖,悬浮栏让位就乱了。
(本页每个 @Monitor 都是"直接赋值",不是累加。) */
this.settingsOpen = false;
if (action === 'vehicles') {
this.vehiclesOpen = true;
} else if (action === 'travelmodes') {
this.travelModesOpen = true;
} else if (action === 'nodetypes') {
this.nodeTypesOpen = true;
}
}
})
.transition(fbSheetTransition())
@@ -327,6 +384,37 @@ export struct FbTripsPage {
})
.transition(fbSheetTransition())
}
// ---- 旅程三项设置浮层(v66)----
if (this.vehiclesOpen) {
FbVehicleSheet({
accent: this.accent,
onClose: (): void => {
this.vehiclesOpen = false;
}
})
.transition(fbSheetTransition())
}
if (this.travelModesOpen) {
FbTravelModesSheet({
accent: this.accent,
onClose: (): void => {
this.travelModesOpen = false;
}
})
.transition(fbSheetTransition())
}
if (this.nodeTypesOpen) {
FbNodeTypeSheet({
accent: this.accent,
onClose: (): void => {
this.nodeTypesOpen = false;
}
})
.transition(fbSheetTransition())
}
}
.width('100%')
.height('100%')