使用 Google Apps Script 打造學生作品書櫃及按讚網頁程式
資料更新 20241220
資料更新 20241220
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>TileBlind Slideshow</title> <!-- 引入 jQuery --> <script src="https ://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <!-- 引入jQuery Cycle 2 外掛程式--> <script src="https:/ /malsup.github.io/min/jquery.cycle2.min.js"></script> <!-- 引入Cycle2tileSlide 外掛程式--> <script src="https://malsup.github.io/min/ jquery .cycle2.tile.min.js"></script> <style> /* 在這裡加入自訂的CSS 樣式*/ /* 以下是一個範例*/ body { font-family: Arial, sans-serif;保證金:20;填充:10;背景顏色:#f8f8f8;顏色:#333; } .container { 最大寬度:800px;保證金:0 自動;內邊距:10px;背景顏色:#fffeee;盒子陰影: 0 0 10px rgba(0, 0, 0, 0.3);邊框半徑:5px;位置:相對; /* 增加相對定位,以便包裝器元素的絕對定位生效 */ } .slideshow-wrapper { text-align: center; /* 居中按鈕 */ margin-top: 20px; /* 上邊距 */ } h1 { text-align: center;下邊距:20px;顏色:#333; } hr { 邊框:0;頂部邊框:1px 實線#ccc;下邊距:20px; } .cycle-slideshow { 位置:相對;上邊距:20px; } .cycle-slideshow img { 顯示:區塊;寬度:800px; /* 設定圖片寬度為1024px */ height: 480px; /* 設定圖片高度為 768px */ border-radius: 5px;盒子陰影: 0 0 5px rgba(0, 0, 0, 0.1); } .btn-prev, .btn-next { 背景顏色: #007bff;顏色:#fff;邊框:無;內邊距:10px 20px;邊距:0 10px;邊框半徑:5px;遊標:指針; } .btn-prev: 懸停, .btn-next: 懸停 { 背景顏色:#0056b3; } </style> </head> <body> <音訊自動播放循環> <source src="https://drive.google.com/uc?export=download&id=1S-dy_ZsRwT5sZwarVAVZEPU5Ce2AAwji" type="audio/mpeg" >您的瀏覽器不支援音訊元素。 "循環投影片" data-cycle-fx="tileSlide" data-cycle-tile-count="10"> <? for (var i = 0; i < imageUrls.length; i++) { ?> <img src="https://drive.google.com/thumbnail?id=<?= imageUrls[i] ?>&sz=w960" alt="Image <?= i + 1 ?>"> <? } ?> </div> <!-- 投影片控制按鈕--> <div class="slideshow-wrapper"> <button class="btn-prev">上一張</button> <button class="btn-next">下一張</button> </div > </div> <script> // 等待文件載入完成$(document).ready(function() { // 取得投影片容器varlideshow = $('.cycle-slideshow'); // 上一張按鈕點擊事件$('.btn-prev').click(function() { Slideshow.cycle('prev'); }); // 下一張按鈕點選事件$('.btn-next').click( function () { Slideshow.cycle('next') }); </script> </body> </html> 和<!DOCTYPE html> <html> <head> <title id="htmlTitle" > 學生作品清單< /title> <style> body { font-family: 'Arial', sans-serif; margin: 0; 背景顏色: #333; :列;最小高度:100vh;}標題{背景:#4a90e2;填充:20px;字體大小:24px; : 重複(自動調整, minmax(200px, 1fr)); 間隙: 20px; 最大寬度: 1200px; } .button-container { 顯示: flex;彈性方向:列;對齊項目:居中;邊框:1px實線#ddd;邊框半徑:10px;背景:白色;溢出:隱藏;盒子陰影:0 2px 5px rgba(0, 0, 0, 0.1);最大寬度:200px;寬度:100%; } .button { 寬度:100%;高度:350像素;顯示:柔性;調整內容:居中;對齊項目:居中;位置:相對;溢出:隱藏;背景顏色:#000;遊標:指針; } .button img { 最大寬度:100%;最大高度:100%;物件適合:包含;顯示:塊; } .button span { 位置:絕對;頂部:50%;左:50%;變換:翻譯(-50%,-50%);顏色: 白色;字體粗細:粗體;字體大小:16px;文字對齊:居中;背景顏色: rgba(0, 0, 0, 0.5);內邊距:5px 10px;邊框半徑:5px; } .like-container { 顯示:flex;調整內容:居中;對齊項目:居中;間隙:10px;邊距:10px 0; } .like-button { 背景:#4caf50;顏色: 白色;邊框:無;內邊距:10 像素 15 像素;邊框半徑:5px;游標:指針; } 頁尾 { 文字對齊:居中;內邊距:10px;上邊距:自動;背景:#f4f4f4;顏色:#333; } 頁尾 a { 顏色:#4a90e2;文字裝飾:無; } 頁尾 a:hover { 文字裝飾: 底線; } #adminLayer { 顯示:無;位置:固定;頂部:0;左:0;寬度:100%;高度:100%;背景:rgba(0,0,0,0.8);顏色: 白色;內邊距:20px; z 索引:1000; } #adminLayer h1 { 頂邊距:0; } #adminLayer 表單 { 顯示:flex;彈性方向:列;間隙:10px; } #adminLayer 輸入,#adminLayer 鈕 { padding: 10px;邊框半徑:5px;邊框:無;上邊距:5px; } #adminLayer 按鈕{ 背景:#4caf50;顏色: 白色;遊標:指針; } </style> </head> <body> <header id="pageHeader">學生工作清單</header> <div id="buttons"></div> <footer>由<a href="https製作://kentxchang.blogspot.tw" target="_blank">阿剛老師</a> </footer> <div id="adminLayer"> <h1>後台管理</h1> <form onsubmit="addButton( event)"> <input id="adminName" type="text" placeholder="按鈕名稱" 必填/> <input id="adminLink" type="url" placeholder="按鈕連結" 必填/> <button type= "submit">新增按鈕</button> </form> <form onsubmit="updateTitle(event)"> <input id="adminTitle" type="text" placeholder="新標題名稱" required /> <button type="submit">修改標題</button> </form> <button onclick="resetLikes()">重置按讚數</button> <button onclick="closeAdmin()">關閉後台< /button > </div> <script> 讓按鈕= [];讓 bgPressed = false; const userId = sessionStorage.getItem("userId") || (() => { const newUserId = `user-${Date.now()}`; sessionStorage.setItem("userId", newUserId); return newUserId; })();函式 loadButtons() { google.script.run.withSuccessHandler(renderButtons).getButtons(); google.script.run.withSuccessHandler(updateHeader).getPageTitle(); } 函數 renderButtons(data) { 按鈕 = 資料; const 容器 = document.getElementById("buttons");容器.innerHTML = ""; Buttons.forEach((button) => { const div = document.createElement("div"); div.className = "按鈕容器"; div.innerHTML = ` <div class="button" onclick="openLink('${button.link}')"> <img src="https://cdn.pixabay.com/photo/2014/04/02 /16/21/book-307045_1280.png" alt="${button.name}" /> <span>${button.name}</span> </div> <div class="like-container"> <button class="like-button" onclick="likeButton(${button.id})">👍按讚</button> <span id="like-count-${button.id}">${button .like}次讚</span> </div> `;容器.appendChild(div); }); } 函式 addButton(event) { event.preventDefault(); const name = document.getElementById("adminName").value.trim(); const link = document.getElementById("adminLink").value.trim(); if (!name || !link) {alert("請輸入按鈕名稱和連結!");返回; } google.script.run .withSuccessHandler(() => {alert("按鈕新增成功!"); loadButtons(); }) .withFailureHandler((error) => { console.error("新增按鈕失敗: ", error);alert("新增按鈕失敗,請稍後再試!"); }) .addButton(name, link); } function likeButton(id) { google.script.run .withSuccessHandler((response) => { if (response.success) { const likeCountSpan = document.getElementById(`like-count-${id}`); if (likeCountSpan ) { const currentLikes = parseInt(likeCountSpan.textContent) || 0; likeCountSpan.textContent = `${currentLikes + 1}次讚`; } } else {alert(response.message) } }) .withFailureHandler((error) = > { console.error("按讚失敗:", error);alert("按讚失敗,請稍後再試!") .likeButton(id, userId); } 函數 openLink(link) { window.open(link, '_blank'); } 函式 updateTitle(event) { event.preventDefault(); const title = document.getElementById("adminTitle").value.trim(); if (!title) {alert("請輸入標題!");返回; } google.script.run .withSuccessHandler(() => {alert("標題更新成功!"); updateHeader(title); }) .withFailureHandler((error) => { console.error("標題更新失敗:" , error);alert("標題更新失敗,請稍後再試!") .setPageTitle(title); } 函數 updateHeader(title) { document.getElementById("pageHeader").textContent = title;文件.標題=標題; // 更新 HTML 標題 } function resetLikes() { google.script.run .withSuccessHandler(() => {alert("讚數已重置!"); loadButtons(); }) .withFailureHandler((error) => { console.error("重置贊數失敗:", error); } function openAdmin() { document.getElementById("adminLayer").style.display = "block"; } 函數 closeAdmin() { document.getElementById("adminLayer").style.display = "none"; } document.addEventListener("keydown", (e) => { if (e.key.toLowerCase() === "b") { bgPressed = true; } if (e.key.toLowerCase() === " g" && bgPressed) { openAdmin(); } }); document.addEventListener("keyup", (e) => { if (e.key.toLowerCase() === "b") { bgPressed = false; } });載入按鈕(); </script> </body> </html> 試著將兩個專案合併起來,設計一個能自動抓取資料夾ID的圖片放置在網站上,可以點選讚後同時記錄在試算表中,試算表中自動抓取資料夾內的ID計算出按了多少個贊,最後將進入後台的方法改為一個按鈕,但需要密碼才能進入後台,密碼為123。
好的,我們可以將這兩個專案合併,並實現以下功能:
1. 自動抓取資料夾ID的圖片並顯示在網站上。
2. 點選讚後記錄在試算表中。
3. 試算表自動抓取資料夾內的ID並計算按讚數。
4. 進入後台的方法改為按鈕,並需要密碼才能進入。
以下是合併後的完整 HTML 和 JavaScript 程式碼:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>學生作品清單與瀑布流相簿</title>
<!-- 引入 jQuery -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<!-- 引入 jQuery Cycle 2 插件 -->
<script src="https://malsup.github.io/min/jquery.cycle2.min.js"></script>
<!-- 引入 Cycle2 tileSlide 插件 -->
<script src="https://malsup.github.io/min/jquery.cycle2.tile.min.js"></script>
<style>
/* 在这里添加自定义的 CSS 样式 */
/* 以下是一个示例 */
body {
font-family: Arial, sans-serif;
margin: 20;
padding: 10;
background-color: #f8f8f8;
color: #333;
display: flex;
flex-direction: column;
min-height: 100vh;
}
.container {
max-width: 800px;
margin: 0 auto;
padding: 10px;
background-color: #fffeee;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
border-radius: 5px;
position: relative; /* 添加相对定位,以便包装器元素的绝对定位生效 */
}
.slideshow-wrapper {
text-align: center; /* 居中按钮 */
margin-top: 20px; /* 上边距 */
}
h1 {
text-align: center;
margin-bottom: 20px;
color: #333;
}
hr {
border: 0;
border-top: 1px solid #ccc;
margin-bottom: 20px;
}
.cycle-slideshow {
position: relative;
margin-top: 20px;
}
.cycle-slideshow img {
display: block;
width: 800px; /* 设置图片宽度为 1024px */
height: 480px; /* 设置图片高度为 768px */
border-radius: 5px;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
}
.btn-prev,
.btn-next {
background-color: #007bff;
color: #fff;
border: none;
padding: 10px 20px;
margin: 0 10px;
border-radius: 5px;
cursor: pointer;
}
.btn-prev:hover,
.btn-next:hover {
background-color: #0056b3;
}
header {
background: #4a90e2;
color: white;
padding: 20px;
text-align: center;
font-size: 24px;
}
#buttons {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 15px;
padding: 20px;
max-width: 1200px;
margin: auto;
}
.button-container {
display: flex;
flex-direction: column;
align-items: center;
border: 1px solid #ddd;
border-radius: 10px;
background: white;
overflow: hidden;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
max-width: 200px;
width: 100%;
}
.button {
width: 100%;
height: 350px;
display: flex;
justify-content: center;
align-items: center;
position: relative;
overflow: hidden;
background-color: #000;
cursor: pointer;
}
.button img {
max-width: 100%;
max-height: 100%;
object-fit: contain;
display: block;
}
.button span {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: white;
font-weight: bold;
font-size: 16px;
text-align: center;
background-color: rgba(0, 0, 0, 0.5);
padding: 5px 10px;
border-radius: 5px;
}
.like-container {
display: flex;
justify-content: center;
align-items: center;
gap: 10px;
margin: 10px 0;
}
.like-button {
background: #4caf50;
color: white;
border: none;
padding: 10px 15px;
border-radius: 5px;
cursor: pointer;
}
footer {
text-align: center;
padding: 10px;
margin-top: auto;
background: #f4f4f4;
color: #333;
}
footer a {
color: #4a90e2;
text-decoration: none;
}
footer a:hover {
text-decoration: underline;
}
#adminLayer {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.8);
color: white;
padding: 20px;
z-index: 1000;
}
#adminLayer h1 {
margin-top: 0;
}
#adminLayer form {
display: flex;
flex-direction: column;
gap: 10px;
}
#adminLayer input,
#adminLayer button {
padding: 10px;
border-radius: 5px;
border: none;
margin-top: 5px;
}
#adminLayer button {
background: #4caf50;
color: white;
cursor: pointer;
}
</style>
</head>
<body>
<header id="pageHeader">學生作品清單與瀑布流相簿</header>
<div id="buttons"></div>
<div class="container">
<h1>瀑布流相簿</h1>
<hr>
<!-- 幻燈片容器 -->
<div class="cycle-slideshow"
data-cycle-fx="tileSlide"
data-cycle-tile-count="10">
<!-- 這裡的圖片將由 JavaScript 動態生成 -->
</div>
<!-- 幻燈片控制按鈕 -->
<div class="slideshow-wrapper">
<button class="btn-prev">上一張</button>
<button class="btn-next">下一張</button>
</div>
</div>
<footer>
made by <a href="https://kentxchang.blogspot.tw" target="_blank">阿剛老師</a>
</footer>
<div id="adminLayer">
<h1>後台管理</h1>
<form onsubmit="addButton(event)">
<input id="adminName" type="text" placeholder="按鈕名稱" required />
<input id="adminLink" type="url" placeholder="按鈕連結" required />
<button type="submit">新增按鈕</button>
</form>
<form onsubmit="updateTitle(event)">
<input id="adminTitle" type="text" placeholder="新標題名稱" required />
<button type="submit">修改標題</button>
</form>
<button onclick="resetLikes()">重置按讚數</button>
<button onclick="closeAdmin()">關閉後台</button>
</div>
<button onclick="openAdminPrompt()">進入後台</button>
<script>
let buttons = [];
let bgPressed = false;
const userId = sessionStorage.getItem("userId") || (() => {
const newUserId = `user-${Date.now()}`;
sessionStorage.setItem("userId", newUserId);
return newUserId;
})();
function loadButtons() {
google.script.run.withSuccessHandler(renderButtons).getButtons();
google.script.run.withSuccessHandler(updateHeader).getPageTitle();
}
function renderButtons(data) {
buttons = data;
const container = document.getElementById("buttons");
container.innerHTML = "";
buttons.forEach((button) => {
const div = document.createElement("div");
div.className = "button-container";
div.innerHTML = `
<div class="button" onclick="openLink('${button.link}')">
<img src="https://cdn.pixabay.com/photo/2014/04/02/16/21/book-307045_1280.png" alt="${button.name}" />
<span>${button.name}</span>
</div>
<div class="like-container">
<button class="like-button" onclick="likeButton(${button.id})">👍 按讚</button>
<span id="like-count-${button.id}">${button.likes} 次讚</span>
</div>
`;
container.appendChild(div);
});
}
function addButton(event) {
event.preventDefault();
const name = document.getElementById("adminName").value.trim();
const link = document.getElementById("adminLink").value.trim();
if (!name || !link) {
alert("請輸入按鈕名稱和連結!");
return;
}
google.script.run
.withSuccessHandler(() => {
alert("按鈕新增成功!");
loadButtons();
})
.withFailureHandler((error) => {
console.error("新增按鈕失敗:", error);
alert("新增按鈕失敗,請稍後再試!");
})
.addButton(name, link);
}
function likeButton(id) {
google.script.run
.withSuccessHandler((response) => {
if (response.success) {
const likeCountSpan = document.getElementById(`like-count-${id}`);
if (likeCountSpan) {
const currentLikes = parseInt(likeCountSpan.textContent) || 0;
likeCountSpan.textContent = `${currentLikes + 1} 次讚`;
}
} else {
alert(response.message);
}
})
.withFailureHandler((error) => {
console.error("按讚失敗:", error);
alert("按讚失敗,請稍後再試!");
})
.likeButton(id, userId);
}
function openLink(link) {
window.open(link, '_blank');
}
function updateTitle(event) {
event.preventDefault();
const title = document.getElementById("adminTitle").value.trim();
if (!title) {
alert("請輸入標題!");
return;
}
google.script.run
.withSuccessHandler(() => {
alert("標題更新成功!");
updateHeader(title);
})
.withFailureHandler((error) => {
console.error("標題更新失敗:", error);
alert("標題更新失敗,請稍後再試!");
})
.setPageTitle(title);
}
function updateHeader(title) {
document.getElementById("pageHeader").textContent = title;
document.title = title; // 更新 HTML 標題
}
function resetLikes() {
google.script.run
.withSuccessHandler(() => {
alert("讚數已重置!");
loadButtons();
})
.withFailureHandler((error) => {
console.error("重置讚數失敗:", error);
alert("重置讚數失敗,請稍後再試!");
})
.resetLikes();
}
function openAdminPrompt() {
const password = prompt("請輸入密碼:");
if (password === "123") {
openAdmin();
} else {
alert("密碼錯誤!");
}
}
function openAdmin() {
document.getElementById("adminLayer").style.display = "block";
}
function closeAdmin() {
document.getElementById("adminLayer").style.display = "none";
}
function loadImages() {
google.script.run.withSuccessHandler(renderImages).getImagesFromFolder();
}
function renderImages(imageUrls) {
const slideshow = $('.cycle-slideshow');
slideshow.empty();
imageUrls.forEach((url, index) => {
slideshow.append(`<img src="https://drive.google.com/thumbnail?id=${url}&sz=w960" alt="Image ${index + 1}">`);
});
}
$(document).ready(function() {
// 获取幻灯片容器
var slideshow = $('.cycle-slideshow');
// 上一张按钮点击事件
$('.btn-prev').click(function() {
slideshow.cycle('prev');
});
// 下一张按钮点击事件
$('.btn-next').click(function() {
slideshow.cycle('next');
});
loadButtons();
loadImages();
});
</script>
</body>
</html>
```
### 說明:
1. **自動抓取圖片**:`loadImages` 函數會從 Google Apps Script 中抓取資料夾內的圖片 ID,並動態生成圖片元素插入到幻燈片中。
2. **按讚功能**:`likeButton` 函數會將按讚數記錄到試算表中,並更新按讚數顯示。
3. **後台管理**:新增了一個按鈕 `進入後台`,點擊後會彈出密碼提示框,輸入正確密碼(123)後才能進入後台。
4. **合併樣式**:將兩個專案的樣式合併,確保頁面風格一致。
請確保 Google Apps Script 中有相應的函數來處理圖片抓取和按讚數記錄等操作。