# 運動中心 api
邏輯: 某一頁可以找到場地的 Object : providers
利用 Template7 先將 BODY 建立一個 屬於外掛的 DOM,給予 ID,由於頁面本身有 Jqeury 所以直接引用。接著綁定按鈕事件, reload 跟 原始網頁的 method 預約
再跑一次 providers 迴圈,將變數塞入物件,建立實例,因為後段一次只吃一個場地的參數,所以依次將 ID 塞到 job 陣列裡面。
建立完畢之後 doJob,每次將 job 的陣列吐出一個 value, 塞入 run 中,run 建立一個 Promise,代表這個場地資料取得完畢,並且 render dom。結束之後繼續把 job 變數重複傳遞,直到 job 變成空陣列為止
class 物件:主要包裝了兩個 load、send
#### load
根據 actionInit 去針對後端寫入場地參數
接著 actionGetDateList 去要每日的時段列表
讀取資料 render 到 dom 中
#### send
根據 actionInit 去針對後端寫入場地參數
呼叫原生網頁的 API 送 日期 (date) 時間(time) => 跳轉
## Fetch 版本
```javascript
// ==UserScript==
// @name sport_auto_api
// @namespace http://mesak.tw
// @version 1.0
// @description Help order sport place
// @author Mesak
// @match https://pzsc.17fit.com/service-flow-sp
// @icon https://www.google.com/s2/favicons?sz=64&domain=17fit.com
// @require https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.3/moment.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/template7/1.4.1/template7.min.js
// ==/UserScript==
const dataFormat = "YYYY/MM/DD";
const allowDates = [moment(), moment().add(1, "days"), moment().add(2, "days"), moment().add(3, "days")];
const bodyTemplate = `<section class="container" id="plugin_order_place">
<div class="row">
{{#each this}}
<div class="col-md-6">
<div id="place_{{member_id}}" data-key="{{@key}}" class="panel panel-primary">
<div class="panel-heading"><span>{{member_name}}</span>
<button type="button" class="refresh close" data-id="{{member_id}}">
<span class="glyphicon glyphicon-refresh" aria-hidden="true"></span>
</button>
</div>
<div class="panel-body text-center"></div>
</div>
</div>
{{/each}}
</div>
</section>`;
const dateTemplate = `
<div class="row">
{{#each list}}
<div class="col-md-3">
<h4>{{title}}</h4>
{{#each times}}
<div style="margin-bottom:6px">
<a class="btn btn-warning btn-block" rel="pick_up_time" data-id="{{@root.id}}" data-time="{{time}}" data-date="{{date}}">{{time}}</a>
</div>
{{else}}
<div style="text-align: center; ">
本日已額滿,請選擇其它日期
</div>
{{/each}}
</div>
{{/each}}
</div>
`;
const loadTemplate = `
<div class="loader triangle">
<svg viewBox="0 0 86 80">
<path d="M40 65L5.35899 4.99999L74.641 5L40 65Z"/>
</svg>
</div>
`
class place {
constructor(name, member_id, role_relationships_id) {
this.member_id = member_id;
this.role_relationships_id = role_relationships_id;
this.level_price = 0;
this.member_name = name;
this.dates = new Map();
this.$node = $(`#place_${member_id}`);
}
actionInit() {
return new Promise((resolve, _reject) => {
fetch('https://pzsc.17fit.com/service-flow-dt',{
method : 'POST',
headers:{
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
member_id: this.member_id, //場點 ID
role_relationships_id: this.role_relationships_id, //場地 ID
member_name: this.member_name, //場地名稱
level_price: this.level_price,
})
})
.then(function(response) {
resolve();
})
});
}
actionGetDateList() {
const datePromise = [];
allowDates.forEach((moment, index) => {
let date = moment.format(dataFormat);
datePromise.push(
fetch('https://pzsc.17fit.com/getServiceProviderDateTimeApi',{
method : 'POST',
headers:{
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
date: moment.format(dataFormat),
})
}).then( (response) => response.json() ).then( (data) => {
this.setDate(date, data);
})
);
});
return new Promise((resolve, _reject) => {
Promise.all(datePromise).then((result) => {
resolve(result);
});
});
}
setDate(date, data) {
this.dates.set(date, data);
}
load(){
return new Promise((resolve, _reject) => {
this.$node.find('.panel-body').html(Template7.compile(loadTemplate));
this.actionInit().then(() => {
this.actionGetDateList().then((data) => {
this.render();
resolve(data)
});
});
});
}
send(date,time) {
this.actionInit().then(() => {
$17.formPost({
url: "https://pzsc.17fit.com/service-flow-confirm",
params: {
is_cash: 0,
selected_day: date,
selected_time: time
},
});
});
}
render() {
let data = {
id: this.member_id,
list: [],
};
allowDates.forEach((moment, index) => {
let date = moment.format(dataFormat);
let dateTimes = this.dates.get(date);
let dateData = {
title: date,
times: Array.from(dateTimes.values()),
};
dateData.hasTimes = dateData.times.length > 0;
data.list.push(dateData);
});
this.$node.find('.panel-body').html(Template7.compile(dateTemplate)(data));
}
}
(function () {
"use strict";
//$('body').append('<div id="plugin_order_place"></div>')
providers = providers.filter( item => item.member_id != 0);
$("body").append(Template7.compile(bodyTemplate)(providers));
const service = new Map();
const jobs = [];
let test_id ;
providers.forEach((item, index) => {
service.set( `member_${item.member_id}`, new place(item.member_name, item.member_id, item.role_relationships_id));
jobs.push( `member_${item.member_id}` );
test_id = `member_${item.member_id}`
});
$('#plugin_order_place').on('click','a[rel="pick_up_time"]' , (e) => {
$17.swal({
title: `預約時間 ${e.currentTarget.dataset.date} ${e.currentTarget.dataset.time}`,
text: '是否要預約?',
type: 'success',
}, () => {
const member_id = e.currentTarget.dataset.id
const activeService = service.get(`member_${member_id}`);
activeService.send(e.currentTarget.dataset.date,e.currentTarget.dataset.time)
});
}).on('click','.refresh' , (e) => {
const member_id = e.currentTarget.dataset.id
run( `member_${member_id}` )
})
function run( id ) {
const activeService = service.get(id);
return activeService.load();
}
function doJob(jobs){
if( jobs.length ){
run( jobs.shift() ).then(()=>{
doJob(jobs)
})
}
}
doJob( jobs )
//run( test_id )
})();
```