| <!DOCTYPE html> |
| <html lang="zh-CN"> |
| <head> |
| <meta charset="UTF-8" /> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
| <title>PDF 翻译控制台</title> |
| <style> |
| :root { |
| --bg: #f4f7fb; |
| --card: #ffffff; |
| --ink: #0f172a; |
| --sub: #475569; |
| --line: #dbe3ee; |
| --brand: #0f766e; |
| --brand-dark: #115e59; |
| --danger: #b91c1c; |
| } |
| * { box-sizing: border-box; } |
| body { |
| margin: 0; |
| color: var(--ink); |
| background: radial-gradient(circle at 15% -20%, #d5f3ef 0, #f4f7fb 52%); |
| font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; |
| } |
| .wrap { max-width: 1100px; margin: 24px auto; padding: 0 16px 40px; } |
| .top { |
| display: flex; |
| align-items: center; |
| justify-content: space-between; |
| margin-bottom: 16px; |
| } |
| h1 { margin: 0; font-size: 1.5rem; } |
| .user { color: var(--sub); font-size: 0.95rem; } |
| .grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; } |
| .card { |
| background: var(--card); |
| border: 1px solid var(--line); |
| border-radius: 14px; |
| box-shadow: 0 10px 28px rgba(17, 24, 39, 0.06); |
| padding: 16px; |
| } |
| .card h2 { margin: 0 0 10px; font-size: 1.03rem; } |
| .row { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } |
| label { display: block; margin: 10px 0 6px; font-size: 0.86rem; color: var(--sub); } |
| input[type=text], select, input[type=file] { |
| width: 100%; padding: 10px 12px; border-radius: 8px; |
| border: 1px solid var(--line); background: #fff; color: var(--ink); |
| } |
| button { |
| border: none; border-radius: 9px; padding: 10px 14px; |
| font-weight: 600; cursor: pointer; |
| } |
| .primary { background: var(--brand); color: #fff; } |
| .primary:hover { background: var(--brand-dark); } |
| .muted { background: #e2e8f0; color: #0f172a; } |
| .danger { background: #fee2e2; color: var(--danger); } |
| .hint { margin-top: 8px; color: var(--sub); font-size: 0.84rem; } |
| .status { margin-top: 10px; min-height: 22px; font-size: 0.9rem; } |
| table { width: 100%; border-collapse: collapse; margin-top: 8px; font-size: 0.88rem; } |
| th, td { border-bottom: 1px solid var(--line); text-align: left; padding: 8px 6px; } |
| th { color: var(--sub); font-weight: 600; } |
| .mono { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 0.8rem; } |
| .actions button { margin-right: 6px; margin-bottom: 4px; } |
| .foot { margin-top: 20px; color: var(--sub); font-size: 0.82rem; } |
| @media (max-width: 900px) { |
| .grid { grid-template-columns: 1fr; } |
| .row { grid-template-columns: 1fr; } |
| } |
| </style> |
| </head> |
| <body> |
| <div class="wrap"> |
| <div class="top"> |
| <div> |
| <h1>PDF 翻译控制台</h1> |
| <div class="user">当前用户:<strong>__USERNAME__</strong></div> |
| </div> |
| <div><a href="/logout"><button class="muted">退出登录</button></a></div> |
| </div> |
|
|
| <div class="grid"> |
| <section class="card"> |
| <h2>新建任务</h2> |
| <form id="jobForm"> |
| <label>PDF 文件</label> |
| <input name="file" type="file" accept=".pdf" required /> |
|
|
| <div class="row"> |
| <div> |
| <label>源语言</label> |
| <input name="lang_in" type="text" value="__LANG_IN__" required /> |
| </div> |
| <div> |
| <label>目标语言</label> |
| <input name="lang_out" type="text" value="__LANG_OUT__" required /> |
| </div> |
| </div> |
|
|
| <div style="margin-top: 12px;"> |
| <button class="primary" type="submit">提交任务</button> |
| </div> |
| </form> |
| <div class="hint">模型由后台固定为 SiliconFlowFree,用户无需选择。</div> |
| <div id="jobStatus" class="status"></div> |
| </section> |
|
|
| <section class="card"> |
| <h2>我的账单</h2> |
| <div id="billingSummary" class="mono">加载中...</div> |
| <table> |
| <thead> |
| <tr> |
| <th>时间 (UTC)</th> |
| <th>模型</th> |
| <th>输入</th> |
| <th>输出</th> |
| <th>总计</th> |
| <th>费用 (USD)</th> |
| </tr> |
| </thead> |
| <tbody id="billingBody"></tbody> |
| </table> |
| <div class="hint">说明:仅统计计费模型的使用情况,当前 SiliconFlowFree 等免费模型不会产生账单记录。</div> |
| </section> |
| </div> |
|
|
| <section class="card" style="margin-top: 14px;"> |
| <h2>我的任务</h2> |
| <table> |
| <thead> |
| <tr> |
| <th>ID</th> |
| <th>文件</th> |
| <th>状态</th> |
| <th>进度</th> |
| <th>模型</th> |
| <th>更新时间 (UTC)</th> |
| <th>操作</th> |
| </tr> |
| </thead> |
| <tbody id="jobsBody"></tbody> |
| </table> |
| </section> |
|
|
| <div class="foot">内部 OpenAI 接口仅允许 localhost 访问,不会直接暴露给终端用户。</div> |
| </div> |
|
|
| <script src="/static/dashboard.js"></script> |
| </body> |
| </html> |
|
|