feat(activity): 新增活动报名及我的报名功能
11
pages.json
|
|
@ -659,6 +659,17 @@
|
||||||
"group": "物业管理"
|
"group": "物业管理"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "activity/my-registration",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "我的报名"
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"sync": true,
|
||||||
|
"title": "我的报名",
|
||||||
|
"group": "物业管理"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "staff/index",
|
"path": "staff/index",
|
||||||
"style": {
|
"style": {
|
||||||
|
|
|
||||||
|
|
@ -77,23 +77,28 @@
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 活动卡片 -->
|
<!-- 活动卡片列表 -->
|
||||||
<view class="activity-card" @tap="goActivityDetail">
|
<view
|
||||||
<image class="activity-cover" src="/static/img/guest.png" mode="aspectFill"></image>
|
class="activity-card"
|
||||||
|
v-for="(item, index) in activityList"
|
||||||
|
:key="index"
|
||||||
|
@tap="goActivityDetail(item)"
|
||||||
|
>
|
||||||
|
<image class="activity-cover" :src="item.cover" mode="aspectFill"></image>
|
||||||
<view class="activity-info">
|
<view class="activity-info">
|
||||||
<view class="activity-location">
|
<view class="activity-location">
|
||||||
<view class="location-tag">
|
<view class="location-tag">
|
||||||
<image class="location-img" src="/static/img/me-icon7.png" mode="aspectFit" />
|
<image class="location-img" src="/static/img/me-icon7.png" mode="aspectFit" />
|
||||||
</view>
|
</view>
|
||||||
<text class="location-text">福清市音西街道融侨馨苑1号楼下</text>
|
<text class="location-text">{{ item.location }}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="activity-date">
|
<view class="activity-date">
|
||||||
<text class="date-label">报名日期:</text>
|
<text class="date-label">报名日期:</text>
|
||||||
<text class="date-value">2025/06/30-2025/07/01</text>
|
<text class="date-value">{{ item.registerDate }}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="activity-date">
|
<view class="activity-date">
|
||||||
<text class="date-label">活动日期:</text>
|
<text class="date-label">活动日期:</text>
|
||||||
<text class="date-value">2025/07/05 12:00-2025/07/05 18:00</text>
|
<text class="date-value">{{ item.dateRange }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
@ -106,6 +111,7 @@ import { ref, onMounted, computed } from 'vue';
|
||||||
import { onLoad, onShow } from '@dcloudio/uni-app';
|
import { onLoad, onShow } from '@dcloudio/uni-app';
|
||||||
import MemberHouseApi from '@/sheep/api/community/memberHouse';
|
import MemberHouseApi from '@/sheep/api/community/memberHouse';
|
||||||
import NoticeApi from '@/sheep/api/community/notice';
|
import NoticeApi from '@/sheep/api/community/notice';
|
||||||
|
import ActivityApi from '@/sheep/api/community/activity';
|
||||||
import sheep from '@/sheep';
|
import sheep from '@/sheep';
|
||||||
|
|
||||||
// 状态栏高度
|
// 状态栏高度
|
||||||
|
|
@ -122,7 +128,7 @@ const selectedCommunityName = ref('');
|
||||||
|
|
||||||
// 当前小区名称
|
// 当前小区名称
|
||||||
const communityName = computed(() => {
|
const communityName = computed(() => {
|
||||||
return selectedCommunityName.value || userInfo.value.currentCommunityName || '请选择小区';
|
return userInfo.value.currentCommunityName || selectedCommunityName.value || '请选择小区';
|
||||||
});
|
});
|
||||||
|
|
||||||
// 是否已完成房屋认证(根据 currentHouseId 判断)
|
// 是否已完成房屋认证(根据 currentHouseId 判断)
|
||||||
|
|
@ -143,11 +149,16 @@ const houseAddress = computed(() => {
|
||||||
// 通知数据
|
// 通知数据
|
||||||
const noticeTitle = ref('');
|
const noticeTitle = ref('');
|
||||||
|
|
||||||
|
// 活动列表数据(首页只展示2条)
|
||||||
|
const activityList = ref([]);
|
||||||
|
|
||||||
// 查询最新通知
|
// 查询最新通知
|
||||||
const fetchNotice = async () => {
|
const fetchNotice = async () => {
|
||||||
const { code, data } = await NoticeApi.getPage({ pageNo: 1, pageSize: 1 });
|
const { code, data } = await NoticeApi.getPage({ pageNo: 1, pageSize: 1 });
|
||||||
if (code === 0 && data && data.list && data.list.length > 0) {
|
if (code === 0 && data && data.list && data.list.length > 0) {
|
||||||
noticeTitle.value = data.list[0].title;
|
noticeTitle.value = data.list[0].title;
|
||||||
|
}else{
|
||||||
|
noticeTitle.value = '';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -165,6 +176,8 @@ const fetchBannerList = async () => {
|
||||||
icon: item.picUrl,
|
icon: item.picUrl,
|
||||||
url: item.url,
|
url: item.url,
|
||||||
}));
|
}));
|
||||||
|
} else {
|
||||||
|
bannerList.value = [];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -208,6 +221,28 @@ const fetchFunctionList = async () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 查询活动列表(首页只取2条)
|
||||||
|
const fetchActivityList = async () => {
|
||||||
|
const { code, data } = await ActivityApi.getPage({
|
||||||
|
pageNo: 1,
|
||||||
|
pageSize: 2,
|
||||||
|
});
|
||||||
|
if (code === 0 && data) {
|
||||||
|
activityList.value = (data.list || []).map((item) => ({
|
||||||
|
id: item.id,
|
||||||
|
title: item.title || '',
|
||||||
|
cover: item.coverImage || '/static/img/guest.png',
|
||||||
|
location: item.location || '',
|
||||||
|
registerDate: item.registrationStartTime && item.registrationEndTime
|
||||||
|
? `${sheep.$helper.timeFormat(item.registrationStartTime, 'yyyy/mm/dd')} - ${sheep.$helper.timeFormat(item.registrationEndTime, 'yyyy/mm/dd')}`
|
||||||
|
: '',
|
||||||
|
dateRange: item.activityStartTime && item.activityEndTime
|
||||||
|
? `${sheep.$helper.timeFormat(item.activityStartTime, 'yyyy/mm/dd hh:MM')} - ${sheep.$helper.timeFormat(item.activityEndTime, 'yyyy/mm/dd hh:MM')}`
|
||||||
|
: '',
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
onLoad(() => {
|
onLoad(() => {
|
||||||
// 获取状态栏高度
|
// 获取状态栏高度
|
||||||
const systemInfo = uni.getSystemInfoSync();
|
const systemInfo = uni.getSystemInfoSync();
|
||||||
|
|
@ -220,6 +255,8 @@ onLoad(() => {
|
||||||
fetchBannerList();
|
fetchBannerList();
|
||||||
// 加载功能入口
|
// 加载功能入口
|
||||||
fetchFunctionList();
|
fetchFunctionList();
|
||||||
|
// 加载活动列表(只取2条)
|
||||||
|
fetchActivityList();
|
||||||
});
|
});
|
||||||
|
|
||||||
onShow(() => {
|
onShow(() => {
|
||||||
|
|
@ -227,6 +264,11 @@ onShow(() => {
|
||||||
if (userStore.isLogin) {
|
if (userStore.isLogin) {
|
||||||
userStore.getInfo();
|
userStore.getInfo();
|
||||||
}
|
}
|
||||||
|
// 重新加载所有数据(切换房屋后 tenant-id 已变更)
|
||||||
|
fetchNotice();
|
||||||
|
fetchBannerList();
|
||||||
|
fetchFunctionList();
|
||||||
|
fetchActivityList();
|
||||||
});
|
});
|
||||||
|
|
||||||
// 获取小区房屋树
|
// 获取小区房屋树
|
||||||
|
|
@ -269,8 +311,22 @@ const showCommunityPicker = () => {
|
||||||
communityId: selectedCommunity.communityId,
|
communityId: selectedCommunity.communityId,
|
||||||
});
|
});
|
||||||
if (switchRes.code === 0) {
|
if (switchRes.code === 0) {
|
||||||
// 切换成功后刷新用户信息
|
const resData = switchRes.data || {};
|
||||||
|
// 刷新 token / 用户信息
|
||||||
|
if (resData.needRelogin) {
|
||||||
|
await userStore.setToken(resData.accessToken, resData.refreshToken);
|
||||||
|
} else {
|
||||||
await userStore.getInfo();
|
await userStore.getInfo();
|
||||||
|
}
|
||||||
|
// 刷新请求头 tenant-id
|
||||||
|
if (resData.communityId) {
|
||||||
|
uni.setStorageSync('tenant-id', String(resData.communityId));
|
||||||
|
}
|
||||||
|
// 重新加载首页数据
|
||||||
|
fetchNotice();
|
||||||
|
fetchBannerList();
|
||||||
|
fetchFunctionList();
|
||||||
|
fetchActivityList();
|
||||||
uni.showToast({ title: '切换成功', icon: 'success' });
|
uni.showToast({ title: '切换成功', icon: 'success' });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -326,8 +382,8 @@ const goActivityList = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
// 活动详情
|
// 活动详情
|
||||||
const goActivityDetail = () => {
|
const goActivityDetail = (item) => {
|
||||||
uni.navigateTo({ url: '/pages/sub/activity/detail?id=1' });
|
uni.navigateTo({ url: `/pages/sub/activity/detail?id=${item.id}` });
|
||||||
};
|
};
|
||||||
|
|
||||||
// Banner点击跳转
|
// Banner点击跳转
|
||||||
|
|
|
||||||
|
|
@ -136,6 +136,11 @@ const selectHouse = async (item) => {
|
||||||
await sheep.$store('user').getInfo();
|
await sheep.$store('user').getInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 刷新请求头中的 tenant-id
|
||||||
|
if (resData.communityId) {
|
||||||
|
uni.setStorageSync('tenant-id', String(resData.communityId));
|
||||||
|
}
|
||||||
|
|
||||||
uni.showToast({ title: '已切换至 ' + item.name, icon: 'none' });
|
uni.showToast({ title: '已切换至 ' + item.name, icon: 'none' });
|
||||||
|
|
||||||
// 回到首页重新加载数据
|
// 回到首页重新加载数据
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,7 @@ const updateUserInfo = () => {
|
||||||
avatar: user.avatar || '/static/img/login_img.png',
|
avatar: user.avatar || '/static/img/login_img.png',
|
||||||
nickname: user.nickname || '未登录',
|
nickname: user.nickname || '未登录',
|
||||||
mobile: user.mobile || '',
|
mobile: user.mobile || '',
|
||||||
communityAddress: user.communityAddress || '未设置地址'
|
communityAddress: user.currentCommunityName || '未设置地址'
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,9 +37,9 @@
|
||||||
|
|
||||||
<!-- 地址 -->
|
<!-- 地址 -->
|
||||||
<view class="info-row location-row">
|
<view class="info-row location-row">
|
||||||
<text class="sicon-location"></text>
|
<image class="row-icon" src="/static/img/dw.png" mode="aspectFit" />
|
||||||
<text class="location-text">{{ activityInfo.location }}</text>
|
<text class="location-text">{{ activityInfo.location }}</text>
|
||||||
<text class="sicon-right navigation-icon" @tap="openNavigation"></text>
|
<image class="row-icon navigation-icon" src="/static/img/dh.png" mode="aspectFit" @tap="openNavigation" />
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 服务类别 -->
|
<!-- 服务类别 -->
|
||||||
|
|
@ -80,14 +80,14 @@
|
||||||
|
|
||||||
<!-- 人数上限 -->
|
<!-- 人数上限 -->
|
||||||
<view class="info-row text-row">
|
<view class="info-row text-row">
|
||||||
<text class="sicon-person"></text>
|
<image class="row-icon" src="/static/img/people.png" mode="aspectFit" />
|
||||||
<text class="label-text">人数上限:</text>
|
<text class="label-text">人数上限:</text>
|
||||||
<text class="value-text">{{ activityInfo.maxPeople }}人</text>
|
<text class="value-text">{{ activityInfo.maxPeople }}人</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 联系人 -->
|
<!-- 联系人 -->
|
||||||
<view class="info-row contact-row" @tap="callPhone">
|
<view class="info-row contact-row" @tap="callPhone">
|
||||||
<text class="sicon-phone"></text>
|
<image class="row-icon" src="/static/img/phone.png" mode="aspectFit" />
|
||||||
<text class="contact-name">{{ activityInfo.contactName }}</text>
|
<text class="contact-name">{{ activityInfo.contactName }}</text>
|
||||||
<text class="contact-phone">{{ activityInfo.contactPhone }}</text>
|
<text class="contact-phone">{{ activityInfo.contactPhone }}</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
@ -105,14 +105,26 @@
|
||||||
</view>
|
</view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
|
|
||||||
<!-- 底部固定按钮栏 -->
|
<!-- 底部按钮栏 -->
|
||||||
<view class="bottom-bar">
|
<view class="bottom-bar">
|
||||||
<view class="registered-btn" @tap="showRegisteredList">
|
<!-- 未报名:左侧立即报名,右侧返回 -->
|
||||||
<text class="registered-text">已有{{ activityInfo.registeredCount }}人报名</text>
|
<template v-if="!activityInfo.hasRegistered">
|
||||||
|
<view class="register-btn" @tap="handleRegister">
|
||||||
|
<text class="register-text">立即报名</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="back-btn" @tap="goBack">
|
<view class="back-btn" @tap="goBack">
|
||||||
<text class="back-text">返回</text>
|
<text class="back-text">返回</text>
|
||||||
</view>
|
</view>
|
||||||
|
</template>
|
||||||
|
<!-- 已报名:左侧显示人数,右侧取消报名 -->
|
||||||
|
<template v-else>
|
||||||
|
<view class="registered-btn" @tap="goBack">
|
||||||
|
<text class="registered-text">已有{{ activityInfo.registeredCount }}人报名</text>
|
||||||
|
</view>
|
||||||
|
<view class="cancel-btn" @tap="handleCancelRegister">
|
||||||
|
<text class="cancel-text">取消报名</text>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</s-layout>
|
</s-layout>
|
||||||
|
|
@ -121,6 +133,8 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { onLoad } from '@dcloudio/uni-app';
|
import { onLoad } from '@dcloudio/uni-app';
|
||||||
|
import ActivityApi from '@/sheep/api/community/activity';
|
||||||
|
import sheep from '@/sheep';
|
||||||
|
|
||||||
// 当前Tab
|
// 当前Tab
|
||||||
const currentTab = ref('basic');
|
const currentTab = ref('basic');
|
||||||
|
|
@ -139,7 +153,8 @@ const activityInfo = ref({
|
||||||
contactName: '',
|
contactName: '',
|
||||||
contactPhone: '',
|
contactPhone: '',
|
||||||
registeredCount: 0,
|
registeredCount: 0,
|
||||||
introduction: ''
|
hasRegistered: false,
|
||||||
|
introduction: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
// 页面加载
|
// 页面加载
|
||||||
|
|
@ -149,50 +164,113 @@ onLoad((options) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 安全解析 JSON 字符串
|
||||||
|
function safeJsonParse(str, defaultVal = []) {
|
||||||
|
if (!str) return defaultVal;
|
||||||
|
try {
|
||||||
|
return JSON.parse(str);
|
||||||
|
} catch (e) {
|
||||||
|
return defaultVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 服务类别映射
|
||||||
|
const serviceCategoryMap = {
|
||||||
|
1: '社区服务',
|
||||||
|
2: '敬老服务',
|
||||||
|
3: '助残服务',
|
||||||
|
4: '关爱儿童',
|
||||||
|
5: '环保宣传',
|
||||||
|
6: '文明礼仪',
|
||||||
|
7: '文化教育',
|
||||||
|
};
|
||||||
|
|
||||||
|
// 服务对象映射
|
||||||
|
const serviceTargetMap = {
|
||||||
|
1: '儿童',
|
||||||
|
2: '孤寡老人',
|
||||||
|
3: '残障人士',
|
||||||
|
4: '优抚对象',
|
||||||
|
5: '其他',
|
||||||
|
};
|
||||||
|
|
||||||
// 加载活动详情
|
// 加载活动详情
|
||||||
async function loadActivityDetail(id) {
|
async function loadActivityDetail(id) {
|
||||||
// TODO: 调用API获取活动详情
|
const { code, data } = await ActivityApi.getDetail(id);
|
||||||
// 模拟数据
|
if (code === 0 && data) {
|
||||||
activityInfo.value = {
|
activityInfo.value = {
|
||||||
id: id,
|
id: data.id,
|
||||||
title: 'xxxxxxxxxxxxxxxxx活动',
|
title: data.title || '',
|
||||||
banners: [
|
banners: safeJsonParse(data.bannerImages, [data.coverImage]).filter(Boolean),
|
||||||
'/static/img/guest.png',
|
location: data.location || '',
|
||||||
'/static/img/login_img.png'
|
serviceTypes: (data.serviceCategories || []).map((id) => serviceCategoryMap[id] || id),
|
||||||
],
|
targetAudience: (data.serviceTargets|| []).map((id) => serviceTargetMap[id] || id),
|
||||||
location: '福清市音西街道',
|
registerDate: data.registrationStartTime && data.registrationEndTime
|
||||||
serviceTypes: ['社区服务', '敬老服务', '助残服务', '关爱儿童'],
|
? `${sheep.$helper.timeFormat(data.registrationStartTime, 'yyyy/mm/dd')} - ${sheep.$helper.timeFormat(data.registrationEndTime, 'yyyy/mm/dd')}`
|
||||||
targetAudience: ['儿童', '孤寡老人', '残障人士', '优抚对象'],
|
: '',
|
||||||
registerDate: '2025/06/30-2025/07/01',
|
activityDate: data.activityStartTime && data.activityEndTime
|
||||||
activityDate: '2025/07/05 12:00-2025/07/05 18:00',
|
? `${sheep.$helper.timeFormat(data.activityStartTime, 'yyyy/mm/dd hh:MM')} - ${sheep.$helper.timeFormat(data.activityEndTime, 'yyyy/mm/dd hh:MM')}`
|
||||||
maxPeople: 100,
|
: '',
|
||||||
contactName: '王德福',
|
maxPeople: data.maxParticipants || 0,
|
||||||
contactPhone: '13322471131',
|
contactName: data.contactPerson || '',
|
||||||
registeredCount: 37,
|
contactPhone: data.contactPhone || '',
|
||||||
introduction: `<p>本次活动旨在丰富社区居民文化生活,增进邻里关系,共建和谐社区。</p><p>欢迎各位居民踊跃参与!</p>`
|
registeredCount: data.currentParticipants || 0,
|
||||||
|
hasRegistered: data.hasRegistered || false,
|
||||||
|
introduction: data.content || '',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 打开导航
|
// 打开导航
|
||||||
function openNavigation() {
|
function openNavigation() {
|
||||||
// TODO: 调用地图导航
|
if (!activityInfo.value.location) return;
|
||||||
|
uni.openLocation({
|
||||||
|
address: activityInfo.value.location,
|
||||||
|
success: () => console.log('打开导航成功'),
|
||||||
|
fail: () => uni.showToast({ title: '无法打开导航', icon: 'none' }),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 拨打电话
|
// 拨打电话
|
||||||
function callPhone() {
|
function callPhone() {
|
||||||
if (activityInfo.value.contactPhone) {
|
if (activityInfo.value.contactPhone) {
|
||||||
uni.makePhoneCall({
|
uni.makePhoneCall({
|
||||||
phoneNumber: activityInfo.value.contactPhone
|
phoneNumber: activityInfo.value.contactPhone,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 显示已报名列表
|
// 立即报名
|
||||||
function showRegisteredList() {
|
async function handleRegister() {
|
||||||
// TODO: 弹出已报名人员列表或跳转页面
|
const { code, data } = await ActivityApi.register({
|
||||||
uni.showToast({
|
activityId: activityInfo.value.id,
|
||||||
title: '查看报名名单',
|
});
|
||||||
icon: 'none'
|
if (code === 0 && data) {
|
||||||
|
uni.showToast({ title: '报名成功', icon: 'success' });
|
||||||
|
activityInfo.value.hasRegistered = true;
|
||||||
|
activityInfo.value.registeredCount++;
|
||||||
|
} else {
|
||||||
|
uni.showToast({ title: msg, icon: 'none' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 取消报名
|
||||||
|
async function handleCancelRegister() {
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '确定取消报名吗?',
|
||||||
|
success: async (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
const { code, data } = await ActivityApi.cancelRegister(activityInfo.value.id);
|
||||||
|
if (code === 0 && data) {
|
||||||
|
uni.showToast({ title: '取消报名成功', icon: 'success' });
|
||||||
|
activityInfo.value.hasRegistered = false;
|
||||||
|
activityInfo.value.registeredCount--;
|
||||||
|
} else {
|
||||||
|
uni.showToast({ title: '取消报名失败', icon: 'none' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -293,17 +371,17 @@ function goBack() {
|
||||||
/* 信息行 */
|
/* 信息行 */
|
||||||
.info-row {
|
.info-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-start;
|
align-items: center;
|
||||||
padding: 20rpx 32rpx;
|
padding: 20rpx 32rpx;
|
||||||
|
|
||||||
.sicon-location,
|
.row-icon {
|
||||||
.sicon-phone,
|
width: 32rpx;
|
||||||
.sicon-person {
|
height: 32rpx;
|
||||||
font-size: 32rpx;
|
|
||||||
color: #666666;
|
|
||||||
margin-right: 8rpx;
|
margin-right: 8rpx;
|
||||||
margin-top: 2rpx;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 地址行 */
|
/* 地址行 */
|
||||||
|
|
@ -397,17 +475,14 @@ function goBack() {
|
||||||
padding: 32rpx;
|
padding: 32rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 底部占位:基础间距 + 安全区域 */
|
/* 底部占位 */
|
||||||
.bottom-placeholder {
|
.bottom-placeholder {
|
||||||
height: calc(140rpx + env(safe-area-inset-bottom));
|
height: 40rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 底部固定按钮栏 */
|
/* 底部按钮栏:正常文档流,flex-shrink:0 保证不被压缩 */
|
||||||
.bottom-bar {
|
.bottom-bar {
|
||||||
position: fixed;
|
flex-shrink: 0;
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 24rpx;
|
gap: 24rpx;
|
||||||
|
|
@ -416,10 +491,11 @@ function goBack() {
|
||||||
background-color: #FFFFFF;
|
background-color: #FFFFFF;
|
||||||
box-shadow: 0 -4rpx 16rpx rgba(0, 0, 0, 0.06);
|
box-shadow: 0 -4rpx 16rpx rgba(0, 0, 0, 0.06);
|
||||||
|
|
||||||
.registered-btn {
|
.registered-btn,
|
||||||
|
.register-btn,
|
||||||
|
.cancel-btn {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
height: 88rpx;
|
height: 88rpx;
|
||||||
border: 2rpx solid #FA7E49;
|
|
||||||
border-radius: 44rpx;
|
border-radius: 44rpx;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
@ -428,6 +504,10 @@ function goBack() {
|
||||||
&:active {
|
&:active {
|
||||||
opacity: 0.85;
|
opacity: 0.85;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.registered-btn {
|
||||||
|
border: 2rpx solid #FA7E49;
|
||||||
|
|
||||||
.registered-text {
|
.registered-text {
|
||||||
font-size: 30rpx;
|
font-size: 30rpx;
|
||||||
|
|
@ -436,6 +516,26 @@ function goBack() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.register-btn {
|
||||||
|
background-color: #FA7E49;
|
||||||
|
|
||||||
|
.register-text {
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #FFFFFF;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cancel-btn {
|
||||||
|
border: 2rpx solid #999999;
|
||||||
|
|
||||||
|
.cancel-text {
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #999999;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.back-btn {
|
.back-btn {
|
||||||
width: 240rpx;
|
width: 240rpx;
|
||||||
height: 88rpx;
|
height: 88rpx;
|
||||||
|
|
|
||||||
|
|
@ -9,12 +9,25 @@
|
||||||
<view class="list-header">
|
<view class="list-header">
|
||||||
<!-- 顶部提示条 -->
|
<!-- 顶部提示条 -->
|
||||||
<view class="top-banner">
|
<view class="top-banner">
|
||||||
<text class="banner-text">融侨馨苑开展活动啦!!</text>
|
<text class="banner-text">{{ communityName }}开展活动啦!!</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 活动列表 - 独立滚动 -->
|
<!-- 空状态 -->
|
||||||
<scroll-view class="activity-scroll" scroll-y :style="{ height: scrollViewHeight + 'px' }">
|
<view class="empty-state" v-if="activityList.length === 0 && !loading">
|
||||||
|
<text class="empty-text">暂无活动</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 活动列表 - 滚动 -->
|
||||||
|
<scroll-view
|
||||||
|
v-else
|
||||||
|
class="activity-scroll"
|
||||||
|
scroll-y
|
||||||
|
@scrolltolower="onLoadMore"
|
||||||
|
@refresherrefresh="onRefresh"
|
||||||
|
:refresher-triggered="loading"
|
||||||
|
refresher-enabled
|
||||||
|
>
|
||||||
<view class="list-inner">
|
<view class="list-inner">
|
||||||
<view
|
<view
|
||||||
class="activity-item"
|
class="activity-item"
|
||||||
|
|
@ -32,19 +45,19 @@
|
||||||
<text class="item-location">{{ item.location }}</text>
|
<text class="item-location">{{ item.location }}</text>
|
||||||
<text class="item-status" :class="'status-' + item.statusType">{{ item.statusText }}</text>
|
<text class="item-status" :class="'status-' + item.statusType">{{ item.statusText }}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="item-row">
|
<view class="item-row nowrap">
|
||||||
<text class="item-label">报名日期:</text>
|
<text class="item-label">报名日期:</text>
|
||||||
<text class="item-value">{{ item.registerDate }}</text>
|
<text class="item-value">{{ item.registerDate }}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="item-row">
|
<view class="item-row wrap">
|
||||||
<text class="item-date">{{ item.dateRange }}</text>
|
<text class="item-date">{{ item.dateRange }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 空状态 -->
|
<!-- 加载更多提示 -->
|
||||||
<view class="empty-state" v-if="activityList.length === 0">
|
<view class="load-more" v-if="activityList.length > 0">
|
||||||
<text class="empty-text">暂无活动</text>
|
<text class="load-text">{{ finished ? '没有更多了' : loading ? '加载中...' : '上拉加载更多' }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
|
|
@ -58,114 +71,105 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, nextTick, getCurrentInstance } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { onLoad } from '@dcloudio/uni-app';
|
import { onLoad } from '@dcloudio/uni-app';
|
||||||
|
import ActivityApi from '@/sheep/api/community/activity';
|
||||||
|
import sheep from '@/sheep';
|
||||||
|
|
||||||
// 列表滚动区域高度(单位:px)
|
// 分页参数
|
||||||
const scrollViewHeight = ref(0);
|
const pageNo = ref(1);
|
||||||
|
const pageSize = ref(10);
|
||||||
|
const total = ref(0);
|
||||||
|
const loading = ref(false);
|
||||||
|
const finished = ref(false);
|
||||||
|
|
||||||
|
// 小区名称
|
||||||
|
const communityName = ref('');
|
||||||
|
|
||||||
// 活动列表数据
|
// 活动列表数据
|
||||||
const activityList = ref([
|
const activityList = ref([]);
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
title: 'xxxxxxxxxxxxx活动',
|
|
||||||
location: '福清市音西街道融侨馨苑',
|
|
||||||
statusText: '进行中',
|
|
||||||
statusType: 'ongoing',
|
|
||||||
registerDate: '2025/06/30-2025/07/01',
|
|
||||||
dateRange: '2025/07/05 12:00-2025/07/05 18:00',
|
|
||||||
cover: '/static/img/guest.png'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
title: 'xxxxxxxxxxxxx活动',
|
|
||||||
location: '福清市音西街道融侨馨苑',
|
|
||||||
statusText: '报名中',
|
|
||||||
statusType: 'registering',
|
|
||||||
registerDate: '2025/06/30-2025/07/01',
|
|
||||||
dateRange: '2025/07/05 12:00-2025/07/05 18:00',
|
|
||||||
cover: '/static/img/guest.png'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
title: 'xxxxxxxxxxxxx活动',
|
|
||||||
location: '福清市音西街道融侨馨苑',
|
|
||||||
statusText: '已结束',
|
|
||||||
statusType: 'ended',
|
|
||||||
registerDate: '2025/06/30-2025/07/01',
|
|
||||||
dateRange: '2025/07/05 12:00-2025/07/05 18:00',
|
|
||||||
cover: '/static/img/guest.png'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
title: 'xxxxxxxxxxxxx活动',
|
|
||||||
location: '福清市音西街道融侨馨苑',
|
|
||||||
statusText: '已结束',
|
|
||||||
statusType: 'ended',
|
|
||||||
registerDate: '2025/06/30-2025/07/01',
|
|
||||||
dateRange: '2025/07/05 12:00-2025/07/05 18:00',
|
|
||||||
cover: '/static/img/guest.png'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
title: 'xxxxxxxxxxxxx活动',
|
|
||||||
location: '福清市音西街道融侨馨苑',
|
|
||||||
statusText: '已结束',
|
|
||||||
statusType: 'ended',
|
|
||||||
registerDate: '2025/06/30-2025/07/01',
|
|
||||||
dateRange: '2025/07/05 12:00-2025/07/05 18:00',
|
|
||||||
cover: '/static/img/guest.png'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
title: 'xxxxxxxxxxxxx活动',
|
|
||||||
location: '福清市音西街道融侨馨苑',
|
|
||||||
statusText: '已结束',
|
|
||||||
statusType: 'ended',
|
|
||||||
registerDate: '2025/06/30-2025/07/01',
|
|
||||||
dateRange: '2025/07/05 12:00-2025/07/05 18:00',
|
|
||||||
cover: '/static/img/guest.png'
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
// 页面加载
|
// 页面加载
|
||||||
onLoad(() => {
|
onLoad(() => {
|
||||||
|
const userInfo = sheep.$store('user').userInfo;
|
||||||
|
communityName.value = userInfo?.currentCommunityName || '';
|
||||||
loadActivityList();
|
loadActivityList();
|
||||||
});
|
});
|
||||||
|
|
||||||
// 渲染完成后计算scroll-view高度
|
|
||||||
onMounted(() => {
|
|
||||||
const instance = getCurrentInstance();
|
|
||||||
nextTick(() => {
|
|
||||||
const sysInfo = uni.getSystemInfoSync();
|
|
||||||
uni.createSelectorQuery()
|
|
||||||
.in(instance)
|
|
||||||
.select('.list-header')
|
|
||||||
.boundingClientRect((rect) => {
|
|
||||||
if (rect) {
|
|
||||||
// scroll-view高度 = 屏幕可用高度 - 头部区域高度 - 头部距顶部距离
|
|
||||||
scrollViewHeight.value = sysInfo.windowHeight - rect.height - rect.top;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.exec();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// 加载活动列表
|
// 加载活动列表
|
||||||
async function loadActivityList() {
|
async function loadActivityList() {
|
||||||
// TODO: 调用API获取活动列表
|
if (loading.value || finished.value) return;
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
const { code, data } = await ActivityApi.getPage({
|
||||||
|
pageNo: pageNo.value,
|
||||||
|
pageSize: pageSize.value,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (code === 0 && data) {
|
||||||
|
const list = (data.list || []).map((item) => ({
|
||||||
|
id: item.id,
|
||||||
|
title: item.title || '',
|
||||||
|
cover: item.coverImage || '/static/img/guest.png',
|
||||||
|
status: item.status,
|
||||||
|
statusText: getStatusText(item.status),
|
||||||
|
statusType: getStatusType(item.status),
|
||||||
|
registerDate: item.registrationStartTime && item.registrationEndTime
|
||||||
|
? `${sheep.$helper.timeFormat(item.registrationStartTime, 'yyyy/mm/dd')} - ${sheep.$helper.timeFormat(item.registrationEndTime, 'yyyy/mm/dd')}`
|
||||||
|
: '',
|
||||||
|
dateRange: item.activityStartTime && item.activityEndTime
|
||||||
|
? `${sheep.$helper.timeFormat(item.activityStartTime, 'yyyy/mm/dd hh:MM')} - ${sheep.$helper.timeFormat(item.activityEndTime, 'yyyy/mm/dd hh:MM')}`
|
||||||
|
: '',
|
||||||
|
location: item.location || '',
|
||||||
|
}));
|
||||||
|
|
||||||
|
activityList.value = pageNo.value === 1 ? list : [...activityList.value, ...list];
|
||||||
|
total.value = data.total || 0;
|
||||||
|
|
||||||
|
if (activityList.value.length >= total.value) {
|
||||||
|
finished.value = true;
|
||||||
|
} else {
|
||||||
|
pageNo.value++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 状态映射
|
||||||
|
function getStatusText(status) {
|
||||||
|
const map = { 0: '报名中', 1: '进行中', 2: '已结束' };
|
||||||
|
return map[status] || '未知';
|
||||||
|
}
|
||||||
|
|
||||||
|
function getStatusType(status) {
|
||||||
|
const map = { 0: 'registering', 1: 'ongoing', 2: 'ended' };
|
||||||
|
return map[status] || 'ended';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 下拉刷新
|
||||||
|
function onRefresh() {
|
||||||
|
pageNo.value = 1;
|
||||||
|
finished.value = false;
|
||||||
|
activityList.value = [];
|
||||||
|
loadActivityList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 滚动到底部加载更多
|
||||||
|
function onLoadMore() {
|
||||||
|
loadActivityList();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 跳转详情
|
// 跳转详情
|
||||||
function goDetail(item) {
|
function goDetail(item) {
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: `/pages/sub/activity/detail?id=${item.id}`
|
url: `/pages/sub/activity/detail?id=${item.id}`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 浮动按钮点击
|
// 浮动按钮点击 - 跳转我的报名
|
||||||
function handleFloatBtn() {
|
function handleFloatBtn() {
|
||||||
// TODO: 发布活动或跳转相关页面
|
uni.navigateTo({ url: '/pages/sub/activity/my-registration' });
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
@ -174,7 +178,8 @@ function handleFloatBtn() {
|
||||||
.activity-list-page {
|
.activity-list-page {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
min-height: 100vh;
|
height: calc(100vh - 176rpx);
|
||||||
|
overflow: hidden;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -205,9 +210,10 @@ function handleFloatBtn() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 活动列表滚动区域 - 高度由JS动态绑定 */
|
/* 活动列表滚动区域:flex:1 占满剩余空间,height:0 是小程序 scroll-view 配合 flex 的关键 */
|
||||||
.activity-scroll {
|
.activity-scroll {
|
||||||
flex: 1; /* 占据剩余空间 */
|
flex: 1;
|
||||||
|
height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 列表内容包裹层 */
|
/* 列表内容包裹层 */
|
||||||
|
|
@ -254,6 +260,15 @@ function handleFloatBtn() {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-top: 8rpx;
|
margin-top: 8rpx;
|
||||||
|
|
||||||
|
&.nowrap {
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.wrap {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-location {
|
.item-location {
|
||||||
|
|
@ -279,23 +294,28 @@ function handleFloatBtn() {
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-value {
|
.item-value {
|
||||||
font-size: 24rpx;
|
font-size: 22rpx;
|
||||||
color: #333333;
|
color: #333333;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-date {
|
.item-date {
|
||||||
font-size: 24rpx;
|
font-size: 20rpx;
|
||||||
color: #666666;
|
color: #666666;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.load-more{
|
||||||
|
text-align: center;
|
||||||
|
padding-top: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
/* 空状态 */
|
/* 空状态 */
|
||||||
.empty-state {
|
.empty-state {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: 200rpx 0;
|
flex: 1;
|
||||||
|
|
||||||
.empty-text {
|
.empty-text {
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,314 @@
|
||||||
|
<!-- 我的报名页面 -->
|
||||||
|
<template>
|
||||||
|
<s-layout title="我的报名">
|
||||||
|
<view class="my-registration-page">
|
||||||
|
<!-- 空状态 -->
|
||||||
|
<view class="empty-state" v-if="list.length === 0 && !loading">
|
||||||
|
<text class="empty-text">暂无报名记录</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 报名列表 -->
|
||||||
|
<scroll-view
|
||||||
|
v-else
|
||||||
|
class="registration-scroll"
|
||||||
|
scroll-y
|
||||||
|
@scrolltolower="onLoadMore"
|
||||||
|
@refresherrefresh="onRefresh"
|
||||||
|
:refresher-triggered="loading"
|
||||||
|
refresher-enabled
|
||||||
|
>
|
||||||
|
<view class="list-inner">
|
||||||
|
<view
|
||||||
|
class="registration-item"
|
||||||
|
v-for="(item, index) in list"
|
||||||
|
:key="index"
|
||||||
|
@tap="goDetail(item)"
|
||||||
|
>
|
||||||
|
<!-- 左侧封面图 -->
|
||||||
|
<image class="item-cover" :src="item.cover" mode="aspectFill" />
|
||||||
|
|
||||||
|
<!-- 右侧内容区 -->
|
||||||
|
<view class="item-content">
|
||||||
|
<text class="item-title">{{ item.title }}</text>
|
||||||
|
<view class="item-row">
|
||||||
|
<text class="item-location">{{ item.location }}</text>
|
||||||
|
<text class="item-status" :class="'status-' + item.statusType">{{ item.statusText }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="item-row nowrap">
|
||||||
|
<text class="item-label">报名日期:</text>
|
||||||
|
<text class="item-value">{{ item.registerDate }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="item-row wrap">
|
||||||
|
<text class="item-date">{{ item.dateRange }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 加载更多提示 -->
|
||||||
|
<view class="load-more" v-if="list.length > 0">
|
||||||
|
<text class="load-text">{{ finished ? '没有更多了' : loading ? '加载中...' : '上拉加载更多' }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
|
||||||
|
<!-- 底部固定返回按钮 -->
|
||||||
|
<view class="bottom-bar">
|
||||||
|
<view class="back-btn" @tap="goBack">返回</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</s-layout>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { onLoad } from '@dcloudio/uni-app';
|
||||||
|
import ActivityApi from '@/sheep/api/community/activity';
|
||||||
|
import sheep from '@/sheep';
|
||||||
|
|
||||||
|
// 分页参数
|
||||||
|
const pageNo = ref(1);
|
||||||
|
const pageSize = ref(10);
|
||||||
|
const total = ref(0);
|
||||||
|
const loading = ref(false);
|
||||||
|
const finished = ref(false);
|
||||||
|
|
||||||
|
// 报名列表数据
|
||||||
|
const list = ref([]);
|
||||||
|
|
||||||
|
// 页面加载
|
||||||
|
onLoad(() => {
|
||||||
|
loadList();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 加载报名列表
|
||||||
|
async function loadList() {
|
||||||
|
if (loading.value || finished.value) return;
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
const { code, data } = await ActivityApi.getMyRegistrationPage({
|
||||||
|
pageNo: pageNo.value,
|
||||||
|
pageSize: pageSize.value,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (code === 0 && data) {
|
||||||
|
const mapped = (data.list || []).map((item) => ({
|
||||||
|
id: item.id,
|
||||||
|
activityId: item.activityId,
|
||||||
|
title: item.activityTitle || '',
|
||||||
|
cover: item.activityCoverImage || '/static/img/guest.png',
|
||||||
|
status: item.status,
|
||||||
|
statusText: getStatusText(item.status),
|
||||||
|
statusType: getStatusType(item.status),
|
||||||
|
// 接口暂未返回以下字段,先留空兼容;若后端补充后可自动展示
|
||||||
|
location: item.location || '',
|
||||||
|
registerDate: item.registrationStartTime && item.registrationEndTime
|
||||||
|
? `${sheep.$helper.timeFormat(item.registrationStartTime, 'yyyy/mm/dd')} - ${sheep.$helper.timeFormat(item.registrationEndTime, 'yyyy/mm/dd')}`
|
||||||
|
: '',
|
||||||
|
dateRange: item.activityStartTime && item.activityEndTime
|
||||||
|
? `${sheep.$helper.timeFormat(item.activityStartTime, 'yyyy/mm/dd hh:MM')} - ${sheep.$helper.timeFormat(item.activityEndTime, 'yyyy/mm/dd hh:MM')}`
|
||||||
|
: '',
|
||||||
|
}));
|
||||||
|
|
||||||
|
list.value = pageNo.value === 1 ? mapped : [...list.value, ...mapped];
|
||||||
|
total.value = data.total || 0;
|
||||||
|
|
||||||
|
if (list.value.length >= total.value) {
|
||||||
|
finished.value = true;
|
||||||
|
} else {
|
||||||
|
pageNo.value++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 报名状态映射(0-待审核 1-已通过 2-已拒绝 3-已取消)
|
||||||
|
function getStatusText(status) {
|
||||||
|
const map = { 0: '待审核', 1: '已通过', 2: '已拒绝', 3: '已取消' };
|
||||||
|
return map[status] || '未知';
|
||||||
|
}
|
||||||
|
|
||||||
|
function getStatusType(status) {
|
||||||
|
const map = { 0: 'pending', 1: 'passed', 2: 'rejected', 3: 'cancelled' };
|
||||||
|
return map[status] || 'cancelled';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 下拉刷新
|
||||||
|
function onRefresh() {
|
||||||
|
pageNo.value = 1;
|
||||||
|
finished.value = false;
|
||||||
|
list.value = [];
|
||||||
|
loadList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 滚动到底部加载更多
|
||||||
|
function onLoadMore() {
|
||||||
|
loadList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 跳转详情(使用活动ID)
|
||||||
|
function goDetail(item) {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `/pages/sub/activity/detail?id=${item.activityId}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回上一页
|
||||||
|
function goBack() {
|
||||||
|
uni.navigateBack();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
/* 页面容器 - flex布局,底部按钮固定 */
|
||||||
|
.my-registration-page {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: calc(100vh - 176rpx);
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: #F5F5F5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 报名列表滚动区域 */
|
||||||
|
.registration-scroll {
|
||||||
|
flex: 1;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 列表内容包裹层 */
|
||||||
|
.list-inner {
|
||||||
|
padding: 24rpx 32rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 报名卡片 */
|
||||||
|
.registration-item {
|
||||||
|
display: flex;
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
padding: 24rpx;
|
||||||
|
margin-bottom: 24rpx;
|
||||||
|
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
|
||||||
|
|
||||||
|
.item-cover {
|
||||||
|
width: 200rpx;
|
||||||
|
height: 160rpx;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-content {
|
||||||
|
flex: 1;
|
||||||
|
margin-left: 24rpx;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.item-title {
|
||||||
|
font-size: 30rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #1890FF;
|
||||||
|
line-height: 1.4;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
-webkit-line-clamp: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 8rpx;
|
||||||
|
|
||||||
|
&.nowrap {
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.wrap {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-location {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #333333;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 状态标签颜色(0-待审核 1-已通过 2-已拒绝 3-已取消)
|
||||||
|
.item-status {
|
||||||
|
font-size: 26rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
&.status-passed { color: #52C41A; } // 已通过-绿色
|
||||||
|
&.status-pending { color: #FAAD14; } // 待审核-橙色
|
||||||
|
&.status-rejected { color: #FF4D4F; } // 已拒绝-红色
|
||||||
|
&.status-cancelled { color: #999999; } // 已取消-灰色
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-label {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #666666;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-value {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-date {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.load-more {
|
||||||
|
text-align: center;
|
||||||
|
padding: 30rpx 0;
|
||||||
|
|
||||||
|
.load-text {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 空状态 */
|
||||||
|
.empty-state {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.empty-text {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 底部固定栏 */
|
||||||
|
.bottom-bar {
|
||||||
|
flex-shrink: 0;
|
||||||
|
padding: 24rpx 40rpx calc(24rpx + env(safe-area-inset-bottom));
|
||||||
|
// background-color: #FFFFFF;
|
||||||
|
box-shadow: 0 -2rpx 12rpx rgba(0, 0, 0, 0.04);
|
||||||
|
|
||||||
|
.back-btn {
|
||||||
|
height: 88rpx;
|
||||||
|
line-height: 88rpx;
|
||||||
|
text-align: center;
|
||||||
|
background-color: #FA7E49;
|
||||||
|
color: #FFFFFF;
|
||||||
|
font-size: 30rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
border-radius: 44rpx;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
opacity: 0.85;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
import request from '@/sheep/request';
|
||||||
|
|
||||||
|
const ActivityApi = {
|
||||||
|
// 获取活动列表
|
||||||
|
getPage: (data) => {
|
||||||
|
return request({
|
||||||
|
url: '/community/activity/page',
|
||||||
|
method: 'GET',
|
||||||
|
params: data,
|
||||||
|
custom: {
|
||||||
|
showLoading: true,
|
||||||
|
auth: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 获取活动详情
|
||||||
|
getDetail: (id) => {
|
||||||
|
return request({
|
||||||
|
url: '/community/activity/get',
|
||||||
|
method: 'GET',
|
||||||
|
params: { id },
|
||||||
|
custom: {
|
||||||
|
showLoading: true,
|
||||||
|
auth: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 活动报名
|
||||||
|
register: (data) => {
|
||||||
|
return request({
|
||||||
|
url: '/community/activity/registration',
|
||||||
|
method: 'POST',
|
||||||
|
data,
|
||||||
|
custom: {
|
||||||
|
showLoading: true,
|
||||||
|
auth: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 取消报名
|
||||||
|
cancelRegister: (id) => {
|
||||||
|
return request({
|
||||||
|
url: '/community/activity/registration/cancel',
|
||||||
|
method: 'POST',
|
||||||
|
params: { id },
|
||||||
|
custom: {
|
||||||
|
showLoading: true,
|
||||||
|
auth: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 我的报名列表
|
||||||
|
getMyRegistrationPage: (data) => {
|
||||||
|
return request({
|
||||||
|
url: '/community/activity/registration/page',
|
||||||
|
method: 'GET',
|
||||||
|
params: data,
|
||||||
|
custom: {
|
||||||
|
showLoading: true,
|
||||||
|
auth: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ActivityApi;
|
||||||
|
Before Width: | Height: | Size: 6.9 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 9.8 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 5.5 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 3.4 KiB |