forked from mrlan/EnglishPal
				
			解决合并冲突
							parent
							
								
									e3db7c30b0
								
							
						
					
					
						commit
						af59afc7e0
					
				
							
								
								
									
										12
									
								
								app/main.py
								
								
								
								
							
							
						
						
									
										12
									
								
								app/main.py
								
								
								
								
							|  | @ -2,7 +2,7 @@ | ||||||
| # Copyright 2019 (C) Hui Lan <hui.lan@cantab.net> | # Copyright 2019 (C) Hui Lan <hui.lan@cantab.net> | ||||||
| # Written permission must be obtained from the author for commercial uses. | # Written permission must be obtained from the author for commercial uses. | ||||||
| ########################################################################### | ########################################################################### | ||||||
| from flask import abort | from flask import abort, jsonify | ||||||
| from markupsafe import escape | from markupsafe import escape | ||||||
| from Login import * | from Login import * | ||||||
| from Article import * | from Article import * | ||||||
|  | @ -11,6 +11,7 @@ from user_service import userService | ||||||
| from account_service import accountService | from account_service import accountService | ||||||
| from admin_service import adminService, ADMIN_NAME | from admin_service import adminService, ADMIN_NAME | ||||||
| import os | import os | ||||||
|  | from translate import * | ||||||
| 
 | 
 | ||||||
| app = Flask(__name__) | app = Flask(__name__) | ||||||
| app.secret_key = os.urandom(32) | app.secret_key = os.urandom(32) | ||||||
|  | @ -104,6 +105,15 @@ def mainpage(): | ||||||
|                                yml=Yaml.yml, |                                yml=Yaml.yml, | ||||||
|                                number_of_essays=number_of_essays) |                                number_of_essays=number_of_essays) | ||||||
| 
 | 
 | ||||||
