Files
FamilyBook/templates/movies/cinemas.php
T
laoyang 4060c18f86 fix(kin,movies): 家谱连线重构为单一网格 + 观影设置统一页头
需求三点:
1. 观影模块「⚙ 设置」与「记一场电影」按钮高度不一致 → 统一页头动作区
   四个选择器的 padding/font-size(.btn 与 .btn-sm 混用是根因);并把设置
   下拉推广到观影全部页面(详情/影院/搜索/统计/报告/表单),落在返回按钮旁。
2. 家谱连线「线乱」→ 根因三条:每代各建一个网格(列宽最小值由内容决定,
   各代不一致,窄屏实测 93.5px vs 164/78/78/78px);落点用百分比算而 grid
   间距不参与百分比;连线行与卡片行不是同一套列。
   改法:整棵树只留一个网格,辈分行/卡片行/连线行全是它的行,连线元素本身
   也是网格项(靠 justify-self 落位);列宽固定为一卡之宽(不用 minmax/1fr,
   否则宽屏卡片中心 ≠ 列中心)。
3. 亲属关系接口改白名单(parent/child/spouse)——原先未知 kind 被静默记成
   配偶,夹具传 kind=sibling 让家谱断言长期拿错数据自证。

设置下拉抽成可复用片段 _settings_menu.php($setCurrent 高亮当前页、
$setCanWrite 控「影院管理」显隐),六七个页头不再各抄一份。

验证:e2e 456/0、桌面几何 268/0、移动端几何 504/0、交互 97/0、
家谱连线诊断 0 失败、静态空跑 exit=0、静态断言证伪 13/13、
反向验证 68/68 全抓住。
2026-10-01 17:42:15 +08:00

