vomebook commited on
Commit
369ca77
·
verified ·
1 Parent(s): 65a520c

Upload 2 files

Browse files
Files changed (2) hide show
  1. static/app.js +38 -6
  2. static/style.css +58 -0
static/app.js CHANGED
@@ -1357,6 +1357,10 @@ function isImageSource(url) {
1357
  return /\.(?:bmp|gif|jpe?g|png|tiff?|webp)(?:$|\?)/i.test(String(url || ""));
1358
  }
1359
 
 
 
 
 
1360
  async function openRandomPreview() {
1361
  const requestSeq = randomRequestSeq + 1;
1362
  randomRequestSeq = requestSeq;
@@ -1450,7 +1454,7 @@ function changePreviewTagPage(button) {
1450
 
1451
  function compareSelectHTML(item) {
1452
  const proofread = item.article && Array.isArray(item.article.parts)
1453
- ? '<option value="__proofread__">对比原文件并校对</option>'
1454
  : "";
1455
  if ((!item.variants || !item.variants.length) && !proofread) return "";
1456
  const options = item.variants.map((variant) => `<option value="${escapeHTML(variant.doc_id)}">${escapeHTML(variant.publication_name)}</option>`).join("");
@@ -1507,7 +1511,9 @@ function proofreadHTMLV2(item) {
1507
  const pdfPage = /\.pdf(?:$|\?)/i.test(selectedUrl) ? `#page=${page}` : "";
1508
  const sourceViewer = sourceFiles.length ? (isImageSource(selectedUrl)
1509
  ? `<div class="proofread-image-viewer" data-image-viewer><div class="proofread-image-tools"><button type="button" class="text-btn-sm" data-image-zoom="out">缩小</button><button type="button" class="text-btn-sm" data-image-zoom="reset">原始大小</button><button type="button" class="text-btn-sm" data-image-zoom="in">放大</button></div><div class="proofread-image-stage"><img data-proofread-source-image src="${sourceURL}" alt="原文件" data-image-scale="1"><a class="text-btn-sm proofread-image-download" href="${sourceDownload}">下载原文件</a></div></div>`
1510
- : `<iframe sandbox data-proofread-source title="原文件" src="${sourceURL}${pdfPage}"></iframe>`)
 
 
1511
  : '<div class="proofread-no-source"><strong>没有原文件</strong><span>仍可编辑正文并提交校对。</span></div>';
1512
  const partTypeOptions = (current) => PART_TYPES.map((type) => `<option value="${type}" ${type === current ? "selected" : ""}>${type}</option>`).join("");
1513
  const parts = (article.parts || []).map((part, index) => `<div class="proofread-part-group" data-proofread-part-group="${index}"><div data-part-insert-before></div><label class="proofread-field proofread-part" data-proofread-part="${index}"><span>段落 ${index + 1} / <select data-proofread-part-type="${index}">${partTypeOptions(part.type || "paragraph")}</select></span><span class="proofread-part-actions"><button type="button" class="text-btn-sm" data-add-part-before="${index}">在上新建段落</button><button type="button" class="text-btn-sm" data-add-part-after="${index}">在下新建段落</button><button type="button" class="text-btn-sm" data-delete-part="${index}">删除当前段落</button></span><textarea data-proofread-part-input="${index}">${escapeHTML(partTextWithPivots(article, index))}</textarea></label><div data-part-insert-after></div></div>`).join("");
@@ -1551,12 +1557,34 @@ function openProofread(item, focusPart = null, restoring = false) {
1551
  if (!restoring) syncUrl(true);
1552
  DOM.previewPanel.classList.add("proofread-mode");
1553
  DOM.previewPanel.innerHTML = proofreadHTMLV2(item);
 
 
 
 
 
 
1554
  const sourceImage = DOM.previewPanel.querySelector("[data-proofread-source-image]");
1555
  if (sourceImage) sourceImage.addEventListener("error", () => {
1556
  const stage = sourceImage.closest("[data-image-stage], .proofread-image-stage");
1557
  if (stage) stage.innerHTML = `<div class="proofread-no-source"><strong>图片无法在线显示</strong><a class="text-btn-sm" href="${sourceDownloadURL(item, STATE.proofreadFile || 0)}">下载原文件</a></div>`;
1558
  }, { once: true });
1559
  const form = DOM.previewPanel.querySelector("[data-proofread-form]");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1560
  const sourceHeader = DOM.previewPanel.querySelector(".proofread-source .proofread-pane-header");
1561
  if (sourceHeader && !sourceHeader.querySelector("[data-proofread-page]")) {
1562
  sourceHeader.insertAdjacentHTML("beforeend", `<label class="proofread-page-control">页码 <input data-proofread-page type="number" min="1" value="${Math.max(1, Number(STATE.proofreadPage) || Number((item.article || {}).page_start) || 1)}"></label>`);
@@ -2115,10 +2143,14 @@ function attachEvents() {
2115
  }
2116
  const partEditorToggle = event.target.closest("[data-part-editor-toggle]");
2117
  if (partEditorToggle) {
2118
- const editor = DOM.previewPanel.querySelector("[data-part-editor]");
2119
- if (editor) {
2120
- editor.hidden = !editor.hidden;
2121
- partEditorToggle.textContent = editor.hidden ? "段落编辑" : "收起段落编辑";
 
 
 
 
2122
  }
2123
  return;
2124
  }
 
1357
  return /\.(?:bmp|gif|jpe?g|png|tiff?|webp)(?:$|\?)/i.test(String(url || ""));
1358
  }
1359
 
1360
+ function isPDFSource(url) {
1361
+ return /\.pdf(?:$|\?)/i.test(String(url || ""));
1362
+ }
1363
+
1364
  async function openRandomPreview() {
1365
  const requestSeq = randomRequestSeq + 1;
1366
  randomRequestSeq = requestSeq;
 
1454
 
1455
  function compareSelectHTML(item) {
1456
  const proofread = item.article && Array.isArray(item.article.parts)
1457
+ ? `<option value="__proofread__">${item.source_files && item.source_files.length ? "对比原文件并校对" : "校对"}</option>`
1458
  : "";
1459
  if ((!item.variants || !item.variants.length) && !proofread) return "";
1460
  const options = item.variants.map((variant) => `<option value="${escapeHTML(variant.doc_id)}">${escapeHTML(variant.publication_name)}</option>`).join("");
 
1511
  const pdfPage = /\.pdf(?:$|\?)/i.test(selectedUrl) ? `#page=${page}` : "";
1512
  const sourceViewer = sourceFiles.length ? (isImageSource(selectedUrl)
1513
  ? `<div class="proofread-image-viewer" data-image-viewer><div class="proofread-image-tools"><button type="button" class="text-btn-sm" data-image-zoom="out">缩小</button><button type="button" class="text-btn-sm" data-image-zoom="reset">原始大小</button><button type="button" class="text-btn-sm" data-image-zoom="in">放大</button></div><div class="proofread-image-stage"><img data-proofread-source-image src="${sourceURL}" alt="原文件" data-image-scale="1"><a class="text-btn-sm proofread-image-download" href="${sourceDownload}">下载原文件</a></div></div>`
1514
+ : (isPDFSource(selectedUrl)
1515
+ ? `<div class="proofread-document-viewer"><iframe data-proofread-source title="原文件" src="${sourceURL}${pdfPage}"></iframe><a class="text-btn-sm proofread-document-download" href="${sourceDownload}">下载原文件</a></div>`
1516
+ : `<div class="proofread-no-source"><strong>此原文件暂不支持在线预览</strong><a class="text-btn-sm" href="${sourceDownload}">下载原文件</a></div>`))
1517
  : '<div class="proofread-no-source"><strong>没有原文件</strong><span>仍可编辑正文并提交校对。</span></div>';
1518
  const partTypeOptions = (current) => PART_TYPES.map((type) => `<option value="${type}" ${type === current ? "selected" : ""}>${type}</option>`).join("");
1519
  const parts = (article.parts || []).map((part, index) => `<div class="proofread-part-group" data-proofread-part-group="${index}"><div data-part-insert-before></div><label class="proofread-field proofread-part" data-proofread-part="${index}"><span>段落 ${index + 1} / <select data-proofread-part-type="${index}">${partTypeOptions(part.type || "paragraph")}</select></span><span class="proofread-part-actions"><button type="button" class="text-btn-sm" data-add-part-before="${index}">在上新建段落</button><button type="button" class="text-btn-sm" data-add-part-after="${index}">在下新建段落</button><button type="button" class="text-btn-sm" data-delete-part="${index}">删除当前段落</button></span><textarea data-proofread-part-input="${index}">${escapeHTML(partTextWithPivots(article, index))}</textarea></label><div data-part-insert-after></div></div>`).join("");
 
1557
  if (!restoring) syncUrl(true);
1558
  DOM.previewPanel.classList.add("proofread-mode");
1559
  DOM.previewPanel.innerHTML = proofreadHTMLV2(item);
1560
+ if (!(item.source_files || []).length) {
1561
+ const sourcePane = DOM.previewPanel.querySelector(".proofread-source");
1562
+ if (sourcePane) sourcePane.remove();
1563
+ const grid = DOM.previewPanel.querySelector(".proofread-grid");
1564
+ if (grid) grid.classList.add("proofread-grid-no-source");
1565
+ }
1566
  const sourceImage = DOM.previewPanel.querySelector("[data-proofread-source-image]");
1567
  if (sourceImage) sourceImage.addEventListener("error", () => {
1568
  const stage = sourceImage.closest("[data-image-stage], .proofread-image-stage");
1569
  if (stage) stage.innerHTML = `<div class="proofread-no-source"><strong>图片无法在线显示</strong><a class="text-btn-sm" href="${sourceDownloadURL(item, STATE.proofreadFile || 0)}">下载原文件</a></div>`;
1570
  }, { once: true });
1571
  const form = DOM.previewPanel.querySelector("[data-proofread-form]");
1572
+ if (form) {
1573
+ form.classList.add("proofread-structure-closed");
1574
+ const partEditor = form.querySelector("[data-part-editor]");
1575
+ if (partEditor) partEditor.hidden = false;
1576
+ form.querySelectorAll("[data-proofread-part-type]").forEach((select) => {
1577
+ select.insertAdjacentHTML("afterend", `<span class="proofread-part-type-label">${escapeHTML(select.value)}</span>`);
1578
+ });
1579
+ const structureActions = form.querySelector(".proofread-form-actions");
1580
+ const descriptionInput = form.querySelector("[data-proofread-description]");
1581
+ const descriptionField = descriptionInput ? descriptionInput.closest(".proofread-field") : null;
1582
+ const descriptionLabel = descriptionField && descriptionField.querySelector("span");
1583
+ if (structureActions && descriptionLabel) {
1584
+ descriptionLabel.classList.add("proofread-description-heading");
1585
+ descriptionLabel.append(structureActions);
1586
+ }
1587
+ }
1588
  const sourceHeader = DOM.previewPanel.querySelector(".proofread-source .proofread-pane-header");
1589
  if (sourceHeader && !sourceHeader.querySelector("[data-proofread-page]")) {
1590
  sourceHeader.insertAdjacentHTML("beforeend", `<label class="proofread-page-control">页码 <input data-proofread-page type="number" min="1" value="${Math.max(1, Number(STATE.proofreadPage) || Number((item.article || {}).page_start) || 1)}"></label>`);
 
2143
  }
2144
  const partEditorToggle = event.target.closest("[data-part-editor-toggle]");
2145
  if (partEditorToggle) {
2146
+ const form = DOM.previewPanel.querySelector("[data-proofread-form]");
2147
+ if (form) {
2148
+ const open = form.classList.toggle("proofread-structure-open");
2149
+ partEditorToggle.textContent = open ? "收起段落编辑" : "段落编辑";
2150
+ form.querySelectorAll("[data-proofread-part-type]").forEach((select) => {
2151
+ const label = select.nextElementSibling;
2152
+ if (label && label.classList.contains("proofread-part-type-label")) label.textContent = select.value;
2153
+ });
2154
  }
2155
  return;
2156
  }
static/style.css CHANGED
@@ -570,6 +570,10 @@ ul, li {
570
  flex: 1;
571
  }
572
 
 
 
 
 
573
  .proofread-source,
574
  .proofread-editor {
575
  min-width: 0;
@@ -636,6 +640,31 @@ ul, li {
636
  border-radius: 4px;
637
  }
638
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
639
  .proofread-no-source {
640
  display: flex;
641
  min-height: 220px;
@@ -724,6 +753,35 @@ ul, li {
724
  gap: .35rem;
725
  flex-wrap: wrap;
726
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
727
  .proofread-page-control {
728
  display: inline-flex;
729
  align-items: center;
 
570
  flex: 1;
571
  }
572
 
573
+ .proofread-grid-no-source {
574
+ grid-template-columns: minmax(0, 1fr);
575
+ }
576
+
577
  .proofread-source,
578
  .proofread-editor {
579
  min-width: 0;
 
640
  border-radius: 4px;
641
  }
642
 
643
+ .proofread-document-viewer {
644
+ position: relative;
645
+ display: flex;
646
+ min-height: 520px;
647
+ flex: 1;
648
+ flex-direction: column;
649
+ }
650
+
651
+ .proofread-document-viewer iframe {
652
+ width: 100%;
653
+ min-height: 520px;
654
+ flex: 1;
655
+ border: 0;
656
+ background: #fff;
657
+ }
658
+
659
+ .proofread-document-download {
660
+ position: absolute;
661
+ top: 8px;
662
+ right: 8px;
663
+ padding: 5px 8px;
664
+ background: var(--surface);
665
+ border-radius: 4px;
666
+ }
667
+
668
  .proofread-no-source {
669
  display: flex;
670
  min-height: 220px;
 
753
  gap: .35rem;
754
  flex-wrap: wrap;
755
  }
756
+
757
+ .proofread-structure-closed .proofread-part-actions,
758
+ .proofread-structure-closed [data-proofread-part-type] {
759
+ display: none;
760
+ }
761
+
762
+ .proofread-part-type-label {
763
+ display: none;
764
+ }
765
+
766
+ .proofread-structure-closed .proofread-part-type-label {
767
+ display: inline;
768
+ }
769
+
770
+ .proofread-structure-closed .proofread-part > span:first-child {
771
+ display: flex;
772
+ align-items: center;
773
+ gap: .3rem;
774
+ }
775
+
776
+ .proofread-description-heading {
777
+ display: flex;
778
+ align-items: center;
779
+ gap: .5rem;
780
+ }
781
+
782
+ .proofread-description-heading .proofread-form-actions {
783
+ margin-left: auto;
784
+ }
785
  .proofread-page-control {
786
  display: inline-flex;
787
  align-items: center;