This commit is contained in:
qiuyuan 2025-08-04 10:15:46 +08:00
parent d7f7180e80
commit 0b395638ed
2 changed files with 508 additions and 605 deletions

View File

@ -1,12 +1,15 @@
<template> <template>
<view class="activity-detail-container"> <view class="activity-detail-container">
<!-- 顶部图片轮播 --> <!-- 顶部图片轮播 -->
<view class="banner-container">
<swiper class="activity-banner" :autoplay="false" indicator-dots indicator-color="rgba(255,255,255,0.5)" <swiper class="activity-banner" :autoplay="false" indicator-dots indicator-color="rgba(255,255,255,0.5)"
indicator-active-color="#5b9cf8"> indicator-active-color="#5b9cf8">
<swiper-item v-for="(img, index) in bannerImages" :key="index"> <swiper-item v-for="(img, index) in bannerImages" :key="index">
<image :src="img" mode="aspectFill" class="w-full h-full" @click="previewImage(index)" /> <image :src="img" class="w-full h-full" @click="previewImage(index)" />
</swiper-item> </swiper-item>
</swiper> </swiper>
<view class="banner-mask"></view>
</view>
<!-- 活动基本信息 --> <!-- 活动基本信息 -->
<view class="activity-base-info"> <view class="activity-base-info">
@ -25,94 +28,46 @@
<view class="info-grid"> <view class="info-grid">
<view class="info-item"> <view class="info-item">
<u-icon name="star" size="24" color="#5b9cf8"></u-icon> <u-icon name="star" size="26" color="#5b9cf8"></u-icon>
<view class="info-text"><text>活动类型</text>{{activityInfo.categoryName || '待确认'}} </view> <view class="info-text"><text class="info-label">活动类型</text>{{activityInfo.categoryName || '待确认'}} </view>
</view> </view>
<view class="info-item"> <view class="info-item">
<u-icon name="map" size="24" color="#5b9cf8"></u-icon> <u-icon name="clock" size="26" color="#5b9cf8"></u-icon>
<view class="info-text"><text>活动地址</text>{{activityInfo.address || '待定'}}</view> <view class="info-text"><text class="info-label">活动时间</text>{{ activityInfo.openAt }}</view>
</view> </view>
<view class="info-item">
<u-icon name="clock" size="24" color="#5b9cf8"></u-icon>
<view class="info-text">{{ activityInfo.openAt }}</view>
</view>
<!-- <view class="info-item">
<u-icon name="account" size="18" color="#36CFC9"></u-icon>
<text class="info-text">已报名 {{activityInfo.participants}}</text>
</view> -->
<view class="info-item">
<u-icon name="clock-fill" size="26" color="#ff5a5f"></u-icon>
<view class="info-text"><text class="info-label">结束时间</text>{{ formatTime(activityInfo.endAt,"YYYY-MM-DD HH:mm:ss") }}</view>
</view>
<view class="info-item highlight">
<u-icon name="warning" size="26" color="#ff9500"></u-icon>
<view class="info-text"><text class="info-label">报名截止</text>{{ formatTime(activityInfo.endSignupAt,"YYYY-MM-DD HH:mm:ss") }}</view>
</view>
</view> </view>
</view> </view>
<!-- 活动详情卡片 --> <!-- 活动详情卡片 -->
<view class="detail-card"> <view class="detail-card">
<!-- <view class="card-header">
<view class="header-line"></view>
<text class="header-title">活动详情</text>
</view> -->
<view class="detail-section"> <view class="detail-section">
<view class="section-title"> <view class="section-title">
<view class="title-icon"></view> <view class="title-icon"></view>
<text>活动详情</text> <text>活动详情</text>
</view> </view>
<view class="section-content"> <view class="section-content rich-text">
<view v-html="activityInfo.content"></view> <rich-text :nodes="activityInfo.content"></rich-text>
<image src="/static/route-map.jpg" mode="widthFix" class="route-map" <!-- <image src="/static/route-map.jpg" mode="widthFix" class="route-map"
@click="previewImage(bannerImages.length)"></image> @click="previewImage(bannerImages.length)"></image> -->
</view>
</view>
<!-- <view class="detail-section">
<view class="section-title">
<view class="title-icon"></view>
<text>活动流程</text>
</view>
<view class="timeline">
<view class="timeline-item" v-for="(step, index) in timeline" :key="index">
<view class="timeline-dot" :style="{backgroundColor: dotColors[index]}"></view>
<view class="timeline-content">
<text class="timeline-time">{{step.time}}</text>
<text class="timeline-desc">{{step.desc}}</text>
</view> </view>
</view> </view>
</view> </view>
</view> -->
<!-- <view class="detail-section">
<view class="section-title">
<view class="title-icon"></view>
<text>积分规则</text>
</view>
<view class="point-rules">
<view class="rule-item" v-for="(rule, index) in pointRules" :key="index">
<view class="rule-icon">
<text>{{index + 1}}</text>
</view>
<text class="rule-text">{{rule}}</text>
</view>
</view>
</view> -->
</view>
<!-- 温馨提示 -->
<!-- <view class="tips-card">
<view class="card-header">
<view class="header-line"></view>
<text class="header-title">温馨提示</text>
</view>
<view class="tips-content">
<text class="tip-item" v-for="(tip, index) in tips" :key="index">
{{tip}}
</text>
</view>
</view> -->
<!-- 底部操作栏 --> <!-- 底部操作栏 -->
<view class="action-bar"> <view class="action-bar safe-area-inset-bottom">
<button class="share-btn" open-type="share"> <button class="share-btn" open-type="share">
<u-icon name="share" size="36" color="#fff"></u-icon> <u-icon name="share" size="32" color="#fff"></u-icon>
<text class="share-text">分享</text> <text class="share-text">分享</text>
</button> </button>
<button class="signup-btn" @click="handleSignUp">立即报名</button> <button class="signup-btn" @click="handleSignUp">立即报名</button>
@ -241,49 +196,75 @@
<style lang="scss" scoped> <style lang="scss" scoped>
$primary-color: #5b9cf8; $primary-color: #5b9cf8;
$secondary-color: #F7F8FA; $secondary-color: #f7f8fa;
$text-color: #333; $text-color: #333;
$light-text: #666; $light-text: #666;
$lighter-text: #999;
$border-color: #eee; $border-color: #eee;
$border-radius: 16rpx; $border-radius: 16rpx;
$shadow: 0 4rpx 24rpx rgba(0, 0, 0, 0.06); $shadow: 0 4rpx 24rpx rgba(0, 0, 0, 0.08);
$highlight-color: #fff8e6;
.activity-detail-container { .activity-detail-container {
padding-bottom: 120rpx; padding-bottom: 160rpx;
background-color: $secondary-color; background-color: $secondary-color;
color: $text-color;
.banner-container {
position: relative;
height: 500rpx;
overflow: hidden;
.activity-banner { .activity-banner {
width: 100%; width: 100%;
height: 420rpx; height: 100%;
}
image { .activity-banner image {
width: 100%; width: 100%;
height: 100%; height: 100%;
display: block;
}
.banner-mask {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 120rpx;
background: linear-gradient(to top, rgba(0,0,0,0.3), transparent);
} }
} }
.activity-base-info { .activity-base-info {
padding: 30rpx; padding: 30rpx;
margin: -40rpx 20rpx 20rpx;
background-color: #fff; background-color: #fff;
margin-bottom: 20rpx; border-radius: $border-radius;
box-shadow: $shadow; box-shadow: $shadow;
position: relative;
z-index: 2;
.title-box { .title-box {
display: flex; display: flex;
align-items: center; align-items: center;
margin-bottom: 30rpx; margin-bottom: 30rpx;
padding-bottom: 20rpx;
border-bottom: 1rpx solid rgba($border-color, 0.8);
.title { .title {
font-size: 36rpx; flex: 1;
font-size: 38rpx;
font-weight: bold; font-weight: bold;
color: $text-color; line-height: 1.4;
margin-right: 20rpx; margin-right: 20rpx;
} }
.status-tag { .status-tag {
padding: 6rpx 16rpx; padding: 8rpx 20rpx;
border-radius: 30rpx; border-radius: 30rpx;
font-size: 24rpx; font-size: 24rpx;
flex-shrink: 0;
&.active { &.active {
background-color: rgba($primary-color, 0.1); background-color: rgba($primary-color, 0.1);
@ -295,200 +276,93 @@
.info-grid { .info-grid {
display: grid; display: grid;
grid-template-columns: repeat(1, 1fr); grid-template-columns: repeat(1, 1fr);
gap: 20rpx; gap: 24rpx;
.info-item { .info-item {
display: flex; display: flex;
align-items: center; align-items: center; /* 垂直居中 */
&.highlight {
background-color: #fff8e6;
padding: 16rpx;
border-radius: 12rpx;
margin:0rpx -16rpx;
}
.u-icon {
flex-shrink: 0; /* 防止图标被压缩 */
}
.info-text { .info-text {
font-size: 26rpx; font-size: 28rpx;
color: $light-text; line-height: 1.5;
margin-left: 10rpx; margin-left: 12rpx;
display: flex;
align-items: center; /* 确保内部文本垂直居中 */
.info-label {
color: #999;
margin-right: 8rpx;
}
} }
} }
} }
} }
.detail-card, .detail-card {
.tips-card {
background-color: #fff; background-color: #fff;
border-radius: $border-radius; border-radius: $border-radius;
padding: 30rpx; padding: 30rpx;
margin: 0 20rpx 20rpx; margin: 0 20rpx 20rpx;
box-shadow: $shadow; box-shadow: $shadow;
.card-header { .detail-section {
margin-bottom: 40rpx;
.section-title {
display: flex; display: flex;
align-items: center; align-items: center;
margin-bottom: 30rpx; margin-bottom: 24rpx;
padding-bottom: 16rpx;
border-bottom: 1rpx solid rgba($border-color, 0.5);
.header-line { .title-icon {
width: 6rpx; width: 8rpx;
height: 32rpx; height: 32rpx;
background-color: $primary-color; background-color: $primary-color;
border-radius: 4rpx; border-radius: 4rpx;
margin-right: 16rpx; margin-right: 16rpx;
} }
.header-title { text {
font-size: 32rpx; font-size: 32rpx;
font-weight: bold; font-weight: bold;
color: $text-color;
}
}
.detail-section {
margin-bottom: 40rpx;
&:last-child {
margin-bottom: 0;
}
.section-title {
display: flex;
align-items: center;
margin-bottom: 20rpx;
.title-icon {
width: 8rpx;
height: 28rpx;
background-color: $primary-color;
border-radius: 4rpx;
margin-right: 12rpx;
}
text {
font-size: 30rpx;
font-weight: bold;
color: $text-color;
} }
} }
.section-content { .section-content {
font-size: 28rpx; font-size: 30rpx;
line-height: 1.8;
color: $light-text; color: $light-text;
line-height: 1.6;
&.rich-text {
p {
margin-bottom: 24rpx;
line-height: 1.8;
}
img {
max-width: 100%;
border-radius: 8rpx;
margin: 20rpx 0;
}
}
.route-map { .route-map {
width: 100%; width: 100%;
margin-top: 20rpx; margin-top: 30rpx;
border-radius: $border-radius; border-radius: $border-radius;
} box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);
}
.timeline {
position: relative;
padding-left: 40rpx;
&::before {
content: '';
position: absolute;
left: 15rpx;
top: 10rpx;
bottom: 10rpx;
width: 2rpx;
background-color: $border-color;
}
.timeline-item {
position: relative;
padding-bottom: 30rpx;
&:last-child {
padding-bottom: 0;
}
.timeline-dot {
position: absolute;
left: -40rpx;
top: 4rpx;
width: 30rpx;
height: 30rpx;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
z-index: 1;
&::after {
content: '';
width: 10rpx;
height: 10rpx;
background-color: #fff;
border-radius: 50%;
}
}
.timeline-content {
.timeline-time {
display: block;
font-size: 26rpx;
color: $primary-color;
font-weight: bold;
margin-bottom: 6rpx;
}
.timeline-desc {
font-size: 28rpx;
color: $light-text;
}
}
}
}
.point-rules {
.rule-item {
display: flex;
align-items: flex-start;
margin-bottom: 20rpx;
&:last-child {
margin-bottom: 0;
}
.rule-icon {
width: 36rpx;
height: 36rpx;
background-color: $primary-color;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin-right: 16rpx;
flex-shrink: 0;
text {
color: #fff;
font-size: 22rpx;
font-weight: bold;
}
}
.rule-text {
font-size: 28rpx;
color: $light-text;
line-height: 1.5;
}
}
}
}
.tips-content {
.tip-item {
display: block;
position: relative;
padding-left: 30rpx;
font-size: 28rpx;
color: $light-text;
line-height: 1.6;
margin-bottom: 16rpx;
&::before {
content: '•';
position: absolute;
left: 0;
color: $primary-color;
} }
} }
} }
@ -508,31 +382,32 @@
box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.08); box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.08);
z-index: 100; z-index: 100;
// &.safe-area-inset-bottom {
// padding-bottom: env(safe-area-inset-bottom);
// }
.share-btn { .share-btn {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
width: 160rpx;
height: 80rpx; height: 80rpx;
padding: 0 30rpx;
background: linear-gradient(135deg, #6e8cfa, #5b9cf8); background: linear-gradient(135deg, #6e8cfa, #5b9cf8);
border-radius: 40rpx; border-radius: 40rpx;
box-shadow: 0 4rpx 12rpx rgba(91, 156, 248, 0.3);
color: #fff; color: #fff;
font-size: 28rpx; font-size: 28rpx;
margin-right: 20rpx; margin-right: 20rpx;
border: none; border: none;
box-shadow: 0 4rpx 12rpx rgba(91, 156, 248, 0.2);
transition: all 0.2s ease;
.share-text { .share-text {
color: #fff;
font-size: 28rpx;
margin-left: 10rpx; margin-left: 10rpx;
font-weight: 500;
} }
&.btn-hover { &:active {
transform: scale(0.98);
opacity: 0.9; opacity: 0.9;
transform: translateY(2rpx);
box-shadow: 0 2rpx 6rpx rgba(91, 156, 248, 0.4);
} }
} }
@ -543,17 +418,16 @@
.signup-btn { .signup-btn {
flex: 1; flex: 1;
height: 80rpx; height: 80rpx;
margin-left: 30rpx;
background: linear-gradient(135deg, #ff7e5f, #ff5a5f); background: linear-gradient(135deg, #ff7e5f, #ff5a5f);
color: #fff; color: #fff;
border-radius: 40rpx; border-radius: 40rpx;
font-size: 32rpx; font-size: 32rpx;
font-weight: bold; font-weight: 500;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
box-shadow: 0 4rpx 12rpx rgba(255, 90, 95, 0.3); box-shadow: 0 4rpx 12rpx rgba(255, 90, 95, 0.2);
transition: all 0.3s ease; transition: all 0.2s ease;
border: none; border: none;
&::after { &::after {
@ -561,9 +435,8 @@
} }
&:active { &:active {
transform: scale(0.98);
opacity: 0.9; opacity: 0.9;
transform: translateY(2rpx);
box-shadow: 0 2rpx 6rpx rgba(255, 90, 95, 0.4);
} }
} }
} }

View File

@ -85,8 +85,14 @@
</view> </view>
</u-modal> </u-modal>
<u-modal :show="showPhoneDialog" title="联系社区" confirm-text="拨打" cancel-text="取消" @confirm="callCommunityPhone" <u-modal
@cancel="showPhoneDialog = false"> :show="showPhoneDialog"
title="联系社区"
confirm-text="拨打"
cancel-text="取消"
@confirm="callCommunityPhone"
@cancel="showPhoneDialog = false"
:closeOnClickOverlay="true">
<view class="phone-dialog-content"> <view class="phone-dialog-content">
<text>社区电话</text> <text>社区电话</text>
<text class="phone-number">{{communityPhone}}</text> <text class="phone-number">{{communityPhone}}</text>
@ -173,6 +179,9 @@
this.initData(); this.initData();
}, },
methods: { methods: {
handleCloseModal() {
this.showPhoneDialog = false;
},
// //
async initData() { async initData() {
const token = uni.getStorageSync('token'); const token = uni.getStorageSync('token');
@ -197,15 +206,18 @@
// //
updateUserInfo(data) { updateUserInfo(data) {
// IMAGE_BASE_URL
const avatarUrl = data.avatar ? `${IMAGE_BASE_URL}${data.avatar}` : '/static/imgs/index/nav.png';
this.userInfo = { this.userInfo = {
nickName: data.name || data.nickName || '未命名用户', nickName: data.name || data.nickName || '未命名用户',
avatarUrl: data.avatar || data.avatarUrl || '/static/imgs/index/nav.png', avatarUrl: avatarUrl,
bio: data.introduce || data.bio || '这家伙很懒,什么都没有写~', bio: data.introduce || data.bio || '这家伙很懒,什么都没有写~',
phone: data.phone || '' phone: data.phone || ''
}; };
// //
this.displayAvatar = this.userInfo.avatarUrl || '/static/imgs/index/nav.png'; this.displayAvatar = this.userInfo.avatarUrl;
this.formData = { this.formData = {
name: this.userInfo.nickName, name: this.userInfo.nickName,
@ -367,12 +379,13 @@
async loginComplete(data) { async loginComplete(data) {
try { try {
// //
this.showEditModal = false;
const res = await get('/api/v1/app_auth/mine'); const res = await get('/api/v1/app_auth/mine');
if (res && res.success) { if (res && res.success) {
uni.setStorageSync('userInfo', res.data); uni.setStorageSync('userInfo', res.data);
this.updateUserInfo(res.data); this.updateUserInfo(res.data);
this.isLogin = true; this.isLogin = true;
this.showEditModal = false; // this.showEditModal = false;
this.showPhoneButton = false; this.showPhoneButton = false;
uni.showToast({ uni.showToast({
title: '登录成功' title: '登录成功'
@ -413,7 +426,7 @@
}); });
}); });
if (fileInfo.size > 2 * 1024 * 1024) { if (fileInfo.size > 3 * 1024 * 1024) {
throw new Error('图片大小不能超过2MB'); throw new Error('图片大小不能超过2MB');
} }
@ -451,7 +464,7 @@
try { try {
const res = JSON.parse(uploadRes.data); const res = JSON.parse(uploadRes.data);
if (res && res.success) { if (res && res.success) {
resolve(`${IMAGE_BASE_URL}${res.data}`); resolve(res.data);
} else { } else {
reject(new Error(res.message || '上传失败')); reject(new Error(res.message || '上传失败'));
} }
@ -506,7 +519,12 @@
name, name,
bio bio
} = this.formData; } = this.formData;
const avatarUrl = this.avatarList.length > 0 ? this.avatarList[0].url : ""; console.log("====", this.avatarList)
let avatarUrl = this.avatarList.length > 0 ? this.avatarList[0].url : "";
if (avatarUrl && avatarUrl.includes(IMAGE_BASE_URL)) {
avatarUrl = avatarUrl.replace(IMAGE_BASE_URL, '');
}
if (!name) { if (!name) {
uni.showToast({ uni.showToast({
@ -534,12 +552,13 @@
// 3. // 3.
uni.setStorageSync('userInfo', res.data); uni.setStorageSync('userInfo', res.data);
this.updateUserInfo(res.data); this.updateUserInfo(res.data);
this.showEditModal = false;
uni.hideLoading(); uni.hideLoading();
uni.showToast({ uni.showToast({
title: '修改成功' title: '修改成功'
}); });
this.showEditModal = false;
} else { } else {
throw new Error(res.message || '获取用户信息失败'); throw new Error(res.message || '获取用户信息失败');
} }
@ -563,6 +582,7 @@
goPage(item) { goPage(item) {
if (item.key === 6) { // if (item.key === 6) { //
this.handleContactCommunity(); this.handleContactCommunity();
return; return;
} }
@ -590,7 +610,17 @@
return; return;
} }
this.showPhoneDialog = true; uni.showModal({
title: '联系社区',
content: '是否要拨打社区电话:' + this.communityPhone,
confirmText: '拨打',
cancelText: '取消',
success: (res) => {
if (res.confirm) {
this.callCommunityPhone();
}
}
});
}, },
// //