143 lines
6.1 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
/**
* 影院管理(v9,MovieLog cinemas.php 同款):上面加/编表单,下面列表。
*
* 颜色用「取色器 + 50 色预设板」两路输入(内联小段 JS 只是取色联动,
* 不依赖 JS 也能手填 hex 或直接用取色器)。删除是 POST 小表单 + confirm;
* 删掉的影院只把关联观影记录的 cinema_id 置空,记录本身不动。
*
* ⚠️ $editing 是路由传进来的「被编辑影院的记录数组」(或 null)。
* 曾经这里写成 `$editing = !empty($editing);` —— 数组被原地变成布尔值,
* 表面看标题还会显示「编辑影院」,但 hidden id 变 0、四个字段全部回填为空,
* 点「编辑」就像没带入一样(v9 线上实测)。布尔化结果必须存进**另一个**变量。
*/
$isEditing = !empty($editing);
$canWrite = \App\Auth::canWrite();
?>
<div class="page-head">
<h1>影院管理</h1>
<span class="sub">共 <?= count($cinemas) ?> 家影院</span>
<div class="actions">
<?php $setCurrent = 'cinemas'; $setCanWrite = $canWrite; require __DIR__ . '/_settings_menu.php'; ?>
<a class="btn btn-ghost" href="<?= e(url('movies')) ?>">返回观影记录</a>
</div>
</div>
<?php if (!$canWrite): ?>
<div class="card card-pad empty"><b>只读账号</b>访客只能查看影院列表。</div>
<?php else: ?>
<div class="card card-pad cinema-form-card">
<h2 class="cinema-h2"><?= $isEditing ? '编辑影院' : '添加影院' ?></h2>
<form method="post" action="<?= e(url('movies/cinemas_save')) ?>">
<?= csrf_field() ?>
<?php if ($isEditing): ?>
<input type="hidden" name="id" value="<?= (int)$editing['id'] ?>">
<?php endif; ?>
<div class="form-grid">
<div class="field">
<label for="cname">影院名称 *</label>
<input class="input" id="cname" name="name" required
value="<?= e(old('name', $editing['name'] ?? '')) ?>" placeholder="如:万达影城(IMAX 店)">
</div>
<div class="field">
<label for="cplace">所在地方</label>
<input class="input" id="cplace" name="place"
value="<?= e(old('place', $editing['place'] ?? '')) ?>" placeholder="如:青岛 · 崂山区">
</div>
<div class="field full">
<label for="caddress">详细地址</label>
<input class="input" id="caddress" name="address"
value="<?= e(old('address', $editing['address'] ?? '')) ?>">
</div>
<div class="field full">
<label for="ccolor">主题颜色</label>
<div class="color-row">
<input type="color" id="ccolor" name="color" class="color-picker"
value="<?= e(old('color', $editing['color'] ?? '#888888')) ?>">
<span class="color-hex" id="colorHex"><?= e(old('color', $editing['color'] ?? '#888888')) ?></span>
<span class="preset-palette">
<?php foreach (\App\Cinema::PRESET_COLORS as $pc): ?>
<span class="preset-color" data-color="<?= $pc ?>" style="background: <?= $pc ?>;" title="<?= $pc ?>"></span>
<?php endforeach; ?>
</span>
</div>
</div>
</div>
<div class="btn-row">
<button type="submit" class="btn"><?= $isEditing ? '保存' : '添加影院' ?></button>
<?php if ($isEditing): ?>
<a class="btn btn-ghost" href="<?= e(url('movies/cinemas')) ?>">取消编辑</a>
<?php endif; ?>
</div>
</form>
</div>
<?php endif; ?>
<div class="card card-pad">
<h2 class="cinema-h2">影院列表</h2>
<?php if (!$cinemas): ?>
<p class="empty-hint">还没有影院,先在上面添加一家。</p>
<?php else: ?>
<div class="table-wrap">
<table class="table">
<thead>
<tr><th>名称</th><th>所在地方</th><th>详细地址</th><th>观影</th><?php if ($canWrite): ?><th>操作</th><?php endif; ?></tr>
</thead>
<tbody>
<?php foreach ($cinemas as $c): ?>
<tr>
<td>
<span class="color-preview" style="background: <?= e((string)($c['color'] ?: '#888888')) ?>;"></span>
<b><?= e($c['name']) ?></b>
</td>
<td><?= e((string)($c['place'] ?? '')) !== '' ? e($c['place']) : '—' ?></td>
<td><?= !empty($c['address']) ? e($c['address']) : '—' ?></td>
<td><?= (int)$c['movie_count'] ?> 场</td>
<?php if ($canWrite): ?>
<td>
<div class="actions">
<a class="btn btn-ghost btn-sm" href="<?= e(url('movies/cinemas', ['edit' => (int)$c['id']])) ?>">编辑</a>
<form method="post" action="<?= e(url('movies/cinemas_del')) ?>"
onsubmit="return confirm('确定删除「<?= e($c['name']) ?>」吗?关联观影记录的影院信息将置空。')">
<?= csrf_field() ?>
<input type="hidden" name="id" value="<?= (int)$c['id'] ?>">
<button type="submit" class="btn btn-danger btn-sm">删除</button>
</form>
</div>
</td>
<?php endif; ?>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
</div>
<?php if ($canWrite): ?>
<script>
(function () {
var picker = document.getElementById('ccolor');
var hex = document.getElementById('colorHex');
if (!picker || !hex) return;
function setActive(color) {
Array.prototype.forEach.call(document.querySelectorAll('.preset-color'), function (el) {
el.classList.toggle('active', el.getAttribute('data-color') === color);
});
}
picker.addEventListener('input', function () {
hex.textContent = picker.value;
setActive(picker.value);
});
Array.prototype.forEach.call(document.querySelectorAll('.preset-color'), function (el) {
el.addEventListener('click', function () {
picker.value = el.getAttribute('data-color');
hex.textContent = picker.value;
setActive(picker.value);
});
});
setActive(picker.value);
})();
</script>
<?php endif; ?>