const api = require('../../utils/api') const PAGE_SIZE = 10 let usageStatsLoadSeq = 0 let keywordSearchTimer = null const pad2 = value => String(value).padStart(2, '0') const formatDate = date => `${date.getFullYear()}-${pad2(date.getMonth() + 1)}-${pad2(date.getDate())}` const defaultDateRange = () => { const today = new Date() return { startDate: `${today.getFullYear()}-${pad2(today.getMonth() + 1)}-01`, endDate: formatDate(today), } } const metricLabel = metricKind => (metricKind === 'quantity' ? '数量' : '时长') const valueLabel = row => { if (row.metricKind === 'quantity') { return `${Number(row.value || 0)} 件` } return api.formatDurationAllUnits(row.value) } const openDocumentFile = filePath => new Promise((resolve, reject) => { wx.openDocument({ filePath, fileType: 'xlsx', showMenu: true, success: resolve, fail: () => reject(new Error('打开文件失败')), }) }) Page({ data: { ...defaultDateRange(), category: 'device', sortBy: 'value', attendancePoints: [], attendancePointLabels: ['全部考勤点'], attendancePointIndex: 0, attendancePointName: '', keyword: '', rows: [], page: 1, pageInput: '1', totalPages: 1, loading: false, exporting: false, refreshing: false, scrollTop: 0, }, onLoad() { this.init() }, onUnload() { if (keywordSearchTimer) { clearTimeout(keywordSearchTimer) keywordSearchTimer = null } }, async init() { await this.loadAttendancePoints() await this.load(1) }, async loadAttendancePoints() { try { const points = await api.listAccessibleAttendancePoints() const attendancePoints = points || [] this.setData({ attendancePoints, attendancePointLabels: ['全部考勤点'].concat(attendancePoints.map(item => item.name)), }) } catch (error) { wx.showToast({ title: error.message || '加载考勤点失败', icon: 'none' }) } }, async load(page = this.data.page) { const loadSeq = usageStatsLoadSeq + 1 usageStatsLoadSeq = loadSeq this.setData({ loading: true }) try { const result = await api.listUsageStats({ category: this.data.category, sortBy: this.data.sortBy, startDate: this.data.startDate, endDate: this.data.endDate, attendancePointName: this.data.attendancePointName, keyword: this.data.keyword, page, pageSize: PAGE_SIZE, }) if (loadSeq !== usageStatsLoadSeq) { return } const rows = result.rows || [] const maxValue = Math.max(1, ...rows.map(item => Number(item.value || 0))) this.setData({ rows: rows.map(item => ({ ...item, metricLabel: metricLabel(item.metricKind), valueText: valueLabel(item), barPercent: Math.max(4, Math.round(Number(item.value || 0) / maxValue * 100)), uniqueKey: `${item.category || ''}-${item.id || ''}-${item.metricKind || ''}-${item.name || ''}`, })), page: result.page || 1, pageInput: String(result.page || 1), totalPages: result.totalPages || 1, scrollTop: 0, }) } catch (error) { if (loadSeq === usageStatsLoadSeq) { wx.showToast({ title: error.message || '加载统计失败', icon: 'none' }) } } finally { if (loadSeq === usageStatsLoadSeq) { this.setData({ loading: false }) } } }, async onPullDownRefresh() { this.setData({ refreshing: true }) try { await this.load(1) } finally { this.setData({ refreshing: false }) if (wx.stopPullDownRefresh) { wx.stopPullDownRefresh() } } }, chooseCategory(e) { const category = e.currentTarget.dataset.category if (category === this.data.category) { return } this.setData({ category, page: 1 }) this.load(1) }, chooseSort(e) { const sortBy = e.currentTarget.dataset.sort if (sortBy === this.data.sortBy) { return } this.setData({ sortBy, page: 1 }) this.load(1) }, onStartChange(e) { this.setData({ startDate: e.detail.value, page: 1 }) this.load(1) }, onEndChange(e) { this.setData({ endDate: e.detail.value, page: 1 }) this.load(1) }, onAttendancePointChange(e) { const attendancePointIndex = Number(e.detail.value) const point = attendancePointIndex > 0 ? this.data.attendancePoints[attendancePointIndex - 1] : null this.setData({ attendancePointIndex, attendancePointName: point ? point.name : '', page: 1, }) this.load(1) }, onKeywordInput(e) { this.setData({ keyword: e.detail.value, page: 1 }) if (keywordSearchTimer) { clearTimeout(keywordSearchTimer) } keywordSearchTimer = setTimeout(() => { keywordSearchTimer = null this.load(1) }, 350) }, searchKeyword() { if (keywordSearchTimer) { clearTimeout(keywordSearchTimer) keywordSearchTimer = null } this.setData({ page: 1 }) this.load(1) }, openDetail(e) { const row = this.data.rows[Number(e.currentTarget.dataset.index)] if (!row) { return } const attendancePointName = this.data.attendancePointName || row.attendancePointName || '' const params = [ ['category', row.category || this.data.category], ['id', row.id || ''], ['metricKind', row.metricKind || ''], ['startDate', this.data.startDate], ['endDate', this.data.endDate], ['attendancePointName', attendancePointName], ['name', row.name || ''], ['productName', row.productName || ''], ['processName', row.processName || ''], ['stampingMethod', row.stampingMethod || ''], ].map(pair => `${pair[0]}=${encodeURIComponent(pair[1])}`).join('&') wx.navigateTo({ url: `/pages/usageStatsDetail/usageStatsDetail?${params}` }) }, async exportFile() { if (this.data.exporting) { return } this.setData({ exporting: true }) wx.showLoading({ title: '导出中' }) let filePath = '' try { filePath = await api.exportUsageStats({ startDate: this.data.startDate, endDate: this.data.endDate, attendancePointName: this.data.attendancePointName, keyword: this.data.keyword, }) await openDocumentFile(filePath) } catch (error) { wx.showToast({ title: error.message || (filePath ? '打开文件失败' : '导出失败'), icon: 'none' }) } finally { wx.hideLoading() this.setData({ exporting: false }) } }, onPageInput(e) { this.setData({ pageInput: e.detail.value }) }, jumpToPage(e) { wx.hideKeyboard() const inputValue = e && e.detail && e.detail.value !== undefined ? e.detail.value : this.data.pageInput const target = Math.max(1, Math.min(Number(inputValue) || this.data.page, this.data.totalPages)) if (target === this.data.page) { this.setData({ pageInput: String(this.data.page || 1) }) return } this.load(target) }, prevPage() { if (this.data.page > 1) { this.load(this.data.page - 1) } }, nextPage() { if (this.data.page < this.data.totalPages) { this.load(this.data.page + 1) } }, })