Files
-----/tools/epub_review_editor/static/index.html
T

517 lines
22 KiB
HTML

<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>双语 EPUB 审校编辑器</title>
<link rel="stylesheet" href="/static/style.css?v=0.13.0">
</head>
<body>
<header class="topbar">
<button id="bookshelfBtn" class="bookshelfNavButton" type="button">书架</button>
<div class="brandBlock">
<h1>双语 EPUB 审校编辑器 <span id="appVersion" class="versionBadge">v0.13.0</span></h1>
<p id="sessionMeta">正在载入……</p>
</div>
<div class="modeTabs" role="tablist" aria-label="审校模式">
<button id="readingModeBtn" class="modeButton active" type="button">阅读模式</button>
<button id="polishModeBtn" class="modeButton" type="button">精修模式</button>
</div>
<div class="toolbar">
<button id="tocPanelBtn" type="button">目录</button>
<button id="searchPanelBtn" type="button">检索</button>
<button id="openLibraryBtn" type="button">打开 EPUB</button>
<button id="reviewToolsBtn" type="button">审校工具</button>
</div>
</header>
<main class="bookshelfScreen" id="bookshelfScreen" hidden>
<div class="libraryShell">
<aside class="librarySidebar" aria-label="书架分类">
<div class="libraryBrandRow">
<button id="libraryMenuBtn" class="iconTextButton" type="button"></button>
<strong>Starrea</strong>
</div>
<label class="librarySearchLabel">
<span>搜索</span>
<input id="bookshelfSearchInput" type="search" placeholder="搜索书名、作者、系列">
</label>
<nav class="libraryFacetList" id="bookshelfFacetList"></nav>
<div class="librarySidebarFooter">
<button id="bookshelfRefreshBtn" type="button">刷新</button>
<button id="bookshelfOpenUploadBtn" class="primary" type="button">导入 EPUB</button>
</div>
</aside>
<section class="bookshelfPanel">
<div class="bookshelfHeader">
<div>
<h2 id="bookshelfTitle">全部书籍</h2>
<p id="bookshelfDescription">按 EPUB 元数据建立书架,封面悬停可直接进入审校或翻译。</p>
</div>
<div class="bookshelfActions">
<button id="seriesConfigBtn" type="button" disabled>系列设置</button>
<button id="bookshelfOpenUploadBtnInline" class="primary" type="button">打开新的 EPUB</button>
</div>
</div>
<div class="bookshelfMeta" id="bookshelfMeta">正在读取书架……</div>
<div class="bookshelfGrid" id="bookshelfList"></div>
</section>
</div>
</main>
<aside class="seriesConfigDrawer" id="seriesConfigDrawer" hidden>
<div class="seriesConfigHeader">
<div>
<h2 id="seriesConfigTitle">系列设置</h2>
<p id="seriesConfigMeta">同系列书籍会优先共用这里的提示词和术语表。</p>
</div>
<button id="closeSeriesConfigBtn" type="button">关闭</button>
</div>
<label>
术语表路径
<input id="seriesGlossaryPathInput" type="text" placeholder="mingcibiao.json 的完整路径或项目内相对路径">
</label>
<label>
翻译内容提示词
<textarea id="seriesTranslationPromptInput" rows="5"></textarea>
</label>
<label>
格式与标点提示词
<textarea id="seriesFormatPromptInput" rows="5"></textarea>
</label>
<label>
角色状态与口吻提示词
<textarea id="seriesCharacterPromptInput" rows="4"></textarea>
</label>
<div class="seriesConfigActions">
<button id="saveSeriesConfigBtn" class="primary" type="button">保存系列设置</button>
</div>
</aside>
<main class="translationScreen" id="translationScreen" hidden>
<section class="translationPanel">
<div class="translationHeader">
<div>
<h2>AI 翻译 EPUB</h2>
<p id="translationBookMeta">选择书架中的日语 EPUB 后,可在这里设置提示词、术语表、范围和输出格式。</p>
</div>
<div class="translationHeaderActions">
<button id="translationBackBookshelfBtn" type="button">返回书架</button>
<button id="translationOpenReviewBtn" class="primary" type="button" disabled>打开输出审校</button>
</div>
</div>
<section class="translationGrid">
<form class="translationSettings" id="translationForm">
<section class="translationCard">
<div class="sectionTitle compactTitle">
<h2>输出与范围</h2>
<span id="translationSourceMeta">未读取源书信息</span>
</div>
<div class="translationStats" id="translationStats"></div>
<div class="translationOptions">
<label>
输出格式
<select id="translationOutputModeInput">
<option value="bilingual">中日双语 EPUB</option>
<option value="translated">纯中文 EPUB</option>
</select>
</label>
<label>
翻译范围
<select id="translationRangeModeInput">
<option value="limit">前 N 段试译</option>
<option value="all">全书</option>
</select>
</label>
<label>
段数
<input id="translationLimitInput" type="number" min="1" max="5000" value="20">
</label>
<label>
Temperature
<input id="translationTemperatureInput" type="number" min="0" max="1" step="0.1" value="0.2">
</label>
</div>
<div class="translationSample" id="translationSample"></div>
</section>
<section class="translationCard">
<div class="sectionTitle compactTitle">
<h2>API 与术语表</h2>
<span id="translationGptStatus">未读取配置</span>
</div>
<div class="translationOptions apiOptions">
<label>
Base URL
<input id="translationBaseUrlInput" type="url" placeholder="https://api.openai.com/v1">
</label>
<label>
Model
<input id="translationModelInput" type="text" placeholder="gpt-4o-mini">
</label>
<label>
API Key
<input id="translationApiKeyInput" type="password" placeholder="留空则保留已有密钥">
</label>
<label>
术语表路径
<input id="translationGlossaryPathInput" type="text" placeholder="mingcibiao.json 的完整路径或项目内相对路径">
</label>
</div>
<div class="translationActions">
<button id="translationSaveConfigBtn" type="button">保存 API 设置</button>
</div>
</section>
<section class="translationCard">
<div class="sectionTitle compactTitle">
<h2>提示词</h2>
<button id="translationResetPromptsBtn" type="button">恢复预设</button>
</div>
<label>
翻译内容提示词
<textarea id="translationPromptInput" rows="5"></textarea>
</label>
<label>
格式与标点提示词
<textarea id="translationFormatPromptInput" rows="5"></textarea>
</label>
<label>
角色状态与口吻提示词
<textarea id="translationCharacterPromptInput" rows="4"></textarea>
</label>
<div class="translationActions">
<button id="translationStartBtn" class="primary" type="submit">开始翻译</button>
</div>
</section>
</form>
<aside class="translationProgressCard">
<div class="sectionTitle compactTitle">
<h2>翻译进度</h2>
<span id="translationJobMeta">尚未开始</span>
</div>
<div class="translationProgress">
<div class="translationProgressBar" id="translationProgressBar"></div>
</div>
<div class="translationProgressText" id="translationProgressText">等待开始翻译。</div>
<div class="translationOutput" id="translationOutput" hidden></div>
<div class="translationLogs" id="translationLogs"></div>
</aside>
</section>
</section>
</main>
<main class="startScreen" id="startScreen" hidden>
<section class="startPanel">
<div class="startHeader">
<div>
<h2>打开中日双语 EPUB</h2>
<p>上传一个“日文灰字 + 中文译文紧随其后”的双语 EPUB,审校记录会保存在本机或服务器的审校目录中。</p>
</div>
<button id="refreshSessionsBtn" type="button">刷新会话</button>
</div>
<form class="uploadBox" id="uploadForm">
<label class="fileDrop" for="epubFileInput">
<span class="fileDropTitle">选择 EPUB 文件</span>
<span class="fileDropName" id="selectedFileName">尚未选择文件</span>
<input id="epubFileInput" type="file" accept=".epub,application/epub+zip">
</label>
<button id="uploadBtn" class="primary" type="submit">上传并开始审校</button>
</form>
<section class="sessionBrowser">
<div class="sectionTitle compactTitle">
<h2>已有审校会话</h2>
<span id="sessionListMeta"></span>
</div>
<div class="sessionList" id="sessionList"></div>
</section>
</section>
</main>
<main class="layout" id="reviewLayout" hidden>
<aside class="sidebar" id="sidebar" hidden>
<div class="sideHeader">
<strong id="sideTitle">目录</strong>
<button id="closeSidebarBtn" type="button" aria-label="隐藏侧栏">隐藏</button>
</div>
<section class="tocPanel" id="tocPanel">
<div class="tocToolbar" aria-label="目录操作">
<strong>章节目录</strong>
<div>
<button id="expandTocBtn" type="button">展开全部</button>
<button id="collapseTocBtn" type="button">收起</button>
</div>
</div>
<nav class="toc" id="toc" aria-label="章节目录"></nav>
</section>
<section class="searchPanel" id="searchPanel" hidden>
<div class="searchbox">
<input id="searchInput" type="search" placeholder="搜索原文、译文、备注">
<div class="searchScope" role="group" aria-label="检索范围">
<button id="searchScopeCurrentBtn" type="button" class="active">当前范围</button>
<button id="searchScopeBookBtn" type="button">全书全局</button>
</div>
</div>
<div class="stats" id="stats"></div>
<div class="rowList" id="rowList"></div>
</section>
</aside>
<section class="readerPane" id="readerPane">
<div class="readerHeader">
<div>
<div class="chapterKicker" id="chapterKicker">目录</div>
<h2 id="readerTitle">选择章节开始阅读</h2>
</div>
<div class="readerTools">
<div class="appearanceControls" aria-label="阅读外观">
<div class="themeSwitch" role="group" aria-label="背景模式">
<button id="themeDefaultBtn" type="button" data-reader-theme="default">默认</button>
<button id="themeEyeBtn" type="button" data-reader-theme="eye">护眼</button>
<button id="themeNightBtn" type="button" data-reader-theme="night">夜间</button>
</div>
<label class="readerSlider">
<span>字号</span>
<input id="readerFontSizeInput" type="range" min="15" max="24" step="1" value="17">
<output id="readerFontSizeValue">17</output>
</label>
<label class="readerSlider">
<span>行距</span>
<input id="readerLineHeightInput" type="range" min="1.6" max="2.4" step="0.05" value="1.95">
<output id="readerLineHeightValue">1.95</output>
</label>
</div>
<button id="prevPartBtn" type="button">上一节</button>
<button id="nextPartBtn" type="button">下一节</button>
</div>
</div>
<article class="readingFlow" id="readingFlow"></article>
</section>
<section class="editorPane" id="editorPane" hidden>
<div class="emptyState" id="emptyState">选择左侧段落开始审校。</div>
<article class="editorCard" id="editorCard" hidden>
<div class="rowHeader">
<div>
<div class="rowId" id="rowId"></div>
<div class="rowPath" id="rowPath"></div>
</div>
<label class="markToggle">
<input id="markedInput" type="checkbox">
标记为翻译问题
</label>
</div>
<section class="pair">
<h2>日文原文</h2>
<div class="sourceText" id="jpText"></div>
</section>
<section class="pair">
<div class="sectionTitle">
<h2>中文译文</h2>
<div class="inlineTools">
<button id="markSelectionBtn" type="button">标记选中文本</button>
<button id="clearMarksBtn" type="button">清除本段标记</button>
<button id="resetTextBtn" type="button">恢复本段初始译文</button>
</div>
</div>
<div id="cnEditor" class="cnEditor" contenteditable="true" spellcheck="false"></div>
</section>
<section class="reviewFields">
<label>
问题类型
<select id="issueTypeInput">
<option value="">未选择</option>
<option value="误译">误译</option>
<option value="漏译">漏译</option>
<option value="术语不一致">术语不一致</option>
<option value="人名/地名问题">人名/地名问题</option>
<option value="翻译腔">翻译腔</option>
<option value="角色口吻不对">角色口吻不对</option>
<option value="语序不顺">语序不顺</option>
<option value="标点/格式">标点/格式</option>
<option value="其他">其他</option>
</select>
</label>
<label>
严重程度
<select id="severityInput">
<option value="">未选择</option>
<option value="轻微">轻微</option>
<option value="中等">中等</option>
<option value="严重">严重</option>
</select>
</label>
<label>
标签
<input id="tagsInput" type="text" placeholder="例:术语, 对话, 阿格里皮娜">
</label>
</section>
<section class="notes">
<label>
问题备注
<textarea id="commentInput" rows="4" placeholder="写下哪里翻得不好,或你希望我之后怎么处理类似句子。"></textarea>
</label>
<label>
可沉淀为长期规则
<textarea id="learnNoteInput" rows="3" placeholder="例:某个术语只在原文实际出现时才进入重翻提示。"></textarea>
</label>
</section>
<div class="actions">
<button id="prevBtn" type="button">上一段</button>
<button id="saveBtn" type="button">保存本段记录</button>
<button id="nextBtn" type="button">下一段</button>
</div>
</article>
</section>
</main>
<aside class="quickEditor" id="quickEditor" hidden aria-label="审校工具面板">
<div class="quickHeader">
<div>
<div class="rowId" id="quickRowId"></div>
<div class="rowPath" id="quickRowPath"></div>
</div>
<button id="closeQuickEditorBtn" type="button" aria-label="关闭审校工具">关闭</button>
</div>
<details class="toolSection quickSourceWrap" open>
<summary>日文原文</summary>
<section class="quickSource" id="quickJpText"></section>
</details>
<details class="toolSection" open>
<summary>当前段</summary>
<label class="quickField">
中文译文
<div id="quickCnEditor" class="cnEditor quickCnEditor" contenteditable="true" spellcheck="false"></div>
</label>
<div class="quickControls">
<label class="markToggle">
<input id="quickMarkedInput" type="checkbox">
标记问题
</label>
<select id="quickIssueTypeInput">
<option value="">问题类型</option>
<option value="误译">误译</option>
<option value="漏译">漏译</option>
<option value="术语不一致">术语不一致</option>
<option value="人名/地名问题">人名/地名问题</option>
<option value="翻译腔">翻译腔</option>
<option value="角色口吻不对">角色口吻不对</option>
<option value="语序不顺">语序不顺</option>
<option value="标点/格式">标点/格式</option>
<option value="其他">其他</option>
</select>
<select id="quickSeverityInput">
<option value="">严重程度</option>
<option value="轻微">轻微</option>
<option value="中等">中等</option>
<option value="严重">严重</option>
</select>
</div>
<label class="quickField">
标签
<input id="quickTagsInput" type="text" placeholder="例:术语, 对话">
</label>
<label class="quickField">
问题备注
<textarea id="quickCommentInput" rows="3" placeholder="哪里翻得不好,或应该如何改。"></textarea>
</label>
<label class="quickField">
可沉淀为长期规则
<textarea id="quickLearnNoteInput" rows="2" placeholder="可复用的翻译偏好或禁忌。"></textarea>
</label>
<div class="quickActions">
<button id="quickMarkSelectionBtn" type="button">标记选中文本</button>
<button id="quickSaveBtn" type="button">保存当前段</button>
<button id="quickOpenFullBtn" type="button">打开完整精修</button>
</div>
</details>
<section class="gptBox toolSection" id="gptBox">
<div class="gptConfigTitle">AI 重翻</div>
<div class="gptStatus" id="gptStatus">未读取配置</div>
<label class="quickField">
重翻要求
<textarea id="gptInstructionInput" rows="2" placeholder="可选:这次希望更口语、更忠实,或特别注意某个术语。"></textarea>
</label>
<div class="gptActions">
<button id="retranslateBtn" type="button">重翻本段</button>
<button id="applyRetranslationBtn" type="button" disabled>应用重翻</button>
</div>
<div class="gptCandidate" id="gptCandidate" hidden></div>
</section>
<details class="toolSection gptConfig" id="gptConfig" open>
<summary>AI 设置与术语表</summary>
<div class="gptConfigGroup">
<div class="gptConfigTitle">API</div>
<label>
Base URL
<input id="gptBaseUrlInput" type="url" placeholder="https://api.openai.com/v1">
</label>
<label>
Model
<input id="gptModelInput" type="text" placeholder="gpt-4o-mini">
</label>
<label>
API Key
<input id="gptApiKeyInput" type="password" placeholder="留空则保留已有密钥">
</label>
<label>
术语表路径
<input id="glossaryPathInput" type="text" placeholder="mingcibiao.json 的完整路径或项目内相对路径">
</label>
</div>
<div class="gptConfigGroup">
<div class="gptConfigTitle">提示词</div>
<label>
翻译内容提示词
<textarea id="gptTranslationPromptInput" rows="5" placeholder="设置忠实度、文风、术语优先级等内容要求。"></textarea>
</label>
<label>
格式与标点提示词
<textarea id="gptFormatPromptInput" rows="5" placeholder="设置 HTML、ruby、标点替换与输出格式规则。"></textarea>
</label>
<label>
角色状态与口吻提示词
<textarea id="gptCharacterPromptInput" rows="4" placeholder="设置角色状态、性格口吻、对话风格判断规则。"></textarea>
</label>
</div>
<div class="gptConfigGroup glossaryGroup">
<div class="gptConfigTitle">术语表</div>
<div class="glossaryMeta" id="glossaryMeta">未读取术语表</div>
<div class="glossaryTools">
<input id="glossarySearchInput" type="search" placeholder="搜索原文、译名或备注">
<button id="reloadGlossaryBtn" type="button">重新读取</button>
<button id="addGlossaryEntryBtn" type="button">新增术语</button>
<button id="saveGlossaryBtn" type="button" disabled>保存术语表</button>
</div>
<div class="glossaryList" id="glossaryList"></div>
</div>
<div class="gptConfigActions">
<button id="resetGptPromptsBtn" type="button">恢复预设提示词</button>
<button id="saveGptConfigBtn" type="button">保存 AI 设置</button>
</div>
</details>
<details class="toolSection" open>
<summary>反馈与交付</summary>
<div class="deliveryActions">
<button id="showTouchedBtn" type="button">仅看已记录</button>
<button id="feedbackBtn" type="button">生成反馈文件</button>
<button id="applyBtn" type="button">写回 EPUB 内容</button>
<button id="exportBtn" type="button">导出审校 EPUB</button>
</div>
</details>
</aside>
<div class="toast" id="toast" hidden></div>
<script src="/static/app.js?v=0.13.0"></script>
</body>
</html>