rearranged contents
This commit is contained in:
@@ -96,6 +96,34 @@ h3 { margin: 0; font-size: 17px; }
|
||||
border: 1px solid var(--border); color: #334155;
|
||||
}
|
||||
.class-tab.active { border-color: transparent; background: var(--primary); color: #fff; }
|
||||
.class-panel { margin-bottom: 14px; }
|
||||
.class-panel .status-row { margin-top: 14px; }
|
||||
|
||||
.admin-tabs {
|
||||
display: flex; gap: 6px; align-items: center; overflow-x: auto;
|
||||
padding: 7px; margin: 0 0 16px; background: rgba(255,255,255,.94);
|
||||
border: 1px solid var(--border); border-radius: 14px; box-shadow: 0 5px 16px rgba(15,23,42,.05);
|
||||
}
|
||||
.admin-tab {
|
||||
flex: 1 0 auto; min-width: 118px; height: 40px; border-radius: 10px;
|
||||
background: transparent; color: var(--muted); font-size: 14px; font-weight: 650;
|
||||
white-space: nowrap; transition: color .15s, background-color .15s, transform .15s;
|
||||
}
|
||||
.admin-tab:hover:not(:disabled) { background: #eef2f7; color: var(--text); transform: none; }
|
||||
.admin-tab.active { background: var(--primary); color: #fff; }
|
||||
.admin-tab.active:hover:not(:disabled) { background: var(--primary-dark); color: #fff; }
|
||||
.tab-panel { margin-bottom: 0; }
|
||||
.statistics { margin: 0 0 20px; }
|
||||
.create-group-line { margin-bottom: 24px; }
|
||||
.groups-head { margin-top: 4px; }
|
||||
.import-label {
|
||||
display: inline-flex; align-items: center; height: 38px; padding: 0 14px;
|
||||
border: 0; border-radius: 8px; background: #eef2f7; color: var(--text);
|
||||
font-size: 14px; font-weight: 500; line-height: 1; cursor: pointer; transition: .15s;
|
||||
}
|
||||
.import-label:hover { background: #e2e8f0; }
|
||||
.settings-divider { height: 1px; margin: 26px 0 22px; background: var(--border); }
|
||||
.settings-password-line { margin-top: 14px; }
|
||||
|
||||
.grid {
|
||||
display: grid; grid-template-columns: repeat(auto-fill,minmax(290px,1fr)); gap: 16px;
|
||||
@@ -153,4 +181,10 @@ h3 { margin: 0; font-size: 17px; }
|
||||
.brand span { display: none; }
|
||||
.group-card { padding: 13px; }
|
||||
.member-actions button { padding: 0 6px; }
|
||||
.admin-tabs { gap: 5px; padding: 6px; margin-bottom: 13px; }
|
||||
.admin-tab { min-width: 96px; height: 38px; font-size: 13px; }
|
||||
.class-panel, .import-label, .create-group-line { margin-bottom: 14px; }
|
||||
.form-line { flex-direction: column; align-items: stretch; }
|
||||
.form-line button, .form-line span { width: 100%; text-align: center; }
|
||||
.form-line span { height: auto; color: var(--muted); font-size: 13px; }
|
||||
}
|
||||
|
||||
@@ -31,19 +31,49 @@
|
||||
</div>
|
||||
|
||||
<div id="mainArea" class="hidden">
|
||||
<section class="panel">
|
||||
<div class="section-head"><h2>账号安全</h2></div>
|
||||
<form class="form-line" id="teacherPasswordForm">
|
||||
<input id="teacherOldPassword" type="password" autocomplete="current-password" placeholder="原密码" required>
|
||||
<input id="teacherNewPassword" type="password" autocomplete="new-password" minlength="8" placeholder="新密码(至少 8 位)" required>
|
||||
<input id="teacherConfirmPassword" type="password" autocomplete="new-password" minlength="8" placeholder="确认新密码" required>
|
||||
<button data-working type="submit">修改密码</button>
|
||||
</form>
|
||||
<div class="notice" id="teacherPasswordNotice"></div>
|
||||
<section class="panel class-panel">
|
||||
<div class="section-head">
|
||||
<h2>当前班级</h2>
|
||||
<div class="actions">
|
||||
<button class="success" id="exportButton" type="button">导出当前班 Excel</button>
|
||||
<label class="ghost button small import-label">
|
||||
上传名单<input id="importFile" type="file" accept=".xlsx" class="hidden">
|
||||
</label>
|
||||
<button class="warning" id="lockButton" type="button">停止学生操作</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="class-tabs" id="classTabs"></div>
|
||||
<div class="status-row" id="managementStatus"></div>
|
||||
<p class="hint">点击班级即切换当前开放登录班级,并查看/管理该班分组。其它班学生不能登录。</p>
|
||||
</section>
|
||||
|
||||
<section class="panel">
|
||||
<div class="section-head"><h2>分组设置</h2></div>
|
||||
<nav class="admin-tabs" role="tablist" aria-label="教师管理功能">
|
||||
<button class="admin-tab active" id="groupsTab" data-tab="groups" aria-controls="groupsPanel" aria-selected="true" type="button">小组管理</button>
|
||||
<button class="admin-tab" id="ungroupedTab" data-tab="ungrouped" aria-controls="ungroupedPanel" aria-selected="false" type="button">未分组学生</button>
|
||||
<button class="admin-tab" id="settingsTab" data-tab="settings" aria-controls="settingsPanel" aria-selected="false" type="button">设置与安全</button>
|
||||
</nav>
|
||||
|
||||
<section class="panel tab-panel" id="groupsPanel" role="tabpanel" aria-labelledby="groupsTab">
|
||||
<div class="statistics" id="statistics"></div>
|
||||
|
||||
<div class="section-head"><h2>手工新建小组</h2></div>
|
||||
<form class="form-line create-group-line" id="createGroupForm">
|
||||
<input id="newGroupName" maxlength="30" placeholder="输入新组名,例如:第 9 组" required>
|
||||
<button data-working type="submit">创建小组</button>
|
||||
</form>
|
||||
|
||||
<div class="section-head groups-head"><h2>全部小组(成员直接可见)</h2></div>
|
||||
<div class="grid" id="groupsGrid"></div>
|
||||
</section>
|
||||
|
||||
<section class="panel tab-panel hidden" id="ungroupedPanel" role="tabpanel" aria-labelledby="ungroupedTab">
|
||||
<div class="section-head"><h2>未分组学生</h2></div>
|
||||
<div id="ungroupedList"></div>
|
||||
</section>
|
||||
|
||||
<section class="panel tab-panel hidden" id="settingsPanel" role="tabpanel" aria-labelledby="settingsTab">
|
||||
<div class="section-head"><h2>设置与安全</h2></div>
|
||||
<h3>分组上限</h3>
|
||||
<form class="form-line" id="groupLimitForm">
|
||||
<input id="groupLimit" type="number" min="2" max="100" required>
|
||||
<span>人</span>
|
||||
@@ -51,42 +81,16 @@
|
||||
</form>
|
||||
<p class="hint">调整后立即对所有班级生效;已有小组不会被自动拆分。</p>
|
||||
<div class="notice" id="groupLimitNotice"></div>
|
||||
</section>
|
||||
|
||||
<section class="panel">
|
||||
<div class="section-head">
|
||||
<h2>班级管理</h2>
|
||||
<div class="actions">
|
||||
<button class="success" id="exportButton" type="button">导出当前班 Excel</button>
|
||||
<label class="ghost button small" style="display:inline-flex;align-items:center;padding:0 10px;background:#eef2f7;color:#18212f;border-radius:8px;height:38px">
|
||||
上传名单<input id="importFile" type="file" accept=".xlsx" class="hidden">
|
||||
</label>
|
||||
<button class="warning" id="lockButton" type="button">停止学生操作</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="class-tabs" id="classTabs"></div>
|
||||
<div class="status-row" style="margin-top:14px" id="managementStatus"></div>
|
||||
<p class="hint">点击班级即切换当前开放登录班级,并查看/管理该班分组。其它班学生不能登录。</p>
|
||||
</section>
|
||||
|
||||
<div class="statistics" id="statistics"></div>
|
||||
|
||||
<section class="panel">
|
||||
<div class="section-head"><h2>手工新建小组</h2></div>
|
||||
<form class="form-line" id="createGroupForm">
|
||||
<input id="newGroupName" maxlength="30" placeholder="输入新组名,例如:第 9 组" required>
|
||||
<button data-working type="submit">创建小组</button>
|
||||
<div class="settings-divider"></div>
|
||||
<h3>账号安全</h3>
|
||||
<form class="form-line settings-password-line" id="teacherPasswordForm">
|
||||
<input id="teacherOldPassword" type="password" autocomplete="current-password" placeholder="原密码" required>
|
||||
<input id="teacherNewPassword" type="password" autocomplete="new-password" minlength="8" placeholder="新密码(至少 8 位)" required>
|
||||
<input id="teacherConfirmPassword" type="password" autocomplete="new-password" minlength="8" placeholder="确认新密码" required>
|
||||
<button data-working type="submit">修改密码</button>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<section class="panel">
|
||||
<div class="section-head"><h2>全部小组(成员直接可见)</h2></div>
|
||||
<div class="grid" id="groupsGrid"></div>
|
||||
</section>
|
||||
|
||||
<section class="panel">
|
||||
<div class="section-head"><h2>未分组学生</h2></div>
|
||||
<div id="ungroupedList"></div>
|
||||
<div class="notice" id="teacherPasswordNotice"></div>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
const state = { classes: [], snapshot: null, activeClass: '', username: '' };
|
||||
const el = id => document.getElementById(id);
|
||||
const adminTabs = ['groups', 'ungrouped', 'settings'];
|
||||
|
||||
function renderUnauthenticated() {
|
||||
el('loginArea').classList.remove('hidden');
|
||||
@@ -7,6 +8,16 @@ function renderUnauthenticated() {
|
||||
el('teacherToolbar').classList.add('hidden');
|
||||
}
|
||||
|
||||
function switchAdminTab(tabName) {
|
||||
if (!adminTabs.includes(tabName)) tabName = 'groups';
|
||||
document.querySelectorAll('.admin-tab').forEach(button => {
|
||||
const active = button.dataset.tab === tabName;
|
||||
button.classList.toggle('active', active);
|
||||
button.setAttribute('aria-selected', String(active));
|
||||
el(`${button.dataset.tab}Panel`).classList.toggle('hidden', !active);
|
||||
});
|
||||
}
|
||||
|
||||
function renderState() {
|
||||
el('loginArea').classList.add('hidden');
|
||||
el('mainArea').classList.remove('hidden');
|
||||
@@ -19,6 +30,10 @@ function renderState() {
|
||||
renderUngrouped();
|
||||
}
|
||||
|
||||
document.querySelectorAll('.admin-tab').forEach(button => {
|
||||
button.addEventListener('click', () => switchAdminTab(button.dataset.tab));
|
||||
});
|
||||
|
||||
function renderClassTabs() {
|
||||
el('classTabs').innerHTML = state.classes.map(item => `
|
||||
<button class="class-tab ${item.class_name === state.activeClass ? 'active' : ''}"
|
||||
|
||||
Reference in New Issue
Block a user