// 后台交互脚本(原生 JS,无构建步骤)。data-admin-js // 两个入口页面: // - 文章管理混合列表(/admin/articles):批量通过/驳回 // - 街拍编辑页(/admin/street-snaps/:id/edit):主副图合并/拆出(街拍分组) (function () { // 表单动作里的 /admin/articles/ 换成 /admin/api/articles/,得到对应的 JSON 接口地址。 function apiOf(action) { return action.replace('/admin/articles/', '/admin/api/articles/'); } // ── 看大图弹层(所有页面通用)──────────────────────────────────────────── function initZoom() { var modal = document.getElementById('zoom-modal'); if (!modal) return; var img = document.getElementById('zoom-img'); document.querySelectorAll('.thumb[data-zoom]').forEach(function (btn) { btn.addEventListener('click', function () { img.src = btn.querySelector('img').src; modal.showModal(); }); }); modal.addEventListener('click', function (e) { if (e.target === modal) modal.close(); }); } // ── 文章管理列表:批量通过 / 驳回 ────────────────────────────────────── function initArticleList() { var selAll = document.getElementById('sel-all'); var picks = function () { return Array.prototype.slice.call(document.querySelectorAll('.row-pick')); }; var bar = document.getElementById('batchbar'); var count = document.getElementById('sel-count'); function refresh() { var n = picks().filter(function (c) { return c.checked; }).length; if (bar) bar.hidden = n === 0; if (count) count.textContent = '已选 ' + n + ' 条'; } if (selAll) selAll.addEventListener('change', function () { picks().forEach(function (c) { c.checked = selAll.checked; }); refresh(); }); picks().forEach(function (c) { c.addEventListener('change', refresh); }); var clear = document.getElementById('batch-clear'); if (clear) clear.addEventListener('click', function () { picks().forEach(function (c) { c.checked = false; }); if (selAll) selAll.checked = false; refresh(); }); function postBatch(action) { var items = picks().filter(function (c) { return c.checked; }).map(function (c) { var tr = c.closest('tr'); return { kind: tr.getAttribute('data-kind'), id: parseInt(tr.getAttribute('data-id'), 10) }; }); if (items.length === 0) { alert('请先勾选要操作的记录'); return; } if (!confirm('确认' + (action === 'approve' ? '通过' : '驳回') + '选中的 ' + items.length + ' 条?')) return; fetch('/admin/api/articles/batch', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ action: action, items: items }) }).then(function (r) { return r.json(); }).then(function (d) { if (d.failed && d.failed.length) { alert('成功 ' + d.ok + ' 条,失败 ' + d.failed.length + ' 条:' + d.failed[0].error); } location.reload(); }).catch(function (e) { alert('请求失败:' + e); }); } var approve = document.getElementById('batch-approve'); var reject = document.getElementById('batch-reject'); if (approve) approve.addEventListener('click', function () { postBatch('approve'); }); if (reject) reject.addEventListener('click', function () { postBatch('reject'); }); } // ── 街拍编辑页:主副图分组(合并 / 拆出)────────────────────────────── function initArticleDetail() { var batchForm = document.getElementById('batch'); var stat = document.getElementById('img-stat'); var hint = document.getElementById('hint-dismiss'); if (hint) hint.addEventListener('click', function () { var h = hint.closest('.hint'); if (h) h.style.display = 'none'; }); // 每个主图各自的「显示副图」开关:点一下只展开/收起该主图紧邻的副图(不会一次全开)。 var grid = document.querySelector('.grid'); if (grid) { grid.addEventListener('click', function (e) { var btn = e.target.closest('.toggle-det'); if (!btn) return; var pid = btn.getAttribute('data-parent'); var dets = grid.querySelectorAll('.cell.det[data-parent="' + pid + '"]'); var expand = false; dets.forEach(function (d) { if (!d.classList.contains('shown')) expand = true; }); dets.forEach(function (d) { d.classList.toggle('shown', expand); }); btn.textContent = expand ? ('隐藏副图(' + dets.length + ' 张)') : ('显示副图(' + dets.length + ' 张)'); }); } // 合并选中为一组(AJAX,成功后就地更新标签) if (batchForm) batchForm.addEventListener('submit', function (e) { e.preventDefault(); // 注意:主图 radio / 选入 checkbox 用 form="batch" 关联到批量表单,但 DOM 上并不在 //