feat: 复制原文到改写区按钮 + 修复改完字点段号第一次点击丢失

- 改写区新增「复制原文到改写区 →」: 一键以原文为起点手动改写;
  改写区已有内容时二次确认,避免覆盖已写的工作
- 修复既有 bug: 改写区 blur(点段号的 mousedown 触发)会重建段号按钮,
  mouseup 时按钮已被替换 → 第一次点击丢失(改完字要点两次才切段)。
  onRewriteInput/onRewriteBlur 改用轻量 class 更新(updateParagraphSwitcherState),
  不再重建 DOM
- 浏览器实测: 复制/确认/覆盖/切段 9/9 + 核心回归 6/6 通过
This commit is contained in:
LuminousRuoxi
2026-09-10 15:05:01 +08:00
parent 6e0db821a8
commit d4554eb1af
+28 -3
View File
@@ -193,7 +193,7 @@ button,input,textarea{font:inherit}button{cursor:pointer}.hidden{display:none!im
<div class="rewrite-intro">基于左侧原意重新表达这一整段,不需要逐句对应原文。</div>
<textarea id="rewriteArea" class="rewrite-area" placeholder="在这里重写当前段……"></textarea>
<div class="rewrite-meta"><span id="saveMeta">自动保存</span><span id="wordMeta" class="word-meta"></span><span id="charCount">0 characters</span></div>
<div class="translate-row"><button id="translateBtn" class="btn link">译成中文对照 →</button></div>
<div class="translate-row"><button id="copyOriginalBtn" class="btn link">复制原文到改写区 →</button><button id="translateBtn" class="btn link">译成中文对照 →</button></div>
<div id="translateBox" class="translate-box"></div>
<div class="rewrite-help">
<div class="help-entry"><span>需要一点帮助?</span><button id="showScaffold" class="btn link">给我一个写作起点 →</button></div>
@@ -1022,6 +1022,18 @@ function renderParagraphSwitcher(){
$('#focusOriginal').classList.toggle('active', originalView==='focus');
$('#fullOriginal').classList.toggle('active', originalView==='full');
}
// 轻量更新段号按钮状态(active / has-copy),不重建 DOM
// 改写区 blur(点段号的 mousedown 触发)若重建按钮,mouseup 时按钮已被替换,
// 第一次点击会丢失(用户实测:改完字点段号要连点两次)。
function updateParagraphSwitcherState(){
const wrap = $('#paragraphSwitcher');
if(!wrap) return;
wrap.querySelectorAll('[data-para-index]').forEach(btn=>{
const i = Number(btn.dataset.paraIndex);
btn.classList.toggle('active', i===current);
btn.classList.toggle('has-copy', hasRewrite(i));
});
}
function renderOriginalPane(){
const wrap=$('#originalFull');
wrap.innerHTML='';
@@ -1144,6 +1156,18 @@ async function toggleTranslate(){
btn.disabled = false;
renderTranslateBtn(); renderTranslateBox();
}
// 体验优化:把当前段原文一键复制到改写区 —— 顾问以原文为起点手动改写
// (改写区已有内容时二次确认,避免覆盖已写的工作)。
function copyOriginalToRewrite(){
const area = $('#rewriteArea');
const text = String(paragraphs[current]||'').trim();
if(!area || !text) return;
if(String(area.value||'').trim() && !confirm('改写区已有内容,确定用原文覆盖吗?')) return;
area.value = text;
area.focus();
onRewriteInput({target: area}); // 复用输入处理:状态/字数提示/译文过期/保存调度
track('original_copied_to_rewrite', {paragraph_id: pidOf(current)});
}
// 体验优化:原文中文对照(逐句)—— 顾问读英文吃力时,特别是被高亮标注
// 「需要改写」的句子,需要它的中文意思才能判断怎么改。
// 句子由前端拆分(en 为原文精确文本,服务端原样回填),命中批注 evidence 的
@@ -1312,7 +1336,7 @@ function onRewriteInput(e){
}
}
scheduleSave(current);
renderParagraphSwitcher();
updateParagraphSwitcherState();
updateProgress();
}
function onRewriteBlur(){
@@ -1321,7 +1345,7 @@ function onRewriteBlur(){
if(hasRewrite(current)) rewriteStatus[current] = 'REWRITTEN';
else rewriteStatus[current] = 'UNTOUCHED';
flushSave(current);
renderParagraphSwitcher();
updateParagraphSwitcherState(); // 不重建按钮:避免点击段号时 mousedown→blur 重建导致第一次点击丢失
updateProgress();
}
function recordExposure(kind, text){
@@ -1604,6 +1628,7 @@ $('#rewriteArea').addEventListener('input', onRewriteInput);
$('#rewriteArea').addEventListener('blur', onRewriteBlur);
$('#showScaffold').onclick=toggleScaffold;
$('#showReference').onclick=toggleReference;
$('#copyOriginalBtn').onclick=copyOriginalToRewrite;
$('#translateBtn').onclick=toggleTranslate;
$('#recheckHistoryBtn').onclick=()=>toggleRecheckHistory();
// 点击复检历史面板与开关按钮以外的区域自动收起