v76 旅程:信息铺得开 + 每段行程各自成卡 + 照片可点开 / 视频可播
用户 2026-10-22(四条毛病,同一个根因:信息往一行里挤):
「那个城市……如果一行显不下的话,应该显示在下边一行,把所有的城市全列出来。
就跟那个人员一样,你人员特别多的时候,一行显示不下,就直接往下放就行了。」
「点进详情之后……现在人员显示不下的话,你直接都放在右边,都溢出到这个块外面去了……
应该直接顺着往下铺就行了,所以它长一点无所谓。」
「实际行程它应该也是一段一段的,不要把它整个实际行程放在一块,
就是每一个行程都是一个一个块。然后里面的照片要可以点击查看,视频要能够播放。」
根因不是"忘了加滚动",而是 **`Row` 在 ArkUI 里不换行**:
塞不下的子节点会被压缩、或直接横向溢出父容器。四处都改成
`Flex({ wrap: FlexWrap.Wrap })`。
- `Types.ets`:`FbTripItem` 新增 `cities: string[]`(整串只能截断);
`FbTripNodePhoto` 新增 `mime` / `size`
- `FbParse.parseTrips` 新增 `cityListOf()`:优先用服务端 `cities` 数组,
只给整串时按 `·` 拆回来("显示不全"不再从别的入口漏进来)
- 列表卡:城市从「📍 一行长串 + 省略号」改成一颗颗 chip,日期单独占一行
- 详情页:城市 / 参与的人 / 每段的参与人 全部改 `Flex wrap`
(实测「黑龙江」那趟 5 个人自动排成 2 行,不再溢出卡片)
- **每段行程各自一张卡**:组头退成章节标题(不带卡片底),
`nodeCard` 自己带白底 + 圆角 + 左侧阶段色条(取 `n.stage`)
- 照片:点缩略图开全屏查看器(`PanGesture` 左右滑、上一张/下一张、关闭)
- 视频:按 `mime` 前缀认出视频(`is_image` 只有两态),缩略块 + ▶ 角标,
点开用系统 `Video` 播放(`media.php` 支持 Range,可拖进度条)
🔴 真机抓到的布局 bug:`Stack` 子节点上的 `.align(Alignment.Bottom/TopEnd)`
**完全无效** —— 关闭按钮和翻页条双双掉到屏幕正中。改成铺满的 Column +
`layoutWeight(1)` 撑开,并给控制层 `hitTestBehavior(Transparent)`
保证"点背景关闭"仍穿透。
验证:真机 33/0(含"城市 chip 数 == 统计里个城市"、"相邻行程卡有实际间隙"、
"点视频块起播放器且无放不出来");守卫 953/0;反向验证 181/0
(其中一条注入暴露了我新写断言的假绿,已改成结构化顺序判据)。
This commit is contained in:
@@ -271,7 +271,7 @@ export function parseTrips(json: string): FbTripItem[] {
|
||||
const rows: RawTrip[] = asArray<RawTrip>(json);
|
||||
const out: FbTripItem[] = [];
|
||||
for (const r of rows) {
|
||||
const cities: string[] = arr<string>(r.cities);
|
||||
const cities: string[] = cityListOf(r);
|
||||
const dayCount: number = daySpan(s(r.starts_at), s(r.ends_at));
|
||||
const it: FbTripItem = {
|
||||
id: n(r.id),
|
||||
@@ -285,6 +285,7 @@ export function parseTrips(json: string): FbTripItem[] {
|
||||
⚠️ `cover_key` 存**原始键**,拼地址交给 `fbMediaUrl()`(见 FbTripItem 的说明)。 */
|
||||
coverKey: s(r.cover_key),
|
||||
city: s(r.city) !== '' ? s(r.city) : cities.join(' · '),
|
||||
cities: cities,
|
||||
summary: s(r.summary),
|
||||
attendeeCount: n(r.attendee_count),
|
||||
};
|
||||
@@ -293,6 +294,43 @@ export function parseTrips(json: string): FbTripItem[] {
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* 城市的**列表**(卡片上一颗颗 chip 换行用)。
|
||||
*
|
||||
* 🔴 v76(用户 2026-10-22):「如果一行显不下的话,应该显示在下边一行,
|
||||
* 把所有的城市全列出来。」
|
||||
* ⇒ 端上必须要数组,不能只有一个 `city` 整串 —— 整串只能截断。
|
||||
*
|
||||
* ⚠️ 服务端 `Trip::peek()` 同时给 `cities`(数组,`Trip::cities()` 的原值)
|
||||
* 与 `city`(`implode(' · ', $cities)`)。**优先用数组**;
|
||||
* 万一将来某条接口只给整串(老版本 / 单条接口),按同一个分隔符拆回来,
|
||||
* 这样"显示不全"这个毛病不会再从别的入口漏进来。
|
||||
*/
|
||||
function cityListOf(r: RawTrip): string[] {
|
||||
const arr0: string[] = arr<string>(r.cities);
|
||||
const out: string[] = [];
|
||||
for (const c of arr0) {
|
||||
const t: string = c.trim();
|
||||
if (t !== '' && out.indexOf(t) < 0) {
|
||||
out.push(t);
|
||||
}
|
||||
}
|
||||
if (out.length > 0) {
|
||||
return out;
|
||||
}
|
||||
const whole: string = s(r.city);
|
||||
if (whole === '') {
|
||||
return out;
|
||||
}
|
||||
for (const p of whole.split('·')) {
|
||||
const t: string = p.trim();
|
||||
if (t !== '' && out.indexOf(t) < 0) {
|
||||
out.push(t);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/** 纪念日 → FbAnniversaryItem */
|
||||
export function parseDays(json: string): FbAnniversaryItem[] {
|
||||
const rows: RawDay[] = asArray<RawDay>(json);
|
||||
|
||||
Reference in New Issue
Block a user