Files
icassp2027-experiment/floor_event_review_web/index.html
T

286 lines
14 KiB
HTML
Raw Normal View History

<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="EasyCom wearer floor-event local review workspace" />
<title>Floor Event Review</title>
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Crect width='64' height='64' rx='14' fill='%230b1324'/%3E%3Cpath d='M14 39h8l5-17 9 29 6-22 4 10h5' fill='none' stroke='%235eead4' stroke-width='5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E" />
<link rel="stylesheet" href="/app.css" />
</head>
<body>
<header class="topbar">
<div class="brand">
<span class="brand-mark" aria-hidden="true"></span>
<div>
<h1>Floor Event Review</h1>
<p>EasyCom 事件审核</p>
</div>
</div>
<div class="progress-block" aria-live="polite">
<div class="progress-copy">
<strong id="progressText">载入中</strong>
<span id="progressMeta">—</span>
</div>
<div class="progress-track"><span id="progressBar"></span></div>
</div>
<nav class="export-actions" aria-label="导出审核结果">
<a href="/api/export.jsonl" download>导出 JSONL</a>
<a href="/api/export.csv" download>导出 CSV</a>
</nav>
</header>
<section class="filters" aria-label="候选筛选">
<label>
<span>Session</span>
<select id="sessionFilter"><option value="all">全部</option></select>
</label>
<label>
<span>Split</span>
<select id="splitFilter">
<option value="all">全部</option>
<option value="train">train</option>
<option value="test">test</option>
</select>
</label>
<label>
<span>事件族</span>
<select id="familyFilter">
<option value="all">全部</option>
<option value="eot">EOT-response</option>
<option value="int">INT-yield</option>
<option value="onset">wearer onset</option>
<option value="offset">旧 EOT proxy</option>
<option value="interaction">旧 interaction proxy</option>
</select>
</label>
<label>
<span>审核状态</span>
<select id="statusFilter">
<option value="unreviewed">未审核</option>
<option value="all">全部</option>
<option value="reviewed">已审核</option>
</select>
</label>
<label class="search-field">
<span>搜索</span>
<input id="searchFilter" type="search" placeholder="UID、类别、session" />
</label>
<button id="clearFilters" class="button ghost" type="button">清除筛选</button>
</section>
<main class="workspace">
<aside class="queue-panel panel" aria-label="事件候选列表">
<div class="panel-heading">
<div>
<span class="eyebrow">QUEUE</span>
<h2 id="queueTitle">候选</h2>
</div>
<span id="queueCount" class="count-pill">0</span>
</div>
<div id="queueList" class="queue-list"></div>
<p id="queueLimit" class="queue-limit" hidden></p>
</aside>
<section class="evidence-panel panel" aria-label="事件证据">
<div class="event-header">
<div>
<div class="event-badges">
<span id="familyBadge" class="badge accent">—</span>
<span id="splitBadge" class="badge">—</span>
<span id="autoConfidenceBadge" class="badge">—</span>
</div>
<h2 id="eventTitle">请选择一个候选事件</h2>
<p id="eventSubtitle">—</p>
</div>
<div class="event-position"><strong id="eventPosition">0 / 0</strong></div>
</div>
<div id="llmSuggestion" class="llm-suggestion" hidden>
<strong>DeepSeek 预标注(仅供复核)</strong>
<span id="llmSuggestionText">—</span>
</div>
<div class="video-shell">
<video id="eventVideo" controls preload="metadata"></video>
<div id="mediaEmpty" class="empty-state" hidden>
<strong>当前候选未找到视频</strong>
<span>检查 dataset root、session 和 clip stem。</span>
</div>
<div class="time-marker" aria-hidden="true"><span></span></div>
</div>
<div class="transport" aria-label="视频定位">
<button type="button" data-seek="-2">−2 s</button>
<button type="button" data-seek="-0.2">−0.2 s</button>
<button id="jumpEvent" class="jump-event" type="button">回到事件</button>
<button type="button" data-seek="0.2">+0.2 s</button>
<button type="button" data-seek="2">+2 s</button>
<span id="timeReadout">—</span>
</div>
<section class="transcript-section">
<div class="section-heading">
<div>
<span class="eyebrow">TRANSCRIPT</span>
<h3>事件上下文</h3>
</div>
<span id="clipLabel">—</span>
</div>
<div id="transcriptList" class="transcript-list">
<div class="empty-copy">选择事件后显示 transcript。</div>
</div>
</section>
<details class="raw-details">
<summary>查看自动规则与原始候选字段</summary>
<pre id="rawCandidate">{}</pre>
</details>
</section>
<aside class="review-panel panel" aria-label="人工审核表单">
<div class="panel-heading review-heading">
<div>
<span class="eyebrow">HUMAN REVIEW</span>
<h2>审核结论</h2>
</div>
<span id="saveState" class="save-state">未保存</span>
</div>
<form id="reviewForm">
<fieldset>
<legend>1. 稿件协议结论 <span class="required">必填</span></legend>
<div class="choice-grid two compact">
<label><input type="radio" name="protocol_disposition" value="positive" /><span><b>Positive</b><small>EOT-response / INT-yield 正例</small></span></label>
<label><input type="radio" name="protocol_disposition" value="hard_negative" /><span><b>Hard negative</b><small>错误 commit 的计分区间</small></span></label>
<label><input type="radio" name="protocol_disposition" value="exclude" /><span><b>Exclude</b><small>歧义或标注损坏</small></span></label>
<label><input type="radio" name="protocol_disposition" value="uncertain" /><span><b>不确定</b><small>需要裁决</small></span></label>
</div>
</fieldset>
<fieldset>
<legend>2. Hard-negative 类型 <span class="required">必填</span></legend>
<div class="choice-grid two compact">
<label><input type="radio" name="hard_negative_type" value="eot_midturn_pause" /><span><b>EOT 句中停顿</b></span></label>
<label><input type="radio" name="hard_negative_type" value="eot_other_to_other" /><span><b>EOT other→other</b></span></label>
<label><input type="radio" name="hard_negative_type" value="eot_no_response" /><span><b>EOT 保持沉默</b></span></label>
<label><input type="radio" name="hard_negative_type" value="int_backchannel" /><span><b>INT backchannel</b></span></label>
<label><input type="radio" name="hard_negative_type" value="int_non_takeover_overlap" /><span><b>INT 非接管重叠</b></span></label>
<label><input type="radio" name="hard_negative_type" value="int_retain_floor" /><span><b>INT 保持话轮</b></span></label>
<label><input type="radio" name="hard_negative_type" value="other" /><span><b>其他</b></span></label>
<label><input type="radio" name="hard_negative_type" value="not_applicable" /><span><b>不适用</b></span></label>
<label><input type="radio" name="hard_negative_type" value="uncertain" /><span><b>不确定</b></span></label>
</div>
</fieldset>
<fieldset>
<legend>3. 活动边界是否真实? <span class="required">必填</span></legend>
<div class="choice-grid three">
<label><input type="radio" name="validity" value="valid" /><span><b>真实</b><small>有效活动边界</small></span></label>
<label><input type="radio" name="validity" value="artifact" /><span><b>伪边界</b><small>噪声、断点或错标</small></span></label>
<label><input type="radio" name="validity" value="uncertain" /><span><b>不确定</b><small>证据不足</small></span></label>
</div>
</fieldset>
<fieldset>
<legend>4. Onset 的 floor 功能 <span class="required">必填</span></legend>
<div class="choice-grid two compact">
<label><input type="radio" name="onset_function" value="floor_taking" /><span><b>取得话轮</b></span></label>
<label><input type="radio" name="onset_function" value="backchannel" /><span><b>Backchannel</b></span></label>
<label><input type="radio" name="onset_function" value="within_turn_resume" /><span><b>句内恢复</b></span></label>
<label><input type="radio" name="onset_function" value="nonverbal" /><span><b>非语言发声</b></span></label>
<label><input type="radio" name="onset_function" value="not_applicable" /><span><b>不适用</b></span></label>
<label><input type="radio" name="onset_function" value="uncertain" /><span><b>不确定</b></span></label>
</div>
</fieldset>
<fieldset>
<legend>5. 对话指向/场景 <span class="required">必填</span></legend>
<div class="choice-grid two compact">
<label><input type="radio" name="context" value="addressed_wearer" /><span><b>对 wearer</b></span></label>
<label><input type="radio" name="context" value="third_party" /><span><b>第三方交谈</b></span></label>
<label><input type="radio" name="context" value="group" /><span><b>群体</b></span></label>
<label><input type="radio" name="context" value="unknown" /><span><b>未知</b></span></label>
</div>
</fieldset>
<fieldset>
<legend>6. Offset 的结果 <span class="required">必填</span></legend>
<div class="choice-grid two compact">
<label><input type="radio" name="offset_outcome" value="yield_to_other" /><span><b>让给 other</b></span></label>
<label><input type="radio" name="offset_outcome" value="completion_to_silence" /><span><b>结束后静音</b></span></label>
<label><input type="radio" name="offset_outcome" value="temporary_pause" /><span><b>短暂停顿</b></span></label>
<label><input type="radio" name="offset_outcome" value="backchannel_end" /><span><b>Backchannel 结束</b></span></label>
<label><input type="radio" name="offset_outcome" value="cutoff" /><span><b>截断/边界</b></span></label>
<label><input type="radio" name="offset_outcome" value="not_applicable" /><span><b>不适用</b></span></label>
<label><input type="radio" name="offset_outcome" value="uncertain" /><span><b>不确定</b></span></label>
</div>
</fieldset>
<div class="inline-fields">
<label>
<span>other 锚点校正</span>
<select name="anchor_adjustment_bins">
<option value="">无法判断</option>
<option value="-1">−1 bin(−200 ms)</option>
<option value="0" selected>原 bin</option>
<option value="1">+1 bin(+200 ms)</option>
</select>
</label>
<label>
<span>wearer 行为锚点校正</span>
<select name="behavior_adjustment_bins">
<option value="">不适用/无法判断</option>
<option value="-1">−1 bin(−200 ms)</option>
<option value="0" selected>原 bin</option>
<option value="1">+1 bin(+200 ms)</option>
</select>
</label>
<label>
<span>负区间终点校正</span>
<select name="region_end_adjustment_bins">
<option value="">不适用/无法判断</option>
<option value="-1">−1 bin(−200 ms)</option>
<option value="0" selected>原 bin</option>
<option value="1">+1 bin(+200 ms)</option>
</select>
</label>
<label>
<span>置信度</span>
<select name="confidence" required>
<option value="high">高</option>
<option value="medium" selected>中</option>
<option value="low">低</option>
</select>
</label>
</div>
<label class="text-field">
<span>审核者</span>
<input id="reviewerInput" name="reviewer" maxlength="100" placeholder="姓名或代号" required />
</label>
<label class="text-field">
<span>备注</span>
<textarea name="notes" maxlength="4000" rows="3" placeholder="记录歧义、说话对象或边界问题"></textarea>
</label>
<div id="formError" class="form-error" role="alert" hidden></div>
<div class="review-actions">
<button id="uncertainButton" class="button ghost" type="button">全部标为不确定</button>
<button id="saveButton" class="button primary" type="submit">保存并看下一个 <kbd>⌘↵</kbd></button>
</div>
</form>
<div class="shortcuts">
<span><kbd>←</kbd><kbd>→</kbd> 前后事件</span>
<span><kbd>[</kbd><kbd>]</kbd> ±200 ms</span>
<span><kbd>Space</kbd> 播放/暂停</span>
</div>
</aside>
</main>
<div id="toast" class="toast" role="status" aria-live="polite"></div>
<script src="/app.js" defer></script>
</body>
</html>