自製免费点名系统 - 複製贴上就能成为工程师

本文将教授如何使用程式製作一个简单的点名网页。透过这个点名系统,你可以方便地管理你的学生出席状况,并且随时查询历史出席纪录。我们将使用 Google Apps Script, GitHub 和 Google Sheets 来建立这个点名系统。我敢保证即使你完全不会程式也可以在5分钟内完成。本文会详细说明从建立 Google Sheets 到部属网页的步骤,并提供完整的程式码和演示网页。

本篇文章来自毛哥EM资讯密技。建议先右转再阅读,在那裏会有更好的阅读体验喔。
如果你觉得这篇文章有帮助到你欢迎在Instagram或Google新闻追蹤毛哥EM资讯密技

我在两年前曾经写过一篇【GAS】自製点名系统,出乎意料地帮助到许多人,所以我决定重新写一次,比上次更容易製作和操作,也更好看一些(我觉得啦)。

範例网页

首先,我们先来看一下最终的成果。这是我们要製作的点名系统的演示网页。你可以点击这里查看完整的演示网页。他有以下几个功能

点名:点击学生姓名,即可完成点名新增学生:输入学生姓名点击新增按钮,即可新增学生查询历史出席纪录:输入学生姓名点击查询按钮,即可查询历史出席纪录

好了,我们现在就开始製作这个点名系统吧w

步骤一:建立 Google Sheets 文件

首先,我们需要建立一个 Google Sheets 文件,用于存储学生的出席情况。在这个文件中,我们可以添加学生名称、出席时间、剩余课堂等信息。

请打开我建立的这个範例文件并建立副本

建立副本

这样Google Sheet就做好了。请複製这个文件的ID,我们稍后会用到。ID就是网址中的一长串字母和数字,比如说这个试算表:

https://docs.google.com/spreadsheets/d/1m0F6pOejN-ldKFIrFwssmoEPB3EPDmSQJKEPr9T88-E/edit#gid=0

它的ID就是1m0F6pOejN-ldKFIrFwssmoEPB3EPDmSQJKEPr9T88-E

步骤二:建立 Google Apps Script

现在,我们需要建立一个 Google Apps Script,用于向 Google Sheets 文件中添加和读取数据。请在网址输入script.new,进入 Google Apps Script 编辑器。接着贴上我的这一串程式。请把第一行的双引号里面换成刚才複製的ID。

const id = "1m0F6pOejN-ldKFIrFwssmoEPB3EPDmSQJKEPr9T88-E"function doGet(e){let t=e.parameter,a=SpreadsheetApp.openById(id).getSheets();switch(t.type){case"call":if(!t.time)return ContentService.createTextOutput(!1);return a[0].appendRow([t.name,t.time,t.remain]),ContentService.createTextOutput(!0);case"list":var r=a[1].getRange(2,1,a[1].getLastRow()-1,a[1].getLastColumn()).getValues().filter(e=>""!==e[0]).map(e=>({name:e[0],left:e[2]}));return ContentService.createTextOutput(JSON.stringify(r)).setMimeType(ContentService.MimeType.JSON);case"search":var[n,...r]=a[0].getDataRange().getValues();let[u,i,p]=n,s=n.indexOf(u),m=n.indexOf(i),c=n.indexOf(p),l=r.filter(e=>e[s]===t.name).map(e=>({time:e[m],left:e[c]}));return ContentService.createTextOutput(JSON.stringify(l)).setMimeType(ContentService.MimeType.JSON);case"new":let f=a[1].getLastRow()+1;return a[1].appendRow([t.name,`=COUNTIF('纪录'!A:A,A${f})`,`=D${f}-B${f}`]),ContentService.createTextOutput(!0);default:return ContentService.createTextOutput("别乱撞我~")}}

我们需要把它部属成网页,请点击左上角的部属,新增部属作业,选择部属为网页应用程式。执行身分选自己(我),谁可以存取选所有人。接着点击部属,複製网页应用程式网址。比如说:

https://script.google.com/macros/s/AKfycbzxqGIMBbLkCka2aveltdVHYtdG-k_X98qzSd_V9MHDxWaOYXFwZgE3rRHDzCakzTxs/exec

部属网页应用程式

步骤三:建立网页

请你在任意一个网页代管服务,比如说Vercel,Github Pages, Gitlab Pages, Netlify等等,建立一个网页。接着在网页中贴上以下程式码。

如果你没有使用过这些服务,可以参考以下教学:

使用 Github Pages部属网页

请先注册帐号,你可以参考以下影片:

部属网页有两个办法。选一个就可以了

用户名.github.io

第一个是影片说明的方法,就是建立一个叫做用户名.github.io的仓库,然后建立一个index.html的档案并贴上以下程式。

