0
0
Fork 0

Bug521-LiYuFeng-Refactor (#72)

@mrlan
蓝老师:

    本次改进内容如下:
        1. 对生词居中问题进行修改,现在已经不会居中了。
        2. 对于单词数量基数大而导致的排序速度慢的问题,我们进行了优化,提升了排序的速度。
        3. 对用户交互进行了优化,当用户点击“熟悉”或“不熟悉”之后,会自动进行排序,并会跳转到那个单词的位置,用抖动的效果来提示用户。

Co-authored-by: isaac <1141730046@qq.com>
Reviewed-on: http://121.4.94.30:3000/mrlan/EnglishPal/pulls/72
Co-authored-by: 李雨峰 <1141730046@qq.com>
Co-committed-by: 李雨峰 <1141730046@qq.com>
SPM2022F-CONTRIBUTORS-WuWenZhuo
李雨峰 2023-01-29 12:01:19 +08:00 committed by mrlan
parent 972a1a5524
commit 9cdc9c6f7f
2 changed files with 177 additions and 26 deletions

View File

@ -7,10 +7,20 @@ function familiar(theWord) {
url:"/" + username + "/" + word + "/familiar", url:"/" + username + "/" + word + "/familiar",
success:function(response){ success:function(response){
let new_freq = freq - 1; let new_freq = freq - 1;
if(new_freq <1) { const allow_move = document.getElementById("move_dynamiclly").checked;
$("#p_" + theWord).remove(); if (allow_move) {
if (new_freq <= 0) {
removeWord(theWord);
} else {
renderWord({ word: theWord, freq: new_freq });
}
} else { } else {
$("#freq_" + theWord).text(new_freq); if(new_freq <1) {
$("#p_" + theWord).remove();
} else {
$("#freq_" + theWord).text(new_freq);
}
} }
} }
}); });
@ -25,7 +35,12 @@ function unfamiliar(theWord) {
url:"/" + username + "/" + word + "/unfamiliar", url:"/" + username + "/" + word + "/unfamiliar",
success:function(response){ success:function(response){
let new_freq = parseInt(freq) + 1; let new_freq = parseInt(freq) + 1;
$("#freq_" + theWord).text(new_freq); const allow_move = document.getElementById("move_dynamiclly").checked;
if (allow_move) {
renderWord({ word: theWord, freq: new_freq });
} else {
$("#freq_" + theWord).text(new_freq);
}
} }
}); });
} }
@ -37,7 +52,121 @@ function delete_word(theWord) {
type:"GET", type:"GET",
url:"/" + username + "/" + word + "/del", url:"/" + username + "/" + word + "/del",
success:function(response){ success:function(response){
$("#p_" + theWord).remove(); const allow_move = document.getElementById("move_dynamiclly").checked;
if (allow_move) {
removeWord(theWord);
} else {
$("#p_" + theWord).remove();
}
} }
}); });
} }
/*
* interface Word {
* word: string,
* freq: number
* }
* */
/**
* 传入一个词频HTML元素将其解析为Word类型的对象
*/
function parseWord(element) {
const word = element
.querySelector("a.btn.btn-light[role=button]") // 获取当前词频元素的词汇元素
.innerText // 获取词汇值;
const freq = Number.parseInt(element.querySelector(`#freq_${word}`).innerText); // 获取词汇的数量
return {
word,
freq
};
}
/**
* 使用模板将传入的单词转换为相应的HTML字符串
*/
function wordTemplate(word) {
// 这个模板应当与 templates/userpage_get.html 中的 <p id='p_${word.word}' class="new-word" > ... </p> 保持一致
return `<p id='p_${word.word}' class="new-word" >
<a id="word_${word.word}" class="btn btn-light" href='http://youdao.com/w/eng/${word.word}/#keyfrom=dict2.index'
role="button">${word.word}</a>
( <a id="freq_${word.word}" title="${word.word}">${word.freq}</a> )
<a class="btn btn-success" onclick="familiar('${word.word}')" role="button">熟悉</a>
<a class="btn btn-warning" onclick="unfamiliar('${word.word}')" role="button">不熟悉</a>
<a class="btn btn-danger" onclick="delete_word('${word.word}')" role="button">删除</a>
</p>`;
}
/**
* 删除某一词频元素
* 此处word为词频元素对应的单词
*/
function removeWord(word) {
// 根据词频信息删除元素
const element_to_remove = document.getElementById(`p_${word}`);
if (element_to_remove != null) {
element_to_remove.remove();
}
}
function renderWord(word) {
const container = document.querySelector(".word-container");
// 删除原有元素
removeWord(word.word);
// 插入新元素
let inserted = false;
const new_element = elementFromString(wordTemplate(word));
for (const current of container.children) {
const cur_word = parseWord(current);
// 找到第一个词频比它小的元素,插入到这个元素前面
if (compareWord(cur_word, word) == -1) {
container.insertBefore(new_element, current);
inserted = true;
break;
}
}
// 当word就是词频最小的词时把他补回去
if (!inserted) {
container.appendChild(new_element);
}
// 让发生变化的元素抖动
new_element.classList.add("shaking");
// 移动到该元素
new_element.scrollIntoView({behavior: "smooth", block: "center", inline: "nearest"});
// 抖动完毕后删除抖动类
setTimeout(() => {
new_element.classList.remove("shaking");
}, 1600);
}
/**
* 从string中创建一个HTML元素并返回
*/
function elementFromString(string) {
const d = document.createElement('div');
d.innerHTML = string;
return d.children.item(0);
}
/**
* 对比两个单词
* 当first小于second时返回-1
* 当first等于second时返回0
* 当first大于second时返回1
*/
function compareWord(first, second) {
if (first.freq < second.freq) {
return -1;
}
if (first.freq > second.freq) {
return 1;
}
if (first.word < second.word) {
return -1;
}
if (first.word > second.word) {
return 1;
}
return 0;
}

