Update worker.js
fix: resolve TypeError in HistoryManager by ensuring MathJax.typesetPromise is available - Fixed the uncaught TypeError caused by `MathJax.typesetPromise` not being a function. - Ensured MathJax is properly loaded before calling `typesetPromise`. - Updated the HistoryManager.displayHistory function to handle MathJax initialization correctly. Fixes issue at (索引):750:15 and (索引):923:22.
This commit is contained in:
		
							
								
								
									
										182
									
								
								worker.js
									
									
									
									
									
								
							
							
						
						
									
										182
									
								
								worker.js
									
									
									
									
									
								
							| @@ -188,14 +188,15 @@ async function recognizeImage(token, imageId) { | |||||||
|           content: [ |           content: [ | ||||||
|             {  |             {  | ||||||
|               type: 'text',  |               type: 'text',  | ||||||
|               text: '请识别图片中的内容。对于数学公式和数学符号,请使用标准的LaTeX格式输出。' + |               text: '请识别图片中的内容,并按以下要求输出:\n' + | ||||||
|                     '要求:\n' + |                     '1. 所有数学公式和数学符号都必须使用标准的LaTeX格式\n' + | ||||||
|                     '1. 所有数学公式和单个数学符号都要用LaTeX格式\n' + |                     '2. 行内公式使用单个$符号包裹,如:$x^2$\n' + | ||||||
|                     '2. 普通文本保持原样\n' + |                     '3. 独立公式块使用两个$$符号包裹,如:$$\\sum_{i=1}^n i^2$$\n' + | ||||||
|                     '3. 对于行内公式使用$单个符号$\n' + |                     '4. 普通文本保持原样,不要使用LaTeX格式\n' + | ||||||
|                     '4. 对于独立公式块使用$$公式$$\n' + |                     '5. 保持原文的段落格式和换行\n' + | ||||||
|                     '5. 严格保持原文的段落格式和换行\n' + |                     '6. 明显的换行使用\\n表示\n' + | ||||||
|                     '6. 当文本明显换行时,使用\\n进行换行处理' |                     '7. 不要输出任何额外的解释或说明\n' + | ||||||
|  |                     '8. 确保所有数学符号都被正确包裹在$或$$中' | ||||||
|             }, |             }, | ||||||
|             { type: 'image', image: imageId }, |             { type: 'image', image: imageId }, | ||||||
|           ], |           ], | ||||||
| @@ -209,13 +210,17 @@ async function recognizeImage(token, imageId) { | |||||||
|  |  | ||||||
|   const data = await response.json(); |   const data = await response.json(); | ||||||
|    |    | ||||||
|   // 处理识别结果 |   // 处理识别结果,增加额外的格式化步骤 | ||||||
|   let result = data.choices[0]?.message?.content || '识别失败'; |   let result = data.choices[0]?.message?.content || '识别失败'; | ||||||
|   result = result |   result = result | ||||||
|     .replace(/\\(/g, '\\(') |     .replace(/\\(/g, '\\(') | ||||||
|     .replace(/\\)/g, '\\)') |     .replace(/\\)/g, '\\)') | ||||||
|     .replace(/\n{3,}/g, '\n\n') |     .replace(/\n{3,}/g, '\n\n') | ||||||
|     .replace(/([^\n])\n([^\n])/g, '$1\n$2') |     .replace(/([^\n])\n([^\n])/g, '$1\n$2') | ||||||
|  |     // 确保数学公式被正确包裹 | ||||||
|  |     .replace(/\$\s+/g, '$') | ||||||
|  |     .replace(/\s+\$/g, '$') | ||||||
|  |     .replace(/\$\$/g, '$$') | ||||||
|     .trim(); |     .trim(); | ||||||
|  |  | ||||||
|   return new Response(JSON.stringify({  |   return new Response(JSON.stringify({  | ||||||
| @@ -240,7 +245,6 @@ function getHTML() { | |||||||
|      |      | ||||||
|     // 添加 MathJax 支持 |     // 添加 MathJax 支持 | ||||||
|     '<script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>', |     '<script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>', | ||||||
|     '<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>', |  | ||||||
|     '<script>', |     '<script>', | ||||||
|     'window.MathJax = {', |     'window.MathJax = {', | ||||||
|     '  tex: {', |     '  tex: {', | ||||||
| @@ -248,10 +252,35 @@ function getHTML() { | |||||||
|     '    displayMath: [["$$", "$$"]]', |     '    displayMath: [["$$", "$$"]]', | ||||||
|     '  },', |     '  },', | ||||||
|     '  startup: {', |     '  startup: {', | ||||||
|     '    typeset: false', |     '    pageReady: () => {', | ||||||
|  |     '      return MathJax.startup.defaultPageReady().then(() => {', | ||||||
|  |     '        // MathJax 加载完成后刷新历史记录', | ||||||
|  |     '        if (currentToken) {', | ||||||
|  |     '          historyManager.displayHistory(currentToken);', | ||||||
|  |     '        }', | ||||||
|  |     '      });', | ||||||
|  |     '    }', | ||||||
|  |     '  },', | ||||||
|  |     '  options: {', | ||||||
|  |     '    enableMenu: false', | ||||||
|     '  }', |     '  }', | ||||||
|     '};', |     '};', | ||||||
|     '</script>', |     '</script>', | ||||||
|  |     '<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>', | ||||||
|  |     '<script>', | ||||||
|  |     'function waitForMathJax(callback, maxTries = 30) {', | ||||||
|  |     '  let tries = 0;', | ||||||
|  |     '  const checkMathJax = () => {', | ||||||
|  |     '    tries++;', | ||||||
|  |     '    if (window.MathJax && window.MathJax.typesetPromise) {', | ||||||
|  |     '      callback();', | ||||||
|  |     '    } else if (tries < maxTries) {', | ||||||
|  |     '      setTimeout(checkMathJax, 100);', | ||||||
|  |     '    }', | ||||||
|  |     '  };', | ||||||
|  |     '  checkMathJax();', | ||||||
|  |     '}', | ||||||
|  |     '</script>', | ||||||
|      |      | ||||||
|     '<style>', |     '<style>', | ||||||
|     '    * {', |     '    * {', | ||||||
| @@ -1053,8 +1082,14 @@ function getHTML() { | |||||||
|     '      }', |     '      }', | ||||||
|      |      | ||||||
|     '      var html = \'\';', |     '      var html = \'\';', | ||||||
|     '      for (var i = 0; i < history.length; i++) {', |     '      history.forEach((record, i) => {', | ||||||
|     '        var record = history[i];', |     '        // 确保 image 数据存在且格式正确', | ||||||
|  |     '        const imageUrl = record.image && (', | ||||||
|  |     '          record.image.startsWith(\'data:\') ? ', | ||||||
|  |     '          record.image : ', | ||||||
|  |     '          `data:image/png;base64,${record.image}`', | ||||||
|  |     '        );', | ||||||
|  |      | ||||||
|     '        const timestamp = new Date(record.timestamp);', |     '        const timestamp = new Date(record.timestamp);', | ||||||
|     '        const timeStr = timestamp.toLocaleString(\'zh-CN\', {', |     '        const timeStr = timestamp.toLocaleString(\'zh-CN\', {', | ||||||
|     '          year: \'numeric\',', |     '          year: \'numeric\',', | ||||||
| @@ -1063,30 +1098,44 @@ function getHTML() { | |||||||
|     '          hour: \'2-digit\',', |     '          hour: \'2-digit\',', | ||||||
|     '          minute: \'2-digit\'', |     '          minute: \'2-digit\'', | ||||||
|     '        });', |     '        });', | ||||||
|     '        html += \'<div class="history-item">\';', |  | ||||||
|     '        html += \'<div class="history-image-container">\';', |  | ||||||
|     '        html += \'<img src="\' + record.image + \'" class="history-image" alt="历史图片" onclick="showFullImage(this.src)">\';', |  | ||||||
|     '        html += \'<div class="image-overlay">\';', |  | ||||||
|     '        html += \'<button class="overlay-btn" onclick="showFullImage(\\\'\' + record.image + \'\\\')">查看大图</button>\';', |  | ||||||
|     '        html += \'</div>\';', |  | ||||||
|     '        html += \'</div>\';', |  | ||||||
|      |      | ||||||
|     '        html += \'<div class="history-content">\';', |     '        html += `', | ||||||
|     '        html += \'<div class="history-header">\';', |     '          <div class="history-item" data-index="${i}">', | ||||||
|     '        html += \'<span class="history-time">\' + timeStr + \'</span>\';', |     '            <div class="history-image-container">', | ||||||
|     '        html += \'<div class="history-actions">\';', |     '              <img src="${imageUrl}" ', | ||||||
|     '        html += \'<button class="action-btn copy-btn" onclick="copyHistoryResult(\' + i + \')">复制结果</button>\';', |     '                   class="history-image" ', | ||||||
|     '        html += \'<button class="action-btn delete-btn" onclick="deleteHistoryItem(\' + i + \')">删除</button>\';', |     '                   alt="历史图片" ', | ||||||
|     '        html += \'</div>\';', |     '                   onerror="this.src=\'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=\'"', | ||||||
|     '        html += \'</div>\';', |     '                   onclick="event.stopPropagation(); showFullImage(\'${imageUrl}\')">', | ||||||
|     '        html += \'<div class="history-text">\' + record.result + \'</div>\';', |     '              <div class="image-overlay">', | ||||||
|     '        html += \'</div>\';', |     '                <button class="overlay-btn" onclick="event.stopPropagation(); showFullImage(\'${imageUrl}\')">查看大图</button>', | ||||||
|     '        html += \'</div>\';', |     '              </div>', | ||||||
|     '      }', |     '            </div>', | ||||||
|  |     '            <div class="history-content">', | ||||||
|  |     '              <div class="history-header">', | ||||||
|  |     '                <span class="history-time">${timeStr}</span>', | ||||||
|  |     '                <div class="history-actions">', | ||||||
|  |     '                  <button class="action-btn copy-btn" onclick="event.stopPropagation(); copyHistoryResult(${i})">复制结果</button>', | ||||||
|  |     '                  <button class="action-btn delete-btn" onclick="event.stopPropagation(); deleteHistoryItem(${i})">删除</button>', | ||||||
|  |     '                </div>', | ||||||
|  |     '              </div>', | ||||||
|  |     '              <div class="history-text">${record.result || \'无识别结果\'}</div>', | ||||||
|  |     '            </div>', | ||||||
|  |     '          </div>', | ||||||
|  |     '        `;', | ||||||
|  |     '      });', | ||||||
|  |      | ||||||
|     '      historyList.innerHTML = html;', |     '      historyList.innerHTML = html;', | ||||||
|      |      | ||||||
|     '      // 渲染数学公式', |     '      // 使用 waitForMathJax 函数处理公式渲染', | ||||||
|     '      MathJax.typesetPromise([historyList]);', |     '      waitForMathJax(() => {', | ||||||
|  |     '        try {', | ||||||
|  |     '          MathJax.typesetPromise([historyList])', | ||||||
|  |     '            .catch(err => console.error("MathJax渲染错误:", err));', | ||||||
|  |     '        } catch (err) {', | ||||||
|  |     '          console.error("MathJax处理错误:", err);', | ||||||
|  |     '        }', | ||||||
|  |     '      });', | ||||||
|     '    };', |     '    };', | ||||||
|      |      | ||||||
|     '    // 初始化变量', |     '    // 初始化变量', | ||||||
| @@ -1216,9 +1265,21 @@ function getHTML() { | |||||||
|     '        }', |     '        }', | ||||||
|      |      | ||||||
|     '        const result = recognizeData.result || \'识别失败\';', |     '        const result = recognizeData.result || \'识别失败\';', | ||||||
|     '        resultDiv.innerHTML = result;   // 使用innerHTML而不是textContent以支持公式渲染', |     '        resultDiv.innerHTML = result;', | ||||||
|     '        MathJax.typesetPromise([resultDiv]).then(() => {',  // 渲染数学公式', |     '        waitForMathJax(() => {', | ||||||
|     '          resultContainer.classList.add(\'show\');', |     '          try {', | ||||||
|  |     '            MathJax.typesetPromise([resultDiv])', | ||||||
|  |     '              .then(() => {', | ||||||
|  |     '                resultContainer.classList.add(\'show\');', | ||||||
|  |     '              })', | ||||||
|  |     '              .catch(err => {', | ||||||
|  |     '                console.error("MathJax渲染错误:", err);', | ||||||
|  |     '                resultContainer.classList.add(\'show\');', | ||||||
|  |     '              });', | ||||||
|  |     '          } catch (err) {', | ||||||
|  |     '            console.error("MathJax处理错误:", err);', | ||||||
|  |     '            resultContainer.classList.add(\'show\');', | ||||||
|  |     '          }', | ||||||
|     '        });', |     '        });', | ||||||
|      |      | ||||||
|     '        // 添加到历史记录', |     '        // 添加到历史记录', | ||||||
| @@ -1290,13 +1351,27 @@ function getHTML() { | |||||||
|     '    const modalImg = document.getElementById(\'modalImage\');', |     '    const modalImg = document.getElementById(\'modalImage\');', | ||||||
|      |      | ||||||
|     '    function showFullImage(src) {', |     '    function showFullImage(src) {', | ||||||
|     '      modal.style.display = "block";', |     '      const modal = document.getElementById(\'imageModal\');', | ||||||
|     '      modalImg.src = src;', |     '      const modalImg = document.getElementById(\'modalImage\');', | ||||||
|     '      modalImg.style.opacity = "0";', |        | ||||||
|  |     '      if (!src) {', | ||||||
|  |     '        console.error(\'图片源为空\');', | ||||||
|  |     '        return;', | ||||||
|  |     '      }', | ||||||
|      |      | ||||||
|  |     '      modal.style.display = \'block\';', | ||||||
|  |     '      modalImg.src = src;', | ||||||
|  |        | ||||||
|  |     '      // 添加加载错误处理', | ||||||
|  |     '      modalImg.onerror = function() {', | ||||||
|  |     '        alert(\'图片加载失败\');', | ||||||
|  |     '        modal.style.display = \'none\';', | ||||||
|  |     '      };', | ||||||
|  |      | ||||||
|  |     '      modalImg.style.opacity = \'0\';', | ||||||
|     '      setTimeout(() => {', |     '      setTimeout(() => {', | ||||||
|     '        modalImg.style.transition = "opacity 0.3s ease";', |     '        modalImg.style.transition = \'opacity 0.3s ease\';', | ||||||
|     '        modalImg.style.opacity = "1";', |     '        modalImg.style.opacity = \'1\';', | ||||||
|     '      }, 50);', |     '      }, 50);', | ||||||
|     '    }', |     '    }', | ||||||
|      |      | ||||||
| @@ -1404,27 +1479,38 @@ function getHTML() { | |||||||
|     '    // 复制历史记录结果', |     '    // 复制历史记录结果', | ||||||
|     '    async function copyHistoryResult(index) {', |     '    async function copyHistoryResult(index) {', | ||||||
|     '      const history = historyManager.loadHistory(currentToken);', |     '      const history = historyManager.loadHistory(currentToken);', | ||||||
|     '      const result = history[index].result;', |     '      const result = history[index]?.result;', | ||||||
|  |        | ||||||
|  |     '      if (!result) {', | ||||||
|  |     '        alert(\'无法复制:结果为空\');', | ||||||
|  |     '        return;', | ||||||
|  |     '      }', | ||||||
|  |      | ||||||
|     '      try {', |     '      try {', | ||||||
|     '        await navigator.clipboard.writeText(result);', |     '        await navigator.clipboard.writeText(result);', | ||||||
|     '        const btn = event.target;', |     '        const btn = event.target;', | ||||||
|     '        btn.textContent = \'已复制\';', |     '        btn.textContent = \'已复制\';', | ||||||
|     '        btn.style.background = \'#27ae60\';', |     '        btn.classList.add(\'copied\');', | ||||||
|     '        btn.style.color = \'#fff\';', |          | ||||||
|     '        setTimeout(() => {', |     '        setTimeout(() => {', | ||||||
|     '          btn.textContent = \'复制结果\';', |     '          btn.textContent = \'复制结果\';', | ||||||
|     '          btn.style.background = \'none\';', |     '          btn.classList.remove(\'copied\');', | ||||||
|     '          btn.style.color = \'#3498db\';', |  | ||||||
|     '        }, 2000);', |     '        }, 2000);', | ||||||
|     '      } catch (err) {', |     '      } catch (err) {', | ||||||
|     '        console.error(\'复制失败:\', err);', |     '        console.error(\'复制失败:\', err);', | ||||||
|  |     '        alert(\'复制失败,请手动复制\');', | ||||||
|     '      }', |     '      }', | ||||||
|     '    }', |     '    }', | ||||||
|      |      | ||||||
|     '    // 删除历史记录项', |     '    // 删除历史记录项', | ||||||
|     '    function deleteHistoryItem(index) {', |     '    function deleteHistoryItem(index) {', | ||||||
|  |     '      const history = historyManager.loadHistory(currentToken);', | ||||||
|  |     '      if (!history[index]) {', | ||||||
|  |     '        alert(\'该记录不存在\');', | ||||||
|  |     '        return;', | ||||||
|  |     '      }', | ||||||
|  |      | ||||||
|     '      if (confirm(\'确定要删除这条历史记录吗?\')) {', |     '      if (confirm(\'确定要删除这条历史记录吗?\')) {', | ||||||
|     '        const history = historyManager.loadHistory(currentToken);', |  | ||||||
|     '        history.splice(index, 1);', |     '        history.splice(index, 1);', | ||||||
|     '        historyManager.saveHistory(currentToken, history);', |     '        historyManager.saveHistory(currentToken, history);', | ||||||
|     '        historyManager.displayHistory(currentToken);', |     '        historyManager.displayHistory(currentToken);', | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 programmerWsy
					programmerWsy