const TicketsPage = {
tab: 'all',
filters: {},
async render() { return '
'; },
async mount() {
document.getElementById('page-title').textContent = '工单列表';
document.getElementById('page-actions').innerHTML = `
`;
this.renderLayout();
await this.loadTab(this.tab);
},
renderLayout() {
const ct = document.getElementById('page-content');
const isStaff = Auth.isAdmin();
ct.innerHTML = `
${Auth.user().role === 'player' ? '' : ''}
`;
document.querySelectorAll('#ticket-tabs button').forEach(btn => {
btn.onclick = () => {
document.querySelectorAll('#ticket-tabs button').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
this.tab = btn.dataset.tab;
this.loadTab(this.tab);
};
});
},
async loadTab(tab) {
const list = document.getElementById('ticket-list');
U.loading(list);
try {
const params = new URLSearchParams();
if (this.filters.type) params.set('type', this.filters.type);
if (this.filters.status) params.set('status', this.filters.status);
if (this.filters.priority) params.set('priority', this.filters.priority);
if (this.filters.search) params.set('search', this.filters.search);
if (tab === 'pending') params.set('claimed', '0');
else if (tab === 'claimed') params.set('claimed', '1');
else if (tab === 'mine') params.set('status', '');
const qs = params.toString();
const tickets = await API.get('/tickets' + (qs ? '?' + qs : ''));
if (tab === 'mine') {
this.renderList(list, tickets);
return;
}
this.renderList(list, tickets);
} catch (e) { list.innerHTML = `${e.message}
`; }
},
renderList(ct, tickets) {
ct.innerHTML = tickets.length === 0
? ``
: `
| # | 类型 | 标题 | 提交者 | 对象 | 状态 | 优先级 | 负责人 | 时间 | 操作 |
${tickets.map(t => `
| ${t.id} |
${U.badge(t.type,'type')} |
${U.esc(t.title)} |
${U.esc(t.reporter_game_name)} UID:${U.esc(t.reporter_game_uid)} |
${t.target_game_name?`${U.esc(t.target_game_name)}${t.target_game_uid?` UID:${U.esc(t.target_game_uid)}`:''}`:'-'} |
${U.badge(t.status,'status')} |
${U.badge(t.priority,'priority')} |
${t.assignee_name?`${U.esc(t.assignee_name)}`:`待认领`} |
${U.date(t.updated_at)} |
|
`).join('')}
`;
},
applyFilters() {
this.filters = {
type: document.getElementById('ft-type').value,
status: document.getElementById('ft-status').value,
priority: document.getElementById('ft-priority').value,
search: document.getElementById('ft-search').value,
};
this.loadTab(this.tab);
},
resetFilters() {
this.filters = {};
document.querySelectorAll('.filter-bar select, .filter-bar input').forEach(el => { if (el.tagName === 'SELECT' || el.tagName === 'INPUT') el.value = ''; });
this.loadTab(this.tab);
}
};