L2文档三大板块重构+评分细则不公开化;系统对齐:一键三轮评审、受验者注册表映射、提交状态探测工具

- 文档重构为 考核目的(1.x)/提交要求(2.x,含成果物需求)/考核内容(3.x) 板块编号体系
- 删除公开评分细则(7维表/合格线/难度赋分/功能拆分),保留验收基准与提交要求
- 自选题取消事前登记,改由 AGENTS.md 记录核心内容;前端同步移除登记字段
- 新增 l2-participants 注册表服务与 teams-config L2 URL 自动映射
- 新增 startReviewRounds 一键N轮评审(自动续跑+快照聚合中位数),前端「重新评审×3」
- 新增 check-repos.mjs 提交状态探测(API四态判定:已提交/空仓/未创建/未授权)
- 文档措辞与实现对齐(AI辅助评审)、修复引用/残片/格式问题
This commit is contained in:
hangshuo652
2026-08-26 10:52:23 +08:00
parent 6a2419d4a4
commit 040808ef6b
10 changed files with 510 additions and 554 deletions
+8 -34
View File
@@ -205,7 +205,7 @@ function EntryManager({ projectId, track }: { projectId: string; track?: string
const [importResult, setImportResult] = useState<any>(null);
const [editEntry, setEditEntry] = useState<any>(null);
const [showAdd, setShowAdd] = useState(false);
const [addForm, setAddForm] = useState({ title: '', repo_url: '', participant: '', sub_type: '', branch: '', selected_topic: 'self', reg_no: '', reg_features: '' });
const [addForm, setAddForm] = useState({ title: '', repo_url: '', participant: '', sub_type: '', branch: '', selected_topic: 'self' });
const [l2Topics, setL2Topics] = useState<any[]>([]);
const [offset, setOffset] = useState(0);
const PAGE_LIMIT = 50;
@@ -246,9 +246,9 @@ function EntryManager({ projectId, track }: { projectId: string; track?: string
setSelected(next);
};
const doAction = async (action: string, entryId: string) => {
const doAction = async (action: string, entryId: string, body: any = {}) => {
try {
if (action === 'start') await api.request('POST', `/projects/${projectId}/entries/${entryId}/start`);
if (action === 'start') await api.request('POST', `/projects/${projectId}/entries/${entryId}/start`, { rounds: 3, ...body });
else if (action === 'cancel') await api.request('POST', `/projects/${projectId}/entries/${entryId}/cancel`);
else if (action === 'retry') await api.request('POST', `/projects/${projectId}/entries/${entryId}/retry`);
await load();
@@ -282,9 +282,6 @@ function EntryManager({ projectId, track }: { projectId: string; track?: string
};
if (track === 'L2考核') {
payload.selected_topic = editEntry.selected_topic || 'self';
if (payload.selected_topic === 'self') {
payload.self_registration = { no: editEntry.reg_no, features: editEntry.reg_features };
}
}
await api.request('PUT', `/projects/${projectId}/entries/${editEntry.id}`, payload);
setEditEntry(null);
@@ -293,30 +290,23 @@ function EntryManager({ projectId, track }: { projectId: string; track?: string
};
const openEdit = (e: any) => {
let reg = { no: '', features: '' };
try { const p = JSON.parse(e.self_registration || '{}'); reg = { no: p.no || '', features: Array.isArray(p.features) ? p.features.join('\n') : (p.features || '') }; } catch { }
setEditEntry({
id: e.id, title: e.title, repo_url: e.repo_url, participant: e.participant || '',
sub_type: e.sub_type || '', branch: e.branch || '',
service_url: e.service_url || '', build_status: e.build_status || '',
selected_topic: e.selected_topic || 'self', reg_no: reg.no, reg_features: reg.features,
selected_topic: e.selected_topic || 'self',
});
};
const doAdd = async () => {
if (!addForm.title.trim() || !addForm.repo_url.trim()) return;
const payload: any = { ...addForm };
delete payload.reg_no;
delete payload.reg_features;
if (track === 'L2考核') {
payload.selected_topic = addForm.selected_topic || 'self';
if (payload.selected_topic === 'self') {
payload.self_registration = { no: addForm.reg_no, features: addForm.reg_features };
}
}
try {
await api.request('POST', `/projects/${projectId}/entries`, payload);
setAddForm({ title: '', repo_url: '', participant: '', sub_type: '', branch: '', selected_topic: 'self', reg_no: '', reg_features: '' });
setAddForm({ title: '', repo_url: '', participant: '', sub_type: '', branch: '', selected_topic: 'self' });
setShowAdd(false);
await load();
} catch (err: any) { alert(err.message || '添加失败'); }
@@ -439,20 +429,12 @@ function EntryManager({ projectId, track }: { projectId: string; track?: string
</select>
)}
{track === 'L2考核' && (
<>
<select value={addForm.selected_topic} onChange={e => setAddForm({ ...addForm, selected_topic: e.target.value })} className="select-field">
<option value="self"></option>
<option value="self"></option>
{l2Topics.map(t => (
<option key={t.id} value={t.id}> {t.id}{t.title}{'★'.repeat(t.difficulty)} {t.maxScoreCap}</option>
))}
</select>
{addForm.selected_topic === 'self' && (
<>
<input value={addForm.reg_no} onChange={e => setAddForm({ ...addForm, reg_no: e.target.value })} placeholder="登记编号(组委会登记确认后获得)" className="input-field" />
<textarea value={addForm.reg_features} onChange={e => setAddForm({ ...addForm, reg_features: e.target.value })} placeholder="登记功能清单(每行一条;低于该范围核心功能的缩减按未实现计)" rows={3} className="input-field" />
</>
)}
</>
)}
<div className="form-actions">
<button onClick={doAdd} disabled={!addForm.title.trim() || !addForm.repo_url.trim()}></button>
@@ -528,7 +510,7 @@ function EntryManager({ projectId, track }: { projectId: string; track?: string
{e.status === 'verifying' && <button className="btn-action warn" onClick={() => doAction('cancel', e.id)}></button>}
{['clone_fail', 'analysis_fail', 'failed'].includes(e.status) && <button className="btn-action" onClick={() => doAction('retry', e.id)}></button>}
{['review_done', 'admin_reviewed'].includes(e.status) && <button className="btn-action" onClick={() => openDetail(e.id)}></button>}
{['review_done', 'admin_reviewed'].includes(e.status) && <button className="btn-action" onClick={() => doAction('start', e.id)}></button>}
{['review_done', 'admin_reviewed'].includes(e.status) && <button className="btn-action" onClick={() => doAction('start', e.id)}>×3</button>}
</td>
</tr>
))}
@@ -576,20 +558,12 @@ function EntryManager({ projectId, track }: { projectId: string; track?: string
</select>
)}
{track === 'L2考核' && (
<>
<select value={editEntry.selected_topic || 'self'} onChange={e => setEditEntry({ ...editEntry, selected_topic: e.target.value })} className="select-field">
<option value="self"></option>
<option value="self"></option>
{l2Topics.map(t => (
<option key={t.id} value={t.id}> {t.id}{t.title}{'★'.repeat(t.difficulty)} {t.maxScoreCap}</option>
))}
</select>
{editEntry.selected_topic === 'self' && (
<>
<input value={editEntry.reg_no || ''} onChange={e => setEditEntry({ ...editEntry, reg_no: e.target.value })} placeholder="登记编号" className="input-field" />
<textarea value={editEntry.reg_features || ''} onChange={e => setEditEntry({ ...editEntry, reg_features: e.target.value })} placeholder="登记功能清单(每行一条)" rows={3} className="input-field" />
</>
)}
</>
)}
<div className="form-actions">
<button onClick={doEditSave}></button>