提示:本篇文章为学校项目实训的记录,所以可能会写的没头没尾的,不具有实际指导意义,因为是小组共同开发,所以不是自己负责的部分会在别的小组成员博客里。
前言
上次说到完成了发布打卡页面,现在进入下一个主题,活动页面。
一、活动主页
活动主页主要是以卡片的形式展示,卡片展示了活动主题和时效,点击后会进入活动详情页,详情页可参与,可打卡活动。
二、效果详述
1.我的活动主页详述
效果图如下
前端template代码如下:
<template>
<view class="container">
<view class="card" v-for="(item, index) in cards" :key="index">
<image :src="item.picture" class="card-image"></image>
<view class="card-content">
<text class="card-title">{{ item.name }}</text>
<view :class="['card-button', getButtonClass(item.check)]" @tap="handleButtonClick(item)">
<text class="button-text">{{ getButtonText(item.check) }}</text>
</view>
</view>
</view>
</view>
</template>
script代码如下,主要处理查询后返回的活动列表及其check值的不同情况。当活动check值为0(不在活动时间)和3(已完成)时,按钮没有跳转详情页面。
fetchActivities() {
console.log('调用到页面初始化方法')
const data = {
userId: this.userId,
status: null,
activityName: "",
startTime: "",
endTime: "",
orderBy: "participants_count",
order: "desc"
};
// 假设 ajax 方法已经定义并可用
this.ajax(this.api.searchMyActivities, 'POST', data, (resp) => {
console.log(resp)
if (resp.data.code === 200) {
this.cards = resp.data.result;
} else {
uni.showToast({
icon: 'error',
title: resp.msg || '加载失败'
});
}
});
},
getButtonText(check) {
switch (check) {
case 0:
return '不在活动时间';
case 1:
return '去参与';
case 2:
return '去打卡';
case 3:
return '已完成';
default:
return '';
}
},
getButtonClass(check) {
return {
'disabled': check === 0,
'participate': check === 1,
'check-in': check === 2,
'completed': check === 3
};
},
handleButtonClick(item) {
if (item.check === 0) {
uni.showToast({
icon: 'none',
title: '活动未开始或已结束'
});
return;
} else if (item.check === 1) {
uni.setStorageSync('activityId', item.id)
// 跳转到参与页面的逻辑
uni.navigateTo({
url: '/user/activity_check/activity_check'
});
} else if (item.check === 2) {
uni.setStorageSync('activityId', item.id)
// 跳转到打卡页面的逻辑
uni.navigateTo({
url: '/user/activity_check/activity_check'
});
} else if (item.check === 3) {
uni.showToast({
icon: 'none',
title: '活动已完成'
});
}
}
},
onShow() {
this.fetchActivities();
// 监听自定义事件
this.$bus.$on('refreshActivity', this.fetchActivities);
},
onUnload() {
// 组件销毁时,移除事件监听
this.$bus.$off('refreshActivity', this.fetchActivities);
},
2.活动详情页详述
当活动可以参与或打卡时,点击按钮进入活动详情页面。点击去打卡后会跳转到打卡发布页面。效果图如下:
活动详情页的template代码如下:
<template>
<view class="container">
<view class="card" v-if="activity">
<image :src="activity.picture" class="card-image"></image>
<view class="card-content">
<u-row>
<text class="card-title">{{ activity.name }}</text>
</u-row>
<u-row>
<text class="card-description">活动概述: {{ activity.description }}</text>
</u-row>
<u-row>
<text class="card-requirements">详细要求: {{ activity.requirements }}</text>
</u-row>
<u-row>
<text class="card-reward">活动奖励: {{ activity.reward }}</text>
</u-row>
<u-row>
<text class="card-participants">可参与人数: {{ activity.participants_count }}</text>
</u-row>
<u-row>
<text class="card-participants">要求打卡天数: {{ activity.count_day }}</text>
</u-row>
<u-row>
<text class="card-time">活动时间: {{ activity.start_time }} - {{ activity.end_time }}</text>
</u-row>
<u-row>
<view class="card-button" @tap="handleButtonClick(activity)">
<text class="button-text">{{ getButtonText(activity.check) }}</text>
</view>
<u-col span="5">
</u-col>
<text v-if="activity.check === 2 && checkInCount !== null" class="check-in-count">已打卡{{ checkInCount }}天</text>
</u-row>
</view>
</view>
<!-- 确认参与弹窗 -->
<u-popup :show="showConfirmPopup" mode="center" :round="10" @close="hideConfirmPopup">
<view class="confirm-popup">
<text class="popup-header">确认参与活动?</text>
<view class="button-container">
<u-button type="primary" @click="confirmParticipation">确认</u-button>
<u-button type="default" @click="hideConfirmPopup">取消</u-button>
</view>
</view>
</u-popup>
</view>
</template>
页面跳转时只传递活动id,到达新页面会重新查询活动,选择id对应的活动进行卡片展示。
fetchActivity() {
const data = {
userId: this.userId,
status: null,
activityName: "",
startTime: "",
endTime: "",
orderBy: "participants_count",
order: "desc"
};
// 假设 ajax 方法已经定义并可用
this.ajax(this.api.searchMyActivities, 'POST', data, (resp) => {
console.log('活动详细信息返回',resp)
if (resp.data.code === 200) {
const activityId = uni.getStorageSync('activityId');
this.activity = resp.data.result.find(activity => activity.id === activityId);
if (this.activity.check === 2) {
this.fetchCheckInCount();
}
} else {
uni.showToast({
icon: 'error',
title: resp.msg || '加载失败'
});
}
});
},
fetchCheckInCount() {
const data = {
userId: this.userId,
activityId: uni.getStorageSync('activityId')
};
console.log('请求数据',data)
this.ajax(this.api.countMyActivityCheckIn, 'POST', data, (resp) => {
console.log('打卡天数',resp)
if (resp.data.code === 200) {
this.checkInCount = resp.data.result;
} else {
uni.showToast({
icon: 'none',
title: '获取打卡天数失败'
});
}
});
},
getButtonText(check) {
switch (check) {
case 1:
return '去参与';
case 2:
return '去打卡';
case 3:
return '已完成';
default:
return '';
}
},
handleButtonClick(activity) {
if (activity.check === 1) {
this.selectedActivityId = activity.id;
this.showConfirmPopup = true;
} else if (activity.check === 2) {
uni.navigateTo({
url: '/user/everyday_activity_check/everyday_activity_check'
});
} else if (activity.check === 3) {
uni.showToast({
icon: 'none',
title: '活动已完成'
});
}
},
confirmParticipation() {
const data = {
userId: this.userId,
activityId: this.selectedActivityId
};
this.ajax(this.api.participatingActivity, 'POST', data, (resp) => {
if (resp.data.code === 200) {
uni.showToast({
icon: 'success',
title: '参与成功'
});
this.showConfirmPopup = false;
// 更新活动状态或刷新活动信息
this.fetchActivity();
this.$bus.$emit('refreshActivity');
} else {
uni.showToast({
icon: 'error',
title: resp.data.msg || '参与失败'
});
}
});
},
hideConfirmPopup() {
this.showConfirmPopup = false;
}
3.发布活动打卡页面
总体来说,发布活动打卡页面复用了日常打卡页面的部分代码。但是在图片分析部分有改动。效果图如下:
不同之处如下:
checkActivity(uploadedUrls, callback) {
uni.showLoading({
title: '正在验证图片...'
});
uni.request({
url: 'https://u404380-b1e7-5555557b.westc.gpuhub.com:8443/check_activity',
method: 'POST',
data: {
activity_id: uni.getStorageSync('activityId'),
image_url: uploadedUrls[0]
},
success: (res) => {
console.log('图片验证请求',res)
if (res.data.result === "true") {
uni.showToast({
icon: 'none',
title: '图片验证通过'
});
callback(true);
} else {
callback(false);
}
},
fail: () => {
uni.showToast({
icon: 'none',
title: '图片验证请求失败'
});
callback(false);
}
});
},
同样的,也包含事件的监听,在活动详情页面中
onShow() {
this.fetchActivity();
// 监听自定义事件
this.$bus.$on('refreshActivityCheck', this.fetchActivity);
},
onUnload() {
// 组件销毁时,移除事件监听
this.$bus.$off('refreshActivityCheck', this.fetchActivity);
},
总结
这次开发主要使用了卡片组件,复用了之前的一些代码,也用到了事件的监听。