Files
FamilyBook/templates/movies/form.php
T
laoyang ff353b1eee 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/影院三段/照片全量搬
2026-09-30 20:22:46 +08:00

158 lines
6.6 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* 观影表单(新增 / 编辑,一张表单两用 —— 与 people/form 同一思路)。
*
* 字段分三块:看什么(片名/日期/评分/感受)、跟谁(同行的人)、在哪看(影院三段),
* 再加自由文本(简介/观后感/备注)。海报与票根是 free 槽位(v8):
* 不进裁剪器、整图等比缩进框内,所以这里不放裁剪框,只放普通文件控件。
*
* 现场照片只在**新增**时提供多选;编辑时在详情页里逐张补/删 ——
* 一次改一处的表单,比一个巨型表单不容易出错。
*/
$isEdit = !empty($m['id']);
// 回填:校验失败重画时用用户刚提交的值(old()),否则用库里的值
$curAttendees = array_map('intval', array_column($m['attendees'] ?? [], 'id'));
$curFeelings = [];
if (!empty($m['feelings'])) {
$curFeelings = json_decode((string)$m['feelings'], true) ?: [];
}
$selAttendees = array_map('intval', (array)old('attendees', $curAttendees));
$selFeelings = (array)old('feelings', $curFeelings);
$rtVal = old('rating', $m['rating'] ?? '');
?>
<div class="page-head">
<h1><?= $isEdit ? '编辑观影记录' : '记一场电影' ?></h1>
<span class="sub"><?= $isEdit ? e($m['title']) : '片名必填,其他都可以以后再补' ?></span>
</div>
<form method="post" enctype="multipart/form-data"
action="<?= e(url($isEdit ? 'movies/update' : 'movies/create')) ?>">
<?= csrf_field() ?>
<?php if ($isEdit): ?>
<input type="hidden" name="id" value="<?= (int)$m['id'] ?>">
<?php endif; ?>
<div class="card card-pad">
<div class="form-grid">
<div class="field full">
<label for="title">片名 *</label>
<input class="input" id="title" name="title" value="<?= e(old('title', $m['title'] ?? '')) ?>" required>
<?php if (!empty($errors['title'])): ?><span class="err"><?= e($errors['title']) ?></span><?php endif; ?>
</div>
<div class="field">
<label for="starts_at">观影日期</label>
<input class="input" id="starts_at" name="starts_at" type="date"
value="<?= e(old('starts_at', $m['starts_at'] ?? '')) ?>">
</div>
<div class="field">
<label for="rating">评分(1-10)</label>
<select class="select" id="rating" name="rating">
<option value="">不评</option>
<?php for ($i = 10; $i >= 1; $i--): ?>
<option value="<?= $i ?>" <?= (string)$rtVal === (string)$i ? 'selected' : '' ?>><?= $i ?></option>
<?php endfor; ?>
</select>
</div>
<div class="field full">
<label>观后感受</label>
<div class="feel-grid">
<?php foreach (\App\Movie::FEELINGS as $f): ?>
<label class="feel-item">
<input type="checkbox" name="feelings[]" value="<?= e($f) ?>"
<?= in_array($f, $selFeelings, true) ? 'checked' : '' ?>>
<span><?= e($f) ?></span>
</label>
<?php endforeach; ?>
</div>
<span class="tip">MovieLog 里记的英文标签(warm / excited…)搬过来时已经翻成中文。</span>
</div>
<div class="field full">
<label>同行的人</label>
<?php if ($people): ?>
<div class="feel-grid">
<?php foreach ($people as $p): ?>
<label class="feel-item">
<input type="checkbox" name="attendees[]" value="<?= (int)$p['id'] ?>"
<?= in_array((int)$p['id'], $selAttendees, true) ? 'checked' : '' ?>>
<span><?= e($p['shown'] ?? $p['name']) ?></span>
</label>
<?php endforeach; ?>
</div>
<?php else: ?>
<span class="tip">名册里还没有人,先把家人加进名册再来记。</span>
<?php endif; ?>
</div>
<div class="field">
<label for="cinema_place">影院 · 城市/商圈</label>
<input class="input" id="cinema_place" name="cinema_place"
value="<?= e(old('cinema_place', $m['cinema_place'] ?? '')) ?>" placeholder="如:青岛 · 崂山区">
</div>
<div class="field">
<label for="cinema_name">影院 · 名字</label>
<input class="input" id="cinema_name" name="cinema_name"
value="<?= e(old('cinema_name', $m['cinema_name'] ?? '')) ?>" placeholder="如:万达影城 CBD 店">
</div>
<div class="field full">
<label for="cinema_address">影院 · 地址</label>
<input class="input" id="cinema_address" name="cinema_address"
value="<?= e(old('cinema_address', $m['cinema_address'] ?? '')) ?>">
</div>
<div class="field full">
<label for="info">简介</label>
<textarea class="input" id="info" name="info" rows="3"
placeholder="剧情简介(可选)"><?= e(old('info', $m['info'] ?? '')) ?></textarea>
</div>
<div class="field full">
<label for="review">观后感</label>
<textarea class="input" id="review" name="review" rows="4"
placeholder="看完想记下来的话"><?= e(old('review', $m['review'] ?? '')) ?></textarea>
</div>
<div class="field full">
<label for="note">备注</label>
<textarea class="input" id="note" name="note" rows="2"><?= e(old('note', $m['note'] ?? '')) ?></textarea>
</div>
<div class="field">
<label for="poster">海报</label>
<input class="input" id="poster" name="poster" type="file" accept="image/*">
<?php if ($isEdit && !empty($m['poster_key'])): ?>
<span class="tip">已有海报,不选新图就保留原图。</span>
<?php endif; ?>
</div>
<div class="field">
<label for="ticket">票根</label>
<input class="input" id="ticket" name="ticket" type="file" accept="image/*">
<?php if ($isEdit && !empty($m['ticket_key'])): ?>
<span class="tip">已有票根,不选新图就保留原图。</span>
<?php endif; ?>
</div>
<?php if (!$isEdit): ?>
<div class="field full">
<label for="photo">现场照片(可多选)</label>
<input class="input" id="photo" name="photo[]" type="file" accept="image/*" multiple>
<span class="tip">之后也可以在详情页里逐张补传。</span>
</div>
<?php endif; ?>
</div>
<div class="btn-row">
<button type="submit" class="btn"><?= $isEdit ? '保存' : '记下这场电影' ?></button>
<a class="btn btn-ghost"
href="<?= e($isEdit ? url('movies/show', ['id' => (int)$m['id']]) : url('movies')) ?>">取消</a>
</div>
</div>
</form>