v10: 修影院编辑回填布尔化 bug;评分改 10 星制;观影人改弹窗+拼音首字母联想;豆瓣自动补充迁移(movie_details.douban_meta,schema v10)
This commit is contained in:
@@ -10,6 +10,14 @@
|
||||
$canWrite = \App\Auth::canWrite();
|
||||
$hasPoster = !empty($m['poster_key']);
|
||||
$hasTicket = !empty($m['ticket_key']);
|
||||
// 豆瓣元数据(v10):整体 JSON 存 douban_meta,随用随解;解不开就当没有
|
||||
$doubanMeta = [];
|
||||
if (!empty($m['douban_meta'])) {
|
||||
$decoded = json_decode((string)$m['douban_meta'], true);
|
||||
if (is_array($decoded)) {
|
||||
$doubanMeta = $decoded;
|
||||
}
|
||||
}
|
||||
$watchTxt = \App\Movie::formatWatch($m['starts_at'], $m['ends_at'] ?? null);
|
||||
$fmtNum = static function ($v): string {
|
||||
if ($v === null) {
|
||||
@@ -57,6 +65,16 @@ $feelTags = static function (array $keys) use ($feelCat) {
|
||||
<?php return ob_get_clean();
|
||||
};
|
||||
|
||||
/** 静态 10 星展示(v10):左 n 颗实心金黄,其余空心灰;n 越界按 0/10 兜底 */
|
||||
$starsHtml = static function (int $n): string {
|
||||
$n = max(0, min(10, $n));
|
||||
$out = '<span class="stars-disp" aria-hidden="true">';
|
||||
for ($i = 1; $i <= 10; $i++) {
|
||||
$out .= '<span class="' . ($i <= $n ? 'd-on' : 'd-off') . '">' . ($i <= $n ? '★' : '☆') . '</span>';
|
||||
}
|
||||
return $out . '</span>';
|
||||
};
|
||||
|
||||
/** 我的评价表单(打分 + 正文 + 感受),details 按需展开;写评价与修改共用这一份 */
|
||||
$rvForm = static function (string $summary, bool $open) use ($m, $myReview, $feelPick, $rvError) {
|
||||
ob_start(); ?>
|
||||
@@ -67,12 +85,14 @@ $rvForm = static function (string $summary, bool $open) use ($m, $myReview, $fee
|
||||
<input type="hidden" name="id" value="<?= (int)$m['id'] ?>">
|
||||
<div class="rv-rating-row">
|
||||
<span class="rv-rating-label">我的评分</span>
|
||||
<span class="rv-scale" role="radiogroup" aria-label="评分,1 分到 10 分">
|
||||
<?php /* v10:10 星制。DOM 倒序(10..1)+ CSS row-reverse,视觉 1..10 从左到右;
|
||||
点亮由 JS 加 .lit(含悬停预览), radios 保持 name="rating" 原语义。 */ ?>
|
||||
<span class="rv-scale rv-stars no-js" role="radiogroup" aria-label="评分,1 分到 10 分">
|
||||
<?php $myRating = (int)($myReview['rating'] ?? 0); ?>
|
||||
<?php for ($i = 1; $i <= 10; $i++): ?>
|
||||
<label class="rv-num" title="<?= $i ?> 分">
|
||||
<?php for ($i = 10; $i >= 1; $i--): ?>
|
||||
<label class="rv-star" data-v="<?= $i ?>" title="<?= $i ?> 分 · <?= e(\App\MovieReview::ratingWord($i)) ?>">
|
||||
<input type="radio" name="rating" value="<?= $i ?>"<?= $myRating === $i ? ' checked' : '' ?>>
|
||||
<span><?= $i ?></span>
|
||||
<span class="st-glyph st-off" aria-hidden="true">☆</span><span class="st-glyph st-on" aria-hidden="true">★</span>
|
||||
</label>
|
||||
<?php endfor; ?>
|
||||
</span>
|
||||
@@ -157,6 +177,30 @@ $commentBox = static function (int $reviewId, int $parentId, string $summary) us
|
||||
<?php endif; ?>
|
||||
<span>👥 观影人 <?= count($m['attendees']) ?> 人</span>
|
||||
</div>
|
||||
<?php if ($doubanMeta): ?>
|
||||
<div class="db-meta">
|
||||
<?php if (!empty($doubanMeta['rating'])): ?>
|
||||
<span class="db-rating" title="豆瓣评分">豆瓣 <b><?= e((string)$doubanMeta['rating']) ?></b></span>
|
||||
<?php endif; ?>
|
||||
<?php foreach ([
|
||||
'年份' => (string)($doubanMeta['year'] ?? ''),
|
||||
'类型' => (string)($doubanMeta['genre'] ?? ''),
|
||||
'片长' => (string)($doubanMeta['runtime'] ?? ''),
|
||||
'导演' => (string)($doubanMeta['director'] ?? ''),
|
||||
'主演' => (string)($doubanMeta['actors'] ?? ''),
|
||||
'制片国家/地区' => (string)($doubanMeta['country'] ?? ''),
|
||||
'又名' => (string)($doubanMeta['alias'] ?? ''),
|
||||
] as $dbLbl => $dbVal): ?>
|
||||
<?php if ($dbVal !== ''): ?>
|
||||
<span class="db-line"><span class="db-label"><?= $dbLbl ?></span><?= e($dbVal) ?></span>
|
||||
<?php endif; ?>
|
||||
<?php endforeach; ?>
|
||||
<?php if (!empty($doubanMeta['douban_url'])): ?>
|
||||
<a class="db-link" href="<?= e((string)$doubanMeta['douban_url']) ?>"
|
||||
target="_blank" rel="noopener noreferrer">在豆瓣查看 ↗</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($m['info'])): ?>
|
||||
<div class="info-text"><?= nl2br(e($m['info'])) ?></div>
|
||||
<?php endif; ?>
|
||||
@@ -277,7 +321,7 @@ $commentBox = static function (int $reviewId, int $parentId, string $summary) us
|
||||
<?php if ($rvMine): ?><span class="rv-mine">我</span><?php endif; ?>
|
||||
<span class="rv-time"><?= e(substr((string)$rv['created_at'], 0, 16)) ?></span>
|
||||
</span>
|
||||
<span class="rv-score" title="<?= e(\App\MovieReview::ratingWord($rvRate)) ?>"><?= $rvRate ?><span class="rv-score-max">/10</span></span>
|
||||
<span class="rv-score" title="<?= e(\App\MovieReview::ratingWord($rvRate)) ?>"><?= $starsHtml($rvRate) ?><span class="rv-score-max"><?= $rvRate ?>/10</span></span>
|
||||
<?php if ($rvMine && $canWrite): ?>
|
||||
<form method="post" action="<?= e(url('movies/review_del')) ?>" class="rv-del"
|
||||
onsubmit="return confirm('删除我的这条评价?下面的评论也会一起删除,不可恢复。')">
|
||||
@@ -466,23 +510,42 @@ $commentBox = static function (int $reviewId, int $parentId, string $summary) us
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($canWrite): ?>
|
||||
<!-- 打分实时提示「几分 · 怎么样」;纯增强,radio 没 JS 也能选 -->
|
||||
<!-- 打分:星星点亮 + 悬停预览 + 实时提示「几分 · 怎么样」;radio 没 JS 也能选(:has 兜底点亮) -->
|
||||
<script>
|
||||
(function () {
|
||||
var form = document.getElementById('reviewForm');
|
||||
var word = document.getElementById('rvWord');
|
||||
if (!form || !word) return;
|
||||
var scale = form.querySelector('.rv-stars');
|
||||
if (scale) scale.classList.remove('no-js');
|
||||
var WORDS = <?= json_encode(\App\MovieReview::ratingWords(), JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT) ?>;
|
||||
function sync() {
|
||||
function pickedV() {
|
||||
var picked = form.querySelector('input[name="rating"]:checked');
|
||||
if (!picked) { word.textContent = '未评分'; word.classList.remove('is-set'); return; }
|
||||
var v = parseInt(picked.value, 10);
|
||||
return picked ? parseInt(picked.value, 10) : 0;
|
||||
}
|
||||
function paint(v) {
|
||||
if (!scale) return;
|
||||
Array.prototype.forEach.call(scale.querySelectorAll('.rv-star'), function (el) {
|
||||
el.classList.toggle('lit', parseInt(el.getAttribute('data-v'), 10) <= v);
|
||||
});
|
||||
}
|
||||
function sync() {
|
||||
var v = pickedV();
|
||||
if (!v) { word.textContent = '未评分'; word.classList.remove('is-set'); paint(0); return; }
|
||||
word.textContent = v + ' 分 · ' + (WORDS[v - 1] || '');
|
||||
word.classList.add('is-set');
|
||||
paint(v);
|
||||
}
|
||||
Array.prototype.forEach.call(form.querySelectorAll('input[name="rating"]'), function (el) {
|
||||
el.addEventListener('change', sync);
|
||||
});
|
||||
if (scale) {
|
||||
scale.addEventListener('mouseover', function (e) {
|
||||
var lab = e.target.closest ? e.target.closest('.rv-star') : null;
|
||||
if (lab) paint(parseInt(lab.getAttribute('data-v'), 10));
|
||||
});
|
||||
scale.addEventListener('mouseleave', function () { paint(pickedV()); });
|
||||
}
|
||||
sync();
|
||||
})();
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user