您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Save appointments into Excel file
当前为
// ==UserScript== // @name Appointments // @namespace http://tampermonkey.net/ // @version 0.6 // @description Save appointments into Excel file // @author Dorosh // @include https://app.zenmaid.com/appointments/list?* // @grant GM_xmlhttpRequest // ==/UserScript== var dropDownMenu = document.querySelector('ul[class="dropdown-menu"]'); dropDownMenu.innerHTML += '<li><button id="toExcelBtn" class="to-aside" style="background:none;border:none;">        Export Excel</button></li>'; var toExcelBtn = dropDownMenu.querySelector('button[id="toExcelBtn"]'); toExcelBtn.addEventListener("click", exportAppointments); function exportAppointments() { var result = ''; var requestData = []; var appointmentList = document.querySelector('div[id="appointments-list"]'); var appointmentsPerDay = appointmentList.querySelectorAll('div[class="col-sm-12"]'); for(var dayIndex in appointmentsPerDay) { if(appointmentsPerDay[dayIndex].localName == 'div') { var appointmentsGroup = appointmentsPerDay[dayIndex]; var day = appointmentsGroup.querySelector('div[class="row appointment-date-list"]').querySelector('h3').textContent.trim(); result += day + '\n'; result += 'Day;Time;Client;Price;Address from info;Phone;Recurrence;Assigned to;Working Hours;Cash;Check;Credit Card;Invoice;Notes\n'; var appointmentInfos = appointmentsGroup.querySelectorAll('div[class="col-sm-10"]'); Array.from(appointmentInfos).forEach(function(info, index, infos) { var time = info.parentNode.querySelector('h4').textContent.trim().replace(' ', ' '); var workingHours = getHoursInterval(time); var clientName = info.querySelector('h3[class="mt-s"]').textContent; //var address = info.querySelector('p').textContent.trim(); var price = parseInt(info.querySelector('span[class="chargeable-price"]').textContent.trim().replace('$', '')); var previewLinkData = info.querySelector('a[class="btn btn-default btn-rounded btn-lg appointment-entry"]').getAttribute("data-appointment"); requestData.push(previewLinkData); result = result + day + ';' + time + ';' + clientName + ';' + price + ';' + previewLinkData + '\n'; GM_xmlhttpRequest( { method: 'GET', url: 'https://app.zenmaid.com/appointments/preview_panel/' + previewLinkData + '.js', overrideMimeType: 'text/javascript', onload: function( resp ) { var div = document.createElement( 'div' ); div.id = 'response'; div.style.display = 'none'; div.innerHTML = clearResponse(resp.responseText); var address = div.querySelector('p[class="bigger"]').textContent.trim(); var customerPhone = div.querySelector('ul[class="list-unstyled list-contact"]'); if(customerPhone.querySelector('a')) customerPhone = customerPhone.querySelector('a').href.replace("tel:", ""); else customerPhone = "No phone"; var recurrence = div.querySelector('div[class="appointment-recurrence"]').textContent; var assignedTo = div.querySelector('div[id="assigned-employees-preview"]'); if(assignedTo.querySelector('span[class="red"]')) { assignedTo = "No Cleaners Assigned"; } else { assignedTo.querySelector('div').outerHTML = ""; assignedTo = assignedTo.textContent.trim(); } var fields = div.querySelectorAll('strong[class="black"]'); var fieldsMap = {}; fields.forEach(function(element) { var name = element.innerText.trim(); fieldsMap[name] = element;}); var check = ""; if(fieldsMap['Check'] != null) if(fieldsMap['Check'].nextSibling.textContent.trim() == "Yes") check = price; var creditCard = ""; if(fieldsMap['Credit Card'] != null) if(fieldsMap['Credit Card'].nextSibling.textContent.trim() == "Yes") creditCard = price; var cash = ""; if(fieldsMap['Cash'] != null) if(fieldsMap['Cash'].nextSibling.textContent.trim() == "Yes") cash = price; var invoice = ""; if(fieldsMap['Invoice'] != null) if(fieldsMap['Invoice'].nextSibling.textContent.trim() == "Yes") invoice = price; var notesContainer = div.querySelector('div[class="col-xs-12 mb-l"]').querySelector('p'); var notes = notesContainer.innerHTML.replace(/<br\s*[\/]?>/gi, "\\").replace(/</g,'<').replace(/>/g,'>').replace(';', '\\').trim(); var additionalData = address + ';' + customerPhone + ';' + recurrence + ';' + assignedTo + ';' + "[interval]"+ ';' + cash + ';' + check + ';' + creditCard + ';' + invoice + ';' + notes; result = result.replace(previewLinkData, additionalData); result = result.replace("[interval]", workingHours); remove(requestData, previewLinkData); downloadIfDone(requestData, result); //console.log(div); } }); }); } } } function clearResponse(rawText) { var result = rawText.replace("loadAsideWithData(", ""); result = result.slice(0, result.indexOf("event") - 3); result = result.replace(/\\n/gm, "").replace(/\\"/gm, '"').replace(/\\\//gm, '/'); return result; } function remove(array, element) { const index = array.indexOf(element); if (index !== -1) array.splice(index, 1); } function downloadIfDone(array, result) { if(array.length > 0) return; console.log(result); var currentDate = new Date(); var a = document.createElement("a"); a.href = "data:text," + result; //content a.download = currentDate.toUTCString() + ".csv"; //file name a.click(); } function getHoursInterval(input) { var time = {}; time.full = input.split(' ').join(''); var startPart = time.full.substring(0, time.full.indexOf('-')); var endPart = time.full.substring(time.full.indexOf('-') + 1, time.full.length); time.begin = to24HoursFormat(startPart); time.end = to24HoursFormat(endPart); var dateBegin = new Date(2000, 1, 1, time.begin.hours, time.begin.minutes); var dateEnd = new Date(2000, 1, 1, time.end.hours, time.end.minutes); var hoursDiff = (dateEnd.getTime() - dateBegin.getTime()) / 3600000; return hoursDiff; } function to24HoursFormat(input) { var result = {}; var dayPart = input.substring(5, 7); var hours = parseInt(input.substring(0, 2)); if(dayPart == "PM" && hours != 12) result.hours = hours + 12; else result.hours = hours; result.minutes = parseInt(input.substring(3, 5)); return result; }