v8:观影落地(MovieLog 整体迁入统一事件原语)+ 三处 UI 撤除
- Schema v8:events / movie_details / event_attendees / event_photos 四张表, uk_event_source(family_id, source_ref) 作迁移幂等锚 - Movie 模型:时间线/详情/增删改、同行人整组替换、照片逐张管理、感受英→中映射 - ImageSlot 新增 poster(2:3) / ticket(free) / photo(free) 三槽位; free 槽位不裁剪、整图等比缩进框(只缩不放大) - OssDriver::copyObject:同桶 CopyObject(手写 V1 签名,x-oss-* 头按字典序进签名串) - 路由:movies 时间线/详情/新增/编辑/删除/补照片/删照片;同行人按家庭过滤; 访客只读(requireWrite) - UI 撤除:首页「我的一句话」、家谱页「补充我的亲属关系 / 看整个名册」两个按钮; 顶栏加「观影」入口 - 修潜伏 bug:ImageSlot::parseRatio 的正则用 / 作分隔符,字符类里的 / 把模式 提前截断(Unknown modifier ']')—— ratio() 只在上传 POST 里被调到,一直没被观察到 - 线上数据迁移(临时 token 门禁页,用完即删):MovieLog 219 条观影 → events, 14 位观影人新增进名册(带 MovieLog 头像),431 个 OSS 对象同桶拷贝 (movielog/uploads/<dir>/x → family/<dir>/x),review/feelings/影院三段/照片全量搬
This commit is contained in:
+39
-4
@@ -41,7 +41,34 @@ final class ImageSlot
|
||||
'dir' => 'avatars',
|
||||
'hint' => '正方形。页面上显示成圆形或圆角方形,所以按 1:1 裁。',
|
||||
],
|
||||
// 题图按 16:9 —— 宽屏横幅。现在还没有位置用它,需要时把它启用即可:
|
||||
// v8 观影三槽位。海报是竖版的(豆瓣海报约 2:3)→ 裁剪;
|
||||
// 票根/现场照片是随手拍、比例五花八门 → ratio='free':**不裁剪**,
|
||||
// 等比缩到框内(w×h 是「最长边」而不是固定输出尺寸),服务端保证不变形。
|
||||
'poster' => [
|
||||
'label' => '海报',
|
||||
'ratio' => '2:3',
|
||||
'w' => 600,
|
||||
'h' => 900,
|
||||
'dir' => 'posters',
|
||||
'hint' => '竖版海报,按 2:3 裁。没裁就按整图居中取。',
|
||||
],
|
||||
'ticket' => [
|
||||
'label' => '票根',
|
||||
'ratio' => 'free',
|
||||
'w' => 1400,
|
||||
'h' => 1400,
|
||||
'dir' => 'tickets',
|
||||
'hint' => '票根不裁剪,等比缩到最长边 1400。',
|
||||
],
|
||||
'photo' => [
|
||||
'label' => '照片',
|
||||
'ratio' => 'free',
|
||||
'w' => 1600,
|
||||
'h' => 1600,
|
||||
'dir' => 'photos',
|
||||
'hint' => '现场照片不裁剪,等比缩到最长边 1600。',
|
||||
],
|
||||
// 题图按 16:9 —— 宽屏横幅。需要时把它启用即可:
|
||||
// 'cover' => ['label' => '题图', 'ratio' => '16:9', 'w' => 1920, 'h' => 1080,
|
||||
// 'dir' => 'covers', 'hint' => '宽屏横幅,显示在详情页顶部。'],
|
||||
];
|
||||
@@ -57,16 +84,22 @@ final class ImageSlot
|
||||
return self::SLOTS[$key] ?? null;
|
||||
}
|
||||
|
||||
/** 宽高比(宽 / 高)。'1:1' → 1.0,'16:9' → 1.777… */
|
||||
/** 宽高比(宽 / 高)。'1:1' → 1.0,'16:9' → 1.777…,'free' → 0.0(不锁比例、不裁剪) */
|
||||
public static function ratio(array $slot): float
|
||||
{
|
||||
if (($slot['ratio'] ?? '') === 'free') {
|
||||
return 0.0;
|
||||
}
|
||||
[$a, $b] = self::parseRatio((string)($slot['ratio'] ?? '1:1'));
|
||||
return $b > 0 ? $a / $b : 1.0;
|
||||
}
|
||||
|
||||
/** 给前端用的 CSS aspect-ratio 写法:'1 / 1'、'16 / 9' */
|
||||
/** 给前端用的 CSS aspect-ratio 写法:'1 / 1'、'16 / 9';free 槽位返回空串(前端不进裁剪器) */
|
||||
public static function ratioCss(array $slot): string
|
||||
{
|
||||
if (($slot['ratio'] ?? '') === 'free') {
|
||||
return '';
|
||||
}
|
||||
[$a, $b] = self::parseRatio((string)($slot['ratio'] ?? '1:1'));
|
||||
return $a . ' / ' . $b;
|
||||
}
|
||||
@@ -74,7 +107,9 @@ final class ImageSlot
|
||||
/** @return array{0:int,1:int} */
|
||||
private static function parseRatio(string $ratio): array
|
||||
{
|
||||
if (preg_match('/^\s*(\d+)\s*[:/]\s*(\d+)\s*$/', $ratio, $m)) {
|
||||
// ⚠️ 分隔符别用 /:'[:/]' 里的斜杠会把模式提前截断("Unknown modifier ']'"),
|
||||
// 这个潜伏 bug 一直没炸是因为 ratio() 只在上传 POST 里被调到(302 正文没人扫)。
|
||||
if (preg_match('#^\s*(\d+)\s*[:/]\s*(\d+)\s*$#', $ratio, $m)) {
|
||||
$a = max(1, (int)$m[1]);
|
||||
$b = max(1, (int)$m[2]);
|
||||
return [$a, $b];
|
||||
|
||||
Reference in New Issue
Block a user