2022-01-26 21:10:09 +08:00
<!DOCTYPE html>
< html lang = "en" >
< head >
< meta charset = "UTF-8" >
< meta name = "viewport"
content="width=device-width, initial-scale=1.0, minimum-scale=0.5, maximum-scale=3.0, user-scalable=yes"/>
< meta name = "format-detection" content = "telephone=no" / >
2023-08-11 19:28:53 +08:00
< link href = "https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.min.css" rel = "stylesheet" >
< script src = "https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/js/bootstrap.bundle.min.js" > < / script >
2022-01-26 21:10:09 +08:00
{{ yml['header'] | safe }}
{% if yml['css']['item'] %}
{% for css in yml['css']['item'] %}
< link href = "{{ css }}" rel = "stylesheet" >
{% endfor %}
{% endif %}
{% if yml['js']['head'] %}
{% for js in yml['js']['head'] %}
< script src = "{{ js }}" > < / script >
{% endfor %}
{% endif %}
< title > EnglishPal Study Room for {{ username }}< / title >
2023-01-29 12:01:19 +08:00
< style >
2023-08-12 17:36:49 +08:00
.shaking {
animation: shakes 1600ms ease-in-out;
}
2023-01-29 12:01:19 +08:00
2023-08-12 17:36:49 +08:00
@keyframes shakes {
10%, 90% { transform: translate3d(-1px, 0, 0); }
20%, 50% { transform: translate3d(+2px, 0, 0); }
30%, 70% { transform: translate3d(-4px, 0, 0); }
40%, 60% { transform: translate3d(+4px, 0, 0); }
50% { transform: translate3d(-4px, 0, 0); }
}
2023-06-15 15:54:46 +08:00
2023-08-12 17:36:49 +08:00
.lead{
font-size: 22px;
font-family: Helvetica, sans-serif;
white-space: pre-wrap;
}
2023-08-10 10:03:02 +08:00
2023-08-12 17:36:49 +08:00
.arrow {
padding: 0;
2023-08-13 21:08:13 +08:00
font-size: 20px;
line-height: 21px;
2023-08-12 17:36:49 +08:00
display: inline-block;
}
2023-06-15 15:54:46 +08:00
2023-08-12 17:36:49 +08:00
.arrow:hover {
cursor: pointer;
}
2023-06-15 15:54:46 +08:00
2023-01-29 12:01:19 +08:00
< / style >
2022-01-26 21:10:09 +08:00
< / head >
< body >
< div class = "container-fluid" >
2022-07-18 13:29:04 +08:00
< p > < b > English Pal for < font id = "username" color = "red" > {{ username }}< / font > < / b >
2023-04-25 08:47:22 +08:00
2023-03-23 13:35:10 +08:00
{% if username == admin_name %}
2022-12-31 18:25:13 +08:00
< a class = "btn btn-secondary" href = "/admin" role = "button" onclick = "stopRead()" > 管理< / a >
2023-03-20 20:15:58 +08:00
{% endif %}
2023-04-25 08:47:22 +08:00
< a id = "quit" class = "btn btn-secondary" href = "/logout" role = "button" onclick = "stopRead()" > 退出< / a >
2022-11-25 15:42:37 +08:00
< a class = "btn btn-secondary" href = "/reset" role = "button" onclick = "stopRead()" > 重设密码< / a >
2023-04-25 08:47:22 +08:00
2022-01-26 21:10:09 +08:00
< / p >
2023-08-11 19:14:51 +08:00
{% for message in get_flashed_messages() %}
2023-08-11 19:28:53 +08:00
< div class = "alert alert-warning alert-dismissible fade show" role = "alert" >
{{ message }}
< button type = "button" class = "btn-close" data-bs-dismiss = "alert" aria-label = "Close" > < / button >
< / div >
2023-08-11 19:14:51 +08:00
{% endfor %}
2022-01-27 11:27:26 +08:00
2023-08-12 17:36:49 +08:00
< button class = "arrow" id = "load_next_article" onclick = "load_next_article();Reader.stopRead()" title = "下一篇 Next Article" > ⇨< / button >
< button class = "arrow" id = "load_pre_article" onclick = "load_pre_article();Reader.stopRead()" style = "display: none" title = "上一篇 Previous Article" > ⇦< / button >
2022-07-21 23:13:33 +08:00
2022-01-26 21:10:09 +08:00
< p > < b > 阅读文章并回答问题< / b > < / p >
2023-03-08 16:33:13 +08:00
< div id = "text-content" >
2023-05-11 15:51:10 +08:00
< div id = "found" >
2023-08-10 19:12:30 +08:00
< div class = "alert alert-success" role = "alert" > According to your word list, your level is < span class = "text-decoration-underline" id = "user_level" > {{ today_article["user_level"] }}< / span > and we have chosen an article with a difficulty level of < span class = "text-decoration-underline" id = "text_level" > {{ today_article["text_level"] }}< / span > for you.< / div >
2023-05-08 14:33:48 +08:00
< p class = "text-muted" id = "date" > Article added on: {{ today_article["date"] }}< / p > < br / >
2023-06-15 15:54:46 +08:00
< div class = "p-3 mb-2 bg-light text-dark" style = "margin: 0 0.5%;" > < br / >
2023-08-10 10:03:02 +08:00
< p class = "display-6" id = "article_title" > {{ today_article["article_title"] }}< / p > < br / >
2023-06-15 15:54:46 +08:00
< p class = "lead" > < font id = "article" > {{ today_article["article_body"] }}< / font > < / p > < br / >
< div >
< p > < small class = "text-muted" id = "source" > {{ today_article['source'] }}< / small > < / p > < br / >
< / div >
2024-03-27 12:39:42 +08:00
2023-05-08 14:33:48 +08:00
< p > < b id = "question" > {{ today_article['question'] }}< / b > < / p > < br / >
2023-03-08 16:33:13 +08:00
< script type = "text/javascript" >
function toggle_visibility(id) { {# https://css-tricks.com/snippets/javascript/showhide-element/#}
const e = document.getElementById(id);
if(e.style.display === 'block')
e.style.display = 'none';
else
e.style.display = 'block';
}
< / script >
< button onclick = "toggle_visibility('answer');" > ANSWER< / button >
< div id = "answer" style = "display:none;" > {{ today_article['answer'] }}< / div > < br / >
< / div >
2023-05-11 15:51:10 +08:00
< / 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 >
< / div >
< div class = "alert alert-success" role = "alert" id = "read_all" style = "display:none;" >
< p class = "text-muted" > < span class = "badge bg-success" > Notes:< / span > < br > You've read all the articles.< / p >
< / div >
2023-03-08 16:33:13 +08:00
< / div >
2022-01-27 11:27:26 +08:00
2024-03-27 12:39:42 +08:00
< input type = "checkbox" id = "highlightCheckbox" onclick = "toggleHighlighting()" / > 生词高亮
< input type = "checkbox" id = "readCheckbox" onclick = "onReadClick()" / > 大声朗读
< input type = "checkbox" id = "chooseCheckbox" onclick = "onChooseClick()" / > 划词入库
2022-07-18 16:00:08 +08:00
< div class = "range" >
< div class = "field" >
< div class = "sliderValue" >
< span id = "rangeValue" > 1× < / span >
< / div >
2024-04-09 21:21:19 +08:00
< input type = "range" id = "rangeComponent" min = "0.5" max = "2" value = "1" step = "0.25" / >
2022-07-18 16:00:08 +08:00
< / div >
2023-02-21 20:05:48 +08:00
< / div >
2022-01-26 21:10:09 +08:00
< p > < b > 收集生词吧< / b > (可以在正文中划词,也可以复制黏贴)< / p >
2023-04-20 20:30:14 +08:00
< form method = "post" action = "/{{ username }}/userpage" >
2022-01-26 21:10:09 +08:00
< textarea name = "content" id = "selected-words" rows = "10" cols = "120" > < / textarea > < br / >
2023-08-12 17:42:25 +08:00
< button class = "btn btn-primary btn-lg" type = "submit" onclick = "Reader.stopRead()" > 把生词加入我的生词库< / button >
2024-03-27 12:39:42 +08:00
< button class = "btn btn-primary btn-lg" type = "reset" onclick = "clearSelectedWords()" > 清除< / button >
2022-01-26 21:10:09 +08:00
< / form >
{% if session.get['thisWord'] %}
< script type = "text/javascript" >
//point to the anchor in the page whose id is aaa if it exists
window.onload = function () {
var element = document.getElementsByName("aaa");
if (element != null)
document.getElementsByName("aaa")[0].scrollIntoView(true);
}
< / script >
{% endif %}
{% if d_len > 0 %}
2023-01-29 12:01:19 +08:00
< p >
2024-03-27 12:39:42 +08:00
< b > 我的生词簿< / b >
2023-01-29 12:01:19 +08:00
< label for = "move_dynamiclly" >
< input type = "checkbox" name = "move_dynamiclly" id = "move_dynamiclly" checked >
允许动态调整顺序
< / label >
< / p >
< a name = "aaa" > < / a >
< div class = "word-container" >
{% for x in lst3 %}
{% set word = x[0] %}
{% set freq = x[1] %}
{% if session.get('thisWord') == x[0] and session.get('time') == 1 %}
{% endif %}
< p id = 'p_{{ word }}' class = "new-word" >
< a id = "word_{{ word }}" class = "btn btn-light" href = 'http://youdao.com/w/eng/{{ word }}/#keyfrom=dict2.index'
role="button">{{ word }}< / a >
( < a id = "freq_{{ word }}" title = "{{ word }}" > {{ freq }}< / a > )
< a class = "btn btn-success" onclick = "familiar('{{ word }}')" role = "button" > 熟悉< / a >
< a class = "btn btn-warning" onclick = "unfamiliar('{{ word }}')" role = "button" > 不熟悉< / a >
< a class = "btn btn-danger" onclick = "delete_word('{{ word }}')" role = "button" > 删除< / a >
2023-05-25 17:35:31 +08:00
< a class = "btn btn-info" onclick = "read_word('{{ word }}')" role = "button" > 朗读< / a >
2023-01-29 12:01:19 +08:00
< / p >
{% endfor %}
< / div >
2022-01-26 21:10:09 +08:00
< input id = "selected-words2" type = "hidden" value = "{{ words }}" >
{% endif %}
< / div >
{{ yml['footer'] | safe }}
{% if yml['js']['bottom'] %}
{% for js in yml['js']['bottom'] %}
< script src = "{{ js }}" > < / script >
{% endfor %}
{% endif %}
2023-05-11 15:51:10 +08:00
< script type = "text/javascript" >
2023-06-21 16:48:45 +08:00
window.onload = function () { // 页面加载时执行
2024-04-09 21:21:19 +08:00
const settings = {
// initialize settings from localStorage
highlightChecked: localStorage.getItem('highlightChecked') !== 'false', // localStorage stores strings, default to true. same below
readChecked: localStorage.getItem('readChecked') !== 'false',
chooseChecked: localStorage.getItem('chooseChecked') !== 'false',
rangeValue: localStorage.getItem('rangeValue') || '1',
selectedWords: localStorage.getItem('selectedWords') || ''
};
const elements = {
highlightCheckbox: document.querySelector('#highlightCheckbox'),
readCheckbox: document.querySelector('#readCheckbox'),
chooseCheckbox: document.querySelector('#chooseCheckbox'),
rangeComponent: document.querySelector('#rangeComponent'),
rangeValueDisplay: document.querySelector('#rangeValue'),
selectedWordsInput: document.querySelector('#selected-words')
};
// 应用设置到页面元素
elements.highlightCheckbox.checked = settings.highlightChecked;
elements.readCheckbox.checked = settings.readChecked;
elements.chooseCheckbox.checked = settings.chooseChecked;
elements.rangeComponent.value = settings.rangeValue;
elements.rangeValueDisplay.textContent = `${settings.rangeValue}x`;
elements.selectedWordsInput.value = settings.selectedWords;
2024-03-27 12:39:42 +08:00
2023-06-21 16:48:45 +08:00
// 刷新页面或进入页面时判断,若不是首篇文章,则上一篇按钮可见
2024-04-09 21:21:19 +08:00
if (sessionStorage.getItem('pre_page_button') !== 'display' & & sessionStorage.getItem('pre_page_button')) {
2023-06-21 16:48:45 +08:00
$('#load_pre_article').show();
}
2024-03-27 12:39:42 +08:00
2024-04-09 21:21:19 +08:00
// 事件监听器
elements.selectedWordsInput.addEventListener('input', () => {
localStorage.setItem('selectedWords', elements.selectedWordsInput.value);
});
elements.rangeComponent.addEventListener('input', () => {
const rangeValue = elements.rangeComponent.value;
elements.rangeValueDisplay.textContent = `${rangeValue}x`;
localStorage.setItem('rangeValue', rangeValue);
});
2024-05-27 21:22:56 +08:00
startTime=Date.now();//记录用户页面的初始时间
if(window.performance.navigation.type!=1){//将第一次加载页面时的文章id,level保存到本地
sessionStorage.setItem('article_id','{{today_article['article_id']}}');
sessionStorage.setItem('text_level','{{today_article['text_level']}}');
}
2024-04-09 21:21:19 +08:00
};
2024-03-27 12:39:42 +08:00
function clearSelectedWords() {
localStorage.removeItem('selectedWords');
2024-04-09 21:21:19 +08:00
document.querySelector('#selected-words').value = '';
2024-03-27 12:39:42 +08:00
}
2023-05-08 14:33:48 +08:00
function load_next_article(){
2024-05-27 21:22:56 +08:00
//在进入下一篇之前处理
endTime=Date.now();//记录用户点击下一篇文章时的时间
spendtime=endTime-startTime;//计算出用户浏览该页面的时长,单位毫秒
if(spendtime/1000>15){//若浏览时长大于15, 说明用户认真阅读了该篇文章( 时长小于15代表用户不感兴趣, 跳过, 不做任何处理)
if(!checkMarkedWords()){//检查该篇文章是否有生词高亮, 若没有将文章id,level发送到后台, 保存至文件中, 在计算用户level时根据文件中保存的文章等级计算
$.ajax({
url: '/submit_article_id_without_new_words/{{username}}/'+sessionStorage.getItem('article_id')+'/'+sessionStorage.getItem('text_level'),
dataType: 'json',
success: function(data) {}
});
}
}
2023-05-08 14:33:48 +08:00
$.ajax({
url: '/get_next_article/{{username}}',
dataType: 'json',
success: function(data) {
// 更新页面内容
2023-05-11 15:51:10 +08:00
if(data['today_article']){
update(data['today_article']);
check_pre(data['visited_articles']);
check_next(data['result_of_generate_article']);
}
2023-05-08 14:33:48 +08:00
}
});
2024-05-27 21:22:56 +08:00
startTime=Date.now();//在页面加载完下一篇文章,记录起始时间
2023-05-08 14:33:48 +08:00
}
function load_pre_article(){
2024-05-27 21:22:56 +08:00
//在进入上一篇之前处理
endTime=Date.now();//记录用户点击上一篇文章时的时间
spendtime=endTime-startTime;//计算出用户浏览该文章的时长,单位毫秒
if(spendtime/1000>15){
if(!checkMarkedWords()){
$.ajax({
url: '/submit_article_id_without_new_words/{{username}}/'+sessionStorage.getItem('article_id')+'/'+sessionStorage.getItem('text_level'),
dataType: 'json',
success: function(data) {}
});
}
}
2023-05-08 14:33:48 +08:00
$.ajax({
url: '/get_pre_article/{{username}}',
dataType: 'json',
success: function(data) {
// 更新页面内容
2023-05-11 15:51:10 +08:00
if(data['today_article']){
update(data['today_article']);
check_pre(data['visited_articles']);
2023-05-08 14:33:48 +08:00
}
}
});
2024-05-27 21:22:56 +08:00
startTime=Date.now();//在页面加载完下一篇文章,记录起始时间
2023-05-11 15:51:10 +08:00
}
function update(today_article){
2023-08-10 19:12:30 +08:00
$('#user_level').html(today_article['user_level']);
2023-05-11 15:51:10 +08:00
$('#text_level').html(today_article["text_level"]);
$('#date').html('Article added on: '+today_article["date"]);
$('#article_title').html(today_article["article_title"]);
$('#article').html(today_article["article_body"]);
$('#source').html(today_article['source']);
$('#question').html(today_article["question"]);
$('#answer').html(today_article["answer"]);
2023-08-10 19:09:15 +08:00
document.querySelector('#text_level').classList.add('mark'); // highlight text difficult level for 2 seconds
setTimeout(() => {document.querySelector('#text_level').classList.remove('mark');}, 2000);
2023-08-10 19:12:30 +08:00
document.querySelector('#user_level').classList.add('mark'); // do the same thing for user difficulty level
setTimeout(() => {document.querySelector('#user_level').classList.remove('mark');}, 2000);
2024-05-27 21:22:56 +08:00
sessionStorage.setItem('article_id',today_article["article_id"]);//将更新后的文章id,level保存到本地
sessionStorage.setItem('text_level',today_article['text_level']);
}
function checkMarkedWords(){//检查文章中是否有高亮生词
let article_title= document.getElementById("article_title").innerHTML;//从页面中获取文章名和内容
let article_body=document.getElementById("article").innerHTML;
let article=article_title+" "+article_body;
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;
const list = allWords.split(" "); // 将所有的生词放入一个list中
for (let i = 0; i < list.length ; + + i ) {
list[i] = list[i].replace(/(^\W*)|(\W*$)/g, "");
}
for (let i=1;i< list.length-1 ; i + + ) { / / 对 list 中 的 每 个 生 词 进 行 查 找 , 判 断 文 章 中 是 否 有 该 生 词
if(article.search(list[i])!==-1){
return true;
}
}
return false;
2023-05-11 15:51:10 +08:00
}
<!-- 检查是否存在上一篇或下一篇,不存在则对应按钮隐藏 -->
function check_pre(visited_articles){
if((visited_articles=='')||(visited_articles['index']< =0)){
$('#load_pre_article').hide();
2023-06-21 16:48:45 +08:00
sessionStorage.setItem('pre_page_button', 'display')
2023-05-11 15:51:10 +08:00
}else{
$('#load_pre_article').show();
2023-06-21 16:48:45 +08:00
sessionStorage.setItem('pre_page_button', 'show')
2023-05-11 15:51:10 +08:00
}
}
function check_next(result_of_generate_article){
if(result_of_generate_article == "found"){
$('#found').show();$('#not_found').hide();
$('#read_all').hide();
}else if(result_of_generate_article == "not found"){
$('#found').hide();
$('#not_found').show();
$('#read_all').hide();
}else{
$('#found').hide();
$('#not_found').hide();
$('#read_all').show();
}
2023-05-08 14:33:48 +08:00
}
< / script >
2022-01-26 21:10:09 +08:00
< / body >
< style >
mark {
2023-02-21 20:05:48 +08:00
color: #{{ yml['highlight']['color'] }};
background-color: rgba(0, 0, 0, 0);
}
2022-01-26 21:10:09 +08:00
< / style >
2022-01-27 20:15:26 +08:00
< / html >