557 lines
17 KiB
JavaScript
557 lines
17 KiB
JavaScript
const { API } = require('../../utils/constants');
|
||
const { request } = require('../../utils/http');
|
||
const { formatDateTime, eventStatusText, eventStatusForPill, eventFormatText } = require('../../utils/format');
|
||
const auth = require('../../utils/auth');
|
||
|
||
/** 统一后台轮播字段(camelCase / PascalCase、枚举数字)供 wxml 绑定 */
|
||
function normalizeBannerItem(raw) {
|
||
if (!raw || typeof raw !== 'object') {
|
||
return { imageUrl: '', linkType: '', eventId: null, linkUrl: '' };
|
||
}
|
||
const imageUrl = raw.imageUrl || raw.ImageUrl || '';
|
||
const linkUrl = String(raw.linkUrl || raw.LinkUrl || '').trim();
|
||
let linkType = raw.linkType != null ? raw.linkType : raw.LinkType;
|
||
const rawEventId = raw.eventId != null ? raw.eventId : raw.EventId;
|
||
const eventId =
|
||
rawEventId != null && rawEventId !== '' ? Number(rawEventId) : null;
|
||
const idOk = Number.isFinite(eventId) && eventId > 0;
|
||
|
||
if (typeof linkType === 'number') {
|
||
if (linkType === 1) linkType = 'Event';
|
||
else if (linkType === 2) linkType = 'Url';
|
||
else if (linkType === 0) linkType = '';
|
||
else linkType = String(linkType);
|
||
} else if (typeof linkType === 'string') {
|
||
const lower = linkType.toLowerCase();
|
||
if (lower === 'event') linkType = 'Event';
|
||
else if (lower === 'url' || lower === 'link' || lower === 'external') linkType = 'Url';
|
||
}
|
||
|
||
if (linkType == null || linkType === '' || linkType === '0') {
|
||
if (idOk) linkType = 'Event';
|
||
else if (linkUrl) linkType = 'Url';
|
||
else linkType = '';
|
||
}
|
||
|
||
return {
|
||
imageUrl,
|
||
linkType,
|
||
eventId: idOk ? eventId : null,
|
||
linkUrl
|
||
};
|
||
}
|
||
|
||
function canCancelByEventStatus(rawEventStatus) {
|
||
// 仅报名中(Enrolling / 1)允许取消
|
||
if (rawEventStatus === 'Enrolling') return true;
|
||
const n = Number(rawEventStatus);
|
||
if (!Number.isNaN(n)) return n === 1;
|
||
const s = rawEventStatus == null ? '' : String(rawEventStatus).toLowerCase();
|
||
return s === 'enrolling' || s === '1';
|
||
}
|
||
|
||
Page({
|
||
data: {
|
||
sectionTab: 'list',
|
||
loggedIn: false,
|
||
|
||
banners: [],
|
||
rows: [],
|
||
loading: false,
|
||
isFirstLoad: false,
|
||
loadingText: '加载中...',
|
||
|
||
pageNo: 1,
|
||
pageSize: 10,
|
||
hasMore: true,
|
||
|
||
/** 列表筛选:-1=全部(不传 status),0~4 与后端 EventStatus 一致;默认报名中 */
|
||
status: 1,
|
||
keyword: '',
|
||
|
||
refresherTriggered: false
|
||
},
|
||
|
||
onLoad() {
|
||
this.fetchBanners();
|
||
this.loadEvents(true);
|
||
},
|
||
|
||
onShow() {
|
||
const loggedIn = !!(wx.getStorageSync('accessToken') || '');
|
||
this.setData({ loggedIn });
|
||
if (this.data.sectionTab === 'registered' && loggedIn) {
|
||
this.loadMyEvents(true);
|
||
}
|
||
},
|
||
|
||
/** 页面 disableScroll 后,下拉刷新由 scroll-view 的 refresher 承担 */
|
||
onRefresherRefresh() {
|
||
this.setData({ refresherTriggered: true });
|
||
this.fetchBanners();
|
||
const p =
|
||
this.data.sectionTab === 'list'
|
||
? this.loadEvents(true)
|
||
: this.loadMyEvents(true);
|
||
p.finally(() => {
|
||
this.setData({ refresherTriggered: false });
|
||
});
|
||
},
|
||
|
||
onPullDownRefresh() {
|
||
this.fetchBanners();
|
||
const p =
|
||
this.data.sectionTab === 'list'
|
||
? this.loadEvents(true)
|
||
: this.loadMyEvents(true);
|
||
p.finally(() => {
|
||
wx.stopPullDownRefresh();
|
||
});
|
||
},
|
||
|
||
fetchBanners() {
|
||
request({
|
||
path: API.banners,
|
||
method: 'GET',
|
||
needAuth: false
|
||
})
|
||
.then((data) => {
|
||
const arr = Array.isArray(data) ? data : [];
|
||
const banners = arr.map((item, index) => ({
|
||
...normalizeBannerItem(item),
|
||
_bannerKey: index
|
||
}));
|
||
this.setData({ banners });
|
||
})
|
||
.catch(() => {
|
||
this.setData({ banners: [] });
|
||
});
|
||
},
|
||
|
||
onSectionTab(e) {
|
||
const tab = e.currentTarget.dataset.tab;
|
||
if (!tab || tab === this.data.sectionTab) return;
|
||
|
||
this.setData({
|
||
sectionTab: tab,
|
||
pageNo: 1,
|
||
rows: [],
|
||
hasMore: true
|
||
});
|
||
|
||
if (tab === 'list') {
|
||
this.loadEvents(true);
|
||
} else {
|
||
this.loadMyEvents(true);
|
||
}
|
||
},
|
||
|
||
onStatusTap(e) {
|
||
const status = Number(e.currentTarget.dataset.status);
|
||
if (Number.isNaN(status)) return;
|
||
this.setData({
|
||
status,
|
||
pageNo: 1,
|
||
rows: [],
|
||
hasMore: true
|
||
});
|
||
this.loadEvents(true);
|
||
},
|
||
|
||
onKeywordInput(e) {
|
||
this.setData({ keyword: e.detail.value || '' });
|
||
},
|
||
|
||
onSearch() {
|
||
if (this.data.sectionTab !== 'list') {
|
||
this.setData({ sectionTab: 'list', pageNo: 1, rows: [], hasMore: true });
|
||
}
|
||
this.setData({
|
||
pageNo: 1,
|
||
rows: [],
|
||
hasMore: true
|
||
});
|
||
this.loadEvents(true);
|
||
},
|
||
|
||
onScrollToLower() {
|
||
if (this.data.loading || !this.data.hasMore) return;
|
||
if (this.data.sectionTab === 'list') {
|
||
const next = this.data.pageNo + 1;
|
||
this.setData({ pageNo: next });
|
||
this.loadEvents(false);
|
||
} else {
|
||
if (!this.data.loggedIn) return;
|
||
const next = this.data.pageNo + 1;
|
||
this.setData({ pageNo: next });
|
||
this.loadMyEvents(false);
|
||
}
|
||
},
|
||
|
||
goLogin() {
|
||
wx.navigateTo({ url: '/subpackages/mine/login/login' });
|
||
},
|
||
|
||
onBannerTap(e) {
|
||
const linkType = e.currentTarget.dataset.linktype;
|
||
const eventId = Number(e.currentTarget.dataset.eventid);
|
||
const linkUrl = e.currentTarget.dataset.linkurl || '';
|
||
|
||
if (linkType === 'Event' && eventId > 0) {
|
||
wx.navigateTo({ url: `/pages/detail/detail?id=${eventId}` });
|
||
return;
|
||
}
|
||
if (linkUrl) {
|
||
wx.showToast({ title: '该轮播链接为外部链接/其他跳转,请在后台配置', icon: 'none' });
|
||
}
|
||
},
|
||
|
||
onEventTap(e) {
|
||
const id = Number(e.currentTarget.dataset.id);
|
||
if (!id) return;
|
||
wx.navigateTo({ url: `/pages/detail/detail?id=${id}` });
|
||
},
|
||
|
||
onCancelRegistrationTap(e) {
|
||
const canCancel = e.currentTarget.dataset.cancancel;
|
||
if (!canCancel) return;
|
||
const registrationId = Number(e.currentTarget.dataset.registrationid);
|
||
if (!registrationId) return;
|
||
wx.navigateTo({
|
||
url: `/subpackages/mine/cancel-registration/cancel-registration?registrationId=${registrationId}`
|
||
});
|
||
},
|
||
|
||
onUploadMaterialTap(e) {
|
||
const registrationId = Number(e.currentTarget.dataset.registrationid);
|
||
if (!registrationId) return;
|
||
|
||
const now = Date.now();
|
||
console.log('时间', e.currentTarget.dataset.matstarttime, e.currentTarget.dataset.matendtime , now);
|
||
|
||
const matStartTime = e.currentTarget.dataset.matstarttime;
|
||
const matEndTime = e.currentTarget.dataset.matendtime;
|
||
const rangeText = e.currentTarget.dataset.materialrangetext || '';
|
||
|
||
if (matStartTime && now < Number(matStartTime)) {
|
||
wx.showToast({
|
||
title: `素材上传未开始,开始时间:${rangeText.split(' ~ ')[0] || rangeText}`,
|
||
icon: 'none',
|
||
duration: 2500
|
||
});
|
||
return;
|
||
}
|
||
if (matEndTime && now > Number(matEndTime)) {
|
||
wx.showToast({
|
||
title: `素材上传已截止,截止时间:${rangeText.split(' ~ ')[1] || rangeText}`,
|
||
icon: 'none',
|
||
duration: 2500
|
||
});
|
||
return;
|
||
}
|
||
|
||
this.openUploadPicker({ kind: 'material', registrationId });
|
||
},
|
||
|
||
onUploadVoucherTap(e) {
|
||
const registrationId = Number(e.currentTarget.dataset.registrationid);
|
||
if (!registrationId) return;
|
||
this.openUploadPicker({ kind: 'voucher', registrationId });
|
||
},
|
||
|
||
openUploadPicker({ kind, registrationId }) {
|
||
const title = kind === 'voucher' ? '上传付款凭证' : '上传素材';
|
||
|
||
if (kind === 'material') {
|
||
wx.showActionSheet({
|
||
itemList: ['从相册选择图片/视频', '拍照/录视频', '选择音乐文件'],
|
||
success: (r) => {
|
||
if (!r || typeof r.tapIndex !== 'number') return;
|
||
if (r.tapIndex === 2) {
|
||
wx.chooseMessageFile({
|
||
count: 1,
|
||
type: 'file',
|
||
extension: ['mp3', 'wav', 'aac', 'flac', 'm4a', 'ogg'],
|
||
success: (res) => {
|
||
const file = res && res.tempFiles && res.tempFiles[0];
|
||
const tempFilePath = file ? file.path : '';
|
||
if (!tempFilePath) return;
|
||
this._confirmAndUploadMaterial(title, tempFilePath, registrationId);
|
||
}
|
||
});
|
||
} else {
|
||
const sourceType = r.tapIndex === 1 ? ['camera'] : ['album'];
|
||
wx.chooseMedia({
|
||
count: 1,
|
||
mediaType: ['image', 'video'],
|
||
sourceType,
|
||
success: (res) => {
|
||
const tempFilePath =
|
||
res && res.tempFiles && res.tempFiles[0] ? res.tempFiles[0].tempFilePath : '';
|
||
if (!tempFilePath) return;
|
||
this._confirmAndUploadMaterial(title, tempFilePath, registrationId);
|
||
}
|
||
});
|
||
}
|
||
}
|
||
});
|
||
} else {
|
||
wx.showActionSheet({
|
||
itemList: ['从相册选择', '拍照'],
|
||
success: (r) => {
|
||
if (!r || typeof r.tapIndex !== 'number') return;
|
||
const sourceType = r.tapIndex === 1 ? ['camera'] : ['album'];
|
||
wx.chooseMedia({
|
||
count: 1,
|
||
mediaType: ['image'],
|
||
sourceType,
|
||
success: (res) => {
|
||
const tempFilePath =
|
||
res && res.tempFiles && res.tempFiles[0] ? res.tempFiles[0].tempFilePath : '';
|
||
if (!tempFilePath) return;
|
||
wx.showModal({
|
||
title,
|
||
content: '确认上传该图片?',
|
||
cancelText: '取消',
|
||
confirmText: '确定',
|
||
success: (mr) => {
|
||
if (!mr || !mr.confirm) return;
|
||
// TODO: 接入付款凭证上传接口
|
||
wx.showToast({ title: '已选择', icon: 'success' });
|
||
}
|
||
});
|
||
}
|
||
});
|
||
}
|
||
});
|
||
}
|
||
},
|
||
|
||
_confirmAndUploadMaterial(title, tempFilePath, registrationId) {
|
||
wx.showModal({
|
||
title,
|
||
content: '确认上传该文件?',
|
||
cancelText: '取消',
|
||
confirmText: '确定',
|
||
success: (mr) => {
|
||
console.log('用户选择:', mr);
|
||
if (!mr || !mr.confirm) return;
|
||
wx.showLoading({ title: '上传中...', mask: true });
|
||
auth.uploadFile(tempFilePath)
|
||
.then((url) => {
|
||
return request({
|
||
path: API.uploadMaterial,
|
||
method: 'POST',
|
||
needAuth: true,
|
||
data: { registrationId, materialUrl: url }
|
||
});
|
||
})
|
||
.then(() => {
|
||
wx.showToast({ title: '上传成功', icon: 'success' });
|
||
})
|
||
.catch((err) => {
|
||
wx.showToast({ title: (err && err.message) || '上传失败', icon: 'none' });
|
||
});
|
||
}
|
||
});
|
||
},
|
||
|
||
loadEvents(reset) {
|
||
if (this.data.loading) return Promise.resolve();
|
||
|
||
if (reset) {
|
||
this.setData({
|
||
rows: [],
|
||
pageNo: 1,
|
||
hasMore: true
|
||
});
|
||
}
|
||
|
||
this.setData({ loading: true, isFirstLoad: !!reset });
|
||
const pageNo = reset ? 1 : this.data.pageNo;
|
||
const pageSize = this.data.pageSize;
|
||
const status = this.data.status;
|
||
const keyword = this.data.keyword;
|
||
|
||
const query = {
|
||
page: pageNo,
|
||
pagesize: pageSize,
|
||
PageNo: pageNo,
|
||
PageSize: pageSize,
|
||
keyword,
|
||
Keyword: keyword
|
||
};
|
||
if (status >= 0) {
|
||
query.status = status;
|
||
query.Status = status;
|
||
}
|
||
|
||
return request({
|
||
path: API.eventList,
|
||
method: 'GET',
|
||
needAuth: false,
|
||
data: query
|
||
})
|
||
.then((res) => {
|
||
const rows = (res && Array.isArray(res.rows) ? res.rows : []).map((item) => {
|
||
const id = item.id;
|
||
const rawEventStatus =
|
||
item.eventStatus != null
|
||
? item.eventStatus
|
||
: item.EventStatus != null
|
||
? item.EventStatus
|
||
: item.status != null
|
||
? item.status
|
||
: item.Status;
|
||
return {
|
||
...item,
|
||
rowKey: `e-${id}`,
|
||
registrationStartText: formatDateTime(item.registrationStartTime),
|
||
registrationEndText: formatDateTime(item.registrationEndTime),
|
||
matchStartText: formatDateTime(item.matchStartTime),
|
||
matchEndText: formatDateTime(item.matchEndTime),
|
||
eventStatusText: eventStatusText(rawEventStatus),
|
||
eventStatusPill: eventStatusForPill(rawEventStatus),
|
||
eventFormatText: eventFormatText(item.eventType || item.eventFormat)
|
||
};
|
||
});
|
||
|
||
const nextRows = reset ? rows : this.data.rows.concat(rows);
|
||
|
||
const pages = res && typeof res.pages === 'number' ? res.pages : 1;
|
||
const hasMore = pageNo < pages && rows.length > 0;
|
||
|
||
this.setData({
|
||
rows: nextRows,
|
||
hasMore,
|
||
loading: false,
|
||
isFirstLoad: false,
|
||
loadingText: hasMore ? '加载中...' : '没有更多了'
|
||
});
|
||
})
|
||
.catch((err) => {
|
||
this.setData({
|
||
loading: false,
|
||
isFirstLoad: false,
|
||
hasMore: false,
|
||
rows: reset ? [] : this.data.rows,
|
||
loadingText: err && err.message ? err.message : '加载失败'
|
||
});
|
||
});
|
||
},
|
||
|
||
loadMyEvents(reset) {
|
||
if (!this.data.loggedIn) {
|
||
this.setData({ rows: [], loading: false });
|
||
return Promise.resolve();
|
||
}
|
||
|
||
if (this.data.loading) return Promise.resolve();
|
||
|
||
if (reset) {
|
||
this.setData({
|
||
rows: [],
|
||
pageNo: 1,
|
||
hasMore: true
|
||
});
|
||
}
|
||
|
||
this.setData({ loading: true, isFirstLoad: !!reset });
|
||
const pageNo = reset ? 1 : this.data.pageNo;
|
||
const pageSize = this.data.pageSize;
|
||
|
||
return request({
|
||
path: API.eventMyList,
|
||
method: 'GET',
|
||
needAuth: true,
|
||
data: {
|
||
page: pageNo,
|
||
pagesize: pageSize,
|
||
PageNo: pageNo,
|
||
PageSize: pageSize
|
||
}
|
||
})
|
||
.then((res) => {
|
||
const rows = (res && Array.isArray(res.rows) ? res.rows : []).map((item) => {
|
||
const eid = item.eventId;
|
||
const rid = item.registrationId;
|
||
const rawEventStatus =
|
||
item.eventStatus != null
|
||
? item.eventStatus
|
||
: item.EventStatus != null
|
||
? item.EventStatus
|
||
: item.status != null
|
||
? item.status
|
||
: item.Status;
|
||
const eventStatusPill = eventStatusForPill(rawEventStatus);
|
||
const matStart =
|
||
item.materialUploadStartTime ||
|
||
item.MaterialUploadStartTime ||
|
||
item.uploadMaterialStartTime ||
|
||
item.UploadMaterialStartTime;
|
||
const matEnd =
|
||
item.materialUploadEndTime ||
|
||
item.MaterialUploadEndTime ||
|
||
item.uploadMaterialEndTime ||
|
||
item.UploadMaterialEndTime;
|
||
const matDeadlineText =
|
||
item.materialUploadDeadlineText || item.MaterialUploadDeadlineText || '';
|
||
const matStartFmt = formatDateTime(matStart);
|
||
const matEndFmt = formatDateTime(matEnd);
|
||
let materialRangeText = matDeadlineText;
|
||
if (!materialRangeText) {
|
||
if (matStartFmt && matStartFmt !== '-' && matEndFmt && matEndFmt !== '-') {
|
||
materialRangeText = `${matStartFmt} ~ ${matEndFmt}`;
|
||
} else if (matStartFmt && matStartFmt !== '-') {
|
||
materialRangeText = matStartFmt;
|
||
} else if (matEndFmt && matEndFmt !== '-') {
|
||
materialRangeText = matEndFmt;
|
||
}
|
||
}
|
||
|
||
return {
|
||
id: eid,
|
||
rowKey: `m-${rid}`,
|
||
registrationId: rid,
|
||
eventName: item.eventName,
|
||
coverImage: item.coverImage,
|
||
address: '',
|
||
isNeedMaterial: !!item.isNeedMaterial,
|
||
materialRangeText,
|
||
matStartTime: matStart ? new Date(matStart).getTime() : null,
|
||
matEndTime: matEnd ? new Date(matEnd).getTime() : null,
|
||
eventStatusPill,
|
||
eventStatusText: eventStatusText(rawEventStatus) || '已报名',
|
||
registrationTimeText: formatDateTime(item.registrationTime),
|
||
projectCount: item.projectCount,
|
||
eventFormatText: '',
|
||
paymentStatus: item.paymentStatus != null ? Number(item.paymentStatus) : null,
|
||
canCancel: canCancelByEventStatus(rawEventStatus)
|
||
};
|
||
});
|
||
|
||
const nextRows = reset ? rows : this.data.rows.concat(rows);
|
||
|
||
const pages = res && typeof res.pages === 'number' ? res.pages : 1;
|
||
const hasMore = pageNo < pages && rows.length > 0;
|
||
|
||
this.setData({
|
||
rows: nextRows,
|
||
hasMore,
|
||
loading: false,
|
||
isFirstLoad: false,
|
||
loadingText: hasMore ? '加载中...' : '没有更多了'
|
||
});
|
||
})
|
||
.catch(() => {
|
||
this.setData({
|
||
loading: false,
|
||
isFirstLoad: false,
|
||
hasMore: false,
|
||
rows: reset ? [] : this.data.rows,
|
||
loadingText: '加载失败'
|
||
});
|
||
});
|
||
}
|
||
});
|