隨著互聯網的普及和移動設備的廣泛使用,越來越多的服務和功能被移植到了線上。其中,樓簽到小程序作為一種便捷的工具,被廣泛應用于樓宇管理、物業服務等領域。本文將詳細介紹如何制作一個樓簽到小程序,從設計到優化,為您提供全面的指導。
設計頁面
首先,我們需要選擇一個合適的模板,并根據具體需求來設計頁面。這個過程主要包括以下步驟:
1.1登錄頁面:添加登錄功能,允許用戶通過微信登錄,簡化注冊流程。
1.2注冊頁面:允許新用戶注冊,并提供找回密碼功能。
1.3樓宇列表頁面:展示所有可用的樓宇,方便用戶查找。
1.4簽到頁面:設計一個簡潔明了的簽到頁面,以便用戶快速完成簽到操作。
2.編寫代碼
接下來,我們需要使用適當的編程語言來編寫簽到小程序的代碼。考慮到微信小程序的平臺特性,建議使用JavaScript、HTML和CSS來完成。
2.1 JavaScript:使用JavaScript編寫邏輯代碼,處理用戶登錄、注冊、查找樓宇及簽到等操作。
2.2 HTML:使用HTML來構建小程序的結構,包括登錄、注冊、樓宇列表和簽到等頁面的布局。
2.3 CSS:使用CSS來美化頁面的外觀,提升用戶體驗。
3.測試效果
完成代碼編寫后,我們需要在微信或瀏覽器中打開簽到小程序,測試其功能和界面顯示是否符合預期。這個階段主要關注以下幾個方面:
3.1功能測試:確保小程序的所有功能都能正常運行,例如登錄、注冊、查找樓宇和簽到等。
3.2界面測試:檢查頁面的布局、顏色、字體等外觀元素是否滿足設計要求。
3.3兼容性測試:確保小程序在不同設備、不同瀏覽器上都能正常運行。
4.優化體驗
根據測試結果,我們可能會發現一些問題或不足之處。這時,我們就需要進行優化,以提升用戶的使用體驗。以下是一些常見的優化方法:
4.1響應速度優化:通過優化代碼和減少不必要的網絡請求,提高小程序的響應速度。
4.2用戶體驗優化:調整界面布局、簡化操作流程,使小程序更易于使用。
4.3功能完善:根據用戶反饋和實際需求,添加或改進一些功能,提高小程序的實用性。
4.4安全性提升:加強小程序的安全防護,防止用戶數據泄露和惡意攻擊。
5.總結
樓簽到小程序的制作并非難事,只需按照設計好的頁面模板,使用合適的編程語言編寫代碼,然后進行必要的測試和優化,就能制作出符合預期的簽到小程序。在實際制作過程中,關注用戶需求和體驗是關鍵,只有不斷優化和完善,才能打造出高質量的小程序應用。
到功能
1、數據庫中要有相應的表,并創建相應的實體類,復寫相關方法
2、在相關的jsp頁面添加兩個jsp按鈕,用于簽到與簽退,并添加id屬性
簽到簽退
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<base href="<%=basePath%>" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>無標題文檔</title>
<link href="css/style.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript">
//給按鈕signin綁定單擊事件,實現簽到功能
$(function(){
$("#signin").click(function(){
//alert("ok");
//發送ajax請求,完成簽到.并通過回調函數顯示結果
$.ajax({
url:"duty?method=signin",
type:"post",
dataType:"text",
success:function(data){
//顯示簽到結果
if(data==0){
$("#result").html("簽到失敗");
}else if (data==1) {
$("#result").html("簽到成功");
}else {
$("#result").html("已經簽到,無需重復簽到");
}
}
});
});
//給按鈕signout綁定單擊事件,實現簽退
$("#signout").click(function(){
//alert("ok?");
$.ajax({
url:"duty?method=signout",
type:"post",
dataType:"text",
success:function(result){
$("#result").html(result);
}
});
});
});
</script>
</head>
<body>
<div class="place">
<span>位置:</span>
<ul class="placeul">
<li><a href="#">考勤管理</a></li>
<li><a href="#">簽到簽退</a></li>
</ul>
</div>
<div class="formbody">
<div class="formtitle"><span>基本信息</span></div>
<ul class="forminfo">
<li><label> </label><input name="signinTime" type="button" class="btn" id="signin" value="簽到"/> 每天簽到一次,不可重復簽到</li>
<li><label> </label></li>
<li><label> </label></li>
<li><label> </label><input name="signoutTime" type="button" class="btn" id="signout" value="簽退"/>可重復簽退,以最后一次簽退為準</li>
</ul>
</div>
<div id="result"></div>
</body>
</html>
3、在servlet中編寫簽到相關方法
servlet方法
//考勤簽到操作
public void signin(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
//獲取session作用域中的emp對象,emp存放的是被考勤人信息,自行創建
Employee emp= (Employee) request.getSession().getAttribute("emp");
String empId=emp.getEmpId();
//調用業務層完成簽到操作
DutyService ds=new DutyServiceImpl();
int n=ds.signin(empId);//0失敗 1成功 2已經簽到
//無需頁面跳轉,直接響應結果(通常與ajax連用)
response.getWriter().println(n);
}
4、在service實現類編寫簽到的邏輯方法
業務實現類
截圖勾線有誤,其實進行在dao層進行了兩個操作 1、查詢是否簽到的操作 2、保存簽到信息的操作
@Override
public int signin(String empId) {
//判斷用戶是否已經簽到
Date now=new Date();//yyyyMMdd——>hhmmss
java.sql.Date today=new java.sql.Date(now.getTime());//hhmmss
boolean flag= dd.find(empId,today);//1、查詢是否簽到的操作
//對返回的flag進行處理,true:已經簽到,false沒有簽到,進行簽到
int n=0;
if (flag) {
return 2;
} else {
Duty duty=new Duty();
//duty.setDtId(dtId);序列自增
duty.setEmpId(empId);
duty.setDtDate(today);
DateFormat sdf = new SimpleDateFormat("hh:mm:ss");
String signinTime= sdf.format(now);
duty.setSigninTime(signinTime);
//完成簽到
n=dd.save(duty);//2、保存簽到信息的操作
return n;//0失敗 1成功
}
}
dao層方法
@Override
public boolean find(String empId, Date today) {
//jdbc查詢操作
//創建jdbc變量
Connection conn=null;
PreparedStatement ps=null;
ResultSet rs=null;
//創建變量
boolean flag=false;//默認情況為查不到
try {
//創建連接
conn=DBUtil.getConnection();
//創建SQL語句
String sql="select * from duty where empid=? and dtdate=?";
//創建SQL命令
ps=conn.prepareStatement(sql);
//給占位符賦值
ps.setString(1, empId);
ps.setDate(2, today);
//執行sql語句
rs=ps.executeQuery();
//遍歷
if (rs.next()) {
flag=true;//簽到成功
}
} catch (Exception e) {
e.printStackTrace();
}finally{
//關閉變量
DBUtil.closeAll(rs, ps, conn);
}
return flag;
}
@Override
public int save(Duty duty) {
//添加操作
//創建sql語句
String sql="insert into duty values(seq_duty.nextval,?,?,?,null)";
//創建params變量集合
Object[] params={duty.getEmpId(),duty.getDtDate(),duty.getSigninTime()};
return DBUtil.executeUpdate(sql, params);
6、在原來的jsp頁面中,編寫ajax請求,處理從servlet傳來的數據
jsp頁面添加方法
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<base href="<%=basePath%>" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>無標題文檔</title>
<link href="css/style.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript">
//給按鈕signin綁定單擊事件,實現簽到功能
$(function(){
$("#signin").click(function(){
//alert("ok");
//發送ajax請求,完成簽到.并通過回調函數顯示結果
$.ajax({
url:"duty?method=signin",
type:"post",
dataType:"text",
success:function(data){
//顯示簽到結果
if(data==0){
$("#result").html("簽到失敗");
}else if (data==1) {
$("#result").html("簽到成功");
}else {
$("#result").html("已經簽到,無需重復簽到");
}
}
});
});
//給按鈕signout綁定單擊事件,實現簽退
$("#signout").click(function(){
//alert("ok?");
$.ajax({
url:"duty?method=signout",
type:"post",
dataType:"text",
success:function(result){
$("#result").html(result);
}
});
});
});
</script>
</head>
<body>
<div class="place">
<span>位置:</span>
<ul class="placeul">
<li><a href="#">考勤管理</a></li>
<li><a href="#">簽到簽退</a></li>
</ul>
</div>
<div class="formbody">
<div class="formtitle"><span>基本信息</span></div>
<ul class="forminfo">
<li><label> </label><input name="signinTime" type="button" class="btn" id="signin" value="簽到"/> 每天簽到一次,不可重復簽到</li>
<li><label> </label></li>
<li><label> </label></li>
<li><label> </label><input name="signoutTime" type="button" class="btn" id="signout" value="簽退"/>可重復簽退,以最后一次簽退為準</li>
</ul>
</div>
<div id="result"></div>
</body>
</html>
簽退功能
1、在servlet層編寫簽退相關方法(提前處理,ajax直接顯示結果)
//考勤簽退操作
public void signout(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
//獲取session作用域中的emp對象
Employee emp= (Employee) request.getSession().getAttribute("emp");
String empId=emp.getEmpId();
//調用業務層完成簽到操作
DutyService ds=new DutyServiceImpl();
int n=ds.signout(empId);//0失敗 1成功 2沒有簽到
//無需頁面跳轉,直接響應結果(通常與ajax連用)
response.setContentType("text/html; charset =utf-8");
PrintWriter out= response.getWriter();
if (n==1) {
out.println("簽退成功");
} else if (n==0) {
out.println("簽退失敗");
} else {
out.println("尚未簽退");
}
}
2、在service的實現類編寫簽退的邏輯方法
//考勤簽退操作
public void signout(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
//獲取session作用域中的emp對象
Employee emp= (Employee) request.getSession().getAttribute("emp");
String empId=emp.getEmpId();
//調用業務層完成簽到操作
DutyService ds=new DutyServiceImpl();
int n=ds.signout(empId);//0失敗 1成功 2沒有簽到
//無需頁面跳轉,直接響應結果(通常與ajax連用)
response.setContentType("text/html; charset =utf-8");
PrintWriter out= response.getWriter();
if (n==1) {
out.println("簽退成功");
} else if (n==0) {
out.println("簽退失敗");
} else {
out.println("尚未簽退");
}
}
3、dao層調用的方法與簽到一致,無需添加 4、在原來的jsp頁面中,編寫ajax請求,處理從servlet傳來的數據(result為簽到簽退按鈕下的一個div的id用來顯示考勤結果)
jsp頁面中的添加的方法/函數
//給按鈕signout綁定單擊事件,實現簽退
$("#signout").click(function(){
//alert("ok?");
$.ajax({
url:"duty?method=signout",
type:"post",
dataType:"text",
success:function(result){
$("#result").html(result);
}
});
});
注:采取mvc架構模式
簽到實現 1、點擊簽到按鈕,跳轉到簽到的servlet,調用相關的方法 2、dao層首先去數據庫查看用戶是否簽到,如果簽到則返回true,如果沒簽到則返回false,并執行保存簽到信息的方法。返回簽到的結果0失敗,1成功,2已簽到,并將數據返回到servlet 3、servlet將數據直接響應給前臺頁面,jsp頁面通過Ajax獲取信息,更根據相應的值顯示相應的提示語。
簽退實現 1、點擊簽退按鈕,跳轉到簽退的servlet,調用相關的方法 2、dao層首先去數據庫查看用戶是否簽退,如果簽到則返回true,如果沒簽到則返回false,并執行保存簽退信息的方法。返回簽退的結果0失敗,1成功,2已簽到,并將數據返回到servlet 3、servlet將數據直接響應給前臺頁面,jsp頁面通過Ajax獲取信息,更根據相應的值顯示相應的提示語。
項目地址(手動復制下面地址到瀏覽器即可): shimo.im/docs/IaCeHAzWu80UoG45
一個網站每天簽到可以獲取流量,之前每天都是自己打開網頁登錄然后手動點簽到,但是如果連續7天沒簽到之前獲取的所有流量都會清空。類似的需求會有很多,很多網站、應用也都會提供簽到獲取積分、金幣、能量、飼料...其實用node腳本來實現每天自動簽到很簡單。
下方示例采用了第二種接口簽到方式,一般我們只需要先分析登錄接口,拿到登錄態,如果是直接返回的 token 那就更簡單了,也有的網站會自動通過 cookie 設置登錄態,拿到登錄態我們再帶上登錄態去請求簽到接口就可以了。
輸入賬號密碼登錄后,發現登錄接口 Response 里并沒有數據返回,然后看 Headers 里的 Response Headers 里的 Set-Cookies 就是登陸成功服務端自動設置的登錄態信息:
添加圖片注釋,不超過 140 字(可選)
這一步只需要帶著賬號密碼參數去請求登錄接口,然后再解析出 Set-Cookies 里我們需要的參數就行了,發起請求不需要用第三方庫,17.5.0版本后 node 里也可以直接使用 fetch 發送請求了,可以直接在瀏覽器控制臺 network 里選中接口右鍵 Copy - Copy as Node.js fetch 復制,示例代碼如下
/**
* 獲取登錄態 cookies
* @returns
*/
const getCookie = async function() {
const res = await fetch("https://cafe123.cn/auth/login", {
"headers": {
"accept": "application/json, text/javascript, */*; q=0.01",
"accept-language": "zh-CN,zh;q=0.9",
"content-type": "application/x-www-form-urlencoded; charset=UTF-8",
"sec-ch-ua": "\"Google Chrome\";v=\"117\", \"Not;A=Brand\";v=\"8\", \"Chromium\";v=\"117\"",
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": "\"Windows\"",
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "same-origin",
"x-requested-with": "XMLHttpRequest",
"Referer": "https://cafe123.cn/auth/login",
"Referrer-Policy": "strict-origin-when-cross-origin"
},
"body": "email=123456%40qq.com&passwd=123456&code=&remember_me=week",
"method": "POST"
})
if (res.status !== 200) {
console.log('登錄失敗:', new Date(), res)
return
}
// res.json().then(r => {
// console.log(r)
// })
const headers = res.headers
cookies = []
for (const element of headers) {
if (element[0] === 'set-cookie') {
const val = element[1].split(';')[0]
cookies.push(val)
}
}
checkin()
}
拿到響應結果后,通過 res.headers 可以拿到響應頭里的所有參數,然后可以用 for of 遍歷下取出我們需要的參數就行了。
先按照上面登錄接口類似的方法分析簽到接口的構成,這一步主要是請求頭里面的 cookie 參數,直接用上一步拿到的響應頭里的 Set-Cookies 里的登錄信息按 key=value 用分號分隔拼接好就行了。
/**
* 簽到
*/
const checkin = async function() {
if (!cookies) {
getCookie()
return
}
const res = await fetch("https://cafe123.cn/user/checkin", {
"headers": {
"accept": "application/json, text/javascript, */*; q=0.01",
"accept-language": "zh-CN,zh;q=0.9",
"sec-ch-ua": "\"Google Chrome\";v=\"117\", \"Not;A=Brand\";v=\"8\", \"Chromium\";v=\"117\"",
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": "\"Windows\"",
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "same-origin",
"x-requested-with": "XMLHttpRequest",
"cookie": cookies.join(';'),
"Referer": "https://cafe123.cn/user",
"Referrer-Policy": "strict-origin-when-cross-origin"
},
"body": null,
"method": "POST"
})
if (res.status !== 200) {
console.log('簽到失敗:', new Date().toLocaleString(), res)
cookies = null
getCookie()
} else {
console.log('簽到成功:', new Date().toLocaleString(), res)
res.json().then(r => {
console.log(r)
})
}
}
這一步需要借助定時任務 node-cron 庫,注意 node-cron 表達式總共6位,首位的秒是可以省略的,所以也可以5位:
/**
* 定時任務
*/
cron.schedule("30 2 8 * * *", function() {
// node-cron 表達式總共6位,首位的秒可以省略,所以也可以5位
// 每秒執行一次 * * * * * *
// 每天12點30分執行一次 30 12 * * *
// 每隔5秒執行一次 */5 * * * * *
// 每天早上8點到晚上6點之間每個正點執行任務一次 0 0 8-18 * * *,等同于 0 0 8,9,10,11,12,13,14,15,16,17,18 * * *
console.log("觸發定時任務:", new Date().toLocaleString())
checkin()
})
如果在自己本地電腦上運行,windows 進入睡眠狀態時,定時任務是不會執行的,即使用 pm2 啟動服務也不會執行的,只能設置讓電腦從不睡眠了,或者有服務器的部署在自己的服務器上跑。
還有如果想要在每天隨機一個時間執行內執行,用 cron 表達式是不行的,定時任務開啟后只能在某個時間點執行或者間隔多長時間執行,想到的方案是可以開啟兩個定時任務,第一個都是每天同一時間觸發,最好是每天0點0分0秒,然后在這個定時任務里再去隨機獲取一個時間,去開啟另一個定時任務去執行,這個我還沒實驗,或者你有更好的方案可以分享下喲!
完整的示例項目源碼地址:https://github.com/cafehaus/check-in,直接把里面的接口地址、參數這些換一下就行了。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。