Add indicator qualification and admissions announcements

This commit is contained in:
2026-07-21 14:37:06 +08:00 Unverified
parent 5e0bee60e2
commit 6be1ff227a
17 changed files with 332 additions and 70 deletions
+16 -4
View File
@@ -20,12 +20,12 @@ export function createPublicViews(context) {
}
function publicHeader() {
return `<header class="public-header"><div class="public-nav">${brand()}<nav><a href="#home" data-route="home">首页</a><a href="#home-exams" data-action="scroll-to" data-target="home-exams">考试报名</a><a href="#home-notices" data-action="scroll-to" data-target="home-notices">通知公告</a><a href="#home-admissions" data-action="scroll-to" data-target="home-admissions">录取公示</a><a href="#service-flow" data-action="scroll-to" data-target="service-flow">办事指南</a></nav><div class="nav-actions">${state.user ? `<button class="text-button" data-route="${state.user.role}/dashboard">进入${state.user.role === 'admin' ? '管理后台' : state.user.role === 'admission_school' ? '招生学校' : '考生中心'}</button><button class="solid-button" data-action="logout">退出</button>` : `<button class="text-button" data-route="login">登录</button><button class="solid-button" data-route="register">考生注册</button>`}<button class="mobile-menu" data-action="toggle-public-nav" aria-label="打开导航">${icons.menu}</button></div></div></header>`;
return `<header class="public-header"><div class="public-nav">${brand()}<nav><a href="#home" data-route="home">首页</a><a href="#home-exams" data-action="scroll-to" data-target="home-exams">考试报名</a><a href="#home-notices" data-action="scroll-to" data-target="home-notices">通知公告</a><a href="#announcements" data-route="announcements">招生公示</a><a href="#service-flow" data-action="scroll-to" data-target="service-flow">办事指南</a></nav><div class="nav-actions">${state.user ? `<button class="text-button" data-route="${state.user.role}/dashboard">进入${state.user.role === 'admin' ? '管理后台' : state.user.role === 'admission_school' ? '招生学校' : '考生中心'}</button><button class="solid-button" data-action="logout">退出</button>` : `<button class="text-button" data-route="login">登录</button><button class="solid-button" data-route="register">考生注册</button>`}<button class="mobile-menu" data-action="toggle-public-nav" aria-label="打开导航">${icons.menu}</button></div></div></header>`;
}
function renderHome() {
app.classList.remove('admin-readable');
const { notices, exams, stats, organization, admissionAnnouncements = [] } = state.publicData;
const { notices, exams, stats, organization } = state.publicData;
const siteCopy = state.publicData.siteCopy || {};
const featured = exams.find(exam => exam.registrationState === 'open') || exams[0];
const topNotice = notices[0];
@@ -37,11 +37,23 @@ export function createPublicViews(context) {
</div>
</section>
<section class="content-section" id="home-notices"><div class="section-heading"><div><p class="overline">NOTICE BOARD</p><h2>通知公告</h2></div><p>报名、考试、准考证与成绩发布的重要时间,请以平台通知为准。</p></div><div class="notice-layout"><article class="featured-notice">${topNotice ? `<span>${h(topNotice.category)}</span><h3>${h(topNotice.title)}</h3><p>${h(topNotice.summary)}</p><footer><time>${formatDate(topNotice.publishAt)}</time><button data-action="open-notice" data-id="${h(topNotice.id)}">阅读通知 ${icons.arrow}</button></footer>` : '<p>暂无通知</p>'}</article><div class="notice-list">${notices.slice(1, 5).map(renderNoticeRow).join('') || '<div class="empty-state">暂无更多通知</div>'}</div></div></section>
${admissionAnnouncements.length ? `<section class="content-section public-admission-section" id="home-admissions"><div class="section-heading"><div><p class="overline">ADMISSION DISCLOSURE</p><h2>录取结果公示</h2></div><p>报名号、姓名、总成绩与录取学校透明公开;证件号和联系方式已脱敏。</p></div>${admissionAnnouncements.map(announcement => `<article class="panel public-admission-board"><header><div><span>${formatDate(announcement.completedAt)}</span><h3>${h(announcement.examName)}</h3></div><strong>${announcement.rows.length} 人录取</strong></header><div class="table-scroll"><table><thead><tr><th>报名号</th><th>姓名</th><th>总成绩</th><th>录取学校</th><th>录取类别</th><th>身份核验</th></tr></thead><tbody>${announcement.rows.map(row => `<tr><td class="mono">${h(row.registrationNumber)}</td><td><strong>${h(row.name)}</strong></td><td>${h(row.totalScore)}</td><td>${h(row.admittedSchool)}</td><td>${h(row.categoryName)}</td><td class="mono">${h(row.idNumberMasked)}</td></tr>`).join('')}</tbody></table></div></article>`).join('')}</section>` : ''}
<section class="content-section disclosure-entry"><div><p class="overline">ADMISSION DISCLOSURE</p><h2>招生录取公开卷宗</h2><p>指标分配资格、最终录取名单和录取分数线集中公开,所有重要身份信息均按规则脱敏。</p></div><button class="solid-button large" data-route="announcements">进入招生公示页 ${icons.arrow}</button></section>
<section class="content-section exam-section" id="home-exams"><div class="section-heading"><div><p class="overline">OPEN EXAMINATIONS</p><h2>考试报名</h2></div><p>登录后选择考试,并按实际需要勾选报考科目。</p></div><div class="public-exam-grid">${exams.map(renderPublicExam).join('') || '<div class="empty-state">当前没有已发布的考试</div>'}</div></section>
<section class="service-flow" id="service-flow"><div class="section-heading light"><div><p class="overline">SERVICE FLOW</p><h2>报名号是唯一账户</h2></div><p>报名号不会随考试改变,每场考试只新增一条报名记录。</p></div><div class="flow-track">${[['01','领取报名号','学校创建账户并下发初始密码。'],['02','修改初始密码','首次登录必须设置自己的新密码。'],['03','补全个人信息','填写籍贯、住址、手机、邮箱和班级等资料。'],['04','选择考试科目','资料审核通过后自主选择考试。'],['05','下载准考证与查分','继续使用同一报名号办理后续事项。']].map(item => `<article><span>${item[0]}</span><h3>${item[1]}</h3><p>${item[2]}</p></article>`).join('')}</div></section>
</main><footer class="public-footer"><div>${brand()}<p>${[organization.name, organization.phone].filter(Boolean).map(h).join(' · ')}</p>${organization.address || organization.email ? `<p class="public-contact-detail">${[organization.address, organization.email].filter(Boolean).map(h).join(' · ')}</p>` : ''}</div><span>${h(siteCopy.footerNotice || '')}</span></footer>`;
}
function renderAnnouncements(data = state.publicAnnouncements) {
app.classList.remove('admin-readable');
const organization = state.publicData.organization || {};
const sections = [data.qualifications?.length, data.admissions?.length, data.cutoffs?.length].filter(Boolean).length;
app.innerHTML = `${publicHeader()}<main class="public-main announcement-page"><section class="announcement-hero"><div><p class="overline">PUBLIC ADMISSION LEDGER</p><h1>招生录取<br><em>公开卷宗</em></h1><p>按考试留存资格确认、录取结果和分数线。报名号、姓名、总成绩与录取学校透明公开,证件及联系方式不在本页展示。</p></div><dl><div><dt>公开类别</dt><dd>${sections}</dd></div><div><dt>资格公示</dt><dd>${h(data.qualifications?.length || 0)}</dd></div><div><dt>录取公告</dt><dd>${h(data.admissions?.length || 0)}</dd></div></dl></section>
<nav class="announcement-index"><a href="#qualification-publications">01 指标资格</a><a href="#admission-publications">02 录取名单</a><a href="#cutoff-publications">03 录取分数线</a></nav>
<section class="content-section announcement-register" id="qualification-publications"><div class="section-heading"><div><p class="overline">QUALIFICATION REGISTER</p><h2>指标分配资格公示</h2></div><p>仅在生源校全部考生完成资格确认后自动发布。</p></div>${(data.qualifications || []).map(item => `<article class="panel announcement-sheet"><header><div><span>${formatDate(item.publishedAt, true)} · ${h(item.schoolName)}</span><h3>${h(item.examName)}</h3></div><strong>${h(item.rows.length)} 人</strong></header><div class="table-scroll"><table><thead><tr><th>报名号</th><th>姓名</th><th>指标分配资格</th><th>特长类型</th></tr></thead><tbody>${item.rows.map(row => `<tr><td class="mono">${h(row.registrationNumber)}</td><td><strong>${h(row.name)}</strong></td><td><span class="qualification-result ${row.eligible ? 'eligible' : ''}">${row.eligible ? '有' : '无'}</span></td><td>${h(row.specialtyLabel || '普通生')}</td></tr>`).join('')}</tbody></table></div></article>`).join('') || '<div class="empty-state">暂无已完成全校确认的资格公示</div>'}</section>
<section class="content-section announcement-register" id="admission-publications"><div class="section-heading"><div><p class="overline">ADMISSION RESULTS</p><h2>最终录取名单</h2></div><p>录取完成后自动公告,报名号、姓名、总成绩与录取学校公开透明。</p></div>${(data.admissions || []).map(item => `<article class="panel announcement-sheet"><header><div><span>${formatDate(item.publishedAt, true)}</span><h3>${h(item.examName)}</h3></div><strong>${h(item.rows.length)} 人录取</strong></header><div class="table-scroll"><table><thead><tr><th>报名号</th><th>姓名</th><th>总成绩</th><th>录取学校</th><th>录取类别</th></tr></thead><tbody>${item.rows.map(row => `<tr><td class="mono">${h(row.registrationNumber)}</td><td><strong>${h(row.name)}</strong></td><td>${h(row.totalScore)}</td><td>${h(row.admittedSchool)}</td><td>${h(row.categoryName)}</td></tr>`).join('')}</tbody></table></div></article>`).join('') || '<div class="empty-state">暂无已完成的录取公告</div>'}</section>
<section class="content-section announcement-register" id="cutoff-publications"><div class="section-heading"><div><p class="overline">ADMISSION CUTOFFS</p><h2>录取分数线统计</h2></div><p>分数线为对应学校、招生类别最终录取考生的最低总成绩。</p></div>${(data.cutoffs || []).map(item => `<article class="panel announcement-sheet cutoff-sheet"><header><div><span>${formatDate(item.publishedAt, true)}</span><h3>${h(item.examName)}</h3></div><strong>${h(item.rows.length)} 条分数线</strong></header><div class="table-scroll"><table><thead><tr><th>招生学校</th><th>招生类别</th><th>计划数</th><th>录取数</th><th>最高分</th><th>录取分数线</th></tr></thead><tbody>${item.rows.map(row => `<tr><td><strong>${h(row.schoolName)}</strong></td><td>${h(row.categoryName)}</td><td>${h(row.planQuota)}</td><td>${h(row.admittedCount)}</td><td>${h(row.highestScore)}</td><td><strong class="cutoff-score">${h(row.cutoffScore)}</strong></td></tr>`).join('')}</tbody></table></div></article>`).join('') || '<div class="empty-state">暂无已发布的录取分数线</div>'}</section>
</main><footer class="public-footer"><div>${brand()}<p>${[organization.name, organization.phone].filter(Boolean).map(h).join(' · ')}</p></div><span>招生公示数据由系统按业务状态自动生成</span></footer>`;
}
function renderHeroTicket(exam) {
const status = exam.registrationState;
@@ -72,5 +84,5 @@ export function createPublicViews(context) {
return `<form class="stack-form register-form" data-form="register"><div class="field-row"><label><span>考生姓名 *</span><input name="name" required placeholder="与证件一致"></label><label><span>性别 *</span><select name="gender" required><option value="">请选择</option><option>男</option><option>女</option></select></label></div><div class="field-row"><label><span>就读学校 *</span><select name="schoolId" data-action="school-select" required><option value="">请选择学校</option>${schools.map(item => `<option value="${h(item.id)}">${h(item.name)}</option>`).join('')}</select></label><label><span>班级 *</span><select name="classId" required><option value="">请先选择学校</option></select></label></div><label><span>设置登录密码 *</span><input name="password" type="password" required minlength="8" placeholder="至少 8 位字符"></label><label class="agreement"><input type="checkbox" required><span>我会妥善保存系统生成的报名号,并在登录后补全真实个人信息。</span></label><button class="solid-button large" type="submit">生成我的报名号 ${icons.arrow}</button></form>`;
}
return { brand, renderHome, renderAuth };
return { brand, renderHome, renderAnnouncements, renderAuth };
}