Files
qipai/miniapp/pages/cleaner/tasks.js
T

109 lines
2.9 KiB
JavaScript

const { request, ensureLogin, cents } = require('../../utils/api.js')
Page({
data: {
loading: false,
errorMessage: '',
activeTab: 'hall',
hallTasks: [],
myTasks: [],
stats: { byStatus: {}, pendingSettlementText: cents(0) },
submitPhotoText: '',
},
onShow() {
this.refreshAll()
},
async refreshAll() {
this.setData({ loading: true, errorMessage: '' })
try {
await ensureLogin()
const [hall, mine, stats] = await Promise.all([
request('/cleaning/tasks/hall?page=1&pageSize=20'),
request('/cleaning/tasks/mine?page=1&pageSize=20'),
request('/cleaning/stats'),
])
this.setData({
hallTasks: (hall.data.items || []).map(formatTask),
myTasks: (mine.data.items || []).map(formatTask),
stats: formatStats(stats.data),
})
} catch (error) {
this.setData({ errorMessage: error.message || '保洁任务加载失败' })
} finally {
this.setData({ loading: false })
}
},
switchTab(event) {
const tab = event.currentTarget.dataset.tab
if (!tab || tab === this.data.activeTab) return
this.setData({ activeTab: tab })
},
async claimTask(event) {
await this.mutateTask(event.currentTarget.dataset.taskId, 'claim')
},
async startTask(event) {
await this.mutateTask(event.currentTarget.dataset.taskId, 'start')
},
onPhotoTextInput(event) {
this.setData({ submitPhotoText: event.detail.value })
},
async submitTask(event) {
const photoUrls = this.data.submitPhotoText
.split('\n')
.map((item) => item.trim())
.filter(Boolean)
.slice(0, 9)
await this.mutateTask(event.currentTarget.dataset.taskId, 'submit', { photoUrls })
this.setData({ submitPhotoText: '' })
},
async mutateTask(taskId, action, data = {}) {
if (!taskId) return
this.setData({ loading: true, errorMessage: '' })
try {
await ensureLogin()
await request(`/cleaning/tasks/${encodeURIComponent(taskId)}/${action}`, {
method: 'POST',
data,
})
await this.refreshAll()
} catch (error) {
this.setData({ errorMessage: error.message || '保洁任务处理失败' })
} finally {
this.setData({ loading: false })
}
},
})
function formatTask(task) {
return {
...task,
rewardText: cents(task.rewardCents),
timeText: formatDate(task.updatedAt || task.createdAt),
canClaim: task.status === 'WAITING',
canStart: task.status === 'CLAIMED',
canSubmit: task.status === 'STARTED',
}
}
function formatStats(stats) {
return {
byStatus: stats.byStatus || {},
pendingSettlementText: cents(stats.pendingSettlementCents),
}
}
function formatDate(value) {
if (!value) return ''
const date = new Date(value)
const pad = (input) => String(input).padStart(2, '0')
return `${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}`
}