專業級下嵌花崗岩水槽安裝紀錄表|零遺漏施工檢查助手
下嵌花崗岩水槽現場變數多,每次遇到新現場,尺寸、補強、矽利康細節、甚至現場溝通都會讓人緊張。我以前協助裝修團隊,光靠手寫筆記跟拍照,收尾階段一定有人問:「這邊矽利康有壓?角落墊片是厚的還薄的?」一旦細節沒追蹤,後續出問題一定被抓包。靠這份紀錄表,誰填的、做過什麼、工地現場狀態全都一目了然,老闆、設計、師傅都能對帳,減少扯皮機會。
立即複製標準安裝紀錄工具|工程細節不再遺漏
這個工具讓現場負責人直接用 Google 表單介面,輸入下嵌水槽每一項檢查重點,現場照片、尺寸數據一鍵記錄,全部自動寫進 Google Sheet,還能一鍵查歷史紀錄、統計合格率。誰操作、什麼時間,完整留存,現場問責、回查、交接完全不怕。
// === 下嵌花崗岩水槽施工紀錄工具 ===
function doGet(e) {
var html = [];
html.push('<html><head>');
html.push('<meta charset="UTF-8">');
html.push('<title>下嵌花崗岩水槽紀錄表</title>');
html.push('<style>body{font:15px/1.5 Arial;'
+ 'background:#f7f7f7;}label{display:block;margin:8px 0 3px;}'
+ '.err{color:#c00;}</style></head>');
html.push('<body><div style="max-width:400px;'
+ 'margin:30px auto;padding:24px;background:#fff;border-radius:8px;">');
html.push('<h2>下嵌花崗岩水槽施工紀錄</h2>');
html.push('<form id="recForm">');
html.push('<label>施工人員姓名</label>');
html.push('<input name="name" required style="width:100%">');
html.push('<label>現場地址/工地名稱</label>');
html.push('<input name="site" required style="width:100%">');
html.push('<label>檢查項目</label>');
html.push('<select name="item" required style="width:100%">'
+ '<option>檯面開孔尺寸對照圖一致</option>'
+ '<option>下緣補強條是否已完成</option>'
+ '<option>水槽放置穩固無晃動</option>'
+ '<option>邊緣矽利康填縫密合</option>'
+ '<option>下方結構支撐檢查</option>'
+ '<option>水槽進出水密封狀態</option>'
+ '</select>');
html.push('<label>實際量測(公分)</label>');
html.push('<input name="measure" type="number" step="0.1" min="0"'
+ ' style="width:80px">');
html.push('<label>現場拍照記錄(雲端連結)</label>');
html.push('<input name="photo" type="url" placeholder="Google Drive 連結"'
+ ' style="width:100%">');
html.push('<label>合格狀態</label>');
html.push('<select name="status" required>'
+ '<option>合格</option>'
+ '<option>需改善</option>'
+ '</select>');
html.push('<label>備註</label>');
html.push('<input name="note" style="width:100%">');
html.push('<button type="button" '
+ 'onclick="submitRec()" style="margin-top:16px;width:100%">'
+ '送出紀錄</button>');
html.push('</form>');
html.push('<div id="resMsg"></div>');
html.push('<hr>');
html.push('<button onclick="getHis()" '
+ 'style="width:100%;margin-bottom:12px;">'
+ '查詢歷史紀錄</button>');
html.push('<div id="hisTbl"></div>');
html.push('</div>');
html.push('<script>');
html.push('function submitRec(){');
html.push('var f=document.getElementById("recForm");');
html.push('var d={};["name","site","item","measure","photo","status","note"]'
+ '.forEach(function(k){d[k]=f[k].value});');
html.push('if(!d.name||!d.site){msg("姓名/工地必填",1);return;}');
html.push('var q=new URLSearchParams(d).toString();');
html.push('fetch("?action=add&"+q).then(x=>x.text()).then(function(res){'
+ 'msg("已儲存");f.reset();setTimeout(getHis,700);'
+ '}).catch(function(e){msg("送出失敗",1)});}');
html.push('function msg(t,err){'
+ 'var m=document.getElementById("resMsg");'
+ 'm.innerHTML="<span class=\'"+(err?"err":"")'
+ "+\"'>\"+t+\"</span>\";'
+ 'setTimeout(function(){m.innerHTML=""},2300);'
+ '}');
html.push('function getHis(){fetch("?action=his").then(x=>x.json()).then('
+ 'function(list){var html="";if(!list.length){html="無資料"}else{'
+ 'html+="<table border=1 style=\'font-size:12px;width:100%;'
+ 'margin-top:8px;\'><tr><th>時間</th>'
+ '<th>人員</th><th>工地</th>'
+ '<th>項目</th><th>量測</th>'
+ '<th>狀態</th></tr>";'
+ 'list.forEach(function(r){html+="<tr><td>"+r[0]+"</td>"'
+ '+ "<td>"+r[1]+"</td><td>"+r[2]+"</td>"'
+ '+ "<td>"+r[3]+"</td><td>"+r[4]+"</td>"'
+ '+ "<td>"+r[6]+"</td></tr>"});'
+ 'html+="</table>";}document.getElementById("hisTbl").innerHTML=html;})}'
);
html.push('window.onload=getHis;</script>');
html.push('</body></html>');
return HtmlService.createHtmlOutput(html.join(''));
}
// 處理前端表單的資料存到 Google Sheet
function doGet(e){
if(e && e.parameter && e.parameter.action){
if(e.parameter.action=='add'){
return addRecord(e);
}
if(e.parameter.action=='his'){
return getHistory();
}
}
return mainPage();
}
function addRecord(e){
var ss=SpreadsheetApp.getActiveSpreadsheet();
var sh=ss.getSheetByName('紀錄表');
if(!sh){
sh=ss.insertSheet('紀錄表');
sh.appendRow(['時間','人員','工地','檢查項目','量測(cm)',
'照片','合格','備註']);
}
var now=new Date();
var row=[
Utilities.formatDate(now,Session.getScriptTimeZone(),"yyyy/MM/dd HH:mm"),
e.parameter.name||'',
e.parameter.site||'',
e.parameter.item||'',
e.parameter.measure||'',
e.parameter.photo||'',
e.parameter.status||'',
e.parameter.note||''
];
sh.appendRow(row);
return ContentService.createTextOutput('ok');
}
// 取得歷史紀錄(最多顯示 15 筆)
function getHistory(){
var ss=SpreadsheetApp.getActiveSpreadsheet();
var sh=ss.getSheetByName('紀錄表');
var arr=sh?sh.getRange(
Math.max(2,sh.getLastRow()-14),1,
Math.min(15,sh.getLastRow()-1),8
).getValues():[];
return ContentService.createTextOutput(JSON.stringify(arr))
.setMimeType(ContentService.MimeType.JSON);
}
// 回傳主要畫面
function mainPage(){
return doGet();
}
標準化 Apps Script 安裝與部署流程
按照這個流程,就能讓你的現場團隊安全又順利使用這份紀錄表。
- 開啟 Apps Script 編輯器
先開 Google 試算表,然後在畫面上方選單找到「擴充功能」→「Apps Script」。位置就在「檔案」旁邊幾個字那邊。
進去後會看到一個新的分頁,是白底的編輯器。
⚠️ 某些公司帳號權限會擋 Apps Script,不要傻傻卡半天。
- 清空並貼上完整程式碼
在編輯器中央白色區域 Ctrl+A 全選、Delete 清空後,整段程式碼 Ctrl+V 貼進去。
畫面只留這段,原本那個 myFunction 也要刪。
⚠️ 我就有朋友沒全刪掉,結果跑出一堆 bug,完全對不起現場。
- 儲存專案
點上面那個磁碟片圖示,或直接按 Ctrl+S。
第一次存檔會跳出讓你輸入名稱,隨便取個「花崗岩水槽紀錄」就行。
⚠️ 沒有存檔直接部署的話,根本不會動,錯超久。
- 部署為網頁應用程式
右上角有個「部署」藍色按鈕,點下去→「新增部署作業」。
這時會跳出設定:
1. 點「類型」齒輪,選「網頁應用程式」
2. 「執行身分」選「我」
3. 「誰可以存取」選「任何人」
4. 全部設定完,按「部署」
⚠️ 「誰可以存取」如果沒選「任何人」,同事根本不能用,我之前就被設計師抱怨好幾次。
- 處理授權警告
一定會跳紅色警告頁,照流程點進階→「前往(不安全)」→允許。
完成後就授權成功,Apps Script 會幫你自動回到主頁。
⚠️ 這不是什麼駭客程式,自己寫的東西本來就會跳這個。我第一次超怕,實際上安全。
- 取得網址並開始使用
授權結束會顯示一串網址,複製起來,貼到瀏覽器就能開始用這套工具了。
⚠️ 只要有修改程式碼,一定要再部署一次才會變更上線。我剛開始時常常忘,現場一直罵沒更新,其實就是沒重發。
⚠️ 關於紅色授權警告頁的真相
Google 只要偵測到這份程式碼不是公開上架、也不是有取得驗證的第三方,就會自動跳出「尚未驗證」的安全警示。這不代表你的程式有毒,也不是駭客,只是 Google 很保守。如果是自己公司或信任團隊使用,照流程允許就好。我問過專業維護 G Suite 的前輩,他們公司內部小工具也都會遇到,大家都直接跳過。安全沒問題,只是提醒而已。
現場應用場景實例
負責現場監工時,我常常遇到協力廠商一天要同時跑三個案場,一不留神就忘記剛剛這個水槽矽利康條有沒有壓、下方支撐木條誰補的。用這工具,現場師傅邊裝邊填、拍照存證,主管遠端直接用手機查紀錄,不用再問來問去。還有一次幫家人做廚房,臨時換水槽型號,幸好之前有完整記錄現場尺寸,馬上就能對照。不管大案場小住宅,細節紀錄就靠它。