调优
This commit is contained in:
@@ -59,7 +59,7 @@ function renderError(error) {
|
||||
}
|
||||
|
||||
const baseViewContext = { state, app, h, formatDate, dateRange, badge, money, passPolicyText, statusLabels, icons, api, renderError, emptyState };
|
||||
const { brand, renderHome, renderAnnouncements, renderAuth } = createPublicViews(baseViewContext);
|
||||
const { brand, renderHome, renderNoticeCenter, renderAuth } = createPublicViews(baseViewContext);
|
||||
const { adminNavForUser, portalShell, loadingPanel, renderCandidate, accountSecurity } = createCandidateViews({ ...baseViewContext, brand });
|
||||
const { renderAdmin, workflowStepEditor } = createAdminViews({ ...baseViewContext, brand, portalShell, loadingPanel, adminNavForUser, accountSecurity });
|
||||
const { renderAdmission } = createAdmissionViews({ ...baseViewContext, brand });
|
||||
@@ -75,7 +75,8 @@ async function renderRoute() {
|
||||
const route = location.hash.slice(1) || 'home';
|
||||
const [section, page = 'dashboard'] = route.split('/');
|
||||
if (section === 'home') renderHome();
|
||||
else if (section === 'announcements') { state.publicAnnouncements = await api('/api/public/announcements'); renderAnnouncements(state.publicAnnouncements); }
|
||||
else if (section === 'notices' || section === 'announcements') { state.publicAnnouncements = await api('/api/public/announcements'); renderNoticeCenter(state.publicAnnouncements); }
|
||||
else if (section === 'notice') { state.publicAnnouncements = await api('/api/public/announcements'); renderNoticeCenter(state.publicAnnouncements, page); }
|
||||
else if (section === 'login' || section === 'register') renderAuth(section);
|
||||
else if (section === 'candidate') await renderCandidate(page);
|
||||
else if (section === 'admin') await renderAdmin(page);
|
||||
@@ -103,6 +104,19 @@ function updateRegistrationSelection() {
|
||||
document.querySelectorAll('[data-action="bulk-registration-review"]').forEach(button => { button.disabled = selected.length === 0; });
|
||||
}
|
||||
|
||||
function updateQualificationSelection(container) {
|
||||
if (!container) return;
|
||||
const rows = [...container.querySelectorAll('[data-qualification-select]')];
|
||||
const selected = rows.filter(input => input.checked);
|
||||
const selectAll = container.querySelector('[data-action="qualification-select-all"]');
|
||||
if (selectAll) {
|
||||
selectAll.checked = rows.length > 0 && selected.length === rows.length;
|
||||
selectAll.indeterminate = selected.length > 0 && selected.length < rows.length;
|
||||
}
|
||||
const count = container.querySelector('[data-qualification-selected-count]');
|
||||
if (count) count.textContent = `已选 ${selected.length} 人`;
|
||||
}
|
||||
|
||||
function applyTableFilters(tableId) {
|
||||
const table = document.getElementById(tableId);
|
||||
if (!table) return;
|
||||
@@ -182,9 +196,20 @@ document.addEventListener('click', async event => {
|
||||
await refreshPublic(); navigate('home'); toast('已安全退出', '期待下次见面'); return;
|
||||
}
|
||||
if (action === 'open-notice') {
|
||||
const notice = state.publicData.notices.find(item => item.id === target.dataset.id) || (await api(`/api/public/notices/${target.dataset.id}`)).notice;
|
||||
const contentHtml = notice.contentHtml || `<p>${h(notice.content).replace(/\r?\n/g, '</p><p>')}</p>`;
|
||||
setModal(`<div class="modal-head"><div><span>${h(notice.category)}</span><h2>${h(notice.title)}</h2><p>${formatDate(notice.publishAt,true)} · ${h(notice.author)}</p></div><button data-action="close-modal">×</button></div><article class="notice-content">${contentHtml}</article><div class="modal-foot"><button class="ghost-button" data-action="close-modal">关闭</button></div>`); return;
|
||||
return navigate(`notice/${target.dataset.id}`);
|
||||
}
|
||||
if (action === 'notice-category') {
|
||||
state.noticeCategory = target.dataset.category;
|
||||
state.noticePage = 1;
|
||||
renderNoticeCenter(state.publicAnnouncements);
|
||||
return;
|
||||
}
|
||||
if (action === 'notice-page') {
|
||||
if (target.disabled) return;
|
||||
state.noticePage = Number(target.dataset.page || 1);
|
||||
renderNoticeCenter(state.publicAnnouncements);
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
return;
|
||||
}
|
||||
if (action === 'download-admit') { window.location.href = `/api/candidate/registrations/${target.dataset.id}/admit-card`; return; }
|
||||
if (action === 'download-admitted-candidates') {
|
||||
@@ -230,6 +255,37 @@ document.addEventListener('click', async event => {
|
||||
toast(data.published ? '资格已确认并自动公示' : '资格已确认', data.published ? '本校全部考生已确认完成' : '继续核对其他考生');
|
||||
return renderRoute();
|
||||
}
|
||||
if (action === 'qualification-select-all') {
|
||||
const container = target.closest('[data-qualification-bulk]')?.closest('.qualification-ledger');
|
||||
container?.querySelectorAll('[data-qualification-select]').forEach(input => { input.checked = target.checked; });
|
||||
updateQualificationSelection(container);
|
||||
return;
|
||||
}
|
||||
if (action === 'bulk-indicator-qualification') {
|
||||
const toolbar = target.closest('[data-qualification-bulk]');
|
||||
const ledger = toolbar?.closest('.qualification-ledger');
|
||||
const userIds = [...ledger.querySelectorAll('[data-qualification-select]:checked')].map(input => input.closest('tr').dataset.userId);
|
||||
const value = toolbar.querySelector('[data-bulk-eligible]').value;
|
||||
if (!userIds.length) return toast('请先选择考生', '可使用左侧复选框或全选');
|
||||
if (!value) return toast('请选择批量资格结论');
|
||||
if (!window.confirm(`确认将所选 ${userIds.length} 名考生批量设为“${value === 'true' ? '有' : '无'}指标分配资格”?`)) return;
|
||||
const data = await api(`/api/admin/indicator-qualifications/${toolbar.dataset.examId}/bulk`, { method: 'PUT', body: { userIds, eligible: value === 'true' } });
|
||||
toast(data.published ? '批量确认完成并自动公示' : '批量确认完成', `已更新 ${data.count} 名考生`);
|
||||
return renderRoute();
|
||||
}
|
||||
if (action === 'toggle-admin-account') {
|
||||
const active = target.dataset.active === 'true';
|
||||
if (!active && !window.confirm('确认停用该管理员账户?其现有登录会话会立即失效,历史审批记录将保留。')) return;
|
||||
await api(`/api/admin/admins/${target.dataset.id}`, { method: 'PATCH', body: { active } });
|
||||
toast(active ? '管理员账户已启用' : '管理员账户已停用', active ? '该账号可以重新登录' : '现有会话已结束,历史记录仍保留');
|
||||
return renderRoute();
|
||||
}
|
||||
if (action === 'reset-admin-password') {
|
||||
if (!window.confirm('确认重置该管理员密码?其现有登录会话会立即失效。')) return;
|
||||
const data = await api(`/api/admin/admins/${target.dataset.id}/reset-password`, { method: 'POST' });
|
||||
setModal(`<div class="modal-head"><div><span>ADMIN PASSWORD RESET</span><h2>管理员临时密码已生成</h2><p>请通过线下安全渠道交给管理员,本页面关闭后不再展示。</p></div><button data-action="close-modal">×</button></div><div class="issued-number"><span>登录账号</span><strong>${h(data.username)}</strong><span>临时密码</span><strong>${h(data.temporaryPassword)}</strong><p>旧密码和现有登录会话均已失效。</p></div><div class="modal-foot"><button class="solid-button" data-action="close-modal">我已保存</button></div>`);
|
||||
return;
|
||||
}
|
||||
if (action === 'add-admission-category') {
|
||||
const sources = state.pageData?.sourceSchools || [];
|
||||
target.closest('form')?.querySelector('[data-admission-categories]')?.insertAdjacentHTML('beforeend', admissionCategoryEditor(h, sources));
|
||||
@@ -451,6 +507,7 @@ document.addEventListener('input', event => {
|
||||
});
|
||||
|
||||
document.addEventListener('change', event => {
|
||||
if (event.target.matches('[data-qualification-select]')) updateQualificationSelection(event.target.closest('.qualification-ledger'));
|
||||
if (event.target.matches('[data-table-filter]')) applyTableFilters(event.target.dataset.target);
|
||||
if (event.target.matches('[data-registration-select]')) updateRegistrationSelection();
|
||||
if (event.target.matches('[data-registration-select-all]')) {
|
||||
|
||||
Reference in New Issue
Block a user