Merge pull request 'Bug573-PanBinjie' (#169) from Bug573-PanBinjie into Alpha-snapshot20240618
Reviewed-on: #169BUG543-JiWenkai
commit
329732038f
12
app/main.py
12
app/main.py
|
@ -2,7 +2,7 @@
|
|||
# Copyright 2019 (C) Hui Lan <hui.lan@cantab.net>
|
||||
# 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 Login import *
|
||||
from Article import *
|
||||
|
@ -11,6 +11,7 @@ from user_service import userService
|
|||
from account_service import accountService
|
||||
from admin_service import adminService, ADMIN_NAME
|
||||
import os
|
||||
from translate import *
|
||||
|
||||
app = Flask(__name__)
|
||||
app.secret_key = os.urandom(32)
|
||||
|
@ -118,6 +119,15 @@ def mainpage():
|
|||
number_of_essays=number_of_essays,
|
||||
ratio = ratio)
|
||||
|
||||
@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__':
|
||||
'''
|
||||
|
|
|
@ -17,21 +17,20 @@ function showBtnHandler() {
|
|||
}
|
||||
|
||||
function getWord() {
|
||||
return window.getSelection ? window.getSelection() : document.selection.createRange().text;
|
||||
return window.getSelection ? window.getSelection().toString() : document.selection.createRange().text;
|
||||
}
|
||||
|
||||
function highLight() {
|
||||
if (!isHighlight) return;
|
||||
let word = (getWord() + "").trim();
|
||||
let word = (getWord() + "").trim().replace(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g, "");
|
||||
let articleContent = document.getElementById("article").innerHTML; // innerHTML保留HTML标签来保持部分格式,且适配不同的浏览器
|
||||
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 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;
|
||||
const list = allWords.split(" "); // 将所有的生词放入一个list中
|
||||
if(word !== null && word !== "" && word !== " "){
|
||||
let articleContent_fb2 = articleContent;
|
||||
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);
|
||||
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>");
|
||||
}
|
||||
document.getElementById("article").innerHTML = articleContent;
|
||||
addClickEventToHighlightedWords();
|
||||
}
|
||||
|
||||
function cancelHighlighting() {
|
||||
|
@ -83,7 +83,62 @@ function toggleHighlighting() {
|
|||
isHighlight = true;
|
||||
highLight();
|
||||
}
|
||||
localStorage.setItem('highlightChecked', isHighlight);
|
||||
localStorage.setItem('highlightChecked', isHighlight);
|
||||
}
|
||||
|
||||
showBtnHandler();
|
||||
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.style.position = 'absolute';
|
||||
tooltip.style.background = 'yellow';
|
||||
|
||||
// 可以在这里添加点击事件监听器来隐藏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();
|
||||
|
|
|
@ -107,6 +107,7 @@
|
|||
<button onclick="toggle_visibility('answer');">ANSWER</button>
|
||||
<div id="answer" style="display:none;">{{ today_article['answer'] }}</div><br/>
|
||||
</div>
|
||||
<div id="tooltip"></div>
|
||||
</div>
|
||||
<div class="alert alert-success" role="alert" id="not_found" style="display:none;">
|
||||
<p class="text-muted"><span class="badge bg-success">Notes:</span><br>No article is currently available for you. You can try again a few times or mark new words in the passage to improve your level.</p>
|
||||
|
|
|
@ -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}"}
|
|
@ -4,5 +4,5 @@ PyYAML~=6.0
|
|||
pony==0.7.16
|
||||
snowballstemmer==2.2.0
|
||||
Werkzeug==2.2.2
|
||||
|
||||
pytest~=8.1.1
|
||||
requests
|
||||
pytest~=8.1.1
|
||||
|
|
Loading…
Reference in New Issue