<!DOCTYPE html><html lang="zh-TW"><head>    <meta charset="UTF-8">    <meta http-equiv="X-UA-Compatible" content="IE=edge">    <meta name="viewport" content="width=device-width, initial-scale=1.0">    <title>简易点名系统</title>    <meta name="theme-color" content="3B4252" />    <style>        h1 {            /* 标题颜色 */            color: var(--nord7)        }        body {            /* 背景颜色 */            background-color: var(--nord0)        }        body {            /* 可选颜色 */            --nord0: #2E3440;            --nord1: #3B4252;            --nord2: #434C5E;            --nord3: #4C566A;            --nord4: #D8DEE9;            --nord5: #E5E9F0;            --nord6: #ECEFF4;            --nord7: #8FBCBB;            --nord8: #88C0D0;            --nord9: #81A1C1;            --nord10: #5E81AC;            --nord11: #BF616A;            --nord12: #D08770;            --nord13: #EBCB8B;            --nord14: #A3BE8C;            --nord15: #B48EAD;            --black: #000;            --line: #4C566A        }        main,        nav {            display: flex        }        .call button,        button:hover {            background-color: var(--nord2)        }        button,        section>div {            background-color: var(--nord1);            box-shadow: rgba(0, 0, 0, .2) 0 0 .5rem        }        main,        section>div {            padding: 1rem;            width: 100%        }        footer,        footer a {            color: var(--nord4)        }        .search button,        button,        input,        section>div {            box-shadow: rgba(0, 0, 0, .2) 0 0 .5rem        }        body,        button,        h2,        html {            text-align: center        }        * {            padding: 0;            margin: 0;            box-sizing: border-box;            font-family: Arial, "微软正黑体", Helvetica, sans-serif;            color: var(--nord6)        }        body,        html {            min-height: 100%        }        main {            flex-direction: column;            height: 100vh;            height: 100dvh;            max-width: 500px;            margin: 0 auto        }        nav {            justify-content: space-between        }        button {            display: block;            height: 50px;            width: calc(1/3*100% - 1rem);            line-height: 50px;            border-radius: 1rem;            text-decoration: none;            border: none;            cursor: pointer;            transition: background-color .2s ease-in-out        }        #call,        .search,        footer {            display: flex        }        .call button {            width: calc(1/4*100% - 1rem);            margin: .5rem        }        button:hover {            filter: brightness(1.2)        }        button:active {            background-color: var(--nord3);            filter: brightness(1.5)        }        section {            flex-grow: 1;            margin: 1rem 0;            position: relative        }        footer {            justify-content: flex-end;            align-items: flex-end        }        section>div {            border-radius: 1rem;            overflow-x: hidden;            overflow-y: auto;            position: absolute;            height: 100%;            transition: opacity .5s ease-in-out        }        #add,        #history {            opacity: 0        }        #call {            z-index: 2;            flex-wrap: wrap;            justify-content: space-between        }        .search {            justify-content: center;            align-items: center        }        .search button,        input {            height: 2rem;            width: 50%;            border-radius: .5rem;            border: transparent;            padding: 0 1rem;            background-color: var(--nord3);            color: var(--nord4)        }        h2,        table {            width: 100%        }        input:focus {            outline: transparent        }        .search button {            margin-left: 1rem;            width: auto;            line-height: 100%        }        table {            border-collapse: collapse;            margin-top: 1rem        }        tr {            border-bottom: 1px solid var(--line)        }        td {            padding: .5rem        }        h2 {            margin-top: 2rem;            font-weight: 600        }        #status {            margin: .5rem 0 1rem;            color: var(--nord13);            font-size: 1.3rem        }    </style></head><body>    <main>        <h1>简易点名系统</h1>        <h2 id="status">欢迎使用</h2>        <nav>            <button onclick="searchA()">查询纪录</button><button onclick="callA()">点名</button><button                onclick="addA()">新增学生</button>        </nav>        <section>            <div id="history">                <div class="search">                    <input type="text"><button>搜寻</button>                </div>                <table>                    <thead>                        <tr>                            <td>时间</td>                            <td>剩下课堂</td>                        </tr>                    </thead>                    <tbody>                    </tbody>                </table>            </div>            <div id="call">                <h2>载入中</h2>            </div>            <div id="add">                <div class="search"><input type="text"><button>新增</button></div>            </div>        </section>        <footer><a href="edit-mr.github.io/">毛哥EM</a>製作 | <a href="https://em-tec.github.io/post/roll-call">教学</a>        </footer>    </main>    <script>        //部属连结放这里        var url = "https://script.google.com/macros/s/AKfycbzxqGIMBbLkCka2aveltdVHYtdG-k_X98qzSd_V9MHDxWaOYXFwZgE3rRHDzCakzTxs/exec";        const [history, call, add] = ["history", "call", "add"].map(t => document.getElementById(t)), searchA = () => { history.style.opacity = 1, history.style.zIndex = 2, call.style.opacity = add.style.opacity = 0, call.style.zIndex = add.style.zIndex = 1 }, callA = () => { history.style.opacity = add.style.opacity = 0, history.style.zIndex = add.style.zIndex = 1, call.style.opacity = 1, call.style.zIndex = 2 }, addA = () => { history.style.opacity = call.style.opacity = 0, history.style.zIndex = call.style.zIndex = 1, add.style.opacity = 1, add.style.zIndex = 2 }; fetch(url + "?type=list").then(t => t.json()).then(t => { let e = document.getElementById("call"); e.innerHTML = "", t.forEach((t, n) => { let a = document.createElement("button"); a.textContent = t.name, a.id = `student-${n + 1}`, a.addEventListener("click", () => { rollCall(t.name, t.left, n + 1) }), e.appendChild(a) }) }).catch(t => console.error(t)); const status = document.getElementById("status"); function rollCall(t, e, n) { status.innerHTML = `${t} 点名中...`; var a = new Date, a = a.toLocaleString("zh-TW", { year: "numeric", month: "2-digit", day: "2-digit", hour: "numeric", minute: "numeric", second: "numeric", hour12: !0 }).replace("-", "/").replace(" ", " "); fetch(url + `?type=call&name=${t}&time=${a}&remain=${e}`).then(a => { a.ok ? (status.innerHTML = `${t} 已点名成功!剩余课堂:${e - 1}`, document.getElementById("student-" + n).style.backgroundColor = "var(--nord14)") : (status.innerHTML = `${t} 已点名失败!剩余课堂:${e}`, document.getElementById("student-" + n).style.backgroundColor = "var(--nord11)") }).catch(t => { status.innerHTML = `发生错误:${t}` }) } const searchBtn = document.querySelector("#history button"), searchInput = document.querySelector("#history input"), historyTableBody = document.querySelector("#history tbody"); searchBtn.addEventListener("click", () => { status.innerHTML = "搜寻中..."; let t = searchInput.value, e = `${e}?type=search&name=${encodeURIComponent(t)}`; fetch(e).then(t => t.json()).then(t => { let e = document.querySelector("#history table tbody"); e.innerHTML = "", t.forEach(t => { let n = document.createElement("tr"), a = document.createElement("td"), l = document.createElement("td"); var r = new Date(t.time); a.textContent = r.toLocaleString("zh-TW", { year: "numeric", month: "2-digit", day: "2-digit", hour: "numeric", minute: "numeric", second: "numeric", hour12: !0 }).replace("-", "/").replace(" ", " "), l.textContent = t.left, n.appendChild(a), n.appendChild(l), e.appendChild(n), status.innerHTML = "搜寻完成" }) }).catch(t => status.innerHTML = t) }); const addBtn = document.querySelector("#add button"), addInput = document.querySelector("#add input"); addBtn.addEventListener("click", () => { let t = addInput.value; t && (status.innerHTML = "新增中...", fetch(`${url}?type=new&name=${encodeURIComponent(t)}`).then(t => status.innerHTML = "新增成功").catch(t => { status.innerHTML = t })) });    </script></body></html>

请把第265行的双引号里面换成刚才複製的网页应用程式网址,然后按下储存。这样你的网页就完成了!你可以到网址https://你的Github帐号.github.io/来使用你的网页。

Use this template

第二个方式也很简单,请先到这个Github仓库并点击右上角的Fork,或是Use this template。仓库名称Repository name会成为你的网址(例如:https://你的Github帐号.github.io/仓库名称),然后点击Create repository from template。

请点击档案index.html并点击右上角的铅笔按钮编辑,
把第265行的双引号里面换成刚才複製的网页应用程式网址,然后按下储存。

然后再到你的仓库里面,点击Settings,然后点击左边的Pages,把Branch改成main,然后按下Save,就完成了!

Github Pages设定

好啦,现在你的网页就完成了!你可以到网址https://你的Github帐号.github.io/仓库名称来使用你的网页。

自订

这样你的网页就建立完成且可以使用了。如果你想客製化颜色的话可以修改CSS。比如说如果你想改标题你可以修改第13行

color: var(--nord7)

你可以改成任何颜色,例如:color: red,或是color: #ff0000,或是color: rgb(255, 0, 0)

你可以Google colorpicker 选取颜色,然后把HEX或是RGB的数字贴上去。

或是你可以使用预设的Nord颜色组。使用方式就是预设那样,只要修改数字就好了。对应的颜色如下:

希望你喜欢这个网页!如果你觉得这篇文章有帮助到你欢迎在Instagram或Google新闻追蹤毛哥EM资讯密技。如果你有任何问题,欢迎直接到毛哥EM资讯密技的Instagram私讯我,我很乐意协助解决你的问题。


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章