// ==UserScript==
// @name 导出订单最新版
// @namespace https://greasyfork.org/zh-CN/users/177458-bd777
// @version 1.35
// @description 快速导出抖店订单
// @author spper
// @match https://fxg.jinritemai.com/ffa/morder/order/list
// @icon https://www.google.com/s2/favicons?domain=jinritemai.com
// @grant GM_xmlhttpRequest
// @grant GM_setValue
// @grant GM_getValue
// ==/UserScript==
async function Sleep(sleepSecs) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
}, sleepSecs * 1000)
})
}
async function WaitUntil(conditionFunc, sleepSecs) {
sleepSecs = sleepSecs || 1
return new Promise((resolve, reject) => {
if (conditionFunc()) resolve()
let interval = setInterval(() => {
if (conditionFunc()) {
clearInterval(interval)
resolve()
}
}, sleepSecs * 1000)
})
}
// GM_xmlhttpRequest
function Request(url, opt={}) {
Object.assign(opt, {
url,
timeout: 2000,
responseType: 'json'
})
return new Promise((resolve, reject) => {
/*
for (let f of ['onerror', 'ontimeout'])
opt[f] = reject
*/
opt.onerror = opt.ontimeout = reject
opt.onload = resolve
// console.log('Request', opt)
GM_xmlhttpRequest(opt)
}).then(res => {
if (res.status === 200) return Promise.resolve(res.response)
else return Promise.reject(res)
}, err => {
return Promise.reject(err)
})
}
function Get(url, opt={}) {
Object.assign(opt, {
method: 'GET'
})
return Request(url, opt)
}
function Post(url, opt={}) {
Object.assign(opt, {
method: 'POST'
})
return Request(url, opt)
}
async function getShopName() {
await WaitUntil(() => {
return !!document.querySelector('div.headerShopName')
})
return document.querySelector('div.headerShopName').innerText
}
function toCsvString(headers, dataList) {
let rows = []
rows.push(headers)
for (let d of dataList) {
let row = []
for (let h of headers) {
row.push(d[h])
}
rows.push(row)
}
rows = rows.map(row => {
return row.map(s => `"${s}"`).join(',')
}).join('\n')
return 'data:text/csv;charset=utf-8,\ufeff' + rows
}
function extractOrderDiv(div) { // 将div里的内容搞成object
let resp = {}
let header = div.querySelector('div[class^="index_rowHeader"] > div[class^="index_RowHeader"] > div[class^="index_leftWrapper"]')
let spanList = header.querySelectorAll('span')
if (spanList.length >= 1) {
// console.log(spanList[0].innerText)
}
if (spanList.length >= 2) {
// console.log(spanList[1].innerText)
resp.orderTime = spanList[1].innerText.match(/下单时间:\s*([\d\/ :]+)/)[1]
}
if (spanList.length >= 3) {
// console.log(spanList[1].innerText)
resp.sourceType = spanList[2].innerText.match(/推广类型:\s*(.*)/)[1]
}
// content
let content = div.querySelector('div:nth-of-type(2)')
let product = content.querySelector('div[class^="style_productItem"] > div[class^="style_content"]')
resp.image = product.querySelector('img').getAttribute('src')
resp.title = product.querySelector('div[class^="style_detail"] > div[class^="style_name"]').innerText
resp.sku = product.querySelector('div[class^="style_property"] > div[class^="style_desc"]').innerText
resp.unitPrice = content.querySelector('div[class^="index_cellRow"] > div[class^="index_cell"]:nth-of-type(2) > div[class^="table_comboAmount"]').innerText
resp.number = content.querySelector('div[class^="index_cellRow"] > div[class^="index_cell"]:nth-of-type(2) > div[class^="table_comboNum"]').innerText
resp.payAmount = content.querySelector('div[class^="index_payAmount"]').innerText
resp.nickname = content.querySelector('a[class^="table_nickname"]').innerText
resp.contact = content.querySelector('div[class^="index_locationDetail"]').innerText
let contactList = resp.contact.split(',')
if (contactList.length >= 3) {
resp.contactName = contactList[0]
resp.contactPhone = contactList[1]
resp.contactAddress = contactList[2]
}
resp.status = div.querySelector('div:nth-of-type(2) > div[class^="index_cell"]:nth-of-type(4) > div:first-of-type').innerText
return resp
}
async function downloadCurrentPage() {
let divList = document.querySelectorAll('div.auxo-spin-container > div:nth-of-type(2) > div > div[data-kora_order_status]')
let dataList = []
let headers = ['orderId', 'orderTime', 'sourceType', 'title', 'sku', 'unitPrice', 'number', 'payAmount', 'nickname', 'contactName', 'contactPhone', 'contactAddress', 'contact', 'status', 'image']
for (let div of divList) {
let data = extractOrderDiv(div)
console.log(data)
dataList.push(data)
}
const csvString = toCsvString(headers, dataList)
console.log('csvString', csvString)
let shopName = await getShopName()
let link = document.createElement('a')
link.setAttribute('href', csvString)
let filename = `${shopName}-订单`
link.setAttribute('download', filename + '.csv')
link.click()
}
async function addDownloadButton() {
await WaitUntil(() => {
return !!document.querySelector('div[class^="index_middle-bar-wrapper"] div[class^="index_batchOpWrap"] div[class^="index_buttonGroup"]')
})
let div = document.querySelector('div[class^="index_middle-bar-wrapper"] div[class^="index_batchOpWrap"] div[class^="index_buttonGroup"]')
let btn = div.querySelector('button').cloneNode(true)
btn.setAttribute('data-id', '下载订单')
btn.setAttribute('_cid', 'export-orders')
btn.innerHTML = `<span>下载订单</span>`
div.appendChild(btn)
btn.onclick = (e) => {
console.log('btn.onclick', e)
downloadCurrentPage()
}
}
(async function() {
'use strict';
// Your code here...
await addDownloadButton()
})();