init
项目初始化
This commit is contained in:
211
pages/checkin/checkin.js
Normal file
211
pages/checkin/checkin.js
Normal file
@@ -0,0 +1,211 @@
|
||||
const api = require('../../utils/api');
|
||||
const auth = require('../../utils/auth');
|
||||
|
||||
const STATUSES = ['正常', '迟到', '请假', '不参加讨论', '早退'];
|
||||
const WEEKDAYS = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
|
||||
const STATUS_META = {
|
||||
正常: '#2E7D32',
|
||||
迟到: '#C67B30',
|
||||
请假: '#3A7BD5',
|
||||
早退: '#8B7A6A',
|
||||
'不参加讨论': '#C0392B'
|
||||
};
|
||||
const STATUS_ITEMS = STATUSES.map((label) => ({
|
||||
label,
|
||||
color: STATUS_META[label] || '#C67B30'
|
||||
}));
|
||||
|
||||
function errMessage(err) {
|
||||
if (err && typeof err === 'object') {
|
||||
if (err.detail) return String(err.detail);
|
||||
if (err.error) return String(err.error);
|
||||
if (err.message) return err.message;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
function pad2(n) {
|
||||
return n < 10 ? '0' + n : String(n);
|
||||
}
|
||||
|
||||
function fmtTime(ts) {
|
||||
if (!ts) return '';
|
||||
const d = new Date(String(ts).replace(' ', 'T'));
|
||||
if (isNaN(d.getTime())) return String(ts);
|
||||
const now = new Date();
|
||||
const startOfDay = (x) => new Date(x.getFullYear(), x.getMonth(), x.getDate()).getTime();
|
||||
const diff = Math.round((startOfDay(now) - startOfDay(d)) / 86400000);
|
||||
const hm = pad2(d.getHours()) + ':' + pad2(d.getMinutes());
|
||||
if (diff === 0) return '今天 ' + hm;
|
||||
if (diff === 1) return '昨天 ' + hm;
|
||||
return pad2(d.getMonth() + 1) + '-' + pad2(d.getDate()) + ' ' + hm;
|
||||
}
|
||||
|
||||
Page({
|
||||
data: {
|
||||
statuses: STATUSES,
|
||||
statusItems: STATUS_ITEMS,
|
||||
statusIndex: -1,
|
||||
loading: true,
|
||||
classDate: '',
|
||||
weekday: '',
|
||||
dayNum: '',
|
||||
checked: false,
|
||||
record: null,
|
||||
statusColor: '',
|
||||
statusBg: '',
|
||||
history: [],
|
||||
group: [],
|
||||
groupName: '',
|
||||
checkedCount: 0,
|
||||
total: 0,
|
||||
tab: 'group',
|
||||
submitting: false,
|
||||
refreshing: false,
|
||||
loadError: '',
|
||||
},
|
||||
|
||||
onShow() {
|
||||
this.loadPage();
|
||||
},
|
||||
|
||||
onPullDownRefresh() {
|
||||
this.loadPage().then(() => wx.stopPullDownRefresh());
|
||||
},
|
||||
|
||||
loadPage() {
|
||||
this.setData({ loadError: '' });
|
||||
return auth.ensureLogin()
|
||||
.then((token) => {
|
||||
if (!token) {
|
||||
wx.switchTab({ url: '/pages/profile/profile' });
|
||||
return;
|
||||
}
|
||||
return this.loadWeek();
|
||||
})
|
||||
.catch((err) => {
|
||||
const msg = (err && (err.error || err.detail || err.message)) || '加载失败,请重试';
|
||||
this.setData({ loading: false, loadError: msg });
|
||||
wx.showToast({ title: msg, icon: 'none' });
|
||||
});
|
||||
},
|
||||
|
||||
onRetry() {
|
||||
this.loadPage();
|
||||
},
|
||||
|
||||
loadWeek() {
|
||||
this.setData({ loading: true });
|
||||
return api.request({ url: '/api/v1/checkin/week' }).then((res) => {
|
||||
const classDate = res.class_date || '';
|
||||
const weekday = WEEKDAYS[new Date(classDate + 'T00:00:00').getDay()] || '';
|
||||
const dayNum = classDate.split('-')[2] || '';
|
||||
const statusIndex = res.record && res.record.status
|
||||
? Math.max(0, STATUSES.indexOf(res.record.status))
|
||||
: -1;
|
||||
const statusColor = res.record ? (STATUS_META[res.record.status] || '#C67B30') : '';
|
||||
this.setData({
|
||||
classDate,
|
||||
weekday,
|
||||
dayNum,
|
||||
checked: !!res.checked,
|
||||
record: res.record || null,
|
||||
statusIndex,
|
||||
statusColor,
|
||||
statusBg: statusColor ? statusColor + '1A' : ''
|
||||
});
|
||||
return this.loadGroup();
|
||||
}).then(() => {
|
||||
this.setData({ loading: false });
|
||||
}).catch(() => {
|
||||
this.setData({ loading: false });
|
||||
});
|
||||
},
|
||||
|
||||
loadGroup() {
|
||||
const data = this.data.classDate ? { class_date: this.data.classDate } : {};
|
||||
return api.request({ url: '/api/v1/checkin/group', data }).then((res) => {
|
||||
const members = (res.members || []).map((m) => ({
|
||||
...m,
|
||||
shortName: (m.name || '?').charAt(0),
|
||||
timeText: m.checked && m.record ? fmtTime(m.record.checked_at) : ''
|
||||
}));
|
||||
const checkedCount = members.filter((m) => m.checked).length;
|
||||
this.setData({
|
||||
group: members,
|
||||
groupName: res.group_name || '',
|
||||
checkedCount,
|
||||
total: members.length
|
||||
});
|
||||
}).catch(() => {});
|
||||
},
|
||||
|
||||
loadHistory() {
|
||||
return api.request({ url: '/api/v1/checkin/list', data: { page: 1, size: 20 } }).then((res) => {
|
||||
const history = (res.list || []).map((item) => {
|
||||
const color = STATUS_META[item.status] || '#C67B30';
|
||||
return {
|
||||
...item,
|
||||
timeText: fmtTime(item.checked_at),
|
||||
color,
|
||||
bg: color + '1A'
|
||||
};
|
||||
});
|
||||
this.setData({ history });
|
||||
}).catch(() => {});
|
||||
},
|
||||
|
||||
onStatusTap(e) {
|
||||
if (this.data.submitting) {
|
||||
return;
|
||||
}
|
||||
const statusIndex = Number(e.currentTarget.dataset.index);
|
||||
const status = STATUSES[statusIndex];
|
||||
if (!status) {
|
||||
return;
|
||||
}
|
||||
const prevIndex = this.data.statusIndex;
|
||||
this.setData({ statusIndex, submitting: true });
|
||||
api.request({
|
||||
url: '/api/v1/checkin',
|
||||
method: 'POST',
|
||||
data: {
|
||||
status,
|
||||
class_date: this.data.classDate,
|
||||
course_type: '会员课程'
|
||||
}
|
||||
}).then((res) => {
|
||||
const record = res.record || null;
|
||||
const statusColor = record ? (STATUS_META[record.status] || '#C67B30') : '';
|
||||
this.setData({ submitting: false, checked: true, record, statusColor, statusBg: statusColor ? statusColor + '1A' : '' });
|
||||
wx.showToast({ title: '打卡成功', icon: 'success' });
|
||||
this.loadGroup();
|
||||
if (this.data.tab === 'personal') {
|
||||
this.loadHistory();
|
||||
}
|
||||
}).catch((err) => {
|
||||
this.setData({ submitting: false, statusIndex: prevIndex });
|
||||
wx.showToast({ title: errMessage(err) || '打卡失败', icon: 'none' });
|
||||
});
|
||||
},
|
||||
|
||||
switchTab(e) {
|
||||
const tab = e.currentTarget.dataset.tab;
|
||||
if (tab !== 'group' && tab !== 'personal') {
|
||||
return;
|
||||
}
|
||||
this.setData({ tab });
|
||||
if (tab === 'personal') {
|
||||
this.loadHistory();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
onRefresh() {
|
||||
this.setData({ refreshing: true });
|
||||
const task = this.data.tab === 'group' ? this.loadWeek() : this.loadHistory();
|
||||
Promise.resolve(task).then(() => {
|
||||
this.setData({ refreshing: false });
|
||||
});
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user