最近在駕校學(xué)習(xí),采用的是一種叫做『智慧駕培』的教學(xué)模式——學(xué)員可以在網(wǎng)站(蘇州智慧駕培管理系統(tǒng))上預(yù)約教練,然后一對一練車。預(yù)約的時(shí)候,可以選擇不同教練、不同時(shí)段,但要想預(yù)約到合適的教練和時(shí)段,就需要『搶』了。于是我想,如果有一個(gè)類似于搶火車票插件的東西來輔助預(yù)約,肯定事半功倍——這就是開發(fā)『智慧駕培助手』的初衷。
Chrome擴(kuò)展
首先,在本地『搶』是比較容易的,早期的搶火車票插件也是這個(gè)思路,所以做成瀏覽器擴(kuò)展的形式再好不過了——在前端操作,方便快捷。
瀏覽器擴(kuò)展,有Chrome的、Firefox的,甚至Edge的,等等。考慮到通用程度,Chrome擴(kuò)展無疑是最方便的。由于內(nèi)核相同的緣故,Chrome擴(kuò)展不作任何改動(dòng)即可適配一排國產(chǎn)瀏覽器——360極速瀏覽器、獵豹瀏覽器、搜狗瀏覽器、QQ瀏覽器、百度瀏覽器...
Chrome擴(kuò)展的開發(fā)文檔,推薦360極速瀏覽器擴(kuò)展開發(fā)文檔和百度瀏覽器擴(kuò)展開發(fā)文檔,這兩個(gè)可以認(rèn)為是官方文檔的中文版,經(jīng)過他們整理后,也比官方文檔更好理解。當(dāng)然,追求最新、最權(quán)威的解釋,還得去找官方的。
如果有些前端基礎(chǔ),Chrome擴(kuò)展上手是很快的,畢竟它本質(zhì)上來說就是Web頁面。
系統(tǒng)預(yù)約頁面
系統(tǒng)預(yù)約頁面如上圖,橫排為教練,縱列為時(shí)段。每天20:00,系統(tǒng)會(huì)放出7天后的教練排班信息。如果某位教練的某個(gè)時(shí)段有排班,那對應(yīng)位置就會(huì)出現(xiàn)一個(gè)綠色的塊,點(diǎn)擊,確認(rèn),即可完成預(yù)約過程。
需要說明的是,一個(gè)白色格子代表一個(gè)小時(shí),但是練一次車一般是兩個(gè)小時(shí),所以一個(gè)綠色的塊一般會(huì)覆蓋兩個(gè)白色格子。
智慧駕培助手
最后寫出來是這樣的:
在設(shè)置頁面,設(shè)置好預(yù)約日期、教練和時(shí)段,然后在首頁就可以開始預(yù)約了。
點(diǎn)擊『開始預(yù)約』按鈕后,插件會(huì)自動(dòng)刷新和監(jiān)測預(yù)約日期當(dāng)天的教練排班信息。新的教練排班信息放出后,插件會(huì)立即響應(yīng),自動(dòng)完成預(yù)約過程并通知提醒,然后自動(dòng)停止。當(dāng)然,如果設(shè)置的教練和時(shí)段,與系統(tǒng)中的教練排班信息沒有匹配的,插件也會(huì)提醒預(yù)約失敗。
技術(shù)細(xì)節(jié)
完整的項(xiàng)目結(jié)構(gòu)見下圖:
項(xiàng)目采用了Gulp
作為前端構(gòu)建工具,gulpfile.js
里有兩個(gè)關(guān)鍵任務(wù),分別對應(yīng)SCSS文件和JavaScript文件的處理。
// Styles
gulp.task('styles', function() {
return sass('src/css/*.scss', {
style: 'compressed'
})
.pipe(rename({
suffix: '.min'
}))
.pipe(gulp.dest('dist/css'))
.pipe(notify({
message: 'Styles task complete'
}));
});
// Scripts
gulp.task('scripts', function() {
return gulp.src('src/js/*.js')
.pipe(rename({
suffix: '.min'
}))
.pipe(uglify())
.pipe(gulp.dest('dist/js'))
.pipe(notify({
message: 'Scripts task complete'
}));
});
Gulp引入到項(xiàng)目中,很多操作都可以自動(dòng)化了,開發(fā)效率大大提高。
項(xiàng)目也引入了jQuery
和Bootstrap
,在寫CSS樣式和DOM操作邏輯的時(shí)候省心不少。
在插件設(shè)置頁面,預(yù)約日期選項(xiàng)會(huì)貼心地提醒用戶幾天后是幾月幾日,這是借助Moment.js
來實(shí)現(xiàn)的;教練名字輸入后也會(huì)進(jìn)行校驗(yàn),除了字符長度合適,還得是中文(少數(shù)民族和外國人就不考慮了)。
// popup.js
function isChinese(str) {
var reg = /[^\u4e00-\u9fa5]/;
if (reg.test(str)) return false;
return true;
}
中文校驗(yàn)通過Unicode編碼來實(shí)現(xiàn),雖然比較粗糙,但區(qū)分中文和英文還是完全可以的。
關(guān)于第一教練、第二教練、第一時(shí)段和第二時(shí)段,中間也有一些邏輯,見下圖:
設(shè)置完成后,通過Chrome存儲(chǔ)相關(guān)的API將數(shù)據(jù)保存在本地,比如保存預(yù)約日期:
// popup.js
chrome.storage.local.set({'reservationDate': reservation_date}, function() {
// 后續(xù)操作
});
同時(shí),首頁也更新了,顯示的是設(shè)置之后的信息。
點(diǎn)擊『開始預(yù)約』按鈕后,插件會(huì)在特定頁面執(zhí)行相應(yīng)的腳本。
特定頁面是哪些頁面?manifest.json
里有相應(yīng)的限制:
{
"name": "智慧駕培助手",
"version": "1.0",
"description": "蘇州智慧駕培管理系統(tǒng)助手",
...
"permissions": [
"activeTab",
"notifications",
"storage",
"http://zhjp.sz-its.cn/"
]
}
執(zhí)行什么腳本?popup.js
里有相應(yīng)的邏輯:
chrome.tabs.executeScript(null, { file: 'lib/js/jquery.min.js' }, function() {
chrome.tabs.executeScript(null, { file: 'dist/js/script.min.js' });
});
jQuery就不說了,$
用起來實(shí)在方便。script.js
是自己寫的,負(fù)責(zé)系統(tǒng)預(yù)約頁面的刷新、監(jiān)測以及預(yù)約操作。
具體的邏輯就不細(xì)說了,主要涉及DOM的查詢、修改和點(diǎn)擊事件的模擬等。
預(yù)約結(jié)果的提醒通過Chrome桌面通知相關(guān)的API來實(shí)現(xiàn)。
// popup.js
function showNotification(title, message) {
var options = {
type : "basic",
title: title,
message: message,
iconUrl: "images/icon_48.png"
};
chrome.notifications.create("start", options, function(notId) {
setTimeout(function() {
chrome.notifications.clear(notId);
}, 5000);
});
}
Chrome擴(kuò)展『智慧駕培助手』的代碼已經(jīng)在GitHub
上開源了——點(diǎn)此前往,歡迎學(xué)習(xí)交流。
個(gè)人技術(shù)博客 biebu.xin,原文鏈接——Chrome擴(kuò)展『智慧駕培助手』開發(fā)心得