票根并入观影照片:端上不再「票根另算」(#87)
用户:现在不是已经没有票根的概念了吗?全部都换成观影照片了。
现在只分两类:一类是海报,一类是观影照片。
数据层已迁移(服务端 #87):220 条 ticket_key 搬进 event_photos,
旧字段置 NULL,Movie::find 也不再返回它。
端上跟着收:
- allPhotos() 不再把 ticketKey 拼进列表,直接 return d.photos.slice();
原来那段还特意给它 id=0("删不掉"的标记),现在没这个特殊项了;
- FbMovieRepo 不再写/解析 ticket_key(本地列留着不改 schema,
但恒为空串,字段标 @deprecated);
- FbSyncAll 收附件时 SQL 去掉 ticket_key(票根的 key 会在
module_cache.payload 递归扫描里被收进来,不丢附件)。
⚠️ 特别注意 allPhotos 里**不留** ticketKey 兜底分支:留着就等于承认
还有第三类,而那正是用户要消灭的东西。若线上还有残留(迁移漏跑),
症状是"某些老记录照片变少",应该去补跑迁移,不是在这里兜。
hvigorw assembleHap BUILD SUCCESSFUL。真机验证待做(当时手机锁屏)。
This commit is contained in:
@@ -103,29 +103,24 @@ export struct FbMovieDetailSheet {
|
|||||||
@Local viewerVideoError: boolean = false;
|
@Local viewerVideoError: boolean = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 详情里所有可看的图:**票根在前 + 现场照片**。
|
* 详情里所有可看的图 = `event_photos` 全量(**票根已经并进来了**)。
|
||||||
*
|
*
|
||||||
* ⚠️ 与 Web 端口径一致(`templates/movies/show.php` 把票根和照片
|
* 🔴 2026-11-06(用户):「现在不是已经没有票根的概念了吗?全部都换成
|
||||||
* "合成一块展示、同一套灯箱",注释里写明了不再分类)。
|
* 观影照片了。别管是票根还是观影照片,都在一起。现在只分两类:
|
||||||
* 端上也别分类 —— 用户关心的是"这次观影的照片",不是它的来源。
|
* 一类是海报,一类是观影照片。海报是来自豆瓣的,这个不用管它,
|
||||||
|
* 主要就是观影照片,所有的都在观影照片里边。」
|
||||||
|
*
|
||||||
|
* ⇒ 数据层已经做过一次性迁移:`movie_details.ticket_key` 里的旧票根
|
||||||
|
* 逐条搬进了 `event_photos`(220 条,position 排在最前),
|
||||||
|
* 旧字段置 NULL。所以这里**不再需要**"票根另算"那段逻辑 ——
|
||||||
|
* 它现在就是一条普通照片,有 id、能滑、能删。
|
||||||
|
*
|
||||||
|
* ⚠️ 留 `d.ticketKey` 的兜底分支?**不留**。留着就等于承认还有第三类,
|
||||||
|
* 而这正是用户要消灭的东西。若线上还有残留(迁移漏跑),
|
||||||
|
* 症状是"某些老记录照片变少了" —— 那应该去补跑迁移,不是在这里兜。
|
||||||
*/
|
*/
|
||||||
private allPhotos(d: FbMovieDetail): FbMovieMedia[] {
|
private allPhotos(d: FbMovieDetail): FbMovieMedia[] {
|
||||||
const out: FbMovieMedia[] = [];
|
return d.photos.slice();
|
||||||
/* 票根:历史数据里它就是一张图(`ticket_key` 单独存在 movie_details),
|
|
||||||
这里归并进同一个列表 —— 与网页端"合成一块展示"同口径。
|
|
||||||
⚠️ 票根永远是图片,不会是视频。 */
|
|
||||||
if (d.ticketKey !== '') {
|
|
||||||
/* ⚠️ `id` 给 0:票根存在 `movie_details.ticket_key` 上,**不是**
|
|
||||||
`event_photos` 的行,没有照片 id。查看器只用 id 来标"第几项",
|
|
||||||
0 不影响显示;但编辑表单里"删这张"是按 id 调的,
|
|
||||||
所以票根那边(表单的 `existingPhotos`)本来也不含票根。
|
|
||||||
—— 删票根请用「换海报/票根」入口,不在照片列表里删。 */
|
|
||||||
out.push({ id: 0, key: d.ticketKey, kind: 'image', thumb: '', mime: '' });
|
|
||||||
}
|
|
||||||
for (const m of d.photos) {
|
|
||||||
out.push(m);
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -689,7 +684,7 @@ export struct FbMovieDetailSheet {
|
|||||||
.alignItems(HorizontalAlign.Start)
|
.alignItems(HorizontalAlign.Start)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- 照片(票根 + 现场照片合成一块,与 Web 端一致)----
|
// ---- 观影照片(**只此一类**:票根已并入 event_photos)----
|
||||||
if (this.allPhotos(d).length > 0) {
|
if (this.allPhotos(d).length > 0) {
|
||||||
Column({ space: 6 }) {
|
Column({ space: 6 }) {
|
||||||
/* 同样按《全局表单规范》:主题色 + Bold + fontSmall。
|
/* 同样按《全局表单规范》:主题色 + Bold + fontSmall。
|
||||||
|
|||||||
@@ -234,7 +234,8 @@ export struct FbMovieNewSheet {
|
|||||||
⚠️ 别塞进 doubanPosterKey —— 那个会被 PATCH 带上去,
|
⚠️ 别塞进 doubanPosterKey —— 那个会被 PATCH 带上去,
|
||||||
虽然值相同不出错,但语义就乱了,后人容易改错。 */
|
虽然值相同不出错,但语义就乱了,后人容易改错。 */
|
||||||
this.existingPosterKey = d.posterKey;
|
this.existingPosterKey = d.posterKey;
|
||||||
/* 已有观影照片(票根另算,它是 movie_details.ticket_key,不在这里) */
|
/* 已有观影照片。2026-11-06 起**票根也在这里**了 —— 它已经迁进
|
||||||
|
`event_photos`,与现场照片同一类,可看可删。 */
|
||||||
this.existingPhotos = d.photos.slice();
|
this.existingPhotos = d.photos.slice();
|
||||||
const ids: number[] = [];
|
const ids: number[] = [];
|
||||||
/* ⚠️ 必须显式标类型(`arkts-no-any-unknown`):
|
/* ⚠️ 必须显式标类型(`arkts-no-any-unknown`):
|
||||||
@@ -1333,7 +1334,7 @@ export struct FbMovieNewSheet {
|
|||||||
Row({ space: 8 }) {
|
Row({ space: 8 }) {
|
||||||
Text(this.photoUris.length > 0
|
Text(this.photoUris.length > 0
|
||||||
? ('已新选 ' + this.photoUris.length.toString() + ' 张')
|
? ('已新选 ' + this.photoUris.length.toString() + ' 张')
|
||||||
: '票根、合影、随手拍都可以放这儿')
|
: '合影、票根、随手拍都可以放这儿')
|
||||||
.fontSize(FbMetric.fontSmall)
|
.fontSize(FbMetric.fontSmall)
|
||||||
.fontColor(this.photoUris.length > 0 ? FbColors.ink : FbColors.muted)
|
.fontColor(this.photoUris.length > 0 ? FbColors.ink : FbColors.muted)
|
||||||
.maxLines(1)
|
.maxLines(1)
|
||||||
|
|||||||
@@ -272,7 +272,11 @@ export interface FbMovieDetail {
|
|||||||
/** 剧情简介(movie_details.info) */
|
/** 剧情简介(movie_details.info) */
|
||||||
info: string;
|
info: string;
|
||||||
posterKey: string;
|
posterKey: string;
|
||||||
/** 票根图(movie_details.ticket_key) */
|
/**
|
||||||
|
* @deprecated 2026-11-06:票根概念取消,已并入 `photos`(`event_photos`)。
|
||||||
|
* 「只分两类:海报 / 观影照片」。字段留着只为不动本地库 schema,
|
||||||
|
* **恒为空串**,任何新代码都不要再读它。
|
||||||
|
*/
|
||||||
ticketKey: string;
|
ticketKey: string;
|
||||||
cinemaName: string;
|
cinemaName: string;
|
||||||
cinemaPlace: string;
|
cinemaPlace: string;
|
||||||
@@ -618,7 +622,10 @@ export class FbMovieRepo {
|
|||||||
b['event_id'] = m.id;
|
b['event_id'] = m.id;
|
||||||
b['info'] = m.movieInfo;
|
b['info'] = m.movieInfo;
|
||||||
b['poster_key'] = m.posterKey;
|
b['poster_key'] = m.posterKey;
|
||||||
b['ticket_key'] = m.ticketKey;
|
/* 🔴 2026-11-06:`ticket_key` **不再写入**(票根已并入 `event_photos`,
|
||||||
|
服务端也置 NULL 且不再 SELECT 它)。本地列留着(改 schema 要迁移,
|
||||||
|
收益为零),但恒为 NULL —— 写入空串会让"死列里有值"看着像还有票根。 */
|
||||||
|
b['ticket_key'] = '';
|
||||||
b['cinema_id'] = cinemaId;
|
b['cinema_id'] = cinemaId;
|
||||||
b['douban_meta'] = m.doubanMeta;
|
b['douban_meta'] = m.doubanMeta;
|
||||||
b['updated_at'] = m.updatedAt;
|
b['updated_at'] = m.updatedAt;
|
||||||
@@ -1684,7 +1691,8 @@ function parseDetail(id: number, json: string): FbMovieDetail {
|
|||||||
note: strOf(o.note),
|
note: strOf(o.note),
|
||||||
info: strOf(o.info),
|
info: strOf(o.info),
|
||||||
posterKey: strOf(o.poster_key),
|
posterKey: strOf(o.poster_key),
|
||||||
ticketKey: strOf(o.ticket_key),
|
/* 2026-11-06:票根并入 photos,不再解析 ticket_key(服务端也不返回了) */
|
||||||
|
ticketKey: '',
|
||||||
cinemaName: strOf(o.cinema_name),
|
cinemaName: strOf(o.cinema_name),
|
||||||
cinemaPlace: strOf(o.cinema_place),
|
cinemaPlace: strOf(o.cinema_place),
|
||||||
cinemaAddress: strOf(o.cinema_address),
|
cinemaAddress: strOf(o.cinema_address),
|
||||||
|
|||||||
@@ -429,7 +429,8 @@ async function pingReachable(): Promise<boolean> {
|
|||||||
*
|
*
|
||||||
* 来源三处(都在本地,不额外发请求):
|
* 来源三处(都在本地,不额外发请求):
|
||||||
* · `module_cache.payload` —— 9 个模块的完整 JSON(递归扫,见 `FbAttachQueue.collectFromJson`);
|
* · `module_cache.payload` —— 9 个模块的完整 JSON(递归扫,见 `FbAttachQueue.collectFromJson`);
|
||||||
* · `movie_details.poster_key` / `ticket_key` —— 海报与票根;
|
* · `movie_details.poster_key` —— 海报(票根已并入 event_photos,
|
||||||
|
* 它的 key 会在上面那条 `module_cache.payload` 递归扫描里被收进来);
|
||||||
* · `persons.avatar` —— 名册头像。
|
* · `persons.avatar` —— 名册头像。
|
||||||
*/
|
*/
|
||||||
async function collectAttachKeys(): Promise<void> {
|
async function collectAttachKeys(): Promise<void> {
|
||||||
@@ -444,18 +445,13 @@ async function collectAttachKeys(): Promise<void> {
|
|||||||
FB_ATTACH.collectFromJson(r.strOr('payload', ''), keys);
|
FB_ATTACH.collectFromJson(r.strOr('payload', ''), keys);
|
||||||
}
|
}
|
||||||
const posters: FbRow[] = await db.queryRows(
|
const posters: FbRow[] = await db.queryRows(
|
||||||
"SELECT poster_key, ticket_key FROM movie_details "
|
"SELECT poster_key FROM movie_details "
|
||||||
+ "WHERE (poster_key IS NOT NULL AND poster_key <> '') "
|
+ "WHERE poster_key IS NOT NULL AND poster_key <> ''");
|
||||||
+ " OR (ticket_key IS NOT NULL AND ticket_key <> '')");
|
|
||||||
for (const r of posters) {
|
for (const r of posters) {
|
||||||
const p: string = r.strOr('poster_key', '');
|
const p: string = r.strOr('poster_key', '');
|
||||||
const t: string = r.strOr('ticket_key', '');
|
|
||||||
if (p !== '') {
|
if (p !== '') {
|
||||||
keys.push(p);
|
keys.push(p);
|
||||||
}
|
}
|
||||||
if (t !== '') {
|
|
||||||
keys.push(t);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const avatars: FbRow[] = await db.queryRows(
|
const avatars: FbRow[] = await db.queryRows(
|
||||||
"SELECT avatar FROM persons WHERE avatar IS NOT NULL AND avatar <> ''");
|
"SELECT avatar FROM persons WHERE avatar IS NOT NULL AND avatar <> ''");
|
||||||
|
|||||||
Reference in New Issue
Block a user