import { formatRegionAddress } from './region-select.js';
import { admissionCategoriesEditor } from './admission-plan-editor.js';
import { specialtyLabel } from '../data/specialty-types.js';
import { filterTableItems, getTableControl } from './table-state.js';

export const numberSegmentMeta = {
  year: ['年份', '4 位考试年份'], school_code: ['学校代码', '使用学校档案代码'], gender: ['考生性别', '男 M / 女 F / 未知 X'],
  sequence: ['流水号', '按规则前缀连续编号'], literal: ['固定值', '自定义固定字母或数字']
};

export function createAdminViews(context) {
  const {
    state,
    app,
    h,
    formatDate,
    dateRange,
    badge,
    money,
    passPolicyText,
    statusLabels,
    icons,
    api,
    renderError,
    requireLogin,
    emptyState,
    brand,
    portalShell,
    loadingPanel,
    adminNavForUser,
    accountSecurity
  } = context;

  async function renderAdmin(page) {
    if (state.user?.role !== 'admin') return requireLogin();
    if (page === 'admissions') page = 'admission-settings';
    app.classList.add('admin-readable');
    const meta = {
      dashboard: ['考务工作台', '掌握当前报名、审核和发布任务。'], candidates: ['考生资料审核', '核验考生实名、学籍与联系信息。'],
      schools: ['学校管理', '创建和维护学校档案，控制学校在考生公开入口中的可选状态。'],
      registrations: ['考试报名审核', '确认考生所报考试、科目与缴费状态。'], exams: ['考试与科目', '创建考试、配置报名时间与考试科目。'],
      payments: [state.user.adminLevel === 'class' ? '考生缴费确认' : '缴费名单', '查看、导出并修改当前管理范围内考生的考试缴费状态。'],
      notices: ['通知发布', '编辑通知草稿，并统一控制手动通知与系统公示是否公开显示。'], admit: [state.user.adminLevel === 'super' ? '准考证编排' : state.user.adminLevel === 'school' ? '校内准考证' : '本班准考证', state.user.adminLevel === 'super' ? '按整场考试预检容量，并批量分配固定考点、分科考场与准考证号。' : '按当前管理范围批量下载准考证，并导出逐科准考证信息。'],
      results: [state.user.adminLevel === 'super' ? '成绩管理中心' : '成绩分析', state.user.adminLevel === 'super' ? '按考试录入、预览导入、发布并跟踪各科达线情况。' : '按考试、科目和发布状态分析管理范围内成绩。'],
      admins: ['分级管理员', '同一级可以配置多名管理员，并分别绑定学校或班级。'],
      centers: ['考务场所档案', state.user.adminLevel === 'school' ? '查看本校考点与结构化考场，所有变更提交后进入审批。' : '管理各校考点、考场容量与变更审批台账。'],
      organization: ['本校组织与权限', '维护本校班级，并为每个班级配置一个或多个班级管理员。'],
      'account-batches': ['批量报名号申领', '按班级填写申领人数；审批通过后系统生成固定报名号和初始密码。'],
      flows: [state.user.adminLevel === 'super' ? '流程监督' : '流程中心', state.user.adminLevel === 'super' ? '查看全部流程，监督转交、修改和退回节点。' : '处理分配给你的流程，并可转交给本校同级管理员。'],
      'flow-design': ['流程设计', '配置考生信息、报名审核、考点考场变更与批量建号的审批步骤。'],
      'number-rules': ['报名号规则', '设计审批通过后生成的新账户号码组成。'],
      'admission-settings': ['录取设置', '设置志愿窗口并控制投档、签发通知书和报到阶段。'],
      'admission-accounts': ['招生学校账户', '创建、停用和维护招生学校工作台账户。'],
      'admission-plans': ['招生计划', '代上传、审核招生计划并实时查看计划完成率。'],
      'admission-reporting': ['报到与补录', '审核学校报到统计和是否开展补充录取的决定。'],
      'admission-supervision': ['投档与退档监督', '搜索、筛选投档记录并审批特殊退档；考生志愿保持只读。'],
      'indicator-qualifications': ['指标分配资格确认', '由生源校逐人确认；本校全部考生确认后，系统自动发布资格公示。'],
      security: ['账户安全', '使用当前密码设置新的登录密码。']
    };
    const allowedPages = adminNavForUser().map(item => item[0]);
    if (!meta[page] || !allowedPages.includes(page)) page = 'dashboard';
    app.innerHTML = portalShell('admin', page, loadingPanel(), ...meta[page]);
    try {
      const endpoint = page === 'admit' ? 'admission-arrangements' : page === 'flows' ? 'workflow-instances' : page === 'flow-design' ? 'workflows' : page === 'account-batches' ? 'candidate-account-batches' : page === 'organization' ? 'school-organization' : page.startsWith('admission-') ? 'admissions' : page;
      let data = page === 'results' && !state.resultExamFilter
        ? { ok: true, selectedExamId: '', results: [], appeals: [], registrations: [], exams: state.resultExamCatalog || state.publicData.exams || [], resultCache: { enabled: false, status: 'not-loaded' } }
        : page === 'security' ? await api('/api/auth/totp') : page === 'results'
          ? await api(`/api/admin/results/summary?examId=${encodeURIComponent(state.resultExamFilter)}`)
          : await api(`/api/admin/${endpoint}`);
      if (page === 'results' && state.resultExamFilter) {
        const activeExam = data.exams.find(item => item.id === state.resultExamFilter);
        const subjectId = state.resultSubjectFilter || activeExam?.subjects?.[0]?.id || '';
        state.resultSubjectFilter = subjectId;
        const requestQuery = (key, extra = {}) => {
          const current = state.tablePages[key] || {};
          const control = getTableControl(state, key);
          const params = new URLSearchParams({
            examId: state.resultExamFilter,
            page: String(current.page || 1),
            pageSize: String(current.pageSize || 50),
            query: control.query || '',
            status: control.status || 'all',
            ...extra
          });
          return params.toString();
        };
        const resultPromise = api(`/api/admin/results?${requestQuery('resultTable')}`);
        const entryPromise = state.user.adminLevel === 'super' && subjectId
          ? api(`/api/admin/results/roster?${requestQuery('resultEntryTable', { subjectId })}`)
          : Promise.resolve({ items: [], pagination: { page: 1, pageSize: 50, total: 0, totalPages: 1, key: 'resultEntryTable' } });
        const featurePromise = state.user.adminLevel === 'super'
          ? api(`/api/admin/results/roster?${requestQuery('featureScoreTable', { mode: 'feature' })}`)
          : Promise.resolve({ items: [], pagination: { page: 1, pageSize: 50, total: 0, totalPages: 1, key: 'featureScoreTable' } });
        const [resultData, entryData, featureData] = await Promise.all([resultPromise, entryPromise, featurePromise]);
        data = {
          ...data,
          results: resultData.items || [],
          resultPage: { ...(resultData.pagination || {}), items: resultData.items || [] },
          entryPage: { ...(entryData.pagination || {}), items: entryData.items || [] },
          featurePage: { ...(featureData.pagination || {}), items: featureData.items || [] },
          entryCounts: entryData.counts || {},
          featureCounts: featureData.counts || {}
        };
      }
      if (page === 'results' && data.selectedExamId) state.resultExamFilter = data.selectedExamId;
      if (page === 'results' && data.exams?.length) state.resultExamCatalog = data.exams;
      state.pageData = data;
      const content = {
        dashboard: () => adminDashboard(data), candidates: () => adminCandidates(data), registrations: () => adminRegistrations(data.registrations), payments: () => adminPayments(data),
        exams: () => adminExams(data.exams), notices: () => adminNotices(data.notices, data.publications), admit: () => adminAdmit(data), results: () => adminResults(data),
        schools: () => adminSchoolsV2(data), admins: () => adminUsers(data), centers: () => adminCenters(data), flows: () => adminFlows(data), organization: () => adminSchoolOrganization(data), 'account-batches': () => adminAccountBatches(data),
        'flow-design': () => adminFlowDesign(data.workflows), 'number-rules': () => adminNumberRules(data), 'admission-settings': () => adminAdmissionsV2(data, 'settings'), 'admission-accounts': () => adminAdmissionsV2(data, 'accounts'), 'admission-plans': () => adminAdmissionsV2(data, 'plans'), 'admission-reporting': () => adminAdmissionsV2(data, 'reporting'), 'admission-supervision': () => adminAdmissionsV2(data, 'supervision'), 'indicator-qualifications': () => adminIndicatorQualifications(data), security: () => accountSecurity(data)
      }[page]();
      app.innerHTML = portalShell('admin', page, content, ...meta[page]);
      if (page === 'admission-supervision') mountPreferenceLedger(data);
    } catch (error) { renderError(error); }
  }

  function mountPreferenceLedger(data) {
    const container = app.querySelector('.portal-content');
    if (!container) return;
    const rows = data.preferenceRows || [];
    const preferencePage = paged(rows, 'adminPreferenceTable');
    const statusClass = { unfilled: 'pending', submitted: 'approved', locked: 'completed', unavailable: 'closed', ineligible: 'rejected' };
    container.insertAdjacentHTML('beforeend', `<section class="panel data-panel admission-preference-ledger"><div class="panel-title"><div><h2>考生志愿实时台账</h2><p>同时显示未填报、已填报和已锁定考生；页面仅供监督，不提供代改入口。</p></div><span>当前筛选 ${preferencePage.total} / 共 ${rows.length} 人</span></div><div class="data-toolbar admission-ledger-toolbar"><label class="search-box">${icons.search}<input data-action="table-search" data-target="adminPreferenceTable" placeholder="搜索考生、报名号、生源校、志愿学校或类别"></label><div class="table-filter-selects"><select data-table-filter="examId" data-target="adminPreferenceTable"><option value="">全部考试</option>${data.exams.map(exam => `<option value="${h(exam.id)}">${h(exam.name)}</option>`).join('')}</select><select data-table-filter="sourceSchoolId" data-target="adminPreferenceTable"><option value="">全部生源学校</option>${data.sourceSchools.map(school => `<option value="${h(school.id)}">${h(school.name)}</option>`).join('')}</select></div><div class="filter-pills"><button class="active" data-action="status-filter" data-target="adminPreferenceTable" data-status="all">全部</button><button data-action="status-filter" data-target="adminPreferenceTable" data-status="unfilled">尚未填报</button><button data-action="status-filter" data-target="adminPreferenceTable" data-status="submitted">已填报</button><button data-action="status-filter" data-target="adminPreferenceTable" data-status="locked">已锁定</button><button data-action="status-filter" data-target="adminPreferenceTable" data-status="unavailable">成绩未齐</button><button data-action="status-filter" data-target="adminPreferenceTable" data-status="ineligible">不可补录</button></div><div class="ledger-toolbar-actions"><button class="row-action" data-action="clear-table-filters" data-target="adminPreferenceTable">清除筛选</button><button class="row-action primary" data-action="admission-ledger-export" data-ledger="preferences" data-table="adminPreferenceTable">导出当前筛选</button></div></div><div class="table-scroll"><table id="adminPreferenceTable"><thead><tr><th>报名号 / 考生</th><th>考试 / 生源校</th><th>轮次 / 状态</th><th>志愿顺序</th><th>提交与锁定</th></tr></thead><tbody>${preferencePage.items.map(item => `<tr data-status="${h(item.status)}"><td><strong>${h(item.candidate.name)}</strong><small class="mono">${h(item.candidate.registrationNumber)}</small><small>${h(item.specialty)}</small></td><td><strong>${h(item.examName)}</strong><small>${h(item.sourceSchoolName)}${item.className ? ` · ${h(item.className)}` : ''}</small></td><td>第 ${h(item.round)} 轮<small><span class="status status-${h(statusClass[item.status] || 'pending')}">${h(item.fillStatus)}</span></small></td><td><div class="admin-preference-choices">${item.choices.map((choice, index) => `<span><b>${choice.preferenceType === 'indicator' ? '指标' : index + 1}</b><i><strong>${h(choice.schoolName || choice.schoolId)}</strong><small>${h([choice.schoolCode, choice.categoryName || choice.categoryCode].filter(Boolean).join(' · '))}</small></i></span>`).join('') || '<em class="preference-empty">尚未填报志愿</em>'}</div></td><td><strong>${h(item.submissionCount)} / ${h(item.maxSubmissions)} 次</strong><small>${item.submittedAt ? formatDate(item.submittedAt, true) : '暂无提交时间'} · ${h(item.lockStatus)}</small></td></tr>`).join('') || '<tr><td colspan="5" class="empty-state">没有符合条件的考生填报记录</td></tr>'}</tbody></table></div>${pagination(preferencePage)}</section>`);
  }
  
  function adminDashboard(data) {
    const m = data.metrics;
    const canFlow = true;
    return `<section class="scope-banner"><span>${statusLabels[state.user.adminLevel]}</span><div><strong>${h(data.scopeLabel)}</strong><small>所有指标均已按当前管理员的数据范围过滤</small></div></section><div class="admin-metrics"><article><span>${icons.users}</span><div><small>范围内考生</small><strong>${m.candidates}</strong><em>${m.pendingCandidates} 人待审核</em></div></article><article><span>${icons.check}</span><div><small>考试报名</small><strong>${m.registrations}</strong><em>${m.pendingRegistrations} 条待审核</em></div></article><article><span>${icons.ticket}</span><div><small>待确认缴费</small><strong>${m.pendingPayments ?? 0}</strong><em>可按当前管理范围办理</em></div></article><article><span>${icons.exam}</span><div><small>待处理流程</small><strong>${m.pendingFlows ?? 0}</strong><em>进入流程中心办理</em></div></article><article><span>${icons.chart}</span><div><small>已发布考试</small><strong>${m.publishedExams}</strong><em>全平台考试计划</em></div></article></div><div class="admin-dashboard-grid"><section class="panel admin-todos"><div class="panel-title"><h2>${canFlow ? '当前工作入口' : '本班查询入口'}</h2><span>${h(data.scopeLabel)}</span></div><button data-route="admin/candidates"><i class="urgent">${m.pendingCandidates}</i><span><strong>${state.user.adminLevel === 'class' ? '查看本班考生' : '考生资料流程'}</strong><small>身份、学籍与联系方式</small></span>${icons.arrow}</button><button data-route="admin/registrations"><i>${m.pendingRegistrations}</i><span><strong>${state.user.adminLevel === 'class' ? '查看报名状态' : '考试报名流程'}</strong><small>考试、科目和报名号</small></span>${icons.arrow}</button><button data-route="admin/payments"><i>${m.pendingPayments ?? 0}</i><span><strong>管理缴费名单</strong><small>线下缴费状态修改与名单导出</small></span>${icons.arrow}</button>${canFlow ? `<button data-route="admin/flows"><i>${m.pendingFlows ?? 0}</i><span><strong>流程中心</strong><small>处理、转交与监督审批</small></span>${icons.arrow}</button>` : ''}<button data-route="admin/results"><i>成</i><span><strong>${state.user.adminLevel === 'super' ? '录入与发布成绩' : '查看范围内成绩'}</strong><small>成绩可见范围由权限控制</small></span>${icons.arrow}</button></section><section class="panel audit-feed"><div class="panel-title"><h2>最近操作</h2><span>系统审计日志</span></div>${data.logs.map(log => `<div><span class="user-avatar">${h((log.actorName || '系').slice(0,1))}</span><p><strong>${h(log.actorName || '系统')} · ${h(log.action)}</strong><small>${h(log.detail)}</small></p><time>${formatDate(log.createdAt,true)}</time></div>`).join('') || '<p class="empty-state">当前账号暂无操作记录</p>'}</section></div>`;
  }
  
  function excelToolbar(resource, { importable = true, template = true, label = '数据' } = {}) {
    return `<div class="excel-toolbar"><span><strong>${h(label)} Excel</strong><small>使用系统模板可获得逐行校验</small></span><div>${template ? `<button class="row-action" data-action="excel-download" data-resource="${h(resource)}" data-template="1">下载模板</button>` : ''}<button class="row-action" data-action="excel-download" data-resource="${h(resource)}">导出当前数据</button>${importable ? `<button class="row-action primary" data-action="excel-import" data-resource="${h(resource)}">导入 Excel</button><input type="file" accept=".xlsx" hidden data-excel-file="${h(resource)}">` : ''}</div></div>`;
  }

  function adminSchools(data) {
    const schools = data.schools || [];
    const activeCount = schools.filter(item => item.active).length;
    return `<section class="center-summary"><div><span>学校总数</span><strong>${schools.length}</strong></div><div><span>启用学校</span><strong>${activeCount}</strong></div><div><span>在册考生</span><strong>${schools.reduce((sum, item) => sum + item.candidateCount, 0)}</strong></div></section><section class="panel data-panel"><div class="data-toolbar"><label class="search-box">${icons.search}<input data-action="table-search" data-target="schoolTable" placeholder="搜索学校名称、代码或地址"></label><div class="filter-pills"><button class="active" data-action="status-filter" data-target="schoolTable" data-status="all">全部</button><button data-action="status-filter" data-target="schoolTable" data-status="active">启用</button><button data-action="status-filter" data-target="schoolTable" data-status="inactive">停用</button></div></div><div class="table-scroll"><table id="schoolTable"><thead><tr><th>学校</th><th>学校代码</th><th>地址</th><th>班级</th><th>管理员</th><th>考生</th><th>考点</th><th>状态</th><th>操作</th></tr></thead><tbody>${schools.map(item => `<tr data-status="${item.active ? 'active' : 'inactive'}"><td><strong>${h(item.name)}</strong><small>${h(item.id)}</small></td><td class="mono"><strong>${h(item.code)}</strong></td><td>${h(item.address || '未填写')}</td><td>${item.classCount}</td><td>${item.adminCount}</td><td>${item.candidateCount}</td><td>${item.centerCount}</td><td>${badge(item.active ? 'approved' : 'closed')}</td><td><div class="candidate-account-actions"><button class="row-action" data-action="edit-school" data-id="${h(item.id)}">编辑</button><button class="row-action" data-action="toggle-school" data-id="${h(item.id)}" data-active="${item.active ? 'false' : 'true'}">${item.active ? '停用' : '启用'}</button></div></td></tr>`).join('') || '<tr><td colspan="9" class="empty-state">还没有学校，请先创建学校档案。</td></tr>'}</tbody></table></div></section>`;
  }
  
  function adminSchoolsV2(data) {
    const schools = data.schools || [];
    const schoolPage = paged(schools, 'schoolTable', 20);
    const sourceCount = schools.filter(item => item.active && item.isSourceSchool).length;
    const admissionCount = schools.filter(item => item.active && item.isAdmissionSchool).length;
    const roles = item => `${item.isSourceSchool ? '<span class="school-role source">生源校</span>' : ''}${item.isAdmissionSchool ? '<span class="school-role admission">招生校</span>' : ''}`;
    return `<section class="center-summary school-type-summary"><div><span>学校总数</span><strong>${schools.length}</strong></div><div><span>启用生源校</span><strong>${sourceCount}</strong></div><div><span>启用招生校</span><strong>${admissionCount}</strong></div><div><span>在册考生</span><strong>${schools.reduce((sum, item) => sum + item.candidateCount, 0)}</strong></div></section><section class="panel data-panel"><div class="data-toolbar"><label class="search-box">${icons.search}<input data-action="table-search" data-target="schoolTable" placeholder="搜索学校名称、代码、类型或地址"></label><div class="filter-pills"><button class="active" data-action="status-filter" data-target="schoolTable" data-status="all">全部</button><button data-action="status-filter" data-target="schoolTable" data-status="active">启用</button><button data-action="status-filter" data-target="schoolTable" data-status="inactive">停用</button></div></div><div class="table-scroll"><table id="schoolTable"><thead><tr><th>学校 / 代码</th><th>学校类型</th><th>地址</th><th>班级</th><th>管理员</th><th>考生</th><th>考点</th><th>状态</th><th>操作</th></tr></thead><tbody>${schoolPage.items.map(item => `<tr data-status="${item.active ? 'active' : 'inactive'}"><td><strong>${h(item.name)}</strong><small class="mono">${h(item.code)}</small></td><td><div class="school-role-tags">${roles(item)}</div></td><td>${h(item.address || '未填写')}</td><td>${item.classCount}</td><td>${item.adminCount}</td><td>${item.candidateCount}</td><td>${item.centerCount}</td><td>${badge(item.active ? 'approved' : 'closed')}</td><td><div class="candidate-account-actions"><button class="row-action" data-action="edit-school" data-id="${h(item.id)}">编辑</button><button class="row-action" data-action="toggle-school" data-id="${h(item.id)}" data-active="${item.active ? 'false' : 'true'}">${item.active ? '停用' : '启用'}</button></div></td></tr>`).join('') || '<tr><td colspan="9" class="empty-state">没有符合条件的学校。</td></tr>'}</tbody></table></div>${pagination(schoolPage)}</section>`;
  }

  function adminSchoolOrganization(data) {
    const classes = data.classes || [];
    const activeAdmins = classes.reduce((sum, item) => sum + item.admins.filter(admin => admin.active).length, 0);
    return `<section class="school-org-banner"><div><span>SCHOOL ORGANIZATION</span><h2>${h(data.school?.name)}</h2><p>班级决定考生、报名与成绩的可见范围；一个班级可以配置多名班级管理员。</p></div><dl><div><dt>班级</dt><dd>${classes.length}</dd></div><div><dt>班级管理员</dt><dd>${activeAdmins}</dd></div><div><dt>在册考生</dt><dd>${classes.reduce((sum, item) => sum + item.candidateCount, 0)}</dd></div></dl></section>${excelToolbar('classes', { label: '班级台账' })}${excelToolbar('class_admins', { label: '班级管理员' })}<section class="org-class-grid">${classes.map(item => `<article class="panel org-class-card ${item.active ? '' : 'inactive'}"><header><div><span>${h(item.grade)}</span><h2>${h(item.name)}</h2></div>${badge(item.active ? 'approved' : 'closed')}</header><div class="org-class-metrics"><span><strong>${item.candidateCount}</strong><small>在册考生</small></span><span><strong>${item.admins.length}</strong><small>管理员</small></span></div><section><div class="org-admin-head"><strong>班级管理员</strong><button class="row-action" data-action="new-class-admin" data-class-id="${h(item.id)}">添加管理员</button></div>${item.admins.map(admin => `<button class="org-admin-row" data-action="edit-class-admin" data-id="${h(admin.id)}" data-class-id="${h(item.id)}"><span class="user-avatar">${h(admin.displayName.slice(0,1))}</span><span><strong>${h(admin.displayName)}</strong><small class="mono">${h(admin.username)}</small></span>${badge(admin.active ? 'approved' : 'closed')}</button>`).join('') || '<p class="org-empty">尚未配置班级管理员</p>'}</section><footer><button class="row-action" data-action="edit-school-class" data-id="${h(item.id)}">编辑班级</button><button class="row-action" data-action="toggle-school-class" data-id="${h(item.id)}" data-active="${item.active ? 'false' : 'true'}">${item.active ? '停用班级' : '重新启用'}</button></footer></article>`).join('') || emptyState('还没有班级', '点击“新增班级”建立本校组织范围。')}</section>`;
  }
  
  function adminCandidates(data) {
    const allCandidates = data.candidates || [];
    const candidatePage = paged(allCandidates, 'candidateTable');
    const candidates = candidatePage.items;
    const canReview = state.user.adminLevel === 'super' || state.permissions?.includes('candidates.review');
    const classById = new Map((data.classes || []).map(item => [item.id, item]));
    const optionList = getter => [...new Set(allCandidates.map(getter).filter(Boolean))]
      .sort((left, right) => left.localeCompare(right, 'zh-CN'))
      .map(value => `<option value="${h(value)}">${h(value)}</option>`).join('');
    const archiveConsole = state.user.adminLevel === 'school' ? (() => {
      const classes = data.classes || [];
      const grades = [...new Set(classes.map(item => item.grade))];
      return `<section class="panel candidate-archive-console"><div><span>SCHOOL ACCOUNT ARCHIVE</span><h2>按班级或年级归档账户</h2><p>归档只冻结登录，不删除考生、报名、准考证、成绩和审计记录；可随时按相同范围恢复。</p></div><div class="archive-controls"><select data-archive-scope><option value="">请选择范围</option><optgroup label="按班级">${classes.map(item => `<option value="class:${h(item.id)}">${h(item.grade)} · ${h(item.name)}</option>`).join('')}</optgroup><optgroup label="按年级">${grades.map(grade => `<option value="grade:${h(grade)}">${h(grade)}全部班级</option>`).join('')}</optgroup></select><button class="ghost-button" data-action="candidate-archive" data-archived="false">恢复账户</button><button class="solid-button archive-button" data-action="candidate-archive" data-archived="true">归档账户</button></div></section>`;
    })() : '';
    const rows = candidates.map(item => {
      const schoolClass = classById.get(item.classId);
      const grade = schoolClass?.grade || '';
      const className = schoolClass?.name || item.grade || '';
      const exams = item.registrations || [];
      const canSelect = canReview && item.profileCompleted && !item.accountArchived && item.status === 'pending' && item.workflow?.status === 'pending'
        && (state.user.adminLevel === 'super' || item.workflow?.assignee?.id === state.user.id);
      const examNames = exams.map(registration => registration.exam?.name).filter(Boolean);
      return `<tr class="${item.accountArchived ? 'account-archived-row' : ''}" data-filter-row data-status="${h(item.status)} ${item.accountArchived ? 'archived' : 'active'}" data-school="${h(item.school || '')}" data-grade="${h(grade)}" data-class="${h(className)}" data-exam="${h(examNames.join('|'))}"><td class="selection-cell"><input type="checkbox" data-candidate-select value="${h(item.id)}" aria-label="选择 ${h(item.name)}" ${canSelect ? '' : 'disabled'}></td><td><div class="person-cell"><span>${h(item.name.slice(0,1))}</span><div><strong>${h(item.name)}</strong><small class="mono">${h(item.candidateNumber || '待分配')}</small></div></div></td><td class="mono">${h(item.idNumberMasked)}</td><td><strong>${h(item.school || '未填写')}</strong><small>${h([grade, className].filter(Boolean).join(' · '))}</small></td><td><div class="candidate-exam-summary">${exams.length ? `<strong>${h(examNames.slice(0, 2).join('、'))}${exams.length > 2 ? ` 等 ${exams.length} 场` : ''}</strong><small>${h(exams.flatMap(registration => registration.subjects || []).map(subject => subject.name).slice(0, 5).join('、') || '尚未选择科目')}</small>` : '<span>暂无考试报名</span>'}</div></td><td><strong>${item.accountArchived ? '已归档' : item.mustChangePassword ? '待首次改密' : item.profileCompleted ? '正常' : '待补全资料'}</strong><small>${item.accountArchived ? `${formatDate(item.archivedAt, true)} · ${h(item.archivedByName || '校方')}` : h(item.workflow?.assignee?.displayName || '')}</small></td><td>${item.profileCompleted ? badge(item.status) : '<span class="onboarding-badge">未完成</span>'}</td><td><div class="candidate-account-actions"><button class="row-action primary" data-action="review-candidate" data-id="${h(item.id)}" ${item.profileCompleted && !item.accountArchived ? '' : 'disabled'}>${item.profileCompleted ? '进入审核页' : '等待考生'}</button>${state.user.adminLevel === 'super' ? `<button class="row-action" data-action="reset-candidate-password" data-id="${h(item.id)}" ${item.accountArchived ? 'disabled' : ''}>重置密码</button>` : ''}</div></td></tr>`;
    }).join('');
    const bulkToolbar = canReview ? `<div class="registration-bulk-bar candidate-bulk-bar"><span>已选择 <strong data-candidate-selection-count>0</strong> 名当前可处理考生</span><div><button class="row-action" data-action="bulk-candidate-review" data-status="rejected" disabled>批量退回修改</button><button class="row-action primary" data-action="bulk-candidate-review" data-status="approved" disabled>批量通过当前步骤</button></div></div>` : '';
    const examOptions = [...new Set(allCandidates.flatMap(item => (item.registrations || []).map(registration => registration.exam?.name).filter(Boolean)))]
      .sort((left, right) => left.localeCompare(right, 'zh-CN'))
      .map(value => `<option value="${h(value)}">${h(value)}</option>`).join('');
    const filters = `<div class="table-filter-selects"><select data-table-filter="school" data-target="candidateTable"><option value="">全部学校</option>${optionList(item => item.school)}</select><select data-table-filter="grade" data-target="candidateTable"><option value="">全部年级</option>${optionList(item => classById.get(item.classId)?.grade)}</select><select data-table-filter="class" data-target="candidateTable"><option value="">全部班级</option>${optionList(item => classById.get(item.classId)?.name || item.grade)}</select><select data-table-filter="exam" data-target="candidateTable"><option value="">全部关联考试</option>${examOptions}</select></div>`;
    return `${archiveConsole}${excelToolbar('candidates', { importable: true, label: '考生资料' })}<section class="panel data-panel candidate-ledger">${bulkToolbar}<div class="data-toolbar candidate-toolbar"><label class="search-box">${icons.search}<input data-action="table-search" data-target="candidateTable" placeholder="跨页搜索报名号、姓名、证件号、考试或学校"></label><div class="filter-pills"><button class="active" data-action="status-filter" data-target="candidateTable" data-status="all">全部</button><button data-action="status-filter" data-target="candidateTable" data-status="pending">待审核</button><button data-action="status-filter" data-target="candidateTable" data-status="approved">已通过</button><button data-action="status-filter" data-target="candidateTable" data-status="rejected">需修改</button><button data-action="status-filter" data-target="candidateTable" data-status="archived">已归档</button></div>${filters}</div><div class="table-scroll"><table id="candidateTable"><thead><tr><th class="selection-cell"><input type="checkbox" data-candidate-select-all data-target="candidateTable" aria-label="全选当前筛选结果"></th><th>报名号 / 考生</th><th>证件号码</th><th>学校 / 年级 / 班级</th><th>关联考试 / 科目</th><th>账户状态</th><th>资料状态</th><th>操作</th></tr></thead><tbody>${rows || '<tr><td colspan="8" class="empty-state">当前范围暂无考生</td></tr>'}</tbody></table></div>${pagination(candidatePage)}</section>`;
  }

  function paged(items, key, defaultPageSize = 50) {
    items = filterTableItems(state, items, key);
    const current = state.tablePages[key] || {};
    const pageSize = [20, 50, 100].includes(Number(current.pageSize)) ? Number(current.pageSize) : defaultPageSize;
    const total = items.length;
    const totalPages = Math.max(1, Math.ceil(total / pageSize));
    const page = Math.min(Math.max(1, Number(current.page) || 1), totalPages);
    state.tablePages[key] = { page, pageSize };
    return { items: items.slice((page - 1) * pageSize, page * pageSize), page, pageSize, total, totalPages, key };
  }

  function pagination(meta) {
    if (!meta || meta.total <= meta.pageSize) return '';
    const start = (meta.page - 1) * meta.pageSize + 1;
    const end = Math.min(meta.total, meta.page * meta.pageSize);
    const pages = [...new Set([1, meta.page - 1, meta.page, meta.page + 1, meta.totalPages])].filter(page => page >= 1 && page <= meta.totalPages);
    return `<nav class="table-pagination" aria-label="列表分页"><span>第 ${start}—${end} 条，共 ${meta.total} 条</span><div><button type="button" data-action="table-page" data-table-key="${h(meta.key)}" data-page="${meta.page - 1}" ${meta.page === 1 ? 'disabled' : ''}>上一页</button>${pages.map((page, index) => `${index && page - pages[index - 1] > 1 ? '<i>…</i>' : ''}<button type="button" class="${page === meta.page ? 'active' : ''}" data-action="table-page" data-table-key="${h(meta.key)}" data-page="${page}">${page}</button>`).join('')}<button type="button" data-action="table-page" data-table-key="${h(meta.key)}" data-page="${meta.page + 1}" ${meta.page === meta.totalPages ? 'disabled' : ''}>下一页</button><label>每页 <select data-action="table-page-size" data-table-key="${h(meta.key)}">${[20, 50, 100].map(size => `<option value="${size}" ${size === meta.pageSize ? 'selected' : ''}>${size}</option>`).join('')}</select> 条</label></div></nav>`;
  }
  
  function adminRegistrations(registrations) {
    const isSuper = state.user.adminLevel === 'super';
    const canReview = state.user.adminLevel === 'super' || state.permissions?.includes('registrations.review');
    const optionList = (getter) => [...new Set(registrations.map(getter).filter(Boolean))]
      .sort((left, right) => left.localeCompare(right, 'zh-CN'))
      .map(value => `<option value="${h(value)}">${h(value)}</option>`).join('');
    const rows = (items, selectable = false) => items.map(reg => {
      const canSelect = selectable && reg.status === 'pending' && reg.workflow?.status === 'pending'
        && (isSuper || reg.workflow?.assignee?.id === state.user.id);
      return `<tr data-filter-row data-status="${h(reg.status)}" data-exam="${h(reg.exam?.name || '')}" data-subject="${h(reg.subjects.map(subject => subject.name).join('|'))}" data-school="${h(reg.schoolName || '')}" data-grade="${h(reg.gradeName || '')}" data-class="${h(reg.className || '')}">${selectable ? `<td class="selection-cell"><input type="checkbox" data-registration-select value="${h(reg.id)}" aria-label="选择 ${h(reg.candidate?.name || '考生')}" ${canSelect ? '' : 'disabled'}></td>` : ''}<td><div class="person-cell"><span>${h((reg.candidate?.name || '?').slice(0,1))}</span><div><strong>${h(reg.candidate?.name)}</strong><small>${h([reg.schoolName, reg.gradeName, reg.className].filter(Boolean).join(' · '))}</small></div></div></td><td><div class="registration-exam-cell"><strong>${h(reg.exam.name)}</strong><div class="subject-summary">${reg.subjects.map(subject => `<span>${h(subject.name)}</span>`).join('') || '<em>未选择科目</em>'}</div><small>${h(reg.subjects.length)} 科 · ${money(reg.amountDue || 0)}</small></div></td><td class="mono"><strong>${h(reg.registrationNumber || '待同步账户号码')}</strong><small>各次考试保持一致</small></td><td><strong>${h(reg.workflow?.currentStepDetail?.name || '流程已结束')}</strong><small>${h(reg.workflow?.assignee?.displayName || '')}</small></td><td>${badge(reg.paymentStatus)}</td><td>${badge(reg.exam.archivedAt ? 'archived' : reg.status)}</td><td>${reg.exam.archivedAt ? '<span class="archive-readonly-label">只读封存</span>' : `<button class="row-action primary" data-action="review-registration" data-id="${h(reg.id)}">进入审核页</button>`}</td></tr>`;
    }).join('');
    const table = (items, id, selectable = false) => `<div class="table-scroll"><table id="${id}"><thead><tr>${selectable ? '<th class="selection-cell"><input type="checkbox" data-registration-select-all data-target="registrationTable" aria-label="全选当前筛选结果"></th>' : ''}<th>考生</th><th>考试 / 科目</th><th>账户报名号</th><th>当前流程</th><th>缴费</th><th>状态</th><th>操作</th></tr></thead><tbody>${rows(items, selectable) || `<tr><td colspan="${selectable ? 8 : 7}" class="empty-state">当前范围暂无报名记录</td></tr>`}</tbody></table></div>`;
    const allCurrent = registrations.filter(reg => !reg.exam.archivedAt);
    const allArchived = registrations.filter(reg => reg.exam.archivedAt);
    const currentPage = paged(allCurrent, 'registrationTable');
    const archivedPage = paged(allArchived, 'archivedRegistrationTable');
    const current = currentPage.items;
    const archived = archivedPage.items;
    const subjectOptions = [...new Set(registrations.flatMap(item => item.subjects.map(subject => subject.name)))].sort((left, right) => left.localeCompare(right, 'zh-CN')).map(value => `<option value="${h(value)}">${h(value)}</option>`).join('');
    const bulkToolbar = canReview ? `<div class="registration-bulk-bar"><span>已选择 <strong data-registration-selection-count>0</strong> 条当前可处理报名</span><div><button class="row-action" data-action="bulk-registration-review" data-status="rejected" disabled>批量退回</button><button class="row-action primary" data-action="bulk-registration-review" data-status="approved" disabled>批量通过当前步骤</button></div></div>` : '';
    return `<section class="panel data-panel registration-ledger">${bulkToolbar}<div class="data-toolbar registration-toolbar"><label class="search-box">${icons.search}<input data-action="table-search" data-target="registrationTable" placeholder="跨页搜索考生、考试、科目、固定报名号"></label><div class="filter-pills"><button class="active" data-action="status-filter" data-target="registrationTable" data-status="all">全部</button><button data-action="status-filter" data-target="registrationTable" data-status="pending">待审核</button><button data-action="status-filter" data-target="registrationTable" data-status="approved">已通过</button><button data-action="status-filter" data-target="registrationTable" data-status="rejected">已退回</button></div><div class="table-filter-selects five-columns"><select data-table-filter="exam" data-target="registrationTable"><option value="">全部考试</option>${optionList(item => item.exam?.name)}</select><select data-table-filter="subject" data-target="registrationTable"><option value="">全部科目</option>${subjectOptions}</select><select data-table-filter="school" data-target="registrationTable"><option value="">全部学校</option>${optionList(item => item.schoolName)}</select><select data-table-filter="grade" data-target="registrationTable"><option value="">全部年级</option>${optionList(item => item.gradeName)}</select><select data-table-filter="class" data-target="registrationTable"><option value="">全部班级</option>${optionList(item => item.className)}</select></div></div>${table(current, 'registrationTable', Boolean(canReview))}${pagination(currentPage)}</section>${allArchived.length ? `<details class="candidate-archive-fold admin-registration-archive"><summary><span><strong>归档考试报名记录</strong><small>${allArchived.length} 条 · 流程与报名信息已冻结</small></span><b>${allArchived.length}</b></summary><div class="data-toolbar"><label class="search-box">${icons.search}<input data-action="table-search" data-target="archivedRegistrationTable" placeholder="跨页搜索归档考生、考试、科目或报名号"></label><div class="filter-pills"><button class="active" data-action="status-filter" data-target="archivedRegistrationTable" data-status="all">全部</button><button data-action="status-filter" data-target="archivedRegistrationTable" data-status="approved">已通过</button><button data-action="status-filter" data-target="archivedRegistrationTable" data-status="rejected">已退回</button><button data-action="status-filter" data-target="archivedRegistrationTable" data-status="pending">待审核</button></div></div>${table(archived, 'archivedRegistrationTable')}${pagination(archivedPage)}</details>` : ''}`;
  }

  function adminPayments(data) {
    const allRegistrations = data.registrations || [];
    const paymentPage = paged(allRegistrations, 'paymentTable');
    const registrations = paymentPage.items;
    const paid = allRegistrations.filter(item => item.paymentStatus === 'paid');
    const unpaid = allRegistrations.filter(item => item.paymentStatus === 'unpaid');
    const totalDue = allRegistrations.reduce((sum, item) => sum + Number(item.amountDue || 0), 0);
    const totalPaid = paid.reduce((sum, item) => sum + Number(item.amountDue || 0), 0);
    const optionList = (getter) => [...new Set(allRegistrations.map(getter).filter(Boolean))]
      .sort((left, right) => left.localeCompare(right, 'zh-CN'))
      .map(value => `<option value="${h(value)}">${h(value)}</option>`).join('');
    const rows = registrations.map(item => `<tr data-filter-row data-status="${h(item.paymentStatus)}" data-exam="${h(item.exam?.name || '')}" data-school="${h(item.schoolName || '')}" data-grade="${h(item.gradeName || '')}" data-class="${h(item.className || '')}">${data.canUpdatePayment ? `<td class="selection-cell"><input type="checkbox" data-payment-select value="${h(item.id)}" data-status="${h(item.paymentStatus)}" aria-label="选择 ${h(item.candidate?.name || '考生')}" ${item.exam?.archivedAt ? 'disabled' : ''}></td>` : ''}<td><div class="person-cell"><span>${h((item.candidate?.name || '?').slice(0, 1))}</span><div><strong>${h(item.candidate?.name || '未知考生')}</strong><small class="mono">${h(item.registrationNumber || '')}</small></div></div></td><td><strong>${h(item.schoolName)}</strong><small>${h([item.gradeName, item.className].filter(Boolean).join(' · '))}</small></td><td><strong>${h(item.exam?.name || '')}</strong><div class="subject-summary">${item.subjects.map(subject => `<span>${h(subject.name)}</span>`).join('')}</div></td><td><strong>${money(item.amountDue || 0)}</strong></td><td>${badge(item.paymentStatus)}</td><td>${item.paidAt ? `<strong>${formatDate(item.paidAt, true)}</strong><small>${h(item.paidByName || '管理员')}</small>` : '<span>—</span>'}</td><td>${data.canUpdatePayment && !item.exam?.archivedAt ? `<button class="row-action ${item.paymentStatus === 'unpaid' ? 'primary' : 'danger'}" data-action="update-payment" data-id="${h(item.id)}" data-name="${h(item.candidate?.name || '')}" data-exam="${h(item.exam?.name || '')}" data-status="${item.paymentStatus === 'paid' ? 'unpaid' : 'paid'}">${item.paymentStatus === 'paid' ? '改为待缴费' : '标记已缴费'}</button>` : item.exam?.archivedAt ? '<span class="archive-readonly-label">只读封存</span>' : '<span>—</span>'}</td></tr>`).join('');
    const filters = `<div class="table-filter-selects"><select data-table-filter="exam" data-target="paymentTable"><option value="">全部考试</option>${optionList(item => item.exam?.name)}</select><select data-table-filter="school" data-target="paymentTable"><option value="">全部学校</option>${optionList(item => item.schoolName)}</select><select data-table-filter="grade" data-target="paymentTable"><option value="">全部年级</option>${optionList(item => item.gradeName)}</select><select data-table-filter="class" data-target="paymentTable"><option value="">全部班级</option>${optionList(item => item.className)}</select></div>`;
    const bulkToolbar = data.canUpdatePayment ? `<div class="registration-bulk-bar payment-bulk-bar"><span>已选择 <strong data-payment-selection-count>0</strong> 条缴费记录</span><div><button class="row-action" data-action="bulk-payment-update" data-status="unpaid" disabled>批量改为待缴费</button><button class="row-action primary" data-action="bulk-payment-update" data-status="paid" disabled>批量标记已缴费</button></div></div>` : '';
    return `${excelToolbar('payments', { importable: false, template: false, label: '缴费名单' })}<section class="center-summary payment-summary"><div><span>报名人数</span><strong>${allRegistrations.length}</strong></div><div><span>待确认</span><strong>${unpaid.length}</strong></div><div><span>已缴费</span><strong>${paid.length}</strong></div><div><span>应缴合计</span><strong>${money(totalDue)}</strong></div><div><span>已缴合计</span><strong>${money(totalPaid)}</strong></div></section><section class="panel data-panel payment-ledger">${bulkToolbar}<div class="data-toolbar payment-toolbar"><label class="search-box">${icons.search}<input data-action="table-search" data-target="paymentTable" placeholder="跨页搜索考生、报名号、考试、科目、学校或班级"></label><div class="filter-pills"><button class="active" data-action="status-filter" data-target="paymentTable" data-status="all">全部</button><button data-action="status-filter" data-target="paymentTable" data-status="unpaid">待缴费</button><button data-action="status-filter" data-target="paymentTable" data-status="paid">已缴费</button></div>${filters}</div><div class="table-scroll"><table id="paymentTable"><thead><tr>${data.canUpdatePayment ? '<th class="selection-cell"><input type="checkbox" data-payment-select-all data-target="paymentTable" aria-label="全选当前筛选结果"></th>' : ''}<th>考生 / 报名号</th><th>学校 / 年级 / 班级</th><th>考试 / 科目</th><th>应缴金额</th><th>缴费状态</th><th>确认记录</th><th>操作</th></tr></thead><tbody>${rows || `<tr><td colspan="${data.canUpdatePayment ? 8 : 7}" class="empty-state">当前范围暂无已审核通过的报名</td></tr>`}</tbody></table></div>${pagination(paymentPage)}</section>`;
  }
  
  function adminExams(exams) {
    const active = exams.filter(exam => !exam.archivedAt);
    const archived = exams.filter(exam => exam.archivedAt).sort((left, right) => new Date(right.archivedAt) - new Date(left.archivedAt));
    const card = exam => `<article class="admin-exam-card ${exam.archivedAt ? 'archived' : exam.status}${exam.status === 'draft' && !exam.archivedAt ? ' editable' : ''}" ${exam.status === 'draft' && !exam.archivedAt ? `data-action="edit-exam" data-id="${h(exam.id)}" title="点击编辑草稿"` : ''}><header><span class="exam-code">${h(exam.code)}</span>${badge(exam.archivedAt ? 'archived' : exam.status)}</header><h2>${h(exam.name)}</h2><p>${h(exam.description)}</p><div class="exam-score-band"><span><small>考试总分</small><strong>${h(exam.totalScore)}</strong><em>分</em></span><span><small>合格规则</small><b>${h(passPolicyText(exam))}</b></span></div><dl><div><dt>报名时间</dt><dd>${dateRange(exam.registrationStart, exam.registrationEnd)}</dd></div><div><dt>考试时间</dt><dd>${dateRange(exam.examStart, exam.examEnd)}</dd></div><div><dt>考点</dt><dd>${h(exam.location)}</dd></div></dl><div class="admin-subjects">${exam.subjects.map(subject => `<span><b>${h(subject.name)}</b><small>${h(subject.date)} ${h(subject.start)} · 满分 ${h(subject.fullScore)} · ${subject.passRule === 'none' ? '不设单科线' : subject.passRule === 'rank_percent' ? `本科排名前 ${h(subject.passValue)}%` : `固定 ${h(subject.passScore)} 分`}</small></span>`).join('') || '<span>科目待配置</span>'}</div><footer><span>${exam.archivedAt ? `${formatDate(exam.archivedAt, true)} 归档 · 成绩永久锁定` : `${exam.registrationCount} 人报名 · ${exam.subjects.length} 科`}</span>${exam.archivedAt ? '' : `<div class="exam-card-actions">${exam.status === 'draft' ? `<button class="row-action" data-action="edit-exam" data-id="${h(exam.id)}">编辑草稿</button>` : ''}<button class="row-action" data-action="toggle-exam" data-id="${h(exam.id)}" data-status="${exam.status === 'published' ? 'draft' : 'published'}">${exam.status === 'published' ? '撤回为草稿' : '发布考试'}</button><button class="row-action archive-exam-action" data-action="archive-exam" data-id="${h(exam.id)}" data-name="${h(exam.name)}">归档并锁定</button></div>`}</footer></article>`;
    const archiveShelf = archived.length ? `<details class="exam-archive-shelf"><summary><span><b>历史考试归档</b><small>${archived.length} 场 · 成绩永久锁定，点击按需查阅</small></span><strong>${archived.length}</strong></summary><div class="admin-exam-grid archived-exam-grid">${archived.map(card).join('')}</div></details>` : '';
    return `<div class="admin-exam-grid">${active.map(card).join('') || emptyState('没有进行中的考试', '新建考试，或在下方查阅已归档历史。')}</div>${archiveShelf}`;
  }
  
  function adminAdmissions(data) {
    const selected = data.settings.find(item => item.status !== 'completed') || data.settings[0];
    const pendingPlans = data.plans.filter(item => item.status === 'pending');
    const withdrawals = data.placements.filter(item => item.status === 'withdrawal_pending');
    const phaseLabels = { draft: '草稿', filling: '志愿填报中', closed: '填报已截止' };
    if (selected && !phaseLabels[selected.status]) phaseLabels[selected.status] = { matching: '投档中', school_review: '学校审核中', supplementary: '补录填报中', completed: '录取完成' }[selected.status] || selected.status;
    return `<section class="admission-command-banner"><div><span>ADMISSION COMMAND</span><h2>中考招生录取控制台</h2><p>志愿内容仅超级管理员可见且不可代改；投档和录取状态变更均进入审计日志。</p></div><dl><div><dt>待审计划</dt><dd>${pendingPlans.length}</dd></div><div><dt>学校审核中</dt><dd>${data.placements.filter(item => item.status === 'school_review').length}</dd></div><div><dt>退档待审</dt><dd>${withdrawals.length}</dd></div><div><dt>正式录取</dt><dd>${data.placements.filter(item => item.status === 'final').length}</dd></div></dl></section><div class="admission-admin-grid"><section class="panel admission-settings-panel"><div class="panel-title"><div><h2>考试志愿设置</h2><p>不是所有考试都需要开启。</p></div></div><form data-form="admission-setting"><label><span>考试 *</span><select name="examId" required>${data.exams.map(exam => `<option value="${h(exam.id)}" ${exam.id === selected?.examId ? 'selected' : ''}>${h(exam.name)}</option>`).join('')}</select></label><div class="field-row"><label><span>填报开始</span><input name="preferenceStart" type="datetime-local" value="${h(selected?.payload?.preferenceStart?.slice(0,16))}"></label><label><span>填报结束</span><input name="preferenceEnd" type="datetime-local" value="${h(selected?.payload?.preferenceEnd?.slice(0,16))}"></label></div><div class="field-row"><label><span>当前阶段</span><select name="status">${Object.entries(phaseLabels).map(([value,label]) => `<option value="${value}" ${value === (selected?.status || 'draft') ? 'selected' : ''}>${label}</option>`).join('')}</select></label><label><span>最多志愿数</span><input name="maxChoices" type="number" min="1" max="20" value="${h(selected?.payload?.maxChoices || 5)}"></label></div><label><span>考生进度说明</span><input name="progress" value="${h(selected?.payload?.progress || '')}" placeholder="例如：招生学校正在审核投档名单"></label><label class="agreement"><input type="checkbox" name="enabled" ${selected?.payload?.enabled ? 'checked' : ''}><span>为本场考试启用志愿填报</span></label><label class="agreement"><input type="checkbox" name="autoPublish" ${selected?.payload?.autoPublish === false ? '' : 'checked'}><span>录取结束后自动脱敏公示</span></label><button class="solid-button" type="submit">保存志愿设置</button></form>${selected ? `<div class="admission-control-actions"><button class="solid-button" data-action="admission-match" data-exam-id="${h(selected.examId)}">按规则投档</button><button class="ghost-button" data-action="admission-finalize" data-exam-id="${h(selected.examId)}">结束录取并通知</button><button class="ghost-button" data-action="admission-supplementary" data-exam-id="${h(selected.examId)}">开启补录</button></div>` : ''}</section><section class="panel admission-account-panel"><div class="panel-title"><div><h2>招生学校账号</h2><p>账号只能查看本校投档名单和本校计划。</p></div><span>${data.schoolAccounts.length} 个</span></div><form data-form="admission-account"><label><span>招生学校 *</span><select name="schoolId" required>${data.schools.map(school => `<option value="${h(school.id)}">${h(school.name)}</option>`).join('')}</select></label><div class="field-row"><label><span>登录账号 *</span><input name="username" required></label><label><span>初始密码 *</span><input name="password" type="password" minlength="8" required></label></div><label><span>显示名称</span><input name="displayName" placeholder="学校招生办公室"></label><button class="solid-button" type="submit">创建招生学校账号</button></form></section></div><section class="panel admission-plan-console"><div class="panel-title"><div><h2>代上传招生计划</h2><p>每行格式：类别名称 | 计划人数 | 特长类型（普通生留空）。指标分配可由招生学校提交后审核。</p></div></div><form data-form="admission-plan"><div class="field-row"><label><span>考试 *</span><select name="examId">${data.exams.map(exam => `<option value="${h(exam.id)}">${h(exam.name)}</option>`).join('')}</select></label><label><span>招生学校 *</span><select name="schoolId">${data.schools.map(school => `<option value="${h(school.id)}">${h(school.name)}</option>`).join('')}</select></label></div><label><span>招生类别与计划 *</span><textarea name="categoriesText" rows="4" required placeholder="普通生 | 120 |&#10;体育特长生 | 8 | 田径"></textarea></label><button class="solid-button" type="submit">代上传并审核通过</button></form></section><section class="panel data-panel"><div class="panel-title"><h2>招生计划审核</h2><span>${pendingPlans.length} 份待审</span></div><div class="table-scroll"><table><thead><tr><th>考试 / 学校</th><th>计划构成</th><th>提交人</th><th>状态</th><th>操作</th></tr></thead><tbody>${data.plans.map(plan => `<tr><td><strong>${h(plan.examName)}</strong><small>${h(plan.schoolName)}</small></td><td>${plan.payload.categories.map(category => `${h(category.name)} ${h(category.quota)} 人${category.specialtyType ? ` · ${h(category.specialtyType)}` : ''}`).join('<br>')}</td><td>${h(plan.payload.submittedBy || '超级管理员')}</td><td>${badge(plan.status)}</td><td>${plan.status === 'pending' ? `<button class="row-action primary" data-action="admission-plan-review" data-id="${h(plan.id)}" data-status="approved">通过</button><button class="row-action" data-action="admission-plan-review" data-id="${h(plan.id)}" data-status="rejected">退回</button>` : h(plan.payload.reviewNote || '')}</td></tr>`).join('') || '<tr><td colspan="5" class="empty-state">暂无招生计划</td></tr>'}</tbody></table></div></section><section class="panel data-panel"><div class="panel-title"><h2>投档与退档监督</h2><span>超级管理员可见，任何管理员均不能修改考生志愿</span></div><div class="table-scroll"><table><thead><tr><th>考生</th><th>成绩 / 志愿</th><th>投档学校</th><th>类别</th><th>状态</th><th>退档审核</th></tr></thead><tbody>${data.placements.map(item => `<tr><td><strong>${h(item.candidate.name)}</strong><small class="mono">${h(item.candidate.registrationNumber)}</small></td><td>${h(item.payload.totalScore)} 分 · 第 ${h(item.payload.preferenceOrder)} 志愿</td><td>${h(item.schoolName)}</td><td>${h(item.payload.categoryName)}</td><td>${badge(item.status)}</td><td>${item.status === 'withdrawal_pending' ? `<small>${h(item.payload.withdrawalReason)}</small><button class="row-action primary" data-action="withdrawal-review" data-id="${h(item.id)}" data-approved="true">批准</button><button class="row-action" data-action="withdrawal-review" data-id="${h(item.id)}" data-approved="false">驳回</button>` : '—'}</td></tr>`).join('') || '<tr><td colspan="6" class="empty-state">尚未产生投档记录</td></tr>'}</tbody></table></div></section>`;
  }

  function adminAdmissionsV2(data, section = 'settings') {
    const selected = data.settings.find(item => item.status !== 'completed') || data.settings[0];
    const pendingPlans = data.plans.filter(item => item.status === 'pending');
    const withdrawals = data.placements.filter(item => item.status === 'withdrawal_pending');
    const phaseLabels = { draft: '草稿', filling: '志愿填报中', closed: '填报已截止', matching: '投档中', school_review: '学校审核中', reporting: '考生报到中', supplementary: '补录填报中', completed: '录取完成' };
    const accountPage = paged(data.schoolAccounts, 'admissionAccountTable', 20);
    const planPage = paged(data.plans, 'adminAdmissionPlanTable', 20);
    const placementPage = paged(data.placements, 'adminPlacementTable');
    const preferenceSnapshots = data.preferenceRows || [];
    const preferenceSnapshotPanel = `<section class="panel admission-snapshot-console"><div class="panel-title"><div><h2>志愿填报实时快照</h2><p>不受填报阶段限制，可随时导出当前轮次全部考生的填报、未填报与锁定情况。</p></div><span>${preferenceSnapshots.length} 人</span></div><div class="snapshot-ledger-grid">${data.settings.filter(item => item.payload?.enabled).map(setting => {
      const exam = data.exams.find(item => item.id === setting.examId) || {};
      const round = Number(setting.payload?.round || 1);
      const rows = preferenceSnapshots.filter(item => item.examId === setting.examId && Number(item.round) === round);
      return `<article><div><span>${h(exam.code || 'EXAM')}</span><h3>${h(exam.name || setting.examId)}</h3><p>第 ${h(round)} 轮 · ${h(phaseLabels[setting.status] || setting.status)}</p></div><dl><div><dt>全部考生</dt><dd>${rows.length}</dd></div><div><dt>尚未填报</dt><dd>${rows.filter(item => item.status === 'unfilled').length}</dd></div><div><dt>已填报</dt><dd>${rows.filter(item => ['submitted', 'locked'].includes(item.status)).length}</dd></div><div><dt>已锁定</dt><dd>${rows.filter(item => item.status === 'locked').length}</dd></div></dl><button class="row-action primary" data-action="admission-ledger-export" data-ledger="preferences" data-exam-id="${h(setting.examId)}" data-round="${h(round)}">导出本轮填报情况</button></article>`;
    }).join('') || '<p class="empty-state">启用志愿填报后，可在这里随时导出实时台账。</p>'}</div></section>`;
    const settings = `<section class="panel admission-settings-panel"><div class="panel-title"><div><h2>考试志愿设置</h2><p>成绩发布后按场次开放，并持续向考生展示录取进度。</p></div></div><form data-form="admission-setting"><label><span>考试 *</span><select name="examId" required>${data.exams.map(exam => `<option value="${h(exam.id)}" ${exam.id === selected?.examId ? 'selected' : ''}>${h(exam.name)}</option>`).join('')}</select></label><div class="field-row"><label><span>填报开始</span><input name="preferenceStart" type="datetime-local" value="${h(selected?.payload?.preferenceStart?.slice(0,16))}"></label><label><span>填报结束</span><input name="preferenceEnd" type="datetime-local" value="${h(selected?.payload?.preferenceEnd?.slice(0,16))}"></label></div><div class="field-row"><label><span>当前阶段</span><select name="status">${Object.entries(phaseLabels).map(([value,label]) => `<option value="${value}" ${value === (selected?.status || 'draft') ? 'selected' : ''}>${label}</option>`).join('')}</select></label><label><span>普通志愿数</span><input name="maxChoices" type="number" min="1" max="20" value="${h(selected?.payload?.maxChoices || 5)}"></label></div><div class="field-row"><label><span>最多提交次数</span><input name="maxSubmissions" type="number" min="1" max="50" value="${h(selected?.payload?.maxSubmissions || 3)}"><small>首次保存也计 1 次；达到上限自动锁定。</small></label><label><span>考生进度说明</span><input name="progress" value="${h(selected?.payload?.progress || '')}" placeholder="例如：招生学校正在审核投档名单"></label></div><label class="agreement"><input type="checkbox" name="enabled" ${selected?.payload?.enabled ? 'checked' : ''}><span>为本场考试启用志愿填报</span></label><label class="agreement"><input type="checkbox" name="autoPublish" ${selected?.payload?.autoPublish === false ? '' : 'checked'}><span>录取结束后自动脱敏公示录取结果与分数线</span></label><button class="solid-button" type="submit">保存志愿设置</button></form>${selected ? `<div class="admission-control-actions"><button class="solid-button" data-action="admission-match" data-exam-id="${h(selected.examId)}">按规则投档</button><button class="ghost-button" data-action="admission-finalize" data-exam-id="${h(selected.examId)}">签发通知书并开启报到</button></div><small class="workflow-hint">补录不能手工开启，必须由招生学校提交报到情况和补录决定，并经超级管理员审批。</small>` : ''}</section>`;
    const accountRows = accountPage.items.map(account => `<tr data-status="${account.active ? 'active' : 'disabled'}" data-school="${h(account.schoolId)}"><td><div class="person-cell"><span>${h((account.displayName || '招').slice(0, 1))}</span><div><strong>${h(account.displayName)}</strong><small>${h(account.id)}</small></div></div></td><td><strong class="mono">${h(account.username)}</strong></td><td><strong>${h(account.schoolName || '未绑定')}</strong><small class="mono">${h(account.schoolCode || '')}</small></td><td><span class="status status-${account.active ? 'approved' : 'closed'}">${account.active ? '已启用' : '已停用'}</span></td><td>${formatDate(account.createdAt, true)}</td><td><div class="admin-account-actions"><button class="row-action" data-action="reset-admission-account-password" data-id="${h(account.id)}">重置密码</button><button class="row-action ${account.active ? 'danger' : 'primary'}" data-action="toggle-admission-account" data-id="${h(account.id)}" data-active="${account.active ? 'false' : 'true'}">${account.active ? '停用账户' : '重新启用'}</button></div></td></tr>`).join('');
    const accounts = `<section class="panel admission-account-panel admission-account-management"><div class="panel-title"><div><h2>招生学校账户管理</h2><p>创建并维护各招生学校登录账户；停用会立即结束该账户现有会话。</p></div><span>${data.schoolAccounts.filter(item => item.active).length} 个启用 / 共 ${data.schoolAccounts.length} 个</span></div><form data-form="admission-account"><label><span>招生学校 *</span><select name="schoolId" required>${data.admissionSchools.map(school => `<option value="${h(school.id)}">${h(school.code)} · ${h(school.name)}</option>`).join('')}</select></label><div class="field-row"><label><span>登录账号 *</span><input name="username" required></label><label><span>初始密码 *</span><input name="password" type="password" minlength="8" required></label></div><label><span>显示名称</span><input name="displayName" placeholder="学校招生办公室"></label><button class="solid-button" type="submit">创建招生学校账号</button></form><div class="account-management-divider"><strong>已建账户</strong><span>保留历史记录，不提供物理删除</span></div><div class="data-toolbar"><label class="search-box">${icons.search}<input data-action="table-search" data-target="admissionAccountTable" placeholder="跨页搜索学校、账号或显示名称"></label><div class="table-filter-selects"><select data-table-filter="school" data-target="admissionAccountTable"><option value="">全部招生学校</option>${data.admissionSchools.map(school => `<option value="${h(school.id)}">${h(school.name)}</option>`).join('')}</select></div></div><div class="filter-pills account-status-pills"><button type="button" class="active" data-action="status-filter" data-target="admissionAccountTable" data-status="all">全部</button><button type="button" data-action="status-filter" data-target="admissionAccountTable" data-status="active">已启用</button><button type="button" data-action="status-filter" data-target="admissionAccountTable" data-status="disabled">已停用</button></div><div class="table-scroll"><table id="admissionAccountTable"><thead><tr><th>账户</th><th>登录账号</th><th>绑定招生学校</th><th>状态</th><th>创建时间</th><th>账户操作</th></tr></thead><tbody>${accountRows || '<tr><td colspan="6" class="empty-state">还没有招生学校账户</td></tr>'}</tbody></table></div>${pagination(accountPage)}</section>`;
    const planForm = `<section class="panel admission-plan-console structured"><div class="panel-title"><div><h2>代招生校上传计划</h2><p>每个类别独立设置人数、特长资格和生源校指标，保存后直接审核通过。</p></div></div><form data-form="admission-plan"><div class="field-row"><label><span>考试 *</span><select name="examId" required>${data.exams.map(exam => `<option value="${h(exam.id)}">${h(exam.name)}</option>`).join('')}</select></label><label><span>招生学校 *</span><select name="schoolId" required>${data.admissionSchools.map(school => `<option value="${h(school.id)}">${h(school.code)} · ${h(school.name)}</option>`).join('')}</select></label></div>${admissionCategoriesEditor(h, data.sourceSchools)}<label><span>计划说明</span><textarea name="note" rows="2" placeholder="可填写政策依据或补充说明"></textarea></label><button class="solid-button" type="submit">代上传并审核通过</button></form></section>`;
    const plans = `<section class="panel data-panel"><div class="panel-title"><div><h2>招生计划审核与完成率</h2><p>实时核对计划、正式录取和实际报到完成情况。</p></div><span>${pendingPlans.length} 份待审</span></div><div class="data-toolbar"><label class="search-box">${icons.search}<input data-action="table-search" data-target="adminAdmissionPlanTable" placeholder="搜索考试、学校、招生类别或指标学校"></label><div class="filter-pills"><button class="active" data-action="status-filter" data-target="adminAdmissionPlanTable" data-status="all">全部</button><button data-action="status-filter" data-target="adminAdmissionPlanTable" data-status="pending">待审核</button><button data-action="status-filter" data-target="adminAdmissionPlanTable" data-status="approved">已通过</button><button data-action="status-filter" data-target="adminAdmissionPlanTable" data-status="rejected">已退回</button></div></div><div class="table-scroll"><table id="adminAdmissionPlanTable"><thead><tr><th>考试 / 学校</th><th>计划构成</th><th>实时完成率</th><th>指标分配</th><th>状态</th><th>操作</th></tr></thead><tbody>${planPage.items.map(plan => `<tr data-status="${h(plan.status)}"><td><strong>${h(plan.examName)}</strong><small>${h(plan.schoolName)}</small></td><td>${plan.payload.categories.map(category => `<strong>${h(category.name)} ${h(category.quota)} 人</strong><small>${h(specialtyLabel(category.specialtyCategory, category.specialtyType) || '普通 / 政策类')}</small>`).join('')}</td><td><strong>${h(plan.progress?.admissionRate || 0)}%</strong><small>正式录取 ${h(plan.progress?.finalCount || 0)} / ${h(plan.progress?.totalQuota || 0)}</small><small>实际报到 ${h(plan.progress?.reportingRate || 0)}%</small></td><td>${plan.payload.categories.flatMap(category => (category.indicatorAllocations || []).map(allocation => `${h(data.sourceSchools.find(item => item.id === allocation.sourceSchoolId)?.name || allocation.sourceSchoolId)} ${h(allocation.quota)} 人`)).join('<br>') || '无定向指标'}</td><td>${badge(plan.status)}</td><td>${plan.status === 'pending' ? `<button class="row-action primary" data-action="admission-plan-review" data-id="${h(plan.id)}" data-status="approved">通过</button><button class="row-action" data-action="admission-plan-review" data-id="${h(plan.id)}" data-status="rejected">退回</button>` : h(plan.payload.reviewNote || '')}</td></tr>`).join('') || '<tr><td colspan="6" class="empty-state">暂无招生计划</td></tr>'}</tbody></table></div>${pagination(planPage)}</section>`;
    const reportingPage = paged(data.reportingRequests || [], 'adminReportingApprovalTable', 20);
    const reportingApprovals = `<section class="panel data-panel"><div class="panel-title"><div><h2>报到情况与补录审批</h2><p>学校决定审批通过后，统计数据和说明将自动进入公开通知。</p></div><span>${(data.reportingRequests || []).filter(item => item.status === 'pending_approval').length} 项待审批</span></div><div class="data-toolbar"><label class="search-box">${icons.search}<input data-action="table-search" data-target="adminReportingApprovalTable" placeholder="搜索考试、学校、轮次、决定或说明"></label><div class="filter-pills"><button class="active" data-action="status-filter" data-target="adminReportingApprovalTable" data-status="all">全部</button><button data-action="status-filter" data-target="adminReportingApprovalTable" data-status="draft">草稿</button><button data-action="status-filter" data-target="adminReportingApprovalTable" data-status="submitted">已提交</button><button data-action="status-filter" data-target="adminReportingApprovalTable" data-status="pending_approval">待审批</button><button data-action="status-filter" data-target="adminReportingApprovalTable" data-status="approved">已通过</button><button data-action="status-filter" data-target="adminReportingApprovalTable" data-status="rejected">已退回</button></div></div><div class="table-scroll"><table id="adminReportingApprovalTable"><thead><tr><th>考试 / 学校</th><th>报到统计</th><th>学校决定</th><th>状态</th><th>审批</th></tr></thead><tbody>${reportingPage.items.map(item => `<tr data-status="${h(item.status)}"><td><strong>${h(item.examName)}</strong><small>${h(item.schoolName)} · 第 ${h(item.payload?.round || 1)} 轮</small></td><td>计划 ${h(item.progress.totalQuota)} 人 · 已报到 ${h(item.progress.reportedCount)} 人<small>完成率 ${h(item.progress.reportingRate)}% · 缺额 ${h(item.progress.reportingGap)} 人</small></td><td><strong>${item.payload?.supplementDecision === 'supplement' ? '申请补录' : '不进行补录'}</strong><small>${h(item.payload?.decisionNote || '')}</small></td><td>${badge(item.status)}</td><td>${item.status === 'pending_approval' ? `<button class="row-action primary" data-action="review-admission-reporting" data-id="${h(item.id)}" data-approved="true" data-supplement="${item.payload?.supplementDecision === 'supplement'}">批准并公开</button><button class="row-action" data-action="review-admission-reporting" data-id="${h(item.id)}" data-approved="false">退回</button>` : h(item.payload?.approvalNote || '—')}</td></tr>`).join('') || '<tr><td colspan="5" class="empty-state">暂无报到与补录审批记录</td></tr>'}</tbody></table></div>${pagination(reportingPage)}</section>`;
    const placements = `<section class="panel data-panel"><div class="panel-title"><div><h2>录取情况台账</h2><p>支持跨页搜索、考试/学校/状态筛选，并按当前筛选结果导出 Excel。</p></div><span>当前筛选 ${placementPage.total} / 共 ${data.placements.length} 条</span></div><div class="data-toolbar placement-supervision-toolbar"><label class="search-box">${icons.search}<input data-action="table-search" data-target="adminPlacementTable" placeholder="搜索考生、报名号、考试、学校、类别或退档理由"></label><div class="table-filter-selects"><select data-table-filter="examId" data-target="adminPlacementTable"><option value="">全部考试</option>${data.exams.map(exam => `<option value="${h(exam.id)}">${h(exam.name)}</option>`).join('')}</select><select data-table-filter="schoolId" data-target="adminPlacementTable"><option value="">全部招生学校</option>${data.admissionSchools.map(school => `<option value="${h(school.id)}">${h(school.name)}</option>`).join('')}</select></div><div class="filter-pills"><button class="active" data-action="status-filter" data-target="adminPlacementTable" data-status="all">全部</button><button data-action="status-filter" data-target="adminPlacementTable" data-status="school_review">学校审核中</button><button data-action="status-filter" data-target="adminPlacementTable" data-status="withdrawal_pending">退档待审</button><button data-action="status-filter" data-target="adminPlacementTable" data-status="final">正式录取</button><button data-action="status-filter" data-target="adminPlacementTable" data-status="withdrawn">已退档</button><button data-action="status-filter" data-target="adminPlacementTable" data-status="forfeited">未报到放弃</button></div><div class="ledger-toolbar-actions"><button class="row-action" data-action="clear-table-filters" data-target="adminPlacementTable">清除筛选</button><button class="row-action primary" data-action="admission-ledger-export" data-ledger="placements" data-table="adminPlacementTable">导出当前筛选</button></div></div><div class="table-scroll"><table id="adminPlacementTable"><thead><tr><th>考生 / 生源校</th><th>考试 / 成绩</th><th>录取学校</th><th>类别</th><th>录取 / 报到状态</th><th>退档审核</th></tr></thead><tbody>${placementPage.items.map(item => `<tr data-status="${h(item.status)}"><td><strong>${h(item.candidate.name)}</strong><small class="mono">${h(item.candidate.registrationNumber)}</small><small>${h(item.sourceSchoolName || '生源校未登记')}${item.className ? ` · ${h(item.className)}` : ''}</small></td><td><strong>${h(item.examName || item.examId)}</strong><small>${h(item.payload.totalScore)} 分 · 特征分 ${h(item.payload.featureScore || 0)} · 第 ${h(item.payload.preferenceOrder)} 志愿</small></td><td><strong>${h(item.schoolName)}</strong><small class="mono">${h(item.schoolCode || '')}</small></td><td>${h(item.payload.categoryName)}<small>${h(item.candidate.specialtyLabel || '普通生')}</small></td><td>${badge(item.status)}<small>报到：${h(item.reportingStatusLabel || '—')}</small></td><td>${item.status === 'withdrawal_pending' ? `<small>${h(item.payload.withdrawalReason)}</small><button class="row-action primary" data-action="withdrawal-review" data-id="${h(item.id)}" data-approved="true">批准</button><button class="row-action" data-action="withdrawal-review" data-id="${h(item.id)}" data-approved="false">驳回</button>` : '—'}</td></tr>`).join('') || '<tr><td colspan="6" class="empty-state">没有符合条件的录取记录</td></tr>'}</tbody></table></div>${pagination(placementPage)}</section>`;
    const banner = `<section class="admission-command-banner"><div><span>ADMISSION COMMAND</span><h2>中考招生录取控制台</h2><p>计划完成率、考生报到与补录审批在同一条可审计链路中实时更新。</p></div><dl><div><dt>待审计划</dt><dd>${pendingPlans.length}</dd></div><div><dt>补录待审批</dt><dd>${(data.reportingRequests || []).filter(item => item.status === 'pending_approval').length}</dd></div><div><dt>正式录取</dt><dd>${data.placements.filter(item => item.status === 'final').length}</dd></div><div><dt>已报到</dt><dd>${(data.reportingRequests || []).reduce((sum, item) => sum + Number(item.progress?.reportedCount || 0), 0)}</dd></div></dl></section>`;
    const sections = {
      settings: `<div class="admission-admin-grid single">${settings}${preferenceSnapshotPanel}</div>`,
      accounts,
      plans: `${planForm}${plans}`,
      reporting: reportingApprovals,
      supervision: placements
    };
    return `${banner}${sections[section] || sections.settings}`;
  }

  function adminIndicatorQualifications(data) {
    if (!data.exams?.length) return emptyState('暂无需要确认的考试', '超级管理员启用中考志愿填报后，本校资格名单会出现在这里。');
    return `<section class="qualification-ledger-intro"><div><span>SOURCE SCHOOL CERTIFICATION</span><h2>${h(data.school?.name)}资格确认簿</h2><p>先按姓名、报名号、确认状态或特长类型筛选，再逐人确认或多选批量设置。每场考试全部确认后立即自动公示。</p></div></section>${data.exams.map((item, index) => {
      const status = item.qualificationStatus;
      const tableId = `qualificationTable-${index}`;
      const qualificationPage = paged(status.rows, tableId);
      const specialties = [...new Set(status.rows.map(row => row.specialtyLabel).filter(Boolean))].sort((left, right) => left.localeCompare(right, 'zh-CN'));
      const filters = `<div class="data-toolbar qualification-filter-toolbar"><label class="search-box">${icons.search}<input data-action="table-search" data-target="${tableId}" placeholder="搜索报名号、姓名或特长类型"></label><div class="filter-pills"><button class="active" data-action="status-filter" data-target="${tableId}" data-status="all">全部</button><button data-action="status-filter" data-target="${tableId}" data-status="unconfirmed">待确认</button><button data-action="status-filter" data-target="${tableId}" data-status="eligible">有资格</button><button data-action="status-filter" data-target="${tableId}" data-status="ineligible">无资格</button></div><div class="qualification-specialty-filter"><select data-table-filter="specialty" data-target="${tableId}"><option value="">全部特长类型</option>${specialties.map(value => `<option value="${h(value)}">${h(value)}</option>`).join('')}</select><button class="row-action" data-action="clear-table-filters" data-target="${tableId}">清除筛选</button></div></div>`;
      const bulk = `<div class="qualification-bulk-toolbar" data-qualification-bulk data-exam-id="${h(item.examId)}"><label><input type="checkbox" data-action="qualification-select-all"><span>全选当前筛选结果</span></label><div><strong data-qualification-selected-count>已选 0 人</strong><select data-bulk-eligible><option value="">批量设置资格</option><option value="true">设为有指标分配资格</option><option value="false">设为无指标分配资格</option></select><button class="solid-button" data-action="bulk-indicator-qualification">应用到所选考生</button></div></div>`;
      const rows = qualificationPage.items.map(row => `<tr data-filter-row data-status="${row.confirmed ? `${row.eligible ? 'eligible' : 'ineligible'} confirmed` : 'unconfirmed'}" data-specialty="${h(row.specialtyLabel || '')}" data-exam-id="${h(item.examId)}" data-user-id="${h(row.userId)}"><td><input type="checkbox" data-qualification-select aria-label="选择 ${h(row.name)}"></td><td><strong>${h(row.name)}</strong><small class="mono">${h(row.registrationNumber)}</small></td><td>${h(row.specialtyLabel)}</td><td><select data-indicator-eligible><option value="" ${row.confirmed ? '' : 'selected'}>请选择</option><option value="true" ${row.confirmed && row.eligible ? 'selected' : ''}>有指标分配资格</option><option value="false" ${row.confirmed && !row.eligible ? 'selected' : ''}>无指标分配资格</option></select></td><td>${row.confirmedAt ? formatDate(row.confirmedAt, true) : '待确认'}</td><td><button class="row-action primary" data-action="save-indicator-qualification">确认</button></td></tr>`).join('');
      return `<section class="panel qualification-ledger"><header><div><span>${h(item.exam.code)}</span><h2>${h(item.exam.name)}</h2></div><strong class="${status.complete ? 'complete' : ''}">${h(status.confirmed)} / ${h(status.total)} 已确认</strong></header><div class="qualification-progress"><i style="width:${status.total ? Math.round(status.confirmed / status.total * 100) : 0}%"></i></div>${status.complete ? '<div class="qualification-publication-state">✓ 本校资格已全部确认，公开公示已自动发布</div>' : '<div class="qualification-publication-state pending">未全部确认前不会公开，请逐项核对。</div>'}${filters}${bulk}<div class="table-scroll"><table id="${tableId}"><thead><tr><th>选择</th><th>报名号 / 姓名</th><th>特长类型</th><th>指标分配资格</th><th>确认时间</th><th>保存</th></tr></thead><tbody>${rows || '<tr><td colspan="6" class="empty-state">本校暂无资料已完善的在册考生</td></tr>'}</tbody></table></div>${pagination(qualificationPage)}</section>`;
    }).join('')}`;
  }

  function adminNotices(notices, publications = []) {
    const entries = [
      ...notices.map(data => ({ kind: 'notice', status: `ordinary ${data.status} ${data.status === 'published' ? 'visible' : 'hidden'}`, data })),
      ...publications.map(data => ({ kind: 'publication', status: `system ${data.status} ${data.visible ? 'visible' : 'hidden'}`, data }))
    ];
    const noticePage = paged(entries, 'noticeTable', 20);
    const rows = noticePage.items.map(entry => {
      const item = entry.data;
      if (entry.kind === 'notice') return `<tr data-filter-row data-status="${h(entry.status)}"><td><strong>${h(item.title)}</strong><small>${h(item.summary)}</small></td><td><strong>手动通知</strong><small>${h(item.category)}</small></td><td>${h(item.author)}</td><td>${formatDate(item.publishAt || item.createdAt,true)}</td><td>${item.pinned ? '<span class="pin-label">首页置顶</span>' : item.status === 'published' ? '通知目录' : '尚未展示'}</td><td>${badge(item.status)}</td><td><div class="notice-row-actions">${item.status === 'draft' ? `<button class="row-action primary" data-action="edit-notice" data-id="${h(item.id)}">编辑</button>` : ''}<button class="row-action" data-action="toggle-notice" data-id="${h(item.id)}" data-status="${item.status === 'published' ? 'draft' : 'published'}">${item.status === 'published' ? '隐藏' : '发布'}</button></div></td></tr>`;
      return `<tr data-filter-row data-status="${h(entry.status)}"><td><strong>${h(item.title)}</strong><small>${h(item.summary)}</small></td><td><strong>自动公示</strong><small>${h(item.category)}</small></td><td>${h(item.author)}</td><td>${formatDate(item.publishedAt,true)}</td><td>通知目录</td><td>${badge(item.status)}</td><td><button class="row-action ${item.visible ? '' : 'primary'}" data-action="toggle-publication" data-id="${h(item.id)}" data-source-type="${h(item.sourceType)}" data-visible="${item.visible ? 'false' : 'true'}">${item.visible ? '隐藏' : '显示'}</button></td></tr>`;
    }).join('');
    return `<section class="panel data-panel"><div class="data-toolbar notice-admin-toolbar"><label class="search-box">${icons.search}<input data-action="table-search" data-target="noticeTable" placeholder="搜索全部通知、公示标题或分类"></label><div class="filter-pills"><button class="active" data-action="status-filter" data-target="noticeTable" data-status="all">全部</button><button data-action="status-filter" data-target="noticeTable" data-status="visible">正在显示</button><button data-action="status-filter" data-target="noticeTable" data-status="hidden">已隐藏</button><button data-action="status-filter" data-target="noticeTable" data-status="draft">草稿</button><button data-action="status-filter" data-target="noticeTable" data-status="system">自动公示</button></div><p>自动公示的内容由招生录取流程生成，这里只控制是否公开显示。</p></div><div class="table-scroll"><table id="noticeTable"><thead><tr><th>标题</th><th>来源 / 分类</th><th>发布人</th><th>发布时间</th><th>展示位置</th><th>状态</th><th>操作</th></tr></thead><tbody>${rows || '<tr><td colspan="7" class="empty-state">暂无符合条件的通知或系统公示</td></tr>'}</tbody></table></div>${pagination(noticePage)}</section>`;
  }
  
  function adminAdmit(data) {
    const approved = data.registrations || [];
    const admitPage = paged(approved, 'admitTable');
    const selectedExam = data.exams.find(exam => !exam.archivedAt && exam.approvedCount > 0) || data.exams.find(exam => !exam.archivedAt) || data.exams[0];
    const selectedPlan = selectedExam?.plan;
    const scopeName = code => data.mixingScopes.find(item => item.code === code)?.name || code;
    const form = data.canArrange ? (selectedExam ? `<section class="panel arrangement-config"><div class="panel-title"><div><h2>整场编排控制台</h2><p>先预检容量与档案，再以一个事务生成或替换整套编排。</p></div><span>${data.centers.length} 个启用考点 · ${data.centers.reduce((sum, item) => sum + item.capacity, 0)} 个常规席位</span></div><form data-form="admission-arrangement"><div class="arrangement-fields"><label><span>考试 *</span><select name="examId" required>${data.exams.map(exam => `<option value="${h(exam.id)}" ${exam.id === selectedExam.id ? 'selected' : ''}>${h(exam.name)}（审核通过 ${exam.approvedCount} 人 / 已编排 ${exam.arrangedCount} 人）</option>`).join('')}</select></label><label><span>混编范围 *</span><select name="mixingScope" required>${data.mixingScopes.map(item => `<option value="${h(item.code)}" ${item.code === (selectedPlan?.mixingScope || 'school') ? 'selected' : ''}>${h(item.name)}</option>`).join('')}</select></label><label><span>准考证号规则 *</span><select name="numberRuleId" required>${data.rules.map(rule => `<option value="${h(rule.id)}" ${rule.id === selectedPlan?.numberRuleId ? 'selected' : ''}>${h(rule.name)}</option>`).join('')}</select></label><label><span>稳定编排种子</span><input name="seed" value="${h(selectedPlan?.randomSeed || selectedExam.code)}" maxlength="80"><small>相同数据与种子会得到相同顺序，便于复核。</small></label></div><div class="arrangement-actions"><button type="button" class="ghost-button" data-action="preview-arrangement">仅预检，不写入</button><button type="submit" class="solid-button">${selectedPlan ? '重新编排整场考试' : '生成整场编排'}</button></div></form><div data-arrangement-preview></div></section>` : emptyState('还没有可编排考试', '请先创建考试并完成报名审核。')) : '';
    const ruleCards = data.canArrange ? `<section class="arrangement-rules">${data.rules.map(rule => `<article><span>号码规则</span><h3>${h(rule.name)}</h3><p>${h(rule.description)}</p><code>${h(rule.example)}</code></article>`).join('')}</section>` : '';
    const planCards = data.canArrange && data.plans.length ? `<section class="arrangement-plan-grid">${data.plans.map(plan => `<article class="panel"><header><div><span>${h(scopeName(plan.mixingScope))}</span><h3>${h(plan.examName)}</h3></div><time>${formatDate(plan.generatedAt, true)}</time></header><div><strong>${plan.candidateCount}</strong><small>名考生</small><strong>${plan.centerCount}</strong><small>个考点</small><strong>${plan.subjectCombinationCount}</strong><small>种科目组合</small></div><p>${h(plan.ruleName)} · 本校考点率 ${h(plan.sameSchoolCenterRate)}%</p>${plan.warnings.length ? `<ul>${plan.warnings.map(item => `<li>${h(item)}</li>`).join('')}</ul>` : '<p class="arrangement-ok">容量、档案与时间冲突检查通过</p>'}</article>`).join('')}</section>` : '';
    const exportExam = data.exams.find(exam => exam.arrangedCount > 0) || data.exams[0];
    const exportPanel = exportExam ? `<section class="panel arrangement-config admission-export-panel"><div class="panel-title"><div><h2>${data.canArrange ? '准考证与考务材料' : h(data.scopeLabel)}</h2><p>批量准考证为 A4 横向打印文件；“准考证信息”是逐考生、逐科目的 Excel 台账。</p></div><span>${approved.filter(item => item.admitCard).length} 份范围内准考证</span></div><div class="arrangement-fields"><label><span>选择考试</span><select data-admission-export-exam>${data.exams.map(exam => `<option value="${h(exam.id)}" ${exam.id === exportExam.id ? 'selected' : ''}>${h(exam.name)}（已编排 ${exam.arrangedCount} 人）</option>`).join('')}</select></label></div><div class="arrangement-actions"><button class="solid-button" data-action="batch-admit-download">批量下载准考证</button><button class="ghost-button" data-action="admit-info-export">导出准考证信息</button>${data.canExportCenterMaterials ? '<button class="ghost-button" data-action="center-materials-export">导出本校考点桌贴 / 门贴 / 签名单</button>' : ''}</div></section>` : emptyState('当前范围还没有考试报名', '待报名审核通过并完成整场编排后，可在这里批量下载。');
    const rows = admitPage.items.map(reg => {
      const assignments = new Map((reg.admitCard?.assignments || []).map(item => [item.subjectId, item]));
      const subjects = reg.subjects.map(subject => {
        const assignment = assignments.get(subject.id);
        return `<span><b>${h(subject.name)}</b><small>${assignment ? `考试考场序号 ${h(assignment.examRoomCode)} · ${h(assignment.roomName || assignment.room)}（场地 ${h(assignment.roomCode || '—')}）· ${h(assignment.building || '楼栋待定')} ${h(assignment.floor || '')} · 座位 ${h(assignment.seat)}` : '待编排'}</small></span>`;
      }).join('');
      return `<tr><td><div class="person-cell"><span>${h((reg.candidate?.name || '?').slice(0,1))}</span><div><strong>${h(reg.candidate?.name)}</strong><small>${h(reg.candidate?.school || '')} · ${h(reg.candidate?.grade || '')}</small></div></div></td><td><strong>${h(reg.exam.name)}</strong><small>${h(reg.exam.code)}</small></td><td class="mono">${h(reg.admitCard?.number || '待编排')}</td><td><strong>${h(reg.admitCard?.testCenter || '—')}</strong><small>${h(reg.admitCard?.centerCode || '')} · ${h(reg.admitCard?.centerAddress || '')}</small></td><td><div class="subject-room-list">${subjects}</div></td><td>${reg.admitCard ? `<button class="row-action" data-action="generate-admit" data-id="${h(reg.id)}">查看</button>` : '—'}</td></tr>`;
    }).join('');
    return `${form}${ruleCards}${planCards}${exportPanel}<section class="panel data-panel"><div class="data-toolbar"><label class="search-box">${icons.search}<input data-action="table-search" data-target="admitTable" placeholder="跨页搜索考生、考试、准考证号或考点"></label><p>考试考场序号来自本次编排；通用名称和场地代码来自考点物理场地档案。</p></div><div class="table-scroll"><table id="admitTable"><thead><tr><th>考生</th><th>考试</th><th>准考证号</th><th>固定考点 / 地址</th><th>分科考试考场 / 物理场地 / 座位</th><th>操作</th></tr></thead><tbody>${rows || '<tr><td colspan="6" class="empty-state">暂无已通过的考试报名</td></tr>'}</tbody></table></div>${pagination(admitPage)}</section>`;
  }
  
  function adminResults(data) {
    const preview = state.resultImportPreview;
    const activeExam = state.resultExamFilter ? data.exams.find(item => item.id === state.resultExamFilter) : null;
    if (!activeExam) {
      const examButton = exam => `<button class="${exam.archivedAt ? 'archived' : ''}" data-action="result-exam-filter" data-id="${h(exam.id)}"><span>${h(exam.code)}</span><strong>${h(exam.name)}</strong><small>${exam.archivedAt ? `已归档 · 点击按需加载` : '点击后按需加载本场成绩'}</small><i style="--progress:0%"></i></button>`;
      const currentExams = data.exams.filter(exam => !exam.archivedAt);
      const archivedExams = data.exams.filter(exam => exam.archivedAt);
      return `<section class="result-exam-strip">${currentExams.map(examButton).join('')}</section>${archivedExams.length ? `<details class="result-archive-switcher"><summary>历史归档考试 <span>${archivedExams.length} 场 · 选择后读取</span></summary><section class="result-exam-strip archived">${archivedExams.map(examButton).join('')}</section></details>` : ''}${emptyState('请先选择考试', '未选择考试时不会读取成绩、考生录分名单或成绩复议数据。')}`;
    }
    const activeSubject = activeExam?.subjects.find(item => item.id === state.resultSubjectFilter) || activeExam?.subjects[0];
    if (activeSubject) state.resultSubjectFilter = activeSubject.id;
    const examResults = data.results || [];
    const resultPage = data.resultPage || { items: examResults, page: 1, pageSize: 50, total: examResults.length, totalPages: 1, key: 'resultTable' };
    const examAppeals = activeExam ? (data.appeals || []).filter(item => item.result?.examId === activeExam.id) : (data.appeals || []);
    const appealPage = paged(examAppeals, 'resultAppealTable');
    const passRate = activeExam?.complete ? Math.round(activeExam.qualified / activeExam.complete * 100) : null;
    const resultEntryPage = data.entryPage || { items: [], page: 1, pageSize: 50, total: 0, totalPages: 1, key: 'resultEntryTable' };
    const subjectRegistrations = resultEntryPage.items;
    const recordedCount = Number(data.entryCounts?.recorded || 0);
    const publishedCount = Number(data.entryCounts?.published || 0);
    const entryRows = resultEntryPage.items.map((registration, index) => {
      const result = registration.result;
      const status = result?.published ? 'published' : result ? 'draft' : 'missing';
      return `<tr data-status="${status}"><td class="mono result-row-index">${(resultEntryPage.page - 1) * resultEntryPage.pageSize + index + 1}</td><td><div class="person-cell"><span>${h((registration.candidateName || '?').slice(0, 1))}</span><div><strong>${h(registration.candidateName)}</strong><small>${h(registration.schoolName)} · ${h(registration.className)}</small></div></div></td><td><strong class="mono">${h(registration.candidateNumber)}</strong></td><td><strong class="mono">${h(registration.admitCard?.number || '待编排')}</strong></td><td class="result-score-input-cell"><input data-result-score data-registration-id="${h(registration.id)}" type="number" min="0" max="${h(activeSubject?.fullScore || '')}" step="0.5" value="${result ? h(result.score) : ''}" placeholder="0—${h(activeSubject?.fullScore || '')}" aria-label="${h(registration.candidateName)}成绩"><small data-score-error></small></td><td>${result ? badge(result.published ? 'published' : 'draft') : '<span class="result-missing">未录入</span>'}</td><td>${result ? formatDate(result.updatedAt || result.publishedAt, true) : '—'}</td></tr>`;
    }).join('');
    const entry = state.user.adminLevel === 'super' && !activeExam?.archivedAt ? `<section class="panel result-entry-workbench"><form data-form="result-bulk-entry"><header class="result-workbench-head"><div><span>SCORE ENTRY ROSTER</span><h2>按名单录入单科成绩</h2><p>选定考试和科目后，按服务端分页录分；暂存不会向考生发布。</p></div><div class="result-workbench-selectors"><label><span>考试</span><select name="examId" data-action="result-bulk-exam">${data.exams.filter(exam => !exam.archivedAt).map(exam => `<option value="${h(exam.id)}" ${exam.id === activeExam?.id ? 'selected' : ''}>${h(exam.name)} · ${h(exam.code)}</option>`).join('')}</select></label><label><span>科目</span><select name="subjectId" data-action="result-bulk-subject">${(activeExam?.subjects || []).map(subject => `<option value="${h(subject.id)}" ${subject.id === activeSubject?.id ? 'selected' : ''}>${h(subject.name)} · 满分 ${h(subject.fullScore)}</option>`).join('')}</select></label></div></header><div class="result-workbench-summary"><span><small>应录人数</small><strong>${Number(data.entryCounts?.total || 0)}</strong></span><span><small>已录入</small><strong>${recordedCount}</strong></span><span><small>已暂存</small><strong>${Math.max(0, recordedCount - publishedCount)}</strong></span><span><small>已发布</small><strong>${publishedCount}</strong></span><p>${activeSubject ? `${h(activeSubject.name)} · 满分 ${h(activeSubject.fullScore)} 分 · ${h(activeSubject.passRule === 'none' ? '不设单科线' : activeSubject.passRule === 'rank_percent' ? `本科排名前 ${activeSubject.passValue}%` : `固定 ${activeSubject.passScore} 分达线`)}` : '请选择科目'}</p></div><div class="data-toolbar result-entry-toolbar"><label class="search-box">${icons.search}<input data-action="table-search" data-target="resultEntryTable" placeholder="搜索全部姓名、报名号、学校或班级"></label><div class="filter-pills"><button type="button" class="active" data-action="status-filter" data-target="resultEntryTable" data-status="all">全部</button><button type="button" data-action="status-filter" data-target="resultEntryTable" data-status="missing">未录入</button><button type="button" data-action="status-filter" data-target="resultEntryTable" data-status="draft">已暂存</button><button type="button" data-action="status-filter" data-target="resultEntryTable" data-status="published">已发布</button></div></div><div class="table-scroll result-entry-table-wrap"><table id="resultEntryTable"><thead><tr><th>序号</th><th>考生</th><th>报名号</th><th>准考证号</th><th>成绩（0—${h(activeSubject?.fullScore || '—')}）</th><th>状态</th><th>最近保存</th></tr></thead><tbody>${entryRows || '<tr><td colspan="7" class="empty-state">该科目暂无符合条件的考生</td></tr>'}</tbody></table></div><footer class="result-workbench-actions"><div><strong data-result-dirty-count>尚无未保存修改</strong><small>按 Ctrl / ⌘ + S 可快速暂存；发布操作只处理当前页已填写的成绩。</small></div><button type="submit" class="ghost-button" data-result-mode="draft">暂存已修改成绩</button><button type="submit" class="solid-button" data-result-mode="publish">发布当前页成绩</button></footer></form></section>` : '';
    const featurePage = data.featurePage || { items: [], page: 1, pageSize: 50, total: 0, totalPages: 1, key: 'featureScoreTable' };
    const featureRegistrations = featurePage.items;
    const featureModified = Number(data.featureCounts?.modified || 0);
    const featureRows = featurePage.items.map((registration, index) => {
      const featureScore = Number(registration.featureScore || 0);
      const status = `${featureScore ? 'modified' : 'zero'} ${registration.specialtyType ? 'specialty' : 'general'}`;
      return `<tr data-status="${status}"><td class="mono result-row-index">${(featurePage.page - 1) * featurePage.pageSize + index + 1}</td><td><div class="person-cell"><span>${h((registration.candidateName || '?').slice(0, 1))}</span><div><strong>${h(registration.candidateName)}</strong><small>${h(registration.schoolName)} · ${h(registration.className)}</small></div></div></td><td><strong class="mono">${h(registration.candidateNumber)}</strong></td><td><strong class="mono">${h(registration.admitCard?.number || '待编排')}</strong></td><td><strong>${h(registration.specialtyLabel || '普通生')}</strong><small>${registration.specialtyType ? '特长类别投档时计入' : '普通类别不计特征分'}</small></td><td class="result-score-input-cell feature-score-input-cell"><input data-feature-score data-registration-id="${h(registration.id)}" type="number" min="0" max="1000" step="0.01" value="${h(featureScore)}" aria-label="${h(registration.candidateName)}特征分"><small data-feature-score-error></small></td></tr>`;
    }).join('');
    const featureEntry = state.user.adminLevel === 'super' && !activeExam?.archivedAt ? `<section class="panel feature-score-workbench"><form data-form="feature-score-bulk"><input type="hidden" name="examId" value="${h(activeExam?.id || '')}"><header><div><span>UNIFIED SPECIALTY TEST</span><h2>按名单登记特征分</h2><p>所有考生默认 0 分；只有录取到特长生招生类别时，特征分才加入文化课总分参与该类别投档。</p></div><div class="feature-score-rule"><strong>分类计分规则</strong><span>普通类别：文化课总分</span><span>特长类别：文化课总分 + 特征分</span></div></header><div class="result-workbench-summary feature-score-summary"><span><small>本场考生</small><strong>${Number(data.featureCounts?.total || 0)}</strong></span><span><small>默认 0 分</small><strong>${Math.max(0, Number(data.featureCounts?.total || 0) - featureModified)}</strong></span><span><small>已修改</small><strong>${featureModified}</strong></span><span><small>具有特长资格</small><strong>${Number(data.featureCounts?.specialty || 0)}</strong></span><p>特征分按考试、按考生独立保存，不改变文化课成绩。</p></div><div class="data-toolbar result-entry-toolbar"><label class="search-box">${icons.search}<input data-action="table-search" data-target="featureScoreTable" placeholder="搜索全部姓名、报名号、学校或特长类型"></label><div class="filter-pills"><button type="button" class="active" data-action="status-filter" data-target="featureScoreTable" data-status="all">全部</button><button type="button" data-action="status-filter" data-target="featureScoreTable" data-status="zero">默认 0 分</button><button type="button" data-action="status-filter" data-target="featureScoreTable" data-status="modified">已修改</button><button type="button" data-action="status-filter" data-target="featureScoreTable" data-status="specialty">有特长资格</button></div></div><div class="table-scroll result-entry-table-wrap"><table id="featureScoreTable"><thead><tr><th>序号</th><th>考生</th><th>报名号</th><th>准考证号</th><th>特长资格 / 计分范围</th><th>特征分（0—1000）</th></tr></thead><tbody>${featureRows || '<tr><td colspan="6" class="empty-state">本场暂无符合条件的考生</td></tr>'}</tbody></table></div><footer class="result-workbench-actions"><div><strong data-feature-dirty-count>尚无未保存修改</strong><small>未修改的考生保持 0 分；保存后仅影响特长生类别的投档分。</small></div><button type="submit" class="solid-button">保存已修改特征分</button></footer></form></section>` : '';
    const importPreviewPage = preview ? paged(preview.rows, 'resultImportPreviewTable') : null;
    const importPreview = preview ? `<section class="panel result-import-preview"><header><div><span>EXCEL STAGING AREA</span><h2>${h(preview.fileName || '成绩导入预览')}</h2><p>此处数据尚未写入数据库。请检查错误、更新覆盖项和发布状态后再提交。</p></div><button class="row-action" data-action="cancel-result-import">取消预览</button></header><div class="import-preview-metrics"><span><small>总行数</small><strong>${preview.summary.total}</strong></span><span class="valid"><small>可提交</small><strong>${preview.summary.valid}</strong></span><span class="invalid"><small>有错误</small><strong>${preview.summary.invalid}</strong></span><span><small>新增 / 更新</small><strong>${preview.summary.create} / ${preview.summary.update}</strong></span><span><small>将发布</small><strong>${preview.summary.publish}</strong></span></div><div class="data-toolbar"><label class="search-box">${icons.search}<input data-action="table-search" data-target="resultImportPreviewTable" placeholder="跨页搜索考生、报名号、考试、科目或校验信息"></label><div class="table-filter-selects"><select data-table-filter="mode" data-target="resultImportPreviewTable"><option value="">全部写入方式</option><option value="create">新增成绩</option><option value="update">覆盖已有成绩</option></select></div></div><div class="table-scroll"><table id="resultImportPreviewTable" class="import-preview-table"><thead><tr><th>Excel 行</th><th>考生</th><th>考试 / 科目</th><th>成绩</th><th>独立及格线</th><th>发布</th><th>写入方式 / 校验</th></tr></thead><tbody>${importPreviewPage.items.map(row => `<tr class="${row.errors.length ? 'row-invalid' : ''}"><td class="mono">${h(row.sourceRow)}</td><td><strong>${h(row.candidateName || '未匹配')}</strong><small class="mono">${h(row.candidateNumber)}</small></td><td><strong>${h(row.examName || row.examCode)}</strong><small>${h(row.subjectName)}</small></td><td><strong>${Number.isFinite(row.score) ? h(row.score) : '—'}</strong><small>${row.scoreRate == null ? '' : `${h(row.scoreRate)}% · ${h(row.grade)}`}</small></td><td><strong>${h(row.passText || '—')}</strong><small>${row.qualified == null ? '不判定' : row.qualified ? '达到单科线' : '未达到单科线'}</small></td><td>${badge(row.published ? 'published' : 'draft')}</td><td>${row.errors.length ? `<ul>${row.errors.map(error => `<li>${h(error)}</li>`).join('')}</ul>` : `<strong>${row.mode === 'update' ? '覆盖已有成绩' : '新增成绩'}</strong><small>校验通过</small>`}</td></tr>`).join('')}</tbody></table></div>${pagination(importPreviewPage)}<form data-form="result-import-commit"><div class="import-commit-bar"><p>${preview.summary.invalid ? `有 ${preview.summary.invalid} 行错误，修正 Excel 后请重新选择文件。` : `确认后将以一个事务写入 ${preview.summary.valid} 条成绩，失败时不会留下部分数据。`}</p><button class="solid-button" type="submit" ${preview.summary.invalid ? 'disabled' : ''}>确认提交到数据库</button></div></form></section>` : '';
    const appealLedger = `<section class="panel data-panel"><div class="panel-title"><div><h2>本场成绩复议</h2><p>复议按考生所属班级和学校自动分配，可在流程中心办理。</p></div><button class="row-action" data-route="admin/flows">进入流程中心</button></div><div class="data-toolbar"><label class="search-box">${icons.search}<input data-action="table-search" data-target="resultAppealTable" placeholder="跨页搜索考生、科目、理由、责任人或步骤"></label><div class="filter-pills"><button class="active" data-action="status-filter" data-target="resultAppealTable" data-status="all">全部</button><button data-action="status-filter" data-target="resultAppealTable" data-status="pending">处理中</button><button data-action="status-filter" data-target="resultAppealTable" data-status="approved">已通过</button><button data-action="status-filter" data-target="resultAppealTable" data-status="rejected">已退回</button></div></div><div class="table-scroll"><table id="resultAppealTable"><thead><tr><th>考生 / 科目</th><th>考试</th><th>原成绩</th><th>复议理由</th><th>当前步骤</th><th>责任人</th><th>状态</th></tr></thead><tbody>${appealPage.items.map(appeal => `<tr><td><strong>${h(appeal.result?.candidateName)} · ${h(appeal.result?.subjectName)}</strong></td><td>${h(appeal.result?.examName)}</td><td><strong>${h(appeal.result?.score)}</strong></td><td><small>${h(appeal.reason)}</small></td><td>${h(appeal.currentStepDetail?.name || '流程已结束')}</td><td>${h(appeal.assignee?.displayName || '—')}</td><td>${badge(appeal.status)}</td></tr>`).join('') || '<tr><td colspan="7" class="empty-state">本场暂无成绩复议申请</td></tr>'}</tbody></table></div>${pagination(appealPage)}</section>`;
    const examButton = exam => `<button class="${exam.id === activeExam?.id ? 'active' : ''} ${exam.archivedAt ? 'archived' : ''}" data-action="result-exam-filter" data-id="${h(exam.id)}"><span>${h(exam.code)}</span><strong>${h(exam.name)}</strong><small>${exam.archivedAt ? `归档于 ${formatDate(exam.archivedAt, true)} · 已锁定` : `${exam.registrationCount ?? 0} 人 · 已录 ${exam.scored ?? 0}/${exam.enrolledSubjects ?? 0} 科次`}</small><i style="--progress:${exam.enrolledSubjects ? Math.round((exam.scored ?? 0) / exam.enrolledSubjects * 100) : 0}%"></i></button>`;
    const currentExams = data.exams.filter(exam => !exam.archivedAt);
    const archivedExams = data.exams.filter(exam => exam.archivedAt);
    const examStrip = `<section class="result-exam-strip">${currentExams.map(examButton).join('')}</section>${archivedExams.length ? `<details class="result-archive-switcher" ${activeExam?.archivedAt ? 'open' : ''}><summary>历史归档考试 <span>${archivedExams.length} 场 · 成绩永久锁定</span></summary><section class="result-exam-strip archived">${archivedExams.map(examButton).join('')}</section></details>` : ''}`;
    const cacheButton = state.user.adminLevel === 'super'
      ? `<button class="row-action" data-action="refresh-results-cache" ${data.resultCache?.enabled ? '' : 'disabled'} title="${data.resultCache?.enabled ? '让所有考生成绩查询在下次访问时重新生成 Redis 缓存' : 'Redis 缓存当前未连接'}">${data.resultCache?.enabled ? '刷新成绩 Redis 缓存' : 'Redis 缓存未启用'}</button>`
      : '';
    const toolbar = `<div class="excel-toolbar result-excel-toolbar"><span><strong>${activeExam?.archivedAt ? '归档成绩只读区' : '成绩 Excel 工作区'}</strong><small>${activeExam?.archivedAt ? '本场成绩已永久锁定，仅保留导出与查阅能力' : '名单模板已预填本场全部考生；导入后先预览，确认才写入数据库'}</small></span><div>${cacheButton}${activeExam?.archivedAt ? '' : '<button class="row-action" data-action="excel-download" data-resource="results" data-template="1">下载本场考生名单模板</button>'}<button class="row-action" data-action="excel-download" data-resource="results" data-exam-id="${h(activeExam?.id || '')}">导出本场成绩</button>${state.user.adminLevel === 'super' && !activeExam?.archivedAt ? '<button class="row-action primary" data-action="excel-import" data-resource="results">选择 Excel 预览</button><input type="file" accept=".xlsx" hidden data-excel-file="results">' : ''}</div></div>`;
    const metrics = `<section class="result-metric-grid"><article><small>报名考生</small><strong>${activeExam?.registrationCount ?? 0}</strong><span>本场已通过报名</span></article><article><small>录入进度</small><strong>${activeExam?.scored ?? 0}<em> / ${activeExam?.enrolledSubjects ?? 0}</em></strong><span>剩余 ${activeExam?.missing ?? 0} 科次</span></article><article><small>已发布</small><strong>${activeExam?.published ?? 0}</strong><span>草稿 ${Math.max(0, (activeExam?.scored || 0) - (activeExam?.published || 0))} 条</span></article><article><small>成绩已出齐</small><strong>${activeExam?.complete ?? 0}</strong><span>人</span></article><article><small>整场合格率</small><strong>${passRate == null ? '—' : `${passRate}%`}</strong><span>按本场排名或所设规则判定</span></article><article><small>成绩复议</small><strong>${examAppeals.length}</strong><span>当前考试累计</span></article></section>`;
    const ledger = `<section class="panel data-panel result-ledger"><div class="data-toolbar"><label class="search-box">${icons.search}<input data-action="table-search" data-target="resultTable" placeholder="跨页搜索报名号、姓名、学校或科目"></label><div class="filter-pills"><button class="active" data-action="status-filter" data-target="resultTable" data-status="all">全部</button><button data-action="status-filter" data-target="resultTable" data-status="published">已发布</button><button data-action="status-filter" data-target="resultTable" data-status="draft">草稿</button><button data-action="status-filter" data-target="resultTable" data-status="qualified">单科达线</button><button data-action="status-filter" data-target="resultTable" data-status="unqualified">单科未达线</button></div></div><div class="table-scroll"><table id="resultTable"><thead><tr><th>考生</th><th>考试 / 科目</th><th>成绩</th><th>排名 / 等级</th><th>单科及格规则</th><th>达线</th><th>发布</th><th>更新时间</th></tr></thead><tbody>${resultPage.items.map(result => `<tr data-status="${result.published ? 'published' : 'draft'} ${result.qualified === true ? 'qualified' : result.qualified === false ? 'unqualified' : ''}"><td><div class="person-cell"><span>${h((result.candidateName || '?').slice(0,1))}</span><div><strong>${h(result.candidateName)}</strong><small class="mono">${h(result.candidateNumber)}</small><small>${h(result.schoolName)} · ${h(result.className)}</small></div></div></td><td><strong>${h(result.subjectName)}</strong><small>${h(result.examCode)}</small></td><td><strong class="result-score">${h(result.score)}<em> / ${h(result.fullScore)}</em></strong></td><td><strong>第 ${h(result.rank)} / ${h(result.cohortSize)} 名</strong><small>${h(result.grade)} · 前 ${h(result.rankPercent)}%</small></td><td><strong>${h(result.passText)}</strong></td><td>${result.qualified == null ? '<span class="result-neutral">不判定</span>' : result.qualified ? '<span class="result-qualified">达线</span>' : '<span class="result-unqualified">未达线</span>'}</td><td>${badge(result.published ? 'published' : 'draft')}</td><td>${formatDate(result.updatedAt || result.publishedAt, true)}</td></tr>`).join('') || '<tr><td colspan="8" class="empty-state">本场考试还没有成绩记录</td></tr>'}</tbody></table></div>${pagination(resultPage)}</section>`;
    const archiveLock = activeExam?.archivedAt ? `<section class="exam-lock-banner"><span>${icons.check}</span><div><strong>本场考试已归档</strong><small>${formatDate(activeExam.archivedAt, true)} 起，手工录入、Excel 导入和成绩复议改分均已永久关闭。</small></div></section>` : '';
    return `${examStrip}${archiveLock}${metrics}${toolbar}${activeExam?.archivedAt ? '' : importPreview}${entry}${pagination(resultEntryPage)}${featureEntry}${pagination(featurePage)}${ledger}${appealLedger}`;
  }
  
  function adminUsers(data) {
    const adminPage = paged(data.admins || [], 'adminAccountTable', 20);
    return `<section class="panel registration-policy"><div><span>SELF REGISTRATION</span><h2>考生自主注册</h2><p>${data.selfRegistrationEnabled ? '公开入口已开放，考生可以自主申请固定报名号。' : '当前由学校统一创建账户、下发报名号和初始密码。'}</p></div><form data-form="self-registration-setting"><input type="hidden" name="enabled" value="${data.selfRegistrationEnabled ? 'false' : 'true'}"><span class="policy-state ${data.selfRegistrationEnabled ? 'open' : ''}">${data.selfRegistrationEnabled ? '已开放' : '已关闭'}</span><button class="${data.selfRegistrationEnabled ? 'ghost-button' : 'solid-button'}" type="submit">${data.selfRegistrationEnabled ? '关闭自主注册' : '开启自主注册'}</button></form></section><section class="panel data-panel admin-account-ledger"><div class="data-toolbar"><label class="search-box">${icons.search}<input data-action="table-search" data-target="adminAccountTable" placeholder="搜索姓名、账号、层级、学校或班级"></label><div class="filter-pills"><button class="active" data-action="status-filter" data-target="adminAccountTable" data-status="all">全部</button><button data-action="status-filter" data-target="adminAccountTable" data-status="active">已启用</button><button data-action="status-filter" data-target="adminAccountTable" data-status="disabled">已停用</button></div><p>账户不物理删除，停用后历史审批记录仍保留。</p></div><div class="table-scroll"><table id="adminAccountTable"><thead><tr><th>管理员</th><th>登录账号</th><th>层级</th><th>绑定范围</th><th>状态</th><th>账户操作</th></tr></thead><tbody>${adminPage.items.map(item => { const self = item.id === state.user.id; return `<tr data-status="${item.active ? 'active' : 'disabled'}"><td><div class="person-cell"><span>${h(item.displayName.slice(0, 1))}</span><div><strong>${h(item.displayName)}</strong><small>${h(item.id)}</small></div></div></td><td class="mono">${h(item.username)}</td><td><span class="admin-level level-${h(item.adminLevel)}">${h(item.levelName)}</span></td><td><strong>${h(item.schoolName || '全局')}</strong><small>${h(item.className || '')}</small></td><td>${item.active ? badge('approved') : badge('closed')}</td><td><div class="admin-account-actions"><button class="row-action" data-action="reset-admin-password" data-id="${h(item.id)}" ${self ? 'disabled title="当前账号请到账户安全修改密码"' : ''}>重置密码</button><button class="row-action ${item.active ? 'danger' : 'primary'}" data-action="toggle-admin-account" data-id="${h(item.id)}" data-active="${item.active ? 'false' : 'true'}" ${self ? 'disabled title="不能停用当前账号"' : ''}>${item.active ? '停用账户' : '重新启用'}</button></div></td></tr>`; }).join('') || '<tr><td colspan="6" class="empty-state">没有符合条件的管理员</td></tr>'}</tbody></table></div>${pagination(adminPage)}</section>`;
  }
  
  function adminCenters(data) {
    const roomTypeNames = { standard: '标准考场', computer: '机考考场', accessible: '无障碍考场', spare: '备用考场' };
    const detailAddresses = new Map(data.centers.map(center => [center.id, center.address]));
    data.centers.forEach(center => { center.address = formatRegionAddress(center); });
    const centerPage = paged(data.centers, 'centerDossierGrid', 20);
    const cards = centerPage.items.map(center => `<article class="panel center-dossier"><header><div><span>${h(center.schoolName)} · <b class="mono">${h(center.code)}</b></span><h2>${h(center.name)}</h2></div><div>${center.pendingChange ? '<span class="pending-mark">变更审批中</span>' : ''}${badge(center.status === 'active' ? 'approved' : 'closed')}<button class="row-action" data-action="edit-center" data-id="${h(center.id)}" ${center.pendingChange ? 'disabled title="已有待审批变更"' : ''}>提交变更</button></div></header><div class="center-metrics"><div><small>结构化考场</small><strong>${center.rooms.length}</strong><span>个</span></div><div><small>启用席位</small><strong>${center.totalCapacity}</strong><span>席</span></div><div><small>开放时间</small><strong>${h(center.gateOpenTime || '未设')}</strong></div></div><dl class="center-profile"><div><dt>详细地址</dt><dd>${h(center.address)}</dd></div><div><dt>考点负责人</dt><dd>${h(center.managerName || '未填写')} · ${h(center.managerPhone || center.contact || '未填写')}</dd></div><div><dt>应急电话</dt><dd>${h(center.emergencyPhone || '未填写')}</dd></div><div><dt>交通提示</dt><dd>${h(center.transport || '未填写')}</dd></div></dl><div class="room-table-wrap"><table class="room-table"><thead><tr><th>考场</th><th>位置</th><th>类型</th><th>容量</th><th>座位编排</th><th>状态</th></tr></thead><tbody>${center.rooms.map(room => `<tr><td><strong>${h(room.name)}</strong><small class="mono">${h(room.code)}</small></td><td>${h(room.building)} · ${h(room.floor || '楼层未填')}</td><td>${h(roomTypeNames[room.roomType] || room.roomType)}</td><td>${h(room.capacity)} 席</td><td>${h(room.seatPlan || '按现场座次表编排')}</td><td>${badge(room.status === 'active' ? 'approved' : 'closed')}</td></tr>`).join('')}</tbody></table></div><footer><span>${h(center.notes || '无补充说明')}</span><time>更新于 ${formatDate(center.updatedAt, true)}</time></footer></article>`).join('');
    data.centers.forEach(center => { center.address = detailAddresses.get(center.id); });
    const requests = data.changeRequests || [];
    const requestPage = paged(requests, 'centerChangeTable', 20);
    return `${excelToolbar('centers', { label: '考点考场档案' })}<section class="center-summary"><div><span>正式考点</span><strong>${data.centers.length}</strong></div><div><span>结构化考场</span><strong>${data.centers.reduce((sum, item) => sum + item.rooms.length, 0)}</strong></div><div><span>待审批变更</span><strong>${requests.filter(item => item.status === 'pending').length}</strong></div></section><div class="panel data-toolbar"><label class="search-box">${icons.search}<input data-action="table-search" data-target="centerDossierGrid" placeholder="搜索考点、学校、考场、负责人或地址"></label></div><div class="center-dossier-grid" id="centerDossierGrid">${cards || emptyState('没有符合条件的考点', '可清除搜索后查看全部正式考点。')}</div>${pagination(centerPage)}<section class="panel center-change-ledger"><div class="panel-title"><div><h2>考点变更台账</h2><p>新增和修改均保留申请快照，审批通过后才更新正式档案。</p></div><button class="row-action" data-route="admin/flows">进入流程中心</button></div><div class="data-toolbar"><label class="search-box">${icons.search}<input data-action="table-search" data-target="centerChangeTable" placeholder="搜索变更类型、考点、学校或责任人"></label><div class="filter-pills"><button class="active" data-action="status-filter" data-target="centerChangeTable" data-status="all">全部</button><button data-action="status-filter" data-target="centerChangeTable" data-status="pending">待审批</button><button data-action="status-filter" data-target="centerChangeTable" data-status="approved">已通过</button><button data-action="status-filter" data-target="centerChangeTable" data-status="rejected">已退回</button></div></div><div class="table-scroll"><table id="centerChangeTable"><thead><tr><th>申请类型</th><th>考点</th><th>学校</th><th>考场数</th><th>提交时间</th><th>当前状态</th><th>责任人</th></tr></thead><tbody>${requestPage.items.map(item => `<tr data-status="${h(item.status)}"><td>${item.requestType === 'create' ? '新增考点' : '修改档案'}</td><td><strong>${h(item.name)}</strong><small class="mono">${h(item.code)}</small></td><td>${h(item.schoolName)}</td><td>${item.rooms.length} 个</td><td>${formatDate(item.createdAt, true)}</td><td>${badge(item.status)}</td><td>${h(item.workflow?.assignee?.displayName || '流程已结束')}</td></tr>`).join('') || '<tr><td colspan="7" class="empty-state">没有符合条件的考点变更申请</td></tr>'}</tbody></table></div>${pagination(requestPage)}</section>`;
  }
  
  function adminAccountBatches(data) {
    const classes = data.classes || [];
    const batches = data.batches || [];
    const batchPage = paged(batches, 'accountBatchLedger', 20);
    const form = `<section class="panel batch-quota-panel"><div class="batch-quota-head"><div><span>SCHOOL ACCOUNT REQUEST</span><h2>按班级申领报名号</h2><p>只填写需要的数量。提交后进入审批，最终批准前不会创建任何考生账户。</p></div><div><small>单批上限</small><strong>500</strong><span>个账户</span></div></div><form data-form="candidate-account-batch"><div class="quota-grid">${classes.map(item => `<label><span><strong>${h(item.name)}</strong><small>${h(item.grade)}</small></span><span class="quota-input"><input type="number" min="0" max="200" value="0" data-class-id="${h(item.id)}"><em>人</em></span></label>`).join('')}</div><div class="batch-submit-bar"><p><strong>审批通过后生成</strong><span>固定报名号、随机初始密码、待补录考生账户</span></p><button class="solid-button" type="submit">提交批量申领</button></div></form></section>`;
    const ledger = batchPage.items.map(batch => {
      const resultRows = batch.status === 'approved' ? `<div class="credential-sheet"><header><div><strong>账号下发清单</strong><span>${batch.totalCount} 个账号 · 考生首次登录必须改密</span></div><button class="row-action" data-action="excel-download" data-resource="account_results" data-batch-id="${h(batch.id)}">导出 Excel</button></header><div class="table-scroll"><table><thead><tr><th>序号</th><th>班级</th><th>固定报名号 / 账户</th><th>初始密码</th></tr></thead><tbody>${batch.items.map((item, index) => `<tr><td>${index + 1}</td><td>${h(item.className)}</td><td class="mono"><strong>${h(item.candidateNumber)}</strong></td><td class="mono credential-password">${h(item.initialPassword)}</td></tr>`).join('')}</tbody></table></div></div>` : '';
      return `<article class="panel account-batch-card ${h(batch.status)}"><header><div><span class="mono">${h(batch.id)}</span><h2>${h(batch.schoolName)} · ${batch.totalCount} 个报名号</h2><p>${formatDate(batch.createdAt, true)} 由 ${h(batch.requesterName)} 提交</p></div>${badge(batch.status)}</header><div class="batch-quota-summary">${batch.quotas.map(item => `<span><strong>${h(item.className)}</strong><em>${item.count} 人</em></span>`).join('')}</div><div class="batch-flow-line"><span>当前进度</span><strong>${h(batch.workflow?.currentStepDetail?.name || statusLabels[batch.status])}</strong><small>${batch.workflow?.assignee ? `责任人：${h(batch.workflow.assignee.displayName)}` : batch.status === 'approved' ? '已生成并返回全部账户凭据' : '流程已结束'}</small></div>${batch.reviewNote ? `<div class="batch-review-note"><strong>审批意见</strong><span>${h(batch.reviewNote)}</span></div>` : ''}${resultRows}</article>`;
    }).join('');
    return `${excelToolbar('account_quotas', { label: '班级申领配额' })}${form}<section class="account-batch-ledger"><div class="ledger-title"><div><span>REQUEST LEDGER</span><h2>申领批次与返回结果</h2></div><p>结果只在最终批准后生成；报名号随后作为考生长期账户。</p></div><div class="panel data-toolbar"><label class="search-box">${icons.search}<input data-action="table-search" data-target="accountBatchLedger" placeholder="搜索学校、班级、批次号、提交人或状态"></label><div class="filter-pills"><button class="active" data-action="status-filter" data-target="accountBatchLedger" data-status="all">全部</button><button data-action="status-filter" data-target="accountBatchLedger" data-status="pending">审批中</button><button data-action="status-filter" data-target="accountBatchLedger" data-status="approved">已通过</button><button data-action="status-filter" data-target="accountBatchLedger" data-status="rejected">已退回</button></div></div><div id="accountBatchLedger">${ledger || emptyState('没有符合条件的申领批次', '可清除筛选后查看全部记录。')}</div>${pagination(batchPage)}</section>`;
  }
  
  function adminNumberRules(data) {
    const rule = data.activeRule || { name: '自定义报名号规则', separator: '-', segments: [] };
    const byType = Object.fromEntries(rule.segments.map(item => [item.type, item]));
    const types = Object.keys(numberSegmentMeta);
    return `<section class="account-number-principle"><span>ONE CANDIDATE · ONE NUMBER</span><strong>超级管理员只设计号码规则</strong><p>校级管理员按班级提交申领，流程最终批准后系统才创建长期考生账户。</p></section><div class="number-rule-layout"><section class="panel rule-builder"><div class="panel-title"><div><h2>账户报名号组成</h2><p>规则用于最终审批后的批量建号；流水号为必选字段。</p></div><span>当前规则</span></div><form data-form="number-rule"><input type="hidden" name="id" value="${h(rule.id)}"><div class="field-row"><label><span>规则名称</span><input name="name" required value="${h(rule.name)}"></label><label><span>字段分隔符</span><input name="separator" maxlength="3" value="${h(rule.separator)}" placeholder="留空表示直接拼接"></label></div><div class="segment-builder">${types.map((type, index) => { const segment = byType[type]; const checked = Boolean(segment) || type === 'sequence'; return `<label class="segment-option ${checked ? 'selected' : ''}"><input type="checkbox" name="include_${type}" ${checked ? 'checked' : ''} ${type === 'sequence' ? 'disabled' : ''}><span class="segment-order"><small>顺序</small><input type="number" name="position_${type}" min="1" max="9" value="${segment?.position || index + 1}"></span><span class="segment-copy"><strong>${numberSegmentMeta[type][0]}</strong><small>${numberSegmentMeta[type][1]}</small></span>${type === 'literal' ? `<input class="segment-value" name="value_${type}" value="${h(segment?.value)}" placeholder="例如 HZ">` : ''}${['year','sequence'].includes(type) ? `<input class="segment-width" type="number" name="width_${type}" min="1" max="12" value="${segment?.width || 4}" title="位数">` : ''}</label>`; }).join('')}</div><button class="solid-button" type="submit">保存审批建号规则</button></form></section><aside class="rule-preview"><span>审批后账户样例</span><strong>${h(data.preview || '2026-HZ01-X-0001')}</strong><p>${rule.segments.map(item => numberSegmentMeta[item.type]?.[0] || item.type).join(' + ')}</p><small>批量申领阶段尚无性别资料，因此性别段使用 X；考生补录资料后号码保持不变。</small></aside></div>`;
  }
  
  function adminFlowDesign(workflows) {
    const codes = { profile_change: 'PROFILE CHANGE', registration_review: 'REGISTRATION', center_change: 'CENTER & ROOM CHANGE', candidate_account_batch: 'ACCOUNT BATCH', score_appeal: 'SCORE APPEAL' };
    return `<div class="workflow-design-grid">${workflows.map(workflow => `<section class="panel workflow-designer"><header><div><span>${h(codes[workflow.businessType] || workflow.businessType)}</span><h2>${h(workflow.name)}</h2></div><button class="row-action" data-action="add-workflow-step" data-type="${h(workflow.businessType)}">添加步骤</button></header><form data-form="workflow-design" data-type="${h(workflow.businessType)}"><input name="name" value="${h(workflow.name)}" required><div class="workflow-step-editor" data-workflow-steps>${workflow.steps.map(step => workflowStepEditor(step)).join('')}</div><button class="solid-button" type="submit">保存流程</button></form></section>`).join('')}</div>`;
  }
  
  function workflowStepEditor(step = {}) {
    return `<div class="workflow-step-row"><i></i><input name="stepName" value="${h(step.name)}" placeholder="步骤名称" required><select name="stepLevel"><option value="class" ${step.adminLevel === 'class' ? 'selected' : ''}>班级管理员</option><option value="school" ${step.adminLevel === 'school' ? 'selected' : ''}>校级管理员</option><option value="super" ${step.adminLevel === 'super' ? 'selected' : ''}>超级管理员</option></select><button type="button" data-action="remove-workflow-step" aria-label="移除步骤">×</button></div>`;
  }
  
  function adminFlows(data) {
    const actionNames = { submit: '提交', approve: '通过', reject: '退回考生', transfer: '转交', return: '退回节点', supervise: '监督调整' };
    const typeNames = { profile_change: '考生信息修改', registration_review: '考试报名', center_change: '考点考场变更', candidate_account_batch: '批量报名号申领', score_appeal: '考生成绩复议' };
    const visibleTypes = [...new Set(data.instances.map(instance => instance.businessType))];
    const workflowPage = paged(data.instances, 'workflowBoard', 20);
    const toolbar = `<section class="panel data-toolbar workflow-filter-toolbar"><label class="search-box">${icons.search}<input data-action="table-search" data-target="workflowBoard" placeholder="搜索考生、学校、考试、责任人或流程"></label><div class="filter-pills"><button class="active" data-action="status-filter" data-target="workflowBoard" data-status="all">全部</button><button data-action="status-filter" data-target="workflowBoard" data-status="pending">待处理</button><button data-action="status-filter" data-target="workflowBoard" data-status="approved">已通过</button><button data-action="status-filter" data-target="workflowBoard" data-status="rejected">已退回</button></div><div class="workflow-type-filter"><select data-table-filter="type" data-target="workflowBoard"><option value="">全部流程类型</option>${visibleTypes.map(type => `<option value="${h(type)}">${h(typeNames[type] || type)}</option>`).join('')}</select></div></section>`;
    return `${toolbar}<div class="workflow-board" id="workflowBoard">${workflowPage.items.map(instance => {
      const isCenter = instance.businessType === 'center_change';
      const isBatch = instance.businessType === 'candidate_account_batch';
      const isAppeal = instance.businessType === 'score_appeal';
      const title = isCenter ? instance.centerName : isBatch ? `${instance.schoolName} · ${instance.batchTotalCount} 个账户` : isAppeal ? `${instance.candidateName} · ${instance.appealResult?.subjectName || '成绩复议'}` : instance.candidateName;
      const sub = isCenter ? `${instance.requestType === 'create' ? '新增考点' : '修改档案'} · ${instance.schoolName}` : isBatch ? (instance.accountBatch?.quotas || []).map(item => `${item.className} ${item.count} 人`).join(' · ') : isAppeal ? `${instance.appealResult?.examName || ''} · 原成绩 ${instance.appealResult?.score ?? '—'}` : `${instance.examName ? `${instance.examName} · ` : ''}${instance.schoolName} · ${instance.className}`;
      return `<article class="panel workflow-card ${instance.status}" data-filter-row data-status="${h(instance.status)}" data-type="${h(instance.businessType)}"><header><div><span>${h(typeNames[instance.businessType] || instance.businessType)}</span><h2>${h(title)}</h2><p>${h(sub)}</p></div>${badge(instance.status)}</header><div class="workflow-track">${instance.steps.map(step => `<div class="${step.position < instance.currentStep || instance.status === 'approved' ? 'done' : step.position === instance.currentStep && instance.status === 'pending' ? 'current' : ''}"><i>${step.position < instance.currentStep || instance.status === 'approved' ? '✓' : step.position}</i><span><strong>${h(step.name)}</strong><small>${h(statusLabels[step.adminLevel])}</small></span></div>`).join('')}</div><div class="workflow-owner"><span>当前责任人</span><strong>${h(instance.assignee?.displayName || '流程已结束')}</strong><small>${h(instance.currentStepDetail?.name || statusLabels[instance.status])}</small></div><footer><span>${instance.actions.length ? `${h(actionNames[instance.actions.at(-1).action] || instance.actions.at(-1).action)} · ${h(instance.actions.at(-1).actorName)}` : '尚无操作记录'}</span><button class="row-action primary" data-action="open-flow" data-id="${h(instance.id)}">查看与处理</button></footer></article>`;
    }).join('') || emptyState('暂无审批流程', '考生资料、考试报名、考点档案或批量建号提交后，流程会显示在这里。')}</div>${pagination(workflowPage)}`;
  }

  return { renderAdmin, workflowStepEditor };
}
