// ============ 表单 + 生成图 + MantleDB 提交 ============ const form = document.getElementById('commissionForm'); const sheetWrapper = document.getElementById('sheetWrapper'); const modal = document.getElementById('modal'); const closeBtn = document.getElementById('closeBtn'); const downloadBtn = document.getElementById('downloadBtn'); const previewBtn = document.getElementById('previewBtn'); const statusMsg = document.getElementById('status'); let currentData = null; function collect() { const fd = new FormData(form); const data = {}; fd.forEach((v, k) => data[k] = (v || '').toString().trim()); return data; } function escapeHtml(s) { return String(s ?? '').replace(/[&<>"']/g, c => ({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c]) ); } function cell(num, label, value) { const v = value && value.trim() ? escapeHtml(value) : ''; return `
${num}. ${label} ${v}
`; } function cellFull(num, label, value) { const v = value && value.trim() ? escapeHtml(value) : ''; return `
${num}. ${label} ${v}
`; } function rand(seed) { let h = 0; for (let i = 0; i < seed.length; i++) h = (h * 31 + seed.charCodeAt(i)) | 0; return Math.abs(h); } function renderSheet(data) { const now = new Date(); const dateStr = now.toISOString().slice(0,10); const id = `NO. ${(rand(data.clientName + data.charName) % 9000 + 1000)}-${dateStr.replace(/-/g,'')}`; const showDraft = (rand(data.clientName) % 3) === 0; const showReceived = (rand(data.charName) % 2) === 0; return `
STANDARD FORM 50
REV. APRIL 1951
FORM APPROVED
BUDGET BUREAU NO. 50-R06

Notification of Commission

COMMISSION
STAMP
${dateStr.replace(/-/g,'.')}
${cell(1, 'CLIENT', data.clientName)} ${cell(2, 'CONTACT', data.contact)} ${cell(3, 'IP', data.ip)} ${cell(4, 'CHAR. NAME', data.charName)} ${cell(5, 'EN NAME', data.charNameEn)} ${cell(6, 'BIRTHDAY', data.birthday)} ${cell(7, 'KEYWORDS (EN)', data.keywordsEn)} ${cell(8, 'ID NO.', id)} ${cell(9, 'SIZE', data.size)} ${cell(10, 'USAGE', data.usage)} ${cell(11, 'BLEED', data.bleed || '3mm')} ${cell(12, 'DDL', data.ddl)} ${cell(13, 'TEMPLATE', data.hasTemplate)} ${cell(14, 'TRANSPARENT BG', data.transparentBg)} ${cell(15, 'LAYERED FILE', data.layeredFile)} ${cellFull(16, 'STYLE / 参考图链接', data.style)} ${cellFull(17, 'COLOR / 色卡链接', data.color)} ${cellFull(18, 'OTHER NOTES', data.other)}
Client Signature
${escapeHtml(data.clientName || '')}
Date Filed
${dateStr}
PREPARED BY CLIENT · FILED AUTOMATICALLY · ${id}
${showDraft ? `
DRAFT
` : ''} ${showReceived ? `
RECEIVED
` : ''}
`; } function showSheet(data) { currentData = data; sheetWrapper.innerHTML = renderSheet(data); modal.classList.remove('hidden'); } function hideSheet() { modal.classList.add('hidden'); } function setStatus(msg, isError) { if (!statusMsg) return; statusMsg.textContent = msg; statusMsg.style.color = isError ? '#b22222' : '#2a7a2a'; } // ============ MantleDB 提交 ============ async function submitToMantle(data) { const { MANTLEDB_NS, MANTLEDB_KEY, MANTLEDB_BASE } = window.CONFIG; const url = `${MANTLEDB_BASE}/${MANTLEDB_NS}/submissions`; const headers = { 'Content-Type': 'application/json', 'X-Mantle-Key': MANTLEDB_KEY }; // 1. 读取现有列表 const readRes = await fetch(url, { headers }); let list = []; if (readRes.ok) { list = await readRes.json(); if (!Array.isArray(list)) list = []; } // 2. 追加新条目 const submission = { id: Date.now().toString(36) + Math.random().toString(36).slice(2,8), createdAt: new Date().toISOString(), ...data }; list.unshift(submission); // 3. 写回 const writeRes = await fetch(url, { method: 'POST', headers, body: JSON.stringify(list) }); if (!writeRes.ok) throw new Error('写入失败: ' + writeRes.status); return true; } // ============ 事件 ============ previewBtn.addEventListener('click', () => { const data = collect(); if (!data.clientName || !data.charName || !data.ddl) { alert('请至少填写:单主昵称、角色名、DDL'); return; } showSheet(data); }); closeBtn.addEventListener('click', hideSheet); modal.addEventListener('click', e => { if (e.target === modal) hideSheet(); }); downloadBtn.addEventListener('click', async () => { if (!currentData) return; const sheet = document.getElementById('sheet'); const canvas = await html2canvas(sheet, { backgroundColor: '#d8d2bf', scale: 2, useCORS: true, logging: false, }); const a = document.createElement('a'); a.href = canvas.toDataURL('image/png'); a.download = `约稿单-${currentData.charName || 'commission'}-${Date.now()}.png`; a.click(); }); form.addEventListener('submit', async e => { e.preventDefault(); const data = collect(); if (!data.clientName || !data.charName || !data.ddl) { alert('请至少填写:单主昵称、角色名、DDL'); return; } // 先展示预览(这样即使提交失败单主也能下载图) showSheet(data); // 提交到 MantleDB try { setStatus('正在提交...'); const ok = await submitToMantle(data); setStatus(ok ? '✓ 已提交,请下载图片发给画师' : '⚠ 提交异常,请直接下载图片发给画师'); } catch (err) { console.error(err); setStatus('⚠ 提交失败,但你可以直接下载图片发给画师', true); } });