โชว์การ์ดพิเศษที่ได้ + ปุ่มไปต่อ

This commit is contained in:
2026-06-02 08:29:04 +00:00
parent 18cad3e9f6
commit f98cbfa9e0
69 changed files with 725 additions and 48 deletions
+139
View File
@@ -4184,6 +4184,144 @@
if (saveBtn) saveBtn.addEventListener('click', saveEvidenceCardsPanel);
})();
/* ===== รูปคดี & Cutscene (LobbyA → LobbyB) ===== */
var CASE_MEDIA_API = '/Game/api/case-media';
var CASE_MEDIA_IMAGES_API = '/Game/api/case-media-images';
var CASE_MEDIA_COUNT = 15;
var caseMediaData = null;
var caseMediaImages = null; // { case:[...], cutscene:[...] }
var caseMediaCurrent = '1';
function caseMediaPopulateSelect() {
var sel = el('case-media-case');
if (!sel || sel.options.length) return;
for (var i = 1; i <= CASE_MEDIA_COUNT; i++) {
var o = document.createElement('option');
o.value = String(i); o.textContent = 'คดี ' + i;
sel.appendChild(o);
}
}
function loadCaseMediaPanel() {
caseMediaPopulateSelect();
if (caseMediaImages == null) {
fetch(CASE_MEDIA_IMAGES_API + '?_=' + Date.now(), { credentials: 'include', cache: 'no-store' })
.then(function (r) { return r.json(); })
.then(function (j) { caseMediaImages = (j && j.images) || { case: [], cutscene: [] }; renderCaseMedia(caseMediaCurrent); })
.catch(function () { caseMediaImages = { case: [], cutscene: [] }; });
}
fetch(CASE_MEDIA_API + '?_=' + Date.now(), { credentials: 'include', cache: 'no-store' })
.then(function (r) { return r.json(); })
.then(function (j) {
caseMediaData = (j && j.cases) ? j : { cases: {} };
var sel = el('case-media-case');
if (sel) caseMediaCurrent = sel.value || '1';
renderCaseMedia(caseMediaCurrent);
})
.catch(function (e) {
setMsg('case-media-msg', (e.message || 'โหลดไม่ได้') + ' — เช็คว่า Node รัน Game/server.js และ /Game/api/case-media ไม่ 404', 'error');
});
}
function caseMediaGetCase(cid) {
if (!caseMediaData) caseMediaData = { cases: {} };
if (!caseMediaData.cases) caseMediaData.cases = {};
var n = parseInt(cid, 10) || 1;
if (!caseMediaData.cases[cid]) caseMediaData.cases[cid] = {};
var c = caseMediaData.cases[cid];
if (typeof c.name !== 'string') c.name = 'คดีที่ ' + n;
if (typeof c.art !== 'string') c.art = '/Main-Lobby/IMAGE/case/case-' + n + '.png';
if (typeof c.detail !== 'string') c.detail = '/Main-Lobby/IMAGE/case/case-detail-' + n + '.png';
if (!Array.isArray(c.story)) c.story = [];
if (typeof c.story[0] !== 'string') c.story[0] = '/Main-Lobby/IMAGE/cutscene/case-' + n + '-story-1.png';
if (typeof c.story[1] !== 'string') c.story[1] = '/Main-Lobby/IMAGE/cutscene/case-' + n + '-story-2.png';
return c;
}
/** ตัวเลือกรูป (dropdown + พรีวิว) — kind = 'case' | 'cutscene' */
function caseMediaImagePicker(label, kind, current, onChange) {
var wrap = document.createElement('div');
wrap.className = 'cm-pick';
var lab = document.createElement('div'); lab.className = 'cm-pick-label'; lab.textContent = label;
var prev = document.createElement('img'); prev.className = 'cm-pick-prev'; prev.alt = ''; prev.src = current;
prev.onerror = function () { this.style.opacity = '0.25'; };
var sel = document.createElement('select'); sel.className = 'admin-inp-num';
var list = (caseMediaImages && caseMediaImages[kind]) ? caseMediaImages[kind].slice() : [];
if (current && list.indexOf(current) < 0) list.unshift(current);
list.forEach(function (u) {
var o = document.createElement('option');
o.value = u; o.textContent = u.split('/').pop();
if (u === current) o.selected = true;
sel.appendChild(o);
});
sel.addEventListener('change', function () { prev.src = sel.value; onChange(sel.value); });
wrap.appendChild(lab); wrap.appendChild(prev); wrap.appendChild(sel);
return wrap;
}
function renderCaseMedia(cid) {
caseMediaCurrent = cid;
var tag = el('case-media-set-tag');
if (tag) tag.textContent = 'กำลังแก้: คดี ' + cid;
var root = el('case-media-root');
if (!root) return;
var c = caseMediaGetCase(cid);
root.innerHTML = '';
var nameLabel = document.createElement('label');
nameLabel.className = 'admin-field';
nameLabel.textContent = 'ชื่อคดี';
var nameInp = document.createElement('input');
nameInp.type = 'text'; nameInp.maxLength = 80; nameInp.value = c.name || '';
nameInp.addEventListener('input', function () { c.name = nameInp.value; });
nameLabel.appendChild(nameInp);
root.appendChild(nameLabel);
var grid = document.createElement('div');
grid.className = 'cm-grid';
grid.appendChild(caseMediaImagePicker('รูปเลือกคดี (การ์ด)', 'case', c.art, function (v) { c.art = v; }));
grid.appendChild(caseMediaImagePicker('รูปรายละเอียดคดี', 'case', c.detail, function (v) { c.detail = v; }));
grid.appendChild(caseMediaImagePicker('Cutscene รูปที่ 1', 'cutscene', c.story[0], function (v) { c.story[0] = v; }));
grid.appendChild(caseMediaImagePicker('Cutscene รูปที่ 2', 'cutscene', c.story[1], function (v) { c.story[1] = v; }));
root.appendChild(grid);
}
function saveCaseMediaPanel() {
if (!caseMediaData) return;
var btn = el('btn-case-media-save');
if (btn) btn.disabled = true;
setMsg('case-media-msg', 'กำลังบันทึก…', '');
fetch(CASE_MEDIA_API, {
method: 'PUT',
credentials: 'include',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(caseMediaData),
}).then(function (r) {
return r.text().then(function (t) {
var j = {};
try { j = t ? JSON.parse(t) : {}; } catch (e) { /* ignore */ }
if (!r.ok || !j.ok) throw new Error((j && j.error) || ('HTTP ' + r.status));
return j;
});
}).then(function (j) {
if (j && j.cases) caseMediaData = { cases: j.cases };
renderCaseMedia(caseMediaCurrent);
setMsg('case-media-msg', 'บันทึกแล้ว — มีผลในเกมเมื่อรีเฟรช LobbyA/LobbyB', 'ok');
}).catch(function (e) {
setMsg('case-media-msg', e.message || 'บันทึกไม่ได้', 'error');
}).then(function () {
if (btn) btn.disabled = false;
});
}
(function bindCaseMediaPanel() {
caseMediaPopulateSelect();
var caseSel = el('case-media-case');
if (caseSel) caseSel.addEventListener('change', function () { renderCaseMedia(caseSel.value || '1'); });
var saveBtn = el('btn-case-media-save');
if (saveBtn) saveBtn.addEventListener('click', saveCaseMediaPanel);
})();
function setTab(name) {
document.querySelectorAll('.tab').forEach(function (t) {
var on = t.getAttribute('data-tab') === name;
@@ -4212,6 +4350,7 @@
if (name === 'quiz') loadQuizSettingsPanel();
if (name === 'special-quiz') loadSpecialQuizPanel();
if (name === 'evidence-cards') loadEvidenceCardsPanel();
if (name === 'case-media') loadCaseMediaPanel();
if (name === 'quiz-carry') loadQuizCarryPanel();
if (name === 'quiz-battle') loadQbBattlePanel();
if (name === 'jump-survive') loadJumpSurviveTimingPanel();