|  | @app.route("/translate", methods=['POST']) | ||||||
|  | def translate_word(): | ||||||
|  |     data = request.get_json() | ||||||
|  |     word = data.get('word', '') | ||||||
|  |     from_lang = data.get('from_lang', 'en')  # 假设默认源语言是英语 | ||||||
|  |     to_lang = data.get('to_lang', 'zh')     # 假设默认目标语言是中文 | ||||||
|  |     result = translate(word, from_lang, to_lang) | ||||||
|  |     return jsonify({'translation': result}) | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| if __name__ == '__main__': | if __name__ == '__main__': | ||||||
|     ''' |     ''' | ||||||
|  |  | ||||||
|  | @ -17,21 +17,20 @@ function showBtnHandler() { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function getWord() { | function getWord() { | ||||||
|     return window.getSelection ? window.getSelection() : document.selection.createRange().text; |     return window.getSelection ? window.getSelection().toString() : document.selection.createRange().text; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function highLight() { | function highLight() { | ||||||
|     if (!isHighlight) return; |     if (!isHighlight) return; | ||||||
|     let word = (getWord() + "").trim(); |     let word = (getWord() + "").trim().replace(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g, ""); | ||||||
|     let articleContent = document.getElementById("article").innerHTML; // innerHTML保留HTML标签来保持部分格式,且适配不同的浏览器
 |     let articleContent = document.getElementById("article").innerHTML; // innerHTML保留HTML标签来保持部分格式,且适配不同的浏览器
 | ||||||
|     let pickedWords = document.getElementById("selected-words");  // words picked to the text area
 |     let pickedWords = document.getElementById("selected-words");  // words picked to the text area
 | ||||||
|     let dictionaryWords = document.getElementById("selected-words2"); // words appearing in the user's new words list
 |     let dictionaryWords = document.getElementById("selected-words2"); // words appearing in the user's new words list
 | ||||||
|     let allWords = dictionaryWords === null ? pickedWords.value + " " : pickedWords.value + " " + dictionaryWords.value; |     let allWords = dictionaryWords === null ? pickedWords.value + " " : pickedWords.value + " " + dictionaryWords.value; | ||||||
|     highlightWords = document.getElementById("selected-words3"); |     let highlightWords = document.getElementById("selected-words3"); | ||||||
|     allWords = highlightWords == null ? allWords : allWords + " " + highlightWords.value; |     allWords = highlightWords == null ? allWords : allWords + " " + highlightWords.value; | ||||||
|     const list = allWords.split(" "); // 将所有的生词放入一个list中
 |     const list = allWords.split(" "); // 将所有的生词放入一个list中
 | ||||||
|     if(word !== null && word !== "" && word !== " "){ |     if(word !== null && word !== "" && word !== " "){ | ||||||
|         let articleContent_fb2 = articleContent; |  | ||||||
|         if(localStorage.getItem("nowWords").indexOf(word) !== -1 || localStorage.getItem("nowWords").indexOf(word.toLowerCase()) !== -1){ |         if(localStorage.getItem("nowWords").indexOf(word) !== -1 || localStorage.getItem("nowWords").indexOf(word.toLowerCase()) !== -1){ | ||||||
|             articleContent = articleContent.replace(new RegExp('<span class="highlighted">' + word + '</span>', "gi"), word); |             articleContent = articleContent.replace(new RegExp('<span class="highlighted">' + word + '</span>', "gi"), word); | ||||||
|             pickedWords.value = localStorage.getItem("nowWords").replace(word,""); |             pickedWords.value = localStorage.getItem("nowWords").replace(word,""); | ||||||
|  | @ -58,6 +57,7 @@ function highLight() { | ||||||
|         articleContent = articleContent.replace(new RegExp("\\b" + word + "\\b", "g"), "<span class='highlighted'>" + word + "</span>"); |         articleContent = articleContent.replace(new RegExp("\\b" + word + "\\b", "g"), "<span class='highlighted'>" + word + "</span>"); | ||||||
|     } |     } | ||||||
|     document.getElementById("article").innerHTML = articleContent; |     document.getElementById("article").innerHTML = articleContent; | ||||||
|  |     addClickEventToHighlightedWords(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function cancelHighlighting() { | function cancelHighlighting() { | ||||||
|  | @ -86,4 +86,59 @@ function toggleHighlighting() { | ||||||
|     localStorage.setItem('highlightChecked', isHighlight); |     localStorage.setItem('highlightChecked', isHighlight); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | function showWordMeaning(event) { | ||||||
|  |     const word = event.target.innerText.trim().replace(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g, "").toLowerCase(); | ||||||
|  |     const apiUrl = '/translate'; | ||||||
|  |     const rect = event.target.getBoundingClientRect(); | ||||||
|  |     const tooltipX = rect.left + window.scrollX; | ||||||
|  |     const tooltipY = rect.top + window.scrollY + rect.height; | ||||||
|  |     // 发送POST请求
 | ||||||
|  |     fetch(apiUrl, { | ||||||
|  |         method: 'POST', | ||||||
|  |         headers: { | ||||||
|  |             'Content-Type': 'application/json', | ||||||
|  |         }, | ||||||
|  |         body: JSON.stringify({ word: word }), // 发送的JSON数据
 | ||||||
|  |     }) | ||||||
|  |         .then(response => { | ||||||
|  |             if (!response.ok) { | ||||||
|  |                 throw new Error('Network response was not ok'); | ||||||
|  |             } | ||||||
|  |             return response.json(); // 解析JSON响应
 | ||||||
|  |         }) | ||||||
|  |         .then(data => { | ||||||
|  |             // 假设data.translation是翻译结果
 | ||||||
|  |             const tooltip = document.getElementById('tooltip'); | ||||||
|  |             if (!tooltip) { | ||||||
|  |                 console.error('Tooltip element not found'); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |             tooltip.textContent = data.translation || '没有找到该单词的中文意思'; | ||||||
|  |             tooltip.style.left = `${tooltipX}px`; | ||||||
|  |             tooltip.style.top = `${tooltipY}px`; | ||||||
|  |             tooltip.style.display = 'block'; | ||||||
|  | 
 | ||||||
|  |             // 可以在这里添加点击事件监听器来隐藏tooltip,但注意避免内存泄漏
 | ||||||
|  |             document.addEventListener('click', function handler(e) { | ||||||
|  |                 if (!tooltip.contains(e.target)) { | ||||||
|  |                     tooltip.style.display = 'none'; | ||||||
|  |                     document.removeEventListener('click', handler); | ||||||
|  |                 } | ||||||
|  |             }); | ||||||
|  |         }) | ||||||
|  |         .catch(error => { | ||||||
|  |             console.error('There was a problem with your fetch operation:', error); | ||||||
|  |         }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function addClickEventToHighlightedWords() { | ||||||
|  |     const highlightedWords = document.querySelectorAll('.highlighted'); | ||||||
|  |     highlightedWords.forEach(word => { | ||||||
|  |         word.addEventListener('click', showWordMeaning); | ||||||
|  |     }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| showBtnHandler(); | showBtnHandler(); | ||||||
|  | @ -0,0 +1,52 @@ | ||||||
|  | import requests | ||||||
|  | import hashlib | ||||||
|  | import time | ||||||
|  | from urllib.parse import urlencode | ||||||
|  | 
 | ||||||
|  | # 假设这是从某个配置文件中读取的 | ||||||
|  | class BaiduContent: | ||||||
|  |     APPID = '20240702002090356' | ||||||
|  |     SECRET = '3CcqcMAJdIIpgG0uMS_f' | ||||||
|  | 
 | ||||||
|  | def generate_sign(q, salt): | ||||||
|  |     """生成百度翻译API所需的签名""" | ||||||
|  |     appid = BaiduContent.APPID | ||||||
|  |     secret = BaiduContent.SECRET | ||||||
|  |     appid_with_data = appid + q + salt + secret | ||||||
|  |     md5_obj = hashlib.md5(appid_with_data.encode('utf-8')) | ||||||
|  |     return md5_obj.hexdigest() | ||||||
|  | 
 | ||||||
|  | def translate(q, from_lang, to_lang): | ||||||
|  |     """调用百度翻译API进行翻译""" | ||||||
|  |     salt = str(int(time.time()))  # 生成一个时间戳作为salt | ||||||
|  |     sign = generate_sign(q, salt) | ||||||
|  | 
 | ||||||
|  |     # 封装请求参数 | ||||||
|  |     params = { | ||||||
|  |         'q': q, | ||||||
|  |         'from': from_lang, | ||||||
|  |         'to': to_lang, | ||||||
|  |         'appid': BaiduContent.APPID, | ||||||
|  |         'salt': salt, | ||||||
|  |         'sign': sign | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     # 构造请求URL(百度翻译API使用POST请求,并将参数放在请求体中) | ||||||
|  |     url = "http://api.fanyi.baidu.com/api/trans/vip/translate" | ||||||
|  | 
 | ||||||
|  |     # 发送POST请求 | ||||||
|  |     headers = {'Content-Type': 'application/x-www-form-urlencoded'} | ||||||
|  |     data = urlencode(params).encode('utf-8')  # 注意:需要编码为bytes | ||||||
|  | 
 | ||||||
|  |     response = requests.post(url, data=data, headers=headers) | ||||||
|  | 
 | ||||||
|  |     # 检查响应状态码 | ||||||
|  |     if response.status_code == 200: | ||||||
|  |         # 解析并返回JSON响应体中的翻译结果 | ||||||
|  |         try: | ||||||
|  |             return response.json()['trans_result'][0]['dst'] | ||||||
|  |         except (KeyError, IndexError): | ||||||
|  |             return "Invalid response from API" | ||||||
|  |     else: | ||||||
|  |         # 返回错误信息或状态码 | ||||||
|  |         return {"error": f"Failed with status code {response.status_code}"} | ||||||
		Loading…
	
		Reference in New Issue