基本信息${U.badge(t.status,'status')} ${U.badge(t.type,'type')} ${U.badge(t.priority,'priority')}
标题${U.esc(t.title)}
提交?/span>${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.attachments?.length?`
附件 (${t.attachments.length})
`:''}
沟通记?/div>
${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||'')})`:'匿名'}
负责?/span>${t.assignee_name?`${U.esc(t.assignee_name)}`:'待认?/span>'}
${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' ? `
结果申诉
对处理结果有异议?可以提交一次申诉,由服主复核?/p>
`:''}
${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); }
};
}
};