const TicketDetail = { id: null, async render(id) { this.id = id; return '
'; }, async mount() { const id = this.id; document.getElementById('page-title').textContent = `工单 #${id}`; document.getElementById('page-actions').innerHTML = ``; try { this.renderDetail(document.getElementById('page-content'), await API.get(`/tickets/${id}`)); } catch (e) { document.getElementById('page-content').innerHTML = `
${e.message}
`; } }, renderDetail(ct, t) { const isStaff = Auth.isAdmin(); const isOwner = Auth.isOwner(); const isRep = t.type === 'report'; const isAppeal = t.type === 'appeal' || t.type === 'result_appeal'; const canClaim = isStaff && !t.assigned_to && t.status === 'pending'; const canTransfer = isStaff && t.assigned_to === Auth.user().id && t.status === 'processing'; const isMyTicket = t.assigned_to === Auth.user().id; ct.innerHTML = `
基本信息
${U.badge(t.status,'status')} ${U.badge(t.type,'type')} ${U.badge(t.priority,'priority')}
标题${U.esc(t.title)}
提交者${U.esc(t.reporter_game_name)} (UID: ${U.esc(t.reporter_game_uid)})
${isRep?`
被举报人${U.esc(t.target_game_name||'?')} (UID: ${U.esc(t.target_game_uid||'?')})
原因${U.esc(t.reason)}
`:''} ${isAppeal?`
申诉理由${U.esc(t.reason)}
`:''} ${t.description?`
${isRep?'详情':isAppeal?'详细说明':'建议内容'}${U.esc(t.description)}
`:''}
提交时间${U.date(t.created_at)}
更新时间${U.date(t.updated_at)}
${t.claim_note?`
处理备注
${U.esc(t.claim_note)}
`:''} ${t.parent_ticket?`
关联工单
原工单#${t.parent_ticket.id} ${U.esc(t.parent_ticket.title)} — ${U.badge(t.parent_ticket.status,'status')}
`:''} ${t.attachments?.length?`
附件 (${t.attachments.length})
${t.attachments.map(a=>a.mime_type.startsWith('image')?``:` ${U.esc(a.original_name)}`).join('')}
`:''}
沟通记录
${t.responses?.length?`
${t.responses.map(r=>`
${U.esc(r.username||'系统')}${r.role?`${U.ROLE[r.role]}`:''}${U.date(r.created_at)}
${U.esc(r.content)}
`).join('')}
`:'

暂无记录

'}
${isStaff?'回复 (公开)':'补充信息'}
处理信息
提交账号${t.submitter?`${U.esc(t.submitter)} (${U.esc(t.user_game_name||'')})`:'匿名'}
负责人${t.assignee_name?`${U.esc(t.assignee_name)}`:'待认领'}
${t.claimed_at?`
认领时间${U.date(t.claimed_at)}
`:''}
${isStaff?`
管理操作
${canClaim?``:''} ${isMyTicket?``:''} ${canTransfer?``:''} ${isOwner||isMyTicket?``:''}
`:''} ${!isStaff && t.user_id === Auth.user().id && ['resolved','rejected'].includes(t.status) && t.type !== 'result_appeal' ? `
结果申诉

对处理结果有异议?可以提交一次申诉,由服主复核。

`:''} ${t.transfers?.length?`
转交历史
${t.transfers.map(tf=>`
${U.esc(tf.from_game_name||tf.from_username)}${U.esc(tf.to_game_name||tf.to_username)}${U.date(tf.created_at)}
${tf.reason?`
${U.esc(tf.reason)}
`:''}
`).join('')}
`:''}
`; document.getElementById('reply-form')?.addEventListener('submit', async e => { e.preventDefault(); const c = document.getElementById('reply-content').value.trim(); if(!c)return; try { await API.post(`/tickets/${id}/response`, {content:c}); this.mount(); } catch(ex){alert(ex.message);} }); }, async claimTicket(id) { U.modal('接单认领', `
`); document.getElementById('claim-form').onsubmit = async e => { e.preventDefault(); try { await API.post(`/tickets/${id}/claim`, {claim_note: document.getElementById('claim-note').value, initial_reply: document.getElementById('claim-reply').value}); App.closeModal(); this.mount(); } catch(ex){alert(ex.message);} }; }, async editNote(id) { const t = await API.get(`/tickets/${id}`); U.modal('更新处理备注', `
`); document.getElementById('note-form').onsubmit = async e => { e.preventDefault(); try { await API.put(`/tickets/${id}`, {claim_note: document.getElementById('upd-note').value}); App.closeModal(); this.mount(); } catch(ex){alert(ex.message);} }; }, async transferTicket(id) { const users = await API.get('/users'); const staff = users.filter(u => (u.role==='owner'||u.role==='admin') && u.id !== Auth.user().id); U.modal('转单', `
`); document.getElementById('tf-form').onsubmit = async e => { e.preventDefault(); try { await API.post(`/tickets/${id}/transfer`, {to_user_id: parseInt(document.getElementById('tf-to').value), reason: document.getElementById('tf-reason').value}); App.closeModal(); this.mount(); } catch(ex){alert(ex.message);} }; }, async changeStatus(id) { U.modal('变更状态', `
`); document.getElementById('cs-form').onsubmit = async e => { e.preventDefault(); try { await API.put(`/tickets/${id}`, {status:document.getElementById('cs-status').value}); App.closeModal(); this.mount(); } catch(ex){alert(ex.message);} }; }, appealResult(parentId) { U.modal('结果申诉', `
申诉后将生成新工单,仅服主可见及处理
`); document.getElementById('ar-form').onsubmit = async e => { e.preventDefault(); try { await API.post('/tickets', { type: 'result_appeal', title: `结果申诉: #${parentId}`, reason: document.getElementById('ar-reason').value, description: document.getElementById('ar-desc').value, parent_ticket_id: parentId, }); App.closeModal(); alert('申诉已提交,请等待服主处理'); this.mount(); } catch(ex) { alert(ex.message); } }; } };