View File

@ -19,19 +19,33 @@
{% endif %} {% endif %}
<title>EnglishPal Study Room for {{ username }}</title> <title>EnglishPal Study Room for {{ username }}</title>
<style>
.shaking {
animation: shakes 1600ms ease-in-out;
}
@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); }
}
</style>
</head> </head>
<body> <body>
<div class="container-fluid"> <div class="container-fluid">
<p><b>English Pal for <font id="username" color="red">{{ username }}</font></b> <p><b>English Pal for <font id="username" color="red">{{ username }}</font></b>
<a class="btn btn-secondary" href="/logout" role="button" onclick="stopRead()">退出</a> <a class="btn btn-secondary" href="/logout" role="button">退出</a>
<a class="btn btn-secondary" href="/reset" role="button" onclick="stopRead()">重设密码</a> <a class="btn btn-secondary" href="/reset" role="button">重设密码</a>
</p> </p>
{{ flashed_messages|safe }} {{ flashed_messages|safe }}
<a class="btn btn-success" href="/{{ username }}/reset" role="button" onclick="stopRead()"> 下一篇 Next Article </a> <a class="btn btn-success" href="/{{ username }}/reset" role="button"> 下一篇 Next Article </a>
{% if session.get('articleID') != session.get('old_articleID') %} {% if session.get('articleID') != session.get('old_articleID') %}
{% if session.get('old_articleID') != None %} {% if session.get('old_articleID') != None %}
<a class="btn btn-success" href="/{{ username }}/back" role="button" onclick="stopRead()"> 上一篇 Previous Article </a> <a class="btn btn-success" href="/{{ username }}/back" role="button"> 上一篇 Previous Article </a>
{% endif%} {% endif%}
{% endif %} {% endif %}
@ -52,7 +66,7 @@
<p><b>收集生词吧</b> (可以在正文中划词,也可以复制黏贴)</p> <p><b>收集生词吧</b> (可以在正文中划词,也可以复制黏贴)</p>
<form method="post" action="/{{ username }}"> <form method="post" action="/{{ username }}">
<textarea name="content" id="selected-words" rows="10" cols="120"></textarea><br/> <textarea name="content" id="selected-words" rows="10" cols="120"></textarea><br/>
<input type="submit" onclick="stopRead()" value="把生词加入我的生词库"/> <input type="submit" value="把生词加入我的生词库"/>
<input type="reset" value="清除"/> <input type="reset" value="清除"/>
</form> </form>
{% if session.get['thisWord'] %} {% if session.get['thisWord'] %}
@ -67,22 +81,30 @@
{% endif %} {% endif %}
{% if d_len > 0 %} {% if d_len > 0 %}
<p><b>我的生词簿</b></p> <p>
{% for x in lst3 %} <b>我的生词簿</b>
{% set word = x[0] %} <label for="move_dynamiclly">
{% set freq = x[1] %} <input type="checkbox" name="move_dynamiclly" id="move_dynamiclly" checked>
{% if session.get('thisWord') == x[0] and session.get('time') == 1 %} 允许动态调整顺序
<a name="aaa"></a> </label>
{% endif %} </p>
<p id='p_{{ word }}' class="new-word" > <a name="aaa"></a>
<a id="word_{{ word }}" class="btn btn-light" href='http://youdao.com/w/eng/{{ word }}/#keyfrom=dict2.index' <div class="word-container">
role="button">{{ word }}</a> {% for x in lst3 %}
( <a id="freq_{{ word }}" title="{{ word }}">{{ freq }}</a> ) {% set word = x[0] %}
<a class="btn btn-success" onclick="familiar('{{ word }}')" role="button">熟悉</a> {% set freq = x[1] %}
<a class="btn btn-warning" onclick="unfamiliar('{{ word }}')" role="button">不熟悉</a> {% if session.get('thisWord') == x[0] and session.get('time') == 1 %}
<a class="btn btn-danger" onclick="delete_word('{{ word }}')" role="button">删除</a> {% endif %}
</p> <p id='p_{{ word }}' class="new-word" >
{% endfor %} <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>
</p>
{% endfor %}
</div>
<input id="selected-words2" type="hidden" value="{{ words }}"> <input id="selected-words2" type="hidden" value="{{ words }}">
{% endif %} {% endif %}
</div> </div>