# 2023-9-22開發日誌 ## 歌:toca toca ## 單字檢測: ### 動機 很久之前國二在背3-5級單字的時候就有想要寫一個網站可以抽背的 但是都只有找到1-6級的的excel而且比單字本上的還要多~~我還要多背很懶~~所以作罷 最近同學有找到3-5級的純英文excel(真的不知道哪裡找到的) 如下: ![](https://hackmd.io/_uploads/B1EGXNoJp.png) 聽說國9就做成網頁了 但那時候我在忙會考(才怪)所以我不知道這件事 https://script.google.com/macros/s/AKfycbww_-8ircXqxULe4Cz6L6OKuXpvOQ91J3L8u3QbVGZU1aA11QniLepMDuEs3dqo5N5a/exec ![](https://hackmd.io/_uploads/HkEeSEjk6.png) 其實蠻陽春的 聽說有做成有帳號可以給個人複習用的 但我覺得懶了 那還要去想演算法 --- ### 原始版介紹 雖然說這個東西功能超級陽春但核心的單字調用都在這 我還是介紹一下: 1. 選取單字範圍 用了兩個下拉式選單 這叫我寫我也要想一下: ```javascript= function populateEndLetters() { var startLetter = document.getElementById("startLetter").value; var endLetterSelect = document.getElementById("endLetter"); endLetterSelect.innerHTML = "<option value='' disabled selected></option>"; var alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; var startIndex = alphabet.indexOf(startLetter); for (var i = startIndex; i < alphabet.length; i++) { var letter = alphabet.charAt(i); var option = document.createElement("option"); option.value = letter; option.innerText = letter; endLetterSelect.appendChild(option); } } ``` 2. 還有隨機抽取單字的寫法 主要概念就是取範圍重新排序在取前n個 邊看邊佩服邊感嘆自己怎麼那麼弱 ```javascript= function pickAndOutputWords(startLetter, endLetter, numToPick) { var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); var words = sheet.getRange('A2:A').getValues().flat().filter(word => { var firstLetter = word.trim().charAt(0).toUpperCase(); return firstLetter >= startLetter && firstLetter <= endLetter; }); var pickedWords = []; if (words.length < numToPick) { numToPick = words.length; } while (pickedWords.length < numToPick) { var randomIndex = Math.floor(Math.random() * words.length); var word = words[randomIndex]; if (!pickedWords.includes(word)) { pickedWords.push(word); } } return pickedWords; } ``` --- ### 範圍內全選 這挺無腦的就改本來的 目的是要背新的範圍的時候可以不用拿本子 ```javascript= function pickall(startLetter, endLetter) { var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet()[0]; var words = sheet.getRange('A2:A').getValues().flat().filter(word => { var firstLetter = word.trim().charAt(0).toUpperCase(); return firstLetter >= startLetter && firstLetter <= endLetter; }); // var pickedWords = []; // if (words.length < numToPick) { // numToPick = words.length; // } // while (pickedWords.length < numToPick) { // var randomIndex = Math.floor(Math.random() * words.length); // var word = words[randomIndex]; // if (!pickedWords.includes(word)) { // pickedWords.push(word); // } // } //console.log((words)); return words; } ``` 就單純把篩選去掉 ### GAS API化 把網頁架在GAS(google app script)上面問題在於這樣所有的運算都要在GAS上面跑真的太慢了 所以我打算把靜態html放在github上 **Github真的太好用了** 遵從`chatgpt`的建議決定讓網頁發出`fetch`給GAS網址 > (其實細節例如為什麼適用fetch不用之前用過的ajax我也不清楚畢竟我根本不熟) 主要就是改了doGet讓他不是回傳html tamplate ```javascript= function doGet(e) { var action = e.parameter.action; // 从请求参数中获取操作名称 // var action = "pickAndOutputWords" if (action == "pickAndOutputWords") { var startLetter = e.parameter.startLetter; var endLetter = e.parameter.endLetter; var numToPick = e.parameter.numToPick; var resultArray = pickAndOutputWords(startLetter,endLetter,numToPick); // 执行功能1 var response = { result: resultArray }; // console.log(ContentService // .createTextOutput(JSON.stringify(response)) // .setMimeType(ContentService.MimeType.JSON)); return ContentService .createTextOutput(JSON.stringify(response)) .setMimeType(ContentService.MimeType.JSON); } else if (action == "pickall") { var startLetter = e.parameter.startLetter; var endLetter = e.parameter.endLetter; var resultArray = pickall(startLetter,endLetter); // 执行功能1 var response = { result: resultArray }; return ContentService .createTextOutput(JSON.stringify(response)) .setMimeType(ContentService.MimeType.JSON); } } ``` 改成用json的方法 細節不太瞭解還要學其實 都抄chatGPT 接下來就是github上面的html ### html ```javascript= function pickWords() { var startLetter = document.getElementById("startLetter").value.trim().toUpperCase(); var endLetter = document.getElementById("endLetter").value.trim().toUpperCase(); var numToPick = parseInt(document.getElementById("numToPick").value); var outputDiv = document.getElementById("outputDiv"); //console.log(numToPick); if (startLetter !== '' && endLetter !== '' && numToPick ) { outputDiv.innerHTML = "<h2>請等等...</h2><ul>"; pickAndOutputWords(startLetter, endLetter, numToPick) .then(words => { displayWords(words); }) .catch(error => { console.error('Error:', error); }); } else { outputDiv.innerHTML = "<h2>你好像漏了些甚麼沒有填喔</h2><ul>"; } } function pickAllWords() { var startLetter = document.getElementById("startLetter").value.trim().toUpperCase(); var endLetter = document.getElementById("endLetter").value.trim().toUpperCase(); var outputDiv = document.getElementById("outputDiv"); if (startLetter !== '' && endLetter !== '') { outputDiv.innerHTML = "<h2>請等等...</h2><ul>"; pickall(startLetter, endLetter) .then(words => { displayWords(words); }) .catch(error => { console.error('Error:', error); }); } else { outputDiv.innerHTML = "<h2>你好像漏了些甚麼沒有填喔</h2><ul>"; } } var api_url = 'https://script.google.com/macros/s/AKfycbxN6TKYrCfvVvxDVhM3V61TH62vj0BAUW9l05XYzWCyjYNeYDIea2MBLQhetqpePAK9/exec'; function pickAndOutputWords(startLetter, endLetter, numToPick) { return fetch(api_url + '?action=pickAndOutputWords&startLetter=' + startLetter + '&endLetter=' + endLetter + '&numToPick=' + numToPick) .then(response => response.json()) .then(data => { var resultArray = data.result; //console.log(resultArray); return resultArray; }) .catch(error => { console.error('Error:', error); }); } function pickall(startLetter, endLetter) { return fetch(api_url + '?action=pickall&startLetter=' + startLetter + '&endLetter=' + endLetter) .then(response => response.json()) .then(data => { var resultArray = data.result; //console.log(resultArray); return resultArray; }) .catch(error => { console.error('Error:', error); }); } ``` 就發一個request 本來就可以這樣再加上一個顯示功能就好 但我就覺得沒有中文就很奇怪 所以我就發願給他配上中文 之前就有找到1-6級的單字表格如下: [7000單字表](https://view.officeapps.live.com/op/view.aspx?src=http%3A%2F%2Fwww.kmsh.tn.edu.tw%2F~edu92%2Fkmedu100%2Fsenior_7000.xls&wdOrigin=BROWSELINK) 這網址剛剛突然找不太到 ### 整理7000單字表 ![單字表](https://hackmd.io/_uploads/Hyyrzbhkp.png) 簡單看過他給的表格之後發現了幾個問題 * 沒有分欄 * 好險他有分隔符號 "@" (我猜覺得是當csv加入html的時候他們沒有設定好) * 用excel直接解決 * 不同等級分開了 * 雖然不是什麼大問題,但是這樣我如果要加入我本來的試算表的話就會很雜 而且也不方便對照 搜索 * 先加上一欄是等級的 就用拉的還有右鍵的快速填入 * 大體上是這樣處理的: * [教學影片](https://www.youtube.com/watch?v=HTc0Tnpft2M) * 只有一個小問題就是快捷鍵沒有辦法在網頁版上使用會變成瀏覽器的開啟分業快捷鍵 * 解決方法是對儲存格按下右鍵 ![](https://hackmd.io/_uploads/HkLZHbhkT.png) * 不同意思分在不同欄 * 這跟前一個問題是同時發生 * 看了很久的excel教學還是覺得用gas解就好 ```javascript= function mergeRows() { var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("voc2"); var data = sheet.getDataRange().getValues(); var newData = []; for (var i = 0; i < data.length; i++) { var currentRow = data[i]; var englishWord = currentRow[0]; var chineseDefinition = currentRow[1]; var level = data[i][2].toString(); // 初始化为一个空字符串 // 查找相同英文单词的行并合并 for (var j = i + 1; j < data.length; j++) { if (data[j][0] === englishWord) { chineseDefinition += ', ' + data[j][1]; // 检查是否已包含相同的 level,如果没有才添加 var currentLevel = data[j][2].toString(); // 将数字转换为字符串 if (level.indexOf(currentLevel) === -1) { level += ', ' + currentLevel; } i = j; // 设置 i 到下一个相同单词的行 } } newData.push([englishWord, chineseDefinition, level]); } // 清空原始数据 sheet.getDataRange().clear(); // 将合并后的数据写回工作表 sheet.getRange(1, 1, newData.length, newData[0].length).setValues(newData); } ``` 主要是chatGPT寫的 但自己改了一點 主要是因為level的第地方改了一下才成功 ##### 結果演示: ![](https://hackmd.io/_uploads/H1VYP-3y6.png) 接下來就是用迴圈跑: ```javascript= function def_check(word) { /*word = [ ["abandon"], ["abdomen"], ["abide"], ["abolish"], ["abortion"], ["abrupt"], ["absolute"], ["absorb"], ["abstract"], ["absurd"], ["abundant"], ["academy"], ["accent"], ["access"], ["accompany"], ["accomplish"], ["aboard"] ];*/ var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('voc2'); var data = sheet.getDataRange().getValues(); var new_word = []; for (var j = 0; j <word.length; j++) { for (var i = 0; i < data.length; i++) { var englishWord = data[i][0]; var chineseMeaning = data[i][1]; if (englishWord === word[j][0]) { new_word.push([englishWord, chineseMeaning]); } } } //Logger.log(new_word) return new_word; } ``` 理論上自己也寫得出來 但就是習慣去讓chatGPT寫 真的越來越退化了 在來就是html上的顯示了 我希望能夠用按鈕的方式讓答案用點的才出現 所以把 ```javascript= function displayWords(words) { var outputDiv = document.getElementById("outputDiv"); outputDiv.innerHTML = "<h2>抽到的單字:</h2><ul>"; words.forEach(function(word) { outputDiv.innerHTML += "<li>" + word + "</li>"; }); outputDiv.innerHTML += "</ul>"; } ``` 先改成了`<table>`又改成了 ```javascript= function displayWords(words) { var outputDiv = document.getElementById("outputDiv"); //console.log(words); var content = "<h2>抽到的單字:</h2><table>"; for (var i = 0; i < words.length; i++) { content += "<tr><td>" + words[i][0] + "</td><td><input type=\"button\" onclick=\"showChinese(this,\'"+ words[i][1] + "\' ) \" value=\"顯示中文\"></td></tr>"; } content += "</table>"; outputDiv.innerHTML = content; } ``` 這樣的按鈕就變成 ```htmlmixed= <tr> <td>英文</td> <td> <input type="button" onclick="showChinese(this,中文)"> </td> </tr> ``` 因為有this(原來js也可以this)所以function很好寫 ```javascript= function showChinese(button,ch) { if(button.value=="顯示中文") { button.value =ch; } else { button.value ="顯示中文"; } } document.addEventListener("DOMContentLoaded", function () { // 在这里放置你的 JavaScript 代码 // 例如,添加事件监听器等 document.getElementById("startLetter").addEventListener("change", populateEndLetters); document.getElementById("startLetter").dispatchEvent(new Event("change")); }); ``` 然後再來就是問chatGPT等等的去條響應式網站(以手機為主)和CSS ![](https://hackmd.io/_uploads/BkOqSMnkT.png) (其實沒有很好看但還行啦) ## 成果 * 網站: https://watermelon-1234.github.io/memorize_voc/ * GAS端: * 檔案 * **單字涉及著作權 不公開** * code.gs ```javascript= function doGet(e) { var action = e.parameter.action; // 从请求参数中获取操作名称 // var action = "pickAndOutputWords" if (action == "pickAndOutputWords") { var startLetter = e.parameter.startLetter; var endLetter = e.parameter.endLetter; var numToPick = e.parameter.numToPick; var resultArray = pickAndOutputWords(startLetter,endLetter,numToPick); // 执行功能1 var response = { result: resultArray }; // console.log(ContentService // .createTextOutput(JSON.stringify(response)) // .setMimeType(ContentService.MimeType.JSON)); return ContentService .createTextOutput(JSON.stringify(response)) .setMimeType(ContentService.MimeType.JSON); } else if (action == "pickall") { var startLetter = e.parameter.startLetter; var endLetter = e.parameter.endLetter; var resultArray = pickall(startLetter,endLetter); // 执行功能1 var response = { result: resultArray }; return ContentService .createTextOutput(JSON.stringify(response)) .setMimeType(ContentService.MimeType.JSON); } } function translation(word) { } function pickAndOutputWords(startLetter, endLetter, numToPick) {//大寫 var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet()[0]; var words = sheet.getRange('A2:A').getValues().flat().filter(word => { var firstLetter = word.trim().charAt(0).toUpperCase(); return firstLetter >= startLetter && firstLetter <= endLetter; }); var pickedWords = []; if (words.length < numToPick) { numToPick = words.length; } while (pickedWords.length < numToPick) { var randomIndex = Math.floor(Math.random() * words.length); var word = words[randomIndex]; if (!pickedWords.includes(word)) { pickedWords.push(word); } } return def_check(pickedWords); } function pickall(startLetter, endLetter) { var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet()[0]; var words = sheet.getRange('A2:A').getValues().flat().filter(word => { var firstLetter = word.trim().charAt(0).toUpperCase(); return firstLetter >= startLetter && firstLetter <= endLetter; }); // var pickedWords = []; // if (words.length < numToPick) { // numToPick = words.length; // } // while (pickedWords.length < numToPick) { // var randomIndex = Math.floor(Math.random() * words.length); // var word = words[randomIndex]; // if (!pickedWords.includes(word)) { // pickedWords.push(word); // } // } //console.log((words)); return def_check(words); } function include(filename) { return HtmlService.createHtmlOutputFrom File(filename).getContent(); } function mergeRows() { var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("voc2"); var data = sheet.getDataRange().getValues(); var newData = []; for (var i = 0; i < data.length; i++) { var currentRow = data[i]; var englishWord = currentRow[0]; var chineseDefinition = currentRow[1]; var level = data[i][2].toString(); // 初始化为一个空字符串 // 查找相同英文单词的行并合并 for (var j = i + 1; j < data.length; j++) { if (data[j][0] === englishWord) { chineseDefinition += ', ' + data[j][1]; // 检查是否已包含相同的 level,如果没有才添加 var currentLevel = data[j][2].toString(); // 将数字转换为字符串 if (level.indexOf(currentLevel) === -1) { level += ', ' + currentLevel; } i = j; // 设置 i 到下一个相同单词的行 } } newData.push([englishWord, chineseDefinition, level]); } // 清空原始数据 sheet.getDataRange().clear(); // 将合并后的数据写回工作表 sheet.getRange(1, 1, newData.length, newData[0].length).setValues(newData); } function def_check(word) { /*word = [ ["abandon"], ["abdomen"], ["abide"], ["abolish"], ["abortion"], ["abrupt"], ["absolute"], ["absorb"], ["abstract"], ["absurd"], ["abundant"], ["academy"], ["accent"], ["access"], ["accompany"], ["accomplish"], ["aboard"] ];*/ var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('voc2'); var data = sheet.getDataRange().getValues(); var new_word = []; for (var j = 0; j <word.length; j++) { for (var i = 0; i < data.length; i++) { var englishWord = data[i][0]; var chineseMeaning = data[i][1]; if (englishWord === word[j][0]) { new_word.push([englishWord, chineseMeaning]); } } } //Logger.log(new_word) return new_word; } ``` * html ```htmlembedded= <!DOCTYPE html> <html> <head> <base target="_top"> <link href="style.css" rel="stylesheet"> <script src="scripts.js"></script> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="icon" href="favicon.ico" type="image/x-icon"> </head> <body> <div class="banner"> <h1>單字檢測系統</h1> </div> <div class="container"> <div class="empty-div"></div> <form> <label for="startLetter">單字檢測:從</label> <select id="startLetter" name="startLetter" required> <option value="" disabled selected></option> <option value="A">A</option> <option value="B">B</option> <option value="C">C</option> <option value="D">D</option> <option value="E">E</option> <option value="F">F</option> <option value="G">G</option> <option value="H">H</option> <option value="I">I</option> <option value="J">J</option> <option value="K">K</option> <option value="L">L</option> <option value="M">M</option> <option value="N">N</option> <option value="O">O</option> <option value="P">P</option> <option value="Q">Q</option> <option value="R">R</option> <option value="S">S</option> <option value="T">T</option> <option value="U">U</option> <option value="V">V</option> <option value="W">W</option> <option value="X">X</option> <option value="Y">Y</option> <option value="Z">Z</option> </select> <label for="endLetter">到</label> <select id="endLetter" name="endLetter" required> </select><br> <label for="numToPick">單字數:</label> <input type="number" id="numToPick" name="numToPick" required><br> <input type="button" value="確定" onclick="pickWords()"> <input type="button" value="區段中全部[排序]" onclick="pickAllWords()"> </form> <div class="empty-div"> </div> </div> <div class="container" style="justify-content: flex-start;"> <div class="empty-div"> </div> <div id="outputDiv"></div> <div class="empty-div"> </div> </div> <div class="footer"> <p>&copy; 2023 單字檢測系統</p> </div> </body> </html> ``` * javascript ```javascript= function populateEndLetters() {//作為下拉式選單的內容 var startLetter = document.getElementById("startLetter").value; var endLetterSelect = document.getElementById("endLetter"); endLetterSelect.innerHTML = "<option value='' disabled selected></option>"; var alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; var startIndex = alphabet.indexOf(startLetter); for (var i = startIndex; i < alphabet.length; i++) { var letter = alphabet.charAt(i); var option = document.createElement("option"); option.value = letter; option.innerText = letter; endLetterSelect.appendChild(option); } } function pickWords() { var startLetter = document.getElementById("startLetter").value.trim().toUpperCase(); var endLetter = document.getElementById("endLetter").value.trim().toUpperCase(); var numToPick = parseInt(document.getElementById("numToPick").value); var outputDiv = document.getElementById("outputDiv"); //console.log(numToPick); if (startLetter !== '' && endLetter !== '' && numToPick ) { outputDiv.innerHTML = "<h2>請等等...</h2><ul>"; pickAndOutputWords(startLetter, endLetter, numToPick) .then(words => { displayWords(words); }) .catch(error => { console.error('Error:', error); }); } else { outputDiv.innerHTML = "<h2>你好像漏了些甚麼沒有填喔</h2><ul>"; } } function pickAllWords() { var startLetter = document.getElementById("startLetter").value.trim().toUpperCase(); var endLetter = document.getElementById("endLetter").value.trim().toUpperCase(); var outputDiv = document.getElementById("outputDiv"); if (startLetter !== '' && endLetter !== '') { outputDiv.innerHTML = "<h2>請等等...</h2><ul>"; pickall(startLetter, endLetter) .then(words => { displayWords(words); }) .catch(error => { console.error('Error:', error); }); } else { outputDiv.innerHTML = "<h2>你好像漏了些甚麼沒有填喔</h2><ul>"; } } var api_url = 'https://script.google.com/macros/s/AKfycbxN6TKYrCfvVvxDVhM3V61TH62vj0BAUW9l05XYzWCyjYNeYDIea2MBLQhetqpePAK9/exec'; function pickAndOutputWords(startLetter, endLetter, numToPick) { return fetch(api_url + '?action=pickAndOutputWords&startLetter=' + startLetter + '&endLetter=' + endLetter + '&numToPick=' + numToPick) .then(response => response.json()) .then(data => { var resultArray = data.result; //console.log(resultArray); return resultArray; }) .catch(error => { console.error('Error:', error); }); } function pickall(startLetter, endLetter) { return fetch(api_url + '?action=pickall&startLetter=' + startLetter + '&endLetter=' + endLetter) .then(response => response.json()) .then(data => { var resultArray = data.result; //console.log(resultArray); return resultArray; }) .catch(error => { console.error('Error:', error); }); } function displayWords(words) { var outputDiv = document.getElementById("outputDiv"); //console.log(words); var content = "<h2>抽到的單字:</h2><table>"; for (var i = 0; i < words.length; i++) { content += "<tr><td>" + words[i][0] + "</td><td><input type=\"button\" onclick=\"showChinese(this,\'"+ words[i][1] + "\' ) \" value=\"顯示中文\"></td></tr>"; } content += "</table>"; outputDiv.innerHTML = content; } function showChinese(button,ch) { if(button.value=="顯示中文") { button.value =ch; } else { button.value ="顯示中文"; } } document.addEventListener("DOMContentLoaded", function () { // 在这里放置你的 JavaScript 代码 // 例如,添加事件监听器等 document.getElementById("startLetter").addEventListener("change", populateEndLetters); document.getElementById("startLetter").dispatchEvent(new Event("change")); }); ``` * Css ```css= /* 基本樣式 */ body { background-color: #000; /* 黑色背景 */ color: #00FF00; /* 深綠色文字 */ font-family: Arial, sans-serif; /* 使用Arial字體,sans-serif作為備用字體 */ margin: 0; padding: 0; justify-content: center; align-items: center; min-height: 100vh; } /* 響應式設計 */ @media screen and (min-width: 768px) { body { font-size: 50px; /* 使用相對大小,而不是固定像素大小 */ } h1 { font-size: 50px; /* 調整標題字體大小 */ } select, input[type="number"], input[type="button"] { padding: 15px; height: 50px; font-size: 35px; /* 设置字体大小 */ margin: 10px; /* 设置外边距 */ font-weight: bold; /* 设置文本粗细 */ text-align: center; } } /* 其他樣式 */ h1 { color: #00FF00; /* 標題文字為深綠色 */ text-align: center; /* 文字置中 */ font-weight: bold; } /* 新增橫幅的樣式 */ .banner { background-color: #333; /* 橫幅背景色 */ color: #fff; /* 橫幅文字顏色 */ padding: 10px; /* 橫幅內邊距 */ text-align: center; /* 文字居中 */ } /* 新增頁尾的樣式 */ .footer { background-color: #333; /* 頁尾背景色 */ color: #fff; /* 頁尾文字顏色 */ padding: 10px; /* 頁尾內邊距 */ text-align: center; /* 文字居中 */ font-size: 10; } form { margin: 20px; /* 距離外容器的邊距 */ } label { color: #00FF00; /* 標籤文字為深綠色 */ font-weight: bold; } select, input[type="number"], input[type="button"] { background-color: #000; /* 背景色為黑色 */ color: #00FF00; /* 文字顏色為深綠色 */ border: 2px solid #00FF00; /* 邊框為深綠色實線 */ border-radius: 5px; /* 圓角邊框 */ padding: 5px; /* 內邊距 */ margin: 5px; /* 外邊距 */ text-align: center; padding-top: 0; padding-bottom: 0; width:fit-content; } select:focus, input[type="number"]:focus { border-color: #00FFFF; /* 聚焦時邊框顏色為淺綠色 */ } #outputDiv { background-color: #000; /* 輸出區域背景為黑色 */ color: #00FF00; /* 輸出文字顏色為深綠色 */ margin: 20px; /* 外邊距 */ padding: 10px; /* 內邊距 */ width: 60%; } ul { list-style-type: none; /* 隱藏列表樣式 */ padding: 0; } li { margin: 5px 0; /* 調整列表項目的外邊距 */ } .container { display: flex; flex-direction: row; align-items: flex-start; justify-content: space-between; } .form-output { display: row; flex-direction: column; align-items: flex-start; justify-content: center; } .empty-div { background-color: #a6a6a6; /* 輸出區域背景為黑色 */ width:20% ; height: 100%; } ``` github: https://github.com/Watermelon-1234/memorize_voc ##心得