150 lines
3.9 KiB
TypeScript
150 lines
3.9 KiB
TypeScript
import { ref } from 'vue'
|
|
import { useToast } from './useToast'
|
|
import { useAccounts } from './useAccounts'
|
|
import { useProducts } from './useProducts'
|
|
|
|
const App = window.go.main.App
|
|
|
|
const scheduleActive = ref(false)
|
|
const countdownSeconds = ref(0)
|
|
const countdownTimer = ref<number | null>(null)
|
|
const runState = ref('等待操作')
|
|
|
|
export function useScheduler() {
|
|
const { showToast } = useToast()
|
|
const { resetStatus, buildAccountProducts } = useAccounts()
|
|
const { selectedProductId, selectedProductName } = useProducts()
|
|
|
|
const setRunState = (text: string) => {
|
|
runState.value = text || '等待操作'
|
|
}
|
|
|
|
const startNow = async () => {
|
|
const ap = buildAccountProducts(selectedProductId.value || '')
|
|
if (!ap) return
|
|
|
|
resetStatus()
|
|
setRunState('立即抢购已提交')
|
|
showToast('抢购中', `${Object.keys(ap).length} 个账号正在抢购`, 'info', 3000)
|
|
|
|
try {
|
|
const d = await App.StartSeckill(ap)
|
|
setRunState(d.msg || '已提交')
|
|
} catch (e: any) {
|
|
setRunState('提交失败')
|
|
showToast('提交失败', e.message, 'error')
|
|
}
|
|
}
|
|
|
|
const startSchedule = async (targetTime: string, advance: number) => {
|
|
const ap = buildAccountProducts(selectedProductId.value || '')
|
|
if (!ap) return
|
|
|
|
if (!targetTime) {
|
|
showToast('提示', '请选择目标时间', 'warn')
|
|
return
|
|
}
|
|
|
|
// 格式化时间
|
|
let timeStr = targetTime
|
|
if (timeStr.split(':').length === 2) timeStr += ':00'
|
|
|
|
const today = new Intl.DateTimeFormat('zh-CN', {
|
|
year: 'numeric',
|
|
month: '2-digit',
|
|
day: '2-digit'
|
|
}).format(new Date()).replace(/\//g, '-')
|
|
|
|
const fullTime = today + ' ' + timeStr
|
|
|
|
resetStatus()
|
|
setRunState('定时配置中')
|
|
|
|
try {
|
|
const d = await App.SetSchedule({
|
|
accountProducts: ap,
|
|
targetTime: fullTime,
|
|
advance
|
|
})
|
|
|
|
scheduleActive.value = true
|
|
localStorage.setItem('targetTime', timeStr)
|
|
localStorage.setItem('advance', String(advance))
|
|
|
|
setRunState(`定时已开启,触发 ${d.triggerTime}`)
|
|
showToast(
|
|
'定时已开启',
|
|
`触发时刻: ${d.triggerTime}<br>剩余时间: ${formatRemain(d.remainSecond)}`,
|
|
'success',
|
|
5000
|
|
)
|
|
startCountdown(d.remainSecond)
|
|
} catch (e: any) {
|
|
setRunState('定时设置失败')
|
|
showToast('定时失败', e.message, 'error')
|
|
}
|
|
}
|
|
|
|
const cancelSchedule = async () => {
|
|
try {
|
|
await App.CancelSchedule()
|
|
} catch {}
|
|
|
|
scheduleActive.value = false
|
|
localStorage.removeItem('targetTime')
|
|
localStorage.removeItem('advance')
|
|
stopCountdown()
|
|
setRunState('定时已停止')
|
|
showToast('定时已停止', '抢购任务已取消', 'warn')
|
|
}
|
|
|
|
const startCountdown = (sec: number) => {
|
|
stopCountdown()
|
|
const endTime = Date.now() + sec * 1000
|
|
|
|
countdownTimer.value = window.setInterval(() => {
|
|
const remain = Math.max(0, Math.ceil((endTime - Date.now()) / 1000))
|
|
countdownSeconds.value = remain
|
|
|
|
if (remain <= 0) {
|
|
scheduleActive.value = false
|
|
setRunState('定时已触发')
|
|
stopCountdown()
|
|
}
|
|
}, 500)
|
|
}
|
|
|
|
const stopCountdown = () => {
|
|
if (countdownTimer.value) {
|
|
clearInterval(countdownTimer.value)
|
|
countdownTimer.value = null
|
|
}
|
|
countdownSeconds.value = 0
|
|
}
|
|
|
|
const formatRemain = (sec: number): string => {
|
|
const h = Math.floor(sec / 3600)
|
|
const m = Math.floor((sec % 3600) / 60)
|
|
const s = sec % 60
|
|
return `${h}:${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`
|
|
}
|
|
|
|
const restoreSchedule = () => {
|
|
const savedTime = localStorage.getItem('targetTime')
|
|
const savedAdv = localStorage.getItem('advance')
|
|
return { savedTime, savedAdv: savedAdv ? parseInt(savedAdv) : 300 }
|
|
}
|
|
|
|
return {
|
|
scheduleActive,
|
|
countdownSeconds,
|
|
runState,
|
|
setRunState,
|
|
startNow,
|
|
startSchedule,
|
|
cancelSchedule,
|
|
formatRemain,
|
|
restoreSchedule
|
|
}
|
|
}
|